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