Use const, move declarations to header files.
[emacs.git] / src / font.c
blob05c5003db79c0b1a5442f0a2427b92e19aeb663e
1 /* font.c -- "Font" primitives.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010
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>
26 #include <setjmp.h>
28 #include "lisp.h"
29 #include "buffer.h"
30 #include "frame.h"
31 #include "window.h"
32 #include "dispextern.h"
33 #include "charset.h"
34 #include "character.h"
35 #include "composite.h"
36 #include "fontset.h"
37 #include "font.h"
39 #ifdef HAVE_X_WINDOWS
40 #include "xterm.h"
41 #endif /* HAVE_X_WINDOWS */
43 #ifdef HAVE_NTGUI
44 #include "w32term.h"
45 #endif /* HAVE_NTGUI */
47 #ifdef HAVE_NS
48 #include "nsterm.h"
49 #endif /* HAVE_NS */
51 #ifdef HAVE_NS
52 extern Lisp_Object Qfontsize;
53 #endif
55 Lisp_Object Qopentype;
57 /* Important character set strings. */
58 Lisp_Object Qascii_0, Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
60 #define DEFAULT_ENCODING Qiso8859_1
62 /* Unicode category `Cf'. */
63 static Lisp_Object QCf;
65 /* Special vector of zero length. This is repeatedly used by (struct
66 font_driver *)->list when a specified font is not found. */
67 static Lisp_Object null_vector;
69 static Lisp_Object Vfont_weight_table, Vfont_slant_table, Vfont_width_table;
71 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
72 static Lisp_Object font_style_table;
74 /* Structure used for tables mapping weight, slant, and width numeric
75 values and their names. */
77 struct table_entry
79 int numeric;
80 /* The first one is a valid name as a face attribute.
81 The second one (if any) is a typical name in XLFD field. */
82 const char *names[5];
85 /* Table of weight numeric values and their names. This table must be
86 sorted by numeric values in ascending order. */
88 static const struct table_entry weight_table[] =
90 { 0, { "thin" }},
91 { 20, { "ultra-light", "ultralight" }},
92 { 40, { "extra-light", "extralight" }},
93 { 50, { "light" }},
94 { 75, { "semi-light", "semilight", "demilight", "book" }},
95 { 100, { "normal", "medium", "regular", "unspecified" }},
96 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
97 { 200, { "bold" }},
98 { 205, { "extra-bold", "extrabold" }},
99 { 210, { "ultra-bold", "ultrabold", "black" }}
102 /* Table of slant numeric values and their names. This table must be
103 sorted by numeric values in ascending order. */
105 static const struct table_entry slant_table[] =
107 { 0, { "reverse-oblique", "ro" }},
108 { 10, { "reverse-italic", "ri" }},
109 { 100, { "normal", "r", "unspecified" }},
110 { 200, { "italic" ,"i", "ot" }},
111 { 210, { "oblique", "o" }}
114 /* Table of width numeric values and their names. This table must be
115 sorted by numeric values in ascending order. */
117 static const struct table_entry width_table[] =
119 { 50, { "ultra-condensed", "ultracondensed" }},
120 { 63, { "extra-condensed", "extracondensed" }},
121 { 75, { "condensed", "compressed", "narrow" }},
122 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
123 { 100, { "normal", "medium", "regular", "unspecified" }},
124 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
125 { 125, { "expanded" }},
126 { 150, { "extra-expanded", "extraexpanded" }},
127 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
130 Lisp_Object QCfoundry, QCadstyle, QCregistry;
131 /* Symbols representing keys of font extra info. */
132 Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
133 Lisp_Object QCantialias, QCfont_entity, QCfc_unknown_spec;
134 /* Symbols representing values of font spacing property. */
135 Lisp_Object Qc, Qm, Qp, Qd;
136 /* Special ADSTYLE properties to avoid fonts used for Latin
137 characters; used in xfont.c and ftfont.c. */
138 Lisp_Object Qja, Qko;
140 Lisp_Object QCuser_spec;
142 Lisp_Object Vfont_encoding_alist;
144 /* Alist of font registry symbol and the corresponding charsets
145 information. The information is retrieved from
146 Vfont_encoding_alist on demand.
148 Eash element has the form:
149 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
151 (REGISTRY . nil)
153 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
154 encodes a character code to a glyph code of a font, and
155 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
156 character is supported by a font.
158 The latter form means that the information for REGISTRY couldn't be
159 retrieved. */
160 static Lisp_Object font_charset_alist;
162 /* List of all font drivers. Each font-backend (XXXfont.c) calls
163 register_font_driver in syms_of_XXXfont to register its font-driver
164 here. */
165 static struct font_driver_list *font_driver_list;
169 /* Creaters of font-related Lisp object. */
171 Lisp_Object
172 font_make_spec (void)
174 Lisp_Object font_spec;
175 struct font_spec *spec
176 = ((struct font_spec *)
177 allocate_pseudovector (VECSIZE (struct font_spec),
178 FONT_SPEC_MAX, PVEC_FONT));
179 XSETFONT (font_spec, spec);
180 return font_spec;
183 Lisp_Object
184 font_make_entity (void)
186 Lisp_Object font_entity;
187 struct font_entity *entity
188 = ((struct font_entity *)
189 allocate_pseudovector (VECSIZE (struct font_entity),
190 FONT_ENTITY_MAX, PVEC_FONT));
191 XSETFONT (font_entity, entity);
192 return font_entity;
195 /* Create a font-object whose structure size is SIZE. If ENTITY is
196 not nil, copy properties from ENTITY to the font-object. If
197 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
198 Lisp_Object
199 font_make_object (int size, Lisp_Object entity, int pixelsize)
201 Lisp_Object font_object;
202 struct font *font
203 = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX, PVEC_FONT);
204 int i;
206 XSETFONT (font_object, font);
208 if (! NILP (entity))
210 for (i = 1; i < FONT_SPEC_MAX; i++)
211 font->props[i] = AREF (entity, i);
212 if (! NILP (AREF (entity, FONT_EXTRA_INDEX)))
213 font->props[FONT_EXTRA_INDEX]
214 = Fcopy_alist (AREF (entity, FONT_EXTRA_INDEX));
216 if (size > 0)
217 font->props[FONT_SIZE_INDEX] = make_number (pixelsize);
218 return font_object;
223 static int font_pixel_size (FRAME_PTR f, Lisp_Object);
224 static Lisp_Object font_open_entity (FRAME_PTR, Lisp_Object, int);
225 static Lisp_Object font_matching_entity (FRAME_PTR, Lisp_Object *,
226 Lisp_Object);
228 /* Number of registered font drivers. */
229 static int num_font_drivers;
232 /* Return a Lispy value of a font property value at STR and LEN bytes.
233 If STR is "*", it returns nil.
234 If FORCE_SYMBOL is zero and all characters in STR are digits, it
235 returns an integer. Otherwise, it returns a symbol interned from
236 STR. */
238 Lisp_Object
239 font_intern_prop (char *str, int len, int force_symbol)
241 int i;
242 Lisp_Object tem;
243 Lisp_Object obarray;
244 int nbytes, nchars;
246 if (len == 1 && *str == '*')
247 return Qnil;
248 if (!force_symbol && len >=1 && isdigit (*str))
250 for (i = 1; i < len; i++)
251 if (! isdigit (str[i]))
252 break;
253 if (i == len)
254 return make_number (atoi (str));
257 /* The following code is copied from the function intern (in
258 lread.c), and modified to suite our purpose. */
259 obarray = Vobarray;
260 if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
261 obarray = check_obarray (obarray);
262 parse_str_as_multibyte ((unsigned char *) str, len, &nchars, &nbytes);
263 if (len == nchars || len != nbytes)
264 /* CONTENTS contains no multibyte sequences or contains an invalid
265 multibyte sequence. We'll make a unibyte string. */
266 tem = oblookup (obarray, str, len, len);
267 else
268 tem = oblookup (obarray, str, nchars, len);
269 if (SYMBOLP (tem))
270 return tem;
271 if (len == nchars || len != nbytes)
272 tem = make_unibyte_string (str, len);
273 else
274 tem = make_multibyte_string (str, nchars, len);
275 return Fintern (tem, obarray);
278 /* Return a pixel size of font-spec SPEC on frame F. */
280 static int
281 font_pixel_size (FRAME_PTR f, Lisp_Object spec)
283 #ifdef HAVE_WINDOW_SYSTEM
284 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
285 double point_size;
286 int dpi, pixel_size;
287 Lisp_Object val;
289 if (INTEGERP (size))
290 return XINT (size);
291 if (NILP (size))
292 return 0;
293 font_assert (FLOATP (size));
294 point_size = XFLOAT_DATA (size);
295 val = AREF (spec, FONT_DPI_INDEX);
296 if (INTEGERP (val))
297 dpi = XINT (val);
298 else
299 dpi = f->resy;
300 pixel_size = POINT_TO_PIXEL (point_size, dpi);
301 return pixel_size;
302 #else
303 return 1;
304 #endif
308 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
309 font vector. If VAL is not valid (i.e. not registered in
310 font_style_table), return -1 if NOERROR is zero, and return a
311 proper index if NOERROR is nonzero. In that case, register VAL in
312 font_style_table if VAL is a symbol, and return a closest index if
313 VAL is an integer. */
316 font_style_to_value (enum font_property_index prop, Lisp_Object val, int noerror)
318 Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
319 int len = ASIZE (table);
320 int i, j;
322 if (SYMBOLP (val))
324 unsigned char *s;
325 Lisp_Object args[2], elt;
327 /* At first try exact match. */
328 for (i = 0; i < len; i++)
329 for (j = 1; j < ASIZE (AREF (table, i)); j++)
330 if (EQ (val, AREF (AREF (table, i), j)))
331 return ((XINT (AREF (AREF (table, i), 0)) << 8)
332 | (i << 4) | (j - 1));
333 /* Try also with case-folding match. */
334 s = SDATA (SYMBOL_NAME (val));
335 for (i = 0; i < len; i++)
336 for (j = 1; j < ASIZE (AREF (table, i)); j++)
338 elt = AREF (AREF (table, i), j);
339 if (xstrcasecmp (s, SDATA (SYMBOL_NAME (elt))) == 0)
340 return ((XINT (AREF (AREF (table, i), 0)) << 8)
341 | (i << 4) | (j - 1));
343 if (! noerror)
344 return -1;
345 if (len == 255)
346 abort ();
347 elt = Fmake_vector (make_number (2), make_number (100));
348 ASET (elt, 1, val);
349 args[0] = table;
350 args[1] = Fmake_vector (make_number (1), elt);
351 ASET (font_style_table, prop - FONT_WEIGHT_INDEX, Fvconcat (2, args));
352 return (100 << 8) | (i << 4);
354 else
356 int i, last_n;
357 int numeric = XINT (val);
359 for (i = 0, last_n = -1; i < len; i++)
361 int n = XINT (AREF (AREF (table, i), 0));
363 if (numeric == n)
364 return (n << 8) | (i << 4);
365 if (numeric < n)
367 if (! noerror)
368 return -1;
369 return ((i == 0 || n - numeric < numeric - last_n)
370 ? (n << 8) | (i << 4): (last_n << 8 | ((i - 1) << 4)));
372 last_n = n;
374 if (! noerror)
375 return -1;
376 return ((last_n << 8) | ((i - 1) << 4));
380 Lisp_Object
381 font_style_symbolic (Lisp_Object font, enum font_property_index prop, int for_face)
383 Lisp_Object val = AREF (font, prop);
384 Lisp_Object table, elt;
385 int i;
387 if (NILP (val))
388 return Qnil;
389 table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
390 i = XINT (val) & 0xFF;
391 font_assert (((i >> 4) & 0xF) < ASIZE (table));
392 elt = AREF (table, ((i >> 4) & 0xF));
393 font_assert ((i & 0xF) + 1 < ASIZE (elt));
394 return (for_face ? AREF (elt, 1) : AREF (elt, (i & 0xF) + 1));
397 extern Lisp_Object Vface_alternative_font_family_alist;
399 extern Lisp_Object find_font_encoding (Lisp_Object);
402 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
403 FONTNAME. ENCODING is a charset symbol that specifies the encoding
404 of the font. REPERTORY is a charset symbol or nil. */
406 Lisp_Object
407 find_font_encoding (Lisp_Object fontname)
409 Lisp_Object tail, elt;
411 for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
413 elt = XCAR (tail);
414 if (CONSP (elt)
415 && STRINGP (XCAR (elt))
416 && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
417 && (SYMBOLP (XCDR (elt))
418 ? CHARSETP (XCDR (elt))
419 : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
420 return (XCDR (elt));
422 return Qnil;
425 /* Return encoding charset and repertory charset for REGISTRY in
426 ENCODING and REPERTORY correspondingly. If correct information for
427 REGISTRY is available, return 0. Otherwise return -1. */
430 font_registry_charsets (Lisp_Object registry, struct charset **encoding, struct charset **repertory)
432 Lisp_Object val;
433 int encoding_id, repertory_id;
435 val = Fassoc_string (registry, font_charset_alist, Qt);
436 if (! NILP (val))
438 val = XCDR (val);
439 if (NILP (val))
440 return -1;
441 encoding_id = XINT (XCAR (val));
442 repertory_id = XINT (XCDR (val));
444 else
446 val = find_font_encoding (SYMBOL_NAME (registry));
447 if (SYMBOLP (val) && CHARSETP (val))
449 encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val));
451 else if (CONSP (val))
453 if (! CHARSETP (XCAR (val)))
454 goto invalid_entry;
455 encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val)));
456 if (NILP (XCDR (val)))
457 repertory_id = -1;
458 else
460 if (! CHARSETP (XCDR (val)))
461 goto invalid_entry;
462 repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val)));
465 else
466 goto invalid_entry;
467 val = Fcons (make_number (encoding_id), make_number (repertory_id));
468 font_charset_alist
469 = nconc2 (font_charset_alist, Fcons (Fcons (registry, val), Qnil));
472 if (encoding)
473 *encoding = CHARSET_FROM_ID (encoding_id);
474 if (repertory)
475 *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL;
476 return 0;
478 invalid_entry:
479 font_charset_alist
480 = nconc2 (font_charset_alist, Fcons (Fcons (registry, Qnil), Qnil));
481 return -1;
485 /* Font property value validaters. See the comment of
486 font_property_table for the meaning of the arguments. */
488 static Lisp_Object font_prop_validate (int, Lisp_Object, Lisp_Object);
489 static Lisp_Object font_prop_validate_symbol (Lisp_Object, Lisp_Object);
490 static Lisp_Object font_prop_validate_style (Lisp_Object, Lisp_Object);
491 static Lisp_Object font_prop_validate_non_neg (Lisp_Object, Lisp_Object);
492 static Lisp_Object font_prop_validate_spacing (Lisp_Object, Lisp_Object);
493 static int get_font_prop_index (Lisp_Object);
495 static Lisp_Object
496 font_prop_validate_symbol (Lisp_Object prop, Lisp_Object val)
498 if (STRINGP (val))
499 val = Fintern (val, Qnil);
500 if (! SYMBOLP (val))
501 val = Qerror;
502 else if (EQ (prop, QCregistry))
503 val = Fintern (Fdowncase (SYMBOL_NAME (val)), Qnil);
504 return val;
508 static Lisp_Object
509 font_prop_validate_style (Lisp_Object style, Lisp_Object val)
511 enum font_property_index prop = (EQ (style, QCweight) ? FONT_WEIGHT_INDEX
512 : EQ (style, QCslant) ? FONT_SLANT_INDEX
513 : FONT_WIDTH_INDEX);
514 int n;
515 if (INTEGERP (val))
517 n = XINT (val);
518 if (((n >> 4) & 0xF)
519 >= ASIZE (AREF (font_style_table, prop - FONT_WEIGHT_INDEX)))
520 val = Qerror;
521 else
523 Lisp_Object elt = AREF (AREF (font_style_table, prop - FONT_WEIGHT_INDEX), (n >> 4) & 0xF);
525 if ((n & 0xF) + 1 >= ASIZE (elt))
526 val = Qerror;
527 else if (XINT (AREF (elt, 0)) != (n >> 8))
528 val = Qerror;
531 else if (SYMBOLP (val))
533 int n = font_style_to_value (prop, val, 0);
535 val = n >= 0 ? make_number (n) : Qerror;
537 else
538 val = Qerror;
539 return val;
542 static Lisp_Object
543 font_prop_validate_non_neg (Lisp_Object prop, Lisp_Object val)
545 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
546 ? val : Qerror);
549 static Lisp_Object
550 font_prop_validate_spacing (Lisp_Object prop, Lisp_Object val)
552 if (NILP (val) || (NATNUMP (val) && XINT (val) <= FONT_SPACING_CHARCELL))
553 return val;
554 if (SYMBOLP (val) && SBYTES (SYMBOL_NAME (val)) == 1)
556 char spacing = SDATA (SYMBOL_NAME (val))[0];
558 if (spacing == 'c' || spacing == 'C')
559 return make_number (FONT_SPACING_CHARCELL);
560 if (spacing == 'm' || spacing == 'M')
561 return make_number (FONT_SPACING_MONO);
562 if (spacing == 'p' || spacing == 'P')
563 return make_number (FONT_SPACING_PROPORTIONAL);
564 if (spacing == 'd' || spacing == 'D')
565 return make_number (FONT_SPACING_DUAL);
567 return Qerror;
570 static Lisp_Object
571 font_prop_validate_otf (Lisp_Object prop, Lisp_Object val)
573 Lisp_Object tail, tmp;
574 int i;
576 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
577 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
578 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
579 if (! CONSP (val))
580 return Qerror;
581 if (! SYMBOLP (XCAR (val)))
582 return Qerror;
583 tail = XCDR (val);
584 if (NILP (tail))
585 return val;
586 if (! CONSP (tail) || ! SYMBOLP (XCAR (val)))
587 return Qerror;
588 for (i = 0; i < 2; i++)
590 tail = XCDR (tail);
591 if (NILP (tail))
592 return val;
593 if (! CONSP (tail))
594 return Qerror;
595 for (tmp = XCAR (tail); CONSP (tmp); tmp = XCDR (tmp))
596 if (! SYMBOLP (XCAR (tmp)))
597 return Qerror;
598 if (! NILP (tmp))
599 return Qerror;
601 return val;
604 /* Structure of known font property keys and validater of the
605 values. */
606 struct
608 /* Pointer to the key symbol. */
609 Lisp_Object *key;
610 /* Function to validate PROP's value VAL, or NULL if any value is
611 ok. The value is VAL or its regularized value if VAL is valid,
612 and Qerror if not. */
613 Lisp_Object (*validater) (Lisp_Object prop, Lisp_Object val);
614 } font_property_table[] =
615 { { &QCtype, font_prop_validate_symbol },
616 { &QCfoundry, font_prop_validate_symbol },
617 { &QCfamily, font_prop_validate_symbol },
618 { &QCadstyle, font_prop_validate_symbol },
619 { &QCregistry, font_prop_validate_symbol },
620 { &QCweight, font_prop_validate_style },
621 { &QCslant, font_prop_validate_style },
622 { &QCwidth, font_prop_validate_style },
623 { &QCsize, font_prop_validate_non_neg },
624 { &QCdpi, font_prop_validate_non_neg },
625 { &QCspacing, font_prop_validate_spacing },
626 { &QCavgwidth, font_prop_validate_non_neg },
627 /* The order of the above entries must match with enum
628 font_property_index. */
629 { &QClang, font_prop_validate_symbol },
630 { &QCscript, font_prop_validate_symbol },
631 { &QCotf, font_prop_validate_otf }
634 /* Size (number of elements) of the above table. */
635 #define FONT_PROPERTY_TABLE_SIZE \
636 ((sizeof font_property_table) / (sizeof *font_property_table))
638 /* Return an index number of font property KEY or -1 if KEY is not an
639 already known property. */
641 static int
642 get_font_prop_index (Lisp_Object key)
644 int i;
646 for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++)
647 if (EQ (key, *font_property_table[i].key))
648 return i;
649 return -1;
652 /* Validate the font property. The property key is specified by the
653 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
654 signal an error. The value is VAL or the regularized one. */
656 static Lisp_Object
657 font_prop_validate (int idx, Lisp_Object prop, Lisp_Object val)
659 Lisp_Object validated;
661 if (NILP (val))
662 return val;
663 if (NILP (prop))
664 prop = *font_property_table[idx].key;
665 else
667 idx = get_font_prop_index (prop);
668 if (idx < 0)
669 return val;
671 validated = (font_property_table[idx].validater) (prop, val);
672 if (EQ (validated, Qerror))
673 signal_error ("invalid font property", Fcons (prop, val));
674 return validated;
678 /* Store VAL as a value of extra font property PROP in FONT while
679 keeping the sorting order. Don't check the validity of VAL. */
681 Lisp_Object
682 font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
684 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
685 Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
687 if (NILP (slot))
689 Lisp_Object prev = Qnil;
691 while (CONSP (extra)
692 && NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
693 prev = extra, extra = XCDR (extra);
695 if (NILP (prev))
696 ASET (font, FONT_EXTRA_INDEX, Fcons (Fcons (prop, val), extra));
697 else
698 XSETCDR (prev, Fcons (Fcons (prop, val), extra));
700 return val;
702 XSETCDR (slot, val);
703 if (NILP (val))
704 ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra));
705 return val;
709 /* Font name parser and unparser */
711 static int parse_matrix (char *);
712 static int font_expand_wildcards (Lisp_Object *, int);
713 static int font_parse_name (char *, Lisp_Object);
715 /* An enumerator for each field of an XLFD font name. */
716 enum xlfd_field_index
718 XLFD_FOUNDRY_INDEX,
719 XLFD_FAMILY_INDEX,
720 XLFD_WEIGHT_INDEX,
721 XLFD_SLANT_INDEX,
722 XLFD_SWIDTH_INDEX,
723 XLFD_ADSTYLE_INDEX,
724 XLFD_PIXEL_INDEX,
725 XLFD_POINT_INDEX,
726 XLFD_RESX_INDEX,
727 XLFD_RESY_INDEX,
728 XLFD_SPACING_INDEX,
729 XLFD_AVGWIDTH_INDEX,
730 XLFD_REGISTRY_INDEX,
731 XLFD_ENCODING_INDEX,
732 XLFD_LAST_INDEX
735 /* An enumerator for mask bit corresponding to each XLFD field. */
736 enum xlfd_field_mask
738 XLFD_FOUNDRY_MASK = 0x0001,
739 XLFD_FAMILY_MASK = 0x0002,
740 XLFD_WEIGHT_MASK = 0x0004,
741 XLFD_SLANT_MASK = 0x0008,
742 XLFD_SWIDTH_MASK = 0x0010,
743 XLFD_ADSTYLE_MASK = 0x0020,
744 XLFD_PIXEL_MASK = 0x0040,
745 XLFD_POINT_MASK = 0x0080,
746 XLFD_RESX_MASK = 0x0100,
747 XLFD_RESY_MASK = 0x0200,
748 XLFD_SPACING_MASK = 0x0400,
749 XLFD_AVGWIDTH_MASK = 0x0800,
750 XLFD_REGISTRY_MASK = 0x1000,
751 XLFD_ENCODING_MASK = 0x2000
755 /* Parse P pointing the pixel/point size field of the form
756 `[A B C D]' which specifies a transformation matrix:
758 A B 0
759 C D 0
760 0 0 1
762 by which all glyphs of the font are transformed. The spec says
763 that scalar value N for the pixel/point size is equivalent to:
764 A = N * resx/resy, B = C = 0, D = N.
766 Return the scalar value N if the form is valid. Otherwise return
767 -1. */
769 static int
770 parse_matrix (char *p)
772 double matrix[4];
773 char *end;
774 int i;
776 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
778 if (*p == '~')
779 matrix[i] = - strtod (p + 1, &end);
780 else
781 matrix[i] = strtod (p, &end);
782 p = end;
784 return (i == 4 ? (int) matrix[3] : -1);
787 /* Expand a wildcard field in FIELD (the first N fields are filled) to
788 multiple fields to fill in all 14 XLFD fields while restring a
789 field position by its contents. */
791 static int
792 font_expand_wildcards (Lisp_Object *field, int n)
794 /* Copy of FIELD. */
795 Lisp_Object tmp[XLFD_LAST_INDEX];
796 /* Array of information about where this element can go. Nth
797 element is for Nth element of FIELD. */
798 struct {
799 /* Minimum possible field. */
800 int from;
801 /* Maxinum possible field. */
802 int to;
803 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
804 int mask;
805 } range[XLFD_LAST_INDEX];
806 int i, j;
807 int range_from, range_to;
808 unsigned range_mask;
810 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
811 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
812 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
813 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
814 | XLFD_AVGWIDTH_MASK)
815 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
817 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
818 field. The value is shifted to left one bit by one in the
819 following loop. */
820 for (i = 0, range_mask = 0; i <= 14 - n; i++)
821 range_mask = (range_mask << 1) | 1;
823 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
824 position-based retriction for FIELD[I]. */
825 for (i = 0, range_from = 0, range_to = 14 - n; i < n;
826 i++, range_from++, range_to++, range_mask <<= 1)
828 Lisp_Object val = field[i];
830 tmp[i] = val;
831 if (NILP (val))
833 /* Wildcard. */
834 range[i].from = range_from;
835 range[i].to = range_to;
836 range[i].mask = range_mask;
838 else
840 /* The triplet FROM, TO, and MASK is a value-based
841 retriction for FIELD[I]. */
842 int from, to;
843 unsigned mask;
845 if (INTEGERP (val))
847 int numeric = XINT (val);
849 if (i + 1 == n)
850 from = to = XLFD_ENCODING_INDEX,
851 mask = XLFD_ENCODING_MASK;
852 else if (numeric == 0)
853 from = XLFD_PIXEL_INDEX, to = XLFD_AVGWIDTH_INDEX,
854 mask = XLFD_PIXEL_MASK | XLFD_LARGENUM_MASK;
855 else if (numeric <= 48)
856 from = to = XLFD_PIXEL_INDEX,
857 mask = XLFD_PIXEL_MASK;
858 else
859 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
860 mask = XLFD_LARGENUM_MASK;
862 else if (SBYTES (SYMBOL_NAME (val)) == 0)
863 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
864 mask = XLFD_NULL_MASK;
865 else if (i == 0)
866 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
867 else if (i + 1 == n)
869 Lisp_Object name = SYMBOL_NAME (val);
871 if (SDATA (name)[SBYTES (name) - 1] == '*')
872 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
873 mask = XLFD_REGENC_MASK;
874 else
875 from = to = XLFD_ENCODING_INDEX,
876 mask = XLFD_ENCODING_MASK;
878 else if (range_from <= XLFD_WEIGHT_INDEX
879 && range_to >= XLFD_WEIGHT_INDEX
880 && FONT_WEIGHT_NAME_NUMERIC (val) >= 0)
881 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
882 else if (range_from <= XLFD_SLANT_INDEX
883 && range_to >= XLFD_SLANT_INDEX
884 && FONT_SLANT_NAME_NUMERIC (val) >= 0)
885 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
886 else if (range_from <= XLFD_SWIDTH_INDEX
887 && range_to >= XLFD_SWIDTH_INDEX
888 && FONT_WIDTH_NAME_NUMERIC (val) >= 0)
889 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
890 else
892 if (EQ (val, Qc) || EQ (val, Qm) || EQ (val, Qp) || EQ (val, Qd))
893 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
894 else
895 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
896 mask = XLFD_SYMBOL_MASK;
899 /* Merge position-based and value-based restrictions. */
900 mask &= range_mask;
901 while (from < range_from)
902 mask &= ~(1 << from++);
903 while (from < 14 && ! (mask & (1 << from)))
904 from++;
905 while (to > range_to)
906 mask &= ~(1 << to--);
907 while (to >= 0 && ! (mask & (1 << to)))
908 to--;
909 if (from > to)
910 return -1;
911 range[i].from = from;
912 range[i].to = to;
913 range[i].mask = mask;
915 if (from > range_from || to < range_to)
917 /* The range is narrowed by value-based restrictions.
918 Reflect it to the other fields. */
920 /* Following fields should be after FROM. */
921 range_from = from;
922 /* Preceding fields should be before TO. */
923 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
925 /* Check FROM for non-wildcard field. */
926 if (! NILP (tmp[j]) && range[j].from < from)
928 while (range[j].from < from)
929 range[j].mask &= ~(1 << range[j].from++);
930 while (from < 14 && ! (range[j].mask & (1 << from)))
931 from++;
932 range[j].from = from;
934 else
935 from = range[j].from;
936 if (range[j].to > to)
938 while (range[j].to > to)
939 range[j].mask &= ~(1 << range[j].to--);
940 while (to >= 0 && ! (range[j].mask & (1 << to)))
941 to--;
942 range[j].to = to;
944 else
945 to = range[j].to;
946 if (from > to)
947 return -1;
953 /* Decide all fileds from restrictions in RANGE. */
954 for (i = j = 0; i < n ; i++)
956 if (j < range[i].from)
958 if (i == 0 || ! NILP (tmp[i - 1]))
959 /* None of TMP[X] corresponds to Jth field. */
960 return -1;
961 for (; j < range[i].from; j++)
962 field[j] = Qnil;
964 field[j++] = tmp[i];
966 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
967 return -1;
968 for (; j < XLFD_LAST_INDEX; j++)
969 field[j] = Qnil;
970 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
971 field[XLFD_ENCODING_INDEX]
972 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
973 return 0;
977 /* Parse NAME (null terminated) as XLFD and store information in FONT
978 (font-spec or font-entity). Size property of FONT is set as
979 follows:
980 specified XLFD fields FONT property
981 --------------------- -------------
982 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
983 POINT_SIZE and RESY calculated pixel size (Lisp integer)
984 POINT_SIZE POINT_SIZE/10 (Lisp float)
986 If NAME is successfully parsed, return 0. Otherwise return -1.
988 FONT is usually a font-spec, but when this function is called from
989 X font backend driver, it is a font-entity. In that case, NAME is
990 a fully specified XLFD. */
993 font_parse_xlfd (char *name, Lisp_Object font)
995 int len = strlen (name);
996 int i, j, n;
997 char *f[XLFD_LAST_INDEX + 1];
998 Lisp_Object val;
999 char *p;
1001 if (len > 255 || !len)
1002 /* Maximum XLFD name length is 255. */
1003 return -1;
1004 /* Accept "*-.." as a fully specified XLFD. */
1005 if (name[0] == '*' && (len == 1 || name[1] == '-'))
1006 i = 1, f[XLFD_FOUNDRY_INDEX] = name;
1007 else
1008 i = 0;
1009 for (p = name + i; *p; p++)
1010 if (*p == '-')
1012 f[i++] = p + 1;
1013 if (i == XLFD_LAST_INDEX)
1014 break;
1016 f[i] = name + len;
1018 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1019 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1021 if (i == XLFD_LAST_INDEX)
1023 /* Fully specified XLFD. */
1024 int pixel_size;
1026 ASET (font, FONT_FOUNDRY_INDEX, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX));
1027 ASET (font, FONT_FAMILY_INDEX, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX));
1028 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1029 i <= XLFD_SWIDTH_INDEX; i++, j++)
1031 val = INTERN_FIELD_SYM (i);
1032 if (! NILP (val))
1034 if ((n = font_style_to_value (j, INTERN_FIELD_SYM (i), 0)) < 0)
1035 return -1;
1036 ASET (font, j, make_number (n));
1039 ASET (font, FONT_ADSTYLE_INDEX, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX));
1040 if (strcmp (f[XLFD_REGISTRY_INDEX], "*-*") == 0)
1041 ASET (font, FONT_REGISTRY_INDEX, Qnil);
1042 else
1043 ASET (font, FONT_REGISTRY_INDEX,
1044 font_intern_prop (f[XLFD_REGISTRY_INDEX],
1045 f[XLFD_LAST_INDEX] - f[XLFD_REGISTRY_INDEX],
1046 1));
1047 p = f[XLFD_PIXEL_INDEX];
1048 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
1049 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
1050 else
1052 val = INTERN_FIELD (XLFD_PIXEL_INDEX);
1053 if (INTEGERP (val))
1054 ASET (font, FONT_SIZE_INDEX, val);
1055 else if (FONT_ENTITY_P (font))
1056 return -1;
1057 else
1059 double point_size = -1;
1061 font_assert (FONT_SPEC_P (font));
1062 p = f[XLFD_POINT_INDEX];
1063 if (*p == '[')
1064 point_size = parse_matrix (p);
1065 else if (isdigit (*p))
1066 point_size = atoi (p), point_size /= 10;
1067 if (point_size >= 0)
1068 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1072 val = INTERN_FIELD (XLFD_RESY_INDEX);
1073 if (! NILP (val) && ! INTEGERP (val))
1074 return -1;
1075 ASET (font, FONT_DPI_INDEX, val);
1076 val = INTERN_FIELD (XLFD_SPACING_INDEX);
1077 if (! NILP (val))
1079 val = font_prop_validate_spacing (QCspacing, val);
1080 if (! INTEGERP (val))
1081 return -1;
1082 ASET (font, FONT_SPACING_INDEX, val);
1084 p = f[XLFD_AVGWIDTH_INDEX];
1085 if (*p == '~')
1086 p++;
1087 val = font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p, 0);
1088 if (! NILP (val) && ! INTEGERP (val))
1089 return -1;
1090 ASET (font, FONT_AVGWIDTH_INDEX, val);
1092 else
1094 int wild_card_found = 0;
1095 Lisp_Object prop[XLFD_LAST_INDEX];
1097 if (FONT_ENTITY_P (font))
1098 return -1;
1099 for (j = 0; j < i; j++)
1101 if (*f[j] == '*')
1103 if (f[j][1] && f[j][1] != '-')
1104 return -1;
1105 prop[j] = Qnil;
1106 wild_card_found = 1;
1108 else if (j + 1 < i)
1109 prop[j] = INTERN_FIELD (j);
1110 else
1111 prop[j] = font_intern_prop (f[j], f[i] - f[j], 0);
1113 if (! wild_card_found)
1114 return -1;
1115 if (font_expand_wildcards (prop, i) < 0)
1116 return -1;
1118 ASET (font, FONT_FOUNDRY_INDEX, prop[XLFD_FOUNDRY_INDEX]);
1119 ASET (font, FONT_FAMILY_INDEX, prop[XLFD_FAMILY_INDEX]);
1120 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1121 i <= XLFD_SWIDTH_INDEX; i++, j++)
1122 if (! NILP (prop[i]))
1124 if ((n = font_style_to_value (j, prop[i], 1)) < 0)
1125 return -1;
1126 ASET (font, j, make_number (n));
1128 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1129 val = prop[XLFD_REGISTRY_INDEX];
1130 if (NILP (val))
1132 val = prop[XLFD_ENCODING_INDEX];
1133 if (! NILP (val))
1134 val = concat2 (build_string ("*-"), SYMBOL_NAME (val));
1136 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1137 val = concat2 (SYMBOL_NAME (val), build_string ("-*"));
1138 else
1139 val = concat3 (SYMBOL_NAME (val), build_string ("-"),
1140 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX]));
1141 if (! NILP (val))
1142 ASET (font, FONT_REGISTRY_INDEX, Fintern (val, Qnil));
1144 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1145 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
1146 else if (INTEGERP (prop[XLFD_POINT_INDEX]))
1148 double point_size = XINT (prop[XLFD_POINT_INDEX]);
1150 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1153 if (INTEGERP (prop[XLFD_RESX_INDEX]))
1154 ASET (font, FONT_DPI_INDEX, prop[XLFD_RESY_INDEX]);
1155 if (! NILP (prop[XLFD_SPACING_INDEX]))
1157 val = font_prop_validate_spacing (QCspacing,
1158 prop[XLFD_SPACING_INDEX]);
1159 if (! INTEGERP (val))
1160 return -1;
1161 ASET (font, FONT_SPACING_INDEX, val);
1163 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1164 ASET (font, FONT_AVGWIDTH_INDEX, prop[XLFD_AVGWIDTH_INDEX]);
1167 return 0;
1170 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1171 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1172 0, use PIXEL_SIZE instead. */
1175 font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
1177 char *f[XLFD_REGISTRY_INDEX + 1];
1178 Lisp_Object val;
1179 int i, j, len = 0;
1181 font_assert (FONTP (font));
1183 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
1184 i++, j++)
1186 if (i == FONT_ADSTYLE_INDEX)
1187 j = XLFD_ADSTYLE_INDEX;
1188 else if (i == FONT_REGISTRY_INDEX)
1189 j = XLFD_REGISTRY_INDEX;
1190 val = AREF (font, i);
1191 if (NILP (val))
1193 if (j == XLFD_REGISTRY_INDEX)
1194 f[j] = "*-*", len += 4;
1195 else
1196 f[j] = "*", len += 2;
1198 else
1200 if (SYMBOLP (val))
1201 val = SYMBOL_NAME (val);
1202 if (j == XLFD_REGISTRY_INDEX
1203 && ! strchr ((char *) SDATA (val), '-'))
1205 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1206 if (SDATA (val)[SBYTES (val) - 1] == '*')
1208 f[j] = alloca (SBYTES (val) + 3);
1209 sprintf (f[j], "%s-*", SDATA (val));
1210 len += SBYTES (val) + 3;
1212 else
1214 f[j] = alloca (SBYTES (val) + 4);
1215 sprintf (f[j], "%s*-*", SDATA (val));
1216 len += SBYTES (val) + 4;
1219 else
1220 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1224 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1225 i++, j++)
1227 val = font_style_symbolic (font, i, 0);
1228 if (NILP (val))
1229 f[j] = "*", len += 2;
1230 else
1232 val = SYMBOL_NAME (val);
1233 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1237 val = AREF (font, FONT_SIZE_INDEX);
1238 font_assert (NUMBERP (val) || NILP (val));
1239 if (INTEGERP (val))
1241 i = XINT (val);
1242 if (i <= 0)
1243 i = pixel_size;
1244 if (i > 0)
1246 f[XLFD_PIXEL_INDEX] = alloca (22);
1247 len += sprintf (f[XLFD_PIXEL_INDEX], "%d-*", i) + 1;
1249 else
1250 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1252 else if (FLOATP (val))
1254 i = XFLOAT_DATA (val) * 10;
1255 f[XLFD_PIXEL_INDEX] = alloca (12);
1256 len += sprintf (f[XLFD_PIXEL_INDEX], "*-%d", i) + 1;
1258 else
1259 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1261 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1263 i = XINT (AREF (font, FONT_DPI_INDEX));
1264 f[XLFD_RESX_INDEX] = alloca (22);
1265 len += sprintf (f[XLFD_RESX_INDEX],
1266 "%d-%d", i, i) + 1;
1268 else
1269 f[XLFD_RESX_INDEX] = "*-*", len += 4;
1270 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1272 int spacing = XINT (AREF (font, FONT_SPACING_INDEX));
1274 f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
1275 : spacing <= FONT_SPACING_DUAL ? "d"
1276 : spacing <= FONT_SPACING_MONO ? "m"
1277 : "c");
1278 len += 2;
1280 else
1281 f[XLFD_SPACING_INDEX] = "*", len += 2;
1282 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1284 f[XLFD_AVGWIDTH_INDEX] = alloca (11);
1285 len += sprintf (f[XLFD_AVGWIDTH_INDEX], "%ld",
1286 (long) XINT (AREF (font, FONT_AVGWIDTH_INDEX))) + 1;
1288 else
1289 f[XLFD_AVGWIDTH_INDEX] = "*", len += 2;
1290 len++; /* for terminating '\0'. */
1291 if (len >= nbytes)
1292 return -1;
1293 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1294 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1295 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1296 f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
1297 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
1298 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
1299 f[XLFD_REGISTRY_INDEX]);
1302 /* Parse NAME (null terminated) and store information in FONT
1303 (font-spec or font-entity). NAME is supplied in either the
1304 Fontconfig or GTK font name format. If NAME is successfully
1305 parsed, return 0. Otherwise return -1.
1307 The fontconfig format is
1309 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1311 The GTK format is
1313 FAMILY [PROPS...] [SIZE]
1315 This function tries to guess which format it is. */
1318 font_parse_fcname (char *name, Lisp_Object font)
1320 char *p, *q;
1321 char *size_beg = NULL, *size_end = NULL;
1322 char *props_beg = NULL, *family_end = NULL;
1323 int len = strlen (name);
1325 if (len == 0)
1326 return -1;
1328 for (p = name; *p; p++)
1330 if (*p == '\\' && p[1])
1331 p++;
1332 else if (*p == ':')
1334 props_beg = family_end = p;
1335 break;
1337 else if (*p == '-')
1339 int decimal = 0, size_found = 1;
1340 for (q = p + 1; *q && *q != ':'; q++)
1341 if (! isdigit(*q))
1343 if (*q != '.' || decimal)
1345 size_found = 0;
1346 break;
1348 decimal = 1;
1350 if (size_found)
1352 family_end = p;
1353 size_beg = p + 1;
1354 size_end = q;
1355 break;
1360 if (family_end)
1362 Lisp_Object extra_props = Qnil;
1364 /* A fontconfig name with size and/or property data. */
1365 if (family_end > name)
1367 Lisp_Object family;
1368 family = font_intern_prop (name, family_end - name, 1);
1369 ASET (font, FONT_FAMILY_INDEX, family);
1371 if (size_beg)
1373 double point_size = strtod (size_beg, &size_end);
1374 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1375 if (*size_end == ':' && size_end[1])
1376 props_beg = size_end;
1378 if (props_beg)
1380 /* Now parse ":KEY=VAL" patterns. */
1381 Lisp_Object val;
1383 for (p = props_beg; *p; p = q)
1385 for (q = p + 1; *q && *q != '=' && *q != ':'; q++);
1386 if (*q != '=')
1388 /* Must be an enumerated value. */
1389 int word_len;
1390 p = p + 1;
1391 word_len = q - p;
1392 val = font_intern_prop (p, q - p, 1);
1394 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1396 if (PROP_MATCH ("light", 5)
1397 || PROP_MATCH ("medium", 6)
1398 || PROP_MATCH ("demibold", 8)
1399 || PROP_MATCH ("bold", 4)
1400 || PROP_MATCH ("black", 5))
1401 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
1402 else if (PROP_MATCH ("roman", 5)
1403 || PROP_MATCH ("italic", 6)
1404 || PROP_MATCH ("oblique", 7))
1405 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
1406 else if (PROP_MATCH ("charcell", 8))
1407 ASET (font, FONT_SPACING_INDEX,
1408 make_number (FONT_SPACING_CHARCELL));
1409 else if (PROP_MATCH ("mono", 4))
1410 ASET (font, FONT_SPACING_INDEX,
1411 make_number (FONT_SPACING_MONO));
1412 else if (PROP_MATCH ("proportional", 12))
1413 ASET (font, FONT_SPACING_INDEX,
1414 make_number (FONT_SPACING_PROPORTIONAL));
1415 #undef PROP_MATCH
1417 else
1419 /* KEY=VAL pairs */
1420 Lisp_Object key;
1421 int prop;
1423 if (q - p == 10 && memcmp (p + 1, "pixelsize", 9) == 0)
1424 prop = FONT_SIZE_INDEX;
1425 else
1427 key = font_intern_prop (p, q - p, 1);
1428 prop = get_font_prop_index (key);
1431 p = q + 1;
1432 for (q = p; *q && *q != ':'; q++);
1433 val = font_intern_prop (p, q - p, 0);
1435 if (prop >= FONT_FOUNDRY_INDEX
1436 && prop < FONT_EXTRA_INDEX)
1437 ASET (font, prop, font_prop_validate (prop, Qnil, val));
1438 else
1440 extra_props = nconc2 (extra_props,
1441 Fcons (Fcons (key, val), Qnil));
1444 p = q;
1448 if (! NILP (extra_props))
1450 struct font_driver_list *driver_list = font_driver_list;
1451 for ( ; driver_list; driver_list = driver_list->next)
1452 if (driver_list->driver->filter_properties)
1453 (*driver_list->driver->filter_properties) (font, extra_props);
1457 else
1459 /* Either a fontconfig-style name with no size and property
1460 data, or a GTK-style name. */
1461 Lisp_Object prop;
1462 int word_len, prop_found = 0;
1464 for (p = name; *p; p = *q ? q + 1 : q)
1466 if (isdigit (*p))
1468 int size_found = 1;
1470 for (q = p + 1; *q && *q != ' '; q++)
1471 if (! isdigit (*q) && *q != '.')
1473 size_found = 0;
1474 break;
1476 if (size_found)
1478 double point_size = strtod (p, &q);
1479 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1480 continue;
1484 for (q = p + 1; *q && *q != ' '; q++)
1485 if (*q == '\\' && q[1])
1486 q++;
1487 word_len = q - p;
1489 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1491 if (PROP_MATCH ("Ultra-Light", 11))
1493 prop_found = 1;
1494 prop = font_intern_prop ("ultra-light", 11, 1);
1495 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1497 else if (PROP_MATCH ("Light", 5))
1499 prop_found = 1;
1500 prop = font_intern_prop ("light", 5, 1);
1501 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1503 else if (PROP_MATCH ("Book", 4))
1505 prop_found = 1;
1506 prop = font_intern_prop ("book", 4, 1);
1507 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1509 else if (PROP_MATCH ("Medium", 6))
1511 prop_found = 1;
1512 prop = font_intern_prop ("medium", 6, 1);
1513 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1515 else if (PROP_MATCH ("Semi-Bold", 9))
1517 prop_found = 1;
1518 prop = font_intern_prop ("semi-bold", 9, 1);
1519 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1521 else if (PROP_MATCH ("Bold", 4))
1523 prop_found = 1;
1524 prop = font_intern_prop ("bold", 4, 1);
1525 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1527 else if (PROP_MATCH ("Italic", 6))
1529 prop_found = 1;
1530 prop = font_intern_prop ("italic", 4, 1);
1531 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
1533 else if (PROP_MATCH ("Oblique", 7))
1535 prop_found = 1;
1536 prop = font_intern_prop ("oblique", 7, 1);
1537 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
1539 else if (PROP_MATCH ("Semi-Condensed", 14))
1541 prop_found = 1;
1542 prop = font_intern_prop ("semi-condensed", 14, 1);
1543 FONT_SET_STYLE (font, FONT_WIDTH_INDEX, prop);
1545 else if (PROP_MATCH ("Condensed", 9))
1547 prop_found = 1;
1548 prop = font_intern_prop ("condensed", 9, 1);
1549 FONT_SET_STYLE (font, FONT_WIDTH_INDEX, prop);
1551 else {
1552 if (prop_found)
1553 return -1; /* Unknown property in GTK-style font name. */
1554 family_end = q;
1557 #undef PROP_MATCH
1559 if (family_end)
1561 Lisp_Object family;
1562 family = font_intern_prop (name, family_end - name, 1);
1563 ASET (font, FONT_FAMILY_INDEX, family);
1567 return 0;
1570 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1571 NAME (NBYTES length), and return the name length. If
1572 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1575 font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes)
1577 Lisp_Object family, foundry;
1578 Lisp_Object tail, val;
1579 int point_size;
1580 int i, len = 1;
1581 char *p;
1582 Lisp_Object styles[3];
1583 char *style_names[3] = { "weight", "slant", "width" };
1584 char work[256];
1586 family = AREF (font, FONT_FAMILY_INDEX);
1587 if (! NILP (family))
1589 if (SYMBOLP (family))
1591 family = SYMBOL_NAME (family);
1592 len += SBYTES (family);
1594 else
1595 family = Qnil;
1598 val = AREF (font, FONT_SIZE_INDEX);
1599 if (INTEGERP (val))
1601 if (XINT (val) != 0)
1602 pixel_size = XINT (val);
1603 point_size = -1;
1604 len += 21; /* for ":pixelsize=NUM" */
1606 else if (FLOATP (val))
1608 pixel_size = -1;
1609 point_size = (int) XFLOAT_DATA (val);
1610 len += 11; /* for "-NUM" */
1613 foundry = AREF (font, FONT_FOUNDRY_INDEX);
1614 if (! NILP (foundry))
1616 if (SYMBOLP (foundry))
1618 foundry = SYMBOL_NAME (foundry);
1619 len += 9 + SBYTES (foundry); /* ":foundry=NAME" */
1621 else
1622 foundry = Qnil;
1625 for (i = 0; i < 3; i++)
1627 styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
1628 if (! NILP (styles[i]))
1629 len += sprintf (work, ":%s=%s", style_names[i],
1630 SDATA (SYMBOL_NAME (styles[i])));
1633 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1634 len += sprintf (work, ":dpi=%ld", (long)XINT (AREF (font, FONT_DPI_INDEX)));
1635 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1636 len += strlen (":spacing=100");
1637 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1638 len += strlen (":scalable=false"); /* or ":scalable=true" */
1639 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
1641 Lisp_Object key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
1643 len += SBYTES (SYMBOL_NAME (key)) + 1; /* for :KEY= */
1644 if (STRINGP (val))
1645 len += SBYTES (val);
1646 else if (INTEGERP (val))
1647 len += sprintf (work, "%ld", (long) XINT (val));
1648 else if (SYMBOLP (val))
1649 len += (NILP (val) ? 5 : 4); /* for "false" or "true" */
1652 if (len > nbytes)
1653 return -1;
1654 p = name;
1655 if (! NILP (family))
1656 p += sprintf (p, "%s", SDATA (family));
1657 if (point_size > 0)
1659 if (p == name)
1660 p += sprintf (p, "%d", point_size);
1661 else
1662 p += sprintf (p, "-%d", point_size);
1664 else if (pixel_size > 0)
1665 p += sprintf (p, ":pixelsize=%d", pixel_size);
1666 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1667 p += sprintf (p, ":foundry=%s",
1668 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1669 for (i = 0; i < 3; i++)
1670 if (! NILP (styles[i]))
1671 p += sprintf (p, ":%s=%s", style_names[i],
1672 SDATA (SYMBOL_NAME (styles[i])));
1673 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1674 p += sprintf (p, ":dpi=%ld", (long) XINT (AREF (font, FONT_DPI_INDEX)));
1675 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1676 p += sprintf (p, ":spacing=%ld",
1677 (long) XINT (AREF (font, FONT_SPACING_INDEX)));
1678 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1680 if (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0)
1681 p += sprintf (p, ":scalable=true");
1682 else
1683 p += sprintf (p, ":scalable=false");
1685 return (p - name);
1688 /* Store GTK-style font name of FONT (font-spec or font-entity) in
1689 NAME (NBYTES length), and return the name length. F is the frame
1690 on which the font is displayed; it is used to calculate the point
1691 size. */
1694 font_unparse_gtkname (Lisp_Object font, struct frame *f, char *name, int nbytes)
1696 char *p;
1697 int len = 1;
1698 Lisp_Object family, weight, slant, size;
1699 int point_size = -1;
1701 family = AREF (font, FONT_FAMILY_INDEX);
1702 if (! NILP (family))
1704 if (! SYMBOLP (family))
1705 return -1;
1706 family = SYMBOL_NAME (family);
1707 len += SBYTES (family);
1710 weight = font_style_symbolic (font, FONT_WEIGHT_INDEX, 0);
1711 if (EQ (weight, Qnormal))
1712 weight = Qnil;
1713 else if (! NILP (weight))
1715 weight = SYMBOL_NAME (weight);
1716 len += SBYTES (weight);
1719 slant = font_style_symbolic (font, FONT_SLANT_INDEX, 0);
1720 if (EQ (slant, Qnormal))
1721 slant = Qnil;
1722 else if (! NILP (slant))
1724 slant = SYMBOL_NAME (slant);
1725 len += SBYTES (slant);
1728 size = AREF (font, FONT_SIZE_INDEX);
1729 /* Convert pixel size to point size. */
1730 if (INTEGERP (size))
1732 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
1733 int dpi = 75;
1734 if (INTEGERP (font_dpi))
1735 dpi = XINT (font_dpi);
1736 else if (f)
1737 dpi = f->resy;
1738 point_size = PIXEL_TO_POINT (XINT (size), dpi);
1739 len += 11;
1741 else if (FLOATP (size))
1743 point_size = (int) XFLOAT_DATA (size);
1744 len += 11;
1747 if (len > nbytes)
1748 return -1;
1750 p = name + sprintf (name, "%s", SDATA (family));
1752 if (! NILP (weight))
1754 char *q = p;
1755 p += sprintf (p, " %s", SDATA (weight));
1756 q[1] = toupper (q[1]);
1759 if (! NILP (slant))
1761 char *q = p;
1762 p += sprintf (p, " %s", SDATA (slant));
1763 q[1] = toupper (q[1]);
1766 if (point_size > 0)
1767 p += sprintf (p, " %d", point_size);
1769 return (p - name);
1772 /* Parse NAME (null terminated) and store information in FONT
1773 (font-spec or font-entity). If NAME is successfully parsed, return
1774 0. Otherwise return -1. */
1776 static int
1777 font_parse_name (char *name, Lisp_Object font)
1779 if (name[0] == '-' || strchr (name, '*') || strchr (name, '?'))
1780 return font_parse_xlfd (name, font);
1781 return font_parse_fcname (name, font);
1785 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1786 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1787 part. */
1789 void
1790 font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Object font_spec)
1792 int len;
1793 char *p0, *p1;
1795 if (! NILP (family)
1796 && NILP (AREF (font_spec, FONT_FAMILY_INDEX)))
1798 CHECK_STRING (family);
1799 len = SBYTES (family);
1800 p0 = (char *) SDATA (family);
1801 p1 = strchr (p0, '-');
1802 if (p1)
1804 if ((*p0 != '*' && p1 - p0 > 0)
1805 && NILP (AREF (font_spec, FONT_FOUNDRY_INDEX)))
1806 Ffont_put (font_spec, QCfoundry, font_intern_prop (p0, p1 - p0, 1));
1807 p1++;
1808 len -= p1 - p0;
1809 Ffont_put (font_spec, QCfamily, font_intern_prop (p1, len, 1));
1811 else
1812 ASET (font_spec, FONT_FAMILY_INDEX, Fintern (family, Qnil));
1814 if (! NILP (registry))
1816 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1817 CHECK_STRING (registry);
1818 len = SBYTES (registry);
1819 p0 = (char *) SDATA (registry);
1820 p1 = strchr (p0, '-');
1821 if (! p1)
1823 if (SDATA (registry)[len - 1] == '*')
1824 registry = concat2 (registry, build_string ("-*"));
1825 else
1826 registry = concat2 (registry, build_string ("*-*"));
1828 registry = Fdowncase (registry);
1829 ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil));
1834 /* This part (through the next ^L) is still experimental and not
1835 tested much. We may drastically change codes. */
1837 /* OTF handler */
1839 #if 0
1841 #define LGSTRING_HEADER_SIZE 6
1842 #define LGSTRING_GLYPH_SIZE 8
1844 static int
1845 check_gstring (gstring)
1846 Lisp_Object gstring;
1848 Lisp_Object val;
1849 int i, j;
1851 CHECK_VECTOR (gstring);
1852 val = AREF (gstring, 0);
1853 CHECK_VECTOR (val);
1854 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1855 goto err;
1856 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1857 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1858 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1859 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1860 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1861 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1862 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1863 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1864 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1865 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1866 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1868 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
1870 val = LGSTRING_GLYPH (gstring, i);
1871 CHECK_VECTOR (val);
1872 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1873 goto err;
1874 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1875 break;
1876 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1877 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1878 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1879 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1880 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1881 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1882 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1883 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1885 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1886 CHECK_VECTOR (val);
1887 if (ASIZE (val) < 3)
1888 goto err;
1889 for (j = 0; j < 3; j++)
1890 CHECK_NUMBER (AREF (val, j));
1893 return i;
1894 err:
1895 error ("Invalid glyph-string format");
1896 return -1;
1899 static void
1900 check_otf_features (otf_features)
1901 Lisp_Object otf_features;
1903 Lisp_Object val;
1905 CHECK_CONS (otf_features);
1906 CHECK_SYMBOL (XCAR (otf_features));
1907 otf_features = XCDR (otf_features);
1908 CHECK_CONS (otf_features);
1909 CHECK_SYMBOL (XCAR (otf_features));
1910 otf_features = XCDR (otf_features);
1911 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1913 CHECK_SYMBOL (Fcar (val));
1914 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1915 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val)));
1917 otf_features = XCDR (otf_features);
1918 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1920 CHECK_SYMBOL (Fcar (val));
1921 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1922 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val)));
1926 #ifdef HAVE_LIBOTF
1927 #include <otf.h>
1929 Lisp_Object otf_list;
1931 static Lisp_Object
1932 otf_tag_symbol (tag)
1933 OTF_Tag tag;
1935 char name[5];
1937 OTF_tag_name (tag, name);
1938 return Fintern (make_unibyte_string (name, 4), Qnil);
1941 static OTF *
1942 otf_open (file)
1943 Lisp_Object file;
1945 Lisp_Object val = Fassoc (file, otf_list);
1946 OTF *otf;
1948 if (! NILP (val))
1949 otf = XSAVE_VALUE (XCDR (val))->pointer;
1950 else
1952 otf = STRINGP (file) ? OTF_open ((char *) SDATA (file)) : NULL;
1953 val = make_save_value (otf, 0);
1954 otf_list = Fcons (Fcons (file, val), otf_list);
1956 return otf;
1960 /* Return a list describing which scripts/languages FONT supports by
1961 which GSUB/GPOS features of OpenType tables. See the comment of
1962 (struct font_driver).otf_capability. */
1964 Lisp_Object
1965 font_otf_capability (font)
1966 struct font *font;
1968 OTF *otf;
1969 Lisp_Object capability = Fcons (Qnil, Qnil);
1970 int i;
1972 otf = otf_open (font->props[FONT_FILE_INDEX]);
1973 if (! otf)
1974 return Qnil;
1975 for (i = 0; i < 2; i++)
1977 OTF_GSUB_GPOS *gsub_gpos;
1978 Lisp_Object script_list = Qnil;
1979 int j;
1981 if (OTF_get_features (otf, i == 0) < 0)
1982 continue;
1983 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1984 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1986 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1987 Lisp_Object langsys_list = Qnil;
1988 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1989 int k;
1991 for (k = script->LangSysCount; k >= 0; k--)
1993 OTF_LangSys *langsys;
1994 Lisp_Object feature_list = Qnil;
1995 Lisp_Object langsys_tag;
1996 int l;
1998 if (k == script->LangSysCount)
2000 langsys = &script->DefaultLangSys;
2001 langsys_tag = Qnil;
2003 else
2005 langsys = script->LangSys + k;
2006 langsys_tag
2007 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
2009 for (l = langsys->FeatureCount - 1; l >= 0; l--)
2011 OTF_Feature *feature
2012 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
2013 Lisp_Object feature_tag
2014 = otf_tag_symbol (feature->FeatureTag);
2016 feature_list = Fcons (feature_tag, feature_list);
2018 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
2019 langsys_list);
2021 script_list = Fcons (Fcons (script_tag, langsys_list),
2022 script_list);
2025 if (i == 0)
2026 XSETCAR (capability, script_list);
2027 else
2028 XSETCDR (capability, script_list);
2031 return capability;
2034 /* Parse OTF features in SPEC and write a proper features spec string
2035 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
2036 assured that the sufficient memory has already allocated for
2037 FEATURES. */
2039 static void
2040 generate_otf_features (spec, features)
2041 Lisp_Object spec;
2042 char *features;
2044 Lisp_Object val;
2045 char *p;
2046 int asterisk;
2048 p = features;
2049 *p = '\0';
2050 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
2052 val = XCAR (spec);
2053 CHECK_SYMBOL (val);
2054 if (p > features)
2055 *p++ = ',';
2056 if (SREF (SYMBOL_NAME (val), 0) == '*')
2058 asterisk = 1;
2059 *p++ = '*';
2061 else if (! asterisk)
2063 val = SYMBOL_NAME (val);
2064 p += sprintf (p, "%s", SDATA (val));
2066 else
2068 val = SYMBOL_NAME (val);
2069 p += sprintf (p, "~%s", SDATA (val));
2072 if (CONSP (spec))
2073 error ("OTF spec too long");
2076 Lisp_Object
2077 font_otf_DeviceTable (device_table)
2078 OTF_DeviceTable *device_table;
2080 int len = device_table->StartSize - device_table->EndSize + 1;
2082 return Fcons (make_number (len),
2083 make_unibyte_string (device_table->DeltaValue, len));
2086 Lisp_Object
2087 font_otf_ValueRecord (value_format, value_record)
2088 int value_format;
2089 OTF_ValueRecord *value_record;
2091 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
2093 if (value_format & OTF_XPlacement)
2094 ASET (val, 0, make_number (value_record->XPlacement));
2095 if (value_format & OTF_YPlacement)
2096 ASET (val, 1, make_number (value_record->YPlacement));
2097 if (value_format & OTF_XAdvance)
2098 ASET (val, 2, make_number (value_record->XAdvance));
2099 if (value_format & OTF_YAdvance)
2100 ASET (val, 3, make_number (value_record->YAdvance));
2101 if (value_format & OTF_XPlaDevice)
2102 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
2103 if (value_format & OTF_YPlaDevice)
2104 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
2105 if (value_format & OTF_XAdvDevice)
2106 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
2107 if (value_format & OTF_YAdvDevice)
2108 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
2109 return val;
2112 Lisp_Object
2113 font_otf_Anchor (anchor)
2114 OTF_Anchor *anchor;
2116 Lisp_Object val;
2118 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
2119 ASET (val, 0, make_number (anchor->XCoordinate));
2120 ASET (val, 1, make_number (anchor->YCoordinate));
2121 if (anchor->AnchorFormat == 2)
2122 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
2123 else
2125 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
2126 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
2128 return val;
2130 #endif /* HAVE_LIBOTF */
2131 #endif /* 0 */
2134 /* Font sorting */
2136 static unsigned font_score (Lisp_Object, Lisp_Object *);
2137 static int font_compare (const void *, const void *);
2138 static Lisp_Object font_sort_entities (Lisp_Object, Lisp_Object,
2139 Lisp_Object, int);
2141 /* Return a rescaling ratio of FONT_ENTITY. */
2142 extern Lisp_Object Vface_font_rescale_alist;
2144 static double
2145 font_rescale_ratio (Lisp_Object font_entity)
2147 Lisp_Object tail, elt;
2148 Lisp_Object name = Qnil;
2150 for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail))
2152 elt = XCAR (tail);
2153 if (FLOATP (XCDR (elt)))
2155 if (STRINGP (XCAR (elt)))
2157 if (NILP (name))
2158 name = Ffont_xlfd_name (font_entity, Qnil);
2159 if (fast_string_match_ignore_case (XCAR (elt), name) >= 0)
2160 return XFLOAT_DATA (XCDR (elt));
2162 else if (FONT_SPEC_P (XCAR (elt)))
2164 if (font_match_p (XCAR (elt), font_entity))
2165 return XFLOAT_DATA (XCDR (elt));
2169 return 1.0;
2172 /* We sort fonts by scoring each of them against a specified
2173 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2174 the value is, the closer the font is to the font-spec.
2176 The lowest 2 bits of the score is used for driver type. The font
2177 available by the most preferred font driver is 0.
2179 Each 7-bit in the higher 28 bits are used for numeric properties
2180 WEIGHT, SLANT, WIDTH, and SIZE. */
2182 /* How many bits to shift to store the difference value of each font
2183 property in a score. Note that flots for FONT_TYPE_INDEX and
2184 FONT_REGISTRY_INDEX are not used. */
2185 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
2187 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2188 The return value indicates how different ENTITY is compared with
2189 SPEC_PROP. */
2191 static unsigned
2192 font_score (Lisp_Object entity, Lisp_Object *spec_prop)
2194 unsigned score = 0;
2195 int i;
2197 /* Score three style numeric fields. Maximum difference is 127. */
2198 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
2199 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
2201 int diff = (XINT (AREF (entity, i)) >> 8) - (XINT (spec_prop[i]) >> 8);
2203 if (diff < 0)
2204 diff = - diff;
2205 if (diff > 0)
2206 score |= min (diff, 127) << sort_shift_bits[i];
2209 /* Score the size. Maximum difference is 127. */
2210 i = FONT_SIZE_INDEX;
2211 if (! NILP (spec_prop[FONT_SIZE_INDEX])
2212 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2214 /* We use the higher 6-bit for the actual size difference. The
2215 lowest bit is set if the DPI is different. */
2216 int diff;
2217 int pixel_size = XINT (spec_prop[FONT_SIZE_INDEX]);
2219 if (CONSP (Vface_font_rescale_alist))
2220 pixel_size *= font_rescale_ratio (entity);
2221 diff = pixel_size - XINT (AREF (entity, FONT_SIZE_INDEX));
2222 if (diff < 0)
2223 diff = - diff;
2224 diff <<= 1;
2225 if (! NILP (spec_prop[FONT_DPI_INDEX])
2226 && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX)))
2227 diff |= 1;
2228 if (! NILP (spec_prop[FONT_AVGWIDTH_INDEX])
2229 && ! EQ (spec_prop[FONT_AVGWIDTH_INDEX], AREF (entity, FONT_AVGWIDTH_INDEX)))
2230 diff |= 1;
2231 score |= min (diff, 127) << sort_shift_bits[FONT_SIZE_INDEX];
2234 return score;
2238 /* Concatenate all elements of LIST into one vector. LIST is a list
2239 of font-entity vectors. */
2241 static Lisp_Object
2242 font_vconcat_entity_vectors (Lisp_Object list)
2244 int nargs = XINT (Flength (list));
2245 Lisp_Object *args = alloca (sizeof (Lisp_Object) * nargs);
2246 int i;
2248 for (i = 0; i < nargs; i++, list = XCDR (list))
2249 args[i] = XCAR (list);
2250 return Fvconcat (nargs, args);
2254 /* The structure for elements being sorted by qsort. */
2255 struct font_sort_data
2257 unsigned score;
2258 int font_driver_preference;
2259 Lisp_Object entity;
2263 /* The comparison function for qsort. */
2265 static int
2266 font_compare (const void *d1, const void *d2)
2268 const struct font_sort_data *data1 = d1;
2269 const struct font_sort_data *data2 = d2;
2271 if (data1->score < data2->score)
2272 return -1;
2273 else if (data1->score > data2->score)
2274 return 1;
2275 return (data1->font_driver_preference - data2->font_driver_preference);
2279 /* Sort each font-entity vector in LIST by closeness to font-spec PREFER.
2280 If PREFER specifies a point-size, calculate the corresponding
2281 pixel-size from QCdpi property of PREFER or from the Y-resolution
2282 of FRAME before sorting.
2284 If BEST-ONLY is nonzero, return the best matching entity (that
2285 supports the character BEST-ONLY if BEST-ONLY is positive, or any
2286 if BEST-ONLY is negative). Otherwise, return the sorted result as
2287 a single vector of font-entities.
2289 This function does no optimization for the case that the total
2290 number of elements is 1. The caller should avoid calling this in
2291 such a case. */
2293 static Lisp_Object
2294 font_sort_entities (Lisp_Object list, Lisp_Object prefer, Lisp_Object frame, int best_only)
2296 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2297 int len, maxlen, i;
2298 struct font_sort_data *data;
2299 unsigned best_score;
2300 Lisp_Object best_entity;
2301 struct frame *f = XFRAME (frame);
2302 Lisp_Object tail, vec;
2303 USE_SAFE_ALLOCA;
2305 for (i = FONT_WEIGHT_INDEX; i <= FONT_AVGWIDTH_INDEX; i++)
2306 prefer_prop[i] = AREF (prefer, i);
2307 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2308 prefer_prop[FONT_SIZE_INDEX]
2309 = make_number (font_pixel_size (XFRAME (frame), prefer));
2311 if (NILP (XCDR (list)))
2313 /* What we have to take care of is this single vector. */
2314 vec = XCAR (list);
2315 maxlen = ASIZE (vec);
2317 else if (best_only)
2319 /* We don't have to perform sort, so there's no need of creating
2320 a single vector. But, we must find the length of the longest
2321 vector. */
2322 maxlen = 0;
2323 for (tail = list; CONSP (tail); tail = XCDR (tail))
2324 if (maxlen < ASIZE (XCAR (tail)))
2325 maxlen = ASIZE (XCAR (tail));
2327 else
2329 /* We have to create a single vector to sort it. */
2330 vec = font_vconcat_entity_vectors (list);
2331 maxlen = ASIZE (vec);
2334 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * maxlen);
2335 best_score = 0xFFFFFFFF;
2336 best_entity = Qnil;
2338 for (tail = list; CONSP (tail); tail = XCDR (tail))
2340 int font_driver_preference = 0;
2341 Lisp_Object current_font_driver;
2343 if (best_only)
2344 vec = XCAR (tail);
2345 len = ASIZE (vec);
2347 /* We are sure that the length of VEC > 0. */
2348 current_font_driver = AREF (AREF (vec, 0), FONT_TYPE_INDEX);
2349 /* Score the elements. */
2350 for (i = 0; i < len; i++)
2352 data[i].entity = AREF (vec, i);
2353 data[i].score
2354 = ((best_only <= 0 || font_has_char (f, data[i].entity, best_only)
2355 > 0)
2356 ? font_score (data[i].entity, prefer_prop)
2357 : 0xFFFFFFFF);
2358 if (best_only && best_score > data[i].score)
2360 best_score = data[i].score;
2361 best_entity = data[i].entity;
2362 if (best_score == 0)
2363 break;
2365 if (! EQ (current_font_driver, AREF (AREF (vec, i), FONT_TYPE_INDEX)))
2367 current_font_driver = AREF (AREF (vec, i), FONT_TYPE_INDEX);
2368 font_driver_preference++;
2370 data[i].font_driver_preference = font_driver_preference;
2373 /* Sort if necessary. */
2374 if (! best_only)
2376 qsort (data, len, sizeof *data, font_compare);
2377 for (i = 0; i < len; i++)
2378 ASET (vec, i, data[i].entity);
2379 break;
2381 else
2382 vec = best_entity;
2385 SAFE_FREE ();
2387 FONT_ADD_LOG ("sort-by", prefer, vec);
2388 return vec;
2392 /* API of Font Service Layer. */
2394 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2395 sort_shift_bits. Finternal_set_font_selection_order calls this
2396 function with font_sort_order after setting up it. */
2398 void
2399 font_update_sort_order (int *order)
2401 int i, shift_bits;
2403 for (i = 0, shift_bits = 23; i < 4; i++, shift_bits -= 7)
2405 int xlfd_idx = order[i];
2407 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2408 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2409 else if (xlfd_idx == XLFD_SLANT_INDEX)
2410 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2411 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2412 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2413 else
2414 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2418 static int
2419 font_check_otf_features (Lisp_Object script, Lisp_Object langsys, Lisp_Object features, Lisp_Object table)
2421 Lisp_Object val;
2422 int negative;
2424 table = assq_no_quit (script, table);
2425 if (NILP (table))
2426 return 0;
2427 table = XCDR (table);
2428 if (! NILP (langsys))
2430 table = assq_no_quit (langsys, table);
2431 if (NILP (table))
2432 return 0;
2434 else
2436 val = assq_no_quit (Qnil, table);
2437 if (NILP (val))
2438 table = XCAR (table);
2439 else
2440 table = val;
2442 table = XCDR (table);
2443 for (negative = 0; CONSP (features); features = XCDR (features))
2445 if (NILP (XCAR (features)))
2447 negative = 1;
2448 continue;
2450 if (NILP (Fmemq (XCAR (features), table)) != negative)
2451 return 0;
2453 return 1;
2456 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2458 static int
2459 font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
2461 Lisp_Object script, langsys = Qnil, gsub = Qnil, gpos = Qnil;
2463 script = XCAR (spec);
2464 spec = XCDR (spec);
2465 if (! NILP (spec))
2467 langsys = XCAR (spec);
2468 spec = XCDR (spec);
2469 if (! NILP (spec))
2471 gsub = XCAR (spec);
2472 spec = XCDR (spec);
2473 if (! NILP (spec))
2474 gpos = XCAR (spec);
2478 if (! NILP (gsub) && ! font_check_otf_features (script, langsys, gsub,
2479 XCAR (otf_capability)))
2480 return 0;
2481 if (! NILP (gpos) && ! font_check_otf_features (script, langsys, gpos,
2482 XCDR (otf_capability)))
2483 return 0;
2484 return 1;
2489 /* Check if FONT (font-entity or font-object) matches with the font
2490 specification SPEC. */
2493 font_match_p (Lisp_Object spec, Lisp_Object font)
2495 Lisp_Object prop[FONT_SPEC_MAX], *props;
2496 Lisp_Object extra, font_extra;
2497 int i;
2499 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2500 if (! NILP (AREF (spec, i))
2501 && ! NILP (AREF (font, i))
2502 && ! EQ (AREF (spec, i), AREF (font, i)))
2503 return 0;
2504 props = XFONT_SPEC (spec)->props;
2505 if (FLOATP (props[FONT_SIZE_INDEX]))
2507 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
2508 prop[i] = AREF (spec, i);
2509 prop[FONT_SIZE_INDEX]
2510 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2511 props = prop;
2514 if (font_score (font, props) > 0)
2515 return 0;
2516 extra = AREF (spec, FONT_EXTRA_INDEX);
2517 font_extra = AREF (font, FONT_EXTRA_INDEX);
2518 for (; CONSP (extra); extra = XCDR (extra))
2520 Lisp_Object key = XCAR (XCAR (extra));
2521 Lisp_Object val = XCDR (XCAR (extra)), val2;
2523 if (EQ (key, QClang))
2525 val2 = assq_no_quit (key, font_extra);
2526 if (NILP (val2))
2527 return 0;
2528 val2 = XCDR (val2);
2529 if (CONSP (val))
2531 if (! CONSP (val2))
2532 return 0;
2533 while (CONSP (val))
2534 if (NILP (Fmemq (val, val2)))
2535 return 0;
2537 else
2538 if (CONSP (val2)
2539 ? NILP (Fmemq (val, XCDR (val2)))
2540 : ! EQ (val, val2))
2541 return 0;
2543 else if (EQ (key, QCscript))
2545 val2 = assq_no_quit (val, Vscript_representative_chars);
2546 if (CONSP (val2))
2548 val2 = XCDR (val2);
2549 if (CONSP (val2))
2551 /* All characters in the list must be supported. */
2552 for (; CONSP (val2); val2 = XCDR (val2))
2554 if (! NATNUMP (XCAR (val2)))
2555 continue;
2556 if (font_encode_char (font, XFASTINT (XCAR (val2)))
2557 == FONT_INVALID_CODE)
2558 return 0;
2561 else if (VECTORP (val2))
2563 /* At most one character in the vector must be supported. */
2564 for (i = 0; i < ASIZE (val2); i++)
2566 if (! NATNUMP (AREF (val2, i)))
2567 continue;
2568 if (font_encode_char (font, XFASTINT (AREF (val2, i)))
2569 != FONT_INVALID_CODE)
2570 break;
2572 if (i == ASIZE (val2))
2573 return 0;
2577 else if (EQ (key, QCotf))
2579 struct font *fontp;
2581 if (! FONT_OBJECT_P (font))
2582 return 0;
2583 fontp = XFONT_OBJECT (font);
2584 if (! fontp->driver->otf_capability)
2585 return 0;
2586 val2 = fontp->driver->otf_capability (fontp);
2587 if (NILP (val2) || ! font_check_otf (val, val2))
2588 return 0;
2592 return 1;
2596 /* Font cache
2598 Each font backend has the callback function get_cache, and it
2599 returns a cons cell of which cdr part can be freely used for
2600 caching fonts. The cons cell may be shared by multiple frames
2601 and/or multiple font drivers. So, we arrange the cdr part as this:
2603 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2605 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2606 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2607 cons (FONT-SPEC FONT-ENTITY ...). */
2609 static void font_prepare_cache (FRAME_PTR, struct font_driver *);
2610 static void font_finish_cache (FRAME_PTR, struct font_driver *);
2611 static Lisp_Object font_get_cache (FRAME_PTR, struct font_driver *);
2612 static void font_clear_cache (FRAME_PTR, Lisp_Object,
2613 struct font_driver *);
2615 static void
2616 font_prepare_cache (FRAME_PTR f, struct font_driver *driver)
2618 Lisp_Object cache, val;
2620 cache = driver->get_cache (f);
2621 val = XCDR (cache);
2622 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2623 val = XCDR (val);
2624 if (NILP (val))
2626 val = Fcons (driver->type, Fcons (make_number (1), Qnil));
2627 XSETCDR (cache, Fcons (val, XCDR (cache)));
2629 else
2631 val = XCDR (XCAR (val));
2632 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2637 static void
2638 font_finish_cache (FRAME_PTR f, struct font_driver *driver)
2640 Lisp_Object cache, val, tmp;
2643 cache = driver->get_cache (f);
2644 val = XCDR (cache);
2645 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2646 cache = val, val = XCDR (val);
2647 font_assert (! NILP (val));
2648 tmp = XCDR (XCAR (val));
2649 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2650 if (XINT (XCAR (tmp)) == 0)
2652 font_clear_cache (f, XCAR (val), driver);
2653 XSETCDR (cache, XCDR (val));
2658 static Lisp_Object
2659 font_get_cache (FRAME_PTR f, struct font_driver *driver)
2661 Lisp_Object val = driver->get_cache (f);
2662 Lisp_Object type = driver->type;
2664 font_assert (CONSP (val));
2665 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2666 font_assert (CONSP (val));
2667 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2668 val = XCDR (XCAR (val));
2669 return val;
2672 static int num_fonts;
2674 static void
2675 font_clear_cache (FRAME_PTR f, Lisp_Object cache, struct font_driver *driver)
2677 Lisp_Object tail, elt;
2678 Lisp_Object tail2, entity;
2680 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2681 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2683 elt = XCAR (tail);
2684 /* elt should have the form (FONT-SPEC FONT-ENTITY ...) */
2685 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2687 for (tail2 = XCDR (elt); CONSP (tail2); tail2 = XCDR (tail2))
2689 entity = XCAR (tail2);
2691 if (FONT_ENTITY_P (entity)
2692 && EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2694 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2696 for (; CONSP (objlist); objlist = XCDR (objlist))
2698 Lisp_Object val = XCAR (objlist);
2699 struct font *font = XFONT_OBJECT (val);
2701 if (! NILP (AREF (val, FONT_TYPE_INDEX)))
2703 font_assert (font && driver == font->driver);
2704 driver->close (f, font);
2705 num_fonts--;
2708 if (driver->free_entity)
2709 driver->free_entity (entity);
2714 XSETCDR (cache, Qnil);
2718 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2720 /* Check each font-entity in VEC, and return a list of font-entities
2721 that satisfy this condition:
2722 (1) matches with SPEC and SIZE if SPEC is not nil, and
2723 (2) doesn't match with any regexps in Vface_ignored_fonts (if non-nil).
2726 extern Lisp_Object Vface_ignored_fonts;
2728 Lisp_Object
2729 font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size)
2731 Lisp_Object entity, val;
2732 enum font_property_index prop;
2733 int i;
2735 for (val = Qnil, i = ASIZE (vec) - 1; i >= 0; i--)
2737 entity = AREF (vec, i);
2738 if (! NILP (Vface_ignored_fonts))
2740 char name[256];
2741 Lisp_Object tail, regexp;
2743 if (font_unparse_xlfd (entity, 0, name, 256) >= 0)
2745 for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
2747 regexp = XCAR (tail);
2748 if (STRINGP (regexp)
2749 && fast_c_string_match_ignore_case (regexp, name) >= 0)
2750 break;
2752 if (CONSP (tail))
2753 continue;
2756 if (NILP (spec))
2758 val = Fcons (entity, val);
2759 continue;
2761 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++)
2762 if (INTEGERP (AREF (spec, prop))
2763 && ((XINT (AREF (spec, prop)) >> 8)
2764 != (XINT (AREF (entity, prop)) >> 8)))
2765 prop = FONT_SPEC_MAX;
2766 if (prop < FONT_SPEC_MAX
2767 && size
2768 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2770 int diff = XINT (AREF (entity, FONT_SIZE_INDEX)) - size;
2772 if (diff != 0
2773 && (diff < 0 ? -diff > FONT_PIXEL_SIZE_QUANTUM
2774 : diff > FONT_PIXEL_SIZE_QUANTUM))
2775 prop = FONT_SPEC_MAX;
2777 if (prop < FONT_SPEC_MAX
2778 && INTEGERP (AREF (spec, FONT_DPI_INDEX))
2779 && INTEGERP (AREF (entity, FONT_DPI_INDEX))
2780 && XINT (AREF (entity, FONT_DPI_INDEX)) != 0
2781 && ! EQ (AREF (spec, FONT_DPI_INDEX), AREF (entity, FONT_DPI_INDEX)))
2782 prop = FONT_SPEC_MAX;
2783 if (prop < FONT_SPEC_MAX
2784 && INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
2785 && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
2786 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) != 0
2787 && ! EQ (AREF (spec, FONT_AVGWIDTH_INDEX),
2788 AREF (entity, FONT_AVGWIDTH_INDEX)))
2789 prop = FONT_SPEC_MAX;
2790 if (prop < FONT_SPEC_MAX)
2791 val = Fcons (entity, val);
2793 return (Fvconcat (1, &val));
2797 /* Return a list of vectors of font-entities matching with SPEC on
2798 FRAME. Each elements in the list is a vector of entities from the
2799 same font-driver. */
2801 Lisp_Object
2802 font_list_entities (Lisp_Object frame, Lisp_Object spec)
2804 FRAME_PTR f = XFRAME (frame);
2805 struct font_driver_list *driver_list = f->font_driver_list;
2806 Lisp_Object ftype, val;
2807 Lisp_Object list = Qnil;
2808 int size;
2809 int need_filtering = 0;
2810 int i;
2812 font_assert (FONT_SPEC_P (spec));
2814 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2815 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2816 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2817 size = font_pixel_size (f, spec);
2818 else
2819 size = 0;
2821 ftype = AREF (spec, FONT_TYPE_INDEX);
2822 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2823 ASET (scratch_font_spec, i, AREF (spec, i));
2824 for (i = FONT_WEIGHT_INDEX; i < FONT_EXTRA_INDEX; i++)
2826 ASET (scratch_font_spec, i, Qnil);
2827 if (! NILP (AREF (spec, i)))
2828 need_filtering = 1;
2829 if (i == FONT_DPI_INDEX)
2830 /* Skip FONT_SPACING_INDEX */
2831 i++;
2833 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX));
2834 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
2836 for (i = 0; driver_list; driver_list = driver_list->next)
2837 if (driver_list->on
2838 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2840 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2842 ASET (scratch_font_spec, FONT_TYPE_INDEX, driver_list->driver->type);
2843 val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2844 if (CONSP (val))
2845 val = XCDR (val);
2846 else
2848 Lisp_Object copy;
2850 val = driver_list->driver->list (frame, scratch_font_spec);
2851 if (NILP (val))
2852 val = null_vector;
2853 else
2854 val = Fvconcat (1, &val);
2855 copy = Fcopy_font_spec (scratch_font_spec);
2856 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2857 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2859 if (ASIZE (val) > 0
2860 && (need_filtering
2861 || ! NILP (Vface_ignored_fonts)))
2862 val = font_delete_unmatched (val, need_filtering ? spec : Qnil, size);
2863 if (ASIZE (val) > 0)
2864 list = Fcons (val, list);
2867 list = Fnreverse (list);
2868 FONT_ADD_LOG ("list", spec, list);
2869 return list;
2873 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2874 nil, is an array of face's attributes, which specifies preferred
2875 font-related attributes. */
2877 static Lisp_Object
2878 font_matching_entity (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
2880 struct font_driver_list *driver_list = f->font_driver_list;
2881 Lisp_Object ftype, size, entity;
2882 Lisp_Object frame;
2883 Lisp_Object work = Fcopy_font_spec (spec);
2885 XSETFRAME (frame, f);
2886 ftype = AREF (spec, FONT_TYPE_INDEX);
2887 size = AREF (spec, FONT_SIZE_INDEX);
2889 if (FLOATP (size))
2890 ASET (work, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2891 FONT_SET_STYLE (work, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
2892 FONT_SET_STYLE (work, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
2893 FONT_SET_STYLE (work, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
2895 entity = Qnil;
2896 for (; driver_list; driver_list = driver_list->next)
2897 if (driver_list->on
2898 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2900 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2901 Lisp_Object copy;
2903 ASET (work, FONT_TYPE_INDEX, driver_list->driver->type);
2904 entity = assoc_no_quit (work, XCDR (cache));
2905 if (CONSP (entity))
2906 entity = XCDR (entity);
2907 else
2909 entity = driver_list->driver->match (frame, work);
2910 copy = Fcopy_font_spec (work);
2911 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2912 XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache)));
2914 if (! NILP (entity))
2915 break;
2917 FONT_ADD_LOG ("match", work, entity);
2918 return entity;
2922 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2923 opened font object. */
2925 static Lisp_Object
2926 font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
2928 struct font_driver_list *driver_list;
2929 Lisp_Object objlist, size, val, font_object;
2930 struct font *font;
2931 int min_width, height;
2932 int scaled_pixel_size;
2934 font_assert (FONT_ENTITY_P (entity));
2935 size = AREF (entity, FONT_SIZE_INDEX);
2936 if (XINT (size) != 0)
2937 scaled_pixel_size = pixel_size = XINT (size);
2938 else if (CONSP (Vface_font_rescale_alist))
2939 scaled_pixel_size = pixel_size * font_rescale_ratio (entity);
2941 val = AREF (entity, FONT_TYPE_INDEX);
2942 for (driver_list = f->font_driver_list;
2943 driver_list && ! EQ (driver_list->driver->type, val);
2944 driver_list = driver_list->next);
2945 if (! driver_list)
2946 return Qnil;
2948 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2949 objlist = XCDR (objlist))
2951 Lisp_Object fn = XCAR (objlist);
2952 if (! NILP (AREF (fn, FONT_TYPE_INDEX))
2953 && XFONT_OBJECT (fn)->pixel_size == pixel_size)
2955 if (driver_list->driver->cached_font_ok == NULL
2956 || driver_list->driver->cached_font_ok (f, fn, entity))
2957 return fn;
2961 font_object = driver_list->driver->open (f, entity, scaled_pixel_size);
2962 if (!NILP (font_object))
2963 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
2964 FONT_ADD_LOG ("open", entity, font_object);
2965 if (NILP (font_object))
2966 return Qnil;
2967 ASET (entity, FONT_OBJLIST_INDEX,
2968 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2969 num_fonts++;
2971 font = XFONT_OBJECT (font_object);
2972 min_width = (font->min_width ? font->min_width
2973 : font->average_width ? font->average_width
2974 : font->space_width ? font->space_width
2975 : 1);
2976 height = (font->height ? font->height : 1);
2977 #ifdef HAVE_WINDOW_SYSTEM
2978 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
2979 if (FRAME_X_DISPLAY_INFO (f)->n_fonts == 1)
2981 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
2982 FRAME_SMALLEST_FONT_HEIGHT (f) = height;
2983 fonts_changed_p = 1;
2985 else
2987 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
2988 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
2989 if (FRAME_SMALLEST_FONT_HEIGHT (f) > height)
2990 FRAME_SMALLEST_FONT_HEIGHT (f) = height, fonts_changed_p = 1;
2992 #endif
2994 return font_object;
2998 /* Close FONT_OBJECT that is opened on frame F. */
3000 void
3001 font_close_object (FRAME_PTR f, Lisp_Object font_object)
3003 struct font *font = XFONT_OBJECT (font_object);
3005 if (NILP (AREF (font_object, FONT_TYPE_INDEX)))
3006 /* Already closed. */
3007 return;
3008 FONT_ADD_LOG ("close", font_object, Qnil);
3009 font->driver->close (f, font);
3010 #ifdef HAVE_WINDOW_SYSTEM
3011 font_assert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
3012 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
3013 #endif
3014 num_fonts--;
3018 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
3019 FONT is a font-entity and it must be opened to check. */
3022 font_has_char (FRAME_PTR f, Lisp_Object font, int c)
3024 struct font *fontp;
3026 if (FONT_ENTITY_P (font))
3028 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
3029 struct font_driver_list *driver_list;
3031 for (driver_list = f->font_driver_list;
3032 driver_list && ! EQ (driver_list->driver->type, type);
3033 driver_list = driver_list->next);
3034 if (! driver_list)
3035 return 0;
3036 if (! driver_list->driver->has_char)
3037 return -1;
3038 return driver_list->driver->has_char (font, c);
3041 font_assert (FONT_OBJECT_P (font));
3042 fontp = XFONT_OBJECT (font);
3043 if (fontp->driver->has_char)
3045 int result = fontp->driver->has_char (font, c);
3047 if (result >= 0)
3048 return result;
3050 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
3054 /* Return the glyph ID of FONT_OBJECT for character C. */
3056 unsigned
3057 font_encode_char (Lisp_Object font_object, int c)
3059 struct font *font;
3061 font_assert (FONT_OBJECT_P (font_object));
3062 font = XFONT_OBJECT (font_object);
3063 return font->driver->encode_char (font, c);
3067 /* Return the name of FONT_OBJECT. */
3069 Lisp_Object
3070 font_get_name (Lisp_Object font_object)
3072 font_assert (FONT_OBJECT_P (font_object));
3073 return AREF (font_object, FONT_NAME_INDEX);
3077 /* Return the specification of FONT_OBJECT. */
3079 Lisp_Object
3080 font_get_spec (Lisp_Object font_object)
3082 Lisp_Object spec = font_make_spec ();
3083 int i;
3085 for (i = 0; i < FONT_SIZE_INDEX; i++)
3086 ASET (spec, i, AREF (font_object, i));
3087 ASET (spec, FONT_SIZE_INDEX,
3088 make_number (XFONT_OBJECT (font_object)->pixel_size));
3089 return spec;
3093 /* Create a new font spec from FONT_NAME, and return it. If FONT_NAME
3094 could not be parsed by font_parse_name, return Qnil. */
3096 Lisp_Object
3097 font_spec_from_name (Lisp_Object font_name)
3099 Lisp_Object spec = Ffont_spec (0, NULL);
3101 CHECK_STRING (font_name);
3102 if (font_parse_name ((char *) SDATA (font_name), spec) == -1)
3103 return Qnil;
3104 font_put_extra (spec, QCname, font_name);
3105 font_put_extra (spec, QCuser_spec, font_name);
3106 return spec;
3110 void
3111 font_clear_prop (Lisp_Object *attrs, enum font_property_index prop)
3113 Lisp_Object font = attrs[LFACE_FONT_INDEX];
3115 if (! FONTP (font))
3116 return;
3118 if (! NILP (Ffont_get (font, QCname)))
3120 font = Fcopy_font_spec (font);
3121 font_put_extra (font, QCname, Qnil);
3124 if (NILP (AREF (font, prop))
3125 && prop != FONT_FAMILY_INDEX
3126 && prop != FONT_FOUNDRY_INDEX
3127 && prop != FONT_WIDTH_INDEX
3128 && prop != FONT_SIZE_INDEX)
3129 return;
3130 if (EQ (font, attrs[LFACE_FONT_INDEX]))
3131 font = Fcopy_font_spec (font);
3132 ASET (font, prop, Qnil);
3133 if (prop == FONT_FAMILY_INDEX || prop == FONT_FOUNDRY_INDEX)
3135 if (prop == FONT_FAMILY_INDEX)
3137 ASET (font, FONT_FOUNDRY_INDEX, Qnil);
3138 /* If we are setting the font family, we must also clear
3139 FONT_WIDTH_INDEX to avoid rejecting families that lack
3140 support for some widths. */
3141 ASET (font, FONT_WIDTH_INDEX, Qnil);
3143 ASET (font, FONT_ADSTYLE_INDEX, Qnil);
3144 ASET (font, FONT_REGISTRY_INDEX, Qnil);
3145 ASET (font, FONT_SIZE_INDEX, Qnil);
3146 ASET (font, FONT_DPI_INDEX, Qnil);
3147 ASET (font, FONT_SPACING_INDEX, Qnil);
3148 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3150 else if (prop == FONT_SIZE_INDEX)
3152 ASET (font, FONT_DPI_INDEX, Qnil);
3153 ASET (font, FONT_SPACING_INDEX, Qnil);
3154 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3156 else if (prop == FONT_WIDTH_INDEX)
3157 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3158 attrs[LFACE_FONT_INDEX] = font;
3161 void
3162 font_update_lface (FRAME_PTR f, Lisp_Object *attrs)
3164 Lisp_Object spec;
3166 spec = attrs[LFACE_FONT_INDEX];
3167 if (! FONT_SPEC_P (spec))
3168 return;
3170 if (! NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
3171 attrs[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX));
3172 if (! NILP (AREF (spec, FONT_FAMILY_INDEX)))
3173 attrs[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FAMILY_INDEX));
3174 if (! NILP (AREF (spec, FONT_WEIGHT_INDEX)))
3175 attrs[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (spec);
3176 if (! NILP (AREF (spec, FONT_SLANT_INDEX)))
3177 attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);
3178 if (! NILP (AREF (spec, FONT_WIDTH_INDEX)))
3179 attrs[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (spec);
3180 if (! NILP (AREF (spec, FONT_SIZE_INDEX)))
3182 int point;
3184 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
3186 Lisp_Object val;
3187 int dpi = f->resy;
3189 val = Ffont_get (spec, QCdpi);
3190 if (! NILP (val))
3191 dpi = XINT (val);
3192 point = PIXEL_TO_POINT (XINT (AREF (spec, FONT_SIZE_INDEX)) * 10,
3193 dpi);
3194 attrs[LFACE_HEIGHT_INDEX] = make_number (point);
3196 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
3198 point = XFLOAT_DATA (AREF (spec, FONT_SIZE_INDEX)) * 10;
3199 attrs[LFACE_HEIGHT_INDEX] = make_number (point);
3205 /* Selecte a font from ENTITIES (list of font-entity vectors) that
3206 supports C and matches best with ATTRS and PIXEL_SIZE. */
3208 static Lisp_Object
3209 font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs, int pixel_size, int c)
3211 Lisp_Object font_entity;
3212 Lisp_Object prefer;
3213 int result, i;
3214 FRAME_PTR f = XFRAME (frame);
3216 if (NILP (XCDR (entities))
3217 && ASIZE (XCAR (entities)) == 1)
3219 font_entity = AREF (XCAR (entities), 0);
3220 if (c < 0
3221 || (result = font_has_char (f, font_entity, c)) > 0)
3222 return font_entity;
3223 return Qnil;
3226 /* Sort fonts by properties specified in ATTRS. */
3227 prefer = scratch_font_prefer;
3229 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3230 ASET (prefer, i, Qnil);
3231 if (FONTP (attrs[LFACE_FONT_INDEX]))
3233 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3235 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3236 ASET (prefer, i, AREF (face_font, i));
3238 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
3239 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
3240 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
3241 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
3242 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
3243 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
3244 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
3246 return font_sort_entities (entities, prefer, frame, c);
3249 /* Return a font-entity satisfying SPEC and best matching with face's
3250 font related attributes in ATTRS. C, if not negative, is a
3251 character that the entity must support. */
3253 Lisp_Object
3254 font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
3256 Lisp_Object work;
3257 Lisp_Object frame, entities, val;
3258 Lisp_Object size, foundry[3], *family, registry[3], adstyle[3];
3259 int pixel_size;
3260 int i, j, k, l;
3262 registry[0] = AREF (spec, FONT_REGISTRY_INDEX);
3263 if (NILP (registry[0]))
3265 registry[0] = DEFAULT_ENCODING;
3266 registry[1] = Qascii_0;
3267 registry[2] = null_vector;
3269 else
3270 registry[1] = null_vector;
3272 if (c >= 0 && ! NILP (AREF (spec, FONT_REGISTRY_INDEX)))
3274 struct charset *encoding, *repertory;
3276 if (font_registry_charsets (AREF (spec, FONT_REGISTRY_INDEX),
3277 &encoding, &repertory) < 0)
3278 return Qnil;
3279 if (repertory
3280 && ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
3281 return Qnil;
3282 else if (c > encoding->max_char)
3283 return Qnil;
3286 work = Fcopy_font_spec (spec);
3287 ASET (work, FONT_TYPE_INDEX, AREF (spec, FONT_TYPE_INDEX));
3288 XSETFRAME (frame, f);
3289 size = AREF (spec, FONT_SIZE_INDEX);
3290 pixel_size = font_pixel_size (f, spec);
3291 if (pixel_size == 0)
3293 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3295 pixel_size = POINT_TO_PIXEL (pt / 10, f->resy);
3297 ASET (work, FONT_SIZE_INDEX, Qnil);
3298 foundry[0] = AREF (work, FONT_FOUNDRY_INDEX);
3299 if (! NILP (foundry[0]))
3300 foundry[1] = null_vector;
3301 else if (STRINGP (attrs[LFACE_FOUNDRY_INDEX]))
3303 val = attrs[LFACE_FOUNDRY_INDEX];
3304 foundry[0] = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
3305 foundry[1] = Qnil;
3306 foundry[2] = null_vector;
3308 else
3309 foundry[0] = Qnil, foundry[1] = null_vector;
3311 adstyle[0] = AREF (work, FONT_ADSTYLE_INDEX);
3312 if (! NILP (adstyle[0]))
3313 adstyle[1] = null_vector;
3314 else if (FONTP (attrs[LFACE_FONT_INDEX]))
3316 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3318 if (! NILP (AREF (face_font, FONT_ADSTYLE_INDEX)))
3320 adstyle[0] = AREF (face_font, FONT_ADSTYLE_INDEX);
3321 adstyle[1] = Qnil;
3322 adstyle[2] = null_vector;
3324 else
3325 adstyle[0] = Qnil, adstyle[1] = null_vector;
3327 else
3328 adstyle[0] = Qnil, adstyle[1] = null_vector;
3331 val = AREF (work, FONT_FAMILY_INDEX);
3332 if (NILP (val) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
3334 val = attrs[LFACE_FAMILY_INDEX];
3335 val = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
3337 if (NILP (val))
3339 family = alloca ((sizeof family[0]) * 2);
3340 family[0] = Qnil;
3341 family[1] = null_vector; /* terminator. */
3343 else
3345 Lisp_Object alters
3346 = Fassoc_string (val, Vface_alternative_font_family_alist,
3347 /* Font family names are case-sensitive under NS. */
3348 #ifndef HAVE_NS
3350 #else
3351 Qnil
3352 #endif
3355 if (! NILP (alters))
3357 family = alloca ((sizeof family[0]) * (XINT (Flength (alters)) + 2));
3358 for (i = 0; CONSP (alters); i++, alters = XCDR (alters))
3359 family[i] = XCAR (alters);
3360 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3361 family[i++] = Qnil;
3362 family[i] = null_vector;
3364 else
3366 family = alloca ((sizeof family[0]) * 3);
3367 i = 0;
3368 family[i++] = val;
3369 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3370 family[i++] = Qnil;
3371 family[i] = null_vector;
3375 for (i = 0; SYMBOLP (family[i]); i++)
3377 ASET (work, FONT_FAMILY_INDEX, family[i]);
3378 for (j = 0; SYMBOLP (foundry[j]); j++)
3380 ASET (work, FONT_FOUNDRY_INDEX, foundry[j]);
3381 for (k = 0; SYMBOLP (registry[k]); k++)
3383 ASET (work, FONT_REGISTRY_INDEX, registry[k]);
3384 for (l = 0; SYMBOLP (adstyle[l]); l++)
3386 ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
3387 entities = font_list_entities (frame, work);
3388 if (! NILP (entities))
3390 val = font_select_entity (frame, entities,
3391 attrs, pixel_size, c);
3392 if (! NILP (val))
3393 return val;
3399 return Qnil;
3403 Lisp_Object
3404 font_open_for_lface (FRAME_PTR f, Lisp_Object entity, Lisp_Object *attrs, Lisp_Object spec)
3406 int size;
3408 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX))
3409 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
3410 size = XINT (AREF (entity, FONT_SIZE_INDEX));
3411 else if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
3412 size = font_pixel_size (f, spec);
3413 else
3415 double pt;
3416 if (INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
3417 pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3418 else
3420 struct face *def = FACE_FROM_ID (f, DEFAULT_FACE_ID);
3421 Lisp_Object height = def->lface[LFACE_HEIGHT_INDEX];
3422 if (INTEGERP (height))
3423 pt = XINT (height);
3424 else
3425 abort(); /* We should never end up here. */
3428 pt /= 10;
3429 size = POINT_TO_PIXEL (pt, f->resy);
3430 #ifdef HAVE_NS
3431 if (size == 0)
3433 Lisp_Object ffsize = get_frame_param(f, Qfontsize);
3434 size = NUMBERP (ffsize) ? POINT_TO_PIXEL (XINT (ffsize), f->resy) : 0;
3436 #endif
3438 return font_open_entity (f, entity, size);
3442 /* Find a font satisfying SPEC and best matching with face's
3443 attributes in ATTRS on FRAME, and return the opened
3444 font-object. */
3446 Lisp_Object
3447 font_load_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
3449 Lisp_Object entity, name;
3451 entity = font_find_for_lface (f, attrs, spec, -1);
3452 if (NILP (entity))
3454 /* No font is listed for SPEC, but each font-backend may have
3455 the different criteria about "font matching". So, try
3456 it. */
3457 entity = font_matching_entity (f, attrs, spec);
3458 if (NILP (entity))
3459 return Qnil;
3461 /* Don't loose the original name that was put in initially. We need
3462 it to re-apply the font when font parameters (like hinting or dpi) have
3463 changed. */
3464 entity = font_open_for_lface (f, entity, attrs, spec);
3465 if (!NILP (entity))
3467 name = Ffont_get (spec, QCuser_spec);
3468 if (STRINGP (name)) font_put_extra (entity, QCuser_spec, name);
3470 return entity;
3474 /* Make FACE on frame F ready to use the font opened for FACE. */
3476 void
3477 font_prepare_for_face (FRAME_PTR f, struct face *face)
3479 if (face->font->driver->prepare_face)
3480 face->font->driver->prepare_face (f, face);
3484 /* Make FACE on frame F stop using the font opened for FACE. */
3486 void
3487 font_done_for_face (FRAME_PTR f, struct face *face)
3489 if (face->font->driver->done_face)
3490 face->font->driver->done_face (f, face);
3491 face->extra = NULL;
3495 /* Open a font matching with font-spec SPEC on frame F. If no proper
3496 font is found, return Qnil. */
3498 Lisp_Object
3499 font_open_by_spec (FRAME_PTR f, Lisp_Object spec)
3501 Lisp_Object attrs[LFACE_VECTOR_SIZE];
3503 /* We set up the default font-related attributes of a face to prefer
3504 a moderate font. */
3505 attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
3506 attrs[LFACE_SWIDTH_INDEX] = attrs[LFACE_WEIGHT_INDEX]
3507 = attrs[LFACE_SLANT_INDEX] = Qnormal;
3508 #ifndef HAVE_NS
3509 attrs[LFACE_HEIGHT_INDEX] = make_number (120);
3510 #else
3511 attrs[LFACE_HEIGHT_INDEX] = make_number (0);
3512 #endif
3513 attrs[LFACE_FONT_INDEX] = Qnil;
3515 return font_load_for_lface (f, attrs, spec);
3519 /* Open a font matching with NAME on frame F. If no proper font is
3520 found, return Qnil. */
3522 Lisp_Object
3523 font_open_by_name (FRAME_PTR f, char *name)
3525 Lisp_Object args[2];
3526 Lisp_Object spec, ret;
3528 args[0] = QCname;
3529 args[1] = make_unibyte_string (name, strlen (name));
3530 spec = Ffont_spec (2, args);
3531 ret = font_open_by_spec (f, spec);
3532 /* Do not loose name originally put in. */
3533 if (!NILP (ret))
3534 font_put_extra (ret, QCuser_spec, args[1]);
3536 return ret;
3540 /* Register font-driver DRIVER. This function is used in two ways.
3542 The first is with frame F non-NULL. In this case, make DRIVER
3543 available (but not yet activated) on F. All frame creaters
3544 (e.g. Fx_create_frame) must call this function at least once with
3545 an available font-driver.
3547 The second is with frame F NULL. In this case, DRIVER is globally
3548 registered in the variable `font_driver_list'. All font-driver
3549 implementations must call this function in its syms_of_XXXX
3550 (e.g. syms_of_xfont). */
3552 void
3553 register_font_driver (struct font_driver *driver, FRAME_PTR f)
3555 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
3556 struct font_driver_list *prev, *list;
3558 if (f && ! driver->draw)
3559 error ("Unusable font driver for a frame: %s",
3560 SDATA (SYMBOL_NAME (driver->type)));
3562 for (prev = NULL, list = root; list; prev = list, list = list->next)
3563 if (EQ (list->driver->type, driver->type))
3564 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3566 list = xmalloc (sizeof (struct font_driver_list));
3567 list->on = 0;
3568 list->driver = driver;
3569 list->next = NULL;
3570 if (prev)
3571 prev->next = list;
3572 else if (f)
3573 f->font_driver_list = list;
3574 else
3575 font_driver_list = list;
3576 if (! f)
3577 num_font_drivers++;
3580 void
3581 free_font_driver_list (FRAME_PTR f)
3583 struct font_driver_list *list, *next;
3585 for (list = f->font_driver_list; list; list = next)
3587 next = list->next;
3588 xfree (list);
3590 f->font_driver_list = NULL;
3594 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3595 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3596 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3598 A caller must free all realized faces if any in advance. The
3599 return value is a list of font backends actually made used on
3600 F. */
3602 Lisp_Object
3603 font_update_drivers (FRAME_PTR f, Lisp_Object new_drivers)
3605 Lisp_Object active_drivers = Qnil;
3606 struct font_driver *driver;
3607 struct font_driver_list *list;
3609 /* At first, turn off non-requested drivers, and turn on requested
3610 drivers. */
3611 for (list = f->font_driver_list; list; list = list->next)
3613 driver = list->driver;
3614 if ((EQ (new_drivers, Qt) || ! NILP (Fmemq (driver->type, new_drivers)))
3615 != list->on)
3617 if (list->on)
3619 if (driver->end_for_frame)
3620 driver->end_for_frame (f);
3621 font_finish_cache (f, driver);
3622 list->on = 0;
3624 else
3626 if (! driver->start_for_frame
3627 || driver->start_for_frame (f) == 0)
3629 font_prepare_cache (f, driver);
3630 list->on = 1;
3636 if (NILP (new_drivers))
3637 return Qnil;
3639 if (! EQ (new_drivers, Qt))
3641 /* Re-order the driver list according to new_drivers. */
3642 struct font_driver_list **list_table, **next;
3643 Lisp_Object tail;
3644 int i;
3646 list_table = alloca (sizeof list_table[0] * (num_font_drivers + 1));
3647 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
3649 for (list = f->font_driver_list; list; list = list->next)
3650 if (list->on && EQ (list->driver->type, XCAR (tail)))
3651 break;
3652 if (list)
3653 list_table[i++] = list;
3655 for (list = f->font_driver_list; list; list = list->next)
3656 if (! list->on)
3657 list_table[i++] = list;
3658 list_table[i] = NULL;
3660 next = &f->font_driver_list;
3661 for (i = 0; list_table[i]; i++)
3663 *next = list_table[i];
3664 next = &(*next)->next;
3666 *next = NULL;
3668 if (! f->font_driver_list->on)
3669 { /* None of the drivers is enabled: enable them all.
3670 Happens if you set the list of drivers to (xft x) in your .emacs
3671 and then use it under w32 or ns. */
3672 for (list = f->font_driver_list; list; list = list->next)
3674 struct font_driver *driver = list->driver;
3675 eassert (! list->on);
3676 if (! driver->start_for_frame
3677 || driver->start_for_frame (f) == 0)
3679 font_prepare_cache (f, driver);
3680 list->on = 1;
3686 for (list = f->font_driver_list; list; list = list->next)
3687 if (list->on)
3688 active_drivers = nconc2 (active_drivers,
3689 Fcons (list->driver->type, Qnil));
3690 return active_drivers;
3694 font_put_frame_data (FRAME_PTR f, struct font_driver *driver, void *data)
3696 struct font_data_list *list, *prev;
3698 for (prev = NULL, list = f->font_data_list; list;
3699 prev = list, list = list->next)
3700 if (list->driver == driver)
3701 break;
3702 if (! data)
3704 if (list)
3706 if (prev)
3707 prev->next = list->next;
3708 else
3709 f->font_data_list = list->next;
3710 xfree (list);
3712 return 0;
3715 if (! list)
3717 list = xmalloc (sizeof (struct font_data_list));
3718 list->driver = driver;
3719 list->next = f->font_data_list;
3720 f->font_data_list = list;
3722 list->data = data;
3723 return 0;
3727 void *
3728 font_get_frame_data (FRAME_PTR f, struct font_driver *driver)
3730 struct font_data_list *list;
3732 for (list = f->font_data_list; list; list = list->next)
3733 if (list->driver == driver)
3734 break;
3735 if (! list)
3736 return NULL;
3737 return list->data;
3741 /* Return the font used to draw character C by FACE at buffer position
3742 POS in window W. If STRING is non-nil, it is a string containing C
3743 at index POS. If C is negative, get C from the current buffer or
3744 STRING. */
3746 Lisp_Object
3747 font_at (int c, EMACS_INT pos, struct face *face, struct window *w, Lisp_Object string)
3749 FRAME_PTR f;
3750 int multibyte;
3751 Lisp_Object font_object;
3753 multibyte = (NILP (string)
3754 ? ! NILP (current_buffer->enable_multibyte_characters)
3755 : STRING_MULTIBYTE (string));
3756 if (c < 0)
3758 if (NILP (string))
3760 if (multibyte)
3762 EMACS_INT pos_byte = CHAR_TO_BYTE (pos);
3764 c = FETCH_CHAR (pos_byte);
3766 else
3767 c = FETCH_BYTE (pos);
3769 else
3771 unsigned char *str;
3773 multibyte = STRING_MULTIBYTE (string);
3774 if (multibyte)
3776 EMACS_INT pos_byte = string_char_to_byte (string, pos);
3778 str = SDATA (string) + pos_byte;
3779 c = STRING_CHAR (str);
3781 else
3782 c = SDATA (string)[pos];
3786 f = XFRAME (w->frame);
3787 if (! FRAME_WINDOW_P (f))
3788 return Qnil;
3789 if (! face)
3791 int face_id;
3792 EMACS_INT endptr;
3794 if (STRINGP (string))
3795 face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
3796 DEFAULT_FACE_ID, 0);
3797 else
3798 face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
3799 pos + 100, 0, -1);
3800 face = FACE_FROM_ID (f, face_id);
3802 if (multibyte)
3804 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3805 face = FACE_FROM_ID (f, face_id);
3807 if (! face->font)
3808 return Qnil;
3810 XSETFONT (font_object, face->font);
3811 return font_object;
3815 #ifdef HAVE_WINDOW_SYSTEM
3817 /* Check how many characters after POS (at most to *LIMIT) can be
3818 displayed by the same font on the window W. FACE, if non-NULL, is
3819 the face selected for the character at POS. If STRING is not nil,
3820 it is the string to check instead of the current buffer. In that
3821 case, FACE must be not NULL.
3823 The return value is the font-object for the character at POS.
3824 *LIMIT is set to the position where that font can't be used.
3826 It is assured that the current buffer (or STRING) is multibyte. */
3828 Lisp_Object
3829 font_range (EMACS_INT pos, EMACS_INT *limit, struct window *w, struct face *face, Lisp_Object string)
3831 EMACS_INT pos_byte, ignore;
3832 int c;
3833 Lisp_Object font_object = Qnil;
3835 if (NILP (string))
3837 pos_byte = CHAR_TO_BYTE (pos);
3838 if (! face)
3840 int face_id;
3842 face_id = face_at_buffer_position (w, pos, 0, 0, &ignore,
3843 *limit, 0, -1);
3844 face = FACE_FROM_ID (XFRAME (w->frame), face_id);
3847 else
3849 font_assert (face);
3850 pos_byte = string_char_to_byte (string, pos);
3853 while (pos < *limit)
3855 Lisp_Object category;
3857 if (NILP (string))
3858 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3859 else
3860 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3861 category = CHAR_TABLE_REF (Vunicode_category_table, c);
3862 if (EQ (category, QCf)
3863 || CHAR_VARIATION_SELECTOR_P (c))
3864 continue;
3865 if (NILP (font_object))
3867 font_object = font_for_char (face, c, pos - 1, string);
3868 if (NILP (font_object))
3869 return Qnil;
3870 continue;
3872 if (font_encode_char (font_object, c) == FONT_INVALID_CODE)
3873 *limit = pos - 1;
3875 return font_object;
3877 #endif
3880 /* Lisp API */
3882 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3883 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3884 Return nil otherwise.
3885 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3886 which kind of font it is. It must be one of `font-spec', `font-entity',
3887 `font-object'. */)
3888 (Lisp_Object object, Lisp_Object extra_type)
3890 if (NILP (extra_type))
3891 return (FONTP (object) ? Qt : Qnil);
3892 if (EQ (extra_type, Qfont_spec))
3893 return (FONT_SPEC_P (object) ? Qt : Qnil);
3894 if (EQ (extra_type, Qfont_entity))
3895 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3896 if (EQ (extra_type, Qfont_object))
3897 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3898 wrong_type_argument (intern ("font-extra-type"), extra_type);
3901 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3902 doc: /* Return a newly created font-spec with arguments as properties.
3904 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3905 valid font property name listed below:
3907 `:family', `:weight', `:slant', `:width'
3909 They are the same as face attributes of the same name. See
3910 `set-face-attribute'.
3912 `:foundry'
3914 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3916 `:adstyle'
3918 VALUE must be a string or a symbol specifying the additional
3919 typographic style information of a font, e.g. ``sans''.
3921 `:registry'
3923 VALUE must be a string or a symbol specifying the charset registry and
3924 encoding of a font, e.g. ``iso8859-1''.
3926 `:size'
3928 VALUE must be a non-negative integer or a floating point number
3929 specifying the font size. It specifies the font size in pixels (if
3930 VALUE is an integer), or in points (if VALUE is a float).
3932 `:name'
3934 VALUE must be a string of XLFD-style or fontconfig-style font name.
3936 `:script'
3938 VALUE must be a symbol representing a script that the font must
3939 support. It may be a symbol representing a subgroup of a script
3940 listed in the variable `script-representative-chars'.
3942 `:lang'
3944 VALUE must be a symbol of two-letter ISO-639 language names,
3945 e.g. `ja'.
3947 `:otf'
3949 VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
3950 required OpenType features.
3952 SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
3953 LANGSYS-TAG: OpenType language system tag symbol,
3954 or nil for the default language system.
3955 GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
3956 GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
3958 GSUB and GPOS may contain `nil' element. In such a case, the font
3959 must not have any of the remaining elements.
3961 For instance, if the VALUE is `(thai nil nil (mark))', the font must
3962 be an OpenType font, and whose GPOS table of `thai' script's default
3963 language system must contain `mark' feature.
3965 usage: (font-spec ARGS...) */)
3966 (int nargs, Lisp_Object *args)
3968 Lisp_Object spec = font_make_spec ();
3969 int i;
3971 for (i = 0; i < nargs; i += 2)
3973 Lisp_Object key = args[i], val;
3975 CHECK_SYMBOL (key);
3976 if (i + 1 >= nargs)
3977 error ("No value for key `%s'", SDATA (SYMBOL_NAME (key)));
3978 val = args[i + 1];
3980 if (EQ (key, QCname))
3982 CHECK_STRING (val);
3983 font_parse_name ((char *) SDATA (val), spec);
3984 font_put_extra (spec, key, val);
3986 else
3988 int idx = get_font_prop_index (key);
3990 if (idx >= 0)
3992 val = font_prop_validate (idx, Qnil, val);
3993 if (idx < FONT_EXTRA_INDEX)
3994 ASET (spec, idx, val);
3995 else
3996 font_put_extra (spec, key, val);
3998 else
3999 font_put_extra (spec, key, font_prop_validate (0, key, val));
4002 return spec;
4005 DEFUN ("copy-font-spec", Fcopy_font_spec, Scopy_font_spec, 1, 1, 0,
4006 doc: /* Return a copy of FONT as a font-spec. */)
4007 (Lisp_Object font)
4009 Lisp_Object new_spec, tail, prev, extra;
4010 int i;
4012 CHECK_FONT (font);
4013 new_spec = font_make_spec ();
4014 for (i = 1; i < FONT_EXTRA_INDEX; i++)
4015 ASET (new_spec, i, AREF (font, i));
4016 extra = Fcopy_alist (AREF (font, FONT_EXTRA_INDEX));
4017 /* We must remove :font-entity property. */
4018 for (prev = Qnil, tail = extra; CONSP (tail); prev = tail, tail = XCDR (tail))
4019 if (EQ (XCAR (XCAR (tail)), QCfont_entity))
4021 if (NILP (prev))
4022 extra = XCDR (extra);
4023 else
4024 XSETCDR (prev, XCDR (tail));
4025 break;
4027 ASET (new_spec, FONT_EXTRA_INDEX, extra);
4028 return new_spec;
4031 DEFUN ("merge-font-spec", Fmerge_font_spec, Smerge_font_spec, 2, 2, 0,
4032 doc: /* Merge font-specs FROM and TO, and return a new font-spec.
4033 Every specified properties in FROM override the corresponding
4034 properties in TO. */)
4035 (Lisp_Object from, Lisp_Object to)
4037 Lisp_Object extra, tail;
4038 int i;
4040 CHECK_FONT (from);
4041 CHECK_FONT (to);
4042 to = Fcopy_font_spec (to);
4043 for (i = 0; i < FONT_EXTRA_INDEX; i++)
4044 ASET (to, i, AREF (from, i));
4045 extra = AREF (to, FONT_EXTRA_INDEX);
4046 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
4047 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
4049 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
4051 if (! NILP (slot))
4052 XSETCDR (slot, XCDR (XCAR (tail)));
4053 else
4054 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
4056 ASET (to, FONT_EXTRA_INDEX, extra);
4057 return to;
4060 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
4061 doc: /* Return the value of FONT's property KEY.
4062 FONT is a font-spec, a font-entity, or a font-object.
4063 KEY is any symbol, but these are reserved for specific meanings:
4064 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
4065 :size, :name, :script, :otf
4066 See the documentation of `font-spec' for their meanings.
4067 In addition, if FONT is a font-entity or a font-object, values of
4068 :script and :otf are different from those of a font-spec as below:
4070 The value of :script may be a list of scripts that are supported by the font.
4072 The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
4073 representing the OpenType features supported by the font by this form:
4074 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4075 SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
4076 Layout tags. */)
4077 (Lisp_Object font, Lisp_Object key)
4079 int idx;
4080 Lisp_Object val;
4082 CHECK_FONT (font);
4083 CHECK_SYMBOL (key);
4085 idx = get_font_prop_index (key);
4086 if (idx >= FONT_WEIGHT_INDEX && idx <= FONT_WIDTH_INDEX)
4087 return font_style_symbolic (font, idx, 0);
4088 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4089 return AREF (font, idx);
4090 val = Fassq (key, AREF (font, FONT_EXTRA_INDEX));
4091 if (NILP (val) && EQ (key, QCotf) && FONT_OBJECT_P (font))
4093 struct font *fontp = XFONT_OBJECT (font);
4095 if (fontp->driver->otf_capability)
4096 val = fontp->driver->otf_capability (fontp);
4097 else
4098 val = Fcons (Qnil, Qnil);
4099 font_put_extra (font, QCotf, val);
4101 else
4102 val = Fcdr (val);
4103 return val;
4106 #ifdef HAVE_WINDOW_SYSTEM
4108 DEFUN ("font-face-attributes", Ffont_face_attributes, Sfont_face_attributes, 1, 2, 0,
4109 doc: /* Return a plist of face attributes generated by FONT.
4110 FONT is a font name, a font-spec, a font-entity, or a font-object.
4111 The return value is a list of the form
4113 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
4115 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
4116 compatible with `set-face-attribute'. Some of these key-attribute pairs
4117 may be omitted from the list if they are not specified by FONT.
4119 The optional argument FRAME specifies the frame that the face attributes
4120 are to be displayed on. If omitted, the selected frame is used. */)
4121 (Lisp_Object font, Lisp_Object frame)
4123 struct frame *f;
4124 Lisp_Object plist[10];
4125 Lisp_Object val;
4126 int n = 0;
4128 if (NILP (frame))
4129 frame = selected_frame;
4130 CHECK_LIVE_FRAME (frame);
4131 f = XFRAME (frame);
4133 if (STRINGP (font))
4135 int fontset = fs_query_fontset (font, 0);
4136 Lisp_Object name = font;
4137 if (fontset >= 0)
4138 font = fontset_ascii (fontset);
4139 font = font_spec_from_name (name);
4140 if (! FONTP (font))
4141 signal_error ("Invalid font name", name);
4143 else if (! FONTP (font))
4144 signal_error ("Invalid font object", font);
4146 val = AREF (font, FONT_FAMILY_INDEX);
4147 if (! NILP (val))
4149 plist[n++] = QCfamily;
4150 plist[n++] = SYMBOL_NAME (val);
4153 val = AREF (font, FONT_SIZE_INDEX);
4154 if (INTEGERP (val))
4156 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
4157 int dpi = INTEGERP (font_dpi) ? XINT (font_dpi) : f->resy;
4158 plist[n++] = QCheight;
4159 plist[n++] = make_number (PIXEL_TO_POINT (XINT (val) * 10, dpi));
4161 else if (FLOATP (val))
4163 plist[n++] = QCheight;
4164 plist[n++] = make_number (10 * (int) XFLOAT_DATA (val));
4167 val = FONT_WEIGHT_FOR_FACE (font);
4168 if (! NILP (val))
4170 plist[n++] = QCweight;
4171 plist[n++] = val;
4174 val = FONT_SLANT_FOR_FACE (font);
4175 if (! NILP (val))
4177 plist[n++] = QCslant;
4178 plist[n++] = val;
4181 val = FONT_WIDTH_FOR_FACE (font);
4182 if (! NILP (val))
4184 plist[n++] = QCwidth;
4185 plist[n++] = val;
4188 return Flist (n, plist);
4191 #endif
4193 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
4194 doc: /* Set one property of FONT: give property KEY value VAL.
4195 FONT is a font-spec, a font-entity, or a font-object.
4197 If FONT is a font-spec, KEY can be any symbol. But if KEY is the one
4198 accepted by the function `font-spec' (which see), VAL must be what
4199 allowed in `font-spec'.
4201 If FONT is a font-entity or a font-object, KEY must not be the one
4202 accepted by `font-spec'. */)
4203 (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
4205 int idx;
4207 idx = get_font_prop_index (prop);
4208 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4210 CHECK_FONT_SPEC (font);
4211 ASET (font, idx, font_prop_validate (idx, Qnil, val));
4213 else
4215 if (EQ (prop, QCname)
4216 || EQ (prop, QCscript)
4217 || EQ (prop, QClang)
4218 || EQ (prop, QCotf))
4219 CHECK_FONT_SPEC (font);
4220 else
4221 CHECK_FONT (font);
4222 font_put_extra (font, prop, font_prop_validate (0, prop, val));
4224 return val;
4227 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
4228 doc: /* List available fonts matching FONT-SPEC on the current frame.
4229 Optional 2nd argument FRAME specifies the target frame.
4230 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4231 Optional 4th argument PREFER, if non-nil, is a font-spec to
4232 control the order of the returned list. Fonts are sorted by
4233 how close they are to PREFER. */)
4234 (Lisp_Object font_spec, Lisp_Object frame, Lisp_Object num, Lisp_Object prefer)
4236 Lisp_Object vec, list;
4237 int n = 0;
4239 if (NILP (frame))
4240 frame = selected_frame;
4241 CHECK_LIVE_FRAME (frame);
4242 CHECK_FONT_SPEC (font_spec);
4243 if (! NILP (num))
4245 CHECK_NUMBER (num);
4246 n = XINT (num);
4247 if (n <= 0)
4248 return Qnil;
4250 if (! NILP (prefer))
4251 CHECK_FONT_SPEC (prefer);
4253 list = font_list_entities (frame, font_spec);
4254 if (NILP (list))
4255 return Qnil;
4256 if (NILP (XCDR (list))
4257 && ASIZE (XCAR (list)) == 1)
4258 return Fcons (AREF (XCAR (list), 0), Qnil);
4260 if (! NILP (prefer))
4261 vec = font_sort_entities (list, prefer, frame, 0);
4262 else
4263 vec = font_vconcat_entity_vectors (list);
4264 if (n == 0 || n >= ASIZE (vec))
4266 Lisp_Object args[2];
4268 args[0] = vec;
4269 args[1] = Qnil;
4270 list = Fappend (2, args);
4272 else
4274 for (list = Qnil, n--; n >= 0; n--)
4275 list = Fcons (AREF (vec, n), list);
4277 return list;
4280 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
4281 doc: /* List available font families on the current frame.
4282 Optional argument FRAME, if non-nil, specifies the target frame. */)
4283 (Lisp_Object frame)
4285 FRAME_PTR f;
4286 struct font_driver_list *driver_list;
4287 Lisp_Object list;
4289 if (NILP (frame))
4290 frame = selected_frame;
4291 CHECK_LIVE_FRAME (frame);
4292 f = XFRAME (frame);
4293 list = Qnil;
4294 for (driver_list = f->font_driver_list; driver_list;
4295 driver_list = driver_list->next)
4296 if (driver_list->driver->list_family)
4298 Lisp_Object val = driver_list->driver->list_family (frame);
4299 Lisp_Object tail = list;
4301 for (; CONSP (val); val = XCDR (val))
4302 if (NILP (Fmemq (XCAR (val), tail))
4303 && SYMBOLP (XCAR (val)))
4304 list = Fcons (SYMBOL_NAME (XCAR (val)), list);
4306 return list;
4309 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
4310 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
4311 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4312 (Lisp_Object font_spec, Lisp_Object frame)
4314 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
4316 if (CONSP (val))
4317 val = XCAR (val);
4318 return val;
4321 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
4322 doc: /* Return XLFD name of FONT.
4323 FONT is a font-spec, font-entity, or font-object.
4324 If the name is too long for XLFD (maximum 255 chars), return nil.
4325 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4326 the consecutive wildcards are folded to one. */)
4327 (Lisp_Object font, Lisp_Object fold_wildcards)
4329 char name[256];
4330 int pixel_size = 0;
4332 CHECK_FONT (font);
4334 if (FONT_OBJECT_P (font))
4336 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
4338 if (STRINGP (font_name)
4339 && SDATA (font_name)[0] == '-')
4341 if (NILP (fold_wildcards))
4342 return font_name;
4343 strcpy (name, (char *) SDATA (font_name));
4344 goto done;
4346 pixel_size = XFONT_OBJECT (font)->pixel_size;
4348 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
4349 return Qnil;
4350 done:
4351 if (! NILP (fold_wildcards))
4353 char *p0 = name, *p1;
4355 while ((p1 = strstr (p0, "-*-*")))
4357 strcpy (p1, p1 + 2);
4358 p0 = p1;
4362 return build_string (name);
4365 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
4366 doc: /* Clear font cache. */)
4367 (void)
4369 Lisp_Object list, frame;
4371 FOR_EACH_FRAME (list, frame)
4373 FRAME_PTR f = XFRAME (frame);
4374 struct font_driver_list *driver_list = f->font_driver_list;
4376 for (; driver_list; driver_list = driver_list->next)
4377 if (driver_list->on)
4379 Lisp_Object cache = driver_list->driver->get_cache (f);
4380 Lisp_Object val, tmp;
4382 val = XCDR (cache);
4383 while (! NILP (val)
4384 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
4385 val = XCDR (val);
4386 font_assert (! NILP (val));
4387 tmp = XCDR (XCAR (val));
4388 if (XINT (XCAR (tmp)) == 0)
4390 font_clear_cache (f, XCAR (val), driver_list->driver);
4391 XSETCDR (cache, XCDR (val));
4396 return Qnil;
4400 void
4401 font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object)
4403 struct font *font = XFONT_OBJECT (font_object);
4404 unsigned code;
4405 /* ecode used in LGLYPH_SET_CODE to avoid compiler warnings. */
4406 EMACS_INT ecode = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
4407 struct font_metrics metrics;
4409 LGLYPH_SET_CODE (glyph, ecode);
4410 code = ecode;
4411 font->driver->text_extents (font, &code, 1, &metrics);
4412 LGLYPH_SET_LBEARING (glyph, metrics.lbearing);
4413 LGLYPH_SET_RBEARING (glyph, metrics.rbearing);
4414 LGLYPH_SET_WIDTH (glyph, metrics.width);
4415 LGLYPH_SET_ASCENT (glyph, metrics.ascent);
4416 LGLYPH_SET_DESCENT (glyph, metrics.descent);
4420 DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0,
4421 doc: /* Shape the glyph-string GSTRING.
4422 Shaping means substituting glyphs and/or adjusting positions of glyphs
4423 to get the correct visual image of character sequences set in the
4424 header of the glyph-string.
4426 If the shaping was successful, the value is GSTRING itself or a newly
4427 created glyph-string. Otherwise, the value is nil. */)
4428 (Lisp_Object gstring)
4430 struct font *font;
4431 Lisp_Object font_object, n, glyph;
4432 int i, j, from, to;
4434 if (! composition_gstring_p (gstring))
4435 signal_error ("Invalid glyph-string: ", gstring);
4436 if (! NILP (LGSTRING_ID (gstring)))
4437 return gstring;
4438 font_object = LGSTRING_FONT (gstring);
4439 CHECK_FONT_OBJECT (font_object);
4440 font = XFONT_OBJECT (font_object);
4441 if (! font->driver->shape)
4442 return Qnil;
4444 /* Try at most three times with larger gstring each time. */
4445 for (i = 0; i < 3; i++)
4447 n = font->driver->shape (gstring);
4448 if (INTEGERP (n))
4449 break;
4450 gstring = larger_vector (gstring,
4451 ASIZE (gstring) + LGSTRING_GLYPH_LEN (gstring),
4452 Qnil);
4454 if (i == 3 || XINT (n) == 0)
4455 return Qnil;
4456 if (XINT (n) < LGSTRING_GLYPH_LEN (gstring))
4457 LGSTRING_SET_GLYPH (gstring, XINT (n), Qnil);
4459 glyph = LGSTRING_GLYPH (gstring, 0);
4460 from = LGLYPH_FROM (glyph);
4461 to = LGLYPH_TO (glyph);
4462 for (i = 1, j = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
4464 Lisp_Object this = LGSTRING_GLYPH (gstring, i);
4466 if (NILP (this))
4467 break;
4468 if (NILP (LGLYPH_ADJUSTMENT (this)))
4470 if (j < i - 1)
4471 for (; j < i; j++)
4473 glyph = LGSTRING_GLYPH (gstring, j);
4474 LGLYPH_SET_FROM (glyph, from);
4475 LGLYPH_SET_TO (glyph, to);
4477 from = LGLYPH_FROM (this);
4478 to = LGLYPH_TO (this);
4479 j = i;
4481 else
4483 if (from > LGLYPH_FROM (this))
4484 from = LGLYPH_FROM (this);
4485 if (to < LGLYPH_TO (this))
4486 to = LGLYPH_TO (this);
4489 if (j < i - 1)
4490 for (; j < i; j++)
4492 glyph = LGSTRING_GLYPH (gstring, j);
4493 LGLYPH_SET_FROM (glyph, from);
4494 LGLYPH_SET_TO (glyph, to);
4496 return composition_gstring_put_cache (gstring, XINT (n));
4499 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
4500 2, 2, 0,
4501 doc: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4502 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4503 where
4504 VARIATION-SELECTOR is a chracter code of variation selection
4505 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4506 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4507 (Lisp_Object font_object, Lisp_Object character)
4509 unsigned variations[256];
4510 struct font *font;
4511 int i, n;
4512 Lisp_Object val;
4514 CHECK_FONT_OBJECT (font_object);
4515 CHECK_CHARACTER (character);
4516 font = XFONT_OBJECT (font_object);
4517 if (! font->driver->get_variation_glyphs)
4518 return Qnil;
4519 n = font->driver->get_variation_glyphs (font, XINT (character), variations);
4520 if (! n)
4521 return Qnil;
4522 val = Qnil;
4523 for (i = 0; i < 255; i++)
4524 if (variations[i])
4526 Lisp_Object code;
4527 int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
4528 /* Stops GCC whining about limited range of data type. */
4529 EMACS_INT var = variations[i];
4531 if (var > MOST_POSITIVE_FIXNUM)
4532 code = Fcons (make_number ((variations[i]) >> 16),
4533 make_number ((variations[i]) & 0xFFFF));
4534 else
4535 code = make_number (variations[i]);
4536 val = Fcons (Fcons (make_number (vs), code), val);
4538 return val;
4541 #if 0
4543 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
4544 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
4545 OTF-FEATURES specifies which features to apply in this format:
4546 (SCRIPT LANGSYS GSUB GPOS)
4547 where
4548 SCRIPT is a symbol specifying a script tag of OpenType,
4549 LANGSYS is a symbol specifying a langsys tag of OpenType,
4550 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4552 If LANGYS is nil, the default langsys is selected.
4554 The features are applied in the order they appear in the list. The
4555 symbol `*' means to apply all available features not present in this
4556 list, and the remaining features are ignored. For instance, (vatu
4557 pstf * haln) is to apply vatu and pstf in this order, then to apply
4558 all available features other than vatu, pstf, and haln.
4560 The features are applied to the glyphs in the range FROM and TO of
4561 the glyph-string GSTRING-IN.
4563 If some feature is actually applicable, the resulting glyphs are
4564 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4565 this case, the value is the number of produced glyphs.
4567 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4568 the value is 0.
4570 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4571 produced in GSTRING-OUT, and the value is nil.
4573 See the documentation of `font-make-gstring' for the format of
4574 glyph-string. */)
4575 (Lisp_Object otf_features, Lisp_Object gstring_in, Lisp_Object from, Lisp_Object to, Lisp_Object gstring_out, Lisp_Object index)
4577 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
4578 Lisp_Object val;
4579 struct font *font;
4580 int len, num;
4582 check_otf_features (otf_features);
4583 CHECK_FONT_OBJECT (font_object);
4584 font = XFONT_OBJECT (font_object);
4585 if (! font->driver->otf_drive)
4586 error ("Font backend %s can't drive OpenType GSUB table",
4587 SDATA (SYMBOL_NAME (font->driver->type)));
4588 CHECK_CONS (otf_features);
4589 CHECK_SYMBOL (XCAR (otf_features));
4590 val = XCDR (otf_features);
4591 CHECK_SYMBOL (XCAR (val));
4592 val = XCDR (otf_features);
4593 if (! NILP (val))
4594 CHECK_CONS (val);
4595 len = check_gstring (gstring_in);
4596 CHECK_VECTOR (gstring_out);
4597 CHECK_NATNUM (from);
4598 CHECK_NATNUM (to);
4599 CHECK_NATNUM (index);
4601 if (XINT (from) >= XINT (to) || XINT (to) > len)
4602 args_out_of_range_3 (from, to, make_number (len));
4603 if (XINT (index) >= ASIZE (gstring_out))
4604 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4605 num = font->driver->otf_drive (font, otf_features,
4606 gstring_in, XINT (from), XINT (to),
4607 gstring_out, XINT (index), 0);
4608 if (num < 0)
4609 return Qnil;
4610 return make_number (num);
4613 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4614 3, 3, 0,
4615 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4616 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4617 in this format:
4618 (SCRIPT LANGSYS FEATURE ...)
4619 See the documentation of `font-drive-otf' for more detail.
4621 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4622 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4623 character code corresponding to the glyph or nil if there's no
4624 corresponding character. */)
4625 (Lisp_Object font_object, Lisp_Object character, Lisp_Object otf_features)
4627 struct font *font;
4628 Lisp_Object gstring_in, gstring_out, g;
4629 Lisp_Object alternates;
4630 int i, num;
4632 CHECK_FONT_GET_OBJECT (font_object, font);
4633 if (! font->driver->otf_drive)
4634 error ("Font backend %s can't drive OpenType GSUB table",
4635 SDATA (SYMBOL_NAME (font->driver->type)));
4636 CHECK_CHARACTER (character);
4637 CHECK_CONS (otf_features);
4639 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4640 g = LGSTRING_GLYPH (gstring_in, 0);
4641 LGLYPH_SET_CHAR (g, XINT (character));
4642 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4643 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4644 gstring_out, 0, 1)) < 0)
4645 gstring_out = Ffont_make_gstring (font_object,
4646 make_number (ASIZE (gstring_out) * 2));
4647 alternates = Qnil;
4648 for (i = 0; i < num; i++)
4650 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4651 int c = LGLYPH_CHAR (g);
4652 unsigned code = LGLYPH_CODE (g);
4654 alternates = Fcons (Fcons (make_number (code),
4655 c > 0 ? make_number (c) : Qnil),
4656 alternates);
4658 return Fnreverse (alternates);
4660 #endif /* 0 */
4662 #ifdef FONT_DEBUG
4664 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4665 doc: /* Open FONT-ENTITY. */)
4666 (Lisp_Object font_entity, Lisp_Object size, Lisp_Object frame)
4668 int isize;
4670 CHECK_FONT_ENTITY (font_entity);
4671 if (NILP (frame))
4672 frame = selected_frame;
4673 CHECK_LIVE_FRAME (frame);
4675 if (NILP (size))
4676 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4677 else
4679 CHECK_NUMBER_OR_FLOAT (size);
4680 if (FLOATP (size))
4681 isize = POINT_TO_PIXEL (XFLOAT_DATA (size), XFRAME (frame)->resy);
4682 else
4683 isize = XINT (size);
4684 if (isize == 0)
4685 isize = 120;
4687 return font_open_entity (XFRAME (frame), font_entity, isize);
4690 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4691 doc: /* Close FONT-OBJECT. */)
4692 (Lisp_Object font_object, Lisp_Object frame)
4694 CHECK_FONT_OBJECT (font_object);
4695 if (NILP (frame))
4696 frame = selected_frame;
4697 CHECK_LIVE_FRAME (frame);
4698 font_close_object (XFRAME (frame), font_object);
4699 return Qnil;
4702 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4703 doc: /* Return information about FONT-OBJECT.
4704 The value is a vector:
4705 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4706 CAPABILITY ]
4708 NAME is a string of the font name (or nil if the font backend doesn't
4709 provide a name).
4711 FILENAME is a string of the font file (or nil if the font backend
4712 doesn't provide a file name).
4714 PIXEL-SIZE is a pixel size by which the font is opened.
4716 SIZE is a maximum advance width of the font in pixels.
4718 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4719 pixels.
4721 CAPABILITY is a list whose first element is a symbol representing the
4722 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4723 remaining elements describe the details of the font capability.
4725 If the font is OpenType font, the form of the list is
4726 \(opentype GSUB GPOS)
4727 where GSUB shows which "GSUB" features the font supports, and GPOS
4728 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4729 lists of the format:
4730 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4732 If the font is not OpenType font, currently the length of the form is
4733 one.
4735 SCRIPT is a symbol representing OpenType script tag.
4737 LANGSYS is a symbol representing OpenType langsys tag, or nil
4738 representing the default langsys.
4740 FEATURE is a symbol representing OpenType feature tag.
4742 If the font is not OpenType font, CAPABILITY is nil. */)
4743 (Lisp_Object font_object)
4745 struct font *font;
4746 Lisp_Object val;
4748 CHECK_FONT_GET_OBJECT (font_object, font);
4750 val = Fmake_vector (make_number (9), Qnil);
4751 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4752 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4753 ASET (val, 2, make_number (font->pixel_size));
4754 ASET (val, 3, make_number (font->max_width));
4755 ASET (val, 4, make_number (font->ascent));
4756 ASET (val, 5, make_number (font->descent));
4757 ASET (val, 6, make_number (font->space_width));
4758 ASET (val, 7, make_number (font->average_width));
4759 if (font->driver->otf_capability)
4760 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4761 return val;
4764 DEFUN ("font-get-glyphs", Ffont_get_glyphs, Sfont_get_glyphs, 3, 4, 0,
4765 doc:
4766 /* Return a vector of FONT-OBJECT's glyphs for the specified characters.
4767 FROM and TO are positions (integers or markers) specifying a region
4768 of the current buffer.
4769 If the optional fourth arg OBJECT is not nil, it is a string or a
4770 vector containing the target characters.
4772 Each element is a vector containing information of a glyph in this format:
4773 [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
4774 where
4775 FROM is an index numbers of a character the glyph corresponds to.
4776 TO is the same as FROM.
4777 C is the character of the glyph.
4778 CODE is the glyph-code of C in FONT-OBJECT.
4779 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
4780 ADJUSTMENT is always nil.
4781 If FONT-OBJECT doesn't have a glyph for a character,
4782 the corresponding element is nil. */)
4783 (Lisp_Object font_object, Lisp_Object from, Lisp_Object to,
4784 Lisp_Object object)
4786 struct font *font;
4787 int i, len, c;
4788 Lisp_Object *chars, vec;
4789 USE_SAFE_ALLOCA;
4791 CHECK_FONT_GET_OBJECT (font_object, font);
4792 if (NILP (object))
4794 EMACS_INT charpos, bytepos;
4796 validate_region (&from, &to);
4797 if (EQ (from, to))
4798 return Qnil;
4799 len = XFASTINT (to) - XFASTINT (from);
4800 SAFE_ALLOCA_LISP (chars, len);
4801 charpos = XFASTINT (from);
4802 bytepos = CHAR_TO_BYTE (charpos);
4803 for (i = 0; charpos < XFASTINT (to); i++)
4805 FETCH_CHAR_ADVANCE (c, charpos, bytepos);
4806 chars[i] = make_number (c);
4809 else if (STRINGP (object))
4811 const unsigned char *p;
4813 CHECK_NUMBER (from);
4814 CHECK_NUMBER (to);
4815 if (XINT (from) < 0 || XINT (from) > XINT (to)
4816 || XINT (to) > SCHARS (object))
4817 args_out_of_range_3 (object, from, to);
4818 if (EQ (from, to))
4819 return Qnil;
4820 len = XFASTINT (to) - XFASTINT (from);
4821 SAFE_ALLOCA_LISP (chars, len);
4822 p = SDATA (object);
4823 if (STRING_MULTIBYTE (object))
4824 for (i = 0; i < len; i++)
4826 c = STRING_CHAR_ADVANCE (p);
4827 chars[i] = make_number (c);
4829 else
4830 for (i = 0; i < len; i++)
4831 chars[i] = make_number (p[i]);
4833 else
4835 CHECK_VECTOR (object);
4836 CHECK_NUMBER (from);
4837 CHECK_NUMBER (to);
4838 if (XINT (from) < 0 || XINT (from) > XINT (to)
4839 || XINT (to) > ASIZE (object))
4840 args_out_of_range_3 (object, from, to);
4841 if (EQ (from, to))
4842 return Qnil;
4843 len = XFASTINT (to) - XFASTINT (from);
4844 for (i = 0; i < len; i++)
4846 Lisp_Object elt = AREF (object, XFASTINT (from) + i);
4847 CHECK_CHARACTER (elt);
4849 chars = &(AREF (object, XFASTINT (from)));
4852 vec = Fmake_vector (make_number (len), Qnil);
4853 for (i = 0; i < len; i++)
4855 Lisp_Object g;
4856 int c = XFASTINT (chars[i]);
4857 unsigned code;
4858 EMACS_INT cod;
4859 struct font_metrics metrics;
4861 cod = code = font->driver->encode_char (font, c);
4862 if (code == FONT_INVALID_CODE)
4863 continue;
4864 g = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
4865 LGLYPH_SET_FROM (g, i);
4866 LGLYPH_SET_TO (g, i);
4867 LGLYPH_SET_CHAR (g, c);
4868 LGLYPH_SET_CODE (g, code);
4869 font->driver->text_extents (font, &code, 1, &metrics);
4870 LGLYPH_SET_WIDTH (g, metrics.width);
4871 LGLYPH_SET_LBEARING (g, metrics.lbearing);
4872 LGLYPH_SET_RBEARING (g, metrics.rbearing);
4873 LGLYPH_SET_ASCENT (g, metrics.ascent);
4874 LGLYPH_SET_DESCENT (g, metrics.descent);
4875 ASET (vec, i, g);
4877 if (! VECTORP (object))
4878 SAFE_FREE ();
4879 return vec;
4882 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4883 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4884 FONT is a font-spec, font-entity, or font-object. */)
4885 (Lisp_Object spec, Lisp_Object font)
4887 CHECK_FONT_SPEC (spec);
4888 CHECK_FONT (font);
4890 return (font_match_p (spec, font) ? Qt : Qnil);
4893 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4894 doc: /* Return a font-object for displaying a character at POSITION.
4895 Optional second arg WINDOW, if non-nil, is a window displaying
4896 the current buffer. It defaults to the currently selected window. */)
4897 (Lisp_Object position, Lisp_Object window, Lisp_Object string)
4899 struct window *w;
4900 EMACS_INT pos;
4902 if (NILP (string))
4904 CHECK_NUMBER_COERCE_MARKER (position);
4905 pos = XINT (position);
4906 if (pos < BEGV || pos >= ZV)
4907 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4909 else
4911 CHECK_NUMBER (position);
4912 CHECK_STRING (string);
4913 pos = XINT (position);
4914 if (pos < 0 || pos >= SCHARS (string))
4915 args_out_of_range (string, position);
4917 if (NILP (window))
4918 window = selected_window;
4919 CHECK_LIVE_WINDOW (window);
4920 w = XWINDOW (window);
4922 return font_at (-1, pos, NULL, w, string);
4925 #if 0
4926 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4927 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4928 The value is a number of glyphs drawn.
4929 Type C-l to recover what previously shown. */)
4930 (Lisp_Object font_object, Lisp_Object string)
4932 Lisp_Object frame = selected_frame;
4933 FRAME_PTR f = XFRAME (frame);
4934 struct font *font;
4935 struct face *face;
4936 int i, len, width;
4937 unsigned *code;
4939 CHECK_FONT_GET_OBJECT (font_object, font);
4940 CHECK_STRING (string);
4941 len = SCHARS (string);
4942 code = alloca (sizeof (unsigned) * len);
4943 for (i = 0; i < len; i++)
4945 Lisp_Object ch = Faref (string, make_number (i));
4946 Lisp_Object val;
4947 int c = XINT (ch);
4949 code[i] = font->driver->encode_char (font, c);
4950 if (code[i] == FONT_INVALID_CODE)
4951 break;
4953 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4954 face->fontp = font;
4955 if (font->driver->prepare_face)
4956 font->driver->prepare_face (f, face);
4957 width = font->driver->text_extents (font, code, i, NULL);
4958 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4959 if (font->driver->done_face)
4960 font->driver->done_face (f, face);
4961 face->fontp = NULL;
4962 return make_number (len);
4964 #endif
4966 #endif /* FONT_DEBUG */
4968 #ifdef HAVE_WINDOW_SYSTEM
4970 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
4971 doc: /* Return information about a font named NAME on frame FRAME.
4972 If FRAME is omitted or nil, use the selected frame.
4973 The returned value is a vector of OPENED-NAME, FULL-NAME, SIZE,
4974 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4975 where
4976 OPENED-NAME is the name used for opening the font,
4977 FULL-NAME is the full name of the font,
4978 SIZE is the pixelsize of the font,
4979 HEIGHT is the pixel-height of the font (i.e ascent + descent),
4980 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4981 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4982 how to compose characters.
4983 If the named font is not yet loaded, return nil. */)
4984 (Lisp_Object name, Lisp_Object frame)
4986 FRAME_PTR f;
4987 struct font *font;
4988 Lisp_Object info;
4989 Lisp_Object font_object;
4991 (*check_window_system_func) ();
4993 if (! FONTP (name))
4994 CHECK_STRING (name);
4995 if (NILP (frame))
4996 frame = selected_frame;
4997 CHECK_LIVE_FRAME (frame);
4998 f = XFRAME (frame);
5000 if (STRINGP (name))
5002 int fontset = fs_query_fontset (name, 0);
5004 if (fontset >= 0)
5005 name = fontset_ascii (fontset);
5006 font_object = font_open_by_name (f, (char *) SDATA (name));
5008 else if (FONT_OBJECT_P (name))
5009 font_object = name;
5010 else if (FONT_ENTITY_P (name))
5011 font_object = font_open_entity (f, name, 0);
5012 else
5014 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5015 Lisp_Object entity = font_matching_entity (f, face->lface, name);
5017 font_object = ! NILP (entity) ? font_open_entity (f, entity, 0) : Qnil;
5019 if (NILP (font_object))
5020 return Qnil;
5021 font = XFONT_OBJECT (font_object);
5023 info = Fmake_vector (make_number (7), Qnil);
5024 XVECTOR (info)->contents[0] = AREF (font_object, FONT_NAME_INDEX);
5025 XVECTOR (info)->contents[1] = AREF (font_object, FONT_FULLNAME_INDEX);
5026 XVECTOR (info)->contents[2] = make_number (font->pixel_size);
5027 XVECTOR (info)->contents[3] = make_number (font->height);
5028 XVECTOR (info)->contents[4] = make_number (font->baseline_offset);
5029 XVECTOR (info)->contents[5] = make_number (font->relative_compose);
5030 XVECTOR (info)->contents[6] = make_number (font->default_ascent);
5032 #if 0
5033 /* As font_object is still in FONT_OBJLIST of the entity, we can't
5034 close it now. Perhaps, we should manage font-objects
5035 by `reference-count'. */
5036 font_close_object (f, font_object);
5037 #endif
5038 return info;
5040 #endif
5043 #define BUILD_STYLE_TABLE(TBL) \
5044 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
5046 static Lisp_Object
5047 build_style_table (const struct table_entry *entry, int nelement)
5049 int i, j;
5050 Lisp_Object table, elt;
5052 table = Fmake_vector (make_number (nelement), Qnil);
5053 for (i = 0; i < nelement; i++)
5055 for (j = 0; entry[i].names[j]; j++);
5056 elt = Fmake_vector (make_number (j + 1), Qnil);
5057 ASET (elt, 0, make_number (entry[i].numeric));
5058 for (j = 0; entry[i].names[j]; j++)
5059 ASET (elt, j + 1, intern_c_string (entry[i].names[j]));
5060 ASET (table, i, elt);
5062 return table;
5065 Lisp_Object Vfont_log;
5067 /* The deferred font-log data of the form [ACTION ARG RESULT].
5068 If ACTION is not nil, that is added to the log when font_add_log is
5069 called next time. At that time, ACTION is set back to nil. */
5070 static Lisp_Object Vfont_log_deferred;
5072 /* Prepend the font-related logging data in Vfont_log if it is not
5073 `t'. ACTION describes a kind of font-related action (e.g. listing,
5074 opening), ARG is the argument for the action, and RESULT is the
5075 result of the action. */
5076 void
5077 font_add_log (char *action, Lisp_Object arg, Lisp_Object result)
5079 Lisp_Object tail, val;
5080 int i;
5082 if (EQ (Vfont_log, Qt))
5083 return;
5084 if (STRINGP (AREF (Vfont_log_deferred, 0)))
5086 char *str = (char *) SDATA (AREF (Vfont_log_deferred, 0));
5088 ASET (Vfont_log_deferred, 0, Qnil);
5089 font_add_log (str, AREF (Vfont_log_deferred, 1),
5090 AREF (Vfont_log_deferred, 2));
5093 if (FONTP (arg))
5095 Lisp_Object tail, elt;
5096 Lisp_Object equalstr = build_string ("=");
5098 val = Ffont_xlfd_name (arg, Qt);
5099 for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail);
5100 tail = XCDR (tail))
5102 elt = XCAR (tail);
5103 if (EQ (XCAR (elt), QCscript)
5104 && SYMBOLP (XCDR (elt)))
5105 val = concat3 (val, SYMBOL_NAME (QCscript),
5106 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
5107 else if (EQ (XCAR (elt), QClang)
5108 && SYMBOLP (XCDR (elt)))
5109 val = concat3 (val, SYMBOL_NAME (QClang),
5110 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
5111 else if (EQ (XCAR (elt), QCotf)
5112 && CONSP (XCDR (elt)) && SYMBOLP (XCAR (XCDR (elt))))
5113 val = concat3 (val, SYMBOL_NAME (QCotf),
5114 concat2 (equalstr,
5115 SYMBOL_NAME (XCAR (XCDR (elt)))));
5117 arg = val;
5120 if (CONSP (result)
5121 && VECTORP (XCAR (result))
5122 && ASIZE (XCAR (result)) > 0
5123 && FONTP (AREF (XCAR (result), 0)))
5124 result = font_vconcat_entity_vectors (result);
5125 if (FONTP (result))
5127 val = Ffont_xlfd_name (result, Qt);
5128 if (! FONT_SPEC_P (result))
5129 val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)),
5130 build_string (":"), val);
5131 result = val;
5133 else if (CONSP (result))
5135 result = Fcopy_sequence (result);
5136 for (tail = result; CONSP (tail); tail = XCDR (tail))
5138 val = XCAR (tail);
5139 if (FONTP (val))
5140 val = Ffont_xlfd_name (val, Qt);
5141 XSETCAR (tail, val);
5144 else if (VECTORP (result))
5146 result = Fcopy_sequence (result);
5147 for (i = 0; i < ASIZE (result); i++)
5149 val = AREF (result, i);
5150 if (FONTP (val))
5151 val = Ffont_xlfd_name (val, Qt);
5152 ASET (result, i, val);
5155 Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
5158 /* Record a font-related logging data to be added to Vfont_log when
5159 font_add_log is called next time. ACTION, ARG, RESULT are the same
5160 as font_add_log. */
5162 void
5163 font_deferred_log (char *action, Lisp_Object arg, Lisp_Object result)
5165 if (EQ (Vfont_log, Qt))
5166 return;
5167 ASET (Vfont_log_deferred, 0, build_string (action));
5168 ASET (Vfont_log_deferred, 1, arg);
5169 ASET (Vfont_log_deferred, 2, result);
5172 extern void syms_of_ftfont (void);
5173 extern void syms_of_xfont (void);
5174 extern void syms_of_xftfont (void);
5175 extern void syms_of_ftxfont (void);
5176 extern void syms_of_bdffont (void);
5177 extern void syms_of_w32font (void);
5178 extern void syms_of_atmfont (void);
5179 extern void syms_of_nsfont (void);
5181 void
5182 syms_of_font (void)
5184 sort_shift_bits[FONT_TYPE_INDEX] = 0;
5185 sort_shift_bits[FONT_SLANT_INDEX] = 2;
5186 sort_shift_bits[FONT_WEIGHT_INDEX] = 9;
5187 sort_shift_bits[FONT_SIZE_INDEX] = 16;
5188 sort_shift_bits[FONT_WIDTH_INDEX] = 23;
5189 /* Note that the other elements in sort_shift_bits are not used. */
5191 staticpro (&font_charset_alist);
5192 font_charset_alist = Qnil;
5194 DEFSYM (Qopentype, "opentype");
5196 DEFSYM (Qascii_0, "ascii-0");
5197 DEFSYM (Qiso8859_1, "iso8859-1");
5198 DEFSYM (Qiso10646_1, "iso10646-1");
5199 DEFSYM (Qunicode_bmp, "unicode-bmp");
5200 DEFSYM (Qunicode_sip, "unicode-sip");
5202 DEFSYM (QCf, "Cf");
5204 DEFSYM (QCotf, ":otf");
5205 DEFSYM (QClang, ":lang");
5206 DEFSYM (QCscript, ":script");
5207 DEFSYM (QCantialias, ":antialias");
5209 DEFSYM (QCfoundry, ":foundry");
5210 DEFSYM (QCadstyle, ":adstyle");
5211 DEFSYM (QCregistry, ":registry");
5212 DEFSYM (QCspacing, ":spacing");
5213 DEFSYM (QCdpi, ":dpi");
5214 DEFSYM (QCscalable, ":scalable");
5215 DEFSYM (QCavgwidth, ":avgwidth");
5216 DEFSYM (QCfont_entity, ":font-entity");
5217 DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
5219 DEFSYM (Qc, "c");
5220 DEFSYM (Qm, "m");
5221 DEFSYM (Qp, "p");
5222 DEFSYM (Qd, "d");
5224 DEFSYM (Qja, "ja");
5225 DEFSYM (Qko, "ko");
5227 DEFSYM (QCuser_spec, "user-spec");
5229 staticpro (&null_vector);
5230 null_vector = Fmake_vector (make_number (0), Qnil);
5232 staticpro (&scratch_font_spec);
5233 scratch_font_spec = Ffont_spec (0, NULL);
5234 staticpro (&scratch_font_prefer);
5235 scratch_font_prefer = Ffont_spec (0, NULL);
5237 staticpro (&Vfont_log_deferred);
5238 Vfont_log_deferred = Fmake_vector (make_number (3), Qnil);
5240 #if 0
5241 #ifdef HAVE_LIBOTF
5242 staticpro (&otf_list);
5243 otf_list = Qnil;
5244 #endif /* HAVE_LIBOTF */
5245 #endif /* 0 */
5247 defsubr (&Sfontp);
5248 defsubr (&Sfont_spec);
5249 defsubr (&Sfont_get);
5250 #ifdef HAVE_WINDOW_SYSTEM
5251 defsubr (&Sfont_face_attributes);
5252 #endif
5253 defsubr (&Sfont_put);
5254 defsubr (&Slist_fonts);
5255 defsubr (&Sfont_family_list);
5256 defsubr (&Sfind_font);
5257 defsubr (&Sfont_xlfd_name);
5258 defsubr (&Sclear_font_cache);
5259 defsubr (&Sfont_shape_gstring);
5260 defsubr (&Sfont_variation_glyphs);
5261 #if 0
5262 defsubr (&Sfont_drive_otf);
5263 defsubr (&Sfont_otf_alternates);
5264 #endif /* 0 */
5266 #ifdef FONT_DEBUG
5267 defsubr (&Sopen_font);
5268 defsubr (&Sclose_font);
5269 defsubr (&Squery_font);
5270 defsubr (&Sfont_get_glyphs);
5271 defsubr (&Sfont_match_p);
5272 defsubr (&Sfont_at);
5273 #if 0
5274 defsubr (&Sdraw_string);
5275 #endif
5276 #endif /* FONT_DEBUG */
5277 #ifdef HAVE_WINDOW_SYSTEM
5278 defsubr (&Sfont_info);
5279 #endif
5281 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
5282 doc: /*
5283 Alist of fontname patterns vs the corresponding encoding and repertory info.
5284 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5285 where ENCODING is a charset or a char-table,
5286 and REPERTORY is a charset, a char-table, or nil.
5288 If ENCODING and REPERTORY are the same, the element can have the form
5289 \(REGEXP . ENCODING).
5291 ENCODING is for converting a character to a glyph code of the font.
5292 If ENCODING is a charset, encoding a character by the charset gives
5293 the corresponding glyph code. If ENCODING is a char-table, looking up
5294 the table by a character gives the corresponding glyph code.
5296 REPERTORY specifies a repertory of characters supported by the font.
5297 If REPERTORY is a charset, all characters beloging to the charset are
5298 supported. If REPERTORY is a char-table, all characters who have a
5299 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5300 gets the repertory information by an opened font and ENCODING. */);
5301 Vfont_encoding_alist = Qnil;
5303 /* FIXME: These 3 vars are not quite what they appear: setq on them
5304 won't have any effect other than disconnect them from the style
5305 table used by the font display code. So we make them read-only,
5306 to avoid this confusing situation. */
5308 DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table,
5309 doc: /* Vector of valid font weight values.
5310 Each element has the form:
5311 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5312 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5313 Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
5314 XSYMBOL (intern_c_string ("font-weight-table"))->constant = 1;
5316 DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table,
5317 doc: /* Vector of font slant symbols vs the corresponding numeric values.
5318 See `font-weight-table' for the format of the vector. */);
5319 Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
5320 XSYMBOL (intern_c_string ("font-slant-table"))->constant = 1;
5322 DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table,
5323 doc: /* Alist of font width symbols vs the corresponding numeric values.
5324 See `font-weight-table' for the format of the vector. */);
5325 Vfont_width_table = BUILD_STYLE_TABLE (width_table);
5326 XSYMBOL (intern_c_string ("font-width-table"))->constant = 1;
5328 staticpro (&font_style_table);
5329 font_style_table = Fmake_vector (make_number (3), Qnil);
5330 ASET (font_style_table, 0, Vfont_weight_table);
5331 ASET (font_style_table, 1, Vfont_slant_table);
5332 ASET (font_style_table, 2, Vfont_width_table);
5334 DEFVAR_LISP ("font-log", &Vfont_log, doc: /*
5335 *Logging list of font related actions and results.
5336 The value t means to suppress the logging.
5337 The initial value is set to nil if the environment variable
5338 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5339 Vfont_log = Qnil;
5341 #ifdef HAVE_WINDOW_SYSTEM
5342 #ifdef HAVE_FREETYPE
5343 syms_of_ftfont ();
5344 #ifdef HAVE_X_WINDOWS
5345 syms_of_xfont ();
5346 syms_of_ftxfont ();
5347 #ifdef HAVE_XFT
5348 syms_of_xftfont ();
5349 #endif /* HAVE_XFT */
5350 #endif /* HAVE_X_WINDOWS */
5351 #else /* not HAVE_FREETYPE */
5352 #ifdef HAVE_X_WINDOWS
5353 syms_of_xfont ();
5354 #endif /* HAVE_X_WINDOWS */
5355 #endif /* not HAVE_FREETYPE */
5356 #ifdef HAVE_BDFFONT
5357 syms_of_bdffont ();
5358 #endif /* HAVE_BDFFONT */
5359 #ifdef WINDOWSNT
5360 syms_of_w32font ();
5361 #endif /* WINDOWSNT */
5362 #ifdef HAVE_NS
5363 syms_of_nsfont ();
5364 #endif /* HAVE_NS */
5365 #endif /* HAVE_WINDOW_SYSTEM */
5368 void
5369 init_font (void)
5371 Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;
5374 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
5375 (do not change this comment) */