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