Switch to recommended form of GPLv3 permissions notice.
[emacs.git] / src / font.c
blob197d7a744989ef3ca4bcaa2aa77386129e61e24a
1 /* font.c -- "Font" primitives.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
24 #include <config.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <ctype.h>
28 #ifdef HAVE_M17N_FLT
29 #include <m17n-flt.h>
30 #endif
32 #include "lisp.h"
33 #include "buffer.h"
34 #include "frame.h"
35 #include "window.h"
36 #include "dispextern.h"
37 #include "charset.h"
38 #include "character.h"
39 #include "composite.h"
40 #include "fontset.h"
41 #include "font.h"
43 #ifdef HAVE_X_WINDOWS
44 #include "xterm.h"
45 #endif /* HAVE_X_WINDOWS */
47 #ifdef HAVE_NTGUI
48 #include "w32term.h"
49 #endif /* HAVE_NTGUI */
51 #ifdef MAC_OS
52 #include "macterm.h"
53 #endif /* MAC_OS */
55 #ifndef FONT_DEBUG
56 #define FONT_DEBUG
57 #endif
59 #ifdef FONT_DEBUG
60 #undef xassert
61 #define xassert(X) do {if (!(X)) abort ();} while (0)
62 #else
63 #define xassert(X) (void) 0
64 #endif
66 int enable_font_backend;
68 Lisp_Object Qopentype;
70 /* Important character set symbols. */
71 Lisp_Object Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
73 /* Like CHECK_FONT_SPEC but also validate properties of the font-spec,
74 and set X to the validated result. */
76 #define CHECK_VALIDATE_FONT_SPEC(x) \
77 do { \
78 if (! FONT_SPEC_P (x)) wrong_type_argument (Qfont, x); \
79 x = font_prop_validate (x); \
80 } while (0)
82 /* Number of pt per inch (from the TeXbook). */
83 #define PT_PER_INCH 72.27
85 /* Return a pixel size (integer) corresponding to POINT size (double)
86 on resolution DPI. */
87 #define POINT_TO_PIXEL(POINT, DPI) ((POINT) * (DPI) / PT_PER_INCH + 0.5)
89 /* Return a point size (double) corresponding to POINT size (integer)
90 on resolution DPI. */
91 #define PIXEL_TO_POINT(PIXEL, DPI) ((PIXEL) * PT_PER_INCH * 10 / (DPI) + 0.5)
93 /* Special string of zero length. It is used to specify a NULL name
94 in a font properties (e.g. adstyle). We don't use the symbol of
95 NULL name because it's confusing (Lisp printer prints nothing for
96 it). */
97 Lisp_Object null_string;
99 /* Special vector of zero length. This is repeatedly used by (struct
100 font_driver *)->list when a specified font is not found. */
101 Lisp_Object null_vector;
103 /* Vector of 3 elements. Each element is an alist for one of font
104 style properties (weight, slant, width). Each alist contains a
105 mapping between symbolic property values (e.g. `medium' for weight)
106 and numeric property values (e.g. 100). So, it looks like this:
107 [((thin . 0) ... (heavy . 210))
108 ((ro . 0) ... (ot . 210))
109 ((ultracondensed . 50) ... (wide . 200))] */
110 static Lisp_Object font_style_table;
112 /* Alist of font family vs the corresponding aliases.
113 Each element has this form:
114 (FAMILY ALIAS1 ALIAS2 ...) */
116 static Lisp_Object font_family_alist;
118 /* Symbols representing keys of normal font properties. */
119 extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth, QCsize, QCname;
120 Lisp_Object QCfoundry, QCadstyle, QCregistry, QCextra;
121 /* Symbols representing keys of font extra info. */
122 Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClanguage, QCscript;
123 Lisp_Object QCantialias;
124 /* Symbols representing values of font spacing property. */
125 Lisp_Object Qc, Qm, Qp, Qd;
127 /* Alist of font registry symbol and the corresponding charsets
128 information. The information is retrieved from
129 Vfont_encoding_alist on demand.
131 Eash element has the form:
132 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
134 (REGISTRY . nil)
136 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
137 encodes a character code to a glyph code of a font, and
138 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
139 character is supported by a font.
141 The latter form means that the information for REGISTRY couldn't be
142 retrieved. */
143 static Lisp_Object font_charset_alist;
145 /* List of all font drivers. Each font-backend (XXXfont.c) calls
146 register_font_driver in syms_of_XXXfont to register its font-driver
147 here. */
148 static struct font_driver_list *font_driver_list;
150 static int font_pixel_size P_ ((FRAME_PTR f, Lisp_Object));
151 static Lisp_Object prop_name_to_numeric P_ ((enum font_property_index,
152 Lisp_Object));
153 static Lisp_Object prop_numeric_to_name P_ ((enum font_property_index, int));
154 static Lisp_Object font_open_entity P_ ((FRAME_PTR, Lisp_Object, int));
155 static void build_font_family_alist P_ ((void));
157 /* Number of registered font drivers. */
158 static int num_font_drivers;
160 /* Return a pixel size of font-spec SPEC on frame F. */
162 static int
163 font_pixel_size (f, spec)
164 FRAME_PTR f;
165 Lisp_Object spec;
167 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
168 double point_size;
169 int pixel_size, dpi;
170 Lisp_Object extra, val;
172 if (INTEGERP (size))
173 return XINT (size);
174 if (NILP (size))
175 return 0;
176 point_size = XFLOAT_DATA (size);
177 extra = AREF (spec, FONT_EXTRA_INDEX);
178 val = assq_no_quit (QCdpi, extra);
179 if (CONSP (val))
181 if (INTEGERP (XCDR (val)))
182 dpi = XINT (XCDR (val));
183 else
184 dpi = XFLOAT_DATA (XCDR (val)) + 0.5;
186 else
187 dpi = f->resy;
188 pixel_size = POINT_TO_PIXEL (point_size, dpi);
189 return pixel_size;
192 /* Return a numeric value corresponding to PROP's NAME (symbol). If
193 NAME is not registered in font_style_table, return Qnil. PROP must
194 be one of FONT_{WEIGHT|SLANT|SWIDTH}_INDEX. */
196 static Lisp_Object
197 prop_name_to_numeric (prop, name)
198 enum font_property_index prop;
199 Lisp_Object name;
201 int table_index = prop - FONT_WEIGHT_INDEX;
202 Lisp_Object val;
204 val = assq_no_quit (name, AREF (font_style_table, table_index));
205 return (NILP (val) ? Qnil : XCDR (val));
209 /* Return a name (symbol) corresponding to PROP's NUMERIC value. If
210 no name is registered for NUMERIC in font_style_table, return a
211 symbol of integer name (e.g. `123'). PROP must be one of
212 FONT_{WEIGHT|SLANT|SWIDTH}_INDEX. */
214 static Lisp_Object
215 prop_numeric_to_name (prop, numeric)
216 enum font_property_index prop;
217 int numeric;
219 int table_index = prop - FONT_WEIGHT_INDEX;
220 Lisp_Object table = AREF (font_style_table, table_index);
221 char buf[10];
223 while (! NILP (table))
225 if (XINT (XCDR (XCAR (table))) >= numeric)
227 if (XINT (XCDR (XCAR (table))) == numeric)
228 return XCAR (XCAR (table));
229 else
230 break;
232 table = XCDR (table);
234 sprintf (buf, "%d", numeric);
235 return intern (buf);
239 /* Return a symbol whose name is STR (length LEN). If STR contains
240 uppercase letters, downcase them in advance. */
242 Lisp_Object
243 intern_downcase (str, len)
244 char *str;
245 int len;
247 char *buf;
248 int i;
250 for (i = 0; i < len; i++)
251 if (isupper (str[i]))
252 break;
253 if (i == len)
254 return Fintern (make_unibyte_string (str, len), Qnil);
255 buf = alloca (len);
256 if (! buf)
257 return Fintern (null_string, Qnil);
258 bcopy (str, buf, len);
259 for (; i < len; i++)
260 if (isascii (buf[i]))
261 buf[i] = tolower (buf[i]);
262 return Fintern (make_unibyte_string (buf, len), Qnil);
265 extern Lisp_Object Vface_alternative_font_family_alist;
267 /* Setup font_family_alist of the form:
268 ((FAMILY-SYMBOL ALIAS-SYMBOL ...) ...)
269 from Vface_alternative_font_family_alist of the form:
270 ((FAMILY-STRING ALIAS-STRING ...) ...) */
272 static void
273 build_font_family_alist ()
275 Lisp_Object alist = Vface_alternative_font_family_alist;
277 for (; CONSP (alist); alist = XCDR (alist))
279 Lisp_Object tail, elt;
281 for (tail = XCAR (alist), elt = Qnil ; CONSP (tail); tail = XCDR (tail))
282 elt = nconc2 (elt, Fcons (Fintern (XCAR (tail), Qnil), Qnil));
283 font_family_alist = Fcons (elt, font_family_alist);
287 extern Lisp_Object find_font_encoding P_ ((Lisp_Object));
289 /* Return encoding charset and repertory charset for REGISTRY in
290 ENCODING and REPERTORY correspondingly. If correct information for
291 REGISTRY is available, return 0. Otherwise return -1. */
294 font_registry_charsets (registry, encoding, repertory)
295 Lisp_Object registry;
296 struct charset **encoding, **repertory;
298 Lisp_Object val;
299 int encoding_id, repertory_id;
301 val = assq_no_quit (registry, font_charset_alist);
302 if (! NILP (val))
304 val = XCDR (val);
305 if (NILP (val))
306 return -1;
307 encoding_id = XINT (XCAR (val));
308 repertory_id = XINT (XCDR (val));
310 else
312 val = find_font_encoding (SYMBOL_NAME (registry));
313 if (SYMBOLP (val) && CHARSETP (val))
315 encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val));
317 else if (CONSP (val))
319 if (! CHARSETP (XCAR (val)))
320 goto invalid_entry;
321 encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val)));
322 if (NILP (XCDR (val)))
323 repertory_id = -1;
324 else
326 if (! CHARSETP (XCDR (val)))
327 goto invalid_entry;
328 repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val)));
331 else
332 goto invalid_entry;
333 val = Fcons (make_number (encoding_id), make_number (repertory_id));
334 font_charset_alist
335 = nconc2 (font_charset_alist, Fcons (Fcons (registry, val), Qnil));
338 if (encoding)
339 *encoding = CHARSET_FROM_ID (encoding_id);
340 if (repertory)
341 *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL;
342 return 0;
344 invalid_entry:
345 font_charset_alist
346 = nconc2 (font_charset_alist, Fcons (Fcons (registry, Qnil), Qnil));
347 return -1;
351 /* Font property value validaters. See the comment of
352 font_property_table for the meaning of the arguments. */
354 static Lisp_Object font_prop_validate_symbol P_ ((Lisp_Object, Lisp_Object));
355 static Lisp_Object font_prop_validate_style P_ ((Lisp_Object, Lisp_Object));
356 static Lisp_Object font_prop_validate_non_neg P_ ((Lisp_Object, Lisp_Object));
357 static Lisp_Object font_prop_validate_spacing P_ ((Lisp_Object, Lisp_Object));
358 static int get_font_prop_index P_ ((Lisp_Object, int));
359 static Lisp_Object font_prop_validate P_ ((Lisp_Object));
361 static Lisp_Object
362 font_prop_validate_symbol (prop, val)
363 Lisp_Object prop, val;
365 if (EQ (prop, QCotf))
366 return (SYMBOLP (val) ? val : Qerror);
367 if (STRINGP (val))
368 val = (SCHARS (val) == 0 ? null_string
369 : intern_downcase ((char *) SDATA (val), SBYTES (val)));
370 else if (SYMBOLP (val))
372 if (SCHARS (SYMBOL_NAME (val)) == 0)
373 val = null_string;
375 else
376 val = Qerror;
377 return val;
380 static Lisp_Object
381 font_prop_validate_style (prop, val)
382 Lisp_Object prop, val;
384 if (! INTEGERP (val))
386 if (STRINGP (val))
387 val = intern_downcase ((char *) SDATA (val), SBYTES (val));
388 if (! SYMBOLP (val))
389 val = Qerror;
390 else
392 enum font_property_index prop_index
393 = (EQ (prop, QCweight) ? FONT_WEIGHT_INDEX
394 : EQ (prop, QCslant) ? FONT_SLANT_INDEX
395 : FONT_WIDTH_INDEX);
397 val = prop_name_to_numeric (prop_index, val);
398 if (NILP (val))
399 val = Qerror;
402 return val;
405 static Lisp_Object
406 font_prop_validate_non_neg (prop, val)
407 Lisp_Object prop, val;
409 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
410 ? val : Qerror);
413 static Lisp_Object
414 font_prop_validate_spacing (prop, val)
415 Lisp_Object prop, val;
417 if (NILP (val) || (NATNUMP (val) && XINT (val) <= FONT_SPACING_CHARCELL))
418 return val;
419 if (EQ (val, Qc))
420 return make_number (FONT_SPACING_CHARCELL);
421 if (EQ (val, Qm))
422 return make_number (FONT_SPACING_MONO);
423 if (EQ (val, Qp))
424 return make_number (FONT_SPACING_PROPORTIONAL);
425 return Qerror;
428 static Lisp_Object
429 font_prop_validate_otf (prop, val)
430 Lisp_Object prop, val;
432 Lisp_Object tail, tmp;
433 int i;
435 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
436 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
437 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
438 if (! CONSP (val))
439 return Qerror;
440 if (! SYMBOLP (XCAR (val)))
441 return Qerror;
442 tail = XCDR (val);
443 if (NILP (tail))
444 return val;
445 if (! CONSP (tail) || ! SYMBOLP (XCAR (val)))
446 return Qerror;
447 for (i = 0; i < 2; i++)
449 tail = XCDR (tail);
450 if (NILP (tail))
451 return val;
452 if (! CONSP (tail))
453 return Qerror;
454 for (tmp = XCAR (tail); CONSP (tmp); tmp = XCDR (tmp))
455 if (! SYMBOLP (XCAR (tmp)))
456 return Qerror;
457 if (! NILP (tmp))
458 return Qerror;
460 return val;
463 /* Structure of known font property keys and validater of the
464 values. */
465 struct
467 /* Pointer to the key symbol. */
468 Lisp_Object *key;
469 /* Function to validate PROP's value VAL, or NULL if any value is
470 ok. The value is VAL or its regularized value if VAL is valid,
471 and Qerror if not. */
472 Lisp_Object (*validater) P_ ((Lisp_Object prop, Lisp_Object val));
473 } font_property_table[] =
474 { { &QCtype, font_prop_validate_symbol },
475 { &QCfoundry, font_prop_validate_symbol },
476 { &QCfamily, font_prop_validate_symbol },
477 { &QCadstyle, font_prop_validate_symbol },
478 { &QCregistry, font_prop_validate_symbol },
479 { &QCweight, font_prop_validate_style },
480 { &QCslant, font_prop_validate_style },
481 { &QCwidth, font_prop_validate_style },
482 { &QCsize, font_prop_validate_non_neg },
483 { &QClanguage, font_prop_validate_symbol },
484 { &QCscript, font_prop_validate_symbol },
485 { &QCdpi, font_prop_validate_non_neg },
486 { &QCspacing, font_prop_validate_spacing },
487 { &QCscalable, NULL },
488 { &QCotf, font_prop_validate_otf },
489 { &QCantialias, font_prop_validate_symbol }
492 /* Size (number of elements) of the above table. */
493 #define FONT_PROPERTY_TABLE_SIZE \
494 ((sizeof font_property_table) / (sizeof *font_property_table))
496 /* Return an index number of font property KEY or -1 if KEY is not an
497 already known property. Start searching font_property_table from
498 index FROM (which is 0 or FONT_EXTRA_INDEX). */
500 static int
501 get_font_prop_index (key, from)
502 Lisp_Object key;
503 int from;
505 for (; from < FONT_PROPERTY_TABLE_SIZE; from++)
506 if (EQ (key, *font_property_table[from].key))
507 return from;
508 return -1;
511 /* Validate font properties in SPEC (vector) while updating elements
512 to regularized values. Signal an error if an invalid property is
513 found. */
515 static Lisp_Object
516 font_prop_validate (spec)
517 Lisp_Object spec;
519 int i;
520 Lisp_Object prop, val, extra;
522 for (i = FONT_TYPE_INDEX; i < FONT_EXTRA_INDEX; i++)
524 if (! NILP (AREF (spec, i)))
526 prop = *font_property_table[i].key;
527 val = (font_property_table[i].validater) (prop, AREF (spec, i));
528 if (EQ (val, Qerror))
529 Fsignal (Qfont, list2 (build_string ("invalid font property"),
530 Fcons (prop, AREF (spec, i))));
531 ASET (spec, i, val);
534 for (extra = AREF (spec, FONT_EXTRA_INDEX);
535 CONSP (extra); extra = XCDR (extra))
537 Lisp_Object elt = XCAR (extra);
539 prop = XCAR (elt);
540 i = get_font_prop_index (prop, FONT_EXTRA_INDEX);
541 if (i >= 0
542 && font_property_table[i].validater)
544 val = (font_property_table[i].validater) (prop, XCDR (elt));
545 if (EQ (val, Qerror))
546 signal_error ("invalid font property", elt);
547 XSETCDR (elt, val);
550 return spec;
553 /* Store VAL as a value of extra font property PROP in FONT. */
555 Lisp_Object
556 font_put_extra (font, prop, val)
557 Lisp_Object font, prop, val;
559 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
560 Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
562 if (NILP (slot))
564 extra = Fcons (Fcons (prop, val), extra);
565 ASET (font, FONT_EXTRA_INDEX, extra);
566 return val;
568 XSETCDR (slot, val);
569 return val;
573 /* Font name parser and unparser */
575 static Lisp_Object intern_font_field P_ ((char *, int));
576 static int parse_matrix P_ ((char *));
577 static int font_expand_wildcards P_ ((Lisp_Object *, int));
578 static int font_parse_name P_ ((char *, Lisp_Object));
580 /* An enumerator for each field of an XLFD font name. */
581 enum xlfd_field_index
583 XLFD_FOUNDRY_INDEX,
584 XLFD_FAMILY_INDEX,
585 XLFD_WEIGHT_INDEX,
586 XLFD_SLANT_INDEX,
587 XLFD_SWIDTH_INDEX,
588 XLFD_ADSTYLE_INDEX,
589 XLFD_PIXEL_INDEX,
590 XLFD_POINT_INDEX,
591 XLFD_RESX_INDEX,
592 XLFD_RESY_INDEX,
593 XLFD_SPACING_INDEX,
594 XLFD_AVGWIDTH_INDEX,
595 XLFD_REGISTRY_INDEX,
596 XLFD_ENCODING_INDEX,
597 XLFD_LAST_INDEX
600 /* An enumerator for mask bit corresponding to each XLFD field. */
601 enum xlfd_field_mask
603 XLFD_FOUNDRY_MASK = 0x0001,
604 XLFD_FAMILY_MASK = 0x0002,
605 XLFD_WEIGHT_MASK = 0x0004,
606 XLFD_SLANT_MASK = 0x0008,
607 XLFD_SWIDTH_MASK = 0x0010,
608 XLFD_ADSTYLE_MASK = 0x0020,
609 XLFD_PIXEL_MASK = 0x0040,
610 XLFD_POINT_MASK = 0x0080,
611 XLFD_RESX_MASK = 0x0100,
612 XLFD_RESY_MASK = 0x0200,
613 XLFD_SPACING_MASK = 0x0400,
614 XLFD_AVGWIDTH_MASK = 0x0800,
615 XLFD_REGISTRY_MASK = 0x1000,
616 XLFD_ENCODING_MASK = 0x2000
620 /* Return a Lispy value of a XLFD font field at STR and LEN bytes.
621 If LEN is zero, it returns `null_string'.
622 If STR is "*", it returns nil.
623 If all characters in STR are digits, it returns an integer.
624 Otherwise, it returns a symbol interned from downcased STR. */
626 static Lisp_Object
627 intern_font_field (str, len)
628 char *str;
629 int len;
631 int i;
633 if (len == 0)
634 return null_string;
635 if (*str == '*' && len == 1)
636 return Qnil;
637 if (isdigit (*str))
639 for (i = 1; i < len; i++)
640 if (! isdigit (str[i]))
641 break;
642 if (i == len)
643 return make_number (atoi (str));
645 return intern_downcase (str, len);
648 /* Parse P pointing the pixel/point size field of the form
649 `[A B C D]' which specifies a transformation matrix:
651 A B 0
652 C D 0
653 0 0 1
655 by which all glyphs of the font are transformed. The spec says
656 that scalar value N for the pixel/point size is equivalent to:
657 A = N * resx/resy, B = C = 0, D = N.
659 Return the scalar value N if the form is valid. Otherwise return
660 -1. */
662 static int
663 parse_matrix (p)
664 char *p;
666 double matrix[4];
667 char *end;
668 int i;
670 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
672 if (*p == '~')
673 matrix[i] = - strtod (p + 1, &end);
674 else
675 matrix[i] = strtod (p, &end);
676 p = end;
678 return (i == 4 ? (int) matrix[3] : -1);
681 /* Expand a wildcard field in FIELD (the first N fields are filled) to
682 multiple fields to fill in all 14 XLFD fields while restring a
683 field position by its contents. */
685 static int
686 font_expand_wildcards (field, n)
687 Lisp_Object field[XLFD_LAST_INDEX];
688 int n;
690 /* Copy of FIELD. */
691 Lisp_Object tmp[XLFD_LAST_INDEX];
692 /* Array of information about where this element can go. Nth
693 element is for Nth element of FIELD. */
694 struct {
695 /* Minimum possible field. */
696 int from;
697 /* Maxinum possible field. */
698 int to;
699 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
700 int mask;
701 } range[XLFD_LAST_INDEX];
702 int i, j;
703 int range_from, range_to;
704 unsigned range_mask;
706 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
707 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
708 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
709 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
710 | XLFD_AVGWIDTH_MASK)
711 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
713 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
714 field. The value is shifted to left one bit by one in the
715 following loop. */
716 for (i = 0, range_mask = 0; i <= 14 - n; i++)
717 range_mask = (range_mask << 1) | 1;
719 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
720 position-based retriction for FIELD[I]. */
721 for (i = 0, range_from = 0, range_to = 14 - n; i < n;
722 i++, range_from++, range_to++, range_mask <<= 1)
724 Lisp_Object val = field[i];
726 tmp[i] = val;
727 if (NILP (val))
729 /* Wildcard. */
730 range[i].from = range_from;
731 range[i].to = range_to;
732 range[i].mask = range_mask;
734 else
736 /* The triplet FROM, TO, and MASK is a value-based
737 retriction for FIELD[I]. */
738 int from, to;
739 unsigned mask;
741 if (INTEGERP (val))
743 int numeric = XINT (val);
745 if (i + 1 == n)
746 from = to = XLFD_ENCODING_INDEX,
747 mask = XLFD_ENCODING_MASK;
748 else if (numeric == 0)
749 from = XLFD_PIXEL_INDEX, to = XLFD_AVGWIDTH_INDEX,
750 mask = XLFD_PIXEL_MASK | XLFD_LARGENUM_MASK;
751 else if (numeric <= 48)
752 from = to = XLFD_PIXEL_INDEX,
753 mask = XLFD_PIXEL_MASK;
754 else
755 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
756 mask = XLFD_LARGENUM_MASK;
758 else if (EQ (val, null_string))
759 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
760 mask = XLFD_NULL_MASK;
761 else if (i == 0)
762 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
763 else if (i + 1 == n)
765 Lisp_Object name = SYMBOL_NAME (val);
767 if (SDATA (name)[SBYTES (name) - 1] == '*')
768 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
769 mask = XLFD_REGENC_MASK;
770 else
771 from = to = XLFD_ENCODING_INDEX,
772 mask = XLFD_ENCODING_MASK;
774 else if (range_from <= XLFD_WEIGHT_INDEX
775 && range_to >= XLFD_WEIGHT_INDEX
776 && !NILP (prop_name_to_numeric (FONT_WEIGHT_INDEX, val)))
777 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
778 else if (range_from <= XLFD_SLANT_INDEX
779 && range_to >= XLFD_SLANT_INDEX
780 && !NILP (prop_name_to_numeric (FONT_SLANT_INDEX, val)))
781 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
782 else if (range_from <= XLFD_SWIDTH_INDEX
783 && range_to >= XLFD_SWIDTH_INDEX
784 && !NILP (prop_name_to_numeric (FONT_WIDTH_INDEX, val)))
785 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
786 else
788 if (EQ (val, Qc) || EQ (val, Qm) || EQ (val, Qp) || EQ (val, Qd))
789 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
790 else
791 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
792 mask = XLFD_SYMBOL_MASK;
795 /* Merge position-based and value-based restrictions. */
796 mask &= range_mask;
797 while (from < range_from)
798 mask &= ~(1 << from++);
799 while (from < 14 && ! (mask & (1 << from)))
800 from++;
801 while (to > range_to)
802 mask &= ~(1 << to--);
803 while (to >= 0 && ! (mask & (1 << to)))
804 to--;
805 if (from > to)
806 return -1;
807 range[i].from = from;
808 range[i].to = to;
809 range[i].mask = mask;
811 if (from > range_from || to < range_to)
813 /* The range is narrowed by value-based restrictions.
814 Reflect it to the other fields. */
816 /* Following fields should be after FROM. */
817 range_from = from;
818 /* Preceding fields should be before TO. */
819 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
821 /* Check FROM for non-wildcard field. */
822 if (! NILP (tmp[j]) && range[j].from < from)
824 while (range[j].from < from)
825 range[j].mask &= ~(1 << range[j].from++);
826 while (from < 14 && ! (range[j].mask & (1 << from)))
827 from++;
828 range[j].from = from;
830 else
831 from = range[j].from;
832 if (range[j].to > to)
834 while (range[j].to > to)
835 range[j].mask &= ~(1 << range[j].to--);
836 while (to >= 0 && ! (range[j].mask & (1 << to)))
837 to--;
838 range[j].to = to;
840 else
841 to = range[j].to;
842 if (from > to)
843 return -1;
849 /* Decide all fileds from restrictions in RANGE. */
850 for (i = j = 0; i < n ; i++)
852 if (j < range[i].from)
854 if (i == 0 || ! NILP (tmp[i - 1]))
855 /* None of TMP[X] corresponds to Jth field. */
856 return -1;
857 for (; j < range[i].from; j++)
858 field[j] = Qnil;
860 field[j++] = tmp[i];
862 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
863 return -1;
864 for (; j < XLFD_LAST_INDEX; j++)
865 field[j] = Qnil;
866 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
867 field[XLFD_ENCODING_INDEX]
868 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
869 return 0;
873 #ifdef ENABLE_CHECKING
874 /* Match a 14-field XLFD pattern against a full XLFD font name. */
875 static int
876 font_match_xlfd (char *pattern, char *name)
878 while (*pattern && *name)
880 if (*pattern == *name)
881 pattern++;
882 else if (*pattern == '*')
883 if (*name == pattern[1])
884 pattern += 2;
885 else
887 else
888 return 0;
889 name++;
891 return 1;
894 /* Make sure the font object matches the XLFD font name. */
895 static int
896 font_check_xlfd_parse (Lisp_Object font, char *name)
898 char name_check[256];
899 font_unparse_xlfd (font, 0, name_check, 255);
900 return font_match_xlfd (name_check, name);
903 #endif
905 /* Parse NAME (null terminated) as XLFD and store information in FONT
906 (font-spec or font-entity). Size property of FONT is set as
907 follows:
908 specified XLFD fields FONT property
909 --------------------- -------------
910 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
911 POINT_SIZE and RESY calculated pixel size (Lisp integer)
912 POINT_SIZE POINT_SIZE/10 (Lisp float)
914 If NAME is successfully parsed, return 0. Otherwise return -1.
916 FONT is usually a font-spec, but when this function is called from
917 X font backend driver, it is a font-entity. In that case, NAME is
918 a fully specified XLFD, and we set FONT_EXTRA_INDEX of FONT to a
919 symbol RESX-RESY-SPACING-AVGWIDTH.
923 font_parse_xlfd (name, font)
924 char *name;
925 Lisp_Object font;
927 int len = strlen (name);
928 int i, j;
929 Lisp_Object dpi, spacing;
930 int avgwidth;
931 char *f[XLFD_LAST_INDEX + 1];
932 Lisp_Object val;
933 char *p;
935 if (len > 255)
936 /* Maximum XLFD name length is 255. */
937 return -1;
938 /* Accept "*-.." as a fully specified XLFD. */
939 if (name[0] == '*' && name[1] == '-')
940 i = 1, f[XLFD_FOUNDRY_INDEX] = name;
941 else
942 i = 0;
943 for (p = name + i; *p; p++)
944 if (*p == '-' && i < XLFD_LAST_INDEX)
945 f[i++] = p + 1;
946 f[i] = p;
948 dpi = spacing = Qnil;
949 avgwidth = -1;
951 if (i == XLFD_LAST_INDEX)
953 int pixel_size;
955 /* Fully specified XLFD. */
956 for (i = 0, j = FONT_FOUNDRY_INDEX; i < XLFD_WEIGHT_INDEX; i++, j++)
958 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
959 if (! NILP (val))
960 ASET (font, j, val);
962 for (j = FONT_WEIGHT_INDEX; i < XLFD_ADSTYLE_INDEX; i++, j++)
964 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
965 if (! NILP (val))
967 Lisp_Object numeric = prop_name_to_numeric (j, val);
969 if (INTEGERP (numeric))
970 val = numeric;
971 ASET (font, j, val);
974 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
975 if (! NILP (val))
976 ASET (font, FONT_ADSTYLE_INDEX, val);
977 i = XLFD_REGISTRY_INDEX;
978 val = intern_font_field (f[i], f[i + 2] - f[i]);
979 if (! NILP (val))
980 ASET (font, FONT_REGISTRY_INDEX, val);
982 p = f[XLFD_PIXEL_INDEX];
983 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
984 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
985 else
987 i = XLFD_PIXEL_INDEX;
988 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
989 if (! NILP (val))
990 ASET (font, FONT_SIZE_INDEX, val);
991 else
993 double point_size = -1;
995 xassert (FONT_SPEC_P (font));
996 p = f[XLFD_POINT_INDEX];
997 if (*p == '[')
998 point_size = parse_matrix (p);
999 else if (isdigit (*p))
1000 point_size = atoi (p), point_size /= 10;
1001 if (point_size >= 0)
1002 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1003 else
1005 i = XLFD_PIXEL_INDEX;
1006 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
1007 if (! NILP (val))
1008 ASET (font, FONT_SIZE_INDEX, val);
1013 /* Parse RESX, RESY, SPACING, and AVGWIDTH. */
1014 if (FONT_ENTITY_P (font))
1016 i = XLFD_RESX_INDEX;
1017 ASET (font, FONT_EXTRA_INDEX,
1018 intern_font_field (f[i], f[XLFD_REGISTRY_INDEX] - 1 - f[i]));
1019 eassert (font_check_xlfd_parse (font, name));
1020 return 0;
1023 /* Here we just setup DPI, SPACING, and AVGWIDTH. They are set
1024 in FONT_EXTRA_INDEX later. */
1025 i = XLFD_RESX_INDEX;
1026 dpi = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
1027 i = XLFD_SPACING_INDEX;
1028 spacing = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
1029 p = f[XLFD_AVGWIDTH_INDEX];
1030 if (*p == '~')
1031 p++;
1032 if (isdigit (*p))
1033 avgwidth = atoi (p);
1035 else
1037 int wild_card_found = 0;
1038 Lisp_Object prop[XLFD_LAST_INDEX];
1040 for (j = 0; j < i; j++)
1042 if (*f[j] == '*')
1044 if (f[j][1] && f[j][1] != '-')
1045 return -1;
1046 prop[j] = Qnil;
1047 wild_card_found = 1;
1049 else if (isdigit (*f[j]))
1051 for (p = f[j] + 1; isdigit (*p); p++);
1052 if (*p && *p != '-')
1053 prop[j] = intern_downcase (f[j], p - f[j]);
1054 else
1055 prop[j] = make_number (atoi (f[j]));
1057 else if (j + 1 < i)
1058 prop[j] = intern_font_field (f[j], f[j + 1] - 1 - f[j]);
1059 else
1060 prop[j] = intern_font_field (f[j], f[i] - f[j]);
1062 if (! wild_card_found)
1063 return -1;
1064 if (font_expand_wildcards (prop, i) < 0)
1065 return -1;
1067 for (i = 0, j = FONT_FOUNDRY_INDEX; i < XLFD_WEIGHT_INDEX; i++, j++)
1068 if (! NILP (prop[i]))
1069 ASET (font, j, prop[i]);
1070 for (j = FONT_WEIGHT_INDEX; i < XLFD_ADSTYLE_INDEX; i++, j++)
1071 if (! NILP (prop[i]))
1072 ASET (font, j, prop[i]);
1073 if (! NILP (prop[XLFD_ADSTYLE_INDEX]))
1074 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1075 val = prop[XLFD_REGISTRY_INDEX];
1076 if (NILP (val))
1078 val = prop[XLFD_ENCODING_INDEX];
1079 if (! NILP (val))
1080 val = Fintern (concat2 (build_string ("*-"), SYMBOL_NAME (val)),
1081 Qnil);
1083 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1084 val = Fintern (concat2 (SYMBOL_NAME (val), build_string ("-*")),
1085 Qnil);
1086 else
1087 val = Fintern (concat3 (SYMBOL_NAME (val), build_string ("-"),
1088 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX])),
1089 Qnil);
1090 if (! NILP (val))
1091 ASET (font, FONT_REGISTRY_INDEX, val);
1093 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1094 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
1095 else if (INTEGERP (prop[XLFD_POINT_INDEX]))
1097 double point_size = XINT (prop[XLFD_POINT_INDEX]);
1099 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1102 dpi = prop[XLFD_RESX_INDEX];
1103 spacing = prop[XLFD_SPACING_INDEX];
1104 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1105 avgwidth = XINT (prop[XLFD_AVGWIDTH_INDEX]);
1108 if (! NILP (dpi))
1109 font_put_extra (font, QCdpi, dpi);
1110 if (! NILP (spacing))
1111 font_put_extra (font, QCspacing, spacing);
1112 if (avgwidth >= 0)
1113 font_put_extra (font, QCscalable, avgwidth == 0 ? Qt : Qnil);
1115 return 0;
1118 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1119 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1120 0, use PIXEL_SIZE instead. */
1123 font_unparse_xlfd (font, pixel_size, name, nbytes)
1124 Lisp_Object font;
1125 int pixel_size;
1126 char *name;
1127 int nbytes;
1129 char *f[XLFD_REGISTRY_INDEX + 1];
1130 Lisp_Object val;
1131 int i, j, len = 0;
1133 xassert (FONTP (font));
1135 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
1136 i++, j++)
1138 if (i == FONT_ADSTYLE_INDEX)
1139 j = XLFD_ADSTYLE_INDEX;
1140 else if (i == FONT_REGISTRY_INDEX)
1141 j = XLFD_REGISTRY_INDEX;
1142 val = AREF (font, i);
1143 if (NILP (val))
1145 if (j == XLFD_REGISTRY_INDEX)
1146 f[j] = "*-*", len += 4;
1147 else
1148 f[j] = "*", len += 2;
1150 else
1152 if (SYMBOLP (val))
1153 val = SYMBOL_NAME (val);
1154 if (j == XLFD_REGISTRY_INDEX
1155 && ! strchr ((char *) SDATA (val), '-'))
1157 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1158 if (SDATA (val)[SBYTES (val) - 1] == '*')
1160 f[j] = alloca (SBYTES (val) + 3);
1161 sprintf (f[j], "%s-*", SDATA (val));
1162 len += SBYTES (val) + 3;
1164 else
1166 f[j] = alloca (SBYTES (val) + 4);
1167 sprintf (f[j], "%s*-*", SDATA (val));
1168 len += SBYTES (val) + 4;
1171 else
1172 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1176 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1177 i++, j++)
1179 val = AREF (font, i);
1180 if (NILP (val))
1181 f[j] = "*", len += 2;
1182 else
1184 if (INTEGERP (val))
1185 val = prop_numeric_to_name (i, XINT (val));
1186 if (SYMBOLP (val))
1187 val = SYMBOL_NAME (val);
1188 xassert (STRINGP (val));
1189 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1193 val = AREF (font, FONT_SIZE_INDEX);
1194 xassert (NUMBERP (val) || NILP (val));
1195 if (INTEGERP (val))
1197 int i = XINT (val);
1198 if (i <= 0)
1199 i = pixel_size;
1200 if (i > 0)
1202 f[XLFD_PIXEL_INDEX] = alloca (22);
1203 len += sprintf (f[XLFD_PIXEL_INDEX], "%d-*", i) + 1;
1205 else
1206 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1208 else if (FLOATP (val))
1210 int i = XFLOAT_DATA (val) * 10;
1211 f[XLFD_PIXEL_INDEX] = alloca (12);
1212 len += sprintf (f[XLFD_PIXEL_INDEX], "*-%d", i) + 1;
1214 else
1215 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1217 val = AREF (font, FONT_EXTRA_INDEX);
1219 if (FONT_ENTITY_P (font)
1220 && EQ (AREF (font, FONT_TYPE_INDEX), Qx))
1222 /* Setup names for RESX-RESY-SPACING-AVWIDTH. */
1223 if (SYMBOLP (val) && ! NILP (val))
1225 val = SYMBOL_NAME (val);
1226 f[XLFD_RESX_INDEX] = (char *) SDATA (val), len += SBYTES (val) + 1;
1228 else
1229 f[XLFD_RESX_INDEX] = "*-*-*-*", len += 6;
1231 else
1233 Lisp_Object dpi = assq_no_quit (QCdpi, val);
1234 Lisp_Object spacing = assq_no_quit (QCspacing, val);
1235 Lisp_Object scalable = assq_no_quit (QCscalable, val);
1237 if (CONSP (dpi) || CONSP (spacing) || CONSP (scalable))
1239 char *str = alloca (24);
1240 int this_len;
1242 if (CONSP (dpi) && INTEGERP (XCDR (dpi)))
1243 this_len = sprintf (str, "%d-%d",
1244 XINT (XCDR (dpi)), XINT (XCDR (dpi)));
1245 else
1246 this_len = sprintf (str, "*-*");
1247 if (CONSP (spacing) && ! NILP (XCDR (spacing)))
1249 val = XCDR (spacing);
1250 if (INTEGERP (val))
1252 if (XINT (val) < FONT_SPACING_MONO)
1253 val = Qp;
1254 else if (XINT (val) < FONT_SPACING_CHARCELL)
1255 val = Qm;
1256 else
1257 val = Qc;
1259 xassert (SYMBOLP (val));
1260 this_len += sprintf (str + this_len, "-%c",
1261 SDATA (SYMBOL_NAME (val))[0]);
1263 else
1264 this_len += sprintf (str + this_len, "-*");
1265 if (CONSP (scalable) && ! NILP (XCDR (spacing)))
1266 this_len += sprintf (str + this_len, "-0");
1267 else
1268 this_len += sprintf (str + this_len, "-*");
1269 f[XLFD_RESX_INDEX] = str;
1270 len += this_len;
1272 else
1273 f[XLFD_RESX_INDEX] = "*-*-*-*", len += 8;
1276 len++; /* for terminating '\0'. */
1277 if (len >= nbytes)
1278 return -1;
1279 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1280 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1281 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1282 f[XLFD_SWIDTH_INDEX],
1283 f[XLFD_ADSTYLE_INDEX], f[XLFD_PIXEL_INDEX],
1284 f[XLFD_RESX_INDEX], f[XLFD_REGISTRY_INDEX]);
1287 /* Parse NAME (null terminated) as Fonconfig's name format and store
1288 information in FONT (font-spec or font-entity). If NAME is
1289 successfully parsed, return 0. Otherwise return -1. */
1292 font_parse_fcname (name, font)
1293 char *name;
1294 Lisp_Object font;
1296 char *p0, *p1;
1297 int len = strlen (name);
1298 char *copy;
1299 int weight_set = 0;
1300 int slant_set = 0;
1302 if (len == 0)
1303 return -1;
1304 /* It is assured that (name[0] && name[0] != '-'). */
1305 if (name[0] == ':')
1306 p0 = name;
1307 else
1309 Lisp_Object family;
1310 double point_size;
1312 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++)
1313 if (*p0 == '\\' && p0[1])
1314 p0++;
1315 family = intern_font_field (name, p0 - name);
1316 if (*p0 == '-')
1318 if (! isdigit (p0[1]))
1319 return -1;
1320 point_size = strtod (p0 + 1, &p1);
1321 if (*p1 && *p1 != ':')
1322 return -1;
1323 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1324 p0 = p1;
1326 ASET (font, FONT_FAMILY_INDEX, family);
1329 len -= p0 - name;
1330 copy = alloca (len + 1);
1331 if (! copy)
1332 return -1;
1333 name = copy;
1335 /* Now parse ":KEY=VAL" patterns. Store known keys and values in
1336 extra, copy unknown ones to COPY. */
1337 while (*p0)
1339 Lisp_Object key, val;
1340 int prop;
1342 for (p1 = p0 + 1; *p1 && *p1 != '=' && *p1 != ':'; p1++);
1343 if (*p1 != '=')
1345 /* Must be an enumerated value. */
1346 val = intern_font_field (p0 + 1, p1 - p0 - 1);
1347 if (memcmp (p0 + 1, "light", 5) == 0
1348 || memcmp (p0 + 1, "medium", 6) == 0
1349 || memcmp (p0 + 1, "demibold", 8) == 0
1350 || memcmp (p0 + 1, "bold", 4) == 0
1351 || memcmp (p0 + 1, "black", 5) == 0)
1353 ASET (font, FONT_WEIGHT_INDEX, val);
1354 weight_set = 1;
1356 else if (memcmp (p0 + 1, "roman", 5) == 0
1357 || memcmp (p0 + 1, "italic", 6) == 0
1358 || memcmp (p0 + 1, "oblique", 7) == 0)
1360 ASET (font, FONT_SLANT_INDEX, val);
1361 slant_set = 1;
1363 else if (memcmp (p0 + 1, "charcell", 8) == 0
1364 || memcmp (p0 + 1, "mono", 4) == 0
1365 || memcmp (p0 + 1, "proportional", 12) == 0)
1367 font_put_extra (font, QCspacing,
1368 (p0[1] == 'c' ? Qc : p0[1] == 'm' ? Qm : Qp));
1370 else
1372 /* unknown key */
1373 bcopy (p0, copy, p1 - p0);
1374 copy += p1 - p0;
1377 else
1379 if (memcmp (p0 + 1, "pixelsize=", 10) == 0)
1380 prop = FONT_SIZE_INDEX;
1381 else
1383 key = intern_font_field (p0, p1 - p0);
1384 prop = get_font_prop_index (key, 0);
1386 p0 = p1 + 1;
1387 for (p1 = p0; *p1 && *p1 != ':'; p1++);
1388 val = intern_font_field (p0, p1 - p0);
1389 if (! NILP (val))
1391 if (prop >= 0 && prop < FONT_EXTRA_INDEX)
1393 if (prop == FONT_WEIGHT_INDEX)
1394 weight_set = 1;
1395 else if (prop == FONT_SLANT_INDEX)
1396 slant_set = 1;
1398 ASET (font, prop, val);
1400 else
1401 font_put_extra (font, key, val);
1404 p0 = p1;
1407 if (!weight_set)
1408 ASET (font, FONT_WEIGHT_INDEX, build_string ("normal"));
1409 if (!slant_set)
1410 ASET (font, FONT_SLANT_INDEX, build_string ("normal"));
1412 return 0;
1415 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1416 NAME (NBYTES length), and return the name length. If
1417 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1420 font_unparse_fcname (font, pixel_size, name, nbytes)
1421 Lisp_Object font;
1422 int pixel_size;
1423 char *name;
1424 int nbytes;
1426 Lisp_Object val;
1427 int point_size;
1428 int dpi, spacing, scalable;
1429 int i, len = 1;
1430 char *p;
1431 Lisp_Object styles[3];
1432 char *style_names[3] = { "weight", "slant", "width" };
1434 val = AREF (font, FONT_FAMILY_INDEX);
1435 if (SYMBOLP (val) && ! NILP (val))
1436 len += SBYTES (SYMBOL_NAME (val));
1438 val = AREF (font, FONT_SIZE_INDEX);
1439 if (INTEGERP (val))
1441 if (XINT (val) != 0)
1442 pixel_size = XINT (val);
1443 point_size = -1;
1444 len += 21; /* for ":pixelsize=NUM" */
1446 else if (FLOATP (val))
1448 pixel_size = -1;
1449 point_size = (int) XFLOAT_DATA (val);
1450 len += 11; /* for "-NUM" */
1453 val = AREF (font, FONT_FOUNDRY_INDEX);
1454 if (SYMBOLP (val) && ! NILP (val))
1455 /* ":foundry=NAME" */
1456 len += 9 + SBYTES (SYMBOL_NAME (val));
1458 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
1460 val = AREF (font, i);
1461 if (INTEGERP (val))
1463 val = prop_numeric_to_name (i, XINT (val));
1465 if (SYMBOLP (val) && ! NILP (val))
1466 len += (strlen (style_names[i - FONT_WEIGHT_INDEX])
1467 + 2 + SBYTES (SYMBOL_NAME (val))); /* :xxx=NAME */
1468 styles[i - FONT_WEIGHT_INDEX] = val;
1471 val = AREF (font, FONT_EXTRA_INDEX);
1472 if (FONT_ENTITY_P (font)
1473 && EQ (AREF (font, FONT_TYPE_INDEX), Qx))
1475 char *p;
1477 /* VAL is a symbol of name `RESX-RESY-SPACING-AVWIDTH'. */
1478 p = (char *) SDATA (SYMBOL_NAME (val));
1479 dpi = atoi (p);
1480 for (p++; *p != '-'; p++); /* skip RESX */
1481 for (p++; *p != '-'; p++); /* skip RESY */
1482 spacing = (*p == 'c' ? FONT_SPACING_CHARCELL
1483 : *p == 'm' ? FONT_SPACING_MONO
1484 : FONT_SPACING_PROPORTIONAL);
1485 for (p++; *p != '-'; p++); /* skip SPACING */
1486 scalable = (atoi (p) == 0);
1487 /* The longest pattern is ":dpi=NUM:scalable=False:spacing=100" */
1488 len += 42;
1490 else
1492 Lisp_Object elt;
1494 dpi = spacing = scalable = -1;
1495 elt = assq_no_quit (QCdpi, val);
1496 if (CONSP (elt))
1497 dpi = XINT (XCDR (elt)), len += 15; /* for ":dpi=NUM" */
1498 elt = assq_no_quit (QCspacing, val);
1499 if (CONSP (elt))
1500 spacing = XINT (XCDR (elt)), len += 12; /* for ":spacing=100" */
1501 elt = assq_no_quit (QCscalable, val);
1502 if (CONSP (elt))
1503 scalable = ! NILP (XCDR (elt)), len += 15; /* for ":scalable=False" */
1506 if (len > nbytes)
1507 return -1;
1508 p = name;
1509 if (! NILP (AREF (font, FONT_FAMILY_INDEX)))
1510 p += sprintf(p, "%s",
1511 SDATA (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX))));
1512 if (point_size > 0)
1514 if (p == name)
1515 p += sprintf (p, "%d", point_size);
1516 else
1517 p += sprintf (p, "-%d", point_size);
1519 else if (pixel_size > 0)
1520 p += sprintf (p, ":pixelsize=%d", pixel_size);
1521 if (SYMBOLP (AREF (font, FONT_FOUNDRY_INDEX))
1522 && ! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1523 p += sprintf (p, ":foundry=%s",
1524 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1525 for (i = 0; i < 3; i++)
1526 if (SYMBOLP (styles[i]) && ! NILP (styles [i]))
1527 p += sprintf (p, ":%s=%s", style_names[i],
1528 SDATA (SYMBOL_NAME (styles [i])));
1529 if (dpi >= 0)
1530 p += sprintf (p, ":dpi=%d", dpi);
1531 if (spacing >= 0)
1532 p += sprintf (p, ":spacing=%d", spacing);
1533 if (scalable > 0)
1534 p += sprintf (p, ":scalable=True");
1535 else if (scalable == 0)
1536 p += sprintf (p, ":scalable=False");
1537 return (p - name);
1540 /* Parse NAME (null terminated) and store information in FONT
1541 (font-spec or font-entity). If NAME is successfully parsed, return
1542 0. Otherwise return -1.
1544 If NAME is XLFD and FONT is a font-entity, store
1545 RESX-RESY-SPACING-AVWIDTH information as a symbol in
1546 FONT_EXTRA_INDEX. */
1548 static int
1549 font_parse_name (name, font)
1550 char *name;
1551 Lisp_Object font;
1553 if (name[0] == '-' || index (name, '*'))
1554 return font_parse_xlfd (name, font);
1555 return font_parse_fcname (name, font);
1558 /* Merge old style font specification (either a font name NAME or a
1559 combination of a family name FAMILY and a registry name REGISTRY
1560 into the font specification SPEC. */
1562 void
1563 font_merge_old_spec (name, family, registry, spec)
1564 Lisp_Object name, family, registry, spec;
1566 if (STRINGP (name))
1568 if (font_parse_xlfd ((char *) SDATA (name), spec) < 0)
1570 Lisp_Object extra = Fcons (Fcons (QCname, name), Qnil);
1572 ASET (spec, FONT_EXTRA_INDEX, extra);
1575 else
1577 if (! NILP (family))
1579 int len;
1580 char *p0, *p1;
1582 xassert (STRINGP (family));
1583 len = SBYTES (family);
1584 p0 = (char *) SDATA (family);
1585 p1 = index (p0, '-');
1586 if (p1)
1588 if ((*p0 != '*' || p1 - p0 > 1)
1589 && NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
1590 ASET (spec, FONT_FOUNDRY_INDEX,
1591 intern_downcase (p0, p1 - p0));
1592 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1593 ASET (spec, FONT_FAMILY_INDEX,
1594 intern_downcase (p1 + 1, len - (p1 + 1 - p0)));
1596 else if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1597 ASET (spec, FONT_FAMILY_INDEX, intern_downcase (p0, len));
1599 if (! NILP (registry)
1600 && NILP (AREF (spec, FONT_REGISTRY_INDEX)))
1601 ASET (spec, FONT_REGISTRY_INDEX,
1602 intern_downcase ((char *) SDATA (registry), SBYTES (registry)));
1607 /* This part (through the next ^L) is still experimental and never
1608 tested. We may drastically change codes. */
1610 /* OTF handler */
1612 #define LGSTRING_HEADER_SIZE 6
1613 #define LGSTRING_GLYPH_SIZE 8
1615 static int
1616 check_gstring (gstring)
1617 Lisp_Object gstring;
1619 Lisp_Object val;
1620 int i, j;
1622 CHECK_VECTOR (gstring);
1623 val = AREF (gstring, 0);
1624 CHECK_VECTOR (val);
1625 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1626 goto err;
1627 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1628 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1629 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1630 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1631 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1632 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1633 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1634 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1635 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1636 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1637 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1639 for (i = 0; i < LGSTRING_LENGTH (gstring); i++)
1641 val = LGSTRING_GLYPH (gstring, i);
1642 CHECK_VECTOR (val);
1643 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1644 goto err;
1645 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1646 break;
1647 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1648 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1649 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1650 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1651 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1652 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1653 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1654 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1656 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1657 CHECK_VECTOR (val);
1658 if (ASIZE (val) < 3)
1659 goto err;
1660 for (j = 0; j < 3; j++)
1661 CHECK_NUMBER (AREF (val, j));
1664 return i;
1665 err:
1666 error ("Invalid glyph-string format");
1667 return -1;
1670 static void
1671 check_otf_features (otf_features)
1672 Lisp_Object otf_features;
1674 Lisp_Object val, elt;
1676 CHECK_CONS (otf_features);
1677 CHECK_SYMBOL (XCAR (otf_features));
1678 otf_features = XCDR (otf_features);
1679 CHECK_CONS (otf_features);
1680 CHECK_SYMBOL (XCAR (otf_features));
1681 otf_features = XCDR (otf_features);
1682 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1684 CHECK_SYMBOL (Fcar (val));
1685 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1686 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val)));
1688 otf_features = XCDR (otf_features);
1689 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1691 CHECK_SYMBOL (Fcar (val));
1692 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1693 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val)));
1697 #ifdef HAVE_LIBOTF
1698 #include <otf.h>
1700 Lisp_Object otf_list;
1702 static Lisp_Object
1703 otf_tag_symbol (tag)
1704 OTF_Tag tag;
1706 char name[5];
1708 OTF_tag_name (tag, name);
1709 return Fintern (make_unibyte_string (name, 4), Qnil);
1712 static OTF *
1713 otf_open (entity, file)
1714 Lisp_Object entity;
1715 char *file;
1717 Lisp_Object val = Fassoc (entity, otf_list);
1718 OTF *otf;
1720 if (! NILP (val))
1721 otf = XSAVE_VALUE (XCDR (val))->pointer;
1722 else
1724 otf = file ? OTF_open (file) : NULL;
1725 val = make_save_value (otf, 0);
1726 otf_list = Fcons (Fcons (entity, val), otf_list);
1728 return otf;
1732 /* Return a list describing which scripts/languages FONT supports by
1733 which GSUB/GPOS features of OpenType tables. See the comment of
1734 (struct font_driver).otf_capability. */
1736 Lisp_Object
1737 font_otf_capability (font)
1738 struct font *font;
1740 OTF *otf;
1741 Lisp_Object capability = Fcons (Qnil, Qnil);
1742 int i;
1744 otf = otf_open (font->entity, font->file_name);
1745 if (! otf)
1746 return Qnil;
1747 for (i = 0; i < 2; i++)
1749 OTF_GSUB_GPOS *gsub_gpos;
1750 Lisp_Object script_list = Qnil;
1751 int j;
1753 if (OTF_get_features (otf, i == 0) < 0)
1754 continue;
1755 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1756 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1758 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1759 Lisp_Object langsys_list = Qnil;
1760 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1761 int k;
1763 for (k = script->LangSysCount; k >= 0; k--)
1765 OTF_LangSys *langsys;
1766 Lisp_Object feature_list = Qnil;
1767 Lisp_Object langsys_tag;
1768 int l;
1770 if (k == script->LangSysCount)
1772 langsys = &script->DefaultLangSys;
1773 langsys_tag = Qnil;
1775 else
1777 langsys = script->LangSys + k;
1778 langsys_tag
1779 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
1781 for (l = langsys->FeatureCount - 1; l >= 0; l--)
1783 OTF_Feature *feature
1784 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
1785 Lisp_Object feature_tag
1786 = otf_tag_symbol (feature->FeatureTag);
1788 feature_list = Fcons (feature_tag, feature_list);
1790 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1791 langsys_list);
1793 script_list = Fcons (Fcons (script_tag, langsys_list),
1794 script_list);
1797 if (i == 0)
1798 XSETCAR (capability, script_list);
1799 else
1800 XSETCDR (capability, script_list);
1803 return capability;
1806 /* Parse OTF features in SPEC and write a proper features spec string
1807 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1808 assured that the sufficient memory has already allocated for
1809 FEATURES. */
1811 static void
1812 generate_otf_features (spec, features)
1813 Lisp_Object spec;
1814 char *features;
1816 Lisp_Object val;
1817 char *p, *pend;
1818 int asterisk;
1820 p = features;
1821 *p = '\0';
1822 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
1824 val = XCAR (spec);
1825 CHECK_SYMBOL (val);
1826 if (p > features)
1827 *p++ = ',';
1828 if (SREF (SYMBOL_NAME (val), 0) == '*')
1830 asterisk = 1;
1831 *p++ = '*';
1833 else if (! asterisk)
1835 val = SYMBOL_NAME (val);
1836 p += sprintf (p, "%s", SDATA (val));
1838 else
1840 val = SYMBOL_NAME (val);
1841 p += sprintf (p, "~%s", SDATA (val));
1844 if (CONSP (spec))
1845 error ("OTF spec too long");
1849 Lisp_Object
1850 font_otf_DeviceTable (device_table)
1851 OTF_DeviceTable *device_table;
1853 int len = device_table->StartSize - device_table->EndSize + 1;
1855 return Fcons (make_number (len),
1856 make_unibyte_string (device_table->DeltaValue, len));
1859 Lisp_Object
1860 font_otf_ValueRecord (value_format, value_record)
1861 int value_format;
1862 OTF_ValueRecord *value_record;
1864 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
1866 if (value_format & OTF_XPlacement)
1867 ASET (val, 0, make_number (value_record->XPlacement));
1868 if (value_format & OTF_YPlacement)
1869 ASET (val, 1, make_number (value_record->YPlacement));
1870 if (value_format & OTF_XAdvance)
1871 ASET (val, 2, make_number (value_record->XAdvance));
1872 if (value_format & OTF_YAdvance)
1873 ASET (val, 3, make_number (value_record->YAdvance));
1874 if (value_format & OTF_XPlaDevice)
1875 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
1876 if (value_format & OTF_YPlaDevice)
1877 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
1878 if (value_format & OTF_XAdvDevice)
1879 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
1880 if (value_format & OTF_YAdvDevice)
1881 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
1882 return val;
1885 Lisp_Object
1886 font_otf_Anchor (anchor)
1887 OTF_Anchor *anchor;
1889 Lisp_Object val;
1891 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
1892 ASET (val, 0, make_number (anchor->XCoordinate));
1893 ASET (val, 1, make_number (anchor->YCoordinate));
1894 if (anchor->AnchorFormat == 2)
1895 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
1896 else
1898 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
1899 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
1901 return val;
1904 #endif /* HAVE_LIBOTF */
1906 /* G-string (glyph string) handler */
1908 /* G-string is a vector of the form [HEADER GLYPH ...].
1909 See the docstring of `font-make-gstring' for more detail. */
1911 struct font *
1912 font_prepare_composition (cmp, f)
1913 struct composition *cmp;
1914 FRAME_PTR f;
1916 Lisp_Object gstring
1917 = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
1918 cmp->hash_index * 2);
1920 cmp->font = XSAVE_VALUE (LGSTRING_FONT (gstring))->pointer;
1921 cmp->glyph_len = LGSTRING_LENGTH (gstring);
1922 cmp->pixel_width = LGSTRING_WIDTH (gstring);
1923 cmp->lbearing = LGSTRING_LBEARING (gstring);
1924 cmp->rbearing = LGSTRING_RBEARING (gstring);
1925 cmp->ascent = LGSTRING_ASCENT (gstring);
1926 cmp->descent = LGSTRING_DESCENT (gstring);
1927 cmp->width = cmp->pixel_width / FRAME_COLUMN_WIDTH (f);
1928 if (cmp->width == 0)
1929 cmp->width = 1;
1931 return cmp->font;
1935 /* Font sorting */
1937 static unsigned font_score P_ ((Lisp_Object, Lisp_Object *));
1938 static int font_compare P_ ((const void *, const void *));
1939 static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object,
1940 Lisp_Object, Lisp_Object));
1942 /* We sort fonts by scoring each of them against a specified
1943 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1944 the value is, the closer the font is to the font-spec.
1946 Each 1-bit of the highest 4 bits of the score is used for atomic
1947 properties FOUNDRY, FAMILY, ADSTYLE, and REGISTRY.
1949 Each 7-bit in the lowest 28 bits are used for numeric properties
1950 WEIGHT, SLANT, WIDTH, and SIZE. */
1952 /* How many bits to shift to store the difference value of each font
1953 property in a score. */
1954 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
1956 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1957 The return value indicates how different ENTITY is compared with
1958 SPEC_PROP. */
1960 static unsigned
1961 font_score (entity, spec_prop)
1962 Lisp_Object entity, *spec_prop;
1964 unsigned score = 0;
1965 int i;
1966 /* Score four atomic fields. Maximum difference is 1. */
1967 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
1968 if (! NILP (spec_prop[i])
1969 && ! EQ (spec_prop[i], AREF (entity, i)))
1970 score |= 1 << sort_shift_bits[i];
1972 /* Score four numeric fields. Maximum difference is 127. */
1973 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
1975 Lisp_Object entity_val = AREF (entity, i);
1976 Lisp_Object spec_val = spec_prop[i];
1978 /* If weight and slant are unspecified, score normal lower (low wins). */
1979 if (NILP (spec_val))
1981 if (i == FONT_WEIGHT_INDEX || i == FONT_SLANT_INDEX)
1982 spec_val = prop_name_to_numeric (i, build_string ("normal"));
1985 if (! NILP (spec_val) && ! EQ (spec_val, entity_val))
1987 if (! INTEGERP (entity_val))
1988 score |= 127 << sort_shift_bits[i];
1989 else
1991 int diff = XINT (entity_val) - XINT (spec_val);
1993 if (diff < 0)
1994 diff = - diff;
1995 if (i == FONT_SIZE_INDEX)
1997 if (XINT (entity_val) > 0
1998 && diff > FONT_PIXEL_SIZE_QUANTUM)
1999 score |= min (diff, 127) << sort_shift_bits[i];
2001 #ifdef WINDOWSNT
2002 else if (i == FONT_WEIGHT_INDEX)
2004 /* Windows uses a much wider range for weight (100-900)
2005 compared with freetype (0-210), so scale down the
2006 difference. A more general way of doing this
2007 would be to look up the values of regular and bold
2008 and/or light and calculate the scale factor from them,
2009 but the lookup would be expensive, and if only Windows
2010 needs it, not worth the effort. */
2011 score |= min (diff / 4, 127) << sort_shift_bits[i];
2013 #endif
2014 else
2015 score |= min (diff, 127) << sort_shift_bits[i];
2020 return score;
2024 /* The comparison function for qsort. */
2026 static int
2027 font_compare (d1, d2)
2028 const void *d1, *d2;
2030 return (*(unsigned *) d1 < *(unsigned *) d2
2031 ? -1 : *(unsigned *) d1 > *(unsigned *) d2);
2035 /* The structure for elements being sorted by qsort. */
2036 struct font_sort_data
2038 unsigned score;
2039 Lisp_Object entity;
2043 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2044 If PREFER specifies a point-size, calculate the corresponding
2045 pixel-size from QCdpi property of PREFER or from the Y-resolution
2046 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
2047 get the font-entities in VEC. */
2049 static Lisp_Object
2050 font_sort_entites (vec, prefer, frame, spec)
2051 Lisp_Object vec, prefer, frame, spec;
2053 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2054 int len, i;
2055 struct font_sort_data *data;
2056 USE_SAFE_ALLOCA;
2058 len = ASIZE (vec);
2059 if (len <= 1)
2060 return vec;
2062 for (i = FONT_FOUNDRY_INDEX; i <= FONT_SIZE_INDEX; i++)
2063 prefer_prop[i] = AREF (prefer, i);
2065 if (! NILP (spec))
2067 /* As it is assured that all fonts in VEC match with SPEC, we
2068 should ignore properties specified in SPEC. So, set the
2069 corresponding properties in PREFER_PROP to nil. */
2070 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
2071 if (! NILP (AREF (spec, i)))
2072 prefer_prop[i++] = Qnil;
2075 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2076 prefer_prop[FONT_SIZE_INDEX]
2077 = make_number (font_pixel_size (XFRAME (frame), prefer));
2079 /* Scoring and sorting. */
2080 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
2081 for (i = 0; i < len; i++)
2083 data[i].entity = AREF (vec, i);
2084 data[i].score = font_score (data[i].entity, prefer_prop);
2086 qsort (data, len, sizeof *data, font_compare);
2087 for (i = 0; i < len; i++)
2088 ASET (vec, i, data[i].entity);
2089 SAFE_FREE ();
2091 return vec;
2095 /* API of Font Service Layer. */
2097 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2098 sort_shift_bits. Finternal_set_font_selection_order calls this
2099 function with font_sort_order after setting up it. */
2101 void
2102 font_update_sort_order (order)
2103 int *order;
2105 int i, shift_bits = 21;
2107 for (i = 0; i < 4; i++, shift_bits -= 7)
2109 int xlfd_idx = order[i];
2111 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2112 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2113 else if (xlfd_idx == XLFD_SLANT_INDEX)
2114 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2115 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2116 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2117 else
2118 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2123 /* Return weight property of FONT as symbol. */
2125 Lisp_Object
2126 font_symbolic_weight (font)
2127 Lisp_Object font;
2129 Lisp_Object weight = AREF (font, FONT_WEIGHT_INDEX);
2131 if (INTEGERP (weight))
2132 weight = prop_numeric_to_name (FONT_WEIGHT_INDEX, XINT (weight));
2133 return weight;
2137 /* Return slant property of FONT as symbol. */
2139 Lisp_Object
2140 font_symbolic_slant (font)
2141 Lisp_Object font;
2143 Lisp_Object slant = AREF (font, FONT_SLANT_INDEX);
2145 if (INTEGERP (slant))
2146 slant = prop_numeric_to_name (FONT_SLANT_INDEX, XINT (slant));
2147 return slant;
2151 /* Return width property of FONT as symbol. */
2153 Lisp_Object
2154 font_symbolic_width (font)
2155 Lisp_Object font;
2157 Lisp_Object width = AREF (font, FONT_WIDTH_INDEX);
2159 if (INTEGERP (width))
2160 width = prop_numeric_to_name (FONT_WIDTH_INDEX, XINT (width));
2161 return width;
2165 /* Check if ENTITY matches with the font specification SPEC. */
2168 font_match_p (spec, entity)
2169 Lisp_Object spec, entity;
2171 int i;
2173 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
2174 if (! NILP (AREF (spec, i))
2175 && ! EQ (AREF (spec, i), AREF (entity, i)))
2176 return 0;
2177 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX))
2178 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0
2179 && (XINT (AREF (spec, FONT_SIZE_INDEX))
2180 != XINT (AREF (entity, FONT_SIZE_INDEX))))
2181 return 0;
2182 return 1;
2186 /* Return a lispy font object corresponding to FONT. */
2188 Lisp_Object
2189 font_find_object (font)
2190 struct font *font;
2192 Lisp_Object tail, elt;
2194 for (tail = AREF (font->entity, FONT_OBJLIST_INDEX); CONSP (tail);
2195 tail = XCDR (tail))
2197 elt = XCAR (tail);
2198 if (font == XSAVE_VALUE (elt)->pointer
2199 && XSAVE_VALUE (elt)->integer > 0)
2200 return elt;
2202 abort ();
2203 return Qnil;
2207 /* Font cache
2209 Each font backend has the callback function get_cache, and it
2210 returns a cons cell of which cdr part can be freely used for
2211 caching fonts. The cons cell may be shared by multiple frames
2212 and/or multiple font drivers. So, we arrange the cdr part as this:
2214 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2216 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2217 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2218 cons (FONT-SPEC FONT-ENTITY ...). */
2220 static void font_prepare_cache P_ ((FRAME_PTR, struct font_driver *));
2221 static void font_finish_cache P_ ((FRAME_PTR, struct font_driver *));
2222 static Lisp_Object font_get_cache P_ ((FRAME_PTR, struct font_driver *));
2223 static void font_clear_cache P_ ((FRAME_PTR, Lisp_Object,
2224 struct font_driver *));
2226 static void
2227 font_prepare_cache (f, driver)
2228 FRAME_PTR f;
2229 struct font_driver *driver;
2231 Lisp_Object cache, val;
2233 cache = driver->get_cache (f);
2234 val = XCDR (cache);
2235 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2236 val = XCDR (val);
2237 if (NILP (val))
2239 val = Fcons (driver->type, Fcons (make_number (1), Qnil));
2240 XSETCDR (cache, Fcons (val, XCDR (cache)));
2242 else
2244 val = XCDR (XCAR (val));
2245 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2250 static void
2251 font_finish_cache (f, driver)
2252 FRAME_PTR f;
2253 struct font_driver *driver;
2255 Lisp_Object cache, val, tmp;
2258 cache = driver->get_cache (f);
2259 val = XCDR (cache);
2260 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2261 cache = val, val = XCDR (val);
2262 xassert (! NILP (val));
2263 tmp = XCDR (XCAR (val));
2264 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2265 if (XINT (XCAR (tmp)) == 0)
2267 font_clear_cache (f, XCAR (val), driver);
2268 XSETCDR (cache, XCDR (val));
2273 static Lisp_Object
2274 font_get_cache (f, driver)
2275 FRAME_PTR f;
2276 struct font_driver *driver;
2278 Lisp_Object val = driver->get_cache (f);
2279 Lisp_Object type = driver->type;
2281 xassert (CONSP (val));
2282 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2283 xassert (CONSP (val));
2284 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2285 val = XCDR (XCAR (val));
2286 return val;
2289 static int num_fonts;
2291 static void
2292 font_clear_cache (f, cache, driver)
2293 FRAME_PTR f;
2294 Lisp_Object cache;
2295 struct font_driver *driver;
2297 Lisp_Object tail, elt;
2299 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2300 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2302 elt = XCAR (tail);
2303 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2305 Lisp_Object vec = XCDR (elt);
2306 int i;
2308 for (i = 0; i < ASIZE (vec); i++)
2310 Lisp_Object entity = AREF (vec, i);
2312 if (EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2314 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2316 for (; CONSP (objlist); objlist = XCDR (objlist))
2318 Lisp_Object val = XCAR (objlist);
2319 struct Lisp_Save_Value *p = XSAVE_VALUE (val);
2320 struct font *font = p->pointer;
2322 xassert (font && driver == font->driver);
2323 driver->close (f, font);
2324 p->pointer = NULL;
2325 p->integer = 0;
2326 num_fonts--;
2328 if (driver->free_entity)
2329 driver->free_entity (entity);
2334 XSETCDR (cache, Qnil);
2338 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2341 /* Return a vector of font-entities matching with SPEC on frame F. */
2343 static Lisp_Object
2344 font_list_entities (frame, spec)
2345 Lisp_Object frame, spec;
2347 FRAME_PTR f = XFRAME (frame);
2348 struct font_driver_list *driver_list = f->font_driver_list;
2349 Lisp_Object ftype, family, size, alternate_familes;
2350 Lisp_Object *vec = alloca (sizeof (Lisp_Object) * num_font_drivers);
2351 int i;
2353 if (! vec)
2354 return null_vector;
2356 family = AREF (spec, FONT_FAMILY_INDEX);
2357 if (NILP (family))
2358 alternate_familes = Qnil;
2359 else
2361 if (NILP (font_family_alist)
2362 && !NILP (Vface_alternative_font_family_alist))
2363 build_font_family_alist ();
2364 alternate_familes = assq_no_quit (family, font_family_alist);
2365 if (! NILP (alternate_familes))
2366 alternate_familes = XCDR (alternate_familes);
2368 size = AREF (spec, FONT_SIZE_INDEX);
2369 if (FLOATP (size))
2370 ASET (spec, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2372 xassert (ASIZE (spec) == FONT_SPEC_MAX);
2373 ftype = AREF (spec, FONT_TYPE_INDEX);
2375 for (i = 0; driver_list; driver_list = driver_list->next)
2376 if (driver_list->on
2377 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2379 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2380 Lisp_Object tail = alternate_familes;
2382 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2383 ASET (spec, FONT_FAMILY_INDEX, family);
2385 while (1)
2387 Lisp_Object val = assoc_no_quit (spec, XCDR (cache));
2389 if (CONSP (val))
2390 val = XCDR (val);
2391 else
2393 val = driver_list->driver->list (frame, spec);
2394 if (VECTORP (val))
2395 XSETCDR (cache, Fcons (Fcons (Fcopy_sequence (spec), val),
2396 XCDR (cache)));
2398 if (VECTORP (val) && ASIZE (val) > 0)
2400 vec[i++] = val;
2401 break;
2403 if (NILP (tail))
2404 break;
2405 ASET (spec, FONT_FAMILY_INDEX, XCAR (tail));
2406 tail = XCDR (tail);
2409 ASET (spec, FONT_TYPE_INDEX, ftype);
2410 ASET (spec, FONT_FAMILY_INDEX, family);
2411 ASET (spec, FONT_SIZE_INDEX, size);
2412 return (i > 0 ? Fvconcat (i, vec) : null_vector);
2416 /* Return a font entity matching with SPEC on FRAME. */
2418 static Lisp_Object
2419 font_matching_entity (frame, spec)
2420 Lisp_Object frame, spec;
2422 FRAME_PTR f = XFRAME (frame);
2423 struct font_driver_list *driver_list = f->font_driver_list;
2424 Lisp_Object ftype, size, entity;
2426 ftype = AREF (spec, FONT_TYPE_INDEX);
2427 size = AREF (spec, FONT_SIZE_INDEX);
2428 if (FLOATP (size))
2429 ASET (spec, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2430 entity = Qnil;
2431 for (; driver_list; driver_list = driver_list->next)
2432 if (driver_list->on
2433 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2435 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2436 Lisp_Object key;
2438 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2439 key = Fcons (spec, Qnil);
2440 entity = assoc_no_quit (key, XCDR (cache));
2441 if (CONSP (entity))
2442 entity = XCDR (entity);
2443 else
2445 entity = driver_list->driver->match (frame, spec);
2446 if (! NILP (entity))
2448 XSETCAR (key, Fcopy_sequence (spec));
2449 XSETCDR (cache, Fcons (Fcons (key, entity), XCDR (cache)));
2452 if (! NILP (entity))
2453 break;
2455 ASET (spec, FONT_TYPE_INDEX, ftype);
2456 ASET (spec, FONT_SIZE_INDEX, size);
2457 return entity;
2461 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2462 opened font object. */
2464 static Lisp_Object
2465 font_open_entity (f, entity, pixel_size)
2466 FRAME_PTR f;
2467 Lisp_Object entity;
2468 int pixel_size;
2470 struct font_driver_list *driver_list;
2471 Lisp_Object objlist, size, val, font_object;
2472 struct font *font;
2474 size = AREF (entity, FONT_SIZE_INDEX);
2475 xassert (NATNUMP (size));
2476 if (XINT (size) != 0)
2477 pixel_size = XINT (size);
2479 font_object = Qnil;
2480 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2481 objlist = XCDR (objlist))
2483 font = XSAVE_VALUE (XCAR (objlist))->pointer;
2484 if (font->pixel_size == pixel_size)
2486 font_object = XCAR (objlist);
2487 XSAVE_VALUE (font_object)->integer++;
2488 break;
2492 if (NILP (font_object))
2494 val = AREF (entity, FONT_TYPE_INDEX);
2495 for (driver_list = f->font_driver_list;
2496 driver_list && ! EQ (driver_list->driver->type, val);
2497 driver_list = driver_list->next);
2498 if (! driver_list)
2499 return Qnil;
2501 font = driver_list->driver->open (f, entity, pixel_size);
2502 if (! font)
2503 return Qnil;
2504 font->scalable = XINT (size) == 0;
2506 font_object = make_save_value (font, 1);
2507 ASET (entity, FONT_OBJLIST_INDEX,
2508 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2509 num_fonts++;
2512 if (FRAME_SMALLEST_CHAR_WIDTH (f) > font->min_width)
2513 FRAME_SMALLEST_CHAR_WIDTH (f) = font->min_width;
2514 if (FRAME_SMALLEST_CHAR_WIDTH (f) <= 0)
2515 FRAME_SMALLEST_CHAR_WIDTH (f) = 1;
2516 if (FRAME_SMALLEST_FONT_HEIGHT (f) > font->font.height)
2517 FRAME_SMALLEST_FONT_HEIGHT (f) = font->font.height;
2518 if (FRAME_SMALLEST_FONT_HEIGHT (f) <= 0)
2519 FRAME_SMALLEST_FONT_HEIGHT (f) = 1;
2521 return font_object;
2525 /* Close FONT_OBJECT that is opened on frame F. */
2527 void
2528 font_close_object (f, font_object)
2529 FRAME_PTR f;
2530 Lisp_Object font_object;
2532 struct font *font = XSAVE_VALUE (font_object)->pointer;
2533 Lisp_Object objlist;
2534 Lisp_Object tail, prev = Qnil;
2536 xassert (XSAVE_VALUE (font_object)->integer > 0);
2537 XSAVE_VALUE (font_object)->integer--;
2538 if (XSAVE_VALUE (font_object)->integer > 0)
2539 return;
2541 objlist = AREF (font->entity, FONT_OBJLIST_INDEX);
2542 for (prev = Qnil, tail = objlist; CONSP (tail);
2543 prev = tail, tail = XCDR (tail))
2544 if (EQ (font_object, XCAR (tail)))
2546 if (font->driver->close)
2547 font->driver->close (f, font);
2548 XSAVE_VALUE (font_object)->pointer = NULL;
2549 if (NILP (prev))
2550 ASET (font->entity, FONT_OBJLIST_INDEX, XCDR (objlist));
2551 else
2552 XSETCDR (prev, XCDR (objlist));
2553 num_fonts--;
2554 return;
2556 abort ();
2560 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2561 FONT is a font-entity and it must be opened to check. */
2564 font_has_char (f, font, c)
2565 FRAME_PTR f;
2566 Lisp_Object font;
2567 int c;
2569 struct font *fontp;
2571 if (FONT_ENTITY_P (font))
2573 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
2574 struct font_driver_list *driver_list;
2576 for (driver_list = f->font_driver_list;
2577 driver_list && ! EQ (driver_list->driver->type, type);
2578 driver_list = driver_list->next);
2579 if (! driver_list)
2580 return 0;
2581 if (! driver_list->driver->has_char)
2582 return -1;
2583 return driver_list->driver->has_char (font, c);
2586 xassert (FONT_OBJECT_P (font));
2587 fontp = XSAVE_VALUE (font)->pointer;
2589 if (fontp->driver->has_char)
2591 int result = fontp->driver->has_char (fontp->entity, c);
2593 if (result >= 0)
2594 return result;
2596 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
2600 /* Return the glyph ID of FONT_OBJECT for character C. */
2602 unsigned
2603 font_encode_char (font_object, c)
2604 Lisp_Object font_object;
2605 int c;
2607 struct font *font = XSAVE_VALUE (font_object)->pointer;
2609 return font->driver->encode_char (font, c);
2613 /* Return the name of FONT_OBJECT. */
2615 Lisp_Object
2616 font_get_name (font_object)
2617 Lisp_Object font_object;
2619 struct font *font = XSAVE_VALUE (font_object)->pointer;
2620 char *name = (font->font.full_name ? font->font.full_name
2621 : font->font.name ? font->font.name
2622 : NULL);
2624 return (name ? make_unibyte_string (name, strlen (name)) : null_string);
2628 /* Return the specification of FONT_OBJECT. */
2630 Lisp_Object
2631 font_get_spec (font_object)
2632 Lisp_Object font_object;
2634 struct font *font = XSAVE_VALUE (font_object)->pointer;
2635 Lisp_Object spec = Ffont_spec (0, NULL);
2636 int i;
2638 for (i = 0; i < FONT_SIZE_INDEX; i++)
2639 ASET (spec, i, AREF (font->entity, i));
2640 ASET (spec, FONT_SIZE_INDEX, make_number (font->pixel_size));
2641 return spec;
2645 /* Return the frame on which FONT exists. FONT is a font object or a
2646 font entity. */
2648 Lisp_Object
2649 font_get_frame (font)
2650 Lisp_Object font;
2652 if (FONT_OBJECT_P (font))
2653 font = ((struct font *) XSAVE_VALUE (font)->pointer)->entity;
2654 xassert (FONT_ENTITY_P (font));
2655 return AREF (font, FONT_FRAME_INDEX);
2659 /* Find a font entity best matching with LFACE. If SPEC is non-nil,
2660 the font must exactly match with it. C, if not negative, is a
2661 character that the entity must support. */
2663 Lisp_Object
2664 font_find_for_lface (f, lface, spec, c)
2665 FRAME_PTR f;
2666 Lisp_Object *lface;
2667 Lisp_Object spec;
2668 int c;
2670 Lisp_Object frame, entities, val;
2671 int i, result;
2673 XSETFRAME (frame, f);
2675 if (NILP (spec))
2677 if (c >= 0x100)
2678 return Qnil;
2679 for (i = 0; i < FONT_SPEC_MAX; i++)
2680 ASET (scratch_font_spec, i, Qnil);
2681 ASET (scratch_font_spec, FONT_REGISTRY_INDEX, Qiso8859_1);
2683 if (! NILP (lface[LFACE_FAMILY_INDEX]))
2684 font_merge_old_spec (Qnil, lface[LFACE_FAMILY_INDEX], Qnil,
2685 scratch_font_spec);
2686 entities = font_list_entities (frame, scratch_font_spec);
2687 while (ASIZE (entities) == 0)
2689 /* Try without FOUNDRY or FAMILY. */
2690 if (! NILP (AREF (scratch_font_spec, FONT_FOUNDRY_INDEX)))
2692 ASET (scratch_font_spec, FONT_FOUNDRY_INDEX, Qnil);
2693 entities = font_list_entities (frame, scratch_font_spec);
2695 else if (! NILP (AREF (scratch_font_spec, FONT_FAMILY_INDEX)))
2697 ASET (scratch_font_spec, FONT_FAMILY_INDEX, Qnil);
2698 entities = font_list_entities (frame, scratch_font_spec);
2700 else
2701 break;
2704 else
2706 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
2708 if (NILP (registry))
2709 registry = Qiso8859_1;
2711 if (c >= 0)
2713 struct charset *encoding, *repertory;
2715 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
2716 return Qnil;
2717 if (repertory)
2719 if (ENCODE_CHAR (repertory, c)
2720 == CHARSET_INVALID_CODE (repertory))
2721 return Qnil;
2722 /* Any font of this registry support C. So, let's
2723 suppress the further checking. */
2724 c = -1;
2726 else if (c > encoding->max_char)
2727 return Qnil;
2729 for (i = 0; i < FONT_SPEC_MAX; i++)
2730 ASET (scratch_font_spec, i, AREF (spec, i));
2731 ASET (scratch_font_spec, FONT_REGISTRY_INDEX, registry);
2732 entities = font_list_entities (frame, scratch_font_spec);
2735 if (ASIZE (entities) == 0)
2736 return Qnil;
2737 if (ASIZE (entities) > 1)
2739 /* Sort fonts by properties specified in LFACE. */
2740 Lisp_Object prefer = scratch_font_prefer;
2741 double pt;
2743 if (! NILP (lface[LFACE_FAMILY_INDEX]))
2744 font_merge_old_spec (Qnil, lface[LFACE_FAMILY_INDEX], Qnil, prefer);
2745 ASET (prefer, FONT_WEIGHT_INDEX,
2746 font_prop_validate_style (QCweight, lface[LFACE_WEIGHT_INDEX]));
2747 ASET (prefer, FONT_SLANT_INDEX,
2748 font_prop_validate_style (QCslant, lface[LFACE_SLANT_INDEX]));
2749 ASET (prefer, FONT_WIDTH_INDEX,
2750 font_prop_validate_style (QCwidth, lface[LFACE_SWIDTH_INDEX]));
2751 pt = XINT (lface[LFACE_HEIGHT_INDEX]);
2752 ASET (prefer, FONT_SIZE_INDEX, make_float (pt / 10));
2754 font_sort_entites (entities, prefer, frame, spec);
2757 if (c < 0)
2758 return AREF (entities, 0);
2760 val = AREF (entities, 0);
2761 result = font_has_char (f, val, c);
2762 if (result > 0)
2763 return val;
2764 if (result == 0)
2765 return Qnil;
2766 val = font_open_for_lface (f, val, lface, spec);
2767 if (NILP (val))
2768 return Qnil;
2769 result = font_has_char (f, val, c);
2770 font_close_object (f, val);
2771 if (result > 0)
2772 return val;
2773 return Qnil;
2777 Lisp_Object
2778 font_open_for_lface (f, entity, lface, spec)
2779 FRAME_PTR f;
2780 Lisp_Object entity;
2781 Lisp_Object *lface;
2782 Lisp_Object spec;
2784 int size;
2786 if (FONT_SPEC_P (spec) && INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2787 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2788 else
2790 double pt = XINT (lface[LFACE_HEIGHT_INDEX]);
2792 pt /= 10;
2793 size = POINT_TO_PIXEL (pt, f->resy);
2795 return font_open_entity (f, entity, size);
2799 /* Load a font best matching with FACE's font-related properties into
2800 FACE on frame F. If no proper font is found, record that FACE has
2801 no font. */
2803 void
2804 font_load_for_face (f, face)
2805 FRAME_PTR f;
2806 struct face *face;
2808 Lisp_Object font_object = face->lface[LFACE_FONT_INDEX];
2810 if (NILP (font_object))
2812 Lisp_Object entity = font_find_for_lface (f, face->lface, Qnil, -1);
2814 if (! NILP (entity))
2815 font_object = font_open_for_lface (f, entity, face->lface, Qnil);
2817 else if (STRINGP (font_object))
2819 font_object = font_open_by_name (f, SDATA (font_object));
2822 if (! NILP (font_object))
2824 struct font *font = XSAVE_VALUE (font_object)->pointer;
2826 face->font = font->font.font;
2827 face->font_info = (struct font_info *) font;
2828 face->font_info_id = 0;
2829 face->font_name = font->font.full_name;
2831 else
2833 face->font = NULL;
2834 face->font_info = NULL;
2835 face->font_info_id = -1;
2836 face->font_name = NULL;
2837 add_to_log ("Unable to load font for a face%s", null_string, Qnil);
2842 /* Make FACE on frame F ready to use the font opened for FACE. */
2844 void
2845 font_prepare_for_face (f, face)
2846 FRAME_PTR f;
2847 struct face *face;
2849 struct font *font = (struct font *) face->font_info;
2851 if (font->driver->prepare_face)
2852 font->driver->prepare_face (f, face);
2856 /* Make FACE on frame F stop using the font opened for FACE. */
2858 void
2859 font_done_for_face (f, face)
2860 FRAME_PTR f;
2861 struct face *face;
2863 struct font *font = (struct font *) face->font_info;
2865 if (font->driver->done_face)
2866 font->driver->done_face (f, face);
2867 face->extra = NULL;
2871 /* Open a font best matching with NAME on frame F. If no proper font
2872 is found, return Qnil. */
2874 Lisp_Object
2875 font_open_by_name (f, name)
2876 FRAME_PTR f;
2877 char *name;
2879 Lisp_Object args[2];
2880 Lisp_Object spec, prefer, size, entity, entity_list;
2881 Lisp_Object frame;
2882 int i;
2883 int pixel_size;
2885 XSETFRAME (frame, f);
2887 args[0] = QCname;
2888 args[1] = make_unibyte_string (name, strlen (name));
2889 spec = Ffont_spec (2, args);
2890 prefer = scratch_font_prefer;
2891 for (i = FONT_WEIGHT_INDEX; i < FONT_SIZE_INDEX; i++)
2892 if (NILP (AREF (spec, i)))
2893 ASET (prefer, i, make_number (100));
2894 size = AREF (spec, FONT_SIZE_INDEX);
2895 if (NILP (size))
2896 pixel_size = 0;
2897 else if (INTEGERP (size))
2898 pixel_size = XINT (size);
2899 else /* FLOATP (size) */
2901 double pt = XFLOAT_DATA (size);
2903 pixel_size = POINT_TO_PIXEL (pt, f->resy);
2904 size = make_number (pixel_size);
2905 ASET (spec, FONT_SIZE_INDEX, size);
2907 if (pixel_size == 0)
2909 pixel_size = POINT_TO_PIXEL (12.0, f->resy);
2910 size = make_number (pixel_size);
2912 ASET (prefer, FONT_SIZE_INDEX, size);
2913 if (NILP (AREF (spec, FONT_REGISTRY_INDEX)))
2914 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
2916 entity_list = Flist_fonts (spec, frame, make_number (1), prefer);
2917 if (NILP (entity_list))
2918 entity = font_matching_entity (frame, spec);
2919 else
2920 entity = XCAR (entity_list);
2921 return (NILP (entity)
2922 ? Qnil
2923 : font_open_entity (f, entity, pixel_size));
2927 /* Register font-driver DRIVER. This function is used in two ways.
2929 The first is with frame F non-NULL. In this case, make DRIVER
2930 available (but not yet activated) on F. All frame creaters
2931 (e.g. Fx_create_frame) must call this function at least once with
2932 an available font-driver.
2934 The second is with frame F NULL. In this case, DRIVER is globally
2935 registered in the variable `font_driver_list'. All font-driver
2936 implementations must call this function in its syms_of_XXXX
2937 (e.g. syms_of_xfont). */
2939 void
2940 register_font_driver (driver, f)
2941 struct font_driver *driver;
2942 FRAME_PTR f;
2944 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
2945 struct font_driver_list *prev, *list;
2947 if (f && ! driver->draw)
2948 error ("Unusable font driver for a frame: %s",
2949 SDATA (SYMBOL_NAME (driver->type)));
2951 for (prev = NULL, list = root; list; prev = list, list = list->next)
2952 if (EQ (list->driver->type, driver->type))
2953 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
2955 list = malloc (sizeof (struct font_driver_list));
2956 list->on = 0;
2957 list->driver = driver;
2958 list->next = NULL;
2959 if (prev)
2960 prev->next = list;
2961 else if (f)
2962 f->font_driver_list = list;
2963 else
2964 font_driver_list = list;
2965 num_font_drivers++;
2969 /* Free font-driver list on frame F. It doesn't free font-drivers
2970 themselves. */
2972 void
2973 free_font_driver_list (f)
2974 FRAME_PTR f;
2976 while (f->font_driver_list)
2978 struct font_driver_list *next = f->font_driver_list->next;
2980 free (f->font_driver_list);
2981 f->font_driver_list = next;
2986 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
2987 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
2988 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
2990 A caller must free all realized faces if any in advance. The
2991 return value is a list of font backends actually made used on
2992 F. */
2994 Lisp_Object
2995 font_update_drivers (f, new_drivers)
2996 FRAME_PTR f;
2997 Lisp_Object new_drivers;
2999 Lisp_Object active_drivers = Qnil;
3000 struct font_driver_list *list;
3002 for (list = f->font_driver_list; list; list = list->next)
3003 if (list->on)
3005 if (! EQ (new_drivers, Qt)
3006 && NILP (Fmemq (list->driver->type, new_drivers)))
3008 if (list->driver->end_for_frame)
3009 list->driver->end_for_frame (f);
3010 font_finish_cache (f, list->driver);
3011 list->on = 0;
3014 else
3016 if (EQ (new_drivers, Qt)
3017 || ! NILP (Fmemq (list->driver->type, new_drivers)))
3019 if (! list->driver->start_for_frame
3020 || list->driver->start_for_frame (f) == 0)
3022 font_prepare_cache (f, list->driver);
3023 list->on = 1;
3024 active_drivers = nconc2 (active_drivers,
3025 Fcons (list->driver->type, Qnil));
3030 return active_drivers;
3034 font_put_frame_data (f, driver, data)
3035 FRAME_PTR f;
3036 struct font_driver *driver;
3037 void *data;
3039 struct font_data_list *list, *prev;
3041 for (prev = NULL, list = f->font_data_list; list;
3042 prev = list, list = list->next)
3043 if (list->driver == driver)
3044 break;
3045 if (! data)
3047 if (list)
3049 if (prev)
3050 prev->next = list->next;
3051 else
3052 f->font_data_list = list->next;
3053 free (list);
3055 return 0;
3058 if (! list)
3060 list = malloc (sizeof (struct font_data_list));
3061 if (! list)
3062 return -1;
3063 list->driver = driver;
3064 list->next = f->font_data_list;
3065 f->font_data_list = list;
3067 list->data = data;
3068 return 0;
3072 void *
3073 font_get_frame_data (f, driver)
3074 FRAME_PTR f;
3075 struct font_driver *driver;
3077 struct font_data_list *list;
3079 for (list = f->font_data_list; list; list = list->next)
3080 if (list->driver == driver)
3081 break;
3082 if (! list)
3083 return NULL;
3084 return list->data;
3088 /* Return the font used to draw character C by FACE at buffer position
3089 POS in window W. If STRING is non-nil, it is a string containing C
3090 at index POS. If C is negative, get C from the current buffer or
3091 STRING. */
3093 Lisp_Object
3094 font_at (c, pos, face, w, string)
3095 int c;
3096 EMACS_INT pos;
3097 struct face *face;
3098 struct window *w;
3099 Lisp_Object string;
3101 FRAME_PTR f;
3102 int multibyte;
3104 if (c < 0)
3106 if (NILP (string))
3108 multibyte = ! NILP (current_buffer->enable_multibyte_characters);
3109 if (multibyte)
3111 EMACS_INT pos_byte = CHAR_TO_BYTE (pos);
3113 c = FETCH_CHAR (pos_byte);
3115 else
3116 c = FETCH_BYTE (pos);
3118 else
3120 unsigned char *str;
3122 multibyte = STRING_MULTIBYTE (string);
3123 if (multibyte)
3125 EMACS_INT pos_byte = string_char_to_byte (string, pos);
3127 str = SDATA (string) + pos_byte;
3128 c = STRING_CHAR (str, 0);
3130 else
3131 c = SDATA (string)[pos];
3135 f = XFRAME (w->frame);
3136 if (! FRAME_WINDOW_P (f))
3137 return Qnil;
3138 if (! face)
3140 int face_id;
3141 EMACS_INT endptr;
3143 if (STRINGP (string))
3144 face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
3145 DEFAULT_FACE_ID, 0);
3146 else
3147 face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
3148 pos + 100, 0);
3149 face = FACE_FROM_ID (f, face_id);
3151 if (multibyte)
3153 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3154 face = FACE_FROM_ID (f, face_id);
3156 if (! face->font_info)
3157 return Qnil;
3158 return font_find_object ((struct font *) face->font_info);
3162 /* Lisp API */
3164 DEFUN ("fontp", Ffontp, Sfontp, 1, 1, 0,
3165 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3166 Return nil otherwise. */)
3167 (object)
3168 Lisp_Object object;
3170 return (FONTP (object) ? Qt : Qnil);
3173 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3174 doc: /* Return a newly created font-spec with arguments as properties.
3176 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3177 valid font property name listed below:
3179 `:family', `:weight', `:slant', `:width'
3181 They are the same as face attributes of the same name. See
3182 `set-face-attribute'.
3184 `:foundry'
3186 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3188 `:adstyle'
3190 VALUE must be a string or a symbol specifying the additional
3191 typographic style information of a font, e.g. ``sans''. Usually null.
3193 `:registry'
3195 VALUE must be a string or a symbol specifying the charset registry and
3196 encoding of a font, e.g. ``iso8859-1''.
3198 `:size'
3200 VALUE must be a non-negative integer or a floating point number
3201 specifying the font size. It specifies the font size in 1/10 pixels
3202 (if VALUE is an integer), or in points (if VALUE is a float).
3203 usage: (font-spec ARGS ...) */)
3204 (nargs, args)
3205 int nargs;
3206 Lisp_Object *args;
3208 Lisp_Object spec = Fmake_vector (make_number (FONT_SPEC_MAX), Qnil);
3209 int i;
3211 for (i = 0; i < nargs; i += 2)
3213 enum font_property_index prop;
3214 Lisp_Object key = args[i], val = args[i + 1];
3216 prop = get_font_prop_index (key, 0);
3217 if (prop < FONT_EXTRA_INDEX)
3218 ASET (spec, prop, val);
3219 else
3221 if (EQ (key, QCname))
3223 CHECK_STRING (val);
3224 font_parse_name ((char *) SDATA (val), spec);
3226 font_put_extra (spec, key, val);
3229 CHECK_VALIDATE_FONT_SPEC (spec);
3230 return spec;
3234 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
3235 doc: /* Return the value of FONT's property KEY.
3236 FONT is a font-spec, a font-entity, or a font-object. */)
3237 (font, key)
3238 Lisp_Object font, key;
3240 enum font_property_index idx;
3242 if (FONT_OBJECT_P (font))
3244 struct font *fontp = XSAVE_VALUE (font)->pointer;
3246 if (EQ (key, QCotf))
3248 if (fontp->driver->otf_capability)
3249 return fontp->driver->otf_capability (fontp);
3250 else
3251 return Qnil;
3253 font = fontp->entity;
3255 else
3256 CHECK_FONT (font);
3257 idx = get_font_prop_index (key, 0);
3258 if (idx < FONT_EXTRA_INDEX)
3259 return AREF (font, idx);
3260 if (FONT_ENTITY_P (font))
3261 return Qnil;
3262 return Fcdr (Fassoc (key, AREF (font, FONT_EXTRA_INDEX)));
3266 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
3267 doc: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
3268 (font_spec, prop, val)
3269 Lisp_Object font_spec, prop, val;
3271 enum font_property_index idx;
3272 Lisp_Object extra, slot;
3274 CHECK_FONT_SPEC (font_spec);
3275 idx = get_font_prop_index (prop, 0);
3276 if (idx < FONT_EXTRA_INDEX)
3277 return ASET (font_spec, idx, val);
3278 extra = AREF (font_spec, FONT_EXTRA_INDEX);
3279 slot = Fassoc (extra, prop);
3280 if (NILP (slot))
3281 extra = Fcons (Fcons (prop, val), extra);
3282 else
3283 Fsetcdr (slot, val);
3284 return val;
3287 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
3288 doc: /* List available fonts matching FONT-SPEC on the current frame.
3289 Optional 2nd argument FRAME specifies the target frame.
3290 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
3291 Optional 4th argument PREFER, if non-nil, is a font-spec to
3292 control the order of the returned list. Fonts are sorted by
3293 how they are close to PREFER. */)
3294 (font_spec, frame, num, prefer)
3295 Lisp_Object font_spec, frame, num, prefer;
3297 Lisp_Object vec, list, tail;
3298 int n = 0, i, len;
3300 if (NILP (frame))
3301 frame = selected_frame;
3302 CHECK_LIVE_FRAME (frame);
3303 CHECK_VALIDATE_FONT_SPEC (font_spec);
3304 if (! NILP (num))
3306 CHECK_NUMBER (num);
3307 n = XINT (num);
3308 if (n <= 0)
3309 return Qnil;
3311 if (! NILP (prefer))
3312 CHECK_FONT (prefer);
3314 vec = font_list_entities (frame, font_spec);
3315 len = ASIZE (vec);
3316 if (len == 0)
3317 return Qnil;
3318 if (len == 1)
3319 return Fcons (AREF (vec, 0), Qnil);
3321 if (! NILP (prefer))
3322 vec = font_sort_entites (vec, prefer, frame, font_spec);
3324 list = tail = Fcons (AREF (vec, 0), Qnil);
3325 if (n == 0 || n > len)
3326 n = len;
3327 for (i = 1; i < n; i++)
3329 Lisp_Object val = Fcons (AREF (vec, i), Qnil);
3331 XSETCDR (tail, val);
3332 tail = val;
3334 return list;
3337 DEFUN ("list-families", Flist_families, Slist_families, 0, 1, 0,
3338 doc: /* List available font families on the current frame.
3339 Optional argument FRAME specifies the target frame. */)
3340 (frame)
3341 Lisp_Object frame;
3343 FRAME_PTR f;
3344 struct font_driver_list *driver_list;
3345 Lisp_Object list;
3347 if (NILP (frame))
3348 frame = selected_frame;
3349 CHECK_LIVE_FRAME (frame);
3350 f = XFRAME (frame);
3351 list = Qnil;
3352 for (driver_list = f->font_driver_list; driver_list;
3353 driver_list = driver_list->next)
3354 if (driver_list->driver->list_family)
3356 Lisp_Object val = driver_list->driver->list_family (frame);
3358 if (NILP (list))
3359 list = val;
3360 else
3362 Lisp_Object tail = list;
3364 for (; CONSP (val); val = XCDR (val))
3365 if (NILP (Fmemq (XCAR (val), tail)))
3366 list = Fcons (XCAR (val), list);
3369 return list;
3372 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
3373 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
3374 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
3375 (font_spec, frame)
3376 Lisp_Object font_spec, frame;
3378 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
3380 if (CONSP (val))
3381 val = XCAR (val);
3382 return val;
3385 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 1, 0,
3386 doc: /* Return XLFD name of FONT.
3387 FONT is a font-spec, font-entity, or font-object.
3388 If the name is too long for XLFD (maximum 255 chars), return nil. */)
3389 (font)
3390 Lisp_Object font;
3392 char name[256];
3393 int pixel_size = 0;
3395 if (FONT_SPEC_P (font))
3396 CHECK_VALIDATE_FONT_SPEC (font);
3397 else if (FONT_ENTITY_P (font))
3398 CHECK_FONT (font);
3399 else
3401 struct font *fontp;
3403 CHECK_FONT_GET_OBJECT (font, fontp);
3404 font = fontp->entity;
3405 pixel_size = fontp->pixel_size;
3408 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
3409 return Qnil;
3410 return build_string (name);
3413 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
3414 doc: /* Clear font cache. */)
3417 Lisp_Object list, frame;
3419 FOR_EACH_FRAME (list, frame)
3421 FRAME_PTR f = XFRAME (frame);
3422 struct font_driver_list *driver_list = f->font_driver_list;
3424 for (; driver_list; driver_list = driver_list->next)
3425 if (driver_list->on)
3427 Lisp_Object cache = driver_list->driver->get_cache (f);
3428 Lisp_Object val;
3430 val = XCDR (cache);
3431 while (! NILP (val)
3432 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
3433 val = XCDR (val);
3434 xassert (! NILP (val));
3435 val = XCDR (XCAR (val));
3436 if (XINT (XCAR (val)) == 0)
3438 font_clear_cache (f, XCAR (val), driver_list->driver);
3439 XSETCDR (cache, XCDR (val));
3444 return Qnil;
3447 DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table,
3448 Sinternal_set_font_style_table, 2, 2, 0,
3449 doc: /* Set font style table for PROP to TABLE.
3450 PROP must be `:weight', `:slant', or `:width'.
3451 TABLE must be an alist of symbols vs the corresponding numeric values
3452 sorted by numeric values. */)
3453 (prop, table)
3454 Lisp_Object prop, table;
3456 int table_index;
3457 int numeric;
3458 Lisp_Object tail, val;
3460 CHECK_SYMBOL (prop);
3461 table_index = (EQ (prop, QCweight) ? 0
3462 : EQ (prop, QCslant) ? 1
3463 : EQ (prop, QCwidth) ? 2
3464 : 3);
3465 if (table_index >= ASIZE (font_style_table))
3466 error ("Invalid font style property: %s", SDATA (SYMBOL_NAME (prop)));
3467 table = Fcopy_sequence (table);
3468 numeric = -1;
3469 for (tail = table; CONSP (tail); tail = XCDR (tail))
3471 prop = Fcar (XCAR (tail));
3472 val = Fcdr (XCAR (tail));
3473 CHECK_SYMBOL (prop);
3474 CHECK_NATNUM (val);
3475 if (numeric > XINT (val))
3476 error ("Numeric values not sorted for %s", SDATA (SYMBOL_NAME (prop)));
3477 else if (numeric == XINT (val))
3478 error ("Duplicate numeric values for %s", SDATA (SYMBOL_NAME (prop)));
3479 numeric = XINT (val);
3480 XSETCAR (tail, Fcons (prop, val));
3482 ASET (font_style_table, table_index, table);
3483 return Qnil;
3486 /* The following three functions are still expremental. */
3488 DEFUN ("font-make-gstring", Ffont_make_gstring, Sfont_make_gstring, 2, 2, 0,
3489 doc: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
3490 FONT-OBJECT may be nil if it is not yet known.
3492 G-string is sequence of glyphs of a specific font,
3493 and is a vector of this form:
3494 [ HEADER GLYPH ... ]
3495 HEADER is a vector of this form:
3496 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
3497 where
3498 FONT-OBJECT is a font-object for all glyphs in the g-string,
3499 WIDTH thry DESCENT are the metrics (in pixels) of the whole G-string.
3500 GLYPH is a vector of this form:
3501 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
3502 [ [X-OFF Y-OFF WADJUST] | nil] ]
3503 where
3504 FROM-IDX and TO-IDX are used internally and should not be touched.
3505 C is the character of the glyph.
3506 CODE is the glyph-code of C in FONT-OBJECT.
3507 WIDTH thry DESCENT are the metrics (in pixels) of the glyph.
3508 X-OFF and Y-OFF are offests to the base position for the glyph.
3509 WADJUST is the adjustment to the normal width of the glyph. */)
3510 (font_object, num)
3511 Lisp_Object font_object, num;
3513 Lisp_Object gstring, g;
3514 int len;
3515 int i;
3517 if (! NILP (font_object))
3518 CHECK_FONT_OBJECT (font_object);
3519 CHECK_NATNUM (num);
3521 len = XINT (num) + 1;
3522 gstring = Fmake_vector (make_number (len), Qnil);
3523 g = Fmake_vector (make_number (6), Qnil);
3524 ASET (g, 0, font_object);
3525 ASET (gstring, 0, g);
3526 for (i = 1; i < len; i++)
3527 ASET (gstring, i, Fmake_vector (make_number (10), Qnil));
3528 return gstring;
3531 DEFUN ("font-fill-gstring", Ffont_fill_gstring, Sfont_fill_gstring, 4, 5, 0,
3532 doc: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
3533 START and END specify the region to extract characters.
3534 If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
3535 where to extract characters.
3536 FONT-OBJECT may be nil if GSTRING already already contains one. */)
3537 (gstring, font_object, start, end, object)
3538 Lisp_Object gstring, font_object, start, end, object;
3540 int len, i, c;
3541 unsigned code;
3542 struct font *font;
3544 CHECK_VECTOR (gstring);
3545 if (NILP (font_object))
3546 font_object = LGSTRING_FONT (gstring);
3547 CHECK_FONT_GET_OBJECT (font_object, font);
3549 if (STRINGP (object))
3551 const unsigned char *p;
3553 CHECK_NATNUM (start);
3554 CHECK_NATNUM (end);
3555 if (XINT (start) > XINT (end)
3556 || XINT (end) > ASIZE (object)
3557 || XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3558 args_out_of_range_3 (object, start, end);
3560 len = XINT (end) - XINT (start);
3561 p = SDATA (object) + string_char_to_byte (object, XINT (start));
3562 for (i = 0; i < len; i++)
3564 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3565 /* Shut up GCC warning in comparison with
3566 MOST_POSITIVE_FIXNUM below. */
3567 EMACS_INT cod;
3569 c = STRING_CHAR_ADVANCE (p);
3570 cod = code = font->driver->encode_char (font, c);
3571 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3572 break;
3573 LGLYPH_SET_FROM (g, i);
3574 LGLYPH_SET_TO (g, i);
3575 LGLYPH_SET_CHAR (g, c);
3576 LGLYPH_SET_CODE (g, code);
3579 else
3581 int pos, pos_byte;
3583 if (! NILP (object))
3584 Fset_buffer (object);
3585 validate_region (&start, &end);
3586 if (XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3587 args_out_of_range (start, end);
3588 len = XINT (end) - XINT (start);
3589 pos = XINT (start);
3590 pos_byte = CHAR_TO_BYTE (pos);
3591 for (i = 0; i < len; i++)
3593 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3594 /* Shut up GCC warning in comparison with
3595 MOST_POSITIVE_FIXNUM below. */
3596 EMACS_INT cod;
3598 FETCH_CHAR_ADVANCE (c, pos, pos_byte);
3599 cod = code = font->driver->encode_char (font, c);
3600 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3601 break;
3602 LGLYPH_SET_FROM (g, i);
3603 LGLYPH_SET_TO (g, i);
3604 LGLYPH_SET_CHAR (g, c);
3605 LGLYPH_SET_CODE (g, code);
3608 for (; i < LGSTRING_LENGTH (gstring); i++)
3609 LGSTRING_SET_GLYPH (gstring, i, Qnil);
3610 return Qnil;
3613 DEFUN ("font-shape-text", Ffont_shape_text, Sfont_shape_text, 3, 4, 0,
3614 doc: /* Shape text between FROM and TO by FONT-OBJECT.
3615 If optional 4th argument STRING is non-nil, it is a string to shape,
3616 and FROM and TO are indices to the string.
3617 The value is the end position of the text that can be shaped by
3618 FONT-OBJECT. */)
3619 (from, to, font_object, string)
3620 Lisp_Object from, to, font_object, string;
3622 struct font *font;
3623 struct font_metrics metrics;
3624 EMACS_INT start, end;
3625 Lisp_Object gstring, n;
3626 int len, i, j;
3628 if (! FONT_OBJECT_P (font_object))
3629 return Qnil;
3630 CHECK_FONT_GET_OBJECT (font_object, font);
3631 if (! font->driver->shape)
3632 return Qnil;
3634 if (NILP (string))
3636 validate_region (&from, &to);
3637 start = XFASTINT (from);
3638 end = XFASTINT (to);
3639 modify_region (current_buffer, start, end, 0);
3641 else
3643 CHECK_STRING (string);
3644 start = XINT (from);
3645 end = XINT (to);
3646 if (start < 0 || start > end || end > SCHARS (string))
3647 args_out_of_range_3 (string, from, to);
3650 len = end - start;
3651 gstring = Ffont_make_gstring (font_object, make_number (len));
3652 Ffont_fill_gstring (gstring, font_object, from, to, string);
3654 /* Try at most three times with larger gstring each time. */
3655 for (i = 0; i < 3; i++)
3657 Lisp_Object args[2];
3659 n = font->driver->shape (gstring);
3660 if (INTEGERP (n))
3661 break;
3662 args[0] = gstring;
3663 args[1] = Fmake_vector (make_number (len), Qnil);
3664 gstring = Fvconcat (2, args);
3666 if (! INTEGERP (n) || XINT (n) == 0)
3667 return Qnil;
3668 len = XINT (n);
3670 for (i = 0; i < len;)
3672 Lisp_Object gstr;
3673 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3674 EMACS_INT this_from = LGLYPH_FROM (g);
3675 EMACS_INT this_to = LGLYPH_TO (g) + 1;
3676 int j, k;
3677 int need_composition = 0;
3679 metrics.lbearing = LGLYPH_LBEARING (g);
3680 metrics.rbearing = LGLYPH_RBEARING (g);
3681 metrics.ascent = LGLYPH_ASCENT (g);
3682 metrics.descent = LGLYPH_DESCENT (g);
3683 if (NILP (LGLYPH_ADJUSTMENT (g)))
3685 metrics.width = LGLYPH_WIDTH (g);
3686 if (LGLYPH_CHAR (g) == 0 || metrics.width == 0)
3687 need_composition = 1;
3689 else
3691 metrics.width = LGLYPH_WADJUST (g);
3692 metrics.lbearing += LGLYPH_XOFF (g);
3693 metrics.rbearing += LGLYPH_XOFF (g);
3694 metrics.ascent -= LGLYPH_YOFF (g);
3695 metrics.descent += LGLYPH_YOFF (g);
3696 need_composition = 1;
3698 for (j = i + 1; j < len; j++)
3700 int x;
3702 g = LGSTRING_GLYPH (gstring, j);
3703 if (this_from != LGLYPH_FROM (g))
3704 break;
3705 need_composition = 1;
3706 x = metrics.width + LGLYPH_LBEARING (g) + LGLYPH_XOFF (g);
3707 if (metrics.lbearing > x)
3708 metrics.lbearing = x;
3709 x = metrics.width + LGLYPH_RBEARING (g) + LGLYPH_XOFF (g);
3710 if (metrics.rbearing < x)
3711 metrics.rbearing = x;
3712 x = LGLYPH_ASCENT (g) - LGLYPH_YOFF (g);
3713 if (metrics.ascent < x)
3714 metrics.ascent = x;
3715 x = LGLYPH_DESCENT (g) - LGLYPH_YOFF (g);
3716 if (metrics.descent < x)
3717 metrics.descent = x;
3718 if (NILP (LGLYPH_ADJUSTMENT (g)))
3719 metrics.width += LGLYPH_WIDTH (g);
3720 else
3721 metrics.width += LGLYPH_WADJUST (g);
3724 if (need_composition)
3726 gstr = Ffont_make_gstring (font_object, make_number (j - i));
3727 LGSTRING_SET_WIDTH (gstr, metrics.width);
3728 LGSTRING_SET_LBEARING (gstr, metrics.lbearing);
3729 LGSTRING_SET_RBEARING (gstr, metrics.rbearing);
3730 LGSTRING_SET_ASCENT (gstr, metrics.ascent);
3731 LGSTRING_SET_DESCENT (gstr, metrics.descent);
3732 for (k = i; i < j; i++)
3734 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3736 LGLYPH_SET_FROM (g, LGLYPH_FROM (g) - this_from);
3737 LGLYPH_SET_TO (g, LGLYPH_TO (g) - this_from);
3738 LGSTRING_SET_GLYPH (gstr, i - k, LGSTRING_GLYPH (gstring, i));
3740 from = make_number (start + this_from);
3741 to = make_number (start + this_to);
3742 if (NILP (string))
3743 Fcompose_region_internal (from, to, gstr, Qnil);
3744 else
3745 Fcompose_string_internal (string, from, to, gstr, Qnil);
3747 else
3748 i = j;
3751 return to;
3754 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
3755 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
3756 OTF-FEATURES specifies which features to apply in this format:
3757 (SCRIPT LANGSYS GSUB GPOS)
3758 where
3759 SCRIPT is a symbol specifying a script tag of OpenType,
3760 LANGSYS is a symbol specifying a langsys tag of OpenType,
3761 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
3763 If LANGYS is nil, the default langsys is selected.
3765 The features are applied in the order they appear in the list. The
3766 symbol `*' means to apply all available features not present in this
3767 list, and the remaining features are ignored. For instance, (vatu
3768 pstf * haln) is to apply vatu and pstf in this order, then to apply
3769 all available features other than vatu, pstf, and haln.
3771 The features are applied to the glyphs in the range FROM and TO of
3772 the glyph-string GSTRING-IN.
3774 If some feature is actually applicable, the resulting glyphs are
3775 produced in the glyph-string GSTRING-OUT from the index INDEX. In
3776 this case, the value is the number of produced glyphs.
3778 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
3779 the value is 0.
3781 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
3782 produced in GSTRING-OUT, and the value is nil.
3784 See the documentation of `font-make-gstring' for the format of
3785 glyph-string. */)
3786 (otf_features, gstring_in, from, to, gstring_out, index)
3787 Lisp_Object otf_features, gstring_in, from, to, gstring_out, index;
3789 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
3790 Lisp_Object val;
3791 struct font *font;
3792 int len, num;
3794 check_otf_features (otf_features);
3795 CHECK_FONT_GET_OBJECT (font_object, font);
3796 if (! font->driver->otf_drive)
3797 error ("Font backend %s can't drive OpenType GSUB table",
3798 SDATA (SYMBOL_NAME (font->driver->type)));
3799 CHECK_CONS (otf_features);
3800 CHECK_SYMBOL (XCAR (otf_features));
3801 val = XCDR (otf_features);
3802 CHECK_SYMBOL (XCAR (val));
3803 val = XCDR (otf_features);
3804 if (! NILP (val))
3805 CHECK_CONS (val);
3806 len = check_gstring (gstring_in);
3807 CHECK_VECTOR (gstring_out);
3808 CHECK_NATNUM (from);
3809 CHECK_NATNUM (to);
3810 CHECK_NATNUM (index);
3812 if (XINT (from) >= XINT (to) || XINT (to) > len)
3813 args_out_of_range_3 (from, to, make_number (len));
3814 if (XINT (index) >= ASIZE (gstring_out))
3815 args_out_of_range (index, make_number (ASIZE (gstring_out)));
3816 num = font->driver->otf_drive (font, otf_features,
3817 gstring_in, XINT (from), XINT (to),
3818 gstring_out, XINT (index), 0);
3819 if (num < 0)
3820 return Qnil;
3821 return make_number (num);
3824 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
3825 3, 3, 0,
3826 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
3827 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
3828 in this format:
3829 (SCRIPT LANGSYS FEATURE ...)
3830 See the documentation of `font-otf-gsub' for more detail.
3832 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
3833 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
3834 character code corresponding to the glyph or nil if there's no
3835 corresponding character. */)
3836 (font_object, character, otf_features)
3837 Lisp_Object font_object, character, otf_features;
3839 struct font *font;
3840 Lisp_Object gstring_in, gstring_out, g;
3841 Lisp_Object alternates;
3842 int i, num;
3844 CHECK_FONT_GET_OBJECT (font_object, font);
3845 if (! font->driver->otf_drive)
3846 error ("Font backend %s can't drive OpenType GSUB table",
3847 SDATA (SYMBOL_NAME (font->driver->type)));
3848 CHECK_CHARACTER (character);
3849 CHECK_CONS (otf_features);
3851 gstring_in = Ffont_make_gstring (font_object, make_number (1));
3852 g = LGSTRING_GLYPH (gstring_in, 0);
3853 LGLYPH_SET_CHAR (g, XINT (character));
3854 gstring_out = Ffont_make_gstring (font_object, make_number (10));
3855 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
3856 gstring_out, 0, 1)) < 0)
3857 gstring_out = Ffont_make_gstring (font_object,
3858 make_number (ASIZE (gstring_out) * 2));
3859 alternates = Qnil;
3860 for (i = 0; i < num; i++)
3862 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
3863 int c = LGLYPH_CHAR (g);
3864 unsigned code = LGLYPH_CODE (g);
3866 alternates = Fcons (Fcons (make_number (code),
3867 c > 0 ? make_number (c) : Qnil),
3868 alternates);
3870 return Fnreverse (alternates);
3874 #ifdef FONT_DEBUG
3876 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
3877 doc: /* Open FONT-ENTITY. */)
3878 (font_entity, size, frame)
3879 Lisp_Object font_entity;
3880 Lisp_Object size;
3881 Lisp_Object frame;
3883 int isize;
3885 CHECK_FONT_ENTITY (font_entity);
3886 if (NILP (size))
3887 size = AREF (font_entity, FONT_SIZE_INDEX);
3888 CHECK_NUMBER (size);
3889 if (NILP (frame))
3890 frame = selected_frame;
3891 CHECK_LIVE_FRAME (frame);
3893 isize = XINT (size);
3894 if (isize == 0)
3895 isize = 120;
3896 if (isize < 0)
3897 isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy);
3899 return font_open_entity (XFRAME (frame), font_entity, isize);
3902 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
3903 doc: /* Close FONT-OBJECT. */)
3904 (font_object, frame)
3905 Lisp_Object font_object, frame;
3907 CHECK_FONT_OBJECT (font_object);
3908 if (NILP (frame))
3909 frame = selected_frame;
3910 CHECK_LIVE_FRAME (frame);
3911 font_close_object (XFRAME (frame), font_object);
3912 return Qnil;
3915 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
3916 doc: /* Return information about FONT-OBJECT.
3917 The value is a vector:
3918 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
3919 CAPABILITY ]
3921 NAME is a string of the font name (or nil if the font backend doesn't
3922 provide a name).
3924 FILENAME is a string of the font file (or nil if the font backend
3925 doesn't provide a file name).
3927 PIXEL-SIZE is a pixel size by which the font is opened.
3929 SIZE is a maximum advance width of the font in pixel.
3931 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
3932 pixel.
3934 CAPABILITY is a list whose first element is a symbol representing the
3935 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
3936 remaining elements describes a detail of the font capability.
3938 If the font is OpenType font, the form of the list is
3939 \(opentype GSUB GPOS)
3940 where GSUB shows which "GSUB" features the font supports, and GPOS
3941 shows which "GPOS" features the font supports. Both GSUB and GPOS are
3942 lists of the format:
3943 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
3945 If the font is not OpenType font, currently the length of the form is
3946 one.
3948 SCRIPT is a symbol representing OpenType script tag.
3950 LANGSYS is a symbol representing OpenType langsys tag, or nil
3951 representing the default langsys.
3953 FEATURE is a symbol representing OpenType feature tag.
3955 If the font is not OpenType font, CAPABILITY is nil. */)
3956 (font_object)
3957 Lisp_Object font_object;
3959 struct font *font;
3960 Lisp_Object val;
3962 CHECK_FONT_GET_OBJECT (font_object, font);
3964 val = Fmake_vector (make_number (9), Qnil);
3965 if (font->font.full_name)
3966 ASET (val, 0, make_unibyte_string (font->font.full_name,
3967 strlen (font->font.full_name)));
3968 if (font->file_name)
3969 ASET (val, 1, make_unibyte_string (font->file_name,
3970 strlen (font->file_name)));
3971 ASET (val, 2, make_number (font->pixel_size));
3972 ASET (val, 3, make_number (font->font.size));
3973 ASET (val, 4, make_number (font->ascent));
3974 ASET (val, 5, make_number (font->descent));
3975 ASET (val, 6, make_number (font->font.space_width));
3976 ASET (val, 7, make_number (font->font.average_width));
3977 if (font->driver->otf_capability)
3978 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
3979 else
3980 ASET (val, 8, Fcons (font->format, Qnil));
3981 return val;
3984 DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
3985 doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
3986 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
3987 (font_object, string)
3988 Lisp_Object font_object, string;
3990 struct font *font;
3991 int i, len;
3992 Lisp_Object vec;
3994 CHECK_FONT_GET_OBJECT (font_object, font);
3995 CHECK_STRING (string);
3996 len = SCHARS (string);
3997 vec = Fmake_vector (make_number (len), Qnil);
3998 for (i = 0; i < len; i++)
4000 Lisp_Object ch = Faref (string, make_number (i));
4001 Lisp_Object val;
4002 int c = XINT (ch);
4003 unsigned code;
4004 EMACS_INT cod;
4005 struct font_metrics metrics;
4007 cod = code = font->driver->encode_char (font, c);
4008 if (code == FONT_INVALID_CODE)
4009 continue;
4010 val = Fmake_vector (make_number (6), Qnil);
4011 if (cod <= MOST_POSITIVE_FIXNUM)
4012 ASET (val, 0, make_number (code));
4013 else
4014 ASET (val, 0, Fcons (make_number (code >> 16),
4015 make_number (code & 0xFFFF)));
4016 font->driver->text_extents (font, &code, 1, &metrics);
4017 ASET (val, 1, make_number (metrics.lbearing));
4018 ASET (val, 2, make_number (metrics.rbearing));
4019 ASET (val, 3, make_number (metrics.width));
4020 ASET (val, 4, make_number (metrics.ascent));
4021 ASET (val, 5, make_number (metrics.descent));
4022 ASET (vec, i, val);
4024 return vec;
4027 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4028 doc: /* Return t iff font-spec SPEC matches with FONT.
4029 FONT is a font-spec, font-entity, or font-object. */)
4030 (spec, font)
4031 Lisp_Object spec, font;
4033 CHECK_FONT_SPEC (spec);
4034 if (FONT_OBJECT_P (font))
4035 font = ((struct font *) XSAVE_VALUE (font)->pointer)->entity;
4036 else if (! FONT_ENTITY_P (font))
4037 CHECK_FONT_SPEC (font);
4039 return (font_match_p (spec, font) ? Qt : Qnil);
4042 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4043 doc: /* Return a font-object for displaying a character at POSITION.
4044 Optional second arg WINDOW, if non-nil, is a window displaying
4045 the current buffer. It defaults to the currently selected window. */)
4046 (position, window, string)
4047 Lisp_Object position, window, string;
4049 struct window *w;
4050 EMACS_INT pos;
4052 if (NILP (string))
4054 CHECK_NUMBER_COERCE_MARKER (position);
4055 pos = XINT (position);
4056 if (pos < BEGV || pos >= ZV)
4057 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4059 else
4061 EMACS_INT len;
4062 unsigned char *str;
4064 CHECK_NUMBER (position);
4065 CHECK_STRING (string);
4066 pos = XINT (position);
4067 if (pos < 0 || pos >= SCHARS (string))
4068 args_out_of_range (string, position);
4070 if (NILP (window))
4071 window = selected_window;
4072 CHECK_LIVE_WINDOW (window);
4073 w = XWINDOW (window);
4075 return font_at (-1, pos, NULL, w, string);
4078 #if 0
4079 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4080 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4081 The value is a number of glyphs drawn.
4082 Type C-l to recover what previously shown. */)
4083 (font_object, string)
4084 Lisp_Object font_object, string;
4086 Lisp_Object frame = selected_frame;
4087 FRAME_PTR f = XFRAME (frame);
4088 struct font *font;
4089 struct face *face;
4090 int i, len, width;
4091 unsigned *code;
4093 CHECK_FONT_GET_OBJECT (font_object, font);
4094 CHECK_STRING (string);
4095 len = SCHARS (string);
4096 code = alloca (sizeof (unsigned) * len);
4097 for (i = 0; i < len; i++)
4099 Lisp_Object ch = Faref (string, make_number (i));
4100 Lisp_Object val;
4101 int c = XINT (ch);
4103 code[i] = font->driver->encode_char (font, c);
4104 if (code[i] == FONT_INVALID_CODE)
4105 break;
4107 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4108 face->fontp = font;
4109 if (font->driver->prepare_face)
4110 font->driver->prepare_face (f, face);
4111 width = font->driver->text_extents (font, code, i, NULL);
4112 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4113 if (font->driver->done_face)
4114 font->driver->done_face (f, face);
4115 face->fontp = NULL;
4116 return make_number (len);
4118 #endif
4120 #endif /* FONT_DEBUG */
4123 extern void syms_of_ftfont P_ (());
4124 extern void syms_of_xfont P_ (());
4125 extern void syms_of_xftfont P_ (());
4126 extern void syms_of_ftxfont P_ (());
4127 extern void syms_of_bdffont P_ (());
4128 extern void syms_of_w32font P_ (());
4129 extern void syms_of_atmfont P_ (());
4131 void
4132 syms_of_font ()
4134 sort_shift_bits[FONT_SLANT_INDEX] = 0;
4135 sort_shift_bits[FONT_WEIGHT_INDEX] = 7;
4136 sort_shift_bits[FONT_SIZE_INDEX] = 14;
4137 sort_shift_bits[FONT_WIDTH_INDEX] = 21;
4138 sort_shift_bits[FONT_ADSTYLE_INDEX] = 28;
4139 sort_shift_bits[FONT_FOUNDRY_INDEX] = 29;
4140 sort_shift_bits[FONT_FAMILY_INDEX] = 30;
4141 sort_shift_bits[FONT_REGISTRY_INDEX] = 31;
4142 /* Note that sort_shift_bits[FONT_TYPE_INDEX] is never used. */
4144 staticpro (&font_style_table);
4145 font_style_table = Fmake_vector (make_number (3), Qnil);
4147 staticpro (&font_family_alist);
4148 font_family_alist = Qnil;
4150 staticpro (&font_charset_alist);
4151 font_charset_alist = Qnil;
4153 DEFSYM (Qopentype, "opentype");
4155 DEFSYM (Qiso8859_1, "iso8859-1");
4156 DEFSYM (Qiso10646_1, "iso10646-1");
4157 DEFSYM (Qunicode_bmp, "unicode-bmp");
4158 DEFSYM (Qunicode_sip, "unicode-sip");
4160 DEFSYM (QCotf, ":otf");
4161 DEFSYM (QClanguage, ":language");
4162 DEFSYM (QCscript, ":script");
4163 DEFSYM (QCantialias, ":antialias");
4165 DEFSYM (QCfoundry, ":foundry");
4166 DEFSYM (QCadstyle, ":adstyle");
4167 DEFSYM (QCregistry, ":registry");
4168 DEFSYM (QCspacing, ":spacing");
4169 DEFSYM (QCdpi, ":dpi");
4170 DEFSYM (QCscalable, ":scalable");
4171 DEFSYM (QCextra, ":extra");
4173 DEFSYM (Qc, "c");
4174 DEFSYM (Qm, "m");
4175 DEFSYM (Qp, "p");
4176 DEFSYM (Qd, "d");
4178 staticpro (&null_string);
4179 null_string = build_string ("");
4180 staticpro (&null_vector);
4181 null_vector = Fmake_vector (make_number (0), Qnil);
4183 staticpro (&scratch_font_spec);
4184 scratch_font_spec = Ffont_spec (0, NULL);
4185 staticpro (&scratch_font_prefer);
4186 scratch_font_prefer = Ffont_spec (0, NULL);
4188 #ifdef HAVE_LIBOTF
4189 staticpro (&otf_list);
4190 otf_list = Qnil;
4191 #endif
4193 defsubr (&Sfontp);
4194 defsubr (&Sfont_spec);
4195 defsubr (&Sfont_get);
4196 defsubr (&Sfont_put);
4197 defsubr (&Slist_fonts);
4198 defsubr (&Slist_families);
4199 defsubr (&Sfind_font);
4200 defsubr (&Sfont_xlfd_name);
4201 defsubr (&Sclear_font_cache);
4202 defsubr (&Sinternal_set_font_style_table);
4203 defsubr (&Sfont_make_gstring);
4204 defsubr (&Sfont_fill_gstring);
4205 defsubr (&Sfont_shape_text);
4206 defsubr (&Sfont_drive_otf);
4207 defsubr (&Sfont_otf_alternates);
4209 #ifdef FONT_DEBUG
4210 defsubr (&Sopen_font);
4211 defsubr (&Sclose_font);
4212 defsubr (&Squery_font);
4213 defsubr (&Sget_font_glyphs);
4214 defsubr (&Sfont_match_p);
4215 defsubr (&Sfont_at);
4216 #if 0
4217 defsubr (&Sdraw_string);
4218 #endif
4219 #endif /* FONT_DEBUG */
4221 #ifdef USE_FONT_BACKEND
4222 if (enable_font_backend)
4224 #ifdef HAVE_FREETYPE
4225 syms_of_ftfont ();
4226 #ifdef HAVE_X_WINDOWS
4227 syms_of_xfont ();
4228 syms_of_ftxfont ();
4229 #ifdef HAVE_XFT
4230 syms_of_xftfont ();
4231 #endif /* HAVE_XFT */
4232 #endif /* HAVE_X_WINDOWS */
4233 #else /* not HAVE_FREETYPE */
4234 #ifdef HAVE_X_WINDOWS
4235 syms_of_xfont ();
4236 #endif /* HAVE_X_WINDOWS */
4237 #endif /* not HAVE_FREETYPE */
4238 #ifdef HAVE_BDFFONT
4239 syms_of_bdffont ();
4240 #endif /* HAVE_BDFFONT */
4241 #ifdef WINDOWSNT
4242 syms_of_w32font ();
4243 #endif /* WINDOWSNT */
4244 #ifdef MAC_OS
4245 syms_of_atmfont ();
4246 #endif /* MAC_OS */
4248 #endif /* USE_FONT_BACKEND */
4251 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
4252 (do not change this comment) */