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 */
53 Lisp_Object Qfont_spec
, Qfont_entity
, Qfont_object
;
55 Lisp_Object Qopentype
;
57 /* Important character set strings. */
58 Lisp_Object Qascii_0
, Qiso8859_1
, Qiso10646_1
, Qunicode_bmp
, Qunicode_sip
;
60 /* Special vector of zero length. This is repeatedly used by (struct
61 font_driver *)->list when a specified font is not found. */
62 static Lisp_Object null_vector
;
64 static Lisp_Object Vfont_weight_table
, Vfont_slant_table
, Vfont_width_table
;
66 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
67 static Lisp_Object font_style_table
;
69 /* Structure used for tables mapping weight, slant, and width numeric
70 values and their names. */
75 /* The first one is a valid name as a face attribute.
76 The second one (if any) is a typical name in XLFD field. */
81 /* Table of weight numeric values and their names. This table must be
82 sorted by numeric values in ascending order. */
84 static struct table_entry weight_table
[] =
87 { 20, { "ultra-light", "ultralight" }},
88 { 40, { "extra-light", "extralight" }},
90 { 75, { "semi-light", "semilight", "demilight", "book" }},
91 { 100, { "normal", "medium", "regular" }},
92 { 180, { "semi-bold", "semibold", "demibold", "demi" }},
94 { 205, { "extra-bold", "extrabold" }},
95 { 210, { "ultra-bold", "ultrabold", "black" }}
98 /* Table of slant numeric values and their names. This table must be
99 sorted by numeric values in ascending order. */
101 static struct table_entry slant_table
[] =
103 { 0, { "reverse-oblique", "ro" }},
104 { 10, { "reverse-italic", "ri" }},
105 { 100, { "normal", "r" }},
106 { 200, { "italic" ,"i", "ot" }},
107 { 210, { "oblique", "o" }}
110 /* Table of width numeric values and their names. This table must be
111 sorted by numeric values in ascending order. */
113 static struct table_entry width_table
[] =
115 { 50, { "ultra-condensed", "ultracondensed" }},
116 { 63, { "extra-condensed", "extracondensed" }},
117 { 75, { "condensed", "compressed", "narrow" }},
118 { 87, { "semi-condensed", "semicondensed", "demicondensed" }},
119 { 100, { "normal", "medium", "regular" }},
120 { 113, { "semi-expanded", "semiexpanded", "demiexpanded" }},
121 { 125, { "expanded" }},
122 { 150, { "extra-expanded", "extraexpanded" }},
123 { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
126 extern Lisp_Object Qnormal
;
128 /* Symbols representing keys of normal font properties. */
129 extern Lisp_Object QCtype
, QCfamily
, QCweight
, QCslant
, QCwidth
, QCsize
, QCname
;
130 Lisp_Object QCfoundry
, QCadstyle
, QCregistry
;
131 /* Symbols representing keys of font extra info. */
132 Lisp_Object QCspacing
, QCdpi
, QCscalable
, QCotf
, QClang
, QCscript
, QCavgwidth
;
133 Lisp_Object QCantialias
, QCfont_entity
, QCfc_unknown_spec
;
134 /* Symbols representing values of font spacing property. */
135 Lisp_Object Qc
, Qm
, Qp
, Qd
;
137 Lisp_Object Vfont_encoding_alist
;
139 /* Alist of font registry symbol and the corresponding charsets
140 information. The information is retrieved from
141 Vfont_encoding_alist on demand.
143 Eash element has the form:
144 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
148 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
149 encodes a character code to a glyph code of a font, and
150 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
151 character is supported by a font.
153 The latter form means that the information for REGISTRY couldn't be
155 static Lisp_Object font_charset_alist
;
157 /* List of all font drivers. Each font-backend (XXXfont.c) calls
158 register_font_driver in syms_of_XXXfont to register its font-driver
160 static struct font_driver_list
*font_driver_list
;
164 /* Creaters of font-related Lisp object. */
169 Lisp_Object font_spec
;
170 struct font_spec
*spec
171 = ((struct font_spec
*)
172 allocate_pseudovector (VECSIZE (struct font_spec
),
173 FONT_SPEC_MAX
, PVEC_FONT
));
174 XSETFONT (font_spec
, spec
);
181 Lisp_Object font_entity
;
182 struct font_entity
*entity
183 = ((struct font_entity
*)
184 allocate_pseudovector (VECSIZE (struct font_entity
),
185 FONT_ENTITY_MAX
, PVEC_FONT
));
186 XSETFONT (font_entity
, entity
);
191 font_make_object (size
)
194 Lisp_Object font_object
;
196 = (struct font
*) allocate_pseudovector (size
, FONT_OBJECT_MAX
, PVEC_FONT
);
197 XSETFONT (font_object
, font
);
204 static int font_pixel_size
P_ ((FRAME_PTR f
, Lisp_Object
));
205 static Lisp_Object font_open_entity
P_ ((FRAME_PTR
, Lisp_Object
, int));
206 static Lisp_Object font_matching_entity
P_ ((FRAME_PTR
, Lisp_Object
*,
209 /* Number of registered font drivers. */
210 static int num_font_drivers
;
213 /* Return a Lispy value of a font property value at STR and LEN bytes.
214 If STR is "*", it returns nil.
215 If FORCE_SYMBOL is zero and all characters in STR are digits, it
216 returns an integer. Otherwise, it returns a symbol interned from
220 font_intern_prop (str
, len
, force_symbol
)
229 if (len
== 1 && *str
== '*')
231 if (!force_symbol
&& len
>=1 && isdigit (*str
))
233 for (i
= 1; i
< len
; i
++)
234 if (! isdigit (str
[i
]))
237 return make_number (atoi (str
));
240 /* The following code is copied from the function intern (in lread.c). */
242 if (!VECTORP (obarray
) || XVECTOR (obarray
)->size
== 0)
243 obarray
= check_obarray (obarray
);
244 tem
= oblookup (obarray
, str
, len
, len
);
247 return Fintern (make_unibyte_string (str
, len
), obarray
);
250 /* Return a pixel size of font-spec SPEC on frame F. */
253 font_pixel_size (f
, spec
)
257 #ifdef HAVE_WINDOW_SYSTEM
258 Lisp_Object size
= AREF (spec
, FONT_SIZE_INDEX
);
267 font_assert (FLOATP (size
));
268 point_size
= XFLOAT_DATA (size
);
269 val
= AREF (spec
, FONT_DPI_INDEX
);
274 pixel_size
= POINT_TO_PIXEL (point_size
, dpi
);
282 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
283 font vector. If VAL is not valid (i.e. not registered in
284 font_style_table), return -1 if NOERROR is zero, and return a
285 proper index if NOERROR is nonzero. In that case, register VAL in
286 font_style_table if VAL is a symbol, and return a closest index if
287 VAL is an integer. */
290 font_style_to_value (prop
, val
, noerror
)
291 enum font_property_index prop
;
295 Lisp_Object table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
296 int len
= ASIZE (table
);
302 Lisp_Object args
[2], elt
;
304 /* At first try exact match. */
305 for (i
= 0; i
< len
; i
++)
306 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
307 if (EQ (val
, AREF (AREF (table
, i
), j
)))
308 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
309 | (i
<< 4) | (j
- 1));
310 /* Try also with case-folding match. */
311 s
= SDATA (SYMBOL_NAME (val
));
312 for (i
= 0; i
< len
; i
++)
313 for (j
= 1; j
< ASIZE (AREF (table
, i
)); j
++)
315 elt
= AREF (AREF (table
, i
), j
);
316 if (xstrcasecmp (s
, SDATA (SYMBOL_NAME (elt
))) == 0)
317 return ((XINT (AREF (AREF (table
, i
), 0)) << 8)
318 | (i
<< 4) | (j
- 1));
324 elt
= Fmake_vector (make_number (2), make_number (255));
327 args
[1] = Fmake_vector (make_number (1), elt
);
328 ASET (font_style_table
, prop
- FONT_WEIGHT_INDEX
, Fvconcat (2, args
));
329 return (255 << 8) | (i
<< 4);
334 int numeric
= XINT (val
);
336 for (i
= 0, last_n
= -1; i
< len
; i
++)
338 int n
= XINT (AREF (AREF (table
, i
), 0));
341 return (n
<< 8) | (i
<< 4);
346 return ((i
== 0 || n
- numeric
< numeric
- last_n
)
347 ? (n
<< 8) | (i
<< 4): (last_n
<< 8 | ((i
- 1) << 4)));
353 return ((last_n
<< 8) | ((i
- 1) << 4));
358 font_style_symbolic (font
, prop
, for_face
)
360 enum font_property_index prop
;
363 Lisp_Object val
= AREF (font
, prop
);
364 Lisp_Object table
, elt
;
369 table
= AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
);
370 i
= XINT (val
) & 0xFF;
371 font_assert (((i
>> 4) & 0xF) < ASIZE (table
));
372 elt
= AREF (table
, ((i
>> 4) & 0xF));
373 font_assert ((i
& 0xF) + 1 < ASIZE (elt
));
374 return (for_face
? AREF (elt
, 1) : AREF (elt
, (i
& 0xF) + 1));
377 extern Lisp_Object Vface_alternative_font_family_alist
;
379 extern Lisp_Object find_font_encoding
P_ ((Lisp_Object
));
382 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
383 FONTNAME. ENCODING is a charset symbol that specifies the encoding
384 of the font. REPERTORY is a charset symbol or nil. */
387 find_font_encoding (fontname
)
388 Lisp_Object fontname
;
390 Lisp_Object tail
, elt
;
392 for (tail
= Vfont_encoding_alist
; CONSP (tail
); tail
= XCDR (tail
))
396 && STRINGP (XCAR (elt
))
397 && fast_string_match_ignore_case (XCAR (elt
), fontname
) >= 0
398 && (SYMBOLP (XCDR (elt
))
399 ? CHARSETP (XCDR (elt
))
400 : CONSP (XCDR (elt
)) && CHARSETP (XCAR (XCDR (elt
)))))
403 /* We don't know the encoding of this font. Let's assume `ascii'. */
407 /* Return encoding charset and repertory charset for REGISTRY in
408 ENCODING and REPERTORY correspondingly. If correct information for
409 REGISTRY is available, return 0. Otherwise return -1. */
412 font_registry_charsets (registry
, encoding
, repertory
)
413 Lisp_Object registry
;
414 struct charset
**encoding
, **repertory
;
417 int encoding_id
, repertory_id
;
419 val
= Fassoc_string (registry
, font_charset_alist
, Qt
);
425 encoding_id
= XINT (XCAR (val
));
426 repertory_id
= XINT (XCDR (val
));
430 val
= find_font_encoding (SYMBOL_NAME (registry
));
431 if (SYMBOLP (val
) && CHARSETP (val
))
433 encoding_id
= repertory_id
= XINT (CHARSET_SYMBOL_ID (val
));
435 else if (CONSP (val
))
437 if (! CHARSETP (XCAR (val
)))
439 encoding_id
= XINT (CHARSET_SYMBOL_ID (XCAR (val
)));
440 if (NILP (XCDR (val
)))
444 if (! CHARSETP (XCDR (val
)))
446 repertory_id
= XINT (CHARSET_SYMBOL_ID (XCDR (val
)));
451 val
= Fcons (make_number (encoding_id
), make_number (repertory_id
));
453 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, val
), Qnil
));
457 *encoding
= CHARSET_FROM_ID (encoding_id
);
459 *repertory
= repertory_id
>= 0 ? CHARSET_FROM_ID (repertory_id
) : NULL
;
464 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, Qnil
), Qnil
));
469 /* Font property value validaters. See the comment of
470 font_property_table for the meaning of the arguments. */
472 static Lisp_Object font_prop_validate
P_ ((int, Lisp_Object
, Lisp_Object
));
473 static Lisp_Object font_prop_validate_symbol
P_ ((Lisp_Object
, Lisp_Object
));
474 static Lisp_Object font_prop_validate_style
P_ ((Lisp_Object
, Lisp_Object
));
475 static Lisp_Object font_prop_validate_non_neg
P_ ((Lisp_Object
, Lisp_Object
));
476 static Lisp_Object font_prop_validate_spacing
P_ ((Lisp_Object
, Lisp_Object
));
477 static int get_font_prop_index
P_ ((Lisp_Object
));
480 font_prop_validate_symbol (prop
, val
)
481 Lisp_Object prop
, val
;
484 val
= Fintern (val
, Qnil
);
487 else if (EQ (prop
, QCregistry
))
488 val
= Fintern (Fdowncase (SYMBOL_NAME (val
)), Qnil
);
494 font_prop_validate_style (style
, val
)
495 Lisp_Object style
, val
;
497 enum font_property_index prop
= (EQ (style
, QCweight
) ? FONT_WEIGHT_INDEX
498 : EQ (style
, QCslant
) ? FONT_SLANT_INDEX
505 >= ASIZE (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
)))
509 Lisp_Object elt
= AREF (AREF (font_style_table
, prop
- FONT_WEIGHT_INDEX
), (n
>> 4) & 0xF);
511 if ((n
& 0xF) + 1 >= ASIZE (elt
))
513 else if (XINT (AREF (elt
, 0)) != (n
>> 8))
517 else if (SYMBOLP (val
))
519 int n
= font_style_to_value (prop
, val
, 0);
521 val
= n
>= 0 ? make_number (n
) : Qerror
;
529 font_prop_validate_non_neg (prop
, val
)
530 Lisp_Object prop
, val
;
532 return (NATNUMP (val
) || (FLOATP (val
) && XFLOAT_DATA (val
) >= 0)
537 font_prop_validate_spacing (prop
, val
)
538 Lisp_Object prop
, val
;
540 if (NILP (val
) || (NATNUMP (val
) && XINT (val
) <= FONT_SPACING_CHARCELL
))
542 if (SYMBOLP (val
) && SBYTES (SYMBOL_NAME (val
)) == 1)
544 char spacing
= SDATA (SYMBOL_NAME (val
))[0];
546 if (spacing
== 'c' || spacing
== 'C')
547 return make_number (FONT_SPACING_CHARCELL
);
548 if (spacing
== 'm' || spacing
== 'M')
549 return make_number (FONT_SPACING_MONO
);
550 if (spacing
== 'p' || spacing
== 'P')
551 return make_number (FONT_SPACING_PROPORTIONAL
);
552 if (spacing
== 'd' || spacing
== 'D')
553 return make_number (FONT_SPACING_DUAL
);
559 font_prop_validate_otf (prop
, val
)
560 Lisp_Object prop
, val
;
562 Lisp_Object tail
, tmp
;
565 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
566 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
567 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
570 if (! SYMBOLP (XCAR (val
)))
575 if (! CONSP (tail
) || ! SYMBOLP (XCAR (val
)))
577 for (i
= 0; i
< 2; i
++)
584 for (tmp
= XCAR (tail
); CONSP (tmp
); tmp
= XCDR (tmp
))
585 if (! SYMBOLP (XCAR (tmp
)))
593 /* Structure of known font property keys and validater of the
597 /* Pointer to the key symbol. */
599 /* Function to validate PROP's value VAL, or NULL if any value is
600 ok. The value is VAL or its regularized value if VAL is valid,
601 and Qerror if not. */
602 Lisp_Object (*validater
) P_ ((Lisp_Object prop
, Lisp_Object val
));
603 } font_property_table
[] =
604 { { &QCtype
, font_prop_validate_symbol
},
605 { &QCfoundry
, font_prop_validate_symbol
},
606 { &QCfamily
, font_prop_validate_symbol
},
607 { &QCadstyle
, font_prop_validate_symbol
},
608 { &QCregistry
, font_prop_validate_symbol
},
609 { &QCweight
, font_prop_validate_style
},
610 { &QCslant
, font_prop_validate_style
},
611 { &QCwidth
, font_prop_validate_style
},
612 { &QCsize
, font_prop_validate_non_neg
},
613 { &QCdpi
, font_prop_validate_non_neg
},
614 { &QCspacing
, font_prop_validate_spacing
},
615 { &QCavgwidth
, font_prop_validate_non_neg
},
616 /* The order of the above entries must match with enum
617 font_property_index. */
618 { &QClang
, font_prop_validate_symbol
},
619 { &QCscript
, font_prop_validate_symbol
},
620 { &QCotf
, font_prop_validate_otf
}
623 /* Size (number of elements) of the above table. */
624 #define FONT_PROPERTY_TABLE_SIZE \
625 ((sizeof font_property_table) / (sizeof *font_property_table))
627 /* Return an index number of font property KEY or -1 if KEY is not an
628 already known property. */
631 get_font_prop_index (key
)
636 for (i
= 0; i
< FONT_PROPERTY_TABLE_SIZE
; i
++)
637 if (EQ (key
, *font_property_table
[i
].key
))
642 /* Validate the font property. The property key is specified by the
643 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
644 signal an error. The value is VAL or the regularized one. */
647 font_prop_validate (idx
, prop
, val
)
649 Lisp_Object prop
, val
;
651 Lisp_Object validated
;
656 prop
= *font_property_table
[idx
].key
;
659 idx
= get_font_prop_index (prop
);
663 validated
= (font_property_table
[idx
].validater
) (prop
, val
);
664 if (EQ (validated
, Qerror
))
665 signal_error ("invalid font property", Fcons (prop
, val
));
670 /* Store VAL as a value of extra font property PROP in FONT while
671 keeping the sorting order. Don't check the validity of VAL. */
674 font_put_extra (font
, prop
, val
)
675 Lisp_Object font
, prop
, val
;
677 Lisp_Object extra
= AREF (font
, FONT_EXTRA_INDEX
);
678 Lisp_Object slot
= (NILP (extra
) ? Qnil
: assq_no_quit (prop
, extra
));
682 Lisp_Object prev
= Qnil
;
685 && NILP (Fstring_lessp (prop
, XCAR (XCAR (extra
)))))
686 prev
= extra
, extra
= XCDR (extra
);
688 ASET (font
, FONT_EXTRA_INDEX
, Fcons (Fcons (prop
, val
), extra
));
690 XSETCDR (prev
, Fcons (Fcons (prop
, val
), extra
));
698 /* Font name parser and unparser */
700 static int parse_matrix
P_ ((char *));
701 static int font_expand_wildcards
P_ ((Lisp_Object
*, int));
702 static int font_parse_name
P_ ((char *, Lisp_Object
));
704 /* An enumerator for each field of an XLFD font name. */
705 enum xlfd_field_index
724 /* An enumerator for mask bit corresponding to each XLFD field. */
727 XLFD_FOUNDRY_MASK
= 0x0001,
728 XLFD_FAMILY_MASK
= 0x0002,
729 XLFD_WEIGHT_MASK
= 0x0004,
730 XLFD_SLANT_MASK
= 0x0008,
731 XLFD_SWIDTH_MASK
= 0x0010,
732 XLFD_ADSTYLE_MASK
= 0x0020,
733 XLFD_PIXEL_MASK
= 0x0040,
734 XLFD_POINT_MASK
= 0x0080,
735 XLFD_RESX_MASK
= 0x0100,
736 XLFD_RESY_MASK
= 0x0200,
737 XLFD_SPACING_MASK
= 0x0400,
738 XLFD_AVGWIDTH_MASK
= 0x0800,
739 XLFD_REGISTRY_MASK
= 0x1000,
740 XLFD_ENCODING_MASK
= 0x2000
744 /* Parse P pointing the pixel/point size field of the form
745 `[A B C D]' which specifies a transformation matrix:
751 by which all glyphs of the font are transformed. The spec says
752 that scalar value N for the pixel/point size is equivalent to:
753 A = N * resx/resy, B = C = 0, D = N.
755 Return the scalar value N if the form is valid. Otherwise return
766 for (i
= 0, p
++; i
< 4 && *p
&& *p
!= ']'; i
++)
769 matrix
[i
] = - strtod (p
+ 1, &end
);
771 matrix
[i
] = strtod (p
, &end
);
774 return (i
== 4 ? (int) matrix
[3] : -1);
777 /* Expand a wildcard field in FIELD (the first N fields are filled) to
778 multiple fields to fill in all 14 XLFD fields while restring a
779 field position by its contents. */
782 font_expand_wildcards (field
, n
)
783 Lisp_Object field
[XLFD_LAST_INDEX
];
787 Lisp_Object tmp
[XLFD_LAST_INDEX
];
788 /* Array of information about where this element can go. Nth
789 element is for Nth element of FIELD. */
791 /* Minimum possible field. */
793 /* Maxinum possible field. */
795 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
797 } range
[XLFD_LAST_INDEX
];
799 int range_from
, range_to
;
802 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
803 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
804 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
805 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
806 | XLFD_AVGWIDTH_MASK)
807 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
809 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
810 field. The value is shifted to left one bit by one in the
812 for (i
= 0, range_mask
= 0; i
<= 14 - n
; i
++)
813 range_mask
= (range_mask
<< 1) | 1;
815 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
816 position-based retriction for FIELD[I]. */
817 for (i
= 0, range_from
= 0, range_to
= 14 - n
; i
< n
;
818 i
++, range_from
++, range_to
++, range_mask
<<= 1)
820 Lisp_Object val
= field
[i
];
826 range
[i
].from
= range_from
;
827 range
[i
].to
= range_to
;
828 range
[i
].mask
= range_mask
;
832 /* The triplet FROM, TO, and MASK is a value-based
833 retriction for FIELD[I]. */
839 int numeric
= XINT (val
);
842 from
= to
= XLFD_ENCODING_INDEX
,
843 mask
= XLFD_ENCODING_MASK
;
844 else if (numeric
== 0)
845 from
= XLFD_PIXEL_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
846 mask
= XLFD_PIXEL_MASK
| XLFD_LARGENUM_MASK
;
847 else if (numeric
<= 48)
848 from
= to
= XLFD_PIXEL_INDEX
,
849 mask
= XLFD_PIXEL_MASK
;
851 from
= XLFD_POINT_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
852 mask
= XLFD_LARGENUM_MASK
;
854 else if (SBYTES (SYMBOL_NAME (val
)) == 0)
855 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ADSTYLE_INDEX
,
856 mask
= XLFD_NULL_MASK
;
858 from
= to
= XLFD_FOUNDRY_INDEX
, mask
= XLFD_FOUNDRY_MASK
;
861 Lisp_Object name
= SYMBOL_NAME (val
);
863 if (SDATA (name
)[SBYTES (name
) - 1] == '*')
864 from
= XLFD_REGISTRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
865 mask
= XLFD_REGENC_MASK
;
867 from
= to
= XLFD_ENCODING_INDEX
,
868 mask
= XLFD_ENCODING_MASK
;
870 else if (range_from
<= XLFD_WEIGHT_INDEX
871 && range_to
>= XLFD_WEIGHT_INDEX
872 && FONT_WEIGHT_NAME_NUMERIC (val
) >= 0)
873 from
= to
= XLFD_WEIGHT_INDEX
, mask
= XLFD_WEIGHT_MASK
;
874 else if (range_from
<= XLFD_SLANT_INDEX
875 && range_to
>= XLFD_SLANT_INDEX
876 && FONT_SLANT_NAME_NUMERIC (val
) >= 0)
877 from
= to
= XLFD_SLANT_INDEX
, mask
= XLFD_SLANT_MASK
;
878 else if (range_from
<= XLFD_SWIDTH_INDEX
879 && range_to
>= XLFD_SWIDTH_INDEX
880 && FONT_WIDTH_NAME_NUMERIC (val
) >= 0)
881 from
= to
= XLFD_SWIDTH_INDEX
, mask
= XLFD_SWIDTH_MASK
;
884 if (EQ (val
, Qc
) || EQ (val
, Qm
) || EQ (val
, Qp
) || EQ (val
, Qd
))
885 from
= to
= XLFD_SPACING_INDEX
, mask
= XLFD_SPACING_MASK
;
887 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
888 mask
= XLFD_SYMBOL_MASK
;
891 /* Merge position-based and value-based restrictions. */
893 while (from
< range_from
)
894 mask
&= ~(1 << from
++);
895 while (from
< 14 && ! (mask
& (1 << from
)))
897 while (to
> range_to
)
898 mask
&= ~(1 << to
--);
899 while (to
>= 0 && ! (mask
& (1 << to
)))
903 range
[i
].from
= from
;
905 range
[i
].mask
= mask
;
907 if (from
> range_from
|| to
< range_to
)
909 /* The range is narrowed by value-based restrictions.
910 Reflect it to the other fields. */
912 /* Following fields should be after FROM. */
914 /* Preceding fields should be before TO. */
915 for (j
= i
- 1, from
--, to
--; j
>= 0; j
--, from
--, to
--)
917 /* Check FROM for non-wildcard field. */
918 if (! NILP (tmp
[j
]) && range
[j
].from
< from
)
920 while (range
[j
].from
< from
)
921 range
[j
].mask
&= ~(1 << range
[j
].from
++);
922 while (from
< 14 && ! (range
[j
].mask
& (1 << from
)))
924 range
[j
].from
= from
;
927 from
= range
[j
].from
;
928 if (range
[j
].to
> to
)
930 while (range
[j
].to
> to
)
931 range
[j
].mask
&= ~(1 << range
[j
].to
--);
932 while (to
>= 0 && ! (range
[j
].mask
& (1 << to
)))
945 /* Decide all fileds from restrictions in RANGE. */
946 for (i
= j
= 0; i
< n
; i
++)
948 if (j
< range
[i
].from
)
950 if (i
== 0 || ! NILP (tmp
[i
- 1]))
951 /* None of TMP[X] corresponds to Jth field. */
953 for (; j
< range
[i
].from
; j
++)
958 if (! NILP (tmp
[n
- 1]) && j
< XLFD_REGISTRY_INDEX
)
960 for (; j
< XLFD_LAST_INDEX
; j
++)
962 if (INTEGERP (field
[XLFD_ENCODING_INDEX
]))
963 field
[XLFD_ENCODING_INDEX
]
964 = Fintern (Fnumber_to_string (field
[XLFD_ENCODING_INDEX
]), Qnil
);
969 #ifdef ENABLE_CHECKING
970 /* Match a 14-field XLFD pattern against a full XLFD font name. */
972 font_match_xlfd (char *pattern
, char *name
)
974 while (*pattern
&& *name
)
976 if (*pattern
== *name
)
978 else if (*pattern
== '*')
979 if (*name
== pattern
[1])
990 /* Make sure the font object matches the XLFD font name. */
992 font_check_xlfd_parse (Lisp_Object font
, char *name
)
994 char name_check
[256];
995 font_unparse_xlfd (font
, 0, name_check
, 255);
996 return font_match_xlfd (name_check
, name
);
1002 /* Parse NAME (null terminated) as XLFD and store information in FONT
1003 (font-spec or font-entity). Size property of FONT is set as
1005 specified XLFD fields FONT property
1006 --------------------- -------------
1007 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
1008 POINT_SIZE and RESY calculated pixel size (Lisp integer)
1009 POINT_SIZE POINT_SIZE/10 (Lisp float)
1011 If NAME is successfully parsed, return 0. Otherwise return -1.
1013 FONT is usually a font-spec, but when this function is called from
1014 X font backend driver, it is a font-entity. In that case, NAME is
1015 a fully specified XLFD. */
1018 font_parse_xlfd (name
, font
)
1022 int len
= strlen (name
);
1024 char *f
[XLFD_LAST_INDEX
+ 1];
1029 /* Maximum XLFD name length is 255. */
1031 /* Accept "*-.." as a fully specified XLFD. */
1032 if (name
[0] == '*' && name
[1] == '-')
1033 i
= 1, f
[XLFD_FOUNDRY_INDEX
] = name
;
1036 for (p
= name
+ i
; *p
; p
++)
1040 if (i
== XLFD_LAST_INDEX
)
1045 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 0)
1046 #define INTERN_FIELD_SYM(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N], 1)
1048 if (i
== XLFD_LAST_INDEX
)
1050 /* Fully specified XLFD. */
1053 ASET (font
, FONT_FOUNDRY_INDEX
, INTERN_FIELD_SYM (XLFD_FOUNDRY_INDEX
));
1054 ASET (font
, FONT_FAMILY_INDEX
, INTERN_FIELD_SYM (XLFD_FAMILY_INDEX
));
1055 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1056 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1058 val
= INTERN_FIELD_SYM (i
);
1061 if ((n
= font_style_to_value (j
, INTERN_FIELD_SYM (i
), 0)) < 0)
1063 ASET (font
, j
, make_number (n
));
1066 ASET (font
, FONT_ADSTYLE_INDEX
, INTERN_FIELD_SYM (XLFD_ADSTYLE_INDEX
));
1067 if (strcmp (f
[XLFD_REGISTRY_INDEX
], "*-*") == 0)
1068 ASET (font
, FONT_REGISTRY_INDEX
, Qnil
);
1070 ASET (font
, FONT_REGISTRY_INDEX
,
1071 font_intern_prop (f
[XLFD_REGISTRY_INDEX
],
1072 f
[XLFD_LAST_INDEX
] - f
[XLFD_REGISTRY_INDEX
],
1074 p
= f
[XLFD_PIXEL_INDEX
];
1075 if (*p
== '[' && (pixel_size
= parse_matrix (p
)) >= 0)
1076 ASET (font
, FONT_SIZE_INDEX
, make_number (pixel_size
));
1079 val
= INTERN_FIELD (XLFD_PIXEL_INDEX
);
1081 ASET (font
, FONT_SIZE_INDEX
, val
);
1084 double point_size
= -1;
1086 font_assert (FONT_SPEC_P (font
));
1087 p
= f
[XLFD_POINT_INDEX
];
1089 point_size
= parse_matrix (p
);
1090 else if (isdigit (*p
))
1091 point_size
= atoi (p
), point_size
/= 10;
1092 if (point_size
>= 0)
1093 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1097 ASET (font
, FONT_DPI_INDEX
, INTERN_FIELD (XLFD_RESY_INDEX
));
1098 val
= INTERN_FIELD (XLFD_SPACING_INDEX
);
1101 val
= font_prop_validate_spacing (QCspacing
, val
);
1102 if (! INTEGERP (val
))
1104 ASET (font
, FONT_SPACING_INDEX
, val
);
1106 p
= f
[XLFD_AVGWIDTH_INDEX
];
1109 ASET (font
, FONT_AVGWIDTH_INDEX
,
1110 font_intern_prop (p
, f
[XLFD_REGISTRY_INDEX
] - 1 - p
, 1));
1114 int wild_card_found
= 0;
1115 Lisp_Object prop
[XLFD_LAST_INDEX
];
1117 if (FONT_ENTITY_P (font
))
1119 for (j
= 0; j
< i
; j
++)
1123 if (f
[j
][1] && f
[j
][1] != '-')
1126 wild_card_found
= 1;
1129 prop
[j
] = INTERN_FIELD (j
);
1131 prop
[j
] = font_intern_prop (f
[j
], f
[i
] - f
[j
], 0);
1133 if (! wild_card_found
)
1135 if (font_expand_wildcards (prop
, i
) < 0)
1138 ASET (font
, FONT_FOUNDRY_INDEX
, prop
[XLFD_FOUNDRY_INDEX
]);
1139 ASET (font
, FONT_FAMILY_INDEX
, prop
[XLFD_FAMILY_INDEX
]);
1140 for (i
= XLFD_WEIGHT_INDEX
, j
= FONT_WEIGHT_INDEX
;
1141 i
<= XLFD_SWIDTH_INDEX
; i
++, j
++)
1142 if (! NILP (prop
[i
]))
1144 if ((n
= font_style_to_value (j
, prop
[i
], 1)) < 0)
1146 ASET (font
, j
, make_number (n
));
1148 ASET (font
, FONT_ADSTYLE_INDEX
, prop
[XLFD_ADSTYLE_INDEX
]);
1149 val
= prop
[XLFD_REGISTRY_INDEX
];
1152 val
= prop
[XLFD_ENCODING_INDEX
];
1154 val
= concat2 (build_string ("*-"), SYMBOL_NAME (val
));
1156 else if (NILP (prop
[XLFD_ENCODING_INDEX
]))
1157 val
= concat2 (SYMBOL_NAME (val
), build_string ("-*"));
1159 val
= concat3 (SYMBOL_NAME (val
), build_string ("-"),
1160 SYMBOL_NAME (prop
[XLFD_ENCODING_INDEX
]));
1162 ASET (font
, FONT_REGISTRY_INDEX
, Fintern (val
, Qnil
));
1164 if (INTEGERP (prop
[XLFD_PIXEL_INDEX
]))
1165 ASET (font
, FONT_SIZE_INDEX
, prop
[XLFD_PIXEL_INDEX
]);
1166 else if (INTEGERP (prop
[XLFD_POINT_INDEX
]))
1168 double point_size
= XINT (prop
[XLFD_POINT_INDEX
]);
1170 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
/ 10));
1173 if (INTEGERP (prop
[XLFD_RESX_INDEX
]))
1174 ASET (font
, FONT_DPI_INDEX
, prop
[XLFD_RESY_INDEX
]);
1175 if (! NILP (prop
[XLFD_SPACING_INDEX
]))
1177 val
= font_prop_validate_spacing (QCspacing
,
1178 prop
[XLFD_SPACING_INDEX
]);
1179 if (! INTEGERP (val
))
1181 ASET (font
, FONT_SPACING_INDEX
, val
);
1183 if (INTEGERP (prop
[XLFD_AVGWIDTH_INDEX
]))
1184 ASET (font
, FONT_AVGWIDTH_INDEX
, prop
[XLFD_AVGWIDTH_INDEX
]);
1190 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1191 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1192 0, use PIXEL_SIZE instead. */
1195 font_unparse_xlfd (font
, pixel_size
, name
, nbytes
)
1201 char *f
[XLFD_REGISTRY_INDEX
+ 1];
1205 font_assert (FONTP (font
));
1207 for (i
= FONT_FOUNDRY_INDEX
, j
= XLFD_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
;
1210 if (i
== FONT_ADSTYLE_INDEX
)
1211 j
= XLFD_ADSTYLE_INDEX
;
1212 else if (i
== FONT_REGISTRY_INDEX
)
1213 j
= XLFD_REGISTRY_INDEX
;
1214 val
= AREF (font
, i
);
1217 if (j
== XLFD_REGISTRY_INDEX
)
1218 f
[j
] = "*-*", len
+= 4;
1220 f
[j
] = "*", len
+= 2;
1225 val
= SYMBOL_NAME (val
);
1226 if (j
== XLFD_REGISTRY_INDEX
1227 && ! strchr ((char *) SDATA (val
), '-'))
1229 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1230 if (SDATA (val
)[SBYTES (val
) - 1] == '*')
1232 f
[j
] = alloca (SBYTES (val
) + 3);
1233 sprintf (f
[j
], "%s-*", SDATA (val
));
1234 len
+= SBYTES (val
) + 3;
1238 f
[j
] = alloca (SBYTES (val
) + 4);
1239 sprintf (f
[j
], "%s*-*", SDATA (val
));
1240 len
+= SBYTES (val
) + 4;
1244 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1248 for (i
= FONT_WEIGHT_INDEX
, j
= XLFD_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
;
1251 val
= font_style_symbolic (font
, i
, 0);
1253 f
[j
] = "*", len
+= 2;
1256 val
= SYMBOL_NAME (val
);
1257 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1261 val
= AREF (font
, FONT_SIZE_INDEX
);
1262 font_assert (NUMBERP (val
) || NILP (val
));
1270 f
[XLFD_PIXEL_INDEX
] = alloca (22);
1271 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "%d-*", i
) + 1;
1274 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1276 else if (FLOATP (val
))
1278 i
= XFLOAT_DATA (val
) * 10;
1279 f
[XLFD_PIXEL_INDEX
] = alloca (12);
1280 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "*-%d", i
) + 1;
1283 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1285 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1287 i
= XINT (AREF (font
, FONT_DPI_INDEX
));
1288 f
[XLFD_RESX_INDEX
] = alloca (22);
1289 len
+= sprintf (f
[XLFD_RESX_INDEX
],
1293 f
[XLFD_RESX_INDEX
] = "*-*", len
+= 4;
1294 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1296 int spacing
= XINT (AREF (font
, FONT_SPACING_INDEX
));
1298 f
[XLFD_SPACING_INDEX
] = (spacing
<= FONT_SPACING_PROPORTIONAL
? "p"
1299 : spacing
<= FONT_SPACING_DUAL
? "d"
1300 : spacing
<= FONT_SPACING_MONO
? "m"
1305 f
[XLFD_SPACING_INDEX
] = "*", len
+= 2;
1306 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1308 f
[XLFD_AVGWIDTH_INDEX
] = alloca (11);
1309 len
+= sprintf (f
[XLFD_AVGWIDTH_INDEX
],
1310 "%d", XINT (AREF (font
, FONT_AVGWIDTH_INDEX
))) + 1;
1313 f
[XLFD_AVGWIDTH_INDEX
] = "*", len
+= 2;
1314 len
++; /* for terminating '\0'. */
1317 return sprintf (name
, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1318 f
[XLFD_FOUNDRY_INDEX
], f
[XLFD_FAMILY_INDEX
],
1319 f
[XLFD_WEIGHT_INDEX
], f
[XLFD_SLANT_INDEX
],
1320 f
[XLFD_SWIDTH_INDEX
], f
[XLFD_ADSTYLE_INDEX
],
1321 f
[XLFD_PIXEL_INDEX
], f
[XLFD_RESX_INDEX
],
1322 f
[XLFD_SPACING_INDEX
], f
[XLFD_AVGWIDTH_INDEX
],
1323 f
[XLFD_REGISTRY_INDEX
]);
1326 /* Parse NAME (null terminated) as Fonconfig's name format and store
1327 information in FONT (font-spec or font-entity). If NAME is
1328 successfully parsed, return 0. Otherwise return -1. */
1331 font_parse_fcname (name
, font
)
1336 int len
= strlen (name
);
1341 /* It is assured that (name[0] && name[0] != '-'). */
1349 for (p0
= name
+ 1; *p0
&& (*p0
!= '-' && *p0
!= ':'); p0
++)
1350 if (*p0
== '\\' && p0
[1])
1352 family
= font_intern_prop (name
, p0
- name
, 1);
1355 if (! isdigit (p0
[1]))
1357 point_size
= strtod (p0
+ 1, &p1
);
1358 if (*p1
&& *p1
!= ':')
1360 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1363 ASET (font
, FONT_FAMILY_INDEX
, family
);
1367 copy
= alloca (len
+ 1);
1372 /* Now parse ":KEY=VAL" patterns. Store known keys and values in
1373 extra, copy unknown ones to COPY. It is stored in extra slot by
1374 the key QCfc_unknown_spec. */
1377 Lisp_Object key
, val
;
1380 for (p1
= p0
+ 1; *p1
&& *p1
!= '=' && *p1
!= ':'; p1
++);
1383 /* Must be an enumerated value. */
1384 val
= font_intern_prop (p0
+ 1, p1
- p0
- 1, 1);
1385 if (memcmp (p0
+ 1, "light", 5) == 0
1386 || memcmp (p0
+ 1, "medium", 6) == 0
1387 || memcmp (p0
+ 1, "demibold", 8) == 0
1388 || memcmp (p0
+ 1, "bold", 4) == 0
1389 || memcmp (p0
+ 1, "black", 5) == 0)
1390 FONT_SET_STYLE (font
, FONT_WEIGHT_INDEX
, val
);
1391 else if (memcmp (p0
+ 1, "roman", 5) == 0
1392 || memcmp (p0
+ 1, "italic", 6) == 0
1393 || memcmp (p0
+ 1, "oblique", 7) == 0)
1394 FONT_SET_STYLE (font
, FONT_SLANT_INDEX
, val
);
1395 else if (memcmp (p0
+ 1, "charcell", 8) == 0
1396 || memcmp (p0
+ 1, "mono", 4) == 0
1397 || memcmp (p0
+ 1, "proportional", 12) == 0)
1399 int spacing
= (p0
[1] == 'c' ? FONT_SPACING_CHARCELL
1400 : p0
[1] == 'm' ? FONT_SPACING_MONO
1401 : FONT_SPACING_PROPORTIONAL
);
1402 ASET (font
, FONT_SPACING_INDEX
, make_number (spacing
));
1407 bcopy (p0
, copy
, p1
- p0
);
1415 if (memcmp (p0
+ 1, "pixelsize=", 10) == 0)
1416 prop
= FONT_SIZE_INDEX
;
1419 key
= font_intern_prop (p0
, p1
- p0
, 1);
1420 prop
= get_font_prop_index (key
);
1423 for (p1
= p0
; *p1
&& *p1
!= ':'; p1
++);
1424 val
= font_intern_prop (p0
, p1
- p0
, 0);
1427 if (prop
>= FONT_FOUNDRY_INDEX
&& prop
< FONT_EXTRA_INDEX
)
1428 ASET (font
, prop
, font_prop_validate (prop
, Qnil
, val
));
1430 Ffont_put (font
, key
, val
);
1432 bcopy (keyhead
, copy
, p1
- keyhead
);
1433 copy
+= p1
- keyhead
;
1439 font_put_extra (font
, QCfc_unknown_spec
,
1440 make_unibyte_string (name
, copy
- name
));
1445 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1446 NAME (NBYTES length), and return the name length. If
1447 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1450 font_unparse_fcname (font
, pixel_size
, name
, nbytes
)
1456 Lisp_Object tail
, val
;
1461 Lisp_Object styles
[3];
1462 char *style_names
[3] = { "weight", "slant", "width" };
1465 val
= AREF (font
, FONT_FAMILY_INDEX
);
1467 len
+= SBYTES (val
);
1469 val
= AREF (font
, FONT_SIZE_INDEX
);
1472 if (XINT (val
) != 0)
1473 pixel_size
= XINT (val
);
1475 len
+= 21; /* for ":pixelsize=NUM" */
1477 else if (FLOATP (val
))
1480 point_size
= (int) XFLOAT_DATA (val
);
1481 len
+= 11; /* for "-NUM" */
1484 val
= AREF (font
, FONT_FOUNDRY_INDEX
);
1486 /* ":foundry=NAME" */
1487 len
+= 9 + SBYTES (val
);
1489 for (i
= 0; i
< 3; i
++)
1491 styles
[i
] = font_style_symbolic (font
, FONT_WEIGHT_INDEX
+ i
, 0);
1492 if (! NILP (styles
[i
]))
1493 len
+= sprintf (work
, ":%s=%s", style_names
[i
],
1494 SDATA (SYMBOL_NAME (styles
[i
])));
1497 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1498 len
+= sprintf (work
, ":dpi=%d", dpi
);
1499 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1500 len
+= strlen (":spacing=100");
1501 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1502 len
+= strlen (":scalable=false"); /* or ":scalable=true" */
1503 for (tail
= AREF (font
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
1505 Lisp_Object key
= XCAR (XCAR (tail
)), val
= XCDR (XCAR (tail
));
1507 len
+= SBYTES (SYMBOL_NAME (key
)) + 1; /* for :KEY= */
1509 len
+= SBYTES (val
);
1510 else if (INTEGERP (val
))
1511 len
+= sprintf (work
, "%d", XINT (val
));
1512 else if (SYMBOLP (val
))
1513 len
+= (NILP (val
) ? 5 : 4); /* for "false" or "true" */
1519 if (! NILP (AREF (font
, FONT_FAMILY_INDEX
)))
1520 p
+= sprintf(p
, "%s", SDATA (SYMBOL_NAME (AREF (font
, FONT_FAMILY_INDEX
))));
1524 p
+= sprintf (p
, "%d", point_size
);
1526 p
+= sprintf (p
, "-%d", point_size
);
1528 else if (pixel_size
> 0)
1529 p
+= sprintf (p
, ":pixelsize=%d", pixel_size
);
1530 if (! NILP (AREF (font
, FONT_FOUNDRY_INDEX
)))
1531 p
+= sprintf (p
, ":foundry=%s",
1532 SDATA (SYMBOL_NAME (AREF (font
, FONT_FOUNDRY_INDEX
))));
1533 for (i
= 0; i
< 3; i
++)
1534 if (! NILP (styles
[i
]))
1535 p
+= sprintf (p
, ":%s=%s", style_names
[i
],
1536 SDATA (SYMBOL_NAME (styles
[i
])));
1537 if (INTEGERP (AREF (font
, FONT_DPI_INDEX
)))
1538 p
+= sprintf (p
, ":dpi=%d", XINT (AREF (font
, FONT_DPI_INDEX
)));
1539 if (INTEGERP (AREF (font
, FONT_SPACING_INDEX
)))
1540 p
+= sprintf (p
, ":spacing=%d", XINT (AREF (font
, FONT_SPACING_INDEX
)));
1541 if (INTEGERP (AREF (font
, FONT_AVGWIDTH_INDEX
)))
1543 if (XINT (AREF (font
, FONT_AVGWIDTH_INDEX
)) == 0)
1544 p
+= sprintf (p
, ":scalable=true");
1546 p
+= sprintf (p
, ":scalable=false");
1551 /* Parse NAME (null terminated) and store information in FONT
1552 (font-spec or font-entity). If NAME is successfully parsed, return
1553 0. Otherwise return -1. */
1556 font_parse_name (name
, font
)
1560 if (name
[0] == '-' || index (name
, '*'))
1561 return font_parse_xlfd (name
, font
);
1562 return font_parse_fcname (name
, font
);
1566 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1567 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1571 font_parse_family_registry (family
, registry
, font_spec
)
1572 Lisp_Object family
, registry
, font_spec
;
1578 && NILP (AREF (font_spec
, FONT_FAMILY_INDEX
)))
1580 CHECK_STRING (family
);
1581 len
= SBYTES (family
);
1582 p0
= (char *) SDATA (family
);
1583 p1
= index (p0
, '-');
1586 if ((*p0
!= '*' || p1
- p0
> 1)
1587 && NILP (AREF (font_spec
, FONT_FOUNDRY_INDEX
)))
1588 Ffont_put (font_spec
, QCfoundry
, font_intern_prop (p0
, p1
- p0
, 1));
1591 Ffont_put (font_spec
, QCfamily
, font_intern_prop (p1
, len
, 1));
1594 ASET (font_spec
, FONT_FAMILY_INDEX
, Fintern (family
, Qnil
));
1596 if (! NILP (registry
))
1598 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1599 CHECK_STRING (registry
);
1600 len
= SBYTES (registry
);
1601 p0
= (char *) SDATA (registry
);
1602 p1
= index (p0
, '-');
1605 if (SDATA (registry
)[len
- 1] == '*')
1606 registry
= concat2 (registry
, build_string ("-*"));
1608 registry
= concat2 (registry
, build_string ("*-*"));
1610 registry
= Fdowncase (registry
);
1611 ASET (font_spec
, FONT_REGISTRY_INDEX
, Fintern (registry
, Qnil
));
1616 /* This part (through the next ^L) is still experimental and not
1617 tested much. We may drastically change codes. */
1623 #define LGSTRING_HEADER_SIZE 6
1624 #define LGSTRING_GLYPH_SIZE 8
1627 check_gstring (gstring
)
1628 Lisp_Object gstring
;
1633 CHECK_VECTOR (gstring
);
1634 val
= AREF (gstring
, 0);
1636 if (ASIZE (val
) < LGSTRING_HEADER_SIZE
)
1638 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring
));
1639 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
)))
1640 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
));
1641 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
)))
1642 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
));
1643 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
)))
1644 CHECK_NATNUM (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
));
1645 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1646 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1647 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1648 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1650 for (i
= 0; i
< LGSTRING_LENGTH (gstring
); i
++)
1652 val
= LGSTRING_GLYPH (gstring
, i
);
1654 if (ASIZE (val
) < LGSTRING_GLYPH_SIZE
)
1656 if (NILP (AREF (val
, LGLYPH_IX_CHAR
)))
1658 CHECK_NATNUM (AREF (val
, LGLYPH_IX_FROM
));
1659 CHECK_NATNUM (AREF (val
, LGLYPH_IX_TO
));
1660 CHECK_CHARACTER (AREF (val
, LGLYPH_IX_CHAR
));
1661 if (!NILP (AREF (val
, LGLYPH_IX_CODE
)))
1662 CHECK_NATNUM (AREF (val
, LGLYPH_IX_CODE
));
1663 if (!NILP (AREF (val
, LGLYPH_IX_WIDTH
)))
1664 CHECK_NATNUM (AREF (val
, LGLYPH_IX_WIDTH
));
1665 if (!NILP (AREF (val
, LGLYPH_IX_ADJUSTMENT
)))
1667 val
= AREF (val
, LGLYPH_IX_ADJUSTMENT
);
1669 if (ASIZE (val
) < 3)
1671 for (j
= 0; j
< 3; j
++)
1672 CHECK_NUMBER (AREF (val
, j
));
1677 error ("Invalid glyph-string format");
1682 check_otf_features (otf_features
)
1683 Lisp_Object otf_features
;
1687 CHECK_CONS (otf_features
);
1688 CHECK_SYMBOL (XCAR (otf_features
));
1689 otf_features
= XCDR (otf_features
);
1690 CHECK_CONS (otf_features
);
1691 CHECK_SYMBOL (XCAR (otf_features
));
1692 otf_features
= XCDR (otf_features
);
1693 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1695 CHECK_SYMBOL (Fcar (val
));
1696 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1697 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val
)));
1699 otf_features
= XCDR (otf_features
);
1700 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1702 CHECK_SYMBOL (Fcar (val
));
1703 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1704 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val
)));
1711 Lisp_Object otf_list
;
1714 otf_tag_symbol (tag
)
1719 OTF_tag_name (tag
, name
);
1720 return Fintern (make_unibyte_string (name
, 4), Qnil
);
1727 Lisp_Object val
= Fassoc (file
, otf_list
);
1731 otf
= XSAVE_VALUE (XCDR (val
))->pointer
;
1734 otf
= STRINGP (file
) ? OTF_open ((char *) SDATA (file
)) : NULL
;
1735 val
= make_save_value (otf
, 0);
1736 otf_list
= Fcons (Fcons (file
, val
), otf_list
);
1742 /* Return a list describing which scripts/languages FONT supports by
1743 which GSUB/GPOS features of OpenType tables. See the comment of
1744 (struct font_driver).otf_capability. */
1747 font_otf_capability (font
)
1751 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
1754 otf
= otf_open (font
->props
[FONT_FILE_INDEX
]);
1757 for (i
= 0; i
< 2; i
++)
1759 OTF_GSUB_GPOS
*gsub_gpos
;
1760 Lisp_Object script_list
= Qnil
;
1763 if (OTF_get_features (otf
, i
== 0) < 0)
1765 gsub_gpos
= i
== 0 ? otf
->gsub
: otf
->gpos
;
1766 for (j
= gsub_gpos
->ScriptList
.ScriptCount
- 1; j
>= 0; j
--)
1768 OTF_Script
*script
= gsub_gpos
->ScriptList
.Script
+ j
;
1769 Lisp_Object langsys_list
= Qnil
;
1770 Lisp_Object script_tag
= otf_tag_symbol (script
->ScriptTag
);
1773 for (k
= script
->LangSysCount
; k
>= 0; k
--)
1775 OTF_LangSys
*langsys
;
1776 Lisp_Object feature_list
= Qnil
;
1777 Lisp_Object langsys_tag
;
1780 if (k
== script
->LangSysCount
)
1782 langsys
= &script
->DefaultLangSys
;
1787 langsys
= script
->LangSys
+ k
;
1789 = otf_tag_symbol (script
->LangSysRecord
[k
].LangSysTag
);
1791 for (l
= langsys
->FeatureCount
- 1; l
>= 0; l
--)
1793 OTF_Feature
*feature
1794 = gsub_gpos
->FeatureList
.Feature
+ langsys
->FeatureIndex
[l
];
1795 Lisp_Object feature_tag
1796 = otf_tag_symbol (feature
->FeatureTag
);
1798 feature_list
= Fcons (feature_tag
, feature_list
);
1800 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
1803 script_list
= Fcons (Fcons (script_tag
, langsys_list
),
1808 XSETCAR (capability
, script_list
);
1810 XSETCDR (capability
, script_list
);
1816 /* Parse OTF features in SPEC and write a proper features spec string
1817 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1818 assured that the sufficient memory has already allocated for
1822 generate_otf_features (spec
, features
)
1832 for (asterisk
= 0; CONSP (spec
); spec
= XCDR (spec
))
1838 if (SREF (SYMBOL_NAME (val
), 0) == '*')
1843 else if (! asterisk
)
1845 val
= SYMBOL_NAME (val
);
1846 p
+= sprintf (p
, "%s", SDATA (val
));
1850 val
= SYMBOL_NAME (val
);
1851 p
+= sprintf (p
, "~%s", SDATA (val
));
1855 error ("OTF spec too long");
1859 font_otf_DeviceTable (device_table
)
1860 OTF_DeviceTable
*device_table
;
1862 int len
= device_table
->StartSize
- device_table
->EndSize
+ 1;
1864 return Fcons (make_number (len
),
1865 make_unibyte_string (device_table
->DeltaValue
, len
));
1869 font_otf_ValueRecord (value_format
, value_record
)
1871 OTF_ValueRecord
*value_record
;
1873 Lisp_Object val
= Fmake_vector (make_number (8), Qnil
);
1875 if (value_format
& OTF_XPlacement
)
1876 ASET (val
, 0, make_number (value_record
->XPlacement
));
1877 if (value_format
& OTF_YPlacement
)
1878 ASET (val
, 1, make_number (value_record
->YPlacement
));
1879 if (value_format
& OTF_XAdvance
)
1880 ASET (val
, 2, make_number (value_record
->XAdvance
));
1881 if (value_format
& OTF_YAdvance
)
1882 ASET (val
, 3, make_number (value_record
->YAdvance
));
1883 if (value_format
& OTF_XPlaDevice
)
1884 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XPlaDevice
));
1885 if (value_format
& OTF_YPlaDevice
)
1886 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YPlaDevice
));
1887 if (value_format
& OTF_XAdvDevice
)
1888 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XAdvDevice
));
1889 if (value_format
& OTF_YAdvDevice
)
1890 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YAdvDevice
));
1895 font_otf_Anchor (anchor
)
1900 val
= Fmake_vector (make_number (anchor
->AnchorFormat
+ 1), Qnil
);
1901 ASET (val
, 0, make_number (anchor
->XCoordinate
));
1902 ASET (val
, 1, make_number (anchor
->YCoordinate
));
1903 if (anchor
->AnchorFormat
== 2)
1904 ASET (val
, 2, make_number (anchor
->f
.f1
.AnchorPoint
));
1907 ASET (val
, 3, font_otf_DeviceTable (&anchor
->f
.f2
.XDeviceTable
));
1908 ASET (val
, 4, font_otf_DeviceTable (&anchor
->f
.f2
.YDeviceTable
));
1912 #endif /* HAVE_LIBOTF */
1915 /* G-string (glyph string) handler */
1917 /* G-string is a vector of the form [HEADER GLYPH ...].
1918 See the docstring of `font-make-gstring' for more detail. */
1921 font_prepare_composition (cmp
, f
)
1922 struct composition
*cmp
;
1926 = AREF (XHASH_TABLE (composition_hash_table
)->key_and_value
,
1927 cmp
->hash_index
* 2);
1929 cmp
->font
= XFONT_OBJECT (LGSTRING_FONT (gstring
));
1930 cmp
->glyph_len
= LGSTRING_LENGTH (gstring
);
1931 cmp
->pixel_width
= LGSTRING_WIDTH (gstring
);
1932 cmp
->lbearing
= LGSTRING_LBEARING (gstring
);
1933 cmp
->rbearing
= LGSTRING_RBEARING (gstring
);
1934 cmp
->ascent
= LGSTRING_ASCENT (gstring
);
1935 cmp
->descent
= LGSTRING_DESCENT (gstring
);
1936 cmp
->width
= cmp
->pixel_width
/ FRAME_COLUMN_WIDTH (f
);
1937 if (cmp
->width
== 0)
1946 static unsigned font_score
P_ ((Lisp_Object
, Lisp_Object
*, Lisp_Object
));
1947 static int font_compare
P_ ((const void *, const void *));
1948 static Lisp_Object font_sort_entites
P_ ((Lisp_Object
, Lisp_Object
,
1949 Lisp_Object
, Lisp_Object
,
1952 /* We sort fonts by scoring each of them against a specified
1953 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1954 the value is, the closer the font is to the font-spec.
1956 The highest 2 bits of the score is used for FAMILY. The exact
1957 match is 0, match with one of face-font-family-alternatives is
1960 The next 2 bits of the score is used for the atomic properties
1961 FOUNDRY and ADSTYLE respectively.
1963 Each 7-bit in the lower 28 bits are used for numeric properties
1964 WEIGHT, SLANT, WIDTH, and SIZE. */
1966 /* How many bits to shift to store the difference value of each font
1967 property in a score. Note that flots for FONT_TYPE_INDEX and
1968 FONT_REGISTRY_INDEX are not used. */
1969 static int sort_shift_bits
[FONT_SIZE_INDEX
+ 1];
1971 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1972 The return value indicates how different ENTITY is compared with
1975 ALTERNATE_FAMILIES, if non-nil, is a pre-calculated list of
1976 alternate family names for AREF (SPEC_PROP, FONT_FAMILY_INDEX). */
1979 font_score (entity
, spec_prop
, alternate_families
)
1980 Lisp_Object entity
, *spec_prop
;
1981 Lisp_Object alternate_families
;
1986 /* Score three atomic fields. Maximum difference is 1 (family is 3). */
1987 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_ADSTYLE_INDEX
; i
++)
1988 if (i
!= FONT_REGISTRY_INDEX
1989 && ! NILP (spec_prop
[i
]) && ! EQ (AREF (entity
, i
), spec_prop
[i
]))
1991 Lisp_Object entity_str
= SYMBOL_NAME (AREF (entity
, i
));
1992 Lisp_Object spec_str
= SYMBOL_NAME (spec_prop
[i
]);
1994 if (xstrcasecmp (SDATA (spec_str
), SDATA (entity_str
)))
1996 if (i
== FONT_FAMILY_INDEX
&& CONSP (alternate_families
))
2000 for (j
= 1; CONSP (alternate_families
);
2001 j
++, alternate_families
= XCDR (alternate_families
))
2003 spec_str
= XCAR (alternate_families
);
2004 if (xstrcasecmp (SDATA (spec_str
), SDATA (entity_str
)) == 0)
2009 score
|= j
<< sort_shift_bits
[i
];
2012 score
|= 1 << sort_shift_bits
[i
];
2016 /* Score three style numeric fields. Maximum difference is 127. */
2017 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
; i
++)
2018 if (! NILP (spec_prop
[i
]) && ! EQ (AREF (entity
, i
), spec_prop
[i
]))
2020 int diff
= (XINT (AREF (entity
, i
)) >> 8) - (XINT (spec_prop
[i
]) >> 8);
2024 /* This is to prefer the exact symbol style. */
2026 score
|= min (diff
, 127) << sort_shift_bits
[i
];
2029 /* Score the size. Maximum difference is 127. */
2030 i
= FONT_SIZE_INDEX
;
2031 if (! NILP (spec_prop
[i
]) && ! EQ (AREF (entity
, i
), spec_prop
[i
])
2032 && XINT (AREF (entity
, i
)) > 0)
2034 /* We use the higher 6-bit for the actual size difference. The
2035 lowest bit is set if the DPI is different. */
2036 int diff
= XINT (spec_prop
[i
]) - XINT (AREF (entity
, i
));
2041 if (! NILP (spec_prop
[FONT_DPI_INDEX
])
2042 && ! EQ (spec_prop
[FONT_DPI_INDEX
], AREF (entity
, FONT_DPI_INDEX
)))
2044 score
|= min (diff
, 127) << sort_shift_bits
[FONT_SIZE_INDEX
];
2051 /* The comparison function for qsort. */
2054 font_compare (d1
, d2
)
2055 const void *d1
, *d2
;
2057 return (*(unsigned *) d1
- *(unsigned *) d2
);
2061 /* The structure for elements being sorted by qsort. */
2062 struct font_sort_data
2069 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2070 If PREFER specifies a point-size, calculate the corresponding
2071 pixel-size from QCdpi property of PREFER or from the Y-resolution
2072 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
2073 get the font-entities in VEC.
2075 If BEST-ONLY is nonzero, return the best matching entity. Otherwise,
2076 return the sorted VEC. */
2079 font_sort_entites (vec
, prefer
, frame
, spec
, best_only
)
2080 Lisp_Object vec
, prefer
, frame
, spec
;
2083 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2085 struct font_sort_data
*data
;
2086 Lisp_Object alternate_families
= Qnil
;
2087 unsigned best_score
;
2088 Lisp_Object best_entity
;
2093 return best_only
? AREF (vec
, 0) : vec
;
2095 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_DPI_INDEX
; i
++)
2096 prefer_prop
[i
] = AREF (prefer
, i
);
2100 /* A font driver may return a font that has a property value
2101 different from the value specified in SPEC if the driver
2102 thinks they are the same. That happens, for instance, such a
2103 generic family name as "serif" is specified. So, to ignore
2104 such a difference, for all properties specified in SPEC, set
2105 the corresponding properties in PREFER_PROP to nil. */
2106 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
2107 if (! NILP (AREF (spec
, i
)))
2108 prefer_prop
[i
] = Qnil
;
2111 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2112 prefer_prop
[FONT_SIZE_INDEX
]
2113 = make_number (font_pixel_size (XFRAME (frame
), prefer
));
2114 if (! NILP (prefer_prop
[FONT_FAMILY_INDEX
]))
2117 = Fassoc_string (prefer_prop
[FONT_FAMILY_INDEX
],
2118 Vface_alternative_font_family_alist
, Qt
);
2119 if (CONSP (alternate_families
))
2120 alternate_families
= XCDR (alternate_families
);
2123 /* Scoring and sorting. */
2124 SAFE_ALLOCA (data
, struct font_sort_data
*, (sizeof *data
) * len
);
2125 best_score
= 0xFFFFFFFF;
2127 for (i
= 0; i
< len
; i
++)
2129 data
[i
].entity
= AREF (vec
, i
);
2130 data
[i
].score
= font_score (data
[i
].entity
, prefer_prop
,
2131 alternate_families
);
2132 if (best_only
&& best_score
> data
[i
].score
)
2134 best_score
= data
[i
].score
;
2135 best_entity
= data
[i
].entity
;
2136 if (best_score
== 0)
2140 if (NILP (best_entity
))
2142 qsort (data
, len
, sizeof *data
, font_compare
);
2143 for (i
= 0; i
< len
; i
++)
2144 ASET (vec
, i
, data
[i
].entity
);
2150 font_add_log ("sort-by", prefer
, vec
);
2155 /* API of Font Service Layer. */
2157 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2158 sort_shift_bits. Finternal_set_font_selection_order calls this
2159 function with font_sort_order after setting up it. */
2162 font_update_sort_order (order
)
2167 for (i
= 0, shift_bits
= 21; i
< 4; i
++, shift_bits
-= 7)
2169 int xlfd_idx
= order
[i
];
2171 if (xlfd_idx
== XLFD_WEIGHT_INDEX
)
2172 sort_shift_bits
[FONT_WEIGHT_INDEX
] = shift_bits
;
2173 else if (xlfd_idx
== XLFD_SLANT_INDEX
)
2174 sort_shift_bits
[FONT_SLANT_INDEX
] = shift_bits
;
2175 else if (xlfd_idx
== XLFD_SWIDTH_INDEX
)
2176 sort_shift_bits
[FONT_WIDTH_INDEX
] = shift_bits
;
2178 sort_shift_bits
[FONT_SIZE_INDEX
] = shift_bits
;
2183 /* Check if ENTITY matches with the font specification SPEC. */
2186 font_match_p (spec
, entity
)
2187 Lisp_Object spec
, entity
;
2189 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2190 Lisp_Object alternate_families
= Qnil
;
2193 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
2194 prefer_prop
[i
] = AREF (spec
, i
);
2195 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2196 prefer_prop
[FONT_SIZE_INDEX
]
2197 = make_number (font_pixel_size (XFRAME (selected_frame
), spec
));
2198 if (! NILP (prefer_prop
[FONT_FAMILY_INDEX
]))
2201 = Fassoc_string (prefer_prop
[FONT_FAMILY_INDEX
],
2202 Vface_alternative_font_family_alist
, Qt
);
2203 if (CONSP (alternate_families
))
2204 alternate_families
= XCDR (alternate_families
);
2207 return (font_score (entity
, prefer_prop
, alternate_families
) == 0);
2211 /* CHeck a lispy font object corresponding to FONT. */
2214 font_check_object (font
)
2217 Lisp_Object tail
, elt
;
2219 for (tail
= font
->props
[FONT_OBJLIST_INDEX
]; CONSP (tail
);
2223 if (font
== XFONT_OBJECT (elt
))
2233 Each font backend has the callback function get_cache, and it
2234 returns a cons cell of which cdr part can be freely used for
2235 caching fonts. The cons cell may be shared by multiple frames
2236 and/or multiple font drivers. So, we arrange the cdr part as this:
2238 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2240 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2241 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2242 cons (FONT-SPEC FONT-ENTITY ...). */
2244 static void font_prepare_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2245 static void font_finish_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2246 static Lisp_Object font_get_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2247 static void font_clear_cache
P_ ((FRAME_PTR
, Lisp_Object
,
2248 struct font_driver
*));
2251 font_prepare_cache (f
, driver
)
2253 struct font_driver
*driver
;
2255 Lisp_Object cache
, val
;
2257 cache
= driver
->get_cache (f
);
2259 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2263 val
= Fcons (driver
->type
, Fcons (make_number (1), Qnil
));
2264 XSETCDR (cache
, Fcons (val
, XCDR (cache
)));
2268 val
= XCDR (XCAR (val
));
2269 XSETCAR (val
, make_number (XINT (XCAR (val
)) + 1));
2275 font_finish_cache (f
, driver
)
2277 struct font_driver
*driver
;
2279 Lisp_Object cache
, val
, tmp
;
2282 cache
= driver
->get_cache (f
);
2284 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2285 cache
= val
, val
= XCDR (val
);
2286 font_assert (! NILP (val
));
2287 tmp
= XCDR (XCAR (val
));
2288 XSETCAR (tmp
, make_number (XINT (XCAR (tmp
)) - 1));
2289 if (XINT (XCAR (tmp
)) == 0)
2291 font_clear_cache (f
, XCAR (val
), driver
);
2292 XSETCDR (cache
, XCDR (val
));
2298 font_get_cache (f
, driver
)
2300 struct font_driver
*driver
;
2302 Lisp_Object val
= driver
->get_cache (f
);
2303 Lisp_Object type
= driver
->type
;
2305 font_assert (CONSP (val
));
2306 for (val
= XCDR (val
); ! EQ (XCAR (XCAR (val
)), type
); val
= XCDR (val
));
2307 font_assert (CONSP (val
));
2308 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2309 val
= XCDR (XCAR (val
));
2313 static int num_fonts
;
2316 font_clear_cache (f
, cache
, driver
)
2319 struct font_driver
*driver
;
2321 Lisp_Object tail
, elt
;
2323 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2324 for (tail
= XCDR (XCDR (cache
)); CONSP (tail
); tail
= XCDR (tail
))
2327 if (CONSP (elt
) && FONT_SPEC_P (XCAR (elt
)) && VECTORP (XCDR (elt
)))
2329 Lisp_Object vec
= XCDR (elt
);
2332 for (i
= 0; i
< ASIZE (vec
); i
++)
2334 Lisp_Object entity
= AREF (vec
, i
);
2336 if (EQ (driver
->type
, AREF (entity
, FONT_TYPE_INDEX
)))
2338 Lisp_Object objlist
= AREF (entity
, FONT_OBJLIST_INDEX
);
2340 for (; CONSP (objlist
); objlist
= XCDR (objlist
))
2342 Lisp_Object val
= XCAR (objlist
);
2343 struct font
*font
= XFONT_OBJECT (val
);
2345 font_assert (font
&& driver
== font
->driver
);
2346 driver
->close (f
, font
);
2349 if (driver
->free_entity
)
2350 driver
->free_entity (entity
);
2355 XSETCDR (cache
, Qnil
);
2359 static Lisp_Object scratch_font_spec
, scratch_font_prefer
;
2362 font_delete_unmatched (list
, spec
, size
)
2363 Lisp_Object list
, spec
;
2366 Lisp_Object entity
, val
;
2367 enum font_property_index prop
;
2369 for (val
= Qnil
; CONSP (list
); list
= XCDR (list
))
2371 entity
= XCAR (list
);
2372 for (prop
= FONT_WEIGHT_INDEX
; prop
< FONT_SIZE_INDEX
; prop
++)
2373 if (INTEGERP (AREF (spec
, prop
))
2374 && ((XINT (AREF (spec
, prop
)) >> 8)
2375 != (XINT (AREF (entity
, prop
)) >> 8)))
2376 prop
= FONT_SPEC_MAX
;
2377 if (prop
++ <= FONT_SIZE_INDEX
2379 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0)
2381 int diff
= XINT (AREF (entity
, FONT_SIZE_INDEX
)) - size
;
2384 && (diff
< 0 ? -diff
> FONT_PIXEL_SIZE_QUANTUM
2385 : diff
> FONT_PIXEL_SIZE_QUANTUM
))
2386 prop
= FONT_SPEC_MAX
;
2388 if (prop
< FONT_SPEC_MAX
)
2389 val
= Fcons (entity
, val
);
2395 /* Return a vector of font-entities matching with SPEC on FRAME. */
2398 font_list_entities (frame
, spec
)
2399 Lisp_Object frame
, spec
;
2401 FRAME_PTR f
= XFRAME (frame
);
2402 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2403 Lisp_Object ftype
, family
, alternate_familes
, val
;
2406 int need_filtering
= 0;
2410 font_assert (FONT_SPEC_P (spec
));
2412 family
= AREF (spec
, FONT_FAMILY_INDEX
);
2414 alternate_familes
= Qnil
;
2417 alternate_familes
= Fassoc_string (family
,
2418 Vface_alternative_font_family_alist
,
2420 if (! NILP (alternate_familes
))
2421 alternate_familes
= XCDR (alternate_familes
);
2422 n_family
+= XINT (Flength (alternate_familes
));
2425 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2426 size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
2427 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
2428 size
= font_pixel_size (f
, spec
);
2432 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2433 for (i
= 1; i
<= FONT_REGISTRY_INDEX
; i
++)
2434 ASET (scratch_font_spec
, i
, AREF (spec
, i
));
2435 for (i
= FONT_DPI_INDEX
; i
< FONT_EXTRA_INDEX
; i
+= 2)
2437 ASET (scratch_font_spec
, i
, Qnil
);
2438 if (! NILP (AREF (spec
, i
)))
2441 ASET (scratch_font_spec
, FONT_SPACING_INDEX
, AREF (spec
, FONT_SPACING_INDEX
));
2442 ASET (scratch_font_spec
, FONT_EXTRA_INDEX
, AREF (spec
, FONT_EXTRA_INDEX
));
2444 vec
= alloca (sizeof (Lisp_Object
) * num_font_drivers
* n_family
);
2448 for (i
= 0; driver_list
; driver_list
= driver_list
->next
)
2450 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2452 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2453 Lisp_Object tail
= alternate_familes
;
2455 ASET (scratch_font_spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2456 ASET (scratch_font_spec
, FONT_FAMILY_INDEX
, family
);
2459 val
= assoc_no_quit (scratch_font_spec
, XCDR (cache
));
2466 val
= driver_list
->driver
->list (frame
, scratch_font_spec
);
2467 copy
= Fcopy_font_spec (scratch_font_spec
);
2468 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2469 XSETCDR (cache
, Fcons (Fcons (copy
, val
), XCDR (cache
)));
2471 if (! NILP (val
) && need_filtering
)
2472 val
= font_delete_unmatched (val
, spec
, size
);
2480 ASET (scratch_font_spec
, FONT_FAMILY_INDEX
,
2481 Fintern (XCAR (tail
), Qnil
));
2486 val
= (i
> 0 ? Fvconcat (i
, vec
) : null_vector
);
2487 font_add_log ("list", spec
, val
);
2492 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2493 nil, is an array of face's attributes, which specifies preferred
2494 font-related attributes. */
2497 font_matching_entity (f
, attrs
, spec
)
2499 Lisp_Object
*attrs
, spec
;
2501 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2502 Lisp_Object ftype
, size
, entity
;
2505 XSETFRAME (frame
, f
);
2506 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2507 size
= AREF (spec
, FONT_SIZE_INDEX
);
2509 ASET (spec
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2511 for (; driver_list
; driver_list
= driver_list
->next
)
2513 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2515 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2518 ASET (spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2519 entity
= assoc_no_quit (spec
, XCDR (cache
));
2521 entity
= XCDR (entity
);
2524 entity
= driver_list
->driver
->match (frame
, spec
);
2525 copy
= Fcopy_font_spec (spec
);
2526 ASET (copy
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2527 XSETCDR (cache
, Fcons (Fcons (copy
, entity
), XCDR (cache
)));
2529 if (! NILP (entity
))
2532 ASET (spec
, FONT_TYPE_INDEX
, ftype
);
2533 ASET (spec
, FONT_SIZE_INDEX
, size
);
2534 font_add_log ("match", spec
, entity
);
2539 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2540 opened font object. */
2543 font_open_entity (f
, entity
, pixel_size
)
2548 struct font_driver_list
*driver_list
;
2549 Lisp_Object objlist
, size
, val
, font_object
;
2553 font_assert (FONT_ENTITY_P (entity
));
2554 size
= AREF (entity
, FONT_SIZE_INDEX
);
2555 if (XINT (size
) != 0)
2556 pixel_size
= XINT (size
);
2558 for (objlist
= AREF (entity
, FONT_OBJLIST_INDEX
); CONSP (objlist
);
2559 objlist
= XCDR (objlist
))
2560 if (XFONT_OBJECT (XCAR (objlist
))->pixel_size
== pixel_size
)
2561 return XCAR (objlist
);
2563 val
= AREF (entity
, FONT_TYPE_INDEX
);
2564 for (driver_list
= f
->font_driver_list
;
2565 driver_list
&& ! EQ (driver_list
->driver
->type
, val
);
2566 driver_list
= driver_list
->next
);
2570 font_object
= driver_list
->driver
->open (f
, entity
, pixel_size
);
2571 font_add_log ("open", entity
, font_object
);
2572 if (NILP (font_object
))
2574 ASET (entity
, FONT_OBJLIST_INDEX
,
2575 Fcons (font_object
, AREF (entity
, FONT_OBJLIST_INDEX
)));
2576 ASET (font_object
, FONT_OBJLIST_INDEX
, AREF (entity
, FONT_OBJLIST_INDEX
));
2579 font
= XFONT_OBJECT (font_object
);
2580 min_width
= (font
->min_width
? font
->min_width
2581 : font
->average_width
? font
->average_width
2582 : font
->space_width
? font
->space_width
2584 #ifdef HAVE_WINDOW_SYSTEM
2585 FRAME_X_DISPLAY_INFO (f
)->n_fonts
++;
2586 if (FRAME_X_DISPLAY_INFO (f
)->n_fonts
== 1)
2588 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
;
2589 FRAME_SMALLEST_FONT_HEIGHT (f
) = font
->height
;
2590 fonts_changed_p
= 1;
2594 if (FRAME_SMALLEST_CHAR_WIDTH (f
) > min_width
)
2595 FRAME_SMALLEST_CHAR_WIDTH (f
) = min_width
, fonts_changed_p
= 1;
2596 if (FRAME_SMALLEST_FONT_HEIGHT (f
) > font
->height
)
2597 FRAME_SMALLEST_FONT_HEIGHT (f
) = font
->height
, fonts_changed_p
= 1;
2605 /* Close FONT_OBJECT that is opened on frame F. */
2608 font_close_object (f
, font_object
)
2610 Lisp_Object font_object
;
2612 struct font
*font
= XFONT_OBJECT (font_object
);
2613 Lisp_Object objlist
;
2614 Lisp_Object tail
, prev
= Qnil
;
2616 objlist
= AREF (font_object
, FONT_OBJLIST_INDEX
);
2617 for (prev
= Qnil
, tail
= objlist
; CONSP (tail
);
2618 prev
= tail
, tail
= XCDR (tail
))
2619 if (EQ (font_object
, XCAR (tail
)))
2621 font_add_log ("close", font_object
, Qnil
);
2622 font
->driver
->close (f
, font
);
2623 #ifdef HAVE_WINDOW_SYSTEM
2624 font_assert (FRAME_X_DISPLAY_INFO (f
)->n_fonts
);
2625 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
2628 ASET (font_object
, FONT_OBJLIST_INDEX
, XCDR (objlist
));
2630 XSETCDR (prev
, XCDR (objlist
));
2638 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2639 FONT is a font-entity and it must be opened to check. */
2642 font_has_char (f
, font
, c
)
2649 if (FONT_ENTITY_P (font
))
2651 Lisp_Object type
= AREF (font
, FONT_TYPE_INDEX
);
2652 struct font_driver_list
*driver_list
;
2654 for (driver_list
= f
->font_driver_list
;
2655 driver_list
&& ! EQ (driver_list
->driver
->type
, type
);
2656 driver_list
= driver_list
->next
);
2659 if (! driver_list
->driver
->has_char
)
2661 return driver_list
->driver
->has_char (font
, c
);
2664 font_assert (FONT_OBJECT_P (font
));
2665 fontp
= XFONT_OBJECT (font
);
2666 if (fontp
->driver
->has_char
)
2668 int result
= fontp
->driver
->has_char (font
, c
);
2673 return (fontp
->driver
->encode_char (fontp
, c
) != FONT_INVALID_CODE
);
2677 /* Return the glyph ID of FONT_OBJECT for character C. */
2680 font_encode_char (font_object
, c
)
2681 Lisp_Object font_object
;
2686 font_assert (FONT_OBJECT_P (font_object
));
2687 font
= XFONT_OBJECT (font_object
);
2688 return font
->driver
->encode_char (font
, c
);
2692 /* Return the name of FONT_OBJECT. */
2695 font_get_name (font_object
)
2696 Lisp_Object font_object
;
2698 font_assert (FONT_OBJECT_P (font_object
));
2699 return AREF (font_object
, FONT_NAME_INDEX
);
2703 /* Return the specification of FONT_OBJECT. */
2706 font_get_spec (font_object
)
2707 Lisp_Object font_object
;
2709 Lisp_Object spec
= font_make_spec ();
2712 for (i
= 0; i
< FONT_SIZE_INDEX
; i
++)
2713 ASET (spec
, i
, AREF (font_object
, i
));
2714 ASET (spec
, FONT_SIZE_INDEX
,
2715 make_number (XFONT_OBJECT (font_object
)->pixel_size
));
2720 font_spec_from_name (font_name
)
2721 Lisp_Object font_name
;
2723 Lisp_Object args
[2];
2726 args
[1] = font_name
;
2727 return Ffont_spec (2, args
);
2732 font_clear_prop (attrs
, prop
)
2734 enum font_property_index prop
;
2736 Lisp_Object font
= attrs
[LFACE_FONT_INDEX
];
2740 if (NILP (AREF (font
, prop
))
2741 && prop
!= FONT_FAMILY_INDEX
&& prop
!= FONT_FAMILY_INDEX
)
2743 font
= Fcopy_font_spec (font
);
2744 ASET (font
, prop
, Qnil
);
2745 if (prop
== FONT_FAMILY_INDEX
)
2747 ASET (font
, FONT_FOUNDRY_INDEX
, Qnil
);
2748 ASET (font
, FONT_ADSTYLE_INDEX
, Qnil
);
2749 ASET (font
, FONT_SIZE_INDEX
, Qnil
);
2750 ASET (font
, FONT_DPI_INDEX
, Qnil
);
2751 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
2752 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
2754 else if (prop
== FONT_SIZE_INDEX
)
2756 ASET (font
, FONT_DPI_INDEX
, Qnil
);
2757 ASET (font
, FONT_SPACING_INDEX
, Qnil
);
2758 ASET (font
, FONT_AVGWIDTH_INDEX
, Qnil
);
2760 attrs
[LFACE_FONT_INDEX
] = font
;
2764 font_update_lface (f
, attrs
)
2770 spec
= attrs
[LFACE_FONT_INDEX
];
2771 if (! FONT_SPEC_P (spec
))
2774 if (! NILP (AREF (spec
, FONT_FOUNDRY_INDEX
))
2775 || ! NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
2779 if (NILP (AREF (spec
, FONT_FOUNDRY_INDEX
)))
2780 family
= AREF (spec
, FONT_FAMILY_INDEX
);
2781 else if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
2782 family
= concat2 (SYMBOL_NAME (AREF (spec
, FONT_FOUNDRY_INDEX
)),
2783 build_string ("-*"));
2785 family
= concat3 (SYMBOL_NAME (AREF (spec
, FONT_FOUNDRY_INDEX
)),
2787 SYMBOL_NAME (AREF (spec
, FONT_FAMILY_INDEX
)));
2788 attrs
[LFACE_FAMILY_INDEX
] = family
;
2790 if (! NILP (AREF (spec
, FONT_WEIGHT_INDEX
)))
2791 attrs
[LFACE_WEIGHT_INDEX
] = FONT_WEIGHT_FOR_FACE (spec
);
2792 if (! NILP (AREF (spec
, FONT_SLANT_INDEX
)))
2793 attrs
[LFACE_SLANT_INDEX
] = FONT_SLANT_FOR_FACE (spec
);;
2794 if (! NILP (AREF (spec
, FONT_WIDTH_INDEX
)))
2795 attrs
[LFACE_SWIDTH_INDEX
] = FONT_WIDTH_FOR_FACE (spec
);
2796 if (! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
2800 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2805 val
= Ffont_get (spec
, QCdpi
);
2808 point
= PIXEL_TO_POINT (XINT (AREF (spec
, FONT_SIZE_INDEX
)) * 10,
2811 else if (FLOATP (AREF (spec
, FONT_SIZE_INDEX
)))
2812 point
= XFLOAT_DATA (AREF (spec
, FONT_SIZE_INDEX
)) * 10;
2813 attrs
[LFACE_HEIGHT_INDEX
] = make_number (point
);
2818 /* Return a font-entity satisfying SPEC and best matching with face's
2819 font related attributes in ATTRS. C, if not negative, is a
2820 character that the entity must support. */
2823 font_find_for_lface (f
, attrs
, spec
, c
)
2829 Lisp_Object frame
, entities
, val
, props
[FONT_REGISTRY_INDEX
+ 1] ;
2836 Lisp_Object registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
2837 struct charset
*encoding
, *repertory
;
2839 if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
2843 if (ENCODE_CHAR (repertory
, c
) == CHARSET_INVALID_CODE (repertory
))
2845 /* Any font of this registry support C. So, let's
2846 suppress the further checking. */
2849 else if (c
> encoding
->max_char
)
2853 XSETFRAME (frame
, f
);
2854 size
= AREF (spec
, FONT_SIZE_INDEX
);
2855 pixel_size
= font_pixel_size (f
, spec
);
2856 if (pixel_size
== 0)
2858 double pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
2860 pixel_size
= POINT_TO_PIXEL (pt
/ 10, f
->resy
);
2862 ASET (spec
, FONT_SIZE_INDEX
, Qnil
);
2863 entities
= font_list_entities (frame
, spec
);
2864 ASET (spec
, FONT_SIZE_INDEX
, size
);
2865 if (ASIZE (entities
) == 0)
2867 if (ASIZE (entities
) == 1)
2870 return AREF (entities
, 0);
2874 /* Sort fonts by properties specified in LFACE. */
2875 Lisp_Object prefer
= scratch_font_prefer
;
2877 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
2878 ASET (prefer
, i
, AREF (spec
, i
));
2879 if (FONTP (attrs
[LFACE_FONT_INDEX
]))
2881 Lisp_Object face_font
= attrs
[LFACE_FONT_INDEX
];
2883 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
2884 if (NILP (AREF (prefer
, i
)))
2885 ASET (prefer
, i
, AREF (face_font
, i
));
2887 if (NILP (AREF (prefer
, FONT_FAMILY_INDEX
)))
2888 font_parse_family_registry (attrs
[LFACE_FAMILY_INDEX
], Qnil
, prefer
);
2889 if (NILP (AREF (prefer
, FONT_WEIGHT_INDEX
)))
2890 FONT_SET_STYLE (prefer
, FONT_WEIGHT_INDEX
, attrs
[LFACE_WEIGHT_INDEX
]);
2891 if (NILP (AREF (prefer
, FONT_SLANT_INDEX
)))
2892 FONT_SET_STYLE (prefer
, FONT_SLANT_INDEX
, attrs
[LFACE_SLANT_INDEX
]);
2893 if (NILP (AREF (prefer
, FONT_WIDTH_INDEX
)))
2894 FONT_SET_STYLE (prefer
, FONT_WIDTH_INDEX
, attrs
[LFACE_SWIDTH_INDEX
]);
2895 ASET (prefer
, FONT_SIZE_INDEX
, make_number (pixel_size
));
2896 ASET (spec
, FONT_SIZE_INDEX
, Qnil
);
2897 entities
= font_sort_entites (entities
, prefer
, frame
, spec
, c
< 0);
2898 ASET (spec
, FONT_SIZE_INDEX
, size
);
2903 for (i
= 0; i
< ASIZE (entities
); i
++)
2907 val
= AREF (entities
, i
);
2910 for (j
= FONT_FOUNDRY_INDEX
; j
<= FONT_REGISTRY_INDEX
; j
++)
2911 if (! EQ (AREF (val
, j
), props
[j
]))
2913 if (j
> FONT_REGISTRY_INDEX
)
2916 for (j
= FONT_FOUNDRY_INDEX
; j
<= FONT_REGISTRY_INDEX
; j
++)
2917 props
[j
] = AREF (val
, j
);
2918 result
= font_has_char (f
, val
, c
);
2923 val
= font_open_for_lface (f
, val
, attrs
, spec
);
2926 result
= font_has_char (f
, val
, c
);
2927 font_close_object (f
, val
);
2929 return AREF (entities
, i
);
2936 font_open_for_lface (f
, entity
, attrs
, spec
)
2944 if (FONT_SPEC_P (spec
) && ! NILP (AREF (spec
, FONT_SIZE_INDEX
)))
2945 size
= font_pixel_size (f
, spec
);
2948 double pt
= XINT (attrs
[LFACE_HEIGHT_INDEX
]);
2951 size
= POINT_TO_PIXEL (pt
, f
->resy
);
2953 return font_open_entity (f
, entity
, size
);
2957 /* Find a font satisfying SPEC and best matching with face's
2958 attributes in ATTRS on FRAME, and return the opened
2962 font_load_for_lface (f
, attrs
, spec
)
2964 Lisp_Object
*attrs
, spec
;
2968 entity
= font_find_for_lface (f
, attrs
, spec
, -1);
2971 /* No font is listed for SPEC, but each font-backend may have
2972 the different criteria about "font matching". So, try
2974 entity
= font_matching_entity (f
, attrs
, spec
);
2978 return font_open_for_lface (f
, entity
, attrs
, spec
);
2982 /* Make FACE on frame F ready to use the font opened for FACE. */
2985 font_prepare_for_face (f
, face
)
2989 if (face
->font
->driver
->prepare_face
)
2990 face
->font
->driver
->prepare_face (f
, face
);
2994 /* Make FACE on frame F stop using the font opened for FACE. */
2997 font_done_for_face (f
, face
)
3001 if (face
->font
->driver
->done_face
)
3002 face
->font
->driver
->done_face (f
, face
);
3007 /* Open a font best matching with NAME on frame F. If no proper font
3008 is found, return Qnil. */
3011 font_open_by_name (f
, name
)
3015 Lisp_Object args
[2];
3016 Lisp_Object spec
, prefer
, size
, registry
, entity
, entity_list
;
3021 XSETFRAME (frame
, f
);
3024 args
[1] = make_unibyte_string (name
, strlen (name
));
3025 spec
= Ffont_spec (2, args
);
3026 prefer
= scratch_font_prefer
;
3027 for (i
= 0; i
< FONT_SPEC_MAX
; i
++)
3029 ASET (prefer
, i
, AREF (spec
, i
));
3030 if (NILP (AREF (prefer
, i
))
3031 && i
>= FONT_WEIGHT_INDEX
&& i
<= FONT_WIDTH_INDEX
)
3032 FONT_SET_STYLE (prefer
, i
, make_number (100));
3034 size
= AREF (spec
, FONT_SIZE_INDEX
);
3039 if (INTEGERP (size
))
3040 pixel_size
= XINT (size
);
3041 else /* FLOATP (size) */
3043 double pt
= XFLOAT_DATA (size
);
3045 pixel_size
= POINT_TO_PIXEL (pt
, f
->resy
);
3047 if (pixel_size
== 0)
3048 ASET (spec
, FONT_SIZE_INDEX
, Qnil
);
3050 if (pixel_size
== 0)
3052 pixel_size
= POINT_TO_PIXEL (12.0, f
->resy
);
3053 size
= make_number (pixel_size
);
3054 ASET (prefer
, FONT_SIZE_INDEX
, size
);
3056 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
3057 if (NILP (registry
))
3058 ASET (spec
, FONT_REGISTRY_INDEX
, Qiso8859_1
);
3059 entity_list
= Flist_fonts (spec
, frame
, make_number (1), prefer
);
3060 if (NILP (entity_list
) && NILP (registry
))
3062 ASET (spec
, FONT_REGISTRY_INDEX
, Qascii_0
);
3063 entity_list
= Flist_fonts (spec
, frame
, make_number (1), prefer
);
3065 ASET (spec
, FONT_REGISTRY_INDEX
, registry
);
3066 if (NILP (entity_list
))
3067 entity
= font_matching_entity (f
, NULL
, spec
);
3069 entity
= XCAR (entity_list
);
3070 return (NILP (entity
)
3072 : font_open_entity (f
, entity
, pixel_size
));
3076 /* Register font-driver DRIVER. This function is used in two ways.
3078 The first is with frame F non-NULL. In this case, make DRIVER
3079 available (but not yet activated) on F. All frame creaters
3080 (e.g. Fx_create_frame) must call this function at least once with
3081 an available font-driver.
3083 The second is with frame F NULL. In this case, DRIVER is globally
3084 registered in the variable `font_driver_list'. All font-driver
3085 implementations must call this function in its syms_of_XXXX
3086 (e.g. syms_of_xfont). */
3089 register_font_driver (driver
, f
)
3090 struct font_driver
*driver
;
3093 struct font_driver_list
*root
= f
? f
->font_driver_list
: font_driver_list
;
3094 struct font_driver_list
*prev
, *list
;
3096 if (f
&& ! driver
->draw
)
3097 error ("Unusable font driver for a frame: %s",
3098 SDATA (SYMBOL_NAME (driver
->type
)));
3100 for (prev
= NULL
, list
= root
; list
; prev
= list
, list
= list
->next
)
3101 if (EQ (list
->driver
->type
, driver
->type
))
3102 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver
->type
)));
3104 list
= malloc (sizeof (struct font_driver_list
));
3106 list
->driver
= driver
;
3111 f
->font_driver_list
= list
;
3113 font_driver_list
= list
;
3119 /* Free font-driver list on frame F. It doesn't free font-drivers
3123 free_font_driver_list (f
)
3126 while (f
->font_driver_list
)
3128 struct font_driver_list
*next
= f
->font_driver_list
->next
;
3130 free (f
->font_driver_list
);
3131 f
->font_driver_list
= next
;
3136 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3137 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3138 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3140 A caller must free all realized faces if any in advance. The
3141 return value is a list of font backends actually made used on
3145 font_update_drivers (f
, new_drivers
)
3147 Lisp_Object new_drivers
;
3149 Lisp_Object active_drivers
= Qnil
;
3150 struct font_driver_list
*list
;
3152 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3155 if (! EQ (new_drivers
, Qt
)
3156 && NILP (Fmemq (list
->driver
->type
, new_drivers
)))
3158 if (list
->driver
->end_for_frame
)
3159 list
->driver
->end_for_frame (f
);
3160 font_finish_cache (f
, list
->driver
);
3166 if (EQ (new_drivers
, Qt
)
3167 || ! NILP (Fmemq (list
->driver
->type
, new_drivers
)))
3169 if (! list
->driver
->start_for_frame
3170 || list
->driver
->start_for_frame (f
) == 0)
3172 font_prepare_cache (f
, list
->driver
);
3174 active_drivers
= nconc2 (active_drivers
,
3175 Fcons (list
->driver
->type
, Qnil
));
3180 return active_drivers
;
3184 font_put_frame_data (f
, driver
, data
)
3186 struct font_driver
*driver
;
3189 struct font_data_list
*list
, *prev
;
3191 for (prev
= NULL
, list
= f
->font_data_list
; list
;
3192 prev
= list
, list
= list
->next
)
3193 if (list
->driver
== driver
)
3200 prev
->next
= list
->next
;
3202 f
->font_data_list
= list
->next
;
3210 list
= malloc (sizeof (struct font_data_list
));
3213 list
->driver
= driver
;
3214 list
->next
= f
->font_data_list
;
3215 f
->font_data_list
= list
;
3223 font_get_frame_data (f
, driver
)
3225 struct font_driver
*driver
;
3227 struct font_data_list
*list
;
3229 for (list
= f
->font_data_list
; list
; list
= list
->next
)
3230 if (list
->driver
== driver
)
3238 /* Return the font used to draw character C by FACE at buffer position
3239 POS in window W. If STRING is non-nil, it is a string containing C
3240 at index POS. If C is negative, get C from the current buffer or
3244 font_at (c
, pos
, face
, w
, string
)
3253 Lisp_Object font_object
;
3259 multibyte
= ! NILP (current_buffer
->enable_multibyte_characters
);
3262 EMACS_INT pos_byte
= CHAR_TO_BYTE (pos
);
3264 c
= FETCH_CHAR (pos_byte
);
3267 c
= FETCH_BYTE (pos
);
3273 multibyte
= STRING_MULTIBYTE (string
);
3276 EMACS_INT pos_byte
= string_char_to_byte (string
, pos
);
3278 str
= SDATA (string
) + pos_byte
;
3279 c
= STRING_CHAR (str
, 0);
3282 c
= SDATA (string
)[pos
];
3286 f
= XFRAME (w
->frame
);
3287 if (! FRAME_WINDOW_P (f
))
3294 if (STRINGP (string
))
3295 face_id
= face_at_string_position (w
, string
, pos
, 0, -1, -1, &endptr
,
3296 DEFAULT_FACE_ID
, 0);
3298 face_id
= face_at_buffer_position (w
, pos
, -1, -1, &endptr
,
3300 face
= FACE_FROM_ID (f
, face_id
);
3304 int face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3305 face
= FACE_FROM_ID (f
, face_id
);
3310 font_assert (font_check_object ((struct font
*) face
->font
));
3311 XSETFONT (font_object
, face
->font
);
3316 /* Check how many characters after POS (at most to LIMIT) can be
3317 displayed by the same font. FACE is the face selected for the
3318 character as POS on frame F. STRING, if not nil, is the string to
3319 check instead of the current buffer.
3321 The return value is the position of the character that is displayed
3322 by the differnt font than that of the character as POS. */
3325 font_range (pos
, limit
, face
, f
, string
)
3326 EMACS_INT pos
, limit
;
3339 multibyte
= ! NILP (current_buffer
->enable_multibyte_characters
);
3340 pos_byte
= CHAR_TO_BYTE (pos
);
3344 multibyte
= STRING_MULTIBYTE (string
);
3345 pos_byte
= string_char_to_byte (string
, pos
);
3349 /* All unibyte character are displayed by the same font. */
3357 FETCH_CHAR_ADVANCE_NO_CHECK (c
, pos
, pos_byte
);
3359 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c
, string
, pos
, pos_byte
);
3360 face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3361 face
= FACE_FROM_ID (f
, face_id
);
3368 else if (font
!= face
->font
)
3380 DEFUN ("fontp", Ffontp
, Sfontp
, 1, 2, 0,
3381 doc
: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3382 Return nil otherwise.
3383 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3384 which kind of font it is. It must be one of `font-spec', `font-entity',
3386 (object
, extra_type
)
3387 Lisp_Object object
, extra_type
;
3389 if (NILP (extra_type
))
3390 return (FONTP (object
) ? Qt
: Qnil
);
3391 if (EQ (extra_type
, Qfont_spec
))
3392 return (FONT_SPEC_P (object
) ? Qt
: Qnil
);
3393 if (EQ (extra_type
, Qfont_entity
))
3394 return (FONT_ENTITY_P (object
) ? Qt
: Qnil
);
3395 if (EQ (extra_type
, Qfont_object
))
3396 return (FONT_OBJECT_P (object
) ? Qt
: Qnil
);
3397 wrong_type_argument (intern ("font-extra-type"), extra_type
);
3400 DEFUN ("font-spec", Ffont_spec
, Sfont_spec
, 0, MANY
, 0,
3401 doc
: /* Return a newly created font-spec with arguments as properties.
3403 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3404 valid font property name listed below:
3406 `:family', `:weight', `:slant', `:width'
3408 They are the same as face attributes of the same name. See
3409 `set-face-attribute'.
3413 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3417 VALUE must be a string or a symbol specifying the additional
3418 typographic style information of a font, e.g. ``sans''.
3422 VALUE must be a string or a symbol specifying the charset registry and
3423 encoding of a font, e.g. ``iso8859-1''.
3427 VALUE must be a non-negative integer or a floating point number
3428 specifying the font size. It specifies the font size in pixels
3429 (if VALUE is an integer), or in points (if VALUE is a float).
3430 usage: (font-spec ARGS ...) */)
3435 Lisp_Object spec
= font_make_spec ();
3438 for (i
= 0; i
< nargs
; i
+= 2)
3440 Lisp_Object key
= args
[i
], val
= args
[i
+ 1];
3442 if (EQ (key
, QCname
))
3445 font_parse_name ((char *) SDATA (val
), spec
);
3446 font_put_extra (spec
, key
, val
);
3450 int idx
= get_font_prop_index (key
);
3454 val
= font_prop_validate (idx
, Qnil
, val
);
3455 if (idx
< FONT_EXTRA_INDEX
)
3456 ASET (spec
, idx
, val
);
3458 font_put_extra (spec
, key
, val
);
3461 font_put_extra (spec
, key
, font_prop_validate (0, key
, val
));
3467 DEFUN ("copy-font-spec", Fcopy_font_spec
, Scopy_font_spec
, 1, 1, 0,
3468 doc
: /* Return a copy of FONT as a font-spec. */)
3472 Lisp_Object new_spec
, tail
, extra
;
3476 new_spec
= font_make_spec ();
3477 for (i
= 1; i
< FONT_EXTRA_INDEX
; i
++)
3478 ASET (new_spec
, i
, AREF (font
, i
));
3480 for (tail
= AREF (font
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
3482 if (! EQ (XCAR (XCAR (tail
)), QCfont_entity
))
3483 extra
= Fcons (Fcons (XCAR (XCAR (tail
)), XCDR (XCAR (tail
))), extra
);
3485 ASET (new_spec
, FONT_EXTRA_INDEX
, extra
);
3489 DEFUN ("merge-font-spec", Fmerge_font_spec
, Smerge_font_spec
, 2, 2, 0,
3490 doc
: /* Merge font-specs FROM and TO, and return a new font-spec.
3491 Every specified properties in FROM override the corresponding
3492 properties in TO. */)
3494 Lisp_Object from
, to
;
3496 Lisp_Object extra
, tail
;
3501 to
= Fcopy_font_spec (to
);
3502 for (i
= 0; i
< FONT_EXTRA_INDEX
; i
++)
3503 ASET (to
, i
, AREF (from
, i
));
3504 extra
= AREF (to
, FONT_EXTRA_INDEX
);
3505 for (tail
= AREF (from
, FONT_EXTRA_INDEX
); CONSP (tail
); tail
= XCDR (tail
))
3506 if (! EQ (XCAR (XCAR (tail
)), Qfont_entity
))
3508 Lisp_Object slot
= assq_no_quit (XCAR (XCAR (tail
)), extra
);
3511 XSETCDR (slot
, XCDR (XCAR (tail
)));
3513 extra
= Fcons (Fcons (XCAR (XCAR (tail
)), XCDR (XCAR (tail
))), extra
);
3515 ASET (to
, FONT_EXTRA_INDEX
, extra
);
3519 DEFUN ("font-get", Ffont_get
, Sfont_get
, 2, 2, 0,
3520 doc
: /* Return the value of FONT's property KEY.
3521 FONT is a font-spec, a font-entity, or a font-object. */)
3523 Lisp_Object font
, key
;
3530 idx
= get_font_prop_index (key
);
3531 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
3532 return AREF (font
, idx
);
3533 return Fcdr (Fassq (key
, AREF (font
, FONT_EXTRA_INDEX
)));
3537 DEFUN ("font-put", Ffont_put
, Sfont_put
, 3, 3, 0,
3538 doc
: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
3539 (font_spec
, prop
, val
)
3540 Lisp_Object font_spec
, prop
, val
;
3544 CHECK_FONT_SPEC (font_spec
);
3545 idx
= get_font_prop_index (prop
);
3546 if (idx
>= 0 && idx
< FONT_EXTRA_INDEX
)
3547 ASET (font_spec
, idx
, font_prop_validate (idx
, Qnil
, val
));
3549 font_put_extra (font_spec
, prop
, font_prop_validate (0, prop
, val
));
3553 DEFUN ("list-fonts", Flist_fonts
, Slist_fonts
, 1, 4, 0,
3554 doc
: /* List available fonts matching FONT-SPEC on the current frame.
3555 Optional 2nd argument FRAME specifies the target frame.
3556 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
3557 Optional 4th argument PREFER, if non-nil, is a font-spec to
3558 control the order of the returned list. Fonts are sorted by
3559 how close they are to PREFER. */)
3560 (font_spec
, frame
, num
, prefer
)
3561 Lisp_Object font_spec
, frame
, num
, prefer
;
3563 Lisp_Object vec
, list
, tail
;
3567 frame
= selected_frame
;
3568 CHECK_LIVE_FRAME (frame
);
3569 CHECK_FONT_SPEC (font_spec
);
3577 if (! NILP (prefer
))
3578 CHECK_FONT_SPEC (prefer
);
3580 vec
= font_list_entities (frame
, font_spec
);
3585 return Fcons (AREF (vec
, 0), Qnil
);
3587 if (! NILP (prefer
))
3588 vec
= font_sort_entites (vec
, prefer
, frame
, font_spec
, 0);
3590 list
= tail
= Fcons (AREF (vec
, 0), Qnil
);
3591 if (n
== 0 || n
> len
)
3593 for (i
= 1; i
< n
; i
++)
3595 Lisp_Object val
= Fcons (AREF (vec
, i
), Qnil
);
3597 XSETCDR (tail
, val
);
3603 DEFUN ("font-family-list", Ffont_family_list
, Sfont_family_list
, 0, 1, 0,
3604 doc
: /* List available font families on the current frame.
3605 Optional argument FRAME, if non-nil, specifies the target frame. */)
3610 struct font_driver_list
*driver_list
;
3614 frame
= selected_frame
;
3615 CHECK_LIVE_FRAME (frame
);
3618 for (driver_list
= f
->font_driver_list
; driver_list
;
3619 driver_list
= driver_list
->next
)
3620 if (driver_list
->driver
->list_family
)
3622 Lisp_Object val
= driver_list
->driver
->list_family (frame
);
3628 Lisp_Object tail
= list
;
3630 for (; CONSP (val
); val
= XCDR (val
))
3631 if (NILP (Fmemq (XCAR (val
), tail
)))
3632 list
= Fcons (XCAR (val
), list
);
3638 DEFUN ("find-font", Ffind_font
, Sfind_font
, 1, 2, 0,
3639 doc
: /* Return a font-entity matching with FONT-SPEC on the current frame.
3640 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
3642 Lisp_Object font_spec
, frame
;
3644 Lisp_Object val
= Flist_fonts (font_spec
, frame
, make_number (1), Qnil
);
3651 DEFUN ("font-xlfd-name", Ffont_xlfd_name
, Sfont_xlfd_name
, 1, 2, 0,
3652 doc
: /* Return XLFD name of FONT.
3653 FONT is a font-spec, font-entity, or font-object.
3654 If the name is too long for XLFD (maximum 255 chars), return nil.
3655 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
3656 the consecutive wildcards are folded to one. */)
3657 (font
, fold_wildcards
)
3658 Lisp_Object font
, fold_wildcards
;
3665 if (FONT_OBJECT_P (font
))
3667 Lisp_Object font_name
= AREF (font
, FONT_NAME_INDEX
);
3669 if (STRINGP (font_name
)
3670 && SDATA (font_name
)[0] == '-')
3672 if (NILP (fold_wildcards
))
3674 strcpy (name
, (char *) SDATA (font_name
));
3677 pixel_size
= XFONT_OBJECT (font
)->pixel_size
;
3679 if (font_unparse_xlfd (font
, pixel_size
, name
, 256) < 0)
3682 if (! NILP (fold_wildcards
))
3684 char *p0
= name
, *p1
;
3686 while ((p1
= strstr (p0
, "-*-*")))
3688 strcpy (p1
, p1
+ 2);
3693 return build_string (name
);
3696 DEFUN ("clear-font-cache", Fclear_font_cache
, Sclear_font_cache
, 0, 0, 0,
3697 doc
: /* Clear font cache. */)
3700 Lisp_Object list
, frame
;
3702 FOR_EACH_FRAME (list
, frame
)
3704 FRAME_PTR f
= XFRAME (frame
);
3705 struct font_driver_list
*driver_list
= f
->font_driver_list
;
3707 for (; driver_list
; driver_list
= driver_list
->next
)
3708 if (driver_list
->on
)
3710 Lisp_Object cache
= driver_list
->driver
->get_cache (f
);
3715 && ! EQ (XCAR (XCAR (val
)), driver_list
->driver
->type
))
3717 font_assert (! NILP (val
));
3718 val
= XCDR (XCAR (val
));
3719 if (XINT (XCAR (val
)) == 0)
3721 font_clear_cache (f
, XCAR (val
), driver_list
->driver
);
3722 XSETCDR (cache
, XCDR (val
));
3730 /* The following three functions are still experimental. */
3732 DEFUN ("font-make-gstring", Ffont_make_gstring
, Sfont_make_gstring
, 2, 2, 0,
3733 doc
: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
3734 FONT-OBJECT may be nil if it is not yet known.
3736 G-string is sequence of glyphs of a specific font,
3737 and is a vector of this form:
3738 [ HEADER GLYPH ... ]
3739 HEADER is a vector of this form:
3740 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
3742 FONT-OBJECT is a font-object for all glyphs in the g-string,
3743 WIDTH thru DESCENT are the metrics (in pixels) of the whole G-string.
3744 GLYPH is a vector of this form:
3745 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
3746 [ [X-OFF Y-OFF WADJUST] | nil] ]
3748 FROM-IDX and TO-IDX are used internally and should not be touched.
3749 C is the character of the glyph.
3750 CODE is the glyph-code of C in FONT-OBJECT.
3751 WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
3752 X-OFF and Y-OFF are offests to the base position for the glyph.
3753 WADJUST is the adjustment to the normal width of the glyph. */)
3755 Lisp_Object font_object
, num
;
3757 Lisp_Object gstring
, g
;
3761 if (! NILP (font_object
))
3762 CHECK_FONT_OBJECT (font_object
);
3765 len
= XINT (num
) + 1;
3766 gstring
= Fmake_vector (make_number (len
), Qnil
);
3767 g
= Fmake_vector (make_number (6), Qnil
);
3768 ASET (g
, 0, font_object
);
3769 ASET (gstring
, 0, g
);
3770 for (i
= 1; i
< len
; i
++)
3771 ASET (gstring
, i
, Fmake_vector (make_number (10), Qnil
));
3775 DEFUN ("font-fill-gstring", Ffont_fill_gstring
, Sfont_fill_gstring
, 4, 5, 0,
3776 doc
: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
3777 START and END specify the region to extract characters.
3778 If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
3779 where to extract characters.
3780 FONT-OBJECT may be nil if GSTRING already contains one. */)
3781 (gstring
, font_object
, start
, end
, object
)
3782 Lisp_Object gstring
, font_object
, start
, end
, object
;
3788 CHECK_VECTOR (gstring
);
3789 if (NILP (font_object
))
3790 font_object
= LGSTRING_FONT (gstring
);
3791 font
= XFONT_OBJECT (font_object
);
3793 if (STRINGP (object
))
3795 const unsigned char *p
;
3797 CHECK_NATNUM (start
);
3799 if (XINT (start
) > XINT (end
)
3800 || XINT (end
) > ASIZE (object
)
3801 || XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
3802 args_out_of_range_3 (object
, start
, end
);
3804 len
= XINT (end
) - XINT (start
);
3805 p
= SDATA (object
) + string_char_to_byte (object
, XINT (start
));
3806 for (i
= 0; i
< len
; i
++)
3808 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3809 /* Shut up GCC warning in comparison with
3810 MOST_POSITIVE_FIXNUM below. */
3813 c
= STRING_CHAR_ADVANCE (p
);
3814 cod
= code
= font
->driver
->encode_char (font
, c
);
3815 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
3817 LGLYPH_SET_FROM (g
, i
);
3818 LGLYPH_SET_TO (g
, i
);
3819 LGLYPH_SET_CHAR (g
, c
);
3820 LGLYPH_SET_CODE (g
, code
);
3827 if (! NILP (object
))
3828 Fset_buffer (object
);
3829 validate_region (&start
, &end
);
3830 if (XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
3831 args_out_of_range (start
, end
);
3832 len
= XINT (end
) - XINT (start
);
3834 pos_byte
= CHAR_TO_BYTE (pos
);
3835 for (i
= 0; i
< len
; i
++)
3837 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3838 /* Shut up GCC warning in comparison with
3839 MOST_POSITIVE_FIXNUM below. */
3842 FETCH_CHAR_ADVANCE (c
, pos
, pos_byte
);
3843 cod
= code
= font
->driver
->encode_char (font
, c
);
3844 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
3846 LGLYPH_SET_FROM (g
, i
);
3847 LGLYPH_SET_TO (g
, i
);
3848 LGLYPH_SET_CHAR (g
, c
);
3849 LGLYPH_SET_CODE (g
, code
);
3852 for (; i
< LGSTRING_LENGTH (gstring
); i
++)
3853 LGSTRING_SET_GLYPH (gstring
, i
, Qnil
);
3857 DEFUN ("font-shape-text", Ffont_shape_text
, Sfont_shape_text
, 3, 4, 0,
3858 doc
: /* Shape text between FROM and TO by FONT-OBJECT.
3859 If optional 4th argument STRING is non-nil, it is a string to shape,
3860 and FROM and TO are indices to the string.
3861 The value is the end position of the text that can be shaped by
3863 (from
, to
, font_object
, string
)
3864 Lisp_Object from
, to
, font_object
, string
;
3867 struct font_metrics metrics
;
3868 EMACS_INT start
, end
;
3869 Lisp_Object gstring
, n
;
3872 if (! FONT_OBJECT_P (font_object
))
3874 font
= XFONT_OBJECT (font_object
);
3875 if (! font
->driver
->shape
)
3880 validate_region (&from
, &to
);
3881 start
= XFASTINT (from
);
3882 end
= XFASTINT (to
);
3883 modify_region (current_buffer
, start
, end
, 0);
3887 CHECK_STRING (string
);
3888 start
= XINT (from
);
3890 if (start
< 0 || start
> end
|| end
> SCHARS (string
))
3891 args_out_of_range_3 (string
, from
, to
);
3895 gstring
= Ffont_make_gstring (font_object
, make_number (len
));
3896 Ffont_fill_gstring (gstring
, font_object
, from
, to
, string
);
3898 /* Try at most three times with larger gstring each time. */
3899 for (i
= 0; i
< 3; i
++)
3901 Lisp_Object args
[2];
3903 n
= font
->driver
->shape (gstring
);
3907 args
[1] = Fmake_vector (make_number (len
), Qnil
);
3908 gstring
= Fvconcat (2, args
);
3910 if (! INTEGERP (n
) || XINT (n
) == 0)
3914 for (i
= 0; i
< len
;)
3917 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3918 EMACS_INT this_from
= LGLYPH_FROM (g
);
3919 EMACS_INT this_to
= LGLYPH_TO (g
) + 1;
3921 int need_composition
= 0;
3923 metrics
.lbearing
= LGLYPH_LBEARING (g
);
3924 metrics
.rbearing
= LGLYPH_RBEARING (g
);
3925 metrics
.ascent
= LGLYPH_ASCENT (g
);
3926 metrics
.descent
= LGLYPH_DESCENT (g
);
3927 if (NILP (LGLYPH_ADJUSTMENT (g
)))
3929 metrics
.width
= LGLYPH_WIDTH (g
);
3930 if (LGLYPH_CHAR (g
) == 0 || metrics
.width
== 0)
3931 need_composition
= 1;
3935 metrics
.width
= LGLYPH_WADJUST (g
);
3936 metrics
.lbearing
+= LGLYPH_XOFF (g
);
3937 metrics
.rbearing
+= LGLYPH_XOFF (g
);
3938 metrics
.ascent
-= LGLYPH_YOFF (g
);
3939 metrics
.descent
+= LGLYPH_YOFF (g
);
3940 need_composition
= 1;
3942 for (j
= i
+ 1; j
< len
; j
++)
3946 g
= LGSTRING_GLYPH (gstring
, j
);
3947 if (this_from
!= LGLYPH_FROM (g
))
3949 need_composition
= 1;
3950 x
= metrics
.width
+ LGLYPH_LBEARING (g
) + LGLYPH_XOFF (g
);
3951 if (metrics
.lbearing
> x
)
3952 metrics
.lbearing
= x
;
3953 x
= metrics
.width
+ LGLYPH_RBEARING (g
) + LGLYPH_XOFF (g
);
3954 if (metrics
.rbearing
< x
)
3955 metrics
.rbearing
= x
;
3956 x
= LGLYPH_ASCENT (g
) - LGLYPH_YOFF (g
);
3957 if (metrics
.ascent
< x
)
3959 x
= LGLYPH_DESCENT (g
) - LGLYPH_YOFF (g
);
3960 if (metrics
.descent
< x
)
3961 metrics
.descent
= x
;
3962 if (NILP (LGLYPH_ADJUSTMENT (g
)))
3963 metrics
.width
+= LGLYPH_WIDTH (g
);
3965 metrics
.width
+= LGLYPH_WADJUST (g
);
3968 if (need_composition
)
3970 gstr
= Ffont_make_gstring (font_object
, make_number (j
- i
));
3971 LGSTRING_SET_WIDTH (gstr
, metrics
.width
);
3972 LGSTRING_SET_LBEARING (gstr
, metrics
.lbearing
);
3973 LGSTRING_SET_RBEARING (gstr
, metrics
.rbearing
);
3974 LGSTRING_SET_ASCENT (gstr
, metrics
.ascent
);
3975 LGSTRING_SET_DESCENT (gstr
, metrics
.descent
);
3976 for (k
= i
; i
< j
; i
++)
3978 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3980 LGLYPH_SET_FROM (g
, LGLYPH_FROM (g
) - this_from
);
3981 LGLYPH_SET_TO (g
, LGLYPH_TO (g
) - this_from
);
3982 LGSTRING_SET_GLYPH (gstr
, i
- k
, LGSTRING_GLYPH (gstring
, i
));
3984 from
= make_number (start
+ this_from
);
3985 to
= make_number (start
+ this_to
);
3987 Fcompose_region_internal (from
, to
, gstr
, Qnil
);
3989 Fcompose_string_internal (string
, from
, to
, gstr
, Qnil
);
4000 DEFUN ("font-drive-otf", Ffont_drive_otf
, Sfont_drive_otf
, 6, 6, 0,
4001 doc
: /* Apply OpenType features on glyph-string GSTRING-IN.
4002 OTF-FEATURES specifies which features to apply in this format:
4003 (SCRIPT LANGSYS GSUB GPOS)
4005 SCRIPT is a symbol specifying a script tag of OpenType,
4006 LANGSYS is a symbol specifying a langsys tag of OpenType,
4007 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
4009 If LANGYS is nil, the default langsys is selected.
4011 The features are applied in the order they appear in the list. The
4012 symbol `*' means to apply all available features not present in this
4013 list, and the remaining features are ignored. For instance, (vatu
4014 pstf * haln) is to apply vatu and pstf in this order, then to apply
4015 all available features other than vatu, pstf, and haln.
4017 The features are applied to the glyphs in the range FROM and TO of
4018 the glyph-string GSTRING-IN.
4020 If some feature is actually applicable, the resulting glyphs are
4021 produced in the glyph-string GSTRING-OUT from the index INDEX. In
4022 this case, the value is the number of produced glyphs.
4024 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
4027 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
4028 produced in GSTRING-OUT, and the value is nil.
4030 See the documentation of `font-make-gstring' for the format of
4032 (otf_features
, gstring_in
, from
, to
, gstring_out
, index
)
4033 Lisp_Object otf_features
, gstring_in
, from
, to
, gstring_out
, index
;
4035 Lisp_Object font_object
= LGSTRING_FONT (gstring_in
);
4040 check_otf_features (otf_features
);
4041 CHECK_FONT_OBJECT (font_object
);
4042 font
= XFONT_OBJECT (font_object
);
4043 if (! font
->driver
->otf_drive
)
4044 error ("Font backend %s can't drive OpenType GSUB table",
4045 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4046 CHECK_CONS (otf_features
);
4047 CHECK_SYMBOL (XCAR (otf_features
));
4048 val
= XCDR (otf_features
);
4049 CHECK_SYMBOL (XCAR (val
));
4050 val
= XCDR (otf_features
);
4053 len
= check_gstring (gstring_in
);
4054 CHECK_VECTOR (gstring_out
);
4055 CHECK_NATNUM (from
);
4057 CHECK_NATNUM (index
);
4059 if (XINT (from
) >= XINT (to
) || XINT (to
) > len
)
4060 args_out_of_range_3 (from
, to
, make_number (len
));
4061 if (XINT (index
) >= ASIZE (gstring_out
))
4062 args_out_of_range (index
, make_number (ASIZE (gstring_out
)));
4063 num
= font
->driver
->otf_drive (font
, otf_features
,
4064 gstring_in
, XINT (from
), XINT (to
),
4065 gstring_out
, XINT (index
), 0);
4068 return make_number (num
);
4071 DEFUN ("font-otf-alternates", Ffont_otf_alternates
, Sfont_otf_alternates
,
4073 doc
: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4074 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4076 (SCRIPT LANGSYS FEATURE ...)
4077 See the documentation of `font-drive-otf' for more detail.
4079 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4080 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4081 character code corresponding to the glyph or nil if there's no
4082 corresponding character. */)
4083 (font_object
, character
, otf_features
)
4084 Lisp_Object font_object
, character
, otf_features
;
4087 Lisp_Object gstring_in
, gstring_out
, g
;
4088 Lisp_Object alternates
;
4091 CHECK_FONT_GET_OBJECT (font_object
, font
);
4092 if (! font
->driver
->otf_drive
)
4093 error ("Font backend %s can't drive OpenType GSUB table",
4094 SDATA (SYMBOL_NAME (font
->driver
->type
)));
4095 CHECK_CHARACTER (character
);
4096 CHECK_CONS (otf_features
);
4098 gstring_in
= Ffont_make_gstring (font_object
, make_number (1));
4099 g
= LGSTRING_GLYPH (gstring_in
, 0);
4100 LGLYPH_SET_CHAR (g
, XINT (character
));
4101 gstring_out
= Ffont_make_gstring (font_object
, make_number (10));
4102 while ((num
= font
->driver
->otf_drive (font
, otf_features
, gstring_in
, 0, 1,
4103 gstring_out
, 0, 1)) < 0)
4104 gstring_out
= Ffont_make_gstring (font_object
,
4105 make_number (ASIZE (gstring_out
) * 2));
4107 for (i
= 0; i
< num
; i
++)
4109 Lisp_Object g
= LGSTRING_GLYPH (gstring_out
, i
);
4110 int c
= LGLYPH_CHAR (g
);
4111 unsigned code
= LGLYPH_CODE (g
);
4113 alternates
= Fcons (Fcons (make_number (code
),
4114 c
> 0 ? make_number (c
) : Qnil
),
4117 return Fnreverse (alternates
);
4123 DEFUN ("open-font", Fopen_font
, Sopen_font
, 1, 3, 0,
4124 doc
: /* Open FONT-ENTITY. */)
4125 (font_entity
, size
, frame
)
4126 Lisp_Object font_entity
;
4132 CHECK_FONT_ENTITY (font_entity
);
4134 frame
= selected_frame
;
4135 CHECK_LIVE_FRAME (frame
);
4138 isize
= XINT (AREF (font_entity
, FONT_SIZE_INDEX
));
4141 CHECK_NUMBER_OR_FLOAT (size
);
4143 isize
= POINT_TO_PIXEL (- isize
, XFRAME (frame
)->resy
);
4145 isize
= XINT (size
);
4149 return font_open_entity (XFRAME (frame
), font_entity
, isize
);
4152 DEFUN ("close-font", Fclose_font
, Sclose_font
, 1, 2, 0,
4153 doc
: /* Close FONT-OBJECT. */)
4154 (font_object
, frame
)
4155 Lisp_Object font_object
, frame
;
4157 CHECK_FONT_OBJECT (font_object
);
4159 frame
= selected_frame
;
4160 CHECK_LIVE_FRAME (frame
);
4161 font_close_object (XFRAME (frame
), font_object
);
4165 DEFUN ("query-font", Fquery_font
, Squery_font
, 1, 1, 0,
4166 doc
: /* Return information about FONT-OBJECT.
4167 The value is a vector:
4168 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4171 NAME is a string of the font name (or nil if the font backend doesn't
4174 FILENAME is a string of the font file (or nil if the font backend
4175 doesn't provide a file name).
4177 PIXEL-SIZE is a pixel size by which the font is opened.
4179 SIZE is a maximum advance width of the font in pixels.
4181 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4184 CAPABILITY is a list whose first element is a symbol representing the
4185 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4186 remaining elements describe the details of the font capability.
4188 If the font is OpenType font, the form of the list is
4189 \(opentype GSUB GPOS)
4190 where GSUB shows which "GSUB" features the font supports, and GPOS
4191 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4192 lists of the format:
4193 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4195 If the font is not OpenType font, currently the length of the form is
4198 SCRIPT is a symbol representing OpenType script tag.
4200 LANGSYS is a symbol representing OpenType langsys tag, or nil
4201 representing the default langsys.
4203 FEATURE is a symbol representing OpenType feature tag.
4205 If the font is not OpenType font, CAPABILITY is nil. */)
4207 Lisp_Object font_object
;
4212 CHECK_FONT_GET_OBJECT (font_object
, font
);
4214 val
= Fmake_vector (make_number (9), Qnil
);
4215 ASET (val
, 0, AREF (font_object
, FONT_NAME_INDEX
));
4216 ASET (val
, 1, AREF (font_object
, FONT_FILE_INDEX
));
4217 ASET (val
, 2, make_number (font
->pixel_size
));
4218 ASET (val
, 3, make_number (font
->max_width
));
4219 ASET (val
, 4, make_number (font
->ascent
));
4220 ASET (val
, 5, make_number (font
->descent
));
4221 ASET (val
, 6, make_number (font
->space_width
));
4222 ASET (val
, 7, make_number (font
->average_width
));
4223 if (font
->driver
->otf_capability
)
4224 ASET (val
, 8, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
4228 DEFUN ("get-font-glyphs", Fget_font_glyphs
, Sget_font_glyphs
, 2, 2, 0,
4229 doc
: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
4230 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
4231 (font_object
, string
)
4232 Lisp_Object font_object
, string
;
4238 CHECK_FONT_GET_OBJECT (font_object
, font
);
4239 CHECK_STRING (string
);
4240 len
= SCHARS (string
);
4241 vec
= Fmake_vector (make_number (len
), Qnil
);
4242 for (i
= 0; i
< len
; i
++)
4244 Lisp_Object ch
= Faref (string
, make_number (i
));
4249 struct font_metrics metrics
;
4251 cod
= code
= font
->driver
->encode_char (font
, c
);
4252 if (code
== FONT_INVALID_CODE
)
4254 val
= Fmake_vector (make_number (6), Qnil
);
4255 if (cod
<= MOST_POSITIVE_FIXNUM
)
4256 ASET (val
, 0, make_number (code
));
4258 ASET (val
, 0, Fcons (make_number (code
>> 16),
4259 make_number (code
& 0xFFFF)));
4260 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4261 ASET (val
, 1, make_number (metrics
.lbearing
));
4262 ASET (val
, 2, make_number (metrics
.rbearing
));
4263 ASET (val
, 3, make_number (metrics
.width
));
4264 ASET (val
, 4, make_number (metrics
.ascent
));
4265 ASET (val
, 5, make_number (metrics
.descent
));
4271 DEFUN ("font-match-p", Ffont_match_p
, Sfont_match_p
, 2, 2, 0,
4272 doc
: /* Return t if and only if font-spec SPEC matches with FONT.
4273 FONT is a font-spec, font-entity, or font-object. */)
4275 Lisp_Object spec
, font
;
4277 CHECK_FONT_SPEC (spec
);
4280 return (font_match_p (spec
, font
) ? Qt
: Qnil
);
4283 DEFUN ("font-at", Ffont_at
, Sfont_at
, 1, 3, 0,
4284 doc
: /* Return a font-object for displaying a character at POSITION.
4285 Optional second arg WINDOW, if non-nil, is a window displaying
4286 the current buffer. It defaults to the currently selected window. */)
4287 (position
, window
, string
)
4288 Lisp_Object position
, window
, string
;
4295 CHECK_NUMBER_COERCE_MARKER (position
);
4296 pos
= XINT (position
);
4297 if (pos
< BEGV
|| pos
>= ZV
)
4298 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
4302 CHECK_NUMBER (position
);
4303 CHECK_STRING (string
);
4304 pos
= XINT (position
);
4305 if (pos
< 0 || pos
>= SCHARS (string
))
4306 args_out_of_range (string
, position
);
4309 window
= selected_window
;
4310 CHECK_LIVE_WINDOW (window
);
4311 w
= XWINDOW (window
);
4313 return font_at (-1, pos
, NULL
, w
, string
);
4317 DEFUN ("draw-string", Fdraw_string
, Sdraw_string
, 2, 2, 0,
4318 doc
: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4319 The value is a number of glyphs drawn.
4320 Type C-l to recover what previously shown. */)
4321 (font_object
, string
)
4322 Lisp_Object font_object
, string
;
4324 Lisp_Object frame
= selected_frame
;
4325 FRAME_PTR f
= XFRAME (frame
);
4331 CHECK_FONT_GET_OBJECT (font_object
, font
);
4332 CHECK_STRING (string
);
4333 len
= SCHARS (string
);
4334 code
= alloca (sizeof (unsigned) * len
);
4335 for (i
= 0; i
< len
; i
++)
4337 Lisp_Object ch
= Faref (string
, make_number (i
));
4341 code
[i
] = font
->driver
->encode_char (font
, c
);
4342 if (code
[i
] == FONT_INVALID_CODE
)
4345 face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4347 if (font
->driver
->prepare_face
)
4348 font
->driver
->prepare_face (f
, face
);
4349 width
= font
->driver
->text_extents (font
, code
, i
, NULL
);
4350 len
= font
->driver
->draw_text (f
, face
, 0, font
->ascent
, code
, i
, width
);
4351 if (font
->driver
->done_face
)
4352 font
->driver
->done_face (f
, face
);
4354 return make_number (len
);
4358 #endif /* FONT_DEBUG */
4360 #ifdef HAVE_WINDOW_SYSTEM
4362 DEFUN ("font-info", Ffont_info
, Sfont_info
, 1, 2, 0,
4363 doc
: /* Return information about a font named NAME on frame FRAME.
4364 If FRAME is omitted or nil, use the selected frame.
4365 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
4366 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
4368 OPENED-NAME is the name used for opening the font,
4369 FULL-NAME is the full name of the font,
4370 SIZE is the maximum bound width of the font,
4371 HEIGHT is the height of the font,
4372 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
4373 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
4374 how to compose characters.
4375 If the named font is not yet loaded, return nil. */)
4377 Lisp_Object name
, frame
;
4382 Lisp_Object font_object
;
4384 (*check_window_system_func
) ();
4387 CHECK_STRING (name
);
4389 frame
= selected_frame
;
4390 CHECK_LIVE_FRAME (frame
);
4395 int fontset
= fs_query_fontset (name
, 0);
4398 name
= fontset_ascii (fontset
);
4399 font_object
= font_open_by_name (f
, (char *) SDATA (name
));
4401 else if (FONT_OBJECT_P (name
))
4403 else if (FONT_ENTITY_P (name
))
4404 font_object
= font_open_entity (f
, name
, 0);
4407 struct face
*face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4408 Lisp_Object entity
= font_matching_entity (f
, face
->lface
, name
);
4410 font_object
= ! NILP (entity
) ? font_open_entity (f
, entity
, 0) : Qnil
;
4412 if (NILP (font_object
))
4414 font
= XFONT_OBJECT (font_object
);
4416 info
= Fmake_vector (make_number (7), Qnil
);
4417 XVECTOR (info
)->contents
[0] = AREF (font_object
, FONT_NAME_INDEX
);
4418 XVECTOR (info
)->contents
[1] = AREF (font_object
, FONT_NAME_INDEX
);
4419 XVECTOR (info
)->contents
[2] = make_number (font
->pixel_size
);
4420 XVECTOR (info
)->contents
[3] = make_number (font
->height
);
4421 XVECTOR (info
)->contents
[4] = make_number (font
->baseline_offset
);
4422 XVECTOR (info
)->contents
[5] = make_number (font
->relative_compose
);
4423 XVECTOR (info
)->contents
[6] = make_number (font
->default_ascent
);
4426 /* As font_object is still in FONT_OBJLIST of the entity, we can't
4427 close it now. Perhaps, we should manage font-objects
4428 by `reference-count'. */
4429 font_close_object (f
, font_object
);
4436 #define BUILD_STYLE_TABLE(TBL) \
4437 build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
4440 build_style_table (entry
, nelement
)
4441 struct table_entry
*entry
;
4445 Lisp_Object table
, elt
;
4447 table
= Fmake_vector (make_number (nelement
), Qnil
);
4448 for (i
= 0; i
< nelement
; i
++)
4450 for (j
= 0; entry
[i
].names
[j
]; j
++);
4451 elt
= Fmake_vector (make_number (j
+ 1), Qnil
);
4452 ASET (elt
, 0, make_number (entry
[i
].numeric
));
4453 for (j
= 0; entry
[i
].names
[j
]; j
++)
4454 ASET (elt
, j
+ 1, intern (entry
[i
].names
[j
]));
4455 ASET (table
, i
, elt
);
4460 static Lisp_Object Vfont_log
;
4461 static int font_log_env_checked
;
4464 font_add_log (action
, arg
, result
)
4466 Lisp_Object arg
, result
;
4468 Lisp_Object tail
, val
;
4471 if (! font_log_env_checked
)
4473 Vfont_log
= egetenv ("EMACS_FONT_LOG") ? Qnil
: Qt
;
4474 font_log_env_checked
= 1;
4476 if (EQ (Vfont_log
, Qt
))
4479 arg
= Ffont_xlfd_name (arg
, Qt
);
4481 result
= Ffont_xlfd_name (result
, Qt
);
4482 else if (CONSP (result
))
4484 result
= Fcopy_sequence (result
);
4485 for (tail
= result
; CONSP (tail
); tail
= XCDR (tail
))
4489 val
= Ffont_xlfd_name (val
, Qt
);
4490 XSETCAR (tail
, val
);
4493 else if (VECTORP (result
))
4495 result
= Fcopy_sequence (result
);
4496 for (i
= 0; i
< ASIZE (result
); i
++)
4498 val
= AREF (result
, i
);
4500 val
= Ffont_xlfd_name (val
, Qt
);
4501 ASET (result
, i
, val
);
4504 Vfont_log
= Fcons (list3 (intern (action
), arg
, result
), Vfont_log
);
4507 extern void syms_of_ftfont
P_ (());
4508 extern void syms_of_xfont
P_ (());
4509 extern void syms_of_xftfont
P_ (());
4510 extern void syms_of_ftxfont
P_ (());
4511 extern void syms_of_bdffont
P_ (());
4512 extern void syms_of_w32font
P_ (());
4513 extern void syms_of_atmfont
P_ (());
4518 sort_shift_bits
[FONT_SLANT_INDEX
] = 0;
4519 sort_shift_bits
[FONT_WEIGHT_INDEX
] = 7;
4520 sort_shift_bits
[FONT_SIZE_INDEX
] = 14;
4521 sort_shift_bits
[FONT_WIDTH_INDEX
] = 21;
4522 sort_shift_bits
[FONT_ADSTYLE_INDEX
] = 28;
4523 sort_shift_bits
[FONT_FOUNDRY_INDEX
] = 29;
4524 sort_shift_bits
[FONT_FAMILY_INDEX
] = 30;
4525 /* Note that sort_shift_bits[FONT_SORT_TYPE] and
4526 sort_shift_bits[FONT_SORT_REGISTRY] are never used. */
4528 staticpro (&font_charset_alist
);
4529 font_charset_alist
= Qnil
;
4531 DEFSYM (Qfont_spec
, "font-spec");
4532 DEFSYM (Qfont_entity
, "font-entity");
4533 DEFSYM (Qfont_object
, "font-object");
4535 DEFSYM (Qopentype
, "opentype");
4537 DEFSYM (Qascii_0
, "ascii-0");
4538 DEFSYM (Qiso8859_1
, "iso8859-1");
4539 DEFSYM (Qiso10646_1
, "iso10646-1");
4540 DEFSYM (Qunicode_bmp
, "unicode-bmp");
4541 DEFSYM (Qunicode_sip
, "unicode-sip");
4543 DEFSYM (QCotf
, ":otf");
4544 DEFSYM (QClang
, ":lang");
4545 DEFSYM (QCscript
, ":script");
4546 DEFSYM (QCantialias
, ":antialias");
4548 DEFSYM (QCfoundry
, ":foundry");
4549 DEFSYM (QCadstyle
, ":adstyle");
4550 DEFSYM (QCregistry
, ":registry");
4551 DEFSYM (QCspacing
, ":spacing");
4552 DEFSYM (QCdpi
, ":dpi");
4553 DEFSYM (QCscalable
, ":scalable");
4554 DEFSYM (QCavgwidth
, ":avgwidth");
4555 DEFSYM (QCfont_entity
, ":font-entity");
4556 DEFSYM (QCfc_unknown_spec
, ":fc-unknown-spec");
4563 staticpro (&null_vector
);
4564 null_vector
= Fmake_vector (make_number (0), Qnil
);
4566 staticpro (&scratch_font_spec
);
4567 scratch_font_spec
= Ffont_spec (0, NULL
);
4568 staticpro (&scratch_font_prefer
);
4569 scratch_font_prefer
= Ffont_spec (0, NULL
);
4573 staticpro (&otf_list
);
4575 #endif /* HAVE_LIBOTF */
4579 defsubr (&Sfont_spec
);
4580 defsubr (&Sfont_get
);
4581 defsubr (&Sfont_put
);
4582 defsubr (&Slist_fonts
);
4583 defsubr (&Sfont_family_list
);
4584 defsubr (&Sfind_font
);
4585 defsubr (&Sfont_xlfd_name
);
4586 defsubr (&Sclear_font_cache
);
4587 defsubr (&Sfont_make_gstring
);
4588 defsubr (&Sfont_fill_gstring
);
4589 defsubr (&Sfont_shape_text
);
4591 defsubr (&Sfont_drive_otf
);
4592 defsubr (&Sfont_otf_alternates
);
4596 defsubr (&Sopen_font
);
4597 defsubr (&Sclose_font
);
4598 defsubr (&Squery_font
);
4599 defsubr (&Sget_font_glyphs
);
4600 defsubr (&Sfont_match_p
);
4601 defsubr (&Sfont_at
);
4603 defsubr (&Sdraw_string
);
4605 #endif /* FONT_DEBUG */
4606 #ifdef HAVE_WINDOW_SYSTEM
4607 defsubr (&Sfont_info
);
4610 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist
,
4612 Alist of fontname patterns vs the corresponding encoding and repertory info.
4613 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
4614 where ENCODING is a charset or a char-table,
4615 and REPERTORY is a charset, a char-table, or nil.
4617 If ENCODING and REPERTORY are the same, the element can have the form
4618 \(REGEXP . ENCODING).
4620 ENCODING is for converting a character to a glyph code of the font.
4621 If ENCODING is a charset, encoding a character by the charset gives
4622 the corresponding glyph code. If ENCODING is a char-table, looking up
4623 the table by a character gives the corresponding glyph code.
4625 REPERTORY specifies a repertory of characters supported by the font.
4626 If REPERTORY is a charset, all characters beloging to the charset are
4627 supported. If REPERTORY is a char-table, all characters who have a
4628 non-nil value in the table are supported. If REPERTORY is nil, Emacs
4629 gets the repertory information by an opened font and ENCODING. */);
4630 Vfont_encoding_alist
= Qnil
;
4632 DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table
,
4633 doc
: /* Vector of valid font weight values.
4634 Each element has the form:
4635 [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
4636 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symobls. */);
4637 Vfont_weight_table
= BUILD_STYLE_TABLE (weight_table
);
4639 DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table
,
4640 doc
: /* Vector of font slant symbols vs the corresponding numeric values.
4641 See `font-weight_table' for the format of the vector. */);
4642 Vfont_slant_table
= BUILD_STYLE_TABLE (slant_table
);
4644 DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table
,
4645 doc
: /* Alist of font width symbols vs the corresponding numeric values.
4646 See `font-weight_table' for the format of the vector. */);
4647 Vfont_width_table
= BUILD_STYLE_TABLE (width_table
);
4649 staticpro (&font_style_table
);
4650 font_style_table
= Fmake_vector (make_number (3), Qnil
);
4651 ASET (font_style_table
, 0, Vfont_weight_table
);
4652 ASET (font_style_table
, 1, Vfont_slant_table
);
4653 ASET (font_style_table
, 2, Vfont_width_table
);
4655 DEFVAR_LISP ("font-log", &Vfont_log
, doc
: /*
4656 *Logging list of font related actions and results.
4657 The value t means to suppress the logging.
4658 The initial value is set to nil if the environment variable
4659 EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
4662 #ifdef HAVE_WINDOW_SYSTEM
4663 #ifdef HAVE_FREETYPE
4665 #ifdef HAVE_X_WINDOWS
4670 #endif /* HAVE_XFT */
4671 #endif /* HAVE_X_WINDOWS */
4672 #else /* not HAVE_FREETYPE */
4673 #ifdef HAVE_X_WINDOWS
4675 #endif /* HAVE_X_WINDOWS */
4676 #endif /* not HAVE_FREETYPE */
4679 #endif /* HAVE_BDFFONT */
4682 #endif /* WINDOWSNT */
4686 #endif /* HAVE_WINDOW_SYSTEM */
4689 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
4690 (do not change this comment) */