1 /* font.c -- "Font" primitives.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 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/>. */
31 #include "dispextern.h"
33 #include "character.h"
34 #include "composite.h"
40 #endif /* HAVE_X_WINDOWS */
44 #endif /* HAVE_NTGUI */
50 Lisp_Object Qfont_spec
, Qfont_entity
, Qfont_object
;
53 extern Lisp_Object Qfontsize
;
56 Lisp_Object Qopentype
;
58 /* Important character set strings. */
59 Lisp_Object Qascii_0
, Qiso8859_1
, Qiso10646_1
, Qunicode_bmp
, Qunicode_sip
;
62 #define DEFAULT_ENCODING Qiso10646_1
64 #define DEFAULT_ENCODING Qiso8859_1
67 /* Unicode category `Cf'. */
68 static Lisp_Object QCf
;
70 /* Special vector of zero length. This is repeatedly used by (struct
71 font_driver *)->list when a specified font is not found. */
72 static Lisp_Object null_vector
;
74 static Lisp_Object Vfont_weight_table
, Vfont_slant_table
, Vfont_width_table
;
76 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
77 static Lisp_Object font_style_table
;
79 /* Structure used for tables mapping weight, slant, and width numeric
80 values and their names. */
85 /* The first one is a valid name as a face attribute.
86 The second one (if any) is a typical name in XLFD field. */
91 /* Table of weight numeric values and their names. This table must be
92 sorted by numeric values in ascending order. */
94 static struct table_entry weight_table
[] =
97 { 20, { "ultra-light", "ultralight" }},
98 { 40, { "extra-light", "extralight" }},
100 { 75, { "semi-light", "semilight", "demilight", "book" }},
101 { 100, { "normal", "medium", "regular" }},
102 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
104 { 205, { "extra-bold", "extrabold" }},
105 { 210, { "ultra-bold", "ultrabold", "black" }}
108 /* Table of slant numeric values and their names. This table must be
109 sorted by numeric values in ascending order. */
111 static struct table_entry slant_table
[] =
113 { 0, { "reverse-oblique", "ro" }},
114 { 10, { "reverse-italic", "ri" }},
115 { 100, { "normal", "r" }},
116 { 200, { "italic" ,"i", "ot" }},
117 { 210, { "oblique", "o" }}
120 /* Table of width numeric values and their names. This table must be
121 sorted by numeric values in ascending order. */
123 static struct table_entry width_table
[] =
125 { 50, { "ultra-condensed", "ultracondensed" }},
126 { 63, { "extra-condensed", "extracondensed" }},
127 { 75, { "condensed", "compressed", "narrow" }},
128 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
129 { 100, { "normal", "medium", "regular" }},
130 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
131 { 125, { "expanded" }},
132 { 150, { "extra-expanded", "extraexpanded" }},
133 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
136 extern Lisp_Object Qnormal
;
138 /* Symbols representing keys of normal font properties. */
139 extern Lisp_Object QCtype
, QCfamily
, QCweight
, QCslant
, QCwidth
;
140 extern Lisp_Object QCheight
, QCsize
, QCname
;
142 Lisp_Object QCfoundry
, QCadstyle
, QCregistry
;
143 /* Symbols representing keys of font extra info. */
144 Lisp_Object QCspacing
, QCdpi
, QCscalable
, QCotf
, QClang
, QCscript
, QCavgwidth
;
145 Lisp_Object QCantialias
, QCfont_entity
, QCfc_unknown_spec
;
146 /* Symbols representing values of font spacing property. */
147 Lisp_Object Qc
, Qm
, Qp
, Qd
;
149 Lisp_Object Vfont_encoding_alist
;
151 /* Alist of font registry symbol and the corresponding charsets
152 information. The information is retrieved from
153 Vfont_encoding_alist on demand.
155 Eash element has the form:
156 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
160 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
161 encodes a character code to a glyph code of a font, and
162 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
163 character is supported by a font.
165 The latter form means that the information for REGISTRY couldn't be
167 static Lisp_Object font_charset_alist
;
169 /* List of all font drivers. Each font-backend (XXXfont.c) calls
170 register_font_driver in syms_of_XXXfont to register its font-driver
172 static struct font_driver_list
*font_driver_list
;
176 /* Creaters of font-related Lisp object. */
181 Lisp_Object font_spec
;
182 struct font_spec
*spec
183 = ((struct font_spec
*)
184 allocate_pseudovector (VECSIZE (struct font_spec
),
185 FONT_SPEC_MAX
, PVEC_FONT
));
186 XSETFONT (font_spec
, spec
);
193 Lisp_Object font_entity
;
194 struct font_entity
*entity
195 = ((struct font_entity
*)
196 allocate_pseudovector (VECSIZE (struct font_entity
),
197 FONT_ENTITY_MAX
, PVEC_FONT
));
198 XSETFONT (font_entity
, entity
);
202 /* Create a font-object whose structure size is SIZE. If ENTITY is
203 not nil, copy properties from ENTITY to the font-object. If
204 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
206 font_make_object (size
, entity
, pixelsize
)
211 Lisp_Object font_object
;
213 = (struct font
*) allocate_pseudovector (size
, FONT_OBJECT_MAX
, PVEC_FONT
);
216 XSETFONT (font_object
, font
);
220 for (i
= 1; i
< FONT_SPEC_MAX
; i
++)
221 font
->props
[i
] = AREF (entity
, i
);
222 if (! NILP (AREF (entity
, FONT_EXTRA_INDEX
)))
223 font
->props
[FONT_EXTRA_INDEX
]
224 = Fcopy_sequence (AREF (entity
, FONT_EXTRA_INDEX
));
227 font
->props
[FONT_SIZE_INDEX
] = make_number (pixelsize
);
233 static int font_pixel_size
P_ ((FRAME_PTR f
, Lisp_Object
));
234 static Lisp_Object font_open_entity
P_ ((FRAME_PTR
, Lisp_Object
, int));
235 static Lisp_Object font_matching_entity
P_ ((FRAME_PTR
, Lisp_Object
*,
238 /* Number of registered font drivers. */
239 static int num_font_drivers
;
242 /* Return a Lispy value of a font property value at STR and LEN bytes.
243 If STR is "*", it returns nil.
244 If FORCE_SYMBOL is zero and all characters in STR are digits, it
245 returns an integer. Otherwise, it returns a symbol interned from
249 font_intern_prop (str
, len
, force_symbol
)
259 if (len
== 1 && *str
== '*')
261 if (!force_symbol
&& len
>=1 && isdigit (*str
))
263 for (i
= 1; i
< len
; i
++)
264 if (! isdigit (str
[i
]))
267 return make_number (atoi (str
));
270 /* The following code is copied from the function intern (in
271 lread.c), and modified to suite our purpose. */
273 if (!VECTORP (obarray
) || XVECTOR (obarray
)->size
== 0)
274 obarray
= check_obarray (obarray
);
275 parse_str_as_multibyte (str
, len
, &nchars
, &nbytes
);
276 if (len
== nchars
|| len
!= nbytes
)
277 /* CONTENTS contains no multibyte sequences or contains an invalid
278 multibyte sequence. We'll make a unibyte string. */
279 tem
= oblookup (obarray
, str
, len
, len
);
281 tem
= oblookup (obarray
, str
, nchars
, len
);
284 if (len
== nchars
|| len
!= nbytes
)
285 tem
= make_unibyte_string (str
, len
);
287 tem
= make_multibyte_string (str
, nchars
, len
);
288 return Fintern (tem
, obarray
);
291 /* Return a pixel size of font-spec SPEC on frame F. */
294 font_pixel_size (f
, spec
)
298 #ifdef HAVE_WINDOW_SYSTEM
299 Lisp_Object size
= AREF (spec
, FONT_SIZE_INDEX
);
308 font_assert (FLOATP (size
));
309 point_size
= XFLOAT_DATA (size
);
310 val
= AREF (spec
, FONT_DPI_INDEX
);
315 pixel_size
= POINT_TO_PIXEL (point_size
, dpi
);
323 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
324 font vector. If VAL is not valid (i.e. not registered in
325 font_style_table), return -1 if NOERROR is zero, and return a
326 proper index if NOERROR is nonzero. In that case, register VAL in
327 font_style_table if VAL is a symbol, and return a closest index if
328 VAL is an integer. */
331 font_style_to_value (prop
, val
, noerror
)
332 enum font_property_index prop
;
336 Lisp_Object table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
337 int len
= ASIZE (table
);
343 Lisp_Object args
[2], elt
;
345 /* At first try exact match. */
346 for (i
= 0; i
< len
; i
++)
347 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
348 if (EQ (val
, AREF (AREF (table
, i
), j
)))
349 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
350 | (i
<< 4) | (j
- 1));
351 /* Try also with case-folding match. */
352 s
= SDATA (SYMBOL_NAME (val
));
353 for (i
= 0; i
< len
; i
++)
354 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
356 elt
= AREF (AREF (table
, i
), j
);
357 if (xstrcasecmp (s
, SDATA (SYMBOL_NAME (elt
))) == 0)
358 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
359 | (i
<< 4) | (j
- 1));
365 elt
= Fmake_vector (make_number (2), make_number (255));
368 args
[1] = Fmake_vector (make_number (1), elt
);
369 ASET (font_style_table
, prop
- FONT_WEIGHT_INDEX
, Fvconcat (2, args
));
370 return (255 << 8) | (i
<< 4);
375 int numeric
= XINT (val
);
377 for (i
= 0, last_n
= -1; i
< len
; i
++)
379 int n
= XINT (AREF (AREF (table
, i
), 0));
382 return (n
<< 8) | (i
<< 4);
387 return ((i
== 0 || n
- numeric
< numeric
- last_n
)
388 ? (n
<< 8) | (i
<< 4): (last_n
<< 8 | ((i
- 1) << 4)));
394 return ((last_n
<< 8) | ((i
- 1) << 4));
399 font_style_symbolic (font
, prop
, for_face
)
401 enum font_property_index prop
;
404 Lisp_Object val
= AREF (font
, prop
);
405 Lisp_Object table
, elt
;
410 table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
411 i
= XINT (val
) & 0xFF;
412 font_assert (((i
>> 4) & 0xF) < ASIZE (table
));
413 elt
= AREF (table
, ((i
>> 4) & 0xF));
414 font_assert ((i
& 0xF) + 1 < ASIZE (elt
));
415 return (for_face
? AREF (elt
, 1) : AREF (elt
, (i
& 0xF) + 1));
418 extern Lisp_Object Vface_alternative_font_family_alist
;
420 extern Lisp_Object find_font_encoding
P_ ((Lisp_Object
));
423 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
424 FONTNAME. ENCODING is a charset symbol that specifies the encoding
425 of the font. REPERTORY is a charset symbol or nil. */
428 find_font_encoding (fontname
)
429 Lisp_Object fontname
;
431 Lisp_Object tail
, elt
;
433 for (tail
= Vfont_encoding_alist
; CONSP (tail
); tail
= XCDR (tail
))
437 && STRINGP (XCAR (elt
))
438 && fast_string_match_ignore_case (XCAR (elt
), fontname
) >= 0
439 && (SYMBOLP (XCDR (elt
))
440 ? CHARSETP (XCDR (elt
))
441 : CONSP (XCDR (elt
)) && CHARSETP (XCAR (XCDR (elt
)))))
444 /* We don't know the encoding of this font. Let's assume `ascii'. */
448 /* Return encoding charset and repertory charset for REGISTRY in
449 ENCODING and REPERTORY correspondingly. If correct information for
450 REGISTRY is available, return 0. Otherwise return -1. */
453 font_registry_charsets (registry
, encoding
, repertory
)
454 Lisp_Object registry
;
455 struct charset
**encoding
, **repertory
;
458 int encoding_id
, repertory_id
;
460 val
= Fassoc_string (registry
, font_charset_alist
, Qt
);
466 encoding_id
= XINT (XCAR (val
));
467 repertory_id
= XINT (XCDR (val
));
471 val
= find_font_encoding (SYMBOL_NAME (registry
));
472 if (SYMBOLP (val
) && CHARSETP (val
))
474 encoding_id
= repertory_id
= XINT (CHARSET_SYMBOL_ID (val
));
476 else if (CONSP (val
))
478 if (! CHARSETP (XCAR (val
)))
480 encoding_id
= XINT (CHARSET_SYMBOL_ID (XCAR (val
)));
481 if (NILP (XCDR (val
)))
485 if (! CHARSETP (XCDR (val
)))
487 repertory_id
= XINT (CHARSET_SYMBOL_ID (XCDR (val
)));
492 val
= Fcons (make_number (encoding_id
), make_number (repertory_id
));
494 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, val
), Qnil
));
498 *encoding
= CHARSET_FROM_ID (encoding_id
);
500 *repertory
= repertory_id
>= 0 ? CHARSET_FROM_ID (repertory_id
) : NULL
;
505 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, Qnil
), Qnil
));
510 /* Font property value validaters. See the comment of
511 font_property_table for the meaning of the arguments. */
513 static Lisp_Object font_prop_validate
P_ ((int, Lisp_Object
, Lisp_Object
));
514 static Lisp_Object font_prop_validate_symbol
P_ ((Lisp_Object
, Lisp_Object
));
515 static Lisp_Object font_prop_validate_style
P_ ((Lisp_Object
, Lisp_Object
));
516 static Lisp_Object font_prop_validate_non_neg
P_ ((Lisp_Object
, Lisp_Object
));
517 static Lisp_Object font_prop_validate_spacing
P_ ((Lisp_Object
, Lisp_Object
));
518 static int get_font_prop_index
P_ ((Lisp_Object
));
521 font_prop_validate_symbol (prop
, val
)
522 Lisp_Object prop
, val
;
525 val
= Fintern (val
, Qnil
);
528 else if (EQ (prop
, QCregistry
))
529 val
= Fintern (Fdowncase (SYMBOL_NAME (val
)), Qnil
);
535 font_prop_validate_style (style
, val
)
536 Lisp_Object style
, val
;
538 enum font_property_index prop
= (EQ (style
, QCweight
) ? FONT_WEIGHT_INDEX
539 : EQ (style
, QCslant
) ? FONT_SLANT_INDEX
546 >= ASIZE (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
)))
550 Lisp_Object elt
= AREF (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
), (n
>> 4) & 0xF);
552 if ((n
& 0xF) + 1 >= ASIZE (elt
))
554 else if (XINT (AREF (elt
, 0)) != (n
>> 8))
558 else if (SYMBOLP (val
))
560 int n
= font_style_to_value (prop
, val
, 0);
562 val
= n
>= 0 ? make_number (n
) : Qerror
;
570 font_prop_validate_non_neg (prop
, val
)
571 Lisp_Object prop
, val
;
573 return (NATNUMP (val
) || (FLOATP (val
) && XFLOAT_DATA (val
) >= 0)
578 font_prop_validate_spacing (prop
, val
)
579 Lisp_Object prop
, val
;
581 if (NILP (val
) || (NATNUMP (val
) && XINT (val
) <= FONT_SPACING_CHARCELL
))
583 if (SYMBOLP (val
) && SBYTES (SYMBOL_NAME (val
)) == 1)
585 char spacing
= SDATA (SYMBOL_NAME (val
))[0];
587 if (spacing
== 'c' || spacing
== 'C')
588 return make_number (FONT_SPACING_CHARCELL
);
589 if (spacing
== 'm' || spacing
== 'M')
590 return make_number (FONT_SPACING_MONO
);
591 if (spacing
== 'p' || spacing
== 'P')
592 return make_number (FONT_SPACING_PROPORTIONAL
);
593 if (spacing
== 'd' || spacing
== 'D')
594 return make_number (FONT_SPACING_DUAL
);
600 font_prop_validate_otf (prop
, val
)
601 Lisp_Object prop
, val
;
603 Lisp_Object tail
, tmp
;
606 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
607 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
608 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
611 if (! SYMBOLP (XCAR (val
)))
616 if (! CONSP (tail
) || ! SYMBOLP (XCAR (val
)))
618 for (i
= 0; i
< 2; i
++)
625 for (tmp
= XCAR (tail
); CONSP (tmp
); tmp
= XCDR (tmp
))
626 if (! SYMBOLP (XCAR (tmp
)))
634 /* Structure of known font property keys and validater of the
638 /* Pointer to the key symbol. */
640 /* Function to validate PROP's value VAL, or NULL if any value is
641 ok. The value is VAL or its regularized value if VAL is valid,
642 and Qerror if not. */
643 Lisp_Object (*validater
) P_ ((Lisp_Object prop
, Lisp_Object val
));
644 } font_property_table
[] =
645 { { &QCtype
, font_prop_validate_symbol
},
646 { &QCfoundry
, font_prop_validate_symbol
},
647 { &QCfamily
, font_prop_validate_symbol
},
648 { &QCadstyle
, font_prop_validate_symbol
},
649 { &QCregistry
, font_prop_validate_symbol
},
650 { &QCweight
, font_prop_validate_style
},
651 { &QCslant
, font_prop_validate_style
},
652 { &QCwidth
, font_prop_validate_style
},
653 { &QCsize
, font_prop_validate_non_neg
},
654 { &QCdpi
, font_prop_validate_non_neg
},
655 { &QCspacing
, font_prop_validate_spacing
},
656 { &QCavgwidth
, font_prop_validate_non_neg
},
657 /* The order of the above entries must match with enum
658 font_property_index. */
659 { &QClang
, font_prop_validate_symbol
},
660 { &QCscript
, font_prop_validate_symbol
},
661 { &QCotf
, font_prop_validate_otf
}
664 /* Size (number of elements) of the above table. */
665 #define FONT_PROPERTY_TABLE_SIZE \
666 ((sizeof font_property_table) / (sizeof *font_property_table))
668 /* Return an index number of font property KEY or -1 if KEY is not an
669 already known property. */
672 get_font_prop_index (key
)
677 for (i
= 0; i
< FONT_PROPERTY_TABLE_SIZE
; i
++)
678 if (EQ (key
, *font_property_table
[i
].key
))
683 /* Validate the font property. The property key is specified by the
684 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
685 signal an error. The value is VAL or the regularized one. */
688 font_prop_validate (idx
, prop
, val
)
690 Lisp_Object prop
, val
;
692 Lisp_Object validated
;
697 prop
= *font_property_table
[idx
].key
;
700 idx
= get_font_prop_index (prop
);
704 validated
= (font_property_table
[idx
].validater
) (prop
, val
);
705 if (EQ (validated
, Qerror
))
706 signal_error ("invalid font property", Fcons (prop
, val
));
711 /* Store VAL as a value of extra font property PROP in FONT while
712 keeping the sorting order. Don't check the validity of VAL. */
715 font_put_extra (font
, prop
, val
)
716 Lisp_Object font
, prop
, val
;
718 Lisp_Object extra
= AREF (font
, FONT_EXTRA_INDEX
);
719 Lisp_Object slot
= (NILP (extra
) ? Qnil
: assq_no_quit (prop
, extra
));
723 Lisp_Object prev
= Qnil
;
726 && NILP (Fstring_lessp (prop
, XCAR (XCAR (extra
)))))
727 prev
= extra
, extra
= XCDR (extra
);
729 ASET (font
, FONT_EXTRA_INDEX
, Fcons (Fcons (prop
, val
), extra
));
731 XSETCDR (prev
, Fcons (Fcons (prop
, val
), extra
));
739 /* Font name parser and unparser */
741 static int parse_matrix
P_ ((char *));
742 static int font_expand_wildcards
P_ ((Lisp_Object
*, int));
743 static int font_parse_name
P_ ((char *, Lisp_Object
));
745 /* An enumerator for each field of an XLFD font name. */
746 enum xlfd_field_index
765 /* An enumerator for mask bit corresponding to each XLFD field. */
768 XLFD_FOUNDRY_MASK
= 0x0001,
769 XLFD_FAMILY_MASK
= 0x0002,
770 XLFD_WEIGHT_MASK
= 0x0004,
771 XLFD_SLANT_MASK
= 0x0008,
772 XLFD_SWIDTH_MASK
= 0x0010,
773 XLFD_ADSTYLE_MASK
= 0x0020,
774 XLFD_PIXEL_MASK
= 0x0040,
775 XLFD_POINT_MASK
= 0x0080,
776 XLFD_RESX_MASK
= 0x0100,
777 XLFD_RESY_MASK
= 0x0200,
778 XLFD_SPACING_MASK
= 0x0400,
779 XLFD_AVGWIDTH_MASK
= 0x0800,
780 XLFD_REGISTRY_MASK
= 0x1000,
781 XLFD_ENCODING_MASK
= 0x2000
785 /* Parse P pointing the pixel/point size field of the form
786 `[A B C D]' which specifies a transformation matrix:
792 by which all glyphs of the font are transformed. The spec says
793 that scalar value N for the pixel/point size is equivalent to:
794 A = N * resx/resy, B = C = 0, D = N.
796 Return the scalar value N if the form is valid. Otherwise return
807 for (i
= 0, p
++; i
< 4 && *p
&& *p
!= ']'; i
++)
810 matrix
[i
] = - strtod (p
+ 1, &end
);
812 matrix
[i
] = strtod (p
, &end
);
815 return (i
== 4 ? (int) matrix
[3] : -1);
818 /* Expand a wildcard field in FIELD (the first N fields are filled) to
819 multiple fields to fill in all 14 XLFD fields while restring a
820 field position by its contents. */
823 font_expand_wildcards (field
, n
)
824 Lisp_Object field
[XLFD_LAST_INDEX
];
828 Lisp_Object tmp
[XLFD_LAST_INDEX
];
829 /* Array of information about where this element can go. Nth
830 element is for Nth element of FIELD. */
832 /* Minimum possible field. */
834 /* Maxinum possible field. */
836 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
838 } range
[XLFD_LAST_INDEX
];
840 int range_from
, range_to
;
843 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
844 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
845 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
846 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
847 | XLFD_AVGWIDTH_MASK)
848 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
850 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
851 field. The value is shifted to left one bit by one in the
853 for (i
= 0, range_mask
= 0; i
<= 14 - n
; i
++)
854 range_mask
= (range_mask
<< 1) | 1;
856 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
857 position-based retriction for FIELD[I]. */
858 for (i
= 0, range_from
= 0, range_to
= 14 - n
; i
< n
;
859 i
++, range_from
++, range_to
++, range_mask
<<= 1)
861 Lisp_Object val
= field
[i
];
867 range
[i
].from
= range_from
;
868 range
[i
].to
= range_to
;
869 range
[i
].mask
= range_mask
;
873 /* The triplet FROM, TO, and MASK is a value-based
874 retriction for FIELD[I]. */
880 int numeric
= XINT (val
);
883 from
= to
= XLFD_ENCODING_INDEX
,
884 mask
= XLFD_ENCODING_MASK
;
885 else if (numeric
== 0)
886 from
= XLFD_PIXEL_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
887 mask
= XLFD_PIXEL_MASK
| XLFD_LARGENUM_MASK
;
888 else if (numeric
<= 48)
889 from
= to
= XLFD_PIXEL_INDEX
,
890 mask
= XLFD_PIXEL_MASK
;
892 from
= XLFD_POINT_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
893 mask
= XLFD_LARGENUM_MASK
;
895 else if (SBYTES (SYMBOL_NAME (val
)) == 0)
896 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ADSTYLE_INDEX
,
897 mask
= XLFD_NULL_MASK
;
899 from
= to
= XLFD_FOUNDRY_INDEX
, mask
= XLFD_FOUNDRY_MASK
;
902 Lisp_Object name
= SYMBOL_NAME (val
);
904 if (SDATA (name
)[SBYTES (name
) - 1] == '*')
905 from
= XLFD_REGISTRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
906 mask
= XLFD_REGENC_MASK
;
908 from
= to
= XLFD_ENCODING_INDEX
,
909 mask
= XLFD_ENCODING_MASK
;
911 else if (range_from
<= XLFD_WEIGHT_INDEX
912 && range_to
>= XLFD_WEIGHT_INDEX
913 && FONT_WEIGHT_NAME_NUMERIC (val
) >= 0)
914 from
= to
= XLFD_WEIGHT_INDEX
, mask
= XLFD_WEIGHT_MASK
;
915 else if (range_from
<= XLFD_SLANT_INDEX
916 && range_to
>= XLFD_SLANT_INDEX
917 && FONT_SLANT_NAME_NUMERIC (val
) >= 0)
918 from
= to
= XLFD_SLANT_INDEX
, mask
= XLFD_SLANT_MASK
;
919 else if (range_from
<= XLFD_SWIDTH_INDEX
920 && range_to
>= XLFD_SWIDTH_INDEX
921 && FONT_WIDTH_NAME_NUMERIC (val
) >= 0)
922 from
= to
= XLFD_SWIDTH_INDEX
, mask
= XLFD_SWIDTH_MASK
;
925 if (EQ (val
, Qc
) || EQ (val
, Qm
) || EQ (val
, Qp
) || EQ (val
, Qd
))
926 from
= to
= XLFD_SPACING_INDEX
, mask
= XLFD_SPACING_MASK
;
928 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
929 mask
= XLFD_SYMBOL_MASK
;
932 /* Merge position-based and value-based restrictions. */
934 while (from
< range_from
)
935 mask
&= ~(1 << from
++);
936 while (from
< 14 && ! (mask
& (1 << from
)))
938 while (to
> range_to
)
939 mask
&= ~(1 << to
--);
940 while (to
>= 0 && ! (mask
& (1 << to
)))
944 range
[i
].from
= from
;
946 range
[i
].mask
= mask
;
948 if (from
> range_from
|| to
< range_to
)
950 /* The range is narrowed by value-based restrictions.
951 Reflect it to the other fields. */
953 /* Following fields should be after FROM. */
955 /* Preceding fields should be before TO. */
956 for (j
= i
- 1, from
--, to
--; j
>= 0; j
--, from
--, to
--)
958 /* Check FROM for non-wildcard field. */
959 if (! NILP (tmp
[j
]) && range
[j
].from
< from
)
961 while (range
[j
].from
< from
)
962 range
[j
].mask
&= ~(1 << range
[j
].from
++);
963 while (from
< 14 && ! (range
[j
].mask
& (1 << from
)))
965 range
[j
].from
= from
;
968 from
= range
[j
].from
;
969 if (range
[j
].to
> to
)
971 while (range
[j
].to
> to
)
972 range
[j
].mask
&= ~(1 << range
[j
].to
--);
973 while (to
>= 0 && ! (range
[j
].mask
& (1 << to
)))
986 /* Decide all fileds from restrictions in RANGE. */
987 for (i
= j
= 0; i
< n
; i
++)
989 if (j
< range
[i
].from
)
991 if (i
== 0 || ! NILP (tmp
[i
- 1]))
992 /* None of TMP[X] corresponds to Jth field. */
994 for (; j
< range
[i
].from
; j
++)
999 if (! NILP (tmp
[n
- 1]) && j
< XLFD_REGISTRY_INDEX
)
1001 for (; j
< XLFD_LAST_INDEX
; j
++)
1003 if (INTEGERP (field
[XLFD_ENCODING_INDEX
]))
1004 field
[XLFD_ENCODING_INDEX
]
1005 = Fintern (Fnumber_to_string (field
[XLFD_ENCODING_INDEX
]), Qnil
);
1010 #ifdef ENABLE_CHECKING
1011 /* Match a 14-field XLFD pattern against a full XLFD font name. */
1013 font_match_xlfd (char *pattern
, char *name
)
1015 while (*pattern
&& *name
)
1017 if (*pattern
== *name
)
1019 else if (*pattern
== '*')
1020 if (*name
== pattern
[1])
1031 /* Make sure the font object matches the XLFD font name. */
1033 font_check_xlfd_parse (Lisp_Object font
, char *name
)
1035 char name_check
[256];
1036 font_unparse_xlfd (font
, 0, name_check
, 255);
1037 return font_match_xlfd (name_check
, name
);
1043 /* Parse NAME (null terminated) as XLFD and store information in FONT
1044 (font-spec or font-entity). Size property of FONT is set as
1046 specified XLFD fields FONT property
1047 --------------------- -------------
1048 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
1049 POINT_SIZE and RESY calculated pixel size (Lisp integer)
1050 POINT_SIZE POINT_SIZE/10 (Lisp float)
1052 If NAME is successfully parsed, return 0. Otherwise return -1.
1054 FONT is usually a font-spec, but when this function is called from
1055 X font backend driver, it is a font-entity. In that case, NAME is
1056 a fully specified XLFD. */
1059 font_parse_xlfd (name
, font
)
1063 int len
= strlen (name
);
1065 char *f
[XLFD_LAST_INDEX
+ 1];
1070 /* Maximum XLFD name length is 255. */
1072 /* Accept "*-.." as a fully specified XLFD. */
1073 if (name
[0] == '*' && name
[1] == '-')
1074 i
= 1, f
[XLFD_FOUNDRY_INDEX
] = name
;
1077 for (p
= name
+ i
; *p
; p
++)
1081 if (i
== XLFD_LAST_INDEX
)
1086 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1087 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1089 if (i
== XLFD_LAST_INDEX
)
1091 /* Fully specified XLFD. */
1094 ASET (font
, FONT_FOUNDRY_INDEX
, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX
));
1095 ASET (font
, FONT_FAMILY_INDEX
, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX
));
1096 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1097 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1099 val
= INTERN_FIELD_SYM (i
);
1102 if ((n
= font_style_to_value (j
, INTERN_FIELD_SYM (i
), 0)) < 0)
1104 ASET (font
, j
, make_number (n
));
1107 ASET (font
, FONT_ADSTYLE_INDEX
, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX
));
1108 if (strcmp (f
[XLFD_REGISTRY_INDEX
], "*-*") == 0)
1109 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
1111 ASET (font
, FONT_REGISTRY_INDEX
,
1112 font_intern_prop (f
[XLFD_REGISTRY_INDEX
],
1113 f
[XLFD_LAST_INDEX
] - f
[XLFD_REGISTRY_INDEX
],
1115 p
= f
[XLFD_PIXEL_INDEX
];
1116 if (*p
== '[' && (pixel_size
= parse_matrix (p
)) >= 0)
1117 ASET (font
, FONT_SIZE_INDEX
, make_number (pixel_size
));
1120 val
= INTERN_FIELD (XLFD_PIXEL_INDEX
);
1122 ASET (font
, FONT_SIZE_INDEX
, val
);
1125 double point_size
= -1;
1127 font_assert (FONT_SPEC_P (font
));
1128 p
= f
[XLFD_POINT_INDEX
];
1130 point_size
= parse_matrix (p
);
1131 else if (isdigit (*p
))
1132 point_size
= atoi (p
), point_size
/= 10;
1133 if (point_size
>= 0)
1134 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1138 ASET (font
, FONT_DPI_INDEX
, INTERN_FIELD (XLFD_RESY_INDEX
));
1139 val
= INTERN_FIELD (XLFD_SPACING_INDEX
);
1142 val
= font_prop_validate_spacing (QCspacing
, val
);
1143 if (! INTEGERP (val
))
1145 ASET (font
, FONT_SPACING_INDEX
, val
);
1147 p
= f
[XLFD_AVGWIDTH_INDEX
];
1150 ASET (font
, FONT_AVGWIDTH_INDEX
,
1151 font_intern_prop (p
, f
[XLFD_REGISTRY_INDEX
] - 1 - p
, 0));
1155 int wild_card_found
= 0;
1156 Lisp_Object prop
[XLFD_LAST_INDEX
];
1158 if (FONT_ENTITY_P (font
))
1160 for (j
= 0; j
< i
; j
++)
1164 if (f
[j
][1] && f
[j
][1] != '-')
1167 wild_card_found
= 1;
1170 prop
[j
] = INTERN_FIELD (j
);
1172 prop
[j
] = font_intern_prop (f
[j
], f
[i
] - f
[j
], 0);
1174 if (! wild_card_found
)
1176 if (font_expand_wildcards (prop
, i
) < 0)
1179 ASET (font
, FONT_FOUNDRY_INDEX
, prop
[XLFD_FOUNDRY_INDEX
]);
1180 ASET (font
, FONT_FAMILY_INDEX
, prop
[XLFD_FAMILY_INDEX
]);
1181 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1182 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1183 if (! NILP (prop
[i
]))
1185 if ((n
= font_style_to_value (j
, prop
[i
], 1)) < 0)
1187 ASET (font
, j
, make_number (n
));
1189 ASET (font
, FONT_ADSTYLE_INDEX
, prop
[XLFD_ADSTYLE_INDEX
]);
1190 val
= prop
[XLFD_REGISTRY_INDEX
];
1193 val
= prop
[XLFD_ENCODING_INDEX
];
1195 val
= concat2 (build_string ("*-"), SYMBOL_NAME (val
));
1197 else if (NILP (prop
[XLFD_ENCODING_INDEX
]))
1198 val
= concat2 (SYMBOL_NAME (val
), build_string ("-*"));
1200 val
= concat3 (SYMBOL_NAME (val
), build_string ("-"),
1201 SYMBOL_NAME (prop
[XLFD_ENCODING_INDEX
]));
1203 ASET (font
, FONT_REGISTRY_INDEX
, Fintern (val
, Qnil
));
1205 if (INTEGERP (prop
[XLFD_PIXEL_INDEX
]))
1206 ASET (font
, FONT_SIZE_INDEX
, prop
[XLFD_PIXEL_INDEX
]);
1207 else if (INTEGERP (prop
[XLFD_POINT_INDEX
]))
1209 double point_size
= XINT (prop
[XLFD_POINT_INDEX
]);
1211 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
/ 10));
1214 if (INTEGERP (prop
[XLFD_RESX_INDEX
]))
1215 ASET (font
, FONT_DPI_INDEX
, prop
[XLFD_RESY_INDEX
]);
1216 if (! NILP (prop
[XLFD_SPACING_INDEX
]))
1218 val
= font_prop_validate_spacing (QCspacing
,
1219 prop
[XLFD_SPACING_INDEX
]);
1220 if (! INTEGERP (val
))
1222 ASET (font
, FONT_SPACING_INDEX
, val
);
1224 if (INTEGERP (prop
[XLFD_AVGWIDTH_INDEX
]))
1225 ASET (font
, FONT_AVGWIDTH_INDEX
, prop
[XLFD_AVGWIDTH_INDEX
]);
1231 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1232 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1233 0, use PIXEL_SIZE instead. */
1236 font_unparse_xlfd (font
, pixel_size
, name
, nbytes
)
1242 char *f
[XLFD_REGISTRY_INDEX
+ 1];
1246 font_assert (FONTP (font
));
1248 for (i
= FONT_FOUNDRY_INDEX
, j
= XLFD_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
;
1251 if (i
== FONT_ADSTYLE_INDEX
)
1252 j
= XLFD_ADSTYLE_INDEX
;
1253 else if (i
== FONT_REGISTRY_INDEX
)
1254 j
= XLFD_REGISTRY_INDEX
;
1255 val
= AREF (font
, i
);
1258 if (j
== XLFD_REGISTRY_INDEX
)
1259 f
[j
] = "*-*", len
+= 4;
1261 f
[j
] = "*", len
+= 2;
1266 val
= SYMBOL_NAME (val
);
1267 if (j
== XLFD_REGISTRY_INDEX
1268 && ! strchr ((char *) SDATA (val
), '-'))
1270 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1271 if (SDATA (val
)[SBYTES (val
) - 1] == '*')
1273 f
[j
] = alloca (SBYTES (val
) + 3);
1274 sprintf (f
[j
], "%s-*", SDATA (val
));
1275 len
+= SBYTES (val
) + 3;
1279 f
[j
] = alloca (SBYTES (val
) + 4);
1280 sprintf (f
[j
], "%s*-*", SDATA (val
));
1281 len
+= SBYTES (val
) + 4;
1285 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1289 for (i
= FONT_WEIGHT_INDEX
, j
= XLFD_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
;
1292 val
= font_style_symbolic (font
, i
, 0);
1294 f
[j
] = "*", len
+= 2;
1297 val
= SYMBOL_NAME (val
);
1298 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1302 val
= AREF (font
, FONT_SIZE_INDEX
);
1303 font_assert (NUMBERP (val
) || NILP (val
));
1311 f
[XLFD_PIXEL_INDEX
] = alloca (22);
1312 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "%d-*", i
) + 1;
1315 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1317 else if (FLOATP (val
))
1319 i
= XFLOAT_DATA (val
) * 10;
1320 f
[XLFD_PIXEL_INDEX
] = alloca (12);
1321 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "*-%d", i
) + 1;
1324 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1326 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1328 i
= XINT (AREF (font
, FONT_DPI_INDEX
));
1329 f
[XLFD_RESX_INDEX
] = alloca (22);
1330 len
+= sprintf (f
[XLFD_RESX_INDEX
],
1334 f
[XLFD_RESX_INDEX
] = "*-*", len
+= 4;
1335 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1337 int spacing
= XINT (AREF (font
, FONT_SPACING_INDEX
));
1339 f
[XLFD_SPACING_INDEX
] = (spacing
<= FONT_SPACING_PROPORTIONAL
? "p"
1340 : spacing
<= FONT_SPACING_DUAL
? "d"
1341 : spacing
<= FONT_SPACING_MONO
? "m"
1346 f
[XLFD_SPACING_INDEX
] = "*", len
+= 2;
1347 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1349 f
[XLFD_AVGWIDTH_INDEX
] = alloca (11);
1350 len
+= sprintf (f
[XLFD_AVGWIDTH_INDEX
],
1351 "%d", XINT (AREF (font
, FONT_AVGWIDTH_INDEX
))) + 1;
1354 f
[XLFD_AVGWIDTH_INDEX
] = "*", len
+= 2;
1355 len
++; /* for terminating '\0'. */
1358 return sprintf (name
, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1359 f
[XLFD_FOUNDRY_INDEX
], f
[XLFD_FAMILY_INDEX
],
1360 f
[XLFD_WEIGHT_INDEX
], f
[XLFD_SLANT_INDEX
],
1361 f
[XLFD_SWIDTH_INDEX
], f
[XLFD_ADSTYLE_INDEX
],
1362 f
[XLFD_PIXEL_INDEX
], f
[XLFD_RESX_INDEX
],
1363 f
[XLFD_SPACING_INDEX
], f
[XLFD_AVGWIDTH_INDEX
],
1364 f
[XLFD_REGISTRY_INDEX
]);
1367 /* Parse NAME (null terminated) and store information in FONT
1368 (font-spec or font-entity). NAME is supplied in either the
1369 Fontconfig or GTK font name format. If NAME is successfully
1370 parsed, return 0. Otherwise return -1.
1372 The fontconfig format is
1374 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1378 FAMILY [PROPS...] [SIZE]
1380 This function tries to guess which format it is. */
1383 font_parse_fcname (name
, font
)
1388 char *size_beg
= NULL
, *size_end
= NULL
;
1389 char *props_beg
= NULL
, *family_end
= NULL
;
1390 int len
= strlen (name
);
1395 for (p
= name
; *p
; p
++)
1397 if (*p
== '\\' && p
[1])
1401 props_beg
= family_end
= p
;
1406 int decimal
= 0, size_found
= 1;
1407 for (q
= p
+ 1; *q
&& *q
!= ':'; q
++)
1410 if (*q
!= '.' || decimal
)
1429 /* A fontconfig name with size and/or property data. */
1430 if (family_end
> name
)
1433 family
= font_intern_prop (name
, family_end
- name
, 1);
1434 ASET (font
, FONT_FAMILY_INDEX
, family
);
1438 double point_size
= strtod (size_beg
, &size_end
);
1439 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1440 if (*size_end
== ':' && size_end
[1])
1441 props_beg
= size_end
;
1445 /* Now parse ":KEY=VAL" patterns. */
1448 for (p
= props_beg
; *p
; p
= q
)
1450 for (q
= p
+ 1; *q
&& *q
!= '=' && *q
!= ':'; q
++);
1453 /* Must be an enumerated value. */
1457 val
= font_intern_prop (p
, q
- p
, 1);
1459 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1461 if (PROP_MATCH ("light", 5)
1462 || PROP_MATCH ("medium", 6)
1463 || PROP_MATCH ("demibold", 8)
1464 || PROP_MATCH ("bold", 4)
1465 || PROP_MATCH ("black", 5))
1466 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, val
);
1467 else if (PROP_MATCH ("roman", 5)
1468 || PROP_MATCH ("italic", 6)
1469 || PROP_MATCH ("oblique", 7))
1470 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, val
);
1471 else if (PROP_MATCH ("charcell", 8))
1472 ASET (font
, FONT_SPACING_INDEX
,
1473 make_number (FONT_SPACING_CHARCELL
));
1474 else if (PROP_MATCH ("mono", 4))
1475 ASET (font
, FONT_SPACING_INDEX
,
1476 make_number (FONT_SPACING_MONO
));
1477 else if (PROP_MATCH ("proportional", 12))
1478 ASET (font
, FONT_SPACING_INDEX
,
1479 make_number (FONT_SPACING_PROPORTIONAL
));
1488 if (q
- p
== 10 && memcmp (p
+ 1, "pixelsize", 9) == 0)
1489 prop
= FONT_SIZE_INDEX
;
1492 key
= font_intern_prop (p
, q
- p
, 1);
1493 prop
= get_font_prop_index (key
);
1497 for (q
= p
; *q
&& *q
!= ':'; q
++);
1498 val
= font_intern_prop (p
, q
- p
, 0);
1500 if (prop
>= FONT_FOUNDRY_INDEX
1501 && prop
< FONT_EXTRA_INDEX
)
1502 ASET (font
, prop
, font_prop_validate (prop
, Qnil
, val
));
1504 Ffont_put (font
, key
, val
);
1512 /* Either a fontconfig-style name with no size and property
1513 data, or a GTK-style name. */
1515 int word_len
, prop_found
= 0;
1517 for (p
= name
; *p
; p
= *q
? q
+ 1 : q
)
1523 for (q
= p
+ 1; *q
&& *q
!= ' '; q
++)
1531 double point_size
= strtod (p
, &q
);
1532 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1537 for (q
= p
+ 1; *q
&& *q
!= ' '; q
++)
1538 if (*q
== '\\' && q
[1])
1542 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1544 if (PROP_MATCH ("Ultra-Light", 11))
1547 prop
= font_intern_prop ("ultra-light", 11, 1);
1548 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1550 else if (PROP_MATCH ("Light", 5))
1553 prop
= font_intern_prop ("light", 5, 1);
1554 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1556 else if (PROP_MATCH ("Semi-Bold", 9))
1559 prop
= font_intern_prop ("semi-bold", 9, 1);
1560 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1562 else if (PROP_MATCH ("Bold", 4))
1565 prop
= font_intern_prop ("bold", 4, 1);
1566 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1568 else if (PROP_MATCH ("Italic", 6))
1571 prop
= font_intern_prop ("italic", 4, 1);
1572 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, prop
);
1574 else if (PROP_MATCH ("Oblique", 7))
1577 prop
= font_intern_prop ("oblique", 7, 1);
1578 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, prop
);
1582 return -1; /* Unknown property in GTK-style font name. */
1591 family
= font_intern_prop (name
, family_end
- name
, 1);
1592 ASET (font
, FONT_FAMILY_INDEX
, family
);
1599 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1600 NAME (NBYTES length), and return the name length. If
1601 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1604 font_unparse_fcname (font
, pixel_size
, name
, nbytes
)
1610 Lisp_Object family
, foundry
;
1611 Lisp_Object tail
, val
;
1615 Lisp_Object styles
[3];
1616 char *style_names
[3] = { "weight", "slant", "width" };
1619 family
= AREF (font
, FONT_FAMILY_INDEX
);
1620 if (! NILP (family
))
1622 if (SYMBOLP (family
))
1624 family
= SYMBOL_NAME (family
);
1625 len
+= SBYTES (family
);
1631 val
= AREF (font
, FONT_SIZE_INDEX
);
1634 if (XINT (val
) != 0)
1635 pixel_size
= XINT (val
);
1637 len
+= 21; /* for ":pixelsize=NUM" */
1639 else if (FLOATP (val
))
1642 point_size
= (int) XFLOAT_DATA (val
);
1643 len
+= 11; /* for "-NUM" */
1646 foundry
= AREF (font
, FONT_FOUNDRY_INDEX
);
1647 if (! NILP (foundry
))
1649 if (SYMBOLP (foundry
))
1651 foundry
= SYMBOL_NAME (foundry
);
1652 len
+= 9 + SBYTES (foundry
); /* ":foundry=NAME" */
1658 for (i
= 0; i
< 3; i
++)
1660 styles
[i
] = font_style_symbolic (font
, FONT_WEIGHT_INDEX
+ i
, 0);
1661 if (! NILP (styles
[i
]))
1662 len
+= sprintf (work
, ":%s=%s", style_names
[i
],
1663 SDATA (SYMBOL_NAME (styles
[i
])));
1666 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1667 len
+= sprintf (work
, ":dpi=%d", XINT (AREF (font
, FONT_DPI_INDEX
)));
1668 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1669 len
+= strlen (":spacing=100");
1670 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1671 len
+= strlen (":scalable=false"); /* or ":scalable=true" */
1672 for (tail
= AREF (font
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
1674 Lisp_Object key
= XCAR (XCAR (tail
)), val
= XCDR (XCAR (tail
));
1676 len
+= SBYTES (SYMBOL_NAME (key
)) + 1; /* for :KEY= */
1678 len
+= SBYTES (val
);
1679 else if (INTEGERP (val
))
1680 len
+= sprintf (work
, "%d", XINT (val
));
1681 else if (SYMBOLP (val
))
1682 len
+= (NILP (val
) ? 5 : 4); /* for "false" or "true" */
1688 if (! NILP (family
))
1689 p
+= sprintf (p
, "%s", SDATA (family
));
1693 p
+= sprintf (p
, "%d", point_size
);
1695 p
+= sprintf (p
, "-%d", point_size
);
1697 else if (pixel_size
> 0)
1698 p
+= sprintf (p
, ":pixelsize=%d", pixel_size
);
1699 if (! NILP (AREF (font
, FONT_FOUNDRY_INDEX
)))
1700 p
+= sprintf (p
, ":foundry=%s",
1701 SDATA (SYMBOL_NAME (AREF (font
, FONT_FOUNDRY_INDEX
))));
1702 for (i
= 0; i
< 3; i
++)
1703 if (! NILP (styles
[i
]))
1704 p
+= sprintf (p
, ":%s=%s", style_names
[i
],
1705 SDATA (SYMBOL_NAME (styles
[i
])));
1706 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1707 p
+= sprintf (p
, ":dpi=%d", XINT (AREF (font
, FONT_DPI_INDEX
)));
1708 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1709 p
+= sprintf (p
, ":spacing=%d", XINT (AREF (font
, FONT_SPACING_INDEX
)));
1710 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1712 if (XINT (AREF (font
, FONT_AVGWIDTH_INDEX
)) == 0)
1713 p
+= sprintf (p
, ":scalable=true");
1715 p
+= sprintf (p
, ":scalable=false");
1720 /* Store GTK-style font name of FONT (font-spec or font-entity) in
1721 NAME (NBYTES length), and return the name length. F is the frame
1722 on which the font is displayed; it is used to calculate the point
1726 font_unparse_gtkname (font
, f
, name
, nbytes
)
1734 Lisp_Object family
, weight
, slant
, size
;
1735 int point_size
= -1;
1737 family
= AREF (font
, FONT_FAMILY_INDEX
);
1738 if (! NILP (family
))
1740 if (! SYMBOLP (family
))
1742 family
= SYMBOL_NAME (family
);
1743 len
+= SBYTES (family
);
1746 weight
= font_style_symbolic (font
, FONT_WEIGHT_INDEX
, 0);
1747 if (EQ (weight
, Qnormal
))
1749 else if (! NILP (weight
))
1751 weight
= SYMBOL_NAME (weight
);
1752 len
+= SBYTES (weight
);
1755 slant
= font_style_symbolic (font
, FONT_SLANT_INDEX
, 0);
1756 if (EQ (slant
, Qnormal
))
1758 else if (! NILP (slant
))
1760 slant
= SYMBOL_NAME (slant
);
1761 len
+= SBYTES (slant
);
1764 size
= AREF (font
, FONT_SIZE_INDEX
);
1765 /* Convert pixel size to point size. */
1766 if (INTEGERP (size
))
1768 Lisp_Object font_dpi
= AREF (font
, FONT_DPI_INDEX
);
1770 if (INTEGERP (font_dpi
))
1771 dpi
= XINT (font_dpi
);
1774 point_size
= PIXEL_TO_POINT (XINT (size
), dpi
);
1777 else if (FLOATP (size
))
1779 point_size
= (int) XFLOAT_DATA (size
);
1786 p
= name
+ sprintf (name
, "%s", SDATA (family
));
1788 if (! NILP (weight
))
1791 p
+= sprintf (p
, " %s", SDATA (weight
));
1792 q
[1] = toupper (q
[1]);
1798 p
+= sprintf (p
, " %s", SDATA (slant
));
1799 q
[1] = toupper (q
[1]);
1803 p
+= sprintf (p
, " %d", point_size
);
1808 /* Parse NAME (null terminated) and store information in FONT
1809 (font-spec or font-entity). If NAME is successfully parsed, return
1810 0. Otherwise return -1. */
1813 font_parse_name (name
, font
)
1817 if (name
[0] == '-' || index (name
, '*'))
1818 return font_parse_xlfd (name
, font
);
1819 return font_parse_fcname (name
, font
);
1823 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1824 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1828 font_parse_family_registry (family
, registry
, font_spec
)
1829 Lisp_Object family
, registry
, font_spec
;
1835 && NILP (AREF (font_spec
, FONT_FAMILY_INDEX
)))
1837 CHECK_STRING (family
);
1838 len
= SBYTES (family
);
1839 p0
= (char *) SDATA (family
);
1840 p1
= index (p0
, '-');
1843 if ((*p0
!= '*' || p1
- p0
> 1)
1844 && NILP (AREF (font_spec
, FONT_FOUNDRY_INDEX
)))
1845 Ffont_put (font_spec
, QCfoundry
, font_intern_prop (p0
, p1
- p0
, 1));
1848 Ffont_put (font_spec
, QCfamily
, font_intern_prop (p1
, len
, 1));
1851 ASET (font_spec
, FONT_FAMILY_INDEX
, Fintern (family
, Qnil
));
1853 if (! NILP (registry
))
1855 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1856 CHECK_STRING (registry
);
1857 len
= SBYTES (registry
);
1858 p0
= (char *) SDATA (registry
);
1859 p1
= index (p0
, '-');
1862 if (SDATA (registry
)[len
- 1] == '*')
1863 registry
= concat2 (registry
, build_string ("-*"));
1865 registry
= concat2 (registry
, build_string ("*-*"));
1867 registry
= Fdowncase (registry
);
1868 ASET (font_spec
, FONT_REGISTRY_INDEX
, Fintern (registry
, Qnil
));
1873 /* This part (through the next ^L) is still experimental and not
1874 tested much. We may drastically change codes. */
1880 #define LGSTRING_HEADER_SIZE 6
1881 #define LGSTRING_GLYPH_SIZE 8
1884 check_gstring (gstring
)
1885 Lisp_Object gstring
;
1890 CHECK_VECTOR (gstring
);
1891 val
= AREF (gstring
, 0);
1893 if (ASIZE (val
) < LGSTRING_HEADER_SIZE
)
1895 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring
));
1896 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
)))
1897 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
));
1898 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
)))
1899 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
));
1900 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
)))
1901 CHECK_NATNUM (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
));
1902 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1903 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1904 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1905 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1907 for (i
= 0; i
< LGSTRING_GLYPH_LEN (gstring
); i
++)
1909 val
= LGSTRING_GLYPH (gstring
, i
);
1911 if (ASIZE (val
) < LGSTRING_GLYPH_SIZE
)
1913 if (NILP (AREF (val
, LGLYPH_IX_CHAR
)))
1915 CHECK_NATNUM (AREF (val
, LGLYPH_IX_FROM
));
1916 CHECK_NATNUM (AREF (val
, LGLYPH_IX_TO
));
1917 CHECK_CHARACTER (AREF (val
, LGLYPH_IX_CHAR
));
1918 if (!NILP (AREF (val
, LGLYPH_IX_CODE
)))
1919 CHECK_NATNUM (AREF (val
, LGLYPH_IX_CODE
));
1920 if (!NILP (AREF (val
, LGLYPH_IX_WIDTH
)))
1921 CHECK_NATNUM (AREF (val
, LGLYPH_IX_WIDTH
));
1922 if (!NILP (AREF (val
, LGLYPH_IX_ADJUSTMENT
)))
1924 val
= AREF (val
, LGLYPH_IX_ADJUSTMENT
);
1926 if (ASIZE (val
) < 3)
1928 for (j
= 0; j
< 3; j
++)
1929 CHECK_NUMBER (AREF (val
, j
));
1934 error ("Invalid glyph-string format");
1939 check_otf_features (otf_features
)
1940 Lisp_Object otf_features
;
1944 CHECK_CONS (otf_features
);
1945 CHECK_SYMBOL (XCAR (otf_features
));
1946 otf_features
= XCDR (otf_features
);
1947 CHECK_CONS (otf_features
);
1948 CHECK_SYMBOL (XCAR (otf_features
));
1949 otf_features
= XCDR (otf_features
);
1950 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1952 CHECK_SYMBOL (Fcar (val
));
1953 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1954 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val
)));
1956 otf_features
= XCDR (otf_features
);
1957 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1959 CHECK_SYMBOL (Fcar (val
));
1960 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1961 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val
)));
1968 Lisp_Object otf_list
;
1971 otf_tag_symbol (tag
)
1976 OTF_tag_name (tag
, name
);
1977 return Fintern (make_unibyte_string (name
, 4), Qnil
);
1984 Lisp_Object val
= Fassoc (file
, otf_list
);
1988 otf
= XSAVE_VALUE (XCDR (val
))->pointer
;
1991 otf
= STRINGP (file
) ? OTF_open ((char *) SDATA (file
)) : NULL
;
1992 val
= make_save_value (otf
, 0);
1993 otf_list
= Fcons (Fcons (file
, val
), otf_list
);
1999 /* Return a list describing which scripts/languages FONT supports by
2000 which GSUB/GPOS features of OpenType tables. See the comment of
2001 (struct font_driver).otf_capability. */
2004 font_otf_capability (font
)
2008 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
2011 otf
= otf_open (font
->props
[FONT_FILE_INDEX
]);
2014 for (i
= 0; i
< 2; i
++)
2016 OTF_GSUB_GPOS
*gsub_gpos
;
2017 Lisp_Object script_list
= Qnil
;
2020 if (OTF_get_features (otf
, i
== 0) < 0)
2022 gsub_gpos
= i
== 0 ? otf
->gsub
: otf
->gpos
;
2023 for (j
= gsub_gpos
->ScriptList
.ScriptCount
- 1; j
>= 0; j
--)
2025 OTF_Script
*script
= gsub_gpos
->ScriptList
.Script
+ j
;
2026 Lisp_Object langsys_list
= Qnil
;
2027 Lisp_Object script_tag
= otf_tag_symbol (script
->ScriptTag
);
2030 for (k
= script
->LangSysCount
; k
>= 0; k
--)
2032 OTF_LangSys
*langsys
;
2033 Lisp_Object feature_list
= Qnil
;
2034 Lisp_Object langsys_tag
;
2037 if (k
== script
->LangSysCount
)
2039 langsys
= &script
->DefaultLangSys
;
2044 langsys
= script
->LangSys
+ k
;
2046 = otf_tag_symbol (script
->LangSysRecord
[k
].LangSysTag
);
2048 for (l
= langsys
->FeatureCount
- 1; l
>= 0; l
--)
2050 OTF_Feature
*feature
2051 = gsub_gpos
->FeatureList
.Feature
+ langsys
->FeatureIndex
[l
];
2052 Lisp_Object feature_tag
2053 = otf_tag_symbol (feature
->FeatureTag
);
2055 feature_list
= Fcons (feature_tag
, feature_list
);
2057 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
2060 script_list
= Fcons (Fcons (script_tag
, langsys_list
),
2065 XSETCAR (capability
, script_list
);
2067 XSETCDR (capability
, script_list
);
2073 /* Parse OTF features in SPEC and write a proper features spec string
2074 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
2075 assured that the sufficient memory has already allocated for
2079 generate_otf_features (spec
, features
)
2089 for (asterisk
= 0; CONSP (spec
); spec
= XCDR (spec
))
2095 if (SREF (SYMBOL_NAME (val
), 0) == '*')
2100 else if (! asterisk
)
2102 val
= SYMBOL_NAME (val
);
2103 p
+= sprintf (p
, "%s", SDATA (val
));
2107 val
= SYMBOL_NAME (val
);
2108 p
+= sprintf (p
, "~%s", SDATA (val
));
2112 error ("OTF spec too long");
2116 font_otf_DeviceTable (device_table
)
2117 OTF_DeviceTable
*device_table
;
2119 int len
= device_table
->StartSize
- device_table
->EndSize
+ 1;
2121 return Fcons (make_number (len
),
2122 make_unibyte_string (device_table
->DeltaValue
, len
));
2126 font_otf_ValueRecord (value_format
, value_record
)
2128 OTF_ValueRecord
*value_record
;
2130 Lisp_Object val
= Fmake_vector (make_number (8), Qnil
);
2132 if (value_format
& OTF_XPlacement
)
2133 ASET (val
, 0, make_number (value_record
->XPlacement
));
2134 if (value_format
& OTF_YPlacement
)
2135 ASET (val
, 1, make_number (value_record
->YPlacement
));
2136 if (value_format
& OTF_XAdvance
)
2137 ASET (val
, 2, make_number (value_record
->XAdvance
));
2138 if (value_format
& OTF_YAdvance
)
2139 ASET (val
, 3, make_number (value_record
->YAdvance
));
2140 if (value_format
& OTF_XPlaDevice
)
2141 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XPlaDevice
));
2142 if (value_format
& OTF_YPlaDevice
)
2143 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YPlaDevice
));
2144 if (value_format
& OTF_XAdvDevice
)
2145 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XAdvDevice
));
2146 if (value_format
& OTF_YAdvDevice
)
2147 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YAdvDevice
));
2152 font_otf_Anchor (anchor
)
2157 val
= Fmake_vector (make_number (anchor
->AnchorFormat
+ 1), Qnil
);
2158 ASET (val
, 0, make_number (anchor
->XCoordinate
));
2159 ASET (val
, 1, make_number (anchor
->YCoordinate
));
2160 if (anchor
->AnchorFormat
== 2)
2161 ASET (val
, 2, make_number (anchor
->f
.f1
.AnchorPoint
));
2164 ASET (val
, 3, font_otf_DeviceTable (&anchor
->f
.f2
.XDeviceTable
));
2165 ASET (val
, 4, font_otf_DeviceTable (&anchor
->f
.f2
.YDeviceTable
));
2169 #endif /* HAVE_LIBOTF */
2175 static unsigned font_score
P_ ((Lisp_Object
, Lisp_Object
*));
2176 static int font_compare
P_ ((const void *, const void *));
2177 static Lisp_Object font_sort_entites
P_ ((Lisp_Object
, Lisp_Object
,
2180 /* Return a rescaling ratio of FONT_ENTITY. */
2181 extern Lisp_Object Vface_font_rescale_alist
;
2184 font_rescale_ratio (font_entity
)
2185 Lisp_Object font_entity
;
2187 Lisp_Object tail
, elt
;
2188 Lisp_Object name
= Qnil
;
2190 for (tail
= Vface_font_rescale_alist
; CONSP (tail
); tail
= XCDR (tail
))
2193 if (FLOATP (XCDR (elt
)))
2195 if (STRINGP (XCAR (elt
)))
2198 name
= Ffont_xlfd_name (font_entity
, Qnil
);
2199 if (fast_string_match_ignore_case (XCAR (elt
), name
) >= 0)
2200 return XFLOAT_DATA (XCDR (elt
));
2202 else if (FONT_SPEC_P (XCAR (elt
)))
2204 if (font_match_p (XCAR (elt
), font_entity
))
2205 return XFLOAT_DATA (XCDR (elt
));
2212 /* We sort fonts by scoring each of them against a specified
2213 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2214 the value is, the closer the font is to the font-spec.
2216 The lowest 2 bits of the score is used for driver type. The font
2217 available by the most preferred font driver is 0.
2219 Each 7-bit in the higher 28 bits are used for numeric properties
2220 WEIGHT, SLANT, WIDTH, and SIZE. */
2222 /* How many bits to shift to store the difference value of each font
2223 property in a score. Note that flots for FONT_TYPE_INDEX and
2224 FONT_REGISTRY_INDEX are not used. */
2225 static int sort_shift_bits
[FONT_SIZE_INDEX
+ 1];
2227 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2228 The return value indicates how different ENTITY is compared with
2232 font_score (entity
, spec_prop
)
2233 Lisp_Object entity
, *spec_prop
;
2238 /* Score three style numeric fields. Maximum difference is 127. */
2239 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
; i
++)
2240 if (! NILP (spec_prop
[i
]) && ! EQ (AREF (entity
, i
), spec_prop
[i
]))
2242 int diff
= (XINT (AREF (entity
, i
)) >> 8) - (XINT (spec_prop
[i
]) >> 8);
2247 score
|= min (diff
, 127) << sort_shift_bits
[i
];
2250 /* Score the size. Maximum difference is 127. */
2251 i
= FONT_SIZE_INDEX
;
2252 if (! NILP (spec_prop
[FONT_SIZE_INDEX
])
2253 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2255 /* We use the higher 6-bit for the actual size difference. The
2256 lowest bit is set if the DPI is different. */
2258 int pixel_size
= XINT (spec_prop
[FONT_SIZE_INDEX
]);
2260 if (CONSP (Vface_font_rescale_alist
))
2261 pixel_size
*= font_rescale_ratio (entity
);
2262 diff
= pixel_size
- XINT (AREF (entity
, FONT_SIZE_INDEX
));
2266 if (! NILP (spec_prop
[FONT_DPI_INDEX
])
2267 && ! EQ (spec_prop
[FONT_DPI_INDEX
], AREF (entity
, FONT_DPI_INDEX
)))
2269 score
|= min (diff
, 127) << sort_shift_bits
[FONT_SIZE_INDEX
];
2276 /* The comparison function for qsort. */
2279 font_compare (d1
, d2
)
2280 const void *d1
, *d2
;
2282 return (*(unsigned *) d1
- *(unsigned *) d2
);
2286 /* The structure for elements being sorted by qsort. */
2287 struct font_sort_data
2294 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2295 If PREFER specifies a point-size, calculate the corresponding
2296 pixel-size from QCdpi property of PREFER or from the Y-resolution
2297 of FRAME before sorting.
2299 If BEST-ONLY is nonzero, return the best matching entity. Otherwise,
2300 return the sorted VEC. */
2303 font_sort_entites (vec
, prefer
, frame
, best_only
)
2304 Lisp_Object vec
, prefer
, frame
;
2307 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2309 struct font_sort_data
*data
;
2310 unsigned best_score
;
2311 Lisp_Object best_entity
, driver_type
;
2313 struct frame
*f
= XFRAME (frame
);
2314 struct font_driver_list
*list
;
2319 return best_only
? AREF (vec
, 0) : vec
;
2321 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_DPI_INDEX
; i
++)
2322 prefer_prop
[i
] = AREF (prefer
, i
);
2323 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2324 prefer_prop
[FONT_SIZE_INDEX
]
2325 = make_number (font_pixel_size (XFRAME (frame
), prefer
));
2327 /* Scoring and sorting. */
2328 SAFE_ALLOCA (data
, struct font_sort_data
*, (sizeof *data
) * len
);
2329 best_score
= 0xFFFFFFFF;
2330 /* We are sure that the length of VEC > 1. */
2331 driver_type
= AREF (AREF (vec
, 0), FONT_TYPE_INDEX
);
2332 for (driver_order
= 0, list
= f
->font_driver_list
; list
;
2333 driver_order
++, list
= list
->next
)
2334 if (EQ (driver_type
, list
->driver
->type
))
2336 best_entity
= data
[0].entity
= AREF (vec
, 0);
2337 best_score
= data
[0].score
2338 = font_score (data
[0].entity
, prefer_prop
) | driver_order
;
2339 for (i
= 0; i
< len
; i
++)
2341 if (!EQ (driver_type
, AREF (AREF (vec
, i
), FONT_TYPE_INDEX
)))
2342 for (driver_order
= 0, list
= f
->font_driver_list
; list
;
2343 driver_order
++, list
= list
->next
)
2344 if (EQ (driver_type
, list
->driver
->type
))
2346 data
[i
].entity
= AREF (vec
, i
);
2347 data
[i
].score
= font_score (data
[i
].entity
, prefer_prop
) | driver_order
;
2348 if (best_only
&& best_score
> data
[i
].score
)
2350 best_score
= data
[i
].score
;
2351 best_entity
= data
[i
].entity
;
2352 if (best_score
== 0)
2358 qsort (data
, len
, sizeof *data
, font_compare
);
2359 for (i
= 0; i
< len
; i
++)
2360 ASET (vec
, i
, data
[i
].entity
);
2366 font_add_log ("sort-by", prefer
, vec
);
2371 /* API of Font Service Layer. */
2373 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2374 sort_shift_bits. Finternal_set_font_selection_order calls this
2375 function with font_sort_order after setting up it. */
2378 font_update_sort_order (order
)
2383 for (i
= 0, shift_bits
= 23; i
< 4; i
++, shift_bits
-= 7)
2385 int xlfd_idx
= order
[i
];
2387 if (xlfd_idx
== XLFD_WEIGHT_INDEX
)
2388 sort_shift_bits
[FONT_WEIGHT_INDEX
] = shift_bits
;
2389 else if (xlfd_idx
== XLFD_SLANT_INDEX
)
2390 sort_shift_bits
[FONT_SLANT_INDEX
] = shift_bits
;
2391 else if (xlfd_idx
== XLFD_SWIDTH_INDEX
)
2392 sort_shift_bits
[FONT_WIDTH_INDEX
] = shift_bits
;
2394 sort_shift_bits
[FONT_SIZE_INDEX
] = shift_bits
;
2399 font_check_otf_features (script
, langsys
, features
, table
)
2400 Lisp_Object script
, langsys
, features
, table
;
2405 table
= assq_no_quit (script
, table
);
2408 table
= XCDR (table
);
2409 if (! NILP (langsys
))
2411 table
= assq_no_quit (langsys
, table
);
2417 val
= assq_no_quit (Qnil
, table
);
2419 table
= XCAR (table
);
2423 table
= XCDR (table
);
2424 for (negative
= 0; CONSP (features
); features
= XCDR (features
))
2426 if (NILP (XCAR (features
)))
2428 if (NILP (Fmemq (XCAR (features
), table
)) != negative
)
2434 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2437 font_check_otf (Lisp_Object spec
, Lisp_Object otf_capability
)
2439 Lisp_Object script
, langsys
= Qnil
, gsub
= Qnil
, gpos
= Qnil
;
2441 script
= XCAR (spec
);
2445 langsys
= XCAR (spec
);
2456 if (! NILP (gsub
) && ! font_check_otf_features (script
, langsys
, gsub
,
2457 XCAR (otf_capability
)))
2459 if (! NILP (gpos
) && ! font_check_otf_features (script
, langsys
, gpos
,
2460 XCDR (otf_capability
)))
2467 /* Check if FONT (font-entity or font-object) matches with the font
2468 specification SPEC. */
2471 font_match_p (spec
, font
)
2472 Lisp_Object spec
, font
;
2474 Lisp_Object prop
[FONT_SPEC_MAX
], *props
;
2475 Lisp_Object extra
, font_extra
;
2478 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2479 if (! NILP (AREF (spec
, i
))
2480 && ! NILP (AREF (font
, i
))
2481 && ! EQ (AREF (spec
, i
), AREF (font
, i
)))
2483 props
= XFONT_SPEC (spec
)->props
;
2484 if (FLOATP (props
[FONT_SIZE_INDEX
]))
2486 for (i
= FONT_FOUNDRY_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2487 prop
[i
] = AREF (spec
, i
);
2488 prop
[FONT_SIZE_INDEX
]
2489 = make_number (font_pixel_size (XFRAME (selected_frame
), spec
));
2493 if (font_score (font
, props
) > 0)
2495 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
2496 font_extra
= AREF (font
, FONT_EXTRA_INDEX
);
2497 for (; CONSP (extra
); extra
= XCDR (extra
))
2499 Lisp_Object key
= XCAR (XCAR (extra
));
2500 Lisp_Object val
= XCDR (XCAR (extra
)), val2
;
2502 if (EQ (key
, QClang
))
2504 val2
= assq_no_quit (key
, font_extra
);
2513 if (NILP (Fmemq (val
, val2
)))
2518 ? NILP (Fmemq (val
, XCDR (val2
)))
2522 else if (EQ (key
, QCscript
))
2524 val2
= assq_no_quit (val
, Vscript_representative_chars
);
2530 /* All characters in the list must be supported. */
2531 for (; CONSP (val2
); val2
= XCDR (val2
))
2533 if (! NATNUMP (XCAR (val2
)))
2535 if (font_encode_char (font
, XFASTINT (XCAR (val2
)))
2536 == FONT_INVALID_CODE
)
2540 else if (VECTORP (val2
))
2542 /* At most one character in the vector must be supported. */
2543 for (i
= 0; i
< ASIZE (val2
); i
++)
2545 if (! NATNUMP (AREF (val2
, i
)))
2547 if (font_encode_char (font
, XFASTINT (AREF (val2
, i
)))
2548 != FONT_INVALID_CODE
)
2551 if (i
== ASIZE (val2
))
2556 else if (EQ (key
, QCotf
))
2560 if (! FONT_OBJECT_P (font
))
2562 fontp
= XFONT_OBJECT (font
);
2563 if (! fontp
->driver
->otf_capability
)
2565 val2
= fontp
->driver
->otf_capability (fontp
);
2566 if (NILP (val2
) || ! font_check_otf (val
, val2
))
2577 Each font backend has the callback function get_cache, and it
2578 returns a cons cell of which cdr part can be freely used for
2579 caching fonts. The cons cell may be shared by multiple frames
2580 and/or multiple font drivers. So, we arrange the cdr part as this:
2582 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2584 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2585 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2586 cons (FONT-SPEC FONT-ENTITY ...). */
2588 static void font_prepare_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2589 static void font_finish_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2590 static Lisp_Object font_get_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2591 static void font_clear_cache
P_ ((FRAME_PTR
, Lisp_Object
,
2592 struct font_driver
*));
2595 font_prepare_cache (f
, driver
)
2597 struct font_driver
*driver
;
2599 Lisp_Object cache
, val
;
2601 cache
= driver
->get_cache (f
);
2603 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2607 val
= Fcons (driver
->type
, Fcons (make_number (1), Qnil
));
2608 XSETCDR (cache
, Fcons (val
, XCDR (cache
)));
2612 val
= XCDR (XCAR (val
));
2613 XSETCAR (val
, make_number (XINT (XCAR (val
)) + 1));
2619 font_finish_cache (f
, driver
)
2621 struct font_driver
*driver
;
2623 Lisp_Object cache
, val
, tmp
;
2626 cache
= driver
->get_cache (f
);
2628 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2629 cache
= val
, val
= XCDR (val
);
2630 font_assert (! NILP (val
));
2631 tmp
= XCDR (XCAR (val
));
2632 XSETCAR (tmp
, make_number (XINT (XCAR (tmp
)) - 1));
2633 if (XINT (XCAR (tmp
)) == 0)
2635 font_clear_cache (f
, XCAR (val
), driver
);
2636 XSETCDR (cache
, XCDR (val
));
2642 font_get_cache (f
, driver
)
2644 struct font_driver
*driver
;
2646 Lisp_Object val
= driver
->get_cache (f
);
2647 Lisp_Object type
= driver
->type
;
2649 font_assert (CONSP (val
));
2650 for (val
= XCDR (val
); ! EQ (XCAR (XCAR (val
)), type
); val
= XCDR (val
));
2651 font_assert (CONSP (val
));
2652 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2653 val
= XCDR (XCAR (val
));
2657 static int num_fonts
;
2660 font_clear_cache (f
, cache
, driver
)
2663 struct font_driver
*driver
;
2665 Lisp_Object tail
, elt
;
2666 Lisp_Object tail2
, entity
;
2668 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2669 for (tail
= XCDR (XCDR (cache
)); CONSP (tail
); tail
= XCDR (tail
))
2672 /* elt should have the form (FONT-SPEC FONT-ENTITY ...) */
2673 if (CONSP (elt
) && FONT_SPEC_P (XCAR (elt
)))
2675 for (tail2
= XCDR (elt
); CONSP (tail2
); tail2
= XCDR (tail2
))
2677 entity
= XCAR (tail2
);
2679 if (FONT_ENTITY_P (entity
)
2680 && EQ (driver
->type
, AREF (entity
, FONT_TYPE_INDEX
)))
2682 Lisp_Object objlist
= AREF (entity
, FONT_OBJLIST_INDEX
);
2684 for (; CONSP (objlist
); objlist
= XCDR (objlist
))
2686 Lisp_Object val
= XCAR (objlist
);
2687 struct font
*font
= XFONT_OBJECT (val
);
2689 if (! NILP (AREF (val
, FONT_TYPE_INDEX
)))
2691 font_assert (font
&& driver
== font
->driver
);
2692 driver
->close (f
, font
);
2696 if (driver
->free_entity
)
2697 driver
->free_entity (entity
);
2702 XSETCDR (cache
, Qnil
);
2706 static Lisp_Object scratch_font_spec
, scratch_font_prefer
;
2709 font_delete_unmatched (list
, spec
, size
)
2710 Lisp_Object list
, spec
;
2713 Lisp_Object entity
, val
;
2714 enum font_property_index prop
;
2716 for (val
= Qnil
; CONSP (list
); list
= XCDR (list
))
2718 entity
= XCAR (list
);
2719 for (prop
= FONT_WEIGHT_INDEX
; prop
< FONT_SIZE_INDEX
; prop
++)
2720 if (INTEGERP (AREF (spec
, prop
))
2721 && ((XINT (AREF (spec
, prop
)) >> 8)
2722 != (XINT (AREF (entity
, prop
)) >> 8)))
2723 prop
= FONT_SPEC_MAX
;
2724 if (prop
< FONT_SPEC_MAX
2726 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2728 int diff
= XINT (AREF (entity
, FONT_SIZE_INDEX
)) - size
;
2731 && (diff
< 0 ? -diff
> FONT_PIXEL_SIZE_QUANTUM
2732 : diff
> FONT_PIXEL_SIZE_QUANTUM
))
2733 prop
= FONT_SPEC_MAX
;
2735 if (prop
< FONT_SPEC_MAX
2736 && INTEGERP (AREF (spec
, FONT_DPI_INDEX
))
2737 && INTEGERP (AREF (entity
, FONT_DPI_INDEX
))
2738 && XINT (AREF (entity
, FONT_DPI_INDEX
)) != 0
2739 && ! EQ (AREF (spec
, FONT_DPI_INDEX
), AREF (entity
, FONT_DPI_INDEX
)))
2740 prop
= FONT_SPEC_MAX
;
2741 if (prop
< FONT_SPEC_MAX
2742 && INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
2743 && INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
2744 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) != 0
2745 && ! EQ (AREF (spec
, FONT_AVGWIDTH_INDEX
),
2746 AREF (entity
, FONT_AVGWIDTH_INDEX
)))
2747 prop
= FONT_SPEC_MAX
;
2748 if (prop
< FONT_SPEC_MAX
)
2749 val
= Fcons (entity
, val
);
2755 /* Return a vector of font-entities matching with SPEC on FRAME. */
2758 font_list_entities (frame
, spec
)
2759 Lisp_Object frame
, spec
;
2761 FRAME_PTR f
= XFRAME (frame
);
2762 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2763 Lisp_Object ftype
, val
;
2766 int need_filtering
= 0;
2769 font_assert (FONT_SPEC_P (spec
));
2771 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2772 size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
2773 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
2774 size
= font_pixel_size (f
, spec
);
2778 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2779 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2780 ASET (scratch_font_spec
, i
, AREF (spec
, i
));
2781 for (i
= FONT_WEIGHT_INDEX
; i
< FONT_EXTRA_INDEX
; i
++)
2783 ASET (scratch_font_spec
, i
, Qnil
);
2784 if (! NILP (AREF (spec
, i
)))
2786 if (i
== FONT_DPI_INDEX
)
2787 /* Skip FONT_SPACING_INDEX */
2790 ASET (scratch_font_spec
, FONT_SPACING_INDEX
, AREF (spec
, FONT_SPACING_INDEX
));
2791 ASET (scratch_font_spec
, FONT_EXTRA_INDEX
, AREF (spec
, FONT_EXTRA_INDEX
));
2793 vec
= alloca (sizeof (Lisp_Object
) * num_font_drivers
);
2797 for (i
= 0; driver_list
; driver_list
= driver_list
->next
)
2799 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2801 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2803 ASET (scratch_font_spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2804 val
= assoc_no_quit (scratch_font_spec
, XCDR (cache
));
2811 val
= driver_list
->driver
->list (frame
, scratch_font_spec
);
2812 copy
= Fcopy_font_spec (scratch_font_spec
);
2813 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2814 XSETCDR (cache
, Fcons (Fcons (copy
, val
), XCDR (cache
)));
2816 if (! NILP (val
) && need_filtering
)
2817 val
= font_delete_unmatched (val
, spec
, size
);
2822 val
= (i
> 0 ? Fvconcat (i
, vec
) : null_vector
);
2823 font_add_log ("list", spec
, val
);
2828 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2829 nil, is an array of face's attributes, which specifies preferred
2830 font-related attributes. */
2833 font_matching_entity (f
, attrs
, spec
)
2835 Lisp_Object
*attrs
, spec
;
2837 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2838 Lisp_Object ftype
, size
, entity
;
2840 Lisp_Object work
= Fcopy_font_spec (spec
);
2842 XSETFRAME (frame
, f
);
2843 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2844 size
= AREF (spec
, FONT_SIZE_INDEX
);
2847 ASET (work
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2848 FONT_SET_STYLE (work
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
2849 FONT_SET_STYLE (work
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
2850 FONT_SET_STYLE (work
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
2853 for (; driver_list
; driver_list
= driver_list
->next
)
2855 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2857 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2860 ASET (work
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2861 entity
= assoc_no_quit (work
, XCDR (cache
));
2863 entity
= XCDR (entity
);
2866 entity
= driver_list
->driver
->match (frame
, work
);
2867 copy
= Fcopy_font_spec (work
);
2868 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2869 XSETCDR (cache
, Fcons (Fcons (copy
, entity
), XCDR (cache
)));
2871 if (! NILP (entity
))
2874 font_add_log ("match", work
, entity
);
2879 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2880 opened font object. */
2883 font_open_entity (f
, entity
, pixel_size
)
2888 struct font_driver_list
*driver_list
;
2889 Lisp_Object objlist
, size
, val
, font_object
;
2891 int min_width
, height
;
2892 int scaled_pixel_size
;
2894 font_assert (FONT_ENTITY_P (entity
));
2895 size
= AREF (entity
, FONT_SIZE_INDEX
);
2896 if (XINT (size
) != 0)
2897 scaled_pixel_size
= pixel_size
= XINT (size
);
2898 else if (CONSP (Vface_font_rescale_alist
))
2899 scaled_pixel_size
= pixel_size
* font_rescale_ratio (entity
);
2901 for (objlist
= AREF (entity
, FONT_OBJLIST_INDEX
); CONSP (objlist
);
2902 objlist
= XCDR (objlist
))
2903 if (! NILP (AREF (XCAR (objlist
), FONT_TYPE_INDEX
))
2904 && XFONT_OBJECT (XCAR (objlist
))->pixel_size
== pixel_size
)
2905 return XCAR (objlist
);
2907 val
= AREF (entity
, FONT_TYPE_INDEX
);
2908 for (driver_list
= f
->font_driver_list
;
2909 driver_list
&& ! EQ (driver_list
->driver
->type
, val
);
2910 driver_list
= driver_list
->next
);
2914 font_object
= driver_list
->driver
->open (f
, entity
, scaled_pixel_size
);
2915 ASET (font_object
, FONT_SIZE_INDEX
, make_number (pixel_size
));
2916 font_add_log ("open", entity
, font_object
);
2917 if (NILP (font_object
))
2919 ASET (entity
, FONT_OBJLIST_INDEX
,
2920 Fcons (font_object
, AREF (entity
, FONT_OBJLIST_INDEX
)));
2921 ASET (font_object
, FONT_OBJLIST_INDEX
, Qnil
);
2924 font
= XFONT_OBJECT (font_object
);
2925 min_width
= (font
->min_width
? font
->min_width
2926 : font
->average_width
? font
->average_width
2927 : font
->space_width
? font
->space_width
2929 height
= (font
->height
? font
->height
: 1);
2930 #ifdef HAVE_WINDOW_SYSTEM
2931 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
2932 if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
== 1)
2934 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
;
2935 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
;
2936 fonts_changed_p
= 1;
2940 if (FRAME_SMALLEST_CHAR_WIDTH (f
) > min_width
)
2941 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
, fonts_changed_p
= 1;
2942 if (FRAME_SMALLEST_FONT_HEIGHT (f
) > height
)
2943 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
, fonts_changed_p
= 1;
2951 /* Close FONT_OBJECT that is opened on frame F. */
2954 font_close_object (f
, font_object
)
2956 Lisp_Object font_object
;
2958 struct font
*font
= XFONT_OBJECT (font_object
);
2960 if (NILP (AREF (font_object
, FONT_TYPE_INDEX
)))
2961 /* Already closed. */
2963 font_add_log ("close", font_object
, Qnil
);
2964 font
->driver
->close (f
, font
);
2965 #ifdef HAVE_WINDOW_SYSTEM
2966 font_assert (FRAME_X_DISPLAY_INFO (f
)->n_fonts
);
2967 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
2973 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2974 FONT is a font-entity and it must be opened to check. */
2977 font_has_char (f
, font
, c
)
2984 if (FONT_ENTITY_P (font
))
2986 Lisp_Object type
= AREF (font
, FONT_TYPE_INDEX
);
2987 struct font_driver_list
*driver_list
;
2989 for (driver_list
= f
->font_driver_list
;
2990 driver_list
&& ! EQ (driver_list
->driver
->type
, type
);
2991 driver_list
= driver_list
->next
);
2994 if (! driver_list
->driver
->has_char
)
2996 return driver_list
->driver
->has_char (font
, c
);
2999 font_assert (FONT_OBJECT_P (font
));
3000 fontp
= XFONT_OBJECT (font
);
3001 if (fontp
->driver
->has_char
)
3003 int result
= fontp
->driver
->has_char (font
, c
);
3008 return (fontp
->driver
->encode_char (fontp
, c
) != FONT_INVALID_CODE
);
3012 /* Return the glyph ID of FONT_OBJECT for character C. */
3015 font_encode_char (font_object
, c
)
3016 Lisp_Object font_object
;
3021 font_assert (FONT_OBJECT_P (font_object
));
3022 font
= XFONT_OBJECT (font_object
);
3023 return font
->driver
->encode_char (font
, c
);
3027 /* Return the name of FONT_OBJECT. */
3030 font_get_name (font_object
)
3031 Lisp_Object font_object
;
3033 font_assert (FONT_OBJECT_P (font_object
));
3034 return AREF (font_object
, FONT_NAME_INDEX
);
3038 /* Return the specification of FONT_OBJECT. */
3041 font_get_spec (font_object
)
3042 Lisp_Object font_object
;
3044 Lisp_Object spec
= font_make_spec ();
3047 for (i
= 0; i
< FONT_SIZE_INDEX
; i
++)
3048 ASET (spec
, i
, AREF (font_object
, i
));
3049 ASET (spec
, FONT_SIZE_INDEX
,
3050 make_number (XFONT_OBJECT (font_object
)->pixel_size
));
3055 font_spec_from_name (font_name
)
3056 Lisp_Object font_name
;
3058 Lisp_Object args
[2];
3061 args
[1] = font_name
;
3062 return Ffont_spec (2, args
);
3067 font_clear_prop (attrs
, prop
)
3069 enum font_property_index prop
;
3071 Lisp_Object font
= attrs
[LFACE_FONT_INDEX
];
3075 if (NILP (AREF (font
, prop
))
3076 && prop
!= FONT_FAMILY_INDEX
3077 && prop
!= FONT_FOUNDRY_INDEX
3078 && prop
!= FONT_WIDTH_INDEX
3079 && prop
!= FONT_SIZE_INDEX
)
3081 font
= Fcopy_font_spec (font
);
3082 ASET (font
, prop
, Qnil
);
3083 if (prop
== FONT_FAMILY_INDEX
|| prop
== FONT_FOUNDRY_INDEX
)
3085 if (prop
== FONT_FAMILY_INDEX
)
3086 ASET (font
, FONT_FOUNDRY_INDEX
, Qnil
);
3087 ASET (font
, FONT_ADSTYLE_INDEX
, Qnil
);
3088 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
3089 ASET (font
, FONT_SIZE_INDEX
, Qnil
);
3090 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3091 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3092 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3094 else if (prop
== FONT_SIZE_INDEX
)
3096 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3097 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3098 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3100 else if (prop
== FONT_WIDTH_INDEX
)
3101 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3102 attrs
[LFACE_FONT_INDEX
] = font
;
3106 font_update_lface (f
, attrs
)
3112 spec
= attrs
[LFACE_FONT_INDEX
];
3113 if (! FONT_SPEC_P (spec
))
3116 if (! NILP (AREF (spec
, FONT_FOUNDRY_INDEX
)))
3117 attrs
[LFACE_FOUNDRY_INDEX
] = SYMBOL_NAME (AREF (spec
, FONT_FOUNDRY_INDEX
));
3118 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3119 attrs
[LFACE_FAMILY_INDEX
] = SYMBOL_NAME (AREF (spec
, FONT_FAMILY_INDEX
));
3120 if (! NILP (AREF (spec
, FONT_WEIGHT_INDEX
)))
3121 attrs
[LFACE_WEIGHT_INDEX
] = FONT_WEIGHT_FOR_FACE (spec
);
3122 if (! NILP (AREF (spec
, FONT_SLANT_INDEX
)))
3123 attrs
[LFACE_SLANT_INDEX
] = FONT_SLANT_FOR_FACE (spec
);;
3124 if (! NILP (AREF (spec
, FONT_WIDTH_INDEX
)))
3125 attrs
[LFACE_SWIDTH_INDEX
] = FONT_WIDTH_FOR_FACE (spec
);
3126 if (! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
3130 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
3135 val
= Ffont_get (spec
, QCdpi
);
3138 point
= PIXEL_TO_POINT (XINT (AREF (spec
, FONT_SIZE_INDEX
)) * 10,
3140 attrs
[LFACE_HEIGHT_INDEX
] = make_number (point
);
3142 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
3144 point
= XFLOAT_DATA (AREF (spec
, FONT_SIZE_INDEX
)) * 10;
3145 attrs
[LFACE_HEIGHT_INDEX
] = make_number (point
);
3151 /* Return a font-entity satisfying SPEC and best matching with face's
3152 font related attributes in ATTRS. C, if not negative, is a
3153 character that the entity must support. */
3156 font_find_for_lface (f
, attrs
, spec
, c
)
3163 Lisp_Object frame
, entities
, val
, props
[FONT_REGISTRY_INDEX
+ 1] ;
3164 Lisp_Object size
, foundry
[3], *family
, registry
[3], adstyle
[3];
3166 int i
, j
, k
, l
, result
;
3168 registry
[0] = AREF (spec
, FONT_REGISTRY_INDEX
);
3169 if (NILP (registry
[0]))
3171 registry
[0] = DEFAULT_ENCODING
;
3172 registry
[1] = Qascii_0
;
3173 registry
[2] = null_vector
;
3176 registry
[1] = null_vector
;
3178 if (c
>= 0 && ! NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
3180 struct charset
*encoding
, *repertory
;
3182 if (font_registry_charsets (AREF (spec
, FONT_REGISTRY_INDEX
),
3183 &encoding
, &repertory
) < 0)
3187 if (ENCODE_CHAR (repertory
, c
) == CHARSET_INVALID_CODE (repertory
))
3189 /* Any font of this registry support C. So, let's
3190 suppress the further checking. */
3193 else if (c
> encoding
->max_char
)
3197 work
= Fcopy_font_spec (spec
);
3198 XSETFRAME (frame
, f
);
3199 size
= AREF (spec
, FONT_SIZE_INDEX
);
3200 pixel_size
= font_pixel_size (f
, spec
);
3201 if (pixel_size
== 0)
3203 double pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3205 pixel_size
= POINT_TO_PIXEL (pt
/ 10, f
->resy
);
3207 ASET (work
, FONT_SIZE_INDEX
, Qnil
);
3208 foundry
[0] = AREF (work
, FONT_FOUNDRY_INDEX
);
3209 if (! NILP (foundry
[0]))
3210 foundry
[1] = null_vector
;
3211 else if (STRINGP (attrs
[LFACE_FOUNDRY_INDEX
]))
3213 val
= attrs
[LFACE_FOUNDRY_INDEX
];
3214 foundry
[0] = font_intern_prop ((char *) SDATA (val
), SBYTES (val
), 1);
3216 foundry
[2] = null_vector
;
3219 foundry
[0] = Qnil
, foundry
[1] = null_vector
;
3221 adstyle
[0] = AREF (work
, FONT_ADSTYLE_INDEX
);
3222 if (! NILP (adstyle
[0]))
3223 adstyle
[1] = null_vector
;
3224 else if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3226 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3228 if (! NILP (AREF (face_font
, FONT_ADSTYLE_INDEX
)))
3230 adstyle
[0] = AREF (face_font
, FONT_ADSTYLE_INDEX
);
3232 adstyle
[2] = null_vector
;
3235 adstyle
[0] = Qnil
, adstyle
[1] = null_vector
;
3238 adstyle
[0] = Qnil
, adstyle
[1] = null_vector
;
3241 val
= AREF (work
, FONT_FAMILY_INDEX
);
3242 if (NILP (val
) && STRINGP (attrs
[LFACE_FAMILY_INDEX
]))
3244 val
= attrs
[LFACE_FAMILY_INDEX
];
3245 val
= font_intern_prop ((char *) SDATA (val
), SBYTES (val
), 1);
3249 family
= alloca ((sizeof family
[0]) * 2);
3251 family
[1] = null_vector
; /* terminator. */
3256 = Fassoc_string (val
, Vface_alternative_font_family_alist
,
3264 if (! NILP (alters
))
3266 family
= alloca ((sizeof family
[0]) * (XINT (Flength (alters
)) + 2));
3267 for (i
= 0; CONSP (alters
); i
++, alters
= XCDR (alters
))
3268 family
[i
] = XCAR (alters
);
3269 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3271 family
[i
] = null_vector
;
3275 family
= alloca ((sizeof family
[0]) * 3);
3278 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3280 family
[i
] = null_vector
;
3284 for (i
= 0; SYMBOLP (family
[i
]); i
++)
3286 ASET (work
, FONT_FAMILY_INDEX
, family
[i
]);
3287 for (j
= 0; SYMBOLP (foundry
[j
]); j
++)
3289 ASET (work
, FONT_FOUNDRY_INDEX
, foundry
[j
]);
3290 for (k
= 0; SYMBOLP (registry
[k
]); k
++)
3292 ASET (work
, FONT_REGISTRY_INDEX
, registry
[k
]);
3293 for (l
= 0; SYMBOLP (adstyle
[l
]); l
++)
3295 ASET (work
, FONT_ADSTYLE_INDEX
, adstyle
[l
]);
3296 entities
= font_list_entities (frame
, work
);
3297 if (ASIZE (entities
) > 0)
3305 if (ASIZE (entities
) == 1)
3308 return AREF (entities
, 0);
3312 /* Sort fonts by properties specified in LFACE. */
3313 Lisp_Object prefer
= scratch_font_prefer
;
3315 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
3316 ASET (prefer
, i
, AREF (work
, i
));
3317 if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3319 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3321 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
3322 if (NILP (AREF (prefer
, i
)))
3323 ASET (prefer
, i
, AREF (face_font
, i
));
3325 if (NILP (AREF (prefer
, FONT_WEIGHT_INDEX
)))
3326 FONT_SET_STYLE (prefer
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
3327 if (NILP (AREF (prefer
, FONT_SLANT_INDEX
)))
3328 FONT_SET_STYLE (prefer
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
3329 if (NILP (AREF (prefer
, FONT_WIDTH_INDEX
)))
3330 FONT_SET_STYLE (prefer
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
3331 ASET (prefer
, FONT_SIZE_INDEX
, make_number (pixel_size
));
3332 entities
= font_sort_entites (entities
, prefer
, frame
, c
< 0);
3337 for (i
= 0; i
< ASIZE (entities
); i
++)
3341 val
= AREF (entities
, i
);
3344 for (j
= FONT_FOUNDRY_INDEX
; j
<= FONT_REGISTRY_INDEX
; j
++)
3345 if (! EQ (AREF (val
, j
), props
[j
]))
3347 if (j
> FONT_REGISTRY_INDEX
)
3350 for (j
= FONT_FOUNDRY_INDEX
; j
<= FONT_REGISTRY_INDEX
; j
++)
3351 props
[j
] = AREF (val
, j
);
3352 result
= font_has_char (f
, val
, c
);
3357 val
= font_open_for_lface (f
, val
, attrs
, spec
);
3360 result
= font_has_char (f
, val
, c
);
3361 font_close_object (f
, val
);
3363 return AREF (entities
, i
);
3370 font_open_for_lface (f
, entity
, attrs
, spec
)
3378 if (INTEGERP (AREF (entity
, FONT_SIZE_INDEX
))
3379 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
3380 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
3381 else if (FONT_SPEC_P (spec
) && ! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
3382 size
= font_pixel_size (f
, spec
);
3385 double pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3388 size
= POINT_TO_PIXEL (pt
, f
->resy
);
3392 Lisp_Object ffsize
= get_frame_param(f
, Qfontsize
);
3393 size
= NUMBERP (ffsize
) ? POINT_TO_PIXEL (XINT (ffsize
), f
->resy
) : 0;
3397 return font_open_entity (f
, entity
, size
);
3401 /* Find a font satisfying SPEC and best matching with face's
3402 attributes in ATTRS on FRAME, and return the opened
3406 font_load_for_lface (f
, attrs
, spec
)
3408 Lisp_Object
*attrs
, spec
;
3412 entity
= font_find_for_lface (f
, attrs
, spec
, -1);
3415 /* No font is listed for SPEC, but each font-backend may have
3416 the different criteria about "font matching". So, try
3418 entity
= font_matching_entity (f
, attrs
, spec
);
3422 return font_open_for_lface (f
, entity
, attrs
, spec
);
3426 /* Make FACE on frame F ready to use the font opened for FACE. */
3429 font_prepare_for_face (f
, face
)
3433 if (face
->font
->driver
->prepare_face
)
3434 face
->font
->driver
->prepare_face (f
, face
);
3438 /* Make FACE on frame F stop using the font opened for FACE. */
3441 font_done_for_face (f
, face
)
3445 if (face
->font
->driver
->done_face
)
3446 face
->font
->driver
->done_face (f
, face
);
3451 /* Open a font best matching with NAME on frame F. If no proper font
3452 is found, return Qnil. */
3455 font_open_by_name (f
, name
)
3459 Lisp_Object args
[2];
3460 Lisp_Object spec
, attrs
[LFACE_VECTOR_SIZE
];
3463 args
[1] = make_unibyte_string (name
, strlen (name
));
3464 spec
= Ffont_spec (2, args
);
3465 /* We set up the default font-related attributes of a face to prefer
3467 attrs
[LFACE_FAMILY_INDEX
] = attrs
[LFACE_FOUNDRY_INDEX
] = Qnil
;
3468 attrs
[LFACE_SWIDTH_INDEX
] = attrs
[LFACE_WEIGHT_INDEX
]
3469 = attrs
[LFACE_SLANT_INDEX
] = Qnormal
;
3471 attrs
[LFACE_HEIGHT_INDEX
] = make_number (120);
3473 attrs
[LFACE_HEIGHT_INDEX
] = make_number (0);
3475 attrs
[LFACE_FONT_INDEX
] = Qnil
;
3477 return font_load_for_lface (f
, attrs
, spec
);
3481 /* Register font-driver DRIVER. This function is used in two ways.
3483 The first is with frame F non-NULL. In this case, make DRIVER
3484 available (but not yet activated) on F. All frame creaters
3485 (e.g. Fx_create_frame) must call this function at least once with
3486 an available font-driver.
3488 The second is with frame F NULL. In this case, DRIVER is globally
3489 registered in the variable `font_driver_list'. All font-driver
3490 implementations must call this function in its syms_of_XXXX
3491 (e.g. syms_of_xfont). */
3494 register_font_driver (driver
, f
)
3495 struct font_driver
*driver
;
3498 struct font_driver_list
*root
= f
? f
->font_driver_list
: font_driver_list
;
3499 struct font_driver_list
*prev
, *list
;
3501 if (f
&& ! driver
->draw
)
3502 error ("Unusable font driver for a frame: %s",
3503 SDATA (SYMBOL_NAME (driver
->type
)));
3505 for (prev
= NULL
, list
= root
; list
; prev
= list
, list
= list
->next
)
3506 if (EQ (list
->driver
->type
, driver
->type
))
3507 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver
->type
)));
3509 list
= xmalloc (sizeof (struct font_driver_list
));
3511 list
->driver
= driver
;
3516 f
->font_driver_list
= list
;
3518 font_driver_list
= list
;
3524 free_font_driver_list (f
)
3527 struct font_driver_list
*list
, *next
;
3529 for (list
= f
->font_driver_list
; list
; list
= next
)
3534 f
->font_driver_list
= NULL
;
3538 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3539 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3540 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3542 A caller must free all realized faces if any in advance. The
3543 return value is a list of font backends actually made used on
3547 font_update_drivers (f
, new_drivers
)
3549 Lisp_Object new_drivers
;
3551 Lisp_Object active_drivers
= Qnil
;
3552 struct font_driver
*driver
;
3553 struct font_driver_list
*list
;
3555 /* At first, turn off non-requested drivers, and turn on requested
3557 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3559 driver
= list
->driver
;
3560 if ((EQ (new_drivers
, Qt
) || ! NILP (Fmemq (driver
->type
, new_drivers
)))
3565 if (driver
->end_for_frame
)
3566 driver
->end_for_frame (f
);
3567 font_finish_cache (f
, driver
);
3572 if (! driver
->start_for_frame
3573 || driver
->start_for_frame (f
) == 0)
3575 font_prepare_cache (f
, driver
);
3582 if (NILP (new_drivers
))
3585 if (! EQ (new_drivers
, Qt
))
3587 /* Re-order the driver list according to new_drivers. */
3588 struct font_driver_list
**list_table
, **next
;
3592 list_table
= alloca (sizeof list_table
[0] * (num_font_drivers
+ 1));
3593 for (i
= 0, tail
= new_drivers
; ! NILP (tail
); tail
= XCDR (tail
))
3595 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3596 if (list
->on
&& EQ (list
->driver
->type
, XCAR (tail
)))
3599 list_table
[i
++] = list
;
3601 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3603 list_table
[i
++] = list
;
3604 list_table
[i
] = NULL
;
3606 next
= &f
->font_driver_list
;
3607 for (i
= 0; list_table
[i
]; i
++)
3609 *next
= list_table
[i
];
3610 next
= &(*next
)->next
;
3615 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3617 active_drivers
= nconc2 (active_drivers
,
3618 Fcons (list
->driver
->type
, Qnil
));
3619 return active_drivers
;
3623 font_put_frame_data (f
, driver
, data
)
3625 struct font_driver
*driver
;
3628 struct font_data_list
*list
, *prev
;
3630 for (prev
= NULL
, list
= f
->font_data_list
; list
;
3631 prev
= list
, list
= list
->next
)
3632 if (list
->driver
== driver
)
3639 prev
->next
= list
->next
;
3641 f
->font_data_list
= list
->next
;
3649 list
= xmalloc (sizeof (struct font_data_list
));
3650 list
->driver
= driver
;
3651 list
->next
= f
->font_data_list
;
3652 f
->font_data_list
= list
;
3660 font_get_frame_data (f
, driver
)
3662 struct font_driver
*driver
;
3664 struct font_data_list
*list
;
3666 for (list
= f
->font_data_list
; list
; list
= list
->next
)
3667 if (list
->driver
== driver
)
3675 /* Return the font used to draw character C by FACE at buffer position
3676 POS in window W. If STRING is non-nil, it is a string containing C
3677 at index POS. If C is negative, get C from the current buffer or
3681 font_at (c
, pos
, face
, w
, string
)
3690 Lisp_Object font_object
;
3692 multibyte
= (NILP (string
)
3693 ? ! NILP (current_buffer
->enable_multibyte_characters
)
3694 : STRING_MULTIBYTE (string
));
3701 EMACS_INT pos_byte
= CHAR_TO_BYTE (pos
);
3703 c
= FETCH_CHAR (pos_byte
);
3706 c
= FETCH_BYTE (pos
);
3712 multibyte
= STRING_MULTIBYTE (string
);
3715 EMACS_INT pos_byte
= string_char_to_byte (string
, pos
);
3717 str
= SDATA (string
) + pos_byte
;
3718 c
= STRING_CHAR (str
, 0);
3721 c
= SDATA (string
)[pos
];
3725 f
= XFRAME (w
->frame
);
3726 if (! FRAME_WINDOW_P (f
))
3733 if (STRINGP (string
))
3734 face_id
= face_at_string_position (w
, string
, pos
, 0, -1, -1, &endptr
,
3735 DEFAULT_FACE_ID
, 0);
3737 face_id
= face_at_buffer_position (w
, pos
, -1, -1, &endptr
,
3739 face
= FACE_FROM_ID (f
, face_id
);
3743 int face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3744 face
= FACE_FROM_ID (f
, face_id
);
3749 XSETFONT (font_object
, face
->font
);
3754 #ifdef HAVE_WINDOW_SYSTEM
3756 /* Check how many characters after POS (at most to *LIMIT) can be
3757 displayed by the same font on the window W. FACE, if non-NULL, is
3758 the face selected for the character at POS. If STRING is not nil,
3759 it is the string to check instead of the current buffer. In that
3760 case, FACE must be not NULL.
3762 The return value is the font-object for the character at POS.
3763 *LIMIT is set to the position where that font can't be used.
3765 It is assured that the current buffer (or STRING) is multibyte. */
3768 font_range (pos
, limit
, w
, face
, string
)
3769 EMACS_INT pos
, *limit
;
3774 EMACS_INT pos_byte
, ignore
, start
, start_byte
;
3776 Lisp_Object font_object
= Qnil
;
3780 pos_byte
= CHAR_TO_BYTE (pos
);
3785 face_id
= face_at_buffer_position (w
, pos
, 0, 0, &ignore
, *limit
, 0);
3786 face
= FACE_FROM_ID (XFRAME (w
->frame
), face_id
);
3792 pos_byte
= string_char_to_byte (string
, pos
);
3795 start
= pos
, start_byte
= pos_byte
;
3796 while (pos
< *limit
)
3798 Lisp_Object category
;
3801 FETCH_CHAR_ADVANCE_NO_CHECK (c
, pos
, pos_byte
);
3803 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c
, string
, pos
, pos_byte
);
3804 if (NILP (font_object
))
3806 font_object
= font_for_char (face
, c
, pos
- 1, string
);
3807 if (NILP (font_object
))
3812 category
= CHAR_TABLE_REF (Vunicode_category_table
, c
);
3813 if (! EQ (category
, QCf
)
3814 && ! CHAR_VARIATION_SELECTOR_P (c
)
3815 && font_encode_char (font_object
, c
) == FONT_INVALID_CODE
)
3817 Lisp_Object f
= font_for_char (face
, c
, pos
- 1, string
);
3818 EMACS_INT i
, i_byte
;
3826 i
= start
, i_byte
= start_byte
;
3831 FETCH_CHAR_ADVANCE_NO_CHECK (c
, i
, i_byte
);
3833 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c
, string
, i
, i_byte
);
3834 category
= CHAR_TABLE_REF (Vunicode_category_table
, c
);
3835 if (! EQ (category
, QCf
)
3836 && ! CHAR_VARIATION_SELECTOR_P (c
)
3837 && font_encode_char (f
, c
) == FONT_INVALID_CODE
)
3853 DEFUN ("fontp", Ffontp
, Sfontp
, 1, 2, 0,
3854 doc
: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3855 Return nil otherwise.
3856 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3857 which kind of font it is. It must be one of `font-spec', `font-entity',
3859 (object
, extra_type
)
3860 Lisp_Object object
, extra_type
;
3862 if (NILP (extra_type
))
3863 return (FONTP (object
) ? Qt
: Qnil
);
3864 if (EQ (extra_type
, Qfont_spec
))
3865 return (FONT_SPEC_P (object
) ? Qt
: Qnil
);
3866 if (EQ (extra_type
, Qfont_entity
))
3867 return (FONT_ENTITY_P (object
) ? Qt
: Qnil
);
3868 if (EQ (extra_type
, Qfont_object
))
3869 return (FONT_OBJECT_P (object
) ? Qt
: Qnil
);
3870 wrong_type_argument (intern ("font-extra-type"), extra_type
);
3873 DEFUN ("font-spec", Ffont_spec
, Sfont_spec
, 0, MANY
, 0,
3874 doc
: /* Return a newly created font-spec with arguments as properties.
3876 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3877 valid font property name listed below:
3879 `:family', `:weight', `:slant', `:width'
3881 They are the same as face attributes of the same name. See
3882 `set-face-attribute'.
3886 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3890 VALUE must be a string or a symbol specifying the additional
3891 typographic style information of a font, e.g. ``sans''.
3895 VALUE must be a string or a symbol specifying the charset registry and
3896 encoding of a font, e.g. ``iso8859-1''.
3900 VALUE must be a non-negative integer or a floating point number
3901 specifying the font size. It specifies the font size in pixels
3902 (if VALUE is an integer), or in points (if VALUE is a float).
3906 VALUE must be a string of XLFD-style or fontconfig-style font name.
3910 VALUE must be a symbol representing a script that the font must
3912 usage: (font-spec ARGS...) */)
3917 Lisp_Object spec
= font_make_spec ();
3920 for (i
= 0; i
< nargs
; i
+= 2)
3922 Lisp_Object key
= args
[i
], val
= args
[i
+ 1];
3924 if (EQ (key
, QCname
))
3927 font_parse_name ((char *) SDATA (val
), spec
);
3928 font_put_extra (spec
, key
, val
);
3932 int idx
= get_font_prop_index (key
);
3936 val
= font_prop_validate (idx
, Qnil
, val
);
3937 if (idx
< FONT_EXTRA_INDEX
)
3938 ASET (spec
, idx
, val
);
3940 font_put_extra (spec
, key
, val
);
3943 font_put_extra (spec
, key
, font_prop_validate (0, key
, val
));
3949 DEFUN ("copy-font-spec", Fcopy_font_spec
, Scopy_font_spec
, 1, 1, 0,
3950 doc
: /* Return a copy of FONT as a font-spec. */)
3954 Lisp_Object new_spec
, tail
, prev
, extra
;
3958 new_spec
= font_make_spec ();
3959 for (i
= 1; i
< FONT_EXTRA_INDEX
; i
++)
3960 ASET (new_spec
, i
, AREF (font
, i
));
3961 extra
= Fcopy_sequence (AREF (font
, FONT_EXTRA_INDEX
));
3962 /* We must remove :font-entity property. */
3963 for (prev
= Qnil
, tail
= extra
; CONSP (tail
); prev
= tail
, tail
= XCDR (tail
))
3964 if (EQ (XCAR (XCAR (tail
)), QCfont_entity
))
3967 extra
= XCDR (extra
);
3969 XSETCDR (prev
, XCDR (tail
));
3972 ASET (new_spec
, FONT_EXTRA_INDEX
, extra
);
3976 DEFUN ("merge-font-spec", Fmerge_font_spec
, Smerge_font_spec
, 2, 2, 0,
3977 doc
: /* Merge font-specs FROM and TO, and return a new font-spec.
3978 Every specified properties in FROM override the corresponding
3979 properties in TO. */)
3981 Lisp_Object from
, to
;
3983 Lisp_Object extra
, tail
;
3988 to
= Fcopy_font_spec (to
);
3989 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
3990 ASET (to
, i
, AREF (from
, i
));
3991 extra
= AREF (to
, FONT_EXTRA_INDEX
);
3992 for (tail
= AREF (from
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
3993 if (! EQ (XCAR (XCAR (tail
)), Qfont_entity
))
3995 Lisp_Object slot
= assq_no_quit (XCAR (XCAR (tail
)), extra
);
3998 XSETCDR (slot
, XCDR (XCAR (tail
)));
4000 extra
= Fcons (Fcons (XCAR (XCAR (tail
)), XCDR (XCAR (tail
))), extra
);
4002 ASET (to
, FONT_EXTRA_INDEX
, extra
);
4006 DEFUN ("font-get", Ffont_get
, Sfont_get
, 2, 2, 0,
4007 doc
: /* Return the value of FONT's property KEY.
4008 FONT is a font-spec, a font-entity, or a font-object.
4009 KEY must be one of these symbols:
4010 :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
4011 :size, :name, :script
4012 See the documentation of `font-spec' for their meanings.
4013 If FONT is a font-entity or font-object, the value of :script may be
4014 a list of scripts that are supported by the font. */)
4016 Lisp_Object font
, key
;
4023 idx
= get_font_prop_index (key
);
4024 if (idx
>= FONT_WEIGHT_INDEX
&& idx
<= FONT_WIDTH_INDEX
)
4025 return font_style_symbolic (font
, idx
, 0);
4026 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
4027 return AREF (font
, idx
);
4028 return Fcdr (Fassq (key
, AREF (font
, FONT_EXTRA_INDEX
)));
4031 #ifdef HAVE_WINDOW_SYSTEM
4033 DEFUN ("font-face-attributes", Ffont_face_attributes
, Sfont_face_attributes
, 1, 2, 0,
4034 doc
: /* Return a plist of face attributes generated by FONT.
4035 FONT is a font name, a font-spec, a font-entity, or a font-object.
4036 The return value is a list of the form
4038 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
4040 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
4041 compatible with `set-face-attribute'. Some of these key-attribute pairs
4042 may be omitted from the list if they are not specified by FONT.
4044 The optional argument FRAME specifies the frame that the face attributes
4045 are to be displayed on. If omitted, the selected frame is used. */)
4047 Lisp_Object font
, frame
;
4050 Lisp_Object plist
[10];
4055 frame
= selected_frame
;
4056 CHECK_LIVE_FRAME (frame
);
4061 int fontset
= fs_query_fontset (font
, 0);
4062 Lisp_Object name
= font
;
4064 font
= fontset_ascii (fontset
);
4065 font
= font_spec_from_name (name
);
4067 signal_error ("Invalid font name", name
);
4069 else if (! FONTP (font
))
4070 signal_error ("Invalid font object", font
);
4072 val
= AREF (font
, FONT_FAMILY_INDEX
);
4075 plist
[n
++] = QCfamily
;
4076 plist
[n
++] = SYMBOL_NAME (val
);
4079 val
= AREF (font
, FONT_SIZE_INDEX
);
4082 Lisp_Object font_dpi
= AREF (font
, FONT_DPI_INDEX
);
4083 int dpi
= INTEGERP (font_dpi
) ? XINT (font_dpi
) : f
->resy
;
4084 plist
[n
++] = QCheight
;
4085 plist
[n
++] = make_number (PIXEL_TO_POINT (XINT (val
) * 10, dpi
));
4087 else if (FLOATP (val
))
4089 plist
[n
++] = QCheight
;
4090 plist
[n
++] = make_number (10 * (int) XFLOAT_DATA (val
));
4093 val
= FONT_WEIGHT_FOR_FACE (font
);
4096 plist
[n
++] = QCweight
;
4100 val
= FONT_SLANT_FOR_FACE (font
);
4103 plist
[n
++] = QCslant
;
4107 val
= FONT_WIDTH_FOR_FACE (font
);
4110 plist
[n
++] = QCwidth
;
4114 return Flist (n
, plist
);
4119 DEFUN ("font-put", Ffont_put
, Sfont_put
, 3, 3, 0,
4120 doc
: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
4121 (font_spec
, prop
, val
)
4122 Lisp_Object font_spec
, prop
, val
;
4126 CHECK_FONT_SPEC (font_spec
);
4127 idx
= get_font_prop_index (prop
);
4128 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
4129 ASET (font_spec
, idx
, font_prop_validate (idx
, Qnil
, val
));
4131 font_put_extra (font_spec
, prop
, font_prop_validate (0, prop
, val
));
4135 DEFUN ("list-fonts", Flist_fonts
, Slist_fonts
, 1, 4, 0,
4136 doc
: /* List available fonts matching FONT-SPEC on the current frame.
4137 Optional 2nd argument FRAME specifies the target frame.
4138 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4139 Optional 4th argument PREFER, if non-nil, is a font-spec to
4140 control the order of the returned list. Fonts are sorted by
4141 how close they are to PREFER. */)
4142 (font_spec
, frame
, num
, prefer
)
4143 Lisp_Object font_spec
, frame
, num
, prefer
;
4145 Lisp_Object vec
, list
, tail
;
4149 frame
= selected_frame
;
4150 CHECK_LIVE_FRAME (frame
);
4151 CHECK_FONT_SPEC (font_spec
);
4159 if (! NILP (prefer
))
4160 CHECK_FONT_SPEC (prefer
);
4162 vec
= font_list_entities (frame
, font_spec
);
4167 return Fcons (AREF (vec
, 0), Qnil
);
4169 if (! NILP (prefer
))
4170 vec
= font_sort_entites (vec
, prefer
, frame
, 0);
4172 list
= tail
= Fcons (AREF (vec
, 0), Qnil
);
4173 if (n
== 0 || n
> len
)
4175 for (i
= 1; i
< n
; i
++)
4177 Lisp_Object val
= Fcons (AREF (vec
, i
), Qnil
);
4179 XSETCDR (tail
, val
);
4185 DEFUN ("font-family-list", Ffont_family_list
, Sfont_family_list
, 0, 1, 0,
4186 doc
: /* List available font families on the current frame.
4187 Optional argument FRAME, if non-nil, specifies the target frame. */)
4192 struct font_driver_list
*driver_list
;
4196 frame
= selected_frame
;
4197 CHECK_LIVE_FRAME (frame
);
4200 for (driver_list
= f
->font_driver_list
; driver_list
;
4201 driver_list
= driver_list
->next
)
4202 if (driver_list
->driver
->list_family
)
4204 Lisp_Object val
= driver_list
->driver
->list_family (frame
);
4210 Lisp_Object tail
= list
;
4212 for (; CONSP (val
); val
= XCDR (val
))
4213 if (NILP (Fmemq (XCAR (val
), tail
)))
4214 list
= Fcons (XCAR (val
), list
);
4220 DEFUN ("find-font", Ffind_font
, Sfind_font
, 1, 2, 0,
4221 doc
: /* Return a font-entity matching with FONT-SPEC on the current frame.
4222 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4224 Lisp_Object font_spec
, frame
;
4226 Lisp_Object val
= Flist_fonts (font_spec
, frame
, make_number (1), Qnil
);
4233 DEFUN ("font-xlfd-name", Ffont_xlfd_name
, Sfont_xlfd_name
, 1, 2, 0,
4234 doc
: /* Return XLFD name of FONT.
4235 FONT is a font-spec, font-entity, or font-object.
4236 If the name is too long for XLFD (maximum 255 chars), return nil.
4237 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4238 the consecutive wildcards are folded to one. */)
4239 (font
, fold_wildcards
)
4240 Lisp_Object font
, fold_wildcards
;
4247 if (FONT_OBJECT_P (font
))
4249 Lisp_Object font_name
= AREF (font
, FONT_NAME_INDEX
);
4251 if (STRINGP (font_name
)
4252 && SDATA (font_name
)[0] == '-')
4254 if (NILP (fold_wildcards
))
4256 strcpy (name
, (char *) SDATA (font_name
));
4259 pixel_size
= XFONT_OBJECT (font
)->pixel_size
;
4261 if (font_unparse_xlfd (font
, pixel_size
, name
, 256) < 0)
4264 if (! NILP (fold_wildcards
))
4266 char *p0
= name
, *p1
;
4268 while ((p1
= strstr (p0
, "-*-*")))
4270 strcpy (p1
, p1
+ 2);
4275 return build_string (name
);
4278 DEFUN ("clear-font-cache", Fclear_font_cache
, Sclear_font_cache
, 0, 0, 0,
4279 doc
: /* Clear font cache. */)
4282 Lisp_Object list
, frame
;
4284 FOR_EACH_FRAME (list
, frame
)
4286 FRAME_PTR f
= XFRAME (frame
);
4287 struct font_driver_list
*driver_list
= f
->font_driver_list
;
4289 for (; driver_list
; driver_list
= driver_list
->next
)
4290 if (driver_list
->on
)
4292 Lisp_Object cache
= driver_list
->driver
->get_cache (f
);
4297 && ! EQ (XCAR (XCAR (val
)), driver_list
->driver
->type
))
4299 font_assert (! NILP (val
));
4300 val
= XCDR (XCAR (val
));
4301 if (XINT (XCAR (val
)) == 0)
4303 font_clear_cache (f
, XCAR (val
), driver_list
->driver
);
4304 XSETCDR (cache
, XCDR (val
));
4314 font_fill_lglyph_metrics (glyph
, font_object
)
4315 Lisp_Object glyph
, font_object
;
4317 struct font
*font
= XFONT_OBJECT (font_object
);
4319 /* ecode used in LGLYPH_SET_CODE to avoid compiler warnings. */
4320 EMACS_INT ecode
= font
->driver
->encode_char (font
, LGLYPH_CHAR (glyph
));
4321 struct font_metrics metrics
;
4323 LGLYPH_SET_CODE (glyph
, ecode
);
4325 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4326 LGLYPH_SET_LBEARING (glyph
, metrics
.lbearing
);
4327 LGLYPH_SET_RBEARING (glyph
, metrics
.rbearing
);
4328 LGLYPH_SET_WIDTH (glyph
, metrics
.width
);
4329 LGLYPH_SET_ASCENT (glyph
, metrics
.ascent
);
4330 LGLYPH_SET_DESCENT (glyph
, metrics
.descent
);
4334 DEFUN ("font-shape-gstring", Ffont_shape_gstring
, Sfont_shape_gstring
, 1, 1, 0,
4335 doc
: /* Shape the glyph-string GSTRING.
4336 Shaping means substituting glyphs and/or adjusting positions of glyphs
4337 to get the correct visual image of character sequences set in the
4338 header of the glyph-string.
4340 If the shaping was successful, the value is GSTRING itself or a newly
4341 created glyph-string. Otherwise, the value is nil. */)
4343 Lisp_Object gstring
;
4346 Lisp_Object font_object
, n
, glyph
;
4349 if (! composition_gstring_p (gstring
))
4350 signal_error ("Invalid glyph-string: ", gstring
);
4351 if (! NILP (LGSTRING_ID (gstring
)))
4353 font_object
= LGSTRING_FONT (gstring
);
4354 CHECK_FONT_OBJECT (font_object
);
4355 font
= XFONT_OBJECT (font_object
);
4356 if (! font
->driver
->shape
)
4359 /* Try at most three times with larger gstring each time. */
4360 for (i
= 0; i
< 3; i
++)
4362 n
= font
->driver
->shape (gstring
);
4365 gstring
= larger_vector (gstring
,
4366 ASIZE (gstring
) + LGSTRING_GLYPH_LEN (gstring
),
4369 if (i
== 3 || XINT (n
) == 0)
4372 glyph
= LGSTRING_GLYPH (gstring
, 0);
4373 from
= LGLYPH_FROM (glyph
);
4374 to
= LGLYPH_TO (glyph
);
4375 for (i
= 1, j
= 0; i
< LGSTRING_GLYPH_LEN (gstring
); i
++)
4377 Lisp_Object
this = LGSTRING_GLYPH (gstring
, i
);
4381 if (NILP (LGLYPH_ADJUSTMENT (this)))
4386 glyph
= LGSTRING_GLYPH (gstring
, j
);
4387 LGLYPH_SET_FROM (glyph
, from
);
4388 LGLYPH_SET_TO (glyph
, to
);
4390 from
= LGLYPH_FROM (this);
4391 to
= LGLYPH_TO (this);
4396 if (from
> LGLYPH_FROM (this))
4397 from
= LGLYPH_FROM (this);
4398 if (to
< LGLYPH_TO (this))
4399 to
= LGLYPH_TO (this);
4405 glyph
= LGSTRING_GLYPH (gstring
, j
);
4406 LGLYPH_SET_FROM (glyph
, from
);
4407 LGLYPH_SET_TO (glyph
, to
);
4409 return composition_gstring_put_cache (gstring
, XINT (n
));
4412 DEFUN ("font-variation-glyphs", Ffont_variation_glyphs
, Sfont_variation_glyphs
,
4414 doc
: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
4415 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
4417 VARIATION-SELECTOR is a chracter code of variation selection
4418 (#xFE00..#xFE0F or #xE0100..#xE01EF)
4419 GLYPH-ID is a glyph code of the corresponding variation glyph. */)
4420 (font_object
, character
)
4421 Lisp_Object font_object
, character
;
4423 unsigned variations
[256];
4428 CHECK_FONT_OBJECT (font_object
);
4429 CHECK_CHARACTER (character
);
4430 font
= XFONT_OBJECT (font_object
);
4431 if (! font
->driver
->get_variation_glyphs
)
4433 n
= font
->driver
->get_variation_glyphs (font
, XINT (character
), variations
);
4437 for (i
= 0; i
< 255; i
++)
4441 int vs
= (i
< 16 ? 0xFE00 + i
: 0xE0100 + (i
- 16));
4443 if (variations
[i
] > MOST_POSITIVE_FIXNUM
)
4444 code
= Fcons (make_number ((variations
[i
]) >> 16),
4445 make_number ((variations
[i
]) & 0xFFFF));
4447 code
= make_number (variations
[i
]);
4448 val
= Fcons (Fcons (make_number (vs
), code
), val
);
4455 DEFUN ("font-drive-otf", Ffont_drive_otf
, Sfont_drive_otf
, 6, 6, 0,
4456 doc
: /* Apply OpenType features on glyph-string GSTRING-IN.
4457 OTF-FEATURES specifies which features to apply in this format:
4458 (SCRIPT LANGSYS GSUB GPOS)
4460 SCRIPT is a symbol specifying a script tag of OpenType,
4461 LANGSYS is a symbol specifying a langsys tag of OpenType,
4462 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4464 If LANGYS is nil, the default langsys is selected.
4466 The features are applied in the order they appear in the list. The
4467 symbol `*' means to apply all available features not present in this
4468 list, and the remaining features are ignored. For instance, (vatu
4469 pstf * haln) is to apply vatu and pstf in this order, then to apply
4470 all available features other than vatu, pstf, and haln.
4472 The features are applied to the glyphs in the range FROM and TO of
4473 the glyph-string GSTRING-IN.
4475 If some feature is actually applicable, the resulting glyphs are
4476 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4477 this case, the value is the number of produced glyphs.
4479 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4482 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4483 produced in GSTRING-OUT, and the value is nil.
4485 See the documentation of `font-make-gstring' for the format of
4487 (otf_features
, gstring_in
, from
, to
, gstring_out
, index
)
4488 Lisp_Object otf_features
, gstring_in
, from
, to
, gstring_out
, index
;
4490 Lisp_Object font_object
= LGSTRING_FONT (gstring_in
);
4495 check_otf_features (otf_features
);
4496 CHECK_FONT_OBJECT (font_object
);
4497 font
= XFONT_OBJECT (font_object
);
4498 if (! font
->driver
->otf_drive
)
4499 error ("Font backend %s can't drive OpenType GSUB table",
4500 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4501 CHECK_CONS (otf_features
);
4502 CHECK_SYMBOL (XCAR (otf_features
));
4503 val
= XCDR (otf_features
);
4504 CHECK_SYMBOL (XCAR (val
));
4505 val
= XCDR (otf_features
);
4508 len
= check_gstring (gstring_in
);
4509 CHECK_VECTOR (gstring_out
);
4510 CHECK_NATNUM (from
);
4512 CHECK_NATNUM (index
);
4514 if (XINT (from
) >= XINT (to
) || XINT (to
) > len
)
4515 args_out_of_range_3 (from
, to
, make_number (len
));
4516 if (XINT (index
) >= ASIZE (gstring_out
))
4517 args_out_of_range (index
, make_number (ASIZE (gstring_out
)));
4518 num
= font
->driver
->otf_drive (font
, otf_features
,
4519 gstring_in
, XINT (from
), XINT (to
),
4520 gstring_out
, XINT (index
), 0);
4523 return make_number (num
);
4526 DEFUN ("font-otf-alternates", Ffont_otf_alternates
, Sfont_otf_alternates
,
4528 doc
: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4529 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4531 (SCRIPT LANGSYS FEATURE ...)
4532 See the documentation of `font-drive-otf' for more detail.
4534 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4535 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4536 character code corresponding to the glyph or nil if there's no
4537 corresponding character. */)
4538 (font_object
, character
, otf_features
)
4539 Lisp_Object font_object
, character
, otf_features
;
4542 Lisp_Object gstring_in
, gstring_out
, g
;
4543 Lisp_Object alternates
;
4546 CHECK_FONT_GET_OBJECT (font_object
, font
);
4547 if (! font
->driver
->otf_drive
)
4548 error ("Font backend %s can't drive OpenType GSUB table",
4549 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4550 CHECK_CHARACTER (character
);
4551 CHECK_CONS (otf_features
);
4553 gstring_in
= Ffont_make_gstring (font_object
, make_number (1));
4554 g
= LGSTRING_GLYPH (gstring_in
, 0);
4555 LGLYPH_SET_CHAR (g
, XINT (character
));
4556 gstring_out
= Ffont_make_gstring (font_object
, make_number (10));
4557 while ((num
= font
->driver
->otf_drive (font
, otf_features
, gstring_in
, 0, 1,
4558 gstring_out
, 0, 1)) < 0)
4559 gstring_out
= Ffont_make_gstring (font_object
,
4560 make_number (ASIZE (gstring_out
) * 2));
4562 for (i
= 0; i
< num
; i
++)
4564 Lisp_Object g
= LGSTRING_GLYPH (gstring_out
, i
);
4565 int c
= LGLYPH_CHAR (g
);
4566 unsigned code
= LGLYPH_CODE (g
);
4568 alternates
= Fcons (Fcons (make_number (code
),
4569 c
> 0 ? make_number (c
) : Qnil
),
4572 return Fnreverse (alternates
);
4578 DEFUN ("open-font", Fopen_font
, Sopen_font
, 1, 3, 0,
4579 doc
: /* Open FONT-ENTITY. */)
4580 (font_entity
, size
, frame
)
4581 Lisp_Object font_entity
;
4587 CHECK_FONT_ENTITY (font_entity
);
4589 frame
= selected_frame
;
4590 CHECK_LIVE_FRAME (frame
);
4593 isize
= XINT (AREF (font_entity
, FONT_SIZE_INDEX
));
4596 CHECK_NUMBER_OR_FLOAT (size
);
4598 isize
= POINT_TO_PIXEL (XFLOAT_DATA (size
), XFRAME (frame
)->resy
);
4600 isize
= XINT (size
);
4604 return font_open_entity (XFRAME (frame
), font_entity
, isize
);
4607 DEFUN ("close-font", Fclose_font
, Sclose_font
, 1, 2, 0,
4608 doc
: /* Close FONT-OBJECT. */)
4609 (font_object
, frame
)
4610 Lisp_Object font_object
, frame
;
4612 CHECK_FONT_OBJECT (font_object
);
4614 frame
= selected_frame
;
4615 CHECK_LIVE_FRAME (frame
);
4616 font_close_object (XFRAME (frame
), font_object
);
4620 DEFUN ("query-font", Fquery_font
, Squery_font
, 1, 1, 0,
4621 doc
: /* Return information about FONT-OBJECT.
4622 The value is a vector:
4623 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4626 NAME is a string of the font name (or nil if the font backend doesn't
4629 FILENAME is a string of the font file (or nil if the font backend
4630 doesn't provide a file name).
4632 PIXEL-SIZE is a pixel size by which the font is opened.
4634 SIZE is a maximum advance width of the font in pixels.
4636 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4639 CAPABILITY is a list whose first element is a symbol representing the
4640 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4641 remaining elements describe the details of the font capability.
4643 If the font is OpenType font, the form of the list is
4644 \(opentype GSUB GPOS)
4645 where GSUB shows which "GSUB" features the font supports, and GPOS
4646 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4647 lists of the format:
4648 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4650 If the font is not OpenType font, currently the length of the form is
4653 SCRIPT is a symbol representing OpenType script tag.
4655 LANGSYS is a symbol representing OpenType langsys tag, or nil
4656 representing the default langsys.
4658 FEATURE is a symbol representing OpenType feature tag.
4660 If the font is not OpenType font, CAPABILITY is nil. */)
4662 Lisp_Object font_object
;
4667 CHECK_FONT_GET_OBJECT (font_object
, font
);
4669 val
= Fmake_vector (make_number (9), Qnil
);
4670 ASET (val
, 0, AREF (font_object
, FONT_NAME_INDEX
));
4671 ASET (val
, 1, AREF (font_object
, FONT_FILE_INDEX
));
4672 ASET (val
, 2, make_number (font
->pixel_size
));
4673 ASET (val
, 3, make_number (font
->max_width
));
4674 ASET (val
, 4, make_number (font
->ascent
));
4675 ASET (val
, 5, make_number (font
->descent
));
4676 ASET (val
, 6, make_number (font
->space_width
));
4677 ASET (val
, 7, make_number (font
->average_width
));
4678 if (font
->driver
->otf_capability
)
4679 ASET (val
, 8, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
4683 DEFUN ("get-font-glyphs", Fget_font_glyphs
, Sget_font_glyphs
, 2, 2, 0,
4684 doc
: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
4685 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
4686 (font_object
, string
)
4687 Lisp_Object font_object
, string
;
4693 CHECK_FONT_GET_OBJECT (font_object
, font
);
4694 CHECK_STRING (string
);
4695 len
= SCHARS (string
);
4696 vec
= Fmake_vector (make_number (len
), Qnil
);
4697 for (i
= 0; i
< len
; i
++)
4699 Lisp_Object ch
= Faref (string
, make_number (i
));
4704 struct font_metrics metrics
;
4706 cod
= code
= font
->driver
->encode_char (font
, c
);
4707 if (code
== FONT_INVALID_CODE
)
4709 val
= Fmake_vector (make_number (6), Qnil
);
4710 if (cod
<= MOST_POSITIVE_FIXNUM
)
4711 ASET (val
, 0, make_number (code
));
4713 ASET (val
, 0, Fcons (make_number (code
>> 16),
4714 make_number (code
& 0xFFFF)));
4715 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4716 ASET (val
, 1, make_number (metrics
.lbearing
));
4717 ASET (val
, 2, make_number (metrics
.rbearing
));
4718 ASET (val
, 3, make_number (metrics
.width
));
4719 ASET (val
, 4, make_number (metrics
.ascent
));
4720 ASET (val
, 5, make_number (metrics
.descent
));
4726 DEFUN ("font-match-p", Ffont_match_p
, Sfont_match_p
, 2, 2, 0,
4727 doc
: /* Return t if and only if font-spec SPEC matches with FONT.
4728 FONT is a font-spec, font-entity, or font-object. */)
4730 Lisp_Object spec
, font
;
4732 CHECK_FONT_SPEC (spec
);
4735 return (font_match_p (spec
, font
) ? Qt
: Qnil
);
4738 DEFUN ("font-at", Ffont_at
, Sfont_at
, 1, 3, 0,
4739 doc
: /* Return a font-object for displaying a character at POSITION.
4740 Optional second arg WINDOW, if non-nil, is a window displaying
4741 the current buffer. It defaults to the currently selected window. */)
4742 (position
, window
, string
)
4743 Lisp_Object position
, window
, string
;
4750 CHECK_NUMBER_COERCE_MARKER (position
);
4751 pos
= XINT (position
);
4752 if (pos
< BEGV
|| pos
>= ZV
)
4753 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
4757 CHECK_NUMBER (position
);
4758 CHECK_STRING (string
);
4759 pos
= XINT (position
);
4760 if (pos
< 0 || pos
>= SCHARS (string
))
4761 args_out_of_range (string
, position
);
4764 window
= selected_window
;
4765 CHECK_LIVE_WINDOW (window
);
4766 w
= XWINDOW (window
);
4768 return font_at (-1, pos
, NULL
, w
, string
);
4772 DEFUN ("draw-string", Fdraw_string
, Sdraw_string
, 2, 2, 0,
4773 doc
: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4774 The value is a number of glyphs drawn.
4775 Type C-l to recover what previously shown. */)
4776 (font_object
, string
)
4777 Lisp_Object font_object
, string
;
4779 Lisp_Object frame
= selected_frame
;
4780 FRAME_PTR f
= XFRAME (frame
);
4786 CHECK_FONT_GET_OBJECT (font_object
, font
);
4787 CHECK_STRING (string
);
4788 len
= SCHARS (string
);
4789 code
= alloca (sizeof (unsigned) * len
);
4790 for (i
= 0; i
< len
; i
++)
4792 Lisp_Object ch
= Faref (string
, make_number (i
));
4796 code
[i
] = font
->driver
->encode_char (font
, c
);
4797 if (code
[i
] == FONT_INVALID_CODE
)
4800 face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4802 if (font
->driver
->prepare_face
)
4803 font
->driver
->prepare_face (f
, face
);
4804 width
= font
->driver
->text_extents (font
, code
, i
, NULL
);
4805 len
= font
->driver
->draw_text (f
, face
, 0, font
->ascent
, code
, i
, width
);
4806 if (font
->driver
->done_face
)
4807 font
->driver
->done_face (f
, face
);
4809 return make_number (len
);
4813 #endif /* FONT_DEBUG */
4815 #ifdef HAVE_WINDOW_SYSTEM
4817 DEFUN ("font-info", Ffont_info
, Sfont_info
, 1, 2, 0,
4818 doc
: /* Return information about a font named NAME on frame FRAME.
4819 If FRAME is omitted or nil, use the selected frame.
4820 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
4821 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4823 OPENED-NAME is the name used for opening the font,
4824 FULL-NAME is the full name of the font,
4825 SIZE is the maximum bound width of the font,
4826 HEIGHT is the height of the font,
4827 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4828 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4829 how to compose characters.
4830 If the named font is not yet loaded, return nil. */)
4832 Lisp_Object name
, frame
;
4837 Lisp_Object font_object
;
4839 (*check_window_system_func
) ();
4842 CHECK_STRING (name
);
4844 frame
= selected_frame
;
4845 CHECK_LIVE_FRAME (frame
);
4850 int fontset
= fs_query_fontset (name
, 0);
4853 name
= fontset_ascii (fontset
);
4854 font_object
= font_open_by_name (f
, (char *) SDATA (name
));
4856 else if (FONT_OBJECT_P (name
))
4858 else if (FONT_ENTITY_P (name
))
4859 font_object
= font_open_entity (f
, name
, 0);
4862 struct face
*face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4863 Lisp_Object entity
= font_matching_entity (f
, face
->lface
, name
);
4865 font_object
= ! NILP (entity
) ? font_open_entity (f
, entity
, 0) : Qnil
;
4867 if (NILP (font_object
))
4869 font
= XFONT_OBJECT (font_object
);
4871 info
= Fmake_vector (make_number (7), Qnil
);
4872 XVECTOR (info
)->contents
[0] = AREF (font_object
, FONT_NAME_INDEX
);
4873 XVECTOR (info
)->contents
[1] = AREF (font_object
, FONT_NAME_INDEX
);
4874 XVECTOR (info
)->contents
[2] = make_number (font
->pixel_size
);
4875 XVECTOR (info
)->contents
[3] = make_number (font
->height
);
4876 XVECTOR (info
)->contents
[4] = make_number (font
->baseline_offset
);
4877 XVECTOR (info
)->contents
[5] = make_number (font
->relative_compose
);
4878 XVECTOR (info
)->contents
[6] = make_number (font
->default_ascent
);
4881 /* As font_object is still in FONT_OBJLIST of the entity, we can't
4882 close it now. Perhaps, we should manage font-objects
4883 by `reference-count'. */
4884 font_close_object (f
, font_object
);
4891 #define BUILD_STYLE_TABLE(TBL) \
4892 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
4895 build_style_table (entry
, nelement
)
4896 struct table_entry
*entry
;
4900 Lisp_Object table
, elt
;
4902 table
= Fmake_vector (make_number (nelement
), Qnil
);
4903 for (i
= 0; i
< nelement
; i
++)
4905 for (j
= 0; entry
[i
].names
[j
]; j
++);
4906 elt
= Fmake_vector (make_number (j
+ 1), Qnil
);
4907 ASET (elt
, 0, make_number (entry
[i
].numeric
));
4908 for (j
= 0; entry
[i
].names
[j
]; j
++)
4909 ASET (elt
, j
+ 1, intern (entry
[i
].names
[j
]));
4910 ASET (table
, i
, elt
);
4915 static Lisp_Object Vfont_log
;
4916 static int font_log_env_checked
;
4918 /* The deferred font-log data of the form [ACTION ARG RESULT].
4919 If ACTION is not nil, that is added to the log when font_add_log is
4920 called next time. At that time, ACTION is set back to nil. */
4921 static Lisp_Object Vfont_log_deferred
;
4923 /* Prepend the font-related logging data in Vfont_log if it is not
4924 `t'. ACTION describes a kind of font-related action (e.g. listing,
4925 opening), ARG is the argument for the action, and RESULT is the
4926 result of the action. */
4928 font_add_log (action
, arg
, result
)
4930 Lisp_Object arg
, result
;
4932 Lisp_Object tail
, val
;
4935 if (! font_log_env_checked
)
4937 Vfont_log
= egetenv ("EMACS_FONT_LOG") ? Qnil
: Qt
;
4938 font_log_env_checked
= 1;
4940 if (EQ (Vfont_log
, Qt
))
4942 if (STRINGP (AREF (Vfont_log_deferred
, 0)))
4944 char *str
= (char *) SDATA (AREF (Vfont_log_deferred
, 0));
4946 ASET (Vfont_log_deferred
, 0, Qnil
);
4947 font_add_log (str
, AREF (Vfont_log_deferred
, 1),
4948 AREF (Vfont_log_deferred
, 2));
4953 Lisp_Object tail
, elt
;
4954 Lisp_Object equalstr
= build_string ("=");
4956 val
= Ffont_xlfd_name (arg
, Qt
);
4957 for (tail
= AREF (arg
, FONT_EXTRA_INDEX
); CONSP (tail
);
4961 if (EQ (XCAR (elt
), QCscript
)
4962 && SYMBOLP (XCDR (elt
)))
4963 val
= concat3 (val
, SYMBOL_NAME (QCscript
),
4964 concat2 (equalstr
, SYMBOL_NAME (XCDR (elt
))));
4965 else if (EQ (XCAR (elt
), QClang
)
4966 && SYMBOLP (XCDR (elt
)))
4967 val
= concat3 (val
, SYMBOL_NAME (QClang
),
4968 concat2 (equalstr
, SYMBOL_NAME (XCDR (elt
))));
4969 else if (EQ (XCAR (elt
), QCotf
)
4970 && CONSP (XCDR (elt
)) && SYMBOLP (XCAR (XCDR (elt
))))
4971 val
= concat3 (val
, SYMBOL_NAME (QCotf
),
4973 SYMBOL_NAME (XCAR (XCDR (elt
)))));
4979 val
= Ffont_xlfd_name (result
, Qt
);
4980 if (! FONT_SPEC_P (result
))
4981 val
= concat3 (SYMBOL_NAME (AREF (result
, FONT_TYPE_INDEX
)),
4982 build_string (":"), val
);
4985 else if (CONSP (result
))
4987 result
= Fcopy_sequence (result
);
4988 for (tail
= result
; CONSP (tail
); tail
= XCDR (tail
))
4992 val
= Ffont_xlfd_name (val
, Qt
);
4993 XSETCAR (tail
, val
);
4996 else if (VECTORP (result
))
4998 result
= Fcopy_sequence (result
);
4999 for (i
= 0; i
< ASIZE (result
); i
++)
5001 val
= AREF (result
, i
);
5003 val
= Ffont_xlfd_name (val
, Qt
);
5004 ASET (result
, i
, val
);
5007 Vfont_log
= Fcons (list3 (intern (action
), arg
, result
), Vfont_log
);
5010 /* Record a font-related logging data to be added to Vfont_log when
5011 font_add_log is called next time. ACTION, ARG, RESULT are the same
5015 font_deferred_log (action
, arg
, result
)
5017 Lisp_Object arg
, result
;
5019 ASET (Vfont_log_deferred
, 0, build_string (action
));
5020 ASET (Vfont_log_deferred
, 1, arg
);
5021 ASET (Vfont_log_deferred
, 2, result
);
5024 extern void syms_of_ftfont
P_ (());
5025 extern void syms_of_xfont
P_ (());
5026 extern void syms_of_xftfont
P_ (());
5027 extern void syms_of_ftxfont
P_ (());
5028 extern void syms_of_bdffont
P_ (());
5029 extern void syms_of_w32font
P_ (());
5030 extern void syms_of_atmfont
P_ (());
5031 extern void syms_of_nsfont
P_ (());
5036 sort_shift_bits
[FONT_TYPE_INDEX
] = 0;
5037 sort_shift_bits
[FONT_SLANT_INDEX
] = 2;
5038 sort_shift_bits
[FONT_WEIGHT_INDEX
] = 9;
5039 sort_shift_bits
[FONT_SIZE_INDEX
] = 16;
5040 sort_shift_bits
[FONT_WIDTH_INDEX
] = 23;
5041 /* Note that the other elements in sort_shift_bits are not used. */
5043 staticpro (&font_charset_alist
);
5044 font_charset_alist
= Qnil
;
5046 DEFSYM (Qfont_spec
, "font-spec");
5047 DEFSYM (Qfont_entity
, "font-entity");
5048 DEFSYM (Qfont_object
, "font-object");
5050 DEFSYM (Qopentype
, "opentype");
5052 DEFSYM (Qascii_0
, "ascii-0");
5053 DEFSYM (Qiso8859_1
, "iso8859-1");
5054 DEFSYM (Qiso10646_1
, "iso10646-1");
5055 DEFSYM (Qunicode_bmp
, "unicode-bmp");
5056 DEFSYM (Qunicode_sip
, "unicode-sip");
5060 DEFSYM (QCotf
, ":otf");
5061 DEFSYM (QClang
, ":lang");
5062 DEFSYM (QCscript
, ":script");
5063 DEFSYM (QCantialias
, ":antialias");
5065 DEFSYM (QCfoundry
, ":foundry");
5066 DEFSYM (QCadstyle
, ":adstyle");
5067 DEFSYM (QCregistry
, ":registry");
5068 DEFSYM (QCspacing
, ":spacing");
5069 DEFSYM (QCdpi
, ":dpi");
5070 DEFSYM (QCscalable
, ":scalable");
5071 DEFSYM (QCavgwidth
, ":avgwidth");
5072 DEFSYM (QCfont_entity
, ":font-entity");
5073 DEFSYM (QCfc_unknown_spec
, ":fc-unknown-spec");
5080 staticpro (&null_vector
);
5081 null_vector
= Fmake_vector (make_number (0), Qnil
);
5083 staticpro (&scratch_font_spec
);
5084 scratch_font_spec
= Ffont_spec (0, NULL
);
5085 staticpro (&scratch_font_prefer
);
5086 scratch_font_prefer
= Ffont_spec (0, NULL
);
5088 staticpro (&Vfont_log_deferred
);
5089 Vfont_log_deferred
= Fmake_vector (make_number (3), Qnil
);
5093 staticpro (&otf_list
);
5095 #endif /* HAVE_LIBOTF */
5099 defsubr (&Sfont_spec
);
5100 defsubr (&Sfont_get
);
5101 #ifdef HAVE_WINDOW_SYSTEM
5102 defsubr (&Sfont_face_attributes
);
5104 defsubr (&Sfont_put
);
5105 defsubr (&Slist_fonts
);
5106 defsubr (&Sfont_family_list
);
5107 defsubr (&Sfind_font
);
5108 defsubr (&Sfont_xlfd_name
);
5109 defsubr (&Sclear_font_cache
);
5110 defsubr (&Sfont_shape_gstring
);
5111 defsubr (&Sfont_variation_glyphs
);
5113 defsubr (&Sfont_drive_otf
);
5114 defsubr (&Sfont_otf_alternates
);
5118 defsubr (&Sopen_font
);
5119 defsubr (&Sclose_font
);
5120 defsubr (&Squery_font
);
5121 defsubr (&Sget_font_glyphs
);
5122 defsubr (&Sfont_match_p
);
5123 defsubr (&Sfont_at
);
5125 defsubr (&Sdraw_string
);
5127 #endif /* FONT_DEBUG */
5128 #ifdef HAVE_WINDOW_SYSTEM
5129 defsubr (&Sfont_info
);
5132 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist
,
5134 Alist of fontname patterns vs the corresponding encoding and repertory info.
5135 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5136 where ENCODING is a charset or a char-table,
5137 and REPERTORY is a charset, a char-table, or nil.
5139 If ENCODING and REPERTORY are the same, the element can have the form
5140 \(REGEXP . ENCODING).
5142 ENCODING is for converting a character to a glyph code of the font.
5143 If ENCODING is a charset, encoding a character by the charset gives
5144 the corresponding glyph code. If ENCODING is a char-table, looking up
5145 the table by a character gives the corresponding glyph code.
5147 REPERTORY specifies a repertory of characters supported by the font.
5148 If REPERTORY is a charset, all characters beloging to the charset are
5149 supported. If REPERTORY is a char-table, all characters who have a
5150 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5151 gets the repertory information by an opened font and ENCODING. */);
5152 Vfont_encoding_alist
= Qnil
;
5154 DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table
,
5155 doc
: /* Vector of valid font weight values.
5156 Each element has the form:
5157 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5158 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5159 Vfont_weight_table
= BUILD_STYLE_TABLE (weight_table
);
5161 DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table
,
5162 doc
: /* Vector of font slant symbols vs the corresponding numeric values.
5163 See `font-weight-table' for the format of the vector. */);
5164 Vfont_slant_table
= BUILD_STYLE_TABLE (slant_table
);
5166 DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table
,
5167 doc
: /* Alist of font width symbols vs the corresponding numeric values.
5168 See `font-weight-table' for the format of the vector. */);
5169 Vfont_width_table
= BUILD_STYLE_TABLE (width_table
);
5171 staticpro (&font_style_table
);
5172 font_style_table
= Fmake_vector (make_number (3), Qnil
);
5173 ASET (font_style_table
, 0, Vfont_weight_table
);
5174 ASET (font_style_table
, 1, Vfont_slant_table
);
5175 ASET (font_style_table
, 2, Vfont_width_table
);
5177 DEFVAR_LISP ("font-log", &Vfont_log
, doc
: /*
5178 *Logging list of font related actions and results.
5179 The value t means to suppress the logging.
5180 The initial value is set to nil if the environment variable
5181 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5184 #ifdef HAVE_WINDOW_SYSTEM
5185 #ifdef HAVE_FREETYPE
5187 #ifdef HAVE_X_WINDOWS
5192 #endif /* HAVE_XFT */
5193 #endif /* HAVE_X_WINDOWS */
5194 #else /* not HAVE_FREETYPE */
5195 #ifdef HAVE_X_WINDOWS
5197 #endif /* HAVE_X_WINDOWS */
5198 #endif /* not HAVE_FREETYPE */
5201 #endif /* HAVE_BDFFONT */
5204 #endif /* WINDOWSNT */
5207 #endif /* HAVE_NS */
5208 #endif /* HAVE_WINDOW_SYSTEM */
5211 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
5212 (do not change this comment) */