Merge from emacs-24; up to 2014-06-02T11:35:40Z!michael.albinus@gmx.de
[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 face->extra = NULL;
3341 }
3342
3343
3344 /* Open a font that is a match for font-spec SPEC on frame F. If no proper
3345 font is found, return Qnil. */
3346
3347 Lisp_Object
3348 font_open_by_spec (struct frame *f, Lisp_Object spec)
3349 {
3350 Lisp_Object attrs[LFACE_VECTOR_SIZE];
3351
3352 /* We set up the default font-related attributes of a face to prefer
3353 a moderate font. */
3354 attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
3355 attrs[LFACE_SWIDTH_INDEX] = attrs[LFACE_WEIGHT_INDEX]
3356 = attrs[LFACE_SLANT_INDEX] = Qnormal;
3357 #ifndef HAVE_NS
3358 attrs[LFACE_HEIGHT_INDEX] = make_number (120);
3359 #else
3360 attrs[LFACE_HEIGHT_INDEX] = make_number (0);
3361 #endif
3362 attrs[LFACE_FONT_INDEX] = Qnil;
3363
3364 return font_load_for_lface (f, attrs, spec);
3365 }
3366
3367
3368 /* Open a font that matches NAME on frame F. If no proper font is
3369 found, return Qnil. */
3370
3371 Lisp_Object
3372 font_open_by_name (struct frame *f, Lisp_Object name)
3373 {
3374 Lisp_Object args[2];
3375 Lisp_Object spec, ret;
3376
3377 args[0] = QCname;
3378 args[1] = name;
3379 spec = Ffont_spec (2, args);
3380 ret = font_open_by_spec (f, spec);
3381 /* Do not lose name originally put in. */
3382 if (!NILP (ret))
3383 font_put_extra (ret, QCuser_spec, args[1]);
3384
3385 return ret;
3386 }
3387
3388
3389 /* Register font-driver DRIVER. This function is used in two ways.
3390
3391 The first is with frame F non-NULL. In this case, make DRIVER
3392 available (but not yet activated) on F. All frame creators
3393 (e.g. Fx_create_frame) must call this function at least once with
3394 an available font-driver.
3395
3396 The second is with frame F NULL. In this case, DRIVER is globally
3397 registered in the variable `font_driver_list'. All font-driver
3398 implementations must call this function in its syms_of_XXXX
3399 (e.g. syms_of_xfont). */
3400
3401 void
3402 register_font_driver (struct font_driver *driver, struct frame *f)
3403 {
3404 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
3405 struct font_driver_list *prev, *list;
3406
3407 #ifdef HAVE_WINDOW_SYSTEM
3408 if (f && ! driver->draw)
3409 error ("Unusable font driver for a frame: %s",
3410 SDATA (SYMBOL_NAME (driver->type)));
3411 #endif /* HAVE_WINDOW_SYSTEM */
3412
3413 for (prev = NULL, list = root; list; prev = list, list = list->next)
3414 if (EQ (list->driver->type, driver->type))
3415 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3416
3417 list = xmalloc (sizeof *list);
3418 list->on = 0;
3419 list->driver = driver;
3420 list->next = NULL;
3421 if (prev)
3422 prev->next = list;
3423 else if (f)
3424 f->font_driver_list = list;
3425 else
3426 font_driver_list = list;
3427 if (! f)
3428 num_font_drivers++;
3429 }
3430
3431 void
3432 free_font_driver_list (struct frame *f)
3433 {
3434 struct font_driver_list *list, *next;
3435
3436 for (list = f->font_driver_list; list; list = next)
3437 {
3438 next = list->next;
3439 xfree (list);
3440 }
3441 f->font_driver_list = NULL;
3442 }
3443
3444
3445 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3446 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3447 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3448
3449 A caller must free all realized faces if any in advance. The
3450 return value is a list of font backends actually made used on
3451 F. */
3452
3453 Lisp_Object
3454 font_update_drivers (struct frame *f, Lisp_Object new_drivers)
3455 {
3456 Lisp_Object active_drivers = Qnil;
3457 struct font_driver_list *list;
3458
3459 /* At first, turn off non-requested drivers, and turn on requested
3460 drivers. */
3461 for (list = f->font_driver_list; list; list = list->next)
3462 {
3463 struct font_driver *driver = list->driver;
3464 if ((EQ (new_drivers, Qt) || ! NILP (Fmemq (driver->type, new_drivers)))
3465 != list->on)
3466 {
3467 if (list->on)
3468 {
3469 if (driver->end_for_frame)
3470 driver->end_for_frame (f);
3471 font_finish_cache (f, driver);
3472 list->on = 0;
3473 }
3474 else
3475 {
3476 if (! driver->start_for_frame
3477 || driver->start_for_frame (f) == 0)
3478 {
3479 font_prepare_cache (f, driver);
3480 list->on = 1;
3481 }
3482 }
3483 }
3484 }
3485
3486 if (NILP (new_drivers))
3487 return Qnil;
3488
3489 if (! EQ (new_drivers, Qt))
3490 {
3491 /* Re-order the driver list according to new_drivers. */
3492 struct font_driver_list **list_table, **next;
3493 Lisp_Object tail;
3494 int i;
3495
3496 list_table = alloca (sizeof list_table[0] * (num_font_drivers + 1));
3497 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
3498 {
3499 for (list = f->font_driver_list; list; list = list->next)
3500 if (list->on && EQ (list->driver->type, XCAR (tail)))
3501 break;
3502 if (list)
3503 list_table[i++] = list;
3504 }
3505 for (list = f->font_driver_list; list; list = list->next)
3506 if (! list->on)
3507 list_table[i++] = list;
3508 list_table[i] = NULL;
3509
3510 next = &f->font_driver_list;
3511 for (i = 0; list_table[i]; i++)
3512 {
3513 *next = list_table[i];
3514 next = &(*next)->next;
3515 }
3516 *next = NULL;
3517
3518 if (! f->font_driver_list->on)
3519 { /* None of the drivers is enabled: enable them all.
3520 Happens if you set the list of drivers to (xft x) in your .emacs
3521 and then use it under w32 or ns. */
3522 for (list = f->font_driver_list; list; list = list->next)
3523 {
3524 struct font_driver *driver = list->driver;
3525 eassert (! list->on);
3526 if (! driver->start_for_frame
3527 || driver->start_for_frame (f) == 0)
3528 {
3529 font_prepare_cache (f, driver);
3530 list->on = 1;
3531 }
3532 }
3533 }
3534 }
3535
3536 for (list = f->font_driver_list; list; list = list->next)
3537 if (list->on)
3538 active_drivers = nconc2 (active_drivers, list1 (list->driver->type));
3539 return active_drivers;
3540 }
3541
3542 int
3543 font_put_frame_data (struct frame *f, struct font_driver *driver, void *data)
3544 {
3545 struct font_data_list *list, *prev;
3546
3547 for (prev = NULL, list = f->font_data_list; list;
3548 prev = list, list = list->next)
3549 if (list->driver == driver)
3550 break;
3551 if (! data)
3552 {
3553 if (list)
3554 {
3555 if (prev)
3556 prev->next = list->next;
3557 else
3558 f->font_data_list = list->next;
3559 xfree (list);
3560 }
3561 return 0;
3562 }
3563
3564 if (! list)
3565 {
3566 list = xmalloc (sizeof *list);
3567 list->driver = driver;
3568 list->next = f->font_data_list;
3569 f->font_data_list = list;
3570 }
3571 list->data = data;
3572 return 0;
3573 }
3574
3575
3576 void *
3577 font_get_frame_data (struct frame *f, struct font_driver *driver)
3578 {
3579 struct font_data_list *list;
3580
3581 for (list = f->font_data_list; list; list = list->next)
3582 if (list->driver == driver)
3583 break;
3584 if (! list)
3585 return NULL;
3586 return list->data;
3587 }
3588
3589
3590 /* Sets attributes on a font. Any properties that appear in ALIST and
3591 BOOLEAN_PROPERTIES or NON_BOOLEAN_PROPERTIES are set on the font.
3592 BOOLEAN_PROPERTIES and NON_BOOLEAN_PROPERTIES are NULL-terminated
3593 arrays of strings. This function is intended for use by the font
3594 drivers to implement their specific font_filter_properties. */
3595 void
3596 font_filter_properties (Lisp_Object font,
3597 Lisp_Object alist,
3598 const char *const boolean_properties[],
3599 const char *const non_boolean_properties[])
3600 {
3601 Lisp_Object it;
3602 int i;
3603
3604 /* Set boolean values to Qt or Qnil. */
3605 for (i = 0; boolean_properties[i] != NULL; ++i)
3606 for (it = alist; ! NILP (it); it = XCDR (it))
3607 {
3608 Lisp_Object key = XCAR (XCAR (it));
3609 Lisp_Object val = XCDR (XCAR (it));
3610 char *keystr = SSDATA (SYMBOL_NAME (key));
3611
3612 if (strcmp (boolean_properties[i], keystr) == 0)
3613 {
3614 const char *str = INTEGERP (val) ? (XINT (val) ? "true" : "false")
3615 : SYMBOLP (val) ? SSDATA (SYMBOL_NAME (val))
3616 : "true";
3617
3618 if (strcmp ("false", str) == 0 || strcmp ("False", str) == 0
3619 || strcmp ("FALSE", str) == 0 || strcmp ("FcFalse", str) == 0
3620 || strcmp ("off", str) == 0 || strcmp ("OFF", str) == 0
3621 || strcmp ("Off", str) == 0)
3622 val = Qnil;
3623 else
3624 val = Qt;
3625
3626 Ffont_put (font, key, val);
3627 }
3628 }
3629
3630 for (i = 0; non_boolean_properties[i] != NULL; ++i)
3631 for (it = alist; ! NILP (it); it = XCDR (it))
3632 {
3633 Lisp_Object key = XCAR (XCAR (it));
3634 Lisp_Object val = XCDR (XCAR (it));
3635 char *keystr = SSDATA (SYMBOL_NAME (key));
3636 if (strcmp (non_boolean_properties[i], keystr) == 0)
3637 Ffont_put (font, key, val);
3638 }
3639 }
3640
3641
3642 /* Return the font used to draw character C by FACE at buffer position
3643 POS in window W. If STRING is non-nil, it is a string containing C
3644 at index POS. If C is negative, get C from the current buffer or
3645 STRING. */
3646
3647 static Lisp_Object
3648 font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
3649 Lisp_Object string)
3650 {
3651 struct frame *f;
3652 bool multibyte;
3653 Lisp_Object font_object;
3654
3655 multibyte = (NILP (string)
3656 ? ! NILP (BVAR (current_buffer, enable_multibyte_characters))
3657 : STRING_MULTIBYTE (string));
3658 if (c < 0)
3659 {
3660 if (NILP (string))
3661 {
3662 if (multibyte)
3663 {
3664 ptrdiff_t pos_byte = CHAR_TO_BYTE (pos);
3665
3666 c = FETCH_CHAR (pos_byte);
3667 }
3668 else
3669 c = FETCH_BYTE (pos);
3670 }
3671 else
3672 {
3673 unsigned char *str;
3674
3675 multibyte = STRING_MULTIBYTE (string);
3676 if (multibyte)
3677 {
3678 ptrdiff_t pos_byte = string_char_to_byte (string, pos);
3679
3680 str = SDATA (string) + pos_byte;
3681 c = STRING_CHAR (str);
3682 }
3683 else
3684 c = SDATA (string)[pos];
3685 }
3686 }
3687
3688 f = XFRAME (w->frame);
3689 if (! FRAME_WINDOW_P (f))
3690 return Qnil;
3691 if (! face)
3692 {
3693 int face_id;
3694 ptrdiff_t endptr;
3695
3696 if (STRINGP (string))
3697 face_id = face_at_string_position (w, string, pos, 0, &endptr,
3698 DEFAULT_FACE_ID, 0);
3699 else
3700 face_id = face_at_buffer_position (w, pos, &endptr,
3701 pos + 100, 0, -1);
3702 face = FACE_FROM_ID (f, face_id);
3703 }
3704 if (multibyte)
3705 {
3706 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3707 face = FACE_FROM_ID (f, face_id);
3708 }
3709 if (! face->font)
3710 return Qnil;
3711
3712 XSETFONT (font_object, face->font);
3713 return font_object;
3714 }
3715
3716
3717 #ifdef HAVE_WINDOW_SYSTEM
3718
3719 /* Check how many characters after character/byte position POS/POS_BYTE
3720 (at most to *LIMIT) can be displayed by the same font in the window W.
3721 FACE, if non-NULL, is the face selected for the character at POS.
3722 If STRING is not nil, it is the string to check instead of the current
3723 buffer. In that case, FACE must be not NULL.
3724
3725 The return value is the font-object for the character at POS.
3726 *LIMIT is set to the position where that font can't be used.
3727
3728 It is assured that the current buffer (or STRING) is multibyte. */
3729
3730 Lisp_Object
3731 font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
3732 struct window *w, struct face *face, Lisp_Object string)
3733 {
3734 ptrdiff_t ignore;
3735 int c;
3736 Lisp_Object font_object = Qnil;
3737
3738 if (NILP (string))
3739 {
3740 if (! face)
3741 {
3742 int face_id;
3743
3744 face_id = face_at_buffer_position (w, pos, &ignore,
3745 *limit, 0, -1);
3746 face = FACE_FROM_ID (XFRAME (w->frame), face_id);
3747 }
3748 }
3749 else
3750 eassert (face);
3751
3752 while (pos < *limit)
3753 {
3754 Lisp_Object category;
3755
3756 if (NILP (string))
3757 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3758 else
3759 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3760 category = CHAR_TABLE_REF (Vunicode_category_table, c);
3761 if (INTEGERP (category)
3762 && (XINT (category) == UNICODE_CATEGORY_Cf
3763 || CHAR_VARIATION_SELECTOR_P (c)))
3764 continue;
3765 if (NILP (font_object))
3766 {
3767 font_object = font_for_char (face, c, pos - 1, string);
3768 if (NILP (font_object))
3769 return Qnil;
3770 continue;
3771 }
3772 if (font_encode_char (font_object, c) == FONT_INVALID_CODE)
3773 *limit = pos - 1;
3774 }
3775 return font_object;
3776 }
3777 #endif
3778
3779 \f
3780 /* Lisp API. */
3781
3782 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3783 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3784 Return nil otherwise.
3785 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3786 which kind of font it is. It must be one of `font-spec', `font-entity',
3787 `font-object'. */)
3788 (Lisp_Object object, Lisp_Object extra_type)
3789 {
3790 if (NILP (extra_type))
3791 return (FONTP (object) ? Qt : Qnil);
3792 if (EQ (extra_type, Qfont_spec))
3793 return (FONT_SPEC_P (object) ? Qt : Qnil);
3794 if (EQ (extra_type, Qfont_entity))
3795 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3796 if (EQ (extra_type, Qfont_object))
3797 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3798 wrong_type_argument (intern ("font-extra-type"), extra_type);
3799 }
3800
3801 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3802 doc: /* Return a newly created font-spec with arguments as properties.
3803
3804 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3805 valid font property name listed below:
3806
3807 `:family', `:weight', `:slant', `:width'
3808
3809 They are the same as face attributes of the same name. See
3810 `set-face-attribute'.
3811
3812 `:foundry'
3813
3814 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3815
3816 `:adstyle'
3817
3818 VALUE must be a string or a symbol specifying the additional
3819 typographic style information of a font, e.g. ``sans''.
3820
3821 `:registry'
3822
3823 VALUE must be a string or a symbol specifying the charset registry and
3824 encoding of a font, e.g. ``iso8859-1''.
3825
3826 `:size'
3827
3828 VALUE must be a non-negative integer or a floating point number
3829 specifying the font size. It specifies the font size in pixels (if
3830 VALUE is an integer), or in points (if VALUE is a float).
3831
3832 `:name'
3833
3834 VALUE must be a string of XLFD-style or fontconfig-style font name.
3835
3836 `:script'
3837
3838 VALUE must be a symbol representing a script that the font must
3839 support. It may be a symbol representing a subgroup of a script
3840 listed in the variable `script-representative-chars'.
3841
3842 `:lang'
3843
3844 VALUE must be a symbol of two-letter ISO-639 language names,
3845 e.g. `ja'.
3846
3847 `:otf'
3848
3849 VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
3850 required OpenType features.
3851
3852 SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
3853 LANGSYS-TAG: OpenType language system tag symbol,
3854 or nil for the default language system.
3855 GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
3856 GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
3857
3858 GSUB and GPOS may contain `nil' element. In such a case, the font
3859 must not have any of the remaining elements.
3860
3861 For instance, if the VALUE is `(thai nil nil (mark))', the font must
3862 be an OpenType font whose GPOS table of `thai' script's default
3863 language system must contain `mark' feature.
3864
3865 usage: (font-spec ARGS...) */)
3866 (ptrdiff_t nargs, Lisp_Object *args)
3867 {
3868 Lisp_Object spec = font_make_spec ();
3869 ptrdiff_t i;
3870
3871 for (i = 0; i < nargs; i += 2)
3872 {
3873 Lisp_Object key = args[i], val;
3874
3875 CHECK_SYMBOL (key);
3876 if (i + 1 >= nargs)
3877 error ("No value for key `%s'", SDATA (SYMBOL_NAME (key)));
3878 val = args[i + 1];
3879
3880 if (EQ (key, QCname))
3881 {
3882 CHECK_STRING (val);
3883 if (font_parse_name (SSDATA (val), SBYTES (val), spec) < 0)
3884 error ("Invalid font name: %s", SSDATA (val));
3885 font_put_extra (spec, key, val);
3886 }
3887 else
3888 {
3889 int idx = get_font_prop_index (key);
3890
3891 if (idx >= 0)
3892 {
3893 val = font_prop_validate (idx, Qnil, val);
3894 if (idx < FONT_EXTRA_INDEX)
3895 ASET (spec, idx, val);
3896 else
3897 font_put_extra (spec, key, val);
3898 }
3899 else
3900 font_put_extra (spec, key, font_prop_validate (0, key, val));
3901 }
3902 }
3903 return spec;
3904 }
3905
3906 /* Return a copy of FONT as a font-spec. */
3907 Lisp_Object
3908 copy_font_spec (Lisp_Object font)
3909 {
3910 Lisp_Object new_spec, tail, prev, extra;
3911 int i;
3912
3913 CHECK_FONT (font);
3914 new_spec = font_make_spec ();
3915 for (i = 1; i < FONT_EXTRA_INDEX; i++)
3916 ASET (new_spec, i, AREF (font, i));
3917 extra = Fcopy_alist (AREF (font, FONT_EXTRA_INDEX));
3918 /* We must remove :font-entity property. */
3919 for (prev = Qnil, tail = extra; CONSP (tail); prev = tail, tail = XCDR (tail))
3920 if (EQ (XCAR (XCAR (tail)), QCfont_entity))
3921 {
3922 if (NILP (prev))
3923 extra = XCDR (extra);
3924 else
3925 XSETCDR (prev, XCDR (tail));
3926 break;
3927 }
3928 ASET (new_spec, FONT_EXTRA_INDEX, extra);
3929 return new_spec;
3930 }
3931
3932 /* Merge font-specs FROM and TO, and return a new font-spec.
3933 Every specified property in FROM overrides the corresponding
3934 property in TO. */
3935 Lisp_Object
3936 merge_font_spec (Lisp_Object from, Lisp_Object to)
3937 {
3938 Lisp_Object extra, tail;
3939 int i;
3940
3941 CHECK_FONT (from);
3942 CHECK_FONT (to);
3943 to = copy_font_spec (to);
3944 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3945 ASET (to, i, AREF (from, i));
3946 extra = AREF (to, FONT_EXTRA_INDEX);
3947 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3948 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
3949 {
3950 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
3951
3952 if (! NILP (slot))
3953 XSETCDR (slot, XCDR (XCAR (tail)));
3954 else
3955 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
3956 }
3957 ASET (to, FONT_EXTRA_INDEX, extra);
3958 return to;
3959 }
3960
3961 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
3962 doc: /* Return the value of FONT's property KEY.
3963 FONT is a font-spec, a font-entity, or a font-object.
3964 KEY is any symbol, but these are reserved for specific meanings:
3965 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
3966 :size, :name, :script, :otf
3967 See the documentation of `font-spec' for their meanings.
3968 In addition, if FONT is a font-entity or a font-object, values of
3969 :script and :otf are different from those of a font-spec as below:
3970
3971 The value of :script may be a list of scripts that are supported by the font.
3972
3973 The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
3974 representing the OpenType features supported by the font by this form:
3975 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
3976 SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
3977 Layout tags. */)
3978 (Lisp_Object font, Lisp_Object key)
3979 {
3980 int idx;
3981 Lisp_Object val;
3982
3983 CHECK_FONT (font);
3984 CHECK_SYMBOL (key);
3985
3986 idx = get_font_prop_index (key);
3987 if (idx >= FONT_WEIGHT_INDEX && idx <= FONT_WIDTH_INDEX)
3988 return font_style_symbolic (font, idx, 0);
3989 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3990 return AREF (font, idx);
3991 val = Fassq (key, AREF (font, FONT_EXTRA_INDEX));
3992 if (NILP (val) && EQ (key, QCotf) && FONT_OBJECT_P (font))
3993 {
3994 struct font *fontp = XFONT_OBJECT (font);
3995
3996 if (fontp->driver->otf_capability)
3997 val = fontp->driver->otf_capability (fontp);
3998 else
3999 val = Fcons (Qnil, Qnil);
4000 }
4001 else
4002 val = Fcdr (val);
4003 return val;
4004 }
4005
4006 #ifdef HAVE_WINDOW_SYSTEM
4007
4008 DEFUN ("font-face-attributes", Ffont_face_attributes, Sfont_face_attributes, 1, 2, 0,
4009 doc: /* Return a plist of face attributes generated by FONT.
4010 FONT is a font name, a font-spec, a font-entity, or a font-object.
4011 The return value is a list of the form
4012
4013 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
4014
4015 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
4016 compatible with `set-face-attribute'. Some of these key-attribute pairs
4017 may be omitted from the list if they are not specified by FONT.
4018
4019 The optional argument FRAME specifies the frame that the face attributes
4020 are to be displayed on. If omitted, the selected frame is used. */)
4021 (Lisp_Object font, Lisp_Object frame)
4022 {
4023 struct frame *f = decode_live_frame (frame);
4024 Lisp_Object plist[10];
4025 Lisp_Object val;
4026 int n = 0;
4027
4028 if (STRINGP (font))
4029 {
4030 int fontset = fs_query_fontset (font, 0);
4031 Lisp_Object name = font;
4032 if (fontset >= 0)
4033 font = fontset_ascii (fontset);
4034 font = font_spec_from_name (name);
4035 if (! FONTP (font))
4036 signal_error ("Invalid font name", name);
4037 }
4038 else if (! FONTP (font))
4039 signal_error ("Invalid font object", font);
4040
4041 val = AREF (font, FONT_FAMILY_INDEX);
4042 if (! NILP (val))
4043 {
4044 plist[n++] = QCfamily;
4045 plist[n++] = SYMBOL_NAME (val);
4046 }
4047
4048 val = AREF (font, FONT_SIZE_INDEX);
4049 if (INTEGERP (val))
4050 {
4051 Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
4052 int dpi = INTEGERP (font_dpi) ? XINT (font_dpi) : FRAME_RES_Y (f);
4053 plist[n++] = QCheight;
4054 plist[n++] = make_number (PIXEL_TO_POINT (XINT (val) * 10, dpi));
4055 }
4056 else if (FLOATP (val))
4057 {
4058 plist[n++] = QCheight;
4059 plist[n++] = make_number (10 * (int) XFLOAT_DATA (val));
4060 }
4061
4062 val = FONT_WEIGHT_FOR_FACE (font);
4063 if (! NILP (val))
4064 {
4065 plist[n++] = QCweight;
4066 plist[n++] = val;
4067 }
4068
4069 val = FONT_SLANT_FOR_FACE (font);
4070 if (! NILP (val))
4071 {
4072 plist[n++] = QCslant;
4073 plist[n++] = val;
4074 }
4075
4076 val = FONT_WIDTH_FOR_FACE (font);
4077 if (! NILP (val))
4078 {
4079 plist[n++] = QCwidth;
4080 plist[n++] = val;
4081 }
4082
4083 return Flist (n, plist);
4084 }
4085
4086 #endif
4087
4088 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
4089 doc: /* Set one property of FONT: give property KEY value VAL.
4090 FONT is a font-spec, a font-entity, or a font-object.
4091
4092 If FONT is a font-spec, KEY can be any symbol. But if KEY is the one
4093 accepted by the function `font-spec' (which see), VAL must be what
4094 allowed in `font-spec'.
4095
4096 If FONT is a font-entity or a font-object, KEY must not be the one
4097 accepted by `font-spec'. */)
4098 (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
4099 {
4100 int idx;
4101
4102 idx = get_font_prop_index (prop);
4103 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
4104 {
4105 CHECK_FONT_SPEC (font);
4106 ASET (font, idx, font_prop_validate (idx, Qnil, val));
4107 }
4108 else
4109 {
4110 if (EQ (prop, QCname)
4111 || EQ (prop, QCscript)
4112 || EQ (prop, QClang)
4113 || EQ (prop, QCotf))
4114 CHECK_FONT_SPEC (font);
4115 else
4116 CHECK_FONT (font);
4117 font_put_extra (font, prop, font_prop_validate (0, prop, val));
4118 }
4119 return val;
4120 }
4121
4122 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
4123 doc: /* List available fonts matching FONT-SPEC on the current frame.
4124 Optional 2nd argument FRAME specifies the target frame.
4125 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4126 Optional 4th argument PREFER, if non-nil, is a font-spec to
4127 control the order of the returned list. Fonts are sorted by
4128 how close they are to PREFER. */)
4129 (Lisp_Object font_spec, Lisp_Object frame, Lisp_Object num, Lisp_Object prefer)
4130 {
4131 struct frame *f = decode_live_frame (frame);
4132 Lisp_Object vec, list;
4133 EMACS_INT n = 0;
4134
4135 CHECK_FONT_SPEC (font_spec);
4136 if (! NILP (num))
4137 {
4138 CHECK_NUMBER (num);
4139 n = XINT (num);
4140 if (n <= 0)
4141 return Qnil;
4142 }
4143 if (! NILP (prefer))
4144 CHECK_FONT_SPEC (prefer);
4145
4146 list = font_list_entities (f, font_spec);
4147 if (NILP (list))
4148 return Qnil;
4149 if (NILP (XCDR (list))
4150 && ASIZE (XCAR (list)) == 1)
4151 return list1 (AREF (XCAR (list), 0));
4152
4153 if (! NILP (prefer))
4154 vec = font_sort_entities (list, prefer, f, 0);
4155 else
4156 vec = font_vconcat_entity_vectors (list);
4157 if (n == 0 || n >= ASIZE (vec))
4158 {
4159 Lisp_Object args[2];
4160
4161 args[0] = vec;
4162 args[1] = Qnil;
4163 list = Fappend (2, args);
4164 }
4165 else
4166 {
4167 for (list = Qnil, n--; n >= 0; n--)
4168 list = Fcons (AREF (vec, n), list);
4169 }
4170 return list;
4171 }
4172
4173 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
4174 doc: /* List available font families on the current frame.
4175 If FRAME is omitted or nil, the selected frame is used. */)
4176 (Lisp_Object frame)
4177 {
4178 struct frame *f = decode_live_frame (frame);
4179 struct font_driver_list *driver_list;
4180 Lisp_Object list = Qnil;
4181
4182 for (driver_list = f->font_driver_list; driver_list;
4183 driver_list = driver_list->next)
4184 if (driver_list->driver->list_family)
4185 {
4186 Lisp_Object val = driver_list->driver->list_family (f);
4187 Lisp_Object tail = list;
4188
4189 for (; CONSP (val); val = XCDR (val))
4190 if (NILP (Fmemq (XCAR (val), tail))
4191 && SYMBOLP (XCAR (val)))
4192 list = Fcons (SYMBOL_NAME (XCAR (val)), list);
4193 }
4194 return list;
4195 }
4196
4197 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
4198 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
4199 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4200 (Lisp_Object font_spec, Lisp_Object frame)
4201 {
4202 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
4203
4204 if (CONSP (val))
4205 val = XCAR (val);
4206 return val;
4207 }
4208
4209 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
4210 doc: /* Return XLFD name of FONT.
4211 FONT is a font-spec, font-entity, or font-object.
4212 If the name is too long for XLFD (maximum 255 chars), return nil.
4213 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4214 the consecutive wildcards are folded into one. */)
4215 (Lisp_Object font, Lisp_Object fold_wildcards)
4216 {
4217 char name[256];
4218 int namelen, pixel_size = 0;
4219
4220 CHECK_FONT (font);
4221
4222 if (FONT_OBJECT_P (font))
4223 {
4224 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
4225
4226 if (STRINGP (font_name)
4227 && SDATA (font_name)[0] == '-')
4228 {
4229 if (NILP (fold_wildcards))
4230 return font_name;
4231 strcpy (name, SSDATA (font_name));
4232 namelen = SBYTES (font_name);
4233 goto done;
4234 }
4235 pixel_size = XFONT_OBJECT (font)->pixel_size;
4236 }
4237 namelen = font_unparse_xlfd (font, pixel_size, name, 256);
4238 if (namelen < 0)
4239 return Qnil;
4240 done:
4241 if (! NILP (fold_wildcards))
4242 {
4243 char *p0 = name, *p1;
4244
4245 while ((p1 = strstr (p0, "-*-*")))
4246 {
4247 strcpy (p1, p1 + 2);
4248 namelen -= 2;
4249 p0 = p1;
4250 }
4251 }
4252
4253 return make_string (name, namelen);
4254 }
4255
4256 void
4257 clear_font_cache (struct frame *f)
4258 {
4259 struct font_driver_list *driver_list = f->font_driver_list;
4260
4261 for (; driver_list; driver_list = driver_list->next)
4262 if (driver_list->on)
4263 {
4264 Lisp_Object val, tmp, cache = driver_list->driver->get_cache (f);
4265
4266 val = XCDR (cache);
4267 while (! NILP (val)
4268 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
4269 val = XCDR (val);
4270 eassert (! NILP (val));
4271 tmp = XCDR (XCAR (val));
4272 if (XINT (XCAR (tmp)) == 0)
4273 {
4274 font_clear_cache (f, XCAR (val), driver_list->driver);
4275 XSETCDR (cache, XCDR (val));
4276 }
4277 }
4278 }
4279
4280 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
4281 doc: /* Clear font cache of each frame. */)
4282 (void)
4283 {
4284 Lisp_Object list, frame;
4285
4286 FOR_EACH_FRAME (list, frame)
4287 clear_font_cache (XFRAME (frame));
4288
4289 return Qnil;
4290 }
4291
4292 \f
4293 void
4294 font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object)
4295 {
4296 struct font *font = XFONT_OBJECT (font_object);
4297 unsigned code = font->driver->encode_char (font, LGLYPH_CHAR (glyph));
4298 struct font_metrics metrics;
4299
4300 LGLYPH_SET_CODE (glyph, code);
4301 font->driver->text_extents (font, &code, 1, &metrics);
4302 LGLYPH_SET_LBEARING (glyph, metrics.lbearing);
4303 LGLYPH_SET_RBEARING (glyph, metrics.rbearing);
4304 LGLYPH_SET_WIDTH (glyph, metrics.width);
4305 LGLYPH_SET_ASCENT (glyph, metrics.ascent);
4306 LGLYPH_SET_DESCENT (glyph, metrics.descent);
4307 }
4308
4309
4310 DEFUN ("font-shape-gstring", Ffont_shape_gstring, Sfont_shape_gstring, 1, 1, 0,
4311 doc: /* Shape the glyph-string GSTRING.
4312 Shaping means substituting glyphs and/or adjusting positions of glyphs
4313 to get the correct visual image of character sequences set in the
4314 header of the glyph-string.
4315
4316 If the shaping was successful, the value is GSTRING itself or a newly
4317 created glyph-string. Otherwise, the value is nil.
4318
4319 See the documentation of `composition-get-gstring' for the format of
4320 GSTRING. */)
4321 (Lisp_Object gstring)
4322 {
4323 struct font *font;
4324 Lisp_Object font_object, n, glyph;
4325 ptrdiff_t i, from, to;
4326
4327 if (! composition_gstring_p (gstring))
4328 signal_error ("Invalid glyph-string: ", gstring);
4329 if (! NILP (LGSTRING_ID (gstring)))
4330 return gstring;
4331 font_object = LGSTRING_FONT (gstring);
4332 CHECK_FONT_OBJECT (font_object);
4333 font = XFONT_OBJECT (font_object);
4334 if (! font->driver->shape)
4335 return Qnil;
4336
4337 /* Try at most three times with larger gstring each time. */
4338 for (i = 0; i < 3; i++)
4339 {
4340 n = font->driver->shape (gstring);
4341 if (INTEGERP (n))
4342 break;
4343 gstring = larger_vector (gstring,
4344 LGSTRING_GLYPH_LEN (gstring), -1);
4345 }
4346 if (i == 3 || XINT (n) == 0)
4347 return Qnil;
4348 if (XINT (n) < LGSTRING_GLYPH_LEN (gstring))
4349 LGSTRING_SET_GLYPH (gstring, XINT (n), Qnil);
4350
4351 /* Check FROM_IDX and TO_IDX of each GLYPH in GSTRING to assure that
4352 GLYPHS covers all characters (except for the last few ones) in
4353 GSTRING. More formally, provided that NCHARS is the number of
4354 characters in GSTRING and GLYPHS[i] is the ith glyph, FROM_IDX
4355 and TO_IDX of each glyph must satisfy these conditions:
4356
4357 GLYPHS[0].FROM_IDX == 0
4358 GLYPHS[i].FROM_IDX <= GLYPHS[i].TO_IDX
4359 if (GLYPHS[i].FROM_IDX == GLYPHS[i-1].FROM_IDX)
4360 ;; GLYPHS[i] and GLYPHS[i-1] belongs to the same grapheme cluster
4361 GLYPHS[i].TO_IDX == GLYPHS[i-1].TO_IDX
4362 else
4363 ;; Be sure to cover all characters.
4364 GLYPHS[i].FROM_IDX == GLYPHS[i-1].TO_IDX + 1 */
4365 glyph = LGSTRING_GLYPH (gstring, 0);
4366 from = LGLYPH_FROM (glyph);
4367 to = LGLYPH_TO (glyph);
4368 if (from != 0 || to < from)
4369 goto shaper_error;
4370 for (i = 1; i < LGSTRING_GLYPH_LEN (gstring); i++)
4371 {
4372 glyph = LGSTRING_GLYPH (gstring, i);
4373 if (NILP (glyph))
4374 break;
4375 if (! (LGLYPH_FROM (glyph) <= LGLYPH_TO (glyph)
4376 && (LGLYPH_FROM (glyph) == from
4377 ? LGLYPH_TO (glyph) == to
4378 : LGLYPH_FROM (glyph) == to + 1)))
4379 goto shaper_error;
4380 from = LGLYPH_FROM (glyph);
4381 to = LGLYPH_TO (glyph);
4382 }
4383 return composition_gstring_put_cache (gstring, XINT (n));
4384
4385 shaper_error:
4386 return Qnil;
4387 }
4388
4389 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
4390 2, 2, 0,
4391 doc: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4392 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4393 where
4394 VARIATION-SELECTOR is a character code of variation selection
4395 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4396 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4397 (Lisp_Object font_object, Lisp_Object character)
4398 {
4399 unsigned variations[256];
4400 struct font *font;
4401 int i, n;
4402 Lisp_Object val;
4403
4404 CHECK_FONT_OBJECT (font_object);
4405 CHECK_CHARACTER (character);
4406 font = XFONT_OBJECT (font_object);
4407 if (! font->driver->get_variation_glyphs)
4408 return Qnil;
4409 n = font->driver->get_variation_glyphs (font, XINT (character), variations);
4410 if (! n)
4411 return Qnil;
4412 val = Qnil;
4413 for (i = 0; i < 255; i++)
4414 if (variations[i])
4415 {
4416 int vs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
4417 Lisp_Object code = INTEGER_TO_CONS (variations[i]);
4418 val = Fcons (Fcons (make_number (vs), code), val);
4419 }
4420 return val;
4421 }
4422
4423 #if 0
4424
4425 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
4426 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
4427 OTF-FEATURES specifies which features to apply in this format:
4428 (SCRIPT LANGSYS GSUB GPOS)
4429 where
4430 SCRIPT is a symbol specifying a script tag of OpenType,
4431 LANGSYS is a symbol specifying a langsys tag of OpenType,
4432 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4433
4434 If LANGSYS is nil, the default langsys is selected.
4435
4436 The features are applied in the order they appear in the list. The
4437 symbol `*' means to apply all available features not present in this
4438 list, and the remaining features are ignored. For instance, (vatu
4439 pstf * haln) is to apply vatu and pstf in this order, then to apply
4440 all available features other than vatu, pstf, and haln.
4441
4442 The features are applied to the glyphs in the range FROM and TO of
4443 the glyph-string GSTRING-IN.
4444
4445 If some feature is actually applicable, the resulting glyphs are
4446 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4447 this case, the value is the number of produced glyphs.
4448
4449 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4450 the value is 0.
4451
4452 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4453 produced in GSTRING-OUT, and the value is nil.
4454
4455 See the documentation of `composition-get-gstring' for the format of
4456 glyph-string. */)
4457 (Lisp_Object otf_features, Lisp_Object gstring_in, Lisp_Object from, Lisp_Object to, Lisp_Object gstring_out, Lisp_Object index)
4458 {
4459 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
4460 Lisp_Object val;
4461 struct font *font;
4462 int len, num;
4463
4464 check_otf_features (otf_features);
4465 CHECK_FONT_OBJECT (font_object);
4466 font = XFONT_OBJECT (font_object);
4467 if (! font->driver->otf_drive)
4468 error ("Font backend %s can't drive OpenType GSUB table",
4469 SDATA (SYMBOL_NAME (font->driver->type)));
4470 CHECK_CONS (otf_features);
4471 CHECK_SYMBOL (XCAR (otf_features));
4472 val = XCDR (otf_features);
4473 CHECK_SYMBOL (XCAR (val));
4474 val = XCDR (otf_features);
4475 if (! NILP (val))
4476 CHECK_CONS (val);
4477 len = check_gstring (gstring_in);
4478 CHECK_VECTOR (gstring_out);
4479 CHECK_NATNUM (from);
4480 CHECK_NATNUM (to);
4481 CHECK_NATNUM (index);
4482
4483 if (XINT (from) >= XINT (to) || XINT (to) > len)
4484 args_out_of_range_3 (from, to, make_number (len));
4485 if (XINT (index) >= ASIZE (gstring_out))
4486 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4487 num = font->driver->otf_drive (font, otf_features,
4488 gstring_in, XINT (from), XINT (to),
4489 gstring_out, XINT (index), 0);
4490 if (num < 0)
4491 return Qnil;
4492 return make_number (num);
4493 }
4494
4495 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4496 3, 3, 0,
4497 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4498 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4499 in this format:
4500 (SCRIPT LANGSYS FEATURE ...)
4501 See the documentation of `font-drive-otf' for more detail.
4502
4503 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4504 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4505 character code corresponding to the glyph or nil if there's no
4506 corresponding character. */)
4507 (Lisp_Object font_object, Lisp_Object character, Lisp_Object otf_features)
4508 {
4509 struct font *font;
4510 Lisp_Object gstring_in, gstring_out, g;
4511 Lisp_Object alternates;
4512 int i, num;
4513
4514 CHECK_FONT_GET_OBJECT (font_object, font);
4515 if (! font->driver->otf_drive)
4516 error ("Font backend %s can't drive OpenType GSUB table",
4517 SDATA (SYMBOL_NAME (font->driver->type)));
4518 CHECK_CHARACTER (character);
4519 CHECK_CONS (otf_features);
4520
4521 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4522 g = LGSTRING_GLYPH (gstring_in, 0);
4523 LGLYPH_SET_CHAR (g, XINT (character));
4524 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4525 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4526 gstring_out, 0, 1)) < 0)
4527 gstring_out = Ffont_make_gstring (font_object,
4528 make_number (ASIZE (gstring_out) * 2));
4529 alternates = Qnil;
4530 for (i = 0; i < num; i++)
4531 {
4532 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4533 int c = LGLYPH_CHAR (g);
4534 unsigned code = LGLYPH_CODE (g);
4535
4536 alternates = Fcons (Fcons (make_number (code),
4537 c > 0 ? make_number (c) : Qnil),
4538 alternates);
4539 }
4540 return Fnreverse (alternates);
4541 }
4542 #endif /* 0 */
4543
4544 #ifdef FONT_DEBUG
4545
4546 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4547 doc: /* Open FONT-ENTITY. */)
4548 (Lisp_Object font_entity, Lisp_Object size, Lisp_Object frame)
4549 {
4550 EMACS_INT isize;
4551 struct frame *f = decode_live_frame (frame);
4552
4553 CHECK_FONT_ENTITY (font_entity);
4554
4555 if (NILP (size))
4556 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4557 else
4558 {
4559 CHECK_NUMBER_OR_FLOAT (size);
4560 if (FLOATP (size))
4561 isize = POINT_TO_PIXEL (XFLOAT_DATA (size), FRAME_RES_Y (f));
4562 else
4563 isize = XINT (size);
4564 if (! (INT_MIN <= isize && isize <= INT_MAX))
4565 args_out_of_range (font_entity, size);
4566 if (isize == 0)
4567 isize = 120;
4568 }
4569 return font_open_entity (f, font_entity, isize);
4570 }
4571
4572 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4573 doc: /* Close FONT-OBJECT. */)
4574 (Lisp_Object font_object, Lisp_Object frame)
4575 {
4576 CHECK_FONT_OBJECT (font_object);
4577 font_close_object (decode_live_frame (frame), font_object);
4578 return Qnil;
4579 }
4580
4581 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4582 doc: /* Return information about FONT-OBJECT.
4583 The value is a vector:
4584 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4585 CAPABILITY ]
4586
4587 NAME is the font name, a string (or nil if the font backend doesn't
4588 provide a name).
4589
4590 FILENAME is the font file name, a string (or nil if the font backend
4591 doesn't provide a file name).
4592
4593 PIXEL-SIZE is a pixel size by which the font is opened.
4594
4595 SIZE is a maximum advance width of the font in pixels.
4596
4597 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4598 pixels.
4599
4600 CAPABILITY is a list whose first element is a symbol representing the
4601 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4602 remaining elements describe the details of the font capability.
4603
4604 If the font is OpenType font, the form of the list is
4605 \(opentype GSUB GPOS)
4606 where GSUB shows which "GSUB" features the font supports, and GPOS
4607 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4608 lists of the format:
4609 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4610
4611 If the font is not OpenType font, currently the length of the form is
4612 one.
4613
4614 SCRIPT is a symbol representing OpenType script tag.
4615
4616 LANGSYS is a symbol representing OpenType langsys tag, or nil
4617 representing the default langsys.
4618
4619 FEATURE is a symbol representing OpenType feature tag.
4620
4621 If the font is not OpenType font, CAPABILITY is nil. */)
4622 (Lisp_Object font_object)
4623 {
4624 struct font *font;
4625 Lisp_Object val;
4626
4627 CHECK_FONT_GET_OBJECT (font_object, font);
4628
4629 val = make_uninit_vector (9);
4630 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4631 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4632 ASET (val, 2, make_number (font->pixel_size));
4633 ASET (val, 3, make_number (font->max_width));
4634 ASET (val, 4, make_number (font->ascent));
4635 ASET (val, 5, make_number (font->descent));
4636 ASET (val, 6, make_number (font->space_width));
4637 ASET (val, 7, make_number (font->average_width));
4638 if (font->driver->otf_capability)
4639 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4640 else
4641 ASET (val, 8, Qnil);
4642 return val;
4643 }
4644
4645 DEFUN ("font-get-glyphs", Ffont_get_glyphs, Sfont_get_glyphs, 3, 4, 0,
4646 doc:
4647 /* Return a vector of FONT-OBJECT's glyphs for the specified characters.
4648 FROM and TO are positions (integers or markers) specifying a region
4649 of the current buffer.
4650 If the optional fourth arg OBJECT is not nil, it is a string or a
4651 vector containing the target characters.
4652
4653 Each element is a vector containing information of a glyph in this format:
4654 [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
4655 where
4656 FROM is an index numbers of a character the glyph corresponds to.
4657 TO is the same as FROM.
4658 C is the character of the glyph.
4659 CODE is the glyph-code of C in FONT-OBJECT.
4660 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
4661 ADJUSTMENT is always nil.
4662 If FONT-OBJECT doesn't have a glyph for a character,
4663 the corresponding element is nil. */)
4664 (Lisp_Object font_object, Lisp_Object from, Lisp_Object to,
4665 Lisp_Object object)
4666 {
4667 struct font *font;
4668 ptrdiff_t i, len;
4669 Lisp_Object *chars, vec;
4670 USE_SAFE_ALLOCA;
4671
4672 CHECK_FONT_GET_OBJECT (font_object, font);
4673 if (NILP (object))
4674 {
4675 ptrdiff_t charpos, bytepos;
4676
4677 validate_region (&from, &to);
4678 if (EQ (from, to))
4679 return Qnil;
4680 len = XFASTINT (to) - XFASTINT (from);
4681 SAFE_ALLOCA_LISP (chars, len);
4682 charpos = XFASTINT (from);
4683 bytepos = CHAR_TO_BYTE (charpos);
4684 for (i = 0; charpos < XFASTINT (to); i++)
4685 {
4686 int c;
4687 FETCH_CHAR_ADVANCE (c, charpos, bytepos);
4688 chars[i] = make_number (c);
4689 }
4690 }
4691 else if (STRINGP (object))
4692 {
4693 const unsigned char *p;
4694
4695 CHECK_NUMBER (from);
4696 CHECK_NUMBER (to);
4697 if (XINT (from) < 0 || XINT (from) > XINT (to)
4698 || XINT (to) > SCHARS (object))
4699 args_out_of_range_3 (object, from, to);
4700 if (EQ (from, to))
4701 return Qnil;
4702 len = XFASTINT (to) - XFASTINT (from);
4703 SAFE_ALLOCA_LISP (chars, len);
4704 p = SDATA (object);
4705 if (STRING_MULTIBYTE (object))
4706 for (i = 0; i < len; i++)
4707 {
4708 int c = STRING_CHAR_ADVANCE (p);
4709 chars[i] = make_number (c);
4710 }
4711 else
4712 for (i = 0; i < len; i++)
4713 chars[i] = make_number (p[i]);
4714 }
4715 else
4716 {
4717 CHECK_VECTOR (object);
4718 CHECK_NUMBER (from);
4719 CHECK_NUMBER (to);
4720 if (XINT (from) < 0 || XINT (from) > XINT (to)
4721 || XINT (to) > ASIZE (object))
4722 args_out_of_range_3 (object, from, to);
4723 if (EQ (from, to))
4724 return Qnil;
4725 len = XFASTINT (to) - XFASTINT (from);
4726 for (i = 0; i < len; i++)
4727 {
4728 Lisp_Object elt = AREF (object, XFASTINT (from) + i);
4729 CHECK_CHARACTER (elt);
4730 }
4731 chars = aref_addr (object, XFASTINT (from));
4732 }
4733
4734 vec = make_uninit_vector (len);
4735 for (i = 0; i < len; i++)
4736 {
4737 Lisp_Object g;
4738 int c = XFASTINT (chars[i]);
4739 unsigned code;
4740 struct font_metrics metrics;
4741
4742 code = font->driver->encode_char (font, c);
4743 if (code == FONT_INVALID_CODE)
4744 {
4745 ASET (vec, i, Qnil);
4746 continue;
4747 }
4748 g = LGLYPH_NEW ();
4749 LGLYPH_SET_FROM (g, i);
4750 LGLYPH_SET_TO (g, i);
4751 LGLYPH_SET_CHAR (g, c);
4752 LGLYPH_SET_CODE (g, code);
4753 font->driver->text_extents (font, &code, 1, &metrics);
4754 LGLYPH_SET_WIDTH (g, metrics.width);
4755 LGLYPH_SET_LBEARING (g, metrics.lbearing);
4756 LGLYPH_SET_RBEARING (g, metrics.rbearing);
4757 LGLYPH_SET_ASCENT (g, metrics.ascent);
4758 LGLYPH_SET_DESCENT (g, metrics.descent);
4759 ASET (vec, i, g);
4760 }
4761 if (! VECTORP (object))
4762 SAFE_FREE ();
4763 return vec;
4764 }
4765
4766 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4767 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4768 FONT is a font-spec, font-entity, or font-object. */)
4769 (Lisp_Object spec, Lisp_Object font)
4770 {
4771 CHECK_FONT_SPEC (spec);
4772 CHECK_FONT (font);
4773
4774 return (font_match_p (spec, font) ? Qt : Qnil);
4775 }
4776
4777 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4778 doc: /* Return a font-object for displaying a character at POSITION.
4779 Optional second arg WINDOW, if non-nil, is a window displaying
4780 the current buffer. It defaults to the currently selected window.
4781 Optional third arg STRING, if non-nil, is a string containing the target
4782 character at index specified by POSITION. */)
4783 (Lisp_Object position, Lisp_Object window, Lisp_Object string)
4784 {
4785 struct window *w = decode_live_window (window);
4786
4787 if (NILP (string))
4788 {
4789 if (XBUFFER (w->contents) != current_buffer)
4790 error ("Specified window is not displaying the current buffer");
4791 CHECK_NUMBER_COERCE_MARKER (position);
4792 if (! (BEGV <= XINT (position) && XINT (position) < ZV))
4793 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4794 }
4795 else
4796 {
4797 CHECK_NUMBER (position);
4798 CHECK_STRING (string);
4799 if (! (0 <= XINT (position) && XINT (position) < SCHARS (string)))
4800 args_out_of_range (string, position);
4801 }
4802
4803 return font_at (-1, XINT (position), NULL, w, string);
4804 }
4805
4806 #if 0
4807 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4808 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4809 The value is a number of glyphs drawn.
4810 Type C-l to recover what previously shown. */)
4811 (Lisp_Object font_object, Lisp_Object string)
4812 {
4813 Lisp_Object frame = selected_frame;
4814 struct frame *f = XFRAME (frame);
4815 struct font *font;
4816 struct face *face;
4817 int i, len, width;
4818 unsigned *code;
4819
4820 CHECK_FONT_GET_OBJECT (font_object, font);
4821 CHECK_STRING (string);
4822 len = SCHARS (string);
4823 code = alloca (sizeof (unsigned) * len);
4824 for (i = 0; i < len; i++)
4825 {
4826 Lisp_Object ch = Faref (string, make_number (i));
4827 Lisp_Object val;
4828 int c = XINT (ch);
4829
4830 code[i] = font->driver->encode_char (font, c);
4831 if (code[i] == FONT_INVALID_CODE)
4832 break;
4833 }
4834 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4835 face->fontp = font;
4836 if (font->driver->prepare_face)
4837 font->driver->prepare_face (f, face);
4838 width = font->driver->text_extents (font, code, i, NULL);
4839 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4840 if (font->driver->done_face)
4841 font->driver->done_face (f, face);
4842 face->fontp = NULL;
4843 return make_number (len);
4844 }
4845 #endif
4846
4847 DEFUN ("frame-font-cache", Fframe_font_cache, Sframe_font_cache, 0, 1, 0,
4848 doc: /* Return FRAME's font cache. Mainly used for debugging.
4849 If FRAME is omitted or nil, use the selected frame. */)
4850 (Lisp_Object frame)
4851 {
4852 #ifdef HAVE_WINDOW_SYSTEM
4853 struct frame *f = decode_live_frame (frame);
4854
4855 if (FRAME_WINDOW_P (f))
4856 return FRAME_DISPLAY_INFO (f)->name_list_element;
4857 else
4858 #endif
4859 return Qnil;
4860 }
4861
4862 #endif /* FONT_DEBUG */
4863
4864 #ifdef HAVE_WINDOW_SYSTEM
4865
4866 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
4867 doc: /* Return information about a font named NAME on frame FRAME.
4868 If FRAME is omitted or nil, use the selected frame.
4869 The returned value is a vector of OPENED-NAME, FULL-NAME, SIZE,
4870 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4871 where
4872 OPENED-NAME is the name used for opening the font,
4873 FULL-NAME is the full name of the font,
4874 SIZE is the pixelsize of the font,
4875 HEIGHT is the pixel-height of the font (i.e., ascent + descent),
4876 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4877 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4878 how to compose characters.
4879 If the named font is not yet loaded, return nil. */)
4880 (Lisp_Object name, Lisp_Object frame)
4881 {
4882 struct frame *f;
4883 struct font *font;
4884 Lisp_Object info;
4885 Lisp_Object font_object;
4886
4887 if (! FONTP (name))
4888 CHECK_STRING (name);
4889 f = decode_window_system_frame (frame);
4890
4891 if (STRINGP (name))
4892 {
4893 int fontset = fs_query_fontset (name, 0);
4894
4895 if (fontset >= 0)
4896 name = fontset_ascii (fontset);
4897 font_object = font_open_by_name (f, name);
4898 }
4899 else if (FONT_OBJECT_P (name))
4900 font_object = name;
4901 else if (FONT_ENTITY_P (name))
4902 font_object = font_open_entity (f, name, 0);
4903 else
4904 {
4905 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4906 Lisp_Object entity = font_matching_entity (f, face->lface, name);
4907
4908 font_object = ! NILP (entity) ? font_open_entity (f, entity, 0) : Qnil;
4909 }
4910 if (NILP (font_object))
4911 return Qnil;
4912 font = XFONT_OBJECT (font_object);
4913
4914 info = make_uninit_vector (7);
4915 ASET (info, 0, AREF (font_object, FONT_NAME_INDEX));
4916 ASET (info, 1, AREF (font_object, FONT_FULLNAME_INDEX));
4917 ASET (info, 2, make_number (font->pixel_size));
4918 ASET (info, 3, make_number (font->height));
4919 ASET (info, 4, make_number (font->baseline_offset));
4920 ASET (info, 5, make_number (font->relative_compose));
4921 ASET (info, 6, make_number (font->default_ascent));
4922
4923 #if 0
4924 /* As font_object is still in FONT_OBJLIST of the entity, we can't
4925 close it now. Perhaps, we should manage font-objects
4926 by `reference-count'. */
4927 font_close_object (f, font_object);
4928 #endif
4929 return info;
4930 }
4931 #endif
4932
4933 \f
4934 #define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, ARRAYELTS (TBL))
4935
4936 static Lisp_Object
4937 build_style_table (const struct table_entry *entry, int nelement)
4938 {
4939 int i, j;
4940 Lisp_Object table, elt;
4941
4942 table = make_uninit_vector (nelement);
4943 for (i = 0; i < nelement; i++)
4944 {
4945 for (j = 0; entry[i].names[j]; j++);
4946 elt = Fmake_vector (make_number (j + 1), Qnil);
4947 ASET (elt, 0, make_number (entry[i].numeric));
4948 for (j = 0; entry[i].names[j]; j++)
4949 ASET (elt, j + 1, intern_c_string (entry[i].names[j]));
4950 ASET (table, i, elt);
4951 }
4952 return table;
4953 }
4954
4955 /* The deferred font-log data of the form [ACTION ARG RESULT].
4956 If ACTION is not nil, that is added to the log when font_add_log is
4957 called next time. At that time, ACTION is set back to nil. */
4958 static Lisp_Object Vfont_log_deferred;
4959
4960 /* Prepend the font-related logging data in Vfont_log if it is not
4961 `t'. ACTION describes a kind of font-related action (e.g. listing,
4962 opening), ARG is the argument for the action, and RESULT is the
4963 result of the action. */
4964 void
4965 font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
4966 {
4967 Lisp_Object val;
4968 int i;
4969
4970 if (EQ (Vfont_log, Qt))
4971 return;
4972 if (STRINGP (AREF (Vfont_log_deferred, 0)))
4973 {
4974 char *str = SSDATA (AREF (Vfont_log_deferred, 0));
4975
4976 ASET (Vfont_log_deferred, 0, Qnil);
4977 font_add_log (str, AREF (Vfont_log_deferred, 1),
4978 AREF (Vfont_log_deferred, 2));
4979 }
4980
4981 if (FONTP (arg))
4982 {
4983 Lisp_Object tail, elt;
4984 Lisp_Object equalstr = build_string ("=");
4985
4986 val = Ffont_xlfd_name (arg, Qt);
4987 for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail);
4988 tail = XCDR (tail))
4989 {
4990 elt = XCAR (tail);
4991 if (EQ (XCAR (elt), QCscript)
4992 && SYMBOLP (XCDR (elt)))
4993 val = concat3 (val, SYMBOL_NAME (QCscript),
4994 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
4995 else if (EQ (XCAR (elt), QClang)
4996 && SYMBOLP (XCDR (elt)))
4997 val = concat3 (val, SYMBOL_NAME (QClang),
4998 concat2 (equalstr, SYMBOL_NAME (XCDR (elt))));
4999 else if (EQ (XCAR (elt), QCotf)
5000 && CONSP (XCDR (elt)) && SYMBOLP (XCAR (XCDR (elt))))
5001 val = concat3 (val, SYMBOL_NAME (QCotf),
5002 concat2 (equalstr,
5003 SYMBOL_NAME (XCAR (XCDR (elt)))));
5004 }
5005 arg = val;
5006 }
5007
5008 if (CONSP (result)
5009 && VECTORP (XCAR (result))
5010 && ASIZE (XCAR (result)) > 0
5011 && FONTP (AREF (XCAR (result), 0)))
5012 result = font_vconcat_entity_vectors (result);
5013 if (FONTP (result))
5014 {
5015 val = Ffont_xlfd_name (result, Qt);
5016 if (! FONT_SPEC_P (result))
5017 val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)),
5018 build_string (":"), val);
5019 result = val;
5020 }
5021 else if (CONSP (result))
5022 {
5023 Lisp_Object tail;
5024 result = Fcopy_sequence (result);
5025 for (tail = result; CONSP (tail); tail = XCDR (tail))
5026 {
5027 val = XCAR (tail);
5028 if (FONTP (val))
5029 val = Ffont_xlfd_name (val, Qt);
5030 XSETCAR (tail, val);
5031 }
5032 }
5033 else if (VECTORP (result))
5034 {
5035 result = Fcopy_sequence (result);
5036 for (i = 0; i < ASIZE (result); i++)
5037 {
5038 val = AREF (result, i);
5039 if (FONTP (val))
5040 val = Ffont_xlfd_name (val, Qt);
5041 ASET (result, i, val);
5042 }
5043 }
5044 Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
5045 }
5046
5047 /* Record a font-related logging data to be added to Vfont_log when
5048 font_add_log is called next time. ACTION, ARG, RESULT are the same
5049 as font_add_log. */
5050
5051 void
5052 font_deferred_log (const char *action, Lisp_Object arg, Lisp_Object result)
5053 {
5054 if (EQ (Vfont_log, Qt))
5055 return;
5056 ASET (Vfont_log_deferred, 0, build_string (action));
5057 ASET (Vfont_log_deferred, 1, arg);
5058 ASET (Vfont_log_deferred, 2, result);
5059 }
5060
5061 void
5062 syms_of_font (void)
5063 {
5064 sort_shift_bits[FONT_TYPE_INDEX] = 0;
5065 sort_shift_bits[FONT_SLANT_INDEX] = 2;
5066 sort_shift_bits[FONT_WEIGHT_INDEX] = 9;
5067 sort_shift_bits[FONT_SIZE_INDEX] = 16;
5068 sort_shift_bits[FONT_WIDTH_INDEX] = 23;
5069 /* Note that the other elements in sort_shift_bits are not used. */
5070
5071 staticpro (&font_charset_alist);
5072 font_charset_alist = Qnil;
5073
5074 DEFSYM (Qopentype, "opentype");
5075
5076 DEFSYM (Qascii_0, "ascii-0");
5077 DEFSYM (Qiso8859_1, "iso8859-1");
5078 DEFSYM (Qiso10646_1, "iso10646-1");
5079 DEFSYM (Qunicode_bmp, "unicode-bmp");
5080 DEFSYM (Qunicode_sip, "unicode-sip");
5081
5082 DEFSYM (QCf, "Cf");
5083
5084 DEFSYM (QCotf, ":otf");
5085 DEFSYM (QClang, ":lang");
5086 DEFSYM (QCscript, ":script");
5087 DEFSYM (QCantialias, ":antialias");
5088
5089 DEFSYM (QCfoundry, ":foundry");
5090 DEFSYM (QCadstyle, ":adstyle");
5091 DEFSYM (QCregistry, ":registry");
5092 DEFSYM (QCspacing, ":spacing");
5093 DEFSYM (QCdpi, ":dpi");
5094 DEFSYM (QCscalable, ":scalable");
5095 DEFSYM (QCavgwidth, ":avgwidth");
5096 DEFSYM (QCfont_entity, ":font-entity");
5097 DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
5098
5099 DEFSYM (Qc, "c");
5100 DEFSYM (Qm, "m");
5101 DEFSYM (Qp, "p");
5102 DEFSYM (Qd, "d");
5103
5104 DEFSYM (Qja, "ja");
5105 DEFSYM (Qko, "ko");
5106
5107 DEFSYM (QCuser_spec, "user-spec");
5108
5109 staticpro (&scratch_font_spec);
5110 scratch_font_spec = Ffont_spec (0, NULL);
5111 staticpro (&scratch_font_prefer);
5112 scratch_font_prefer = Ffont_spec (0, NULL);
5113
5114 staticpro (&Vfont_log_deferred);
5115 Vfont_log_deferred = Fmake_vector (make_number (3), Qnil);
5116
5117 #if 0
5118 #ifdef HAVE_LIBOTF
5119 staticpro (&otf_list);
5120 otf_list = Qnil;
5121 #endif /* HAVE_LIBOTF */
5122 #endif /* 0 */
5123
5124 defsubr (&Sfontp);
5125 defsubr (&Sfont_spec);
5126 defsubr (&Sfont_get);
5127 #ifdef HAVE_WINDOW_SYSTEM
5128 defsubr (&Sfont_face_attributes);
5129 #endif
5130 defsubr (&Sfont_put);
5131 defsubr (&Slist_fonts);
5132 defsubr (&Sfont_family_list);
5133 defsubr (&Sfind_font);
5134 defsubr (&Sfont_xlfd_name);
5135 defsubr (&Sclear_font_cache);
5136 defsubr (&Sfont_shape_gstring);
5137 defsubr (&Sfont_variation_glyphs);
5138 #if 0
5139 defsubr (&Sfont_drive_otf);
5140 defsubr (&Sfont_otf_alternates);
5141 #endif /* 0 */
5142
5143 #ifdef FONT_DEBUG
5144 defsubr (&Sopen_font);
5145 defsubr (&Sclose_font);
5146 defsubr (&Squery_font);
5147 defsubr (&Sfont_get_glyphs);
5148 defsubr (&Sfont_match_p);
5149 defsubr (&Sfont_at);
5150 #if 0
5151 defsubr (&Sdraw_string);
5152 #endif
5153 defsubr (&Sframe_font_cache);
5154 #endif /* FONT_DEBUG */
5155 #ifdef HAVE_WINDOW_SYSTEM
5156 defsubr (&Sfont_info);
5157 #endif
5158
5159 DEFVAR_LISP ("font-encoding-alist", Vfont_encoding_alist,
5160 doc: /*
5161 Alist of fontname patterns vs the corresponding encoding and repertory info.
5162 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5163 where ENCODING is a charset or a char-table,
5164 and REPERTORY is a charset, a char-table, or nil.
5165
5166 If ENCODING and REPERTORY are the same, the element can have the form
5167 \(REGEXP . ENCODING).
5168
5169 ENCODING is for converting a character to a glyph code of the font.
5170 If ENCODING is a charset, encoding a character by the charset gives
5171 the corresponding glyph code. If ENCODING is a char-table, looking up
5172 the table by a character gives the corresponding glyph code.
5173
5174 REPERTORY specifies a repertory of characters supported by the font.
5175 If REPERTORY is a charset, all characters belonging to the charset are
5176 supported. If REPERTORY is a char-table, all characters who have a
5177 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5178 gets the repertory information by an opened font and ENCODING. */);
5179 Vfont_encoding_alist = Qnil;
5180
5181 /* FIXME: These 3 vars are not quite what they appear: setq on them
5182 won't have any effect other than disconnect them from the style
5183 table used by the font display code. So we make them read-only,
5184 to avoid this confusing situation. */
5185
5186 DEFVAR_LISP_NOPRO ("font-weight-table", Vfont_weight_table,
5187 doc: /* Vector of valid font weight values.
5188 Each element has the form:
5189 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5190 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5191 Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
5192 XSYMBOL (intern_c_string ("font-weight-table"))->constant = 1;
5193
5194 DEFVAR_LISP_NOPRO ("font-slant-table", Vfont_slant_table,
5195 doc: /* Vector of font slant symbols vs the corresponding numeric values.
5196 See `font-weight-table' for the format of the vector. */);
5197 Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
5198 XSYMBOL (intern_c_string ("font-slant-table"))->constant = 1;
5199
5200 DEFVAR_LISP_NOPRO ("font-width-table", Vfont_width_table,
5201 doc: /* Alist of font width symbols vs the corresponding numeric values.
5202 See `font-weight-table' for the format of the vector. */);
5203 Vfont_width_table = BUILD_STYLE_TABLE (width_table);
5204 XSYMBOL (intern_c_string ("font-width-table"))->constant = 1;
5205
5206 staticpro (&font_style_table);
5207 font_style_table = make_uninit_vector (3);
5208 ASET (font_style_table, 0, Vfont_weight_table);
5209 ASET (font_style_table, 1, Vfont_slant_table);
5210 ASET (font_style_table, 2, Vfont_width_table);
5211
5212 DEFVAR_LISP ("font-log", Vfont_log, doc: /*
5213 *Logging list of font related actions and results.
5214 The value t means to suppress the logging.
5215 The initial value is set to nil if the environment variable
5216 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5217 Vfont_log = Qnil;
5218
5219 #ifdef HAVE_WINDOW_SYSTEM
5220 #ifdef HAVE_FREETYPE
5221 syms_of_ftfont ();
5222 #ifdef HAVE_X_WINDOWS
5223 syms_of_xfont ();
5224 syms_of_ftxfont ();
5225 #ifdef HAVE_XFT
5226 syms_of_xftfont ();
5227 #endif /* HAVE_XFT */
5228 #endif /* HAVE_X_WINDOWS */
5229 #else /* not HAVE_FREETYPE */
5230 #ifdef HAVE_X_WINDOWS
5231 syms_of_xfont ();
5232 #endif /* HAVE_X_WINDOWS */
5233 #endif /* not HAVE_FREETYPE */
5234 #ifdef HAVE_BDFFONT
5235 syms_of_bdffont ();
5236 #endif /* HAVE_BDFFONT */
5237 #ifdef HAVE_NTGUI
5238 syms_of_w32font ();
5239 #endif /* HAVE_NTGUI */
5240 #endif /* HAVE_WINDOW_SYSTEM */
5241 }
5242
5243 void
5244 init_font (void)
5245 {
5246 Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;
5247 }