1 /* font.c -- "Font" primitives.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
32 #include "dispextern.h"
34 #include "character.h"
35 #include "composite.h"
41 #endif /* HAVE_X_WINDOWS */
45 #endif /* HAVE_NTGUI */
52 extern Lisp_Object Qfontsize
;
55 Lisp_Object Qopentype
;
57 /* Important character set strings. */
58 Lisp_Object Qascii_0
, Qiso8859_1
, Qiso10646_1
, Qunicode_bmp
, Qunicode_sip
;
60 #define DEFAULT_ENCODING Qiso8859_1
62 /* Unicode category `Cf'. */
63 static Lisp_Object QCf
;
65 /* Special vector of zero length. This is repeatedly used by (struct
66 font_driver *)->list when a specified font is not found. */
67 static Lisp_Object null_vector
;
69 static Lisp_Object Vfont_weight_table
, Vfont_slant_table
, Vfont_width_table
;
71 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
72 static Lisp_Object font_style_table
;
74 /* Structure used for tables mapping weight, slant, and width numeric
75 values and their names. */
80 /* The first one is a valid name as a face attribute.
81 The second one (if any) is a typical name in XLFD field. */
85 /* Table of weight numeric values and their names. This table must be
86 sorted by numeric values in ascending order. */
88 static const struct table_entry weight_table
[] =
91 { 20, { "ultra-light", "ultralight" }},
92 { 40, { "extra-light", "extralight" }},
94 { 75, { "semi-light", "semilight", "demilight", "book" }},
95 { 100, { "normal", "medium", "regular", "unspecified" }},
96 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
98 { 205, { "extra-bold", "extrabold" }},
99 { 210, { "ultra-bold", "ultrabold", "black" }}
102 /* Table of slant numeric values and their names. This table must be
103 sorted by numeric values in ascending order. */
105 static const struct table_entry slant_table
[] =
107 { 0, { "reverse-oblique", "ro" }},
108 { 10, { "reverse-italic", "ri" }},
109 { 100, { "normal", "r", "unspecified" }},
110 { 200, { "italic" ,"i", "ot" }},
111 { 210, { "oblique", "o" }}
114 /* Table of width numeric values and their names. This table must be
115 sorted by numeric values in ascending order. */
117 static const struct table_entry width_table
[] =
119 { 50, { "ultra-condensed", "ultracondensed" }},
120 { 63, { "extra-condensed", "extracondensed" }},
121 { 75, { "condensed", "compressed", "narrow" }},
122 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
123 { 100, { "normal", "medium", "regular", "unspecified" }},
124 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
125 { 125, { "expanded" }},
126 { 150, { "extra-expanded", "extraexpanded" }},
127 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
130 Lisp_Object QCfoundry
, QCadstyle
, QCregistry
;
131 /* Symbols representing keys of font extra info. */
132 Lisp_Object QCspacing
, QCdpi
, QCscalable
, QCotf
, QClang
, QCscript
, QCavgwidth
;
133 Lisp_Object QCantialias
, QCfont_entity
, QCfc_unknown_spec
;
134 /* Symbols representing values of font spacing property. */
135 Lisp_Object Qc
, Qm
, Qp
, Qd
;
136 /* Special ADSTYLE properties to avoid fonts used for Latin
137 characters; used in xfont.c and ftfont.c. */
138 Lisp_Object Qja
, Qko
;
140 Lisp_Object QCuser_spec
;
142 Lisp_Object Vfont_encoding_alist
;
144 /* Alist of font registry symbol and the corresponding charsets
145 information. The information is retrieved from
146 Vfont_encoding_alist on demand.
148 Eash element has the form:
149 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
153 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
154 encodes a character code to a glyph code of a font, and
155 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
156 character is supported by a font.
158 The latter form means that the information for REGISTRY couldn't be
160 static Lisp_Object font_charset_alist
;
162 /* List of all font drivers. Each font-backend (XXXfont.c) calls
163 register_font_driver in syms_of_XXXfont to register its font-driver
165 static struct font_driver_list
*font_driver_list
;
169 /* Creaters of font-related Lisp object. */
172 font_make_spec (void)
174 Lisp_Object font_spec
;
175 struct font_spec
*spec
176 = ((struct font_spec
*)
177 allocate_pseudovector (VECSIZE (struct font_spec
),
178 FONT_SPEC_MAX
, PVEC_FONT
));
179 XSETFONT (font_spec
, spec
);
184 font_make_entity (void)
186 Lisp_Object font_entity
;
187 struct font_entity
*entity
188 = ((struct font_entity
*)
189 allocate_pseudovector (VECSIZE (struct font_entity
),
190 FONT_ENTITY_MAX
, PVEC_FONT
));
191 XSETFONT (font_entity
, entity
);
195 /* Create a font-object whose structure size is SIZE. If ENTITY is
196 not nil, copy properties from ENTITY to the font-object. If
197 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
199 font_make_object (int size
, Lisp_Object entity
, int pixelsize
)
201 Lisp_Object font_object
;
203 = (struct font
*) allocate_pseudovector (size
, FONT_OBJECT_MAX
, PVEC_FONT
);
206 XSETFONT (font_object
, font
);
210 for (i
= 1; i
< FONT_SPEC_MAX
; i
++)
211 font
->props
[i
] = AREF (entity
, i
);
212 if (! NILP (AREF (entity
, FONT_EXTRA_INDEX
)))
213 font
->props
[FONT_EXTRA_INDEX
]
214 = Fcopy_alist (AREF (entity
, FONT_EXTRA_INDEX
));
217 font
->props
[FONT_SIZE_INDEX
] = make_number (pixelsize
);
223 static int font_pixel_size (FRAME_PTR f
, Lisp_Object
);
224 static Lisp_Object
font_open_entity (FRAME_PTR
, Lisp_Object
, int);
225 static Lisp_Object
font_matching_entity (FRAME_PTR
, Lisp_Object
*,
228 /* Number of registered font drivers. */
229 static int num_font_drivers
;
232 /* Return a Lispy value of a font property value at STR and LEN bytes.
233 If STR is "*", it returns nil.
234 If FORCE_SYMBOL is zero and all characters in STR are digits, it
235 returns an integer. Otherwise, it returns a symbol interned from
239 font_intern_prop (char *str
, int len
, int force_symbol
)
246 if (len
== 1 && *str
== '*')
248 if (!force_symbol
&& len
>=1 && isdigit (*str
))
250 for (i
= 1; i
< len
; i
++)
251 if (! isdigit (str
[i
]))
254 return make_number (atoi (str
));
257 /* The following code is copied from the function intern (in
258 lread.c), and modified to suite our purpose. */
260 if (!VECTORP (obarray
) || XVECTOR (obarray
)->size
== 0)
261 obarray
= check_obarray (obarray
);
262 parse_str_as_multibyte ((unsigned char *) str
, len
, &nchars
, &nbytes
);
263 if (len
== nchars
|| len
!= nbytes
)
264 /* CONTENTS contains no multibyte sequences or contains an invalid
265 multibyte sequence. We'll make a unibyte string. */
266 tem
= oblookup (obarray
, str
, len
, len
);
268 tem
= oblookup (obarray
, str
, nchars
, len
);
271 if (len
== nchars
|| len
!= nbytes
)
272 tem
= make_unibyte_string (str
, len
);
274 tem
= make_multibyte_string (str
, nchars
, len
);
275 return Fintern (tem
, obarray
);
278 /* Return a pixel size of font-spec SPEC on frame F. */
281 font_pixel_size (FRAME_PTR f
, Lisp_Object spec
)
283 #ifdef HAVE_WINDOW_SYSTEM
284 Lisp_Object size
= AREF (spec
, FONT_SIZE_INDEX
);
293 font_assert (FLOATP (size
));
294 point_size
= XFLOAT_DATA (size
);
295 val
= AREF (spec
, FONT_DPI_INDEX
);
300 pixel_size
= POINT_TO_PIXEL (point_size
, dpi
);
308 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
309 font vector. If VAL is not valid (i.e. not registered in
310 font_style_table), return -1 if NOERROR is zero, and return a
311 proper index if NOERROR is nonzero. In that case, register VAL in
312 font_style_table if VAL is a symbol, and return a closest index if
313 VAL is an integer. */
316 font_style_to_value (enum font_property_index prop
, Lisp_Object val
, int noerror
)
318 Lisp_Object table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
319 int len
= ASIZE (table
);
325 Lisp_Object args
[2], elt
;
327 /* At first try exact match. */
328 for (i
= 0; i
< len
; i
++)
329 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
330 if (EQ (val
, AREF (AREF (table
, i
), j
)))
331 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
332 | (i
<< 4) | (j
- 1));
333 /* Try also with case-folding match. */
334 s
= SDATA (SYMBOL_NAME (val
));
335 for (i
= 0; i
< len
; i
++)
336 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
338 elt
= AREF (AREF (table
, i
), j
);
339 if (xstrcasecmp (s
, SDATA (SYMBOL_NAME (elt
))) == 0)
340 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
341 | (i
<< 4) | (j
- 1));
347 elt
= Fmake_vector (make_number (2), make_number (100));
350 args
[1] = Fmake_vector (make_number (1), elt
);
351 ASET (font_style_table
, prop
- FONT_WEIGHT_INDEX
, Fvconcat (2, args
));
352 return (100 << 8) | (i
<< 4);
357 int numeric
= XINT (val
);
359 for (i
= 0, last_n
= -1; i
< len
; i
++)
361 int n
= XINT (AREF (AREF (table
, i
), 0));
364 return (n
<< 8) | (i
<< 4);
369 return ((i
== 0 || n
- numeric
< numeric
- last_n
)
370 ? (n
<< 8) | (i
<< 4): (last_n
<< 8 | ((i
- 1) << 4)));
376 return ((last_n
<< 8) | ((i
- 1) << 4));
381 font_style_symbolic (Lisp_Object font
, enum font_property_index prop
, int for_face
)
383 Lisp_Object val
= AREF (font
, prop
);
384 Lisp_Object table
, elt
;
389 table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
390 i
= XINT (val
) & 0xFF;
391 font_assert (((i
>> 4) & 0xF) < ASIZE (table
));
392 elt
= AREF (table
, ((i
>> 4) & 0xF));
393 font_assert ((i
& 0xF) + 1 < ASIZE (elt
));
394 return (for_face
? AREF (elt
, 1) : AREF (elt
, (i
& 0xF) + 1));
397 extern Lisp_Object Vface_alternative_font_family_alist
;
399 extern Lisp_Object
find_font_encoding (Lisp_Object
);
402 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
403 FONTNAME. ENCODING is a charset symbol that specifies the encoding
404 of the font. REPERTORY is a charset symbol or nil. */
407 find_font_encoding (Lisp_Object fontname
)
409 Lisp_Object tail
, elt
;
411 for (tail
= Vfont_encoding_alist
; CONSP (tail
); tail
= XCDR (tail
))
415 && STRINGP (XCAR (elt
))
416 && fast_string_match_ignore_case (XCAR (elt
), fontname
) >= 0
417 && (SYMBOLP (XCDR (elt
))
418 ? CHARSETP (XCDR (elt
))
419 : CONSP (XCDR (elt
)) && CHARSETP (XCAR (XCDR (elt
)))))
425 /* Return encoding charset and repertory charset for REGISTRY in
426 ENCODING and REPERTORY correspondingly. If correct information for
427 REGISTRY is available, return 0. Otherwise return -1. */
430 font_registry_charsets (Lisp_Object registry
, struct charset
**encoding
, struct charset
**repertory
)
433 int encoding_id
, repertory_id
;
435 val
= Fassoc_string (registry
, font_charset_alist
, Qt
);
441 encoding_id
= XINT (XCAR (val
));
442 repertory_id
= XINT (XCDR (val
));
446 val
= find_font_encoding (SYMBOL_NAME (registry
));
447 if (SYMBOLP (val
) && CHARSETP (val
))
449 encoding_id
= repertory_id
= XINT (CHARSET_SYMBOL_ID (val
));
451 else if (CONSP (val
))
453 if (! CHARSETP (XCAR (val
)))
455 encoding_id
= XINT (CHARSET_SYMBOL_ID (XCAR (val
)));
456 if (NILP (XCDR (val
)))
460 if (! CHARSETP (XCDR (val
)))
462 repertory_id
= XINT (CHARSET_SYMBOL_ID (XCDR (val
)));
467 val
= Fcons (make_number (encoding_id
), make_number (repertory_id
));
469 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, val
), Qnil
));
473 *encoding
= CHARSET_FROM_ID (encoding_id
);
475 *repertory
= repertory_id
>= 0 ? CHARSET_FROM_ID (repertory_id
) : NULL
;
480 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, Qnil
), Qnil
));
485 /* Font property value validaters. See the comment of
486 font_property_table for the meaning of the arguments. */
488 static Lisp_Object
font_prop_validate (int, Lisp_Object
, Lisp_Object
);
489 static Lisp_Object
font_prop_validate_symbol (Lisp_Object
, Lisp_Object
);
490 static Lisp_Object
font_prop_validate_style (Lisp_Object
, Lisp_Object
);
491 static Lisp_Object
font_prop_validate_non_neg (Lisp_Object
, Lisp_Object
);
492 static Lisp_Object
font_prop_validate_spacing (Lisp_Object
, Lisp_Object
);
493 static int get_font_prop_index (Lisp_Object
);
496 font_prop_validate_symbol (Lisp_Object prop
, Lisp_Object val
)
499 val
= Fintern (val
, Qnil
);
502 else if (EQ (prop
, QCregistry
))
503 val
= Fintern (Fdowncase (SYMBOL_NAME (val
)), Qnil
);
509 font_prop_validate_style (Lisp_Object style
, Lisp_Object val
)
511 enum font_property_index prop
= (EQ (style
, QCweight
) ? FONT_WEIGHT_INDEX
512 : EQ (style
, QCslant
) ? FONT_SLANT_INDEX
519 >= ASIZE (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
)))
523 Lisp_Object elt
= AREF (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
), (n
>> 4) & 0xF);
525 if ((n
& 0xF) + 1 >= ASIZE (elt
))
527 else if (XINT (AREF (elt
, 0)) != (n
>> 8))
531 else if (SYMBOLP (val
))
533 int n
= font_style_to_value (prop
, val
, 0);
535 val
= n
>= 0 ? make_number (n
) : Qerror
;
543 font_prop_validate_non_neg (Lisp_Object prop
, Lisp_Object val
)
545 return (NATNUMP (val
) || (FLOATP (val
) && XFLOAT_DATA (val
) >= 0)
550 font_prop_validate_spacing (Lisp_Object prop
, Lisp_Object val
)
552 if (NILP (val
) || (NATNUMP (val
) && XINT (val
) <= FONT_SPACING_CHARCELL
))
554 if (SYMBOLP (val
) && SBYTES (SYMBOL_NAME (val
)) == 1)
556 char spacing
= SDATA (SYMBOL_NAME (val
))[0];
558 if (spacing
== 'c' || spacing
== 'C')
559 return make_number (FONT_SPACING_CHARCELL
);
560 if (spacing
== 'm' || spacing
== 'M')
561 return make_number (FONT_SPACING_MONO
);
562 if (spacing
== 'p' || spacing
== 'P')
563 return make_number (FONT_SPACING_PROPORTIONAL
);
564 if (spacing
== 'd' || spacing
== 'D')
565 return make_number (FONT_SPACING_DUAL
);
571 font_prop_validate_otf (Lisp_Object prop
, Lisp_Object val
)
573 Lisp_Object tail
, tmp
;
576 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
577 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
578 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
581 if (! SYMBOLP (XCAR (val
)))
586 if (! CONSP (tail
) || ! SYMBOLP (XCAR (val
)))
588 for (i
= 0; i
< 2; i
++)
595 for (tmp
= XCAR (tail
); CONSP (tmp
); tmp
= XCDR (tmp
))
596 if (! SYMBOLP (XCAR (tmp
)))
604 /* Structure of known font property keys and validater of the
608 /* Pointer to the key symbol. */
610 /* Function to validate PROP's value VAL, or NULL if any value is
611 ok. The value is VAL or its regularized value if VAL is valid,
612 and Qerror if not. */
613 Lisp_Object (*validater
) (Lisp_Object prop
, Lisp_Object val
);
614 } font_property_table
[] =
615 { { &QCtype
, font_prop_validate_symbol
},
616 { &QCfoundry
, font_prop_validate_symbol
},
617 { &QCfamily
, font_prop_validate_symbol
},
618 { &QCadstyle
, font_prop_validate_symbol
},
619 { &QCregistry
, font_prop_validate_symbol
},
620 { &QCweight
, font_prop_validate_style
},
621 { &QCslant
, font_prop_validate_style
},
622 { &QCwidth
, font_prop_validate_style
},
623 { &QCsize
, font_prop_validate_non_neg
},
624 { &QCdpi
, font_prop_validate_non_neg
},
625 { &QCspacing
, font_prop_validate_spacing
},
626 { &QCavgwidth
, font_prop_validate_non_neg
},
627 /* The order of the above entries must match with enum
628 font_property_index. */
629 { &QClang
, font_prop_validate_symbol
},
630 { &QCscript
, font_prop_validate_symbol
},
631 { &QCotf
, font_prop_validate_otf
}
634 /* Size (number of elements) of the above table. */
635 #define FONT_PROPERTY_TABLE_SIZE \
636 ((sizeof font_property_table) / (sizeof *font_property_table))
638 /* Return an index number of font property KEY or -1 if KEY is not an
639 already known property. */
642 get_font_prop_index (Lisp_Object key
)
646 for (i
= 0; i
< FONT_PROPERTY_TABLE_SIZE
; i
++)
647 if (EQ (key
, *font_property_table
[i
].key
))
652 /* Validate the font property. The property key is specified by the
653 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
654 signal an error. The value is VAL or the regularized one. */
657 font_prop_validate (int idx
, Lisp_Object prop
, Lisp_Object val
)
659 Lisp_Object validated
;
664 prop
= *font_property_table
[idx
].key
;
667 idx
= get_font_prop_index (prop
);
671 validated
= (font_property_table
[idx
].validater
) (prop
, val
);
672 if (EQ (validated
, Qerror
))
673 signal_error ("invalid font property", Fcons (prop
, val
));
678 /* Store VAL as a value of extra font property PROP in FONT while
679 keeping the sorting order. Don't check the validity of VAL. */
682 font_put_extra (Lisp_Object font
, Lisp_Object prop
, Lisp_Object val
)
684 Lisp_Object extra
= AREF (font
, FONT_EXTRA_INDEX
);
685 Lisp_Object slot
= (NILP (extra
) ? Qnil
: assq_no_quit (prop
, extra
));
689 Lisp_Object prev
= Qnil
;
692 && NILP (Fstring_lessp (prop
, XCAR (XCAR (extra
)))))
693 prev
= extra
, extra
= XCDR (extra
);
696 ASET (font
, FONT_EXTRA_INDEX
, Fcons (Fcons (prop
, val
), extra
));
698 XSETCDR (prev
, Fcons (Fcons (prop
, val
), extra
));
704 ASET (font
, FONT_EXTRA_INDEX
, Fdelq (slot
, extra
));
709 /* Font name parser and unparser */
711 static int parse_matrix (char *);
712 static int font_expand_wildcards (Lisp_Object
*, int);
713 static int font_parse_name (char *, Lisp_Object
);
715 /* An enumerator for each field of an XLFD font name. */
716 enum xlfd_field_index
735 /* An enumerator for mask bit corresponding to each XLFD field. */
738 XLFD_FOUNDRY_MASK
= 0x0001,
739 XLFD_FAMILY_MASK
= 0x0002,
740 XLFD_WEIGHT_MASK
= 0x0004,
741 XLFD_SLANT_MASK
= 0x0008,
742 XLFD_SWIDTH_MASK
= 0x0010,
743 XLFD_ADSTYLE_MASK
= 0x0020,
744 XLFD_PIXEL_MASK
= 0x0040,
745 XLFD_POINT_MASK
= 0x0080,
746 XLFD_RESX_MASK
= 0x0100,
747 XLFD_RESY_MASK
= 0x0200,
748 XLFD_SPACING_MASK
= 0x0400,
749 XLFD_AVGWIDTH_MASK
= 0x0800,
750 XLFD_REGISTRY_MASK
= 0x1000,
751 XLFD_ENCODING_MASK
= 0x2000
755 /* Parse P pointing the pixel/point size field of the form
756 `[A B C D]' which specifies a transformation matrix:
762 by which all glyphs of the font are transformed. The spec says
763 that scalar value N for the pixel/point size is equivalent to:
764 A = N * resx/resy, B = C = 0, D = N.
766 Return the scalar value N if the form is valid. Otherwise return
770 parse_matrix (char *p
)
776 for (i
= 0, p
++; i
< 4 && *p
&& *p
!= ']'; i
++)
779 matrix
[i
] = - strtod (p
+ 1, &end
);
781 matrix
[i
] = strtod (p
, &end
);
784 return (i
== 4 ? (int) matrix
[3] : -1);
787 /* Expand a wildcard field in FIELD (the first N fields are filled) to
788 multiple fields to fill in all 14 XLFD fields while restring a
789 field position by its contents. */
792 font_expand_wildcards (Lisp_Object
*field
, int n
)
795 Lisp_Object tmp
[XLFD_LAST_INDEX
];
796 /* Array of information about where this element can go. Nth
797 element is for Nth element of FIELD. */
799 /* Minimum possible field. */
801 /* Maxinum possible field. */
803 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
805 } range
[XLFD_LAST_INDEX
];
807 int range_from
, range_to
;
810 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
811 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
812 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
813 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
814 | XLFD_AVGWIDTH_MASK)
815 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
817 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
818 field. The value is shifted to left one bit by one in the
820 for (i
= 0, range_mask
= 0; i
<= 14 - n
; i
++)
821 range_mask
= (range_mask
<< 1) | 1;
823 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
824 position-based retriction for FIELD[I]. */
825 for (i
= 0, range_from
= 0, range_to
= 14 - n
; i
< n
;
826 i
++, range_from
++, range_to
++, range_mask
<<= 1)
828 Lisp_Object val
= field
[i
];
834 range
[i
].from
= range_from
;
835 range
[i
].to
= range_to
;
836 range
[i
].mask
= range_mask
;
840 /* The triplet FROM, TO, and MASK is a value-based
841 retriction for FIELD[I]. */
847 int numeric
= XINT (val
);
850 from
= to
= XLFD_ENCODING_INDEX
,
851 mask
= XLFD_ENCODING_MASK
;
852 else if (numeric
== 0)
853 from
= XLFD_PIXEL_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
854 mask
= XLFD_PIXEL_MASK
| XLFD_LARGENUM_MASK
;
855 else if (numeric
<= 48)
856 from
= to
= XLFD_PIXEL_INDEX
,
857 mask
= XLFD_PIXEL_MASK
;
859 from
= XLFD_POINT_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
860 mask
= XLFD_LARGENUM_MASK
;
862 else if (SBYTES (SYMBOL_NAME (val
)) == 0)
863 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ADSTYLE_INDEX
,
864 mask
= XLFD_NULL_MASK
;
866 from
= to
= XLFD_FOUNDRY_INDEX
, mask
= XLFD_FOUNDRY_MASK
;
869 Lisp_Object name
= SYMBOL_NAME (val
);
871 if (SDATA (name
)[SBYTES (name
) - 1] == '*')
872 from
= XLFD_REGISTRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
873 mask
= XLFD_REGENC_MASK
;
875 from
= to
= XLFD_ENCODING_INDEX
,
876 mask
= XLFD_ENCODING_MASK
;
878 else if (range_from
<= XLFD_WEIGHT_INDEX
879 && range_to
>= XLFD_WEIGHT_INDEX
880 && FONT_WEIGHT_NAME_NUMERIC (val
) >= 0)
881 from
= to
= XLFD_WEIGHT_INDEX
, mask
= XLFD_WEIGHT_MASK
;
882 else if (range_from
<= XLFD_SLANT_INDEX
883 && range_to
>= XLFD_SLANT_INDEX
884 && FONT_SLANT_NAME_NUMERIC (val
) >= 0)
885 from
= to
= XLFD_SLANT_INDEX
, mask
= XLFD_SLANT_MASK
;
886 else if (range_from
<= XLFD_SWIDTH_INDEX
887 && range_to
>= XLFD_SWIDTH_INDEX
888 && FONT_WIDTH_NAME_NUMERIC (val
) >= 0)
889 from
= to
= XLFD_SWIDTH_INDEX
, mask
= XLFD_SWIDTH_MASK
;
892 if (EQ (val
, Qc
) || EQ (val
, Qm
) || EQ (val
, Qp
) || EQ (val
, Qd
))
893 from
= to
= XLFD_SPACING_INDEX
, mask
= XLFD_SPACING_MASK
;
895 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
896 mask
= XLFD_SYMBOL_MASK
;
899 /* Merge position-based and value-based restrictions. */
901 while (from
< range_from
)
902 mask
&= ~(1 << from
++);
903 while (from
< 14 && ! (mask
& (1 << from
)))
905 while (to
> range_to
)
906 mask
&= ~(1 << to
--);
907 while (to
>= 0 && ! (mask
& (1 << to
)))
911 range
[i
].from
= from
;
913 range
[i
].mask
= mask
;
915 if (from
> range_from
|| to
< range_to
)
917 /* The range is narrowed by value-based restrictions.
918 Reflect it to the other fields. */
920 /* Following fields should be after FROM. */
922 /* Preceding fields should be before TO. */
923 for (j
= i
- 1, from
--, to
--; j
>= 0; j
--, from
--, to
--)
925 /* Check FROM for non-wildcard field. */
926 if (! NILP (tmp
[j
]) && range
[j
].from
< from
)
928 while (range
[j
].from
< from
)
929 range
[j
].mask
&= ~(1 << range
[j
].from
++);
930 while (from
< 14 && ! (range
[j
].mask
& (1 << from
)))
932 range
[j
].from
= from
;
935 from
= range
[j
].from
;
936 if (range
[j
].to
> to
)
938 while (range
[j
].to
> to
)
939 range
[j
].mask
&= ~(1 << range
[j
].to
--);
940 while (to
>= 0 && ! (range
[j
].mask
& (1 << to
)))
953 /* Decide all fileds from restrictions in RANGE. */
954 for (i
= j
= 0; i
< n
; i
++)
956 if (j
< range
[i
].from
)
958 if (i
== 0 || ! NILP (tmp
[i
- 1]))
959 /* None of TMP[X] corresponds to Jth field. */
961 for (; j
< range
[i
].from
; j
++)
966 if (! NILP (tmp
[n
- 1]) && j
< XLFD_REGISTRY_INDEX
)
968 for (; j
< XLFD_LAST_INDEX
; j
++)
970 if (INTEGERP (field
[XLFD_ENCODING_INDEX
]))
971 field
[XLFD_ENCODING_INDEX
]
972 = Fintern (Fnumber_to_string (field
[XLFD_ENCODING_INDEX
]), Qnil
);
977 /* Parse NAME (null terminated) as XLFD and store information in FONT
978 (font-spec or font-entity). Size property of FONT is set as
980 specified XLFD fields FONT property
981 --------------------- -------------
982 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
983 POINT_SIZE and RESY calculated pixel size (Lisp integer)
984 POINT_SIZE POINT_SIZE/10 (Lisp float)
986 If NAME is successfully parsed, return 0. Otherwise return -1.
988 FONT is usually a font-spec, but when this function is called from
989 X font backend driver, it is a font-entity. In that case, NAME is
990 a fully specified XLFD. */
993 font_parse_xlfd (char *name
, Lisp_Object font
)
995 int len
= strlen (name
);
997 char *f
[XLFD_LAST_INDEX
+ 1];
1001 if (len
> 255 || !len
)
1002 /* Maximum XLFD name length is 255. */
1004 /* Accept "*-.." as a fully specified XLFD. */
1005 if (name
[0] == '*' && (len
== 1 || name
[1] == '-'))
1006 i
= 1, f
[XLFD_FOUNDRY_INDEX
] = name
;
1009 for (p
= name
+ i
; *p
; p
++)
1013 if (i
== XLFD_LAST_INDEX
)
1018 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1019 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1021 if (i
== XLFD_LAST_INDEX
)
1023 /* Fully specified XLFD. */
1026 ASET (font
, FONT_FOUNDRY_INDEX
, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX
));
1027 ASET (font
, FONT_FAMILY_INDEX
, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX
));
1028 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1029 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1031 val
= INTERN_FIELD_SYM (i
);
1034 if ((n
= font_style_to_value (j
, INTERN_FIELD_SYM (i
), 0)) < 0)
1036 ASET (font
, j
, make_number (n
));
1039 ASET (font
, FONT_ADSTYLE_INDEX
, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX
));
1040 if (strcmp (f
[XLFD_REGISTRY_INDEX
], "*-*") == 0)
1041 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
1043 ASET (font
, FONT_REGISTRY_INDEX
,
1044 font_intern_prop (f
[XLFD_REGISTRY_INDEX
],
1045 f
[XLFD_LAST_INDEX
] - f
[XLFD_REGISTRY_INDEX
],
1047 p
= f
[XLFD_PIXEL_INDEX
];
1048 if (*p
== '[' && (pixel_size
= parse_matrix (p
)) >= 0)
1049 ASET (font
, FONT_SIZE_INDEX
, make_number (pixel_size
));
1052 val
= INTERN_FIELD (XLFD_PIXEL_INDEX
);
1054 ASET (font
, FONT_SIZE_INDEX
, val
);
1055 else if (FONT_ENTITY_P (font
))
1059 double point_size
= -1;
1061 font_assert (FONT_SPEC_P (font
));
1062 p
= f
[XLFD_POINT_INDEX
];
1064 point_size
= parse_matrix (p
);
1065 else if (isdigit (*p
))
1066 point_size
= atoi (p
), point_size
/= 10;
1067 if (point_size
>= 0)
1068 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1072 val
= INTERN_FIELD (XLFD_RESY_INDEX
);
1073 if (! NILP (val
) && ! INTEGERP (val
))
1075 ASET (font
, FONT_DPI_INDEX
, val
);
1076 val
= INTERN_FIELD (XLFD_SPACING_INDEX
);
1079 val
= font_prop_validate_spacing (QCspacing
, val
);
1080 if (! INTEGERP (val
))
1082 ASET (font
, FONT_SPACING_INDEX
, val
);
1084 p
= f
[XLFD_AVGWIDTH_INDEX
];
1087 val
= font_intern_prop (p
, f
[XLFD_REGISTRY_INDEX
] - 1 - p
, 0);
1088 if (! NILP (val
) && ! INTEGERP (val
))
1090 ASET (font
, FONT_AVGWIDTH_INDEX
, val
);
1094 int wild_card_found
= 0;
1095 Lisp_Object prop
[XLFD_LAST_INDEX
];
1097 if (FONT_ENTITY_P (font
))
1099 for (j
= 0; j
< i
; j
++)
1103 if (f
[j
][1] && f
[j
][1] != '-')
1106 wild_card_found
= 1;
1109 prop
[j
] = INTERN_FIELD (j
);
1111 prop
[j
] = font_intern_prop (f
[j
], f
[i
] - f
[j
], 0);
1113 if (! wild_card_found
)
1115 if (font_expand_wildcards (prop
, i
) < 0)
1118 ASET (font
, FONT_FOUNDRY_INDEX
, prop
[XLFD_FOUNDRY_INDEX
]);
1119 ASET (font
, FONT_FAMILY_INDEX
, prop
[XLFD_FAMILY_INDEX
]);
1120 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1121 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1122 if (! NILP (prop
[i
]))
1124 if ((n
= font_style_to_value (j
, prop
[i
], 1)) < 0)
1126 ASET (font
, j
, make_number (n
));
1128 ASET (font
, FONT_ADSTYLE_INDEX
, prop
[XLFD_ADSTYLE_INDEX
]);
1129 val
= prop
[XLFD_REGISTRY_INDEX
];
1132 val
= prop
[XLFD_ENCODING_INDEX
];
1134 val
= concat2 (build_string ("*-"), SYMBOL_NAME (val
));
1136 else if (NILP (prop
[XLFD_ENCODING_INDEX
]))
1137 val
= concat2 (SYMBOL_NAME (val
), build_string ("-*"));
1139 val
= concat3 (SYMBOL_NAME (val
), build_string ("-"),
1140 SYMBOL_NAME (prop
[XLFD_ENCODING_INDEX
]));
1142 ASET (font
, FONT_REGISTRY_INDEX
, Fintern (val
, Qnil
));
1144 if (INTEGERP (prop
[XLFD_PIXEL_INDEX
]))
1145 ASET (font
, FONT_SIZE_INDEX
, prop
[XLFD_PIXEL_INDEX
]);
1146 else if (INTEGERP (prop
[XLFD_POINT_INDEX
]))
1148 double point_size
= XINT (prop
[XLFD_POINT_INDEX
]);
1150 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
/ 10));
1153 if (INTEGERP (prop
[XLFD_RESX_INDEX
]))
1154 ASET (font
, FONT_DPI_INDEX
, prop
[XLFD_RESY_INDEX
]);
1155 if (! NILP (prop
[XLFD_SPACING_INDEX
]))
1157 val
= font_prop_validate_spacing (QCspacing
,
1158 prop
[XLFD_SPACING_INDEX
]);
1159 if (! INTEGERP (val
))
1161 ASET (font
, FONT_SPACING_INDEX
, val
);
1163 if (INTEGERP (prop
[XLFD_AVGWIDTH_INDEX
]))
1164 ASET (font
, FONT_AVGWIDTH_INDEX
, prop
[XLFD_AVGWIDTH_INDEX
]);
1170 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1171 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1172 0, use PIXEL_SIZE instead. */
1175 font_unparse_xlfd (Lisp_Object font
, int pixel_size
, char *name
, int nbytes
)
1177 char *f
[XLFD_REGISTRY_INDEX
+ 1];
1181 font_assert (FONTP (font
));
1183 for (i
= FONT_FOUNDRY_INDEX
, j
= XLFD_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
;
1186 if (i
== FONT_ADSTYLE_INDEX
)
1187 j
= XLFD_ADSTYLE_INDEX
;
1188 else if (i
== FONT_REGISTRY_INDEX
)
1189 j
= XLFD_REGISTRY_INDEX
;
1190 val
= AREF (font
, i
);
1193 if (j
== XLFD_REGISTRY_INDEX
)
1194 f
[j
] = "*-*", len
+= 4;
1196 f
[j
] = "*", len
+= 2;
1201 val
= SYMBOL_NAME (val
);
1202 if (j
== XLFD_REGISTRY_INDEX
1203 && ! strchr ((char *) SDATA (val
), '-'))
1205 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1206 if (SDATA (val
)[SBYTES (val
) - 1] == '*')
1208 f
[j
] = alloca (SBYTES (val
) + 3);
1209 sprintf (f
[j
], "%s-*", SDATA (val
));
1210 len
+= SBYTES (val
) + 3;
1214 f
[j
] = alloca (SBYTES (val
) + 4);
1215 sprintf (f
[j
], "%s*-*", SDATA (val
));
1216 len
+= SBYTES (val
) + 4;
1220 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1224 for (i
= FONT_WEIGHT_INDEX
, j
= XLFD_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
;
1227 val
= font_style_symbolic (font
, i
, 0);
1229 f
[j
] = "*", len
+= 2;
1232 val
= SYMBOL_NAME (val
);
1233 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1237 val
= AREF (font
, FONT_SIZE_INDEX
);
1238 font_assert (NUMBERP (val
) || NILP (val
));
1246 f
[XLFD_PIXEL_INDEX
] = alloca (22);
1247 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "%d-*", i
) + 1;
1250 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1252 else if (FLOATP (val
))
1254 i
= XFLOAT_DATA (val
) * 10;
1255 f
[XLFD_PIXEL_INDEX
] = alloca (12);
1256 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "*-%d", i
) + 1;
1259 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1261 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1263 i
= XINT (AREF (font
, FONT_DPI_INDEX
));
1264 f
[XLFD_RESX_INDEX
] = alloca (22);
1265 len
+= sprintf (f
[XLFD_RESX_INDEX
],
1269 f
[XLFD_RESX_INDEX
] = "*-*", len
+= 4;
1270 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1272 int spacing
= XINT (AREF (font
, FONT_SPACING_INDEX
));
1274 f
[XLFD_SPACING_INDEX
] = (spacing
<= FONT_SPACING_PROPORTIONAL
? "p"
1275 : spacing
<= FONT_SPACING_DUAL
? "d"
1276 : spacing
<= FONT_SPACING_MONO
? "m"
1281 f
[XLFD_SPACING_INDEX
] = "*", len
+= 2;
1282 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1284 f
[XLFD_AVGWIDTH_INDEX
] = alloca (11);
1285 len
+= sprintf (f
[XLFD_AVGWIDTH_INDEX
], "%ld",
1286 (long) XINT (AREF (font
, FONT_AVGWIDTH_INDEX
))) + 1;
1289 f
[XLFD_AVGWIDTH_INDEX
] = "*", len
+= 2;
1290 len
++; /* for terminating '\0'. */
1293 return sprintf (name
, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1294 f
[XLFD_FOUNDRY_INDEX
], f
[XLFD_FAMILY_INDEX
],
1295 f
[XLFD_WEIGHT_INDEX
], f
[XLFD_SLANT_INDEX
],
1296 f
[XLFD_SWIDTH_INDEX
], f
[XLFD_ADSTYLE_INDEX
],
1297 f
[XLFD_PIXEL_INDEX
], f
[XLFD_RESX_INDEX
],
1298 f
[XLFD_SPACING_INDEX
], f
[XLFD_AVGWIDTH_INDEX
],
1299 f
[XLFD_REGISTRY_INDEX
]);
1302 /* Parse NAME (null terminated) and store information in FONT
1303 (font-spec or font-entity). NAME is supplied in either the
1304 Fontconfig or GTK font name format. If NAME is successfully
1305 parsed, return 0. Otherwise return -1.
1307 The fontconfig format is
1309 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1313 FAMILY [PROPS...] [SIZE]
1315 This function tries to guess which format it is. */
1318 font_parse_fcname (char *name
, Lisp_Object font
)
1321 char *size_beg
= NULL
, *size_end
= NULL
;
1322 char *props_beg
= NULL
, *family_end
= NULL
;
1323 int len
= strlen (name
);
1328 for (p
= name
; *p
; p
++)
1330 if (*p
== '\\' && p
[1])
1334 props_beg
= family_end
= p
;
1339 int decimal
= 0, size_found
= 1;
1340 for (q
= p
+ 1; *q
&& *q
!= ':'; q
++)
1343 if (*q
!= '.' || decimal
)
1362 Lisp_Object extra_props
= Qnil
;
1364 /* A fontconfig name with size and/or property data. */
1365 if (family_end
> name
)
1368 family
= font_intern_prop (name
, family_end
- name
, 1);
1369 ASET (font
, FONT_FAMILY_INDEX
, family
);
1373 double point_size
= strtod (size_beg
, &size_end
);
1374 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1375 if (*size_end
== ':' && size_end
[1])
1376 props_beg
= size_end
;
1380 /* Now parse ":KEY=VAL" patterns. */
1383 for (p
= props_beg
; *p
; p
= q
)
1385 for (q
= p
+ 1; *q
&& *q
!= '=' && *q
!= ':'; q
++);
1388 /* Must be an enumerated value. */
1392 val
= font_intern_prop (p
, q
- p
, 1);
1394 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1396 if (PROP_MATCH ("light", 5)
1397 || PROP_MATCH ("medium", 6)
1398 || PROP_MATCH ("demibold", 8)
1399 || PROP_MATCH ("bold", 4)
1400 || PROP_MATCH ("black", 5))
1401 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, val
);
1402 else if (PROP_MATCH ("roman", 5)
1403 || PROP_MATCH ("italic", 6)
1404 || PROP_MATCH ("oblique", 7))
1405 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, val
);
1406 else if (PROP_MATCH ("charcell", 8))
1407 ASET (font
, FONT_SPACING_INDEX
,
1408 make_number (FONT_SPACING_CHARCELL
));
1409 else if (PROP_MATCH ("mono", 4))
1410 ASET (font
, FONT_SPACING_INDEX
,
1411 make_number (FONT_SPACING_MONO
));
1412 else if (PROP_MATCH ("proportional", 12))
1413 ASET (font
, FONT_SPACING_INDEX
,
1414 make_number (FONT_SPACING_PROPORTIONAL
));
1423 if (q
- p
== 10 && memcmp (p
+ 1, "pixelsize", 9) == 0)
1424 prop
= FONT_SIZE_INDEX
;
1427 key
= font_intern_prop (p
, q
- p
, 1);
1428 prop
= get_font_prop_index (key
);
1432 for (q
= p
; *q
&& *q
!= ':'; q
++);
1433 val
= font_intern_prop (p
, q
- p
, 0);
1435 if (prop
>= FONT_FOUNDRY_INDEX
1436 && prop
< FONT_EXTRA_INDEX
)
1437 ASET (font
, prop
, font_prop_validate (prop
, Qnil
, val
));
1440 extra_props
= nconc2 (extra_props
,
1441 Fcons (Fcons (key
, val
), Qnil
));
1448 if (! NILP (extra_props
))
1450 struct font_driver_list
*driver_list
= font_driver_list
;
1451 for ( ; driver_list
; driver_list
= driver_list
->next
)
1452 if (driver_list
->driver
->filter_properties
)
1453 (*driver_list
->driver
->filter_properties
) (font
, extra_props
);
1459 /* Either a fontconfig-style name with no size and property
1460 data, or a GTK-style name. */
1462 int word_len
, prop_found
= 0;
1464 for (p
= name
; *p
; p
= *q
? q
+ 1 : q
)
1470 for (q
= p
+ 1; *q
&& *q
!= ' '; q
++)
1471 if (! isdigit (*q
) && *q
!= '.')
1478 double point_size
= strtod (p
, &q
);
1479 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1484 for (q
= p
+ 1; *q
&& *q
!= ' '; q
++)
1485 if (*q
== '\\' && q
[1])
1489 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1491 if (PROP_MATCH ("Ultra-Light", 11))
1494 prop
= font_intern_prop ("ultra-light", 11, 1);
1495 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1497 else if (PROP_MATCH ("Light", 5))
1500 prop
= font_intern_prop ("light", 5, 1);
1501 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1503 else if (PROP_MATCH ("Book", 4))
1506 prop
= font_intern_prop ("book", 4, 1);
1507 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1509 else if (PROP_MATCH ("Medium", 6))
1512 prop
= font_intern_prop ("medium", 6, 1);
1513 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1515 else if (PROP_MATCH ("Semi-Bold", 9))
1518 prop
= font_intern_prop ("semi-bold", 9, 1);
1519 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1521 else if (PROP_MATCH ("Bold", 4))
1524 prop
= font_intern_prop ("bold", 4, 1);
1525 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1527 else if (PROP_MATCH ("Italic", 6))
1530 prop
= font_intern_prop ("italic", 4, 1);
1531 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, prop
);
1533 else if (PROP_MATCH ("Oblique", 7))
1536 prop
= font_intern_prop ("oblique", 7, 1);
1537 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, prop
);
1539 else if (PROP_MATCH ("Semi-Condensed", 14))
1542 prop
= font_intern_prop ("semi-condensed", 14, 1);
1543 FONT_SET_STYLE (font
, FONT_WIDTH_INDEX
, prop
);
1545 else if (PROP_MATCH ("Condensed", 9))
1548 prop
= font_intern_prop ("condensed", 9, 1);
1549 FONT_SET_STYLE (font
, FONT_WIDTH_INDEX
, prop
);
1553 return -1; /* Unknown property in GTK-style font name. */
1562 family
= font_intern_prop (name
, family_end
- name
, 1);
1563 ASET (font
, FONT_FAMILY_INDEX
, family
);
1570 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1571 NAME (NBYTES length), and return the name length. If
1572 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1575 font_unparse_fcname (Lisp_Object font
, int pixel_size
, char *name
, int nbytes
)
1577 Lisp_Object family
, foundry
;
1578 Lisp_Object tail
, val
;
1582 Lisp_Object styles
[3];
1583 char *style_names
[3] = { "weight", "slant", "width" };
1586 family
= AREF (font
, FONT_FAMILY_INDEX
);
1587 if (! NILP (family
))
1589 if (SYMBOLP (family
))
1591 family
= SYMBOL_NAME (family
);
1592 len
+= SBYTES (family
);
1598 val
= AREF (font
, FONT_SIZE_INDEX
);
1601 if (XINT (val
) != 0)
1602 pixel_size
= XINT (val
);
1604 len
+= 21; /* for ":pixelsize=NUM" */
1606 else if (FLOATP (val
))
1609 point_size
= (int) XFLOAT_DATA (val
);
1610 len
+= 11; /* for "-NUM" */
1613 foundry
= AREF (font
, FONT_FOUNDRY_INDEX
);
1614 if (! NILP (foundry
))
1616 if (SYMBOLP (foundry
))
1618 foundry
= SYMBOL_NAME (foundry
);
1619 len
+= 9 + SBYTES (foundry
); /* ":foundry=NAME" */
1625 for (i
= 0; i
< 3; i
++)
1627 styles
[i
] = font_style_symbolic (font
, FONT_WEIGHT_INDEX
+ i
, 0);
1628 if (! NILP (styles
[i
]))
1629 len
+= sprintf (work
, ":%s=%s", style_names
[i
],
1630 SDATA (SYMBOL_NAME (styles
[i
])));
1633 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1634 len
+= sprintf (work
, ":dpi=%ld", (long)XINT (AREF (font
, FONT_DPI_INDEX
)));
1635 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1636 len
+= strlen (":spacing=100");
1637 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1638 len
+= strlen (":scalable=false"); /* or ":scalable=true" */
1639 for (tail
= AREF (font
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
1641 Lisp_Object key
= XCAR (XCAR (tail
)), val
= XCDR (XCAR (tail
));
1643 len
+= SBYTES (SYMBOL_NAME (key
)) + 1; /* for :KEY= */
1645 len
+= SBYTES (val
);
1646 else if (INTEGERP (val
))
1647 len
+= sprintf (work
, "%ld", (long) XINT (val
));
1648 else if (SYMBOLP (val
))
1649 len
+= (NILP (val
) ? 5 : 4); /* for "false" or "true" */
1655 if (! NILP (family
))
1656 p
+= sprintf (p
, "%s", SDATA (family
));
1660 p
+= sprintf (p
, "%d", point_size
);
1662 p
+= sprintf (p
, "-%d", point_size
);
1664 else if (pixel_size
> 0)
1665 p
+= sprintf (p
, ":pixelsize=%d", pixel_size
);
1666 if (! NILP (AREF (font
, FONT_FOUNDRY_INDEX
)))
1667 p
+= sprintf (p
, ":foundry=%s",
1668 SDATA (SYMBOL_NAME (AREF (font
, FONT_FOUNDRY_INDEX
))));
1669 for (i
= 0; i
< 3; i
++)
1670 if (! NILP (styles
[i
]))
1671 p
+= sprintf (p
, ":%s=%s", style_names
[i
],
1672 SDATA (SYMBOL_NAME (styles
[i
])));
1673 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1674 p
+= sprintf (p
, ":dpi=%ld", (long) XINT (AREF (font
, FONT_DPI_INDEX
)));
1675 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1676 p
+= sprintf (p
, ":spacing=%ld",
1677 (long) XINT (AREF (font
, FONT_SPACING_INDEX
)));
1678 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1680 if (XINT (AREF (font
, FONT_AVGWIDTH_INDEX
)) == 0)
1681 p
+= sprintf (p
, ":scalable=true");
1683 p
+= sprintf (p
, ":scalable=false");
1688 /* Store GTK-style font name of FONT (font-spec or font-entity) in
1689 NAME (NBYTES length), and return the name length. F is the frame
1690 on which the font is displayed; it is used to calculate the point
1694 font_unparse_gtkname (Lisp_Object font
, struct frame
*f
, char *name
, int nbytes
)
1698 Lisp_Object family
, weight
, slant
, size
;
1699 int point_size
= -1;
1701 family
= AREF (font
, FONT_FAMILY_INDEX
);
1702 if (! NILP (family
))
1704 if (! SYMBOLP (family
))
1706 family
= SYMBOL_NAME (family
);
1707 len
+= SBYTES (family
);
1710 weight
= font_style_symbolic (font
, FONT_WEIGHT_INDEX
, 0);
1711 if (EQ (weight
, Qnormal
))
1713 else if (! NILP (weight
))
1715 weight
= SYMBOL_NAME (weight
);
1716 len
+= SBYTES (weight
);
1719 slant
= font_style_symbolic (font
, FONT_SLANT_INDEX
, 0);
1720 if (EQ (slant
, Qnormal
))
1722 else if (! NILP (slant
))
1724 slant
= SYMBOL_NAME (slant
);
1725 len
+= SBYTES (slant
);
1728 size
= AREF (font
, FONT_SIZE_INDEX
);
1729 /* Convert pixel size to point size. */
1730 if (INTEGERP (size
))
1732 Lisp_Object font_dpi
= AREF (font
, FONT_DPI_INDEX
);
1734 if (INTEGERP (font_dpi
))
1735 dpi
= XINT (font_dpi
);
1738 point_size
= PIXEL_TO_POINT (XINT (size
), dpi
);
1741 else if (FLOATP (size
))
1743 point_size
= (int) XFLOAT_DATA (size
);
1750 p
= name
+ sprintf (name
, "%s", SDATA (family
));
1752 if (! NILP (weight
))
1755 p
+= sprintf (p
, " %s", SDATA (weight
));
1756 q
[1] = toupper (q
[1]);
1762 p
+= sprintf (p
, " %s", SDATA (slant
));
1763 q
[1] = toupper (q
[1]);
1767 p
+= sprintf (p
, " %d", point_size
);
1772 /* Parse NAME (null terminated) and store information in FONT
1773 (font-spec or font-entity). If NAME is successfully parsed, return
1774 0. Otherwise return -1. */
1777 font_parse_name (char *name
, Lisp_Object font
)
1779 if (name
[0] == '-' || strchr (name
, '*') || strchr (name
, '?'))
1780 return font_parse_xlfd (name
, font
);
1781 return font_parse_fcname (name
, font
);
1785 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1786 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1790 font_parse_family_registry (Lisp_Object family
, Lisp_Object registry
, Lisp_Object font_spec
)
1796 && NILP (AREF (font_spec
, FONT_FAMILY_INDEX
)))
1798 CHECK_STRING (family
);
1799 len
= SBYTES (family
);
1800 p0
= (char *) SDATA (family
);
1801 p1
= strchr (p0
, '-');
1804 if ((*p0
!= '*' && p1
- p0
> 0)
1805 && NILP (AREF (font_spec
, FONT_FOUNDRY_INDEX
)))
1806 Ffont_put (font_spec
, QCfoundry
, font_intern_prop (p0
, p1
- p0
, 1));
1809 Ffont_put (font_spec
, QCfamily
, font_intern_prop (p1
, len
, 1));
1812 ASET (font_spec
, FONT_FAMILY_INDEX
, Fintern (family
, Qnil
));
1814 if (! NILP (registry
))
1816 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1817 CHECK_STRING (registry
);
1818 len
= SBYTES (registry
);
1819 p0
= (char *) SDATA (registry
);
1820 p1
= strchr (p0
, '-');
1823 if (SDATA (registry
)[len
- 1] == '*')
1824 registry
= concat2 (registry
, build_string ("-*"));
1826 registry
= concat2 (registry
, build_string ("*-*"));
1828 registry
= Fdowncase (registry
);
1829 ASET (font_spec
, FONT_REGISTRY_INDEX
, Fintern (registry
, Qnil
));
1834 /* This part (through the next ^L) is still experimental and not
1835 tested much. We may drastically change codes. */
1841 #define LGSTRING_HEADER_SIZE 6
1842 #define LGSTRING_GLYPH_SIZE 8
1845 check_gstring (gstring
)
1846 Lisp_Object gstring
;
1851 CHECK_VECTOR (gstring
);
1852 val
= AREF (gstring
, 0);
1854 if (ASIZE (val
) < LGSTRING_HEADER_SIZE
)
1856 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring
));
1857 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
)))
1858 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
));
1859 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
)))
1860 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
));
1861 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
)))
1862 CHECK_NATNUM (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
));
1863 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1864 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1865 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1866 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1868 for (i
= 0; i
< LGSTRING_GLYPH_LEN (gstring
); i
++)
1870 val
= LGSTRING_GLYPH (gstring
, i
);
1872 if (ASIZE (val
) < LGSTRING_GLYPH_SIZE
)
1874 if (NILP (AREF (val
, LGLYPH_IX_CHAR
)))
1876 CHECK_NATNUM (AREF (val
, LGLYPH_IX_FROM
));
1877 CHECK_NATNUM (AREF (val
, LGLYPH_IX_TO
));
1878 CHECK_CHARACTER (AREF (val
, LGLYPH_IX_CHAR
));
1879 if (!NILP (AREF (val
, LGLYPH_IX_CODE
)))
1880 CHECK_NATNUM (AREF (val
, LGLYPH_IX_CODE
));
1881 if (!NILP (AREF (val
, LGLYPH_IX_WIDTH
)))
1882 CHECK_NATNUM (AREF (val
, LGLYPH_IX_WIDTH
));
1883 if (!NILP (AREF (val
, LGLYPH_IX_ADJUSTMENT
)))
1885 val
= AREF (val
, LGLYPH_IX_ADJUSTMENT
);
1887 if (ASIZE (val
) < 3)
1889 for (j
= 0; j
< 3; j
++)
1890 CHECK_NUMBER (AREF (val
, j
));
1895 error ("Invalid glyph-string format");
1900 check_otf_features (otf_features
)
1901 Lisp_Object otf_features
;
1905 CHECK_CONS (otf_features
);
1906 CHECK_SYMBOL (XCAR (otf_features
));
1907 otf_features
= XCDR (otf_features
);
1908 CHECK_CONS (otf_features
);
1909 CHECK_SYMBOL (XCAR (otf_features
));
1910 otf_features
= XCDR (otf_features
);
1911 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1913 CHECK_SYMBOL (Fcar (val
));
1914 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1915 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val
)));
1917 otf_features
= XCDR (otf_features
);
1918 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1920 CHECK_SYMBOL (Fcar (val
));
1921 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1922 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val
)));
1929 Lisp_Object otf_list
;
1932 otf_tag_symbol (tag
)
1937 OTF_tag_name (tag
, name
);
1938 return Fintern (make_unibyte_string (name
, 4), Qnil
);
1945 Lisp_Object val
= Fassoc (file
, otf_list
);
1949 otf
= XSAVE_VALUE (XCDR (val
))->pointer
;
1952 otf
= STRINGP (file
) ? OTF_open ((char *) SDATA (file
)) : NULL
;
1953 val
= make_save_value (otf
, 0);
1954 otf_list
= Fcons (Fcons (file
, val
), otf_list
);
1960 /* Return a list describing which scripts/languages FONT supports by
1961 which GSUB/GPOS features of OpenType tables. See the comment of
1962 (struct font_driver).otf_capability. */
1965 font_otf_capability (font
)
1969 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
1972 otf
= otf_open (font
->props
[FONT_FILE_INDEX
]);
1975 for (i
= 0; i
< 2; i
++)
1977 OTF_GSUB_GPOS
*gsub_gpos
;
1978 Lisp_Object script_list
= Qnil
;
1981 if (OTF_get_features (otf
, i
== 0) < 0)
1983 gsub_gpos
= i
== 0 ? otf
->gsub
: otf
->gpos
;
1984 for (j
= gsub_gpos
->ScriptList
.ScriptCount
- 1; j
>= 0; j
--)
1986 OTF_Script
*script
= gsub_gpos
->ScriptList
.Script
+ j
;
1987 Lisp_Object langsys_list
= Qnil
;
1988 Lisp_Object script_tag
= otf_tag_symbol (script
->ScriptTag
);
1991 for (k
= script
->LangSysCount
; k
>= 0; k
--)
1993 OTF_LangSys
*langsys
;
1994 Lisp_Object feature_list
= Qnil
;
1995 Lisp_Object langsys_tag
;
1998 if (k
== script
->LangSysCount
)
2000 langsys
= &script
->DefaultLangSys
;
2005 langsys
= script
->LangSys
+ k
;
2007 = otf_tag_symbol (script
->LangSysRecord
[k
].LangSysTag
);
2009 for (l
= langsys
->FeatureCount
- 1; l
>= 0; l
--)
2011 OTF_Feature
*feature
2012 = gsub_gpos
->FeatureList
.Feature
+ langsys
->FeatureIndex
[l
];
2013 Lisp_Object feature_tag
2014 = otf_tag_symbol (feature
->FeatureTag
);
2016 feature_list
= Fcons (feature_tag
, feature_list
);
2018 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
2021 script_list
= Fcons (Fcons (script_tag
, langsys_list
),
2026 XSETCAR (capability
, script_list
);
2028 XSETCDR (capability
, script_list
);
2034 /* Parse OTF features in SPEC and write a proper features spec string
2035 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
2036 assured that the sufficient memory has already allocated for
2040 generate_otf_features (spec
, features
)
2050 for (asterisk
= 0; CONSP (spec
); spec
= XCDR (spec
))
2056 if (SREF (SYMBOL_NAME (val
), 0) == '*')
2061 else if (! asterisk
)
2063 val
= SYMBOL_NAME (val
);
2064 p
+= sprintf (p
, "%s", SDATA (val
));
2068 val
= SYMBOL_NAME (val
);
2069 p
+= sprintf (p
, "~%s", SDATA (val
));
2073 error ("OTF spec too long");
2077 font_otf_DeviceTable (device_table
)
2078 OTF_DeviceTable
*device_table
;
2080 int len
= device_table
->StartSize
- device_table
->EndSize
+ 1;
2082 return Fcons (make_number (len
),
2083 make_unibyte_string (device_table
->DeltaValue
, len
));
2087 font_otf_ValueRecord (value_format
, value_record
)
2089 OTF_ValueRecord
*value_record
;
2091 Lisp_Object val
= Fmake_vector (make_number (8), Qnil
);
2093 if (value_format
& OTF_XPlacement
)
2094 ASET (val
, 0, make_number (value_record
->XPlacement
));
2095 if (value_format
& OTF_YPlacement
)
2096 ASET (val
, 1, make_number (value_record
->YPlacement
));
2097 if (value_format
& OTF_XAdvance
)
2098 ASET (val
, 2, make_number (value_record
->XAdvance
));
2099 if (value_format
& OTF_YAdvance
)
2100 ASET (val
, 3, make_number (value_record
->YAdvance
));
2101 if (value_format
& OTF_XPlaDevice
)
2102 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XPlaDevice
));
2103 if (value_format
& OTF_YPlaDevice
)
2104 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YPlaDevice
));
2105 if (value_format
& OTF_XAdvDevice
)
2106 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XAdvDevice
));
2107 if (value_format
& OTF_YAdvDevice
)
2108 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YAdvDevice
));
2113 font_otf_Anchor (anchor
)
2118 val
= Fmake_vector (make_number (anchor
->AnchorFormat
+ 1), Qnil
);
2119 ASET (val
, 0, make_number (anchor
->XCoordinate
));
2120 ASET (val
, 1, make_number (anchor
->YCoordinate
));
2121 if (anchor
->AnchorFormat
== 2)
2122 ASET (val
, 2, make_number (anchor
->f
.f1
.AnchorPoint
));
2125 ASET (val
, 3, font_otf_DeviceTable (&anchor
->f
.f2
.XDeviceTable
));
2126 ASET (val
, 4, font_otf_DeviceTable (&anchor
->f
.f2
.YDeviceTable
));
2130 #endif /* HAVE_LIBOTF */
2136 static unsigned font_score (Lisp_Object
, Lisp_Object
*);
2137 static int font_compare (const void *, const void *);
2138 static Lisp_Object
font_sort_entities (Lisp_Object
, Lisp_Object
,
2141 /* Return a rescaling ratio of FONT_ENTITY. */
2142 extern Lisp_Object Vface_font_rescale_alist
;
2145 font_rescale_ratio (Lisp_Object font_entity
)
2147 Lisp_Object tail
, elt
;
2148 Lisp_Object name
= Qnil
;
2150 for (tail
= Vface_font_rescale_alist
; CONSP (tail
); tail
= XCDR (tail
))
2153 if (FLOATP (XCDR (elt
)))
2155 if (STRINGP (XCAR (elt
)))
2158 name
= Ffont_xlfd_name (font_entity
, Qnil
);
2159 if (fast_string_match_ignore_case (XCAR (elt
), name
) >= 0)
2160 return XFLOAT_DATA (XCDR (elt
));
2162 else if (FONT_SPEC_P (XCAR (elt
)))
2164 if (font_match_p (XCAR (elt
), font_entity
))
2165 return XFLOAT_DATA (XCDR (elt
));
2172 /* We sort fonts by scoring each of them against a specified
2173 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2174 the value is, the closer the font is to the font-spec.
2176 The lowest 2 bits of the score is used for driver type. The font
2177 available by the most preferred font driver is 0.
2179 Each 7-bit in the higher 28 bits are used for numeric properties
2180 WEIGHT, SLANT, WIDTH, and SIZE. */
2182 /* How many bits to shift to store the difference value of each font
2183 property in a score. Note that flots for FONT_TYPE_INDEX and
2184 FONT_REGISTRY_INDEX are not used. */
2185 static int sort_shift_bits
[FONT_SIZE_INDEX
+ 1];
2187 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2188 The return value indicates how different ENTITY is compared with
2192 font_score (Lisp_Object entity
, Lisp_Object
*spec_prop
)
2197 /* Score three style numeric fields. Maximum difference is 127. */
2198 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
; i
++)
2199 if (! NILP (spec_prop
[i
]) && ! EQ (AREF (entity
, i
), spec_prop
[i
]))
2201 int diff
= (XINT (AREF (entity
, i
)) >> 8) - (XINT (spec_prop
[i
]) >> 8);
2206 score
|= min (diff
, 127) << sort_shift_bits
[i
];
2209 /* Score the size. Maximum difference is 127. */
2210 i
= FONT_SIZE_INDEX
;
2211 if (! NILP (spec_prop
[FONT_SIZE_INDEX
])
2212 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2214 /* We use the higher 6-bit for the actual size difference. The
2215 lowest bit is set if the DPI is different. */
2217 int pixel_size
= XINT (spec_prop
[FONT_SIZE_INDEX
]);
2219 if (CONSP (Vface_font_rescale_alist
))
2220 pixel_size
*= font_rescale_ratio (entity
);
2221 diff
= pixel_size
- XINT (AREF (entity
, FONT_SIZE_INDEX
));
2225 if (! NILP (spec_prop
[FONT_DPI_INDEX
])
2226 && ! EQ (spec_prop
[FONT_DPI_INDEX
], AREF (entity
, FONT_DPI_INDEX
)))
2228 if (! NILP (spec_prop
[FONT_AVGWIDTH_INDEX
])
2229 && ! EQ (spec_prop
[FONT_AVGWIDTH_INDEX
], AREF (entity
, FONT_AVGWIDTH_INDEX
)))
2231 score
|= min (diff
, 127) << sort_shift_bits
[FONT_SIZE_INDEX
];
2238 /* Concatenate all elements of LIST into one vector. LIST is a list
2239 of font-entity vectors. */
2242 font_vconcat_entity_vectors (Lisp_Object list
)
2244 int nargs
= XINT (Flength (list
));
2245 Lisp_Object
*args
= alloca (sizeof (Lisp_Object
) * nargs
);
2248 for (i
= 0; i
< nargs
; i
++, list
= XCDR (list
))
2249 args
[i
] = XCAR (list
);
2250 return Fvconcat (nargs
, args
);
2254 /* The structure for elements being sorted by qsort. */
2255 struct font_sort_data
2258 int font_driver_preference
;
2263 /* The comparison function for qsort. */
2266 font_compare (const void *d1
, const void *d2
)
2268 const struct font_sort_data
*data1
= d1
;
2269 const struct font_sort_data
*data2
= d2
;
2271 if (data1
->score
< data2
->score
)
2273 else if (data1
->score
> data2
->score
)
2275 return (data1
->font_driver_preference
- data2
->font_driver_preference
);
2279 /* Sort each font-entity vector in LIST by closeness to font-spec PREFER.
2280 If PREFER specifies a point-size, calculate the corresponding
2281 pixel-size from QCdpi property of PREFER or from the Y-resolution
2282 of FRAME before sorting.
2284 If BEST-ONLY is nonzero, return the best matching entity (that
2285 supports the character BEST-ONLY if BEST-ONLY is positive, or any
2286 if BEST-ONLY is negative). Otherwise, return the sorted result as
2287 a single vector of font-entities.
2289 This function does no optimization for the case that the total
2290 number of elements is 1. The caller should avoid calling this in
2294 font_sort_entities (Lisp_Object list
, Lisp_Object prefer
, Lisp_Object frame
, int best_only
)
2296 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2298 struct font_sort_data
*data
;
2299 unsigned best_score
;
2300 Lisp_Object best_entity
;
2301 struct frame
*f
= XFRAME (frame
);
2302 Lisp_Object tail
, vec
;
2305 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_AVGWIDTH_INDEX
; i
++)
2306 prefer_prop
[i
] = AREF (prefer
, i
);
2307 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2308 prefer_prop
[FONT_SIZE_INDEX
]
2309 = make_number (font_pixel_size (XFRAME (frame
), prefer
));
2311 if (NILP (XCDR (list
)))
2313 /* What we have to take care of is this single vector. */
2315 maxlen
= ASIZE (vec
);
2319 /* We don't have to perform sort, so there's no need of creating
2320 a single vector. But, we must find the length of the longest
2323 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
2324 if (maxlen
< ASIZE (XCAR (tail
)))
2325 maxlen
= ASIZE (XCAR (tail
));
2329 /* We have to create a single vector to sort it. */
2330 vec
= font_vconcat_entity_vectors (list
);
2331 maxlen
= ASIZE (vec
);
2334 SAFE_ALLOCA (data
, struct font_sort_data
*, (sizeof *data
) * maxlen
);
2335 best_score
= 0xFFFFFFFF;
2338 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
2340 int font_driver_preference
= 0;
2341 Lisp_Object current_font_driver
;
2347 /* We are sure that the length of VEC > 0. */
2348 current_font_driver
= AREF (AREF (vec
, 0), FONT_TYPE_INDEX
);
2349 /* Score the elements. */
2350 for (i
= 0; i
< len
; i
++)
2352 data
[i
].entity
= AREF (vec
, i
);
2354 = ((best_only
<= 0 || font_has_char (f
, data
[i
].entity
, best_only
)
2356 ? font_score (data
[i
].entity
, prefer_prop
)
2358 if (best_only
&& best_score
> data
[i
].score
)
2360 best_score
= data
[i
].score
;
2361 best_entity
= data
[i
].entity
;
2362 if (best_score
== 0)
2365 if (! EQ (current_font_driver
, AREF (AREF (vec
, i
), FONT_TYPE_INDEX
)))
2367 current_font_driver
= AREF (AREF (vec
, i
), FONT_TYPE_INDEX
);
2368 font_driver_preference
++;
2370 data
[i
].font_driver_preference
= font_driver_preference
;
2373 /* Sort if necessary. */
2376 qsort (data
, len
, sizeof *data
, font_compare
);
2377 for (i
= 0; i
< len
; i
++)
2378 ASET (vec
, i
, data
[i
].entity
);
2387 FONT_ADD_LOG ("sort-by", prefer
, vec
);
2392 /* API of Font Service Layer. */
2394 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2395 sort_shift_bits. Finternal_set_font_selection_order calls this
2396 function with font_sort_order after setting up it. */
2399 font_update_sort_order (int *order
)
2403 for (i
= 0, shift_bits
= 23; i
< 4; i
++, shift_bits
-= 7)
2405 int xlfd_idx
= order
[i
];
2407 if (xlfd_idx
== XLFD_WEIGHT_INDEX
)
2408 sort_shift_bits
[FONT_WEIGHT_INDEX
] = shift_bits
;
2409 else if (xlfd_idx
== XLFD_SLANT_INDEX
)
2410 sort_shift_bits
[FONT_SLANT_INDEX
] = shift_bits
;
2411 else if (xlfd_idx
== XLFD_SWIDTH_INDEX
)
2412 sort_shift_bits
[FONT_WIDTH_INDEX
] = shift_bits
;
2414 sort_shift_bits
[FONT_SIZE_INDEX
] = shift_bits
;
2419 font_check_otf_features (Lisp_Object script
, Lisp_Object langsys
, Lisp_Object features
, Lisp_Object table
)
2424 table
= assq_no_quit (script
, table
);
2427 table
= XCDR (table
);
2428 if (! NILP (langsys
))
2430 table
= assq_no_quit (langsys
, table
);
2436 val
= assq_no_quit (Qnil
, table
);
2438 table
= XCAR (table
);
2442 table
= XCDR (table
);
2443 for (negative
= 0; CONSP (features
); features
= XCDR (features
))
2445 if (NILP (XCAR (features
)))
2450 if (NILP (Fmemq (XCAR (features
), table
)) != negative
)
2456 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2459 font_check_otf (Lisp_Object spec
, Lisp_Object otf_capability
)
2461 Lisp_Object script
, langsys
= Qnil
, gsub
= Qnil
, gpos
= Qnil
;
2463 script
= XCAR (spec
);
2467 langsys
= XCAR (spec
);
2478 if (! NILP (gsub
) && ! font_check_otf_features (script
, langsys
, gsub
,
2479 XCAR (otf_capability
)))
2481 if (! NILP (gpos
) && ! font_check_otf_features (script
, langsys
, gpos
,
2482 XCDR (otf_capability
)))
2489 /* Check if FONT (font-entity or font-object) matches with the font
2490 specification SPEC. */
2493 font_match_p (Lisp_Object spec
, Lisp_Object font
)
2495 Lisp_Object prop
[FONT_SPEC_MAX
], *props
;
2496 Lisp_Object extra
, font_extra
;
2499 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2500 if (! NILP (AREF (spec
, i
))
2501 && ! NILP (AREF (font
, i
))
2502 && ! EQ (AREF (spec
, i
), AREF (font
, i
)))
2504 props
= XFONT_SPEC (spec
)->props
;
2505 if (FLOATP (props
[FONT_SIZE_INDEX
]))
2507 for (i
= FONT_FOUNDRY_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2508 prop
[i
] = AREF (spec
, i
);
2509 prop
[FONT_SIZE_INDEX
]
2510 = make_number (font_pixel_size (XFRAME (selected_frame
), spec
));
2514 if (font_score (font
, props
) > 0)
2516 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
2517 font_extra
= AREF (font
, FONT_EXTRA_INDEX
);
2518 for (; CONSP (extra
); extra
= XCDR (extra
))
2520 Lisp_Object key
= XCAR (XCAR (extra
));
2521 Lisp_Object val
= XCDR (XCAR (extra
)), val2
;
2523 if (EQ (key
, QClang
))
2525 val2
= assq_no_quit (key
, font_extra
);
2534 if (NILP (Fmemq (val
, val2
)))
2539 ? NILP (Fmemq (val
, XCDR (val2
)))
2543 else if (EQ (key
, QCscript
))
2545 val2
= assq_no_quit (val
, Vscript_representative_chars
);
2551 /* All characters in the list must be supported. */
2552 for (; CONSP (val2
); val2
= XCDR (val2
))
2554 if (! NATNUMP (XCAR (val2
)))
2556 if (font_encode_char (font
, XFASTINT (XCAR (val2
)))
2557 == FONT_INVALID_CODE
)
2561 else if (VECTORP (val2
))
2563 /* At most one character in the vector must be supported. */
2564 for (i
= 0; i
< ASIZE (val2
); i
++)
2566 if (! NATNUMP (AREF (val2
, i
)))
2568 if (font_encode_char (font
, XFASTINT (AREF (val2
, i
)))
2569 != FONT_INVALID_CODE
)
2572 if (i
== ASIZE (val2
))
2577 else if (EQ (key
, QCotf
))
2581 if (! FONT_OBJECT_P (font
))
2583 fontp
= XFONT_OBJECT (font
);
2584 if (! fontp
->driver
->otf_capability
)
2586 val2
= fontp
->driver
->otf_capability (fontp
);
2587 if (NILP (val2
) || ! font_check_otf (val
, val2
))
2598 Each font backend has the callback function get_cache, and it
2599 returns a cons cell of which cdr part can be freely used for
2600 caching fonts. The cons cell may be shared by multiple frames
2601 and/or multiple font drivers. So, we arrange the cdr part as this:
2603 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2605 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2606 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2607 cons (FONT-SPEC FONT-ENTITY ...). */
2609 static void font_prepare_cache (FRAME_PTR
, struct font_driver
*);
2610 static void font_finish_cache (FRAME_PTR
, struct font_driver
*);
2611 static Lisp_Object
font_get_cache (FRAME_PTR
, struct font_driver
*);
2612 static void font_clear_cache (FRAME_PTR
, Lisp_Object
,
2613 struct font_driver
*);
2616 font_prepare_cache (FRAME_PTR f
, struct font_driver
*driver
)
2618 Lisp_Object cache
, val
;
2620 cache
= driver
->get_cache (f
);
2622 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2626 val
= Fcons (driver
->type
, Fcons (make_number (1), Qnil
));
2627 XSETCDR (cache
, Fcons (val
, XCDR (cache
)));
2631 val
= XCDR (XCAR (val
));
2632 XSETCAR (val
, make_number (XINT (XCAR (val
)) + 1));
2638 font_finish_cache (FRAME_PTR f
, struct font_driver
*driver
)
2640 Lisp_Object cache
, val
, tmp
;
2643 cache
= driver
->get_cache (f
);
2645 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2646 cache
= val
, val
= XCDR (val
);
2647 font_assert (! NILP (val
));
2648 tmp
= XCDR (XCAR (val
));
2649 XSETCAR (tmp
, make_number (XINT (XCAR (tmp
)) - 1));
2650 if (XINT (XCAR (tmp
)) == 0)
2652 font_clear_cache (f
, XCAR (val
), driver
);
2653 XSETCDR (cache
, XCDR (val
));
2659 font_get_cache (FRAME_PTR f
, struct font_driver
*driver
)
2661 Lisp_Object val
= driver
->get_cache (f
);
2662 Lisp_Object type
= driver
->type
;
2664 font_assert (CONSP (val
));
2665 for (val
= XCDR (val
); ! EQ (XCAR (XCAR (val
)), type
); val
= XCDR (val
));
2666 font_assert (CONSP (val
));
2667 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2668 val
= XCDR (XCAR (val
));
2672 static int num_fonts
;
2675 font_clear_cache (FRAME_PTR f
, Lisp_Object cache
, struct font_driver
*driver
)
2677 Lisp_Object tail
, elt
;
2678 Lisp_Object tail2
, entity
;
2680 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2681 for (tail
= XCDR (XCDR (cache
)); CONSP (tail
); tail
= XCDR (tail
))
2684 /* elt should have the form (FONT-SPEC FONT-ENTITY ...) */
2685 if (CONSP (elt
) && FONT_SPEC_P (XCAR (elt
)))
2687 for (tail2
= XCDR (elt
); CONSP (tail2
); tail2
= XCDR (tail2
))
2689 entity
= XCAR (tail2
);
2691 if (FONT_ENTITY_P (entity
)
2692 && EQ (driver
->type
, AREF (entity
, FONT_TYPE_INDEX
)))
2694 Lisp_Object objlist
= AREF (entity
, FONT_OBJLIST_INDEX
);
2696 for (; CONSP (objlist
); objlist
= XCDR (objlist
))
2698 Lisp_Object val
= XCAR (objlist
);
2699 struct font
*font
= XFONT_OBJECT (val
);
2701 if (! NILP (AREF (val
, FONT_TYPE_INDEX
)))
2703 font_assert (font
&& driver
== font
->driver
);
2704 driver
->close (f
, font
);
2708 if (driver
->free_entity
)
2709 driver
->free_entity (entity
);
2714 XSETCDR (cache
, Qnil
);
2718 static Lisp_Object scratch_font_spec
, scratch_font_prefer
;
2720 /* Check each font-entity in VEC, and return a list of font-entities
2721 that satisfy this condition:
2722 (1) matches with SPEC and SIZE if SPEC is not nil, and
2723 (2) doesn't match with any regexps in Vface_ignored_fonts (if non-nil).
2726 extern Lisp_Object Vface_ignored_fonts
;
2729 font_delete_unmatched (Lisp_Object vec
, Lisp_Object spec
, int size
)
2731 Lisp_Object entity
, val
;
2732 enum font_property_index prop
;
2735 for (val
= Qnil
, i
= ASIZE (vec
) - 1; i
>= 0; i
--)
2737 entity
= AREF (vec
, i
);
2738 if (! NILP (Vface_ignored_fonts
))
2741 Lisp_Object tail
, regexp
;
2743 if (font_unparse_xlfd (entity
, 0, name
, 256) >= 0)
2745 for (tail
= Vface_ignored_fonts
; CONSP (tail
); tail
= XCDR (tail
))
2747 regexp
= XCAR (tail
);
2748 if (STRINGP (regexp
)
2749 && fast_c_string_match_ignore_case (regexp
, name
) >= 0)
2758 val
= Fcons (entity
, val
);
2761 for (prop
= FONT_WEIGHT_INDEX
; prop
< FONT_SIZE_INDEX
; prop
++)
2762 if (INTEGERP (AREF (spec
, prop
))
2763 && ((XINT (AREF (spec
, prop
)) >> 8)
2764 != (XINT (AREF (entity
, prop
)) >> 8)))
2765 prop
= FONT_SPEC_MAX
;
2766 if (prop
< FONT_SPEC_MAX
2768 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2770 int diff
= XINT (AREF (entity
, FONT_SIZE_INDEX
)) - size
;
2773 && (diff
< 0 ? -diff
> FONT_PIXEL_SIZE_QUANTUM
2774 : diff
> FONT_PIXEL_SIZE_QUANTUM
))
2775 prop
= FONT_SPEC_MAX
;
2777 if (prop
< FONT_SPEC_MAX
2778 && INTEGERP (AREF (spec
, FONT_DPI_INDEX
))
2779 && INTEGERP (AREF (entity
, FONT_DPI_INDEX
))
2780 && XINT (AREF (entity
, FONT_DPI_INDEX
)) != 0
2781 && ! EQ (AREF (spec
, FONT_DPI_INDEX
), AREF (entity
, FONT_DPI_INDEX
)))
2782 prop
= FONT_SPEC_MAX
;
2783 if (prop
< FONT_SPEC_MAX
2784 && INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
2785 && INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
2786 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) != 0
2787 && ! EQ (AREF (spec
, FONT_AVGWIDTH_INDEX
),
2788 AREF (entity
, FONT_AVGWIDTH_INDEX
)))
2789 prop
= FONT_SPEC_MAX
;
2790 if (prop
< FONT_SPEC_MAX
)
2791 val
= Fcons (entity
, val
);
2793 return (Fvconcat (1, &val
));
2797 /* Return a list of vectors of font-entities matching with SPEC on
2798 FRAME. Each elements in the list is a vector of entities from the
2799 same font-driver. */
2802 font_list_entities (Lisp_Object frame
, Lisp_Object spec
)
2804 FRAME_PTR f
= XFRAME (frame
);
2805 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2806 Lisp_Object ftype
, val
;
2807 Lisp_Object list
= Qnil
;
2809 int need_filtering
= 0;
2812 font_assert (FONT_SPEC_P (spec
));
2814 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2815 size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
2816 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
2817 size
= font_pixel_size (f
, spec
);
2821 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2822 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2823 ASET (scratch_font_spec
, i
, AREF (spec
, i
));
2824 for (i
= FONT_WEIGHT_INDEX
; i
< FONT_EXTRA_INDEX
; i
++)
2826 ASET (scratch_font_spec
, i
, Qnil
);
2827 if (! NILP (AREF (spec
, i
)))
2829 if (i
== FONT_DPI_INDEX
)
2830 /* Skip FONT_SPACING_INDEX */
2833 ASET (scratch_font_spec
, FONT_SPACING_INDEX
, AREF (spec
, FONT_SPACING_INDEX
));
2834 ASET (scratch_font_spec
, FONT_EXTRA_INDEX
, AREF (spec
, FONT_EXTRA_INDEX
));
2836 for (i
= 0; driver_list
; driver_list
= driver_list
->next
)
2838 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2840 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2842 ASET (scratch_font_spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2843 val
= assoc_no_quit (scratch_font_spec
, XCDR (cache
));
2850 val
= driver_list
->driver
->list (frame
, scratch_font_spec
);
2854 val
= Fvconcat (1, &val
);
2855 copy
= Fcopy_font_spec (scratch_font_spec
);
2856 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2857 XSETCDR (cache
, Fcons (Fcons (copy
, val
), XCDR (cache
)));
2861 || ! NILP (Vface_ignored_fonts
)))
2862 val
= font_delete_unmatched (val
, need_filtering
? spec
: Qnil
, size
);
2863 if (ASIZE (val
) > 0)
2864 list
= Fcons (val
, list
);
2867 list
= Fnreverse (list
);
2868 FONT_ADD_LOG ("list", spec
, list
);
2873 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2874 nil, is an array of face's attributes, which specifies preferred
2875 font-related attributes. */
2878 font_matching_entity (FRAME_PTR f
, Lisp_Object
*attrs
, Lisp_Object spec
)
2880 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2881 Lisp_Object ftype
, size
, entity
;
2883 Lisp_Object work
= Fcopy_font_spec (spec
);
2885 XSETFRAME (frame
, f
);
2886 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2887 size
= AREF (spec
, FONT_SIZE_INDEX
);
2890 ASET (work
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2891 FONT_SET_STYLE (work
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
2892 FONT_SET_STYLE (work
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
2893 FONT_SET_STYLE (work
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
2896 for (; driver_list
; driver_list
= driver_list
->next
)
2898 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2900 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2903 ASET (work
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2904 entity
= assoc_no_quit (work
, XCDR (cache
));
2906 entity
= XCDR (entity
);
2909 entity
= driver_list
->driver
->match (frame
, work
);
2910 copy
= Fcopy_font_spec (work
);
2911 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2912 XSETCDR (cache
, Fcons (Fcons (copy
, entity
), XCDR (cache
)));
2914 if (! NILP (entity
))
2917 FONT_ADD_LOG ("match", work
, entity
);
2922 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2923 opened font object. */
2926 font_open_entity (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
2928 struct font_driver_list
*driver_list
;
2929 Lisp_Object objlist
, size
, val
, font_object
;
2931 int min_width
, height
;
2932 int scaled_pixel_size
;
2934 font_assert (FONT_ENTITY_P (entity
));
2935 size
= AREF (entity
, FONT_SIZE_INDEX
);
2936 if (XINT (size
) != 0)
2937 scaled_pixel_size
= pixel_size
= XINT (size
);
2938 else if (CONSP (Vface_font_rescale_alist
))
2939 scaled_pixel_size
= pixel_size
* font_rescale_ratio (entity
);
2941 val
= AREF (entity
, FONT_TYPE_INDEX
);
2942 for (driver_list
= f
->font_driver_list
;
2943 driver_list
&& ! EQ (driver_list
->driver
->type
, val
);
2944 driver_list
= driver_list
->next
);
2948 for (objlist
= AREF (entity
, FONT_OBJLIST_INDEX
); CONSP (objlist
);
2949 objlist
= XCDR (objlist
))
2951 Lisp_Object fn
= XCAR (objlist
);
2952 if (! NILP (AREF (fn
, FONT_TYPE_INDEX
))
2953 && XFONT_OBJECT (fn
)->pixel_size
== pixel_size
)
2955 if (driver_list
->driver
->cached_font_ok
== NULL
2956 || driver_list
->driver
->cached_font_ok (f
, fn
, entity
))
2961 font_object
= driver_list
->driver
->open (f
, entity
, scaled_pixel_size
);
2962 if (!NILP (font_object
))
2963 ASET (font_object
, FONT_SIZE_INDEX
, make_number (pixel_size
));
2964 FONT_ADD_LOG ("open", entity
, font_object
);
2965 if (NILP (font_object
))
2967 ASET (entity
, FONT_OBJLIST_INDEX
,
2968 Fcons (font_object
, AREF (entity
, FONT_OBJLIST_INDEX
)));
2971 font
= XFONT_OBJECT (font_object
);
2972 min_width
= (font
->min_width
? font
->min_width
2973 : font
->average_width
? font
->average_width
2974 : font
->space_width
? font
->space_width
2976 height
= (font
->height
? font
->height
: 1);
2977 #ifdef HAVE_WINDOW_SYSTEM
2978 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
2979 if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
== 1)
2981 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
;
2982 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
;
2983 fonts_changed_p
= 1;
2987 if (FRAME_SMALLEST_CHAR_WIDTH (f
) > min_width
)
2988 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
, fonts_changed_p
= 1;
2989 if (FRAME_SMALLEST_FONT_HEIGHT (f
) > height
)
2990 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
, fonts_changed_p
= 1;
2998 /* Close FONT_OBJECT that is opened on frame F. */
3001 font_close_object (FRAME_PTR f
, Lisp_Object font_object
)
3003 struct font
*font
= XFONT_OBJECT (font_object
);
3005 if (NILP (AREF (font_object
, FONT_TYPE_INDEX
)))
3006 /* Already closed. */
3008 FONT_ADD_LOG ("close", font_object
, Qnil
);
3009 font
->driver
->close (f
, font
);
3010 #ifdef HAVE_WINDOW_SYSTEM
3011 font_assert (FRAME_X_DISPLAY_INFO (f
)->n_fonts
);
3012 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
3018 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
3019 FONT is a font-entity and it must be opened to check. */
3022 font_has_char (FRAME_PTR f
, Lisp_Object font
, int c
)
3026 if (FONT_ENTITY_P (font
))
3028 Lisp_Object type
= AREF (font
, FONT_TYPE_INDEX
);
3029 struct font_driver_list
*driver_list
;
3031 for (driver_list
= f
->font_driver_list
;
3032 driver_list
&& ! EQ (driver_list
->driver
->type
, type
);
3033 driver_list
= driver_list
->next
);
3036 if (! driver_list
->driver
->has_char
)
3038 return driver_list
->driver
->has_char (font
, c
);
3041 font_assert (FONT_OBJECT_P (font
));
3042 fontp
= XFONT_OBJECT (font
);
3043 if (fontp
->driver
->has_char
)
3045 int result
= fontp
->driver
->has_char (font
, c
);
3050 return (fontp
->driver
->encode_char (fontp
, c
) != FONT_INVALID_CODE
);
3054 /* Return the glyph ID of FONT_OBJECT for character C. */
3057 font_encode_char (Lisp_Object font_object
, int c
)
3061 font_assert (FONT_OBJECT_P (font_object
));
3062 font
= XFONT_OBJECT (font_object
);
3063 return font
->driver
->encode_char (font
, c
);
3067 /* Return the name of FONT_OBJECT. */
3070 font_get_name (Lisp_Object font_object
)
3072 font_assert (FONT_OBJECT_P (font_object
));
3073 return AREF (font_object
, FONT_NAME_INDEX
);
3077 /* Return the specification of FONT_OBJECT. */
3080 font_get_spec (Lisp_Object font_object
)
3082 Lisp_Object spec
= font_make_spec ();
3085 for (i
= 0; i
< FONT_SIZE_INDEX
; i
++)
3086 ASET (spec
, i
, AREF (font_object
, i
));
3087 ASET (spec
, FONT_SIZE_INDEX
,
3088 make_number (XFONT_OBJECT (font_object
)->pixel_size
));
3093 /* Create a new font spec from FONT_NAME, and return it. If FONT_NAME
3094 could not be parsed by font_parse_name, return Qnil. */
3097 font_spec_from_name (Lisp_Object font_name
)
3099 Lisp_Object spec
= Ffont_spec (0, NULL
);
3101 CHECK_STRING (font_name
);
3102 if (font_parse_name ((char *) SDATA (font_name
), spec
) == -1)
3104 font_put_extra (spec
, QCname
, font_name
);
3105 font_put_extra (spec
, QCuser_spec
, font_name
);
3111 font_clear_prop (Lisp_Object
*attrs
, enum font_property_index prop
)
3113 Lisp_Object font
= attrs
[LFACE_FONT_INDEX
];
3118 if (! NILP (Ffont_get (font
, QCname
)))
3120 font
= Fcopy_font_spec (font
);
3121 font_put_extra (font
, QCname
, Qnil
);
3124 if (NILP (AREF (font
, prop
))
3125 && prop
!= FONT_FAMILY_INDEX
3126 && prop
!= FONT_FOUNDRY_INDEX
3127 && prop
!= FONT_WIDTH_INDEX
3128 && prop
!= FONT_SIZE_INDEX
)
3130 if (EQ (font
, attrs
[LFACE_FONT_INDEX
]))
3131 font
= Fcopy_font_spec (font
);
3132 ASET (font
, prop
, Qnil
);
3133 if (prop
== FONT_FAMILY_INDEX
|| prop
== FONT_FOUNDRY_INDEX
)
3135 if (prop
== FONT_FAMILY_INDEX
)
3137 ASET (font
, FONT_FOUNDRY_INDEX
, Qnil
);
3138 /* If we are setting the font family, we must also clear
3139 FONT_WIDTH_INDEX to avoid rejecting families that lack
3140 support for some widths. */
3141 ASET (font
, FONT_WIDTH_INDEX
, Qnil
);
3143 ASET (font
, FONT_ADSTYLE_INDEX
, Qnil
);
3144 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
3145 ASET (font
, FONT_SIZE_INDEX
, Qnil
);
3146 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3147 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3148 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3150 else if (prop
== FONT_SIZE_INDEX
)
3152 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3153 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3154 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3156 else if (prop
== FONT_WIDTH_INDEX
)
3157 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3158 attrs
[LFACE_FONT_INDEX
] = font
;
3162 font_update_lface (FRAME_PTR f
, Lisp_Object
*attrs
)
3166 spec
= attrs
[LFACE_FONT_INDEX
];
3167 if (! FONT_SPEC_P (spec
))
3170 if (! NILP (AREF (spec
, FONT_FOUNDRY_INDEX
)))
3171 attrs
[LFACE_FOUNDRY_INDEX
] = SYMBOL_NAME (AREF (spec
, FONT_FOUNDRY_INDEX
));
3172 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3173 attrs
[LFACE_FAMILY_INDEX
] = SYMBOL_NAME (AREF (spec
, FONT_FAMILY_INDEX
));
3174 if (! NILP (AREF (spec
, FONT_WEIGHT_INDEX
)))
3175 attrs
[LFACE_WEIGHT_INDEX
] = FONT_WEIGHT_FOR_FACE (spec
);
3176 if (! NILP (AREF (spec
, FONT_SLANT_INDEX
)))
3177 attrs
[LFACE_SLANT_INDEX
] = FONT_SLANT_FOR_FACE (spec
);
3178 if (! NILP (AREF (spec
, FONT_WIDTH_INDEX
)))
3179 attrs
[LFACE_SWIDTH_INDEX
] = FONT_WIDTH_FOR_FACE (spec
);
3180 if (! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
3184 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
3189 val
= Ffont_get (spec
, QCdpi
);
3192 point
= PIXEL_TO_POINT (XINT (AREF (spec
, FONT_SIZE_INDEX
)) * 10,
3194 attrs
[LFACE_HEIGHT_INDEX
] = make_number (point
);
3196 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
3198 point
= XFLOAT_DATA (AREF (spec
, FONT_SIZE_INDEX
)) * 10;
3199 attrs
[LFACE_HEIGHT_INDEX
] = make_number (point
);
3205 /* Selecte a font from ENTITIES (list of font-entity vectors) that
3206 supports C and matches best with ATTRS and PIXEL_SIZE. */
3209 font_select_entity (Lisp_Object frame
, Lisp_Object entities
, Lisp_Object
*attrs
, int pixel_size
, int c
)
3211 Lisp_Object font_entity
;
3214 FRAME_PTR f
= XFRAME (frame
);
3216 if (NILP (XCDR (entities
))
3217 && ASIZE (XCAR (entities
)) == 1)
3219 font_entity
= AREF (XCAR (entities
), 0);
3221 || (result
= font_has_char (f
, font_entity
, c
)) > 0)
3226 /* Sort fonts by properties specified in ATTRS. */
3227 prefer
= scratch_font_prefer
;
3229 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
3230 ASET (prefer
, i
, Qnil
);
3231 if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3233 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3235 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
3236 ASET (prefer
, i
, AREF (face_font
, i
));
3238 if (NILP (AREF (prefer
, FONT_WEIGHT_INDEX
)))
3239 FONT_SET_STYLE (prefer
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
3240 if (NILP (AREF (prefer
, FONT_SLANT_INDEX
)))
3241 FONT_SET_STYLE (prefer
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
3242 if (NILP (AREF (prefer
, FONT_WIDTH_INDEX
)))
3243 FONT_SET_STYLE (prefer
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
3244 ASET (prefer
, FONT_SIZE_INDEX
, make_number (pixel_size
));
3246 return font_sort_entities (entities
, prefer
, frame
, c
);
3249 /* Return a font-entity satisfying SPEC and best matching with face's
3250 font related attributes in ATTRS. C, if not negative, is a
3251 character that the entity must support. */
3254 font_find_for_lface (FRAME_PTR f
, Lisp_Object
*attrs
, Lisp_Object spec
, int c
)
3257 Lisp_Object frame
, entities
, val
;
3258 Lisp_Object size
, foundry
[3], *family
, registry
[3], adstyle
[3];
3262 registry
[0] = AREF (spec
, FONT_REGISTRY_INDEX
);
3263 if (NILP (registry
[0]))
3265 registry
[0] = DEFAULT_ENCODING
;
3266 registry
[1] = Qascii_0
;
3267 registry
[2] = null_vector
;
3270 registry
[1] = null_vector
;
3272 if (c
>= 0 && ! NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
3274 struct charset
*encoding
, *repertory
;
3276 if (font_registry_charsets (AREF (spec
, FONT_REGISTRY_INDEX
),
3277 &encoding
, &repertory
) < 0)
3280 && ENCODE_CHAR (repertory
, c
) == CHARSET_INVALID_CODE (repertory
))
3282 else if (c
> encoding
->max_char
)
3286 work
= Fcopy_font_spec (spec
);
3287 ASET (work
, FONT_TYPE_INDEX
, AREF (spec
, FONT_TYPE_INDEX
));
3288 XSETFRAME (frame
, f
);
3289 size
= AREF (spec
, FONT_SIZE_INDEX
);
3290 pixel_size
= font_pixel_size (f
, spec
);
3291 if (pixel_size
== 0)
3293 double pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3295 pixel_size
= POINT_TO_PIXEL (pt
/ 10, f
->resy
);
3297 ASET (work
, FONT_SIZE_INDEX
, Qnil
);
3298 foundry
[0] = AREF (work
, FONT_FOUNDRY_INDEX
);
3299 if (! NILP (foundry
[0]))
3300 foundry
[1] = null_vector
;
3301 else if (STRINGP (attrs
[LFACE_FOUNDRY_INDEX
]))
3303 val
= attrs
[LFACE_FOUNDRY_INDEX
];
3304 foundry
[0] = font_intern_prop ((char *) SDATA (val
), SBYTES (val
), 1);
3306 foundry
[2] = null_vector
;
3309 foundry
[0] = Qnil
, foundry
[1] = null_vector
;
3311 adstyle
[0] = AREF (work
, FONT_ADSTYLE_INDEX
);
3312 if (! NILP (adstyle
[0]))
3313 adstyle
[1] = null_vector
;
3314 else if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3316 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3318 if (! NILP (AREF (face_font
, FONT_ADSTYLE_INDEX
)))
3320 adstyle
[0] = AREF (face_font
, FONT_ADSTYLE_INDEX
);
3322 adstyle
[2] = null_vector
;
3325 adstyle
[0] = Qnil
, adstyle
[1] = null_vector
;
3328 adstyle
[0] = Qnil
, adstyle
[1] = null_vector
;
3331 val
= AREF (work
, FONT_FAMILY_INDEX
);
3332 if (NILP (val
) && STRINGP (attrs
[LFACE_FAMILY_INDEX
]))
3334 val
= attrs
[LFACE_FAMILY_INDEX
];
3335 val
= font_intern_prop ((char *) SDATA (val
), SBYTES (val
), 1);
3339 family
= alloca ((sizeof family
[0]) * 2);
3341 family
[1] = null_vector
; /* terminator. */
3346 = Fassoc_string (val
, Vface_alternative_font_family_alist
,
3347 /* Font family names are case-sensitive under NS. */
3355 if (! NILP (alters
))
3357 family
= alloca ((sizeof family
[0]) * (XINT (Flength (alters
)) + 2));
3358 for (i
= 0; CONSP (alters
); i
++, alters
= XCDR (alters
))
3359 family
[i
] = XCAR (alters
);
3360 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3362 family
[i
] = null_vector
;
3366 family
= alloca ((sizeof family
[0]) * 3);
3369 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3371 family
[i
] = null_vector
;
3375 for (i
= 0; SYMBOLP (family
[i
]); i
++)
3377 ASET (work
, FONT_FAMILY_INDEX
, family
[i
]);
3378 for (j
= 0; SYMBOLP (foundry
[j
]); j
++)
3380 ASET (work
, FONT_FOUNDRY_INDEX
, foundry
[j
]);
3381 for (k
= 0; SYMBOLP (registry
[k
]); k
++)
3383 ASET (work
, FONT_REGISTRY_INDEX
, registry
[k
]);
3384 for (l
= 0; SYMBOLP (adstyle
[l
]); l
++)
3386 ASET (work
, FONT_ADSTYLE_INDEX
, adstyle
[l
]);
3387 entities
= font_list_entities (frame
, work
);
3388 if (! NILP (entities
))
3390 val
= font_select_entity (frame
, entities
,
3391 attrs
, pixel_size
, c
);
3404 font_open_for_lface (FRAME_PTR f
, Lisp_Object entity
, Lisp_Object
*attrs
, Lisp_Object spec
)
3408 if (INTEGERP (AREF (entity
, FONT_SIZE_INDEX
))
3409 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
3410 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
3411 else if (FONT_SPEC_P (spec
) && ! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
3412 size
= font_pixel_size (f
, spec
);
3416 if (INTEGERP (attrs
[LFACE_HEIGHT_INDEX
]))
3417 pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3420 struct face
*def
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
3421 Lisp_Object height
= def
->lface
[LFACE_HEIGHT_INDEX
];
3422 if (INTEGERP (height
))
3425 abort(); /* We should never end up here. */
3429 size
= POINT_TO_PIXEL (pt
, f
->resy
);
3433 Lisp_Object ffsize
= get_frame_param(f
, Qfontsize
);
3434 size
= NUMBERP (ffsize
) ? POINT_TO_PIXEL (XINT (ffsize
), f
->resy
) : 0;
3438 return font_open_entity (f
, entity
, size
);
3442 /* Find a font satisfying SPEC and best matching with face's
3443 attributes in ATTRS on FRAME, and return the opened
3447 font_load_for_lface (FRAME_PTR f
, Lisp_Object
*attrs
, Lisp_Object spec
)
3449 Lisp_Object entity
, name
;
3451 entity
= font_find_for_lface (f
, attrs
, spec
, -1);
3454 /* No font is listed for SPEC, but each font-backend may have
3455 the different criteria about "font matching". So, try
3457 entity
= font_matching_entity (f
, attrs
, spec
);
3461 /* Don't loose the original name that was put in initially. We need
3462 it to re-apply the font when font parameters (like hinting or dpi) have
3464 entity
= font_open_for_lface (f
, entity
, attrs
, spec
);
3467 name
= Ffont_get (spec
, QCuser_spec
);
3468 if (STRINGP (name
)) font_put_extra (entity
, QCuser_spec
, name
);
3474 /* Make FACE on frame F ready to use the font opened for FACE. */
3477 font_prepare_for_face (FRAME_PTR f
, struct face
*face
)
3479 if (face
->font
->driver
->prepare_face
)
3480 face
->font
->driver
->prepare_face (f
, face
);
3484 /* Make FACE on frame F stop using the font opened for FACE. */
3487 font_done_for_face (FRAME_PTR f
, struct face
*face
)
3489 if (face
->font
->driver
->done_face
)
3490 face
->font
->driver
->done_face (f
, face
);
3495 /* Open a font matching with font-spec SPEC on frame F. If no proper
3496 font is found, return Qnil. */
3499 font_open_by_spec (FRAME_PTR f
, Lisp_Object spec
)
3501 Lisp_Object attrs
[LFACE_VECTOR_SIZE
];
3503 /* We set up the default font-related attributes of a face to prefer
3505 attrs
[LFACE_FAMILY_INDEX
] = attrs
[LFACE_FOUNDRY_INDEX
] = Qnil
;
3506 attrs
[LFACE_SWIDTH_INDEX
] = attrs
[LFACE_WEIGHT_INDEX
]
3507 = attrs
[LFACE_SLANT_INDEX
] = Qnormal
;
3509 attrs
[LFACE_HEIGHT_INDEX
] = make_number (120);
3511 attrs
[LFACE_HEIGHT_INDEX
] = make_number (0);
3513 attrs
[LFACE_FONT_INDEX
] = Qnil
;
3515 return font_load_for_lface (f
, attrs
, spec
);
3519 /* Open a font matching with NAME on frame F. If no proper font is
3520 found, return Qnil. */
3523 font_open_by_name (FRAME_PTR f
, char *name
)
3525 Lisp_Object args
[2];
3526 Lisp_Object spec
, ret
;
3529 args
[1] = make_unibyte_string (name
, strlen (name
));
3530 spec
= Ffont_spec (2, args
);
3531 ret
= font_open_by_spec (f
, spec
);
3532 /* Do not loose name originally put in. */
3534 font_put_extra (ret
, QCuser_spec
, args
[1]);
3540 /* Register font-driver DRIVER. This function is used in two ways.
3542 The first is with frame F non-NULL. In this case, make DRIVER
3543 available (but not yet activated) on F. All frame creaters
3544 (e.g. Fx_create_frame) must call this function at least once with
3545 an available font-driver.
3547 The second is with frame F NULL. In this case, DRIVER is globally
3548 registered in the variable `font_driver_list'. All font-driver
3549 implementations must call this function in its syms_of_XXXX
3550 (e.g. syms_of_xfont). */
3553 register_font_driver (struct font_driver
*driver
, FRAME_PTR f
)
3555 struct font_driver_list
*root
= f
? f
->font_driver_list
: font_driver_list
;
3556 struct font_driver_list
*prev
, *list
;
3558 if (f
&& ! driver
->draw
)
3559 error ("Unusable font driver for a frame: %s",
3560 SDATA (SYMBOL_NAME (driver
->type
)));
3562 for (prev
= NULL
, list
= root
; list
; prev
= list
, list
= list
->next
)
3563 if (EQ (list
->driver
->type
, driver
->type
))
3564 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver
->type
)));
3566 list
= xmalloc (sizeof (struct font_driver_list
));
3568 list
->driver
= driver
;
3573 f
->font_driver_list
= list
;
3575 font_driver_list
= list
;
3581 free_font_driver_list (FRAME_PTR f
)
3583 struct font_driver_list
*list
, *next
;
3585 for (list
= f
->font_driver_list
; list
; list
= next
)
3590 f
->font_driver_list
= NULL
;
3594 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3595 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3596 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3598 A caller must free all realized faces if any in advance. The
3599 return value is a list of font backends actually made used on
3603 font_update_drivers (FRAME_PTR f
, Lisp_Object new_drivers
)
3605 Lisp_Object active_drivers
= Qnil
;
3606 struct font_driver
*driver
;
3607 struct font_driver_list
*list
;
3609 /* At first, turn off non-requested drivers, and turn on requested
3611 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3613 driver
= list
->driver
;
3614 if ((EQ (new_drivers
, Qt
) || ! NILP (Fmemq (driver
->type
, new_drivers
)))
3619 if (driver
->end_for_frame
)
3620 driver
->end_for_frame (f
);
3621 font_finish_cache (f
, driver
);
3626 if (! driver
->start_for_frame
3627 || driver
->start_for_frame (f
) == 0)
3629 font_prepare_cache (f
, driver
);
3636 if (NILP (new_drivers
))
3639 if (! EQ (new_drivers
, Qt
))
3641 /* Re-order the driver list according to new_drivers. */
3642 struct font_driver_list
**list_table
, **next
;
3646 list_table
= alloca (sizeof list_table
[0] * (num_font_drivers
+ 1));
3647 for (i
= 0, tail
= new_drivers
; ! NILP (tail
); tail
= XCDR (tail
))
3649 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3650 if (list
->on
&& EQ (list
->driver
->type
, XCAR (tail
)))
3653 list_table
[i
++] = list
;
3655 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3657 list_table
[i
++] = list
;
3658 list_table
[i
] = NULL
;
3660 next
= &f
->font_driver_list
;
3661 for (i
= 0; list_table
[i
]; i
++)
3663 *next
= list_table
[i
];
3664 next
= &(*next
)->next
;
3668 if (! f
->font_driver_list
->on
)
3669 { /* None of the drivers is enabled: enable them all.
3670 Happens if you set the list of drivers to (xft x) in your .emacs
3671 and then use it under w32 or ns. */
3672 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3674 struct font_driver
*driver
= list
->driver
;
3675 eassert (! list
->on
);
3676 if (! driver
->start_for_frame
3677 || driver
->start_for_frame (f
) == 0)
3679 font_prepare_cache (f
, driver
);
3686 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3688 active_drivers
= nconc2 (active_drivers
,
3689 Fcons (list
->driver
->type
, Qnil
));
3690 return active_drivers
;
3694 font_put_frame_data (FRAME_PTR f
, struct font_driver
*driver
, void *data
)
3696 struct font_data_list
*list
, *prev
;
3698 for (prev
= NULL
, list
= f
->font_data_list
; list
;
3699 prev
= list
, list
= list
->next
)
3700 if (list
->driver
== driver
)
3707 prev
->next
= list
->next
;
3709 f
->font_data_list
= list
->next
;
3717 list
= xmalloc (sizeof (struct font_data_list
));
3718 list
->driver
= driver
;
3719 list
->next
= f
->font_data_list
;
3720 f
->font_data_list
= list
;
3728 font_get_frame_data (FRAME_PTR f
, struct font_driver
*driver
)
3730 struct font_data_list
*list
;
3732 for (list
= f
->font_data_list
; list
; list
= list
->next
)
3733 if (list
->driver
== driver
)
3741 /* Return the font used to draw character C by FACE at buffer position
3742 POS in window W. If STRING is non-nil, it is a string containing C
3743 at index POS. If C is negative, get C from the current buffer or
3747 font_at (int c
, EMACS_INT pos
, struct face
*face
, struct window
*w
, Lisp_Object string
)
3751 Lisp_Object font_object
;
3753 multibyte
= (NILP (string
)
3754 ? ! NILP (current_buffer
->enable_multibyte_characters
)
3755 : STRING_MULTIBYTE (string
));
3762 EMACS_INT pos_byte
= CHAR_TO_BYTE (pos
);
3764 c
= FETCH_CHAR (pos_byte
);
3767 c
= FETCH_BYTE (pos
);
3773 multibyte
= STRING_MULTIBYTE (string
);
3776 EMACS_INT pos_byte
= string_char_to_byte (string
, pos
);
3778 str
= SDATA (string
) + pos_byte
;
3779 c
= STRING_CHAR (str
);
3782 c
= SDATA (string
)[pos
];
3786 f
= XFRAME (w
->frame
);
3787 if (! FRAME_WINDOW_P (f
))
3794 if (STRINGP (string
))
3795 face_id
= face_at_string_position (w
, string
, pos
, 0, -1, -1, &endptr
,
3796 DEFAULT_FACE_ID
, 0);
3798 face_id
= face_at_buffer_position (w
, pos
, -1, -1, &endptr
,
3800 face
= FACE_FROM_ID (f
, face_id
);
3804 int face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3805 face
= FACE_FROM_ID (f
, face_id
);
3810 XSETFONT (font_object
, face
->font
);
3815 #ifdef HAVE_WINDOW_SYSTEM
3817 /* Check how many characters after POS (at most to *LIMIT) can be
3818 displayed by the same font on the window W. FACE, if non-NULL, is
3819 the face selected for the character at POS. If STRING is not nil,
3820 it is the string to check instead of the current buffer. In that
3821 case, FACE must be not NULL.
3823 The return value is the font-object for the character at POS.
3824 *LIMIT is set to the position where that font can't be used.
3826 It is assured that the current buffer (or STRING) is multibyte. */
3829 font_range (EMACS_INT pos
, EMACS_INT
*limit
, struct window
*w
, struct face
*face
, Lisp_Object string
)
3831 EMACS_INT pos_byte
, ignore
;
3833 Lisp_Object font_object
= Qnil
;
3837 pos_byte
= CHAR_TO_BYTE (pos
);
3842 face_id
= face_at_buffer_position (w
, pos
, 0, 0, &ignore
,
3844 face
= FACE_FROM_ID (XFRAME (w
->frame
), face_id
);
3850 pos_byte
= string_char_to_byte (string
, pos
);
3853 while (pos
< *limit
)
3855 Lisp_Object category
;
3858 FETCH_CHAR_ADVANCE_NO_CHECK (c
, pos
, pos_byte
);
3860 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c
, string
, pos
, pos_byte
);
3861 category
= CHAR_TABLE_REF (Vunicode_category_table
, c
);
3862 if (EQ (category
, QCf
)
3863 || CHAR_VARIATION_SELECTOR_P (c
))
3865 if (NILP (font_object
))
3867 font_object
= font_for_char (face
, c
, pos
- 1, string
);
3868 if (NILP (font_object
))
3872 if (font_encode_char (font_object
, c
) == FONT_INVALID_CODE
)
3882 DEFUN ("fontp", Ffontp
, Sfontp
, 1, 2, 0,
3883 doc
: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3884 Return nil otherwise.
3885 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3886 which kind of font it is. It must be one of `font-spec', `font-entity',
3888 (Lisp_Object object
, Lisp_Object extra_type
)
3890 if (NILP (extra_type
))
3891 return (FONTP (object
) ? Qt
: Qnil
);
3892 if (EQ (extra_type
, Qfont_spec
))
3893 return (FONT_SPEC_P (object
) ? Qt
: Qnil
);
3894 if (EQ (extra_type
, Qfont_entity
))
3895 return (FONT_ENTITY_P (object
) ? Qt
: Qnil
);
3896 if (EQ (extra_type
, Qfont_object
))
3897 return (FONT_OBJECT_P (object
) ? Qt
: Qnil
);
3898 wrong_type_argument (intern ("font-extra-type"), extra_type
);
3901 DEFUN ("font-spec", Ffont_spec
, Sfont_spec
, 0, MANY
, 0,
3902 doc
: /* Return a newly created font-spec with arguments as properties.
3904 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3905 valid font property name listed below:
3907 `:family', `:weight', `:slant', `:width'
3909 They are the same as face attributes of the same name. See
3910 `set-face-attribute'.
3914 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3918 VALUE must be a string or a symbol specifying the additional
3919 typographic style information of a font, e.g. ``sans''.
3923 VALUE must be a string or a symbol specifying the charset registry and
3924 encoding of a font, e.g. ``iso8859-1''.
3928 VALUE must be a non-negative integer or a floating point number
3929 specifying the font size. It specifies the font size in pixels (if
3930 VALUE is an integer), or in points (if VALUE is a float).
3934 VALUE must be a string of XLFD-style or fontconfig-style font name.
3938 VALUE must be a symbol representing a script that the font must
3939 support. It may be a symbol representing a subgroup of a script
3940 listed in the variable `script-representative-chars'.
3944 VALUE must be a symbol of two-letter ISO-639 language names,
3949 VALUE must be a list (SCRIPT-TAG LANGSYS-TAG GSUB [ GPOS ]) to specify
3950 required OpenType features.
3952 SCRIPT-TAG: OpenType script tag symbol (e.g. `deva').
3953 LANGSYS-TAG: OpenType language system tag symbol,
3954 or nil for the default language system.
3955 GSUB: List of OpenType GSUB feature tag symbols, or nil if none required.
3956 GPOS: List of OpenType GPOS feature tag symbols, or nil if none required.
3958 GSUB and GPOS may contain `nil' element. In such a case, the font
3959 must not have any of the remaining elements.
3961 For instance, if the VALUE is `(thai nil nil (mark))', the font must
3962 be an OpenType font, and whose GPOS table of `thai' script's default
3963 language system must contain `mark' feature.
3965 usage: (font-spec ARGS...) */)
3966 (int nargs
, Lisp_Object
*args
)
3968 Lisp_Object spec
= font_make_spec ();
3971 for (i
= 0; i
< nargs
; i
+= 2)
3973 Lisp_Object key
= args
[i
], val
;
3977 error ("No value for key `%s'", SDATA (SYMBOL_NAME (key
)));
3980 if (EQ (key
, QCname
))
3983 font_parse_name ((char *) SDATA (val
), spec
);
3984 font_put_extra (spec
, key
, val
);
3988 int idx
= get_font_prop_index (key
);
3992 val
= font_prop_validate (idx
, Qnil
, val
);
3993 if (idx
< FONT_EXTRA_INDEX
)
3994 ASET (spec
, idx
, val
);
3996 font_put_extra (spec
, key
, val
);
3999 font_put_extra (spec
, key
, font_prop_validate (0, key
, val
));
4005 DEFUN ("copy-font-spec", Fcopy_font_spec
, Scopy_font_spec
, 1, 1, 0,
4006 doc
: /* Return a copy of FONT as a font-spec. */)
4009 Lisp_Object new_spec
, tail
, prev
, extra
;
4013 new_spec
= font_make_spec ();
4014 for (i
= 1; i
< FONT_EXTRA_INDEX
; i
++)
4015 ASET (new_spec
, i
, AREF (font
, i
));
4016 extra
= Fcopy_alist (AREF (font
, FONT_EXTRA_INDEX
));
4017 /* We must remove :font-entity property. */
4018 for (prev
= Qnil
, tail
= extra
; CONSP (tail
); prev
= tail
, tail
= XCDR (tail
))
4019 if (EQ (XCAR (XCAR (tail
)), QCfont_entity
))
4022 extra
= XCDR (extra
);
4024 XSETCDR (prev
, XCDR (tail
));
4027 ASET (new_spec
, FONT_EXTRA_INDEX
, extra
);
4031 DEFUN ("merge-font-spec", Fmerge_font_spec
, Smerge_font_spec
, 2, 2, 0,
4032 doc
: /* Merge font-specs FROM and TO, and return a new font-spec.
4033 Every specified properties in FROM override the corresponding
4034 properties in TO. */)
4035 (Lisp_Object from
, Lisp_Object to
)
4037 Lisp_Object extra
, tail
;
4042 to
= Fcopy_font_spec (to
);
4043 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
4044 ASET (to
, i
, AREF (from
, i
));
4045 extra
= AREF (to
, FONT_EXTRA_INDEX
);
4046 for (tail
= AREF (from
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
4047 if (! EQ (XCAR (XCAR (tail
)), Qfont_entity
))
4049 Lisp_Object slot
= assq_no_quit (XCAR (XCAR (tail
)), extra
);
4052 XSETCDR (slot
, XCDR (XCAR (tail
)));
4054 extra
= Fcons (Fcons (XCAR (XCAR (tail
)), XCDR (XCAR (tail
))), extra
);
4056 ASET (to
, FONT_EXTRA_INDEX
, extra
);
4060 DEFUN ("font-get", Ffont_get
, Sfont_get
, 2, 2, 0,
4061 doc
: /* Return the value of FONT's property KEY.
4062 FONT is a font-spec, a font-entity, or a font-object.
4063 KEY is any symbol, but these are reserved for specific meanings:
4064 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
4065 :size, :name, :script, :otf
4066 See the documentation of `font-spec' for their meanings.
4067 In addition, if FONT is a font-entity or a font-object, values of
4068 :script and :otf are different from those of a font-spec as below:
4070 The value of :script may be a list of scripts that are supported by the font.
4072 The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
4073 representing the OpenType features supported by the font by this form:
4074 ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4075 SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
4077 (Lisp_Object font
, Lisp_Object key
)
4085 idx
= get_font_prop_index (key
);
4086 if (idx
>= FONT_WEIGHT_INDEX
&& idx
<= FONT_WIDTH_INDEX
)
4087 return font_style_symbolic (font
, idx
, 0);
4088 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
4089 return AREF (font
, idx
);
4090 val
= Fassq (key
, AREF (font
, FONT_EXTRA_INDEX
));
4091 if (NILP (val
) && EQ (key
, QCotf
) && FONT_OBJECT_P (font
))
4093 struct font
*fontp
= XFONT_OBJECT (font
);
4095 if (fontp
->driver
->otf_capability
)
4096 val
= fontp
->driver
->otf_capability (fontp
);
4098 val
= Fcons (Qnil
, Qnil
);
4099 font_put_extra (font
, QCotf
, val
);
4106 #ifdef HAVE_WINDOW_SYSTEM
4108 DEFUN ("font-face-attributes", Ffont_face_attributes
, Sfont_face_attributes
, 1, 2, 0,
4109 doc
: /* Return a plist of face attributes generated by FONT.
4110 FONT is a font name, a font-spec, a font-entity, or a font-object.
4111 The return value is a list of the form
4113 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
4115 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
4116 compatible with `set-face-attribute'. Some of these key-attribute pairs
4117 may be omitted from the list if they are not specified by FONT.
4119 The optional argument FRAME specifies the frame that the face attributes
4120 are to be displayed on. If omitted, the selected frame is used. */)
4121 (Lisp_Object font
, Lisp_Object frame
)
4124 Lisp_Object plist
[10];
4129 frame
= selected_frame
;
4130 CHECK_LIVE_FRAME (frame
);
4135 int fontset
= fs_query_fontset (font
, 0);
4136 Lisp_Object name
= font
;
4138 font
= fontset_ascii (fontset
);
4139 font
= font_spec_from_name (name
);
4141 signal_error ("Invalid font name", name
);
4143 else if (! FONTP (font
))
4144 signal_error ("Invalid font object", font
);
4146 val
= AREF (font
, FONT_FAMILY_INDEX
);
4149 plist
[n
++] = QCfamily
;
4150 plist
[n
++] = SYMBOL_NAME (val
);
4153 val
= AREF (font
, FONT_SIZE_INDEX
);
4156 Lisp_Object font_dpi
= AREF (font
, FONT_DPI_INDEX
);
4157 int dpi
= INTEGERP (font_dpi
) ? XINT (font_dpi
) : f
->resy
;
4158 plist
[n
++] = QCheight
;
4159 plist
[n
++] = make_number (PIXEL_TO_POINT (XINT (val
) * 10, dpi
));
4161 else if (FLOATP (val
))
4163 plist
[n
++] = QCheight
;
4164 plist
[n
++] = make_number (10 * (int) XFLOAT_DATA (val
));
4167 val
= FONT_WEIGHT_FOR_FACE (font
);
4170 plist
[n
++] = QCweight
;
4174 val
= FONT_SLANT_FOR_FACE (font
);
4177 plist
[n
++] = QCslant
;
4181 val
= FONT_WIDTH_FOR_FACE (font
);
4184 plist
[n
++] = QCwidth
;
4188 return Flist (n
, plist
);
4193 DEFUN ("font-put", Ffont_put
, Sfont_put
, 3, 3, 0,
4194 doc
: /* Set one property of FONT: give property KEY value VAL.
4195 FONT is a font-spec, a font-entity, or a font-object.
4197 If FONT is a font-spec, KEY can be any symbol. But if KEY is the one
4198 accepted by the function `font-spec' (which see), VAL must be what
4199 allowed in `font-spec'.
4201 If FONT is a font-entity or a font-object, KEY must not be the one
4202 accepted by `font-spec'. */)
4203 (Lisp_Object font
, Lisp_Object prop
, Lisp_Object val
)
4207 idx
= get_font_prop_index (prop
);
4208 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
4210 CHECK_FONT_SPEC (font
);
4211 ASET (font
, idx
, font_prop_validate (idx
, Qnil
, val
));
4215 if (EQ (prop
, QCname
)
4216 || EQ (prop
, QCscript
)
4217 || EQ (prop
, QClang
)
4218 || EQ (prop
, QCotf
))
4219 CHECK_FONT_SPEC (font
);
4222 font_put_extra (font
, prop
, font_prop_validate (0, prop
, val
));
4227 DEFUN ("list-fonts", Flist_fonts
, Slist_fonts
, 1, 4, 0,
4228 doc
: /* List available fonts matching FONT-SPEC on the current frame.
4229 Optional 2nd argument FRAME specifies the target frame.
4230 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4231 Optional 4th argument PREFER, if non-nil, is a font-spec to
4232 control the order of the returned list. Fonts are sorted by
4233 how close they are to PREFER. */)
4234 (Lisp_Object font_spec
, Lisp_Object frame
, Lisp_Object num
, Lisp_Object prefer
)
4236 Lisp_Object vec
, list
;
4240 frame
= selected_frame
;
4241 CHECK_LIVE_FRAME (frame
);
4242 CHECK_FONT_SPEC (font_spec
);
4250 if (! NILP (prefer
))
4251 CHECK_FONT_SPEC (prefer
);
4253 list
= font_list_entities (frame
, font_spec
);
4256 if (NILP (XCDR (list
))
4257 && ASIZE (XCAR (list
)) == 1)
4258 return Fcons (AREF (XCAR (list
), 0), Qnil
);
4260 if (! NILP (prefer
))
4261 vec
= font_sort_entities (list
, prefer
, frame
, 0);
4263 vec
= font_vconcat_entity_vectors (list
);
4264 if (n
== 0 || n
>= ASIZE (vec
))
4266 Lisp_Object args
[2];
4270 list
= Fappend (2, args
);
4274 for (list
= Qnil
, n
--; n
>= 0; n
--)
4275 list
= Fcons (AREF (vec
, n
), list
);
4280 DEFUN ("font-family-list", Ffont_family_list
, Sfont_family_list
, 0, 1, 0,
4281 doc
: /* List available font families on the current frame.
4282 Optional argument FRAME, if non-nil, specifies the target frame. */)
4286 struct font_driver_list
*driver_list
;
4290 frame
= selected_frame
;
4291 CHECK_LIVE_FRAME (frame
);
4294 for (driver_list
= f
->font_driver_list
; driver_list
;
4295 driver_list
= driver_list
->next
)
4296 if (driver_list
->driver
->list_family
)
4298 Lisp_Object val
= driver_list
->driver
->list_family (frame
);
4299 Lisp_Object tail
= list
;
4301 for (; CONSP (val
); val
= XCDR (val
))
4302 if (NILP (Fmemq (XCAR (val
), tail
))
4303 && SYMBOLP (XCAR (val
)))
4304 list
= Fcons (SYMBOL_NAME (XCAR (val
)), list
);
4309 DEFUN ("find-font", Ffind_font
, Sfind_font
, 1, 2, 0,
4310 doc
: /* Return a font-entity matching with FONT-SPEC on the current frame.
4311 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4312 (Lisp_Object font_spec
, Lisp_Object frame
)
4314 Lisp_Object val
= Flist_fonts (font_spec
, frame
, make_number (1), Qnil
);
4321 DEFUN ("font-xlfd-name", Ffont_xlfd_name
, Sfont_xlfd_name
, 1, 2, 0,
4322 doc
: /* Return XLFD name of FONT.
4323 FONT is a font-spec, font-entity, or font-object.
4324 If the name is too long for XLFD (maximum 255 chars), return nil.
4325 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4326 the consecutive wildcards are folded to one. */)
4327 (Lisp_Object font
, Lisp_Object fold_wildcards
)
4334 if (FONT_OBJECT_P (font
))
4336 Lisp_Object font_name
= AREF (font
, FONT_NAME_INDEX
);
4338 if (STRINGP (font_name
)
4339 && SDATA (font_name
)[0] == '-')
4341 if (NILP (fold_wildcards
))
4343 strcpy (name
, (char *) SDATA (font_name
));
4346 pixel_size
= XFONT_OBJECT (font
)->pixel_size
;
4348 if (font_unparse_xlfd (font
, pixel_size
, name
, 256) < 0)
4351 if (! NILP (fold_wildcards
))
4353 char *p0
= name
, *p1
;
4355 while ((p1
= strstr (p0
, "-*-*")))
4357 strcpy (p1
, p1
+ 2);
4362 return build_string (name
);
4365 DEFUN ("clear-font-cache", Fclear_font_cache
, Sclear_font_cache
, 0, 0, 0,
4366 doc
: /* Clear font cache. */)
4369 Lisp_Object list
, frame
;
4371 FOR_EACH_FRAME (list
, frame
)
4373 FRAME_PTR f
= XFRAME (frame
);
4374 struct font_driver_list
*driver_list
= f
->font_driver_list
;
4376 for (; driver_list
; driver_list
= driver_list
->next
)
4377 if (driver_list
->on
)
4379 Lisp_Object cache
= driver_list
->driver
->get_cache (f
);
4380 Lisp_Object val
, tmp
;
4384 && ! EQ (XCAR (XCAR (val
)), driver_list
->driver
->type
))
4386 font_assert (! NILP (val
));
4387 tmp
= XCDR (XCAR (val
));
4388 if (XINT (XCAR (tmp
)) == 0)
4390 font_clear_cache (f
, XCAR (val
), driver_list
->driver
);
4391 XSETCDR (cache
, XCDR (val
));
4401 font_fill_lglyph_metrics (Lisp_Object glyph
, Lisp_Object font_object
)
4403 struct font
*font
= XFONT_OBJECT (font_object
);
4405 /* ecode used in LGLYPH_SET_CODE to avoid compiler warnings. */
4406 EMACS_INT ecode
= font
->driver
->encode_char (font
, LGLYPH_CHAR (glyph
));
4407 struct font_metrics metrics
;
4409 LGLYPH_SET_CODE (glyph
, ecode
);
4411 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4412 LGLYPH_SET_LBEARING (glyph
, metrics
.lbearing
);
4413 LGLYPH_SET_RBEARING (glyph
, metrics
.rbearing
);
4414 LGLYPH_SET_WIDTH (glyph
, metrics
.width
);
4415 LGLYPH_SET_ASCENT (glyph
, metrics
.ascent
);
4416 LGLYPH_SET_DESCENT (glyph
, metrics
.descent
);
4420 DEFUN ("font-shape-gstring", Ffont_shape_gstring
, Sfont_shape_gstring
, 1, 1, 0,
4421 doc
: /* Shape the glyph-string GSTRING.
4422 Shaping means substituting glyphs and/or adjusting positions of glyphs
4423 to get the correct visual image of character sequences set in the
4424 header of the glyph-string.
4426 If the shaping was successful, the value is GSTRING itself or a newly
4427 created glyph-string. Otherwise, the value is nil. */)
4428 (Lisp_Object gstring
)
4431 Lisp_Object font_object
, n
, glyph
;
4434 if (! composition_gstring_p (gstring
))
4435 signal_error ("Invalid glyph-string: ", gstring
);
4436 if (! NILP (LGSTRING_ID (gstring
)))
4438 font_object
= LGSTRING_FONT (gstring
);
4439 CHECK_FONT_OBJECT (font_object
);
4440 font
= XFONT_OBJECT (font_object
);
4441 if (! font
->driver
->shape
)
4444 /* Try at most three times with larger gstring each time. */
4445 for (i
= 0; i
< 3; i
++)
4447 n
= font
->driver
->shape (gstring
);
4450 gstring
= larger_vector (gstring
,
4451 ASIZE (gstring
) + LGSTRING_GLYPH_LEN (gstring
),
4454 if (i
== 3 || XINT (n
) == 0)
4456 if (XINT (n
) < LGSTRING_GLYPH_LEN (gstring
))
4457 LGSTRING_SET_GLYPH (gstring
, XINT (n
), Qnil
);
4459 glyph
= LGSTRING_GLYPH (gstring
, 0);
4460 from
= LGLYPH_FROM (glyph
);
4461 to
= LGLYPH_TO (glyph
);
4462 for (i
= 1, j
= 0; i
< LGSTRING_GLYPH_LEN (gstring
); i
++)
4464 Lisp_Object
this = LGSTRING_GLYPH (gstring
, i
);
4468 if (NILP (LGLYPH_ADJUSTMENT (this)))
4473 glyph
= LGSTRING_GLYPH (gstring
, j
);
4474 LGLYPH_SET_FROM (glyph
, from
);
4475 LGLYPH_SET_TO (glyph
, to
);
4477 from
= LGLYPH_FROM (this);
4478 to
= LGLYPH_TO (this);
4483 if (from
> LGLYPH_FROM (this))
4484 from
= LGLYPH_FROM (this);
4485 if (to
< LGLYPH_TO (this))
4486 to
= LGLYPH_TO (this);
4492 glyph
= LGSTRING_GLYPH (gstring
, j
);
4493 LGLYPH_SET_FROM (glyph
, from
);
4494 LGLYPH_SET_TO (glyph
, to
);
4496 return composition_gstring_put_cache (gstring
, XINT (n
));
4499 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs
, Sfont_variation_glyphs
,
4501 doc
: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4502 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4504 VARIATION-SELECTOR is a chracter code of variation selection
4505 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4506 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4507 (Lisp_Object font_object
, Lisp_Object character
)
4509 unsigned variations
[256];
4514 CHECK_FONT_OBJECT (font_object
);
4515 CHECK_CHARACTER (character
);
4516 font
= XFONT_OBJECT (font_object
);
4517 if (! font
->driver
->get_variation_glyphs
)
4519 n
= font
->driver
->get_variation_glyphs (font
, XINT (character
), variations
);
4523 for (i
= 0; i
< 255; i
++)
4527 int vs
= (i
< 16 ? 0xFE00 + i
: 0xE0100 + (i
- 16));
4528 /* Stops GCC whining about limited range of data type. */
4529 EMACS_INT var
= variations
[i
];
4531 if (var
> MOST_POSITIVE_FIXNUM
)
4532 code
= Fcons (make_number ((variations
[i
]) >> 16),
4533 make_number ((variations
[i
]) & 0xFFFF));
4535 code
= make_number (variations
[i
]);
4536 val
= Fcons (Fcons (make_number (vs
), code
), val
);
4543 DEFUN ("font-drive-otf", Ffont_drive_otf
, Sfont_drive_otf
, 6, 6, 0,
4544 doc
: /* Apply OpenType features on glyph-string GSTRING-IN.
4545 OTF-FEATURES specifies which features to apply in this format:
4546 (SCRIPT LANGSYS GSUB GPOS)
4548 SCRIPT is a symbol specifying a script tag of OpenType,
4549 LANGSYS is a symbol specifying a langsys tag of OpenType,
4550 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4552 If LANGYS is nil, the default langsys is selected.
4554 The features are applied in the order they appear in the list. The
4555 symbol `*' means to apply all available features not present in this
4556 list, and the remaining features are ignored. For instance, (vatu
4557 pstf * haln) is to apply vatu and pstf in this order, then to apply
4558 all available features other than vatu, pstf, and haln.
4560 The features are applied to the glyphs in the range FROM and TO of
4561 the glyph-string GSTRING-IN.
4563 If some feature is actually applicable, the resulting glyphs are
4564 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4565 this case, the value is the number of produced glyphs.
4567 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4570 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4571 produced in GSTRING-OUT, and the value is nil.
4573 See the documentation of `font-make-gstring' for the format of
4575 (Lisp_Object otf_features
, Lisp_Object gstring_in
, Lisp_Object from
, Lisp_Object to
, Lisp_Object gstring_out
, Lisp_Object index
)
4577 Lisp_Object font_object
= LGSTRING_FONT (gstring_in
);
4582 check_otf_features (otf_features
);
4583 CHECK_FONT_OBJECT (font_object
);
4584 font
= XFONT_OBJECT (font_object
);
4585 if (! font
->driver
->otf_drive
)
4586 error ("Font backend %s can't drive OpenType GSUB table",
4587 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4588 CHECK_CONS (otf_features
);
4589 CHECK_SYMBOL (XCAR (otf_features
));
4590 val
= XCDR (otf_features
);
4591 CHECK_SYMBOL (XCAR (val
));
4592 val
= XCDR (otf_features
);
4595 len
= check_gstring (gstring_in
);
4596 CHECK_VECTOR (gstring_out
);
4597 CHECK_NATNUM (from
);
4599 CHECK_NATNUM (index
);
4601 if (XINT (from
) >= XINT (to
) || XINT (to
) > len
)
4602 args_out_of_range_3 (from
, to
, make_number (len
));
4603 if (XINT (index
) >= ASIZE (gstring_out
))
4604 args_out_of_range (index
, make_number (ASIZE (gstring_out
)));
4605 num
= font
->driver
->otf_drive (font
, otf_features
,
4606 gstring_in
, XINT (from
), XINT (to
),
4607 gstring_out
, XINT (index
), 0);
4610 return make_number (num
);
4613 DEFUN ("font-otf-alternates", Ffont_otf_alternates
, Sfont_otf_alternates
,
4615 doc
: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4616 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4618 (SCRIPT LANGSYS FEATURE ...)
4619 See the documentation of `font-drive-otf' for more detail.
4621 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4622 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4623 character code corresponding to the glyph or nil if there's no
4624 corresponding character. */)
4625 (Lisp_Object font_object
, Lisp_Object character
, Lisp_Object otf_features
)
4628 Lisp_Object gstring_in
, gstring_out
, g
;
4629 Lisp_Object alternates
;
4632 CHECK_FONT_GET_OBJECT (font_object
, font
);
4633 if (! font
->driver
->otf_drive
)
4634 error ("Font backend %s can't drive OpenType GSUB table",
4635 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4636 CHECK_CHARACTER (character
);
4637 CHECK_CONS (otf_features
);
4639 gstring_in
= Ffont_make_gstring (font_object
, make_number (1));
4640 g
= LGSTRING_GLYPH (gstring_in
, 0);
4641 LGLYPH_SET_CHAR (g
, XINT (character
));
4642 gstring_out
= Ffont_make_gstring (font_object
, make_number (10));
4643 while ((num
= font
->driver
->otf_drive (font
, otf_features
, gstring_in
, 0, 1,
4644 gstring_out
, 0, 1)) < 0)
4645 gstring_out
= Ffont_make_gstring (font_object
,
4646 make_number (ASIZE (gstring_out
) * 2));
4648 for (i
= 0; i
< num
; i
++)
4650 Lisp_Object g
= LGSTRING_GLYPH (gstring_out
, i
);
4651 int c
= LGLYPH_CHAR (g
);
4652 unsigned code
= LGLYPH_CODE (g
);
4654 alternates
= Fcons (Fcons (make_number (code
),
4655 c
> 0 ? make_number (c
) : Qnil
),
4658 return Fnreverse (alternates
);
4664 DEFUN ("open-font", Fopen_font
, Sopen_font
, 1, 3, 0,
4665 doc
: /* Open FONT-ENTITY. */)
4666 (Lisp_Object font_entity
, Lisp_Object size
, Lisp_Object frame
)
4670 CHECK_FONT_ENTITY (font_entity
);
4672 frame
= selected_frame
;
4673 CHECK_LIVE_FRAME (frame
);
4676 isize
= XINT (AREF (font_entity
, FONT_SIZE_INDEX
));
4679 CHECK_NUMBER_OR_FLOAT (size
);
4681 isize
= POINT_TO_PIXEL (XFLOAT_DATA (size
), XFRAME (frame
)->resy
);
4683 isize
= XINT (size
);
4687 return font_open_entity (XFRAME (frame
), font_entity
, isize
);
4690 DEFUN ("close-font", Fclose_font
, Sclose_font
, 1, 2, 0,
4691 doc
: /* Close FONT-OBJECT. */)
4692 (Lisp_Object font_object
, Lisp_Object frame
)
4694 CHECK_FONT_OBJECT (font_object
);
4696 frame
= selected_frame
;
4697 CHECK_LIVE_FRAME (frame
);
4698 font_close_object (XFRAME (frame
), font_object
);
4702 DEFUN ("query-font", Fquery_font
, Squery_font
, 1, 1, 0,
4703 doc
: /* Return information about FONT-OBJECT.
4704 The value is a vector:
4705 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4708 NAME is a string of the font name (or nil if the font backend doesn't
4711 FILENAME is a string of the font file (or nil if the font backend
4712 doesn't provide a file name).
4714 PIXEL-SIZE is a pixel size by which the font is opened.
4716 SIZE is a maximum advance width of the font in pixels.
4718 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4721 CAPABILITY is a list whose first element is a symbol representing the
4722 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4723 remaining elements describe the details of the font capability.
4725 If the font is OpenType font, the form of the list is
4726 \(opentype GSUB GPOS)
4727 where GSUB shows which "GSUB" features the font supports, and GPOS
4728 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4729 lists of the format:
4730 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4732 If the font is not OpenType font, currently the length of the form is
4735 SCRIPT is a symbol representing OpenType script tag.
4737 LANGSYS is a symbol representing OpenType langsys tag, or nil
4738 representing the default langsys.
4740 FEATURE is a symbol representing OpenType feature tag.
4742 If the font is not OpenType font, CAPABILITY is nil. */)
4743 (Lisp_Object font_object
)
4748 CHECK_FONT_GET_OBJECT (font_object
, font
);
4750 val
= Fmake_vector (make_number (9), Qnil
);
4751 ASET (val
, 0, AREF (font_object
, FONT_NAME_INDEX
));
4752 ASET (val
, 1, AREF (font_object
, FONT_FILE_INDEX
));
4753 ASET (val
, 2, make_number (font
->pixel_size
));
4754 ASET (val
, 3, make_number (font
->max_width
));
4755 ASET (val
, 4, make_number (font
->ascent
));
4756 ASET (val
, 5, make_number (font
->descent
));
4757 ASET (val
, 6, make_number (font
->space_width
));
4758 ASET (val
, 7, make_number (font
->average_width
));
4759 if (font
->driver
->otf_capability
)
4760 ASET (val
, 8, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
4764 DEFUN ("font-get-glyphs", Ffont_get_glyphs
, Sfont_get_glyphs
, 3, 4, 0,
4766 /* Return a vector of FONT-OBJECT's glyphs for the specified characters.
4767 FROM and TO are positions (integers or markers) specifying a region
4768 of the current buffer.
4769 If the optional fourth arg OBJECT is not nil, it is a string or a
4770 vector containing the target characters.
4772 Each element is a vector containing information of a glyph in this format:
4773 [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
4775 FROM is an index numbers of a character the glyph corresponds to.
4776 TO is the same as FROM.
4777 C is the character of the glyph.
4778 CODE is the glyph-code of C in FONT-OBJECT.
4779 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
4780 ADJUSTMENT is always nil.
4781 If FONT-OBJECT doesn't have a glyph for a character,
4782 the corresponding element is nil. */)
4783 (Lisp_Object font_object
, Lisp_Object from
, Lisp_Object to
,
4788 Lisp_Object
*chars
, vec
;
4791 CHECK_FONT_GET_OBJECT (font_object
, font
);
4794 EMACS_INT charpos
, bytepos
;
4796 validate_region (&from
, &to
);
4799 len
= XFASTINT (to
) - XFASTINT (from
);
4800 SAFE_ALLOCA_LISP (chars
, len
);
4801 charpos
= XFASTINT (from
);
4802 bytepos
= CHAR_TO_BYTE (charpos
);
4803 for (i
= 0; charpos
< XFASTINT (to
); i
++)
4805 FETCH_CHAR_ADVANCE (c
, charpos
, bytepos
);
4806 chars
[i
] = make_number (c
);
4809 else if (STRINGP (object
))
4811 const unsigned char *p
;
4813 CHECK_NUMBER (from
);
4815 if (XINT (from
) < 0 || XINT (from
) > XINT (to
)
4816 || XINT (to
) > SCHARS (object
))
4817 args_out_of_range_3 (object
, from
, to
);
4820 len
= XFASTINT (to
) - XFASTINT (from
);
4821 SAFE_ALLOCA_LISP (chars
, len
);
4823 if (STRING_MULTIBYTE (object
))
4824 for (i
= 0; i
< len
; i
++)
4826 c
= STRING_CHAR_ADVANCE (p
);
4827 chars
[i
] = make_number (c
);
4830 for (i
= 0; i
< len
; i
++)
4831 chars
[i
] = make_number (p
[i
]);
4835 CHECK_VECTOR (object
);
4836 CHECK_NUMBER (from
);
4838 if (XINT (from
) < 0 || XINT (from
) > XINT (to
)
4839 || XINT (to
) > ASIZE (object
))
4840 args_out_of_range_3 (object
, from
, to
);
4843 len
= XFASTINT (to
) - XFASTINT (from
);
4844 for (i
= 0; i
< len
; i
++)
4846 Lisp_Object elt
= AREF (object
, XFASTINT (from
) + i
);
4847 CHECK_CHARACTER (elt
);
4849 chars
= &(AREF (object
, XFASTINT (from
)));
4852 vec
= Fmake_vector (make_number (len
), Qnil
);
4853 for (i
= 0; i
< len
; i
++)
4856 int c
= XFASTINT (chars
[i
]);
4859 struct font_metrics metrics
;
4861 cod
= code
= font
->driver
->encode_char (font
, c
);
4862 if (code
== FONT_INVALID_CODE
)
4864 g
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
4865 LGLYPH_SET_FROM (g
, i
);
4866 LGLYPH_SET_TO (g
, i
);
4867 LGLYPH_SET_CHAR (g
, c
);
4868 LGLYPH_SET_CODE (g
, code
);
4869 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4870 LGLYPH_SET_WIDTH (g
, metrics
.width
);
4871 LGLYPH_SET_LBEARING (g
, metrics
.lbearing
);
4872 LGLYPH_SET_RBEARING (g
, metrics
.rbearing
);
4873 LGLYPH_SET_ASCENT (g
, metrics
.ascent
);
4874 LGLYPH_SET_DESCENT (g
, metrics
.descent
);
4877 if (! VECTORP (object
))
4882 DEFUN ("font-match-p", Ffont_match_p
, Sfont_match_p
, 2, 2, 0,
4883 doc
: /* Return t if and only if font-spec SPEC matches with FONT.
4884 FONT is a font-spec, font-entity, or font-object. */)
4885 (Lisp_Object spec
, Lisp_Object font
)
4887 CHECK_FONT_SPEC (spec
);
4890 return (font_match_p (spec
, font
) ? Qt
: Qnil
);
4893 DEFUN ("font-at", Ffont_at
, Sfont_at
, 1, 3, 0,
4894 doc
: /* Return a font-object for displaying a character at POSITION.
4895 Optional second arg WINDOW, if non-nil, is a window displaying
4896 the current buffer. It defaults to the currently selected window. */)
4897 (Lisp_Object position
, Lisp_Object window
, Lisp_Object string
)
4904 CHECK_NUMBER_COERCE_MARKER (position
);
4905 pos
= XINT (position
);
4906 if (pos
< BEGV
|| pos
>= ZV
)
4907 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
4911 CHECK_NUMBER (position
);
4912 CHECK_STRING (string
);
4913 pos
= XINT (position
);
4914 if (pos
< 0 || pos
>= SCHARS (string
))
4915 args_out_of_range (string
, position
);
4918 window
= selected_window
;
4919 CHECK_LIVE_WINDOW (window
);
4920 w
= XWINDOW (window
);
4922 return font_at (-1, pos
, NULL
, w
, string
);
4926 DEFUN ("draw-string", Fdraw_string
, Sdraw_string
, 2, 2, 0,
4927 doc
: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4928 The value is a number of glyphs drawn.
4929 Type C-l to recover what previously shown. */)
4930 (Lisp_Object font_object
, Lisp_Object string
)
4932 Lisp_Object frame
= selected_frame
;
4933 FRAME_PTR f
= XFRAME (frame
);
4939 CHECK_FONT_GET_OBJECT (font_object
, font
);
4940 CHECK_STRING (string
);
4941 len
= SCHARS (string
);
4942 code
= alloca (sizeof (unsigned) * len
);
4943 for (i
= 0; i
< len
; i
++)
4945 Lisp_Object ch
= Faref (string
, make_number (i
));
4949 code
[i
] = font
->driver
->encode_char (font
, c
);
4950 if (code
[i
] == FONT_INVALID_CODE
)
4953 face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4955 if (font
->driver
->prepare_face
)
4956 font
->driver
->prepare_face (f
, face
);
4957 width
= font
->driver
->text_extents (font
, code
, i
, NULL
);
4958 len
= font
->driver
->draw_text (f
, face
, 0, font
->ascent
, code
, i
, width
);
4959 if (font
->driver
->done_face
)
4960 font
->driver
->done_face (f
, face
);
4962 return make_number (len
);
4966 #endif /* FONT_DEBUG */
4968 #ifdef HAVE_WINDOW_SYSTEM
4970 DEFUN ("font-info", Ffont_info
, Sfont_info
, 1, 2, 0,
4971 doc
: /* Return information about a font named NAME on frame FRAME.
4972 If FRAME is omitted or nil, use the selected frame.
4973 The returned value is a vector of OPENED-NAME, FULL-NAME, SIZE,
4974 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4976 OPENED-NAME is the name used for opening the font,
4977 FULL-NAME is the full name of the font,
4978 SIZE is the pixelsize of the font,
4979 HEIGHT is the pixel-height of the font (i.e ascent + descent),
4980 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4981 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4982 how to compose characters.
4983 If the named font is not yet loaded, return nil. */)
4984 (Lisp_Object name
, Lisp_Object frame
)
4989 Lisp_Object font_object
;
4991 (*check_window_system_func
) ();
4994 CHECK_STRING (name
);
4996 frame
= selected_frame
;
4997 CHECK_LIVE_FRAME (frame
);
5002 int fontset
= fs_query_fontset (name
, 0);
5005 name
= fontset_ascii (fontset
);
5006 font_object
= font_open_by_name (f
, (char *) SDATA (name
));
5008 else if (FONT_OBJECT_P (name
))
5010 else if (FONT_ENTITY_P (name
))
5011 font_object
= font_open_entity (f
, name
, 0);
5014 struct face
*face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
5015 Lisp_Object entity
= font_matching_entity (f
, face
->lface
, name
);
5017 font_object
= ! NILP (entity
) ? font_open_entity (f
, entity
, 0) : Qnil
;
5019 if (NILP (font_object
))
5021 font
= XFONT_OBJECT (font_object
);
5023 info
= Fmake_vector (make_number (7), Qnil
);
5024 XVECTOR (info
)->contents
[0] = AREF (font_object
, FONT_NAME_INDEX
);
5025 XVECTOR (info
)->contents
[1] = AREF (font_object
, FONT_FULLNAME_INDEX
);
5026 XVECTOR (info
)->contents
[2] = make_number (font
->pixel_size
);
5027 XVECTOR (info
)->contents
[3] = make_number (font
->height
);
5028 XVECTOR (info
)->contents
[4] = make_number (font
->baseline_offset
);
5029 XVECTOR (info
)->contents
[5] = make_number (font
->relative_compose
);
5030 XVECTOR (info
)->contents
[6] = make_number (font
->default_ascent
);
5033 /* As font_object is still in FONT_OBJLIST of the entity, we can't
5034 close it now. Perhaps, we should manage font-objects
5035 by `reference-count'. */
5036 font_close_object (f
, font_object
);
5043 #define BUILD_STYLE_TABLE(TBL) \
5044 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
5047 build_style_table (const struct table_entry
*entry
, int nelement
)
5050 Lisp_Object table
, elt
;
5052 table
= Fmake_vector (make_number (nelement
), Qnil
);
5053 for (i
= 0; i
< nelement
; i
++)
5055 for (j
= 0; entry
[i
].names
[j
]; j
++);
5056 elt
= Fmake_vector (make_number (j
+ 1), Qnil
);
5057 ASET (elt
, 0, make_number (entry
[i
].numeric
));
5058 for (j
= 0; entry
[i
].names
[j
]; j
++)
5059 ASET (elt
, j
+ 1, intern_c_string (entry
[i
].names
[j
]));
5060 ASET (table
, i
, elt
);
5065 Lisp_Object Vfont_log
;
5067 /* The deferred font-log data of the form [ACTION ARG RESULT].
5068 If ACTION is not nil, that is added to the log when font_add_log is
5069 called next time. At that time, ACTION is set back to nil. */
5070 static Lisp_Object Vfont_log_deferred
;
5072 /* Prepend the font-related logging data in Vfont_log if it is not
5073 `t'. ACTION describes a kind of font-related action (e.g. listing,
5074 opening), ARG is the argument for the action, and RESULT is the
5075 result of the action. */
5077 font_add_log (char *action
, Lisp_Object arg
, Lisp_Object result
)
5079 Lisp_Object tail
, val
;
5082 if (EQ (Vfont_log
, Qt
))
5084 if (STRINGP (AREF (Vfont_log_deferred
, 0)))
5086 char *str
= (char *) SDATA (AREF (Vfont_log_deferred
, 0));
5088 ASET (Vfont_log_deferred
, 0, Qnil
);
5089 font_add_log (str
, AREF (Vfont_log_deferred
, 1),
5090 AREF (Vfont_log_deferred
, 2));
5095 Lisp_Object tail
, elt
;
5096 Lisp_Object equalstr
= build_string ("=");
5098 val
= Ffont_xlfd_name (arg
, Qt
);
5099 for (tail
= AREF (arg
, FONT_EXTRA_INDEX
); CONSP (tail
);
5103 if (EQ (XCAR (elt
), QCscript
)
5104 && SYMBOLP (XCDR (elt
)))
5105 val
= concat3 (val
, SYMBOL_NAME (QCscript
),
5106 concat2 (equalstr
, SYMBOL_NAME (XCDR (elt
))));
5107 else if (EQ (XCAR (elt
), QClang
)
5108 && SYMBOLP (XCDR (elt
)))
5109 val
= concat3 (val
, SYMBOL_NAME (QClang
),
5110 concat2 (equalstr
, SYMBOL_NAME (XCDR (elt
))));
5111 else if (EQ (XCAR (elt
), QCotf
)
5112 && CONSP (XCDR (elt
)) && SYMBOLP (XCAR (XCDR (elt
))))
5113 val
= concat3 (val
, SYMBOL_NAME (QCotf
),
5115 SYMBOL_NAME (XCAR (XCDR (elt
)))));
5121 && VECTORP (XCAR (result
))
5122 && ASIZE (XCAR (result
)) > 0
5123 && FONTP (AREF (XCAR (result
), 0)))
5124 result
= font_vconcat_entity_vectors (result
);
5127 val
= Ffont_xlfd_name (result
, Qt
);
5128 if (! FONT_SPEC_P (result
))
5129 val
= concat3 (SYMBOL_NAME (AREF (result
, FONT_TYPE_INDEX
)),
5130 build_string (":"), val
);
5133 else if (CONSP (result
))
5135 result
= Fcopy_sequence (result
);
5136 for (tail
= result
; CONSP (tail
); tail
= XCDR (tail
))
5140 val
= Ffont_xlfd_name (val
, Qt
);
5141 XSETCAR (tail
, val
);
5144 else if (VECTORP (result
))
5146 result
= Fcopy_sequence (result
);
5147 for (i
= 0; i
< ASIZE (result
); i
++)
5149 val
= AREF (result
, i
);
5151 val
= Ffont_xlfd_name (val
, Qt
);
5152 ASET (result
, i
, val
);
5155 Vfont_log
= Fcons (list3 (intern (action
), arg
, result
), Vfont_log
);
5158 /* Record a font-related logging data to be added to Vfont_log when
5159 font_add_log is called next time. ACTION, ARG, RESULT are the same
5163 font_deferred_log (char *action
, Lisp_Object arg
, Lisp_Object result
)
5165 if (EQ (Vfont_log
, Qt
))
5167 ASET (Vfont_log_deferred
, 0, build_string (action
));
5168 ASET (Vfont_log_deferred
, 1, arg
);
5169 ASET (Vfont_log_deferred
, 2, result
);
5172 extern void syms_of_ftfont (void);
5173 extern void syms_of_xfont (void);
5174 extern void syms_of_xftfont (void);
5175 extern void syms_of_ftxfont (void);
5176 extern void syms_of_bdffont (void);
5177 extern void syms_of_w32font (void);
5178 extern void syms_of_atmfont (void);
5179 extern void syms_of_nsfont (void);
5184 sort_shift_bits
[FONT_TYPE_INDEX
] = 0;
5185 sort_shift_bits
[FONT_SLANT_INDEX
] = 2;
5186 sort_shift_bits
[FONT_WEIGHT_INDEX
] = 9;
5187 sort_shift_bits
[FONT_SIZE_INDEX
] = 16;
5188 sort_shift_bits
[FONT_WIDTH_INDEX
] = 23;
5189 /* Note that the other elements in sort_shift_bits are not used. */
5191 staticpro (&font_charset_alist
);
5192 font_charset_alist
= Qnil
;
5194 DEFSYM (Qopentype
, "opentype");
5196 DEFSYM (Qascii_0
, "ascii-0");
5197 DEFSYM (Qiso8859_1
, "iso8859-1");
5198 DEFSYM (Qiso10646_1
, "iso10646-1");
5199 DEFSYM (Qunicode_bmp
, "unicode-bmp");
5200 DEFSYM (Qunicode_sip
, "unicode-sip");
5204 DEFSYM (QCotf
, ":otf");
5205 DEFSYM (QClang
, ":lang");
5206 DEFSYM (QCscript
, ":script");
5207 DEFSYM (QCantialias
, ":antialias");
5209 DEFSYM (QCfoundry
, ":foundry");
5210 DEFSYM (QCadstyle
, ":adstyle");
5211 DEFSYM (QCregistry
, ":registry");
5212 DEFSYM (QCspacing
, ":spacing");
5213 DEFSYM (QCdpi
, ":dpi");
5214 DEFSYM (QCscalable
, ":scalable");
5215 DEFSYM (QCavgwidth
, ":avgwidth");
5216 DEFSYM (QCfont_entity
, ":font-entity");
5217 DEFSYM (QCfc_unknown_spec
, ":fc-unknown-spec");
5227 DEFSYM (QCuser_spec
, "user-spec");
5229 staticpro (&null_vector
);
5230 null_vector
= Fmake_vector (make_number (0), Qnil
);
5232 staticpro (&scratch_font_spec
);
5233 scratch_font_spec
= Ffont_spec (0, NULL
);
5234 staticpro (&scratch_font_prefer
);
5235 scratch_font_prefer
= Ffont_spec (0, NULL
);
5237 staticpro (&Vfont_log_deferred
);
5238 Vfont_log_deferred
= Fmake_vector (make_number (3), Qnil
);
5242 staticpro (&otf_list
);
5244 #endif /* HAVE_LIBOTF */
5248 defsubr (&Sfont_spec
);
5249 defsubr (&Sfont_get
);
5250 #ifdef HAVE_WINDOW_SYSTEM
5251 defsubr (&Sfont_face_attributes
);
5253 defsubr (&Sfont_put
);
5254 defsubr (&Slist_fonts
);
5255 defsubr (&Sfont_family_list
);
5256 defsubr (&Sfind_font
);
5257 defsubr (&Sfont_xlfd_name
);
5258 defsubr (&Sclear_font_cache
);
5259 defsubr (&Sfont_shape_gstring
);
5260 defsubr (&Sfont_variation_glyphs
);
5262 defsubr (&Sfont_drive_otf
);
5263 defsubr (&Sfont_otf_alternates
);
5267 defsubr (&Sopen_font
);
5268 defsubr (&Sclose_font
);
5269 defsubr (&Squery_font
);
5270 defsubr (&Sfont_get_glyphs
);
5271 defsubr (&Sfont_match_p
);
5272 defsubr (&Sfont_at
);
5274 defsubr (&Sdraw_string
);
5276 #endif /* FONT_DEBUG */
5277 #ifdef HAVE_WINDOW_SYSTEM
5278 defsubr (&Sfont_info
);
5281 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist
,
5283 Alist of fontname patterns vs the corresponding encoding and repertory info.
5284 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5285 where ENCODING is a charset or a char-table,
5286 and REPERTORY is a charset, a char-table, or nil.
5288 If ENCODING and REPERTORY are the same, the element can have the form
5289 \(REGEXP . ENCODING).
5291 ENCODING is for converting a character to a glyph code of the font.
5292 If ENCODING is a charset, encoding a character by the charset gives
5293 the corresponding glyph code. If ENCODING is a char-table, looking up
5294 the table by a character gives the corresponding glyph code.
5296 REPERTORY specifies a repertory of characters supported by the font.
5297 If REPERTORY is a charset, all characters beloging to the charset are
5298 supported. If REPERTORY is a char-table, all characters who have a
5299 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5300 gets the repertory information by an opened font and ENCODING. */);
5301 Vfont_encoding_alist
= Qnil
;
5303 /* FIXME: These 3 vars are not quite what they appear: setq on them
5304 won't have any effect other than disconnect them from the style
5305 table used by the font display code. So we make them read-only,
5306 to avoid this confusing situation. */
5308 DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table
,
5309 doc
: /* Vector of valid font weight values.
5310 Each element has the form:
5311 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5312 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5313 Vfont_weight_table
= BUILD_STYLE_TABLE (weight_table
);
5314 XSYMBOL (intern_c_string ("font-weight-table"))->constant
= 1;
5316 DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table
,
5317 doc
: /* Vector of font slant symbols vs the corresponding numeric values.
5318 See `font-weight-table' for the format of the vector. */);
5319 Vfont_slant_table
= BUILD_STYLE_TABLE (slant_table
);
5320 XSYMBOL (intern_c_string ("font-slant-table"))->constant
= 1;
5322 DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table
,
5323 doc
: /* Alist of font width symbols vs the corresponding numeric values.
5324 See `font-weight-table' for the format of the vector. */);
5325 Vfont_width_table
= BUILD_STYLE_TABLE (width_table
);
5326 XSYMBOL (intern_c_string ("font-width-table"))->constant
= 1;
5328 staticpro (&font_style_table
);
5329 font_style_table
= Fmake_vector (make_number (3), Qnil
);
5330 ASET (font_style_table
, 0, Vfont_weight_table
);
5331 ASET (font_style_table
, 1, Vfont_slant_table
);
5332 ASET (font_style_table
, 2, Vfont_width_table
);
5334 DEFVAR_LISP ("font-log", &Vfont_log
, doc
: /*
5335 *Logging list of font related actions and results.
5336 The value t means to suppress the logging.
5337 The initial value is set to nil if the environment variable
5338 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5341 #ifdef HAVE_WINDOW_SYSTEM
5342 #ifdef HAVE_FREETYPE
5344 #ifdef HAVE_X_WINDOWS
5349 #endif /* HAVE_XFT */
5350 #endif /* HAVE_X_WINDOWS */
5351 #else /* not HAVE_FREETYPE */
5352 #ifdef HAVE_X_WINDOWS
5354 #endif /* HAVE_X_WINDOWS */
5355 #endif /* not HAVE_FREETYPE */
5358 #endif /* HAVE_BDFFONT */
5361 #endif /* WINDOWSNT */
5364 #endif /* HAVE_NS */
5365 #endif /* HAVE_WINDOW_SYSTEM */
5371 Vfont_log
= egetenv ("EMACS_FONT_LOG") ? Qnil
: Qt
;
5374 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
5375 (do not change this comment) */