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