(font_open_entity): Cancel the previous change.
[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{
7740d2c7
KH
209 return xstrcasecmp (*(const unsigned char **) name1,
210 *(const unsigned char **) name2);
f0c55750
KH
211}
212
213static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
214
c2f5bfd6 215static Lisp_Object
6c4aeab6
KH
216xfont_list_pattern (frame, display, pattern)
217 Lisp_Object frame;
218 Display *display;
219 char *pattern;
c2f5bfd6 220{
6c4aeab6
KH
221 Lisp_Object list = Qnil;
222 int i, limit, num_fonts;
223 char **names;
c2f5bfd6
KH
224
225 BLOCK_INPUT;
6c4aeab6 226 x_catch_errors (display);
c2f5bfd6 227
6c4aeab6 228 for (limit = 512; ; limit *= 2)
c2f5bfd6 229 {
6c4aeab6
KH
230 names = XListFonts (display, pattern, limit, &num_fonts);
231 if (x_had_errors_p (display))
c2f5bfd6
KH
232 {
233 /* This error is perhaps due to insufficient memory on X
234 server. Let's just ignore it. */
6c4aeab6
KH
235 x_clear_errors (display);
236 num_fonts = 0;
237 break;
c2f5bfd6 238 }
6c4aeab6
KH
239 if (num_fonts < limit)
240 break;
241 XFreeFontNames (names);
242 }
243
f0c55750 244 if (num_fonts > 0)
6c4aeab6 245 {
f0c55750 246 char **indices = alloca (sizeof (char *) * num_fonts);
6c4aeab6 247
f0c55750
KH
248 for (i = 0; i < num_fonts; i++)
249 indices[i] = names[i];
250 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
6c4aeab6 251
f0c55750 252 for (i = 0; i < num_fonts; i++)
c2f5bfd6 253 {
f0c55750
KH
254 Lisp_Object entity;
255 int result;
6c4aeab6 256
05131107 257 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
6c4aeab6 258 continue;
6c4aeab6 259
f0c55750
KH
260 entity = font_make_entity ();
261 ASET (entity, FONT_TYPE_INDEX, Qx);
6c4aeab6 262
f0c55750
KH
263 result = font_parse_xlfd (indices[i], entity);
264 if (result < 0)
c2f5bfd6 265 {
f0c55750
KH
266 /* This may be an alias name. Try to get the full XLFD name
267 from XA_FONT property of the font. */
268 XFontStruct *font = XLoadQueryFont (display, indices[i]);
269 unsigned long value;
270
271 if (! font)
6c4aeab6 272 continue;
f0c55750
KH
273 if (XGetFontProperty (font, XA_FONT, &value))
274 {
275 char *name = (char *) XGetAtomName (display, (Atom) value);
276 int len = strlen (name);
277
278 /* If DXPC (a Differential X Protocol Compressor)
279 Ver.3.7 is running, XGetAtomName will return null
280 string. We must avoid such a name. */
281 if (len > 0)
282 result = font_parse_xlfd (name, entity);
283 XFree (name);
284 }
285 XFreeFont (display, font);
c2f5bfd6 286 }
f0c55750
KH
287
288 if (result == 0
289 /* Avoid auto-scaled fonts. */
290 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
291 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
292 list = Fcons (entity, list);
c2f5bfd6 293 }
019e13ef 294 XFreeFontNames (names);
c2f5bfd6
KH
295 }
296
297 x_uncatch_errors ();
298 UNBLOCK_INPUT;
299
960d80b9 300 font_add_log ("xfont-list", build_string (pattern), list);
6c4aeab6
KH
301 return list;
302}
c2f5bfd6 303
6c4aeab6
KH
304static Lisp_Object
305xfont_list (frame, spec)
306 Lisp_Object frame, spec;
307{
308 FRAME_PTR f = XFRAME (frame);
309 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
960d80b9 310 Lisp_Object registry, list, val, extra;
6c4aeab6
KH
311 int len;
312 char name[256];
313
314 extra = AREF (spec, FONT_EXTRA_INDEX);
6c4aeab6 315 if (CONSP (extra))
c2f5bfd6 316 {
6c4aeab6
KH
317 val = assq_no_quit (QCotf, extra);
318 if (! NILP (val))
f0c55750 319 return Qnil;
6c4aeab6
KH
320 val = assq_no_quit (QCscript, extra);
321 if (! NILP (val))
f0c55750
KH
322 return Qnil;
323 val = assq_no_quit (QClang, extra);
6c4aeab6 324 if (! NILP (val))
f0c55750 325 return Qnil;
c2f5bfd6 326 }
6c4aeab6 327
f0c55750 328 registry = AREF (spec, FONT_REGISTRY_INDEX);
f0c55750
KH
329 len = font_unparse_xlfd (spec, 0, name, 256);
330 ASET (spec, FONT_REGISTRY_INDEX, registry);
331 if (len < 0)
332 return Qnil;
333 list = xfont_list_pattern (frame, display, name);
334 if (NILP (list) && NILP (registry))
c2f5bfd6 335 {
f0c55750
KH
336 /* Try iso10646-1 */
337 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
338
339 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
6c4aeab6 340 {
f0c55750
KH
341 strcpy (r, "iso10646-1");
342 list = xfont_list_pattern (frame, display, name);
343 }
344 }
345 if (NILP (list) && ! NILP (registry))
346 {
37470f4d 347 /* Try alternate registries. */
f0c55750 348 Lisp_Object alter;
6c4aeab6 349
f0c55750
KH
350 if ((alter = Fassoc (SYMBOL_NAME (registry),
351 Vface_alternative_font_registry_alist),
352 CONSP (alter)))
353 {
354 /* Pointer to REGISTRY-ENCODING field. */
355 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
356
357 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
358 if (STRINGP (XCAR (alter))
359 && ((r - name) + SBYTES (XCAR (alter))) < 256)
360 {
361 strcpy (r, (char *) SDATA (XCAR (alter)));
362 list = xfont_list_pattern (frame, display, name);
363 if (! NILP (list))
364 break;
365 }
6c4aeab6 366 }
c2f5bfd6 367 }
37470f4d
KH
368 if (NILP (list))
369 {
370 /* Try alias. */
371 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
372 if (CONSP (val) && STRINGP (XCDR (val)))
7740d2c7 373 list = xfont_list_pattern (frame, display, (char *) SDATA (XCDR (val)));
37470f4d 374 }
c2f5bfd6 375
f0c55750 376 return list;
c2f5bfd6
KH
377}
378
6e34c9c1
KH
379static Lisp_Object
380xfont_match (frame, spec)
381 Lisp_Object frame, spec;
382{
383 FRAME_PTR f = XFRAME (frame);
384 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
385 Lisp_Object extra, val, entity;
f0c55750 386 char buf[256], *name;
6e34c9c1
KH
387 XFontStruct *xfont;
388 unsigned long value;
389
390 extra = AREF (spec, FONT_EXTRA_INDEX);
391 val = assq_no_quit (QCname, extra);
392 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750
KH
393 {
394 if (font_unparse_xlfd (spec, 0, buf, 256) < 0)
395 return Qnil;
396 name = buf;
397 }
398 else
399 name = (char *) SDATA (XCDR (val));
6e34c9c1 400
9c6d1df5 401 BLOCK_INPUT;
6e34c9c1 402 entity = Qnil;
6e34c9c1
KH
403 xfont = XLoadQueryFont (display, name);
404 if (xfont)
405 {
406 if (XGetFontProperty (xfont, XA_FONT, &value))
407 {
408 int len;
409
410 name = (char *) XGetAtomName (display, (Atom) value);
411 len = strlen (name);
412
413 /* If DXPC (a Differential X Protocol Compressor)
414 Ver.3.7 is running, XGetAtomName will return null
415 string. We must avoid such a name. */
416 if (len > 0)
417 {
f0c55750 418 entity = font_make_entity ();
6e34c9c1 419 ASET (entity, FONT_TYPE_INDEX, Qx);
6e34c9c1
KH
420 if (font_parse_xlfd (name, entity) < 0)
421 entity = Qnil;
422 }
423 XFree (name);
424 }
425 XFreeFont (display, xfont);
426 }
9c6d1df5 427 UNBLOCK_INPUT;
6e34c9c1 428
960d80b9 429 font_add_log ("xfont-match", spec, entity);
6e34c9c1
KH
430 return entity;
431}
432
c2f5bfd6
KH
433static Lisp_Object
434xfont_list_family (frame)
9df50a31 435 Lisp_Object frame;
c2f5bfd6
KH
436{
437 FRAME_PTR f = XFRAME (frame);
438 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
439 char **names;
440 int num_fonts, i;
441 Lisp_Object list;
442 char *last_family;
443 int last_len;
444
445 BLOCK_INPUT;
446 x_catch_errors (dpyinfo->display);
447 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
448 0x8000, &num_fonts);
449 if (x_had_errors_p (dpyinfo->display))
450 {
451 /* This error is perhaps due to insufficient memory on X server.
452 Let's just ignore it. */
453 x_clear_errors (dpyinfo->display);
454 num_fonts = 0;
455 }
456
457 list = Qnil;
458 for (i = 0, last_len = 0; i < num_fonts; i++)
459 {
460 char *p0 = names[i], *p1;
461 Lisp_Object family;
462
463 p0++; /* skip the leading '-' */
464 while (*p0 && *p0 != '-') p0++; /* skip foundry */
465 if (! *p0)
466 continue;
467 p1 = ++p0;
468 while (*p1 && *p1 != '-') p1++; /* find the end of family */
469 if (! *p1 || p1 == p0)
470 continue;
471 if (last_len == p1 - p0
472 && bcmp (last_family, p0, last_len) == 0)
473 continue;
474 last_len = p1 - p0;
475 last_family = p0;
f0c55750
KH
476 family = make_unibyte_string (p0, last_len);
477 if (NILP (Fassoc_string (family, list, Qt)))
c2f5bfd6
KH
478 list = Fcons (family, list);
479 }
480
481 XFreeFontNames (names);
482 x_uncatch_errors ();
483 UNBLOCK_INPUT;
484
485 return list;
486}
487
f0c55750
KH
488extern Lisp_Object QCavgwidth;
489
490static Lisp_Object
c2f5bfd6
KH
491xfont_open (f, entity, pixel_size)
492 FRAME_PTR f;
493 Lisp_Object entity;
494 int pixel_size;
495{
496 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
497 Display *display = dpyinfo->display;
498 char name[256];
499 int len;
500 unsigned long value;
501 Lisp_Object registry;
502 struct charset *encoding, *repertory;
f0c55750 503 Lisp_Object font_object, fullname;
c2f5bfd6
KH
504 struct font *font;
505 XFontStruct *xfont;
f0c55750 506 int i;
c2f5bfd6
KH
507
508 /* At first, check if we know how to encode characters for this
509 font. */
510 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 511 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
f0c55750 512 return Qnil;
c2f5bfd6
KH
513
514 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
515 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
516 else if (pixel_size == 0)
517 {
518 if (FRAME_FONT (f))
519 pixel_size = FRAME_FONT (f)->pixel_size;
520 else
521 pixel_size = 14;
522 }
c2f5bfd6
KH
523 len = font_unparse_xlfd (entity, pixel_size, name, 256);
524 if (len <= 0)
f0c55750 525 return Qnil;
c2f5bfd6
KH
526
527 BLOCK_INPUT;
528 x_catch_errors (display);
529 xfont = XLoadQueryFont (display, name);
530 if (x_had_errors_p (display))
531 {
532 /* This error is perhaps due to insufficient memory on X server.
533 Let's just ignore it. */
534 x_clear_errors (display);
535 xfont = NULL;
536 }
f0c55750
KH
537 fullname = Qnil;
538 /* Try to get the full name of FONT. */
539 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
540 {
541 char *p0, *p;
542 int dashes = 0;
543
544 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
545 /* Count the number of dashes in the "full name".
546 If it is too few, this isn't really the font's full name,
547 so don't use it.
548 In X11R4, the fonts did not come with their canonical names
549 stored in them. */
550 while (*p)
551 {
552 if (*p == '-')
553 dashes++;
554 p++;
555 }
556
557 if (dashes >= 13)
558 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
559 XFree (p0);
560 }
c2f5bfd6
KH
561 x_uncatch_errors ();
562 UNBLOCK_INPUT;
563
564 if (! xfont)
f0c55750
KH
565 return Qnil;
566
947eecfb
KH
567 font_object = font_make_object (VECSIZE (struct xfont_info),
568 entity, pixel_size);
f0c55750
KH
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 if (STRINGP (fullname))
573 ASET (font_object, FONT_NAME_INDEX, fullname);
574 else
575 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
576 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
577 ASET (font_object, FONT_FILE_INDEX, Qnil);
578 ASET (font_object, FONT_FORMAT_INDEX, Qx);
579 font = XFONT_OBJECT (font_object);
580 ((struct xfont_info *) font)->xfont = xfont;
581 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
c2f5bfd6
KH
582 font->pixel_size = pixel_size;
583 font->driver = &xfont_driver;
c2f5bfd6 584 font->encoding_charset = encoding->id;
1886668d 585 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
586 font->ascent = xfont->ascent;
587 font->descent = xfont->descent;
f0c55750
KH
588 font->height = font->ascent + font->descent;
589 font->min_width = xfont->min_bounds.width;
c2f5bfd6
KH
590 if (xfont->min_bounds.width == xfont->max_bounds.width)
591 {
592 /* Fixed width font. */
f0c55750 593 font->average_width = font->space_width = xfont->min_bounds.width;
c2f5bfd6
KH
594 }
595 else
596 {
c2f5bfd6 597 XCharStruct *pcm;
f0c55750
KH
598 XChar2b char2b;
599 Lisp_Object val;
c2f5bfd6
KH
600
601 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
602 pcm = xfont_get_pcm (xfont, &char2b);
603 if (pcm)
f0c55750 604 font->space_width = pcm->width;
c2f5bfd6 605 else
f0c55750
KH
606 font->space_width = 0;
607
608 val = Ffont_get (font_object, QCavgwidth);
609 if (INTEGERP (val))
610 font->average_width = XINT (val);
611 if (font->average_width < 0)
612 font->average_width = - font->average_width;
613 if (font->average_width == 0
614 && encoding->ascii_compatible_p)
c2f5bfd6 615 {
f0c55750 616 int width = font->space_width, n = pcm != NULL;
c2f5bfd6 617
f0c55750
KH
618 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
619 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
620 width += pcm->width, n++;
4f64a164
KH
621 if (n > 0)
622 font->average_width = width / n;
c2f5bfd6 623 }
4f64a164
KH
624 if (font->average_width == 0)
625 /* No easy way other than this to get a reasonable
626 average_width. */
627 font->average_width
628 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
c2f5bfd6 629 }
c2f5bfd6 630
f0c55750
KH
631 BLOCK_INPUT;
632 font->underline_thickness
633 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
634 ? (long) value : 0);
635 font->underline_position
636 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
637 ? (long) value : -1);
638 font->baseline_offset
c2f5bfd6
KH
639 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
640 ? (long) value : 0);
f0c55750 641 font->relative_compose
c2f5bfd6
KH
642 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
643 ? (long) value : 0);
f0c55750 644 font->default_ascent
c2f5bfd6
KH
645 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
646 ? (long) value : 0);
c2f5bfd6
KH
647 UNBLOCK_INPUT;
648
f0c55750
KH
649 if (NILP (fullname))
650 fullname = AREF (font_object, FONT_NAME_INDEX);
947eecfb 651 font->vertical_centering = 0;
c2f5bfd6 652
f0c55750 653 return font_object;
c2f5bfd6
KH
654}
655
656static void
657xfont_close (f, font)
658 FRAME_PTR f;
659 struct font *font;
660{
661 BLOCK_INPUT;
f0c55750 662 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
c2f5bfd6 663 UNBLOCK_INPUT;
c2f5bfd6
KH
664}
665
666static int
667xfont_prepare_face (f, face)
668 FRAME_PTR f;
669 struct face *face;
670{
671 BLOCK_INPUT;
f0c55750
KH
672 XSetFont (FRAME_X_DISPLAY (f), face->gc,
673 ((struct xfont_info *) face->font)->xfont->fid);
c2f5bfd6
KH
674 UNBLOCK_INPUT;
675
676 return 0;
677}
678
c2f5bfd6
KH
679static int
680xfont_has_char (entity, c)
681 Lisp_Object entity;
682 int c;
683{
684 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
685 struct charset *repertory;
686
a9822ae8 687 if (font_registry_charsets (registry, NULL, &repertory) < 0)
c2f5bfd6
KH
688 return -1;
689 if (! repertory)
690 return -1;
691 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
692}
693
694static unsigned
695xfont_encode_char (font, c)
696 struct font *font;
697 int c;
698{
f0c55750 699 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
700 struct charset *charset;
701 unsigned code;
702 XChar2b char2b;
703
704 charset = CHARSET_FROM_ID (font->encoding_charset);
705 code = ENCODE_CHAR (charset, c);
706 if (code == CHARSET_INVALID_CODE (charset))
21138cff 707 return FONT_INVALID_CODE;
1886668d 708 if (font->repertory_charset >= 0)
c2f5bfd6 709 {
1886668d 710 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 711 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 712 ? code : FONT_INVALID_CODE);
c2f5bfd6 713 }
88649c62
KH
714 char2b.byte1 = code >> 8;
715 char2b.byte2 = code & 0xFF;
f0c55750 716 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
717}
718
719static int
720xfont_text_extents (font, code, nglyphs, metrics)
721 struct font *font;
722 unsigned *code;
723 int nglyphs;
724 struct font_metrics *metrics;
725{
f0c55750 726 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
727 int width = 0;
728 int i, x;
729
730 if (metrics)
731 bzero (metrics, sizeof (struct font_metrics));
732 for (i = 0, x = 0; i < nglyphs; i++)
733 {
734 XChar2b char2b;
735 static XCharStruct *pcm;
736
737 if (code[i] >= 0x10000)
738 continue;
739 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
f0c55750 740 pcm = xfont_get_pcm (xfont, &char2b);
c2f5bfd6
KH
741 if (! pcm)
742 continue;
743 if (metrics->lbearing > width + pcm->lbearing)
744 metrics->lbearing = width + pcm->lbearing;
745 if (metrics->rbearing < width + pcm->rbearing)
746 metrics->rbearing = width + pcm->rbearing;
747 if (metrics->ascent < pcm->ascent)
748 metrics->ascent = pcm->ascent;
749 if (metrics->descent < pcm->descent)
750 metrics->descent = pcm->descent;
751 width += pcm->width;
752 }
753 if (metrics)
754 metrics->width = width;
755 return width;
756}
757
758static int
759xfont_draw (s, from, to, x, y, with_background)
760 struct glyph_string *s;
761 int from, to, x, y, with_background;
762{
f0c55750 763 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
c2f5bfd6 764 int len = to - from;
6e34c9c1 765 GC gc = s->gc;
298fd5b1 766 int i;
6e34c9c1 767
f0c55750 768 if (s->gc != s->face->gc)
6e34c9c1 769 {
d45fefc7 770 BLOCK_INPUT;
f0c55750 771 XSetFont (s->display, gc, xfont->fid);
d45fefc7 772 UNBLOCK_INPUT;
6e34c9c1 773 }
c2f5bfd6
KH
774
775 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
776 {
777 char *str;
c2f5bfd6
KH
778 USE_SAFE_ALLOCA;
779
780 SAFE_ALLOCA (str, char *, len);
781 for (i = 0; i < len ; i++)
782 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
d45fefc7 783 BLOCK_INPUT;
c2f5bfd6 784 if (with_background > 0)
298fd5b1
KH
785 {
786 if (s->padding_p)
787 for (i = 0; i < len; i++)
788 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
789 gc, x + i, y, str + i, 1);
790 else
791 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
792 gc, x, y, str, len);
793 }
c2f5bfd6 794 else
298fd5b1
KH
795 {
796 if (s->padding_p)
797 for (i = 0; i < len; i++)
798 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
799 gc, x + i, y, str + i, 1);
800 else
801 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
802 gc, x, y, str, len);
803 }
d45fefc7 804 UNBLOCK_INPUT;
c2f5bfd6
KH
805 SAFE_FREE ();
806 return s->nchars;
807 }
808
d45fefc7 809 BLOCK_INPUT;
c2f5bfd6 810 if (with_background > 0)
298fd5b1
KH
811 {
812 if (s->padding_p)
813 for (i = 0; i < len; i++)
814 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
815 gc, x + i, y, s->char2b + from + i, 1);
816 else
817 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
818 gc, x, y, s->char2b + from, len);
819 }
c2f5bfd6 820 else
298fd5b1
KH
821 {
822 if (s->padding_p)
823 for (i = 0; i < len; i++)
824 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
825 gc, x + i, y, s->char2b + from + i, 1);
826 else
827 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
828 gc, x, y, s->char2b + from, len);
829 }
d45fefc7 830 UNBLOCK_INPUT;
c2f5bfd6
KH
831
832 return len;
833}
834
f0c55750
KH
835static int
836xfont_check (f, font)
837 FRAME_PTR f;
838 struct font *font;
839{
840 struct xfont_info *xfont = (struct xfont_info *) font;
841
842 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
843}
844
c2f5bfd6
KH
845\f
846void
847syms_of_xfont ()
848{
c2f5bfd6
KH
849 xfont_driver.type = Qx;
850 register_font_driver (&xfont_driver, NULL);
851}
885b7d09
MB
852
853/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
854 (do not change this comment) */