(font_intern_prop): New arg force_symbol.
[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) as Fonconfig's name format and store
1327 information in FONT (font-spec or font-entity). If NAME is
1328 successfully parsed, return 0. Otherwise return -1. */
1329
1330 int
1331 font_parse_fcname (name, font)
1332 char *name;
1333 Lisp_Object font;
1334 {
1335 char *p0, *p1;
1336 int len = strlen (name);
1337 char *copy;
1338
1339 if (len == 0)
1340 return -1;
1341 /* It is assured that (name[0] && name[0] != '-'). */
1342 if (name[0] == ':')
1343 p0 = name;
1344 else
1345 {
1346 Lisp_Object family;
1347 double point_size;
1348
1349 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++)
1350 if (*p0 == '\\' && p0[1])
1351 p0++;
1352 family = font_intern_prop (name, p0 - name, 1);
1353 if (*p0 == '-')
1354 {
1355 if (! isdigit (p0[1]))
1356 return -1;
1357 point_size = strtod (p0 + 1, &p1);
1358 if (*p1 && *p1 != ':')
1359 return -1;
1360 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1361 p0 = p1;
1362 }
1363 ASET (font, FONT_FAMILY_INDEX, family);
1364 }
1365
1366 len -= p0 - name;
1367 copy = alloca (len + 1);
1368 if (! copy)
1369 return -1;
1370 name = copy;
1371
1372 /* Now parse ":KEY=VAL" patterns. Store known keys and values in
1373 extra, copy unknown ones to COPY. It is stored in extra slot by
1374 the key QCfc_unknown_spec. */
1375 while (*p0)
1376 {
1377 Lisp_Object key, val;
1378 int prop;
1379
1380 for (p1 = p0 + 1; *p1 && *p1 != '=' && *p1 != ':'; p1++);
1381 if (*p1 != '=')
1382 {
1383 /* Must be an enumerated value. */
1384 val = font_intern_prop (p0 + 1, p1 - p0 - 1, 1);
1385 if (memcmp (p0 + 1, "light", 5) == 0
1386 || memcmp (p0 + 1, "medium", 6) == 0
1387 || memcmp (p0 + 1, "demibold", 8) == 0
1388 || memcmp (p0 + 1, "bold", 4) == 0
1389 || memcmp (p0 + 1, "black", 5) == 0)
1390 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
1391 else if (memcmp (p0 + 1, "roman", 5) == 0
1392 || memcmp (p0 + 1, "italic", 6) == 0
1393 || memcmp (p0 + 1, "oblique", 7) == 0)
1394 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
1395 else if (memcmp (p0 + 1, "charcell", 8) == 0
1396 || memcmp (p0 + 1, "mono", 4) == 0
1397 || memcmp (p0 + 1, "proportional", 12) == 0)
1398 {
1399 int spacing = (p0[1] == 'c' ? FONT_SPACING_CHARCELL
1400 : p0[1] == 'm' ? FONT_SPACING_MONO
1401 : FONT_SPACING_PROPORTIONAL);
1402 ASET (font, FONT_SPACING_INDEX, make_number (spacing));
1403 }
1404 else
1405 {
1406 /* unknown key */
1407 bcopy (p0, copy, p1 - p0);
1408 copy += p1 - p0;
1409 }
1410 }
1411 else
1412 {
1413 char *keyhead = p0;
1414
1415 if (memcmp (p0 + 1, "pixelsize=", 10) == 0)
1416 prop = FONT_SIZE_INDEX;
1417 else
1418 {
1419 key = font_intern_prop (p0, p1 - p0, 1);
1420 prop = get_font_prop_index (key);
1421 }
1422 p0 = p1 + 1;
1423 for (p1 = p0; *p1 && *p1 != ':'; p1++);
1424 val = font_intern_prop (p0, p1 - p0, 0);
1425 if (! NILP (val))
1426 {
1427 if (prop >= FONT_FOUNDRY_INDEX && prop < FONT_EXTRA_INDEX)
1428 ASET (font, prop, font_prop_validate (prop, Qnil, val));
1429 else if (prop >= 0)
1430 Ffont_put (font, key, val);
1431 else
1432 bcopy (keyhead, copy, p1 - keyhead);
1433 copy += p1 - keyhead;
1434 }
1435 }
1436 p0 = p1;
1437 }
1438 if (name != copy)
1439 font_put_extra (font, QCfc_unknown_spec,
1440 make_unibyte_string (name, copy - name));
1441
1442 return 0;
1443 }
1444
1445 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1446 NAME (NBYTES length), and return the name length. If
1447 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1448
1449 int
1450 font_unparse_fcname (font, pixel_size, name, nbytes)
1451 Lisp_Object font;
1452 int pixel_size;
1453 char *name;
1454 int nbytes;
1455 {
1456 Lisp_Object tail, val;
1457 int point_size;
1458 int dpi;
1459 int i, len = 1;
1460 char *p;
1461 Lisp_Object styles[3];
1462 char *style_names[3] = { "weight", "slant", "width" };
1463 char work[256];
1464
1465 val = AREF (font, FONT_FAMILY_INDEX);
1466 if (STRINGP (val))
1467 len += SBYTES (val);
1468
1469 val = AREF (font, FONT_SIZE_INDEX);
1470 if (INTEGERP (val))
1471 {
1472 if (XINT (val) != 0)
1473 pixel_size = XINT (val);
1474 point_size = -1;
1475 len += 21; /* for ":pixelsize=NUM" */
1476 }
1477 else if (FLOATP (val))
1478 {
1479 pixel_size = -1;
1480 point_size = (int) XFLOAT_DATA (val);
1481 len += 11; /* for "-NUM" */
1482 }
1483
1484 val = AREF (font, FONT_FOUNDRY_INDEX);
1485 if (STRINGP (val))
1486 /* ":foundry=NAME" */
1487 len += 9 + SBYTES (val);
1488
1489 for (i = 0; i < 3; i++)
1490 {
1491 styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
1492 if (! NILP (styles[i]))
1493 len += sprintf (work, ":%s=%s", style_names[i],
1494 SDATA (SYMBOL_NAME (styles[i])));
1495 }
1496
1497 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1498 len += sprintf (work, ":dpi=%d", dpi);
1499 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1500 len += strlen (":spacing=100");
1501 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1502 len += strlen (":scalable=false"); /* or ":scalable=true" */
1503 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
1504 {
1505 Lisp_Object key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
1506
1507 len += SBYTES (SYMBOL_NAME (key)) + 1; /* for :KEY= */
1508 if (STRINGP (val))
1509 len += SBYTES (val);
1510 else if (INTEGERP (val))
1511 len += sprintf (work, "%d", XINT (val));
1512 else if (SYMBOLP (val))
1513 len += (NILP (val) ? 5 : 4); /* for "false" or "true" */
1514 }
1515
1516 if (len > nbytes)
1517 return -1;
1518 p = name;
1519 if (! NILP (AREF (font, FONT_FAMILY_INDEX)))
1520 p += sprintf(p, "%s", SDATA (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX))));
1521 if (point_size > 0)
1522 {
1523 if (p == name)
1524 p += sprintf (p, "%d", point_size);
1525 else
1526 p += sprintf (p, "-%d", point_size);
1527 }
1528 else if (pixel_size > 0)
1529 p += sprintf (p, ":pixelsize=%d", pixel_size);
1530 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1531 p += sprintf (p, ":foundry=%s",
1532 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1533 for (i = 0; i < 3; i++)
1534 if (! NILP (styles[i]))
1535 p += sprintf (p, ":%s=%s", style_names[i],
1536 SDATA (SYMBOL_NAME (styles[i])));
1537 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1538 p += sprintf (p, ":dpi=%d", XINT (AREF (font, FONT_DPI_INDEX)));
1539 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1540 p += sprintf (p, ":spacing=%d", XINT (AREF (font, FONT_SPACING_INDEX)));
1541 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1542 {
1543 if (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0)
1544 p += sprintf (p, ":scalable=true");
1545 else
1546 p += sprintf (p, ":scalable=false");
1547 }
1548 return (p - name);
1549 }
1550
1551 /* Parse NAME (null terminated) and store information in FONT
1552 (font-spec or font-entity). If NAME is successfully parsed, return
1553 0. Otherwise return -1. */
1554
1555 static int
1556 font_parse_name (name, font)
1557 char *name;
1558 Lisp_Object font;
1559 {
1560 if (name[0] == '-' || index (name, '*'))
1561 return font_parse_xlfd (name, font);
1562 return font_parse_fcname (name, font);
1563 }
1564
1565
1566 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1567 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1568 part. */
1569
1570 void
1571 font_parse_family_registry (family, registry, font_spec)
1572 Lisp_Object family, registry, font_spec;
1573 {
1574 int len;
1575 char *p0, *p1;
1576
1577 if (! NILP (family)
1578 && NILP (AREF (font_spec, FONT_FAMILY_INDEX)))
1579 {
1580 CHECK_STRING (family);
1581 len = SBYTES (family);
1582 p0 = (char *) SDATA (family);
1583 p1 = index (p0, '-');
1584 if (p1)
1585 {
1586 if ((*p0 != '*' || p1 - p0 > 1)
1587 && NILP (AREF (font_spec, FONT_FOUNDRY_INDEX)))
1588 Ffont_put (font_spec, QCfoundry, font_intern_prop (p0, p1 - p0, 1));
1589 p1++;
1590 len -= p1 - p0;
1591 Ffont_put (font_spec, QCfamily, font_intern_prop (p1, len, 1));
1592 }
1593 else
1594 ASET (font_spec, FONT_FAMILY_INDEX, Fintern (family, Qnil));
1595 }
1596 if (! NILP (registry))
1597 {
1598 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1599 CHECK_STRING (registry);
1600 len = SBYTES (registry);
1601 p0 = (char *) SDATA (registry);
1602 p1 = index (p0, '-');
1603 if (! p1)
1604 {
1605 if (SDATA (registry)[len - 1] == '*')
1606 registry = concat2 (registry, build_string ("-*"));
1607 else
1608 registry = concat2 (registry, build_string ("*-*"));
1609 }
1610 registry = Fdowncase (registry);
1611 ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil));
1612 }
1613 }
1614
1615 \f
1616 /* This part (through the next ^L) is still experimental and not
1617 tested much. We may drastically change codes. */
1618
1619 /* OTF handler */
1620
1621 #if 0
1622
1623 #define LGSTRING_HEADER_SIZE 6
1624 #define LGSTRING_GLYPH_SIZE 8
1625
1626 static int
1627 check_gstring (gstring)
1628 Lisp_Object gstring;
1629 {
1630 Lisp_Object val;
1631 int i, j;
1632
1633 CHECK_VECTOR (gstring);
1634 val = AREF (gstring, 0);
1635 CHECK_VECTOR (val);
1636 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1637 goto err;
1638 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1639 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1640 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1641 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1642 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1643 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1644 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1645 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1646 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1647 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1648 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1649
1650 for (i = 0; i < LGSTRING_LENGTH (gstring); i++)
1651 {
1652 val = LGSTRING_GLYPH (gstring, i);
1653 CHECK_VECTOR (val);
1654 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1655 goto err;
1656 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1657 break;
1658 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1659 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1660 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1661 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1662 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1663 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1664 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1665 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1666 {
1667 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1668 CHECK_VECTOR (val);
1669 if (ASIZE (val) < 3)
1670 goto err;
1671 for (j = 0; j < 3; j++)
1672 CHECK_NUMBER (AREF (val, j));
1673 }
1674 }
1675 return i;
1676 err:
1677 error ("Invalid glyph-string format");
1678 return -1;
1679 }
1680
1681 static void
1682 check_otf_features (otf_features)
1683 Lisp_Object otf_features;
1684 {
1685 Lisp_Object val;
1686
1687 CHECK_CONS (otf_features);
1688 CHECK_SYMBOL (XCAR (otf_features));
1689 otf_features = XCDR (otf_features);
1690 CHECK_CONS (otf_features);
1691 CHECK_SYMBOL (XCAR (otf_features));
1692 otf_features = XCDR (otf_features);
1693 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1694 {
1695 CHECK_SYMBOL (Fcar (val));
1696 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1697 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val)));
1698 }
1699 otf_features = XCDR (otf_features);
1700 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1701 {
1702 CHECK_SYMBOL (Fcar (val));
1703 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1704 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val)));
1705 }
1706 }
1707
1708 #ifdef HAVE_LIBOTF
1709 #include <otf.h>
1710
1711 Lisp_Object otf_list;
1712
1713 static Lisp_Object
1714 otf_tag_symbol (tag)
1715 OTF_Tag tag;
1716 {
1717 char name[5];
1718
1719 OTF_tag_name (tag, name);
1720 return Fintern (make_unibyte_string (name, 4), Qnil);
1721 }
1722
1723 static OTF *
1724 otf_open (file)
1725 Lisp_Object file;
1726 {
1727 Lisp_Object val = Fassoc (file, otf_list);
1728 OTF *otf;
1729
1730 if (! NILP (val))
1731 otf = XSAVE_VALUE (XCDR (val))->pointer;
1732 else
1733 {
1734 otf = STRINGP (file) ? OTF_open ((char *) SDATA (file)) : NULL;
1735 val = make_save_value (otf, 0);
1736 otf_list = Fcons (Fcons (file, val), otf_list);
1737 }
1738 return otf;
1739 }
1740
1741
1742 /* Return a list describing which scripts/languages FONT supports by
1743 which GSUB/GPOS features of OpenType tables. See the comment of
1744 (struct font_driver).otf_capability. */
1745
1746 Lisp_Object
1747 font_otf_capability (font)
1748 struct font *font;
1749 {
1750 OTF *otf;
1751 Lisp_Object capability = Fcons (Qnil, Qnil);
1752 int i;
1753
1754 otf = otf_open (font->props[FONT_FILE_INDEX]);
1755 if (! otf)
1756 return Qnil;
1757 for (i = 0; i < 2; i++)
1758 {
1759 OTF_GSUB_GPOS *gsub_gpos;
1760 Lisp_Object script_list = Qnil;
1761 int j;
1762
1763 if (OTF_get_features (otf, i == 0) < 0)
1764 continue;
1765 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1766 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1767 {
1768 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1769 Lisp_Object langsys_list = Qnil;
1770 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1771 int k;
1772
1773 for (k = script->LangSysCount; k >= 0; k--)
1774 {
1775 OTF_LangSys *langsys;
1776 Lisp_Object feature_list = Qnil;
1777 Lisp_Object langsys_tag;
1778 int l;
1779
1780 if (k == script->LangSysCount)
1781 {
1782 langsys = &script->DefaultLangSys;
1783 langsys_tag = Qnil;
1784 }
1785 else
1786 {
1787 langsys = script->LangSys + k;
1788 langsys_tag
1789 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
1790 }
1791 for (l = langsys->FeatureCount - 1; l >= 0; l--)
1792 {
1793 OTF_Feature *feature
1794 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
1795 Lisp_Object feature_tag
1796 = otf_tag_symbol (feature->FeatureTag);
1797
1798 feature_list = Fcons (feature_tag, feature_list);
1799 }
1800 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1801 langsys_list);
1802 }
1803 script_list = Fcons (Fcons (script_tag, langsys_list),
1804 script_list);
1805 }
1806
1807 if (i == 0)
1808 XSETCAR (capability, script_list);
1809 else
1810 XSETCDR (capability, script_list);
1811 }
1812
1813 return capability;
1814 }
1815
1816 /* Parse OTF features in SPEC and write a proper features spec string
1817 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1818 assured that the sufficient memory has already allocated for
1819 FEATURES. */
1820
1821 static void
1822 generate_otf_features (spec, features)
1823 Lisp_Object spec;
1824 char *features;
1825 {
1826 Lisp_Object val;
1827 char *p;
1828 int asterisk;
1829
1830 p = features;
1831 *p = '\0';
1832 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
1833 {
1834 val = XCAR (spec);
1835 CHECK_SYMBOL (val);
1836 if (p > features)
1837 *p++ = ',';
1838 if (SREF (SYMBOL_NAME (val), 0) == '*')
1839 {
1840 asterisk = 1;
1841 *p++ = '*';
1842 }
1843 else if (! asterisk)
1844 {
1845 val = SYMBOL_NAME (val);
1846 p += sprintf (p, "%s", SDATA (val));
1847 }
1848 else
1849 {
1850 val = SYMBOL_NAME (val);
1851 p += sprintf (p, "~%s", SDATA (val));
1852 }
1853 }
1854 if (CONSP (spec))
1855 error ("OTF spec too long");
1856 }
1857
1858 Lisp_Object
1859 font_otf_DeviceTable (device_table)
1860 OTF_DeviceTable *device_table;
1861 {
1862 int len = device_table->StartSize - device_table->EndSize + 1;
1863
1864 return Fcons (make_number (len),
1865 make_unibyte_string (device_table->DeltaValue, len));
1866 }
1867
1868 Lisp_Object
1869 font_otf_ValueRecord (value_format, value_record)
1870 int value_format;
1871 OTF_ValueRecord *value_record;
1872 {
1873 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
1874
1875 if (value_format & OTF_XPlacement)
1876 ASET (val, 0, make_number (value_record->XPlacement));
1877 if (value_format & OTF_YPlacement)
1878 ASET (val, 1, make_number (value_record->YPlacement));
1879 if (value_format & OTF_XAdvance)
1880 ASET (val, 2, make_number (value_record->XAdvance));
1881 if (value_format & OTF_YAdvance)
1882 ASET (val, 3, make_number (value_record->YAdvance));
1883 if (value_format & OTF_XPlaDevice)
1884 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
1885 if (value_format & OTF_YPlaDevice)
1886 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
1887 if (value_format & OTF_XAdvDevice)
1888 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
1889 if (value_format & OTF_YAdvDevice)
1890 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
1891 return val;
1892 }
1893
1894 Lisp_Object
1895 font_otf_Anchor (anchor)
1896 OTF_Anchor *anchor;
1897 {
1898 Lisp_Object val;
1899
1900 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
1901 ASET (val, 0, make_number (anchor->XCoordinate));
1902 ASET (val, 1, make_number (anchor->YCoordinate));
1903 if (anchor->AnchorFormat == 2)
1904 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
1905 else
1906 {
1907 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
1908 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
1909 }
1910 return val;
1911 }
1912 #endif /* HAVE_LIBOTF */
1913 #endif /* 0 */
1914
1915 /* G-string (glyph string) handler */
1916
1917 /* G-string is a vector of the form [HEADER GLYPH ...].
1918 See the docstring of `font-make-gstring' for more detail. */
1919
1920 struct font *
1921 font_prepare_composition (cmp, f)
1922 struct composition *cmp;
1923 FRAME_PTR f;
1924 {
1925 Lisp_Object gstring
1926 = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
1927 cmp->hash_index * 2);
1928
1929 cmp->font = XFONT_OBJECT (LGSTRING_FONT (gstring));
1930 cmp->glyph_len = LGSTRING_LENGTH (gstring);
1931 cmp->pixel_width = LGSTRING_WIDTH (gstring);
1932 cmp->lbearing = LGSTRING_LBEARING (gstring);
1933 cmp->rbearing = LGSTRING_RBEARING (gstring);
1934 cmp->ascent = LGSTRING_ASCENT (gstring);
1935 cmp->descent = LGSTRING_DESCENT (gstring);
1936 cmp->width = cmp->pixel_width / FRAME_COLUMN_WIDTH (f);
1937 if (cmp->width == 0)
1938 cmp->width = 1;
1939
1940 return cmp->font;
1941 }
1942
1943 \f
1944 /* Font sorting */
1945
1946 static unsigned font_score P_ ((Lisp_Object, Lisp_Object *, Lisp_Object));
1947 static int font_compare P_ ((const void *, const void *));
1948 static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object,
1949 Lisp_Object, Lisp_Object,
1950 int));
1951
1952 /* We sort fonts by scoring each of them against a specified
1953 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1954 the value is, the closer the font is to the font-spec.
1955
1956 The highest 2 bits of the score is used for FAMILY. The exact
1957 match is 0, match with one of face-font-family-alternatives is
1958 nonzero.
1959
1960 The next 2 bits of the score is used for the atomic properties
1961 FOUNDRY and ADSTYLE respectively.
1962
1963 Each 7-bit in the lower 28 bits are used for numeric properties
1964 WEIGHT, SLANT, WIDTH, and SIZE. */
1965
1966 /* How many bits to shift to store the difference value of each font
1967 property in a score. Note that flots for FONT_TYPE_INDEX and
1968 FONT_REGISTRY_INDEX are not used. */
1969 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
1970
1971 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1972 The return value indicates how different ENTITY is compared with
1973 SPEC_PROP.
1974
1975 ALTERNATE_FAMILIES, if non-nil, is a pre-calculated list of
1976 alternate family names for AREF (SPEC_PROP, FONT_FAMILY_INDEX). */
1977
1978 static unsigned
1979 font_score (entity, spec_prop, alternate_families)
1980 Lisp_Object entity, *spec_prop;
1981 Lisp_Object alternate_families;
1982 {
1983 unsigned score = 0;
1984 int i;
1985
1986 /* Score three atomic fields. Maximum difference is 1 (family is 3). */
1987 for (i = FONT_FOUNDRY_INDEX; i <= FONT_ADSTYLE_INDEX; i++)
1988 if (i != FONT_REGISTRY_INDEX
1989 && ! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
1990 {
1991 Lisp_Object entity_str = SYMBOL_NAME (AREF (entity, i));
1992 Lisp_Object spec_str = SYMBOL_NAME (spec_prop[i]);
1993
1994 if (xstrcasecmp (SDATA (spec_str), SDATA (entity_str)))
1995 {
1996 if (i == FONT_FAMILY_INDEX && CONSP (alternate_families))
1997 {
1998 int j;
1999
2000 for (j = 1; CONSP (alternate_families);
2001 j++, alternate_families = XCDR (alternate_families))
2002 {
2003 spec_str = XCAR (alternate_families);
2004 if (xstrcasecmp (SDATA (spec_str), SDATA (entity_str)) == 0)
2005 break;
2006 }
2007 if (j > 3)
2008 j = 3;
2009 score |= j << sort_shift_bits[i];
2010 }
2011 else
2012 score |= 1 << sort_shift_bits[i];
2013 }
2014 }
2015
2016 /* Score three style numeric fields. Maximum difference is 127. */
2017 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
2018 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
2019 {
2020 int diff = (XINT (AREF (entity, i)) >> 8) - (XINT (spec_prop[i]) >> 8);
2021
2022 if (diff < 0)
2023 diff = - diff;
2024 /* This is to prefer the exact symbol style. */
2025 diff++;
2026 score |= min (diff, 127) << sort_shift_bits[i];
2027 }
2028
2029 /* Score the size. Maximum difference is 127. */
2030 i = FONT_SIZE_INDEX;
2031 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i])
2032 && XINT (AREF (entity, i)) > 0)
2033 {
2034 /* We use the higher 6-bit for the actual size difference. The
2035 lowest bit is set if the DPI is different. */
2036 int diff = XINT (spec_prop[i]) - XINT (AREF (entity, i));
2037
2038 if (diff < 0)
2039 diff = - diff;
2040 diff <<= 1;
2041 if (! NILP (spec_prop[FONT_DPI_INDEX])
2042 && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX)))
2043 diff |= 1;
2044 score |= min (diff, 127) << sort_shift_bits[FONT_SIZE_INDEX];
2045 }
2046
2047 return score;
2048 }
2049
2050
2051 /* The comparison function for qsort. */
2052
2053 static int
2054 font_compare (d1, d2)
2055 const void *d1, *d2;
2056 {
2057 return (*(unsigned *) d1 - *(unsigned *) d2);
2058 }
2059
2060
2061 /* The structure for elements being sorted by qsort. */
2062 struct font_sort_data
2063 {
2064 unsigned score;
2065 Lisp_Object entity;
2066 };
2067
2068
2069 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2070 If PREFER specifies a point-size, calculate the corresponding
2071 pixel-size from QCdpi property of PREFER or from the Y-resolution
2072 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
2073 get the font-entities in VEC.
2074
2075 If BEST-ONLY is nonzero, return the best matching entity. Otherwise,
2076 return the sorted VEC. */
2077
2078 static Lisp_Object
2079 font_sort_entites (vec, prefer, frame, spec, best_only)
2080 Lisp_Object vec, prefer, frame, spec;
2081 int best_only;
2082 {
2083 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2084 int len, i;
2085 struct font_sort_data *data;
2086 Lisp_Object alternate_families = Qnil;
2087 unsigned best_score;
2088 Lisp_Object best_entity;
2089 USE_SAFE_ALLOCA;
2090
2091 len = ASIZE (vec);
2092 if (len <= 1)
2093 return best_only ? AREF (vec, 0) : vec;
2094
2095 for (i = FONT_FOUNDRY_INDEX; i <= FONT_DPI_INDEX; i++)
2096 prefer_prop[i] = AREF (prefer, i);
2097
2098 if (! NILP (spec))
2099 {
2100 /* A font driver may return a font that has a property value
2101 different from the value specified in SPEC if the driver
2102 thinks they are the same. That happens, for instance, such a
2103 generic family name as "serif" is specified. So, to ignore
2104 such a difference, for all properties specified in SPEC, set
2105 the corresponding properties in PREFER_PROP to nil. */
2106 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2107 if (! NILP (AREF (spec, i)))
2108 prefer_prop[i] = Qnil;
2109 }
2110
2111 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2112 prefer_prop[FONT_SIZE_INDEX]
2113 = make_number (font_pixel_size (XFRAME (frame), prefer));
2114 if (! NILP (prefer_prop[FONT_FAMILY_INDEX]))
2115 {
2116 alternate_families
2117 = Fassoc_string (prefer_prop[FONT_FAMILY_INDEX],
2118 Vface_alternative_font_family_alist, Qt);
2119 if (CONSP (alternate_families))
2120 alternate_families = XCDR (alternate_families);
2121 }
2122
2123 /* Scoring and sorting. */
2124 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
2125 best_score = 0xFFFFFFFF;
2126 best_entity = Qnil;
2127 for (i = 0; i < len; i++)
2128 {
2129 data[i].entity = AREF (vec, i);
2130 data[i].score = font_score (data[i].entity, prefer_prop,
2131 alternate_families);
2132 if (best_only && best_score > data[i].score)
2133 {
2134 best_score = data[i].score;
2135 best_entity = data[i].entity;
2136 if (best_score == 0)
2137 break;
2138 }
2139 }
2140 if (NILP (best_entity))
2141 {
2142 qsort (data, len, sizeof *data, font_compare);
2143 for (i = 0; i < len; i++)
2144 ASET (vec, i, data[i].entity);
2145 }
2146 else
2147 vec = best_entity;
2148 SAFE_FREE ();
2149
2150 font_add_log ("sort-by", prefer, vec);
2151 return vec;
2152 }
2153
2154 \f
2155 /* API of Font Service Layer. */
2156
2157 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2158 sort_shift_bits. Finternal_set_font_selection_order calls this
2159 function with font_sort_order after setting up it. */
2160
2161 void
2162 font_update_sort_order (order)
2163 int *order;
2164 {
2165 int i, shift_bits;
2166
2167 for (i = 0, shift_bits = 21; i < 4; i++, shift_bits -= 7)
2168 {
2169 int xlfd_idx = order[i];
2170
2171 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2172 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2173 else if (xlfd_idx == XLFD_SLANT_INDEX)
2174 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2175 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2176 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2177 else
2178 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2179 }
2180 }
2181
2182
2183 /* Check if ENTITY matches with the font specification SPEC. */
2184
2185 int
2186 font_match_p (spec, entity)
2187 Lisp_Object spec, entity;
2188 {
2189 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2190 Lisp_Object alternate_families = Qnil;
2191 int i;
2192
2193 for (i = FONT_FOUNDRY_INDEX; i <= FONT_SIZE_INDEX; i++)
2194 prefer_prop[i] = AREF (spec, i);
2195 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2196 prefer_prop[FONT_SIZE_INDEX]
2197 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2198 if (! NILP (prefer_prop[FONT_FAMILY_INDEX]))
2199 {
2200 alternate_families
2201 = Fassoc_string (prefer_prop[FONT_FAMILY_INDEX],
2202 Vface_alternative_font_family_alist, Qt);
2203 if (CONSP (alternate_families))
2204 alternate_families = XCDR (alternate_families);
2205 }
2206
2207 return (font_score (entity, prefer_prop, alternate_families) == 0);
2208 }
2209
2210
2211 /* CHeck a lispy font object corresponding to FONT. */
2212
2213 int
2214 font_check_object (font)
2215 struct font *font;
2216 {
2217 Lisp_Object tail, elt;
2218
2219 for (tail = font->props[FONT_OBJLIST_INDEX]; CONSP (tail);
2220 tail = XCDR (tail))
2221 {
2222 elt = XCAR (tail);
2223 if (font == XFONT_OBJECT (elt))
2224 return 1;
2225 }
2226 return 0;
2227 }
2228
2229 \f
2230
2231 /* Font cache
2232
2233 Each font backend has the callback function get_cache, and it
2234 returns a cons cell of which cdr part can be freely used for
2235 caching fonts. The cons cell may be shared by multiple frames
2236 and/or multiple font drivers. So, we arrange the cdr part as this:
2237
2238 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2239
2240 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2241 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2242 cons (FONT-SPEC FONT-ENTITY ...). */
2243
2244 static void font_prepare_cache P_ ((FRAME_PTR, struct font_driver *));
2245 static void font_finish_cache P_ ((FRAME_PTR, struct font_driver *));
2246 static Lisp_Object font_get_cache P_ ((FRAME_PTR, struct font_driver *));
2247 static void font_clear_cache P_ ((FRAME_PTR, Lisp_Object,
2248 struct font_driver *));
2249
2250 static void
2251 font_prepare_cache (f, driver)
2252 FRAME_PTR f;
2253 struct font_driver *driver;
2254 {
2255 Lisp_Object cache, val;
2256
2257 cache = driver->get_cache (f);
2258 val = XCDR (cache);
2259 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2260 val = XCDR (val);
2261 if (NILP (val))
2262 {
2263 val = Fcons (driver->type, Fcons (make_number (1), Qnil));
2264 XSETCDR (cache, Fcons (val, XCDR (cache)));
2265 }
2266 else
2267 {
2268 val = XCDR (XCAR (val));
2269 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2270 }
2271 }
2272
2273
2274 static void
2275 font_finish_cache (f, driver)
2276 FRAME_PTR f;
2277 struct font_driver *driver;
2278 {
2279 Lisp_Object cache, val, tmp;
2280
2281
2282 cache = driver->get_cache (f);
2283 val = XCDR (cache);
2284 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2285 cache = val, val = XCDR (val);
2286 font_assert (! NILP (val));
2287 tmp = XCDR (XCAR (val));
2288 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2289 if (XINT (XCAR (tmp)) == 0)
2290 {
2291 font_clear_cache (f, XCAR (val), driver);
2292 XSETCDR (cache, XCDR (val));
2293 }
2294 }
2295
2296
2297 static Lisp_Object
2298 font_get_cache (f, driver)
2299 FRAME_PTR f;
2300 struct font_driver *driver;
2301 {
2302 Lisp_Object val = driver->get_cache (f);
2303 Lisp_Object type = driver->type;
2304
2305 font_assert (CONSP (val));
2306 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2307 font_assert (CONSP (val));
2308 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2309 val = XCDR (XCAR (val));
2310 return val;
2311 }
2312
2313 static int num_fonts;
2314
2315 static void
2316 font_clear_cache (f, cache, driver)
2317 FRAME_PTR f;
2318 Lisp_Object cache;
2319 struct font_driver *driver;
2320 {
2321 Lisp_Object tail, elt;
2322
2323 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2324 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2325 {
2326 elt = XCAR (tail);
2327 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)) && VECTORP (XCDR (elt)))
2328 {
2329 Lisp_Object vec = XCDR (elt);
2330 int i;
2331
2332 for (i = 0; i < ASIZE (vec); i++)
2333 {
2334 Lisp_Object entity = AREF (vec, i);
2335
2336 if (EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2337 {
2338 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2339
2340 for (; CONSP (objlist); objlist = XCDR (objlist))
2341 {
2342 Lisp_Object val = XCAR (objlist);
2343 struct font *font = XFONT_OBJECT (val);
2344
2345 font_assert (font && driver == font->driver);
2346 driver->close (f, font);
2347 num_fonts--;
2348 }
2349 if (driver->free_entity)
2350 driver->free_entity (entity);
2351 }
2352 }
2353 }
2354 }
2355 XSETCDR (cache, Qnil);
2356 }
2357 \f
2358
2359 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2360
2361 Lisp_Object
2362 font_delete_unmatched (list, spec, size)
2363 Lisp_Object list, spec;
2364 int size;
2365 {
2366 Lisp_Object entity, val;
2367 enum font_property_index prop;
2368
2369 for (val = Qnil; CONSP (list); list = XCDR (list))
2370 {
2371 entity = XCAR (list);
2372 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++)
2373 if (INTEGERP (AREF (spec, prop))
2374 && ((XINT (AREF (spec, prop)) >> 8)
2375 != (XINT (AREF (entity, prop)) >> 8)))
2376 prop = FONT_SPEC_MAX;
2377 if (prop++ <= FONT_SIZE_INDEX
2378 && size
2379 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2380 {
2381 int diff = XINT (AREF (entity, FONT_SIZE_INDEX)) - size;
2382
2383 if (diff != 0
2384 && (diff < 0 ? -diff > FONT_PIXEL_SIZE_QUANTUM
2385 : diff > FONT_PIXEL_SIZE_QUANTUM))
2386 prop = FONT_SPEC_MAX;
2387 }
2388 if (prop < FONT_SPEC_MAX)
2389 val = Fcons (entity, val);
2390 }
2391 return val;
2392 }
2393
2394
2395 /* Return a vector of font-entities matching with SPEC on FRAME. */
2396
2397 Lisp_Object
2398 font_list_entities (frame, spec)
2399 Lisp_Object frame, spec;
2400 {
2401 FRAME_PTR f = XFRAME (frame);
2402 struct font_driver_list *driver_list = f->font_driver_list;
2403 Lisp_Object ftype, family, alternate_familes, val;
2404 Lisp_Object *vec;
2405 int size;
2406 int need_filtering = 0;
2407 int n_family = 1;
2408 int i;
2409
2410 font_assert (FONT_SPEC_P (spec));
2411
2412 family = AREF (spec, FONT_FAMILY_INDEX);
2413 if (NILP (family))
2414 alternate_familes = Qnil;
2415 else
2416 {
2417 alternate_familes = Fassoc_string (family,
2418 Vface_alternative_font_family_alist,
2419 Qt);
2420 if (! NILP (alternate_familes))
2421 alternate_familes = XCDR (alternate_familes);
2422 n_family += XINT (Flength (alternate_familes));
2423 }
2424
2425 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2426 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2427 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2428 size = font_pixel_size (f, spec);
2429 else
2430 size = 0;
2431
2432 ftype = AREF (spec, FONT_TYPE_INDEX);
2433 for (i = 1; i <= FONT_REGISTRY_INDEX; i++)
2434 ASET (scratch_font_spec, i, AREF (spec, i));
2435 for (i = FONT_DPI_INDEX; i < FONT_EXTRA_INDEX; i += 2)
2436 {
2437 ASET (scratch_font_spec, i, Qnil);
2438 if (! NILP (AREF (spec, i)))
2439 need_filtering = 1;
2440 }
2441 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX));
2442 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
2443
2444 vec = alloca (sizeof (Lisp_Object) * num_font_drivers * n_family);
2445 if (! vec)
2446 return null_vector;
2447
2448 for (i = 0; driver_list; driver_list = driver_list->next)
2449 if (driver_list->on
2450 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2451 {
2452 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2453 Lisp_Object tail = alternate_familes;
2454
2455 ASET (scratch_font_spec, FONT_TYPE_INDEX, driver_list->driver->type);
2456 ASET (scratch_font_spec, FONT_FAMILY_INDEX, family);
2457 while (1)
2458 {
2459 val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2460 if (CONSP (val))
2461 val = XCDR (val);
2462 else
2463 {
2464 Lisp_Object copy;
2465
2466 val = driver_list->driver->list (frame, scratch_font_spec);
2467 copy = Fcopy_font_spec (scratch_font_spec);
2468 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2469 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2470 }
2471 if (! NILP (val) && need_filtering)
2472 val = font_delete_unmatched (val, spec, size);
2473 if (! NILP (val))
2474 {
2475 vec[i++] = val;
2476 break;
2477 }
2478 if (NILP (tail))
2479 break;
2480 ASET (scratch_font_spec, FONT_FAMILY_INDEX,
2481 Fintern (XCAR (tail), Qnil));
2482 tail = XCDR (tail);
2483 }
2484 }
2485
2486 val = (i > 0 ? Fvconcat (i, vec) : null_vector);
2487 font_add_log ("list", spec, val);
2488 return (val);
2489 }
2490
2491
2492 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2493 nil, is an array of face's attributes, which specifies preferred
2494 font-related attributes. */
2495
2496 static Lisp_Object
2497 font_matching_entity (f, attrs, spec)
2498 FRAME_PTR f;
2499 Lisp_Object *attrs, spec;
2500 {
2501 struct font_driver_list *driver_list = f->font_driver_list;
2502 Lisp_Object ftype, size, entity;
2503 Lisp_Object frame;
2504
2505 XSETFRAME (frame, f);
2506 ftype = AREF (spec, FONT_TYPE_INDEX);
2507 size = AREF (spec, FONT_SIZE_INDEX);
2508 if (FLOATP (size))
2509 ASET (spec, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2510 entity = Qnil;
2511 for (; driver_list; driver_list = driver_list->next)
2512 if (driver_list->on
2513 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2514 {
2515 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2516 Lisp_Object copy;
2517
2518 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2519 entity = assoc_no_quit (spec, XCDR (cache));
2520 if (CONSP (entity))
2521 entity = XCDR (entity);
2522 else
2523 {
2524 entity = driver_list->driver->match (frame, spec);
2525 copy = Fcopy_font_spec (spec);
2526 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2527 XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache)));
2528 }
2529 if (! NILP (entity))
2530 break;
2531 }
2532 ASET (spec, FONT_TYPE_INDEX, ftype);
2533 ASET (spec, FONT_SIZE_INDEX, size);
2534 font_add_log ("match", spec, entity);
2535 return entity;
2536 }
2537
2538
2539 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2540 opened font object. */
2541
2542 static Lisp_Object
2543 font_open_entity (f, entity, pixel_size)
2544 FRAME_PTR f;
2545 Lisp_Object entity;
2546 int pixel_size;
2547 {
2548 struct font_driver_list *driver_list;
2549 Lisp_Object objlist, size, val, font_object;
2550 struct font *font;
2551 int min_width;
2552
2553 font_assert (FONT_ENTITY_P (entity));
2554 size = AREF (entity, FONT_SIZE_INDEX);
2555 if (XINT (size) != 0)
2556 pixel_size = XINT (size);
2557
2558 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2559 objlist = XCDR (objlist))
2560 if (XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size)
2561 return XCAR (objlist);
2562
2563 val = AREF (entity, FONT_TYPE_INDEX);
2564 for (driver_list = f->font_driver_list;
2565 driver_list && ! EQ (driver_list->driver->type, val);
2566 driver_list = driver_list->next);
2567 if (! driver_list)
2568 return Qnil;
2569
2570 font_object = driver_list->driver->open (f, entity, pixel_size);
2571 font_add_log ("open", entity, font_object);
2572 if (NILP (font_object))
2573 return Qnil;
2574 ASET (entity, FONT_OBJLIST_INDEX,
2575 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2576 ASET (font_object, FONT_OBJLIST_INDEX, AREF (entity, FONT_OBJLIST_INDEX));
2577 num_fonts++;
2578
2579 font = XFONT_OBJECT (font_object);
2580 min_width = (font->min_width ? font->min_width
2581 : font->average_width ? font->average_width
2582 : font->space_width ? font->space_width
2583 : 1);
2584 #ifdef HAVE_WINDOW_SYSTEM
2585 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
2586 if (FRAME_X_DISPLAY_INFO (f)->n_fonts == 1)
2587 {
2588 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
2589 FRAME_SMALLEST_FONT_HEIGHT (f) = font->height;
2590 fonts_changed_p = 1;
2591 }
2592 else
2593 {
2594 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
2595 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
2596 if (FRAME_SMALLEST_FONT_HEIGHT (f) > font->height)
2597 FRAME_SMALLEST_FONT_HEIGHT (f) = font->height, fonts_changed_p = 1;
2598 }
2599 #endif
2600
2601 return font_object;
2602 }
2603
2604
2605 /* Close FONT_OBJECT that is opened on frame F. */
2606
2607 void
2608 font_close_object (f, font_object)
2609 FRAME_PTR f;
2610 Lisp_Object font_object;
2611 {
2612 struct font *font = XFONT_OBJECT (font_object);
2613 Lisp_Object objlist;
2614 Lisp_Object tail, prev = Qnil;
2615
2616 objlist = AREF (font_object, FONT_OBJLIST_INDEX);
2617 for (prev = Qnil, tail = objlist; CONSP (tail);
2618 prev = tail, tail = XCDR (tail))
2619 if (EQ (font_object, XCAR (tail)))
2620 {
2621 font_add_log ("close", font_object, Qnil);
2622 font->driver->close (f, font);
2623 #ifdef HAVE_WINDOW_SYSTEM
2624 font_assert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
2625 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
2626 #endif
2627 if (NILP (prev))
2628 ASET (font_object, FONT_OBJLIST_INDEX, XCDR (objlist));
2629 else
2630 XSETCDR (prev, XCDR (objlist));
2631 num_fonts--;
2632 return;
2633 }
2634 abort ();
2635 }
2636
2637
2638 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2639 FONT is a font-entity and it must be opened to check. */
2640
2641 int
2642 font_has_char (f, font, c)
2643 FRAME_PTR f;
2644 Lisp_Object font;
2645 int c;
2646 {
2647 struct font *fontp;
2648
2649 if (FONT_ENTITY_P (font))
2650 {
2651 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
2652 struct font_driver_list *driver_list;
2653
2654 for (driver_list = f->font_driver_list;
2655 driver_list && ! EQ (driver_list->driver->type, type);
2656 driver_list = driver_list->next);
2657 if (! driver_list)
2658 return 0;
2659 if (! driver_list->driver->has_char)
2660 return -1;
2661 return driver_list->driver->has_char (font, c);
2662 }
2663
2664 font_assert (FONT_OBJECT_P (font));
2665 fontp = XFONT_OBJECT (font);
2666 if (fontp->driver->has_char)
2667 {
2668 int result = fontp->driver->has_char (font, c);
2669
2670 if (result >= 0)
2671 return result;
2672 }
2673 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
2674 }
2675
2676
2677 /* Return the glyph ID of FONT_OBJECT for character C. */
2678
2679 unsigned
2680 font_encode_char (font_object, c)
2681 Lisp_Object font_object;
2682 int c;
2683 {
2684 struct font *font;
2685
2686 font_assert (FONT_OBJECT_P (font_object));
2687 font = XFONT_OBJECT (font_object);
2688 return font->driver->encode_char (font, c);
2689 }
2690
2691
2692 /* Return the name of FONT_OBJECT. */
2693
2694 Lisp_Object
2695 font_get_name (font_object)
2696 Lisp_Object font_object;
2697 {
2698 font_assert (FONT_OBJECT_P (font_object));
2699 return AREF (font_object, FONT_NAME_INDEX);
2700 }
2701
2702
2703 /* Return the specification of FONT_OBJECT. */
2704
2705 Lisp_Object
2706 font_get_spec (font_object)
2707 Lisp_Object font_object;
2708 {
2709 Lisp_Object spec = font_make_spec ();
2710 int i;
2711
2712 for (i = 0; i < FONT_SIZE_INDEX; i++)
2713 ASET (spec, i, AREF (font_object, i));
2714 ASET (spec, FONT_SIZE_INDEX,
2715 make_number (XFONT_OBJECT (font_object)->pixel_size));
2716 return spec;
2717 }
2718
2719 Lisp_Object
2720 font_spec_from_name (font_name)
2721 Lisp_Object font_name;
2722 {
2723 Lisp_Object args[2];
2724
2725 args[0] = QCname;
2726 args[1] = font_name;
2727 return Ffont_spec (2, args);
2728 }
2729
2730
2731 void
2732 font_clear_prop (attrs, prop)
2733 Lisp_Object *attrs;
2734 enum font_property_index prop;
2735 {
2736 Lisp_Object font = attrs[LFACE_FONT_INDEX];
2737
2738 if (! FONTP (font))
2739 return;
2740 if (NILP (AREF (font, prop))
2741 && prop != FONT_FAMILY_INDEX && prop != FONT_FAMILY_INDEX)
2742 return;
2743 font = Fcopy_font_spec (font);
2744 ASET (font, prop, Qnil);
2745 if (prop == FONT_FAMILY_INDEX)
2746 {
2747 ASET (font, FONT_FOUNDRY_INDEX, Qnil);
2748 ASET (font, FONT_ADSTYLE_INDEX, Qnil);
2749 ASET (font, FONT_SIZE_INDEX, Qnil);
2750 ASET (font, FONT_DPI_INDEX, Qnil);
2751 ASET (font, FONT_SPACING_INDEX, Qnil);
2752 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
2753 }
2754 else if (prop == FONT_SIZE_INDEX)
2755 {
2756 ASET (font, FONT_DPI_INDEX, Qnil);
2757 ASET (font, FONT_SPACING_INDEX, Qnil);
2758 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
2759 }
2760 attrs[LFACE_FONT_INDEX] = font;
2761 }
2762
2763 void
2764 font_update_lface (f, attrs)
2765 FRAME_PTR f;
2766 Lisp_Object *attrs;
2767 {
2768 Lisp_Object spec;
2769
2770 spec = attrs[LFACE_FONT_INDEX];
2771 if (! FONT_SPEC_P (spec))
2772 return;
2773
2774 if (! NILP (AREF (spec, FONT_FOUNDRY_INDEX))
2775 || ! NILP (AREF (spec, FONT_FAMILY_INDEX)))
2776 {
2777 Lisp_Object family;
2778
2779 if (NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
2780 family = AREF (spec, FONT_FAMILY_INDEX);
2781 else if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
2782 family = concat2 (SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX)),
2783 build_string ("-*"));
2784 else
2785 family = concat3 (SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX)),
2786 build_string ("-"),
2787 SYMBOL_NAME (AREF (spec, FONT_FAMILY_INDEX)));
2788 attrs[LFACE_FAMILY_INDEX] = family;
2789 }
2790 if (! NILP (AREF (spec, FONT_WEIGHT_INDEX)))
2791 attrs[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (spec);
2792 if (! NILP (AREF (spec, FONT_SLANT_INDEX)))
2793 attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);;
2794 if (! NILP (AREF (spec, FONT_WIDTH_INDEX)))
2795 attrs[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (spec);
2796 if (! NILP (AREF (spec, FONT_SIZE_INDEX)))
2797 {
2798 int point;
2799
2800 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2801 {
2802 Lisp_Object val;
2803 int dpi = f->resy;
2804
2805 val = Ffont_get (spec, QCdpi);
2806 if (! NILP (val))
2807 dpi = XINT (val);
2808 point = PIXEL_TO_POINT (XINT (AREF (spec, FONT_SIZE_INDEX)) * 10,
2809 dpi);
2810 }
2811 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2812 point = XFLOAT_DATA (AREF (spec, FONT_SIZE_INDEX)) * 10;
2813 attrs[LFACE_HEIGHT_INDEX] = make_number (point);
2814 }
2815 }
2816
2817
2818 /* Return a font-entity satisfying SPEC and best matching with face's
2819 font related attributes in ATTRS. C, if not negative, is a
2820 character that the entity must support. */
2821
2822 Lisp_Object
2823 font_find_for_lface (f, attrs, spec, c)
2824 FRAME_PTR f;
2825 Lisp_Object *attrs;
2826 Lisp_Object spec;
2827 int c;
2828 {
2829 Lisp_Object frame, entities, val, props[FONT_REGISTRY_INDEX + 1] ;
2830 Lisp_Object size;
2831 int pixel_size;
2832 int i, result;
2833
2834 if (c >= 0)
2835 {
2836 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
2837 struct charset *encoding, *repertory;
2838
2839 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
2840 return Qnil;
2841 if (repertory)
2842 {
2843 if (ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
2844 return Qnil;
2845 /* Any font of this registry support C. So, let's
2846 suppress the further checking. */
2847 c = -1;
2848 }
2849 else if (c > encoding->max_char)
2850 return Qnil;
2851 }
2852
2853 XSETFRAME (frame, f);
2854 size = AREF (spec, FONT_SIZE_INDEX);
2855 pixel_size = font_pixel_size (f, spec);
2856 if (pixel_size == 0)
2857 {
2858 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
2859
2860 pixel_size = POINT_TO_PIXEL (pt / 10, f->resy);
2861 }
2862 ASET (spec, FONT_SIZE_INDEX, Qnil);
2863 entities = font_list_entities (frame, spec);
2864 ASET (spec, FONT_SIZE_INDEX, size);
2865 if (ASIZE (entities) == 0)
2866 return Qnil;
2867 if (ASIZE (entities) == 1)
2868 {
2869 if (c < 0)
2870 return AREF (entities, 0);
2871 }
2872 else
2873 {
2874 /* Sort fonts by properties specified in LFACE. */
2875 Lisp_Object prefer = scratch_font_prefer;
2876
2877 for (i = 0; i < FONT_EXTRA_INDEX; i++)
2878 ASET (prefer, i, AREF (spec, i));
2879 if (FONTP (attrs[LFACE_FONT_INDEX]))
2880 {
2881 Lisp_Object face_font = attrs[LFACE_FONT_INDEX];
2882
2883 for (i = 0; i < FONT_EXTRA_INDEX; i++)
2884 if (NILP (AREF (prefer, i)))
2885 ASET (prefer, i, AREF (face_font, i));
2886 }
2887 if (NILP (AREF (prefer, FONT_FAMILY_INDEX)))
2888 font_parse_family_registry (attrs[LFACE_FAMILY_INDEX], Qnil, prefer);
2889 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
2890 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
2891 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
2892 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
2893 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
2894 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
2895 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
2896 ASET (spec, FONT_SIZE_INDEX, Qnil);
2897 entities = font_sort_entites (entities, prefer, frame, spec, c < 0);
2898 ASET (spec, FONT_SIZE_INDEX, size);
2899 }
2900 if (c < 0)
2901 return entities;
2902
2903 for (i = 0; i < ASIZE (entities); i++)
2904 {
2905 int j;
2906
2907 val = AREF (entities, i);
2908 if (i > 0)
2909 {
2910 for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
2911 if (! EQ (AREF (val, j), props[j]))
2912 break;
2913 if (j > FONT_REGISTRY_INDEX)
2914 continue;
2915 }
2916 for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
2917 props[j] = AREF (val, j);
2918 result = font_has_char (f, val, c);
2919 if (result > 0)
2920 return val;
2921 if (result == 0)
2922 return Qnil;
2923 val = font_open_for_lface (f, val, attrs, spec);
2924 if (NILP (val))
2925 continue;
2926 result = font_has_char (f, val, c);
2927 font_close_object (f, val);
2928 if (result > 0)
2929 return AREF (entities, i);
2930 }
2931 return Qnil;
2932 }
2933
2934
2935 Lisp_Object
2936 font_open_for_lface (f, entity, attrs, spec)
2937 FRAME_PTR f;
2938 Lisp_Object entity;
2939 Lisp_Object *attrs;
2940 Lisp_Object spec;
2941 {
2942 int size;
2943
2944 if (FONT_SPEC_P (spec) && ! NILP (AREF (spec, FONT_SIZE_INDEX)))
2945 size = font_pixel_size (f, spec);
2946 else
2947 {
2948 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
2949
2950 pt /= 10;
2951 size = POINT_TO_PIXEL (pt, f->resy);
2952 }
2953 return font_open_entity (f, entity, size);
2954 }
2955
2956
2957 /* Find a font satisfying SPEC and best matching with face's
2958 attributes in ATTRS on FRAME, and return the opened
2959 font-object. */
2960
2961 Lisp_Object
2962 font_load_for_lface (f, attrs, spec)
2963 FRAME_PTR f;
2964 Lisp_Object *attrs, spec;
2965 {
2966 Lisp_Object entity;
2967
2968 entity = font_find_for_lface (f, attrs, spec, -1);
2969 if (NILP (entity))
2970 {
2971 /* No font is listed for SPEC, but each font-backend may have
2972 the different criteria about "font matching". So, try
2973 it. */
2974 entity = font_matching_entity (f, attrs, spec);
2975 if (NILP (entity))
2976 return Qnil;
2977 }
2978 return font_open_for_lface (f, entity, attrs, spec);
2979 }
2980
2981
2982 /* Make FACE on frame F ready to use the font opened for FACE. */
2983
2984 void
2985 font_prepare_for_face (f, face)
2986 FRAME_PTR f;
2987 struct face *face;
2988 {
2989 if (face->font->driver->prepare_face)
2990 face->font->driver->prepare_face (f, face);
2991 }
2992
2993
2994 /* Make FACE on frame F stop using the font opened for FACE. */
2995
2996 void
2997 font_done_for_face (f, face)
2998 FRAME_PTR f;
2999 struct face *face;
3000 {
3001 if (face->font->driver->done_face)
3002 face->font->driver->done_face (f, face);
3003 face->extra = NULL;
3004 }
3005
3006
3007 /* Open a font best matching with NAME on frame F. If no proper font
3008 is found, return Qnil. */
3009
3010 Lisp_Object
3011 font_open_by_name (f, name)
3012 FRAME_PTR f;
3013 char *name;
3014 {
3015 Lisp_Object args[2];
3016 Lisp_Object spec, prefer, size, registry, entity, entity_list;
3017 Lisp_Object frame;
3018 int i;
3019 int pixel_size;
3020
3021 XSETFRAME (frame, f);
3022
3023 args[0] = QCname;
3024 args[1] = make_unibyte_string (name, strlen (name));
3025 spec = Ffont_spec (2, args);
3026 prefer = scratch_font_prefer;
3027 for (i = 0; i < FONT_SPEC_MAX; i++)
3028 {
3029 ASET (prefer, i, AREF (spec, i));
3030 if (NILP (AREF (prefer, i))
3031 && i >= FONT_WEIGHT_INDEX && i <= FONT_WIDTH_INDEX)
3032 FONT_SET_STYLE (prefer, i, make_number (100));
3033 }
3034 size = AREF (spec, FONT_SIZE_INDEX);
3035 if (NILP (size))
3036 pixel_size = 0;
3037 else
3038 {
3039 if (INTEGERP (size))
3040 pixel_size = XINT (size);
3041 else /* FLOATP (size) */
3042 {
3043 double pt = XFLOAT_DATA (size);
3044
3045 pixel_size = POINT_TO_PIXEL (pt, f->resy);
3046 }
3047 if (pixel_size == 0)
3048 ASET (spec, FONT_SIZE_INDEX, Qnil);
3049 }
3050 if (pixel_size == 0)
3051 {
3052 pixel_size = POINT_TO_PIXEL (12.0, f->resy);
3053 size = make_number (pixel_size);
3054 ASET (prefer, FONT_SIZE_INDEX, size);
3055 }
3056 registry = AREF (spec, FONT_REGISTRY_INDEX);
3057 if (NILP (registry))
3058 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
3059 entity_list = Flist_fonts (spec, frame, make_number (1), prefer);
3060 if (NILP (entity_list) && NILP (registry))
3061 {
3062 ASET (spec, FONT_REGISTRY_INDEX, Qascii_0);
3063 entity_list = Flist_fonts (spec, frame, make_number (1), prefer);
3064 }
3065 ASET (spec, FONT_REGISTRY_INDEX, registry);
3066 if (NILP (entity_list))
3067 entity = font_matching_entity (f, NULL, spec);
3068 else
3069 entity = XCAR (entity_list);
3070 return (NILP (entity)
3071 ? Qnil
3072 : font_open_entity (f, entity, pixel_size));
3073 }
3074
3075
3076 /* Register font-driver DRIVER. This function is used in two ways.
3077
3078 The first is with frame F non-NULL. In this case, make DRIVER
3079 available (but not yet activated) on F. All frame creaters
3080 (e.g. Fx_create_frame) must call this function at least once with
3081 an available font-driver.
3082
3083 The second is with frame F NULL. In this case, DRIVER is globally
3084 registered in the variable `font_driver_list'. All font-driver
3085 implementations must call this function in its syms_of_XXXX
3086 (e.g. syms_of_xfont). */
3087
3088 void
3089 register_font_driver (driver, f)
3090 struct font_driver *driver;
3091 FRAME_PTR f;
3092 {
3093 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
3094 struct font_driver_list *prev, *list;
3095
3096 if (f && ! driver->draw)
3097 error ("Unusable font driver for a frame: %s",
3098 SDATA (SYMBOL_NAME (driver->type)));
3099
3100 for (prev = NULL, list = root; list; prev = list, list = list->next)
3101 if (EQ (list->driver->type, driver->type))
3102 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3103
3104 list = malloc (sizeof (struct font_driver_list));
3105 list->on = 0;
3106 list->driver = driver;
3107 list->next = NULL;
3108 if (prev)
3109 prev->next = list;
3110 else if (f)
3111 f->font_driver_list = list;
3112 else
3113 font_driver_list = list;
3114 if (! f)
3115 num_font_drivers++;
3116 }
3117
3118
3119 /* Free font-driver list on frame F. It doesn't free font-drivers
3120 themselves. */
3121
3122 void
3123 free_font_driver_list (f)
3124 FRAME_PTR f;
3125 {
3126 while (f->font_driver_list)
3127 {
3128 struct font_driver_list *next = f->font_driver_list->next;
3129
3130 free (f->font_driver_list);
3131 f->font_driver_list = next;
3132 }
3133 }
3134
3135
3136 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3137 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3138 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3139
3140 A caller must free all realized faces if any in advance. The
3141 return value is a list of font backends actually made used on
3142 F. */
3143
3144 Lisp_Object
3145 font_update_drivers (f, new_drivers)
3146 FRAME_PTR f;
3147 Lisp_Object new_drivers;
3148 {
3149 Lisp_Object active_drivers = Qnil;
3150 struct font_driver_list *list;
3151
3152 for (list = f->font_driver_list; list; list = list->next)
3153 if (list->on)
3154 {
3155 if (! EQ (new_drivers, Qt)
3156 && NILP (Fmemq (list->driver->type, new_drivers)))
3157 {
3158 if (list->driver->end_for_frame)
3159 list->driver->end_for_frame (f);
3160 font_finish_cache (f, list->driver);
3161 list->on = 0;
3162 }
3163 }
3164 else
3165 {
3166 if (EQ (new_drivers, Qt)
3167 || ! NILP (Fmemq (list->driver->type, new_drivers)))
3168 {
3169 if (! list->driver->start_for_frame
3170 || list->driver->start_for_frame (f) == 0)
3171 {
3172 font_prepare_cache (f, list->driver);
3173 list->on = 1;
3174 active_drivers = nconc2 (active_drivers,
3175 Fcons (list->driver->type, Qnil));
3176 }
3177 }
3178 }
3179
3180 return active_drivers;
3181 }
3182
3183 int
3184 font_put_frame_data (f, driver, data)
3185 FRAME_PTR f;
3186 struct font_driver *driver;
3187 void *data;
3188 {
3189 struct font_data_list *list, *prev;
3190
3191 for (prev = NULL, list = f->font_data_list; list;
3192 prev = list, list = list->next)
3193 if (list->driver == driver)
3194 break;
3195 if (! data)
3196 {
3197 if (list)
3198 {
3199 if (prev)
3200 prev->next = list->next;
3201 else
3202 f->font_data_list = list->next;
3203 free (list);
3204 }
3205 return 0;
3206 }
3207
3208 if (! list)
3209 {
3210 list = malloc (sizeof (struct font_data_list));
3211 if (! list)
3212 return -1;
3213 list->driver = driver;
3214 list->next = f->font_data_list;
3215 f->font_data_list = list;
3216 }
3217 list->data = data;
3218 return 0;
3219 }
3220
3221
3222 void *
3223 font_get_frame_data (f, driver)
3224 FRAME_PTR f;
3225 struct font_driver *driver;
3226 {
3227 struct font_data_list *list;
3228
3229 for (list = f->font_data_list; list; list = list->next)
3230 if (list->driver == driver)
3231 break;
3232 if (! list)
3233 return NULL;
3234 return list->data;
3235 }
3236
3237
3238 /* Return the font used to draw character C by FACE at buffer position
3239 POS in window W. If STRING is non-nil, it is a string containing C
3240 at index POS. If C is negative, get C from the current buffer or
3241 STRING. */
3242
3243 Lisp_Object
3244 font_at (c, pos, face, w, string)
3245 int c;
3246 EMACS_INT pos;
3247 struct face *face;
3248 struct window *w;
3249 Lisp_Object string;
3250 {
3251 FRAME_PTR f;
3252 int multibyte;
3253 Lisp_Object font_object;
3254
3255 if (c < 0)
3256 {
3257 if (NILP (string))
3258 {
3259 multibyte = ! NILP (current_buffer->enable_multibyte_characters);
3260 if (multibyte)
3261 {
3262 EMACS_INT pos_byte = CHAR_TO_BYTE (pos);
3263
3264 c = FETCH_CHAR (pos_byte);
3265 }
3266 else
3267 c = FETCH_BYTE (pos);
3268 }
3269 else
3270 {
3271 unsigned char *str;
3272
3273 multibyte = STRING_MULTIBYTE (string);
3274 if (multibyte)
3275 {
3276 EMACS_INT pos_byte = string_char_to_byte (string, pos);
3277
3278 str = SDATA (string) + pos_byte;
3279 c = STRING_CHAR (str, 0);
3280 }
3281 else
3282 c = SDATA (string)[pos];
3283 }
3284 }
3285
3286 f = XFRAME (w->frame);
3287 if (! FRAME_WINDOW_P (f))
3288 return Qnil;
3289 if (! face)
3290 {
3291 int face_id;
3292 EMACS_INT endptr;
3293
3294 if (STRINGP (string))
3295 face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
3296 DEFAULT_FACE_ID, 0);
3297 else
3298 face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
3299 pos + 100, 0);
3300 face = FACE_FROM_ID (f, face_id);
3301 }
3302 if (multibyte)
3303 {
3304 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3305 face = FACE_FROM_ID (f, face_id);
3306 }
3307 if (! face->font)
3308 return Qnil;
3309
3310 font_assert (font_check_object ((struct font *) face->font));
3311 XSETFONT (font_object, face->font);
3312 return font_object;
3313 }
3314
3315
3316 /* Check how many characters after POS (at most to LIMIT) can be
3317 displayed by the same font. FACE is the face selected for the
3318 character as POS on frame F. STRING, if not nil, is the string to
3319 check instead of the current buffer.
3320
3321 The return value is the position of the character that is displayed
3322 by the differnt font than that of the character as POS. */
3323
3324 EMACS_INT
3325 font_range (pos, limit, face, f, string)
3326 EMACS_INT pos, limit;
3327 struct face *face;
3328 FRAME_PTR f;
3329 Lisp_Object string;
3330 {
3331 int multibyte;
3332 EMACS_INT pos_byte;
3333 int c;
3334 struct font *font;
3335 int first = 1;
3336
3337 if (NILP (string))
3338 {
3339 multibyte = ! NILP (current_buffer->enable_multibyte_characters);
3340 pos_byte = CHAR_TO_BYTE (pos);
3341 }
3342 else
3343 {
3344 multibyte = STRING_MULTIBYTE (string);
3345 pos_byte = string_char_to_byte (string, pos);
3346 }
3347
3348 if (! multibyte)
3349 /* All unibyte character are displayed by the same font. */
3350 return limit;
3351
3352 while (pos < limit)
3353 {
3354 int face_id;
3355
3356 if (NILP (string))
3357 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3358 else
3359 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3360 face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3361 face = FACE_FROM_ID (f, face_id);
3362 if (first)
3363 {
3364 font = face->font;
3365 first = 0;
3366 continue;
3367 }
3368 else if (font != face->font)
3369 {
3370 pos--;
3371 break;
3372 }
3373 }
3374 return pos;
3375 }
3376
3377 \f
3378 /* Lisp API */
3379
3380 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3381 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3382 Return nil otherwise.
3383 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3384 which kind of font it is. It must be one of `font-spec', `font-entity',
3385 `font-object'. */)
3386 (object, extra_type)
3387 Lisp_Object object, extra_type;
3388 {
3389 if (NILP (extra_type))
3390 return (FONTP (object) ? Qt : Qnil);
3391 if (EQ (extra_type, Qfont_spec))
3392 return (FONT_SPEC_P (object) ? Qt : Qnil);
3393 if (EQ (extra_type, Qfont_entity))
3394 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3395 if (EQ (extra_type, Qfont_object))
3396 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3397 wrong_type_argument (intern ("font-extra-type"), extra_type);
3398 }
3399
3400 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3401 doc: /* Return a newly created font-spec with arguments as properties.
3402
3403 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3404 valid font property name listed below:
3405
3406 `:family', `:weight', `:slant', `:width'
3407
3408 They are the same as face attributes of the same name. See
3409 `set-face-attribute'.
3410
3411 `:foundry'
3412
3413 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3414
3415 `:adstyle'
3416
3417 VALUE must be a string or a symbol specifying the additional
3418 typographic style information of a font, e.g. ``sans''.
3419
3420 `:registry'
3421
3422 VALUE must be a string or a symbol specifying the charset registry and
3423 encoding of a font, e.g. ``iso8859-1''.
3424
3425 `:size'
3426
3427 VALUE must be a non-negative integer or a floating point number
3428 specifying the font size. It specifies the font size in pixels
3429 (if VALUE is an integer), or in points (if VALUE is a float).
3430 usage: (font-spec ARGS ...) */)
3431 (nargs, args)
3432 int nargs;
3433 Lisp_Object *args;
3434 {
3435 Lisp_Object spec = font_make_spec ();
3436 int i;
3437
3438 for (i = 0; i < nargs; i += 2)
3439 {
3440 Lisp_Object key = args[i], val = args[i + 1];
3441
3442 if (EQ (key, QCname))
3443 {
3444 CHECK_STRING (val);
3445 font_parse_name ((char *) SDATA (val), spec);
3446 font_put_extra (spec, key, val);
3447 }
3448 else
3449 {
3450 int idx = get_font_prop_index (key);
3451
3452 if (idx >= 0)
3453 {
3454 val = font_prop_validate (idx, Qnil, val);
3455 if (idx < FONT_EXTRA_INDEX)
3456 ASET (spec, idx, val);
3457 else
3458 font_put_extra (spec, key, val);
3459 }
3460 else
3461 font_put_extra (spec, key, font_prop_validate (0, key, val));
3462 }
3463 }
3464 return spec;
3465 }
3466
3467 DEFUN ("copy-font-spec", Fcopy_font_spec, Scopy_font_spec, 1, 1, 0,
3468 doc: /* Return a copy of FONT as a font-spec. */)
3469 (font)
3470 Lisp_Object font;
3471 {
3472 Lisp_Object new_spec, tail, extra;
3473 int i;
3474
3475 CHECK_FONT (font);
3476 new_spec = font_make_spec ();
3477 for (i = 1; i < FONT_EXTRA_INDEX; i++)
3478 ASET (new_spec, i, AREF (font, i));
3479 extra = Qnil;
3480 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3481 {
3482 if (! EQ (XCAR (XCAR (tail)), QCfont_entity))
3483 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
3484 }
3485 ASET (new_spec, FONT_EXTRA_INDEX, extra);
3486 return new_spec;
3487 }
3488
3489 DEFUN ("merge-font-spec", Fmerge_font_spec, Smerge_font_spec, 2, 2, 0,
3490 doc: /* Merge font-specs FROM and TO, and return a new font-spec.
3491 Every specified properties in FROM override the corresponding
3492 properties in TO. */)
3493 (from, to)
3494 Lisp_Object from, to;
3495 {
3496 Lisp_Object extra, tail;
3497 int i;
3498
3499 CHECK_FONT (from);
3500 CHECK_FONT (to);
3501 to = Fcopy_font_spec (to);
3502 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3503 ASET (to, i, AREF (from, i));
3504 extra = AREF (to, FONT_EXTRA_INDEX);
3505 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3506 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
3507 {
3508 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
3509
3510 if (! NILP (slot))
3511 XSETCDR (slot, XCDR (XCAR (tail)));
3512 else
3513 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
3514 }
3515 ASET (to, FONT_EXTRA_INDEX, extra);
3516 return to;
3517 }
3518
3519 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
3520 doc: /* Return the value of FONT's property KEY.
3521 FONT is a font-spec, a font-entity, or a font-object. */)
3522 (font, key)
3523 Lisp_Object font, key;
3524 {
3525 int idx;
3526
3527 CHECK_FONT (font);
3528 CHECK_SYMBOL (key);
3529
3530 idx = get_font_prop_index (key);
3531 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3532 return AREF (font, idx);
3533 return Fcdr (Fassq (key, AREF (font, FONT_EXTRA_INDEX)));
3534 }
3535
3536
3537 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
3538 doc: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
3539 (font_spec, prop, val)
3540 Lisp_Object font_spec, prop, val;
3541 {
3542 int idx;
3543
3544 CHECK_FONT_SPEC (font_spec);
3545 idx = get_font_prop_index (prop);
3546 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3547 ASET (font_spec, idx, font_prop_validate (idx, Qnil, val));
3548 else
3549 font_put_extra (font_spec, prop, font_prop_validate (0, prop, val));
3550 return val;
3551 }
3552
3553 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
3554 doc: /* List available fonts matching FONT-SPEC on the current frame.
3555 Optional 2nd argument FRAME specifies the target frame.
3556 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
3557 Optional 4th argument PREFER, if non-nil, is a font-spec to
3558 control the order of the returned list. Fonts are sorted by
3559 how close they are to PREFER. */)
3560 (font_spec, frame, num, prefer)
3561 Lisp_Object font_spec, frame, num, prefer;
3562 {
3563 Lisp_Object vec, list, tail;
3564 int n = 0, i, len;
3565
3566 if (NILP (frame))
3567 frame = selected_frame;
3568 CHECK_LIVE_FRAME (frame);
3569 CHECK_FONT_SPEC (font_spec);
3570 if (! NILP (num))
3571 {
3572 CHECK_NUMBER (num);
3573 n = XINT (num);
3574 if (n <= 0)
3575 return Qnil;
3576 }
3577 if (! NILP (prefer))
3578 CHECK_FONT_SPEC (prefer);
3579
3580 vec = font_list_entities (frame, font_spec);
3581 len = ASIZE (vec);
3582 if (len == 0)
3583 return Qnil;
3584 if (len == 1)
3585 return Fcons (AREF (vec, 0), Qnil);
3586
3587 if (! NILP (prefer))
3588 vec = font_sort_entites (vec, prefer, frame, font_spec, 0);
3589
3590 list = tail = Fcons (AREF (vec, 0), Qnil);
3591 if (n == 0 || n > len)
3592 n = len;
3593 for (i = 1; i < n; i++)
3594 {
3595 Lisp_Object val = Fcons (AREF (vec, i), Qnil);
3596
3597 XSETCDR (tail, val);
3598 tail = val;
3599 }
3600 return list;
3601 }
3602
3603 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
3604 doc: /* List available font families on the current frame.
3605 Optional argument FRAME, if non-nil, specifies the target frame. */)
3606 (frame)
3607 Lisp_Object frame;
3608 {
3609 FRAME_PTR f;
3610 struct font_driver_list *driver_list;
3611 Lisp_Object list;
3612
3613 if (NILP (frame))
3614 frame = selected_frame;
3615 CHECK_LIVE_FRAME (frame);
3616 f = XFRAME (frame);
3617 list = Qnil;
3618 for (driver_list = f->font_driver_list; driver_list;
3619 driver_list = driver_list->next)
3620 if (driver_list->driver->list_family)
3621 {
3622 Lisp_Object val = driver_list->driver->list_family (frame);
3623
3624 if (NILP (list))
3625 list = val;
3626 else
3627 {
3628 Lisp_Object tail = list;
3629
3630 for (; CONSP (val); val = XCDR (val))
3631 if (NILP (Fmemq (XCAR (val), tail)))
3632 list = Fcons (XCAR (val), list);
3633 }
3634 }
3635 return list;
3636 }
3637
3638 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
3639 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
3640 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
3641 (font_spec, frame)
3642 Lisp_Object font_spec, frame;
3643 {
3644 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
3645
3646 if (CONSP (val))
3647 val = XCAR (val);
3648 return val;
3649 }
3650
3651 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
3652 doc: /* Return XLFD name of FONT.
3653 FONT is a font-spec, font-entity, or font-object.
3654 If the name is too long for XLFD (maximum 255 chars), return nil.
3655 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
3656 the consecutive wildcards are folded to one. */)
3657 (font, fold_wildcards)
3658 Lisp_Object font, fold_wildcards;
3659 {
3660 char name[256];
3661 int pixel_size = 0;
3662
3663 CHECK_FONT (font);
3664
3665 if (FONT_OBJECT_P (font))
3666 {
3667 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
3668
3669 if (STRINGP (font_name)
3670 && SDATA (font_name)[0] == '-')
3671 {
3672 if (NILP (fold_wildcards))
3673 return font_name;
3674 strcpy (name, (char *) SDATA (font_name));
3675 goto done;
3676 }
3677 pixel_size = XFONT_OBJECT (font)->pixel_size;
3678 }
3679 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
3680 return Qnil;
3681 done:
3682 if (! NILP (fold_wildcards))
3683 {
3684 char *p0 = name, *p1;
3685
3686 while ((p1 = strstr (p0, "-*-*")))
3687 {
3688 strcpy (p1, p1 + 2);
3689 p0 = p1;
3690 }
3691 }
3692
3693 return build_string (name);
3694 }
3695
3696 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
3697 doc: /* Clear font cache. */)
3698 ()
3699 {
3700 Lisp_Object list, frame;
3701
3702 FOR_EACH_FRAME (list, frame)
3703 {
3704 FRAME_PTR f = XFRAME (frame);
3705 struct font_driver_list *driver_list = f->font_driver_list;
3706
3707 for (; driver_list; driver_list = driver_list->next)
3708 if (driver_list->on)
3709 {
3710 Lisp_Object cache = driver_list->driver->get_cache (f);
3711 Lisp_Object val;
3712
3713 val = XCDR (cache);
3714 while (! NILP (val)
3715 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
3716 val = XCDR (val);
3717 font_assert (! NILP (val));
3718 val = XCDR (XCAR (val));
3719 if (XINT (XCAR (val)) == 0)
3720 {
3721 font_clear_cache (f, XCAR (val), driver_list->driver);
3722 XSETCDR (cache, XCDR (val));
3723 }
3724 }
3725 }
3726
3727 return Qnil;
3728 }
3729
3730 /* The following three functions are still experimental. */
3731
3732 DEFUN ("font-make-gstring", Ffont_make_gstring, Sfont_make_gstring, 2, 2, 0,
3733 doc: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
3734 FONT-OBJECT may be nil if it is not yet known.
3735
3736 G-string is sequence of glyphs of a specific font,
3737 and is a vector of this form:
3738 [ HEADER GLYPH ... ]
3739 HEADER is a vector of this form:
3740 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
3741 where
3742 FONT-OBJECT is a font-object for all glyphs in the g-string,
3743 WIDTH thru DESCENT are the metrics (in pixels) of the whole G-string.
3744 GLYPH is a vector of this form:
3745 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
3746 [ [X-OFF Y-OFF WADJUST] | nil] ]
3747 where
3748 FROM-IDX and TO-IDX are used internally and should not be touched.
3749 C is the character of the glyph.
3750 CODE is the glyph-code of C in FONT-OBJECT.
3751 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
3752 X-OFF and Y-OFF are offests to the base position for the glyph.
3753 WADJUST is the adjustment to the normal width of the glyph. */)
3754 (font_object, num)
3755 Lisp_Object font_object, num;
3756 {
3757 Lisp_Object gstring, g;
3758 int len;
3759 int i;
3760
3761 if (! NILP (font_object))
3762 CHECK_FONT_OBJECT (font_object);
3763 CHECK_NATNUM (num);
3764
3765 len = XINT (num) + 1;
3766 gstring = Fmake_vector (make_number (len), Qnil);
3767 g = Fmake_vector (make_number (6), Qnil);
3768 ASET (g, 0, font_object);
3769 ASET (gstring, 0, g);
3770 for (i = 1; i < len; i++)
3771 ASET (gstring, i, Fmake_vector (make_number (10), Qnil));
3772 return gstring;
3773 }
3774
3775 DEFUN ("font-fill-gstring", Ffont_fill_gstring, Sfont_fill_gstring, 4, 5, 0,
3776 doc: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
3777 START and END specify the region to extract characters.
3778 If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
3779 where to extract characters.
3780 FONT-OBJECT may be nil if GSTRING already contains one. */)
3781 (gstring, font_object, start, end, object)
3782 Lisp_Object gstring, font_object, start, end, object;
3783 {
3784 int len, i, c;
3785 unsigned code;
3786 struct font *font;
3787
3788 CHECK_VECTOR (gstring);
3789 if (NILP (font_object))
3790 font_object = LGSTRING_FONT (gstring);
3791 font = XFONT_OBJECT (font_object);
3792
3793 if (STRINGP (object))
3794 {
3795 const unsigned char *p;
3796
3797 CHECK_NATNUM (start);
3798 CHECK_NATNUM (end);
3799 if (XINT (start) > XINT (end)
3800 || XINT (end) > ASIZE (object)
3801 || XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3802 args_out_of_range_3 (object, start, end);
3803
3804 len = XINT (end) - XINT (start);
3805 p = SDATA (object) + string_char_to_byte (object, XINT (start));
3806 for (i = 0; i < len; i++)
3807 {
3808 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3809 /* Shut up GCC warning in comparison with
3810 MOST_POSITIVE_FIXNUM below. */
3811 EMACS_INT cod;
3812
3813 c = STRING_CHAR_ADVANCE (p);
3814 cod = code = font->driver->encode_char (font, c);
3815 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3816 break;
3817 LGLYPH_SET_FROM (g, i);
3818 LGLYPH_SET_TO (g, i);
3819 LGLYPH_SET_CHAR (g, c);
3820 LGLYPH_SET_CODE (g, code);
3821 }
3822 }
3823 else
3824 {
3825 int pos, pos_byte;
3826
3827 if (! NILP (object))
3828 Fset_buffer (object);
3829 validate_region (&start, &end);
3830 if (XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3831 args_out_of_range (start, end);
3832 len = XINT (end) - XINT (start);
3833 pos = XINT (start);
3834 pos_byte = CHAR_TO_BYTE (pos);
3835 for (i = 0; i < len; i++)
3836 {
3837 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3838 /* Shut up GCC warning in comparison with
3839 MOST_POSITIVE_FIXNUM below. */
3840 EMACS_INT cod;
3841
3842 FETCH_CHAR_ADVANCE (c, pos, pos_byte);
3843 cod = code = font->driver->encode_char (font, c);
3844 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3845 break;
3846 LGLYPH_SET_FROM (g, i);
3847 LGLYPH_SET_TO (g, i);
3848 LGLYPH_SET_CHAR (g, c);
3849 LGLYPH_SET_CODE (g, code);
3850 }
3851 }
3852 for (; i < LGSTRING_LENGTH (gstring); i++)
3853 LGSTRING_SET_GLYPH (gstring, i, Qnil);
3854 return Qnil;
3855 }
3856
3857 DEFUN ("font-shape-text", Ffont_shape_text, Sfont_shape_text, 3, 4, 0,
3858 doc: /* Shape text between FROM and TO by FONT-OBJECT.
3859 If optional 4th argument STRING is non-nil, it is a string to shape,
3860 and FROM and TO are indices to the string.
3861 The value is the end position of the text that can be shaped by
3862 FONT-OBJECT. */)
3863 (from, to, font_object, string)
3864 Lisp_Object from, to, font_object, string;
3865 {
3866 struct font *font;
3867 struct font_metrics metrics;
3868 EMACS_INT start, end;
3869 Lisp_Object gstring, n;
3870 int len, i;
3871
3872 if (! FONT_OBJECT_P (font_object))
3873 return Qnil;
3874 font = XFONT_OBJECT (font_object);
3875 if (! font->driver->shape)
3876 return Qnil;
3877
3878 if (NILP (string))
3879 {
3880 validate_region (&from, &to);
3881 start = XFASTINT (from);
3882 end = XFASTINT (to);
3883 modify_region (current_buffer, start, end, 0);
3884 }
3885 else
3886 {
3887 CHECK_STRING (string);
3888 start = XINT (from);
3889 end = XINT (to);
3890 if (start < 0 || start > end || end > SCHARS (string))
3891 args_out_of_range_3 (string, from, to);
3892 }
3893
3894 len = end - start;
3895 gstring = Ffont_make_gstring (font_object, make_number (len));
3896 Ffont_fill_gstring (gstring, font_object, from, to, string);
3897
3898 /* Try at most three times with larger gstring each time. */
3899 for (i = 0; i < 3; i++)
3900 {
3901 Lisp_Object args[2];
3902
3903 n = font->driver->shape (gstring);
3904 if (INTEGERP (n))
3905 break;
3906 args[0] = gstring;
3907 args[1] = Fmake_vector (make_number (len), Qnil);
3908 gstring = Fvconcat (2, args);
3909 }
3910 if (! INTEGERP (n) || XINT (n) == 0)
3911 return Qnil;
3912 len = XINT (n);
3913
3914 for (i = 0; i < len;)
3915 {
3916 Lisp_Object gstr;
3917 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3918 EMACS_INT this_from = LGLYPH_FROM (g);
3919 EMACS_INT this_to = LGLYPH_TO (g) + 1;
3920 int j, k;
3921 int need_composition = 0;
3922
3923 metrics.lbearing = LGLYPH_LBEARING (g);
3924 metrics.rbearing = LGLYPH_RBEARING (g);
3925 metrics.ascent = LGLYPH_ASCENT (g);
3926 metrics.descent = LGLYPH_DESCENT (g);
3927 if (NILP (LGLYPH_ADJUSTMENT (g)))
3928 {
3929 metrics.width = LGLYPH_WIDTH (g);
3930 if (LGLYPH_CHAR (g) == 0 || metrics.width == 0)
3931 need_composition = 1;
3932 }
3933 else
3934 {
3935 metrics.width = LGLYPH_WADJUST (g);
3936 metrics.lbearing += LGLYPH_XOFF (g);
3937 metrics.rbearing += LGLYPH_XOFF (g);
3938 metrics.ascent -= LGLYPH_YOFF (g);
3939 metrics.descent += LGLYPH_YOFF (g);
3940 need_composition = 1;
3941 }
3942 for (j = i + 1; j < len; j++)
3943 {
3944 int x;
3945
3946 g = LGSTRING_GLYPH (gstring, j);
3947 if (this_from != LGLYPH_FROM (g))
3948 break;
3949 need_composition = 1;
3950 x = metrics.width + LGLYPH_LBEARING (g) + LGLYPH_XOFF (g);
3951 if (metrics.lbearing > x)
3952 metrics.lbearing = x;
3953 x = metrics.width + LGLYPH_RBEARING (g) + LGLYPH_XOFF (g);
3954 if (metrics.rbearing < x)
3955 metrics.rbearing = x;
3956 x = LGLYPH_ASCENT (g) - LGLYPH_YOFF (g);
3957 if (metrics.ascent < x)
3958 metrics.ascent = x;
3959 x = LGLYPH_DESCENT (g) - LGLYPH_YOFF (g);
3960 if (metrics.descent < x)
3961 metrics.descent = x;
3962 if (NILP (LGLYPH_ADJUSTMENT (g)))
3963 metrics.width += LGLYPH_WIDTH (g);
3964 else
3965 metrics.width += LGLYPH_WADJUST (g);
3966 }
3967
3968 if (need_composition)
3969 {
3970 gstr = Ffont_make_gstring (font_object, make_number (j - i));
3971 LGSTRING_SET_WIDTH (gstr, metrics.width);
3972 LGSTRING_SET_LBEARING (gstr, metrics.lbearing);
3973 LGSTRING_SET_RBEARING (gstr, metrics.rbearing);
3974 LGSTRING_SET_ASCENT (gstr, metrics.ascent);
3975 LGSTRING_SET_DESCENT (gstr, metrics.descent);
3976 for (k = i; i < j; i++)
3977 {
3978 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3979
3980 LGLYPH_SET_FROM (g, LGLYPH_FROM (g) - this_from);
3981 LGLYPH_SET_TO (g, LGLYPH_TO (g) - this_from);
3982 LGSTRING_SET_GLYPH (gstr, i - k, LGSTRING_GLYPH (gstring, i));
3983 }
3984 from = make_number (start + this_from);
3985 to = make_number (start + this_to);
3986 if (NILP (string))
3987 Fcompose_region_internal (from, to, gstr, Qnil);
3988 else
3989 Fcompose_string_internal (string, from, to, gstr, Qnil);
3990 }
3991 else
3992 i = j;
3993 }
3994
3995 return to;
3996 }
3997
3998 #if 0
3999
4000 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
4001 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
4002 OTF-FEATURES specifies which features to apply in this format:
4003 (SCRIPT LANGSYS GSUB GPOS)
4004 where
4005 SCRIPT is a symbol specifying a script tag of OpenType,
4006 LANGSYS is a symbol specifying a langsys tag of OpenType,
4007 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4008
4009 If LANGYS is nil, the default langsys is selected.
4010
4011 The features are applied in the order they appear in the list. The
4012 symbol `*' means to apply all available features not present in this
4013 list, and the remaining features are ignored. For instance, (vatu
4014 pstf * haln) is to apply vatu and pstf in this order, then to apply
4015 all available features other than vatu, pstf, and haln.
4016
4017 The features are applied to the glyphs in the range FROM and TO of
4018 the glyph-string GSTRING-IN.
4019
4020 If some feature is actually applicable, the resulting glyphs are
4021 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4022 this case, the value is the number of produced glyphs.
4023
4024 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4025 the value is 0.
4026
4027 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4028 produced in GSTRING-OUT, and the value is nil.
4029
4030 See the documentation of `font-make-gstring' for the format of
4031 glyph-string. */)
4032 (otf_features, gstring_in, from, to, gstring_out, index)
4033 Lisp_Object otf_features, gstring_in, from, to, gstring_out, index;
4034 {
4035 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
4036 Lisp_Object val;
4037 struct font *font;
4038 int len, num;
4039
4040 check_otf_features (otf_features);
4041 CHECK_FONT_OBJECT (font_object);
4042 font = XFONT_OBJECT (font_object);
4043 if (! font->driver->otf_drive)
4044 error ("Font backend %s can't drive OpenType GSUB table",
4045 SDATA (SYMBOL_NAME (font->driver->type)));
4046 CHECK_CONS (otf_features);
4047 CHECK_SYMBOL (XCAR (otf_features));
4048 val = XCDR (otf_features);
4049 CHECK_SYMBOL (XCAR (val));
4050 val = XCDR (otf_features);
4051 if (! NILP (val))
4052 CHECK_CONS (val);
4053 len = check_gstring (gstring_in);
4054 CHECK_VECTOR (gstring_out);
4055 CHECK_NATNUM (from);
4056 CHECK_NATNUM (to);
4057 CHECK_NATNUM (index);
4058
4059 if (XINT (from) >= XINT (to) || XINT (to) > len)
4060 args_out_of_range_3 (from, to, make_number (len));
4061 if (XINT (index) >= ASIZE (gstring_out))
4062 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4063 num = font->driver->otf_drive (font, otf_features,
4064 gstring_in, XINT (from), XINT (to),
4065 gstring_out, XINT (index), 0);
4066 if (num < 0)
4067 return Qnil;
4068 return make_number (num);
4069 }
4070
4071 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4072 3, 3, 0,
4073 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4074 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4075 in this format:
4076 (SCRIPT LANGSYS FEATURE ...)
4077 See the documentation of `font-drive-otf' for more detail.
4078
4079 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4080 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4081 character code corresponding to the glyph or nil if there's no
4082 corresponding character. */)
4083 (font_object, character, otf_features)
4084 Lisp_Object font_object, character, otf_features;
4085 {
4086 struct font *font;
4087 Lisp_Object gstring_in, gstring_out, g;
4088 Lisp_Object alternates;
4089 int i, num;
4090
4091 CHECK_FONT_GET_OBJECT (font_object, font);
4092 if (! font->driver->otf_drive)
4093 error ("Font backend %s can't drive OpenType GSUB table",
4094 SDATA (SYMBOL_NAME (font->driver->type)));
4095 CHECK_CHARACTER (character);
4096 CHECK_CONS (otf_features);
4097
4098 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4099 g = LGSTRING_GLYPH (gstring_in, 0);
4100 LGLYPH_SET_CHAR (g, XINT (character));
4101 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4102 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4103 gstring_out, 0, 1)) < 0)
4104 gstring_out = Ffont_make_gstring (font_object,
4105 make_number (ASIZE (gstring_out) * 2));
4106 alternates = Qnil;
4107 for (i = 0; i < num; i++)
4108 {
4109 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4110 int c = LGLYPH_CHAR (g);
4111 unsigned code = LGLYPH_CODE (g);
4112
4113 alternates = Fcons (Fcons (make_number (code),
4114 c > 0 ? make_number (c) : Qnil),
4115 alternates);
4116 }
4117 return Fnreverse (alternates);
4118 }
4119 #endif /* 0 */
4120
4121 #ifdef FONT_DEBUG
4122
4123 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4124 doc: /* Open FONT-ENTITY. */)
4125 (font_entity, size, frame)
4126 Lisp_Object font_entity;
4127 Lisp_Object size;
4128 Lisp_Object frame;
4129 {
4130 int isize;
4131
4132 CHECK_FONT_ENTITY (font_entity);
4133 if (NILP (frame))
4134 frame = selected_frame;
4135 CHECK_LIVE_FRAME (frame);
4136
4137 if (NILP (size))
4138 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4139 else
4140 {
4141 CHECK_NUMBER_OR_FLOAT (size);
4142 if (FLOATP (size))
4143 isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy);
4144 else
4145 isize = XINT (size);
4146 if (isize == 0)
4147 isize = 120;
4148 }
4149 return font_open_entity (XFRAME (frame), font_entity, isize);
4150 }
4151
4152 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4153 doc: /* Close FONT-OBJECT. */)
4154 (font_object, frame)
4155 Lisp_Object font_object, frame;
4156 {
4157 CHECK_FONT_OBJECT (font_object);
4158 if (NILP (frame))
4159 frame = selected_frame;
4160 CHECK_LIVE_FRAME (frame);
4161 font_close_object (XFRAME (frame), font_object);
4162 return Qnil;
4163 }
4164
4165 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4166 doc: /* Return information about FONT-OBJECT.
4167 The value is a vector:
4168 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4169 CAPABILITY ]
4170
4171 NAME is a string of the font name (or nil if the font backend doesn't
4172 provide a name).
4173
4174 FILENAME is a string of the font file (or nil if the font backend
4175 doesn't provide a file name).
4176
4177 PIXEL-SIZE is a pixel size by which the font is opened.
4178
4179 SIZE is a maximum advance width of the font in pixels.
4180
4181 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4182 pixels.
4183
4184 CAPABILITY is a list whose first element is a symbol representing the
4185 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4186 remaining elements describe the details of the font capability.
4187
4188 If the font is OpenType font, the form of the list is
4189 \(opentype GSUB GPOS)
4190 where GSUB shows which "GSUB" features the font supports, and GPOS
4191 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4192 lists of the format:
4193 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4194
4195 If the font is not OpenType font, currently the length of the form is
4196 one.
4197
4198 SCRIPT is a symbol representing OpenType script tag.
4199
4200 LANGSYS is a symbol representing OpenType langsys tag, or nil
4201 representing the default langsys.
4202
4203 FEATURE is a symbol representing OpenType feature tag.
4204
4205 If the font is not OpenType font, CAPABILITY is nil. */)
4206 (font_object)
4207 Lisp_Object font_object;
4208 {
4209 struct font *font;
4210 Lisp_Object val;
4211
4212 CHECK_FONT_GET_OBJECT (font_object, font);
4213
4214 val = Fmake_vector (make_number (9), Qnil);
4215 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4216 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4217 ASET (val, 2, make_number (font->pixel_size));
4218 ASET (val, 3, make_number (font->max_width));
4219 ASET (val, 4, make_number (font->ascent));
4220 ASET (val, 5, make_number (font->descent));
4221 ASET (val, 6, make_number (font->space_width));
4222 ASET (val, 7, make_number (font->average_width));
4223 if (font->driver->otf_capability)
4224 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4225 return val;
4226 }
4227
4228 DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
4229 doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
4230 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
4231 (font_object, string)
4232 Lisp_Object font_object, string;
4233 {
4234 struct font *font;
4235 int i, len;
4236 Lisp_Object vec;
4237
4238 CHECK_FONT_GET_OBJECT (font_object, font);
4239 CHECK_STRING (string);
4240 len = SCHARS (string);
4241 vec = Fmake_vector (make_number (len), Qnil);
4242 for (i = 0; i < len; i++)
4243 {
4244 Lisp_Object ch = Faref (string, make_number (i));
4245 Lisp_Object val;
4246 int c = XINT (ch);
4247 unsigned code;
4248 EMACS_INT cod;
4249 struct font_metrics metrics;
4250
4251 cod = code = font->driver->encode_char (font, c);
4252 if (code == FONT_INVALID_CODE)
4253 continue;
4254 val = Fmake_vector (make_number (6), Qnil);
4255 if (cod <= MOST_POSITIVE_FIXNUM)
4256 ASET (val, 0, make_number (code));
4257 else
4258 ASET (val, 0, Fcons (make_number (code >> 16),
4259 make_number (code & 0xFFFF)));
4260 font->driver->text_extents (font, &code, 1, &metrics);
4261 ASET (val, 1, make_number (metrics.lbearing));
4262 ASET (val, 2, make_number (metrics.rbearing));
4263 ASET (val, 3, make_number (metrics.width));
4264 ASET (val, 4, make_number (metrics.ascent));
4265 ASET (val, 5, make_number (metrics.descent));
4266 ASET (vec, i, val);
4267 }
4268 return vec;
4269 }
4270
4271 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4272 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4273 FONT is a font-spec, font-entity, or font-object. */)
4274 (spec, font)
4275 Lisp_Object spec, font;
4276 {
4277 CHECK_FONT_SPEC (spec);
4278 CHECK_FONT (font);
4279
4280 return (font_match_p (spec, font) ? Qt : Qnil);
4281 }
4282
4283 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4284 doc: /* Return a font-object for displaying a character at POSITION.
4285 Optional second arg WINDOW, if non-nil, is a window displaying
4286 the current buffer. It defaults to the currently selected window. */)
4287 (position, window, string)
4288 Lisp_Object position, window, string;
4289 {
4290 struct window *w;
4291 EMACS_INT pos;
4292
4293 if (NILP (string))
4294 {
4295 CHECK_NUMBER_COERCE_MARKER (position);
4296 pos = XINT (position);
4297 if (pos < BEGV || pos >= ZV)
4298 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4299 }
4300 else
4301 {
4302 CHECK_NUMBER (position);
4303 CHECK_STRING (string);
4304 pos = XINT (position);
4305 if (pos < 0 || pos >= SCHARS (string))
4306 args_out_of_range (string, position);
4307 }
4308 if (NILP (window))
4309 window = selected_window;
4310 CHECK_LIVE_WINDOW (window);
4311 w = XWINDOW (window);
4312
4313 return font_at (-1, pos, NULL, w, string);
4314 }
4315
4316 #if 0
4317 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4318 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4319 The value is a number of glyphs drawn.
4320 Type C-l to recover what previously shown. */)
4321 (font_object, string)
4322 Lisp_Object font_object, string;
4323 {
4324 Lisp_Object frame = selected_frame;
4325 FRAME_PTR f = XFRAME (frame);
4326 struct font *font;
4327 struct face *face;
4328 int i, len, width;
4329 unsigned *code;
4330
4331 CHECK_FONT_GET_OBJECT (font_object, font);
4332 CHECK_STRING (string);
4333 len = SCHARS (string);
4334 code = alloca (sizeof (unsigned) * len);
4335 for (i = 0; i < len; i++)
4336 {
4337 Lisp_Object ch = Faref (string, make_number (i));
4338 Lisp_Object val;
4339 int c = XINT (ch);
4340
4341 code[i] = font->driver->encode_char (font, c);
4342 if (code[i] == FONT_INVALID_CODE)
4343 break;
4344 }
4345 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4346 face->fontp = font;
4347 if (font->driver->prepare_face)
4348 font->driver->prepare_face (f, face);
4349 width = font->driver->text_extents (font, code, i, NULL);
4350 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4351 if (font->driver->done_face)
4352 font->driver->done_face (f, face);
4353 face->fontp = NULL;
4354 return make_number (len);
4355 }
4356 #endif
4357
4358 #endif /* FONT_DEBUG */
4359
4360 #ifdef HAVE_WINDOW_SYSTEM
4361
4362 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
4363 doc: /* Return information about a font named NAME on frame FRAME.
4364 If FRAME is omitted or nil, use the selected frame.
4365 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
4366 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4367 where
4368 OPENED-NAME is the name used for opening the font,
4369 FULL-NAME is the full name of the font,
4370 SIZE is the maximum bound width of the font,
4371 HEIGHT is the height of the font,
4372 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4373 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4374 how to compose characters.
4375 If the named font is not yet loaded, return nil. */)
4376 (name, frame)
4377 Lisp_Object name, frame;
4378 {
4379 FRAME_PTR f;
4380 struct font *font;
4381 Lisp_Object info;
4382 Lisp_Object font_object;
4383
4384 (*check_window_system_func) ();
4385
4386 if (! FONTP (name))
4387 CHECK_STRING (name);
4388 if (NILP (frame))
4389 frame = selected_frame;
4390 CHECK_LIVE_FRAME (frame);
4391 f = XFRAME (frame);
4392
4393 if (STRINGP (name))
4394 {
4395 int fontset = fs_query_fontset (name, 0);
4396
4397 if (fontset >= 0)
4398 name = fontset_ascii (fontset);
4399 font_object = font_open_by_name (f, (char *) SDATA (name));
4400 }
4401 else if (FONT_OBJECT_P (name))
4402 font_object = name;
4403 else if (FONT_ENTITY_P (name))
4404 font_object = font_open_entity (f, name, 0);
4405 else
4406 {
4407 struct face *face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4408 Lisp_Object entity = font_matching_entity (f, face->lface, name);
4409
4410 font_object = ! NILP (entity) ? font_open_entity (f, entity, 0) : Qnil;
4411 }
4412 if (NILP (font_object))
4413 return Qnil;
4414 font = XFONT_OBJECT (font_object);
4415
4416 info = Fmake_vector (make_number (7), Qnil);
4417 XVECTOR (info)->contents[0] = AREF (font_object, FONT_NAME_INDEX);
4418 XVECTOR (info)->contents[1] = AREF (font_object, FONT_NAME_INDEX);
4419 XVECTOR (info)->contents[2] = make_number (font->pixel_size);
4420 XVECTOR (info)->contents[3] = make_number (font->height);
4421 XVECTOR (info)->contents[4] = make_number (font->baseline_offset);
4422 XVECTOR (info)->contents[5] = make_number (font->relative_compose);
4423 XVECTOR (info)->contents[6] = make_number (font->default_ascent);
4424
4425 #if 0
4426 /* As font_object is still in FONT_OBJLIST of the entity, we can't
4427 close it now. Perhaps, we should manage font-objects
4428 by `reference-count'. */
4429 font_close_object (f, font_object);
4430 #endif
4431 return info;
4432 }
4433 #endif
4434
4435 \f
4436 #define BUILD_STYLE_TABLE(TBL) \
4437 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
4438
4439 static Lisp_Object
4440 build_style_table (entry, nelement)
4441 struct table_entry *entry;
4442 int nelement;
4443 {
4444 int i, j;
4445 Lisp_Object table, elt;
4446
4447 table = Fmake_vector (make_number (nelement), Qnil);
4448 for (i = 0; i < nelement; i++)
4449 {
4450 for (j = 0; entry[i].names[j]; j++);
4451 elt = Fmake_vector (make_number (j + 1), Qnil);
4452 ASET (elt, 0, make_number (entry[i].numeric));
4453 for (j = 0; entry[i].names[j]; j++)
4454 ASET (elt, j + 1, intern (entry[i].names[j]));
4455 ASET (table, i, elt);
4456 }
4457 return table;
4458 }
4459
4460 static Lisp_Object Vfont_log;
4461 static int font_log_env_checked;
4462
4463 void
4464 font_add_log (action, arg, result)
4465 char *action;
4466 Lisp_Object arg, result;
4467 {
4468 Lisp_Object tail, val;
4469 int i;
4470
4471 if (! font_log_env_checked)
4472 {
4473 Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;
4474 font_log_env_checked = 1;
4475 }
4476 if (EQ (Vfont_log, Qt))
4477 return;
4478 if (FONTP (arg))
4479 arg = Ffont_xlfd_name (arg, Qt);
4480 if (FONTP (result))
4481 result = Ffont_xlfd_name (result, Qt);
4482 else if (CONSP (result))
4483 {
4484 result = Fcopy_sequence (result);
4485 for (tail = result; CONSP (tail); tail = XCDR (tail))
4486 {
4487 val = XCAR (tail);
4488 if (FONTP (val))
4489 val = Ffont_xlfd_name (val, Qt);
4490 XSETCAR (tail, val);
4491 }
4492 }
4493 else if (VECTORP (result))
4494 {
4495 result = Fcopy_sequence (result);
4496 for (i = 0; i < ASIZE (result); i++)
4497 {
4498 val = AREF (result, i);
4499 if (FONTP (val))
4500 val = Ffont_xlfd_name (val, Qt);
4501 ASET (result, i, val);
4502 }
4503 }
4504 Vfont_log = Fcons (list3 (intern (action), arg, result), Vfont_log);
4505 }
4506
4507 extern void syms_of_ftfont P_ (());
4508 extern void syms_of_xfont P_ (());
4509 extern void syms_of_xftfont P_ (());
4510 extern void syms_of_ftxfont P_ (());
4511 extern void syms_of_bdffont P_ (());
4512 extern void syms_of_w32font P_ (());
4513 extern void syms_of_atmfont P_ (());
4514
4515 void
4516 syms_of_font ()
4517 {
4518 sort_shift_bits[FONT_SLANT_INDEX] = 0;
4519 sort_shift_bits[FONT_WEIGHT_INDEX] = 7;
4520 sort_shift_bits[FONT_SIZE_INDEX] = 14;
4521 sort_shift_bits[FONT_WIDTH_INDEX] = 21;
4522 sort_shift_bits[FONT_ADSTYLE_INDEX] = 28;
4523 sort_shift_bits[FONT_FOUNDRY_INDEX] = 29;
4524 sort_shift_bits[FONT_FAMILY_INDEX] = 30;
4525 /* Note that sort_shift_bits[FONT_SORT_TYPE] and
4526 sort_shift_bits[FONT_SORT_REGISTRY] are never used. */
4527
4528 staticpro (&font_charset_alist);
4529 font_charset_alist = Qnil;
4530
4531 DEFSYM (Qfont_spec, "font-spec");
4532 DEFSYM (Qfont_entity, "font-entity");
4533 DEFSYM (Qfont_object, "font-object");
4534
4535 DEFSYM (Qopentype, "opentype");
4536
4537 DEFSYM (Qascii_0, "ascii-0");
4538 DEFSYM (Qiso8859_1, "iso8859-1");
4539 DEFSYM (Qiso10646_1, "iso10646-1");
4540 DEFSYM (Qunicode_bmp, "unicode-bmp");
4541 DEFSYM (Qunicode_sip, "unicode-sip");
4542
4543 DEFSYM (QCotf, ":otf");
4544 DEFSYM (QClang, ":lang");
4545 DEFSYM (QCscript, ":script");
4546 DEFSYM (QCantialias, ":antialias");
4547
4548 DEFSYM (QCfoundry, ":foundry");
4549 DEFSYM (QCadstyle, ":adstyle");
4550 DEFSYM (QCregistry, ":registry");
4551 DEFSYM (QCspacing, ":spacing");
4552 DEFSYM (QCdpi, ":dpi");
4553 DEFSYM (QCscalable, ":scalable");
4554 DEFSYM (QCavgwidth, ":avgwidth");
4555 DEFSYM (QCfont_entity, ":font-entity");
4556 DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
4557
4558 DEFSYM (Qc, "c");
4559 DEFSYM (Qm, "m");
4560 DEFSYM (Qp, "p");
4561 DEFSYM (Qd, "d");
4562
4563 staticpro (&null_vector);
4564 null_vector = Fmake_vector (make_number (0), Qnil);
4565
4566 staticpro (&scratch_font_spec);
4567 scratch_font_spec = Ffont_spec (0, NULL);
4568 staticpro (&scratch_font_prefer);
4569 scratch_font_prefer = Ffont_spec (0, NULL);
4570
4571 #if 0
4572 #ifdef HAVE_LIBOTF
4573 staticpro (&otf_list);
4574 otf_list = Qnil;
4575 #endif /* HAVE_LIBOTF */
4576 #endif /* 0 */
4577
4578 defsubr (&Sfontp);
4579 defsubr (&Sfont_spec);
4580 defsubr (&Sfont_get);
4581 defsubr (&Sfont_put);
4582 defsubr (&Slist_fonts);
4583 defsubr (&Sfont_family_list);
4584 defsubr (&Sfind_font);
4585 defsubr (&Sfont_xlfd_name);
4586 defsubr (&Sclear_font_cache);
4587 defsubr (&Sfont_make_gstring);
4588 defsubr (&Sfont_fill_gstring);
4589 defsubr (&Sfont_shape_text);
4590 #if 0
4591 defsubr (&Sfont_drive_otf);
4592 defsubr (&Sfont_otf_alternates);
4593 #endif /* 0 */
4594
4595 #ifdef FONT_DEBUG
4596 defsubr (&Sopen_font);
4597 defsubr (&Sclose_font);
4598 defsubr (&Squery_font);
4599 defsubr (&Sget_font_glyphs);
4600 defsubr (&Sfont_match_p);
4601 defsubr (&Sfont_at);
4602 #if 0
4603 defsubr (&Sdraw_string);
4604 #endif
4605 #endif /* FONT_DEBUG */
4606 #ifdef HAVE_WINDOW_SYSTEM
4607 defsubr (&Sfont_info);
4608 #endif
4609
4610 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
4611 doc: /*
4612 Alist of fontname patterns vs the corresponding encoding and repertory info.
4613 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
4614 where ENCODING is a charset or a char-table,
4615 and REPERTORY is a charset, a char-table, or nil.
4616
4617 If ENCODING and REPERTORY are the same, the element can have the form
4618 \(REGEXP . ENCODING).
4619
4620 ENCODING is for converting a character to a glyph code of the font.
4621 If ENCODING is a charset, encoding a character by the charset gives
4622 the corresponding glyph code. If ENCODING is a char-table, looking up
4623 the table by a character gives the corresponding glyph code.
4624
4625 REPERTORY specifies a repertory of characters supported by the font.
4626 If REPERTORY is a charset, all characters beloging to the charset are
4627 supported. If REPERTORY is a char-table, all characters who have a
4628 non-nil value in the table are supported. If REPERTORY is nil, Emacs
4629 gets the repertory information by an opened font and ENCODING. */);
4630 Vfont_encoding_alist = Qnil;
4631
4632 DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table,
4633 doc: /* Vector of valid font weight values.
4634 Each element has the form:
4635 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
4636 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symobls. */);
4637 Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
4638
4639 DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table,
4640 doc: /* Vector of font slant symbols vs the corresponding numeric values.
4641 See `font-weight_table' for the format of the vector. */);
4642 Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
4643
4644 DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table,
4645 doc: /* Alist of font width symbols vs the corresponding numeric values.
4646 See `font-weight_table' for the format of the vector. */);
4647 Vfont_width_table = BUILD_STYLE_TABLE (width_table);
4648
4649 staticpro (&font_style_table);
4650 font_style_table = Fmake_vector (make_number (3), Qnil);
4651 ASET (font_style_table, 0, Vfont_weight_table);
4652 ASET (font_style_table, 1, Vfont_slant_table);
4653 ASET (font_style_table, 2, Vfont_width_table);
4654
4655 DEFVAR_LISP ("font-log", &Vfont_log, doc: /*
4656 *Logging list of font related actions and results.
4657 The value t means to suppress the logging.
4658 The initial value is set to nil if the environment variable
4659 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
4660 Vfont_log = Qnil;
4661
4662 #ifdef HAVE_WINDOW_SYSTEM
4663 #ifdef HAVE_FREETYPE
4664 syms_of_ftfont ();
4665 #ifdef HAVE_X_WINDOWS
4666 syms_of_xfont ();
4667 syms_of_ftxfont ();
4668 #ifdef HAVE_XFT
4669 syms_of_xftfont ();
4670 #endif /* HAVE_XFT */
4671 #endif /* HAVE_X_WINDOWS */
4672 #else /* not HAVE_FREETYPE */
4673 #ifdef HAVE_X_WINDOWS
4674 syms_of_xfont ();
4675 #endif /* HAVE_X_WINDOWS */
4676 #endif /* not HAVE_FREETYPE */
4677 #ifdef HAVE_BDFFONT
4678 syms_of_bdffont ();
4679 #endif /* HAVE_BDFFONT */
4680 #ifdef WINDOWSNT
4681 syms_of_w32font ();
4682 #endif /* WINDOWSNT */
4683 #ifdef MAC_OS
4684 syms_of_atmfont ();
4685 #endif /* MAC_OS */
4686 #endif /* HAVE_WINDOW_SYSTEM */
4687 }
4688
4689 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
4690 (do not change this comment) */