In debug restore assignment to debugger-old-buffer.
[emacs.git] / src / font.c
blob1f22fee88ee65d78d033ed81f8be29dfbd690013
1 /* font.c -- "Font" primitives.
3 Copyright (C) 2006-2012 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
13 (at 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 <http://www.gnu.org/licenses/>. */
23 #include <config.h>
24 #include <float.h>
25 #include <stdio.h>
27 #include <c-ctype.h>
29 #include "lisp.h"
30 #include "character.h"
31 #include "buffer.h"
32 #include "frame.h"
33 #include "window.h"
34 #include "dispextern.h"
35 #include "charset.h"
36 #include "composite.h"
37 #include "fontset.h"
38 #include "font.h"
40 #ifdef HAVE_WINDOW_SYSTEM
41 #include TERM_HEADER
42 #endif /* HAVE_WINDOW_SYSTEM */
44 Lisp_Object Qopentype;
46 /* Important character set strings. */
47 Lisp_Object Qascii_0, Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
49 #define DEFAULT_ENCODING Qiso8859_1
51 /* Unicode category `Cf'. */
52 static Lisp_Object QCf;
54 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
55 static Lisp_Object font_style_table;
57 /* Structure used for tables mapping weight, slant, and width numeric
58 values and their names. */
60 struct table_entry
62 int numeric;
63 /* The first one is a valid name as a face attribute.
64 The second one (if any) is a typical name in XLFD field. */
65 const char *names[5];
68 /* Table of weight numeric values and their names. This table must be
69 sorted by numeric values in ascending order. */
71 static const struct table_entry weight_table[] =
73 { 0, { "thin" }},
74 { 20, { "ultra-light", "ultralight" }},
75 { 40, { "extra-light", "extralight" }},
76 { 50, { "light" }},
77 { 75, { "semi-light", "semilight", "demilight", "book" }},
78 { 100, { "normal", "medium", "regular", "unspecified" }},
79 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
80 { 200, { "bold" }},
81 { 205, { "extra-bold", "extrabold" }},
82 { 210, { "ultra-bold", "ultrabold", "black" }}
85 /* Table of slant numeric values and their names. This table must be
86 sorted by numeric values in ascending order. */
88 static const struct table_entry slant_table[] =
90 { 0, { "reverse-oblique", "ro" }},
91 { 10, { "reverse-italic", "ri" }},
92 { 100, { "normal", "r", "unspecified" }},
93 { 200, { "italic" ,"i", "ot" }},
94 { 210, { "oblique", "o" }}
97 /* Table of width numeric values and their names. This table must be
98 sorted by numeric values in ascending order. */
100 static const struct table_entry width_table[] =
102 { 50, { "ultra-condensed", "ultracondensed" }},
103 { 63, { "extra-condensed", "extracondensed" }},
104 { 75, { "condensed", "compressed", "narrow" }},
105 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
106 { 100, { "normal", "medium", "regular", "unspecified" }},
107 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
108 { 125, { "expanded" }},
109 { 150, { "extra-expanded", "extraexpanded" }},
110 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
113 Lisp_Object QCfoundry;
114 static Lisp_Object QCadstyle, QCregistry;
115 /* Symbols representing keys of font extra info. */
116 Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
117 Lisp_Object QCantialias, QCfont_entity;
118 static Lisp_Object QCfc_unknown_spec;
119 /* Symbols representing values of font spacing property. */
120 static Lisp_Object Qc, Qm, Qd;
121 Lisp_Object Qp;
122 /* Special ADSTYLE properties to avoid fonts used for Latin
123 characters; used in xfont.c and ftfont.c. */
124 Lisp_Object Qja, Qko;
126 static Lisp_Object QCuser_spec;
128 /* Alist of font registry symbols and the corresponding charset
129 information. The information is retrieved from
130 Vfont_encoding_alist on demand.
132 Eash element has the form:
133 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
135 (REGISTRY . nil)
137 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
138 encodes a character code to a glyph code of a font, and
139 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
140 character is supported by a font.
142 The latter form means that the information for REGISTRY couldn't be
143 retrieved. */
144 static Lisp_Object font_charset_alist;
146 /* List of all font drivers. Each font-backend (XXXfont.c) calls
147 register_font_driver in syms_of_XXXfont to register its font-driver
148 here. */
149 static struct font_driver_list *font_driver_list;
153 /* Creators of font-related Lisp object. */
155 static Lisp_Object
156 font_make_spec (void)
158 Lisp_Object font_spec;
159 struct font_spec *spec
160 = ((struct font_spec *)
161 allocate_pseudovector (VECSIZE (struct font_spec),
162 FONT_SPEC_MAX, PVEC_FONT));
163 XSETFONT (font_spec, spec);
164 return font_spec;
167 Lisp_Object
168 font_make_entity (void)
170 Lisp_Object font_entity;
171 struct font_entity *entity
172 = ((struct font_entity *)
173 allocate_pseudovector (VECSIZE (struct font_entity),
174 FONT_ENTITY_MAX, PVEC_FONT));
175 XSETFONT (font_entity, entity);
176 return font_entity;
179 /* Create a font-object whose structure size is SIZE. If ENTITY is
180 not nil, copy properties from ENTITY to the font-object. If
181 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
182 Lisp_Object
183 font_make_object (int size, Lisp_Object entity, int pixelsize)
185 Lisp_Object font_object;
186 struct font *font
187 = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX, PVEC_FONT);
188 int i;
190 XSETFONT (font_object, font);
192 if (! NILP (entity))
194 for (i = 1; i < FONT_SPEC_MAX; i++)
195 font->props[i] = AREF (entity, i);
196 if (! NILP (AREF (entity, FONT_EXTRA_INDEX)))
197 font->props[FONT_EXTRA_INDEX]
198 = Fcopy_alist (AREF (entity, FONT_EXTRA_INDEX));
200 if (size > 0)
201 font->props[FONT_SIZE_INDEX] = make_number (pixelsize);
202 return font_object;
207 static int font_pixel_size (FRAME_PTR f, Lisp_Object);
208 static Lisp_Object font_open_entity (FRAME_PTR, Lisp_Object, int);
209 static Lisp_Object font_matching_entity (FRAME_PTR, Lisp_Object *,
210 Lisp_Object);
211 static unsigned font_encode_char (Lisp_Object, int);
213 /* Number of registered font drivers. */
214 static int num_font_drivers;
217 /* Return a Lispy value of a font property value at STR and LEN bytes.
218 If STR is "*", return nil. If FORCE_SYMBOL, or if STR does not
219 consist entirely of one or more digits, return a symbol interned
220 from STR. Otherwise, return an integer. */
222 Lisp_Object
223 font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol)
225 ptrdiff_t i;
226 Lisp_Object tem;
227 Lisp_Object obarray;
228 ptrdiff_t nbytes, nchars;
230 if (len == 1 && *str == '*')
231 return Qnil;
232 if (!force_symbol && 0 < len && '0' <= *str && *str <= '9')
234 for (i = 1; i < len; i++)
235 if (! ('0' <= str[i] && str[i] <= '9'))
236 break;
237 if (i == len)
239 EMACS_INT n;
241 i = 0;
242 for (n = 0; (n += str[i++] - '0') <= MOST_POSITIVE_FIXNUM; n *= 10)
244 if (i == len)
245 return make_number (n);
246 if (MOST_POSITIVE_FIXNUM / 10 < n)
247 break;
250 xsignal1 (Qoverflow_error, make_string (str, len));
254 /* This code is similar to intern function from lread.c. */
255 obarray = check_obarray (Vobarray);
256 parse_str_as_multibyte ((unsigned char *) str, len, &nchars, &nbytes);
257 tem = oblookup (obarray, str,
258 (len == nchars || len != nbytes) ? len : nchars, len);
260 if (SYMBOLP (tem))
261 return tem;
262 if (len == nchars || len != nbytes)
263 tem = make_unibyte_string (str, len);
264 else
265 tem = make_multibyte_string (str, nchars, len);
266 return Fintern (tem, obarray);
269 /* Return a pixel size of font-spec SPEC on frame F. */
271 static int
272 font_pixel_size (FRAME_PTR f, Lisp_Object spec)
274 #ifdef HAVE_WINDOW_SYSTEM
275 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
276 double point_size;
277 int dpi, pixel_size;
278 Lisp_Object val;
280 if (INTEGERP (size))
281 return XINT (size);
282 if (NILP (size))
283 return 0;
284 eassert (FLOATP (size));
285 point_size = XFLOAT_DATA (size);
286 val = AREF (spec, FONT_DPI_INDEX);
287 if (INTEGERP (val))
288 dpi = XINT (val);
289 else
290 dpi = f->resy;
291 pixel_size = POINT_TO_PIXEL (point_size, dpi);
292 return pixel_size;
293 #else
294 return 1;
295 #endif
299 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
300 font vector. If VAL is not valid (i.e. not registered in
301 font_style_table), return -1 if NOERROR is zero, and return a
302 proper index if NOERROR is nonzero. In that case, register VAL in
303 font_style_table if VAL is a symbol, and return the closest index if
304 VAL is an integer. */
307 font_style_to_value (enum font_property_index prop, Lisp_Object val,
308 bool noerror)
310 Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
311 int len;
313 CHECK_VECTOR (table);
314 len = ASIZE (table);
316 if (SYMBOLP (val))
318 int i, j;
319 char *s;
320 Lisp_Object args[2], elt;
322 /* At first try exact match. */
323 for (i = 0; i < len; i++)
325 CHECK_VECTOR (AREF (table, i));
326 for (j = 1; j < ASIZE (AREF (table, i)); j++)
327 if (EQ (val, AREF (AREF (table, i), j)))
329 CHECK_NUMBER (AREF (AREF (table, i), 0));
330 return ((XINT (AREF (AREF (table, i), 0)) << 8)
331 | (i << 4) | (j - 1));
334 /* Try also with case-folding match. */
335 s = SSDATA (SYMBOL_NAME (val));
336 for (i = 0; i < len; i++)
337 for (j = 1; j < ASIZE (AREF (table, i)); j++)
339 elt = AREF (AREF (table, i), j);
340 if (xstrcasecmp (s, SSDATA (SYMBOL_NAME (elt))) == 0)
342 CHECK_NUMBER (AREF (AREF (table, i), 0));
343 return ((XINT (AREF (AREF (table, i), 0)) << 8)
344 | (i << 4) | (j - 1));
347 if (! noerror)
348 return -1;
349 eassert (len < 255);
350 elt = Fmake_vector (make_number (2), make_number (100));
351 ASET (elt, 1, val);
352 args[0] = table;
353 args[1] = Fmake_vector (make_number (1), elt);
354 ASET (font_style_table, prop - FONT_WEIGHT_INDEX, Fvconcat (2, args));
355 return (100 << 8) | (i << 4);
357 else
359 int i, last_n;
360 EMACS_INT numeric = XINT (val);
362 for (i = 0, last_n = -1; i < len; i++)
364 int n;
366 CHECK_VECTOR (AREF (table, i));
367 CHECK_NUMBER (AREF (AREF (table, i), 0));
368 n = XINT (AREF (AREF (table, i), 0));
369 if (numeric == n)
370 return (n << 8) | (i << 4);
371 if (numeric < n)
373 if (! noerror)
374 return -1;
375 return ((i == 0 || n - numeric < numeric - last_n)
376 ? (n << 8) | (i << 4): (last_n << 8 | ((i - 1) << 4)));
378 last_n = n;
380 if (! noerror)
381 return -1;
382 return ((last_n << 8) | ((i - 1) << 4));
386 Lisp_Object
387 font_style_symbolic (Lisp_Object font, enum font_property_index prop,
388 bool for_face)
390 Lisp_Object val = AREF (font, prop);
391 Lisp_Object table, elt;
392 int i;
394 if (NILP (val))
395 return Qnil;
396 table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
397 CHECK_VECTOR (table);
398 i = XINT (val) & 0xFF;
399 eassert (((i >> 4) & 0xF) < ASIZE (table));
400 elt = AREF (table, ((i >> 4) & 0xF));
401 CHECK_VECTOR (elt);
402 eassert ((i & 0xF) + 1 < ASIZE (elt));
403 elt = (for_face ? AREF (elt, 1) : AREF (elt, (i & 0xF) + 1));
404 CHECK_SYMBOL (elt);
405 return elt;
408 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
409 FONTNAME. ENCODING is a charset symbol that specifies the encoding
410 of the font. REPERTORY is a charset symbol or nil. */
412 Lisp_Object
413 find_font_encoding (Lisp_Object fontname)
415 Lisp_Object tail, elt;
417 for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
419 elt = XCAR (tail);
420 if (CONSP (elt)
421 && STRINGP (XCAR (elt))
422 && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
423 && (SYMBOLP (XCDR (elt))
424 ? CHARSETP (XCDR (elt))
425 : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
426 return (XCDR (elt));
428 return Qnil;
431 /* Return encoding charset and repertory charset for REGISTRY in
432 ENCODING and REPERTORY correspondingly. If correct information for
433 REGISTRY is available, return 0. Otherwise return -1. */
436 font_registry_charsets (Lisp_Object registry, struct charset **encoding, struct charset **repertory)
438 Lisp_Object val;
439 int encoding_id, repertory_id;
441 val = Fassoc_string (registry, font_charset_alist, Qt);
442 if (! NILP (val))
444 val = XCDR (val);
445 if (NILP (val))
446 return -1;
447 encoding_id = XINT (XCAR (val));
448 repertory_id = XINT (XCDR (val));
450 else
452 val = find_font_encoding (SYMBOL_NAME (registry));
453 if (SYMBOLP (val) && CHARSETP (val))
455 encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val));
457 else if (CONSP (val))
459 if (! CHARSETP (XCAR (val)))
460 goto invalid_entry;
461 encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val)));
462 if (NILP (XCDR (val)))
463 repertory_id = -1;
464 else
466 if (! CHARSETP (XCDR (val)))
467 goto invalid_entry;
468 repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val)));
471 else
472 goto invalid_entry;
473 val = Fcons (make_number (encoding_id), make_number (repertory_id));
474 font_charset_alist
475 = nconc2 (font_charset_alist, Fcons (Fcons (registry, val), Qnil));
478 if (encoding)
479 *encoding = CHARSET_FROM_ID (encoding_id);
480 if (repertory)
481 *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL;
482 return 0;
484 invalid_entry:
485 font_charset_alist
486 = nconc2 (font_charset_alist, Fcons (Fcons (registry, Qnil), Qnil));
487 return -1;
491 /* Font property value validators. See the comment of
492 font_property_table for the meaning of the arguments. */
494 static Lisp_Object font_prop_validate (int, Lisp_Object, Lisp_Object);
495 static Lisp_Object font_prop_validate_symbol (Lisp_Object, Lisp_Object);
496 static Lisp_Object font_prop_validate_style (Lisp_Object, Lisp_Object);
497 static Lisp_Object font_prop_validate_non_neg (Lisp_Object, Lisp_Object);
498 static Lisp_Object font_prop_validate_spacing (Lisp_Object, Lisp_Object);
499 static int get_font_prop_index (Lisp_Object);
501 static Lisp_Object
502 font_prop_validate_symbol (Lisp_Object prop, Lisp_Object val)
504 if (STRINGP (val))
505 val = Fintern (val, Qnil);
506 if (! SYMBOLP (val))
507 val = Qerror;
508 else if (EQ (prop, QCregistry))
509 val = Fintern (Fdowncase (SYMBOL_NAME (val)), Qnil);
510 return val;
514 static Lisp_Object
515 font_prop_validate_style (Lisp_Object style, Lisp_Object val)
517 enum font_property_index prop = (EQ (style, QCweight) ? FONT_WEIGHT_INDEX
518 : EQ (style, QCslant) ? FONT_SLANT_INDEX
519 : FONT_WIDTH_INDEX);
520 if (INTEGERP (val))
522 EMACS_INT n = XINT (val);
523 CHECK_VECTOR (AREF (font_style_table, prop - FONT_WEIGHT_INDEX));
524 if (((n >> 4) & 0xF)
525 >= ASIZE (AREF (font_style_table, prop - FONT_WEIGHT_INDEX)))
526 val = Qerror;
527 else
529 Lisp_Object elt = AREF (AREF (font_style_table, prop - FONT_WEIGHT_INDEX), (n >> 4) & 0xF);
531 CHECK_VECTOR (elt);
532 if ((n & 0xF) + 1 >= ASIZE (elt))
533 val = Qerror;
534 else
536 CHECK_NUMBER (AREF (elt, 0));
537 if (XINT (AREF (elt, 0)) != (n >> 8))
538 val = Qerror;
542 else if (SYMBOLP (val))
544 int n = font_style_to_value (prop, val, 0);
546 val = n >= 0 ? make_number (n) : Qerror;
548 else
549 val = Qerror;
550 return val;
553 static Lisp_Object
554 font_prop_validate_non_neg (Lisp_Object prop, Lisp_Object val)
556 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
557 ? val : Qerror);
560 static Lisp_Object
561 font_prop_validate_spacing (Lisp_Object prop, Lisp_Object val)
563 if (NILP (val) || (NATNUMP (val) && XINT (val) <= FONT_SPACING_CHARCELL))
564 return val;
565 if (SYMBOLP (val) && SBYTES (SYMBOL_NAME (val)) == 1)
567 char spacing = SDATA (SYMBOL_NAME (val))[0];
569 if (spacing == 'c' || spacing == 'C')
570 return make_number (FONT_SPACING_CHARCELL);
571 if (spacing == 'm' || spacing == 'M')
572 return make_number (FONT_SPACING_MONO);
573 if (spacing == 'p' || spacing == 'P')
574 return make_number (FONT_SPACING_PROPORTIONAL);
575 if (spacing == 'd' || spacing == 'D')
576 return make_number (FONT_SPACING_DUAL);
578 return Qerror;
581 static Lisp_Object
582 font_prop_validate_otf (Lisp_Object prop, Lisp_Object val)
584 Lisp_Object tail, tmp;
585 int i;
587 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
588 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
589 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
590 if (! CONSP (val))
591 return Qerror;
592 if (! SYMBOLP (XCAR (val)))
593 return Qerror;
594 tail = XCDR (val);
595 if (NILP (tail))
596 return val;
597 if (! CONSP (tail) || ! SYMBOLP (XCAR (val)))
598 return Qerror;
599 for (i = 0; i < 2; i++)
601 tail = XCDR (tail);
602 if (NILP (tail))
603 return val;
604 if (! CONSP (tail))
605 return Qerror;
606 for (tmp = XCAR (tail); CONSP (tmp); tmp = XCDR (tmp))
607 if (! SYMBOLP (XCAR (tmp)))
608 return Qerror;
609 if (! NILP (tmp))
610 return Qerror;
612 return val;
615 /* Structure of known font property keys and validator of the
616 values. */
617 static const struct
619 /* Pointer to the key symbol. */
620 Lisp_Object *key;
621 /* Function to validate PROP's value VAL, or NULL if any value is
622 ok. The value is VAL or its regularized value if VAL is valid,
623 and Qerror if not. */
624 Lisp_Object (*validator) (Lisp_Object prop, Lisp_Object val);
625 } font_property_table[] =
626 { { &QCtype, font_prop_validate_symbol },
627 { &QCfoundry, font_prop_validate_symbol },
628 { &QCfamily, font_prop_validate_symbol },
629 { &QCadstyle, font_prop_validate_symbol },
630 { &QCregistry, font_prop_validate_symbol },
631 { &QCweight, font_prop_validate_style },
632 { &QCslant, font_prop_validate_style },
633 { &QCwidth, font_prop_validate_style },
634 { &QCsize, font_prop_validate_non_neg },
635 { &QCdpi, font_prop_validate_non_neg },
636 { &QCspacing, font_prop_validate_spacing },
637 { &QCavgwidth, font_prop_validate_non_neg },
638 /* The order of the above entries must match with enum
639 font_property_index. */
640 { &QClang, font_prop_validate_symbol },
641 { &QCscript, font_prop_validate_symbol },
642 { &QCotf, font_prop_validate_otf }
645 /* Size (number of elements) of the above table. */
646 #define FONT_PROPERTY_TABLE_SIZE \
647 ((sizeof font_property_table) / (sizeof *font_property_table))
649 /* Return an index number of font property KEY or -1 if KEY is not an
650 already known property. */
652 static int
653 get_font_prop_index (Lisp_Object key)
655 int i;
657 for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++)
658 if (EQ (key, *font_property_table[i].key))
659 return i;
660 return -1;
663 /* Validate the font property. The property key is specified by the
664 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
665 signal an error. The value is VAL or the regularized one. */
667 static Lisp_Object
668 font_prop_validate (int idx, Lisp_Object prop, Lisp_Object val)
670 Lisp_Object validated;
672 if (NILP (val))
673 return val;
674 if (NILP (prop))
675 prop = *font_property_table[idx].key;
676 else
678 idx = get_font_prop_index (prop);
679 if (idx < 0)
680 return val;
682 validated = (font_property_table[idx].validator) (prop, val);
683 if (EQ (validated, Qerror))
684 signal_error ("invalid font property", Fcons (prop, val));
685 return validated;
689 /* Store VAL as a value of extra font property PROP in FONT while
690 keeping the sorting order. Don't check the validity of VAL. */
692 Lisp_Object
693 font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
695 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
696 Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
698 if (NILP (slot))
700 Lisp_Object prev = Qnil;
702 while (CONSP (extra)
703 && NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
704 prev = extra, extra = XCDR (extra);
706 if (NILP (prev))
707 ASET (font, FONT_EXTRA_INDEX, Fcons (Fcons (prop, val), extra));
708 else
709 XSETCDR (prev, Fcons (Fcons (prop, val), extra));
711 return val;
713 XSETCDR (slot, val);
714 if (NILP (val))
715 ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra));
716 return val;
720 /* Font name parser and unparser */
722 static int parse_matrix (const char *);
723 static int font_expand_wildcards (Lisp_Object *, int);
724 static int font_parse_name (char *, ptrdiff_t, Lisp_Object);
726 /* An enumerator for each field of an XLFD font name. */
727 enum xlfd_field_index
729 XLFD_FOUNDRY_INDEX,
730 XLFD_FAMILY_INDEX,
731 XLFD_WEIGHT_INDEX,
732 XLFD_SLANT_INDEX,
733 XLFD_SWIDTH_INDEX,
734 XLFD_ADSTYLE_INDEX,
735 XLFD_PIXEL_INDEX,
736 XLFD_POINT_INDEX,
737 XLFD_RESX_INDEX,
738 XLFD_RESY_INDEX,
739 XLFD_SPACING_INDEX,
740 XLFD_AVGWIDTH_INDEX,
741 XLFD_REGISTRY_INDEX,
742 XLFD_ENCODING_INDEX,
743 XLFD_LAST_INDEX
746 /* An enumerator for mask bit corresponding to each XLFD field. */
747 enum xlfd_field_mask
749 XLFD_FOUNDRY_MASK = 0x0001,
750 XLFD_FAMILY_MASK = 0x0002,
751 XLFD_WEIGHT_MASK = 0x0004,
752 XLFD_SLANT_MASK = 0x0008,
753 XLFD_SWIDTH_MASK = 0x0010,
754 XLFD_ADSTYLE_MASK = 0x0020,
755 XLFD_PIXEL_MASK = 0x0040,
756 XLFD_POINT_MASK = 0x0080,
757 XLFD_RESX_MASK = 0x0100,
758 XLFD_RESY_MASK = 0x0200,
759 XLFD_SPACING_MASK = 0x0400,
760 XLFD_AVGWIDTH_MASK = 0x0800,
761 XLFD_REGISTRY_MASK = 0x1000,
762 XLFD_ENCODING_MASK = 0x2000
766 /* Parse P pointing to the pixel/point size field of the form
767 `[A B C D]' which specifies a transformation matrix:
769 A B 0
770 C D 0
771 0 0 1
773 by which all glyphs of the font are transformed. The spec says
774 that scalar value N for the pixel/point size is equivalent to:
775 A = N * resx/resy, B = C = 0, D = N.
777 Return the scalar value N if the form is valid. Otherwise return
778 -1. */
780 static int
781 parse_matrix (const char *p)
783 double matrix[4];
784 char *end;
785 int i;
787 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
789 if (*p == '~')
790 matrix[i] = - strtod (p + 1, &end);
791 else
792 matrix[i] = strtod (p, &end);
793 p = end;
795 return (i == 4 ? (int) matrix[3] : -1);
798 /* Expand a wildcard field in FIELD (the first N fields are filled) to
799 multiple fields to fill in all 14 XLFD fields while restricting a
800 field position by its contents. */
802 static int
803 font_expand_wildcards (Lisp_Object *field, int n)
805 /* Copy of FIELD. */
806 Lisp_Object tmp[XLFD_LAST_INDEX];
807 /* Array of information about where this element can go. Nth
808 element is for Nth element of FIELD. */
809 struct {
810 /* Minimum possible field. */
811 int from;
812 /* Maximum possible field. */
813 int to;
814 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
815 int mask;
816 } range[XLFD_LAST_INDEX];
817 int i, j;
818 int range_from, range_to;
819 unsigned range_mask;
821 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
822 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
823 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
824 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
825 | XLFD_AVGWIDTH_MASK)
826 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
828 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
829 field. The value is shifted to left one bit by one in the
830 following loop. */
831 for (i = 0, range_mask = 0; i <= 14 - n; i++)
832 range_mask = (range_mask << 1) | 1;
834 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
835 position-based restriction for FIELD[I]. */
836 for (i = 0, range_from = 0, range_to = 14 - n; i < n;
837 i++, range_from++, range_to++, range_mask <<= 1)
839 Lisp_Object val = field[i];
841 tmp[i] = val;
842 if (NILP (val))
844 /* Wildcard. */
845 range[i].from = range_from;
846 range[i].to = range_to;
847 range[i].mask = range_mask;
849 else
851 /* The triplet FROM, TO, and MASK is a value-based
852 restriction for FIELD[I]. */
853 int from, to;
854 unsigned mask;
856 if (INTEGERP (val))
858 EMACS_INT numeric = XINT (val);
860 if (i + 1 == n)
861 from = to = XLFD_ENCODING_INDEX,
862 mask = XLFD_ENCODING_MASK;
863 else if (numeric == 0)
864 from = XLFD_PIXEL_INDEX, to = XLFD_AVGWIDTH_INDEX,
865 mask = XLFD_PIXEL_MASK | XLFD_LARGENUM_MASK;
866 else if (numeric <= 48)
867 from = to = XLFD_PIXEL_INDEX,
868 mask = XLFD_PIXEL_MASK;
869 else
870 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
871 mask = XLFD_LARGENUM_MASK;
873 else if (SBYTES (SYMBOL_NAME (val)) == 0)
874 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
875 mask = XLFD_NULL_MASK;
876 else if (i == 0)
877 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
878 else if (i + 1 == n)
880 Lisp_Object name = SYMBOL_NAME (val);
882 if (SDATA (name)[SBYTES (name) - 1] == '*')
883 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
884 mask = XLFD_REGENC_MASK;
885 else
886 from = to = XLFD_ENCODING_INDEX,
887 mask = XLFD_ENCODING_MASK;
889 else if (range_from <= XLFD_WEIGHT_INDEX
890 && range_to >= XLFD_WEIGHT_INDEX
891 && FONT_WEIGHT_NAME_NUMERIC (val) >= 0)
892 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
893 else if (range_from <= XLFD_SLANT_INDEX
894 && range_to >= XLFD_SLANT_INDEX
895 && FONT_SLANT_NAME_NUMERIC (val) >= 0)
896 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
897 else if (range_from <= XLFD_SWIDTH_INDEX
898 && range_to >= XLFD_SWIDTH_INDEX
899 && FONT_WIDTH_NAME_NUMERIC (val) >= 0)
900 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
901 else
903 if (EQ (val, Qc) || EQ (val, Qm) || EQ (val, Qp) || EQ (val, Qd))
904 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
905 else
906 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
907 mask = XLFD_SYMBOL_MASK;
910 /* Merge position-based and value-based restrictions. */
911 mask &= range_mask;
912 while (from < range_from)
913 mask &= ~(1 << from++);
914 while (from < 14 && ! (mask & (1 << from)))
915 from++;
916 while (to > range_to)
917 mask &= ~(1 << to--);
918 while (to >= 0 && ! (mask & (1 << to)))
919 to--;
920 if (from > to)
921 return -1;
922 range[i].from = from;
923 range[i].to = to;
924 range[i].mask = mask;
926 if (from > range_from || to < range_to)
928 /* The range is narrowed by value-based restrictions.
929 Reflect it to the other fields. */
931 /* Following fields should be after FROM. */
932 range_from = from;
933 /* Preceding fields should be before TO. */
934 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
936 /* Check FROM for non-wildcard field. */
937 if (! NILP (tmp[j]) && range[j].from < from)
939 while (range[j].from < from)
940 range[j].mask &= ~(1 << range[j].from++);
941 while (from < 14 && ! (range[j].mask & (1 << from)))
942 from++;
943 range[j].from = from;
945 else
946 from = range[j].from;
947 if (range[j].to > to)
949 while (range[j].to > to)
950 range[j].mask &= ~(1 << range[j].to--);
951 while (to >= 0 && ! (range[j].mask & (1 << to)))
952 to--;
953 range[j].to = to;
955 else
956 to = range[j].to;
957 if (from > to)
958 return -1;
964 /* Decide all fields from restrictions in RANGE. */
965 for (i = j = 0; i < n ; i++)
967 if (j < range[i].from)
969 if (i == 0 || ! NILP (tmp[i - 1]))
970 /* None of TMP[X] corresponds to Jth field. */
971 return -1;
972 for (; j < range[i].from; j++)
973 field[j] = Qnil;
975 field[j++] = tmp[i];
977 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
978 return -1;
979 for (; j < XLFD_LAST_INDEX; j++)
980 field[j] = Qnil;
981 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
982 field[XLFD_ENCODING_INDEX]
983 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
984 return 0;
988 /* Parse NAME (null terminated) as XLFD and store information in FONT
989 (font-spec or font-entity). Size property of FONT is set as
990 follows:
991 specified XLFD fields FONT property
992 --------------------- -------------
993 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
994 POINT_SIZE and RESY calculated pixel size (Lisp integer)
995 POINT_SIZE POINT_SIZE/10 (Lisp float)
997 If NAME is successfully parsed, return 0. Otherwise return -1.
999 FONT is usually a font-spec, but when this function is called from
1000 X font backend driver, it is a font-entity. In that case, NAME is
1001 a fully specified XLFD. */
1004 font_parse_xlfd (char *name, ptrdiff_t len, Lisp_Object font)
1006 int i, j, n;
1007 char *f[XLFD_LAST_INDEX + 1];
1008 Lisp_Object val;
1009 char *p;
1011 if (len > 255 || !len)
1012 /* Maximum XLFD name length is 255. */
1013 return -1;
1014 /* Accept "*-.." as a fully specified XLFD. */
1015 if (name[0] == '*' && (len == 1 || name[1] == '-'))
1016 i = 1, f[XLFD_FOUNDRY_INDEX] = name;
1017 else
1018 i = 0;
1019 for (p = name + i; *p; p++)
1020 if (*p == '-')
1022 f[i++] = p + 1;
1023 if (i == XLFD_LAST_INDEX)
1024 break;
1026 f[i] = name + len;
1028 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1029 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1031 if (i == XLFD_LAST_INDEX)
1033 /* Fully specified XLFD. */
1034 int pixel_size;
1036 ASET (font, FONT_FOUNDRY_INDEX, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX));
1037 ASET (font, FONT_FAMILY_INDEX, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX));
1038 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1039 i <= XLFD_SWIDTH_INDEX; i++, j++)
1041 val = INTERN_FIELD_SYM (i);
1042 if (! NILP (val))
1044 if ((n = font_style_to_value (j, INTERN_FIELD_SYM (i), 0)) < 0)
1045 return -1;
1046 ASET (font, j, make_number (n));
1049 ASET (font, FONT_ADSTYLE_INDEX, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX));
1050 if (strcmp (f[XLFD_REGISTRY_INDEX], "*-*") == 0)
1051 ASET (font, FONT_REGISTRY_INDEX, Qnil);
1052 else
1053 ASET (font, FONT_REGISTRY_INDEX,
1054 font_intern_prop (f[XLFD_REGISTRY_INDEX],
1055 f[XLFD_LAST_INDEX] - f[XLFD_REGISTRY_INDEX],
1056 1));
1057 p = f[XLFD_PIXEL_INDEX];
1058 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
1059 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
1060 else
1062 val = INTERN_FIELD (XLFD_PIXEL_INDEX);
1063 if (INTEGERP (val))
1064 ASET (font, FONT_SIZE_INDEX, val);
1065 else if (FONT_ENTITY_P (font))
1066 return -1;
1067 else
1069 double point_size = -1;
1071 eassert (FONT_SPEC_P (font));
1072 p = f[XLFD_POINT_INDEX];
1073 if (*p == '[')
1074 point_size = parse_matrix (p);
1075 else if (c_isdigit (*p))
1076 point_size = atoi (p), point_size /= 10;
1077 if (point_size >= 0)
1078 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1082 val = INTERN_FIELD (XLFD_RESY_INDEX);
1083 if (! NILP (val) && ! INTEGERP (val))
1084 return -1;
1085 ASET (font, FONT_DPI_INDEX, val);
1086 val = INTERN_FIELD (XLFD_SPACING_INDEX);
1087 if (! NILP (val))
1089 val = font_prop_validate_spacing (QCspacing, val);
1090 if (! INTEGERP (val))
1091 return -1;
1092 ASET (font, FONT_SPACING_INDEX, val);
1094 p = f[XLFD_AVGWIDTH_INDEX];
1095 if (*p == '~')
1096 p++;
1097 val = font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p, 0);
1098 if (! NILP (val) && ! INTEGERP (val))
1099 return -1;
1100 ASET (font, FONT_AVGWIDTH_INDEX, val);
1102 else
1104 bool wild_card_found = 0;
1105 Lisp_Object prop[XLFD_LAST_INDEX];
1107 if (FONT_ENTITY_P (font))
1108 return -1;
1109 for (j = 0; j < i; j++)
1111 if (*f[j] == '*')
1113 if (f[j][1] && f[j][1] != '-')
1114 return -1;
1115 prop[j] = Qnil;
1116 wild_card_found = 1;
1118 else if (j + 1 < i)
1119 prop[j] = INTERN_FIELD (j);
1120 else
1121 prop[j] = font_intern_prop (f[j], f[i] - f[j], 0);
1123 if (! wild_card_found)
1124 return -1;
1125 if (font_expand_wildcards (prop, i) < 0)
1126 return -1;
1128 ASET (font, FONT_FOUNDRY_INDEX, prop[XLFD_FOUNDRY_INDEX]);
1129 ASET (font, FONT_FAMILY_INDEX, prop[XLFD_FAMILY_INDEX]);
1130 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1131 i <= XLFD_SWIDTH_INDEX; i++, j++)
1132 if (! NILP (prop[i]))
1134 if ((n = font_style_to_value (j, prop[i], 1)) < 0)
1135 return -1;
1136 ASET (font, j, make_number (n));
1138 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1139 val = prop[XLFD_REGISTRY_INDEX];
1140 if (NILP (val))
1142 val = prop[XLFD_ENCODING_INDEX];
1143 if (! NILP (val))
1144 val = concat2 (build_string ("*-"), SYMBOL_NAME (val));
1146 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1147 val = concat2 (SYMBOL_NAME (val), build_string ("-*"));
1148 else
1149 val = concat3 (SYMBOL_NAME (val), build_string ("-"),
1150 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX]));
1151 if (! NILP (val))
1152 ASET (font, FONT_REGISTRY_INDEX, Fintern (val, Qnil));
1154 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1155 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
1156 else if (INTEGERP (prop[XLFD_POINT_INDEX]))
1158 double point_size = XINT (prop[XLFD_POINT_INDEX]);
1160 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1163 if (INTEGERP (prop[XLFD_RESX_INDEX]))
1164 ASET (font, FONT_DPI_INDEX, prop[XLFD_RESY_INDEX]);
1165 if (! NILP (prop[XLFD_SPACING_INDEX]))
1167 val = font_prop_validate_spacing (QCspacing,
1168 prop[XLFD_SPACING_INDEX]);
1169 if (! INTEGERP (val))
1170 return -1;
1171 ASET (font, FONT_SPACING_INDEX, val);
1173 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1174 ASET (font, FONT_AVGWIDTH_INDEX, prop[XLFD_AVGWIDTH_INDEX]);
1177 return 0;
1180 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1181 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1182 0, use PIXEL_SIZE instead. */
1184 ptrdiff_t
1185 font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
1187 char *p;
1188 const char *f[XLFD_REGISTRY_INDEX + 1];
1189 Lisp_Object val;
1190 int i, j, len;
1192 eassert (FONTP (font));
1194 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
1195 i++, j++)
1197 if (i == FONT_ADSTYLE_INDEX)
1198 j = XLFD_ADSTYLE_INDEX;
1199 else if (i == FONT_REGISTRY_INDEX)
1200 j = XLFD_REGISTRY_INDEX;
1201 val = AREF (font, i);
1202 if (NILP (val))
1204 if (j == XLFD_REGISTRY_INDEX)
1205 f[j] = "*-*";
1206 else
1207 f[j] = "*";
1209 else
1211 if (SYMBOLP (val))
1212 val = SYMBOL_NAME (val);
1213 if (j == XLFD_REGISTRY_INDEX
1214 && ! strchr (SSDATA (val), '-'))
1216 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1217 ptrdiff_t alloc = SBYTES (val) + 4;
1218 if (nbytes <= alloc)
1219 return -1;
1220 f[j] = p = alloca (alloc);
1221 sprintf (p, "%s%s-*", SDATA (val),
1222 "*" + (SDATA (val)[SBYTES (val) - 1] == '*'));
1224 else
1225 f[j] = SSDATA (val);
1229 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1230 i++, j++)
1232 val = font_style_symbolic (font, i, 0);
1233 if (NILP (val))
1234 f[j] = "*";
1235 else
1237 val = SYMBOL_NAME (val);
1238 f[j] = SSDATA (val);
1242 val = AREF (font, FONT_SIZE_INDEX);
1243 eassert (NUMBERP (val) || NILP (val));
1244 if (INTEGERP (val))
1246 EMACS_INT v = XINT (val);
1247 if (v <= 0)
1248 v = pixel_size;
1249 if (v > 0)
1251 f[XLFD_PIXEL_INDEX] = p =
1252 alloca (sizeof "-*" + INT_STRLEN_BOUND (EMACS_INT));
1253 sprintf (p, "%"pI"d-*", v);
1255 else
1256 f[XLFD_PIXEL_INDEX] = "*-*";
1258 else if (FLOATP (val))
1260 double v = XFLOAT_DATA (val) * 10;
1261 f[XLFD_PIXEL_INDEX] = p = alloca (sizeof "*-" + 1 + DBL_MAX_10_EXP + 1);
1262 sprintf (p, "*-%.0f", v);
1264 else
1265 f[XLFD_PIXEL_INDEX] = "*-*";
1267 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1269 EMACS_INT v = XINT (AREF (font, FONT_DPI_INDEX));
1270 f[XLFD_RESX_INDEX] = p =
1271 alloca (sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT));
1272 sprintf (p, "%"pI"d-%"pI"d", v, v);
1274 else
1275 f[XLFD_RESX_INDEX] = "*-*";
1276 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1278 EMACS_INT spacing = XINT (AREF (font, FONT_SPACING_INDEX));
1280 f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
1281 : spacing <= FONT_SPACING_DUAL ? "d"
1282 : spacing <= FONT_SPACING_MONO ? "m"
1283 : "c");
1285 else
1286 f[XLFD_SPACING_INDEX] = "*";
1287 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1289 f[XLFD_AVGWIDTH_INDEX] = p = alloca (INT_BUFSIZE_BOUND (EMACS_INT));
1290 sprintf (p, "%"pI"d", XINT (AREF (font, FONT_AVGWIDTH_INDEX)));
1292 else
1293 f[XLFD_AVGWIDTH_INDEX] = "*";
1294 len = snprintf (name, nbytes, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1295 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1296 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1297 f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
1298 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
1299 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
1300 f[XLFD_REGISTRY_INDEX]);
1301 return len < nbytes ? len : -1;
1304 /* Parse NAME (null terminated) and store information in FONT
1305 (font-spec or font-entity). NAME is supplied in either the
1306 Fontconfig or GTK font name format. If NAME is successfully
1307 parsed, return 0. Otherwise return -1.
1309 The fontconfig format is
1311 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1313 The GTK format is
1315 FAMILY [PROPS...] [SIZE]
1317 This function tries to guess which format it is. */
1319 static int
1320 font_parse_fcname (char *name, ptrdiff_t len, Lisp_Object font)
1322 char *p, *q;
1323 char *size_beg = NULL, *size_end = NULL;
1324 char *props_beg = NULL, *family_end = NULL;
1326 if (len == 0)
1327 return -1;
1329 for (p = name; *p; p++)
1331 if (*p == '\\' && p[1])
1332 p++;
1333 else if (*p == ':')
1335 props_beg = family_end = p;
1336 break;
1338 else if (*p == '-')
1340 bool decimal = 0, size_found = 1;
1341 for (q = p + 1; *q && *q != ':'; q++)
1342 if (! c_isdigit (*q))
1344 if (*q != '.' || decimal)
1346 size_found = 0;
1347 break;
1349 decimal = 1;
1351 if (size_found)
1353 family_end = p;
1354 size_beg = p + 1;
1355 size_end = q;
1356 break;
1361 if (family_end)
1363 Lisp_Object extra_props = Qnil;
1365 /* A fontconfig name with size and/or property data. */
1366 if (family_end > name)
1368 Lisp_Object family;
1369 family = font_intern_prop (name, family_end - name, 1);
1370 ASET (font, FONT_FAMILY_INDEX, family);
1372 if (size_beg)
1374 double point_size = strtod (size_beg, &size_end);
1375 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1376 if (*size_end == ':' && size_end[1])
1377 props_beg = size_end;
1379 if (props_beg)
1381 /* Now parse ":KEY=VAL" patterns. */
1382 Lisp_Object val;
1384 for (p = props_beg; *p; p = q)
1386 for (q = p + 1; *q && *q != '=' && *q != ':'; q++);
1387 if (*q != '=')
1389 /* Must be an enumerated value. */
1390 ptrdiff_t word_len;
1391 p = p + 1;
1392 word_len = q - p;
1393 val = font_intern_prop (p, q - p, 1);
1395 #define PROP_MATCH(STR) (word_len == strlen (STR) \
1396 && memcmp (p, STR, strlen (STR)) == 0)
1398 if (PROP_MATCH ("light")
1399 || PROP_MATCH ("medium")
1400 || PROP_MATCH ("demibold")
1401 || PROP_MATCH ("bold")
1402 || PROP_MATCH ("black"))
1403 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
1404 else if (PROP_MATCH ("roman")
1405 || PROP_MATCH ("italic")
1406 || PROP_MATCH ("oblique"))
1407 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
1408 else if (PROP_MATCH ("charcell"))
1409 ASET (font, FONT_SPACING_INDEX,
1410 make_number (FONT_SPACING_CHARCELL));
1411 else if (PROP_MATCH ("mono"))
1412 ASET (font, FONT_SPACING_INDEX,
1413 make_number (FONT_SPACING_MONO));
1414 else if (PROP_MATCH ("proportional"))
1415 ASET (font, FONT_SPACING_INDEX,
1416 make_number (FONT_SPACING_PROPORTIONAL));
1417 #undef PROP_MATCH
1419 else
1421 /* KEY=VAL pairs */
1422 Lisp_Object key;
1423 int prop;
1425 if (q - p == 10 && memcmp (p + 1, "pixelsize", 9) == 0)
1426 prop = FONT_SIZE_INDEX;
1427 else
1429 key = font_intern_prop (p, q - p, 1);
1430 prop = get_font_prop_index (key);
1433 p = q + 1;
1434 for (q = p; *q && *q != ':'; q++);
1435 val = font_intern_prop (p, q - p, 0);
1437 if (prop >= FONT_FOUNDRY_INDEX
1438 && prop < FONT_EXTRA_INDEX)
1439 ASET (font, prop, font_prop_validate (prop, Qnil, val));
1440 else
1442 extra_props = nconc2 (extra_props,
1443 Fcons (Fcons (key, val), Qnil));
1446 p = q;
1450 if (! NILP (extra_props))
1452 struct font_driver_list *driver_list = font_driver_list;
1453 for ( ; driver_list; driver_list = driver_list->next)
1454 if (driver_list->driver->filter_properties)
1455 (*driver_list->driver->filter_properties) (font, extra_props);
1459 else
1461 /* Either a fontconfig-style name with no size and property
1462 data, or a GTK-style name. */
1463 Lisp_Object weight = Qnil, slant = Qnil;
1464 Lisp_Object width = Qnil, size = Qnil;
1465 char *word_start;
1466 ptrdiff_t word_len;
1468 /* Scan backwards from the end, looking for a size. */
1469 for (p = name + len - 1; p >= name; p--)
1470 if (!c_isdigit (*p))
1471 break;
1473 if ((p < name + len - 1) && ((p + 1 == name) || *p == ' '))
1474 /* Found a font size. */
1475 size = make_float (strtod (p + 1, NULL));
1476 else
1477 p = name + len;
1479 /* Now P points to the termination of the string, sans size.
1480 Scan backwards, looking for font properties. */
1481 for (; p > name; p = q)
1483 for (q = p - 1; q >= name; q--)
1485 if (q > name && *(q-1) == '\\')
1486 --q; /* Skip quoting backslashes. */
1487 else if (*q == ' ')
1488 break;
1491 word_start = q + 1;
1492 word_len = p - word_start;
1494 #define PROP_MATCH(STR) \
1495 (word_len == strlen (STR) \
1496 && memcmp (word_start, STR, strlen (STR)) == 0)
1497 #define PROP_SAVE(VAR, STR) \
1498 (VAR = NILP (VAR) ? font_intern_prop (STR, strlen (STR), 1) : VAR)
1500 if (PROP_MATCH ("Ultra-Light"))
1501 PROP_SAVE (weight, "ultra-light");
1502 else if (PROP_MATCH ("Light"))
1503 PROP_SAVE (weight, "light");
1504 else if (PROP_MATCH ("Book"))
1505 PROP_SAVE (weight, "book");
1506 else if (PROP_MATCH ("Medium"))
1507 PROP_SAVE (weight, "medium");
1508 else if (PROP_MATCH ("Semi-Bold"))
1509 PROP_SAVE (weight, "semi-bold");
1510 else if (PROP_MATCH ("Bold"))
1511 PROP_SAVE (weight, "bold");
1512 else if (PROP_MATCH ("Italic"))
1513 PROP_SAVE (slant, "italic");
1514 else if (PROP_MATCH ("Oblique"))
1515 PROP_SAVE (slant, "oblique");
1516 else if (PROP_MATCH ("Semi-Condensed"))
1517 PROP_SAVE (width, "semi-condensed");
1518 else if (PROP_MATCH ("Condensed"))
1519 PROP_SAVE (width, "condensed");
1520 /* An unknown word must be part of the font name. */
1521 else
1523 family_end = p;
1524 break;
1527 #undef PROP_MATCH
1528 #undef PROP_SAVE
1530 if (family_end)
1531 ASET (font, FONT_FAMILY_INDEX,
1532 font_intern_prop (name, family_end - name, 1));
1533 if (!NILP (size))
1534 ASET (font, FONT_SIZE_INDEX, size);
1535 if (!NILP (weight))
1536 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, weight);
1537 if (!NILP (slant))
1538 FONT_SET_STYLE (font, FONT_SLANT_INDEX, slant);
1539 if (!NILP (width))
1540 FONT_SET_STYLE (font, FONT_WIDTH_INDEX, width);
1543 return 0;
1546 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1547 NAME (NBYTES length), and return the name length. If
1548 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1551 font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes)
1553 Lisp_Object family, foundry;
1554 Lisp_Object val;
1555 int point_size;
1556 int i;
1557 char *p;
1558 char *lim;
1559 Lisp_Object styles[3];
1560 const char *style_names[3] = { "weight", "slant", "width" };
1562 family = AREF (font, FONT_FAMILY_INDEX);
1563 if (! NILP (family))
1565 if (SYMBOLP (family))
1566 family = SYMBOL_NAME (family);
1567 else
1568 family = Qnil;
1571 val = AREF (font, FONT_SIZE_INDEX);
1572 if (INTEGERP (val))
1574 if (XINT (val) != 0)
1575 pixel_size = XINT (val);
1576 point_size = -1;
1578 else
1580 eassert (FLOATP (val));
1581 pixel_size = -1;
1582 point_size = (int) XFLOAT_DATA (val);
1585 foundry = AREF (font, FONT_FOUNDRY_INDEX);
1586 if (! NILP (foundry))
1588 if (SYMBOLP (foundry))
1589 foundry = SYMBOL_NAME (foundry);
1590 else
1591 foundry = Qnil;
1594 for (i = 0; i < 3; i++)
1595 styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
1597 p = name;
1598 lim = name + nbytes;
1599 if (! NILP (family))
1601 int len = snprintf (p, lim - p, "%s", SSDATA (family));
1602 if (! (0 <= len && len < lim - p))
1603 return -1;
1604 p += len;
1606 if (point_size > 0)
1608 int len = snprintf (p, lim - p, "-%d" + (p == name), point_size);
1609 if (! (0 <= len && len < lim - p))
1610 return -1;
1611 p += len;
1613 else if (pixel_size > 0)
1615 int len = snprintf (p, lim - p, ":pixelsize=%d", pixel_size);
1616 if (! (0 <= len && len < lim - p))
1617 return -1;
1618 p += len;
1620 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1622 int len = snprintf (p, lim - p, ":foundry=%s",
1623 SSDATA (SYMBOL_NAME (AREF (font,
1624 FONT_FOUNDRY_INDEX))));
1625 if (! (0 <= len && len < lim - p))
1626 return -1;
1627 p += len;
1629 for (i = 0; i < 3; i++)
1630 if (! NILP (styles[i]))
1632 int len = snprintf (p, lim - p, ":%s=%s", style_names[i],
1633 SSDATA (SYMBOL_NAME (styles[i])));
1634 if (! (0 <= len && len < lim - p))
1635 return -1;
1636 p += len;
1639 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1641 int len = snprintf (p, lim - p, ":dpi=%"pI"d",
1642 XINT (AREF (font, FONT_DPI_INDEX)));
1643 if (! (0 <= len && len < lim - p))
1644 return -1;
1645 p += len;
1648 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1650 int len = snprintf (p, lim - p, ":spacing=%"pI"d",
1651 XINT (AREF (font, FONT_SPACING_INDEX)));
1652 if (! (0 <= len && len < lim - p))
1653 return -1;
1654 p += len;
1657 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1659 int len = snprintf (p, lim - p,
1660 (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0
1661 ? ":scalable=true"
1662 : ":scalable=false"));
1663 if (! (0 <= len && len < lim - p))
1664 return -1;
1665 p += len;
1668 return (p - name);
1671 /* Parse NAME (null terminated) and store information in FONT
1672 (font-spec or font-entity). If NAME is successfully parsed, return
1673 0. Otherwise return -1. */
1675 static int
1676 font_parse_name (char *name, ptrdiff_t namelen, Lisp_Object font)
1678 if (name[0] == '-' || strchr (name, '*') || strchr (name, '?'))
1679 return font_parse_xlfd (name, namelen, font);
1680 return font_parse_fcname (name, namelen, font);
1684 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1685 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1686 part. */
1688 void
1689 font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Object font_spec)
1691 int len;
1692 char *p0, *p1;
1694 if (! NILP (family)
1695 && NILP (AREF (font_spec, FONT_FAMILY_INDEX)))
1697 CHECK_STRING (family);
1698 len = SBYTES (family);
1699 p0 = SSDATA (family);
1700 p1 = strchr (p0, '-');
1701 if (p1)
1703 if ((*p0 != '*' && p1 - p0 > 0)
1704 && NILP (AREF (font_spec, FONT_FOUNDRY_INDEX)))
1705 Ffont_put (font_spec, QCfoundry, font_intern_prop (p0, p1 - p0, 1));
1706 p1++;
1707 len -= p1 - p0;
1708 Ffont_put (font_spec, QCfamily, font_intern_prop (p1, len, 1));
1710 else
1711 ASET (font_spec, FONT_FAMILY_INDEX, Fintern (family, Qnil));
1713 if (! NILP (registry))
1715 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1716 CHECK_STRING (registry);
1717 len = SBYTES (registry);
1718 p0 = SSDATA (registry);
1719 p1 = strchr (p0, '-');
1720 if (! p1)
1722 if (SDATA (registry)[len - 1] == '*')
1723 registry = concat2 (registry, build_string ("-*"));
1724 else
1725 registry = concat2 (registry, build_string ("*-*"));
1727 registry = Fdowncase (registry);
1728 ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil));
1733 /* This part (through the next ^L) is still experimental and not
1734 tested much. We may drastically change codes. */
1736 /* OTF handler */
1738 #if 0
1740 #define LGSTRING_HEADER_SIZE 6
1741 #define LGSTRING_GLYPH_SIZE 8
1743 static int
1744 check_gstring (Lisp_Object gstring)
1746 Lisp_Object val;
1747 ptrdiff_t i;
1748 int j;
1750 CHECK_VECTOR (gstring);
1751 val = AREF (gstring, 0);
1752 CHECK_VECTOR (val);
1753 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1754 goto err;
1755 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1756 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1757 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1758 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1759 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1760 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1761 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1762 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1763 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1764 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1765 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1767 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
1769 val = LGSTRING_GLYPH (gstring, i);
1770 CHECK_VECTOR (val);
1771 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1772 goto err;
1773 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1774 break;
1775 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1776 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1777 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1778 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1779 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1780 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1781 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1782 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1784 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1785 CHECK_VECTOR (val);
1786 if (ASIZE (val) < 3)
1787 goto err;
1788 for (j = 0; j < 3; j++)
1789 CHECK_NUMBER (AREF (val, j));
1792 return i;
1793 err:
1794 error ("Invalid glyph-string format");
1795 return -1;
1798 static void
1799 check_otf_features (Lisp_Object otf_features)
1801 Lisp_Object val;
1803 CHECK_CONS (otf_features);
1804 CHECK_SYMBOL (XCAR (otf_features));
1805 otf_features = XCDR (otf_features);
1806 CHECK_CONS (otf_features);
1807 CHECK_SYMBOL (XCAR (otf_features));
1808 otf_features = XCDR (otf_features);
1809 for (val = Fcar (otf_features); CONSP (val); val = XCDR (val))
1811 CHECK_SYMBOL (XCAR (val));
1812 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1813 error ("Invalid OTF GSUB feature: %s",
1814 SDATA (SYMBOL_NAME (XCAR (val))));
1816 otf_features = XCDR (otf_features);
1817 for (val = Fcar (otf_features); CONSP (val); val = XCDR (val))
1819 CHECK_SYMBOL (XCAR (val));
1820 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1821 error ("Invalid OTF GPOS feature: %s",
1822 SDATA (SYMBOL_NAME (XCAR (val))));
1826 #ifdef HAVE_LIBOTF
1827 #include <otf.h>
1829 Lisp_Object otf_list;
1831 static Lisp_Object
1832 otf_tag_symbol (OTF_Tag tag)
1834 char name[5];
1836 OTF_tag_name (tag, name);
1837 return Fintern (make_unibyte_string (name, 4), Qnil);
1840 static OTF *
1841 otf_open (Lisp_Object file)
1843 Lisp_Object val = Fassoc (file, otf_list);
1844 OTF *otf;
1846 if (! NILP (val))
1847 otf = XSAVE_VALUE (XCDR (val))->pointer;
1848 else
1850 otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL;
1851 val = make_save_value (otf, 0);
1852 otf_list = Fcons (Fcons (file, val), otf_list);
1854 return otf;
1858 /* Return a list describing which scripts/languages FONT supports by
1859 which GSUB/GPOS features of OpenType tables. See the comment of
1860 (struct font_driver).otf_capability. */
1862 Lisp_Object
1863 font_otf_capability (struct font *font)
1865 OTF *otf;
1866 Lisp_Object capability = Fcons (Qnil, Qnil);
1867 int i;
1869 otf = otf_open (font->props[FONT_FILE_INDEX]);
1870 if (! otf)
1871 return Qnil;
1872 for (i = 0; i < 2; i++)
1874 OTF_GSUB_GPOS *gsub_gpos;
1875 Lisp_Object script_list = Qnil;
1876 int j;
1878 if (OTF_get_features (otf, i == 0) < 0)
1879 continue;
1880 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1881 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1883 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1884 Lisp_Object langsys_list = Qnil;
1885 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1886 int k;
1888 for (k = script->LangSysCount; k >= 0; k--)
1890 OTF_LangSys *langsys;
1891 Lisp_Object feature_list = Qnil;
1892 Lisp_Object langsys_tag;
1893 int l;
1895 if (k == script->LangSysCount)
1897 langsys = &script->DefaultLangSys;
1898 langsys_tag = Qnil;
1900 else
1902 langsys = script->LangSys + k;
1903 langsys_tag
1904 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
1906 for (l = langsys->FeatureCount - 1; l >= 0; l--)
1908 OTF_Feature *feature
1909 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
1910 Lisp_Object feature_tag
1911 = otf_tag_symbol (feature->FeatureTag);
1913 feature_list = Fcons (feature_tag, feature_list);
1915 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1916 langsys_list);
1918 script_list = Fcons (Fcons (script_tag, langsys_list),
1919 script_list);
1922 if (i == 0)
1923 XSETCAR (capability, script_list);
1924 else
1925 XSETCDR (capability, script_list);
1928 return capability;
1931 /* Parse OTF features in SPEC and write a proper features spec string
1932 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1933 assured that the sufficient memory has already allocated for
1934 FEATURES. */
1936 static void
1937 generate_otf_features (Lisp_Object spec, char *features)
1939 Lisp_Object val;
1940 char *p;
1941 bool asterisk;
1943 p = features;
1944 *p = '\0';
1945 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
1947 val = XCAR (spec);
1948 CHECK_SYMBOL (val);
1949 if (p > features)
1950 *p++ = ',';
1951 if (SREF (SYMBOL_NAME (val), 0) == '*')
1953 asterisk = 1;
1954 *p++ = '*';
1956 else if (! asterisk)
1958 val = SYMBOL_NAME (val);
1959 p += esprintf (p, "%s", SDATA (val));
1961 else
1963 val = SYMBOL_NAME (val);
1964 p += esprintf (p, "~%s", SDATA (val));
1967 if (CONSP (spec))
1968 error ("OTF spec too long");
1971 Lisp_Object
1972 font_otf_DeviceTable (OTF_DeviceTable *device_table)
1974 int len = device_table->StartSize - device_table->EndSize + 1;
1976 return Fcons (make_number (len),
1977 make_unibyte_string (device_table->DeltaValue, len));
1980 Lisp_Object
1981 font_otf_ValueRecord (int value_format, OTF_ValueRecord *value_record)
1983 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
1985 if (value_format & OTF_XPlacement)
1986 ASET (val, 0, make_number (value_record->XPlacement));
1987 if (value_format & OTF_YPlacement)
1988 ASET (val, 1, make_number (value_record->YPlacement));
1989 if (value_format & OTF_XAdvance)
1990 ASET (val, 2, make_number (value_record->XAdvance));
1991 if (value_format & OTF_YAdvance)
1992 ASET (val, 3, make_number (value_record->YAdvance));
1993 if (value_format & OTF_XPlaDevice)
1994 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
1995 if (value_format & OTF_YPlaDevice)
1996 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
1997 if (value_format & OTF_XAdvDevice)
1998 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
1999 if (value_format & OTF_YAdvDevice)
2000 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
2001 return val;
2004 Lisp_Object
2005 font_otf_Anchor (OTF_Anchor *anchor)
2007 Lisp_Object val;
2009 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
2010 ASET (val, 0, make_number (anchor->XCoordinate));
2011 ASET (val, 1, make_number (anchor->YCoordinate));
2012 if (anchor->AnchorFormat == 2)
2013 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
2014 else
2016 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
2017 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
2019 return val;
2021 #endif /* HAVE_LIBOTF */
2022 #endif /* 0 */
2025 /* Font sorting */
2027 static unsigned font_score (Lisp_Object, Lisp_Object *);
2028 static int font_compare (const void *, const void *);
2029 static Lisp_Object font_sort_entities (Lisp_Object, Lisp_Object,
2030 Lisp_Object, int);
2032 static double
2033 font_rescale_ratio (Lisp_Object font_entity)
2035 Lisp_Object tail, elt;
2036 Lisp_Object name = Qnil;
2038 for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail))
2040 elt = XCAR (tail);
2041 if (FLOATP (XCDR (elt)))
2043 if (STRINGP (XCAR (elt)))
2045 if (NILP (name))
2046 name = Ffont_xlfd_name (font_entity, Qnil);
2047 if (fast_string_match_ignore_case (XCAR (elt), name) >= 0)
2048 return XFLOAT_DATA (XCDR (elt));
2050 else if (FONT_SPEC_P (XCAR (elt)))
2052 if (font_match_p (XCAR (elt), font_entity))
2053 return XFLOAT_DATA (XCDR (elt));
2057 return 1.0;
2060 /* We sort fonts by scoring each of them against a specified
2061 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2062 the value is, the closer the font is to the font-spec.
2064 The lowest 2 bits of the score are used for driver type. The font
2065 available by the most preferred font driver is 0.
2067 The 4 7-bit fields in the higher 28 bits are used for numeric properties
2068 WEIGHT, SLANT, WIDTH, and SIZE. */
2070 /* How many bits to shift to store the difference value of each font
2071 property in a score. Note that floats for FONT_TYPE_INDEX and
2072 FONT_REGISTRY_INDEX are not used. */
2073 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
2075 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2076 The return value indicates how different ENTITY is compared with
2077 SPEC_PROP. */
2079 static unsigned
2080 font_score (Lisp_Object entity, Lisp_Object *spec_prop)
2082 unsigned score = 0;
2083 int i;
2085 /* Score three style numeric fields. Maximum difference is 127. */
2086 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
2087 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
2089 EMACS_INT diff = ((XINT (AREF (entity, i)) >> 8)
2090 - (XINT (spec_prop[i]) >> 8));
2091 if (diff < 0)
2092 diff = - diff;
2093 score |= min (diff, 127) << sort_shift_bits[i];
2096 /* Score the size. Maximum difference is 127. */
2097 i = FONT_SIZE_INDEX;
2098 if (! NILP (spec_prop[FONT_SIZE_INDEX])
2099 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2101 /* We use the higher 6-bit for the actual size difference. The
2102 lowest bit is set if the DPI is different. */
2103 EMACS_INT diff;
2104 EMACS_INT pixel_size = XINT (spec_prop[FONT_SIZE_INDEX]);
2106 if (CONSP (Vface_font_rescale_alist))
2107 pixel_size *= font_rescale_ratio (entity);
2108 diff = pixel_size - XINT (AREF (entity, FONT_SIZE_INDEX));
2109 if (diff < 0)
2110 diff = - diff;
2111 diff <<= 1;
2112 if (! NILP (spec_prop[FONT_DPI_INDEX])
2113 && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX)))
2114 diff |= 1;
2115 if (! NILP (spec_prop[FONT_AVGWIDTH_INDEX])
2116 && ! EQ (spec_prop[FONT_AVGWIDTH_INDEX], AREF (entity, FONT_AVGWIDTH_INDEX)))
2117 diff |= 1;
2118 score |= min (diff, 127) << sort_shift_bits[FONT_SIZE_INDEX];
2121 return score;
2125 /* Concatenate all elements of LIST into one vector. LIST is a list
2126 of font-entity vectors. */
2128 static Lisp_Object
2129 font_vconcat_entity_vectors (Lisp_Object list)
2131 int nargs = XINT (Flength (list));
2132 Lisp_Object *args = alloca (word_size * nargs);
2133 int i;
2135 for (i = 0; i < nargs; i++, list = XCDR (list))
2136 args[i] = XCAR (list);
2137 return Fvconcat (nargs, args);
2141 /* The structure for elements being sorted by qsort. */
2142 struct font_sort_data
2144 unsigned score;
2145 int font_driver_preference;
2146 Lisp_Object entity;
2150 /* The comparison function for qsort. */
2152 static int
2153 font_compare (const void *d1, const void *d2)
2155 const struct font_sort_data *data1 = d1;
2156 const struct font_sort_data *data2 = d2;
2158 if (data1->score < data2->score)
2159 return -1;
2160 else if (data1->score > data2->score)
2161 return 1;
2162 return (data1->font_driver_preference - data2->font_driver_preference);
2166 /* Sort each font-entity vector in LIST by closeness to font-spec PREFER.
2167 If PREFER specifies a point-size, calculate the corresponding
2168 pixel-size from QCdpi property of PREFER or from the Y-resolution
2169 of FRAME before sorting.
2171 If BEST-ONLY is nonzero, return the best matching entity (that
2172 supports the character BEST-ONLY if BEST-ONLY is positive, or any
2173 if BEST-ONLY is negative). Otherwise, return the sorted result as
2174 a single vector of font-entities.
2176 This function does no optimization for the case that the total
2177 number of elements is 1. The caller should avoid calling this in
2178 such a case. */
2180 static Lisp_Object
2181 font_sort_entities (Lisp_Object list, Lisp_Object prefer, Lisp_Object frame, int best_only)
2183 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2184 int len, maxlen, i;
2185 struct font_sort_data *data;
2186 unsigned best_score;
2187 Lisp_Object best_entity;
2188 struct frame *f = XFRAME (frame);
2189 Lisp_Object tail, vec IF_LINT (= Qnil);
2190 USE_SAFE_ALLOCA;
2192 for (i = FONT_WEIGHT_INDEX; i <= FONT_AVGWIDTH_INDEX; i++)
2193 prefer_prop[i] = AREF (prefer, i);
2194 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2195 prefer_prop[FONT_SIZE_INDEX]
2196 = make_number (font_pixel_size (XFRAME (frame), prefer));
2198 if (NILP (XCDR (list)))
2200 /* What we have to take care of is this single vector. */
2201 vec = XCAR (list);
2202 maxlen = ASIZE (vec);
2204 else if (best_only)
2206 /* We don't have to perform sort, so there's no need of creating
2207 a single vector. But, we must find the length of the longest
2208 vector. */
2209 maxlen = 0;
2210 for (tail = list; CONSP (tail); tail = XCDR (tail))
2211 if (maxlen < ASIZE (XCAR (tail)))
2212 maxlen = ASIZE (XCAR (tail));
2214 else
2216 /* We have to create a single vector to sort it. */
2217 vec = font_vconcat_entity_vectors (list);
2218 maxlen = ASIZE (vec);
2221 data = SAFE_ALLOCA (maxlen * sizeof *data);
2222 best_score = 0xFFFFFFFF;
2223 best_entity = Qnil;
2225 for (tail = list; CONSP (tail); tail = XCDR (tail))
2227 int font_driver_preference = 0;
2228 Lisp_Object current_font_driver;
2230 if (best_only)
2231 vec = XCAR (tail);
2232 len = ASIZE (vec);
2234 /* We are sure that the length of VEC > 0. */
2235 current_font_driver = AREF (AREF (vec, 0), FONT_TYPE_INDEX);
2236 /* Score the elements. */
2237 for (i = 0; i < len; i++)
2239 data[i].entity = AREF (vec, i);
2240 data[i].score
2241 = ((best_only <= 0 || font_has_char (f, data[i].entity, best_only)
2242 > 0)
2243 ? font_score (data[i].entity, prefer_prop)
2244 : 0xFFFFFFFF);
2245 if (best_only && best_score > data[i].score)
2247 best_score = data[i].score;
2248 best_entity = data[i].entity;
2249 if (best_score == 0)
2250 break;
2252 if (! EQ (current_font_driver, AREF (AREF (vec, i), FONT_TYPE_INDEX)))
2254 current_font_driver = AREF (AREF (vec, i), FONT_TYPE_INDEX);
2255 font_driver_preference++;
2257 data[i].font_driver_preference = font_driver_preference;
2260 /* Sort if necessary. */
2261 if (! best_only)
2263 qsort (data, len, sizeof *data, font_compare);
2264 for (i = 0; i < len; i++)
2265 ASET (vec, i, data[i].entity);
2266 break;
2268 else
2269 vec = best_entity;
2272 SAFE_FREE ();
2274 FONT_ADD_LOG ("sort-by", prefer, vec);
2275 return vec;
2279 /* API of Font Service Layer. */
2281 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2282 sort_shift_bits. Finternal_set_font_selection_order calls this
2283 function with font_sort_order after setting up it. */
2285 void
2286 font_update_sort_order (int *order)
2288 int i, shift_bits;
2290 for (i = 0, shift_bits = 23; i < 4; i++, shift_bits -= 7)
2292 int xlfd_idx = order[i];
2294 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2295 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2296 else if (xlfd_idx == XLFD_SLANT_INDEX)
2297 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2298 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2299 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2300 else
2301 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2305 static bool
2306 font_check_otf_features (Lisp_Object script, Lisp_Object langsys,
2307 Lisp_Object features, Lisp_Object table)
2309 Lisp_Object val;
2310 bool negative;
2312 table = assq_no_quit (script, table);
2313 if (NILP (table))
2314 return 0;
2315 table = XCDR (table);
2316 if (! NILP (langsys))
2318 table = assq_no_quit (langsys, table);
2319 if (NILP (table))
2320 return 0;
2322 else
2324 val = assq_no_quit (Qnil, table);
2325 if (NILP (val))
2326 table = XCAR (table);
2327 else
2328 table = val;
2330 table = XCDR (table);
2331 for (negative = 0; CONSP (features); features = XCDR (features))
2333 if (NILP (XCAR (features)))
2335 negative = 1;
2336 continue;
2338 if (NILP (Fmemq (XCAR (features), table)) != negative)
2339 return 0;
2341 return 1;
2344 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2346 static bool
2347 font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
2349 Lisp_Object script, langsys = Qnil, gsub = Qnil, gpos = Qnil;
2351 script = XCAR (spec);
2352 spec = XCDR (spec);
2353 if (! NILP (spec))
2355 langsys = XCAR (spec);
2356 spec = XCDR (spec);
2357 if (! NILP (spec))
2359 gsub = XCAR (spec);
2360 spec = XCDR (spec);
2361 if (! NILP (spec))
2362 gpos = XCAR (spec);
2366 if (! NILP (gsub) && ! font_check_otf_features (script, langsys, gsub,
2367 XCAR (otf_capability)))
2368 return 0;
2369 if (! NILP (gpos) && ! font_check_otf_features (script, langsys, gpos,
2370 XCDR (otf_capability)))
2371 return 0;
2372 return 1;
2377 /* Check if FONT (font-entity or font-object) matches with the font
2378 specification SPEC. */
2380 bool
2381 font_match_p (Lisp_Object spec, Lisp_Object font)
2383 Lisp_Object prop[FONT_SPEC_MAX], *props;
2384 Lisp_Object extra, font_extra;
2385 int i;
2387 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2388 if (! NILP (AREF (spec, i))
2389 && ! NILP (AREF (font, i))
2390 && ! EQ (AREF (spec, i), AREF (font, i)))
2391 return 0;
2392 props = XFONT_SPEC (spec)->props;
2393 if (FLOATP (props[FONT_SIZE_INDEX]))
2395 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
2396 prop[i] = AREF (spec, i);
2397 prop[FONT_SIZE_INDEX]
2398 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2399 props = prop;
2402 if (font_score (font, props) > 0)
2403 return 0;
2404 extra = AREF (spec, FONT_EXTRA_INDEX);
2405 font_extra = AREF (font, FONT_EXTRA_INDEX);
2406 for (; CONSP (extra); extra = XCDR (extra))
2408 Lisp_Object key = XCAR (XCAR (extra));
2409 Lisp_Object val = XCDR (XCAR (extra)), val2;
2411 if (EQ (key, QClang))
2413 val2 = assq_no_quit (key, font_extra);
2414 if (NILP (val2))
2415 return 0;
2416 val2 = XCDR (val2);
2417 if (CONSP (val))
2419 if (! CONSP (val2))
2420 return 0;
2421 while (CONSP (val))
2422 if (NILP (Fmemq (val, val2)))
2423 return 0;
2425 else
2426 if (CONSP (val2)
2427 ? NILP (Fmemq (val, XCDR (val2)))
2428 : ! EQ (val, val2))
2429 return 0;
2431 else if (EQ (key, QCscript))
2433 val2 = assq_no_quit (val, Vscript_representative_chars);
2434 if (CONSP (val2))
2436 val2 = XCDR (val2);
2437 if (CONSP (val2))
2439 /* All characters in the list must be supported. */
2440 for (; CONSP (val2); val2 = XCDR (val2))
2442 if (! CHARACTERP (XCAR (val2)))
2443 continue;
2444 if (font_encode_char (font, XFASTINT (XCAR (val2)))
2445 == FONT_INVALID_CODE)
2446 return 0;
2449 else if (VECTORP (val2))
2451 /* At most one character in the vector must be supported. */
2452 for (i = 0; i < ASIZE (val2); i++)
2454 if (! CHARACTERP (AREF (val2, i)))
2455 continue;
2456 if (font_encode_char (font, XFASTINT (AREF (val2, i)))
2457 != FONT_INVALID_CODE)
2458 break;
2460 if (i == ASIZE (val2))
2461 return 0;
2465 else if (EQ (key, QCotf))
2467 struct font *fontp;
2469 if (! FONT_OBJECT_P (font))
2470 return 0;
2471 fontp = XFONT_OBJECT (font);
2472 if (! fontp->driver->otf_capability)
2473 return 0;
2474 val2 = fontp->driver->otf_capability (fontp);
2475 if (NILP (val2) || ! font_check_otf (val, val2))
2476 return 0;
2480 return 1;
2484 /* Font cache
2486 Each font backend has the callback function get_cache, and it
2487 returns a cons cell of which cdr part can be freely used for
2488 caching fonts. The cons cell may be shared by multiple frames
2489 and/or multiple font drivers. So, we arrange the cdr part as this:
2491 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2493 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2494 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2495 cons (FONT-SPEC FONT-ENTITY ...). */
2497 static void font_prepare_cache (FRAME_PTR, struct font_driver *);
2498 static void font_finish_cache (FRAME_PTR, struct font_driver *);
2499 static Lisp_Object font_get_cache (FRAME_PTR, struct font_driver *);
2500 static void font_clear_cache (FRAME_PTR, Lisp_Object,
2501 struct font_driver *);
2503 static void
2504 font_prepare_cache (FRAME_PTR f, struct font_driver *driver)
2506 Lisp_Object cache, val;
2508 cache = driver->get_cache (f);
2509 val = XCDR (cache);
2510 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2511 val = XCDR (val);
2512 if (NILP (val))
2514 val = Fcons (driver->type, Fcons (make_number (1), Qnil));
2515 XSETCDR (cache, Fcons (val, XCDR (cache)));
2517 else
2519 val = XCDR (XCAR (val));
2520 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2525 static void
2526 font_finish_cache (FRAME_PTR f, struct font_driver *driver)
2528 Lisp_Object cache, val, tmp;
2531 cache = driver->get_cache (f);
2532 val = XCDR (cache);
2533 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2534 cache = val, val = XCDR (val);
2535 eassert (! NILP (val));
2536 tmp = XCDR (XCAR (val));
2537 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2538 if (XINT (XCAR (tmp)) == 0)
2540 font_clear_cache (f, XCAR (val), driver);
2541 XSETCDR (cache, XCDR (val));
2546 static Lisp_Object
2547 font_get_cache (FRAME_PTR f, struct font_driver *driver)
2549 Lisp_Object val = driver->get_cache (f);
2550 Lisp_Object type = driver->type;
2552 eassert (CONSP (val));
2553 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2554 eassert (CONSP (val));
2555 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2556 val = XCDR (XCAR (val));
2557 return val;
2560 static int num_fonts;
2562 static void
2563 font_clear_cache (FRAME_PTR f, Lisp_Object cache, struct font_driver *driver)
2565 Lisp_Object tail, elt;
2566 Lisp_Object tail2, entity;
2568 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2569 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2571 elt = XCAR (tail);
2572 /* elt should have the form (FONT-SPEC FONT-ENTITY ...) */
2573 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2575 for (tail2 = XCDR (elt); CONSP (tail2); tail2 = XCDR (tail2))
2577 entity = XCAR (tail2);
2579 if (FONT_ENTITY_P (entity)
2580 && EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2582 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2584 for (; CONSP (objlist); objlist = XCDR (objlist))
2586 Lisp_Object val = XCAR (objlist);
2587 struct font *font = XFONT_OBJECT (val);
2589 if (! NILP (AREF (val, FONT_TYPE_INDEX)))
2591 eassert (font && driver == font->driver);
2592 driver->close (f, font);
2593 num_fonts--;
2596 if (driver->free_entity)
2597 driver->free_entity (entity);
2602 XSETCDR (cache, Qnil);
2606 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2608 /* Check each font-entity in VEC, and return a list of font-entities
2609 that satisfy these conditions:
2610 (1) matches with SPEC and SIZE if SPEC is not nil, and
2611 (2) doesn't match with any regexps in Vface_ignored_fonts (if non-nil).
2614 static Lisp_Object
2615 font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size)
2617 Lisp_Object entity, val;
2618 enum font_property_index prop;
2619 int i;
2621 for (val = Qnil, i = ASIZE (vec) - 1; i >= 0; i--)
2623 entity = AREF (vec, i);
2624 if (! NILP (Vface_ignored_fonts))
2626 char name[256];
2627 ptrdiff_t namelen;
2628 Lisp_Object tail, regexp;
2630 namelen = font_unparse_xlfd (entity, 0, name, 256);
2631 if (namelen >= 0)
2633 for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
2635 regexp = XCAR (tail);
2636 if (STRINGP (regexp)
2637 && fast_c_string_match_ignore_case (regexp, name,
2638 namelen) >= 0)
2639 break;
2641 if (CONSP (tail))
2642 continue;
2645 if (NILP (spec))
2647 val = Fcons (entity, val);
2648 continue;
2650 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++)
2651 if (INTEGERP (AREF (spec, prop))
2652 && ((XINT (AREF (spec, prop)) >> 8)
2653 != (XINT (AREF (entity, prop)) >> 8)))
2654 prop = FONT_SPEC_MAX;
2655 if (prop < FONT_SPEC_MAX
2656 && size
2657 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2659 int diff = XINT (AREF (entity, FONT_SIZE_INDEX)) - size;
2661 if (diff != 0
2662 && (diff < 0 ? -diff > FONT_PIXEL_SIZE_QUANTUM
2663 : diff > FONT_PIXEL_SIZE_QUANTUM))
2664 prop = FONT_SPEC_MAX;
2666 if (prop < FONT_SPEC_MAX
2667 && INTEGERP (AREF (spec, FONT_DPI_INDEX))
2668 && INTEGERP (AREF (entity, FONT_DPI_INDEX))
2669 && XINT (AREF (entity, FONT_DPI_INDEX)) != 0
2670 && ! EQ (AREF (spec, FONT_DPI_INDEX), AREF (entity, FONT_DPI_INDEX)))
2671 prop = FONT_SPEC_MAX;
2672 if (prop < FONT_SPEC_MAX
2673 && INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
2674 && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
2675 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) != 0
2676 && ! EQ (AREF (spec, FONT_AVGWIDTH_INDEX),
2677 AREF (entity, FONT_AVGWIDTH_INDEX)))
2678 prop = FONT_SPEC_MAX;
2679 if (prop < FONT_SPEC_MAX)
2680 val = Fcons (entity, val);
2682 return (Fvconcat (1, &val));
2686 /* Return a list of vectors of font-entities matching with SPEC on
2687 FRAME. Each elements in the list is a vector of entities from the
2688 same font-driver. */
2690 Lisp_Object
2691 font_list_entities (Lisp_Object frame, Lisp_Object spec)
2693 FRAME_PTR f = XFRAME (frame);
2694 struct font_driver_list *driver_list = f->font_driver_list;
2695 Lisp_Object ftype, val;
2696 Lisp_Object list = Qnil;
2697 int size;
2698 bool need_filtering = 0;
2699 int i;
2701 eassert (FONT_SPEC_P (spec));
2703 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2704 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2705 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2706 size = font_pixel_size (f, spec);
2707 else
2708 size = 0;
2710 ftype = AREF (spec, FONT_TYPE_INDEX);
2711 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2712 ASET (scratch_font_spec, i, AREF (spec, i));
2713 for (i = FONT_WEIGHT_INDEX; i < FONT_EXTRA_INDEX; i++)
2714 if (i != FONT_SPACING_INDEX)
2716 ASET (scratch_font_spec, i, Qnil);
2717 if (! NILP (AREF (spec, i)))
2718 need_filtering = 1;
2720 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX));
2721 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
2723 for (i = 0; driver_list; driver_list = driver_list->next)
2724 if (driver_list->on
2725 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2727 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2729 ASET (scratch_font_spec, FONT_TYPE_INDEX, driver_list->driver->type);
2730 val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2731 if (CONSP (val))
2732 val = XCDR (val);
2733 else
2735 Lisp_Object copy;
2737 val = driver_list->driver->list (frame, scratch_font_spec);
2738 if (NILP (val))
2739 val = zero_vector;
2740 else
2741 val = Fvconcat (1, &val);
2742 copy = copy_font_spec (scratch_font_spec);
2743 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2744 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2746 if (ASIZE (val) > 0
2747 && (need_filtering
2748 || ! NILP (Vface_ignored_fonts)))
2749 val = font_delete_unmatched (val, need_filtering ? spec : Qnil, size);
2750 if (ASIZE (val) > 0)
2751 list = Fcons (val, list);
2754 list = Fnreverse (list);
2755 FONT_ADD_LOG ("list", spec, list);
2756 return list;
2760 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2761 nil, is an array of face's attributes, which specifies preferred
2762 font-related attributes. */
2764 static Lisp_Object
2765 font_matching_entity (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
2767 struct font_driver_list *driver_list = f->font_driver_list;
2768 Lisp_Object ftype, size, entity;
2769 Lisp_Object frame;
2770 Lisp_Object work = copy_font_spec (spec);
2772 XSETFRAME (frame, f);
2773 ftype = AREF (spec, FONT_TYPE_INDEX);
2774 size = AREF (spec, FONT_SIZE_INDEX);
2776 if (FLOATP (size))
2777 ASET (work, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2778 FONT_SET_STYLE (work, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
2779 FONT_SET_STYLE (work, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
2780 FONT_SET_STYLE (work, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
2782 entity = Qnil;
2783 for (; driver_list; driver_list = driver_list->next)
2784 if (driver_list->on
2785 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2787 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2788 Lisp_Object copy;
2790 ASET (work, FONT_TYPE_INDEX, driver_list->driver->type);
2791 entity = assoc_no_quit (work, XCDR (cache));
2792 if (CONSP (entity))
2793 entity = XCDR (entity);
2794 else
2796 entity = driver_list->driver->match (frame, work);
2797 copy = copy_font_spec (work);
2798 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2799 XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache)));
2801 if (! NILP (entity))
2802 break;
2804 FONT_ADD_LOG ("match", work, entity);
2805 return entity;
2809 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2810 opened font object. */
2812 static Lisp_Object
2813 font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
2815 struct font_driver_list *driver_list;
2816 Lisp_Object objlist, size, val, font_object;
2817 struct font *font;
2818 int min_width, height;
2819 int scaled_pixel_size = pixel_size;
2821 eassert (FONT_ENTITY_P (entity));
2822 size = AREF (entity, FONT_SIZE_INDEX);
2823 if (XINT (size) != 0)
2824 scaled_pixel_size = pixel_size = XINT (size);
2825 else if (CONSP (Vface_font_rescale_alist))
2826 scaled_pixel_size = pixel_size * font_rescale_ratio (entity);
2828 val = AREF (entity, FONT_TYPE_INDEX);
2829 for (driver_list = f->font_driver_list;
2830 driver_list && ! EQ (driver_list->driver->type, val);
2831 driver_list = driver_list->next);
2832 if (! driver_list)
2833 return Qnil;
2835 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2836 objlist = XCDR (objlist))
2838 Lisp_Object fn = XCAR (objlist);
2839 if (! NILP (AREF (fn, FONT_TYPE_INDEX))
2840 && XFONT_OBJECT (fn)->pixel_size == pixel_size)
2842 if (driver_list->driver->cached_font_ok == NULL
2843 || driver_list->driver->cached_font_ok (f, fn, entity))
2844 return fn;
2848 font_object = driver_list->driver->open (f, entity, scaled_pixel_size);
2849 if (!NILP (font_object))
2850 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
2851 FONT_ADD_LOG ("open", entity, font_object);
2852 if (NILP (font_object))
2853 return Qnil;
2854 ASET (entity, FONT_OBJLIST_INDEX,
2855 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2856 num_fonts++;
2858 font = XFONT_OBJECT (font_object);
2859 min_width = (font->min_width ? font->min_width
2860 : font->average_width ? font->average_width
2861 : font->space_width ? font->space_width
2862 : 1);
2863 height = (font->height ? font->height : 1);
2864 #ifdef HAVE_WINDOW_SYSTEM
2865 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
2866 if (FRAME_X_DISPLAY_INFO (f)->n_fonts == 1)
2868 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
2869 FRAME_SMALLEST_FONT_HEIGHT (f) = height;
2870 fonts_changed_p = 1;
2872 else
2874 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
2875 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
2876 if (FRAME_SMALLEST_FONT_HEIGHT (f) > height)
2877 FRAME_SMALLEST_FONT_HEIGHT (f) = height, fonts_changed_p = 1;
2879 #endif
2881 return font_object;
2885 /* Close FONT_OBJECT that is opened on frame F. */
2887 static void
2888 font_close_object (FRAME_PTR f, Lisp_Object font_object)
2890 struct font *font = XFONT_OBJECT (font_object);
2892 if (NILP (AREF (font_object, FONT_TYPE_INDEX)))
2893 /* Already closed. */
2894 return;
2895 FONT_ADD_LOG ("close", font_object, Qnil);
2896 font->driver->close (f, font);
2897 #ifdef HAVE_WINDOW_SYSTEM
2898 eassert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
2899 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
2900 #endif
2901 num_fonts--;
2905 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2906 FONT is a font-entity and it must be opened to check. */
2909 font_has_char (FRAME_PTR f, Lisp_Object font, int c)
2911 struct font *fontp;
2913 if (FONT_ENTITY_P (font))
2915 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
2916 struct font_driver_list *driver_list;
2918 for (driver_list = f->font_driver_list;
2919 driver_list && ! EQ (driver_list->driver->type, type);
2920 driver_list = driver_list->next);
2921 if (! driver_list)
2922 return 0;
2923 if (! driver_list->driver->has_char)
2924 return -1;
2925 return driver_list->driver->has_char (font, c);
2928 eassert (FONT_OBJECT_P (font));
2929 fontp = XFONT_OBJECT (font);
2930 if (fontp->driver->has_char)
2932 int result = fontp->driver->has_char (font, c);
2934 if (result >= 0)
2935 return result;
2937 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
2941 /* Return the glyph ID of FONT_OBJECT for character C. */
2943 static unsigned
2944 font_encode_char (Lisp_Object font_object, int c)
2946 struct font *font;
2948 eassert (FONT_OBJECT_P (font_object));
2949 font = XFONT_OBJECT (font_object);
2950 return font->driver->encode_char (font, c);
2954 /* Return the name of FONT_OBJECT. */
2956 Lisp_Object
2957 font_get_name (Lisp_Object font_object)
2959 eassert (FONT_OBJECT_P (font_object));
2960 return AREF (font_object, FONT_NAME_INDEX);
2964 /* Create a new font spec from FONT_NAME, and return it. If FONT_NAME
2965 could not be parsed by font_parse_name, return Qnil. */
2967 Lisp_Object
2968 font_spec_from_name (Lisp_Object font_name)
2970 Lisp_Object spec = Ffont_spec (0, NULL);
2972 CHECK_STRING (font_name);
2973 if (font_parse_name (SSDATA (font_name), SBYTES (font_name), spec) == -1)
2974 return Qnil;
2975 font_put_extra (spec, QCname, font_name);
2976 font_put_extra (spec, QCuser_spec, font_name);
2977 return spec;
2981 void
2982 font_clear_prop (Lisp_Object *attrs, enum font_property_index prop)
2984 Lisp_Object font = attrs[LFACE_FONT_INDEX];
2986 if (! FONTP (font))
2987 return;
2989 if (! NILP (Ffont_get (font, QCname)))
2991 font = copy_font_spec (font);
2992 font_put_extra (font, QCname, Qnil);
2995 if (NILP (AREF (font, prop))
2996 && prop != FONT_FAMILY_INDEX
2997 && prop != FONT_FOUNDRY_INDEX
2998 && prop != FONT_WIDTH_INDEX
2999 && prop != FONT_SIZE_INDEX)
3000 return;
3001 if (EQ (font, attrs[LFACE_FONT_INDEX]))
3002 font = copy_font_spec (font);
3003 ASET (font, prop, Qnil);
3004 if (prop == FONT_FAMILY_INDEX || prop == FONT_FOUNDRY_INDEX)
3006 if (prop == FONT_FAMILY_INDEX)
3008 ASET (font, FONT_FOUNDRY_INDEX, Qnil);
3009 /* If we are setting the font family, we must also clear
3010 FONT_WIDTH_INDEX to avoid rejecting families that lack
3011 support for some widths. */
3012 ASET (font, FONT_WIDTH_INDEX, Qnil);
3014 ASET (font, FONT_ADSTYLE_INDEX, Qnil);
3015 ASET (font, FONT_REGISTRY_INDEX, Qnil);
3016 ASET (font, FONT_SIZE_INDEX, Qnil);
3017 ASET (font, FONT_DPI_INDEX, Qnil);
3018 ASET (font, FONT_SPACING_INDEX, Qnil);
3019 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3021 else if (prop == FONT_SIZE_INDEX)
3023 ASET (font, FONT_DPI_INDEX, Qnil);
3024 ASET (font, FONT_SPACING_INDEX, Qnil);
3025 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3027 else if (prop == FONT_WIDTH_INDEX)
3028 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3029 attrs[LFACE_FONT_INDEX] = font;
3032 /* Select a font from ENTITIES (list of font-entity vectors) that
3033 supports C and is the best match for ATTRS and PIXEL_SIZE. */
3035 static Lisp_Object
3036 font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs, int pixel_size, int c)
3038 Lisp_Object font_entity;
3039 Lisp_Object prefer;
3040 int i;
3041 FRAME_PTR f = XFRAME (frame);
3043 if (NILP (XCDR (entities))
3044 && ASIZE (XCAR (entities)) == 1)
3046 font_entity = AREF (XCAR (entities), 0);
3047 if (c < 0 || font_has_char (f, font_entity, c) > 0)
3048 return font_entity;
3049 return Qnil;
3052 /* Sort fonts by properties specified in ATTRS. */
3053 prefer = scratch_font_prefer;
3055 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3056 ASET (prefer, i, Qnil);
3057 if (FONTP (attrs[LFACE_FONT_INDEX]))
3059 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3061 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3062 ASET (prefer, i, AREF (face_font, i));
3064 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
3065 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
3066 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
3067 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
3068 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
3069 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
3070 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
3072 return font_sort_entities (entities, prefer, frame, c);
3075 /* Return a font-entity that satisfies SPEC and is the best match for
3076 face's font related attributes in ATTRS. C, if not negative, is a
3077 character that the entity must support. */
3079 Lisp_Object
3080 font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
3082 Lisp_Object work;
3083 Lisp_Object frame, entities, val;
3084 Lisp_Object foundry[3], *family, registry[3], adstyle[3];
3085 int pixel_size;
3086 int i, j, k, l;
3087 USE_SAFE_ALLOCA;
3089 registry[0] = AREF (spec, FONT_REGISTRY_INDEX);
3090 if (NILP (registry[0]))
3092 registry[0] = DEFAULT_ENCODING;
3093 registry[1] = Qascii_0;
3094 registry[2] = zero_vector;
3096 else
3097 registry[1] = zero_vector;
3099 if (c >= 0 && ! NILP (AREF (spec, FONT_REGISTRY_INDEX)))
3101 struct charset *encoding, *repertory;
3103 if (font_registry_charsets (AREF (spec, FONT_REGISTRY_INDEX),
3104 &encoding, &repertory) < 0)
3105 return Qnil;
3106 if (repertory
3107 && ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
3108 return Qnil;
3109 else if (c > encoding->max_char)
3110 return Qnil;
3113 work = copy_font_spec (spec);
3114 ASET (work, FONT_TYPE_INDEX, AREF (spec, FONT_TYPE_INDEX));
3115 XSETFRAME (frame, f);
3116 pixel_size = font_pixel_size (f, spec);
3117 if (pixel_size == 0 && INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
3119 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3121 pixel_size = POINT_TO_PIXEL (pt / 10, f->resy);
3123 ASET (work, FONT_SIZE_INDEX, Qnil);
3124 foundry[0] = AREF (work, FONT_FOUNDRY_INDEX);
3125 if (! NILP (foundry[0]))
3126 foundry[1] = zero_vector;
3127 else if (STRINGP (attrs[LFACE_FOUNDRY_INDEX]))
3129 val = attrs[LFACE_FOUNDRY_INDEX];
3130 foundry[0] = font_intern_prop (SSDATA (val), SBYTES (val), 1);
3131 foundry[1] = Qnil;
3132 foundry[2] = zero_vector;
3134 else
3135 foundry[0] = Qnil, foundry[1] = zero_vector;
3137 adstyle[0] = AREF (work, FONT_ADSTYLE_INDEX);
3138 if (! NILP (adstyle[0]))
3139 adstyle[1] = zero_vector;
3140 else if (FONTP (attrs[LFACE_FONT_INDEX]))
3142 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3144 if (! NILP (AREF (face_font, FONT_ADSTYLE_INDEX)))
3146 adstyle[0] = AREF (face_font, FONT_ADSTYLE_INDEX);
3147 adstyle[1] = Qnil;
3148 adstyle[2] = zero_vector;
3150 else
3151 adstyle[0] = Qnil, adstyle[1] = zero_vector;
3153 else
3154 adstyle[0] = Qnil, adstyle[1] = zero_vector;
3157 val = AREF (work, FONT_FAMILY_INDEX);
3158 if (NILP (val) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
3160 val = attrs[LFACE_FAMILY_INDEX];
3161 val = font_intern_prop (SSDATA (val), SBYTES (val), 1);
3163 if (NILP (val))
3165 family = alloca ((sizeof family[0]) * 2);
3166 family[0] = Qnil;
3167 family[1] = zero_vector; /* terminator. */
3169 else
3171 Lisp_Object alters
3172 = Fassoc_string (val, Vface_alternative_font_family_alist, Qt);
3174 if (! NILP (alters))
3176 EMACS_INT alterslen = XFASTINT (Flength (alters));
3177 SAFE_ALLOCA_LISP (family, alterslen + 2);
3178 for (i = 0; CONSP (alters); i++, alters = XCDR (alters))
3179 family[i] = XCAR (alters);
3180 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3181 family[i++] = Qnil;
3182 family[i] = zero_vector;
3184 else
3186 family = alloca ((sizeof family[0]) * 3);
3187 i = 0;
3188 family[i++] = val;
3189 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3190 family[i++] = Qnil;
3191 family[i] = zero_vector;
3195 for (i = 0; SYMBOLP (family[i]); i++)
3197 ASET (work, FONT_FAMILY_INDEX, family[i]);
3198 for (j = 0; SYMBOLP (foundry[j]); j++)
3200 ASET (work, FONT_FOUNDRY_INDEX, foundry[j]);
3201 for (k = 0; SYMBOLP (registry[k]); k++)
3203 ASET (work, FONT_REGISTRY_INDEX, registry[k]);
3204 for (l = 0; SYMBOLP (adstyle[l]); l++)
3206 ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
3207 entities = font_list_entities (frame, work);
3208 if (! NILP (entities))
3210 val = font_select_entity (frame, entities,
3211 attrs, pixel_size, c);
3212 if (! NILP (val))
3213 return val;
3220 SAFE_FREE ();
3221 return Qnil;
3225 Lisp_Object
3226 font_open_for_lface (FRAME_PTR f, Lisp_Object entity, Lisp_Object *attrs, Lisp_Object spec)
3228 int size;
3230 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX))
3231 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
3232 size = XINT (AREF (entity, FONT_SIZE_INDEX));
3233 else if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
3234 size = font_pixel_size (f, spec);
3235 else
3237 double pt;
3238 if (INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
3239 pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3240 else
3242 struct face *def = FACE_FROM_ID (f, DEFAULT_FACE_ID);
3243 Lisp_Object height = def->lface[LFACE_HEIGHT_INDEX];
3244 eassert (INTEGERP (height));
3245 pt = XINT (height);
3248 pt /= 10;
3249 size = POINT_TO_PIXEL (pt, f->resy);
3250 #ifdef HAVE_NS
3251 if (size == 0)
3253 Lisp_Object ffsize = get_frame_param (f, Qfontsize);
3254 size = NUMBERP (ffsize) ? POINT_TO_PIXEL (XINT (ffsize), f->resy) : 0;
3256 #endif
3258 return font_open_entity (f, entity, size);
3262 /* Find a font that satisfies SPEC and is the best match for
3263 face's attributes in ATTRS on FRAME, and return the opened
3264 font-object. */
3266 Lisp_Object
3267 font_load_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
3269 Lisp_Object entity, name;
3271 entity = font_find_for_lface (f, attrs, spec, -1);
3272 if (NILP (entity))
3274 /* No font is listed for SPEC, but each font-backend may have
3275 different criteria about "font matching". So, try it. */
3276 entity = font_matching_entity (f, attrs, spec);
3277 if (NILP (entity))
3278 return Qnil;
3280 /* Don't lose the original name that was put in initially. We need
3281 it to re-apply the font when font parameters (like hinting or dpi) have
3282 changed. */
3283 entity = font_open_for_lface (f, entity, attrs, spec);
3284 if (!NILP (entity))
3286 name = Ffont_get (spec, QCuser_spec);
3287 if (STRINGP (name)) font_put_extra (entity, QCuser_spec, name);
3289 return entity;
3293 /* Make FACE on frame F ready to use the font opened for FACE. */
3295 void
3296 font_prepare_for_face (FRAME_PTR f, struct face *face)
3298 if (face->font->driver->prepare_face)
3299 face->font->driver->prepare_face (f, face);
3303 /* Make FACE on frame F stop using the font opened for FACE. */
3305 void
3306 font_done_for_face (FRAME_PTR f, struct face *face)
3308 if (face->font->driver->done_face)
3309 face->font->driver->done_face (f, face);
3310 face->extra = NULL;
3314 /* Open a font that is a match for font-spec SPEC on frame F. If no proper
3315 font is found, return Qnil. */
3317 Lisp_Object
3318 font_open_by_spec (FRAME_PTR f, Lisp_Object spec)
3320 Lisp_Object attrs[LFACE_VECTOR_SIZE];
3322 /* We set up the default font-related attributes of a face to prefer
3323 a moderate font. */
3324 attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
3325 attrs[LFACE_SWIDTH_INDEX] = attrs[LFACE_WEIGHT_INDEX]
3326 = attrs[LFACE_SLANT_INDEX] = Qnormal;
3327 #ifndef HAVE_NS
3328 attrs[LFACE_HEIGHT_INDEX] = make_number (120);
3329 #else
3330 attrs[LFACE_HEIGHT_INDEX] = make_number (0);
3331 #endif
3332 attrs[LFACE_FONT_INDEX] = Qnil;
3334 return font_load_for_lface (f, attrs, spec);
3338 /* Open a font that matches NAME on frame F. If no proper font is
3339 found, return Qnil. */
3341 Lisp_Object
3342 font_open_by_name (FRAME_PTR f, Lisp_Object name)
3344 Lisp_Object args[2];
3345 Lisp_Object spec, ret;
3347 args[0] = QCname;
3348 args[1] = name;
3349 spec = Ffont_spec (2, args);
3350 ret = font_open_by_spec (f, spec);
3351 /* Do not lose name originally put in. */
3352 if (!NILP (ret))
3353 font_put_extra (ret, QCuser_spec, args[1]);
3355 return ret;
3359 /* Register font-driver DRIVER. This function is used in two ways.
3361 The first is with frame F non-NULL. In this case, make DRIVER
3362 available (but not yet activated) on F. All frame creators
3363 (e.g. Fx_create_frame) must call this function at least once with
3364 an available font-driver.
3366 The second is with frame F NULL. In this case, DRIVER is globally
3367 registered in the variable `font_driver_list'. All font-driver
3368 implementations must call this function in its syms_of_XXXX
3369 (e.g. syms_of_xfont). */
3371 void
3372 register_font_driver (struct font_driver *driver, FRAME_PTR f)
3374 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
3375 struct font_driver_list *prev, *list;
3377 if (f && ! driver->draw)
3378 error ("Unusable font driver for a frame: %s",
3379 SDATA (SYMBOL_NAME (driver->type)));
3381 for (prev = NULL, list = root; list; prev = list, list = list->next)
3382 if (EQ (list->driver->type, driver->type))
3383 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3385 list = xmalloc (sizeof *list);
3386 list->on = 0;
3387 list->driver = driver;
3388 list->next = NULL;
3389 if (prev)
3390 prev->next = list;
3391 else if (f)
3392 f->font_driver_list = list;
3393 else
3394 font_driver_list = list;
3395 if (! f)
3396 num_font_drivers++;
3399 void
3400 free_font_driver_list (FRAME_PTR f)
3402 struct font_driver_list *list, *next;
3404 for (list = f->font_driver_list; list; list = next)
3406 next = list->next;
3407 xfree (list);
3409 f->font_driver_list = NULL;
3413 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3414 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3415 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3417 A caller must free all realized faces if any in advance. The
3418 return value is a list of font backends actually made used on
3419 F. */
3421 Lisp_Object
3422 font_update_drivers (FRAME_PTR f, Lisp_Object new_drivers)
3424 Lisp_Object active_drivers = Qnil;
3425 struct font_driver_list *list;
3427 /* At first, turn off non-requested drivers, and turn on requested
3428 drivers. */
3429 for (list = f->font_driver_list; list; list = list->next)
3431 struct font_driver *driver = list->driver;
3432 if ((EQ (new_drivers, Qt) || ! NILP (Fmemq (driver->type, new_drivers)))
3433 != list->on)
3435 if (list->on)
3437 if (driver->end_for_frame)
3438 driver->end_for_frame (f);
3439 font_finish_cache (f, driver);
3440 list->on = 0;
3442 else
3444 if (! driver->start_for_frame
3445 || driver->start_for_frame (f) == 0)
3447 font_prepare_cache (f, driver);
3448 list->on = 1;
3454 if (NILP (new_drivers))
3455 return Qnil;
3457 if (! EQ (new_drivers, Qt))
3459 /* Re-order the driver list according to new_drivers. */
3460 struct font_driver_list **list_table, **next;
3461 Lisp_Object tail;
3462 int i;
3464 list_table = alloca (sizeof list_table[0] * (num_font_drivers + 1));
3465 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
3467 for (list = f->font_driver_list; list; list = list->next)
3468 if (list->on && EQ (list->driver->type, XCAR (tail)))
3469 break;
3470 if (list)
3471 list_table[i++] = list;
3473 for (list = f->font_driver_list; list; list = list->next)
3474 if (! list->on)
3475 list_table[i++] = list;
3476 list_table[i] = NULL;
3478 next = &f->font_driver_list;
3479 for (i = 0; list_table[i]; i++)
3481 *next = list_table[i];
3482 next = &(*next)->next;
3484 *next = NULL;
3486 if (! f->font_driver_list->on)
3487 { /* None of the drivers is enabled: enable them all.
3488 Happens if you set the list of drivers to (xft x) in your .emacs
3489 and then use it under w32 or ns. */
3490 for (list = f->font_driver_list; list; list = list->next)
3492 struct font_driver *driver = list->driver;
3493 eassert (! list->on);
3494 if (! driver->start_for_frame
3495 || driver->start_for_frame (f) == 0)
3497 font_prepare_cache (f, driver);
3498 list->on = 1;
3504 for (list = f->font_driver_list; list; list = list->next)
3505 if (list->on)
3506 active_drivers = nconc2 (active_drivers,
3507 Fcons (list->driver->type, Qnil));
3508 return active_drivers;
3512 font_put_frame_data (FRAME_PTR f, struct font_driver *driver, void *data)
3514 struct font_data_list *list, *prev;
3516 for (prev = NULL, list = f->font_data_list; list;
3517 prev = list, list = list->next)
3518 if (list->driver == driver)
3519 break;
3520 if (! data)
3522 if (list)
3524 if (prev)
3525 prev->next = list->next;
3526 else
3527 f->font_data_list = list->next;
3528 xfree (list);
3530 return 0;
3533 if (! list)
3535 list = xmalloc (sizeof *list);
3536 list->driver = driver;
3537 list->next = f->font_data_list;
3538 f->font_data_list = list;
3540 list->data = data;
3541 return 0;
3545 void *
3546 font_get_frame_data (FRAME_PTR f, struct font_driver *driver)
3548 struct font_data_list *list;
3550 for (list = f->font_data_list; list; list = list->next)
3551 if (list->driver == driver)
3552 break;
3553 if (! list)
3554 return NULL;
3555 return list->data;
3559 /* Sets attributes on a font. Any properties that appear in ALIST and
3560 BOOLEAN_PROPERTIES or NON_BOOLEAN_PROPERTIES are set on the font.
3561 BOOLEAN_PROPERTIES and NON_BOOLEAN_PROPERTIES are NULL-terminated
3562 arrays of strings. This function is intended for use by the font
3563 drivers to implement their specific font_filter_properties. */
3564 void
3565 font_filter_properties (Lisp_Object font,
3566 Lisp_Object alist,
3567 const char *const boolean_properties[],
3568 const char *const non_boolean_properties[])
3570 Lisp_Object it;
3571 int i;
3573 /* Set boolean values to Qt or Qnil */
3574 for (i = 0; boolean_properties[i] != NULL; ++i)
3575 for (it = alist; ! NILP (it); it = XCDR (it))
3577 Lisp_Object key = XCAR (XCAR (it));
3578 Lisp_Object val = XCDR (XCAR (it));
3579 char *keystr = SSDATA (SYMBOL_NAME (key));
3581 if (strcmp (boolean_properties[i], keystr) == 0)
3583 const char *str = INTEGERP (val) ? (XINT (val) ? "true" : "false")
3584 : SYMBOLP (val) ? SSDATA (SYMBOL_NAME (val))
3585 : "true";
3587 if (strcmp ("false", str) == 0 || strcmp ("False", str) == 0
3588 || strcmp ("FALSE", str) == 0 || strcmp ("FcFalse", str) == 0
3589 || strcmp ("off", str) == 0 || strcmp ("OFF", str) == 0
3590 || strcmp ("Off", str) == 0)
3591 val = Qnil;
3592 else
3593 val = Qt;
3595 Ffont_put (font, key, val);
3599 for (i = 0; non_boolean_properties[i] != NULL; ++i)
3600 for (it = alist; ! NILP (it); it = XCDR (it))
3602 Lisp_Object key = XCAR (XCAR (it));
3603 Lisp_Object val = XCDR (XCAR (it));
3604 char *keystr = SSDATA (SYMBOL_NAME (key));
3605 if (strcmp (non_boolean_properties[i], keystr) == 0)
3606 Ffont_put (font, key, val);
3611 /* Return the font used to draw character C by FACE at buffer position
3612 POS in window W. If STRING is non-nil, it is a string containing C
3613 at index POS. If C is negative, get C from the current buffer or
3614 STRING. */
3616 static Lisp_Object
3617 font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
3618 Lisp_Object string)
3620 FRAME_PTR f;
3621 bool multibyte;
3622 Lisp_Object font_object;
3624 multibyte = (NILP (string)
3625 ? ! NILP (BVAR (current_buffer, enable_multibyte_characters))
3626 : STRING_MULTIBYTE (string));
3627 if (c < 0)
3629 if (NILP (string))
3631 if (multibyte)
3633 ptrdiff_t pos_byte = CHAR_TO_BYTE (pos);
3635 c = FETCH_CHAR (pos_byte);
3637 else
3638 c = FETCH_BYTE (pos);
3640 else
3642 unsigned char *str;
3644 multibyte = STRING_MULTIBYTE (string);
3645 if (multibyte)
3647 ptrdiff_t pos_byte = string_char_to_byte (string, pos);
3649 str = SDATA (string) + pos_byte;
3650 c = STRING_CHAR (str);
3652 else
3653 c = SDATA (string)[pos];
3657 f = XFRAME (w->frame);
3658 if (! FRAME_WINDOW_P (f))
3659 return Qnil;
3660 if (! face)
3662 int face_id;
3663 ptrdiff_t endptr;
3665 if (STRINGP (string))
3666 face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
3667 DEFAULT_FACE_ID, 0);
3668 else
3669 face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
3670 pos + 100, 0, -1);
3671 face = FACE_FROM_ID (f, face_id);
3673 if (multibyte)
3675 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3676 face = FACE_FROM_ID (f, face_id);
3678 if (! face->font)
3679 return Qnil;
3681 XSETFONT (font_object, face->font);
3682 return font_object;
3686 #ifdef HAVE_WINDOW_SYSTEM
3688 /* Check how many characters after POS (at most to *LIMIT) can be
3689 displayed by the same font in the window W. FACE, if non-NULL, is
3690 the face selected for the character at POS. If STRING is not nil,
3691 it is the string to check instead of the current buffer. In that
3692 case, FACE must be not NULL.
3694 The return value is the font-object for the character at POS.
3695 *LIMIT is set to the position where that font can't be used.
3697 It is assured that the current buffer (or STRING) is multibyte. */
3699 Lisp_Object
3700 font_range (ptrdiff_t pos, ptrdiff_t *limit, struct window *w, struct face *face, Lisp_Object string)
3702 ptrdiff_t pos_byte, ignore;
3703 int c;
3704 Lisp_Object font_object = Qnil;
3706 if (NILP (string))
3708 pos_byte = CHAR_TO_BYTE (pos);
3709 if (! face)
3711 int face_id;
3713 face_id = face_at_buffer_position (w, pos, 0, 0, &ignore,
3714 *limit, 0, -1);
3715 face = FACE_FROM_ID (XFRAME (w->frame), face_id);
3718 else
3720 eassert (face);
3721 pos_byte = string_char_to_byte (string, pos);
3724 while (pos < *limit)
3726 Lisp_Object category;
3728 if (NILP (string))
3729 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3730 else
3731 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3732 category = CHAR_TABLE_REF (Vunicode_category_table, c);
3733 if (INTEGERP (category)
3734 && (XINT (category) == UNICODE_CATEGORY_Cf
3735 || CHAR_VARIATION_SELECTOR_P (c)))
3736 continue;
3737 if (NILP (font_object))
3739 font_object = font_for_char (face, c, pos - 1, string);
3740 if (NILP (font_object))
3741 return Qnil;
3742 continue;
3744 if (font_encode_char (font_object, c) == FONT_INVALID_CODE)
3745 *limit = pos - 1;
3747 return font_object;
3749 #endif
3752 /* Lisp API */
3754 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3755 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3756 Return nil otherwise.
3757 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3758 which kind of font it is. It must be one of `font-spec', `font-entity',
3759 `font-object'. */)
3760 (Lisp_Object object, Lisp_Object extra_type)
3762 if (NILP (extra_type))
3763 return (FONTP (object) ? Qt : Qnil);
3764 if (EQ (extra_type, Qfont_spec))
3765 return (FONT_SPEC_P (object) ? Qt : Qnil);
3766 if (EQ (extra_type, Qfont_entity))
3767 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3768 if (EQ (extra_type, Qfont_object))
3769 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3770 wrong_type_argument (intern ("font-extra-type"), extra_type);
3773 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3774 doc: /* Return a newly created font-spec with arguments as properties.
3776 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3777 valid font property name listed below:
3779 `:family', `:weight', `:slant', `:width'
3781 They are the same as face attributes of the same name. See
3782 `set-face-attribute'.
3784 `:foundry'
3786 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3788 `:adstyle'
3790 VALUE must be a string or a symbol specifying the additional
3791 typographic style information of a font, e.g. ``sans''.
3793 `:registry'
3795 VALUE must be a string or a symbol specifying the charset registry and
3796 encoding of a font, e.g. ``iso8859-1''.
3798 `:size'
3800 VALUE must be a non-negative integer or a floating point number
3801 specifying the font size. It specifies the font size in pixels (if
3802 VALUE is an integer), or in points (if VALUE is a float).
3804 `:name'
3806 VALUE must be a string of XLFD-style or fontconfig-style font name.
3808 `:script'
3810 VALUE must be a symbol representing a script that the font must
3811 support. It may be a symbol representing a subgroup of a script
3812 listed in the variable `script-representative-chars'.
3814 `:lang'
3816 VALUE must be a symbol of two-letter ISO-639 language names,
3817 e.g. `ja'.
3819 `:otf'
3821 VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
3822 required OpenType features.
3824 SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
3825 LANGSYS-TAG: OpenType language system tag symbol,
3826 or nil for the default language system.
3827 GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
3828 GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
3830 GSUB and GPOS may contain `nil' element. In such a case, the font
3831 must not have any of the remaining elements.
3833 For instance, if the VALUE is `(thai nil nil (mark))', the font must
3834 be an OpenType font whose GPOS table of `thai' script's default
3835 language system must contain `mark' feature.
3837 usage: (font-spec ARGS...) */)
3838 (ptrdiff_t nargs, Lisp_Object *args)
3840 Lisp_Object spec = font_make_spec ();
3841 ptrdiff_t i;
3843 for (i = 0; i < nargs; i += 2)
3845 Lisp_Object key = args[i], val;
3847 CHECK_SYMBOL (key);
3848 if (i + 1 >= nargs)
3849 error ("No value for key `%s'", SDATA (SYMBOL_NAME (key)));
3850 val = args[i + 1];
3852 if (EQ (key, QCname))
3854 CHECK_STRING (val);
3855 font_parse_name (SSDATA (val), SBYTES (val), spec);
3856 font_put_extra (spec, key, val);
3858 else
3860 int idx = get_font_prop_index (key);
3862 if (idx >= 0)
3864 val = font_prop_validate (idx, Qnil, val);
3865 if (idx < FONT_EXTRA_INDEX)
3866 ASET (spec, idx, val);
3867 else
3868 font_put_extra (spec, key, val);
3870 else
3871 font_put_extra (spec, key, font_prop_validate (0, key, val));
3874 return spec;
3877 /* Return a copy of FONT as a font-spec. */
3878 Lisp_Object
3879 copy_font_spec (Lisp_Object font)
3881 Lisp_Object new_spec, tail, prev, extra;
3882 int i;
3884 CHECK_FONT (font);
3885 new_spec = font_make_spec ();
3886 for (i = 1; i < FONT_EXTRA_INDEX; i++)
3887 ASET (new_spec, i, AREF (font, i));
3888 extra = Fcopy_alist (AREF (font, FONT_EXTRA_INDEX));
3889 /* We must remove :font-entity property. */
3890 for (prev = Qnil, tail = extra; CONSP (tail); prev = tail, tail = XCDR (tail))
3891 if (EQ (XCAR (XCAR (tail)), QCfont_entity))
3893 if (NILP (prev))
3894 extra = XCDR (extra);
3895 else
3896 XSETCDR (prev, XCDR (tail));
3897 break;
3899 ASET (new_spec, FONT_EXTRA_INDEX, extra);
3900 return new_spec;
3903 /* Merge font-specs FROM and TO, and return a new font-spec.
3904 Every specified property in FROM overrides the corresponding
3905 property in TO. */
3906 Lisp_Object
3907 merge_font_spec (Lisp_Object from, Lisp_Object to)
3909 Lisp_Object extra, tail;
3910 int i;
3912 CHECK_FONT (from);
3913 CHECK_FONT (to);
3914 to = copy_font_spec (to);
3915 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3916 ASET (to, i, AREF (from, i));
3917 extra = AREF (to, FONT_EXTRA_INDEX);
3918 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3919 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
3921 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
3923 if (! NILP (slot))
3924 XSETCDR (slot, XCDR (XCAR (tail)));
3925 else
3926 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
3928 ASET (to, FONT_EXTRA_INDEX, extra);
3929 return to;
3932 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
3933 doc: /* Return the value of FONT's property KEY.
3934 FONT is a font-spec, a font-entity, or a font-object.
3935 KEY is any symbol, but these are reserved for specific meanings:
3936 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
3937 :size, :name, :script, :otf
3938 See the documentation of `font-spec' for their meanings.
3939 In addition, if FONT is a font-entity or a font-object, values of
3940 :script and :otf are different from those of a font-spec as below:
3942 The value of :script may be a list of scripts that are supported by the font.
3944 The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
3945 representing the OpenType features supported by the font by this form:
3946 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
3947 SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
3948 Layout tags. */)
3949 (Lisp_Object font, Lisp_Object key)
3951 int idx;
3952 Lisp_Object val;
3954 CHECK_FONT (font);
3955 CHECK_SYMBOL (key);
3957 idx = get_font_prop_index (key);
3958 if (idx >= FONT_WEIGHT_INDEX && idx <= FONT_WIDTH_INDEX)
3959 return font_style_symbolic (font, idx, 0);
3960 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3961 return AREF (font, idx);
3962 val = Fassq (key, AREF (font, FONT_EXTRA_INDEX));
3963 if (NILP (val) && EQ (key, QCotf) && FONT_OBJECT_P (font))
3965 struct font *fontp = XFONT_OBJECT (font);
3967 if (fontp->driver->otf_capability)
3968 val = fontp->driver->otf_capability (fontp);
3969 else
3970 val = Fcons (Qnil, Qnil);
3972 else
3973 val = Fcdr (val);
3974 return val;
3977 #ifdef HAVE_WINDOW_SYSTEM
3979 DEFUN ("font-face-attributes", Ffont_face_attributes, Sfont_face_attributes, 1, 2, 0,
3980 doc: /* Return a plist of face attributes generated by FONT.
3981 FONT is a font name, a font-spec, a font-entity, or a font-object.
3982 The return value is a list of the form
3984 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
3986 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
3987 compatible with `set-face-attribute'. Some of these key-attribute pairs
3988 may be omitted from the list if they are not specified by FONT.
3990 The optional argument FRAME specifies the frame that the face attributes
3991 are to be displayed on. If omitted, the selected frame is used. */)
3992 (Lisp_Object font, Lisp_Object frame)
3994 struct frame *f;
3995 Lisp_Object plist[10];
3996 Lisp_Object val;
3997 int n = 0;
3999 if (NILP (frame))
4000 frame = selected_frame;
4001 CHECK_LIVE_FRAME (frame);
4002 f = XFRAME (frame);
4004 if (STRINGP (font))
4006 int fontset = fs_query_fontset (font, 0);
4007 Lisp_Object name = font;
4008 if (fontset >= 0)
4009 font = fontset_ascii (fontset);
4010 font = font_spec_from_name (name);
4011 if (! FONTP (font))
4012 signal_error ("Invalid font name", name);
4014 else if (! FONTP (font))
4015 signal_error ("Invalid font object", font);
4017 val = AREF (font, FONT_FAMILY_INDEX);
4018 if (! NILP (val))
4020 plist[n++] = QCfamily;
4021 plist[n++] = SYMBOL_NAME (val);
4024 val = AREF (font, FONT_SIZE_INDEX);
4025 if (INTEGERP (val))
4027 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
4028 int dpi = INTEGERP (font_dpi) ? XINT (font_dpi) : f->resy;
4029 plist[n++] = QCheight;
4030 plist[n++] = make_number (PIXEL_TO_POINT (XINT (val) * 10, dpi));
4032 else if (FLOATP (val))
4034 plist[n++] = QCheight;
4035 plist[n++] = make_number (10 * (int) XFLOAT_DATA (val));
4038 val = FONT_WEIGHT_FOR_FACE (font);
4039 if (! NILP (val))
4041 plist[n++] = QCweight;
4042 plist[n++] = val;
4045 val = FONT_SLANT_FOR_FACE (font);
4046 if (! NILP (val))
4048 plist[n++] = QCslant;
4049 plist[n++] = val;
4052 val = FONT_WIDTH_FOR_FACE (font);
4053 if (! NILP (val))
4055 plist[n++] = QCwidth;
4056 plist[n++] = val;
4059 return Flist (n, plist);
4062 #endif
4064 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
4065 doc: /* Set one property of FONT: give property KEY value VAL.
4066 FONT is a font-spec, a font-entity, or a font-object.
4068 If FONT is a font-spec, KEY can be any symbol. But if KEY is the one
4069 accepted by the function `font-spec' (which see), VAL must be what
4070 allowed in `font-spec'.
4072 If FONT is a font-entity or a font-object, KEY must not be the one
4073 accepted by `font-spec'. */)
4074 (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
4076 int idx;
4078 idx = get_font_prop_index (prop);
4079 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4081 CHECK_FONT_SPEC (font);
4082 ASET (font, idx, font_prop_validate (idx, Qnil, val));
4084 else
4086 if (EQ (prop, QCname)
4087 || EQ (prop, QCscript)
4088 || EQ (prop, QClang)
4089 || EQ (prop, QCotf))
4090 CHECK_FONT_SPEC (font);
4091 else
4092 CHECK_FONT (font);
4093 font_put_extra (font, prop, font_prop_validate (0, prop, val));
4095 return val;
4098 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
4099 doc: /* List available fonts matching FONT-SPEC on the current frame.
4100 Optional 2nd argument FRAME specifies the target frame.
4101 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4102 Optional 4th argument PREFER, if non-nil, is a font-spec to
4103 control the order of the returned list. Fonts are sorted by
4104 how close they are to PREFER. */)
4105 (Lisp_Object font_spec, Lisp_Object frame, Lisp_Object num, Lisp_Object prefer)
4107 Lisp_Object vec, list;
4108 EMACS_INT n = 0;
4110 if (NILP (frame))
4111 frame = selected_frame;
4112 CHECK_LIVE_FRAME (frame);
4113 CHECK_FONT_SPEC (font_spec);
4114 if (! NILP (num))
4116 CHECK_NUMBER (num);
4117 n = XINT (num);
4118 if (n <= 0)
4119 return Qnil;
4121 if (! NILP (prefer))
4122 CHECK_FONT_SPEC (prefer);
4124 list = font_list_entities (frame, font_spec);
4125 if (NILP (list))
4126 return Qnil;
4127 if (NILP (XCDR (list))
4128 && ASIZE (XCAR (list)) == 1)
4129 return Fcons (AREF (XCAR (list), 0), Qnil);
4131 if (! NILP (prefer))
4132 vec = font_sort_entities (list, prefer, frame, 0);
4133 else
4134 vec = font_vconcat_entity_vectors (list);
4135 if (n == 0 || n >= ASIZE (vec))
4137 Lisp_Object args[2];
4139 args[0] = vec;
4140 args[1] = Qnil;
4141 list = Fappend (2, args);
4143 else
4145 for (list = Qnil, n--; n >= 0; n--)
4146 list = Fcons (AREF (vec, n), list);
4148 return list;
4151 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
4152 doc: /* List available font families on the current frame.
4153 Optional argument FRAME, if non-nil, specifies the target frame. */)
4154 (Lisp_Object frame)
4156 FRAME_PTR f;
4157 struct font_driver_list *driver_list;
4158 Lisp_Object list;
4160 if (NILP (frame))
4161 frame = selected_frame;
4162 CHECK_LIVE_FRAME (frame);
4163 f = XFRAME (frame);
4164 list = Qnil;
4165 for (driver_list = f->font_driver_list; driver_list;
4166 driver_list = driver_list->next)
4167 if (driver_list->driver->list_family)
4169 Lisp_Object val = driver_list->driver->list_family (frame);
4170 Lisp_Object tail = list;
4172 for (; CONSP (val); val = XCDR (val))
4173 if (NILP (Fmemq (XCAR (val), tail))
4174 && SYMBOLP (XCAR (val)))
4175 list = Fcons (SYMBOL_NAME (XCAR (val)), list);
4177 return list;
4180 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
4181 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
4182 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4183 (Lisp_Object font_spec, Lisp_Object frame)
4185 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
4187 if (CONSP (val))
4188 val = XCAR (val);
4189 return val;
4192 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
4193 doc: /* Return XLFD name of FONT.
4194 FONT is a font-spec, font-entity, or font-object.
4195 If the name is too long for XLFD (maximum 255 chars), return nil.
4196 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4197 the consecutive wildcards are folded into one. */)
4198 (Lisp_Object font, Lisp_Object fold_wildcards)
4200 char name[256];
4201 int namelen, pixel_size = 0;
4203 CHECK_FONT (font);
4205 if (FONT_OBJECT_P (font))
4207 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
4209 if (STRINGP (font_name)
4210 && SDATA (font_name)[0] == '-')
4212 if (NILP (fold_wildcards))
4213 return font_name;
4214 strcpy (name, SSDATA (font_name));
4215 namelen = SBYTES (font_name);
4216 goto done;
4218 pixel_size = XFONT_OBJECT (font)->pixel_size;
4220 namelen = font_unparse_xlfd (font, pixel_size, name, 256);
4221 if (namelen < 0)
4222 return Qnil;
4223 done:
4224 if (! NILP (fold_wildcards))
4226 char *p0 = name, *p1;
4228 while ((p1 = strstr (p0, "-*-*")))
4230 strcpy (p1, p1 + 2);
4231 namelen -= 2;
4232 p0 = p1;
4236 return make_string (name, namelen);
4239 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
4240 doc: /* Clear font cache. */)
4241 (void)
4243 Lisp_Object list, frame;
4245 FOR_EACH_FRAME (list, frame)
4247 FRAME_PTR f = XFRAME (frame);
4248 struct font_driver_list *driver_list = f->font_driver_list;
4250 for (; driver_list; driver_list = driver_list->next)
4251 if (driver_list->on)
4253 Lisp_Object cache = driver_list->driver->get_cache (f);
4254 Lisp_Object val, tmp;
4256 val = XCDR (cache);
4257 while (! NILP (val)
4258 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
4259 val = XCDR (val);
4260 eassert (! NILP (val));
4261 tmp = XCDR (XCAR (val));
4262 if (XINT (XCAR (tmp)) == 0)
4264 font_clear_cache (f, XCAR (val), driver_list->driver);
4265 XSETCDR (cache, XCDR (val));
4270 return Qnil;
4274 void
4275 font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object)
4277 struct font *font = XFONT_OBJECT (font_object);
4278 unsigned code = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
4279 struct font_metrics metrics;
4281 LGLYPH_SET_CODE (glyph, code);
4282 font->driver->text_extents (font, &code, 1, &metrics);
4283 LGLYPH_SET_LBEARING (glyph, metrics.lbearing);
4284 LGLYPH_SET_RBEARING (glyph, metrics.rbearing);
4285 LGLYPH_SET_WIDTH (glyph, metrics.width);
4286 LGLYPH_SET_ASCENT (glyph, metrics.ascent);
4287 LGLYPH_SET_DESCENT (glyph, metrics.descent);
4291 DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0,
4292 doc: /* Shape the glyph-string GSTRING.
4293 Shaping means substituting glyphs and/or adjusting positions of glyphs
4294 to get the correct visual image of character sequences set in the
4295 header of the glyph-string.
4297 If the shaping was successful, the value is GSTRING itself or a newly
4298 created glyph-string. Otherwise, the value is nil.
4300 See the documentation of `composition-get-gstring' for the format of
4301 GSTRING. */)
4302 (Lisp_Object gstring)
4304 struct font *font;
4305 Lisp_Object font_object, n, glyph;
4306 ptrdiff_t i, from, to;
4308 if (! composition_gstring_p (gstring))
4309 signal_error ("Invalid glyph-string: ", gstring);
4310 if (! NILP (LGSTRING_ID (gstring)))
4311 return gstring;
4312 font_object = LGSTRING_FONT (gstring);
4313 CHECK_FONT_OBJECT (font_object);
4314 font = XFONT_OBJECT (font_object);
4315 if (! font->driver->shape)
4316 return Qnil;
4318 /* Try at most three times with larger gstring each time. */
4319 for (i = 0; i < 3; i++)
4321 n = font->driver->shape (gstring);
4322 if (INTEGERP (n))
4323 break;
4324 gstring = larger_vector (gstring,
4325 LGSTRING_GLYPH_LEN (gstring), -1);
4327 if (i == 3 || XINT (n) == 0)
4328 return Qnil;
4329 if (XINT (n) < LGSTRING_GLYPH_LEN (gstring))
4330 LGSTRING_SET_GLYPH (gstring, XINT (n), Qnil);
4332 /* Check FROM_IDX and TO_IDX of each GLYPH in GSTRING to assure that
4333 GLYPHS covers all characters (except for the last few ones) in
4334 GSTRING. More formally, provided that NCHARS is the number of
4335 characters in GSTRING and GLYPHS[i] is the ith glyph, FROM_IDX
4336 and TO_IDX of each glyph must satisfy these conditions:
4338 GLYPHS[0].FROM_IDX == 0
4339 GLYPHS[i].FROM_IDX <= GLYPHS[i].TO_IDX
4340 if (GLYPHS[i].FROM_IDX == GLYPHS[i-1].FROM_IDX)
4341 ;; GLYPHS[i] and GLYPHS[i-1] belongs to the same grapheme cluster
4342 GLYPHS[i].TO_IDX == GLYPHS[i-1].TO_IDX
4343 else
4344 ;; Be sure to cover all characters.
4345 GLYPHS[i].FROM_IDX == GLYPHS[i-1].TO_IDX + 1 */
4346 glyph = LGSTRING_GLYPH (gstring, 0);
4347 from = LGLYPH_FROM (glyph);
4348 to = LGLYPH_TO (glyph);
4349 if (from != 0 || to < from)
4350 goto shaper_error;
4351 for (i = 1; i < LGSTRING_GLYPH_LEN (gstring); i++)
4353 glyph = LGSTRING_GLYPH (gstring, i);
4354 if (NILP (glyph))
4355 break;
4356 if (! (LGLYPH_FROM (glyph) <= LGLYPH_TO (glyph)
4357 && (LGLYPH_FROM (glyph) == from
4358 ? LGLYPH_TO (glyph) == to
4359 : LGLYPH_FROM (glyph) == to + 1)))
4360 goto shaper_error;
4361 from = LGLYPH_FROM (glyph);
4362 to = LGLYPH_TO (glyph);
4364 return composition_gstring_put_cache (gstring, XINT (n));
4366 shaper_error:
4367 return Qnil;
4370 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
4371 2, 2, 0,
4372 doc: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4373 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4374 where
4375 VARIATION-SELECTOR is a character code of variation selection
4376 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4377 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4378 (Lisp_Object font_object, Lisp_Object character)
4380 unsigned variations[256];
4381 struct font *font;
4382 int i, n;
4383 Lisp_Object val;
4385 CHECK_FONT_OBJECT (font_object);
4386 CHECK_CHARACTER (character);
4387 font = XFONT_OBJECT (font_object);
4388 if (! font->driver->get_variation_glyphs)
4389 return Qnil;
4390 n = font->driver->get_variation_glyphs (font, XINT (character), variations);
4391 if (! n)
4392 return Qnil;
4393 val = Qnil;
4394 for (i = 0; i < 255; i++)
4395 if (variations[i])
4397 int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
4398 Lisp_Object code = INTEGER_TO_CONS (variations[i]);
4399 val = Fcons (Fcons (make_number (vs), code), val);
4401 return val;
4404 #if 0
4406 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
4407 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
4408 OTF-FEATURES specifies which features to apply in this format:
4409 (SCRIPT LANGSYS GSUB GPOS)
4410 where
4411 SCRIPT is a symbol specifying a script tag of OpenType,
4412 LANGSYS is a symbol specifying a langsys tag of OpenType,
4413 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4415 If LANGYS is nil, the default langsys is selected.
4417 The features are applied in the order they appear in the list. The
4418 symbol `*' means to apply all available features not present in this
4419 list, and the remaining features are ignored. For instance, (vatu
4420 pstf * haln) is to apply vatu and pstf in this order, then to apply
4421 all available features other than vatu, pstf, and haln.
4423 The features are applied to the glyphs in the range FROM and TO of
4424 the glyph-string GSTRING-IN.
4426 If some feature is actually applicable, the resulting glyphs are
4427 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4428 this case, the value is the number of produced glyphs.
4430 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4431 the value is 0.
4433 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4434 produced in GSTRING-OUT, and the value is nil.
4436 See the documentation of `composition-get-gstring' for the format of
4437 glyph-string. */)
4438 (Lisp_Object otf_features, Lisp_Object gstring_in, Lisp_Object from, Lisp_Object to, Lisp_Object gstring_out, Lisp_Object index)
4440 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
4441 Lisp_Object val;
4442 struct font *font;
4443 int len, num;
4445 check_otf_features (otf_features);
4446 CHECK_FONT_OBJECT (font_object);
4447 font = XFONT_OBJECT (font_object);
4448 if (! font->driver->otf_drive)
4449 error ("Font backend %s can't drive OpenType GSUB table",
4450 SDATA (SYMBOL_NAME (font->driver->type)));
4451 CHECK_CONS (otf_features);
4452 CHECK_SYMBOL (XCAR (otf_features));
4453 val = XCDR (otf_features);
4454 CHECK_SYMBOL (XCAR (val));
4455 val = XCDR (otf_features);
4456 if (! NILP (val))
4457 CHECK_CONS (val);
4458 len = check_gstring (gstring_in);
4459 CHECK_VECTOR (gstring_out);
4460 CHECK_NATNUM (from);
4461 CHECK_NATNUM (to);
4462 CHECK_NATNUM (index);
4464 if (XINT (from) >= XINT (to) || XINT (to) > len)
4465 args_out_of_range_3 (from, to, make_number (len));
4466 if (XINT (index) >= ASIZE (gstring_out))
4467 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4468 num = font->driver->otf_drive (font, otf_features,
4469 gstring_in, XINT (from), XINT (to),
4470 gstring_out, XINT (index), 0);
4471 if (num < 0)
4472 return Qnil;
4473 return make_number (num);
4476 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4477 3, 3, 0,
4478 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4479 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4480 in this format:
4481 (SCRIPT LANGSYS FEATURE ...)
4482 See the documentation of `font-drive-otf' for more detail.
4484 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4485 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4486 character code corresponding to the glyph or nil if there's no
4487 corresponding character. */)
4488 (Lisp_Object font_object, Lisp_Object character, Lisp_Object otf_features)
4490 struct font *font;
4491 Lisp_Object gstring_in, gstring_out, g;
4492 Lisp_Object alternates;
4493 int i, num;
4495 CHECK_FONT_GET_OBJECT (font_object, font);
4496 if (! font->driver->otf_drive)
4497 error ("Font backend %s can't drive OpenType GSUB table",
4498 SDATA (SYMBOL_NAME (font->driver->type)));
4499 CHECK_CHARACTER (character);
4500 CHECK_CONS (otf_features);
4502 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4503 g = LGSTRING_GLYPH (gstring_in, 0);
4504 LGLYPH_SET_CHAR (g, XINT (character));
4505 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4506 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4507 gstring_out, 0, 1)) < 0)
4508 gstring_out = Ffont_make_gstring (font_object,
4509 make_number (ASIZE (gstring_out) * 2));
4510 alternates = Qnil;
4511 for (i = 0; i < num; i++)
4513 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4514 int c = LGLYPH_CHAR (g);
4515 unsigned code = LGLYPH_CODE (g);
4517 alternates = Fcons (Fcons (make_number (code),
4518 c > 0 ? make_number (c) : Qnil),
4519 alternates);
4521 return Fnreverse (alternates);
4523 #endif /* 0 */
4525 #ifdef FONT_DEBUG
4527 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4528 doc: /* Open FONT-ENTITY. */)
4529 (Lisp_Object font_entity, Lisp_Object size, Lisp_Object frame)
4531 EMACS_INT isize;
4533 CHECK_FONT_ENTITY (font_entity);
4534 if (NILP (frame))
4535 frame = selected_frame;
4536 CHECK_LIVE_FRAME (frame);
4538 if (NILP (size))
4539 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4540 else
4542 CHECK_NUMBER_OR_FLOAT (size);
4543 if (FLOATP (size))
4544 isize = POINT_TO_PIXEL (XFLOAT_DATA (size), XFRAME (frame)->resy);
4545 else
4546 isize = XINT (size);
4547 if (! (INT_MIN <= isize && isize <= INT_MAX))
4548 args_out_of_range (font_entity, size);
4549 if (isize == 0)
4550 isize = 120;
4552 return font_open_entity (XFRAME (frame), font_entity, isize);
4555 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4556 doc: /* Close FONT-OBJECT. */)
4557 (Lisp_Object font_object, Lisp_Object frame)
4559 CHECK_FONT_OBJECT (font_object);
4560 if (NILP (frame))
4561 frame = selected_frame;
4562 CHECK_LIVE_FRAME (frame);
4563 font_close_object (XFRAME (frame), font_object);
4564 return Qnil;
4567 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4568 doc: /* Return information about FONT-OBJECT.
4569 The value is a vector:
4570 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4571 CAPABILITY ]
4573 NAME is the font name, a string (or nil if the font backend doesn't
4574 provide a name).
4576 FILENAME is the font file name, a string (or nil if the font backend
4577 doesn't provide a file name).
4579 PIXEL-SIZE is a pixel size by which the font is opened.
4581 SIZE is a maximum advance width of the font in pixels.
4583 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4584 pixels.
4586 CAPABILITY is a list whose first element is a symbol representing the
4587 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4588 remaining elements describe the details of the font capability.
4590 If the font is OpenType font, the form of the list is
4591 \(opentype GSUB GPOS)
4592 where GSUB shows which "GSUB" features the font supports, and GPOS
4593 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4594 lists of the format:
4595 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4597 If the font is not OpenType font, currently the length of the form is
4598 one.
4600 SCRIPT is a symbol representing OpenType script tag.
4602 LANGSYS is a symbol representing OpenType langsys tag, or nil
4603 representing the default langsys.
4605 FEATURE is a symbol representing OpenType feature tag.
4607 If the font is not OpenType font, CAPABILITY is nil. */)
4608 (Lisp_Object font_object)
4610 struct font *font;
4611 Lisp_Object val;
4613 CHECK_FONT_GET_OBJECT (font_object, font);
4615 val = Fmake_vector (make_number (9), Qnil);
4616 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4617 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4618 ASET (val, 2, make_number (font->pixel_size));
4619 ASET (val, 3, make_number (font->max_width));
4620 ASET (val, 4, make_number (font->ascent));
4621 ASET (val, 5, make_number (font->descent));
4622 ASET (val, 6, make_number (font->space_width));
4623 ASET (val, 7, make_number (font->average_width));
4624 if (font->driver->otf_capability)
4625 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4626 return val;
4629 DEFUN ("font-get-glyphs", Ffont_get_glyphs, Sfont_get_glyphs, 3, 4, 0,
4630 doc:
4631 /* Return a vector of FONT-OBJECT's glyphs for the specified characters.
4632 FROM and TO are positions (integers or markers) specifying a region
4633 of the current buffer.
4634 If the optional fourth arg OBJECT is not nil, it is a string or a
4635 vector containing the target characters.
4637 Each element is a vector containing information of a glyph in this format:
4638 [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
4639 where
4640 FROM is an index numbers of a character the glyph corresponds to.
4641 TO is the same as FROM.
4642 C is the character of the glyph.
4643 CODE is the glyph-code of C in FONT-OBJECT.
4644 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
4645 ADJUSTMENT is always nil.
4646 If FONT-OBJECT doesn't have a glyph for a character,
4647 the corresponding element is nil. */)
4648 (Lisp_Object font_object, Lisp_Object from, Lisp_Object to,
4649 Lisp_Object object)
4651 struct font *font;
4652 ptrdiff_t i, len;
4653 Lisp_Object *chars, vec;
4654 USE_SAFE_ALLOCA;
4656 CHECK_FONT_GET_OBJECT (font_object, font);
4657 if (NILP (object))
4659 ptrdiff_t charpos, bytepos;
4661 validate_region (&from, &to);
4662 if (EQ (from, to))
4663 return Qnil;
4664 len = XFASTINT (to) - XFASTINT (from);
4665 SAFE_ALLOCA_LISP (chars, len);
4666 charpos = XFASTINT (from);
4667 bytepos = CHAR_TO_BYTE (charpos);
4668 for (i = 0; charpos < XFASTINT (to); i++)
4670 int c;
4671 FETCH_CHAR_ADVANCE (c, charpos, bytepos);
4672 chars[i] = make_number (c);
4675 else if (STRINGP (object))
4677 const unsigned char *p;
4679 CHECK_NUMBER (from);
4680 CHECK_NUMBER (to);
4681 if (XINT (from) < 0 || XINT (from) > XINT (to)
4682 || XINT (to) > SCHARS (object))
4683 args_out_of_range_3 (object, from, to);
4684 if (EQ (from, to))
4685 return Qnil;
4686 len = XFASTINT (to) - XFASTINT (from);
4687 SAFE_ALLOCA_LISP (chars, len);
4688 p = SDATA (object);
4689 if (STRING_MULTIBYTE (object))
4690 for (i = 0; i < len; i++)
4692 int c = STRING_CHAR_ADVANCE (p);
4693 chars[i] = make_number (c);
4695 else
4696 for (i = 0; i < len; i++)
4697 chars[i] = make_number (p[i]);
4699 else
4701 CHECK_VECTOR (object);
4702 CHECK_NUMBER (from);
4703 CHECK_NUMBER (to);
4704 if (XINT (from) < 0 || XINT (from) > XINT (to)
4705 || XINT (to) > ASIZE (object))
4706 args_out_of_range_3 (object, from, to);
4707 if (EQ (from, to))
4708 return Qnil;
4709 len = XFASTINT (to) - XFASTINT (from);
4710 for (i = 0; i < len; i++)
4712 Lisp_Object elt = AREF (object, XFASTINT (from) + i);
4713 CHECK_CHARACTER (elt);
4715 chars = aref_addr (object, XFASTINT (from));
4718 vec = Fmake_vector (make_number (len), Qnil);
4719 for (i = 0; i < len; i++)
4721 Lisp_Object g;
4722 int c = XFASTINT (chars[i]);
4723 unsigned code;
4724 struct font_metrics metrics;
4726 code = font->driver->encode_char (font, c);
4727 if (code == FONT_INVALID_CODE)
4728 continue;
4729 g = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
4730 LGLYPH_SET_FROM (g, i);
4731 LGLYPH_SET_TO (g, i);
4732 LGLYPH_SET_CHAR (g, c);
4733 LGLYPH_SET_CODE (g, code);
4734 font->driver->text_extents (font, &code, 1, &metrics);
4735 LGLYPH_SET_WIDTH (g, metrics.width);
4736 LGLYPH_SET_LBEARING (g, metrics.lbearing);
4737 LGLYPH_SET_RBEARING (g, metrics.rbearing);
4738 LGLYPH_SET_ASCENT (g, metrics.ascent);
4739 LGLYPH_SET_DESCENT (g, metrics.descent);
4740 ASET (vec, i, g);
4742 if (! VECTORP (object))
4743 SAFE_FREE ();
4744 return vec;
4747 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4748 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4749 FONT is a font-spec, font-entity, or font-object. */)
4750 (Lisp_Object spec, Lisp_Object font)
4752 CHECK_FONT_SPEC (spec);
4753 CHECK_FONT (font);
4755 return (font_match_p (spec, font) ? Qt : Qnil);
4758 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4759 doc: /* Return a font-object for displaying a character at POSITION.
4760 Optional second arg WINDOW, if non-nil, is a window displaying
4761 the current buffer. It defaults to the currently selected window. */)
4762 (Lisp_Object position, Lisp_Object window, Lisp_Object string)
4764 struct window *w;
4765 ptrdiff_t pos;
4767 if (NILP (string))
4769 CHECK_NUMBER_COERCE_MARKER (position);
4770 if (! (BEGV <= XINT (position) && XINT (position) < ZV))
4771 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4772 pos = XINT (position);
4774 else
4776 CHECK_NUMBER (position);
4777 CHECK_STRING (string);
4778 if (! (0 < XINT (position) && XINT (position) < SCHARS (string)))
4779 args_out_of_range (string, position);
4780 pos = XINT (position);
4782 if (NILP (window))
4783 window = selected_window;
4784 CHECK_LIVE_WINDOW (window);
4785 w = XWINDOW (window);
4787 return font_at (-1, pos, NULL, w, string);
4790 #if 0
4791 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4792 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4793 The value is a number of glyphs drawn.
4794 Type C-l to recover what previously shown. */)
4795 (Lisp_Object font_object, Lisp_Object string)
4797 Lisp_Object frame = selected_frame;
4798 FRAME_PTR f = XFRAME (frame);
4799 struct font *font;
4800 struct face *face;
4801 int i, len, width;
4802 unsigned *code;
4804 CHECK_FONT_GET_OBJECT (font_object, font);
4805 CHECK_STRING (string);
4806 len = SCHARS (string);
4807 code = alloca (sizeof (unsigned) * len);
4808 for (i = 0; i < len; i++)
4810 Lisp_Object ch = Faref (string, make_number (i));
4811 Lisp_Object val;
4812 int c = XINT (ch);
4814 code[i] = font->driver->encode_char (font, c);
4815 if (code[i] == FONT_INVALID_CODE)
4816 break;
4818 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4819 face->fontp = font;
4820 if (font->driver->prepare_face)
4821 font->driver->prepare_face (f, face);
4822 width = font->driver->text_extents (font, code, i, NULL);
4823 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4824 if (font->driver->done_face)
4825 font->driver->done_face (f, face);
4826 face->fontp = NULL;
4827 return make_number (len);
4829 #endif
4831 #endif /* FONT_DEBUG */
4833 #ifdef HAVE_WINDOW_SYSTEM
4835 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
4836 doc: /* Return information about a font named NAME on frame FRAME.
4837 If FRAME is omitted or nil, use the selected frame.
4838 The returned value is a vector of OPENED-NAME, FULL-NAME, SIZE,
4839 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4840 where
4841 OPENED-NAME is the name used for opening the font,
4842 FULL-NAME is the full name of the font,
4843 SIZE is the pixelsize of the font,
4844 HEIGHT is the pixel-height of the font (i.e ascent + descent),
4845 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4846 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4847 how to compose characters.
4848 If the named font is not yet loaded, return nil. */)
4849 (Lisp_Object name, Lisp_Object frame)
4851 FRAME_PTR f;
4852 struct font *font;
4853 Lisp_Object info;
4854 Lisp_Object font_object;
4856 (*check_window_system_func) ();
4858 if (! FONTP (name))
4859 CHECK_STRING (name);
4860 if (NILP (frame))
4861 frame = selected_frame;
4862 CHECK_LIVE_FRAME (frame);
4863 f = XFRAME (frame);
4865 if (STRINGP (name))
4867 int fontset = fs_query_fontset (name, 0);
4869 if (fontset >= 0)
4870 name = fontset_ascii (fontset);
4871 font_object = font_open_by_name (f, name);
4873 else if (FONT_OBJECT_P (name))
4874 font_object = name;
4875 else if (FONT_ENTITY_P (name))
4876 font_object = font_open_entity (f, name, 0);
4877 else
4879 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4880 Lisp_Object entity = font_matching_entity (f, face->lface, name);
4882 font_object = ! NILP (entity) ? font_open_entity (f, entity, 0) : Qnil;
4884 if (NILP (font_object))
4885 return Qnil;
4886 font = XFONT_OBJECT (font_object);
4888 info = Fmake_vector (make_number (7), Qnil);
4889 ASET (info, 0, AREF (font_object, FONT_NAME_INDEX));
4890 ASET (info, 1, AREF (font_object, FONT_FULLNAME_INDEX));
4891 ASET (info, 2, make_number (font->pixel_size));
4892 ASET (info, 3, make_number (font->height));
4893 ASET (info, 4, make_number (font->baseline_offset));
4894 ASET (info, 5, make_number (font->relative_compose));
4895 ASET (info, 6, make_number (font->default_ascent));
4897 #if 0
4898 /* As font_object is still in FONT_OBJLIST of the entity, we can't
4899 close it now. Perhaps, we should manage font-objects
4900 by `reference-count'. */
4901 font_close_object (f, font_object);
4902 #endif
4903 return info;
4905 #endif
4908 #define BUILD_STYLE_TABLE(TBL) \
4909 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
4911 static Lisp_Object
4912 build_style_table (const struct table_entry *entry, int nelement)
4914 int i, j;
4915 Lisp_Object table, elt;
4917 table = Fmake_vector (make_number (nelement), Qnil);
4918 for (i = 0; i < nelement; i++)
4920 for (j = 0; entry[i].names[j]; j++);
4921 elt = Fmake_vector (make_number (j + 1), Qnil);
4922 ASET (elt, 0, make_number (entry[i].numeric));
4923 for (j = 0; entry[i].names[j]; j++)
4924 ASET (elt, j + 1, intern_c_string (entry[i].names[j]));
4925 ASET (table, i, elt);
4927 return table;
4930 /* The deferred font-log data of the form [ACTION ARG RESULT].
4931 If ACTION is not nil, that is added to the log when font_add_log is
4932 called next time. At that time, ACTION is set back to nil. */
4933 static Lisp_Object Vfont_log_deferred;
4935 /* Prepend the font-related logging data in Vfont_log if it is not
4936 `t'. ACTION describes a kind of font-related action (e.g. listing,
4937 opening), ARG is the argument for the action, and RESULT is the
4938 result of the action. */
4939 void
4940 font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
4942 Lisp_Object val;
4943 int i;
4945 if (EQ (Vfont_log, Qt))
4946 return;
4947 if (STRINGP (AREF (Vfont_log_deferred, 0)))
4949 char *str = SSDATA (AREF (Vfont_log_deferred, 0));
4951 ASET (Vfont_log_deferred, 0, Qnil);
4952 font_add_log (str, AREF (Vfont_log_deferred, 1),
4953 AREF (Vfont_log_deferred, 2));
4956 if (FONTP (arg))
4958 Lisp_Object tail, elt;
4959 Lisp_Object equalstr = build_string ("=");
4961 val = Ffont_xlfd_name (arg, Qt);
4962 for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail);
4963 tail = XCDR (tail))
4965 elt = XCAR (tail);
4966 if (EQ (XCAR (elt), QCscript)
4967 && SYMBOLP (XCDR (elt)))
4968 val = concat3 (val, SYMBOL_NAME (QCscript),
4969 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
4970 else if (EQ (XCAR (elt), QClang)
4971 && SYMBOLP (XCDR (elt)))
4972 val = concat3 (val, SYMBOL_NAME (QClang),
4973 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
4974 else if (EQ (XCAR (elt), QCotf)
4975 && CONSP (XCDR (elt)) && SYMBOLP (XCAR (XCDR (elt))))
4976 val = concat3 (val, SYMBOL_NAME (QCotf),
4977 concat2 (equalstr,
4978 SYMBOL_NAME (XCAR (XCDR (elt)))));
4980 arg = val;
4983 if (CONSP (result)
4984 && VECTORP (XCAR (result))
4985 && ASIZE (XCAR (result)) > 0
4986 && FONTP (AREF (XCAR (result), 0)))
4987 result = font_vconcat_entity_vectors (result);
4988 if (FONTP (result))
4990 val = Ffont_xlfd_name (result, Qt);
4991 if (! FONT_SPEC_P (result))
4992 val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)),
4993 build_string (":"), val);
4994 result = val;
4996 else if (CONSP (result))
4998 Lisp_Object tail;
4999 result = Fcopy_sequence (result);
5000 for (tail = result; CONSP (tail); tail = XCDR (tail))
5002 val = XCAR (tail);
5003 if (FONTP (val))
5004 val = Ffont_xlfd_name (val, Qt);
5005 XSETCAR (tail, val);
5008 else if (VECTORP (result))
5010 result = Fcopy_sequence (result);
5011 for (i = 0; i < ASIZE (result); i++)
5013 val = AREF (result, i);
5014 if (FONTP (val))
5015 val = Ffont_xlfd_name (val, Qt);
5016 ASET (result, i, val);
5019 Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
5022 /* Record a font-related logging data to be added to Vfont_log when
5023 font_add_log is called next time. ACTION, ARG, RESULT are the same
5024 as font_add_log. */
5026 void
5027 font_deferred_log (const char *action, Lisp_Object arg, Lisp_Object result)
5029 if (EQ (Vfont_log, Qt))
5030 return;
5031 ASET (Vfont_log_deferred, 0, build_string (action));
5032 ASET (Vfont_log_deferred, 1, arg);
5033 ASET (Vfont_log_deferred, 2, result);
5036 void
5037 syms_of_font (void)
5039 sort_shift_bits[FONT_TYPE_INDEX] = 0;
5040 sort_shift_bits[FONT_SLANT_INDEX] = 2;
5041 sort_shift_bits[FONT_WEIGHT_INDEX] = 9;
5042 sort_shift_bits[FONT_SIZE_INDEX] = 16;
5043 sort_shift_bits[FONT_WIDTH_INDEX] = 23;
5044 /* Note that the other elements in sort_shift_bits are not used. */
5046 staticpro (&font_charset_alist);
5047 font_charset_alist = Qnil;
5049 DEFSYM (Qopentype, "opentype");
5051 DEFSYM (Qascii_0, "ascii-0");
5052 DEFSYM (Qiso8859_1, "iso8859-1");
5053 DEFSYM (Qiso10646_1, "iso10646-1");
5054 DEFSYM (Qunicode_bmp, "unicode-bmp");
5055 DEFSYM (Qunicode_sip, "unicode-sip");
5057 DEFSYM (QCf, "Cf");
5059 DEFSYM (QCotf, ":otf");
5060 DEFSYM (QClang, ":lang");
5061 DEFSYM (QCscript, ":script");
5062 DEFSYM (QCantialias, ":antialias");
5064 DEFSYM (QCfoundry, ":foundry");
5065 DEFSYM (QCadstyle, ":adstyle");
5066 DEFSYM (QCregistry, ":registry");
5067 DEFSYM (QCspacing, ":spacing");
5068 DEFSYM (QCdpi, ":dpi");
5069 DEFSYM (QCscalable, ":scalable");
5070 DEFSYM (QCavgwidth, ":avgwidth");
5071 DEFSYM (QCfont_entity, ":font-entity");
5072 DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
5074 DEFSYM (Qc, "c");
5075 DEFSYM (Qm, "m");
5076 DEFSYM (Qp, "p");
5077 DEFSYM (Qd, "d");
5079 DEFSYM (Qja, "ja");
5080 DEFSYM (Qko, "ko");
5082 DEFSYM (QCuser_spec, "user-spec");
5084 staticpro (&scratch_font_spec);
5085 scratch_font_spec = Ffont_spec (0, NULL);
5086 staticpro (&scratch_font_prefer);
5087 scratch_font_prefer = Ffont_spec (0, NULL);
5089 staticpro (&Vfont_log_deferred);
5090 Vfont_log_deferred = Fmake_vector (make_number (3), Qnil);
5092 #if 0
5093 #ifdef HAVE_LIBOTF
5094 staticpro (&otf_list);
5095 otf_list = Qnil;
5096 #endif /* HAVE_LIBOTF */
5097 #endif /* 0 */
5099 defsubr (&Sfontp);
5100 defsubr (&Sfont_spec);
5101 defsubr (&Sfont_get);
5102 #ifdef HAVE_WINDOW_SYSTEM
5103 defsubr (&Sfont_face_attributes);
5104 #endif
5105 defsubr (&Sfont_put);
5106 defsubr (&Slist_fonts);
5107 defsubr (&Sfont_family_list);
5108 defsubr (&Sfind_font);
5109 defsubr (&Sfont_xlfd_name);
5110 defsubr (&Sclear_font_cache);
5111 defsubr (&Sfont_shape_gstring);
5112 defsubr (&Sfont_variation_glyphs);
5113 #if 0
5114 defsubr (&Sfont_drive_otf);
5115 defsubr (&Sfont_otf_alternates);
5116 #endif /* 0 */
5118 #ifdef FONT_DEBUG
5119 defsubr (&Sopen_font);
5120 defsubr (&Sclose_font);
5121 defsubr (&Squery_font);
5122 defsubr (&Sfont_get_glyphs);
5123 defsubr (&Sfont_match_p);
5124 defsubr (&Sfont_at);
5125 #if 0
5126 defsubr (&Sdraw_string);
5127 #endif
5128 #endif /* FONT_DEBUG */
5129 #ifdef HAVE_WINDOW_SYSTEM
5130 defsubr (&Sfont_info);
5131 #endif
5133 DEFVAR_LISP ("font-encoding-alist", Vfont_encoding_alist,
5134 doc: /*
5135 Alist of fontname patterns vs the corresponding encoding and repertory info.
5136 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5137 where ENCODING is a charset or a char-table,
5138 and REPERTORY is a charset, a char-table, or nil.
5140 If ENCODING and REPERTORY are the same, the element can have the form
5141 \(REGEXP . ENCODING).
5143 ENCODING is for converting a character to a glyph code of the font.
5144 If ENCODING is a charset, encoding a character by the charset gives
5145 the corresponding glyph code. If ENCODING is a char-table, looking up
5146 the table by a character gives the corresponding glyph code.
5148 REPERTORY specifies a repertory of characters supported by the font.
5149 If REPERTORY is a charset, all characters belonging to the charset are
5150 supported. If REPERTORY is a char-table, all characters who have a
5151 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5152 gets the repertory information by an opened font and ENCODING. */);
5153 Vfont_encoding_alist = Qnil;
5155 /* FIXME: These 3 vars are not quite what they appear: setq on them
5156 won't have any effect other than disconnect them from the style
5157 table used by the font display code. So we make them read-only,
5158 to avoid this confusing situation. */
5160 DEFVAR_LISP_NOPRO ("font-weight-table", Vfont_weight_table,
5161 doc: /* Vector of valid font weight values.
5162 Each element has the form:
5163 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5164 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5165 Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
5166 XSYMBOL (intern_c_string ("font-weight-table"))->constant = 1;
5168 DEFVAR_LISP_NOPRO ("font-slant-table", Vfont_slant_table,
5169 doc: /* Vector of font slant symbols vs the corresponding numeric values.
5170 See `font-weight-table' for the format of the vector. */);
5171 Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
5172 XSYMBOL (intern_c_string ("font-slant-table"))->constant = 1;
5174 DEFVAR_LISP_NOPRO ("font-width-table", Vfont_width_table,
5175 doc: /* Alist of font width symbols vs the corresponding numeric values.
5176 See `font-weight-table' for the format of the vector. */);
5177 Vfont_width_table = BUILD_STYLE_TABLE (width_table);
5178 XSYMBOL (intern_c_string ("font-width-table"))->constant = 1;
5180 staticpro (&font_style_table);
5181 font_style_table = Fmake_vector (make_number (3), Qnil);
5182 ASET (font_style_table, 0, Vfont_weight_table);
5183 ASET (font_style_table, 1, Vfont_slant_table);
5184 ASET (font_style_table, 2, Vfont_width_table);
5186 DEFVAR_LISP ("font-log", Vfont_log, doc: /*
5187 *Logging list of font related actions and results.
5188 The value t means to suppress the logging.
5189 The initial value is set to nil if the environment variable
5190 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5191 Vfont_log = Qnil;
5193 #ifdef HAVE_WINDOW_SYSTEM
5194 #ifdef HAVE_FREETYPE
5195 syms_of_ftfont ();
5196 #ifdef HAVE_X_WINDOWS
5197 syms_of_xfont ();
5198 syms_of_ftxfont ();
5199 #ifdef HAVE_XFT
5200 syms_of_xftfont ();
5201 #endif /* HAVE_XFT */
5202 #endif /* HAVE_X_WINDOWS */
5203 #else /* not HAVE_FREETYPE */
5204 #ifdef HAVE_X_WINDOWS
5205 syms_of_xfont ();
5206 #endif /* HAVE_X_WINDOWS */
5207 #endif /* not HAVE_FREETYPE */
5208 #ifdef HAVE_BDFFONT
5209 syms_of_bdffont ();
5210 #endif /* HAVE_BDFFONT */
5211 #ifdef WINDOWSNT
5212 syms_of_w32font ();
5213 #endif /* WINDOWSNT */
5214 #ifdef HAVE_NS
5215 syms_of_nsfont ();
5216 #endif /* HAVE_NS */
5217 #endif /* HAVE_WINDOW_SYSTEM */
5220 void
5221 init_font (void)
5223 Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;