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