(browse-url-text-xterm): Unquote browse-url-text-browser.
[emacs.git] / src / font.c
blob9856c935ef6e0ee0aa765d43ae00fb3e7a019dc3
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 Fsignal (Qfont, list2 (build_string ("invalid font property"),
547 elt));
548 XSETCDR (elt, val);
551 return spec;
554 /* Store VAL as a value of extra font property PROP in FONT. */
556 Lisp_Object
557 font_put_extra (font, prop, val)
558 Lisp_Object font, prop, val;
560 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
561 Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
563 if (NILP (slot))
565 extra = Fcons (Fcons (prop, val), extra);
566 ASET (font, FONT_EXTRA_INDEX, extra);
567 return val;
569 XSETCDR (slot, val);
570 return val;
574 /* Font name parser and unparser */
576 static Lisp_Object intern_font_field P_ ((char *, int));
577 static int parse_matrix P_ ((char *));
578 static int font_expand_wildcards P_ ((Lisp_Object *, int));
579 static int font_parse_name P_ ((char *, Lisp_Object));
581 /* An enumerator for each field of an XLFD font name. */
582 enum xlfd_field_index
584 XLFD_FOUNDRY_INDEX,
585 XLFD_FAMILY_INDEX,
586 XLFD_WEIGHT_INDEX,
587 XLFD_SLANT_INDEX,
588 XLFD_SWIDTH_INDEX,
589 XLFD_ADSTYLE_INDEX,
590 XLFD_PIXEL_INDEX,
591 XLFD_POINT_INDEX,
592 XLFD_RESX_INDEX,
593 XLFD_RESY_INDEX,
594 XLFD_SPACING_INDEX,
595 XLFD_AVGWIDTH_INDEX,
596 XLFD_REGISTRY_INDEX,
597 XLFD_ENCODING_INDEX,
598 XLFD_LAST_INDEX
601 /* An enumerator for mask bit corresponding to each XLFD field. */
602 enum xlfd_field_mask
604 XLFD_FOUNDRY_MASK = 0x0001,
605 XLFD_FAMILY_MASK = 0x0002,
606 XLFD_WEIGHT_MASK = 0x0004,
607 XLFD_SLANT_MASK = 0x0008,
608 XLFD_SWIDTH_MASK = 0x0010,
609 XLFD_ADSTYLE_MASK = 0x0020,
610 XLFD_PIXEL_MASK = 0x0040,
611 XLFD_POINT_MASK = 0x0080,
612 XLFD_RESX_MASK = 0x0100,
613 XLFD_RESY_MASK = 0x0200,
614 XLFD_SPACING_MASK = 0x0400,
615 XLFD_AVGWIDTH_MASK = 0x0800,
616 XLFD_REGISTRY_MASK = 0x1000,
617 XLFD_ENCODING_MASK = 0x2000
621 /* Return a Lispy value of a XLFD font field at STR and LEN bytes.
622 If LEN is zero, it returns `null_string'.
623 If STR is "*", it returns nil.
624 If all characters in STR are digits, it returns an integer.
625 Otherwise, it returns a symbol interned from downcased STR. */
627 static Lisp_Object
628 intern_font_field (str, len)
629 char *str;
630 int len;
632 int i;
634 if (len == 0)
635 return null_string;
636 if (*str == '*' && len == 1)
637 return Qnil;
638 if (isdigit (*str))
640 for (i = 1; i < len; i++)
641 if (! isdigit (str[i]))
642 break;
643 if (i == len)
644 return make_number (atoi (str));
646 return intern_downcase (str, len);
649 /* Parse P pointing the pixel/point size field of the form
650 `[A B C D]' which specifies a transformation matrix:
652 A B 0
653 C D 0
654 0 0 1
656 by which all glyphs of the font are transformed. The spec says
657 that scalar value N for the pixel/point size is equivalent to:
658 A = N * resx/resy, B = C = 0, D = N.
660 Return the scalar value N if the form is valid. Otherwise return
661 -1. */
663 static int
664 parse_matrix (p)
665 char *p;
667 double matrix[4];
668 char *end;
669 int i;
671 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
673 if (*p == '~')
674 matrix[i] = - strtod (p + 1, &end);
675 else
676 matrix[i] = strtod (p, &end);
677 p = end;
679 return (i == 4 ? (int) matrix[3] : -1);
682 /* Expand a wildcard field in FIELD (the first N fields are filled) to
683 multiple fields to fill in all 14 XLFD fields while restring a
684 field position by its contents. */
686 static int
687 font_expand_wildcards (field, n)
688 Lisp_Object field[XLFD_LAST_INDEX];
689 int n;
691 /* Copy of FIELD. */
692 Lisp_Object tmp[XLFD_LAST_INDEX];
693 /* Array of information about where this element can go. Nth
694 element is for Nth element of FIELD. */
695 struct {
696 /* Minimum possible field. */
697 int from;
698 /* Maxinum possible field. */
699 int to;
700 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
701 int mask;
702 } range[XLFD_LAST_INDEX];
703 int i, j;
704 int range_from, range_to;
705 unsigned range_mask;
707 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
708 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
709 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
710 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
711 | XLFD_AVGWIDTH_MASK)
712 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
714 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
715 field. The value is shifted to left one bit by one in the
716 following loop. */
717 for (i = 0, range_mask = 0; i <= 14 - n; i++)
718 range_mask = (range_mask << 1) | 1;
720 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
721 position-based retriction for FIELD[I]. */
722 for (i = 0, range_from = 0, range_to = 14 - n; i < n;
723 i++, range_from++, range_to++, range_mask <<= 1)
725 Lisp_Object val = field[i];
727 tmp[i] = val;
728 if (NILP (val))
730 /* Wildcard. */
731 range[i].from = range_from;
732 range[i].to = range_to;
733 range[i].mask = range_mask;
735 else
737 /* The triplet FROM, TO, and MASK is a value-based
738 retriction for FIELD[I]. */
739 int from, to;
740 unsigned mask;
742 if (INTEGERP (val))
744 int numeric = XINT (val);
746 if (i + 1 == n)
747 from = to = XLFD_ENCODING_INDEX,
748 mask = XLFD_ENCODING_MASK;
749 else if (numeric == 0)
750 from = XLFD_PIXEL_INDEX, to = XLFD_AVGWIDTH_INDEX,
751 mask = XLFD_PIXEL_MASK | XLFD_LARGENUM_MASK;
752 else if (numeric <= 48)
753 from = to = XLFD_PIXEL_INDEX,
754 mask = XLFD_PIXEL_MASK;
755 else
756 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
757 mask = XLFD_LARGENUM_MASK;
759 else if (EQ (val, null_string))
760 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
761 mask = XLFD_NULL_MASK;
762 else if (i == 0)
763 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
764 else if (i + 1 == n)
766 Lisp_Object name = SYMBOL_NAME (val);
768 if (SDATA (name)[SBYTES (name) - 1] == '*')
769 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
770 mask = XLFD_REGENC_MASK;
771 else
772 from = to = XLFD_ENCODING_INDEX,
773 mask = XLFD_ENCODING_MASK;
775 else if (range_from <= XLFD_WEIGHT_INDEX
776 && range_to >= XLFD_WEIGHT_INDEX
777 && !NILP (prop_name_to_numeric (FONT_WEIGHT_INDEX, val)))
778 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
779 else if (range_from <= XLFD_SLANT_INDEX
780 && range_to >= XLFD_SLANT_INDEX
781 && !NILP (prop_name_to_numeric (FONT_SLANT_INDEX, val)))
782 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
783 else if (range_from <= XLFD_SWIDTH_INDEX
784 && range_to >= XLFD_SWIDTH_INDEX
785 && !NILP (prop_name_to_numeric (FONT_WIDTH_INDEX, val)))
786 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
787 else
789 if (EQ (val, Qc) || EQ (val, Qm) || EQ (val, Qp) || EQ (val, Qd))
790 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
791 else
792 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
793 mask = XLFD_SYMBOL_MASK;
796 /* Merge position-based and value-based restrictions. */
797 mask &= range_mask;
798 while (from < range_from)
799 mask &= ~(1 << from++);
800 while (from < 14 && ! (mask & (1 << from)))
801 from++;
802 while (to > range_to)
803 mask &= ~(1 << to--);
804 while (to >= 0 && ! (mask & (1 << to)))
805 to--;
806 if (from > to)
807 return -1;
808 range[i].from = from;
809 range[i].to = to;
810 range[i].mask = mask;
812 if (from > range_from || to < range_to)
814 /* The range is narrowed by value-based restrictions.
815 Reflect it to the other fields. */
817 /* Following fields should be after FROM. */
818 range_from = from;
819 /* Preceding fields should be before TO. */
820 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
822 /* Check FROM for non-wildcard field. */
823 if (! NILP (tmp[j]) && range[j].from < from)
825 while (range[j].from < from)
826 range[j].mask &= ~(1 << range[j].from++);
827 while (from < 14 && ! (range[j].mask & (1 << from)))
828 from++;
829 range[j].from = from;
831 else
832 from = range[j].from;
833 if (range[j].to > to)
835 while (range[j].to > to)
836 range[j].mask &= ~(1 << range[j].to--);
837 while (to >= 0 && ! (range[j].mask & (1 << to)))
838 to--;
839 range[j].to = to;
841 else
842 to = range[j].to;
843 if (from > to)
844 return -1;
850 /* Decide all fileds from restrictions in RANGE. */
851 for (i = j = 0; i < n ; i++)
853 if (j < range[i].from)
855 if (i == 0 || ! NILP (tmp[i - 1]))
856 /* None of TMP[X] corresponds to Jth field. */
857 return -1;
858 for (; j < range[i].from; j++)
859 field[j] = Qnil;
861 field[j++] = tmp[i];
863 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
864 return -1;
865 for (; j < XLFD_LAST_INDEX; j++)
866 field[j] = Qnil;
867 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
868 field[XLFD_ENCODING_INDEX]
869 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
870 return 0;
874 #ifdef ENABLE_CHECKING
875 /* Match a 14-field XLFD pattern against a full XLFD font name. */
876 static int
877 font_match_xlfd (char *pattern, char *name)
879 while (*pattern && *name)
881 if (*pattern == *name)
882 pattern++;
883 else if (*pattern == '*')
884 if (*name == pattern[1])
885 pattern += 2;
886 else
888 else
889 return 0;
890 name++;
892 return 1;
895 /* Make sure the font object matches the XLFD font name. */
896 static int
897 font_check_xlfd_parse (Lisp_Object font, char *name)
899 char name_check[256];
900 font_unparse_xlfd (font, 0, name_check, 255);
901 return font_match_xlfd (name_check, name);
904 #endif
906 /* Parse NAME (null terminated) as XLFD and store information in FONT
907 (font-spec or font-entity). Size property of FONT is set as
908 follows:
909 specified XLFD fields FONT property
910 --------------------- -------------
911 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
912 POINT_SIZE and RESY calculated pixel size (Lisp integer)
913 POINT_SIZE POINT_SIZE/10 (Lisp float)
915 If NAME is successfully parsed, return 0. Otherwise return -1.
917 FONT is usually a font-spec, but when this function is called from
918 X font backend driver, it is a font-entity. In that case, NAME is
919 a fully specified XLFD, and we set FONT_EXTRA_INDEX of FONT to a
920 symbol RESX-RESY-SPACING-AVGWIDTH.
924 font_parse_xlfd (name, font)
925 char *name;
926 Lisp_Object font;
928 int len = strlen (name);
929 int i, j;
930 Lisp_Object dpi, spacing;
931 int avgwidth;
932 char *f[XLFD_LAST_INDEX + 1];
933 Lisp_Object val;
934 char *p;
936 if (len > 255)
937 /* Maximum XLFD name length is 255. */
938 return -1;
939 /* Accept "*-.." as a fully specified XLFD. */
940 if (name[0] == '*' && name[1] == '-')
941 i = 1, f[XLFD_FOUNDRY_INDEX] = name;
942 else
943 i = 0;
944 for (p = name + i; *p; p++)
945 if (*p == '-' && i < XLFD_LAST_INDEX)
946 f[i++] = p + 1;
947 f[i] = p;
949 dpi = spacing = Qnil;
950 avgwidth = -1;
952 if (i == XLFD_LAST_INDEX)
954 int pixel_size;
956 /* Fully specified XLFD. */
957 for (i = 0, j = FONT_FOUNDRY_INDEX; i < XLFD_WEIGHT_INDEX; i++, j++)
959 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
960 if (! NILP (val))
961 ASET (font, j, val);
963 for (j = FONT_WEIGHT_INDEX; i < XLFD_ADSTYLE_INDEX; i++, j++)
965 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
966 if (! NILP (val))
968 Lisp_Object numeric = prop_name_to_numeric (j, val);
970 if (INTEGERP (numeric))
971 val = numeric;
972 ASET (font, j, val);
975 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
976 if (! NILP (val))
977 ASET (font, FONT_ADSTYLE_INDEX, val);
978 i = XLFD_REGISTRY_INDEX;
979 val = intern_font_field (f[i], f[i + 2] - f[i]);
980 if (! NILP (val))
981 ASET (font, FONT_REGISTRY_INDEX, val);
983 p = f[XLFD_PIXEL_INDEX];
984 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
985 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
986 else
988 i = XLFD_PIXEL_INDEX;
989 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
990 if (! NILP (val))
991 ASET (font, FONT_SIZE_INDEX, val);
992 else
994 double point_size = -1;
996 xassert (FONT_SPEC_P (font));
997 p = f[XLFD_POINT_INDEX];
998 if (*p == '[')
999 point_size = parse_matrix (p);
1000 else if (isdigit (*p))
1001 point_size = atoi (p), point_size /= 10;
1002 if (point_size >= 0)
1003 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1004 else
1006 i = XLFD_PIXEL_INDEX;
1007 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
1008 if (! NILP (val))
1009 ASET (font, FONT_SIZE_INDEX, val);
1014 /* Parse RESX, RESY, SPACING, and AVGWIDTH. */
1015 if (FONT_ENTITY_P (font))
1017 i = XLFD_RESX_INDEX;
1018 ASET (font, FONT_EXTRA_INDEX,
1019 intern_font_field (f[i], f[XLFD_REGISTRY_INDEX] - 1 - f[i]));
1020 eassert (font_check_xlfd_parse (font, name));
1021 return 0;
1024 /* Here we just setup DPI, SPACING, and AVGWIDTH. They are set
1025 in FONT_EXTRA_INDEX later. */
1026 i = XLFD_RESX_INDEX;
1027 dpi = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
1028 i = XLFD_SPACING_INDEX;
1029 spacing = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
1030 p = f[XLFD_AVGWIDTH_INDEX];
1031 if (*p == '~')
1032 p++;
1033 if (isdigit (*p))
1034 avgwidth = atoi (p);
1036 else
1038 int wild_card_found = 0;
1039 Lisp_Object prop[XLFD_LAST_INDEX];
1041 for (j = 0; j < i; j++)
1043 if (*f[j] == '*')
1045 if (f[j][1] && f[j][1] != '-')
1046 return -1;
1047 prop[j] = Qnil;
1048 wild_card_found = 1;
1050 else if (isdigit (*f[j]))
1052 for (p = f[j] + 1; isdigit (*p); p++);
1053 if (*p && *p != '-')
1054 prop[j] = intern_downcase (f[j], p - f[j]);
1055 else
1056 prop[j] = make_number (atoi (f[j]));
1058 else if (j + 1 < i)
1059 prop[j] = intern_font_field (f[j], f[j + 1] - 1 - f[j]);
1060 else
1061 prop[j] = intern_font_field (f[j], f[i] - f[j]);
1063 if (! wild_card_found)
1064 return -1;
1065 if (font_expand_wildcards (prop, i) < 0)
1066 return -1;
1068 for (i = 0, j = FONT_FOUNDRY_INDEX; i < XLFD_WEIGHT_INDEX; i++, j++)
1069 if (! NILP (prop[i]))
1070 ASET (font, j, prop[i]);
1071 for (j = FONT_WEIGHT_INDEX; i < XLFD_ADSTYLE_INDEX; i++, j++)
1072 if (! NILP (prop[i]))
1073 ASET (font, j, prop[i]);
1074 if (! NILP (prop[XLFD_ADSTYLE_INDEX]))
1075 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1076 val = prop[XLFD_REGISTRY_INDEX];
1077 if (NILP (val))
1079 val = prop[XLFD_ENCODING_INDEX];
1080 if (! NILP (val))
1081 val = Fintern (concat2 (build_string ("*-"), SYMBOL_NAME (val)),
1082 Qnil);
1084 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1085 val = Fintern (concat2 (SYMBOL_NAME (val), build_string ("-*")),
1086 Qnil);
1087 else
1088 val = Fintern (concat3 (SYMBOL_NAME (val), build_string ("-"),
1089 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX])),
1090 Qnil);
1091 if (! NILP (val))
1092 ASET (font, FONT_REGISTRY_INDEX, val);
1094 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1095 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
1096 else if (INTEGERP (prop[XLFD_POINT_INDEX]))
1098 double point_size = XINT (prop[XLFD_POINT_INDEX]);
1100 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1103 dpi = prop[XLFD_RESX_INDEX];
1104 spacing = prop[XLFD_SPACING_INDEX];
1105 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1106 avgwidth = XINT (prop[XLFD_AVGWIDTH_INDEX]);
1109 if (! NILP (dpi))
1110 font_put_extra (font, QCdpi, dpi);
1111 if (! NILP (spacing))
1112 font_put_extra (font, QCspacing, spacing);
1113 if (avgwidth >= 0)
1114 font_put_extra (font, QCscalable, avgwidth == 0 ? Qt : Qnil);
1116 return 0;
1119 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1120 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1121 0, use PIXEL_SIZE instead. */
1124 font_unparse_xlfd (font, pixel_size, name, nbytes)
1125 Lisp_Object font;
1126 int pixel_size;
1127 char *name;
1128 int nbytes;
1130 char *f[XLFD_REGISTRY_INDEX + 1];
1131 Lisp_Object val;
1132 int i, j, len = 0;
1134 xassert (FONTP (font));
1136 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
1137 i++, j++)
1139 if (i == FONT_ADSTYLE_INDEX)
1140 j = XLFD_ADSTYLE_INDEX;
1141 else if (i == FONT_REGISTRY_INDEX)
1142 j = XLFD_REGISTRY_INDEX;
1143 val = AREF (font, i);
1144 if (NILP (val))
1146 if (j == XLFD_REGISTRY_INDEX)
1147 f[j] = "*-*", len += 4;
1148 else
1149 f[j] = "*", len += 2;
1151 else
1153 if (SYMBOLP (val))
1154 val = SYMBOL_NAME (val);
1155 if (j == XLFD_REGISTRY_INDEX
1156 && ! strchr ((char *) SDATA (val), '-'))
1158 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1159 if (SDATA (val)[SBYTES (val) - 1] == '*')
1161 f[j] = alloca (SBYTES (val) + 3);
1162 sprintf (f[j], "%s-*", SDATA (val));
1163 len += SBYTES (val) + 3;
1165 else
1167 f[j] = alloca (SBYTES (val) + 4);
1168 sprintf (f[j], "%s*-*", SDATA (val));
1169 len += SBYTES (val) + 4;
1172 else
1173 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1177 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1178 i++, j++)
1180 val = AREF (font, i);
1181 if (NILP (val))
1182 f[j] = "*", len += 2;
1183 else
1185 if (INTEGERP (val))
1186 val = prop_numeric_to_name (i, XINT (val));
1187 if (SYMBOLP (val))
1188 val = SYMBOL_NAME (val);
1189 xassert (STRINGP (val));
1190 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1194 val = AREF (font, FONT_SIZE_INDEX);
1195 xassert (NUMBERP (val) || NILP (val));
1196 if (INTEGERP (val))
1198 int i = XINT (val);
1199 if (i <= 0)
1200 i = pixel_size;
1201 if (i > 0)
1203 f[XLFD_PIXEL_INDEX] = alloca (22);
1204 len += sprintf (f[XLFD_PIXEL_INDEX], "%d-*", i) + 1;
1206 else
1207 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1209 else if (FLOATP (val))
1211 int i = XFLOAT_DATA (val) * 10;
1212 f[XLFD_PIXEL_INDEX] = alloca (12);
1213 len += sprintf (f[XLFD_PIXEL_INDEX], "*-%d", i) + 1;
1215 else
1216 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1218 val = AREF (font, FONT_EXTRA_INDEX);
1220 if (FONT_ENTITY_P (font)
1221 && EQ (AREF (font, FONT_TYPE_INDEX), Qx))
1223 /* Setup names for RESX-RESY-SPACING-AVWIDTH. */
1224 if (SYMBOLP (val) && ! NILP (val))
1226 val = SYMBOL_NAME (val);
1227 f[XLFD_RESX_INDEX] = (char *) SDATA (val), len += SBYTES (val) + 1;
1229 else
1230 f[XLFD_RESX_INDEX] = "*-*-*-*", len += 6;
1232 else
1234 Lisp_Object dpi = assq_no_quit (QCdpi, val);
1235 Lisp_Object spacing = assq_no_quit (QCspacing, val);
1236 Lisp_Object scalable = assq_no_quit (QCscalable, val);
1238 if (CONSP (dpi) || CONSP (spacing) || CONSP (scalable))
1240 char *str = alloca (24);
1241 int this_len;
1243 if (CONSP (dpi) && INTEGERP (XCDR (dpi)))
1244 this_len = sprintf (str, "%d-%d",
1245 XINT (XCDR (dpi)), XINT (XCDR (dpi)));
1246 else
1247 this_len = sprintf (str, "*-*");
1248 if (CONSP (spacing) && ! NILP (XCDR (spacing)))
1250 val = XCDR (spacing);
1251 if (INTEGERP (val))
1253 if (XINT (val) < FONT_SPACING_MONO)
1254 val = Qp;
1255 else if (XINT (val) < FONT_SPACING_CHARCELL)
1256 val = Qm;
1257 else
1258 val = Qc;
1260 xassert (SYMBOLP (val));
1261 this_len += sprintf (str + this_len, "-%c",
1262 SDATA (SYMBOL_NAME (val))[0]);
1264 else
1265 this_len += sprintf (str + this_len, "-*");
1266 if (CONSP (scalable) && ! NILP (XCDR (spacing)))
1267 this_len += sprintf (str + this_len, "-0");
1268 else
1269 this_len += sprintf (str + this_len, "-*");
1270 f[XLFD_RESX_INDEX] = str;
1271 len += this_len;
1273 else
1274 f[XLFD_RESX_INDEX] = "*-*-*-*", len += 8;
1277 len++; /* for terminating '\0'. */
1278 if (len >= nbytes)
1279 return -1;
1280 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1281 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1282 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1283 f[XLFD_SWIDTH_INDEX],
1284 f[XLFD_ADSTYLE_INDEX], f[XLFD_PIXEL_INDEX],
1285 f[XLFD_RESX_INDEX], f[XLFD_REGISTRY_INDEX]);
1288 /* Parse NAME (null terminated) as Fonconfig's name format and store
1289 information in FONT (font-spec or font-entity). If NAME is
1290 successfully parsed, return 0. Otherwise return -1. */
1293 font_parse_fcname (name, font)
1294 char *name;
1295 Lisp_Object font;
1297 char *p0, *p1;
1298 int len = strlen (name);
1299 char *copy;
1300 int weight_set = 0;
1301 int slant_set = 0;
1303 if (len == 0)
1304 return -1;
1305 /* It is assured that (name[0] && name[0] != '-'). */
1306 if (name[0] == ':')
1307 p0 = name;
1308 else
1310 Lisp_Object family;
1311 double point_size;
1313 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++)
1314 if (*p0 == '\\' && p0[1])
1315 p0++;
1316 family = intern_font_field (name, p0 - name);
1317 if (*p0 == '-')
1319 if (! isdigit (p0[1]))
1320 return -1;
1321 point_size = strtod (p0 + 1, &p1);
1322 if (*p1 && *p1 != ':')
1323 return -1;
1324 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1325 p0 = p1;
1327 ASET (font, FONT_FAMILY_INDEX, family);
1330 len -= p0 - name;
1331 copy = alloca (len + 1);
1332 if (! copy)
1333 return -1;
1334 name = copy;
1336 /* Now parse ":KEY=VAL" patterns. Store known keys and values in
1337 extra, copy unknown ones to COPY. */
1338 while (*p0)
1340 Lisp_Object key, val;
1341 int prop;
1343 for (p1 = p0 + 1; *p1 && *p1 != '=' && *p1 != ':'; p1++);
1344 if (*p1 != '=')
1346 /* Must be an enumerated value. */
1347 val = intern_font_field (p0 + 1, p1 - p0 - 1);
1348 if (memcmp (p0 + 1, "light", 5) == 0
1349 || memcmp (p0 + 1, "medium", 6) == 0
1350 || memcmp (p0 + 1, "demibold", 8) == 0
1351 || memcmp (p0 + 1, "bold", 4) == 0
1352 || memcmp (p0 + 1, "black", 5) == 0)
1354 ASET (font, FONT_WEIGHT_INDEX, val);
1355 weight_set = 1;
1357 else if (memcmp (p0 + 1, "roman", 5) == 0
1358 || memcmp (p0 + 1, "italic", 6) == 0
1359 || memcmp (p0 + 1, "oblique", 7) == 0)
1361 ASET (font, FONT_SLANT_INDEX, val);
1362 slant_set = 1;
1364 else if (memcmp (p0 + 1, "charcell", 8) == 0
1365 || memcmp (p0 + 1, "mono", 4) == 0
1366 || memcmp (p0 + 1, "proportional", 12) == 0)
1368 font_put_extra (font, QCspacing,
1369 (p0[1] == 'c' ? Qc : p0[1] == 'm' ? Qm : Qp));
1371 else
1373 /* unknown key */
1374 bcopy (p0, copy, p1 - p0);
1375 copy += p1 - p0;
1378 else
1380 if (memcmp (p0 + 1, "pixelsize=", 10) == 0)
1381 prop = FONT_SIZE_INDEX;
1382 else
1384 key = intern_font_field (p0, p1 - p0);
1385 prop = get_font_prop_index (key, 0);
1387 p0 = p1 + 1;
1388 for (p1 = p0; *p1 && *p1 != ':'; p1++);
1389 val = intern_font_field (p0, p1 - p0);
1390 if (! NILP (val))
1392 if (prop >= 0 && prop < FONT_EXTRA_INDEX)
1394 if (prop == FONT_WEIGHT_INDEX)
1395 weight_set = 1;
1396 else if (prop == FONT_SLANT_INDEX)
1397 slant_set = 1;
1399 ASET (font, prop, val);
1401 else
1402 font_put_extra (font, key, val);
1405 p0 = p1;
1408 if (!weight_set)
1409 ASET (font, FONT_WEIGHT_INDEX, build_string ("normal"));
1410 if (!slant_set)
1411 ASET (font, FONT_SLANT_INDEX, build_string ("normal"));
1413 return 0;
1416 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1417 NAME (NBYTES length), and return the name length. If
1418 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1421 font_unparse_fcname (font, pixel_size, name, nbytes)
1422 Lisp_Object font;
1423 int pixel_size;
1424 char *name;
1425 int nbytes;
1427 Lisp_Object val;
1428 int point_size;
1429 int dpi, spacing, scalable;
1430 int i, len = 1;
1431 char *p;
1432 Lisp_Object styles[3];
1433 char *style_names[3] = { "weight", "slant", "width" };
1435 val = AREF (font, FONT_FAMILY_INDEX);
1436 if (SYMBOLP (val) && ! NILP (val))
1437 len += SBYTES (SYMBOL_NAME (val));
1439 val = AREF (font, FONT_SIZE_INDEX);
1440 if (INTEGERP (val))
1442 if (XINT (val) != 0)
1443 pixel_size = XINT (val);
1444 point_size = -1;
1445 len += 21; /* for ":pixelsize=NUM" */
1447 else if (FLOATP (val))
1449 pixel_size = -1;
1450 point_size = (int) XFLOAT_DATA (val);
1451 len += 11; /* for "-NUM" */
1454 val = AREF (font, FONT_FOUNDRY_INDEX);
1455 if (SYMBOLP (val) && ! NILP (val))
1456 /* ":foundry=NAME" */
1457 len += 9 + SBYTES (SYMBOL_NAME (val));
1459 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
1461 val = AREF (font, i);
1462 if (INTEGERP (val))
1464 val = prop_numeric_to_name (i, XINT (val));
1466 if (SYMBOLP (val) && ! NILP (val))
1467 len += (strlen (style_names[i - FONT_WEIGHT_INDEX])
1468 + 2 + SBYTES (SYMBOL_NAME (val))); /* :xxx=NAME */
1469 styles[i - FONT_WEIGHT_INDEX] = val;
1472 val = AREF (font, FONT_EXTRA_INDEX);
1473 if (FONT_ENTITY_P (font)
1474 && EQ (AREF (font, FONT_TYPE_INDEX), Qx))
1476 char *p;
1478 /* VAL is a symbol of name `RESX-RESY-SPACING-AVWIDTH'. */
1479 p = (char *) SDATA (SYMBOL_NAME (val));
1480 dpi = atoi (p);
1481 for (p++; *p != '-'; p++); /* skip RESX */
1482 for (p++; *p != '-'; p++); /* skip RESY */
1483 spacing = (*p == 'c' ? FONT_SPACING_CHARCELL
1484 : *p == 'm' ? FONT_SPACING_MONO
1485 : FONT_SPACING_PROPORTIONAL);
1486 for (p++; *p != '-'; p++); /* skip SPACING */
1487 scalable = (atoi (p) == 0);
1488 /* The longest pattern is ":dpi=NUM:scalable=False:spacing=100" */
1489 len += 42;
1491 else
1493 Lisp_Object elt;
1495 dpi = spacing = scalable = -1;
1496 elt = assq_no_quit (QCdpi, val);
1497 if (CONSP (elt))
1498 dpi = XINT (XCDR (elt)), len += 15; /* for ":dpi=NUM" */
1499 elt = assq_no_quit (QCspacing, val);
1500 if (CONSP (elt))
1501 spacing = XINT (XCDR (elt)), len += 12; /* for ":spacing=100" */
1502 elt = assq_no_quit (QCscalable, val);
1503 if (CONSP (elt))
1504 scalable = ! NILP (XCDR (elt)), len += 15; /* for ":scalable=False" */
1507 if (len > nbytes)
1508 return -1;
1509 p = name;
1510 if (! NILP (AREF (font, FONT_FAMILY_INDEX)))
1511 p += sprintf(p, "%s",
1512 SDATA (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX))));
1513 if (point_size > 0)
1515 if (p == name)
1516 p += sprintf (p, "%d", point_size);
1517 else
1518 p += sprintf (p, "-%d", point_size);
1520 else if (pixel_size > 0)
1521 p += sprintf (p, ":pixelsize=%d", pixel_size);
1522 if (SYMBOLP (AREF (font, FONT_FOUNDRY_INDEX))
1523 && ! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1524 p += sprintf (p, ":foundry=%s",
1525 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1526 for (i = 0; i < 3; i++)
1527 if (SYMBOLP (styles[i]) && ! NILP (styles [i]))
1528 p += sprintf (p, ":%s=%s", style_names[i],
1529 SDATA (SYMBOL_NAME (styles [i])));
1530 if (dpi >= 0)
1531 p += sprintf (p, ":dpi=%d", dpi);
1532 if (spacing >= 0)
1533 p += sprintf (p, ":spacing=%d", spacing);
1534 if (scalable > 0)
1535 p += sprintf (p, ":scalable=True");
1536 else if (scalable == 0)
1537 p += sprintf (p, ":scalable=False");
1538 return (p - name);
1541 /* Parse NAME (null terminated) and store information in FONT
1542 (font-spec or font-entity). If NAME is successfully parsed, return
1543 0. Otherwise return -1.
1545 If NAME is XLFD and FONT is a font-entity, store
1546 RESX-RESY-SPACING-AVWIDTH information as a symbol in
1547 FONT_EXTRA_INDEX. */
1549 static int
1550 font_parse_name (name, font)
1551 char *name;
1552 Lisp_Object font;
1554 if (name[0] == '-' || index (name, '*'))
1555 return font_parse_xlfd (name, font);
1556 return font_parse_fcname (name, font);
1559 /* Merge old style font specification (either a font name NAME or a
1560 combination of a family name FAMILY and a registry name REGISTRY
1561 into the font specification SPEC. */
1563 void
1564 font_merge_old_spec (name, family, registry, spec)
1565 Lisp_Object name, family, registry, spec;
1567 if (STRINGP (name))
1569 if (font_parse_xlfd ((char *) SDATA (name), spec) < 0)
1571 Lisp_Object extra = Fcons (Fcons (QCname, name), Qnil);
1573 ASET (spec, FONT_EXTRA_INDEX, extra);
1576 else
1578 if (! NILP (family))
1580 int len;
1581 char *p0, *p1;
1583 xassert (STRINGP (family));
1584 len = SBYTES (family);
1585 p0 = (char *) SDATA (family);
1586 p1 = index (p0, '-');
1587 if (p1)
1589 if ((*p0 != '*' || p1 - p0 > 1)
1590 && NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
1591 ASET (spec, FONT_FOUNDRY_INDEX,
1592 intern_downcase (p0, p1 - p0));
1593 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1594 ASET (spec, FONT_FAMILY_INDEX,
1595 intern_downcase (p1 + 1, len - (p1 + 1 - p0)));
1597 else if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1598 ASET (spec, FONT_FAMILY_INDEX, intern_downcase (p0, len));
1600 if (! NILP (registry)
1601 && NILP (AREF (spec, FONT_REGISTRY_INDEX)))
1602 ASET (spec, FONT_REGISTRY_INDEX,
1603 intern_downcase ((char *) SDATA (registry), SBYTES (registry)));
1608 /* This part (through the next ^L) is still experimental and never
1609 tested. We may drastically change codes. */
1611 /* OTF handler */
1613 #define LGSTRING_HEADER_SIZE 6
1614 #define LGSTRING_GLYPH_SIZE 8
1616 static int
1617 check_gstring (gstring)
1618 Lisp_Object gstring;
1620 Lisp_Object val;
1621 int i, j;
1623 CHECK_VECTOR (gstring);
1624 val = AREF (gstring, 0);
1625 CHECK_VECTOR (val);
1626 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1627 goto err;
1628 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1629 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1630 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1631 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1632 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1633 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1634 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1635 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1636 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1637 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1638 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1640 for (i = 0; i < LGSTRING_LENGTH (gstring); i++)
1642 val = LGSTRING_GLYPH (gstring, i);
1643 CHECK_VECTOR (val);
1644 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1645 goto err;
1646 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1647 break;
1648 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1649 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1650 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1651 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1652 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1653 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1654 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1655 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1657 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1658 CHECK_VECTOR (val);
1659 if (ASIZE (val) < 3)
1660 goto err;
1661 for (j = 0; j < 3; j++)
1662 CHECK_NUMBER (AREF (val, j));
1665 return i;
1666 err:
1667 error ("Invalid glyph-string format");
1668 return -1;
1671 static void
1672 check_otf_features (otf_features)
1673 Lisp_Object otf_features;
1675 Lisp_Object val, elt;
1677 CHECK_CONS (otf_features);
1678 CHECK_SYMBOL (XCAR (otf_features));
1679 otf_features = XCDR (otf_features);
1680 CHECK_CONS (otf_features);
1681 CHECK_SYMBOL (XCAR (otf_features));
1682 otf_features = XCDR (otf_features);
1683 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1685 CHECK_SYMBOL (Fcar (val));
1686 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1687 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val)));
1689 otf_features = XCDR (otf_features);
1690 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1692 CHECK_SYMBOL (Fcar (val));
1693 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1694 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val)));
1698 #ifdef HAVE_LIBOTF
1699 #include <otf.h>
1701 Lisp_Object otf_list;
1703 static Lisp_Object
1704 otf_tag_symbol (tag)
1705 OTF_Tag tag;
1707 char name[5];
1709 OTF_tag_name (tag, name);
1710 return Fintern (make_unibyte_string (name, 4), Qnil);
1713 static OTF *
1714 otf_open (entity, file)
1715 Lisp_Object entity;
1716 char *file;
1718 Lisp_Object val = Fassoc (entity, otf_list);
1719 OTF *otf;
1721 if (! NILP (val))
1722 otf = XSAVE_VALUE (XCDR (val))->pointer;
1723 else
1725 otf = file ? OTF_open (file) : NULL;
1726 val = make_save_value (otf, 0);
1727 otf_list = Fcons (Fcons (entity, val), otf_list);
1729 return otf;
1733 /* Return a list describing which scripts/languages FONT supports by
1734 which GSUB/GPOS features of OpenType tables. See the comment of
1735 (struct font_driver).otf_capability. */
1737 Lisp_Object
1738 font_otf_capability (font)
1739 struct font *font;
1741 OTF *otf;
1742 Lisp_Object capability = Fcons (Qnil, Qnil);
1743 int i;
1745 otf = otf_open (font->entity, font->file_name);
1746 if (! otf)
1747 return Qnil;
1748 for (i = 0; i < 2; i++)
1750 OTF_GSUB_GPOS *gsub_gpos;
1751 Lisp_Object script_list = Qnil;
1752 int j;
1754 if (OTF_get_features (otf, i == 0) < 0)
1755 continue;
1756 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1757 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1759 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1760 Lisp_Object langsys_list = Qnil;
1761 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1762 int k;
1764 for (k = script->LangSysCount; k >= 0; k--)
1766 OTF_LangSys *langsys;
1767 Lisp_Object feature_list = Qnil;
1768 Lisp_Object langsys_tag;
1769 int l;
1771 if (k == script->LangSysCount)
1773 langsys = &script->DefaultLangSys;
1774 langsys_tag = Qnil;
1776 else
1778 langsys = script->LangSys + k;
1779 langsys_tag
1780 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
1782 for (l = langsys->FeatureCount - 1; l >= 0; l--)
1784 OTF_Feature *feature
1785 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
1786 Lisp_Object feature_tag
1787 = otf_tag_symbol (feature->FeatureTag);
1789 feature_list = Fcons (feature_tag, feature_list);
1791 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1792 langsys_list);
1794 script_list = Fcons (Fcons (script_tag, langsys_list),
1795 script_list);
1798 if (i == 0)
1799 XSETCAR (capability, script_list);
1800 else
1801 XSETCDR (capability, script_list);
1804 return capability;
1807 /* Parse OTF features in SPEC and write a proper features spec string
1808 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1809 assured that the sufficient memory has already allocated for
1810 FEATURES. */
1812 static void
1813 generate_otf_features (spec, features)
1814 Lisp_Object spec;
1815 char *features;
1817 Lisp_Object val;
1818 char *p, *pend;
1819 int asterisk;
1821 p = features;
1822 *p = '\0';
1823 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
1825 val = XCAR (spec);
1826 CHECK_SYMBOL (val);
1827 if (p > features)
1828 *p++ = ',';
1829 if (SREF (SYMBOL_NAME (val), 0) == '*')
1831 asterisk = 1;
1832 *p++ = '*';
1834 else if (! asterisk)
1836 val = SYMBOL_NAME (val);
1837 p += sprintf (p, "%s", SDATA (val));
1839 else
1841 val = SYMBOL_NAME (val);
1842 p += sprintf (p, "~%s", SDATA (val));
1845 if (CONSP (spec))
1846 error ("OTF spec too long");
1850 Lisp_Object
1851 font_otf_DeviceTable (device_table)
1852 OTF_DeviceTable *device_table;
1854 int len = device_table->StartSize - device_table->EndSize + 1;
1856 return Fcons (make_number (len),
1857 make_unibyte_string (device_table->DeltaValue, len));
1860 Lisp_Object
1861 font_otf_ValueRecord (value_format, value_record)
1862 int value_format;
1863 OTF_ValueRecord *value_record;
1865 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
1867 if (value_format & OTF_XPlacement)
1868 ASET (val, 0, make_number (value_record->XPlacement));
1869 if (value_format & OTF_YPlacement)
1870 ASET (val, 1, make_number (value_record->YPlacement));
1871 if (value_format & OTF_XAdvance)
1872 ASET (val, 2, make_number (value_record->XAdvance));
1873 if (value_format & OTF_YAdvance)
1874 ASET (val, 3, make_number (value_record->YAdvance));
1875 if (value_format & OTF_XPlaDevice)
1876 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
1877 if (value_format & OTF_YPlaDevice)
1878 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
1879 if (value_format & OTF_XAdvDevice)
1880 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
1881 if (value_format & OTF_YAdvDevice)
1882 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
1883 return val;
1886 Lisp_Object
1887 font_otf_Anchor (anchor)
1888 OTF_Anchor *anchor;
1890 Lisp_Object val;
1892 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
1893 ASET (val, 0, make_number (anchor->XCoordinate));
1894 ASET (val, 1, make_number (anchor->YCoordinate));
1895 if (anchor->AnchorFormat == 2)
1896 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
1897 else
1899 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
1900 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
1902 return val;
1905 #endif /* HAVE_LIBOTF */
1907 /* G-string (glyph string) handler */
1909 /* G-string is a vector of the form [HEADER GLYPH ...].
1910 See the docstring of `font-make-gstring' for more detail. */
1912 struct font *
1913 font_prepare_composition (cmp, f)
1914 struct composition *cmp;
1915 FRAME_PTR f;
1917 Lisp_Object gstring
1918 = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
1919 cmp->hash_index * 2);
1921 cmp->font = XSAVE_VALUE (LGSTRING_FONT (gstring))->pointer;
1922 cmp->glyph_len = LGSTRING_LENGTH (gstring);
1923 cmp->pixel_width = LGSTRING_WIDTH (gstring);
1924 cmp->lbearing = LGSTRING_LBEARING (gstring);
1925 cmp->rbearing = LGSTRING_RBEARING (gstring);
1926 cmp->ascent = LGSTRING_ASCENT (gstring);
1927 cmp->descent = LGSTRING_DESCENT (gstring);
1928 cmp->width = cmp->pixel_width / FRAME_COLUMN_WIDTH (f);
1929 if (cmp->width == 0)
1930 cmp->width = 1;
1932 return cmp->font;
1936 /* Font sorting */
1938 static unsigned font_score P_ ((Lisp_Object, Lisp_Object *));
1939 static int font_compare P_ ((const void *, const void *));
1940 static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object,
1941 Lisp_Object, Lisp_Object));
1943 /* We sort fonts by scoring each of them against a specified
1944 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1945 the value is, the closer the font is to the font-spec.
1947 Each 1-bit of the highest 4 bits of the score is used for atomic
1948 properties FOUNDRY, FAMILY, ADSTYLE, and REGISTRY.
1950 Each 7-bit in the lowest 28 bits are used for numeric properties
1951 WEIGHT, SLANT, WIDTH, and SIZE. */
1953 /* How many bits to shift to store the difference value of each font
1954 property in a score. */
1955 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
1957 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1958 The return value indicates how different ENTITY is compared with
1959 SPEC_PROP. */
1961 static unsigned
1962 font_score (entity, spec_prop)
1963 Lisp_Object entity, *spec_prop;
1965 unsigned score = 0;
1966 int i;
1967 /* Score four atomic fields. Maximum difference is 1. */
1968 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
1969 if (! NILP (spec_prop[i])
1970 && ! EQ (spec_prop[i], AREF (entity, i)))
1971 score |= 1 << sort_shift_bits[i];
1973 /* Score four numeric fields. Maximum difference is 127. */
1974 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
1976 Lisp_Object entity_val = AREF (entity, i);
1977 Lisp_Object spec_val = spec_prop[i];
1979 /* If weight and slant are unspecified, score normal lower (low wins). */
1980 if (NILP (spec_val))
1982 if (i == FONT_WEIGHT_INDEX || i == FONT_SLANT_INDEX)
1983 spec_val = prop_name_to_numeric (i, build_string ("normal"));
1986 if (! NILP (spec_val) && ! EQ (spec_val, entity_val))
1988 if (! INTEGERP (entity_val))
1989 score |= 127 << sort_shift_bits[i];
1990 else
1992 int diff = XINT (entity_val) - XINT (spec_val);
1994 if (diff < 0)
1995 diff = - diff;
1996 if (i == FONT_SIZE_INDEX)
1998 if (XINT (entity_val) > 0
1999 && diff > FONT_PIXEL_SIZE_QUANTUM)
2000 score |= min (diff, 127) << sort_shift_bits[i];
2002 #ifdef WINDOWSNT
2003 else if (i == FONT_WEIGHT_INDEX)
2005 /* Windows uses a much wider range for weight (100-900)
2006 compared with freetype (0-210), so scale down the
2007 difference. A more general way of doing this
2008 would be to look up the values of regular and bold
2009 and/or light and calculate the scale factor from them,
2010 but the lookup would be expensive, and if only Windows
2011 needs it, not worth the effort. */
2012 score |= min (diff / 4, 127) << sort_shift_bits[i];
2014 #endif
2015 else
2016 score |= min (diff, 127) << sort_shift_bits[i];
2021 return score;
2025 /* The comparison function for qsort. */
2027 static int
2028 font_compare (d1, d2)
2029 const void *d1, *d2;
2031 return (*(unsigned *) d1 < *(unsigned *) d2
2032 ? -1 : *(unsigned *) d1 > *(unsigned *) d2);
2036 /* The structure for elements being sorted by qsort. */
2037 struct font_sort_data
2039 unsigned score;
2040 Lisp_Object entity;
2044 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2045 If PREFER specifies a point-size, calculate the corresponding
2046 pixel-size from QCdpi property of PREFER or from the Y-resolution
2047 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
2048 get the font-entities in VEC. */
2050 static Lisp_Object
2051 font_sort_entites (vec, prefer, frame, spec)
2052 Lisp_Object vec, prefer, frame, spec;
2054 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2055 int len, i;
2056 struct font_sort_data *data;
2057 USE_SAFE_ALLOCA;
2059 len = ASIZE (vec);
2060 if (len <= 1)
2061 return vec;
2063 for (i = FONT_FOUNDRY_INDEX; i <= FONT_SIZE_INDEX; i++)
2064 prefer_prop[i] = AREF (prefer, i);
2066 if (! NILP (spec))
2068 /* As it is assured that all fonts in VEC match with SPEC, we
2069 should ignore properties specified in SPEC. So, set the
2070 corresponding properties in PREFER_PROP to nil. */
2071 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
2072 if (! NILP (AREF (spec, i)))
2073 prefer_prop[i++] = Qnil;
2076 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2077 prefer_prop[FONT_SIZE_INDEX]
2078 = make_number (font_pixel_size (XFRAME (frame), prefer));
2080 /* Scoring and sorting. */
2081 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
2082 for (i = 0; i < len; i++)
2084 data[i].entity = AREF (vec, i);
2085 data[i].score = font_score (data[i].entity, prefer_prop);
2087 qsort (data, len, sizeof *data, font_compare);
2088 for (i = 0; i < len; i++)
2089 ASET (vec, i, data[i].entity);
2090 SAFE_FREE ();
2092 return vec;
2096 /* API of Font Service Layer. */
2098 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2099 sort_shift_bits. Finternal_set_font_selection_order calls this
2100 function with font_sort_order after setting up it. */
2102 void
2103 font_update_sort_order (order)
2104 int *order;
2106 int i, shift_bits = 21;
2108 for (i = 0; i < 4; i++, shift_bits -= 7)
2110 int xlfd_idx = order[i];
2112 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2113 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2114 else if (xlfd_idx == XLFD_SLANT_INDEX)
2115 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2116 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2117 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2118 else
2119 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2124 /* Return weight property of FONT as symbol. */
2126 Lisp_Object
2127 font_symbolic_weight (font)
2128 Lisp_Object font;
2130 Lisp_Object weight = AREF (font, FONT_WEIGHT_INDEX);
2132 if (INTEGERP (weight))
2133 weight = prop_numeric_to_name (FONT_WEIGHT_INDEX, XINT (weight));
2134 return weight;
2138 /* Return slant property of FONT as symbol. */
2140 Lisp_Object
2141 font_symbolic_slant (font)
2142 Lisp_Object font;
2144 Lisp_Object slant = AREF (font, FONT_SLANT_INDEX);
2146 if (INTEGERP (slant))
2147 slant = prop_numeric_to_name (FONT_SLANT_INDEX, XINT (slant));
2148 return slant;
2152 /* Return width property of FONT as symbol. */
2154 Lisp_Object
2155 font_symbolic_width (font)
2156 Lisp_Object font;
2158 Lisp_Object width = AREF (font, FONT_WIDTH_INDEX);
2160 if (INTEGERP (width))
2161 width = prop_numeric_to_name (FONT_WIDTH_INDEX, XINT (width));
2162 return width;
2166 /* Check if ENTITY matches with the font specification SPEC. */
2169 font_match_p (spec, entity)
2170 Lisp_Object spec, entity;
2172 int i;
2174 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
2175 if (! NILP (AREF (spec, i))
2176 && ! EQ (AREF (spec, i), AREF (entity, i)))
2177 return 0;
2178 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX))
2179 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0
2180 && (XINT (AREF (spec, FONT_SIZE_INDEX))
2181 != XINT (AREF (entity, FONT_SIZE_INDEX))))
2182 return 0;
2183 return 1;
2187 /* Return a lispy font object corresponding to FONT. */
2189 Lisp_Object
2190 font_find_object (font)
2191 struct font *font;
2193 Lisp_Object tail, elt;
2195 for (tail = AREF (font->entity, FONT_OBJLIST_INDEX); CONSP (tail);
2196 tail = XCDR (tail))
2198 elt = XCAR (tail);
2199 if (font == XSAVE_VALUE (elt)->pointer
2200 && XSAVE_VALUE (elt)->integer > 0)
2201 return elt;
2203 abort ();
2204 return Qnil;
2208 /* Font cache
2210 Each font backend has the callback function get_cache, and it
2211 returns a cons cell of which cdr part can be freely used for
2212 caching fonts. The cons cell may be shared by multiple frames
2213 and/or multiple font drivers. So, we arrange the cdr part as this:
2215 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2217 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2218 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2219 cons (FONT-SPEC FONT-ENTITY ...). */
2221 static void font_prepare_cache P_ ((FRAME_PTR, struct font_driver *));
2222 static void font_finish_cache P_ ((FRAME_PTR, struct font_driver *));
2223 static Lisp_Object font_get_cache P_ ((FRAME_PTR, struct font_driver *));
2224 static void font_clear_cache P_ ((FRAME_PTR, Lisp_Object,
2225 struct font_driver *));
2227 static void
2228 font_prepare_cache (f, driver)
2229 FRAME_PTR f;
2230 struct font_driver *driver;
2232 Lisp_Object cache, val;
2234 cache = driver->get_cache (f);
2235 val = XCDR (cache);
2236 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2237 val = XCDR (val);
2238 if (NILP (val))
2240 val = Fcons (driver->type, Fcons (make_number (1), Qnil));
2241 XSETCDR (cache, Fcons (val, XCDR (cache)));
2243 else
2245 val = XCDR (XCAR (val));
2246 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2251 static void
2252 font_finish_cache (f, driver)
2253 FRAME_PTR f;
2254 struct font_driver *driver;
2256 Lisp_Object cache, val, tmp;
2259 cache = driver->get_cache (f);
2260 val = XCDR (cache);
2261 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2262 cache = val, val = XCDR (val);
2263 xassert (! NILP (val));
2264 tmp = XCDR (XCAR (val));
2265 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2266 if (XINT (XCAR (tmp)) == 0)
2268 font_clear_cache (f, XCAR (val), driver);
2269 XSETCDR (cache, XCDR (val));
2274 static Lisp_Object
2275 font_get_cache (f, driver)
2276 FRAME_PTR f;
2277 struct font_driver *driver;
2279 Lisp_Object val = driver->get_cache (f);
2280 Lisp_Object type = driver->type;
2282 xassert (CONSP (val));
2283 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2284 xassert (CONSP (val));
2285 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2286 val = XCDR (XCAR (val));
2287 return val;
2290 static int num_fonts;
2292 static void
2293 font_clear_cache (f, cache, driver)
2294 FRAME_PTR f;
2295 Lisp_Object cache;
2296 struct font_driver *driver;
2298 Lisp_Object tail, elt;
2300 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2301 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2303 elt = XCAR (tail);
2304 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2306 Lisp_Object vec = XCDR (elt);
2307 int i;
2309 for (i = 0; i < ASIZE (vec); i++)
2311 Lisp_Object entity = AREF (vec, i);
2313 if (EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2315 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2317 for (; CONSP (objlist); objlist = XCDR (objlist))
2319 Lisp_Object val = XCAR (objlist);
2320 struct Lisp_Save_Value *p = XSAVE_VALUE (val);
2321 struct font *font = p->pointer;
2323 xassert (font && driver == font->driver);
2324 driver->close (f, font);
2325 p->pointer = NULL;
2326 p->integer = 0;
2327 num_fonts--;
2329 if (driver->free_entity)
2330 driver->free_entity (entity);
2335 XSETCDR (cache, Qnil);
2339 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2342 /* Return a vector of font-entities matching with SPEC on frame F. */
2344 static Lisp_Object
2345 font_list_entities (frame, spec)
2346 Lisp_Object frame, spec;
2348 FRAME_PTR f = XFRAME (frame);
2349 struct font_driver_list *driver_list = f->font_driver_list;
2350 Lisp_Object ftype, family, size, alternate_familes;
2351 Lisp_Object *vec = alloca (sizeof (Lisp_Object) * num_font_drivers);
2352 int i;
2354 if (! vec)
2355 return null_vector;
2357 family = AREF (spec, FONT_FAMILY_INDEX);
2358 if (NILP (family))
2359 alternate_familes = Qnil;
2360 else
2362 if (NILP (font_family_alist)
2363 && !NILP (Vface_alternative_font_family_alist))
2364 build_font_family_alist ();
2365 alternate_familes = assq_no_quit (family, font_family_alist);
2366 if (! NILP (alternate_familes))
2367 alternate_familes = XCDR (alternate_familes);
2369 size = AREF (spec, FONT_SIZE_INDEX);
2370 if (FLOATP (size))
2371 ASET (spec, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2373 xassert (ASIZE (spec) == FONT_SPEC_MAX);
2374 ftype = AREF (spec, FONT_TYPE_INDEX);
2376 for (i = 0; driver_list; driver_list = driver_list->next)
2377 if (driver_list->on
2378 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2380 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2381 Lisp_Object tail = alternate_familes;
2383 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2384 ASET (spec, FONT_FAMILY_INDEX, family);
2386 while (1)
2388 Lisp_Object val = assoc_no_quit (spec, XCDR (cache));
2390 if (CONSP (val))
2391 val = XCDR (val);
2392 else
2394 val = driver_list->driver->list (frame, spec);
2395 if (VECTORP (val))
2396 XSETCDR (cache, Fcons (Fcons (Fcopy_sequence (spec), val),
2397 XCDR (cache)));
2399 if (VECTORP (val) && ASIZE (val) > 0)
2401 vec[i++] = val;
2402 break;
2404 if (NILP (tail))
2405 break;
2406 ASET (spec, FONT_FAMILY_INDEX, XCAR (tail));
2407 tail = XCDR (tail);
2410 ASET (spec, FONT_TYPE_INDEX, ftype);
2411 ASET (spec, FONT_FAMILY_INDEX, family);
2412 ASET (spec, FONT_SIZE_INDEX, size);
2413 return (i > 0 ? Fvconcat (i, vec) : null_vector);
2417 /* Return a font entity matching with SPEC on FRAME. */
2419 static Lisp_Object
2420 font_matching_entity (frame, spec)
2421 Lisp_Object frame, spec;
2423 FRAME_PTR f = XFRAME (frame);
2424 struct font_driver_list *driver_list = f->font_driver_list;
2425 Lisp_Object ftype, size, entity;
2427 ftype = AREF (spec, FONT_TYPE_INDEX);
2428 size = AREF (spec, FONT_SIZE_INDEX);
2429 if (FLOATP (size))
2430 ASET (spec, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2431 entity = Qnil;
2432 for (; driver_list; driver_list = driver_list->next)
2433 if (driver_list->on
2434 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2436 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2437 Lisp_Object key;
2439 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2440 key = Fcons (spec, Qnil);
2441 entity = assoc_no_quit (key, XCDR (cache));
2442 if (CONSP (entity))
2443 entity = XCDR (entity);
2444 else
2446 entity = driver_list->driver->match (frame, spec);
2447 if (! NILP (entity))
2449 XSETCAR (key, Fcopy_sequence (spec));
2450 XSETCDR (cache, Fcons (Fcons (key, entity), XCDR (cache)));
2453 if (! NILP (entity))
2454 break;
2456 ASET (spec, FONT_TYPE_INDEX, ftype);
2457 ASET (spec, FONT_SIZE_INDEX, size);
2458 return entity;
2462 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2463 opened font object. */
2465 static Lisp_Object
2466 font_open_entity (f, entity, pixel_size)
2467 FRAME_PTR f;
2468 Lisp_Object entity;
2469 int pixel_size;
2471 struct font_driver_list *driver_list;
2472 Lisp_Object objlist, size, val, font_object;
2473 struct font *font;
2475 size = AREF (entity, FONT_SIZE_INDEX);
2476 xassert (NATNUMP (size));
2477 if (XINT (size) != 0)
2478 pixel_size = XINT (size);
2480 font_object = Qnil;
2481 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2482 objlist = XCDR (objlist))
2484 font = XSAVE_VALUE (XCAR (objlist))->pointer;
2485 if (font->pixel_size == pixel_size)
2487 font_object = XCAR (objlist);
2488 XSAVE_VALUE (font_object)->integer++;
2489 break;
2493 if (NILP (font_object))
2495 val = AREF (entity, FONT_TYPE_INDEX);
2496 for (driver_list = f->font_driver_list;
2497 driver_list && ! EQ (driver_list->driver->type, val);
2498 driver_list = driver_list->next);
2499 if (! driver_list)
2500 return Qnil;
2502 font = driver_list->driver->open (f, entity, pixel_size);
2503 if (! font)
2504 return Qnil;
2505 font->scalable = XINT (size) == 0;
2507 font_object = make_save_value (font, 1);
2508 ASET (entity, FONT_OBJLIST_INDEX,
2509 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2510 num_fonts++;
2513 if (FRAME_SMALLEST_CHAR_WIDTH (f) > font->min_width)
2514 FRAME_SMALLEST_CHAR_WIDTH (f) = font->min_width;
2515 if (FRAME_SMALLEST_CHAR_WIDTH (f) <= 0)
2516 FRAME_SMALLEST_CHAR_WIDTH (f) = 1;
2517 if (FRAME_SMALLEST_FONT_HEIGHT (f) > font->font.height)
2518 FRAME_SMALLEST_FONT_HEIGHT (f) = font->font.height;
2519 if (FRAME_SMALLEST_FONT_HEIGHT (f) <= 0)
2520 FRAME_SMALLEST_FONT_HEIGHT (f) = 1;
2522 return font_object;
2526 /* Close FONT_OBJECT that is opened on frame F. */
2528 void
2529 font_close_object (f, font_object)
2530 FRAME_PTR f;
2531 Lisp_Object font_object;
2533 struct font *font = XSAVE_VALUE (font_object)->pointer;
2534 Lisp_Object objlist;
2535 Lisp_Object tail, prev = Qnil;
2537 xassert (XSAVE_VALUE (font_object)->integer > 0);
2538 XSAVE_VALUE (font_object)->integer--;
2539 if (XSAVE_VALUE (font_object)->integer > 0)
2540 return;
2542 objlist = AREF (font->entity, FONT_OBJLIST_INDEX);
2543 for (prev = Qnil, tail = objlist; CONSP (tail);
2544 prev = tail, tail = XCDR (tail))
2545 if (EQ (font_object, XCAR (tail)))
2547 if (font->driver->close)
2548 font->driver->close (f, font);
2549 XSAVE_VALUE (font_object)->pointer = NULL;
2550 if (NILP (prev))
2551 ASET (font->entity, FONT_OBJLIST_INDEX, XCDR (objlist));
2552 else
2553 XSETCDR (prev, XCDR (objlist));
2554 num_fonts--;
2555 return;
2557 abort ();
2561 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2562 FONT is a font-entity and it must be opened to check. */
2565 font_has_char (f, font, c)
2566 FRAME_PTR f;
2567 Lisp_Object font;
2568 int c;
2570 struct font *fontp;
2572 if (FONT_ENTITY_P (font))
2574 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
2575 struct font_driver_list *driver_list;
2577 for (driver_list = f->font_driver_list;
2578 driver_list && ! EQ (driver_list->driver->type, type);
2579 driver_list = driver_list->next);
2580 if (! driver_list)
2581 return 0;
2582 if (! driver_list->driver->has_char)
2583 return -1;
2584 return driver_list->driver->has_char (font, c);
2587 xassert (FONT_OBJECT_P (font));
2588 fontp = XSAVE_VALUE (font)->pointer;
2590 if (fontp->driver->has_char)
2592 int result = fontp->driver->has_char (fontp->entity, c);
2594 if (result >= 0)
2595 return result;
2597 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
2601 /* Return the glyph ID of FONT_OBJECT for character C. */
2603 unsigned
2604 font_encode_char (font_object, c)
2605 Lisp_Object font_object;
2606 int c;
2608 struct font *font = XSAVE_VALUE (font_object)->pointer;
2610 return font->driver->encode_char (font, c);
2614 /* Return the name of FONT_OBJECT. */
2616 Lisp_Object
2617 font_get_name (font_object)
2618 Lisp_Object font_object;
2620 struct font *font = XSAVE_VALUE (font_object)->pointer;
2621 char *name = (font->font.full_name ? font->font.full_name
2622 : font->font.name ? font->font.name
2623 : NULL);
2625 return (name ? make_unibyte_string (name, strlen (name)) : null_string);
2629 /* Return the specification of FONT_OBJECT. */
2631 Lisp_Object
2632 font_get_spec (font_object)
2633 Lisp_Object font_object;
2635 struct font *font = XSAVE_VALUE (font_object)->pointer;
2636 Lisp_Object spec = Ffont_spec (0, NULL);
2637 int i;
2639 for (i = 0; i < FONT_SIZE_INDEX; i++)
2640 ASET (spec, i, AREF (font->entity, i));
2641 ASET (spec, FONT_SIZE_INDEX, make_number (font->pixel_size));
2642 return spec;
2646 /* Return the frame on which FONT exists. FONT is a font object or a
2647 font entity. */
2649 Lisp_Object
2650 font_get_frame (font)
2651 Lisp_Object font;
2653 if (FONT_OBJECT_P (font))
2654 font = ((struct font *) XSAVE_VALUE (font)->pointer)->entity;
2655 xassert (FONT_ENTITY_P (font));
2656 return AREF (font, FONT_FRAME_INDEX);
2660 /* Find a font entity best matching with LFACE. If SPEC is non-nil,
2661 the font must exactly match with it. C, if not negative, is a
2662 character that the entity must support. */
2664 Lisp_Object
2665 font_find_for_lface (f, lface, spec, c)
2666 FRAME_PTR f;
2667 Lisp_Object *lface;
2668 Lisp_Object spec;
2669 int c;
2671 Lisp_Object frame, entities, val;
2672 int i, result;
2674 XSETFRAME (frame, f);
2676 if (NILP (spec))
2678 if (c >= 0x100)
2679 return Qnil;
2680 for (i = 0; i < FONT_SPEC_MAX; i++)
2681 ASET (scratch_font_spec, i, Qnil);
2682 ASET (scratch_font_spec, FONT_REGISTRY_INDEX, Qiso8859_1);
2684 if (! NILP (lface[LFACE_FAMILY_INDEX]))
2685 font_merge_old_spec (Qnil, lface[LFACE_FAMILY_INDEX], Qnil,
2686 scratch_font_spec);
2687 entities = font_list_entities (frame, scratch_font_spec);
2688 while (ASIZE (entities) == 0)
2690 /* Try without FOUNDRY or FAMILY. */
2691 if (! NILP (AREF (scratch_font_spec, FONT_FOUNDRY_INDEX)))
2693 ASET (scratch_font_spec, FONT_FOUNDRY_INDEX, Qnil);
2694 entities = font_list_entities (frame, scratch_font_spec);
2696 else if (! NILP (AREF (scratch_font_spec, FONT_FAMILY_INDEX)))
2698 ASET (scratch_font_spec, FONT_FAMILY_INDEX, Qnil);
2699 entities = font_list_entities (frame, scratch_font_spec);
2701 else
2702 break;
2705 else
2707 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
2709 if (NILP (registry))
2710 registry = Qiso8859_1;
2712 if (c >= 0)
2714 struct charset *encoding, *repertory;
2716 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
2717 return Qnil;
2718 if (repertory)
2720 if (ENCODE_CHAR (repertory, c)
2721 == CHARSET_INVALID_CODE (repertory))
2722 return Qnil;
2723 /* Any font of this registry support C. So, let's
2724 suppress the further checking. */
2725 c = -1;
2727 else if (c > encoding->max_char)
2728 return Qnil;
2730 for (i = 0; i < FONT_SPEC_MAX; i++)
2731 ASET (scratch_font_spec, i, AREF (spec, i));
2732 ASET (scratch_font_spec, FONT_REGISTRY_INDEX, registry);
2733 entities = font_list_entities (frame, scratch_font_spec);
2736 if (ASIZE (entities) == 0)
2737 return Qnil;
2738 if (ASIZE (entities) > 1)
2740 /* Sort fonts by properties specified in LFACE. */
2741 Lisp_Object prefer = scratch_font_prefer;
2742 double pt;
2744 if (! NILP (lface[LFACE_FAMILY_INDEX]))
2745 font_merge_old_spec (Qnil, lface[LFACE_FAMILY_INDEX], Qnil, prefer);
2746 ASET (prefer, FONT_WEIGHT_INDEX,
2747 font_prop_validate_style (QCweight, lface[LFACE_WEIGHT_INDEX]));
2748 ASET (prefer, FONT_SLANT_INDEX,
2749 font_prop_validate_style (QCslant, lface[LFACE_SLANT_INDEX]));
2750 ASET (prefer, FONT_WIDTH_INDEX,
2751 font_prop_validate_style (QCwidth, lface[LFACE_SWIDTH_INDEX]));
2752 pt = XINT (lface[LFACE_HEIGHT_INDEX]);
2753 ASET (prefer, FONT_SIZE_INDEX, make_float (pt / 10));
2755 font_sort_entites (entities, prefer, frame, spec);
2758 if (c < 0)
2759 return AREF (entities, 0);
2761 val = AREF (entities, 0);
2762 result = font_has_char (f, val, c);
2763 if (result > 0)
2764 return val;
2765 if (result == 0)
2766 return Qnil;
2767 val = font_open_for_lface (f, val, lface, spec);
2768 if (NILP (val))
2769 return Qnil;
2770 result = font_has_char (f, val, c);
2771 font_close_object (f, val);
2772 if (result > 0)
2773 return val;
2774 return Qnil;
2778 Lisp_Object
2779 font_open_for_lface (f, entity, lface, spec)
2780 FRAME_PTR f;
2781 Lisp_Object entity;
2782 Lisp_Object *lface;
2783 Lisp_Object spec;
2785 int size;
2787 if (FONT_SPEC_P (spec) && INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2788 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2789 else
2791 double pt = XINT (lface[LFACE_HEIGHT_INDEX]);
2793 pt /= 10;
2794 size = POINT_TO_PIXEL (pt, f->resy);
2796 return font_open_entity (f, entity, size);
2800 /* Load a font best matching with FACE's font-related properties into
2801 FACE on frame F. If no proper font is found, record that FACE has
2802 no font. */
2804 void
2805 font_load_for_face (f, face)
2806 FRAME_PTR f;
2807 struct face *face;
2809 Lisp_Object font_object = face->lface[LFACE_FONT_INDEX];
2811 if (NILP (font_object))
2813 Lisp_Object entity = font_find_for_lface (f, face->lface, Qnil, -1);
2815 if (! NILP (entity))
2816 font_object = font_open_for_lface (f, entity, face->lface, Qnil);
2818 else if (STRINGP (font_object))
2820 font_object = font_open_by_name (f, SDATA (font_object));
2823 if (! NILP (font_object))
2825 struct font *font = XSAVE_VALUE (font_object)->pointer;
2827 face->font = font->font.font;
2828 face->font_info = (struct font_info *) font;
2829 face->font_info_id = 0;
2830 face->font_name = font->font.full_name;
2832 else
2834 face->font = NULL;
2835 face->font_info = NULL;
2836 face->font_info_id = -1;
2837 face->font_name = NULL;
2838 add_to_log ("Unable to load font for a face%s", null_string, Qnil);
2843 /* Make FACE on frame F ready to use the font opened for FACE. */
2845 void
2846 font_prepare_for_face (f, face)
2847 FRAME_PTR f;
2848 struct face *face;
2850 struct font *font = (struct font *) face->font_info;
2852 if (font->driver->prepare_face)
2853 font->driver->prepare_face (f, face);
2857 /* Make FACE on frame F stop using the font opened for FACE. */
2859 void
2860 font_done_for_face (f, face)
2861 FRAME_PTR f;
2862 struct face *face;
2864 struct font *font = (struct font *) face->font_info;
2866 if (font->driver->done_face)
2867 font->driver->done_face (f, face);
2868 face->extra = NULL;
2872 /* Open a font best matching with NAME on frame F. If no proper font
2873 is found, return Qnil. */
2875 Lisp_Object
2876 font_open_by_name (f, name)
2877 FRAME_PTR f;
2878 char *name;
2880 Lisp_Object args[2];
2881 Lisp_Object spec, prefer, size, entity, entity_list;
2882 Lisp_Object frame;
2883 int i;
2884 int pixel_size;
2886 XSETFRAME (frame, f);
2888 args[0] = QCname;
2889 args[1] = make_unibyte_string (name, strlen (name));
2890 spec = Ffont_spec (2, args);
2891 prefer = scratch_font_prefer;
2892 for (i = FONT_WEIGHT_INDEX; i < FONT_SIZE_INDEX; i++)
2893 if (NILP (AREF (spec, i)))
2894 ASET (prefer, i, make_number (100));
2895 size = AREF (spec, FONT_SIZE_INDEX);
2896 if (NILP (size))
2897 pixel_size = 0;
2898 else if (INTEGERP (size))
2899 pixel_size = XINT (size);
2900 else /* FLOATP (size) */
2902 double pt = XFLOAT_DATA (size);
2904 pixel_size = POINT_TO_PIXEL (pt, f->resy);
2905 size = make_number (pixel_size);
2906 ASET (spec, FONT_SIZE_INDEX, size);
2908 if (pixel_size == 0)
2910 pixel_size = POINT_TO_PIXEL (12.0, f->resy);
2911 size = make_number (pixel_size);
2913 ASET (prefer, FONT_SIZE_INDEX, size);
2914 if (NILP (AREF (spec, FONT_REGISTRY_INDEX)))
2915 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
2917 entity_list = Flist_fonts (spec, frame, make_number (1), prefer);
2918 if (NILP (entity_list))
2919 entity = font_matching_entity (frame, spec);
2920 else
2921 entity = XCAR (entity_list);
2922 return (NILP (entity)
2923 ? Qnil
2924 : font_open_entity (f, entity, pixel_size));
2928 /* Register font-driver DRIVER. This function is used in two ways.
2930 The first is with frame F non-NULL. In this case, make DRIVER
2931 available (but not yet activated) on F. All frame creaters
2932 (e.g. Fx_create_frame) must call this function at least once with
2933 an available font-driver.
2935 The second is with frame F NULL. In this case, DRIVER is globally
2936 registered in the variable `font_driver_list'. All font-driver
2937 implementations must call this function in its syms_of_XXXX
2938 (e.g. syms_of_xfont). */
2940 void
2941 register_font_driver (driver, f)
2942 struct font_driver *driver;
2943 FRAME_PTR f;
2945 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
2946 struct font_driver_list *prev, *list;
2948 if (f && ! driver->draw)
2949 error ("Unusable font driver for a frame: %s",
2950 SDATA (SYMBOL_NAME (driver->type)));
2952 for (prev = NULL, list = root; list; prev = list, list = list->next)
2953 if (EQ (list->driver->type, driver->type))
2954 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
2956 list = malloc (sizeof (struct font_driver_list));
2957 list->on = 0;
2958 list->driver = driver;
2959 list->next = NULL;
2960 if (prev)
2961 prev->next = list;
2962 else if (f)
2963 f->font_driver_list = list;
2964 else
2965 font_driver_list = list;
2966 num_font_drivers++;
2970 /* Free font-driver list on frame F. It doesn't free font-drivers
2971 themselves. */
2973 void
2974 free_font_driver_list (f)
2975 FRAME_PTR f;
2977 while (f->font_driver_list)
2979 struct font_driver_list *next = f->font_driver_list->next;
2981 free (f->font_driver_list);
2982 f->font_driver_list = next;
2987 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
2988 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
2989 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
2991 A caller must free all realized faces if any in advance. The
2992 return value is a list of font backends actually made used on
2993 F. */
2995 Lisp_Object
2996 font_update_drivers (f, new_drivers)
2997 FRAME_PTR f;
2998 Lisp_Object new_drivers;
3000 Lisp_Object active_drivers = Qnil;
3001 struct font_driver_list *list;
3003 for (list = f->font_driver_list; list; list = list->next)
3004 if (list->on)
3006 if (! EQ (new_drivers, Qt)
3007 && NILP (Fmemq (list->driver->type, new_drivers)))
3009 if (list->driver->end_for_frame)
3010 list->driver->end_for_frame (f);
3011 font_finish_cache (f, list->driver);
3012 list->on = 0;
3015 else
3017 if (EQ (new_drivers, Qt)
3018 || ! NILP (Fmemq (list->driver->type, new_drivers)))
3020 if (! list->driver->start_for_frame
3021 || list->driver->start_for_frame (f) == 0)
3023 font_prepare_cache (f, list->driver);
3024 list->on = 1;
3025 active_drivers = nconc2 (active_drivers,
3026 Fcons (list->driver->type, Qnil));
3031 return active_drivers;
3035 font_put_frame_data (f, driver, data)
3036 FRAME_PTR f;
3037 struct font_driver *driver;
3038 void *data;
3040 struct font_data_list *list, *prev;
3042 for (prev = NULL, list = f->font_data_list; list;
3043 prev = list, list = list->next)
3044 if (list->driver == driver)
3045 break;
3046 if (! data)
3048 if (list)
3050 if (prev)
3051 prev->next = list->next;
3052 else
3053 f->font_data_list = list->next;
3054 free (list);
3056 return 0;
3059 if (! list)
3061 list = malloc (sizeof (struct font_data_list));
3062 if (! list)
3063 return -1;
3064 list->driver = driver;
3065 list->next = f->font_data_list;
3066 f->font_data_list = list;
3068 list->data = data;
3069 return 0;
3073 void *
3074 font_get_frame_data (f, driver)
3075 FRAME_PTR f;
3076 struct font_driver *driver;
3078 struct font_data_list *list;
3080 for (list = f->font_data_list; list; list = list->next)
3081 if (list->driver == driver)
3082 break;
3083 if (! list)
3084 return NULL;
3085 return list->data;
3089 /* Return the font used to draw character C by FACE at buffer position
3090 POS in window W. If STRING is non-nil, it is a string containing C
3091 at index POS. If C is negative, get C from the current buffer or
3092 STRING. */
3094 Lisp_Object
3095 font_at (c, pos, face, w, string)
3096 int c;
3097 EMACS_INT pos;
3098 struct face *face;
3099 struct window *w;
3100 Lisp_Object string;
3102 FRAME_PTR f;
3103 int multibyte;
3105 if (c < 0)
3107 if (NILP (string))
3109 multibyte = ! NILP (current_buffer->enable_multibyte_characters);
3110 if (multibyte)
3112 EMACS_INT pos_byte = CHAR_TO_BYTE (pos);
3114 c = FETCH_CHAR (pos_byte);
3116 else
3117 c = FETCH_BYTE (pos);
3119 else
3121 unsigned char *str;
3123 multibyte = STRING_MULTIBYTE (string);
3124 if (multibyte)
3126 EMACS_INT pos_byte = string_char_to_byte (string, pos);
3128 str = SDATA (string) + pos_byte;
3129 c = STRING_CHAR (str, 0);
3131 else
3132 c = SDATA (string)[pos];
3136 f = XFRAME (w->frame);
3137 if (! FRAME_WINDOW_P (f))
3138 return Qnil;
3139 if (! face)
3141 int face_id;
3142 EMACS_INT endptr;
3144 if (STRINGP (string))
3145 face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
3146 DEFAULT_FACE_ID, 0);
3147 else
3148 face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
3149 pos + 100, 0);
3150 face = FACE_FROM_ID (f, face_id);
3152 if (multibyte)
3154 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3155 face = FACE_FROM_ID (f, face_id);
3157 if (! face->font_info)
3158 return Qnil;
3159 return font_find_object ((struct font *) face->font_info);
3163 /* Lisp API */
3165 DEFUN ("fontp", Ffontp, Sfontp, 1, 1, 0,
3166 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3167 Return nil otherwise. */)
3168 (object)
3169 Lisp_Object object;
3171 return (FONTP (object) ? Qt : Qnil);
3174 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3175 doc: /* Return a newly created font-spec with arguments as properties.
3177 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3178 valid font property name listed below:
3180 `:family', `:weight', `:slant', `:width'
3182 They are the same as face attributes of the same name. See
3183 `set-face-attribute'.
3185 `:foundry'
3187 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3189 `:adstyle'
3191 VALUE must be a string or a symbol specifying the additional
3192 typographic style information of a font, e.g. ``sans''. Usually null.
3194 `:registry'
3196 VALUE must be a string or a symbol specifying the charset registry and
3197 encoding of a font, e.g. ``iso8859-1''.
3199 `:size'
3201 VALUE must be a non-negative integer or a floating point number
3202 specifying the font size. It specifies the font size in 1/10 pixels
3203 (if VALUE is an integer), or in points (if VALUE is a float).
3204 usage: (font-spec ARGS ...) */)
3205 (nargs, args)
3206 int nargs;
3207 Lisp_Object *args;
3209 Lisp_Object spec = Fmake_vector (make_number (FONT_SPEC_MAX), Qnil);
3210 int i;
3212 for (i = 0; i < nargs; i += 2)
3214 enum font_property_index prop;
3215 Lisp_Object key = args[i], val = args[i + 1];
3217 prop = get_font_prop_index (key, 0);
3218 if (prop < FONT_EXTRA_INDEX)
3219 ASET (spec, prop, val);
3220 else
3222 if (EQ (key, QCname))
3224 CHECK_STRING (val);
3225 font_parse_name ((char *) SDATA (val), spec);
3227 font_put_extra (spec, key, val);
3230 CHECK_VALIDATE_FONT_SPEC (spec);
3231 return spec;
3235 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
3236 doc: /* Return the value of FONT's property KEY.
3237 FONT is a font-spec, a font-entity, or a font-object. */)
3238 (font, key)
3239 Lisp_Object font, key;
3241 enum font_property_index idx;
3243 if (FONT_OBJECT_P (font))
3245 struct font *fontp = XSAVE_VALUE (font)->pointer;
3247 if (EQ (key, QCotf))
3249 if (fontp->driver->otf_capability)
3250 return fontp->driver->otf_capability (fontp);
3251 else
3252 return Qnil;
3254 font = fontp->entity;
3256 else
3257 CHECK_FONT (font);
3258 idx = get_font_prop_index (key, 0);
3259 if (idx < FONT_EXTRA_INDEX)
3260 return AREF (font, idx);
3261 if (FONT_ENTITY_P (font))
3262 return Qnil;
3263 return Fcdr (Fassoc (key, AREF (font, FONT_EXTRA_INDEX)));
3267 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
3268 doc: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
3269 (font_spec, prop, val)
3270 Lisp_Object font_spec, prop, val;
3272 enum font_property_index idx;
3273 Lisp_Object extra, slot;
3275 CHECK_FONT_SPEC (font_spec);
3276 idx = get_font_prop_index (prop, 0);
3277 if (idx < FONT_EXTRA_INDEX)
3278 return ASET (font_spec, idx, val);
3279 extra = AREF (font_spec, FONT_EXTRA_INDEX);
3280 slot = Fassoc (extra, prop);
3281 if (NILP (slot))
3282 extra = Fcons (Fcons (prop, val), extra);
3283 else
3284 Fsetcdr (slot, val);
3285 return val;
3288 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
3289 doc: /* List available fonts matching FONT-SPEC on the current frame.
3290 Optional 2nd argument FRAME specifies the target frame.
3291 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
3292 Optional 4th argument PREFER, if non-nil, is a font-spec to
3293 control the order of the returned list. Fonts are sorted by
3294 how they are close to PREFER. */)
3295 (font_spec, frame, num, prefer)
3296 Lisp_Object font_spec, frame, num, prefer;
3298 Lisp_Object vec, list, tail;
3299 int n = 0, i, len;
3301 if (NILP (frame))
3302 frame = selected_frame;
3303 CHECK_LIVE_FRAME (frame);
3304 CHECK_VALIDATE_FONT_SPEC (font_spec);
3305 if (! NILP (num))
3307 CHECK_NUMBER (num);
3308 n = XINT (num);
3309 if (n <= 0)
3310 return Qnil;
3312 if (! NILP (prefer))
3313 CHECK_FONT (prefer);
3315 vec = font_list_entities (frame, font_spec);
3316 len = ASIZE (vec);
3317 if (len == 0)
3318 return Qnil;
3319 if (len == 1)
3320 return Fcons (AREF (vec, 0), Qnil);
3322 if (! NILP (prefer))
3323 vec = font_sort_entites (vec, prefer, frame, font_spec);
3325 list = tail = Fcons (AREF (vec, 0), Qnil);
3326 if (n == 0 || n > len)
3327 n = len;
3328 for (i = 1; i < n; i++)
3330 Lisp_Object val = Fcons (AREF (vec, i), Qnil);
3332 XSETCDR (tail, val);
3333 tail = val;
3335 return list;
3338 DEFUN ("list-families", Flist_families, Slist_families, 0, 1, 0,
3339 doc: /* List available font families on the current frame.
3340 Optional argument FRAME specifies the target frame. */)
3341 (frame)
3342 Lisp_Object frame;
3344 FRAME_PTR f;
3345 struct font_driver_list *driver_list;
3346 Lisp_Object list;
3348 if (NILP (frame))
3349 frame = selected_frame;
3350 CHECK_LIVE_FRAME (frame);
3351 f = XFRAME (frame);
3352 list = Qnil;
3353 for (driver_list = f->font_driver_list; driver_list;
3354 driver_list = driver_list->next)
3355 if (driver_list->driver->list_family)
3357 Lisp_Object val = driver_list->driver->list_family (frame);
3359 if (NILP (list))
3360 list = val;
3361 else
3363 Lisp_Object tail = list;
3365 for (; CONSP (val); val = XCDR (val))
3366 if (NILP (Fmemq (XCAR (val), tail)))
3367 list = Fcons (XCAR (val), list);
3370 return list;
3373 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
3374 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
3375 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
3376 (font_spec, frame)
3377 Lisp_Object font_spec, frame;
3379 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
3381 if (CONSP (val))
3382 val = XCAR (val);
3383 return val;
3386 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 1, 0,
3387 doc: /* Return XLFD name of FONT.
3388 FONT is a font-spec, font-entity, or font-object.
3389 If the name is too long for XLFD (maximum 255 chars), return nil. */)
3390 (font)
3391 Lisp_Object font;
3393 char name[256];
3394 int pixel_size = 0;
3396 if (FONT_SPEC_P (font))
3397 CHECK_VALIDATE_FONT_SPEC (font);
3398 else if (FONT_ENTITY_P (font))
3399 CHECK_FONT (font);
3400 else
3402 struct font *fontp;
3404 CHECK_FONT_GET_OBJECT (font, fontp);
3405 font = fontp->entity;
3406 pixel_size = fontp->pixel_size;
3409 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
3410 return Qnil;
3411 return build_string (name);
3414 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
3415 doc: /* Clear font cache. */)
3418 Lisp_Object list, frame;
3420 FOR_EACH_FRAME (list, frame)
3422 FRAME_PTR f = XFRAME (frame);
3423 struct font_driver_list *driver_list = f->font_driver_list;
3425 for (; driver_list; driver_list = driver_list->next)
3426 if (driver_list->on)
3428 Lisp_Object cache = driver_list->driver->get_cache (f);
3429 Lisp_Object val;
3431 val = XCDR (cache);
3432 while (! NILP (val)
3433 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
3434 val = XCDR (val);
3435 xassert (! NILP (val));
3436 val = XCDR (XCAR (val));
3437 if (XINT (XCAR (val)) == 0)
3439 font_clear_cache (f, XCAR (val), driver_list->driver);
3440 XSETCDR (cache, XCDR (val));
3445 return Qnil;
3448 DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table,
3449 Sinternal_set_font_style_table, 2, 2, 0,
3450 doc: /* Set font style table for PROP to TABLE.
3451 PROP must be `:weight', `:slant', or `:width'.
3452 TABLE must be an alist of symbols vs the corresponding numeric values
3453 sorted by numeric values. */)
3454 (prop, table)
3455 Lisp_Object prop, table;
3457 int table_index;
3458 int numeric;
3459 Lisp_Object tail, val;
3461 CHECK_SYMBOL (prop);
3462 table_index = (EQ (prop, QCweight) ? 0
3463 : EQ (prop, QCslant) ? 1
3464 : EQ (prop, QCwidth) ? 2
3465 : 3);
3466 if (table_index >= ASIZE (font_style_table))
3467 error ("Invalid font style property: %s", SDATA (SYMBOL_NAME (prop)));
3468 table = Fcopy_sequence (table);
3469 numeric = -1;
3470 for (tail = table; CONSP (tail); tail = XCDR (tail))
3472 prop = Fcar (XCAR (tail));
3473 val = Fcdr (XCAR (tail));
3474 CHECK_SYMBOL (prop);
3475 CHECK_NATNUM (val);
3476 if (numeric > XINT (val))
3477 error ("Numeric values not sorted for %s", SDATA (SYMBOL_NAME (prop)));
3478 else if (numeric == XINT (val))
3479 error ("Duplicate numeric values for %s", SDATA (SYMBOL_NAME (prop)));
3480 numeric = XINT (val);
3481 XSETCAR (tail, Fcons (prop, val));
3483 ASET (font_style_table, table_index, table);
3484 return Qnil;
3487 /* The following three functions are still expremental. */
3489 DEFUN ("font-make-gstring", Ffont_make_gstring, Sfont_make_gstring, 2, 2, 0,
3490 doc: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
3491 FONT-OBJECT may be nil if it is not yet known.
3493 G-string is sequence of glyphs of a specific font,
3494 and is a vector of this form:
3495 [ HEADER GLYPH ... ]
3496 HEADER is a vector of this form:
3497 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
3498 where
3499 FONT-OBJECT is a font-object for all glyphs in the g-string,
3500 WIDTH thry DESCENT are the metrics (in pixels) of the whole G-string.
3501 GLYPH is a vector of this form:
3502 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
3503 [ [X-OFF Y-OFF WADJUST] | nil] ]
3504 where
3505 FROM-IDX and TO-IDX are used internally and should not be touched.
3506 C is the character of the glyph.
3507 CODE is the glyph-code of C in FONT-OBJECT.
3508 WIDTH thry DESCENT are the metrics (in pixels) of the glyph.
3509 X-OFF and Y-OFF are offests to the base position for the glyph.
3510 WADJUST is the adjustment to the normal width of the glyph. */)
3511 (font_object, num)
3512 Lisp_Object font_object, num;
3514 Lisp_Object gstring, g;
3515 int len;
3516 int i;
3518 if (! NILP (font_object))
3519 CHECK_FONT_OBJECT (font_object);
3520 CHECK_NATNUM (num);
3522 len = XINT (num) + 1;
3523 gstring = Fmake_vector (make_number (len), Qnil);
3524 g = Fmake_vector (make_number (6), Qnil);
3525 ASET (g, 0, font_object);
3526 ASET (gstring, 0, g);
3527 for (i = 1; i < len; i++)
3528 ASET (gstring, i, Fmake_vector (make_number (10), Qnil));
3529 return gstring;
3532 DEFUN ("font-fill-gstring", Ffont_fill_gstring, Sfont_fill_gstring, 4, 5, 0,
3533 doc: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
3534 START and END specify the region to extract characters.
3535 If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
3536 where to extract characters.
3537 FONT-OBJECT may be nil if GSTRING already already contains one. */)
3538 (gstring, font_object, start, end, object)
3539 Lisp_Object gstring, font_object, start, end, object;
3541 int len, i, c;
3542 unsigned code;
3543 struct font *font;
3545 CHECK_VECTOR (gstring);
3546 if (NILP (font_object))
3547 font_object = LGSTRING_FONT (gstring);
3548 CHECK_FONT_GET_OBJECT (font_object, font);
3550 if (STRINGP (object))
3552 const unsigned char *p;
3554 CHECK_NATNUM (start);
3555 CHECK_NATNUM (end);
3556 if (XINT (start) > XINT (end)
3557 || XINT (end) > ASIZE (object)
3558 || XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3559 args_out_of_range_3 (object, start, end);
3561 len = XINT (end) - XINT (start);
3562 p = SDATA (object) + string_char_to_byte (object, XINT (start));
3563 for (i = 0; i < len; i++)
3565 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3566 /* Shut up GCC warning in comparison with
3567 MOST_POSITIVE_FIXNUM below. */
3568 EMACS_INT cod;
3570 c = STRING_CHAR_ADVANCE (p);
3571 cod = code = font->driver->encode_char (font, c);
3572 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3573 break;
3574 LGLYPH_SET_FROM (g, i);
3575 LGLYPH_SET_TO (g, i);
3576 LGLYPH_SET_CHAR (g, c);
3577 LGLYPH_SET_CODE (g, code);
3580 else
3582 int pos, pos_byte;
3584 if (! NILP (object))
3585 Fset_buffer (object);
3586 validate_region (&start, &end);
3587 if (XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3588 args_out_of_range (start, end);
3589 len = XINT (end) - XINT (start);
3590 pos = XINT (start);
3591 pos_byte = CHAR_TO_BYTE (pos);
3592 for (i = 0; i < len; i++)
3594 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3595 /* Shut up GCC warning in comparison with
3596 MOST_POSITIVE_FIXNUM below. */
3597 EMACS_INT cod;
3599 FETCH_CHAR_ADVANCE (c, pos, pos_byte);
3600 cod = code = font->driver->encode_char (font, c);
3601 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3602 break;
3603 LGLYPH_SET_FROM (g, i);
3604 LGLYPH_SET_TO (g, i);
3605 LGLYPH_SET_CHAR (g, c);
3606 LGLYPH_SET_CODE (g, code);
3609 for (; i < LGSTRING_LENGTH (gstring); i++)
3610 LGSTRING_SET_GLYPH (gstring, i, Qnil);
3611 return Qnil;
3614 DEFUN ("font-shape-text", Ffont_shape_text, Sfont_shape_text, 3, 4, 0,
3615 doc: /* Shape text between FROM and TO by FONT-OBJECT.
3616 If optional 4th argument STRING is non-nil, it is a string to shape,
3617 and FROM and TO are indices to the string.
3618 The value is the end position of the text that can be shaped by
3619 FONT-OBJECT. */)
3620 (from, to, font_object, string)
3621 Lisp_Object from, to, font_object, string;
3623 struct font *font;
3624 struct font_metrics metrics;
3625 EMACS_INT start, end;
3626 Lisp_Object gstring, n;
3627 int len, i, j;
3629 if (! FONT_OBJECT_P (font_object))
3630 return Qnil;
3631 CHECK_FONT_GET_OBJECT (font_object, font);
3632 if (! font->driver->shape)
3633 return Qnil;
3635 if (NILP (string))
3637 validate_region (&from, &to);
3638 start = XFASTINT (from);
3639 end = XFASTINT (to);
3640 modify_region (current_buffer, start, end, 0);
3642 else
3644 CHECK_STRING (string);
3645 start = XINT (from);
3646 end = XINT (to);
3647 if (start < 0 || start > end || end > SCHARS (string))
3648 args_out_of_range_3 (string, from, to);
3651 len = end - start;
3652 gstring = Ffont_make_gstring (font_object, make_number (len));
3653 Ffont_fill_gstring (gstring, font_object, from, to, string);
3655 /* Try at most three times with larger gstring each time. */
3656 for (i = 0; i < 3; i++)
3658 Lisp_Object args[2];
3660 n = font->driver->shape (gstring);
3661 if (INTEGERP (n))
3662 break;
3663 args[0] = gstring;
3664 args[1] = Fmake_vector (make_number (len), Qnil);
3665 gstring = Fvconcat (2, args);
3667 if (! INTEGERP (n) || XINT (n) == 0)
3668 return Qnil;
3669 len = XINT (n);
3671 for (i = 0; i < len;)
3673 Lisp_Object gstr;
3674 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3675 EMACS_INT this_from = LGLYPH_FROM (g);
3676 EMACS_INT this_to = LGLYPH_TO (g) + 1;
3677 int j, k;
3678 int need_composition = 0;
3680 metrics.lbearing = LGLYPH_LBEARING (g);
3681 metrics.rbearing = LGLYPH_RBEARING (g);
3682 metrics.ascent = LGLYPH_ASCENT (g);
3683 metrics.descent = LGLYPH_DESCENT (g);
3684 if (NILP (LGLYPH_ADJUSTMENT (g)))
3686 metrics.width = LGLYPH_WIDTH (g);
3687 if (LGLYPH_CHAR (g) == 0 || metrics.width == 0)
3688 need_composition = 1;
3690 else
3692 metrics.width = LGLYPH_WADJUST (g);
3693 metrics.lbearing += LGLYPH_XOFF (g);
3694 metrics.rbearing += LGLYPH_XOFF (g);
3695 metrics.ascent -= LGLYPH_YOFF (g);
3696 metrics.descent += LGLYPH_YOFF (g);
3697 need_composition = 1;
3699 for (j = i + 1; j < len; j++)
3701 int x;
3703 g = LGSTRING_GLYPH (gstring, j);
3704 if (this_from != LGLYPH_FROM (g))
3705 break;
3706 need_composition = 1;
3707 x = metrics.width + LGLYPH_LBEARING (g) + LGLYPH_XOFF (g);
3708 if (metrics.lbearing > x)
3709 metrics.lbearing = x;
3710 x = metrics.width + LGLYPH_RBEARING (g) + LGLYPH_XOFF (g);
3711 if (metrics.rbearing < x)
3712 metrics.rbearing = x;
3713 x = LGLYPH_ASCENT (g) - LGLYPH_YOFF (g);
3714 if (metrics.ascent < x)
3715 metrics.ascent = x;
3716 x = LGLYPH_DESCENT (g) - LGLYPH_YOFF (g);
3717 if (metrics.descent < x)
3718 metrics.descent = x;
3719 if (NILP (LGLYPH_ADJUSTMENT (g)))
3720 metrics.width += LGLYPH_WIDTH (g);
3721 else
3722 metrics.width += LGLYPH_WADJUST (g);
3725 if (need_composition)
3727 gstr = Ffont_make_gstring (font_object, make_number (j - i));
3728 LGSTRING_SET_WIDTH (gstr, metrics.width);
3729 LGSTRING_SET_LBEARING (gstr, metrics.lbearing);
3730 LGSTRING_SET_RBEARING (gstr, metrics.rbearing);
3731 LGSTRING_SET_ASCENT (gstr, metrics.ascent);
3732 LGSTRING_SET_DESCENT (gstr, metrics.descent);
3733 for (k = i; i < j; i++)
3735 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3737 LGLYPH_SET_FROM (g, LGLYPH_FROM (g) - this_from);
3738 LGLYPH_SET_TO (g, LGLYPH_TO (g) - this_from);
3739 LGSTRING_SET_GLYPH (gstr, i - k, LGSTRING_GLYPH (gstring, i));
3741 from = make_number (start + this_from);
3742 to = make_number (start + this_to);
3743 if (NILP (string))
3744 Fcompose_region_internal (from, to, gstr, Qnil);
3745 else
3746 Fcompose_string_internal (string, from, to, gstr, Qnil);
3748 else
3749 i = j;
3752 return to;
3755 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
3756 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
3757 OTF-FEATURES specifies which features to apply in this format:
3758 (SCRIPT LANGSYS GSUB GPOS)
3759 where
3760 SCRIPT is a symbol specifying a script tag of OpenType,
3761 LANGSYS is a symbol specifying a langsys tag of OpenType,
3762 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
3764 If LANGYS is nil, the default langsys is selected.
3766 The features are applied in the order they appear in the list. The
3767 symbol `*' means to apply all available features not present in this
3768 list, and the remaining features are ignored. For instance, (vatu
3769 pstf * haln) is to apply vatu and pstf in this order, then to apply
3770 all available features other than vatu, pstf, and haln.
3772 The features are applied to the glyphs in the range FROM and TO of
3773 the glyph-string GSTRING-IN.
3775 If some feature is actually applicable, the resulting glyphs are
3776 produced in the glyph-string GSTRING-OUT from the index INDEX. In
3777 this case, the value is the number of produced glyphs.
3779 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
3780 the value is 0.
3782 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
3783 produced in GSTRING-OUT, and the value is nil.
3785 See the documentation of `font-make-gstring' for the format of
3786 glyph-string. */)
3787 (otf_features, gstring_in, from, to, gstring_out, index)
3788 Lisp_Object otf_features, gstring_in, from, to, gstring_out, index;
3790 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
3791 Lisp_Object val;
3792 struct font *font;
3793 int len, num;
3795 check_otf_features (otf_features);
3796 CHECK_FONT_GET_OBJECT (font_object, font);
3797 if (! font->driver->otf_drive)
3798 error ("Font backend %s can't drive OpenType GSUB table",
3799 SDATA (SYMBOL_NAME (font->driver->type)));
3800 CHECK_CONS (otf_features);
3801 CHECK_SYMBOL (XCAR (otf_features));
3802 val = XCDR (otf_features);
3803 CHECK_SYMBOL (XCAR (val));
3804 val = XCDR (otf_features);
3805 if (! NILP (val))
3806 CHECK_CONS (val);
3807 len = check_gstring (gstring_in);
3808 CHECK_VECTOR (gstring_out);
3809 CHECK_NATNUM (from);
3810 CHECK_NATNUM (to);
3811 CHECK_NATNUM (index);
3813 if (XINT (from) >= XINT (to) || XINT (to) > len)
3814 args_out_of_range_3 (from, to, make_number (len));
3815 if (XINT (index) >= ASIZE (gstring_out))
3816 args_out_of_range (index, make_number (ASIZE (gstring_out)));
3817 num = font->driver->otf_drive (font, otf_features,
3818 gstring_in, XINT (from), XINT (to),
3819 gstring_out, XINT (index), 0);
3820 if (num < 0)
3821 return Qnil;
3822 return make_number (num);
3825 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
3826 3, 3, 0,
3827 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
3828 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
3829 in this format:
3830 (SCRIPT LANGSYS FEATURE ...)
3831 See the documentation of `font-otf-gsub' for more detail.
3833 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
3834 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
3835 character code corresponding to the glyph or nil if there's no
3836 corresponding character. */)
3837 (font_object, character, otf_features)
3838 Lisp_Object font_object, character, otf_features;
3840 struct font *font;
3841 Lisp_Object gstring_in, gstring_out, g;
3842 Lisp_Object alternates;
3843 int i, num;
3845 CHECK_FONT_GET_OBJECT (font_object, font);
3846 if (! font->driver->otf_drive)
3847 error ("Font backend %s can't drive OpenType GSUB table",
3848 SDATA (SYMBOL_NAME (font->driver->type)));
3849 CHECK_CHARACTER (character);
3850 CHECK_CONS (otf_features);
3852 gstring_in = Ffont_make_gstring (font_object, make_number (1));
3853 g = LGSTRING_GLYPH (gstring_in, 0);
3854 LGLYPH_SET_CHAR (g, XINT (character));
3855 gstring_out = Ffont_make_gstring (font_object, make_number (10));
3856 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
3857 gstring_out, 0, 1)) < 0)
3858 gstring_out = Ffont_make_gstring (font_object,
3859 make_number (ASIZE (gstring_out) * 2));
3860 alternates = Qnil;
3861 for (i = 0; i < num; i++)
3863 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
3864 int c = LGLYPH_CHAR (g);
3865 unsigned code = LGLYPH_CODE (g);
3867 alternates = Fcons (Fcons (make_number (code),
3868 c > 0 ? make_number (c) : Qnil),
3869 alternates);
3871 return Fnreverse (alternates);
3875 #ifdef FONT_DEBUG
3877 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
3878 doc: /* Open FONT-ENTITY. */)
3879 (font_entity, size, frame)
3880 Lisp_Object font_entity;
3881 Lisp_Object size;
3882 Lisp_Object frame;
3884 int isize;
3886 CHECK_FONT_ENTITY (font_entity);
3887 if (NILP (size))
3888 size = AREF (font_entity, FONT_SIZE_INDEX);
3889 CHECK_NUMBER (size);
3890 if (NILP (frame))
3891 frame = selected_frame;
3892 CHECK_LIVE_FRAME (frame);
3894 isize = XINT (size);
3895 if (isize == 0)
3896 isize = 120;
3897 if (isize < 0)
3898 isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy);
3900 return font_open_entity (XFRAME (frame), font_entity, isize);
3903 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
3904 doc: /* Close FONT-OBJECT. */)
3905 (font_object, frame)
3906 Lisp_Object font_object, frame;
3908 CHECK_FONT_OBJECT (font_object);
3909 if (NILP (frame))
3910 frame = selected_frame;
3911 CHECK_LIVE_FRAME (frame);
3912 font_close_object (XFRAME (frame), font_object);
3913 return Qnil;
3916 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
3917 doc: /* Return information about FONT-OBJECT.
3918 The value is a vector:
3919 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
3920 CAPABILITY ]
3922 NAME is a string of the font name (or nil if the font backend doesn't
3923 provide a name).
3925 FILENAME is a string of the font file (or nil if the font backend
3926 doesn't provide a file name).
3928 PIXEL-SIZE is a pixel size by which the font is opened.
3930 SIZE is a maximum advance width of the font in pixel.
3932 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
3933 pixel.
3935 CAPABILITY is a list whose first element is a symbol representing the
3936 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
3937 remaining elements describes a detail of the font capability.
3939 If the font is OpenType font, the form of the list is
3940 \(opentype GSUB GPOS)
3941 where GSUB shows which "GSUB" features the font supports, and GPOS
3942 shows which "GPOS" features the font supports. Both GSUB and GPOS are
3943 lists of the format:
3944 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
3946 If the font is not OpenType font, currently the length of the form is
3947 one.
3949 SCRIPT is a symbol representing OpenType script tag.
3951 LANGSYS is a symbol representing OpenType langsys tag, or nil
3952 representing the default langsys.
3954 FEATURE is a symbol representing OpenType feature tag.
3956 If the font is not OpenType font, CAPABILITY is nil. */)
3957 (font_object)
3958 Lisp_Object font_object;
3960 struct font *font;
3961 Lisp_Object val;
3963 CHECK_FONT_GET_OBJECT (font_object, font);
3965 val = Fmake_vector (make_number (9), Qnil);
3966 if (font->font.full_name)
3967 ASET (val, 0, make_unibyte_string (font->font.full_name,
3968 strlen (font->font.full_name)));
3969 if (font->file_name)
3970 ASET (val, 1, make_unibyte_string (font->file_name,
3971 strlen (font->file_name)));
3972 ASET (val, 2, make_number (font->pixel_size));
3973 ASET (val, 3, make_number (font->font.size));
3974 ASET (val, 4, make_number (font->ascent));
3975 ASET (val, 5, make_number (font->descent));
3976 ASET (val, 6, make_number (font->font.space_width));
3977 ASET (val, 7, make_number (font->font.average_width));
3978 if (font->driver->otf_capability)
3979 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
3980 else
3981 ASET (val, 8, Fcons (font->format, Qnil));
3982 return val;
3985 DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
3986 doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
3987 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
3988 (font_object, string)
3989 Lisp_Object font_object, string;
3991 struct font *font;
3992 int i, len;
3993 Lisp_Object vec;
3995 CHECK_FONT_GET_OBJECT (font_object, font);
3996 CHECK_STRING (string);
3997 len = SCHARS (string);
3998 vec = Fmake_vector (make_number (len), Qnil);
3999 for (i = 0; i < len; i++)
4001 Lisp_Object ch = Faref (string, make_number (i));
4002 Lisp_Object val;
4003 int c = XINT (ch);
4004 unsigned code;
4005 EMACS_INT cod;
4006 struct font_metrics metrics;
4008 cod = code = font->driver->encode_char (font, c);
4009 if (code == FONT_INVALID_CODE)
4010 continue;
4011 val = Fmake_vector (make_number (6), Qnil);
4012 if (cod <= MOST_POSITIVE_FIXNUM)
4013 ASET (val, 0, make_number (code));
4014 else
4015 ASET (val, 0, Fcons (make_number (code >> 16),
4016 make_number (code & 0xFFFF)));
4017 font->driver->text_extents (font, &code, 1, &metrics);
4018 ASET (val, 1, make_number (metrics.lbearing));
4019 ASET (val, 2, make_number (metrics.rbearing));
4020 ASET (val, 3, make_number (metrics.width));
4021 ASET (val, 4, make_number (metrics.ascent));
4022 ASET (val, 5, make_number (metrics.descent));
4023 ASET (vec, i, val);
4025 return vec;
4028 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4029 doc: /* Return t iff font-spec SPEC matches with FONT.
4030 FONT is a font-spec, font-entity, or font-object. */)
4031 (spec, font)
4032 Lisp_Object spec, font;
4034 CHECK_FONT_SPEC (spec);
4035 if (FONT_OBJECT_P (font))
4036 font = ((struct font *) XSAVE_VALUE (font)->pointer)->entity;
4037 else if (! FONT_ENTITY_P (font))
4038 CHECK_FONT_SPEC (font);
4040 return (font_match_p (spec, font) ? Qt : Qnil);
4043 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4044 doc: /* Return a font-object for displaying a character at POSITION.
4045 Optional second arg WINDOW, if non-nil, is a window displaying
4046 the current buffer. It defaults to the currently selected window. */)
4047 (position, window, string)
4048 Lisp_Object position, window, string;
4050 struct window *w;
4051 EMACS_INT pos;
4053 if (NILP (string))
4055 CHECK_NUMBER_COERCE_MARKER (position);
4056 pos = XINT (position);
4057 if (pos < BEGV || pos >= ZV)
4058 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4060 else
4062 EMACS_INT len;
4063 unsigned char *str;
4065 CHECK_NUMBER (position);
4066 CHECK_STRING (string);
4067 pos = XINT (position);
4068 if (pos < 0 || pos >= SCHARS (string))
4069 args_out_of_range (string, position);
4071 if (NILP (window))
4072 window = selected_window;
4073 CHECK_LIVE_WINDOW (window);
4074 w = XWINDOW (window);
4076 return font_at (-1, pos, NULL, w, string);
4079 #if 0
4080 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4081 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4082 The value is a number of glyphs drawn.
4083 Type C-l to recover what previously shown. */)
4084 (font_object, string)
4085 Lisp_Object font_object, string;
4087 Lisp_Object frame = selected_frame;
4088 FRAME_PTR f = XFRAME (frame);
4089 struct font *font;
4090 struct face *face;
4091 int i, len, width;
4092 unsigned *code;
4094 CHECK_FONT_GET_OBJECT (font_object, font);
4095 CHECK_STRING (string);
4096 len = SCHARS (string);
4097 code = alloca (sizeof (unsigned) * len);
4098 for (i = 0; i < len; i++)
4100 Lisp_Object ch = Faref (string, make_number (i));
4101 Lisp_Object val;
4102 int c = XINT (ch);
4104 code[i] = font->driver->encode_char (font, c);
4105 if (code[i] == FONT_INVALID_CODE)
4106 break;
4108 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4109 face->fontp = font;
4110 if (font->driver->prepare_face)
4111 font->driver->prepare_face (f, face);
4112 width = font->driver->text_extents (font, code, i, NULL);
4113 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4114 if (font->driver->done_face)
4115 font->driver->done_face (f, face);
4116 face->fontp = NULL;
4117 return make_number (len);
4119 #endif
4121 #endif /* FONT_DEBUG */
4124 extern void syms_of_ftfont P_ (());
4125 extern void syms_of_xfont P_ (());
4126 extern void syms_of_xftfont P_ (());
4127 extern void syms_of_ftxfont P_ (());
4128 extern void syms_of_bdffont P_ (());
4129 extern void syms_of_w32font P_ (());
4130 extern void syms_of_atmfont P_ (());
4132 void
4133 syms_of_font ()
4135 sort_shift_bits[FONT_SLANT_INDEX] = 0;
4136 sort_shift_bits[FONT_WEIGHT_INDEX] = 7;
4137 sort_shift_bits[FONT_SIZE_INDEX] = 14;
4138 sort_shift_bits[FONT_WIDTH_INDEX] = 21;
4139 sort_shift_bits[FONT_ADSTYLE_INDEX] = 28;
4140 sort_shift_bits[FONT_FOUNDRY_INDEX] = 29;
4141 sort_shift_bits[FONT_FAMILY_INDEX] = 30;
4142 sort_shift_bits[FONT_REGISTRY_INDEX] = 31;
4143 /* Note that sort_shift_bits[FONT_TYPE_INDEX] is never used. */
4145 staticpro (&font_style_table);
4146 font_style_table = Fmake_vector (make_number (3), Qnil);
4148 staticpro (&font_family_alist);
4149 font_family_alist = Qnil;
4151 staticpro (&font_charset_alist);
4152 font_charset_alist = Qnil;
4154 DEFSYM (Qopentype, "opentype");
4156 DEFSYM (Qiso8859_1, "iso8859-1");
4157 DEFSYM (Qiso10646_1, "iso10646-1");
4158 DEFSYM (Qunicode_bmp, "unicode-bmp");
4159 DEFSYM (Qunicode_sip, "unicode-sip");
4161 DEFSYM (QCotf, ":otf");
4162 DEFSYM (QClanguage, ":language");
4163 DEFSYM (QCscript, ":script");
4164 DEFSYM (QCantialias, ":antialias");
4166 DEFSYM (QCfoundry, ":foundry");
4167 DEFSYM (QCadstyle, ":adstyle");
4168 DEFSYM (QCregistry, ":registry");
4169 DEFSYM (QCspacing, ":spacing");
4170 DEFSYM (QCdpi, ":dpi");
4171 DEFSYM (QCscalable, ":scalable");
4172 DEFSYM (QCextra, ":extra");
4174 DEFSYM (Qc, "c");
4175 DEFSYM (Qm, "m");
4176 DEFSYM (Qp, "p");
4177 DEFSYM (Qd, "d");
4179 staticpro (&null_string);
4180 null_string = build_string ("");
4181 staticpro (&null_vector);
4182 null_vector = Fmake_vector (make_number (0), Qnil);
4184 staticpro (&scratch_font_spec);
4185 scratch_font_spec = Ffont_spec (0, NULL);
4186 staticpro (&scratch_font_prefer);
4187 scratch_font_prefer = Ffont_spec (0, NULL);
4189 #ifdef HAVE_LIBOTF
4190 staticpro (&otf_list);
4191 otf_list = Qnil;
4192 #endif
4194 defsubr (&Sfontp);
4195 defsubr (&Sfont_spec);
4196 defsubr (&Sfont_get);
4197 defsubr (&Sfont_put);
4198 defsubr (&Slist_fonts);
4199 defsubr (&Slist_families);
4200 defsubr (&Sfind_font);
4201 defsubr (&Sfont_xlfd_name);
4202 defsubr (&Sclear_font_cache);
4203 defsubr (&Sinternal_set_font_style_table);
4204 defsubr (&Sfont_make_gstring);
4205 defsubr (&Sfont_fill_gstring);
4206 defsubr (&Sfont_shape_text);
4207 defsubr (&Sfont_drive_otf);
4208 defsubr (&Sfont_otf_alternates);
4210 #ifdef FONT_DEBUG
4211 defsubr (&Sopen_font);
4212 defsubr (&Sclose_font);
4213 defsubr (&Squery_font);
4214 defsubr (&Sget_font_glyphs);
4215 defsubr (&Sfont_match_p);
4216 defsubr (&Sfont_at);
4217 #if 0
4218 defsubr (&Sdraw_string);
4219 #endif
4220 #endif /* FONT_DEBUG */
4222 #ifdef USE_FONT_BACKEND
4223 if (enable_font_backend)
4225 #ifdef HAVE_FREETYPE
4226 syms_of_ftfont ();
4227 #ifdef HAVE_X_WINDOWS
4228 syms_of_xfont ();
4229 syms_of_ftxfont ();
4230 #ifdef HAVE_XFT
4231 syms_of_xftfont ();
4232 #endif /* HAVE_XFT */
4233 #endif /* HAVE_X_WINDOWS */
4234 #else /* not HAVE_FREETYPE */
4235 #ifdef HAVE_X_WINDOWS
4236 syms_of_xfont ();
4237 #endif /* HAVE_X_WINDOWS */
4238 #endif /* not HAVE_FREETYPE */
4239 #ifdef HAVE_BDFFONT
4240 syms_of_bdffont ();
4241 #endif /* HAVE_BDFFONT */
4242 #ifdef WINDOWSNT
4243 syms_of_w32font ();
4244 #endif /* WINDOWSNT */
4245 #ifdef MAC_OS
4246 syms_of_atmfont ();
4247 #endif /* MAC_OS */
4249 #endif /* USE_FONT_BACKEND */
4252 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
4253 (do not change this comment) */