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