]> code.delx.au - gnu-emacs/blob - src/font.c
Fix memory leak in fontset handling
[gnu-emacs] / src / font.c
1 /* font.c -- "Font" primitives.
2
3 Copyright (C) 2006-2015 Free Software Foundation, Inc.
4 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
5 National Institute of Advanced Industrial Science and Technology (AIST)
6 Registration Number H13PRO009
7
8 This file is part of GNU Emacs.
9
10 GNU Emacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 GNU Emacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22
23 #include <config.h>
24 #include <float.h>
25 #include <stdio.h>
26
27 #include <c-ctype.h>
28
29 #include "lisp.h"
30 #include "character.h"
31 #include "buffer.h"
32 #include "frame.h"
33 #include "window.h"
34 #include "dispextern.h"
35 #include "charset.h"
36 #include "composite.h"
37 #include "fontset.h"
38 #include "font.h"
39
40 #ifdef HAVE_WINDOW_SYSTEM
41 #include TERM_HEADER
42 #endif /* HAVE_WINDOW_SYSTEM */
43
44 #define DEFAULT_ENCODING Qiso8859_1
45
46 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
47 static Lisp_Object font_style_table;
48
49 /* Structure used for tables mapping weight, slant, and width numeric
50 values and their names. */
51
52 struct table_entry
53 {
54 int numeric;
55 /* The first one is a valid name as a face attribute.
56 The second one (if any) is a typical name in XLFD field. */
57 const char *names[5];
58 };
59
60 /* Table of weight numeric values and their names. This table must be
61 sorted by numeric values in ascending order. */
62
63 static const struct table_entry weight_table[] =
64 {
65 { 0, { "thin" }},
66 { 20, { "ultra-light", "ultralight" }},
67 { 40, { "extra-light", "extralight" }},
68 { 50, { "light" }},
69 { 75, { "semi-light", "semilight", "demilight", "book" }},
70 { 100, { "normal", "medium", "regular", "unspecified" }},
71 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
72 { 200, { "bold" }},
73 { 205, { "extra-bold", "extrabold" }},
74 { 210, { "ultra-bold", "ultrabold", "black" }}
75 };
76
77 /* Table of slant numeric values and their names. This table must be
78 sorted by numeric values in ascending order. */
79
80 static const struct table_entry slant_table[] =
81 {
82 { 0, { "reverse-oblique", "ro" }},
83 { 10, { "reverse-italic", "ri" }},
84 { 100, { "normal", "r", "unspecified" }},
85 { 200, { "italic" ,"i", "ot" }},
86 { 210, { "oblique", "o" }}
87 };
88
89 /* Table of width numeric values and their names. This table must be
90 sorted by numeric values in ascending order. */
91
92 static const struct table_entry width_table[] =
93 {
94 { 50, { "ultra-condensed", "ultracondensed" }},
95 { 63, { "extra-condensed", "extracondensed" }},
96 { 75, { "condensed", "compressed", "narrow" }},
97 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
98 { 100, { "normal", "medium", "regular", "unspecified" }},
99 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
100 { 125, { "expanded" }},
101 { 150, { "extra-expanded", "extraexpanded" }},
102 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
103 };
104
105 /* Alist of font registry symbols and the corresponding charset
106 information. The information is retrieved from
107 Vfont_encoding_alist on demand.
108
109 Eash element has the form:
110 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
111 or
112 (REGISTRY . nil)
113
114 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
115 encodes a character code to a glyph code of a font, and
116 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
117 character is supported by a font.
118
119 The latter form means that the information for REGISTRY couldn't be
120 retrieved. */
121 static Lisp_Object font_charset_alist;
122
123 /* List of all font drivers. Each font-backend (XXXfont.c) calls
124 register_font_driver in syms_of_XXXfont to register its font-driver
125 here. */
126 static struct font_driver_list *font_driver_list;
127
128 #ifdef ENABLE_CHECKING
129
130 /* Used to catch bogus pointers in font objects. */
131
132 bool
133 valid_font_driver (struct font_driver *drv)
134 {
135 Lisp_Object tail, frame;
136 struct font_driver_list *fdl;
137
138 for (fdl = font_driver_list; fdl; fdl = fdl->next)
139 if (fdl->driver == drv)
140 return true;
141 FOR_EACH_FRAME (tail, frame)
142 for (fdl = XFRAME (frame)->font_driver_list; fdl; fdl = fdl->next)
143 if (fdl->driver == drv)
144 return true;
145 return false;
146 }
147
148 #endif /* ENABLE_CHECKING */
149
150 /* Creators of font-related Lisp object. */
151
152 static Lisp_Object
153 font_make_spec (void)
154 {
155 Lisp_Object font_spec;
156 struct font_spec *spec
157 = ((struct font_spec *)
158 allocate_pseudovector (VECSIZE (struct font_spec),
159 FONT_SPEC_MAX, FONT_SPEC_MAX, PVEC_FONT));
160 XSETFONT (font_spec, spec);
161 return font_spec;
162 }
163
164 Lisp_Object
165 font_make_entity (void)
166 {
167 Lisp_Object font_entity;
168 struct font_entity *entity
169 = ((struct font_entity *)
170 allocate_pseudovector (VECSIZE (struct font_entity),
171 FONT_ENTITY_MAX, FONT_ENTITY_MAX, PVEC_FONT));
172 XSETFONT (font_entity, entity);
173 return font_entity;
174 }
175
176 /* Create a font-object whose structure size is SIZE. If ENTITY is
177 not nil, copy properties from ENTITY to the font-object. If
178 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
179 Lisp_Object
180 font_make_object (int size, Lisp_Object entity, int pixelsize)
181 {
182 Lisp_Object font_object;
183 struct font *font
184 = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX,
185 FONT_OBJECT_MAX, PVEC_FONT);
186 int i;
187
188 /* GC can happen before the driver is set up,
189 so avoid dangling pointer here (Bug#17771). */
190 font->driver = NULL;
191 XSETFONT (font_object, font);
192
193 if (! NILP (entity))
194 {
195 for (i = 1; i < FONT_SPEC_MAX; i++)
196 font->props[i] = AREF (entity, i);
197 if (! NILP (AREF (entity, FONT_EXTRA_INDEX)))
198 font->props[FONT_EXTRA_INDEX]
199 = Fcopy_alist (AREF (entity, FONT_EXTRA_INDEX));
200 }
201 if (size > 0)
202 font->props[FONT_SIZE_INDEX] = make_number (pixelsize);
203 return font_object;
204 }
205
206 #if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS)
207
208 static int font_unparse_fcname (Lisp_Object, int, char *, int);
209
210 /* Like above, but also set `type', `name' and `fullname' properties
211 of font-object. */
212
213 Lisp_Object
214 font_build_object (int vectorsize, Lisp_Object type,
215 Lisp_Object entity, double pixelsize)
216 {
217 int len;
218 char name[256];
219 Lisp_Object font_object = font_make_object (vectorsize, entity, pixelsize);
220
221 ASET (font_object, FONT_TYPE_INDEX, type);
222 len = font_unparse_xlfd (entity, pixelsize, name, sizeof name);
223 if (len > 0)
224 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
225 len = font_unparse_fcname (entity, pixelsize, name, sizeof name);
226 if (len > 0)
227 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
228 else
229 ASET (font_object, FONT_FULLNAME_INDEX,
230 AREF (font_object, FONT_NAME_INDEX));
231 return font_object;
232 }
233
234 #endif /* HAVE_XFT || HAVE_FREETYPE || HAVE_NS */
235
236 static int font_pixel_size (struct frame *f, Lisp_Object);
237 static Lisp_Object font_open_entity (struct frame *, Lisp_Object, int);
238 static Lisp_Object font_matching_entity (struct frame *, Lisp_Object *,
239 Lisp_Object);
240 static unsigned font_encode_char (Lisp_Object, int);
241
242 /* Number of registered font drivers. */
243 static int num_font_drivers;
244
245
246 /* Return a Lispy value of a font property value at STR and LEN bytes.
247 If STR is "*", return nil. If FORCE_SYMBOL, or if STR does not
248 consist entirely of one or more digits, return a symbol interned
249 from STR. Otherwise, return an integer. */
250
251 Lisp_Object
252 font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol)
253 {
254 ptrdiff_t i, nbytes, nchars;
255 Lisp_Object tem, name, obarray;
256
257 if (len == 1 && *str == '*')
258 return Qnil;
259 if (!force_symbol && 0 < len && '0' <= *str && *str <= '9')
260 {
261 for (i = 1; i < len; i++)
262 if (! ('0' <= str[i] && str[i] <= '9'))
263 break;
264 if (i == len)
265 {
266 EMACS_INT n;
267
268 i = 0;
269 for (n = 0; (n += str[i++] - '0') <= MOST_POSITIVE_FIXNUM; n *= 10)
270 {
271 if (i == len)
272 return make_number (n);
273 if (MOST_POSITIVE_FIXNUM / 10 < n)
274 break;
275 }
276
277 xsignal1 (Qoverflow_error, make_string (str, len));
278 }
279 }
280
281 /* This code is similar to intern function from lread.c. */
282 obarray = check_obarray (Vobarray);
283 parse_str_as_multibyte ((unsigned char *) str, len, &nchars, &nbytes);
284 tem = oblookup (obarray, str,
285 (len == nchars || len != nbytes) ? len : nchars, len);
286 if (SYMBOLP (tem))
287 return tem;
288 name = make_specified_string (str, nchars, len,
289 len != nchars && len == nbytes);
290 return intern_driver (name, obarray, tem);
291 }
292
293 /* Return a pixel size of font-spec SPEC on frame F. */
294
295 static int
296 font_pixel_size (struct frame *f, Lisp_Object spec)
297 {
298 #ifdef HAVE_WINDOW_SYSTEM
299 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
300 double point_size;
301 int dpi, pixel_size;
302 Lisp_Object val;
303
304 if (INTEGERP (size))
305 return XINT (size);
306 if (NILP (size))
307 return 0;
308 eassert (FLOATP (size));
309 point_size = XFLOAT_DATA (size);
310 val = AREF (spec, FONT_DPI_INDEX);
311 if (INTEGERP (val))
312 dpi = XINT (val);
313 else
314 dpi = FRAME_RES_Y (f);
315 pixel_size = POINT_TO_PIXEL (point_size, dpi);
316 return pixel_size;
317 #else
318 return 1;
319 #endif
320 }
321
322
323 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
324 font vector. If VAL is not valid (i.e. not registered in
325 font_style_table), return -1 if NOERROR is zero, and return a
326 proper index if NOERROR is nonzero. In that case, register VAL in
327 font_style_table if VAL is a symbol, and return the closest index if
328 VAL is an integer. */
329
330 int
331 font_style_to_value (enum font_property_index prop, Lisp_Object val,
332 bool noerror)
333 {
334 Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
335 int len;
336
337 CHECK_VECTOR (table);
338 len = ASIZE (table);
339
340 if (SYMBOLP (val))
341 {
342 int i, j;
343 char *s;
344 Lisp_Object elt;
345
346 /* At first try exact match. */
347 for (i = 0; i < len; i++)
348 {
349 CHECK_VECTOR (AREF (table, i));
350 for (j = 1; j < ASIZE (AREF (table, i)); j++)
351 if (EQ (val, AREF (AREF (table, i), j)))
352 {
353 CHECK_NUMBER (AREF (AREF (table, i), 0));
354 return ((XINT (AREF (AREF (table, i), 0)) << 8)
355 | (i << 4) | (j - 1));
356 }
357 }
358 /* Try also with case-folding match. */
359 s = SSDATA (SYMBOL_NAME (val));
360 for (i = 0; i < len; i++)
361 for (j = 1; j < ASIZE (AREF (table, i)); j++)
362 {
363 elt = AREF (AREF (table, i), j);
364 if (xstrcasecmp (s, SSDATA (SYMBOL_NAME (elt))) == 0)
365 {
366 CHECK_NUMBER (AREF (AREF (table, i), 0));
367 return ((XINT (AREF (AREF (table, i), 0)) << 8)
368 | (i << 4) | (j - 1));
369 }
370 }
371 if (! noerror)
372 return -1;
373 eassert (len < 255);
374 elt = Fmake_vector (make_number (2), make_number (100));
375 ASET (elt, 1, val);
376 ASET (font_style_table, prop - FONT_WEIGHT_INDEX,
377 CALLN (Fvconcat, table, Fmake_vector (make_number (1), elt)));
378 return (100 << 8) | (i << 4);
379 }
380 else
381 {
382 int i, last_n;
383 EMACS_INT numeric = XINT (val);
384
385 for (i = 0, last_n = -1; i < len; i++)
386 {
387 int n;
388
389 CHECK_VECTOR (AREF (table, i));
390 CHECK_NUMBER (AREF (AREF (table, i), 0));
391 n = XINT (AREF (AREF (table, i), 0));
392 if (numeric == n)
393 return (n << 8) | (i << 4);
394 if (numeric < n)
395 {
396 if (! noerror)
397 return -1;
398 return ((i == 0 || n - numeric < numeric - last_n)
399 ? (n << 8) | (i << 4): (last_n << 8 | ((i - 1) << 4)));
400 }
401 last_n = n;
402 }
403 if (! noerror)
404 return -1;
405 return ((last_n << 8) | ((i - 1) << 4));
406 }
407 }
408
409 Lisp_Object
410 font_style_symbolic (Lisp_Object font, enum font_property_index prop,
411 bool for_face)
412 {
413 Lisp_Object val = AREF (font, prop);
414 Lisp_Object table, elt;
415 int i;
416
417 if (NILP (val))
418 return Qnil;
419 table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
420 CHECK_VECTOR (table);
421 i = XINT (val) & 0xFF;
422 eassert (((i >> 4) & 0xF) < ASIZE (table));
423 elt = AREF (table, ((i >> 4) & 0xF));
424 CHECK_VECTOR (elt);
425 eassert ((i & 0xF) + 1 < ASIZE (elt));
426 elt = (for_face ? AREF (elt, 1) : AREF (elt, (i & 0xF) + 1));
427 CHECK_SYMBOL (elt);
428 return elt;
429 }
430
431 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
432 FONTNAME. ENCODING is a charset symbol that specifies the encoding
433 of the font. REPERTORY is a charset symbol or nil. */
434
435 Lisp_Object
436 find_font_encoding (Lisp_Object fontname)
437 {
438 Lisp_Object tail, elt;
439
440 for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
441 {
442 elt = XCAR (tail);
443 if (CONSP (elt)
444 && STRINGP (XCAR (elt))
445 && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
446 && (SYMBOLP (XCDR (elt))
447 ? CHARSETP (XCDR (elt))
448 : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
449 return (XCDR (elt));
450 }
451 return Qnil;
452 }
453
454 /* Return encoding charset and repertory charset for REGISTRY in
455 ENCODING and REPERTORY correspondingly. If correct information for
456 REGISTRY is available, return 0. Otherwise return -1. */
457
458 int
459 font_registry_charsets (Lisp_Object registry, struct charset **encoding, struct charset **repertory)
460 {
461 Lisp_Object val;
462 int encoding_id, repertory_id;
463
464 val = Fassoc_string (registry, font_charset_alist, Qt);
465 if (! NILP (val))
466 {
467 val = XCDR (val);
468 if (NILP (val))
469 return -1;
470 encoding_id = XINT (XCAR (val));
471 repertory_id = XINT (XCDR (val));
472 }
473 else
474 {
475 val = find_font_encoding (SYMBOL_NAME (registry));
476 if (SYMBOLP (val) && CHARSETP (val))
477 {
478 encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val));
479 }
480 else if (CONSP (val))
481 {
482 if (! CHARSETP (XCAR (val)))
483 goto invalid_entry;
484 encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val)));
485 if (NILP (XCDR (val)))
486 repertory_id = -1;
487 else
488 {
489 if (! CHARSETP (XCDR (val)))
490 goto invalid_entry;
491 repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val)));
492 }
493 }
494 else
495 goto invalid_entry;
496 val = Fcons (make_number (encoding_id), make_number (repertory_id));
497 font_charset_alist
498 = nconc2 (font_charset_alist, list1 (Fcons (registry, val)));
499 }
500
501 if (encoding)
502 *encoding = CHARSET_FROM_ID (encoding_id);
503 if (repertory)
504 *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL;
505 return 0;
506
507 invalid_entry:
508 font_charset_alist
509 = nconc2 (font_charset_alist, list1 (Fcons (registry, Qnil)));
510 return -1;
511 }
512
513 \f
514 /* Font property value validators. See the comment of
515 font_property_table for the meaning of the arguments. */
516
517 static Lisp_Object font_prop_validate (int, Lisp_Object, Lisp_Object);
518 static Lisp_Object font_prop_validate_symbol (Lisp_Object, Lisp_Object);
519 static Lisp_Object font_prop_validate_style (Lisp_Object, Lisp_Object);
520 static Lisp_Object font_prop_validate_non_neg (Lisp_Object, Lisp_Object);
521 static Lisp_Object font_prop_validate_spacing (Lisp_Object, Lisp_Object);
522 static int get_font_prop_index (Lisp_Object);
523
524 static Lisp_Object
525 font_prop_validate_symbol (Lisp_Object prop, Lisp_Object val)
526 {
527 if (STRINGP (val))
528 val = Fintern (val, Qnil);
529 if (! SYMBOLP (val))
530 val = Qerror;
531 else if (EQ (prop, QCregistry))
532 val = Fintern (Fdowncase (SYMBOL_NAME (val)), Qnil);
533 return val;
534 }
535
536
537 static Lisp_Object
538 font_prop_validate_style (Lisp_Object style, Lisp_Object val)
539 {
540 enum font_property_index prop = (EQ (style, QCweight) ? FONT_WEIGHT_INDEX
541 : EQ (style, QCslant) ? FONT_SLANT_INDEX
542 : FONT_WIDTH_INDEX);
543 if (INTEGERP (val))
544 {
545 EMACS_INT n = XINT (val);
546 CHECK_VECTOR (AREF (font_style_table, prop - FONT_WEIGHT_INDEX));
547 if (((n >> 4) & 0xF)
548 >= ASIZE (AREF (font_style_table, prop - FONT_WEIGHT_INDEX)))
549 val = Qerror;
550 else
551 {
552 Lisp_Object elt = AREF (AREF (font_style_table, prop - FONT_WEIGHT_INDEX), (n >> 4) & 0xF);
553
554 CHECK_VECTOR (elt);
555 if ((n & 0xF) + 1 >= ASIZE (elt))
556 val = Qerror;
557 else
558 {
559 CHECK_NUMBER (AREF (elt, 0));
560 if (XINT (AREF (elt, 0)) != (n >> 8))
561 val = Qerror;
562 }
563 }
564 }
565 else if (SYMBOLP (val))
566 {
567 int n = font_style_to_value (prop, val, 0);
568
569 val = n >= 0 ? make_number (n) : Qerror;
570 }
571 else
572 val = Qerror;
573 return val;
574 }
575
576 static Lisp_Object
577 font_prop_validate_non_neg (Lisp_Object prop, Lisp_Object val)
578 {
579 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
580 ? val : Qerror);
581 }
582
583 static Lisp_Object
584 font_prop_validate_spacing (Lisp_Object prop, Lisp_Object val)
585 {
586 if (NILP (val) || (NATNUMP (val) && XINT (val) <= FONT_SPACING_CHARCELL))
587 return val;
588 if (SYMBOLP (val) && SBYTES (SYMBOL_NAME (val)) == 1)
589 {
590 char spacing = SDATA (SYMBOL_NAME (val))[0];
591
592 if (spacing == 'c' || spacing == 'C')
593 return make_number (FONT_SPACING_CHARCELL);
594 if (spacing == 'm' || spacing == 'M')
595 return make_number (FONT_SPACING_MONO);
596 if (spacing == 'p' || spacing == 'P')
597 return make_number (FONT_SPACING_PROPORTIONAL);
598 if (spacing == 'd' || spacing == 'D')
599 return make_number (FONT_SPACING_DUAL);
600 }
601 return Qerror;
602 }
603
604 static Lisp_Object
605 font_prop_validate_otf (Lisp_Object prop, Lisp_Object val)
606 {
607 Lisp_Object tail, tmp;
608 int i;
609
610 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
611 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
612 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
613 if (! CONSP (val))
614 return Qerror;
615 if (! SYMBOLP (XCAR (val)))
616 return Qerror;
617 tail = XCDR (val);
618 if (NILP (tail))
619 return val;
620 if (! CONSP (tail) || ! SYMBOLP (XCAR (val)))
621 return Qerror;
622 for (i = 0; i < 2; i++)
623 {
624 tail = XCDR (tail);
625 if (NILP (tail))
626 return val;
627 if (! CONSP (tail))
628 return Qerror;
629 for (tmp = XCAR (tail); CONSP (tmp); tmp = XCDR (tmp))
630 if (! SYMBOLP (XCAR (tmp)))
631 return Qerror;
632 if (! NILP (tmp))
633 return Qerror;
634 }
635 return val;
636 }
637
638 /* Structure of known font property keys and validator of the
639 values. */
640 static const struct
641 {
642 /* Index of the key symbol. */
643 int key;
644 /* Function to validate PROP's value VAL, or NULL if any value is
645 ok. The value is VAL or its regularized value if VAL is valid,
646 and Qerror if not. */
647 Lisp_Object (*validator) (Lisp_Object prop, Lisp_Object val);
648 } font_property_table[] =
649 { { SYMBOL_INDEX (QCtype), font_prop_validate_symbol },
650 { SYMBOL_INDEX (QCfoundry), font_prop_validate_symbol },
651 { SYMBOL_INDEX (QCfamily), font_prop_validate_symbol },
652 { SYMBOL_INDEX (QCadstyle), font_prop_validate_symbol },
653 { SYMBOL_INDEX (QCregistry), font_prop_validate_symbol },
654 { SYMBOL_INDEX (QCweight), font_prop_validate_style },
655 { SYMBOL_INDEX (QCslant), font_prop_validate_style },
656 { SYMBOL_INDEX (QCwidth), font_prop_validate_style },
657 { SYMBOL_INDEX (QCsize), font_prop_validate_non_neg },
658 { SYMBOL_INDEX (QCdpi), font_prop_validate_non_neg },
659 { SYMBOL_INDEX (QCspacing), font_prop_validate_spacing },
660 { SYMBOL_INDEX (QCavgwidth), font_prop_validate_non_neg },
661 /* The order of the above entries must match with enum
662 font_property_index. */
663 { SYMBOL_INDEX (QClang), font_prop_validate_symbol },
664 { SYMBOL_INDEX (QCscript), font_prop_validate_symbol },
665 { SYMBOL_INDEX (QCotf), font_prop_validate_otf }
666 };
667
668 /* Return an index number of font property KEY or -1 if KEY is not an
669 already known property. */
670
671 static int
672 get_font_prop_index (Lisp_Object key)
673 {
674 int i;
675
676 for (i = 0; i < ARRAYELTS (font_property_table); i++)
677 if (EQ (key, builtin_lisp_symbol (font_property_table[i].key)))
678 return i;
679 return -1;
680 }
681
682 /* Validate the font property. The property key is specified by the
683 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
684 signal an error. The value is VAL or the regularized one. */
685
686 static Lisp_Object
687 font_prop_validate (int idx, Lisp_Object prop, Lisp_Object val)
688 {
689 Lisp_Object validated;
690
691 if (NILP (val))
692 return val;
693 if (NILP (prop))
694 prop = builtin_lisp_symbol (font_property_table[idx].key);
695 else
696 {
697 idx = get_font_prop_index (prop);
698 if (idx < 0)
699 return val;
700 }
701 validated = (font_property_table[idx].validator) (prop, val);
702 if (EQ (validated, Qerror))
703 signal_error ("invalid font property", Fcons (prop, val));
704 return validated;
705 }
706
707
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. */
710
711 Lisp_Object
712 font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
713 {
714 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
715 Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
716
717 if (NILP (slot))
718 {
719 Lisp_Object prev = Qnil;
720
721 while (CONSP (extra)
722 && NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
723 prev = extra, extra = XCDR (extra);
724
725 if (NILP (prev))
726 ASET (font, FONT_EXTRA_INDEX, Fcons (Fcons (prop, val), extra));
727 else
728 XSETCDR (prev, Fcons (Fcons (prop, val), extra));
729
730 return val;
731 }
732 XSETCDR (slot, val);
733 if (NILP (val))
734 ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra));
735 return val;
736 }
737
738 \f
739 /* Font name parser and unparser. */
740
741 static int parse_matrix (const char *);
742 static int font_expand_wildcards (Lisp_Object *, int);
743 static int font_parse_name (char *, ptrdiff_t, Lisp_Object);
744
745 /* An enumerator for each field of an XLFD font name. */
746 enum xlfd_field_index
747 {
748 XLFD_FOUNDRY_INDEX,
749 XLFD_FAMILY_INDEX,
750 XLFD_WEIGHT_INDEX,
751 XLFD_SLANT_INDEX,
752 XLFD_SWIDTH_INDEX,
753 XLFD_ADSTYLE_INDEX,
754 XLFD_PIXEL_INDEX,
755 XLFD_POINT_INDEX,
756 XLFD_RESX_INDEX,
757 XLFD_RESY_INDEX,
758 XLFD_SPACING_INDEX,
759 XLFD_AVGWIDTH_INDEX,
760 XLFD_REGISTRY_INDEX,
761 XLFD_ENCODING_INDEX,
762 XLFD_LAST_INDEX
763 };
764
765 /* An enumerator for mask bit corresponding to each XLFD field. */
766 enum xlfd_field_mask
767 {
768 XLFD_FOUNDRY_MASK = 0x0001,
769 XLFD_FAMILY_MASK = 0x0002,
770 XLFD_WEIGHT_MASK = 0x0004,
771 XLFD_SLANT_MASK = 0x0008,
772 XLFD_SWIDTH_MASK = 0x0010,
773 XLFD_ADSTYLE_MASK = 0x0020,
774 XLFD_PIXEL_MASK = 0x0040,
775 XLFD_POINT_MASK = 0x0080,
776 XLFD_RESX_MASK = 0x0100,
777 XLFD_RESY_MASK = 0x0200,
778 XLFD_SPACING_MASK = 0x0400,
779 XLFD_AVGWIDTH_MASK = 0x0800,
780 XLFD_REGISTRY_MASK = 0x1000,
781 XLFD_ENCODING_MASK = 0x2000
782 };
783
784
785 /* Parse P pointing to the pixel/point size field of the form
786 `[A B C D]' which specifies a transformation matrix:
787
788 A B 0
789 C D 0
790 0 0 1
791
792 by which all glyphs of the font are transformed. The spec says
793 that scalar value N for the pixel/point size is equivalent to:
794 A = N * resx/resy, B = C = 0, D = N.
795
796 Return the scalar value N if the form is valid. Otherwise return
797 -1. */
798
799 static int
800 parse_matrix (const char *p)
801 {
802 double matrix[4];
803 char *end;
804 int i;
805
806 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
807 {
808 if (*p == '~')
809 matrix[i] = - strtod (p + 1, &end);
810 else
811 matrix[i] = strtod (p, &end);
812 p = end;
813 }
814 return (i == 4 ? (int) matrix[3] : -1);
815 }
816
817 /* Expand a wildcard field in FIELD (the first N fields are filled) to
818 multiple fields to fill in all 14 XLFD fields while restricting a
819 field position by its contents. */
820
821 static int
822 font_expand_wildcards (Lisp_Object *field, int n)
823 {
824 /* Copy of FIELD. */
825 Lisp_Object tmp[XLFD_LAST_INDEX];
826 /* Array of information about where this element can go. Nth
827 element is for Nth element of FIELD. */
828 struct {
829 /* Minimum possible field. */
830 int from;
831 /* Maximum possible field. */
832 int to;
833 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
834 int mask;
835 } range[XLFD_LAST_INDEX];
836 int i, j;
837 int range_from, range_to;
838 unsigned range_mask;
839
840 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
841 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
842 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
843 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
844 | XLFD_AVGWIDTH_MASK)
845 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
846
847 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
848 field. The value is shifted to left one bit by one in the
849 following loop. */
850 for (i = 0, range_mask = 0; i <= 14 - n; i++)
851 range_mask = (range_mask << 1) | 1;
852
853 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
854 position-based restriction for FIELD[I]. */
855 for (i = 0, range_from = 0, range_to = 14 - n; i < n;
856 i++, range_from++, range_to++, range_mask <<= 1)
857 {
858 Lisp_Object val = field[i];
859
860 tmp[i] = val;
861 if (NILP (val))
862 {
863 /* Wildcard. */
864 range[i].from = range_from;
865 range[i].to = range_to;
866 range[i].mask = range_mask;
867 }
868 else
869 {
870 /* The triplet FROM, TO, and MASK is a value-based
871 restriction for FIELD[I]. */
872 int from, to;
873 unsigned mask;
874
875 if (INTEGERP (val))
876 {
877 EMACS_INT numeric = XINT (val);
878
879 if (i + 1 == n)
880 from = to = XLFD_ENCODING_INDEX,
881 mask = XLFD_ENCODING_MASK;
882 else if (numeric == 0)
883 from = XLFD_PIXEL_INDEX, to = XLFD_AVGWIDTH_INDEX,
884 mask = XLFD_PIXEL_MASK | XLFD_LARGENUM_MASK;
885 else if (numeric <= 48)
886 from = to = XLFD_PIXEL_INDEX,
887 mask = XLFD_PIXEL_MASK;
888 else
889 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
890 mask = XLFD_LARGENUM_MASK;
891 }
892 else if (SBYTES (SYMBOL_NAME (val)) == 0)
893 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
894 mask = XLFD_NULL_MASK;
895 else if (i == 0)
896 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
897 else if (i + 1 == n)
898 {
899 Lisp_Object name = SYMBOL_NAME (val);
900
901 if (SDATA (name)[SBYTES (name) - 1] == '*')
902 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
903 mask = XLFD_REGENC_MASK;
904 else
905 from = to = XLFD_ENCODING_INDEX,
906 mask = XLFD_ENCODING_MASK;
907 }
908 else if (range_from <= XLFD_WEIGHT_INDEX
909 && range_to >= XLFD_WEIGHT_INDEX
910 && FONT_WEIGHT_NAME_NUMERIC (val) >= 0)
911 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
912 else if (range_from <= XLFD_SLANT_INDEX
913 && range_to >= XLFD_SLANT_INDEX
914 && FONT_SLANT_NAME_NUMERIC (val) >= 0)
915 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
916 else if (range_from <= XLFD_SWIDTH_INDEX
917 && range_to >= XLFD_SWIDTH_INDEX
918 && FONT_WIDTH_NAME_NUMERIC (val) >= 0)
919 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
920 else
921 {
922 if (EQ (val, Qc) || EQ (val, Qm) || EQ (val, Qp) || EQ (val, Qd))
923 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
924 else
925 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
926 mask = XLFD_SYMBOL_MASK;
927 }
928
929 /* Merge position-based and value-based restrictions. */
930 mask &= range_mask;
931 while (from < range_from)
932 mask &= ~(1 << from++);
933 while (from < 14 && ! (mask & (1 << from)))
934 from++;
935 while (to > range_to)
936 mask &= ~(1 << to--);
937 while (to >= 0 && ! (mask & (1 << to)))
938 to--;
939 if (from > to)
940 return -1;
941 range[i].from = from;
942 range[i].to = to;
943 range[i].mask = mask;
944
945 if (from > range_from || to < range_to)
946 {
947 /* The range is narrowed by value-based restrictions.
948 Reflect it to the other fields. */
949
950 /* Following fields should be after FROM. */
951 range_from = from;
952 /* Preceding fields should be before TO. */
953 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
954 {
955 /* Check FROM for non-wildcard field. */
956 if (! NILP (tmp[j]) && range[j].from < from)
957 {
958 while (range[j].from < from)
959 range[j].mask &= ~(1 << range[j].from++);
960 while (from < 14 && ! (range[j].mask & (1 << from)))
961 from++;
962 range[j].from = from;
963 }
964 else
965 from = range[j].from;
966 if (range[j].to > to)
967 {
968 while (range[j].to > to)
969 range[j].mask &= ~(1 << range[j].to--);
970 while (to >= 0 && ! (range[j].mask & (1 << to)))
971 to--;
972 range[j].to = to;
973 }
974 else
975 to = range[j].to;
976 if (from > to)
977 return -1;
978 }
979 }
980 }
981 }
982
983 /* Decide all fields from restrictions in RANGE. */
984 for (i = j = 0; i < n ; i++)
985 {
986 if (j < range[i].from)
987 {
988 if (i == 0 || ! NILP (tmp[i - 1]))
989 /* None of TMP[X] corresponds to Jth field. */
990 return -1;
991 memclear (field + j, (range[i].from - j) * word_size);
992 j = range[i].from;
993 }
994 field[j++] = tmp[i];
995 }
996 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
997 return -1;
998 memclear (field + j, (XLFD_LAST_INDEX - j) * word_size);
999 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
1000 field[XLFD_ENCODING_INDEX]
1001 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
1002 return 0;
1003 }
1004
1005
1006 /* Parse NAME (null terminated) as XLFD and store information in FONT
1007 (font-spec or font-entity). Size property of FONT is set as
1008 follows:
1009 specified XLFD fields FONT property
1010 --------------------- -------------
1011 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
1012 POINT_SIZE and RESY calculated pixel size (Lisp integer)
1013 POINT_SIZE POINT_SIZE/10 (Lisp float)
1014
1015 If NAME is successfully parsed, return 0. Otherwise return -1.
1016
1017 FONT is usually a font-spec, but when this function is called from
1018 X font backend driver, it is a font-entity. In that case, NAME is
1019 a fully specified XLFD. */
1020
1021 int
1022 font_parse_xlfd (char *name, ptrdiff_t len, Lisp_Object font)
1023 {
1024 int i, j, n;
1025 char *f[XLFD_LAST_INDEX + 1];
1026 Lisp_Object val;
1027 char *p;
1028
1029 if (len > 255 || !len)
1030 /* Maximum XLFD name length is 255. */
1031 return -1;
1032 /* Accept "*-.." as a fully specified XLFD. */
1033 if (name[0] == '*' && (len == 1 || name[1] == '-'))
1034 i = 1, f[XLFD_FOUNDRY_INDEX] = name;
1035 else
1036 i = 0;
1037 for (p = name + i; *p; p++)
1038 if (*p == '-')
1039 {
1040 f[i++] = p + 1;
1041 if (i == XLFD_LAST_INDEX)
1042 break;
1043 }
1044 f[i] = name + len;
1045
1046 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1047 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1048
1049 if (i == XLFD_LAST_INDEX)
1050 {
1051 /* Fully specified XLFD. */
1052 int pixel_size;
1053
1054 ASET (font, FONT_FOUNDRY_INDEX, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX));
1055 ASET (font, FONT_FAMILY_INDEX, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX));
1056 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1057 i <= XLFD_SWIDTH_INDEX; i++, j++)
1058 {
1059 val = INTERN_FIELD_SYM (i);
1060 if (! NILP (val))
1061 {
1062 if ((n = font_style_to_value (j, INTERN_FIELD_SYM (i), 0)) < 0)
1063 return -1;
1064 ASET (font, j, make_number (n));
1065 }
1066 }
1067 ASET (font, FONT_ADSTYLE_INDEX, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX));
1068 if (strcmp (f[XLFD_REGISTRY_INDEX], "*-*") == 0)
1069 ASET (font, FONT_REGISTRY_INDEX, Qnil);
1070 else
1071 ASET (font, FONT_REGISTRY_INDEX,
1072 font_intern_prop (f[XLFD_REGISTRY_INDEX],
1073 f[XLFD_LAST_INDEX] - f[XLFD_REGISTRY_INDEX],
1074 1));
1075 p = f[XLFD_PIXEL_INDEX];
1076 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
1077 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
1078 else
1079 {
1080 val = INTERN_FIELD (XLFD_PIXEL_INDEX);
1081 if (INTEGERP (val))
1082 ASET (font, FONT_SIZE_INDEX, val);
1083 else if (FONT_ENTITY_P (font))
1084 return -1;
1085 else
1086 {
1087 double point_size = -1;
1088
1089 eassert (FONT_SPEC_P (font));
1090 p = f[XLFD_POINT_INDEX];
1091 if (*p == '[')
1092 point_size = parse_matrix (p);
1093 else if (c_isdigit (*p))
1094 point_size = atoi (p), point_size /= 10;
1095 if (point_size >= 0)
1096 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1097 }
1098 }
1099
1100 val = INTERN_FIELD (XLFD_RESY_INDEX);
1101 if (! NILP (val) && ! INTEGERP (val))
1102 return -1;
1103 ASET (font, FONT_DPI_INDEX, val);
1104 val = INTERN_FIELD (XLFD_SPACING_INDEX);
1105 if (! NILP (val))
1106 {
1107 val = font_prop_validate_spacing (QCspacing, val);
1108 if (! INTEGERP (val))
1109 return -1;
1110 ASET (font, FONT_SPACING_INDEX, val);
1111 }
1112 p = f[XLFD_AVGWIDTH_INDEX];
1113 if (*p == '~')
1114 p++;
1115 val = font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p, 0);
1116 if (! NILP (val) && ! INTEGERP (val))
1117 return -1;
1118 ASET (font, FONT_AVGWIDTH_INDEX, val);
1119 }
1120 else
1121 {
1122 bool wild_card_found = 0;
1123 Lisp_Object prop[XLFD_LAST_INDEX];
1124
1125 if (FONT_ENTITY_P (font))
1126 return -1;
1127 for (j = 0; j < i; j++)
1128 {
1129 if (*f[j] == '*')
1130 {
1131 if (f[j][1] && f[j][1] != '-')
1132 return -1;
1133 prop[j] = Qnil;
1134 wild_card_found = 1;
1135 }
1136 else if (j + 1 < i)
1137 prop[j] = INTERN_FIELD (j);
1138 else
1139 prop[j] = font_intern_prop (f[j], f[i] - f[j], 0);
1140 }
1141 if (! wild_card_found)
1142 return -1;
1143 if (font_expand_wildcards (prop, i) < 0)
1144 return -1;
1145
1146 ASET (font, FONT_FOUNDRY_INDEX, prop[XLFD_FOUNDRY_INDEX]);
1147 ASET (font, FONT_FAMILY_INDEX, prop[XLFD_FAMILY_INDEX]);
1148 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1149 i <= XLFD_SWIDTH_INDEX; i++, j++)
1150 if (! NILP (prop[i]))
1151 {
1152 if ((n = font_style_to_value (j, prop[i], 1)) < 0)
1153 return -1;
1154 ASET (font, j, make_number (n));
1155 }
1156 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1157 val = prop[XLFD_REGISTRY_INDEX];
1158 if (NILP (val))
1159 {
1160 val = prop[XLFD_ENCODING_INDEX];
1161 if (! NILP (val))
1162 {
1163 AUTO_STRING (star_dash, "*-");
1164 val = concat2 (star_dash, SYMBOL_NAME (val));
1165 }
1166 }
1167 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1168 {
1169 AUTO_STRING (dash_star, "-*");
1170 val = concat2 (SYMBOL_NAME (val), dash_star);
1171 }
1172 else
1173 {
1174 AUTO_STRING (dash, "-");
1175 val = concat3 (SYMBOL_NAME (val), dash,
1176 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX]));
1177 }
1178 if (! NILP (val))
1179 ASET (font, FONT_REGISTRY_INDEX, Fintern (val, Qnil));
1180
1181 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1182 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
1183 else if (INTEGERP (prop[XLFD_POINT_INDEX]))
1184 {
1185 double point_size = XINT (prop[XLFD_POINT_INDEX]);
1186
1187 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1188 }
1189
1190 if (INTEGERP (prop[XLFD_RESX_INDEX]))
1191 ASET (font, FONT_DPI_INDEX, prop[XLFD_RESY_INDEX]);
1192 if (! NILP (prop[XLFD_SPACING_INDEX]))
1193 {
1194 val = font_prop_validate_spacing (QCspacing,
1195 prop[XLFD_SPACING_INDEX]);
1196 if (! INTEGERP (val))
1197 return -1;
1198 ASET (font, FONT_SPACING_INDEX, val);
1199 }
1200 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1201 ASET (font, FONT_AVGWIDTH_INDEX, prop[XLFD_AVGWIDTH_INDEX]);
1202 }
1203
1204 return 0;
1205 }
1206
1207 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1208 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1209 0, use PIXEL_SIZE instead. */
1210
1211 ptrdiff_t
1212 font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
1213 {
1214 char *p;
1215 const char *f[XLFD_REGISTRY_INDEX + 1];
1216 Lisp_Object val;
1217 int i, j, len;
1218
1219 eassert (FONTP (font));
1220
1221 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
1222 i++, j++)
1223 {
1224 if (i == FONT_ADSTYLE_INDEX)
1225 j = XLFD_ADSTYLE_INDEX;
1226 else if (i == FONT_REGISTRY_INDEX)
1227 j = XLFD_REGISTRY_INDEX;
1228 val = AREF (font, i);
1229 if (NILP (val))
1230 {
1231 if (j == XLFD_REGISTRY_INDEX)
1232 f[j] = "*-*";
1233 else
1234 f[j] = "*";
1235 }
1236 else
1237 {
1238 if (SYMBOLP (val))
1239 val = SYMBOL_NAME (val);
1240 if (j == XLFD_REGISTRY_INDEX
1241 && ! strchr (SSDATA (val), '-'))
1242 {
1243 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1244 ptrdiff_t alloc = SBYTES (val) + 4;
1245 if (nbytes <= alloc)
1246 return -1;
1247 f[j] = p = alloca (alloc);
1248 sprintf (p, "%s%s-*", SDATA (val),
1249 &"*"[SDATA (val)[SBYTES (val) - 1] == '*']);
1250 }
1251 else
1252 f[j] = SSDATA (val);
1253 }
1254 }
1255
1256 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1257 i++, j++)
1258 {
1259 val = font_style_symbolic (font, i, 0);
1260 if (NILP (val))
1261 f[j] = "*";
1262 else
1263 {
1264 int c, k, l;
1265 ptrdiff_t alloc;
1266
1267 val = SYMBOL_NAME (val);
1268 alloc = SBYTES (val) + 1;
1269 if (nbytes <= alloc)
1270 return -1;
1271 f[j] = p = alloca (alloc);
1272 /* Copy the name while excluding '-', '?', ',', and '"'. */
1273 for (k = l = 0; k < alloc; k++)
1274 {
1275 c = SREF (val, k);
1276 if (c != '-' && c != '?' && c != ',' && c != '"')
1277 p[l++] = c;
1278 }
1279 }
1280 }
1281
1282 val = AREF (font, FONT_SIZE_INDEX);
1283 eassert (NUMBERP (val) || NILP (val));
1284 char font_size_index_buf[sizeof "-*"
1285 + max (INT_STRLEN_BOUND (EMACS_INT),
1286 1 + DBL_MAX_10_EXP + 1)];
1287 if (INTEGERP (val))
1288 {
1289 EMACS_INT v = XINT (val);
1290 if (v <= 0)
1291 v = pixel_size;
1292 if (v > 0)
1293 {
1294 f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
1295 sprintf (p, "%"pI"d-*", v);
1296 }
1297 else
1298 f[XLFD_PIXEL_INDEX] = "*-*";
1299 }
1300 else if (FLOATP (val))
1301 {
1302 double v = XFLOAT_DATA (val) * 10;
1303 f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
1304 sprintf (p, "*-%.0f", v);
1305 }
1306 else
1307 f[XLFD_PIXEL_INDEX] = "*-*";
1308
1309 char dpi_index_buf[sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT)];
1310 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1311 {
1312 EMACS_INT v = XINT (AREF (font, FONT_DPI_INDEX));
1313 f[XLFD_RESX_INDEX] = p = dpi_index_buf;
1314 sprintf (p, "%"pI"d-%"pI"d", v, v);
1315 }
1316 else
1317 f[XLFD_RESX_INDEX] = "*-*";
1318
1319 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1320 {
1321 EMACS_INT spacing = XINT (AREF (font, FONT_SPACING_INDEX));
1322
1323 f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
1324 : spacing <= FONT_SPACING_DUAL ? "d"
1325 : spacing <= FONT_SPACING_MONO ? "m"
1326 : "c");
1327 }
1328 else
1329 f[XLFD_SPACING_INDEX] = "*";
1330
1331 char avgwidth_index_buf[INT_BUFSIZE_BOUND (EMACS_INT)];
1332 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1333 {
1334 f[XLFD_AVGWIDTH_INDEX] = p = avgwidth_index_buf;
1335 sprintf (p, "%"pI"d", XINT (AREF (font, FONT_AVGWIDTH_INDEX)));
1336 }
1337 else
1338 f[XLFD_AVGWIDTH_INDEX] = "*";
1339
1340 len = snprintf (name, nbytes, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1341 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1342 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1343 f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
1344 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
1345 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
1346 f[XLFD_REGISTRY_INDEX]);
1347 return len < nbytes ? len : -1;
1348 }
1349
1350 /* Parse NAME (null terminated) and store information in FONT
1351 (font-spec or font-entity). NAME is supplied in either the
1352 Fontconfig or GTK font name format. If NAME is successfully
1353 parsed, return 0. Otherwise return -1.
1354
1355 The fontconfig format is
1356
1357 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1358
1359 The GTK format is
1360
1361 FAMILY [PROPS...] [SIZE]
1362
1363 This function tries to guess which format it is. */
1364
1365 static int
1366 font_parse_fcname (char *name, ptrdiff_t len, Lisp_Object font)
1367 {
1368 char *p, *q;
1369 char *size_beg = NULL, *size_end = NULL;
1370 char *props_beg = NULL, *family_end = NULL;
1371
1372 if (len == 0)
1373 return -1;
1374
1375 for (p = name; *p; p++)
1376 {
1377 if (*p == '\\' && p[1])
1378 p++;
1379 else if (*p == ':')
1380 {
1381 props_beg = family_end = p;
1382 break;
1383 }
1384 else if (*p == '-')
1385 {
1386 bool decimal = 0, size_found = 1;
1387 for (q = p + 1; *q && *q != ':'; q++)
1388 if (! c_isdigit (*q))
1389 {
1390 if (*q != '.' || decimal)
1391 {
1392 size_found = 0;
1393 break;
1394 }
1395 decimal = 1;
1396 }
1397 if (size_found)
1398 {
1399 family_end = p;
1400 size_beg = p + 1;
1401 size_end = q;
1402 break;
1403 }
1404 }
1405 }
1406
1407 if (family_end)
1408 {
1409 Lisp_Object extra_props = Qnil;
1410
1411 /* A fontconfig name with size and/or property data. */
1412 if (family_end > name)
1413 {
1414 Lisp_Object family;
1415 family = font_intern_prop (name, family_end - name, 1);
1416 ASET (font, FONT_FAMILY_INDEX, family);
1417 }
1418 if (size_beg)
1419 {
1420 double point_size = strtod (size_beg, &size_end);
1421 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1422 if (*size_end == ':' && size_end[1])
1423 props_beg = size_end;
1424 }
1425 if (props_beg)
1426 {
1427 /* Now parse ":KEY=VAL" patterns. */
1428 Lisp_Object val;
1429
1430 for (p = props_beg; *p; p = q)
1431 {
1432 for (q = p + 1; *q && *q != '=' && *q != ':'; q++);
1433 if (*q != '=')
1434 {
1435 /* Must be an enumerated value. */
1436 ptrdiff_t word_len;
1437 p = p + 1;
1438 word_len = q - p;
1439 val = font_intern_prop (p, q - p, 1);
1440
1441 #define PROP_MATCH(STR) (word_len == strlen (STR) \
1442 && memcmp (p, STR, strlen (STR)) == 0)
1443
1444 if (PROP_MATCH ("light")
1445 || PROP_MATCH ("medium")
1446 || PROP_MATCH ("demibold")
1447 || PROP_MATCH ("bold")
1448 || PROP_MATCH ("black"))
1449 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
1450 else if (PROP_MATCH ("roman")
1451 || PROP_MATCH ("italic")
1452 || PROP_MATCH ("oblique"))
1453 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
1454 else if (PROP_MATCH ("charcell"))
1455 ASET (font, FONT_SPACING_INDEX,
1456 make_number (FONT_SPACING_CHARCELL));
1457 else if (PROP_MATCH ("mono"))
1458 ASET (font, FONT_SPACING_INDEX,
1459 make_number (FONT_SPACING_MONO));
1460 else if (PROP_MATCH ("proportional"))
1461 ASET (font, FONT_SPACING_INDEX,
1462 make_number (FONT_SPACING_PROPORTIONAL));
1463 #undef PROP_MATCH
1464 }
1465 else
1466 {
1467 /* KEY=VAL pairs */
1468 Lisp_Object key;
1469 int prop;
1470
1471 if (q - p == 10 && memcmp (p + 1, "pixelsize", 9) == 0)
1472 prop = FONT_SIZE_INDEX;
1473 else
1474 {
1475 key = font_intern_prop (p, q - p, 1);
1476 prop = get_font_prop_index (key);
1477 }
1478
1479 p = q + 1;
1480 for (q = p; *q && *q != ':'; q++);
1481 val = font_intern_prop (p, q - p, 0);
1482
1483 if (prop >= FONT_FOUNDRY_INDEX
1484 && prop < FONT_EXTRA_INDEX)
1485 ASET (font, prop, font_prop_validate (prop, Qnil, val));
1486 else
1487 {
1488 extra_props = nconc2 (extra_props,
1489 list1 (Fcons (key, val)));
1490 }
1491 }
1492 p = q;
1493 }
1494 }
1495
1496 if (! NILP (extra_props))
1497 {
1498 struct font_driver_list *driver_list = font_driver_list;
1499 for ( ; driver_list; driver_list = driver_list->next)
1500 if (driver_list->driver->filter_properties)
1501 (*driver_list->driver->filter_properties) (font, extra_props);
1502 }
1503
1504 }
1505 else
1506 {
1507 /* Either a fontconfig-style name with no size and property
1508 data, or a GTK-style name. */
1509 Lisp_Object weight = Qnil, slant = Qnil;
1510 Lisp_Object width = Qnil, size = Qnil;
1511 char *word_start;
1512 ptrdiff_t word_len;
1513
1514 /* Scan backwards from the end, looking for a size. */
1515 for (p = name + len - 1; p >= name; p--)
1516 if (!c_isdigit (*p))
1517 break;
1518
1519 if ((p < name + len - 1) && ((p + 1 == name) || *p == ' '))
1520 /* Found a font size. */
1521 size = make_float (strtod (p + 1, NULL));
1522 else
1523 p = name + len;
1524
1525 /* Now P points to the termination of the string, sans size.
1526 Scan backwards, looking for font properties. */
1527 for (; p > name; p = q)
1528 {
1529 for (q = p - 1; q >= name; q--)
1530 {
1531 if (q > name && *(q-1) == '\\')
1532 --q; /* Skip quoting backslashes. */
1533 else if (*q == ' ')
1534 break;
1535 }
1536
1537 word_start = q + 1;
1538 word_len = p - word_start;
1539
1540 #define PROP_MATCH(STR) \
1541 (word_len == strlen (STR) \
1542 && memcmp (word_start, STR, strlen (STR)) == 0)
1543 #define PROP_SAVE(VAR, STR) \
1544 (VAR = NILP (VAR) ? font_intern_prop (STR, strlen (STR), 1) : VAR)
1545
1546 if (PROP_MATCH ("Ultra-Light"))
1547 PROP_SAVE (weight, "ultra-light");
1548 else if (PROP_MATCH ("Light"))
1549 PROP_SAVE (weight, "light");
1550 else if (PROP_MATCH ("Book"))
1551 PROP_SAVE (weight, "book");
1552 else if (PROP_MATCH ("Medium"))
1553 PROP_SAVE (weight, "medium");
1554 else if (PROP_MATCH ("Semi-Bold"))
1555 PROP_SAVE (weight, "semi-bold");
1556 else if (PROP_MATCH ("Bold"))
1557 PROP_SAVE (weight, "bold");
1558 else if (PROP_MATCH ("Italic"))
1559 PROP_SAVE (slant, "italic");
1560 else if (PROP_MATCH ("Oblique"))
1561 PROP_SAVE (slant, "oblique");
1562 else if (PROP_MATCH ("Semi-Condensed"))
1563 PROP_SAVE (width, "semi-condensed");
1564 else if (PROP_MATCH ("Condensed"))
1565 PROP_SAVE (width, "condensed");
1566 /* An unknown word must be part of the font name. */
1567 else
1568 {
1569 family_end = p;
1570 break;
1571 }
1572 }
1573 #undef PROP_MATCH
1574 #undef PROP_SAVE
1575
1576 if (family_end)
1577 ASET (font, FONT_FAMILY_INDEX,
1578 font_intern_prop (name, family_end - name, 1));
1579 if (!NILP (size))
1580 ASET (font, FONT_SIZE_INDEX, size);
1581 if (!NILP (weight))
1582 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, weight);
1583 if (!NILP (slant))
1584 FONT_SET_STYLE (font, FONT_SLANT_INDEX, slant);
1585 if (!NILP (width))
1586 FONT_SET_STYLE (font, FONT_WIDTH_INDEX, width);
1587 }
1588
1589 return 0;
1590 }
1591
1592 #if defined HAVE_XFT || defined HAVE_FREETYPE || defined HAVE_NS
1593
1594 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1595 NAME (NBYTES length), and return the name length. If
1596 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead.
1597 Return a negative value on error. */
1598
1599 static int
1600 font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes)
1601 {
1602 Lisp_Object family, foundry;
1603 Lisp_Object val;
1604 int point_size;
1605 int i;
1606 char *p;
1607 char *lim;
1608 Lisp_Object styles[3];
1609 const char *style_names[3] = { "weight", "slant", "width" };
1610
1611 family = AREF (font, FONT_FAMILY_INDEX);
1612 if (! NILP (family))
1613 {
1614 if (SYMBOLP (family))
1615 family = SYMBOL_NAME (family);
1616 else
1617 family = Qnil;
1618 }
1619
1620 val = AREF (font, FONT_SIZE_INDEX);
1621 if (INTEGERP (val))
1622 {
1623 if (XINT (val) != 0)
1624 pixel_size = XINT (val);
1625 point_size = -1;
1626 }
1627 else
1628 {
1629 eassert (FLOATP (val));
1630 pixel_size = -1;
1631 point_size = (int) XFLOAT_DATA (val);
1632 }
1633
1634 foundry = AREF (font, FONT_FOUNDRY_INDEX);
1635 if (! NILP (foundry))
1636 {
1637 if (SYMBOLP (foundry))
1638 foundry = SYMBOL_NAME (foundry);
1639 else
1640 foundry = Qnil;
1641 }
1642
1643 for (i = 0; i < 3; i++)
1644 styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
1645
1646 p = name;
1647 lim = name + nbytes;
1648 if (! NILP (family))
1649 {
1650 int len = snprintf (p, lim - p, "%s", SSDATA (family));
1651 if (! (0 <= len && len < lim - p))
1652 return -1;
1653 p += len;
1654 }
1655 if (point_size > 0)
1656 {
1657 int len = snprintf (p, lim - p, &"-%d"[p == name], point_size);
1658 if (! (0 <= len && len < lim - p))
1659 return -1;
1660 p += len;
1661 }
1662 else if (pixel_size > 0)
1663 {
1664 int len = snprintf (p, lim - p, ":pixelsize=%d", pixel_size);
1665 if (! (0 <= len && len < lim - p))
1666 return -1;
1667 p += len;
1668 }
1669 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1670 {
1671 int len = snprintf (p, lim - p, ":foundry=%s",
1672 SSDATA (SYMBOL_NAME (AREF (font,
1673 FONT_FOUNDRY_INDEX))));
1674 if (! (0 <= len && len < lim - p))
1675 return -1;
1676 p += len;
1677 }
1678 for (i = 0; i < 3; i++)
1679 if (! NILP (styles[i]))
1680 {
1681 int len = snprintf (p, lim - p, ":%s=%s", style_names[i],
1682 SSDATA (SYMBOL_NAME (styles[i])));
1683 if (! (0 <= len && len < lim - p))
1684 return -1;
1685 p += len;
1686 }
1687
1688 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1689 {
1690 int len = snprintf (p, lim - p, ":dpi=%"pI"d",
1691 XINT (AREF (font, FONT_DPI_INDEX)));
1692 if (! (0 <= len && len < lim - p))
1693 return -1;
1694 p += len;
1695 }
1696
1697 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1698 {
1699 int len = snprintf (p, lim - p, ":spacing=%"pI"d",
1700 XINT (AREF (font, FONT_SPACING_INDEX)));
1701 if (! (0 <= len && len < lim - p))
1702 return -1;
1703 p += len;
1704 }
1705
1706 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1707 {
1708 int len = snprintf (p, lim - p,
1709 (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0
1710 ? ":scalable=true"
1711 : ":scalable=false"));
1712 if (! (0 <= len && len < lim - p))
1713 return -1;
1714 p += len;
1715 }
1716
1717 return (p - name);
1718 }
1719
1720 #endif
1721
1722 /* Parse NAME (null terminated) and store information in FONT
1723 (font-spec or font-entity). If NAME is successfully parsed, return
1724 0. Otherwise return -1. */
1725
1726 static int
1727 font_parse_name (char *name, ptrdiff_t namelen, Lisp_Object font)
1728 {
1729 if (name[0] == '-' || strchr (name, '*') || strchr (name, '?'))
1730 return font_parse_xlfd (name, namelen, font);
1731 return font_parse_fcname (name, namelen, font);
1732 }
1733
1734
1735 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1736 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1737 part. */
1738
1739 void
1740 font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Object font_spec)
1741 {
1742 ptrdiff_t len;
1743 char *p0, *p1;
1744
1745 if (! NILP (family)
1746 && NILP (AREF (font_spec, FONT_FAMILY_INDEX)))
1747 {
1748 CHECK_STRING (family);
1749 len = SBYTES (family);
1750 p0 = SSDATA (family);
1751 p1 = strchr (p0, '-');
1752 if (p1)
1753 {
1754 if ((*p0 != '*' && p1 - p0 > 0)
1755 && NILP (AREF (font_spec, FONT_FOUNDRY_INDEX)))
1756 Ffont_put (font_spec, QCfoundry, font_intern_prop (p0, p1 - p0, 1));
1757 p1++;
1758 len -= p1 - p0;
1759 Ffont_put (font_spec, QCfamily, font_intern_prop (p1, len, 1));
1760 }
1761 else
1762 ASET (font_spec, FONT_FAMILY_INDEX, Fintern (family, Qnil));
1763 }
1764 if (! NILP (registry))
1765 {
1766 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1767 CHECK_STRING (registry);
1768 len = SBYTES (registry);
1769 p0 = SSDATA (registry);
1770 p1 = strchr (p0, '-');
1771 if (! p1)
1772 {
1773 AUTO_STRING (extra, (&"*-*"[len && p0[len - 1] == '*']));
1774 registry = concat2 (registry, extra);
1775 }
1776 registry = Fdowncase (registry);
1777 ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil));
1778 }
1779 }
1780
1781 \f
1782 /* This part (through the next ^L) is still experimental and not
1783 tested much. We may drastically change codes. */
1784
1785 /* OTF handler. */
1786
1787 #if 0
1788
1789 #define LGSTRING_HEADER_SIZE 6
1790 #define LGSTRING_GLYPH_SIZE 8
1791
1792 static int
1793 check_gstring (Lisp_Object gstring)
1794 {
1795 Lisp_Object val;
1796 ptrdiff_t i;
1797 int j;
1798
1799 CHECK_VECTOR (gstring);
1800 val = AREF (gstring, 0);
1801 CHECK_VECTOR (val);
1802 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1803 goto err;
1804 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1805 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1806 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1807 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1808 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1809 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1810 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1811 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1812 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1813 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1814 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1815
1816 for (i = 0; i < LGSTRING_GLYPH_LEN (gstring); i++)
1817 {
1818 val = LGSTRING_GLYPH (gstring, i);
1819 CHECK_VECTOR (val);
1820 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1821 goto err;
1822 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1823 break;
1824 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1825 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1826 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1827 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1828 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1829 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1830 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1831 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1832 {
1833 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1834 CHECK_VECTOR (val);
1835 if (ASIZE (val) < 3)
1836 goto err;
1837 for (j = 0; j < 3; j++)
1838 CHECK_NUMBER (AREF (val, j));
1839 }
1840 }
1841 return i;
1842 err:
1843 error ("Invalid glyph-string format");
1844 return -1;
1845 }
1846
1847 static void
1848 check_otf_features (Lisp_Object otf_features)
1849 {
1850 Lisp_Object val;
1851
1852 CHECK_CONS (otf_features);
1853 CHECK_SYMBOL (XCAR (otf_features));
1854 otf_features = XCDR (otf_features);
1855 CHECK_CONS (otf_features);
1856 CHECK_SYMBOL (XCAR (otf_features));
1857 otf_features = XCDR (otf_features);
1858 for (val = Fcar (otf_features); CONSP (val); val = XCDR (val))
1859 {
1860 CHECK_SYMBOL (XCAR (val));
1861 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1862 error ("Invalid OTF GSUB feature: %s",
1863 SDATA (SYMBOL_NAME (XCAR (val))));
1864 }
1865 otf_features = XCDR (otf_features);
1866 for (val = Fcar (otf_features); CONSP (val); val = XCDR (val))
1867 {
1868 CHECK_SYMBOL (XCAR (val));
1869 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1870 error ("Invalid OTF GPOS feature: %s",
1871 SDATA (SYMBOL_NAME (XCAR (val))));
1872 }
1873 }
1874
1875 #ifdef HAVE_LIBOTF
1876 #include <otf.h>
1877
1878 Lisp_Object otf_list;
1879
1880 static Lisp_Object
1881 otf_tag_symbol (OTF_Tag tag)
1882 {
1883 char name[5];
1884
1885 OTF_tag_name (tag, name);
1886 return Fintern (make_unibyte_string (name, 4), Qnil);
1887 }
1888
1889 static OTF *
1890 otf_open (Lisp_Object file)
1891 {
1892 Lisp_Object val = Fassoc (file, otf_list);
1893 OTF *otf;
1894
1895 if (! NILP (val))
1896 otf = XSAVE_POINTER (XCDR (val), 0);
1897 else
1898 {
1899 otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL;
1900 val = make_save_ptr (otf);
1901 otf_list = Fcons (Fcons (file, val), otf_list);
1902 }
1903 return otf;
1904 }
1905
1906
1907 /* Return a list describing which scripts/languages FONT supports by
1908 which GSUB/GPOS features of OpenType tables. See the comment of
1909 (struct font_driver).otf_capability. */
1910
1911 Lisp_Object
1912 font_otf_capability (struct font *font)
1913 {
1914 OTF *otf;
1915 Lisp_Object capability = Fcons (Qnil, Qnil);
1916 int i;
1917
1918 otf = otf_open (font->props[FONT_FILE_INDEX]);
1919 if (! otf)
1920 return Qnil;
1921 for (i = 0; i < 2; i++)
1922 {
1923 OTF_GSUB_GPOS *gsub_gpos;
1924 Lisp_Object script_list = Qnil;
1925 int j;
1926
1927 if (OTF_get_features (otf, i == 0) < 0)
1928 continue;
1929 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1930 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1931 {
1932 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1933 Lisp_Object langsys_list = Qnil;
1934 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1935 int k;
1936
1937 for (k = script->LangSysCount; k >= 0; k--)
1938 {
1939 OTF_LangSys *langsys;
1940 Lisp_Object feature_list = Qnil;
1941 Lisp_Object langsys_tag;
1942 int l;
1943
1944 if (k == script->LangSysCount)
1945 {
1946 langsys = &script->DefaultLangSys;
1947 langsys_tag = Qnil;
1948 }
1949 else
1950 {
1951 langsys = script->LangSys + k;
1952 langsys_tag
1953 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
1954 }
1955 for (l = langsys->FeatureCount - 1; l >= 0; l--)
1956 {
1957 OTF_Feature *feature
1958 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
1959 Lisp_Object feature_tag
1960 = otf_tag_symbol (feature->FeatureTag);
1961
1962 feature_list = Fcons (feature_tag, feature_list);
1963 }
1964 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1965 langsys_list);
1966 }
1967 script_list = Fcons (Fcons (script_tag, langsys_list),
1968 script_list);
1969 }
1970
1971 if (i == 0)
1972 XSETCAR (capability, script_list);
1973 else
1974 XSETCDR (capability, script_list);
1975 }
1976
1977 return capability;
1978 }
1979
1980 /* Parse OTF features in SPEC and write a proper features spec string
1981 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1982 assured that the sufficient memory has already allocated for
1983 FEATURES. */
1984
1985 static void
1986 generate_otf_features (Lisp_Object spec, char *features)
1987 {
1988 Lisp_Object val;
1989 char *p;
1990 bool asterisk;
1991
1992 p = features;
1993 *p = '\0';
1994 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
1995 {
1996 val = XCAR (spec);
1997 CHECK_SYMBOL (val);
1998 if (p > features)
1999 *p++ = ',';
2000 if (SREF (SYMBOL_NAME (val), 0) == '*')
2001 {
2002 asterisk = 1;
2003 *p++ = '*';
2004 }
2005 else if (! asterisk)
2006 {
2007 val = SYMBOL_NAME (val);
2008 p += esprintf (p, "%s", SDATA (val));
2009 }
2010 else
2011 {
2012 val = SYMBOL_NAME (val);
2013 p += esprintf (p, "~%s", SDATA (val));
2014 }
2015 }
2016 if (CONSP (spec))
2017 error ("OTF spec too long");
2018 }
2019
2020 Lisp_Object
2021 font_otf_DeviceTable (OTF_DeviceTable *device_table)
2022 {
2023 int len = device_table->StartSize - device_table->EndSize + 1;
2024
2025 return Fcons (make_number (len),
2026 make_unibyte_string (device_table->DeltaValue, len));
2027 }
2028
2029 Lisp_Object
2030 font_otf_ValueRecord (int value_format, OTF_ValueRecord *value_record)
2031 {
2032 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
2033
2034 if (value_format & OTF_XPlacement)
2035 ASET (val, 0, make_number (value_record->XPlacement));
2036 if (value_format & OTF_YPlacement)
2037 ASET (val, 1, make_number (value_record->YPlacement));
2038 if (value_format & OTF_XAdvance)
2039 ASET (val, 2, make_number (value_record->XAdvance));
2040 if (value_format & OTF_YAdvance)
2041 ASET (val, 3, make_number (value_record->YAdvance));
2042 if (value_format & OTF_XPlaDevice)
2043 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
2044 if (value_format & OTF_YPlaDevice)
2045 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
2046 if (value_format & OTF_XAdvDevice)
2047 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
2048 if (value_format & OTF_YAdvDevice)
2049 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
2050 return val;
2051 }
2052
2053 Lisp_Object
2054 font_otf_Anchor (OTF_Anchor *anchor)
2055 {
2056 Lisp_Object val;
2057
2058 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
2059 ASET (val, 0, make_number (anchor->XCoordinate));
2060 ASET (val, 1, make_number (anchor->YCoordinate));
2061 if (anchor->AnchorFormat == 2)
2062 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
2063 else
2064 {
2065 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
2066 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
2067 }
2068 return val;
2069 }
2070 #endif /* HAVE_LIBOTF */
2071 #endif /* 0 */
2072
2073 \f
2074 /* Font sorting. */
2075
2076 static double
2077 font_rescale_ratio (Lisp_Object font_entity)
2078 {
2079 Lisp_Object tail, elt;
2080 Lisp_Object name = Qnil;
2081
2082 for (tail = Vface_font_rescale_alist; CONSP (tail); tail = XCDR (tail))
2083 {
2084 elt = XCAR (tail);
2085 if (FLOATP (XCDR (elt)))
2086 {
2087 if (STRINGP (XCAR (elt)))
2088 {
2089 if (NILP (name))
2090 name = Ffont_xlfd_name (font_entity, Qnil);
2091 if (fast_string_match_ignore_case (XCAR (elt), name) >= 0)
2092 return XFLOAT_DATA (XCDR (elt));
2093 }
2094 else if (FONT_SPEC_P (XCAR (elt)))
2095 {
2096 if (font_match_p (XCAR (elt), font_entity))
2097 return XFLOAT_DATA (XCDR (elt));
2098 }
2099 }
2100 }
2101 return 1.0;
2102 }
2103
2104 /* We sort fonts by scoring each of them against a specified
2105 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2106 the value is, the closer the font is to the font-spec.
2107
2108 The lowest 2 bits of the score are used for driver type. The font
2109 available by the most preferred font driver is 0.
2110
2111 The 4 7-bit fields in the higher 28 bits are used for numeric properties
2112 WEIGHT, SLANT, WIDTH, and SIZE. */
2113
2114 /* How many bits to shift to store the difference value of each font
2115 property in a score. Note that floats for FONT_TYPE_INDEX and
2116 FONT_REGISTRY_INDEX are not used. */
2117 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
2118
2119 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2120 The return value indicates how different ENTITY is compared with
2121 SPEC_PROP. */
2122
2123 static unsigned
2124 font_score (Lisp_Object entity, Lisp_Object *spec_prop)
2125 {
2126 unsigned score = 0;
2127 int i;
2128
2129 /* Score three style numeric fields. Maximum difference is 127. */
2130 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
2131 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
2132 {
2133 EMACS_INT diff = ((XINT (AREF (entity, i)) >> 8)
2134 - (XINT (spec_prop[i]) >> 8));
2135 score |= min (eabs (diff), 127) << sort_shift_bits[i];
2136 }
2137
2138 /* Score the size. Maximum difference is 127. */
2139 if (! NILP (spec_prop[FONT_SIZE_INDEX])
2140 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2141 {
2142 /* We use the higher 6-bit for the actual size difference. The
2143 lowest bit is set if the DPI is different. */
2144 EMACS_INT diff;
2145 EMACS_INT pixel_size = XINT (spec_prop[FONT_SIZE_INDEX]);
2146 EMACS_INT entity_size = XINT (AREF (entity, FONT_SIZE_INDEX));
2147
2148 if (CONSP (Vface_font_rescale_alist))
2149 pixel_size *= font_rescale_ratio (entity);
2150 if (pixel_size * 2 < entity_size || entity_size * 2 < pixel_size)
2151 /* This size is wrong by more than a factor 2: reject it! */
2152 return 0xFFFFFFFF;
2153 diff = eabs (pixel_size - entity_size) << 1;
2154 if (! NILP (spec_prop[FONT_DPI_INDEX])
2155 && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX)))
2156 diff |= 1;
2157 if (! NILP (spec_prop[FONT_AVGWIDTH_INDEX])
2158 && ! EQ (spec_prop[FONT_AVGWIDTH_INDEX], AREF (entity, FONT_AVGWIDTH_INDEX)))
2159 diff |= 1;
2160 score |= min (diff, 127) << sort_shift_bits[FONT_SIZE_INDEX];
2161 }
2162
2163 return score;
2164 }
2165
2166
2167 /* Concatenate all elements of LIST into one vector. LIST is a list
2168 of font-entity vectors. */
2169
2170 static Lisp_Object
2171 font_vconcat_entity_vectors (Lisp_Object list)
2172 {
2173 EMACS_INT nargs = XFASTINT (Flength (list));
2174 Lisp_Object *args;
2175 USE_SAFE_ALLOCA;
2176 SAFE_ALLOCA_LISP (args, nargs);
2177 ptrdiff_t i;
2178
2179 for (i = 0; i < nargs; i++, list = XCDR (list))
2180 args[i] = XCAR (list);
2181 Lisp_Object result = Fvconcat (nargs, args);
2182 SAFE_FREE ();
2183 return result;
2184 }
2185
2186
2187 /* The structure for elements being sorted by qsort. */
2188 struct font_sort_data
2189 {
2190 unsigned score;
2191 int font_driver_preference;
2192 Lisp_Object entity;
2193 };
2194
2195
2196 /* The comparison function for qsort. */
2197
2198 static int
2199 font_compare (const void *d1, const void *d2)
2200 {
2201 const struct font_sort_data *data1 = d1;
2202 const struct font_sort_data *data2 = d2;
2203
2204 if (data1->score < data2->score)
2205 return -1;
2206 else if (data1->score > data2->score)
2207 return 1;
2208 return (data1->font_driver_preference - data2->font_driver_preference);
2209 }
2210
2211
2212 /* Sort each font-entity vector in LIST by closeness to font-spec PREFER.
2213 If PREFER specifies a point-size, calculate the corresponding
2214 pixel-size from QCdpi property of PREFER or from the Y-resolution
2215 of FRAME before sorting.
2216
2217 If BEST-ONLY is nonzero, return the best matching entity (that
2218 supports the character BEST-ONLY if BEST-ONLY is positive, or any
2219 if BEST-ONLY is negative). Otherwise, return the sorted result as
2220 a single vector of font-entities.
2221
2222 This function does no optimization for the case that the total
2223 number of elements is 1. The caller should avoid calling this in
2224 such a case. */
2225
2226 static Lisp_Object
2227 font_sort_entities (Lisp_Object list, Lisp_Object prefer,
2228 struct frame *f, int best_only)
2229 {
2230 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2231 int len, maxlen, i;
2232 struct font_sort_data *data;
2233 unsigned best_score;
2234 Lisp_Object best_entity;
2235 Lisp_Object tail, vec IF_LINT (= Qnil);
2236 USE_SAFE_ALLOCA;
2237
2238 for (i = FONT_WEIGHT_INDEX; i <= FONT_AVGWIDTH_INDEX; i++)
2239 prefer_prop[i] = AREF (prefer, i);
2240 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2241 prefer_prop[FONT_SIZE_INDEX]
2242 = make_number (font_pixel_size (f, prefer));
2243
2244 if (NILP (XCDR (list)))
2245 {
2246 /* What we have to take care of is this single vector. */
2247 vec = XCAR (list);
2248 maxlen = ASIZE (vec);
2249 }
2250 else if (best_only)
2251 {
2252 /* We don't have to perform sort, so there's no need of creating
2253 a single vector. But, we must find the length of the longest
2254 vector. */
2255 maxlen = 0;
2256 for (tail = list; CONSP (tail); tail = XCDR (tail))
2257 if (maxlen < ASIZE (XCAR (tail)))
2258 maxlen = ASIZE (XCAR (tail));
2259 }
2260 else
2261 {
2262 /* We have to create a single vector to sort it. */
2263 vec = font_vconcat_entity_vectors (list);
2264 maxlen = ASIZE (vec);
2265 }
2266
2267 data = SAFE_ALLOCA (maxlen * sizeof *data);
2268 best_score = 0xFFFFFFFF;
2269 best_entity = Qnil;
2270
2271 for (tail = list; CONSP (tail); tail = XCDR (tail))
2272 {
2273 int font_driver_preference = 0;
2274 Lisp_Object current_font_driver;
2275
2276 if (best_only)
2277 vec = XCAR (tail);
2278 len = ASIZE (vec);
2279
2280 /* We are sure that the length of VEC > 0. */
2281 current_font_driver = AREF (AREF (vec, 0), FONT_TYPE_INDEX);
2282 /* Score the elements. */
2283 for (i = 0; i < len; i++)
2284 {
2285 data[i].entity = AREF (vec, i);
2286 data[i].score
2287 = ((best_only <= 0 || font_has_char (f, data[i].entity, best_only)
2288 > 0)
2289 ? font_score (data[i].entity, prefer_prop)
2290 : 0xFFFFFFFF);
2291 if (best_only && best_score > data[i].score)
2292 {
2293 best_score = data[i].score;
2294 best_entity = data[i].entity;
2295 if (best_score == 0)
2296 break;
2297 }
2298 if (! EQ (current_font_driver, AREF (AREF (vec, i), FONT_TYPE_INDEX)))
2299 {
2300 current_font_driver = AREF (AREF (vec, i), FONT_TYPE_INDEX);
2301 font_driver_preference++;
2302 }
2303 data[i].font_driver_preference = font_driver_preference;
2304 }
2305
2306 /* Sort if necessary. */
2307 if (! best_only)
2308 {
2309 qsort (data, len, sizeof *data, font_compare);
2310 for (i = 0; i < len; i++)
2311 ASET (vec, i, data[i].entity);
2312 break;
2313 }
2314 else
2315 vec = best_entity;
2316 }
2317
2318 SAFE_FREE ();
2319
2320 FONT_ADD_LOG ("sort-by", prefer, vec);
2321 return vec;
2322 }
2323
2324 \f
2325 /* API of Font Service Layer. */
2326
2327 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2328 sort_shift_bits. Finternal_set_font_selection_order calls this
2329 function with font_sort_order after setting up it. */
2330
2331 void
2332 font_update_sort_order (int *order)
2333 {
2334 int i, shift_bits;
2335
2336 for (i = 0, shift_bits = 23; i < 4; i++, shift_bits -= 7)
2337 {
2338 int xlfd_idx = order[i];
2339
2340 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2341 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2342 else if (xlfd_idx == XLFD_SLANT_INDEX)
2343 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2344 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2345 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2346 else
2347 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2348 }
2349 }
2350
2351 static bool
2352 font_check_otf_features (Lisp_Object script, Lisp_Object langsys,
2353 Lisp_Object features, Lisp_Object table)
2354 {
2355 Lisp_Object val;
2356 bool negative;
2357
2358 table = assq_no_quit (script, table);
2359 if (NILP (table))
2360 return 0;
2361 table = XCDR (table);
2362 if (! NILP (langsys))
2363 {
2364 table = assq_no_quit (langsys, table);
2365 if (NILP (table))
2366 return 0;
2367 }
2368 else
2369 {
2370 val = assq_no_quit (Qnil, table);
2371 if (NILP (val))
2372 table = XCAR (table);
2373 else
2374 table = val;
2375 }
2376 table = XCDR (table);
2377 for (negative = 0; CONSP (features); features = XCDR (features))
2378 {
2379 if (NILP (XCAR (features)))
2380 {
2381 negative = 1;
2382 continue;
2383 }
2384 if (NILP (Fmemq (XCAR (features), table)) != negative)
2385 return 0;
2386 }
2387 return 1;
2388 }
2389
2390 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2391
2392 static bool
2393 font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
2394 {
2395 Lisp_Object script, langsys = Qnil, gsub = Qnil, gpos = Qnil;
2396
2397 script = XCAR (spec);
2398 spec = XCDR (spec);
2399 if (! NILP (spec))
2400 {
2401 langsys = XCAR (spec);
2402 spec = XCDR (spec);
2403 if (! NILP (spec))
2404 {
2405 gsub = XCAR (spec);
2406 spec = XCDR (spec);
2407 if (! NILP (spec))
2408 gpos = XCAR (spec);
2409 }
2410 }
2411
2412 if (! NILP (gsub) && ! font_check_otf_features (script, langsys, gsub,
2413 XCAR (otf_capability)))
2414 return 0;
2415 if (! NILP (gpos) && ! font_check_otf_features (script, langsys, gpos,
2416 XCDR (otf_capability)))
2417 return 0;
2418 return 1;
2419 }
2420
2421
2422
2423 /* Check if FONT (font-entity or font-object) matches with the font
2424 specification SPEC. */
2425
2426 bool
2427 font_match_p (Lisp_Object spec, Lisp_Object font)
2428 {
2429 Lisp_Object prop[FONT_SPEC_MAX], *props;
2430 Lisp_Object extra, font_extra;
2431 int i;
2432
2433 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2434 if (! NILP (AREF (spec, i))
2435 && ! NILP (AREF (font, i))
2436 && ! EQ (AREF (spec, i), AREF (font, i)))
2437 return 0;
2438 props = XFONT_SPEC (spec)->props;
2439 if (FLOATP (props[FONT_SIZE_INDEX]))
2440 {
2441 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
2442 prop[i] = AREF (spec, i);
2443 prop[FONT_SIZE_INDEX]
2444 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2445 props = prop;
2446 }
2447
2448 if (font_score (font, props) > 0)
2449 return 0;
2450 extra = AREF (spec, FONT_EXTRA_INDEX);
2451 font_extra = AREF (font, FONT_EXTRA_INDEX);
2452 for (; CONSP (extra); extra = XCDR (extra))
2453 {
2454 Lisp_Object key = XCAR (XCAR (extra));
2455 Lisp_Object val = XCDR (XCAR (extra)), val2;
2456
2457 if (EQ (key, QClang))
2458 {
2459 val2 = assq_no_quit (key, font_extra);
2460 if (NILP (val2))
2461 return 0;
2462 val2 = XCDR (val2);
2463 if (CONSP (val))
2464 {
2465 if (! CONSP (val2))
2466 return 0;
2467 while (CONSP (val))
2468 if (NILP (Fmemq (val, val2)))
2469 return 0;
2470 }
2471 else
2472 if (CONSP (val2)
2473 ? NILP (Fmemq (val, XCDR (val2)))
2474 : ! EQ (val, val2))
2475 return 0;
2476 }
2477 else if (EQ (key, QCscript))
2478 {
2479 val2 = assq_no_quit (val, Vscript_representative_chars);
2480 if (CONSP (val2))
2481 {
2482 val2 = XCDR (val2);
2483 if (CONSP (val2))
2484 {
2485 /* All characters in the list must be supported. */
2486 for (; CONSP (val2); val2 = XCDR (val2))
2487 {
2488 if (! CHARACTERP (XCAR (val2)))
2489 continue;
2490 if (font_encode_char (font, XFASTINT (XCAR (val2)))
2491 == FONT_INVALID_CODE)
2492 return 0;
2493 }
2494 }
2495 else if (VECTORP (val2))
2496 {
2497 /* At most one character in the vector must be supported. */
2498 for (i = 0; i < ASIZE (val2); i++)
2499 {
2500 if (! CHARACTERP (AREF (val2, i)))
2501 continue;
2502 if (font_encode_char (font, XFASTINT (AREF (val2, i)))
2503 != FONT_INVALID_CODE)
2504 break;
2505 }
2506 if (i == ASIZE (val2))
2507 return 0;
2508 }
2509 }
2510 }
2511 else if (EQ (key, QCotf))
2512 {
2513 struct font *fontp;
2514
2515 if (! FONT_OBJECT_P (font))
2516 return 0;
2517 fontp = XFONT_OBJECT (font);
2518 if (! fontp->driver->otf_capability)
2519 return 0;
2520 val2 = fontp->driver->otf_capability (fontp);
2521 if (NILP (val2) || ! font_check_otf (val, val2))
2522 return 0;
2523 }
2524 }
2525
2526 return 1;
2527 }
2528 \f
2529
2530 /* Font cache
2531
2532 Each font backend has the callback function get_cache, and it
2533 returns a cons cell of which cdr part can be freely used for
2534 caching fonts. The cons cell may be shared by multiple frames
2535 and/or multiple font drivers. So, we arrange the cdr part as this:
2536
2537 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2538
2539 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2540 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2541 cons (FONT-SPEC . [FONT-ENTITY ...]). */
2542
2543 static void font_prepare_cache (struct frame *, struct font_driver *);
2544 static void font_finish_cache (struct frame *, struct font_driver *);
2545 static Lisp_Object font_get_cache (struct frame *, struct font_driver *);
2546 static void font_clear_cache (struct frame *, Lisp_Object,
2547 struct font_driver *);
2548
2549 static void
2550 font_prepare_cache (struct frame *f, struct font_driver *driver)
2551 {
2552 Lisp_Object cache, val;
2553
2554 cache = driver->get_cache (f);
2555 val = XCDR (cache);
2556 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2557 val = XCDR (val);
2558 if (NILP (val))
2559 {
2560 val = list2 (driver->type, make_number (1));
2561 XSETCDR (cache, Fcons (val, XCDR (cache)));
2562 }
2563 else
2564 {
2565 val = XCDR (XCAR (val));
2566 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2567 }
2568 }
2569
2570
2571 static void
2572 font_finish_cache (struct frame *f, struct font_driver *driver)
2573 {
2574 Lisp_Object cache, val, tmp;
2575
2576
2577 cache = driver->get_cache (f);
2578 val = XCDR (cache);
2579 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2580 cache = val, val = XCDR (val);
2581 eassert (! NILP (val));
2582 tmp = XCDR (XCAR (val));
2583 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2584 if (XINT (XCAR (tmp)) == 0)
2585 {
2586 font_clear_cache (f, XCAR (val), driver);
2587 XSETCDR (cache, XCDR (val));
2588 }
2589 }
2590
2591
2592 static Lisp_Object
2593 font_get_cache (struct frame *f, struct font_driver *driver)
2594 {
2595 Lisp_Object val = driver->get_cache (f);
2596 Lisp_Object type = driver->type;
2597
2598 eassert (CONSP (val));
2599 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2600 eassert (CONSP (val));
2601 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2602 val = XCDR (XCAR (val));
2603 return val;
2604 }
2605
2606
2607 static void
2608 font_clear_cache (struct frame *f, Lisp_Object cache, struct font_driver *driver)
2609 {
2610 Lisp_Object tail, elt;
2611 Lisp_Object entity;
2612 ptrdiff_t i;
2613
2614 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2615 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2616 {
2617 elt = XCAR (tail);
2618 /* elt should have the form (FONT-SPEC . [FONT-ENTITY ...]) */
2619 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2620 {
2621 elt = XCDR (elt);
2622 eassert (VECTORP (elt));
2623 for (i = 0; i < ASIZE (elt); i++)
2624 {
2625 entity = AREF (elt, i);
2626
2627 if (FONT_ENTITY_P (entity)
2628 && EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2629 {
2630 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2631
2632 for (; CONSP (objlist); objlist = XCDR (objlist))
2633 {
2634 Lisp_Object val = XCAR (objlist);
2635 struct font *font = XFONT_OBJECT (val);
2636
2637 if (! NILP (AREF (val, FONT_TYPE_INDEX)))
2638 {
2639 eassert (font && driver == font->driver);
2640 driver->close (font);
2641 }
2642 }
2643 if (driver->free_entity)
2644 driver->free_entity (entity);
2645 }
2646 }
2647 }
2648 }
2649 XSETCDR (cache, Qnil);
2650 }
2651 \f
2652
2653 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2654
2655 /* Check each font-entity in VEC, and return a list of font-entities
2656 that satisfy these conditions:
2657 (1) matches with SPEC and SIZE if SPEC is not nil, and
2658 (2) doesn't match with any regexps in Vface_ignored_fonts (if non-nil).
2659 */
2660
2661 static Lisp_Object
2662 font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size)
2663 {
2664 Lisp_Object entity, val;
2665 enum font_property_index prop;
2666 ptrdiff_t i;
2667
2668 for (val = Qnil, i = ASIZE (vec) - 1; i >= 0; i--)
2669 {
2670 entity = AREF (vec, i);
2671 if (! NILP (Vface_ignored_fonts))
2672 {
2673 char name[256];
2674 ptrdiff_t namelen;
2675 Lisp_Object tail, regexp;
2676
2677 namelen = font_unparse_xlfd (entity, 0, name, 256);
2678 if (namelen >= 0)
2679 {
2680 for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
2681 {
2682 regexp = XCAR (tail);
2683 if (STRINGP (regexp)
2684 && fast_c_string_match_ignore_case (regexp, name,
2685 namelen) >= 0)
2686 break;
2687 }
2688 if (CONSP (tail))
2689 continue;
2690 }
2691 }
2692 if (NILP (spec))
2693 {
2694 val = Fcons (entity, val);
2695 continue;
2696 }
2697 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++)
2698 if (INTEGERP (AREF (spec, prop))
2699 && ((XINT (AREF (spec, prop)) >> 8)
2700 != (XINT (AREF (entity, prop)) >> 8)))
2701 prop = FONT_SPEC_MAX;
2702 if (prop < FONT_SPEC_MAX
2703 && size
2704 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2705 {
2706 int diff = XINT (AREF (entity, FONT_SIZE_INDEX)) - size;
2707
2708 if (eabs (diff) > FONT_PIXEL_SIZE_QUANTUM)
2709 prop = FONT_SPEC_MAX;
2710 }
2711 if (prop < FONT_SPEC_MAX
2712 && INTEGERP (AREF (spec, FONT_DPI_INDEX))
2713 && INTEGERP (AREF (entity, FONT_DPI_INDEX))
2714 && XINT (AREF (entity, FONT_DPI_INDEX)) != 0
2715 && ! EQ (AREF (spec, FONT_DPI_INDEX), AREF (entity, FONT_DPI_INDEX)))
2716 prop = FONT_SPEC_MAX;
2717 if (prop < FONT_SPEC_MAX
2718 && INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
2719 && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
2720 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) != 0
2721 && ! EQ (AREF (spec, FONT_AVGWIDTH_INDEX),
2722 AREF (entity, FONT_AVGWIDTH_INDEX)))
2723 prop = FONT_SPEC_MAX;
2724 if (prop < FONT_SPEC_MAX)
2725 val = Fcons (entity, val);
2726 }
2727 return (Fvconcat (1, &val));
2728 }
2729
2730
2731 /* Return a list of vectors of font-entities matching with SPEC on
2732 FRAME. Each elements in the list is a vector of entities from the
2733 same font-driver. */
2734
2735 Lisp_Object
2736 font_list_entities (struct frame *f, Lisp_Object spec)
2737 {
2738 struct font_driver_list *driver_list = f->font_driver_list;
2739 Lisp_Object ftype, val;
2740 Lisp_Object list = Qnil;
2741 int size;
2742 bool need_filtering = 0;
2743 int i;
2744
2745 eassert (FONT_SPEC_P (spec));
2746
2747 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2748 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2749 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2750 size = font_pixel_size (f, spec);
2751 else
2752 size = 0;
2753
2754 ftype = AREF (spec, FONT_TYPE_INDEX);
2755 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2756 ASET (scratch_font_spec, i, AREF (spec, i));
2757 for (i = FONT_WEIGHT_INDEX; i < FONT_EXTRA_INDEX; i++)
2758 if (i != FONT_SPACING_INDEX)
2759 {
2760 ASET (scratch_font_spec, i, Qnil);
2761 if (! NILP (AREF (spec, i)))
2762 need_filtering = 1;
2763 }
2764 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX));
2765 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
2766
2767 for (; driver_list; driver_list = driver_list->next)
2768 if (driver_list->on
2769 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2770 {
2771 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2772
2773 ASET (scratch_font_spec, FONT_TYPE_INDEX, driver_list->driver->type);
2774 val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2775 if (CONSP (val))
2776 val = XCDR (val);
2777 else
2778 {
2779 val = driver_list->driver->list (f, scratch_font_spec);
2780 if (!NILP (val))
2781 {
2782 Lisp_Object copy = copy_font_spec (scratch_font_spec);
2783
2784 val = Fvconcat (1, &val);
2785 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2786 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2787 }
2788 }
2789 if (VECTORP (val) && ASIZE (val) > 0
2790 && (need_filtering
2791 || ! NILP (Vface_ignored_fonts)))
2792 val = font_delete_unmatched (val, need_filtering ? spec : Qnil, size);
2793 if (VECTORP (val) && ASIZE (val) > 0)
2794 list = Fcons (val, list);
2795 }
2796
2797 list = Fnreverse (list);
2798 FONT_ADD_LOG ("list", spec, list);
2799 return list;
2800 }
2801
2802
2803 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2804 nil, is an array of face's attributes, which specifies preferred
2805 font-related attributes. */
2806
2807 static Lisp_Object
2808 font_matching_entity (struct frame *f, Lisp_Object *attrs, Lisp_Object spec)
2809 {
2810 struct font_driver_list *driver_list = f->font_driver_list;
2811 Lisp_Object ftype, size, entity;
2812 Lisp_Object work = copy_font_spec (spec);
2813
2814 ftype = AREF (spec, FONT_TYPE_INDEX);
2815 size = AREF (spec, FONT_SIZE_INDEX);
2816
2817 if (FLOATP (size))
2818 ASET (work, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2819 FONT_SET_STYLE (work, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
2820 FONT_SET_STYLE (work, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
2821 FONT_SET_STYLE (work, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
2822
2823 entity = Qnil;
2824 for (; driver_list; driver_list = driver_list->next)
2825 if (driver_list->on
2826 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2827 {
2828 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2829
2830 ASET (work, FONT_TYPE_INDEX, driver_list->driver->type);
2831 entity = assoc_no_quit (work, XCDR (cache));
2832 if (CONSP (entity))
2833 entity = AREF (XCDR (entity), 0);
2834 else
2835 {
2836 entity = driver_list->driver->match (f, work);
2837 if (!NILP (entity))
2838 {
2839 Lisp_Object copy = copy_font_spec (work);
2840 Lisp_Object match = Fvector (1, &entity);
2841
2842 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2843 XSETCDR (cache, Fcons (Fcons (copy, match), XCDR (cache)));
2844 }
2845 }
2846 if (! NILP (entity))
2847 break;
2848 }
2849 FONT_ADD_LOG ("match", work, entity);
2850 return entity;
2851 }
2852
2853
2854 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2855 opened font object. */
2856
2857 static Lisp_Object
2858 font_open_entity (struct frame *f, Lisp_Object entity, int pixel_size)
2859 {
2860 struct font_driver_list *driver_list;
2861 Lisp_Object objlist, size, val, font_object;
2862 struct font *font;
2863 int min_width, height, psize;
2864
2865 eassert (FONT_ENTITY_P (entity));
2866 size = AREF (entity, FONT_SIZE_INDEX);
2867 if (XINT (size) != 0)
2868 pixel_size = XINT (size);
2869
2870 val = AREF (entity, FONT_TYPE_INDEX);
2871 for (driver_list = f->font_driver_list;
2872 driver_list && ! EQ (driver_list->driver->type, val);
2873 driver_list = driver_list->next);
2874 if (! driver_list)
2875 return Qnil;
2876
2877 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2878 objlist = XCDR (objlist))
2879 {
2880 Lisp_Object fn = XCAR (objlist);
2881 if (! NILP (AREF (fn, FONT_TYPE_INDEX))
2882 && XFONT_OBJECT (fn)->pixel_size == pixel_size)
2883 {
2884 if (driver_list->driver->cached_font_ok == NULL
2885 || driver_list->driver->cached_font_ok (f, fn, entity))
2886 return fn;
2887 }
2888 }
2889
2890 /* We always open a font of manageable size; i.e non-zero average
2891 width and height. */
2892 for (psize = pixel_size; ; psize++)
2893 {
2894 font_object = driver_list->driver->open (f, entity, psize);
2895 if (NILP (font_object))
2896 return Qnil;
2897 font = XFONT_OBJECT (font_object);
2898 if (font->average_width > 0 && font->height > 0)
2899 break;
2900 }
2901 ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
2902 FONT_ADD_LOG ("open", entity, font_object);
2903 ASET (entity, FONT_OBJLIST_INDEX,
2904 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2905
2906 font = XFONT_OBJECT (font_object);
2907 min_width = (font->min_width ? font->min_width
2908 : font->average_width ? font->average_width
2909 : font->space_width ? font->space_width
2910 : 1);
2911
2912 int font_ascent, font_descent;
2913 get_font_ascent_descent (font, &font_ascent, &font_descent);
2914 height = font_ascent + font_descent;
2915 if (height <= 0)
2916 height = 1;
2917 #ifdef HAVE_WINDOW_SYSTEM
2918 FRAME_DISPLAY_INFO (f)->n_fonts++;
2919 if (FRAME_DISPLAY_INFO (f)->n_fonts == 1)
2920 {
2921 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
2922 FRAME_SMALLEST_FONT_HEIGHT (f) = height;
2923 f->fonts_changed = 1;
2924 }
2925 else
2926 {
2927 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
2928 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, f->fonts_changed = 1;
2929 if (FRAME_SMALLEST_FONT_HEIGHT (f) > height)
2930 FRAME_SMALLEST_FONT_HEIGHT (f) = height, f->fonts_changed = 1;
2931 }
2932 #endif
2933
2934 return font_object;
2935 }
2936
2937
2938 /* Close FONT_OBJECT that is opened on frame F. */
2939
2940 static void
2941 font_close_object (struct frame *f, Lisp_Object font_object)
2942 {
2943 struct font *font = XFONT_OBJECT (font_object);
2944
2945 if (NILP (AREF (font_object, FONT_TYPE_INDEX)))
2946 /* Already closed. */
2947 return;
2948 FONT_ADD_LOG ("close", font_object, Qnil);
2949 font->driver->close (font);
2950 #ifdef HAVE_WINDOW_SYSTEM
2951 eassert (FRAME_DISPLAY_INFO (f)->n_fonts);
2952 FRAME_DISPLAY_INFO (f)->n_fonts--;
2953 #endif
2954 }
2955
2956
2957 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2958 FONT is a font-entity and it must be opened to check. */
2959
2960 int
2961 font_has_char (struct frame *f, Lisp_Object font, int c)
2962 {
2963 struct font *fontp;
2964
2965 if (FONT_ENTITY_P (font))
2966 {
2967 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
2968 struct font_driver_list *driver_list;
2969
2970 for (driver_list = f->font_driver_list;
2971 driver_list && ! EQ (driver_list->driver->type, type);
2972 driver_list = driver_list->next);
2973 if (! driver_list)
2974 return 0;
2975 if (! driver_list->driver->has_char)
2976 return -1;
2977 return driver_list->driver->has_char (font, c);
2978 }
2979
2980 eassert (FONT_OBJECT_P (font));
2981 fontp = XFONT_OBJECT (font);
2982 if (fontp->driver->has_char)
2983 {
2984 int result = fontp->driver->has_char (font, c);
2985
2986 if (result >= 0)
2987 return result;
2988 }
2989 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
2990 }
2991
2992
2993 /* Return the glyph ID of FONT_OBJECT for character C. */
2994
2995 static unsigned
2996 font_encode_char (Lisp_Object font_object, int c)
2997 {
2998 struct font *font;
2999
3000 eassert (FONT_OBJECT_P (font_object));
3001 font = XFONT_OBJECT (font_object);
3002 return font->driver->encode_char (font, c);
3003 }
3004
3005
3006 /* Return the name of FONT_OBJECT. */
3007
3008 Lisp_Object
3009 font_get_name (Lisp_Object font_object)
3010 {
3011 eassert (FONT_OBJECT_P (font_object));
3012 return AREF (font_object, FONT_NAME_INDEX);
3013 }
3014
3015
3016 /* Create a new font spec from FONT_NAME, and return it. If FONT_NAME
3017 could not be parsed by font_parse_name, return Qnil. */
3018
3019 Lisp_Object
3020 font_spec_from_name (Lisp_Object font_name)
3021 {
3022 Lisp_Object spec = Ffont_spec (0, NULL);
3023
3024 CHECK_STRING (font_name);
3025 if (font_parse_name (SSDATA (font_name), SBYTES (font_name), spec) == -1)
3026 return Qnil;
3027 font_put_extra (spec, QCname, font_name);
3028 font_put_extra (spec, QCuser_spec, font_name);
3029 return spec;
3030 }
3031
3032
3033 void
3034 font_clear_prop (Lisp_Object *attrs, enum font_property_index prop)
3035 {
3036 Lisp_Object font = attrs[LFACE_FONT_INDEX];
3037
3038 if (! FONTP (font))
3039 return;
3040
3041 if (! NILP (Ffont_get (font, QCname)))
3042 {
3043 font = copy_font_spec (font);
3044 font_put_extra (font, QCname, Qnil);
3045 }
3046
3047 if (NILP (AREF (font, prop))
3048 && prop != FONT_FAMILY_INDEX
3049 && prop != FONT_FOUNDRY_INDEX
3050 && prop != FONT_WIDTH_INDEX
3051 && prop != FONT_SIZE_INDEX)
3052 return;
3053 if (EQ (font, attrs[LFACE_FONT_INDEX]))
3054 font = copy_font_spec (font);
3055 ASET (font, prop, Qnil);
3056 if (prop == FONT_FAMILY_INDEX || prop == FONT_FOUNDRY_INDEX)
3057 {
3058 if (prop == FONT_FAMILY_INDEX)
3059 {
3060 ASET (font, FONT_FOUNDRY_INDEX, Qnil);
3061 /* If we are setting the font family, we must also clear
3062 FONT_WIDTH_INDEX to avoid rejecting families that lack
3063 support for some widths. */
3064 ASET (font, FONT_WIDTH_INDEX, Qnil);
3065 }
3066 ASET (font, FONT_ADSTYLE_INDEX, Qnil);
3067 ASET (font, FONT_REGISTRY_INDEX, Qnil);
3068 ASET (font, FONT_SIZE_INDEX, Qnil);
3069 ASET (font, FONT_DPI_INDEX, Qnil);
3070 ASET (font, FONT_SPACING_INDEX, Qnil);
3071 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3072 }
3073 else if (prop == FONT_SIZE_INDEX)
3074 {
3075 ASET (font, FONT_DPI_INDEX, Qnil);
3076 ASET (font, FONT_SPACING_INDEX, Qnil);
3077 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3078 }
3079 else if (prop == FONT_WIDTH_INDEX)
3080 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
3081 attrs[LFACE_FONT_INDEX] = font;
3082 }
3083
3084 /* Select a font from ENTITIES (list of font-entity vectors) that
3085 supports C and is the best match for ATTRS and PIXEL_SIZE. */
3086
3087 static Lisp_Object
3088 font_select_entity (struct frame *f, Lisp_Object entities,
3089 Lisp_Object *attrs, int pixel_size, int c)
3090 {
3091 Lisp_Object font_entity;
3092 Lisp_Object prefer;
3093 int i;
3094
3095 if (NILP (XCDR (entities))
3096 && ASIZE (XCAR (entities)) == 1)
3097 {
3098 font_entity = AREF (XCAR (entities), 0);
3099 if (c < 0 || font_has_char (f, font_entity, c) > 0)
3100 return font_entity;
3101 return Qnil;
3102 }
3103
3104 /* Sort fonts by properties specified in ATTRS. */
3105 prefer = scratch_font_prefer;
3106
3107 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3108 ASET (prefer, i, Qnil);
3109 if (FONTP (attrs[LFACE_FONT_INDEX]))
3110 {
3111 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3112
3113 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
3114 ASET (prefer, i, AREF (face_font, i));
3115 }
3116 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
3117 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
3118 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
3119 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
3120 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
3121 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
3122 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
3123
3124 return font_sort_entities (entities, prefer, f, c);
3125 }
3126
3127 /* Return a font-entity that satisfies SPEC and is the best match for
3128 face's font related attributes in ATTRS. C, if not negative, is a
3129 character that the entity must support. */
3130
3131 Lisp_Object
3132 font_find_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec, int c)
3133 {
3134 Lisp_Object work;
3135 Lisp_Object entities, val;
3136 Lisp_Object foundry[3], *family, registry[3], adstyle[3];
3137 int pixel_size;
3138 int i, j, k, l;
3139 USE_SAFE_ALLOCA;
3140
3141 registry[0] = AREF (spec, FONT_REGISTRY_INDEX);
3142 if (NILP (registry[0]))
3143 {
3144 registry[0] = DEFAULT_ENCODING;
3145 registry[1] = Qascii_0;
3146 registry[2] = zero_vector;
3147 }
3148 else
3149 registry[1] = zero_vector;
3150
3151 if (c >= 0 && ! NILP (AREF (spec, FONT_REGISTRY_INDEX)))
3152 {
3153 struct charset *encoding, *repertory;
3154
3155 if (font_registry_charsets (AREF (spec, FONT_REGISTRY_INDEX),
3156 &encoding, &repertory) < 0)
3157 return Qnil;
3158 if (repertory
3159 && ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
3160 return Qnil;
3161 else if (c > encoding->max_char)
3162 return Qnil;
3163 }
3164
3165 work = copy_font_spec (spec);
3166 ASET (work, FONT_TYPE_INDEX, AREF (spec, FONT_TYPE_INDEX));
3167 pixel_size = font_pixel_size (f, spec);
3168 if (pixel_size == 0 && INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
3169 {
3170 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3171
3172 pixel_size = POINT_TO_PIXEL (pt / 10, FRAME_RES_Y (f));
3173 if (pixel_size < 1)
3174 pixel_size = 1;
3175 }
3176 ASET (work, FONT_SIZE_INDEX, Qnil);
3177 foundry[0] = AREF (work, FONT_FOUNDRY_INDEX);
3178 if (! NILP (foundry[0]))
3179 foundry[1] = zero_vector;
3180 else if (STRINGP (attrs[LFACE_FOUNDRY_INDEX]))
3181 {
3182 val = attrs[LFACE_FOUNDRY_INDEX];
3183 foundry[0] = font_intern_prop (SSDATA (val), SBYTES (val), 1);
3184 foundry[1] = Qnil;
3185 foundry[2] = zero_vector;
3186 }
3187 else
3188 foundry[0] = Qnil, foundry[1] = zero_vector;
3189
3190 adstyle[0] = AREF (work, FONT_ADSTYLE_INDEX);
3191 if (! NILP (adstyle[0]))
3192 adstyle[1] = zero_vector;
3193 else if (FONTP (attrs[LFACE_FONT_INDEX]))
3194 {
3195 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3196
3197 if (! NILP (AREF (face_font, FONT_ADSTYLE_INDEX)))
3198 {
3199 adstyle[0] = AREF (face_font, FONT_ADSTYLE_INDEX);
3200 adstyle[1] = Qnil;
3201 adstyle[2] = zero_vector;
3202 }
3203 else
3204 adstyle[0] = Qnil, adstyle[1] = zero_vector;
3205 }
3206 else
3207 adstyle[0] = Qnil, adstyle[1] = zero_vector;
3208
3209
3210 val = AREF (work, FONT_FAMILY_INDEX);
3211 if (NILP (val) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
3212 {
3213 val = attrs[LFACE_FAMILY_INDEX];
3214 val = font_intern_prop (SSDATA (val), SBYTES (val), 1);
3215 }
3216 Lisp_Object familybuf[3];
3217 if (NILP (val))
3218 {
3219 family = familybuf;
3220 family[0] = Qnil;
3221 family[1] = zero_vector; /* terminator. */
3222 }
3223 else
3224 {
3225 Lisp_Object alters
3226 = Fassoc_string (val, Vface_alternative_font_family_alist, Qt);
3227
3228 if (! NILP (alters))
3229 {
3230 EMACS_INT alterslen = XFASTINT (Flength (alters));
3231 SAFE_ALLOCA_LISP (family, alterslen + 2);
3232 for (i = 0; CONSP (alters); i++, alters = XCDR (alters))
3233 family[i] = XCAR (alters);
3234 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3235 family[i++] = Qnil;
3236 family[i] = zero_vector;
3237 }
3238 else
3239 {
3240 family = familybuf;
3241 i = 0;
3242 family[i++] = val;
3243 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
3244 family[i++] = Qnil;
3245 family[i] = zero_vector;
3246 }
3247 }
3248
3249 for (i = 0; SYMBOLP (family[i]); i++)
3250 {
3251 ASET (work, FONT_FAMILY_INDEX, family[i]);
3252 for (j = 0; SYMBOLP (foundry[j]); j++)
3253 {
3254 ASET (work, FONT_FOUNDRY_INDEX, foundry[j]);
3255 for (k = 0; SYMBOLP (registry[k]); k++)
3256 {
3257 ASET (work, FONT_REGISTRY_INDEX, registry[k]);
3258 for (l = 0; SYMBOLP (adstyle[l]); l++)
3259 {
3260 ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
3261 entities = font_list_entities (f, work);
3262 if (! NILP (entities))
3263 {
3264 val = font_select_entity (f, entities,
3265 attrs, pixel_size, c);
3266 if (! NILP (val))
3267 {
3268 SAFE_FREE ();
3269 return val;
3270 }
3271 }
3272 }
3273 }
3274 }
3275 }
3276
3277 SAFE_FREE ();
3278 return Qnil;
3279 }
3280
3281
3282 Lisp_Object
3283 font_open_for_lface (struct frame *f, Lisp_Object entity, Lisp_Object *attrs, Lisp_Object spec)
3284 {
3285 int size;
3286
3287 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX))
3288 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
3289 size = XINT (AREF (entity, FONT_SIZE_INDEX));
3290 else
3291 {
3292 if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
3293 size = font_pixel_size (f, spec);
3294 else
3295 {
3296 double pt;
3297 if (INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
3298 pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3299 else
3300 {
3301 struct face *def = FACE_FROM_ID (f, DEFAULT_FACE_ID);
3302 Lisp_Object height = def->lface[LFACE_HEIGHT_INDEX];
3303 eassert (INTEGERP (height));
3304 pt = XINT (height);
3305 }
3306
3307 pt /= 10;
3308 size = POINT_TO_PIXEL (pt, FRAME_RES_Y (f));
3309 #ifdef HAVE_NS
3310 if (size == 0)
3311 {
3312 Lisp_Object ffsize = get_frame_param (f, Qfontsize);
3313 size = (NUMBERP (ffsize)
3314 ? POINT_TO_PIXEL (XINT (ffsize), FRAME_RES_Y (f)) : 0);
3315 }
3316 #endif
3317 }
3318 size *= font_rescale_ratio (entity);
3319 }
3320
3321 return font_open_entity (f, entity, size);
3322 }
3323
3324
3325 /* Find a font that satisfies SPEC and is the best match for
3326 face's attributes in ATTRS on FRAME, and return the opened
3327 font-object. */
3328
3329 Lisp_Object
3330 font_load_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec)
3331 {
3332 Lisp_Object entity, name;
3333
3334 entity = font_find_for_lface (f, attrs, spec, -1);
3335 if (NILP (entity))
3336 {
3337 /* No font is listed for SPEC, but each font-backend may have
3338 different criteria about "font matching". So, try it. */
3339 entity = font_matching_entity (f, attrs, spec);
3340 /* Perhaps the user asked for a font "Foobar-123", and we
3341 interpreted "-123" as the size, whereas it really is part of
3342 the name. So we reset the size to nil and the family name to
3343 the entire "Foobar-123" thing, and try again with that. */
3344 if (NILP (entity))
3345 {
3346 name = Ffont_get (spec, QCuser_spec);
3347 if (STRINGP (name))
3348 {
3349 char *p = SSDATA (name), *q = strrchr (p, '-');
3350
3351 if (q != NULL && c_isdigit (q[1]))
3352 {
3353 char *tail;
3354 double font_size = strtod (q + 1, &tail);
3355
3356 if (font_size > 0 && tail != q + 1)
3357 {
3358 Lisp_Object lsize = Ffont_get (spec, QCsize);
3359
3360 if ((FLOATP (lsize) && XFLOAT_DATA (lsize) == font_size)
3361 || (INTEGERP (lsize) && XINT (lsize) == font_size))
3362 {
3363 ASET (spec, FONT_FAMILY_INDEX,
3364 font_intern_prop (p, tail - p, 1));
3365 ASET (spec, FONT_SIZE_INDEX, Qnil);
3366 entity = font_matching_entity (f, attrs, spec);
3367 }
3368 }
3369 }
3370 }
3371 }
3372 if (NILP (entity))
3373 return Qnil;
3374 }
3375 /* Don't lose the original name that was put in initially. We need
3376 it to re-apply the font when font parameters (like hinting or dpi) have
3377 changed. */
3378 entity = font_open_for_lface (f, entity, attrs, spec);
3379 if (!NILP (entity))
3380 {
3381 name = Ffont_get (spec, QCuser_spec);
3382 if (STRINGP (name)) font_put_extra (entity, QCuser_spec, name);
3383 }
3384 return entity;
3385 }
3386
3387
3388 /* Make FACE on frame F ready to use the font opened for FACE. */
3389
3390 void
3391 font_prepare_for_face (struct frame *f, struct face *face)
3392 {
3393 if (face->font->driver->prepare_face)
3394 face->font->driver->prepare_face (f, face);
3395 }
3396
3397
3398 /* Make FACE on frame F stop using the font opened for FACE. */
3399
3400 void
3401 font_done_for_face (struct frame *f, struct face *face)
3402 {
3403 if (face->font->driver->done_face)
3404 face->font->driver->done_face (f, face);
3405 }
3406
3407
3408 /* Open a font that is a match for font-spec SPEC on frame F. If no proper
3409 font is found, return Qnil. */
3410
3411 Lisp_Object
3412 font_open_by_spec (struct frame *f, Lisp_Object spec)
3413 {
3414 Lisp_Object attrs[LFACE_VECTOR_SIZE];
3415
3416 /* We set up the default font-related attributes of a face to prefer
3417 a moderate font. */
3418 attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
3419 attrs[LFACE_SWIDTH_INDEX] = attrs[LFACE_WEIGHT_INDEX]
3420 = attrs[LFACE_SLANT_INDEX] = Qnormal;
3421 #ifndef HAVE_NS
3422 attrs[LFACE_HEIGHT_INDEX] = make_number (120);
3423 #else
3424 attrs[LFACE_HEIGHT_INDEX] = make_number (0);
3425 #endif
3426 attrs[LFACE_FONT_INDEX] = Qnil;
3427
3428 return font_load_for_lface (f, attrs, spec);
3429 }
3430
3431
3432 /* Open a font that matches NAME on frame F. If no proper font is
3433 found, return Qnil. */
3434
3435 Lisp_Object
3436 font_open_by_name (struct frame *f, Lisp_Object name)
3437 {
3438 Lisp_Object spec = CALLN (Ffont_spec, QCname, name);
3439 Lisp_Object ret = font_open_by_spec (f, spec);
3440 /* Do not lose name originally put in. */
3441 if (!NILP (ret))
3442 font_put_extra (ret, QCuser_spec, name);
3443
3444 return ret;
3445 }
3446
3447
3448 /* Register font-driver DRIVER. This function is used in two ways.
3449
3450 The first is with frame F non-NULL. In this case, make DRIVER
3451 available (but not yet activated) on F. All frame creators
3452 (e.g. Fx_create_frame) must call this function at least once with
3453 an available font-driver.
3454
3455 The second is with frame F NULL. In this case, DRIVER is globally
3456 registered in the variable `font_driver_list'. All font-driver
3457 implementations must call this function in its syms_of_XXXX
3458 (e.g. syms_of_xfont). */
3459
3460 void
3461 register_font_driver (struct font_driver *driver, struct frame *f)
3462 {
3463 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
3464 struct font_driver_list *prev, *list;
3465
3466 #ifdef HAVE_WINDOW_SYSTEM
3467 if (f && ! driver->draw)
3468 error ("Unusable font driver for a frame: %s",
3469 SDATA (SYMBOL_NAME (driver->type)));
3470 #endif /* HAVE_WINDOW_SYSTEM */
3471
3472 for (prev = NULL, list = root; list; prev = list, list = list->next)
3473 if (EQ (list->driver->type, driver->type))
3474 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3475
3476 list = xmalloc (sizeof *list);
3477 list->on = 0;
3478 list->driver = driver;
3479 list->next = NULL;
3480 if (prev)
3481 prev->next = list;
3482 else if (f)
3483 f->font_driver_list = list;
3484 else
3485 font_driver_list = list;
3486 if (! f)
3487 num_font_drivers++;
3488 }
3489
3490 void
3491 free_font_driver_list (struct frame *f)
3492 {
3493 struct font_driver_list *list, *next;
3494
3495 for (list = f->font_driver_list; list; list = next)
3496 {
3497 next = list->next;
3498 xfree (list);
3499 }
3500 f->font_driver_list = NULL;
3501 }
3502
3503
3504 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3505 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3506 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3507
3508 A caller must free all realized faces if any in advance. The
3509 return value is a list of font backends actually made used on
3510 F. */
3511
3512 Lisp_Object
3513 font_update_drivers (struct frame *f, Lisp_Object new_drivers)
3514 {
3515 Lisp_Object active_drivers = Qnil;
3516 struct font_driver_list *list;
3517
3518 /* At first, turn off non-requested drivers, and turn on requested
3519 drivers. */
3520 for (list = f->font_driver_list; list; list = list->next)
3521 {
3522 struct font_driver *driver = list->driver;
3523 if ((EQ (new_drivers, Qt) || ! NILP (Fmemq (driver->type, new_drivers)))
3524 != list->on)
3525 {
3526 if (list->on)
3527 {
3528 if (driver->end_for_frame)
3529 driver->end_for_frame (f);
3530 font_finish_cache (f, driver);
3531 list->on = 0;
3532 }
3533 else
3534 {
3535 if (! driver->start_for_frame
3536 || driver->start_for_frame (f) == 0)
3537 {
3538 font_prepare_cache (f, driver);
3539 list->on = 1;
3540 }
3541 }
3542 }
3543 }
3544
3545 if (NILP (new_drivers))
3546 return Qnil;
3547
3548 if (! EQ (new_drivers, Qt))
3549 {
3550 /* Re-order the driver list according to new_drivers. */
3551 struct font_driver_list **list_table, **next;
3552 Lisp_Object tail;
3553 int i;
3554 USE_SAFE_ALLOCA;
3555
3556 SAFE_NALLOCA (list_table, 1, num_font_drivers + 1);
3557 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
3558 {
3559 for (list = f->font_driver_list; list; list = list->next)
3560 if (list->on && EQ (list->driver->type, XCAR (tail)))
3561 break;
3562 if (list)
3563 list_table[i++] = list;
3564 }
3565 for (list = f->font_driver_list; list; list = list->next)
3566 if (! list->on)
3567 list_table[i++] = list;
3568 list_table[i] = NULL;
3569
3570 next = &f->font_driver_list;
3571 for (i = 0; list_table[i]; i++)
3572 {
3573 *next = list_table[i];
3574 next = &(*next)->next;
3575 }
3576 *next = NULL;
3577 SAFE_FREE ();
3578
3579 if (! f->font_driver_list->on)
3580 { /* None of the drivers is enabled: enable them all.
3581 Happens if you set the list of drivers to (xft x) in your .emacs
3582 and then use it under w32 or ns. */
3583 for (list = f->font_driver_list; list; list = list->next)
3584 {
3585 struct font_driver *driver = list->driver;
3586 eassert (! list->on);
3587 if (! driver->start_for_frame
3588 || driver->start_for_frame (f) == 0)
3589 {
3590 font_prepare_cache (f, driver);
3591 list->on = 1;
3592 }
3593 }
3594 }
3595 }
3596
3597 for (list = f->font_driver_list; list; list = list->next)
3598 if (list->on)
3599 active_drivers = nconc2 (active_drivers, list1 (list->driver->type));
3600 return active_drivers;
3601 }
3602
3603 #if defined (HAVE_XFT) || defined (HAVE_FREETYPE)
3604
3605 static void
3606 fset_font_data (struct frame *f, Lisp_Object val)
3607 {
3608 f->font_data = val;
3609 }
3610
3611 void
3612 font_put_frame_data (struct frame *f, Lisp_Object driver, void *data)
3613 {
3614 Lisp_Object val = assq_no_quit (driver, f->font_data);
3615
3616 if (!data)
3617 fset_font_data (f, Fdelq (val, f->font_data));
3618 else
3619 {
3620 if (NILP (val))
3621 fset_font_data (f, Fcons (Fcons (driver, make_save_ptr (data)),
3622 f->font_data));
3623 else
3624 XSETCDR (val, make_save_ptr (data));
3625 }
3626 }
3627
3628 void *
3629 font_get_frame_data (struct frame *f, Lisp_Object driver)
3630 {
3631 Lisp_Object val = assq_no_quit (driver, f->font_data);
3632
3633 return NILP (val) ? NULL : XSAVE_POINTER (XCDR (val), 0);
3634 }
3635
3636 #endif /* HAVE_XFT || HAVE_FREETYPE */
3637
3638 /* Sets attributes on a font. Any properties that appear in ALIST and
3639 BOOLEAN_PROPERTIES or NON_BOOLEAN_PROPERTIES are set on the font.
3640 BOOLEAN_PROPERTIES and NON_BOOLEAN_PROPERTIES are NULL-terminated
3641 arrays of strings. This function is intended for use by the font
3642 drivers to implement their specific font_filter_properties. */
3643 void
3644 font_filter_properties (Lisp_Object font,
3645 Lisp_Object alist,
3646 const char *const boolean_properties[],
3647 const char *const non_boolean_properties[])
3648 {
3649 Lisp_Object it;
3650 int i;
3651
3652 /* Set boolean values to Qt or Qnil. */
3653 for (i = 0; boolean_properties[i] != NULL; ++i)
3654 for (it = alist; ! NILP (it); it = XCDR (it))
3655 {
3656 Lisp_Object key = XCAR (XCAR (it));
3657 Lisp_Object val = XCDR (XCAR (it));
3658 char *keystr = SSDATA (SYMBOL_NAME (key));
3659
3660 if (strcmp (boolean_properties[i], keystr) == 0)
3661 {
3662 const char *str = INTEGERP (val) ? (XINT (val) ? "true" : "false")
3663 : SYMBOLP (val) ? SSDATA (SYMBOL_NAME (val))
3664 : "true";
3665
3666 if (strcmp ("false", str) == 0 || strcmp ("False", str) == 0
3667 || strcmp ("FALSE", str) == 0 || strcmp ("FcFalse", str) == 0
3668 || strcmp ("off", str) == 0 || strcmp ("OFF", str) == 0
3669 || strcmp ("Off", str) == 0)
3670 val = Qnil;
3671 else
3672 val = Qt;
3673
3674 Ffont_put (font, key, val);
3675 }
3676 }
3677
3678 for (i = 0; non_boolean_properties[i] != NULL; ++i)
3679 for (it = alist; ! NILP (it); it = XCDR (it))
3680 {
3681 Lisp_Object key = XCAR (XCAR (it));
3682 Lisp_Object val = XCDR (XCAR (it));
3683 char *keystr = SSDATA (SYMBOL_NAME (key));
3684 if (strcmp (non_boolean_properties[i], keystr) == 0)
3685 Ffont_put (font, key, val);
3686 }
3687 }
3688
3689
3690 /* Return the font used to draw character C by FACE at buffer position
3691 POS in window W. If STRING is non-nil, it is a string containing C
3692 at index POS. If C is negative, get C from the current buffer or
3693 STRING. */
3694
3695 static Lisp_Object
3696 font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
3697 Lisp_Object string)
3698 {
3699 struct frame *f;
3700 bool multibyte;
3701 Lisp_Object font_object;
3702
3703 multibyte = (NILP (string)
3704 ? ! NILP (BVAR (current_buffer, enable_multibyte_characters))
3705 : STRING_MULTIBYTE (string));
3706 if (c < 0)
3707 {
3708 if (NILP (string))
3709 {
3710 if (multibyte)
3711 {
3712 ptrdiff_t pos_byte = CHAR_TO_BYTE (pos);
3713
3714 c = FETCH_CHAR (pos_byte);
3715 }
3716 else
3717 c = FETCH_BYTE (pos);
3718 }
3719 else
3720 {
3721 unsigned char *str;
3722
3723 multibyte = STRING_MULTIBYTE (string);
3724 if (multibyte)
3725 {
3726 ptrdiff_t pos_byte = string_char_to_byte (string, pos);
3727
3728 str = SDATA (string) + pos_byte;
3729 c = STRING_CHAR (str);
3730 }
3731 else
3732 c = SDATA (string)[pos];
3733 }
3734 }
3735
3736 f = XFRAME (w->frame);
3737 if (! FRAME_WINDOW_P (f))
3738 return Qnil;
3739 if (! face)
3740 {
3741 int face_id;
3742 ptrdiff_t endptr;
3743
3744 if (STRINGP (string))
3745 face_id = face_at_string_position (w, string, pos, 0, &endptr,
3746 DEFAULT_FACE_ID, false);
3747 else
3748 face_id = face_at_buffer_position (w, pos, &endptr,
3749 pos + 100, false, -1);
3750 face = FACE_FROM_ID (f, face_id);
3751 }
3752 if (multibyte)
3753 {
3754 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3755 face = FACE_FROM_ID (f, face_id);
3756 }
3757 if (! face->font)
3758 return Qnil;
3759
3760 XSETFONT (font_object, face->font);
3761 return font_object;
3762 }
3763
3764
3765 #ifdef HAVE_WINDOW_SYSTEM
3766
3767 /* Check how many characters after character/byte position POS/POS_BYTE
3768 (at most to *LIMIT) can be displayed by the same font in the window W.
3769 FACE, if non-NULL, is the face selected for the character at POS.
3770 If STRING is not nil, it is the string to check instead of the current
3771 buffer. In that case, FACE must be not NULL.
3772
3773 The return value is the font-object for the character at POS.
3774 *LIMIT is set to the position where that font can't be used.
3775
3776 It is assured that the current buffer (or STRING) is multibyte. */
3777
3778 Lisp_Object
3779 font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
3780 struct window *w, struct face *face, Lisp_Object string)
3781 {
3782 ptrdiff_t ignore;
3783 int c;
3784 Lisp_Object font_object = Qnil;
3785
3786 if (NILP (string))
3787 {
3788 if (! face)
3789 {
3790 int face_id;
3791
3792 face_id = face_at_buffer_position (w, pos, &ignore,
3793 *limit, false, -1);
3794 face = FACE_FROM_ID (XFRAME (w->frame), face_id);
3795 }
3796 }
3797 else
3798 eassert (face);
3799
3800 while (pos < *limit)
3801 {
3802 Lisp_Object category;
3803
3804 if (NILP (string))
3805 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3806 else
3807 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3808 category = CHAR_TABLE_REF (Vunicode_category_table, c);
3809 if (INTEGERP (category)
3810 && (XINT (category) == UNICODE_CATEGORY_Cf
3811 || CHAR_VARIATION_SELECTOR_P (c)))
3812 continue;
3813 if (NILP (font_object))
3814 {
3815 font_object = font_for_char (face, c, pos - 1, string);
3816 if (NILP (font_object))
3817 return Qnil;
3818 continue;
3819 }
3820 if (font_encode_char (font_object, c) == FONT_INVALID_CODE)
3821 *limit = pos - 1;
3822 }
3823 return font_object;
3824 }
3825 #endif
3826
3827 \f
3828 /* Lisp API. */
3829
3830 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3831 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3832 Return nil otherwise.
3833 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3834 which kind of font it is. It must be one of `font-spec', `font-entity',
3835 `font-object'. */)
3836 (Lisp_Object object, Lisp_Object extra_type)
3837 {
3838 if (NILP (extra_type))
3839 return (FONTP (object) ? Qt : Qnil);
3840 if (EQ (extra_type, Qfont_spec))
3841 return (FONT_SPEC_P (object) ? Qt : Qnil);
3842 if (EQ (extra_type, Qfont_entity))
3843 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3844 if (EQ (extra_type, Qfont_object))
3845 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3846 wrong_type_argument (intern ("font-extra-type"), extra_type);
3847 }
3848
3849 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3850 doc: /* Return a newly created font-spec with arguments as properties.
3851
3852 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3853 valid font property name listed below:
3854
3855 `:family', `:weight', `:slant', `:width'
3856
3857 They are the same as face attributes of the same name. See
3858 `set-face-attribute'.
3859
3860 `:foundry'
3861
3862 VALUE must be a string or a symbol specifying the font foundry, e.g. `misc'.
3863
3864 `:adstyle'
3865
3866 VALUE must be a string or a symbol specifying the additional
3867 typographic style information of a font, e.g. `sans'.
3868
3869 `:registry'
3870
3871 VALUE must be a string or a symbol specifying the charset registry and
3872 encoding of a font, e.g. `iso8859-1'.
3873
3874 `:size'
3875
3876 VALUE must be a non-negative integer or a floating point number
3877 specifying the font size. It specifies the font size in pixels (if
3878 VALUE is an integer), or in points (if VALUE is a float).
3879
3880 `:name'
3881
3882 VALUE must be a string of XLFD-style or fontconfig-style font name.
3883
3884 `:script'
3885
3886 VALUE must be a symbol representing a script that the font must
3887 support. It may be a symbol representing a subgroup of a script
3888 listed in the variable `script-representative-chars'.
3889
3890 `:lang'
3891
3892 VALUE must be a symbol whose name is a two-letter ISO-639 language
3893 name, e.g. `ja'. The value is matched against the "Additional Style"
3894 field of the XLFD spec of a font, if it's non-empty, on X, and
3895 against the codepages supported by the font on w32.
3896
3897 `:otf'
3898
3899 VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
3900 required OpenType features.
3901
3902 SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
3903 LANGSYS-TAG: OpenType language system tag symbol,
3904 or nil for the default language system.
3905 GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
3906 GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
3907
3908 GSUB and GPOS may contain nil elements. In such a case, the font
3909 must not have any of the remaining elements.
3910
3911 For instance, if the VALUE is `(thai nil nil (mark))', the font must
3912 be an OpenType font whose GPOS table of `thai' script's default
3913 language system must contain `mark' feature.
3914
3915 usage: (font-spec ARGS...) */)
3916 (ptrdiff_t nargs, Lisp_Object *args)
3917 {
3918 Lisp_Object spec = font_make_spec ();
3919 ptrdiff_t i;
3920
3921 for (i = 0; i < nargs; i += 2)
3922 {
3923 Lisp_Object key = args[i], val;
3924
3925 CHECK_SYMBOL (key);
3926 if (i + 1 >= nargs)
3927 error ("No value for key `%s'", SDATA (SYMBOL_NAME (key)));
3928 val = args[i + 1];
3929
3930 if (EQ (key, QCname))
3931 {
3932 CHECK_STRING (val);
3933 if (font_parse_name (SSDATA (val), SBYTES (val), spec) < 0)
3934 error ("Invalid font name: %s", SSDATA (val));
3935 font_put_extra (spec, key, val);
3936 }
3937 else
3938 {
3939 int idx = get_font_prop_index (key);
3940
3941 if (idx >= 0)
3942 {
3943 val = font_prop_validate (idx, Qnil, val);
3944 if (idx < FONT_EXTRA_INDEX)
3945 ASET (spec, idx, val);
3946 else
3947 font_put_extra (spec, key, val);
3948 }
3949 else
3950 font_put_extra (spec, key, font_prop_validate (0, key, val));
3951 }
3952 }
3953 return spec;
3954 }
3955
3956 /* Return a copy of FONT as a font-spec. For the sake of speed, this code
3957 relies on an internal stuff exposed from alloc.c and should be handled
3958 with care. */
3959
3960 Lisp_Object
3961 copy_font_spec (Lisp_Object font)
3962 {
3963 enum { font_spec_size = VECSIZE (struct font_spec) };
3964 Lisp_Object new_spec, tail, *pcdr;
3965 struct font_spec *spec;
3966
3967 CHECK_FONT (font);
3968
3969 /* Make an uninitialized font-spec object. */
3970 spec = (struct font_spec *) allocate_vector (font_spec_size);
3971 XSETPVECTYPESIZE (spec, PVEC_FONT, FONT_SPEC_MAX,
3972 font_spec_size - FONT_SPEC_MAX);
3973
3974 spec->props[FONT_TYPE_INDEX] = spec->props[FONT_EXTRA_INDEX] = Qnil;
3975
3976 /* Copy basic properties FONT_FOUNDRY_INDEX..FONT_AVGWIDTH_INDEX. */
3977 memcpy (spec->props + 1, XVECTOR (font)->contents + 1,
3978 (FONT_EXTRA_INDEX - 1) * word_size);
3979
3980 /* Copy an alist of extra information but discard :font-entity property. */
3981 pcdr = spec->props + FONT_EXTRA_INDEX;
3982 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3983 if (!EQ (XCAR (XCAR (tail)), QCfont_entity))
3984 {
3985 *pcdr = Fcons (Fcons (XCAR (XCAR (tail)), CDR (XCAR (tail))), Qnil);
3986 pcdr = xcdr_addr (*pcdr);
3987 }
3988
3989 XSETFONT (new_spec, spec);
3990 return new_spec;
3991 }
3992
3993 /* Merge font-specs FROM and TO, and return a new font-spec.
3994 Every specified property in FROM overrides the corresponding
3995 property in TO. */
3996 Lisp_Object
3997 merge_font_spec (Lisp_Object from, Lisp_Object to)
3998 {
3999 Lisp_Object extra, tail;
4000 int i;
4001
4002 CHECK_FONT (from);
4003 CHECK_FONT (to);
4004 to = copy_font_spec (to);
4005 for (i = 0; i < FONT_EXTRA_INDEX; i++)
4006 ASET (to, i, AREF (from, i));
4007 extra = AREF (to, FONT_EXTRA_INDEX);
4008 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
4009 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
4010 {
4011 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
4012
4013 if (! NILP (slot))
4014 XSETCDR (slot, XCDR (XCAR (tail)));
4015 else
4016 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
4017 }
4018 ASET (to, FONT_EXTRA_INDEX, extra);
4019 return to;
4020 }
4021
4022 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
4023 doc: /* Return the value of FONT's property KEY.
4024 FONT is a font-spec, a font-entity, or a font-object.
4025 KEY is any symbol, but these are reserved for specific meanings:
4026 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
4027 :size, :name, :script, :otf
4028 See the documentation of `font-spec' for their meanings.
4029 In addition, if FONT is a font-entity or a font-object, values of
4030 :script and :otf are different from those of a font-spec as below:
4031
4032 The value of :script may be a list of scripts that are supported by the font.
4033
4034 The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
4035 representing the OpenType features supported by the font by this form:
4036 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4037 SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
4038 Layout tags. */)
4039 (Lisp_Object font, Lisp_Object key)
4040 {
4041 int idx;
4042 Lisp_Object val;
4043
4044 CHECK_FONT (font);
4045 CHECK_SYMBOL (key);
4046
4047 idx = get_font_prop_index (key);
4048 if (idx >= FONT_WEIGHT_INDEX && idx <= FONT_WIDTH_INDEX)
4049 return font_style_symbolic (font, idx, 0);
4050 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4051 return AREF (font, idx);
4052 val = Fassq (key, AREF (font, FONT_EXTRA_INDEX));
4053 if (NILP (val) && EQ (key, QCotf) && FONT_OBJECT_P (font))
4054 {
4055 struct font *fontp = XFONT_OBJECT (font);
4056
4057 if (fontp->driver->otf_capability)
4058 val = fontp->driver->otf_capability (fontp);
4059 else
4060 val = Fcons (Qnil, Qnil);
4061 }
4062 else
4063 val = Fcdr (val);
4064 return val;
4065 }
4066
4067 #ifdef HAVE_WINDOW_SYSTEM
4068
4069 DEFUN ("font-face-attributes", Ffont_face_attributes, Sfont_face_attributes, 1, 2, 0,
4070 doc: /* Return a plist of face attributes generated by FONT.
4071 FONT is a font name, a font-spec, a font-entity, or a font-object.
4072 The return value is a list of the form
4073
4074 (:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
4075
4076 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
4077 compatible with `set-face-attribute'. Some of these key-attribute pairs
4078 may be omitted from the list if they are not specified by FONT.
4079
4080 The optional argument FRAME specifies the frame that the face attributes
4081 are to be displayed on. If omitted, the selected frame is used. */)
4082 (Lisp_Object font, Lisp_Object frame)
4083 {
4084 struct frame *f = decode_live_frame (frame);
4085 Lisp_Object plist[10];
4086 Lisp_Object val;
4087 int n = 0;
4088
4089 if (STRINGP (font))
4090 {
4091 int fontset = fs_query_fontset (font, 0);
4092 Lisp_Object name = font;
4093 if (fontset >= 0)
4094 font = fontset_ascii (fontset);
4095 font = font_spec_from_name (name);
4096 if (! FONTP (font))
4097 signal_error ("Invalid font name", name);
4098 }
4099 else if (! FONTP (font))
4100 signal_error ("Invalid font object", font);
4101
4102 val = AREF (font, FONT_FAMILY_INDEX);
4103 if (! NILP (val))
4104 {
4105 plist[n++] = QCfamily;
4106 plist[n++] = SYMBOL_NAME (val);
4107 }
4108
4109 val = AREF (font, FONT_SIZE_INDEX);
4110 if (INTEGERP (val))
4111 {
4112 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
4113 int dpi = INTEGERP (font_dpi) ? XINT (font_dpi) : FRAME_RES_Y (f);
4114 plist[n++] = QCheight;
4115 plist[n++] = make_number (PIXEL_TO_POINT (XINT (val) * 10, dpi));
4116 }
4117 else if (FLOATP (val))
4118 {
4119 plist[n++] = QCheight;
4120 plist[n++] = make_number (10 * (int) XFLOAT_DATA (val));
4121 }
4122
4123 val = FONT_WEIGHT_FOR_FACE (font);
4124 if (! NILP (val))
4125 {
4126 plist[n++] = QCweight;
4127 plist[n++] = val;
4128 }
4129
4130 val = FONT_SLANT_FOR_FACE (font);
4131 if (! NILP (val))
4132 {
4133 plist[n++] = QCslant;
4134 plist[n++] = val;
4135 }
4136
4137 val = FONT_WIDTH_FOR_FACE (font);
4138 if (! NILP (val))
4139 {
4140 plist[n++] = QCwidth;
4141 plist[n++] = val;
4142 }
4143
4144 return Flist (n, plist);
4145 }
4146
4147 #endif
4148
4149 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
4150 doc: /* Set one property of FONT: give property KEY value VAL.
4151 FONT is a font-spec, a font-entity, or a font-object.
4152
4153 If FONT is a font-spec, KEY can be any symbol. But if KEY is the one
4154 accepted by the function `font-spec' (which see), VAL must be what
4155 allowed in `font-spec'.
4156
4157 If FONT is a font-entity or a font-object, KEY must not be the one
4158 accepted by `font-spec'. */)
4159 (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
4160 {
4161 int idx;
4162
4163 idx = get_font_prop_index (prop);
4164 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4165 {
4166 CHECK_FONT_SPEC (font);
4167 ASET (font, idx, font_prop_validate (idx, Qnil, val));
4168 }
4169 else
4170 {
4171 if (EQ (prop, QCname)
4172 || EQ (prop, QCscript)
4173 || EQ (prop, QClang)
4174 || EQ (prop, QCotf))
4175 CHECK_FONT_SPEC (font);
4176 else
4177 CHECK_FONT (font);
4178 font_put_extra (font, prop, font_prop_validate (0, prop, val));
4179 }
4180 return val;
4181 }
4182
4183 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
4184 doc: /* List available fonts matching FONT-SPEC on the current frame.
4185 Optional 2nd argument FRAME specifies the target frame.
4186 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4187 Optional 4th argument PREFER, if non-nil, is a font-spec to
4188 control the order of the returned list. Fonts are sorted by
4189 how close they are to PREFER. */)
4190 (Lisp_Object font_spec, Lisp_Object frame, Lisp_Object num, Lisp_Object prefer)
4191 {
4192 struct frame *f = decode_live_frame (frame);
4193 Lisp_Object vec, list;
4194 EMACS_INT n = 0;
4195
4196 CHECK_FONT_SPEC (font_spec);
4197 if (! NILP (num))
4198 {
4199 CHECK_NUMBER (num);
4200 n = XINT (num);
4201 if (n <= 0)
4202 return Qnil;
4203 }
4204 if (! NILP (prefer))
4205 CHECK_FONT_SPEC (prefer);
4206
4207 list = font_list_entities (f, font_spec);
4208 if (NILP (list))
4209 return Qnil;
4210 if (NILP (XCDR (list))
4211 && ASIZE (XCAR (list)) == 1)
4212 return list1 (AREF (XCAR (list), 0));
4213
4214 if (! NILP (prefer))
4215 vec = font_sort_entities (list, prefer, f, 0);
4216 else
4217 vec = font_vconcat_entity_vectors (list);
4218 if (n == 0 || n >= ASIZE (vec))
4219 list = CALLN (Fappend, vec, Qnil);
4220 else
4221 {
4222 for (list = Qnil, n--; n >= 0; n--)
4223 list = Fcons (AREF (vec, n), list);
4224 }
4225 return list;
4226 }
4227
4228 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
4229 doc: /* List available font families on the current frame.
4230 If FRAME is omitted or nil, the selected frame is used. */)
4231 (Lisp_Object frame)
4232 {
4233 struct frame *f = decode_live_frame (frame);
4234 struct font_driver_list *driver_list;
4235 Lisp_Object list = Qnil;
4236
4237 for (driver_list = f->font_driver_list; driver_list;
4238 driver_list = driver_list->next)
4239 if (driver_list->driver->list_family)
4240 {
4241 Lisp_Object val = driver_list->driver->list_family (f);
4242 Lisp_Object tail = list;
4243
4244 for (; CONSP (val); val = XCDR (val))
4245 if (NILP (Fmemq (XCAR (val), tail))
4246 && SYMBOLP (XCAR (val)))
4247 list = Fcons (SYMBOL_NAME (XCAR (val)), list);
4248 }
4249 return list;
4250 }
4251
4252 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
4253 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
4254 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4255 (Lisp_Object font_spec, Lisp_Object frame)
4256 {
4257 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
4258
4259 if (CONSP (val))
4260 val = XCAR (val);
4261 return val;
4262 }
4263
4264 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
4265 doc: /* Return XLFD name of FONT.
4266 FONT is a font-spec, font-entity, or font-object.
4267 If the name is too long for XLFD (maximum 255 chars), return nil.
4268 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4269 the consecutive wildcards are folded into one. */)
4270 (Lisp_Object font, Lisp_Object fold_wildcards)
4271 {
4272 char name[256];
4273 int namelen, pixel_size = 0;
4274
4275 CHECK_FONT (font);
4276
4277 if (FONT_OBJECT_P (font))
4278 {
4279 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
4280
4281 if (STRINGP (font_name)
4282 && SDATA (font_name)[0] == '-')
4283 {
4284 if (NILP (fold_wildcards))
4285 return font_name;
4286 lispstpcpy (name, font_name);
4287 namelen = SBYTES (font_name);
4288 goto done;
4289 }
4290 pixel_size = XFONT_OBJECT (font)->pixel_size;
4291 }
4292 namelen = font_unparse_xlfd (font, pixel_size, name, 256);
4293 if (namelen < 0)
4294 return Qnil;
4295 done:
4296 if (! NILP (fold_wildcards))
4297 {
4298 char *p0 = name, *p1;
4299
4300 while ((p1 = strstr (p0, "-*-*")))
4301 {
4302 strcpy (p1, p1 + 2);
4303 namelen -= 2;
4304 p0 = p1;
4305 }
4306 }
4307
4308 return make_string (name, namelen);
4309 }
4310
4311 void
4312 clear_font_cache (struct frame *f)
4313 {
4314 struct font_driver_list *driver_list = f->font_driver_list;
4315
4316 for (; driver_list; driver_list = driver_list->next)
4317 if (driver_list->on)
4318 {
4319 Lisp_Object val, tmp, cache = driver_list->driver->get_cache (f);
4320
4321 val = XCDR (cache);
4322 while (! NILP (val)
4323 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
4324 val = XCDR (val);
4325 eassert (! NILP (val));
4326 tmp = XCDR (XCAR (val));
4327 if (XINT (XCAR (tmp)) == 0)
4328 {
4329 font_clear_cache (f, XCAR (val), driver_list->driver);
4330 XSETCDR (cache, XCDR (val));
4331 }
4332 }
4333 }
4334
4335 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
4336 doc: /* Clear font cache of each frame. */)
4337 (void)
4338 {
4339 Lisp_Object list, frame;
4340
4341 FOR_EACH_FRAME (list, frame)
4342 clear_font_cache (XFRAME (frame));
4343
4344 return Qnil;
4345 }
4346
4347 \f
4348 void
4349 font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object)
4350 {
4351 struct font *font = XFONT_OBJECT (font_object);
4352 unsigned code = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
4353 struct font_metrics metrics;
4354
4355 LGLYPH_SET_CODE (glyph, code);
4356 font->driver->text_extents (font, &code, 1, &metrics);
4357 LGLYPH_SET_LBEARING (glyph, metrics.lbearing);
4358 LGLYPH_SET_RBEARING (glyph, metrics.rbearing);
4359 LGLYPH_SET_WIDTH (glyph, metrics.width);
4360 LGLYPH_SET_ASCENT (glyph, metrics.ascent);
4361 LGLYPH_SET_DESCENT (glyph, metrics.descent);
4362 }
4363
4364
4365 DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0,
4366 doc: /* Shape the glyph-string GSTRING.
4367 Shaping means substituting glyphs and/or adjusting positions of glyphs
4368 to get the correct visual image of character sequences set in the
4369 header of the glyph-string.
4370
4371 If the shaping was successful, the value is GSTRING itself or a newly
4372 created glyph-string. Otherwise, the value is nil.
4373
4374 See the documentation of `composition-get-gstring' for the format of
4375 GSTRING. */)
4376 (Lisp_Object gstring)
4377 {
4378 struct font *font;
4379 Lisp_Object font_object, n, glyph;
4380 ptrdiff_t i, from, to;
4381
4382 if (! composition_gstring_p (gstring))
4383 signal_error ("Invalid glyph-string: ", gstring);
4384 if (! NILP (LGSTRING_ID (gstring)))
4385 return gstring;
4386 font_object = LGSTRING_FONT (gstring);
4387 CHECK_FONT_OBJECT (font_object);
4388 font = XFONT_OBJECT (font_object);
4389 if (! font->driver->shape)
4390 return Qnil;
4391
4392 /* Try at most three times with larger gstring each time. */
4393 for (i = 0; i < 3; i++)
4394 {
4395 n = font->driver->shape (gstring);
4396 if (INTEGERP (n))
4397 break;
4398 gstring = larger_vector (gstring,
4399 LGSTRING_GLYPH_LEN (gstring), -1);
4400 }
4401 if (i == 3 || XINT (n) == 0)
4402 return Qnil;
4403 if (XINT (n) < LGSTRING_GLYPH_LEN (gstring))
4404 LGSTRING_SET_GLYPH (gstring, XINT (n), Qnil);
4405
4406 /* Check FROM_IDX and TO_IDX of each GLYPH in GSTRING to assure that
4407 GLYPHS covers all characters (except for the last few ones) in
4408 GSTRING. More formally, provided that NCHARS is the number of
4409 characters in GSTRING and GLYPHS[i] is the ith glyph, FROM_IDX
4410 and TO_IDX of each glyph must satisfy these conditions:
4411
4412 GLYPHS[0].FROM_IDX == 0
4413 GLYPHS[i].FROM_IDX <= GLYPHS[i].TO_IDX
4414 if (GLYPHS[i].FROM_IDX == GLYPHS[i-1].FROM_IDX)
4415 ;; GLYPHS[i] and GLYPHS[i-1] belongs to the same grapheme cluster
4416 GLYPHS[i].TO_IDX == GLYPHS[i-1].TO_IDX
4417 else
4418 ;; Be sure to cover all characters.
4419 GLYPHS[i].FROM_IDX == GLYPHS[i-1].TO_IDX + 1 */
4420 glyph = LGSTRING_GLYPH (gstring, 0);
4421 from = LGLYPH_FROM (glyph);
4422 to = LGLYPH_TO (glyph);
4423 if (from != 0 || to < from)
4424 goto shaper_error;
4425 for (i = 1; i < LGSTRING_GLYPH_LEN (gstring); i++)
4426 {
4427 glyph = LGSTRING_GLYPH (gstring, i);
4428 if (NILP (glyph))
4429 break;
4430 if (! (LGLYPH_FROM (glyph) <= LGLYPH_TO (glyph)
4431 && (LGLYPH_FROM (glyph) == from
4432 ? LGLYPH_TO (glyph) == to
4433 : LGLYPH_FROM (glyph) == to + 1)))
4434 goto shaper_error;
4435 from = LGLYPH_FROM (glyph);
4436 to = LGLYPH_TO (glyph);
4437 }
4438 return composition_gstring_put_cache (gstring, XINT (n));
4439
4440 shaper_error:
4441 return Qnil;
4442 }
4443
4444 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
4445 2, 2, 0,
4446 doc: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4447 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4448 where
4449 VARIATION-SELECTOR is a character code of variation selection
4450 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4451 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4452 (Lisp_Object font_object, Lisp_Object character)
4453 {
4454 unsigned variations[256];
4455 struct font *font;
4456 int i, n;
4457 Lisp_Object val;
4458
4459 CHECK_FONT_OBJECT (font_object);
4460 CHECK_CHARACTER (character);
4461 font = XFONT_OBJECT (font_object);
4462 if (! font->driver->get_variation_glyphs)
4463 return Qnil;
4464 n = font->driver->get_variation_glyphs (font, XINT (character), variations);
4465 if (! n)
4466 return Qnil;
4467 val = Qnil;
4468 for (i = 0; i < 255; i++)
4469 if (variations[i])
4470 {
4471 int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
4472 Lisp_Object code = INTEGER_TO_CONS (variations[i]);
4473 val = Fcons (Fcons (make_number (vs), code), val);
4474 }
4475 return val;
4476 }
4477
4478 /* Return a description of the font at POSITION in the current buffer.
4479 If the 2nd optional arg CH is non-nil, it is a character to check
4480 the font instead of the character at POSITION.
4481
4482 For a graphical display, return a cons (FONT-OBJECT . GLYPH-CODE).
4483 FONT-OBJECT is the font for the character at POSITION in the current
4484 buffer. This is computed from all the text properties and overlays
4485 that apply to POSITION. POSITION may be nil, in which case,
4486 FONT-SPEC is the font for displaying the character CH with the
4487 default face. GLYPH-CODE is the glyph code in the font to use for
4488 the character.
4489
4490 For a text terminal, return a nonnegative integer glyph code for
4491 the character, or a negative integer if the character is not
4492 displayable. Terminal glyph codes are system-dependent integers
4493 that represent displayable characters: for example, on a Linux x86
4494 console they represent VGA code points.
4495
4496 It returns nil in the following cases:
4497
4498 (1) The window system doesn't have a font for the character (thus
4499 it is displayed by an empty box).
4500
4501 (2) The character code is invalid.
4502
4503 (3) If POSITION is not nil, and the current buffer is not displayed
4504 in any window.
4505
4506 (4) For a text terminal, the terminal does not report glyph codes.
4507
4508 In addition, the returned font name may not take into account of
4509 such redisplay engine hooks as what used in jit-lock-mode if
4510 POSITION is currently not visible. */
4511
4512
4513 DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
4514 doc: /* For internal use only. */)
4515 (Lisp_Object position, Lisp_Object ch)
4516 {
4517 ptrdiff_t pos, pos_byte, dummy;
4518 int face_id;
4519 int c;
4520 struct frame *f;
4521
4522 if (NILP (position))
4523 {
4524 CHECK_CHARACTER (ch);
4525 c = XINT (ch);
4526 f = XFRAME (selected_frame);
4527 face_id = lookup_basic_face (f, DEFAULT_FACE_ID);
4528 pos = -1;
4529 }
4530 else
4531 {
4532 Lisp_Object window;
4533 struct window *w;
4534
4535 CHECK_NUMBER_COERCE_MARKER (position);
4536 if (! (BEGV <= XINT (position) && XINT (position) < ZV))
4537 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4538 pos = XINT (position);
4539 pos_byte = CHAR_TO_BYTE (pos);
4540 if (NILP (ch))
4541 c = FETCH_CHAR (pos_byte);
4542 else
4543 {
4544 CHECK_NATNUM (ch);
4545 c = XINT (ch);
4546 }
4547 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
4548 if (NILP (window))
4549 return Qnil;
4550 w = XWINDOW (window);
4551 f = XFRAME (w->frame);
4552 face_id = face_at_buffer_position (w, pos, &dummy,
4553 pos + 100, false, -1);
4554 }
4555 if (! CHAR_VALID_P (c))
4556 return Qnil;
4557
4558 if (! FRAME_WINDOW_P (f))
4559 return terminal_glyph_code (FRAME_TERMINAL (f), c);
4560
4561 /* We need the basic faces to be valid below, so recompute them if
4562 some code just happened to clear the face cache. */
4563 if (FRAME_FACE_CACHE (f)->used == 0)
4564 recompute_basic_faces (f);
4565
4566 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
4567 struct face *face = FACE_FROM_ID (f, face_id);
4568 if (! face->font)
4569 return Qnil;
4570 unsigned code = face->font->driver->encode_char (face->font, c);
4571 if (code == FONT_INVALID_CODE)
4572 return Qnil;
4573 Lisp_Object font_object;
4574 XSETFONT (font_object, face->font);
4575 return Fcons (font_object, INTEGER_TO_CONS (code));
4576 }
4577
4578 #if 0
4579
4580 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
4581 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
4582 OTF-FEATURES specifies which features to apply in this format:
4583 (SCRIPT LANGSYS GSUB GPOS)
4584 where
4585 SCRIPT is a symbol specifying a script tag of OpenType,
4586 LANGSYS is a symbol specifying a langsys tag of OpenType,
4587 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4588
4589 If LANGSYS is nil, the default langsys is selected.
4590
4591 The features are applied in the order they appear in the list. The
4592 symbol `*' means to apply all available features not present in this
4593 list, and the remaining features are ignored. For instance, (vatu
4594 pstf * haln) is to apply vatu and pstf in this order, then to apply
4595 all available features other than vatu, pstf, and haln.
4596
4597 The features are applied to the glyphs in the range FROM and TO of
4598 the glyph-string GSTRING-IN.
4599
4600 If some feature is actually applicable, the resulting glyphs are
4601 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4602 this case, the value is the number of produced glyphs.
4603
4604 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4605 the value is 0.
4606
4607 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4608 produced in GSTRING-OUT, and the value is nil.
4609
4610 See the documentation of `composition-get-gstring' for the format of
4611 glyph-string. */)
4612 (Lisp_Object otf_features, Lisp_Object gstring_in, Lisp_Object from, Lisp_Object to, Lisp_Object gstring_out, Lisp_Object index)
4613 {
4614 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
4615 Lisp_Object val;
4616 struct font *font;
4617 int len, num;
4618
4619 check_otf_features (otf_features);
4620 CHECK_FONT_OBJECT (font_object);
4621 font = XFONT_OBJECT (font_object);
4622 if (! font->driver->otf_drive)
4623 error ("Font backend %s can't drive OpenType GSUB table",
4624 SDATA (SYMBOL_NAME (font->driver->type)));
4625 CHECK_CONS (otf_features);
4626 CHECK_SYMBOL (XCAR (otf_features));
4627 val = XCDR (otf_features);
4628 CHECK_SYMBOL (XCAR (val));
4629 val = XCDR (otf_features);
4630 if (! NILP (val))
4631 CHECK_CONS (val);
4632 len = check_gstring (gstring_in);
4633 CHECK_VECTOR (gstring_out);
4634 CHECK_NATNUM (from);
4635 CHECK_NATNUM (to);
4636 CHECK_NATNUM (index);
4637
4638 if (XINT (from) >= XINT (to) || XINT (to) > len)
4639 args_out_of_range_3 (from, to, make_number (len));
4640 if (XINT (index) >= ASIZE (gstring_out))
4641 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4642 num = font->driver->otf_drive (font, otf_features,
4643 gstring_in, XINT (from), XINT (to),
4644 gstring_out, XINT (index), 0);
4645 if (num < 0)
4646 return Qnil;
4647 return make_number (num);
4648 }
4649
4650 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4651 3, 3, 0,
4652 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4653 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4654 in this format:
4655 (SCRIPT LANGSYS FEATURE ...)
4656 See the documentation of `font-drive-otf' for more detail.
4657
4658 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4659 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4660 character code corresponding to the glyph or nil if there's no
4661 corresponding character. */)
4662 (Lisp_Object font_object, Lisp_Object character, Lisp_Object otf_features)
4663 {
4664 struct font *font = CHECK_FONT_GET_OBJECT (font_object);
4665 Lisp_Object gstring_in, gstring_out, g;
4666 Lisp_Object alternates;
4667 int i, num;
4668
4669 if (! font->driver->otf_drive)
4670 error ("Font backend %s can't drive OpenType GSUB table",
4671 SDATA (SYMBOL_NAME (font->driver->type)));
4672 CHECK_CHARACTER (character);
4673 CHECK_CONS (otf_features);
4674
4675 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4676 g = LGSTRING_GLYPH (gstring_in, 0);
4677 LGLYPH_SET_CHAR (g, XINT (character));
4678 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4679 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4680 gstring_out, 0, 1)) < 0)
4681 gstring_out = Ffont_make_gstring (font_object,
4682 make_number (ASIZE (gstring_out) * 2));
4683 alternates = Qnil;
4684 for (i = 0; i < num; i++)
4685 {
4686 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4687 int c = LGLYPH_CHAR (g);
4688 unsigned code = LGLYPH_CODE (g);
4689
4690 alternates = Fcons (Fcons (make_number (code),
4691 c > 0 ? make_number (c) : Qnil),
4692 alternates);
4693 }
4694 return Fnreverse (alternates);
4695 }
4696 #endif /* 0 */
4697
4698 #ifdef FONT_DEBUG
4699
4700 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4701 doc: /* Open FONT-ENTITY. */)
4702 (Lisp_Object font_entity, Lisp_Object size, Lisp_Object frame)
4703 {
4704 EMACS_INT isize;
4705 struct frame *f = decode_live_frame (frame);
4706
4707 CHECK_FONT_ENTITY (font_entity);
4708
4709 if (NILP (size))
4710 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4711 else
4712 {
4713 CHECK_NUMBER_OR_FLOAT (size);
4714 if (FLOATP (size))
4715 isize = POINT_TO_PIXEL (XFLOAT_DATA (size), FRAME_RES_Y (f));
4716 else
4717 isize = XINT (size);
4718 if (! (INT_MIN <= isize && isize <= INT_MAX))
4719 args_out_of_range (font_entity, size);
4720 if (isize == 0)
4721 isize = 120;
4722 }
4723 return font_open_entity (f, font_entity, isize);
4724 }
4725
4726 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4727 doc: /* Close FONT-OBJECT. */)
4728 (Lisp_Object font_object, Lisp_Object frame)
4729 {
4730 CHECK_FONT_OBJECT (font_object);
4731 font_close_object (decode_live_frame (frame), font_object);
4732 return Qnil;
4733 }
4734
4735 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4736 doc: /* Return information about FONT-OBJECT.
4737 The value is a vector:
4738 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4739 CAPABILITY ]
4740
4741 NAME is the font name, a string (or nil if the font backend doesn't
4742 provide a name).
4743
4744 FILENAME is the font file name, a string (or nil if the font backend
4745 doesn't provide a file name).
4746
4747 PIXEL-SIZE is a pixel size by which the font is opened.
4748
4749 SIZE is a maximum advance width of the font in pixels.
4750
4751 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4752 pixels.
4753
4754 CAPABILITY is a list whose first element is a symbol representing the
4755 font format (x, opentype, truetype, type1, pcf, or bdf) and the
4756 remaining elements describe the details of the font capability.
4757
4758 If the font is OpenType font, the form of the list is
4759 (opentype GSUB GPOS)
4760 where GSUB shows which "GSUB" features the font supports, and GPOS
4761 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4762 lists of the format:
4763 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4764
4765 If the font is not OpenType font, currently the length of the form is
4766 one.
4767
4768 SCRIPT is a symbol representing OpenType script tag.
4769
4770 LANGSYS is a symbol representing OpenType langsys tag, or nil
4771 representing the default langsys.
4772
4773 FEATURE is a symbol representing OpenType feature tag.
4774
4775 If the font is not OpenType font, CAPABILITY is nil. */)
4776 (Lisp_Object font_object)
4777 {
4778 struct font *font = CHECK_FONT_GET_OBJECT (font_object);
4779 Lisp_Object val = make_uninit_vector (9);
4780
4781 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4782 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4783 ASET (val, 2, make_number (font->pixel_size));
4784 ASET (val, 3, make_number (font->max_width));
4785 ASET (val, 4, make_number (font->ascent));
4786 ASET (val, 5, make_number (font->descent));
4787 ASET (val, 6, make_number (font->space_width));
4788 ASET (val, 7, make_number (font->average_width));
4789 if (font->driver->otf_capability)
4790 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4791 else
4792 ASET (val, 8, Qnil);
4793 return val;
4794 }
4795
4796 DEFUN ("font-get-glyphs", Ffont_get_glyphs, Sfont_get_glyphs, 3, 4, 0,
4797 doc:
4798 /* Return a vector of FONT-OBJECT's glyphs for the specified characters.
4799 FROM and TO are positions (integers or markers) specifying a region
4800 of the current buffer, and can be in either order. If the optional
4801 fourth arg OBJECT is not nil, it is a string or a vector containing
4802 the target characters between indices FROM and TO, which are treated
4803 as in `substring'.
4804
4805 Each element is a vector containing information of a glyph in this format:
4806 [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
4807 where
4808 FROM is an index numbers of a character the glyph corresponds to.
4809 TO is the same as FROM.
4810 C is the character of the glyph.
4811 CODE is the glyph-code of C in FONT-OBJECT.
4812 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
4813 ADJUSTMENT is always nil.
4814 If FONT-OBJECT doesn't have a glyph for a character,
4815 the corresponding element is nil. */)
4816 (Lisp_Object font_object, Lisp_Object from, Lisp_Object to,
4817 Lisp_Object object)
4818 {
4819 struct font *font = CHECK_FONT_GET_OBJECT (font_object);
4820 ptrdiff_t i, len;
4821 Lisp_Object *chars, vec;
4822 USE_SAFE_ALLOCA;
4823
4824 if (NILP (object))
4825 {
4826 ptrdiff_t charpos, bytepos;
4827
4828 validate_region (&from, &to);
4829 if (EQ (from, to))
4830 return Qnil;
4831 len = XFASTINT (to) - XFASTINT (from);
4832 SAFE_ALLOCA_LISP (chars, len);
4833 charpos = XFASTINT (from);
4834 bytepos = CHAR_TO_BYTE (charpos);
4835 for (i = 0; charpos < XFASTINT (to); i++)
4836 {
4837 int c;
4838 FETCH_CHAR_ADVANCE (c, charpos, bytepos);
4839 chars[i] = make_number (c);
4840 }
4841 }
4842 else if (STRINGP (object))
4843 {
4844 const unsigned char *p;
4845 ptrdiff_t ifrom, ito;
4846
4847 validate_subarray (object, from, to, SCHARS (object), &ifrom, &ito);
4848 if (ifrom == ito)
4849 return Qnil;
4850 len = ito - ifrom;
4851 SAFE_ALLOCA_LISP (chars, len);
4852 p = SDATA (object);
4853 if (STRING_MULTIBYTE (object))
4854 {
4855 int c;
4856
4857 /* Skip IFROM characters from the beginning. */
4858 for (i = 0; i < ifrom; i++)
4859 c = STRING_CHAR_ADVANCE (p);
4860
4861 /* Now fetch an interesting characters. */
4862 for (i = 0; i < len; i++)
4863 {
4864 c = STRING_CHAR_ADVANCE (p);
4865 chars[i] = make_number (c);
4866 }
4867 }
4868 else
4869 for (i = 0; i < len; i++)
4870 chars[i] = make_number (p[ifrom + i]);
4871 }
4872 else if (VECTORP (object))
4873 {
4874 ptrdiff_t ifrom, ito;
4875
4876 validate_subarray (object, from, to, ASIZE (object), &ifrom, &ito);
4877 if (ifrom == ito)
4878 return Qnil;
4879 len = ito - ifrom;
4880 for (i = 0; i < len; i++)
4881 {
4882 Lisp_Object elt = AREF (object, ifrom + i);
4883 CHECK_CHARACTER (elt);
4884 }
4885 chars = aref_addr (object, ifrom);
4886 }
4887 else
4888 wrong_type_argument (Qarrayp, object);
4889
4890 vec = make_uninit_vector (len);
4891 for (i = 0; i < len; i++)
4892 {
4893 Lisp_Object g;
4894 int c = XFASTINT (chars[i]);
4895 unsigned code;
4896 struct font_metrics metrics;
4897
4898 code = font->driver->encode_char (font, c);
4899 if (code == FONT_INVALID_CODE)
4900 {
4901 ASET (vec, i, Qnil);
4902 continue;
4903 }
4904 g = LGLYPH_NEW ();
4905 LGLYPH_SET_FROM (g, i);
4906 LGLYPH_SET_TO (g, i);
4907 LGLYPH_SET_CHAR (g, c);
4908 LGLYPH_SET_CODE (g, code);
4909 font->driver->text_extents (font, &code, 1, &metrics);
4910 LGLYPH_SET_WIDTH (g, metrics.width);
4911 LGLYPH_SET_LBEARING (g, metrics.lbearing);
4912 LGLYPH_SET_RBEARING (g, metrics.rbearing);
4913 LGLYPH_SET_ASCENT (g, metrics.ascent);
4914 LGLYPH_SET_DESCENT (g, metrics.descent);
4915 ASET (vec, i, g);
4916 }
4917 if (! VECTORP (object))
4918 SAFE_FREE ();
4919 return vec;
4920 }
4921
4922 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4923 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4924 FONT is a font-spec, font-entity, or font-object. */)
4925 (Lisp_Object spec, Lisp_Object font)
4926 {
4927 CHECK_FONT_SPEC (spec);
4928 CHECK_FONT (font);
4929
4930 return (font_match_p (spec, font) ? Qt : Qnil);
4931 }
4932
4933 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4934 doc: /* Return a font-object for displaying a character at POSITION.
4935 Optional second arg WINDOW, if non-nil, is a window displaying
4936 the current buffer. It defaults to the currently selected window.
4937 Optional third arg STRING, if non-nil, is a string containing the target
4938 character at index specified by POSITION. */)
4939 (Lisp_Object position, Lisp_Object window, Lisp_Object string)
4940 {
4941 struct window *w = decode_live_window (window);
4942
4943 if (NILP (string))
4944 {
4945 if (XBUFFER (w->contents) != current_buffer)
4946 error ("Specified window is not displaying the current buffer");
4947 CHECK_NUMBER_COERCE_MARKER (position);
4948 if (! (BEGV <= XINT (position) && XINT (position) < ZV))
4949 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4950 }
4951 else
4952 {
4953 CHECK_NUMBER (position);
4954 CHECK_STRING (string);
4955 if (! (0 <= XINT (position) && XINT (position) < SCHARS (string)))
4956 args_out_of_range (string, position);
4957 }
4958
4959 return font_at (-1, XINT (position), NULL, w, string);
4960 }
4961
4962 #if 0
4963 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4964 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4965 The value is a number of glyphs drawn.
4966 Type C-l to recover what previously shown. */)
4967 (Lisp_Object font_object, Lisp_Object string)
4968 {
4969 Lisp_Object frame = selected_frame;
4970 struct frame *f = XFRAME (frame);
4971 struct font *font;
4972 struct face *face;
4973 int i, len, width;
4974 unsigned *code;
4975
4976 CHECK_FONT_GET_OBJECT (font_object, font);
4977 CHECK_STRING (string);
4978 len = SCHARS (string);
4979 code = alloca (sizeof (unsigned) * len);
4980 for (i = 0; i < len; i++)
4981 {
4982 Lisp_Object ch = Faref (string, make_number (i));
4983 Lisp_Object val;
4984 int c = XINT (ch);
4985
4986 code[i] = font->driver->encode_char (font, c);
4987 if (code[i] == FONT_INVALID_CODE)
4988 break;
4989 }
4990 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4991 face->fontp = font;
4992 if (font->driver->prepare_face)
4993 font->driver->prepare_face (f, face);
4994 width = font->driver->text_extents (font, code, i, NULL);
4995 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4996 if (font->driver->done_face)
4997 font->driver->done_face (f, face);
4998 face->fontp = NULL;
4999 return make_number (len);
5000 }
5001 #endif
5002
5003 DEFUN ("frame-font-cache", Fframe_font_cache, Sframe_font_cache, 0, 1, 0,
5004 doc: /* Return FRAME's font cache. Mainly used for debugging.
5005 If FRAME is omitted or nil, use the selected frame. */)
5006 (Lisp_Object frame)
5007 {
5008 #ifdef HAVE_WINDOW_SYSTEM
5009 struct frame *f = decode_live_frame (frame);
5010
5011 if (FRAME_WINDOW_P (f))
5012 return FRAME_DISPLAY_INFO (f)->name_list_element;
5013 else
5014 #endif
5015 return Qnil;
5016 }
5017
5018 #endif /* FONT_DEBUG */
5019
5020 #ifdef HAVE_WINDOW_SYSTEM
5021
5022 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
5023 doc: /* Return information about a font named NAME on frame FRAME.
5024 If FRAME is omitted or nil, use the selected frame.
5025
5026 The returned value is a vector:
5027 [ OPENED-NAME FULL-NAME SIZE HEIGHT BASELINE-OFFSET RELATIVE-COMPOSE
5028 DEFAULT-ASCENT MAX-WIDTH ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
5029 CAPABILITY ]
5030 where
5031 OPENED-NAME is the name used for opening the font,
5032 FULL-NAME is the full name of the font,
5033 SIZE is the pixelsize of the font,
5034 HEIGHT is the pixel-height of the font (i.e., ascent + descent),
5035 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
5036 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
5037 how to compose characters,
5038 MAX-WIDTH is the maximum advance width of the font,
5039 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font
5040 in pixels,
5041 FILENAME is the font file name, a string (or nil if the font backend
5042 doesn't provide a file name).
5043 CAPABILITY is a list whose first element is a symbol representing the
5044 font format, one of x, opentype, truetype, type1, pcf, or bdf.
5045 The remaining elements describe the details of the font capabilities,
5046 as follows:
5047
5048 If the font is OpenType font, the form of the list is
5049 (opentype GSUB GPOS)
5050 where GSUB shows which "GSUB" features the font supports, and GPOS
5051 shows which "GPOS" features the font supports. Both GSUB and GPOS are
5052 lists of the form:
5053 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
5054
5055 where
5056 SCRIPT is a symbol representing OpenType script tag.
5057 LANGSYS is a symbol representing OpenType langsys tag, or nil
5058 representing the default langsys.
5059 FEATURE is a symbol representing OpenType feature tag.
5060
5061 If the font is not an OpenType font, there are no elements
5062 in CAPABILITY except the font format symbol.
5063
5064 If the named font is not yet loaded, return nil. */)
5065 (Lisp_Object name, Lisp_Object frame)
5066 {
5067 struct frame *f;
5068 struct font *font;
5069 Lisp_Object info;
5070 Lisp_Object font_object;
5071
5072 if (! FONTP (name))
5073 CHECK_STRING (name);
5074 f = decode_window_system_frame (frame);
5075
5076 if (STRINGP (name))
5077 {
5078 int fontset = fs_query_fontset (name, 0);
5079
5080 if (fontset >= 0)
5081 name = fontset_ascii (fontset);
5082 font_object = font_open_by_name (f, name);
5083 }
5084 else if (FONT_OBJECT_P (name))
5085 font_object = name;
5086 else if (FONT_ENTITY_P (name))
5087 font_object = font_open_entity (f, name, 0);
5088 else
5089 {
5090 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5091 Lisp_Object entity = font_matching_entity (f, face->lface, name);
5092
5093 font_object = ! NILP (entity) ? font_open_entity (f, entity, 0) : Qnil;
5094 }
5095 if (NILP (font_object))
5096 return Qnil;
5097 font = XFONT_OBJECT (font_object);
5098
5099 info = make_uninit_vector (14);
5100 ASET (info, 0, AREF (font_object, FONT_NAME_INDEX));
5101 ASET (info, 1, AREF (font_object, FONT_FULLNAME_INDEX));
5102 ASET (info, 2, make_number (font->pixel_size));
5103 ASET (info, 3, make_number (font->height));
5104 ASET (info, 4, make_number (font->baseline_offset));
5105 ASET (info, 5, make_number (font->relative_compose));
5106 ASET (info, 6, make_number (font->default_ascent));
5107 ASET (info, 7, make_number (font->max_width));
5108 ASET (info, 8, make_number (font->ascent));
5109 ASET (info, 9, make_number (font->descent));
5110 ASET (info, 10, make_number (font->space_width));
5111 ASET (info, 11, make_number (font->average_width));
5112 ASET (info, 12, AREF (font_object, FONT_FILE_INDEX));
5113 if (font->driver->otf_capability)
5114 ASET (info, 13, Fcons (Qopentype, font->driver->otf_capability (font)));
5115 else
5116 ASET (info, 13, Qnil);
5117
5118 #if 0
5119 /* As font_object is still in FONT_OBJLIST of the entity, we can't
5120 close it now. Perhaps, we should manage font-objects
5121 by `reference-count'. */
5122 font_close_object (f, font_object);
5123 #endif
5124 return info;
5125 }
5126 #endif
5127
5128 \f
5129 #define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, ARRAYELTS (TBL))
5130
5131 static Lisp_Object
5132 build_style_table (const struct table_entry *entry, int nelement)
5133 {
5134 int i, j;
5135 Lisp_Object table, elt;
5136
5137 table = make_uninit_vector (nelement);
5138 for (i = 0; i < nelement; i++)
5139 {
5140 for (j = 0; entry[i].names[j]; j++);
5141 elt = Fmake_vector (make_number (j + 1), Qnil);
5142 ASET (elt, 0, make_number (entry[i].numeric));
5143 for (j = 0; entry[i].names[j]; j++)
5144 ASET (elt, j + 1, intern_c_string (entry[i].names[j]));
5145 ASET (table, i, elt);
5146 }
5147 return table;
5148 }
5149
5150 /* The deferred font-log data of the form [ACTION ARG RESULT].
5151 If ACTION is not nil, that is added to the log when font_add_log is
5152 called next time. At that time, ACTION is set back to nil. */
5153 static Lisp_Object Vfont_log_deferred;
5154
5155 /* Prepend the font-related logging data in Vfont_log if it is not
5156 t. ACTION describes a kind of font-related action (e.g. listing,
5157 opening), ARG is the argument for the action, and RESULT is the
5158 result of the action. */
5159 void
5160 font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
5161 {
5162 Lisp_Object val;
5163 int i;
5164
5165 if (EQ (Vfont_log, Qt))
5166 return;
5167 if (STRINGP (AREF (Vfont_log_deferred, 0)))
5168 {
5169 char *str = SSDATA (AREF (Vfont_log_deferred, 0));
5170
5171 ASET (Vfont_log_deferred, 0, Qnil);
5172 font_add_log (str, AREF (Vfont_log_deferred, 1),
5173 AREF (Vfont_log_deferred, 2));
5174 }
5175
5176 if (FONTP (arg))
5177 {
5178 Lisp_Object tail, elt;
5179 AUTO_STRING (equal, "=");
5180
5181 val = Ffont_xlfd_name (arg, Qt);
5182 for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail);
5183 tail = XCDR (tail))
5184 {
5185 elt = XCAR (tail);
5186 if (EQ (XCAR (elt), QCscript)
5187 && SYMBOLP (XCDR (elt)))
5188 val = concat3 (val, SYMBOL_NAME (QCscript),
5189 concat2 (equal, SYMBOL_NAME (XCDR (elt))));
5190 else if (EQ (XCAR (elt), QClang)
5191 && SYMBOLP (XCDR (elt)))
5192 val = concat3 (val, SYMBOL_NAME (QClang),
5193 concat2 (equal, SYMBOL_NAME (XCDR (elt))));
5194 else if (EQ (XCAR (elt), QCotf)
5195 && CONSP (XCDR (elt)) && SYMBOLP (XCAR (XCDR (elt))))
5196 val = concat3 (val, SYMBOL_NAME (QCotf),
5197 concat2 (equal, SYMBOL_NAME (XCAR (XCDR (elt)))));
5198 }
5199 arg = val;
5200 }
5201
5202 if (CONSP (result)
5203 && VECTORP (XCAR (result))
5204 && ASIZE (XCAR (result)) > 0
5205 && FONTP (AREF (XCAR (result), 0)))
5206 result = font_vconcat_entity_vectors (result);
5207 if (FONTP (result))
5208 {
5209 val = Ffont_xlfd_name (result, Qt);
5210 if (! FONT_SPEC_P (result))
5211 {
5212 AUTO_STRING (colon, ":");
5213 val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)),
5214 colon, val);
5215 }
5216 result = val;
5217 }
5218 else if (CONSP (result))
5219 {
5220 Lisp_Object tail;
5221 result = Fcopy_sequence (result);
5222 for (tail = result; CONSP (tail); tail = XCDR (tail))
5223 {
5224 val = XCAR (tail);
5225 if (FONTP (val))
5226 val = Ffont_xlfd_name (val, Qt);
5227 XSETCAR (tail, val);
5228 }
5229 }
5230 else if (VECTORP (result))
5231 {
5232 result = Fcopy_sequence (result);
5233 for (i = 0; i < ASIZE (result); i++)
5234 {
5235 val = AREF (result, i);
5236 if (FONTP (val))
5237 val = Ffont_xlfd_name (val, Qt);
5238 ASET (result, i, val);
5239 }
5240 }
5241 Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
5242 }
5243
5244 /* Record a font-related logging data to be added to Vfont_log when
5245 font_add_log is called next time. ACTION, ARG, RESULT are the same
5246 as font_add_log. */
5247
5248 void
5249 font_deferred_log (const char *action, Lisp_Object arg, Lisp_Object result)
5250 {
5251 if (EQ (Vfont_log, Qt))
5252 return;
5253 ASET (Vfont_log_deferred, 0, build_string (action));
5254 ASET (Vfont_log_deferred, 1, arg);
5255 ASET (Vfont_log_deferred, 2, result);
5256 }
5257
5258 void
5259 syms_of_font (void)
5260 {
5261 sort_shift_bits[FONT_TYPE_INDEX] = 0;
5262 sort_shift_bits[FONT_SLANT_INDEX] = 2;
5263 sort_shift_bits[FONT_WEIGHT_INDEX] = 9;
5264 sort_shift_bits[FONT_SIZE_INDEX] = 16;
5265 sort_shift_bits[FONT_WIDTH_INDEX] = 23;
5266 /* Note that the other elements in sort_shift_bits are not used. */
5267
5268 staticpro (&font_charset_alist);
5269 font_charset_alist = Qnil;
5270
5271 DEFSYM (Qopentype, "opentype");
5272
5273 /* Important character set symbols. */
5274 DEFSYM (Qascii_0, "ascii-0");
5275 DEFSYM (Qiso8859_1, "iso8859-1");
5276 DEFSYM (Qiso10646_1, "iso10646-1");
5277 DEFSYM (Qunicode_bmp, "unicode-bmp");
5278
5279 /* Symbols representing keys of font extra info. */
5280 DEFSYM (QCotf, ":otf");
5281 DEFSYM (QClang, ":lang");
5282 DEFSYM (QCscript, ":script");
5283 DEFSYM (QCantialias, ":antialias");
5284 DEFSYM (QCfoundry, ":foundry");
5285 DEFSYM (QCadstyle, ":adstyle");
5286 DEFSYM (QCregistry, ":registry");
5287 DEFSYM (QCspacing, ":spacing");
5288 DEFSYM (QCdpi, ":dpi");
5289 DEFSYM (QCscalable, ":scalable");
5290 DEFSYM (QCavgwidth, ":avgwidth");
5291 DEFSYM (QCfont_entity, ":font-entity");
5292
5293 /* Symbols representing values of font spacing property. */
5294 DEFSYM (Qc, "c");
5295 DEFSYM (Qm, "m");
5296 DEFSYM (Qp, "p");
5297 DEFSYM (Qd, "d");
5298
5299 /* Special ADSTYLE properties to avoid fonts used for Latin
5300 characters; used in xfont.c and ftfont.c. */
5301 DEFSYM (Qja, "ja");
5302 DEFSYM (Qko, "ko");
5303
5304 DEFSYM (QCuser_spec, "user-spec");
5305
5306 staticpro (&scratch_font_spec);
5307 scratch_font_spec = Ffont_spec (0, NULL);
5308 staticpro (&scratch_font_prefer);
5309 scratch_font_prefer = Ffont_spec (0, NULL);
5310
5311 staticpro (&Vfont_log_deferred);
5312 Vfont_log_deferred = Fmake_vector (make_number (3), Qnil);
5313
5314 #if 0
5315 #ifdef HAVE_LIBOTF
5316 staticpro (&otf_list);
5317 otf_list = Qnil;
5318 #endif /* HAVE_LIBOTF */
5319 #endif /* 0 */
5320
5321 defsubr (&Sfontp);
5322 defsubr (&Sfont_spec);
5323 defsubr (&Sfont_get);
5324 #ifdef HAVE_WINDOW_SYSTEM
5325 defsubr (&Sfont_face_attributes);
5326 #endif
5327 defsubr (&Sfont_put);
5328 defsubr (&Slist_fonts);
5329 defsubr (&Sfont_family_list);
5330 defsubr (&Sfind_font);
5331 defsubr (&Sfont_xlfd_name);
5332 defsubr (&Sclear_font_cache);
5333 defsubr (&Sfont_shape_gstring);
5334 defsubr (&Sfont_variation_glyphs);
5335 defsubr (&Sinternal_char_font);
5336 #if 0
5337 defsubr (&Sfont_drive_otf);
5338 defsubr (&Sfont_otf_alternates);
5339 #endif /* 0 */
5340
5341 #ifdef FONT_DEBUG
5342 defsubr (&Sopen_font);
5343 defsubr (&Sclose_font);
5344 defsubr (&Squery_font);
5345 defsubr (&Sfont_get_glyphs);
5346 defsubr (&Sfont_match_p);
5347 defsubr (&Sfont_at);
5348 #if 0
5349 defsubr (&Sdraw_string);
5350 #endif
5351 defsubr (&Sframe_font_cache);
5352 #endif /* FONT_DEBUG */
5353 #ifdef HAVE_WINDOW_SYSTEM
5354 defsubr (&Sfont_info);
5355 #endif
5356
5357 DEFVAR_LISP ("font-encoding-alist", Vfont_encoding_alist,
5358 doc: /*
5359 Alist of fontname patterns vs the corresponding encoding and repertory info.
5360 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5361 where ENCODING is a charset or a char-table,
5362 and REPERTORY is a charset, a char-table, or nil.
5363
5364 If ENCODING and REPERTORY are the same, the element can have the form
5365 (REGEXP . ENCODING).
5366
5367 ENCODING is for converting a character to a glyph code of the font.
5368 If ENCODING is a charset, encoding a character by the charset gives
5369 the corresponding glyph code. If ENCODING is a char-table, looking up
5370 the table by a character gives the corresponding glyph code.
5371
5372 REPERTORY specifies a repertory of characters supported by the font.
5373 If REPERTORY is a charset, all characters belonging to the charset are
5374 supported. If REPERTORY is a char-table, all characters who have a
5375 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5376 gets the repertory information by an opened font and ENCODING. */);
5377 Vfont_encoding_alist = Qnil;
5378
5379 /* FIXME: These 3 vars are not quite what they appear: setq on them
5380 won't have any effect other than disconnect them from the style
5381 table used by the font display code. So we make them read-only,
5382 to avoid this confusing situation. */
5383
5384 DEFVAR_LISP_NOPRO ("font-weight-table", Vfont_weight_table,
5385 doc: /* Vector of valid font weight values.
5386 Each element has the form:
5387 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5388 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5389 Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
5390 XSYMBOL (intern_c_string ("font-weight-table"))->constant = 1;
5391
5392 DEFVAR_LISP_NOPRO ("font-slant-table", Vfont_slant_table,
5393 doc: /* Vector of font slant symbols vs the corresponding numeric values.
5394 See `font-weight-table' for the format of the vector. */);
5395 Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
5396 XSYMBOL (intern_c_string ("font-slant-table"))->constant = 1;
5397
5398 DEFVAR_LISP_NOPRO ("font-width-table", Vfont_width_table,
5399 doc: /* Alist of font width symbols vs the corresponding numeric values.
5400 See `font-weight-table' for the format of the vector. */);
5401 Vfont_width_table = BUILD_STYLE_TABLE (width_table);
5402 XSYMBOL (intern_c_string ("font-width-table"))->constant = 1;
5403
5404 staticpro (&font_style_table);
5405 font_style_table = make_uninit_vector (3);
5406 ASET (font_style_table, 0, Vfont_weight_table);
5407 ASET (font_style_table, 1, Vfont_slant_table);
5408 ASET (font_style_table, 2, Vfont_width_table);
5409
5410 DEFVAR_LISP ("font-log", Vfont_log, doc: /*
5411 A list that logs font-related actions and results, for debugging.
5412 The default value is t, which means to suppress logging.
5413 Set it to nil to enable logging. If the environment variable
5414 EMACS_FONT_LOG is set at startup, it defaults to nil. */);
5415 Vfont_log = Qnil;
5416
5417 #ifdef HAVE_WINDOW_SYSTEM
5418 #ifdef HAVE_FREETYPE
5419 syms_of_ftfont ();
5420 #ifdef HAVE_X_WINDOWS
5421 #ifdef USE_CAIRO
5422 syms_of_ftcrfont ();
5423 #else
5424 syms_of_xfont ();
5425 syms_of_ftxfont ();
5426 #ifdef HAVE_XFT
5427 syms_of_xftfont ();
5428 #endif /* HAVE_XFT */
5429 #endif /* not USE_CAIRO */
5430 #endif /* HAVE_X_WINDOWS */
5431 #else /* not HAVE_FREETYPE */
5432 #ifdef HAVE_X_WINDOWS
5433 syms_of_xfont ();
5434 #endif /* HAVE_X_WINDOWS */
5435 #endif /* not HAVE_FREETYPE */
5436 #ifdef HAVE_BDFFONT
5437 syms_of_bdffont ();
5438 #endif /* HAVE_BDFFONT */
5439 #ifdef HAVE_NTGUI
5440 syms_of_w32font ();
5441 #endif /* HAVE_NTGUI */
5442 #endif /* HAVE_WINDOW_SYSTEM */
5443 }
5444
5445 void
5446 init_font (void)
5447 {
5448 Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;
5449 }