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