* verilog-mode.el (verilog-getopt-file, verilog-set-define):
[emacs.git] / src / font.c
blob6e33b9bec554b361d1ce3a5a9b6ab3417a965f25
1 /* font.c -- "Font" primitives.
2 Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009
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 char *names[5];
83 Lisp_Object *symbols;
86 /* Table of weight numeric values and their names. This table must be
87 sorted by numeric values in ascending order. */
89 static struct table_entry weight_table[] =
91 { 0, { "thin" }},
92 { 20, { "ultra-light", "ultralight" }},
93 { 40, { "extra-light", "extralight" }},
94 { 50, { "light" }},
95 { 75, { "semi-light", "semilight", "demilight", "book" }},
96 { 100, { "normal", "medium", "regular", "unspecified" }},
97 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
98 { 200, { "bold" }},
99 { 205, { "extra-bold", "extrabold" }},
100 { 210, { "ultra-bold", "ultrabold", "black" }}
103 /* Table of slant numeric values and their names. This table must be
104 sorted by numeric values in ascending order. */
106 static struct table_entry slant_table[] =
108 { 0, { "reverse-oblique", "ro" }},
109 { 10, { "reverse-italic", "ri" }},
110 { 100, { "normal", "r", "unspecified" }},
111 { 200, { "italic" ,"i", "ot" }},
112 { 210, { "oblique", "o" }}
115 /* Table of width numeric values and their names. This table must be
116 sorted by numeric values in ascending order. */
118 static struct table_entry width_table[] =
120 { 50, { "ultra-condensed", "ultracondensed" }},
121 { 63, { "extra-condensed", "extracondensed" }},
122 { 75, { "condensed", "compressed", "narrow" }},
123 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
124 { 100, { "normal", "medium", "regular", "unspecified" }},
125 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
126 { 125, { "expanded" }},
127 { 150, { "extra-expanded", "extraexpanded" }},
128 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
131 extern Lisp_Object Qnormal;
133 /* Symbols representing keys of normal font properties. */
134 extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth;
135 extern Lisp_Object QCheight, QCsize, QCname;
137 Lisp_Object QCfoundry, QCadstyle, QCregistry;
138 /* Symbols representing keys of font extra info. */
139 Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
140 Lisp_Object QCantialias, QCfont_entity, QCfc_unknown_spec;
141 /* Symbols representing values of font spacing property. */
142 Lisp_Object Qc, Qm, Qp, Qd;
143 /* Special ADSTYLE properties to avoid fonts used for Latin
144 characters; used in xfont.c and ftfont.c. */
145 Lisp_Object Qja, Qko;
147 Lisp_Object Vfont_encoding_alist;
149 /* Alist of font registry symbol and the corresponding charsets
150 information. The information is retrieved from
151 Vfont_encoding_alist on demand.
153 Eash element has the form:
154 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
156 (REGISTRY . nil)
158 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
159 encodes a character code to a glyph code of a font, and
160 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
161 character is supported by a font.
163 The latter form means that the information for REGISTRY couldn't be
164 retrieved. */
165 static Lisp_Object font_charset_alist;
167 /* List of all font drivers. Each font-backend (XXXfont.c) calls
168 register_font_driver in syms_of_XXXfont to register its font-driver
169 here. */
170 static struct font_driver_list *font_driver_list;
174 /* Creaters of font-related Lisp object. */
176 Lisp_Object
177 font_make_spec ()
179 Lisp_Object font_spec;
180 struct font_spec *spec
181 = ((struct font_spec *)
182 allocate_pseudovector (VECSIZE (struct font_spec),
183 FONT_SPEC_MAX, PVEC_FONT));
184 XSETFONT (font_spec, spec);
185 return font_spec;
188 Lisp_Object
189 font_make_entity ()
191 Lisp_Object font_entity;
192 struct font_entity *entity
193 = ((struct font_entity *)
194 allocate_pseudovector (VECSIZE (struct font_entity),
195 FONT_ENTITY_MAX, PVEC_FONT));
196 XSETFONT (font_entity, entity);
197 return font_entity;
200 /* Create a font-object whose structure size is SIZE. If ENTITY is
201 not nil, copy properties from ENTITY to the font-object. If
202 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
203 Lisp_Object
204 font_make_object (size, entity, pixelsize)
205 int size;
206 Lisp_Object entity;
207 int pixelsize;
209 Lisp_Object font_object;
210 struct font *font
211 = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX, PVEC_FONT);
212 int i;
214 XSETFONT (font_object, font);
216 if (! NILP (entity))
218 for (i = 1; i < FONT_SPEC_MAX; i++)
219 font->props[i] = AREF (entity, i);
220 if (! NILP (AREF (entity, FONT_EXTRA_INDEX)))
221 font->props[FONT_EXTRA_INDEX]
222 = Fcopy_sequence (AREF (entity, FONT_EXTRA_INDEX));
224 if (size > 0)
225 font->props[FONT_SIZE_INDEX] = make_number (pixelsize);
226 return font_object;
231 static int font_pixel_size P_ ((FRAME_PTR f, Lisp_Object));
232 static Lisp_Object font_open_entity P_ ((FRAME_PTR, Lisp_Object, int));
233 static Lisp_Object font_matching_entity P_ ((FRAME_PTR, Lisp_Object *,
234 Lisp_Object));
236 /* Number of registered font drivers. */
237 static int num_font_drivers;
240 /* Return a Lispy value of a font property value at STR and LEN bytes.
241 If STR is "*", it returns nil.
242 If FORCE_SYMBOL is zero and all characters in STR are digits, it
243 returns an integer. Otherwise, it returns a symbol interned from
244 STR. */
246 Lisp_Object
247 font_intern_prop (str, len, force_symbol)
248 char *str;
249 int len;
250 int force_symbol;
252 int i;
253 Lisp_Object tem;
254 Lisp_Object obarray;
255 int nbytes, nchars;
257 if (len == 1 && *str == '*')
258 return Qnil;
259 if (!force_symbol && len >=1 && isdigit (*str))
261 for (i = 1; i < len; i++)
262 if (! isdigit (str[i]))
263 break;
264 if (i == len)
265 return make_number (atoi (str));
268 /* The following code is copied from the function intern (in
269 lread.c), and modified to suite our purpose. */
270 obarray = Vobarray;
271 if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
272 obarray = check_obarray (obarray);
273 parse_str_as_multibyte ((unsigned char *) str, len, &nchars, &nbytes);
274 if (len == nchars || len != nbytes)
275 /* CONTENTS contains no multibyte sequences or contains an invalid
276 multibyte sequence. We'll make a unibyte string. */
277 tem = oblookup (obarray, str, len, len);
278 else
279 tem = oblookup (obarray, str, nchars, len);
280 if (SYMBOLP (tem))
281 return tem;
282 if (len == nchars || len != nbytes)
283 tem = make_unibyte_string (str, len);
284 else
285 tem = make_multibyte_string (str, nchars, len);
286 return Fintern (tem, obarray);
289 /* Return a pixel size of font-spec SPEC on frame F. */
291 static int
292 font_pixel_size (f, spec)
293 FRAME_PTR f;
294 Lisp_Object spec;
296 #ifdef HAVE_WINDOW_SYSTEM
297 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
298 double point_size;
299 int dpi, pixel_size;
300 Lisp_Object val;
302 if (INTEGERP (size))
303 return XINT (size);
304 if (NILP (size))
305 return 0;
306 font_assert (FLOATP (size));
307 point_size = XFLOAT_DATA (size);
308 val = AREF (spec, FONT_DPI_INDEX);
309 if (INTEGERP (val))
310 dpi = XINT (val);
311 else
312 dpi = f->resy;
313 pixel_size = POINT_TO_PIXEL (point_size, dpi);
314 return pixel_size;
315 #else
316 return 1;
317 #endif
321 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
322 font vector. If VAL is not valid (i.e. not registered in
323 font_style_table), return -1 if NOERROR is zero, and return a
324 proper index if NOERROR is nonzero. In that case, register VAL in
325 font_style_table if VAL is a symbol, and return a closest index if
326 VAL is an integer. */
329 font_style_to_value (prop, val, noerror)
330 enum font_property_index prop;
331 Lisp_Object val;
332 int noerror;
334 Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
335 int len = ASIZE (table);
336 int i, j;
338 if (SYMBOLP (val))
340 unsigned char *s;
341 Lisp_Object args[2], elt;
343 /* At first try exact match. */
344 for (i = 0; i < len; i++)
345 for (j = 1; j < ASIZE (AREF (table, i)); j++)
346 if (EQ (val, AREF (AREF (table, i), j)))
347 return ((XINT (AREF (AREF (table, i), 0)) << 8)
348 | (i << 4) | (j - 1));
349 /* Try also with case-folding match. */
350 s = SDATA (SYMBOL_NAME (val));
351 for (i = 0; i < len; i++)
352 for (j = 1; j < ASIZE (AREF (table, i)); j++)
354 elt = AREF (AREF (table, i), j);
355 if (xstrcasecmp (s, SDATA (SYMBOL_NAME (elt))) == 0)
356 return ((XINT (AREF (AREF (table, i), 0)) << 8)
357 | (i << 4) | (j - 1));
359 if (! noerror)
360 return -1;
361 if (len == 255)
362 abort ();
363 elt = Fmake_vector (make_number (2), make_number (100));
364 ASET (elt, 1, val);
365 args[0] = table;
366 args[1] = Fmake_vector (make_number (1), elt);
367 ASET (font_style_table, prop - FONT_WEIGHT_INDEX, Fvconcat (2, args));
368 return (100 << 8) | (i << 4);
370 else
372 int i, last_n;
373 int numeric = XINT (val);
375 for (i = 0, last_n = -1; i < len; i++)
377 int n = XINT (AREF (AREF (table, i), 0));
379 if (numeric == n)
380 return (n << 8) | (i << 4);
381 if (numeric < n)
383 if (! noerror)
384 return -1;
385 return ((i == 0 || n - numeric < numeric - last_n)
386 ? (n << 8) | (i << 4): (last_n << 8 | ((i - 1) << 4)));
388 last_n = n;
390 if (! noerror)
391 return -1;
392 return ((last_n << 8) | ((i - 1) << 4));
396 Lisp_Object
397 font_style_symbolic (font, prop, for_face)
398 Lisp_Object font;
399 enum font_property_index prop;
400 int for_face;
402 Lisp_Object val = AREF (font, prop);
403 Lisp_Object table, elt;
404 int i;
406 if (NILP (val))
407 return Qnil;
408 table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
409 i = XINT (val) & 0xFF;
410 font_assert (((i >> 4) & 0xF) < ASIZE (table));
411 elt = AREF (table, ((i >> 4) & 0xF));
412 font_assert ((i & 0xF) + 1 < ASIZE (elt));
413 return (for_face ? AREF (elt, 1) : AREF (elt, (i & 0xF) + 1));
416 extern Lisp_Object Vface_alternative_font_family_alist;
418 extern Lisp_Object find_font_encoding P_ ((Lisp_Object));
421 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
422 FONTNAME. ENCODING is a charset symbol that specifies the encoding
423 of the font. REPERTORY is a charset symbol or nil. */
425 Lisp_Object
426 find_font_encoding (fontname)
427 Lisp_Object fontname;
429 Lisp_Object tail, elt;
431 for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
433 elt = XCAR (tail);
434 if (CONSP (elt)
435 && STRINGP (XCAR (elt))
436 && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
437 && (SYMBOLP (XCDR (elt))
438 ? CHARSETP (XCDR (elt))
439 : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
440 return (XCDR (elt));
442 return Qnil;
445 /* Return encoding charset and repertory charset for REGISTRY in
446 ENCODING and REPERTORY correspondingly. If correct information for
447 REGISTRY is available, return 0. Otherwise return -1. */
450 font_registry_charsets (registry, encoding, repertory)
451 Lisp_Object registry;
452 struct charset **encoding, **repertory;
454 Lisp_Object val;
455 int encoding_id, repertory_id;
457 val = Fassoc_string (registry, font_charset_alist, Qt);
458 if (! NILP (val))
460 val = XCDR (val);
461 if (NILP (val))
462 return -1;
463 encoding_id = XINT (XCAR (val));
464 repertory_id = XINT (XCDR (val));
466 else
468 val = find_font_encoding (SYMBOL_NAME (registry));
469 if (SYMBOLP (val) && CHARSETP (val))
471 encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val));
473 else if (CONSP (val))
475 if (! CHARSETP (XCAR (val)))
476 goto invalid_entry;
477 encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val)));
478 if (NILP (XCDR (val)))
479 repertory_id = -1;
480 else
482 if (! CHARSETP (XCDR (val)))
483 goto invalid_entry;
484 repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val)));
487 else
488 goto invalid_entry;
489 val = Fcons (make_number (encoding_id), make_number (repertory_id));
490 font_charset_alist
491 = nconc2 (font_charset_alist, Fcons (Fcons (registry, val), Qnil));
494 if (encoding)
495 *encoding = CHARSET_FROM_ID (encoding_id);
496 if (repertory)
497 *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL;
498 return 0;
500 invalid_entry:
501 font_charset_alist
502 = nconc2 (font_charset_alist, Fcons (Fcons (registry, Qnil), Qnil));
503 return -1;
507 /* Font property value validaters. See the comment of
508 font_property_table for the meaning of the arguments. */
510 static Lisp_Object font_prop_validate P_ ((int, Lisp_Object, Lisp_Object));
511 static Lisp_Object font_prop_validate_symbol P_ ((Lisp_Object, Lisp_Object));
512 static Lisp_Object font_prop_validate_style P_ ((Lisp_Object, Lisp_Object));
513 static Lisp_Object font_prop_validate_non_neg P_ ((Lisp_Object, Lisp_Object));
514 static Lisp_Object font_prop_validate_spacing P_ ((Lisp_Object, Lisp_Object));
515 static int get_font_prop_index P_ ((Lisp_Object));
517 static Lisp_Object
518 font_prop_validate_symbol (prop, val)
519 Lisp_Object prop, val;
521 if (STRINGP (val))
522 val = Fintern (val, Qnil);
523 if (! SYMBOLP (val))
524 val = Qerror;
525 else if (EQ (prop, QCregistry))
526 val = Fintern (Fdowncase (SYMBOL_NAME (val)), Qnil);
527 return val;
531 static Lisp_Object
532 font_prop_validate_style (style, val)
533 Lisp_Object style, val;
535 enum font_property_index prop = (EQ (style, QCweight) ? FONT_WEIGHT_INDEX
536 : EQ (style, QCslant) ? FONT_SLANT_INDEX
537 : FONT_WIDTH_INDEX);
538 int n;
539 if (INTEGERP (val))
541 n = XINT (val);
542 if (((n >> 4) & 0xF)
543 >= ASIZE (AREF (font_style_table, prop - FONT_WEIGHT_INDEX)))
544 val = Qerror;
545 else
547 Lisp_Object elt = AREF (AREF (font_style_table, prop - FONT_WEIGHT_INDEX), (n >> 4) & 0xF);
549 if ((n & 0xF) + 1 >= ASIZE (elt))
550 val = Qerror;
551 else if (XINT (AREF (elt, 0)) != (n >> 8))
552 val = Qerror;
555 else if (SYMBOLP (val))
557 int n = font_style_to_value (prop, val, 0);
559 val = n >= 0 ? make_number (n) : Qerror;
561 else
562 val = Qerror;
563 return val;
566 static Lisp_Object
567 font_prop_validate_non_neg (prop, val)
568 Lisp_Object prop, val;
570 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
571 ? val : Qerror);
574 static Lisp_Object
575 font_prop_validate_spacing (prop, val)
576 Lisp_Object prop, val;
578 if (NILP (val) || (NATNUMP (val) && XINT (val) <= FONT_SPACING_CHARCELL))
579 return val;
580 if (SYMBOLP (val) && SBYTES (SYMBOL_NAME (val)) == 1)
582 char spacing = SDATA (SYMBOL_NAME (val))[0];
584 if (spacing == 'c' || spacing == 'C')
585 return make_number (FONT_SPACING_CHARCELL);
586 if (spacing == 'm' || spacing == 'M')
587 return make_number (FONT_SPACING_MONO);
588 if (spacing == 'p' || spacing == 'P')
589 return make_number (FONT_SPACING_PROPORTIONAL);
590 if (spacing == 'd' || spacing == 'D')
591 return make_number (FONT_SPACING_DUAL);
593 return Qerror;
596 static Lisp_Object
597 font_prop_validate_otf (prop, val)
598 Lisp_Object prop, val;
600 Lisp_Object tail, tmp;
601 int i;
603 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
604 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
605 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
606 if (! CONSP (val))
607 return Qerror;
608 if (! SYMBOLP (XCAR (val)))
609 return Qerror;
610 tail = XCDR (val);
611 if (NILP (tail))
612 return val;
613 if (! CONSP (tail) || ! SYMBOLP (XCAR (val)))
614 return Qerror;
615 for (i = 0; i < 2; i++)
617 tail = XCDR (tail);
618 if (NILP (tail))
619 return val;
620 if (! CONSP (tail))
621 return Qerror;
622 for (tmp = XCAR (tail); CONSP (tmp); tmp = XCDR (tmp))
623 if (! SYMBOLP (XCAR (tmp)))
624 return Qerror;
625 if (! NILP (tmp))
626 return Qerror;
628 return val;
631 /* Structure of known font property keys and validater of the
632 values. */
633 struct
635 /* Pointer to the key symbol. */
636 Lisp_Object *key;
637 /* Function to validate PROP's value VAL, or NULL if any value is
638 ok. The value is VAL or its regularized value if VAL is valid,
639 and Qerror if not. */
640 Lisp_Object (*validater) P_ ((Lisp_Object prop, Lisp_Object val));
641 } font_property_table[] =
642 { { &QCtype, font_prop_validate_symbol },
643 { &QCfoundry, font_prop_validate_symbol },
644 { &QCfamily, font_prop_validate_symbol },
645 { &QCadstyle, font_prop_validate_symbol },
646 { &QCregistry, font_prop_validate_symbol },
647 { &QCweight, font_prop_validate_style },
648 { &QCslant, font_prop_validate_style },
649 { &QCwidth, font_prop_validate_style },
650 { &QCsize, font_prop_validate_non_neg },
651 { &QCdpi, font_prop_validate_non_neg },
652 { &QCspacing, font_prop_validate_spacing },
653 { &QCavgwidth, font_prop_validate_non_neg },
654 /* The order of the above entries must match with enum
655 font_property_index. */
656 { &QClang, font_prop_validate_symbol },
657 { &QCscript, font_prop_validate_symbol },
658 { &QCotf, font_prop_validate_otf }
661 /* Size (number of elements) of the above table. */
662 #define FONT_PROPERTY_TABLE_SIZE \
663 ((sizeof font_property_table) / (sizeof *font_property_table))
665 /* Return an index number of font property KEY or -1 if KEY is not an
666 already known property. */
668 static int
669 get_font_prop_index (key)
670 Lisp_Object key;
672 int i;
674 for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++)
675 if (EQ (key, *font_property_table[i].key))
676 return i;
677 return -1;
680 /* Validate the font property. The property key is specified by the
681 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
682 signal an error. The value is VAL or the regularized one. */
684 static Lisp_Object
685 font_prop_validate (idx, prop, val)
686 int idx;
687 Lisp_Object prop, val;
689 Lisp_Object validated;
691 if (NILP (val))
692 return val;
693 if (NILP (prop))
694 prop = *font_property_table[idx].key;
695 else
697 idx = get_font_prop_index (prop);
698 if (idx < 0)
699 return val;
701 validated = (font_property_table[idx].validater) (prop, val);
702 if (EQ (validated, Qerror))
703 signal_error ("invalid font property", Fcons (prop, val));
704 return validated;
708 /* Store VAL as a value of extra font property PROP in FONT while
709 keeping the sorting order. Don't check the validity of VAL. */
711 Lisp_Object
712 font_put_extra (font, prop, val)
713 Lisp_Object font, prop, val;
715 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
716 Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
718 if (NILP (slot))
720 Lisp_Object prev = Qnil;
722 if (NILP (val))
723 return val;
724 while (CONSP (extra)
725 && NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
726 prev = extra, extra = XCDR (extra);
727 if (NILP (prev))
728 ASET (font, FONT_EXTRA_INDEX, Fcons (Fcons (prop, val), extra));
729 else
730 XSETCDR (prev, Fcons (Fcons (prop, val), extra));
731 return val;
733 XSETCDR (slot, val);
734 if (NILP (val))
735 ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra));
736 return val;
740 /* Font name parser and unparser */
742 static int parse_matrix P_ ((char *));
743 static int font_expand_wildcards P_ ((Lisp_Object *, int));
744 static int font_parse_name P_ ((char *, Lisp_Object));
746 /* An enumerator for each field of an XLFD font name. */
747 enum xlfd_field_index
749 XLFD_FOUNDRY_INDEX,
750 XLFD_FAMILY_INDEX,
751 XLFD_WEIGHT_INDEX,
752 XLFD_SLANT_INDEX,
753 XLFD_SWIDTH_INDEX,
754 XLFD_ADSTYLE_INDEX,
755 XLFD_PIXEL_INDEX,
756 XLFD_POINT_INDEX,
757 XLFD_RESX_INDEX,
758 XLFD_RESY_INDEX,
759 XLFD_SPACING_INDEX,
760 XLFD_AVGWIDTH_INDEX,
761 XLFD_REGISTRY_INDEX,
762 XLFD_ENCODING_INDEX,
763 XLFD_LAST_INDEX
766 /* An enumerator for mask bit corresponding to each XLFD field. */
767 enum xlfd_field_mask
769 XLFD_FOUNDRY_MASK = 0x0001,
770 XLFD_FAMILY_MASK = 0x0002,
771 XLFD_WEIGHT_MASK = 0x0004,
772 XLFD_SLANT_MASK = 0x0008,
773 XLFD_SWIDTH_MASK = 0x0010,
774 XLFD_ADSTYLE_MASK = 0x0020,
775 XLFD_PIXEL_MASK = 0x0040,
776 XLFD_POINT_MASK = 0x0080,
777 XLFD_RESX_MASK = 0x0100,
778 XLFD_RESY_MASK = 0x0200,
779 XLFD_SPACING_MASK = 0x0400,
780 XLFD_AVGWIDTH_MASK = 0x0800,
781 XLFD_REGISTRY_MASK = 0x1000,
782 XLFD_ENCODING_MASK = 0x2000
786 /* Parse P pointing the pixel/point size field of the form
787 `[A B C D]' which specifies a transformation matrix:
789 A B 0
790 C D 0
791 0 0 1
793 by which all glyphs of the font are transformed. The spec says
794 that scalar value N for the pixel/point size is equivalent to:
795 A = N * resx/resy, B = C = 0, D = N.
797 Return the scalar value N if the form is valid. Otherwise return
798 -1. */
800 static int
801 parse_matrix (p)
802 char *p;
804 double matrix[4];
805 char *end;
806 int i;
808 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
810 if (*p == '~')
811 matrix[i] = - strtod (p + 1, &end);
812 else
813 matrix[i] = strtod (p, &end);
814 p = end;
816 return (i == 4 ? (int) matrix[3] : -1);
819 /* Expand a wildcard field in FIELD (the first N fields are filled) to
820 multiple fields to fill in all 14 XLFD fields while restring a
821 field position by its contents. */
823 static int
824 font_expand_wildcards (field, n)
825 Lisp_Object field[XLFD_LAST_INDEX];
826 int n;
828 /* Copy of FIELD. */
829 Lisp_Object tmp[XLFD_LAST_INDEX];
830 /* Array of information about where this element can go. Nth
831 element is for Nth element of FIELD. */
832 struct {
833 /* Minimum possible field. */
834 int from;
835 /* Maxinum possible field. */
836 int to;
837 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
838 int mask;
839 } range[XLFD_LAST_INDEX];
840 int i, j;
841 int range_from, range_to;
842 unsigned range_mask;
844 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
845 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
846 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
847 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
848 | XLFD_AVGWIDTH_MASK)
849 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
851 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
852 field. The value is shifted to left one bit by one in the
853 following loop. */
854 for (i = 0, range_mask = 0; i <= 14 - n; i++)
855 range_mask = (range_mask << 1) | 1;
857 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
858 position-based retriction for FIELD[I]. */
859 for (i = 0, range_from = 0, range_to = 14 - n; i < n;
860 i++, range_from++, range_to++, range_mask <<= 1)
862 Lisp_Object val = field[i];
864 tmp[i] = val;
865 if (NILP (val))
867 /* Wildcard. */
868 range[i].from = range_from;
869 range[i].to = range_to;
870 range[i].mask = range_mask;
872 else
874 /* The triplet FROM, TO, and MASK is a value-based
875 retriction for FIELD[I]. */
876 int from, to;
877 unsigned mask;
879 if (INTEGERP (val))
881 int numeric = XINT (val);
883 if (i + 1 == n)
884 from = to = XLFD_ENCODING_INDEX,
885 mask = XLFD_ENCODING_MASK;
886 else if (numeric == 0)
887 from = XLFD_PIXEL_INDEX, to = XLFD_AVGWIDTH_INDEX,
888 mask = XLFD_PIXEL_MASK | XLFD_LARGENUM_MASK;
889 else if (numeric <= 48)
890 from = to = XLFD_PIXEL_INDEX,
891 mask = XLFD_PIXEL_MASK;
892 else
893 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
894 mask = XLFD_LARGENUM_MASK;
896 else if (SBYTES (SYMBOL_NAME (val)) == 0)
897 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
898 mask = XLFD_NULL_MASK;
899 else if (i == 0)
900 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
901 else if (i + 1 == n)
903 Lisp_Object name = SYMBOL_NAME (val);
905 if (SDATA (name)[SBYTES (name) - 1] == '*')
906 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
907 mask = XLFD_REGENC_MASK;
908 else
909 from = to = XLFD_ENCODING_INDEX,
910 mask = XLFD_ENCODING_MASK;
912 else if (range_from <= XLFD_WEIGHT_INDEX
913 && range_to >= XLFD_WEIGHT_INDEX
914 && FONT_WEIGHT_NAME_NUMERIC (val) >= 0)
915 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
916 else if (range_from <= XLFD_SLANT_INDEX
917 && range_to >= XLFD_SLANT_INDEX
918 && FONT_SLANT_NAME_NUMERIC (val) >= 0)
919 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
920 else if (range_from <= XLFD_SWIDTH_INDEX
921 && range_to >= XLFD_SWIDTH_INDEX
922 && FONT_WIDTH_NAME_NUMERIC (val) >= 0)
923 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
924 else
926 if (EQ (val, Qc) || EQ (val, Qm) || EQ (val, Qp) || EQ (val, Qd))
927 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
928 else
929 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
930 mask = XLFD_SYMBOL_MASK;
933 /* Merge position-based and value-based restrictions. */
934 mask &= range_mask;
935 while (from < range_from)
936 mask &= ~(1 << from++);
937 while (from < 14 && ! (mask & (1 << from)))
938 from++;
939 while (to > range_to)
940 mask &= ~(1 << to--);
941 while (to >= 0 && ! (mask & (1 << to)))
942 to--;
943 if (from > to)
944 return -1;
945 range[i].from = from;
946 range[i].to = to;
947 range[i].mask = mask;
949 if (from > range_from || to < range_to)
951 /* The range is narrowed by value-based restrictions.
952 Reflect it to the other fields. */
954 /* Following fields should be after FROM. */
955 range_from = from;
956 /* Preceding fields should be before TO. */
957 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
959 /* Check FROM for non-wildcard field. */
960 if (! NILP (tmp[j]) && range[j].from < from)
962 while (range[j].from < from)
963 range[j].mask &= ~(1 << range[j].from++);
964 while (from < 14 && ! (range[j].mask & (1 << from)))
965 from++;
966 range[j].from = from;
968 else
969 from = range[j].from;
970 if (range[j].to > to)
972 while (range[j].to > to)
973 range[j].mask &= ~(1 << range[j].to--);
974 while (to >= 0 && ! (range[j].mask & (1 << to)))
975 to--;
976 range[j].to = to;
978 else
979 to = range[j].to;
980 if (from > to)
981 return -1;
987 /* Decide all fileds from restrictions in RANGE. */
988 for (i = j = 0; i < n ; i++)
990 if (j < range[i].from)
992 if (i == 0 || ! NILP (tmp[i - 1]))
993 /* None of TMP[X] corresponds to Jth field. */
994 return -1;
995 for (; j < range[i].from; j++)
996 field[j] = Qnil;
998 field[j++] = tmp[i];
1000 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
1001 return -1;
1002 for (; j < XLFD_LAST_INDEX; j++)
1003 field[j] = Qnil;
1004 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
1005 field[XLFD_ENCODING_INDEX]
1006 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
1007 return 0;
1011 #ifdef ENABLE_CHECKING
1012 /* Match a 14-field XLFD pattern against a full XLFD font name. */
1013 static int
1014 font_match_xlfd (char *pattern, char *name)
1016 while (*pattern && *name)
1018 if (*pattern == *name)
1019 pattern++;
1020 else if (*pattern == '*')
1021 if (*name == pattern[1])
1022 pattern += 2;
1023 else
1025 else
1026 return 0;
1027 name++;
1029 return 1;
1032 /* Make sure the font object matches the XLFD font name. */
1033 static int
1034 font_check_xlfd_parse (Lisp_Object font, char *name)
1036 char name_check[256];
1037 font_unparse_xlfd (font, 0, name_check, 255);
1038 return font_match_xlfd (name_check, name);
1041 #endif
1044 /* Parse NAME (null terminated) as XLFD and store information in FONT
1045 (font-spec or font-entity). Size property of FONT is set as
1046 follows:
1047 specified XLFD fields FONT property
1048 --------------------- -------------
1049 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
1050 POINT_SIZE and RESY calculated pixel size (Lisp integer)
1051 POINT_SIZE POINT_SIZE/10 (Lisp float)
1053 If NAME is successfully parsed, return 0. Otherwise return -1.
1055 FONT is usually a font-spec, but when this function is called from
1056 X font backend driver, it is a font-entity. In that case, NAME is
1057 a fully specified XLFD. */
1060 font_parse_xlfd (name, font)
1061 char *name;
1062 Lisp_Object font;
1064 int len = strlen (name);
1065 int i, j, n;
1066 char *f[XLFD_LAST_INDEX + 1];
1067 Lisp_Object val;
1068 char *p;
1070 if (len > 255 || !len)
1071 /* Maximum XLFD name length is 255. */
1072 return -1;
1073 /* Accept "*-.." as a fully specified XLFD. */
1074 if (name[0] == '*' && (len == 1 || name[1] == '-'))
1075 i = 1, f[XLFD_FOUNDRY_INDEX] = name;
1076 else
1077 i = 0;
1078 for (p = name + i; *p; p++)
1079 if (*p == '-')
1081 f[i++] = p + 1;
1082 if (i == XLFD_LAST_INDEX)
1083 break;
1085 f[i] = name + len;
1087 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1088 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1090 if (i == XLFD_LAST_INDEX)
1092 /* Fully specified XLFD. */
1093 int pixel_size;
1095 ASET (font, FONT_FOUNDRY_INDEX, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX));
1096 ASET (font, FONT_FAMILY_INDEX, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX));
1097 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1098 i <= XLFD_SWIDTH_INDEX; i++, j++)
1100 val = INTERN_FIELD_SYM (i);
1101 if (! NILP (val))
1103 if ((n = font_style_to_value (j, INTERN_FIELD_SYM (i), 0)) < 0)
1104 return -1;
1105 ASET (font, j, make_number (n));
1108 ASET (font, FONT_ADSTYLE_INDEX, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX));
1109 if (strcmp (f[XLFD_REGISTRY_INDEX], "*-*") == 0)
1110 ASET (font, FONT_REGISTRY_INDEX, Qnil);
1111 else
1112 ASET (font, FONT_REGISTRY_INDEX,
1113 font_intern_prop (f[XLFD_REGISTRY_INDEX],
1114 f[XLFD_LAST_INDEX] - f[XLFD_REGISTRY_INDEX],
1115 1));
1116 p = f[XLFD_PIXEL_INDEX];
1117 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
1118 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
1119 else
1121 val = INTERN_FIELD (XLFD_PIXEL_INDEX);
1122 if (INTEGERP (val))
1123 ASET (font, FONT_SIZE_INDEX, val);
1124 else
1126 double point_size = -1;
1128 font_assert (FONT_SPEC_P (font));
1129 p = f[XLFD_POINT_INDEX];
1130 if (*p == '[')
1131 point_size = parse_matrix (p);
1132 else if (isdigit (*p))
1133 point_size = atoi (p), point_size /= 10;
1134 if (point_size >= 0)
1135 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1139 val = INTERN_FIELD (XLFD_RESY_INDEX);
1140 if (! NILP (val) && ! INTEGERP (val))
1141 return -1;
1142 ASET (font, FONT_DPI_INDEX, val);
1143 val = INTERN_FIELD (XLFD_SPACING_INDEX);
1144 if (! NILP (val))
1146 val = font_prop_validate_spacing (QCspacing, val);
1147 if (! INTEGERP (val))
1148 return -1;
1149 ASET (font, FONT_SPACING_INDEX, val);
1151 p = f[XLFD_AVGWIDTH_INDEX];
1152 if (*p == '~')
1153 p++;
1154 val = font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p, 0);
1155 if (! NILP (val) && ! INTEGERP (val))
1156 return -1;
1157 ASET (font, FONT_AVGWIDTH_INDEX, val);
1159 else
1161 int wild_card_found = 0;
1162 Lisp_Object prop[XLFD_LAST_INDEX];
1164 if (FONT_ENTITY_P (font))
1165 return -1;
1166 for (j = 0; j < i; j++)
1168 if (*f[j] == '*')
1170 if (f[j][1] && f[j][1] != '-')
1171 return -1;
1172 prop[j] = Qnil;
1173 wild_card_found = 1;
1175 else if (j + 1 < i)
1176 prop[j] = INTERN_FIELD (j);
1177 else
1178 prop[j] = font_intern_prop (f[j], f[i] - f[j], 0);
1180 if (! wild_card_found)
1181 return -1;
1182 if (font_expand_wildcards (prop, i) < 0)
1183 return -1;
1185 ASET (font, FONT_FOUNDRY_INDEX, prop[XLFD_FOUNDRY_INDEX]);
1186 ASET (font, FONT_FAMILY_INDEX, prop[XLFD_FAMILY_INDEX]);
1187 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1188 i <= XLFD_SWIDTH_INDEX; i++, j++)
1189 if (! NILP (prop[i]))
1191 if ((n = font_style_to_value (j, prop[i], 1)) < 0)
1192 return -1;
1193 ASET (font, j, make_number (n));
1195 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1196 val = prop[XLFD_REGISTRY_INDEX];
1197 if (NILP (val))
1199 val = prop[XLFD_ENCODING_INDEX];
1200 if (! NILP (val))
1201 val = concat2 (build_string ("*-"), SYMBOL_NAME (val));
1203 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1204 val = concat2 (SYMBOL_NAME (val), build_string ("-*"));
1205 else
1206 val = concat3 (SYMBOL_NAME (val), build_string ("-"),
1207 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX]));
1208 if (! NILP (val))
1209 ASET (font, FONT_REGISTRY_INDEX, Fintern (val, Qnil));
1211 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1212 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
1213 else if (INTEGERP (prop[XLFD_POINT_INDEX]))
1215 double point_size = XINT (prop[XLFD_POINT_INDEX]);
1217 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1220 if (INTEGERP (prop[XLFD_RESX_INDEX]))
1221 ASET (font, FONT_DPI_INDEX, prop[XLFD_RESY_INDEX]);
1222 if (! NILP (prop[XLFD_SPACING_INDEX]))
1224 val = font_prop_validate_spacing (QCspacing,
1225 prop[XLFD_SPACING_INDEX]);
1226 if (! INTEGERP (val))
1227 return -1;
1228 ASET (font, FONT_SPACING_INDEX, val);
1230 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1231 ASET (font, FONT_AVGWIDTH_INDEX, prop[XLFD_AVGWIDTH_INDEX]);
1234 return 0;
1237 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1238 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1239 0, use PIXEL_SIZE instead. */
1242 font_unparse_xlfd (font, pixel_size, name, nbytes)
1243 Lisp_Object font;
1244 int pixel_size;
1245 char *name;
1246 int nbytes;
1248 char *f[XLFD_REGISTRY_INDEX + 1];
1249 Lisp_Object val;
1250 int i, j, len = 0;
1252 font_assert (FONTP (font));
1254 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
1255 i++, j++)
1257 if (i == FONT_ADSTYLE_INDEX)
1258 j = XLFD_ADSTYLE_INDEX;
1259 else if (i == FONT_REGISTRY_INDEX)
1260 j = XLFD_REGISTRY_INDEX;
1261 val = AREF (font, i);
1262 if (NILP (val))
1264 if (j == XLFD_REGISTRY_INDEX)
1265 f[j] = "*-*", len += 4;
1266 else
1267 f[j] = "*", len += 2;
1269 else
1271 if (SYMBOLP (val))
1272 val = SYMBOL_NAME (val);
1273 if (j == XLFD_REGISTRY_INDEX
1274 && ! strchr ((char *) SDATA (val), '-'))
1276 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1277 if (SDATA (val)[SBYTES (val) - 1] == '*')
1279 f[j] = alloca (SBYTES (val) + 3);
1280 sprintf (f[j], "%s-*", SDATA (val));
1281 len += SBYTES (val) + 3;
1283 else
1285 f[j] = alloca (SBYTES (val) + 4);
1286 sprintf (f[j], "%s*-*", SDATA (val));
1287 len += SBYTES (val) + 4;
1290 else
1291 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1295 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1296 i++, j++)
1298 val = font_style_symbolic (font, i, 0);
1299 if (NILP (val))
1300 f[j] = "*", len += 2;
1301 else
1303 val = SYMBOL_NAME (val);
1304 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1308 val = AREF (font, FONT_SIZE_INDEX);
1309 font_assert (NUMBERP (val) || NILP (val));
1310 if (INTEGERP (val))
1312 i = XINT (val);
1313 if (i <= 0)
1314 i = pixel_size;
1315 if (i > 0)
1317 f[XLFD_PIXEL_INDEX] = alloca (22);
1318 len += sprintf (f[XLFD_PIXEL_INDEX], "%d-*", i) + 1;
1320 else
1321 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1323 else if (FLOATP (val))
1325 i = XFLOAT_DATA (val) * 10;
1326 f[XLFD_PIXEL_INDEX] = alloca (12);
1327 len += sprintf (f[XLFD_PIXEL_INDEX], "*-%d", i) + 1;
1329 else
1330 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1332 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1334 i = XINT (AREF (font, FONT_DPI_INDEX));
1335 f[XLFD_RESX_INDEX] = alloca (22);
1336 len += sprintf (f[XLFD_RESX_INDEX],
1337 "%d-%d", i, i) + 1;
1339 else
1340 f[XLFD_RESX_INDEX] = "*-*", len += 4;
1341 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1343 int spacing = XINT (AREF (font, FONT_SPACING_INDEX));
1345 f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
1346 : spacing <= FONT_SPACING_DUAL ? "d"
1347 : spacing <= FONT_SPACING_MONO ? "m"
1348 : "c");
1349 len += 2;
1351 else
1352 f[XLFD_SPACING_INDEX] = "*", len += 2;
1353 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1355 f[XLFD_AVGWIDTH_INDEX] = alloca (11);
1356 len += sprintf (f[XLFD_AVGWIDTH_INDEX], "%ld",
1357 (long) XINT (AREF (font, FONT_AVGWIDTH_INDEX))) + 1;
1359 else
1360 f[XLFD_AVGWIDTH_INDEX] = "*", len += 2;
1361 len++; /* for terminating '\0'. */
1362 if (len >= nbytes)
1363 return -1;
1364 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1365 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1366 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1367 f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
1368 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
1369 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
1370 f[XLFD_REGISTRY_INDEX]);
1373 /* Parse NAME (null terminated) and store information in FONT
1374 (font-spec or font-entity). NAME is supplied in either the
1375 Fontconfig or GTK font name format. If NAME is successfully
1376 parsed, return 0. Otherwise return -1.
1378 The fontconfig format is
1380 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1382 The GTK format is
1384 FAMILY [PROPS...] [SIZE]
1386 This function tries to guess which format it is. */
1389 font_parse_fcname (name, font)
1390 char *name;
1391 Lisp_Object font;
1393 char *p, *q;
1394 char *size_beg = NULL, *size_end = NULL;
1395 char *props_beg = NULL, *family_end = NULL;
1396 int len = strlen (name);
1398 if (len == 0)
1399 return -1;
1401 for (p = name; *p; p++)
1403 if (*p == '\\' && p[1])
1404 p++;
1405 else if (*p == ':')
1407 props_beg = family_end = p;
1408 break;
1410 else if (*p == '-')
1412 int decimal = 0, size_found = 1;
1413 for (q = p + 1; *q && *q != ':'; q++)
1414 if (! isdigit(*q))
1416 if (*q != '.' || decimal)
1418 size_found = 0;
1419 break;
1421 decimal = 1;
1423 if (size_found)
1425 family_end = p;
1426 size_beg = p + 1;
1427 size_end = q;
1428 break;
1433 if (family_end)
1435 /* A fontconfig name with size and/or property data. */
1436 if (family_end > name)
1438 Lisp_Object family;
1439 family = font_intern_prop (name, family_end - name, 1);
1440 ASET (font, FONT_FAMILY_INDEX, family);
1442 if (size_beg)
1444 double point_size = strtod (size_beg, &size_end);
1445 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1446 if (*size_end == ':' && size_end[1])
1447 props_beg = size_end;
1449 if (props_beg)
1451 /* Now parse ":KEY=VAL" patterns. */
1452 Lisp_Object val;
1454 for (p = props_beg; *p; p = q)
1456 for (q = p + 1; *q && *q != '=' && *q != ':'; q++);
1457 if (*q != '=')
1459 /* Must be an enumerated value. */
1460 int word_len;
1461 p = p + 1;
1462 word_len = q - p;
1463 val = font_intern_prop (p, q - p, 1);
1465 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1467 if (PROP_MATCH ("light", 5)
1468 || PROP_MATCH ("medium", 6)
1469 || PROP_MATCH ("demibold", 8)
1470 || PROP_MATCH ("bold", 4)
1471 || PROP_MATCH ("black", 5))
1472 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
1473 else if (PROP_MATCH ("roman", 5)
1474 || PROP_MATCH ("italic", 6)
1475 || PROP_MATCH ("oblique", 7))
1476 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
1477 else if (PROP_MATCH ("charcell", 8))
1478 ASET (font, FONT_SPACING_INDEX,
1479 make_number (FONT_SPACING_CHARCELL));
1480 else if (PROP_MATCH ("mono", 4))
1481 ASET (font, FONT_SPACING_INDEX,
1482 make_number (FONT_SPACING_MONO));
1483 else if (PROP_MATCH ("proportional", 12))
1484 ASET (font, FONT_SPACING_INDEX,
1485 make_number (FONT_SPACING_PROPORTIONAL));
1486 #undef PROP_MATCH
1488 else
1490 /* KEY=VAL pairs */
1491 Lisp_Object key;
1492 int prop;
1494 if (q - p == 10 && memcmp (p + 1, "pixelsize", 9) == 0)
1495 prop = FONT_SIZE_INDEX;
1496 else
1498 key = font_intern_prop (p, q - p, 1);
1499 prop = get_font_prop_index (key);
1502 p = q + 1;
1503 for (q = p; *q && *q != ':'; q++);
1504 val = font_intern_prop (p, q - p, 0);
1506 if (prop >= FONT_FOUNDRY_INDEX
1507 && prop < FONT_EXTRA_INDEX)
1508 ASET (font, prop, font_prop_validate (prop, Qnil, val));
1509 else
1510 Ffont_put (font, key, val);
1512 p = q;
1516 else
1518 /* Either a fontconfig-style name with no size and property
1519 data, or a GTK-style name. */
1520 Lisp_Object prop;
1521 int word_len, prop_found = 0;
1523 for (p = name; *p; p = *q ? q + 1 : q)
1525 if (isdigit (*p))
1527 int size_found = 1;
1529 for (q = p + 1; *q && *q != ' '; q++)
1530 if (! isdigit (*q))
1532 size_found = 0;
1533 break;
1535 if (size_found)
1537 double point_size = strtod (p, &q);
1538 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1539 continue;
1543 for (q = p + 1; *q && *q != ' '; q++)
1544 if (*q == '\\' && q[1])
1545 q++;
1546 word_len = q - p;
1548 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1550 if (PROP_MATCH ("Ultra-Light", 11))
1552 prop_found = 1;
1553 prop = font_intern_prop ("ultra-light", 11, 1);
1554 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1556 else if (PROP_MATCH ("Light", 5))
1558 prop_found = 1;
1559 prop = font_intern_prop ("light", 5, 1);
1560 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1562 else if (PROP_MATCH ("Semi-Bold", 9))
1564 prop_found = 1;
1565 prop = font_intern_prop ("semi-bold", 9, 1);
1566 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1568 else if (PROP_MATCH ("Bold", 4))
1570 prop_found = 1;
1571 prop = font_intern_prop ("bold", 4, 1);
1572 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1574 else if (PROP_MATCH ("Italic", 6))
1576 prop_found = 1;
1577 prop = font_intern_prop ("italic", 4, 1);
1578 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
1580 else if (PROP_MATCH ("Oblique", 7))
1582 prop_found = 1;
1583 prop = font_intern_prop ("oblique", 7, 1);
1584 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
1586 else {
1587 if (prop_found)
1588 return -1; /* Unknown property in GTK-style font name. */
1589 family_end = q;
1592 #undef PROP_MATCH
1594 if (family_end)
1596 Lisp_Object family;
1597 family = font_intern_prop (name, family_end - name, 1);
1598 ASET (font, FONT_FAMILY_INDEX, family);
1602 return 0;
1605 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1606 NAME (NBYTES length), and return the name length. If
1607 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1610 font_unparse_fcname (font, pixel_size, name, nbytes)
1611 Lisp_Object font;
1612 int pixel_size;
1613 char *name;
1614 int nbytes;
1616 Lisp_Object family, foundry;
1617 Lisp_Object tail, val;
1618 int point_size;
1619 int i, len = 1;
1620 char *p;
1621 Lisp_Object styles[3];
1622 char *style_names[3] = { "weight", "slant", "width" };
1623 char work[256];
1625 family = AREF (font, FONT_FAMILY_INDEX);
1626 if (! NILP (family))
1628 if (SYMBOLP (family))
1630 family = SYMBOL_NAME (family);
1631 len += SBYTES (family);
1633 else
1634 family = Qnil;
1637 val = AREF (font, FONT_SIZE_INDEX);
1638 if (INTEGERP (val))
1640 if (XINT (val) != 0)
1641 pixel_size = XINT (val);
1642 point_size = -1;
1643 len += 21; /* for ":pixelsize=NUM" */
1645 else if (FLOATP (val))
1647 pixel_size = -1;
1648 point_size = (int) XFLOAT_DATA (val);
1649 len += 11; /* for "-NUM" */
1652 foundry = AREF (font, FONT_FOUNDRY_INDEX);
1653 if (! NILP (foundry))
1655 if (SYMBOLP (foundry))
1657 foundry = SYMBOL_NAME (foundry);
1658 len += 9 + SBYTES (foundry); /* ":foundry=NAME" */
1660 else
1661 foundry = Qnil;
1664 for (i = 0; i < 3; i++)
1666 styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
1667 if (! NILP (styles[i]))
1668 len += sprintf (work, ":%s=%s", style_names[i],
1669 SDATA (SYMBOL_NAME (styles[i])));
1672 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1673 len += sprintf (work, ":dpi=%ld", (long)XINT (AREF (font, FONT_DPI_INDEX)));
1674 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1675 len += strlen (":spacing=100");
1676 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1677 len += strlen (":scalable=false"); /* or ":scalable=true" */
1678 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
1680 Lisp_Object key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
1682 len += SBYTES (SYMBOL_NAME (key)) + 1; /* for :KEY= */
1683 if (STRINGP (val))
1684 len += SBYTES (val);
1685 else if (INTEGERP (val))
1686 len += sprintf (work, "%ld", (long) XINT (val));
1687 else if (SYMBOLP (val))
1688 len += (NILP (val) ? 5 : 4); /* for "false" or "true" */
1691 if (len > nbytes)
1692 return -1;
1693 p = name;
1694 if (! NILP (family))
1695 p += sprintf (p, "%s", SDATA (family));
1696 if (point_size > 0)
1698 if (p == name)
1699 p += sprintf (p, "%d", point_size);
1700 else
1701 p += sprintf (p, "-%d", point_size);
1703 else if (pixel_size > 0)
1704 p += sprintf (p, ":pixelsize=%d", pixel_size);
1705 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1706 p += sprintf (p, ":foundry=%s",
1707 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1708 for (i = 0; i < 3; i++)
1709 if (! NILP (styles[i]))
1710 p += sprintf (p, ":%s=%s", style_names[i],
1711 SDATA (SYMBOL_NAME (styles[i])));
1712 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1713 p += sprintf (p, ":dpi=%ld", (long) XINT (AREF (font, FONT_DPI_INDEX)));
1714 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1715 p += sprintf (p, ":spacing=%ld",
1716 (long) XINT (AREF (font, FONT_SPACING_INDEX)));
1717 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1719 if (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0)
1720 p += sprintf (p, ":scalable=true");
1721 else
1722 p += sprintf (p, ":scalable=false");
1724 return (p - name);
1727 /* Store GTK-style font name of FONT (font-spec or font-entity) in
1728 NAME (NBYTES length), and return the name length. F is the frame
1729 on which the font is displayed; it is used to calculate the point
1730 size. */
1733 font_unparse_gtkname (font, f, name, nbytes)
1734 Lisp_Object font;
1735 struct frame *f;
1736 char *name;
1737 int nbytes;
1739 char *p;
1740 int len = 1;
1741 Lisp_Object family, weight, slant, size;
1742 int point_size = -1;
1744 family = AREF (font, FONT_FAMILY_INDEX);
1745 if (! NILP (family))
1747 if (! SYMBOLP (family))
1748 return -1;
1749 family = SYMBOL_NAME (family);
1750 len += SBYTES (family);
1753 weight = font_style_symbolic (font, FONT_WEIGHT_INDEX, 0);
1754 if (EQ (weight, Qnormal))
1755 weight = Qnil;
1756 else if (! NILP (weight))
1758 weight = SYMBOL_NAME (weight);
1759 len += SBYTES (weight);
1762 slant = font_style_symbolic (font, FONT_SLANT_INDEX, 0);
1763 if (EQ (slant, Qnormal))
1764 slant = Qnil;
1765 else if (! NILP (slant))
1767 slant = SYMBOL_NAME (slant);
1768 len += SBYTES (slant);
1771 size = AREF (font, FONT_SIZE_INDEX);
1772 /* Convert pixel size to point size. */
1773 if (INTEGERP (size))
1775 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
1776 int dpi = 75;
1777 if (INTEGERP (font_dpi))
1778 dpi = XINT (font_dpi);
1779 else if (f)
1780 dpi = f->resy;
1781 point_size = PIXEL_TO_POINT (XINT (size), dpi);
1782 len += 11;
1784 else if (FLOATP (size))
1786 point_size = (int) XFLOAT_DATA (size);
1787 len += 11;
1790 if (len > nbytes)
1791 return -1;
1793 p = name + sprintf (name, "%s", SDATA (family));
1795 if (! NILP (weight))
1797 char *q = p;
1798 p += sprintf (p, " %s", SDATA (weight));
1799 q[1] = toupper (q[1]);
1802 if (! NILP (slant))
1804 char *q = p;
1805 p += sprintf (p, " %s", SDATA (slant));
1806 q[1] = toupper (q[1]);
1809 if (point_size > 0)
1810 p += sprintf (p, " %d", point_size);
1812 return (p - name);
1815 /* Parse NAME (null terminated) and store information in FONT
1816 (font-spec or font-entity). If NAME is successfully parsed, return
1817 0. Otherwise return -1. */
1819 static int
1820 font_parse_name (name, font)
1821 char *name;
1822 Lisp_Object font;
1824 if (name[0] == '-' || index (name, '*') || index (name, '?'))
1825 return font_parse_xlfd (name, font);
1826 return font_parse_fcname (name, font);
1830 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1831 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1832 part. */
1834 void
1835 font_parse_family_registry (family, registry, font_spec)
1836 Lisp_Object family, registry, font_spec;
1838 int len;
1839 char *p0, *p1;
1841 if (! NILP (family)
1842 && NILP (AREF (font_spec, FONT_FAMILY_INDEX)))
1844 CHECK_STRING (family);
1845 len = SBYTES (family);
1846 p0 = (char *) SDATA (family);
1847 p1 = index (p0, '-');
1848 if (p1)
1850 if ((*p0 != '*' && p1 - p0 > 0)
1851 && NILP (AREF (font_spec, FONT_FOUNDRY_INDEX)))
1852 Ffont_put (font_spec, QCfoundry, font_intern_prop (p0, p1 - p0, 1));
1853 p1++;
1854 len -= p1 - p0;
1855 Ffont_put (font_spec, QCfamily, font_intern_prop (p1, len, 1));
1857 else
1858 ASET (font_spec, FONT_FAMILY_INDEX, Fintern (family, Qnil));
1860 if (! NILP (registry))
1862 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1863 CHECK_STRING (registry);
1864 len = SBYTES (registry);
1865 p0 = (char *) SDATA (registry);
1866 p1 = index (p0, '-');
1867 if (! p1)
1869 if (SDATA (registry)[len - 1] == '*')
1870 registry = concat2 (registry, build_string ("-*"));
1871 else
1872 registry = concat2 (registry, build_string ("*-*"));
1874 registry = Fdowncase (registry);
1875 ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil));
1880 /* This part (through the next ^L) is still experimental and not
1881 tested much. We may drastically change codes. */
1883 /* OTF handler */
1885 #if 0
1887 #define LGSTRING_HEADER_SIZE 6
1888 #define LGSTRING_GLYPH_SIZE 8
1890 static int
1891 check_gstring (gstring)
1892 Lisp_Object gstring;
1894 Lisp_Object val;
1895 int i, j;
1897 CHECK_VECTOR (gstring);
1898 val = AREF (gstring, 0);
1899 CHECK_VECTOR (val);
1900 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1901 goto err;
1902 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1903 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1904 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1905 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1906 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1907 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1908 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1909 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1910 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1911 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1912 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1914 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
1916 val = LGSTRING_GLYPH (gstring, i);
1917 CHECK_VECTOR (val);
1918 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1919 goto err;
1920 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1921 break;
1922 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1923 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1924 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1925 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1926 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1927 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1928 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1929 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1931 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1932 CHECK_VECTOR (val);
1933 if (ASIZE (val) < 3)
1934 goto err;
1935 for (j = 0; j < 3; j++)
1936 CHECK_NUMBER (AREF (val, j));
1939 return i;
1940 err:
1941 error ("Invalid glyph-string format");
1942 return -1;
1945 static void
1946 check_otf_features (otf_features)
1947 Lisp_Object otf_features;
1949 Lisp_Object val;
1951 CHECK_CONS (otf_features);
1952 CHECK_SYMBOL (XCAR (otf_features));
1953 otf_features = XCDR (otf_features);
1954 CHECK_CONS (otf_features);
1955 CHECK_SYMBOL (XCAR (otf_features));
1956 otf_features = XCDR (otf_features);
1957 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1959 CHECK_SYMBOL (Fcar (val));
1960 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1961 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val)));
1963 otf_features = XCDR (otf_features);
1964 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1966 CHECK_SYMBOL (Fcar (val));
1967 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1968 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val)));
1972 #ifdef HAVE_LIBOTF
1973 #include <otf.h>
1975 Lisp_Object otf_list;
1977 static Lisp_Object
1978 otf_tag_symbol (tag)
1979 OTF_Tag tag;
1981 char name[5];
1983 OTF_tag_name (tag, name);
1984 return Fintern (make_unibyte_string (name, 4), Qnil);
1987 static OTF *
1988 otf_open (file)
1989 Lisp_Object file;
1991 Lisp_Object val = Fassoc (file, otf_list);
1992 OTF *otf;
1994 if (! NILP (val))
1995 otf = XSAVE_VALUE (XCDR (val))->pointer;
1996 else
1998 otf = STRINGP (file) ? OTF_open ((char *) SDATA (file)) : NULL;
1999 val = make_save_value (otf, 0);
2000 otf_list = Fcons (Fcons (file, val), otf_list);
2002 return otf;
2006 /* Return a list describing which scripts/languages FONT supports by
2007 which GSUB/GPOS features of OpenType tables. See the comment of
2008 (struct font_driver).otf_capability. */
2010 Lisp_Object
2011 font_otf_capability (font)
2012 struct font *font;
2014 OTF *otf;
2015 Lisp_Object capability = Fcons (Qnil, Qnil);
2016 int i;
2018 otf = otf_open (font->props[FONT_FILE_INDEX]);
2019 if (! otf)
2020 return Qnil;
2021 for (i = 0; i < 2; i++)
2023 OTF_GSUB_GPOS *gsub_gpos;
2024 Lisp_Object script_list = Qnil;
2025 int j;
2027 if (OTF_get_features (otf, i == 0) < 0)
2028 continue;
2029 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
2030 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
2032 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
2033 Lisp_Object langsys_list = Qnil;
2034 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
2035 int k;
2037 for (k = script->LangSysCount; k >= 0; k--)
2039 OTF_LangSys *langsys;
2040 Lisp_Object feature_list = Qnil;
2041 Lisp_Object langsys_tag;
2042 int l;
2044 if (k == script->LangSysCount)
2046 langsys = &script->DefaultLangSys;
2047 langsys_tag = Qnil;
2049 else
2051 langsys = script->LangSys + k;
2052 langsys_tag
2053 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
2055 for (l = langsys->FeatureCount - 1; l >= 0; l--)
2057 OTF_Feature *feature
2058 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
2059 Lisp_Object feature_tag
2060 = otf_tag_symbol (feature->FeatureTag);
2062 feature_list = Fcons (feature_tag, feature_list);
2064 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
2065 langsys_list);
2067 script_list = Fcons (Fcons (script_tag, langsys_list),
2068 script_list);
2071 if (i == 0)
2072 XSETCAR (capability, script_list);
2073 else
2074 XSETCDR (capability, script_list);
2077 return capability;
2080 /* Parse OTF features in SPEC and write a proper features spec string
2081 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
2082 assured that the sufficient memory has already allocated for
2083 FEATURES. */
2085 static void
2086 generate_otf_features (spec, features)
2087 Lisp_Object spec;
2088 char *features;
2090 Lisp_Object val;
2091 char *p;
2092 int asterisk;
2094 p = features;
2095 *p = '\0';
2096 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
2098 val = XCAR (spec);
2099 CHECK_SYMBOL (val);
2100 if (p > features)
2101 *p++ = ',';
2102 if (SREF (SYMBOL_NAME (val), 0) == '*')
2104 asterisk = 1;
2105 *p++ = '*';
2107 else if (! asterisk)
2109 val = SYMBOL_NAME (val);
2110 p += sprintf (p, "%s", SDATA (val));
2112 else
2114 val = SYMBOL_NAME (val);
2115 p += sprintf (p, "~%s", SDATA (val));
2118 if (CONSP (spec))
2119 error ("OTF spec too long");
2122 Lisp_Object
2123 font_otf_DeviceTable (device_table)
2124 OTF_DeviceTable *device_table;
2126 int len = device_table->StartSize - device_table->EndSize + 1;
2128 return Fcons (make_number (len),
2129 make_unibyte_string (device_table->DeltaValue, len));
2132 Lisp_Object
2133 font_otf_ValueRecord (value_format, value_record)
2134 int value_format;
2135 OTF_ValueRecord *value_record;
2137 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
2139 if (value_format & OTF_XPlacement)
2140 ASET (val, 0, make_number (value_record->XPlacement));
2141 if (value_format & OTF_YPlacement)
2142 ASET (val, 1, make_number (value_record->YPlacement));
2143 if (value_format & OTF_XAdvance)
2144 ASET (val, 2, make_number (value_record->XAdvance));
2145 if (value_format & OTF_YAdvance)
2146 ASET (val, 3, make_number (value_record->YAdvance));
2147 if (value_format & OTF_XPlaDevice)
2148 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
2149 if (value_format & OTF_YPlaDevice)
2150 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
2151 if (value_format & OTF_XAdvDevice)
2152 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
2153 if (value_format & OTF_YAdvDevice)
2154 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
2155 return val;
2158 Lisp_Object
2159 font_otf_Anchor (anchor)
2160 OTF_Anchor *anchor;
2162 Lisp_Object val;
2164 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
2165 ASET (val, 0, make_number (anchor->XCoordinate));
2166 ASET (val, 1, make_number (anchor->YCoordinate));
2167 if (anchor->AnchorFormat == 2)
2168 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
2169 else
2171 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
2172 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
2174 return val;
2176 #endif /* HAVE_LIBOTF */
2177 #endif /* 0 */
2180 /* Font sorting */
2182 static unsigned font_score P_ ((Lisp_Object, Lisp_Object *));
2183 static int font_compare P_ ((const void *, const void *));
2184 static Lisp_Object font_sort_entities P_ ((Lisp_Object, Lisp_Object,
2185 Lisp_Object, int));
2187 /* Return a rescaling ratio of FONT_ENTITY. */
2188 extern Lisp_Object Vface_font_rescale_alist;
2190 static double
2191 font_rescale_ratio (font_entity)
2192 Lisp_Object font_entity;
2194 Lisp_Object tail, elt;
2195 Lisp_Object name = Qnil;
2197 for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail))
2199 elt = XCAR (tail);
2200 if (FLOATP (XCDR (elt)))
2202 if (STRINGP (XCAR (elt)))
2204 if (NILP (name))
2205 name = Ffont_xlfd_name (font_entity, Qnil);
2206 if (fast_string_match_ignore_case (XCAR (elt), name) >= 0)
2207 return XFLOAT_DATA (XCDR (elt));
2209 else if (FONT_SPEC_P (XCAR (elt)))
2211 if (font_match_p (XCAR (elt), font_entity))
2212 return XFLOAT_DATA (XCDR (elt));
2216 return 1.0;
2219 /* We sort fonts by scoring each of them against a specified
2220 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2221 the value is, the closer the font is to the font-spec.
2223 The lowest 2 bits of the score is used for driver type. The font
2224 available by the most preferred font driver is 0.
2226 Each 7-bit in the higher 28 bits are used for numeric properties
2227 WEIGHT, SLANT, WIDTH, and SIZE. */
2229 /* How many bits to shift to store the difference value of each font
2230 property in a score. Note that flots for FONT_TYPE_INDEX and
2231 FONT_REGISTRY_INDEX are not used. */
2232 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
2234 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2235 The return value indicates how different ENTITY is compared with
2236 SPEC_PROP. */
2238 static unsigned
2239 font_score (entity, spec_prop)
2240 Lisp_Object entity, *spec_prop;
2242 unsigned score = 0;
2243 int i;
2245 /* Score three style numeric fields. Maximum difference is 127. */
2246 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
2247 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
2249 int diff = (XINT (AREF (entity, i)) >> 8) - (XINT (spec_prop[i]) >> 8);
2251 if (diff < 0)
2252 diff = - diff;
2253 if (diff > 0)
2254 score |= min (diff, 127) << sort_shift_bits[i];
2257 /* Score the size. Maximum difference is 127. */
2258 i = FONT_SIZE_INDEX;
2259 if (! NILP (spec_prop[FONT_SIZE_INDEX])
2260 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2262 /* We use the higher 6-bit for the actual size difference. The
2263 lowest bit is set if the DPI is different. */
2264 int diff;
2265 int pixel_size = XINT (spec_prop[FONT_SIZE_INDEX]);
2267 if (CONSP (Vface_font_rescale_alist))
2268 pixel_size *= font_rescale_ratio (entity);
2269 diff = pixel_size - XINT (AREF (entity, FONT_SIZE_INDEX));
2270 if (diff < 0)
2271 diff = - diff;
2272 diff <<= 1;
2273 if (! NILP (spec_prop[FONT_DPI_INDEX])
2274 && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX)))
2275 diff |= 1;
2276 if (! NILP (spec_prop[FONT_AVGWIDTH_INDEX])
2277 && ! EQ (spec_prop[FONT_AVGWIDTH_INDEX], AREF (entity, FONT_AVGWIDTH_INDEX)))
2278 diff |= 1;
2279 score |= min (diff, 127) << sort_shift_bits[FONT_SIZE_INDEX];
2282 return score;
2286 /* Concatenate all elements of LIST into one vector. LIST is a list
2287 of font-entity vectors. */
2289 static Lisp_Object
2290 font_vconcat_entity_vectors (Lisp_Object list)
2292 int nargs = XINT (Flength (list));
2293 Lisp_Object *args = alloca (sizeof (Lisp_Object) * nargs);
2294 int i;
2296 for (i = 0; i < nargs; i++, list = XCDR (list))
2297 args[i] = XCAR (list);
2298 return Fvconcat (nargs, args);
2302 /* The structure for elements being sorted by qsort. */
2303 struct font_sort_data
2305 unsigned score;
2306 int font_driver_preference;
2307 Lisp_Object entity;
2311 /* The comparison function for qsort. */
2313 static int
2314 font_compare (d1, d2)
2315 const void *d1, *d2;
2317 const struct font_sort_data *data1 = d1;
2318 const struct font_sort_data *data2 = d2;
2320 if (data1->score < data2->score)
2321 return -1;
2322 else if (data1->score > data2->score)
2323 return 1;
2324 return (data1->font_driver_preference - data2->font_driver_preference);
2328 /* Sort each font-entity vector in LIST by closeness to font-spec PREFER.
2329 If PREFER specifies a point-size, calculate the corresponding
2330 pixel-size from QCdpi property of PREFER or from the Y-resolution
2331 of FRAME before sorting.
2333 If BEST-ONLY is nonzero, return the best matching entity (that
2334 supports the character BEST-ONLY if BEST-ONLY is positive, or any
2335 if BEST-ONLY is negative). Otherwise, return the sorted result as
2336 a single vector of font-entities.
2338 This function does no optimization for the case that the total
2339 number of elements is 1. The caller should avoid calling this in
2340 such a case. */
2342 static Lisp_Object
2343 font_sort_entities (list, prefer, frame, best_only)
2344 Lisp_Object list, prefer, frame;
2345 int best_only;
2347 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2348 int len, maxlen, i;
2349 struct font_sort_data *data;
2350 unsigned best_score;
2351 Lisp_Object best_entity;
2352 struct frame *f = XFRAME (frame);
2353 Lisp_Object tail, vec;
2354 USE_SAFE_ALLOCA;
2356 for (i = FONT_WEIGHT_INDEX; i <= FONT_AVGWIDTH_INDEX; i++)
2357 prefer_prop[i] = AREF (prefer, i);
2358 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2359 prefer_prop[FONT_SIZE_INDEX]
2360 = make_number (font_pixel_size (XFRAME (frame), prefer));
2362 if (NILP (XCDR (list)))
2364 /* What we have to take care of is this single vector. */
2365 vec = XCAR (list);
2366 maxlen = ASIZE (vec);
2368 else if (best_only)
2370 /* We don't have to perform sort, so there's no need of creating
2371 a single vector. But, we must find the length of the longest
2372 vector. */
2373 maxlen = 0;
2374 for (tail = list; CONSP (tail); tail = XCDR (tail))
2375 if (maxlen < ASIZE (XCAR (tail)))
2376 maxlen = ASIZE (XCAR (tail));
2378 else
2380 /* We have to create a single vector to sort it. */
2381 vec = font_vconcat_entity_vectors (list);
2382 maxlen = ASIZE (vec);
2385 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * maxlen);
2386 best_score = 0xFFFFFFFF;
2387 best_entity = Qnil;
2389 for (tail = list; CONSP (tail); tail = XCDR (tail))
2391 int font_driver_preference = 0;
2392 Lisp_Object current_font_driver;
2394 if (best_only)
2395 vec = XCAR (tail);
2396 len = ASIZE (vec);
2398 /* We are sure that the length of VEC > 0. */
2399 current_font_driver = AREF (AREF (vec, 0), FONT_TYPE_INDEX);
2400 /* Score the elements. */
2401 for (i = 0; i < len; i++)
2403 data[i].entity = AREF (vec, i);
2404 data[i].score
2405 = ((best_only <= 0 || font_has_char (f, data[i].entity, best_only)
2406 > 0)
2407 ? font_score (data[i].entity, prefer_prop)
2408 : 0xFFFFFFFF);
2409 if (best_only && best_score > data[i].score)
2411 best_score = data[i].score;
2412 best_entity = data[i].entity;
2413 if (best_score == 0)
2414 break;
2416 if (! EQ (current_font_driver, AREF (AREF (vec, i), FONT_TYPE_INDEX)))
2418 current_font_driver = AREF (AREF (vec, i), FONT_TYPE_INDEX);
2419 font_driver_preference++;
2421 data[i].font_driver_preference = font_driver_preference;
2424 /* Sort if necessary. */
2425 if (! best_only)
2427 qsort (data, len, sizeof *data, font_compare);
2428 for (i = 0; i < len; i++)
2429 ASET (vec, i, data[i].entity);
2430 break;
2432 else
2433 vec = best_entity;
2436 SAFE_FREE ();
2438 FONT_ADD_LOG ("sort-by", prefer, vec);
2439 return vec;
2443 /* API of Font Service Layer. */
2445 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2446 sort_shift_bits. Finternal_set_font_selection_order calls this
2447 function with font_sort_order after setting up it. */
2449 void
2450 font_update_sort_order (order)
2451 int *order;
2453 int i, shift_bits;
2455 for (i = 0, shift_bits = 23; i < 4; i++, shift_bits -= 7)
2457 int xlfd_idx = order[i];
2459 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2460 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2461 else if (xlfd_idx == XLFD_SLANT_INDEX)
2462 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2463 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2464 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2465 else
2466 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2470 static int
2471 font_check_otf_features (script, langsys, features, table)
2472 Lisp_Object script, langsys, features, table;
2474 Lisp_Object val;
2475 int negative;
2477 table = assq_no_quit (script, table);
2478 if (NILP (table))
2479 return 0;
2480 table = XCDR (table);
2481 if (! NILP (langsys))
2483 table = assq_no_quit (langsys, table);
2484 if (NILP (table))
2485 return 0;
2487 else
2489 val = assq_no_quit (Qnil, table);
2490 if (NILP (val))
2491 table = XCAR (table);
2492 else
2493 table = val;
2495 table = XCDR (table);
2496 for (negative = 0; CONSP (features); features = XCDR (features))
2498 if (NILP (XCAR (features)))
2500 negative = 1;
2501 continue;
2503 if (NILP (Fmemq (XCAR (features), table)) != negative)
2504 return 0;
2506 return 1;
2509 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2511 static int
2512 font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
2514 Lisp_Object script, langsys = Qnil, gsub = Qnil, gpos = Qnil;
2516 script = XCAR (spec);
2517 spec = XCDR (spec);
2518 if (! NILP (spec))
2520 langsys = XCAR (spec);
2521 spec = XCDR (spec);
2522 if (! NILP (spec))
2524 gsub = XCAR (spec);
2525 spec = XCDR (spec);
2526 if (! NILP (spec))
2527 gpos = XCAR (spec);
2531 if (! NILP (gsub) && ! font_check_otf_features (script, langsys, gsub,
2532 XCAR (otf_capability)))
2533 return 0;
2534 if (! NILP (gpos) && ! font_check_otf_features (script, langsys, gpos,
2535 XCDR (otf_capability)))
2536 return 0;
2537 return 1;
2542 /* Check if FONT (font-entity or font-object) matches with the font
2543 specification SPEC. */
2546 font_match_p (spec, font)
2547 Lisp_Object spec, font;
2549 Lisp_Object prop[FONT_SPEC_MAX], *props;
2550 Lisp_Object extra, font_extra;
2551 int i;
2553 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2554 if (! NILP (AREF (spec, i))
2555 && ! NILP (AREF (font, i))
2556 && ! EQ (AREF (spec, i), AREF (font, i)))
2557 return 0;
2558 props = XFONT_SPEC (spec)->props;
2559 if (FLOATP (props[FONT_SIZE_INDEX]))
2561 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
2562 prop[i] = AREF (spec, i);
2563 prop[FONT_SIZE_INDEX]
2564 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2565 props = prop;
2568 if (font_score (font, props) > 0)
2569 return 0;
2570 extra = AREF (spec, FONT_EXTRA_INDEX);
2571 font_extra = AREF (font, FONT_EXTRA_INDEX);
2572 for (; CONSP (extra); extra = XCDR (extra))
2574 Lisp_Object key = XCAR (XCAR (extra));
2575 Lisp_Object val = XCDR (XCAR (extra)), val2;
2577 if (EQ (key, QClang))
2579 val2 = assq_no_quit (key, font_extra);
2580 if (NILP (val2))
2581 return 0;
2582 val2 = XCDR (val2);
2583 if (CONSP (val))
2585 if (! CONSP (val2))
2586 return 0;
2587 while (CONSP (val))
2588 if (NILP (Fmemq (val, val2)))
2589 return 0;
2591 else
2592 if (CONSP (val2)
2593 ? NILP (Fmemq (val, XCDR (val2)))
2594 : ! EQ (val, val2))
2595 return 0;
2597 else if (EQ (key, QCscript))
2599 val2 = assq_no_quit (val, Vscript_representative_chars);
2600 if (CONSP (val2))
2602 val2 = XCDR (val2);
2603 if (CONSP (val2))
2605 /* All characters in the list must be supported. */
2606 for (; CONSP (val2); val2 = XCDR (val2))
2608 if (! NATNUMP (XCAR (val2)))
2609 continue;
2610 if (font_encode_char (font, XFASTINT (XCAR (val2)))
2611 == FONT_INVALID_CODE)
2612 return 0;
2615 else if (VECTORP (val2))
2617 /* At most one character in the vector must be supported. */
2618 for (i = 0; i < ASIZE (val2); i++)
2620 if (! NATNUMP (AREF (val2, i)))
2621 continue;
2622 if (font_encode_char (font, XFASTINT (AREF (val2, i)))
2623 != FONT_INVALID_CODE)
2624 break;
2626 if (i == ASIZE (val2))
2627 return 0;
2631 else if (EQ (key, QCotf))
2633 struct font *fontp;
2635 if (! FONT_OBJECT_P (font))
2636 return 0;
2637 fontp = XFONT_OBJECT (font);
2638 if (! fontp->driver->otf_capability)
2639 return 0;
2640 val2 = fontp->driver->otf_capability (fontp);
2641 if (NILP (val2) || ! font_check_otf (val, val2))
2642 return 0;
2646 return 1;
2650 /* Font cache
2652 Each font backend has the callback function get_cache, and it
2653 returns a cons cell of which cdr part can be freely used for
2654 caching fonts. The cons cell may be shared by multiple frames
2655 and/or multiple font drivers. So, we arrange the cdr part as this:
2657 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2659 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2660 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2661 cons (FONT-SPEC FONT-ENTITY ...). */
2663 static void font_prepare_cache P_ ((FRAME_PTR, struct font_driver *));
2664 static void font_finish_cache P_ ((FRAME_PTR, struct font_driver *));
2665 static Lisp_Object font_get_cache P_ ((FRAME_PTR, struct font_driver *));
2666 static void font_clear_cache P_ ((FRAME_PTR, Lisp_Object,
2667 struct font_driver *));
2669 static void
2670 font_prepare_cache (f, driver)
2671 FRAME_PTR f;
2672 struct font_driver *driver;
2674 Lisp_Object cache, val;
2676 cache = driver->get_cache (f);
2677 val = XCDR (cache);
2678 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2679 val = XCDR (val);
2680 if (NILP (val))
2682 val = Fcons (driver->type, Fcons (make_number (1), Qnil));
2683 XSETCDR (cache, Fcons (val, XCDR (cache)));
2685 else
2687 val = XCDR (XCAR (val));
2688 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2693 static void
2694 font_finish_cache (f, driver)
2695 FRAME_PTR f;
2696 struct font_driver *driver;
2698 Lisp_Object cache, val, tmp;
2701 cache = driver->get_cache (f);
2702 val = XCDR (cache);
2703 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2704 cache = val, val = XCDR (val);
2705 font_assert (! NILP (val));
2706 tmp = XCDR (XCAR (val));
2707 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2708 if (XINT (XCAR (tmp)) == 0)
2710 font_clear_cache (f, XCAR (val), driver);
2711 XSETCDR (cache, XCDR (val));
2716 static Lisp_Object
2717 font_get_cache (f, driver)
2718 FRAME_PTR f;
2719 struct font_driver *driver;
2721 Lisp_Object val = driver->get_cache (f);
2722 Lisp_Object type = driver->type;
2724 font_assert (CONSP (val));
2725 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2726 font_assert (CONSP (val));
2727 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2728 val = XCDR (XCAR (val));
2729 return val;
2732 static int num_fonts;
2734 static void
2735 font_clear_cache (f, cache, driver)
2736 FRAME_PTR f;
2737 Lisp_Object cache;
2738 struct font_driver *driver;
2740 Lisp_Object tail, elt;
2741 Lisp_Object tail2, entity;
2743 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2744 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2746 elt = XCAR (tail);
2747 /* elt should have the form (FONT-SPEC FONT-ENTITY ...) */
2748 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2750 for (tail2 = XCDR (elt); CONSP (tail2); tail2 = XCDR (tail2))
2752 entity = XCAR (tail2);
2754 if (FONT_ENTITY_P (entity)
2755 && EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2757 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2759 for (; CONSP (objlist); objlist = XCDR (objlist))
2761 Lisp_Object val = XCAR (objlist);
2762 struct font *font = XFONT_OBJECT (val);
2764 if (! NILP (AREF (val, FONT_TYPE_INDEX)))
2766 font_assert (font && driver == font->driver);
2767 driver->close (f, font);
2768 num_fonts--;
2771 if (driver->free_entity)
2772 driver->free_entity (entity);
2777 XSETCDR (cache, Qnil);
2781 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2783 Lisp_Object
2784 font_delete_unmatched (vec, spec, size)
2785 Lisp_Object vec, spec;
2786 int size;
2788 Lisp_Object entity, val;
2789 enum font_property_index prop;
2790 int i;
2792 for (val = Qnil, i = ASIZE (vec) - 1; i >= 0; i--)
2794 entity = AREF (vec, i);
2795 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++)
2796 if (INTEGERP (AREF (spec, prop))
2797 && ((XINT (AREF (spec, prop)) >> 8)
2798 != (XINT (AREF (entity, prop)) >> 8)))
2799 prop = FONT_SPEC_MAX;
2800 if (prop < FONT_SPEC_MAX
2801 && size
2802 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2804 int diff = XINT (AREF (entity, FONT_SIZE_INDEX)) - size;
2806 if (diff != 0
2807 && (diff < 0 ? -diff > FONT_PIXEL_SIZE_QUANTUM
2808 : diff > FONT_PIXEL_SIZE_QUANTUM))
2809 prop = FONT_SPEC_MAX;
2811 if (prop < FONT_SPEC_MAX
2812 && INTEGERP (AREF (spec, FONT_DPI_INDEX))
2813 && INTEGERP (AREF (entity, FONT_DPI_INDEX))
2814 && XINT (AREF (entity, FONT_DPI_INDEX)) != 0
2815 && ! EQ (AREF (spec, FONT_DPI_INDEX), AREF (entity, FONT_DPI_INDEX)))
2816 prop = FONT_SPEC_MAX;
2817 if (prop < FONT_SPEC_MAX
2818 && INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
2819 && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
2820 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) != 0
2821 && ! EQ (AREF (spec, FONT_AVGWIDTH_INDEX),
2822 AREF (entity, FONT_AVGWIDTH_INDEX)))
2823 prop = FONT_SPEC_MAX;
2824 if (prop < FONT_SPEC_MAX)
2825 val = Fcons (entity, val);
2827 return (Fvconcat (1, &val));
2831 /* Return a list of vectors of font-entities matching with SPEC on
2832 FRAME. The elements of the list are in the same of order of
2833 font-drivers. */
2835 Lisp_Object
2836 font_list_entities (frame, spec)
2837 Lisp_Object frame, spec;
2839 FRAME_PTR f = XFRAME (frame);
2840 struct font_driver_list *driver_list = f->font_driver_list;
2841 Lisp_Object ftype, val;
2842 Lisp_Object list = Qnil;
2843 int size;
2844 int need_filtering = 0;
2845 int i;
2847 font_assert (FONT_SPEC_P (spec));
2849 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2850 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2851 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2852 size = font_pixel_size (f, spec);
2853 else
2854 size = 0;
2856 ftype = AREF (spec, FONT_TYPE_INDEX);
2857 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2858 ASET (scratch_font_spec, i, AREF (spec, i));
2859 for (i = FONT_WEIGHT_INDEX; i < FONT_EXTRA_INDEX; i++)
2861 ASET (scratch_font_spec, i, Qnil);
2862 if (! NILP (AREF (spec, i)))
2863 need_filtering = 1;
2864 if (i == FONT_DPI_INDEX)
2865 /* Skip FONT_SPACING_INDEX */
2866 i++;
2868 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX));
2869 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
2871 for (i = 0; driver_list; driver_list = driver_list->next)
2872 if (driver_list->on
2873 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2875 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2877 ASET (scratch_font_spec, FONT_TYPE_INDEX, driver_list->driver->type);
2878 val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2879 if (CONSP (val))
2880 val = XCDR (val);
2881 else
2883 Lisp_Object copy;
2885 val = driver_list->driver->list (frame, scratch_font_spec);
2886 if (NILP (val))
2887 val = null_vector;
2888 else
2889 val = Fvconcat (1, &val);
2890 copy = Fcopy_font_spec (scratch_font_spec);
2891 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2892 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2894 if (ASIZE (val) > 0 && need_filtering)
2895 val = font_delete_unmatched (val, spec, size);
2896 if (ASIZE (val) > 0)
2897 list = Fcons (val, list);
2900 list = Fnreverse (list);
2901 FONT_ADD_LOG ("list", spec, list);
2902 return list;
2906 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2907 nil, is an array of face's attributes, which specifies preferred
2908 font-related attributes. */
2910 static Lisp_Object
2911 font_matching_entity (f, attrs, spec)
2912 FRAME_PTR f;
2913 Lisp_Object *attrs, spec;
2915 struct font_driver_list *driver_list = f->font_driver_list;
2916 Lisp_Object ftype, size, entity;
2917 Lisp_Object frame;
2918 Lisp_Object work = Fcopy_font_spec (spec);
2920 XSETFRAME (frame, f);
2921 ftype = AREF (spec, FONT_TYPE_INDEX);
2922 size = AREF (spec, FONT_SIZE_INDEX);
2924 if (FLOATP (size))
2925 ASET (work, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2926 FONT_SET_STYLE (work, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
2927 FONT_SET_STYLE (work, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
2928 FONT_SET_STYLE (work, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
2930 entity = Qnil;
2931 for (; driver_list; driver_list = driver_list->next)
2932 if (driver_list->on
2933 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2935 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2936 Lisp_Object copy;
2938 ASET (work, FONT_TYPE_INDEX, driver_list->driver->type);
2939 entity = assoc_no_quit (work, XCDR (cache));
2940 if (CONSP (entity))
2941 entity = XCDR (entity);
2942 else
2944 entity = driver_list->driver->match (frame, work);
2945 copy = Fcopy_font_spec (work);
2946 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2947 XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache)));
2949 if (! NILP (entity))
2950 break;
2952 FONT_ADD_LOG ("match", work, entity);
2953 return entity;
2957 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2958 opened font object. */
2960 static Lisp_Object
2961 font_open_entity (f, entity, pixel_size)
2962 FRAME_PTR f;
2963 Lisp_Object entity;
2964 int pixel_size;
2966 struct font_driver_list *driver_list;
2967 Lisp_Object objlist, size, val, font_object;
2968 struct font *font;
2969 int min_width, height;
2970 int scaled_pixel_size;
2972 font_assert (FONT_ENTITY_P (entity));
2973 size = AREF (entity, FONT_SIZE_INDEX);
2974 if (XINT (size) != 0)
2975 scaled_pixel_size = pixel_size = XINT (size);
2976 else if (CONSP (Vface_font_rescale_alist))
2977 scaled_pixel_size = pixel_size * font_rescale_ratio (entity);
2979 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2980 objlist = XCDR (objlist))
2981 if (! NILP (AREF (XCAR (objlist), FONT_TYPE_INDEX))
2982 && XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size)
2983 return XCAR (objlist);
2985 val = AREF (entity, FONT_TYPE_INDEX);
2986 for (driver_list = f->font_driver_list;
2987 driver_list && ! EQ (driver_list->driver->type, val);
2988 driver_list = driver_list->next);
2989 if (! driver_list)
2990 return Qnil;
2992 font_object = driver_list->driver->open (f, entity, scaled_pixel_size);
2993 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
2994 FONT_ADD_LOG ("open", entity, font_object);
2995 if (NILP (font_object))
2996 return Qnil;
2997 ASET (entity, FONT_OBJLIST_INDEX,
2998 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2999 ASET (font_object, FONT_OBJLIST_INDEX, Qnil);
3000 num_fonts++;
3002 font = XFONT_OBJECT (font_object);
3003 min_width = (font->min_width ? font->min_width
3004 : font->average_width ? font->average_width
3005 : font->space_width ? font->space_width
3006 : 1);
3007 height = (font->height ? font->height : 1);
3008 #ifdef HAVE_WINDOW_SYSTEM
3009 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
3010 if (FRAME_X_DISPLAY_INFO (f)->n_fonts == 1)
3012 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
3013 FRAME_SMALLEST_FONT_HEIGHT (f) = height;
3014 fonts_changed_p = 1;
3016 else
3018 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
3019 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
3020 if (FRAME_SMALLEST_FONT_HEIGHT (f) > height)
3021 FRAME_SMALLEST_FONT_HEIGHT (f) = height, fonts_changed_p = 1;
3023 #endif
3025 return font_object;
3029 /* Close FONT_OBJECT that is opened on frame F. */
3031 void
3032 font_close_object (f, font_object)
3033 FRAME_PTR f;
3034 Lisp_Object font_object;
3036 struct font *font = XFONT_OBJECT (font_object);
3038 if (NILP (AREF (font_object, FONT_TYPE_INDEX)))
3039 /* Already closed. */
3040 return;
3041 FONT_ADD_LOG ("close", font_object, Qnil);
3042 font->driver->close (f, font);
3043 #ifdef HAVE_WINDOW_SYSTEM
3044 font_assert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
3045 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
3046 #endif
3047 num_fonts--;
3051 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
3052 FONT is a font-entity and it must be opened to check. */
3055 font_has_char (f, font, c)
3056 FRAME_PTR f;
3057 Lisp_Object font;
3058 int c;
3060 struct font *fontp;
3062 if (FONT_ENTITY_P (font))
3064 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
3065 struct font_driver_list *driver_list;
3067 for (driver_list = f->font_driver_list;
3068 driver_list && ! EQ (driver_list->driver->type, type);
3069 driver_list = driver_list->next);
3070 if (! driver_list)
3071 return 0;
3072 if (! driver_list->driver->has_char)
3073 return -1;
3074 return driver_list->driver->has_char (font, c);
3077 font_assert (FONT_OBJECT_P (font));
3078 fontp = XFONT_OBJECT (font);
3079 if (fontp->driver->has_char)
3081 int result = fontp->driver->has_char (font, c);
3083 if (result >= 0)
3084 return result;
3086 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
3090 /* Return the glyph ID of FONT_OBJECT for character C. */
3092 unsigned
3093 font_encode_char (font_object, c)
3094 Lisp_Object font_object;
3095 int c;
3097 struct font *font;
3099 font_assert (FONT_OBJECT_P (font_object));
3100 font = XFONT_OBJECT (font_object);
3101 return font->driver->encode_char (font, c);
3105 /* Return the name of FONT_OBJECT. */
3107 Lisp_Object
3108 font_get_name (font_object)
3109 Lisp_Object font_object;
3111 font_assert (FONT_OBJECT_P (font_object));
3112 return AREF (font_object, FONT_NAME_INDEX);
3116 /* Return the specification of FONT_OBJECT. */
3118 Lisp_Object
3119 font_get_spec (font_object)
3120 Lisp_Object font_object;
3122 Lisp_Object spec = font_make_spec ();
3123 int i;
3125 for (i = 0; i < FONT_SIZE_INDEX; i++)
3126 ASET (spec, i, AREF (font_object, i));
3127 ASET (spec, FONT_SIZE_INDEX,
3128 make_number (XFONT_OBJECT (font_object)->pixel_size));
3129 return spec;
3133 /* Create a new font spec from FONT_NAME, and return it. If FONT_NAME
3134 could not be parsed by font_parse_name, return Qnil. */
3136 Lisp_Object
3137 font_spec_from_name (font_name)
3138 Lisp_Object font_name;
3140 Lisp_Object spec = Ffont_spec (0, NULL);
3142 CHECK_STRING (font_name);
3143 if (font_parse_name ((char *) SDATA (font_name), spec) == -1)
3144 return Qnil;
3145 font_put_extra (spec, QCname, font_name);
3146 return spec;
3150 void
3151 font_clear_prop (attrs, prop)
3152 Lisp_Object *attrs;
3153 enum font_property_index prop;
3155 Lisp_Object font = attrs[LFACE_FONT_INDEX];
3157 if (! FONTP (font))
3158 return;
3159 if (! NILP (Ffont_get (font, QCname)))
3161 font = Fcopy_font_spec (font);
3162 font_put_extra (font, QCname, Qnil);
3165 if (NILP (AREF (font, prop))
3166 && prop != FONT_FAMILY_INDEX
3167 && prop != FONT_FOUNDRY_INDEX
3168 && prop != FONT_WIDTH_INDEX
3169 && prop != FONT_SIZE_INDEX)
3170 return;
3171 if (EQ (font, attrs[LFACE_FONT_INDEX]))
3172 font = Fcopy_font_spec (font);
3173 ASET (font, prop, Qnil);
3174 if (prop == FONT_FAMILY_INDEX || prop == FONT_FOUNDRY_INDEX)
3176 if (prop == FONT_FAMILY_INDEX)
3178 ASET (font, FONT_FOUNDRY_INDEX, Qnil);
3179 /* If we are setting the font family, we must also clear
3180 FONT_WIDTH_INDEX to avoid rejecting families that lack
3181 support for some widths. */
3182 ASET (font, FONT_WIDTH_INDEX, Qnil);
3184 ASET (font, FONT_ADSTYLE_INDEX, Qnil);
3185 ASET (font, FONT_REGISTRY_INDEX, Qnil);
3186 ASET (font, FONT_SIZE_INDEX, Qnil);
3187 ASET (font, FONT_DPI_INDEX, Qnil);
3188 ASET (font, FONT_SPACING_INDEX, Qnil);
3189 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3191 else if (prop == FONT_SIZE_INDEX)
3193 ASET (font, FONT_DPI_INDEX, Qnil);
3194 ASET (font, FONT_SPACING_INDEX, Qnil);
3195 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3197 else if (prop == FONT_WIDTH_INDEX)
3198 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3199 attrs[LFACE_FONT_INDEX] = font;
3202 void
3203 font_update_lface (f, attrs)
3204 FRAME_PTR f;
3205 Lisp_Object *attrs;
3207 Lisp_Object spec;
3209 spec = attrs[LFACE_FONT_INDEX];
3210 if (! FONT_SPEC_P (spec))
3211 return;
3213 if (! NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
3214 attrs[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX));
3215 if (! NILP (AREF (spec, FONT_FAMILY_INDEX)))
3216 attrs[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FAMILY_INDEX));
3217 if (! NILP (AREF (spec, FONT_WEIGHT_INDEX)))
3218 attrs[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (spec);
3219 if (! NILP (AREF (spec, FONT_SLANT_INDEX)))
3220 attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);
3221 if (! NILP (AREF (spec, FONT_WIDTH_INDEX)))
3222 attrs[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (spec);
3223 if (! NILP (AREF (spec, FONT_SIZE_INDEX)))
3225 int point;
3227 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
3229 Lisp_Object val;
3230 int dpi = f->resy;
3232 val = Ffont_get (spec, QCdpi);
3233 if (! NILP (val))
3234 dpi = XINT (val);
3235 point = PIXEL_TO_POINT (XINT (AREF (spec, FONT_SIZE_INDEX)) * 10,
3236 dpi);
3237 attrs[LFACE_HEIGHT_INDEX] = make_number (point);
3239 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
3241 point = XFLOAT_DATA (AREF (spec, FONT_SIZE_INDEX)) * 10;
3242 attrs[LFACE_HEIGHT_INDEX] = make_number (point);
3248 /* Selecte a font from ENTITIES (list of font-entity vectors) that
3249 supports C and matches best with ATTRS and PIXEL_SIZE. */
3251 static Lisp_Object
3252 font_select_entity (frame, entities, attrs, pixel_size, c)
3253 Lisp_Object frame, entities, *attrs;
3254 int pixel_size, c;
3256 Lisp_Object font_entity;
3257 Lisp_Object prefer;
3258 int result, i;
3259 FRAME_PTR f = XFRAME (frame);
3261 if (NILP (XCDR (entities))
3262 && ASIZE (XCAR (entities)) == 1)
3264 font_entity = AREF (XCAR (entities), 0);
3265 if (c < 0
3266 || (result = font_has_char (f, font_entity, c)) > 0)
3267 return font_entity;
3268 return Qnil;
3271 /* Sort fonts by properties specified in ATTRS. */
3272 prefer = scratch_font_prefer;
3274 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3275 ASET (prefer, i, Qnil);
3276 if (FONTP (attrs[LFACE_FONT_INDEX]))
3278 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3280 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3281 ASET (prefer, i, AREF (face_font, i));
3283 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
3284 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
3285 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
3286 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
3287 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
3288 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
3289 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
3291 return font_sort_entities (entities, prefer, frame, c);
3294 /* Return a font-entity satisfying SPEC and best matching with face's
3295 font related attributes in ATTRS. C, if not negative, is a
3296 character that the entity must support. */
3298 Lisp_Object
3299 font_find_for_lface (f, attrs, spec, c)
3300 FRAME_PTR f;
3301 Lisp_Object *attrs;
3302 Lisp_Object spec;
3303 int c;
3305 Lisp_Object work;
3306 Lisp_Object frame, entities, val;
3307 Lisp_Object size, foundry[3], *family, registry[3], adstyle[3];
3308 int pixel_size;
3309 int i, j, k, l;
3311 registry[0] = AREF (spec, FONT_REGISTRY_INDEX);
3312 if (NILP (registry[0]))
3314 registry[0] = DEFAULT_ENCODING;
3315 registry[1] = Qascii_0;
3316 registry[2] = null_vector;
3318 else
3319 registry[1] = null_vector;
3321 if (c >= 0 && ! NILP (AREF (spec, FONT_REGISTRY_INDEX)))
3323 struct charset *encoding, *repertory;
3325 if (font_registry_charsets (AREF (spec, FONT_REGISTRY_INDEX),
3326 &encoding, &repertory) < 0)
3327 return Qnil;
3328 if (repertory
3329 && ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
3330 return Qnil;
3331 else if (c > encoding->max_char)
3332 return Qnil;
3335 work = Fcopy_font_spec (spec);
3336 ASET (work, FONT_TYPE_INDEX, AREF (spec, FONT_TYPE_INDEX));
3337 XSETFRAME (frame, f);
3338 size = AREF (spec, FONT_SIZE_INDEX);
3339 pixel_size = font_pixel_size (f, spec);
3340 if (pixel_size == 0)
3342 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3344 pixel_size = POINT_TO_PIXEL (pt / 10, f->resy);
3346 ASET (work, FONT_SIZE_INDEX, Qnil);
3347 foundry[0] = AREF (work, FONT_FOUNDRY_INDEX);
3348 if (! NILP (foundry[0]))
3349 foundry[1] = null_vector;
3350 else if (STRINGP (attrs[LFACE_FOUNDRY_INDEX]))
3352 val = attrs[LFACE_FOUNDRY_INDEX];
3353 foundry[0] = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
3354 foundry[1] = Qnil;
3355 foundry[2] = null_vector;
3357 else
3358 foundry[0] = Qnil, foundry[1] = null_vector;
3360 adstyle[0] = AREF (work, FONT_ADSTYLE_INDEX);
3361 if (! NILP (adstyle[0]))
3362 adstyle[1] = null_vector;
3363 else if (FONTP (attrs[LFACE_FONT_INDEX]))
3365 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3367 if (! NILP (AREF (face_font, FONT_ADSTYLE_INDEX)))
3369 adstyle[0] = AREF (face_font, FONT_ADSTYLE_INDEX);
3370 adstyle[1] = Qnil;
3371 adstyle[2] = null_vector;
3373 else
3374 adstyle[0] = Qnil, adstyle[1] = null_vector;
3376 else
3377 adstyle[0] = Qnil, adstyle[1] = null_vector;
3380 val = AREF (work, FONT_FAMILY_INDEX);
3381 if (NILP (val) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
3383 val = attrs[LFACE_FAMILY_INDEX];
3384 val = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
3386 if (NILP (val))
3388 family = alloca ((sizeof family[0]) * 2);
3389 family[0] = Qnil;
3390 family[1] = null_vector; /* terminator. */
3392 else
3394 Lisp_Object alters
3395 = Fassoc_string (val, Vface_alternative_font_family_alist,
3396 /* Font family names are case-sensitive under NS. */
3397 #ifndef HAVE_NS
3399 #else
3400 Qnil
3401 #endif
3404 if (! NILP (alters))
3406 family = alloca ((sizeof family[0]) * (XINT (Flength (alters)) + 2));
3407 for (i = 0; CONSP (alters); i++, alters = XCDR (alters))
3408 family[i] = XCAR (alters);
3409 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3410 family[i++] = Qnil;
3411 family[i] = null_vector;
3413 else
3415 family = alloca ((sizeof family[0]) * 3);
3416 i = 0;
3417 family[i++] = val;
3418 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3419 family[i++] = Qnil;
3420 family[i] = null_vector;
3424 for (i = 0; SYMBOLP (family[i]); i++)
3426 ASET (work, FONT_FAMILY_INDEX, family[i]);
3427 for (j = 0; SYMBOLP (foundry[j]); j++)
3429 ASET (work, FONT_FOUNDRY_INDEX, foundry[j]);
3430 for (k = 0; SYMBOLP (registry[k]); k++)
3432 ASET (work, FONT_REGISTRY_INDEX, registry[k]);
3433 for (l = 0; SYMBOLP (adstyle[l]); l++)
3435 ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
3436 entities = font_list_entities (frame, work);
3437 if (! NILP (entities))
3439 val = font_select_entity (frame, entities,
3440 attrs, pixel_size, c);
3441 if (! NILP (val))
3442 return val;
3448 return Qnil;
3452 Lisp_Object
3453 font_open_for_lface (f, entity, attrs, spec)
3454 FRAME_PTR f;
3455 Lisp_Object entity;
3456 Lisp_Object *attrs;
3457 Lisp_Object spec;
3459 int size;
3461 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX))
3462 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
3463 size = XINT (AREF (entity, FONT_SIZE_INDEX));
3464 else if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
3465 size = font_pixel_size (f, spec);
3466 else
3468 double pt;
3469 if (INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
3470 pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3471 else
3473 struct face *def = FACE_FROM_ID (f, DEFAULT_FACE_ID);
3474 Lisp_Object height = def->lface[LFACE_HEIGHT_INDEX];
3475 if (INTEGERP (height))
3476 pt = XINT (height);
3477 else
3478 abort(); /* We should never end up here. */
3481 pt /= 10;
3482 size = POINT_TO_PIXEL (pt, f->resy);
3483 #ifdef HAVE_NS
3484 if (size == 0)
3486 Lisp_Object ffsize = get_frame_param(f, Qfontsize);
3487 size = NUMBERP (ffsize) ? POINT_TO_PIXEL (XINT (ffsize), f->resy) : 0;
3489 #endif
3491 return font_open_entity (f, entity, size);
3495 /* Find a font satisfying SPEC and best matching with face's
3496 attributes in ATTRS on FRAME, and return the opened
3497 font-object. */
3499 Lisp_Object
3500 font_load_for_lface (f, attrs, spec)
3501 FRAME_PTR f;
3502 Lisp_Object *attrs, spec;
3504 Lisp_Object entity;
3506 entity = font_find_for_lface (f, attrs, spec, -1);
3507 if (NILP (entity))
3509 /* No font is listed for SPEC, but each font-backend may have
3510 the different criteria about "font matching". So, try
3511 it. */
3512 entity = font_matching_entity (f, attrs, spec);
3513 if (NILP (entity))
3514 return Qnil;
3516 return font_open_for_lface (f, entity, attrs, spec);
3520 /* Make FACE on frame F ready to use the font opened for FACE. */
3522 void
3523 font_prepare_for_face (f, face)
3524 FRAME_PTR f;
3525 struct face *face;
3527 if (face->font->driver->prepare_face)
3528 face->font->driver->prepare_face (f, face);
3532 /* Make FACE on frame F stop using the font opened for FACE. */
3534 void
3535 font_done_for_face (f, face)
3536 FRAME_PTR f;
3537 struct face *face;
3539 if (face->font->driver->done_face)
3540 face->font->driver->done_face (f, face);
3541 face->extra = NULL;
3545 /* Open a font matching with font-spec SPEC on frame F. If no proper
3546 font is found, return Qnil. */
3548 Lisp_Object
3549 font_open_by_spec (f, spec)
3550 FRAME_PTR f;
3551 Lisp_Object spec;
3553 Lisp_Object attrs[LFACE_VECTOR_SIZE];
3555 /* We set up the default font-related attributes of a face to prefer
3556 a moderate font. */
3557 attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
3558 attrs[LFACE_SWIDTH_INDEX] = attrs[LFACE_WEIGHT_INDEX]
3559 = attrs[LFACE_SLANT_INDEX] = Qnormal;
3560 #ifndef HAVE_NS
3561 attrs[LFACE_HEIGHT_INDEX] = make_number (120);
3562 #else
3563 attrs[LFACE_HEIGHT_INDEX] = make_number (0);
3564 #endif
3565 attrs[LFACE_FONT_INDEX] = Qnil;
3567 return font_load_for_lface (f, attrs, spec);
3571 /* Open a font matching with NAME on frame F. If no proper font is
3572 found, return Qnil. */
3574 Lisp_Object
3575 font_open_by_name (f, name)
3576 FRAME_PTR f;
3577 char *name;
3579 Lisp_Object args[2];
3580 Lisp_Object spec;
3582 args[0] = QCname;
3583 args[1] = make_unibyte_string (name, strlen (name));
3584 spec = Ffont_spec (2, args);
3585 return font_open_by_spec (f, spec);
3589 /* Register font-driver DRIVER. This function is used in two ways.
3591 The first is with frame F non-NULL. In this case, make DRIVER
3592 available (but not yet activated) on F. All frame creaters
3593 (e.g. Fx_create_frame) must call this function at least once with
3594 an available font-driver.
3596 The second is with frame F NULL. In this case, DRIVER is globally
3597 registered in the variable `font_driver_list'. All font-driver
3598 implementations must call this function in its syms_of_XXXX
3599 (e.g. syms_of_xfont). */
3601 void
3602 register_font_driver (driver, f)
3603 struct font_driver *driver;
3604 FRAME_PTR f;
3606 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
3607 struct font_driver_list *prev, *list;
3609 if (f && ! driver->draw)
3610 error ("Unusable font driver for a frame: %s",
3611 SDATA (SYMBOL_NAME (driver->type)));
3613 for (prev = NULL, list = root; list; prev = list, list = list->next)
3614 if (EQ (list->driver->type, driver->type))
3615 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3617 list = xmalloc (sizeof (struct font_driver_list));
3618 list->on = 0;
3619 list->driver = driver;
3620 list->next = NULL;
3621 if (prev)
3622 prev->next = list;
3623 else if (f)
3624 f->font_driver_list = list;
3625 else
3626 font_driver_list = list;
3627 if (! f)
3628 num_font_drivers++;
3631 void
3632 free_font_driver_list (f)
3633 FRAME_PTR f;
3635 struct font_driver_list *list, *next;
3637 for (list = f->font_driver_list; list; list = next)
3639 next = list->next;
3640 xfree (list);
3642 f->font_driver_list = NULL;
3646 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3647 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3648 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3650 A caller must free all realized faces if any in advance. The
3651 return value is a list of font backends actually made used on
3652 F. */
3654 Lisp_Object
3655 font_update_drivers (f, new_drivers)
3656 FRAME_PTR f;
3657 Lisp_Object new_drivers;
3659 Lisp_Object active_drivers = Qnil;
3660 struct font_driver *driver;
3661 struct font_driver_list *list;
3663 /* At first, turn off non-requested drivers, and turn on requested
3664 drivers. */
3665 for (list = f->font_driver_list; list; list = list->next)
3667 driver = list->driver;
3668 if ((EQ (new_drivers, Qt) || ! NILP (Fmemq (driver->type, new_drivers)))
3669 != list->on)
3671 if (list->on)
3673 if (driver->end_for_frame)
3674 driver->end_for_frame (f);
3675 font_finish_cache (f, driver);
3676 list->on = 0;
3678 else
3680 if (! driver->start_for_frame
3681 || driver->start_for_frame (f) == 0)
3683 font_prepare_cache (f, driver);
3684 list->on = 1;
3690 if (NILP (new_drivers))
3691 return Qnil;
3693 if (! EQ (new_drivers, Qt))
3695 /* Re-order the driver list according to new_drivers. */
3696 struct font_driver_list **list_table, **next;
3697 Lisp_Object tail;
3698 int i;
3700 list_table = alloca (sizeof list_table[0] * (num_font_drivers + 1));
3701 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
3703 for (list = f->font_driver_list; list; list = list->next)
3704 if (list->on && EQ (list->driver->type, XCAR (tail)))
3705 break;
3706 if (list)
3707 list_table[i++] = list;
3709 for (list = f->font_driver_list; list; list = list->next)
3710 if (! list->on)
3711 list_table[i++] = list;
3712 list_table[i] = NULL;
3714 next = &f->font_driver_list;
3715 for (i = 0; list_table[i]; i++)
3717 *next = list_table[i];
3718 next = &(*next)->next;
3720 *next = NULL;
3722 if (! f->font_driver_list->on)
3723 { /* None of the drivers is enabled: enable them all.
3724 Happens if you set the list of drivers to (xft x) in your .emacs
3725 and then use it under w32 or ns. */
3726 for (list = f->font_driver_list; list; list = list->next)
3728 struct font_driver *driver = list->driver;
3729 eassert (! list->on);
3730 if (! driver->start_for_frame
3731 || driver->start_for_frame (f) == 0)
3733 font_prepare_cache (f, driver);
3734 list->on = 1;
3740 for (list = f->font_driver_list; list; list = list->next)
3741 if (list->on)
3742 active_drivers = nconc2 (active_drivers,
3743 Fcons (list->driver->type, Qnil));
3744 return active_drivers;
3748 font_put_frame_data (f, driver, data)
3749 FRAME_PTR f;
3750 struct font_driver *driver;
3751 void *data;
3753 struct font_data_list *list, *prev;
3755 for (prev = NULL, list = f->font_data_list; list;
3756 prev = list, list = list->next)
3757 if (list->driver == driver)
3758 break;
3759 if (! data)
3761 if (list)
3763 if (prev)
3764 prev->next = list->next;
3765 else
3766 f->font_data_list = list->next;
3767 xfree (list);
3769 return 0;
3772 if (! list)
3774 list = xmalloc (sizeof (struct font_data_list));
3775 list->driver = driver;
3776 list->next = f->font_data_list;
3777 f->font_data_list = list;
3779 list->data = data;
3780 return 0;
3784 void *
3785 font_get_frame_data (f, driver)
3786 FRAME_PTR f;
3787 struct font_driver *driver;
3789 struct font_data_list *list;
3791 for (list = f->font_data_list; list; list = list->next)
3792 if (list->driver == driver)
3793 break;
3794 if (! list)
3795 return NULL;
3796 return list->data;
3800 /* Return the font used to draw character C by FACE at buffer position
3801 POS in window W. If STRING is non-nil, it is a string containing C
3802 at index POS. If C is negative, get C from the current buffer or
3803 STRING. */
3805 Lisp_Object
3806 font_at (c, pos, face, w, string)
3807 int c;
3808 EMACS_INT pos;
3809 struct face *face;
3810 struct window *w;
3811 Lisp_Object string;
3813 FRAME_PTR f;
3814 int multibyte;
3815 Lisp_Object font_object;
3817 multibyte = (NILP (string)
3818 ? ! NILP (current_buffer->enable_multibyte_characters)
3819 : STRING_MULTIBYTE (string));
3820 if (c < 0)
3822 if (NILP (string))
3824 if (multibyte)
3826 EMACS_INT pos_byte = CHAR_TO_BYTE (pos);
3828 c = FETCH_CHAR (pos_byte);
3830 else
3831 c = FETCH_BYTE (pos);
3833 else
3835 unsigned char *str;
3837 multibyte = STRING_MULTIBYTE (string);
3838 if (multibyte)
3840 EMACS_INT pos_byte = string_char_to_byte (string, pos);
3842 str = SDATA (string) + pos_byte;
3843 c = STRING_CHAR (str, 0);
3845 else
3846 c = SDATA (string)[pos];
3850 f = XFRAME (w->frame);
3851 if (! FRAME_WINDOW_P (f))
3852 return Qnil;
3853 if (! face)
3855 int face_id;
3856 EMACS_INT endptr;
3858 if (STRINGP (string))
3859 face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
3860 DEFAULT_FACE_ID, 0);
3861 else
3862 face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
3863 pos + 100, 0, -1);
3864 face = FACE_FROM_ID (f, face_id);
3866 if (multibyte)
3868 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3869 face = FACE_FROM_ID (f, face_id);
3871 if (! face->font)
3872 return Qnil;
3874 XSETFONT (font_object, face->font);
3875 return font_object;
3879 #ifdef HAVE_WINDOW_SYSTEM
3881 /* Check how many characters after POS (at most to *LIMIT) can be
3882 displayed by the same font on the window W. FACE, if non-NULL, is
3883 the face selected for the character at POS. If STRING is not nil,
3884 it is the string to check instead of the current buffer. In that
3885 case, FACE must be not NULL.
3887 The return value is the font-object for the character at POS.
3888 *LIMIT is set to the position where that font can't be used.
3890 It is assured that the current buffer (or STRING) is multibyte. */
3892 Lisp_Object
3893 font_range (pos, limit, w, face, string)
3894 EMACS_INT pos, *limit;
3895 struct window *w;
3896 struct face *face;
3897 Lisp_Object string;
3899 EMACS_INT pos_byte, ignore, start, start_byte;
3900 int c;
3901 Lisp_Object font_object = Qnil;
3903 if (NILP (string))
3905 pos_byte = CHAR_TO_BYTE (pos);
3906 if (! face)
3908 int face_id;
3910 face_id = face_at_buffer_position (w, pos, 0, 0, &ignore,
3911 *limit, 0, -1);
3912 face = FACE_FROM_ID (XFRAME (w->frame), face_id);
3915 else
3917 font_assert (face);
3918 pos_byte = string_char_to_byte (string, pos);
3921 start = pos, start_byte = pos_byte;
3922 while (pos < *limit)
3924 Lisp_Object category;
3926 if (NILP (string))
3927 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3928 else
3929 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3930 if (NILP (font_object))
3932 font_object = font_for_char (face, c, pos - 1, string);
3933 if (NILP (font_object))
3934 return Qnil;
3935 continue;
3938 category = CHAR_TABLE_REF (Vunicode_category_table, c);
3939 if (! EQ (category, QCf)
3940 && ! CHAR_VARIATION_SELECTOR_P (c)
3941 && font_encode_char (font_object, c) == FONT_INVALID_CODE)
3943 Lisp_Object f = font_for_char (face, c, pos - 1, string);
3944 EMACS_INT i, i_byte;
3947 if (NILP (f))
3949 *limit = pos - 1;
3950 return font_object;
3952 i = start, i_byte = start_byte;
3953 while (i < pos - 1)
3956 if (NILP (string))
3957 FETCH_CHAR_ADVANCE_NO_CHECK (c, i, i_byte);
3958 else
3959 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, i, i_byte);
3960 category = CHAR_TABLE_REF (Vunicode_category_table, c);
3961 if (! EQ (category, QCf)
3962 && ! CHAR_VARIATION_SELECTOR_P (c)
3963 && font_encode_char (f, c) == FONT_INVALID_CODE)
3965 *limit = pos - 1;
3966 return font_object;
3969 font_object = f;
3972 return font_object;
3974 #endif
3977 /* Lisp API */
3979 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3980 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3981 Return nil otherwise.
3982 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3983 which kind of font it is. It must be one of `font-spec', `font-entity',
3984 `font-object'. */)
3985 (object, extra_type)
3986 Lisp_Object object, extra_type;
3988 if (NILP (extra_type))
3989 return (FONTP (object) ? Qt : Qnil);
3990 if (EQ (extra_type, Qfont_spec))
3991 return (FONT_SPEC_P (object) ? Qt : Qnil);
3992 if (EQ (extra_type, Qfont_entity))
3993 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3994 if (EQ (extra_type, Qfont_object))
3995 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3996 wrong_type_argument (intern ("font-extra-type"), extra_type);
3999 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
4000 doc: /* Return a newly created font-spec with arguments as properties.
4002 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
4003 valid font property name listed below:
4005 `:family', `:weight', `:slant', `:width'
4007 They are the same as face attributes of the same name. See
4008 `set-face-attribute'.
4010 `:foundry'
4012 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
4014 `:adstyle'
4016 VALUE must be a string or a symbol specifying the additional
4017 typographic style information of a font, e.g. ``sans''.
4019 `:registry'
4021 VALUE must be a string or a symbol specifying the charset registry and
4022 encoding of a font, e.g. ``iso8859-1''.
4024 `:size'
4026 VALUE must be a non-negative integer or a floating point number
4027 specifying the font size. It specifies the font size in pixels (if
4028 VALUE is an integer), or in points (if VALUE is a float).
4030 `:name'
4032 VALUE must be a string of XLFD-style or fontconfig-style font name.
4034 `:script'
4036 VALUE must be a symbol representing a script that the font must
4037 support. It may be a symbol representing a subgroup of a script
4038 listed in the variable `script-representative-chars'.
4040 `:lang'
4042 VALUE must be a symbol of two-letter ISO-639 language names,
4043 e.g. `ja'.
4045 `:otf'
4047 VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
4048 required OpenType features.
4050 SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
4051 LANGSYS-TAG: OpenType language system tag symbol,
4052 or nil for the default language system.
4053 GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
4054 GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
4056 GSUB and GPOS may contain `nil' element. In such a case, the font
4057 must not have any of the remaining elements.
4059 For instance, if the VALUE is `(thai nil nil (mark))', the font must
4060 be an OpenType font, and whose GPOS table of `thai' script's default
4061 language system must contain `mark' feature.
4063 usage: (font-spec ARGS...) */)
4064 (nargs, args)
4065 int nargs;
4066 Lisp_Object *args;
4068 Lisp_Object spec = font_make_spec ();
4069 int i;
4071 for (i = 0; i < nargs; i += 2)
4073 Lisp_Object key = args[i], val;
4075 CHECK_SYMBOL (key);
4076 if (i + 1 >= nargs)
4077 error ("No value for key `%s'", SDATA (SYMBOL_NAME (key)));
4078 val = args[i + 1];
4080 if (EQ (key, QCname))
4082 CHECK_STRING (val);
4083 font_parse_name ((char *) SDATA (val), spec);
4084 font_put_extra (spec, key, val);
4086 else
4088 int idx = get_font_prop_index (key);
4090 if (idx >= 0)
4092 val = font_prop_validate (idx, Qnil, val);
4093 if (idx < FONT_EXTRA_INDEX)
4094 ASET (spec, idx, val);
4095 else
4096 font_put_extra (spec, key, val);
4098 else
4099 font_put_extra (spec, key, font_prop_validate (0, key, val));
4102 return spec;
4105 DEFUN ("copy-font-spec", Fcopy_font_spec, Scopy_font_spec, 1, 1, 0,
4106 doc: /* Return a copy of FONT as a font-spec. */)
4107 (font)
4108 Lisp_Object font;
4110 Lisp_Object new_spec, tail, prev, extra;
4111 int i;
4113 CHECK_FONT (font);
4114 new_spec = font_make_spec ();
4115 for (i = 1; i < FONT_EXTRA_INDEX; i++)
4116 ASET (new_spec, i, AREF (font, i));
4117 extra = Fcopy_sequence (AREF (font, FONT_EXTRA_INDEX));
4118 /* We must remove :font-entity property. */
4119 for (prev = Qnil, tail = extra; CONSP (tail); prev = tail, tail = XCDR (tail))
4120 if (EQ (XCAR (XCAR (tail)), QCfont_entity))
4122 if (NILP (prev))
4123 extra = XCDR (extra);
4124 else
4125 XSETCDR (prev, XCDR (tail));
4126 break;
4128 ASET (new_spec, FONT_EXTRA_INDEX, extra);
4129 return new_spec;
4132 DEFUN ("merge-font-spec", Fmerge_font_spec, Smerge_font_spec, 2, 2, 0,
4133 doc: /* Merge font-specs FROM and TO, and return a new font-spec.
4134 Every specified properties in FROM override the corresponding
4135 properties in TO. */)
4136 (from, to)
4137 Lisp_Object from, to;
4139 Lisp_Object extra, tail;
4140 int i;
4142 CHECK_FONT (from);
4143 CHECK_FONT (to);
4144 to = Fcopy_font_spec (to);
4145 for (i = 0; i < FONT_EXTRA_INDEX; i++)
4146 ASET (to, i, AREF (from, i));
4147 extra = AREF (to, FONT_EXTRA_INDEX);
4148 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
4149 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
4151 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
4153 if (! NILP (slot))
4154 XSETCDR (slot, XCDR (XCAR (tail)));
4155 else
4156 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
4158 ASET (to, FONT_EXTRA_INDEX, extra);
4159 return to;
4162 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
4163 doc: /* Return the value of FONT's property KEY.
4164 FONT is a font-spec, a font-entity, or a font-object.
4165 KEY must be one of these symbols:
4166 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
4167 :size, :name, :script
4168 See the documentation of `font-spec' for their meanings.
4169 If FONT is a font-entity or font-object, the value of :script may be
4170 a list of scripts that are supported by the font. */)
4171 (font, key)
4172 Lisp_Object font, key;
4174 int idx;
4176 CHECK_FONT (font);
4177 CHECK_SYMBOL (key);
4179 idx = get_font_prop_index (key);
4180 if (idx >= FONT_WEIGHT_INDEX && idx <= FONT_WIDTH_INDEX)
4181 return font_style_symbolic (font, idx, 0);
4182 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4183 return AREF (font, idx);
4184 return Fcdr (Fassq (key, AREF (font, FONT_EXTRA_INDEX)));
4187 #ifdef HAVE_WINDOW_SYSTEM
4189 DEFUN ("font-face-attributes", Ffont_face_attributes, Sfont_face_attributes, 1, 2, 0,
4190 doc: /* Return a plist of face attributes generated by FONT.
4191 FONT is a font name, a font-spec, a font-entity, or a font-object.
4192 The return value is a list of the form
4194 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
4196 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
4197 compatible with `set-face-attribute'. Some of these key-attribute pairs
4198 may be omitted from the list if they are not specified by FONT.
4200 The optional argument FRAME specifies the frame that the face attributes
4201 are to be displayed on. If omitted, the selected frame is used. */)
4202 (font, frame)
4203 Lisp_Object font, frame;
4205 struct frame *f;
4206 Lisp_Object plist[10];
4207 Lisp_Object val;
4208 int n = 0;
4210 if (NILP (frame))
4211 frame = selected_frame;
4212 CHECK_LIVE_FRAME (frame);
4213 f = XFRAME (frame);
4215 if (STRINGP (font))
4217 int fontset = fs_query_fontset (font, 0);
4218 Lisp_Object name = font;
4219 if (fontset >= 0)
4220 font = fontset_ascii (fontset);
4221 font = font_spec_from_name (name);
4222 if (! FONTP (font))
4223 signal_error ("Invalid font name", name);
4225 else if (! FONTP (font))
4226 signal_error ("Invalid font object", font);
4228 val = AREF (font, FONT_FAMILY_INDEX);
4229 if (! NILP (val))
4231 plist[n++] = QCfamily;
4232 plist[n++] = SYMBOL_NAME (val);
4235 val = AREF (font, FONT_SIZE_INDEX);
4236 if (INTEGERP (val))
4238 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
4239 int dpi = INTEGERP (font_dpi) ? XINT (font_dpi) : f->resy;
4240 plist[n++] = QCheight;
4241 plist[n++] = make_number (PIXEL_TO_POINT (XINT (val) * 10, dpi));
4243 else if (FLOATP (val))
4245 plist[n++] = QCheight;
4246 plist[n++] = make_number (10 * (int) XFLOAT_DATA (val));
4249 val = FONT_WEIGHT_FOR_FACE (font);
4250 if (! NILP (val))
4252 plist[n++] = QCweight;
4253 plist[n++] = val;
4256 val = FONT_SLANT_FOR_FACE (font);
4257 if (! NILP (val))
4259 plist[n++] = QCslant;
4260 plist[n++] = val;
4263 val = FONT_WIDTH_FOR_FACE (font);
4264 if (! NILP (val))
4266 plist[n++] = QCwidth;
4267 plist[n++] = val;
4270 return Flist (n, plist);
4273 #endif
4275 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
4276 doc: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
4277 (font_spec, prop, val)
4278 Lisp_Object font_spec, prop, val;
4280 int idx;
4282 CHECK_FONT_SPEC (font_spec);
4283 idx = get_font_prop_index (prop);
4284 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4285 ASET (font_spec, idx, font_prop_validate (idx, Qnil, val));
4286 else
4287 font_put_extra (font_spec, prop, font_prop_validate (0, prop, val));
4288 return val;
4291 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
4292 doc: /* List available fonts matching FONT-SPEC on the current frame.
4293 Optional 2nd argument FRAME specifies the target frame.
4294 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4295 Optional 4th argument PREFER, if non-nil, is a font-spec to
4296 control the order of the returned list. Fonts are sorted by
4297 how close they are to PREFER. */)
4298 (font_spec, frame, num, prefer)
4299 Lisp_Object font_spec, frame, num, prefer;
4301 Lisp_Object vec, list;
4302 int n = 0;
4304 if (NILP (frame))
4305 frame = selected_frame;
4306 CHECK_LIVE_FRAME (frame);
4307 CHECK_FONT_SPEC (font_spec);
4308 if (! NILP (num))
4310 CHECK_NUMBER (num);
4311 n = XINT (num);
4312 if (n <= 0)
4313 return Qnil;
4315 if (! NILP (prefer))
4316 CHECK_FONT_SPEC (prefer);
4318 list = font_list_entities (frame, font_spec);
4319 if (NILP (list))
4320 return Qnil;
4321 if (NILP (XCDR (list))
4322 && ASIZE (XCAR (list)) == 1)
4323 return Fcons (AREF (XCAR (list), 0), Qnil);
4325 if (! NILP (prefer))
4326 vec = font_sort_entities (list, prefer, frame, 0);
4327 else
4328 vec = font_vconcat_entity_vectors (list);
4329 if (n == 0 || n >= ASIZE (vec))
4331 Lisp_Object args[2];
4333 args[0] = vec;
4334 args[1] = Qnil;
4335 list = Fappend (2, args);
4337 else
4339 for (list = Qnil, n--; n >= 0; n--)
4340 list = Fcons (AREF (vec, n), list);
4342 return list;
4345 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
4346 doc: /* List available font families on the current frame.
4347 Optional argument FRAME, if non-nil, specifies the target frame. */)
4348 (frame)
4349 Lisp_Object frame;
4351 FRAME_PTR f;
4352 struct font_driver_list *driver_list;
4353 Lisp_Object list;
4355 if (NILP (frame))
4356 frame = selected_frame;
4357 CHECK_LIVE_FRAME (frame);
4358 f = XFRAME (frame);
4359 list = Qnil;
4360 for (driver_list = f->font_driver_list; driver_list;
4361 driver_list = driver_list->next)
4362 if (driver_list->driver->list_family)
4364 Lisp_Object val = driver_list->driver->list_family (frame);
4365 Lisp_Object tail = list;
4367 for (; CONSP (val); val = XCDR (val))
4368 if (NILP (Fmemq (XCAR (val), tail))
4369 && SYMBOLP (XCAR (val)))
4370 list = Fcons (SYMBOL_NAME (XCAR (val)), list);
4372 return list;
4375 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
4376 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
4377 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4378 (font_spec, frame)
4379 Lisp_Object font_spec, frame;
4381 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
4383 if (CONSP (val))
4384 val = XCAR (val);
4385 return val;
4388 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
4389 doc: /* Return XLFD name of FONT.
4390 FONT is a font-spec, font-entity, or font-object.
4391 If the name is too long for XLFD (maximum 255 chars), return nil.
4392 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4393 the consecutive wildcards are folded to one. */)
4394 (font, fold_wildcards)
4395 Lisp_Object font, fold_wildcards;
4397 char name[256];
4398 int pixel_size = 0;
4400 CHECK_FONT (font);
4402 if (FONT_OBJECT_P (font))
4404 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
4406 if (STRINGP (font_name)
4407 && SDATA (font_name)[0] == '-')
4409 if (NILP (fold_wildcards))
4410 return font_name;
4411 strcpy (name, (char *) SDATA (font_name));
4412 goto done;
4414 pixel_size = XFONT_OBJECT (font)->pixel_size;
4416 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
4417 return Qnil;
4418 done:
4419 if (! NILP (fold_wildcards))
4421 char *p0 = name, *p1;
4423 while ((p1 = strstr (p0, "-*-*")))
4425 strcpy (p1, p1 + 2);
4426 p0 = p1;
4430 return build_string (name);
4433 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
4434 doc: /* Clear font cache. */)
4437 Lisp_Object list, frame;
4439 FOR_EACH_FRAME (list, frame)
4441 FRAME_PTR f = XFRAME (frame);
4442 struct font_driver_list *driver_list = f->font_driver_list;
4444 for (; driver_list; driver_list = driver_list->next)
4445 if (driver_list->on)
4447 Lisp_Object cache = driver_list->driver->get_cache (f);
4448 Lisp_Object val;
4450 val = XCDR (cache);
4451 while (! NILP (val)
4452 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
4453 val = XCDR (val);
4454 font_assert (! NILP (val));
4455 val = XCDR (XCAR (val));
4456 if (XINT (XCAR (val)) == 0)
4458 font_clear_cache (f, XCAR (val), driver_list->driver);
4459 XSETCDR (cache, XCDR (val));
4464 return Qnil;
4468 void
4469 font_fill_lglyph_metrics (glyph, font_object)
4470 Lisp_Object glyph, font_object;
4472 struct font *font = XFONT_OBJECT (font_object);
4473 unsigned code;
4474 /* ecode used in LGLYPH_SET_CODE to avoid compiler warnings. */
4475 EMACS_INT ecode = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
4476 struct font_metrics metrics;
4478 LGLYPH_SET_CODE (glyph, ecode);
4479 code = ecode;
4480 font->driver->text_extents (font, &code, 1, &metrics);
4481 LGLYPH_SET_LBEARING (glyph, metrics.lbearing);
4482 LGLYPH_SET_RBEARING (glyph, metrics.rbearing);
4483 LGLYPH_SET_WIDTH (glyph, metrics.width);
4484 LGLYPH_SET_ASCENT (glyph, metrics.ascent);
4485 LGLYPH_SET_DESCENT (glyph, metrics.descent);
4489 DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0,
4490 doc: /* Shape the glyph-string GSTRING.
4491 Shaping means substituting glyphs and/or adjusting positions of glyphs
4492 to get the correct visual image of character sequences set in the
4493 header of the glyph-string.
4495 If the shaping was successful, the value is GSTRING itself or a newly
4496 created glyph-string. Otherwise, the value is nil. */)
4497 (gstring)
4498 Lisp_Object gstring;
4500 struct font *font;
4501 Lisp_Object font_object, n, glyph;
4502 int i, j, from, to;
4504 if (! composition_gstring_p (gstring))
4505 signal_error ("Invalid glyph-string: ", gstring);
4506 if (! NILP (LGSTRING_ID (gstring)))
4507 return gstring;
4508 font_object = LGSTRING_FONT (gstring);
4509 CHECK_FONT_OBJECT (font_object);
4510 font = XFONT_OBJECT (font_object);
4511 if (! font->driver->shape)
4512 return Qnil;
4514 /* Try at most three times with larger gstring each time. */
4515 for (i = 0; i < 3; i++)
4517 n = font->driver->shape (gstring);
4518 if (INTEGERP (n))
4519 break;
4520 gstring = larger_vector (gstring,
4521 ASIZE (gstring) + LGSTRING_GLYPH_LEN (gstring),
4522 Qnil);
4524 if (i == 3 || XINT (n) == 0)
4525 return Qnil;
4527 glyph = LGSTRING_GLYPH (gstring, 0);
4528 from = LGLYPH_FROM (glyph);
4529 to = LGLYPH_TO (glyph);
4530 for (i = 1, j = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
4532 Lisp_Object this = LGSTRING_GLYPH (gstring, i);
4534 if (NILP (this))
4535 break;
4536 if (NILP (LGLYPH_ADJUSTMENT (this)))
4538 if (j < i - 1)
4539 for (; j < i; j++)
4541 glyph = LGSTRING_GLYPH (gstring, j);
4542 LGLYPH_SET_FROM (glyph, from);
4543 LGLYPH_SET_TO (glyph, to);
4545 from = LGLYPH_FROM (this);
4546 to = LGLYPH_TO (this);
4547 j = i;
4549 else
4551 if (from > LGLYPH_FROM (this))
4552 from = LGLYPH_FROM (this);
4553 if (to < LGLYPH_TO (this))
4554 to = LGLYPH_TO (this);
4557 if (j < i - 1)
4558 for (; j < i; j++)
4560 glyph = LGSTRING_GLYPH (gstring, j);
4561 LGLYPH_SET_FROM (glyph, from);
4562 LGLYPH_SET_TO (glyph, to);
4564 return composition_gstring_put_cache (gstring, XINT (n));
4567 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
4568 2, 2, 0,
4569 doc: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4570 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4571 where
4572 VARIATION-SELECTOR is a chracter code of variation selection
4573 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4574 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4575 (font_object, character)
4576 Lisp_Object font_object, character;
4578 unsigned variations[256];
4579 struct font *font;
4580 int i, n;
4581 Lisp_Object val;
4583 CHECK_FONT_OBJECT (font_object);
4584 CHECK_CHARACTER (character);
4585 font = XFONT_OBJECT (font_object);
4586 if (! font->driver->get_variation_glyphs)
4587 return Qnil;
4588 n = font->driver->get_variation_glyphs (font, XINT (character), variations);
4589 if (! n)
4590 return Qnil;
4591 val = Qnil;
4592 for (i = 0; i < 255; i++)
4593 if (variations[i])
4595 Lisp_Object code;
4596 int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
4597 /* Stops GCC whining about limited range of data type. */
4598 EMACS_INT var = variations[i];
4600 if (var > MOST_POSITIVE_FIXNUM)
4601 code = Fcons (make_number ((variations[i]) >> 16),
4602 make_number ((variations[i]) & 0xFFFF));
4603 else
4604 code = make_number (variations[i]);
4605 val = Fcons (Fcons (make_number (vs), code), val);
4607 return val;
4610 #if 0
4612 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
4613 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
4614 OTF-FEATURES specifies which features to apply in this format:
4615 (SCRIPT LANGSYS GSUB GPOS)
4616 where
4617 SCRIPT is a symbol specifying a script tag of OpenType,
4618 LANGSYS is a symbol specifying a langsys tag of OpenType,
4619 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4621 If LANGYS is nil, the default langsys is selected.
4623 The features are applied in the order they appear in the list. The
4624 symbol `*' means to apply all available features not present in this
4625 list, and the remaining features are ignored. For instance, (vatu
4626 pstf * haln) is to apply vatu and pstf in this order, then to apply
4627 all available features other than vatu, pstf, and haln.
4629 The features are applied to the glyphs in the range FROM and TO of
4630 the glyph-string GSTRING-IN.
4632 If some feature is actually applicable, the resulting glyphs are
4633 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4634 this case, the value is the number of produced glyphs.
4636 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4637 the value is 0.
4639 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4640 produced in GSTRING-OUT, and the value is nil.
4642 See the documentation of `font-make-gstring' for the format of
4643 glyph-string. */)
4644 (otf_features, gstring_in, from, to, gstring_out, index)
4645 Lisp_Object otf_features, gstring_in, from, to, gstring_out, index;
4647 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
4648 Lisp_Object val;
4649 struct font *font;
4650 int len, num;
4652 check_otf_features (otf_features);
4653 CHECK_FONT_OBJECT (font_object);
4654 font = XFONT_OBJECT (font_object);
4655 if (! font->driver->otf_drive)
4656 error ("Font backend %s can't drive OpenType GSUB table",
4657 SDATA (SYMBOL_NAME (font->driver->type)));
4658 CHECK_CONS (otf_features);
4659 CHECK_SYMBOL (XCAR (otf_features));
4660 val = XCDR (otf_features);
4661 CHECK_SYMBOL (XCAR (val));
4662 val = XCDR (otf_features);
4663 if (! NILP (val))
4664 CHECK_CONS (val);
4665 len = check_gstring (gstring_in);
4666 CHECK_VECTOR (gstring_out);
4667 CHECK_NATNUM (from);
4668 CHECK_NATNUM (to);
4669 CHECK_NATNUM (index);
4671 if (XINT (from) >= XINT (to) || XINT (to) > len)
4672 args_out_of_range_3 (from, to, make_number (len));
4673 if (XINT (index) >= ASIZE (gstring_out))
4674 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4675 num = font->driver->otf_drive (font, otf_features,
4676 gstring_in, XINT (from), XINT (to),
4677 gstring_out, XINT (index), 0);
4678 if (num < 0)
4679 return Qnil;
4680 return make_number (num);
4683 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4684 3, 3, 0,
4685 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4686 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4687 in this format:
4688 (SCRIPT LANGSYS FEATURE ...)
4689 See the documentation of `font-drive-otf' for more detail.
4691 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4692 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4693 character code corresponding to the glyph or nil if there's no
4694 corresponding character. */)
4695 (font_object, character, otf_features)
4696 Lisp_Object font_object, character, otf_features;
4698 struct font *font;
4699 Lisp_Object gstring_in, gstring_out, g;
4700 Lisp_Object alternates;
4701 int i, num;
4703 CHECK_FONT_GET_OBJECT (font_object, font);
4704 if (! font->driver->otf_drive)
4705 error ("Font backend %s can't drive OpenType GSUB table",
4706 SDATA (SYMBOL_NAME (font->driver->type)));
4707 CHECK_CHARACTER (character);
4708 CHECK_CONS (otf_features);
4710 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4711 g = LGSTRING_GLYPH (gstring_in, 0);
4712 LGLYPH_SET_CHAR (g, XINT (character));
4713 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4714 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4715 gstring_out, 0, 1)) < 0)
4716 gstring_out = Ffont_make_gstring (font_object,
4717 make_number (ASIZE (gstring_out) * 2));
4718 alternates = Qnil;
4719 for (i = 0; i < num; i++)
4721 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4722 int c = LGLYPH_CHAR (g);
4723 unsigned code = LGLYPH_CODE (g);
4725 alternates = Fcons (Fcons (make_number (code),
4726 c > 0 ? make_number (c) : Qnil),
4727 alternates);
4729 return Fnreverse (alternates);
4731 #endif /* 0 */
4733 #ifdef FONT_DEBUG
4735 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4736 doc: /* Open FONT-ENTITY. */)
4737 (font_entity, size, frame)
4738 Lisp_Object font_entity;
4739 Lisp_Object size;
4740 Lisp_Object frame;
4742 int isize;
4744 CHECK_FONT_ENTITY (font_entity);
4745 if (NILP (frame))
4746 frame = selected_frame;
4747 CHECK_LIVE_FRAME (frame);
4749 if (NILP (size))
4750 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4751 else
4753 CHECK_NUMBER_OR_FLOAT (size);
4754 if (FLOATP (size))
4755 isize = POINT_TO_PIXEL (XFLOAT_DATA (size), XFRAME (frame)->resy);
4756 else
4757 isize = XINT (size);
4758 if (isize == 0)
4759 isize = 120;
4761 return font_open_entity (XFRAME (frame), font_entity, isize);
4764 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4765 doc: /* Close FONT-OBJECT. */)
4766 (font_object, frame)
4767 Lisp_Object font_object, frame;
4769 CHECK_FONT_OBJECT (font_object);
4770 if (NILP (frame))
4771 frame = selected_frame;
4772 CHECK_LIVE_FRAME (frame);
4773 font_close_object (XFRAME (frame), font_object);
4774 return Qnil;
4777 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4778 doc: /* Return information about FONT-OBJECT.
4779 The value is a vector:
4780 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4781 CAPABILITY ]
4783 NAME is a string of the font name (or nil if the font backend doesn't
4784 provide a name).
4786 FILENAME is a string of the font file (or nil if the font backend
4787 doesn't provide a file name).
4789 PIXEL-SIZE is a pixel size by which the font is opened.
4791 SIZE is a maximum advance width of the font in pixels.
4793 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4794 pixels.
4796 CAPABILITY is a list whose first element is a symbol representing the
4797 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4798 remaining elements describe the details of the font capability.
4800 If the font is OpenType font, the form of the list is
4801 \(opentype GSUB GPOS)
4802 where GSUB shows which "GSUB" features the font supports, and GPOS
4803 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4804 lists of the format:
4805 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4807 If the font is not OpenType font, currently the length of the form is
4808 one.
4810 SCRIPT is a symbol representing OpenType script tag.
4812 LANGSYS is a symbol representing OpenType langsys tag, or nil
4813 representing the default langsys.
4815 FEATURE is a symbol representing OpenType feature tag.
4817 If the font is not OpenType font, CAPABILITY is nil. */)
4818 (font_object)
4819 Lisp_Object font_object;
4821 struct font *font;
4822 Lisp_Object val;
4824 CHECK_FONT_GET_OBJECT (font_object, font);
4826 val = Fmake_vector (make_number (9), Qnil);
4827 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4828 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4829 ASET (val, 2, make_number (font->pixel_size));
4830 ASET (val, 3, make_number (font->max_width));
4831 ASET (val, 4, make_number (font->ascent));
4832 ASET (val, 5, make_number (font->descent));
4833 ASET (val, 6, make_number (font->space_width));
4834 ASET (val, 7, make_number (font->average_width));
4835 if (font->driver->otf_capability)
4836 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4837 return val;
4840 DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
4841 doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
4842 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
4843 (font_object, string)
4844 Lisp_Object font_object, string;
4846 struct font *font;
4847 int i, len;
4848 Lisp_Object vec;
4850 CHECK_FONT_GET_OBJECT (font_object, font);
4851 CHECK_STRING (string);
4852 len = SCHARS (string);
4853 vec = Fmake_vector (make_number (len), Qnil);
4854 for (i = 0; i < len; i++)
4856 Lisp_Object ch = Faref (string, make_number (i));
4857 Lisp_Object val;
4858 int c = XINT (ch);
4859 unsigned code;
4860 EMACS_INT cod;
4861 struct font_metrics metrics;
4863 cod = code = font->driver->encode_char (font, c);
4864 if (code == FONT_INVALID_CODE)
4865 continue;
4866 val = Fmake_vector (make_number (6), Qnil);
4867 if (cod <= MOST_POSITIVE_FIXNUM)
4868 ASET (val, 0, make_number (code));
4869 else
4870 ASET (val, 0, Fcons (make_number (code >> 16),
4871 make_number (code & 0xFFFF)));
4872 font->driver->text_extents (font, &code, 1, &metrics);
4873 ASET (val, 1, make_number (metrics.lbearing));
4874 ASET (val, 2, make_number (metrics.rbearing));
4875 ASET (val, 3, make_number (metrics.width));
4876 ASET (val, 4, make_number (metrics.ascent));
4877 ASET (val, 5, make_number (metrics.descent));
4878 ASET (vec, i, val);
4880 return vec;
4883 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4884 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4885 FONT is a font-spec, font-entity, or font-object. */)
4886 (spec, font)
4887 Lisp_Object spec, font;
4889 CHECK_FONT_SPEC (spec);
4890 CHECK_FONT (font);
4892 return (font_match_p (spec, font) ? Qt : Qnil);
4895 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4896 doc: /* Return a font-object for displaying a character at POSITION.
4897 Optional second arg WINDOW, if non-nil, is a window displaying
4898 the current buffer. It defaults to the currently selected window. */)
4899 (position, window, string)
4900 Lisp_Object position, window, string;
4902 struct window *w;
4903 EMACS_INT pos;
4905 if (NILP (string))
4907 CHECK_NUMBER_COERCE_MARKER (position);
4908 pos = XINT (position);
4909 if (pos < BEGV || pos >= ZV)
4910 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4912 else
4914 CHECK_NUMBER (position);
4915 CHECK_STRING (string);
4916 pos = XINT (position);
4917 if (pos < 0 || pos >= SCHARS (string))
4918 args_out_of_range (string, position);
4920 if (NILP (window))
4921 window = selected_window;
4922 CHECK_LIVE_WINDOW (window);
4923 w = XWINDOW (window);
4925 return font_at (-1, pos, NULL, w, string);
4928 #if 0
4929 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4930 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4931 The value is a number of glyphs drawn.
4932 Type C-l to recover what previously shown. */)
4933 (font_object, string)
4934 Lisp_Object font_object, string;
4936 Lisp_Object frame = selected_frame;
4937 FRAME_PTR f = XFRAME (frame);
4938 struct font *font;
4939 struct face *face;
4940 int i, len, width;
4941 unsigned *code;
4943 CHECK_FONT_GET_OBJECT (font_object, font);
4944 CHECK_STRING (string);
4945 len = SCHARS (string);
4946 code = alloca (sizeof (unsigned) * len);
4947 for (i = 0; i < len; i++)
4949 Lisp_Object ch = Faref (string, make_number (i));
4950 Lisp_Object val;
4951 int c = XINT (ch);
4953 code[i] = font->driver->encode_char (font, c);
4954 if (code[i] == FONT_INVALID_CODE)
4955 break;
4957 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4958 face->fontp = font;
4959 if (font->driver->prepare_face)
4960 font->driver->prepare_face (f, face);
4961 width = font->driver->text_extents (font, code, i, NULL);
4962 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4963 if (font->driver->done_face)
4964 font->driver->done_face (f, face);
4965 face->fontp = NULL;
4966 return make_number (len);
4968 #endif
4970 #endif /* FONT_DEBUG */
4972 #ifdef HAVE_WINDOW_SYSTEM
4974 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
4975 doc: /* Return information about a font named NAME on frame FRAME.
4976 If FRAME is omitted or nil, use the selected frame.
4977 The returned value is a vector of OPENED-NAME, FULL-NAME, SIZE,
4978 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4979 where
4980 OPENED-NAME is the name used for opening the font,
4981 FULL-NAME is the full name of the font,
4982 SIZE is the pixelsize of the font,
4983 HEIGHT is the pixel-height of the font (i.e ascent + descent),
4984 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4985 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4986 how to compose characters.
4987 If the named font is not yet loaded, return nil. */)
4988 (name, frame)
4989 Lisp_Object name, frame;
4991 FRAME_PTR f;
4992 struct font *font;
4993 Lisp_Object info;
4994 Lisp_Object font_object;
4996 (*check_window_system_func) ();
4998 if (! FONTP (name))
4999 CHECK_STRING (name);
5000 if (NILP (frame))
5001 frame = selected_frame;
5002 CHECK_LIVE_FRAME (frame);
5003 f = XFRAME (frame);
5005 if (STRINGP (name))
5007 int fontset = fs_query_fontset (name, 0);
5009 if (fontset >= 0)
5010 name = fontset_ascii (fontset);
5011 font_object = font_open_by_name (f, (char *) SDATA (name));
5013 else if (FONT_OBJECT_P (name))
5014 font_object = name;
5015 else if (FONT_ENTITY_P (name))
5016 font_object = font_open_entity (f, name, 0);
5017 else
5019 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5020 Lisp_Object entity = font_matching_entity (f, face->lface, name);
5022 font_object = ! NILP (entity) ? font_open_entity (f, entity, 0) : Qnil;
5024 if (NILP (font_object))
5025 return Qnil;
5026 font = XFONT_OBJECT (font_object);
5028 info = Fmake_vector (make_number (7), Qnil);
5029 XVECTOR (info)->contents[0] = AREF (font_object, FONT_NAME_INDEX);
5030 XVECTOR (info)->contents[1] = AREF (font_object, FONT_FULLNAME_INDEX);
5031 XVECTOR (info)->contents[2] = make_number (font->pixel_size);
5032 XVECTOR (info)->contents[3] = make_number (font->height);
5033 XVECTOR (info)->contents[4] = make_number (font->baseline_offset);
5034 XVECTOR (info)->contents[5] = make_number (font->relative_compose);
5035 XVECTOR (info)->contents[6] = make_number (font->default_ascent);
5037 #if 0
5038 /* As font_object is still in FONT_OBJLIST of the entity, we can't
5039 close it now. Perhaps, we should manage font-objects
5040 by `reference-count'. */
5041 font_close_object (f, font_object);
5042 #endif
5043 return info;
5045 #endif
5048 #define BUILD_STYLE_TABLE(TBL) \
5049 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
5051 static Lisp_Object
5052 build_style_table (entry, nelement)
5053 struct table_entry *entry;
5054 int nelement;
5056 int i, j;
5057 Lisp_Object table, elt;
5059 table = Fmake_vector (make_number (nelement), Qnil);
5060 for (i = 0; i < nelement; i++)
5062 for (j = 0; entry[i].names[j]; j++);
5063 elt = Fmake_vector (make_number (j + 1), Qnil);
5064 ASET (elt, 0, make_number (entry[i].numeric));
5065 for (j = 0; entry[i].names[j]; j++)
5066 ASET (elt, j + 1, intern (entry[i].names[j]));
5067 ASET (table, i, elt);
5069 return table;
5072 Lisp_Object Vfont_log;
5074 /* The deferred font-log data of the form [ACTION ARG RESULT].
5075 If ACTION is not nil, that is added to the log when font_add_log is
5076 called next time. At that time, ACTION is set back to nil. */
5077 static Lisp_Object Vfont_log_deferred;
5079 /* Prepend the font-related logging data in Vfont_log if it is not
5080 `t'. ACTION describes a kind of font-related action (e.g. listing,
5081 opening), ARG is the argument for the action, and RESULT is the
5082 result of the action. */
5083 void
5084 font_add_log (action, arg, result)
5085 char *action;
5086 Lisp_Object arg, result;
5088 Lisp_Object tail, val;
5089 int i;
5091 if (EQ (Vfont_log, Qt))
5092 return;
5093 if (STRINGP (AREF (Vfont_log_deferred, 0)))
5095 char *str = (char *) SDATA (AREF (Vfont_log_deferred, 0));
5097 ASET (Vfont_log_deferred, 0, Qnil);
5098 font_add_log (str, AREF (Vfont_log_deferred, 1),
5099 AREF (Vfont_log_deferred, 2));
5102 if (FONTP (arg))
5104 Lisp_Object tail, elt;
5105 Lisp_Object equalstr = build_string ("=");
5107 val = Ffont_xlfd_name (arg, Qt);
5108 for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail);
5109 tail = XCDR (tail))
5111 elt = XCAR (tail);
5112 if (EQ (XCAR (elt), QCscript)
5113 && SYMBOLP (XCDR (elt)))
5114 val = concat3 (val, SYMBOL_NAME (QCscript),
5115 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
5116 else if (EQ (XCAR (elt), QClang)
5117 && SYMBOLP (XCDR (elt)))
5118 val = concat3 (val, SYMBOL_NAME (QClang),
5119 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
5120 else if (EQ (XCAR (elt), QCotf)
5121 && CONSP (XCDR (elt)) && SYMBOLP (XCAR (XCDR (elt))))
5122 val = concat3 (val, SYMBOL_NAME (QCotf),
5123 concat2 (equalstr,
5124 SYMBOL_NAME (XCAR (XCDR (elt)))));
5126 arg = val;
5129 if (CONSP (result)
5130 && VECTORP (XCAR (result))
5131 && ASIZE (XCAR (result)) > 0
5132 && FONTP (AREF (XCAR (result), 0)))
5133 result = font_vconcat_entity_vectors (result);
5134 if (FONTP (result))
5136 val = Ffont_xlfd_name (result, Qt);
5137 if (! FONT_SPEC_P (result))
5138 val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)),
5139 build_string (":"), val);
5140 result = val;
5142 else if (CONSP (result))
5144 result = Fcopy_sequence (result);
5145 for (tail = result; CONSP (tail); tail = XCDR (tail))
5147 val = XCAR (tail);
5148 if (FONTP (val))
5149 val = Ffont_xlfd_name (val, Qt);
5150 XSETCAR (tail, val);
5153 else if (VECTORP (result))
5155 result = Fcopy_sequence (result);
5156 for (i = 0; i < ASIZE (result); i++)
5158 val = AREF (result, i);
5159 if (FONTP (val))
5160 val = Ffont_xlfd_name (val, Qt);
5161 ASET (result, i, val);
5164 Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
5167 /* Record a font-related logging data to be added to Vfont_log when
5168 font_add_log is called next time. ACTION, ARG, RESULT are the same
5169 as font_add_log. */
5171 void
5172 font_deferred_log (action, arg, result)
5173 char *action;
5174 Lisp_Object arg, result;
5176 if (EQ (Vfont_log, Qt))
5177 return;
5178 ASET (Vfont_log_deferred, 0, build_string (action));
5179 ASET (Vfont_log_deferred, 1, arg);
5180 ASET (Vfont_log_deferred, 2, result);
5183 extern void syms_of_ftfont P_ (());
5184 extern void syms_of_xfont P_ (());
5185 extern void syms_of_xftfont P_ (());
5186 extern void syms_of_ftxfont P_ (());
5187 extern void syms_of_bdffont P_ (());
5188 extern void syms_of_w32font P_ (());
5189 extern void syms_of_atmfont P_ (());
5190 extern void syms_of_nsfont P_ (());
5192 void
5193 syms_of_font ()
5195 sort_shift_bits[FONT_TYPE_INDEX] = 0;
5196 sort_shift_bits[FONT_SLANT_INDEX] = 2;
5197 sort_shift_bits[FONT_WEIGHT_INDEX] = 9;
5198 sort_shift_bits[FONT_SIZE_INDEX] = 16;
5199 sort_shift_bits[FONT_WIDTH_INDEX] = 23;
5200 /* Note that the other elements in sort_shift_bits are not used. */
5202 staticpro (&font_charset_alist);
5203 font_charset_alist = Qnil;
5205 DEFSYM (Qopentype, "opentype");
5207 DEFSYM (Qascii_0, "ascii-0");
5208 DEFSYM (Qiso8859_1, "iso8859-1");
5209 DEFSYM (Qiso10646_1, "iso10646-1");
5210 DEFSYM (Qunicode_bmp, "unicode-bmp");
5211 DEFSYM (Qunicode_sip, "unicode-sip");
5213 DEFSYM (QCf, "Cf");
5215 DEFSYM (QCotf, ":otf");
5216 DEFSYM (QClang, ":lang");
5217 DEFSYM (QCscript, ":script");
5218 DEFSYM (QCantialias, ":antialias");
5220 DEFSYM (QCfoundry, ":foundry");
5221 DEFSYM (QCadstyle, ":adstyle");
5222 DEFSYM (QCregistry, ":registry");
5223 DEFSYM (QCspacing, ":spacing");
5224 DEFSYM (QCdpi, ":dpi");
5225 DEFSYM (QCscalable, ":scalable");
5226 DEFSYM (QCavgwidth, ":avgwidth");
5227 DEFSYM (QCfont_entity, ":font-entity");
5228 DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
5230 DEFSYM (Qc, "c");
5231 DEFSYM (Qm, "m");
5232 DEFSYM (Qp, "p");
5233 DEFSYM (Qd, "d");
5235 DEFSYM (Qja, "ja");
5236 DEFSYM (Qko, "ko");
5238 staticpro (&null_vector);
5239 null_vector = Fmake_vector (make_number (0), Qnil);
5241 staticpro (&scratch_font_spec);
5242 scratch_font_spec = Ffont_spec (0, NULL);
5243 staticpro (&scratch_font_prefer);
5244 scratch_font_prefer = Ffont_spec (0, NULL);
5246 staticpro (&Vfont_log_deferred);
5247 Vfont_log_deferred = Fmake_vector (make_number (3), Qnil);
5249 #if 0
5250 #ifdef HAVE_LIBOTF
5251 staticpro (&otf_list);
5252 otf_list = Qnil;
5253 #endif /* HAVE_LIBOTF */
5254 #endif /* 0 */
5256 defsubr (&Sfontp);
5257 defsubr (&Sfont_spec);
5258 defsubr (&Sfont_get);
5259 #ifdef HAVE_WINDOW_SYSTEM
5260 defsubr (&Sfont_face_attributes);
5261 #endif
5262 defsubr (&Sfont_put);
5263 defsubr (&Slist_fonts);
5264 defsubr (&Sfont_family_list);
5265 defsubr (&Sfind_font);
5266 defsubr (&Sfont_xlfd_name);
5267 defsubr (&Sclear_font_cache);
5268 defsubr (&Sfont_shape_gstring);
5269 defsubr (&Sfont_variation_glyphs);
5270 #if 0
5271 defsubr (&Sfont_drive_otf);
5272 defsubr (&Sfont_otf_alternates);
5273 #endif /* 0 */
5275 #ifdef FONT_DEBUG
5276 defsubr (&Sopen_font);
5277 defsubr (&Sclose_font);
5278 defsubr (&Squery_font);
5279 defsubr (&Sget_font_glyphs);
5280 defsubr (&Sfont_match_p);
5281 defsubr (&Sfont_at);
5282 #if 0
5283 defsubr (&Sdraw_string);
5284 #endif
5285 #endif /* FONT_DEBUG */
5286 #ifdef HAVE_WINDOW_SYSTEM
5287 defsubr (&Sfont_info);
5288 #endif
5290 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
5291 doc: /*
5292 Alist of fontname patterns vs the corresponding encoding and repertory info.
5293 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5294 where ENCODING is a charset or a char-table,
5295 and REPERTORY is a charset, a char-table, or nil.
5297 If ENCODING and REPERTORY are the same, the element can have the form
5298 \(REGEXP . ENCODING).
5300 ENCODING is for converting a character to a glyph code of the font.
5301 If ENCODING is a charset, encoding a character by the charset gives
5302 the corresponding glyph code. If ENCODING is a char-table, looking up
5303 the table by a character gives the corresponding glyph code.
5305 REPERTORY specifies a repertory of characters supported by the font.
5306 If REPERTORY is a charset, all characters beloging to the charset are
5307 supported. If REPERTORY is a char-table, all characters who have a
5308 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5309 gets the repertory information by an opened font and ENCODING. */);
5310 Vfont_encoding_alist = Qnil;
5312 DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table,
5313 doc: /* Vector of valid font weight values.
5314 Each element has the form:
5315 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5316 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5317 Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
5319 DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table,
5320 doc: /* Vector of font slant symbols vs the corresponding numeric values.
5321 See `font-weight-table' for the format of the vector. */);
5322 Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
5324 DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table,
5325 doc: /* Alist of font width symbols vs the corresponding numeric values.
5326 See `font-weight-table' for the format of the vector. */);
5327 Vfont_width_table = BUILD_STYLE_TABLE (width_table);
5329 staticpro (&font_style_table);
5330 font_style_table = Fmake_vector (make_number (3), Qnil);
5331 ASET (font_style_table, 0, Vfont_weight_table);
5332 ASET (font_style_table, 1, Vfont_slant_table);
5333 ASET (font_style_table, 2, Vfont_width_table);
5335 DEFVAR_LISP ("font-log", &Vfont_log, doc: /*
5336 *Logging list of font related actions and results.
5337 The value t means to suppress the logging.
5338 The initial value is set to nil if the environment variable
5339 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5340 Vfont_log = Qnil;
5342 #ifdef HAVE_WINDOW_SYSTEM
5343 #ifdef HAVE_FREETYPE
5344 syms_of_ftfont ();
5345 #ifdef HAVE_X_WINDOWS
5346 syms_of_xfont ();
5347 syms_of_ftxfont ();
5348 #ifdef HAVE_XFT
5349 syms_of_xftfont ();
5350 #endif /* HAVE_XFT */
5351 #endif /* HAVE_X_WINDOWS */
5352 #else /* not HAVE_FREETYPE */
5353 #ifdef HAVE_X_WINDOWS
5354 syms_of_xfont ();
5355 #endif /* HAVE_X_WINDOWS */
5356 #endif /* not HAVE_FREETYPE */
5357 #ifdef HAVE_BDFFONT
5358 syms_of_bdffont ();
5359 #endif /* HAVE_BDFFONT */
5360 #ifdef WINDOWSNT
5361 syms_of_w32font ();
5362 #endif /* WINDOWSNT */
5363 #ifdef HAVE_NS
5364 syms_of_nsfont ();
5365 #endif /* HAVE_NS */
5366 #endif /* HAVE_WINDOW_SYSTEM */
5369 void
5370 init_font ()
5372 Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;
5375 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
5376 (do not change this comment) */