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