Bump version number to 23.0.95.
[emacs.git] / src / xfont.c
blob35113fdf798dc6f1162579fc44334ea818aa3745
1 /* xfont.c -- X core font driver.
2 Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <X11/Xlib.h>
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"
36 #include "ccl.h"
39 /* X core font driver. */
41 struct xfont_info
43 struct font font;
44 Display *display;
45 XFontStruct *xfont;
48 /* Prototypes of support functions. */
49 extern void x_clear_errors P_ ((Display *));
51 static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
53 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
54 is not contained in the font. */
56 static XCharStruct *
57 xfont_get_pcm (xfont, char2b)
58 XFontStruct *xfont;
59 XChar2b *char2b;
61 /* The result metric information. */
62 XCharStruct *pcm = NULL;
64 font_assert (xfont && char2b);
66 if (xfont->per_char != NULL)
68 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
70 /* min_char_or_byte2 specifies the linear character index
71 corresponding to the first element of the per_char array,
72 max_char_or_byte2 is the index of the last character. A
73 character with non-zero CHAR2B->byte1 is not in the font.
74 A character with byte2 less than min_char_or_byte2 or
75 greater max_char_or_byte2 is not in the font. */
76 if (char2b->byte1 == 0
77 && char2b->byte2 >= xfont->min_char_or_byte2
78 && char2b->byte2 <= xfont->max_char_or_byte2)
79 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
81 else
83 /* If either min_byte1 or max_byte1 are nonzero, both
84 min_char_or_byte2 and max_char_or_byte2 are less than
85 256, and the 2-byte character index values corresponding
86 to the per_char array element N (counting from 0) are:
88 byte1 = N/D + min_byte1
89 byte2 = N\D + min_char_or_byte2
91 where:
93 D = max_char_or_byte2 - min_char_or_byte2 + 1
94 / = integer division
95 \ = integer modulus */
96 if (char2b->byte1 >= xfont->min_byte1
97 && char2b->byte1 <= xfont->max_byte1
98 && char2b->byte2 >= xfont->min_char_or_byte2
99 && char2b->byte2 <= xfont->max_char_or_byte2)
100 pcm = (xfont->per_char
101 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
102 * (char2b->byte1 - xfont->min_byte1))
103 + (char2b->byte2 - xfont->min_char_or_byte2));
106 else
108 /* If the per_char pointer is null, all glyphs between the first
109 and last character indexes inclusive have the same
110 information, as given by both min_bounds and max_bounds. */
111 if (char2b->byte2 >= xfont->min_char_or_byte2
112 && char2b->byte2 <= xfont->max_char_or_byte2)
113 pcm = &xfont->max_bounds;
116 return ((pcm == NULL
117 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
118 ? NULL : pcm);
121 static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
122 static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
123 static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
124 static Lisp_Object xfont_list_family P_ ((Lisp_Object));
125 static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
126 static void xfont_close P_ ((FRAME_PTR, struct font *));
127 static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
128 static int xfont_has_char P_ ((Lisp_Object, int));
129 static unsigned xfont_encode_char P_ ((struct font *, int));
130 static int xfont_text_extents P_ ((struct font *, unsigned *, int,
131 struct font_metrics *));
132 static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
133 static int xfont_check P_ ((FRAME_PTR, struct font *));
135 struct font_driver xfont_driver =
137 0, /* Qx */
138 0, /* case insensitive */
139 xfont_get_cache,
140 xfont_list,
141 xfont_match,
142 xfont_list_family,
143 NULL,
144 xfont_open,
145 xfont_close,
146 xfont_prepare_face,
147 NULL,
148 xfont_has_char,
149 xfont_encode_char,
150 xfont_text_extents,
151 xfont_draw,
152 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
153 xfont_check
156 extern Lisp_Object QCname;
158 static Lisp_Object
159 xfont_get_cache (f)
160 FRAME_PTR f;
162 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
164 return (dpyinfo->name_list_element);
167 extern Lisp_Object Vface_alternative_font_registry_alist;
169 static int
170 compare_font_names (const void *name1, const void *name2)
172 return xstrcasecmp (*(const unsigned char **) name1,
173 *(const unsigned char **) name2);
176 /* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
177 of the decoding result. LEN is the byte length of XLFD, or -1 if
178 XLFD is NULL terminated. The caller must assure that OUTPUT is at
179 least twice (plus 1) as large as XLFD. */
181 static int
182 xfont_decode_coding_xlfd (char *xlfd, int len, char *output)
184 char *p0 = xlfd, *p1 = output;
185 int c;
187 while (*p0)
189 c = *(unsigned char *) p0++;
190 p1 += CHAR_STRING (c, p1);
191 if (--len == 0)
192 break;
194 *p1 = 0;
195 return (p1 - output);
198 /* Encode XLFD from UTF-8 to iso-8859-1 destructively, and return the
199 resulting byte length. If XLFD contains unencodable character,
200 return -1. */
202 static int
203 xfont_encode_coding_xlfd (char *xlfd)
205 const unsigned char *p0 = (unsigned char *) xlfd;
206 unsigned char *p1 = (unsigned char *) xlfd;
207 int len = 0;
209 while (*p0)
211 int c = STRING_CHAR_ADVANCE (p0);
213 if (c >= 0x100)
214 return -1;
215 *p1++ = c;
216 len++;
218 *p1 = 0;
219 return len;
222 /* Check if CHARS (cons or vector) is supported by XFONT whose
223 encoding charset is ENCODING (XFONT is NULL) or by a font whose
224 registry corresponds to ENCODING and REPERTORY.
225 Return 1 if supported, return 0 otherwise. */
227 static int
228 xfont_chars_supported (Lisp_Object chars, XFontStruct *xfont,
229 struct charset *encoding, struct charset *repertory)
231 struct charset *charset = repertory ? repertory : encoding;
233 if (CONSP (chars))
235 for (; CONSP (chars); chars = XCDR (chars))
237 int c = XINT (XCAR (chars));
238 unsigned code = ENCODE_CHAR (charset, c);
239 XChar2b char2b;
241 if (code == CHARSET_INVALID_CODE (charset))
242 break;
243 if (! xfont)
244 continue;
245 if (code >= 0x10000)
246 break;
247 char2b.byte1 = code >> 8;
248 char2b.byte2 = code & 0xFF;
249 if (! xfont_get_pcm (xfont, &char2b))
250 break;
252 return (NILP (chars));
254 else if (VECTORP (chars))
256 int i;
258 for (i = ASIZE (chars) - 1; i >= 0; i--)
260 int c = XINT (AREF (chars, i));
261 unsigned code = ENCODE_CHAR (charset, c);
262 XChar2b char2b;
264 if (code == CHARSET_INVALID_CODE (charset))
265 continue;
266 if (! xfont)
267 break;
268 if (code >= 0x10000)
269 continue;
270 char2b.byte1 = code >> 8;
271 char2b.byte2 = code & 0xFF;
272 if (xfont_get_pcm (xfont, &char2b))
273 break;
275 return (i >= 0);
277 return 0;
280 /* A hash table recoding which font supports which scritps. Each key
281 is a vector of characteristic font propertis FOUNDRY to WIDTH and
282 ADDSTYLE, and each value is a list of script symbols.
284 We assume that fonts that have the same value in the above
285 properties supports the same set of characters on all displays. */
287 static Lisp_Object xfont_scripts_cache;
289 /* Re-usable vector to store characteristic font properites. */
290 static Lisp_Object xfont_scratch_props;
292 extern Lisp_Object Qlatin;
294 /* Return a list of scripts supported by the font of FONTNAME whose
295 characteristic properties are in PROPS and whose encoding charset
296 is ENCODING. A caller must call BLOCK_INPUT in advance. */
298 static Lisp_Object
299 xfont_supported_scripts (Display *display, char *fontname, Lisp_Object props,
300 struct charset *encoding)
302 Lisp_Object scripts;
304 /* Two special cases to avoid opening rather big fonts. */
305 if (EQ (AREF (props, 2), Qja))
306 return Fcons (intern ("kana"), Fcons (intern ("han"), Qnil));
307 if (EQ (AREF (props, 2), Qko))
308 return Fcons (intern ("hangul"), Qnil);
309 scripts = Fgethash (props, xfont_scripts_cache, Qt);
310 if (EQ (scripts, Qt))
312 XFontStruct *xfont;
313 Lisp_Object val;
315 scripts = Qnil;
316 xfont = XLoadQueryFont (display, fontname);
317 if (xfont)
319 if (xfont->per_char)
321 for (val = Vscript_representative_chars; CONSP (val);
322 val = XCDR (val))
323 if (CONSP (XCAR (val)) && SYMBOLP (XCAR (XCAR (val))))
325 Lisp_Object script = XCAR (XCAR (val));
326 Lisp_Object chars = XCDR (XCAR (val));
328 if (xfont_chars_supported (chars, xfont, encoding, NULL))
329 scripts = Fcons (script, scripts);
332 XFreeFont (display, xfont);
334 if (EQ (AREF (props, 3), Qiso10646_1)
335 && NILP (Fmemq (Qlatin, scripts)))
336 scripts = Fcons (Qlatin, scripts);
337 Fputhash (Fcopy_sequence (props), scripts, xfont_scripts_cache);
339 return scripts;
342 extern Lisp_Object Vscalable_fonts_allowed;
344 static Lisp_Object
345 xfont_list_pattern (Display *display, char *pattern,
346 Lisp_Object registry, Lisp_Object script)
348 Lisp_Object list = Qnil;
349 Lisp_Object chars = Qnil;
350 struct charset *encoding, *repertory = NULL;
351 int i, limit, num_fonts;
352 char **names;
353 /* Large enough to decode the longest XLFD (255 bytes). */
354 char buf[512];
356 if (! NILP (registry)
357 && font_registry_charsets (registry, &encoding, &repertory) < 0)
358 /* Unknown REGISTRY, not supported. */
359 return Qnil;
360 if (! NILP (script))
362 chars = assq_no_quit (script, Vscript_representative_chars);
363 if (NILP (chars))
364 /* We can't tell whether or not a font supports SCRIPT. */
365 return Qnil;
366 chars = XCDR (chars);
367 if (repertory)
369 if (! xfont_chars_supported (chars, NULL, encoding, repertory))
370 return Qnil;
371 script = Qnil;
375 BLOCK_INPUT;
376 x_catch_errors (display);
378 for (limit = 512; ; limit *= 2)
380 names = XListFonts (display, pattern, limit, &num_fonts);
381 if (x_had_errors_p (display))
383 /* This error is perhaps due to insufficient memory on X
384 server. Let's just ignore it. */
385 x_clear_errors (display);
386 num_fonts = 0;
387 break;
389 if (num_fonts < limit)
390 break;
391 XFreeFontNames (names);
394 if (num_fonts > 0)
396 char **indices = alloca (sizeof (char *) * num_fonts);
397 Lisp_Object *props = XVECTOR (xfont_scratch_props)->contents;
398 Lisp_Object scripts = Qnil;
400 for (i = 0; i < ASIZE (xfont_scratch_props); i++)
401 props[i] = Qnil;
402 for (i = 0; i < num_fonts; i++)
403 indices[i] = names[i];
404 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
406 for (i = 0; i < num_fonts; i++)
408 Lisp_Object entity;
410 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
411 continue;
412 entity = font_make_entity ();
413 xfont_decode_coding_xlfd (indices[i], -1, buf);
414 font_parse_xlfd (buf, entity);
415 ASET (entity, FONT_TYPE_INDEX, Qx);
416 /* Avoid auto-scaled fonts. */
417 if (XINT (AREF (entity, FONT_DPI_INDEX)) != 0
418 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0)
419 continue;
420 /* Avoid not-allowed scalable fonts. */
421 if (NILP (Vscalable_fonts_allowed))
423 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
424 continue;
426 else if (CONSP (Vscalable_fonts_allowed))
428 Lisp_Object tail, elt;
430 for (tail = Vscalable_fonts_allowed; CONSP (tail);
431 tail = XCDR (tail))
433 elt = XCAR (tail);
434 if (STRINGP (elt)
435 && fast_c_string_match_ignore_case (elt, indices[i]) >= 0)
436 break;
438 if (! CONSP (tail))
439 continue;
442 /* Update encoding and repertory if necessary. */
443 if (! EQ (registry, AREF (entity, FONT_REGISTRY_INDEX)))
445 registry = AREF (entity, FONT_REGISTRY_INDEX);
446 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
447 encoding = NULL;
449 if (! encoding)
450 /* Unknown REGISTRY, not supported. */
451 continue;
452 if (repertory)
454 if (NILP (script)
455 || xfont_chars_supported (chars, NULL, encoding, repertory))
456 list = Fcons (entity, list);
457 continue;
459 if (memcmp (props, &(AREF (entity, FONT_FOUNDRY_INDEX)),
460 sizeof (Lisp_Object) * 7)
461 || ! EQ (AREF (entity, FONT_SPACING_INDEX), props[7]))
463 memcpy (props, &(AREF (entity, FONT_FOUNDRY_INDEX)),
464 sizeof (Lisp_Object) * 7);
465 props[7] = AREF (entity, FONT_SPACING_INDEX);
466 scripts = xfont_supported_scripts (display, indices[i],
467 xfont_scratch_props, encoding);
469 if (NILP (script)
470 || ! NILP (Fmemq (script, scripts)))
471 list = Fcons (entity, list);
473 XFreeFontNames (names);
476 x_uncatch_errors ();
477 UNBLOCK_INPUT;
479 font_add_log ("xfont-list", build_string (pattern), list);
480 return list;
483 static Lisp_Object
484 xfont_list (frame, spec)
485 Lisp_Object frame, spec;
487 FRAME_PTR f = XFRAME (frame);
488 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
489 Lisp_Object registry, list, val, extra, script;
490 int len;
491 /* Large enough to contain the longest XLFD (255 bytes) in UTF-8. */
492 char name[512];
494 extra = AREF (spec, FONT_EXTRA_INDEX);
495 if (CONSP (extra))
497 val = assq_no_quit (QCotf, extra);
498 if (! NILP (val))
499 return Qnil;
500 val = assq_no_quit (QClang, extra);
501 if (! NILP (val))
502 return Qnil;
505 registry = AREF (spec, FONT_REGISTRY_INDEX);
506 len = font_unparse_xlfd (spec, 0, name, 512);
507 if (len < 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
508 return Qnil;
510 val = assq_no_quit (QCscript, extra);
511 script = CDR (val);
512 list = xfont_list_pattern (display, name, registry, script);
513 if (NILP (list) && NILP (registry))
515 /* Try iso10646-1 */
516 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
518 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
520 strcpy (r, "iso10646-1");
521 list = xfont_list_pattern (display, name, Qiso10646_1, script);
524 if (NILP (list) && ! NILP (registry))
526 /* Try alternate registries. */
527 Lisp_Object alter;
529 if ((alter = Fassoc (SYMBOL_NAME (registry),
530 Vface_alternative_font_registry_alist),
531 CONSP (alter)))
533 /* Pointer to REGISTRY-ENCODING field. */
534 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
536 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
537 if (STRINGP (XCAR (alter))
538 && ((r - name) + SBYTES (XCAR (alter))) < 256)
540 strcpy (r, (char *) SDATA (XCAR (alter)));
541 list = xfont_list_pattern (display, name, registry, script);
542 if (! NILP (list))
543 break;
547 if (NILP (list))
549 /* Try alias. */
550 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
551 if (CONSP (val) && STRINGP (XCDR (val)) && SBYTES (XCDR (val)) < 512)
553 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
554 if (xfont_encode_coding_xlfd (name) < 0)
555 return Qnil;
556 list = xfont_list_pattern (display, name, registry, script);
560 return list;
563 static Lisp_Object
564 xfont_match (frame, spec)
565 Lisp_Object frame, spec;
567 FRAME_PTR f = XFRAME (frame);
568 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
569 Lisp_Object extra, val, entity;
570 char name[512];
571 XFontStruct *xfont;
572 unsigned long value;
574 extra = AREF (spec, FONT_EXTRA_INDEX);
575 val = assq_no_quit (QCname, extra);
576 if (! CONSP (val) || ! STRINGP (XCDR (val)))
578 if (font_unparse_xlfd (spec, 0, name, 512) < 0)
579 return Qnil;
581 else if (SBYTES (XCDR (val)) < 512)
582 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
583 else
584 return Qnil;
585 if (xfont_encode_coding_xlfd (name) < 0)
586 return Qnil;
588 BLOCK_INPUT;
589 entity = Qnil;
590 xfont = XLoadQueryFont (display, name);
591 if (xfont)
593 if (XGetFontProperty (xfont, XA_FONT, &value))
595 int len;
596 char *s;
598 s = (char *) XGetAtomName (display, (Atom) value);
599 len = strlen (s);
601 /* If DXPC (a Differential X Protocol Compressor)
602 Ver.3.7 is running, XGetAtomName will return null
603 string. We must avoid such a name. */
604 if (len > 0)
606 entity = font_make_entity ();
607 ASET (entity, FONT_TYPE_INDEX, Qx);
608 xfont_decode_coding_xlfd (s, -1, name);
609 if (font_parse_xlfd (name, entity) < 0)
610 entity = Qnil;
612 XFree (s);
614 XFreeFont (display, xfont);
616 UNBLOCK_INPUT;
618 font_add_log ("xfont-match", spec, entity);
619 return entity;
622 static Lisp_Object
623 xfont_list_family (frame)
624 Lisp_Object frame;
626 FRAME_PTR f = XFRAME (frame);
627 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
628 char **names;
629 int num_fonts, i;
630 Lisp_Object list;
631 char *last_family;
632 int last_len;
634 BLOCK_INPUT;
635 x_catch_errors (dpyinfo->display);
636 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
637 0x8000, &num_fonts);
638 if (x_had_errors_p (dpyinfo->display))
640 /* This error is perhaps due to insufficient memory on X server.
641 Let's just ignore it. */
642 x_clear_errors (dpyinfo->display);
643 num_fonts = 0;
646 list = Qnil;
647 for (i = 0, last_len = 0; i < num_fonts; i++)
649 char *p0 = names[i], *p1, buf[512];
650 Lisp_Object family;
651 int decoded_len;
653 p0++; /* skip the leading '-' */
654 while (*p0 && *p0 != '-') p0++; /* skip foundry */
655 if (! *p0)
656 continue;
657 p1 = ++p0;
658 while (*p1 && *p1 != '-') p1++; /* find the end of family */
659 if (! *p1 || p1 == p0)
660 continue;
661 if (last_len == p1 - p0
662 && bcmp (last_family, p0, last_len) == 0)
663 continue;
664 last_len = p1 - p0;
665 last_family = p0;
667 decoded_len = xfont_decode_coding_xlfd (p0, last_len, buf);
668 family = font_intern_prop (p0, decoded_len, 1);
669 if (NILP (assq_no_quit (family, list)))
670 list = Fcons (family, list);
673 XFreeFontNames (names);
674 x_uncatch_errors ();
675 UNBLOCK_INPUT;
677 return list;
680 extern Lisp_Object QCavgwidth;
682 static Lisp_Object
683 xfont_open (f, entity, pixel_size)
684 FRAME_PTR f;
685 Lisp_Object entity;
686 int pixel_size;
688 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
689 Display *display = dpyinfo->display;
690 char name[512];
691 int len;
692 unsigned long value;
693 Lisp_Object registry;
694 struct charset *encoding, *repertory;
695 Lisp_Object font_object, fullname;
696 struct font *font;
697 XFontStruct *xfont;
699 /* At first, check if we know how to encode characters for this
700 font. */
701 registry = AREF (entity, FONT_REGISTRY_INDEX);
702 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
704 font_add_log (" x:unknown registry", registry, Qnil);
705 return Qnil;
708 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
709 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
710 else if (pixel_size == 0)
712 if (FRAME_FONT (f))
713 pixel_size = FRAME_FONT (f)->pixel_size;
714 else
715 pixel_size = 14;
717 len = font_unparse_xlfd (entity, pixel_size, name, 512);
718 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
720 font_add_log (" x:unparse failed", entity, Qnil);
721 return Qnil;
724 BLOCK_INPUT;
725 x_catch_errors (display);
726 xfont = XLoadQueryFont (display, name);
727 if (x_had_errors_p (display))
729 /* This error is perhaps due to insufficient memory on X server.
730 Let's just ignore it. */
731 x_clear_errors (display);
732 xfont = NULL;
734 else if (! xfont)
736 /* Some version of X lists:
737 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
738 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
739 but can open only:
740 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
742 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
743 So, we try again with wildcards in RESX and RESY. */
744 Lisp_Object temp;
746 temp = Fcopy_font_spec (entity);
747 ASET (temp, FONT_DPI_INDEX, Qnil);
748 len = font_unparse_xlfd (temp, pixel_size, name, 512);
749 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
751 font_add_log (" x:unparse failed", temp, Qnil);
752 return Qnil;
754 xfont = XLoadQueryFont (display, name);
755 if (x_had_errors_p (display))
757 /* This error is perhaps due to insufficient memory on X server.
758 Let's just ignore it. */
759 x_clear_errors (display);
760 xfont = NULL;
763 fullname = Qnil;
764 /* Try to get the full name of FONT. */
765 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
767 char *p0, *p;
768 int dashes = 0;
770 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
771 /* Count the number of dashes in the "full name".
772 If it is too few, this isn't really the font's full name,
773 so don't use it.
774 In X11R4, the fonts did not come with their canonical names
775 stored in them. */
776 while (*p)
778 if (*p == '-')
779 dashes++;
780 p++;
783 if (dashes >= 13)
785 len = xfont_decode_coding_xlfd (p0, -1, name);
786 fullname = Fdowncase (make_string (name, len));
788 XFree (p0);
790 x_uncatch_errors ();
791 UNBLOCK_INPUT;
793 if (! xfont)
795 font_add_log (" x:open failed", build_string (name), Qnil);
796 return Qnil;
799 font_object = font_make_object (VECSIZE (struct xfont_info),
800 entity, pixel_size);
801 ASET (font_object, FONT_TYPE_INDEX, Qx);
802 if (STRINGP (fullname))
804 font_parse_xlfd ((char *) SDATA (fullname), font_object);
805 ASET (font_object, FONT_NAME_INDEX, fullname);
807 else
809 char buf[512];
811 len = xfont_decode_coding_xlfd (name, -1, buf);
812 ASET (font_object, FONT_NAME_INDEX, make_string (buf, len));
814 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
815 ASET (font_object, FONT_FILE_INDEX, Qnil);
816 ASET (font_object, FONT_FORMAT_INDEX, Qx);
817 font = XFONT_OBJECT (font_object);
818 ((struct xfont_info *) font)->xfont = xfont;
819 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
820 font->pixel_size = pixel_size;
821 font->driver = &xfont_driver;
822 font->encoding_charset = encoding->id;
823 font->repertory_charset = repertory ? repertory->id : -1;
824 font->ascent = xfont->ascent;
825 font->descent = xfont->descent;
826 font->height = font->ascent + font->descent;
827 font->min_width = xfont->min_bounds.width;
828 if (xfont->min_bounds.width == xfont->max_bounds.width)
830 /* Fixed width font. */
831 font->average_width = font->space_width = xfont->min_bounds.width;
833 else
835 XCharStruct *pcm;
836 XChar2b char2b;
837 Lisp_Object val;
839 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
840 pcm = xfont_get_pcm (xfont, &char2b);
841 if (pcm)
842 font->space_width = pcm->width;
843 else
844 font->space_width = 0;
846 val = Ffont_get (font_object, QCavgwidth);
847 if (INTEGERP (val))
848 font->average_width = XINT (val);
849 if (font->average_width < 0)
850 font->average_width = - font->average_width;
851 if (font->average_width == 0
852 && encoding->ascii_compatible_p)
854 int width = font->space_width, n = pcm != NULL;
856 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
857 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
858 width += pcm->width, n++;
859 if (n > 0)
860 font->average_width = width / n;
862 if (font->average_width == 0)
863 /* No easy way other than this to get a reasonable
864 average_width. */
865 font->average_width
866 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
869 BLOCK_INPUT;
870 font->underline_thickness
871 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
872 ? (long) value : 0);
873 font->underline_position
874 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
875 ? (long) value : -1);
876 font->baseline_offset
877 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
878 ? (long) value : 0);
879 font->relative_compose
880 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
881 ? (long) value : 0);
882 font->default_ascent
883 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
884 ? (long) value : 0);
885 UNBLOCK_INPUT;
887 if (NILP (fullname))
888 fullname = AREF (font_object, FONT_NAME_INDEX);
889 font->vertical_centering
890 = (STRINGP (Vvertical_centering_font_regexp)
891 && (fast_string_match_ignore_case
892 (Vvertical_centering_font_regexp, fullname) >= 0));
894 return font_object;
897 static void
898 xfont_close (f, font)
899 FRAME_PTR f;
900 struct font *font;
902 BLOCK_INPUT;
903 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
904 UNBLOCK_INPUT;
907 static int
908 xfont_prepare_face (f, face)
909 FRAME_PTR f;
910 struct face *face;
912 BLOCK_INPUT;
913 XSetFont (FRAME_X_DISPLAY (f), face->gc,
914 ((struct xfont_info *) face->font)->xfont->fid);
915 UNBLOCK_INPUT;
917 return 0;
920 static int
921 xfont_has_char (font, c)
922 Lisp_Object font;
923 int c;
925 Lisp_Object registry = AREF (font, FONT_REGISTRY_INDEX);
926 struct charset *encoding;
927 struct charset *repertory = NULL;
929 if (EQ (registry, Qiso10646_1))
931 encoding = CHARSET_FROM_ID (charset_unicode);
932 /* We use a font of `ja' and `ko' adstyle only for a character
933 in JISX0208 and KSC5601 charsets respectively. */
934 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
935 && charset_jisx0208 >= 0)
936 repertory = CHARSET_FROM_ID (charset_jisx0208);
937 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
938 && charset_ksc5601 >= 0)
939 repertory = CHARSET_FROM_ID (charset_ksc5601);
941 else if (font_registry_charsets (registry, &encoding, &repertory) < 0)
942 /* Unknown REGISTRY, not usable. */
943 return 0;
944 if (ASCII_CHAR_P (c) && encoding->ascii_compatible_p)
945 return 1;
946 if (! repertory)
947 return -1;
948 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
951 static unsigned
952 xfont_encode_char (font, c)
953 struct font *font;
954 int c;
956 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
957 struct charset *charset;
958 unsigned code;
959 XChar2b char2b;
961 charset = CHARSET_FROM_ID (font->encoding_charset);
962 code = ENCODE_CHAR (charset, c);
963 if (code == CHARSET_INVALID_CODE (charset))
964 return FONT_INVALID_CODE;
965 if (font->repertory_charset >= 0)
967 charset = CHARSET_FROM_ID (font->repertory_charset);
968 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
969 ? code : FONT_INVALID_CODE);
971 char2b.byte1 = code >> 8;
972 char2b.byte2 = code & 0xFF;
973 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
976 static int
977 xfont_text_extents (font, code, nglyphs, metrics)
978 struct font *font;
979 unsigned *code;
980 int nglyphs;
981 struct font_metrics *metrics;
983 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
984 int width = 0;
985 int i, first, x;
987 if (metrics)
988 bzero (metrics, sizeof (struct font_metrics));
989 for (i = 0, x = 0, first = 1; i < nglyphs; i++)
991 XChar2b char2b;
992 static XCharStruct *pcm;
994 if (code[i] >= 0x10000)
995 continue;
996 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
997 pcm = xfont_get_pcm (xfont, &char2b);
998 if (! pcm)
999 continue;
1000 if (first)
1002 if (metrics)
1004 metrics->lbearing = pcm->lbearing;
1005 metrics->rbearing = pcm->rbearing;
1006 metrics->ascent = pcm->ascent;
1007 metrics->descent = pcm->descent;
1009 first = 0;
1011 else
1013 if (metrics)
1015 if (metrics->lbearing > width + pcm->lbearing)
1016 metrics->lbearing = width + pcm->lbearing;
1017 if (metrics->rbearing < width + pcm->rbearing)
1018 metrics->rbearing = width + pcm->rbearing;
1019 if (metrics->ascent < pcm->ascent)
1020 metrics->ascent = pcm->ascent;
1021 if (metrics->descent < pcm->descent)
1022 metrics->descent = pcm->descent;
1025 width += pcm->width;
1027 if (metrics)
1028 metrics->width = width;
1029 return width;
1032 static int
1033 xfont_draw (s, from, to, x, y, with_background)
1034 struct glyph_string *s;
1035 int from, to, x, y, with_background;
1037 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
1038 int len = to - from;
1039 GC gc = s->gc;
1040 int i;
1042 if (s->gc != s->face->gc)
1044 BLOCK_INPUT;
1045 XSetFont (s->display, gc, xfont->fid);
1046 UNBLOCK_INPUT;
1049 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
1051 char *str;
1052 USE_SAFE_ALLOCA;
1054 SAFE_ALLOCA (str, char *, len);
1055 for (i = 0; i < len ; i++)
1056 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
1057 BLOCK_INPUT;
1058 if (with_background > 0)
1060 if (s->padding_p)
1061 for (i = 0; i < len; i++)
1062 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1063 gc, x + i, y, str + i, 1);
1064 else
1065 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1066 gc, x, y, str, len);
1068 else
1070 if (s->padding_p)
1071 for (i = 0; i < len; i++)
1072 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1073 gc, x + i, y, str + i, 1);
1074 else
1075 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1076 gc, x, y, str, len);
1078 UNBLOCK_INPUT;
1079 SAFE_FREE ();
1080 return s->nchars;
1083 BLOCK_INPUT;
1084 if (with_background > 0)
1086 if (s->padding_p)
1087 for (i = 0; i < len; i++)
1088 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1089 gc, x + i, y, s->char2b + from + i, 1);
1090 else
1091 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1092 gc, x, y, s->char2b + from, len);
1094 else
1096 if (s->padding_p)
1097 for (i = 0; i < len; i++)
1098 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1099 gc, x + i, y, s->char2b + from + i, 1);
1100 else
1101 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1102 gc, x, y, s->char2b + from, len);
1104 UNBLOCK_INPUT;
1106 return len;
1109 static int
1110 xfont_check (f, font)
1111 FRAME_PTR f;
1112 struct font *font;
1114 struct xfont_info *xfont = (struct xfont_info *) font;
1116 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
1120 void
1121 syms_of_xfont ()
1123 staticpro (&xfont_scripts_cache);
1124 { /* Here we rely on the fact that syms_of_xfont (via syms_of_font)
1125 is called fairly late, when QCtest and Qequal are known to be set. */
1126 Lisp_Object args[2];
1127 args[0] = QCtest;
1128 args[1] = Qequal;
1129 xfont_scripts_cache = Fmake_hash_table (2, args);
1131 staticpro (&xfont_scratch_props);
1132 xfont_scratch_props = Fmake_vector (make_number (8), Qnil);
1133 xfont_driver.type = Qx;
1134 register_font_driver (&xfont_driver, NULL);
1137 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
1138 (do not change this comment) */