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/>. */
34 #include "dispextern.h"
36 #include "character.h"
37 #include "composite.h"
43 #endif /* HAVE_X_WINDOWS */
47 #endif /* HAVE_NTGUI */
57 Lisp_Object Qfont_spec
, Qfont_entity
, Qfont_object
;
60 extern Lisp_Object Qfontsize
;
63 Lisp_Object Qopentype
;
65 /* Important character set strings. */
66 Lisp_Object Qascii_0
, Qiso8859_1
, Qiso10646_1
, Qunicode_bmp
, Qunicode_sip
;
69 #define DEFAULT_ENCODING Qiso10646_1
71 #define DEFAULT_ENCODING Qiso8859_1
74 /* Special vector of zero length. This is repeatedly used by (struct
75 font_driver *)->list when a specified font is not found. */
76 static Lisp_Object null_vector
;
78 static Lisp_Object Vfont_weight_table
, Vfont_slant_table
, Vfont_width_table
;
80 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
81 static Lisp_Object font_style_table
;
83 /* Structure used for tables mapping weight, slant, and width numeric
84 values and their names. */
89 /* The first one is a valid name as a face attribute.
90 The second one (if any) is a typical name in XLFD field. */
95 /* Table of weight numeric values and their names. This table must be
96 sorted by numeric values in ascending order. */
98 static struct table_entry weight_table
[] =
101 { 20, { "ultra-light", "ultralight" }},
102 { 40, { "extra-light", "extralight" }},
104 { 75, { "semi-light", "semilight", "demilight", "book" }},
105 { 100, { "normal", "medium", "regular" }},
106 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
108 { 205, { "extra-bold", "extrabold" }},
109 { 210, { "ultra-bold", "ultrabold", "black" }}
112 /* Table of slant numeric values and their names. This table must be
113 sorted by numeric values in ascending order. */
115 static struct table_entry slant_table
[] =
117 { 0, { "reverse-oblique", "ro" }},
118 { 10, { "reverse-italic", "ri" }},
119 { 100, { "normal", "r" }},
120 { 200, { "italic" ,"i", "ot" }},
121 { 210, { "oblique", "o" }}
124 /* Table of width numeric values and their names. This table must be
125 sorted by numeric values in ascending order. */
127 static struct table_entry width_table
[] =
129 { 50, { "ultra-condensed", "ultracondensed" }},
130 { 63, { "extra-condensed", "extracondensed" }},
131 { 75, { "condensed", "compressed", "narrow" }},
132 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
133 { 100, { "normal", "medium", "regular" }},
134 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
135 { 125, { "expanded" }},
136 { 150, { "extra-expanded", "extraexpanded" }},
137 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
140 extern Lisp_Object Qnormal
;
142 /* Symbols representing keys of normal font properties. */
143 extern Lisp_Object QCtype
, QCfamily
, QCweight
, QCslant
, QCwidth
;
144 extern Lisp_Object QCheight
, QCsize
, QCname
;
146 Lisp_Object QCfoundry
, QCadstyle
, QCregistry
;
147 /* Symbols representing keys of font extra info. */
148 Lisp_Object QCspacing
, QCdpi
, QCscalable
, QCotf
, QClang
, QCscript
, QCavgwidth
;
149 Lisp_Object QCantialias
, QCfont_entity
, QCfc_unknown_spec
;
150 /* Symbols representing values of font spacing property. */
151 Lisp_Object Qc
, Qm
, Qp
, Qd
;
153 Lisp_Object Vfont_encoding_alist
;
155 /* Alist of font registry symbol and the corresponding charsets
156 information. The information is retrieved from
157 Vfont_encoding_alist on demand.
159 Eash element has the form:
160 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
164 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
165 encodes a character code to a glyph code of a font, and
166 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
167 character is supported by a font.
169 The latter form means that the information for REGISTRY couldn't be
171 static Lisp_Object font_charset_alist
;
173 /* List of all font drivers. Each font-backend (XXXfont.c) calls
174 register_font_driver in syms_of_XXXfont to register its font-driver
176 static struct font_driver_list
*font_driver_list
;
180 /* Creaters of font-related Lisp object. */
185 Lisp_Object font_spec
;
186 struct font_spec
*spec
187 = ((struct font_spec
*)
188 allocate_pseudovector (VECSIZE (struct font_spec
),
189 FONT_SPEC_MAX
, PVEC_FONT
));
190 XSETFONT (font_spec
, spec
);
197 Lisp_Object font_entity
;
198 struct font_entity
*entity
199 = ((struct font_entity
*)
200 allocate_pseudovector (VECSIZE (struct font_entity
),
201 FONT_ENTITY_MAX
, PVEC_FONT
));
202 XSETFONT (font_entity
, entity
);
206 /* Create a font-object whose structure size is SIZE. If ENTITY is
207 not nil, copy properties from ENTITY to the font-object. If
208 PIXELSIZE is positive, set the `size' property to PIXELSIZE. */
210 font_make_object (size
, entity
, pixelsize
)
215 Lisp_Object font_object
;
217 = (struct font
*) allocate_pseudovector (size
, FONT_OBJECT_MAX
, PVEC_FONT
);
220 XSETFONT (font_object
, font
);
224 for (i
= 1; i
< FONT_SPEC_MAX
; i
++)
225 font
->props
[i
] = AREF (entity
, i
);
226 if (! NILP (AREF (entity
, FONT_EXTRA_INDEX
)))
227 font
->props
[FONT_EXTRA_INDEX
]
228 = Fcopy_sequence (AREF (entity
, FONT_EXTRA_INDEX
));
231 font
->props
[FONT_SIZE_INDEX
] = make_number (pixelsize
);
237 static int font_pixel_size
P_ ((FRAME_PTR f
, Lisp_Object
));
238 static Lisp_Object font_open_entity
P_ ((FRAME_PTR
, Lisp_Object
, int));
239 static Lisp_Object font_matching_entity
P_ ((FRAME_PTR
, Lisp_Object
*,
242 /* Number of registered font drivers. */
243 static int num_font_drivers
;
246 /* Return a Lispy value of a font property value at STR and LEN bytes.
247 If STR is "*", it returns nil.
248 If FORCE_SYMBOL is zero and all characters in STR are digits, it
249 returns an integer. Otherwise, it returns a symbol interned from
253 font_intern_prop (str
, len
, force_symbol
)
262 if (len
== 1 && *str
== '*')
264 if (!force_symbol
&& len
>=1 && isdigit (*str
))
266 for (i
= 1; i
< len
; i
++)
267 if (! isdigit (str
[i
]))
270 return make_number (atoi (str
));
273 /* The following code is copied from the function intern (in lread.c). */
275 if (!VECTORP (obarray
) || XVECTOR (obarray
)->size
== 0)
276 obarray
= check_obarray (obarray
);
277 tem
= oblookup (obarray
, str
, len
, len
);
280 return Fintern (make_unibyte_string (str
, len
), obarray
);
283 /* Return a pixel size of font-spec SPEC on frame F. */
286 font_pixel_size (f
, spec
)
290 #ifdef HAVE_WINDOW_SYSTEM
291 Lisp_Object size
= AREF (spec
, FONT_SIZE_INDEX
);
300 font_assert (FLOATP (size
));
301 point_size
= XFLOAT_DATA (size
);
302 val
= AREF (spec
, FONT_DPI_INDEX
);
307 pixel_size
= POINT_TO_PIXEL (point_size
, dpi
);
315 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
316 font vector. If VAL is not valid (i.e. not registered in
317 font_style_table), return -1 if NOERROR is zero, and return a
318 proper index if NOERROR is nonzero. In that case, register VAL in
319 font_style_table if VAL is a symbol, and return a closest index if
320 VAL is an integer. */
323 font_style_to_value (prop
, val
, noerror
)
324 enum font_property_index prop
;
328 Lisp_Object table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
329 int len
= ASIZE (table
);
335 Lisp_Object args
[2], elt
;
337 /* At first try exact match. */
338 for (i
= 0; i
< len
; i
++)
339 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
340 if (EQ (val
, AREF (AREF (table
, i
), j
)))
341 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
342 | (i
<< 4) | (j
- 1));
343 /* Try also with case-folding match. */
344 s
= SDATA (SYMBOL_NAME (val
));
345 for (i
= 0; i
< len
; i
++)
346 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
348 elt
= AREF (AREF (table
, i
), j
);
349 if (xstrcasecmp (s
, SDATA (SYMBOL_NAME (elt
))) == 0)
350 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
351 | (i
<< 4) | (j
- 1));
357 elt
= Fmake_vector (make_number (2), make_number (255));
360 args
[1] = Fmake_vector (make_number (1), elt
);
361 ASET (font_style_table
, prop
- FONT_WEIGHT_INDEX
, Fvconcat (2, args
));
362 return (255 << 8) | (i
<< 4);
367 int numeric
= XINT (val
);
369 for (i
= 0, last_n
= -1; i
< len
; i
++)
371 int n
= XINT (AREF (AREF (table
, i
), 0));
374 return (n
<< 8) | (i
<< 4);
379 return ((i
== 0 || n
- numeric
< numeric
- last_n
)
380 ? (n
<< 8) | (i
<< 4): (last_n
<< 8 | ((i
- 1) << 4)));
386 return ((last_n
<< 8) | ((i
- 1) << 4));
391 font_style_symbolic (font
, prop
, for_face
)
393 enum font_property_index prop
;
396 Lisp_Object val
= AREF (font
, prop
);
397 Lisp_Object table
, elt
;
402 table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
403 i
= XINT (val
) & 0xFF;
404 font_assert (((i
>> 4) & 0xF) < ASIZE (table
));
405 elt
= AREF (table
, ((i
>> 4) & 0xF));
406 font_assert ((i
& 0xF) + 1 < ASIZE (elt
));
407 return (for_face
? AREF (elt
, 1) : AREF (elt
, (i
& 0xF) + 1));
410 extern Lisp_Object Vface_alternative_font_family_alist
;
412 extern Lisp_Object find_font_encoding
P_ ((Lisp_Object
));
415 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
416 FONTNAME. ENCODING is a charset symbol that specifies the encoding
417 of the font. REPERTORY is a charset symbol or nil. */
420 find_font_encoding (fontname
)
421 Lisp_Object fontname
;
423 Lisp_Object tail
, elt
;
425 for (tail
= Vfont_encoding_alist
; CONSP (tail
); tail
= XCDR (tail
))
429 && STRINGP (XCAR (elt
))
430 && fast_string_match_ignore_case (XCAR (elt
), fontname
) >= 0
431 && (SYMBOLP (XCDR (elt
))
432 ? CHARSETP (XCDR (elt
))
433 : CONSP (XCDR (elt
)) && CHARSETP (XCAR (XCDR (elt
)))))
436 /* We don't know the encoding of this font. Let's assume `ascii'. */
440 /* Return encoding charset and repertory charset for REGISTRY in
441 ENCODING and REPERTORY correspondingly. If correct information for
442 REGISTRY is available, return 0. Otherwise return -1. */
445 font_registry_charsets (registry
, encoding
, repertory
)
446 Lisp_Object registry
;
447 struct charset
**encoding
, **repertory
;
450 int encoding_id
, repertory_id
;
452 val
= Fassoc_string (registry
, font_charset_alist
, Qt
);
458 encoding_id
= XINT (XCAR (val
));
459 repertory_id
= XINT (XCDR (val
));
463 val
= find_font_encoding (SYMBOL_NAME (registry
));
464 if (SYMBOLP (val
) && CHARSETP (val
))
466 encoding_id
= repertory_id
= XINT (CHARSET_SYMBOL_ID (val
));
468 else if (CONSP (val
))
470 if (! CHARSETP (XCAR (val
)))
472 encoding_id
= XINT (CHARSET_SYMBOL_ID (XCAR (val
)));
473 if (NILP (XCDR (val
)))
477 if (! CHARSETP (XCDR (val
)))
479 repertory_id
= XINT (CHARSET_SYMBOL_ID (XCDR (val
)));
484 val
= Fcons (make_number (encoding_id
), make_number (repertory_id
));
486 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, val
), Qnil
));
490 *encoding
= CHARSET_FROM_ID (encoding_id
);
492 *repertory
= repertory_id
>= 0 ? CHARSET_FROM_ID (repertory_id
) : NULL
;
497 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, Qnil
), Qnil
));
502 /* Font property value validaters. See the comment of
503 font_property_table for the meaning of the arguments. */
505 static Lisp_Object font_prop_validate
P_ ((int, Lisp_Object
, Lisp_Object
));
506 static Lisp_Object font_prop_validate_symbol
P_ ((Lisp_Object
, Lisp_Object
));
507 static Lisp_Object font_prop_validate_style
P_ ((Lisp_Object
, Lisp_Object
));
508 static Lisp_Object font_prop_validate_non_neg
P_ ((Lisp_Object
, Lisp_Object
));
509 static Lisp_Object font_prop_validate_spacing
P_ ((Lisp_Object
, Lisp_Object
));
510 static int get_font_prop_index
P_ ((Lisp_Object
));
513 font_prop_validate_symbol (prop
, val
)
514 Lisp_Object prop
, val
;
517 val
= Fintern (val
, Qnil
);
520 else if (EQ (prop
, QCregistry
))
521 val
= Fintern (Fdowncase (SYMBOL_NAME (val
)), Qnil
);
527 font_prop_validate_style (style
, val
)
528 Lisp_Object style
, val
;
530 enum font_property_index prop
= (EQ (style
, QCweight
) ? FONT_WEIGHT_INDEX
531 : EQ (style
, QCslant
) ? FONT_SLANT_INDEX
538 >= ASIZE (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
)))
542 Lisp_Object elt
= AREF (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
), (n
>> 4) & 0xF);
544 if ((n
& 0xF) + 1 >= ASIZE (elt
))
546 else if (XINT (AREF (elt
, 0)) != (n
>> 8))
550 else if (SYMBOLP (val
))
552 int n
= font_style_to_value (prop
, val
, 0);
554 val
= n
>= 0 ? make_number (n
) : Qerror
;
562 font_prop_validate_non_neg (prop
, val
)
563 Lisp_Object prop
, val
;
565 return (NATNUMP (val
) || (FLOATP (val
) && XFLOAT_DATA (val
) >= 0)
570 font_prop_validate_spacing (prop
, val
)
571 Lisp_Object prop
, val
;
573 if (NILP (val
) || (NATNUMP (val
) && XINT (val
) <= FONT_SPACING_CHARCELL
))
575 if (SYMBOLP (val
) && SBYTES (SYMBOL_NAME (val
)) == 1)
577 char spacing
= SDATA (SYMBOL_NAME (val
))[0];
579 if (spacing
== 'c' || spacing
== 'C')
580 return make_number (FONT_SPACING_CHARCELL
);
581 if (spacing
== 'm' || spacing
== 'M')
582 return make_number (FONT_SPACING_MONO
);
583 if (spacing
== 'p' || spacing
== 'P')
584 return make_number (FONT_SPACING_PROPORTIONAL
);
585 if (spacing
== 'd' || spacing
== 'D')
586 return make_number (FONT_SPACING_DUAL
);
592 font_prop_validate_otf (prop
, val
)
593 Lisp_Object prop
, val
;
595 Lisp_Object tail
, tmp
;
598 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
599 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
600 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
603 if (! SYMBOLP (XCAR (val
)))
608 if (! CONSP (tail
) || ! SYMBOLP (XCAR (val
)))
610 for (i
= 0; i
< 2; i
++)
617 for (tmp
= XCAR (tail
); CONSP (tmp
); tmp
= XCDR (tmp
))
618 if (! SYMBOLP (XCAR (tmp
)))
626 /* Structure of known font property keys and validater of the
630 /* Pointer to the key symbol. */
632 /* Function to validate PROP's value VAL, or NULL if any value is
633 ok. The value is VAL or its regularized value if VAL is valid,
634 and Qerror if not. */
635 Lisp_Object (*validater
) P_ ((Lisp_Object prop
, Lisp_Object val
));
636 } font_property_table
[] =
637 { { &QCtype
, font_prop_validate_symbol
},
638 { &QCfoundry
, font_prop_validate_symbol
},
639 { &QCfamily
, font_prop_validate_symbol
},
640 { &QCadstyle
, font_prop_validate_symbol
},
641 { &QCregistry
, font_prop_validate_symbol
},
642 { &QCweight
, font_prop_validate_style
},
643 { &QCslant
, font_prop_validate_style
},
644 { &QCwidth
, font_prop_validate_style
},
645 { &QCsize
, font_prop_validate_non_neg
},
646 { &QCdpi
, font_prop_validate_non_neg
},
647 { &QCspacing
, font_prop_validate_spacing
},
648 { &QCavgwidth
, font_prop_validate_non_neg
},
649 /* The order of the above entries must match with enum
650 font_property_index. */
651 { &QClang
, font_prop_validate_symbol
},
652 { &QCscript
, font_prop_validate_symbol
},
653 { &QCotf
, font_prop_validate_otf
}
656 /* Size (number of elements) of the above table. */
657 #define FONT_PROPERTY_TABLE_SIZE \
658 ((sizeof font_property_table) / (sizeof *font_property_table))
660 /* Return an index number of font property KEY or -1 if KEY is not an
661 already known property. */
664 get_font_prop_index (key
)
669 for (i
= 0; i
< FONT_PROPERTY_TABLE_SIZE
; i
++)
670 if (EQ (key
, *font_property_table
[i
].key
))
675 /* Validate the font property. The property key is specified by the
676 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
677 signal an error. The value is VAL or the regularized one. */
680 font_prop_validate (idx
, prop
, val
)
682 Lisp_Object prop
, val
;
684 Lisp_Object validated
;
689 prop
= *font_property_table
[idx
].key
;
692 idx
= get_font_prop_index (prop
);
696 validated
= (font_property_table
[idx
].validater
) (prop
, val
);
697 if (EQ (validated
, Qerror
))
698 signal_error ("invalid font property", Fcons (prop
, val
));
703 /* Store VAL as a value of extra font property PROP in FONT while
704 keeping the sorting order. Don't check the validity of VAL. */
707 font_put_extra (font
, prop
, val
)
708 Lisp_Object font
, prop
, val
;
710 Lisp_Object extra
= AREF (font
, FONT_EXTRA_INDEX
);
711 Lisp_Object slot
= (NILP (extra
) ? Qnil
: assq_no_quit (prop
, extra
));
715 Lisp_Object prev
= Qnil
;
718 && NILP (Fstring_lessp (prop
, XCAR (XCAR (extra
)))))
719 prev
= extra
, extra
= XCDR (extra
);
721 ASET (font
, FONT_EXTRA_INDEX
, Fcons (Fcons (prop
, val
), extra
));
723 XSETCDR (prev
, Fcons (Fcons (prop
, val
), extra
));
731 /* Font name parser and unparser */
733 static int parse_matrix
P_ ((char *));
734 static int font_expand_wildcards
P_ ((Lisp_Object
*, int));
735 static int font_parse_name
P_ ((char *, Lisp_Object
));
737 /* An enumerator for each field of an XLFD font name. */
738 enum xlfd_field_index
757 /* An enumerator for mask bit corresponding to each XLFD field. */
760 XLFD_FOUNDRY_MASK
= 0x0001,
761 XLFD_FAMILY_MASK
= 0x0002,
762 XLFD_WEIGHT_MASK
= 0x0004,
763 XLFD_SLANT_MASK
= 0x0008,
764 XLFD_SWIDTH_MASK
= 0x0010,
765 XLFD_ADSTYLE_MASK
= 0x0020,
766 XLFD_PIXEL_MASK
= 0x0040,
767 XLFD_POINT_MASK
= 0x0080,
768 XLFD_RESX_MASK
= 0x0100,
769 XLFD_RESY_MASK
= 0x0200,
770 XLFD_SPACING_MASK
= 0x0400,
771 XLFD_AVGWIDTH_MASK
= 0x0800,
772 XLFD_REGISTRY_MASK
= 0x1000,
773 XLFD_ENCODING_MASK
= 0x2000
777 /* Parse P pointing the pixel/point size field of the form
778 `[A B C D]' which specifies a transformation matrix:
784 by which all glyphs of the font are transformed. The spec says
785 that scalar value N for the pixel/point size is equivalent to:
786 A = N * resx/resy, B = C = 0, D = N.
788 Return the scalar value N if the form is valid. Otherwise return
799 for (i
= 0, p
++; i
< 4 && *p
&& *p
!= ']'; i
++)
802 matrix
[i
] = - strtod (p
+ 1, &end
);
804 matrix
[i
] = strtod (p
, &end
);
807 return (i
== 4 ? (int) matrix
[3] : -1);
810 /* Expand a wildcard field in FIELD (the first N fields are filled) to
811 multiple fields to fill in all 14 XLFD fields while restring a
812 field position by its contents. */
815 font_expand_wildcards (field
, n
)
816 Lisp_Object field
[XLFD_LAST_INDEX
];
820 Lisp_Object tmp
[XLFD_LAST_INDEX
];
821 /* Array of information about where this element can go. Nth
822 element is for Nth element of FIELD. */
824 /* Minimum possible field. */
826 /* Maxinum possible field. */
828 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
830 } range
[XLFD_LAST_INDEX
];
832 int range_from
, range_to
;
835 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
836 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
837 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
838 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
839 | XLFD_AVGWIDTH_MASK)
840 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
842 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
843 field. The value is shifted to left one bit by one in the
845 for (i
= 0, range_mask
= 0; i
<= 14 - n
; i
++)
846 range_mask
= (range_mask
<< 1) | 1;
848 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
849 position-based retriction for FIELD[I]. */
850 for (i
= 0, range_from
= 0, range_to
= 14 - n
; i
< n
;
851 i
++, range_from
++, range_to
++, range_mask
<<= 1)
853 Lisp_Object val
= field
[i
];
859 range
[i
].from
= range_from
;
860 range
[i
].to
= range_to
;
861 range
[i
].mask
= range_mask
;
865 /* The triplet FROM, TO, and MASK is a value-based
866 retriction for FIELD[I]. */
872 int numeric
= XINT (val
);
875 from
= to
= XLFD_ENCODING_INDEX
,
876 mask
= XLFD_ENCODING_MASK
;
877 else if (numeric
== 0)
878 from
= XLFD_PIXEL_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
879 mask
= XLFD_PIXEL_MASK
| XLFD_LARGENUM_MASK
;
880 else if (numeric
<= 48)
881 from
= to
= XLFD_PIXEL_INDEX
,
882 mask
= XLFD_PIXEL_MASK
;
884 from
= XLFD_POINT_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
885 mask
= XLFD_LARGENUM_MASK
;
887 else if (SBYTES (SYMBOL_NAME (val
)) == 0)
888 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ADSTYLE_INDEX
,
889 mask
= XLFD_NULL_MASK
;
891 from
= to
= XLFD_FOUNDRY_INDEX
, mask
= XLFD_FOUNDRY_MASK
;
894 Lisp_Object name
= SYMBOL_NAME (val
);
896 if (SDATA (name
)[SBYTES (name
) - 1] == '*')
897 from
= XLFD_REGISTRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
898 mask
= XLFD_REGENC_MASK
;
900 from
= to
= XLFD_ENCODING_INDEX
,
901 mask
= XLFD_ENCODING_MASK
;
903 else if (range_from
<= XLFD_WEIGHT_INDEX
904 && range_to
>= XLFD_WEIGHT_INDEX
905 && FONT_WEIGHT_NAME_NUMERIC (val
) >= 0)
906 from
= to
= XLFD_WEIGHT_INDEX
, mask
= XLFD_WEIGHT_MASK
;
907 else if (range_from
<= XLFD_SLANT_INDEX
908 && range_to
>= XLFD_SLANT_INDEX
909 && FONT_SLANT_NAME_NUMERIC (val
) >= 0)
910 from
= to
= XLFD_SLANT_INDEX
, mask
= XLFD_SLANT_MASK
;
911 else if (range_from
<= XLFD_SWIDTH_INDEX
912 && range_to
>= XLFD_SWIDTH_INDEX
913 && FONT_WIDTH_NAME_NUMERIC (val
) >= 0)
914 from
= to
= XLFD_SWIDTH_INDEX
, mask
= XLFD_SWIDTH_MASK
;
917 if (EQ (val
, Qc
) || EQ (val
, Qm
) || EQ (val
, Qp
) || EQ (val
, Qd
))
918 from
= to
= XLFD_SPACING_INDEX
, mask
= XLFD_SPACING_MASK
;
920 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
921 mask
= XLFD_SYMBOL_MASK
;
924 /* Merge position-based and value-based restrictions. */
926 while (from
< range_from
)
927 mask
&= ~(1 << from
++);
928 while (from
< 14 && ! (mask
& (1 << from
)))
930 while (to
> range_to
)
931 mask
&= ~(1 << to
--);
932 while (to
>= 0 && ! (mask
& (1 << to
)))
936 range
[i
].from
= from
;
938 range
[i
].mask
= mask
;
940 if (from
> range_from
|| to
< range_to
)
942 /* The range is narrowed by value-based restrictions.
943 Reflect it to the other fields. */
945 /* Following fields should be after FROM. */
947 /* Preceding fields should be before TO. */
948 for (j
= i
- 1, from
--, to
--; j
>= 0; j
--, from
--, to
--)
950 /* Check FROM for non-wildcard field. */
951 if (! NILP (tmp
[j
]) && range
[j
].from
< from
)
953 while (range
[j
].from
< from
)
954 range
[j
].mask
&= ~(1 << range
[j
].from
++);
955 while (from
< 14 && ! (range
[j
].mask
& (1 << from
)))
957 range
[j
].from
= from
;
960 from
= range
[j
].from
;
961 if (range
[j
].to
> to
)
963 while (range
[j
].to
> to
)
964 range
[j
].mask
&= ~(1 << range
[j
].to
--);
965 while (to
>= 0 && ! (range
[j
].mask
& (1 << to
)))
978 /* Decide all fileds from restrictions in RANGE. */
979 for (i
= j
= 0; i
< n
; i
++)
981 if (j
< range
[i
].from
)
983 if (i
== 0 || ! NILP (tmp
[i
- 1]))
984 /* None of TMP[X] corresponds to Jth field. */
986 for (; j
< range
[i
].from
; j
++)
991 if (! NILP (tmp
[n
- 1]) && j
< XLFD_REGISTRY_INDEX
)
993 for (; j
< XLFD_LAST_INDEX
; j
++)
995 if (INTEGERP (field
[XLFD_ENCODING_INDEX
]))
996 field
[XLFD_ENCODING_INDEX
]
997 = Fintern (Fnumber_to_string (field
[XLFD_ENCODING_INDEX
]), Qnil
);
1002 #ifdef ENABLE_CHECKING
1003 /* Match a 14-field XLFD pattern against a full XLFD font name. */
1005 font_match_xlfd (char *pattern
, char *name
)
1007 while (*pattern
&& *name
)
1009 if (*pattern
== *name
)
1011 else if (*pattern
== '*')
1012 if (*name
== pattern
[1])
1023 /* Make sure the font object matches the XLFD font name. */
1025 font_check_xlfd_parse (Lisp_Object font
, char *name
)
1027 char name_check
[256];
1028 font_unparse_xlfd (font
, 0, name_check
, 255);
1029 return font_match_xlfd (name_check
, name
);
1035 /* Parse NAME (null terminated) as XLFD and store information in FONT
1036 (font-spec or font-entity). Size property of FONT is set as
1038 specified XLFD fields FONT property
1039 --------------------- -------------
1040 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
1041 POINT_SIZE and RESY calculated pixel size (Lisp integer)
1042 POINT_SIZE POINT_SIZE/10 (Lisp float)
1044 If NAME is successfully parsed, return 0. Otherwise return -1.
1046 FONT is usually a font-spec, but when this function is called from
1047 X font backend driver, it is a font-entity. In that case, NAME is
1048 a fully specified XLFD. */
1051 font_parse_xlfd (name
, font
)
1055 int len
= strlen (name
);
1057 char *f
[XLFD_LAST_INDEX
+ 1];
1062 /* Maximum XLFD name length is 255. */
1064 /* Accept "*-.." as a fully specified XLFD. */
1065 if (name
[0] == '*' && name
[1] == '-')
1066 i
= 1, f
[XLFD_FOUNDRY_INDEX
] = name
;
1069 for (p
= name
+ i
; *p
; p
++)
1073 if (i
== XLFD_LAST_INDEX
)
1078 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1079 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1081 if (i
== XLFD_LAST_INDEX
)
1083 /* Fully specified XLFD. */
1086 ASET (font
, FONT_FOUNDRY_INDEX
, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX
));
1087 ASET (font
, FONT_FAMILY_INDEX
, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX
));
1088 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1089 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1091 val
= INTERN_FIELD_SYM (i
);
1094 if ((n
= font_style_to_value (j
, INTERN_FIELD_SYM (i
), 0)) < 0)
1096 ASET (font
, j
, make_number (n
));
1099 ASET (font
, FONT_ADSTYLE_INDEX
, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX
));
1100 if (strcmp (f
[XLFD_REGISTRY_INDEX
], "*-*") == 0)
1101 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
1103 ASET (font
, FONT_REGISTRY_INDEX
,
1104 font_intern_prop (f
[XLFD_REGISTRY_INDEX
],
1105 f
[XLFD_LAST_INDEX
] - f
[XLFD_REGISTRY_INDEX
],
1107 p
= f
[XLFD_PIXEL_INDEX
];
1108 if (*p
== '[' && (pixel_size
= parse_matrix (p
)) >= 0)
1109 ASET (font
, FONT_SIZE_INDEX
, make_number (pixel_size
));
1112 val
= INTERN_FIELD (XLFD_PIXEL_INDEX
);
1114 ASET (font
, FONT_SIZE_INDEX
, val
);
1117 double point_size
= -1;
1119 font_assert (FONT_SPEC_P (font
));
1120 p
= f
[XLFD_POINT_INDEX
];
1122 point_size
= parse_matrix (p
);
1123 else if (isdigit (*p
))
1124 point_size
= atoi (p
), point_size
/= 10;
1125 if (point_size
>= 0)
1126 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1130 ASET (font
, FONT_DPI_INDEX
, INTERN_FIELD (XLFD_RESY_INDEX
));
1131 val
= INTERN_FIELD (XLFD_SPACING_INDEX
);
1134 val
= font_prop_validate_spacing (QCspacing
, val
);
1135 if (! INTEGERP (val
))
1137 ASET (font
, FONT_SPACING_INDEX
, val
);
1139 p
= f
[XLFD_AVGWIDTH_INDEX
];
1142 ASET (font
, FONT_AVGWIDTH_INDEX
,
1143 font_intern_prop (p
, f
[XLFD_REGISTRY_INDEX
] - 1 - p
, 0));
1147 int wild_card_found
= 0;
1148 Lisp_Object prop
[XLFD_LAST_INDEX
];
1150 if (FONT_ENTITY_P (font
))
1152 for (j
= 0; j
< i
; j
++)
1156 if (f
[j
][1] && f
[j
][1] != '-')
1159 wild_card_found
= 1;
1162 prop
[j
] = INTERN_FIELD (j
);
1164 prop
[j
] = font_intern_prop (f
[j
], f
[i
] - f
[j
], 0);
1166 if (! wild_card_found
)
1168 if (font_expand_wildcards (prop
, i
) < 0)
1171 ASET (font
, FONT_FOUNDRY_INDEX
, prop
[XLFD_FOUNDRY_INDEX
]);
1172 ASET (font
, FONT_FAMILY_INDEX
, prop
[XLFD_FAMILY_INDEX
]);
1173 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1174 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1175 if (! NILP (prop
[i
]))
1177 if ((n
= font_style_to_value (j
, prop
[i
], 1)) < 0)
1179 ASET (font
, j
, make_number (n
));
1181 ASET (font
, FONT_ADSTYLE_INDEX
, prop
[XLFD_ADSTYLE_INDEX
]);
1182 val
= prop
[XLFD_REGISTRY_INDEX
];
1185 val
= prop
[XLFD_ENCODING_INDEX
];
1187 val
= concat2 (build_string ("*-"), SYMBOL_NAME (val
));
1189 else if (NILP (prop
[XLFD_ENCODING_INDEX
]))
1190 val
= concat2 (SYMBOL_NAME (val
), build_string ("-*"));
1192 val
= concat3 (SYMBOL_NAME (val
), build_string ("-"),
1193 SYMBOL_NAME (prop
[XLFD_ENCODING_INDEX
]));
1195 ASET (font
, FONT_REGISTRY_INDEX
, Fintern (val
, Qnil
));
1197 if (INTEGERP (prop
[XLFD_PIXEL_INDEX
]))
1198 ASET (font
, FONT_SIZE_INDEX
, prop
[XLFD_PIXEL_INDEX
]);
1199 else if (INTEGERP (prop
[XLFD_POINT_INDEX
]))
1201 double point_size
= XINT (prop
[XLFD_POINT_INDEX
]);
1203 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
/ 10));
1206 if (INTEGERP (prop
[XLFD_RESX_INDEX
]))
1207 ASET (font
, FONT_DPI_INDEX
, prop
[XLFD_RESY_INDEX
]);
1208 if (! NILP (prop
[XLFD_SPACING_INDEX
]))
1210 val
= font_prop_validate_spacing (QCspacing
,
1211 prop
[XLFD_SPACING_INDEX
]);
1212 if (! INTEGERP (val
))
1214 ASET (font
, FONT_SPACING_INDEX
, val
);
1216 if (INTEGERP (prop
[XLFD_AVGWIDTH_INDEX
]))
1217 ASET (font
, FONT_AVGWIDTH_INDEX
, prop
[XLFD_AVGWIDTH_INDEX
]);
1223 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1224 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1225 0, use PIXEL_SIZE instead. */
1228 font_unparse_xlfd (font
, pixel_size
, name
, nbytes
)
1234 char *f
[XLFD_REGISTRY_INDEX
+ 1];
1238 font_assert (FONTP (font
));
1240 for (i
= FONT_FOUNDRY_INDEX
, j
= XLFD_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
;
1243 if (i
== FONT_ADSTYLE_INDEX
)
1244 j
= XLFD_ADSTYLE_INDEX
;
1245 else if (i
== FONT_REGISTRY_INDEX
)
1246 j
= XLFD_REGISTRY_INDEX
;
1247 val
= AREF (font
, i
);
1250 if (j
== XLFD_REGISTRY_INDEX
)
1251 f
[j
] = "*-*", len
+= 4;
1253 f
[j
] = "*", len
+= 2;
1258 val
= SYMBOL_NAME (val
);
1259 if (j
== XLFD_REGISTRY_INDEX
1260 && ! strchr ((char *) SDATA (val
), '-'))
1262 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1263 if (SDATA (val
)[SBYTES (val
) - 1] == '*')
1265 f
[j
] = alloca (SBYTES (val
) + 3);
1266 sprintf (f
[j
], "%s-*", SDATA (val
));
1267 len
+= SBYTES (val
) + 3;
1271 f
[j
] = alloca (SBYTES (val
) + 4);
1272 sprintf (f
[j
], "%s*-*", SDATA (val
));
1273 len
+= SBYTES (val
) + 4;
1277 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1281 for (i
= FONT_WEIGHT_INDEX
, j
= XLFD_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
;
1284 val
= font_style_symbolic (font
, i
, 0);
1286 f
[j
] = "*", len
+= 2;
1289 val
= SYMBOL_NAME (val
);
1290 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1294 val
= AREF (font
, FONT_SIZE_INDEX
);
1295 font_assert (NUMBERP (val
) || NILP (val
));
1303 f
[XLFD_PIXEL_INDEX
] = alloca (22);
1304 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "%d-*", i
) + 1;
1307 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1309 else if (FLOATP (val
))
1311 i
= XFLOAT_DATA (val
) * 10;
1312 f
[XLFD_PIXEL_INDEX
] = alloca (12);
1313 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "*-%d", i
) + 1;
1316 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1318 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1320 i
= XINT (AREF (font
, FONT_DPI_INDEX
));
1321 f
[XLFD_RESX_INDEX
] = alloca (22);
1322 len
+= sprintf (f
[XLFD_RESX_INDEX
],
1326 f
[XLFD_RESX_INDEX
] = "*-*", len
+= 4;
1327 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1329 int spacing
= XINT (AREF (font
, FONT_SPACING_INDEX
));
1331 f
[XLFD_SPACING_INDEX
] = (spacing
<= FONT_SPACING_PROPORTIONAL
? "p"
1332 : spacing
<= FONT_SPACING_DUAL
? "d"
1333 : spacing
<= FONT_SPACING_MONO
? "m"
1338 f
[XLFD_SPACING_INDEX
] = "*", len
+= 2;
1339 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1341 f
[XLFD_AVGWIDTH_INDEX
] = alloca (11);
1342 len
+= sprintf (f
[XLFD_AVGWIDTH_INDEX
],
1343 "%d", XINT (AREF (font
, FONT_AVGWIDTH_INDEX
))) + 1;
1346 f
[XLFD_AVGWIDTH_INDEX
] = "*", len
+= 2;
1347 len
++; /* for terminating '\0'. */
1350 return sprintf (name
, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1351 f
[XLFD_FOUNDRY_INDEX
], f
[XLFD_FAMILY_INDEX
],
1352 f
[XLFD_WEIGHT_INDEX
], f
[XLFD_SLANT_INDEX
],
1353 f
[XLFD_SWIDTH_INDEX
], f
[XLFD_ADSTYLE_INDEX
],
1354 f
[XLFD_PIXEL_INDEX
], f
[XLFD_RESX_INDEX
],
1355 f
[XLFD_SPACING_INDEX
], f
[XLFD_AVGWIDTH_INDEX
],
1356 f
[XLFD_REGISTRY_INDEX
]);
1359 /* Parse NAME (null terminated) and store information in FONT
1360 (font-spec or font-entity). NAME is supplied in either the
1361 Fontconfig or GTK font name format. If NAME is successfully
1362 parsed, return 0. Otherwise return -1.
1364 The fontconfig format is
1366 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]]
1370 FAMILY [PROPS...] [SIZE]
1372 This function tries to guess which format it is. */
1375 font_parse_fcname (name
, font
)
1380 char *size_beg
= NULL
, *size_end
= NULL
;
1381 char *props_beg
= NULL
, *family_end
= NULL
;
1382 int len
= strlen (name
);
1387 for (p
= name
; *p
; p
++)
1389 if (*p
== '\\' && p
[1])
1393 props_beg
= family_end
= p
;
1398 int decimal
= 0, size_found
= 1;
1399 for (q
= p
+ 1; *q
&& *q
!= ':'; q
++)
1402 if (*q
!= '.' || decimal
)
1421 /* A fontconfig name with size and/or property data. */
1422 if (family_end
> name
)
1425 family
= font_intern_prop (name
, family_end
- name
, 1);
1426 ASET (font
, FONT_FAMILY_INDEX
, family
);
1430 double point_size
= strtod (size_beg
, &size_end
);
1431 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1432 if (*size_end
== ':' && size_end
[1])
1433 props_beg
= size_end
;
1437 /* Now parse ":KEY=VAL" patterns. */
1440 for (p
= props_beg
; *p
; p
= q
)
1442 for (q
= p
+ 1; *q
&& *q
!= '=' && *q
!= ':'; q
++);
1445 /* Must be an enumerated value. */
1449 val
= font_intern_prop (p
, q
- p
, 1);
1451 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1453 if (PROP_MATCH ("light", 5)
1454 || PROP_MATCH ("medium", 6)
1455 || PROP_MATCH ("demibold", 8)
1456 || PROP_MATCH ("bold", 4)
1457 || PROP_MATCH ("black", 5))
1458 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, val
);
1459 else if (PROP_MATCH ("roman", 5)
1460 || PROP_MATCH ("italic", 6)
1461 || PROP_MATCH ("oblique", 7))
1462 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, val
);
1463 else if (PROP_MATCH ("charcell", 8))
1464 ASET (font
, FONT_SPACING_INDEX
,
1465 make_number (FONT_SPACING_CHARCELL
));
1466 else if (PROP_MATCH ("mono", 4))
1467 ASET (font
, FONT_SPACING_INDEX
,
1468 make_number (FONT_SPACING_MONO
));
1469 else if (PROP_MATCH ("proportional", 12))
1470 ASET (font
, FONT_SPACING_INDEX
,
1471 make_number (FONT_SPACING_PROPORTIONAL
));
1480 if (q
- p
== 10 && memcmp (p
+ 1, "pixelsize", 9) == 0)
1481 prop
= FONT_SIZE_INDEX
;
1484 key
= font_intern_prop (p
, q
- p
, 1);
1485 prop
= get_font_prop_index (key
);
1489 for (q
= p
; *q
&& *q
!= ':'; q
++);
1490 val
= font_intern_prop (p
, q
- p
, 0);
1492 if (prop
>= FONT_FOUNDRY_INDEX
1493 && prop
< FONT_EXTRA_INDEX
)
1494 ASET (font
, prop
, font_prop_validate (prop
, Qnil
, val
));
1496 Ffont_put (font
, key
, val
);
1504 /* Either a fontconfig-style name with no size and property
1505 data, or a GTK-style name. */
1507 int word_len
, prop_found
= 0;
1509 for (p
= name
; *p
; p
= *q
? q
+ 1 : q
)
1515 for (q
= p
+ 1; *q
&& *q
!= ' '; q
++)
1523 double point_size
= strtod (p
, &q
);
1524 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1529 for (q
= p
+ 1; *q
&& *q
!= ' '; q
++)
1530 if (*q
== '\\' && q
[1])
1534 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
1536 if (PROP_MATCH ("Ultra-Light", 11))
1539 prop
= font_intern_prop ("ultra-light", 11, 1);
1540 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1542 else if (PROP_MATCH ("Light", 5))
1545 prop
= font_intern_prop ("light", 5, 1);
1546 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1548 else if (PROP_MATCH ("Semi-Bold", 9))
1551 prop
= font_intern_prop ("semi-bold", 9, 1);
1552 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1554 else if (PROP_MATCH ("Bold", 4))
1557 prop
= font_intern_prop ("bold", 4, 1);
1558 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, prop
);
1560 else if (PROP_MATCH ("Italic", 6))
1563 prop
= font_intern_prop ("italic", 4, 1);
1564 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, prop
);
1566 else if (PROP_MATCH ("Oblique", 7))
1569 prop
= font_intern_prop ("oblique", 7, 1);
1570 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, prop
);
1574 return -1; /* Unknown property in GTK-style font name. */
1583 family
= font_intern_prop (name
, family_end
- name
, 1);
1584 ASET (font
, FONT_FAMILY_INDEX
, family
);
1591 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1592 NAME (NBYTES length), and return the name length. If
1593 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1596 font_unparse_fcname (font
, pixel_size
, name
, nbytes
)
1602 Lisp_Object family
, foundry
;
1603 Lisp_Object tail
, val
;
1608 Lisp_Object styles
[3];
1609 char *style_names
[3] = { "weight", "slant", "width" };
1612 family
= AREF (font
, FONT_FAMILY_INDEX
);
1613 if (! NILP (family
))
1615 if (SYMBOLP (family
))
1617 family
= SYMBOL_NAME (family
);
1618 len
+= SBYTES (family
);
1624 val
= AREF (font
, FONT_SIZE_INDEX
);
1627 if (XINT (val
) != 0)
1628 pixel_size
= XINT (val
);
1630 len
+= 21; /* for ":pixelsize=NUM" */
1632 else if (FLOATP (val
))
1635 point_size
= (int) XFLOAT_DATA (val
);
1636 len
+= 11; /* for "-NUM" */
1639 foundry
= AREF (font
, FONT_FOUNDRY_INDEX
);
1640 if (! NILP (foundry
))
1642 if (SYMBOLP (foundry
))
1644 foundry
= SYMBOL_NAME (foundry
);
1645 len
+= 9 + SBYTES (foundry
); /* ":foundry=NAME" */
1651 for (i
= 0; i
< 3; i
++)
1653 styles
[i
] = font_style_symbolic (font
, FONT_WEIGHT_INDEX
+ i
, 0);
1654 if (! NILP (styles
[i
]))
1655 len
+= sprintf (work
, ":%s=%s", style_names
[i
],
1656 SDATA (SYMBOL_NAME (styles
[i
])));
1659 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1660 len
+= sprintf (work
, ":dpi=%d", dpi
);
1661 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1662 len
+= strlen (":spacing=100");
1663 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1664 len
+= strlen (":scalable=false"); /* or ":scalable=true" */
1665 for (tail
= AREF (font
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
1667 Lisp_Object key
= XCAR (XCAR (tail
)), val
= XCDR (XCAR (tail
));
1669 len
+= SBYTES (SYMBOL_NAME (key
)) + 1; /* for :KEY= */
1671 len
+= SBYTES (val
);
1672 else if (INTEGERP (val
))
1673 len
+= sprintf (work
, "%d", XINT (val
));
1674 else if (SYMBOLP (val
))
1675 len
+= (NILP (val
) ? 5 : 4); /* for "false" or "true" */
1681 if (! NILP (family
))
1682 p
+= sprintf (p
, "%s", SDATA (family
));
1686 p
+= sprintf (p
, "%d", point_size
);
1688 p
+= sprintf (p
, "-%d", point_size
);
1690 else if (pixel_size
> 0)
1691 p
+= sprintf (p
, ":pixelsize=%d", pixel_size
);
1692 if (! NILP (AREF (font
, FONT_FOUNDRY_INDEX
)))
1693 p
+= sprintf (p
, ":foundry=%s",
1694 SDATA (SYMBOL_NAME (AREF (font
, FONT_FOUNDRY_INDEX
))));
1695 for (i
= 0; i
< 3; i
++)
1696 if (! NILP (styles
[i
]))
1697 p
+= sprintf (p
, ":%s=%s", style_names
[i
],
1698 SDATA (SYMBOL_NAME (styles
[i
])));
1699 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1700 p
+= sprintf (p
, ":dpi=%d", XINT (AREF (font
, FONT_DPI_INDEX
)));
1701 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1702 p
+= sprintf (p
, ":spacing=%d", XINT (AREF (font
, FONT_SPACING_INDEX
)));
1703 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1705 if (XINT (AREF (font
, FONT_AVGWIDTH_INDEX
)) == 0)
1706 p
+= sprintf (p
, ":scalable=true");
1708 p
+= sprintf (p
, ":scalable=false");
1713 /* Store GTK-style font name of FONT (font-spec or font-entity) in
1714 NAME (NBYTES length), and return the name length. F is the frame
1715 on which the font is displayed; it is used to calculate the point
1719 font_unparse_gtkname (font
, f
, name
, nbytes
)
1727 Lisp_Object family
, weight
, slant
, size
;
1728 int point_size
= -1;
1730 family
= AREF (font
, FONT_FAMILY_INDEX
);
1731 if (! NILP (family
))
1733 if (! SYMBOLP (family
))
1735 family
= SYMBOL_NAME (family
);
1736 len
+= SBYTES (family
);
1739 weight
= font_style_symbolic (font
, FONT_WEIGHT_INDEX
, 0);
1740 if (EQ (weight
, Qnormal
))
1742 else if (! NILP (weight
))
1744 weight
= SYMBOL_NAME (weight
);
1745 len
+= SBYTES (weight
);
1748 slant
= font_style_symbolic (font
, FONT_SLANT_INDEX
, 0);
1749 if (EQ (slant
, Qnormal
))
1751 else if (! NILP (slant
))
1753 slant
= SYMBOL_NAME (slant
);
1754 len
+= SBYTES (slant
);
1757 size
= AREF (font
, FONT_SIZE_INDEX
);
1758 /* Convert pixel size to point size. */
1759 if (INTEGERP (size
))
1761 Lisp_Object font_dpi
= AREF (font
, FONT_DPI_INDEX
);
1763 if (INTEGERP (font_dpi
))
1764 dpi
= XINT (font_dpi
);
1767 point_size
= PIXEL_TO_POINT (XINT (size
), dpi
);
1770 else if (FLOATP (size
))
1772 point_size
= (int) XFLOAT_DATA (size
);
1779 p
= name
+ sprintf (name
, "%s", SDATA (family
));
1781 if (! NILP (weight
))
1784 p
+= sprintf (p
, " %s", SDATA (weight
));
1785 q
[1] = toupper (q
[1]);
1791 p
+= sprintf (p
, " %s", SDATA (slant
));
1792 q
[1] = toupper (q
[1]);
1796 p
+= sprintf (p
, " %d", point_size
);
1801 /* Parse NAME (null terminated) and store information in FONT
1802 (font-spec or font-entity). If NAME is successfully parsed, return
1803 0. Otherwise return -1. */
1806 font_parse_name (name
, font
)
1810 if (name
[0] == '-' || index (name
, '*'))
1811 return font_parse_xlfd (name
, font
);
1812 return font_parse_fcname (name
, font
);
1816 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1817 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1821 font_parse_family_registry (family
, registry
, font_spec
)
1822 Lisp_Object family
, registry
, font_spec
;
1828 && NILP (AREF (font_spec
, FONT_FAMILY_INDEX
)))
1830 CHECK_STRING (family
);
1831 len
= SBYTES (family
);
1832 p0
= (char *) SDATA (family
);
1833 p1
= index (p0
, '-');
1836 if ((*p0
!= '*' || p1
- p0
> 1)
1837 && NILP (AREF (font_spec
, FONT_FOUNDRY_INDEX
)))
1838 Ffont_put (font_spec
, QCfoundry
, font_intern_prop (p0
, p1
- p0
, 1));
1841 Ffont_put (font_spec
, QCfamily
, font_intern_prop (p1
, len
, 1));
1844 ASET (font_spec
, FONT_FAMILY_INDEX
, Fintern (family
, Qnil
));
1846 if (! NILP (registry
))
1848 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1849 CHECK_STRING (registry
);
1850 len
= SBYTES (registry
);
1851 p0
= (char *) SDATA (registry
);
1852 p1
= index (p0
, '-');
1855 if (SDATA (registry
)[len
- 1] == '*')
1856 registry
= concat2 (registry
, build_string ("-*"));
1858 registry
= concat2 (registry
, build_string ("*-*"));
1860 registry
= Fdowncase (registry
);
1861 ASET (font_spec
, FONT_REGISTRY_INDEX
, Fintern (registry
, Qnil
));
1866 /* This part (through the next ^L) is still experimental and not
1867 tested much. We may drastically change codes. */
1873 #define LGSTRING_HEADER_SIZE 6
1874 #define LGSTRING_GLYPH_SIZE 8
1877 check_gstring (gstring
)
1878 Lisp_Object gstring
;
1883 CHECK_VECTOR (gstring
);
1884 val
= AREF (gstring
, 0);
1886 if (ASIZE (val
) < LGSTRING_HEADER_SIZE
)
1888 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring
));
1889 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
)))
1890 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
));
1891 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
)))
1892 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
));
1893 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
)))
1894 CHECK_NATNUM (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
));
1895 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1896 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1897 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1898 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1900 for (i
= 0; i
< LGSTRING_LENGTH (gstring
); i
++)
1902 val
= LGSTRING_GLYPH (gstring
, i
);
1904 if (ASIZE (val
) < LGSTRING_GLYPH_SIZE
)
1906 if (NILP (AREF (val
, LGLYPH_IX_CHAR
)))
1908 CHECK_NATNUM (AREF (val
, LGLYPH_IX_FROM
));
1909 CHECK_NATNUM (AREF (val
, LGLYPH_IX_TO
));
1910 CHECK_CHARACTER (AREF (val
, LGLYPH_IX_CHAR
));
1911 if (!NILP (AREF (val
, LGLYPH_IX_CODE
)))
1912 CHECK_NATNUM (AREF (val
, LGLYPH_IX_CODE
));
1913 if (!NILP (AREF (val
, LGLYPH_IX_WIDTH
)))
1914 CHECK_NATNUM (AREF (val
, LGLYPH_IX_WIDTH
));
1915 if (!NILP (AREF (val
, LGLYPH_IX_ADJUSTMENT
)))
1917 val
= AREF (val
, LGLYPH_IX_ADJUSTMENT
);
1919 if (ASIZE (val
) < 3)
1921 for (j
= 0; j
< 3; j
++)
1922 CHECK_NUMBER (AREF (val
, j
));
1927 error ("Invalid glyph-string format");
1932 check_otf_features (otf_features
)
1933 Lisp_Object otf_features
;
1937 CHECK_CONS (otf_features
);
1938 CHECK_SYMBOL (XCAR (otf_features
));
1939 otf_features
= XCDR (otf_features
);
1940 CHECK_CONS (otf_features
);
1941 CHECK_SYMBOL (XCAR (otf_features
));
1942 otf_features
= XCDR (otf_features
);
1943 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1945 CHECK_SYMBOL (Fcar (val
));
1946 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1947 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val
)));
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 GPOS feature: %s", SYMBOL_NAME (XCAR (val
)));
1961 Lisp_Object otf_list
;
1964 otf_tag_symbol (tag
)
1969 OTF_tag_name (tag
, name
);
1970 return Fintern (make_unibyte_string (name
, 4), Qnil
);
1977 Lisp_Object val
= Fassoc (file
, otf_list
);
1981 otf
= XSAVE_VALUE (XCDR (val
))->pointer
;
1984 otf
= STRINGP (file
) ? OTF_open ((char *) SDATA (file
)) : NULL
;
1985 val
= make_save_value (otf
, 0);
1986 otf_list
= Fcons (Fcons (file
, val
), otf_list
);
1992 /* Return a list describing which scripts/languages FONT supports by
1993 which GSUB/GPOS features of OpenType tables. See the comment of
1994 (struct font_driver).otf_capability. */
1997 font_otf_capability (font
)
2001 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
2004 otf
= otf_open (font
->props
[FONT_FILE_INDEX
]);
2007 for (i
= 0; i
< 2; i
++)
2009 OTF_GSUB_GPOS
*gsub_gpos
;
2010 Lisp_Object script_list
= Qnil
;
2013 if (OTF_get_features (otf
, i
== 0) < 0)
2015 gsub_gpos
= i
== 0 ? otf
->gsub
: otf
->gpos
;
2016 for (j
= gsub_gpos
->ScriptList
.ScriptCount
- 1; j
>= 0; j
--)
2018 OTF_Script
*script
= gsub_gpos
->ScriptList
.Script
+ j
;
2019 Lisp_Object langsys_list
= Qnil
;
2020 Lisp_Object script_tag
= otf_tag_symbol (script
->ScriptTag
);
2023 for (k
= script
->LangSysCount
; k
>= 0; k
--)
2025 OTF_LangSys
*langsys
;
2026 Lisp_Object feature_list
= Qnil
;
2027 Lisp_Object langsys_tag
;
2030 if (k
== script
->LangSysCount
)
2032 langsys
= &script
->DefaultLangSys
;
2037 langsys
= script
->LangSys
+ k
;
2039 = otf_tag_symbol (script
->LangSysRecord
[k
].LangSysTag
);
2041 for (l
= langsys
->FeatureCount
- 1; l
>= 0; l
--)
2043 OTF_Feature
*feature
2044 = gsub_gpos
->FeatureList
.Feature
+ langsys
->FeatureIndex
[l
];
2045 Lisp_Object feature_tag
2046 = otf_tag_symbol (feature
->FeatureTag
);
2048 feature_list
= Fcons (feature_tag
, feature_list
);
2050 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
2053 script_list
= Fcons (Fcons (script_tag
, langsys_list
),
2058 XSETCAR (capability
, script_list
);
2060 XSETCDR (capability
, script_list
);
2066 /* Parse OTF features in SPEC and write a proper features spec string
2067 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
2068 assured that the sufficient memory has already allocated for
2072 generate_otf_features (spec
, features
)
2082 for (asterisk
= 0; CONSP (spec
); spec
= XCDR (spec
))
2088 if (SREF (SYMBOL_NAME (val
), 0) == '*')
2093 else if (! asterisk
)
2095 val
= SYMBOL_NAME (val
);
2096 p
+= sprintf (p
, "%s", SDATA (val
));
2100 val
= SYMBOL_NAME (val
);
2101 p
+= sprintf (p
, "~%s", SDATA (val
));
2105 error ("OTF spec too long");
2109 font_otf_DeviceTable (device_table
)
2110 OTF_DeviceTable
*device_table
;
2112 int len
= device_table
->StartSize
- device_table
->EndSize
+ 1;
2114 return Fcons (make_number (len
),
2115 make_unibyte_string (device_table
->DeltaValue
, len
));
2119 font_otf_ValueRecord (value_format
, value_record
)
2121 OTF_ValueRecord
*value_record
;
2123 Lisp_Object val
= Fmake_vector (make_number (8), Qnil
);
2125 if (value_format
& OTF_XPlacement
)
2126 ASET (val
, 0, make_number (value_record
->XPlacement
));
2127 if (value_format
& OTF_YPlacement
)
2128 ASET (val
, 1, make_number (value_record
->YPlacement
));
2129 if (value_format
& OTF_XAdvance
)
2130 ASET (val
, 2, make_number (value_record
->XAdvance
));
2131 if (value_format
& OTF_YAdvance
)
2132 ASET (val
, 3, make_number (value_record
->YAdvance
));
2133 if (value_format
& OTF_XPlaDevice
)
2134 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XPlaDevice
));
2135 if (value_format
& OTF_YPlaDevice
)
2136 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YPlaDevice
));
2137 if (value_format
& OTF_XAdvDevice
)
2138 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XAdvDevice
));
2139 if (value_format
& OTF_YAdvDevice
)
2140 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YAdvDevice
));
2145 font_otf_Anchor (anchor
)
2150 val
= Fmake_vector (make_number (anchor
->AnchorFormat
+ 1), Qnil
);
2151 ASET (val
, 0, make_number (anchor
->XCoordinate
));
2152 ASET (val
, 1, make_number (anchor
->YCoordinate
));
2153 if (anchor
->AnchorFormat
== 2)
2154 ASET (val
, 2, make_number (anchor
->f
.f1
.AnchorPoint
));
2157 ASET (val
, 3, font_otf_DeviceTable (&anchor
->f
.f2
.XDeviceTable
));
2158 ASET (val
, 4, font_otf_DeviceTable (&anchor
->f
.f2
.YDeviceTable
));
2162 #endif /* HAVE_LIBOTF */
2165 /* G-string (glyph string) handler */
2167 /* G-string is a vector of the form [HEADER GLYPH ...].
2168 See the docstring of `font-make-gstring' for more detail. */
2171 font_prepare_composition (cmp
, f
)
2172 struct composition
*cmp
;
2176 = AREF (XHASH_TABLE (composition_hash_table
)->key_and_value
,
2177 cmp
->hash_index
* 2);
2179 cmp
->font
= XFONT_OBJECT (LGSTRING_FONT (gstring
));
2180 cmp
->glyph_len
= LGSTRING_LENGTH (gstring
);
2181 cmp
->pixel_width
= LGSTRING_WIDTH (gstring
);
2182 cmp
->lbearing
= LGSTRING_LBEARING (gstring
);
2183 cmp
->rbearing
= LGSTRING_RBEARING (gstring
);
2184 cmp
->ascent
= LGSTRING_ASCENT (gstring
);
2185 cmp
->descent
= LGSTRING_DESCENT (gstring
);
2186 cmp
->width
= cmp
->pixel_width
/ FRAME_COLUMN_WIDTH (f
);
2187 if (cmp
->width
== 0)
2196 static unsigned font_score
P_ ((Lisp_Object
, Lisp_Object
*));
2197 static int font_compare
P_ ((const void *, const void *));
2198 static Lisp_Object font_sort_entites
P_ ((Lisp_Object
, Lisp_Object
,
2201 /* We sort fonts by scoring each of them against a specified
2202 font-spec. The score value is 32 bit (`unsigned'), and the smaller
2203 the value is, the closer the font is to the font-spec.
2205 The lowest 2 bits of the score is used for driver type. The font
2206 available by the most preferred font driver is 0.
2208 Each 7-bit in the higher 28 bits are used for numeric properties
2209 WEIGHT, SLANT, WIDTH, and SIZE. */
2211 /* How many bits to shift to store the difference value of each font
2212 property in a score. Note that flots for FONT_TYPE_INDEX and
2213 FONT_REGISTRY_INDEX are not used. */
2214 static int sort_shift_bits
[FONT_SIZE_INDEX
+ 1];
2216 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
2217 The return value indicates how different ENTITY is compared with
2221 font_score (entity
, spec_prop
)
2222 Lisp_Object entity
, *spec_prop
;
2227 /* Score three style numeric fields. Maximum difference is 127. */
2228 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
; i
++)
2229 if (! NILP (spec_prop
[i
]) && ! EQ (AREF (entity
, i
), spec_prop
[i
]))
2231 int diff
= (XINT (AREF (entity
, i
)) >> 8) - (XINT (spec_prop
[i
]) >> 8);
2236 score
|= min (diff
, 127) << sort_shift_bits
[i
];
2239 /* Score the size. Maximum difference is 127. */
2240 i
= FONT_SIZE_INDEX
;
2241 if (! NILP (spec_prop
[i
]) && XINT (AREF (entity
, i
)) > 0)
2243 /* We use the higher 6-bit for the actual size difference. The
2244 lowest bit is set if the DPI is different. */
2245 int diff
= XINT (spec_prop
[i
]) - XINT (AREF (entity
, i
));
2250 if (! NILP (spec_prop
[FONT_DPI_INDEX
])
2251 && ! EQ (spec_prop
[FONT_DPI_INDEX
], AREF (entity
, FONT_DPI_INDEX
)))
2253 score
|= min (diff
, 127) << sort_shift_bits
[FONT_SIZE_INDEX
];
2260 /* The comparison function for qsort. */
2263 font_compare (d1
, d2
)
2264 const void *d1
, *d2
;
2266 return (*(unsigned *) d1
- *(unsigned *) d2
);
2270 /* The structure for elements being sorted by qsort. */
2271 struct font_sort_data
2278 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2279 If PREFER specifies a point-size, calculate the corresponding
2280 pixel-size from QCdpi property of PREFER or from the Y-resolution
2281 of FRAME before sorting.
2283 If BEST-ONLY is nonzero, return the best matching entity. Otherwise,
2284 return the sorted VEC. */
2287 font_sort_entites (vec
, prefer
, frame
, best_only
)
2288 Lisp_Object vec
, prefer
, frame
;
2291 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2293 struct font_sort_data
*data
;
2294 unsigned best_score
;
2295 Lisp_Object best_entity
, driver_type
;
2297 struct frame
*f
= XFRAME (frame
);
2298 struct font_driver_list
*list
;
2303 return best_only
? AREF (vec
, 0) : vec
;
2305 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_DPI_INDEX
; i
++)
2306 prefer_prop
[i
] = AREF (prefer
, i
);
2307 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2308 prefer_prop
[FONT_SIZE_INDEX
]
2309 = make_number (font_pixel_size (XFRAME (frame
), prefer
));
2311 /* Scoring and sorting. */
2312 SAFE_ALLOCA (data
, struct font_sort_data
*, (sizeof *data
) * len
);
2313 best_score
= 0xFFFFFFFF;
2314 /* We are sure that the length of VEC > 1. */
2315 driver_type
= AREF (AREF (vec
, 0), FONT_TYPE_INDEX
);
2316 for (driver_order
= 0, list
= f
->font_driver_list
; list
;
2317 driver_order
++, list
= list
->next
)
2318 if (EQ (driver_type
, list
->driver
->type
))
2320 best_entity
= data
[0].entity
= AREF (vec
, 0);
2321 best_score
= data
[0].score
2322 = font_score (data
[0].entity
, prefer_prop
) | driver_order
;
2323 for (i
= 0; i
< len
; i
++)
2325 if (!EQ (driver_type
, AREF (AREF (vec
, i
), FONT_TYPE_INDEX
)))
2326 for (driver_order
= 0, list
= f
->font_driver_list
; list
;
2327 driver_order
++, list
= list
->next
)
2328 if (EQ (driver_type
, list
->driver
->type
))
2330 data
[i
].entity
= AREF (vec
, i
);
2331 data
[i
].score
= font_score (data
[i
].entity
, prefer_prop
) | driver_order
;
2332 if (best_only
&& best_score
> data
[i
].score
)
2334 best_score
= data
[i
].score
;
2335 best_entity
= data
[i
].entity
;
2336 if (best_score
== 0)
2342 qsort (data
, len
, sizeof *data
, font_compare
);
2343 for (i
= 0; i
< len
; i
++)
2344 ASET (vec
, i
, data
[i
].entity
);
2350 font_add_log ("sort-by", prefer
, vec
);
2355 /* API of Font Service Layer. */
2357 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2358 sort_shift_bits. Finternal_set_font_selection_order calls this
2359 function with font_sort_order after setting up it. */
2362 font_update_sort_order (order
)
2367 for (i
= 0, shift_bits
= 23; i
< 4; i
++, shift_bits
-= 7)
2369 int xlfd_idx
= order
[i
];
2371 if (xlfd_idx
== XLFD_WEIGHT_INDEX
)
2372 sort_shift_bits
[FONT_WEIGHT_INDEX
] = shift_bits
;
2373 else if (xlfd_idx
== XLFD_SLANT_INDEX
)
2374 sort_shift_bits
[FONT_SLANT_INDEX
] = shift_bits
;
2375 else if (xlfd_idx
== XLFD_SWIDTH_INDEX
)
2376 sort_shift_bits
[FONT_WIDTH_INDEX
] = shift_bits
;
2378 sort_shift_bits
[FONT_SIZE_INDEX
] = shift_bits
;
2383 font_check_otf_features (script
, langsys
, features
, table
)
2384 Lisp_Object script
, langsys
, features
, table
;
2389 table
= assq_no_quit (script
, table
);
2392 table
= XCDR (table
);
2393 if (! NILP (langsys
))
2395 table
= assq_no_quit (langsys
, table
);
2401 val
= assq_no_quit (Qnil
, table
);
2403 table
= XCAR (table
);
2407 table
= XCDR (table
);
2408 for (negative
= 0; CONSP (features
); features
= XCDR (features
))
2410 if (NILP (XCAR (features
)))
2412 if (NILP (Fmemq (XCAR (features
), table
)) != negative
)
2418 /* Check if OTF_CAPABILITY satisfies SPEC (otf-spec). */
2421 font_check_otf (Lisp_Object spec
, Lisp_Object otf_capability
)
2423 Lisp_Object script
, langsys
= Qnil
, gsub
= Qnil
, gpos
= Qnil
;
2425 script
= XCAR (spec
);
2429 langsys
= XCAR (spec
);
2440 if (! NILP (gsub
) && ! font_check_otf_features (script
, langsys
, gsub
,
2441 XCAR (otf_capability
)))
2443 if (! NILP (gpos
) && ! font_check_otf_features (script
, langsys
, gpos
,
2444 XCDR (otf_capability
)))
2451 /* Check if FONT (font-entity or font-object) matches with the font
2452 specification SPEC. */
2455 font_match_p (spec
, font
)
2456 Lisp_Object spec
, font
;
2458 Lisp_Object prop
[FONT_SPEC_MAX
], *props
;
2459 Lisp_Object extra
, font_extra
;
2462 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2463 if (! NILP (AREF (spec
, i
))
2464 && ! NILP (AREF (font
, i
))
2465 && ! EQ (AREF (spec
, i
), AREF (font
, i
)))
2467 props
= XFONT_SPEC (spec
)->props
;
2468 if (FLOATP (props
[FONT_SIZE_INDEX
]))
2470 for (i
= FONT_FOUNDRY_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2471 prop
[i
] = AREF (spec
, i
);
2472 prop
[FONT_SIZE_INDEX
]
2473 = make_number (font_pixel_size (XFRAME (selected_frame
), spec
));
2477 if (font_score (font
, props
) > 0)
2479 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
2480 font_extra
= AREF (font
, FONT_EXTRA_INDEX
);
2481 for (; CONSP (extra
); extra
= XCDR (extra
))
2483 Lisp_Object key
= XCAR (XCAR (extra
));
2484 Lisp_Object val
= XCDR (XCAR (extra
)), val2
;
2486 if (EQ (key
, QClang
))
2488 val2
= assq_no_quit (key
, font_extra
);
2497 if (NILP (Fmemq (val
, val2
)))
2502 ? NILP (Fmemq (val
, XCDR (val2
)))
2506 else if (EQ (key
, QCscript
))
2508 val2
= assq_no_quit (val
, Vscript_representative_chars
);
2510 for (val2
= XCDR (val2
); CONSP (val2
); val2
= XCDR (val2
))
2511 if (font_encode_char (font
, XINT (XCAR (val2
)))
2512 == FONT_INVALID_CODE
)
2515 else if (EQ (key
, QCotf
))
2519 if (! FONT_OBJECT_P (font
))
2521 fontp
= XFONT_OBJECT (font
);
2522 if (! fontp
->driver
->otf_capability
)
2524 val2
= fontp
->driver
->otf_capability (fontp
);
2525 if (NILP (val2
) || ! font_check_otf (val
, val2
))
2536 Each font backend has the callback function get_cache, and it
2537 returns a cons cell of which cdr part can be freely used for
2538 caching fonts. The cons cell may be shared by multiple frames
2539 and/or multiple font drivers. So, we arrange the cdr part as this:
2541 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2543 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2544 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2545 cons (FONT-SPEC FONT-ENTITY ...). */
2547 static void font_prepare_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2548 static void font_finish_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2549 static Lisp_Object font_get_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2550 static void font_clear_cache
P_ ((FRAME_PTR
, Lisp_Object
,
2551 struct font_driver
*));
2554 font_prepare_cache (f
, driver
)
2556 struct font_driver
*driver
;
2558 Lisp_Object cache
, val
;
2560 cache
= driver
->get_cache (f
);
2562 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2566 val
= Fcons (driver
->type
, Fcons (make_number (1), Qnil
));
2567 XSETCDR (cache
, Fcons (val
, XCDR (cache
)));
2571 val
= XCDR (XCAR (val
));
2572 XSETCAR (val
, make_number (XINT (XCAR (val
)) + 1));
2578 font_finish_cache (f
, driver
)
2580 struct font_driver
*driver
;
2582 Lisp_Object cache
, val
, tmp
;
2585 cache
= driver
->get_cache (f
);
2587 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2588 cache
= val
, val
= XCDR (val
);
2589 font_assert (! NILP (val
));
2590 tmp
= XCDR (XCAR (val
));
2591 XSETCAR (tmp
, make_number (XINT (XCAR (tmp
)) - 1));
2592 if (XINT (XCAR (tmp
)) == 0)
2594 font_clear_cache (f
, XCAR (val
), driver
);
2595 XSETCDR (cache
, XCDR (val
));
2601 font_get_cache (f
, driver
)
2603 struct font_driver
*driver
;
2605 Lisp_Object val
= driver
->get_cache (f
);
2606 Lisp_Object type
= driver
->type
;
2608 font_assert (CONSP (val
));
2609 for (val
= XCDR (val
); ! EQ (XCAR (XCAR (val
)), type
); val
= XCDR (val
));
2610 font_assert (CONSP (val
));
2611 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2612 val
= XCDR (XCAR (val
));
2616 static int num_fonts
;
2619 font_clear_cache (f
, cache
, driver
)
2622 struct font_driver
*driver
;
2624 Lisp_Object tail
, elt
;
2626 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2627 for (tail
= XCDR (XCDR (cache
)); CONSP (tail
); tail
= XCDR (tail
))
2630 if (CONSP (elt
) && FONT_SPEC_P (XCAR (elt
)) && VECTORP (XCDR (elt
)))
2632 Lisp_Object vec
= XCDR (elt
);
2635 for (i
= 0; i
< ASIZE (vec
); i
++)
2637 Lisp_Object entity
= AREF (vec
, i
);
2639 if (EQ (driver
->type
, AREF (entity
, FONT_TYPE_INDEX
)))
2641 Lisp_Object objlist
= AREF (entity
, FONT_OBJLIST_INDEX
);
2643 for (; CONSP (objlist
); objlist
= XCDR (objlist
))
2645 Lisp_Object val
= XCAR (objlist
);
2646 struct font
*font
= XFONT_OBJECT (val
);
2648 if (! NILP (AREF (val
, FONT_TYPE_INDEX
)))
2650 font_assert (font
&& driver
== font
->driver
);
2651 driver
->close (f
, font
);
2655 if (driver
->free_entity
)
2656 driver
->free_entity (entity
);
2661 XSETCDR (cache
, Qnil
);
2665 static Lisp_Object scratch_font_spec
, scratch_font_prefer
;
2668 font_delete_unmatched (list
, spec
, size
)
2669 Lisp_Object list
, spec
;
2672 Lisp_Object entity
, val
;
2673 enum font_property_index prop
;
2675 for (val
= Qnil
; CONSP (list
); list
= XCDR (list
))
2677 entity
= XCAR (list
);
2678 for (prop
= FONT_WEIGHT_INDEX
; prop
< FONT_SIZE_INDEX
; prop
++)
2679 if (INTEGERP (AREF (spec
, prop
))
2680 && ((XINT (AREF (spec
, prop
)) >> 8)
2681 != (XINT (AREF (entity
, prop
)) >> 8)))
2682 prop
= FONT_SPEC_MAX
;
2683 if (prop
< FONT_SPEC_MAX
2685 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2687 int diff
= XINT (AREF (entity
, FONT_SIZE_INDEX
)) - size
;
2690 && (diff
< 0 ? -diff
> FONT_PIXEL_SIZE_QUANTUM
2691 : diff
> FONT_PIXEL_SIZE_QUANTUM
))
2692 prop
= FONT_SPEC_MAX
;
2694 if (prop
< FONT_SPEC_MAX
2695 && INTEGERP (AREF (spec
, FONT_DPI_INDEX
))
2696 && INTEGERP (AREF (entity
, FONT_DPI_INDEX
))
2697 && ! EQ (AREF (spec
, FONT_DPI_INDEX
), AREF (entity
, FONT_DPI_INDEX
)))
2698 prop
= FONT_SPEC_MAX
;
2699 if (prop
< FONT_SPEC_MAX
2700 && INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
2701 && INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
2702 && ! EQ (AREF (spec
, FONT_AVGWIDTH_INDEX
),
2703 AREF (entity
, FONT_AVGWIDTH_INDEX
)))
2704 prop
= FONT_SPEC_MAX
;
2705 if (prop
< FONT_SPEC_MAX
)
2706 val
= Fcons (entity
, val
);
2712 /* Return a vector of font-entities matching with SPEC on FRAME. */
2715 font_list_entities (frame
, spec
)
2716 Lisp_Object frame
, spec
;
2718 FRAME_PTR f
= XFRAME (frame
);
2719 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2720 Lisp_Object ftype
, val
;
2723 int need_filtering
= 0;
2726 font_assert (FONT_SPEC_P (spec
));
2728 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2729 size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
2730 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
2731 size
= font_pixel_size (f
, spec
);
2735 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2736 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2737 ASET (scratch_font_spec
, i
, AREF (spec
, i
));
2738 for (i
= FONT_WEIGHT_INDEX
; i
< FONT_EXTRA_INDEX
; i
++)
2740 ASET (scratch_font_spec
, i
, Qnil
);
2741 if (! NILP (AREF (spec
, i
)))
2743 if (i
== FONT_DPI_INDEX
)
2744 /* Skip FONT_SPACING_INDEX */
2747 ASET (scratch_font_spec
, FONT_SPACING_INDEX
, AREF (spec
, FONT_SPACING_INDEX
));
2748 ASET (scratch_font_spec
, FONT_EXTRA_INDEX
, AREF (spec
, FONT_EXTRA_INDEX
));
2750 vec
= alloca (sizeof (Lisp_Object
) * num_font_drivers
);
2754 for (i
= 0; driver_list
; driver_list
= driver_list
->next
)
2756 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2758 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2760 ASET (scratch_font_spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2761 val
= assoc_no_quit (scratch_font_spec
, XCDR (cache
));
2768 val
= driver_list
->driver
->list (frame
, scratch_font_spec
);
2769 copy
= Fcopy_font_spec (scratch_font_spec
);
2770 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2771 XSETCDR (cache
, Fcons (Fcons (copy
, val
), XCDR (cache
)));
2773 if (! NILP (val
) && need_filtering
)
2774 val
= font_delete_unmatched (val
, spec
, size
);
2779 val
= (i
> 0 ? Fvconcat (i
, vec
) : null_vector
);
2780 font_add_log ("list", spec
, val
);
2785 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2786 nil, is an array of face's attributes, which specifies preferred
2787 font-related attributes. */
2790 font_matching_entity (f
, attrs
, spec
)
2792 Lisp_Object
*attrs
, spec
;
2794 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2795 Lisp_Object ftype
, size
, entity
;
2798 XSETFRAME (frame
, f
);
2799 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2800 size
= AREF (spec
, FONT_SIZE_INDEX
);
2802 ASET (spec
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2804 for (; driver_list
; driver_list
= driver_list
->next
)
2806 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2808 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2811 ASET (spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2812 entity
= assoc_no_quit (spec
, XCDR (cache
));
2814 entity
= XCDR (entity
);
2817 entity
= driver_list
->driver
->match (frame
, spec
);
2818 copy
= Fcopy_font_spec (spec
);
2819 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2820 XSETCDR (cache
, Fcons (Fcons (copy
, entity
), XCDR (cache
)));
2822 if (! NILP (entity
))
2825 ASET (spec
, FONT_TYPE_INDEX
, ftype
);
2826 ASET (spec
, FONT_SIZE_INDEX
, size
);
2827 font_add_log ("match", spec
, entity
);
2832 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2833 opened font object. */
2836 font_open_entity (f
, entity
, pixel_size
)
2841 struct font_driver_list
*driver_list
;
2842 Lisp_Object objlist
, size
, val
, font_object
;
2844 int min_width
, height
;
2846 font_assert (FONT_ENTITY_P (entity
));
2847 size
= AREF (entity
, FONT_SIZE_INDEX
);
2848 if (XINT (size
) != 0)
2849 pixel_size
= XINT (size
);
2851 for (objlist
= AREF (entity
, FONT_OBJLIST_INDEX
); CONSP (objlist
);
2852 objlist
= XCDR (objlist
))
2853 if (! NILP (AREF (XCAR (objlist
), FONT_TYPE_INDEX
))
2854 && XFONT_OBJECT (XCAR (objlist
))->pixel_size
== pixel_size
)
2855 return XCAR (objlist
);
2857 val
= AREF (entity
, FONT_TYPE_INDEX
);
2858 for (driver_list
= f
->font_driver_list
;
2859 driver_list
&& ! EQ (driver_list
->driver
->type
, val
);
2860 driver_list
= driver_list
->next
);
2864 font_object
= driver_list
->driver
->open (f
, entity
, pixel_size
);
2865 font_add_log ("open", entity
, font_object
);
2866 if (NILP (font_object
))
2868 ASET (entity
, FONT_OBJLIST_INDEX
,
2869 Fcons (font_object
, AREF (entity
, FONT_OBJLIST_INDEX
)));
2870 ASET (font_object
, FONT_OBJLIST_INDEX
, Qnil
);
2873 font
= XFONT_OBJECT (font_object
);
2874 min_width
= (font
->min_width
? font
->min_width
2875 : font
->average_width
? font
->average_width
2876 : font
->space_width
? font
->space_width
2878 height
= (font
->height
? font
->height
: 1);
2879 #ifdef HAVE_WINDOW_SYSTEM
2880 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
2881 if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
== 1)
2883 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
;
2884 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
;
2885 fonts_changed_p
= 1;
2889 if (FRAME_SMALLEST_CHAR_WIDTH (f
) > min_width
)
2890 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
, fonts_changed_p
= 1;
2891 if (FRAME_SMALLEST_FONT_HEIGHT (f
) > height
)
2892 FRAME_SMALLEST_FONT_HEIGHT (f
) = height
, fonts_changed_p
= 1;
2900 /* Close FONT_OBJECT that is opened on frame F. */
2903 font_close_object (f
, font_object
)
2905 Lisp_Object font_object
;
2907 struct font
*font
= XFONT_OBJECT (font_object
);
2909 if (NILP (AREF (font_object
, FONT_TYPE_INDEX
)))
2910 /* Already closed. */
2912 font_add_log ("close", font_object
, Qnil
);
2913 font
->driver
->close (f
, font
);
2914 #ifdef HAVE_WINDOW_SYSTEM
2915 font_assert (FRAME_X_DISPLAY_INFO (f
)->n_fonts
);
2916 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
2922 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2923 FONT is a font-entity and it must be opened to check. */
2926 font_has_char (f
, font
, c
)
2933 if (FONT_ENTITY_P (font
))
2935 Lisp_Object type
= AREF (font
, FONT_TYPE_INDEX
);
2936 struct font_driver_list
*driver_list
;
2938 for (driver_list
= f
->font_driver_list
;
2939 driver_list
&& ! EQ (driver_list
->driver
->type
, type
);
2940 driver_list
= driver_list
->next
);
2943 if (! driver_list
->driver
->has_char
)
2945 return driver_list
->driver
->has_char (font
, c
);
2948 font_assert (FONT_OBJECT_P (font
));
2949 fontp
= XFONT_OBJECT (font
);
2950 if (fontp
->driver
->has_char
)
2952 int result
= fontp
->driver
->has_char (font
, c
);
2957 return (fontp
->driver
->encode_char (fontp
, c
) != FONT_INVALID_CODE
);
2961 /* Return the glyph ID of FONT_OBJECT for character C. */
2964 font_encode_char (font_object
, c
)
2965 Lisp_Object font_object
;
2970 font_assert (FONT_OBJECT_P (font_object
));
2971 font
= XFONT_OBJECT (font_object
);
2972 return font
->driver
->encode_char (font
, c
);
2976 /* Return the name of FONT_OBJECT. */
2979 font_get_name (font_object
)
2980 Lisp_Object font_object
;
2982 font_assert (FONT_OBJECT_P (font_object
));
2983 return AREF (font_object
, FONT_NAME_INDEX
);
2987 /* Return the specification of FONT_OBJECT. */
2990 font_get_spec (font_object
)
2991 Lisp_Object font_object
;
2993 Lisp_Object spec
= font_make_spec ();
2996 for (i
= 0; i
< FONT_SIZE_INDEX
; i
++)
2997 ASET (spec
, i
, AREF (font_object
, i
));
2998 ASET (spec
, FONT_SIZE_INDEX
,
2999 make_number (XFONT_OBJECT (font_object
)->pixel_size
));
3004 font_spec_from_name (font_name
)
3005 Lisp_Object font_name
;
3007 Lisp_Object args
[2];
3010 args
[1] = font_name
;
3011 return Ffont_spec (2, args
);
3016 font_clear_prop (attrs
, prop
)
3018 enum font_property_index prop
;
3020 Lisp_Object font
= attrs
[LFACE_FONT_INDEX
];
3024 if (NILP (AREF (font
, prop
))
3025 && prop
!= FONT_FAMILY_INDEX
&& prop
!= FONT_FOUNDRY_INDEX
3026 && prop
!= FONT_SIZE_INDEX
)
3028 font
= Fcopy_font_spec (font
);
3029 ASET (font
, prop
, Qnil
);
3030 if (prop
== FONT_FAMILY_INDEX
|| prop
== FONT_FOUNDRY_INDEX
)
3032 if (prop
== FONT_FAMILY_INDEX
)
3033 ASET (font
, FONT_FOUNDRY_INDEX
, Qnil
);
3034 ASET (font
, FONT_ADSTYLE_INDEX
, Qnil
);
3035 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
3036 ASET (font
, FONT_SIZE_INDEX
, Qnil
);
3037 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3038 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3039 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3041 else if (prop
== FONT_SIZE_INDEX
)
3043 ASET (font
, FONT_DPI_INDEX
, Qnil
);
3044 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
3045 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
3047 attrs
[LFACE_FONT_INDEX
] = font
;
3051 font_update_lface (f
, attrs
)
3057 spec
= attrs
[LFACE_FONT_INDEX
];
3058 if (! FONT_SPEC_P (spec
))
3061 if (! NILP (AREF (spec
, FONT_FOUNDRY_INDEX
)))
3062 attrs
[LFACE_FOUNDRY_INDEX
] = SYMBOL_NAME (AREF (spec
, FONT_FOUNDRY_INDEX
));
3063 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3064 attrs
[LFACE_FAMILY_INDEX
] = SYMBOL_NAME (AREF (spec
, FONT_FAMILY_INDEX
));
3065 if (! NILP (AREF (spec
, FONT_WEIGHT_INDEX
)))
3066 attrs
[LFACE_WEIGHT_INDEX
] = FONT_WEIGHT_FOR_FACE (spec
);
3067 if (! NILP (AREF (spec
, FONT_SLANT_INDEX
)))
3068 attrs
[LFACE_SLANT_INDEX
] = FONT_SLANT_FOR_FACE (spec
);;
3069 if (! NILP (AREF (spec
, FONT_WIDTH_INDEX
)))
3070 attrs
[LFACE_SWIDTH_INDEX
] = FONT_WIDTH_FOR_FACE (spec
);
3071 if (! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
3075 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
3080 val
= Ffont_get (spec
, QCdpi
);
3083 point
= PIXEL_TO_POINT (XINT (AREF (spec
, FONT_SIZE_INDEX
)) * 10,
3086 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
3087 point
= XFLOAT_DATA (AREF (spec
, FONT_SIZE_INDEX
)) * 10;
3088 attrs
[LFACE_HEIGHT_INDEX
] = make_number (point
);
3093 /* Return a font-entity satisfying SPEC and best matching with face's
3094 font related attributes in ATTRS. C, if not negative, is a
3095 character that the entity must support. */
3098 font_find_for_lface (f
, attrs
, spec
, c
)
3105 Lisp_Object frame
, entities
, val
, props
[FONT_REGISTRY_INDEX
+ 1] ;
3106 Lisp_Object size
, foundry
[3], *family
, registry
[3], adstyle
[3];
3108 int i
, j
, k
, l
, result
;
3110 registry
[0] = AREF (spec
, FONT_REGISTRY_INDEX
);
3111 if (NILP (registry
[0]))
3113 registry
[0] = DEFAULT_ENCODING
;
3114 registry
[1] = Qascii_0
;
3115 registry
[2] = null_vector
;
3118 registry
[1] = null_vector
;
3120 if (c
>= 0 && ! NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
3122 struct charset
*encoding
, *repertory
;
3124 if (font_registry_charsets (AREF (spec
, FONT_REGISTRY_INDEX
),
3125 &encoding
, &repertory
) < 0)
3129 if (ENCODE_CHAR (repertory
, c
) == CHARSET_INVALID_CODE (repertory
))
3131 /* Any font of this registry support C. So, let's
3132 suppress the further checking. */
3135 else if (c
> encoding
->max_char
)
3139 work
= Fcopy_font_spec (spec
);
3140 XSETFRAME (frame
, f
);
3141 size
= AREF (spec
, FONT_SIZE_INDEX
);
3142 pixel_size
= font_pixel_size (f
, spec
);
3143 if (pixel_size
== 0)
3145 double pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3147 pixel_size
= POINT_TO_PIXEL (pt
/ 10, f
->resy
);
3149 ASET (work
, FONT_SIZE_INDEX
, Qnil
);
3150 foundry
[0] = AREF (work
, FONT_FOUNDRY_INDEX
);
3151 if (! NILP (foundry
[0]))
3152 foundry
[1] = null_vector
;
3153 else if (STRINGP (attrs
[LFACE_FOUNDRY_INDEX
]))
3155 foundry
[0] = font_intern_prop (SDATA (attrs
[LFACE_FOUNDRY_INDEX
]),
3156 SBYTES (attrs
[LFACE_FOUNDRY_INDEX
]), 1);
3158 foundry
[2] = null_vector
;
3161 foundry
[0] = Qnil
, foundry
[1] = null_vector
;
3163 adstyle
[0] = AREF (work
, FONT_ADSTYLE_INDEX
);
3164 if (! NILP (adstyle
[0]))
3165 adstyle
[1] = null_vector
;
3166 else if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3168 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3170 if (! NILP (AREF (face_font
, FONT_ADSTYLE_INDEX
)))
3172 adstyle
[0] = AREF (face_font
, FONT_ADSTYLE_INDEX
);
3174 adstyle
[2] = null_vector
;
3177 adstyle
[0] = Qnil
, adstyle
[1] = null_vector
;
3180 adstyle
[0] = Qnil
, adstyle
[1] = null_vector
;
3183 val
= AREF (work
, FONT_FAMILY_INDEX
);
3184 if (NILP (val
) && STRINGP (attrs
[LFACE_FAMILY_INDEX
]))
3185 val
= font_intern_prop (SDATA (attrs
[LFACE_FAMILY_INDEX
]),
3186 SBYTES (attrs
[LFACE_FAMILY_INDEX
]), 1);
3189 family
= alloca ((sizeof family
[0]) * 2);
3191 family
[1] = null_vector
; /* terminator. */
3196 = Fassoc_string (val
, Vface_alternative_font_family_alist
, Qt
);
3198 if (! NILP (alters
))
3200 family
= alloca ((sizeof family
[0]) * (XINT (Flength (alters
)) + 2));
3201 for (i
= 0; CONSP (alters
); i
++, alters
= XCDR (alters
))
3202 family
[i
] = XCAR (alters
);
3203 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3205 family
[i
] = null_vector
;
3209 family
= alloca ((sizeof family
[0]) * 3);
3212 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
3214 family
[i
] = null_vector
;
3218 for (i
= 0; SYMBOLP (family
[i
]); i
++)
3220 ASET (work
, FONT_FAMILY_INDEX
, family
[i
]);
3221 for (j
= 0; SYMBOLP (foundry
[j
]); j
++)
3223 ASET (work
, FONT_FOUNDRY_INDEX
, foundry
[j
]);
3224 for (k
= 0; SYMBOLP (registry
[k
]); k
++)
3226 ASET (work
, FONT_REGISTRY_INDEX
, registry
[k
]);
3227 for (l
= 0; SYMBOLP (adstyle
[l
]); l
++)
3229 ASET (work
, FONT_ADSTYLE_INDEX
, adstyle
[l
]);
3230 entities
= font_list_entities (frame
, work
);
3231 if (ASIZE (entities
) > 0)
3239 if (ASIZE (entities
) == 1)
3242 return AREF (entities
, 0);
3246 /* Sort fonts by properties specified in LFACE. */
3247 Lisp_Object prefer
= scratch_font_prefer
;
3249 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
3250 ASET (prefer
, i
, AREF (work
, i
));
3251 if (FONTP (attrs
[LFACE_FONT_INDEX
]))
3253 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
3255 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
3256 if (NILP (AREF (prefer
, i
)))
3257 ASET (prefer
, i
, AREF (face_font
, i
));
3259 if (NILP (AREF (prefer
, FONT_WEIGHT_INDEX
)))
3260 FONT_SET_STYLE (prefer
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
3261 if (NILP (AREF (prefer
, FONT_SLANT_INDEX
)))
3262 FONT_SET_STYLE (prefer
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
3263 if (NILP (AREF (prefer
, FONT_WIDTH_INDEX
)))
3264 FONT_SET_STYLE (prefer
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
3265 ASET (prefer
, FONT_SIZE_INDEX
, make_number (pixel_size
));
3266 entities
= font_sort_entites (entities
, prefer
, frame
, c
< 0);
3271 for (i
= 0; i
< ASIZE (entities
); i
++)
3275 val
= AREF (entities
, i
);
3278 for (j
= FONT_FOUNDRY_INDEX
; j
<= FONT_REGISTRY_INDEX
; j
++)
3279 if (! EQ (AREF (val
, j
), props
[j
]))
3281 if (j
> FONT_REGISTRY_INDEX
)
3284 for (j
= FONT_FOUNDRY_INDEX
; j
<= FONT_REGISTRY_INDEX
; j
++)
3285 props
[j
] = AREF (val
, j
);
3286 result
= font_has_char (f
, val
, c
);
3291 val
= font_open_for_lface (f
, val
, attrs
, spec
);
3294 result
= font_has_char (f
, val
, c
);
3295 font_close_object (f
, val
);
3297 return AREF (entities
, i
);
3304 font_open_for_lface (f
, entity
, attrs
, spec
)
3312 if (INTEGERP (AREF (entity
, FONT_SIZE_INDEX
))
3313 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
3314 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
3315 else if (FONT_SPEC_P (spec
) && ! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
3316 size
= font_pixel_size (f
, spec
);
3319 double pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
3322 size
= POINT_TO_PIXEL (pt
, f
->resy
);
3326 Lisp_Object ffsize
= get_frame_param(f
, Qfontsize
);
3327 size
= NUMBERP (ffsize
) ? POINT_TO_PIXEL (XINT (ffsize
), f
->resy
) : 0;
3331 return font_open_entity (f
, entity
, size
);
3335 /* Find a font satisfying SPEC and best matching with face's
3336 attributes in ATTRS on FRAME, and return the opened
3340 font_load_for_lface (f
, attrs
, spec
)
3342 Lisp_Object
*attrs
, spec
;
3346 entity
= font_find_for_lface (f
, attrs
, spec
, -1);
3349 /* No font is listed for SPEC, but each font-backend may have
3350 the different criteria about "font matching". So, try
3352 entity
= font_matching_entity (f
, attrs
, spec
);
3356 return font_open_for_lface (f
, entity
, attrs
, spec
);
3360 /* Make FACE on frame F ready to use the font opened for FACE. */
3363 font_prepare_for_face (f
, face
)
3367 if (face
->font
->driver
->prepare_face
)
3368 face
->font
->driver
->prepare_face (f
, face
);
3372 /* Make FACE on frame F stop using the font opened for FACE. */
3375 font_done_for_face (f
, face
)
3379 if (face
->font
->driver
->done_face
)
3380 face
->font
->driver
->done_face (f
, face
);
3385 /* Open a font best matching with NAME on frame F. If no proper font
3386 is found, return Qnil. */
3389 font_open_by_name (f
, name
)
3393 Lisp_Object args
[2];
3394 Lisp_Object spec
, attrs
[LFACE_VECTOR_SIZE
];
3397 args
[1] = make_unibyte_string (name
, strlen (name
));
3398 spec
= Ffont_spec (2, args
);
3399 /* We set up the default font-related attributes of a face to prefer
3401 attrs
[LFACE_FAMILY_INDEX
] = attrs
[LFACE_FOUNDRY_INDEX
] = Qnil
;
3402 attrs
[LFACE_SWIDTH_INDEX
] = attrs
[LFACE_WEIGHT_INDEX
]
3403 = attrs
[LFACE_SLANT_INDEX
] = Qnormal
;
3405 attrs
[LFACE_HEIGHT_INDEX
] = make_number (120);
3407 attrs
[LFACE_HEIGHT_INDEX
] = make_number (0);
3409 attrs
[LFACE_FONT_INDEX
] = Qnil
;
3411 return font_load_for_lface (f
, attrs
, spec
);
3415 /* Register font-driver DRIVER. This function is used in two ways.
3417 The first is with frame F non-NULL. In this case, make DRIVER
3418 available (but not yet activated) on F. All frame creaters
3419 (e.g. Fx_create_frame) must call this function at least once with
3420 an available font-driver.
3422 The second is with frame F NULL. In this case, DRIVER is globally
3423 registered in the variable `font_driver_list'. All font-driver
3424 implementations must call this function in its syms_of_XXXX
3425 (e.g. syms_of_xfont). */
3428 register_font_driver (driver
, f
)
3429 struct font_driver
*driver
;
3432 struct font_driver_list
*root
= f
? f
->font_driver_list
: font_driver_list
;
3433 struct font_driver_list
*prev
, *list
;
3435 if (f
&& ! driver
->draw
)
3436 error ("Unusable font driver for a frame: %s",
3437 SDATA (SYMBOL_NAME (driver
->type
)));
3439 for (prev
= NULL
, list
= root
; list
; prev
= list
, list
= list
->next
)
3440 if (EQ (list
->driver
->type
, driver
->type
))
3441 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver
->type
)));
3443 list
= malloc (sizeof (struct font_driver_list
));
3445 list
->driver
= driver
;
3450 f
->font_driver_list
= list
;
3452 font_driver_list
= list
;
3458 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3459 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3460 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3462 A caller must free all realized faces if any in advance. The
3463 return value is a list of font backends actually made used on
3467 font_update_drivers (f
, new_drivers
)
3469 Lisp_Object new_drivers
;
3471 Lisp_Object active_drivers
= Qnil
;
3472 struct font_driver
*driver
;
3473 struct font_driver_list
*list
;
3475 /* At first, turn off non-requested drivers, and turn on requested
3477 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3479 driver
= list
->driver
;
3480 if ((EQ (new_drivers
, Qt
) || ! NILP (Fmemq (driver
->type
, new_drivers
)))
3485 if (driver
->end_for_frame
)
3486 driver
->end_for_frame (f
);
3487 font_finish_cache (f
, driver
);
3492 if (! driver
->start_for_frame
3493 || driver
->start_for_frame (f
) == 0)
3495 font_prepare_cache (f
, driver
);
3502 if (NILP (new_drivers
))
3505 if (! EQ (new_drivers
, Qt
))
3507 /* Re-order the driver list according to new_drivers. */
3508 struct font_driver_list
**list_table
, **next
;
3512 list_table
= alloca (sizeof list_table
[0] * (num_font_drivers
+ 1));
3513 for (i
= 0, tail
= new_drivers
; ! NILP (tail
); tail
= XCDR (tail
))
3515 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3516 if (list
->on
&& EQ (list
->driver
->type
, XCAR (tail
)))
3519 list_table
[i
++] = list
;
3521 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3523 list_table
[i
] = list
;
3524 list_table
[i
] = NULL
;
3526 next
= &f
->font_driver_list
;
3527 for (i
= 0; list_table
[i
]; i
++)
3529 *next
= list_table
[i
];
3530 next
= &(*next
)->next
;
3535 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3537 active_drivers
= nconc2 (active_drivers
,
3538 Fcons (list
->driver
->type
, Qnil
));
3539 return active_drivers
;
3543 font_put_frame_data (f
, driver
, data
)
3545 struct font_driver
*driver
;
3548 struct font_data_list
*list
, *prev
;
3550 for (prev
= NULL
, list
= f
->font_data_list
; list
;
3551 prev
= list
, list
= list
->next
)
3552 if (list
->driver
== driver
)
3559 prev
->next
= list
->next
;
3561 f
->font_data_list
= list
->next
;
3569 list
= malloc (sizeof (struct font_data_list
));
3572 list
->driver
= driver
;
3573 list
->next
= f
->font_data_list
;
3574 f
->font_data_list
= list
;
3582 font_get_frame_data (f
, driver
)
3584 struct font_driver
*driver
;
3586 struct font_data_list
*list
;
3588 for (list
= f
->font_data_list
; list
; list
= list
->next
)
3589 if (list
->driver
== driver
)
3597 /* Return the font used to draw character C by FACE at buffer position
3598 POS in window W. If STRING is non-nil, it is a string containing C
3599 at index POS. If C is negative, get C from the current buffer or
3603 font_at (c
, pos
, face
, w
, string
)
3612 Lisp_Object font_object
;
3618 multibyte
= ! NILP (current_buffer
->enable_multibyte_characters
);
3621 EMACS_INT pos_byte
= CHAR_TO_BYTE (pos
);
3623 c
= FETCH_CHAR (pos_byte
);
3626 c
= FETCH_BYTE (pos
);
3632 multibyte
= STRING_MULTIBYTE (string
);
3635 EMACS_INT pos_byte
= string_char_to_byte (string
, pos
);
3637 str
= SDATA (string
) + pos_byte
;
3638 c
= STRING_CHAR (str
, 0);
3641 c
= SDATA (string
)[pos
];
3645 f
= XFRAME (w
->frame
);
3646 if (! FRAME_WINDOW_P (f
))
3653 if (STRINGP (string
))
3654 face_id
= face_at_string_position (w
, string
, pos
, 0, -1, -1, &endptr
,
3655 DEFAULT_FACE_ID
, 0);
3657 face_id
= face_at_buffer_position (w
, pos
, -1, -1, &endptr
,
3659 face
= FACE_FROM_ID (f
, face_id
);
3663 int face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3664 face
= FACE_FROM_ID (f
, face_id
);
3669 XSETFONT (font_object
, face
->font
);
3674 /* Check how many characters after POS (at most to LIMIT) can be
3675 displayed by the same font. FACE is the face selected for the
3676 character as POS on frame F. STRING, if not nil, is the string to
3677 check instead of the current buffer.
3679 The return value is the position of the character that is displayed
3680 by the differnt font than that of the character as POS. */
3683 font_range (pos
, limit
, face
, f
, string
)
3684 EMACS_INT pos
, limit
;
3697 multibyte
= ! NILP (current_buffer
->enable_multibyte_characters
);
3698 pos_byte
= CHAR_TO_BYTE (pos
);
3702 multibyte
= STRING_MULTIBYTE (string
);
3703 pos_byte
= string_char_to_byte (string
, pos
);
3707 /* All unibyte character are displayed by the same font. */
3715 FETCH_CHAR_ADVANCE_NO_CHECK (c
, pos
, pos_byte
);
3717 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c
, string
, pos
, pos_byte
);
3718 face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3719 face
= FACE_FROM_ID (f
, face_id
);
3726 else if (font
!= face
->font
)
3738 DEFUN ("fontp", Ffontp
, Sfontp
, 1, 2, 0,
3739 doc
: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3740 Return nil otherwise.
3741 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3742 which kind of font it is. It must be one of `font-spec', `font-entity',
3744 (object
, extra_type
)
3745 Lisp_Object object
, extra_type
;
3747 if (NILP (extra_type
))
3748 return (FONTP (object
) ? Qt
: Qnil
);
3749 if (EQ (extra_type
, Qfont_spec
))
3750 return (FONT_SPEC_P (object
) ? Qt
: Qnil
);
3751 if (EQ (extra_type
, Qfont_entity
))
3752 return (FONT_ENTITY_P (object
) ? Qt
: Qnil
);
3753 if (EQ (extra_type
, Qfont_object
))
3754 return (FONT_OBJECT_P (object
) ? Qt
: Qnil
);
3755 wrong_type_argument (intern ("font-extra-type"), extra_type
);
3758 DEFUN ("font-spec", Ffont_spec
, Sfont_spec
, 0, MANY
, 0,
3759 doc
: /* Return a newly created font-spec with arguments as properties.
3761 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3762 valid font property name listed below:
3764 `:family', `:weight', `:slant', `:width'
3766 They are the same as face attributes of the same name. See
3767 `set-face-attribute'.
3771 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3775 VALUE must be a string or a symbol specifying the additional
3776 typographic style information of a font, e.g. ``sans''.
3780 VALUE must be a string or a symbol specifying the charset registry and
3781 encoding of a font, e.g. ``iso8859-1''.
3785 VALUE must be a non-negative integer or a floating point number
3786 specifying the font size. It specifies the font size in pixels
3787 (if VALUE is an integer), or in points (if VALUE is a float).
3791 VALUE must be a string of XLFD-style or fontconfig-style font name.
3792 usage: (font-spec ARGS ...) */)
3797 Lisp_Object spec
= font_make_spec ();
3800 for (i
= 0; i
< nargs
; i
+= 2)
3802 Lisp_Object key
= args
[i
], val
= args
[i
+ 1];
3804 if (EQ (key
, QCname
))
3807 font_parse_name ((char *) SDATA (val
), spec
);
3808 font_put_extra (spec
, key
, val
);
3812 int idx
= get_font_prop_index (key
);
3816 val
= font_prop_validate (idx
, Qnil
, val
);
3817 if (idx
< FONT_EXTRA_INDEX
)
3818 ASET (spec
, idx
, val
);
3820 font_put_extra (spec
, key
, val
);
3823 font_put_extra (spec
, key
, font_prop_validate (0, key
, val
));
3829 DEFUN ("copy-font-spec", Fcopy_font_spec
, Scopy_font_spec
, 1, 1, 0,
3830 doc
: /* Return a copy of FONT as a font-spec. */)
3834 Lisp_Object new_spec
, tail
, prev
, extra
;
3838 new_spec
= font_make_spec ();
3839 for (i
= 1; i
< FONT_EXTRA_INDEX
; i
++)
3840 ASET (new_spec
, i
, AREF (font
, i
));
3841 extra
= Fcopy_sequence (AREF (font
, FONT_EXTRA_INDEX
));
3842 /* We must remove :font-entity property. */
3843 for (prev
= Qnil
, tail
= extra
; CONSP (tail
); prev
= tail
, tail
= XCDR (tail
))
3844 if (EQ (XCAR (XCAR (tail
)), QCfont_entity
))
3847 extra
= XCDR (extra
);
3849 XSETCDR (prev
, XCDR (tail
));
3852 ASET (new_spec
, FONT_EXTRA_INDEX
, extra
);
3856 DEFUN ("merge-font-spec", Fmerge_font_spec
, Smerge_font_spec
, 2, 2, 0,
3857 doc
: /* Merge font-specs FROM and TO, and return a new font-spec.
3858 Every specified properties in FROM override the corresponding
3859 properties in TO. */)
3861 Lisp_Object from
, to
;
3863 Lisp_Object extra
, tail
;
3868 to
= Fcopy_font_spec (to
);
3869 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
3870 ASET (to
, i
, AREF (from
, i
));
3871 extra
= AREF (to
, FONT_EXTRA_INDEX
);
3872 for (tail
= AREF (from
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
3873 if (! EQ (XCAR (XCAR (tail
)), Qfont_entity
))
3875 Lisp_Object slot
= assq_no_quit (XCAR (XCAR (tail
)), extra
);
3878 XSETCDR (slot
, XCDR (XCAR (tail
)));
3880 extra
= Fcons (Fcons (XCAR (XCAR (tail
)), XCDR (XCAR (tail
))), extra
);
3882 ASET (to
, FONT_EXTRA_INDEX
, extra
);
3886 DEFUN ("font-get", Ffont_get
, Sfont_get
, 2, 2, 0,
3887 doc
: /* Return the value of FONT's property KEY.
3888 FONT is a font-spec, a font-entity, or a font-object. */)
3890 Lisp_Object font
, key
;
3897 idx
= get_font_prop_index (key
);
3898 if (idx
>= FONT_WEIGHT_INDEX
&& idx
<= FONT_WIDTH_INDEX
)
3899 return font_style_symbolic (font
, idx
, 0);
3900 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
3901 return AREF (font
, idx
);
3902 return Fcdr (Fassq (key
, AREF (font
, FONT_EXTRA_INDEX
)));
3905 #ifdef HAVE_WINDOW_SYSTEM
3907 DEFUN ("font-face-attributes", Ffont_face_attributes
, Sfont_face_attributes
, 1, 2, 0,
3908 doc
: /* Return a plist of face attributes generated by FONT.
3909 FONT is a font name, a font-spec, a font-entity, or a font-object.
3910 The return value is a list of the form
3912 \(:family FAMILY :height HEIGHT :weight WEIGHT :slant SLANT :width WIDTH)
3914 where FAMILY, HEIGHT, WEIGHT, SLANT, and WIDTH are face attribute values
3915 compatible with `set-face-attribute'. Some of these key-attribute pairs
3916 may be omitted from the list if they are not specified by FONT.
3918 The optional argument FRAME specifies the frame that the face attributes
3919 are to be displayed on. If omitted, the selected frame is used. */)
3921 Lisp_Object font
, frame
;
3924 Lisp_Object plist
[10];
3929 frame
= selected_frame
;
3930 CHECK_LIVE_FRAME (frame
);
3935 int fontset
= fs_query_fontset (font
, 0);
3936 Lisp_Object name
= font
;
3938 font
= fontset_ascii (fontset
);
3939 font
= font_spec_from_name (name
);
3941 signal_error ("Invalid font name", name
);
3943 else if (! FONTP (font
))
3944 signal_error ("Invalid font object", font
);
3946 val
= AREF (font
, FONT_FAMILY_INDEX
);
3949 plist
[n
++] = QCfamily
;
3950 plist
[n
++] = SYMBOL_NAME (val
);
3953 val
= AREF (font
, FONT_SIZE_INDEX
);
3956 Lisp_Object font_dpi
= AREF (font
, FONT_DPI_INDEX
);
3957 int dpi
= INTEGERP (font_dpi
) ? XINT (font_dpi
) : f
->resy
;
3958 plist
[n
++] = QCheight
;
3959 plist
[n
++] = make_number (PIXEL_TO_POINT (XINT (val
) * 10, dpi
));
3961 else if (FLOATP (val
))
3963 plist
[n
++] = QCheight
;
3964 plist
[n
++] = make_number (10 * (int) XFLOAT_DATA (val
));
3967 val
= FONT_WEIGHT_FOR_FACE (font
);
3970 plist
[n
++] = QCweight
;
3974 val
= FONT_SLANT_FOR_FACE (font
);
3977 plist
[n
++] = QCslant
;
3981 val
= FONT_WIDTH_FOR_FACE (font
);
3984 plist
[n
++] = QCwidth
;
3988 return Flist (n
, plist
);
3993 DEFUN ("font-put", Ffont_put
, Sfont_put
, 3, 3, 0,
3994 doc
: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
3995 (font_spec
, prop
, val
)
3996 Lisp_Object font_spec
, prop
, val
;
4000 CHECK_FONT_SPEC (font_spec
);
4001 idx
= get_font_prop_index (prop
);
4002 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
4003 ASET (font_spec
, idx
, font_prop_validate (idx
, Qnil
, val
));
4005 font_put_extra (font_spec
, prop
, font_prop_validate (0, prop
, val
));
4009 DEFUN ("list-fonts", Flist_fonts
, Slist_fonts
, 1, 4, 0,
4010 doc
: /* List available fonts matching FONT-SPEC on the current frame.
4011 Optional 2nd argument FRAME specifies the target frame.
4012 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
4013 Optional 4th argument PREFER, if non-nil, is a font-spec to
4014 control the order of the returned list. Fonts are sorted by
4015 how close they are to PREFER. */)
4016 (font_spec
, frame
, num
, prefer
)
4017 Lisp_Object font_spec
, frame
, num
, prefer
;
4019 Lisp_Object vec
, list
, tail
;
4023 frame
= selected_frame
;
4024 CHECK_LIVE_FRAME (frame
);
4025 CHECK_FONT_SPEC (font_spec
);
4033 if (! NILP (prefer
))
4034 CHECK_FONT_SPEC (prefer
);
4036 vec
= font_list_entities (frame
, font_spec
);
4041 return Fcons (AREF (vec
, 0), Qnil
);
4043 if (! NILP (prefer
))
4044 vec
= font_sort_entites (vec
, prefer
, frame
, 0);
4046 list
= tail
= Fcons (AREF (vec
, 0), Qnil
);
4047 if (n
== 0 || n
> len
)
4049 for (i
= 1; i
< n
; i
++)
4051 Lisp_Object val
= Fcons (AREF (vec
, i
), Qnil
);
4053 XSETCDR (tail
, val
);
4059 DEFUN ("font-family-list", Ffont_family_list
, Sfont_family_list
, 0, 1, 0,
4060 doc
: /* List available font families on the current frame.
4061 Optional argument FRAME, if non-nil, specifies the target frame. */)
4066 struct font_driver_list
*driver_list
;
4070 frame
= selected_frame
;
4071 CHECK_LIVE_FRAME (frame
);
4074 for (driver_list
= f
->font_driver_list
; driver_list
;
4075 driver_list
= driver_list
->next
)
4076 if (driver_list
->driver
->list_family
)
4078 Lisp_Object val
= driver_list
->driver
->list_family (frame
);
4084 Lisp_Object tail
= list
;
4086 for (; CONSP (val
); val
= XCDR (val
))
4087 if (NILP (Fmemq (XCAR (val
), tail
)))
4088 list
= Fcons (XCAR (val
), list
);
4094 DEFUN ("find-font", Ffind_font
, Sfind_font
, 1, 2, 0,
4095 doc
: /* Return a font-entity matching with FONT-SPEC on the current frame.
4096 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
4098 Lisp_Object font_spec
, frame
;
4100 Lisp_Object val
= Flist_fonts (font_spec
, frame
, make_number (1), Qnil
);
4107 DEFUN ("font-xlfd-name", Ffont_xlfd_name
, Sfont_xlfd_name
, 1, 2, 0,
4108 doc
: /* Return XLFD name of FONT.
4109 FONT is a font-spec, font-entity, or font-object.
4110 If the name is too long for XLFD (maximum 255 chars), return nil.
4111 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
4112 the consecutive wildcards are folded to one. */)
4113 (font
, fold_wildcards
)
4114 Lisp_Object font
, fold_wildcards
;
4121 if (FONT_OBJECT_P (font
))
4123 Lisp_Object font_name
= AREF (font
, FONT_NAME_INDEX
);
4125 if (STRINGP (font_name
)
4126 && SDATA (font_name
)[0] == '-')
4128 if (NILP (fold_wildcards
))
4130 strcpy (name
, (char *) SDATA (font_name
));
4133 pixel_size
= XFONT_OBJECT (font
)->pixel_size
;
4135 if (font_unparse_xlfd (font
, pixel_size
, name
, 256) < 0)
4138 if (! NILP (fold_wildcards
))
4140 char *p0
= name
, *p1
;
4142 while ((p1
= strstr (p0
, "-*-*")))
4144 strcpy (p1
, p1
+ 2);
4149 return build_string (name
);
4152 DEFUN ("clear-font-cache", Fclear_font_cache
, Sclear_font_cache
, 0, 0, 0,
4153 doc
: /* Clear font cache. */)
4156 Lisp_Object list
, frame
;
4158 FOR_EACH_FRAME (list
, frame
)
4160 FRAME_PTR f
= XFRAME (frame
);
4161 struct font_driver_list
*driver_list
= f
->font_driver_list
;
4163 for (; driver_list
; driver_list
= driver_list
->next
)
4164 if (driver_list
->on
)
4166 Lisp_Object cache
= driver_list
->driver
->get_cache (f
);
4171 && ! EQ (XCAR (XCAR (val
)), driver_list
->driver
->type
))
4173 font_assert (! NILP (val
));
4174 val
= XCDR (XCAR (val
));
4175 if (XINT (XCAR (val
)) == 0)
4177 font_clear_cache (f
, XCAR (val
), driver_list
->driver
);
4178 XSETCDR (cache
, XCDR (val
));
4186 /* The following three functions are still experimental. */
4188 DEFUN ("font-make-gstring", Ffont_make_gstring
, Sfont_make_gstring
, 2, 2, 0,
4189 doc
: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
4190 FONT-OBJECT may be nil if it is not yet known.
4192 G-string is sequence of glyphs of a specific font,
4193 and is a vector of this form:
4194 [ HEADER GLYPH ... ]
4195 HEADER is a vector of this form:
4196 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
4198 FONT-OBJECT is a font-object for all glyphs in the g-string,
4199 WIDTH thru DESCENT are the metrics (in pixels) of the whole G-string.
4200 GLYPH is a vector of this form:
4201 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
4202 [ [X-OFF Y-OFF WADJUST] | nil] ]
4204 FROM-IDX and TO-IDX are used internally and should not be touched.
4205 C is the character of the glyph.
4206 CODE is the glyph-code of C in FONT-OBJECT.
4207 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
4208 X-OFF and Y-OFF are offests to the base position for the glyph.
4209 WADJUST is the adjustment to the normal width of the glyph. */)
4211 Lisp_Object font_object
, num
;
4213 Lisp_Object gstring
, g
;
4217 if (! NILP (font_object
))
4218 CHECK_FONT_OBJECT (font_object
);
4221 len
= XINT (num
) + 1;
4222 gstring
= Fmake_vector (make_number (len
), Qnil
);
4223 g
= Fmake_vector (make_number (6), Qnil
);
4224 ASET (g
, 0, font_object
);
4225 ASET (gstring
, 0, g
);
4226 for (i
= 1; i
< len
; i
++)
4227 ASET (gstring
, i
, Fmake_vector (make_number (10), Qnil
));
4231 DEFUN ("font-fill-gstring", Ffont_fill_gstring
, Sfont_fill_gstring
, 4, 5, 0,
4232 doc
: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
4233 START and END specify the region to extract characters.
4234 If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
4235 where to extract characters.
4236 FONT-OBJECT may be nil if GSTRING already contains one. */)
4237 (gstring
, font_object
, start
, end
, object
)
4238 Lisp_Object gstring
, font_object
, start
, end
, object
;
4244 CHECK_VECTOR (gstring
);
4245 if (NILP (font_object
))
4246 font_object
= LGSTRING_FONT (gstring
);
4247 font
= XFONT_OBJECT (font_object
);
4249 if (STRINGP (object
))
4251 const unsigned char *p
;
4253 CHECK_NATNUM (start
);
4255 if (XINT (start
) > XINT (end
)
4256 || XINT (end
) > ASIZE (object
)
4257 || XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
4258 args_out_of_range_3 (object
, start
, end
);
4260 len
= XINT (end
) - XINT (start
);
4261 p
= SDATA (object
) + string_char_to_byte (object
, XINT (start
));
4262 for (i
= 0; i
< len
; i
++)
4264 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
4265 /* Shut up GCC warning in comparison with
4266 MOST_POSITIVE_FIXNUM below. */
4269 c
= STRING_CHAR_ADVANCE (p
);
4270 cod
= code
= font
->driver
->encode_char (font
, c
);
4271 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
4273 LGLYPH_SET_FROM (g
, i
);
4274 LGLYPH_SET_TO (g
, i
);
4275 LGLYPH_SET_CHAR (g
, c
);
4276 LGLYPH_SET_CODE (g
, code
);
4283 if (! NILP (object
))
4284 Fset_buffer (object
);
4285 validate_region (&start
, &end
);
4286 if (XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
4287 args_out_of_range (start
, end
);
4288 len
= XINT (end
) - XINT (start
);
4290 pos_byte
= CHAR_TO_BYTE (pos
);
4291 for (i
= 0; i
< len
; i
++)
4293 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
4294 /* Shut up GCC warning in comparison with
4295 MOST_POSITIVE_FIXNUM below. */
4298 FETCH_CHAR_ADVANCE (c
, pos
, pos_byte
);
4299 cod
= code
= font
->driver
->encode_char (font
, c
);
4300 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
4302 LGLYPH_SET_FROM (g
, i
);
4303 LGLYPH_SET_TO (g
, i
);
4304 LGLYPH_SET_CHAR (g
, c
);
4305 LGLYPH_SET_CODE (g
, code
);
4308 for (; i
< LGSTRING_LENGTH (gstring
); i
++)
4309 LGSTRING_SET_GLYPH (gstring
, i
, Qnil
);
4313 DEFUN ("font-shape-text", Ffont_shape_text
, Sfont_shape_text
, 3, 4, 0,
4314 doc
: /* Shape text between FROM and TO by FONT-OBJECT.
4315 If optional 4th argument STRING is non-nil, it is a string to shape,
4316 and FROM and TO are indices to the string.
4317 The value is the end position of the text that can be shaped by
4319 (from
, to
, font_object
, string
)
4320 Lisp_Object from
, to
, font_object
, string
;
4323 struct font_metrics metrics
;
4324 EMACS_INT start
, end
;
4325 Lisp_Object gstring
, n
;
4328 if (! FONT_OBJECT_P (font_object
))
4330 font
= XFONT_OBJECT (font_object
);
4331 if (! font
->driver
->shape
)
4336 validate_region (&from
, &to
);
4337 start
= XFASTINT (from
);
4338 end
= XFASTINT (to
);
4339 modify_region (current_buffer
, start
, end
, 0);
4343 CHECK_STRING (string
);
4344 start
= XINT (from
);
4346 if (start
< 0 || start
> end
|| end
> SCHARS (string
))
4347 args_out_of_range_3 (string
, from
, to
);
4351 gstring
= Ffont_make_gstring (font_object
, make_number (len
));
4352 Ffont_fill_gstring (gstring
, font_object
, from
, to
, string
);
4354 /* Try at most three times with larger gstring each time. */
4355 for (i
= 0; i
< 3; i
++)
4357 Lisp_Object args
[2];
4359 n
= font
->driver
->shape (gstring
);
4363 args
[1] = Fmake_vector (make_number (len
), Qnil
);
4364 gstring
= Fvconcat (2, args
);
4366 if (! INTEGERP (n
) || XINT (n
) == 0)
4370 for (i
= 0; i
< len
;)
4373 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
4374 EMACS_INT this_from
= LGLYPH_FROM (g
);
4375 EMACS_INT this_to
= LGLYPH_TO (g
) + 1;
4377 int need_composition
= 0;
4379 metrics
.lbearing
= LGLYPH_LBEARING (g
);
4380 metrics
.rbearing
= LGLYPH_RBEARING (g
);
4381 metrics
.ascent
= LGLYPH_ASCENT (g
);
4382 metrics
.descent
= LGLYPH_DESCENT (g
);
4383 if (NILP (LGLYPH_ADJUSTMENT (g
)))
4385 metrics
.width
= LGLYPH_WIDTH (g
);
4386 if (LGLYPH_CHAR (g
) == 0 || metrics
.width
== 0)
4387 need_composition
= 1;
4391 metrics
.width
= LGLYPH_WADJUST (g
);
4392 metrics
.lbearing
+= LGLYPH_XOFF (g
);
4393 metrics
.rbearing
+= LGLYPH_XOFF (g
);
4394 metrics
.ascent
-= LGLYPH_YOFF (g
);
4395 metrics
.descent
+= LGLYPH_YOFF (g
);
4396 need_composition
= 1;
4398 for (j
= i
+ 1; j
< len
; j
++)
4402 g
= LGSTRING_GLYPH (gstring
, j
);
4403 if (this_from
!= LGLYPH_FROM (g
))
4405 need_composition
= 1;
4406 x
= metrics
.width
+ LGLYPH_LBEARING (g
) + LGLYPH_XOFF (g
);
4407 if (metrics
.lbearing
> x
)
4408 metrics
.lbearing
= x
;
4409 x
= metrics
.width
+ LGLYPH_RBEARING (g
) + LGLYPH_XOFF (g
);
4410 if (metrics
.rbearing
< x
)
4411 metrics
.rbearing
= x
;
4412 x
= LGLYPH_ASCENT (g
) - LGLYPH_YOFF (g
);
4413 if (metrics
.ascent
< x
)
4415 x
= LGLYPH_DESCENT (g
) - LGLYPH_YOFF (g
);
4416 if (metrics
.descent
< x
)
4417 metrics
.descent
= x
;
4418 if (NILP (LGLYPH_ADJUSTMENT (g
)))
4419 metrics
.width
+= LGLYPH_WIDTH (g
);
4421 metrics
.width
+= LGLYPH_WADJUST (g
);
4424 if (need_composition
)
4426 gstr
= Ffont_make_gstring (font_object
, make_number (j
- i
));
4427 LGSTRING_SET_WIDTH (gstr
, metrics
.width
);
4428 LGSTRING_SET_LBEARING (gstr
, metrics
.lbearing
);
4429 LGSTRING_SET_RBEARING (gstr
, metrics
.rbearing
);
4430 LGSTRING_SET_ASCENT (gstr
, metrics
.ascent
);
4431 LGSTRING_SET_DESCENT (gstr
, metrics
.descent
);
4432 for (k
= i
; i
< j
; i
++)
4434 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
4436 LGLYPH_SET_FROM (g
, LGLYPH_FROM (g
) - this_from
);
4437 LGLYPH_SET_TO (g
, LGLYPH_TO (g
) - this_from
);
4438 LGSTRING_SET_GLYPH (gstr
, i
- k
, LGSTRING_GLYPH (gstring
, i
));
4440 from
= make_number (start
+ this_from
);
4441 to
= make_number (start
+ this_to
);
4443 Fcompose_region_internal (from
, to
, gstr
, Qnil
);
4445 Fcompose_string_internal (string
, from
, to
, gstr
, Qnil
);
4456 DEFUN ("font-drive-otf", Ffont_drive_otf
, Sfont_drive_otf
, 6, 6, 0,
4457 doc
: /* Apply OpenType features on glyph-string GSTRING-IN.
4458 OTF-FEATURES specifies which features to apply in this format:
4459 (SCRIPT LANGSYS GSUB GPOS)
4461 SCRIPT is a symbol specifying a script tag of OpenType,
4462 LANGSYS is a symbol specifying a langsys tag of OpenType,
4463 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4465 If LANGYS is nil, the default langsys is selected.
4467 The features are applied in the order they appear in the list. The
4468 symbol `*' means to apply all available features not present in this
4469 list, and the remaining features are ignored. For instance, (vatu
4470 pstf * haln) is to apply vatu and pstf in this order, then to apply
4471 all available features other than vatu, pstf, and haln.
4473 The features are applied to the glyphs in the range FROM and TO of
4474 the glyph-string GSTRING-IN.
4476 If some feature is actually applicable, the resulting glyphs are
4477 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4478 this case, the value is the number of produced glyphs.
4480 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4483 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4484 produced in GSTRING-OUT, and the value is nil.
4486 See the documentation of `font-make-gstring' for the format of
4488 (otf_features
, gstring_in
, from
, to
, gstring_out
, index
)
4489 Lisp_Object otf_features
, gstring_in
, from
, to
, gstring_out
, index
;
4491 Lisp_Object font_object
= LGSTRING_FONT (gstring_in
);
4496 check_otf_features (otf_features
);
4497 CHECK_FONT_OBJECT (font_object
);
4498 font
= XFONT_OBJECT (font_object
);
4499 if (! font
->driver
->otf_drive
)
4500 error ("Font backend %s can't drive OpenType GSUB table",
4501 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4502 CHECK_CONS (otf_features
);
4503 CHECK_SYMBOL (XCAR (otf_features
));
4504 val
= XCDR (otf_features
);
4505 CHECK_SYMBOL (XCAR (val
));
4506 val
= XCDR (otf_features
);
4509 len
= check_gstring (gstring_in
);
4510 CHECK_VECTOR (gstring_out
);
4511 CHECK_NATNUM (from
);
4513 CHECK_NATNUM (index
);
4515 if (XINT (from
) >= XINT (to
) || XINT (to
) > len
)
4516 args_out_of_range_3 (from
, to
, make_number (len
));
4517 if (XINT (index
) >= ASIZE (gstring_out
))
4518 args_out_of_range (index
, make_number (ASIZE (gstring_out
)));
4519 num
= font
->driver
->otf_drive (font
, otf_features
,
4520 gstring_in
, XINT (from
), XINT (to
),
4521 gstring_out
, XINT (index
), 0);
4524 return make_number (num
);
4527 DEFUN ("font-otf-alternates", Ffont_otf_alternates
, Sfont_otf_alternates
,
4529 doc
: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4530 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4532 (SCRIPT LANGSYS FEATURE ...)
4533 See the documentation of `font-drive-otf' for more detail.
4535 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4536 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4537 character code corresponding to the glyph or nil if there's no
4538 corresponding character. */)
4539 (font_object
, character
, otf_features
)
4540 Lisp_Object font_object
, character
, otf_features
;
4543 Lisp_Object gstring_in
, gstring_out
, g
;
4544 Lisp_Object alternates
;
4547 CHECK_FONT_GET_OBJECT (font_object
, font
);
4548 if (! font
->driver
->otf_drive
)
4549 error ("Font backend %s can't drive OpenType GSUB table",
4550 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4551 CHECK_CHARACTER (character
);
4552 CHECK_CONS (otf_features
);
4554 gstring_in
= Ffont_make_gstring (font_object
, make_number (1));
4555 g
= LGSTRING_GLYPH (gstring_in
, 0);
4556 LGLYPH_SET_CHAR (g
, XINT (character
));
4557 gstring_out
= Ffont_make_gstring (font_object
, make_number (10));
4558 while ((num
= font
->driver
->otf_drive (font
, otf_features
, gstring_in
, 0, 1,
4559 gstring_out
, 0, 1)) < 0)
4560 gstring_out
= Ffont_make_gstring (font_object
,
4561 make_number (ASIZE (gstring_out
) * 2));
4563 for (i
= 0; i
< num
; i
++)
4565 Lisp_Object g
= LGSTRING_GLYPH (gstring_out
, i
);
4566 int c
= LGLYPH_CHAR (g
);
4567 unsigned code
= LGLYPH_CODE (g
);
4569 alternates
= Fcons (Fcons (make_number (code
),
4570 c
> 0 ? make_number (c
) : Qnil
),
4573 return Fnreverse (alternates
);
4579 DEFUN ("open-font", Fopen_font
, Sopen_font
, 1, 3, 0,
4580 doc
: /* Open FONT-ENTITY. */)
4581 (font_entity
, size
, frame
)
4582 Lisp_Object font_entity
;
4588 CHECK_FONT_ENTITY (font_entity
);
4590 frame
= selected_frame
;
4591 CHECK_LIVE_FRAME (frame
);
4594 isize
= XINT (AREF (font_entity
, FONT_SIZE_INDEX
));
4597 CHECK_NUMBER_OR_FLOAT (size
);
4599 isize
= POINT_TO_PIXEL (- isize
, XFRAME (frame
)->resy
);
4601 isize
= XINT (size
);
4605 return font_open_entity (XFRAME (frame
), font_entity
, isize
);
4608 DEFUN ("close-font", Fclose_font
, Sclose_font
, 1, 2, 0,
4609 doc
: /* Close FONT-OBJECT. */)
4610 (font_object
, frame
)
4611 Lisp_Object font_object
, frame
;
4613 CHECK_FONT_OBJECT (font_object
);
4615 frame
= selected_frame
;
4616 CHECK_LIVE_FRAME (frame
);
4617 font_close_object (XFRAME (frame
), font_object
);
4621 DEFUN ("query-font", Fquery_font
, Squery_font
, 1, 1, 0,
4622 doc
: /* Return information about FONT-OBJECT.
4623 The value is a vector:
4624 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4627 NAME is a string of the font name (or nil if the font backend doesn't
4630 FILENAME is a string of the font file (or nil if the font backend
4631 doesn't provide a file name).
4633 PIXEL-SIZE is a pixel size by which the font is opened.
4635 SIZE is a maximum advance width of the font in pixels.
4637 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4640 CAPABILITY is a list whose first element is a symbol representing the
4641 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4642 remaining elements describe the details of the font capability.
4644 If the font is OpenType font, the form of the list is
4645 \(opentype GSUB GPOS)
4646 where GSUB shows which "GSUB" features the font supports, and GPOS
4647 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4648 lists of the format:
4649 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4651 If the font is not OpenType font, currently the length of the form is
4654 SCRIPT is a symbol representing OpenType script tag.
4656 LANGSYS is a symbol representing OpenType langsys tag, or nil
4657 representing the default langsys.
4659 FEATURE is a symbol representing OpenType feature tag.
4661 If the font is not OpenType font, CAPABILITY is nil. */)
4663 Lisp_Object font_object
;
4668 CHECK_FONT_GET_OBJECT (font_object
, font
);
4670 val
= Fmake_vector (make_number (9), Qnil
);
4671 ASET (val
, 0, AREF (font_object
, FONT_NAME_INDEX
));
4672 ASET (val
, 1, AREF (font_object
, FONT_FILE_INDEX
));
4673 ASET (val
, 2, make_number (font
->pixel_size
));
4674 ASET (val
, 3, make_number (font
->max_width
));
4675 ASET (val
, 4, make_number (font
->ascent
));
4676 ASET (val
, 5, make_number (font
->descent
));
4677 ASET (val
, 6, make_number (font
->space_width
));
4678 ASET (val
, 7, make_number (font
->average_width
));
4679 if (font
->driver
->otf_capability
)
4680 ASET (val
, 8, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
4684 DEFUN ("get-font-glyphs", Fget_font_glyphs
, Sget_font_glyphs
, 2, 2, 0,
4685 doc
: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
4686 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
4687 (font_object
, string
)
4688 Lisp_Object font_object
, string
;
4694 CHECK_FONT_GET_OBJECT (font_object
, font
);
4695 CHECK_STRING (string
);
4696 len
= SCHARS (string
);
4697 vec
= Fmake_vector (make_number (len
), Qnil
);
4698 for (i
= 0; i
< len
; i
++)
4700 Lisp_Object ch
= Faref (string
, make_number (i
));
4705 struct font_metrics metrics
;
4707 cod
= code
= font
->driver
->encode_char (font
, c
);
4708 if (code
== FONT_INVALID_CODE
)
4710 val
= Fmake_vector (make_number (6), Qnil
);
4711 if (cod
<= MOST_POSITIVE_FIXNUM
)
4712 ASET (val
, 0, make_number (code
));
4714 ASET (val
, 0, Fcons (make_number (code
>> 16),
4715 make_number (code
& 0xFFFF)));
4716 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4717 ASET (val
, 1, make_number (metrics
.lbearing
));
4718 ASET (val
, 2, make_number (metrics
.rbearing
));
4719 ASET (val
, 3, make_number (metrics
.width
));
4720 ASET (val
, 4, make_number (metrics
.ascent
));
4721 ASET (val
, 5, make_number (metrics
.descent
));
4727 DEFUN ("font-match-p", Ffont_match_p
, Sfont_match_p
, 2, 2, 0,
4728 doc
: /* Return t if and only if font-spec SPEC matches with FONT.
4729 FONT is a font-spec, font-entity, or font-object. */)
4731 Lisp_Object spec
, font
;
4733 CHECK_FONT_SPEC (spec
);
4736 return (font_match_p (spec
, font
) ? Qt
: Qnil
);
4739 DEFUN ("font-at", Ffont_at
, Sfont_at
, 1, 3, 0,
4740 doc
: /* Return a font-object for displaying a character at POSITION.
4741 Optional second arg WINDOW, if non-nil, is a window displaying
4742 the current buffer. It defaults to the currently selected window. */)
4743 (position
, window
, string
)
4744 Lisp_Object position
, window
, string
;
4751 CHECK_NUMBER_COERCE_MARKER (position
);
4752 pos
= XINT (position
);
4753 if (pos
< BEGV
|| pos
>= ZV
)
4754 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
4758 CHECK_NUMBER (position
);
4759 CHECK_STRING (string
);
4760 pos
= XINT (position
);
4761 if (pos
< 0 || pos
>= SCHARS (string
))
4762 args_out_of_range (string
, position
);
4765 window
= selected_window
;
4766 CHECK_LIVE_WINDOW (window
);
4767 w
= XWINDOW (window
);
4769 return font_at (-1, pos
, NULL
, w
, string
);
4773 DEFUN ("draw-string", Fdraw_string
, Sdraw_string
, 2, 2, 0,
4774 doc
: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4775 The value is a number of glyphs drawn.
4776 Type C-l to recover what previously shown. */)
4777 (font_object
, string
)
4778 Lisp_Object font_object
, string
;
4780 Lisp_Object frame
= selected_frame
;
4781 FRAME_PTR f
= XFRAME (frame
);
4787 CHECK_FONT_GET_OBJECT (font_object
, font
);
4788 CHECK_STRING (string
);
4789 len
= SCHARS (string
);
4790 code
= alloca (sizeof (unsigned) * len
);
4791 for (i
= 0; i
< len
; i
++)
4793 Lisp_Object ch
= Faref (string
, make_number (i
));
4797 code
[i
] = font
->driver
->encode_char (font
, c
);
4798 if (code
[i
] == FONT_INVALID_CODE
)
4801 face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4803 if (font
->driver
->prepare_face
)
4804 font
->driver
->prepare_face (f
, face
);
4805 width
= font
->driver
->text_extents (font
, code
, i
, NULL
);
4806 len
= font
->driver
->draw_text (f
, face
, 0, font
->ascent
, code
, i
, width
);
4807 if (font
->driver
->done_face
)
4808 font
->driver
->done_face (f
, face
);
4810 return make_number (len
);
4814 #endif /* FONT_DEBUG */
4816 #ifdef HAVE_WINDOW_SYSTEM
4818 DEFUN ("font-info", Ffont_info
, Sfont_info
, 1, 2, 0,
4819 doc
: /* Return information about a font named NAME on frame FRAME.
4820 If FRAME is omitted or nil, use the selected frame.
4821 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
4822 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4824 OPENED-NAME is the name used for opening the font,
4825 FULL-NAME is the full name of the font,
4826 SIZE is the maximum bound width of the font,
4827 HEIGHT is the height of the font,
4828 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4829 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4830 how to compose characters.
4831 If the named font is not yet loaded, return nil. */)
4833 Lisp_Object name
, frame
;
4838 Lisp_Object font_object
;
4840 (*check_window_system_func
) ();
4843 CHECK_STRING (name
);
4845 frame
= selected_frame
;
4846 CHECK_LIVE_FRAME (frame
);
4851 int fontset
= fs_query_fontset (name
, 0);
4854 name
= fontset_ascii (fontset
);
4855 font_object
= font_open_by_name (f
, (char *) SDATA (name
));
4857 else if (FONT_OBJECT_P (name
))
4859 else if (FONT_ENTITY_P (name
))
4860 font_object
= font_open_entity (f
, name
, 0);
4863 struct face
*face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4864 Lisp_Object entity
= font_matching_entity (f
, face
->lface
, name
);
4866 font_object
= ! NILP (entity
) ? font_open_entity (f
, entity
, 0) : Qnil
;
4868 if (NILP (font_object
))
4870 font
= XFONT_OBJECT (font_object
);
4872 info
= Fmake_vector (make_number (7), Qnil
);
4873 XVECTOR (info
)->contents
[0] = AREF (font_object
, FONT_NAME_INDEX
);
4874 XVECTOR (info
)->contents
[1] = AREF (font_object
, FONT_NAME_INDEX
);
4875 XVECTOR (info
)->contents
[2] = make_number (font
->pixel_size
);
4876 XVECTOR (info
)->contents
[3] = make_number (font
->height
);
4877 XVECTOR (info
)->contents
[4] = make_number (font
->baseline_offset
);
4878 XVECTOR (info
)->contents
[5] = make_number (font
->relative_compose
);
4879 XVECTOR (info
)->contents
[6] = make_number (font
->default_ascent
);
4882 /* As font_object is still in FONT_OBJLIST of the entity, we can't
4883 close it now. Perhaps, we should manage font-objects
4884 by `reference-count'. */
4885 font_close_object (f
, font_object
);
4892 #define BUILD_STYLE_TABLE(TBL) \
4893 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
4896 build_style_table (entry
, nelement
)
4897 struct table_entry
*entry
;
4901 Lisp_Object table
, elt
;
4903 table
= Fmake_vector (make_number (nelement
), Qnil
);
4904 for (i
= 0; i
< nelement
; i
++)
4906 for (j
= 0; entry
[i
].names
[j
]; j
++);
4907 elt
= Fmake_vector (make_number (j
+ 1), Qnil
);
4908 ASET (elt
, 0, make_number (entry
[i
].numeric
));
4909 for (j
= 0; entry
[i
].names
[j
]; j
++)
4910 ASET (elt
, j
+ 1, intern (entry
[i
].names
[j
]));
4911 ASET (table
, i
, elt
);
4916 static Lisp_Object Vfont_log
;
4917 static int font_log_env_checked
;
4920 font_add_log (action
, arg
, result
)
4922 Lisp_Object arg
, result
;
4924 Lisp_Object tail
, val
;
4927 if (! font_log_env_checked
)
4929 Vfont_log
= egetenv ("EMACS_FONT_LOG") ? Qnil
: Qt
;
4930 font_log_env_checked
= 1;
4932 if (EQ (Vfont_log
, Qt
))
4935 arg
= Ffont_xlfd_name (arg
, Qt
);
4938 val
= Ffont_xlfd_name (result
, Qt
);
4939 if (! FONT_SPEC_P (result
))
4940 val
= concat3 (SYMBOL_NAME (AREF (result
, FONT_TYPE_INDEX
)),
4941 build_string (":"), val
);
4944 else if (CONSP (result
))
4946 result
= Fcopy_sequence (result
);
4947 for (tail
= result
; CONSP (tail
); tail
= XCDR (tail
))
4951 val
= Ffont_xlfd_name (val
, Qt
);
4952 XSETCAR (tail
, val
);
4955 else if (VECTORP (result
))
4957 result
= Fcopy_sequence (result
);
4958 for (i
= 0; i
< ASIZE (result
); i
++)
4960 val
= AREF (result
, i
);
4962 val
= Ffont_xlfd_name (val
, Qt
);
4963 ASET (result
, i
, val
);
4966 Vfont_log
= Fcons (list3 (intern (action
), arg
, result
), Vfont_log
);
4969 extern void syms_of_ftfont
P_ (());
4970 extern void syms_of_xfont
P_ (());
4971 extern void syms_of_xftfont
P_ (());
4972 extern void syms_of_ftxfont
P_ (());
4973 extern void syms_of_bdffont
P_ (());
4974 extern void syms_of_w32font
P_ (());
4975 extern void syms_of_atmfont
P_ (());
4976 extern void syms_of_nsfont
P_ (());
4981 sort_shift_bits
[FONT_TYPE_INDEX
] = 0;
4982 sort_shift_bits
[FONT_SLANT_INDEX
] = 2;
4983 sort_shift_bits
[FONT_WEIGHT_INDEX
] = 9;
4984 sort_shift_bits
[FONT_SIZE_INDEX
] = 16;
4985 sort_shift_bits
[FONT_WIDTH_INDEX
] = 23;
4986 /* Note that the other elements in sort_shift_bits are not used. */
4988 staticpro (&font_charset_alist
);
4989 font_charset_alist
= Qnil
;
4991 DEFSYM (Qfont_spec
, "font-spec");
4992 DEFSYM (Qfont_entity
, "font-entity");
4993 DEFSYM (Qfont_object
, "font-object");
4995 DEFSYM (Qopentype
, "opentype");
4997 DEFSYM (Qascii_0
, "ascii-0");
4998 DEFSYM (Qiso8859_1
, "iso8859-1");
4999 DEFSYM (Qiso10646_1
, "iso10646-1");
5000 DEFSYM (Qunicode_bmp
, "unicode-bmp");
5001 DEFSYM (Qunicode_sip
, "unicode-sip");
5003 DEFSYM (QCotf
, ":otf");
5004 DEFSYM (QClang
, ":lang");
5005 DEFSYM (QCscript
, ":script");
5006 DEFSYM (QCantialias
, ":antialias");
5008 DEFSYM (QCfoundry
, ":foundry");
5009 DEFSYM (QCadstyle
, ":adstyle");
5010 DEFSYM (QCregistry
, ":registry");
5011 DEFSYM (QCspacing
, ":spacing");
5012 DEFSYM (QCdpi
, ":dpi");
5013 DEFSYM (QCscalable
, ":scalable");
5014 DEFSYM (QCavgwidth
, ":avgwidth");
5015 DEFSYM (QCfont_entity
, ":font-entity");
5016 DEFSYM (QCfc_unknown_spec
, ":fc-unknown-spec");
5023 staticpro (&null_vector
);
5024 null_vector
= Fmake_vector (make_number (0), Qnil
);
5026 staticpro (&scratch_font_spec
);
5027 scratch_font_spec
= Ffont_spec (0, NULL
);
5028 staticpro (&scratch_font_prefer
);
5029 scratch_font_prefer
= Ffont_spec (0, NULL
);
5033 staticpro (&otf_list
);
5035 #endif /* HAVE_LIBOTF */
5039 defsubr (&Sfont_spec
);
5040 defsubr (&Sfont_get
);
5041 #ifdef HAVE_WINDOW_SYSTEM
5042 defsubr (&Sfont_face_attributes
);
5044 defsubr (&Sfont_put
);
5045 defsubr (&Slist_fonts
);
5046 defsubr (&Sfont_family_list
);
5047 defsubr (&Sfind_font
);
5048 defsubr (&Sfont_xlfd_name
);
5049 defsubr (&Sclear_font_cache
);
5050 defsubr (&Sfont_make_gstring
);
5051 defsubr (&Sfont_fill_gstring
);
5052 defsubr (&Sfont_shape_text
);
5054 defsubr (&Sfont_drive_otf
);
5055 defsubr (&Sfont_otf_alternates
);
5059 defsubr (&Sopen_font
);
5060 defsubr (&Sclose_font
);
5061 defsubr (&Squery_font
);
5062 defsubr (&Sget_font_glyphs
);
5063 defsubr (&Sfont_match_p
);
5064 defsubr (&Sfont_at
);
5066 defsubr (&Sdraw_string
);
5068 #endif /* FONT_DEBUG */
5069 #ifdef HAVE_WINDOW_SYSTEM
5070 defsubr (&Sfont_info
);
5073 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist
,
5075 Alist of fontname patterns vs the corresponding encoding and repertory info.
5076 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
5077 where ENCODING is a charset or a char-table,
5078 and REPERTORY is a charset, a char-table, or nil.
5080 If ENCODING and REPERTORY are the same, the element can have the form
5081 \(REGEXP . ENCODING).
5083 ENCODING is for converting a character to a glyph code of the font.
5084 If ENCODING is a charset, encoding a character by the charset gives
5085 the corresponding glyph code. If ENCODING is a char-table, looking up
5086 the table by a character gives the corresponding glyph code.
5088 REPERTORY specifies a repertory of characters supported by the font.
5089 If REPERTORY is a charset, all characters beloging to the charset are
5090 supported. If REPERTORY is a char-table, all characters who have a
5091 non-nil value in the table are supported. If REPERTORY is nil, Emacs
5092 gets the repertory information by an opened font and ENCODING. */);
5093 Vfont_encoding_alist
= Qnil
;
5095 DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table
,
5096 doc
: /* Vector of valid font weight values.
5097 Each element has the form:
5098 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
5099 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
5100 Vfont_weight_table
= BUILD_STYLE_TABLE (weight_table
);
5102 DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table
,
5103 doc
: /* Vector of font slant symbols vs the corresponding numeric values.
5104 See `font-weight-table' for the format of the vector. */);
5105 Vfont_slant_table
= BUILD_STYLE_TABLE (slant_table
);
5107 DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table
,
5108 doc
: /* Alist of font width symbols vs the corresponding numeric values.
5109 See `font-weight-table' for the format of the vector. */);
5110 Vfont_width_table
= BUILD_STYLE_TABLE (width_table
);
5112 staticpro (&font_style_table
);
5113 font_style_table
= Fmake_vector (make_number (3), Qnil
);
5114 ASET (font_style_table
, 0, Vfont_weight_table
);
5115 ASET (font_style_table
, 1, Vfont_slant_table
);
5116 ASET (font_style_table
, 2, Vfont_width_table
);
5118 DEFVAR_LISP ("font-log", &Vfont_log
, doc
: /*
5119 *Logging list of font related actions and results.
5120 The value t means to suppress the logging.
5121 The initial value is set to nil if the environment variable
5122 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5125 #ifdef HAVE_WINDOW_SYSTEM
5126 #ifdef HAVE_FREETYPE
5128 #ifdef HAVE_X_WINDOWS
5133 #endif /* HAVE_XFT */
5134 #endif /* HAVE_X_WINDOWS */
5135 #else /* not HAVE_FREETYPE */
5136 #ifdef HAVE_X_WINDOWS
5138 #endif /* HAVE_X_WINDOWS */
5139 #endif /* not HAVE_FREETYPE */
5142 #endif /* HAVE_BDFFONT */
5145 #endif /* WINDOWSNT */
5148 #endif /* HAVE_NS */
5152 #endif /* HAVE_WINDOW_SYSTEM */
5155 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
5156 (do not change this comment) */