Fix some file names.
[emacs.git] / src / font.c
blob2f98141b53dd8137e4d9b5c80e6a9d79356ee9c0
1 /* font.c -- "Font" primitives.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ctype.h>
27 #include "lisp.h"
28 #include "buffer.h"
29 #include "frame.h"
30 #include "window.h"
31 #include "dispextern.h"
32 #include "charset.h"
33 #include "character.h"
34 #include "composite.h"
35 #include "fontset.h"
36 #include "font.h"
38 #ifdef HAVE_X_WINDOWS
39 #include "xterm.h"
40 #endif /* HAVE_X_WINDOWS */
42 #ifdef HAVE_NTGUI
43 #include "w32term.h"
44 #endif /* HAVE_NTGUI */
46 #ifdef HAVE_NS
47 #include "nsterm.h"
48 #endif /* HAVE_NS */
50 Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
52 #ifdef HAVE_NS
53 extern Lisp_Object Qfontsize;
54 #endif
56 Lisp_Object Qopentype;
58 /* Important character set strings. */
59 Lisp_Object Qascii_0, Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
61 #ifdef HAVE_NS
62 #define DEFAULT_ENCODING Qiso10646_1
63 #else
64 #define DEFAULT_ENCODING Qiso8859_1
65 #endif
67 /* Unicode category `Cf'. */
68 static Lisp_Object QCf;
70 /* Special vector of zero length. This is repeatedly used by (struct
71 font_driver *)->list when a specified font is not found. */
72 static Lisp_Object null_vector;
74 static Lisp_Object Vfont_weight_table, Vfont_slant_table, Vfont_width_table;
76 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
77 static Lisp_Object font_style_table;
79 /* Structure used for tables mapping weight, slant, and width numeric
80 values and their names. */
82 struct table_entry
84 int numeric;
85 /* The first one is a valid name as a face attribute.
86 The second one (if any) is a typical name in XLFD field. */
87 char *names[5];
88 Lisp_Object *symbols;
91 /* Table of weight numeric values and their names. This table must be
92 sorted by numeric values in ascending order. */
94 static struct table_entry weight_table[] =
96 { 0, { "thin" }},
97 { 20, { "ultra-light", "ultralight" }},
98 { 40, { "extra-light", "extralight" }},
99 { 50, { "light" }},
100 { 75, { "semi-light", "semilight", "demilight", "book" }},
101 { 100, { "normal", "medium", "regular" }},
102 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
103 { 200, { "bold" }},
104 { 205, { "extra-bold", "extrabold" }},
105 { 210, { "ultra-bold", "ultrabold", "black" }}
108 /* Table of slant numeric values and their names. This table must be
109 sorted by numeric values in ascending order. */
111 static struct table_entry slant_table[] =
113 { 0, { "reverse-oblique", "ro" }},
114 { 10, { "reverse-italic", "ri" }},
115 { 100, { "normal", "r" }},
116 { 200, { "italic" ,"i", "ot" }},
117 { 210, { "oblique", "o" }}
120 /* Table of width numeric values and their names. This table must be
121 sorted by numeric values in ascending order. */
123 static struct table_entry width_table[] =
125 { 50, { "ultra-condensed", "ultracondensed" }},
126 { 63, { "extra-condensed", "extracondensed" }},
127 { 75, { "condensed", "compressed", "narrow" }},
128 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
129 { 100, { "normal", "medium", "regular" }},
130 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
131 { 125, { "expanded" }},
132 { 150, { "extra-expanded", "extraexpanded" }},
133 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
136 extern Lisp_Object Qnormal;
138 /* Symbols representing keys of normal font properties. */
139 extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth;
140 extern Lisp_Object QCheight, QCsize, QCname;
142 Lisp_Object QCfoundry, QCadstyle, QCregistry;
143 /* Symbols representing keys of font extra info. */
144 Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
145 Lisp_Object QCantialias, QCfont_entity, QCfc_unknown_spec;
146 /* Symbols representing values of font spacing property. */
147 Lisp_Object Qc, Qm, Qp, Qd;
149 Lisp_Object Vfont_encoding_alist;
151 /* Alist of font registry symbol and the corresponding charsets
152 information. The information is retrieved from
153 Vfont_encoding_alist on demand.
155 Eash element has the form:
156 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
158 (REGISTRY . nil)
160 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
161 encodes a character code to a glyph code of a font, and
162 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
163 character is supported by a font.
165 The latter form means that the information for REGISTRY couldn't be
166 retrieved. */
167 static Lisp_Object font_charset_alist;
169 /* List of all font drivers. Each font-backend (XXXfont.c) calls
170 register_font_driver in syms_of_XXXfont to register its font-driver
171 here. */
172 static struct font_driver_list *font_driver_list;
176 /* Creaters of font-related Lisp object. */
178 Lisp_Object
179 font_make_spec ()
181 Lisp_Object font_spec;
182 struct font_spec *spec
183 = ((struct font_spec *)
184 allocate_pseudovector (VECSIZE (struct font_spec),
185 FONT_SPEC_MAX, PVEC_FONT));
186 XSETFONT (font_spec, spec);
187 return font_spec;
190 Lisp_Object
191 font_make_entity ()
193 Lisp_Object font_entity;
194 struct font_entity *entity
195 = ((struct font_entity *)
196 allocate_pseudovector (VECSIZE (struct font_entity),
197 FONT_ENTITY_MAX, PVEC_FONT));
198 XSETFONT (font_entity, entity);
199 return font_entity;
202 /* Create a font-object whose structure size is SIZE. If ENTITY is
203 not nil, copy properties from ENTITY to the font-object. If
204 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
205 Lisp_Object
206 font_make_object (size, entity, pixelsize)
207 int size;
208 Lisp_Object entity;
209 int pixelsize;
211 Lisp_Object font_object;
212 struct font *font
213 = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX, PVEC_FONT);
214 int i;
216 XSETFONT (font_object, font);
218 if (! NILP (entity))
220 for (i = 1; i < FONT_SPEC_MAX; i++)
221 font->props[i] = AREF (entity, i);
222 if (! NILP (AREF (entity, FONT_EXTRA_INDEX)))
223 font->props[FONT_EXTRA_INDEX]
224 = Fcopy_sequence (AREF (entity, FONT_EXTRA_INDEX));
226 if (size > 0)
227 font->props[FONT_SIZE_INDEX] = make_number (pixelsize);
228 return font_object;
233 static int font_pixel_size P_ ((FRAME_PTR f, Lisp_Object));
234 static Lisp_Object font_open_entity P_ ((FRAME_PTR, Lisp_Object, int));
235 static Lisp_Object font_matching_entity P_ ((FRAME_PTR, Lisp_Object *,
236 Lisp_Object));
238 /* Number of registered font drivers. */
239 static int num_font_drivers;
242 /* Return a Lispy value of a font property value at STR and LEN bytes.
243 If STR is "*", it returns nil.
244 If FORCE_SYMBOL is zero and all characters in STR are digits, it
245 returns an integer. Otherwise, it returns a symbol interned from
246 STR. */
248 Lisp_Object
249 font_intern_prop (str, len, force_symbol)
250 char *str;
251 int len;
252 int force_symbol;
254 int i;
255 Lisp_Object tem;
256 Lisp_Object obarray;
258 if (len == 1 && *str == '*')
259 return Qnil;
260 if (!force_symbol && len >=1 && isdigit (*str))
262 for (i = 1; i < len; i++)
263 if (! isdigit (str[i]))
264 break;
265 if (i == len)
266 return make_number (atoi (str));
269 /* The following code is copied from the function intern (in lread.c). */
270 obarray = Vobarray;
271 if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
272 obarray = check_obarray (obarray);
273 tem = oblookup (obarray, str, len, len);
274 if (SYMBOLP (tem))
275 return tem;
276 return Fintern (make_unibyte_string (str, len), obarray);
279 /* Return a pixel size of font-spec SPEC on frame F. */
281 static int
282 font_pixel_size (f, spec)
283 FRAME_PTR f;
284 Lisp_Object spec;
286 #ifdef HAVE_WINDOW_SYSTEM
287 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
288 double point_size;
289 int dpi, pixel_size;
290 Lisp_Object val;
292 if (INTEGERP (size))
293 return XINT (size);
294 if (NILP (size))
295 return 0;
296 font_assert (FLOATP (size));
297 point_size = XFLOAT_DATA (size);
298 val = AREF (spec, FONT_DPI_INDEX);
299 if (INTEGERP (val))
300 dpi = XINT (val);
301 else
302 dpi = f->resy;
303 pixel_size = POINT_TO_PIXEL (point_size, dpi);
304 return pixel_size;
305 #else
306 return 1;
307 #endif
311 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
312 font vector. If VAL is not valid (i.e. not registered in
313 font_style_table), return -1 if NOERROR is zero, and return a
314 proper index if NOERROR is nonzero. In that case, register VAL in
315 font_style_table if VAL is a symbol, and return a closest index if
316 VAL is an integer. */
319 font_style_to_value (prop, val, noerror)
320 enum font_property_index prop;
321 Lisp_Object val;
322 int noerror;
324 Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
325 int len = ASIZE (table);
326 int i, j;
328 if (SYMBOLP (val))
330 unsigned char *s;
331 Lisp_Object args[2], elt;
333 /* At first try exact match. */
334 for (i = 0; i < len; i++)
335 for (j = 1; j < ASIZE (AREF (table, i)); j++)
336 if (EQ (val, AREF (AREF (table, i), j)))
337 return ((XINT (AREF (AREF (table, i), 0)) << 8)
338 | (i << 4) | (j - 1));
339 /* Try also with case-folding match. */
340 s = SDATA (SYMBOL_NAME (val));
341 for (i = 0; i < len; i++)
342 for (j = 1; j < ASIZE (AREF (table, i)); j++)
344 elt = AREF (AREF (table, i), j);
345 if (xstrcasecmp (s, SDATA (SYMBOL_NAME (elt))) == 0)
346 return ((XINT (AREF (AREF (table, i), 0)) << 8)
347 | (i << 4) | (j - 1));
349 if (! noerror)
350 return -1;
351 if (len == 255)
352 abort ();
353 elt = Fmake_vector (make_number (2), make_number (255));
354 ASET (elt, 1, val);
355 args[0] = table;
356 args[1] = Fmake_vector (make_number (1), elt);
357 ASET (font_style_table, prop - FONT_WEIGHT_INDEX, Fvconcat (2, args));
358 return (255 << 8) | (i << 4);
360 else
362 int i, last_n;
363 int numeric = XINT (val);
365 for (i = 0, last_n = -1; i < len; i++)
367 int 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 (font, prop, for_face)
388 Lisp_Object font;
389 enum font_property_index prop;
390 int for_face;
392 Lisp_Object val = AREF (font, prop);
393 Lisp_Object table, elt;
394 int i;
396 if (NILP (val))
397 return Qnil;
398 table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
399 i = XINT (val) & 0xFF;
400 font_assert (((i >> 4) & 0xF) < ASIZE (table));
401 elt = AREF (table, ((i >> 4) & 0xF));
402 font_assert ((i & 0xF) + 1 < ASIZE (elt));
403 return (for_face ? AREF (elt, 1) : AREF (elt, (i & 0xF) + 1));
406 extern Lisp_Object Vface_alternative_font_family_alist;
408 extern Lisp_Object find_font_encoding P_ ((Lisp_Object));
411 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
412 FONTNAME. ENCODING is a charset symbol that specifies the encoding
413 of the font. REPERTORY is a charset symbol or nil. */
415 Lisp_Object
416 find_font_encoding (fontname)
417 Lisp_Object fontname;
419 Lisp_Object tail, elt;
421 for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
423 elt = XCAR (tail);
424 if (CONSP (elt)
425 && STRINGP (XCAR (elt))
426 && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
427 && (SYMBOLP (XCDR (elt))
428 ? CHARSETP (XCDR (elt))
429 : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
430 return (XCDR (elt));
432 /* We don't know the encoding of this font. Let's assume `ascii'. */
433 return Qascii;
436 /* Return encoding charset and repertory charset for REGISTRY in
437 ENCODING and REPERTORY correspondingly. If correct information for
438 REGISTRY is available, return 0. Otherwise return -1. */
441 font_registry_charsets (registry, encoding, repertory)
442 Lisp_Object registry;
443 struct charset **encoding, **repertory;
445 Lisp_Object val;
446 int encoding_id, repertory_id;
448 val = Fassoc_string (registry, font_charset_alist, Qt);
449 if (! NILP (val))
451 val = XCDR (val);
452 if (NILP (val))
453 return -1;
454 encoding_id = XINT (XCAR (val));
455 repertory_id = XINT (XCDR (val));
457 else
459 val = find_font_encoding (SYMBOL_NAME (registry));
460 if (SYMBOLP (val) && CHARSETP (val))
462 encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val));
464 else if (CONSP (val))
466 if (! CHARSETP (XCAR (val)))
467 goto invalid_entry;
468 encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val)));
469 if (NILP (XCDR (val)))
470 repertory_id = -1;
471 else
473 if (! CHARSETP (XCDR (val)))
474 goto invalid_entry;
475 repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val)));
478 else
479 goto invalid_entry;
480 val = Fcons (make_number (encoding_id), make_number (repertory_id));
481 font_charset_alist
482 = nconc2 (font_charset_alist, Fcons (Fcons (registry, val), Qnil));
485 if (encoding)
486 *encoding = CHARSET_FROM_ID (encoding_id);
487 if (repertory)
488 *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL;
489 return 0;
491 invalid_entry:
492 font_charset_alist
493 = nconc2 (font_charset_alist, Fcons (Fcons (registry, Qnil), Qnil));
494 return -1;
498 /* Font property value validaters. See the comment of
499 font_property_table for the meaning of the arguments. */
501 static Lisp_Object font_prop_validate P_ ((int, Lisp_Object, Lisp_Object));
502 static Lisp_Object font_prop_validate_symbol P_ ((Lisp_Object, Lisp_Object));
503 static Lisp_Object font_prop_validate_style P_ ((Lisp_Object, Lisp_Object));
504 static Lisp_Object font_prop_validate_non_neg P_ ((Lisp_Object, Lisp_Object));
505 static Lisp_Object font_prop_validate_spacing P_ ((Lisp_Object, Lisp_Object));
506 static int get_font_prop_index P_ ((Lisp_Object));
508 static Lisp_Object
509 font_prop_validate_symbol (prop, val)
510 Lisp_Object prop, val;
512 if (STRINGP (val))
513 val = Fintern (val, Qnil);
514 if (! SYMBOLP (val))
515 val = Qerror;
516 else if (EQ (prop, QCregistry))
517 val = Fintern (Fdowncase (SYMBOL_NAME (val)), Qnil);
518 return val;
522 static Lisp_Object
523 font_prop_validate_style (style, val)
524 Lisp_Object style, val;
526 enum font_property_index prop = (EQ (style, QCweight) ? FONT_WEIGHT_INDEX
527 : EQ (style, QCslant) ? FONT_SLANT_INDEX
528 : FONT_WIDTH_INDEX);
529 int n;
530 if (INTEGERP (val))
532 n = XINT (val);
533 if (((n >> 4) & 0xF)
534 >= ASIZE (AREF (font_style_table, prop - FONT_WEIGHT_INDEX)))
535 val = Qerror;
536 else
538 Lisp_Object elt = AREF (AREF (font_style_table, prop - FONT_WEIGHT_INDEX), (n >> 4) & 0xF);
540 if ((n & 0xF) + 1 >= ASIZE (elt))
541 val = Qerror;
542 else if (XINT (AREF (elt, 0)) != (n >> 8))
543 val = Qerror;
546 else if (SYMBOLP (val))
548 int n = font_style_to_value (prop, val, 0);
550 val = n >= 0 ? make_number (n) : Qerror;
552 else
553 val = Qerror;
554 return val;
557 static Lisp_Object
558 font_prop_validate_non_neg (prop, val)
559 Lisp_Object prop, val;
561 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
562 ? val : Qerror);
565 static Lisp_Object
566 font_prop_validate_spacing (prop, val)
567 Lisp_Object prop, val;
569 if (NILP (val) || (NATNUMP (val) && XINT (val) <= FONT_SPACING_CHARCELL))
570 return val;
571 if (SYMBOLP (val) && SBYTES (SYMBOL_NAME (val)) == 1)
573 char spacing = SDATA (SYMBOL_NAME (val))[0];
575 if (spacing == 'c' || spacing == 'C')
576 return make_number (FONT_SPACING_CHARCELL);
577 if (spacing == 'm' || spacing == 'M')
578 return make_number (FONT_SPACING_MONO);
579 if (spacing == 'p' || spacing == 'P')
580 return make_number (FONT_SPACING_PROPORTIONAL);
581 if (spacing == 'd' || spacing == 'D')
582 return make_number (FONT_SPACING_DUAL);
584 return Qerror;
587 static Lisp_Object
588 font_prop_validate_otf (prop, val)
589 Lisp_Object prop, val;
591 Lisp_Object tail, tmp;
592 int i;
594 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
595 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
596 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
597 if (! CONSP (val))
598 return Qerror;
599 if (! SYMBOLP (XCAR (val)))
600 return Qerror;
601 tail = XCDR (val);
602 if (NILP (tail))
603 return val;
604 if (! CONSP (tail) || ! SYMBOLP (XCAR (val)))
605 return Qerror;
606 for (i = 0; i < 2; i++)
608 tail = XCDR (tail);
609 if (NILP (tail))
610 return val;
611 if (! CONSP (tail))
612 return Qerror;
613 for (tmp = XCAR (tail); CONSP (tmp); tmp = XCDR (tmp))
614 if (! SYMBOLP (XCAR (tmp)))
615 return Qerror;
616 if (! NILP (tmp))
617 return Qerror;
619 return val;
622 /* Structure of known font property keys and validater of the
623 values. */
624 struct
626 /* Pointer to the key symbol. */
627 Lisp_Object *key;
628 /* Function to validate PROP's value VAL, or NULL if any value is
629 ok. The value is VAL or its regularized value if VAL is valid,
630 and Qerror if not. */
631 Lisp_Object (*validater) P_ ((Lisp_Object prop, Lisp_Object val));
632 } font_property_table[] =
633 { { &QCtype, font_prop_validate_symbol },
634 { &QCfoundry, font_prop_validate_symbol },
635 { &QCfamily, font_prop_validate_symbol },
636 { &QCadstyle, font_prop_validate_symbol },
637 { &QCregistry, font_prop_validate_symbol },
638 { &QCweight, font_prop_validate_style },
639 { &QCslant, font_prop_validate_style },
640 { &QCwidth, font_prop_validate_style },
641 { &QCsize, font_prop_validate_non_neg },
642 { &QCdpi, font_prop_validate_non_neg },
643 { &QCspacing, font_prop_validate_spacing },
644 { &QCavgwidth, font_prop_validate_non_neg },
645 /* The order of the above entries must match with enum
646 font_property_index. */
647 { &QClang, font_prop_validate_symbol },
648 { &QCscript, font_prop_validate_symbol },
649 { &QCotf, font_prop_validate_otf }
652 /* Size (number of elements) of the above table. */
653 #define FONT_PROPERTY_TABLE_SIZE \
654 ((sizeof font_property_table) / (sizeof *font_property_table))
656 /* Return an index number of font property KEY or -1 if KEY is not an
657 already known property. */
659 static int
660 get_font_prop_index (key)
661 Lisp_Object key;
663 int i;
665 for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++)
666 if (EQ (key, *font_property_table[i].key))
667 return i;
668 return -1;
671 /* Validate the font property. The property key is specified by the
672 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
673 signal an error. The value is VAL or the regularized one. */
675 static Lisp_Object
676 font_prop_validate (idx, prop, val)
677 int idx;
678 Lisp_Object prop, val;
680 Lisp_Object validated;
682 if (NILP (val))
683 return val;
684 if (NILP (prop))
685 prop = *font_property_table[idx].key;
686 else
688 idx = get_font_prop_index (prop);
689 if (idx < 0)
690 return val;
692 validated = (font_property_table[idx].validater) (prop, val);
693 if (EQ (validated, Qerror))
694 signal_error ("invalid font property", Fcons (prop, val));
695 return validated;
699 /* Store VAL as a value of extra font property PROP in FONT while
700 keeping the sorting order. Don't check the validity of VAL. */
702 Lisp_Object
703 font_put_extra (font, prop, val)
704 Lisp_Object font, prop, val;
706 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
707 Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
709 if (NILP (slot))
711 Lisp_Object prev = Qnil;
713 while (CONSP (extra)
714 && NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
715 prev = extra, extra = XCDR (extra);
716 if (NILP (prev))
717 ASET (font, FONT_EXTRA_INDEX, Fcons (Fcons (prop, val), extra));
718 else
719 XSETCDR (prev, Fcons (Fcons (prop, val), extra));
720 return val;
722 XSETCDR (slot, val);
723 return val;
727 /* Font name parser and unparser */
729 static int parse_matrix P_ ((char *));
730 static int font_expand_wildcards P_ ((Lisp_Object *, int));
731 static int font_parse_name P_ ((char *, Lisp_Object));
733 /* An enumerator for each field of an XLFD font name. */
734 enum xlfd_field_index
736 XLFD_FOUNDRY_INDEX,
737 XLFD_FAMILY_INDEX,
738 XLFD_WEIGHT_INDEX,
739 XLFD_SLANT_INDEX,
740 XLFD_SWIDTH_INDEX,
741 XLFD_ADSTYLE_INDEX,
742 XLFD_PIXEL_INDEX,
743 XLFD_POINT_INDEX,
744 XLFD_RESX_INDEX,
745 XLFD_RESY_INDEX,
746 XLFD_SPACING_INDEX,
747 XLFD_AVGWIDTH_INDEX,
748 XLFD_REGISTRY_INDEX,
749 XLFD_ENCODING_INDEX,
750 XLFD_LAST_INDEX
753 /* An enumerator for mask bit corresponding to each XLFD field. */
754 enum xlfd_field_mask
756 XLFD_FOUNDRY_MASK = 0x0001,
757 XLFD_FAMILY_MASK = 0x0002,
758 XLFD_WEIGHT_MASK = 0x0004,
759 XLFD_SLANT_MASK = 0x0008,
760 XLFD_SWIDTH_MASK = 0x0010,
761 XLFD_ADSTYLE_MASK = 0x0020,
762 XLFD_PIXEL_MASK = 0x0040,
763 XLFD_POINT_MASK = 0x0080,
764 XLFD_RESX_MASK = 0x0100,
765 XLFD_RESY_MASK = 0x0200,
766 XLFD_SPACING_MASK = 0x0400,
767 XLFD_AVGWIDTH_MASK = 0x0800,
768 XLFD_REGISTRY_MASK = 0x1000,
769 XLFD_ENCODING_MASK = 0x2000
773 /* Parse P pointing the pixel/point size field of the form
774 `[A B C D]' which specifies a transformation matrix:
776 A B 0
777 C D 0
778 0 0 1
780 by which all glyphs of the font are transformed. The spec says
781 that scalar value N for the pixel/point size is equivalent to:
782 A = N * resx/resy, B = C = 0, D = N.
784 Return the scalar value N if the form is valid. Otherwise return
785 -1. */
787 static int
788 parse_matrix (p)
789 char *p;
791 double matrix[4];
792 char *end;
793 int i;
795 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
797 if (*p == '~')
798 matrix[i] = - strtod (p + 1, &end);
799 else
800 matrix[i] = strtod (p, &end);
801 p = end;
803 return (i == 4 ? (int) matrix[3] : -1);
806 /* Expand a wildcard field in FIELD (the first N fields are filled) to
807 multiple fields to fill in all 14 XLFD fields while restring a
808 field position by its contents. */
810 static int
811 font_expand_wildcards (field, n)
812 Lisp_Object field[XLFD_LAST_INDEX];
813 int n;
815 /* Copy of FIELD. */
816 Lisp_Object tmp[XLFD_LAST_INDEX];
817 /* Array of information about where this element can go. Nth
818 element is for Nth element of FIELD. */
819 struct {
820 /* Minimum possible field. */
821 int from;
822 /* Maxinum possible field. */
823 int to;
824 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
825 int mask;
826 } range[XLFD_LAST_INDEX];
827 int i, j;
828 int range_from, range_to;
829 unsigned range_mask;
831 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
832 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
833 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
834 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
835 | XLFD_AVGWIDTH_MASK)
836 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
838 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
839 field. The value is shifted to left one bit by one in the
840 following loop. */
841 for (i = 0, range_mask = 0; i <= 14 - n; i++)
842 range_mask = (range_mask << 1) | 1;
844 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
845 position-based retriction for FIELD[I]. */
846 for (i = 0, range_from = 0, range_to = 14 - n; i < n;
847 i++, range_from++, range_to++, range_mask <<= 1)
849 Lisp_Object val = field[i];
851 tmp[i] = val;
852 if (NILP (val))
854 /* Wildcard. */
855 range[i].from = range_from;
856 range[i].to = range_to;
857 range[i].mask = range_mask;
859 else
861 /* The triplet FROM, TO, and MASK is a value-based
862 retriction for FIELD[I]. */
863 int from, to;
864 unsigned mask;
866 if (INTEGERP (val))
868 int numeric = XINT (val);
870 if (i + 1 == n)
871 from = to = XLFD_ENCODING_INDEX,
872 mask = XLFD_ENCODING_MASK;
873 else if (numeric == 0)
874 from = XLFD_PIXEL_INDEX, to = XLFD_AVGWIDTH_INDEX,
875 mask = XLFD_PIXEL_MASK | XLFD_LARGENUM_MASK;
876 else if (numeric <= 48)
877 from = to = XLFD_PIXEL_INDEX,
878 mask = XLFD_PIXEL_MASK;
879 else
880 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
881 mask = XLFD_LARGENUM_MASK;
883 else if (SBYTES (SYMBOL_NAME (val)) == 0)
884 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
885 mask = XLFD_NULL_MASK;
886 else if (i == 0)
887 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
888 else if (i + 1 == n)
890 Lisp_Object name = SYMBOL_NAME (val);
892 if (SDATA (name)[SBYTES (name) - 1] == '*')
893 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
894 mask = XLFD_REGENC_MASK;
895 else
896 from = to = XLFD_ENCODING_INDEX,
897 mask = XLFD_ENCODING_MASK;
899 else if (range_from <= XLFD_WEIGHT_INDEX
900 && range_to >= XLFD_WEIGHT_INDEX
901 && FONT_WEIGHT_NAME_NUMERIC (val) >= 0)
902 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
903 else if (range_from <= XLFD_SLANT_INDEX
904 && range_to >= XLFD_SLANT_INDEX
905 && FONT_SLANT_NAME_NUMERIC (val) >= 0)
906 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
907 else if (range_from <= XLFD_SWIDTH_INDEX
908 && range_to >= XLFD_SWIDTH_INDEX
909 && FONT_WIDTH_NAME_NUMERIC (val) >= 0)
910 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
911 else
913 if (EQ (val, Qc) || EQ (val, Qm) || EQ (val, Qp) || EQ (val, Qd))
914 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
915 else
916 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
917 mask = XLFD_SYMBOL_MASK;
920 /* Merge position-based and value-based restrictions. */
921 mask &= range_mask;
922 while (from < range_from)
923 mask &= ~(1 << from++);
924 while (from < 14 && ! (mask & (1 << from)))
925 from++;
926 while (to > range_to)
927 mask &= ~(1 << to--);
928 while (to >= 0 && ! (mask & (1 << to)))
929 to--;
930 if (from > to)
931 return -1;
932 range[i].from = from;
933 range[i].to = to;
934 range[i].mask = mask;
936 if (from > range_from || to < range_to)
938 /* The range is narrowed by value-based restrictions.
939 Reflect it to the other fields. */
941 /* Following fields should be after FROM. */
942 range_from = from;
943 /* Preceding fields should be before TO. */
944 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
946 /* Check FROM for non-wildcard field. */
947 if (! NILP (tmp[j]) && range[j].from < from)
949 while (range[j].from < from)
950 range[j].mask &= ~(1 << range[j].from++);
951 while (from < 14 && ! (range[j].mask & (1 << from)))
952 from++;
953 range[j].from = from;
955 else
956 from = range[j].from;
957 if (range[j].to > to)
959 while (range[j].to > to)
960 range[j].mask &= ~(1 << range[j].to--);
961 while (to >= 0 && ! (range[j].mask & (1 << to)))
962 to--;
963 range[j].to = to;
965 else
966 to = range[j].to;
967 if (from > to)
968 return -1;
974 /* Decide all fileds from restrictions in RANGE. */
975 for (i = j = 0; i < n ; i++)
977 if (j < range[i].from)
979 if (i == 0 || ! NILP (tmp[i - 1]))
980 /* None of TMP[X] corresponds to Jth field. */
981 return -1;
982 for (; j < range[i].from; j++)
983 field[j] = Qnil;
985 field[j++] = tmp[i];
987 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
988 return -1;
989 for (; j < XLFD_LAST_INDEX; j++)
990 field[j] = Qnil;
991 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
992 field[XLFD_ENCODING_INDEX]
993 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
994 return 0;
998 #ifdef ENABLE_CHECKING
999 /* Match a 14-field XLFD pattern against a full XLFD font name. */
1000 static int
1001 font_match_xlfd (char *pattern, char *name)
1003 while (*pattern && *name)
1005 if (*pattern == *name)
1006 pattern++;
1007 else if (*pattern == '*')
1008 if (*name == pattern[1])
1009 pattern += 2;
1010 else
1012 else
1013 return 0;
1014 name++;
1016 return 1;
1019 /* Make sure the font object matches the XLFD font name. */
1020 static int
1021 font_check_xlfd_parse (Lisp_Object font, char *name)
1023 char name_check[256];
1024 font_unparse_xlfd (font, 0, name_check, 255);
1025 return font_match_xlfd (name_check, name);
1028 #endif
1031 /* Parse NAME (null terminated) as XLFD and store information in FONT
1032 (font-spec or font-entity). Size property of FONT is set as
1033 follows:
1034 specified XLFD fields FONT property
1035 --------------------- -------------
1036 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
1037 POINT_SIZE and RESY calculated pixel size (Lisp integer)
1038 POINT_SIZE POINT_SIZE/10 (Lisp float)
1040 If NAME is successfully parsed, return 0. Otherwise return -1.
1042 FONT is usually a font-spec, but when this function is called from
1043 X font backend driver, it is a font-entity. In that case, NAME is
1044 a fully specified XLFD. */
1047 font_parse_xlfd (name, font)
1048 char *name;
1049 Lisp_Object font;
1051 int len = strlen (name);
1052 int i, j, n;
1053 char *f[XLFD_LAST_INDEX + 1];
1054 Lisp_Object val;
1055 char *p;
1057 if (len > 255)
1058 /* Maximum XLFD name length is 255. */
1059 return -1;
1060 /* Accept "*-.." as a fully specified XLFD. */
1061 if (name[0] == '*' && name[1] == '-')
1062 i = 1, f[XLFD_FOUNDRY_INDEX] = name;
1063 else
1064 i = 0;
1065 for (p = name + i; *p; p++)
1066 if (*p == '-')
1068 f[i++] = p + 1;
1069 if (i == XLFD_LAST_INDEX)
1070 break;
1072 f[i] = name + len;
1074 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1075 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1077 if (i == XLFD_LAST_INDEX)
1079 /* Fully specified XLFD. */
1080 int pixel_size;
1082 ASET (font, FONT_FOUNDRY_INDEX, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX));
1083 ASET (font, FONT_FAMILY_INDEX, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX));
1084 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1085 i <= XLFD_SWIDTH_INDEX; i++, j++)
1087 val = INTERN_FIELD_SYM (i);
1088 if (! NILP (val))
1090 if ((n = font_style_to_value (j, INTERN_FIELD_SYM (i), 0)) < 0)
1091 return -1;
1092 ASET (font, j, make_number (n));
1095 ASET (font, FONT_ADSTYLE_INDEX, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX));
1096 if (strcmp (f[XLFD_REGISTRY_INDEX], "*-*") == 0)
1097 ASET (font, FONT_REGISTRY_INDEX, Qnil);
1098 else
1099 ASET (font, FONT_REGISTRY_INDEX,
1100 font_intern_prop (f[XLFD_REGISTRY_INDEX],
1101 f[XLFD_LAST_INDEX] - f[XLFD_REGISTRY_INDEX],
1102 1));
1103 p = f[XLFD_PIXEL_INDEX];
1104 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
1105 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
1106 else
1108 val = INTERN_FIELD (XLFD_PIXEL_INDEX);
1109 if (INTEGERP (val))
1110 ASET (font, FONT_SIZE_INDEX, val);
1111 else
1113 double point_size = -1;
1115 font_assert (FONT_SPEC_P (font));
1116 p = f[XLFD_POINT_INDEX];
1117 if (*p == '[')
1118 point_size = parse_matrix (p);
1119 else if (isdigit (*p))
1120 point_size = atoi (p), point_size /= 10;
1121 if (point_size >= 0)
1122 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1126 ASET (font, FONT_DPI_INDEX, INTERN_FIELD (XLFD_RESY_INDEX));
1127 val = INTERN_FIELD (XLFD_SPACING_INDEX);
1128 if (! NILP (val))
1130 val = font_prop_validate_spacing (QCspacing, val);
1131 if (! INTEGERP (val))
1132 return -1;
1133 ASET (font, FONT_SPACING_INDEX, val);
1135 p = f[XLFD_AVGWIDTH_INDEX];
1136 if (*p == '~')
1137 p++;
1138 ASET (font, FONT_AVGWIDTH_INDEX,
1139 font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p, 0));
1141 else
1143 int wild_card_found = 0;
1144 Lisp_Object prop[XLFD_LAST_INDEX];
1146 if (FONT_ENTITY_P (font))
1147 return -1;
1148 for (j = 0; j < i; j++)
1150 if (*f[j] == '*')
1152 if (f[j][1] && f[j][1] != '-')
1153 return -1;
1154 prop[j] = Qnil;
1155 wild_card_found = 1;
1157 else if (j + 1 < i)
1158 prop[j] = INTERN_FIELD (j);
1159 else
1160 prop[j] = font_intern_prop (f[j], f[i] - f[j], 0);
1162 if (! wild_card_found)
1163 return -1;
1164 if (font_expand_wildcards (prop, i) < 0)
1165 return -1;
1167 ASET (font, FONT_FOUNDRY_INDEX, prop[XLFD_FOUNDRY_INDEX]);
1168 ASET (font, FONT_FAMILY_INDEX, prop[XLFD_FAMILY_INDEX]);
1169 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1170 i <= XLFD_SWIDTH_INDEX; i++, j++)
1171 if (! NILP (prop[i]))
1173 if ((n = font_style_to_value (j, prop[i], 1)) < 0)
1174 return -1;
1175 ASET (font, j, make_number (n));
1177 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1178 val = prop[XLFD_REGISTRY_INDEX];
1179 if (NILP (val))
1181 val = prop[XLFD_ENCODING_INDEX];
1182 if (! NILP (val))
1183 val = concat2 (build_string ("*-"), SYMBOL_NAME (val));
1185 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1186 val = concat2 (SYMBOL_NAME (val), build_string ("-*"));
1187 else
1188 val = concat3 (SYMBOL_NAME (val), build_string ("-"),
1189 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX]));
1190 if (! NILP (val))
1191 ASET (font, FONT_REGISTRY_INDEX, Fintern (val, Qnil));
1193 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1194 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
1195 else if (INTEGERP (prop[XLFD_POINT_INDEX]))
1197 double point_size = XINT (prop[XLFD_POINT_INDEX]);
1199 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1202 if (INTEGERP (prop[XLFD_RESX_INDEX]))
1203 ASET (font, FONT_DPI_INDEX, prop[XLFD_RESY_INDEX]);
1204 if (! NILP (prop[XLFD_SPACING_INDEX]))
1206 val = font_prop_validate_spacing (QCspacing,
1207 prop[XLFD_SPACING_INDEX]);
1208 if (! INTEGERP (val))
1209 return -1;
1210 ASET (font, FONT_SPACING_INDEX, val);
1212 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1213 ASET (font, FONT_AVGWIDTH_INDEX, prop[XLFD_AVGWIDTH_INDEX]);
1216 return 0;
1219 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1220 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1221 0, use PIXEL_SIZE instead. */
1224 font_unparse_xlfd (font, pixel_size, name, nbytes)
1225 Lisp_Object font;
1226 int pixel_size;
1227 char *name;
1228 int nbytes;
1230 char *f[XLFD_REGISTRY_INDEX + 1];
1231 Lisp_Object val;
1232 int i, j, len = 0;
1234 font_assert (FONTP (font));
1236 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
1237 i++, j++)
1239 if (i == FONT_ADSTYLE_INDEX)
1240 j = XLFD_ADSTYLE_INDEX;
1241 else if (i == FONT_REGISTRY_INDEX)
1242 j = XLFD_REGISTRY_INDEX;
1243 val = AREF (font, i);
1244 if (NILP (val))
1246 if (j == XLFD_REGISTRY_INDEX)
1247 f[j] = "*-*", len += 4;
1248 else
1249 f[j] = "*", len += 2;
1251 else
1253 if (SYMBOLP (val))
1254 val = SYMBOL_NAME (val);
1255 if (j == XLFD_REGISTRY_INDEX
1256 && ! strchr ((char *) SDATA (val), '-'))
1258 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1259 if (SDATA (val)[SBYTES (val) - 1] == '*')
1261 f[j] = alloca (SBYTES (val) + 3);
1262 sprintf (f[j], "%s-*", SDATA (val));
1263 len += SBYTES (val) + 3;
1265 else
1267 f[j] = alloca (SBYTES (val) + 4);
1268 sprintf (f[j], "%s*-*", SDATA (val));
1269 len += SBYTES (val) + 4;
1272 else
1273 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1277 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1278 i++, j++)
1280 val = font_style_symbolic (font, i, 0);
1281 if (NILP (val))
1282 f[j] = "*", len += 2;
1283 else
1285 val = SYMBOL_NAME (val);
1286 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1290 val = AREF (font, FONT_SIZE_INDEX);
1291 font_assert (NUMBERP (val) || NILP (val));
1292 if (INTEGERP (val))
1294 i = XINT (val);
1295 if (i <= 0)
1296 i = pixel_size;
1297 if (i > 0)
1299 f[XLFD_PIXEL_INDEX] = alloca (22);
1300 len += sprintf (f[XLFD_PIXEL_INDEX], "%d-*", i) + 1;
1302 else
1303 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1305 else if (FLOATP (val))
1307 i = XFLOAT_DATA (val) * 10;
1308 f[XLFD_PIXEL_INDEX] = alloca (12);
1309 len += sprintf (f[XLFD_PIXEL_INDEX], "*-%d", i) + 1;
1311 else
1312 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1314 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1316 i = XINT (AREF (font, FONT_DPI_INDEX));
1317 f[XLFD_RESX_INDEX] = alloca (22);
1318 len += sprintf (f[XLFD_RESX_INDEX],
1319 "%d-%d", i, i) + 1;
1321 else
1322 f[XLFD_RESX_INDEX] = "*-*", len += 4;
1323 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1325 int spacing = XINT (AREF (font, FONT_SPACING_INDEX));
1327 f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
1328 : spacing <= FONT_SPACING_DUAL ? "d"
1329 : spacing <= FONT_SPACING_MONO ? "m"
1330 : "c");
1331 len += 2;
1333 else
1334 f[XLFD_SPACING_INDEX] = "*", len += 2;
1335 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1337 f[XLFD_AVGWIDTH_INDEX] = alloca (11);
1338 len += sprintf (f[XLFD_AVGWIDTH_INDEX],
1339 "%d", XINT (AREF (font, FONT_AVGWIDTH_INDEX))) + 1;
1341 else
1342 f[XLFD_AVGWIDTH_INDEX] = "*", len += 2;
1343 len++; /* for terminating '\0'. */
1344 if (len >= nbytes)
1345 return -1;
1346 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1347 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1348 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1349 f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
1350 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
1351 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
1352 f[XLFD_REGISTRY_INDEX]);
1355 /* Parse NAME (null terminated) and store information in FONT
1356 (font-spec or font-entity). NAME is supplied in either the
1357 Fontconfig or GTK font name format. If NAME is successfully
1358 parsed, return 0. Otherwise return -1.
1360 The fontconfig format is
1362 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1364 The GTK format is
1366 FAMILY [PROPS...] [SIZE]
1368 This function tries to guess which format it is. */
1371 font_parse_fcname (name, font)
1372 char *name;
1373 Lisp_Object font;
1375 char *p, *q;
1376 char *size_beg = NULL, *size_end = NULL;
1377 char *props_beg = NULL, *family_end = NULL;
1378 int len = strlen (name);
1380 if (len == 0)
1381 return -1;
1383 for (p = name; *p; p++)
1385 if (*p == '\\' && p[1])
1386 p++;
1387 else if (*p == ':')
1389 props_beg = family_end = p;
1390 break;
1392 else if (*p == '-')
1394 int decimal = 0, size_found = 1;
1395 for (q = p + 1; *q && *q != ':'; q++)
1396 if (! isdigit(*q))
1398 if (*q != '.' || decimal)
1400 size_found = 0;
1401 break;
1403 decimal = 1;
1405 if (size_found)
1407 family_end = p;
1408 size_beg = p + 1;
1409 size_end = q;
1410 break;
1415 if (family_end)
1417 /* A fontconfig name with size and/or property data. */
1418 if (family_end > name)
1420 Lisp_Object family;
1421 family = font_intern_prop (name, family_end - name, 1);
1422 ASET (font, FONT_FAMILY_INDEX, family);
1424 if (size_beg)
1426 double point_size = strtod (size_beg, &size_end);
1427 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1428 if (*size_end == ':' && size_end[1])
1429 props_beg = size_end;
1431 if (props_beg)
1433 /* Now parse ":KEY=VAL" patterns. */
1434 Lisp_Object val;
1436 for (p = props_beg; *p; p = q)
1438 for (q = p + 1; *q && *q != '=' && *q != ':'; q++);
1439 if (*q != '=')
1441 /* Must be an enumerated value. */
1442 int word_len;
1443 p = p + 1;
1444 word_len = q - p;
1445 val = font_intern_prop (p, q - p, 1);
1447 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1449 if (PROP_MATCH ("light", 5)
1450 || PROP_MATCH ("medium", 6)
1451 || PROP_MATCH ("demibold", 8)
1452 || PROP_MATCH ("bold", 4)
1453 || PROP_MATCH ("black", 5))
1454 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
1455 else if (PROP_MATCH ("roman", 5)
1456 || PROP_MATCH ("italic", 6)
1457 || PROP_MATCH ("oblique", 7))
1458 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
1459 else if (PROP_MATCH ("charcell", 8))
1460 ASET (font, FONT_SPACING_INDEX,
1461 make_number (FONT_SPACING_CHARCELL));
1462 else if (PROP_MATCH ("mono", 4))
1463 ASET (font, FONT_SPACING_INDEX,
1464 make_number (FONT_SPACING_MONO));
1465 else if (PROP_MATCH ("proportional", 12))
1466 ASET (font, FONT_SPACING_INDEX,
1467 make_number (FONT_SPACING_PROPORTIONAL));
1468 #undef PROP_MATCH
1470 else
1472 /* KEY=VAL pairs */
1473 Lisp_Object key;
1474 int prop;
1476 if (q - p == 10 && memcmp (p + 1, "pixelsize", 9) == 0)
1477 prop = FONT_SIZE_INDEX;
1478 else
1480 key = font_intern_prop (p, q - p, 1);
1481 prop = get_font_prop_index (key);
1484 p = q + 1;
1485 for (q = p; *q && *q != ':'; q++);
1486 val = font_intern_prop (p, q - p, 0);
1488 if (prop >= FONT_FOUNDRY_INDEX
1489 && prop < FONT_EXTRA_INDEX)
1490 ASET (font, prop, font_prop_validate (prop, Qnil, val));
1491 else
1492 Ffont_put (font, key, val);
1494 p = q;
1498 else
1500 /* Either a fontconfig-style name with no size and property
1501 data, or a GTK-style name. */
1502 Lisp_Object prop;
1503 int word_len, prop_found = 0;
1505 for (p = name; *p; p = *q ? q + 1 : q)
1507 if (isdigit (*p))
1509 int size_found = 1;
1511 for (q = p + 1; *q && *q != ' '; q++)
1512 if (! isdigit (*q))
1514 size_found = 0;
1515 break;
1517 if (size_found)
1519 double point_size = strtod (p, &q);
1520 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1521 continue;
1525 for (q = p + 1; *q && *q != ' '; q++)
1526 if (*q == '\\' && q[1])
1527 q++;
1528 word_len = q - p;
1530 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1532 if (PROP_MATCH ("Ultra-Light", 11))
1534 prop_found = 1;
1535 prop = font_intern_prop ("ultra-light", 11, 1);
1536 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1538 else if (PROP_MATCH ("Light", 5))
1540 prop_found = 1;
1541 prop = font_intern_prop ("light", 5, 1);
1542 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1544 else if (PROP_MATCH ("Semi-Bold", 9))
1546 prop_found = 1;
1547 prop = font_intern_prop ("semi-bold", 9, 1);
1548 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1550 else if (PROP_MATCH ("Bold", 4))
1552 prop_found = 1;
1553 prop = font_intern_prop ("bold", 4, 1);
1554 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1556 else if (PROP_MATCH ("Italic", 6))
1558 prop_found = 1;
1559 prop = font_intern_prop ("italic", 4, 1);
1560 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
1562 else if (PROP_MATCH ("Oblique", 7))
1564 prop_found = 1;
1565 prop = font_intern_prop ("oblique", 7, 1);
1566 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
1568 else {
1569 if (prop_found)
1570 return -1; /* Unknown property in GTK-style font name. */
1571 family_end = q;
1574 #undef PROP_MATCH
1576 if (family_end)
1578 Lisp_Object family;
1579 family = font_intern_prop (name, family_end - name, 1);
1580 ASET (font, FONT_FAMILY_INDEX, family);
1584 return 0;
1587 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1588 NAME (NBYTES length), and return the name length. If
1589 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1592 font_unparse_fcname (font, pixel_size, name, nbytes)
1593 Lisp_Object font;
1594 int pixel_size;
1595 char *name;
1596 int nbytes;
1598 Lisp_Object family, foundry;
1599 Lisp_Object tail, val;
1600 int point_size;
1601 int i, len = 1;
1602 char *p;
1603 Lisp_Object styles[3];
1604 char *style_names[3] = { "weight", "slant", "width" };
1605 char work[256];
1607 family = AREF (font, FONT_FAMILY_INDEX);
1608 if (! NILP (family))
1610 if (SYMBOLP (family))
1612 family = SYMBOL_NAME (family);
1613 len += SBYTES (family);
1615 else
1616 family = Qnil;
1619 val = AREF (font, FONT_SIZE_INDEX);
1620 if (INTEGERP (val))
1622 if (XINT (val) != 0)
1623 pixel_size = XINT (val);
1624 point_size = -1;
1625 len += 21; /* for ":pixelsize=NUM" */
1627 else if (FLOATP (val))
1629 pixel_size = -1;
1630 point_size = (int) XFLOAT_DATA (val);
1631 len += 11; /* for "-NUM" */
1634 foundry = AREF (font, FONT_FOUNDRY_INDEX);
1635 if (! NILP (foundry))
1637 if (SYMBOLP (foundry))
1639 foundry = SYMBOL_NAME (foundry);
1640 len += 9 + SBYTES (foundry); /* ":foundry=NAME" */
1642 else
1643 foundry = Qnil;
1646 for (i = 0; i < 3; i++)
1648 styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
1649 if (! NILP (styles[i]))
1650 len += sprintf (work, ":%s=%s", style_names[i],
1651 SDATA (SYMBOL_NAME (styles[i])));
1654 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1655 len += sprintf (work, ":dpi=%d", XINT (AREF (font, FONT_DPI_INDEX)));
1656 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1657 len += strlen (":spacing=100");
1658 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1659 len += strlen (":scalable=false"); /* or ":scalable=true" */
1660 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
1662 Lisp_Object key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
1664 len += SBYTES (SYMBOL_NAME (key)) + 1; /* for :KEY= */
1665 if (STRINGP (val))
1666 len += SBYTES (val);
1667 else if (INTEGERP (val))
1668 len += sprintf (work, "%d", XINT (val));
1669 else if (SYMBOLP (val))
1670 len += (NILP (val) ? 5 : 4); /* for "false" or "true" */
1673 if (len > nbytes)
1674 return -1;
1675 p = name;
1676 if (! NILP (family))
1677 p += sprintf (p, "%s", SDATA (family));
1678 if (point_size > 0)
1680 if (p == name)
1681 p += sprintf (p, "%d", point_size);
1682 else
1683 p += sprintf (p, "-%d", point_size);
1685 else if (pixel_size > 0)
1686 p += sprintf (p, ":pixelsize=%d", pixel_size);
1687 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1688 p += sprintf (p, ":foundry=%s",
1689 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1690 for (i = 0; i < 3; i++)
1691 if (! NILP (styles[i]))
1692 p += sprintf (p, ":%s=%s", style_names[i],
1693 SDATA (SYMBOL_NAME (styles[i])));
1694 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1695 p += sprintf (p, ":dpi=%d", XINT (AREF (font, FONT_DPI_INDEX)));
1696 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1697 p += sprintf (p, ":spacing=%d", XINT (AREF (font, FONT_SPACING_INDEX)));
1698 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1700 if (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0)
1701 p += sprintf (p, ":scalable=true");
1702 else
1703 p += sprintf (p, ":scalable=false");
1705 return (p - name);
1708 /* Store GTK-style font name of FONT (font-spec or font-entity) in
1709 NAME (NBYTES length), and return the name length. F is the frame
1710 on which the font is displayed; it is used to calculate the point
1711 size. */
1714 font_unparse_gtkname (font, f, name, nbytes)
1715 Lisp_Object font;
1716 struct frame *f;
1717 char *name;
1718 int nbytes;
1720 char *p;
1721 int len = 1;
1722 Lisp_Object family, weight, slant, size;
1723 int point_size = -1;
1725 family = AREF (font, FONT_FAMILY_INDEX);
1726 if (! NILP (family))
1728 if (! SYMBOLP (family))
1729 return -1;
1730 family = SYMBOL_NAME (family);
1731 len += SBYTES (family);
1734 weight = font_style_symbolic (font, FONT_WEIGHT_INDEX, 0);
1735 if (EQ (weight, Qnormal))
1736 weight = Qnil;
1737 else if (! NILP (weight))
1739 weight = SYMBOL_NAME (weight);
1740 len += SBYTES (weight);
1743 slant = font_style_symbolic (font, FONT_SLANT_INDEX, 0);
1744 if (EQ (slant, Qnormal))
1745 slant = Qnil;
1746 else if (! NILP (slant))
1748 slant = SYMBOL_NAME (slant);
1749 len += SBYTES (slant);
1752 size = AREF (font, FONT_SIZE_INDEX);
1753 /* Convert pixel size to point size. */
1754 if (INTEGERP (size))
1756 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
1757 int dpi = 75;
1758 if (INTEGERP (font_dpi))
1759 dpi = XINT (font_dpi);
1760 else if (f)
1761 dpi = f->resy;
1762 point_size = PIXEL_TO_POINT (XINT (size), dpi);
1763 len += 11;
1765 else if (FLOATP (size))
1767 point_size = (int) XFLOAT_DATA (size);
1768 len += 11;
1771 if (len > nbytes)
1772 return -1;
1774 p = name + sprintf (name, "%s", SDATA (family));
1776 if (! NILP (weight))
1778 char *q = p;
1779 p += sprintf (p, " %s", SDATA (weight));
1780 q[1] = toupper (q[1]);
1783 if (! NILP (slant))
1785 char *q = p;
1786 p += sprintf (p, " %s", SDATA (slant));
1787 q[1] = toupper (q[1]);
1790 if (point_size > 0)
1791 p += sprintf (p, " %d", point_size);
1793 return (p - name);
1796 /* Parse NAME (null terminated) and store information in FONT
1797 (font-spec or font-entity). If NAME is successfully parsed, return
1798 0. Otherwise return -1. */
1800 static int
1801 font_parse_name (name, font)
1802 char *name;
1803 Lisp_Object font;
1805 if (name[0] == '-' || index (name, '*'))
1806 return font_parse_xlfd (name, font);
1807 return font_parse_fcname (name, font);
1811 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1812 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1813 part. */
1815 void
1816 font_parse_family_registry (family, registry, font_spec)
1817 Lisp_Object family, registry, font_spec;
1819 int len;
1820 char *p0, *p1;
1822 if (! NILP (family)
1823 && NILP (AREF (font_spec, FONT_FAMILY_INDEX)))
1825 CHECK_STRING (family);
1826 len = SBYTES (family);
1827 p0 = (char *) SDATA (family);
1828 p1 = index (p0, '-');
1829 if (p1)
1831 if ((*p0 != '*' || p1 - p0 > 1)
1832 && NILP (AREF (font_spec, FONT_FOUNDRY_INDEX)))
1833 Ffont_put (font_spec, QCfoundry, font_intern_prop (p0, p1 - p0, 1));
1834 p1++;
1835 len -= p1 - p0;
1836 Ffont_put (font_spec, QCfamily, font_intern_prop (p1, len, 1));
1838 else
1839 ASET (font_spec, FONT_FAMILY_INDEX, Fintern (family, Qnil));
1841 if (! NILP (registry))
1843 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1844 CHECK_STRING (registry);
1845 len = SBYTES (registry);
1846 p0 = (char *) SDATA (registry);
1847 p1 = index (p0, '-');
1848 if (! p1)
1850 if (SDATA (registry)[len - 1] == '*')
1851 registry = concat2 (registry, build_string ("-*"));
1852 else
1853 registry = concat2 (registry, build_string ("*-*"));
1855 registry = Fdowncase (registry);
1856 ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil));
1861 /* This part (through the next ^L) is still experimental and not
1862 tested much. We may drastically change codes. */
1864 /* OTF handler */
1866 #if 0
1868 #define LGSTRING_HEADER_SIZE 6
1869 #define LGSTRING_GLYPH_SIZE 8
1871 static int
1872 check_gstring (gstring)
1873 Lisp_Object gstring;
1875 Lisp_Object val;
1876 int i, j;
1878 CHECK_VECTOR (gstring);
1879 val = AREF (gstring, 0);
1880 CHECK_VECTOR (val);
1881 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1882 goto err;
1883 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1884 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1885 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1886 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1887 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1888 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1889 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1890 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1891 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1892 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1893 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1895 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
1897 val = LGSTRING_GLYPH (gstring, i);
1898 CHECK_VECTOR (val);
1899 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1900 goto err;
1901 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1902 break;
1903 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1904 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1905 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1906 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1907 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1908 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1909 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1910 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1912 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1913 CHECK_VECTOR (val);
1914 if (ASIZE (val) < 3)
1915 goto err;
1916 for (j = 0; j < 3; j++)
1917 CHECK_NUMBER (AREF (val, j));
1920 return i;
1921 err:
1922 error ("Invalid glyph-string format");
1923 return -1;
1926 static void
1927 check_otf_features (otf_features)
1928 Lisp_Object otf_features;
1930 Lisp_Object val;
1932 CHECK_CONS (otf_features);
1933 CHECK_SYMBOL (XCAR (otf_features));
1934 otf_features = XCDR (otf_features);
1935 CHECK_CONS (otf_features);
1936 CHECK_SYMBOL (XCAR (otf_features));
1937 otf_features = XCDR (otf_features);
1938 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1940 CHECK_SYMBOL (Fcar (val));
1941 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1942 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val)));
1944 otf_features = XCDR (otf_features);
1945 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1947 CHECK_SYMBOL (Fcar (val));
1948 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1949 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val)));
1953 #ifdef HAVE_LIBOTF
1954 #include <otf.h>
1956 Lisp_Object otf_list;
1958 static Lisp_Object
1959 otf_tag_symbol (tag)
1960 OTF_Tag tag;
1962 char name[5];
1964 OTF_tag_name (tag, name);
1965 return Fintern (make_unibyte_string (name, 4), Qnil);
1968 static OTF *
1969 otf_open (file)
1970 Lisp_Object file;
1972 Lisp_Object val = Fassoc (file, otf_list);
1973 OTF *otf;
1975 if (! NILP (val))
1976 otf = XSAVE_VALUE (XCDR (val))->pointer;
1977 else
1979 otf = STRINGP (file) ? OTF_open ((char *) SDATA (file)) : NULL;
1980 val = make_save_value (otf, 0);
1981 otf_list = Fcons (Fcons (file, val), otf_list);
1983 return otf;
1987 /* Return a list describing which scripts/languages FONT supports by
1988 which GSUB/GPOS features of OpenType tables. See the comment of
1989 (struct font_driver).otf_capability. */
1991 Lisp_Object
1992 font_otf_capability (font)
1993 struct font *font;
1995 OTF *otf;
1996 Lisp_Object capability = Fcons (Qnil, Qnil);
1997 int i;
1999 otf = otf_open (font->props[FONT_FILE_INDEX]);
2000 if (! otf)
2001 return Qnil;
2002 for (i = 0; i < 2; i++)
2004 OTF_GSUB_GPOS *gsub_gpos;
2005 Lisp_Object script_list = Qnil;
2006 int j;
2008 if (OTF_get_features (otf, i == 0) < 0)
2009 continue;
2010 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
2011 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
2013 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
2014 Lisp_Object langsys_list = Qnil;
2015 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
2016 int k;
2018 for (k = script->LangSysCount; k >= 0; k--)
2020 OTF_LangSys *langsys;
2021 Lisp_Object feature_list = Qnil;
2022 Lisp_Object langsys_tag;
2023 int l;
2025 if (k == script->LangSysCount)
2027 langsys = &script->DefaultLangSys;
2028 langsys_tag = Qnil;
2030 else
2032 langsys = script->LangSys + k;
2033 langsys_tag
2034 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
2036 for (l = langsys->FeatureCount - 1; l >= 0; l--)
2038 OTF_Feature *feature
2039 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
2040 Lisp_Object feature_tag
2041 = otf_tag_symbol (feature->FeatureTag);
2043 feature_list = Fcons (feature_tag, feature_list);
2045 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
2046 langsys_list);
2048 script_list = Fcons (Fcons (script_tag, langsys_list),
2049 script_list);
2052 if (i == 0)
2053 XSETCAR (capability, script_list);
2054 else
2055 XSETCDR (capability, script_list);
2058 return capability;
2061 /* Parse OTF features in SPEC and write a proper features spec string
2062 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
2063 assured that the sufficient memory has already allocated for
2064 FEATURES. */
2066 static void
2067 generate_otf_features (spec, features)
2068 Lisp_Object spec;
2069 char *features;
2071 Lisp_Object val;
2072 char *p;
2073 int asterisk;
2075 p = features;
2076 *p = '\0';
2077 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
2079 val = XCAR (spec);
2080 CHECK_SYMBOL (val);
2081 if (p > features)
2082 *p++ = ',';
2083 if (SREF (SYMBOL_NAME (val), 0) == '*')
2085 asterisk = 1;
2086 *p++ = '*';
2088 else if (! asterisk)
2090 val = SYMBOL_NAME (val);
2091 p += sprintf (p, "%s", SDATA (val));
2093 else
2095 val = SYMBOL_NAME (val);
2096 p += sprintf (p, "~%s", SDATA (val));
2099 if (CONSP (spec))
2100 error ("OTF spec too long");
2103 Lisp_Object
2104 font_otf_DeviceTable (device_table)
2105 OTF_DeviceTable *device_table;
2107 int len = device_table->StartSize - device_table->EndSize + 1;
2109 return Fcons (make_number (len),
2110 make_unibyte_string (device_table->DeltaValue, len));
2113 Lisp_Object
2114 font_otf_ValueRecord (value_format, value_record)
2115 int value_format;
2116 OTF_ValueRecord *value_record;
2118 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
2120 if (value_format & OTF_XPlacement)
2121 ASET (val, 0, make_number (value_record->XPlacement));
2122 if (value_format & OTF_YPlacement)
2123 ASET (val, 1, make_number (value_record->YPlacement));
2124 if (value_format & OTF_XAdvance)
2125 ASET (val, 2, make_number (value_record->XAdvance));
2126 if (value_format & OTF_YAdvance)
2127 ASET (val, 3, make_number (value_record->YAdvance));
2128 if (value_format & OTF_XPlaDevice)
2129 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
2130 if (value_format & OTF_YPlaDevice)
2131 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
2132 if (value_format & OTF_XAdvDevice)
2133 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
2134 if (value_format & OTF_YAdvDevice)
2135 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
2136 return val;
2139 Lisp_Object
2140 font_otf_Anchor (anchor)
2141 OTF_Anchor *anchor;
2143 Lisp_Object val;
2145 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
2146 ASET (val, 0, make_number (anchor->XCoordinate));
2147 ASET (val, 1, make_number (anchor->YCoordinate));
2148 if (anchor->AnchorFormat == 2)
2149 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
2150 else
2152 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
2153 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
2155 return val;
2157 #endif /* HAVE_LIBOTF */
2158 #endif /* 0 */
2161 /* Font sorting */
2163 static unsigned font_score P_ ((Lisp_Object, Lisp_Object *));
2164 static int font_compare P_ ((const void *, const void *));
2165 static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object,
2166 Lisp_Object, int));
2168 /* Return a rescaling ratio of FONT_ENTITY. */
2169 extern Lisp_Object Vface_font_rescale_alist;
2171 static double
2172 font_rescale_ratio (font_entity)
2173 Lisp_Object font_entity;
2175 Lisp_Object tail, elt;
2176 Lisp_Object name = Qnil;
2178 for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail))
2180 elt = XCAR (tail);
2181 if (FLOATP (XCDR (elt)))
2183 if (STRINGP (XCAR (elt)))
2185 if (NILP (name))
2186 name = Ffont_xlfd_name (font_entity, Qnil);
2187 if (fast_string_match_ignore_case (XCAR (elt), name) >= 0)
2188 return XFLOAT_DATA (XCDR (elt));
2190 else if (FONT_SPEC_P (XCAR (elt)))
2192 if (font_match_p (XCAR (elt), font_entity))
2193 return XFLOAT_DATA (XCDR (elt));
2197 return 1.0;
2200 /* We sort fonts by scoring each of them against a specified
2201 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2202 the value is, the closer the font is to the font-spec.
2204 The lowest 2 bits of the score is used for driver type. The font
2205 available by the most preferred font driver is 0.
2207 Each 7-bit in the higher 28 bits are used for numeric properties
2208 WEIGHT, SLANT, WIDTH, and SIZE. */
2210 /* How many bits to shift to store the difference value of each font
2211 property in a score. Note that flots for FONT_TYPE_INDEX and
2212 FONT_REGISTRY_INDEX are not used. */
2213 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
2215 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2216 The return value indicates how different ENTITY is compared with
2217 SPEC_PROP. */
2219 static unsigned
2220 font_score (entity, spec_prop)
2221 Lisp_Object entity, *spec_prop;
2223 unsigned score = 0;
2224 int i;
2226 /* Score three style numeric fields. Maximum difference is 127. */
2227 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
2228 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
2230 int diff = (XINT (AREF (entity, i)) >> 8) - (XINT (spec_prop[i]) >> 8);
2232 if (diff < 0)
2233 diff = - diff;
2234 if (diff > 0)
2235 score |= min (diff, 127) << sort_shift_bits[i];
2238 /* Score the size. Maximum difference is 127. */
2239 i = FONT_SIZE_INDEX;
2240 if (! NILP (spec_prop[FONT_SIZE_INDEX])
2241 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2243 /* We use the higher 6-bit for the actual size difference. The
2244 lowest bit is set if the DPI is different. */
2245 int diff;
2246 int pixel_size = XINT (spec_prop[FONT_SIZE_INDEX]);
2248 if (CONSP (Vface_font_rescale_alist))
2249 pixel_size *= font_rescale_ratio (entity);
2250 diff = pixel_size - XINT (AREF (entity, FONT_SIZE_INDEX));
2251 if (diff < 0)
2252 diff = - diff;
2253 diff <<= 1;
2254 if (! NILP (spec_prop[FONT_DPI_INDEX])
2255 && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX)))
2256 diff |= 1;
2257 score |= min (diff, 127) << sort_shift_bits[FONT_SIZE_INDEX];
2260 return score;
2264 /* The comparison function for qsort. */
2266 static int
2267 font_compare (d1, d2)
2268 const void *d1, *d2;
2270 return (*(unsigned *) d1 - *(unsigned *) d2);
2274 /* The structure for elements being sorted by qsort. */
2275 struct font_sort_data
2277 unsigned score;
2278 Lisp_Object entity;
2282 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2283 If PREFER specifies a point-size, calculate the corresponding
2284 pixel-size from QCdpi property of PREFER or from the Y-resolution
2285 of FRAME before sorting.
2287 If BEST-ONLY is nonzero, return the best matching entity. Otherwise,
2288 return the sorted VEC. */
2290 static Lisp_Object
2291 font_sort_entites (vec, prefer, frame, best_only)
2292 Lisp_Object vec, prefer, frame;
2293 int best_only;
2295 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2296 int len, i;
2297 struct font_sort_data *data;
2298 unsigned best_score;
2299 Lisp_Object best_entity, driver_type;
2300 int driver_order;
2301 struct frame *f = XFRAME (frame);
2302 struct font_driver_list *list;
2303 USE_SAFE_ALLOCA;
2305 len = ASIZE (vec);
2306 if (len <= 1)
2307 return best_only ? AREF (vec, 0) : vec;
2309 for (i = FONT_WEIGHT_INDEX; i <= FONT_DPI_INDEX; i++)
2310 prefer_prop[i] = AREF (prefer, i);
2311 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2312 prefer_prop[FONT_SIZE_INDEX]
2313 = make_number (font_pixel_size (XFRAME (frame), prefer));
2315 /* Scoring and sorting. */
2316 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
2317 best_score = 0xFFFFFFFF;
2318 /* We are sure that the length of VEC > 1. */
2319 driver_type = AREF (AREF (vec, 0), FONT_TYPE_INDEX);
2320 for (driver_order = 0, list = f->font_driver_list; list;
2321 driver_order++, list = list->next)
2322 if (EQ (driver_type, list->driver->type))
2323 break;
2324 best_entity = data[0].entity = AREF (vec, 0);
2325 best_score = data[0].score
2326 = font_score (data[0].entity, prefer_prop) | driver_order;
2327 for (i = 0; i < len; i++)
2329 if (!EQ (driver_type, AREF (AREF (vec, i), FONT_TYPE_INDEX)))
2330 for (driver_order = 0, list = f->font_driver_list; list;
2331 driver_order++, list = list->next)
2332 if (EQ (driver_type, list->driver->type))
2333 break;
2334 data[i].entity = AREF (vec, i);
2335 data[i].score = font_score (data[i].entity, prefer_prop) | driver_order;
2336 if (best_only && best_score > data[i].score)
2338 best_score = data[i].score;
2339 best_entity = data[i].entity;
2340 if (best_score == 0)
2341 break;
2344 if (! best_only)
2346 qsort (data, len, sizeof *data, font_compare);
2347 for (i = 0; i < len; i++)
2348 ASET (vec, i, data[i].entity);
2350 else
2351 vec = best_entity;
2352 SAFE_FREE ();
2354 font_add_log ("sort-by", prefer, vec);
2355 return vec;
2359 /* API of Font Service Layer. */
2361 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2362 sort_shift_bits. Finternal_set_font_selection_order calls this
2363 function with font_sort_order after setting up it. */
2365 void
2366 font_update_sort_order (order)
2367 int *order;
2369 int i, shift_bits;
2371 for (i = 0, shift_bits = 23; i < 4; i++, shift_bits -= 7)
2373 int xlfd_idx = order[i];
2375 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2376 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2377 else if (xlfd_idx == XLFD_SLANT_INDEX)
2378 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2379 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2380 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2381 else
2382 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2386 static int
2387 font_check_otf_features (script, langsys, features, table)
2388 Lisp_Object script, langsys, features, table;
2390 Lisp_Object val;
2391 int negative;
2393 table = assq_no_quit (script, table);
2394 if (NILP (table))
2395 return 0;
2396 table = XCDR (table);
2397 if (! NILP (langsys))
2399 table = assq_no_quit (langsys, table);
2400 if (NILP (table))
2401 return 0;
2403 else
2405 val = assq_no_quit (Qnil, table);
2406 if (NILP (val))
2407 table = XCAR (table);
2408 else
2409 table = val;
2411 table = XCDR (table);
2412 for (negative = 0; CONSP (features); features = XCDR (features))
2414 if (NILP (XCAR (features)))
2415 negative = 1;
2416 if (NILP (Fmemq (XCAR (features), table)) != negative)
2417 return 0;
2419 return 1;
2422 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2424 static int
2425 font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
2427 Lisp_Object script, langsys = Qnil, gsub = Qnil, gpos = Qnil;
2429 script = XCAR (spec);
2430 spec = XCDR (spec);
2431 if (! NILP (spec))
2433 langsys = XCAR (spec);
2434 spec = XCDR (spec);
2435 if (! NILP (spec))
2437 gsub = XCAR (spec);
2438 spec = XCDR (spec);
2439 if (! NILP (spec))
2440 gpos = XCAR (spec);
2444 if (! NILP (gsub) && ! font_check_otf_features (script, langsys, gsub,
2445 XCAR (otf_capability)))
2446 return 0;
2447 if (! NILP (gpos) && ! font_check_otf_features (script, langsys, gpos,
2448 XCDR (otf_capability)))
2449 return 0;
2450 return 1;
2455 /* Check if FONT (font-entity or font-object) matches with the font
2456 specification SPEC. */
2459 font_match_p (spec, font)
2460 Lisp_Object spec, font;
2462 Lisp_Object prop[FONT_SPEC_MAX], *props;
2463 Lisp_Object extra, font_extra;
2464 int i;
2466 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2467 if (! NILP (AREF (spec, i))
2468 && ! NILP (AREF (font, i))
2469 && ! EQ (AREF (spec, i), AREF (font, i)))
2470 return 0;
2471 props = XFONT_SPEC (spec)->props;
2472 if (FLOATP (props[FONT_SIZE_INDEX]))
2474 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
2475 prop[i] = AREF (spec, i);
2476 prop[FONT_SIZE_INDEX]
2477 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2478 props = prop;
2481 if (font_score (font, props) > 0)
2482 return 0;
2483 extra = AREF (spec, FONT_EXTRA_INDEX);
2484 font_extra = AREF (font, FONT_EXTRA_INDEX);
2485 for (; CONSP (extra); extra = XCDR (extra))
2487 Lisp_Object key = XCAR (XCAR (extra));
2488 Lisp_Object val = XCDR (XCAR (extra)), val2;
2490 if (EQ (key, QClang))
2492 val2 = assq_no_quit (key, font_extra);
2493 if (NILP (val2))
2494 return 0;
2495 val2 = XCDR (val2);
2496 if (CONSP (val))
2498 if (! CONSP (val2))
2499 return 0;
2500 while (CONSP (val))
2501 if (NILP (Fmemq (val, val2)))
2502 return 0;
2504 else
2505 if (CONSP (val2)
2506 ? NILP (Fmemq (val, XCDR (val2)))
2507 : ! EQ (val, val2))
2508 return 0;
2510 else if (EQ (key, QCscript))
2512 val2 = assq_no_quit (val, Vscript_representative_chars);
2513 if (CONSP (val2))
2515 val2 = XCDR (val2);
2516 if (CONSP (val2))
2518 /* All characters in the list must be supported. */
2519 for (; CONSP (val2); val2 = XCDR (val2))
2521 if (! NATNUMP (XCAR (val2)))
2522 continue;
2523 if (font_encode_char (font, XFASTINT (XCAR (val2)))
2524 == FONT_INVALID_CODE)
2525 return 0;
2528 else if (VECTORP (val2))
2530 /* At most one character in the vector must be supported. */
2531 for (i = 0; i < ASIZE (val2); i++)
2533 if (! NATNUMP (AREF (val2, i)))
2534 continue;
2535 if (font_encode_char (font, XFASTINT (AREF (val2, i)))
2536 != FONT_INVALID_CODE)
2537 break;
2539 if (i == ASIZE (val2))
2540 return 0;
2544 else if (EQ (key, QCotf))
2546 struct font *fontp;
2548 if (! FONT_OBJECT_P (font))
2549 return 0;
2550 fontp = XFONT_OBJECT (font);
2551 if (! fontp->driver->otf_capability)
2552 return 0;
2553 val2 = fontp->driver->otf_capability (fontp);
2554 if (NILP (val2) || ! font_check_otf (val, val2))
2555 return 0;
2559 return 1;
2563 /* Font cache
2565 Each font backend has the callback function get_cache, and it
2566 returns a cons cell of which cdr part can be freely used for
2567 caching fonts. The cons cell may be shared by multiple frames
2568 and/or multiple font drivers. So, we arrange the cdr part as this:
2570 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2572 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2573 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2574 cons (FONT-SPEC FONT-ENTITY ...). */
2576 static void font_prepare_cache P_ ((FRAME_PTR, struct font_driver *));
2577 static void font_finish_cache P_ ((FRAME_PTR, struct font_driver *));
2578 static Lisp_Object font_get_cache P_ ((FRAME_PTR, struct font_driver *));
2579 static void font_clear_cache P_ ((FRAME_PTR, Lisp_Object,
2580 struct font_driver *));
2582 static void
2583 font_prepare_cache (f, driver)
2584 FRAME_PTR f;
2585 struct font_driver *driver;
2587 Lisp_Object cache, val;
2589 cache = driver->get_cache (f);
2590 val = XCDR (cache);
2591 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2592 val = XCDR (val);
2593 if (NILP (val))
2595 val = Fcons (driver->type, Fcons (make_number (1), Qnil));
2596 XSETCDR (cache, Fcons (val, XCDR (cache)));
2598 else
2600 val = XCDR (XCAR (val));
2601 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2606 static void
2607 font_finish_cache (f, driver)
2608 FRAME_PTR f;
2609 struct font_driver *driver;
2611 Lisp_Object cache, val, tmp;
2614 cache = driver->get_cache (f);
2615 val = XCDR (cache);
2616 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2617 cache = val, val = XCDR (val);
2618 font_assert (! NILP (val));
2619 tmp = XCDR (XCAR (val));
2620 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2621 if (XINT (XCAR (tmp)) == 0)
2623 font_clear_cache (f, XCAR (val), driver);
2624 XSETCDR (cache, XCDR (val));
2629 static Lisp_Object
2630 font_get_cache (f, driver)
2631 FRAME_PTR f;
2632 struct font_driver *driver;
2634 Lisp_Object val = driver->get_cache (f);
2635 Lisp_Object type = driver->type;
2637 font_assert (CONSP (val));
2638 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2639 font_assert (CONSP (val));
2640 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2641 val = XCDR (XCAR (val));
2642 return val;
2645 static int num_fonts;
2647 static void
2648 font_clear_cache (f, cache, driver)
2649 FRAME_PTR f;
2650 Lisp_Object cache;
2651 struct font_driver *driver;
2653 Lisp_Object tail, elt;
2654 Lisp_Object tail2, entity;
2656 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2657 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2659 elt = XCAR (tail);
2660 /* elt should have the form (FONT-SPEC FONT-ENTITY ...) */
2661 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2663 for (tail2 = XCDR (elt); CONSP (tail2); tail2 = XCDR (tail2))
2665 entity = XCAR (tail2);
2667 if (FONT_ENTITY_P (entity)
2668 && EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2670 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2672 for (; CONSP (objlist); objlist = XCDR (objlist))
2674 Lisp_Object val = XCAR (objlist);
2675 struct font *font = XFONT_OBJECT (val);
2677 if (! NILP (AREF (val, FONT_TYPE_INDEX)))
2679 font_assert (font && driver == font->driver);
2680 driver->close (f, font);
2681 num_fonts--;
2684 if (driver->free_entity)
2685 driver->free_entity (entity);
2690 XSETCDR (cache, Qnil);
2694 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2696 Lisp_Object
2697 font_delete_unmatched (list, spec, size)
2698 Lisp_Object list, spec;
2699 int size;
2701 Lisp_Object entity, val;
2702 enum font_property_index prop;
2704 for (val = Qnil; CONSP (list); list = XCDR (list))
2706 entity = XCAR (list);
2707 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++)
2708 if (INTEGERP (AREF (spec, prop))
2709 && ((XINT (AREF (spec, prop)) >> 8)
2710 != (XINT (AREF (entity, prop)) >> 8)))
2711 prop = FONT_SPEC_MAX;
2712 if (prop < FONT_SPEC_MAX
2713 && size
2714 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2716 int diff = XINT (AREF (entity, FONT_SIZE_INDEX)) - size;
2718 if (diff != 0
2719 && (diff < 0 ? -diff > FONT_PIXEL_SIZE_QUANTUM
2720 : diff > FONT_PIXEL_SIZE_QUANTUM))
2721 prop = FONT_SPEC_MAX;
2723 if (prop < FONT_SPEC_MAX
2724 && INTEGERP (AREF (spec, FONT_DPI_INDEX))
2725 && INTEGERP (AREF (entity, FONT_DPI_INDEX))
2726 && XINT (AREF (entity, FONT_DPI_INDEX)) != 0
2727 && ! EQ (AREF (spec, FONT_DPI_INDEX), AREF (entity, FONT_DPI_INDEX)))
2728 prop = FONT_SPEC_MAX;
2729 if (prop < FONT_SPEC_MAX
2730 && INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
2731 && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
2732 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) != 0
2733 && ! EQ (AREF (spec, FONT_AVGWIDTH_INDEX),
2734 AREF (entity, FONT_AVGWIDTH_INDEX)))
2735 prop = FONT_SPEC_MAX;
2736 if (prop < FONT_SPEC_MAX)
2737 val = Fcons (entity, val);
2739 return val;
2743 /* Return a vector of font-entities matching with SPEC on FRAME. */
2745 Lisp_Object
2746 font_list_entities (frame, spec)
2747 Lisp_Object frame, spec;
2749 FRAME_PTR f = XFRAME (frame);
2750 struct font_driver_list *driver_list = f->font_driver_list;
2751 Lisp_Object ftype, val;
2752 Lisp_Object *vec;
2753 int size;
2754 int need_filtering = 0;
2755 int i;
2757 font_assert (FONT_SPEC_P (spec));
2759 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2760 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2761 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2762 size = font_pixel_size (f, spec);
2763 else
2764 size = 0;
2766 ftype = AREF (spec, FONT_TYPE_INDEX);
2767 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2768 ASET (scratch_font_spec, i, AREF (spec, i));
2769 for (i = FONT_WEIGHT_INDEX; i < FONT_EXTRA_INDEX; i++)
2771 ASET (scratch_font_spec, i, Qnil);
2772 if (! NILP (AREF (spec, i)))
2773 need_filtering = 1;
2774 if (i == FONT_DPI_INDEX)
2775 /* Skip FONT_SPACING_INDEX */
2776 i++;
2778 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX));
2779 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
2781 vec = alloca (sizeof (Lisp_Object) * num_font_drivers);
2782 if (! vec)
2783 return null_vector;
2785 for (i = 0; driver_list; driver_list = driver_list->next)
2786 if (driver_list->on
2787 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2789 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2791 ASET (scratch_font_spec, FONT_TYPE_INDEX, driver_list->driver->type);
2792 val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2793 if (CONSP (val))
2794 val = XCDR (val);
2795 else
2797 Lisp_Object copy;
2799 val = driver_list->driver->list (frame, scratch_font_spec);
2800 copy = Fcopy_font_spec (scratch_font_spec);
2801 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2802 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2804 if (! NILP (val) && need_filtering)
2805 val = font_delete_unmatched (val, spec, size);
2806 if (! NILP (val))
2807 vec[i++] = val;
2810 val = (i > 0 ? Fvconcat (i, vec) : null_vector);
2811 font_add_log ("list", spec, val);
2812 return (val);
2816 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2817 nil, is an array of face's attributes, which specifies preferred
2818 font-related attributes. */
2820 static Lisp_Object
2821 font_matching_entity (f, attrs, spec)
2822 FRAME_PTR f;
2823 Lisp_Object *attrs, spec;
2825 struct font_driver_list *driver_list = f->font_driver_list;
2826 Lisp_Object ftype, size, entity;
2827 Lisp_Object frame;
2828 Lisp_Object work = Fcopy_font_spec (spec);
2830 XSETFRAME (frame, f);
2831 ftype = AREF (spec, FONT_TYPE_INDEX);
2832 size = AREF (spec, FONT_SIZE_INDEX);
2834 if (FLOATP (size))
2835 ASET (work, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2836 FONT_SET_STYLE (work, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
2837 FONT_SET_STYLE (work, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
2838 FONT_SET_STYLE (work, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
2840 entity = Qnil;
2841 for (; driver_list; driver_list = driver_list->next)
2842 if (driver_list->on
2843 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2845 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2846 Lisp_Object copy;
2848 ASET (work, FONT_TYPE_INDEX, driver_list->driver->type);
2849 entity = assoc_no_quit (work, XCDR (cache));
2850 if (CONSP (entity))
2851 entity = XCDR (entity);
2852 else
2854 entity = driver_list->driver->match (frame, work);
2855 copy = Fcopy_font_spec (work);
2856 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2857 XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache)));
2859 if (! NILP (entity))
2860 break;
2862 font_add_log ("match", work, entity);
2863 return entity;
2867 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2868 opened font object. */
2870 static Lisp_Object
2871 font_open_entity (f, entity, pixel_size)
2872 FRAME_PTR f;
2873 Lisp_Object entity;
2874 int pixel_size;
2876 struct font_driver_list *driver_list;
2877 Lisp_Object objlist, size, val, font_object;
2878 struct font *font;
2879 int min_width, height;
2880 int scaled_pixel_size;
2882 font_assert (FONT_ENTITY_P (entity));
2883 size = AREF (entity, FONT_SIZE_INDEX);
2884 if (XINT (size) != 0)
2885 scaled_pixel_size = pixel_size = XINT (size);
2886 else if (CONSP (Vface_font_rescale_alist))
2887 scaled_pixel_size = pixel_size * font_rescale_ratio (entity);
2889 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2890 objlist = XCDR (objlist))
2891 if (! NILP (AREF (XCAR (objlist), FONT_TYPE_INDEX))
2892 && XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size)
2893 return XCAR (objlist);
2895 val = AREF (entity, FONT_TYPE_INDEX);
2896 for (driver_list = f->font_driver_list;
2897 driver_list && ! EQ (driver_list->driver->type, val);
2898 driver_list = driver_list->next);
2899 if (! driver_list)
2900 return Qnil;
2902 font_object = driver_list->driver->open (f, entity, scaled_pixel_size);
2903 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
2904 font_add_log ("open", entity, font_object);
2905 if (NILP (font_object))
2906 return Qnil;
2907 ASET (entity, FONT_OBJLIST_INDEX,
2908 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2909 ASET (font_object, FONT_OBJLIST_INDEX, Qnil);
2910 num_fonts++;
2912 font = XFONT_OBJECT (font_object);
2913 min_width = (font->min_width ? font->min_width
2914 : font->average_width ? font->average_width
2915 : font->space_width ? font->space_width
2916 : 1);
2917 height = (font->height ? font->height : 1);
2918 #ifdef HAVE_WINDOW_SYSTEM
2919 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
2920 if (FRAME_X_DISPLAY_INFO (f)->n_fonts == 1)
2922 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
2923 FRAME_SMALLEST_FONT_HEIGHT (f) = height;
2924 fonts_changed_p = 1;
2926 else
2928 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
2929 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
2930 if (FRAME_SMALLEST_FONT_HEIGHT (f) > height)
2931 FRAME_SMALLEST_FONT_HEIGHT (f) = height, fonts_changed_p = 1;
2933 #endif
2935 return font_object;
2939 /* Close FONT_OBJECT that is opened on frame F. */
2941 void
2942 font_close_object (f, font_object)
2943 FRAME_PTR f;
2944 Lisp_Object font_object;
2946 struct font *font = XFONT_OBJECT (font_object);
2948 if (NILP (AREF (font_object, FONT_TYPE_INDEX)))
2949 /* Already closed. */
2950 return;
2951 font_add_log ("close", font_object, Qnil);
2952 font->driver->close (f, font);
2953 #ifdef HAVE_WINDOW_SYSTEM
2954 font_assert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
2955 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
2956 #endif
2957 num_fonts--;
2961 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2962 FONT is a font-entity and it must be opened to check. */
2965 font_has_char (f, font, c)
2966 FRAME_PTR f;
2967 Lisp_Object font;
2968 int c;
2970 struct font *fontp;
2972 if (FONT_ENTITY_P (font))
2974 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
2975 struct font_driver_list *driver_list;
2977 for (driver_list = f->font_driver_list;
2978 driver_list && ! EQ (driver_list->driver->type, type);
2979 driver_list = driver_list->next);
2980 if (! driver_list)
2981 return 0;
2982 if (! driver_list->driver->has_char)
2983 return -1;
2984 return driver_list->driver->has_char (font, c);
2987 font_assert (FONT_OBJECT_P (font));
2988 fontp = XFONT_OBJECT (font);
2989 if (fontp->driver->has_char)
2991 int result = fontp->driver->has_char (font, c);
2993 if (result >= 0)
2994 return result;
2996 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
3000 /* Return the glyph ID of FONT_OBJECT for character C. */
3002 unsigned
3003 font_encode_char (font_object, c)
3004 Lisp_Object font_object;
3005 int c;
3007 struct font *font;
3009 font_assert (FONT_OBJECT_P (font_object));
3010 font = XFONT_OBJECT (font_object);
3011 return font->driver->encode_char (font, c);
3015 /* Return the name of FONT_OBJECT. */
3017 Lisp_Object
3018 font_get_name (font_object)
3019 Lisp_Object font_object;
3021 font_assert (FONT_OBJECT_P (font_object));
3022 return AREF (font_object, FONT_NAME_INDEX);
3026 /* Return the specification of FONT_OBJECT. */
3028 Lisp_Object
3029 font_get_spec (font_object)
3030 Lisp_Object font_object;
3032 Lisp_Object spec = font_make_spec ();
3033 int i;
3035 for (i = 0; i < FONT_SIZE_INDEX; i++)
3036 ASET (spec, i, AREF (font_object, i));
3037 ASET (spec, FONT_SIZE_INDEX,
3038 make_number (XFONT_OBJECT (font_object)->pixel_size));
3039 return spec;
3042 Lisp_Object
3043 font_spec_from_name (font_name)
3044 Lisp_Object font_name;
3046 Lisp_Object args[2];
3048 args[0] = QCname;
3049 args[1] = font_name;
3050 return Ffont_spec (2, args);
3054 void
3055 font_clear_prop (attrs, prop)
3056 Lisp_Object *attrs;
3057 enum font_property_index prop;
3059 Lisp_Object font = attrs[LFACE_FONT_INDEX];
3061 if (! FONTP (font))
3062 return;
3063 if (NILP (AREF (font, prop))
3064 && prop != FONT_FAMILY_INDEX
3065 && prop != FONT_FOUNDRY_INDEX
3066 && prop != FONT_WIDTH_INDEX
3067 && prop != FONT_SIZE_INDEX)
3068 return;
3069 font = Fcopy_font_spec (font);
3070 ASET (font, prop, Qnil);
3071 if (prop == FONT_FAMILY_INDEX || prop == FONT_FOUNDRY_INDEX)
3073 if (prop == FONT_FAMILY_INDEX)
3074 ASET (font, FONT_FOUNDRY_INDEX, Qnil);
3075 ASET (font, FONT_ADSTYLE_INDEX, Qnil);
3076 ASET (font, FONT_REGISTRY_INDEX, Qnil);
3077 ASET (font, FONT_SIZE_INDEX, Qnil);
3078 ASET (font, FONT_DPI_INDEX, Qnil);
3079 ASET (font, FONT_SPACING_INDEX, Qnil);
3080 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3082 else if (prop == FONT_SIZE_INDEX)
3084 ASET (font, FONT_DPI_INDEX, Qnil);
3085 ASET (font, FONT_SPACING_INDEX, Qnil);
3086 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3088 else if (prop == FONT_WIDTH_INDEX)
3089 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3090 attrs[LFACE_FONT_INDEX] = font;
3093 void
3094 font_update_lface (f, attrs)
3095 FRAME_PTR f;
3096 Lisp_Object *attrs;
3098 Lisp_Object spec;
3100 spec = attrs[LFACE_FONT_INDEX];
3101 if (! FONT_SPEC_P (spec))
3102 return;
3104 if (! NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
3105 attrs[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX));
3106 if (! NILP (AREF (spec, FONT_FAMILY_INDEX)))
3107 attrs[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FAMILY_INDEX));
3108 if (! NILP (AREF (spec, FONT_WEIGHT_INDEX)))
3109 attrs[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (spec);
3110 if (! NILP (AREF (spec, FONT_SLANT_INDEX)))
3111 attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);;
3112 if (! NILP (AREF (spec, FONT_WIDTH_INDEX)))
3113 attrs[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (spec);
3114 if (! NILP (AREF (spec, FONT_SIZE_INDEX)))
3116 int point;
3118 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
3120 Lisp_Object val;
3121 int dpi = f->resy;
3123 val = Ffont_get (spec, QCdpi);
3124 if (! NILP (val))
3125 dpi = XINT (val);
3126 point = PIXEL_TO_POINT (XINT (AREF (spec, FONT_SIZE_INDEX)) * 10,
3127 dpi);
3128 attrs[LFACE_HEIGHT_INDEX] = make_number (point);
3130 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
3132 point = XFLOAT_DATA (AREF (spec, FONT_SIZE_INDEX)) * 10;
3133 attrs[LFACE_HEIGHT_INDEX] = make_number (point);
3139 /* Return a font-entity satisfying SPEC and best matching with face's
3140 font related attributes in ATTRS. C, if not negative, is a
3141 character that the entity must support. */
3143 Lisp_Object
3144 font_find_for_lface (f, attrs, spec, c)
3145 FRAME_PTR f;
3146 Lisp_Object *attrs;
3147 Lisp_Object spec;
3148 int c;
3150 Lisp_Object work;
3151 Lisp_Object frame, entities, val, props[FONT_REGISTRY_INDEX + 1] ;
3152 Lisp_Object size, foundry[3], *family, registry[3], adstyle[3];
3153 int pixel_size;
3154 int i, j, k, l, result;
3156 registry[0] = AREF (spec, FONT_REGISTRY_INDEX);
3157 if (NILP (registry[0]))
3159 registry[0] = DEFAULT_ENCODING;
3160 registry[1] = Qascii_0;
3161 registry[2] = null_vector;
3163 else
3164 registry[1] = null_vector;
3166 if (c >= 0 && ! NILP (AREF (spec, FONT_REGISTRY_INDEX)))
3168 struct charset *encoding, *repertory;
3170 if (font_registry_charsets (AREF (spec, FONT_REGISTRY_INDEX),
3171 &encoding, &repertory) < 0)
3172 return Qnil;
3173 if (repertory)
3175 if (ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
3176 return Qnil;
3177 /* Any font of this registry support C. So, let's
3178 suppress the further checking. */
3179 c = -1;
3181 else if (c > encoding->max_char)
3182 return Qnil;
3185 work = Fcopy_font_spec (spec);
3186 XSETFRAME (frame, f);
3187 size = AREF (spec, FONT_SIZE_INDEX);
3188 pixel_size = font_pixel_size (f, spec);
3189 if (pixel_size == 0)
3191 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3193 pixel_size = POINT_TO_PIXEL (pt / 10, f->resy);
3195 ASET (work, FONT_SIZE_INDEX, Qnil);
3196 foundry[0] = AREF (work, FONT_FOUNDRY_INDEX);
3197 if (! NILP (foundry[0]))
3198 foundry[1] = null_vector;
3199 else if (STRINGP (attrs[LFACE_FOUNDRY_INDEX]))
3201 val = attrs[LFACE_FOUNDRY_INDEX];
3202 foundry[0] = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
3203 foundry[1] = Qnil;
3204 foundry[2] = null_vector;
3206 else
3207 foundry[0] = Qnil, foundry[1] = null_vector;
3209 adstyle[0] = AREF (work, FONT_ADSTYLE_INDEX);
3210 if (! NILP (adstyle[0]))
3211 adstyle[1] = null_vector;
3212 else if (FONTP (attrs[LFACE_FONT_INDEX]))
3214 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3216 if (! NILP (AREF (face_font, FONT_ADSTYLE_INDEX)))
3218 adstyle[0] = AREF (face_font, FONT_ADSTYLE_INDEX);
3219 adstyle[1] = Qnil;
3220 adstyle[2] = null_vector;
3222 else
3223 adstyle[0] = Qnil, adstyle[1] = null_vector;
3225 else
3226 adstyle[0] = Qnil, adstyle[1] = null_vector;
3229 val = AREF (work, FONT_FAMILY_INDEX);
3230 if (NILP (val) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
3232 val = attrs[LFACE_FAMILY_INDEX];
3233 val = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
3235 if (NILP (val))
3237 family = alloca ((sizeof family[0]) * 2);
3238 family[0] = Qnil;
3239 family[1] = null_vector; /* terminator. */
3241 else
3243 Lisp_Object alters
3244 = Fassoc_string (val, Vface_alternative_font_family_alist,
3245 #ifndef HAVE_NS
3247 #else
3248 Qnil
3249 #endif
3252 if (! NILP (alters))
3254 family = alloca ((sizeof family[0]) * (XINT (Flength (alters)) + 2));
3255 for (i = 0; CONSP (alters); i++, alters = XCDR (alters))
3256 family[i] = XCAR (alters);
3257 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3258 family[i++] = Qnil;
3259 family[i] = null_vector;
3261 else
3263 family = alloca ((sizeof family[0]) * 3);
3264 i = 0;
3265 family[i++] = val;
3266 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3267 family[i++] = Qnil;
3268 family[i] = null_vector;
3272 for (i = 0; SYMBOLP (family[i]); i++)
3274 ASET (work, FONT_FAMILY_INDEX, family[i]);
3275 for (j = 0; SYMBOLP (foundry[j]); j++)
3277 ASET (work, FONT_FOUNDRY_INDEX, foundry[j]);
3278 for (k = 0; SYMBOLP (registry[k]); k++)
3280 ASET (work, FONT_REGISTRY_INDEX, registry[k]);
3281 for (l = 0; SYMBOLP (adstyle[l]); l++)
3283 ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
3284 entities = font_list_entities (frame, work);
3285 if (ASIZE (entities) > 0)
3286 goto found;
3291 return Qnil;
3292 found:
3293 if (ASIZE (entities) == 1)
3295 if (c < 0)
3296 return AREF (entities, 0);
3298 else
3300 /* Sort fonts by properties specified in LFACE. */
3301 Lisp_Object prefer = scratch_font_prefer;
3303 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3304 ASET (prefer, i, AREF (work, i));
3305 if (FONTP (attrs[LFACE_FONT_INDEX]))
3307 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3309 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3310 if (NILP (AREF (prefer, i)))
3311 ASET (prefer, i, AREF (face_font, i));
3313 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
3314 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
3315 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
3316 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
3317 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
3318 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
3319 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
3320 entities = font_sort_entites (entities, prefer, frame, c < 0);
3322 if (c < 0)
3323 return entities;
3325 for (i = 0; i < ASIZE (entities); i++)
3327 int j;
3329 val = AREF (entities, i);
3330 if (i > 0)
3332 for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
3333 if (! EQ (AREF (val, j), props[j]))
3334 break;
3335 if (j > FONT_REGISTRY_INDEX)
3336 continue;
3338 for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
3339 props[j] = AREF (val, j);
3340 result = font_has_char (f, val, c);
3341 if (result > 0)
3342 return val;
3343 if (result == 0)
3344 return Qnil;
3345 val = font_open_for_lface (f, val, attrs, spec);
3346 if (NILP (val))
3347 continue;
3348 result = font_has_char (f, val, c);
3349 font_close_object (f, val);
3350 if (result > 0)
3351 return AREF (entities, i);
3353 return Qnil;
3357 Lisp_Object
3358 font_open_for_lface (f, entity, attrs, spec)
3359 FRAME_PTR f;
3360 Lisp_Object entity;
3361 Lisp_Object *attrs;
3362 Lisp_Object spec;
3364 int size;
3366 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX))
3367 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
3368 size = XINT (AREF (entity, FONT_SIZE_INDEX));
3369 else if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
3370 size = font_pixel_size (f, spec);
3371 else
3373 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3375 pt /= 10;
3376 size = POINT_TO_PIXEL (pt, f->resy);
3377 #ifdef HAVE_NS
3378 if (size == 0)
3380 Lisp_Object ffsize = get_frame_param(f, Qfontsize);
3381 size = NUMBERP (ffsize) ? POINT_TO_PIXEL (XINT (ffsize), f->resy) : 0;
3383 #endif
3385 return font_open_entity (f, entity, size);
3389 /* Find a font satisfying SPEC and best matching with face's
3390 attributes in ATTRS on FRAME, and return the opened
3391 font-object. */
3393 Lisp_Object
3394 font_load_for_lface (f, attrs, spec)
3395 FRAME_PTR f;
3396 Lisp_Object *attrs, spec;
3398 Lisp_Object entity;
3400 entity = font_find_for_lface (f, attrs, spec, -1);
3401 if (NILP (entity))
3403 /* No font is listed for SPEC, but each font-backend may have
3404 the different criteria about "font matching". So, try
3405 it. */
3406 entity = font_matching_entity (f, attrs, spec);
3407 if (NILP (entity))
3408 return Qnil;
3410 return font_open_for_lface (f, entity, attrs, spec);
3414 /* Make FACE on frame F ready to use the font opened for FACE. */
3416 void
3417 font_prepare_for_face (f, face)
3418 FRAME_PTR f;
3419 struct face *face;
3421 if (face->font->driver->prepare_face)
3422 face->font->driver->prepare_face (f, face);
3426 /* Make FACE on frame F stop using the font opened for FACE. */
3428 void
3429 font_done_for_face (f, face)
3430 FRAME_PTR f;
3431 struct face *face;
3433 if (face->font->driver->done_face)
3434 face->font->driver->done_face (f, face);
3435 face->extra = NULL;
3439 /* Open a font best matching with NAME on frame F. If no proper font
3440 is found, return Qnil. */
3442 Lisp_Object
3443 font_open_by_name (f, name)
3444 FRAME_PTR f;
3445 char *name;
3447 Lisp_Object args[2];
3448 Lisp_Object spec, attrs[LFACE_VECTOR_SIZE];
3450 args[0] = QCname;
3451 args[1] = make_unibyte_string (name, strlen (name));
3452 spec = Ffont_spec (2, args);
3453 /* We set up the default font-related attributes of a face to prefer
3454 a moderate font. */
3455 attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
3456 attrs[LFACE_SWIDTH_INDEX] = attrs[LFACE_WEIGHT_INDEX]
3457 = attrs[LFACE_SLANT_INDEX] = Qnormal;
3458 #ifndef HAVE_NS
3459 attrs[LFACE_HEIGHT_INDEX] = make_number (120);
3460 #else
3461 attrs[LFACE_HEIGHT_INDEX] = make_number (0);
3462 #endif
3463 attrs[LFACE_FONT_INDEX] = Qnil;
3465 return font_load_for_lface (f, attrs, spec);
3469 /* Register font-driver DRIVER. This function is used in two ways.
3471 The first is with frame F non-NULL. In this case, make DRIVER
3472 available (but not yet activated) on F. All frame creaters
3473 (e.g. Fx_create_frame) must call this function at least once with
3474 an available font-driver.
3476 The second is with frame F NULL. In this case, DRIVER is globally
3477 registered in the variable `font_driver_list'. All font-driver
3478 implementations must call this function in its syms_of_XXXX
3479 (e.g. syms_of_xfont). */
3481 void
3482 register_font_driver (driver, f)
3483 struct font_driver *driver;
3484 FRAME_PTR f;
3486 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
3487 struct font_driver_list *prev, *list;
3489 if (f && ! driver->draw)
3490 error ("Unusable font driver for a frame: %s",
3491 SDATA (SYMBOL_NAME (driver->type)));
3493 for (prev = NULL, list = root; list; prev = list, list = list->next)
3494 if (EQ (list->driver->type, driver->type))
3495 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3497 list = xmalloc (sizeof (struct font_driver_list));
3498 list->on = 0;
3499 list->driver = driver;
3500 list->next = NULL;
3501 if (prev)
3502 prev->next = list;
3503 else if (f)
3504 f->font_driver_list = list;
3505 else
3506 font_driver_list = list;
3507 if (! f)
3508 num_font_drivers++;
3511 void
3512 free_font_driver_list (f)
3513 FRAME_PTR f;
3515 struct font_driver_list *list, *next;
3517 for (list = f->font_driver_list; list; list = next)
3519 next = list->next;
3520 xfree (list);
3522 f->font_driver_list = NULL;
3526 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3527 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3528 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3530 A caller must free all realized faces if any in advance. The
3531 return value is a list of font backends actually made used on
3532 F. */
3534 Lisp_Object
3535 font_update_drivers (f, new_drivers)
3536 FRAME_PTR f;
3537 Lisp_Object new_drivers;
3539 Lisp_Object active_drivers = Qnil;
3540 struct font_driver *driver;
3541 struct font_driver_list *list;
3543 /* At first, turn off non-requested drivers, and turn on requested
3544 drivers. */
3545 for (list = f->font_driver_list; list; list = list->next)
3547 driver = list->driver;
3548 if ((EQ (new_drivers, Qt) || ! NILP (Fmemq (driver->type, new_drivers)))
3549 != list->on)
3551 if (list->on)
3553 if (driver->end_for_frame)
3554 driver->end_for_frame (f);
3555 font_finish_cache (f, driver);
3556 list->on = 0;
3558 else
3560 if (! driver->start_for_frame
3561 || driver->start_for_frame (f) == 0)
3563 font_prepare_cache (f, driver);
3564 list->on = 1;
3570 if (NILP (new_drivers))
3571 return Qnil;
3573 if (! EQ (new_drivers, Qt))
3575 /* Re-order the driver list according to new_drivers. */
3576 struct font_driver_list **list_table, **next;
3577 Lisp_Object tail;
3578 int i;
3580 list_table = alloca (sizeof list_table[0] * (num_font_drivers + 1));
3581 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
3583 for (list = f->font_driver_list; list; list = list->next)
3584 if (list->on && EQ (list->driver->type, XCAR (tail)))
3585 break;
3586 if (list)
3587 list_table[i++] = list;
3589 for (list = f->font_driver_list; list; list = list->next)
3590 if (! list->on)
3591 list_table[i++] = list;
3592 list_table[i] = NULL;
3594 next = &f->font_driver_list;
3595 for (i = 0; list_table[i]; i++)
3597 *next = list_table[i];
3598 next = &(*next)->next;
3600 *next = NULL;
3603 for (list = f->font_driver_list; list; list = list->next)
3604 if (list->on)
3605 active_drivers = nconc2 (active_drivers,
3606 Fcons (list->driver->type, Qnil));
3607 return active_drivers;
3611 font_put_frame_data (f, driver, data)
3612 FRAME_PTR f;
3613 struct font_driver *driver;
3614 void *data;
3616 struct font_data_list *list, *prev;
3618 for (prev = NULL, list = f->font_data_list; list;
3619 prev = list, list = list->next)
3620 if (list->driver == driver)
3621 break;
3622 if (! data)
3624 if (list)
3626 if (prev)
3627 prev->next = list->next;
3628 else
3629 f->font_data_list = list->next;
3630 free (list);
3632 return 0;
3635 if (! list)
3637 list = xmalloc (sizeof (struct font_data_list));
3638 list->driver = driver;
3639 list->next = f->font_data_list;
3640 f->font_data_list = list;
3642 list->data = data;
3643 return 0;
3647 void *
3648 font_get_frame_data (f, driver)
3649 FRAME_PTR f;
3650 struct font_driver *driver;
3652 struct font_data_list *list;
3654 for (list = f->font_data_list; list; list = list->next)
3655 if (list->driver == driver)
3656 break;
3657 if (! list)
3658 return NULL;
3659 return list->data;
3663 /* Return the font used to draw character C by FACE at buffer position
3664 POS in window W. If STRING is non-nil, it is a string containing C
3665 at index POS. If C is negative, get C from the current buffer or
3666 STRING. */
3668 Lisp_Object
3669 font_at (c, pos, face, w, string)
3670 int c;
3671 EMACS_INT pos;
3672 struct face *face;
3673 struct window *w;
3674 Lisp_Object string;
3676 FRAME_PTR f;
3677 int multibyte;
3678 Lisp_Object font_object;
3680 multibyte = (NILP (string)
3681 ? ! NILP (current_buffer->enable_multibyte_characters)
3682 : STRING_MULTIBYTE (string));
3683 if (c < 0)
3685 if (NILP (string))
3687 if (multibyte)
3689 EMACS_INT pos_byte = CHAR_TO_BYTE (pos);
3691 c = FETCH_CHAR (pos_byte);
3693 else
3694 c = FETCH_BYTE (pos);
3696 else
3698 unsigned char *str;
3700 multibyte = STRING_MULTIBYTE (string);
3701 if (multibyte)
3703 EMACS_INT pos_byte = string_char_to_byte (string, pos);
3705 str = SDATA (string) + pos_byte;
3706 c = STRING_CHAR (str, 0);
3708 else
3709 c = SDATA (string)[pos];
3713 f = XFRAME (w->frame);
3714 if (! FRAME_WINDOW_P (f))
3715 return Qnil;
3716 if (! face)
3718 int face_id;
3719 EMACS_INT endptr;
3721 if (STRINGP (string))
3722 face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
3723 DEFAULT_FACE_ID, 0);
3724 else
3725 face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
3726 pos + 100, 0);
3727 face = FACE_FROM_ID (f, face_id);
3729 if (multibyte)
3731 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3732 face = FACE_FROM_ID (f, face_id);
3734 if (! face->font)
3735 return Qnil;
3737 XSETFONT (font_object, face->font);
3738 return font_object;
3742 #ifdef HAVE_WINDOW_SYSTEM
3744 /* Check how many characters after POS (at most to *LIMIT) can be
3745 displayed by the same font on the window W. FACE, if non-NULL, is
3746 the face selected for the character at POS. If STRING is not nil,
3747 it is the string to check instead of the current buffer. In that
3748 case, FACE must be not NULL.
3750 The return value is the font-object for the character at POS.
3751 *LIMIT is set to the position where that font can't be used.
3753 It is assured that the current buffer (or STRING) is multibyte. */
3755 Lisp_Object
3756 font_range (pos, limit, w, face, string)
3757 EMACS_INT pos, *limit;
3758 struct window *w;
3759 struct face *face;
3760 Lisp_Object string;
3762 EMACS_INT pos_byte, ignore, start, start_byte;
3763 int c;
3764 Lisp_Object font_object = Qnil;
3766 if (NILP (string))
3768 pos_byte = CHAR_TO_BYTE (pos);
3769 if (! face)
3771 int face_id;
3773 face_id = face_at_buffer_position (w, pos, 0, 0, &ignore, *limit, 0);
3774 face = FACE_FROM_ID (XFRAME (w->frame), face_id);
3777 else
3779 font_assert (face);
3780 pos_byte = string_char_to_byte (string, pos);
3783 start = pos, start_byte = pos_byte;
3784 while (pos < *limit)
3786 Lisp_Object category;
3788 if (NILP (string))
3789 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3790 else
3791 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3792 if (NILP (font_object))
3794 font_object = font_for_char (face, c, pos - 1, string);
3795 if (NILP (font_object))
3796 return Qnil;
3797 continue;
3800 category = CHAR_TABLE_REF (Vunicode_category_table, c);
3801 if (! EQ (category, QCf)
3802 && font_encode_char (font_object, c) == FONT_INVALID_CODE)
3804 Lisp_Object f = font_for_char (face, c, pos - 1, string);
3805 EMACS_INT i, i_byte;
3808 if (NILP (f))
3810 *limit = pos - 1;
3811 return font_object;
3813 i = start, i_byte = start_byte;
3814 while (i < pos - 1)
3817 if (NILP (string))
3818 FETCH_CHAR_ADVANCE_NO_CHECK (c, i, i_byte);
3819 else
3820 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, i, i_byte);
3821 category = CHAR_TABLE_REF (Vunicode_category_table, c);
3822 if (! EQ (category, QCf)
3823 && font_encode_char (f, c) == FONT_INVALID_CODE)
3825 *limit = pos - 1;
3826 return font_object;
3829 font_object = f;
3832 return font_object;
3834 #endif
3837 /* Lisp API */
3839 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3840 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3841 Return nil otherwise.
3842 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3843 which kind of font it is. It must be one of `font-spec', `font-entity',
3844 `font-object'. */)
3845 (object, extra_type)
3846 Lisp_Object object, extra_type;
3848 if (NILP (extra_type))
3849 return (FONTP (object) ? Qt : Qnil);
3850 if (EQ (extra_type, Qfont_spec))
3851 return (FONT_SPEC_P (object) ? Qt : Qnil);
3852 if (EQ (extra_type, Qfont_entity))
3853 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3854 if (EQ (extra_type, Qfont_object))
3855 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3856 wrong_type_argument (intern ("font-extra-type"), extra_type);
3859 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3860 doc: /* Return a newly created font-spec with arguments as properties.
3862 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3863 valid font property name listed below:
3865 `:family', `:weight', `:slant', `:width'
3867 They are the same as face attributes of the same name. See
3868 `set-face-attribute'.
3870 `:foundry'
3872 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3874 `:adstyle'
3876 VALUE must be a string or a symbol specifying the additional
3877 typographic style information of a font, e.g. ``sans''.
3879 `:registry'
3881 VALUE must be a string or a symbol specifying the charset registry and
3882 encoding of a font, e.g. ``iso8859-1''.
3884 `:size'
3886 VALUE must be a non-negative integer or a floating point number
3887 specifying the font size. It specifies the font size in pixels
3888 (if VALUE is an integer), or in points (if VALUE is a float).
3890 `:name'
3892 VALUE must be a string of XLFD-style or fontconfig-style font name.
3894 `:script'
3896 VALUE must be a symbol representing a script that the font must
3897 support.
3898 usage: (font-spec ARGS...) */)
3899 (nargs, args)
3900 int nargs;
3901 Lisp_Object *args;
3903 Lisp_Object spec = font_make_spec ();
3904 int i;
3906 for (i = 0; i < nargs; i += 2)
3908 Lisp_Object key = args[i], val = args[i + 1];
3910 if (EQ (key, QCname))
3912 CHECK_STRING (val);
3913 font_parse_name ((char *) SDATA (val), spec);
3914 font_put_extra (spec, key, val);
3916 else
3918 int idx = get_font_prop_index (key);
3920 if (idx >= 0)
3922 val = font_prop_validate (idx, Qnil, val);
3923 if (idx < FONT_EXTRA_INDEX)
3924 ASET (spec, idx, val);
3925 else
3926 font_put_extra (spec, key, val);
3928 else
3929 font_put_extra (spec, key, font_prop_validate (0, key, val));
3932 return spec;
3935 DEFUN ("copy-font-spec", Fcopy_font_spec, Scopy_font_spec, 1, 1, 0,
3936 doc: /* Return a copy of FONT as a font-spec. */)
3937 (font)
3938 Lisp_Object font;
3940 Lisp_Object new_spec, tail, prev, extra;
3941 int i;
3943 CHECK_FONT (font);
3944 new_spec = font_make_spec ();
3945 for (i = 1; i < FONT_EXTRA_INDEX; i++)
3946 ASET (new_spec, i, AREF (font, i));
3947 extra = Fcopy_sequence (AREF (font, FONT_EXTRA_INDEX));
3948 /* We must remove :font-entity property. */
3949 for (prev = Qnil, tail = extra; CONSP (tail); prev = tail, tail = XCDR (tail))
3950 if (EQ (XCAR (XCAR (tail)), QCfont_entity))
3952 if (NILP (prev))
3953 extra = XCDR (extra);
3954 else
3955 XSETCDR (prev, XCDR (tail));
3956 break;
3958 ASET (new_spec, FONT_EXTRA_INDEX, extra);
3959 return new_spec;
3962 DEFUN ("merge-font-spec", Fmerge_font_spec, Smerge_font_spec, 2, 2, 0,
3963 doc: /* Merge font-specs FROM and TO, and return a new font-spec.
3964 Every specified properties in FROM override the corresponding
3965 properties in TO. */)
3966 (from, to)
3967 Lisp_Object from, to;
3969 Lisp_Object extra, tail;
3970 int i;
3972 CHECK_FONT (from);
3973 CHECK_FONT (to);
3974 to = Fcopy_font_spec (to);
3975 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3976 ASET (to, i, AREF (from, i));
3977 extra = AREF (to, FONT_EXTRA_INDEX);
3978 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3979 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
3981 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
3983 if (! NILP (slot))
3984 XSETCDR (slot, XCDR (XCAR (tail)));
3985 else
3986 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
3988 ASET (to, FONT_EXTRA_INDEX, extra);
3989 return to;
3992 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
3993 doc: /* Return the value of FONT's property KEY.
3994 FONT is a font-spec, a font-entity, or a font-object.
3995 KEY must be one of these symbols:
3996 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
3997 :size, :name, :script
3998 See the documentation of `font-spec' for their meanings.
3999 If FONT is a font-entity or font-object, the value of :script may be
4000 a list of scripts that are supported by the font. */)
4001 (font, key)
4002 Lisp_Object font, key;
4004 int idx;
4006 CHECK_FONT (font);
4007 CHECK_SYMBOL (key);
4009 idx = get_font_prop_index (key);
4010 if (idx >= FONT_WEIGHT_INDEX && idx <= FONT_WIDTH_INDEX)
4011 return font_style_symbolic (font, idx, 0);
4012 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4013 return AREF (font, idx);
4014 return Fcdr (Fassq (key, AREF (font, FONT_EXTRA_INDEX)));
4017 #ifdef HAVE_WINDOW_SYSTEM
4019 DEFUN ("font-face-attributes", Ffont_face_attributes, Sfont_face_attributes, 1, 2, 0,
4020 doc: /* Return a plist of face attributes generated by FONT.
4021 FONT is a font name, a font-spec, a font-entity, or a font-object.
4022 The return value is a list of the form
4024 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
4026 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
4027 compatible with `set-face-attribute'. Some of these key-attribute pairs
4028 may be omitted from the list if they are not specified by FONT.
4030 The optional argument FRAME specifies the frame that the face attributes
4031 are to be displayed on. If omitted, the selected frame is used. */)
4032 (font, frame)
4033 Lisp_Object font, frame;
4035 struct frame *f;
4036 Lisp_Object plist[10];
4037 Lisp_Object val;
4038 int n = 0;
4040 if (NILP (frame))
4041 frame = selected_frame;
4042 CHECK_LIVE_FRAME (frame);
4043 f = XFRAME (frame);
4045 if (STRINGP (font))
4047 int fontset = fs_query_fontset (font, 0);
4048 Lisp_Object name = font;
4049 if (fontset >= 0)
4050 font = fontset_ascii (fontset);
4051 font = font_spec_from_name (name);
4052 if (! FONTP (font))
4053 signal_error ("Invalid font name", name);
4055 else if (! FONTP (font))
4056 signal_error ("Invalid font object", font);
4058 val = AREF (font, FONT_FAMILY_INDEX);
4059 if (! NILP (val))
4061 plist[n++] = QCfamily;
4062 plist[n++] = SYMBOL_NAME (val);
4065 val = AREF (font, FONT_SIZE_INDEX);
4066 if (INTEGERP (val))
4068 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
4069 int dpi = INTEGERP (font_dpi) ? XINT (font_dpi) : f->resy;
4070 plist[n++] = QCheight;
4071 plist[n++] = make_number (PIXEL_TO_POINT (XINT (val) * 10, dpi));
4073 else if (FLOATP (val))
4075 plist[n++] = QCheight;
4076 plist[n++] = make_number (10 * (int) XFLOAT_DATA (val));
4079 val = FONT_WEIGHT_FOR_FACE (font);
4080 if (! NILP (val))
4082 plist[n++] = QCweight;
4083 plist[n++] = val;
4086 val = FONT_SLANT_FOR_FACE (font);
4087 if (! NILP (val))
4089 plist[n++] = QCslant;
4090 plist[n++] = val;
4093 val = FONT_WIDTH_FOR_FACE (font);
4094 if (! NILP (val))
4096 plist[n++] = QCwidth;
4097 plist[n++] = val;
4100 return Flist (n, plist);
4103 #endif
4105 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
4106 doc: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
4107 (font_spec, prop, val)
4108 Lisp_Object font_spec, prop, val;
4110 int idx;
4112 CHECK_FONT_SPEC (font_spec);
4113 idx = get_font_prop_index (prop);
4114 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4115 ASET (font_spec, idx, font_prop_validate (idx, Qnil, val));
4116 else
4117 font_put_extra (font_spec, prop, font_prop_validate (0, prop, val));
4118 return val;
4121 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
4122 doc: /* List available fonts matching FONT-SPEC on the current frame.
4123 Optional 2nd argument FRAME specifies the target frame.
4124 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4125 Optional 4th argument PREFER, if non-nil, is a font-spec to
4126 control the order of the returned list. Fonts are sorted by
4127 how close they are to PREFER. */)
4128 (font_spec, frame, num, prefer)
4129 Lisp_Object font_spec, frame, num, prefer;
4131 Lisp_Object vec, list, tail;
4132 int n = 0, i, len;
4134 if (NILP (frame))
4135 frame = selected_frame;
4136 CHECK_LIVE_FRAME (frame);
4137 CHECK_FONT_SPEC (font_spec);
4138 if (! NILP (num))
4140 CHECK_NUMBER (num);
4141 n = XINT (num);
4142 if (n <= 0)
4143 return Qnil;
4145 if (! NILP (prefer))
4146 CHECK_FONT_SPEC (prefer);
4148 vec = font_list_entities (frame, font_spec);
4149 len = ASIZE (vec);
4150 if (len == 0)
4151 return Qnil;
4152 if (len == 1)
4153 return Fcons (AREF (vec, 0), Qnil);
4155 if (! NILP (prefer))
4156 vec = font_sort_entites (vec, prefer, frame, 0);
4158 list = tail = Fcons (AREF (vec, 0), Qnil);
4159 if (n == 0 || n > len)
4160 n = len;
4161 for (i = 1; i < n; i++)
4163 Lisp_Object val = Fcons (AREF (vec, i), Qnil);
4165 XSETCDR (tail, val);
4166 tail = val;
4168 return list;
4171 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
4172 doc: /* List available font families on the current frame.
4173 Optional argument FRAME, if non-nil, specifies the target frame. */)
4174 (frame)
4175 Lisp_Object frame;
4177 FRAME_PTR f;
4178 struct font_driver_list *driver_list;
4179 Lisp_Object list;
4181 if (NILP (frame))
4182 frame = selected_frame;
4183 CHECK_LIVE_FRAME (frame);
4184 f = XFRAME (frame);
4185 list = Qnil;
4186 for (driver_list = f->font_driver_list; driver_list;
4187 driver_list = driver_list->next)
4188 if (driver_list->driver->list_family)
4190 Lisp_Object val = driver_list->driver->list_family (frame);
4192 if (NILP (list))
4193 list = val;
4194 else
4196 Lisp_Object tail = list;
4198 for (; CONSP (val); val = XCDR (val))
4199 if (NILP (Fmemq (XCAR (val), tail)))
4200 list = Fcons (XCAR (val), list);
4203 return list;
4206 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
4207 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
4208 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4209 (font_spec, frame)
4210 Lisp_Object font_spec, frame;
4212 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
4214 if (CONSP (val))
4215 val = XCAR (val);
4216 return val;
4219 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
4220 doc: /* Return XLFD name of FONT.
4221 FONT is a font-spec, font-entity, or font-object.
4222 If the name is too long for XLFD (maximum 255 chars), return nil.
4223 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4224 the consecutive wildcards are folded to one. */)
4225 (font, fold_wildcards)
4226 Lisp_Object font, fold_wildcards;
4228 char name[256];
4229 int pixel_size = 0;
4231 CHECK_FONT (font);
4233 if (FONT_OBJECT_P (font))
4235 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
4237 if (STRINGP (font_name)
4238 && SDATA (font_name)[0] == '-')
4240 if (NILP (fold_wildcards))
4241 return font_name;
4242 strcpy (name, (char *) SDATA (font_name));
4243 goto done;
4245 pixel_size = XFONT_OBJECT (font)->pixel_size;
4247 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
4248 return Qnil;
4249 done:
4250 if (! NILP (fold_wildcards))
4252 char *p0 = name, *p1;
4254 while ((p1 = strstr (p0, "-*-*")))
4256 strcpy (p1, p1 + 2);
4257 p0 = p1;
4261 return build_string (name);
4264 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
4265 doc: /* Clear font cache. */)
4268 Lisp_Object list, frame;
4270 FOR_EACH_FRAME (list, frame)
4272 FRAME_PTR f = XFRAME (frame);
4273 struct font_driver_list *driver_list = f->font_driver_list;
4275 for (; driver_list; driver_list = driver_list->next)
4276 if (driver_list->on)
4278 Lisp_Object cache = driver_list->driver->get_cache (f);
4279 Lisp_Object val;
4281 val = XCDR (cache);
4282 while (! NILP (val)
4283 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
4284 val = XCDR (val);
4285 font_assert (! NILP (val));
4286 val = XCDR (XCAR (val));
4287 if (XINT (XCAR (val)) == 0)
4289 font_clear_cache (f, XCAR (val), driver_list->driver);
4290 XSETCDR (cache, XCDR (val));
4295 return Qnil;
4299 void
4300 font_fill_lglyph_metrics (glyph, font_object)
4301 Lisp_Object glyph, font_object;
4303 struct font *font = XFONT_OBJECT (font_object);
4304 unsigned code;
4305 /* ecode used in LGLYPH_SET_CODE to avoid compiler warnings. */
4306 EMACS_INT ecode = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
4307 struct font_metrics metrics;
4309 LGLYPH_SET_CODE (glyph, ecode);
4310 code = ecode;
4311 font->driver->text_extents (font, &code, 1, &metrics);
4312 LGLYPH_SET_LBEARING (glyph, metrics.lbearing);
4313 LGLYPH_SET_RBEARING (glyph, metrics.rbearing);
4314 LGLYPH_SET_WIDTH (glyph, metrics.width);
4315 LGLYPH_SET_ASCENT (glyph, metrics.ascent);
4316 LGLYPH_SET_DESCENT (glyph, metrics.descent);
4320 DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0,
4321 doc: /* Shape the glyph-string GSTRING.
4322 Shaping means substituting glyphs and/or adjusting positions of glyphs
4323 to get the correct visual image of character sequences set in the
4324 header of the glyph-string.
4326 If the shaping was successful, the value is GSTRING itself or a newly
4327 created glyph-string. Otherwise, the value is nil. */)
4328 (gstring)
4329 Lisp_Object gstring;
4331 struct font *font;
4332 Lisp_Object font_object, n, glyph;
4333 int i, j, from, to;
4335 if (! composition_gstring_p (gstring))
4336 signal_error ("Invalid glyph-string: ", gstring);
4337 if (! NILP (LGSTRING_ID (gstring)))
4338 return gstring;
4339 font_object = LGSTRING_FONT (gstring);
4340 CHECK_FONT_OBJECT (font_object);
4341 font = XFONT_OBJECT (font_object);
4342 if (! font->driver->shape)
4343 return Qnil;
4345 /* Try at most three times with larger gstring each time. */
4346 for (i = 0; i < 3; i++)
4348 n = font->driver->shape (gstring);
4349 if (INTEGERP (n))
4350 break;
4351 gstring = larger_vector (gstring,
4352 ASIZE (gstring) + LGSTRING_GLYPH_LEN (gstring),
4353 Qnil);
4355 if (i == 3 || XINT (n) == 0)
4356 return Qnil;
4358 glyph = LGSTRING_GLYPH (gstring, 0);
4359 from = LGLYPH_FROM (glyph);
4360 to = LGLYPH_TO (glyph);
4361 for (i = 1, j = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
4363 Lisp_Object this = LGSTRING_GLYPH (gstring, i);
4365 if (NILP (this))
4366 break;
4367 if (NILP (LGLYPH_ADJUSTMENT (this)))
4369 if (j < i - 1)
4370 for (; j < i; j++)
4372 glyph = LGSTRING_GLYPH (gstring, j);
4373 LGLYPH_SET_FROM (glyph, from);
4374 LGLYPH_SET_TO (glyph, to);
4376 from = LGLYPH_FROM (this);
4377 to = LGLYPH_TO (this);
4378 j = i;
4380 else
4382 if (from > LGLYPH_FROM (this))
4383 from = LGLYPH_FROM (this);
4384 if (to < LGLYPH_TO (this))
4385 to = LGLYPH_TO (this);
4388 if (j < i - 1)
4389 for (; j < i; j++)
4391 glyph = LGSTRING_GLYPH (gstring, j);
4392 LGLYPH_SET_FROM (glyph, from);
4393 LGLYPH_SET_TO (glyph, to);
4395 return composition_gstring_put_cache (gstring, XINT (n));
4398 #if 0
4400 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
4401 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
4402 OTF-FEATURES specifies which features to apply in this format:
4403 (SCRIPT LANGSYS GSUB GPOS)
4404 where
4405 SCRIPT is a symbol specifying a script tag of OpenType,
4406 LANGSYS is a symbol specifying a langsys tag of OpenType,
4407 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4409 If LANGYS is nil, the default langsys is selected.
4411 The features are applied in the order they appear in the list. The
4412 symbol `*' means to apply all available features not present in this
4413 list, and the remaining features are ignored. For instance, (vatu
4414 pstf * haln) is to apply vatu and pstf in this order, then to apply
4415 all available features other than vatu, pstf, and haln.
4417 The features are applied to the glyphs in the range FROM and TO of
4418 the glyph-string GSTRING-IN.
4420 If some feature is actually applicable, the resulting glyphs are
4421 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4422 this case, the value is the number of produced glyphs.
4424 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4425 the value is 0.
4427 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4428 produced in GSTRING-OUT, and the value is nil.
4430 See the documentation of `font-make-gstring' for the format of
4431 glyph-string. */)
4432 (otf_features, gstring_in, from, to, gstring_out, index)
4433 Lisp_Object otf_features, gstring_in, from, to, gstring_out, index;
4435 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
4436 Lisp_Object val;
4437 struct font *font;
4438 int len, num;
4440 check_otf_features (otf_features);
4441 CHECK_FONT_OBJECT (font_object);
4442 font = XFONT_OBJECT (font_object);
4443 if (! font->driver->otf_drive)
4444 error ("Font backend %s can't drive OpenType GSUB table",
4445 SDATA (SYMBOL_NAME (font->driver->type)));
4446 CHECK_CONS (otf_features);
4447 CHECK_SYMBOL (XCAR (otf_features));
4448 val = XCDR (otf_features);
4449 CHECK_SYMBOL (XCAR (val));
4450 val = XCDR (otf_features);
4451 if (! NILP (val))
4452 CHECK_CONS (val);
4453 len = check_gstring (gstring_in);
4454 CHECK_VECTOR (gstring_out);
4455 CHECK_NATNUM (from);
4456 CHECK_NATNUM (to);
4457 CHECK_NATNUM (index);
4459 if (XINT (from) >= XINT (to) || XINT (to) > len)
4460 args_out_of_range_3 (from, to, make_number (len));
4461 if (XINT (index) >= ASIZE (gstring_out))
4462 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4463 num = font->driver->otf_drive (font, otf_features,
4464 gstring_in, XINT (from), XINT (to),
4465 gstring_out, XINT (index), 0);
4466 if (num < 0)
4467 return Qnil;
4468 return make_number (num);
4471 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4472 3, 3, 0,
4473 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4474 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4475 in this format:
4476 (SCRIPT LANGSYS FEATURE ...)
4477 See the documentation of `font-drive-otf' for more detail.
4479 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4480 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4481 character code corresponding to the glyph or nil if there's no
4482 corresponding character. */)
4483 (font_object, character, otf_features)
4484 Lisp_Object font_object, character, otf_features;
4486 struct font *font;
4487 Lisp_Object gstring_in, gstring_out, g;
4488 Lisp_Object alternates;
4489 int i, num;
4491 CHECK_FONT_GET_OBJECT (font_object, font);
4492 if (! font->driver->otf_drive)
4493 error ("Font backend %s can't drive OpenType GSUB table",
4494 SDATA (SYMBOL_NAME (font->driver->type)));
4495 CHECK_CHARACTER (character);
4496 CHECK_CONS (otf_features);
4498 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4499 g = LGSTRING_GLYPH (gstring_in, 0);
4500 LGLYPH_SET_CHAR (g, XINT (character));
4501 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4502 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4503 gstring_out, 0, 1)) < 0)
4504 gstring_out = Ffont_make_gstring (font_object,
4505 make_number (ASIZE (gstring_out) * 2));
4506 alternates = Qnil;
4507 for (i = 0; i < num; i++)
4509 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4510 int c = LGLYPH_CHAR (g);
4511 unsigned code = LGLYPH_CODE (g);
4513 alternates = Fcons (Fcons (make_number (code),
4514 c > 0 ? make_number (c) : Qnil),
4515 alternates);
4517 return Fnreverse (alternates);
4519 #endif /* 0 */
4521 #ifdef FONT_DEBUG
4523 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4524 doc: /* Open FONT-ENTITY. */)
4525 (font_entity, size, frame)
4526 Lisp_Object font_entity;
4527 Lisp_Object size;
4528 Lisp_Object frame;
4530 int isize;
4532 CHECK_FONT_ENTITY (font_entity);
4533 if (NILP (frame))
4534 frame = selected_frame;
4535 CHECK_LIVE_FRAME (frame);
4537 if (NILP (size))
4538 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4539 else
4541 CHECK_NUMBER_OR_FLOAT (size);
4542 if (FLOATP (size))
4543 isize = POINT_TO_PIXEL (XFLOAT_DATA (size), XFRAME (frame)->resy);
4544 else
4545 isize = XINT (size);
4546 if (isize == 0)
4547 isize = 120;
4549 return font_open_entity (XFRAME (frame), font_entity, isize);
4552 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4553 doc: /* Close FONT-OBJECT. */)
4554 (font_object, frame)
4555 Lisp_Object font_object, frame;
4557 CHECK_FONT_OBJECT (font_object);
4558 if (NILP (frame))
4559 frame = selected_frame;
4560 CHECK_LIVE_FRAME (frame);
4561 font_close_object (XFRAME (frame), font_object);
4562 return Qnil;
4565 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4566 doc: /* Return information about FONT-OBJECT.
4567 The value is a vector:
4568 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4569 CAPABILITY ]
4571 NAME is a string of the font name (or nil if the font backend doesn't
4572 provide a name).
4574 FILENAME is a string of the font file (or nil if the font backend
4575 doesn't provide a file name).
4577 PIXEL-SIZE is a pixel size by which the font is opened.
4579 SIZE is a maximum advance width of the font in pixels.
4581 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4582 pixels.
4584 CAPABILITY is a list whose first element is a symbol representing the
4585 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4586 remaining elements describe the details of the font capability.
4588 If the font is OpenType font, the form of the list is
4589 \(opentype GSUB GPOS)
4590 where GSUB shows which "GSUB" features the font supports, and GPOS
4591 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4592 lists of the format:
4593 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4595 If the font is not OpenType font, currently the length of the form is
4596 one.
4598 SCRIPT is a symbol representing OpenType script tag.
4600 LANGSYS is a symbol representing OpenType langsys tag, or nil
4601 representing the default langsys.
4603 FEATURE is a symbol representing OpenType feature tag.
4605 If the font is not OpenType font, CAPABILITY is nil. */)
4606 (font_object)
4607 Lisp_Object font_object;
4609 struct font *font;
4610 Lisp_Object val;
4612 CHECK_FONT_GET_OBJECT (font_object, font);
4614 val = Fmake_vector (make_number (9), Qnil);
4615 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4616 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4617 ASET (val, 2, make_number (font->pixel_size));
4618 ASET (val, 3, make_number (font->max_width));
4619 ASET (val, 4, make_number (font->ascent));
4620 ASET (val, 5, make_number (font->descent));
4621 ASET (val, 6, make_number (font->space_width));
4622 ASET (val, 7, make_number (font->average_width));
4623 if (font->driver->otf_capability)
4624 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4625 return val;
4628 DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
4629 doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
4630 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
4631 (font_object, string)
4632 Lisp_Object font_object, string;
4634 struct font *font;
4635 int i, len;
4636 Lisp_Object vec;
4638 CHECK_FONT_GET_OBJECT (font_object, font);
4639 CHECK_STRING (string);
4640 len = SCHARS (string);
4641 vec = Fmake_vector (make_number (len), Qnil);
4642 for (i = 0; i < len; i++)
4644 Lisp_Object ch = Faref (string, make_number (i));
4645 Lisp_Object val;
4646 int c = XINT (ch);
4647 unsigned code;
4648 EMACS_INT cod;
4649 struct font_metrics metrics;
4651 cod = code = font->driver->encode_char (font, c);
4652 if (code == FONT_INVALID_CODE)
4653 continue;
4654 val = Fmake_vector (make_number (6), Qnil);
4655 if (cod <= MOST_POSITIVE_FIXNUM)
4656 ASET (val, 0, make_number (code));
4657 else
4658 ASET (val, 0, Fcons (make_number (code >> 16),
4659 make_number (code & 0xFFFF)));
4660 font->driver->text_extents (font, &code, 1, &metrics);
4661 ASET (val, 1, make_number (metrics.lbearing));
4662 ASET (val, 2, make_number (metrics.rbearing));
4663 ASET (val, 3, make_number (metrics.width));
4664 ASET (val, 4, make_number (metrics.ascent));
4665 ASET (val, 5, make_number (metrics.descent));
4666 ASET (vec, i, val);
4668 return vec;
4671 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4672 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4673 FONT is a font-spec, font-entity, or font-object. */)
4674 (spec, font)
4675 Lisp_Object spec, font;
4677 CHECK_FONT_SPEC (spec);
4678 CHECK_FONT (font);
4680 return (font_match_p (spec, font) ? Qt : Qnil);
4683 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4684 doc: /* Return a font-object for displaying a character at POSITION.
4685 Optional second arg WINDOW, if non-nil, is a window displaying
4686 the current buffer. It defaults to the currently selected window. */)
4687 (position, window, string)
4688 Lisp_Object position, window, string;
4690 struct window *w;
4691 EMACS_INT pos;
4693 if (NILP (string))
4695 CHECK_NUMBER_COERCE_MARKER (position);
4696 pos = XINT (position);
4697 if (pos < BEGV || pos >= ZV)
4698 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4700 else
4702 CHECK_NUMBER (position);
4703 CHECK_STRING (string);
4704 pos = XINT (position);
4705 if (pos < 0 || pos >= SCHARS (string))
4706 args_out_of_range (string, position);
4708 if (NILP (window))
4709 window = selected_window;
4710 CHECK_LIVE_WINDOW (window);
4711 w = XWINDOW (window);
4713 return font_at (-1, pos, NULL, w, string);
4716 #if 0
4717 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4718 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4719 The value is a number of glyphs drawn.
4720 Type C-l to recover what previously shown. */)
4721 (font_object, string)
4722 Lisp_Object font_object, string;
4724 Lisp_Object frame = selected_frame;
4725 FRAME_PTR f = XFRAME (frame);
4726 struct font *font;
4727 struct face *face;
4728 int i, len, width;
4729 unsigned *code;
4731 CHECK_FONT_GET_OBJECT (font_object, font);
4732 CHECK_STRING (string);
4733 len = SCHARS (string);
4734 code = alloca (sizeof (unsigned) * len);
4735 for (i = 0; i < len; i++)
4737 Lisp_Object ch = Faref (string, make_number (i));
4738 Lisp_Object val;
4739 int c = XINT (ch);
4741 code[i] = font->driver->encode_char (font, c);
4742 if (code[i] == FONT_INVALID_CODE)
4743 break;
4745 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4746 face->fontp = font;
4747 if (font->driver->prepare_face)
4748 font->driver->prepare_face (f, face);
4749 width = font->driver->text_extents (font, code, i, NULL);
4750 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4751 if (font->driver->done_face)
4752 font->driver->done_face (f, face);
4753 face->fontp = NULL;
4754 return make_number (len);
4756 #endif
4758 #endif /* FONT_DEBUG */
4760 #ifdef HAVE_WINDOW_SYSTEM
4762 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
4763 doc: /* Return information about a font named NAME on frame FRAME.
4764 If FRAME is omitted or nil, use the selected frame.
4765 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
4766 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4767 where
4768 OPENED-NAME is the name used for opening the font,
4769 FULL-NAME is the full name of the font,
4770 SIZE is the maximum bound width of the font,
4771 HEIGHT is the height of the font,
4772 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4773 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4774 how to compose characters.
4775 If the named font is not yet loaded, return nil. */)
4776 (name, frame)
4777 Lisp_Object name, frame;
4779 FRAME_PTR f;
4780 struct font *font;
4781 Lisp_Object info;
4782 Lisp_Object font_object;
4784 (*check_window_system_func) ();
4786 if (! FONTP (name))
4787 CHECK_STRING (name);
4788 if (NILP (frame))
4789 frame = selected_frame;
4790 CHECK_LIVE_FRAME (frame);
4791 f = XFRAME (frame);
4793 if (STRINGP (name))
4795 int fontset = fs_query_fontset (name, 0);
4797 if (fontset >= 0)
4798 name = fontset_ascii (fontset);
4799 font_object = font_open_by_name (f, (char *) SDATA (name));
4801 else if (FONT_OBJECT_P (name))
4802 font_object = name;
4803 else if (FONT_ENTITY_P (name))
4804 font_object = font_open_entity (f, name, 0);
4805 else
4807 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4808 Lisp_Object entity = font_matching_entity (f, face->lface, name);
4810 font_object = ! NILP (entity) ? font_open_entity (f, entity, 0) : Qnil;
4812 if (NILP (font_object))
4813 return Qnil;
4814 font = XFONT_OBJECT (font_object);
4816 info = Fmake_vector (make_number (7), Qnil);
4817 XVECTOR (info)->contents[0] = AREF (font_object, FONT_NAME_INDEX);
4818 XVECTOR (info)->contents[1] = AREF (font_object, FONT_NAME_INDEX);
4819 XVECTOR (info)->contents[2] = make_number (font->pixel_size);
4820 XVECTOR (info)->contents[3] = make_number (font->height);
4821 XVECTOR (info)->contents[4] = make_number (font->baseline_offset);
4822 XVECTOR (info)->contents[5] = make_number (font->relative_compose);
4823 XVECTOR (info)->contents[6] = make_number (font->default_ascent);
4825 #if 0
4826 /* As font_object is still in FONT_OBJLIST of the entity, we can't
4827 close it now. Perhaps, we should manage font-objects
4828 by `reference-count'. */
4829 font_close_object (f, font_object);
4830 #endif
4831 return info;
4833 #endif
4836 #define BUILD_STYLE_TABLE(TBL) \
4837 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
4839 static Lisp_Object
4840 build_style_table (entry, nelement)
4841 struct table_entry *entry;
4842 int nelement;
4844 int i, j;
4845 Lisp_Object table, elt;
4847 table = Fmake_vector (make_number (nelement), Qnil);
4848 for (i = 0; i < nelement; i++)
4850 for (j = 0; entry[i].names[j]; j++);
4851 elt = Fmake_vector (make_number (j + 1), Qnil);
4852 ASET (elt, 0, make_number (entry[i].numeric));
4853 for (j = 0; entry[i].names[j]; j++)
4854 ASET (elt, j + 1, intern (entry[i].names[j]));
4855 ASET (table, i, elt);
4857 return table;
4860 static Lisp_Object Vfont_log;
4861 static int font_log_env_checked;
4863 /* The deferred font-log data of the form [ACTION ARG RESULT].
4864 If ACTION is not nil, that is added to the log when font_add_log is
4865 called next time. At that time, ACTION is set back to nil. */
4866 static Lisp_Object Vfont_log_deferred;
4868 /* Prepend the font-related logging data in Vfont_log if it is not
4869 `t'. ACTION describes a kind of font-related action (e.g. listing,
4870 opening), ARG is the argument for the action, and RESULT is the
4871 result of the action. */
4872 void
4873 font_add_log (action, arg, result)
4874 char *action;
4875 Lisp_Object arg, result;
4877 Lisp_Object tail, val;
4878 int i;
4880 if (! font_log_env_checked)
4882 Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;
4883 font_log_env_checked = 1;
4885 if (EQ (Vfont_log, Qt))
4886 return;
4887 if (STRINGP (AREF (Vfont_log_deferred, 0)))
4889 char *str = (char *) SDATA (AREF (Vfont_log_deferred, 0));
4891 ASET (Vfont_log_deferred, 0, Qnil);
4892 font_add_log (str, AREF (Vfont_log_deferred, 1),
4893 AREF (Vfont_log_deferred, 2));
4896 if (FONTP (arg))
4898 Lisp_Object tail, elt;
4899 Lisp_Object equalstr = build_string ("=");
4901 val = Ffont_xlfd_name (arg, Qt);
4902 for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail);
4903 tail = XCDR (tail))
4905 elt = XCAR (tail);
4906 if (EQ (XCAR (elt), QCscript)
4907 && SYMBOLP (XCDR (elt)))
4908 val = concat3 (val, SYMBOL_NAME (QCscript),
4909 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
4910 else if (EQ (XCAR (elt), QClang)
4911 && SYMBOLP (XCDR (elt)))
4912 val = concat3 (val, SYMBOL_NAME (QClang),
4913 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
4914 else if (EQ (XCAR (elt), QCotf)
4915 && CONSP (XCDR (elt)) && SYMBOLP (XCAR (XCDR (elt))))
4916 val = concat3 (val, SYMBOL_NAME (QCotf),
4917 concat2 (equalstr,
4918 SYMBOL_NAME (XCAR (XCDR (elt)))));
4920 arg = val;
4922 if (FONTP (result))
4924 val = Ffont_xlfd_name (result, Qt);
4925 if (! FONT_SPEC_P (result))
4926 val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)),
4927 build_string (":"), val);
4928 result = val;
4930 else if (CONSP (result))
4932 result = Fcopy_sequence (result);
4933 for (tail = result; CONSP (tail); tail = XCDR (tail))
4935 val = XCAR (tail);
4936 if (FONTP (val))
4937 val = Ffont_xlfd_name (val, Qt);
4938 XSETCAR (tail, val);
4941 else if (VECTORP (result))
4943 result = Fcopy_sequence (result);
4944 for (i = 0; i < ASIZE (result); i++)
4946 val = AREF (result, i);
4947 if (FONTP (val))
4948 val = Ffont_xlfd_name (val, Qt);
4949 ASET (result, i, val);
4952 Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
4955 /* Record a font-related logging data to be added to Vfont_log when
4956 font_add_log is called next time. ACTION, ARG, RESULT are the same
4957 as font_add_log. */
4959 void
4960 font_deferred_log (action, arg, result)
4961 char *action;
4962 Lisp_Object arg, result;
4964 ASET (Vfont_log_deferred, 0, build_string (action));
4965 ASET (Vfont_log_deferred, 1, arg);
4966 ASET (Vfont_log_deferred, 2, result);
4969 extern void syms_of_ftfont P_ (());
4970 extern void syms_of_xfont P_ (());
4971 extern void syms_of_xftfont P_ (());
4972 extern void syms_of_ftxfont P_ (());
4973 extern void syms_of_bdffont P_ (());
4974 extern void syms_of_w32font P_ (());
4975 extern void syms_of_atmfont P_ (());
4976 extern void syms_of_nsfont P_ (());
4978 void
4979 syms_of_font ()
4981 sort_shift_bits[FONT_TYPE_INDEX] = 0;
4982 sort_shift_bits[FONT_SLANT_INDEX] = 2;
4983 sort_shift_bits[FONT_WEIGHT_INDEX] = 9;
4984 sort_shift_bits[FONT_SIZE_INDEX] = 16;
4985 sort_shift_bits[FONT_WIDTH_INDEX] = 23;
4986 /* Note that the other elements in sort_shift_bits are not used. */
4988 staticpro (&font_charset_alist);
4989 font_charset_alist = Qnil;
4991 DEFSYM (Qfont_spec, "font-spec");
4992 DEFSYM (Qfont_entity, "font-entity");
4993 DEFSYM (Qfont_object, "font-object");
4995 DEFSYM (Qopentype, "opentype");
4997 DEFSYM (Qascii_0, "ascii-0");
4998 DEFSYM (Qiso8859_1, "iso8859-1");
4999 DEFSYM (Qiso10646_1, "iso10646-1");
5000 DEFSYM (Qunicode_bmp, "unicode-bmp");
5001 DEFSYM (Qunicode_sip, "unicode-sip");
5003 DEFSYM (QCf, "Cf");
5005 DEFSYM (QCotf, ":otf");
5006 DEFSYM (QClang, ":lang");
5007 DEFSYM (QCscript, ":script");
5008 DEFSYM (QCantialias, ":antialias");
5010 DEFSYM (QCfoundry, ":foundry");
5011 DEFSYM (QCadstyle, ":adstyle");
5012 DEFSYM (QCregistry, ":registry");
5013 DEFSYM (QCspacing, ":spacing");
5014 DEFSYM (QCdpi, ":dpi");
5015 DEFSYM (QCscalable, ":scalable");
5016 DEFSYM (QCavgwidth, ":avgwidth");
5017 DEFSYM (QCfont_entity, ":font-entity");
5018 DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
5020 DEFSYM (Qc, "c");
5021 DEFSYM (Qm, "m");
5022 DEFSYM (Qp, "p");
5023 DEFSYM (Qd, "d");
5025 staticpro (&null_vector);
5026 null_vector = Fmake_vector (make_number (0), Qnil);
5028 staticpro (&scratch_font_spec);
5029 scratch_font_spec = Ffont_spec (0, NULL);
5030 staticpro (&scratch_font_prefer);
5031 scratch_font_prefer = Ffont_spec (0, NULL);
5033 staticpro (&Vfont_log_deferred);
5034 Vfont_log_deferred = Fmake_vector (make_number (3), Qnil);
5036 #if 0
5037 #ifdef HAVE_LIBOTF
5038 staticpro (&otf_list);
5039 otf_list = Qnil;
5040 #endif /* HAVE_LIBOTF */
5041 #endif /* 0 */
5043 defsubr (&Sfontp);
5044 defsubr (&Sfont_spec);
5045 defsubr (&Sfont_get);
5046 #ifdef HAVE_WINDOW_SYSTEM
5047 defsubr (&Sfont_face_attributes);
5048 #endif
5049 defsubr (&Sfont_put);
5050 defsubr (&Slist_fonts);
5051 defsubr (&Sfont_family_list);
5052 defsubr (&Sfind_font);
5053 defsubr (&Sfont_xlfd_name);
5054 defsubr (&Sclear_font_cache);
5055 defsubr (&Sfont_shape_gstring);
5056 #if 0
5057 defsubr (&Sfont_drive_otf);
5058 defsubr (&Sfont_otf_alternates);
5059 #endif /* 0 */
5061 #ifdef FONT_DEBUG
5062 defsubr (&Sopen_font);
5063 defsubr (&Sclose_font);
5064 defsubr (&Squery_font);
5065 defsubr (&Sget_font_glyphs);
5066 defsubr (&Sfont_match_p);
5067 defsubr (&Sfont_at);
5068 #if 0
5069 defsubr (&Sdraw_string);
5070 #endif
5071 #endif /* FONT_DEBUG */
5072 #ifdef HAVE_WINDOW_SYSTEM
5073 defsubr (&Sfont_info);
5074 #endif
5076 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
5077 doc: /*
5078 Alist of fontname patterns vs the corresponding encoding and repertory info.
5079 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5080 where ENCODING is a charset or a char-table,
5081 and REPERTORY is a charset, a char-table, or nil.
5083 If ENCODING and REPERTORY are the same, the element can have the form
5084 \(REGEXP . ENCODING).
5086 ENCODING is for converting a character to a glyph code of the font.
5087 If ENCODING is a charset, encoding a character by the charset gives
5088 the corresponding glyph code. If ENCODING is a char-table, looking up
5089 the table by a character gives the corresponding glyph code.
5091 REPERTORY specifies a repertory of characters supported by the font.
5092 If REPERTORY is a charset, all characters beloging to the charset are
5093 supported. If REPERTORY is a char-table, all characters who have a
5094 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5095 gets the repertory information by an opened font and ENCODING. */);
5096 Vfont_encoding_alist = Qnil;
5098 DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table,
5099 doc: /* Vector of valid font weight values.
5100 Each element has the form:
5101 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5102 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5103 Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
5105 DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table,
5106 doc: /* Vector of font slant symbols vs the corresponding numeric values.
5107 See `font-weight-table' for the format of the vector. */);
5108 Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
5110 DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table,
5111 doc: /* Alist of font width symbols vs the corresponding numeric values.
5112 See `font-weight-table' for the format of the vector. */);
5113 Vfont_width_table = BUILD_STYLE_TABLE (width_table);
5115 staticpro (&font_style_table);
5116 font_style_table = Fmake_vector (make_number (3), Qnil);
5117 ASET (font_style_table, 0, Vfont_weight_table);
5118 ASET (font_style_table, 1, Vfont_slant_table);
5119 ASET (font_style_table, 2, Vfont_width_table);
5121 DEFVAR_LISP ("font-log", &Vfont_log, doc: /*
5122 *Logging list of font related actions and results.
5123 The value t means to suppress the logging.
5124 The initial value is set to nil if the environment variable
5125 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5126 Vfont_log = Qnil;
5128 #ifdef HAVE_WINDOW_SYSTEM
5129 #ifdef HAVE_FREETYPE
5130 syms_of_ftfont ();
5131 #ifdef HAVE_X_WINDOWS
5132 syms_of_xfont ();
5133 syms_of_ftxfont ();
5134 #ifdef HAVE_XFT
5135 syms_of_xftfont ();
5136 #endif /* HAVE_XFT */
5137 #endif /* HAVE_X_WINDOWS */
5138 #else /* not HAVE_FREETYPE */
5139 #ifdef HAVE_X_WINDOWS
5140 syms_of_xfont ();
5141 #endif /* HAVE_X_WINDOWS */
5142 #endif /* not HAVE_FREETYPE */
5143 #ifdef HAVE_BDFFONT
5144 syms_of_bdffont ();
5145 #endif /* HAVE_BDFFONT */
5146 #ifdef WINDOWSNT
5147 syms_of_w32font ();
5148 #endif /* WINDOWSNT */
5149 #ifdef HAVE_NS
5150 syms_of_nsfont ();
5151 #endif /* HAVE_NS */
5152 #endif /* HAVE_WINDOW_SYSTEM */
5155 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
5156 (do not change this comment) */