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