; doc/emacs/misc.texi (Network Security): Fix typo.
[emacs.git] / src / font.c
blob3a82e501a84db7a9636ef4ad175f1f4ef6333864
1 /* font.c -- "Font" primitives.
3 Copyright (C) 2006-2018 Free Software Foundation, Inc.
4 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
5 National Institute of Advanced Industrial Science and Technology (AIST)
6 Registration Number H13PRO009
8 This file is part of GNU Emacs.
10 GNU Emacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or (at
13 your option) any later version.
15 GNU Emacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
23 #include <config.h>
24 #include <float.h>
25 #include <stdio.h>
26 #include <stdlib.h>
28 #include <c-ctype.h>
30 #include "lisp.h"
31 #include "character.h"
32 #include "buffer.h"
33 #include "frame.h"
34 #include "window.h"
35 #include "dispextern.h"
36 #include "charset.h"
37 #include "composite.h"
38 #include "fontset.h"
39 #include "font.h"
40 #include "termhooks.h"
42 #ifdef HAVE_WINDOW_SYSTEM
43 #include TERM_HEADER
44 #endif /* HAVE_WINDOW_SYSTEM */
46 #define DEFAULT_ENCODING Qiso8859_1
48 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
49 static Lisp_Object font_style_table;
51 /* Structure used for tables mapping weight, slant, and width numeric
52 values and their names. */
54 struct table_entry
56 int numeric;
57 /* The first one is a valid name as a face attribute.
58 The second one (if any) is a typical name in XLFD field. */
59 const char *names[5];
62 /* Table of weight numeric values and their names. This table must be
63 sorted by numeric values in ascending order. */
65 static const struct table_entry weight_table[] =
67 { 0, { "thin" }},
68 { 20, { "ultra-light", "ultralight" }},
69 { 40, { "extra-light", "extralight" }},
70 { 50, { "light" }},
71 { 75, { "semi-light", "semilight", "demilight", "book" }},
72 { 100, { "normal", "medium", "regular", "unspecified" }},
73 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
74 { 200, { "bold" }},
75 { 205, { "extra-bold", "extrabold" }},
76 { 210, { "ultra-bold", "ultrabold", "black" }}
79 /* Table of slant numeric values and their names. This table must be
80 sorted by numeric values in ascending order. */
82 static const struct table_entry slant_table[] =
84 { 0, { "reverse-oblique", "ro" }},
85 { 10, { "reverse-italic", "ri" }},
86 { 100, { "normal", "r", "unspecified" }},
87 { 200, { "italic" ,"i", "ot" }},
88 { 210, { "oblique", "o" }}
91 /* Table of width numeric values and their names. This table must be
92 sorted by numeric values in ascending order. */
94 static const struct table_entry width_table[] =
96 { 50, { "ultra-condensed", "ultracondensed" }},
97 { 63, { "extra-condensed", "extracondensed" }},
98 { 75, { "condensed", "compressed", "narrow" }},
99 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
100 { 100, { "normal", "medium", "regular", "unspecified" }},
101 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
102 { 125, { "expanded" }},
103 { 150, { "extra-expanded", "extraexpanded" }},
104 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
107 /* Alist of font registry symbols and the corresponding charset
108 information. The information is retrieved from
109 Vfont_encoding_alist on demand.
111 Eash element has the form:
112 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
114 (REGISTRY . nil)
116 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
117 encodes a character code to a glyph code of a font, and
118 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
119 character is supported by a font.
121 The latter form means that the information for REGISTRY couldn't be
122 retrieved. */
123 static Lisp_Object font_charset_alist;
125 /* List of all font drivers. Each font-backend (XXXfont.c) calls
126 register_font_driver in syms_of_XXXfont to register its font-driver
127 here. */
128 static struct font_driver_list *font_driver_list;
130 #ifdef ENABLE_CHECKING
132 /* Used to catch bogus pointers in font objects. */
134 bool
135 valid_font_driver (struct font_driver const *drv)
137 Lisp_Object tail, frame;
138 struct font_driver_list *fdl;
140 for (fdl = font_driver_list; fdl; fdl = fdl->next)
141 if (fdl->driver == drv)
142 return true;
143 FOR_EACH_FRAME (tail, frame)
144 for (fdl = XFRAME (frame)->font_driver_list; fdl; fdl = fdl->next)
145 if (fdl->driver == drv)
146 return true;
147 return false;
150 #endif /* ENABLE_CHECKING */
152 /* Creators of font-related Lisp object. */
154 static Lisp_Object
155 font_make_spec (void)
157 Lisp_Object font_spec;
158 struct font_spec *spec
159 = ((struct font_spec *)
160 allocate_pseudovector (VECSIZE (struct font_spec),
161 FONT_SPEC_MAX, FONT_SPEC_MAX, PVEC_FONT));
162 XSETFONT (font_spec, spec);
163 return font_spec;
166 Lisp_Object
167 font_make_entity (void)
169 Lisp_Object font_entity;
170 struct font_entity *entity
171 = ((struct font_entity *)
172 allocate_pseudovector (VECSIZE (struct font_entity),
173 FONT_ENTITY_MAX, FONT_ENTITY_MAX, PVEC_FONT));
174 XSETFONT (font_entity, entity);
175 return font_entity;
178 /* Create a font-object whose structure size is SIZE. If ENTITY is
179 not nil, copy properties from ENTITY to the font-object. If
180 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
181 Lisp_Object
182 font_make_object (int size, Lisp_Object entity, int pixelsize)
184 Lisp_Object font_object;
185 struct font *font
186 = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX,
187 FONT_OBJECT_MAX, PVEC_FONT);
188 int i;
190 /* GC can happen before the driver is set up,
191 so avoid dangling pointer here (Bug#17771). */
192 font->driver = NULL;
193 XSETFONT (font_object, font);
195 if (! NILP (entity))
197 for (i = 1; i < FONT_SPEC_MAX; i++)
198 font->props[i] = AREF (entity, i);
199 if (! NILP (AREF (entity, FONT_EXTRA_INDEX)))
200 font->props[FONT_EXTRA_INDEX]
201 = Fcopy_alist (AREF (entity, FONT_EXTRA_INDEX));
203 if (size > 0)
204 font->props[FONT_SIZE_INDEX] = make_number (pixelsize);
205 return font_object;
208 #if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS)
210 static int font_unparse_fcname (Lisp_Object, int, char *, int);
212 /* Like above, but also set `type', `name' and `fullname' properties
213 of font-object. */
215 Lisp_Object
216 font_build_object (int vectorsize, Lisp_Object type,
217 Lisp_Object entity, double pixelsize)
219 int len;
220 char name[256];
221 Lisp_Object font_object = font_make_object (vectorsize, entity, pixelsize);
223 ASET (font_object, FONT_TYPE_INDEX, type);
224 len = font_unparse_xlfd (entity, pixelsize, name, sizeof name);
225 if (len > 0)
226 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
227 len = font_unparse_fcname (entity, pixelsize, name, sizeof name);
228 if (len > 0)
229 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
230 else
231 ASET (font_object, FONT_FULLNAME_INDEX,
232 AREF (font_object, FONT_NAME_INDEX));
233 return font_object;
236 #endif /* HAVE_XFT || HAVE_FREETYPE || HAVE_NS */
238 static int font_pixel_size (struct frame *f, Lisp_Object);
239 static Lisp_Object font_open_entity (struct frame *, Lisp_Object, int);
240 static Lisp_Object font_matching_entity (struct frame *, Lisp_Object *,
241 Lisp_Object);
242 static unsigned font_encode_char (Lisp_Object, int);
244 /* Number of registered font drivers. */
245 static int num_font_drivers;
248 /* Return a Lispy value of a font property value at STR and LEN bytes.
249 If STR is "*", return nil. If FORCE_SYMBOL, or if STR does not
250 consist entirely of one or more digits, return a symbol interned
251 from STR. Otherwise, return an integer. */
253 Lisp_Object
254 font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol)
256 ptrdiff_t i, nbytes, nchars;
257 Lisp_Object tem, name, obarray;
259 if (len == 1 && *str == '*')
260 return Qnil;
261 if (!force_symbol && 0 < len && '0' <= *str && *str <= '9')
263 for (i = 1; i < len; i++)
264 if (! ('0' <= str[i] && str[i] <= '9'))
265 break;
266 if (i == len)
268 i = 0;
269 for (EMACS_INT n = 0;
270 (n += str[i++] - '0') <= MOST_POSITIVE_FIXNUM; )
272 if (i == len)
273 return make_number (n);
274 if (INT_MULTIPLY_WRAPV (n, 10, &n))
275 break;
278 xsignal1 (Qoverflow_error, make_string (str, len));
282 /* This code is similar to intern function from lread.c. */
283 obarray = check_obarray (Vobarray);
284 parse_str_as_multibyte ((unsigned char *) str, len, &nchars, &nbytes);
285 tem = oblookup (obarray, str,
286 (len == nchars || len != nbytes) ? len : nchars, len);
287 if (SYMBOLP (tem))
288 return tem;
289 name = make_specified_string (str, nchars, len,
290 len != nchars && len == nbytes);
291 return intern_driver (name, obarray, tem);
294 /* Return a pixel size of font-spec SPEC on frame F. */
296 static int
297 font_pixel_size (struct frame *f, Lisp_Object spec)
299 #ifdef HAVE_WINDOW_SYSTEM
300 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
301 double point_size;
302 int dpi, pixel_size;
303 Lisp_Object val;
305 if (INTEGERP (size))
306 return XINT (size);
307 if (NILP (size))
308 return 0;
309 if (FRAME_WINDOW_P (f))
311 eassert (FLOATP (size));
312 point_size = XFLOAT_DATA (size);
313 val = AREF (spec, FONT_DPI_INDEX);
314 if (INTEGERP (val))
315 dpi = XINT (val);
316 else
317 dpi = FRAME_RES_Y (f);
318 pixel_size = POINT_TO_PIXEL (point_size, dpi);
319 return pixel_size;
321 #endif
322 return 1;
326 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
327 font vector. If VAL is not valid (i.e. not registered in
328 font_style_table), return -1 if NOERROR is zero, and return a
329 proper index if NOERROR is nonzero. In that case, register VAL in
330 font_style_table if VAL is a symbol, and return the closest index if
331 VAL is an integer. */
334 font_style_to_value (enum font_property_index prop, Lisp_Object val,
335 bool noerror)
337 Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
338 int len;
340 CHECK_VECTOR (table);
341 len = ASIZE (table);
343 if (SYMBOLP (val))
345 int i, j;
346 char *s;
347 Lisp_Object elt;
349 /* At first try exact match. */
350 for (i = 0; i < len; i++)
352 CHECK_VECTOR (AREF (table, i));
353 for (j = 1; j < ASIZE (AREF (table, i)); j++)
354 if (EQ (val, AREF (AREF (table, i), j)))
356 CHECK_NUMBER (AREF (AREF (table, i), 0));
357 return ((XINT (AREF (AREF (table, i), 0)) << 8)
358 | (i << 4) | (j - 1));
361 /* Try also with case-folding match. */
362 s = SSDATA (SYMBOL_NAME (val));
363 for (i = 0; i < len; i++)
364 for (j = 1; j < ASIZE (AREF (table, i)); j++)
366 elt = AREF (AREF (table, i), j);
367 if (xstrcasecmp (s, SSDATA (SYMBOL_NAME (elt))) == 0)
369 CHECK_NUMBER (AREF (AREF (table, i), 0));
370 return ((XINT (AREF (AREF (table, i), 0)) << 8)
371 | (i << 4) | (j - 1));
374 if (! noerror)
375 return -1;
376 eassert (len < 255);
377 elt = Fmake_vector (make_number (2), make_number (100));
378 ASET (elt, 1, val);
379 ASET (font_style_table, prop - FONT_WEIGHT_INDEX,
380 CALLN (Fvconcat, table, Fmake_vector (make_number (1), elt)));
381 return (100 << 8) | (i << 4);
383 else
385 int i, last_n;
386 EMACS_INT numeric = XINT (val);
388 for (i = 0, last_n = -1; i < len; i++)
390 int n;
392 CHECK_VECTOR (AREF (table, i));
393 CHECK_NUMBER (AREF (AREF (table, i), 0));
394 n = XINT (AREF (AREF (table, i), 0));
395 if (numeric == n)
396 return (n << 8) | (i << 4);
397 if (numeric < n)
399 if (! noerror)
400 return -1;
401 return ((i == 0 || n - numeric < numeric - last_n)
402 ? (n << 8) | (i << 4): (last_n << 8 | ((i - 1) << 4)));
404 last_n = n;
406 if (! noerror)
407 return -1;
408 return ((last_n << 8) | ((i - 1) << 4));
412 Lisp_Object
413 font_style_symbolic (Lisp_Object font, enum font_property_index prop,
414 bool for_face)
416 Lisp_Object val = AREF (font, prop);
417 Lisp_Object table, elt;
418 int i;
420 if (NILP (val))
421 return Qnil;
422 table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
423 CHECK_VECTOR (table);
424 i = XINT (val) & 0xFF;
425 eassert (((i >> 4) & 0xF) < ASIZE (table));
426 elt = AREF (table, ((i >> 4) & 0xF));
427 CHECK_VECTOR (elt);
428 eassert ((i & 0xF) + 1 < ASIZE (elt));
429 elt = (for_face ? AREF (elt, 1) : AREF (elt, (i & 0xF) + 1));
430 CHECK_SYMBOL (elt);
431 return elt;
434 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
435 FONTNAME. ENCODING is a charset symbol that specifies the encoding
436 of the font. REPERTORY is a charset symbol or nil. */
438 Lisp_Object
439 find_font_encoding (Lisp_Object fontname)
441 Lisp_Object tail, elt;
443 for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
445 elt = XCAR (tail);
446 if (CONSP (elt)
447 && STRINGP (XCAR (elt))
448 && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
449 && (SYMBOLP (XCDR (elt))
450 ? CHARSETP (XCDR (elt))
451 : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
452 return (XCDR (elt));
454 return Qnil;
457 /* Return encoding charset and repertory charset for REGISTRY in
458 ENCODING and REPERTORY correspondingly. If correct information for
459 REGISTRY is available, return 0. Otherwise return -1. */
462 font_registry_charsets (Lisp_Object registry, struct charset **encoding, struct charset **repertory)
464 Lisp_Object val;
465 int encoding_id, repertory_id;
467 val = Fassoc_string (registry, font_charset_alist, Qt);
468 if (! NILP (val))
470 val = XCDR (val);
471 if (NILP (val))
472 return -1;
473 encoding_id = XINT (XCAR (val));
474 repertory_id = XINT (XCDR (val));
476 else
478 val = find_font_encoding (SYMBOL_NAME (registry));
479 if (SYMBOLP (val) && CHARSETP (val))
481 encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val));
483 else if (CONSP (val))
485 if (! CHARSETP (XCAR (val)))
486 goto invalid_entry;
487 encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val)));
488 if (NILP (XCDR (val)))
489 repertory_id = -1;
490 else
492 if (! CHARSETP (XCDR (val)))
493 goto invalid_entry;
494 repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val)));
497 else
498 goto invalid_entry;
499 val = Fcons (make_number (encoding_id), make_number (repertory_id));
500 font_charset_alist
501 = nconc2 (font_charset_alist, list1 (Fcons (registry, val)));
504 if (encoding)
505 *encoding = CHARSET_FROM_ID (encoding_id);
506 if (repertory)
507 *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL;
508 return 0;
510 invalid_entry:
511 font_charset_alist
512 = nconc2 (font_charset_alist, list1 (Fcons (registry, Qnil)));
513 return -1;
517 /* Font property value validators. See the comment of
518 font_property_table for the meaning of the arguments. */
520 static Lisp_Object font_prop_validate (int, Lisp_Object, Lisp_Object);
521 static Lisp_Object font_prop_validate_symbol (Lisp_Object, Lisp_Object);
522 static Lisp_Object font_prop_validate_style (Lisp_Object, Lisp_Object);
523 static Lisp_Object font_prop_validate_non_neg (Lisp_Object, Lisp_Object);
524 static Lisp_Object font_prop_validate_spacing (Lisp_Object, Lisp_Object);
525 static int get_font_prop_index (Lisp_Object);
527 static Lisp_Object
528 font_prop_validate_symbol (Lisp_Object prop, Lisp_Object val)
530 if (STRINGP (val))
531 val = Fintern (val, Qnil);
532 if (! SYMBOLP (val))
533 val = Qerror;
534 else if (EQ (prop, QCregistry))
535 val = Fintern (Fdowncase (SYMBOL_NAME (val)), Qnil);
536 return val;
540 static Lisp_Object
541 font_prop_validate_style (Lisp_Object style, Lisp_Object val)
543 enum font_property_index prop = (EQ (style, QCweight) ? FONT_WEIGHT_INDEX
544 : EQ (style, QCslant) ? FONT_SLANT_INDEX
545 : FONT_WIDTH_INDEX);
546 if (INTEGERP (val))
548 EMACS_INT n = XINT (val);
549 CHECK_VECTOR (AREF (font_style_table, prop - FONT_WEIGHT_INDEX));
550 if (((n >> 4) & 0xF)
551 >= ASIZE (AREF (font_style_table, prop - FONT_WEIGHT_INDEX)))
552 val = Qerror;
553 else
555 Lisp_Object elt = AREF (AREF (font_style_table, prop - FONT_WEIGHT_INDEX), (n >> 4) & 0xF);
557 CHECK_VECTOR (elt);
558 if ((n & 0xF) + 1 >= ASIZE (elt))
559 val = Qerror;
560 else
562 CHECK_NUMBER (AREF (elt, 0));
563 if (XINT (AREF (elt, 0)) != (n >> 8))
564 val = Qerror;
568 else if (SYMBOLP (val))
570 int n = font_style_to_value (prop, val, 0);
572 val = n >= 0 ? make_number (n) : Qerror;
574 else
575 val = Qerror;
576 return val;
579 static Lisp_Object
580 font_prop_validate_non_neg (Lisp_Object prop, Lisp_Object val)
582 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
583 ? val : Qerror);
586 static Lisp_Object
587 font_prop_validate_spacing (Lisp_Object prop, Lisp_Object val)
589 if (NILP (val) || (NATNUMP (val) && XINT (val) <= FONT_SPACING_CHARCELL))
590 return val;
591 if (SYMBOLP (val) && SBYTES (SYMBOL_NAME (val)) == 1)
593 char spacing = SDATA (SYMBOL_NAME (val))[0];
595 if (spacing == 'c' || spacing == 'C')
596 return make_number (FONT_SPACING_CHARCELL);
597 if (spacing == 'm' || spacing == 'M')
598 return make_number (FONT_SPACING_MONO);
599 if (spacing == 'p' || spacing == 'P')
600 return make_number (FONT_SPACING_PROPORTIONAL);
601 if (spacing == 'd' || spacing == 'D')
602 return make_number (FONT_SPACING_DUAL);
604 return Qerror;
607 static Lisp_Object
608 font_prop_validate_otf (Lisp_Object prop, Lisp_Object val)
610 Lisp_Object tail, tmp;
611 int i;
613 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
614 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
615 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
616 if (! CONSP (val))
617 return Qerror;
618 if (! SYMBOLP (XCAR (val)))
619 return Qerror;
620 tail = XCDR (val);
621 if (NILP (tail))
622 return val;
623 if (! CONSP (tail) || ! SYMBOLP (XCAR (val)))
624 return Qerror;
625 for (i = 0; i < 2; i++)
627 tail = XCDR (tail);
628 if (NILP (tail))
629 return val;
630 if (! CONSP (tail))
631 return Qerror;
632 for (tmp = XCAR (tail); CONSP (tmp); tmp = XCDR (tmp))
633 if (! SYMBOLP (XCAR (tmp)))
634 return Qerror;
635 if (! NILP (tmp))
636 return Qerror;
638 return val;
641 /* Structure of known font property keys and validator of the
642 values. */
643 static const struct
645 /* Index of the key symbol. */
646 int key;
647 /* Function to validate PROP's value VAL, or NULL if any value is
648 ok. The value is VAL or its regularized value if VAL is valid,
649 and Qerror if not. */
650 Lisp_Object (*validator) (Lisp_Object prop, Lisp_Object val);
651 } font_property_table[] =
652 { { SYMBOL_INDEX (QCtype), font_prop_validate_symbol },
653 { SYMBOL_INDEX (QCfoundry), font_prop_validate_symbol },
654 { SYMBOL_INDEX (QCfamily), font_prop_validate_symbol },
655 { SYMBOL_INDEX (QCadstyle), font_prop_validate_symbol },
656 { SYMBOL_INDEX (QCregistry), font_prop_validate_symbol },
657 { SYMBOL_INDEX (QCweight), font_prop_validate_style },
658 { SYMBOL_INDEX (QCslant), font_prop_validate_style },
659 { SYMBOL_INDEX (QCwidth), font_prop_validate_style },
660 { SYMBOL_INDEX (QCsize), font_prop_validate_non_neg },
661 { SYMBOL_INDEX (QCdpi), font_prop_validate_non_neg },
662 { SYMBOL_INDEX (QCspacing), font_prop_validate_spacing },
663 { SYMBOL_INDEX (QCavgwidth), font_prop_validate_non_neg },
664 /* The order of the above entries must match with enum
665 font_property_index. */
666 { SYMBOL_INDEX (QClang), font_prop_validate_symbol },
667 { SYMBOL_INDEX (QCscript), font_prop_validate_symbol },
668 { SYMBOL_INDEX (QCotf), font_prop_validate_otf }
671 /* Return an index number of font property KEY or -1 if KEY is not an
672 already known property. */
674 static int
675 get_font_prop_index (Lisp_Object key)
677 int i;
679 for (i = 0; i < ARRAYELTS (font_property_table); i++)
680 if (EQ (key, builtin_lisp_symbol (font_property_table[i].key)))
681 return i;
682 return -1;
685 /* Validate the font property. The property key is specified by the
686 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
687 signal an error. The value is VAL or the regularized one. */
689 static Lisp_Object
690 font_prop_validate (int idx, Lisp_Object prop, Lisp_Object val)
692 Lisp_Object validated;
694 if (NILP (val))
695 return val;
696 if (NILP (prop))
697 prop = builtin_lisp_symbol (font_property_table[idx].key);
698 else
700 idx = get_font_prop_index (prop);
701 if (idx < 0)
702 return val;
704 validated = (font_property_table[idx].validator) (prop, val);
705 if (EQ (validated, Qerror))
706 signal_error ("invalid font property", Fcons (prop, val));
707 return validated;
711 /* Store VAL as a value of extra font property PROP in FONT while
712 keeping the sorting order. Don't check the validity of VAL. */
714 Lisp_Object
715 font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
717 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
718 Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
720 if (NILP (slot))
722 Lisp_Object prev = Qnil;
724 while (CONSP (extra)
725 && NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
726 prev = extra, extra = XCDR (extra);
728 if (NILP (prev))
729 ASET (font, FONT_EXTRA_INDEX, Fcons (Fcons (prop, val), extra));
730 else
731 XSETCDR (prev, Fcons (Fcons (prop, val), extra));
733 return val;
735 XSETCDR (slot, val);
736 if (NILP (val))
737 ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra));
738 return val;
742 /* Font name parser and unparser. */
744 static int parse_matrix (const char *);
745 static int font_expand_wildcards (Lisp_Object *, int);
746 static int font_parse_name (char *, ptrdiff_t, Lisp_Object);
748 /* An enumerator for each field of an XLFD font name. */
749 enum xlfd_field_index
751 XLFD_FOUNDRY_INDEX,
752 XLFD_FAMILY_INDEX,
753 XLFD_WEIGHT_INDEX,
754 XLFD_SLANT_INDEX,
755 XLFD_SWIDTH_INDEX,
756 XLFD_ADSTYLE_INDEX,
757 XLFD_PIXEL_INDEX,
758 XLFD_POINT_INDEX,
759 XLFD_RESX_INDEX,
760 XLFD_RESY_INDEX,
761 XLFD_SPACING_INDEX,
762 XLFD_AVGWIDTH_INDEX,
763 XLFD_REGISTRY_INDEX,
764 XLFD_ENCODING_INDEX,
765 XLFD_LAST_INDEX
768 /* An enumerator for mask bit corresponding to each XLFD field. */
769 enum xlfd_field_mask
771 XLFD_FOUNDRY_MASK = 0x0001,
772 XLFD_FAMILY_MASK = 0x0002,
773 XLFD_WEIGHT_MASK = 0x0004,
774 XLFD_SLANT_MASK = 0x0008,
775 XLFD_SWIDTH_MASK = 0x0010,
776 XLFD_ADSTYLE_MASK = 0x0020,
777 XLFD_PIXEL_MASK = 0x0040,
778 XLFD_POINT_MASK = 0x0080,
779 XLFD_RESX_MASK = 0x0100,
780 XLFD_RESY_MASK = 0x0200,
781 XLFD_SPACING_MASK = 0x0400,
782 XLFD_AVGWIDTH_MASK = 0x0800,
783 XLFD_REGISTRY_MASK = 0x1000,
784 XLFD_ENCODING_MASK = 0x2000
788 /* Parse P pointing to the pixel/point size field of the form
789 `[A B C D]' which specifies a transformation matrix:
791 A B 0
792 C D 0
793 0 0 1
795 by which all glyphs of the font are transformed. The spec says
796 that scalar value N for the pixel/point size is equivalent to:
797 A = N * resx/resy, B = C = 0, D = N.
799 Return the scalar value N if the form is valid. Otherwise return
800 -1. */
802 static int
803 parse_matrix (const char *p)
805 double matrix[4];
806 char *end;
807 int i;
809 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
811 if (*p == '~')
812 matrix[i] = - strtod (p + 1, &end);
813 else
814 matrix[i] = strtod (p, &end);
815 p = end;
817 return (i == 4 ? (int) matrix[3] : -1);
820 /* Expand a wildcard field in FIELD (the first N fields are filled) to
821 multiple fields to fill in all 14 XLFD fields while restricting a
822 field position by its contents. */
824 static int
825 font_expand_wildcards (Lisp_Object *field, int n)
827 /* Copy of FIELD. */
828 Lisp_Object tmp[XLFD_LAST_INDEX];
829 /* Array of information about where this element can go. Nth
830 element is for Nth element of FIELD. */
831 struct {
832 /* Minimum possible field. */
833 int from;
834 /* Maximum possible field. */
835 int to;
836 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
837 int mask;
838 } range[XLFD_LAST_INDEX];
839 int i, j;
840 int range_from, range_to;
841 unsigned range_mask;
843 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
844 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
845 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
846 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
847 | XLFD_AVGWIDTH_MASK)
848 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
850 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
851 field. The value is shifted to left one bit by one in the
852 following loop. */
853 for (i = 0, range_mask = 0; i <= 14 - n; i++)
854 range_mask = (range_mask << 1) | 1;
856 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
857 position-based restriction for FIELD[I]. */
858 for (i = 0, range_from = 0, range_to = 14 - n; i < n;
859 i++, range_from++, range_to++, range_mask <<= 1)
861 Lisp_Object val = field[i];
863 tmp[i] = val;
864 if (NILP (val))
866 /* Wildcard. */
867 range[i].from = range_from;
868 range[i].to = range_to;
869 range[i].mask = range_mask;
871 else
873 /* The triplet FROM, TO, and MASK is a value-based
874 restriction for FIELD[I]. */
875 int from, to;
876 unsigned mask;
878 if (INTEGERP (val))
880 EMACS_INT numeric = XINT (val);
882 if (i + 1 == n)
883 from = to = XLFD_ENCODING_INDEX,
884 mask = XLFD_ENCODING_MASK;
885 else if (numeric == 0)
886 from = XLFD_PIXEL_INDEX, to = XLFD_AVGWIDTH_INDEX,
887 mask = XLFD_PIXEL_MASK | XLFD_LARGENUM_MASK;
888 else if (numeric <= 48)
889 from = to = XLFD_PIXEL_INDEX,
890 mask = XLFD_PIXEL_MASK;
891 else
892 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
893 mask = XLFD_LARGENUM_MASK;
895 else if (SBYTES (SYMBOL_NAME (val)) == 0)
896 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
897 mask = XLFD_NULL_MASK;
898 else if (i == 0)
899 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
900 else if (i + 1 == n)
902 Lisp_Object name = SYMBOL_NAME (val);
904 if (SDATA (name)[SBYTES (name) - 1] == '*')
905 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
906 mask = XLFD_REGENC_MASK;
907 else
908 from = to = XLFD_ENCODING_INDEX,
909 mask = XLFD_ENCODING_MASK;
911 else if (range_from <= XLFD_WEIGHT_INDEX
912 && range_to >= XLFD_WEIGHT_INDEX
913 && FONT_WEIGHT_NAME_NUMERIC (val) >= 0)
914 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
915 else if (range_from <= XLFD_SLANT_INDEX
916 && range_to >= XLFD_SLANT_INDEX
917 && FONT_SLANT_NAME_NUMERIC (val) >= 0)
918 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
919 else if (range_from <= XLFD_SWIDTH_INDEX
920 && range_to >= XLFD_SWIDTH_INDEX
921 && FONT_WIDTH_NAME_NUMERIC (val) >= 0)
922 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
923 else
925 if (EQ (val, Qc) || EQ (val, Qm) || EQ (val, Qp) || EQ (val, Qd))
926 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
927 else
928 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
929 mask = XLFD_SYMBOL_MASK;
932 /* Merge position-based and value-based restrictions. */
933 mask &= range_mask;
934 while (from < range_from)
935 mask &= ~(1 << from++);
936 while (from < 14 && ! (mask & (1 << from)))
937 from++;
938 while (to > range_to)
939 mask &= ~(1 << to--);
940 while (to >= 0 && ! (mask & (1 << to)))
941 to--;
942 if (from > to)
943 return -1;
944 range[i].from = from;
945 range[i].to = to;
946 range[i].mask = mask;
948 if (from > range_from || to < range_to)
950 /* The range is narrowed by value-based restrictions.
951 Reflect it to the other fields. */
953 /* Following fields should be after FROM. */
954 range_from = from;
955 /* Preceding fields should be before TO. */
956 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
958 /* Check FROM for non-wildcard field. */
959 if (! NILP (tmp[j]) && range[j].from < from)
961 while (range[j].from < from)
962 range[j].mask &= ~(1 << range[j].from++);
963 while (from < 14 && ! (range[j].mask & (1 << from)))
964 from++;
965 range[j].from = from;
967 else
968 from = range[j].from;
969 if (range[j].to > to)
971 while (range[j].to > to)
972 range[j].mask &= ~(1 << range[j].to--);
973 while (to >= 0 && ! (range[j].mask & (1 << to)))
974 to--;
975 range[j].to = to;
977 else
978 to = range[j].to;
979 if (from > to)
980 return -1;
986 /* Decide all fields from restrictions in RANGE. */
987 for (i = j = 0; i < n ; i++)
989 if (j < range[i].from)
991 if (i == 0 || ! NILP (tmp[i - 1]))
992 /* None of TMP[X] corresponds to Jth field. */
993 return -1;
994 memclear (field + j, (range[i].from - j) * word_size);
995 j = range[i].from;
997 field[j++] = tmp[i];
999 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
1000 return -1;
1001 memclear (field + j, (XLFD_LAST_INDEX - j) * word_size);
1002 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
1003 field[XLFD_ENCODING_INDEX]
1004 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
1005 return 0;
1009 /* Parse NAME (null terminated) as XLFD and store information in FONT
1010 (font-spec or font-entity). Size property of FONT is set as
1011 follows:
1012 specified XLFD fields FONT property
1013 --------------------- -------------
1014 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
1015 POINT_SIZE and RESY calculated pixel size (Lisp integer)
1016 POINT_SIZE POINT_SIZE/10 (Lisp float)
1018 If NAME is successfully parsed, return 0. Otherwise return -1.
1020 FONT is usually a font-spec, but when this function is called from
1021 X font backend driver, it is a font-entity. In that case, NAME is
1022 a fully specified XLFD. */
1025 font_parse_xlfd (char *name, ptrdiff_t len, Lisp_Object font)
1027 int i, j, n;
1028 char *f[XLFD_LAST_INDEX + 1];
1029 Lisp_Object val;
1030 char *p;
1032 if (len > 255 || !len)
1033 /* Maximum XLFD name length is 255. */
1034 return -1;
1035 /* Accept "*-.." as a fully specified XLFD. */
1036 if (name[0] == '*' && (len == 1 || name[1] == '-'))
1037 i = 1, f[XLFD_FOUNDRY_INDEX] = name;
1038 else
1039 i = 0;
1040 for (p = name + i; *p; p++)
1041 if (*p == '-')
1043 f[i++] = p + 1;
1044 if (i == XLFD_LAST_INDEX)
1045 break;
1047 f[i] = name + len;
1049 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1050 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1052 if (i == XLFD_LAST_INDEX)
1054 /* Fully specified XLFD. */
1055 int pixel_size;
1057 ASET (font, FONT_FOUNDRY_INDEX, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX));
1058 ASET (font, FONT_FAMILY_INDEX, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX));
1059 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1060 i <= XLFD_SWIDTH_INDEX; i++, j++)
1062 val = INTERN_FIELD_SYM (i);
1063 if (! NILP (val))
1065 if ((n = font_style_to_value (j, INTERN_FIELD_SYM (i), 0)) < 0)
1066 return -1;
1067 ASET (font, j, make_number (n));
1070 ASET (font, FONT_ADSTYLE_INDEX, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX));
1071 if (strcmp (f[XLFD_REGISTRY_INDEX], "*-*") == 0)
1072 ASET (font, FONT_REGISTRY_INDEX, Qnil);
1073 else
1074 ASET (font, FONT_REGISTRY_INDEX,
1075 font_intern_prop (f[XLFD_REGISTRY_INDEX],
1076 f[XLFD_LAST_INDEX] - f[XLFD_REGISTRY_INDEX],
1077 1));
1078 p = f[XLFD_PIXEL_INDEX];
1079 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
1080 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
1081 else
1083 val = INTERN_FIELD (XLFD_PIXEL_INDEX);
1084 if (INTEGERP (val))
1085 ASET (font, FONT_SIZE_INDEX, val);
1086 else if (FONT_ENTITY_P (font))
1087 return -1;
1088 else
1090 double point_size = -1;
1092 eassert (FONT_SPEC_P (font));
1093 p = f[XLFD_POINT_INDEX];
1094 if (*p == '[')
1095 point_size = parse_matrix (p);
1096 else if (c_isdigit (*p))
1097 point_size = atoi (p), point_size /= 10;
1098 if (point_size >= 0)
1099 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1103 val = INTERN_FIELD (XLFD_RESY_INDEX);
1104 if (! NILP (val) && ! INTEGERP (val))
1105 return -1;
1106 ASET (font, FONT_DPI_INDEX, val);
1107 val = INTERN_FIELD (XLFD_SPACING_INDEX);
1108 if (! NILP (val))
1110 val = font_prop_validate_spacing (QCspacing, val);
1111 if (! INTEGERP (val))
1112 return -1;
1113 ASET (font, FONT_SPACING_INDEX, val);
1115 p = f[XLFD_AVGWIDTH_INDEX];
1116 if (*p == '~')
1117 p++;
1118 val = font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p, 0);
1119 if (! NILP (val) && ! INTEGERP (val))
1120 return -1;
1121 ASET (font, FONT_AVGWIDTH_INDEX, val);
1123 else
1125 bool wild_card_found = 0;
1126 Lisp_Object prop[XLFD_LAST_INDEX];
1128 if (FONT_ENTITY_P (font))
1129 return -1;
1130 for (j = 0; j < i; j++)
1132 if (*f[j] == '*')
1134 if (f[j][1] && f[j][1] != '-')
1135 return -1;
1136 prop[j] = Qnil;
1137 wild_card_found = 1;
1139 else if (j + 1 < i)
1140 prop[j] = INTERN_FIELD (j);
1141 else
1142 prop[j] = font_intern_prop (f[j], f[i] - f[j], 0);
1144 if (! wild_card_found)
1145 return -1;
1146 if (font_expand_wildcards (prop, i) < 0)
1147 return -1;
1149 ASET (font, FONT_FOUNDRY_INDEX, prop[XLFD_FOUNDRY_INDEX]);
1150 ASET (font, FONT_FAMILY_INDEX, prop[XLFD_FAMILY_INDEX]);
1151 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1152 i <= XLFD_SWIDTH_INDEX; i++, j++)
1153 if (! NILP (prop[i]))
1155 if ((n = font_style_to_value (j, prop[i], 1)) < 0)
1156 return -1;
1157 ASET (font, j, make_number (n));
1159 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1160 val = prop[XLFD_REGISTRY_INDEX];
1161 if (NILP (val))
1163 val = prop[XLFD_ENCODING_INDEX];
1164 if (! NILP (val))
1166 AUTO_STRING (star_dash, "*-");
1167 val = concat2 (star_dash, SYMBOL_NAME (val));
1170 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1172 AUTO_STRING (dash_star, "-*");
1173 val = concat2 (SYMBOL_NAME (val), dash_star);
1175 else
1177 AUTO_STRING (dash, "-");
1178 val = concat3 (SYMBOL_NAME (val), dash,
1179 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX]));
1181 if (! NILP (val))
1182 ASET (font, FONT_REGISTRY_INDEX, Fintern (val, Qnil));
1184 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1185 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
1186 else if (INTEGERP (prop[XLFD_POINT_INDEX]))
1188 double point_size = XINT (prop[XLFD_POINT_INDEX]);
1190 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1193 if (INTEGERP (prop[XLFD_RESX_INDEX]))
1194 ASET (font, FONT_DPI_INDEX, prop[XLFD_RESY_INDEX]);
1195 if (! NILP (prop[XLFD_SPACING_INDEX]))
1197 val = font_prop_validate_spacing (QCspacing,
1198 prop[XLFD_SPACING_INDEX]);
1199 if (! INTEGERP (val))
1200 return -1;
1201 ASET (font, FONT_SPACING_INDEX, val);
1203 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1204 ASET (font, FONT_AVGWIDTH_INDEX, prop[XLFD_AVGWIDTH_INDEX]);
1207 return 0;
1210 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1211 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1212 0, use PIXEL_SIZE instead. */
1214 ptrdiff_t
1215 font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
1217 char *p;
1218 const char *f[XLFD_REGISTRY_INDEX + 1];
1219 Lisp_Object val;
1220 int i, j, len;
1222 eassert (FONTP (font));
1224 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
1225 i++, j++)
1227 if (i == FONT_ADSTYLE_INDEX)
1228 j = XLFD_ADSTYLE_INDEX;
1229 else if (i == FONT_REGISTRY_INDEX)
1230 j = XLFD_REGISTRY_INDEX;
1231 val = AREF (font, i);
1232 if (NILP (val))
1234 if (j == XLFD_REGISTRY_INDEX)
1235 f[j] = "*-*";
1236 else
1237 f[j] = "*";
1239 else
1241 if (SYMBOLP (val))
1242 val = SYMBOL_NAME (val);
1243 if (j == XLFD_REGISTRY_INDEX
1244 && ! strchr (SSDATA (val), '-'))
1246 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1247 ptrdiff_t alloc = SBYTES (val) + 4;
1248 if (nbytes <= alloc)
1249 return -1;
1250 f[j] = p = alloca (alloc);
1251 sprintf (p, "%s%s-*", SDATA (val),
1252 &"*"[SDATA (val)[SBYTES (val) - 1] == '*']);
1254 else
1255 f[j] = SSDATA (val);
1259 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1260 i++, j++)
1262 val = font_style_symbolic (font, i, 0);
1263 if (NILP (val))
1264 f[j] = "*";
1265 else
1267 int c, k, l;
1268 ptrdiff_t alloc;
1270 val = SYMBOL_NAME (val);
1271 alloc = SBYTES (val) + 1;
1272 if (nbytes <= alloc)
1273 return -1;
1274 f[j] = p = alloca (alloc);
1275 /* Copy the name while excluding '-', '?', ',', and '"'. */
1276 for (k = l = 0; k < alloc; k++)
1278 c = SREF (val, k);
1279 if (c != '-' && c != '?' && c != ',' && c != '"')
1280 p[l++] = c;
1285 val = AREF (font, FONT_SIZE_INDEX);
1286 eassert (NUMBERP (val) || NILP (val));
1287 char font_size_index_buf[sizeof "-*"
1288 + max (INT_STRLEN_BOUND (EMACS_INT),
1289 1 + DBL_MAX_10_EXP + 1)];
1290 if (INTEGERP (val))
1292 EMACS_INT v = XINT (val);
1293 if (v <= 0)
1294 v = pixel_size;
1295 if (v > 0)
1297 f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
1298 sprintf (p, "%"pI"d-*", v);
1300 else
1301 f[XLFD_PIXEL_INDEX] = "*-*";
1303 else if (FLOATP (val))
1305 double v = XFLOAT_DATA (val) * 10;
1306 f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
1307 sprintf (p, "*-%.0f", v);
1309 else
1310 f[XLFD_PIXEL_INDEX] = "*-*";
1312 char dpi_index_buf[sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT)];
1313 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1315 EMACS_INT v = XINT (AREF (font, FONT_DPI_INDEX));
1316 f[XLFD_RESX_INDEX] = p = dpi_index_buf;
1317 sprintf (p, "%"pI"d-%"pI"d", v, v);
1319 else
1320 f[XLFD_RESX_INDEX] = "*-*";
1322 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1324 EMACS_INT spacing = XINT (AREF (font, FONT_SPACING_INDEX));
1326 f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
1327 : spacing <= FONT_SPACING_DUAL ? "d"
1328 : spacing <= FONT_SPACING_MONO ? "m"
1329 : "c");
1331 else
1332 f[XLFD_SPACING_INDEX] = "*";
1334 char avgwidth_index_buf[INT_BUFSIZE_BOUND (EMACS_INT)];
1335 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1337 f[XLFD_AVGWIDTH_INDEX] = p = avgwidth_index_buf;
1338 sprintf (p, "%"pI"d", XINT (AREF (font, FONT_AVGWIDTH_INDEX)));
1340 else
1341 f[XLFD_AVGWIDTH_INDEX] = "*";
1343 len = snprintf (name, nbytes, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1344 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1345 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1346 f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
1347 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
1348 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
1349 f[XLFD_REGISTRY_INDEX]);
1350 return len < nbytes ? len : -1;
1353 /* Parse NAME (null terminated) and store information in FONT
1354 (font-spec or font-entity). NAME is supplied in either the
1355 Fontconfig or GTK font name format. If NAME is successfully
1356 parsed, return 0. Otherwise return -1.
1358 The fontconfig format is
1360 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1362 The GTK format is
1364 FAMILY [PROPS...] [SIZE]
1366 This function tries to guess which format it is. */
1368 static int
1369 font_parse_fcname (char *name, ptrdiff_t len, Lisp_Object font)
1371 char *p, *q;
1372 char *size_beg = NULL, *size_end = NULL;
1373 char *props_beg = NULL, *family_end = NULL;
1375 if (len == 0)
1376 return -1;
1378 for (p = name; *p; p++)
1380 if (*p == '\\' && p[1])
1381 p++;
1382 else if (*p == ':')
1384 props_beg = family_end = p;
1385 break;
1387 else if (*p == '-')
1389 bool decimal = 0, size_found = 1;
1390 for (q = p + 1; *q && *q != ':'; q++)
1391 if (! c_isdigit (*q))
1393 if (*q != '.' || decimal)
1395 size_found = 0;
1396 break;
1398 decimal = 1;
1400 if (size_found)
1402 family_end = p;
1403 size_beg = p + 1;
1404 size_end = q;
1405 break;
1410 if (family_end)
1412 Lisp_Object extra_props = Qnil;
1414 /* A fontconfig name with size and/or property data. */
1415 if (family_end > name)
1417 Lisp_Object family;
1418 family = font_intern_prop (name, family_end - name, 1);
1419 ASET (font, FONT_FAMILY_INDEX, family);
1421 if (size_beg)
1423 double point_size = strtod (size_beg, &size_end);
1424 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1425 if (*size_end == ':' && size_end[1])
1426 props_beg = size_end;
1428 if (props_beg)
1430 /* Now parse ":KEY=VAL" patterns. */
1431 Lisp_Object val;
1433 for (p = props_beg; *p; p = q)
1435 for (q = p + 1; *q && *q != '=' && *q != ':'; q++);
1436 if (*q != '=')
1438 /* Must be an enumerated value. */
1439 ptrdiff_t word_len;
1440 p = p + 1;
1441 word_len = q - p;
1442 val = font_intern_prop (p, q - p, 1);
1444 #define PROP_MATCH(STR) (word_len == strlen (STR) \
1445 && memcmp (p, STR, strlen (STR)) == 0)
1447 if (PROP_MATCH ("light")
1448 || PROP_MATCH ("medium")
1449 || PROP_MATCH ("demibold")
1450 || PROP_MATCH ("bold")
1451 || PROP_MATCH ("black"))
1452 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
1453 else if (PROP_MATCH ("roman")
1454 || PROP_MATCH ("italic")
1455 || PROP_MATCH ("oblique"))
1456 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
1457 else if (PROP_MATCH ("charcell"))
1458 ASET (font, FONT_SPACING_INDEX,
1459 make_number (FONT_SPACING_CHARCELL));
1460 else if (PROP_MATCH ("mono"))
1461 ASET (font, FONT_SPACING_INDEX,
1462 make_number (FONT_SPACING_MONO));
1463 else if (PROP_MATCH ("proportional"))
1464 ASET (font, FONT_SPACING_INDEX,
1465 make_number (FONT_SPACING_PROPORTIONAL));
1466 #undef PROP_MATCH
1468 else
1470 /* KEY=VAL pairs */
1471 Lisp_Object key;
1472 int prop;
1474 if (q - p == 10 && memcmp (p + 1, "pixelsize", 9) == 0)
1475 prop = FONT_SIZE_INDEX;
1476 else
1478 key = font_intern_prop (p, q - p, 1);
1479 prop = get_font_prop_index (key);
1482 p = q + 1;
1483 for (q = p; *q && *q != ':'; q++);
1484 val = font_intern_prop (p, q - p, 0);
1486 if (prop >= FONT_FOUNDRY_INDEX
1487 && prop < FONT_EXTRA_INDEX)
1488 ASET (font, prop, font_prop_validate (prop, Qnil, val));
1489 else
1491 extra_props = nconc2 (extra_props,
1492 list1 (Fcons (key, val)));
1495 p = q;
1499 if (! NILP (extra_props))
1501 struct font_driver_list *driver_list = font_driver_list;
1502 for ( ; driver_list; driver_list = driver_list->next)
1503 if (driver_list->driver->filter_properties)
1504 (*driver_list->driver->filter_properties) (font, extra_props);
1508 else
1510 /* Either a fontconfig-style name with no size and property
1511 data, or a GTK-style name. */
1512 Lisp_Object weight = Qnil, slant = Qnil;
1513 Lisp_Object width = Qnil, size = Qnil;
1514 char *word_start;
1515 ptrdiff_t word_len;
1517 /* Scan backwards from the end, looking for a size. */
1518 for (p = name + len - 1; p >= name; p--)
1519 if (!c_isdigit (*p))
1520 break;
1522 if ((p < name + len - 1) && ((p + 1 == name) || *p == ' '))
1523 /* Found a font size. */
1524 size = make_float (strtod (p + 1, NULL));
1525 else
1526 p = name + len;
1528 /* Now P points to the termination of the string, sans size.
1529 Scan backwards, looking for font properties. */
1530 for (; p > name; p = q)
1532 for (q = p - 1; q >= name; q--)
1534 if (q > name && *(q-1) == '\\')
1535 --q; /* Skip quoting backslashes. */
1536 else if (*q == ' ')
1537 break;
1540 word_start = q + 1;
1541 word_len = p - word_start;
1543 #define PROP_MATCH(STR) \
1544 (word_len == strlen (STR) \
1545 && memcmp (word_start, STR, strlen (STR)) == 0)
1546 #define PROP_SAVE(VAR, STR) \
1547 (VAR = NILP (VAR) ? font_intern_prop (STR, strlen (STR), 1) : VAR)
1549 if (PROP_MATCH ("Ultra-Light"))
1550 PROP_SAVE (weight, "ultra-light");
1551 else if (PROP_MATCH ("Light"))
1552 PROP_SAVE (weight, "light");
1553 else if (PROP_MATCH ("Book"))
1554 PROP_SAVE (weight, "book");
1555 else if (PROP_MATCH ("Medium"))
1556 PROP_SAVE (weight, "medium");
1557 else if (PROP_MATCH ("Semi-Bold"))
1558 PROP_SAVE (weight, "semi-bold");
1559 else if (PROP_MATCH ("Bold"))
1560 PROP_SAVE (weight, "bold");
1561 else if (PROP_MATCH ("Italic"))
1562 PROP_SAVE (slant, "italic");
1563 else if (PROP_MATCH ("Oblique"))
1564 PROP_SAVE (slant, "oblique");
1565 else if (PROP_MATCH ("Semi-Condensed"))
1566 PROP_SAVE (width, "semi-condensed");
1567 else if (PROP_MATCH ("Condensed"))
1568 PROP_SAVE (width, "condensed");
1569 /* An unknown word must be part of the font name. */
1570 else
1572 family_end = p;
1573 break;
1576 #undef PROP_MATCH
1577 #undef PROP_SAVE
1579 if (family_end)
1580 ASET (font, FONT_FAMILY_INDEX,
1581 font_intern_prop (name, family_end - name, 1));
1582 if (!NILP (size))
1583 ASET (font, FONT_SIZE_INDEX, size);
1584 if (!NILP (weight))
1585 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, weight);
1586 if (!NILP (slant))
1587 FONT_SET_STYLE (font, FONT_SLANT_INDEX, slant);
1588 if (!NILP (width))
1589 FONT_SET_STYLE (font, FONT_WIDTH_INDEX, width);
1592 return 0;
1595 #if defined HAVE_XFT || defined HAVE_FREETYPE || defined HAVE_NS
1597 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1598 NAME (NBYTES length), and return the name length. If
1599 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead.
1600 Return a negative value on error. */
1602 static int
1603 font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes)
1605 Lisp_Object family, foundry;
1606 Lisp_Object val;
1607 int point_size;
1608 int i;
1609 char *p;
1610 char *lim;
1611 Lisp_Object styles[3];
1612 const char *style_names[3] = { "weight", "slant", "width" };
1614 family = AREF (font, FONT_FAMILY_INDEX);
1615 if (! NILP (family))
1617 if (SYMBOLP (family))
1618 family = SYMBOL_NAME (family);
1619 else
1620 family = Qnil;
1623 val = AREF (font, FONT_SIZE_INDEX);
1624 if (INTEGERP (val))
1626 if (XINT (val) != 0)
1627 pixel_size = XINT (val);
1628 point_size = -1;
1630 else
1632 eassert (FLOATP (val));
1633 pixel_size = -1;
1634 point_size = (int) XFLOAT_DATA (val);
1637 foundry = AREF (font, FONT_FOUNDRY_INDEX);
1638 if (! NILP (foundry))
1640 if (SYMBOLP (foundry))
1641 foundry = SYMBOL_NAME (foundry);
1642 else
1643 foundry = Qnil;
1646 for (i = 0; i < 3; i++)
1647 styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
1649 p = name;
1650 lim = name + nbytes;
1651 if (! NILP (family))
1653 int len = snprintf (p, lim - p, "%s", SSDATA (family));
1654 if (! (0 <= len && len < lim - p))
1655 return -1;
1656 p += len;
1658 if (point_size > 0)
1660 int len = snprintf (p, lim - p, &"-%d"[p == name], point_size);
1661 if (! (0 <= len && len < lim - p))
1662 return -1;
1663 p += len;
1665 else if (pixel_size > 0)
1667 int len = snprintf (p, lim - p, ":pixelsize=%d", pixel_size);
1668 if (! (0 <= len && len < lim - p))
1669 return -1;
1670 p += len;
1672 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1674 int len = snprintf (p, lim - p, ":foundry=%s",
1675 SSDATA (SYMBOL_NAME (AREF (font,
1676 FONT_FOUNDRY_INDEX))));
1677 if (! (0 <= len && len < lim - p))
1678 return -1;
1679 p += len;
1681 for (i = 0; i < 3; i++)
1682 if (! NILP (styles[i]))
1684 int len = snprintf (p, lim - p, ":%s=%s", style_names[i],
1685 SSDATA (SYMBOL_NAME (styles[i])));
1686 if (! (0 <= len && len < lim - p))
1687 return -1;
1688 p += len;
1691 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1693 int len = snprintf (p, lim - p, ":dpi=%"pI"d",
1694 XINT (AREF (font, FONT_DPI_INDEX)));
1695 if (! (0 <= len && len < lim - p))
1696 return -1;
1697 p += len;
1700 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1702 int len = snprintf (p, lim - p, ":spacing=%"pI"d",
1703 XINT (AREF (font, FONT_SPACING_INDEX)));
1704 if (! (0 <= len && len < lim - p))
1705 return -1;
1706 p += len;
1709 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1711 int len = snprintf (p, lim - p,
1712 (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0
1713 ? ":scalable=true"
1714 : ":scalable=false"));
1715 if (! (0 <= len && len < lim - p))
1716 return -1;
1717 p += len;
1720 return (p - name);
1723 #endif
1725 /* Parse NAME (null terminated) and store information in FONT
1726 (font-spec or font-entity). If NAME is successfully parsed, return
1727 0. Otherwise return -1. */
1729 static int
1730 font_parse_name (char *name, ptrdiff_t namelen, Lisp_Object font)
1732 if (name[0] == '-' || strchr (name, '*') || strchr (name, '?'))
1733 return font_parse_xlfd (name, namelen, font);
1734 return font_parse_fcname (name, namelen, font);
1738 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1739 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1740 part. */
1742 void
1743 font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Object font_spec)
1745 ptrdiff_t len;
1746 char *p0, *p1;
1748 if (! NILP (family)
1749 && NILP (AREF (font_spec, FONT_FAMILY_INDEX)))
1751 CHECK_STRING (family);
1752 len = SBYTES (family);
1753 p0 = SSDATA (family);
1754 p1 = strchr (p0, '-');
1755 if (p1)
1757 if ((*p0 != '*' && p1 - p0 > 0)
1758 && NILP (AREF (font_spec, FONT_FOUNDRY_INDEX)))
1759 Ffont_put (font_spec, QCfoundry, font_intern_prop (p0, p1 - p0, 1));
1760 p1++;
1761 len -= p1 - p0;
1762 Ffont_put (font_spec, QCfamily, font_intern_prop (p1, len, 1));
1764 else
1765 ASET (font_spec, FONT_FAMILY_INDEX, Fintern (family, Qnil));
1767 if (! NILP (registry))
1769 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1770 CHECK_STRING (registry);
1771 len = SBYTES (registry);
1772 p0 = SSDATA (registry);
1773 p1 = strchr (p0, '-');
1774 if (! p1)
1776 bool asterisk = len && p0[len - 1] == '*';
1777 AUTO_STRING_WITH_LEN (extra, &"*-*"[asterisk], 3 - asterisk);
1778 registry = concat2 (registry, extra);
1780 registry = Fdowncase (registry);
1781 ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil));
1786 /* This part (through the next ^L) is still experimental and not
1787 tested much. We may drastically change codes. */
1789 /* OTF handler. */
1791 #if 0
1793 #define LGSTRING_HEADER_SIZE 6
1794 #define LGSTRING_GLYPH_SIZE 8
1796 static int
1797 check_gstring (Lisp_Object gstring)
1799 Lisp_Object val;
1800 ptrdiff_t i;
1801 int j;
1803 CHECK_VECTOR (gstring);
1804 val = AREF (gstring, 0);
1805 CHECK_VECTOR (val);
1806 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1807 goto err;
1808 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1809 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1810 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1811 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1812 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1813 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1814 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1815 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1816 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1817 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1818 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1820 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
1822 val = LGSTRING_GLYPH (gstring, i);
1823 CHECK_VECTOR (val);
1824 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1825 goto err;
1826 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1827 break;
1828 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1829 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1830 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1831 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1832 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1833 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1834 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1835 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1837 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1838 CHECK_VECTOR (val);
1839 if (ASIZE (val) < 3)
1840 goto err;
1841 for (j = 0; j < 3; j++)
1842 CHECK_NUMBER (AREF (val, j));
1845 return i;
1846 err:
1847 error ("Invalid glyph-string format");
1848 return -1;
1851 static void
1852 check_otf_features (Lisp_Object otf_features)
1854 Lisp_Object val;
1856 CHECK_CONS (otf_features);
1857 CHECK_SYMBOL (XCAR (otf_features));
1858 otf_features = XCDR (otf_features);
1859 CHECK_CONS (otf_features);
1860 CHECK_SYMBOL (XCAR (otf_features));
1861 otf_features = XCDR (otf_features);
1862 for (val = Fcar (otf_features); CONSP (val); val = XCDR (val))
1864 CHECK_SYMBOL (XCAR (val));
1865 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1866 error ("Invalid OTF GSUB feature: %s",
1867 SDATA (SYMBOL_NAME (XCAR (val))));
1869 otf_features = XCDR (otf_features);
1870 for (val = Fcar (otf_features); CONSP (val); val = XCDR (val))
1872 CHECK_SYMBOL (XCAR (val));
1873 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1874 error ("Invalid OTF GPOS feature: %s",
1875 SDATA (SYMBOL_NAME (XCAR (val))));
1879 #ifdef HAVE_LIBOTF
1880 #include <otf.h>
1882 Lisp_Object otf_list;
1884 static Lisp_Object
1885 otf_tag_symbol (OTF_Tag tag)
1887 char name[5];
1889 OTF_tag_name (tag, name);
1890 return Fintern (make_unibyte_string (name, 4), Qnil);
1893 static OTF *
1894 otf_open (Lisp_Object file)
1896 Lisp_Object val = Fassoc (file, otf_list, Qnil);
1897 OTF *otf;
1899 if (! NILP (val))
1900 otf = xmint_pointer (XCDR (val));
1901 else
1903 otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL;
1904 val = make_mint_ptr (otf);
1905 otf_list = Fcons (Fcons (file, val), otf_list);
1907 return otf;
1911 /* Return a list describing which scripts/languages FONT supports by
1912 which GSUB/GPOS features of OpenType tables. See the comment of
1913 (struct font_driver).otf_capability. */
1915 Lisp_Object
1916 font_otf_capability (struct font *font)
1918 OTF *otf;
1919 Lisp_Object capability = Fcons (Qnil, Qnil);
1920 int i;
1922 otf = otf_open (font->props[FONT_FILE_INDEX]);
1923 if (! otf)
1924 return Qnil;
1925 for (i = 0; i < 2; i++)
1927 OTF_GSUB_GPOS *gsub_gpos;
1928 Lisp_Object script_list = Qnil;
1929 int j;
1931 if (OTF_get_features (otf, i == 0) < 0)
1932 continue;
1933 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1934 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1936 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1937 Lisp_Object langsys_list = Qnil;
1938 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1939 int k;
1941 for (k = script->LangSysCount; k >= 0; k--)
1943 OTF_LangSys *langsys;
1944 Lisp_Object feature_list = Qnil;
1945 Lisp_Object langsys_tag;
1946 int l;
1948 if (k == script->LangSysCount)
1950 langsys = &script->DefaultLangSys;
1951 langsys_tag = Qnil;
1953 else
1955 langsys = script->LangSys + k;
1956 langsys_tag
1957 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
1959 for (l = langsys->FeatureCount - 1; l >= 0; l--)
1961 OTF_Feature *feature
1962 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
1963 Lisp_Object feature_tag
1964 = otf_tag_symbol (feature->FeatureTag);
1966 feature_list = Fcons (feature_tag, feature_list);
1968 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1969 langsys_list);
1971 script_list = Fcons (Fcons (script_tag, langsys_list),
1972 script_list);
1975 if (i == 0)
1976 XSETCAR (capability, script_list);
1977 else
1978 XSETCDR (capability, script_list);
1981 return capability;
1984 /* Parse OTF features in SPEC and write a proper features spec string
1985 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1986 assured that the sufficient memory has already allocated for
1987 FEATURES. */
1989 static void
1990 generate_otf_features (Lisp_Object spec, char *features)
1992 Lisp_Object val;
1993 char *p;
1994 bool asterisk;
1996 p = features;
1997 *p = '\0';
1998 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
2000 val = XCAR (spec);
2001 CHECK_SYMBOL (val);
2002 if (p > features)
2003 *p++ = ',';
2004 if (SREF (SYMBOL_NAME (val), 0) == '*')
2006 asterisk = 1;
2007 *p++ = '*';
2009 else if (! asterisk)
2011 val = SYMBOL_NAME (val);
2012 p += esprintf (p, "%s", SDATA (val));
2014 else
2016 val = SYMBOL_NAME (val);
2017 p += esprintf (p, "~%s", SDATA (val));
2020 if (CONSP (spec))
2021 error ("OTF spec too long");
2024 Lisp_Object
2025 font_otf_DeviceTable (OTF_DeviceTable *device_table)
2027 int len = device_table->StartSize - device_table->EndSize + 1;
2029 return Fcons (make_number (len),
2030 make_unibyte_string (device_table->DeltaValue, len));
2033 Lisp_Object
2034 font_otf_ValueRecord (int value_format, OTF_ValueRecord *value_record)
2036 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
2038 if (value_format & OTF_XPlacement)
2039 ASET (val, 0, make_number (value_record->XPlacement));
2040 if (value_format & OTF_YPlacement)
2041 ASET (val, 1, make_number (value_record->YPlacement));
2042 if (value_format & OTF_XAdvance)
2043 ASET (val, 2, make_number (value_record->XAdvance));
2044 if (value_format & OTF_YAdvance)
2045 ASET (val, 3, make_number (value_record->YAdvance));
2046 if (value_format & OTF_XPlaDevice)
2047 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
2048 if (value_format & OTF_YPlaDevice)
2049 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
2050 if (value_format & OTF_XAdvDevice)
2051 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
2052 if (value_format & OTF_YAdvDevice)
2053 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
2054 return val;
2057 Lisp_Object
2058 font_otf_Anchor (OTF_Anchor *anchor)
2060 Lisp_Object val;
2062 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
2063 ASET (val, 0, make_number (anchor->XCoordinate));
2064 ASET (val, 1, make_number (anchor->YCoordinate));
2065 if (anchor->AnchorFormat == 2)
2066 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
2067 else
2069 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
2070 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
2072 return val;
2074 #endif /* HAVE_LIBOTF */
2075 #endif /* 0 */
2078 /* Font sorting. */
2080 static double
2081 font_rescale_ratio (Lisp_Object font_entity)
2083 Lisp_Object tail, elt;
2084 Lisp_Object name = Qnil;
2086 for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail))
2088 elt = XCAR (tail);
2089 if (FLOATP (XCDR (elt)))
2091 if (STRINGP (XCAR (elt)))
2093 if (NILP (name))
2094 name = Ffont_xlfd_name (font_entity, Qnil);
2095 if (fast_string_match_ignore_case (XCAR (elt), name) >= 0)
2096 return XFLOAT_DATA (XCDR (elt));
2098 else if (FONT_SPEC_P (XCAR (elt)))
2100 if (font_match_p (XCAR (elt), font_entity))
2101 return XFLOAT_DATA (XCDR (elt));
2105 return 1.0;
2108 /* We sort fonts by scoring each of them against a specified
2109 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2110 the value is, the closer the font is to the font-spec.
2112 The lowest 2 bits of the score are used for driver type. The font
2113 available by the most preferred font driver is 0.
2115 The 4 7-bit fields in the higher 28 bits are used for numeric properties
2116 WEIGHT, SLANT, WIDTH, and SIZE. */
2118 /* How many bits to shift to store the difference value of each font
2119 property in a score. Note that floats for FONT_TYPE_INDEX and
2120 FONT_REGISTRY_INDEX are not used. */
2121 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
2123 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2124 The return value indicates how different ENTITY is compared with
2125 SPEC_PROP. */
2127 static unsigned
2128 font_score (Lisp_Object entity, Lisp_Object *spec_prop)
2130 unsigned score = 0;
2131 int i;
2133 /* Score three style numeric fields. Maximum difference is 127. */
2134 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
2135 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
2137 EMACS_INT diff = ((XINT (AREF (entity, i)) >> 8)
2138 - (XINT (spec_prop[i]) >> 8));
2139 score |= min (eabs (diff), 127) << sort_shift_bits[i];
2142 /* Score the size. Maximum difference is 127. */
2143 if (! NILP (spec_prop[FONT_SIZE_INDEX])
2144 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2146 /* We use the higher 6-bit for the actual size difference. The
2147 lowest bit is set if the DPI is different. */
2148 EMACS_INT diff;
2149 EMACS_INT pixel_size = XINT (spec_prop[FONT_SIZE_INDEX]);
2150 EMACS_INT entity_size = XINT (AREF (entity, FONT_SIZE_INDEX));
2152 if (CONSP (Vface_font_rescale_alist))
2153 pixel_size *= font_rescale_ratio (entity);
2154 if (pixel_size * 2 < entity_size || entity_size * 2 < pixel_size)
2155 /* This size is wrong by more than a factor 2: reject it! */
2156 return 0xFFFFFFFF;
2157 diff = eabs (pixel_size - entity_size) << 1;
2158 if (! NILP (spec_prop[FONT_DPI_INDEX])
2159 && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX)))
2160 diff |= 1;
2161 if (! NILP (spec_prop[FONT_AVGWIDTH_INDEX])
2162 && ! EQ (spec_prop[FONT_AVGWIDTH_INDEX], AREF (entity, FONT_AVGWIDTH_INDEX)))
2163 diff |= 1;
2164 score |= min (diff, 127) << sort_shift_bits[FONT_SIZE_INDEX];
2167 return score;
2171 /* Concatenate all elements of LIST into one vector. LIST is a list
2172 of font-entity vectors. */
2174 static Lisp_Object
2175 font_vconcat_entity_vectors (Lisp_Object list)
2177 EMACS_INT nargs = XFASTINT (Flength (list));
2178 Lisp_Object *args;
2179 USE_SAFE_ALLOCA;
2180 SAFE_ALLOCA_LISP (args, nargs);
2181 ptrdiff_t i;
2183 for (i = 0; i < nargs; i++, list = XCDR (list))
2184 args[i] = XCAR (list);
2185 Lisp_Object result = Fvconcat (nargs, args);
2186 SAFE_FREE ();
2187 return result;
2191 /* The structure for elements being sorted by qsort. */
2192 struct font_sort_data
2194 unsigned score;
2195 int font_driver_preference;
2196 Lisp_Object entity;
2200 /* The comparison function for qsort. */
2202 static int
2203 font_compare (const void *d1, const void *d2)
2205 const struct font_sort_data *data1 = d1;
2206 const struct font_sort_data *data2 = d2;
2208 if (data1->score < data2->score)
2209 return -1;
2210 else if (data1->score > data2->score)
2211 return 1;
2212 return (data1->font_driver_preference - data2->font_driver_preference);
2216 /* Sort each font-entity vector in LIST by closeness to font-spec PREFER.
2217 If PREFER specifies a point-size, calculate the corresponding
2218 pixel-size from QCdpi property of PREFER or from the Y-resolution
2219 of FRAME before sorting.
2221 If BEST-ONLY is nonzero, return the best matching entity (that
2222 supports the character BEST-ONLY if BEST-ONLY is positive, or any
2223 if BEST-ONLY is negative). Otherwise, return the sorted result as
2224 a single vector of font-entities.
2226 This function does no optimization for the case that the total
2227 number of elements is 1. The caller should avoid calling this in
2228 such a case. */
2230 static Lisp_Object
2231 font_sort_entities (Lisp_Object list, Lisp_Object prefer,
2232 struct frame *f, int best_only)
2234 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2235 int len, maxlen, i;
2236 struct font_sort_data *data;
2237 unsigned best_score;
2238 Lisp_Object best_entity;
2239 Lisp_Object tail;
2240 Lisp_Object vec UNINIT;
2241 USE_SAFE_ALLOCA;
2243 for (i = FONT_WEIGHT_INDEX; i <= FONT_AVGWIDTH_INDEX; i++)
2244 prefer_prop[i] = AREF (prefer, i);
2245 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2246 prefer_prop[FONT_SIZE_INDEX]
2247 = make_number (font_pixel_size (f, prefer));
2249 if (NILP (XCDR (list)))
2251 /* What we have to take care of is this single vector. */
2252 vec = XCAR (list);
2253 maxlen = ASIZE (vec);
2255 else if (best_only)
2257 /* We don't have to perform sort, so there's no need of creating
2258 a single vector. But, we must find the length of the longest
2259 vector. */
2260 maxlen = 0;
2261 for (tail = list; CONSP (tail); tail = XCDR (tail))
2262 if (maxlen < ASIZE (XCAR (tail)))
2263 maxlen = ASIZE (XCAR (tail));
2265 else
2267 /* We have to create a single vector to sort it. */
2268 vec = font_vconcat_entity_vectors (list);
2269 maxlen = ASIZE (vec);
2272 data = SAFE_ALLOCA (maxlen * sizeof *data);
2273 best_score = 0xFFFFFFFF;
2274 best_entity = Qnil;
2276 for (tail = list; CONSP (tail); tail = XCDR (tail))
2278 int font_driver_preference = 0;
2279 Lisp_Object current_font_driver;
2281 if (best_only)
2282 vec = XCAR (tail);
2283 len = ASIZE (vec);
2285 /* We are sure that the length of VEC > 0. */
2286 current_font_driver = AREF (AREF (vec, 0), FONT_TYPE_INDEX);
2287 /* Score the elements. */
2288 for (i = 0; i < len; i++)
2290 data[i].entity = AREF (vec, i);
2291 data[i].score
2292 = ((best_only <= 0 || font_has_char (f, data[i].entity, best_only)
2293 > 0)
2294 ? font_score (data[i].entity, prefer_prop)
2295 : 0xFFFFFFFF);
2296 if (best_only && best_score > data[i].score)
2298 best_score = data[i].score;
2299 best_entity = data[i].entity;
2300 if (best_score == 0)
2301 break;
2303 if (! EQ (current_font_driver, AREF (AREF (vec, i), FONT_TYPE_INDEX)))
2305 current_font_driver = AREF (AREF (vec, i), FONT_TYPE_INDEX);
2306 font_driver_preference++;
2308 data[i].font_driver_preference = font_driver_preference;
2311 /* Sort if necessary. */
2312 if (! best_only)
2314 qsort (data, len, sizeof *data, font_compare);
2315 for (i = 0; i < len; i++)
2316 ASET (vec, i, data[i].entity);
2317 break;
2319 else
2320 vec = best_entity;
2323 SAFE_FREE ();
2325 FONT_ADD_LOG ("sort-by", prefer, vec);
2326 return vec;
2330 /* API of Font Service Layer. */
2332 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2333 sort_shift_bits. Finternal_set_font_selection_order calls this
2334 function with font_sort_order after setting up it. */
2336 void
2337 font_update_sort_order (int *order)
2339 int i, shift_bits;
2341 for (i = 0, shift_bits = 23; i < 4; i++, shift_bits -= 7)
2343 int xlfd_idx = order[i];
2345 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2346 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2347 else if (xlfd_idx == XLFD_SLANT_INDEX)
2348 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2349 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2350 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2351 else
2352 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2356 static bool
2357 font_check_otf_features (Lisp_Object script, Lisp_Object langsys,
2358 Lisp_Object features, Lisp_Object table)
2360 Lisp_Object val;
2361 bool negative;
2363 table = assq_no_quit (script, table);
2364 if (NILP (table))
2365 return 0;
2366 table = XCDR (table);
2367 if (! NILP (langsys))
2369 table = assq_no_quit (langsys, table);
2370 if (NILP (table))
2371 return 0;
2373 else
2375 val = assq_no_quit (Qnil, table);
2376 if (NILP (val))
2377 table = XCAR (table);
2378 else
2379 table = val;
2381 table = XCDR (table);
2382 for (negative = 0; CONSP (features); features = XCDR (features))
2384 if (NILP (XCAR (features)))
2386 negative = 1;
2387 continue;
2389 if (NILP (Fmemq (XCAR (features), table)) != negative)
2390 return 0;
2392 return 1;
2395 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2397 static bool
2398 font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
2400 Lisp_Object script, langsys = Qnil, gsub = Qnil, gpos = Qnil;
2402 script = XCAR (spec);
2403 spec = XCDR (spec);
2404 if (! NILP (spec))
2406 langsys = XCAR (spec);
2407 spec = XCDR (spec);
2408 if (! NILP (spec))
2410 gsub = XCAR (spec);
2411 spec = XCDR (spec);
2412 if (! NILP (spec))
2413 gpos = XCAR (spec);
2417 if (! NILP (gsub) && ! font_check_otf_features (script, langsys, gsub,
2418 XCAR (otf_capability)))
2419 return 0;
2420 if (! NILP (gpos) && ! font_check_otf_features (script, langsys, gpos,
2421 XCDR (otf_capability)))
2422 return 0;
2423 return 1;
2428 /* Check if FONT (font-entity or font-object) matches with the font
2429 specification SPEC. */
2431 bool
2432 font_match_p (Lisp_Object spec, Lisp_Object font)
2434 Lisp_Object prop[FONT_SPEC_MAX], *props;
2435 Lisp_Object extra, font_extra;
2436 int i;
2438 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2439 if (! NILP (AREF (spec, i))
2440 && ! NILP (AREF (font, i))
2441 && ! EQ (AREF (spec, i), AREF (font, i)))
2442 return 0;
2443 props = XFONT_SPEC (spec)->props;
2444 if (FLOATP (props[FONT_SIZE_INDEX]))
2446 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
2447 prop[i] = AREF (spec, i);
2448 prop[FONT_SIZE_INDEX]
2449 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2450 props = prop;
2453 if (font_score (font, props) > 0)
2454 return 0;
2455 extra = AREF (spec, FONT_EXTRA_INDEX);
2456 font_extra = AREF (font, FONT_EXTRA_INDEX);
2457 for (; CONSP (extra); extra = XCDR (extra))
2459 Lisp_Object key = XCAR (XCAR (extra));
2460 Lisp_Object val = XCDR (XCAR (extra)), val2;
2462 if (EQ (key, QClang))
2464 val2 = assq_no_quit (key, font_extra);
2465 if (NILP (val2))
2466 return 0;
2467 val2 = XCDR (val2);
2468 if (CONSP (val))
2470 if (! CONSP (val2))
2471 return 0;
2472 while (CONSP (val))
2473 if (NILP (Fmemq (val, val2)))
2474 return 0;
2476 else
2477 if (CONSP (val2)
2478 ? NILP (Fmemq (val, XCDR (val2)))
2479 : ! EQ (val, val2))
2480 return 0;
2482 else if (EQ (key, QCscript))
2484 val2 = assq_no_quit (val, Vscript_representative_chars);
2485 if (CONSP (val2))
2487 val2 = XCDR (val2);
2488 if (CONSP (val2))
2490 /* All characters in the list must be supported. */
2491 for (; CONSP (val2); val2 = XCDR (val2))
2493 if (! CHARACTERP (XCAR (val2)))
2494 continue;
2495 if (font_encode_char (font, XFASTINT (XCAR (val2)))
2496 == FONT_INVALID_CODE)
2497 return 0;
2500 else if (VECTORP (val2))
2502 /* At most one character in the vector must be supported. */
2503 for (i = 0; i < ASIZE (val2); i++)
2505 if (! CHARACTERP (AREF (val2, i)))
2506 continue;
2507 if (font_encode_char (font, XFASTINT (AREF (val2, i)))
2508 != FONT_INVALID_CODE)
2509 break;
2511 if (i == ASIZE (val2))
2512 return 0;
2516 else if (EQ (key, QCotf))
2518 struct font *fontp;
2520 if (! FONT_OBJECT_P (font))
2521 return 0;
2522 fontp = XFONT_OBJECT (font);
2523 if (! fontp->driver->otf_capability)
2524 return 0;
2525 val2 = fontp->driver->otf_capability (fontp);
2526 if (NILP (val2) || ! font_check_otf (val, val2))
2527 return 0;
2531 return 1;
2535 /* Font cache
2537 Each font backend has the callback function get_cache, and it
2538 returns a cons cell of which cdr part can be freely used for
2539 caching fonts. The cons cell may be shared by multiple frames
2540 and/or multiple font drivers. So, we arrange the cdr part as this:
2542 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2544 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2545 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2546 cons (FONT-SPEC . [FONT-ENTITY ...]). */
2548 static void font_clear_cache (struct frame *, Lisp_Object,
2549 struct font_driver const *);
2551 static void
2552 font_prepare_cache (struct frame *f, struct font_driver const *driver)
2554 Lisp_Object cache, val;
2556 cache = driver->get_cache (f);
2557 val = XCDR (cache);
2558 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2559 val = XCDR (val);
2560 if (NILP (val))
2562 val = list2 (driver->type, make_number (1));
2563 XSETCDR (cache, Fcons (val, XCDR (cache)));
2565 else
2567 val = XCDR (XCAR (val));
2568 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2573 static void
2574 font_finish_cache (struct frame *f, struct font_driver const *driver)
2576 Lisp_Object cache, val, tmp;
2579 cache = driver->get_cache (f);
2580 val = XCDR (cache);
2581 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2582 cache = val, val = XCDR (val);
2583 eassert (! NILP (val));
2584 tmp = XCDR (XCAR (val));
2585 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2586 if (XINT (XCAR (tmp)) == 0)
2588 font_clear_cache (f, XCAR (val), driver);
2589 XSETCDR (cache, XCDR (val));
2594 static Lisp_Object
2595 font_get_cache (struct frame *f, struct font_driver const *driver)
2597 Lisp_Object val = driver->get_cache (f);
2598 Lisp_Object type = driver->type;
2600 eassert (CONSP (val));
2601 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2602 eassert (CONSP (val));
2603 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2604 val = XCDR (XCAR (val));
2605 return val;
2609 static void
2610 font_clear_cache (struct frame *f, Lisp_Object cache,
2611 struct font_driver const *driver)
2613 Lisp_Object tail, elt;
2614 Lisp_Object entity;
2615 ptrdiff_t i;
2617 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2618 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2620 elt = XCAR (tail);
2621 /* elt should have the form (FONT-SPEC . [FONT-ENTITY ...]) */
2622 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2624 elt = XCDR (elt);
2625 eassert (VECTORP (elt));
2626 for (i = 0; i < ASIZE (elt); i++)
2628 entity = AREF (elt, i);
2630 if (FONT_ENTITY_P (entity)
2631 && EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2633 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2635 for (; CONSP (objlist); objlist = XCDR (objlist))
2637 Lisp_Object val = XCAR (objlist);
2638 struct font *font = XFONT_OBJECT (val);
2640 if (! NILP (AREF (val, FONT_TYPE_INDEX)))
2642 eassert (font && driver == font->driver);
2643 driver->close (font);
2646 if (driver->free_entity)
2647 driver->free_entity (entity);
2652 XSETCDR (cache, Qnil);
2656 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2658 /* Check each font-entity in VEC, and return a list of font-entities
2659 that satisfy these conditions:
2660 (1) matches with SPEC and SIZE if SPEC is not nil, and
2661 (2) doesn't match with any regexps in Vface_ignored_fonts (if non-nil).
2664 static Lisp_Object
2665 font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size)
2667 Lisp_Object entity, val;
2668 enum font_property_index prop;
2669 ptrdiff_t i;
2671 for (val = Qnil, i = ASIZE (vec) - 1; i >= 0; i--)
2673 entity = AREF (vec, i);
2674 if (! NILP (Vface_ignored_fonts))
2676 char name[256];
2677 ptrdiff_t namelen;
2678 Lisp_Object tail, regexp;
2680 namelen = font_unparse_xlfd (entity, 0, name, 256);
2681 if (namelen >= 0)
2683 for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
2685 regexp = XCAR (tail);
2686 if (STRINGP (regexp)
2687 && fast_c_string_match_ignore_case (regexp, name,
2688 namelen) >= 0)
2689 break;
2691 if (CONSP (tail))
2692 continue;
2695 if (NILP (spec))
2697 val = Fcons (entity, val);
2698 continue;
2700 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++)
2701 if (INTEGERP (AREF (spec, prop))
2702 && ((XINT (AREF (spec, prop)) >> 8)
2703 != (XINT (AREF (entity, prop)) >> 8)))
2704 prop = FONT_SPEC_MAX;
2705 if (prop < FONT_SPEC_MAX
2706 && size
2707 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2709 int diff = XINT (AREF (entity, FONT_SIZE_INDEX)) - size;
2711 if (eabs (diff) > FONT_PIXEL_SIZE_QUANTUM)
2712 prop = FONT_SPEC_MAX;
2714 if (prop < FONT_SPEC_MAX
2715 && INTEGERP (AREF (spec, FONT_DPI_INDEX))
2716 && INTEGERP (AREF (entity, FONT_DPI_INDEX))
2717 && XINT (AREF (entity, FONT_DPI_INDEX)) != 0
2718 && ! EQ (AREF (spec, FONT_DPI_INDEX), AREF (entity, FONT_DPI_INDEX)))
2719 prop = FONT_SPEC_MAX;
2720 if (prop < FONT_SPEC_MAX
2721 && INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
2722 && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
2723 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) != 0
2724 && ! EQ (AREF (spec, FONT_AVGWIDTH_INDEX),
2725 AREF (entity, FONT_AVGWIDTH_INDEX)))
2726 prop = FONT_SPEC_MAX;
2727 if (prop < FONT_SPEC_MAX)
2728 val = Fcons (entity, val);
2730 return (Fvconcat (1, &val));
2734 /* Return a list of vectors of font-entities matching with SPEC on
2735 FRAME. Each elements in the list is a vector of entities from the
2736 same font-driver. */
2738 Lisp_Object
2739 font_list_entities (struct frame *f, Lisp_Object spec)
2741 struct font_driver_list *driver_list = f->font_driver_list;
2742 Lisp_Object ftype, val;
2743 Lisp_Object list = Qnil;
2744 int size;
2745 bool need_filtering = 0;
2746 int i;
2748 eassert (FONT_SPEC_P (spec));
2750 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2751 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2752 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2753 size = font_pixel_size (f, spec);
2754 else
2755 size = 0;
2757 ftype = AREF (spec, FONT_TYPE_INDEX);
2758 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2759 ASET (scratch_font_spec, i, AREF (spec, i));
2760 for (i = FONT_WEIGHT_INDEX; i < FONT_EXTRA_INDEX; i++)
2761 if (i != FONT_SPACING_INDEX)
2763 ASET (scratch_font_spec, i, Qnil);
2764 if (! NILP (AREF (spec, i)))
2765 need_filtering = 1;
2767 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX));
2768 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
2770 for (; driver_list; driver_list = driver_list->next)
2771 if (driver_list->on
2772 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2774 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2776 ASET (scratch_font_spec, FONT_TYPE_INDEX, driver_list->driver->type);
2777 val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2778 if (CONSP (val))
2779 val = XCDR (val);
2780 else
2782 Lisp_Object copy;
2784 val = driver_list->driver->list (f, scratch_font_spec);
2785 /* We put zero_vector in the font-cache to indicate that
2786 no fonts matching SPEC were found on the system.
2787 Failure to have this indication in the font cache can
2788 cause severe performance degradation in some rare
2789 cases, see bug#21028. */
2790 if (NILP (val))
2791 val = zero_vector;
2792 else
2793 val = Fvconcat (1, &val);
2794 copy = copy_font_spec (scratch_font_spec);
2795 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2796 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2798 if (ASIZE (val) > 0
2799 && (need_filtering
2800 || ! NILP (Vface_ignored_fonts)))
2801 val = font_delete_unmatched (val, need_filtering ? spec : Qnil, size);
2802 if (ASIZE (val) > 0)
2803 list = Fcons (val, list);
2806 list = Fnreverse (list);
2807 FONT_ADD_LOG ("list", spec, list);
2808 return list;
2812 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2813 nil, is an array of face's attributes, which specifies preferred
2814 font-related attributes. */
2816 static Lisp_Object
2817 font_matching_entity (struct frame *f, Lisp_Object *attrs, Lisp_Object spec)
2819 struct font_driver_list *driver_list = f->font_driver_list;
2820 Lisp_Object ftype, size, entity;
2821 Lisp_Object work = copy_font_spec (spec);
2823 ftype = AREF (spec, FONT_TYPE_INDEX);
2824 size = AREF (spec, FONT_SIZE_INDEX);
2826 if (FLOATP (size))
2827 ASET (work, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2828 FONT_SET_STYLE (work, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
2829 FONT_SET_STYLE (work, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
2830 FONT_SET_STYLE (work, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
2832 entity = Qnil;
2833 for (; driver_list; driver_list = driver_list->next)
2834 if (driver_list->on
2835 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2837 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2839 ASET (work, FONT_TYPE_INDEX, driver_list->driver->type);
2840 entity = assoc_no_quit (work, XCDR (cache));
2841 if (CONSP (entity))
2842 entity = AREF (XCDR (entity), 0);
2843 else
2845 entity = driver_list->driver->match (f, work);
2846 if (!NILP (entity))
2848 Lisp_Object copy = copy_font_spec (work);
2849 Lisp_Object match = Fvector (1, &entity);
2851 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2852 XSETCDR (cache, Fcons (Fcons (copy, match), XCDR (cache)));
2855 if (! NILP (entity))
2856 break;
2858 FONT_ADD_LOG ("match", work, entity);
2859 return entity;
2863 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2864 opened font object. */
2866 static Lisp_Object
2867 font_open_entity (struct frame *f, Lisp_Object entity, int pixel_size)
2869 struct font_driver_list *driver_list;
2870 Lisp_Object objlist, size, val, font_object;
2871 struct font *font;
2872 int height, psize;
2874 eassert (FONT_ENTITY_P (entity));
2875 size = AREF (entity, FONT_SIZE_INDEX);
2876 if (XINT (size) != 0)
2877 pixel_size = XINT (size);
2879 val = AREF (entity, FONT_TYPE_INDEX);
2880 for (driver_list = f->font_driver_list;
2881 driver_list && ! EQ (driver_list->driver->type, val);
2882 driver_list = driver_list->next);
2883 if (! driver_list)
2884 return Qnil;
2886 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2887 objlist = XCDR (objlist))
2889 Lisp_Object fn = XCAR (objlist);
2890 if (! NILP (AREF (fn, FONT_TYPE_INDEX))
2891 && XFONT_OBJECT (fn)->pixel_size == pixel_size)
2893 if (driver_list->driver->cached_font_ok == NULL
2894 || driver_list->driver->cached_font_ok (f, fn, entity))
2895 return fn;
2899 /* We always open a font of manageable size; i.e non-zero average
2900 width and height. */
2901 for (psize = pixel_size; ; psize++)
2903 font_object = driver_list->driver->open (f, entity, psize);
2904 if (NILP (font_object))
2905 return Qnil;
2906 font = XFONT_OBJECT (font_object);
2907 if (font->average_width > 0 && font->height > 0)
2908 break;
2909 /* Avoid an infinite loop. */
2910 if (psize > pixel_size + 15)
2911 return Qnil;
2913 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
2914 FONT_ADD_LOG ("open", entity, font_object);
2915 ASET (entity, FONT_OBJLIST_INDEX,
2916 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2918 font = XFONT_OBJECT (font_object);
2919 #ifdef HAVE_WINDOW_SYSTEM
2920 int min_width = (font->min_width ? font->min_width
2921 : font->average_width ? font->average_width
2922 : font->space_width ? font->space_width
2923 : 1);
2924 #endif
2926 int font_ascent, font_descent;
2927 get_font_ascent_descent (font, &font_ascent, &font_descent);
2928 height = font_ascent + font_descent;
2929 if (height <= 0)
2930 height = 1;
2931 #ifdef HAVE_WINDOW_SYSTEM
2932 FRAME_DISPLAY_INFO (f)->n_fonts++;
2933 if (FRAME_DISPLAY_INFO (f)->n_fonts == 1)
2935 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
2936 FRAME_SMALLEST_FONT_HEIGHT (f) = height;
2937 f->fonts_changed = 1;
2939 else
2941 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
2942 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, f->fonts_changed = 1;
2943 if (FRAME_SMALLEST_FONT_HEIGHT (f) > height)
2944 FRAME_SMALLEST_FONT_HEIGHT (f) = height, f->fonts_changed = 1;
2946 #endif
2948 return font_object;
2952 /* Close FONT_OBJECT that is opened on frame F. */
2954 static void
2955 font_close_object (struct frame *f, Lisp_Object font_object)
2957 struct font *font = XFONT_OBJECT (font_object);
2959 if (NILP (AREF (font_object, FONT_TYPE_INDEX)))
2960 /* Already closed. */
2961 return;
2962 FONT_ADD_LOG ("close", font_object, Qnil);
2963 font->driver->close (font);
2964 #ifdef HAVE_WINDOW_SYSTEM
2965 eassert (FRAME_DISPLAY_INFO (f)->n_fonts);
2966 FRAME_DISPLAY_INFO (f)->n_fonts--;
2967 #endif
2971 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2972 FONT is a font-entity and it must be opened to check. */
2975 font_has_char (struct frame *f, Lisp_Object font, int c)
2977 struct font *fontp;
2979 if (FONT_ENTITY_P (font))
2981 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
2982 struct font_driver_list *driver_list;
2984 for (driver_list = f->font_driver_list;
2985 driver_list && ! EQ (driver_list->driver->type, type);
2986 driver_list = driver_list->next);
2987 if (! driver_list)
2988 return 0;
2989 if (! driver_list->driver->has_char)
2990 return -1;
2991 return driver_list->driver->has_char (font, c);
2994 eassert (FONT_OBJECT_P (font));
2995 fontp = XFONT_OBJECT (font);
2996 if (fontp->driver->has_char)
2998 int result = fontp->driver->has_char (font, c);
3000 if (result >= 0)
3001 return result;
3003 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
3007 /* Return the glyph ID of FONT_OBJECT for character C. */
3009 static unsigned
3010 font_encode_char (Lisp_Object font_object, int c)
3012 struct font *font;
3014 eassert (FONT_OBJECT_P (font_object));
3015 font = XFONT_OBJECT (font_object);
3016 return font->driver->encode_char (font, c);
3020 /* Return the name of FONT_OBJECT. */
3022 Lisp_Object
3023 font_get_name (Lisp_Object font_object)
3025 eassert (FONT_OBJECT_P (font_object));
3026 return AREF (font_object, FONT_NAME_INDEX);
3030 /* Create a new font spec from FONT_NAME, and return it. If FONT_NAME
3031 could not be parsed by font_parse_name, return Qnil. */
3033 Lisp_Object
3034 font_spec_from_name (Lisp_Object font_name)
3036 Lisp_Object spec = Ffont_spec (0, NULL);
3038 CHECK_STRING (font_name);
3039 if (font_parse_name (SSDATA (font_name), SBYTES (font_name), spec) == -1)
3040 return Qnil;
3041 font_put_extra (spec, QCname, font_name);
3042 font_put_extra (spec, QCuser_spec, font_name);
3043 return spec;
3047 void
3048 font_clear_prop (Lisp_Object *attrs, enum font_property_index prop)
3050 Lisp_Object font = attrs[LFACE_FONT_INDEX];
3052 if (! FONTP (font))
3053 return;
3055 if (! NILP (Ffont_get (font, QCname)))
3057 font = copy_font_spec (font);
3058 font_put_extra (font, QCname, Qnil);
3061 if (NILP (AREF (font, prop))
3062 && prop != FONT_FAMILY_INDEX
3063 && prop != FONT_FOUNDRY_INDEX
3064 && prop != FONT_WIDTH_INDEX
3065 && prop != FONT_SIZE_INDEX)
3066 return;
3067 if (EQ (font, attrs[LFACE_FONT_INDEX]))
3068 font = copy_font_spec (font);
3069 ASET (font, prop, Qnil);
3070 if (prop == FONT_FAMILY_INDEX || prop == FONT_FOUNDRY_INDEX)
3072 if (prop == FONT_FAMILY_INDEX)
3074 ASET (font, FONT_FOUNDRY_INDEX, Qnil);
3075 /* If we are setting the font family, we must also clear
3076 FONT_WIDTH_INDEX to avoid rejecting families that lack
3077 support for some widths. */
3078 ASET (font, FONT_WIDTH_INDEX, Qnil);
3080 ASET (font, FONT_ADSTYLE_INDEX, Qnil);
3081 ASET (font, FONT_REGISTRY_INDEX, Qnil);
3082 ASET (font, FONT_SIZE_INDEX, Qnil);
3083 ASET (font, FONT_DPI_INDEX, Qnil);
3084 ASET (font, FONT_SPACING_INDEX, Qnil);
3085 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3087 else if (prop == FONT_SIZE_INDEX)
3089 ASET (font, FONT_DPI_INDEX, Qnil);
3090 ASET (font, FONT_SPACING_INDEX, Qnil);
3091 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3093 else if (prop == FONT_WIDTH_INDEX)
3094 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3095 attrs[LFACE_FONT_INDEX] = font;
3098 /* Select a font from ENTITIES (list of font-entity vectors) that
3099 supports C and is the best match for ATTRS and PIXEL_SIZE. */
3101 static Lisp_Object
3102 font_select_entity (struct frame *f, Lisp_Object entities,
3103 Lisp_Object *attrs, int pixel_size, int c)
3105 Lisp_Object font_entity;
3106 Lisp_Object prefer;
3107 int i;
3109 if (NILP (XCDR (entities))
3110 && ASIZE (XCAR (entities)) == 1)
3112 font_entity = AREF (XCAR (entities), 0);
3113 if (c < 0 || font_has_char (f, font_entity, c) > 0)
3114 return font_entity;
3115 return Qnil;
3118 /* Sort fonts by properties specified in ATTRS. */
3119 prefer = scratch_font_prefer;
3121 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3122 ASET (prefer, i, Qnil);
3123 if (FONTP (attrs[LFACE_FONT_INDEX]))
3125 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3127 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3128 ASET (prefer, i, AREF (face_font, i));
3130 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
3131 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
3132 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
3133 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
3134 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
3135 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
3136 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
3138 return font_sort_entities (entities, prefer, f, c);
3141 /* Return a font-entity that satisfies SPEC and is the best match for
3142 face's font related attributes in ATTRS. C, if not negative, is a
3143 character that the entity must support. */
3145 Lisp_Object
3146 font_find_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec, int c)
3148 Lisp_Object work;
3149 Lisp_Object entities, val;
3150 Lisp_Object foundry[3], *family, registry[3], adstyle[3];
3151 int pixel_size;
3152 int i, j, k, l;
3153 USE_SAFE_ALLOCA;
3155 registry[0] = AREF (spec, FONT_REGISTRY_INDEX);
3156 if (NILP (registry[0]))
3158 registry[0] = DEFAULT_ENCODING;
3159 registry[1] = Qascii_0;
3160 registry[2] = zero_vector;
3162 else
3163 registry[1] = zero_vector;
3165 if (c >= 0 && ! NILP (AREF (spec, FONT_REGISTRY_INDEX)))
3167 struct charset *encoding, *repertory;
3169 if (font_registry_charsets (AREF (spec, FONT_REGISTRY_INDEX),
3170 &encoding, &repertory) < 0)
3171 return Qnil;
3172 if (repertory
3173 && ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
3174 return Qnil;
3175 else if (c > encoding->max_char)
3176 return Qnil;
3179 work = copy_font_spec (spec);
3180 ASET (work, FONT_TYPE_INDEX, AREF (spec, FONT_TYPE_INDEX));
3181 pixel_size = font_pixel_size (f, spec);
3182 if (pixel_size == 0 && INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
3184 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3186 pixel_size = POINT_TO_PIXEL (pt / 10, FRAME_RES_Y (f));
3187 if (pixel_size < 1)
3188 pixel_size = 1;
3190 ASET (work, FONT_SIZE_INDEX, Qnil);
3191 foundry[0] = AREF (work, FONT_FOUNDRY_INDEX);
3192 if (! NILP (foundry[0]))
3193 foundry[1] = zero_vector;
3194 else if (STRINGP (attrs[LFACE_FOUNDRY_INDEX]))
3196 val = attrs[LFACE_FOUNDRY_INDEX];
3197 foundry[0] = font_intern_prop (SSDATA (val), SBYTES (val), 1);
3198 foundry[1] = Qnil;
3199 foundry[2] = zero_vector;
3201 else
3202 foundry[0] = Qnil, foundry[1] = zero_vector;
3204 adstyle[0] = AREF (work, FONT_ADSTYLE_INDEX);
3205 if (! NILP (adstyle[0]))
3206 adstyle[1] = zero_vector;
3207 else if (FONTP (attrs[LFACE_FONT_INDEX]))
3209 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3211 if (! NILP (AREF (face_font, FONT_ADSTYLE_INDEX)))
3213 adstyle[0] = AREF (face_font, FONT_ADSTYLE_INDEX);
3214 adstyle[1] = Qnil;
3215 adstyle[2] = zero_vector;
3217 else
3218 adstyle[0] = Qnil, adstyle[1] = zero_vector;
3220 else
3221 adstyle[0] = Qnil, adstyle[1] = zero_vector;
3224 val = AREF (work, FONT_FAMILY_INDEX);
3225 if (NILP (val) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
3227 val = attrs[LFACE_FAMILY_INDEX];
3228 val = font_intern_prop (SSDATA (val), SBYTES (val), 1);
3230 Lisp_Object familybuf[3];
3231 if (NILP (val))
3233 family = familybuf;
3234 family[0] = Qnil;
3235 family[1] = zero_vector; /* terminator. */
3237 else
3239 Lisp_Object alters
3240 = Fassoc_string (val, Vface_alternative_font_family_alist, Qt);
3242 if (! NILP (alters))
3244 EMACS_INT alterslen = XFASTINT (Flength (alters));
3245 SAFE_ALLOCA_LISP (family, alterslen + 2);
3246 for (i = 0; CONSP (alters); i++, alters = XCDR (alters))
3247 family[i] = XCAR (alters);
3248 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3249 family[i++] = Qnil;
3250 family[i] = zero_vector;
3252 else
3254 family = familybuf;
3255 i = 0;
3256 family[i++] = val;
3257 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3258 family[i++] = Qnil;
3259 family[i] = zero_vector;
3263 for (i = 0; SYMBOLP (family[i]); i++)
3265 ASET (work, FONT_FAMILY_INDEX, family[i]);
3266 for (j = 0; SYMBOLP (foundry[j]); j++)
3268 ASET (work, FONT_FOUNDRY_INDEX, foundry[j]);
3269 for (k = 0; SYMBOLP (registry[k]); k++)
3271 ASET (work, FONT_REGISTRY_INDEX, registry[k]);
3272 for (l = 0; SYMBOLP (adstyle[l]); l++)
3274 ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
3275 entities = font_list_entities (f, work);
3276 if (! NILP (entities))
3278 val = font_select_entity (f, entities,
3279 attrs, pixel_size, c);
3280 if (! NILP (val))
3282 SAFE_FREE ();
3283 return val;
3291 SAFE_FREE ();
3292 return Qnil;
3296 Lisp_Object
3297 font_open_for_lface (struct frame *f, Lisp_Object entity, Lisp_Object *attrs, Lisp_Object spec)
3299 int size;
3301 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX))
3302 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
3303 size = XINT (AREF (entity, FONT_SIZE_INDEX));
3304 else
3306 if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
3307 size = font_pixel_size (f, spec);
3308 else
3310 double pt;
3311 if (INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
3312 pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3313 else
3315 struct face *def = FACE_FROM_ID (f, DEFAULT_FACE_ID);
3316 Lisp_Object height = def->lface[LFACE_HEIGHT_INDEX];
3317 eassert (INTEGERP (height));
3318 pt = XINT (height);
3321 pt /= 10;
3322 size = POINT_TO_PIXEL (pt, FRAME_RES_Y (f));
3323 #ifdef HAVE_NS
3324 if (size == 0)
3326 Lisp_Object ffsize = get_frame_param (f, Qfontsize);
3327 size = (NUMBERP (ffsize)
3328 ? POINT_TO_PIXEL (XINT (ffsize), FRAME_RES_Y (f)) : 0);
3330 #endif
3332 size *= font_rescale_ratio (entity);
3335 return font_open_entity (f, entity, size);
3339 /* Find a font that satisfies SPEC and is the best match for
3340 face's attributes in ATTRS on FRAME, and return the opened
3341 font-object. */
3343 Lisp_Object
3344 font_load_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec)
3346 Lisp_Object entity, name;
3348 entity = font_find_for_lface (f, attrs, spec, -1);
3349 if (NILP (entity))
3351 /* No font is listed for SPEC, but each font-backend may have
3352 different criteria about "font matching". So, try it. */
3353 entity = font_matching_entity (f, attrs, spec);
3354 /* Perhaps the user asked for a font "Foobar-123", and we
3355 interpreted "-123" as the size, whereas it really is part of
3356 the name. So we reset the size to nil and the family name to
3357 the entire "Foobar-123" thing, and try again with that. */
3358 if (NILP (entity))
3360 name = Ffont_get (spec, QCuser_spec);
3361 if (STRINGP (name))
3363 char *p = SSDATA (name), *q = strrchr (p, '-');
3365 if (q != NULL && c_isdigit (q[1]))
3367 char *tail;
3368 double font_size = strtod (q + 1, &tail);
3370 if (font_size > 0 && tail != q + 1)
3372 Lisp_Object lsize = Ffont_get (spec, QCsize);
3374 if ((FLOATP (lsize) && XFLOAT_DATA (lsize) == font_size)
3375 || (INTEGERP (lsize) && XINT (lsize) == font_size))
3377 ASET (spec, FONT_FAMILY_INDEX,
3378 font_intern_prop (p, tail - p, 1));
3379 ASET (spec, FONT_SIZE_INDEX, Qnil);
3380 entity = font_matching_entity (f, attrs, spec);
3386 if (NILP (entity))
3387 return Qnil;
3389 /* Don't lose the original name that was put in initially. We need
3390 it to re-apply the font when font parameters (like hinting or dpi) have
3391 changed. */
3392 entity = font_open_for_lface (f, entity, attrs, spec);
3393 if (!NILP (entity))
3395 name = Ffont_get (spec, QCuser_spec);
3396 if (STRINGP (name)) font_put_extra (entity, QCuser_spec, name);
3398 return entity;
3402 /* Make FACE on frame F ready to use the font opened for FACE. */
3404 void
3405 font_prepare_for_face (struct frame *f, struct face *face)
3407 if (face->font->driver->prepare_face)
3408 face->font->driver->prepare_face (f, face);
3412 /* Make FACE on frame F stop using the font opened for FACE. */
3414 void
3415 font_done_for_face (struct frame *f, struct face *face)
3417 if (face->font->driver->done_face)
3418 face->font->driver->done_face (f, face);
3422 /* Open a font that is a match for font-spec SPEC on frame F. If no proper
3423 font is found, return Qnil. */
3425 Lisp_Object
3426 font_open_by_spec (struct frame *f, Lisp_Object spec)
3428 Lisp_Object attrs[LFACE_VECTOR_SIZE];
3430 /* We set up the default font-related attributes of a face to prefer
3431 a moderate font. */
3432 attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
3433 attrs[LFACE_SWIDTH_INDEX] = attrs[LFACE_WEIGHT_INDEX]
3434 = attrs[LFACE_SLANT_INDEX] = Qnormal;
3435 #ifndef HAVE_NS
3436 attrs[LFACE_HEIGHT_INDEX] = make_number (120);
3437 #else
3438 attrs[LFACE_HEIGHT_INDEX] = make_number (0);
3439 #endif
3440 attrs[LFACE_FONT_INDEX] = Qnil;
3442 return font_load_for_lface (f, attrs, spec);
3446 /* Open a font that matches NAME on frame F. If no proper font is
3447 found, return Qnil. */
3449 Lisp_Object
3450 font_open_by_name (struct frame *f, Lisp_Object name)
3452 Lisp_Object spec = CALLN (Ffont_spec, QCname, name);
3453 Lisp_Object ret = font_open_by_spec (f, spec);
3454 /* Do not lose name originally put in. */
3455 if (!NILP (ret))
3456 font_put_extra (ret, QCuser_spec, name);
3458 return ret;
3462 /* Register font-driver DRIVER. This function is used in two ways.
3464 The first is with frame F non-NULL. In this case, make DRIVER
3465 available (but not yet activated) on F. All frame creators
3466 (e.g. Fx_create_frame) must call this function at least once with
3467 an available font-driver.
3469 The second is with frame F NULL. In this case, DRIVER is globally
3470 registered in the variable `font_driver_list'. All font-driver
3471 implementations must call this function in its syms_of_XXXX
3472 (e.g. syms_of_xfont). */
3474 void
3475 register_font_driver (struct font_driver const *driver, struct frame *f)
3477 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
3478 struct font_driver_list *prev, *list;
3480 #ifdef HAVE_WINDOW_SYSTEM
3481 if (f && ! driver->draw)
3482 error ("Unusable font driver for a frame: %s",
3483 SDATA (SYMBOL_NAME (driver->type)));
3484 #endif /* HAVE_WINDOW_SYSTEM */
3486 for (prev = NULL, list = root; list; prev = list, list = list->next)
3487 if (EQ (list->driver->type, driver->type))
3488 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3490 list = xmalloc (sizeof *list);
3491 list->on = 0;
3492 list->driver = driver;
3493 list->next = NULL;
3494 if (prev)
3495 prev->next = list;
3496 else if (f)
3497 f->font_driver_list = list;
3498 else
3499 font_driver_list = list;
3500 if (! f)
3501 num_font_drivers++;
3504 void
3505 free_font_driver_list (struct frame *f)
3507 struct font_driver_list *list, *next;
3509 for (list = f->font_driver_list; list; list = next)
3511 next = list->next;
3512 xfree (list);
3514 f->font_driver_list = NULL;
3518 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3519 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3520 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3522 A caller must free all realized faces if any in advance. The
3523 return value is a list of font backends actually made used on
3524 F. */
3526 Lisp_Object
3527 font_update_drivers (struct frame *f, Lisp_Object new_drivers)
3529 Lisp_Object active_drivers = Qnil;
3530 struct font_driver_list *list;
3532 /* At first, turn off non-requested drivers, and turn on requested
3533 drivers. */
3534 for (list = f->font_driver_list; list; list = list->next)
3536 struct font_driver const *driver = list->driver;
3537 if ((EQ (new_drivers, Qt) || ! NILP (Fmemq (driver->type, new_drivers)))
3538 != list->on)
3540 if (list->on)
3542 if (driver->end_for_frame)
3543 driver->end_for_frame (f);
3544 font_finish_cache (f, driver);
3545 list->on = 0;
3547 else
3549 if (! driver->start_for_frame
3550 || driver->start_for_frame (f) == 0)
3552 font_prepare_cache (f, driver);
3553 list->on = 1;
3559 if (NILP (new_drivers))
3560 return Qnil;
3562 if (! EQ (new_drivers, Qt))
3564 /* Re-order the driver list according to new_drivers. */
3565 struct font_driver_list **list_table, **next;
3566 Lisp_Object tail;
3567 int i;
3568 USE_SAFE_ALLOCA;
3570 SAFE_NALLOCA (list_table, 1, num_font_drivers + 1);
3571 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
3573 for (list = f->font_driver_list; list; list = list->next)
3574 if (list->on && EQ (list->driver->type, XCAR (tail)))
3575 break;
3576 if (list)
3577 list_table[i++] = list;
3579 for (list = f->font_driver_list; list; list = list->next)
3580 if (! list->on)
3581 list_table[i++] = list;
3582 list_table[i] = NULL;
3584 next = &f->font_driver_list;
3585 for (i = 0; list_table[i]; i++)
3587 *next = list_table[i];
3588 next = &(*next)->next;
3590 *next = NULL;
3591 SAFE_FREE ();
3593 if (! f->font_driver_list->on)
3594 { /* None of the drivers is enabled: enable them all.
3595 Happens if you set the list of drivers to (xft x) in your .emacs
3596 and then use it under w32 or ns. */
3597 for (list = f->font_driver_list; list; list = list->next)
3599 struct font_driver const *driver = list->driver;
3600 eassert (! list->on);
3601 if (! driver->start_for_frame
3602 || driver->start_for_frame (f) == 0)
3604 font_prepare_cache (f, driver);
3605 list->on = 1;
3611 for (list = f->font_driver_list; list; list = list->next)
3612 if (list->on)
3613 active_drivers = nconc2 (active_drivers, list1 (list->driver->type));
3614 return active_drivers;
3617 #if defined (HAVE_XFT) || defined (HAVE_FREETYPE)
3619 static void
3620 fset_font_data (struct frame *f, Lisp_Object val)
3622 f->font_data = val;
3625 void
3626 font_put_frame_data (struct frame *f, Lisp_Object driver, void *data)
3628 Lisp_Object val = assq_no_quit (driver, f->font_data);
3630 if (!data)
3631 fset_font_data (f, Fdelq (val, f->font_data));
3632 else
3634 if (NILP (val))
3635 fset_font_data (f, Fcons (Fcons (driver, make_mint_ptr (data)),
3636 f->font_data));
3637 else
3638 XSETCDR (val, make_mint_ptr (data));
3642 void *
3643 font_get_frame_data (struct frame *f, Lisp_Object driver)
3645 Lisp_Object val = assq_no_quit (driver, f->font_data);
3647 return NILP (val) ? NULL : xmint_pointer (XCDR (val));
3650 #endif /* HAVE_XFT || HAVE_FREETYPE */
3652 /* Sets attributes on a font. Any properties that appear in ALIST and
3653 BOOLEAN_PROPERTIES or NON_BOOLEAN_PROPERTIES are set on the font.
3654 BOOLEAN_PROPERTIES and NON_BOOLEAN_PROPERTIES are NULL-terminated
3655 arrays of strings. This function is intended for use by the font
3656 drivers to implement their specific font_filter_properties. */
3657 void
3658 font_filter_properties (Lisp_Object font,
3659 Lisp_Object alist,
3660 const char *const boolean_properties[],
3661 const char *const non_boolean_properties[])
3663 Lisp_Object it;
3664 int i;
3666 /* Set boolean values to Qt or Qnil. */
3667 for (i = 0; boolean_properties[i] != NULL; ++i)
3668 for (it = alist; ! NILP (it); it = XCDR (it))
3670 Lisp_Object key = XCAR (XCAR (it));
3671 Lisp_Object val = XCDR (XCAR (it));
3672 char *keystr = SSDATA (SYMBOL_NAME (key));
3674 if (strcmp (boolean_properties[i], keystr) == 0)
3676 const char *str = INTEGERP (val) ? (XINT (val) ? "true" : "false")
3677 : SYMBOLP (val) ? SSDATA (SYMBOL_NAME (val))
3678 : "true";
3680 if (strcmp ("false", str) == 0 || strcmp ("False", str) == 0
3681 || strcmp ("FALSE", str) == 0 || strcmp ("FcFalse", str) == 0
3682 || strcmp ("off", str) == 0 || strcmp ("OFF", str) == 0
3683 || strcmp ("Off", str) == 0)
3684 val = Qnil;
3685 else
3686 val = Qt;
3688 Ffont_put (font, key, val);
3692 for (i = 0; non_boolean_properties[i] != NULL; ++i)
3693 for (it = alist; ! NILP (it); it = XCDR (it))
3695 Lisp_Object key = XCAR (XCAR (it));
3696 Lisp_Object val = XCDR (XCAR (it));
3697 char *keystr = SSDATA (SYMBOL_NAME (key));
3698 if (strcmp (non_boolean_properties[i], keystr) == 0)
3699 Ffont_put (font, key, val);
3704 /* Return the font used to draw character C by FACE at buffer position
3705 POS in window W. If STRING is non-nil, it is a string containing C
3706 at index POS. If C is negative, get C from the current buffer or
3707 STRING. */
3709 static Lisp_Object
3710 font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
3711 Lisp_Object string)
3713 struct frame *f;
3714 bool multibyte;
3715 Lisp_Object font_object;
3717 multibyte = (NILP (string)
3718 ? ! NILP (BVAR (current_buffer, enable_multibyte_characters))
3719 : STRING_MULTIBYTE (string));
3720 if (c < 0)
3722 if (NILP (string))
3724 if (multibyte)
3726 ptrdiff_t pos_byte = CHAR_TO_BYTE (pos);
3728 c = FETCH_CHAR (pos_byte);
3730 else
3731 c = FETCH_BYTE (pos);
3733 else
3735 unsigned char *str;
3737 multibyte = STRING_MULTIBYTE (string);
3738 if (multibyte)
3740 ptrdiff_t pos_byte = string_char_to_byte (string, pos);
3742 str = SDATA (string) + pos_byte;
3743 c = STRING_CHAR (str);
3745 else
3746 c = SDATA (string)[pos];
3750 f = XFRAME (w->frame);
3751 if (! FRAME_WINDOW_P (f))
3752 return Qnil;
3753 if (! face)
3755 int face_id;
3756 ptrdiff_t endptr;
3758 if (STRINGP (string))
3759 face_id = face_at_string_position (w, string, pos, 0, &endptr,
3760 DEFAULT_FACE_ID, false);
3761 else
3762 face_id = face_at_buffer_position (w, pos, &endptr,
3763 pos + 100, false, -1);
3764 face = FACE_FROM_ID (f, face_id);
3766 if (multibyte)
3768 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3769 face = FACE_FROM_ID (f, face_id);
3771 if (! face->font)
3772 return Qnil;
3774 XSETFONT (font_object, face->font);
3775 return font_object;
3779 #ifdef HAVE_WINDOW_SYSTEM
3781 /* Check how many characters after character/byte position POS/POS_BYTE
3782 (at most to *LIMIT) can be displayed by the same font in the window W.
3783 FACE, if non-NULL, is the face selected for the character at POS.
3784 If STRING is not nil, it is the string to check instead of the current
3785 buffer. In that case, FACE must be not NULL.
3787 The return value is the font-object for the character at POS.
3788 *LIMIT is set to the position where that font can't be used.
3790 It is assured that the current buffer (or STRING) is multibyte. */
3792 Lisp_Object
3793 font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
3794 struct window *w, struct face *face, Lisp_Object string)
3796 ptrdiff_t ignore;
3797 int c;
3798 Lisp_Object font_object = Qnil;
3800 if (!face)
3802 struct frame *f = XFRAME (w->frame);
3803 int face_id;
3805 if (NILP (string))
3806 face_id = face_at_buffer_position (w, pos, &ignore, *limit,
3807 false, -1);
3808 else
3810 face_id =
3811 NILP (Vface_remapping_alist)
3812 ? DEFAULT_FACE_ID
3813 : lookup_basic_face (w, f, DEFAULT_FACE_ID);
3815 face_id = face_at_string_position (w, string, pos, 0, &ignore,
3816 face_id, false);
3818 face = FACE_FROM_ID (f, face_id);
3821 while (pos < *limit)
3823 Lisp_Object category;
3825 if (NILP (string))
3826 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3827 else
3828 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3829 category = CHAR_TABLE_REF (Vunicode_category_table, c);
3830 if (INTEGERP (category)
3831 && (XINT (category) == UNICODE_CATEGORY_Cf
3832 || CHAR_VARIATION_SELECTOR_P (c)))
3833 continue;
3834 if (NILP (font_object))
3836 font_object = font_for_char (face, c, pos - 1, string);
3837 if (NILP (font_object))
3838 return Qnil;
3839 continue;
3841 if (font_encode_char (font_object, c) == FONT_INVALID_CODE)
3842 *limit = pos - 1;
3844 return font_object;
3846 #endif
3849 /* Lisp API. */
3851 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3852 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3853 Return nil otherwise.
3854 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3855 which kind of font it is. It must be one of `font-spec', `font-entity',
3856 `font-object'. */)
3857 (Lisp_Object object, Lisp_Object extra_type)
3859 if (NILP (extra_type))
3860 return (FONTP (object) ? Qt : Qnil);
3861 if (EQ (extra_type, Qfont_spec))
3862 return (FONT_SPEC_P (object) ? Qt : Qnil);
3863 if (EQ (extra_type, Qfont_entity))
3864 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3865 if (EQ (extra_type, Qfont_object))
3866 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3867 wrong_type_argument (intern ("font-extra-type"), extra_type);
3870 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3871 doc: /* Return a newly created font-spec with arguments as properties.
3873 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3874 valid font property name listed below:
3876 `:family', `:weight', `:slant', `:width'
3878 They are the same as face attributes of the same name. See
3879 `set-face-attribute'.
3881 `:foundry'
3883 VALUE must be a string or a symbol specifying the font foundry, e.g. `misc'.
3885 `:adstyle'
3887 VALUE must be a string or a symbol specifying the additional
3888 typographic style information of a font, e.g. `sans'.
3890 `:registry'
3892 VALUE must be a string or a symbol specifying the charset registry and
3893 encoding of a font, e.g. `iso8859-1'.
3895 `:size'
3897 VALUE must be a non-negative integer or a floating point number
3898 specifying the font size. It specifies the font size in pixels (if
3899 VALUE is an integer), or in points (if VALUE is a float).
3901 `:name'
3903 VALUE must be a string of XLFD-style or fontconfig-style font name.
3905 `:script'
3907 VALUE must be a symbol representing a script that the font must
3908 support. It may be a symbol representing a subgroup of a script
3909 listed in the variable `script-representative-chars'.
3911 `:lang'
3913 VALUE must be a symbol whose name is a two-letter ISO-639 language
3914 name, e.g. `ja'. The value is matched against the "Additional Style"
3915 field of the XLFD spec of a font, if it's non-empty, on X, and
3916 against the codepages supported by the font on w32.
3918 `:otf'
3920 VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
3921 required OpenType features.
3923 SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
3924 LANGSYS-TAG: OpenType language system tag symbol,
3925 or nil for the default language system.
3926 GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
3927 GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
3929 GSUB and GPOS may contain nil elements. In such a case, the font
3930 must not have any of the remaining elements.
3932 For instance, if the VALUE is `(thai nil nil (mark))', the font must
3933 be an OpenType font whose GPOS table of `thai' script's default
3934 language system must contain `mark' feature.
3936 usage: (font-spec ARGS...) */)
3937 (ptrdiff_t nargs, Lisp_Object *args)
3939 Lisp_Object spec = font_make_spec ();
3940 ptrdiff_t i;
3942 for (i = 0; i < nargs; i += 2)
3944 Lisp_Object key = args[i], val;
3946 CHECK_SYMBOL (key);
3947 if (i + 1 >= nargs)
3948 error ("No value for key `%s'", SDATA (SYMBOL_NAME (key)));
3949 val = args[i + 1];
3951 if (EQ (key, QCname))
3953 CHECK_STRING (val);
3954 if (font_parse_name (SSDATA (val), SBYTES (val), spec) < 0)
3955 error ("Invalid font name: %s", SSDATA (val));
3956 font_put_extra (spec, key, val);
3958 else
3960 int idx = get_font_prop_index (key);
3962 if (idx >= 0)
3964 val = font_prop_validate (idx, Qnil, val);
3965 if (idx < FONT_EXTRA_INDEX)
3966 ASET (spec, idx, val);
3967 else
3968 font_put_extra (spec, key, val);
3970 else
3971 font_put_extra (spec, key, font_prop_validate (0, key, val));
3974 return spec;
3977 /* Return a copy of FONT as a font-spec. For the sake of speed, this code
3978 relies on an internal stuff exposed from alloc.c and should be handled
3979 with care. */
3981 Lisp_Object
3982 copy_font_spec (Lisp_Object font)
3984 enum { font_spec_size = VECSIZE (struct font_spec) };
3985 Lisp_Object new_spec, tail, *pcdr;
3986 struct font_spec *spec;
3988 CHECK_FONT (font);
3990 /* Make an uninitialized font-spec object. */
3991 spec = (struct font_spec *) allocate_vector (font_spec_size);
3992 XSETPVECTYPESIZE (spec, PVEC_FONT, FONT_SPEC_MAX,
3993 font_spec_size - FONT_SPEC_MAX);
3995 spec->props[FONT_TYPE_INDEX] = spec->props[FONT_EXTRA_INDEX] = Qnil;
3997 /* Copy basic properties FONT_FOUNDRY_INDEX..FONT_AVGWIDTH_INDEX. */
3998 memcpy (spec->props + 1, XVECTOR (font)->contents + 1,
3999 (FONT_EXTRA_INDEX - 1) * word_size);
4001 /* Copy an alist of extra information but discard :font-entity property. */
4002 pcdr = spec->props + FONT_EXTRA_INDEX;
4003 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
4004 if (!EQ (XCAR (XCAR (tail)), QCfont_entity))
4006 *pcdr = Fcons (Fcons (XCAR (XCAR (tail)), CDR (XCAR (tail))), Qnil);
4007 pcdr = xcdr_addr (*pcdr);
4010 XSETFONT (new_spec, spec);
4011 return new_spec;
4014 /* Merge font-specs FROM and TO, and return a new font-spec.
4015 Every specified property in FROM overrides the corresponding
4016 property in TO. */
4017 Lisp_Object
4018 merge_font_spec (Lisp_Object from, Lisp_Object to)
4020 Lisp_Object extra, tail;
4021 int i;
4023 CHECK_FONT (from);
4024 CHECK_FONT (to);
4025 to = copy_font_spec (to);
4026 for (i = 0; i < FONT_EXTRA_INDEX; i++)
4027 ASET (to, i, AREF (from, i));
4028 extra = AREF (to, FONT_EXTRA_INDEX);
4029 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
4030 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
4032 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
4034 if (! NILP (slot))
4035 XSETCDR (slot, XCDR (XCAR (tail)));
4036 else
4037 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
4039 ASET (to, FONT_EXTRA_INDEX, extra);
4040 return to;
4043 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
4044 doc: /* Return the value of FONT's property KEY.
4045 FONT is a font-spec, a font-entity, or a font-object.
4046 KEY is any symbol, but these are reserved for specific meanings:
4047 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
4048 :size, :name, :script, :otf
4049 See the documentation of `font-spec' for their meanings.
4050 In addition, if FONT is a font-entity or a font-object, values of
4051 :script and :otf are different from those of a font-spec as below:
4053 The value of :script may be a list of scripts that are supported by the font.
4055 The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
4056 representing the OpenType features supported by the font by this form:
4057 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4058 SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
4059 Layout tags.
4061 In addition to the keys listed abobe, the following keys are reserved
4062 for the specific meanings as below:
4064 The value of :combining-capability is non-nil if the font-backend of
4065 FONT supports rendering of combining characters for non-OTF fonts. */)
4066 (Lisp_Object font, Lisp_Object key)
4068 int idx;
4069 Lisp_Object val;
4071 CHECK_FONT (font);
4072 CHECK_SYMBOL (key);
4074 idx = get_font_prop_index (key);
4075 if (idx >= FONT_WEIGHT_INDEX && idx <= FONT_WIDTH_INDEX)
4076 return font_style_symbolic (font, idx, 0);
4077 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4078 return AREF (font, idx);
4079 val = Fassq (key, AREF (font, FONT_EXTRA_INDEX));
4080 if (NILP (val) && FONT_OBJECT_P (font))
4082 struct font *fontp = XFONT_OBJECT (font);
4084 if (EQ (key, QCotf))
4086 if (fontp->driver->otf_capability)
4087 val = fontp->driver->otf_capability (fontp);
4088 else
4089 val = Fcons (Qnil, Qnil);
4091 else if (EQ (key, QCcombining_capability))
4093 if (fontp->driver->combining_capability)
4094 val = fontp->driver->combining_capability (fontp);
4097 else
4098 val = Fcdr (val);
4099 return val;
4102 #ifdef HAVE_WINDOW_SYSTEM
4104 DEFUN ("font-face-attributes", Ffont_face_attributes, Sfont_face_attributes, 1, 2, 0,
4105 doc: /* Return a plist of face attributes generated by FONT.
4106 FONT is a font name, a font-spec, a font-entity, or a font-object.
4107 The return value is a list of the form
4109 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
4111 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
4112 compatible with `set-face-attribute'. Some of these key-attribute pairs
4113 may be omitted from the list if they are not specified by FONT.
4115 The optional argument FRAME specifies the frame that the face attributes
4116 are to be displayed on. If omitted, the selected frame is used. */)
4117 (Lisp_Object font, Lisp_Object frame)
4119 struct frame *f = decode_live_frame (frame);
4120 Lisp_Object plist[10];
4121 Lisp_Object val;
4122 int n = 0;
4124 if (STRINGP (font))
4126 int fontset = fs_query_fontset (font, 0);
4127 Lisp_Object name = font;
4128 if (fontset >= 0)
4129 font = fontset_ascii (fontset);
4130 font = font_spec_from_name (name);
4131 if (! FONTP (font))
4132 signal_error ("Invalid font name", name);
4134 else if (! FONTP (font))
4135 signal_error ("Invalid font object", font);
4137 val = AREF (font, FONT_FAMILY_INDEX);
4138 if (! NILP (val))
4140 plist[n++] = QCfamily;
4141 plist[n++] = SYMBOL_NAME (val);
4144 val = AREF (font, FONT_SIZE_INDEX);
4145 if (INTEGERP (val))
4147 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
4148 int dpi = INTEGERP (font_dpi) ? XINT (font_dpi) : FRAME_RES_Y (f);
4149 plist[n++] = QCheight;
4150 plist[n++] = make_number (PIXEL_TO_POINT (XINT (val) * 10, dpi));
4152 else if (FLOATP (val))
4154 plist[n++] = QCheight;
4155 plist[n++] = make_number (10 * (int) XFLOAT_DATA (val));
4158 val = FONT_WEIGHT_FOR_FACE (font);
4159 if (! NILP (val))
4161 plist[n++] = QCweight;
4162 plist[n++] = val;
4165 val = FONT_SLANT_FOR_FACE (font);
4166 if (! NILP (val))
4168 plist[n++] = QCslant;
4169 plist[n++] = val;
4172 val = FONT_WIDTH_FOR_FACE (font);
4173 if (! NILP (val))
4175 plist[n++] = QCwidth;
4176 plist[n++] = val;
4179 return Flist (n, plist);
4182 #endif
4184 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
4185 doc: /* Set one property of FONT: give property KEY value VAL.
4186 FONT is a font-spec, a font-entity, or a font-object.
4188 If FONT is a font-spec, KEY can be any symbol. But if KEY is the one
4189 accepted by the function `font-spec' (which see), VAL must be what
4190 allowed in `font-spec'.
4192 If FONT is a font-entity or a font-object, KEY must not be the one
4193 accepted by `font-spec'. */)
4194 (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
4196 int idx;
4198 idx = get_font_prop_index (prop);
4199 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4201 CHECK_FONT_SPEC (font);
4202 ASET (font, idx, font_prop_validate (idx, Qnil, val));
4204 else
4206 if (EQ (prop, QCname)
4207 || EQ (prop, QCscript)
4208 || EQ (prop, QClang)
4209 || EQ (prop, QCotf))
4210 CHECK_FONT_SPEC (font);
4211 else
4212 CHECK_FONT (font);
4213 font_put_extra (font, prop, font_prop_validate (0, prop, val));
4215 return val;
4218 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
4219 doc: /* List available fonts matching FONT-SPEC on the current frame.
4220 Optional 2nd argument FRAME specifies the target frame.
4221 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4222 Optional 4th argument PREFER, if non-nil, is a font-spec to
4223 control the order of the returned list. Fonts are sorted by
4224 how close they are to PREFER. */)
4225 (Lisp_Object font_spec, Lisp_Object frame, Lisp_Object num, Lisp_Object prefer)
4227 struct frame *f = decode_live_frame (frame);
4228 Lisp_Object vec, list;
4229 EMACS_INT n = 0;
4231 CHECK_FONT_SPEC (font_spec);
4232 if (! NILP (num))
4234 CHECK_NUMBER (num);
4235 n = XINT (num);
4236 if (n <= 0)
4237 return Qnil;
4239 if (! NILP (prefer))
4240 CHECK_FONT_SPEC (prefer);
4242 list = font_list_entities (f, font_spec);
4243 if (NILP (list))
4244 return Qnil;
4245 if (NILP (XCDR (list))
4246 && ASIZE (XCAR (list)) == 1)
4247 return list1 (AREF (XCAR (list), 0));
4249 if (! NILP (prefer))
4250 vec = font_sort_entities (list, prefer, f, 0);
4251 else
4252 vec = font_vconcat_entity_vectors (list);
4253 if (n == 0 || n >= ASIZE (vec))
4254 list = CALLN (Fappend, vec, Qnil);
4255 else
4257 for (list = Qnil, n--; n >= 0; n--)
4258 list = Fcons (AREF (vec, n), list);
4260 return list;
4263 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
4264 doc: /* List available font families on the current frame.
4265 If FRAME is omitted or nil, the selected frame is used. */)
4266 (Lisp_Object frame)
4268 struct frame *f = decode_live_frame (frame);
4269 struct font_driver_list *driver_list;
4270 Lisp_Object list = Qnil;
4272 for (driver_list = f->font_driver_list; driver_list;
4273 driver_list = driver_list->next)
4274 if (driver_list->driver->list_family)
4276 Lisp_Object val = driver_list->driver->list_family (f);
4277 Lisp_Object tail = list;
4279 for (; CONSP (val); val = XCDR (val))
4280 if (NILP (Fmemq (XCAR (val), tail))
4281 && SYMBOLP (XCAR (val)))
4282 list = Fcons (SYMBOL_NAME (XCAR (val)), list);
4284 return list;
4287 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
4288 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
4289 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4290 (Lisp_Object font_spec, Lisp_Object frame)
4292 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
4294 if (CONSP (val))
4295 val = XCAR (val);
4296 return val;
4299 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
4300 doc: /* Return XLFD name of FONT.
4301 FONT is a font-spec, font-entity, or font-object.
4302 If the name is too long for XLFD (maximum 255 chars), return nil.
4303 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4304 the consecutive wildcards are folded into one. */)
4305 (Lisp_Object font, Lisp_Object fold_wildcards)
4307 char name[256];
4308 int namelen, pixel_size = 0;
4310 CHECK_FONT (font);
4312 if (FONT_OBJECT_P (font))
4314 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
4316 if (STRINGP (font_name)
4317 && SDATA (font_name)[0] == '-')
4319 if (NILP (fold_wildcards))
4320 return font_name;
4321 lispstpcpy (name, font_name);
4322 namelen = SBYTES (font_name);
4323 goto done;
4325 pixel_size = XFONT_OBJECT (font)->pixel_size;
4327 namelen = font_unparse_xlfd (font, pixel_size, name, 256);
4328 if (namelen < 0)
4329 return Qnil;
4330 done:
4331 if (! NILP (fold_wildcards))
4333 char *p0 = name, *p1;
4335 while ((p1 = strstr (p0, "-*-*")))
4337 strcpy (p1, p1 + 2);
4338 namelen -= 2;
4339 p0 = p1;
4343 return make_string (name, namelen);
4346 void
4347 clear_font_cache (struct frame *f)
4349 struct font_driver_list *driver_list = f->font_driver_list;
4351 for (; driver_list; driver_list = driver_list->next)
4352 if (driver_list->on)
4354 Lisp_Object val, tmp, cache = driver_list->driver->get_cache (f);
4356 val = XCDR (cache);
4357 while (eassert (CONSP (val)),
4358 ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
4359 val = XCDR (val);
4360 tmp = XCDR (XCAR (val));
4361 if (XINT (XCAR (tmp)) == 0)
4363 font_clear_cache (f, XCAR (val), driver_list->driver);
4364 XSETCDR (cache, XCDR (val));
4369 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
4370 doc: /* Clear font cache of each frame. */)
4371 (void)
4373 Lisp_Object list, frame;
4375 FOR_EACH_FRAME (list, frame)
4376 clear_font_cache (XFRAME (frame));
4378 return Qnil;
4382 void
4383 font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object)
4385 struct font *font = XFONT_OBJECT (font_object);
4386 unsigned code = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
4387 struct font_metrics metrics;
4389 LGLYPH_SET_CODE (glyph, code);
4390 font->driver->text_extents (font, &code, 1, &metrics);
4391 LGLYPH_SET_LBEARING (glyph, metrics.lbearing);
4392 LGLYPH_SET_RBEARING (glyph, metrics.rbearing);
4393 LGLYPH_SET_WIDTH (glyph, metrics.width);
4394 LGLYPH_SET_ASCENT (glyph, metrics.ascent);
4395 LGLYPH_SET_DESCENT (glyph, metrics.descent);
4399 DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0,
4400 doc: /* Shape the glyph-string GSTRING.
4401 Shaping means substituting glyphs and/or adjusting positions of glyphs
4402 to get the correct visual image of character sequences set in the
4403 header of the glyph-string.
4405 If the shaping was successful, the value is GSTRING itself or a newly
4406 created glyph-string. Otherwise, the value is nil.
4408 See the documentation of `composition-get-gstring' for the format of
4409 GSTRING. */)
4410 (Lisp_Object gstring)
4412 struct font *font;
4413 Lisp_Object font_object, n, glyph;
4414 ptrdiff_t i, from, to;
4416 if (! composition_gstring_p (gstring))
4417 signal_error ("Invalid glyph-string: ", gstring);
4418 if (! NILP (LGSTRING_ID (gstring)))
4419 return gstring;
4420 font_object = LGSTRING_FONT (gstring);
4421 CHECK_FONT_OBJECT (font_object);
4422 font = XFONT_OBJECT (font_object);
4423 if (! font->driver->shape)
4424 return Qnil;
4426 /* Try at most three times with larger gstring each time. */
4427 for (i = 0; i < 3; i++)
4429 n = font->driver->shape (gstring);
4430 if (INTEGERP (n))
4431 break;
4432 gstring = larger_vector (gstring,
4433 LGSTRING_GLYPH_LEN (gstring), -1);
4435 if (i == 3 || XINT (n) == 0)
4436 return Qnil;
4437 if (XINT (n) < LGSTRING_GLYPH_LEN (gstring))
4438 LGSTRING_SET_GLYPH (gstring, XINT (n), Qnil);
4440 /* Check FROM_IDX and TO_IDX of each GLYPH in GSTRING to assure that
4441 GLYPHS covers all characters (except for the last few ones) in
4442 GSTRING. More formally, provided that NCHARS is the number of
4443 characters in GSTRING and GLYPHS[i] is the ith glyph, FROM_IDX
4444 and TO_IDX of each glyph must satisfy these conditions:
4446 GLYPHS[0].FROM_IDX == 0
4447 GLYPHS[i].FROM_IDX <= GLYPHS[i].TO_IDX
4448 if (GLYPHS[i].FROM_IDX == GLYPHS[i-1].FROM_IDX)
4449 ;; GLYPHS[i] and GLYPHS[i-1] belongs to the same grapheme cluster
4450 GLYPHS[i].TO_IDX == GLYPHS[i-1].TO_IDX
4451 else
4452 ;; Be sure to cover all characters.
4453 GLYPHS[i].FROM_IDX == GLYPHS[i-1].TO_IDX + 1 */
4454 glyph = LGSTRING_GLYPH (gstring, 0);
4455 from = LGLYPH_FROM (glyph);
4456 to = LGLYPH_TO (glyph);
4457 if (from != 0 || to < from)
4458 goto shaper_error;
4459 for (i = 1; i < LGSTRING_GLYPH_LEN (gstring); i++)
4461 glyph = LGSTRING_GLYPH (gstring, i);
4462 if (NILP (glyph))
4463 break;
4464 if (! (LGLYPH_FROM (glyph) <= LGLYPH_TO (glyph)
4465 && (LGLYPH_FROM (glyph) == from
4466 ? LGLYPH_TO (glyph) == to
4467 : LGLYPH_FROM (glyph) == to + 1)))
4468 goto shaper_error;
4469 from = LGLYPH_FROM (glyph);
4470 to = LGLYPH_TO (glyph);
4472 return composition_gstring_put_cache (gstring, XINT (n));
4474 shaper_error:
4475 return Qnil;
4478 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
4479 2, 2, 0,
4480 doc: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4481 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4482 where
4483 VARIATION-SELECTOR is a character code of variation selection
4484 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4485 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4486 (Lisp_Object font_object, Lisp_Object character)
4488 unsigned variations[256];
4489 struct font *font;
4490 int i, n;
4491 Lisp_Object val;
4493 CHECK_FONT_OBJECT (font_object);
4494 CHECK_CHARACTER (character);
4495 font = XFONT_OBJECT (font_object);
4496 if (! font->driver->get_variation_glyphs)
4497 return Qnil;
4498 n = font->driver->get_variation_glyphs (font, XINT (character), variations);
4499 if (! n)
4500 return Qnil;
4501 val = Qnil;
4502 for (i = 0; i < 255; i++)
4503 if (variations[i])
4505 int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
4506 Lisp_Object code = INTEGER_TO_CONS (variations[i]);
4507 val = Fcons (Fcons (make_number (vs), code), val);
4509 return val;
4512 /* Return a description of the font at POSITION in the current buffer.
4513 If the 2nd optional arg CH is non-nil, it is a character to check
4514 the font instead of the character at POSITION.
4516 For a graphical display, return a cons (FONT-OBJECT . GLYPH-CODE).
4517 FONT-OBJECT is the font for the character at POSITION in the current
4518 buffer. This is computed from all the text properties and overlays
4519 that apply to POSITION. POSITION may be nil, in which case,
4520 FONT-SPEC is the font for displaying the character CH with the
4521 default face. GLYPH-CODE is the glyph code in the font to use for
4522 the character.
4524 For a text terminal, return a nonnegative integer glyph code for
4525 the character, or a negative integer if the character is not
4526 displayable. Terminal glyph codes are system-dependent integers
4527 that represent displayable characters: for example, on a Linux x86
4528 console they represent VGA code points.
4530 It returns nil in the following cases:
4532 (1) The window system doesn't have a font for the character (thus
4533 it is displayed by an empty box).
4535 (2) The character code is invalid.
4537 (3) If POSITION is not nil, and the current buffer is not displayed
4538 in any window.
4540 (4) For a text terminal, the terminal does not report glyph codes.
4542 In addition, the returned font name may not take into account of
4543 such redisplay engine hooks as what used in jit-lock-mode if
4544 POSITION is currently not visible. */
4547 DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
4548 doc: /* For internal use only. */)
4549 (Lisp_Object position, Lisp_Object ch)
4551 ptrdiff_t pos, pos_byte, dummy;
4552 int face_id;
4553 int c;
4554 struct frame *f;
4556 if (NILP (position))
4558 CHECK_CHARACTER (ch);
4559 c = XINT (ch);
4560 f = XFRAME (selected_frame);
4561 face_id = lookup_basic_face (NULL, f, DEFAULT_FACE_ID);
4562 pos = -1;
4564 else
4566 Lisp_Object window;
4567 struct window *w;
4569 CHECK_NUMBER_COERCE_MARKER (position);
4570 if (! (BEGV <= XINT (position) && XINT (position) < ZV))
4571 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4572 pos = XINT (position);
4573 pos_byte = CHAR_TO_BYTE (pos);
4574 if (NILP (ch))
4575 c = FETCH_CHAR (pos_byte);
4576 else
4578 CHECK_NATNUM (ch);
4579 c = XINT (ch);
4581 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
4582 if (NILP (window))
4583 return Qnil;
4584 w = XWINDOW (window);
4585 f = XFRAME (w->frame);
4586 face_id = face_at_buffer_position (w, pos, &dummy,
4587 pos + 100, false, -1);
4589 if (! CHAR_VALID_P (c))
4590 return Qnil;
4592 if (! FRAME_WINDOW_P (f))
4593 return terminal_glyph_code (FRAME_TERMINAL (f), c);
4595 /* We need the basic faces to be valid below, so recompute them if
4596 some code just happened to clear the face cache. */
4597 if (FRAME_FACE_CACHE (f)->used == 0)
4598 recompute_basic_faces (f);
4600 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
4601 struct face *face = FACE_FROM_ID (f, face_id);
4602 if (! face->font)
4603 return Qnil;
4604 unsigned code = face->font->driver->encode_char (face->font, c);
4605 if (code == FONT_INVALID_CODE)
4606 return Qnil;
4607 Lisp_Object font_object;
4608 XSETFONT (font_object, face->font);
4609 return Fcons (font_object, INTEGER_TO_CONS (code));
4612 #if 0
4614 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
4615 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
4616 OTF-FEATURES specifies which features to apply in this format:
4617 (SCRIPT LANGSYS GSUB GPOS)
4618 where
4619 SCRIPT is a symbol specifying a script tag of OpenType,
4620 LANGSYS is a symbol specifying a langsys tag of OpenType,
4621 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4623 If LANGSYS is nil, the default langsys is selected.
4625 The features are applied in the order they appear in the list. The
4626 symbol `*' means to apply all available features not present in this
4627 list, and the remaining features are ignored. For instance, (vatu
4628 pstf * haln) is to apply vatu and pstf in this order, then to apply
4629 all available features other than vatu, pstf, and haln.
4631 The features are applied to the glyphs in the range FROM and TO of
4632 the glyph-string GSTRING-IN.
4634 If some feature is actually applicable, the resulting glyphs are
4635 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4636 this case, the value is the number of produced glyphs.
4638 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4639 the value is 0.
4641 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4642 produced in GSTRING-OUT, and the value is nil.
4644 See the documentation of `composition-get-gstring' for the format of
4645 glyph-string. */)
4646 (Lisp_Object otf_features, Lisp_Object gstring_in, Lisp_Object from, Lisp_Object to, Lisp_Object gstring_out, Lisp_Object index)
4648 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
4649 Lisp_Object val;
4650 struct font *font;
4651 int len, num;
4653 check_otf_features (otf_features);
4654 CHECK_FONT_OBJECT (font_object);
4655 font = XFONT_OBJECT (font_object);
4656 if (! font->driver->otf_drive)
4657 error ("Font backend %s can't drive OpenType GSUB table",
4658 SDATA (SYMBOL_NAME (font->driver->type)));
4659 CHECK_CONS (otf_features);
4660 CHECK_SYMBOL (XCAR (otf_features));
4661 val = XCDR (otf_features);
4662 CHECK_SYMBOL (XCAR (val));
4663 val = XCDR (otf_features);
4664 if (! NILP (val))
4665 CHECK_CONS (val);
4666 len = check_gstring (gstring_in);
4667 CHECK_VECTOR (gstring_out);
4668 CHECK_NATNUM (from);
4669 CHECK_NATNUM (to);
4670 CHECK_NATNUM (index);
4672 if (XINT (from) >= XINT (to) || XINT (to) > len)
4673 args_out_of_range_3 (from, to, make_number (len));
4674 if (XINT (index) >= ASIZE (gstring_out))
4675 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4676 num = font->driver->otf_drive (font, otf_features,
4677 gstring_in, XINT (from), XINT (to),
4678 gstring_out, XINT (index), 0);
4679 if (num < 0)
4680 return Qnil;
4681 return make_number (num);
4684 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4685 3, 3, 0,
4686 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4687 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4688 in this format:
4689 (SCRIPT LANGSYS FEATURE ...)
4690 See the documentation of `font-drive-otf' for more detail.
4692 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4693 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4694 character code corresponding to the glyph or nil if there's no
4695 corresponding character. */)
4696 (Lisp_Object font_object, Lisp_Object character, Lisp_Object otf_features)
4698 struct font *font = CHECK_FONT_GET_OBJECT (font_object);
4699 Lisp_Object gstring_in, gstring_out, g;
4700 Lisp_Object alternates;
4701 int i, num;
4703 if (! font->driver->otf_drive)
4704 error ("Font backend %s can't drive OpenType GSUB table",
4705 SDATA (SYMBOL_NAME (font->driver->type)));
4706 CHECK_CHARACTER (character);
4707 CHECK_CONS (otf_features);
4709 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4710 g = LGSTRING_GLYPH (gstring_in, 0);
4711 LGLYPH_SET_CHAR (g, XINT (character));
4712 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4713 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4714 gstring_out, 0, 1)) < 0)
4715 gstring_out = Ffont_make_gstring (font_object,
4716 make_number (ASIZE (gstring_out) * 2));
4717 alternates = Qnil;
4718 for (i = 0; i < num; i++)
4720 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4721 int c = LGLYPH_CHAR (g);
4722 unsigned code = LGLYPH_CODE (g);
4724 alternates = Fcons (Fcons (make_number (code),
4725 c > 0 ? make_number (c) : Qnil),
4726 alternates);
4728 return Fnreverse (alternates);
4730 #endif /* 0 */
4732 #ifdef FONT_DEBUG
4734 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4735 doc: /* Open FONT-ENTITY. */)
4736 (Lisp_Object font_entity, Lisp_Object size, Lisp_Object frame)
4738 EMACS_INT isize;
4739 struct frame *f = decode_live_frame (frame);
4741 CHECK_FONT_ENTITY (font_entity);
4743 if (NILP (size))
4744 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4745 else
4747 CHECK_NUMBER_OR_FLOAT (size);
4748 if (FLOATP (size))
4749 isize = POINT_TO_PIXEL (XFLOAT_DATA (size), FRAME_RES_Y (f));
4750 else
4751 isize = XINT (size);
4752 if (! (INT_MIN <= isize && isize <= INT_MAX))
4753 args_out_of_range (font_entity, size);
4754 if (isize == 0)
4755 isize = 120;
4757 return font_open_entity (f, font_entity, isize);
4760 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4761 doc: /* Close FONT-OBJECT. */)
4762 (Lisp_Object font_object, Lisp_Object frame)
4764 CHECK_FONT_OBJECT (font_object);
4765 font_close_object (decode_live_frame (frame), font_object);
4766 return Qnil;
4769 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4770 doc: /* Return information about FONT-OBJECT.
4771 The value is a vector:
4772 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4773 CAPABILITY ]
4775 NAME is the font name, a string (or nil if the font backend doesn't
4776 provide a name).
4778 FILENAME is the font file name, a string (or nil if the font backend
4779 doesn't provide a file name).
4781 PIXEL-SIZE is a pixel size by which the font is opened.
4783 SIZE is a maximum advance width of the font in pixels.
4785 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4786 pixels.
4788 CAPABILITY is a list whose first element is a symbol representing the
4789 font format (x, opentype, truetype, type1, pcf, or bdf) and the
4790 remaining elements describe the details of the font capability.
4792 If the font is OpenType font, the form of the list is
4793 (opentype GSUB GPOS)
4794 where GSUB shows which "GSUB" features the font supports, and GPOS
4795 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4796 lists of the format:
4797 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4799 If the font is not OpenType font, currently the length of the form is
4800 one.
4802 SCRIPT is a symbol representing OpenType script tag.
4804 LANGSYS is a symbol representing OpenType langsys tag, or nil
4805 representing the default langsys.
4807 FEATURE is a symbol representing OpenType feature tag.
4809 If the font is not OpenType font, CAPABILITY is nil. */)
4810 (Lisp_Object font_object)
4812 struct font *font = CHECK_FONT_GET_OBJECT (font_object);
4813 Lisp_Object val = make_uninit_vector (9);
4815 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4816 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4817 ASET (val, 2, make_number (font->pixel_size));
4818 ASET (val, 3, make_number (font->max_width));
4819 ASET (val, 4, make_number (font->ascent));
4820 ASET (val, 5, make_number (font->descent));
4821 ASET (val, 6, make_number (font->space_width));
4822 ASET (val, 7, make_number (font->average_width));
4823 if (font->driver->otf_capability)
4824 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4825 else
4826 ASET (val, 8, Qnil);
4827 return val;
4830 DEFUN ("font-get-glyphs", Ffont_get_glyphs, Sfont_get_glyphs, 3, 4, 0,
4831 doc:
4832 /* Return a vector of FONT-OBJECT's glyphs for the specified characters.
4833 FROM and TO are positions (integers or markers) specifying a region
4834 of the current buffer, and can be in either order. If the optional
4835 fourth arg OBJECT is not nil, it is a string or a vector containing
4836 the target characters between indices FROM and TO, which are treated
4837 as in `substring'.
4839 Each element is a vector containing information of a glyph in this format:
4840 [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
4841 where
4842 FROM is an index numbers of a character the glyph corresponds to.
4843 TO is the same as FROM.
4844 C is the character of the glyph.
4845 CODE is the glyph-code of C in FONT-OBJECT.
4846 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
4847 ADJUSTMENT is always nil.
4848 If FONT-OBJECT doesn't have a glyph for a character,
4849 the corresponding element is nil. */)
4850 (Lisp_Object font_object, Lisp_Object from, Lisp_Object to,
4851 Lisp_Object object)
4853 struct font *font = CHECK_FONT_GET_OBJECT (font_object);
4854 ptrdiff_t i, len;
4855 Lisp_Object *chars, vec;
4856 USE_SAFE_ALLOCA;
4858 if (NILP (object))
4860 ptrdiff_t charpos, bytepos;
4862 validate_region (&from, &to);
4863 if (EQ (from, to))
4864 return Qnil;
4865 len = XFASTINT (to) - XFASTINT (from);
4866 SAFE_ALLOCA_LISP (chars, len);
4867 charpos = XFASTINT (from);
4868 bytepos = CHAR_TO_BYTE (charpos);
4869 for (i = 0; charpos < XFASTINT (to); i++)
4871 int c;
4872 FETCH_CHAR_ADVANCE (c, charpos, bytepos);
4873 chars[i] = make_number (c);
4876 else if (STRINGP (object))
4878 const unsigned char *p;
4879 ptrdiff_t ifrom, ito;
4881 validate_subarray (object, from, to, SCHARS (object), &ifrom, &ito);
4882 if (ifrom == ito)
4883 return Qnil;
4884 len = ito - ifrom;
4885 SAFE_ALLOCA_LISP (chars, len);
4886 p = SDATA (object);
4887 if (STRING_MULTIBYTE (object))
4889 int c;
4891 /* Skip IFROM characters from the beginning. */
4892 for (i = 0; i < ifrom; i++)
4893 c = STRING_CHAR_ADVANCE (p);
4895 /* Now fetch an interesting characters. */
4896 for (i = 0; i < len; i++)
4898 c = STRING_CHAR_ADVANCE (p);
4899 chars[i] = make_number (c);
4902 else
4903 for (i = 0; i < len; i++)
4904 chars[i] = make_number (p[ifrom + i]);
4906 else if (VECTORP (object))
4908 ptrdiff_t ifrom, ito;
4910 validate_subarray (object, from, to, ASIZE (object), &ifrom, &ito);
4911 if (ifrom == ito)
4912 return Qnil;
4913 len = ito - ifrom;
4914 for (i = 0; i < len; i++)
4916 Lisp_Object elt = AREF (object, ifrom + i);
4917 CHECK_CHARACTER (elt);
4919 chars = aref_addr (object, ifrom);
4921 else
4922 wrong_type_argument (Qarrayp, object);
4924 vec = make_uninit_vector (len);
4925 for (i = 0; i < len; i++)
4927 Lisp_Object g;
4928 int c = XFASTINT (chars[i]);
4929 unsigned code;
4930 struct font_metrics metrics;
4932 code = font->driver->encode_char (font, c);
4933 if (code == FONT_INVALID_CODE)
4935 ASET (vec, i, Qnil);
4936 continue;
4938 g = LGLYPH_NEW ();
4939 LGLYPH_SET_FROM (g, i);
4940 LGLYPH_SET_TO (g, i);
4941 LGLYPH_SET_CHAR (g, c);
4942 LGLYPH_SET_CODE (g, code);
4943 font->driver->text_extents (font, &code, 1, &metrics);
4944 LGLYPH_SET_WIDTH (g, metrics.width);
4945 LGLYPH_SET_LBEARING (g, metrics.lbearing);
4946 LGLYPH_SET_RBEARING (g, metrics.rbearing);
4947 LGLYPH_SET_ASCENT (g, metrics.ascent);
4948 LGLYPH_SET_DESCENT (g, metrics.descent);
4949 ASET (vec, i, g);
4951 if (! VECTORP (object))
4952 SAFE_FREE ();
4953 return vec;
4956 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4957 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4958 FONT is a font-spec, font-entity, or font-object. */)
4959 (Lisp_Object spec, Lisp_Object font)
4961 CHECK_FONT_SPEC (spec);
4962 CHECK_FONT (font);
4964 return (font_match_p (spec, font) ? Qt : Qnil);
4967 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4968 doc: /* Return a font-object for displaying a character at POSITION.
4969 Optional second arg WINDOW, if non-nil, is a window displaying
4970 the current buffer. It defaults to the currently selected window.
4971 Optional third arg STRING, if non-nil, is a string containing the target
4972 character at index specified by POSITION. */)
4973 (Lisp_Object position, Lisp_Object window, Lisp_Object string)
4975 struct window *w = decode_live_window (window);
4977 if (NILP (string))
4979 if (XBUFFER (w->contents) != current_buffer)
4980 error ("Specified window is not displaying the current buffer");
4981 CHECK_NUMBER_COERCE_MARKER (position);
4982 if (! (BEGV <= XINT (position) && XINT (position) < ZV))
4983 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4985 else
4987 CHECK_NUMBER (position);
4988 CHECK_STRING (string);
4989 if (! (0 <= XINT (position) && XINT (position) < SCHARS (string)))
4990 args_out_of_range (string, position);
4993 return font_at (-1, XINT (position), NULL, w, string);
4996 #if 0
4997 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4998 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4999 The value is a number of glyphs drawn.
5000 Type C-l to recover what previously shown. */)
5001 (Lisp_Object font_object, Lisp_Object string)
5003 Lisp_Object frame = selected_frame;
5004 struct frame *f = XFRAME (frame);
5005 struct font *font;
5006 struct face *face;
5007 int i, len, width;
5008 unsigned *code;
5010 CHECK_FONT_GET_OBJECT (font_object, font);
5011 CHECK_STRING (string);
5012 len = SCHARS (string);
5013 code = alloca (sizeof (unsigned) * len);
5014 for (i = 0; i < len; i++)
5016 Lisp_Object ch = Faref (string, make_number (i));
5017 Lisp_Object val;
5018 int c = XINT (ch);
5020 code[i] = font->driver->encode_char (font, c);
5021 if (code[i] == FONT_INVALID_CODE)
5022 break;
5024 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5025 face->fontp = font;
5026 if (font->driver->prepare_face)
5027 font->driver->prepare_face (f, face);
5028 width = font->driver->text_extents (font, code, i, NULL);
5029 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
5030 if (font->driver->done_face)
5031 font->driver->done_face (f, face);
5032 face->fontp = NULL;
5033 return make_number (len);
5035 #endif
5037 DEFUN ("frame-font-cache", Fframe_font_cache, Sframe_font_cache, 0, 1, 0,
5038 doc: /* Return FRAME's font cache. Mainly used for debugging.
5039 If FRAME is omitted or nil, use the selected frame. */)
5040 (Lisp_Object frame)
5042 #ifdef HAVE_WINDOW_SYSTEM
5043 struct frame *f = decode_live_frame (frame);
5045 if (FRAME_WINDOW_P (f))
5046 return FRAME_DISPLAY_INFO (f)->name_list_element;
5047 else
5048 #endif
5049 return Qnil;
5052 #endif /* FONT_DEBUG */
5054 #ifdef HAVE_WINDOW_SYSTEM
5056 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
5057 doc: /* Return information about a font named NAME on frame FRAME.
5058 If FRAME is omitted or nil, use the selected frame.
5060 The returned value is a vector of 14 elements:
5061 [ OPENED-NAME FULL-NAME SIZE HEIGHT BASELINE-OFFSET RELATIVE-COMPOSE
5062 DEFAULT-ASCENT MAX-WIDTH ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
5063 FILENAME CAPABILITY ]
5064 where
5065 OPENED-NAME is the name used for opening the font,
5066 FULL-NAME is the full name of the font,
5067 SIZE is the pixelsize of the font,
5068 HEIGHT is the pixel-height of the font (i.e., ascent + descent),
5069 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
5070 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
5071 how to compose characters,
5072 MAX-WIDTH is the maximum advance width of the font,
5073 ASCENT, DESCENT, SPACE-WIDTH, and AVERAGE-WIDTH are metrics of
5074 the font in pixels,
5075 FILENAME is the font file name, a string (or nil if the font backend
5076 doesn't provide a file name).
5077 CAPABILITY is a list whose first element is a symbol representing the
5078 font format, one of `x', `opentype', `truetype', `type1', `pcf', or `bdf'.
5079 The remaining elements describe the details of the font capabilities,
5080 as follows:
5082 If the font is OpenType font, the form of the list is
5083 (opentype GSUB GPOS)
5084 where GSUB shows which "GSUB" features the font supports, and GPOS
5085 shows which "GPOS" features the font supports. Both GSUB and GPOS are
5086 lists of the form:
5087 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
5089 where
5090 SCRIPT is a symbol representing OpenType script tag.
5091 LANGSYS is a symbol representing OpenType langsys tag, or nil
5092 representing the default langsys.
5093 FEATURE is a symbol representing OpenType feature tag.
5095 If the font is not an OpenType font, there are no elements
5096 in CAPABILITY except the font format symbol.
5098 If the named font is not yet loaded, return nil. */)
5099 (Lisp_Object name, Lisp_Object frame)
5101 struct frame *f;
5102 struct font *font;
5103 Lisp_Object info;
5104 Lisp_Object font_object;
5106 if (! FONTP (name))
5107 CHECK_STRING (name);
5108 f = decode_window_system_frame (frame);
5110 if (STRINGP (name))
5112 int fontset = fs_query_fontset (name, 0);
5114 if (fontset >= 0)
5115 name = fontset_ascii (fontset);
5116 font_object = font_open_by_name (f, name);
5118 else if (FONT_OBJECT_P (name))
5119 font_object = name;
5120 else if (FONT_ENTITY_P (name))
5121 font_object = font_open_entity (f, name, 0);
5122 else
5124 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5125 Lisp_Object entity = font_matching_entity (f, face->lface, name);
5127 font_object = ! NILP (entity) ? font_open_entity (f, entity, 0) : Qnil;
5129 if (NILP (font_object))
5130 return Qnil;
5131 font = XFONT_OBJECT (font_object);
5133 info = make_uninit_vector (14);
5134 ASET (info, 0, AREF (font_object, FONT_NAME_INDEX));
5135 ASET (info, 1, AREF (font_object, FONT_FULLNAME_INDEX));
5136 ASET (info, 2, make_number (font->pixel_size));
5137 ASET (info, 3, make_number (font->height));
5138 ASET (info, 4, make_number (font->baseline_offset));
5139 ASET (info, 5, make_number (font->relative_compose));
5140 ASET (info, 6, make_number (font->default_ascent));
5141 ASET (info, 7, make_number (font->max_width));
5142 ASET (info, 8, make_number (font->ascent));
5143 ASET (info, 9, make_number (font->descent));
5144 ASET (info, 10, make_number (font->space_width));
5145 ASET (info, 11, make_number (font->average_width));
5146 ASET (info, 12, AREF (font_object, FONT_FILE_INDEX));
5147 if (font->driver->otf_capability)
5148 ASET (info, 13, Fcons (Qopentype, font->driver->otf_capability (font)));
5149 else
5150 ASET (info, 13, Qnil);
5152 #if 0
5153 /* As font_object is still in FONT_OBJLIST of the entity, we can't
5154 close it now. Perhaps, we should manage font-objects
5155 by `reference-count'. */
5156 font_close_object (f, font_object);
5157 #endif
5158 return info;
5160 #endif
5163 #define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, ARRAYELTS (TBL))
5165 static Lisp_Object
5166 build_style_table (const struct table_entry *entry, int nelement)
5168 int i, j;
5169 Lisp_Object table, elt;
5171 table = make_uninit_vector (nelement);
5172 for (i = 0; i < nelement; i++)
5174 for (j = 0; entry[i].names[j]; j++);
5175 elt = Fmake_vector (make_number (j + 1), Qnil);
5176 ASET (elt, 0, make_number (entry[i].numeric));
5177 for (j = 0; entry[i].names[j]; j++)
5178 ASET (elt, j + 1, intern_c_string (entry[i].names[j]));
5179 ASET (table, i, elt);
5181 return table;
5184 /* The deferred font-log data of the form [ACTION ARG RESULT].
5185 If ACTION is not nil, that is added to the log when font_add_log is
5186 called next time. At that time, ACTION is set back to nil. */
5187 static Lisp_Object Vfont_log_deferred;
5189 /* Prepend the font-related logging data in Vfont_log if it is not
5190 t. ACTION describes a kind of font-related action (e.g. listing,
5191 opening), ARG is the argument for the action, and RESULT is the
5192 result of the action. */
5193 void
5194 font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
5196 Lisp_Object val;
5197 int i;
5199 if (EQ (Vfont_log, Qt))
5200 return;
5201 if (STRINGP (AREF (Vfont_log_deferred, 0)))
5203 char *str = SSDATA (AREF (Vfont_log_deferred, 0));
5205 ASET (Vfont_log_deferred, 0, Qnil);
5206 font_add_log (str, AREF (Vfont_log_deferred, 1),
5207 AREF (Vfont_log_deferred, 2));
5210 if (FONTP (arg))
5212 Lisp_Object tail, elt;
5213 AUTO_STRING (equal, "=");
5215 val = Ffont_xlfd_name (arg, Qt);
5216 for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail);
5217 tail = XCDR (tail))
5219 elt = XCAR (tail);
5220 if (EQ (XCAR (elt), QCscript)
5221 && SYMBOLP (XCDR (elt)))
5222 val = concat3 (val, SYMBOL_NAME (QCscript),
5223 concat2 (equal, SYMBOL_NAME (XCDR (elt))));
5224 else if (EQ (XCAR (elt), QClang)
5225 && SYMBOLP (XCDR (elt)))
5226 val = concat3 (val, SYMBOL_NAME (QClang),
5227 concat2 (equal, SYMBOL_NAME (XCDR (elt))));
5228 else if (EQ (XCAR (elt), QCotf)
5229 && CONSP (XCDR (elt)) && SYMBOLP (XCAR (XCDR (elt))))
5230 val = concat3 (val, SYMBOL_NAME (QCotf),
5231 concat2 (equal, SYMBOL_NAME (XCAR (XCDR (elt)))));
5233 arg = val;
5236 if (CONSP (result)
5237 && VECTORP (XCAR (result))
5238 && ASIZE (XCAR (result)) > 0
5239 && FONTP (AREF (XCAR (result), 0)))
5240 result = font_vconcat_entity_vectors (result);
5241 if (FONTP (result))
5243 val = Ffont_xlfd_name (result, Qt);
5244 if (! FONT_SPEC_P (result))
5246 AUTO_STRING (colon, ":");
5247 val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)),
5248 colon, val);
5250 result = val;
5252 else if (CONSP (result))
5254 Lisp_Object tail;
5255 result = Fcopy_sequence (result);
5256 for (tail = result; CONSP (tail); tail = XCDR (tail))
5258 val = XCAR (tail);
5259 if (FONTP (val))
5260 val = Ffont_xlfd_name (val, Qt);
5261 XSETCAR (tail, val);
5264 else if (VECTORP (result))
5266 result = Fcopy_sequence (result);
5267 for (i = 0; i < ASIZE (result); i++)
5269 val = AREF (result, i);
5270 if (FONTP (val))
5271 val = Ffont_xlfd_name (val, Qt);
5272 ASET (result, i, val);
5275 Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
5278 /* Record a font-related logging data to be added to Vfont_log when
5279 font_add_log is called next time. ACTION, ARG, RESULT are the same
5280 as font_add_log. */
5282 void
5283 font_deferred_log (const char *action, Lisp_Object arg, Lisp_Object result)
5285 if (EQ (Vfont_log, Qt))
5286 return;
5287 ASET (Vfont_log_deferred, 0, build_string (action));
5288 ASET (Vfont_log_deferred, 1, arg);
5289 ASET (Vfont_log_deferred, 2, result);
5292 void
5293 font_drop_xrender_surfaces (struct frame *f)
5295 struct font_driver_list *list;
5297 for (list = f->font_driver_list; list; list = list->next)
5298 if (list->on && list->driver->drop_xrender_surfaces)
5299 list->driver->drop_xrender_surfaces (f);
5302 void
5303 syms_of_font (void)
5305 sort_shift_bits[FONT_TYPE_INDEX] = 0;
5306 sort_shift_bits[FONT_SLANT_INDEX] = 2;
5307 sort_shift_bits[FONT_WEIGHT_INDEX] = 9;
5308 sort_shift_bits[FONT_SIZE_INDEX] = 16;
5309 sort_shift_bits[FONT_WIDTH_INDEX] = 23;
5310 /* Note that the other elements in sort_shift_bits are not used. */
5312 staticpro (&font_charset_alist);
5313 font_charset_alist = Qnil;
5315 DEFSYM (Qopentype, "opentype");
5317 /* Important character set symbols. */
5318 DEFSYM (Qascii_0, "ascii-0");
5319 DEFSYM (Qiso8859_1, "iso8859-1");
5320 DEFSYM (Qiso10646_1, "iso10646-1");
5321 DEFSYM (Qunicode_bmp, "unicode-bmp");
5323 /* Symbols representing keys of font extra info. */
5324 DEFSYM (QCotf, ":otf");
5325 DEFSYM (QClang, ":lang");
5326 DEFSYM (QCscript, ":script");
5327 DEFSYM (QCantialias, ":antialias");
5328 DEFSYM (QCfoundry, ":foundry");
5329 DEFSYM (QCadstyle, ":adstyle");
5330 DEFSYM (QCregistry, ":registry");
5331 DEFSYM (QCspacing, ":spacing");
5332 DEFSYM (QCdpi, ":dpi");
5333 DEFSYM (QCscalable, ":scalable");
5334 DEFSYM (QCavgwidth, ":avgwidth");
5335 DEFSYM (QCfont_entity, ":font-entity");
5336 DEFSYM (QCcombining_capability, ":combining-capability");
5338 /* Symbols representing values of font spacing property. */
5339 DEFSYM (Qc, "c");
5340 DEFSYM (Qm, "m");
5341 DEFSYM (Qp, "p");
5342 DEFSYM (Qd, "d");
5344 /* Special ADSTYLE properties to avoid fonts used for Latin
5345 characters; used in xfont.c and ftfont.c. */
5346 DEFSYM (Qja, "ja");
5347 DEFSYM (Qko, "ko");
5349 DEFSYM (QCuser_spec, ":user-spec");
5351 staticpro (&scratch_font_spec);
5352 scratch_font_spec = Ffont_spec (0, NULL);
5353 staticpro (&scratch_font_prefer);
5354 scratch_font_prefer = Ffont_spec (0, NULL);
5356 staticpro (&Vfont_log_deferred);
5357 Vfont_log_deferred = Fmake_vector (make_number (3), Qnil);
5359 #if 0
5360 #ifdef HAVE_LIBOTF
5361 staticpro (&otf_list);
5362 otf_list = Qnil;
5363 #endif /* HAVE_LIBOTF */
5364 #endif /* 0 */
5366 defsubr (&Sfontp);
5367 defsubr (&Sfont_spec);
5368 defsubr (&Sfont_get);
5369 #ifdef HAVE_WINDOW_SYSTEM
5370 defsubr (&Sfont_face_attributes);
5371 #endif
5372 defsubr (&Sfont_put);
5373 defsubr (&Slist_fonts);
5374 defsubr (&Sfont_family_list);
5375 defsubr (&Sfind_font);
5376 defsubr (&Sfont_xlfd_name);
5377 defsubr (&Sclear_font_cache);
5378 defsubr (&Sfont_shape_gstring);
5379 defsubr (&Sfont_variation_glyphs);
5380 defsubr (&Sinternal_char_font);
5381 #if 0
5382 defsubr (&Sfont_drive_otf);
5383 defsubr (&Sfont_otf_alternates);
5384 #endif /* 0 */
5386 #ifdef FONT_DEBUG
5387 defsubr (&Sopen_font);
5388 defsubr (&Sclose_font);
5389 defsubr (&Squery_font);
5390 defsubr (&Sfont_get_glyphs);
5391 defsubr (&Sfont_match_p);
5392 defsubr (&Sfont_at);
5393 #if 0
5394 defsubr (&Sdraw_string);
5395 #endif
5396 defsubr (&Sframe_font_cache);
5397 #endif /* FONT_DEBUG */
5398 #ifdef HAVE_WINDOW_SYSTEM
5399 defsubr (&Sfont_info);
5400 #endif
5402 DEFVAR_LISP ("font-encoding-alist", Vfont_encoding_alist,
5403 doc: /*
5404 Alist of fontname patterns vs the corresponding encoding and repertory info.
5405 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5406 where ENCODING is a charset or a char-table,
5407 and REPERTORY is a charset, a char-table, or nil.
5409 If ENCODING and REPERTORY are the same, the element can have the form
5410 \(REGEXP . ENCODING).
5412 ENCODING is for converting a character to a glyph code of the font.
5413 If ENCODING is a charset, encoding a character by the charset gives
5414 the corresponding glyph code. If ENCODING is a char-table, looking up
5415 the table by a character gives the corresponding glyph code.
5417 REPERTORY specifies a repertory of characters supported by the font.
5418 If REPERTORY is a charset, all characters belonging to the charset are
5419 supported. If REPERTORY is a char-table, all characters who have a
5420 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5421 gets the repertory information by an opened font and ENCODING. */);
5422 Vfont_encoding_alist = Qnil;
5424 /* FIXME: These 3 vars are not quite what they appear: setq on them
5425 won't have any effect other than disconnect them from the style
5426 table used by the font display code. So we make them read-only,
5427 to avoid this confusing situation. */
5429 DEFVAR_LISP_NOPRO ("font-weight-table", Vfont_weight_table,
5430 doc: /* Vector of valid font weight values.
5431 Each element has the form:
5432 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5433 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols.
5434 This variable cannot be set; trying to do so will signal an error. */);
5435 Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
5436 make_symbol_constant (intern_c_string ("font-weight-table"));
5438 DEFVAR_LISP_NOPRO ("font-slant-table", Vfont_slant_table,
5439 doc: /* Vector of font slant symbols vs the corresponding numeric values.
5440 See `font-weight-table' for the format of the vector.
5441 This variable cannot be set; trying to do so will signal an error. */);
5442 Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
5443 make_symbol_constant (intern_c_string ("font-slant-table"));
5445 DEFVAR_LISP_NOPRO ("font-width-table", Vfont_width_table,
5446 doc: /* Alist of font width symbols vs the corresponding numeric values.
5447 See `font-weight-table' for the format of the vector.
5448 This variable cannot be set; trying to do so will signal an error. */);
5449 Vfont_width_table = BUILD_STYLE_TABLE (width_table);
5450 make_symbol_constant (intern_c_string ("font-width-table"));
5452 staticpro (&font_style_table);
5453 font_style_table = make_uninit_vector (3);
5454 ASET (font_style_table, 0, Vfont_weight_table);
5455 ASET (font_style_table, 1, Vfont_slant_table);
5456 ASET (font_style_table, 2, Vfont_width_table);
5458 DEFVAR_LISP ("font-log", Vfont_log, doc: /*
5459 A list that logs font-related actions and results, for debugging.
5460 The default value is t, which means to suppress logging.
5461 Set it to nil to enable logging. If the environment variable
5462 EMACS_FONT_LOG is set at startup, it defaults to nil. */);
5463 Vfont_log = Qnil;
5465 DEFVAR_BOOL ("inhibit-compacting-font-caches", inhibit_compacting_font_caches,
5466 doc: /*
5467 If non-nil, don't compact font caches during GC.
5468 Some large fonts cause lots of consing and trigger GC. If they
5469 are removed from the font caches, they will need to be opened
5470 again during redisplay, which slows down redisplay. If you
5471 see font-related delays in displaying some special characters,
5472 and cannot switch to a smaller font for those characters, set
5473 this variable non-nil.
5474 Disabling compaction of font caches might enlarge the Emacs memory
5475 footprint in sessions that use lots of different fonts. */);
5476 inhibit_compacting_font_caches = 0;
5478 DEFVAR_BOOL ("xft-ignore-color-fonts",
5479 Vxft_ignore_color_fonts,
5480 doc: /*
5481 Non-nil means don't query fontconfig for color fonts, since they often
5482 cause Xft crashes. Only has an effect in Xft builds. */);
5483 Vxft_ignore_color_fonts = 1;
5485 #ifdef HAVE_WINDOW_SYSTEM
5486 #ifdef HAVE_FREETYPE
5487 syms_of_ftfont ();
5488 #ifdef HAVE_X_WINDOWS
5489 #ifdef USE_CAIRO
5490 syms_of_ftcrfont ();
5491 #else
5492 syms_of_xfont ();
5493 syms_of_ftxfont ();
5494 #ifdef HAVE_XFT
5495 syms_of_xftfont ();
5496 #endif /* HAVE_XFT */
5497 #endif /* not USE_CAIRO */
5498 #endif /* HAVE_X_WINDOWS */
5499 #else /* not HAVE_FREETYPE */
5500 #ifdef HAVE_X_WINDOWS
5501 syms_of_xfont ();
5502 #endif /* HAVE_X_WINDOWS */
5503 #endif /* not HAVE_FREETYPE */
5504 #ifdef HAVE_BDFFONT
5505 syms_of_bdffont ();
5506 #endif /* HAVE_BDFFONT */
5507 #ifdef HAVE_NTGUI
5508 syms_of_w32font ();
5509 #endif /* HAVE_NTGUI */
5510 #endif /* HAVE_WINDOW_SYSTEM */
5513 void
5514 init_font (void)
5516 Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;