Update for font-backend changes.
[bpt/emacs.git] / src / xfont.c
CommitLineData
c2f5bfd6 1/* xfont.c -- X core font driver.
77ad4cfe
GM
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
c2f5bfd6
KH
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7This file is part of GNU Emacs.
8
9GNU Emacs is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
77ad4cfe 11the Free Software Foundation; either version 3, or (at your option)
c2f5bfd6
KH
12any later version.
13
14GNU Emacs is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU Emacs; see the file COPYING. If not, write to
21the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22Boston, MA 02110-1301, USA. */
23
24#include <config.h>
25#include <stdio.h>
f0c55750 26#include <stdlib.h>
c2f5bfd6
KH
27#include <X11/Xlib.h>
28
29#include "lisp.h"
30#include "dispextern.h"
31#include "xterm.h"
32#include "frame.h"
33#include "blockinput.h"
34#include "character.h"
35#include "charset.h"
36#include "fontset.h"
37#include "font.h"
f0c55750 38#include "ccl.h"
c2f5bfd6
KH
39
40\f
41/* X core font driver. */
42
f0c55750
KH
43struct xfont_info
44{
45 struct font font;
46 Display *display;
47 XFontStruct *xfont;
48};
49
c2f5bfd6
KH
50/* Prototypes of support functions. */
51extern void x_clear_errors P_ ((Display *));
52
c2f5bfd6 53static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
f0c55750 54static void xfont_find_ccl_program P_ ((struct font *));
c2f5bfd6
KH
55static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **,
56 struct charset **));
57
c2f5bfd6
KH
58
59/* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
60 is not contained in the font. */
61
62static XCharStruct *
63xfont_get_pcm (xfont, char2b)
64 XFontStruct *xfont;
65 XChar2b *char2b;
66{
67 /* The result metric information. */
68 XCharStruct *pcm = NULL;
69
70 xassert (xfont && char2b);
71
72 if (xfont->per_char != NULL)
73 {
74 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
75 {
76 /* min_char_or_byte2 specifies the linear character index
77 corresponding to the first element of the per_char array,
78 max_char_or_byte2 is the index of the last character. A
79 character with non-zero CHAR2B->byte1 is not in the font.
80 A character with byte2 less than min_char_or_byte2 or
81 greater max_char_or_byte2 is not in the font. */
82 if (char2b->byte1 == 0
83 && char2b->byte2 >= xfont->min_char_or_byte2
84 && char2b->byte2 <= xfont->max_char_or_byte2)
85 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
86 }
87 else
88 {
89 /* If either min_byte1 or max_byte1 are nonzero, both
90 min_char_or_byte2 and max_char_or_byte2 are less than
91 256, and the 2-byte character index values corresponding
92 to the per_char array element N (counting from 0) are:
93
94 byte1 = N/D + min_byte1
95 byte2 = N\D + min_char_or_byte2
96
97 where:
98
99 D = max_char_or_byte2 - min_char_or_byte2 + 1
100 / = integer division
101 \ = integer modulus */
102 if (char2b->byte1 >= xfont->min_byte1
103 && char2b->byte1 <= xfont->max_byte1
104 && char2b->byte2 >= xfont->min_char_or_byte2
105 && char2b->byte2 <= xfont->max_char_or_byte2)
106 pcm = (xfont->per_char
107 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
108 * (char2b->byte1 - xfont->min_byte1))
109 + (char2b->byte2 - xfont->min_char_or_byte2));
110 }
111 }
112 else
113 {
114 /* If the per_char pointer is null, all glyphs between the first
115 and last character indexes inclusive have the same
116 information, as given by both min_bounds and max_bounds. */
117 if (char2b->byte2 >= xfont->min_char_or_byte2
118 && char2b->byte2 <= xfont->max_char_or_byte2)
119 pcm = &xfont->max_bounds;
120 }
121
122 return ((pcm == NULL
123 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
124 ? NULL : pcm);
125}
126
f0c55750
KH
127/* Find a CCL program for a font specified by FONTP, and set the member
128 `encoder' of the structure. */
129
130static void
131xfont_find_ccl_program (font)
132 struct font *font;
133{
134 Lisp_Object list, elt;
135
136 elt = Qnil;
137 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
138 {
139 elt = XCAR (list);
140 if (CONSP (elt)
141 && STRINGP (XCAR (elt))
142 && ((fast_string_match_ignore_case (XCAR (elt),
143 font->props[FONT_NAME_INDEX])
144 >= 0)
145 || (fast_string_match_ignore_case (XCAR (elt),
146 font->props[FONT_FULLNAME_INDEX])
147 >= 0)))
148 break;
149 }
150
151 if (! NILP (list))
152 {
153 struct ccl_program *ccl
154 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
155
156 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
157 xfree (ccl);
158 else
159 font->font_encoder = ccl;
160 }
161}
162
feb2737b 163static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
c2f5bfd6 164static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
6e34c9c1 165static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
c2f5bfd6 166static Lisp_Object xfont_list_family P_ ((Lisp_Object));
f0c55750 167static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
c2f5bfd6
KH
168static void xfont_close P_ ((FRAME_PTR, struct font *));
169static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
c2f5bfd6
KH
170static int xfont_has_char P_ ((Lisp_Object, int));
171static unsigned xfont_encode_char P_ ((struct font *, int));
172static int xfont_text_extents P_ ((struct font *, unsigned *, int,
173 struct font_metrics *));
174static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
f0c55750 175static int xfont_check P_ ((FRAME_PTR, struct font *));
c2f5bfd6
KH
176
177struct font_driver xfont_driver =
178 {
575abfb7 179 0, /* Qx */
f0c55750 180 0, /* case insensitive */
c2f5bfd6 181 xfont_get_cache,
c2f5bfd6 182 xfont_list,
6e34c9c1 183 xfont_match,
c2f5bfd6
KH
184 xfont_list_family,
185 NULL,
186 xfont_open,
187 xfont_close,
188 xfont_prepare_face,
f0c55750 189 NULL,
c2f5bfd6
KH
190 xfont_has_char,
191 xfont_encode_char,
192 xfont_text_extents,
f0c55750
KH
193 xfont_draw,
194 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
195 xfont_check
c2f5bfd6
KH
196 };
197
198extern Lisp_Object QCname;
199
200static Lisp_Object
feb2737b
KH
201xfont_get_cache (f)
202 FRAME_PTR f;
c2f5bfd6 203{
feb2737b 204 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
c2f5bfd6
KH
205
206 return (dpyinfo->name_list_element);
207}
208
c2f5bfd6
KH
209extern Lisp_Object Vface_alternative_font_registry_alist;
210
f0c55750
KH
211static int
212compare_font_names (const void *name1, const void *name2)
213{
214 return strcasecmp (*(const char **) name1, *(const char **) name2);
215}
216
217static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
218
c2f5bfd6 219static Lisp_Object
6c4aeab6
KH
220xfont_list_pattern (frame, display, pattern)
221 Lisp_Object frame;
222 Display *display;
223 char *pattern;
c2f5bfd6 224{
6c4aeab6
KH
225 Lisp_Object list = Qnil;
226 int i, limit, num_fonts;
227 char **names;
c2f5bfd6
KH
228
229 BLOCK_INPUT;
6c4aeab6 230 x_catch_errors (display);
c2f5bfd6 231
6c4aeab6 232 for (limit = 512; ; limit *= 2)
c2f5bfd6 233 {
6c4aeab6
KH
234 names = XListFonts (display, pattern, limit, &num_fonts);
235 if (x_had_errors_p (display))
c2f5bfd6
KH
236 {
237 /* This error is perhaps due to insufficient memory on X
238 server. Let's just ignore it. */
6c4aeab6
KH
239 x_clear_errors (display);
240 num_fonts = 0;
241 break;
c2f5bfd6 242 }
6c4aeab6
KH
243 if (num_fonts < limit)
244 break;
245 XFreeFontNames (names);
246 }
247
f0c55750 248 if (num_fonts > 0)
6c4aeab6 249 {
f0c55750 250 char **indices = alloca (sizeof (char *) * num_fonts);
6c4aeab6 251
f0c55750
KH
252 for (i = 0; i < num_fonts; i++)
253 indices[i] = names[i];
254 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
6c4aeab6 255
f0c55750 256 for (i = 0; i < num_fonts; i++)
c2f5bfd6 257 {
f0c55750
KH
258 Lisp_Object entity;
259 int result;
6c4aeab6 260
f0c55750 261 if (i > 0 && strcasecmp (indices[i - 1], indices[i]) == 0)
6c4aeab6 262 continue;
6c4aeab6 263
f0c55750
KH
264 entity = font_make_entity ();
265 ASET (entity, FONT_TYPE_INDEX, Qx);
6c4aeab6 266
f0c55750
KH
267 result = font_parse_xlfd (indices[i], entity);
268 if (result < 0)
c2f5bfd6 269 {
f0c55750
KH
270 /* This may be an alias name. Try to get the full XLFD name
271 from XA_FONT property of the font. */
272 XFontStruct *font = XLoadQueryFont (display, indices[i]);
273 unsigned long value;
274
275 if (! font)
6c4aeab6 276 continue;
f0c55750
KH
277 if (XGetFontProperty (font, XA_FONT, &value))
278 {
279 char *name = (char *) XGetAtomName (display, (Atom) value);
280 int len = strlen (name);
281
282 /* If DXPC (a Differential X Protocol Compressor)
283 Ver.3.7 is running, XGetAtomName will return null
284 string. We must avoid such a name. */
285 if (len > 0)
286 result = font_parse_xlfd (name, entity);
287 XFree (name);
288 }
289 XFreeFont (display, font);
c2f5bfd6 290 }
f0c55750
KH
291
292 if (result == 0
293 /* Avoid auto-scaled fonts. */
294 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
295 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
296 list = Fcons (entity, list);
c2f5bfd6
KH
297 }
298 }
299
300 x_uncatch_errors ();
301 UNBLOCK_INPUT;
302
6c4aeab6
KH
303 return list;
304}
c2f5bfd6 305
6c4aeab6
KH
306static Lisp_Object
307xfont_list (frame, spec)
308 Lisp_Object frame, spec;
309{
310 FRAME_PTR f = XFRAME (frame);
311 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
f0c55750
KH
312 Lisp_Object registry, list, val, extra, font_name;
313 Lisp_Object dpi, avgwidth;
6c4aeab6
KH
314 int len;
315 char name[256];
316
317 extra = AREF (spec, FONT_EXTRA_INDEX);
6c4aeab6 318 if (CONSP (extra))
c2f5bfd6 319 {
6c4aeab6
KH
320 val = assq_no_quit (QCotf, extra);
321 if (! NILP (val))
f0c55750 322 return Qnil;
6c4aeab6
KH
323 val = assq_no_quit (QCscript, extra);
324 if (! NILP (val))
f0c55750
KH
325 return Qnil;
326 val = assq_no_quit (QClang, extra);
6c4aeab6 327 if (! NILP (val))
f0c55750 328 return Qnil;
c2f5bfd6 329 }
6c4aeab6 330
f0c55750
KH
331 registry = AREF (spec, FONT_REGISTRY_INDEX);
332 if (NILP (registry))
333 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
334 len = font_unparse_xlfd (spec, 0, name, 256);
335 ASET (spec, FONT_REGISTRY_INDEX, registry);
336 if (len < 0)
337 return Qnil;
338 list = xfont_list_pattern (frame, display, name);
339 if (NILP (list) && NILP (registry))
c2f5bfd6 340 {
f0c55750
KH
341 /* Try iso10646-1 */
342 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
343
344 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
6c4aeab6 345 {
f0c55750
KH
346 strcpy (r, "iso10646-1");
347 list = xfont_list_pattern (frame, display, name);
348 }
349 }
350 if (NILP (list) && ! NILP (registry))
351 {
352 Lisp_Object alter;
6c4aeab6 353
f0c55750
KH
354 if ((alter = Fassoc (SYMBOL_NAME (registry),
355 Vface_alternative_font_registry_alist),
356 CONSP (alter)))
357 {
358 /* Pointer to REGISTRY-ENCODING field. */
359 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
360
361 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
362 if (STRINGP (XCAR (alter))
363 && ((r - name) + SBYTES (XCAR (alter))) < 256)
364 {
365 strcpy (r, (char *) SDATA (XCAR (alter)));
366 list = xfont_list_pattern (frame, display, name);
367 if (! NILP (list))
368 break;
369 }
6c4aeab6 370 }
c2f5bfd6 371 }
c2f5bfd6 372
f0c55750 373 return list;
c2f5bfd6
KH
374}
375
6e34c9c1
KH
376static Lisp_Object
377xfont_match (frame, spec)
378 Lisp_Object frame, spec;
379{
380 FRAME_PTR f = XFRAME (frame);
381 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
382 Lisp_Object extra, val, entity;
f0c55750 383 char buf[256], *name;
6e34c9c1
KH
384 XFontStruct *xfont;
385 unsigned long value;
386
387 extra = AREF (spec, FONT_EXTRA_INDEX);
388 val = assq_no_quit (QCname, extra);
389 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750
KH
390 {
391 if (font_unparse_xlfd (spec, 0, buf, 256) < 0)
392 return Qnil;
393 name = buf;
394 }
395 else
396 name = (char *) SDATA (XCDR (val));
6e34c9c1 397
9c6d1df5 398 BLOCK_INPUT;
6e34c9c1 399 entity = Qnil;
6e34c9c1
KH
400 xfont = XLoadQueryFont (display, name);
401 if (xfont)
402 {
403 if (XGetFontProperty (xfont, XA_FONT, &value))
404 {
405 int len;
406
407 name = (char *) XGetAtomName (display, (Atom) value);
408 len = strlen (name);
409
410 /* If DXPC (a Differential X Protocol Compressor)
411 Ver.3.7 is running, XGetAtomName will return null
412 string. We must avoid such a name. */
413 if (len > 0)
414 {
f0c55750 415 entity = font_make_entity ();
6e34c9c1 416 ASET (entity, FONT_TYPE_INDEX, Qx);
6e34c9c1
KH
417 if (font_parse_xlfd (name, entity) < 0)
418 entity = Qnil;
419 }
420 XFree (name);
421 }
422 XFreeFont (display, xfont);
423 }
9c6d1df5 424 UNBLOCK_INPUT;
6e34c9c1
KH
425
426 return entity;
427}
428
c2f5bfd6
KH
429static int
430memq_no_quit (elt, list)
431 Lisp_Object elt, list;
432{
433 while (CONSP (list) && ! EQ (XCAR (list), elt))
434 list = XCDR (list);
435 return (CONSP (list));
436}
437
438static Lisp_Object
439xfont_list_family (frame)
9df50a31 440 Lisp_Object frame;
c2f5bfd6
KH
441{
442 FRAME_PTR f = XFRAME (frame);
443 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
444 char **names;
445 int num_fonts, i;
446 Lisp_Object list;
447 char *last_family;
448 int last_len;
449
450 BLOCK_INPUT;
451 x_catch_errors (dpyinfo->display);
452 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
453 0x8000, &num_fonts);
454 if (x_had_errors_p (dpyinfo->display))
455 {
456 /* This error is perhaps due to insufficient memory on X server.
457 Let's just ignore it. */
458 x_clear_errors (dpyinfo->display);
459 num_fonts = 0;
460 }
461
462 list = Qnil;
463 for (i = 0, last_len = 0; i < num_fonts; i++)
464 {
465 char *p0 = names[i], *p1;
466 Lisp_Object family;
467
468 p0++; /* skip the leading '-' */
469 while (*p0 && *p0 != '-') p0++; /* skip foundry */
470 if (! *p0)
471 continue;
472 p1 = ++p0;
473 while (*p1 && *p1 != '-') p1++; /* find the end of family */
474 if (! *p1 || p1 == p0)
475 continue;
476 if (last_len == p1 - p0
477 && bcmp (last_family, p0, last_len) == 0)
478 continue;
479 last_len = p1 - p0;
480 last_family = p0;
f0c55750
KH
481 family = make_unibyte_string (p0, last_len);
482 if (NILP (Fassoc_string (family, list, Qt)))
c2f5bfd6
KH
483 list = Fcons (family, list);
484 }
485
486 XFreeFontNames (names);
487 x_uncatch_errors ();
488 UNBLOCK_INPUT;
489
490 return list;
491}
492
f0c55750
KH
493extern Lisp_Object QCavgwidth;
494
495static Lisp_Object
c2f5bfd6
KH
496xfont_open (f, entity, pixel_size)
497 FRAME_PTR f;
498 Lisp_Object entity;
499 int pixel_size;
500{
501 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
502 Display *display = dpyinfo->display;
503 char name[256];
504 int len;
505 unsigned long value;
506 Lisp_Object registry;
507 struct charset *encoding, *repertory;
f0c55750 508 Lisp_Object font_object, fullname;
c2f5bfd6
KH
509 struct font *font;
510 XFontStruct *xfont;
f0c55750 511 int i;
c2f5bfd6
KH
512
513 /* At first, check if we know how to encode characters for this
514 font. */
515 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 516 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
f0c55750 517 return Qnil;
c2f5bfd6
KH
518
519 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
520 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
521 else if (pixel_size == 0)
522 {
523 if (FRAME_FONT (f))
524 pixel_size = FRAME_FONT (f)->pixel_size;
525 else
526 pixel_size = 14;
527 }
c2f5bfd6
KH
528 len = font_unparse_xlfd (entity, pixel_size, name, 256);
529 if (len <= 0)
f0c55750 530 return Qnil;
c2f5bfd6
KH
531
532 BLOCK_INPUT;
533 x_catch_errors (display);
534 xfont = XLoadQueryFont (display, name);
535 if (x_had_errors_p (display))
536 {
537 /* This error is perhaps due to insufficient memory on X server.
538 Let's just ignore it. */
539 x_clear_errors (display);
540 xfont = NULL;
541 }
f0c55750
KH
542 fullname = Qnil;
543 /* Try to get the full name of FONT. */
544 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
545 {
546 char *p0, *p;
547 int dashes = 0;
548
549 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
550 /* Count the number of dashes in the "full name".
551 If it is too few, this isn't really the font's full name,
552 so don't use it.
553 In X11R4, the fonts did not come with their canonical names
554 stored in them. */
555 while (*p)
556 {
557 if (*p == '-')
558 dashes++;
559 p++;
560 }
561
562 if (dashes >= 13)
563 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
564 XFree (p0);
565 }
c2f5bfd6
KH
566 x_uncatch_errors ();
567 UNBLOCK_INPUT;
568
569 if (! xfont)
f0c55750
KH
570 return Qnil;
571
572 font_object = font_make_object (VECSIZE (struct xfont_info));
573 ASET (font_object, FONT_TYPE_INDEX, Qx);
574 if (STRINGP (fullname))
575 font_parse_xlfd (SDATA (fullname), font_object);
576 for (i = 1; i < FONT_ENTITY_MAX; i++)
577 ASET (font_object, i, AREF (entity, i));
578 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
579 if (STRINGP (fullname))
580 ASET (font_object, FONT_NAME_INDEX, fullname);
581 else
582 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
583 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
584 ASET (font_object, FONT_FILE_INDEX, Qnil);
585 ASET (font_object, FONT_FORMAT_INDEX, Qx);
586 font = XFONT_OBJECT (font_object);
587 ((struct xfont_info *) font)->xfont = xfont;
588 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
c2f5bfd6
KH
589 font->pixel_size = pixel_size;
590 font->driver = &xfont_driver;
c2f5bfd6 591 font->encoding_charset = encoding->id;
1886668d 592 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
593 font->ascent = xfont->ascent;
594 font->descent = xfont->descent;
f0c55750
KH
595 font->height = font->ascent + font->descent;
596 font->min_width = xfont->min_bounds.width;
c2f5bfd6
KH
597 if (xfont->min_bounds.width == xfont->max_bounds.width)
598 {
599 /* Fixed width font. */
f0c55750 600 font->average_width = font->space_width = xfont->min_bounds.width;
c2f5bfd6
KH
601 }
602 else
603 {
c2f5bfd6 604 XCharStruct *pcm;
f0c55750
KH
605 XChar2b char2b;
606 Lisp_Object val;
c2f5bfd6
KH
607
608 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
609 pcm = xfont_get_pcm (xfont, &char2b);
610 if (pcm)
f0c55750 611 font->space_width = pcm->width;
c2f5bfd6 612 else
f0c55750
KH
613 font->space_width = 0;
614
615 val = Ffont_get (font_object, QCavgwidth);
616 if (INTEGERP (val))
617 font->average_width = XINT (val);
618 if (font->average_width < 0)
619 font->average_width = - font->average_width;
620 if (font->average_width == 0
621 && encoding->ascii_compatible_p)
c2f5bfd6 622 {
f0c55750 623 int width = font->space_width, n = pcm != NULL;
c2f5bfd6 624
f0c55750
KH
625 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
626 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
627 width += pcm->width, n++;
628 font->average_width = width / n;
c2f5bfd6 629 }
c2f5bfd6 630 }
c2f5bfd6 631
f0c55750
KH
632 BLOCK_INPUT;
633 font->underline_thickness
634 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
635 ? (long) value : 0);
636 font->underline_position
637 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
638 ? (long) value : -1);
639 font->baseline_offset
c2f5bfd6
KH
640 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
641 ? (long) value : 0);
f0c55750 642 font->relative_compose
c2f5bfd6
KH
643 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
644 ? (long) value : 0);
f0c55750 645 font->default_ascent
c2f5bfd6
KH
646 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
647 ? (long) value : 0);
c2f5bfd6
KH
648 UNBLOCK_INPUT;
649
f0c55750
KH
650 if (NILP (fullname))
651 fullname = AREF (font_object, FONT_NAME_INDEX);
652 font->vertical_centering
653 = (STRINGP (Vvertical_centering_font_regexp)
654 && (fast_string_match_ignore_case
655 (Vvertical_centering_font_regexp, fullname) >= 0));
c2f5bfd6 656
f0c55750 657 return font_object;
c2f5bfd6
KH
658}
659
660static void
661xfont_close (f, font)
662 FRAME_PTR f;
663 struct font *font;
664{
665 BLOCK_INPUT;
f0c55750 666 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
c2f5bfd6 667 UNBLOCK_INPUT;
c2f5bfd6
KH
668}
669
670static int
671xfont_prepare_face (f, face)
672 FRAME_PTR f;
673 struct face *face;
674{
675 BLOCK_INPUT;
f0c55750
KH
676 XSetFont (FRAME_X_DISPLAY (f), face->gc,
677 ((struct xfont_info *) face->font)->xfont->fid);
c2f5bfd6
KH
678 UNBLOCK_INPUT;
679
680 return 0;
681}
682
c2f5bfd6
KH
683static int
684xfont_has_char (entity, c)
685 Lisp_Object entity;
686 int c;
687{
688 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
689 struct charset *repertory;
690
a9822ae8 691 if (font_registry_charsets (registry, NULL, &repertory) < 0)
c2f5bfd6
KH
692 return -1;
693 if (! repertory)
694 return -1;
695 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
696}
697
698static unsigned
699xfont_encode_char (font, c)
700 struct font *font;
701 int c;
702{
f0c55750 703 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
704 struct charset *charset;
705 unsigned code;
706 XChar2b char2b;
707
708 charset = CHARSET_FROM_ID (font->encoding_charset);
709 code = ENCODE_CHAR (charset, c);
710 if (code == CHARSET_INVALID_CODE (charset))
21138cff 711 return FONT_INVALID_CODE;
1886668d 712 if (font->repertory_charset >= 0)
c2f5bfd6 713 {
1886668d 714 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 715 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 716 ? code : FONT_INVALID_CODE);
c2f5bfd6 717 }
88649c62
KH
718 char2b.byte1 = code >> 8;
719 char2b.byte2 = code & 0xFF;
f0c55750 720 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
721}
722
723static int
724xfont_text_extents (font, code, nglyphs, metrics)
725 struct font *font;
726 unsigned *code;
727 int nglyphs;
728 struct font_metrics *metrics;
729{
f0c55750 730 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
731 int width = 0;
732 int i, x;
733
734 if (metrics)
735 bzero (metrics, sizeof (struct font_metrics));
736 for (i = 0, x = 0; i < nglyphs; i++)
737 {
738 XChar2b char2b;
739 static XCharStruct *pcm;
740
741 if (code[i] >= 0x10000)
742 continue;
743 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
f0c55750 744 pcm = xfont_get_pcm (xfont, &char2b);
c2f5bfd6
KH
745 if (! pcm)
746 continue;
747 if (metrics->lbearing > width + pcm->lbearing)
748 metrics->lbearing = width + pcm->lbearing;
749 if (metrics->rbearing < width + pcm->rbearing)
750 metrics->rbearing = width + pcm->rbearing;
751 if (metrics->ascent < pcm->ascent)
752 metrics->ascent = pcm->ascent;
753 if (metrics->descent < pcm->descent)
754 metrics->descent = pcm->descent;
755 width += pcm->width;
756 }
757 if (metrics)
758 metrics->width = width;
759 return width;
760}
761
762static int
763xfont_draw (s, from, to, x, y, with_background)
764 struct glyph_string *s;
765 int from, to, x, y, with_background;
766{
f0c55750 767 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
c2f5bfd6 768 int len = to - from;
6e34c9c1 769 GC gc = s->gc;
298fd5b1 770 int i;
6e34c9c1 771
f0c55750 772 if (s->gc != s->face->gc)
6e34c9c1 773 {
d45fefc7 774 BLOCK_INPUT;
f0c55750 775 XSetFont (s->display, gc, xfont->fid);
d45fefc7 776 UNBLOCK_INPUT;
6e34c9c1 777 }
c2f5bfd6
KH
778
779 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
780 {
781 char *str;
c2f5bfd6
KH
782 USE_SAFE_ALLOCA;
783
784 SAFE_ALLOCA (str, char *, len);
785 for (i = 0; i < len ; i++)
786 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
d45fefc7 787 BLOCK_INPUT;
c2f5bfd6 788 if (with_background > 0)
298fd5b1
KH
789 {
790 if (s->padding_p)
791 for (i = 0; i < len; i++)
792 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
793 gc, x + i, y, str + i, 1);
794 else
795 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
796 gc, x, y, str, len);
797 }
c2f5bfd6 798 else
298fd5b1
KH
799 {
800 if (s->padding_p)
801 for (i = 0; i < len; i++)
802 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
803 gc, x + i, y, str + i, 1);
804 else
805 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
806 gc, x, y, str, len);
807 }
d45fefc7 808 UNBLOCK_INPUT;
c2f5bfd6
KH
809 SAFE_FREE ();
810 return s->nchars;
811 }
812
d45fefc7 813 BLOCK_INPUT;
c2f5bfd6 814 if (with_background > 0)
298fd5b1
KH
815 {
816 if (s->padding_p)
817 for (i = 0; i < len; i++)
818 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
819 gc, x + i, y, s->char2b + from + i, 1);
820 else
821 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
822 gc, x, y, s->char2b + from, len);
823 }
c2f5bfd6 824 else
298fd5b1
KH
825 {
826 if (s->padding_p)
827 for (i = 0; i < len; i++)
828 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
829 gc, x + i, y, s->char2b + from + i, 1);
830 else
831 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
832 gc, x, y, s->char2b + from, len);
833 }
d45fefc7 834 UNBLOCK_INPUT;
c2f5bfd6
KH
835
836 return len;
837}
838
f0c55750
KH
839static int
840xfont_check (f, font)
841 FRAME_PTR f;
842 struct font *font;
843{
844 struct xfont_info *xfont = (struct xfont_info *) font;
845
846 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
847}
848
c2f5bfd6
KH
849\f
850void
851syms_of_xfont ()
852{
c2f5bfd6
KH
853 xfont_driver.type = Qx;
854 register_font_driver (&xfont_driver, NULL);
855}
885b7d09
MB
856
857/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
858 (do not change this comment) */