1 /* font.c -- "Font" primitives.
3 Copyright (C) 2006-2013 Free Software Foundation, Inc.
4 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
5 National Institute of Advanced Industrial Science and Technology (AIST)
6 Registration Number H13PRO009
8 This file is part of GNU Emacs.
10 GNU Emacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 GNU Emacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
30 #include "character.h"
34 #include "dispextern.h"
36 #include "composite.h"
40 #ifdef HAVE_WINDOW_SYSTEM
42 #endif /* HAVE_WINDOW_SYSTEM */
44 Lisp_Object Qopentype
;
46 /* Important character set strings. */
47 Lisp_Object Qascii_0
, Qiso8859_1
, Qiso10646_1
, Qunicode_bmp
, Qunicode_sip
;
49 #define DEFAULT_ENCODING Qiso8859_1
51 /* Unicode category `Cf'. */
52 static Lisp_Object QCf
;
54 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
55 static Lisp_Object font_style_table
;
57 /* Structure used for tables mapping weight, slant, and width numeric
58 values and their names. */
63 /* The first one is a valid name as a face attribute.
64 The second one (if any) is a typical name in XLFD field. */
68 /* Table of weight numeric values and their names. This table must be
69 sorted by numeric values in ascending order. */
71 static const struct table_entry weight_table
[] =
74 { 20, { "ultra-light", "ultralight" }},
75 { 40, { "extra-light", "extralight" }},
77 { 75, { "semi-light", "semilight", "demilight", "book" }},
78 { 100, { "normal", "medium", "regular", "unspecified" }},
79 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
81 { 205, { "extra-bold", "extrabold" }},
82 { 210, { "ultra-bold", "ultrabold", "black" }}
85 /* Table of slant numeric values and their names. This table must be
86 sorted by numeric values in ascending order. */
88 static const struct table_entry slant_table
[] =
90 { 0, { "reverse-oblique", "ro" }},
91 { 10, { "reverse-italic", "ri" }},
92 { 100, { "normal", "r", "unspecified" }},
93 { 200, { "italic" ,"i", "ot" }},
94 { 210, { "oblique", "o" }}
97 /* Table of width numeric values and their names. This table must be
98 sorted by numeric values in ascending order. */
100 static const struct table_entry width_table
[] =
102 { 50, { "ultra-condensed", "ultracondensed" }},
103 { 63, { "extra-condensed", "extracondensed" }},
104 { 75, { "condensed", "compressed", "narrow" }},
105 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
106 { 100, { "normal", "medium", "regular", "unspecified" }},
107 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
108 { 125, { "expanded" }},
109 { 150, { "extra-expanded", "extraexpanded" }},
110 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
113 Lisp_Object QCfoundry
;
114 static Lisp_Object QCadstyle
, QCregistry
;
115 /* Symbols representing keys of font extra info. */
116 Lisp_Object QCspacing
, QCdpi
, QCscalable
, QCotf
, QClang
, QCscript
, QCavgwidth
;
117 Lisp_Object QCantialias
, QCfont_entity
;
118 static Lisp_Object QCfc_unknown_spec
;
119 /* Symbols representing values of font spacing property. */
120 static Lisp_Object Qc
, Qm
, Qd
;
122 /* Special ADSTYLE properties to avoid fonts used for Latin
123 characters; used in xfont.c and ftfont.c. */
124 Lisp_Object Qja
, Qko
;
126 static Lisp_Object QCuser_spec
;
128 /* Alist of font registry symbols and the corresponding charset
129 information. The information is retrieved from
130 Vfont_encoding_alist on demand.
132 Eash element has the form:
133 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
137 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
138 encodes a character code to a glyph code of a font, and
139 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
140 character is supported by a font.
142 The latter form means that the information for REGISTRY couldn't be
144 static Lisp_Object font_charset_alist
;
146 /* List of all font drivers. Each font-backend (XXXfont.c) calls
147 register_font_driver in syms_of_XXXfont to register its font-driver
149 static struct font_driver_list
*font_driver_list
;
153 /* Creators of font-related Lisp object. */
156 font_make_spec (void)
158 Lisp_Object font_spec
;
159 struct font_spec
*spec
160 = ((struct font_spec
*)
161 allocate_pseudovector (VECSIZE (struct font_spec
),
162 FONT_SPEC_MAX
, PVEC_FONT
));
163 XSETFONT (font_spec
, spec
);
168 font_make_entity (void)
170 Lisp_Object font_entity
;
171 struct font_entity
*entity
172 = ((struct font_entity
*)
173 allocate_pseudovector (VECSIZE (struct font_entity
),
174 FONT_ENTITY_MAX
, PVEC_FONT
));
175 XSETFONT (font_entity
, entity
);
179 /* Create a font-object whose structure size is SIZE. If ENTITY is
180 not nil, copy properties from ENTITY to the font-object. If
181 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
183 font_make_object (int size
, Lisp_Object entity
, int pixelsize
)
185 Lisp_Object font_object
;
187 = (struct font
*) allocate_pseudovector (size
, FONT_OBJECT_MAX
, PVEC_FONT
);
190 XSETFONT (font_object
, font
);
194 for (i
= 1; i
< FONT_SPEC_MAX
; i
++)
195 font
->props
[i
] = AREF (entity
, i
);
196 if (! NILP (AREF (entity
, FONT_EXTRA_INDEX
)))
197 font
->props
[FONT_EXTRA_INDEX
]
198 = Fcopy_alist (AREF (entity
, FONT_EXTRA_INDEX
));
201 font
->props
[FONT_SIZE_INDEX
] = make_number (pixelsize
);
207 static int font_pixel_size (FRAME_PTR f
, Lisp_Object
);
208 static Lisp_Object
font_open_entity (FRAME_PTR
, Lisp_Object
, int);
209 static Lisp_Object
font_matching_entity (FRAME_PTR
, Lisp_Object
*,
211 static unsigned font_encode_char (Lisp_Object
, int);
213 /* Number of registered font drivers. */
214 static int num_font_drivers
;
217 /* Return a Lispy value of a font property value at STR and LEN bytes.
218 If STR is "*", return nil. If FORCE_SYMBOL, or if STR does not
219 consist entirely of one or more digits, return a symbol interned
220 from STR. Otherwise, return an integer. */
223 font_intern_prop (const char *str
, ptrdiff_t len
, bool force_symbol
)
228 ptrdiff_t nbytes
, nchars
;
230 if (len
== 1 && *str
== '*')
232 if (!force_symbol
&& 0 < len
&& '0' <= *str
&& *str
<= '9')
234 for (i
= 1; i
< len
; i
++)
235 if (! ('0' <= str
[i
] && str
[i
] <= '9'))
242 for (n
= 0; (n
+= str
[i
++] - '0') <= MOST_POSITIVE_FIXNUM
; n
*= 10)
245 return make_number (n
);
246 if (MOST_POSITIVE_FIXNUM
/ 10 < n
)
250 xsignal1 (Qoverflow_error
, make_string (str
, len
));
254 /* This code is similar to intern function from lread.c. */
255 obarray
= check_obarray (Vobarray
);
256 parse_str_as_multibyte ((unsigned char *) str
, len
, &nchars
, &nbytes
);
257 tem
= oblookup (obarray
, str
,
258 (len
== nchars
|| len
!= nbytes
) ? len
: nchars
, len
);
262 if (len
== nchars
|| len
!= nbytes
)
263 tem
= make_unibyte_string (str
, len
);
265 tem
= make_multibyte_string (str
, nchars
, len
);
266 return Fintern (tem
, obarray
);
269 /* Return a pixel size of font-spec SPEC on frame F. */
272 font_pixel_size (FRAME_PTR f
, Lisp_Object spec
)
274 #ifdef HAVE_WINDOW_SYSTEM
275 Lisp_Object size
= AREF (spec
, FONT_SIZE_INDEX
);
284 eassert (FLOATP (size
));
285 point_size
= XFLOAT_DATA (size
);
286 val
= AREF (spec
, FONT_DPI_INDEX
);
291 pixel_size
= POINT_TO_PIXEL (point_size
, dpi
);
299 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
300 font vector. If VAL is not valid (i.e. not registered in
301 font_style_table), return -1 if NOERROR is zero, and return a
302 proper index if NOERROR is nonzero. In that case, register VAL in
303 font_style_table if VAL is a symbol, and return the closest index if
304 VAL is an integer. */
307 font_style_to_value (enum font_property_index prop
, Lisp_Object val
,
310 Lisp_Object table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
313 CHECK_VECTOR (table
);
320 Lisp_Object args
[2], elt
;
322 /* At first try exact match. */
323 for (i
= 0; i
< len
; i
++)
325 CHECK_VECTOR (AREF (table
, i
));
326 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
327 if (EQ (val
, AREF (AREF (table
, i
), j
)))
329 CHECK_NUMBER (AREF (AREF (table
, i
), 0));
330 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
331 | (i
<< 4) | (j
- 1));
334 /* Try also with case-folding match. */
335 s
= SSDATA (SYMBOL_NAME (val
));
336 for (i
= 0; i
< len
; i
++)
337 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
339 elt
= AREF (AREF (table
, i
), j
);
340 if (xstrcasecmp (s
, SSDATA (SYMBOL_NAME (elt
))) == 0)
342 CHECK_NUMBER (AREF (AREF (table
, i
), 0));
343 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
344 | (i
<< 4) | (j
- 1));
350 elt
= Fmake_vector (make_number (2), make_number (100));
353 args
[1] = Fmake_vector (make_number (1), elt
);
354 ASET (font_style_table
, prop
- FONT_WEIGHT_INDEX
, Fvconcat (2, args
));
355 return (100 << 8) | (i
<< 4);
360 EMACS_INT numeric
= XINT (val
);
362 for (i
= 0, last_n
= -1; i
< len
; i
++)
366 CHECK_VECTOR (AREF (table
, i
));
367 CHECK_NUMBER (AREF (AREF (table
, i
), 0));
368 n
= XINT (AREF (AREF (table
, i
), 0));
370 return (n
<< 8) | (i
<< 4);
375 return ((i
== 0 || n
- numeric
< numeric
- last_n
)
376 ? (n
<< 8) | (i
<< 4): (last_n
<< 8 | ((i
- 1) << 4)));
382 return ((last_n
<< 8) | ((i
- 1) << 4));
387 font_style_symbolic (Lisp_Object font
, enum font_property_index prop
,
390 Lisp_Object val
= AREF (font
, prop
);
391 Lisp_Object table
, elt
;
396 table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
397 CHECK_VECTOR (table
);
398 i
= XINT (val
) & 0xFF;
399 eassert (((i
>> 4) & 0xF) < ASIZE (table
));
400 elt
= AREF (table
, ((i
>> 4) & 0xF));
402 eassert ((i
& 0xF) + 1 < ASIZE (elt
));
403 elt
= (for_face
? AREF (elt
, 1) : AREF (elt
, (i
& 0xF) + 1));
408 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
409 FONTNAME. ENCODING is a charset symbol that specifies the encoding
410 of the font. REPERTORY is a charset symbol or nil. */
413 find_font_encoding (Lisp_Object fontname
)
415 Lisp_Object tail
, elt
;
417 for (tail
= Vfont_encoding_alist
; CONSP (tail
); tail
= XCDR (tail
))
421 && STRINGP (XCAR (elt
))
422 && fast_string_match_ignore_case (XCAR (elt
), fontname
) >= 0
423 && (SYMBOLP (XCDR (elt
))
424 ? CHARSETP (XCDR (elt
))
425 : CONSP (XCDR (elt
)) && CHARSETP (XCAR (XCDR (elt
)))))
431 /* Return encoding charset and repertory charset for REGISTRY in
432 ENCODING and REPERTORY correspondingly. If correct information for
433 REGISTRY is available, return 0. Otherwise return -1. */
436 font_registry_charsets (Lisp_Object registry
, struct charset
**encoding
, struct charset
**repertory
)
439 int encoding_id
, repertory_id
;
441 val
= Fassoc_string (registry
, font_charset_alist
, Qt
);
447 encoding_id
= XINT (XCAR (val
));
448 repertory_id
= XINT (XCDR (val
));
452 val
= find_font_encoding (SYMBOL_NAME (registry
));
453 if (SYMBOLP (val
) && CHARSETP (val
))
455 encoding_id
= repertory_id
= XINT (CHARSET_SYMBOL_ID (val
));
457 else if (CONSP (val
))
459 if (! CHARSETP (XCAR (val
)))
461 encoding_id
= XINT (CHARSET_SYMBOL_ID (XCAR (val
)));
462 if (NILP (XCDR (val
)))
466 if (! CHARSETP (XCDR (val
)))
468 repertory_id
= XINT (CHARSET_SYMBOL_ID (XCDR (val
)));
473 val
= Fcons (make_number (encoding_id
), make_number (repertory_id
));
475 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, val
), Qnil
));
479 *encoding
= CHARSET_FROM_ID (encoding_id
);
481 *repertory
= repertory_id
>= 0 ? CHARSET_FROM_ID (repertory_id
) : NULL
;
486 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, Qnil
), Qnil
));
491 /* Font property value validators. See the comment of
492 font_property_table for the meaning of the arguments. */
494 static Lisp_Object
font_prop_validate (int, Lisp_Object
, Lisp_Object
);
495 static Lisp_Object
font_prop_validate_symbol (Lisp_Object
, Lisp_Object
);
496 static Lisp_Object
font_prop_validate_style (Lisp_Object
, Lisp_Object
);
497 static Lisp_Object
font_prop_validate_non_neg (Lisp_Object
, Lisp_Object
);
498 static Lisp_Object
font_prop_validate_spacing (Lisp_Object
, Lisp_Object
);
499 static int get_font_prop_index (Lisp_Object
);
502 font_prop_validate_symbol (Lisp_Object prop
, Lisp_Object val
)
505 val
= Fintern (val
, Qnil
);
508 else if (EQ (prop
, QCregistry
))
509 val
= Fintern (Fdowncase (SYMBOL_NAME (val
)), Qnil
);
515 font_prop_validate_style (Lisp_Object style
, Lisp_Object val
)
517 enum font_property_index prop
= (EQ (style
, QCweight
) ? FONT_WEIGHT_INDEX
518 : EQ (style
, QCslant
) ? FONT_SLANT_INDEX
522 EMACS_INT n
= XINT (val
);
523 CHECK_VECTOR (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
));
525 >= ASIZE (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
)))
529 Lisp_Object elt
= AREF (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
), (n
>> 4) & 0xF);
532 if ((n
& 0xF) + 1 >= ASIZE (elt
))
536 CHECK_NUMBER (AREF (elt
, 0));
537 if (XINT (AREF (elt
, 0)) != (n
>> 8))
542 else if (SYMBOLP (val
))
544 int n
= font_style_to_value (prop
, val
, 0);
546 val
= n
>= 0 ? make_number (n
) : Qerror
;
554 font_prop_validate_non_neg (Lisp_Object prop
, Lisp_Object val
)
556 return (NATNUMP (val
) || (FLOATP (val
) && XFLOAT_DATA (val
) >= 0)
561 font_prop_validate_spacing (Lisp_Object prop
, Lisp_Object val
)
563 if (NILP (val
) || (NATNUMP (val
) && XINT (val
) <= FONT_SPACING_CHARCELL
))
565 if (SYMBOLP (val
) && SBYTES (SYMBOL_NAME (val
)) == 1)
567 char spacing
= SDATA (SYMBOL_NAME (val
))[0];
569 if (spacing
== 'c' || spacing
== 'C')
570 return make_number (FONT_SPACING_CHARCELL
);
571 if (spacing
== 'm' || spacing
== 'M')
572 return make_number (FONT_SPACING_MONO
);
573 if (spacing
== 'p' || spacing
== 'P')
574 return make_number (FONT_SPACING_PROPORTIONAL
);
575 if (spacing
== 'd' || spacing
== 'D')
576 return make_number (FONT_SPACING_DUAL
);
582 font_prop_validate_otf (Lisp_Object prop
, Lisp_Object val
)
584 Lisp_Object tail
, tmp
;
587 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
588 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
589 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
592 if (! SYMBOLP (XCAR (val
)))
597 if (! CONSP (tail
) || ! SYMBOLP (XCAR (val
)))
599 for (i
= 0; i
< 2; i
++)
606 for (tmp
= XCAR (tail
); CONSP (tmp
); tmp
= XCDR (tmp
))
607 if (! SYMBOLP (XCAR (tmp
)))
615 /* Structure of known font property keys and validator of the
619 /* Pointer to the key symbol. */
621 /* Function to validate PROP's value VAL, or NULL if any value is
622 ok. The value is VAL or its regularized value if VAL is valid,
623 and Qerror if not. */
624 Lisp_Object (*validator
) (Lisp_Object prop
, Lisp_Object val
);
625 } font_property_table
[] =
626 { { &QCtype
, font_prop_validate_symbol
},
627 { &QCfoundry
, font_prop_validate_symbol
},
628 { &QCfamily
, font_prop_validate_symbol
},
629 { &QCadstyle
, font_prop_validate_symbol
},
630 { &QCregistry
, font_prop_validate_symbol
},
631 { &QCweight
, font_prop_validate_style
},
632 { &QCslant
, font_prop_validate_style
},
633 { &QCwidth
, font_prop_validate_style
},
634 { &QCsize
, font_prop_validate_non_neg
},
635 { &QCdpi
, font_prop_validate_non_neg
},
636 { &QCspacing
, font_prop_validate_spacing
},
637 { &QCavgwidth
, font_prop_validate_non_neg
},
638 /* The order of the above entries must match with enum
639 font_property_index. */
640 { &QClang
, font_prop_validate_symbol
},
641 { &QCscript
, font_prop_validate_symbol
},
642 { &QCotf
, font_prop_validate_otf
}
645 /* Size (number of elements) of the above table. */
646 #define FONT_PROPERTY_TABLE_SIZE \
647 ((sizeof font_property_table) / (sizeof *font_property_table))
649 /* Return an index number of font property KEY or -1 if KEY is not an
650 already known property. */
653 get_font_prop_index (Lisp_Object key
)
657 for (i
= 0; i
< FONT_PROPERTY_TABLE_SIZE
; i
++)
658 if (EQ (key
, *font_property_table
[i
].key
))
663 /* Validate the font property. The property key is specified by the
664 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
665 signal an error. The value is VAL or the regularized one. */
668 font_prop_validate (int idx
, Lisp_Object prop
, Lisp_Object val
)
670 Lisp_Object validated
;
675 prop
= *font_property_table
[idx
].key
;
678 idx
= get_font_prop_index (prop
);
682 validated
= (font_property_table
[idx
].validator
) (prop
, val
);
683 if (EQ (validated
, Qerror
))
684 signal_error ("invalid font property", Fcons (prop
, val
));
689 /* Store VAL as a value of extra font property PROP in FONT while
690 keeping the sorting order. Don't check the validity of VAL. */
693 font_put_extra (Lisp_Object font
, Lisp_Object prop
, Lisp_Object val
)
695 Lisp_Object extra
= AREF (font
, FONT_EXTRA_INDEX
);
696 Lisp_Object slot
= (NILP (extra
) ? Qnil
: assq_no_quit (prop
, extra
));
700 Lisp_Object prev
= Qnil
;
703 && NILP (Fstring_lessp (prop
, XCAR (XCAR (extra
)))))
704 prev
= extra
, extra
= XCDR (extra
);
707 ASET (font
, FONT_EXTRA_INDEX
, Fcons (Fcons (prop
, val
), extra
));
709 XSETCDR (prev
, Fcons (Fcons (prop
, val
), extra
));
715 ASET (font
, FONT_EXTRA_INDEX
, Fdelq (slot
, extra
));
720 /* Font name parser and unparser */
722 static int parse_matrix (const char *);
723 static int font_expand_wildcards (Lisp_Object
*, int);
724 static int font_parse_name (char *, ptrdiff_t, Lisp_Object
);
726 /* An enumerator for each field of an XLFD font name. */
727 enum xlfd_field_index
746 /* An enumerator for mask bit corresponding to each XLFD field. */
749 XLFD_FOUNDRY_MASK
= 0x0001,
750 XLFD_FAMILY_MASK
= 0x0002,
751 XLFD_WEIGHT_MASK
= 0x0004,
752 XLFD_SLANT_MASK
= 0x0008,
753 XLFD_SWIDTH_MASK
= 0x0010,
754 XLFD_ADSTYLE_MASK
= 0x0020,
755 XLFD_PIXEL_MASK
= 0x0040,
756 XLFD_POINT_MASK
= 0x0080,
757 XLFD_RESX_MASK
= 0x0100,
758 XLFD_RESY_MASK
= 0x0200,
759 XLFD_SPACING_MASK
= 0x0400,
760 XLFD_AVGWIDTH_MASK
= 0x0800,
761 XLFD_REGISTRY_MASK
= 0x1000,
762 XLFD_ENCODING_MASK
= 0x2000
766 /* Parse P pointing to the pixel/point size field of the form
767 `[A B C D]' which specifies a transformation matrix:
773 by which all glyphs of the font are transformed. The spec says
774 that scalar value N for the pixel/point size is equivalent to:
775 A = N * resx/resy, B = C = 0, D = N.
777 Return the scalar value N if the form is valid. Otherwise return
781 parse_matrix (const char *p
)
787 for (i
= 0, p
++; i
< 4 && *p
&& *p
!= ']'; i
++)
790 matrix
[i
] = - strtod (p
+ 1, &end
);
792 matrix
[i
] = strtod (p
, &end
);
795 return (i
== 4 ? (int) matrix
[3] : -1);
798 /* Expand a wildcard field in FIELD (the first N fields are filled) to
799 multiple fields to fill in all 14 XLFD fields while restricting a
800 field position by its contents. */
803 font_expand_wildcards (Lisp_Object
*field
, int n
)
806 Lisp_Object tmp
[XLFD_LAST_INDEX
];
807 /* Array of information about where this element can go. Nth
808 element is for Nth element of FIELD. */
810 /* Minimum possible field. */
812 /* Maximum possible field. */
814 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
816 } range
[XLFD_LAST_INDEX
];
818 int range_from
, range_to
;
821 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
822 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
823 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
824 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
825 | XLFD_AVGWIDTH_MASK)
826 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
828 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
829 field. The value is shifted to left one bit by one in the
831 for (i
= 0, range_mask
= 0; i
<= 14 - n
; i
++)
832 range_mask
= (range_mask
<< 1) | 1;
834 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
835 position-based restriction for FIELD[I]. */
836 for (i
= 0, range_from
= 0, range_to
= 14 - n
; i
< n
;
837 i
++, range_from
++, range_to
++, range_mask
<<= 1)
839 Lisp_Object val
= field
[i
];
845 range
[i
].from
= range_from
;
846 range
[i
].to
= range_to
;
847 range
[i
].mask
= range_mask
;
851 /* The triplet FROM, TO, and MASK is a value-based
852 restriction for FIELD[I]. */
858 EMACS_INT numeric
= XINT (val
);
861 from
= to
= XLFD_ENCODING_INDEX
,
862 mask
= XLFD_ENCODING_MASK
;
863 else if (numeric
== 0)
864 from
= XLFD_PIXEL_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
865 mask
= XLFD_PIXEL_MASK
| XLFD_LARGENUM_MASK
;
866 else if (numeric
<= 48)
867 from
= to
= XLFD_PIXEL_INDEX
,
868 mask
= XLFD_PIXEL_MASK
;
870 from
= XLFD_POINT_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
871 mask
= XLFD_LARGENUM_MASK
;
873 else if (SBYTES (SYMBOL_NAME (val
)) == 0)
874 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ADSTYLE_INDEX
,
875 mask
= XLFD_NULL_MASK
;
877 from
= to
= XLFD_FOUNDRY_INDEX
, mask
= XLFD_FOUNDRY_MASK
;
880 Lisp_Object name
= SYMBOL_NAME (val
);
882 if (SDATA (name
)[SBYTES (name
) - 1] == '*')
883 from
= XLFD_REGISTRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
884 mask
= XLFD_REGENC_MASK
;
886 from
= to
= XLFD_ENCODING_INDEX
,
887 mask
= XLFD_ENCODING_MASK
;
889 else if (range_from
<= XLFD_WEIGHT_INDEX
890 && range_to
>= XLFD_WEIGHT_INDEX
891 && FONT_WEIGHT_NAME_NUMERIC (val
) >= 0)
892 from
= to
= XLFD_WEIGHT_INDEX
, mask
= XLFD_WEIGHT_MASK
;
893 else if (range_from
<= XLFD_SLANT_INDEX
894 && range_to
>= XLFD_SLANT_INDEX
895 && FONT_SLANT_NAME_NUMERIC (val
) >= 0)
896 from
= to
= XLFD_SLANT_INDEX
, mask
= XLFD_SLANT_MASK
;
897 else if (range_from
<= XLFD_SWIDTH_INDEX
898 && range_to
>= XLFD_SWIDTH_INDEX
899 && FONT_WIDTH_NAME_NUMERIC (val
) >= 0)
900 from
= to
= XLFD_SWIDTH_INDEX
, mask
= XLFD_SWIDTH_MASK
;
903 if (EQ (val
, Qc
) || EQ (val
, Qm
) || EQ (val
, Qp
) || EQ (val
, Qd
))
904 from
= to
= XLFD_SPACING_INDEX
, mask
= XLFD_SPACING_MASK
;
906 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
907 mask
= XLFD_SYMBOL_MASK
;
910 /* Merge position-based and value-based restrictions. */
912 while (from
< range_from
)
913 mask
&= ~(1 << from
++);
914 while (from
< 14 && ! (mask
& (1 << from
)))
916 while (to
> range_to
)
917 mask
&= ~(1 << to
--);
918 while (to
>= 0 && ! (mask
& (1 << to
)))
922 range
[i
].from
= from
;
924 range
[i
].mask
= mask
;
926 if (from
> range_from
|| to
< range_to
)
928 /* The range is narrowed by value-based restrictions.
929 Reflect it to the other fields. */
931 /* Following fields should be after FROM. */
933 /* Preceding fields should be before TO. */
934 for (j
= i
- 1, from
--, to
--; j
>= 0; j
--, from
--, to
--)
936 /* Check FROM for non-wildcard field. */
937 if (! NILP (tmp
[j
]) && range
[j
].from
< from
)
939 while (range
[j
].from
< from
)
940 range
[j
].mask
&= ~(1 << range
[j
].from
++);
941 while (from
< 14 && ! (range
[j
].mask
& (1 << from
)))
943 range
[j
].from
= from
;
946 from
= range
[j
].from
;
947 if (range
[j
].to
> to
)
949 while (range
[j
].to
> to
)
950 range
[j
].mask
&= ~(1 << range
[j
].to
--);
951 while (to
>= 0 && ! (range
[j
].mask
& (1 << to
)))
964 /* Decide all fields from restrictions in RANGE. */
965 for (i
= j
= 0; i
< n
; i
++)
967 if (j
< range
[i
].from
)
969 if (i
== 0 || ! NILP (tmp
[i
- 1]))
970 /* None of TMP[X] corresponds to Jth field. */
972 for (; j
< range
[i
].from
; j
++)
977 if (! NILP (tmp
[n
- 1]) && j
< XLFD_REGISTRY_INDEX
)
979 for (; j
< XLFD_LAST_INDEX
; j
++)
981 if (INTEGERP (field
[XLFD_ENCODING_INDEX
]))
982 field
[XLFD_ENCODING_INDEX
]
983 = Fintern (Fnumber_to_string (field
[XLFD_ENCODING_INDEX
]), Qnil
);
988 /* Parse NAME (null terminated) as XLFD and store information in FONT
989 (font-spec or font-entity). Size property of FONT is set as
991 specified XLFD fields FONT property
992 --------------------- -------------
993 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
994 POINT_SIZE and RESY calculated pixel size (Lisp integer)
995 POINT_SIZE POINT_SIZE/10 (Lisp float)
997 If NAME is successfully parsed, return 0. Otherwise return -1.
999 FONT is usually a font-spec, but when this function is called from
1000 X font backend driver, it is a font-entity. In that case, NAME is
1001 a fully specified XLFD. */
1004 font_parse_xlfd (char *name
, ptrdiff_t len
, Lisp_Object font
)
1007 char *f
[XLFD_LAST_INDEX
+ 1];
1011 if (len
> 255 || !len
)
1012 /* Maximum XLFD name length is 255. */
1014 /* Accept "*-.." as a fully specified XLFD. */
1015 if (name
[0] == '*' && (len
== 1 || name
[1] == '-'))
1016 i
= 1, f
[XLFD_FOUNDRY_INDEX
] = name
;
1019 for (p
= name
+ i
; *p
; p
++)
1023 if (i
== XLFD_LAST_INDEX
)
1028 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1029 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1031 if (i
== XLFD_LAST_INDEX
)
1033 /* Fully specified XLFD. */
1036 ASET (font
, FONT_FOUNDRY_INDEX
, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX
));
1037 ASET (font
, FONT_FAMILY_INDEX
, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX
));
1038 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1039 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1041 val
= INTERN_FIELD_SYM (i
);
1044 if ((n
= font_style_to_value (j
, INTERN_FIELD_SYM (i
), 0)) < 0)
1046 ASET (font
, j
, make_number (n
));
1049 ASET (font
, FONT_ADSTYLE_INDEX
, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX
));
1050 if (strcmp (f
[XLFD_REGISTRY_INDEX
], "*-*") == 0)
1051 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
1053 ASET (font
, FONT_REGISTRY_INDEX
,
1054 font_intern_prop (f
[XLFD_REGISTRY_INDEX
],
1055 f
[XLFD_LAST_INDEX
] - f
[XLFD_REGISTRY_INDEX
],
1057 p
= f
[XLFD_PIXEL_INDEX
];
1058 if (*p
== '[' && (pixel_size
= parse_matrix (p
)) >= 0)
1059 ASET (font
, FONT_SIZE_INDEX
, make_number (pixel_size
));
1062 val
= INTERN_FIELD (XLFD_PIXEL_INDEX
);
1064 ASET (font
, FONT_SIZE_INDEX
, val
);
1065 else if (FONT_ENTITY_P (font
))
1069 double point_size
= -1;
1071 eassert (FONT_SPEC_P (font
));
1072 p
= f
[XLFD_POINT_INDEX
];
1074 point_size
= parse_matrix (p
);
1075 else if (c_isdigit (*p
))
1076 point_size
= atoi (p
), point_size
/= 10;
1077 if (point_size
>= 0)
1078 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1082 val
= INTERN_FIELD (XLFD_RESY_INDEX
);
1083 if (! NILP (val
) && ! INTEGERP (val
))
1085 ASET (font
, FONT_DPI_INDEX
, val
);
1086 val
= INTERN_FIELD (XLFD_SPACING_INDEX
);
1089 val
= font_prop_validate_spacing (QCspacing
, val
);
1090 if (! INTEGERP (val
))
1092 ASET (font
, FONT_SPACING_INDEX
, val
);
1094 p
= f
[XLFD_AVGWIDTH_INDEX
];
1097 val
= font_intern_prop (p
, f
[XLFD_REGISTRY_INDEX
] - 1 - p
, 0);
1098 if (! NILP (val
) && ! INTEGERP (val
))
1100 ASET (font
, FONT_AVGWIDTH_INDEX
, val
);
1104 bool wild_card_found
= 0;
1105 Lisp_Object prop
[XLFD_LAST_INDEX
];
1107 if (FONT_ENTITY_P (font
))
1109 for (j
= 0; j
< i
; j
++)
1113 if (f
[j
][1] && f
[j
][1] != '-')
1116 wild_card_found
= 1;
1119 prop
[j
] = INTERN_FIELD (j
);
1121 prop
[j
] = font_intern_prop (f
[j
], f
[i
] - f
[j
], 0);
1123 if (! wild_card_found
)
1125 if (font_expand_wildcards (prop
, i
) < 0)
1128 ASET (font
, FONT_FOUNDRY_INDEX
, prop
[XLFD_FOUNDRY_INDEX
]);
1129 ASET (font
, FONT_FAMILY_INDEX
, prop
[XLFD_FAMILY_INDEX
]);
1130 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1131 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1132 if (! NILP (prop
[i
]))
1134 if ((n
= font_style_to_value (j
, prop
[i
], 1)) < 0)
1136 ASET (font
, j
, make_number (n
));
1138 ASET (font
, FONT_ADSTYLE_INDEX
, prop
[XLFD_ADSTYLE_INDEX
]);
1139 val
= prop
[XLFD_REGISTRY_INDEX
];
1142 val
= prop
[XLFD_ENCODING_INDEX
];
1144 val
= concat2 (build_string ("*-"), SYMBOL_NAME (val
));
1146 else if (NILP (prop
[XLFD_ENCODING_INDEX
]))
1147 val
= concat2 (SYMBOL_NAME (val
), build_string ("-*"));
1149 val
= concat3 (SYMBOL_NAME (val
), build_string ("-"),
1150 SYMBOL_NAME (prop
[XLFD_ENCODING_INDEX
]));
1152 ASET (font
, FONT_REGISTRY_INDEX
, Fintern (val
, Qnil
));
1154 if (INTEGERP (prop
[XLFD_PIXEL_INDEX
]))
1155 ASET (font
, FONT_SIZE_INDEX
, prop
[XLFD_PIXEL_INDEX
]);
1156 else if (INTEGERP (prop
[XLFD_POINT_INDEX
]))
1158 double point_size
= XINT (prop
[XLFD_POINT_INDEX
]);
1160 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
/ 10));
1163 if (INTEGERP (prop
[XLFD_RESX_INDEX
]))
1164 ASET (font
, FONT_DPI_INDEX
, prop
[XLFD_RESY_INDEX
]);
1165 if (! NILP (prop
[XLFD_SPACING_INDEX
]))
1167 val
= font_prop_validate_spacing (QCspacing
,
1168 prop
[XLFD_SPACING_INDEX
]);
1169 if (! INTEGERP (val
))
1171 ASET (font
, FONT_SPACING_INDEX
, val
);
1173 if (INTEGERP (prop
[XLFD_AVGWIDTH_INDEX
]))
1174 ASET (font
, FONT_AVGWIDTH_INDEX
, prop
[XLFD_AVGWIDTH_INDEX
]);
1180 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1181 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1182 0, use PIXEL_SIZE instead. */
1185 font_unparse_xlfd (Lisp_Object font
, int pixel_size
, char *name
, int nbytes
)
1188 const char *f
[XLFD_REGISTRY_INDEX
+ 1];
1192 eassert (FONTP (font
));
1194 for (i
= FONT_FOUNDRY_INDEX
, j
= XLFD_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
;
1197 if (i
== FONT_ADSTYLE_INDEX
)
1198 j
= XLFD_ADSTYLE_INDEX
;
1199 else if (i
== FONT_REGISTRY_INDEX
)
1200 j
= XLFD_REGISTRY_INDEX
;
1201 val
= AREF (font
, i
);
1204 if (j
== XLFD_REGISTRY_INDEX
)
1212 val
= SYMBOL_NAME (val
);
1213 if (j
== XLFD_REGISTRY_INDEX
1214 && ! strchr (SSDATA (val
), '-'))
1216 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1217 ptrdiff_t alloc
= SBYTES (val
) + 4;
1218 if (nbytes
<= alloc
)
1220 f
[j
] = p
= alloca (alloc
);
1221 sprintf (p
, "%s%s-*", SDATA (val
),
1222 "*" + (SDATA (val
)[SBYTES (val
) - 1] == '*'));
1225 f
[j
] = SSDATA (val
);
1229 for (i
= FONT_WEIGHT_INDEX
, j
= XLFD_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
;
1232 val
= font_style_symbolic (font
, i
, 0);
1237 val
= SYMBOL_NAME (val
);
1238 f
[j
] = SSDATA (val
);
1242 val
= AREF (font
, FONT_SIZE_INDEX
);
1243 eassert (NUMBERP (val
) || NILP (val
));
1246 EMACS_INT v
= XINT (val
);
1251 f
[XLFD_PIXEL_INDEX
] = p
=
1252 alloca (sizeof "-*" + INT_STRLEN_BOUND (EMACS_INT
));
1253 sprintf (p
, "%"pI
"d-*", v
);
1256 f
[XLFD_PIXEL_INDEX
] = "*-*";
1258 else if (FLOATP (val
))
1260 double v
= XFLOAT_DATA (val
) * 10;
1261 f
[XLFD_PIXEL_INDEX
] = p
= alloca (sizeof "*-" + 1 + DBL_MAX_10_EXP
+ 1);
1262 sprintf (p
, "*-%.0f", v
);
1265 f
[XLFD_PIXEL_INDEX
] = "*-*";
1267 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1269 EMACS_INT v
= XINT (AREF (font
, FONT_DPI_INDEX
));
1270 f
[XLFD_RESX_INDEX
] = p
=
1271 alloca (sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT
));
1272 sprintf (p
, "%"pI
"d-%"pI
"d", v
, v
);
1275 f
[XLFD_RESX_INDEX
] = "*-*";
1276 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1278 EMACS_INT spacing
= XINT (AREF (font
, FONT_SPACING_INDEX
));
1280 f
[XLFD_SPACING_INDEX
] = (spacing
<= FONT_SPACING_PROPORTIONAL
? "p"
1281 : spacing
<= FONT_SPACING_DUAL
? "d"
1282 : spacing
<= FONT_SPACING_MONO
? "m"
1286 f
[XLFD_SPACING_INDEX
] = "*";
1287 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1289 f
[XLFD_AVGWIDTH_INDEX
] = p
= alloca (INT_BUFSIZE_BOUND (EMACS_INT
));
1290 sprintf (p
, "%"pI
"d", XINT (AREF (font
, FONT_AVGWIDTH_INDEX
)));
1293 f
[XLFD_AVGWIDTH_INDEX
] = "*";
1294 len
= snprintf (name
, nbytes
, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1295 f
[XLFD_FOUNDRY_INDEX
], f
[XLFD_FAMILY_INDEX
],
1296 f
[XLFD_WEIGHT_INDEX
], f
[XLFD_SLANT_INDEX
],
1297 f
[XLFD_SWIDTH_INDEX
], f
[XLFD_ADSTYLE_INDEX
],
1298 f
[XLFD_PIXEL_INDEX
], f
[XLFD_RESX_INDEX
],
1299 f
[XLFD_SPACING_INDEX
], f
[XLFD_AVGWIDTH_INDEX
],
1300 f
[XLFD_REGISTRY_INDEX
]);
1301 return len
< nbytes
? len
: -1;
1304 /* Parse NAME (null terminated) and store information in FONT
1305 (font-spec or font-entity). NAME is supplied in either the
1306 Fontconfig or GTK font name format. If NAME is successfully
1307 parsed, return 0. Otherwise return -1.
1309 The fontconfig format is
1311 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1315 FAMILY [PROPS...] [SIZE]
1317 This function tries to guess which format it is. */
1320 font_parse_fcname (char *name
, ptrdiff_t len
, Lisp_Object font
)
1323 char *size_beg
= NULL
, *size_end
= NULL
;
1324 char *props_beg
= NULL
, *family_end
= NULL
;
1329 for (p
= name
; *p
; p
++)
1331 if (*p
== '\\' && p
[1])
1335 props_beg
= family_end
= p
;
1340 bool decimal
= 0, size_found
= 1;
1341 for (q
= p
+ 1; *q
&& *q
!= ':'; q
++)
1342 if (! c_isdigit (*q
))
1344 if (*q
!= '.' || decimal
)
1363 Lisp_Object extra_props
= Qnil
;
1365 /* A fontconfig name with size and/or property data. */
1366 if (family_end
> name
)
1369 family
= font_intern_prop (name
, family_end
- name
, 1);
1370 ASET (font
, FONT_FAMILY_INDEX
, family
);
1374 double point_size
= strtod (size_beg
, &size_end
);
1375 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1376 if (*size_end
== ':' && size_end
[1])
1377 props_beg
= size_end
;
1381 /* Now parse ":KEY=VAL" patterns. */
1384 for (p
= props_beg
; *p
; p
= q
)
1386 for (q
= p
+ 1; *q
&& *q
!= '=' && *q
!= ':'; q
++);
1389 /* Must be an enumerated value. */
1393 val
= font_intern_prop (p
, q
- p
, 1);
1395 #define PROP_MATCH(STR) (word_len == strlen (STR) \
1396 && memcmp (p, STR, strlen (STR)) == 0)
1398 if (PROP_MATCH ("light")
1399 || PROP_MATCH ("medium")
1400 || PROP_MATCH ("demibold")
1401 || PROP_MATCH ("bold")
1402 || PROP_MATCH ("black"))
1403 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, val
);
1404 else if (PROP_MATCH ("roman")
1405 || PROP_MATCH ("italic")
1406 || PROP_MATCH ("oblique"))
1407 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, val
);
1408 else if (PROP_MATCH ("charcell"))
1409 ASET (font
, FONT_SPACING_INDEX
,
1410 make_number (FONT_SPACING_CHARCELL
));
1411 else if (PROP_MATCH ("mono"))
1412 ASET (font
, FONT_SPACING_INDEX
,
1413 make_number (FONT_SPACING_MONO
));
1414 else if (PROP_MATCH ("proportional"))
1415 ASET (font
, FONT_SPACING_INDEX
,
1416 make_number (FONT_SPACING_PROPORTIONAL
));
1425 if (q
- p
== 10 && memcmp (p
+ 1, "pixelsize", 9) == 0)
1426 prop
= FONT_SIZE_INDEX
;
1429 key
= font_intern_prop (p
, q
- p
, 1);
1430 prop
= get_font_prop_index (key
);
1434 for (q
= p
; *q
&& *q
!= ':'; q
++);
1435 val
= font_intern_prop (p
, q
- p
, 0);
1437 if (prop
>= FONT_FOUNDRY_INDEX
1438 && prop
< FONT_EXTRA_INDEX
)
1439 ASET (font
, prop
, font_prop_validate (prop
, Qnil
, val
));
1442 extra_props
= nconc2 (extra_props
,
1443 Fcons (Fcons (key
, val
), Qnil
));
1450 if (! NILP (extra_props
))
1452 struct font_driver_list
*driver_list
= font_driver_list
;
1453 for ( ; driver_list
; driver_list
= driver_list
->next
)
1454 if (driver_list
->driver
->filter_properties
)
1455 (*driver_list
->driver
->filter_properties
) (font
, extra_props
);
1461 /* Either a fontconfig-style name with no size and property
1462 data, or a GTK-style name. */
1463 Lisp_Object weight
= Qnil
, slant
= Qnil
;
1464 Lisp_Object width
= Qnil
, size
= Qnil
;
1468 /* Scan backwards from the end, looking for a size. */
1469 for (p
= name
+ len
- 1; p
>= name
; p
--)
1470 if (!c_isdigit (*p
))
1473 if ((p
< name
+ len
- 1) && ((p
+ 1 == name
) || *p
== ' '))
1474 /* Found a font size. */
1475 size
= make_float (strtod (p
+ 1, NULL
));
1479 /* Now P points to the termination of the string, sans size.
1480 Scan backwards, looking for font properties. */
1481 for (; p
> name
; p
= q
)
1483 for (q
= p
- 1; q
>= name
; q
--)
1485 if (q
> name
&& *(q
-1) == '\\')
1486 --q
; /* Skip quoting backslashes. */
1492 word_len
= p
- word_start
;
1494 #define PROP_MATCH(STR) \
1495 (word_len == strlen (STR) \
1496 && memcmp (word_start, STR, strlen (STR)) == 0)
1497 #define PROP_SAVE(VAR, STR) \
1498 (VAR = NILP (VAR) ? font_intern_prop (STR, strlen (STR), 1) : VAR)
1500 if (PROP_MATCH ("Ultra-Light"))
1501 PROP_SAVE (weight
, "ultra-light");
1502 else if (PROP_MATCH ("Light"))
1503 PROP_SAVE (weight
, "light");
1504 else if (PROP_MATCH ("Book"))
1505 PROP_SAVE (weight
, "book");
1506 else if (PROP_MATCH ("Medium"))
1507 PROP_SAVE (weight
, "medium");
1508 else if (PROP_MATCH ("Semi-Bold"))
1509 PROP_SAVE (weight
, "semi-bold");
1510 else if (PROP_MATCH ("Bold"))
1511 PROP_SAVE (weight
, "bold");
1512 else if (PROP_MATCH ("Italic"))
1513 PROP_SAVE (slant
, "italic");
1514 else if (PROP_MATCH ("Oblique"))
1515 PROP_SAVE (slant
, "oblique");
1516 else if (PROP_MATCH ("Semi-Condensed"))
1517 PROP_SAVE (width
, "semi-condensed");
1518 else if (PROP_MATCH ("Condensed"))
1519 PROP_SAVE (width
, "condensed");
1520 /* An unknown word must be part of the font name. */
1531 ASET (font
, FONT_FAMILY_INDEX
,
1532 font_intern_prop (name
, family_end
- name
, 1));
1534 ASET (font
, FONT_SIZE_INDEX
, size
);
1536 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, weight
);
1538 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, slant
);
1540 FONT_SET_STYLE (font
, FONT_WIDTH_INDEX
, width
);
1546 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1547 NAME (NBYTES length), and return the name length. If
1548 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1551 font_unparse_fcname (Lisp_Object font
, int pixel_size
, char *name
, int nbytes
)
1553 Lisp_Object family
, foundry
;
1559 Lisp_Object styles
[3];
1560 const char *style_names
[3] = { "weight", "slant", "width" };
1562 family
= AREF (font
, FONT_FAMILY_INDEX
);
1563 if (! NILP (family
))
1565 if (SYMBOLP (family
))
1566 family
= SYMBOL_NAME (family
);
1571 val
= AREF (font
, FONT_SIZE_INDEX
);
1574 if (XINT (val
) != 0)
1575 pixel_size
= XINT (val
);
1580 eassert (FLOATP (val
));
1582 point_size
= (int) XFLOAT_DATA (val
);
1585 foundry
= AREF (font
, FONT_FOUNDRY_INDEX
);
1586 if (! NILP (foundry
))
1588 if (SYMBOLP (foundry
))
1589 foundry
= SYMBOL_NAME (foundry
);
1594 for (i
= 0; i
< 3; i
++)
1595 styles
[i
] = font_style_symbolic (font
, FONT_WEIGHT_INDEX
+ i
, 0);
1598 lim
= name
+ nbytes
;
1599 if (! NILP (family
))
1601 int len
= snprintf (p
, lim
- p
, "%s", SSDATA (family
));
1602 if (! (0 <= len
&& len
< lim
- p
))
1608 int len
= snprintf (p
, lim
- p
, "-%d" + (p
== name
), point_size
);
1609 if (! (0 <= len
&& len
< lim
- p
))
1613 else if (pixel_size
> 0)
1615 int len
= snprintf (p
, lim
- p
, ":pixelsize=%d", pixel_size
);
1616 if (! (0 <= len
&& len
< lim
- p
))
1620 if (! NILP (AREF (font
, FONT_FOUNDRY_INDEX
)))
1622 int len
= snprintf (p
, lim
- p
, ":foundry=%s",
1623 SSDATA (SYMBOL_NAME (AREF (font
,
1624 FONT_FOUNDRY_INDEX
))));
1625 if (! (0 <= len
&& len
< lim
- p
))
1629 for (i
= 0; i
< 3; i
++)
1630 if (! NILP (styles
[i
]))
1632 int len
= snprintf (p
, lim
- p
, ":%s=%s", style_names
[i
],
1633 SSDATA (SYMBOL_NAME (styles
[i
])));
1634 if (! (0 <= len
&& len
< lim
- p
))
1639 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1641 int len
= snprintf (p
, lim
- p
, ":dpi=%"pI
"d",
1642 XINT (AREF (font
, FONT_DPI_INDEX
)));
1643 if (! (0 <= len
&& len
< lim
- p
))
1648 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1650 int len
= snprintf (p
, lim
- p
, ":spacing=%"pI
"d",
1651 XINT (AREF (font
, FONT_SPACING_INDEX
)));
1652 if (! (0 <= len
&& len
< lim
- p
))
1657 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1659 int len
= snprintf (p
, lim
- p
,
1660 (XINT (AREF (font
, FONT_AVGWIDTH_INDEX
)) == 0
1662 : ":scalable=false"));
1663 if (! (0 <= len
&& len
< lim
- p
))
1671 /* Parse NAME (null terminated) and store information in FONT
1672 (font-spec or font-entity). If NAME is successfully parsed, return
1673 0. Otherwise return -1. */
1676 font_parse_name (char *name
, ptrdiff_t namelen
, Lisp_Object font
)
1678 if (name
[0] == '-' || strchr (name
, '*') || strchr (name
, '?'))
1679 return font_parse_xlfd (name
, namelen
, font
);
1680 return font_parse_fcname (name
, namelen
, font
);
1684 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1685 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1689 font_parse_family_registry (Lisp_Object family
, Lisp_Object registry
, Lisp_Object font_spec
)
1695 && NILP (AREF (font_spec
, FONT_FAMILY_INDEX
)))
1697 CHECK_STRING (family
);
1698 len
= SBYTES (family
);
1699 p0
= SSDATA (family
);
1700 p1
= strchr (p0
, '-');
1703 if ((*p0
!= '*' && p1
- p0
> 0)
1704 && NILP (AREF (font_spec
, FONT_FOUNDRY_INDEX
)))
1705 Ffont_put (font_spec
, QCfoundry
, font_intern_prop (p0
, p1
- p0
, 1));
1708 Ffont_put (font_spec
, QCfamily
, font_intern_prop (p1
, len
, 1));
1711 ASET (font_spec
, FONT_FAMILY_INDEX
, Fintern (family
, Qnil
));
1713 if (! NILP (registry
))
1715 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1716 CHECK_STRING (registry
);
1717 len
= SBYTES (registry
);
1718 p0
= SSDATA (registry
);
1719 p1
= strchr (p0
, '-');
1722 if (SDATA (registry
)[len
- 1] == '*')
1723 registry
= concat2 (registry
, build_string ("-*"));
1725 registry
= concat2 (registry
, build_string ("*-*"));
1727 registry
= Fdowncase (registry
);
1728 ASET (font_spec
, FONT_REGISTRY_INDEX
, Fintern (registry
, Qnil
));
1733 /* This part (through the next ^L) is still experimental and not
1734 tested much. We may drastically change codes. */
1740 #define LGSTRING_HEADER_SIZE 6
1741 #define LGSTRING_GLYPH_SIZE 8
1744 check_gstring (Lisp_Object gstring
)
1750 CHECK_VECTOR (gstring
);
1751 val
= AREF (gstring
, 0);
1753 if (ASIZE (val
) < LGSTRING_HEADER_SIZE
)
1755 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring
));
1756 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
)))
1757 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
));
1758 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
)))
1759 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
));
1760 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
)))
1761 CHECK_NATNUM (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
));
1762 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1763 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1764 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1765 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1767 for (i
= 0; i
< LGSTRING_GLYPH_LEN (gstring
); i
++)
1769 val
= LGSTRING_GLYPH (gstring
, i
);
1771 if (ASIZE (val
) < LGSTRING_GLYPH_SIZE
)
1773 if (NILP (AREF (val
, LGLYPH_IX_CHAR
)))
1775 CHECK_NATNUM (AREF (val
, LGLYPH_IX_FROM
));
1776 CHECK_NATNUM (AREF (val
, LGLYPH_IX_TO
));
1777 CHECK_CHARACTER (AREF (val
, LGLYPH_IX_CHAR
));
1778 if (!NILP (AREF (val
, LGLYPH_IX_CODE
)))
1779 CHECK_NATNUM (AREF (val
, LGLYPH_IX_CODE
));
1780 if (!NILP (AREF (val
, LGLYPH_IX_WIDTH
)))
1781 CHECK_NATNUM (AREF (val
, LGLYPH_IX_WIDTH
));
1782 if (!NILP (AREF (val
, LGLYPH_IX_ADJUSTMENT
)))
1784 val
= AREF (val
, LGLYPH_IX_ADJUSTMENT
);
1786 if (ASIZE (val
) < 3)
1788 for (j
= 0; j
< 3; j
++)
1789 CHECK_NUMBER (AREF (val
, j
));
1794 error ("Invalid glyph-string format");
1799 check_otf_features (Lisp_Object otf_features
)
1803 CHECK_CONS (otf_features
);
1804 CHECK_SYMBOL (XCAR (otf_features
));
1805 otf_features
= XCDR (otf_features
);
1806 CHECK_CONS (otf_features
);
1807 CHECK_SYMBOL (XCAR (otf_features
));
1808 otf_features
= XCDR (otf_features
);
1809 for (val
= Fcar (otf_features
); CONSP (val
); val
= XCDR (val
))
1811 CHECK_SYMBOL (XCAR (val
));
1812 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1813 error ("Invalid OTF GSUB feature: %s",
1814 SDATA (SYMBOL_NAME (XCAR (val
))));
1816 otf_features
= XCDR (otf_features
);
1817 for (val
= Fcar (otf_features
); CONSP (val
); val
= XCDR (val
))
1819 CHECK_SYMBOL (XCAR (val
));
1820 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1821 error ("Invalid OTF GPOS feature: %s",
1822 SDATA (SYMBOL_NAME (XCAR (val
))));
1829 Lisp_Object otf_list
;
1832 otf_tag_symbol (OTF_Tag tag
)
1836 OTF_tag_name (tag
, name
);
1837 return Fintern (make_unibyte_string (name
, 4), Qnil
);
1841 otf_open (Lisp_Object file
)
1843 Lisp_Object val
= Fassoc (file
, otf_list
);
1847 otf
= XSAVE_VALUE (XCDR (val
))->pointer
;
1850 otf
= STRINGP (file
) ? OTF_open (SSDATA (file
)) : NULL
;
1851 val
= make_save_value (otf
, 0);
1852 otf_list
= Fcons (Fcons (file
, val
), otf_list
);
1858 /* Return a list describing which scripts/languages FONT supports by
1859 which GSUB/GPOS features of OpenType tables. See the comment of
1860 (struct font_driver).otf_capability. */
1863 font_otf_capability (struct font
*font
)
1866 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
1869 otf
= otf_open (font
->props
[FONT_FILE_INDEX
]);
1872 for (i
= 0; i
< 2; i
++)
1874 OTF_GSUB_GPOS
*gsub_gpos
;
1875 Lisp_Object script_list
= Qnil
;
1878 if (OTF_get_features (otf
, i
== 0) < 0)
1880 gsub_gpos
= i
== 0 ? otf
->gsub
: otf
->gpos
;
1881 for (j
= gsub_gpos
->ScriptList
.ScriptCount
- 1; j
>= 0; j
--)
1883 OTF_Script
*script
= gsub_gpos
->ScriptList
.Script
+ j
;
1884 Lisp_Object langsys_list
= Qnil
;
1885 Lisp_Object script_tag
= otf_tag_symbol (script
->ScriptTag
);
1888 for (k
= script
->LangSysCount
; k
>= 0; k
--)
1890 OTF_LangSys
*langsys
;
1891 Lisp_Object feature_list
= Qnil
;
1892 Lisp_Object langsys_tag
;
1895 if (k
== script
->LangSysCount
)
1897 langsys
= &script
->DefaultLangSys
;
1902 langsys
= script
->LangSys
+ k
;
1904 = otf_tag_symbol (script
->LangSysRecord
[k
].LangSysTag
);
1906 for (l
= langsys
->FeatureCount
- 1; l
>= 0; l
--)
1908 OTF_Feature
*feature
1909 = gsub_gpos
->FeatureList
.Feature
+ langsys
->FeatureIndex
[l
];
1910 Lisp_Object feature_tag
1911 = otf_tag_symbol (feature
->FeatureTag
);
1913 feature_list
= Fcons (feature_tag
, feature_list
);
1915 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
1918 script_list
= Fcons (Fcons (script_tag
, langsys_list
),
1923 XSETCAR (capability
, script_list
);
1925 XSETCDR (capability
, script_list
);
1931 /* Parse OTF features in SPEC and write a proper features spec string
1932 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1933 assured that the sufficient memory has already allocated for
1937 generate_otf_features (Lisp_Object spec
, char *features
)
1945 for (asterisk
= 0; CONSP (spec
); spec
= XCDR (spec
))
1951 if (SREF (SYMBOL_NAME (val
), 0) == '*')
1956 else if (! asterisk
)
1958 val
= SYMBOL_NAME (val
);
1959 p
+= esprintf (p
, "%s", SDATA (val
));
1963 val
= SYMBOL_NAME (val
);
1964 p
+= esprintf (p
, "~%s", SDATA (val
));
1968 error ("OTF spec too long");
1972 font_otf_DeviceTable (OTF_DeviceTable
*device_table
)
1974 int len
= device_table
->StartSize
- device_table
->EndSize
+ 1;
1976 return Fcons (make_number (len
),
1977 make_unibyte_string (device_table
->DeltaValue
, len
));
1981 font_otf_ValueRecord (int value_format
, OTF_ValueRecord
*value_record
)
1983 Lisp_Object val
= Fmake_vector (make_number (8), Qnil
);
1985 if (value_format
& OTF_XPlacement
)
1986 ASET (val
, 0, make_number (value_record
->XPlacement
));
1987 if (value_format
& OTF_YPlacement
)
1988 ASET (val
, 1, make_number (value_record
->YPlacement
));
1989 if (value_format
& OTF_XAdvance
)
1990 ASET (val
, 2, make_number (value_record
->XAdvance
));
1991 if (value_format
& OTF_YAdvance
)
1992 ASET (val
, 3, make_number (value_record
->YAdvance
));
1993 if (value_format
& OTF_XPlaDevice
)
1994 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XPlaDevice
));
1995 if (value_format
& OTF_YPlaDevice
)
1996 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YPlaDevice
));
1997 if (value_format
& OTF_XAdvDevice
)
1998 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XAdvDevice
));
1999 if (value_format
& OTF_YAdvDevice
)
2000 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YAdvDevice
));
2005 font_otf_Anchor (OTF_Anchor
*anchor
)
2009 val
= Fmake_vector (make_number (anchor
->AnchorFormat
+ 1), Qnil
);
2010 ASET (val
, 0, make_number (anchor
->XCoordinate
));
2011 ASET (val
, 1, make_number (anchor
->YCoordinate
));
2012 if (anchor
->AnchorFormat
== 2)
2013 ASET (val
, 2, make_number (anchor
->f
.f1
.AnchorPoint
));
2016 ASET (val
, 3, font_otf_DeviceTable (&anchor
->f
.f2
.XDeviceTable
));
2017 ASET (val
, 4, font_otf_DeviceTable (&anchor
->f
.f2
.YDeviceTable
));
2021 #endif /* HAVE_LIBOTF */
2027 static unsigned font_score (Lisp_Object
, Lisp_Object
*);
2028 static int font_compare (const void *, const void *);
2029 static Lisp_Object
font_sort_entities (Lisp_Object
, Lisp_Object
,
2033 font_rescale_ratio (Lisp_Object font_entity
)
2035 Lisp_Object tail
, elt
;
2036 Lisp_Object name
= Qnil
;
2038 for (tail
= Vface_font_rescale_alist
; CONSP (tail
); tail
= XCDR (tail
))
2041 if (FLOATP (XCDR (elt
)))
2043 if (STRINGP (XCAR (elt
)))
2046 name
= Ffont_xlfd_name (font_entity
, Qnil
);
2047 if (fast_string_match_ignore_case (XCAR (elt
), name
) >= 0)
2048 return XFLOAT_DATA (XCDR (elt
));
2050 else if (FONT_SPEC_P (XCAR (elt
)))
2052 if (font_match_p (XCAR (elt
), font_entity
))
2053 return XFLOAT_DATA (XCDR (elt
));
2060 /* We sort fonts by scoring each of them against a specified
2061 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2062 the value is, the closer the font is to the font-spec.
2064 The lowest 2 bits of the score are used for driver type. The font
2065 available by the most preferred font driver is 0.
2067 The 4 7-bit fields in the higher 28 bits are used for numeric properties
2068 WEIGHT, SLANT, WIDTH, and SIZE. */
2070 /* How many bits to shift to store the difference value of each font
2071 property in a score. Note that floats for FONT_TYPE_INDEX and
2072 FONT_REGISTRY_INDEX are not used. */
2073 static int sort_shift_bits
[FONT_SIZE_INDEX
+ 1];
2075 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2076 The return value indicates how different ENTITY is compared with
2080 font_score (Lisp_Object entity
, Lisp_Object
*spec_prop
)
2085 /* Score three style numeric fields. Maximum difference is 127. */
2086 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
; i
++)
2087 if (! NILP (spec_prop
[i
]) && ! EQ (AREF (entity
, i
), spec_prop
[i
]))
2089 EMACS_INT diff
= ((XINT (AREF (entity
, i
)) >> 8)
2090 - (XINT (spec_prop
[i
]) >> 8));
2093 score
|= min (diff
, 127) << sort_shift_bits
[i
];
2096 /* Score the size. Maximum difference is 127. */
2097 i
= FONT_SIZE_INDEX
;
2098 if (! NILP (spec_prop
[FONT_SIZE_INDEX
])
2099 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2101 /* We use the higher 6-bit for the actual size difference. The
2102 lowest bit is set if the DPI is different. */
2104 EMACS_INT pixel_size
= XINT (spec_prop
[FONT_SIZE_INDEX
]);
2106 if (CONSP (Vface_font_rescale_alist
))
2107 pixel_size
*= font_rescale_ratio (entity
);
2108 diff
= pixel_size
- XINT (AREF (entity
, FONT_SIZE_INDEX
));
2112 if (! NILP (spec_prop
[FONT_DPI_INDEX
])
2113 && ! EQ (spec_prop
[FONT_DPI_INDEX
], AREF (entity
, FONT_DPI_INDEX
)))
2115 if (! NILP (spec_prop
[FONT_AVGWIDTH_INDEX
])
2116 && ! EQ (spec_prop
[FONT_AVGWIDTH_INDEX
], AREF (entity
, FONT_AVGWIDTH_INDEX
)))
2118 score
|= min (diff
, 127) << sort_shift_bits
[FONT_SIZE_INDEX
];
2125 /* Concatenate all elements of LIST into one vector. LIST is a list
2126 of font-entity vectors. */
2129 font_vconcat_entity_vectors (Lisp_Object list
)
2131 int nargs
= XINT (Flength (list
));
2132 Lisp_Object
*args
= alloca (word_size
* nargs
);
2135 for (i
= 0; i
< nargs
; i
++, list
= XCDR (list
))
2136 args
[i
] = XCAR (list
);
2137 return Fvconcat (nargs
, args
);
2141 /* The structure for elements being sorted by qsort. */
2142 struct font_sort_data
2145 int font_driver_preference
;
2150 /* The comparison function for qsort. */
2153 font_compare (const void *d1
, const void *d2
)
2155 const struct font_sort_data
*data1
= d1
;
2156 const struct font_sort_data
*data2
= d2
;
2158 if (data1
->score
< data2
->score
)
2160 else if (data1
->score
> data2
->score
)
2162 return (data1
->font_driver_preference
- data2
->font_driver_preference
);
2166 /* Sort each font-entity vector in LIST by closeness to font-spec PREFER.
2167 If PREFER specifies a point-size, calculate the corresponding
2168 pixel-size from QCdpi property of PREFER or from the Y-resolution
2169 of FRAME before sorting.
2171 If BEST-ONLY is nonzero, return the best matching entity (that
2172 supports the character BEST-ONLY if BEST-ONLY is positive, or any
2173 if BEST-ONLY is negative). Otherwise, return the sorted result as
2174 a single vector of font-entities.
2176 This function does no optimization for the case that the total
2177 number of elements is 1. The caller should avoid calling this in
2181 font_sort_entities (Lisp_Object list
, Lisp_Object prefer
, Lisp_Object frame
, int best_only
)
2183 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2185 struct font_sort_data
*data
;
2186 unsigned best_score
;
2187 Lisp_Object best_entity
;
2188 struct frame
*f
= XFRAME (frame
);
2189 Lisp_Object tail
, vec
IF_LINT (= Qnil
);
2192 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_AVGWIDTH_INDEX
; i
++)
2193 prefer_prop
[i
] = AREF (prefer
, i
);
2194 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2195 prefer_prop
[FONT_SIZE_INDEX
]
2196 = make_number (font_pixel_size (XFRAME (frame
), prefer
));
2198 if (NILP (XCDR (list
)))
2200 /* What we have to take care of is this single vector. */
2202 maxlen
= ASIZE (vec
);
2206 /* We don't have to perform sort, so there's no need of creating
2207 a single vector. But, we must find the length of the longest
2210 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
2211 if (maxlen
< ASIZE (XCAR (tail
)))
2212 maxlen
= ASIZE (XCAR (tail
));
2216 /* We have to create a single vector to sort it. */
2217 vec
= font_vconcat_entity_vectors (list
);
2218 maxlen
= ASIZE (vec
);
2221 data
= SAFE_ALLOCA (maxlen
* sizeof *data
);
2222 best_score
= 0xFFFFFFFF;
2225 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
2227 int font_driver_preference
= 0;
2228 Lisp_Object current_font_driver
;
2234 /* We are sure that the length of VEC > 0. */
2235 current_font_driver
= AREF (AREF (vec
, 0), FONT_TYPE_INDEX
);
2236 /* Score the elements. */
2237 for (i
= 0; i
< len
; i
++)
2239 data
[i
].entity
= AREF (vec
, i
);
2241 = ((best_only
<= 0 || font_has_char (f
, data
[i
].entity
, best_only
)
2243 ? font_score (data
[i
].entity
, prefer_prop
)
2245 if (best_only
&& best_score
> data
[i
].score
)
2247 best_score
= data
[i
].score
;
2248 best_entity
= data
[i
].entity
;
2249 if (best_score
== 0)
2252 if (! EQ (current_font_driver
, AREF (AREF (vec
, i
), FONT_TYPE_INDEX
)))
2254 current_font_driver
= AREF (AREF (vec
, i
), FONT_TYPE_INDEX
);
2255 font_driver_preference
++;
2257 data
[i
].font_driver_preference
= font_driver_preference
;
2260 /* Sort if necessary. */
2263 qsort (data
, len
, sizeof *data
, font_compare
);
2264 for (i
= 0; i
< len
; i
++)
2265 ASET (vec
, i
, data
[i
].entity
);
2274 FONT_ADD_LOG ("sort-by", prefer
, vec
);
2279 /* API of Font Service Layer. */
2281 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2282 sort_shift_bits. Finternal_set_font_selection_order calls this
2283 function with font_sort_order after setting up it. */
2286 font_update_sort_order (int *order
)
2290 for (i
= 0, shift_bits
= 23; i
< 4; i
++, shift_bits
-= 7)
2292 int xlfd_idx
= order
[i
];
2294 if (xlfd_idx
== XLFD_WEIGHT_INDEX
)
2295 sort_shift_bits
[FONT_WEIGHT_INDEX
] = shift_bits
;
2296 else if (xlfd_idx
== XLFD_SLANT_INDEX
)
2297 sort_shift_bits
[FONT_SLANT_INDEX
] = shift_bits
;
2298 else if (xlfd_idx
== XLFD_SWIDTH_INDEX
)
2299 sort_shift_bits
[FONT_WIDTH_INDEX
] = shift_bits
;
2301 sort_shift_bits
[FONT_SIZE_INDEX
] = shift_bits
;
2306 font_check_otf_features (Lisp_Object script
, Lisp_Object langsys
,
2307 Lisp_Object features
, Lisp_Object table
)
2312 table
= assq_no_quit (script
, table
);
2315 table
= XCDR (table
);
2316 if (! NILP (langsys
))
2318 table
= assq_no_quit (langsys
, table
);
2324 val
= assq_no_quit (Qnil
, table
);
2326 table
= XCAR (table
);
2330 table
= XCDR (table
);
2331 for (negative
= 0; CONSP (features
); features
= XCDR (features
))
2333 if (NILP (XCAR (features
)))
2338 if (NILP (Fmemq (XCAR (features
), table
)) != negative
)
2344 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2347 font_check_otf (Lisp_Object spec
, Lisp_Object otf_capability
)
2349 Lisp_Object script
, langsys
= Qnil
, gsub
= Qnil
, gpos
= Qnil
;
2351 script
= XCAR (spec
);
2355 langsys
= XCAR (spec
);
2366 if (! NILP (gsub
) && ! font_check_otf_features (script
, langsys
, gsub
,
2367 XCAR (otf_capability
)))
2369 if (! NILP (gpos
) && ! font_check_otf_features (script
, langsys
, gpos
,
2370 XCDR (otf_capability
)))
2377 /* Check if FONT (font-entity or font-object) matches with the font
2378 specification SPEC. */
2381 font_match_p (Lisp_Object spec
, Lisp_Object font
)
2383 Lisp_Object prop
[FONT_SPEC_MAX
], *props
;
2384 Lisp_Object extra
, font_extra
;
2387 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2388 if (! NILP (AREF (spec
, i
))
2389 && ! NILP (AREF (font
, i
))
2390 && ! EQ (AREF (spec
, i
), AREF (font
, i
)))
2392 props
= XFONT_SPEC (spec
)->props
;
2393 if (FLOATP (props
[FONT_SIZE_INDEX
]))
2395 for (i
= FONT_FOUNDRY_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2396 prop
[i
] = AREF (spec
, i
);
2397 prop
[FONT_SIZE_INDEX
]
2398 = make_number (font_pixel_size (XFRAME (selected_frame
), spec
));
2402 if (font_score (font
, props
) > 0)
2404 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
2405 font_extra
= AREF (font
, FONT_EXTRA_INDEX
);
2406 for (; CONSP (extra
); extra
= XCDR (extra
))
2408 Lisp_Object key
= XCAR (XCAR (extra
));
2409 Lisp_Object val
= XCDR (XCAR (extra
)), val2
;
2411 if (EQ (key
, QClang
))
2413 val2
= assq_no_quit (key
, font_extra
);
2422 if (NILP (Fmemq (val
, val2
)))
2427 ? NILP (Fmemq (val
, XCDR (val2
)))
2431 else if (EQ (key
, QCscript
))
2433 val2
= assq_no_quit (val
, Vscript_representative_chars
);
2439 /* All characters in the list must be supported. */
2440 for (; CONSP (val2
); val2
= XCDR (val2
))
2442 if (! CHARACTERP (XCAR (val2
)))
2444 if (font_encode_char (font
, XFASTINT (XCAR (val2
)))
2445 == FONT_INVALID_CODE
)
2449 else if (VECTORP (val2
))
2451 /* At most one character in the vector must be supported. */
2452 for (i
= 0; i
< ASIZE (val2
); i
++)
2454 if (! CHARACTERP (AREF (val2
, i
)))
2456 if (font_encode_char (font
, XFASTINT (AREF (val2
, i
)))
2457 != FONT_INVALID_CODE
)
2460 if (i
== ASIZE (val2
))
2465 else if (EQ (key
, QCotf
))
2469 if (! FONT_OBJECT_P (font
))
2471 fontp
= XFONT_OBJECT (font
);
2472 if (! fontp
->driver
->otf_capability
)
2474 val2
= fontp
->driver
->otf_capability (fontp
);
2475 if (NILP (val2
) || ! font_check_otf (val
, val2
))
2486 Each font backend has the callback function get_cache, and it
2487 returns a cons cell of which cdr part can be freely used for
2488 caching fonts. The cons cell may be shared by multiple frames
2489 and/or multiple font drivers. So, we arrange the cdr part as this:
2491 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2493 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2494 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2495 cons (FONT-SPEC FONT-ENTITY ...). */
2497 static void font_prepare_cache (FRAME_PTR
, struct font_driver
*);
2498 static void font_finish_cache (FRAME_PTR
, struct font_driver
*);
2499 static Lisp_Object
font_get_cache (FRAME_PTR
, struct font_driver
*);
2500 static void font_clear_cache (FRAME_PTR
, Lisp_Object
,
2501 struct font_driver
*);
2504 font_prepare_cache (FRAME_PTR f
, struct font_driver
*driver
)
2506 Lisp_Object cache
, val
;
2508 cache
= driver
->get_cache (f
);
2510 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2514 val
= Fcons (driver
->type
, Fcons (make_number (1), Qnil
));
2515 XSETCDR (cache
, Fcons (val
, XCDR (cache
)));
2519 val
= XCDR (XCAR (val
));
2520 XSETCAR (val
, make_number (XINT (XCAR (val
)) + 1));
2526 font_finish_cache (FRAME_PTR f
, struct font_driver
*driver
)
2528 Lisp_Object cache
, val
, tmp
;
2531 cache
= driver
->get_cache (f
);
2533 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2534 cache
= val
, val
= XCDR (val
);
2535 eassert (! NILP (val
));
2536 tmp
= XCDR (XCAR (val
));
2537 XSETCAR (tmp
, make_number (XINT (XCAR (tmp
)) - 1));
2538 if (XINT (XCAR (tmp
)) == 0)
2540 font_clear_cache (f
, XCAR (val
), driver
);
2541 XSETCDR (cache
, XCDR (val
));
2547 font_get_cache (FRAME_PTR f
, struct font_driver
*driver
)
2549 Lisp_Object val
= driver
->get_cache (f
);
2550 Lisp_Object type
= driver
->type
;
2552 eassert (CONSP (val
));
2553 for (val
= XCDR (val
); ! EQ (XCAR (XCAR (val
)), type
); val
= XCDR (val
));
2554 eassert (CONSP (val
));
2555 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2556 val
= XCDR (XCAR (val
));
2560 static int num_fonts
;
2563 font_clear_cache (FRAME_PTR f
, Lisp_Object cache
, struct font_driver
*driver
)
2565 Lisp_Object tail
, elt
;
2566 Lisp_Object tail2
, entity
;
2568 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2569 for (tail
= XCDR (XCDR (cache
)); CONSP (tail
); tail
= XCDR (tail
))
2572 /* elt should have the form (FONT-SPEC FONT-ENTITY ...) */
2573 if (CONSP (elt
) && FONT_SPEC_P (XCAR (elt
)))
2575 for (tail2
= XCDR (elt
); CONSP (tail2
); tail2
= XCDR (tail2
))
2577 entity
= XCAR (tail2
);
2579 if (FONT_ENTITY_P (entity
)
2580 && EQ (driver
->type
, AREF (entity
, FONT_TYPE_INDEX
)))
2582 Lisp_Object objlist
= AREF (entity
, FONT_OBJLIST_INDEX
);
2584 for (; CONSP (objlist
); objlist
= XCDR (objlist
))
2586 Lisp_Object val
= XCAR (objlist
);
2587 struct font
*font
= XFONT_OBJECT (val
);
2589 if (! NILP (AREF (val
, FONT_TYPE_INDEX
)))
2591 eassert (font
&& driver
== font
->driver
);
2592 driver
->close (f
, font
);
2596 if (driver
->free_entity
)
2597 driver
->free_entity (entity
);
2602 XSETCDR (cache
, Qnil
);
2606 static Lisp_Object scratch_font_spec
, scratch_font_prefer
;
2608 /* Check each font-entity in VEC, and return a list of font-entities
2609 that satisfy these conditions:
2610 (1) matches with SPEC and SIZE if SPEC is not nil, and
2611 (2) doesn't match with any regexps in Vface_ignored_fonts (if non-nil).
2615 font_delete_unmatched (Lisp_Object vec
, Lisp_Object spec
, int size
)
2617 Lisp_Object entity
, val
;
2618 enum font_property_index prop
;
2621 for (val
= Qnil
, i
= ASIZE (vec
) - 1; i
>= 0; i
--)
2623 entity
= AREF (vec
, i
);
2624 if (! NILP (Vface_ignored_fonts
))
2628 Lisp_Object tail
, regexp
;
2630 namelen
= font_unparse_xlfd (entity
, 0, name
, 256);
2633 for (tail
= Vface_ignored_fonts
; CONSP (tail
); tail
= XCDR (tail
))
2635 regexp
= XCAR (tail
);
2636 if (STRINGP (regexp
)
2637 && fast_c_string_match_ignore_case (regexp
, name
,
2647 val
= Fcons (entity
, val
);
2650 for (prop
= FONT_WEIGHT_INDEX
; prop
< FONT_SIZE_INDEX
; prop
++)
2651 if (INTEGERP (AREF (spec
, prop
))
2652 && ((XINT (AREF (spec
, prop
)) >> 8)
2653 != (XINT (AREF (entity
, prop
)) >> 8)))
2654 prop
= FONT_SPEC_MAX
;
2655 if (prop
< FONT_SPEC_MAX
2657 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2659 int diff
= XINT (AREF (entity
, FONT_SIZE_INDEX
)) - size
;
2662 && (diff
< 0 ? -diff
> FONT_PIXEL_SIZE_QUANTUM
2663 : diff
> FONT_PIXEL_SIZE_QUANTUM
))
2664 prop
= FONT_SPEC_MAX
;
2666 if (prop
< FONT_SPEC_MAX
2667 && INTEGERP (AREF (spec
, FONT_DPI_INDEX
))
2668 && INTEGERP (AREF (entity
, FONT_DPI_INDEX
))
2669 && XINT (AREF (entity
, FONT_DPI_INDEX
)) != 0
2670 && ! EQ (AREF (spec
, FONT_DPI_INDEX
), AREF (entity
, FONT_DPI_INDEX
)))
2671 prop
= FONT_SPEC_MAX
;
2672 if (prop
< FONT_SPEC_MAX
2673 && INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
2674 && INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
2675 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) != 0
2676 && ! EQ (AREF (spec
, FONT_AVGWIDTH_INDEX
),
2677 AREF (entity
, FONT_AVGWIDTH_INDEX
)))
2678 prop
= FONT_SPEC_MAX
;
2679 if (prop
< FONT_SPEC_MAX
)
2680 val
= Fcons (entity
, val
);
2682 return (Fvconcat (1, &val
));
2686 /* Return a list of vectors of font-entities matching with SPEC on
2687 FRAME. Each elements in the list is a vector of entities from the
2688 same font-driver. */
2691 font_list_entities (Lisp_Object frame
, Lisp_Object spec
)
2693 FRAME_PTR f
= XFRAME (frame
);
2694 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2695 Lisp_Object ftype
, val
;
2696 Lisp_Object list
= Qnil
;
2698 bool need_filtering
= 0;
2701 eassert (FONT_SPEC_P (spec
));
2703 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2704 size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
2705 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
2706 size
= font_pixel_size (f
, spec
);
2710 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2711 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2712 ASET (scratch_font_spec
, i
, AREF (spec
, i
));
2713 for (i
= FONT_WEIGHT_INDEX
; i
< FONT_EXTRA_INDEX
; i
++)
2714 if (i
!= FONT_SPACING_INDEX
)
2716 ASET (scratch_font_spec
, i
, Qnil
);
2717 if (! NILP (AREF (spec
, i
)))
2720 ASET (scratch_font_spec
, FONT_SPACING_INDEX
, AREF (spec
, FONT_SPACING_INDEX
));
2721 ASET (scratch_font_spec
, FONT_EXTRA_INDEX
, AREF (spec
, FONT_EXTRA_INDEX
));
2723 for (i
= 0; driver_list
; driver_list
= driver_list
->next
)
2725 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2727 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2729 ASET (scratch_font_spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2730 val
= assoc_no_quit (scratch_font_spec
, XCDR (cache
));
2737 val
= driver_list
->driver
->list (frame
, scratch_font_spec
);
2741 val
= Fvconcat (1, &val
);
2742 copy
= copy_font_spec (scratch_font_spec
);
2743 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2744 XSETCDR (cache
, Fcons (Fcons (copy
, val
), XCDR (cache
)));
2748 || ! NILP (Vface_ignored_fonts
)))
2749 val
= font_delete_unmatched (val
, need_filtering
? spec
: Qnil
, size
);
2750 if (ASIZE (val
) > 0)
2751 list
= Fcons (val
, list
);
2754 list
= Fnreverse (list
);
2755 FONT_ADD_LOG ("list", spec
, list
);
2760 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2761 nil, is an array of face's attributes, which specifies preferred
2762 font-related attributes. */
2765 font_matching_entity (FRAME_PTR f
, Lisp_Object
*attrs
, Lisp_Object spec
)
2767 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2768 Lisp_Object ftype
, size
, entity
;
2770 Lisp_Object work
= copy_font_spec (spec
);
2772 XSETFRAME (frame
, f
);
2773 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2774 size
= AREF (spec
, FONT_SIZE_INDEX
);
2777 ASET (work
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2778 FONT_SET_STYLE (work
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
2779 FONT_SET_STYLE (work
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
2780 FONT_SET_STYLE (work
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
2783 for (; driver_list
; driver_list
= driver_list
->next
)
2785 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2787 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2790 ASET (work
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2791 entity
= assoc_no_quit (work
, XCDR (cache
));
2793 entity
= XCDR (entity
);
2796 entity
= driver_list
->driver
->match (frame
, work
);
2797 copy
= copy_font_spec (work
);
2798 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2799 XSETCDR (cache
, Fcons (Fcons (copy
, entity
), XCDR (cache
)));
2801 if (! NILP (entity
))
2804 FONT_ADD_LOG ("match", work
, entity
);
2809 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2810 opened font object. */
2813 font_open_entity (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
2815 struct font_driver_list
*driver_list
;
2816 Lisp_Object objlist
, size
, val
, font_object
;
2818 int min_width
, height
;
2820 eassert (FONT_ENTITY_P (entity
));
2821 size
= AREF (entity
, FONT_SIZE_INDEX
);
2822 if (XINT (size
) != 0)
2823 pixel_size
= XINT (size
);
2825 val
= AREF (entity
, FONT_TYPE_INDEX
);
2826 for (driver_list
= f
->font_driver_list
;
2827 driver_list
&& ! EQ (driver_list
->driver
->type
, val
);
2828 driver_list
= driver_list
->next
);
2832 for (objlist
= AREF (entity
, FONT_OBJLIST_INDEX
); CONSP (objlist
);
2833 objlist
= XCDR (objlist
))
2835 Lisp_Object fn
= XCAR (objlist
);
2836 if (! NILP (AREF (fn
, FONT_TYPE_INDEX
))
2837 && XFONT_OBJECT (fn
)->pixel_size
== pixel_size
)
2839 if (driver_list
->driver
->cached_font_ok
== NULL
2840 || driver_list
->driver
->cached_font_ok (f
, fn
, entity
))
2845 font_object
= driver_list
->driver
->open (f
, entity
, pixel_size
);
2846 if (!NILP (font_object
))
2847 ASET (font_object
, FONT_SIZE_INDEX
, make_number (pixel_size
));
2848 FONT_ADD_LOG ("open", entity
, font_object
);
2849 if (NILP (font_object
))
2851 ASET (entity
, FONT_OBJLIST_INDEX
,
2852 Fcons (font_object
, AREF (entity
, FONT_OBJLIST_INDEX
)));
2855 font
= XFONT_OBJECT (font_object
);
2856 min_width
= (font
->min_width
? font
->min_width
2857 : font
->average_width
? font
->average_width
2858 : font
->space_width
? font
->space_width
2860 height
= (font
->height
? font
->height
: 1);
2861 #ifdef HAVE_WINDOW_SYSTEM
2862 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
2863 if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
== 1)
2865 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
;
2866 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
;
2867 fonts_changed_p
= 1;
2871 if (FRAME_SMALLEST_CHAR_WIDTH (f
) > min_width
)
2872 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
, fonts_changed_p
= 1;
2873 if (FRAME_SMALLEST_FONT_HEIGHT (f
) > height
)
2874 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
, fonts_changed_p
= 1;
2882 /* Close FONT_OBJECT that is opened on frame F. */
2885 font_close_object (FRAME_PTR f
, Lisp_Object font_object
)
2887 struct font
*font
= XFONT_OBJECT (font_object
);
2889 if (NILP (AREF (font_object
, FONT_TYPE_INDEX
)))
2890 /* Already closed. */
2892 FONT_ADD_LOG ("close", font_object
, Qnil
);
2893 font
->driver
->close (f
, font
);
2894 #ifdef HAVE_WINDOW_SYSTEM
2895 eassert (FRAME_X_DISPLAY_INFO (f
)->n_fonts
);
2896 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
2902 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2903 FONT is a font-entity and it must be opened to check. */
2906 font_has_char (FRAME_PTR f
, Lisp_Object font
, int c
)
2910 if (FONT_ENTITY_P (font
))
2912 Lisp_Object type
= AREF (font
, FONT_TYPE_INDEX
);
2913 struct font_driver_list
*driver_list
;
2915 for (driver_list
= f
->font_driver_list
;
2916 driver_list
&& ! EQ (driver_list
->driver
->type
, type
);
2917 driver_list
= driver_list
->next
);
2920 if (! driver_list
->driver
->has_char
)
2922 return driver_list
->driver
->has_char (font
, c
);
2925 eassert (FONT_OBJECT_P (font
));
2926 fontp
= XFONT_OBJECT (font
);
2927 if (fontp
->driver
->has_char
)
2929 int result
= fontp
->driver
->has_char (font
, c
);
2934 return (fontp
->driver
->encode_char (fontp
, c
) != FONT_INVALID_CODE
);
2938 /* Return the glyph ID of FONT_OBJECT for character C. */
2941 font_encode_char (Lisp_Object font_object
, int c
)
2945 eassert (FONT_OBJECT_P (font_object
));
2946 font
= XFONT_OBJECT (font_object
);
2947 return font
->driver
->encode_char (font
, c
);
2951 /* Return the name of FONT_OBJECT. */
2954 font_get_name (Lisp_Object font_object
)
2956 eassert (FONT_OBJECT_P (font_object
));
2957 return AREF (font_object
, FONT_NAME_INDEX
);
2961 /* Create a new font spec from FONT_NAME, and return it. If FONT_NAME
2962 could not be parsed by font_parse_name, return Qnil. */
2965 font_spec_from_name (Lisp_Object font_name
)
2967 Lisp_Object spec
= Ffont_spec (0, NULL
);
2969 CHECK_STRING (font_name
);
2970 if (font_parse_name (SSDATA (font_name
), SBYTES (font_name
), spec
) == -1)
2972 font_put_extra (spec
, QCname
, font_name
);
2973 font_put_extra (spec
, QCuser_spec
, font_name
);
2979 font_clear_prop (Lisp_Object
*attrs
, enum font_property_index prop
)
2981 Lisp_Object font
= attrs
[LFACE_FONT_INDEX
];
2986 if (! NILP (Ffont_get (font
, QCname
)))
2988 font
= copy_font_spec (font
);
2989 font_put_extra (font
, QCname
, Qnil
);
2992 if (NILP (AREF (font
, prop
))
2993 && prop
!= FONT_FAMILY_INDEX
2994 && prop
!= FONT_FOUNDRY_INDEX
2995 && prop
!= FONT_WIDTH_INDEX
2996 && prop
!= FONT_SIZE_INDEX
)
2998 if (EQ (font
, attrs
[LFACE_FONT_INDEX
]))
2999 font
= copy_font_spec (font
);
3000 ASET (font
, prop
, Qnil
);
3001 if (prop
== FONT_FAMILY_INDEX
|| prop
== FONT_FOUNDRY_INDEX
)
3003 if (prop
== FONT_FAMILY_INDEX
)
3005 ASET (font
, FONT_FOUNDRY_INDEX
, Qnil
);
3006 /* If we are setting the font family, we must also clear
3007 FONT_WIDTH_INDEX to avoid rejecting families that lack
3008 support for some widths. */
3009 ASET (font
, FONT_WIDTH_INDEX
, Qnil
);
3011 ASET (font
, FONT_ADSTYLE_INDEX
, Qnil
);
3012 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
3013 ASET (font
, FONT_SIZE_INDEX
, Qnil
);
3014 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3015 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3016 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3018 else if (prop
== FONT_SIZE_INDEX
)
3020 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3021 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3022 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3024 else if (prop
== FONT_WIDTH_INDEX
)
3025 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3026 attrs
[LFACE_FONT_INDEX
] = font
;
3029 /* Select a font from ENTITIES (list of font-entity vectors) that
3030 supports C and is the best match for ATTRS and PIXEL_SIZE. */
3033 font_select_entity (Lisp_Object frame
, Lisp_Object entities
, Lisp_Object
*attrs
, int pixel_size
, int c
)
3035 Lisp_Object font_entity
;
3038 FRAME_PTR f
= XFRAME (frame
);
3040 if (NILP (XCDR (entities
))
3041 && ASIZE (XCAR (entities
)) == 1)
3043 font_entity
= AREF (XCAR (entities
), 0);
3044 if (c
< 0 || font_has_char (f
, font_entity
, c
) > 0)
3049 /* Sort fonts by properties specified in ATTRS. */
3050 prefer
= scratch_font_prefer
;
3052 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
3053 ASET (prefer
, i
, Qnil
);
3054 if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3056 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3058 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
3059 ASET (prefer
, i
, AREF (face_font
, i
));
3061 if (NILP (AREF (prefer
, FONT_WEIGHT_INDEX
)))
3062 FONT_SET_STYLE (prefer
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
3063 if (NILP (AREF (prefer
, FONT_SLANT_INDEX
)))
3064 FONT_SET_STYLE (prefer
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
3065 if (NILP (AREF (prefer
, FONT_WIDTH_INDEX
)))
3066 FONT_SET_STYLE (prefer
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
3067 ASET (prefer
, FONT_SIZE_INDEX
, make_number (pixel_size
));
3069 return font_sort_entities (entities
, prefer
, frame
, c
);
3072 /* Return a font-entity that satisfies SPEC and is the best match for
3073 face's font related attributes in ATTRS. C, if not negative, is a
3074 character that the entity must support. */
3077 font_find_for_lface (FRAME_PTR f
, Lisp_Object
*attrs
, Lisp_Object spec
, int c
)
3080 Lisp_Object frame
, entities
, val
;
3081 Lisp_Object foundry
[3], *family
, registry
[3], adstyle
[3];
3086 registry
[0] = AREF (spec
, FONT_REGISTRY_INDEX
);
3087 if (NILP (registry
[0]))
3089 registry
[0] = DEFAULT_ENCODING
;
3090 registry
[1] = Qascii_0
;
3091 registry
[2] = zero_vector
;
3094 registry
[1] = zero_vector
;
3096 if (c
>= 0 && ! NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
3098 struct charset
*encoding
, *repertory
;
3100 if (font_registry_charsets (AREF (spec
, FONT_REGISTRY_INDEX
),
3101 &encoding
, &repertory
) < 0)
3104 && ENCODE_CHAR (repertory
, c
) == CHARSET_INVALID_CODE (repertory
))
3106 else if (c
> encoding
->max_char
)
3110 work
= copy_font_spec (spec
);
3111 ASET (work
, FONT_TYPE_INDEX
, AREF (spec
, FONT_TYPE_INDEX
));
3112 XSETFRAME (frame
, f
);
3113 pixel_size
= font_pixel_size (f
, spec
);
3114 if (pixel_size
== 0 && INTEGERP (attrs
[LFACE_HEIGHT_INDEX
]))
3116 double pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3118 pixel_size
= POINT_TO_PIXEL (pt
/ 10, f
->resy
);
3120 ASET (work
, FONT_SIZE_INDEX
, Qnil
);
3121 foundry
[0] = AREF (work
, FONT_FOUNDRY_INDEX
);
3122 if (! NILP (foundry
[0]))
3123 foundry
[1] = zero_vector
;
3124 else if (STRINGP (attrs
[LFACE_FOUNDRY_INDEX
]))
3126 val
= attrs
[LFACE_FOUNDRY_INDEX
];
3127 foundry
[0] = font_intern_prop (SSDATA (val
), SBYTES (val
), 1);
3129 foundry
[2] = zero_vector
;
3132 foundry
[0] = Qnil
, foundry
[1] = zero_vector
;
3134 adstyle
[0] = AREF (work
, FONT_ADSTYLE_INDEX
);
3135 if (! NILP (adstyle
[0]))
3136 adstyle
[1] = zero_vector
;
3137 else if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3139 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3141 if (! NILP (AREF (face_font
, FONT_ADSTYLE_INDEX
)))
3143 adstyle
[0] = AREF (face_font
, FONT_ADSTYLE_INDEX
);
3145 adstyle
[2] = zero_vector
;
3148 adstyle
[0] = Qnil
, adstyle
[1] = zero_vector
;
3151 adstyle
[0] = Qnil
, adstyle
[1] = zero_vector
;
3154 val
= AREF (work
, FONT_FAMILY_INDEX
);
3155 if (NILP (val
) && STRINGP (attrs
[LFACE_FAMILY_INDEX
]))
3157 val
= attrs
[LFACE_FAMILY_INDEX
];
3158 val
= font_intern_prop (SSDATA (val
), SBYTES (val
), 1);
3162 family
= alloca ((sizeof family
[0]) * 2);
3164 family
[1] = zero_vector
; /* terminator. */
3169 = Fassoc_string (val
, Vface_alternative_font_family_alist
, Qt
);
3171 if (! NILP (alters
))
3173 EMACS_INT alterslen
= XFASTINT (Flength (alters
));
3174 SAFE_ALLOCA_LISP (family
, alterslen
+ 2);
3175 for (i
= 0; CONSP (alters
); i
++, alters
= XCDR (alters
))
3176 family
[i
] = XCAR (alters
);
3177 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3179 family
[i
] = zero_vector
;
3183 family
= alloca ((sizeof family
[0]) * 3);
3186 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3188 family
[i
] = zero_vector
;
3192 for (i
= 0; SYMBOLP (family
[i
]); i
++)
3194 ASET (work
, FONT_FAMILY_INDEX
, family
[i
]);
3195 for (j
= 0; SYMBOLP (foundry
[j
]); j
++)
3197 ASET (work
, FONT_FOUNDRY_INDEX
, foundry
[j
]);
3198 for (k
= 0; SYMBOLP (registry
[k
]); k
++)
3200 ASET (work
, FONT_REGISTRY_INDEX
, registry
[k
]);
3201 for (l
= 0; SYMBOLP (adstyle
[l
]); l
++)
3203 ASET (work
, FONT_ADSTYLE_INDEX
, adstyle
[l
]);
3204 entities
= font_list_entities (frame
, work
);
3205 if (! NILP (entities
))
3207 val
= font_select_entity (frame
, entities
,
3208 attrs
, pixel_size
, c
);
3223 font_open_for_lface (FRAME_PTR f
, Lisp_Object entity
, Lisp_Object
*attrs
, Lisp_Object spec
)
3227 if (INTEGERP (AREF (entity
, FONT_SIZE_INDEX
))
3228 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
3229 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
3232 if (FONT_SPEC_P (spec
) && ! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
3233 size
= font_pixel_size (f
, spec
);
3237 if (INTEGERP (attrs
[LFACE_HEIGHT_INDEX
]))
3238 pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3241 struct face
*def
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
3242 Lisp_Object height
= def
->lface
[LFACE_HEIGHT_INDEX
];
3243 eassert (INTEGERP (height
));
3248 size
= POINT_TO_PIXEL (pt
, f
->resy
);
3252 Lisp_Object ffsize
= get_frame_param (f
, Qfontsize
);
3253 size
= NUMBERP (ffsize
) ? POINT_TO_PIXEL (XINT (ffsize
), f
->resy
) : 0;
3257 size
*= font_rescale_ratio (entity
);
3260 return font_open_entity (f
, entity
, size
);
3264 /* Find a font that satisfies SPEC and is the best match for
3265 face's attributes in ATTRS on FRAME, and return the opened
3269 font_load_for_lface (FRAME_PTR f
, Lisp_Object
*attrs
, Lisp_Object spec
)
3271 Lisp_Object entity
, name
;
3273 entity
= font_find_for_lface (f
, attrs
, spec
, -1);
3276 /* No font is listed for SPEC, but each font-backend may have
3277 different criteria about "font matching". So, try it. */
3278 entity
= font_matching_entity (f
, attrs
, spec
);
3282 /* Don't lose the original name that was put in initially. We need
3283 it to re-apply the font when font parameters (like hinting or dpi) have
3285 entity
= font_open_for_lface (f
, entity
, attrs
, spec
);
3288 name
= Ffont_get (spec
, QCuser_spec
);
3289 if (STRINGP (name
)) font_put_extra (entity
, QCuser_spec
, name
);
3295 /* Make FACE on frame F ready to use the font opened for FACE. */
3298 font_prepare_for_face (FRAME_PTR f
, struct face
*face
)
3300 if (face
->font
->driver
->prepare_face
)
3301 face
->font
->driver
->prepare_face (f
, face
);
3305 /* Make FACE on frame F stop using the font opened for FACE. */
3308 font_done_for_face (FRAME_PTR f
, struct face
*face
)
3310 if (face
->font
->driver
->done_face
)
3311 face
->font
->driver
->done_face (f
, face
);
3316 /* Open a font that is a match for font-spec SPEC on frame F. If no proper
3317 font is found, return Qnil. */
3320 font_open_by_spec (FRAME_PTR f
, Lisp_Object spec
)
3322 Lisp_Object attrs
[LFACE_VECTOR_SIZE
];
3324 /* We set up the default font-related attributes of a face to prefer
3326 attrs
[LFACE_FAMILY_INDEX
] = attrs
[LFACE_FOUNDRY_INDEX
] = Qnil
;
3327 attrs
[LFACE_SWIDTH_INDEX
] = attrs
[LFACE_WEIGHT_INDEX
]
3328 = attrs
[LFACE_SLANT_INDEX
] = Qnormal
;
3330 attrs
[LFACE_HEIGHT_INDEX
] = make_number (120);
3332 attrs
[LFACE_HEIGHT_INDEX
] = make_number (0);
3334 attrs
[LFACE_FONT_INDEX
] = Qnil
;
3336 return font_load_for_lface (f
, attrs
, spec
);
3340 /* Open a font that matches NAME on frame F. If no proper font is
3341 found, return Qnil. */
3344 font_open_by_name (FRAME_PTR f
, Lisp_Object name
)
3346 Lisp_Object args
[2];
3347 Lisp_Object spec
, ret
;
3351 spec
= Ffont_spec (2, args
);
3352 ret
= font_open_by_spec (f
, spec
);
3353 /* Do not lose name originally put in. */
3355 font_put_extra (ret
, QCuser_spec
, args
[1]);
3361 /* Register font-driver DRIVER. This function is used in two ways.
3363 The first is with frame F non-NULL. In this case, make DRIVER
3364 available (but not yet activated) on F. All frame creators
3365 (e.g. Fx_create_frame) must call this function at least once with
3366 an available font-driver.
3368 The second is with frame F NULL. In this case, DRIVER is globally
3369 registered in the variable `font_driver_list'. All font-driver
3370 implementations must call this function in its syms_of_XXXX
3371 (e.g. syms_of_xfont). */
3374 register_font_driver (struct font_driver
*driver
, FRAME_PTR f
)
3376 struct font_driver_list
*root
= f
? f
->font_driver_list
: font_driver_list
;
3377 struct font_driver_list
*prev
, *list
;
3379 if (f
&& ! driver
->draw
)
3380 error ("Unusable font driver for a frame: %s",
3381 SDATA (SYMBOL_NAME (driver
->type
)));
3383 for (prev
= NULL
, list
= root
; list
; prev
= list
, list
= list
->next
)
3384 if (EQ (list
->driver
->type
, driver
->type
))
3385 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver
->type
)));
3387 list
= xmalloc (sizeof *list
);
3389 list
->driver
= driver
;
3394 f
->font_driver_list
= list
;
3396 font_driver_list
= list
;
3402 free_font_driver_list (FRAME_PTR f
)
3404 struct font_driver_list
*list
, *next
;
3406 for (list
= f
->font_driver_list
; list
; list
= next
)
3411 f
->font_driver_list
= NULL
;
3415 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3416 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3417 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3419 A caller must free all realized faces if any in advance. The
3420 return value is a list of font backends actually made used on
3424 font_update_drivers (FRAME_PTR f
, Lisp_Object new_drivers
)
3426 Lisp_Object active_drivers
= Qnil
;
3427 struct font_driver_list
*list
;
3429 /* At first, turn off non-requested drivers, and turn on requested
3431 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3433 struct font_driver
*driver
= list
->driver
;
3434 if ((EQ (new_drivers
, Qt
) || ! NILP (Fmemq (driver
->type
, new_drivers
)))
3439 if (driver
->end_for_frame
)
3440 driver
->end_for_frame (f
);
3441 font_finish_cache (f
, driver
);
3446 if (! driver
->start_for_frame
3447 || driver
->start_for_frame (f
) == 0)
3449 font_prepare_cache (f
, driver
);
3456 if (NILP (new_drivers
))
3459 if (! EQ (new_drivers
, Qt
))
3461 /* Re-order the driver list according to new_drivers. */
3462 struct font_driver_list
**list_table
, **next
;
3466 list_table
= alloca (sizeof list_table
[0] * (num_font_drivers
+ 1));
3467 for (i
= 0, tail
= new_drivers
; ! NILP (tail
); tail
= XCDR (tail
))
3469 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3470 if (list
->on
&& EQ (list
->driver
->type
, XCAR (tail
)))
3473 list_table
[i
++] = list
;
3475 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3477 list_table
[i
++] = list
;
3478 list_table
[i
] = NULL
;
3480 next
= &f
->font_driver_list
;
3481 for (i
= 0; list_table
[i
]; i
++)
3483 *next
= list_table
[i
];
3484 next
= &(*next
)->next
;
3488 if (! f
->font_driver_list
->on
)
3489 { /* None of the drivers is enabled: enable them all.
3490 Happens if you set the list of drivers to (xft x) in your .emacs
3491 and then use it under w32 or ns. */
3492 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3494 struct font_driver
*driver
= list
->driver
;
3495 eassert (! list
->on
);
3496 if (! driver
->start_for_frame
3497 || driver
->start_for_frame (f
) == 0)
3499 font_prepare_cache (f
, driver
);
3506 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3508 active_drivers
= nconc2 (active_drivers
,
3509 Fcons (list
->driver
->type
, Qnil
));
3510 return active_drivers
;
3514 font_put_frame_data (FRAME_PTR f
, struct font_driver
*driver
, void *data
)
3516 struct font_data_list
*list
, *prev
;
3518 for (prev
= NULL
, list
= f
->font_data_list
; list
;
3519 prev
= list
, list
= list
->next
)
3520 if (list
->driver
== driver
)
3527 prev
->next
= list
->next
;
3529 f
->font_data_list
= list
->next
;
3537 list
= xmalloc (sizeof *list
);
3538 list
->driver
= driver
;
3539 list
->next
= f
->font_data_list
;
3540 f
->font_data_list
= list
;
3548 font_get_frame_data (FRAME_PTR f
, struct font_driver
*driver
)
3550 struct font_data_list
*list
;
3552 for (list
= f
->font_data_list
; list
; list
= list
->next
)
3553 if (list
->driver
== driver
)
3561 /* Sets attributes on a font. Any properties that appear in ALIST and
3562 BOOLEAN_PROPERTIES or NON_BOOLEAN_PROPERTIES are set on the font.
3563 BOOLEAN_PROPERTIES and NON_BOOLEAN_PROPERTIES are NULL-terminated
3564 arrays of strings. This function is intended for use by the font
3565 drivers to implement their specific font_filter_properties. */
3567 font_filter_properties (Lisp_Object font
,
3569 const char *const boolean_properties
[],
3570 const char *const non_boolean_properties
[])
3575 /* Set boolean values to Qt or Qnil */
3576 for (i
= 0; boolean_properties
[i
] != NULL
; ++i
)
3577 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
3579 Lisp_Object key
= XCAR (XCAR (it
));
3580 Lisp_Object val
= XCDR (XCAR (it
));
3581 char *keystr
= SSDATA (SYMBOL_NAME (key
));
3583 if (strcmp (boolean_properties
[i
], keystr
) == 0)
3585 const char *str
= INTEGERP (val
) ? (XINT (val
) ? "true" : "false")
3586 : SYMBOLP (val
) ? SSDATA (SYMBOL_NAME (val
))
3589 if (strcmp ("false", str
) == 0 || strcmp ("False", str
) == 0
3590 || strcmp ("FALSE", str
) == 0 || strcmp ("FcFalse", str
) == 0
3591 || strcmp ("off", str
) == 0 || strcmp ("OFF", str
) == 0
3592 || strcmp ("Off", str
) == 0)
3597 Ffont_put (font
, key
, val
);
3601 for (i
= 0; non_boolean_properties
[i
] != NULL
; ++i
)
3602 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
3604 Lisp_Object key
= XCAR (XCAR (it
));
3605 Lisp_Object val
= XCDR (XCAR (it
));
3606 char *keystr
= SSDATA (SYMBOL_NAME (key
));
3607 if (strcmp (non_boolean_properties
[i
], keystr
) == 0)
3608 Ffont_put (font
, key
, val
);
3613 /* Return the font used to draw character C by FACE at buffer position
3614 POS in window W. If STRING is non-nil, it is a string containing C
3615 at index POS. If C is negative, get C from the current buffer or
3619 font_at (int c
, ptrdiff_t pos
, struct face
*face
, struct window
*w
,
3624 Lisp_Object font_object
;
3626 multibyte
= (NILP (string
)
3627 ? ! NILP (BVAR (current_buffer
, enable_multibyte_characters
))
3628 : STRING_MULTIBYTE (string
));
3635 ptrdiff_t pos_byte
= CHAR_TO_BYTE (pos
);
3637 c
= FETCH_CHAR (pos_byte
);
3640 c
= FETCH_BYTE (pos
);
3646 multibyte
= STRING_MULTIBYTE (string
);
3649 ptrdiff_t pos_byte
= string_char_to_byte (string
, pos
);
3651 str
= SDATA (string
) + pos_byte
;
3652 c
= STRING_CHAR (str
);
3655 c
= SDATA (string
)[pos
];
3659 f
= XFRAME (w
->frame
);
3660 if (! FRAME_WINDOW_P (f
))
3667 if (STRINGP (string
))
3668 face_id
= face_at_string_position (w
, string
, pos
, 0, -1, -1, &endptr
,
3669 DEFAULT_FACE_ID
, 0);
3671 face_id
= face_at_buffer_position (w
, pos
, -1, -1, &endptr
,
3673 face
= FACE_FROM_ID (f
, face_id
);
3677 int face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3678 face
= FACE_FROM_ID (f
, face_id
);
3683 XSETFONT (font_object
, face
->font
);
3688 #ifdef HAVE_WINDOW_SYSTEM
3690 /* Check how many characters after POS (at most to *LIMIT) can be
3691 displayed by the same font in the window W. FACE, if non-NULL, is
3692 the face selected for the character at POS. If STRING is not nil,
3693 it is the string to check instead of the current buffer. In that
3694 case, FACE must be not NULL.
3696 The return value is the font-object for the character at POS.
3697 *LIMIT is set to the position where that font can't be used.
3699 It is assured that the current buffer (or STRING) is multibyte. */
3702 font_range (ptrdiff_t pos
, ptrdiff_t *limit
, struct window
*w
, struct face
*face
, Lisp_Object string
)
3704 ptrdiff_t pos_byte
, ignore
;
3706 Lisp_Object font_object
= Qnil
;
3710 pos_byte
= CHAR_TO_BYTE (pos
);
3715 face_id
= face_at_buffer_position (w
, pos
, 0, 0, &ignore
,
3717 face
= FACE_FROM_ID (XFRAME (w
->frame
), face_id
);
3723 pos_byte
= string_char_to_byte (string
, pos
);
3726 while (pos
< *limit
)
3728 Lisp_Object category
;
3731 FETCH_CHAR_ADVANCE_NO_CHECK (c
, pos
, pos_byte
);
3733 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c
, string
, pos
, pos_byte
);
3734 category
= CHAR_TABLE_REF (Vunicode_category_table
, c
);
3735 if (INTEGERP (category
)
3736 && (XINT (category
) == UNICODE_CATEGORY_Cf
3737 || CHAR_VARIATION_SELECTOR_P (c
)))
3739 if (NILP (font_object
))
3741 font_object
= font_for_char (face
, c
, pos
- 1, string
);
3742 if (NILP (font_object
))
3746 if (font_encode_char (font_object
, c
) == FONT_INVALID_CODE
)
3756 DEFUN ("fontp", Ffontp
, Sfontp
, 1, 2, 0,
3757 doc
: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3758 Return nil otherwise.
3759 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3760 which kind of font it is. It must be one of `font-spec', `font-entity',
3762 (Lisp_Object object
, Lisp_Object extra_type
)
3764 if (NILP (extra_type
))
3765 return (FONTP (object
) ? Qt
: Qnil
);
3766 if (EQ (extra_type
, Qfont_spec
))
3767 return (FONT_SPEC_P (object
) ? Qt
: Qnil
);
3768 if (EQ (extra_type
, Qfont_entity
))
3769 return (FONT_ENTITY_P (object
) ? Qt
: Qnil
);
3770 if (EQ (extra_type
, Qfont_object
))
3771 return (FONT_OBJECT_P (object
) ? Qt
: Qnil
);
3772 wrong_type_argument (intern ("font-extra-type"), extra_type
);
3775 DEFUN ("font-spec", Ffont_spec
, Sfont_spec
, 0, MANY
, 0,
3776 doc
: /* Return a newly created font-spec with arguments as properties.
3778 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3779 valid font property name listed below:
3781 `:family', `:weight', `:slant', `:width'
3783 They are the same as face attributes of the same name. See
3784 `set-face-attribute'.
3788 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3792 VALUE must be a string or a symbol specifying the additional
3793 typographic style information of a font, e.g. ``sans''.
3797 VALUE must be a string or a symbol specifying the charset registry and
3798 encoding of a font, e.g. ``iso8859-1''.
3802 VALUE must be a non-negative integer or a floating point number
3803 specifying the font size. It specifies the font size in pixels (if
3804 VALUE is an integer), or in points (if VALUE is a float).
3808 VALUE must be a string of XLFD-style or fontconfig-style font name.
3812 VALUE must be a symbol representing a script that the font must
3813 support. It may be a symbol representing a subgroup of a script
3814 listed in the variable `script-representative-chars'.
3818 VALUE must be a symbol of two-letter ISO-639 language names,
3823 VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
3824 required OpenType features.
3826 SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
3827 LANGSYS-TAG: OpenType language system tag symbol,
3828 or nil for the default language system.
3829 GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
3830 GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
3832 GSUB and GPOS may contain `nil' element. In such a case, the font
3833 must not have any of the remaining elements.
3835 For instance, if the VALUE is `(thai nil nil (mark))', the font must
3836 be an OpenType font whose GPOS table of `thai' script's default
3837 language system must contain `mark' feature.
3839 usage: (font-spec ARGS...) */)
3840 (ptrdiff_t nargs
, Lisp_Object
*args
)
3842 Lisp_Object spec
= font_make_spec ();
3845 for (i
= 0; i
< nargs
; i
+= 2)
3847 Lisp_Object key
= args
[i
], val
;
3851 error ("No value for key `%s'", SDATA (SYMBOL_NAME (key
)));
3854 if (EQ (key
, QCname
))
3857 font_parse_name (SSDATA (val
), SBYTES (val
), spec
);
3858 font_put_extra (spec
, key
, val
);
3862 int idx
= get_font_prop_index (key
);
3866 val
= font_prop_validate (idx
, Qnil
, val
);
3867 if (idx
< FONT_EXTRA_INDEX
)
3868 ASET (spec
, idx
, val
);
3870 font_put_extra (spec
, key
, val
);
3873 font_put_extra (spec
, key
, font_prop_validate (0, key
, val
));
3879 /* Return a copy of FONT as a font-spec. */
3881 copy_font_spec (Lisp_Object font
)
3883 Lisp_Object new_spec
, tail
, prev
, extra
;
3887 new_spec
= font_make_spec ();
3888 for (i
= 1; i
< FONT_EXTRA_INDEX
; i
++)
3889 ASET (new_spec
, i
, AREF (font
, i
));
3890 extra
= Fcopy_alist (AREF (font
, FONT_EXTRA_INDEX
));
3891 /* We must remove :font-entity property. */
3892 for (prev
= Qnil
, tail
= extra
; CONSP (tail
); prev
= tail
, tail
= XCDR (tail
))
3893 if (EQ (XCAR (XCAR (tail
)), QCfont_entity
))
3896 extra
= XCDR (extra
);
3898 XSETCDR (prev
, XCDR (tail
));
3901 ASET (new_spec
, FONT_EXTRA_INDEX
, extra
);
3905 /* Merge font-specs FROM and TO, and return a new font-spec.
3906 Every specified property in FROM overrides the corresponding
3909 merge_font_spec (Lisp_Object from
, Lisp_Object to
)
3911 Lisp_Object extra
, tail
;
3916 to
= copy_font_spec (to
);
3917 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
3918 ASET (to
, i
, AREF (from
, i
));
3919 extra
= AREF (to
, FONT_EXTRA_INDEX
);
3920 for (tail
= AREF (from
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
3921 if (! EQ (XCAR (XCAR (tail
)), Qfont_entity
))
3923 Lisp_Object slot
= assq_no_quit (XCAR (XCAR (tail
)), extra
);
3926 XSETCDR (slot
, XCDR (XCAR (tail
)));
3928 extra
= Fcons (Fcons (XCAR (XCAR (tail
)), XCDR (XCAR (tail
))), extra
);
3930 ASET (to
, FONT_EXTRA_INDEX
, extra
);
3934 DEFUN ("font-get", Ffont_get
, Sfont_get
, 2, 2, 0,
3935 doc
: /* Return the value of FONT's property KEY.
3936 FONT is a font-spec, a font-entity, or a font-object.
3937 KEY is any symbol, but these are reserved for specific meanings:
3938 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
3939 :size, :name, :script, :otf
3940 See the documentation of `font-spec' for their meanings.
3941 In addition, if FONT is a font-entity or a font-object, values of
3942 :script and :otf are different from those of a font-spec as below:
3944 The value of :script may be a list of scripts that are supported by the font.
3946 The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
3947 representing the OpenType features supported by the font by this form:
3948 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
3949 SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
3951 (Lisp_Object font
, Lisp_Object key
)
3959 idx
= get_font_prop_index (key
);
3960 if (idx
>= FONT_WEIGHT_INDEX
&& idx
<= FONT_WIDTH_INDEX
)
3961 return font_style_symbolic (font
, idx
, 0);
3962 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
3963 return AREF (font
, idx
);
3964 val
= Fassq (key
, AREF (font
, FONT_EXTRA_INDEX
));
3965 if (NILP (val
) && EQ (key
, QCotf
) && FONT_OBJECT_P (font
))
3967 struct font
*fontp
= XFONT_OBJECT (font
);
3969 if (fontp
->driver
->otf_capability
)
3970 val
= fontp
->driver
->otf_capability (fontp
);
3972 val
= Fcons (Qnil
, Qnil
);
3979 #ifdef HAVE_WINDOW_SYSTEM
3981 DEFUN ("font-face-attributes", Ffont_face_attributes
, Sfont_face_attributes
, 1, 2, 0,
3982 doc
: /* Return a plist of face attributes generated by FONT.
3983 FONT is a font name, a font-spec, a font-entity, or a font-object.
3984 The return value is a list of the form
3986 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
3988 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
3989 compatible with `set-face-attribute'. Some of these key-attribute pairs
3990 may be omitted from the list if they are not specified by FONT.
3992 The optional argument FRAME specifies the frame that the face attributes
3993 are to be displayed on. If omitted, the selected frame is used. */)
3994 (Lisp_Object font
, Lisp_Object frame
)
3997 Lisp_Object plist
[10];
4002 frame
= selected_frame
;
4003 CHECK_LIVE_FRAME (frame
);
4008 int fontset
= fs_query_fontset (font
, 0);
4009 Lisp_Object name
= font
;
4011 font
= fontset_ascii (fontset
);
4012 font
= font_spec_from_name (name
);
4014 signal_error ("Invalid font name", name
);
4016 else if (! FONTP (font
))
4017 signal_error ("Invalid font object", font
);
4019 val
= AREF (font
, FONT_FAMILY_INDEX
);
4022 plist
[n
++] = QCfamily
;
4023 plist
[n
++] = SYMBOL_NAME (val
);
4026 val
= AREF (font
, FONT_SIZE_INDEX
);
4029 Lisp_Object font_dpi
= AREF (font
, FONT_DPI_INDEX
);
4030 int dpi
= INTEGERP (font_dpi
) ? XINT (font_dpi
) : f
->resy
;
4031 plist
[n
++] = QCheight
;
4032 plist
[n
++] = make_number (PIXEL_TO_POINT (XINT (val
) * 10, dpi
));
4034 else if (FLOATP (val
))
4036 plist
[n
++] = QCheight
;
4037 plist
[n
++] = make_number (10 * (int) XFLOAT_DATA (val
));
4040 val
= FONT_WEIGHT_FOR_FACE (font
);
4043 plist
[n
++] = QCweight
;
4047 val
= FONT_SLANT_FOR_FACE (font
);
4050 plist
[n
++] = QCslant
;
4054 val
= FONT_WIDTH_FOR_FACE (font
);
4057 plist
[n
++] = QCwidth
;
4061 return Flist (n
, plist
);
4066 DEFUN ("font-put", Ffont_put
, Sfont_put
, 3, 3, 0,
4067 doc
: /* Set one property of FONT: give property KEY value VAL.
4068 FONT is a font-spec, a font-entity, or a font-object.
4070 If FONT is a font-spec, KEY can be any symbol. But if KEY is the one
4071 accepted by the function `font-spec' (which see), VAL must be what
4072 allowed in `font-spec'.
4074 If FONT is a font-entity or a font-object, KEY must not be the one
4075 accepted by `font-spec'. */)
4076 (Lisp_Object font
, Lisp_Object prop
, Lisp_Object val
)
4080 idx
= get_font_prop_index (prop
);
4081 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
4083 CHECK_FONT_SPEC (font
);
4084 ASET (font
, idx
, font_prop_validate (idx
, Qnil
, val
));
4088 if (EQ (prop
, QCname
)
4089 || EQ (prop
, QCscript
)
4090 || EQ (prop
, QClang
)
4091 || EQ (prop
, QCotf
))
4092 CHECK_FONT_SPEC (font
);
4095 font_put_extra (font
, prop
, font_prop_validate (0, prop
, val
));
4100 DEFUN ("list-fonts", Flist_fonts
, Slist_fonts
, 1, 4, 0,
4101 doc
: /* List available fonts matching FONT-SPEC on the current frame.
4102 Optional 2nd argument FRAME specifies the target frame.
4103 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4104 Optional 4th argument PREFER, if non-nil, is a font-spec to
4105 control the order of the returned list. Fonts are sorted by
4106 how close they are to PREFER. */)
4107 (Lisp_Object font_spec
, Lisp_Object frame
, Lisp_Object num
, Lisp_Object prefer
)
4109 Lisp_Object vec
, list
;
4113 frame
= selected_frame
;
4114 CHECK_LIVE_FRAME (frame
);
4115 CHECK_FONT_SPEC (font_spec
);
4123 if (! NILP (prefer
))
4124 CHECK_FONT_SPEC (prefer
);
4126 list
= font_list_entities (frame
, font_spec
);
4129 if (NILP (XCDR (list
))
4130 && ASIZE (XCAR (list
)) == 1)
4131 return Fcons (AREF (XCAR (list
), 0), Qnil
);
4133 if (! NILP (prefer
))
4134 vec
= font_sort_entities (list
, prefer
, frame
, 0);
4136 vec
= font_vconcat_entity_vectors (list
);
4137 if (n
== 0 || n
>= ASIZE (vec
))
4139 Lisp_Object args
[2];
4143 list
= Fappend (2, args
);
4147 for (list
= Qnil
, n
--; n
>= 0; n
--)
4148 list
= Fcons (AREF (vec
, n
), list
);
4153 DEFUN ("font-family-list", Ffont_family_list
, Sfont_family_list
, 0, 1, 0,
4154 doc
: /* List available font families on the current frame.
4155 Optional argument FRAME, if non-nil, specifies the target frame. */)
4159 struct font_driver_list
*driver_list
;
4163 frame
= selected_frame
;
4164 CHECK_LIVE_FRAME (frame
);
4167 for (driver_list
= f
->font_driver_list
; driver_list
;
4168 driver_list
= driver_list
->next
)
4169 if (driver_list
->driver
->list_family
)
4171 Lisp_Object val
= driver_list
->driver
->list_family (frame
);
4172 Lisp_Object tail
= list
;
4174 for (; CONSP (val
); val
= XCDR (val
))
4175 if (NILP (Fmemq (XCAR (val
), tail
))
4176 && SYMBOLP (XCAR (val
)))
4177 list
= Fcons (SYMBOL_NAME (XCAR (val
)), list
);
4182 DEFUN ("find-font", Ffind_font
, Sfind_font
, 1, 2, 0,
4183 doc
: /* Return a font-entity matching with FONT-SPEC on the current frame.
4184 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4185 (Lisp_Object font_spec
, Lisp_Object frame
)
4187 Lisp_Object val
= Flist_fonts (font_spec
, frame
, make_number (1), Qnil
);
4194 DEFUN ("font-xlfd-name", Ffont_xlfd_name
, Sfont_xlfd_name
, 1, 2, 0,
4195 doc
: /* Return XLFD name of FONT.
4196 FONT is a font-spec, font-entity, or font-object.
4197 If the name is too long for XLFD (maximum 255 chars), return nil.
4198 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4199 the consecutive wildcards are folded into one. */)
4200 (Lisp_Object font
, Lisp_Object fold_wildcards
)
4203 int namelen
, pixel_size
= 0;
4207 if (FONT_OBJECT_P (font
))
4209 Lisp_Object font_name
= AREF (font
, FONT_NAME_INDEX
);
4211 if (STRINGP (font_name
)
4212 && SDATA (font_name
)[0] == '-')
4214 if (NILP (fold_wildcards
))
4216 strcpy (name
, SSDATA (font_name
));
4217 namelen
= SBYTES (font_name
);
4220 pixel_size
= XFONT_OBJECT (font
)->pixel_size
;
4222 namelen
= font_unparse_xlfd (font
, pixel_size
, name
, 256);
4226 if (! NILP (fold_wildcards
))
4228 char *p0
= name
, *p1
;
4230 while ((p1
= strstr (p0
, "-*-*")))
4232 strcpy (p1
, p1
+ 2);
4238 return make_string (name
, namelen
);
4241 DEFUN ("clear-font-cache", Fclear_font_cache
, Sclear_font_cache
, 0, 0, 0,
4242 doc
: /* Clear font cache. */)
4245 Lisp_Object list
, frame
;
4247 FOR_EACH_FRAME (list
, frame
)
4249 FRAME_PTR f
= XFRAME (frame
);
4250 struct font_driver_list
*driver_list
= f
->font_driver_list
;
4252 for (; driver_list
; driver_list
= driver_list
->next
)
4253 if (driver_list
->on
)
4255 Lisp_Object cache
= driver_list
->driver
->get_cache (f
);
4256 Lisp_Object val
, tmp
;
4260 && ! EQ (XCAR (XCAR (val
)), driver_list
->driver
->type
))
4262 eassert (! NILP (val
));
4263 tmp
= XCDR (XCAR (val
));
4264 if (XINT (XCAR (tmp
)) == 0)
4266 font_clear_cache (f
, XCAR (val
), driver_list
->driver
);
4267 XSETCDR (cache
, XCDR (val
));
4277 font_fill_lglyph_metrics (Lisp_Object glyph
, Lisp_Object font_object
)
4279 struct font
*font
= XFONT_OBJECT (font_object
);
4280 unsigned code
= font
->driver
->encode_char (font
, LGLYPH_CHAR (glyph
));
4281 struct font_metrics metrics
;
4283 LGLYPH_SET_CODE (glyph
, code
);
4284 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4285 LGLYPH_SET_LBEARING (glyph
, metrics
.lbearing
);
4286 LGLYPH_SET_RBEARING (glyph
, metrics
.rbearing
);
4287 LGLYPH_SET_WIDTH (glyph
, metrics
.width
);
4288 LGLYPH_SET_ASCENT (glyph
, metrics
.ascent
);
4289 LGLYPH_SET_DESCENT (glyph
, metrics
.descent
);
4293 DEFUN ("font-shape-gstring", Ffont_shape_gstring
, Sfont_shape_gstring
, 1, 1, 0,
4294 doc
: /* Shape the glyph-string GSTRING.
4295 Shaping means substituting glyphs and/or adjusting positions of glyphs
4296 to get the correct visual image of character sequences set in the
4297 header of the glyph-string.
4299 If the shaping was successful, the value is GSTRING itself or a newly
4300 created glyph-string. Otherwise, the value is nil.
4302 See the documentation of `composition-get-gstring' for the format of
4304 (Lisp_Object gstring
)
4307 Lisp_Object font_object
, n
, glyph
;
4308 ptrdiff_t i
, from
, to
;
4310 if (! composition_gstring_p (gstring
))
4311 signal_error ("Invalid glyph-string: ", gstring
);
4312 if (! NILP (LGSTRING_ID (gstring
)))
4314 font_object
= LGSTRING_FONT (gstring
);
4315 CHECK_FONT_OBJECT (font_object
);
4316 font
= XFONT_OBJECT (font_object
);
4317 if (! font
->driver
->shape
)
4320 /* Try at most three times with larger gstring each time. */
4321 for (i
= 0; i
< 3; i
++)
4323 n
= font
->driver
->shape (gstring
);
4326 gstring
= larger_vector (gstring
,
4327 LGSTRING_GLYPH_LEN (gstring
), -1);
4329 if (i
== 3 || XINT (n
) == 0)
4331 if (XINT (n
) < LGSTRING_GLYPH_LEN (gstring
))
4332 LGSTRING_SET_GLYPH (gstring
, XINT (n
), Qnil
);
4334 /* Check FROM_IDX and TO_IDX of each GLYPH in GSTRING to assure that
4335 GLYPHS covers all characters (except for the last few ones) in
4336 GSTRING. More formally, provided that NCHARS is the number of
4337 characters in GSTRING and GLYPHS[i] is the ith glyph, FROM_IDX
4338 and TO_IDX of each glyph must satisfy these conditions:
4340 GLYPHS[0].FROM_IDX == 0
4341 GLYPHS[i].FROM_IDX <= GLYPHS[i].TO_IDX
4342 if (GLYPHS[i].FROM_IDX == GLYPHS[i-1].FROM_IDX)
4343 ;; GLYPHS[i] and GLYPHS[i-1] belongs to the same grapheme cluster
4344 GLYPHS[i].TO_IDX == GLYPHS[i-1].TO_IDX
4346 ;; Be sure to cover all characters.
4347 GLYPHS[i].FROM_IDX == GLYPHS[i-1].TO_IDX + 1 */
4348 glyph
= LGSTRING_GLYPH (gstring
, 0);
4349 from
= LGLYPH_FROM (glyph
);
4350 to
= LGLYPH_TO (glyph
);
4351 if (from
!= 0 || to
< from
)
4353 for (i
= 1; i
< LGSTRING_GLYPH_LEN (gstring
); i
++)
4355 glyph
= LGSTRING_GLYPH (gstring
, i
);
4358 if (! (LGLYPH_FROM (glyph
) <= LGLYPH_TO (glyph
)
4359 && (LGLYPH_FROM (glyph
) == from
4360 ? LGLYPH_TO (glyph
) == to
4361 : LGLYPH_FROM (glyph
) == to
+ 1)))
4363 from
= LGLYPH_FROM (glyph
);
4364 to
= LGLYPH_TO (glyph
);
4366 return composition_gstring_put_cache (gstring
, XINT (n
));
4372 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs
, Sfont_variation_glyphs
,
4374 doc
: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4375 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4377 VARIATION-SELECTOR is a character code of variation selection
4378 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4379 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4380 (Lisp_Object font_object
, Lisp_Object character
)
4382 unsigned variations
[256];
4387 CHECK_FONT_OBJECT (font_object
);
4388 CHECK_CHARACTER (character
);
4389 font
= XFONT_OBJECT (font_object
);
4390 if (! font
->driver
->get_variation_glyphs
)
4392 n
= font
->driver
->get_variation_glyphs (font
, XINT (character
), variations
);
4396 for (i
= 0; i
< 255; i
++)
4399 int vs
= (i
< 16 ? 0xFE00 + i
: 0xE0100 + (i
- 16));
4400 Lisp_Object code
= INTEGER_TO_CONS (variations
[i
]);
4401 val
= Fcons (Fcons (make_number (vs
), code
), val
);
4408 DEFUN ("font-drive-otf", Ffont_drive_otf
, Sfont_drive_otf
, 6, 6, 0,
4409 doc
: /* Apply OpenType features on glyph-string GSTRING-IN.
4410 OTF-FEATURES specifies which features to apply in this format:
4411 (SCRIPT LANGSYS GSUB GPOS)
4413 SCRIPT is a symbol specifying a script tag of OpenType,
4414 LANGSYS is a symbol specifying a langsys tag of OpenType,
4415 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4417 If LANGYS is nil, the default langsys is selected.
4419 The features are applied in the order they appear in the list. The
4420 symbol `*' means to apply all available features not present in this
4421 list, and the remaining features are ignored. For instance, (vatu
4422 pstf * haln) is to apply vatu and pstf in this order, then to apply
4423 all available features other than vatu, pstf, and haln.
4425 The features are applied to the glyphs in the range FROM and TO of
4426 the glyph-string GSTRING-IN.
4428 If some feature is actually applicable, the resulting glyphs are
4429 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4430 this case, the value is the number of produced glyphs.
4432 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4435 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4436 produced in GSTRING-OUT, and the value is nil.
4438 See the documentation of `composition-get-gstring' for the format of
4440 (Lisp_Object otf_features
, Lisp_Object gstring_in
, Lisp_Object from
, Lisp_Object to
, Lisp_Object gstring_out
, Lisp_Object index
)
4442 Lisp_Object font_object
= LGSTRING_FONT (gstring_in
);
4447 check_otf_features (otf_features
);
4448 CHECK_FONT_OBJECT (font_object
);
4449 font
= XFONT_OBJECT (font_object
);
4450 if (! font
->driver
->otf_drive
)
4451 error ("Font backend %s can't drive OpenType GSUB table",
4452 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4453 CHECK_CONS (otf_features
);
4454 CHECK_SYMBOL (XCAR (otf_features
));
4455 val
= XCDR (otf_features
);
4456 CHECK_SYMBOL (XCAR (val
));
4457 val
= XCDR (otf_features
);
4460 len
= check_gstring (gstring_in
);
4461 CHECK_VECTOR (gstring_out
);
4462 CHECK_NATNUM (from
);
4464 CHECK_NATNUM (index
);
4466 if (XINT (from
) >= XINT (to
) || XINT (to
) > len
)
4467 args_out_of_range_3 (from
, to
, make_number (len
));
4468 if (XINT (index
) >= ASIZE (gstring_out
))
4469 args_out_of_range (index
, make_number (ASIZE (gstring_out
)));
4470 num
= font
->driver
->otf_drive (font
, otf_features
,
4471 gstring_in
, XINT (from
), XINT (to
),
4472 gstring_out
, XINT (index
), 0);
4475 return make_number (num
);
4478 DEFUN ("font-otf-alternates", Ffont_otf_alternates
, Sfont_otf_alternates
,
4480 doc
: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4481 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4483 (SCRIPT LANGSYS FEATURE ...)
4484 See the documentation of `font-drive-otf' for more detail.
4486 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4487 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4488 character code corresponding to the glyph or nil if there's no
4489 corresponding character. */)
4490 (Lisp_Object font_object
, Lisp_Object character
, Lisp_Object otf_features
)
4493 Lisp_Object gstring_in
, gstring_out
, g
;
4494 Lisp_Object alternates
;
4497 CHECK_FONT_GET_OBJECT (font_object
, font
);
4498 if (! font
->driver
->otf_drive
)
4499 error ("Font backend %s can't drive OpenType GSUB table",
4500 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4501 CHECK_CHARACTER (character
);
4502 CHECK_CONS (otf_features
);
4504 gstring_in
= Ffont_make_gstring (font_object
, make_number (1));
4505 g
= LGSTRING_GLYPH (gstring_in
, 0);
4506 LGLYPH_SET_CHAR (g
, XINT (character
));
4507 gstring_out
= Ffont_make_gstring (font_object
, make_number (10));
4508 while ((num
= font
->driver
->otf_drive (font
, otf_features
, gstring_in
, 0, 1,
4509 gstring_out
, 0, 1)) < 0)
4510 gstring_out
= Ffont_make_gstring (font_object
,
4511 make_number (ASIZE (gstring_out
) * 2));
4513 for (i
= 0; i
< num
; i
++)
4515 Lisp_Object g
= LGSTRING_GLYPH (gstring_out
, i
);
4516 int c
= LGLYPH_CHAR (g
);
4517 unsigned code
= LGLYPH_CODE (g
);
4519 alternates
= Fcons (Fcons (make_number (code
),
4520 c
> 0 ? make_number (c
) : Qnil
),
4523 return Fnreverse (alternates
);
4529 DEFUN ("open-font", Fopen_font
, Sopen_font
, 1, 3, 0,
4530 doc
: /* Open FONT-ENTITY. */)
4531 (Lisp_Object font_entity
, Lisp_Object size
, Lisp_Object frame
)
4535 CHECK_FONT_ENTITY (font_entity
);
4537 frame
= selected_frame
;
4538 CHECK_LIVE_FRAME (frame
);
4541 isize
= XINT (AREF (font_entity
, FONT_SIZE_INDEX
));
4544 CHECK_NUMBER_OR_FLOAT (size
);
4546 isize
= POINT_TO_PIXEL (XFLOAT_DATA (size
), XFRAME (frame
)->resy
);
4548 isize
= XINT (size
);
4549 if (! (INT_MIN
<= isize
&& isize
<= INT_MAX
))
4550 args_out_of_range (font_entity
, size
);
4554 return font_open_entity (XFRAME (frame
), font_entity
, isize
);
4557 DEFUN ("close-font", Fclose_font
, Sclose_font
, 1, 2, 0,
4558 doc
: /* Close FONT-OBJECT. */)
4559 (Lisp_Object font_object
, Lisp_Object frame
)
4561 CHECK_FONT_OBJECT (font_object
);
4563 frame
= selected_frame
;
4564 CHECK_LIVE_FRAME (frame
);
4565 font_close_object (XFRAME (frame
), font_object
);
4569 DEFUN ("query-font", Fquery_font
, Squery_font
, 1, 1, 0,
4570 doc
: /* Return information about FONT-OBJECT.
4571 The value is a vector:
4572 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4575 NAME is the font name, a string (or nil if the font backend doesn't
4578 FILENAME is the font file name, a string (or nil if the font backend
4579 doesn't provide a file name).
4581 PIXEL-SIZE is a pixel size by which the font is opened.
4583 SIZE is a maximum advance width of the font in pixels.
4585 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4588 CAPABILITY is a list whose first element is a symbol representing the
4589 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4590 remaining elements describe the details of the font capability.
4592 If the font is OpenType font, the form of the list is
4593 \(opentype GSUB GPOS)
4594 where GSUB shows which "GSUB" features the font supports, and GPOS
4595 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4596 lists of the format:
4597 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4599 If the font is not OpenType font, currently the length of the form is
4602 SCRIPT is a symbol representing OpenType script tag.
4604 LANGSYS is a symbol representing OpenType langsys tag, or nil
4605 representing the default langsys.
4607 FEATURE is a symbol representing OpenType feature tag.
4609 If the font is not OpenType font, CAPABILITY is nil. */)
4610 (Lisp_Object font_object
)
4615 CHECK_FONT_GET_OBJECT (font_object
, font
);
4617 val
= Fmake_vector (make_number (9), Qnil
);
4618 ASET (val
, 0, AREF (font_object
, FONT_NAME_INDEX
));
4619 ASET (val
, 1, AREF (font_object
, FONT_FILE_INDEX
));
4620 ASET (val
, 2, make_number (font
->pixel_size
));
4621 ASET (val
, 3, make_number (font
->max_width
));
4622 ASET (val
, 4, make_number (font
->ascent
));
4623 ASET (val
, 5, make_number (font
->descent
));
4624 ASET (val
, 6, make_number (font
->space_width
));
4625 ASET (val
, 7, make_number (font
->average_width
));
4626 if (font
->driver
->otf_capability
)
4627 ASET (val
, 8, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
4631 DEFUN ("font-get-glyphs", Ffont_get_glyphs
, Sfont_get_glyphs
, 3, 4, 0,
4633 /* Return a vector of FONT-OBJECT's glyphs for the specified characters.
4634 FROM and TO are positions (integers or markers) specifying a region
4635 of the current buffer.
4636 If the optional fourth arg OBJECT is not nil, it is a string or a
4637 vector containing the target characters.
4639 Each element is a vector containing information of a glyph in this format:
4640 [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
4642 FROM is an index numbers of a character the glyph corresponds to.
4643 TO is the same as FROM.
4644 C is the character of the glyph.
4645 CODE is the glyph-code of C in FONT-OBJECT.
4646 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
4647 ADJUSTMENT is always nil.
4648 If FONT-OBJECT doesn't have a glyph for a character,
4649 the corresponding element is nil. */)
4650 (Lisp_Object font_object
, Lisp_Object from
, Lisp_Object to
,
4655 Lisp_Object
*chars
, vec
;
4658 CHECK_FONT_GET_OBJECT (font_object
, font
);
4661 ptrdiff_t charpos
, bytepos
;
4663 validate_region (&from
, &to
);
4666 len
= XFASTINT (to
) - XFASTINT (from
);
4667 SAFE_ALLOCA_LISP (chars
, len
);
4668 charpos
= XFASTINT (from
);
4669 bytepos
= CHAR_TO_BYTE (charpos
);
4670 for (i
= 0; charpos
< XFASTINT (to
); i
++)
4673 FETCH_CHAR_ADVANCE (c
, charpos
, bytepos
);
4674 chars
[i
] = make_number (c
);
4677 else if (STRINGP (object
))
4679 const unsigned char *p
;
4681 CHECK_NUMBER (from
);
4683 if (XINT (from
) < 0 || XINT (from
) > XINT (to
)
4684 || XINT (to
) > SCHARS (object
))
4685 args_out_of_range_3 (object
, from
, to
);
4688 len
= XFASTINT (to
) - XFASTINT (from
);
4689 SAFE_ALLOCA_LISP (chars
, len
);
4691 if (STRING_MULTIBYTE (object
))
4692 for (i
= 0; i
< len
; i
++)
4694 int c
= STRING_CHAR_ADVANCE (p
);
4695 chars
[i
] = make_number (c
);
4698 for (i
= 0; i
< len
; i
++)
4699 chars
[i
] = make_number (p
[i
]);
4703 CHECK_VECTOR (object
);
4704 CHECK_NUMBER (from
);
4706 if (XINT (from
) < 0 || XINT (from
) > XINT (to
)
4707 || XINT (to
) > ASIZE (object
))
4708 args_out_of_range_3 (object
, from
, to
);
4711 len
= XFASTINT (to
) - XFASTINT (from
);
4712 for (i
= 0; i
< len
; i
++)
4714 Lisp_Object elt
= AREF (object
, XFASTINT (from
) + i
);
4715 CHECK_CHARACTER (elt
);
4717 chars
= aref_addr (object
, XFASTINT (from
));
4720 vec
= Fmake_vector (make_number (len
), Qnil
);
4721 for (i
= 0; i
< len
; i
++)
4724 int c
= XFASTINT (chars
[i
]);
4726 struct font_metrics metrics
;
4728 code
= font
->driver
->encode_char (font
, c
);
4729 if (code
== FONT_INVALID_CODE
)
4731 g
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
4732 LGLYPH_SET_FROM (g
, i
);
4733 LGLYPH_SET_TO (g
, i
);
4734 LGLYPH_SET_CHAR (g
, c
);
4735 LGLYPH_SET_CODE (g
, code
);
4736 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4737 LGLYPH_SET_WIDTH (g
, metrics
.width
);
4738 LGLYPH_SET_LBEARING (g
, metrics
.lbearing
);
4739 LGLYPH_SET_RBEARING (g
, metrics
.rbearing
);
4740 LGLYPH_SET_ASCENT (g
, metrics
.ascent
);
4741 LGLYPH_SET_DESCENT (g
, metrics
.descent
);
4744 if (! VECTORP (object
))
4749 DEFUN ("font-match-p", Ffont_match_p
, Sfont_match_p
, 2, 2, 0,
4750 doc
: /* Return t if and only if font-spec SPEC matches with FONT.
4751 FONT is a font-spec, font-entity, or font-object. */)
4752 (Lisp_Object spec
, Lisp_Object font
)
4754 CHECK_FONT_SPEC (spec
);
4757 return (font_match_p (spec
, font
) ? Qt
: Qnil
);
4760 DEFUN ("font-at", Ffont_at
, Sfont_at
, 1, 3, 0,
4761 doc
: /* Return a font-object for displaying a character at POSITION.
4762 Optional second arg WINDOW, if non-nil, is a window displaying
4763 the current buffer. It defaults to the currently selected window.
4764 Optional third arg STRING, if non-nil, is a string containing the target
4765 character at index specified by POSITION. */)
4766 (Lisp_Object position
, Lisp_Object window
, Lisp_Object string
)
4772 window
= selected_window
;
4773 CHECK_LIVE_WINDOW (window
);
4774 w
= XWINDOW (window
);
4777 if (XBUFFER (w
->buffer
) != current_buffer
)
4778 error ("Specified window is not displaying the current buffer.");
4779 CHECK_NUMBER_COERCE_MARKER (position
);
4780 if (! (BEGV
<= XINT (position
) && XINT (position
) < ZV
))
4781 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
4782 pos
= XINT (position
);
4786 CHECK_NUMBER (position
);
4787 CHECK_STRING (string
);
4788 if (! (0 <= XINT (position
) && XINT (position
) < SCHARS (string
)))
4789 args_out_of_range (string
, position
);
4790 pos
= XINT (position
);
4793 return font_at (-1, pos
, NULL
, w
, string
);
4797 DEFUN ("draw-string", Fdraw_string
, Sdraw_string
, 2, 2, 0,
4798 doc
: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4799 The value is a number of glyphs drawn.
4800 Type C-l to recover what previously shown. */)
4801 (Lisp_Object font_object
, Lisp_Object string
)
4803 Lisp_Object frame
= selected_frame
;
4804 FRAME_PTR f
= XFRAME (frame
);
4810 CHECK_FONT_GET_OBJECT (font_object
, font
);
4811 CHECK_STRING (string
);
4812 len
= SCHARS (string
);
4813 code
= alloca (sizeof (unsigned) * len
);
4814 for (i
= 0; i
< len
; i
++)
4816 Lisp_Object ch
= Faref (string
, make_number (i
));
4820 code
[i
] = font
->driver
->encode_char (font
, c
);
4821 if (code
[i
] == FONT_INVALID_CODE
)
4824 face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4826 if (font
->driver
->prepare_face
)
4827 font
->driver
->prepare_face (f
, face
);
4828 width
= font
->driver
->text_extents (font
, code
, i
, NULL
);
4829 len
= font
->driver
->draw_text (f
, face
, 0, font
->ascent
, code
, i
, width
);
4830 if (font
->driver
->done_face
)
4831 font
->driver
->done_face (f
, face
);
4833 return make_number (len
);
4837 #endif /* FONT_DEBUG */
4839 #ifdef HAVE_WINDOW_SYSTEM
4841 DEFUN ("font-info", Ffont_info
, Sfont_info
, 1, 2, 0,
4842 doc
: /* Return information about a font named NAME on frame FRAME.
4843 If FRAME is omitted or nil, use the selected frame.
4844 The returned value is a vector of OPENED-NAME, FULL-NAME, SIZE,
4845 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4847 OPENED-NAME is the name used for opening the font,
4848 FULL-NAME is the full name of the font,
4849 SIZE is the pixelsize of the font,
4850 HEIGHT is the pixel-height of the font (i.e ascent + descent),
4851 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4852 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4853 how to compose characters.
4854 If the named font is not yet loaded, return nil. */)
4855 (Lisp_Object name
, Lisp_Object frame
)
4860 Lisp_Object font_object
;
4862 (*check_window_system_func
) ();
4865 CHECK_STRING (name
);
4867 frame
= selected_frame
;
4868 CHECK_LIVE_FRAME (frame
);
4873 int fontset
= fs_query_fontset (name
, 0);
4876 name
= fontset_ascii (fontset
);
4877 font_object
= font_open_by_name (f
, name
);
4879 else if (FONT_OBJECT_P (name
))
4881 else if (FONT_ENTITY_P (name
))
4882 font_object
= font_open_entity (f
, name
, 0);
4885 struct face
*face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4886 Lisp_Object entity
= font_matching_entity (f
, face
->lface
, name
);
4888 font_object
= ! NILP (entity
) ? font_open_entity (f
, entity
, 0) : Qnil
;
4890 if (NILP (font_object
))
4892 font
= XFONT_OBJECT (font_object
);
4894 info
= Fmake_vector (make_number (7), Qnil
);
4895 ASET (info
, 0, AREF (font_object
, FONT_NAME_INDEX
));
4896 ASET (info
, 1, AREF (font_object
, FONT_FULLNAME_INDEX
));
4897 ASET (info
, 2, make_number (font
->pixel_size
));
4898 ASET (info
, 3, make_number (font
->height
));
4899 ASET (info
, 4, make_number (font
->baseline_offset
));
4900 ASET (info
, 5, make_number (font
->relative_compose
));
4901 ASET (info
, 6, make_number (font
->default_ascent
));
4904 /* As font_object is still in FONT_OBJLIST of the entity, we can't
4905 close it now. Perhaps, we should manage font-objects
4906 by `reference-count'. */
4907 font_close_object (f
, font_object
);
4914 #define BUILD_STYLE_TABLE(TBL) \
4915 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
4918 build_style_table (const struct table_entry
*entry
, int nelement
)
4921 Lisp_Object table
, elt
;
4923 table
= Fmake_vector (make_number (nelement
), Qnil
);
4924 for (i
= 0; i
< nelement
; i
++)
4926 for (j
= 0; entry
[i
].names
[j
]; j
++);
4927 elt
= Fmake_vector (make_number (j
+ 1), Qnil
);
4928 ASET (elt
, 0, make_number (entry
[i
].numeric
));
4929 for (j
= 0; entry
[i
].names
[j
]; j
++)
4930 ASET (elt
, j
+ 1, intern_c_string (entry
[i
].names
[j
]));
4931 ASET (table
, i
, elt
);
4936 /* The deferred font-log data of the form [ACTION ARG RESULT].
4937 If ACTION is not nil, that is added to the log when font_add_log is
4938 called next time. At that time, ACTION is set back to nil. */
4939 static Lisp_Object Vfont_log_deferred
;
4941 /* Prepend the font-related logging data in Vfont_log if it is not
4942 `t'. ACTION describes a kind of font-related action (e.g. listing,
4943 opening), ARG is the argument for the action, and RESULT is the
4944 result of the action. */
4946 font_add_log (const char *action
, Lisp_Object arg
, Lisp_Object result
)
4951 if (EQ (Vfont_log
, Qt
))
4953 if (STRINGP (AREF (Vfont_log_deferred
, 0)))
4955 char *str
= SSDATA (AREF (Vfont_log_deferred
, 0));
4957 ASET (Vfont_log_deferred
, 0, Qnil
);
4958 font_add_log (str
, AREF (Vfont_log_deferred
, 1),
4959 AREF (Vfont_log_deferred
, 2));
4964 Lisp_Object tail
, elt
;
4965 Lisp_Object equalstr
= build_string ("=");
4967 val
= Ffont_xlfd_name (arg
, Qt
);
4968 for (tail
= AREF (arg
, FONT_EXTRA_INDEX
); CONSP (tail
);
4972 if (EQ (XCAR (elt
), QCscript
)
4973 && SYMBOLP (XCDR (elt
)))
4974 val
= concat3 (val
, SYMBOL_NAME (QCscript
),
4975 concat2 (equalstr
, SYMBOL_NAME (XCDR (elt
))));
4976 else if (EQ (XCAR (elt
), QClang
)
4977 && SYMBOLP (XCDR (elt
)))
4978 val
= concat3 (val
, SYMBOL_NAME (QClang
),
4979 concat2 (equalstr
, SYMBOL_NAME (XCDR (elt
))));
4980 else if (EQ (XCAR (elt
), QCotf
)
4981 && CONSP (XCDR (elt
)) && SYMBOLP (XCAR (XCDR (elt
))))
4982 val
= concat3 (val
, SYMBOL_NAME (QCotf
),
4984 SYMBOL_NAME (XCAR (XCDR (elt
)))));
4990 && VECTORP (XCAR (result
))
4991 && ASIZE (XCAR (result
)) > 0
4992 && FONTP (AREF (XCAR (result
), 0)))
4993 result
= font_vconcat_entity_vectors (result
);
4996 val
= Ffont_xlfd_name (result
, Qt
);
4997 if (! FONT_SPEC_P (result
))
4998 val
= concat3 (SYMBOL_NAME (AREF (result
, FONT_TYPE_INDEX
)),
4999 build_string (":"), val
);
5002 else if (CONSP (result
))
5005 result
= Fcopy_sequence (result
);
5006 for (tail
= result
; CONSP (tail
); tail
= XCDR (tail
))
5010 val
= Ffont_xlfd_name (val
, Qt
);
5011 XSETCAR (tail
, val
);
5014 else if (VECTORP (result
))
5016 result
= Fcopy_sequence (result
);
5017 for (i
= 0; i
< ASIZE (result
); i
++)
5019 val
= AREF (result
, i
);
5021 val
= Ffont_xlfd_name (val
, Qt
);
5022 ASET (result
, i
, val
);
5025 Vfont_log
= Fcons (list3 (intern (action
), arg
, result
), Vfont_log
);
5028 /* Record a font-related logging data to be added to Vfont_log when
5029 font_add_log is called next time. ACTION, ARG, RESULT are the same
5033 font_deferred_log (const char *action
, Lisp_Object arg
, Lisp_Object result
)
5035 if (EQ (Vfont_log
, Qt
))
5037 ASET (Vfont_log_deferred
, 0, build_string (action
));
5038 ASET (Vfont_log_deferred
, 1, arg
);
5039 ASET (Vfont_log_deferred
, 2, result
);
5045 sort_shift_bits
[FONT_TYPE_INDEX
] = 0;
5046 sort_shift_bits
[FONT_SLANT_INDEX
] = 2;
5047 sort_shift_bits
[FONT_WEIGHT_INDEX
] = 9;
5048 sort_shift_bits
[FONT_SIZE_INDEX
] = 16;
5049 sort_shift_bits
[FONT_WIDTH_INDEX
] = 23;
5050 /* Note that the other elements in sort_shift_bits are not used. */
5052 staticpro (&font_charset_alist
);
5053 font_charset_alist
= Qnil
;
5055 DEFSYM (Qopentype
, "opentype");
5057 DEFSYM (Qascii_0
, "ascii-0");
5058 DEFSYM (Qiso8859_1
, "iso8859-1");
5059 DEFSYM (Qiso10646_1
, "iso10646-1");
5060 DEFSYM (Qunicode_bmp
, "unicode-bmp");
5061 DEFSYM (Qunicode_sip
, "unicode-sip");
5065 DEFSYM (QCotf
, ":otf");
5066 DEFSYM (QClang
, ":lang");
5067 DEFSYM (QCscript
, ":script");
5068 DEFSYM (QCantialias
, ":antialias");
5070 DEFSYM (QCfoundry
, ":foundry");
5071 DEFSYM (QCadstyle
, ":adstyle");
5072 DEFSYM (QCregistry
, ":registry");
5073 DEFSYM (QCspacing
, ":spacing");
5074 DEFSYM (QCdpi
, ":dpi");
5075 DEFSYM (QCscalable
, ":scalable");
5076 DEFSYM (QCavgwidth
, ":avgwidth");
5077 DEFSYM (QCfont_entity
, ":font-entity");
5078 DEFSYM (QCfc_unknown_spec
, ":fc-unknown-spec");
5088 DEFSYM (QCuser_spec
, "user-spec");
5090 staticpro (&scratch_font_spec
);
5091 scratch_font_spec
= Ffont_spec (0, NULL
);
5092 staticpro (&scratch_font_prefer
);
5093 scratch_font_prefer
= Ffont_spec (0, NULL
);
5095 staticpro (&Vfont_log_deferred
);
5096 Vfont_log_deferred
= Fmake_vector (make_number (3), Qnil
);
5100 staticpro (&otf_list
);
5102 #endif /* HAVE_LIBOTF */
5106 defsubr (&Sfont_spec
);
5107 defsubr (&Sfont_get
);
5108 #ifdef HAVE_WINDOW_SYSTEM
5109 defsubr (&Sfont_face_attributes
);
5111 defsubr (&Sfont_put
);
5112 defsubr (&Slist_fonts
);
5113 defsubr (&Sfont_family_list
);
5114 defsubr (&Sfind_font
);
5115 defsubr (&Sfont_xlfd_name
);
5116 defsubr (&Sclear_font_cache
);
5117 defsubr (&Sfont_shape_gstring
);
5118 defsubr (&Sfont_variation_glyphs
);
5120 defsubr (&Sfont_drive_otf
);
5121 defsubr (&Sfont_otf_alternates
);
5125 defsubr (&Sopen_font
);
5126 defsubr (&Sclose_font
);
5127 defsubr (&Squery_font
);
5128 defsubr (&Sfont_get_glyphs
);
5129 defsubr (&Sfont_match_p
);
5130 defsubr (&Sfont_at
);
5132 defsubr (&Sdraw_string
);
5134 #endif /* FONT_DEBUG */
5135 #ifdef HAVE_WINDOW_SYSTEM
5136 defsubr (&Sfont_info
);
5139 DEFVAR_LISP ("font-encoding-alist", Vfont_encoding_alist
,
5141 Alist of fontname patterns vs the corresponding encoding and repertory info.
5142 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5143 where ENCODING is a charset or a char-table,
5144 and REPERTORY is a charset, a char-table, or nil.
5146 If ENCODING and REPERTORY are the same, the element can have the form
5147 \(REGEXP . ENCODING).
5149 ENCODING is for converting a character to a glyph code of the font.
5150 If ENCODING is a charset, encoding a character by the charset gives
5151 the corresponding glyph code. If ENCODING is a char-table, looking up
5152 the table by a character gives the corresponding glyph code.
5154 REPERTORY specifies a repertory of characters supported by the font.
5155 If REPERTORY is a charset, all characters belonging to the charset are
5156 supported. If REPERTORY is a char-table, all characters who have a
5157 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5158 gets the repertory information by an opened font and ENCODING. */);
5159 Vfont_encoding_alist
= Qnil
;
5161 /* FIXME: These 3 vars are not quite what they appear: setq on them
5162 won't have any effect other than disconnect them from the style
5163 table used by the font display code. So we make them read-only,
5164 to avoid this confusing situation. */
5166 DEFVAR_LISP_NOPRO ("font-weight-table", Vfont_weight_table
,
5167 doc
: /* Vector of valid font weight values.
5168 Each element has the form:
5169 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5170 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5171 Vfont_weight_table
= BUILD_STYLE_TABLE (weight_table
);
5172 XSYMBOL (intern_c_string ("font-weight-table"))->constant
= 1;
5174 DEFVAR_LISP_NOPRO ("font-slant-table", Vfont_slant_table
,
5175 doc
: /* Vector of font slant symbols vs the corresponding numeric values.
5176 See `font-weight-table' for the format of the vector. */);
5177 Vfont_slant_table
= BUILD_STYLE_TABLE (slant_table
);
5178 XSYMBOL (intern_c_string ("font-slant-table"))->constant
= 1;
5180 DEFVAR_LISP_NOPRO ("font-width-table", Vfont_width_table
,
5181 doc
: /* Alist of font width symbols vs the corresponding numeric values.
5182 See `font-weight-table' for the format of the vector. */);
5183 Vfont_width_table
= BUILD_STYLE_TABLE (width_table
);
5184 XSYMBOL (intern_c_string ("font-width-table"))->constant
= 1;
5186 staticpro (&font_style_table
);
5187 font_style_table
= Fmake_vector (make_number (3), Qnil
);
5188 ASET (font_style_table
, 0, Vfont_weight_table
);
5189 ASET (font_style_table
, 1, Vfont_slant_table
);
5190 ASET (font_style_table
, 2, Vfont_width_table
);
5192 DEFVAR_LISP ("font-log", Vfont_log
, doc
: /*
5193 *Logging list of font related actions and results.
5194 The value t means to suppress the logging.
5195 The initial value is set to nil if the environment variable
5196 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5199 #ifdef HAVE_WINDOW_SYSTEM
5200 #ifdef HAVE_FREETYPE
5202 #ifdef HAVE_X_WINDOWS
5207 #endif /* HAVE_XFT */
5208 #endif /* HAVE_X_WINDOWS */
5209 #else /* not HAVE_FREETYPE */
5210 #ifdef HAVE_X_WINDOWS
5212 #endif /* HAVE_X_WINDOWS */
5213 #endif /* not HAVE_FREETYPE */
5216 #endif /* HAVE_BDFFONT */
5219 #endif /* HAVE_NTGUI */
5222 #endif /* HAVE_NS */
5223 #endif /* HAVE_WINDOW_SYSTEM */
5229 Vfont_log
= egetenv ("EMACS_FONT_LOG") ? Qnil
: Qt
;