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