1 /* font.c -- "Font" primitives.
3 Copyright (C) 2006-2015 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 #define DEFAULT_ENCODING Qiso8859_1
46 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
47 static Lisp_Object font_style_table
;
49 /* Structure used for tables mapping weight, slant, and width numeric
50 values and their names. */
55 /* The first one is a valid name as a face attribute.
56 The second one (if any) is a typical name in XLFD field. */
60 /* Table of weight numeric values and their names. This table must be
61 sorted by numeric values in ascending order. */
63 static const struct table_entry weight_table
[] =
66 { 20, { "ultra-light", "ultralight" }},
67 { 40, { "extra-light", "extralight" }},
69 { 75, { "semi-light", "semilight", "demilight", "book" }},
70 { 100, { "normal", "medium", "regular", "unspecified" }},
71 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
73 { 205, { "extra-bold", "extrabold" }},
74 { 210, { "ultra-bold", "ultrabold", "black" }}
77 /* Table of slant numeric values and their names. This table must be
78 sorted by numeric values in ascending order. */
80 static const struct table_entry slant_table
[] =
82 { 0, { "reverse-oblique", "ro" }},
83 { 10, { "reverse-italic", "ri" }},
84 { 100, { "normal", "r", "unspecified" }},
85 { 200, { "italic" ,"i", "ot" }},
86 { 210, { "oblique", "o" }}
89 /* Table of width numeric values and their names. This table must be
90 sorted by numeric values in ascending order. */
92 static const struct table_entry width_table
[] =
94 { 50, { "ultra-condensed", "ultracondensed" }},
95 { 63, { "extra-condensed", "extracondensed" }},
96 { 75, { "condensed", "compressed", "narrow" }},
97 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
98 { 100, { "normal", "medium", "regular", "unspecified" }},
99 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
100 { 125, { "expanded" }},
101 { 150, { "extra-expanded", "extraexpanded" }},
102 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
105 /* Alist of font registry symbols and the corresponding charset
106 information. The information is retrieved from
107 Vfont_encoding_alist on demand.
109 Eash element has the form:
110 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
114 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
115 encodes a character code to a glyph code of a font, and
116 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
117 character is supported by a font.
119 The latter form means that the information for REGISTRY couldn't be
121 static Lisp_Object font_charset_alist
;
123 /* List of all font drivers. Each font-backend (XXXfont.c) calls
124 register_font_driver in syms_of_XXXfont to register its font-driver
126 static struct font_driver_list
*font_driver_list
;
128 #ifdef ENABLE_CHECKING
130 /* Used to catch bogus pointers in font objects. */
133 valid_font_driver (struct font_driver
*drv
)
135 Lisp_Object tail
, frame
;
136 struct font_driver_list
*fdl
;
138 for (fdl
= font_driver_list
; fdl
; fdl
= fdl
->next
)
139 if (fdl
->driver
== drv
)
141 FOR_EACH_FRAME (tail
, frame
)
142 for (fdl
= XFRAME (frame
)->font_driver_list
; fdl
; fdl
= fdl
->next
)
143 if (fdl
->driver
== drv
)
148 #endif /* ENABLE_CHECKING */
150 /* Creators of font-related Lisp object. */
153 font_make_spec (void)
155 Lisp_Object font_spec
;
156 struct font_spec
*spec
157 = ((struct font_spec
*)
158 allocate_pseudovector (VECSIZE (struct font_spec
),
159 FONT_SPEC_MAX
, FONT_SPEC_MAX
, PVEC_FONT
));
160 XSETFONT (font_spec
, spec
);
165 font_make_entity (void)
167 Lisp_Object font_entity
;
168 struct font_entity
*entity
169 = ((struct font_entity
*)
170 allocate_pseudovector (VECSIZE (struct font_entity
),
171 FONT_ENTITY_MAX
, FONT_ENTITY_MAX
, PVEC_FONT
));
172 XSETFONT (font_entity
, entity
);
176 /* Create a font-object whose structure size is SIZE. If ENTITY is
177 not nil, copy properties from ENTITY to the font-object. If
178 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
180 font_make_object (int size
, Lisp_Object entity
, int pixelsize
)
182 Lisp_Object font_object
;
184 = (struct font
*) allocate_pseudovector (size
, FONT_OBJECT_MAX
,
185 FONT_OBJECT_MAX
, PVEC_FONT
);
188 /* GC can happen before the driver is set up,
189 so avoid dangling pointer here (Bug#17771). */
191 XSETFONT (font_object
, font
);
195 for (i
= 1; i
< FONT_SPEC_MAX
; i
++)
196 font
->props
[i
] = AREF (entity
, i
);
197 if (! NILP (AREF (entity
, FONT_EXTRA_INDEX
)))
198 font
->props
[FONT_EXTRA_INDEX
]
199 = Fcopy_alist (AREF (entity
, FONT_EXTRA_INDEX
));
202 font
->props
[FONT_SIZE_INDEX
] = make_number (pixelsize
);
206 #if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS)
208 static int font_unparse_fcname (Lisp_Object
, int, char *, int);
210 /* Like above, but also set `type', `name' and `fullname' properties
214 font_build_object (int vectorsize
, Lisp_Object type
,
215 Lisp_Object entity
, double pixelsize
)
219 Lisp_Object font_object
= font_make_object (vectorsize
, entity
, pixelsize
);
221 ASET (font_object
, FONT_TYPE_INDEX
, type
);
222 len
= font_unparse_xlfd (entity
, pixelsize
, name
, sizeof name
);
224 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
225 len
= font_unparse_fcname (entity
, pixelsize
, name
, sizeof name
);
227 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
229 ASET (font_object
, FONT_FULLNAME_INDEX
,
230 AREF (font_object
, FONT_NAME_INDEX
));
234 #endif /* HAVE_XFT || HAVE_FREETYPE || HAVE_NS */
236 static int font_pixel_size (struct frame
*f
, Lisp_Object
);
237 static Lisp_Object
font_open_entity (struct frame
*, Lisp_Object
, int);
238 static Lisp_Object
font_matching_entity (struct frame
*, Lisp_Object
*,
240 static unsigned font_encode_char (Lisp_Object
, int);
242 /* Number of registered font drivers. */
243 static int num_font_drivers
;
246 /* Return a Lispy value of a font property value at STR and LEN bytes.
247 If STR is "*", return nil. If FORCE_SYMBOL, or if STR does not
248 consist entirely of one or more digits, return a symbol interned
249 from STR. Otherwise, return an integer. */
252 font_intern_prop (const char *str
, ptrdiff_t len
, bool force_symbol
)
254 ptrdiff_t i
, nbytes
, nchars
;
255 Lisp_Object tem
, name
, obarray
;
257 if (len
== 1 && *str
== '*')
259 if (!force_symbol
&& 0 < len
&& '0' <= *str
&& *str
<= '9')
261 for (i
= 1; i
< len
; i
++)
262 if (! ('0' <= str
[i
] && str
[i
] <= '9'))
269 for (n
= 0; (n
+= str
[i
++] - '0') <= MOST_POSITIVE_FIXNUM
; n
*= 10)
272 return make_number (n
);
273 if (MOST_POSITIVE_FIXNUM
/ 10 < n
)
277 xsignal1 (Qoverflow_error
, make_string (str
, len
));
281 /* This code is similar to intern function from lread.c. */
282 obarray
= check_obarray (Vobarray
);
283 parse_str_as_multibyte ((unsigned char *) str
, len
, &nchars
, &nbytes
);
284 tem
= oblookup (obarray
, str
,
285 (len
== nchars
|| len
!= nbytes
) ? len
: nchars
, len
);
288 name
= make_specified_string (str
, nchars
, len
,
289 len
!= nchars
&& len
== nbytes
);
290 return intern_driver (name
, obarray
, tem
);
293 /* Return a pixel size of font-spec SPEC on frame F. */
296 font_pixel_size (struct frame
*f
, Lisp_Object spec
)
298 #ifdef HAVE_WINDOW_SYSTEM
299 Lisp_Object size
= AREF (spec
, FONT_SIZE_INDEX
);
308 eassert (FLOATP (size
));
309 point_size
= XFLOAT_DATA (size
);
310 val
= AREF (spec
, FONT_DPI_INDEX
);
314 dpi
= FRAME_RES_Y (f
);
315 pixel_size
= POINT_TO_PIXEL (point_size
, dpi
);
323 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
324 font vector. If VAL is not valid (i.e. not registered in
325 font_style_table), return -1 if NOERROR is zero, and return a
326 proper index if NOERROR is nonzero. In that case, register VAL in
327 font_style_table if VAL is a symbol, and return the closest index if
328 VAL is an integer. */
331 font_style_to_value (enum font_property_index prop
, Lisp_Object val
,
334 Lisp_Object table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
337 CHECK_VECTOR (table
);
346 /* At first try exact match. */
347 for (i
= 0; i
< len
; i
++)
349 CHECK_VECTOR (AREF (table
, i
));
350 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
351 if (EQ (val
, AREF (AREF (table
, i
), j
)))
353 CHECK_NUMBER (AREF (AREF (table
, i
), 0));
354 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
355 | (i
<< 4) | (j
- 1));
358 /* Try also with case-folding match. */
359 s
= SSDATA (SYMBOL_NAME (val
));
360 for (i
= 0; i
< len
; i
++)
361 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
363 elt
= AREF (AREF (table
, i
), j
);
364 if (xstrcasecmp (s
, SSDATA (SYMBOL_NAME (elt
))) == 0)
366 CHECK_NUMBER (AREF (AREF (table
, i
), 0));
367 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
368 | (i
<< 4) | (j
- 1));
374 elt
= Fmake_vector (make_number (2), make_number (100));
376 ASET (font_style_table
, prop
- FONT_WEIGHT_INDEX
,
377 CALLN (Fvconcat
, table
, Fmake_vector (make_number (1), elt
)));
378 return (100 << 8) | (i
<< 4);
383 EMACS_INT numeric
= XINT (val
);
385 for (i
= 0, last_n
= -1; i
< len
; i
++)
389 CHECK_VECTOR (AREF (table
, i
));
390 CHECK_NUMBER (AREF (AREF (table
, i
), 0));
391 n
= XINT (AREF (AREF (table
, i
), 0));
393 return (n
<< 8) | (i
<< 4);
398 return ((i
== 0 || n
- numeric
< numeric
- last_n
)
399 ? (n
<< 8) | (i
<< 4): (last_n
<< 8 | ((i
- 1) << 4)));
405 return ((last_n
<< 8) | ((i
- 1) << 4));
410 font_style_symbolic (Lisp_Object font
, enum font_property_index prop
,
413 Lisp_Object val
= AREF (font
, prop
);
414 Lisp_Object table
, elt
;
419 table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
420 CHECK_VECTOR (table
);
421 i
= XINT (val
) & 0xFF;
422 eassert (((i
>> 4) & 0xF) < ASIZE (table
));
423 elt
= AREF (table
, ((i
>> 4) & 0xF));
425 eassert ((i
& 0xF) + 1 < ASIZE (elt
));
426 elt
= (for_face
? AREF (elt
, 1) : AREF (elt
, (i
& 0xF) + 1));
431 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
432 FONTNAME. ENCODING is a charset symbol that specifies the encoding
433 of the font. REPERTORY is a charset symbol or nil. */
436 find_font_encoding (Lisp_Object fontname
)
438 Lisp_Object tail
, elt
;
440 for (tail
= Vfont_encoding_alist
; CONSP (tail
); tail
= XCDR (tail
))
444 && STRINGP (XCAR (elt
))
445 && fast_string_match_ignore_case (XCAR (elt
), fontname
) >= 0
446 && (SYMBOLP (XCDR (elt
))
447 ? CHARSETP (XCDR (elt
))
448 : CONSP (XCDR (elt
)) && CHARSETP (XCAR (XCDR (elt
)))))
454 /* Return encoding charset and repertory charset for REGISTRY in
455 ENCODING and REPERTORY correspondingly. If correct information for
456 REGISTRY is available, return 0. Otherwise return -1. */
459 font_registry_charsets (Lisp_Object registry
, struct charset
**encoding
, struct charset
**repertory
)
462 int encoding_id
, repertory_id
;
464 val
= Fassoc_string (registry
, font_charset_alist
, Qt
);
470 encoding_id
= XINT (XCAR (val
));
471 repertory_id
= XINT (XCDR (val
));
475 val
= find_font_encoding (SYMBOL_NAME (registry
));
476 if (SYMBOLP (val
) && CHARSETP (val
))
478 encoding_id
= repertory_id
= XINT (CHARSET_SYMBOL_ID (val
));
480 else if (CONSP (val
))
482 if (! CHARSETP (XCAR (val
)))
484 encoding_id
= XINT (CHARSET_SYMBOL_ID (XCAR (val
)));
485 if (NILP (XCDR (val
)))
489 if (! CHARSETP (XCDR (val
)))
491 repertory_id
= XINT (CHARSET_SYMBOL_ID (XCDR (val
)));
496 val
= Fcons (make_number (encoding_id
), make_number (repertory_id
));
498 = nconc2 (font_charset_alist
, list1 (Fcons (registry
, val
)));
502 *encoding
= CHARSET_FROM_ID (encoding_id
);
504 *repertory
= repertory_id
>= 0 ? CHARSET_FROM_ID (repertory_id
) : NULL
;
509 = nconc2 (font_charset_alist
, list1 (Fcons (registry
, Qnil
)));
514 /* Font property value validators. See the comment of
515 font_property_table for the meaning of the arguments. */
517 static Lisp_Object
font_prop_validate (int, Lisp_Object
, Lisp_Object
);
518 static Lisp_Object
font_prop_validate_symbol (Lisp_Object
, Lisp_Object
);
519 static Lisp_Object
font_prop_validate_style (Lisp_Object
, Lisp_Object
);
520 static Lisp_Object
font_prop_validate_non_neg (Lisp_Object
, Lisp_Object
);
521 static Lisp_Object
font_prop_validate_spacing (Lisp_Object
, Lisp_Object
);
522 static int get_font_prop_index (Lisp_Object
);
525 font_prop_validate_symbol (Lisp_Object prop
, Lisp_Object val
)
528 val
= Fintern (val
, Qnil
);
531 else if (EQ (prop
, QCregistry
))
532 val
= Fintern (Fdowncase (SYMBOL_NAME (val
)), Qnil
);
538 font_prop_validate_style (Lisp_Object style
, Lisp_Object val
)
540 enum font_property_index prop
= (EQ (style
, QCweight
) ? FONT_WEIGHT_INDEX
541 : EQ (style
, QCslant
) ? FONT_SLANT_INDEX
545 EMACS_INT n
= XINT (val
);
546 CHECK_VECTOR (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
));
548 >= ASIZE (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
)))
552 Lisp_Object elt
= AREF (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
), (n
>> 4) & 0xF);
555 if ((n
& 0xF) + 1 >= ASIZE (elt
))
559 CHECK_NUMBER (AREF (elt
, 0));
560 if (XINT (AREF (elt
, 0)) != (n
>> 8))
565 else if (SYMBOLP (val
))
567 int n
= font_style_to_value (prop
, val
, 0);
569 val
= n
>= 0 ? make_number (n
) : Qerror
;
577 font_prop_validate_non_neg (Lisp_Object prop
, Lisp_Object val
)
579 return (NATNUMP (val
) || (FLOATP (val
) && XFLOAT_DATA (val
) >= 0)
584 font_prop_validate_spacing (Lisp_Object prop
, Lisp_Object val
)
586 if (NILP (val
) || (NATNUMP (val
) && XINT (val
) <= FONT_SPACING_CHARCELL
))
588 if (SYMBOLP (val
) && SBYTES (SYMBOL_NAME (val
)) == 1)
590 char spacing
= SDATA (SYMBOL_NAME (val
))[0];
592 if (spacing
== 'c' || spacing
== 'C')
593 return make_number (FONT_SPACING_CHARCELL
);
594 if (spacing
== 'm' || spacing
== 'M')
595 return make_number (FONT_SPACING_MONO
);
596 if (spacing
== 'p' || spacing
== 'P')
597 return make_number (FONT_SPACING_PROPORTIONAL
);
598 if (spacing
== 'd' || spacing
== 'D')
599 return make_number (FONT_SPACING_DUAL
);
605 font_prop_validate_otf (Lisp_Object prop
, Lisp_Object val
)
607 Lisp_Object tail
, tmp
;
610 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
611 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
612 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
615 if (! SYMBOLP (XCAR (val
)))
620 if (! CONSP (tail
) || ! SYMBOLP (XCAR (val
)))
622 for (i
= 0; i
< 2; i
++)
629 for (tmp
= XCAR (tail
); CONSP (tmp
); tmp
= XCDR (tmp
))
630 if (! SYMBOLP (XCAR (tmp
)))
638 /* Structure of known font property keys and validator of the
642 /* Index of the key symbol. */
644 /* Function to validate PROP's value VAL, or NULL if any value is
645 ok. The value is VAL or its regularized value if VAL is valid,
646 and Qerror if not. */
647 Lisp_Object (*validator
) (Lisp_Object prop
, Lisp_Object val
);
648 } font_property_table
[] =
649 { { SYMBOL_INDEX (QCtype
), font_prop_validate_symbol
},
650 { SYMBOL_INDEX (QCfoundry
), font_prop_validate_symbol
},
651 { SYMBOL_INDEX (QCfamily
), font_prop_validate_symbol
},
652 { SYMBOL_INDEX (QCadstyle
), font_prop_validate_symbol
},
653 { SYMBOL_INDEX (QCregistry
), font_prop_validate_symbol
},
654 { SYMBOL_INDEX (QCweight
), font_prop_validate_style
},
655 { SYMBOL_INDEX (QCslant
), font_prop_validate_style
},
656 { SYMBOL_INDEX (QCwidth
), font_prop_validate_style
},
657 { SYMBOL_INDEX (QCsize
), font_prop_validate_non_neg
},
658 { SYMBOL_INDEX (QCdpi
), font_prop_validate_non_neg
},
659 { SYMBOL_INDEX (QCspacing
), font_prop_validate_spacing
},
660 { SYMBOL_INDEX (QCavgwidth
), font_prop_validate_non_neg
},
661 /* The order of the above entries must match with enum
662 font_property_index. */
663 { SYMBOL_INDEX (QClang
), font_prop_validate_symbol
},
664 { SYMBOL_INDEX (QCscript
), font_prop_validate_symbol
},
665 { SYMBOL_INDEX (QCotf
), font_prop_validate_otf
}
668 /* Return an index number of font property KEY or -1 if KEY is not an
669 already known property. */
672 get_font_prop_index (Lisp_Object key
)
676 for (i
= 0; i
< ARRAYELTS (font_property_table
); i
++)
677 if (EQ (key
, builtin_lisp_symbol (font_property_table
[i
].key
)))
682 /* Validate the font property. The property key is specified by the
683 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
684 signal an error. The value is VAL or the regularized one. */
687 font_prop_validate (int idx
, Lisp_Object prop
, Lisp_Object val
)
689 Lisp_Object validated
;
694 prop
= builtin_lisp_symbol (font_property_table
[idx
].key
);
697 idx
= get_font_prop_index (prop
);
701 validated
= (font_property_table
[idx
].validator
) (prop
, val
);
702 if (EQ (validated
, Qerror
))
703 signal_error ("invalid font property", Fcons (prop
, val
));
708 /* Store VAL as a value of extra font property PROP in FONT while
709 keeping the sorting order. Don't check the validity of VAL. */
712 font_put_extra (Lisp_Object font
, Lisp_Object prop
, Lisp_Object val
)
714 Lisp_Object extra
= AREF (font
, FONT_EXTRA_INDEX
);
715 Lisp_Object slot
= (NILP (extra
) ? Qnil
: assq_no_quit (prop
, extra
));
719 Lisp_Object prev
= Qnil
;
722 && NILP (Fstring_lessp (prop
, XCAR (XCAR (extra
)))))
723 prev
= extra
, extra
= XCDR (extra
);
726 ASET (font
, FONT_EXTRA_INDEX
, Fcons (Fcons (prop
, val
), extra
));
728 XSETCDR (prev
, Fcons (Fcons (prop
, val
), extra
));
734 ASET (font
, FONT_EXTRA_INDEX
, Fdelq (slot
, extra
));
739 /* Font name parser and unparser. */
741 static int parse_matrix (const char *);
742 static int font_expand_wildcards (Lisp_Object
*, int);
743 static int font_parse_name (char *, ptrdiff_t, Lisp_Object
);
745 /* An enumerator for each field of an XLFD font name. */
746 enum xlfd_field_index
765 /* An enumerator for mask bit corresponding to each XLFD field. */
768 XLFD_FOUNDRY_MASK
= 0x0001,
769 XLFD_FAMILY_MASK
= 0x0002,
770 XLFD_WEIGHT_MASK
= 0x0004,
771 XLFD_SLANT_MASK
= 0x0008,
772 XLFD_SWIDTH_MASK
= 0x0010,
773 XLFD_ADSTYLE_MASK
= 0x0020,
774 XLFD_PIXEL_MASK
= 0x0040,
775 XLFD_POINT_MASK
= 0x0080,
776 XLFD_RESX_MASK
= 0x0100,
777 XLFD_RESY_MASK
= 0x0200,
778 XLFD_SPACING_MASK
= 0x0400,
779 XLFD_AVGWIDTH_MASK
= 0x0800,
780 XLFD_REGISTRY_MASK
= 0x1000,
781 XLFD_ENCODING_MASK
= 0x2000
785 /* Parse P pointing to the pixel/point size field of the form
786 `[A B C D]' which specifies a transformation matrix:
792 by which all glyphs of the font are transformed. The spec says
793 that scalar value N for the pixel/point size is equivalent to:
794 A = N * resx/resy, B = C = 0, D = N.
796 Return the scalar value N if the form is valid. Otherwise return
800 parse_matrix (const char *p
)
806 for (i
= 0, p
++; i
< 4 && *p
&& *p
!= ']'; i
++)
809 matrix
[i
] = - strtod (p
+ 1, &end
);
811 matrix
[i
] = strtod (p
, &end
);
814 return (i
== 4 ? (int) matrix
[3] : -1);
817 /* Expand a wildcard field in FIELD (the first N fields are filled) to
818 multiple fields to fill in all 14 XLFD fields while restricting a
819 field position by its contents. */
822 font_expand_wildcards (Lisp_Object
*field
, int n
)
825 Lisp_Object tmp
[XLFD_LAST_INDEX
];
826 /* Array of information about where this element can go. Nth
827 element is for Nth element of FIELD. */
829 /* Minimum possible field. */
831 /* Maximum possible field. */
833 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
835 } range
[XLFD_LAST_INDEX
];
837 int range_from
, range_to
;
840 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
841 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
842 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
843 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
844 | XLFD_AVGWIDTH_MASK)
845 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
847 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
848 field. The value is shifted to left one bit by one in the
850 for (i
= 0, range_mask
= 0; i
<= 14 - n
; i
++)
851 range_mask
= (range_mask
<< 1) | 1;
853 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
854 position-based restriction for FIELD[I]. */
855 for (i
= 0, range_from
= 0, range_to
= 14 - n
; i
< n
;
856 i
++, range_from
++, range_to
++, range_mask
<<= 1)
858 Lisp_Object val
= field
[i
];
864 range
[i
].from
= range_from
;
865 range
[i
].to
= range_to
;
866 range
[i
].mask
= range_mask
;
870 /* The triplet FROM, TO, and MASK is a value-based
871 restriction for FIELD[I]. */
877 EMACS_INT numeric
= XINT (val
);
880 from
= to
= XLFD_ENCODING_INDEX
,
881 mask
= XLFD_ENCODING_MASK
;
882 else if (numeric
== 0)
883 from
= XLFD_PIXEL_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
884 mask
= XLFD_PIXEL_MASK
| XLFD_LARGENUM_MASK
;
885 else if (numeric
<= 48)
886 from
= to
= XLFD_PIXEL_INDEX
,
887 mask
= XLFD_PIXEL_MASK
;
889 from
= XLFD_POINT_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
890 mask
= XLFD_LARGENUM_MASK
;
892 else if (SBYTES (SYMBOL_NAME (val
)) == 0)
893 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ADSTYLE_INDEX
,
894 mask
= XLFD_NULL_MASK
;
896 from
= to
= XLFD_FOUNDRY_INDEX
, mask
= XLFD_FOUNDRY_MASK
;
899 Lisp_Object name
= SYMBOL_NAME (val
);
901 if (SDATA (name
)[SBYTES (name
) - 1] == '*')
902 from
= XLFD_REGISTRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
903 mask
= XLFD_REGENC_MASK
;
905 from
= to
= XLFD_ENCODING_INDEX
,
906 mask
= XLFD_ENCODING_MASK
;
908 else if (range_from
<= XLFD_WEIGHT_INDEX
909 && range_to
>= XLFD_WEIGHT_INDEX
910 && FONT_WEIGHT_NAME_NUMERIC (val
) >= 0)
911 from
= to
= XLFD_WEIGHT_INDEX
, mask
= XLFD_WEIGHT_MASK
;
912 else if (range_from
<= XLFD_SLANT_INDEX
913 && range_to
>= XLFD_SLANT_INDEX
914 && FONT_SLANT_NAME_NUMERIC (val
) >= 0)
915 from
= to
= XLFD_SLANT_INDEX
, mask
= XLFD_SLANT_MASK
;
916 else if (range_from
<= XLFD_SWIDTH_INDEX
917 && range_to
>= XLFD_SWIDTH_INDEX
918 && FONT_WIDTH_NAME_NUMERIC (val
) >= 0)
919 from
= to
= XLFD_SWIDTH_INDEX
, mask
= XLFD_SWIDTH_MASK
;
922 if (EQ (val
, Qc
) || EQ (val
, Qm
) || EQ (val
, Qp
) || EQ (val
, Qd
))
923 from
= to
= XLFD_SPACING_INDEX
, mask
= XLFD_SPACING_MASK
;
925 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
926 mask
= XLFD_SYMBOL_MASK
;
929 /* Merge position-based and value-based restrictions. */
931 while (from
< range_from
)
932 mask
&= ~(1 << from
++);
933 while (from
< 14 && ! (mask
& (1 << from
)))
935 while (to
> range_to
)
936 mask
&= ~(1 << to
--);
937 while (to
>= 0 && ! (mask
& (1 << to
)))
941 range
[i
].from
= from
;
943 range
[i
].mask
= mask
;
945 if (from
> range_from
|| to
< range_to
)
947 /* The range is narrowed by value-based restrictions.
948 Reflect it to the other fields. */
950 /* Following fields should be after FROM. */
952 /* Preceding fields should be before TO. */
953 for (j
= i
- 1, from
--, to
--; j
>= 0; j
--, from
--, to
--)
955 /* Check FROM for non-wildcard field. */
956 if (! NILP (tmp
[j
]) && range
[j
].from
< from
)
958 while (range
[j
].from
< from
)
959 range
[j
].mask
&= ~(1 << range
[j
].from
++);
960 while (from
< 14 && ! (range
[j
].mask
& (1 << from
)))
962 range
[j
].from
= from
;
965 from
= range
[j
].from
;
966 if (range
[j
].to
> to
)
968 while (range
[j
].to
> to
)
969 range
[j
].mask
&= ~(1 << range
[j
].to
--);
970 while (to
>= 0 && ! (range
[j
].mask
& (1 << to
)))
983 /* Decide all fields from restrictions in RANGE. */
984 for (i
= j
= 0; i
< n
; i
++)
986 if (j
< range
[i
].from
)
988 if (i
== 0 || ! NILP (tmp
[i
- 1]))
989 /* None of TMP[X] corresponds to Jth field. */
991 memclear (field
+ j
, (range
[i
].from
- j
) * word_size
);
996 if (! NILP (tmp
[n
- 1]) && j
< XLFD_REGISTRY_INDEX
)
998 memclear (field
+ j
, (XLFD_LAST_INDEX
- j
) * word_size
);
999 if (INTEGERP (field
[XLFD_ENCODING_INDEX
]))
1000 field
[XLFD_ENCODING_INDEX
]
1001 = Fintern (Fnumber_to_string (field
[XLFD_ENCODING_INDEX
]), Qnil
);
1006 /* Parse NAME (null terminated) as XLFD and store information in FONT
1007 (font-spec or font-entity). Size property of FONT is set as
1009 specified XLFD fields FONT property
1010 --------------------- -------------
1011 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
1012 POINT_SIZE and RESY calculated pixel size (Lisp integer)
1013 POINT_SIZE POINT_SIZE/10 (Lisp float)
1015 If NAME is successfully parsed, return 0. Otherwise return -1.
1017 FONT is usually a font-spec, but when this function is called from
1018 X font backend driver, it is a font-entity. In that case, NAME is
1019 a fully specified XLFD. */
1022 font_parse_xlfd (char *name
, ptrdiff_t len
, Lisp_Object font
)
1025 char *f
[XLFD_LAST_INDEX
+ 1];
1029 if (len
> 255 || !len
)
1030 /* Maximum XLFD name length is 255. */
1032 /* Accept "*-.." as a fully specified XLFD. */
1033 if (name
[0] == '*' && (len
== 1 || name
[1] == '-'))
1034 i
= 1, f
[XLFD_FOUNDRY_INDEX
] = name
;
1037 for (p
= name
+ i
; *p
; p
++)
1041 if (i
== XLFD_LAST_INDEX
)
1046 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1047 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1049 if (i
== XLFD_LAST_INDEX
)
1051 /* Fully specified XLFD. */
1054 ASET (font
, FONT_FOUNDRY_INDEX
, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX
));
1055 ASET (font
, FONT_FAMILY_INDEX
, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX
));
1056 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1057 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1059 val
= INTERN_FIELD_SYM (i
);
1062 if ((n
= font_style_to_value (j
, INTERN_FIELD_SYM (i
), 0)) < 0)
1064 ASET (font
, j
, make_number (n
));
1067 ASET (font
, FONT_ADSTYLE_INDEX
, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX
));
1068 if (strcmp (f
[XLFD_REGISTRY_INDEX
], "*-*") == 0)
1069 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
1071 ASET (font
, FONT_REGISTRY_INDEX
,
1072 font_intern_prop (f
[XLFD_REGISTRY_INDEX
],
1073 f
[XLFD_LAST_INDEX
] - f
[XLFD_REGISTRY_INDEX
],
1075 p
= f
[XLFD_PIXEL_INDEX
];
1076 if (*p
== '[' && (pixel_size
= parse_matrix (p
)) >= 0)
1077 ASET (font
, FONT_SIZE_INDEX
, make_number (pixel_size
));
1080 val
= INTERN_FIELD (XLFD_PIXEL_INDEX
);
1082 ASET (font
, FONT_SIZE_INDEX
, val
);
1083 else if (FONT_ENTITY_P (font
))
1087 double point_size
= -1;
1089 eassert (FONT_SPEC_P (font
));
1090 p
= f
[XLFD_POINT_INDEX
];
1092 point_size
= parse_matrix (p
);
1093 else if (c_isdigit (*p
))
1094 point_size
= atoi (p
), point_size
/= 10;
1095 if (point_size
>= 0)
1096 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1100 val
= INTERN_FIELD (XLFD_RESY_INDEX
);
1101 if (! NILP (val
) && ! INTEGERP (val
))
1103 ASET (font
, FONT_DPI_INDEX
, val
);
1104 val
= INTERN_FIELD (XLFD_SPACING_INDEX
);
1107 val
= font_prop_validate_spacing (QCspacing
, val
);
1108 if (! INTEGERP (val
))
1110 ASET (font
, FONT_SPACING_INDEX
, val
);
1112 p
= f
[XLFD_AVGWIDTH_INDEX
];
1115 val
= font_intern_prop (p
, f
[XLFD_REGISTRY_INDEX
] - 1 - p
, 0);
1116 if (! NILP (val
) && ! INTEGERP (val
))
1118 ASET (font
, FONT_AVGWIDTH_INDEX
, val
);
1122 bool wild_card_found
= 0;
1123 Lisp_Object prop
[XLFD_LAST_INDEX
];
1125 if (FONT_ENTITY_P (font
))
1127 for (j
= 0; j
< i
; j
++)
1131 if (f
[j
][1] && f
[j
][1] != '-')
1134 wild_card_found
= 1;
1137 prop
[j
] = INTERN_FIELD (j
);
1139 prop
[j
] = font_intern_prop (f
[j
], f
[i
] - f
[j
], 0);
1141 if (! wild_card_found
)
1143 if (font_expand_wildcards (prop
, i
) < 0)
1146 ASET (font
, FONT_FOUNDRY_INDEX
, prop
[XLFD_FOUNDRY_INDEX
]);
1147 ASET (font
, FONT_FAMILY_INDEX
, prop
[XLFD_FAMILY_INDEX
]);
1148 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1149 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1150 if (! NILP (prop
[i
]))
1152 if ((n
= font_style_to_value (j
, prop
[i
], 1)) < 0)
1154 ASET (font
, j
, make_number (n
));
1156 ASET (font
, FONT_ADSTYLE_INDEX
, prop
[XLFD_ADSTYLE_INDEX
]);
1157 val
= prop
[XLFD_REGISTRY_INDEX
];
1160 val
= prop
[XLFD_ENCODING_INDEX
];
1163 AUTO_STRING (star_dash
, "*-");
1164 val
= concat2 (star_dash
, SYMBOL_NAME (val
));
1167 else if (NILP (prop
[XLFD_ENCODING_INDEX
]))
1169 AUTO_STRING (dash_star
, "-*");
1170 val
= concat2 (SYMBOL_NAME (val
), dash_star
);
1174 AUTO_STRING (dash
, "-");
1175 val
= concat3 (SYMBOL_NAME (val
), dash
,
1176 SYMBOL_NAME (prop
[XLFD_ENCODING_INDEX
]));
1179 ASET (font
, FONT_REGISTRY_INDEX
, Fintern (val
, Qnil
));
1181 if (INTEGERP (prop
[XLFD_PIXEL_INDEX
]))
1182 ASET (font
, FONT_SIZE_INDEX
, prop
[XLFD_PIXEL_INDEX
]);
1183 else if (INTEGERP (prop
[XLFD_POINT_INDEX
]))
1185 double point_size
= XINT (prop
[XLFD_POINT_INDEX
]);
1187 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
/ 10));
1190 if (INTEGERP (prop
[XLFD_RESX_INDEX
]))
1191 ASET (font
, FONT_DPI_INDEX
, prop
[XLFD_RESY_INDEX
]);
1192 if (! NILP (prop
[XLFD_SPACING_INDEX
]))
1194 val
= font_prop_validate_spacing (QCspacing
,
1195 prop
[XLFD_SPACING_INDEX
]);
1196 if (! INTEGERP (val
))
1198 ASET (font
, FONT_SPACING_INDEX
, val
);
1200 if (INTEGERP (prop
[XLFD_AVGWIDTH_INDEX
]))
1201 ASET (font
, FONT_AVGWIDTH_INDEX
, prop
[XLFD_AVGWIDTH_INDEX
]);
1207 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1208 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1209 0, use PIXEL_SIZE instead. */
1212 font_unparse_xlfd (Lisp_Object font
, int pixel_size
, char *name
, int nbytes
)
1215 const char *f
[XLFD_REGISTRY_INDEX
+ 1];
1219 eassert (FONTP (font
));
1221 for (i
= FONT_FOUNDRY_INDEX
, j
= XLFD_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
;
1224 if (i
== FONT_ADSTYLE_INDEX
)
1225 j
= XLFD_ADSTYLE_INDEX
;
1226 else if (i
== FONT_REGISTRY_INDEX
)
1227 j
= XLFD_REGISTRY_INDEX
;
1228 val
= AREF (font
, i
);
1231 if (j
== XLFD_REGISTRY_INDEX
)
1239 val
= SYMBOL_NAME (val
);
1240 if (j
== XLFD_REGISTRY_INDEX
1241 && ! strchr (SSDATA (val
), '-'))
1243 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1244 ptrdiff_t alloc
= SBYTES (val
) + 4;
1245 if (nbytes
<= alloc
)
1247 f
[j
] = p
= alloca (alloc
);
1248 sprintf (p
, "%s%s-*", SDATA (val
),
1249 &"*"[SDATA (val
)[SBYTES (val
) - 1] == '*']);
1252 f
[j
] = SSDATA (val
);
1256 for (i
= FONT_WEIGHT_INDEX
, j
= XLFD_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
;
1259 val
= font_style_symbolic (font
, i
, 0);
1267 val
= SYMBOL_NAME (val
);
1268 alloc
= SBYTES (val
) + 1;
1269 if (nbytes
<= alloc
)
1271 f
[j
] = p
= alloca (alloc
);
1272 /* Copy the name while excluding '-', '?', ',', and '"'. */
1273 for (k
= l
= 0; k
< alloc
; k
++)
1276 if (c
!= '-' && c
!= '?' && c
!= ',' && c
!= '"')
1282 val
= AREF (font
, FONT_SIZE_INDEX
);
1283 eassert (NUMBERP (val
) || NILP (val
));
1284 char font_size_index_buf
[sizeof "-*"
1285 + max (INT_STRLEN_BOUND (EMACS_INT
),
1286 1 + DBL_MAX_10_EXP
+ 1)];
1289 EMACS_INT v
= XINT (val
);
1294 f
[XLFD_PIXEL_INDEX
] = p
= font_size_index_buf
;
1295 sprintf (p
, "%"pI
"d-*", v
);
1298 f
[XLFD_PIXEL_INDEX
] = "*-*";
1300 else if (FLOATP (val
))
1302 double v
= XFLOAT_DATA (val
) * 10;
1303 f
[XLFD_PIXEL_INDEX
] = p
= font_size_index_buf
;
1304 sprintf (p
, "*-%.0f", v
);
1307 f
[XLFD_PIXEL_INDEX
] = "*-*";
1309 char dpi_index_buf
[sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT
)];
1310 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1312 EMACS_INT v
= XINT (AREF (font
, FONT_DPI_INDEX
));
1313 f
[XLFD_RESX_INDEX
] = p
= dpi_index_buf
;
1314 sprintf (p
, "%"pI
"d-%"pI
"d", v
, v
);
1317 f
[XLFD_RESX_INDEX
] = "*-*";
1319 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1321 EMACS_INT spacing
= XINT (AREF (font
, FONT_SPACING_INDEX
));
1323 f
[XLFD_SPACING_INDEX
] = (spacing
<= FONT_SPACING_PROPORTIONAL
? "p"
1324 : spacing
<= FONT_SPACING_DUAL
? "d"
1325 : spacing
<= FONT_SPACING_MONO
? "m"
1329 f
[XLFD_SPACING_INDEX
] = "*";
1331 char avgwidth_index_buf
[INT_BUFSIZE_BOUND (EMACS_INT
)];
1332 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1334 f
[XLFD_AVGWIDTH_INDEX
] = p
= avgwidth_index_buf
;
1335 sprintf (p
, "%"pI
"d", XINT (AREF (font
, FONT_AVGWIDTH_INDEX
)));
1338 f
[XLFD_AVGWIDTH_INDEX
] = "*";
1340 len
= snprintf (name
, nbytes
, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1341 f
[XLFD_FOUNDRY_INDEX
], f
[XLFD_FAMILY_INDEX
],
1342 f
[XLFD_WEIGHT_INDEX
], f
[XLFD_SLANT_INDEX
],
1343 f
[XLFD_SWIDTH_INDEX
], f
[XLFD_ADSTYLE_INDEX
],
1344 f
[XLFD_PIXEL_INDEX
], f
[XLFD_RESX_INDEX
],
1345 f
[XLFD_SPACING_INDEX
], f
[XLFD_AVGWIDTH_INDEX
],
1346 f
[XLFD_REGISTRY_INDEX
]);
1347 return len
< nbytes
? len
: -1;
1350 /* Parse NAME (null terminated) and store information in FONT
1351 (font-spec or font-entity). NAME is supplied in either the
1352 Fontconfig or GTK font name format. If NAME is successfully
1353 parsed, return 0. Otherwise return -1.
1355 The fontconfig format is
1357 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1361 FAMILY [PROPS...] [SIZE]
1363 This function tries to guess which format it is. */
1366 font_parse_fcname (char *name
, ptrdiff_t len
, Lisp_Object font
)
1369 char *size_beg
= NULL
, *size_end
= NULL
;
1370 char *props_beg
= NULL
, *family_end
= NULL
;
1375 for (p
= name
; *p
; p
++)
1377 if (*p
== '\\' && p
[1])
1381 props_beg
= family_end
= p
;
1386 bool decimal
= 0, size_found
= 1;
1387 for (q
= p
+ 1; *q
&& *q
!= ':'; q
++)
1388 if (! c_isdigit (*q
))
1390 if (*q
!= '.' || decimal
)
1409 Lisp_Object extra_props
= Qnil
;
1411 /* A fontconfig name with size and/or property data. */
1412 if (family_end
> name
)
1415 family
= font_intern_prop (name
, family_end
- name
, 1);
1416 ASET (font
, FONT_FAMILY_INDEX
, family
);
1420 double point_size
= strtod (size_beg
, &size_end
);
1421 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1422 if (*size_end
== ':' && size_end
[1])
1423 props_beg
= size_end
;
1427 /* Now parse ":KEY=VAL" patterns. */
1430 for (p
= props_beg
; *p
; p
= q
)
1432 for (q
= p
+ 1; *q
&& *q
!= '=' && *q
!= ':'; q
++);
1435 /* Must be an enumerated value. */
1439 val
= font_intern_prop (p
, q
- p
, 1);
1441 #define PROP_MATCH(STR) (word_len == strlen (STR) \
1442 && memcmp (p, STR, strlen (STR)) == 0)
1444 if (PROP_MATCH ("light")
1445 || PROP_MATCH ("medium")
1446 || PROP_MATCH ("demibold")
1447 || PROP_MATCH ("bold")
1448 || PROP_MATCH ("black"))
1449 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, val
);
1450 else if (PROP_MATCH ("roman")
1451 || PROP_MATCH ("italic")
1452 || PROP_MATCH ("oblique"))
1453 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, val
);
1454 else if (PROP_MATCH ("charcell"))
1455 ASET (font
, FONT_SPACING_INDEX
,
1456 make_number (FONT_SPACING_CHARCELL
));
1457 else if (PROP_MATCH ("mono"))
1458 ASET (font
, FONT_SPACING_INDEX
,
1459 make_number (FONT_SPACING_MONO
));
1460 else if (PROP_MATCH ("proportional"))
1461 ASET (font
, FONT_SPACING_INDEX
,
1462 make_number (FONT_SPACING_PROPORTIONAL
));
1471 if (q
- p
== 10 && memcmp (p
+ 1, "pixelsize", 9) == 0)
1472 prop
= FONT_SIZE_INDEX
;
1475 key
= font_intern_prop (p
, q
- p
, 1);
1476 prop
= get_font_prop_index (key
);
1480 for (q
= p
; *q
&& *q
!= ':'; q
++);
1481 val
= font_intern_prop (p
, q
- p
, 0);
1483 if (prop
>= FONT_FOUNDRY_INDEX
1484 && prop
< FONT_EXTRA_INDEX
)
1485 ASET (font
, prop
, font_prop_validate (prop
, Qnil
, val
));
1488 extra_props
= nconc2 (extra_props
,
1489 list1 (Fcons (key
, val
)));
1496 if (! NILP (extra_props
))
1498 struct font_driver_list
*driver_list
= font_driver_list
;
1499 for ( ; driver_list
; driver_list
= driver_list
->next
)
1500 if (driver_list
->driver
->filter_properties
)
1501 (*driver_list
->driver
->filter_properties
) (font
, extra_props
);
1507 /* Either a fontconfig-style name with no size and property
1508 data, or a GTK-style name. */
1509 Lisp_Object weight
= Qnil
, slant
= Qnil
;
1510 Lisp_Object width
= Qnil
, size
= Qnil
;
1514 /* Scan backwards from the end, looking for a size. */
1515 for (p
= name
+ len
- 1; p
>= name
; p
--)
1516 if (!c_isdigit (*p
))
1519 if ((p
< name
+ len
- 1) && ((p
+ 1 == name
) || *p
== ' '))
1520 /* Found a font size. */
1521 size
= make_float (strtod (p
+ 1, NULL
));
1525 /* Now P points to the termination of the string, sans size.
1526 Scan backwards, looking for font properties. */
1527 for (; p
> name
; p
= q
)
1529 for (q
= p
- 1; q
>= name
; q
--)
1531 if (q
> name
&& *(q
-1) == '\\')
1532 --q
; /* Skip quoting backslashes. */
1538 word_len
= p
- word_start
;
1540 #define PROP_MATCH(STR) \
1541 (word_len == strlen (STR) \
1542 && memcmp (word_start, STR, strlen (STR)) == 0)
1543 #define PROP_SAVE(VAR, STR) \
1544 (VAR = NILP (VAR) ? font_intern_prop (STR, strlen (STR), 1) : VAR)
1546 if (PROP_MATCH ("Ultra-Light"))
1547 PROP_SAVE (weight
, "ultra-light");
1548 else if (PROP_MATCH ("Light"))
1549 PROP_SAVE (weight
, "light");
1550 else if (PROP_MATCH ("Book"))
1551 PROP_SAVE (weight
, "book");
1552 else if (PROP_MATCH ("Medium"))
1553 PROP_SAVE (weight
, "medium");
1554 else if (PROP_MATCH ("Semi-Bold"))
1555 PROP_SAVE (weight
, "semi-bold");
1556 else if (PROP_MATCH ("Bold"))
1557 PROP_SAVE (weight
, "bold");
1558 else if (PROP_MATCH ("Italic"))
1559 PROP_SAVE (slant
, "italic");
1560 else if (PROP_MATCH ("Oblique"))
1561 PROP_SAVE (slant
, "oblique");
1562 else if (PROP_MATCH ("Semi-Condensed"))
1563 PROP_SAVE (width
, "semi-condensed");
1564 else if (PROP_MATCH ("Condensed"))
1565 PROP_SAVE (width
, "condensed");
1566 /* An unknown word must be part of the font name. */
1577 ASET (font
, FONT_FAMILY_INDEX
,
1578 font_intern_prop (name
, family_end
- name
, 1));
1580 ASET (font
, FONT_SIZE_INDEX
, size
);
1582 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, weight
);
1584 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, slant
);
1586 FONT_SET_STYLE (font
, FONT_WIDTH_INDEX
, width
);
1592 #if defined HAVE_XFT || defined HAVE_FREETYPE || defined HAVE_NS
1594 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1595 NAME (NBYTES length), and return the name length. If
1596 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead.
1597 Return a negative value on error. */
1600 font_unparse_fcname (Lisp_Object font
, int pixel_size
, char *name
, int nbytes
)
1602 Lisp_Object family
, foundry
;
1608 Lisp_Object styles
[3];
1609 const char *style_names
[3] = { "weight", "slant", "width" };
1611 family
= AREF (font
, FONT_FAMILY_INDEX
);
1612 if (! NILP (family
))
1614 if (SYMBOLP (family
))
1615 family
= SYMBOL_NAME (family
);
1620 val
= AREF (font
, FONT_SIZE_INDEX
);
1623 if (XINT (val
) != 0)
1624 pixel_size
= XINT (val
);
1629 eassert (FLOATP (val
));
1631 point_size
= (int) XFLOAT_DATA (val
);
1634 foundry
= AREF (font
, FONT_FOUNDRY_INDEX
);
1635 if (! NILP (foundry
))
1637 if (SYMBOLP (foundry
))
1638 foundry
= SYMBOL_NAME (foundry
);
1643 for (i
= 0; i
< 3; i
++)
1644 styles
[i
] = font_style_symbolic (font
, FONT_WEIGHT_INDEX
+ i
, 0);
1647 lim
= name
+ nbytes
;
1648 if (! NILP (family
))
1650 int len
= snprintf (p
, lim
- p
, "%s", SSDATA (family
));
1651 if (! (0 <= len
&& len
< lim
- p
))
1657 int len
= snprintf (p
, lim
- p
, &"-%d"[p
== name
], point_size
);
1658 if (! (0 <= len
&& len
< lim
- p
))
1662 else if (pixel_size
> 0)
1664 int len
= snprintf (p
, lim
- p
, ":pixelsize=%d", pixel_size
);
1665 if (! (0 <= len
&& len
< lim
- p
))
1669 if (! NILP (AREF (font
, FONT_FOUNDRY_INDEX
)))
1671 int len
= snprintf (p
, lim
- p
, ":foundry=%s",
1672 SSDATA (SYMBOL_NAME (AREF (font
,
1673 FONT_FOUNDRY_INDEX
))));
1674 if (! (0 <= len
&& len
< lim
- p
))
1678 for (i
= 0; i
< 3; i
++)
1679 if (! NILP (styles
[i
]))
1681 int len
= snprintf (p
, lim
- p
, ":%s=%s", style_names
[i
],
1682 SSDATA (SYMBOL_NAME (styles
[i
])));
1683 if (! (0 <= len
&& len
< lim
- p
))
1688 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1690 int len
= snprintf (p
, lim
- p
, ":dpi=%"pI
"d",
1691 XINT (AREF (font
, FONT_DPI_INDEX
)));
1692 if (! (0 <= len
&& len
< lim
- p
))
1697 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1699 int len
= snprintf (p
, lim
- p
, ":spacing=%"pI
"d",
1700 XINT (AREF (font
, FONT_SPACING_INDEX
)));
1701 if (! (0 <= len
&& len
< lim
- p
))
1706 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1708 int len
= snprintf (p
, lim
- p
,
1709 (XINT (AREF (font
, FONT_AVGWIDTH_INDEX
)) == 0
1711 : ":scalable=false"));
1712 if (! (0 <= len
&& len
< lim
- p
))
1722 /* Parse NAME (null terminated) and store information in FONT
1723 (font-spec or font-entity). If NAME is successfully parsed, return
1724 0. Otherwise return -1. */
1727 font_parse_name (char *name
, ptrdiff_t namelen
, Lisp_Object font
)
1729 if (name
[0] == '-' || strchr (name
, '*') || strchr (name
, '?'))
1730 return font_parse_xlfd (name
, namelen
, font
);
1731 return font_parse_fcname (name
, namelen
, font
);
1735 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1736 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1740 font_parse_family_registry (Lisp_Object family
, Lisp_Object registry
, Lisp_Object font_spec
)
1746 && NILP (AREF (font_spec
, FONT_FAMILY_INDEX
)))
1748 CHECK_STRING (family
);
1749 len
= SBYTES (family
);
1750 p0
= SSDATA (family
);
1751 p1
= strchr (p0
, '-');
1754 if ((*p0
!= '*' && p1
- p0
> 0)
1755 && NILP (AREF (font_spec
, FONT_FOUNDRY_INDEX
)))
1756 Ffont_put (font_spec
, QCfoundry
, font_intern_prop (p0
, p1
- p0
, 1));
1759 Ffont_put (font_spec
, QCfamily
, font_intern_prop (p1
, len
, 1));
1762 ASET (font_spec
, FONT_FAMILY_INDEX
, Fintern (family
, Qnil
));
1764 if (! NILP (registry
))
1766 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1767 CHECK_STRING (registry
);
1768 len
= SBYTES (registry
);
1769 p0
= SSDATA (registry
);
1770 p1
= strchr (p0
, '-');
1773 AUTO_STRING (extra
, ("*-*" + (len
&& p0
[len
- 1] == '*')));
1774 registry
= concat2 (registry
, extra
);
1776 registry
= Fdowncase (registry
);
1777 ASET (font_spec
, FONT_REGISTRY_INDEX
, Fintern (registry
, Qnil
));
1782 /* This part (through the next ^L) is still experimental and not
1783 tested much. We may drastically change codes. */
1789 #define LGSTRING_HEADER_SIZE 6
1790 #define LGSTRING_GLYPH_SIZE 8
1793 check_gstring (Lisp_Object gstring
)
1799 CHECK_VECTOR (gstring
);
1800 val
= AREF (gstring
, 0);
1802 if (ASIZE (val
) < LGSTRING_HEADER_SIZE
)
1804 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring
));
1805 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
)))
1806 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
));
1807 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
)))
1808 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
));
1809 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
)))
1810 CHECK_NATNUM (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
));
1811 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1812 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1813 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1814 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1816 for (i
= 0; i
< LGSTRING_GLYPH_LEN (gstring
); i
++)
1818 val
= LGSTRING_GLYPH (gstring
, i
);
1820 if (ASIZE (val
) < LGSTRING_GLYPH_SIZE
)
1822 if (NILP (AREF (val
, LGLYPH_IX_CHAR
)))
1824 CHECK_NATNUM (AREF (val
, LGLYPH_IX_FROM
));
1825 CHECK_NATNUM (AREF (val
, LGLYPH_IX_TO
));
1826 CHECK_CHARACTER (AREF (val
, LGLYPH_IX_CHAR
));
1827 if (!NILP (AREF (val
, LGLYPH_IX_CODE
)))
1828 CHECK_NATNUM (AREF (val
, LGLYPH_IX_CODE
));
1829 if (!NILP (AREF (val
, LGLYPH_IX_WIDTH
)))
1830 CHECK_NATNUM (AREF (val
, LGLYPH_IX_WIDTH
));
1831 if (!NILP (AREF (val
, LGLYPH_IX_ADJUSTMENT
)))
1833 val
= AREF (val
, LGLYPH_IX_ADJUSTMENT
);
1835 if (ASIZE (val
) < 3)
1837 for (j
= 0; j
< 3; j
++)
1838 CHECK_NUMBER (AREF (val
, j
));
1843 error ("Invalid glyph-string format");
1848 check_otf_features (Lisp_Object otf_features
)
1852 CHECK_CONS (otf_features
);
1853 CHECK_SYMBOL (XCAR (otf_features
));
1854 otf_features
= XCDR (otf_features
);
1855 CHECK_CONS (otf_features
);
1856 CHECK_SYMBOL (XCAR (otf_features
));
1857 otf_features
= XCDR (otf_features
);
1858 for (val
= Fcar (otf_features
); CONSP (val
); val
= XCDR (val
))
1860 CHECK_SYMBOL (XCAR (val
));
1861 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1862 error ("Invalid OTF GSUB feature: %s",
1863 SDATA (SYMBOL_NAME (XCAR (val
))));
1865 otf_features
= XCDR (otf_features
);
1866 for (val
= Fcar (otf_features
); CONSP (val
); val
= XCDR (val
))
1868 CHECK_SYMBOL (XCAR (val
));
1869 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1870 error ("Invalid OTF GPOS feature: %s",
1871 SDATA (SYMBOL_NAME (XCAR (val
))));
1878 Lisp_Object otf_list
;
1881 otf_tag_symbol (OTF_Tag tag
)
1885 OTF_tag_name (tag
, name
);
1886 return Fintern (make_unibyte_string (name
, 4), Qnil
);
1890 otf_open (Lisp_Object file
)
1892 Lisp_Object val
= Fassoc (file
, otf_list
);
1896 otf
= XSAVE_POINTER (XCDR (val
), 0);
1899 otf
= STRINGP (file
) ? OTF_open (SSDATA (file
)) : NULL
;
1900 val
= make_save_ptr (otf
);
1901 otf_list
= Fcons (Fcons (file
, val
), otf_list
);
1907 /* Return a list describing which scripts/languages FONT supports by
1908 which GSUB/GPOS features of OpenType tables. See the comment of
1909 (struct font_driver).otf_capability. */
1912 font_otf_capability (struct font
*font
)
1915 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
1918 otf
= otf_open (font
->props
[FONT_FILE_INDEX
]);
1921 for (i
= 0; i
< 2; i
++)
1923 OTF_GSUB_GPOS
*gsub_gpos
;
1924 Lisp_Object script_list
= Qnil
;
1927 if (OTF_get_features (otf
, i
== 0) < 0)
1929 gsub_gpos
= i
== 0 ? otf
->gsub
: otf
->gpos
;
1930 for (j
= gsub_gpos
->ScriptList
.ScriptCount
- 1; j
>= 0; j
--)
1932 OTF_Script
*script
= gsub_gpos
->ScriptList
.Script
+ j
;
1933 Lisp_Object langsys_list
= Qnil
;
1934 Lisp_Object script_tag
= otf_tag_symbol (script
->ScriptTag
);
1937 for (k
= script
->LangSysCount
; k
>= 0; k
--)
1939 OTF_LangSys
*langsys
;
1940 Lisp_Object feature_list
= Qnil
;
1941 Lisp_Object langsys_tag
;
1944 if (k
== script
->LangSysCount
)
1946 langsys
= &script
->DefaultLangSys
;
1951 langsys
= script
->LangSys
+ k
;
1953 = otf_tag_symbol (script
->LangSysRecord
[k
].LangSysTag
);
1955 for (l
= langsys
->FeatureCount
- 1; l
>= 0; l
--)
1957 OTF_Feature
*feature
1958 = gsub_gpos
->FeatureList
.Feature
+ langsys
->FeatureIndex
[l
];
1959 Lisp_Object feature_tag
1960 = otf_tag_symbol (feature
->FeatureTag
);
1962 feature_list
= Fcons (feature_tag
, feature_list
);
1964 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
1967 script_list
= Fcons (Fcons (script_tag
, langsys_list
),
1972 XSETCAR (capability
, script_list
);
1974 XSETCDR (capability
, script_list
);
1980 /* Parse OTF features in SPEC and write a proper features spec string
1981 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1982 assured that the sufficient memory has already allocated for
1986 generate_otf_features (Lisp_Object spec
, char *features
)
1994 for (asterisk
= 0; CONSP (spec
); spec
= XCDR (spec
))
2000 if (SREF (SYMBOL_NAME (val
), 0) == '*')
2005 else if (! asterisk
)
2007 val
= SYMBOL_NAME (val
);
2008 p
+= esprintf (p
, "%s", SDATA (val
));
2012 val
= SYMBOL_NAME (val
);
2013 p
+= esprintf (p
, "~%s", SDATA (val
));
2017 error ("OTF spec too long");
2021 font_otf_DeviceTable (OTF_DeviceTable
*device_table
)
2023 int len
= device_table
->StartSize
- device_table
->EndSize
+ 1;
2025 return Fcons (make_number (len
),
2026 make_unibyte_string (device_table
->DeltaValue
, len
));
2030 font_otf_ValueRecord (int value_format
, OTF_ValueRecord
*value_record
)
2032 Lisp_Object val
= Fmake_vector (make_number (8), Qnil
);
2034 if (value_format
& OTF_XPlacement
)
2035 ASET (val
, 0, make_number (value_record
->XPlacement
));
2036 if (value_format
& OTF_YPlacement
)
2037 ASET (val
, 1, make_number (value_record
->YPlacement
));
2038 if (value_format
& OTF_XAdvance
)
2039 ASET (val
, 2, make_number (value_record
->XAdvance
));
2040 if (value_format
& OTF_YAdvance
)
2041 ASET (val
, 3, make_number (value_record
->YAdvance
));
2042 if (value_format
& OTF_XPlaDevice
)
2043 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XPlaDevice
));
2044 if (value_format
& OTF_YPlaDevice
)
2045 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YPlaDevice
));
2046 if (value_format
& OTF_XAdvDevice
)
2047 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XAdvDevice
));
2048 if (value_format
& OTF_YAdvDevice
)
2049 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YAdvDevice
));
2054 font_otf_Anchor (OTF_Anchor
*anchor
)
2058 val
= Fmake_vector (make_number (anchor
->AnchorFormat
+ 1), Qnil
);
2059 ASET (val
, 0, make_number (anchor
->XCoordinate
));
2060 ASET (val
, 1, make_number (anchor
->YCoordinate
));
2061 if (anchor
->AnchorFormat
== 2)
2062 ASET (val
, 2, make_number (anchor
->f
.f1
.AnchorPoint
));
2065 ASET (val
, 3, font_otf_DeviceTable (&anchor
->f
.f2
.XDeviceTable
));
2066 ASET (val
, 4, font_otf_DeviceTable (&anchor
->f
.f2
.YDeviceTable
));
2070 #endif /* HAVE_LIBOTF */
2077 font_rescale_ratio (Lisp_Object font_entity
)
2079 Lisp_Object tail
, elt
;
2080 Lisp_Object name
= Qnil
;
2082 for (tail
= Vface_font_rescale_alist
; CONSP (tail
); tail
= XCDR (tail
))
2085 if (FLOATP (XCDR (elt
)))
2087 if (STRINGP (XCAR (elt
)))
2090 name
= Ffont_xlfd_name (font_entity
, Qnil
);
2091 if (fast_string_match_ignore_case (XCAR (elt
), name
) >= 0)
2092 return XFLOAT_DATA (XCDR (elt
));
2094 else if (FONT_SPEC_P (XCAR (elt
)))
2096 if (font_match_p (XCAR (elt
), font_entity
))
2097 return XFLOAT_DATA (XCDR (elt
));
2104 /* We sort fonts by scoring each of them against a specified
2105 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2106 the value is, the closer the font is to the font-spec.
2108 The lowest 2 bits of the score are used for driver type. The font
2109 available by the most preferred font driver is 0.
2111 The 4 7-bit fields in the higher 28 bits are used for numeric properties
2112 WEIGHT, SLANT, WIDTH, and SIZE. */
2114 /* How many bits to shift to store the difference value of each font
2115 property in a score. Note that floats for FONT_TYPE_INDEX and
2116 FONT_REGISTRY_INDEX are not used. */
2117 static int sort_shift_bits
[FONT_SIZE_INDEX
+ 1];
2119 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2120 The return value indicates how different ENTITY is compared with
2124 font_score (Lisp_Object entity
, Lisp_Object
*spec_prop
)
2129 /* Score three style numeric fields. Maximum difference is 127. */
2130 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
; i
++)
2131 if (! NILP (spec_prop
[i
]) && ! EQ (AREF (entity
, i
), spec_prop
[i
]))
2133 EMACS_INT diff
= ((XINT (AREF (entity
, i
)) >> 8)
2134 - (XINT (spec_prop
[i
]) >> 8));
2135 score
|= min (eabs (diff
), 127) << sort_shift_bits
[i
];
2138 /* Score the size. Maximum difference is 127. */
2139 if (! NILP (spec_prop
[FONT_SIZE_INDEX
])
2140 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2142 /* We use the higher 6-bit for the actual size difference. The
2143 lowest bit is set if the DPI is different. */
2145 EMACS_INT pixel_size
= XINT (spec_prop
[FONT_SIZE_INDEX
]);
2146 EMACS_INT entity_size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
2148 if (CONSP (Vface_font_rescale_alist
))
2149 pixel_size
*= font_rescale_ratio (entity
);
2150 if (pixel_size
* 2 < entity_size
|| entity_size
* 2 < pixel_size
)
2151 /* This size is wrong by more than a factor 2: reject it! */
2153 diff
= eabs (pixel_size
- entity_size
) << 1;
2154 if (! NILP (spec_prop
[FONT_DPI_INDEX
])
2155 && ! EQ (spec_prop
[FONT_DPI_INDEX
], AREF (entity
, FONT_DPI_INDEX
)))
2157 if (! NILP (spec_prop
[FONT_AVGWIDTH_INDEX
])
2158 && ! EQ (spec_prop
[FONT_AVGWIDTH_INDEX
], AREF (entity
, FONT_AVGWIDTH_INDEX
)))
2160 score
|= min (diff
, 127) << sort_shift_bits
[FONT_SIZE_INDEX
];
2167 /* Concatenate all elements of LIST into one vector. LIST is a list
2168 of font-entity vectors. */
2171 font_vconcat_entity_vectors (Lisp_Object list
)
2173 EMACS_INT nargs
= XFASTINT (Flength (list
));
2176 SAFE_ALLOCA_LISP (args
, nargs
);
2179 for (i
= 0; i
< nargs
; i
++, list
= XCDR (list
))
2180 args
[i
] = XCAR (list
);
2181 Lisp_Object result
= Fvconcat (nargs
, args
);
2187 /* The structure for elements being sorted by qsort. */
2188 struct font_sort_data
2191 int font_driver_preference
;
2196 /* The comparison function for qsort. */
2199 font_compare (const void *d1
, const void *d2
)
2201 const struct font_sort_data
*data1
= d1
;
2202 const struct font_sort_data
*data2
= d2
;
2204 if (data1
->score
< data2
->score
)
2206 else if (data1
->score
> data2
->score
)
2208 return (data1
->font_driver_preference
- data2
->font_driver_preference
);
2212 /* Sort each font-entity vector in LIST by closeness to font-spec PREFER.
2213 If PREFER specifies a point-size, calculate the corresponding
2214 pixel-size from QCdpi property of PREFER or from the Y-resolution
2215 of FRAME before sorting.
2217 If BEST-ONLY is nonzero, return the best matching entity (that
2218 supports the character BEST-ONLY if BEST-ONLY is positive, or any
2219 if BEST-ONLY is negative). Otherwise, return the sorted result as
2220 a single vector of font-entities.
2222 This function does no optimization for the case that the total
2223 number of elements is 1. The caller should avoid calling this in
2227 font_sort_entities (Lisp_Object list
, Lisp_Object prefer
,
2228 struct frame
*f
, int best_only
)
2230 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2232 struct font_sort_data
*data
;
2233 unsigned best_score
;
2234 Lisp_Object best_entity
;
2235 Lisp_Object tail
, vec
IF_LINT (= Qnil
);
2238 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_AVGWIDTH_INDEX
; i
++)
2239 prefer_prop
[i
] = AREF (prefer
, i
);
2240 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2241 prefer_prop
[FONT_SIZE_INDEX
]
2242 = make_number (font_pixel_size (f
, prefer
));
2244 if (NILP (XCDR (list
)))
2246 /* What we have to take care of is this single vector. */
2248 maxlen
= ASIZE (vec
);
2252 /* We don't have to perform sort, so there's no need of creating
2253 a single vector. But, we must find the length of the longest
2256 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
2257 if (maxlen
< ASIZE (XCAR (tail
)))
2258 maxlen
= ASIZE (XCAR (tail
));
2262 /* We have to create a single vector to sort it. */
2263 vec
= font_vconcat_entity_vectors (list
);
2264 maxlen
= ASIZE (vec
);
2267 data
= SAFE_ALLOCA (maxlen
* sizeof *data
);
2268 best_score
= 0xFFFFFFFF;
2271 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
2273 int font_driver_preference
= 0;
2274 Lisp_Object current_font_driver
;
2280 /* We are sure that the length of VEC > 0. */
2281 current_font_driver
= AREF (AREF (vec
, 0), FONT_TYPE_INDEX
);
2282 /* Score the elements. */
2283 for (i
= 0; i
< len
; i
++)
2285 data
[i
].entity
= AREF (vec
, i
);
2287 = ((best_only
<= 0 || font_has_char (f
, data
[i
].entity
, best_only
)
2289 ? font_score (data
[i
].entity
, prefer_prop
)
2291 if (best_only
&& best_score
> data
[i
].score
)
2293 best_score
= data
[i
].score
;
2294 best_entity
= data
[i
].entity
;
2295 if (best_score
== 0)
2298 if (! EQ (current_font_driver
, AREF (AREF (vec
, i
), FONT_TYPE_INDEX
)))
2300 current_font_driver
= AREF (AREF (vec
, i
), FONT_TYPE_INDEX
);
2301 font_driver_preference
++;
2303 data
[i
].font_driver_preference
= font_driver_preference
;
2306 /* Sort if necessary. */
2309 qsort (data
, len
, sizeof *data
, font_compare
);
2310 for (i
= 0; i
< len
; i
++)
2311 ASET (vec
, i
, data
[i
].entity
);
2320 FONT_ADD_LOG ("sort-by", prefer
, vec
);
2325 /* API of Font Service Layer. */
2327 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2328 sort_shift_bits. Finternal_set_font_selection_order calls this
2329 function with font_sort_order after setting up it. */
2332 font_update_sort_order (int *order
)
2336 for (i
= 0, shift_bits
= 23; i
< 4; i
++, shift_bits
-= 7)
2338 int xlfd_idx
= order
[i
];
2340 if (xlfd_idx
== XLFD_WEIGHT_INDEX
)
2341 sort_shift_bits
[FONT_WEIGHT_INDEX
] = shift_bits
;
2342 else if (xlfd_idx
== XLFD_SLANT_INDEX
)
2343 sort_shift_bits
[FONT_SLANT_INDEX
] = shift_bits
;
2344 else if (xlfd_idx
== XLFD_SWIDTH_INDEX
)
2345 sort_shift_bits
[FONT_WIDTH_INDEX
] = shift_bits
;
2347 sort_shift_bits
[FONT_SIZE_INDEX
] = shift_bits
;
2352 font_check_otf_features (Lisp_Object script
, Lisp_Object langsys
,
2353 Lisp_Object features
, Lisp_Object table
)
2358 table
= assq_no_quit (script
, table
);
2361 table
= XCDR (table
);
2362 if (! NILP (langsys
))
2364 table
= assq_no_quit (langsys
, table
);
2370 val
= assq_no_quit (Qnil
, table
);
2372 table
= XCAR (table
);
2376 table
= XCDR (table
);
2377 for (negative
= 0; CONSP (features
); features
= XCDR (features
))
2379 if (NILP (XCAR (features
)))
2384 if (NILP (Fmemq (XCAR (features
), table
)) != negative
)
2390 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2393 font_check_otf (Lisp_Object spec
, Lisp_Object otf_capability
)
2395 Lisp_Object script
, langsys
= Qnil
, gsub
= Qnil
, gpos
= Qnil
;
2397 script
= XCAR (spec
);
2401 langsys
= XCAR (spec
);
2412 if (! NILP (gsub
) && ! font_check_otf_features (script
, langsys
, gsub
,
2413 XCAR (otf_capability
)))
2415 if (! NILP (gpos
) && ! font_check_otf_features (script
, langsys
, gpos
,
2416 XCDR (otf_capability
)))
2423 /* Check if FONT (font-entity or font-object) matches with the font
2424 specification SPEC. */
2427 font_match_p (Lisp_Object spec
, Lisp_Object font
)
2429 Lisp_Object prop
[FONT_SPEC_MAX
], *props
;
2430 Lisp_Object extra
, font_extra
;
2433 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2434 if (! NILP (AREF (spec
, i
))
2435 && ! NILP (AREF (font
, i
))
2436 && ! EQ (AREF (spec
, i
), AREF (font
, i
)))
2438 props
= XFONT_SPEC (spec
)->props
;
2439 if (FLOATP (props
[FONT_SIZE_INDEX
]))
2441 for (i
= FONT_FOUNDRY_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2442 prop
[i
] = AREF (spec
, i
);
2443 prop
[FONT_SIZE_INDEX
]
2444 = make_number (font_pixel_size (XFRAME (selected_frame
), spec
));
2448 if (font_score (font
, props
) > 0)
2450 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
2451 font_extra
= AREF (font
, FONT_EXTRA_INDEX
);
2452 for (; CONSP (extra
); extra
= XCDR (extra
))
2454 Lisp_Object key
= XCAR (XCAR (extra
));
2455 Lisp_Object val
= XCDR (XCAR (extra
)), val2
;
2457 if (EQ (key
, QClang
))
2459 val2
= assq_no_quit (key
, font_extra
);
2468 if (NILP (Fmemq (val
, val2
)))
2473 ? NILP (Fmemq (val
, XCDR (val2
)))
2477 else if (EQ (key
, QCscript
))
2479 val2
= assq_no_quit (val
, Vscript_representative_chars
);
2485 /* All characters in the list must be supported. */
2486 for (; CONSP (val2
); val2
= XCDR (val2
))
2488 if (! CHARACTERP (XCAR (val2
)))
2490 if (font_encode_char (font
, XFASTINT (XCAR (val2
)))
2491 == FONT_INVALID_CODE
)
2495 else if (VECTORP (val2
))
2497 /* At most one character in the vector must be supported. */
2498 for (i
= 0; i
< ASIZE (val2
); i
++)
2500 if (! CHARACTERP (AREF (val2
, i
)))
2502 if (font_encode_char (font
, XFASTINT (AREF (val2
, i
)))
2503 != FONT_INVALID_CODE
)
2506 if (i
== ASIZE (val2
))
2511 else if (EQ (key
, QCotf
))
2515 if (! FONT_OBJECT_P (font
))
2517 fontp
= XFONT_OBJECT (font
);
2518 if (! fontp
->driver
->otf_capability
)
2520 val2
= fontp
->driver
->otf_capability (fontp
);
2521 if (NILP (val2
) || ! font_check_otf (val
, val2
))
2532 Each font backend has the callback function get_cache, and it
2533 returns a cons cell of which cdr part can be freely used for
2534 caching fonts. The cons cell may be shared by multiple frames
2535 and/or multiple font drivers. So, we arrange the cdr part as this:
2537 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2539 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2540 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2541 cons (FONT-SPEC . [FONT-ENTITY ...]). */
2543 static void font_prepare_cache (struct frame
*, struct font_driver
*);
2544 static void font_finish_cache (struct frame
*, struct font_driver
*);
2545 static Lisp_Object
font_get_cache (struct frame
*, struct font_driver
*);
2546 static void font_clear_cache (struct frame
*, Lisp_Object
,
2547 struct font_driver
*);
2550 font_prepare_cache (struct frame
*f
, struct font_driver
*driver
)
2552 Lisp_Object cache
, val
;
2554 cache
= driver
->get_cache (f
);
2556 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2560 val
= list2 (driver
->type
, make_number (1));
2561 XSETCDR (cache
, Fcons (val
, XCDR (cache
)));
2565 val
= XCDR (XCAR (val
));
2566 XSETCAR (val
, make_number (XINT (XCAR (val
)) + 1));
2572 font_finish_cache (struct frame
*f
, struct font_driver
*driver
)
2574 Lisp_Object cache
, val
, tmp
;
2577 cache
= driver
->get_cache (f
);
2579 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2580 cache
= val
, val
= XCDR (val
);
2581 eassert (! NILP (val
));
2582 tmp
= XCDR (XCAR (val
));
2583 XSETCAR (tmp
, make_number (XINT (XCAR (tmp
)) - 1));
2584 if (XINT (XCAR (tmp
)) == 0)
2586 font_clear_cache (f
, XCAR (val
), driver
);
2587 XSETCDR (cache
, XCDR (val
));
2593 font_get_cache (struct frame
*f
, struct font_driver
*driver
)
2595 Lisp_Object val
= driver
->get_cache (f
);
2596 Lisp_Object type
= driver
->type
;
2598 eassert (CONSP (val
));
2599 for (val
= XCDR (val
); ! EQ (XCAR (XCAR (val
)), type
); val
= XCDR (val
));
2600 eassert (CONSP (val
));
2601 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2602 val
= XCDR (XCAR (val
));
2608 font_clear_cache (struct frame
*f
, Lisp_Object cache
, struct font_driver
*driver
)
2610 Lisp_Object tail
, elt
;
2614 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2615 for (tail
= XCDR (XCDR (cache
)); CONSP (tail
); tail
= XCDR (tail
))
2618 /* elt should have the form (FONT-SPEC . [FONT-ENTITY ...]) */
2619 if (CONSP (elt
) && FONT_SPEC_P (XCAR (elt
)))
2622 eassert (VECTORP (elt
));
2623 for (i
= 0; i
< ASIZE (elt
); i
++)
2625 entity
= AREF (elt
, i
);
2627 if (FONT_ENTITY_P (entity
)
2628 && EQ (driver
->type
, AREF (entity
, FONT_TYPE_INDEX
)))
2630 Lisp_Object objlist
= AREF (entity
, FONT_OBJLIST_INDEX
);
2632 for (; CONSP (objlist
); objlist
= XCDR (objlist
))
2634 Lisp_Object val
= XCAR (objlist
);
2635 struct font
*font
= XFONT_OBJECT (val
);
2637 if (! NILP (AREF (val
, FONT_TYPE_INDEX
)))
2639 eassert (font
&& driver
== font
->driver
);
2640 driver
->close (font
);
2643 if (driver
->free_entity
)
2644 driver
->free_entity (entity
);
2649 XSETCDR (cache
, Qnil
);
2653 static Lisp_Object scratch_font_spec
, scratch_font_prefer
;
2655 /* Check each font-entity in VEC, and return a list of font-entities
2656 that satisfy these conditions:
2657 (1) matches with SPEC and SIZE if SPEC is not nil, and
2658 (2) doesn't match with any regexps in Vface_ignored_fonts (if non-nil).
2662 font_delete_unmatched (Lisp_Object vec
, Lisp_Object spec
, int size
)
2664 Lisp_Object entity
, val
;
2665 enum font_property_index prop
;
2668 for (val
= Qnil
, i
= ASIZE (vec
) - 1; i
>= 0; i
--)
2670 entity
= AREF (vec
, i
);
2671 if (! NILP (Vface_ignored_fonts
))
2675 Lisp_Object tail
, regexp
;
2677 namelen
= font_unparse_xlfd (entity
, 0, name
, 256);
2680 for (tail
= Vface_ignored_fonts
; CONSP (tail
); tail
= XCDR (tail
))
2682 regexp
= XCAR (tail
);
2683 if (STRINGP (regexp
)
2684 && fast_c_string_match_ignore_case (regexp
, name
,
2694 val
= Fcons (entity
, val
);
2697 for (prop
= FONT_WEIGHT_INDEX
; prop
< FONT_SIZE_INDEX
; prop
++)
2698 if (INTEGERP (AREF (spec
, prop
))
2699 && ((XINT (AREF (spec
, prop
)) >> 8)
2700 != (XINT (AREF (entity
, prop
)) >> 8)))
2701 prop
= FONT_SPEC_MAX
;
2702 if (prop
< FONT_SPEC_MAX
2704 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2706 int diff
= XINT (AREF (entity
, FONT_SIZE_INDEX
)) - size
;
2708 if (eabs (diff
) > FONT_PIXEL_SIZE_QUANTUM
)
2709 prop
= FONT_SPEC_MAX
;
2711 if (prop
< FONT_SPEC_MAX
2712 && INTEGERP (AREF (spec
, FONT_DPI_INDEX
))
2713 && INTEGERP (AREF (entity
, FONT_DPI_INDEX
))
2714 && XINT (AREF (entity
, FONT_DPI_INDEX
)) != 0
2715 && ! EQ (AREF (spec
, FONT_DPI_INDEX
), AREF (entity
, FONT_DPI_INDEX
)))
2716 prop
= FONT_SPEC_MAX
;
2717 if (prop
< FONT_SPEC_MAX
2718 && INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
2719 && INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
2720 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) != 0
2721 && ! EQ (AREF (spec
, FONT_AVGWIDTH_INDEX
),
2722 AREF (entity
, FONT_AVGWIDTH_INDEX
)))
2723 prop
= FONT_SPEC_MAX
;
2724 if (prop
< FONT_SPEC_MAX
)
2725 val
= Fcons (entity
, val
);
2727 return (Fvconcat (1, &val
));
2731 /* Return a list of vectors of font-entities matching with SPEC on
2732 FRAME. Each elements in the list is a vector of entities from the
2733 same font-driver. */
2736 font_list_entities (struct frame
*f
, Lisp_Object spec
)
2738 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2739 Lisp_Object ftype
, val
;
2740 Lisp_Object list
= Qnil
;
2742 bool need_filtering
= 0;
2745 eassert (FONT_SPEC_P (spec
));
2747 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2748 size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
2749 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
2750 size
= font_pixel_size (f
, spec
);
2754 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2755 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2756 ASET (scratch_font_spec
, i
, AREF (spec
, i
));
2757 for (i
= FONT_WEIGHT_INDEX
; i
< FONT_EXTRA_INDEX
; i
++)
2758 if (i
!= FONT_SPACING_INDEX
)
2760 ASET (scratch_font_spec
, i
, Qnil
);
2761 if (! NILP (AREF (spec
, i
)))
2764 ASET (scratch_font_spec
, FONT_SPACING_INDEX
, AREF (spec
, FONT_SPACING_INDEX
));
2765 ASET (scratch_font_spec
, FONT_EXTRA_INDEX
, AREF (spec
, FONT_EXTRA_INDEX
));
2767 for (; driver_list
; driver_list
= driver_list
->next
)
2769 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2771 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2773 ASET (scratch_font_spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2774 val
= assoc_no_quit (scratch_font_spec
, XCDR (cache
));
2779 val
= driver_list
->driver
->list (f
, scratch_font_spec
);
2782 Lisp_Object copy
= copy_font_spec (scratch_font_spec
);
2784 val
= Fvconcat (1, &val
);
2785 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2786 XSETCDR (cache
, Fcons (Fcons (copy
, val
), XCDR (cache
)));
2789 if (VECTORP (val
) && ASIZE (val
) > 0
2791 || ! NILP (Vface_ignored_fonts
)))
2792 val
= font_delete_unmatched (val
, need_filtering
? spec
: Qnil
, size
);
2793 if (VECTORP (val
) && ASIZE (val
) > 0)
2794 list
= Fcons (val
, list
);
2797 list
= Fnreverse (list
);
2798 FONT_ADD_LOG ("list", spec
, list
);
2803 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2804 nil, is an array of face's attributes, which specifies preferred
2805 font-related attributes. */
2808 font_matching_entity (struct frame
*f
, Lisp_Object
*attrs
, Lisp_Object spec
)
2810 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2811 Lisp_Object ftype
, size
, entity
;
2812 Lisp_Object work
= copy_font_spec (spec
);
2814 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2815 size
= AREF (spec
, FONT_SIZE_INDEX
);
2818 ASET (work
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2819 FONT_SET_STYLE (work
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
2820 FONT_SET_STYLE (work
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
2821 FONT_SET_STYLE (work
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
2824 for (; driver_list
; driver_list
= driver_list
->next
)
2826 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2828 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2830 ASET (work
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2831 entity
= assoc_no_quit (work
, XCDR (cache
));
2833 entity
= AREF (XCDR (entity
), 0);
2836 entity
= driver_list
->driver
->match (f
, work
);
2839 Lisp_Object copy
= copy_font_spec (work
);
2840 Lisp_Object match
= Fvector (1, &entity
);
2842 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2843 XSETCDR (cache
, Fcons (Fcons (copy
, match
), XCDR (cache
)));
2846 if (! NILP (entity
))
2849 FONT_ADD_LOG ("match", work
, entity
);
2854 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2855 opened font object. */
2858 font_open_entity (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
2860 struct font_driver_list
*driver_list
;
2861 Lisp_Object objlist
, size
, val
, font_object
;
2863 int min_width
, height
, psize
;
2865 eassert (FONT_ENTITY_P (entity
));
2866 size
= AREF (entity
, FONT_SIZE_INDEX
);
2867 if (XINT (size
) != 0)
2868 pixel_size
= XINT (size
);
2870 val
= AREF (entity
, FONT_TYPE_INDEX
);
2871 for (driver_list
= f
->font_driver_list
;
2872 driver_list
&& ! EQ (driver_list
->driver
->type
, val
);
2873 driver_list
= driver_list
->next
);
2877 for (objlist
= AREF (entity
, FONT_OBJLIST_INDEX
); CONSP (objlist
);
2878 objlist
= XCDR (objlist
))
2880 Lisp_Object fn
= XCAR (objlist
);
2881 if (! NILP (AREF (fn
, FONT_TYPE_INDEX
))
2882 && XFONT_OBJECT (fn
)->pixel_size
== pixel_size
)
2884 if (driver_list
->driver
->cached_font_ok
== NULL
2885 || driver_list
->driver
->cached_font_ok (f
, fn
, entity
))
2890 /* We always open a font of manageable size; i.e non-zero average
2891 width and height. */
2892 for (psize
= pixel_size
; ; psize
++)
2894 font_object
= driver_list
->driver
->open (f
, entity
, psize
);
2895 if (NILP (font_object
))
2897 font
= XFONT_OBJECT (font_object
);
2898 if (font
->average_width
> 0 && font
->height
> 0)
2901 ASET (font_object
, FONT_SIZE_INDEX
, make_number (pixel_size
));
2902 FONT_ADD_LOG ("open", entity
, font_object
);
2903 ASET (entity
, FONT_OBJLIST_INDEX
,
2904 Fcons (font_object
, AREF (entity
, FONT_OBJLIST_INDEX
)));
2906 font
= XFONT_OBJECT (font_object
);
2907 min_width
= (font
->min_width
? font
->min_width
2908 : font
->average_width
? font
->average_width
2909 : font
->space_width
? font
->space_width
2912 int font_ascent
, font_descent
;
2913 get_font_ascent_descent (font
, &font_ascent
, &font_descent
);
2914 height
= font_ascent
+ font_descent
;
2917 #ifdef HAVE_WINDOW_SYSTEM
2918 FRAME_DISPLAY_INFO (f
)->n_fonts
++;
2919 if (FRAME_DISPLAY_INFO (f
)->n_fonts
== 1)
2921 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
;
2922 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
;
2923 f
->fonts_changed
= 1;
2927 if (FRAME_SMALLEST_CHAR_WIDTH (f
) > min_width
)
2928 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
, f
->fonts_changed
= 1;
2929 if (FRAME_SMALLEST_FONT_HEIGHT (f
) > height
)
2930 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
, f
->fonts_changed
= 1;
2938 /* Close FONT_OBJECT that is opened on frame F. */
2941 font_close_object (struct frame
*f
, Lisp_Object font_object
)
2943 struct font
*font
= XFONT_OBJECT (font_object
);
2945 if (NILP (AREF (font_object
, FONT_TYPE_INDEX
)))
2946 /* Already closed. */
2948 FONT_ADD_LOG ("close", font_object
, Qnil
);
2949 font
->driver
->close (font
);
2950 #ifdef HAVE_WINDOW_SYSTEM
2951 eassert (FRAME_DISPLAY_INFO (f
)->n_fonts
);
2952 FRAME_DISPLAY_INFO (f
)->n_fonts
--;
2957 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2958 FONT is a font-entity and it must be opened to check. */
2961 font_has_char (struct frame
*f
, Lisp_Object font
, int c
)
2965 if (FONT_ENTITY_P (font
))
2967 Lisp_Object type
= AREF (font
, FONT_TYPE_INDEX
);
2968 struct font_driver_list
*driver_list
;
2970 for (driver_list
= f
->font_driver_list
;
2971 driver_list
&& ! EQ (driver_list
->driver
->type
, type
);
2972 driver_list
= driver_list
->next
);
2975 if (! driver_list
->driver
->has_char
)
2977 return driver_list
->driver
->has_char (font
, c
);
2980 eassert (FONT_OBJECT_P (font
));
2981 fontp
= XFONT_OBJECT (font
);
2982 if (fontp
->driver
->has_char
)
2984 int result
= fontp
->driver
->has_char (font
, c
);
2989 return (fontp
->driver
->encode_char (fontp
, c
) != FONT_INVALID_CODE
);
2993 /* Return the glyph ID of FONT_OBJECT for character C. */
2996 font_encode_char (Lisp_Object font_object
, int c
)
3000 eassert (FONT_OBJECT_P (font_object
));
3001 font
= XFONT_OBJECT (font_object
);
3002 return font
->driver
->encode_char (font
, c
);
3006 /* Return the name of FONT_OBJECT. */
3009 font_get_name (Lisp_Object font_object
)
3011 eassert (FONT_OBJECT_P (font_object
));
3012 return AREF (font_object
, FONT_NAME_INDEX
);
3016 /* Create a new font spec from FONT_NAME, and return it. If FONT_NAME
3017 could not be parsed by font_parse_name, return Qnil. */
3020 font_spec_from_name (Lisp_Object font_name
)
3022 Lisp_Object spec
= Ffont_spec (0, NULL
);
3024 CHECK_STRING (font_name
);
3025 if (font_parse_name (SSDATA (font_name
), SBYTES (font_name
), spec
) == -1)
3027 font_put_extra (spec
, QCname
, font_name
);
3028 font_put_extra (spec
, QCuser_spec
, font_name
);
3034 font_clear_prop (Lisp_Object
*attrs
, enum font_property_index prop
)
3036 Lisp_Object font
= attrs
[LFACE_FONT_INDEX
];
3041 if (! NILP (Ffont_get (font
, QCname
)))
3043 font
= copy_font_spec (font
);
3044 font_put_extra (font
, QCname
, Qnil
);
3047 if (NILP (AREF (font
, prop
))
3048 && prop
!= FONT_FAMILY_INDEX
3049 && prop
!= FONT_FOUNDRY_INDEX
3050 && prop
!= FONT_WIDTH_INDEX
3051 && prop
!= FONT_SIZE_INDEX
)
3053 if (EQ (font
, attrs
[LFACE_FONT_INDEX
]))
3054 font
= copy_font_spec (font
);
3055 ASET (font
, prop
, Qnil
);
3056 if (prop
== FONT_FAMILY_INDEX
|| prop
== FONT_FOUNDRY_INDEX
)
3058 if (prop
== FONT_FAMILY_INDEX
)
3060 ASET (font
, FONT_FOUNDRY_INDEX
, Qnil
);
3061 /* If we are setting the font family, we must also clear
3062 FONT_WIDTH_INDEX to avoid rejecting families that lack
3063 support for some widths. */
3064 ASET (font
, FONT_WIDTH_INDEX
, Qnil
);
3066 ASET (font
, FONT_ADSTYLE_INDEX
, Qnil
);
3067 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
3068 ASET (font
, FONT_SIZE_INDEX
, Qnil
);
3069 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3070 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3071 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3073 else if (prop
== FONT_SIZE_INDEX
)
3075 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3076 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3077 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3079 else if (prop
== FONT_WIDTH_INDEX
)
3080 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3081 attrs
[LFACE_FONT_INDEX
] = font
;
3084 /* Select a font from ENTITIES (list of font-entity vectors) that
3085 supports C and is the best match for ATTRS and PIXEL_SIZE. */
3088 font_select_entity (struct frame
*f
, Lisp_Object entities
,
3089 Lisp_Object
*attrs
, int pixel_size
, int c
)
3091 Lisp_Object font_entity
;
3095 if (NILP (XCDR (entities
))
3096 && ASIZE (XCAR (entities
)) == 1)
3098 font_entity
= AREF (XCAR (entities
), 0);
3099 if (c
< 0 || font_has_char (f
, font_entity
, c
) > 0)
3104 /* Sort fonts by properties specified in ATTRS. */
3105 prefer
= scratch_font_prefer
;
3107 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
3108 ASET (prefer
, i
, Qnil
);
3109 if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3111 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3113 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
3114 ASET (prefer
, i
, AREF (face_font
, i
));
3116 if (NILP (AREF (prefer
, FONT_WEIGHT_INDEX
)))
3117 FONT_SET_STYLE (prefer
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
3118 if (NILP (AREF (prefer
, FONT_SLANT_INDEX
)))
3119 FONT_SET_STYLE (prefer
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
3120 if (NILP (AREF (prefer
, FONT_WIDTH_INDEX
)))
3121 FONT_SET_STYLE (prefer
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
3122 ASET (prefer
, FONT_SIZE_INDEX
, make_number (pixel_size
));
3124 return font_sort_entities (entities
, prefer
, f
, c
);
3127 /* Return a font-entity that satisfies SPEC and is the best match for
3128 face's font related attributes in ATTRS. C, if not negative, is a
3129 character that the entity must support. */
3132 font_find_for_lface (struct frame
*f
, Lisp_Object
*attrs
, Lisp_Object spec
, int c
)
3135 Lisp_Object entities
, val
;
3136 Lisp_Object foundry
[3], *family
, registry
[3], adstyle
[3];
3141 registry
[0] = AREF (spec
, FONT_REGISTRY_INDEX
);
3142 if (NILP (registry
[0]))
3144 registry
[0] = DEFAULT_ENCODING
;
3145 registry
[1] = Qascii_0
;
3146 registry
[2] = zero_vector
;
3149 registry
[1] = zero_vector
;
3151 if (c
>= 0 && ! NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
3153 struct charset
*encoding
, *repertory
;
3155 if (font_registry_charsets (AREF (spec
, FONT_REGISTRY_INDEX
),
3156 &encoding
, &repertory
) < 0)
3159 && ENCODE_CHAR (repertory
, c
) == CHARSET_INVALID_CODE (repertory
))
3161 else if (c
> encoding
->max_char
)
3165 work
= copy_font_spec (spec
);
3166 ASET (work
, FONT_TYPE_INDEX
, AREF (spec
, FONT_TYPE_INDEX
));
3167 pixel_size
= font_pixel_size (f
, spec
);
3168 if (pixel_size
== 0 && INTEGERP (attrs
[LFACE_HEIGHT_INDEX
]))
3170 double pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3172 pixel_size
= POINT_TO_PIXEL (pt
/ 10, FRAME_RES_Y (f
));
3176 ASET (work
, FONT_SIZE_INDEX
, Qnil
);
3177 foundry
[0] = AREF (work
, FONT_FOUNDRY_INDEX
);
3178 if (! NILP (foundry
[0]))
3179 foundry
[1] = zero_vector
;
3180 else if (STRINGP (attrs
[LFACE_FOUNDRY_INDEX
]))
3182 val
= attrs
[LFACE_FOUNDRY_INDEX
];
3183 foundry
[0] = font_intern_prop (SSDATA (val
), SBYTES (val
), 1);
3185 foundry
[2] = zero_vector
;
3188 foundry
[0] = Qnil
, foundry
[1] = zero_vector
;
3190 adstyle
[0] = AREF (work
, FONT_ADSTYLE_INDEX
);
3191 if (! NILP (adstyle
[0]))
3192 adstyle
[1] = zero_vector
;
3193 else if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3195 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3197 if (! NILP (AREF (face_font
, FONT_ADSTYLE_INDEX
)))
3199 adstyle
[0] = AREF (face_font
, FONT_ADSTYLE_INDEX
);
3201 adstyle
[2] = zero_vector
;
3204 adstyle
[0] = Qnil
, adstyle
[1] = zero_vector
;
3207 adstyle
[0] = Qnil
, adstyle
[1] = zero_vector
;
3210 val
= AREF (work
, FONT_FAMILY_INDEX
);
3211 if (NILP (val
) && STRINGP (attrs
[LFACE_FAMILY_INDEX
]))
3213 val
= attrs
[LFACE_FAMILY_INDEX
];
3214 val
= font_intern_prop (SSDATA (val
), SBYTES (val
), 1);
3216 Lisp_Object familybuf
[3];
3221 family
[1] = zero_vector
; /* terminator. */
3226 = Fassoc_string (val
, Vface_alternative_font_family_alist
, Qt
);
3228 if (! NILP (alters
))
3230 EMACS_INT alterslen
= XFASTINT (Flength (alters
));
3231 SAFE_ALLOCA_LISP (family
, alterslen
+ 2);
3232 for (i
= 0; CONSP (alters
); i
++, alters
= XCDR (alters
))
3233 family
[i
] = XCAR (alters
);
3234 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3236 family
[i
] = zero_vector
;
3243 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3245 family
[i
] = zero_vector
;
3249 for (i
= 0; SYMBOLP (family
[i
]); i
++)
3251 ASET (work
, FONT_FAMILY_INDEX
, family
[i
]);
3252 for (j
= 0; SYMBOLP (foundry
[j
]); j
++)
3254 ASET (work
, FONT_FOUNDRY_INDEX
, foundry
[j
]);
3255 for (k
= 0; SYMBOLP (registry
[k
]); k
++)
3257 ASET (work
, FONT_REGISTRY_INDEX
, registry
[k
]);
3258 for (l
= 0; SYMBOLP (adstyle
[l
]); l
++)
3260 ASET (work
, FONT_ADSTYLE_INDEX
, adstyle
[l
]);
3261 entities
= font_list_entities (f
, work
);
3262 if (! NILP (entities
))
3264 val
= font_select_entity (f
, entities
,
3265 attrs
, pixel_size
, c
);
3283 font_open_for_lface (struct frame
*f
, Lisp_Object entity
, Lisp_Object
*attrs
, Lisp_Object spec
)
3287 if (INTEGERP (AREF (entity
, FONT_SIZE_INDEX
))
3288 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
3289 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
3292 if (FONT_SPEC_P (spec
) && ! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
3293 size
= font_pixel_size (f
, spec
);
3297 if (INTEGERP (attrs
[LFACE_HEIGHT_INDEX
]))
3298 pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3301 struct face
*def
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
3302 Lisp_Object height
= def
->lface
[LFACE_HEIGHT_INDEX
];
3303 eassert (INTEGERP (height
));
3308 size
= POINT_TO_PIXEL (pt
, FRAME_RES_Y (f
));
3312 Lisp_Object ffsize
= get_frame_param (f
, Qfontsize
);
3313 size
= (NUMBERP (ffsize
)
3314 ? POINT_TO_PIXEL (XINT (ffsize
), FRAME_RES_Y (f
)) : 0);
3318 size
*= font_rescale_ratio (entity
);
3321 return font_open_entity (f
, entity
, size
);
3325 /* Find a font that satisfies SPEC and is the best match for
3326 face's attributes in ATTRS on FRAME, and return the opened
3330 font_load_for_lface (struct frame
*f
, Lisp_Object
*attrs
, Lisp_Object spec
)
3332 Lisp_Object entity
, name
;
3334 entity
= font_find_for_lface (f
, attrs
, spec
, -1);
3337 /* No font is listed for SPEC, but each font-backend may have
3338 different criteria about "font matching". So, try it. */
3339 entity
= font_matching_entity (f
, attrs
, spec
);
3340 /* Perhaps the user asked for a font "Foobar-123", and we
3341 interpreted "-123" as the size, whereas it really is part of
3342 the name. So we reset the size to nil and the family name to
3343 the entire "Foobar-123" thing, and try again with that. */
3346 name
= Ffont_get (spec
, QCuser_spec
);
3349 char *p
= SSDATA (name
), *q
= strrchr (p
, '-');
3351 if (q
!= NULL
&& c_isdigit (q
[1]))
3354 double font_size
= strtod (q
+ 1, &tail
);
3356 if (font_size
> 0 && tail
!= q
+ 1)
3358 Lisp_Object lsize
= Ffont_get (spec
, QCsize
);
3360 if ((FLOATP (lsize
) && XFLOAT_DATA (lsize
) == font_size
)
3361 || (INTEGERP (lsize
) && XINT (lsize
) == font_size
))
3363 ASET (spec
, FONT_FAMILY_INDEX
,
3364 font_intern_prop (p
, tail
- p
, 1));
3365 ASET (spec
, FONT_SIZE_INDEX
, Qnil
);
3366 entity
= font_matching_entity (f
, attrs
, spec
);
3375 /* Don't lose the original name that was put in initially. We need
3376 it to re-apply the font when font parameters (like hinting or dpi) have
3378 entity
= font_open_for_lface (f
, entity
, attrs
, spec
);
3381 name
= Ffont_get (spec
, QCuser_spec
);
3382 if (STRINGP (name
)) font_put_extra (entity
, QCuser_spec
, name
);
3388 /* Make FACE on frame F ready to use the font opened for FACE. */
3391 font_prepare_for_face (struct frame
*f
, struct face
*face
)
3393 if (face
->font
->driver
->prepare_face
)
3394 face
->font
->driver
->prepare_face (f
, face
);
3398 /* Make FACE on frame F stop using the font opened for FACE. */
3401 font_done_for_face (struct frame
*f
, struct face
*face
)
3403 if (face
->font
->driver
->done_face
)
3404 face
->font
->driver
->done_face (f
, face
);
3408 /* Open a font that is a match for font-spec SPEC on frame F. If no proper
3409 font is found, return Qnil. */
3412 font_open_by_spec (struct frame
*f
, Lisp_Object spec
)
3414 Lisp_Object attrs
[LFACE_VECTOR_SIZE
];
3416 /* We set up the default font-related attributes of a face to prefer
3418 attrs
[LFACE_FAMILY_INDEX
] = attrs
[LFACE_FOUNDRY_INDEX
] = Qnil
;
3419 attrs
[LFACE_SWIDTH_INDEX
] = attrs
[LFACE_WEIGHT_INDEX
]
3420 = attrs
[LFACE_SLANT_INDEX
] = Qnormal
;
3422 attrs
[LFACE_HEIGHT_INDEX
] = make_number (120);
3424 attrs
[LFACE_HEIGHT_INDEX
] = make_number (0);
3426 attrs
[LFACE_FONT_INDEX
] = Qnil
;
3428 return font_load_for_lface (f
, attrs
, spec
);
3432 /* Open a font that matches NAME on frame F. If no proper font is
3433 found, return Qnil. */
3436 font_open_by_name (struct frame
*f
, Lisp_Object name
)
3438 Lisp_Object spec
= CALLN (Ffont_spec
, QCname
, name
);
3439 Lisp_Object ret
= font_open_by_spec (f
, spec
);
3440 /* Do not lose name originally put in. */
3442 font_put_extra (ret
, QCuser_spec
, name
);
3448 /* Register font-driver DRIVER. This function is used in two ways.
3450 The first is with frame F non-NULL. In this case, make DRIVER
3451 available (but not yet activated) on F. All frame creators
3452 (e.g. Fx_create_frame) must call this function at least once with
3453 an available font-driver.
3455 The second is with frame F NULL. In this case, DRIVER is globally
3456 registered in the variable `font_driver_list'. All font-driver
3457 implementations must call this function in its syms_of_XXXX
3458 (e.g. syms_of_xfont). */
3461 register_font_driver (struct font_driver
*driver
, struct frame
*f
)
3463 struct font_driver_list
*root
= f
? f
->font_driver_list
: font_driver_list
;
3464 struct font_driver_list
*prev
, *list
;
3466 #ifdef HAVE_WINDOW_SYSTEM
3467 if (f
&& ! driver
->draw
)
3468 error ("Unusable font driver for a frame: %s",
3469 SDATA (SYMBOL_NAME (driver
->type
)));
3470 #endif /* HAVE_WINDOW_SYSTEM */
3472 for (prev
= NULL
, list
= root
; list
; prev
= list
, list
= list
->next
)
3473 if (EQ (list
->driver
->type
, driver
->type
))
3474 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver
->type
)));
3476 list
= xmalloc (sizeof *list
);
3478 list
->driver
= driver
;
3483 f
->font_driver_list
= list
;
3485 font_driver_list
= list
;
3491 free_font_driver_list (struct frame
*f
)
3493 struct font_driver_list
*list
, *next
;
3495 for (list
= f
->font_driver_list
; list
; list
= next
)
3500 f
->font_driver_list
= NULL
;
3504 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3505 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3506 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3508 A caller must free all realized faces if any in advance. The
3509 return value is a list of font backends actually made used on
3513 font_update_drivers (struct frame
*f
, Lisp_Object new_drivers
)
3515 Lisp_Object active_drivers
= Qnil
;
3516 struct font_driver_list
*list
;
3518 /* At first, turn off non-requested drivers, and turn on requested
3520 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3522 struct font_driver
*driver
= list
->driver
;
3523 if ((EQ (new_drivers
, Qt
) || ! NILP (Fmemq (driver
->type
, new_drivers
)))
3528 if (driver
->end_for_frame
)
3529 driver
->end_for_frame (f
);
3530 font_finish_cache (f
, driver
);
3535 if (! driver
->start_for_frame
3536 || driver
->start_for_frame (f
) == 0)
3538 font_prepare_cache (f
, driver
);
3545 if (NILP (new_drivers
))
3548 if (! EQ (new_drivers
, Qt
))
3550 /* Re-order the driver list according to new_drivers. */
3551 struct font_driver_list
**list_table
, **next
;
3556 SAFE_NALLOCA (list_table
, 1, num_font_drivers
+ 1);
3557 for (i
= 0, tail
= new_drivers
; ! NILP (tail
); tail
= XCDR (tail
))
3559 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3560 if (list
->on
&& EQ (list
->driver
->type
, XCAR (tail
)))
3563 list_table
[i
++] = list
;
3565 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3567 list_table
[i
++] = list
;
3568 list_table
[i
] = NULL
;
3570 next
= &f
->font_driver_list
;
3571 for (i
= 0; list_table
[i
]; i
++)
3573 *next
= list_table
[i
];
3574 next
= &(*next
)->next
;
3579 if (! f
->font_driver_list
->on
)
3580 { /* None of the drivers is enabled: enable them all.
3581 Happens if you set the list of drivers to (xft x) in your .emacs
3582 and then use it under w32 or ns. */
3583 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3585 struct font_driver
*driver
= list
->driver
;
3586 eassert (! list
->on
);
3587 if (! driver
->start_for_frame
3588 || driver
->start_for_frame (f
) == 0)
3590 font_prepare_cache (f
, driver
);
3597 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3599 active_drivers
= nconc2 (active_drivers
, list1 (list
->driver
->type
));
3600 return active_drivers
;
3603 #if defined (HAVE_XFT) || defined (HAVE_FREETYPE)
3606 fset_font_data (struct frame
*f
, Lisp_Object val
)
3612 font_put_frame_data (struct frame
*f
, Lisp_Object driver
, void *data
)
3614 Lisp_Object val
= assq_no_quit (driver
, f
->font_data
);
3617 fset_font_data (f
, Fdelq (val
, f
->font_data
));
3621 fset_font_data (f
, Fcons (Fcons (driver
, make_save_ptr (data
)),
3624 XSETCDR (val
, make_save_ptr (data
));
3629 font_get_frame_data (struct frame
*f
, Lisp_Object driver
)
3631 Lisp_Object val
= assq_no_quit (driver
, f
->font_data
);
3633 return NILP (val
) ? NULL
: XSAVE_POINTER (XCDR (val
), 0);
3636 #endif /* HAVE_XFT || HAVE_FREETYPE */
3638 /* Sets attributes on a font. Any properties that appear in ALIST and
3639 BOOLEAN_PROPERTIES or NON_BOOLEAN_PROPERTIES are set on the font.
3640 BOOLEAN_PROPERTIES and NON_BOOLEAN_PROPERTIES are NULL-terminated
3641 arrays of strings. This function is intended for use by the font
3642 drivers to implement their specific font_filter_properties. */
3644 font_filter_properties (Lisp_Object font
,
3646 const char *const boolean_properties
[],
3647 const char *const non_boolean_properties
[])
3652 /* Set boolean values to Qt or Qnil. */
3653 for (i
= 0; boolean_properties
[i
] != NULL
; ++i
)
3654 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
3656 Lisp_Object key
= XCAR (XCAR (it
));
3657 Lisp_Object val
= XCDR (XCAR (it
));
3658 char *keystr
= SSDATA (SYMBOL_NAME (key
));
3660 if (strcmp (boolean_properties
[i
], keystr
) == 0)
3662 const char *str
= INTEGERP (val
) ? (XINT (val
) ? "true" : "false")
3663 : SYMBOLP (val
) ? SSDATA (SYMBOL_NAME (val
))
3666 if (strcmp ("false", str
) == 0 || strcmp ("False", str
) == 0
3667 || strcmp ("FALSE", str
) == 0 || strcmp ("FcFalse", str
) == 0
3668 || strcmp ("off", str
) == 0 || strcmp ("OFF", str
) == 0
3669 || strcmp ("Off", str
) == 0)
3674 Ffont_put (font
, key
, val
);
3678 for (i
= 0; non_boolean_properties
[i
] != NULL
; ++i
)
3679 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
3681 Lisp_Object key
= XCAR (XCAR (it
));
3682 Lisp_Object val
= XCDR (XCAR (it
));
3683 char *keystr
= SSDATA (SYMBOL_NAME (key
));
3684 if (strcmp (non_boolean_properties
[i
], keystr
) == 0)
3685 Ffont_put (font
, key
, val
);
3690 /* Return the font used to draw character C by FACE at buffer position
3691 POS in window W. If STRING is non-nil, it is a string containing C
3692 at index POS. If C is negative, get C from the current buffer or
3696 font_at (int c
, ptrdiff_t pos
, struct face
*face
, struct window
*w
,
3701 Lisp_Object font_object
;
3703 multibyte
= (NILP (string
)
3704 ? ! NILP (BVAR (current_buffer
, enable_multibyte_characters
))
3705 : STRING_MULTIBYTE (string
));
3712 ptrdiff_t pos_byte
= CHAR_TO_BYTE (pos
);
3714 c
= FETCH_CHAR (pos_byte
);
3717 c
= FETCH_BYTE (pos
);
3723 multibyte
= STRING_MULTIBYTE (string
);
3726 ptrdiff_t pos_byte
= string_char_to_byte (string
, pos
);
3728 str
= SDATA (string
) + pos_byte
;
3729 c
= STRING_CHAR (str
);
3732 c
= SDATA (string
)[pos
];
3736 f
= XFRAME (w
->frame
);
3737 if (! FRAME_WINDOW_P (f
))
3744 if (STRINGP (string
))
3745 face_id
= face_at_string_position (w
, string
, pos
, 0, &endptr
,
3746 DEFAULT_FACE_ID
, false);
3748 face_id
= face_at_buffer_position (w
, pos
, &endptr
,
3749 pos
+ 100, false, -1);
3750 face
= FACE_FROM_ID (f
, face_id
);
3754 int face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3755 face
= FACE_FROM_ID (f
, face_id
);
3760 XSETFONT (font_object
, face
->font
);
3765 #ifdef HAVE_WINDOW_SYSTEM
3767 /* Check how many characters after character/byte position POS/POS_BYTE
3768 (at most to *LIMIT) can be displayed by the same font in the window W.
3769 FACE, if non-NULL, is the face selected for the character at POS.
3770 If STRING is not nil, it is the string to check instead of the current
3771 buffer. In that case, FACE must be not NULL.
3773 The return value is the font-object for the character at POS.
3774 *LIMIT is set to the position where that font can't be used.
3776 It is assured that the current buffer (or STRING) is multibyte. */
3779 font_range (ptrdiff_t pos
, ptrdiff_t pos_byte
, ptrdiff_t *limit
,
3780 struct window
*w
, struct face
*face
, Lisp_Object string
)
3784 Lisp_Object font_object
= Qnil
;
3792 face_id
= face_at_buffer_position (w
, pos
, &ignore
,
3794 face
= FACE_FROM_ID (XFRAME (w
->frame
), face_id
);
3800 while (pos
< *limit
)
3802 Lisp_Object category
;
3805 FETCH_CHAR_ADVANCE_NO_CHECK (c
, pos
, pos_byte
);
3807 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c
, string
, pos
, pos_byte
);
3808 category
= CHAR_TABLE_REF (Vunicode_category_table
, c
);
3809 if (INTEGERP (category
)
3810 && (XINT (category
) == UNICODE_CATEGORY_Cf
3811 || CHAR_VARIATION_SELECTOR_P (c
)))
3813 if (NILP (font_object
))
3815 font_object
= font_for_char (face
, c
, pos
- 1, string
);
3816 if (NILP (font_object
))
3820 if (font_encode_char (font_object
, c
) == FONT_INVALID_CODE
)
3830 DEFUN ("fontp", Ffontp
, Sfontp
, 1, 2, 0,
3831 doc
: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3832 Return nil otherwise.
3833 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3834 which kind of font it is. It must be one of `font-spec', `font-entity',
3836 (Lisp_Object object
, Lisp_Object extra_type
)
3838 if (NILP (extra_type
))
3839 return (FONTP (object
) ? Qt
: Qnil
);
3840 if (EQ (extra_type
, Qfont_spec
))
3841 return (FONT_SPEC_P (object
) ? Qt
: Qnil
);
3842 if (EQ (extra_type
, Qfont_entity
))
3843 return (FONT_ENTITY_P (object
) ? Qt
: Qnil
);
3844 if (EQ (extra_type
, Qfont_object
))
3845 return (FONT_OBJECT_P (object
) ? Qt
: Qnil
);
3846 wrong_type_argument (intern ("font-extra-type"), extra_type
);
3849 DEFUN ("font-spec", Ffont_spec
, Sfont_spec
, 0, MANY
, 0,
3850 doc
: /* Return a newly created font-spec with arguments as properties.
3852 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3853 valid font property name listed below:
3855 `:family', `:weight', `:slant', `:width'
3857 They are the same as face attributes of the same name. See
3858 `set-face-attribute'.
3862 VALUE must be a string or a symbol specifying the font foundry, e.g. `misc'.
3866 VALUE must be a string or a symbol specifying the additional
3867 typographic style information of a font, e.g. `sans'.
3871 VALUE must be a string or a symbol specifying the charset registry and
3872 encoding of a font, e.g. `iso8859-1'.
3876 VALUE must be a non-negative integer or a floating point number
3877 specifying the font size. It specifies the font size in pixels (if
3878 VALUE is an integer), or in points (if VALUE is a float).
3882 VALUE must be a string of XLFD-style or fontconfig-style font name.
3886 VALUE must be a symbol representing a script that the font must
3887 support. It may be a symbol representing a subgroup of a script
3888 listed in the variable `script-representative-chars'.
3892 VALUE must be a symbol whose name is a two-letter ISO-639 language
3893 name, e.g. `ja'. The value is matched against the "Additional Style"
3894 field of the XLFD spec of a font, if it's non-empty, on X, and
3895 against the codepages supported by the font on w32.
3899 VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
3900 required OpenType features.
3902 SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
3903 LANGSYS-TAG: OpenType language system tag symbol,
3904 or nil for the default language system.
3905 GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
3906 GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
3908 GSUB and GPOS may contain nil elements. In such a case, the font
3909 must not have any of the remaining elements.
3911 For instance, if the VALUE is `(thai nil nil (mark))', the font must
3912 be an OpenType font whose GPOS table of `thai' script's default
3913 language system must contain `mark' feature.
3915 usage: (font-spec ARGS...) */)
3916 (ptrdiff_t nargs
, Lisp_Object
*args
)
3918 Lisp_Object spec
= font_make_spec ();
3921 for (i
= 0; i
< nargs
; i
+= 2)
3923 Lisp_Object key
= args
[i
], val
;
3927 error ("No value for key `%s'", SDATA (SYMBOL_NAME (key
)));
3930 if (EQ (key
, QCname
))
3933 if (font_parse_name (SSDATA (val
), SBYTES (val
), spec
) < 0)
3934 error ("Invalid font name: %s", SSDATA (val
));
3935 font_put_extra (spec
, key
, val
);
3939 int idx
= get_font_prop_index (key
);
3943 val
= font_prop_validate (idx
, Qnil
, val
);
3944 if (idx
< FONT_EXTRA_INDEX
)
3945 ASET (spec
, idx
, val
);
3947 font_put_extra (spec
, key
, val
);
3950 font_put_extra (spec
, key
, font_prop_validate (0, key
, val
));
3956 /* Return a copy of FONT as a font-spec. For the sake of speed, this code
3957 relies on an internal stuff exposed from alloc.c and should be handled
3961 copy_font_spec (Lisp_Object font
)
3963 enum { font_spec_size
= VECSIZE (struct font_spec
) };
3964 Lisp_Object new_spec
, tail
, *pcdr
;
3965 struct font_spec
*spec
;
3969 /* Make an uninitialized font-spec object. */
3970 spec
= (struct font_spec
*) allocate_vector (font_spec_size
);
3971 XSETPVECTYPESIZE (spec
, PVEC_FONT
, FONT_SPEC_MAX
,
3972 font_spec_size
- FONT_SPEC_MAX
);
3974 spec
->props
[FONT_TYPE_INDEX
] = spec
->props
[FONT_EXTRA_INDEX
] = Qnil
;
3976 /* Copy basic properties FONT_FOUNDRY_INDEX..FONT_AVGWIDTH_INDEX. */
3977 memcpy (spec
->props
+ 1, XVECTOR (font
)->contents
+ 1,
3978 (FONT_EXTRA_INDEX
- 1) * word_size
);
3980 /* Copy an alist of extra information but discard :font-entity property. */
3981 pcdr
= spec
->props
+ FONT_EXTRA_INDEX
;
3982 for (tail
= AREF (font
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
3983 if (!EQ (XCAR (XCAR (tail
)), QCfont_entity
))
3984 *pcdr
= Fcons (XCAR (tail
), Qnil
), pcdr
= xcdr_addr (*pcdr
);
3986 XSETFONT (new_spec
, spec
);
3990 /* Merge font-specs FROM and TO, and return a new font-spec.
3991 Every specified property in FROM overrides the corresponding
3994 merge_font_spec (Lisp_Object from
, Lisp_Object to
)
3996 Lisp_Object extra
, tail
;
4001 to
= copy_font_spec (to
);
4002 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
4003 ASET (to
, i
, AREF (from
, i
));
4004 extra
= AREF (to
, FONT_EXTRA_INDEX
);
4005 for (tail
= AREF (from
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
4006 if (! EQ (XCAR (XCAR (tail
)), Qfont_entity
))
4008 Lisp_Object slot
= assq_no_quit (XCAR (XCAR (tail
)), extra
);
4011 XSETCDR (slot
, XCDR (XCAR (tail
)));
4013 extra
= Fcons (Fcons (XCAR (XCAR (tail
)), XCDR (XCAR (tail
))), extra
);
4015 ASET (to
, FONT_EXTRA_INDEX
, extra
);
4019 DEFUN ("font-get", Ffont_get
, Sfont_get
, 2, 2, 0,
4020 doc
: /* Return the value of FONT's property KEY.
4021 FONT is a font-spec, a font-entity, or a font-object.
4022 KEY is any symbol, but these are reserved for specific meanings:
4023 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
4024 :size, :name, :script, :otf
4025 See the documentation of `font-spec' for their meanings.
4026 In addition, if FONT is a font-entity or a font-object, values of
4027 :script and :otf are different from those of a font-spec as below:
4029 The value of :script may be a list of scripts that are supported by the font.
4031 The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
4032 representing the OpenType features supported by the font by this form:
4033 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4034 SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
4036 (Lisp_Object font
, Lisp_Object key
)
4044 idx
= get_font_prop_index (key
);
4045 if (idx
>= FONT_WEIGHT_INDEX
&& idx
<= FONT_WIDTH_INDEX
)
4046 return font_style_symbolic (font
, idx
, 0);
4047 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
4048 return AREF (font
, idx
);
4049 val
= Fassq (key
, AREF (font
, FONT_EXTRA_INDEX
));
4050 if (NILP (val
) && EQ (key
, QCotf
) && FONT_OBJECT_P (font
))
4052 struct font
*fontp
= XFONT_OBJECT (font
);
4054 if (fontp
->driver
->otf_capability
)
4055 val
= fontp
->driver
->otf_capability (fontp
);
4057 val
= Fcons (Qnil
, Qnil
);
4064 #ifdef HAVE_WINDOW_SYSTEM
4066 DEFUN ("font-face-attributes", Ffont_face_attributes
, Sfont_face_attributes
, 1, 2, 0,
4067 doc
: /* Return a plist of face attributes generated by FONT.
4068 FONT is a font name, a font-spec, a font-entity, or a font-object.
4069 The return value is a list of the form
4071 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
4073 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
4074 compatible with `set-face-attribute'. Some of these key-attribute pairs
4075 may be omitted from the list if they are not specified by FONT.
4077 The optional argument FRAME specifies the frame that the face attributes
4078 are to be displayed on. If omitted, the selected frame is used. */)
4079 (Lisp_Object font
, Lisp_Object frame
)
4081 struct frame
*f
= decode_live_frame (frame
);
4082 Lisp_Object plist
[10];
4088 int fontset
= fs_query_fontset (font
, 0);
4089 Lisp_Object name
= font
;
4091 font
= fontset_ascii (fontset
);
4092 font
= font_spec_from_name (name
);
4094 signal_error ("Invalid font name", name
);
4096 else if (! FONTP (font
))
4097 signal_error ("Invalid font object", font
);
4099 val
= AREF (font
, FONT_FAMILY_INDEX
);
4102 plist
[n
++] = QCfamily
;
4103 plist
[n
++] = SYMBOL_NAME (val
);
4106 val
= AREF (font
, FONT_SIZE_INDEX
);
4109 Lisp_Object font_dpi
= AREF (font
, FONT_DPI_INDEX
);
4110 int dpi
= INTEGERP (font_dpi
) ? XINT (font_dpi
) : FRAME_RES_Y (f
);
4111 plist
[n
++] = QCheight
;
4112 plist
[n
++] = make_number (PIXEL_TO_POINT (XINT (val
) * 10, dpi
));
4114 else if (FLOATP (val
))
4116 plist
[n
++] = QCheight
;
4117 plist
[n
++] = make_number (10 * (int) XFLOAT_DATA (val
));
4120 val
= FONT_WEIGHT_FOR_FACE (font
);
4123 plist
[n
++] = QCweight
;
4127 val
= FONT_SLANT_FOR_FACE (font
);
4130 plist
[n
++] = QCslant
;
4134 val
= FONT_WIDTH_FOR_FACE (font
);
4137 plist
[n
++] = QCwidth
;
4141 return Flist (n
, plist
);
4146 DEFUN ("font-put", Ffont_put
, Sfont_put
, 3, 3, 0,
4147 doc
: /* Set one property of FONT: give property KEY value VAL.
4148 FONT is a font-spec, a font-entity, or a font-object.
4150 If FONT is a font-spec, KEY can be any symbol. But if KEY is the one
4151 accepted by the function `font-spec' (which see), VAL must be what
4152 allowed in `font-spec'.
4154 If FONT is a font-entity or a font-object, KEY must not be the one
4155 accepted by `font-spec'. */)
4156 (Lisp_Object font
, Lisp_Object prop
, Lisp_Object val
)
4160 idx
= get_font_prop_index (prop
);
4161 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
4163 CHECK_FONT_SPEC (font
);
4164 ASET (font
, idx
, font_prop_validate (idx
, Qnil
, val
));
4168 if (EQ (prop
, QCname
)
4169 || EQ (prop
, QCscript
)
4170 || EQ (prop
, QClang
)
4171 || EQ (prop
, QCotf
))
4172 CHECK_FONT_SPEC (font
);
4175 font_put_extra (font
, prop
, font_prop_validate (0, prop
, val
));
4180 DEFUN ("list-fonts", Flist_fonts
, Slist_fonts
, 1, 4, 0,
4181 doc
: /* List available fonts matching FONT-SPEC on the current frame.
4182 Optional 2nd argument FRAME specifies the target frame.
4183 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4184 Optional 4th argument PREFER, if non-nil, is a font-spec to
4185 control the order of the returned list. Fonts are sorted by
4186 how close they are to PREFER. */)
4187 (Lisp_Object font_spec
, Lisp_Object frame
, Lisp_Object num
, Lisp_Object prefer
)
4189 struct frame
*f
= decode_live_frame (frame
);
4190 Lisp_Object vec
, list
;
4193 CHECK_FONT_SPEC (font_spec
);
4201 if (! NILP (prefer
))
4202 CHECK_FONT_SPEC (prefer
);
4204 list
= font_list_entities (f
, font_spec
);
4207 if (NILP (XCDR (list
))
4208 && ASIZE (XCAR (list
)) == 1)
4209 return list1 (AREF (XCAR (list
), 0));
4211 if (! NILP (prefer
))
4212 vec
= font_sort_entities (list
, prefer
, f
, 0);
4214 vec
= font_vconcat_entity_vectors (list
);
4215 if (n
== 0 || n
>= ASIZE (vec
))
4216 list
= CALLN (Fappend
, vec
, Qnil
);
4219 for (list
= Qnil
, n
--; n
>= 0; n
--)
4220 list
= Fcons (AREF (vec
, n
), list
);
4225 DEFUN ("font-family-list", Ffont_family_list
, Sfont_family_list
, 0, 1, 0,
4226 doc
: /* List available font families on the current frame.
4227 If FRAME is omitted or nil, the selected frame is used. */)
4230 struct frame
*f
= decode_live_frame (frame
);
4231 struct font_driver_list
*driver_list
;
4232 Lisp_Object list
= Qnil
;
4234 for (driver_list
= f
->font_driver_list
; driver_list
;
4235 driver_list
= driver_list
->next
)
4236 if (driver_list
->driver
->list_family
)
4238 Lisp_Object val
= driver_list
->driver
->list_family (f
);
4239 Lisp_Object tail
= list
;
4241 for (; CONSP (val
); val
= XCDR (val
))
4242 if (NILP (Fmemq (XCAR (val
), tail
))
4243 && SYMBOLP (XCAR (val
)))
4244 list
= Fcons (SYMBOL_NAME (XCAR (val
)), list
);
4249 DEFUN ("find-font", Ffind_font
, Sfind_font
, 1, 2, 0,
4250 doc
: /* Return a font-entity matching with FONT-SPEC on the current frame.
4251 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4252 (Lisp_Object font_spec
, Lisp_Object frame
)
4254 Lisp_Object val
= Flist_fonts (font_spec
, frame
, make_number (1), Qnil
);
4261 DEFUN ("font-xlfd-name", Ffont_xlfd_name
, Sfont_xlfd_name
, 1, 2, 0,
4262 doc
: /* Return XLFD name of FONT.
4263 FONT is a font-spec, font-entity, or font-object.
4264 If the name is too long for XLFD (maximum 255 chars), return nil.
4265 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4266 the consecutive wildcards are folded into one. */)
4267 (Lisp_Object font
, Lisp_Object fold_wildcards
)
4270 int namelen
, pixel_size
= 0;
4274 if (FONT_OBJECT_P (font
))
4276 Lisp_Object font_name
= AREF (font
, FONT_NAME_INDEX
);
4278 if (STRINGP (font_name
)
4279 && SDATA (font_name
)[0] == '-')
4281 if (NILP (fold_wildcards
))
4283 lispstpcpy (name
, font_name
);
4284 namelen
= SBYTES (font_name
);
4287 pixel_size
= XFONT_OBJECT (font
)->pixel_size
;
4289 namelen
= font_unparse_xlfd (font
, pixel_size
, name
, 256);
4293 if (! NILP (fold_wildcards
))
4295 char *p0
= name
, *p1
;
4297 while ((p1
= strstr (p0
, "-*-*")))
4299 strcpy (p1
, p1
+ 2);
4305 return make_string (name
, namelen
);
4309 clear_font_cache (struct frame
*f
)
4311 struct font_driver_list
*driver_list
= f
->font_driver_list
;
4313 for (; driver_list
; driver_list
= driver_list
->next
)
4314 if (driver_list
->on
)
4316 Lisp_Object val
, tmp
, cache
= driver_list
->driver
->get_cache (f
);
4320 && ! EQ (XCAR (XCAR (val
)), driver_list
->driver
->type
))
4322 eassert (! NILP (val
));
4323 tmp
= XCDR (XCAR (val
));
4324 if (XINT (XCAR (tmp
)) == 0)
4326 font_clear_cache (f
, XCAR (val
), driver_list
->driver
);
4327 XSETCDR (cache
, XCDR (val
));
4332 DEFUN ("clear-font-cache", Fclear_font_cache
, Sclear_font_cache
, 0, 0, 0,
4333 doc
: /* Clear font cache of each frame. */)
4336 Lisp_Object list
, frame
;
4338 FOR_EACH_FRAME (list
, frame
)
4339 clear_font_cache (XFRAME (frame
));
4346 font_fill_lglyph_metrics (Lisp_Object glyph
, Lisp_Object font_object
)
4348 struct font
*font
= XFONT_OBJECT (font_object
);
4349 unsigned code
= font
->driver
->encode_char (font
, LGLYPH_CHAR (glyph
));
4350 struct font_metrics metrics
;
4352 LGLYPH_SET_CODE (glyph
, code
);
4353 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4354 LGLYPH_SET_LBEARING (glyph
, metrics
.lbearing
);
4355 LGLYPH_SET_RBEARING (glyph
, metrics
.rbearing
);
4356 LGLYPH_SET_WIDTH (glyph
, metrics
.width
);
4357 LGLYPH_SET_ASCENT (glyph
, metrics
.ascent
);
4358 LGLYPH_SET_DESCENT (glyph
, metrics
.descent
);
4362 DEFUN ("font-shape-gstring", Ffont_shape_gstring
, Sfont_shape_gstring
, 1, 1, 0,
4363 doc
: /* Shape the glyph-string GSTRING.
4364 Shaping means substituting glyphs and/or adjusting positions of glyphs
4365 to get the correct visual image of character sequences set in the
4366 header of the glyph-string.
4368 If the shaping was successful, the value is GSTRING itself or a newly
4369 created glyph-string. Otherwise, the value is nil.
4371 See the documentation of `composition-get-gstring' for the format of
4373 (Lisp_Object gstring
)
4376 Lisp_Object font_object
, n
, glyph
;
4377 ptrdiff_t i
, from
, to
;
4379 if (! composition_gstring_p (gstring
))
4380 signal_error ("Invalid glyph-string: ", gstring
);
4381 if (! NILP (LGSTRING_ID (gstring
)))
4383 font_object
= LGSTRING_FONT (gstring
);
4384 CHECK_FONT_OBJECT (font_object
);
4385 font
= XFONT_OBJECT (font_object
);
4386 if (! font
->driver
->shape
)
4389 /* Try at most three times with larger gstring each time. */
4390 for (i
= 0; i
< 3; i
++)
4392 n
= font
->driver
->shape (gstring
);
4395 gstring
= larger_vector (gstring
,
4396 LGSTRING_GLYPH_LEN (gstring
), -1);
4398 if (i
== 3 || XINT (n
) == 0)
4400 if (XINT (n
) < LGSTRING_GLYPH_LEN (gstring
))
4401 LGSTRING_SET_GLYPH (gstring
, XINT (n
), Qnil
);
4403 /* Check FROM_IDX and TO_IDX of each GLYPH in GSTRING to assure that
4404 GLYPHS covers all characters (except for the last few ones) in
4405 GSTRING. More formally, provided that NCHARS is the number of
4406 characters in GSTRING and GLYPHS[i] is the ith glyph, FROM_IDX
4407 and TO_IDX of each glyph must satisfy these conditions:
4409 GLYPHS[0].FROM_IDX == 0
4410 GLYPHS[i].FROM_IDX <= GLYPHS[i].TO_IDX
4411 if (GLYPHS[i].FROM_IDX == GLYPHS[i-1].FROM_IDX)
4412 ;; GLYPHS[i] and GLYPHS[i-1] belongs to the same grapheme cluster
4413 GLYPHS[i].TO_IDX == GLYPHS[i-1].TO_IDX
4415 ;; Be sure to cover all characters.
4416 GLYPHS[i].FROM_IDX == GLYPHS[i-1].TO_IDX + 1 */
4417 glyph
= LGSTRING_GLYPH (gstring
, 0);
4418 from
= LGLYPH_FROM (glyph
);
4419 to
= LGLYPH_TO (glyph
);
4420 if (from
!= 0 || to
< from
)
4422 for (i
= 1; i
< LGSTRING_GLYPH_LEN (gstring
); i
++)
4424 glyph
= LGSTRING_GLYPH (gstring
, i
);
4427 if (! (LGLYPH_FROM (glyph
) <= LGLYPH_TO (glyph
)
4428 && (LGLYPH_FROM (glyph
) == from
4429 ? LGLYPH_TO (glyph
) == to
4430 : LGLYPH_FROM (glyph
) == to
+ 1)))
4432 from
= LGLYPH_FROM (glyph
);
4433 to
= LGLYPH_TO (glyph
);
4435 return composition_gstring_put_cache (gstring
, XINT (n
));
4441 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs
, Sfont_variation_glyphs
,
4443 doc
: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4444 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4446 VARIATION-SELECTOR is a character code of variation selection
4447 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4448 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4449 (Lisp_Object font_object
, Lisp_Object character
)
4451 unsigned variations
[256];
4456 CHECK_FONT_OBJECT (font_object
);
4457 CHECK_CHARACTER (character
);
4458 font
= XFONT_OBJECT (font_object
);
4459 if (! font
->driver
->get_variation_glyphs
)
4461 n
= font
->driver
->get_variation_glyphs (font
, XINT (character
), variations
);
4465 for (i
= 0; i
< 255; i
++)
4468 int vs
= (i
< 16 ? 0xFE00 + i
: 0xE0100 + (i
- 16));
4469 Lisp_Object code
= INTEGER_TO_CONS (variations
[i
]);
4470 val
= Fcons (Fcons (make_number (vs
), code
), val
);
4477 DEFUN ("font-drive-otf", Ffont_drive_otf
, Sfont_drive_otf
, 6, 6, 0,
4478 doc
: /* Apply OpenType features on glyph-string GSTRING-IN.
4479 OTF-FEATURES specifies which features to apply in this format:
4480 (SCRIPT LANGSYS GSUB GPOS)
4482 SCRIPT is a symbol specifying a script tag of OpenType,
4483 LANGSYS is a symbol specifying a langsys tag of OpenType,
4484 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4486 If LANGSYS is nil, the default langsys is selected.
4488 The features are applied in the order they appear in the list. The
4489 symbol `*' means to apply all available features not present in this
4490 list, and the remaining features are ignored. For instance, (vatu
4491 pstf * haln) is to apply vatu and pstf in this order, then to apply
4492 all available features other than vatu, pstf, and haln.
4494 The features are applied to the glyphs in the range FROM and TO of
4495 the glyph-string GSTRING-IN.
4497 If some feature is actually applicable, the resulting glyphs are
4498 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4499 this case, the value is the number of produced glyphs.
4501 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4504 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4505 produced in GSTRING-OUT, and the value is nil.
4507 See the documentation of `composition-get-gstring' for the format of
4509 (Lisp_Object otf_features
, Lisp_Object gstring_in
, Lisp_Object from
, Lisp_Object to
, Lisp_Object gstring_out
, Lisp_Object index
)
4511 Lisp_Object font_object
= LGSTRING_FONT (gstring_in
);
4516 check_otf_features (otf_features
);
4517 CHECK_FONT_OBJECT (font_object
);
4518 font
= XFONT_OBJECT (font_object
);
4519 if (! font
->driver
->otf_drive
)
4520 error ("Font backend %s can't drive OpenType GSUB table",
4521 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4522 CHECK_CONS (otf_features
);
4523 CHECK_SYMBOL (XCAR (otf_features
));
4524 val
= XCDR (otf_features
);
4525 CHECK_SYMBOL (XCAR (val
));
4526 val
= XCDR (otf_features
);
4529 len
= check_gstring (gstring_in
);
4530 CHECK_VECTOR (gstring_out
);
4531 CHECK_NATNUM (from
);
4533 CHECK_NATNUM (index
);
4535 if (XINT (from
) >= XINT (to
) || XINT (to
) > len
)
4536 args_out_of_range_3 (from
, to
, make_number (len
));
4537 if (XINT (index
) >= ASIZE (gstring_out
))
4538 args_out_of_range (index
, make_number (ASIZE (gstring_out
)));
4539 num
= font
->driver
->otf_drive (font
, otf_features
,
4540 gstring_in
, XINT (from
), XINT (to
),
4541 gstring_out
, XINT (index
), 0);
4544 return make_number (num
);
4547 DEFUN ("font-otf-alternates", Ffont_otf_alternates
, Sfont_otf_alternates
,
4549 doc
: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4550 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4552 (SCRIPT LANGSYS FEATURE ...)
4553 See the documentation of `font-drive-otf' for more detail.
4555 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4556 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4557 character code corresponding to the glyph or nil if there's no
4558 corresponding character. */)
4559 (Lisp_Object font_object
, Lisp_Object character
, Lisp_Object otf_features
)
4561 struct font
*font
= CHECK_FONT_GET_OBJECT (font_object
);
4562 Lisp_Object gstring_in
, gstring_out
, g
;
4563 Lisp_Object alternates
;
4566 if (! font
->driver
->otf_drive
)
4567 error ("Font backend %s can't drive OpenType GSUB table",
4568 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4569 CHECK_CHARACTER (character
);
4570 CHECK_CONS (otf_features
);
4572 gstring_in
= Ffont_make_gstring (font_object
, make_number (1));
4573 g
= LGSTRING_GLYPH (gstring_in
, 0);
4574 LGLYPH_SET_CHAR (g
, XINT (character
));
4575 gstring_out
= Ffont_make_gstring (font_object
, make_number (10));
4576 while ((num
= font
->driver
->otf_drive (font
, otf_features
, gstring_in
, 0, 1,
4577 gstring_out
, 0, 1)) < 0)
4578 gstring_out
= Ffont_make_gstring (font_object
,
4579 make_number (ASIZE (gstring_out
) * 2));
4581 for (i
= 0; i
< num
; i
++)
4583 Lisp_Object g
= LGSTRING_GLYPH (gstring_out
, i
);
4584 int c
= LGLYPH_CHAR (g
);
4585 unsigned code
= LGLYPH_CODE (g
);
4587 alternates
= Fcons (Fcons (make_number (code
),
4588 c
> 0 ? make_number (c
) : Qnil
),
4591 return Fnreverse (alternates
);
4597 DEFUN ("open-font", Fopen_font
, Sopen_font
, 1, 3, 0,
4598 doc
: /* Open FONT-ENTITY. */)
4599 (Lisp_Object font_entity
, Lisp_Object size
, Lisp_Object frame
)
4602 struct frame
*f
= decode_live_frame (frame
);
4604 CHECK_FONT_ENTITY (font_entity
);
4607 isize
= XINT (AREF (font_entity
, FONT_SIZE_INDEX
));
4610 CHECK_NUMBER_OR_FLOAT (size
);
4612 isize
= POINT_TO_PIXEL (XFLOAT_DATA (size
), FRAME_RES_Y (f
));
4614 isize
= XINT (size
);
4615 if (! (INT_MIN
<= isize
&& isize
<= INT_MAX
))
4616 args_out_of_range (font_entity
, size
);
4620 return font_open_entity (f
, font_entity
, isize
);
4623 DEFUN ("close-font", Fclose_font
, Sclose_font
, 1, 2, 0,
4624 doc
: /* Close FONT-OBJECT. */)
4625 (Lisp_Object font_object
, Lisp_Object frame
)
4627 CHECK_FONT_OBJECT (font_object
);
4628 font_close_object (decode_live_frame (frame
), font_object
);
4632 DEFUN ("query-font", Fquery_font
, Squery_font
, 1, 1, 0,
4633 doc
: /* Return information about FONT-OBJECT.
4634 The value is a vector:
4635 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4638 NAME is the font name, a string (or nil if the font backend doesn't
4641 FILENAME is the font file name, a string (or nil if the font backend
4642 doesn't provide a file name).
4644 PIXEL-SIZE is a pixel size by which the font is opened.
4646 SIZE is a maximum advance width of the font in pixels.
4648 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4651 CAPABILITY is a list whose first element is a symbol representing the
4652 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4653 remaining elements describe the details of the font capability.
4655 If the font is OpenType font, the form of the list is
4656 \(opentype GSUB GPOS)
4657 where GSUB shows which "GSUB" features the font supports, and GPOS
4658 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4659 lists of the format:
4660 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4662 If the font is not OpenType font, currently the length of the form is
4665 SCRIPT is a symbol representing OpenType script tag.
4667 LANGSYS is a symbol representing OpenType langsys tag, or nil
4668 representing the default langsys.
4670 FEATURE is a symbol representing OpenType feature tag.
4672 If the font is not OpenType font, CAPABILITY is nil. */)
4673 (Lisp_Object font_object
)
4675 struct font
*font
= CHECK_FONT_GET_OBJECT (font_object
);
4676 Lisp_Object val
= make_uninit_vector (9);
4678 ASET (val
, 0, AREF (font_object
, FONT_NAME_INDEX
));
4679 ASET (val
, 1, AREF (font_object
, FONT_FILE_INDEX
));
4680 ASET (val
, 2, make_number (font
->pixel_size
));
4681 ASET (val
, 3, make_number (font
->max_width
));
4682 ASET (val
, 4, make_number (font
->ascent
));
4683 ASET (val
, 5, make_number (font
->descent
));
4684 ASET (val
, 6, make_number (font
->space_width
));
4685 ASET (val
, 7, make_number (font
->average_width
));
4686 if (font
->driver
->otf_capability
)
4687 ASET (val
, 8, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
4689 ASET (val
, 8, Qnil
);
4693 DEFUN ("font-get-glyphs", Ffont_get_glyphs
, Sfont_get_glyphs
, 3, 4, 0,
4695 /* Return a vector of FONT-OBJECT's glyphs for the specified characters.
4696 FROM and TO are positions (integers or markers) specifying a region
4697 of the current buffer, and can be in either order. If the optional
4698 fourth arg OBJECT is not nil, it is a string or a vector containing
4699 the target characters between indices FROM and TO, which are treated
4702 Each element is a vector containing information of a glyph in this format:
4703 [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
4705 FROM is an index numbers of a character the glyph corresponds to.
4706 TO is the same as FROM.
4707 C is the character of the glyph.
4708 CODE is the glyph-code of C in FONT-OBJECT.
4709 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
4710 ADJUSTMENT is always nil.
4711 If FONT-OBJECT doesn't have a glyph for a character,
4712 the corresponding element is nil. */)
4713 (Lisp_Object font_object
, Lisp_Object from
, Lisp_Object to
,
4716 struct font
*font
= CHECK_FONT_GET_OBJECT (font_object
);
4718 Lisp_Object
*chars
, vec
;
4723 ptrdiff_t charpos
, bytepos
;
4725 validate_region (&from
, &to
);
4728 len
= XFASTINT (to
) - XFASTINT (from
);
4729 SAFE_ALLOCA_LISP (chars
, len
);
4730 charpos
= XFASTINT (from
);
4731 bytepos
= CHAR_TO_BYTE (charpos
);
4732 for (i
= 0; charpos
< XFASTINT (to
); i
++)
4735 FETCH_CHAR_ADVANCE (c
, charpos
, bytepos
);
4736 chars
[i
] = make_number (c
);
4739 else if (STRINGP (object
))
4741 const unsigned char *p
;
4742 ptrdiff_t ifrom
, ito
;
4744 validate_subarray (object
, from
, to
, SCHARS (object
), &ifrom
, &ito
);
4748 SAFE_ALLOCA_LISP (chars
, len
);
4750 if (STRING_MULTIBYTE (object
))
4754 /* Skip IFROM characters from the beginning. */
4755 for (i
= 0; i
< ifrom
; i
++)
4756 c
= STRING_CHAR_ADVANCE (p
);
4758 /* Now fetch an interesting characters. */
4759 for (i
= 0; i
< len
; i
++)
4761 c
= STRING_CHAR_ADVANCE (p
);
4762 chars
[i
] = make_number (c
);
4766 for (i
= 0; i
< len
; i
++)
4767 chars
[i
] = make_number (p
[ifrom
+ i
]);
4769 else if (VECTORP (object
))
4771 ptrdiff_t ifrom
, ito
;
4773 validate_subarray (object
, from
, to
, ASIZE (object
), &ifrom
, &ito
);
4777 for (i
= 0; i
< len
; i
++)
4779 Lisp_Object elt
= AREF (object
, ifrom
+ i
);
4780 CHECK_CHARACTER (elt
);
4782 chars
= aref_addr (object
, ifrom
);
4785 wrong_type_argument (Qarrayp
, object
);
4787 vec
= make_uninit_vector (len
);
4788 for (i
= 0; i
< len
; i
++)
4791 int c
= XFASTINT (chars
[i
]);
4793 struct font_metrics metrics
;
4795 code
= font
->driver
->encode_char (font
, c
);
4796 if (code
== FONT_INVALID_CODE
)
4798 ASET (vec
, i
, Qnil
);
4802 LGLYPH_SET_FROM (g
, i
);
4803 LGLYPH_SET_TO (g
, i
);
4804 LGLYPH_SET_CHAR (g
, c
);
4805 LGLYPH_SET_CODE (g
, code
);
4806 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4807 LGLYPH_SET_WIDTH (g
, metrics
.width
);
4808 LGLYPH_SET_LBEARING (g
, metrics
.lbearing
);
4809 LGLYPH_SET_RBEARING (g
, metrics
.rbearing
);
4810 LGLYPH_SET_ASCENT (g
, metrics
.ascent
);
4811 LGLYPH_SET_DESCENT (g
, metrics
.descent
);
4814 if (! VECTORP (object
))
4819 DEFUN ("font-match-p", Ffont_match_p
, Sfont_match_p
, 2, 2, 0,
4820 doc
: /* Return t if and only if font-spec SPEC matches with FONT.
4821 FONT is a font-spec, font-entity, or font-object. */)
4822 (Lisp_Object spec
, Lisp_Object font
)
4824 CHECK_FONT_SPEC (spec
);
4827 return (font_match_p (spec
, font
) ? Qt
: Qnil
);
4830 DEFUN ("font-at", Ffont_at
, Sfont_at
, 1, 3, 0,
4831 doc
: /* Return a font-object for displaying a character at POSITION.
4832 Optional second arg WINDOW, if non-nil, is a window displaying
4833 the current buffer. It defaults to the currently selected window.
4834 Optional third arg STRING, if non-nil, is a string containing the target
4835 character at index specified by POSITION. */)
4836 (Lisp_Object position
, Lisp_Object window
, Lisp_Object string
)
4838 struct window
*w
= decode_live_window (window
);
4842 if (XBUFFER (w
->contents
) != current_buffer
)
4843 error ("Specified window is not displaying the current buffer");
4844 CHECK_NUMBER_COERCE_MARKER (position
);
4845 if (! (BEGV
<= XINT (position
) && XINT (position
) < ZV
))
4846 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
4850 CHECK_NUMBER (position
);
4851 CHECK_STRING (string
);
4852 if (! (0 <= XINT (position
) && XINT (position
) < SCHARS (string
)))
4853 args_out_of_range (string
, position
);
4856 return font_at (-1, XINT (position
), NULL
, w
, string
);
4860 DEFUN ("draw-string", Fdraw_string
, Sdraw_string
, 2, 2, 0,
4861 doc
: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4862 The value is a number of glyphs drawn.
4863 Type C-l to recover what previously shown. */)
4864 (Lisp_Object font_object
, Lisp_Object string
)
4866 Lisp_Object frame
= selected_frame
;
4867 struct frame
*f
= XFRAME (frame
);
4873 CHECK_FONT_GET_OBJECT (font_object
, font
);
4874 CHECK_STRING (string
);
4875 len
= SCHARS (string
);
4876 code
= alloca (sizeof (unsigned) * len
);
4877 for (i
= 0; i
< len
; i
++)
4879 Lisp_Object ch
= Faref (string
, make_number (i
));
4883 code
[i
] = font
->driver
->encode_char (font
, c
);
4884 if (code
[i
] == FONT_INVALID_CODE
)
4887 face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4889 if (font
->driver
->prepare_face
)
4890 font
->driver
->prepare_face (f
, face
);
4891 width
= font
->driver
->text_extents (font
, code
, i
, NULL
);
4892 len
= font
->driver
->draw_text (f
, face
, 0, font
->ascent
, code
, i
, width
);
4893 if (font
->driver
->done_face
)
4894 font
->driver
->done_face (f
, face
);
4896 return make_number (len
);
4900 DEFUN ("frame-font-cache", Fframe_font_cache
, Sframe_font_cache
, 0, 1, 0,
4901 doc
: /* Return FRAME's font cache. Mainly used for debugging.
4902 If FRAME is omitted or nil, use the selected frame. */)
4905 #ifdef HAVE_WINDOW_SYSTEM
4906 struct frame
*f
= decode_live_frame (frame
);
4908 if (FRAME_WINDOW_P (f
))
4909 return FRAME_DISPLAY_INFO (f
)->name_list_element
;
4915 #endif /* FONT_DEBUG */
4917 #ifdef HAVE_WINDOW_SYSTEM
4919 DEFUN ("font-info", Ffont_info
, Sfont_info
, 1, 2, 0,
4920 doc
: /* Return information about a font named NAME on frame FRAME.
4921 If FRAME is omitted or nil, use the selected frame.
4923 The returned value is a vector:
4924 [ OPENED-NAME FULL-NAME SIZE HEIGHT BASELINE-OFFSET RELATIVE-COMPOSE
4925 DEFAULT-ASCENT MAX-WIDTH ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4928 OPENED-NAME is the name used for opening the font,
4929 FULL-NAME is the full name of the font,
4930 SIZE is the pixelsize of the font,
4931 HEIGHT is the pixel-height of the font (i.e., ascent + descent),
4932 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4933 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4934 how to compose characters,
4935 MAX-WIDTH is the maximum advance width of the font,
4936 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font
4938 FILENAME is the font file name, a string (or nil if the font backend
4939 doesn't provide a file name).
4940 CAPABILITY is a list whose first element is a symbol representing the
4941 font format, one of x, opentype, truetype, type1, pcf, or bdf.
4942 The remaining elements describe the details of the font capabilities,
4945 If the font is OpenType font, the form of the list is
4946 \(opentype GSUB GPOS)
4947 where GSUB shows which "GSUB" features the font supports, and GPOS
4948 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4950 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4953 SCRIPT is a symbol representing OpenType script tag.
4954 LANGSYS is a symbol representing OpenType langsys tag, or nil
4955 representing the default langsys.
4956 FEATURE is a symbol representing OpenType feature tag.
4958 If the font is not an OpenType font, there are no elements
4959 in CAPABILITY except the font format symbol.
4961 If the named font is not yet loaded, return nil. */)
4962 (Lisp_Object name
, Lisp_Object frame
)
4967 Lisp_Object font_object
;
4970 CHECK_STRING (name
);
4971 f
= decode_window_system_frame (frame
);
4975 int fontset
= fs_query_fontset (name
, 0);
4978 name
= fontset_ascii (fontset
);
4979 font_object
= font_open_by_name (f
, name
);
4981 else if (FONT_OBJECT_P (name
))
4983 else if (FONT_ENTITY_P (name
))
4984 font_object
= font_open_entity (f
, name
, 0);
4987 struct face
*face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4988 Lisp_Object entity
= font_matching_entity (f
, face
->lface
, name
);
4990 font_object
= ! NILP (entity
) ? font_open_entity (f
, entity
, 0) : Qnil
;
4992 if (NILP (font_object
))
4994 font
= XFONT_OBJECT (font_object
);
4996 info
= make_uninit_vector (14);
4997 ASET (info
, 0, AREF (font_object
, FONT_NAME_INDEX
));
4998 ASET (info
, 1, AREF (font_object
, FONT_FULLNAME_INDEX
));
4999 ASET (info
, 2, make_number (font
->pixel_size
));
5000 ASET (info
, 3, make_number (font
->height
));
5001 ASET (info
, 4, make_number (font
->baseline_offset
));
5002 ASET (info
, 5, make_number (font
->relative_compose
));
5003 ASET (info
, 6, make_number (font
->default_ascent
));
5004 ASET (info
, 7, make_number (font
->max_width
));
5005 ASET (info
, 8, make_number (font
->ascent
));
5006 ASET (info
, 9, make_number (font
->descent
));
5007 ASET (info
, 10, make_number (font
->space_width
));
5008 ASET (info
, 11, make_number (font
->average_width
));
5009 ASET (info
, 12, AREF (font_object
, FONT_FILE_INDEX
));
5010 if (font
->driver
->otf_capability
)
5011 ASET (info
, 13, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
5013 ASET (info
, 13, Qnil
);
5016 /* As font_object is still in FONT_OBJLIST of the entity, we can't
5017 close it now. Perhaps, we should manage font-objects
5018 by `reference-count'. */
5019 font_close_object (f
, font_object
);
5026 #define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, ARRAYELTS (TBL))
5029 build_style_table (const struct table_entry
*entry
, int nelement
)
5032 Lisp_Object table
, elt
;
5034 table
= make_uninit_vector (nelement
);
5035 for (i
= 0; i
< nelement
; i
++)
5037 for (j
= 0; entry
[i
].names
[j
]; j
++);
5038 elt
= Fmake_vector (make_number (j
+ 1), Qnil
);
5039 ASET (elt
, 0, make_number (entry
[i
].numeric
));
5040 for (j
= 0; entry
[i
].names
[j
]; j
++)
5041 ASET (elt
, j
+ 1, intern_c_string (entry
[i
].names
[j
]));
5042 ASET (table
, i
, elt
);
5047 /* The deferred font-log data of the form [ACTION ARG RESULT].
5048 If ACTION is not nil, that is added to the log when font_add_log is
5049 called next time. At that time, ACTION is set back to nil. */
5050 static Lisp_Object Vfont_log_deferred
;
5052 /* Prepend the font-related logging data in Vfont_log if it is not
5053 t. ACTION describes a kind of font-related action (e.g. listing,
5054 opening), ARG is the argument for the action, and RESULT is the
5055 result of the action. */
5057 font_add_log (const char *action
, Lisp_Object arg
, Lisp_Object result
)
5062 if (EQ (Vfont_log
, Qt
))
5064 if (STRINGP (AREF (Vfont_log_deferred
, 0)))
5066 char *str
= SSDATA (AREF (Vfont_log_deferred
, 0));
5068 ASET (Vfont_log_deferred
, 0, Qnil
);
5069 font_add_log (str
, AREF (Vfont_log_deferred
, 1),
5070 AREF (Vfont_log_deferred
, 2));
5075 Lisp_Object tail
, elt
;
5076 AUTO_STRING (equal
, "=");
5078 val
= Ffont_xlfd_name (arg
, Qt
);
5079 for (tail
= AREF (arg
, FONT_EXTRA_INDEX
); CONSP (tail
);
5083 if (EQ (XCAR (elt
), QCscript
)
5084 && SYMBOLP (XCDR (elt
)))
5085 val
= concat3 (val
, SYMBOL_NAME (QCscript
),
5086 concat2 (equal
, SYMBOL_NAME (XCDR (elt
))));
5087 else if (EQ (XCAR (elt
), QClang
)
5088 && SYMBOLP (XCDR (elt
)))
5089 val
= concat3 (val
, SYMBOL_NAME (QClang
),
5090 concat2 (equal
, SYMBOL_NAME (XCDR (elt
))));
5091 else if (EQ (XCAR (elt
), QCotf
)
5092 && CONSP (XCDR (elt
)) && SYMBOLP (XCAR (XCDR (elt
))))
5093 val
= concat3 (val
, SYMBOL_NAME (QCotf
),
5094 concat2 (equal
, SYMBOL_NAME (XCAR (XCDR (elt
)))));
5100 && VECTORP (XCAR (result
))
5101 && ASIZE (XCAR (result
)) > 0
5102 && FONTP (AREF (XCAR (result
), 0)))
5103 result
= font_vconcat_entity_vectors (result
);
5106 val
= Ffont_xlfd_name (result
, Qt
);
5107 if (! FONT_SPEC_P (result
))
5109 AUTO_STRING (colon
, ":");
5110 val
= concat3 (SYMBOL_NAME (AREF (result
, FONT_TYPE_INDEX
)),
5115 else if (CONSP (result
))
5118 result
= Fcopy_sequence (result
);
5119 for (tail
= result
; CONSP (tail
); tail
= XCDR (tail
))
5123 val
= Ffont_xlfd_name (val
, Qt
);
5124 XSETCAR (tail
, val
);
5127 else if (VECTORP (result
))
5129 result
= Fcopy_sequence (result
);
5130 for (i
= 0; i
< ASIZE (result
); i
++)
5132 val
= AREF (result
, i
);
5134 val
= Ffont_xlfd_name (val
, Qt
);
5135 ASET (result
, i
, val
);
5138 Vfont_log
= Fcons (list3 (intern (action
), arg
, result
), Vfont_log
);
5141 /* Record a font-related logging data to be added to Vfont_log when
5142 font_add_log is called next time. ACTION, ARG, RESULT are the same
5146 font_deferred_log (const char *action
, Lisp_Object arg
, Lisp_Object result
)
5148 if (EQ (Vfont_log
, Qt
))
5150 ASET (Vfont_log_deferred
, 0, build_string (action
));
5151 ASET (Vfont_log_deferred
, 1, arg
);
5152 ASET (Vfont_log_deferred
, 2, result
);
5158 sort_shift_bits
[FONT_TYPE_INDEX
] = 0;
5159 sort_shift_bits
[FONT_SLANT_INDEX
] = 2;
5160 sort_shift_bits
[FONT_WEIGHT_INDEX
] = 9;
5161 sort_shift_bits
[FONT_SIZE_INDEX
] = 16;
5162 sort_shift_bits
[FONT_WIDTH_INDEX
] = 23;
5163 /* Note that the other elements in sort_shift_bits are not used. */
5165 staticpro (&font_charset_alist
);
5166 font_charset_alist
= Qnil
;
5168 DEFSYM (Qopentype
, "opentype");
5170 /* Important character set symbols. */
5171 DEFSYM (Qascii_0
, "ascii-0");
5172 DEFSYM (Qiso8859_1
, "iso8859-1");
5173 DEFSYM (Qiso10646_1
, "iso10646-1");
5174 DEFSYM (Qunicode_bmp
, "unicode-bmp");
5176 /* Symbols representing keys of font extra info. */
5177 DEFSYM (QCotf
, ":otf");
5178 DEFSYM (QClang
, ":lang");
5179 DEFSYM (QCscript
, ":script");
5180 DEFSYM (QCantialias
, ":antialias");
5181 DEFSYM (QCfoundry
, ":foundry");
5182 DEFSYM (QCadstyle
, ":adstyle");
5183 DEFSYM (QCregistry
, ":registry");
5184 DEFSYM (QCspacing
, ":spacing");
5185 DEFSYM (QCdpi
, ":dpi");
5186 DEFSYM (QCscalable
, ":scalable");
5187 DEFSYM (QCavgwidth
, ":avgwidth");
5188 DEFSYM (QCfont_entity
, ":font-entity");
5190 /* Symbols representing values of font spacing property. */
5196 /* Special ADSTYLE properties to avoid fonts used for Latin
5197 characters; used in xfont.c and ftfont.c. */
5201 DEFSYM (QCuser_spec
, "user-spec");
5203 staticpro (&scratch_font_spec
);
5204 scratch_font_spec
= Ffont_spec (0, NULL
);
5205 staticpro (&scratch_font_prefer
);
5206 scratch_font_prefer
= Ffont_spec (0, NULL
);
5208 staticpro (&Vfont_log_deferred
);
5209 Vfont_log_deferred
= Fmake_vector (make_number (3), Qnil
);
5213 staticpro (&otf_list
);
5215 #endif /* HAVE_LIBOTF */
5219 defsubr (&Sfont_spec
);
5220 defsubr (&Sfont_get
);
5221 #ifdef HAVE_WINDOW_SYSTEM
5222 defsubr (&Sfont_face_attributes
);
5224 defsubr (&Sfont_put
);
5225 defsubr (&Slist_fonts
);
5226 defsubr (&Sfont_family_list
);
5227 defsubr (&Sfind_font
);
5228 defsubr (&Sfont_xlfd_name
);
5229 defsubr (&Sclear_font_cache
);
5230 defsubr (&Sfont_shape_gstring
);
5231 defsubr (&Sfont_variation_glyphs
);
5233 defsubr (&Sfont_drive_otf
);
5234 defsubr (&Sfont_otf_alternates
);
5238 defsubr (&Sopen_font
);
5239 defsubr (&Sclose_font
);
5240 defsubr (&Squery_font
);
5241 defsubr (&Sfont_get_glyphs
);
5242 defsubr (&Sfont_match_p
);
5243 defsubr (&Sfont_at
);
5245 defsubr (&Sdraw_string
);
5247 defsubr (&Sframe_font_cache
);
5248 #endif /* FONT_DEBUG */
5249 #ifdef HAVE_WINDOW_SYSTEM
5250 defsubr (&Sfont_info
);
5253 DEFVAR_LISP ("font-encoding-alist", Vfont_encoding_alist
,
5255 Alist of fontname patterns vs the corresponding encoding and repertory info.
5256 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5257 where ENCODING is a charset or a char-table,
5258 and REPERTORY is a charset, a char-table, or nil.
5260 If ENCODING and REPERTORY are the same, the element can have the form
5261 \(REGEXP . ENCODING).
5263 ENCODING is for converting a character to a glyph code of the font.
5264 If ENCODING is a charset, encoding a character by the charset gives
5265 the corresponding glyph code. If ENCODING is a char-table, looking up
5266 the table by a character gives the corresponding glyph code.
5268 REPERTORY specifies a repertory of characters supported by the font.
5269 If REPERTORY is a charset, all characters belonging to the charset are
5270 supported. If REPERTORY is a char-table, all characters who have a
5271 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5272 gets the repertory information by an opened font and ENCODING. */);
5273 Vfont_encoding_alist
= Qnil
;
5275 /* FIXME: These 3 vars are not quite what they appear: setq on them
5276 won't have any effect other than disconnect them from the style
5277 table used by the font display code. So we make them read-only,
5278 to avoid this confusing situation. */
5280 DEFVAR_LISP_NOPRO ("font-weight-table", Vfont_weight_table
,
5281 doc
: /* Vector of valid font weight values.
5282 Each element has the form:
5283 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5284 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5285 Vfont_weight_table
= BUILD_STYLE_TABLE (weight_table
);
5286 XSYMBOL (intern_c_string ("font-weight-table"))->constant
= 1;
5288 DEFVAR_LISP_NOPRO ("font-slant-table", Vfont_slant_table
,
5289 doc
: /* Vector of font slant symbols vs the corresponding numeric values.
5290 See `font-weight-table' for the format of the vector. */);
5291 Vfont_slant_table
= BUILD_STYLE_TABLE (slant_table
);
5292 XSYMBOL (intern_c_string ("font-slant-table"))->constant
= 1;
5294 DEFVAR_LISP_NOPRO ("font-width-table", Vfont_width_table
,
5295 doc
: /* Alist of font width symbols vs the corresponding numeric values.
5296 See `font-weight-table' for the format of the vector. */);
5297 Vfont_width_table
= BUILD_STYLE_TABLE (width_table
);
5298 XSYMBOL (intern_c_string ("font-width-table"))->constant
= 1;
5300 staticpro (&font_style_table
);
5301 font_style_table
= make_uninit_vector (3);
5302 ASET (font_style_table
, 0, Vfont_weight_table
);
5303 ASET (font_style_table
, 1, Vfont_slant_table
);
5304 ASET (font_style_table
, 2, Vfont_width_table
);
5306 DEFVAR_LISP ("font-log", Vfont_log
, doc
: /*
5307 A list that logs font-related actions and results, for debugging.
5308 The default value is t, which means to suppress logging.
5309 Set it to nil to enable logging. If the environment variable
5310 EMACS_FONT_LOG is set at startup, it defaults to nil. */);
5313 #ifdef HAVE_WINDOW_SYSTEM
5314 #ifdef HAVE_FREETYPE
5316 #ifdef HAVE_X_WINDOWS
5318 syms_of_ftcrfont ();
5324 #endif /* HAVE_XFT */
5325 #endif /* not USE_CAIRO */
5326 #endif /* HAVE_X_WINDOWS */
5327 #else /* not HAVE_FREETYPE */
5328 #ifdef HAVE_X_WINDOWS
5330 #endif /* HAVE_X_WINDOWS */
5331 #endif /* not HAVE_FREETYPE */
5334 #endif /* HAVE_BDFFONT */
5337 #endif /* HAVE_NTGUI */
5338 #endif /* HAVE_WINDOW_SYSTEM */
5344 Vfont_log
= egetenv ("EMACS_FONT_LOG") ? Qnil
: Qt
;