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