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