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