Allow 'browse-url-emacs' to fetch URL in the selected window
[emacs.git] / src / xfont.c
blobc2e416bc058649bc23f03483630f76ca84e53ad6
1 /* xfont.c -- X core font driver.
2 Copyright (C) 2006-2018 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
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 (at
12 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 <https://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 "xterm.h"
29 #include "frame.h"
30 #include "blockinput.h"
31 #include "character.h"
32 #include "charset.h"
33 #include "font.h"
36 /* X core font driver. */
38 struct xfont_info
40 struct font font;
41 Display *display;
42 XFontStruct *xfont;
43 unsigned x_display_id;
46 /* Prototypes of support functions. */
48 static XCharStruct *xfont_get_pcm (XFontStruct *, XChar2b *);
50 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
51 is not contained in the font. */
53 static XCharStruct *
54 xfont_get_pcm (XFontStruct *xfont, XChar2b *char2b)
56 /* The result metric information. */
57 XCharStruct *pcm = NULL;
59 eassert (xfont && char2b);
61 if (xfont->per_char != NULL)
63 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
65 /* min_char_or_byte2 specifies the linear character index
66 corresponding to the first element of the per_char array,
67 max_char_or_byte2 is the index of the last character. A
68 character with non-zero CHAR2B->byte1 is not in the font.
69 A character with byte2 less than min_char_or_byte2 or
70 greater max_char_or_byte2 is not in the font. */
71 if (char2b->byte1 == 0
72 && char2b->byte2 >= xfont->min_char_or_byte2
73 && char2b->byte2 <= xfont->max_char_or_byte2)
74 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
76 else
78 /* If either min_byte1 or max_byte1 are nonzero, both
79 min_char_or_byte2 and max_char_or_byte2 are less than
80 256, and the 2-byte character index values corresponding
81 to the per_char array element N (counting from 0) are:
83 byte1 = N/D + min_byte1
84 byte2 = N\D + min_char_or_byte2
86 where:
88 D = max_char_or_byte2 - min_char_or_byte2 + 1
89 / = integer division
90 \ = integer modulus */
91 if (char2b->byte1 >= xfont->min_byte1
92 && char2b->byte1 <= xfont->max_byte1
93 && char2b->byte2 >= xfont->min_char_or_byte2
94 && char2b->byte2 <= xfont->max_char_or_byte2)
95 pcm = (xfont->per_char
96 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
97 * (char2b->byte1 - xfont->min_byte1))
98 + (char2b->byte2 - xfont->min_char_or_byte2));
101 else
103 /* If the per_char pointer is null, all glyphs between the first
104 and last character indexes inclusive have the same
105 information, as given by both min_bounds and max_bounds. */
106 if (char2b->byte2 >= xfont->min_char_or_byte2
107 && char2b->byte2 <= xfont->max_char_or_byte2)
108 pcm = &xfont->max_bounds;
111 return ((pcm == NULL
112 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
113 ? NULL : pcm);
116 Lisp_Object
117 xfont_get_cache (struct frame *f)
119 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
121 return (dpyinfo->name_list_element);
124 static int
125 compare_font_names (const void *name1, const void *name2)
127 char *const *n1 = name1;
128 char *const *n2 = name2;
129 return xstrcasecmp (*n1, *n2);
132 /* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
133 of the decoding result. LEN is the byte length of XLFD, or -1 if
134 XLFD is NULL terminated. The caller must assure that OUTPUT is at
135 least twice (plus 1) as large as XLFD. */
137 static ptrdiff_t
138 xfont_decode_coding_xlfd (char *xlfd, int len, char *output)
140 char *p0 = xlfd, *p1 = output;
141 int c;
143 while (*p0)
145 c = *(unsigned char *) p0++;
146 p1 += CHAR_STRING (c, (unsigned char *) p1);
147 if (--len == 0)
148 break;
150 *p1 = 0;
151 return (p1 - output);
154 /* Encode XLFD from UTF-8 to iso-8859-1 destructively, and return the
155 resulting byte length. If XLFD contains unencodable character,
156 return -1. */
158 static int
159 xfont_encode_coding_xlfd (char *xlfd)
161 const unsigned char *p0 = (unsigned char *) xlfd;
162 unsigned char *p1 = (unsigned char *) xlfd;
163 int len = 0;
165 while (*p0)
167 int c = STRING_CHAR_ADVANCE (p0);
169 if (c >= 0x100)
170 return -1;
171 *p1++ = c;
172 len++;
174 *p1 = 0;
175 return len;
178 /* Check if CHARS (cons or vector) is supported by XFONT whose
179 encoding charset is ENCODING (XFONT is NULL) or by a font whose
180 registry corresponds to ENCODING and REPERTORY.
181 Return true if supported. */
183 static bool
184 xfont_chars_supported (Lisp_Object chars, XFontStruct *xfont,
185 struct charset *encoding, struct charset *repertory)
187 struct charset *charset = repertory ? repertory : encoding;
189 if (CONSP (chars))
191 for (; CONSP (chars); chars = XCDR (chars))
193 int c = XINT (XCAR (chars));
194 unsigned code = ENCODE_CHAR (charset, c);
195 XChar2b char2b;
197 if (code == CHARSET_INVALID_CODE (charset))
198 break;
199 if (! xfont)
200 continue;
201 if (code >= 0x10000)
202 break;
203 char2b.byte1 = code >> 8;
204 char2b.byte2 = code & 0xFF;
205 if (! xfont_get_pcm (xfont, &char2b))
206 break;
208 return (NILP (chars));
210 else if (VECTORP (chars))
212 ptrdiff_t i;
214 for (i = ASIZE (chars) - 1; i >= 0; i--)
216 int c = XINT (AREF (chars, i));
217 unsigned code = ENCODE_CHAR (charset, c);
218 XChar2b char2b;
220 if (code == CHARSET_INVALID_CODE (charset))
221 continue;
222 if (! xfont)
223 break;
224 if (code >= 0x10000)
225 continue;
226 char2b.byte1 = code >> 8;
227 char2b.byte2 = code & 0xFF;
228 if (xfont_get_pcm (xfont, &char2b))
229 break;
231 return (i >= 0);
233 return false;
236 /* A hash table recoding which font supports which scripts. Each key
237 is a vector of characteristic font properties FOUNDRY to WIDTH and
238 ADDSTYLE, and each value is a list of script symbols.
240 We assume that fonts that have the same value in the above
241 properties supports the same set of characters on all displays. */
243 static Lisp_Object xfont_scripts_cache;
245 /* Re-usable vector to store characteristic font properties. */
246 static Lisp_Object xfont_scratch_props;
248 /* Return a list of scripts supported by the font of FONTNAME whose
249 characteristic properties are in PROPS and whose encoding charset
250 is ENCODING. A caller must call BLOCK_INPUT in advance. */
252 static Lisp_Object
253 xfont_supported_scripts (Display *display, char *fontname, Lisp_Object props,
254 struct charset *encoding)
256 Lisp_Object scripts;
258 /* Two special cases to avoid opening rather big fonts. */
259 if (EQ (AREF (props, 2), Qja))
260 return list2 (intern ("kana"), intern ("han"));
261 if (EQ (AREF (props, 2), Qko))
262 return list1 (intern ("hangul"));
263 scripts = Fgethash (props, xfont_scripts_cache, Qt);
264 if (EQ (scripts, Qt))
266 XFontStruct *xfont;
267 Lisp_Object val;
269 scripts = Qnil;
270 xfont = XLoadQueryFont (display, fontname);
271 if (xfont)
273 if (xfont->per_char)
275 for (val = Vscript_representative_chars; CONSP (val);
276 val = XCDR (val))
277 if (CONSP (XCAR (val)) && SYMBOLP (XCAR (XCAR (val))))
279 Lisp_Object script = XCAR (XCAR (val));
280 Lisp_Object chars = XCDR (XCAR (val));
282 if (xfont_chars_supported (chars, xfont, encoding, NULL))
283 scripts = Fcons (script, scripts);
286 XFreeFont (display, xfont);
288 if (EQ (AREF (props, 3), Qiso10646_1)
289 && NILP (Fmemq (Qlatin, scripts)))
290 scripts = Fcons (Qlatin, scripts);
291 Fputhash (Fcopy_sequence (props), scripts, xfont_scripts_cache);
293 return scripts;
296 static Lisp_Object
297 xfont_list_pattern (Display *display, const char *pattern,
298 Lisp_Object registry, Lisp_Object script)
300 Lisp_Object list = Qnil;
301 Lisp_Object chars = Qnil;
302 struct charset *encoding, *repertory = NULL;
303 int i, limit, num_fonts;
304 char **names;
305 /* Large enough to decode the longest XLFD (255 bytes). */
306 char buf[512];
308 if (! NILP (registry)
309 && font_registry_charsets (registry, &encoding, &repertory) < 0)
310 /* Unknown REGISTRY, not supported. */
311 return Qnil;
312 if (! NILP (script))
314 chars = assq_no_quit (script, Vscript_representative_chars);
315 if (NILP (chars))
316 /* We can't tell whether or not a font supports SCRIPT. */
317 return Qnil;
318 chars = XCDR (chars);
319 if (repertory)
321 if (! xfont_chars_supported (chars, NULL, encoding, repertory))
322 return Qnil;
323 script = Qnil;
327 block_input ();
328 x_catch_errors (display);
330 for (limit = 512; ; limit *= 2)
332 names = XListFonts (display, pattern, limit, &num_fonts);
333 if (x_had_errors_p (display))
335 /* This error is perhaps due to insufficient memory on X
336 server. Let's just ignore it. */
337 x_clear_errors (display);
338 num_fonts = 0;
339 break;
341 if (num_fonts < limit)
342 break;
343 XFreeFontNames (names);
346 if (num_fonts > 0)
348 char **indices = alloca (sizeof (char *) * num_fonts);
349 Lisp_Object *props = XVECTOR (xfont_scratch_props)->contents;
350 Lisp_Object scripts = Qnil, entity = Qnil;
352 for (i = 0; i < ASIZE (xfont_scratch_props); i++)
353 ASET (xfont_scratch_props, i, Qnil);
354 for (i = 0; i < num_fonts; i++)
355 indices[i] = names[i];
356 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
358 /* Take one or two passes over the font list. Do the second
359 pass only if we really need it, i.e., only if the first pass
360 found no fonts and skipped some scalable fonts. */
361 bool skipped_some_scalable_fonts = false;
362 for (int i_pass = 0;
363 (i_pass == 0
364 || (i_pass == 1 && NILP (list) && skipped_some_scalable_fonts));
365 i_pass++)
366 for (i = 0; i < num_fonts; i++)
368 ptrdiff_t len;
370 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
371 continue;
372 if (NILP (entity))
373 entity = font_make_entity ();
374 len = xfont_decode_coding_xlfd (indices[i], -1, buf);
375 if (font_parse_xlfd (buf, len, entity) < 0)
376 continue;
377 ASET (entity, FONT_TYPE_INDEX, Qx);
378 /* Avoid auto-scaled fonts. */
379 if (INTEGERP (AREF (entity, FONT_DPI_INDEX))
380 && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
381 && XINT (AREF (entity, FONT_DPI_INDEX)) != 0
382 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0)
383 continue;
384 /* Avoid not-allowed scalable fonts. */
385 if (NILP (Vscalable_fonts_allowed))
387 int size = 0;
389 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX)))
390 size = XINT (AREF (entity, FONT_SIZE_INDEX));
391 else if (FLOATP (AREF (entity, FONT_SIZE_INDEX)))
392 size = XFLOAT_DATA (AREF (entity, FONT_SIZE_INDEX));
393 if (size == 0 && i_pass == 0)
395 skipped_some_scalable_fonts = true;
396 continue;
399 else if (CONSP (Vscalable_fonts_allowed))
401 Lisp_Object tail;
403 for (tail = Vscalable_fonts_allowed; CONSP (tail);
404 tail = XCDR (tail))
406 Lisp_Object elt = XCAR (tail);
407 if (STRINGP (elt)
408 && (fast_c_string_match_ignore_case (elt, indices[i],
409 len)
410 >= 0))
411 break;
413 if (! CONSP (tail))
414 continue;
417 /* Avoid fonts of invalid registry. */
418 if (NILP (AREF (entity, FONT_REGISTRY_INDEX)))
419 continue;
421 /* Update encoding and repertory if necessary. */
422 if (! EQ (registry, AREF (entity, FONT_REGISTRY_INDEX)))
424 registry = AREF (entity, FONT_REGISTRY_INDEX);
425 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
426 encoding = NULL;
428 if (! encoding)
429 /* Unknown REGISTRY, not supported. */
430 continue;
431 if (repertory)
433 if (NILP (script)
434 || xfont_chars_supported (chars, NULL, encoding, repertory))
435 list = Fcons (entity, list), entity = Qnil;
436 continue;
438 if (memcmp (props, aref_addr (entity, FONT_FOUNDRY_INDEX),
439 word_size * 7)
440 || ! EQ (AREF (entity, FONT_SPACING_INDEX), props[7]))
442 vcopy (xfont_scratch_props, 0,
443 aref_addr (entity, FONT_FOUNDRY_INDEX), 7);
444 ASET (xfont_scratch_props, 7, AREF (entity, FONT_SPACING_INDEX));
445 scripts = xfont_supported_scripts (display, indices[i],
446 xfont_scratch_props,
447 encoding);
449 if (NILP (script)
450 || ! NILP (Fmemq (script, scripts)))
451 list = Fcons (entity, list), entity = Qnil;
453 XFreeFontNames (names);
456 x_uncatch_errors ();
457 unblock_input ();
459 FONT_ADD_LOG ("xfont-list", build_string (pattern), list);
460 return list;
463 static Lisp_Object
464 xfont_list (struct frame *f, Lisp_Object spec)
466 Display *display = FRAME_DISPLAY_INFO (f)->display;
467 Lisp_Object registry, list, val, extra, script;
468 int len;
469 /* Large enough to contain the longest XLFD (255 bytes) in UTF-8. */
470 char name[512];
472 extra = AREF (spec, FONT_EXTRA_INDEX);
473 if (CONSP (extra))
475 val = assq_no_quit (QCotf, extra);
476 if (! NILP (val))
477 return Qnil;
478 val = assq_no_quit (QClang, extra);
479 if (! NILP (val))
480 return Qnil;
483 registry = AREF (spec, FONT_REGISTRY_INDEX);
484 len = font_unparse_xlfd (spec, 0, name, 512);
485 if (len < 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
486 return Qnil;
488 val = assq_no_quit (QCscript, extra);
489 script = CDR (val);
490 list = xfont_list_pattern (display, name, registry, script);
491 if (NILP (list) && NILP (registry))
493 /* Try iso10646-1 */
494 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
496 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
498 strcpy (r, "iso10646-1");
499 list = xfont_list_pattern (display, name, Qiso10646_1, script);
502 if (NILP (list) && ! NILP (registry))
504 /* Try alternate registries. */
505 Lisp_Object alter;
507 if ((alter = Fassoc (SYMBOL_NAME (registry),
508 Vface_alternative_font_registry_alist,
509 Qnil),
510 CONSP (alter)))
512 /* Pointer to REGISTRY-ENCODING field. */
513 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
515 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
516 if (STRINGP (XCAR (alter))
517 && ((r - name) + SBYTES (XCAR (alter))) < 256)
519 lispstpcpy (r, XCAR (alter));
520 list = xfont_list_pattern (display, name, registry, script);
521 if (! NILP (list))
522 break;
526 if (NILP (list))
528 /* Try alias. */
529 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
530 if (CONSP (val) && STRINGP (XCDR (val)) && SBYTES (XCDR (val)) < 512)
532 memcpy (name, SDATA (XCDR (val)), SBYTES (XCDR (val)) + 1);
533 if (xfont_encode_coding_xlfd (name) < 0)
534 return Qnil;
535 list = xfont_list_pattern (display, name, registry, script);
539 return list;
542 static Lisp_Object
543 xfont_match (struct frame *f, Lisp_Object spec)
545 Display *display = FRAME_DISPLAY_INFO (f)->display;
546 Lisp_Object extra, val, entity;
547 char name[512];
548 XFontStruct *xfont;
549 unsigned long value;
551 extra = AREF (spec, FONT_EXTRA_INDEX);
552 val = assq_no_quit (QCname, extra);
553 if (! CONSP (val) || ! STRINGP (XCDR (val)))
555 if (font_unparse_xlfd (spec, 0, name, 512) < 0)
556 return Qnil;
558 else if (SBYTES (XCDR (val)) < 512)
559 memcpy (name, SDATA (XCDR (val)), SBYTES (XCDR (val)) + 1);
560 else
561 return Qnil;
562 if (xfont_encode_coding_xlfd (name) < 0)
563 return Qnil;
565 block_input ();
566 entity = Qnil;
567 xfont = XLoadQueryFont (display, name);
568 if (xfont)
570 if (XGetFontProperty (xfont, XA_FONT, &value))
572 char *s = XGetAtomName (display, (Atom) value);
574 /* If DXPC (a Differential X Protocol Compressor)
575 Ver.3.7 is running, XGetAtomName will return null
576 string. We must avoid such a name. */
577 if (*s)
579 ptrdiff_t len;
580 entity = font_make_entity ();
581 ASET (entity, FONT_TYPE_INDEX, Qx);
582 len = xfont_decode_coding_xlfd (s, -1, name);
583 if (font_parse_xlfd (name, len, entity) < 0)
584 entity = Qnil;
586 XFree (s);
588 XFreeFont (display, xfont);
590 unblock_input ();
592 FONT_ADD_LOG ("xfont-match", spec, entity);
593 return entity;
596 static Lisp_Object
597 xfont_list_family (struct frame *f)
599 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
600 char **names;
601 int num_fonts, i;
602 Lisp_Object list;
603 char *last_family UNINIT;
604 int last_len;
606 block_input ();
607 x_catch_errors (dpyinfo->display);
608 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
609 0x8000, &num_fonts);
610 if (x_had_errors_p (dpyinfo->display))
612 /* This error is perhaps due to insufficient memory on X server.
613 Let's just ignore it. */
614 x_clear_errors (dpyinfo->display);
615 num_fonts = 0;
618 list = Qnil;
619 for (i = 0, last_len = 0; i < num_fonts; i++)
621 char *p0 = names[i], *p1, buf[512];
622 Lisp_Object family;
623 int decoded_len;
625 p0++; /* skip the leading '-' */
626 while (*p0 && *p0 != '-') p0++; /* skip foundry */
627 if (! *p0)
628 continue;
629 p1 = ++p0;
630 while (*p1 && *p1 != '-') p1++; /* find the end of family */
631 if (! *p1 || p1 == p0)
632 continue;
633 if (last_len == p1 - p0
634 && memcmp (last_family, p0, last_len) == 0)
635 continue;
636 last_len = p1 - p0;
637 last_family = p0;
639 decoded_len = xfont_decode_coding_xlfd (p0, last_len, buf);
640 family = font_intern_prop (p0, decoded_len, 1);
641 if (NILP (assq_no_quit (family, list)))
642 list = Fcons (family, list);
645 XFreeFontNames (names);
646 x_uncatch_errors ();
647 unblock_input ();
649 return list;
652 static Lisp_Object
653 xfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
655 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
656 Display *display = dpyinfo->display;
657 char name[512];
658 int len;
659 unsigned long value;
660 Lisp_Object registry;
661 struct charset *encoding, *repertory;
662 Lisp_Object font_object, fullname;
663 struct font *font;
664 XFontStruct *xfont;
666 /* At first, check if we know how to encode characters for this
667 font. */
668 registry = AREF (entity, FONT_REGISTRY_INDEX);
669 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
671 FONT_ADD_LOG (" x:unknown registry", registry, Qnil);
672 return Qnil;
675 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
676 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
677 else if (pixel_size == 0)
679 if (FRAME_FONT (f))
680 pixel_size = FRAME_FONT (f)->pixel_size;
681 else
682 pixel_size = 14;
684 len = font_unparse_xlfd (entity, pixel_size, name, 512);
685 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
687 FONT_ADD_LOG (" x:unparse failed", entity, Qnil);
688 return Qnil;
691 block_input ();
692 x_catch_errors (display);
693 xfont = XLoadQueryFont (display, name);
694 if (x_had_errors_p (display))
696 /* This error is perhaps due to insufficient memory on X server.
697 Let's just ignore it. */
698 x_clear_errors (display);
699 xfont = NULL;
701 else if (! xfont)
703 /* Some version of X lists:
704 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
705 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
706 but can open only:
707 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
709 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
710 So, we try again with wildcards in RESX and RESY. */
711 Lisp_Object temp;
713 temp = copy_font_spec (entity);
714 ASET (temp, FONT_DPI_INDEX, Qnil);
715 len = font_unparse_xlfd (temp, pixel_size, name, 512);
716 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
718 FONT_ADD_LOG (" x:unparse failed", temp, Qnil);
719 return Qnil;
721 xfont = XLoadQueryFont (display, name);
722 if (x_had_errors_p (display))
724 /* This error is perhaps due to insufficient memory on X server.
725 Let's just ignore it. */
726 x_clear_errors (display);
727 xfont = NULL;
730 fullname = Qnil;
731 /* Try to get the full name of FONT. */
732 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
734 char *p0, *p;
735 int dashes = 0;
737 p0 = p = XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
738 /* Count the number of dashes in the "full name".
739 If it is too few, this isn't really the font's full name,
740 so don't use it.
741 In X11R4, the fonts did not come with their canonical names
742 stored in them. */
743 while (*p)
745 if (*p == '-')
746 dashes++;
747 p++;
750 if (dashes >= 13)
752 len = xfont_decode_coding_xlfd (p0, -1, name);
753 fullname = Fdowncase (make_string (name, len));
755 XFree (p0);
757 x_uncatch_errors ();
758 unblock_input ();
760 if (! xfont)
762 FONT_ADD_LOG (" x:open failed", build_string (name), Qnil);
763 return Qnil;
766 font_object = font_make_object (VECSIZE (struct xfont_info),
767 entity, pixel_size);
768 ASET (font_object, FONT_TYPE_INDEX, Qx);
769 if (STRINGP (fullname))
771 font_parse_xlfd (SSDATA (fullname), SBYTES (fullname), font_object);
772 ASET (font_object, FONT_NAME_INDEX, fullname);
774 else
776 char buf[512];
778 len = xfont_decode_coding_xlfd (name, -1, buf);
779 ASET (font_object, FONT_NAME_INDEX, make_string (buf, len));
781 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
782 font = XFONT_OBJECT (font_object);
783 ((struct xfont_info *) font)->xfont = xfont;
784 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
785 ((struct xfont_info *) font)->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
786 font->pixel_size = pixel_size;
787 font->driver = &xfont_driver;
788 font->encoding_charset = encoding->id;
789 font->repertory_charset = repertory ? repertory->id : -1;
790 font->ascent = xfont->ascent;
791 font->descent = xfont->descent;
792 font->height = font->ascent + font->descent;
793 font->min_width = xfont->min_bounds.width;
794 font->max_width = xfont->max_bounds.width;
795 if (xfont->min_bounds.width == xfont->max_bounds.width)
797 /* Fixed width font. */
798 font->average_width = font->space_width = xfont->min_bounds.width;
800 else
802 XCharStruct *pcm;
803 XChar2b char2b;
804 Lisp_Object val;
806 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
807 pcm = xfont_get_pcm (xfont, &char2b);
808 if (pcm)
809 font->space_width = pcm->width;
810 else
811 font->space_width = 0;
813 val = Ffont_get (font_object, QCavgwidth);
814 if (INTEGERP (val))
815 font->average_width = XINT (val) / 10;
816 if (font->average_width < 0)
817 font->average_width = - font->average_width;
818 else
820 if (font->average_width == 0
821 && encoding->ascii_compatible_p)
823 int width = font->space_width, n = pcm != NULL;
825 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
826 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
827 width += pcm->width, n++;
828 if (n > 0)
829 font->average_width = width / n;
831 if (font->average_width == 0)
832 /* No easy way other than this to get a reasonable
833 average_width. */
834 font->average_width
835 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
839 block_input ();
840 font->underline_thickness
841 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
842 ? (long) value : 0);
843 font->underline_position
844 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
845 ? (long) value : -1);
846 font->baseline_offset
847 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
848 ? (long) value : 0);
849 font->relative_compose
850 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
851 ? (long) value : 0);
852 font->default_ascent
853 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
854 ? (long) value : 0);
855 unblock_input ();
857 if (NILP (fullname))
858 fullname = AREF (font_object, FONT_NAME_INDEX);
859 font->vertical_centering
860 = (STRINGP (Vvertical_centering_font_regexp)
861 && (fast_string_match_ignore_case
862 (Vvertical_centering_font_regexp, fullname) >= 0));
864 return font_object;
867 static void
868 xfont_close (struct font *font)
870 struct x_display_info *xdi;
871 struct xfont_info *xfi = (struct xfont_info *) font;
873 /* This function may be called from GC when X connection is gone
874 (Bug#16093), and an attempt to free font resources on invalid
875 display may lead to X protocol errors or segfaults. Moreover,
876 the memory referenced by 'Display *' pointer may be reused for
877 the logically different X connection after the previous display
878 connection was closed. That's why we also check whether font's
879 ID matches the one recorded in x_display_info for this display.
880 See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=16069. */
881 if (xfi->xfont
882 && ((xdi = x_display_info_for_display (xfi->display))
883 && xfi->x_display_id == xdi->x_id))
885 block_input ();
886 XFreeFont (xfi->display, xfi->xfont);
887 unblock_input ();
888 xfi->xfont = NULL;
892 static void
893 xfont_prepare_face (struct frame *f, struct face *face)
895 block_input ();
896 XSetFont (FRAME_X_DISPLAY (f), face->gc,
897 ((struct xfont_info *) face->font)->xfont->fid);
898 unblock_input ();
901 static int
902 xfont_has_char (Lisp_Object font, int c)
904 Lisp_Object registry = AREF (font, FONT_REGISTRY_INDEX);
905 struct charset *encoding;
906 struct charset *repertory = NULL;
908 if (EQ (registry, Qiso10646_1))
910 encoding = CHARSET_FROM_ID (charset_unicode);
911 /* We use a font of `ja' and `ko' adstyle only for a character
912 in JISX0208 and KSC5601 charsets respectively. */
913 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
914 && charset_jisx0208 >= 0)
915 repertory = CHARSET_FROM_ID (charset_jisx0208);
916 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
917 && charset_ksc5601 >= 0)
918 repertory = CHARSET_FROM_ID (charset_ksc5601);
920 else if (font_registry_charsets (registry, &encoding, &repertory) < 0)
921 /* Unknown REGISTRY, not usable. */
922 return 0;
923 if (ASCII_CHAR_P (c) && encoding->ascii_compatible_p)
924 return 1;
925 if (! repertory)
926 return -1;
927 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
930 static unsigned
931 xfont_encode_char (struct font *font, int c)
933 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
934 struct charset *charset;
935 unsigned code;
936 XChar2b char2b;
938 charset = CHARSET_FROM_ID (font->encoding_charset);
939 code = ENCODE_CHAR (charset, c);
940 if (code == CHARSET_INVALID_CODE (charset))
941 return FONT_INVALID_CODE;
942 if (font->repertory_charset >= 0)
944 charset = CHARSET_FROM_ID (font->repertory_charset);
945 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
946 ? code : FONT_INVALID_CODE);
948 char2b.byte1 = code >> 8;
949 char2b.byte2 = code & 0xFF;
950 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
953 static void
954 xfont_text_extents (struct font *font, unsigned int *code,
955 int nglyphs, struct font_metrics *metrics)
957 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
958 int i, width = 0;
959 bool first;
961 for (i = 0, first = true; i < nglyphs; i++)
963 XChar2b char2b;
964 static XCharStruct *pcm;
966 if (code[i] >= 0x10000)
967 continue;
968 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
969 pcm = xfont_get_pcm (xfont, &char2b);
970 if (! pcm)
971 continue;
972 if (first)
974 metrics->lbearing = pcm->lbearing;
975 metrics->rbearing = pcm->rbearing;
976 metrics->ascent = pcm->ascent;
977 metrics->descent = pcm->descent;
978 first = false;
980 else
982 if (metrics->lbearing > width + pcm->lbearing)
983 metrics->lbearing = width + pcm->lbearing;
984 if (metrics->rbearing < width + pcm->rbearing)
985 metrics->rbearing = width + pcm->rbearing;
986 if (metrics->ascent < pcm->ascent)
987 metrics->ascent = pcm->ascent;
988 if (metrics->descent < pcm->descent)
989 metrics->descent = pcm->descent;
991 width += pcm->width;
994 metrics->width = width;
997 static int
998 xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
999 bool with_background)
1001 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
1002 int len = to - from;
1003 GC gc = s->gc;
1004 int i;
1006 if (s->gc != s->face->gc)
1008 block_input ();
1009 XSetFont (s->display, gc, xfont->fid);
1010 unblock_input ();
1013 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
1015 USE_SAFE_ALLOCA;
1016 char *str = SAFE_ALLOCA (len);
1017 for (i = 0; i < len ; i++)
1018 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
1019 block_input ();
1020 if (with_background)
1022 if (s->padding_p)
1023 for (i = 0; i < len; i++)
1024 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1025 gc, x + i, y, str + i, 1);
1026 else
1027 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1028 gc, x, y, str, len);
1030 else
1032 if (s->padding_p)
1033 for (i = 0; i < len; i++)
1034 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1035 gc, x + i, y, str + i, 1);
1036 else
1037 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1038 gc, x, y, str, len);
1040 unblock_input ();
1041 SAFE_FREE ();
1042 return s->nchars;
1045 block_input ();
1046 if (with_background)
1048 if (s->padding_p)
1049 for (i = 0; i < len; i++)
1050 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1051 gc, x + i, y, s->char2b + from + i, 1);
1052 else
1053 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1054 gc, x, y, s->char2b + from, len);
1056 else
1058 if (s->padding_p)
1059 for (i = 0; i < len; i++)
1060 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1061 gc, x + i, y, s->char2b + from + i, 1);
1062 else
1063 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_DRAWABLE (s->f),
1064 gc, x, y, s->char2b + from, len);
1066 unblock_input ();
1068 return len;
1071 static int
1072 xfont_check (struct frame *f, struct font *font)
1074 struct xfont_info *xfont = (struct xfont_info *) font;
1076 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
1081 struct font_driver const xfont_driver =
1083 .type = LISPSYM_INITIALLY (Qx),
1084 .get_cache = xfont_get_cache,
1085 .list = xfont_list,
1086 .match = xfont_match,
1087 .list_family = xfont_list_family,
1088 .open = xfont_open,
1089 .close = xfont_close,
1090 .prepare_face = xfont_prepare_face,
1091 .has_char = xfont_has_char,
1092 .encode_char = xfont_encode_char,
1093 .text_extents = xfont_text_extents,
1094 .draw = xfont_draw,
1095 .check = xfont_check,
1098 void
1099 syms_of_xfont (void)
1101 staticpro (&xfont_scripts_cache);
1102 xfont_scripts_cache = CALLN (Fmake_hash_table, QCtest, Qequal);
1103 staticpro (&xfont_scratch_props);
1104 xfont_scratch_props = Fmake_vector (make_number (8), Qnil);
1105 register_font_driver (&xfont_driver, NULL);