(vc-string-prefix-p): New function.
[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 {
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 }
c2f5bfd6 368
f0c55750 369 return list;
c2f5bfd6
KH
370}
371
6e34c9c1
KH
372static Lisp_Object
373xfont_match (frame, spec)
374 Lisp_Object frame, spec;
375{
376 FRAME_PTR f = XFRAME (frame);
377 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
378 Lisp_Object extra, val, entity;
f0c55750 379 char buf[256], *name;
6e34c9c1
KH
380 XFontStruct *xfont;
381 unsigned long value;
382
383 extra = AREF (spec, FONT_EXTRA_INDEX);
384 val = assq_no_quit (QCname, extra);
385 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750
KH
386 {
387 if (font_unparse_xlfd (spec, 0, buf, 256) < 0)
388 return Qnil;
389 name = buf;
390 }
391 else
392 name = (char *) SDATA (XCDR (val));
6e34c9c1 393
9c6d1df5 394 BLOCK_INPUT;
6e34c9c1 395 entity = Qnil;
6e34c9c1
KH
396 xfont = XLoadQueryFont (display, name);
397 if (xfont)
398 {
399 if (XGetFontProperty (xfont, XA_FONT, &value))
400 {
401 int len;
402
403 name = (char *) XGetAtomName (display, (Atom) value);
404 len = strlen (name);
405
406 /* If DXPC (a Differential X Protocol Compressor)
407 Ver.3.7 is running, XGetAtomName will return null
408 string. We must avoid such a name. */
409 if (len > 0)
410 {
f0c55750 411 entity = font_make_entity ();
6e34c9c1 412 ASET (entity, FONT_TYPE_INDEX, Qx);
6e34c9c1
KH
413 if (font_parse_xlfd (name, entity) < 0)
414 entity = Qnil;
415 }
416 XFree (name);
417 }
418 XFreeFont (display, xfont);
419 }
9c6d1df5 420 UNBLOCK_INPUT;
6e34c9c1 421
960d80b9 422 font_add_log ("xfont-match", spec, entity);
6e34c9c1
KH
423 return entity;
424}
425
c2f5bfd6
KH
426static Lisp_Object
427xfont_list_family (frame)
9df50a31 428 Lisp_Object frame;
c2f5bfd6
KH
429{
430 FRAME_PTR f = XFRAME (frame);
431 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
432 char **names;
433 int num_fonts, i;
434 Lisp_Object list;
435 char *last_family;
436 int last_len;
437
438 BLOCK_INPUT;
439 x_catch_errors (dpyinfo->display);
440 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
441 0x8000, &num_fonts);
442 if (x_had_errors_p (dpyinfo->display))
443 {
444 /* This error is perhaps due to insufficient memory on X server.
445 Let's just ignore it. */
446 x_clear_errors (dpyinfo->display);
447 num_fonts = 0;
448 }
449
450 list = Qnil;
451 for (i = 0, last_len = 0; i < num_fonts; i++)
452 {
453 char *p0 = names[i], *p1;
454 Lisp_Object family;
455
456 p0++; /* skip the leading '-' */
457 while (*p0 && *p0 != '-') p0++; /* skip foundry */
458 if (! *p0)
459 continue;
460 p1 = ++p0;
461 while (*p1 && *p1 != '-') p1++; /* find the end of family */
462 if (! *p1 || p1 == p0)
463 continue;
464 if (last_len == p1 - p0
465 && bcmp (last_family, p0, last_len) == 0)
466 continue;
467 last_len = p1 - p0;
468 last_family = p0;
f0c55750
KH
469 family = make_unibyte_string (p0, last_len);
470 if (NILP (Fassoc_string (family, list, Qt)))
c2f5bfd6
KH
471 list = Fcons (family, list);
472 }
473
474 XFreeFontNames (names);
475 x_uncatch_errors ();
476 UNBLOCK_INPUT;
477
478 return list;
479}
480
f0c55750
KH
481extern Lisp_Object QCavgwidth;
482
483static Lisp_Object
c2f5bfd6
KH
484xfont_open (f, entity, pixel_size)
485 FRAME_PTR f;
486 Lisp_Object entity;
487 int pixel_size;
488{
489 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
490 Display *display = dpyinfo->display;
491 char name[256];
492 int len;
493 unsigned long value;
494 Lisp_Object registry;
495 struct charset *encoding, *repertory;
f0c55750 496 Lisp_Object font_object, fullname;
c2f5bfd6
KH
497 struct font *font;
498 XFontStruct *xfont;
f0c55750 499 int i;
c2f5bfd6
KH
500
501 /* At first, check if we know how to encode characters for this
502 font. */
503 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 504 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
f0c55750 505 return Qnil;
c2f5bfd6
KH
506
507 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
508 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
509 else if (pixel_size == 0)
510 {
511 if (FRAME_FONT (f))
512 pixel_size = FRAME_FONT (f)->pixel_size;
513 else
514 pixel_size = 14;
515 }
c2f5bfd6
KH
516 len = font_unparse_xlfd (entity, pixel_size, name, 256);
517 if (len <= 0)
f0c55750 518 return Qnil;
c2f5bfd6
KH
519
520 BLOCK_INPUT;
521 x_catch_errors (display);
522 xfont = XLoadQueryFont (display, name);
523 if (x_had_errors_p (display))
524 {
525 /* This error is perhaps due to insufficient memory on X server.
526 Let's just ignore it. */
527 x_clear_errors (display);
528 xfont = NULL;
529 }
f0c55750
KH
530 fullname = Qnil;
531 /* Try to get the full name of FONT. */
532 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
533 {
534 char *p0, *p;
535 int dashes = 0;
536
537 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
538 /* Count the number of dashes in the "full name".
539 If it is too few, this isn't really the font's full name,
540 so don't use it.
541 In X11R4, the fonts did not come with their canonical names
542 stored in them. */
543 while (*p)
544 {
545 if (*p == '-')
546 dashes++;
547 p++;
548 }
549
550 if (dashes >= 13)
551 fullname = Fdowncase (make_unibyte_string (p0, p - p0));
552 XFree (p0);
553 }
c2f5bfd6
KH
554 x_uncatch_errors ();
555 UNBLOCK_INPUT;
556
557 if (! xfont)
f0c55750
KH
558 return Qnil;
559
560 font_object = font_make_object (VECSIZE (struct xfont_info));
561 ASET (font_object, FONT_TYPE_INDEX, Qx);
562 if (STRINGP (fullname))
960d80b9 563 font_parse_xlfd ((char *) SDATA (fullname), font_object);
f0c55750
KH
564 for (i = 1; i < FONT_ENTITY_MAX; i++)
565 ASET (font_object, i, AREF (entity, i));
566 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
567 if (STRINGP (fullname))
568 ASET (font_object, FONT_NAME_INDEX, fullname);
569 else
570 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
571 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
572 ASET (font_object, FONT_FILE_INDEX, Qnil);
573 ASET (font_object, FONT_FORMAT_INDEX, Qx);
574 font = XFONT_OBJECT (font_object);
575 ((struct xfont_info *) font)->xfont = xfont;
576 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
c2f5bfd6
KH
577 font->pixel_size = pixel_size;
578 font->driver = &xfont_driver;
c2f5bfd6 579 font->encoding_charset = encoding->id;
1886668d 580 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
581 font->ascent = xfont->ascent;
582 font->descent = xfont->descent;
f0c55750
KH
583 font->height = font->ascent + font->descent;
584 font->min_width = xfont->min_bounds.width;
c2f5bfd6
KH
585 if (xfont->min_bounds.width == xfont->max_bounds.width)
586 {
587 /* Fixed width font. */
f0c55750 588 font->average_width = font->space_width = xfont->min_bounds.width;
c2f5bfd6
KH
589 }
590 else
591 {
c2f5bfd6 592 XCharStruct *pcm;
f0c55750
KH
593 XChar2b char2b;
594 Lisp_Object val;
c2f5bfd6
KH
595
596 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
597 pcm = xfont_get_pcm (xfont, &char2b);
598 if (pcm)
f0c55750 599 font->space_width = pcm->width;
c2f5bfd6 600 else
f0c55750
KH
601 font->space_width = 0;
602
603 val = Ffont_get (font_object, QCavgwidth);
604 if (INTEGERP (val))
605 font->average_width = XINT (val);
606 if (font->average_width < 0)
607 font->average_width = - font->average_width;
608 if (font->average_width == 0
609 && encoding->ascii_compatible_p)
c2f5bfd6 610 {
f0c55750 611 int width = font->space_width, n = pcm != NULL;
c2f5bfd6 612
f0c55750
KH
613 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
614 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
615 width += pcm->width, n++;
616 font->average_width = width / n;
c2f5bfd6 617 }
c2f5bfd6 618 }
c2f5bfd6 619
f0c55750
KH
620 BLOCK_INPUT;
621 font->underline_thickness
622 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
623 ? (long) value : 0);
624 font->underline_position
625 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
626 ? (long) value : -1);
627 font->baseline_offset
c2f5bfd6
KH
628 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
629 ? (long) value : 0);
f0c55750 630 font->relative_compose
c2f5bfd6
KH
631 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
632 ? (long) value : 0);
f0c55750 633 font->default_ascent
c2f5bfd6
KH
634 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
635 ? (long) value : 0);
c2f5bfd6
KH
636 UNBLOCK_INPUT;
637
f0c55750
KH
638 if (NILP (fullname))
639 fullname = AREF (font_object, FONT_NAME_INDEX);
640 font->vertical_centering
641 = (STRINGP (Vvertical_centering_font_regexp)
642 && (fast_string_match_ignore_case
643 (Vvertical_centering_font_regexp, fullname) >= 0));
c2f5bfd6 644
f0c55750 645 return font_object;
c2f5bfd6
KH
646}
647
648static void
649xfont_close (f, font)
650 FRAME_PTR f;
651 struct font *font;
652{
653 BLOCK_INPUT;
f0c55750 654 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
c2f5bfd6 655 UNBLOCK_INPUT;
c2f5bfd6
KH
656}
657
658static int
659xfont_prepare_face (f, face)
660 FRAME_PTR f;
661 struct face *face;
662{
663 BLOCK_INPUT;
f0c55750
KH
664 XSetFont (FRAME_X_DISPLAY (f), face->gc,
665 ((struct xfont_info *) face->font)->xfont->fid);
c2f5bfd6
KH
666 UNBLOCK_INPUT;
667
668 return 0;
669}
670
c2f5bfd6
KH
671static int
672xfont_has_char (entity, c)
673 Lisp_Object entity;
674 int c;
675{
676 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
677 struct charset *repertory;
678
a9822ae8 679 if (font_registry_charsets (registry, NULL, &repertory) < 0)
c2f5bfd6
KH
680 return -1;
681 if (! repertory)
682 return -1;
683 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
684}
685
686static unsigned
687xfont_encode_char (font, c)
688 struct font *font;
689 int c;
690{
f0c55750 691 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
692 struct charset *charset;
693 unsigned code;
694 XChar2b char2b;
695
696 charset = CHARSET_FROM_ID (font->encoding_charset);
697 code = ENCODE_CHAR (charset, c);
698 if (code == CHARSET_INVALID_CODE (charset))
21138cff 699 return FONT_INVALID_CODE;
1886668d 700 if (font->repertory_charset >= 0)
c2f5bfd6 701 {
1886668d 702 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 703 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 704 ? code : FONT_INVALID_CODE);
c2f5bfd6 705 }
88649c62
KH
706 char2b.byte1 = code >> 8;
707 char2b.byte2 = code & 0xFF;
f0c55750 708 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
709}
710
711static int
712xfont_text_extents (font, code, nglyphs, metrics)
713 struct font *font;
714 unsigned *code;
715 int nglyphs;
716 struct font_metrics *metrics;
717{
f0c55750 718 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
719 int width = 0;
720 int i, x;
721
722 if (metrics)
723 bzero (metrics, sizeof (struct font_metrics));
724 for (i = 0, x = 0; i < nglyphs; i++)
725 {
726 XChar2b char2b;
727 static XCharStruct *pcm;
728
729 if (code[i] >= 0x10000)
730 continue;
731 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
f0c55750 732 pcm = xfont_get_pcm (xfont, &char2b);
c2f5bfd6
KH
733 if (! pcm)
734 continue;
735 if (metrics->lbearing > width + pcm->lbearing)
736 metrics->lbearing = width + pcm->lbearing;
737 if (metrics->rbearing < width + pcm->rbearing)
738 metrics->rbearing = width + pcm->rbearing;
739 if (metrics->ascent < pcm->ascent)
740 metrics->ascent = pcm->ascent;
741 if (metrics->descent < pcm->descent)
742 metrics->descent = pcm->descent;
743 width += pcm->width;
744 }
745 if (metrics)
746 metrics->width = width;
747 return width;
748}
749
750static int
751xfont_draw (s, from, to, x, y, with_background)
752 struct glyph_string *s;
753 int from, to, x, y, with_background;
754{
f0c55750 755 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
c2f5bfd6 756 int len = to - from;
6e34c9c1 757 GC gc = s->gc;
298fd5b1 758 int i;
6e34c9c1 759
f0c55750 760 if (s->gc != s->face->gc)
6e34c9c1 761 {
d45fefc7 762 BLOCK_INPUT;
f0c55750 763 XSetFont (s->display, gc, xfont->fid);
d45fefc7 764 UNBLOCK_INPUT;
6e34c9c1 765 }
c2f5bfd6
KH
766
767 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
768 {
769 char *str;
c2f5bfd6
KH
770 USE_SAFE_ALLOCA;
771
772 SAFE_ALLOCA (str, char *, len);
773 for (i = 0; i < len ; i++)
774 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
d45fefc7 775 BLOCK_INPUT;
c2f5bfd6 776 if (with_background > 0)
298fd5b1
KH
777 {
778 if (s->padding_p)
779 for (i = 0; i < len; i++)
780 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
781 gc, x + i, y, str + i, 1);
782 else
783 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
784 gc, x, y, str, len);
785 }
c2f5bfd6 786 else
298fd5b1
KH
787 {
788 if (s->padding_p)
789 for (i = 0; i < len; i++)
790 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
791 gc, x + i, y, str + i, 1);
792 else
793 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
794 gc, x, y, str, len);
795 }
d45fefc7 796 UNBLOCK_INPUT;
c2f5bfd6
KH
797 SAFE_FREE ();
798 return s->nchars;
799 }
800
d45fefc7 801 BLOCK_INPUT;
c2f5bfd6 802 if (with_background > 0)
298fd5b1
KH
803 {
804 if (s->padding_p)
805 for (i = 0; i < len; i++)
806 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
807 gc, x + i, y, s->char2b + from + i, 1);
808 else
809 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
810 gc, x, y, s->char2b + from, len);
811 }
c2f5bfd6 812 else
298fd5b1
KH
813 {
814 if (s->padding_p)
815 for (i = 0; i < len; i++)
816 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
817 gc, x + i, y, s->char2b + from + i, 1);
818 else
819 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
820 gc, x, y, s->char2b + from, len);
821 }
d45fefc7 822 UNBLOCK_INPUT;
c2f5bfd6
KH
823
824 return len;
825}
826
f0c55750
KH
827static int
828xfont_check (f, font)
829 FRAME_PTR f;
830 struct font *font;
831{
832 struct xfont_info *xfont = (struct xfont_info *) font;
833
834 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
835}
836
c2f5bfd6
KH
837\f
838void
839syms_of_xfont ()
840{
c2f5bfd6
KH
841 xfont_driver.type = Qx;
842 register_font_driver (&xfont_driver, NULL);
843}
885b7d09
MB
844
845/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
846 (do not change this comment) */