(xftfont_prepare_face): Make non-ascii face share
[bpt/emacs.git] / src / font.c
CommitLineData
c2f5bfd6
KH
1/* font.c -- "Font" primitives.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3 Copyright (C) 2006
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7This file is part of GNU Emacs.
8
9GNU Emacs is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
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
20along with GNU Emacs; see the file COPYING. If not, write to
21the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22Boston, MA 02110-1301, USA. */
23
24#include <config.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <ctype.h>
28
29#include "lisp.h"
30#include "buffer.h"
31#include "frame.h"
32#include "dispextern.h"
33#include "charset.h"
34#include "character.h"
35#include "composite.h"
36#include "fontset.h"
37#include "font.h"
38
39#define FONT_DEBUG
40
41#ifdef FONT_DEBUG
42#undef xassert
43#define xassert(X) do {if (!(X)) abort ();} while (0)
44#else
45#define xassert(X) (void) 0
46#endif
47
48int enable_font_backend;
49
50Lisp_Object Qfontp;
51
1bb1d99b
KH
52/* Important character set symbols. */
53Lisp_Object Qiso8859_1, Qiso10646_1, Qunicode_bmp;
54
c2f5bfd6
KH
55/* Like CHECK_FONT_SPEC but also validate properties of the font-spec,
56 and set X to the validated result. */
57
58#define CHECK_VALIDATE_FONT_SPEC(x) \
59 do { \
60 if (! FONT_SPEC_P (x)) x = wrong_type_argument (Qfont, x); \
61 x = font_prop_validate (x); \
62 } while (0)
63
64/* Number of pt per inch (from the TeXbook). */
65#define PT_PER_INCH 72.27
66
9331887d
KH
67/* Return a pixel size (integer) corresponding to POINT size (double)
68 on resolution RESY. */
69#define POINT_TO_PIXEL(POINT, RESY) ((POINT) * (RESY) / PT_PER_INCH + 0.5)
c2f5bfd6 70
9331887d
KH
71/* Return a point size (double) corresponding to POINT size (integer)
72 on resolution RESY. */
c2f5bfd6
KH
73#define PIXEL_TO_POINT(PIXEL, RESY) ((PIXEL) * PT_PER_INCH * 10 / (RESY) + 0.5)
74
75/* Special string of zero length. It is used to specify a NULL name
76 in a font properties (e.g. adstyle). We don't use the symbol of
77 NULL name because it's confusing (Lisp printer prints nothing for
78 it). */
79Lisp_Object null_string;
80
81/* Special vector of zero length. This is repeatedly used by (struct
82 font_driver *)->list when a specified font is not found. */
83Lisp_Object null_vector;
84
85/* Vector of 3 elements. Each element is an alist for one of font
86 style properties (weight, slant, width). The alist contains a
87 mapping between symbolic property values (e.g. `medium' for weight)
88 and numeric property values (e.g. 100). So, it looks like this:
89 [((thin . 0) ... (heavy . 210))
90 ((ro . 0) ... (ot . 210))
91 ((ultracondensed . 50) ... (wide . 200))] */
92static Lisp_Object font_style_table;
93
94/* Alist of font family vs the corresponding aliases.
95 Each element has this form:
96 (FAMILY ALIAS1 ALIAS2 ...) */
97
98static Lisp_Object font_family_alist;
99
100/* Symbols representing keys of normal font properties. */
101extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth, QCsize, QCname;
102Lisp_Object QCfoundry, QCadstyle, QCregistry, QCextra;
103/* Symbols representing keys of font extra info. */
9331887d 104Lisp_Object QCspacing, QCdpi, QCotf, QClanguage, QCscript;
c2f5bfd6
KH
105
106/* List of all font drivers. All font-backends (XXXfont.c) call
107 add_font_driver in syms_of_XXXfont to register the font-driver
108 here. */
109static struct font_driver_list *font_driver_list;
110
111static Lisp_Object prop_name_to_numeric P_ ((enum font_property_index,
112 Lisp_Object));
113static Lisp_Object prop_numeric_to_name P_ ((enum font_property_index, int));
114static Lisp_Object font_open_entity P_ ((FRAME_PTR, Lisp_Object, int));
115
116/* Number of registered font drivers. */
117static int num_font_drivers;
118
9331887d
KH
119/* Return a pixel size of font-spec SPEC on frame F. */
120static int
121font_pixel_size (f, spec)
122 FRAME_PTR f;
123 Lisp_Object spec;
124{
125 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
126 double point_size;
127 int pixel_size, dpi;
128 Lisp_Object extra, val;
129
130 if (INTEGERP (size))
131 return XINT (size);
132 if (NILP (size))
133 return 0;
134 point_size = XFLOAT_DATA (size);
135 extra = AREF (spec, FONT_EXTRA_INDEX);
136 val = assq_no_quit (extra, QCdpi);
137
138 if (CONSP (val) && INTEGERP (XCDR (val)))
139 dpi = XINT (XCDR (val));
140 else
141 dpi = f->resy;
142 pixel_size = POINT_TO_PIXEL (point_size, dpi);
143 return pixel_size;
144}
145
c2f5bfd6
KH
146/* Return a numeric value corresponding to PROP's NAME (symbol). If
147 NAME is not registered in font_style_table, return Qnil. PROP must
148 be one of FONT_{WEIGHT|SLANT|SWIDTH}_INDEX. */
149
150static Lisp_Object
151prop_name_to_numeric (prop, name)
152 enum font_property_index prop;
153 Lisp_Object name;
154{
155 int table_index = prop - FONT_WEIGHT_INDEX;
156 Lisp_Object val;
157
158 val = assq_no_quit (name, AREF (font_style_table, table_index));
159 return (NILP (val) ? Qnil : XCDR (val));
160}
161
162
163/* Return a name (symbol) corresponding to PROP's NUMERIC value. If
164 no name is registered for NUMERIC in font_style_table, return a
165 symbol of integer name (e.g. `123'). PROP must be one of
166 FONT_{WEIGHT|SLANT|SWIDTH}_INDEX. */
167
168static Lisp_Object
169prop_numeric_to_name (prop, numeric)
170 enum font_property_index prop;
171 int numeric;
172{
173 int table_index = prop - FONT_WEIGHT_INDEX;
174 Lisp_Object table = AREF (font_style_table, table_index);
175 char buf[10];
176
177 while (! NILP (table))
178 {
179 if (XINT (XCDR (XCAR (table))) >= numeric)
180 {
181 if (XINT (XCDR (XCAR (table))) == numeric)
182 return XCAR (XCAR (table));
183 else
184 break;
185 }
186 table = XCDR (table);
187 }
188 sprintf (buf, "%d", numeric);
189 return intern (buf);
190}
191
192
193/* Return a symbol whose name is STR (length LEN). If STR contains
194 uppercase letters, downcase them in advance. */
195
196Lisp_Object
197intern_downcase (str, len)
198 char *str;
199 int len;
200{
201 char *buf;
202 int i;
203
204 for (i = 0; i < len; i++)
205 if (isupper (str[i]))
206 break;
207 if (i == len)
208 return Fintern (make_unibyte_string (str, len), Qnil);
209 buf = alloca (len);
210 if (! buf)
211 return Fintern (null_string, Qnil);
212 bcopy (str, buf, len);
213 for (; i < len; i++)
214 if (isascii (buf[i]))
215 buf[i] = tolower (buf[i]);
216 return Fintern (make_unibyte_string (buf, len), Qnil);
217}
218
219extern Lisp_Object Vface_alternative_font_family_alist;
220
221static void
222build_font_family_alist ()
223{
224 Lisp_Object alist = Vface_alternative_font_family_alist;
225
226 for (; CONSP (alist); alist = XCDR (alist))
227 {
228 Lisp_Object tail, elt;
229
230 for (tail = XCAR (alist), elt = Qnil ; CONSP (tail); tail = XCDR (tail))
231 elt = nconc2 (elt, Fcons (Fintern (XCAR (tail), Qnil), Qnil));
232 font_family_alist = Fcons (elt, font_family_alist);
233 }
234}
235
236\f
237/* Font property validater. */
238
239static Lisp_Object
240font_prop_validate_type (prop, val)
241 enum font_property_index prop;
242 Lisp_Object val;
243{
244 return (SYMBOLP (val) ? val : Qerror);
245}
246
247static Lisp_Object
248font_prop_validate_symbol (prop, val)
249 enum font_property_index prop;
250 Lisp_Object val;
251{
252 if (STRINGP (val))
253 val = (SCHARS (val) == 0 ? null_string
254 : intern_downcase ((char *) SDATA (val), SBYTES (val)));
255 else if (SYMBOLP (val))
256 {
257 if (SCHARS (SYMBOL_NAME (val)) == 0)
258 val = null_string;
259 }
260 else
261 val = Qerror;
262 return val;
263}
264
265static Lisp_Object
266font_prop_validate_style (prop, val)
267 enum font_property_index prop;
268 Lisp_Object val;
269{
270 if (! INTEGERP (val))
271 {
272 if (STRINGP (val))
273 val = intern_downcase ((char *) SDATA (val), SBYTES (val));
274 if (! SYMBOLP (val))
275 val = Qerror;
276 else
277 {
278 val = prop_name_to_numeric (prop, val);
279 if (NILP (val))
280 val = Qerror;
281 }
282 }
283 return val;
284}
285
286static Lisp_Object
287font_prop_validate_size (prop, val)
288 enum font_property_index prop;
289 Lisp_Object val;
290{
291 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
292 ? val : Qerror);
293}
294
295static Lisp_Object
296font_prop_validate_extra (prop, val)
297 enum font_property_index prop;
298 Lisp_Object val;
299{
300 Lisp_Object tail;
301
302 for (tail = val; CONSP (tail); tail = XCDR (tail))
303 {
304 Lisp_Object key = Fcar (XCAR (tail)), this_val = Fcdr (XCAR (tail));
305
306 if (NILP (this_val))
307 return Qnil;
308 if (EQ (key, QClanguage))
309 if (! SYMBOLP (this_val))
310 {
311 for (; CONSP (this_val); this_val = XCDR (this_val))
312 if (! SYMBOLP (XCAR (this_val)))
313 return Qerror;
314 if (! NILP (this_val))
315 return Qerror;
316 }
317 if (EQ (key, QCotf))
318 if (! STRINGP (this_val))
319 return Qerror;
320 }
321 return (NILP (tail) ? val : Qerror);
322}
323
324
325struct
326{
327 Lisp_Object *key;
328 Lisp_Object (*validater) P_ ((enum font_property_index prop,
329 Lisp_Object val));
330} font_property_table[FONT_SPEC_MAX] =
331 { { &QCtype, font_prop_validate_type },
332 { &QCfoundry, font_prop_validate_symbol },
333 { &QCfamily, font_prop_validate_symbol },
334 { &QCadstyle, font_prop_validate_symbol },
335 { &QCregistry, font_prop_validate_symbol },
336 { &QCweight, font_prop_validate_style },
337 { &QCslant, font_prop_validate_style },
338 { &QCwidth, font_prop_validate_style },
339 { &QCsize, font_prop_validate_size },
340 { &QCextra, font_prop_validate_extra }
341 };
342
343static enum font_property_index
344check_font_prop_name (key)
345 Lisp_Object key;
346{
347 enum font_property_index i;
348
349 for (i = FONT_TYPE_INDEX; i < FONT_SPEC_MAX; i++)
350 if (EQ (key, *font_property_table[i].key))
351 break;
352 return i;
353}
354
355static Lisp_Object
356font_prop_validate (spec)
357 Lisp_Object spec;
358{
359 enum font_property_index i;
360 Lisp_Object val;
361
362 for (i = FONT_TYPE_INDEX; i <= FONT_EXTRA_INDEX; i++)
363 {
364 if (! NILP (AREF (spec, i)))
365 {
366 val = (font_property_table[i].validater) (i, AREF (spec, i));
367 if (EQ (val, Qerror))
368 Fsignal (Qerror, list3 (build_string ("invalid font property"),
369 *font_property_table[i].key,
370 AREF (spec, i)));
371 ASET (spec, i, val);
372 }
373 }
374 return spec;
375}
376
9331887d
KH
377static void
378font_put_extra (font, prop, val, force)
379 Lisp_Object font, prop, val;
380 int force;
381{
382 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
383 Lisp_Object slot = (NILP (extra) ? Qnil : Fassq (prop, extra));
384
385 if (NILP (slot))
386 {
387 extra = Fcons (Fcons (prop, val), extra);
388 ASET (font, FONT_EXTRA_INDEX, extra);
389 return;
390 }
391 if (! NILP (XCDR (slot)) && ! force)
392 return;
393 XSETCDR (slot, val);
394 return;
395}
396
c2f5bfd6
KH
397\f
398/* Font name parser and unparser */
399
400/* An enumerator for each field of an XLFD font name. */
401
402enum xlfd_field_index
403{
404 XLFD_FOUNDRY_INDEX,
405 XLFD_FAMILY_INDEX,
406 XLFD_WEIGHT_INDEX,
407 XLFD_SLANT_INDEX,
408 XLFD_SWIDTH_INDEX,
409 XLFD_ADSTYLE_INDEX,
4485a28e
KH
410 XLFD_PIXEL_INDEX,
411 XLFD_POINT_INDEX,
c2f5bfd6
KH
412 XLFD_RESX_INDEX,
413 XLFD_RESY_INDEX,
414 XLFD_SPACING_INDEX,
415 XLFD_AVGWIDTH_INDEX,
416 XLFD_REGISTRY_INDEX,
417 XLFD_ENCODING_INDEX,
418 XLFD_LAST_INDEX
419};
420
4485a28e
KH
421enum xlfd_field_mask
422{
423 XLFD_FOUNDRY_MASK = 0x0001,
424 XLFD_FAMILY_MASK = 0x0002,
425 XLFD_WEIGHT_MASK = 0x0004,
426 XLFD_SLANT_MASK = 0x0008,
427 XLFD_SWIDTH_MASK = 0x0010,
428 XLFD_ADSTYLE_MASK = 0x0020,
429 XLFD_PIXEL_MASK = 0x0040,
430 XLFD_POINT_MASK = 0x0080,
431 XLFD_RESX_MASK = 0x0100,
432 XLFD_RESY_MASK = 0x0200,
433 XLFD_SPACING_MASK = 0x0400,
434 XLFD_AVGWIDTH_MASK = 0x0800,
435 XLFD_REGISTRY_MASK = 0x1000,
436 XLFD_ENCODING_MASK = 0x2000
437};
438
439
440/* Return a Lispy value for string at STR and bytes LEN.
c2f5bfd6
KH
441 If LEN == 0, return a null string.
442 If the string is "*", return Qnil.
443 It is assured that LEN < 256. */
444
445static Lisp_Object
4485a28e
KH
446intern_font_field (str, len)
447 char *str;
448 int len;
c2f5bfd6 449{
4485a28e 450 int i;
c2f5bfd6
KH
451
452 if (len == 0)
453 return null_string;
454 if (*str == '*' && len == 1)
455 return Qnil;
4485a28e
KH
456 if (isdigit (*str))
457 {
458 for (i = 1; i < len; i++)
459 if (! isdigit (str[i]))
460 break;
461 if (i == len)
462 return make_number (atoi (str));
463 }
c2f5bfd6
KH
464 return intern_downcase (str, len);
465}
466
467/* Parse P pointing the pixel/point size field of the form
468 `[A B C D]' which specifies a transformation matrix:
469
470 A B 0
471 C D 0
472 0 0 1
473
474 by which all glyphs of the font are transformed. The spec says
475 that scalar value N for the pixel/point size is equivalent to:
476 A = N * resx/resy, B = C = 0, D = N.
477
478 Return the scalar value N if the form is valid. Otherwise return
479 -1. */
480
481static int
482parse_matrix (p)
483 char *p;
484{
485 double matrix[4];
486 char *end;
487 int i;
488
489 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
490 {
491 if (*p == '~')
492 matrix[i] = - strtod (p + 1, &end);
493 else
494 matrix[i] = strtod (p, &end);
495 p = end;
496 }
497 return (i == 4 ? (int) matrix[3] : -1);
498}
499
4485a28e
KH
500/* Expand a wildcard field in FIELD (the first N fields are filled) to
501 multiple fields to fill in all 14 XLFD fields while restring a
502 field position by its contents. */
503
504int
505font_expand_wildcards (field, n)
506 Lisp_Object field[XLFD_LAST_INDEX];
507 int n;
508{
509 /* Copy of FIELD. */
510 Lisp_Object tmp[XLFD_LAST_INDEX];
511 /* Array of information about where this element can go. Nth
512 element is for Nth element of FIELD. */
513 struct {
514 /* Minimum possible field. */
515 int from;
516 /* Maxinum possible field. */
517 int to;
518 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
519 int mask;
520 } range[XLFD_LAST_INDEX];
521 int i, j;
522 unsigned range_mask;
523
524#define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
525 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
526#define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
4485a28e 527#define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
ef18374f 528 | XLFD_AVGWIDTH_MASK)
4485a28e
KH
529#define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
530
531 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
532 field. The value is shifted to left one bit by one in the
533 following loop. */
534 for (i = 0, range_mask = 0; i <= 14 - n; i++)
535 range_mask = (range_mask << 1) | 1;
536
537 for (i = 0; i < n; i++, range_mask <<= 1)
538 {
539 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
540 position-based retriction for FIELD[I]. */
541 int range_from = i, range_to = 14 - n + i;
542 Lisp_Object val = field[i];
543
544 tmp[i] = val;
545 if (NILP (val))
546 {
547 /* Wildcard. */
548 range[i].from = range_from;
549 range[i].to = range_to;
550 range[i].mask = range_mask;
551 }
552 else
553 {
554 /* The triplet FROM, TO, and MASK is a value-based
555 retriction for FIELD[I]. */
556 int from, to;
557 unsigned mask;
558
559 if (INTEGERP (val))
560 {
561 int numeric = XINT (val);
562
ef18374f
KH
563 if (i + 1 == n)
564 from = to = XLFD_ENCODING_INDEX,
565 mask = XLFD_ENCODING_MASK;
566 else if (numeric <= 48)
567 from = to = XLFD_PIXEL_INDEX,
568 mask = XLFD_PIXEL_MASK;
4485a28e 569 else
ef18374f 570 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_MASK,
4485a28e
KH
571 mask = XLFD_LARGENUM_MASK;
572 }
573 else if (EQ (val, null_string))
574 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
575 mask = XLFD_NULL_MASK;
576 else if (i == 0)
577 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
578 else if (i + 1 == n)
579 {
580 Lisp_Object name = SYMBOL_NAME (val);
581
582 if (SDATA (name)[SBYTES (name) - 1] == '*')
583 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
584 mask = XLFD_REGENC_MASK;
585 else
586 from = to = XLFD_ENCODING_INDEX,
587 mask = XLFD_ENCODING_MASK;
588 }
ef18374f
KH
589 else if (range_from <= XLFD_WEIGHT_INDEX
590 && range_to >= XLFD_WEIGHT_INDEX
591 && !NILP (prop_name_to_numeric (FONT_WEIGHT_INDEX, val)))
4485a28e 592 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
ef18374f
KH
593 else if (range_from <= XLFD_SLANT_INDEX
594 && range_to >= XLFD_SLANT_INDEX
595 && !NILP (prop_name_to_numeric (FONT_SLANT_INDEX, val)))
4485a28e 596 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
ef18374f
KH
597 else if (range_from <= XLFD_SWIDTH_INDEX
598 && range_to >= XLFD_SWIDTH_INDEX
599 && !NILP (prop_name_to_numeric (FONT_WIDTH_INDEX, val)))
4485a28e
KH
600 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
601 else
602 {
603 Lisp_Object name = SYMBOL_NAME (val);
604
605 if (SBYTES (name) == 1
606 && (SDATA (name)[0] == 'c'
607 || SDATA (name)[0] == 'm'
608 || SDATA (name)[0] == 'p'))
609 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
610 else
611 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
612 mask = XLFD_SYMBOL_MASK;
613 }
614
615 /* Merge position-based and value-based restrictions. */
616 mask &= range_mask;
617 while (from < range_from)
618 mask &= ~(1 << from++);
619 while (from < 14 && ! (mask & (1 << from)))
620 from++;
621 while (to > range_to)
622 mask &= ~(1 << to--);
623 while (to >= 0 && ! (mask & (1 << to)))
624 to--;
625 if (from > to)
626 return -1;
627 range[i].from = from;
628 range[i].to = to;
629 range[i].mask = mask;
630
631 if (from > range_from || to < range_to)
632 /* The range is narrowed by value-based restrictions.
633 Reflect it to the previous fields. */
634 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
635 {
636 /* Check FROM for non-wildcard field. */
637 if (! NILP (tmp[j]) && range[j].from < from)
638 {
639 while (range[j].from < from)
640 range[j].mask &= ~(1 << range[j].from++);
641 while (from < 14 && ! (range[j].mask & (1 << from)))
642 from++;
643 range[j].from = from;
644 }
645 else
646 from = range[j].from;
647 if (range[j].to > to)
648 {
649 while (range[j].to > to)
650 range[j].mask &= ~(1 << range[j].to--);
651 while (to >= 0 && ! (range[j].mask & (1 << to)))
652 to--;
653 range[j].to = to;
654 }
655 else
656 to = range[j].to;
657 if (from > to)
658 return -1;
659 }
660 }
661 }
662
663 /* Decide all fileds from restrictions in RANGE. */
664 for (i = j = 0; i < n ; i++)
665 {
666 if (j < range[i].from)
667 {
668 if (i == 0 || ! NILP (tmp[i - 1]))
669 /* None of TMP[X] corresponds to Jth field. */
670 return -1;
671 for (; j < range[i].from; j++)
672 field[j] = Qnil;
673 }
674 field[j++] = tmp[i];
675 }
676 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
677 return -1;
678 for (; j < XLFD_LAST_INDEX; j++)
679 field[j] = Qnil;
680 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
681 field[XLFD_ENCODING_INDEX]
682 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
683 return 0;
684}
685
ef18374f 686/* Parse NAME (null terminated) as XLFD and store information in FONT
9331887d
KH
687 (font-spec or font-entity). Size property of FONT is set as
688 follows:
689 specified XLFD fields FONT property
690 --------------------- -------------
691 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
692 POINT_SIZE and RESY calculated pixel size (Lisp integer)
693 POINT_SIZE POINT_SIZE/10 (Lisp float)
694
695 If NAME is successfully parsed, return 2 (size is specified), 1
696 (size is not specified), or 0 (size is not specified but resolution
697 is specified). Otherwise return -1.
698
699 See font_parse_name for more detail. */
c2f5bfd6
KH
700
701int
702font_parse_xlfd (name, font, merge)
703 char *name;
704 Lisp_Object font;
705 int merge;
706{
707 int len = strlen (name);
708 int i, j;
4485a28e 709 int pixel_size, resy, avgwidth;
c2f5bfd6 710 double point_size;
4485a28e 711 Lisp_Object f[XLFD_LAST_INDEX];
c2f5bfd6 712 Lisp_Object val;
4485a28e 713 char *p;
c2f5bfd6
KH
714
715 if (len > 255)
716 /* Maximum XLFD name length is 255. */
717 return -1;
4485a28e
KH
718 i = (name[0] == '*' && name[1] == '-');
719 for (p = name + 1; *p; p++)
720 {
721 if (*p == '-')
722 {
723 i++;
724 if (i == XLFD_ENCODING_INDEX)
725 break;
726 }
727 }
c2f5bfd6 728
4485a28e
KH
729 pixel_size = resy = avgwidth = -1;
730 point_size = -1;
731
732 if (i == XLFD_ENCODING_INDEX)
733 {
734 /* Fully specified XLFD. */
735 if (name[0] == '-')
736 name++;
737 for (i = 0, p = name; ; p++)
738 {
739 if (*p == '-')
740 {
741 if (i < XLFD_PIXEL_INDEX)
742 f[i++] = intern_font_field (name, p - name);
743 else if (i == XLFD_PIXEL_INDEX)
744 {
745 if (isdigit (*name))
746 pixel_size = atoi (name);
747 else if (*name == '[')
748 pixel_size = parse_matrix (name);
749 i++;
750 }
751 else if (i == XLFD_POINT_INDEX)
752 {
9331887d
KH
753 /* If PIXEL_SIZE is specified, we don't have to
754 calculate POINT_SIZE. */
4485a28e
KH
755 if (pixel_size < 0)
756 {
757 if (isdigit (*name))
758 point_size = atoi (name);
759 else if (*name == '[')
760 point_size = parse_matrix (name);
761 }
762 i++;
763 }
764 else if (i == XLFD_RESX_INDEX)
765 {
766 /* Skip this field. */
767 f[i++] = Qnil;
768 }
769 else if (i == XLFD_RESY_INDEX)
770 {
771 /* Stuff RESY, SPACING, and AVGWIDTH. */
9331887d
KH
772 /* If PIXEL_SIZE is specified, we don't have to
773 calculate RESY. */
4485a28e
KH
774 if (pixel_size < 0 && isdigit (*name))
775 resy = atoi (name);
776 for (p++; *p != '-'; p++);
777 if (isdigit (p[1]))
778 avgwidth = atoi (p + 1);
779 else if (p[1] == '~' && isdigit (p[2]))
780 avgwidth = atoi (p + 2);
781 for (p++; *p != '-'; p++);
782 if (FONT_ENTITY_P (font))
783 f[i] = intern_font_field (name, p - name);
784 else
785 f[i] = Qnil;
786 i = XLFD_REGISTRY_INDEX;
787 }
788 else
789 {
790 /* Stuff REGISTRY and ENCODING. */
791 for (p++; *p; p++);
792 f[i++] = intern_font_field (name, p - name);
793 break;
794 }
795 name = p + 1;
796 }
797 }
798 xassert (i == XLFD_ENCODING_INDEX);
799 }
800 else
c2f5bfd6 801 {
4485a28e
KH
802 int wild_card_found = 0;
803
804 if (name[0] == '-')
805 name++;
806 for (i = 0, p = name; ; p++)
807 {
808 if (*p == '-' || ! *p)
809 {
810 if (*name == '*')
811 {
812 if (name + 1 != p)
813 return -1;
814 f[i++] = Qnil;
815 wild_card_found = 1;
816 }
817 else if (isdigit (*name))
818 {
819 f[i++] = make_number (atoi (name));
820 /* Check if all chars in this field is number. */
821 name++;
822 while (isdigit (*name)) name++;
823 if (name != p)
824 return -1;
825 }
826 else if (p == name)
827 f[i++] = null_string;
828 else
829 {
830 f[i++] = intern_downcase (name, p - name);
831 }
832 if (! *p)
833 break;
834 name = p + 1;
835 }
836 }
837 if (! wild_card_found)
c2f5bfd6 838 return -1;
4485a28e
KH
839 if (font_expand_wildcards (f, i) < 0)
840 return -1;
841 if (! NILP (f[XLFD_PIXEL_INDEX]))
842 pixel_size = XINT (f[XLFD_PIXEL_INDEX]);
9331887d
KH
843 /* If PIXEL_SIZE is specified, we don't have to
844 calculate POINT_SIZE and RESY. */
845 if (pixel_size < 0)
846 {
847 if (! NILP (f[XLFD_POINT_INDEX]))
848 point_size = XINT (f[XLFD_POINT_INDEX]);
849 if (! NILP (f[XLFD_RESY_INDEX]))
850 resy = XINT (f[XLFD_RESY_INDEX]);
851 }
4485a28e
KH
852 if (! NILP (f[XLFD_AVGWIDTH_INDEX]))
853 avgwidth = XINT (f[XLFD_AVGWIDTH_INDEX]);
854 if (NILP (f[XLFD_REGISTRY_INDEX]))
c2f5bfd6 855 {
4485a28e
KH
856 if (! NILP (f[XLFD_ENCODING_INDEX]))
857 f[XLFD_REGISTRY_INDEX]
858 = Fintern (concat2 (build_string ("*-"),
859 SYMBOL_NAME (f[XLFD_ENCODING_INDEX])), Qnil);
860 }
861 else
862 {
863 if (! NILP (f[XLFD_ENCODING_INDEX]))
864 f[XLFD_REGISTRY_INDEX]
865 = Fintern (concat2 (SYMBOL_NAME (f[XLFD_REGISTRY_INDEX]),
866 SYMBOL_NAME (f[XLFD_ENCODING_INDEX])), Qnil);
c2f5bfd6
KH
867 }
868 }
c2f5bfd6
KH
869
870 if (! merge || NILP (AREF (font, FONT_FOUNDRY_INDEX)))
4485a28e 871 ASET (font, FONT_FOUNDRY_INDEX, f[XLFD_FOUNDRY_INDEX]);
c2f5bfd6 872 if (! merge || NILP (AREF (font, FONT_FAMILY_INDEX)))
4485a28e 873 ASET (font, FONT_FAMILY_INDEX, f[XLFD_FAMILY_INDEX]);
c2f5bfd6 874 if (! merge || NILP (AREF (font, FONT_ADSTYLE_INDEX)))
4485a28e 875 ASET (font, FONT_ADSTYLE_INDEX, f[XLFD_ADSTYLE_INDEX]);
c2f5bfd6 876 if (! merge || NILP (AREF (font, FONT_REGISTRY_INDEX)))
4485a28e 877 ASET (font, FONT_REGISTRY_INDEX, f[XLFD_REGISTRY_INDEX]);
c2f5bfd6
KH
878
879 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX;
880 j <= XLFD_SWIDTH_INDEX; i++, j++)
881 if (! merge || NILP (AREF (font, i)))
882 {
4485a28e 883 if (! INTEGERP (f[j]))
c2f5bfd6 884 {
4485a28e
KH
885 val = prop_name_to_numeric (i, f[j]);
886 if (INTEGERP (val))
887 f[j] = val;
c2f5bfd6 888 }
4485a28e 889 ASET (font, i, f[j]);
c2f5bfd6
KH
890 }
891
c2f5bfd6
KH
892 if (pixel_size < 0 && FONT_ENTITY_P (font))
893 return -1;
894
c2f5bfd6
KH
895 if (! merge || NILP (AREF (font, FONT_SIZE_INDEX)))
896 {
897 if (pixel_size >= 0)
898 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
4485a28e 899 else if (point_size >= 0)
9331887d 900 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
c2f5bfd6
KH
901 }
902
9331887d
KH
903 if (FONT_ENTITY_P (font))
904 {
905 if (EQ (AREF (font, FONT_TYPE_INDEX), Qx))
906 ASET (font, FONT_EXTRA_INDEX, f[XLFD_RESY_INDEX]);
907 }
908 else if (resy >= 0)
909 font_put_extra (font, QCdpi, make_number (resy), merge);
c2f5bfd6 910
4485a28e 911 return (avgwidth > 0 ? 2 : resy == 0);
c2f5bfd6
KH
912}
913
914/* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
915 length), and return the name length. If FONT_SIZE_INDEX of FONT is
916 0, use PIXEL_SIZE instead. */
917
918int
919font_unparse_xlfd (font, pixel_size, name, nbytes)
920 Lisp_Object font;
1bb1d99b 921 int pixel_size;
c2f5bfd6
KH
922 char *name;
923 int nbytes;
924{
925 char *f[XLFD_REGISTRY_INDEX + 1], *pixel_point;
926 char work[256];
927 Lisp_Object val;
928 int i, j, len = 0;
929
930 xassert (FONTP (font));
931
932 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
933 i++, j++)
934 {
935 if (i == FONT_ADSTYLE_INDEX)
936 j = XLFD_ADSTYLE_INDEX;
937 else if (i == FONT_REGISTRY_INDEX)
938 j = XLFD_REGISTRY_INDEX;
939 val = AREF (font, i);
940 if (NILP (val))
1bb1d99b
KH
941 {
942 if (j == XLFD_REGISTRY_INDEX)
943 f[j] = "*-*", len += 4;
944 else
945 f[j] = "*", len += 2;
946 }
c2f5bfd6
KH
947 else
948 {
949 if (SYMBOLP (val))
950 val = SYMBOL_NAME (val);
1bb1d99b
KH
951 if (j == XLFD_REGISTRY_INDEX
952 && ! strchr ((char *) SDATA (val), '-'))
953 {
954 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
955 if (SDATA (val)[SBYTES (val) - 1] == '*')
956 {
957 f[j] = alloca (SBYTES (val) + 3);
958 sprintf (f[j], "%s-*", SDATA (val));
959 len += SBYTES (val) + 3;
960 }
961 else
962 {
963 f[j] = alloca (SBYTES (val) + 4);
964 sprintf (f[j], "%s*-*", SDATA (val));
965 len += SBYTES (val) + 4;
966 }
967 }
968 else
969 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
c2f5bfd6
KH
970 }
971 }
972
973 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
974 i++, j++)
975 {
976 val = AREF (font, i);
977 if (NILP (val))
978 f[j] = "*", len += 2;
979 else
980 {
981 if (INTEGERP (val))
982 val = prop_numeric_to_name (i, XINT (val));
983 if (SYMBOLP (val))
984 val = SYMBOL_NAME (val);
985 xassert (STRINGP (val));
986 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
987 }
988 }
989
990 val = AREF (font, FONT_SIZE_INDEX);
991 xassert (NUMBERP (val) || NILP (val));
992 if (INTEGERP (val))
993 {
994 i = XINT (val);
995 if (i > 0)
9331887d 996 len += sprintf (work, "%d-*", i) + 1;
c2f5bfd6
KH
997 else /* i == 0 */
998 len += sprintf (work, "%d-*", pixel_size) + 1;
999 pixel_point = work;
1000 }
1001 else if (FLOATP (val))
1002 {
1003 i = XFLOAT_DATA (val) * 10;
1004 len += sprintf (work, "*-%d", i) + 1;
1005 pixel_point = work;
1006 }
1007 else
1008 pixel_point = "*-*", len += 4;
1009
1010 if (FONT_ENTITY_P (font)
1011 && EQ (AREF (font, FONT_TYPE_INDEX), Qx))
1012 {
1013 /* Setup names for RESY-SPACING-AVWIDTH. */
1014 val = AREF (font, FONT_EXTRA_INDEX);
1015 if (SYMBOLP (val) && ! NILP (val))
1016 {
1017 val = SYMBOL_NAME (val);
1018 f[XLFD_RESY_INDEX] = (char *) SDATA (val), len += SBYTES (val) + 1;
1019 }
1020 else
1021 f[XLFD_RESY_INDEX] = "*-*-*", len += 6;
1022 }
1023 else
1024 f[XLFD_RESY_INDEX] = "*-*-*", len += 6;
1025
1026 len += 3; /* for "-*" of resx, and terminating '\0'. */
1027 if (len >= nbytes)
1028 return -1;
1029 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-*-%s-%s",
1030 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1031 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1032 f[XLFD_SWIDTH_INDEX],
1033 f[XLFD_ADSTYLE_INDEX], pixel_point,
1034 f[XLFD_RESY_INDEX], f[XLFD_REGISTRY_INDEX]);
1035}
1036
ef18374f 1037/* Parse NAME (null terminated) as Fonconfig's name format and store
9331887d
KH
1038 information in FONT (font-spec or font-entity). If NAME is
1039 successfully parsed, return 0. Otherwise return -1. */
ef18374f
KH
1040
1041int
1042font_parse_fcname (name, font, merge)
1043 char *name;
1044 Lisp_Object font;
1045 int merge;
1046{
1047 char *p0, *p1;
1048 Lisp_Object family = Qnil;
1049 double point_size = 0;
1050 int pixel_size = 0;
1051 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
9331887d
KH
1052 int len = strlen (name);
1053 char *copy;
ef18374f
KH
1054
1055 /* It is assured that (name[0] && name[0] != '-'). */
1056 if (name[0] == ':')
1057 p0 = name;
1058 else
1059 {
1060 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++);
a9262bb8
KH
1061 if (isdigit (name[0]) && *p0 != '-')
1062 point_size = strtod (name, NULL);
1063 else
ef18374f 1064 {
a9262bb8
KH
1065 family = intern_font_field (name, p0 - name);
1066 if (*p0 == '-')
1067 {
1068 point_size = strtod (p0 + 1, &p1);
1069 if (*p1 && *p1 != ':')
1070 return -1;
1071 p0 = p1;
1072 }
ef18374f
KH
1073 }
1074 if (! merge || NILP (AREF (font, FONT_FAMILY_INDEX)))
1075 ASET (font, FONT_FAMILY_INDEX, family);
1076 }
9331887d
KH
1077
1078 len -= p0 - name;
1079 copy = alloca (len + 1);
1080 if (! copy)
1081 return -1;
1082 name = copy;
1083
1084 /* Now parse ":KEY=VAL" patterns. Store known keys and values in
1085 extra, copy unknown ones to COPY. */
ef18374f
KH
1086 while (*p0)
1087 {
1088 Lisp_Object key, val;
1089 enum font_property_index prop;
1090
9331887d
KH
1091 for (p1 = p0 + 1; islower (*p1); p1++);
1092 if (*p1 != '=')
ef18374f 1093 {
9331887d
KH
1094 /* Must be an enumerated value. */
1095 val = intern_font_field (p0 + 1, p1 - p0 - 1);
1096
1097 if (memcmp (p0 + 1, "light", 5) == 0
1098 || memcmp (p0 + 1, "medium", 6) == 0
1099 || memcmp (p0 + 1, "demibold", 8) == 0
1100 || memcmp (p0 + 1, "bold", 4) == 0
1101 || memcmp (p0 + 1, "black", 5) == 0)
1102 {
1103 if (! merge || NILP (AREF (font, FONT_WEIGHT_INDEX)))
1104 ASET (font, FONT_WEIGHT_INDEX,
1105 prop_name_to_numeric (FONT_WEIGHT_INDEX, val));
1106 }
1107 else if (memcmp (p0 + 1, "roman", 5) == 0
1108 || memcmp (p0 + 1, "italic", 6) == 0
1109 || memcmp (p0 + 1, "oblique", 7) == 0)
1110 {
1111 if (! merge || NILP (AREF (font, FONT_SLANT_INDEX)))
1112 ASET (font, FONT_SLANT_INDEX,
1113 prop_name_to_numeric (FONT_SLANT_INDEX, val));
1114 }
1115 else if (memcmp (p0 + 1, "charcell", 8) == 0
1116 || memcmp (p0 + 1, "mono", 4) == 0
1117 || memcmp (p0 + 1, "proportional", 12) == 0)
1118 {
1119 font_put_extra (font, QCspacing,
1120 p0[1] == 'c' ? make_number (FONT_SPACING_CHARCELL)
1121 : p0[1] == 'm' ? make_number (FONT_SPACING_MONO)
1122 : make_number (FONT_SPACING_PROPORTIONAL),
1123 merge);
1124 }
1125 else
1126 {
1127 /* unknown key */
1128 bcopy (p0, copy, p1 - p0);
1129 copy += p1 - p0;
1130 }
ef18374f
KH
1131 }
1132 else
1133 {
f522f828
KH
1134 char *pbeg = p0;
1135
9331887d
KH
1136 if (memcmp (p0 + 1, "pixelsize=", 10) == 0)
1137 prop = FONT_SIZE_INDEX;
1138 else
1139 {
1140 key = intern_font_field (p0, p1 - p0);
1141 prop = check_font_prop_name (key);
1142 }
1143 p0 = p1 + 1;
1144 for (p1 = p0; *p1 && *p1 != ':'; p1++);
1145 if (prop == FONT_SIZE_INDEX)
1146 {
1147 pixel_size = atoi (p0);
1148 }
1149 else if (prop < FONT_EXTRA_INDEX)
ef18374f
KH
1150 {
1151 if (! merge || NILP (AREF (font, prop)))
1152 {
9331887d
KH
1153 val = intern_font_field (p0, p1 - p0);
1154 if (prop >= FONT_WEIGHT_INDEX && prop <= FONT_WIDTH_INDEX)
1155 val = font_property_table[prop].validater (prop, val);
ef18374f
KH
1156 if (! EQ (val, Qerror))
1157 ASET (font, prop, val);
1158 }
1159 }
9331887d
KH
1160 else if (EQ (key, QCdpi))
1161 {
1162 if (INTEGERP (val))
1163 font_put_extra (font, key, val, merge);
1164 }
ef18374f
KH
1165 else
1166 {
9331887d 1167 /* unknown key */
f522f828
KH
1168 bcopy (pbeg, copy, p1 - pbeg);
1169 copy += p1 - pbeg;
ef18374f
KH
1170 }
1171 }
1172 p0 = p1;
1173 }
9331887d 1174
ef18374f
KH
1175 if (! merge || NILP (AREF (font, FONT_SIZE_INDEX)))
1176 {
9331887d 1177 if (pixel_size > 0)
ef18374f 1178 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
9331887d
KH
1179 else if (point_size > 0)
1180 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
ef18374f 1181 }
9331887d
KH
1182 if (name < copy)
1183 font_put_extra (font, QCname, make_unibyte_string (name, copy - name),
1184 merge);
ef18374f 1185
9331887d 1186 return 0;
ef18374f
KH
1187}
1188
1189/* Store fontconfig's font name of FONT (font-spec or font-entity) in
1190 NAME (NBYTES length), and return the name length. If
1191 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1192
1193int
1194font_unparse_fcname (font, pixel_size, name, nbytes)
1195 Lisp_Object font;
1196 int pixel_size;
1197 char *name;
1198 int nbytes;
1199{
1200 Lisp_Object val, size;
1201 int pt = 0;
1202 int i, j, len = 1;
1203 char *p;
a9262bb8
KH
1204 Lisp_Object styles[3];
1205 char *style_names[3] = { "weight", "slant", "swidth" };
ef18374f
KH
1206
1207 if (SYMBOLP (AREF (font, FONT_FAMILY_INDEX))
1208 && ! NILP (AREF (font, FONT_FAMILY_INDEX)))
1209 len += SBYTES (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX)));
1210 size = AREF (font, FONT_SIZE_INDEX);
1211 if (INTEGERP (size))
1212 {
1213 if (XINT (size) > 0)
1214 pixel_size = XINT (size);
1215 if (pixel_size > 0)
1216 len += 21; /* for ":pixelsize=NUM" */
1217 }
1218 else if (FLOATP (size))
1219 {
1220 pt = (int) XFLOAT_DATA (size);
1221 if (pt > 0)
1222 len += 11; /* for "-NUM" */
1223 }
1224 if (SYMBOLP (AREF (font, FONT_FOUNDRY_INDEX))
1225 && ! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1226 /* ":foundry=NAME" */
1227 len += 9 + SBYTES (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX)));
a9262bb8
KH
1228 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
1229 {
1230 val = AREF (font, i);
1231 if (INTEGERP (val))
1232 {
1233 val = prop_numeric_to_name (i, XINT (val));
1234 len += (strlen (style_names[i - FONT_WEIGHT_INDEX])
1235 + 2 + SBYTES (SYMBOL_NAME (val))); /* :xxx=NAME */
1236 }
1237 styles[i - FONT_WEIGHT_INDEX] = val;
1238 }
ef18374f
KH
1239 if (len > nbytes)
1240 return -1;
1241 p = name;
1242 if (! NILP (AREF (font, FONT_FAMILY_INDEX)))
a9262bb8
KH
1243 p += sprintf(p, "%s",
1244 SDATA (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX))));
ef18374f
KH
1245 if (pt > 0)
1246 p += sprintf (p, "-%d", pt);
1247 else if (pixel_size > 0)
1248 p += sprintf (p, ":pixelsize=%d", pixel_size);
a9262bb8
KH
1249 if (SYMBOLP (AREF (font, FONT_FOUNDRY_INDEX))
1250 && ! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1251 p += sprintf (p, ":foundry=%s",
1252 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1253 for (i = 0; i < 3; i++)
1254 if (! NILP (styles [i]))
1255 p += sprintf (p, ":%s=%s", style_names[i],
1256 SDATA (SYMBOL_NAME (styles [i])));
ef18374f
KH
1257 return (p - name);
1258}
1259
1260/* Parse NAME (null terminated) and store information in FONT
1261 (font-spec or font-entity). If NAME is successfully parsed, return
9331887d 1262 a non-negative value. Otherwise return -1.
ef18374f
KH
1263
1264 If NAME is XLFD and FONT is a font-entity, store
1265 RESY-SPACING-AVWIDTH information as a symbol in FONT_EXTRA_INDEX.
1266
1267 If MERGE is nonzero, set a property of FONT only when it's nil. */
1268
1269static int
1270font_parse_name (name, font, merge)
1271 char *name;
1272 Lisp_Object font;
1273 int merge;
1274{
1275 if (name[0] == '-' || index (name, '*'))
1276 return font_parse_xlfd (name, font, merge);
1277 if (name[0])
1278 return font_parse_fcname (name, font, merge);
1279 return -1;
1280}
1281
c2f5bfd6
KH
1282void
1283font_merge_old_spec (name, family, registry, spec)
1284 Lisp_Object name, family, registry, spec;
1285{
1286 if (STRINGP (name))
1287 {
1288 if (font_parse_xlfd ((char *) SDATA (name), spec, 1) < 0)
1289 {
1290 Lisp_Object extra = Fcons (Fcons (QCname, name), Qnil);
1291
1292 ASET (spec, FONT_EXTRA_INDEX, extra);
1293 }
1294 }
1295 else
1296 {
1297 if (! NILP (family))
1298 {
1299 int len;
1300 char *p0, *p1;
1301
1302 xassert (STRINGP (family));
1303 len = SBYTES (family);
1304 p0 = (char *) SDATA (family);
1305 p1 = index (p0, '-');
1306 if (p1)
1307 {
1308 if (NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
1309 ASET (spec, FONT_FOUNDRY_INDEX,
1310 intern_downcase (p0, p1 - p0));
1311 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1312 ASET (spec, FONT_FAMILY_INDEX,
1313 intern_downcase (p1 + 1, len - (p1 + 1 - p0)));
1314 }
1315 else if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1316 ASET (spec, FONT_FAMILY_INDEX, intern_downcase (p0, len));
1317 }
1318 if (! NILP (registry)
1319 && NILP (AREF (spec, FONT_REGISTRY_INDEX)))
1320 ASET (spec, FONT_REGISTRY_INDEX,
1321 intern_downcase ((char *) SDATA (registry), SBYTES (registry)));
1322 }
1323}
1324
1325\f
1326/* OTF handler */
1327
1328#ifdef HAVE_LIBOTF
1329#include <otf.h>
1330
1331struct otf_list
1332{
1333 Lisp_Object entity;
1334 OTF *otf;
1335 struct otf_list *next;
1336};
1337
1338static struct otf_list *otf_list;
1339
1340static Lisp_Object
1341otf_tag_symbol (tag)
1342 OTF_Tag tag;
1343{
1344 char name[5];
1345
1346 OTF_tag_name (tag, name);
1347 return Fintern (make_unibyte_string (name, 4), Qnil);
1348}
1349
1350static OTF *
1351otf_open (entity, file)
1352 Lisp_Object entity;
1353 char *file;
1354{
1355 struct otf_list *list = otf_list;
1356
1357 while (list && ! EQ (list->entity, entity))
1358 list = list->next;
1359 if (! list)
1360 {
1361 list = malloc (sizeof (struct otf_list));
1362 list->entity = entity;
1363 list->otf = file ? OTF_open (file) : NULL;
1364 list->next = otf_list;
1365 otf_list = list;
1366 }
1367 return list->otf;
1368}
1369
1370
1371/* Return a list describing which scripts/languages FONT supports by
1372 which GSUB/GPOS features of OpenType tables. See the comment of
1373 (sturct font_driver).otf_capability. */
1374
1375Lisp_Object
1376font_otf_capability (font)
1377 struct font *font;
1378{
1379 OTF *otf;
1380 Lisp_Object capability = Fcons (Qnil, Qnil);
1381 int i;
1382
1383 otf = otf_open (font->entity, font->file_name);
1384 if (! otf)
1385 return Qnil;
1386 for (i = 0; i < 2; i++)
1387 {
1388 OTF_GSUB_GPOS *gsub_gpos;
1389 Lisp_Object script_list = Qnil;
1390 int j;
1391
1392 if (OTF_get_features (otf, i == 0) < 0)
1393 continue;
1394 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1395 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1396 {
1397 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1398 Lisp_Object langsys_list = Qnil;
1399 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1400 int k;
1401
1402 for (k = script->LangSysCount; k >= 0; k--)
1403 {
1404 OTF_LangSys *langsys;
1405 Lisp_Object feature_list = Qnil;
1406 Lisp_Object langsys_tag;
1407 int l;
1408
1409 if (j == script->LangSysCount)
1410 {
1411 langsys = &script->DefaultLangSys;
1412 langsys_tag = Qnil;
1413 }
1414 else
1415 {
1416 langsys = script->LangSys + k;
1417 langsys_tag
1418 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
1419 }
1420 for (l = langsys->FeatureCount -1; l >= 0; l--)
1421 {
1422 OTF_Feature *feature
1423 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
1424 Lisp_Object feature_tag
1425 = otf_tag_symbol (feature->FeatureTag);
1426
1427 feature_list = Fcons (feature_tag, feature_list);
1428 }
1429 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1430 langsys_list);
1431 }
1432 script_list = Fcons (Fcons (script_tag, langsys_list),
1433 script_list);
1434 }
1435
1436 if (i == 0)
1437 XSETCAR (capability, script_list);
1438 else
1439 XSETCDR (capability, script_list);
1440 }
1441
1442 return capability;
1443}
1444
1445static int
1446parse_gsub_gpos_spec (spec, script, langsys, features)
1447 Lisp_Object spec;
1448 char **script, **langsys, **features;
1449{
1450 Lisp_Object val;
1451 int len;
1452 char *p;
1453 int asterisk;
1454
1455 val = XCAR (spec);
1456 *script = (char *) SDATA (SYMBOL_NAME (val));
1457 spec = XCDR (spec);
1458 val = XCAR (spec);
1459 *langsys = NILP (val) ? NULL : (char *) SDATA (SYMBOL_NAME (val));
1460 spec = XCDR (spec);
1461 len = XINT (Flength (spec));
1462 *features = p = malloc (6 * len);
1463 if (! p)
1464 return -1;
1465
1466 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
1467 {
1468 val = XCAR (spec);
1469 if (SREF (SYMBOL_NAME (val), 0) == '*')
1470 {
1471 asterisk = 1;
1472 p += sprintf (p, ",*");
1473 }
1474 else if (! asterisk)
1475 p += sprintf (p, ",%s", SDATA (SYMBOL_NAME (val)));
1476 else
1477 p += sprintf (p, ",~%s", SDATA (SYMBOL_NAME (val)));
1478 }
1479 return 0;
1480}
1481
1482#define DEVICE_DELTA(table, size) \
1483 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1484 ? (table).DeltaValue[(size) >= (table).StartSize] \
1485 : 0)
1486
1487void
1488adjust_anchor (struct font *font, OTF_Anchor *anchor,
1489 unsigned code, int size, int *x, int *y)
1490{
1491 if (anchor->AnchorFormat == 2)
1492 {
1493 int x0, y0;
1494
1495 if (font->driver->anchor_point (font, code, anchor->f.f1.AnchorPoint,
1496 &x0, &y0) >= 0)
1497 *x = x0, *y = y0;
1498 }
1499 else if (anchor->AnchorFormat == 3)
1500 {
1501 if (anchor->f.f2.XDeviceTable.offset)
1502 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size);
1503 if (anchor->f.f2.YDeviceTable.offset)
1504 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size);
1505 }
1506}
1507
1508
1509/* Drive FONT's OTF GSUB features according to GSUB_SPEC. See the
1510 comment of (sturct font_driver).otf_gsub. */
1511
1512int
1513font_otf_gsub (font, gsub_spec, gstring_in, from, to, gstring_out, idx)
1514 struct font *font;
1515 Lisp_Object gsub_spec;
1516 Lisp_Object gstring_in;
1517 int from, to;
1518 Lisp_Object gstring_out;
1519 int idx;
1520{
1521 int len;
1522 int i;
1523 OTF *otf;
1524 OTF_GlyphString otf_gstring;
1525 OTF_Glyph *g;
1526 char *script, *langsys, *features;
1527
1528 otf = otf_open (font->entity, font->file_name);
1529 if (! otf)
1530 return 0;
1531 if (OTF_get_table (otf, "head") < 0)
1532 return 0;
1533 if (OTF_check_table (otf, "GSUB") < 0)
1534 return 0;
1535 if (parse_gsub_gpos_spec (gsub_spec, &script, &langsys, &features) < 0)
1536 return 0;
1537 len = to - from;
1538 otf_gstring.size = otf_gstring.used = len;
1539 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
1540 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
1541 for (i = 0; i < len; i++)
1542 {
1543 Lisp_Object g = LGSTRING_GLYPH (gstring_in, from + i);
1544
1545 otf_gstring.glyphs[i].c = XINT (LGLYPH_CHAR (g));
1546 otf_gstring.glyphs[i].glyph_id = XINT (LGLYPH_CODE (g));
1547 }
1548
1549 OTF_drive_gdef (otf, &otf_gstring);
1550 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, features) < 0)
1551 {
1552 free (otf_gstring.glyphs);
1553 return 0;
1554 }
1555 if (ASIZE (gstring_out) < idx + otf_gstring.used)
1556 {
1557 free (otf_gstring.glyphs);
1558 return -1;
1559 }
1560
1561 for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used;)
1562 {
1563 int i0 = g->f.index.from, i1 = g->f.index.to;
1564 Lisp_Object glyph = LGSTRING_GLYPH (gstring_in, from + i0);
1565 Lisp_Object min_idx = AREF (glyph, 0);
1566 Lisp_Object max_idx = AREF (glyph, 1);
1567
1568 if (i0 < i1)
1569 {
1570 int min_idx_i = XINT (min_idx), max_idx_i = XINT (max_idx);
1571
1572 for (i0++; i0 <= i1; i0++)
1573 {
1574 glyph = LGSTRING_GLYPH (gstring_in, from + i0);
1575 if (min_idx_i > XINT (AREF (glyph, 0)))
1576 min_idx_i = XINT (AREF (glyph, 0));
1577 if (max_idx_i < XINT (AREF (glyph, 1)))
1578 max_idx_i = XINT (AREF (glyph, 1));
1579 }
1580 min_idx = make_number (min_idx_i);
1581 max_idx = make_number (max_idx_i);
1582 i0 = g->f.index.from;
1583 }
1584 for (; i < otf_gstring.used && g->f.index.from == i0; i++, g++)
1585 {
1586 glyph = LGSTRING_GLYPH (gstring_out, idx + i);
1587 ASET (glyph, 0, min_idx);
1588 ASET (glyph, 1, max_idx);
1589 LGLYPH_SET_CHAR (glyph, make_number (g->c));
1590 LGLYPH_SET_CODE (glyph, make_number (g->glyph_id));
1591 }
1592 }
1593
1594 free (otf_gstring.glyphs);
1595 return i;
1596}
1597
1598/* Drive FONT's OTF GPOS features according to GPOS_SPEC. See the
1599 comment of (sturct font_driver).otf_gpos. */
1600
1601int
1602font_otf_gpos (font, gpos_spec, gstring, from, to)
1603 struct font *font;
1604 Lisp_Object gpos_spec;
1605 Lisp_Object gstring;
1606 int from, to;
1607{
1608 int len;
1609 int i;
1610 OTF *otf;
1611 OTF_GlyphString otf_gstring;
1612 OTF_Glyph *g;
1613 char *script, *langsys, *features;
1614 Lisp_Object glyph;
1615 int u, size;
1616 Lisp_Object base, mark;
1617
1618 otf = otf_open (font->entity, font->file_name);
1619 if (! otf)
1620 return 0;
1621 if (OTF_get_table (otf, "head") < 0)
1622 return 0;
1623 if (OTF_check_table (otf, "GPOS") < 0)
1624 return 0;
1625 if (parse_gsub_gpos_spec (gpos_spec, &script, &langsys, &features) < 0)
1626 return 0;
1627 len = to - from;
1628 otf_gstring.size = otf_gstring.used = len;
1629 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
1630 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
1631 for (i = 0; i < len; i++)
1632 {
1633 glyph = LGSTRING_GLYPH (gstring, from + i);
1634 otf_gstring.glyphs[i].glyph_id = XINT (LGLYPH_CODE (glyph));
1635 }
1636
1637 OTF_drive_gdef (otf, &otf_gstring);
1638
1639 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, features) < 0)
1640 {
1641 free (otf_gstring.glyphs);
1642 return 0;
1643 }
1644
1645 u = otf->head->unitsPerEm;
1646 size = font->pixel_size;
1647 base = mark = Qnil;
1648 for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used; i++, g++)
1649 {
1650 Lisp_Object prev;
1651 int xoff = 0, yoff = 0, width_adjust = 0;
1652
1653 if (! g->glyph_id)
1654 continue;
1655
1656 glyph = LGSTRING_GLYPH (gstring, from + i);
1657 switch (g->positioning_type)
1658 {
1659 case 0:
1660 break;
1661 case 1: case 2:
1662 {
1663 int format = g->f.f1.format;
1664
1665 if (format & OTF_XPlacement)
1666 xoff = g->f.f1.value->XPlacement * size / u;
1667 if (format & OTF_XPlaDevice)
1668 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, size);
1669 if (format & OTF_YPlacement)
1670 yoff = - (g->f.f1.value->YPlacement * size / u);
1671 if (format & OTF_YPlaDevice)
1672 yoff -= DEVICE_DELTA (g->f.f1.value->YPlaDevice, size);
1673 if (format & OTF_XAdvance)
1674 width_adjust += g->f.f1.value->XAdvance * size / u;
1675 if (format & OTF_XAdvDevice)
1676 width_adjust += DEVICE_DELTA (g->f.f1.value->XAdvDevice, size);
1677 }
1678 break;
1679 case 3:
1680 /* Not yet supported. */
1681 break;
1682 case 4: case 5:
1683 if (NILP (base))
1684 break;
1685 prev = base;
1686 goto label_adjust_anchor;
1687 default: /* i.e. case 6 */
1688 if (NILP (mark))
1689 break;
1690 prev = mark;
1691
1692 label_adjust_anchor:
1693 {
1694 int base_x, base_y, mark_x, mark_y, width;
1695 unsigned code;
1696
1697 base_x = g->f.f4.base_anchor->XCoordinate * size / u;
1698 base_y = g->f.f4.base_anchor->YCoordinate * size / u;
1699 mark_x = g->f.f4.mark_anchor->XCoordinate * size / u;
1700 mark_y = g->f.f4.mark_anchor->YCoordinate * size / u;
1701
1702 code = XINT (LGLYPH_CODE (prev));
1703 if (g->f.f4.base_anchor->AnchorFormat != 1)
1704 adjust_anchor (font, g->f.f4.base_anchor,
1705 code, size, &base_x, &base_y);
1706 if (g->f.f4.mark_anchor->AnchorFormat != 1)
1707 adjust_anchor (font, g->f.f4.mark_anchor,
1708 code, size, &mark_x, &mark_y);
1709
1710 if (NILP (LGLYPH_WIDTH (prev)))
1711 {
1712 width = font->driver->text_extents (font, &code, 1, NULL);
1713 LGLYPH_SET_WIDTH (prev, make_number (width));
1714 }
1715 xoff = XINT (LGLYPH_XOFF (prev)) + (base_x - width) - mark_x;
1716 yoff = XINT (LGLYPH_YOFF (prev)) + mark_y - base_y;
1717 }
1718 }
1719 if (g->GlyphClass == OTF_GlyphClass0)
1720 base = mark = glyph;
1721 else if (g->GlyphClass == OTF_GlyphClassMark)
1722 mark = glyph;
1723 else
1724 base = glyph;
1725
1726 LGLYPH_SET_XOFF (glyph, make_number (xoff));
1727 LGLYPH_SET_YOFF (glyph, make_number (yoff));
1728 LGLYPH_SET_WADJUST (glyph, make_number (width_adjust));
1729 }
1730
1731 free (otf_gstring.glyphs);
1732 return 0;
1733}
1734
1735#endif /* HAVE_LIBOTF */
1736
1737\f
1738/* glyph-string handler */
1739
1740/* GSTRING is a vector of this form:
1741 [ [FONT-OBJECT LBEARING RBEARING WITH ASCENT DESCENT] GLYPH ... ]
1742 and GLYPH is a vector of this form:
1743 [ FROM-IDX TO-IDX C CODE X-OFF Y-OFF WIDTH WADJUST ]
1744 where
1745 FROM-IDX and TO-IDX are used internally and should not be touched.
1746 C is a character of the glyph.
1747 CODE is a glyph-code of C in FONT-OBJECT.
1748 X-OFF and Y-OFF are offests to the base position for the glyph.
1749 WIDTH is a normal width of the glyph.
1750 WADJUST is an adjustment to the normal width of the glyph. */
1751
1752struct font *
1753font_prepare_composition (cmp)
1754 struct composition *cmp;
1755{
1756 Lisp_Object gstring
1757 = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
1758 cmp->hash_index * 2);
1759 struct font *font = XSAVE_VALUE (LGSTRING_FONT (gstring))->pointer;
1760 int len = LGSTRING_LENGTH (gstring);
1761 int i;
1762
1763 cmp->font = font;
1764 cmp->lbearing = cmp->rbearing = cmp->pixel_width = 0;
1765 cmp->ascent = font->ascent;
1766 cmp->descent = font->descent;
1767
1768 for (i = 0; i < len; i++)
1769 {
1770 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
1771 unsigned code = XINT (LGLYPH_CODE (g));
1772 struct font_metrics metrics;
1773
1774 font->driver->text_extents (font, &code, 1, &metrics);
1775 LGLYPH_SET_WIDTH (g, make_number (metrics.width));
1776 metrics.lbearing += XINT (LGLYPH_XOFF (g));
1777 metrics.rbearing += XINT (LGLYPH_XOFF (g));
1778 metrics.ascent += XINT (LGLYPH_YOFF (g));
1779 metrics.descent += XINT (LGLYPH_YOFF (g));
1780
1781 if (cmp->lbearing > cmp->pixel_width + metrics.lbearing)
1782 cmp->lbearing = cmp->pixel_width + metrics.lbearing;
1783 if (cmp->rbearing < cmp->pixel_width + metrics.rbearing)
1784 cmp->rbearing = cmp->pixel_width + metrics.rbearing;
1785 if (cmp->ascent < metrics.ascent)
1786 cmp->ascent = metrics.ascent;
1787 if (cmp->descent < metrics.descent)
1788 cmp->descent = metrics.descent;
1789 cmp->pixel_width += metrics.width + XINT (LGLYPH_WADJUST (g));
1790 }
1791 LGSTRING_SET_LBEARING (gstring, make_number (cmp->lbearing));
1792 LGSTRING_SET_RBEARING (gstring, make_number (cmp->rbearing));
1793 LGSTRING_SET_WIDTH (gstring, make_number (cmp->pixel_width));
1794 LGSTRING_SET_ASCENT (gstring, make_number (cmp->ascent));
1795 LGSTRING_SET_DESCENT (gstring, make_number (cmp->descent));
1796
1797 return font;
1798}
1799
1800int
1801font_gstring_produce (old, from, to, new, idx, code, n)
1802 Lisp_Object old;
1803 int from, to;
1804 Lisp_Object new;
1805 int idx;
1806 unsigned *code;
1807 int n;
1808{
1809 Lisp_Object min_idx, max_idx;
1810 int i;
1811
1812 if (idx + n > ASIZE (new))
1813 return -1;
1814 if (from == to)
1815 {
1816 if (from == 0)
1817 {
1818 min_idx = make_number (0);
1819 max_idx = make_number (1);
1820 }
1821 else
1822 {
1823 min_idx = AREF (AREF (old, from - 1), 0);
1824 max_idx = AREF (AREF (old, from - 1), 1);
1825 }
1826 }
1827 else if (from + 1 == to)
1828 {
1829 min_idx = AREF (AREF (old, from), 0);
1830 max_idx = AREF (AREF (old, from), 1);
1831 }
1832 else
1833 {
1834 int min_idx_i = XINT (AREF (AREF (old, from), 0));
1835 int max_idx_i = XINT (AREF (AREF (old, from), 1));
1836
1837 for (i = from + 1; i < to; i++)
1838 {
1839 if (min_idx_i > XINT (AREF (AREF (old, i), 0)))
1840 min_idx_i = XINT (AREF (AREF (old, i), 0));
1841 if (max_idx_i < XINT (AREF (AREF (old, i), 1)))
1842 max_idx_i = XINT (AREF (AREF (old, i), 1));
1843 }
1844 min_idx = make_number (min_idx_i);
1845 max_idx = make_number (max_idx_i);
1846 }
1847
1848 for (i = 0; i < n; i++)
1849 {
1850 ASET (AREF (new, idx + i), 0, min_idx);
1851 ASET (AREF (new, idx + i), 1, max_idx);
1852 ASET (AREF (new, idx + i), 2, make_number (code[i]));
1853 }
1854
1855 return 0;
1856}
1857\f
1858/* Font sorting */
1859
9331887d 1860static unsigned font_score P_ ((Lisp_Object, Lisp_Object *));
c2f5bfd6
KH
1861static int font_compare P_ ((const void *, const void *));
1862static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object,
1863 Lisp_Object, Lisp_Object));
1864
1865/* We sort fonts by scoring each of them against a specified
1866 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1867 the value is, the closer the font is to the font-spec.
1868
1869 Each 1-bit in the highest 4 bits of the score is used for atomic
1870 properties FOUNDRY, FAMILY, ADSTYLE, and REGISTRY.
1871
1872 Each 7-bit in the lowest 28 bits are used for numeric properties
1873 WEIGHT, SLANT, WIDTH, and SIZE. */
1874
1875/* How many bits to shift to store the difference value of each font
1876 property in a score. */
1877static int sort_shift_bits[FONT_SIZE_INDEX + 1];
1878
9331887d
KH
1879/* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1880 The return value indicates how different ENTITY is compared with
1881 SPEC_PROP. */
c2f5bfd6
KH
1882
1883static unsigned
9331887d
KH
1884font_score (entity, spec_prop)
1885 Lisp_Object entity, *spec_prop;
c2f5bfd6
KH
1886{
1887 unsigned score = 0;
1888 int i;
9331887d 1889 /* Score four atomic fields. Maximum difference is 1. */
c2f5bfd6 1890 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
9331887d
KH
1891 if (! NILP (spec_prop[i])
1892 && ! EQ (spec_prop[i], AREF (entity, i)))
1893 score |= 1 << sort_shift_bits[i];
c2f5bfd6 1894
9331887d 1895 /* Score four numeric fields. Maximum difference is 127. */
c2f5bfd6
KH
1896 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
1897 {
c2f5bfd6
KH
1898 Lisp_Object entity_val = AREF (entity, i);
1899
9331887d 1900 if (! NILP (spec_prop[i]) && ! EQ (spec_prop[i], entity_val))
c2f5bfd6
KH
1901 {
1902 if (! INTEGERP (entity_val))
1903 score |= 127 << sort_shift_bits[i];
9331887d 1904 else
c2f5bfd6 1905 {
9331887d 1906 int diff = XINT (entity_val) - XINT (spec_prop[i]);
c2f5bfd6
KH
1907
1908 if (diff < 0)
1909 diff = - diff;
9331887d
KH
1910 if (i == FONT_SIZE_INDEX)
1911 {
1912 if (XINT (entity_val) > 0
1913 && diff > FONT_PIXEL_SIZE_QUANTUM)
1914 score |= min (diff, 127) << sort_shift_bits[i];
1915 }
1916 else
1917 score |= min (diff, 127) << sort_shift_bits[i];
c2f5bfd6
KH
1918 }
1919 }
1920 }
1921
1922 return score;
1923}
1924
1925
1926/* The comparison function for qsort. */
1927
1928static int
1929font_compare (d1, d2)
1930 const void *d1, *d2;
1931{
1932 return (*(unsigned *) d1 < *(unsigned *) d2
1933 ? -1 : *(unsigned *) d1 > *(unsigned *) d2);
1934}
1935
1936
1937/* The structure for elements being sorted by qsort. */
1938struct font_sort_data
1939{
1940 unsigned score;
1941 Lisp_Object entity;
1942};
1943
1944
1945/* Sort font-entities in vector VEC by closeness to font-spec PREFER.
1946 If PREFER specifies a point-size, calculate the corresponding
9331887d
KH
1947 pixel-size from QCdpi property of PREFER or from the Y-resolution
1948 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
1949 get the font-entities in VEC. */
c2f5bfd6
KH
1950
1951static Lisp_Object
1952font_sort_entites (vec, prefer, frame, spec)
1953 Lisp_Object vec, prefer, frame, spec;
1954{
9331887d 1955 Lisp_Object prefer_prop[FONT_SPEC_MAX];
c2f5bfd6
KH
1956 int len, i;
1957 struct font_sort_data *data;
c2f5bfd6
KH
1958 USE_SAFE_ALLOCA;
1959
1960 len = ASIZE (vec);
1961 if (len <= 1)
1962 return vec;
1963
9331887d
KH
1964 for (i = FONT_FOUNDRY_INDEX; i <= FONT_SIZE_INDEX; i++)
1965 prefer_prop[i] = AREF (prefer, i);
c2f5bfd6
KH
1966
1967 if (! NILP (spec))
1968 {
1969 /* As it is assured that all fonts in VEC match with SPEC, we
1970 should ignore properties specified in SPEC. So, set the
9331887d 1971 corresponding properties in PREFER_PROP to nil. */
c2f5bfd6 1972 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
9331887d
KH
1973 if (! NILP (AREF (spec, i)))
1974 prefer_prop[i++] = Qnil;
c2f5bfd6
KH
1975 }
1976
9331887d
KH
1977 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
1978 prefer_prop[FONT_SIZE_INDEX]
1979 = make_number (font_pixel_size (XFRAME (frame), prefer));
1980
c2f5bfd6
KH
1981 /* Scoring and sorting. */
1982 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
1983 for (i = 0; i < len; i++)
1984 {
1985 data[i].entity = AREF (vec, i);
9331887d 1986 data[i].score = font_score (data[i].entity, prefer_prop);
c2f5bfd6
KH
1987 }
1988 qsort (data, len, sizeof *data, font_compare);
1989 for (i = 0; i < len; i++)
1990 ASET (vec, i, data[i].entity);
1991 SAFE_FREE ();
1992
1993 return vec;
1994}
1995
1996\f
1997/* API of Font Service Layer. */
1998
1999void
2000font_update_sort_order (order)
2001 int *order;
2002{
2003 int i, shift_bits = 21;
2004
2005 for (i = 0; i < 4; i++, shift_bits -= 7)
2006 {
2007 int xlfd_idx = order[i];
2008
2009 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2010 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2011 else if (xlfd_idx == XLFD_SLANT_INDEX)
2012 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2013 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2014 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2015 else
2016 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2017 }
2018}
2019
2020Lisp_Object
2021font_symbolic_weight (font)
2022 Lisp_Object font;
2023{
2024 Lisp_Object weight = AREF (font, FONT_WEIGHT_INDEX);
2025
2026 if (INTEGERP (weight))
2027 weight = prop_numeric_to_name (FONT_WEIGHT_INDEX, XINT (weight));
2028 return weight;
2029}
2030
2031Lisp_Object
2032font_symbolic_slant (font)
2033 Lisp_Object font;
2034{
2035 Lisp_Object slant = AREF (font, FONT_SLANT_INDEX);
2036
2037 if (INTEGERP (slant))
2038 slant = prop_numeric_to_name (FONT_SLANT_INDEX, XINT (slant));
2039 return slant;
2040}
2041
2042Lisp_Object
2043font_symbolic_width (font)
2044 Lisp_Object font;
2045{
2046 Lisp_Object width = AREF (font, FONT_WIDTH_INDEX);
2047
2048 if (INTEGERP (width))
2049 width = prop_numeric_to_name (FONT_WIDTH_INDEX, XINT (width));
2050 return width;
2051}
2052
ef18374f
KH
2053int
2054font_match_p (spec, entity)
2055 Lisp_Object spec, entity;
2056{
2057 int i;
2058
2059 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
2060 if (! NILP (AREF (spec, i))
2061 && ! EQ (AREF (spec, i), AREF (entity, i)))
2062 return 0;
2063 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX))
2064 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0
2065 && (XINT (AREF (spec, FONT_SIZE_INDEX))
2066 != XINT (AREF (entity, FONT_SIZE_INDEX))))
2067 return 0;
2068 return 1;
2069}
2070
c2f5bfd6
KH
2071Lisp_Object
2072font_find_object (font)
2073 struct font *font;
2074{
2075 Lisp_Object tail, elt;
2076
2077 for (tail = AREF (font->entity, FONT_OBJLIST_INDEX); CONSP (tail);
2078 tail = XCDR (tail))
2079 {
2080 elt = XCAR (tail);
2081 if (font == XSAVE_VALUE (elt)->pointer
2082 && XSAVE_VALUE (elt)->integer > 0)
2083 return elt;
2084 }
2085 abort ();
2086 return Qnil;
2087}
2088
2089static Lisp_Object scratch_font_spec, scratch_font_prefer;
2090
2091/* Return a vector of font-entities matching with SPEC on frame F. */
2092
2093static Lisp_Object
2094font_list_entities (frame, spec)
2095 Lisp_Object frame, spec;
2096{
2097 FRAME_PTR f = XFRAME (frame);
2098 struct font_driver_list *driver_list = f->font_driver_list;
a9262bb8 2099 Lisp_Object ftype, family, size, alternate_familes;
c2f5bfd6
KH
2100 Lisp_Object *vec = alloca (sizeof (Lisp_Object) * num_font_drivers);
2101 int i;
2102
2103 if (! vec)
2104 return null_vector;
2105
2106 family = AREF (spec, FONT_FAMILY_INDEX);
2107 if (NILP (family))
2108 alternate_familes = Qnil;
2109 else
2110 {
2111 if (NILP (font_family_alist)
2112 && !NILP (Vface_alternative_font_family_alist))
2113 build_font_family_alist ();
2114 alternate_familes = assq_no_quit (family, font_family_alist);
2115 if (! NILP (alternate_familes))
2116 alternate_familes = XCDR (alternate_familes);
2117 }
a9262bb8
KH
2118 size = AREF (spec, FONT_SIZE_INDEX);
2119 if (FLOATP (size))
9331887d 2120 ASET (spec, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
a9262bb8 2121
c2f5bfd6
KH
2122 xassert (ASIZE (spec) == FONT_SPEC_MAX);
2123 ftype = AREF (spec, FONT_TYPE_INDEX);
2124
2125 for (i = 0; driver_list; driver_list = driver_list->next)
2126 if (NILP (ftype) || EQ (driver_list->driver->type, ftype))
2127 {
2128 Lisp_Object cache = driver_list->driver->get_cache (frame);
2129 Lisp_Object tail = alternate_familes;
2130 Lisp_Object val;
2131
2132 xassert (CONSP (cache));
2133 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2134 ASET (spec, FONT_FAMILY_INDEX, family);
2135
2136 while (1)
2137 {
2138 val = assoc_no_quit (spec, XCDR (cache));
2139 if (CONSP (val))
2140 val = XCDR (val);
2141 else
2142 {
2143 val = driver_list->driver->list (frame, spec);
2144 if (VECTORP (val))
2145 XSETCDR (cache, Fcons (Fcons (Fcopy_sequence (spec), val),
2146 XCDR (cache)));
2147 }
2148 if (VECTORP (val) && ASIZE (val) > 0)
2149 {
2150 vec[i++] = val;
2151 break;
2152 }
2153 if (NILP (tail))
2154 break;
2155 ASET (spec, FONT_FAMILY_INDEX, XCAR (tail));
2156 tail = XCDR (tail);
2157 }
2158 }
2159 ASET (spec, FONT_TYPE_INDEX, ftype);
2160 ASET (spec, FONT_FAMILY_INDEX, family);
a9262bb8 2161 ASET (spec, FONT_SIZE_INDEX, size);
c2f5bfd6
KH
2162 return (i > 0 ? Fvconcat (i, vec) : null_vector);
2163}
2164
2165static int num_fonts;
2166
2167static Lisp_Object
2168font_open_entity (f, entity, pixel_size)
2169 FRAME_PTR f;
2170 Lisp_Object entity;
2171 int pixel_size;
2172{
2173 struct font_driver_list *driver_list;
2174 Lisp_Object objlist, size, val;
2175 struct font *font;
2176
2177 size = AREF (entity, FONT_SIZE_INDEX);
2178 xassert (NATNUMP (size));
2179 if (XINT (size) != 0)
2180 pixel_size = XINT (size);
2181
2182 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2183 objlist = XCDR (objlist))
2184 {
2185 font = XSAVE_VALUE (XCAR (objlist))->pointer;
2186 if (font->pixel_size == pixel_size)
2187 {
2188 XSAVE_VALUE (XCAR (objlist))->integer++;
2189 return XCAR (objlist);
2190 }
2191 }
2192
2193 xassert (FONT_ENTITY_P (entity));
2194 val = AREF (entity, FONT_TYPE_INDEX);
2195 for (driver_list = f->font_driver_list;
2196 driver_list && ! EQ (driver_list->driver->type, val);
2197 driver_list = driver_list->next);
2198 if (! driver_list)
2199 return Qnil;
2200
2201 font = driver_list->driver->open (f, entity, pixel_size);
2202 if (! font)
2203 return Qnil;
2204 val = make_save_value (font, 1);
2205 ASET (entity, FONT_OBJLIST_INDEX,
2206 Fcons (val, AREF (entity, FONT_OBJLIST_INDEX)));
2207 num_fonts++;
2208 return val;
2209}
2210
2211void
2212font_close_object (f, font_object)
2213 FRAME_PTR f;
2214 Lisp_Object font_object;
2215{
2216 struct font *font;
2217 Lisp_Object objlist = AREF (font->entity, FONT_OBJLIST_INDEX);
2218 Lisp_Object tail, prev = Qnil;
2219
2220 for (prev = Qnil, tail = objlist; CONSP (tail);
2221 prev = tail, tail = XCDR (tail))
2222 if (EQ (font_object, XCAR (tail)))
2223 {
2224 struct Lisp_Save_Value *p = XSAVE_VALUE (font_object);
2225
2226 xassert (p->integer > 0);
2227 p->integer--;
2228 if (p->integer == 0)
2229 {
2230 if (font->driver->close)
2231 font->driver->close (f, p->pointer);
2232 p->pointer = NULL;
2233 if (NILP (prev))
2234 ASET (font->entity, FONT_OBJLIST_INDEX, XCDR (objlist));
2235 else
2236 XSETCDR (prev, XCDR (objlist));
2237 }
2238 break;
2239 }
2240}
2241
2242int
2243font_has_char (f, font_entity, c)
2244 FRAME_PTR f;
2245 Lisp_Object font_entity;
2246 int c;
2247{
2248 Lisp_Object type = AREF (font_entity, FONT_TYPE_INDEX);
2249 struct font_driver_list *driver_list;
2250
2251 for (driver_list = f->font_driver_list;
2252 driver_list && ! EQ (driver_list->driver->type, type);
2253 driver_list = driver_list->next);
2254 if (! driver_list)
2255 return -1;
2256 return driver_list->driver->has_char (font_entity, c);
2257}
2258
2259unsigned
2260font_encode_char (font_object, c)
2261 Lisp_Object font_object;
2262 int c;
2263{
2264 struct font *font = XSAVE_VALUE (font_object)->pointer;
2265
2266 return font->driver->encode_char (font, c);
2267}
2268
ef18374f 2269Lisp_Object
c2f5bfd6
KH
2270font_get_name (font_object)
2271 Lisp_Object font_object;
2272{
2273 struct font *font = XSAVE_VALUE (font_object)->pointer;
ef18374f
KH
2274 char *name = (font->font.full_name ? font->font.full_name
2275 : font->font.name ? font->font.name
2276 : NULL);
c2f5bfd6 2277
ef18374f
KH
2278 return (name ? make_unibyte_string (name, strlen (name)) : null_string);
2279}
2280
2281Lisp_Object
2282font_get_spec (font_object)
2283 Lisp_Object font_object;
2284{
2285 struct font *font = XSAVE_VALUE (font_object)->pointer;
2286 Lisp_Object spec = Ffont_spec (0, NULL);
2287 int i;
2288
2289 for (i = 0; i < FONT_SIZE_INDEX; i++)
2290 ASET (spec, i, AREF (font->entity, i));
2291 ASET (spec, FONT_SIZE_INDEX, make_number (font->pixel_size));
2292 return spec;
c2f5bfd6
KH
2293}
2294
2295Lisp_Object
2296font_get_frame (font)
2297 Lisp_Object font;
2298{
2299 if (FONT_OBJECT_P (font))
2300 font = ((struct font *) XSAVE_VALUE (font)->pointer)->entity;
2301 xassert (FONT_ENTITY_P (font));
2302 return AREF (font, FONT_FRAME_INDEX);
2303}
2304
ef18374f
KH
2305/* Find a font entity best matching with LFACE. If SPEC is non-nil,
2306 the font must exactly match with it. */
c2f5bfd6
KH
2307
2308Lisp_Object
2309font_find_for_lface (f, lface, spec)
2310 FRAME_PTR f;
2311 Lisp_Object *lface;
2312 Lisp_Object spec;
2313{
ef18374f 2314 Lisp_Object frame, entities;
c2f5bfd6 2315 int i;
c2f5bfd6 2316
c2f5bfd6
KH
2317 if (NILP (spec))
2318 for (i = 0; i < FONT_SPEC_MAX; i++)
2319 ASET (scratch_font_spec, i, Qnil);
2320 else
2321 for (i = 0; i < FONT_SPEC_MAX; i++)
2322 ASET (scratch_font_spec, i, AREF (spec, i));
2323
c2f5bfd6 2324 if (NILP (AREF (scratch_font_spec, FONT_FAMILY_INDEX))
ef18374f
KH
2325 && ! NILP (lface[LFACE_FAMILY_INDEX]))
2326 font_merge_old_spec (Qnil, lface[LFACE_FAMILY_INDEX], Qnil,
2327 scratch_font_spec);
c2f5bfd6 2328 if (NILP (AREF (scratch_font_spec, FONT_REGISTRY_INDEX)))
ef18374f 2329 ASET (scratch_font_spec, FONT_REGISTRY_INDEX, intern ("iso8859-1"));
c2f5bfd6
KH
2330
2331 XSETFRAME (frame, f);
2332 entities = font_list_entities (frame, scratch_font_spec);
2333 while (ASIZE (entities) == 0)
2334 {
ef18374f
KH
2335 if (! NILP (AREF (scratch_font_spec, FONT_FOUNDRY_INDEX))
2336 && (NILP (spec) || NILP (AREF (spec, FONT_FOUNDRY_INDEX))))
c2f5bfd6 2337 {
c2f5bfd6
KH
2338 ASET (scratch_font_spec, FONT_FOUNDRY_INDEX, Qnil);
2339 entities = font_list_entities (frame, scratch_font_spec);
2340 }
ef18374f
KH
2341 else if (! NILP (AREF (scratch_font_spec, FONT_FAMILY_INDEX))
2342 && (NILP (spec) || NILP (AREF (spec, FONT_FAMILY_INDEX))))
c2f5bfd6 2343 {
c2f5bfd6
KH
2344 ASET (scratch_font_spec, FONT_FAMILY_INDEX, Qnil);
2345 entities = font_list_entities (frame, scratch_font_spec);
2346 }
2347 else
2348 return Qnil;
2349 }
2350
2351 if (ASIZE (entities) > 1)
2352 {
ef18374f 2353 Lisp_Object prefer = scratch_font_prefer, val;
9331887d 2354 double pt;
ef18374f
KH
2355
2356 ASET (prefer, FONT_WEIGHT_INDEX,
2357 font_prop_validate_style (FONT_WEIGHT_INDEX,
2358 lface[LFACE_WEIGHT_INDEX]));
2359 ASET (prefer, FONT_SLANT_INDEX,
2360 font_prop_validate_style (FONT_SLANT_INDEX,
2361 lface[LFACE_SLANT_INDEX]));
2362 ASET (prefer, FONT_WIDTH_INDEX,
2363 font_prop_validate_style (FONT_WIDTH_INDEX,
2364 lface[LFACE_SWIDTH_INDEX]));
9331887d
KH
2365 pt = XINT (lface[LFACE_HEIGHT_INDEX]);
2366 ASET (prefer, FONT_SIZE_INDEX, make_float (pt / 10));
c2f5bfd6 2367
c2f5bfd6
KH
2368 font_sort_entites (entities, prefer, frame, spec);
2369 }
2370
2371 return AREF (entities, 0);
2372}
2373
2374Lisp_Object
2375font_open_for_lface (f, lface, entity)
2376 FRAME_PTR f;
2377 Lisp_Object *lface;
2378 Lisp_Object entity;
2379{
9331887d
KH
2380 double pt = XINT (lface[LFACE_HEIGHT_INDEX]);
2381 int size;
c2f5bfd6 2382
9331887d
KH
2383 pt /= 10;
2384 size = POINT_TO_PIXEL (pt, f->resy);
c2f5bfd6
KH
2385 return font_open_entity (f, entity, size);
2386}
2387
2388void
2389font_load_for_face (f, face)
2390 FRAME_PTR f;
2391 struct face *face;
2392{
ef18374f 2393 Lisp_Object font_object = face->lface[LFACE_FONT_INDEX];
c2f5bfd6 2394
ef18374f 2395 if (NILP (font_object))
c2f5bfd6 2396 {
ef18374f 2397 Lisp_Object entity = font_find_for_lface (f, face->lface, Qnil);
c2f5bfd6 2398
ef18374f
KH
2399 if (! NILP (entity))
2400 font_object = font_open_for_lface (f, face->lface, entity);
2401 }
c2f5bfd6 2402
ef18374f
KH
2403 if (! NILP (font_object))
2404 {
2405 struct font *font = XSAVE_VALUE (font_object)->pointer;
2406
2407 face->font = font->font.font;
2408 face->font_info = (struct font_info *) font;
2409 face->font_info_id = 0;
2410 face->font_name = font->font.full_name;
2411 }
2412 else
2413 {
2414 face->font = NULL;
2415 face->font_info = NULL;
2416 face->font_info_id = -1;
2417 face->font_name = NULL;
2418 add_to_log ("Unable to load font for a face%s", null_string, Qnil);
c2f5bfd6 2419 }
c2f5bfd6
KH
2420}
2421
2422void
2423font_prepare_for_face (f, face)
2424 FRAME_PTR f;
2425 struct face *face;
2426{
2427 struct font *font = (struct font *) face->font_info;
2428
2429 if (font->driver->prepare_face)
2430 font->driver->prepare_face (f, face);
2431}
2432
2433void
2434font_done_for_face (f, face)
2435 FRAME_PTR f;
2436 struct face *face;
2437{
2438 struct font *font = (struct font *) face->font_info;
2439
2440 if (font->driver->done_face)
2441 font->driver->done_face (f, face);
2442 face->extra = NULL;
2443}
2444
2445Lisp_Object
2446font_open_by_name (f, name)
2447 FRAME_PTR f;
2448 char *name;
2449{
ef18374f 2450 Lisp_Object args[2];
a9262bb8 2451 Lisp_Object spec, prefer, size, entities;
c2f5bfd6 2452 Lisp_Object frame;
1bb1d99b 2453 struct font_driver_list *dlist;
a9262bb8 2454 int i;
ef18374f 2455 int pixel_size;
c2f5bfd6
KH
2456
2457 XSETFRAME (frame, f);
a9262bb8 2458
ef18374f
KH
2459 args[0] = QCname;
2460 args[1] = make_unibyte_string (name, strlen (name));
2461 spec = Ffont_spec (2, args);
a9262bb8
KH
2462 prefer = scratch_font_prefer;
2463 for (i = FONT_WEIGHT_INDEX; i < FONT_SIZE_INDEX; i++)
2464 if (NILP (AREF (spec, i)))
2465 ASET (prefer, i, make_number (100));
2466 size = AREF (spec, FONT_SIZE_INDEX);
2467 if (NILP (size))
2468 pixel_size = 0;
2469 else if (INTEGERP (size))
2470 pixel_size = XINT (size);
2471 else /* FLOATP (size) */
ef18374f 2472 {
9331887d 2473 double pt = XFLOAT_DATA (size);
a9262bb8
KH
2474
2475 pixel_size = POINT_TO_PIXEL (pt, f->resy);
2476 size = make_number (pixel_size);
2477 ASET (spec, FONT_SIZE_INDEX, size);
ef18374f 2478 }
a9262bb8 2479 if (pixel_size == 0)
ef18374f 2480 {
9331887d 2481 pixel_size = POINT_TO_PIXEL (12.0, f->resy);
a9262bb8 2482 size = make_number (pixel_size);
ef18374f 2483 }
a9262bb8 2484 ASET (prefer, FONT_SIZE_INDEX, size);
9331887d
KH
2485 if (NILP (AREF (spec, FONT_REGISTRY_INDEX)))
2486 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
a9262bb8
KH
2487
2488 entities = Flist_fonts (spec, frame, make_number (1), prefer);
2489 return (NILP (entities)
2490 ? Qnil
2491 : font_open_entity (f, XCAR (entities), pixel_size));
c2f5bfd6
KH
2492}
2493
2494
2495/* Register font-driver DRIVER. This function is used in two ways.
2496
2497 The first is with frame F non-NULL. In this case, DRIVER is
2498 registered to be used for drawing characters on F. All frame
2499 creaters (e.g. Fx_create_frame) must call this function at least
2500 once with an available font-driver.
2501
2502 The second is with frame F NULL. In this case, DRIVER is globally
2503 registered in the variable `font_driver_list'. All font-driver
2504 implementations must call this function in its syms_of_XXXX
2505 (e.g. syms_of_xfont). */
2506
2507void
2508register_font_driver (driver, f)
2509 struct font_driver *driver;
2510 FRAME_PTR f;
2511{
2512 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
2513 struct font_driver_list *prev, *list;
2514
2515 if (f && ! driver->draw)
2516 error ("Unsable font driver for a frame: %s",
2517 SDATA (SYMBOL_NAME (driver->type)));
2518
2519 for (prev = NULL, list = root; list; prev = list, list = list->next)
2520 if (list->driver->type == driver->type)
2521 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
2522
2523 list = malloc (sizeof (struct font_driver_list));
2524 list->driver = driver;
2525 list->next = NULL;
2526 if (prev)
2527 prev->next = list;
2528 else if (f)
2529 f->font_driver_list = list;
2530 else
2531 font_driver_list = list;
2532 num_font_drivers++;
2533}
2534
2535/* Free font-driver list on frame F. It doesn't free font-drivers
2536 themselves. */
2537
2538void
2539free_font_driver_list (f)
2540 FRAME_PTR f;
2541{
2542 while (f->font_driver_list)
2543 {
2544 struct font_driver_list *next = f->font_driver_list->next;
2545
2546 free (f->font_driver_list);
2547 f->font_driver_list = next;
2548 }
2549}
2550
2551\f
2552/* Lisp API */
2553
2554DEFUN ("fontp", Ffontp, Sfontp, 1, 1, 0,
2555 doc: /* Return t if object is a font-spec or font-entity. */)
2556 (object)
2557 Lisp_Object object;
2558{
2559 return (FONTP (object) ? Qt : Qnil);
2560}
2561
2562DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
2563 doc: /* Return a newly created font-spec with specified arguments as properties.
2564usage: (font-spec &rest properties) */)
2565 (nargs, args)
2566 int nargs;
2567 Lisp_Object *args;
2568{
2569 Lisp_Object spec = Fmake_vector (make_number (FONT_SPEC_MAX), Qnil);
9331887d 2570 Lisp_Object extra = Qnil, name = Qnil;
c2f5bfd6
KH
2571 int i;
2572
2573 for (i = 0; i < nargs; i += 2)
2574 {
2575 enum font_property_index prop;
2576 Lisp_Object key = args[i], val = args[i + 1];
2577
2578 prop = check_font_prop_name (key);
2579 if (prop < FONT_EXTRA_INDEX)
2580 ASET (spec, prop, (font_property_table[prop].validater) (prop, val));
2581 else
4485a28e
KH
2582 {
2583 if (EQ (key, QCname))
9331887d
KH
2584 name = val;
2585 else
2586 extra = Fcons (Fcons (key, val), extra);
4485a28e 2587 }
c2f5bfd6
KH
2588 }
2589 ASET (spec, FONT_EXTRA_INDEX, extra);
9331887d
KH
2590 if (STRINGP (name))
2591 font_parse_name (SDATA (name), spec, 0);
c2f5bfd6
KH
2592 return spec;
2593}
2594
2595
2596DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
2597 doc: /* Return the value of FONT's PROP property.
2598FONT may be a font-spec or font-entity.
2599If FONT is font-entity and PROP is :extra, always nil is returned. */)
2600 (font, prop)
2601 Lisp_Object font, prop;
2602{
2603 enum font_property_index idx;
2604
2605 CHECK_FONT (font);
2606 idx = check_font_prop_name (prop);
2607 if (idx < FONT_EXTRA_INDEX)
2608 return AREF (font, idx);
2609 if (FONT_ENTITY_P (font))
2610 return Qnil;
2611 return Fcdr (Fassoc (AREF (font, FONT_EXTRA_INDEX), prop));
2612}
2613
2614
2615DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
2616 doc: /* Set one property of FONT-SPEC: give property PROP value VALUE. */)
2617 (font_spec, prop, val)
2618 Lisp_Object font_spec, prop, val;
2619{
2620 enum font_property_index idx;
2621 Lisp_Object extra, slot;
2622
2623 CHECK_FONT_SPEC (font_spec);
2624 idx = check_font_prop_name (prop);
2625 if (idx < FONT_EXTRA_INDEX)
2626 return ASET (font_spec, idx, val);
2627 extra = AREF (font_spec, FONT_EXTRA_INDEX);
2628 slot = Fassoc (extra, prop);
2629 if (NILP (slot))
2630 extra = Fcons (Fcons (prop, val), extra);
2631 else
2632 Fsetcdr (slot, val);
2633 return val;
2634}
2635
2636DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
2637 doc: /* List available fonts matching FONT-SPEC on the current frame.
2638Optional 2nd argument FRAME specifies the target frame.
2639Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
2640Optional 4th argument PREFER, if non-nil, is a font-spec to sort fonts
2641by closeness to PREFER. */)
2642 (font_spec, frame, num, prefer)
2643 Lisp_Object font_spec, frame, num, prefer;
2644{
2645 Lisp_Object vec, list, tail;
2646 int n = 0, i, len;
2647
2648 if (NILP (frame))
2649 frame = selected_frame;
2650 CHECK_LIVE_FRAME (frame);
2651 CHECK_VALIDATE_FONT_SPEC (font_spec);
2652 if (! NILP (num))
2653 {
2654 CHECK_NUMBER (num);
2655 n = XINT (num);
2656 if (n <= 0)
2657 return Qnil;
2658 }
2659 if (! NILP (prefer))
2660 CHECK_FONT (prefer);
2661
2662 vec = font_list_entities (frame, font_spec);
2663 len = ASIZE (vec);
2664 if (len == 0)
2665 return Qnil;
2666 if (len == 1)
2667 return Fcons (AREF (vec, 0), Qnil);
2668
2669 if (! NILP (prefer))
2670 vec = font_sort_entites (vec, prefer, frame, font_spec);
2671
2672 list = tail = Fcons (AREF (vec, 0), Qnil);
2673 if (n == 0 || n > len)
2674 n = len;
2675 for (i = 1; i < n; i++)
2676 {
2677 Lisp_Object val = Fcons (AREF (vec, i), Qnil);
2678
2679 XSETCDR (tail, val);
2680 tail = val;
2681 }
2682 return list;
2683}
2684
2685DEFUN ("list-families", Flist_families, Slist_families, 0, 1, 0,
2686 doc: /* List available font families on the current frame.
2687Optional 2nd argument FRAME specifies the target frame. */)
2688 (frame)
2689 Lisp_Object frame;
2690{
2691 FRAME_PTR f;
2692 struct font_driver_list *driver_list;
2693 Lisp_Object list;
2694
2695 if (NILP (frame))
2696 frame = selected_frame;
2697 CHECK_LIVE_FRAME (frame);
2698 f = XFRAME (frame);
2699 list = Qnil;
2700 for (driver_list = f->font_driver_list; driver_list;
2701 driver_list = driver_list->next)
2702 if (driver_list->driver->list_family)
2703 {
2704 Lisp_Object val = driver_list->driver->list_family (frame);
2705
2706 if (NILP (list))
2707 list = val;
2708 else
2709 {
2710 Lisp_Object tail = list;
2711
2712 for (; CONSP (val); val = XCDR (val))
2713 if (NILP (Fmemq (XCAR (val), tail)))
2714 list = Fcons (XCAR (val), list);
2715 }
2716 }
2717 return list;
2718}
2719
2720DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
2721 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
2722Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
2723 (font_spec, frame)
2724 Lisp_Object font_spec, frame;
2725{
2726 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
2727
2728 if (CONSP (val))
2729 val = XCAR (val);
2730 return val;
2731}
2732
2733DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 1, 0,
2734 doc: /* Return XLFD name of FONT.
2735FONT is a font-spec, font-entity, or font-object.
2736If the name is too long for XLFD (maximum 255 chars), return nil. */)
2737 (font)
2738 Lisp_Object font;
2739{
2740 char name[256];
2741 int pixel_size = 0;
2742
2743 if (FONT_SPEC_P (font))
2744 CHECK_VALIDATE_FONT_SPEC (font);
2745 else if (FONT_ENTITY_P (font))
2746 CHECK_FONT (font);
2747 else
2748 {
2749 struct font *fontp;
2750
2751 CHECK_FONT_GET_OBJECT (font, fontp);
2752 font = fontp->entity;
2753 pixel_size = fontp->pixel_size;
2754 }
2755
2756 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
2757 return Qnil;
2758 return build_string (name);
2759}
2760
2761DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
2762 doc: /* Clear font cache. */)
2763 ()
2764{
2765 Lisp_Object list, frame;
2766
2767 FOR_EACH_FRAME (list, frame)
2768 {
2769 FRAME_PTR f = XFRAME (frame);
2770 struct font_driver_list *driver_list = f->font_driver_list;
2771
2772 for (; driver_list; driver_list = driver_list->next)
2773 {
2774 Lisp_Object cache = driver_list->driver->get_cache (frame);
2775 Lisp_Object tail, elt;
2776
2777 for (tail = XCDR (cache); CONSP (tail); tail = XCDR (tail))
2778 {
2779 elt = XCAR (tail);
2780 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2781 {
2782 Lisp_Object vec = XCDR (elt);
2783 int i;
2784
2785 for (i = 0; i < ASIZE (vec); i++)
2786 {
2787 Lisp_Object entity = AREF (vec, i);
2788 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2789
2790 for (; CONSP (objlist); objlist = XCDR (objlist))
2791 {
2792 Lisp_Object val = XCAR (objlist);
2793 struct Lisp_Save_Value *p = XSAVE_VALUE (val);
2794 struct font *font = p->pointer;
2795
2796 xassert (font
2797 && driver_list->driver == font->driver);
2798 driver_list->driver->close (f, font);
2799 p->pointer = NULL;
2800 p->integer = 0;
2801 }
2802 if (driver_list->driver->free_entity)
2803 driver_list->driver->free_entity (entity);
2804 }
2805 }
2806 }
2807 XSETCDR (cache, Qnil);
2808 }
2809 }
2810
2811 return Qnil;
2812}
2813
2814DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table,
2815 Sinternal_set_font_style_table, 2, 2, 0,
2816 doc: /* Set font style table for PROP to TABLE.
2817PROP must be `:weight', `:slant', or `:width'.
2818TABLE must be an alist of symbols vs the corresponding numeric values
2819sorted by numeric values. */)
2820 (prop, table)
2821 Lisp_Object prop, table;
2822{
2823 int table_index;
2824 int numeric;
2825 Lisp_Object tail, val;
2826
2827 CHECK_SYMBOL (prop);
2828 table_index = (EQ (prop, QCweight) ? 0
2829 : EQ (prop, QCslant) ? 1
2830 : EQ (prop, QCwidth) ? 2
2831 : 3);
2832 if (table_index >= ASIZE (font_style_table))
2833 error ("Invalid font style property: %s", SDATA (SYMBOL_NAME (prop)));
2834 table = Fcopy_sequence (table);
2835 numeric = -1;
2836 for (tail = table; ! NILP (tail); tail = Fcdr (tail))
2837 {
2838 prop = Fcar (Fcar (tail));
2839 val = Fcdr (Fcar (tail));
2840 CHECK_SYMBOL (prop);
2841 CHECK_NATNUM (val);
2842 if (numeric > XINT (val))
2843 error ("Numeric values not sorted for %s", SDATA (SYMBOL_NAME (prop)));
2844 numeric = XINT (val);
2845 XSETCAR (tail, Fcons (prop, val));
2846 }
2847 ASET (font_style_table, table_index, table);
2848 return Qnil;
2849}
2850
2851DEFUN ("font-make-gstring", Ffont_make_gstring, Sfont_make_gstring, 2, 2, 0,
2852 doc: /* Return a newly created glyph-string for FONT-OBJECT with NUM glyphs.
2853FONT-OBJECT may be nil if it is not yet known. */)
2854 (font_object, num)
2855 Lisp_Object font_object, num;
2856{
2857 Lisp_Object gstring, g;
2858 int len;
2859 int i;
2860
2861 if (! NILP (font_object))
2862 CHECK_FONT_OBJECT (font_object);
2863 CHECK_NATNUM (num);
2864
2865 len = XINT (num) + 1;
2866 gstring = Fmake_vector (make_number (len), Qnil);
2867 g = Fmake_vector (make_number (6), Qnil);
2868 ASET (g, 0, font_object);
2869 ASET (gstring, 0, g);
2870 for (i = 1; i < len; i++)
2871 ASET (gstring, i, Fmake_vector (make_number (8), make_number (0)));
2872 return gstring;
2873}
2874
2875DEFUN ("font-fill-gstring", Ffont_fill_gstring, Sfont_fill_gstring, 4, 5, 0,
2876 doc: /* Fillin glyph-string GSTRING by characters for FONT-OBJECT.
2877START and END specifies the region to extract characters.
2878If optional 3rd argument OBJECT is non-nil, it is a buffer or a string from
2879where to extract characters.
2880FONT-OBJECT may be nil if GSTRING already already contains one. */)
2881 (gstring, font_object, start, end, object)
2882 Lisp_Object gstring, font_object, start, end, object;
2883{
2884 int len, i, c;
2885 unsigned code;
2886 struct font *font;
2887
2888 CHECK_VECTOR (gstring);
2889 if (NILP (font_object))
2890 font_object = Faref (Faref (gstring, make_number (0)), make_number (0));
2891 CHECK_FONT_GET_OBJECT (font_object, font);
2892
2893 if (STRINGP (object))
2894 {
2895 const unsigned char *p;
2896
2897 CHECK_NATNUM (start);
2898 CHECK_NATNUM (end);
2899 if (XINT (start) > XINT (end)
2900 || XINT (end) > ASIZE (object)
2901 || XINT (end) - XINT (start) >= XINT (Flength (gstring)))
2902 args_out_of_range (start, end);
2903
2904 len = XINT (end) - XINT (start);
2905 p = SDATA (object) + string_char_to_byte (object, XINT (start));
2906 for (i = 0; i < len; i++)
2907 {
2908 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
2909
2910 c = STRING_CHAR_ADVANCE (p);
2911 code = font->driver->encode_char (font, c);
2912 if (code > MOST_POSITIVE_FIXNUM)
2913 error ("Glyph code 0x%X is too large", code);
2914 ASET (g, 0, make_number (i));
2915 ASET (g, 1, make_number (i + 1));
2916 LGLYPH_SET_CHAR (g, make_number (c));
2917 LGLYPH_SET_CODE (g, make_number (code));
2918 }
2919 }
2920 else
2921 {
2922 int pos, pos_byte;
2923
2924 if (! NILP (object))
2925 Fset_buffer (object);
2926 validate_region (&start, &end);
2927 if (XINT (end) - XINT (start) > len)
2928 args_out_of_range (start, end);
2929 len = XINT (end) - XINT (start);
2930 pos = XINT (start);
2931 pos_byte = CHAR_TO_BYTE (pos);
2932 for (i = 0; i < len; i++)
2933 {
2934 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
2935
2936 FETCH_CHAR_ADVANCE (c, pos, pos_byte);
2937 code = font->driver->encode_char (font, c);
2938 if (code > MOST_POSITIVE_FIXNUM)
2939 error ("Glyph code 0x%X is too large", code);
2940 ASET (g, 0, make_number (i));
2941 ASET (g, 1, make_number (i + 1));
2942 LGLYPH_SET_CHAR (g, make_number (c));
2943 LGLYPH_SET_CODE (g, make_number (code));
2944 }
2945 }
2946 return Qnil;
2947}
2948
2949
2950#ifdef FONT_DEBUG
2951
2952DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
2953 doc: /* Open FONT-ENTITY. */)
2954 (font_entity, size, frame)
2955 Lisp_Object font_entity;
2956 Lisp_Object size;
2957 Lisp_Object frame;
2958{
2959 int isize;
2960
2961 CHECK_FONT_ENTITY (font_entity);
2962 if (NILP (size))
2963 size = AREF (font_entity, FONT_SIZE_INDEX);
2964 CHECK_NUMBER (size);
2965 if (NILP (frame))
2966 frame = selected_frame;
2967 CHECK_LIVE_FRAME (frame);
2968
2969 isize = XINT (size);
2970 if (isize < 0)
2971 isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy);
2972
2973 return font_open_entity (XFRAME (frame), font_entity, isize);
2974}
2975
2976DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
2977 doc: /* Close FONT-OBJECT. */)
2978 (font_object, frame)
2979 Lisp_Object font_object, frame;
2980{
2981 CHECK_FONT_OBJECT (font_object);
2982 if (NILP (frame))
2983 frame = selected_frame;
2984 CHECK_LIVE_FRAME (frame);
2985 font_close_object (XFRAME (frame), font_object);
2986 return Qnil;
2987}
2988
2989DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
2990 doc: /* Return information about FONT-OBJECT. */)
2991 (font_object)
2992 Lisp_Object font_object;
2993{
2994 struct font *font;
2995 Lisp_Object val;
2996
2997 CHECK_FONT_GET_OBJECT (font_object, font);
2998
2999 val = Fmake_vector (make_number (9), Qnil);
3000 ASET (val, 0, Ffont_xlfd_name (font_object));
3001 if (font->file_name)
3002 ASET (val, 1, make_unibyte_string (font->file_name,
3003 strlen (font->file_name)));
3004 ASET (val, 2, make_number (font->pixel_size));
3005 ASET (val, 3, make_number (font->font.size));
3006 ASET (val, 4, make_number (font->ascent));
3007 ASET (val, 5, make_number (font->descent));
3008 ASET (val, 6, make_number (font->font.space_width));
3009 ASET (val, 7, make_number (font->font.average_width));
3010 if (font->driver->otf_capability)
3011 ASET (val, 8, font->driver->otf_capability (font));
3012 return val;
3013}
3014
3015DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
3016 doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
3017Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
3018 (font_object, string)
3019 Lisp_Object font_object, string;
3020{
3021 struct font *font;
3022 int i, len;
3023 Lisp_Object vec;
3024
3025 CHECK_FONT_GET_OBJECT (font_object, font);
3026 CHECK_STRING (string);
3027 len = SCHARS (string);
3028 vec = Fmake_vector (make_number (len), Qnil);
3029 for (i = 0; i < len; i++)
3030 {
3031 Lisp_Object ch = Faref (string, make_number (i));
3032 Lisp_Object val;
3033 int c = XINT (ch);
3034 unsigned code;
3035 struct font_metrics metrics;
3036
3037 code = font->driver->encode_char (font, c);
3038 if (code == FONT_INVALID_CODE)
3039 continue;
3040 val = Fmake_vector (make_number (6), Qnil);
3041 if (code <= MOST_POSITIVE_FIXNUM)
3042 ASET (val, 0, make_number (code));
3043 else
3044 ASET (val, 0, Fcons (make_number (code >> 16),
3045 make_number (code & 0xFFFF)));
3046 font->driver->text_extents (font, &code, 1, &metrics);
3047 ASET (val, 1, make_number (metrics.lbearing));
3048 ASET (val, 2, make_number (metrics.rbearing));
3049 ASET (val, 3, make_number (metrics.width));
3050 ASET (val, 4, make_number (metrics.ascent));
3051 ASET (val, 5, make_number (metrics.descent));
3052 ASET (vec, i, val);
3053 }
3054 return vec;
3055}
3056
3057#if 0
3058DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
3059 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
3060The value is a number of glyphs drawn.
3061Type C-l to recover what previously shown. */)
3062 (font_object, string)
3063 Lisp_Object font_object, string;
3064{
3065 Lisp_Object frame = selected_frame;
3066 FRAME_PTR f = XFRAME (frame);
3067 struct font *font;
3068 struct face *face;
3069 int i, len, width;
3070 unsigned *code;
3071
3072 CHECK_FONT_GET_OBJECT (font_object, font);
3073 CHECK_STRING (string);
3074 len = SCHARS (string);
3075 code = alloca (sizeof (unsigned) * len);
3076 for (i = 0; i < len; i++)
3077 {
3078 Lisp_Object ch = Faref (string, make_number (i));
3079 Lisp_Object val;
3080 int c = XINT (ch);
3081
3082 code[i] = font->driver->encode_char (font, c);
3083 if (code[i] == FONT_INVALID_CODE)
3084 break;
3085 }
3086 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
3087 face->fontp = font;
3088 if (font->driver->prepare_face)
3089 font->driver->prepare_face (f, face);
3090 width = font->driver->text_extents (font, code, i, NULL);
3091 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
3092 if (font->driver->done_face)
3093 font->driver->done_face (f, face);
3094 face->fontp = NULL;
3095 return make_number (len);
3096}
3097#endif
3098
3099#endif /* FONT_DEBUG */
3100
3101\f
3102extern void syms_of_ftfont P_ (());
3103extern void syms_of_xfont P_ (());
3104extern void syms_of_xftfont P_ (());
3105extern void syms_of_ftxfont P_ (());
3106extern void syms_of_bdffont P_ (());
3107extern void syms_of_w32font P_ (());
3108extern void syms_of_atmfont P_ (());
3109
3110void
3111syms_of_font ()
3112{
3113 sort_shift_bits[FONT_SLANT_INDEX] = 0;
3114 sort_shift_bits[FONT_WEIGHT_INDEX] = 7;
3115 sort_shift_bits[FONT_SIZE_INDEX] = 14;
3116 sort_shift_bits[FONT_WIDTH_INDEX] = 21;
3117 sort_shift_bits[FONT_ADSTYLE_INDEX] = 28;
3118 sort_shift_bits[FONT_FOUNDRY_INDEX] = 29;
3119 sort_shift_bits[FONT_FAMILY_INDEX] = 30;
3120 sort_shift_bits[FONT_REGISTRY_INDEX] = 31;
3121 /* Note that sort_shift_bits[FONT_SLANT_TYPE] is never used. */
3122
3123 staticpro (&font_style_table);
3124 font_style_table = Fmake_vector (make_number (3), Qnil);
3125
3126 staticpro (&font_family_alist);
3127 font_family_alist = Qnil;
3128
3129 DEFSYM (Qfontp, "fontp");
3130
1bb1d99b
KH
3131 DEFSYM (Qiso8859_1, "iso8859-1");
3132 DEFSYM (Qiso10646_1, "iso10646-1");
3133 DEFSYM (Qunicode_bmp, "unicode-bmp");
3134
c2f5bfd6
KH
3135 DEFSYM (QCotf, ":otf");
3136 DEFSYM (QClanguage, ":language");
3137 DEFSYM (QCscript, ":script");
3138
3139 DEFSYM (QCfoundry, ":foundry");
3140 DEFSYM (QCadstyle, ":adstyle");
3141 DEFSYM (QCregistry, ":registry");
9331887d
KH
3142 DEFSYM (QCspacing, ":spacing");
3143 DEFSYM (QCdpi, ":dpi");
c2f5bfd6
KH
3144 DEFSYM (QCextra, ":extra");
3145
3146 staticpro (&null_string);
3147 null_string = build_string ("");
3148 staticpro (&null_vector);
3149 null_vector = Fmake_vector (make_number (0), Qnil);
3150
3151 staticpro (&scratch_font_spec);
3152 scratch_font_spec = Ffont_spec (0, NULL);
3153 staticpro (&scratch_font_prefer);
3154 scratch_font_prefer = Ffont_spec (0, NULL);
3155
3156 defsubr (&Sfontp);
3157 defsubr (&Sfont_spec);
3158 defsubr (&Sfont_get);
3159 defsubr (&Sfont_put);
3160 defsubr (&Slist_fonts);
3161 defsubr (&Slist_families);
3162 defsubr (&Sfind_font);
3163 defsubr (&Sfont_xlfd_name);
3164 defsubr (&Sclear_font_cache);
3165 defsubr (&Sinternal_set_font_style_table);
3166 defsubr (&Sfont_make_gstring);
3167 defsubr (&Sfont_fill_gstring);
3168
3169#ifdef FONT_DEBUG
3170 defsubr (&Sopen_font);
3171 defsubr (&Sclose_font);
3172 defsubr (&Squery_font);
3173 defsubr (&Sget_font_glyphs);
3174#if 0
3175 defsubr (&Sdraw_string);
3176#endif
3177#endif /* FONT_DEBUG */
3178
3179#ifdef HAVE_FREETYPE
3180 syms_of_ftfont ();
3181#ifdef HAVE_X_WINDOWS
3182 syms_of_xfont ();
3183 syms_of_ftxfont ();
3184#ifdef HAVE_XFT
3185 syms_of_xftfont ();
3186#endif /* HAVE_XFT */
3187#endif /* HAVE_X_WINDOWS */
3188#else /* not HAVE_FREETYPE */
3189#ifdef HAVE_X_WINDOWS
3190 syms_of_xfont ();
3191#endif /* HAVE_X_WINDOWS */
3192#endif /* not HAVE_FREETYPE */
3193#ifdef HAVE_BDFFONT
3194 syms_of_bdffont ();
3195#endif /* HAVE_BDFFONT */
3196#ifdef WINDOWSNT
3197 syms_of_w32font ();
3198#endif /* WINDOWSNT */
3199#ifdef MAC_OS
3200 syms_of_atmfont ();
3201#endif /* MAC_OS */
3202}
885b7d09
MB
3203
3204/* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
3205 (do not change this comment) */