(font_score): Ignore the diffference of alias style symbols.
[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 if (diff > 0)
2121 score |= min (diff, 127) << sort_shift_bits[i];
2122 }
2123
2124 /* Score the size. Maximum difference is 127. */
2125 i = FONT_SIZE_INDEX;
2126 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i])
2127 && XINT (AREF (entity, i)) > 0)
2128 {
2129 /* We use the higher 6-bit for the actual size difference. The
2130 lowest bit is set if the DPI is different. */
2131 int diff = XINT (spec_prop[i]) - XINT (AREF (entity, i));
2132
2133 if (diff < 0)
2134 diff = - diff;
2135 diff <<= 1;
2136 if (! NILP (spec_prop[FONT_DPI_INDEX])
2137 && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX)))
2138 diff |= 1;
2139 score |= min (diff, 127) << sort_shift_bits[FONT_SIZE_INDEX];
2140 }
2141
2142 return score;
2143 }
2144
2145
2146 /* The comparison function for qsort. */
2147
2148 static int
2149 font_compare (d1, d2)
2150 const void *d1, *d2;
2151 {
2152 return (*(unsigned *) d1 - *(unsigned *) d2);
2153 }
2154
2155
2156 /* The structure for elements being sorted by qsort. */
2157 struct font_sort_data
2158 {
2159 unsigned score;
2160 Lisp_Object entity;
2161 };
2162
2163
2164 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2165 If PREFER specifies a point-size, calculate the corresponding
2166 pixel-size from QCdpi property of PREFER or from the Y-resolution
2167 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
2168 get the font-entities in VEC.
2169
2170 If BEST-ONLY is nonzero, return the best matching entity. Otherwise,
2171 return the sorted VEC. */
2172
2173 static Lisp_Object
2174 font_sort_entites (vec, prefer, frame, spec, best_only)
2175 Lisp_Object vec, prefer, frame, spec;
2176 int best_only;
2177 {
2178 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2179 int len, i;
2180 struct font_sort_data *data;
2181 unsigned best_score;
2182 Lisp_Object best_entity, driver_type;
2183 int driver_order;
2184 struct frame *f = XFRAME (frame);
2185 struct font_driver_list *list;
2186 USE_SAFE_ALLOCA;
2187
2188 len = ASIZE (vec);
2189 if (len <= 1)
2190 return best_only ? AREF (vec, 0) : vec;
2191
2192 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
2193 prefer_prop[i] = AREF (prefer, i);
2194
2195 if (! NILP (spec))
2196 {
2197 /* A font driver may return a font that has a property value
2198 different from the value specified in SPEC if the driver
2199 thinks they are the same. That happens, for instance, such a
2200 generic family name as "serif" is specified. So, to ignore
2201 such a difference, for all properties specified in SPEC, set
2202 the corresponding properties in PREFER_PROP to nil. */
2203 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
2204 if (! NILP (AREF (spec, i)))
2205 prefer_prop[i] = Qnil;
2206 }
2207
2208 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2209 prefer_prop[FONT_SIZE_INDEX]
2210 = make_number (font_pixel_size (XFRAME (frame), prefer));
2211
2212 /* Scoring and sorting. */
2213 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
2214 best_score = 0xFFFFFFFF;
2215 /* We are sure that the length of VEC > 1. */
2216 driver_type = AREF (AREF (vec, 0), FONT_TYPE_INDEX);
2217 for (driver_order = 0, list = f->font_driver_list; list;
2218 driver_order++, list = list->next)
2219 if (EQ (driver_type, list->driver->type))
2220 break;
2221 best_entity = data[0].entity = AREF (vec, 0);
2222 best_score = data[0].score
2223 = font_score (data[0].entity, prefer_prop) | driver_order;
2224 for (i = 0; i < len; i++)
2225 {
2226 if (!EQ (driver_type, AREF (AREF (vec, i), FONT_TYPE_INDEX)))
2227 for (driver_order = 0, list = f->font_driver_list; list;
2228 driver_order++, list = list->next)
2229 if (EQ (driver_type, list->driver->type))
2230 break;
2231 data[i].entity = AREF (vec, i);
2232 data[i].score = font_score (data[i].entity, prefer_prop) | driver_order;
2233 if (best_only && best_score > data[i].score)
2234 {
2235 best_score = data[i].score;
2236 best_entity = data[i].entity;
2237 if (best_score == 0)
2238 break;
2239 }
2240 }
2241 if (NILP (best_entity))
2242 {
2243 qsort (data, len, sizeof *data, font_compare);
2244 for (i = 0; i < len; i++)
2245 ASET (vec, i, data[i].entity);
2246 }
2247 else
2248 vec = best_entity;
2249 SAFE_FREE ();
2250
2251 font_add_log ("sort-by", prefer, vec);
2252 return vec;
2253 }
2254
2255 \f
2256 /* API of Font Service Layer. */
2257
2258 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2259 sort_shift_bits. Finternal_set_font_selection_order calls this
2260 function with font_sort_order after setting up it. */
2261
2262 void
2263 font_update_sort_order (order)
2264 int *order;
2265 {
2266 int i, shift_bits;
2267
2268 for (i = 0, shift_bits = 23; i < 4; i++, shift_bits -= 7)
2269 {
2270 int xlfd_idx = order[i];
2271
2272 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2273 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2274 else if (xlfd_idx == XLFD_SLANT_INDEX)
2275 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2276 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2277 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2278 else
2279 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2280 }
2281 }
2282
2283
2284 /* Check if ENTITY matches with the font specification SPEC. */
2285
2286 int
2287 font_match_p (spec, entity)
2288 Lisp_Object spec, entity;
2289 {
2290 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2291 Lisp_Object alternate_families = Qnil;
2292 int i;
2293
2294 for (i = FONT_FOUNDRY_INDEX; i <= FONT_SIZE_INDEX; i++)
2295 prefer_prop[i] = AREF (spec, i);
2296 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2297 prefer_prop[FONT_SIZE_INDEX]
2298 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2299 if (! NILP (prefer_prop[FONT_FAMILY_INDEX]))
2300 {
2301 alternate_families
2302 = Fassoc_string (prefer_prop[FONT_FAMILY_INDEX],
2303 Vface_alternative_font_family_alist, Qt);
2304 if (CONSP (alternate_families))
2305 alternate_families = XCDR (alternate_families);
2306 }
2307
2308 return (font_score (entity, prefer_prop) == 0);
2309 }
2310
2311
2312 /* CHeck a lispy font object corresponding to FONT. */
2313
2314 int
2315 font_check_object (font)
2316 struct font *font;
2317 {
2318 Lisp_Object tail, elt;
2319
2320 for (tail = font->props[FONT_OBJLIST_INDEX]; CONSP (tail);
2321 tail = XCDR (tail))
2322 {
2323 elt = XCAR (tail);
2324 if (font == XFONT_OBJECT (elt))
2325 return 1;
2326 }
2327 return 0;
2328 }
2329
2330 \f
2331
2332 /* Font cache
2333
2334 Each font backend has the callback function get_cache, and it
2335 returns a cons cell of which cdr part can be freely used for
2336 caching fonts. The cons cell may be shared by multiple frames
2337 and/or multiple font drivers. So, we arrange the cdr part as this:
2338
2339 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2340
2341 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2342 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2343 cons (FONT-SPEC FONT-ENTITY ...). */
2344
2345 static void font_prepare_cache P_ ((FRAME_PTR, struct font_driver *));
2346 static void font_finish_cache P_ ((FRAME_PTR, struct font_driver *));
2347 static Lisp_Object font_get_cache P_ ((FRAME_PTR, struct font_driver *));
2348 static void font_clear_cache P_ ((FRAME_PTR, Lisp_Object,
2349 struct font_driver *));
2350
2351 static void
2352 font_prepare_cache (f, driver)
2353 FRAME_PTR f;
2354 struct font_driver *driver;
2355 {
2356 Lisp_Object cache, val;
2357
2358 cache = driver->get_cache (f);
2359 val = XCDR (cache);
2360 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2361 val = XCDR (val);
2362 if (NILP (val))
2363 {
2364 val = Fcons (driver->type, Fcons (make_number (1), Qnil));
2365 XSETCDR (cache, Fcons (val, XCDR (cache)));
2366 }
2367 else
2368 {
2369 val = XCDR (XCAR (val));
2370 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2371 }
2372 }
2373
2374
2375 static void
2376 font_finish_cache (f, driver)
2377 FRAME_PTR f;
2378 struct font_driver *driver;
2379 {
2380 Lisp_Object cache, val, tmp;
2381
2382
2383 cache = driver->get_cache (f);
2384 val = XCDR (cache);
2385 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2386 cache = val, val = XCDR (val);
2387 font_assert (! NILP (val));
2388 tmp = XCDR (XCAR (val));
2389 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2390 if (XINT (XCAR (tmp)) == 0)
2391 {
2392 font_clear_cache (f, XCAR (val), driver);
2393 XSETCDR (cache, XCDR (val));
2394 }
2395 }
2396
2397
2398 static Lisp_Object
2399 font_get_cache (f, driver)
2400 FRAME_PTR f;
2401 struct font_driver *driver;
2402 {
2403 Lisp_Object val = driver->get_cache (f);
2404 Lisp_Object type = driver->type;
2405
2406 font_assert (CONSP (val));
2407 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2408 font_assert (CONSP (val));
2409 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2410 val = XCDR (XCAR (val));
2411 return val;
2412 }
2413
2414 static int num_fonts;
2415
2416 static void
2417 font_clear_cache (f, cache, driver)
2418 FRAME_PTR f;
2419 Lisp_Object cache;
2420 struct font_driver *driver;
2421 {
2422 Lisp_Object tail, elt;
2423
2424 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2425 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2426 {
2427 elt = XCAR (tail);
2428 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)) && VECTORP (XCDR (elt)))
2429 {
2430 Lisp_Object vec = XCDR (elt);
2431 int i;
2432
2433 for (i = 0; i < ASIZE (vec); i++)
2434 {
2435 Lisp_Object entity = AREF (vec, i);
2436
2437 if (EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2438 {
2439 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2440
2441 for (; CONSP (objlist); objlist = XCDR (objlist))
2442 {
2443 Lisp_Object val = XCAR (objlist);
2444 struct font *font = XFONT_OBJECT (val);
2445
2446 font_assert (font && driver == font->driver);
2447 driver->close (f, font);
2448 num_fonts--;
2449 }
2450 if (driver->free_entity)
2451 driver->free_entity (entity);
2452 }
2453 }
2454 }
2455 }
2456 XSETCDR (cache, Qnil);
2457 }
2458 \f
2459
2460 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2461
2462 Lisp_Object
2463 font_delete_unmatched (list, spec, size)
2464 Lisp_Object list, spec;
2465 int size;
2466 {
2467 Lisp_Object entity, val;
2468 enum font_property_index prop;
2469
2470 for (val = Qnil; CONSP (list); list = XCDR (list))
2471 {
2472 entity = XCAR (list);
2473 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++)
2474 if (INTEGERP (AREF (spec, prop))
2475 && ((XINT (AREF (spec, prop)) >> 8)
2476 != (XINT (AREF (entity, prop)) >> 8)))
2477 prop = FONT_SPEC_MAX;
2478 if (prop++ <= FONT_SIZE_INDEX
2479 && size
2480 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2481 {
2482 int diff = XINT (AREF (entity, FONT_SIZE_INDEX)) - size;
2483
2484 if (diff != 0
2485 && (diff < 0 ? -diff > FONT_PIXEL_SIZE_QUANTUM
2486 : diff > FONT_PIXEL_SIZE_QUANTUM))
2487 prop = FONT_SPEC_MAX;
2488 }
2489 if (prop < FONT_SPEC_MAX)
2490 val = Fcons (entity, val);
2491 }
2492 return val;
2493 }
2494
2495
2496 /* Return a vector of font-entities matching with SPEC on FRAME. */
2497
2498 Lisp_Object
2499 font_list_entities (frame, spec)
2500 Lisp_Object frame, spec;
2501 {
2502 FRAME_PTR f = XFRAME (frame);
2503 struct font_driver_list *driver_list = f->font_driver_list;
2504 Lisp_Object ftype, val;
2505 Lisp_Object *vec;
2506 int size;
2507 int need_filtering = 0;
2508 int i;
2509
2510 font_assert (FONT_SPEC_P (spec));
2511
2512 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2513 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2514 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2515 size = font_pixel_size (f, spec);
2516 else
2517 size = 0;
2518
2519 ftype = AREF (spec, FONT_TYPE_INDEX);
2520 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2521 ASET (scratch_font_spec, i, AREF (spec, i));
2522 for (i = FONT_WEIGHT_INDEX; i < FONT_EXTRA_INDEX; i++)
2523 {
2524 ASET (scratch_font_spec, i, Qnil);
2525 if (! NILP (AREF (spec, i)))
2526 need_filtering = 1;
2527 if (i == FONT_DPI_INDEX)
2528 /* Skip FONT_SPACING_INDEX */
2529 i++;
2530 }
2531 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX));
2532 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
2533
2534 vec = alloca (sizeof (Lisp_Object) * num_font_drivers);
2535 if (! vec)
2536 return null_vector;
2537
2538 for (i = 0; driver_list; driver_list = driver_list->next)
2539 if (driver_list->on
2540 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2541 {
2542 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2543
2544 ASET (scratch_font_spec, FONT_TYPE_INDEX, driver_list->driver->type);
2545 val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2546 if (CONSP (val))
2547 val = XCDR (val);
2548 else
2549 {
2550 Lisp_Object copy;
2551
2552 val = driver_list->driver->list (frame, scratch_font_spec);
2553 copy = Fcopy_font_spec (scratch_font_spec);
2554 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2555 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2556 }
2557 if (! NILP (val) && need_filtering)
2558 val = font_delete_unmatched (val, spec, size);
2559 if (! NILP (val))
2560 vec[i++] = val;
2561 }
2562
2563 val = (i > 0 ? Fvconcat (i, vec) : null_vector);
2564 font_add_log ("list", spec, val);
2565 return (val);
2566 }
2567
2568
2569 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2570 nil, is an array of face's attributes, which specifies preferred
2571 font-related attributes. */
2572
2573 static Lisp_Object
2574 font_matching_entity (f, attrs, spec)
2575 FRAME_PTR f;
2576 Lisp_Object *attrs, spec;
2577 {
2578 struct font_driver_list *driver_list = f->font_driver_list;
2579 Lisp_Object ftype, size, entity;
2580 Lisp_Object frame;
2581
2582 XSETFRAME (frame, f);
2583 ftype = AREF (spec, FONT_TYPE_INDEX);
2584 size = AREF (spec, FONT_SIZE_INDEX);
2585 if (FLOATP (size))
2586 ASET (spec, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2587 entity = Qnil;
2588 for (; driver_list; driver_list = driver_list->next)
2589 if (driver_list->on
2590 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2591 {
2592 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2593 Lisp_Object copy;
2594
2595 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2596 entity = assoc_no_quit (spec, XCDR (cache));
2597 if (CONSP (entity))
2598 entity = XCDR (entity);
2599 else
2600 {
2601 entity = driver_list->driver->match (frame, spec);
2602 copy = Fcopy_font_spec (spec);
2603 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2604 XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache)));
2605 }
2606 if (! NILP (entity))
2607 break;
2608 }
2609 ASET (spec, FONT_TYPE_INDEX, ftype);
2610 ASET (spec, FONT_SIZE_INDEX, size);
2611 font_add_log ("match", spec, entity);
2612 return entity;
2613 }
2614
2615
2616 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2617 opened font object. */
2618
2619 static Lisp_Object
2620 font_open_entity (f, entity, pixel_size)
2621 FRAME_PTR f;
2622 Lisp_Object entity;
2623 int pixel_size;
2624 {
2625 struct font_driver_list *driver_list;
2626 Lisp_Object objlist, size, val, font_object;
2627 struct font *font;
2628 int min_width;
2629
2630 font_assert (FONT_ENTITY_P (entity));
2631 size = AREF (entity, FONT_SIZE_INDEX);
2632 if (XINT (size) != 0)
2633 pixel_size = XINT (size);
2634
2635 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2636 objlist = XCDR (objlist))
2637 if (XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size)
2638 return XCAR (objlist);
2639
2640 val = AREF (entity, FONT_TYPE_INDEX);
2641 for (driver_list = f->font_driver_list;
2642 driver_list && ! EQ (driver_list->driver->type, val);
2643 driver_list = driver_list->next);
2644 if (! driver_list)
2645 return Qnil;
2646
2647 font_object = driver_list->driver->open (f, entity, pixel_size);
2648 font_add_log ("open", entity, font_object);
2649 if (NILP (font_object))
2650 return Qnil;
2651 ASET (entity, FONT_OBJLIST_INDEX,
2652 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2653 ASET (font_object, FONT_OBJLIST_INDEX, AREF (entity, FONT_OBJLIST_INDEX));
2654 num_fonts++;
2655
2656 font = XFONT_OBJECT (font_object);
2657 min_width = (font->min_width ? font->min_width
2658 : font->average_width ? font->average_width
2659 : font->space_width ? font->space_width
2660 : 1);
2661 #ifdef HAVE_WINDOW_SYSTEM
2662 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
2663 if (FRAME_X_DISPLAY_INFO (f)->n_fonts == 1)
2664 {
2665 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
2666 FRAME_SMALLEST_FONT_HEIGHT (f) = font->height;
2667 fonts_changed_p = 1;
2668 }
2669 else
2670 {
2671 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
2672 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
2673 if (FRAME_SMALLEST_FONT_HEIGHT (f) > font->height)
2674 FRAME_SMALLEST_FONT_HEIGHT (f) = font->height, fonts_changed_p = 1;
2675 }
2676 #endif
2677
2678 return font_object;
2679 }
2680
2681
2682 /* Close FONT_OBJECT that is opened on frame F. */
2683
2684 void
2685 font_close_object (f, font_object)
2686 FRAME_PTR f;
2687 Lisp_Object font_object;
2688 {
2689 struct font *font = XFONT_OBJECT (font_object);
2690 Lisp_Object objlist;
2691 Lisp_Object tail, prev = Qnil;
2692
2693 objlist = AREF (font_object, FONT_OBJLIST_INDEX);
2694 for (prev = Qnil, tail = objlist; CONSP (tail);
2695 prev = tail, tail = XCDR (tail))
2696 if (EQ (font_object, XCAR (tail)))
2697 {
2698 font_add_log ("close", font_object, Qnil);
2699 font->driver->close (f, font);
2700 #ifdef HAVE_WINDOW_SYSTEM
2701 font_assert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
2702 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
2703 #endif
2704 if (NILP (prev))
2705 ASET (font_object, FONT_OBJLIST_INDEX, XCDR (objlist));
2706 else
2707 XSETCDR (prev, XCDR (objlist));
2708 num_fonts--;
2709 return;
2710 }
2711 abort ();
2712 }
2713
2714
2715 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2716 FONT is a font-entity and it must be opened to check. */
2717
2718 int
2719 font_has_char (f, font, c)
2720 FRAME_PTR f;
2721 Lisp_Object font;
2722 int c;
2723 {
2724 struct font *fontp;
2725
2726 if (FONT_ENTITY_P (font))
2727 {
2728 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
2729 struct font_driver_list *driver_list;
2730
2731 for (driver_list = f->font_driver_list;
2732 driver_list && ! EQ (driver_list->driver->type, type);
2733 driver_list = driver_list->next);
2734 if (! driver_list)
2735 return 0;
2736 if (! driver_list->driver->has_char)
2737 return -1;
2738 return driver_list->driver->has_char (font, c);
2739 }
2740
2741 font_assert (FONT_OBJECT_P (font));
2742 fontp = XFONT_OBJECT (font);
2743 if (fontp->driver->has_char)
2744 {
2745 int result = fontp->driver->has_char (font, c);
2746
2747 if (result >= 0)
2748 return result;
2749 }
2750 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
2751 }
2752
2753
2754 /* Return the glyph ID of FONT_OBJECT for character C. */
2755
2756 unsigned
2757 font_encode_char (font_object, c)
2758 Lisp_Object font_object;
2759 int c;
2760 {
2761 struct font *font;
2762
2763 font_assert (FONT_OBJECT_P (font_object));
2764 font = XFONT_OBJECT (font_object);
2765 return font->driver->encode_char (font, c);
2766 }
2767
2768
2769 /* Return the name of FONT_OBJECT. */
2770
2771 Lisp_Object
2772 font_get_name (font_object)
2773 Lisp_Object font_object;
2774 {
2775 font_assert (FONT_OBJECT_P (font_object));
2776 return AREF (font_object, FONT_NAME_INDEX);
2777 }
2778
2779
2780 /* Return the specification of FONT_OBJECT. */
2781
2782 Lisp_Object
2783 font_get_spec (font_object)
2784 Lisp_Object font_object;
2785 {
2786 Lisp_Object spec = font_make_spec ();
2787 int i;
2788
2789 for (i = 0; i < FONT_SIZE_INDEX; i++)
2790 ASET (spec, i, AREF (font_object, i));
2791 ASET (spec, FONT_SIZE_INDEX,
2792 make_number (XFONT_OBJECT (font_object)->pixel_size));
2793 return spec;
2794 }
2795
2796 Lisp_Object
2797 font_spec_from_name (font_name)
2798 Lisp_Object font_name;
2799 {
2800 Lisp_Object args[2];
2801
2802 args[0] = QCname;
2803 args[1] = font_name;
2804 return Ffont_spec (2, args);
2805 }
2806
2807
2808 void
2809 font_clear_prop (attrs, prop)
2810 Lisp_Object *attrs;
2811 enum font_property_index prop;
2812 {
2813 Lisp_Object font = attrs[LFACE_FONT_INDEX];
2814
2815 if (! FONTP (font))
2816 return;
2817 if (NILP (AREF (font, prop))
2818 && prop != FONT_FAMILY_INDEX && prop != FONT_FOUNDRY_INDEX
2819 && prop != FONT_SIZE_INDEX)
2820 return;
2821 font = Fcopy_font_spec (font);
2822 ASET (font, prop, Qnil);
2823 if (prop == FONT_FAMILY_INDEX || prop == FONT_FOUNDRY_INDEX)
2824 {
2825 if (prop == FONT_FAMILY_INDEX)
2826 ASET (font, FONT_FOUNDRY_INDEX, Qnil);
2827 ASET (font, FONT_ADSTYLE_INDEX, Qnil);
2828 ASET (font, FONT_REGISTRY_INDEX, Qnil);
2829 ASET (font, FONT_SIZE_INDEX, Qnil);
2830 ASET (font, FONT_DPI_INDEX, Qnil);
2831 ASET (font, FONT_SPACING_INDEX, Qnil);
2832 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
2833 }
2834 else if (prop == FONT_SIZE_INDEX)
2835 {
2836 ASET (font, FONT_DPI_INDEX, Qnil);
2837 ASET (font, FONT_SPACING_INDEX, Qnil);
2838 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
2839 }
2840 attrs[LFACE_FONT_INDEX] = font;
2841 }
2842
2843 void
2844 font_update_lface (f, attrs)
2845 FRAME_PTR f;
2846 Lisp_Object *attrs;
2847 {
2848 Lisp_Object spec;
2849
2850 spec = attrs[LFACE_FONT_INDEX];
2851 if (! FONT_SPEC_P (spec))
2852 return;
2853
2854 if (! NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
2855 attrs[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX));
2856 if (! NILP (AREF (spec, FONT_FAMILY_INDEX)))
2857 attrs[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FAMILY_INDEX));
2858 if (! NILP (AREF (spec, FONT_WEIGHT_INDEX)))
2859 attrs[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (spec);
2860 if (! NILP (AREF (spec, FONT_SLANT_INDEX)))
2861 attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);;
2862 if (! NILP (AREF (spec, FONT_WIDTH_INDEX)))
2863 attrs[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (spec);
2864 if (! NILP (AREF (spec, FONT_SIZE_INDEX)))
2865 {
2866 int point;
2867
2868 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2869 {
2870 Lisp_Object val;
2871 int dpi = f->resy;
2872
2873 val = Ffont_get (spec, QCdpi);
2874 if (! NILP (val))
2875 dpi = XINT (val);
2876 point = PIXEL_TO_POINT (XINT (AREF (spec, FONT_SIZE_INDEX)) * 10,
2877 dpi);
2878 }
2879 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2880 point = XFLOAT_DATA (AREF (spec, FONT_SIZE_INDEX)) * 10;
2881 attrs[LFACE_HEIGHT_INDEX] = make_number (point);
2882 }
2883 }
2884
2885
2886 /* Return a font-entity satisfying SPEC and best matching with face's
2887 font related attributes in ATTRS. C, if not negative, is a
2888 character that the entity must support. */
2889
2890 Lisp_Object
2891 font_find_for_lface (f, attrs, spec, c)
2892 FRAME_PTR f;
2893 Lisp_Object *attrs;
2894 Lisp_Object spec;
2895 int c;
2896 {
2897 Lisp_Object work;
2898 Lisp_Object frame, entities, val, props[FONT_REGISTRY_INDEX + 1] ;
2899 Lisp_Object size, foundry[3], *family;
2900 int pixel_size;
2901 int i, j, result;
2902
2903 if (c >= 0 && ! NILP (AREF (spec, FONT_REGISTRY_INDEX)))
2904 {
2905 struct charset *encoding, *repertory;
2906
2907 if (font_registry_charsets (AREF (spec, FONT_REGISTRY_INDEX),
2908 &encoding, &repertory) < 0)
2909 return Qnil;
2910 if (repertory)
2911 {
2912 if (ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
2913 return Qnil;
2914 /* Any font of this registry support C. So, let's
2915 suppress the further checking. */
2916 c = -1;
2917 }
2918 else if (c > encoding->max_char)
2919 return Qnil;
2920 }
2921
2922 work = Fcopy_font_spec (spec);
2923 XSETFRAME (frame, f);
2924 size = AREF (spec, FONT_SIZE_INDEX);
2925 pixel_size = font_pixel_size (f, spec);
2926 if (pixel_size == 0)
2927 {
2928 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
2929
2930 pixel_size = POINT_TO_PIXEL (pt / 10, f->resy);
2931 }
2932 ASET (work, FONT_SIZE_INDEX, Qnil);
2933 foundry[0] = AREF (work, FONT_FOUNDRY_INDEX);
2934 if (! NILP (foundry[0]))
2935 foundry[1] = null_vector;
2936 else if (STRINGP (attrs[LFACE_FOUNDRY_INDEX]))
2937 {
2938 foundry[0] = font_intern_prop (SDATA (attrs[LFACE_FOUNDRY_INDEX]),
2939 SBYTES (attrs[LFACE_FOUNDRY_INDEX]), 1);
2940 foundry[1] = Qnil;
2941 foundry[2] = null_vector;
2942 }
2943 else
2944 foundry[0] = Qnil, foundry[1] = null_vector;
2945
2946 val = AREF (work, FONT_FAMILY_INDEX);
2947 if (NILP (val) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
2948 val = font_intern_prop (SDATA (attrs[LFACE_FAMILY_INDEX]),
2949 SBYTES (attrs[LFACE_FAMILY_INDEX]), 1);
2950 if (NILP (val))
2951 {
2952 family = alloca ((sizeof family[0]) * 2);
2953 family[0] = Qnil;
2954 family[1] = null_vector; /* terminator. */
2955 }
2956 else
2957 {
2958 Lisp_Object alters
2959 = Fassoc_string (val, Vface_alternative_font_family_alist, Qt);
2960
2961 if (! NILP (alters))
2962 {
2963 family = alloca ((sizeof family[0]) * (XINT (Flength (alters)) + 2));
2964 for (i = 0; CONSP (alters); i++, alters = XCDR (alters))
2965 family[i] = XCAR (alters);
2966 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
2967 family[i++] = Qnil;
2968 family[i] = null_vector;
2969 }
2970 else
2971 {
2972 family = alloca ((sizeof family[0]) * 3);
2973 i = 0;
2974 family[i++] = val;
2975 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
2976 family[i++] = Qnil;
2977 family[i] = null_vector;
2978 }
2979 }
2980
2981 for (j = 0; SYMBOLP (family[j]); j++)
2982 {
2983 ASET (work, FONT_FAMILY_INDEX, family[j]);
2984 for (i = 0; SYMBOLP (foundry[i]); i++)
2985 {
2986 ASET (work, FONT_FOUNDRY_INDEX, foundry[i]);
2987 entities = font_list_entities (frame, work);
2988 if (ASIZE (entities) > 0)
2989 break;
2990 }
2991 if (ASIZE (entities) > 0)
2992 break;
2993 }
2994 if (ASIZE (entities) == 0)
2995 return Qnil;
2996 if (ASIZE (entities) == 1)
2997 {
2998 if (c < 0)
2999 return AREF (entities, 0);
3000 }
3001 else
3002 {
3003 /* Sort fonts by properties specified in LFACE. */
3004 Lisp_Object prefer = scratch_font_prefer;
3005
3006 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3007 ASET (prefer, i, AREF (work, i));
3008 if (FONTP (attrs[LFACE_FONT_INDEX]))
3009 {
3010 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
3011
3012 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3013 if (NILP (AREF (prefer, i)))
3014 ASET (prefer, i, AREF (face_font, i));
3015 }
3016 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
3017 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
3018 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
3019 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
3020 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
3021 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
3022 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
3023 entities = font_sort_entites (entities, prefer, frame, work, c < 0);
3024 }
3025 if (c < 0)
3026 return entities;
3027
3028 for (i = 0; i < ASIZE (entities); i++)
3029 {
3030 int j;
3031
3032 val = AREF (entities, i);
3033 if (i > 0)
3034 {
3035 for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
3036 if (! EQ (AREF (val, j), props[j]))
3037 break;
3038 if (j > FONT_REGISTRY_INDEX)
3039 continue;
3040 }
3041 for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
3042 props[j] = AREF (val, j);
3043 result = font_has_char (f, val, c);
3044 if (result > 0)
3045 return val;
3046 if (result == 0)
3047 return Qnil;
3048 val = font_open_for_lface (f, val, attrs, spec);
3049 if (NILP (val))
3050 continue;
3051 result = font_has_char (f, val, c);
3052 font_close_object (f, val);
3053 if (result > 0)
3054 return AREF (entities, i);
3055 }
3056 return Qnil;
3057 }
3058
3059
3060 Lisp_Object
3061 font_open_for_lface (f, entity, attrs, spec)
3062 FRAME_PTR f;
3063 Lisp_Object entity;
3064 Lisp_Object *attrs;
3065 Lisp_Object spec;
3066 {
3067 int size;
3068
3069 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX))
3070 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
3071 size = XINT (AREF (entity, FONT_SIZE_INDEX));
3072 else if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
3073 size = font_pixel_size (f, spec);
3074 else
3075 {
3076 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
3077
3078 pt /= 10;
3079 size = POINT_TO_PIXEL (pt, f->resy);
3080 }
3081 return font_open_entity (f, entity, size);
3082 }
3083
3084
3085 /* Find a font satisfying SPEC and best matching with face's
3086 attributes in ATTRS on FRAME, and return the opened
3087 font-object. */
3088
3089 Lisp_Object
3090 font_load_for_lface (f, attrs, spec)
3091 FRAME_PTR f;
3092 Lisp_Object *attrs, spec;
3093 {
3094 Lisp_Object entity;
3095
3096 entity = font_find_for_lface (f, attrs, spec, -1);
3097 if (NILP (entity))
3098 {
3099 /* No font is listed for SPEC, but each font-backend may have
3100 the different criteria about "font matching". So, try
3101 it. */
3102 entity = font_matching_entity (f, attrs, spec);
3103 if (NILP (entity))
3104 return Qnil;
3105 }
3106 return font_open_for_lface (f, entity, attrs, spec);
3107 }
3108
3109
3110 /* Make FACE on frame F ready to use the font opened for FACE. */
3111
3112 void
3113 font_prepare_for_face (f, face)
3114 FRAME_PTR f;
3115 struct face *face;
3116 {
3117 if (face->font->driver->prepare_face)
3118 face->font->driver->prepare_face (f, face);
3119 }
3120
3121
3122 /* Make FACE on frame F stop using the font opened for FACE. */
3123
3124 void
3125 font_done_for_face (f, face)
3126 FRAME_PTR f;
3127 struct face *face;
3128 {
3129 if (face->font->driver->done_face)
3130 face->font->driver->done_face (f, face);
3131 face->extra = NULL;
3132 }
3133
3134
3135 /* Open a font best matching with NAME on frame F. If no proper font
3136 is found, return Qnil. */
3137
3138 Lisp_Object
3139 font_open_by_name (f, name)
3140 FRAME_PTR f;
3141 char *name;
3142 {
3143 Lisp_Object args[2];
3144 Lisp_Object spec, attrs[LFACE_VECTOR_SIZE];
3145
3146 args[0] = QCname;
3147 args[1] = make_unibyte_string (name, strlen (name));
3148 spec = Ffont_spec (2, args);
3149 /* We set up the default font-related attributes of a face to prefer
3150 a moderate font. */
3151 attrs[LFACE_FAMILY_INDEX] = attrs[LFACE_FOUNDRY_INDEX] = Qnil;
3152 attrs[LFACE_SWIDTH_INDEX] = attrs[LFACE_WEIGHT_INDEX]
3153 = attrs[LFACE_SLANT_INDEX] = Qnormal;
3154 attrs[LFACE_HEIGHT_INDEX] = make_number (120);
3155 attrs[LFACE_FONT_INDEX] = Qnil;
3156
3157 return font_load_for_lface (f, attrs, spec);
3158 }
3159
3160
3161 /* Register font-driver DRIVER. This function is used in two ways.
3162
3163 The first is with frame F non-NULL. In this case, make DRIVER
3164 available (but not yet activated) on F. All frame creaters
3165 (e.g. Fx_create_frame) must call this function at least once with
3166 an available font-driver.
3167
3168 The second is with frame F NULL. In this case, DRIVER is globally
3169 registered in the variable `font_driver_list'. All font-driver
3170 implementations must call this function in its syms_of_XXXX
3171 (e.g. syms_of_xfont). */
3172
3173 void
3174 register_font_driver (driver, f)
3175 struct font_driver *driver;
3176 FRAME_PTR f;
3177 {
3178 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
3179 struct font_driver_list *prev, *list;
3180
3181 if (f && ! driver->draw)
3182 error ("Unusable font driver for a frame: %s",
3183 SDATA (SYMBOL_NAME (driver->type)));
3184
3185 for (prev = NULL, list = root; list; prev = list, list = list->next)
3186 if (EQ (list->driver->type, driver->type))
3187 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3188
3189 list = malloc (sizeof (struct font_driver_list));
3190 list->on = 0;
3191 list->driver = driver;
3192 list->next = NULL;
3193 if (prev)
3194 prev->next = list;
3195 else if (f)
3196 f->font_driver_list = list;
3197 else
3198 font_driver_list = list;
3199 if (! f)
3200 num_font_drivers++;
3201 }
3202
3203
3204 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3205 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3206 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3207
3208 A caller must free all realized faces if any in advance. The
3209 return value is a list of font backends actually made used on
3210 F. */
3211
3212 Lisp_Object
3213 font_update_drivers (f, new_drivers)
3214 FRAME_PTR f;
3215 Lisp_Object new_drivers;
3216 {
3217 Lisp_Object active_drivers = Qnil;
3218 struct font_driver *driver;
3219 struct font_driver_list *list;
3220
3221 /* At first, turn off non-requested drivers, and turn on requested
3222 drivers. */
3223 for (list = f->font_driver_list; list; list = list->next)
3224 {
3225 driver = list->driver;
3226 if ((EQ (new_drivers, Qt) || ! NILP (Fmemq (driver->type, new_drivers)))
3227 != list->on)
3228 {
3229 if (list->on)
3230 {
3231 if (driver->end_for_frame)
3232 driver->end_for_frame (f);
3233 font_finish_cache (f, driver);
3234 list->on = 0;
3235 }
3236 else
3237 {
3238 if (! driver->start_for_frame
3239 || driver->start_for_frame (f) == 0)
3240 {
3241 font_prepare_cache (f, driver);
3242 list->on = 1;
3243 }
3244 }
3245 }
3246 }
3247
3248 if (NILP (new_drivers))
3249 return Qnil;
3250
3251 if (! EQ (new_drivers, Qt))
3252 {
3253 /* Re-order the driver list according to new_drivers. */
3254 struct font_driver_list **list_table, *list;
3255 Lisp_Object tail;
3256 int i;
3257
3258 list_table = alloca (sizeof list_table[0] * (num_font_drivers + 1));
3259 for (i = 0, tail = new_drivers; ! NILP (tail); tail = XCDR (tail))
3260 {
3261 for (list = f->font_driver_list; list; list = list->next)
3262 if (list->on && EQ (list->driver->type, XCAR (tail)))
3263 break;
3264 if (list)
3265 list_table[i++] = list;
3266 }
3267 for (list = f->font_driver_list; list; list = list->next)
3268 if (! list->on)
3269 list_table[i] = list;
3270 list_table[i] = NULL;
3271
3272 f->font_driver_list = list = NULL;
3273 for (i = 0; list_table[i]; i++)
3274 {
3275 if (list)
3276 list->next = list_table[i], list = list->next;
3277 else
3278 f->font_driver_list = list = list_table[i];
3279 }
3280 list->next = NULL;
3281 }
3282
3283 for (list = f->font_driver_list; list; list = list->next)
3284 if (list->on)
3285 active_drivers = nconc2 (active_drivers,
3286 Fcons (list->driver->type, Qnil));
3287 return active_drivers;
3288 }
3289
3290 int
3291 font_put_frame_data (f, driver, data)
3292 FRAME_PTR f;
3293 struct font_driver *driver;
3294 void *data;
3295 {
3296 struct font_data_list *list, *prev;
3297
3298 for (prev = NULL, list = f->font_data_list; list;
3299 prev = list, list = list->next)
3300 if (list->driver == driver)
3301 break;
3302 if (! data)
3303 {
3304 if (list)
3305 {
3306 if (prev)
3307 prev->next = list->next;
3308 else
3309 f->font_data_list = list->next;
3310 free (list);
3311 }
3312 return 0;
3313 }
3314
3315 if (! list)
3316 {
3317 list = malloc (sizeof (struct font_data_list));
3318 if (! list)
3319 return -1;
3320 list->driver = driver;
3321 list->next = f->font_data_list;
3322 f->font_data_list = list;
3323 }
3324 list->data = data;
3325 return 0;
3326 }
3327
3328
3329 void *
3330 font_get_frame_data (f, driver)
3331 FRAME_PTR f;
3332 struct font_driver *driver;
3333 {
3334 struct font_data_list *list;
3335
3336 for (list = f->font_data_list; list; list = list->next)
3337 if (list->driver == driver)
3338 break;
3339 if (! list)
3340 return NULL;
3341 return list->data;
3342 }
3343
3344
3345 /* Return the font used to draw character C by FACE at buffer position
3346 POS in window W. If STRING is non-nil, it is a string containing C
3347 at index POS. If C is negative, get C from the current buffer or
3348 STRING. */
3349
3350 Lisp_Object
3351 font_at (c, pos, face, w, string)
3352 int c;
3353 EMACS_INT pos;
3354 struct face *face;
3355 struct window *w;
3356 Lisp_Object string;
3357 {
3358 FRAME_PTR f;
3359 int multibyte;
3360 Lisp_Object font_object;
3361
3362 if (c < 0)
3363 {
3364 if (NILP (string))
3365 {
3366 multibyte = ! NILP (current_buffer->enable_multibyte_characters);
3367 if (multibyte)
3368 {
3369 EMACS_INT pos_byte = CHAR_TO_BYTE (pos);
3370
3371 c = FETCH_CHAR (pos_byte);
3372 }
3373 else
3374 c = FETCH_BYTE (pos);
3375 }
3376 else
3377 {
3378 unsigned char *str;
3379
3380 multibyte = STRING_MULTIBYTE (string);
3381 if (multibyte)
3382 {
3383 EMACS_INT pos_byte = string_char_to_byte (string, pos);
3384
3385 str = SDATA (string) + pos_byte;
3386 c = STRING_CHAR (str, 0);
3387 }
3388 else
3389 c = SDATA (string)[pos];
3390 }
3391 }
3392
3393 f = XFRAME (w->frame);
3394 if (! FRAME_WINDOW_P (f))
3395 return Qnil;
3396 if (! face)
3397 {
3398 int face_id;
3399 EMACS_INT endptr;
3400
3401 if (STRINGP (string))
3402 face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
3403 DEFAULT_FACE_ID, 0);
3404 else
3405 face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
3406 pos + 100, 0);
3407 face = FACE_FROM_ID (f, face_id);
3408 }
3409 if (multibyte)
3410 {
3411 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3412 face = FACE_FROM_ID (f, face_id);
3413 }
3414 if (! face->font)
3415 return Qnil;
3416
3417 font_assert (font_check_object ((struct font *) face->font));
3418 XSETFONT (font_object, face->font);
3419 return font_object;
3420 }
3421
3422
3423 /* Check how many characters after POS (at most to LIMIT) can be
3424 displayed by the same font. FACE is the face selected for the
3425 character as POS on frame F. STRING, if not nil, is the string to
3426 check instead of the current buffer.
3427
3428 The return value is the position of the character that is displayed
3429 by the differnt font than that of the character as POS. */
3430
3431 EMACS_INT
3432 font_range (pos, limit, face, f, string)
3433 EMACS_INT pos, limit;
3434 struct face *face;
3435 FRAME_PTR f;
3436 Lisp_Object string;
3437 {
3438 int multibyte;
3439 EMACS_INT pos_byte;
3440 int c;
3441 struct font *font;
3442 int first = 1;
3443
3444 if (NILP (string))
3445 {
3446 multibyte = ! NILP (current_buffer->enable_multibyte_characters);
3447 pos_byte = CHAR_TO_BYTE (pos);
3448 }
3449 else
3450 {
3451 multibyte = STRING_MULTIBYTE (string);
3452 pos_byte = string_char_to_byte (string, pos);
3453 }
3454
3455 if (! multibyte)
3456 /* All unibyte character are displayed by the same font. */
3457 return limit;
3458
3459 while (pos < limit)
3460 {
3461 int face_id;
3462
3463 if (NILP (string))
3464 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3465 else
3466 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3467 face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3468 face = FACE_FROM_ID (f, face_id);
3469 if (first)
3470 {
3471 font = face->font;
3472 first = 0;
3473 continue;
3474 }
3475 else if (font != face->font)
3476 {
3477 pos--;
3478 break;
3479 }
3480 }
3481 return pos;
3482 }
3483
3484 \f
3485 /* Lisp API */
3486
3487 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3488 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3489 Return nil otherwise.
3490 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3491 which kind of font it is. It must be one of `font-spec', `font-entity',
3492 `font-object'. */)
3493 (object, extra_type)
3494 Lisp_Object object, extra_type;
3495 {
3496 if (NILP (extra_type))
3497 return (FONTP (object) ? Qt : Qnil);
3498 if (EQ (extra_type, Qfont_spec))
3499 return (FONT_SPEC_P (object) ? Qt : Qnil);
3500 if (EQ (extra_type, Qfont_entity))
3501 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3502 if (EQ (extra_type, Qfont_object))
3503 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3504 wrong_type_argument (intern ("font-extra-type"), extra_type);
3505 }
3506
3507 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3508 doc: /* Return a newly created font-spec with arguments as properties.
3509
3510 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3511 valid font property name listed below:
3512
3513 `:family', `:weight', `:slant', `:width'
3514
3515 They are the same as face attributes of the same name. See
3516 `set-face-attribute'.
3517
3518 `:foundry'
3519
3520 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3521
3522 `:adstyle'
3523
3524 VALUE must be a string or a symbol specifying the additional
3525 typographic style information of a font, e.g. ``sans''.
3526
3527 `:registry'
3528
3529 VALUE must be a string or a symbol specifying the charset registry and
3530 encoding of a font, e.g. ``iso8859-1''.
3531
3532 `:size'
3533
3534 VALUE must be a non-negative integer or a floating point number
3535 specifying the font size. It specifies the font size in pixels
3536 (if VALUE is an integer), or in points (if VALUE is a float).
3537 usage: (font-spec ARGS ...) */)
3538 (nargs, args)
3539 int nargs;
3540 Lisp_Object *args;
3541 {
3542 Lisp_Object spec = font_make_spec ();
3543 int i;
3544
3545 for (i = 0; i < nargs; i += 2)
3546 {
3547 Lisp_Object key = args[i], val = args[i + 1];
3548
3549 if (EQ (key, QCname))
3550 {
3551 CHECK_STRING (val);
3552 font_parse_name ((char *) SDATA (val), spec);
3553 font_put_extra (spec, key, val);
3554 }
3555 else
3556 {
3557 int idx = get_font_prop_index (key);
3558
3559 if (idx >= 0)
3560 {
3561 val = font_prop_validate (idx, Qnil, val);
3562 if (idx < FONT_EXTRA_INDEX)
3563 ASET (spec, idx, val);
3564 else
3565 font_put_extra (spec, key, val);
3566 }
3567 else
3568 font_put_extra (spec, key, font_prop_validate (0, key, val));
3569 }
3570 }
3571 return spec;
3572 }
3573
3574 DEFUN ("copy-font-spec", Fcopy_font_spec, Scopy_font_spec, 1, 1, 0,
3575 doc: /* Return a copy of FONT as a font-spec. */)
3576 (font)
3577 Lisp_Object font;
3578 {
3579 Lisp_Object new_spec, tail, extra;
3580 int i;
3581
3582 CHECK_FONT (font);
3583 new_spec = font_make_spec ();
3584 for (i = 1; i < FONT_EXTRA_INDEX; i++)
3585 ASET (new_spec, i, AREF (font, i));
3586 extra = Qnil;
3587 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3588 {
3589 if (! EQ (XCAR (XCAR (tail)), QCfont_entity))
3590 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
3591 }
3592 ASET (new_spec, FONT_EXTRA_INDEX, extra);
3593 return new_spec;
3594 }
3595
3596 DEFUN ("merge-font-spec", Fmerge_font_spec, Smerge_font_spec, 2, 2, 0,
3597 doc: /* Merge font-specs FROM and TO, and return a new font-spec.
3598 Every specified properties in FROM override the corresponding
3599 properties in TO. */)
3600 (from, to)
3601 Lisp_Object from, to;
3602 {
3603 Lisp_Object extra, tail;
3604 int i;
3605
3606 CHECK_FONT (from);
3607 CHECK_FONT (to);
3608 to = Fcopy_font_spec (to);
3609 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3610 ASET (to, i, AREF (from, i));
3611 extra = AREF (to, FONT_EXTRA_INDEX);
3612 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3613 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
3614 {
3615 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
3616
3617 if (! NILP (slot))
3618 XSETCDR (slot, XCDR (XCAR (tail)));
3619 else
3620 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
3621 }
3622 ASET (to, FONT_EXTRA_INDEX, extra);
3623 return to;
3624 }
3625
3626 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
3627 doc: /* Return the value of FONT's property KEY.
3628 FONT is a font-spec, a font-entity, or a font-object. */)
3629 (font, key)
3630 Lisp_Object font, key;
3631 {
3632 int idx;
3633
3634 CHECK_FONT (font);
3635 CHECK_SYMBOL (key);
3636
3637 idx = get_font_prop_index (key);
3638 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3639 return AREF (font, idx);
3640 return Fcdr (Fassq (key, AREF (font, FONT_EXTRA_INDEX)));
3641 }
3642
3643
3644 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
3645 doc: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
3646 (font_spec, prop, val)
3647 Lisp_Object font_spec, prop, val;
3648 {
3649 int idx;
3650
3651 CHECK_FONT_SPEC (font_spec);
3652 idx = get_font_prop_index (prop);
3653 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3654 ASET (font_spec, idx, font_prop_validate (idx, Qnil, val));
3655 else
3656 font_put_extra (font_spec, prop, font_prop_validate (0, prop, val));
3657 return val;
3658 }
3659
3660 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
3661 doc: /* List available fonts matching FONT-SPEC on the current frame.
3662 Optional 2nd argument FRAME specifies the target frame.
3663 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
3664 Optional 4th argument PREFER, if non-nil, is a font-spec to
3665 control the order of the returned list. Fonts are sorted by
3666 how close they are to PREFER. */)
3667 (font_spec, frame, num, prefer)
3668 Lisp_Object font_spec, frame, num, prefer;
3669 {
3670 Lisp_Object vec, list, tail;
3671 int n = 0, i, len;
3672
3673 if (NILP (frame))
3674 frame = selected_frame;
3675 CHECK_LIVE_FRAME (frame);
3676 CHECK_FONT_SPEC (font_spec);
3677 if (! NILP (num))
3678 {
3679 CHECK_NUMBER (num);
3680 n = XINT (num);
3681 if (n <= 0)
3682 return Qnil;
3683 }
3684 if (! NILP (prefer))
3685 CHECK_FONT_SPEC (prefer);
3686
3687 vec = font_list_entities (frame, font_spec);
3688 len = ASIZE (vec);
3689 if (len == 0)
3690 return Qnil;
3691 if (len == 1)
3692 return Fcons (AREF (vec, 0), Qnil);
3693
3694 if (! NILP (prefer))
3695 vec = font_sort_entites (vec, prefer, frame, font_spec, 0);
3696
3697 list = tail = Fcons (AREF (vec, 0), Qnil);
3698 if (n == 0 || n > len)
3699 n = len;
3700 for (i = 1; i < n; i++)
3701 {
3702 Lisp_Object val = Fcons (AREF (vec, i), Qnil);
3703
3704 XSETCDR (tail, val);
3705 tail = val;
3706 }
3707 return list;
3708 }
3709
3710 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
3711 doc: /* List available font families on the current frame.
3712 Optional argument FRAME, if non-nil, specifies the target frame. */)
3713 (frame)
3714 Lisp_Object frame;
3715 {
3716 FRAME_PTR f;
3717 struct font_driver_list *driver_list;
3718 Lisp_Object list;
3719
3720 if (NILP (frame))
3721 frame = selected_frame;
3722 CHECK_LIVE_FRAME (frame);
3723 f = XFRAME (frame);
3724 list = Qnil;
3725 for (driver_list = f->font_driver_list; driver_list;
3726 driver_list = driver_list->next)
3727 if (driver_list->driver->list_family)
3728 {
3729 Lisp_Object val = driver_list->driver->list_family (frame);
3730
3731 if (NILP (list))
3732 list = val;
3733 else
3734 {
3735 Lisp_Object tail = list;
3736
3737 for (; CONSP (val); val = XCDR (val))
3738 if (NILP (Fmemq (XCAR (val), tail)))
3739 list = Fcons (XCAR (val), list);
3740 }
3741 }
3742 return list;
3743 }
3744
3745 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
3746 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
3747 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
3748 (font_spec, frame)
3749 Lisp_Object font_spec, frame;
3750 {
3751 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
3752
3753 if (CONSP (val))
3754 val = XCAR (val);
3755 return val;
3756 }
3757
3758 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
3759 doc: /* Return XLFD name of FONT.
3760 FONT is a font-spec, font-entity, or font-object.
3761 If the name is too long for XLFD (maximum 255 chars), return nil.
3762 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
3763 the consecutive wildcards are folded to one. */)
3764 (font, fold_wildcards)
3765 Lisp_Object font, fold_wildcards;
3766 {
3767 char name[256];
3768 int pixel_size = 0;
3769
3770 CHECK_FONT (font);
3771
3772 if (FONT_OBJECT_P (font))
3773 {
3774 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
3775
3776 if (STRINGP (font_name)
3777 && SDATA (font_name)[0] == '-')
3778 {
3779 if (NILP (fold_wildcards))
3780 return font_name;
3781 strcpy (name, (char *) SDATA (font_name));
3782 goto done;
3783 }
3784 pixel_size = XFONT_OBJECT (font)->pixel_size;
3785 }
3786 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
3787 return Qnil;
3788 done:
3789 if (! NILP (fold_wildcards))
3790 {
3791 char *p0 = name, *p1;
3792
3793 while ((p1 = strstr (p0, "-*-*")))
3794 {
3795 strcpy (p1, p1 + 2);
3796 p0 = p1;
3797 }
3798 }
3799
3800 return build_string (name);
3801 }
3802
3803 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
3804 doc: /* Clear font cache. */)
3805 ()
3806 {
3807 Lisp_Object list, frame;
3808
3809 FOR_EACH_FRAME (list, frame)
3810 {
3811 FRAME_PTR f = XFRAME (frame);
3812 struct font_driver_list *driver_list = f->font_driver_list;
3813
3814 for (; driver_list; driver_list = driver_list->next)
3815 if (driver_list->on)
3816 {
3817 Lisp_Object cache = driver_list->driver->get_cache (f);
3818 Lisp_Object val;
3819
3820 val = XCDR (cache);
3821 while (! NILP (val)
3822 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
3823 val = XCDR (val);
3824 font_assert (! NILP (val));
3825 val = XCDR (XCAR (val));
3826 if (XINT (XCAR (val)) == 0)
3827 {
3828 font_clear_cache (f, XCAR (val), driver_list->driver);
3829 XSETCDR (cache, XCDR (val));
3830 }
3831 }
3832 }
3833
3834 return Qnil;
3835 }
3836
3837 /* The following three functions are still experimental. */
3838
3839 DEFUN ("font-make-gstring", Ffont_make_gstring, Sfont_make_gstring, 2, 2, 0,
3840 doc: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
3841 FONT-OBJECT may be nil if it is not yet known.
3842
3843 G-string is sequence of glyphs of a specific font,
3844 and is a vector of this form:
3845 [ HEADER GLYPH ... ]
3846 HEADER is a vector of this form:
3847 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
3848 where
3849 FONT-OBJECT is a font-object for all glyphs in the g-string,
3850 WIDTH thru DESCENT are the metrics (in pixels) of the whole G-string.
3851 GLYPH is a vector of this form:
3852 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
3853 [ [X-OFF Y-OFF WADJUST] | nil] ]
3854 where
3855 FROM-IDX and TO-IDX are used internally and should not be touched.
3856 C is the character of the glyph.
3857 CODE is the glyph-code of C in FONT-OBJECT.
3858 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
3859 X-OFF and Y-OFF are offests to the base position for the glyph.
3860 WADJUST is the adjustment to the normal width of the glyph. */)
3861 (font_object, num)
3862 Lisp_Object font_object, num;
3863 {
3864 Lisp_Object gstring, g;
3865 int len;
3866 int i;
3867
3868 if (! NILP (font_object))
3869 CHECK_FONT_OBJECT (font_object);
3870 CHECK_NATNUM (num);
3871
3872 len = XINT (num) + 1;
3873 gstring = Fmake_vector (make_number (len), Qnil);
3874 g = Fmake_vector (make_number (6), Qnil);
3875 ASET (g, 0, font_object);
3876 ASET (gstring, 0, g);
3877 for (i = 1; i < len; i++)
3878 ASET (gstring, i, Fmake_vector (make_number (10), Qnil));
3879 return gstring;
3880 }
3881
3882 DEFUN ("font-fill-gstring", Ffont_fill_gstring, Sfont_fill_gstring, 4, 5, 0,
3883 doc: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
3884 START and END specify the region to extract characters.
3885 If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
3886 where to extract characters.
3887 FONT-OBJECT may be nil if GSTRING already contains one. */)
3888 (gstring, font_object, start, end, object)
3889 Lisp_Object gstring, font_object, start, end, object;
3890 {
3891 int len, i, c;
3892 unsigned code;
3893 struct font *font;
3894
3895 CHECK_VECTOR (gstring);
3896 if (NILP (font_object))
3897 font_object = LGSTRING_FONT (gstring);
3898 font = XFONT_OBJECT (font_object);
3899
3900 if (STRINGP (object))
3901 {
3902 const unsigned char *p;
3903
3904 CHECK_NATNUM (start);
3905 CHECK_NATNUM (end);
3906 if (XINT (start) > XINT (end)
3907 || XINT (end) > ASIZE (object)
3908 || XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3909 args_out_of_range_3 (object, start, end);
3910
3911 len = XINT (end) - XINT (start);
3912 p = SDATA (object) + string_char_to_byte (object, XINT (start));
3913 for (i = 0; i < len; i++)
3914 {
3915 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3916 /* Shut up GCC warning in comparison with
3917 MOST_POSITIVE_FIXNUM below. */
3918 EMACS_INT cod;
3919
3920 c = STRING_CHAR_ADVANCE (p);
3921 cod = code = font->driver->encode_char (font, c);
3922 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3923 break;
3924 LGLYPH_SET_FROM (g, i);
3925 LGLYPH_SET_TO (g, i);
3926 LGLYPH_SET_CHAR (g, c);
3927 LGLYPH_SET_CODE (g, code);
3928 }
3929 }
3930 else
3931 {
3932 int pos, pos_byte;
3933
3934 if (! NILP (object))
3935 Fset_buffer (object);
3936 validate_region (&start, &end);
3937 if (XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3938 args_out_of_range (start, end);
3939 len = XINT (end) - XINT (start);
3940 pos = XINT (start);
3941 pos_byte = CHAR_TO_BYTE (pos);
3942 for (i = 0; i < len; i++)
3943 {
3944 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3945 /* Shut up GCC warning in comparison with
3946 MOST_POSITIVE_FIXNUM below. */
3947 EMACS_INT cod;
3948
3949 FETCH_CHAR_ADVANCE (c, pos, pos_byte);
3950 cod = code = font->driver->encode_char (font, c);
3951 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3952 break;
3953 LGLYPH_SET_FROM (g, i);
3954 LGLYPH_SET_TO (g, i);
3955 LGLYPH_SET_CHAR (g, c);
3956 LGLYPH_SET_CODE (g, code);
3957 }
3958 }
3959 for (; i < LGSTRING_LENGTH (gstring); i++)
3960 LGSTRING_SET_GLYPH (gstring, i, Qnil);
3961 return Qnil;
3962 }
3963
3964 DEFUN ("font-shape-text", Ffont_shape_text, Sfont_shape_text, 3, 4, 0,
3965 doc: /* Shape text between FROM and TO by FONT-OBJECT.
3966 If optional 4th argument STRING is non-nil, it is a string to shape,
3967 and FROM and TO are indices to the string.
3968 The value is the end position of the text that can be shaped by
3969 FONT-OBJECT. */)
3970 (from, to, font_object, string)
3971 Lisp_Object from, to, font_object, string;
3972 {
3973 struct font *font;
3974 struct font_metrics metrics;
3975 EMACS_INT start, end;
3976 Lisp_Object gstring, n;
3977 int len, i;
3978
3979 if (! FONT_OBJECT_P (font_object))
3980 return Qnil;
3981 font = XFONT_OBJECT (font_object);
3982 if (! font->driver->shape)
3983 return Qnil;
3984
3985 if (NILP (string))
3986 {
3987 validate_region (&from, &to);
3988 start = XFASTINT (from);
3989 end = XFASTINT (to);
3990 modify_region (current_buffer, start, end, 0);
3991 }
3992 else
3993 {
3994 CHECK_STRING (string);
3995 start = XINT (from);
3996 end = XINT (to);
3997 if (start < 0 || start > end || end > SCHARS (string))
3998 args_out_of_range_3 (string, from, to);
3999 }
4000
4001 len = end - start;
4002 gstring = Ffont_make_gstring (font_object, make_number (len));
4003 Ffont_fill_gstring (gstring, font_object, from, to, string);
4004
4005 /* Try at most three times with larger gstring each time. */
4006 for (i = 0; i < 3; i++)
4007 {
4008 Lisp_Object args[2];
4009
4010 n = font->driver->shape (gstring);
4011 if (INTEGERP (n))
4012 break;
4013 args[0] = gstring;
4014 args[1] = Fmake_vector (make_number (len), Qnil);
4015 gstring = Fvconcat (2, args);
4016 }
4017 if (! INTEGERP (n) || XINT (n) == 0)
4018 return Qnil;
4019 len = XINT (n);
4020
4021 for (i = 0; i < len;)
4022 {
4023 Lisp_Object gstr;
4024 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
4025 EMACS_INT this_from = LGLYPH_FROM (g);
4026 EMACS_INT this_to = LGLYPH_TO (g) + 1;
4027 int j, k;
4028 int need_composition = 0;
4029
4030 metrics.lbearing = LGLYPH_LBEARING (g);
4031 metrics.rbearing = LGLYPH_RBEARING (g);
4032 metrics.ascent = LGLYPH_ASCENT (g);
4033 metrics.descent = LGLYPH_DESCENT (g);
4034 if (NILP (LGLYPH_ADJUSTMENT (g)))
4035 {
4036 metrics.width = LGLYPH_WIDTH (g);
4037 if (LGLYPH_CHAR (g) == 0 || metrics.width == 0)
4038 need_composition = 1;
4039 }
4040 else
4041 {
4042 metrics.width = LGLYPH_WADJUST (g);
4043 metrics.lbearing += LGLYPH_XOFF (g);
4044 metrics.rbearing += LGLYPH_XOFF (g);
4045 metrics.ascent -= LGLYPH_YOFF (g);
4046 metrics.descent += LGLYPH_YOFF (g);
4047 need_composition = 1;
4048 }
4049 for (j = i + 1; j < len; j++)
4050 {
4051 int x;
4052
4053 g = LGSTRING_GLYPH (gstring, j);
4054 if (this_from != LGLYPH_FROM (g))
4055 break;
4056 need_composition = 1;
4057 x = metrics.width + LGLYPH_LBEARING (g) + LGLYPH_XOFF (g);
4058 if (metrics.lbearing > x)
4059 metrics.lbearing = x;
4060 x = metrics.width + LGLYPH_RBEARING (g) + LGLYPH_XOFF (g);
4061 if (metrics.rbearing < x)
4062 metrics.rbearing = x;
4063 x = LGLYPH_ASCENT (g) - LGLYPH_YOFF (g);
4064 if (metrics.ascent < x)
4065 metrics.ascent = x;
4066 x = LGLYPH_DESCENT (g) - LGLYPH_YOFF (g);
4067 if (metrics.descent < x)
4068 metrics.descent = x;
4069 if (NILP (LGLYPH_ADJUSTMENT (g)))
4070 metrics.width += LGLYPH_WIDTH (g);
4071 else
4072 metrics.width += LGLYPH_WADJUST (g);
4073 }
4074
4075 if (need_composition)
4076 {
4077 gstr = Ffont_make_gstring (font_object, make_number (j - i));
4078 LGSTRING_SET_WIDTH (gstr, metrics.width);
4079 LGSTRING_SET_LBEARING (gstr, metrics.lbearing);
4080 LGSTRING_SET_RBEARING (gstr, metrics.rbearing);
4081 LGSTRING_SET_ASCENT (gstr, metrics.ascent);
4082 LGSTRING_SET_DESCENT (gstr, metrics.descent);
4083 for (k = i; i < j; i++)
4084 {
4085 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
4086
4087 LGLYPH_SET_FROM (g, LGLYPH_FROM (g) - this_from);
4088 LGLYPH_SET_TO (g, LGLYPH_TO (g) - this_from);
4089 LGSTRING_SET_GLYPH (gstr, i - k, LGSTRING_GLYPH (gstring, i));
4090 }
4091 from = make_number (start + this_from);
4092 to = make_number (start + this_to);
4093 if (NILP (string))
4094 Fcompose_region_internal (from, to, gstr, Qnil);
4095 else
4096 Fcompose_string_internal (string, from, to, gstr, Qnil);
4097 }
4098 else
4099 i = j;
4100 }
4101
4102 return to;
4103 }
4104
4105 #if 0
4106
4107 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
4108 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
4109 OTF-FEATURES specifies which features to apply in this format:
4110 (SCRIPT LANGSYS GSUB GPOS)
4111 where
4112 SCRIPT is a symbol specifying a script tag of OpenType,
4113 LANGSYS is a symbol specifying a langsys tag of OpenType,
4114 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4115
4116 If LANGYS is nil, the default langsys is selected.
4117
4118 The features are applied in the order they appear in the list. The
4119 symbol `*' means to apply all available features not present in this
4120 list, and the remaining features are ignored. For instance, (vatu
4121 pstf * haln) is to apply vatu and pstf in this order, then to apply
4122 all available features other than vatu, pstf, and haln.
4123
4124 The features are applied to the glyphs in the range FROM and TO of
4125 the glyph-string GSTRING-IN.
4126
4127 If some feature is actually applicable, the resulting glyphs are
4128 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4129 this case, the value is the number of produced glyphs.
4130
4131 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4132 the value is 0.
4133
4134 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4135 produced in GSTRING-OUT, and the value is nil.
4136
4137 See the documentation of `font-make-gstring' for the format of
4138 glyph-string. */)
4139 (otf_features, gstring_in, from, to, gstring_out, index)
4140 Lisp_Object otf_features, gstring_in, from, to, gstring_out, index;
4141 {
4142 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
4143 Lisp_Object val;
4144 struct font *font;
4145 int len, num;
4146
4147 check_otf_features (otf_features);
4148 CHECK_FONT_OBJECT (font_object);
4149 font = XFONT_OBJECT (font_object);
4150 if (! font->driver->otf_drive)
4151 error ("Font backend %s can't drive OpenType GSUB table",
4152 SDATA (SYMBOL_NAME (font->driver->type)));
4153 CHECK_CONS (otf_features);
4154 CHECK_SYMBOL (XCAR (otf_features));
4155 val = XCDR (otf_features);
4156 CHECK_SYMBOL (XCAR (val));
4157 val = XCDR (otf_features);
4158 if (! NILP (val))
4159 CHECK_CONS (val);
4160 len = check_gstring (gstring_in);
4161 CHECK_VECTOR (gstring_out);
4162 CHECK_NATNUM (from);
4163 CHECK_NATNUM (to);
4164 CHECK_NATNUM (index);
4165
4166 if (XINT (from) >= XINT (to) || XINT (to) > len)
4167 args_out_of_range_3 (from, to, make_number (len));
4168 if (XINT (index) >= ASIZE (gstring_out))
4169 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4170 num = font->driver->otf_drive (font, otf_features,
4171 gstring_in, XINT (from), XINT (to),
4172 gstring_out, XINT (index), 0);
4173 if (num < 0)
4174 return Qnil;
4175 return make_number (num);
4176 }
4177
4178 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4179 3, 3, 0,
4180 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4181 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4182 in this format:
4183 (SCRIPT LANGSYS FEATURE ...)
4184 See the documentation of `font-drive-otf' for more detail.
4185
4186 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4187 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4188 character code corresponding to the glyph or nil if there's no
4189 corresponding character. */)
4190 (font_object, character, otf_features)
4191 Lisp_Object font_object, character, otf_features;
4192 {
4193 struct font *font;
4194 Lisp_Object gstring_in, gstring_out, g;
4195 Lisp_Object alternates;
4196 int i, num;
4197
4198 CHECK_FONT_GET_OBJECT (font_object, font);
4199 if (! font->driver->otf_drive)
4200 error ("Font backend %s can't drive OpenType GSUB table",
4201 SDATA (SYMBOL_NAME (font->driver->type)));
4202 CHECK_CHARACTER (character);
4203 CHECK_CONS (otf_features);
4204
4205 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4206 g = LGSTRING_GLYPH (gstring_in, 0);
4207 LGLYPH_SET_CHAR (g, XINT (character));
4208 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4209 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4210 gstring_out, 0, 1)) < 0)
4211 gstring_out = Ffont_make_gstring (font_object,
4212 make_number (ASIZE (gstring_out) * 2));
4213 alternates = Qnil;
4214 for (i = 0; i < num; i++)
4215 {
4216 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4217 int c = LGLYPH_CHAR (g);
4218 unsigned code = LGLYPH_CODE (g);
4219
4220 alternates = Fcons (Fcons (make_number (code),
4221 c > 0 ? make_number (c) : Qnil),
4222 alternates);
4223 }
4224 return Fnreverse (alternates);
4225 }
4226 #endif /* 0 */
4227
4228 #ifdef FONT_DEBUG
4229
4230 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4231 doc: /* Open FONT-ENTITY. */)
4232 (font_entity, size, frame)
4233 Lisp_Object font_entity;
4234 Lisp_Object size;
4235 Lisp_Object frame;
4236 {
4237 int isize;
4238
4239 CHECK_FONT_ENTITY (font_entity);
4240 if (NILP (frame))
4241 frame = selected_frame;
4242 CHECK_LIVE_FRAME (frame);
4243
4244 if (NILP (size))
4245 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4246 else
4247 {
4248 CHECK_NUMBER_OR_FLOAT (size);
4249 if (FLOATP (size))
4250 isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy);
4251 else
4252 isize = XINT (size);
4253 if (isize == 0)
4254 isize = 120;
4255 }
4256 return font_open_entity (XFRAME (frame), font_entity, isize);
4257 }
4258
4259 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4260 doc: /* Close FONT-OBJECT. */)
4261 (font_object, frame)
4262 Lisp_Object font_object, frame;
4263 {
4264 CHECK_FONT_OBJECT (font_object);
4265 if (NILP (frame))
4266 frame = selected_frame;
4267 CHECK_LIVE_FRAME (frame);
4268 font_close_object (XFRAME (frame), font_object);
4269 return Qnil;
4270 }
4271
4272 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4273 doc: /* Return information about FONT-OBJECT.
4274 The value is a vector:
4275 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4276 CAPABILITY ]
4277
4278 NAME is a string of the font name (or nil if the font backend doesn't
4279 provide a name).
4280
4281 FILENAME is a string of the font file (or nil if the font backend
4282 doesn't provide a file name).
4283
4284 PIXEL-SIZE is a pixel size by which the font is opened.
4285
4286 SIZE is a maximum advance width of the font in pixels.
4287
4288 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4289 pixels.
4290
4291 CAPABILITY is a list whose first element is a symbol representing the
4292 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4293 remaining elements describe the details of the font capability.
4294
4295 If the font is OpenType font, the form of the list is
4296 \(opentype GSUB GPOS)
4297 where GSUB shows which "GSUB" features the font supports, and GPOS
4298 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4299 lists of the format:
4300 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4301
4302 If the font is not OpenType font, currently the length of the form is
4303 one.
4304
4305 SCRIPT is a symbol representing OpenType script tag.
4306
4307 LANGSYS is a symbol representing OpenType langsys tag, or nil
4308 representing the default langsys.
4309
4310 FEATURE is a symbol representing OpenType feature tag.
4311
4312 If the font is not OpenType font, CAPABILITY is nil. */)
4313 (font_object)
4314 Lisp_Object font_object;
4315 {
4316 struct font *font;
4317 Lisp_Object val;
4318
4319 CHECK_FONT_GET_OBJECT (font_object, font);
4320
4321 val = Fmake_vector (make_number (9), Qnil);
4322 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4323 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4324 ASET (val, 2, make_number (font->pixel_size));
4325 ASET (val, 3, make_number (font->max_width));
4326 ASET (val, 4, make_number (font->ascent));
4327 ASET (val, 5, make_number (font->descent));
4328 ASET (val, 6, make_number (font->space_width));
4329 ASET (val, 7, make_number (font->average_width));
4330 if (font->driver->otf_capability)
4331 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4332 return val;
4333 }
4334
4335 DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
4336 doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
4337 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
4338 (font_object, string)
4339 Lisp_Object font_object, string;
4340 {
4341 struct font *font;
4342 int i, len;
4343 Lisp_Object vec;
4344
4345 CHECK_FONT_GET_OBJECT (font_object, font);
4346 CHECK_STRING (string);
4347 len = SCHARS (string);
4348 vec = Fmake_vector (make_number (len), Qnil);
4349 for (i = 0; i < len; i++)
4350 {
4351 Lisp_Object ch = Faref (string, make_number (i));
4352 Lisp_Object val;
4353 int c = XINT (ch);
4354 unsigned code;
4355 EMACS_INT cod;
4356 struct font_metrics metrics;
4357
4358 cod = code = font->driver->encode_char (font, c);
4359 if (code == FONT_INVALID_CODE)
4360 continue;
4361 val = Fmake_vector (make_number (6), Qnil);
4362 if (cod <= MOST_POSITIVE_FIXNUM)
4363 ASET (val, 0, make_number (code));
4364 else
4365 ASET (val, 0, Fcons (make_number (code >> 16),
4366 make_number (code & 0xFFFF)));
4367 font->driver->text_extents (font, &code, 1, &metrics);
4368 ASET (val, 1, make_number (metrics.lbearing));
4369 ASET (val, 2, make_number (metrics.rbearing));
4370 ASET (val, 3, make_number (metrics.width));
4371 ASET (val, 4, make_number (metrics.ascent));
4372 ASET (val, 5, make_number (metrics.descent));
4373 ASET (vec, i, val);
4374 }
4375 return vec;
4376 }
4377
4378 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4379 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4380 FONT is a font-spec, font-entity, or font-object. */)
4381 (spec, font)
4382 Lisp_Object spec, font;
4383 {
4384 CHECK_FONT_SPEC (spec);
4385 CHECK_FONT (font);
4386
4387 return (font_match_p (spec, font) ? Qt : Qnil);
4388 }
4389
4390 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4391 doc: /* Return a font-object for displaying a character at POSITION.
4392 Optional second arg WINDOW, if non-nil, is a window displaying
4393 the current buffer. It defaults to the currently selected window. */)
4394 (position, window, string)
4395 Lisp_Object position, window, string;
4396 {
4397 struct window *w;
4398 EMACS_INT pos;
4399
4400 if (NILP (string))
4401 {
4402 CHECK_NUMBER_COERCE_MARKER (position);
4403 pos = XINT (position);
4404 if (pos < BEGV || pos >= ZV)
4405 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4406 }
4407 else
4408 {
4409 CHECK_NUMBER (position);
4410 CHECK_STRING (string);
4411 pos = XINT (position);
4412 if (pos < 0 || pos >= SCHARS (string))
4413 args_out_of_range (string, position);
4414 }
4415 if (NILP (window))
4416 window = selected_window;
4417 CHECK_LIVE_WINDOW (window);
4418 w = XWINDOW (window);
4419
4420 return font_at (-1, pos, NULL, w, string);
4421 }
4422
4423 #if 0
4424 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4425 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4426 The value is a number of glyphs drawn.
4427 Type C-l to recover what previously shown. */)
4428 (font_object, string)
4429 Lisp_Object font_object, string;
4430 {
4431 Lisp_Object frame = selected_frame;
4432 FRAME_PTR f = XFRAME (frame);
4433 struct font *font;
4434 struct face *face;
4435 int i, len, width;
4436 unsigned *code;
4437
4438 CHECK_FONT_GET_OBJECT (font_object, font);
4439 CHECK_STRING (string);
4440 len = SCHARS (string);
4441 code = alloca (sizeof (unsigned) * len);
4442 for (i = 0; i < len; i++)
4443 {
4444 Lisp_Object ch = Faref (string, make_number (i));
4445 Lisp_Object val;
4446 int c = XINT (ch);
4447
4448 code[i] = font->driver->encode_char (font, c);
4449 if (code[i] == FONT_INVALID_CODE)
4450 break;
4451 }
4452 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4453 face->fontp = font;
4454 if (font->driver->prepare_face)
4455 font->driver->prepare_face (f, face);
4456 width = font->driver->text_extents (font, code, i, NULL);
4457 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4458 if (font->driver->done_face)
4459 font->driver->done_face (f, face);
4460 face->fontp = NULL;
4461 return make_number (len);
4462 }
4463 #endif
4464
4465 #endif /* FONT_DEBUG */
4466
4467 #ifdef HAVE_WINDOW_SYSTEM
4468
4469 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
4470 doc: /* Return information about a font named NAME on frame FRAME.
4471 If FRAME is omitted or nil, use the selected frame.
4472 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
4473 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4474 where
4475 OPENED-NAME is the name used for opening the font,
4476 FULL-NAME is the full name of the font,
4477 SIZE is the maximum bound width of the font,
4478 HEIGHT is the height of the font,
4479 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4480 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4481 how to compose characters.
4482 If the named font is not yet loaded, return nil. */)
4483 (name, frame)
4484 Lisp_Object name, frame;
4485 {
4486 FRAME_PTR f;
4487 struct font *font;
4488 Lisp_Object info;
4489 Lisp_Object font_object;
4490
4491 (*check_window_system_func) ();
4492
4493 if (! FONTP (name))
4494 CHECK_STRING (name);
4495 if (NILP (frame))
4496 frame = selected_frame;
4497 CHECK_LIVE_FRAME (frame);
4498 f = XFRAME (frame);
4499
4500 if (STRINGP (name))
4501 {
4502 int fontset = fs_query_fontset (name, 0);
4503
4504 if (fontset >= 0)
4505 name = fontset_ascii (fontset);
4506 font_object = font_open_by_name (f, (char *) SDATA (name));
4507 }
4508 else if (FONT_OBJECT_P (name))
4509 font_object = name;
4510 else if (FONT_ENTITY_P (name))
4511 font_object = font_open_entity (f, name, 0);
4512 else
4513 {
4514 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4515 Lisp_Object entity = font_matching_entity (f, face->lface, name);
4516
4517 font_object = ! NILP (entity) ? font_open_entity (f, entity, 0) : Qnil;
4518 }
4519 if (NILP (font_object))
4520 return Qnil;
4521 font = XFONT_OBJECT (font_object);
4522
4523 info = Fmake_vector (make_number (7), Qnil);
4524 XVECTOR (info)->contents[0] = AREF (font_object, FONT_NAME_INDEX);
4525 XVECTOR (info)->contents[1] = AREF (font_object, FONT_NAME_INDEX);
4526 XVECTOR (info)->contents[2] = make_number (font->pixel_size);
4527 XVECTOR (info)->contents[3] = make_number (font->height);
4528 XVECTOR (info)->contents[4] = make_number (font->baseline_offset);
4529 XVECTOR (info)->contents[5] = make_number (font->relative_compose);
4530 XVECTOR (info)->contents[6] = make_number (font->default_ascent);
4531
4532 #if 0
4533 /* As font_object is still in FONT_OBJLIST of the entity, we can't
4534 close it now. Perhaps, we should manage font-objects
4535 by `reference-count'. */
4536 font_close_object (f, font_object);
4537 #endif
4538 return info;
4539 }
4540 #endif
4541
4542 \f
4543 #define BUILD_STYLE_TABLE(TBL) \
4544 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
4545
4546 static Lisp_Object
4547 build_style_table (entry, nelement)
4548 struct table_entry *entry;
4549 int nelement;
4550 {
4551 int i, j;
4552 Lisp_Object table, elt;
4553
4554 table = Fmake_vector (make_number (nelement), Qnil);
4555 for (i = 0; i < nelement; i++)
4556 {
4557 for (j = 0; entry[i].names[j]; j++);
4558 elt = Fmake_vector (make_number (j + 1), Qnil);
4559 ASET (elt, 0, make_number (entry[i].numeric));
4560 for (j = 0; entry[i].names[j]; j++)
4561 ASET (elt, j + 1, intern (entry[i].names[j]));
4562 ASET (table, i, elt);
4563 }
4564 return table;
4565 }
4566
4567 static Lisp_Object Vfont_log;
4568 static int font_log_env_checked;
4569
4570 void
4571 font_add_log (action, arg, result)
4572 char *action;
4573 Lisp_Object arg, result;
4574 {
4575 Lisp_Object tail, val;
4576 int i;
4577
4578 if (! font_log_env_checked)
4579 {
4580 Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;
4581 font_log_env_checked = 1;
4582 }
4583 if (EQ (Vfont_log, Qt))
4584 return;
4585 if (FONTP (arg))
4586 arg = Ffont_xlfd_name (arg, Qt);
4587 if (FONTP (result))
4588 result = Ffont_xlfd_name (result, Qt);
4589 else if (CONSP (result))
4590 {
4591 result = Fcopy_sequence (result);
4592 for (tail = result; CONSP (tail); tail = XCDR (tail))
4593 {
4594 val = XCAR (tail);
4595 if (FONTP (val))
4596 val = Ffont_xlfd_name (val, Qt);
4597 XSETCAR (tail, val);
4598 }
4599 }
4600 else if (VECTORP (result))
4601 {
4602 result = Fcopy_sequence (result);
4603 for (i = 0; i < ASIZE (result); i++)
4604 {
4605 val = AREF (result, i);
4606 if (FONTP (val))
4607 val = Ffont_xlfd_name (val, Qt);
4608 ASET (result, i, val);
4609 }
4610 }
4611 Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
4612 }
4613
4614 extern void syms_of_ftfont P_ (());
4615 extern void syms_of_xfont P_ (());
4616 extern void syms_of_xftfont P_ (());
4617 extern void syms_of_ftxfont P_ (());
4618 extern void syms_of_bdffont P_ (());
4619 extern void syms_of_w32font P_ (());
4620 extern void syms_of_atmfont P_ (());
4621
4622 void
4623 syms_of_font ()
4624 {
4625 sort_shift_bits[FONT_TYPE_INDEX] = 0;
4626 sort_shift_bits[FONT_SLANT_INDEX] = 2;
4627 sort_shift_bits[FONT_WEIGHT_INDEX] = 9;
4628 sort_shift_bits[FONT_SIZE_INDEX] = 16;
4629 sort_shift_bits[FONT_WIDTH_INDEX] = 23;
4630 /* Note that the other elements in sort_shift_bits are not used. */
4631
4632 staticpro (&font_charset_alist);
4633 font_charset_alist = Qnil;
4634
4635 DEFSYM (Qfont_spec, "font-spec");
4636 DEFSYM (Qfont_entity, "font-entity");
4637 DEFSYM (Qfont_object, "font-object");
4638
4639 DEFSYM (Qopentype, "opentype");
4640
4641 DEFSYM (Qascii_0, "ascii-0");
4642 DEFSYM (Qiso8859_1, "iso8859-1");
4643 DEFSYM (Qiso10646_1, "iso10646-1");
4644 DEFSYM (Qunicode_bmp, "unicode-bmp");
4645 DEFSYM (Qunicode_sip, "unicode-sip");
4646
4647 DEFSYM (QCotf, ":otf");
4648 DEFSYM (QClang, ":lang");
4649 DEFSYM (QCscript, ":script");
4650 DEFSYM (QCantialias, ":antialias");
4651
4652 DEFSYM (QCfoundry, ":foundry");
4653 DEFSYM (QCadstyle, ":adstyle");
4654 DEFSYM (QCregistry, ":registry");
4655 DEFSYM (QCspacing, ":spacing");
4656 DEFSYM (QCdpi, ":dpi");
4657 DEFSYM (QCscalable, ":scalable");
4658 DEFSYM (QCavgwidth, ":avgwidth");
4659 DEFSYM (QCfont_entity, ":font-entity");
4660 DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
4661
4662 DEFSYM (Qc, "c");
4663 DEFSYM (Qm, "m");
4664 DEFSYM (Qp, "p");
4665 DEFSYM (Qd, "d");
4666
4667 staticpro (&null_vector);
4668 null_vector = Fmake_vector (make_number (0), Qnil);
4669
4670 staticpro (&scratch_font_spec);
4671 scratch_font_spec = Ffont_spec (0, NULL);
4672 staticpro (&scratch_font_prefer);
4673 scratch_font_prefer = Ffont_spec (0, NULL);
4674
4675 #if 0
4676 #ifdef HAVE_LIBOTF
4677 staticpro (&otf_list);
4678 otf_list = Qnil;
4679 #endif /* HAVE_LIBOTF */
4680 #endif /* 0 */
4681
4682 defsubr (&Sfontp);
4683 defsubr (&Sfont_spec);
4684 defsubr (&Sfont_get);
4685 defsubr (&Sfont_put);
4686 defsubr (&Slist_fonts);
4687 defsubr (&Sfont_family_list);
4688 defsubr (&Sfind_font);
4689 defsubr (&Sfont_xlfd_name);
4690 defsubr (&Sclear_font_cache);
4691 defsubr (&Sfont_make_gstring);
4692 defsubr (&Sfont_fill_gstring);
4693 defsubr (&Sfont_shape_text);
4694 #if 0
4695 defsubr (&Sfont_drive_otf);
4696 defsubr (&Sfont_otf_alternates);
4697 #endif /* 0 */
4698
4699 #ifdef FONT_DEBUG
4700 defsubr (&Sopen_font);
4701 defsubr (&Sclose_font);
4702 defsubr (&Squery_font);
4703 defsubr (&Sget_font_glyphs);
4704 defsubr (&Sfont_match_p);
4705 defsubr (&Sfont_at);
4706 #if 0
4707 defsubr (&Sdraw_string);
4708 #endif
4709 #endif /* FONT_DEBUG */
4710 #ifdef HAVE_WINDOW_SYSTEM
4711 defsubr (&Sfont_info);
4712 #endif
4713
4714 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
4715 doc: /*
4716 Alist of fontname patterns vs the corresponding encoding and repertory info.
4717 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
4718 where ENCODING is a charset or a char-table,
4719 and REPERTORY is a charset, a char-table, or nil.
4720
4721 If ENCODING and REPERTORY are the same, the element can have the form
4722 \(REGEXP . ENCODING).
4723
4724 ENCODING is for converting a character to a glyph code of the font.
4725 If ENCODING is a charset, encoding a character by the charset gives
4726 the corresponding glyph code. If ENCODING is a char-table, looking up
4727 the table by a character gives the corresponding glyph code.
4728
4729 REPERTORY specifies a repertory of characters supported by the font.
4730 If REPERTORY is a charset, all characters beloging to the charset are
4731 supported. If REPERTORY is a char-table, all characters who have a
4732 non-nil value in the table are supported. If REPERTORY is nil, Emacs
4733 gets the repertory information by an opened font and ENCODING. */);
4734 Vfont_encoding_alist = Qnil;
4735
4736 DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table,
4737 doc: /* Vector of valid font weight values.
4738 Each element has the form:
4739 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
4740 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symobls. */);
4741 Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
4742
4743 DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table,
4744 doc: /* Vector of font slant symbols vs the corresponding numeric values.
4745 See `font-weight_table' for the format of the vector. */);
4746 Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
4747
4748 DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table,
4749 doc: /* Alist of font width symbols vs the corresponding numeric values.
4750 See `font-weight_table' for the format of the vector. */);
4751 Vfont_width_table = BUILD_STYLE_TABLE (width_table);
4752
4753 staticpro (&font_style_table);
4754 font_style_table = Fmake_vector (make_number (3), Qnil);
4755 ASET (font_style_table, 0, Vfont_weight_table);
4756 ASET (font_style_table, 1, Vfont_slant_table);
4757 ASET (font_style_table, 2, Vfont_width_table);
4758
4759 DEFVAR_LISP ("font-log", &Vfont_log, doc: /*
4760 *Logging list of font related actions and results.
4761 The value t means to suppress the logging.
4762 The initial value is set to nil if the environment variable
4763 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
4764 Vfont_log = Qnil;
4765
4766 #ifdef HAVE_WINDOW_SYSTEM
4767 #ifdef HAVE_FREETYPE
4768 syms_of_ftfont ();
4769 #ifdef HAVE_X_WINDOWS
4770 syms_of_xfont ();
4771 syms_of_ftxfont ();
4772 #ifdef HAVE_XFT
4773 syms_of_xftfont ();
4774 #endif /* HAVE_XFT */
4775 #endif /* HAVE_X_WINDOWS */
4776 #else /* not HAVE_FREETYPE */
4777 #ifdef HAVE_X_WINDOWS
4778 syms_of_xfont ();
4779 #endif /* HAVE_X_WINDOWS */
4780 #endif /* not HAVE_FREETYPE */
4781 #ifdef HAVE_BDFFONT
4782 syms_of_bdffont ();
4783 #endif /* HAVE_BDFFONT */
4784 #ifdef WINDOWSNT
4785 syms_of_w32font ();
4786 #endif /* WINDOWSNT */
4787 #ifdef MAC_OS
4788 syms_of_atmfont ();
4789 #endif /* MAC_OS */
4790 #endif /* HAVE_WINDOW_SYSTEM */
4791 }
4792
4793 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
4794 (do not change this comment) */