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, or (at your option)
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; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
36 #include "dispextern.h"
38 #include "character.h"
39 #include "composite.h"
45 #endif /* HAVE_X_WINDOWS */
49 #endif /* HAVE_NTGUI */
61 #define xassert(X) do {if (!(X)) abort ();} while (0)
63 #define xassert(X) (void) 0
66 int enable_font_backend
;
68 Lisp_Object Qopentype
;
70 /* Important character set symbols. */
71 Lisp_Object Qiso8859_1
, Qiso10646_1
, Qunicode_bmp
, Qunicode_sip
;
73 /* Like CHECK_FONT_SPEC but also validate properties of the font-spec,
74 and set X to the validated result. */
76 #define CHECK_VALIDATE_FONT_SPEC(x) \
78 if (! FONT_SPEC_P (x)) wrong_type_argument (Qfont, x); \
79 x = font_prop_validate (x); \
82 /* Number of pt per inch (from the TeXbook). */
83 #define PT_PER_INCH 72.27
85 /* Return a pixel size (integer) corresponding to POINT size (double)
87 #define POINT_TO_PIXEL(POINT, DPI) ((POINT) * (DPI) / PT_PER_INCH + 0.5)
89 /* Return a point size (double) corresponding to POINT size (integer)
91 #define PIXEL_TO_POINT(PIXEL, DPI) ((PIXEL) * PT_PER_INCH * 10 / (DPI) + 0.5)
93 /* Special string of zero length. It is used to specify a NULL name
94 in a font properties (e.g. adstyle). We don't use the symbol of
95 NULL name because it's confusing (Lisp printer prints nothing for
97 Lisp_Object null_string
;
99 /* Special vector of zero length. This is repeatedly used by (struct
100 font_driver *)->list when a specified font is not found. */
101 Lisp_Object null_vector
;
103 /* Vector of 3 elements. Each element is an alist for one of font
104 style properties (weight, slant, width). Each alist contains a
105 mapping between symbolic property values (e.g. `medium' for weight)
106 and numeric property values (e.g. 100). So, it looks like this:
107 [((thin . 0) ... (heavy . 210))
108 ((ro . 0) ... (ot . 210))
109 ((ultracondensed . 50) ... (wide . 200))] */
110 static Lisp_Object font_style_table
;
112 /* Alist of font family vs the corresponding aliases.
113 Each element has this form:
114 (FAMILY ALIAS1 ALIAS2 ...) */
116 static Lisp_Object font_family_alist
;
118 /* Symbols representing keys of normal font properties. */
119 extern Lisp_Object QCtype
, QCfamily
, QCweight
, QCslant
, QCwidth
, QCsize
, QCname
;
120 Lisp_Object QCfoundry
, QCadstyle
, QCregistry
, QCextra
;
121 /* Symbols representing keys of font extra info. */
122 Lisp_Object QCspacing
, QCdpi
, QCscalable
, QCotf
, QClanguage
, QCscript
;
123 Lisp_Object QCantialias
;
124 /* Symbols representing values of font spacing property. */
125 Lisp_Object Qc
, Qm
, Qp
, Qd
;
127 /* Alist of font registry symbol and the corresponding charsets
128 information. The information is retrieved from
129 Vfont_encoding_alist on demand.
131 Eash element has the form:
132 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
136 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
137 encodes a character code to a glyph code of a font, and
138 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
139 character is supported by a font.
141 The latter form means that the information for REGISTRY couldn't be
143 static Lisp_Object font_charset_alist
;
145 /* List of all font drivers. Each font-backend (XXXfont.c) calls
146 register_font_driver in syms_of_XXXfont to register its font-driver
148 static struct font_driver_list
*font_driver_list
;
150 static int font_pixel_size
P_ ((FRAME_PTR f
, Lisp_Object
));
151 static Lisp_Object prop_name_to_numeric
P_ ((enum font_property_index
,
153 static Lisp_Object prop_numeric_to_name
P_ ((enum font_property_index
, int));
154 static Lisp_Object font_open_entity
P_ ((FRAME_PTR
, Lisp_Object
, int));
155 static void build_font_family_alist
P_ ((void));
157 /* Number of registered font drivers. */
158 static int num_font_drivers
;
160 /* Return a pixel size of font-spec SPEC on frame F. */
163 font_pixel_size (f
, spec
)
167 Lisp_Object size
= AREF (spec
, FONT_SIZE_INDEX
);
170 Lisp_Object extra
, val
;
176 point_size
= XFLOAT_DATA (size
);
177 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
178 val
= assq_no_quit (QCdpi
, extra
);
181 if (INTEGERP (XCDR (val
)))
182 dpi
= XINT (XCDR (val
));
184 dpi
= XFLOAT_DATA (XCDR (val
)) + 0.5;
188 pixel_size
= POINT_TO_PIXEL (point_size
, dpi
);
192 /* Return a numeric value corresponding to PROP's NAME (symbol). If
193 NAME is not registered in font_style_table, return Qnil. PROP must
194 be one of FONT_{WEIGHT|SLANT|SWIDTH}_INDEX. */
197 prop_name_to_numeric (prop
, name
)
198 enum font_property_index prop
;
201 int table_index
= prop
- FONT_WEIGHT_INDEX
;
204 val
= assq_no_quit (name
, AREF (font_style_table
, table_index
));
205 return (NILP (val
) ? Qnil
: XCDR (val
));
209 /* Return a name (symbol) corresponding to PROP's NUMERIC value. If
210 no name is registered for NUMERIC in font_style_table, return a
211 symbol of integer name (e.g. `123'). PROP must be one of
212 FONT_{WEIGHT|SLANT|SWIDTH}_INDEX. */
215 prop_numeric_to_name (prop
, numeric
)
216 enum font_property_index prop
;
219 int table_index
= prop
- FONT_WEIGHT_INDEX
;
220 Lisp_Object table
= AREF (font_style_table
, table_index
);
223 while (! NILP (table
))
225 if (XINT (XCDR (XCAR (table
))) >= numeric
)
227 if (XINT (XCDR (XCAR (table
))) == numeric
)
228 return XCAR (XCAR (table
));
232 table
= XCDR (table
);
234 sprintf (buf
, "%d", numeric
);
239 /* Return a symbol whose name is STR (length LEN). If STR contains
240 uppercase letters, downcase them in advance. */
243 intern_downcase (str
, len
)
250 for (i
= 0; i
< len
; i
++)
251 if (isupper (str
[i
]))
254 return Fintern (make_unibyte_string (str
, len
), Qnil
);
257 return Fintern (null_string
, Qnil
);
258 bcopy (str
, buf
, len
);
260 if (isascii (buf
[i
]))
261 buf
[i
] = tolower (buf
[i
]);
262 return Fintern (make_unibyte_string (buf
, len
), Qnil
);
265 extern Lisp_Object Vface_alternative_font_family_alist
;
267 /* Setup font_family_alist of the form:
268 ((FAMILY-SYMBOL ALIAS-SYMBOL ...) ...)
269 from Vface_alternative_font_family_alist of the form:
270 ((FAMILY-STRING ALIAS-STRING ...) ...) */
273 build_font_family_alist ()
275 Lisp_Object alist
= Vface_alternative_font_family_alist
;
277 for (; CONSP (alist
); alist
= XCDR (alist
))
279 Lisp_Object tail
, elt
;
281 for (tail
= XCAR (alist
), elt
= Qnil
; CONSP (tail
); tail
= XCDR (tail
))
282 elt
= nconc2 (elt
, Fcons (Fintern (XCAR (tail
), Qnil
), Qnil
));
283 font_family_alist
= Fcons (elt
, font_family_alist
);
287 extern Lisp_Object find_font_encoding
P_ ((Lisp_Object
));
289 /* Return encoding charset and repertory charset for REGISTRY in
290 ENCODING and REPERTORY correspondingly. If correct information for
291 REGISTRY is available, return 0. Otherwise return -1. */
294 font_registry_charsets (registry
, encoding
, repertory
)
295 Lisp_Object registry
;
296 struct charset
**encoding
, **repertory
;
299 int encoding_id
, repertory_id
;
301 val
= assq_no_quit (registry
, font_charset_alist
);
307 encoding_id
= XINT (XCAR (val
));
308 repertory_id
= XINT (XCDR (val
));
312 val
= find_font_encoding (SYMBOL_NAME (registry
));
313 if (SYMBOLP (val
) && CHARSETP (val
))
315 encoding_id
= repertory_id
= XINT (CHARSET_SYMBOL_ID (val
));
317 else if (CONSP (val
))
319 if (! CHARSETP (XCAR (val
)))
321 encoding_id
= XINT (CHARSET_SYMBOL_ID (XCAR (val
)));
322 if (NILP (XCDR (val
)))
326 if (! CHARSETP (XCDR (val
)))
328 repertory_id
= XINT (CHARSET_SYMBOL_ID (XCDR (val
)));
333 val
= Fcons (make_number (encoding_id
), make_number (repertory_id
));
335 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, val
), Qnil
));
339 *encoding
= CHARSET_FROM_ID (encoding_id
);
341 *repertory
= repertory_id
>= 0 ? CHARSET_FROM_ID (repertory_id
) : NULL
;
346 = nconc2 (font_charset_alist
, Fcons (Fcons (registry
, Qnil
), Qnil
));
351 /* Font property value validaters. See the comment of
352 font_property_table for the meaning of the arguments. */
354 static Lisp_Object font_prop_validate_symbol
P_ ((Lisp_Object
, Lisp_Object
));
355 static Lisp_Object font_prop_validate_style
P_ ((Lisp_Object
, Lisp_Object
));
356 static Lisp_Object font_prop_validate_non_neg
P_ ((Lisp_Object
, Lisp_Object
));
357 static Lisp_Object font_prop_validate_spacing
P_ ((Lisp_Object
, Lisp_Object
));
358 static int get_font_prop_index
P_ ((Lisp_Object
, int));
359 static Lisp_Object font_prop_validate
P_ ((Lisp_Object
));
362 font_prop_validate_symbol (prop
, val
)
363 Lisp_Object prop
, val
;
365 if (EQ (prop
, QCotf
))
366 return (SYMBOLP (val
) ? val
: Qerror
);
368 val
= (SCHARS (val
) == 0 ? null_string
369 : intern_downcase ((char *) SDATA (val
), SBYTES (val
)));
370 else if (SYMBOLP (val
))
372 if (SCHARS (SYMBOL_NAME (val
)) == 0)
381 font_prop_validate_style (prop
, val
)
382 Lisp_Object prop
, val
;
384 if (! INTEGERP (val
))
387 val
= intern_downcase ((char *) SDATA (val
), SBYTES (val
));
392 enum font_property_index prop_index
393 = (EQ (prop
, QCweight
) ? FONT_WEIGHT_INDEX
394 : EQ (prop
, QCslant
) ? FONT_SLANT_INDEX
397 val
= prop_name_to_numeric (prop_index
, val
);
406 font_prop_validate_non_neg (prop
, val
)
407 Lisp_Object prop
, val
;
409 return (NATNUMP (val
) || (FLOATP (val
) && XFLOAT_DATA (val
) >= 0)
414 font_prop_validate_spacing (prop
, val
)
415 Lisp_Object prop
, val
;
417 if (NILP (val
) || (NATNUMP (val
) && XINT (val
) <= FONT_SPACING_CHARCELL
))
420 return make_number (FONT_SPACING_CHARCELL
);
422 return make_number (FONT_SPACING_MONO
);
424 return make_number (FONT_SPACING_PROPORTIONAL
);
429 font_prop_validate_otf (prop
, val
)
430 Lisp_Object prop
, val
;
432 Lisp_Object tail
, tmp
;
435 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
436 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
437 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
440 if (! SYMBOLP (XCAR (val
)))
445 if (! CONSP (tail
) || ! SYMBOLP (XCAR (val
)))
447 for (i
= 0; i
< 2; i
++)
454 for (tmp
= XCAR (tail
); CONSP (tmp
); tmp
= XCDR (tmp
))
455 if (! SYMBOLP (XCAR (tmp
)))
463 /* Structure of known font property keys and validater of the
467 /* Pointer to the key symbol. */
469 /* Function to validate PROP's value VAL, or NULL if any value is
470 ok. The value is VAL or its regularized value if VAL is valid,
471 and Qerror if not. */
472 Lisp_Object (*validater
) P_ ((Lisp_Object prop
, Lisp_Object val
));
473 } font_property_table
[] =
474 { { &QCtype
, font_prop_validate_symbol
},
475 { &QCfoundry
, font_prop_validate_symbol
},
476 { &QCfamily
, font_prop_validate_symbol
},
477 { &QCadstyle
, font_prop_validate_symbol
},
478 { &QCregistry
, font_prop_validate_symbol
},
479 { &QCweight
, font_prop_validate_style
},
480 { &QCslant
, font_prop_validate_style
},
481 { &QCwidth
, font_prop_validate_style
},
482 { &QCsize
, font_prop_validate_non_neg
},
483 { &QClanguage
, font_prop_validate_symbol
},
484 { &QCscript
, font_prop_validate_symbol
},
485 { &QCdpi
, font_prop_validate_non_neg
},
486 { &QCspacing
, font_prop_validate_spacing
},
487 { &QCscalable
, NULL
},
488 { &QCotf
, font_prop_validate_otf
},
489 { &QCantialias
, font_prop_validate_symbol
}
492 /* Size (number of elements) of the above table. */
493 #define FONT_PROPERTY_TABLE_SIZE \
494 ((sizeof font_property_table) / (sizeof *font_property_table))
496 /* Return an index number of font property KEY or -1 if KEY is not an
497 already known property. Start searching font_property_table from
498 index FROM (which is 0 or FONT_EXTRA_INDEX). */
501 get_font_prop_index (key
, from
)
505 for (; from
< FONT_PROPERTY_TABLE_SIZE
; from
++)
506 if (EQ (key
, *font_property_table
[from
].key
))
511 /* Validate font properties in SPEC (vector) while updating elements
512 to regularized values. Signal an error if an invalid property is
516 font_prop_validate (spec
)
520 Lisp_Object prop
, val
, extra
;
522 for (i
= FONT_TYPE_INDEX
; i
< FONT_EXTRA_INDEX
; i
++)
524 if (! NILP (AREF (spec
, i
)))
526 prop
= *font_property_table
[i
].key
;
527 val
= (font_property_table
[i
].validater
) (prop
, AREF (spec
, i
));
528 if (EQ (val
, Qerror
))
529 Fsignal (Qfont
, list2 (build_string ("invalid font property"),
530 Fcons (prop
, AREF (spec
, i
))));
534 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
535 CONSP (extra
); extra
= XCDR (extra
))
537 Lisp_Object elt
= XCAR (extra
);
540 i
= get_font_prop_index (prop
, FONT_EXTRA_INDEX
);
542 && font_property_table
[i
].validater
)
544 val
= (font_property_table
[i
].validater
) (prop
, XCDR (elt
));
545 if (EQ (val
, Qerror
))
546 Fsignal (Qfont
, list2 (build_string ("invalid font property"),
554 /* Store VAL as a value of extra font property PROP in FONT. */
557 font_put_extra (font
, prop
, val
)
558 Lisp_Object font
, prop
, val
;
560 Lisp_Object extra
= AREF (font
, FONT_EXTRA_INDEX
);
561 Lisp_Object slot
= (NILP (extra
) ? Qnil
: assq_no_quit (prop
, extra
));
565 extra
= Fcons (Fcons (prop
, val
), extra
);
566 ASET (font
, FONT_EXTRA_INDEX
, extra
);
574 /* Font name parser and unparser */
576 static Lisp_Object intern_font_field
P_ ((char *, int));
577 static int parse_matrix
P_ ((char *));
578 static int font_expand_wildcards
P_ ((Lisp_Object
*, int));
579 static int font_parse_name
P_ ((char *, Lisp_Object
));
581 /* An enumerator for each field of an XLFD font name. */
582 enum xlfd_field_index
601 /* An enumerator for mask bit corresponding to each XLFD field. */
604 XLFD_FOUNDRY_MASK
= 0x0001,
605 XLFD_FAMILY_MASK
= 0x0002,
606 XLFD_WEIGHT_MASK
= 0x0004,
607 XLFD_SLANT_MASK
= 0x0008,
608 XLFD_SWIDTH_MASK
= 0x0010,
609 XLFD_ADSTYLE_MASK
= 0x0020,
610 XLFD_PIXEL_MASK
= 0x0040,
611 XLFD_POINT_MASK
= 0x0080,
612 XLFD_RESX_MASK
= 0x0100,
613 XLFD_RESY_MASK
= 0x0200,
614 XLFD_SPACING_MASK
= 0x0400,
615 XLFD_AVGWIDTH_MASK
= 0x0800,
616 XLFD_REGISTRY_MASK
= 0x1000,
617 XLFD_ENCODING_MASK
= 0x2000
621 /* Return a Lispy value of a XLFD font field at STR and LEN bytes.
622 If LEN is zero, it returns `null_string'.
623 If STR is "*", it returns nil.
624 If all characters in STR are digits, it returns an integer.
625 Otherwise, it returns a symbol interned from downcased STR. */
628 intern_font_field (str
, len
)
636 if (*str
== '*' && len
== 1)
640 for (i
= 1; i
< len
; i
++)
641 if (! isdigit (str
[i
]))
644 return make_number (atoi (str
));
646 return intern_downcase (str
, len
);
649 /* Parse P pointing the pixel/point size field of the form
650 `[A B C D]' which specifies a transformation matrix:
656 by which all glyphs of the font are transformed. The spec says
657 that scalar value N for the pixel/point size is equivalent to:
658 A = N * resx/resy, B = C = 0, D = N.
660 Return the scalar value N if the form is valid. Otherwise return
671 for (i
= 0, p
++; i
< 4 && *p
&& *p
!= ']'; i
++)
674 matrix
[i
] = - strtod (p
+ 1, &end
);
676 matrix
[i
] = strtod (p
, &end
);
679 return (i
== 4 ? (int) matrix
[3] : -1);
682 /* Expand a wildcard field in FIELD (the first N fields are filled) to
683 multiple fields to fill in all 14 XLFD fields while restring a
684 field position by its contents. */
687 font_expand_wildcards (field
, n
)
688 Lisp_Object field
[XLFD_LAST_INDEX
];
692 Lisp_Object tmp
[XLFD_LAST_INDEX
];
693 /* Array of information about where this element can go. Nth
694 element is for Nth element of FIELD. */
696 /* Minimum possible field. */
698 /* Maxinum possible field. */
700 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
702 } range
[XLFD_LAST_INDEX
];
704 int range_from
, range_to
;
707 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
708 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
709 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
710 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
711 | XLFD_AVGWIDTH_MASK)
712 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
714 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
715 field. The value is shifted to left one bit by one in the
717 for (i
= 0, range_mask
= 0; i
<= 14 - n
; i
++)
718 range_mask
= (range_mask
<< 1) | 1;
720 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
721 position-based retriction for FIELD[I]. */
722 for (i
= 0, range_from
= 0, range_to
= 14 - n
; i
< n
;
723 i
++, range_from
++, range_to
++, range_mask
<<= 1)
725 Lisp_Object val
= field
[i
];
731 range
[i
].from
= range_from
;
732 range
[i
].to
= range_to
;
733 range
[i
].mask
= range_mask
;
737 /* The triplet FROM, TO, and MASK is a value-based
738 retriction for FIELD[I]. */
744 int numeric
= XINT (val
);
747 from
= to
= XLFD_ENCODING_INDEX
,
748 mask
= XLFD_ENCODING_MASK
;
749 else if (numeric
== 0)
750 from
= XLFD_PIXEL_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
751 mask
= XLFD_PIXEL_MASK
| XLFD_LARGENUM_MASK
;
752 else if (numeric
<= 48)
753 from
= to
= XLFD_PIXEL_INDEX
,
754 mask
= XLFD_PIXEL_MASK
;
756 from
= XLFD_POINT_INDEX
, to
= XLFD_AVGWIDTH_INDEX
,
757 mask
= XLFD_LARGENUM_MASK
;
759 else if (EQ (val
, null_string
))
760 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ADSTYLE_INDEX
,
761 mask
= XLFD_NULL_MASK
;
763 from
= to
= XLFD_FOUNDRY_INDEX
, mask
= XLFD_FOUNDRY_MASK
;
766 Lisp_Object name
= SYMBOL_NAME (val
);
768 if (SDATA (name
)[SBYTES (name
) - 1] == '*')
769 from
= XLFD_REGISTRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
770 mask
= XLFD_REGENC_MASK
;
772 from
= to
= XLFD_ENCODING_INDEX
,
773 mask
= XLFD_ENCODING_MASK
;
775 else if (range_from
<= XLFD_WEIGHT_INDEX
776 && range_to
>= XLFD_WEIGHT_INDEX
777 && !NILP (prop_name_to_numeric (FONT_WEIGHT_INDEX
, val
)))
778 from
= to
= XLFD_WEIGHT_INDEX
, mask
= XLFD_WEIGHT_MASK
;
779 else if (range_from
<= XLFD_SLANT_INDEX
780 && range_to
>= XLFD_SLANT_INDEX
781 && !NILP (prop_name_to_numeric (FONT_SLANT_INDEX
, val
)))
782 from
= to
= XLFD_SLANT_INDEX
, mask
= XLFD_SLANT_MASK
;
783 else if (range_from
<= XLFD_SWIDTH_INDEX
784 && range_to
>= XLFD_SWIDTH_INDEX
785 && !NILP (prop_name_to_numeric (FONT_WIDTH_INDEX
, val
)))
786 from
= to
= XLFD_SWIDTH_INDEX
, mask
= XLFD_SWIDTH_MASK
;
789 if (EQ (val
, Qc
) || EQ (val
, Qm
) || EQ (val
, Qp
) || EQ (val
, Qd
))
790 from
= to
= XLFD_SPACING_INDEX
, mask
= XLFD_SPACING_MASK
;
792 from
= XLFD_FOUNDRY_INDEX
, to
= XLFD_ENCODING_INDEX
,
793 mask
= XLFD_SYMBOL_MASK
;
796 /* Merge position-based and value-based restrictions. */
798 while (from
< range_from
)
799 mask
&= ~(1 << from
++);
800 while (from
< 14 && ! (mask
& (1 << from
)))
802 while (to
> range_to
)
803 mask
&= ~(1 << to
--);
804 while (to
>= 0 && ! (mask
& (1 << to
)))
808 range
[i
].from
= from
;
810 range
[i
].mask
= mask
;
812 if (from
> range_from
|| to
< range_to
)
814 /* The range is narrowed by value-based restrictions.
815 Reflect it to the other fields. */
817 /* Following fields should be after FROM. */
819 /* Preceding fields should be before TO. */
820 for (j
= i
- 1, from
--, to
--; j
>= 0; j
--, from
--, to
--)
822 /* Check FROM for non-wildcard field. */
823 if (! NILP (tmp
[j
]) && range
[j
].from
< from
)
825 while (range
[j
].from
< from
)
826 range
[j
].mask
&= ~(1 << range
[j
].from
++);
827 while (from
< 14 && ! (range
[j
].mask
& (1 << from
)))
829 range
[j
].from
= from
;
832 from
= range
[j
].from
;
833 if (range
[j
].to
> to
)
835 while (range
[j
].to
> to
)
836 range
[j
].mask
&= ~(1 << range
[j
].to
--);
837 while (to
>= 0 && ! (range
[j
].mask
& (1 << to
)))
850 /* Decide all fileds from restrictions in RANGE. */
851 for (i
= j
= 0; i
< n
; i
++)
853 if (j
< range
[i
].from
)
855 if (i
== 0 || ! NILP (tmp
[i
- 1]))
856 /* None of TMP[X] corresponds to Jth field. */
858 for (; j
< range
[i
].from
; j
++)
863 if (! NILP (tmp
[n
- 1]) && j
< XLFD_REGISTRY_INDEX
)
865 for (; j
< XLFD_LAST_INDEX
; j
++)
867 if (INTEGERP (field
[XLFD_ENCODING_INDEX
]))
868 field
[XLFD_ENCODING_INDEX
]
869 = Fintern (Fnumber_to_string (field
[XLFD_ENCODING_INDEX
]), Qnil
);
874 #ifdef ENABLE_CHECKING
875 /* Match a 14-field XLFD pattern against a full XLFD font name. */
877 font_match_xlfd (char *pattern
, char *name
)
879 while (*pattern
&& *name
)
881 if (*pattern
== *name
)
883 else if (*pattern
== '*')
884 if (*name
== pattern
[1])
895 /* Make sure the font object matches the XLFD font name. */
897 font_check_xlfd_parse (Lisp_Object font
, char *name
)
899 char name_check
[256];
900 font_unparse_xlfd (font
, 0, name_check
, 255);
901 return font_match_xlfd (name_check
, name
);
906 /* Parse NAME (null terminated) as XLFD and store information in FONT
907 (font-spec or font-entity). Size property of FONT is set as
909 specified XLFD fields FONT property
910 --------------------- -------------
911 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
912 POINT_SIZE and RESY calculated pixel size (Lisp integer)
913 POINT_SIZE POINT_SIZE/10 (Lisp float)
915 If NAME is successfully parsed, return 0. Otherwise return -1.
917 FONT is usually a font-spec, but when this function is called from
918 X font backend driver, it is a font-entity. In that case, NAME is
919 a fully specified XLFD, and we set FONT_EXTRA_INDEX of FONT to a
920 symbol RESX-RESY-SPACING-AVGWIDTH.
924 font_parse_xlfd (name
, font
)
928 int len
= strlen (name
);
930 Lisp_Object dpi
, spacing
;
932 char *f
[XLFD_LAST_INDEX
+ 1];
937 /* Maximum XLFD name length is 255. */
939 /* Accept "*-.." as a fully specified XLFD. */
940 if (name
[0] == '*' && name
[1] == '-')
941 i
= 1, f
[XLFD_FOUNDRY_INDEX
] = name
;
944 for (p
= name
+ i
; *p
; p
++)
945 if (*p
== '-' && i
< XLFD_LAST_INDEX
)
949 dpi
= spacing
= Qnil
;
952 if (i
== XLFD_LAST_INDEX
)
956 /* Fully specified XLFD. */
957 for (i
= 0, j
= FONT_FOUNDRY_INDEX
; i
< XLFD_WEIGHT_INDEX
; i
++, j
++)
959 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
963 for (j
= FONT_WEIGHT_INDEX
; i
< XLFD_ADSTYLE_INDEX
; i
++, j
++)
965 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
968 Lisp_Object numeric
= prop_name_to_numeric (j
, val
);
970 if (INTEGERP (numeric
))
975 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
977 ASET (font
, FONT_ADSTYLE_INDEX
, val
);
978 i
= XLFD_REGISTRY_INDEX
;
979 val
= intern_font_field (f
[i
], f
[i
+ 2] - f
[i
]);
981 ASET (font
, FONT_REGISTRY_INDEX
, val
);
983 p
= f
[XLFD_PIXEL_INDEX
];
984 if (*p
== '[' && (pixel_size
= parse_matrix (p
)) >= 0)
985 ASET (font
, FONT_SIZE_INDEX
, make_number (pixel_size
));
988 i
= XLFD_PIXEL_INDEX
;
989 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
991 ASET (font
, FONT_SIZE_INDEX
, val
);
994 double point_size
= -1;
996 xassert (FONT_SPEC_P (font
));
997 p
= f
[XLFD_POINT_INDEX
];
999 point_size
= parse_matrix (p
);
1000 else if (isdigit (*p
))
1001 point_size
= atoi (p
), point_size
/= 10;
1002 if (point_size
>= 0)
1003 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1006 i
= XLFD_PIXEL_INDEX
;
1007 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
1009 ASET (font
, FONT_SIZE_INDEX
, val
);
1014 /* Parse RESX, RESY, SPACING, and AVGWIDTH. */
1015 if (FONT_ENTITY_P (font
))
1017 i
= XLFD_RESX_INDEX
;
1018 ASET (font
, FONT_EXTRA_INDEX
,
1019 intern_font_field (f
[i
], f
[XLFD_REGISTRY_INDEX
] - 1 - f
[i
]));
1020 eassert (font_check_xlfd_parse (font
, name
));
1024 /* Here we just setup DPI, SPACING, and AVGWIDTH. They are set
1025 in FONT_EXTRA_INDEX later. */
1026 i
= XLFD_RESX_INDEX
;
1027 dpi
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
1028 i
= XLFD_SPACING_INDEX
;
1029 spacing
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
1030 p
= f
[XLFD_AVGWIDTH_INDEX
];
1034 avgwidth
= atoi (p
);
1038 int wild_card_found
= 0;
1039 Lisp_Object prop
[XLFD_LAST_INDEX
];
1041 for (j
= 0; j
< i
; j
++)
1045 if (f
[j
][1] && f
[j
][1] != '-')
1048 wild_card_found
= 1;
1050 else if (isdigit (*f
[j
]))
1052 for (p
= f
[j
] + 1; isdigit (*p
); p
++);
1053 if (*p
&& *p
!= '-')
1054 prop
[j
] = intern_downcase (f
[j
], p
- f
[j
]);
1056 prop
[j
] = make_number (atoi (f
[j
]));
1059 prop
[j
] = intern_font_field (f
[j
], f
[j
+ 1] - 1 - f
[j
]);
1061 prop
[j
] = intern_font_field (f
[j
], f
[i
] - f
[j
]);
1063 if (! wild_card_found
)
1065 if (font_expand_wildcards (prop
, i
) < 0)
1068 for (i
= 0, j
= FONT_FOUNDRY_INDEX
; i
< XLFD_WEIGHT_INDEX
; i
++, j
++)
1069 if (! NILP (prop
[i
]))
1070 ASET (font
, j
, prop
[i
]);
1071 for (j
= FONT_WEIGHT_INDEX
; i
< XLFD_ADSTYLE_INDEX
; i
++, j
++)
1072 if (! NILP (prop
[i
]))
1073 ASET (font
, j
, prop
[i
]);
1074 if (! NILP (prop
[XLFD_ADSTYLE_INDEX
]))
1075 ASET (font
, FONT_ADSTYLE_INDEX
, prop
[XLFD_ADSTYLE_INDEX
]);
1076 val
= prop
[XLFD_REGISTRY_INDEX
];
1079 val
= prop
[XLFD_ENCODING_INDEX
];
1081 val
= Fintern (concat2 (build_string ("*-"), SYMBOL_NAME (val
)),
1084 else if (NILP (prop
[XLFD_ENCODING_INDEX
]))
1085 val
= Fintern (concat2 (SYMBOL_NAME (val
), build_string ("-*")),
1088 val
= Fintern (concat3 (SYMBOL_NAME (val
), build_string ("-"),
1089 SYMBOL_NAME (prop
[XLFD_ENCODING_INDEX
])),
1092 ASET (font
, FONT_REGISTRY_INDEX
, val
);
1094 if (INTEGERP (prop
[XLFD_PIXEL_INDEX
]))
1095 ASET (font
, FONT_SIZE_INDEX
, prop
[XLFD_PIXEL_INDEX
]);
1096 else if (INTEGERP (prop
[XLFD_POINT_INDEX
]))
1098 double point_size
= XINT (prop
[XLFD_POINT_INDEX
]);
1100 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
/ 10));
1103 dpi
= prop
[XLFD_RESX_INDEX
];
1104 spacing
= prop
[XLFD_SPACING_INDEX
];
1105 if (INTEGERP (prop
[XLFD_AVGWIDTH_INDEX
]))
1106 avgwidth
= XINT (prop
[XLFD_AVGWIDTH_INDEX
]);
1110 font_put_extra (font
, QCdpi
, dpi
);
1111 if (! NILP (spacing
))
1112 font_put_extra (font
, QCspacing
, spacing
);
1114 font_put_extra (font
, QCscalable
, avgwidth
== 0 ? Qt
: Qnil
);
1119 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1120 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1121 0, use PIXEL_SIZE instead. */
1124 font_unparse_xlfd (font
, pixel_size
, name
, nbytes
)
1130 char *f
[XLFD_REGISTRY_INDEX
+ 1];
1134 xassert (FONTP (font
));
1136 for (i
= FONT_FOUNDRY_INDEX
, j
= XLFD_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
;
1139 if (i
== FONT_ADSTYLE_INDEX
)
1140 j
= XLFD_ADSTYLE_INDEX
;
1141 else if (i
== FONT_REGISTRY_INDEX
)
1142 j
= XLFD_REGISTRY_INDEX
;
1143 val
= AREF (font
, i
);
1146 if (j
== XLFD_REGISTRY_INDEX
)
1147 f
[j
] = "*-*", len
+= 4;
1149 f
[j
] = "*", len
+= 2;
1154 val
= SYMBOL_NAME (val
);
1155 if (j
== XLFD_REGISTRY_INDEX
1156 && ! strchr ((char *) SDATA (val
), '-'))
1158 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1159 if (SDATA (val
)[SBYTES (val
) - 1] == '*')
1161 f
[j
] = alloca (SBYTES (val
) + 3);
1162 sprintf (f
[j
], "%s-*", SDATA (val
));
1163 len
+= SBYTES (val
) + 3;
1167 f
[j
] = alloca (SBYTES (val
) + 4);
1168 sprintf (f
[j
], "%s*-*", SDATA (val
));
1169 len
+= SBYTES (val
) + 4;
1173 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1177 for (i
= FONT_WEIGHT_INDEX
, j
= XLFD_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
;
1180 val
= AREF (font
, i
);
1182 f
[j
] = "*", len
+= 2;
1186 val
= prop_numeric_to_name (i
, XINT (val
));
1188 val
= SYMBOL_NAME (val
);
1189 xassert (STRINGP (val
));
1190 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1194 val
= AREF (font
, FONT_SIZE_INDEX
);
1195 xassert (NUMBERP (val
) || NILP (val
));
1203 f
[XLFD_PIXEL_INDEX
] = alloca (22);
1204 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "%d-*", i
) + 1;
1207 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1209 else if (FLOATP (val
))
1211 int i
= XFLOAT_DATA (val
) * 10;
1212 f
[XLFD_PIXEL_INDEX
] = alloca (12);
1213 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "*-%d", i
) + 1;
1216 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1218 val
= AREF (font
, FONT_EXTRA_INDEX
);
1220 if (FONT_ENTITY_P (font
)
1221 && EQ (AREF (font
, FONT_TYPE_INDEX
), Qx
))
1223 /* Setup names for RESX-RESY-SPACING-AVWIDTH. */
1224 if (SYMBOLP (val
) && ! NILP (val
))
1226 val
= SYMBOL_NAME (val
);
1227 f
[XLFD_RESX_INDEX
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1230 f
[XLFD_RESX_INDEX
] = "*-*-*-*", len
+= 6;
1234 Lisp_Object dpi
= assq_no_quit (QCdpi
, val
);
1235 Lisp_Object spacing
= assq_no_quit (QCspacing
, val
);
1236 Lisp_Object scalable
= assq_no_quit (QCscalable
, val
);
1238 if (CONSP (dpi
) || CONSP (spacing
) || CONSP (scalable
))
1240 char *str
= alloca (24);
1243 if (CONSP (dpi
) && INTEGERP (XCDR (dpi
)))
1244 this_len
= sprintf (str
, "%d-%d",
1245 XINT (XCDR (dpi
)), XINT (XCDR (dpi
)));
1247 this_len
= sprintf (str
, "*-*");
1248 if (CONSP (spacing
) && ! NILP (XCDR (spacing
)))
1250 val
= XCDR (spacing
);
1253 if (XINT (val
) < FONT_SPACING_MONO
)
1255 else if (XINT (val
) < FONT_SPACING_CHARCELL
)
1260 xassert (SYMBOLP (val
));
1261 this_len
+= sprintf (str
+ this_len
, "-%c",
1262 SDATA (SYMBOL_NAME (val
))[0]);
1265 this_len
+= sprintf (str
+ this_len
, "-*");
1266 if (CONSP (scalable
) && ! NILP (XCDR (spacing
)))
1267 this_len
+= sprintf (str
+ this_len
, "-0");
1269 this_len
+= sprintf (str
+ this_len
, "-*");
1270 f
[XLFD_RESX_INDEX
] = str
;
1274 f
[XLFD_RESX_INDEX
] = "*-*-*-*", len
+= 8;
1277 len
++; /* for terminating '\0'. */
1280 return sprintf (name
, "-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1281 f
[XLFD_FOUNDRY_INDEX
], f
[XLFD_FAMILY_INDEX
],
1282 f
[XLFD_WEIGHT_INDEX
], f
[XLFD_SLANT_INDEX
],
1283 f
[XLFD_SWIDTH_INDEX
],
1284 f
[XLFD_ADSTYLE_INDEX
], f
[XLFD_PIXEL_INDEX
],
1285 f
[XLFD_RESX_INDEX
], f
[XLFD_REGISTRY_INDEX
]);
1288 /* Parse NAME (null terminated) as Fonconfig's name format and store
1289 information in FONT (font-spec or font-entity). If NAME is
1290 successfully parsed, return 0. Otherwise return -1. */
1293 font_parse_fcname (name
, font
)
1298 int len
= strlen (name
);
1305 /* It is assured that (name[0] && name[0] != '-'). */
1313 for (p0
= name
+ 1; *p0
&& (*p0
!= '-' && *p0
!= ':'); p0
++)
1314 if (*p0
== '\\' && p0
[1])
1316 family
= intern_font_field (name
, p0
- name
);
1319 if (! isdigit (p0
[1]))
1321 point_size
= strtod (p0
+ 1, &p1
);
1322 if (*p1
&& *p1
!= ':')
1324 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1327 ASET (font
, FONT_FAMILY_INDEX
, family
);
1331 copy
= alloca (len
+ 1);
1336 /* Now parse ":KEY=VAL" patterns. Store known keys and values in
1337 extra, copy unknown ones to COPY. */
1340 Lisp_Object key
, val
;
1343 for (p1
= p0
+ 1; *p1
&& *p1
!= '=' && *p1
!= ':'; p1
++);
1346 /* Must be an enumerated value. */
1347 val
= intern_font_field (p0
+ 1, p1
- p0
- 1);
1348 if (memcmp (p0
+ 1, "light", 5) == 0
1349 || memcmp (p0
+ 1, "medium", 6) == 0
1350 || memcmp (p0
+ 1, "demibold", 8) == 0
1351 || memcmp (p0
+ 1, "bold", 4) == 0
1352 || memcmp (p0
+ 1, "black", 5) == 0)
1354 ASET (font
, FONT_WEIGHT_INDEX
, val
);
1357 else if (memcmp (p0
+ 1, "roman", 5) == 0
1358 || memcmp (p0
+ 1, "italic", 6) == 0
1359 || memcmp (p0
+ 1, "oblique", 7) == 0)
1361 ASET (font
, FONT_SLANT_INDEX
, val
);
1364 else if (memcmp (p0
+ 1, "charcell", 8) == 0
1365 || memcmp (p0
+ 1, "mono", 4) == 0
1366 || memcmp (p0
+ 1, "proportional", 12) == 0)
1368 font_put_extra (font
, QCspacing
,
1369 (p0
[1] == 'c' ? Qc
: p0
[1] == 'm' ? Qm
: Qp
));
1374 bcopy (p0
, copy
, p1
- p0
);
1380 if (memcmp (p0
+ 1, "pixelsize=", 10) == 0)
1381 prop
= FONT_SIZE_INDEX
;
1384 key
= intern_font_field (p0
, p1
- p0
);
1385 prop
= get_font_prop_index (key
, 0);
1388 for (p1
= p0
; *p1
&& *p1
!= ':'; p1
++);
1389 val
= intern_font_field (p0
, p1
- p0
);
1392 if (prop
>= 0 && prop
< FONT_EXTRA_INDEX
)
1394 if (prop
== FONT_WEIGHT_INDEX
)
1396 else if (prop
== FONT_SLANT_INDEX
)
1399 ASET (font
, prop
, val
);
1402 font_put_extra (font
, key
, val
);
1409 ASET (font
, FONT_WEIGHT_INDEX
, build_string ("normal"));
1411 ASET (font
, FONT_SLANT_INDEX
, build_string ("normal"));
1416 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1417 NAME (NBYTES length), and return the name length. If
1418 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1421 font_unparse_fcname (font
, pixel_size
, name
, nbytes
)
1429 int dpi
, spacing
, scalable
;
1432 Lisp_Object styles
[3];
1433 char *style_names
[3] = { "weight", "slant", "width" };
1435 val
= AREF (font
, FONT_FAMILY_INDEX
);
1436 if (SYMBOLP (val
) && ! NILP (val
))
1437 len
+= SBYTES (SYMBOL_NAME (val
));
1439 val
= AREF (font
, FONT_SIZE_INDEX
);
1442 if (XINT (val
) != 0)
1443 pixel_size
= XINT (val
);
1445 len
+= 21; /* for ":pixelsize=NUM" */
1447 else if (FLOATP (val
))
1450 point_size
= (int) XFLOAT_DATA (val
);
1451 len
+= 11; /* for "-NUM" */
1454 val
= AREF (font
, FONT_FOUNDRY_INDEX
);
1455 if (SYMBOLP (val
) && ! NILP (val
))
1456 /* ":foundry=NAME" */
1457 len
+= 9 + SBYTES (SYMBOL_NAME (val
));
1459 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
; i
++)
1461 val
= AREF (font
, i
);
1464 val
= prop_numeric_to_name (i
, XINT (val
));
1466 if (SYMBOLP (val
) && ! NILP (val
))
1467 len
+= (strlen (style_names
[i
- FONT_WEIGHT_INDEX
])
1468 + 2 + SBYTES (SYMBOL_NAME (val
))); /* :xxx=NAME */
1469 styles
[i
- FONT_WEIGHT_INDEX
] = val
;
1472 val
= AREF (font
, FONT_EXTRA_INDEX
);
1473 if (FONT_ENTITY_P (font
)
1474 && EQ (AREF (font
, FONT_TYPE_INDEX
), Qx
))
1478 /* VAL is a symbol of name `RESX-RESY-SPACING-AVWIDTH'. */
1479 p
= (char *) SDATA (SYMBOL_NAME (val
));
1481 for (p
++; *p
!= '-'; p
++); /* skip RESX */
1482 for (p
++; *p
!= '-'; p
++); /* skip RESY */
1483 spacing
= (*p
== 'c' ? FONT_SPACING_CHARCELL
1484 : *p
== 'm' ? FONT_SPACING_MONO
1485 : FONT_SPACING_PROPORTIONAL
);
1486 for (p
++; *p
!= '-'; p
++); /* skip SPACING */
1487 scalable
= (atoi (p
) == 0);
1488 /* The longest pattern is ":dpi=NUM:scalable=False:spacing=100" */
1495 dpi
= spacing
= scalable
= -1;
1496 elt
= assq_no_quit (QCdpi
, val
);
1498 dpi
= XINT (XCDR (elt
)), len
+= 15; /* for ":dpi=NUM" */
1499 elt
= assq_no_quit (QCspacing
, val
);
1501 spacing
= XINT (XCDR (elt
)), len
+= 12; /* for ":spacing=100" */
1502 elt
= assq_no_quit (QCscalable
, val
);
1504 scalable
= ! NILP (XCDR (elt
)), len
+= 15; /* for ":scalable=False" */
1510 if (! NILP (AREF (font
, FONT_FAMILY_INDEX
)))
1511 p
+= sprintf(p
, "%s",
1512 SDATA (SYMBOL_NAME (AREF (font
, FONT_FAMILY_INDEX
))));
1516 p
+= sprintf (p
, "%d", point_size
);
1518 p
+= sprintf (p
, "-%d", point_size
);
1520 else if (pixel_size
> 0)
1521 p
+= sprintf (p
, ":pixelsize=%d", pixel_size
);
1522 if (SYMBOLP (AREF (font
, FONT_FOUNDRY_INDEX
))
1523 && ! NILP (AREF (font
, FONT_FOUNDRY_INDEX
)))
1524 p
+= sprintf (p
, ":foundry=%s",
1525 SDATA (SYMBOL_NAME (AREF (font
, FONT_FOUNDRY_INDEX
))));
1526 for (i
= 0; i
< 3; i
++)
1527 if (SYMBOLP (styles
[i
]) && ! NILP (styles
[i
]))
1528 p
+= sprintf (p
, ":%s=%s", style_names
[i
],
1529 SDATA (SYMBOL_NAME (styles
[i
])));
1531 p
+= sprintf (p
, ":dpi=%d", dpi
);
1533 p
+= sprintf (p
, ":spacing=%d", spacing
);
1535 p
+= sprintf (p
, ":scalable=True");
1536 else if (scalable
== 0)
1537 p
+= sprintf (p
, ":scalable=False");
1541 /* Parse NAME (null terminated) and store information in FONT
1542 (font-spec or font-entity). If NAME is successfully parsed, return
1543 0. Otherwise return -1.
1545 If NAME is XLFD and FONT is a font-entity, store
1546 RESX-RESY-SPACING-AVWIDTH information as a symbol in
1547 FONT_EXTRA_INDEX. */
1550 font_parse_name (name
, font
)
1554 if (name
[0] == '-' || index (name
, '*'))
1555 return font_parse_xlfd (name
, font
);
1556 return font_parse_fcname (name
, font
);
1559 /* Merge old style font specification (either a font name NAME or a
1560 combination of a family name FAMILY and a registry name REGISTRY
1561 into the font specification SPEC. */
1564 font_merge_old_spec (name
, family
, registry
, spec
)
1565 Lisp_Object name
, family
, registry
, spec
;
1569 if (font_parse_xlfd ((char *) SDATA (name
), spec
) < 0)
1571 Lisp_Object extra
= Fcons (Fcons (QCname
, name
), Qnil
);
1573 ASET (spec
, FONT_EXTRA_INDEX
, extra
);
1578 if (! NILP (family
))
1583 xassert (STRINGP (family
));
1584 len
= SBYTES (family
);
1585 p0
= (char *) SDATA (family
);
1586 p1
= index (p0
, '-');
1589 if ((*p0
!= '*' || p1
- p0
> 1)
1590 && NILP (AREF (spec
, FONT_FOUNDRY_INDEX
)))
1591 ASET (spec
, FONT_FOUNDRY_INDEX
,
1592 intern_downcase (p0
, p1
- p0
));
1593 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
1594 ASET (spec
, FONT_FAMILY_INDEX
,
1595 intern_downcase (p1
+ 1, len
- (p1
+ 1 - p0
)));
1597 else if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
1598 ASET (spec
, FONT_FAMILY_INDEX
, intern_downcase (p0
, len
));
1600 if (! NILP (registry
)
1601 && NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
1602 ASET (spec
, FONT_REGISTRY_INDEX
,
1603 intern_downcase ((char *) SDATA (registry
), SBYTES (registry
)));
1608 /* This part (through the next ^L) is still experimental and never
1609 tested. We may drastically change codes. */
1613 #define LGSTRING_HEADER_SIZE 6
1614 #define LGSTRING_GLYPH_SIZE 8
1617 check_gstring (gstring
)
1618 Lisp_Object gstring
;
1623 CHECK_VECTOR (gstring
);
1624 val
= AREF (gstring
, 0);
1626 if (ASIZE (val
) < LGSTRING_HEADER_SIZE
)
1628 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring
));
1629 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
)))
1630 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
));
1631 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
)))
1632 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
));
1633 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
)))
1634 CHECK_NATNUM (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
));
1635 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1636 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1637 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1638 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1640 for (i
= 0; i
< LGSTRING_LENGTH (gstring
); i
++)
1642 val
= LGSTRING_GLYPH (gstring
, i
);
1644 if (ASIZE (val
) < LGSTRING_GLYPH_SIZE
)
1646 if (NILP (AREF (val
, LGLYPH_IX_CHAR
)))
1648 CHECK_NATNUM (AREF (val
, LGLYPH_IX_FROM
));
1649 CHECK_NATNUM (AREF (val
, LGLYPH_IX_TO
));
1650 CHECK_CHARACTER (AREF (val
, LGLYPH_IX_CHAR
));
1651 if (!NILP (AREF (val
, LGLYPH_IX_CODE
)))
1652 CHECK_NATNUM (AREF (val
, LGLYPH_IX_CODE
));
1653 if (!NILP (AREF (val
, LGLYPH_IX_WIDTH
)))
1654 CHECK_NATNUM (AREF (val
, LGLYPH_IX_WIDTH
));
1655 if (!NILP (AREF (val
, LGLYPH_IX_ADJUSTMENT
)))
1657 val
= AREF (val
, LGLYPH_IX_ADJUSTMENT
);
1659 if (ASIZE (val
) < 3)
1661 for (j
= 0; j
< 3; j
++)
1662 CHECK_NUMBER (AREF (val
, j
));
1667 error ("Invalid glyph-string format");
1672 check_otf_features (otf_features
)
1673 Lisp_Object otf_features
;
1675 Lisp_Object val
, elt
;
1677 CHECK_CONS (otf_features
);
1678 CHECK_SYMBOL (XCAR (otf_features
));
1679 otf_features
= XCDR (otf_features
);
1680 CHECK_CONS (otf_features
);
1681 CHECK_SYMBOL (XCAR (otf_features
));
1682 otf_features
= XCDR (otf_features
);
1683 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1685 CHECK_SYMBOL (Fcar (val
));
1686 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1687 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val
)));
1689 otf_features
= XCDR (otf_features
);
1690 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1692 CHECK_SYMBOL (Fcar (val
));
1693 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1694 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val
)));
1701 Lisp_Object otf_list
;
1704 otf_tag_symbol (tag
)
1709 OTF_tag_name (tag
, name
);
1710 return Fintern (make_unibyte_string (name
, 4), Qnil
);
1714 otf_open (entity
, file
)
1718 Lisp_Object val
= Fassoc (entity
, otf_list
);
1722 otf
= XSAVE_VALUE (XCDR (val
))->pointer
;
1725 otf
= file
? OTF_open (file
) : NULL
;
1726 val
= make_save_value (otf
, 0);
1727 otf_list
= Fcons (Fcons (entity
, val
), otf_list
);
1733 /* Return a list describing which scripts/languages FONT supports by
1734 which GSUB/GPOS features of OpenType tables. See the comment of
1735 (struct font_driver).otf_capability. */
1738 font_otf_capability (font
)
1742 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
1745 otf
= otf_open (font
->entity
, font
->file_name
);
1748 for (i
= 0; i
< 2; i
++)
1750 OTF_GSUB_GPOS
*gsub_gpos
;
1751 Lisp_Object script_list
= Qnil
;
1754 if (OTF_get_features (otf
, i
== 0) < 0)
1756 gsub_gpos
= i
== 0 ? otf
->gsub
: otf
->gpos
;
1757 for (j
= gsub_gpos
->ScriptList
.ScriptCount
- 1; j
>= 0; j
--)
1759 OTF_Script
*script
= gsub_gpos
->ScriptList
.Script
+ j
;
1760 Lisp_Object langsys_list
= Qnil
;
1761 Lisp_Object script_tag
= otf_tag_symbol (script
->ScriptTag
);
1764 for (k
= script
->LangSysCount
; k
>= 0; k
--)
1766 OTF_LangSys
*langsys
;
1767 Lisp_Object feature_list
= Qnil
;
1768 Lisp_Object langsys_tag
;
1771 if (k
== script
->LangSysCount
)
1773 langsys
= &script
->DefaultLangSys
;
1778 langsys
= script
->LangSys
+ k
;
1780 = otf_tag_symbol (script
->LangSysRecord
[k
].LangSysTag
);
1782 for (l
= langsys
->FeatureCount
- 1; l
>= 0; l
--)
1784 OTF_Feature
*feature
1785 = gsub_gpos
->FeatureList
.Feature
+ langsys
->FeatureIndex
[l
];
1786 Lisp_Object feature_tag
1787 = otf_tag_symbol (feature
->FeatureTag
);
1789 feature_list
= Fcons (feature_tag
, feature_list
);
1791 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
1794 script_list
= Fcons (Fcons (script_tag
, langsys_list
),
1799 XSETCAR (capability
, script_list
);
1801 XSETCDR (capability
, script_list
);
1807 /* Parse OTF features in SPEC and write a proper features spec string
1808 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1809 assured that the sufficient memory has already allocated for
1813 generate_otf_features (spec
, features
)
1823 for (asterisk
= 0; CONSP (spec
); spec
= XCDR (spec
))
1829 if (SREF (SYMBOL_NAME (val
), 0) == '*')
1834 else if (! asterisk
)
1836 val
= SYMBOL_NAME (val
);
1837 p
+= sprintf (p
, "%s", SDATA (val
));
1841 val
= SYMBOL_NAME (val
);
1842 p
+= sprintf (p
, "~%s", SDATA (val
));
1846 error ("OTF spec too long");
1851 font_otf_DeviceTable (device_table
)
1852 OTF_DeviceTable
*device_table
;
1854 int len
= device_table
->StartSize
- device_table
->EndSize
+ 1;
1856 return Fcons (make_number (len
),
1857 make_unibyte_string (device_table
->DeltaValue
, len
));
1861 font_otf_ValueRecord (value_format
, value_record
)
1863 OTF_ValueRecord
*value_record
;
1865 Lisp_Object val
= Fmake_vector (make_number (8), Qnil
);
1867 if (value_format
& OTF_XPlacement
)
1868 ASET (val
, 0, make_number (value_record
->XPlacement
));
1869 if (value_format
& OTF_YPlacement
)
1870 ASET (val
, 1, make_number (value_record
->YPlacement
));
1871 if (value_format
& OTF_XAdvance
)
1872 ASET (val
, 2, make_number (value_record
->XAdvance
));
1873 if (value_format
& OTF_YAdvance
)
1874 ASET (val
, 3, make_number (value_record
->YAdvance
));
1875 if (value_format
& OTF_XPlaDevice
)
1876 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XPlaDevice
));
1877 if (value_format
& OTF_YPlaDevice
)
1878 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YPlaDevice
));
1879 if (value_format
& OTF_XAdvDevice
)
1880 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XAdvDevice
));
1881 if (value_format
& OTF_YAdvDevice
)
1882 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YAdvDevice
));
1887 font_otf_Anchor (anchor
)
1892 val
= Fmake_vector (make_number (anchor
->AnchorFormat
+ 1), Qnil
);
1893 ASET (val
, 0, make_number (anchor
->XCoordinate
));
1894 ASET (val
, 1, make_number (anchor
->YCoordinate
));
1895 if (anchor
->AnchorFormat
== 2)
1896 ASET (val
, 2, make_number (anchor
->f
.f1
.AnchorPoint
));
1899 ASET (val
, 3, font_otf_DeviceTable (&anchor
->f
.f2
.XDeviceTable
));
1900 ASET (val
, 4, font_otf_DeviceTable (&anchor
->f
.f2
.YDeviceTable
));
1905 #endif /* HAVE_LIBOTF */
1907 /* G-string (glyph string) handler */
1909 /* G-string is a vector of the form [HEADER GLYPH ...].
1910 See the docstring of `font-make-gstring' for more detail. */
1913 font_prepare_composition (cmp
, f
)
1914 struct composition
*cmp
;
1918 = AREF (XHASH_TABLE (composition_hash_table
)->key_and_value
,
1919 cmp
->hash_index
* 2);
1921 cmp
->font
= XSAVE_VALUE (LGSTRING_FONT (gstring
))->pointer
;
1922 cmp
->glyph_len
= LGSTRING_LENGTH (gstring
);
1923 cmp
->pixel_width
= LGSTRING_WIDTH (gstring
);
1924 cmp
->lbearing
= LGSTRING_LBEARING (gstring
);
1925 cmp
->rbearing
= LGSTRING_RBEARING (gstring
);
1926 cmp
->ascent
= LGSTRING_ASCENT (gstring
);
1927 cmp
->descent
= LGSTRING_DESCENT (gstring
);
1928 cmp
->width
= cmp
->pixel_width
/ FRAME_COLUMN_WIDTH (f
);
1929 if (cmp
->width
== 0)
1938 static unsigned font_score
P_ ((Lisp_Object
, Lisp_Object
*));
1939 static int font_compare
P_ ((const void *, const void *));
1940 static Lisp_Object font_sort_entites
P_ ((Lisp_Object
, Lisp_Object
,
1941 Lisp_Object
, Lisp_Object
));
1943 /* We sort fonts by scoring each of them against a specified
1944 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1945 the value is, the closer the font is to the font-spec.
1947 Each 1-bit of the highest 4 bits of the score is used for atomic
1948 properties FOUNDRY, FAMILY, ADSTYLE, and REGISTRY.
1950 Each 7-bit in the lowest 28 bits are used for numeric properties
1951 WEIGHT, SLANT, WIDTH, and SIZE. */
1953 /* How many bits to shift to store the difference value of each font
1954 property in a score. */
1955 static int sort_shift_bits
[FONT_SIZE_INDEX
+ 1];
1957 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1958 The return value indicates how different ENTITY is compared with
1962 font_score (entity
, spec_prop
)
1963 Lisp_Object entity
, *spec_prop
;
1967 /* Score four atomic fields. Maximum difference is 1. */
1968 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
1969 if (! NILP (spec_prop
[i
])
1970 && ! EQ (spec_prop
[i
], AREF (entity
, i
)))
1971 score
|= 1 << sort_shift_bits
[i
];
1973 /* Score four numeric fields. Maximum difference is 127. */
1974 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
1976 Lisp_Object entity_val
= AREF (entity
, i
);
1977 Lisp_Object spec_val
= spec_prop
[i
];
1979 /* If weight and slant are unspecified, score normal lower (low wins). */
1980 if (NILP (spec_val
))
1982 if (i
== FONT_WEIGHT_INDEX
|| i
== FONT_SLANT_INDEX
)
1983 spec_val
= prop_name_to_numeric (i
, build_string ("normal"));
1986 if (! NILP (spec_val
) && ! EQ (spec_val
, entity_val
))
1988 if (! INTEGERP (entity_val
))
1989 score
|= 127 << sort_shift_bits
[i
];
1992 int diff
= XINT (entity_val
) - XINT (spec_val
);
1996 if (i
== FONT_SIZE_INDEX
)
1998 if (XINT (entity_val
) > 0
1999 && diff
> FONT_PIXEL_SIZE_QUANTUM
)
2000 score
|= min (diff
, 127) << sort_shift_bits
[i
];
2003 else if (i
== FONT_WEIGHT_INDEX
)
2005 /* Windows uses a much wider range for weight (100-900)
2006 compared with freetype (0-210), so scale down the
2007 difference. A more general way of doing this
2008 would be to look up the values of regular and bold
2009 and/or light and calculate the scale factor from them,
2010 but the lookup would be expensive, and if only Windows
2011 needs it, not worth the effort. */
2012 score
|= min (diff
/ 4, 127) << sort_shift_bits
[i
];
2016 score
|= min (diff
, 127) << sort_shift_bits
[i
];
2025 /* The comparison function for qsort. */
2028 font_compare (d1
, d2
)
2029 const void *d1
, *d2
;
2031 return (*(unsigned *) d1
< *(unsigned *) d2
2032 ? -1 : *(unsigned *) d1
> *(unsigned *) d2
);
2036 /* The structure for elements being sorted by qsort. */
2037 struct font_sort_data
2044 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2045 If PREFER specifies a point-size, calculate the corresponding
2046 pixel-size from QCdpi property of PREFER or from the Y-resolution
2047 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
2048 get the font-entities in VEC. */
2051 font_sort_entites (vec
, prefer
, frame
, spec
)
2052 Lisp_Object vec
, prefer
, frame
, spec
;
2054 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2056 struct font_sort_data
*data
;
2063 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
2064 prefer_prop
[i
] = AREF (prefer
, i
);
2068 /* As it is assured that all fonts in VEC match with SPEC, we
2069 should ignore properties specified in SPEC. So, set the
2070 corresponding properties in PREFER_PROP to nil. */
2071 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
2072 if (! NILP (AREF (spec
, i
)))
2073 prefer_prop
[i
++] = Qnil
;
2076 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2077 prefer_prop
[FONT_SIZE_INDEX
]
2078 = make_number (font_pixel_size (XFRAME (frame
), prefer
));
2080 /* Scoring and sorting. */
2081 SAFE_ALLOCA (data
, struct font_sort_data
*, (sizeof *data
) * len
);
2082 for (i
= 0; i
< len
; i
++)
2084 data
[i
].entity
= AREF (vec
, i
);
2085 data
[i
].score
= font_score (data
[i
].entity
, prefer_prop
);
2087 qsort (data
, len
, sizeof *data
, font_compare
);
2088 for (i
= 0; i
< len
; i
++)
2089 ASET (vec
, i
, data
[i
].entity
);
2096 /* API of Font Service Layer. */
2098 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2099 sort_shift_bits. Finternal_set_font_selection_order calls this
2100 function with font_sort_order after setting up it. */
2103 font_update_sort_order (order
)
2106 int i
, shift_bits
= 21;
2108 for (i
= 0; i
< 4; i
++, shift_bits
-= 7)
2110 int xlfd_idx
= order
[i
];
2112 if (xlfd_idx
== XLFD_WEIGHT_INDEX
)
2113 sort_shift_bits
[FONT_WEIGHT_INDEX
] = shift_bits
;
2114 else if (xlfd_idx
== XLFD_SLANT_INDEX
)
2115 sort_shift_bits
[FONT_SLANT_INDEX
] = shift_bits
;
2116 else if (xlfd_idx
== XLFD_SWIDTH_INDEX
)
2117 sort_shift_bits
[FONT_WIDTH_INDEX
] = shift_bits
;
2119 sort_shift_bits
[FONT_SIZE_INDEX
] = shift_bits
;
2124 /* Return weight property of FONT as symbol. */
2127 font_symbolic_weight (font
)
2130 Lisp_Object weight
= AREF (font
, FONT_WEIGHT_INDEX
);
2132 if (INTEGERP (weight
))
2133 weight
= prop_numeric_to_name (FONT_WEIGHT_INDEX
, XINT (weight
));
2138 /* Return slant property of FONT as symbol. */
2141 font_symbolic_slant (font
)
2144 Lisp_Object slant
= AREF (font
, FONT_SLANT_INDEX
);
2146 if (INTEGERP (slant
))
2147 slant
= prop_numeric_to_name (FONT_SLANT_INDEX
, XINT (slant
));
2152 /* Return width property of FONT as symbol. */
2155 font_symbolic_width (font
)
2158 Lisp_Object width
= AREF (font
, FONT_WIDTH_INDEX
);
2160 if (INTEGERP (width
))
2161 width
= prop_numeric_to_name (FONT_WIDTH_INDEX
, XINT (width
));
2166 /* Check if ENTITY matches with the font specification SPEC. */
2169 font_match_p (spec
, entity
)
2170 Lisp_Object spec
, entity
;
2174 for (i
= FONT_FOUNDRY_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2175 if (! NILP (AREF (spec
, i
))
2176 && ! EQ (AREF (spec
, i
), AREF (entity
, i
)))
2178 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
))
2179 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0
2180 && (XINT (AREF (spec
, FONT_SIZE_INDEX
))
2181 != XINT (AREF (entity
, FONT_SIZE_INDEX
))))
2187 /* Return a lispy font object corresponding to FONT. */
2190 font_find_object (font
)
2193 Lisp_Object tail
, elt
;
2195 for (tail
= AREF (font
->entity
, FONT_OBJLIST_INDEX
); CONSP (tail
);
2199 if (font
== XSAVE_VALUE (elt
)->pointer
2200 && XSAVE_VALUE (elt
)->integer
> 0)
2210 Each font backend has the callback function get_cache, and it
2211 returns a cons cell of which cdr part can be freely used for
2212 caching fonts. The cons cell may be shared by multiple frames
2213 and/or multiple font drivers. So, we arrange the cdr part as this:
2215 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2217 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2218 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2219 cons (FONT-SPEC FONT-ENTITY ...). */
2221 static void font_prepare_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2222 static void font_finish_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2223 static Lisp_Object font_get_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2224 static void font_clear_cache
P_ ((FRAME_PTR
, Lisp_Object
,
2225 struct font_driver
*));
2228 font_prepare_cache (f
, driver
)
2230 struct font_driver
*driver
;
2232 Lisp_Object cache
, val
;
2234 cache
= driver
->get_cache (f
);
2236 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2240 val
= Fcons (driver
->type
, Fcons (make_number (1), Qnil
));
2241 XSETCDR (cache
, Fcons (val
, XCDR (cache
)));
2245 val
= XCDR (XCAR (val
));
2246 XSETCAR (val
, make_number (XINT (XCAR (val
)) + 1));
2252 font_finish_cache (f
, driver
)
2254 struct font_driver
*driver
;
2256 Lisp_Object cache
, val
, tmp
;
2259 cache
= driver
->get_cache (f
);
2261 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2262 cache
= val
, val
= XCDR (val
);
2263 xassert (! NILP (val
));
2264 tmp
= XCDR (XCAR (val
));
2265 XSETCAR (tmp
, make_number (XINT (XCAR (tmp
)) - 1));
2266 if (XINT (XCAR (tmp
)) == 0)
2268 font_clear_cache (f
, XCAR (val
), driver
);
2269 XSETCDR (cache
, XCDR (val
));
2275 font_get_cache (f
, driver
)
2277 struct font_driver
*driver
;
2279 Lisp_Object val
= driver
->get_cache (f
);
2280 Lisp_Object type
= driver
->type
;
2282 xassert (CONSP (val
));
2283 for (val
= XCDR (val
); ! EQ (XCAR (XCAR (val
)), type
); val
= XCDR (val
));
2284 xassert (CONSP (val
));
2285 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2286 val
= XCDR (XCAR (val
));
2290 static int num_fonts
;
2293 font_clear_cache (f
, cache
, driver
)
2296 struct font_driver
*driver
;
2298 Lisp_Object tail
, elt
;
2300 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2301 for (tail
= XCDR (XCDR (cache
)); CONSP (tail
); tail
= XCDR (tail
))
2304 if (CONSP (elt
) && FONT_SPEC_P (XCAR (elt
)))
2306 Lisp_Object vec
= XCDR (elt
);
2309 for (i
= 0; i
< ASIZE (vec
); i
++)
2311 Lisp_Object entity
= AREF (vec
, i
);
2313 if (EQ (driver
->type
, AREF (entity
, FONT_TYPE_INDEX
)))
2315 Lisp_Object objlist
= AREF (entity
, FONT_OBJLIST_INDEX
);
2317 for (; CONSP (objlist
); objlist
= XCDR (objlist
))
2319 Lisp_Object val
= XCAR (objlist
);
2320 struct Lisp_Save_Value
*p
= XSAVE_VALUE (val
);
2321 struct font
*font
= p
->pointer
;
2323 xassert (font
&& driver
== font
->driver
);
2324 driver
->close (f
, font
);
2329 if (driver
->free_entity
)
2330 driver
->free_entity (entity
);
2335 XSETCDR (cache
, Qnil
);
2339 static Lisp_Object scratch_font_spec
, scratch_font_prefer
;
2342 /* Return a vector of font-entities matching with SPEC on frame F. */
2345 font_list_entities (frame
, spec
)
2346 Lisp_Object frame
, spec
;
2348 FRAME_PTR f
= XFRAME (frame
);
2349 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2350 Lisp_Object ftype
, family
, size
, alternate_familes
;
2351 Lisp_Object
*vec
= alloca (sizeof (Lisp_Object
) * num_font_drivers
);
2357 family
= AREF (spec
, FONT_FAMILY_INDEX
);
2359 alternate_familes
= Qnil
;
2362 if (NILP (font_family_alist
)
2363 && !NILP (Vface_alternative_font_family_alist
))
2364 build_font_family_alist ();
2365 alternate_familes
= assq_no_quit (family
, font_family_alist
);
2366 if (! NILP (alternate_familes
))
2367 alternate_familes
= XCDR (alternate_familes
);
2369 size
= AREF (spec
, FONT_SIZE_INDEX
);
2371 ASET (spec
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2373 xassert (ASIZE (spec
) == FONT_SPEC_MAX
);
2374 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2376 for (i
= 0; driver_list
; driver_list
= driver_list
->next
)
2378 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2380 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2381 Lisp_Object tail
= alternate_familes
;
2383 ASET (spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2384 ASET (spec
, FONT_FAMILY_INDEX
, family
);
2388 Lisp_Object val
= assoc_no_quit (spec
, XCDR (cache
));
2394 val
= driver_list
->driver
->list (frame
, spec
);
2396 XSETCDR (cache
, Fcons (Fcons (Fcopy_sequence (spec
), val
),
2399 if (VECTORP (val
) && ASIZE (val
) > 0)
2406 ASET (spec
, FONT_FAMILY_INDEX
, XCAR (tail
));
2410 ASET (spec
, FONT_TYPE_INDEX
, ftype
);
2411 ASET (spec
, FONT_FAMILY_INDEX
, family
);
2412 ASET (spec
, FONT_SIZE_INDEX
, size
);
2413 return (i
> 0 ? Fvconcat (i
, vec
) : null_vector
);
2417 /* Return a font entity matching with SPEC on FRAME. */
2420 font_matching_entity (frame
, spec
)
2421 Lisp_Object frame
, spec
;
2423 FRAME_PTR f
= XFRAME (frame
);
2424 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2425 Lisp_Object ftype
, size
, entity
;
2427 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2428 size
= AREF (spec
, FONT_SIZE_INDEX
);
2430 ASET (spec
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2432 for (; driver_list
; driver_list
= driver_list
->next
)
2434 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2436 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2439 ASET (spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2440 key
= Fcons (spec
, Qnil
);
2441 entity
= assoc_no_quit (key
, XCDR (cache
));
2443 entity
= XCDR (entity
);
2446 entity
= driver_list
->driver
->match (frame
, spec
);
2447 if (! NILP (entity
))
2449 XSETCAR (key
, Fcopy_sequence (spec
));
2450 XSETCDR (cache
, Fcons (Fcons (key
, entity
), XCDR (cache
)));
2453 if (! NILP (entity
))
2456 ASET (spec
, FONT_TYPE_INDEX
, ftype
);
2457 ASET (spec
, FONT_SIZE_INDEX
, size
);
2462 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2463 opened font object. */
2466 font_open_entity (f
, entity
, pixel_size
)
2471 struct font_driver_list
*driver_list
;
2472 Lisp_Object objlist
, size
, val
, font_object
;
2475 size
= AREF (entity
, FONT_SIZE_INDEX
);
2476 xassert (NATNUMP (size
));
2477 if (XINT (size
) != 0)
2478 pixel_size
= XINT (size
);
2481 for (objlist
= AREF (entity
, FONT_OBJLIST_INDEX
); CONSP (objlist
);
2482 objlist
= XCDR (objlist
))
2484 font
= XSAVE_VALUE (XCAR (objlist
))->pointer
;
2485 if (font
->pixel_size
== pixel_size
)
2487 font_object
= XCAR (objlist
);
2488 XSAVE_VALUE (font_object
)->integer
++;
2493 if (NILP (font_object
))
2495 val
= AREF (entity
, FONT_TYPE_INDEX
);
2496 for (driver_list
= f
->font_driver_list
;
2497 driver_list
&& ! EQ (driver_list
->driver
->type
, val
);
2498 driver_list
= driver_list
->next
);
2502 font
= driver_list
->driver
->open (f
, entity
, pixel_size
);
2505 font
->scalable
= XINT (size
) == 0;
2507 font_object
= make_save_value (font
, 1);
2508 ASET (entity
, FONT_OBJLIST_INDEX
,
2509 Fcons (font_object
, AREF (entity
, FONT_OBJLIST_INDEX
)));
2513 if (FRAME_SMALLEST_CHAR_WIDTH (f
) > font
->min_width
)
2514 FRAME_SMALLEST_CHAR_WIDTH (f
) = font
->min_width
;
2515 if (FRAME_SMALLEST_CHAR_WIDTH (f
) <= 0)
2516 FRAME_SMALLEST_CHAR_WIDTH (f
) = 1;
2517 if (FRAME_SMALLEST_FONT_HEIGHT (f
) > font
->font
.height
)
2518 FRAME_SMALLEST_FONT_HEIGHT (f
) = font
->font
.height
;
2519 if (FRAME_SMALLEST_FONT_HEIGHT (f
) <= 0)
2520 FRAME_SMALLEST_FONT_HEIGHT (f
) = 1;
2526 /* Close FONT_OBJECT that is opened on frame F. */
2529 font_close_object (f
, font_object
)
2531 Lisp_Object font_object
;
2533 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2534 Lisp_Object objlist
;
2535 Lisp_Object tail
, prev
= Qnil
;
2537 xassert (XSAVE_VALUE (font_object
)->integer
> 0);
2538 XSAVE_VALUE (font_object
)->integer
--;
2539 if (XSAVE_VALUE (font_object
)->integer
> 0)
2542 objlist
= AREF (font
->entity
, FONT_OBJLIST_INDEX
);
2543 for (prev
= Qnil
, tail
= objlist
; CONSP (tail
);
2544 prev
= tail
, tail
= XCDR (tail
))
2545 if (EQ (font_object
, XCAR (tail
)))
2547 if (font
->driver
->close
)
2548 font
->driver
->close (f
, font
);
2549 XSAVE_VALUE (font_object
)->pointer
= NULL
;
2551 ASET (font
->entity
, FONT_OBJLIST_INDEX
, XCDR (objlist
));
2553 XSETCDR (prev
, XCDR (objlist
));
2561 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2562 FONT is a font-entity and it must be opened to check. */
2565 font_has_char (f
, font
, c
)
2572 if (FONT_ENTITY_P (font
))
2574 Lisp_Object type
= AREF (font
, FONT_TYPE_INDEX
);
2575 struct font_driver_list
*driver_list
;
2577 for (driver_list
= f
->font_driver_list
;
2578 driver_list
&& ! EQ (driver_list
->driver
->type
, type
);
2579 driver_list
= driver_list
->next
);
2582 if (! driver_list
->driver
->has_char
)
2584 return driver_list
->driver
->has_char (font
, c
);
2587 xassert (FONT_OBJECT_P (font
));
2588 fontp
= XSAVE_VALUE (font
)->pointer
;
2590 if (fontp
->driver
->has_char
)
2592 int result
= fontp
->driver
->has_char (fontp
->entity
, c
);
2597 return (fontp
->driver
->encode_char (fontp
, c
) != FONT_INVALID_CODE
);
2601 /* Return the glyph ID of FONT_OBJECT for character C. */
2604 font_encode_char (font_object
, c
)
2605 Lisp_Object font_object
;
2608 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2610 return font
->driver
->encode_char (font
, c
);
2614 /* Return the name of FONT_OBJECT. */
2617 font_get_name (font_object
)
2618 Lisp_Object font_object
;
2620 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2621 char *name
= (font
->font
.full_name
? font
->font
.full_name
2622 : font
->font
.name
? font
->font
.name
2625 return (name
? make_unibyte_string (name
, strlen (name
)) : null_string
);
2629 /* Return the specification of FONT_OBJECT. */
2632 font_get_spec (font_object
)
2633 Lisp_Object font_object
;
2635 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2636 Lisp_Object spec
= Ffont_spec (0, NULL
);
2639 for (i
= 0; i
< FONT_SIZE_INDEX
; i
++)
2640 ASET (spec
, i
, AREF (font
->entity
, i
));
2641 ASET (spec
, FONT_SIZE_INDEX
, make_number (font
->pixel_size
));
2646 /* Return the frame on which FONT exists. FONT is a font object or a
2650 font_get_frame (font
)
2653 if (FONT_OBJECT_P (font
))
2654 font
= ((struct font
*) XSAVE_VALUE (font
)->pointer
)->entity
;
2655 xassert (FONT_ENTITY_P (font
));
2656 return AREF (font
, FONT_FRAME_INDEX
);
2660 /* Find a font entity best matching with LFACE. If SPEC is non-nil,
2661 the font must exactly match with it. C, if not negative, is a
2662 character that the entity must support. */
2665 font_find_for_lface (f
, lface
, spec
, c
)
2671 Lisp_Object frame
, entities
, val
;
2674 XSETFRAME (frame
, f
);
2680 for (i
= 0; i
< FONT_SPEC_MAX
; i
++)
2681 ASET (scratch_font_spec
, i
, Qnil
);
2682 ASET (scratch_font_spec
, FONT_REGISTRY_INDEX
, Qiso8859_1
);
2684 if (! NILP (lface
[LFACE_FAMILY_INDEX
]))
2685 font_merge_old_spec (Qnil
, lface
[LFACE_FAMILY_INDEX
], Qnil
,
2687 entities
= font_list_entities (frame
, scratch_font_spec
);
2688 while (ASIZE (entities
) == 0)
2690 /* Try without FOUNDRY or FAMILY. */
2691 if (! NILP (AREF (scratch_font_spec
, FONT_FOUNDRY_INDEX
)))
2693 ASET (scratch_font_spec
, FONT_FOUNDRY_INDEX
, Qnil
);
2694 entities
= font_list_entities (frame
, scratch_font_spec
);
2696 else if (! NILP (AREF (scratch_font_spec
, FONT_FAMILY_INDEX
)))
2698 ASET (scratch_font_spec
, FONT_FAMILY_INDEX
, Qnil
);
2699 entities
= font_list_entities (frame
, scratch_font_spec
);
2707 Lisp_Object registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
2709 if (NILP (registry
))
2710 registry
= Qiso8859_1
;
2714 struct charset
*encoding
, *repertory
;
2716 if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
2720 if (ENCODE_CHAR (repertory
, c
)
2721 == CHARSET_INVALID_CODE (repertory
))
2723 /* Any font of this registry support C. So, let's
2724 suppress the further checking. */
2727 else if (c
> encoding
->max_char
)
2730 for (i
= 0; i
< FONT_SPEC_MAX
; i
++)
2731 ASET (scratch_font_spec
, i
, AREF (spec
, i
));
2732 ASET (scratch_font_spec
, FONT_REGISTRY_INDEX
, registry
);
2733 entities
= font_list_entities (frame
, scratch_font_spec
);
2736 if (ASIZE (entities
) == 0)
2738 if (ASIZE (entities
) > 1)
2740 /* Sort fonts by properties specified in LFACE. */
2741 Lisp_Object prefer
= scratch_font_prefer
;
2744 if (! NILP (lface
[LFACE_FAMILY_INDEX
]))
2745 font_merge_old_spec (Qnil
, lface
[LFACE_FAMILY_INDEX
], Qnil
, prefer
);
2746 ASET (prefer
, FONT_WEIGHT_INDEX
,
2747 font_prop_validate_style (QCweight
, lface
[LFACE_WEIGHT_INDEX
]));
2748 ASET (prefer
, FONT_SLANT_INDEX
,
2749 font_prop_validate_style (QCslant
, lface
[LFACE_SLANT_INDEX
]));
2750 ASET (prefer
, FONT_WIDTH_INDEX
,
2751 font_prop_validate_style (QCwidth
, lface
[LFACE_SWIDTH_INDEX
]));
2752 pt
= XINT (lface
[LFACE_HEIGHT_INDEX
]);
2753 ASET (prefer
, FONT_SIZE_INDEX
, make_float (pt
/ 10));
2755 font_sort_entites (entities
, prefer
, frame
, spec
);
2759 return AREF (entities
, 0);
2761 val
= AREF (entities
, 0);
2762 result
= font_has_char (f
, val
, c
);
2767 val
= font_open_for_lface (f
, val
, lface
, spec
);
2770 result
= font_has_char (f
, val
, c
);
2771 font_close_object (f
, val
);
2779 font_open_for_lface (f
, entity
, lface
, spec
)
2787 if (FONT_SPEC_P (spec
) && INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2788 size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
2791 double pt
= XINT (lface
[LFACE_HEIGHT_INDEX
]);
2794 size
= POINT_TO_PIXEL (pt
, f
->resy
);
2796 return font_open_entity (f
, entity
, size
);
2800 /* Load a font best matching with FACE's font-related properties into
2801 FACE on frame F. If no proper font is found, record that FACE has
2805 font_load_for_face (f
, face
)
2809 Lisp_Object font_object
= face
->lface
[LFACE_FONT_INDEX
];
2811 if (NILP (font_object
))
2813 Lisp_Object entity
= font_find_for_lface (f
, face
->lface
, Qnil
, -1);
2815 if (! NILP (entity
))
2816 font_object
= font_open_for_lface (f
, entity
, face
->lface
, Qnil
);
2818 else if (STRINGP (font_object
))
2820 font_object
= font_open_by_name (f
, SDATA (font_object
));
2823 if (! NILP (font_object
))
2825 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2827 face
->font
= font
->font
.font
;
2828 face
->font_info
= (struct font_info
*) font
;
2829 face
->font_info_id
= 0;
2830 face
->font_name
= font
->font
.full_name
;
2835 face
->font_info
= NULL
;
2836 face
->font_info_id
= -1;
2837 face
->font_name
= NULL
;
2838 add_to_log ("Unable to load font for a face%s", null_string
, Qnil
);
2843 /* Make FACE on frame F ready to use the font opened for FACE. */
2846 font_prepare_for_face (f
, face
)
2850 struct font
*font
= (struct font
*) face
->font_info
;
2852 if (font
->driver
->prepare_face
)
2853 font
->driver
->prepare_face (f
, face
);
2857 /* Make FACE on frame F stop using the font opened for FACE. */
2860 font_done_for_face (f
, face
)
2864 struct font
*font
= (struct font
*) face
->font_info
;
2866 if (font
->driver
->done_face
)
2867 font
->driver
->done_face (f
, face
);
2872 /* Open a font best matching with NAME on frame F. If no proper font
2873 is found, return Qnil. */
2876 font_open_by_name (f
, name
)
2880 Lisp_Object args
[2];
2881 Lisp_Object spec
, prefer
, size
, entity
, entity_list
;
2886 XSETFRAME (frame
, f
);
2889 args
[1] = make_unibyte_string (name
, strlen (name
));
2890 spec
= Ffont_spec (2, args
);
2891 prefer
= scratch_font_prefer
;
2892 for (i
= FONT_WEIGHT_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2893 if (NILP (AREF (spec
, i
)))
2894 ASET (prefer
, i
, make_number (100));
2895 size
= AREF (spec
, FONT_SIZE_INDEX
);
2898 else if (INTEGERP (size
))
2899 pixel_size
= XINT (size
);
2900 else /* FLOATP (size) */
2902 double pt
= XFLOAT_DATA (size
);
2904 pixel_size
= POINT_TO_PIXEL (pt
, f
->resy
);
2905 size
= make_number (pixel_size
);
2906 ASET (spec
, FONT_SIZE_INDEX
, size
);
2908 if (pixel_size
== 0)
2910 pixel_size
= POINT_TO_PIXEL (12.0, f
->resy
);
2911 size
= make_number (pixel_size
);
2913 ASET (prefer
, FONT_SIZE_INDEX
, size
);
2914 if (NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
2915 ASET (spec
, FONT_REGISTRY_INDEX
, Qiso8859_1
);
2917 entity_list
= Flist_fonts (spec
, frame
, make_number (1), prefer
);
2918 if (NILP (entity_list
))
2919 entity
= font_matching_entity (frame
, spec
);
2921 entity
= XCAR (entity_list
);
2922 return (NILP (entity
)
2924 : font_open_entity (f
, entity
, pixel_size
));
2928 /* Register font-driver DRIVER. This function is used in two ways.
2930 The first is with frame F non-NULL. In this case, make DRIVER
2931 available (but not yet activated) on F. All frame creaters
2932 (e.g. Fx_create_frame) must call this function at least once with
2933 an available font-driver.
2935 The second is with frame F NULL. In this case, DRIVER is globally
2936 registered in the variable `font_driver_list'. All font-driver
2937 implementations must call this function in its syms_of_XXXX
2938 (e.g. syms_of_xfont). */
2941 register_font_driver (driver
, f
)
2942 struct font_driver
*driver
;
2945 struct font_driver_list
*root
= f
? f
->font_driver_list
: font_driver_list
;
2946 struct font_driver_list
*prev
, *list
;
2948 if (f
&& ! driver
->draw
)
2949 error ("Unusable font driver for a frame: %s",
2950 SDATA (SYMBOL_NAME (driver
->type
)));
2952 for (prev
= NULL
, list
= root
; list
; prev
= list
, list
= list
->next
)
2953 if (EQ (list
->driver
->type
, driver
->type
))
2954 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver
->type
)));
2956 list
= malloc (sizeof (struct font_driver_list
));
2958 list
->driver
= driver
;
2963 f
->font_driver_list
= list
;
2965 font_driver_list
= list
;
2970 /* Free font-driver list on frame F. It doesn't free font-drivers
2974 free_font_driver_list (f
)
2977 while (f
->font_driver_list
)
2979 struct font_driver_list
*next
= f
->font_driver_list
->next
;
2981 free (f
->font_driver_list
);
2982 f
->font_driver_list
= next
;
2987 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
2988 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
2989 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
2991 A caller must free all realized faces if any in advance. The
2992 return value is a list of font backends actually made used on
2996 font_update_drivers (f
, new_drivers
)
2998 Lisp_Object new_drivers
;
3000 Lisp_Object active_drivers
= Qnil
;
3001 struct font_driver_list
*list
;
3003 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3006 if (! EQ (new_drivers
, Qt
)
3007 && NILP (Fmemq (list
->driver
->type
, new_drivers
)))
3009 if (list
->driver
->end_for_frame
)
3010 list
->driver
->end_for_frame (f
);
3011 font_finish_cache (f
, list
->driver
);
3017 if (EQ (new_drivers
, Qt
)
3018 || ! NILP (Fmemq (list
->driver
->type
, new_drivers
)))
3020 if (! list
->driver
->start_for_frame
3021 || list
->driver
->start_for_frame (f
) == 0)
3023 font_prepare_cache (f
, list
->driver
);
3025 active_drivers
= nconc2 (active_drivers
,
3026 Fcons (list
->driver
->type
, Qnil
));
3031 return active_drivers
;
3035 font_put_frame_data (f
, driver
, data
)
3037 struct font_driver
*driver
;
3040 struct font_data_list
*list
, *prev
;
3042 for (prev
= NULL
, list
= f
->font_data_list
; list
;
3043 prev
= list
, list
= list
->next
)
3044 if (list
->driver
== driver
)
3051 prev
->next
= list
->next
;
3053 f
->font_data_list
= list
->next
;
3061 list
= malloc (sizeof (struct font_data_list
));
3064 list
->driver
= driver
;
3065 list
->next
= f
->font_data_list
;
3066 f
->font_data_list
= list
;
3074 font_get_frame_data (f
, driver
)
3076 struct font_driver
*driver
;
3078 struct font_data_list
*list
;
3080 for (list
= f
->font_data_list
; list
; list
= list
->next
)
3081 if (list
->driver
== driver
)
3089 /* Return the font used to draw character C by FACE at buffer position
3090 POS in window W. If STRING is non-nil, it is a string containing C
3091 at index POS. If C is negative, get C from the current buffer or
3095 font_at (c
, pos
, face
, w
, string
)
3109 multibyte
= ! NILP (current_buffer
->enable_multibyte_characters
);
3112 EMACS_INT pos_byte
= CHAR_TO_BYTE (pos
);
3114 c
= FETCH_CHAR (pos_byte
);
3117 c
= FETCH_BYTE (pos
);
3123 multibyte
= STRING_MULTIBYTE (string
);
3126 EMACS_INT pos_byte
= string_char_to_byte (string
, pos
);
3128 str
= SDATA (string
) + pos_byte
;
3129 c
= STRING_CHAR (str
, 0);
3132 c
= SDATA (string
)[pos
];
3136 f
= XFRAME (w
->frame
);
3137 if (! FRAME_WINDOW_P (f
))
3144 if (STRINGP (string
))
3145 face_id
= face_at_string_position (w
, string
, pos
, 0, -1, -1, &endptr
,
3146 DEFAULT_FACE_ID
, 0);
3148 face_id
= face_at_buffer_position (w
, pos
, -1, -1, &endptr
,
3150 face
= FACE_FROM_ID (f
, face_id
);
3154 int face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3155 face
= FACE_FROM_ID (f
, face_id
);
3157 if (! face
->font_info
)
3159 return font_find_object ((struct font
*) face
->font_info
);
3165 DEFUN ("fontp", Ffontp
, Sfontp
, 1, 1, 0,
3166 doc
: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3167 Return nil otherwise. */)
3171 return (FONTP (object
) ? Qt
: Qnil
);
3174 DEFUN ("font-spec", Ffont_spec
, Sfont_spec
, 0, MANY
, 0,
3175 doc
: /* Return a newly created font-spec with arguments as properties.
3177 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3178 valid font property name listed below:
3180 `:family', `:weight', `:slant', `:width'
3182 They are the same as face attributes of the same name. See
3183 `set-face-attribute'.
3187 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3191 VALUE must be a string or a symbol specifying the additional
3192 typographic style information of a font, e.g. ``sans''. Usually null.
3196 VALUE must be a string or a symbol specifying the charset registry and
3197 encoding of a font, e.g. ``iso8859-1''.
3201 VALUE must be a non-negative integer or a floating point number
3202 specifying the font size. It specifies the font size in 1/10 pixels
3203 (if VALUE is an integer), or in points (if VALUE is a float).
3204 usage: (font-spec ARGS ...) */)
3209 Lisp_Object spec
= Fmake_vector (make_number (FONT_SPEC_MAX
), Qnil
);
3212 for (i
= 0; i
< nargs
; i
+= 2)
3214 enum font_property_index prop
;
3215 Lisp_Object key
= args
[i
], val
= args
[i
+ 1];
3217 prop
= get_font_prop_index (key
, 0);
3218 if (prop
< FONT_EXTRA_INDEX
)
3219 ASET (spec
, prop
, val
);
3222 if (EQ (key
, QCname
))
3225 font_parse_name ((char *) SDATA (val
), spec
);
3227 font_put_extra (spec
, key
, val
);
3230 CHECK_VALIDATE_FONT_SPEC (spec
);
3235 DEFUN ("font-get", Ffont_get
, Sfont_get
, 2, 2, 0,
3236 doc
: /* Return the value of FONT's property KEY.
3237 FONT is a font-spec, a font-entity, or a font-object. */)
3239 Lisp_Object font
, key
;
3241 enum font_property_index idx
;
3243 if (FONT_OBJECT_P (font
))
3245 struct font
*fontp
= XSAVE_VALUE (font
)->pointer
;
3247 if (EQ (key
, QCotf
))
3249 if (fontp
->driver
->otf_capability
)
3250 return fontp
->driver
->otf_capability (fontp
);
3254 font
= fontp
->entity
;
3258 idx
= get_font_prop_index (key
, 0);
3259 if (idx
< FONT_EXTRA_INDEX
)
3260 return AREF (font
, idx
);
3261 if (FONT_ENTITY_P (font
))
3263 return Fcdr (Fassoc (key
, AREF (font
, FONT_EXTRA_INDEX
)));
3267 DEFUN ("font-put", Ffont_put
, Sfont_put
, 3, 3, 0,
3268 doc
: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
3269 (font_spec
, prop
, val
)
3270 Lisp_Object font_spec
, prop
, val
;
3272 enum font_property_index idx
;
3273 Lisp_Object extra
, slot
;
3275 CHECK_FONT_SPEC (font_spec
);
3276 idx
= get_font_prop_index (prop
, 0);
3277 if (idx
< FONT_EXTRA_INDEX
)
3278 return ASET (font_spec
, idx
, val
);
3279 extra
= AREF (font_spec
, FONT_EXTRA_INDEX
);
3280 slot
= Fassoc (extra
, prop
);
3282 extra
= Fcons (Fcons (prop
, val
), extra
);
3284 Fsetcdr (slot
, val
);
3288 DEFUN ("list-fonts", Flist_fonts
, Slist_fonts
, 1, 4, 0,
3289 doc
: /* List available fonts matching FONT-SPEC on the current frame.
3290 Optional 2nd argument FRAME specifies the target frame.
3291 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
3292 Optional 4th argument PREFER, if non-nil, is a font-spec to
3293 control the order of the returned list. Fonts are sorted by
3294 how they are close to PREFER. */)
3295 (font_spec
, frame
, num
, prefer
)
3296 Lisp_Object font_spec
, frame
, num
, prefer
;
3298 Lisp_Object vec
, list
, tail
;
3302 frame
= selected_frame
;
3303 CHECK_LIVE_FRAME (frame
);
3304 CHECK_VALIDATE_FONT_SPEC (font_spec
);
3312 if (! NILP (prefer
))
3313 CHECK_FONT (prefer
);
3315 vec
= font_list_entities (frame
, font_spec
);
3320 return Fcons (AREF (vec
, 0), Qnil
);
3322 if (! NILP (prefer
))
3323 vec
= font_sort_entites (vec
, prefer
, frame
, font_spec
);
3325 list
= tail
= Fcons (AREF (vec
, 0), Qnil
);
3326 if (n
== 0 || n
> len
)
3328 for (i
= 1; i
< n
; i
++)
3330 Lisp_Object val
= Fcons (AREF (vec
, i
), Qnil
);
3332 XSETCDR (tail
, val
);
3338 DEFUN ("list-families", Flist_families
, Slist_families
, 0, 1, 0,
3339 doc
: /* List available font families on the current frame.
3340 Optional argument FRAME specifies the target frame. */)
3345 struct font_driver_list
*driver_list
;
3349 frame
= selected_frame
;
3350 CHECK_LIVE_FRAME (frame
);
3353 for (driver_list
= f
->font_driver_list
; driver_list
;
3354 driver_list
= driver_list
->next
)
3355 if (driver_list
->driver
->list_family
)
3357 Lisp_Object val
= driver_list
->driver
->list_family (frame
);
3363 Lisp_Object tail
= list
;
3365 for (; CONSP (val
); val
= XCDR (val
))
3366 if (NILP (Fmemq (XCAR (val
), tail
)))
3367 list
= Fcons (XCAR (val
), list
);
3373 DEFUN ("find-font", Ffind_font
, Sfind_font
, 1, 2, 0,
3374 doc
: /* Return a font-entity matching with FONT-SPEC on the current frame.
3375 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
3377 Lisp_Object font_spec
, frame
;
3379 Lisp_Object val
= Flist_fonts (font_spec
, frame
, make_number (1), Qnil
);
3386 DEFUN ("font-xlfd-name", Ffont_xlfd_name
, Sfont_xlfd_name
, 1, 1, 0,
3387 doc
: /* Return XLFD name of FONT.
3388 FONT is a font-spec, font-entity, or font-object.
3389 If the name is too long for XLFD (maximum 255 chars), return nil. */)
3396 if (FONT_SPEC_P (font
))
3397 CHECK_VALIDATE_FONT_SPEC (font
);
3398 else if (FONT_ENTITY_P (font
))
3404 CHECK_FONT_GET_OBJECT (font
, fontp
);
3405 font
= fontp
->entity
;
3406 pixel_size
= fontp
->pixel_size
;
3409 if (font_unparse_xlfd (font
, pixel_size
, name
, 256) < 0)
3411 return build_string (name
);
3414 DEFUN ("clear-font-cache", Fclear_font_cache
, Sclear_font_cache
, 0, 0, 0,
3415 doc
: /* Clear font cache. */)
3418 Lisp_Object list
, frame
;
3420 FOR_EACH_FRAME (list
, frame
)
3422 FRAME_PTR f
= XFRAME (frame
);
3423 struct font_driver_list
*driver_list
= f
->font_driver_list
;
3425 for (; driver_list
; driver_list
= driver_list
->next
)
3426 if (driver_list
->on
)
3428 Lisp_Object cache
= driver_list
->driver
->get_cache (f
);
3433 && ! EQ (XCAR (XCAR (val
)), driver_list
->driver
->type
))
3435 xassert (! NILP (val
));
3436 val
= XCDR (XCAR (val
));
3437 if (XINT (XCAR (val
)) == 0)
3439 font_clear_cache (f
, XCAR (val
), driver_list
->driver
);
3440 XSETCDR (cache
, XCDR (val
));
3448 DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table
,
3449 Sinternal_set_font_style_table
, 2, 2, 0,
3450 doc
: /* Set font style table for PROP to TABLE.
3451 PROP must be `:weight', `:slant', or `:width'.
3452 TABLE must be an alist of symbols vs the corresponding numeric values
3453 sorted by numeric values. */)
3455 Lisp_Object prop
, table
;
3459 Lisp_Object tail
, val
;
3461 CHECK_SYMBOL (prop
);
3462 table_index
= (EQ (prop
, QCweight
) ? 0
3463 : EQ (prop
, QCslant
) ? 1
3464 : EQ (prop
, QCwidth
) ? 2
3466 if (table_index
>= ASIZE (font_style_table
))
3467 error ("Invalid font style property: %s", SDATA (SYMBOL_NAME (prop
)));
3468 table
= Fcopy_sequence (table
);
3470 for (tail
= table
; CONSP (tail
); tail
= XCDR (tail
))
3472 prop
= Fcar (XCAR (tail
));
3473 val
= Fcdr (XCAR (tail
));
3474 CHECK_SYMBOL (prop
);
3476 if (numeric
> XINT (val
))
3477 error ("Numeric values not sorted for %s", SDATA (SYMBOL_NAME (prop
)));
3478 else if (numeric
== XINT (val
))
3479 error ("Duplicate numeric values for %s", SDATA (SYMBOL_NAME (prop
)));
3480 numeric
= XINT (val
);
3481 XSETCAR (tail
, Fcons (prop
, val
));
3483 ASET (font_style_table
, table_index
, table
);
3487 /* The following three functions are still expremental. */
3489 DEFUN ("font-make-gstring", Ffont_make_gstring
, Sfont_make_gstring
, 2, 2, 0,
3490 doc
: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
3491 FONT-OBJECT may be nil if it is not yet known.
3493 G-string is sequence of glyphs of a specific font,
3494 and is a vector of this form:
3495 [ HEADER GLYPH ... ]
3496 HEADER is a vector of this form:
3497 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
3499 FONT-OBJECT is a font-object for all glyphs in the g-string,
3500 WIDTH thry DESCENT are the metrics (in pixels) of the whole G-string.
3501 GLYPH is a vector of this form:
3502 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
3503 [ [X-OFF Y-OFF WADJUST] | nil] ]
3505 FROM-IDX and TO-IDX are used internally and should not be touched.
3506 C is the character of the glyph.
3507 CODE is the glyph-code of C in FONT-OBJECT.
3508 WIDTH thry DESCENT are the metrics (in pixels) of the glyph.
3509 X-OFF and Y-OFF are offests to the base position for the glyph.
3510 WADJUST is the adjustment to the normal width of the glyph. */)
3512 Lisp_Object font_object
, num
;
3514 Lisp_Object gstring
, g
;
3518 if (! NILP (font_object
))
3519 CHECK_FONT_OBJECT (font_object
);
3522 len
= XINT (num
) + 1;
3523 gstring
= Fmake_vector (make_number (len
), Qnil
);
3524 g
= Fmake_vector (make_number (6), Qnil
);
3525 ASET (g
, 0, font_object
);
3526 ASET (gstring
, 0, g
);
3527 for (i
= 1; i
< len
; i
++)
3528 ASET (gstring
, i
, Fmake_vector (make_number (10), Qnil
));
3532 DEFUN ("font-fill-gstring", Ffont_fill_gstring
, Sfont_fill_gstring
, 4, 5, 0,
3533 doc
: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
3534 START and END specify the region to extract characters.
3535 If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
3536 where to extract characters.
3537 FONT-OBJECT may be nil if GSTRING already already contains one. */)
3538 (gstring
, font_object
, start
, end
, object
)
3539 Lisp_Object gstring
, font_object
, start
, end
, object
;
3545 CHECK_VECTOR (gstring
);
3546 if (NILP (font_object
))
3547 font_object
= LGSTRING_FONT (gstring
);
3548 CHECK_FONT_GET_OBJECT (font_object
, font
);
3550 if (STRINGP (object
))
3552 const unsigned char *p
;
3554 CHECK_NATNUM (start
);
3556 if (XINT (start
) > XINT (end
)
3557 || XINT (end
) > ASIZE (object
)
3558 || XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
3559 args_out_of_range_3 (object
, start
, end
);
3561 len
= XINT (end
) - XINT (start
);
3562 p
= SDATA (object
) + string_char_to_byte (object
, XINT (start
));
3563 for (i
= 0; i
< len
; i
++)
3565 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3566 /* Shut up GCC warning in comparison with
3567 MOST_POSITIVE_FIXNUM below. */
3570 c
= STRING_CHAR_ADVANCE (p
);
3571 cod
= code
= font
->driver
->encode_char (font
, c
);
3572 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
3574 LGLYPH_SET_FROM (g
, i
);
3575 LGLYPH_SET_TO (g
, i
);
3576 LGLYPH_SET_CHAR (g
, c
);
3577 LGLYPH_SET_CODE (g
, code
);
3584 if (! NILP (object
))
3585 Fset_buffer (object
);
3586 validate_region (&start
, &end
);
3587 if (XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
3588 args_out_of_range (start
, end
);
3589 len
= XINT (end
) - XINT (start
);
3591 pos_byte
= CHAR_TO_BYTE (pos
);
3592 for (i
= 0; i
< len
; i
++)
3594 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3595 /* Shut up GCC warning in comparison with
3596 MOST_POSITIVE_FIXNUM below. */
3599 FETCH_CHAR_ADVANCE (c
, pos
, pos_byte
);
3600 cod
= code
= font
->driver
->encode_char (font
, c
);
3601 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
3603 LGLYPH_SET_FROM (g
, i
);
3604 LGLYPH_SET_TO (g
, i
);
3605 LGLYPH_SET_CHAR (g
, c
);
3606 LGLYPH_SET_CODE (g
, code
);
3609 for (; i
< LGSTRING_LENGTH (gstring
); i
++)
3610 LGSTRING_SET_GLYPH (gstring
, i
, Qnil
);
3614 DEFUN ("font-shape-text", Ffont_shape_text
, Sfont_shape_text
, 3, 4, 0,
3615 doc
: /* Shape text between FROM and TO by FONT-OBJECT.
3616 If optional 4th argument STRING is non-nil, it is a string to shape,
3617 and FROM and TO are indices to the string.
3618 The value is the end position of the text that can be shaped by
3620 (from
, to
, font_object
, string
)
3621 Lisp_Object from
, to
, font_object
, string
;
3624 struct font_metrics metrics
;
3625 EMACS_INT start
, end
;
3626 Lisp_Object gstring
, n
;
3629 if (! FONT_OBJECT_P (font_object
))
3631 CHECK_FONT_GET_OBJECT (font_object
, font
);
3632 if (! font
->driver
->shape
)
3637 validate_region (&from
, &to
);
3638 start
= XFASTINT (from
);
3639 end
= XFASTINT (to
);
3640 modify_region (current_buffer
, start
, end
, 0);
3644 CHECK_STRING (string
);
3645 start
= XINT (from
);
3647 if (start
< 0 || start
> end
|| end
> SCHARS (string
))
3648 args_out_of_range_3 (string
, from
, to
);
3652 gstring
= Ffont_make_gstring (font_object
, make_number (len
));
3653 Ffont_fill_gstring (gstring
, font_object
, from
, to
, string
);
3655 /* Try at most three times with larger gstring each time. */
3656 for (i
= 0; i
< 3; i
++)
3658 Lisp_Object args
[2];
3660 n
= font
->driver
->shape (gstring
);
3664 args
[1] = Fmake_vector (make_number (len
), Qnil
);
3665 gstring
= Fvconcat (2, args
);
3667 if (! INTEGERP (n
) || XINT (n
) == 0)
3671 for (i
= 0; i
< len
;)
3674 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3675 EMACS_INT this_from
= LGLYPH_FROM (g
);
3676 EMACS_INT this_to
= LGLYPH_TO (g
) + 1;
3678 int need_composition
= 0;
3680 metrics
.lbearing
= LGLYPH_LBEARING (g
);
3681 metrics
.rbearing
= LGLYPH_RBEARING (g
);
3682 metrics
.ascent
= LGLYPH_ASCENT (g
);
3683 metrics
.descent
= LGLYPH_DESCENT (g
);
3684 if (NILP (LGLYPH_ADJUSTMENT (g
)))
3686 metrics
.width
= LGLYPH_WIDTH (g
);
3687 if (LGLYPH_CHAR (g
) == 0 || metrics
.width
== 0)
3688 need_composition
= 1;
3692 metrics
.width
= LGLYPH_WADJUST (g
);
3693 metrics
.lbearing
+= LGLYPH_XOFF (g
);
3694 metrics
.rbearing
+= LGLYPH_XOFF (g
);
3695 metrics
.ascent
-= LGLYPH_YOFF (g
);
3696 metrics
.descent
+= LGLYPH_YOFF (g
);
3697 need_composition
= 1;
3699 for (j
= i
+ 1; j
< len
; j
++)
3703 g
= LGSTRING_GLYPH (gstring
, j
);
3704 if (this_from
!= LGLYPH_FROM (g
))
3706 need_composition
= 1;
3707 x
= metrics
.width
+ LGLYPH_LBEARING (g
) + LGLYPH_XOFF (g
);
3708 if (metrics
.lbearing
> x
)
3709 metrics
.lbearing
= x
;
3710 x
= metrics
.width
+ LGLYPH_RBEARING (g
) + LGLYPH_XOFF (g
);
3711 if (metrics
.rbearing
< x
)
3712 metrics
.rbearing
= x
;
3713 x
= LGLYPH_ASCENT (g
) - LGLYPH_YOFF (g
);
3714 if (metrics
.ascent
< x
)
3716 x
= LGLYPH_DESCENT (g
) - LGLYPH_YOFF (g
);
3717 if (metrics
.descent
< x
)
3718 metrics
.descent
= x
;
3719 if (NILP (LGLYPH_ADJUSTMENT (g
)))
3720 metrics
.width
+= LGLYPH_WIDTH (g
);
3722 metrics
.width
+= LGLYPH_WADJUST (g
);
3725 if (need_composition
)
3727 gstr
= Ffont_make_gstring (font_object
, make_number (j
- i
));
3728 LGSTRING_SET_WIDTH (gstr
, metrics
.width
);
3729 LGSTRING_SET_LBEARING (gstr
, metrics
.lbearing
);
3730 LGSTRING_SET_RBEARING (gstr
, metrics
.rbearing
);
3731 LGSTRING_SET_ASCENT (gstr
, metrics
.ascent
);
3732 LGSTRING_SET_DESCENT (gstr
, metrics
.descent
);
3733 for (k
= i
; i
< j
; i
++)
3735 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3737 LGLYPH_SET_FROM (g
, LGLYPH_FROM (g
) - this_from
);
3738 LGLYPH_SET_TO (g
, LGLYPH_TO (g
) - this_from
);
3739 LGSTRING_SET_GLYPH (gstr
, i
- k
, LGSTRING_GLYPH (gstring
, i
));
3741 from
= make_number (start
+ this_from
);
3742 to
= make_number (start
+ this_to
);
3744 Fcompose_region_internal (from
, to
, gstr
, Qnil
);
3746 Fcompose_string_internal (string
, from
, to
, gstr
, Qnil
);
3755 DEFUN ("font-drive-otf", Ffont_drive_otf
, Sfont_drive_otf
, 6, 6, 0,
3756 doc
: /* Apply OpenType features on glyph-string GSTRING-IN.
3757 OTF-FEATURES specifies which features to apply in this format:
3758 (SCRIPT LANGSYS GSUB GPOS)
3760 SCRIPT is a symbol specifying a script tag of OpenType,
3761 LANGSYS is a symbol specifying a langsys tag of OpenType,
3762 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
3764 If LANGYS is nil, the default langsys is selected.
3766 The features are applied in the order they appear in the list. The
3767 symbol `*' means to apply all available features not present in this
3768 list, and the remaining features are ignored. For instance, (vatu
3769 pstf * haln) is to apply vatu and pstf in this order, then to apply
3770 all available features other than vatu, pstf, and haln.
3772 The features are applied to the glyphs in the range FROM and TO of
3773 the glyph-string GSTRING-IN.
3775 If some feature is actually applicable, the resulting glyphs are
3776 produced in the glyph-string GSTRING-OUT from the index INDEX. In
3777 this case, the value is the number of produced glyphs.
3779 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
3782 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
3783 produced in GSTRING-OUT, and the value is nil.
3785 See the documentation of `font-make-gstring' for the format of
3787 (otf_features
, gstring_in
, from
, to
, gstring_out
, index
)
3788 Lisp_Object otf_features
, gstring_in
, from
, to
, gstring_out
, index
;
3790 Lisp_Object font_object
= LGSTRING_FONT (gstring_in
);
3795 check_otf_features (otf_features
);
3796 CHECK_FONT_GET_OBJECT (font_object
, font
);
3797 if (! font
->driver
->otf_drive
)
3798 error ("Font backend %s can't drive OpenType GSUB table",
3799 SDATA (SYMBOL_NAME (font
->driver
->type
)));
3800 CHECK_CONS (otf_features
);
3801 CHECK_SYMBOL (XCAR (otf_features
));
3802 val
= XCDR (otf_features
);
3803 CHECK_SYMBOL (XCAR (val
));
3804 val
= XCDR (otf_features
);
3807 len
= check_gstring (gstring_in
);
3808 CHECK_VECTOR (gstring_out
);
3809 CHECK_NATNUM (from
);
3811 CHECK_NATNUM (index
);
3813 if (XINT (from
) >= XINT (to
) || XINT (to
) > len
)
3814 args_out_of_range_3 (from
, to
, make_number (len
));
3815 if (XINT (index
) >= ASIZE (gstring_out
))
3816 args_out_of_range (index
, make_number (ASIZE (gstring_out
)));
3817 num
= font
->driver
->otf_drive (font
, otf_features
,
3818 gstring_in
, XINT (from
), XINT (to
),
3819 gstring_out
, XINT (index
), 0);
3822 return make_number (num
);
3825 DEFUN ("font-otf-alternates", Ffont_otf_alternates
, Sfont_otf_alternates
,
3827 doc
: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
3828 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
3830 (SCRIPT LANGSYS FEATURE ...)
3831 See the documentation of `font-otf-gsub' for more detail.
3833 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
3834 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
3835 character code corresponding to the glyph or nil if there's no
3836 corresponding character. */)
3837 (font_object
, character
, otf_features
)
3838 Lisp_Object font_object
, character
, otf_features
;
3841 Lisp_Object gstring_in
, gstring_out
, g
;
3842 Lisp_Object alternates
;
3845 CHECK_FONT_GET_OBJECT (font_object
, font
);
3846 if (! font
->driver
->otf_drive
)
3847 error ("Font backend %s can't drive OpenType GSUB table",
3848 SDATA (SYMBOL_NAME (font
->driver
->type
)));
3849 CHECK_CHARACTER (character
);
3850 CHECK_CONS (otf_features
);
3852 gstring_in
= Ffont_make_gstring (font_object
, make_number (1));
3853 g
= LGSTRING_GLYPH (gstring_in
, 0);
3854 LGLYPH_SET_CHAR (g
, XINT (character
));
3855 gstring_out
= Ffont_make_gstring (font_object
, make_number (10));
3856 while ((num
= font
->driver
->otf_drive (font
, otf_features
, gstring_in
, 0, 1,
3857 gstring_out
, 0, 1)) < 0)
3858 gstring_out
= Ffont_make_gstring (font_object
,
3859 make_number (ASIZE (gstring_out
) * 2));
3861 for (i
= 0; i
< num
; i
++)
3863 Lisp_Object g
= LGSTRING_GLYPH (gstring_out
, i
);
3864 int c
= LGLYPH_CHAR (g
);
3865 unsigned code
= LGLYPH_CODE (g
);
3867 alternates
= Fcons (Fcons (make_number (code
),
3868 c
> 0 ? make_number (c
) : Qnil
),
3871 return Fnreverse (alternates
);
3877 DEFUN ("open-font", Fopen_font
, Sopen_font
, 1, 3, 0,
3878 doc
: /* Open FONT-ENTITY. */)
3879 (font_entity
, size
, frame
)
3880 Lisp_Object font_entity
;
3886 CHECK_FONT_ENTITY (font_entity
);
3888 size
= AREF (font_entity
, FONT_SIZE_INDEX
);
3889 CHECK_NUMBER (size
);
3891 frame
= selected_frame
;
3892 CHECK_LIVE_FRAME (frame
);
3894 isize
= XINT (size
);
3898 isize
= POINT_TO_PIXEL (- isize
, XFRAME (frame
)->resy
);
3900 return font_open_entity (XFRAME (frame
), font_entity
, isize
);
3903 DEFUN ("close-font", Fclose_font
, Sclose_font
, 1, 2, 0,
3904 doc
: /* Close FONT-OBJECT. */)
3905 (font_object
, frame
)
3906 Lisp_Object font_object
, frame
;
3908 CHECK_FONT_OBJECT (font_object
);
3910 frame
= selected_frame
;
3911 CHECK_LIVE_FRAME (frame
);
3912 font_close_object (XFRAME (frame
), font_object
);
3916 DEFUN ("query-font", Fquery_font
, Squery_font
, 1, 1, 0,
3917 doc
: /* Return information about FONT-OBJECT.
3918 The value is a vector:
3919 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
3922 NAME is a string of the font name (or nil if the font backend doesn't
3925 FILENAME is a string of the font file (or nil if the font backend
3926 doesn't provide a file name).
3928 PIXEL-SIZE is a pixel size by which the font is opened.
3930 SIZE is a maximum advance width of the font in pixel.
3932 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
3935 CAPABILITY is a list whose first element is a symbol representing the
3936 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
3937 remaining elements describes a detail of the font capability.
3939 If the font is OpenType font, the form of the list is
3940 \(opentype GSUB GPOS)
3941 where GSUB shows which "GSUB" features the font supports, and GPOS
3942 shows which "GPOS" features the font supports. Both GSUB and GPOS are
3943 lists of the format:
3944 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
3946 If the font is not OpenType font, currently the length of the form is
3949 SCRIPT is a symbol representing OpenType script tag.
3951 LANGSYS is a symbol representing OpenType langsys tag, or nil
3952 representing the default langsys.
3954 FEATURE is a symbol representing OpenType feature tag.
3956 If the font is not OpenType font, CAPABILITY is nil. */)
3958 Lisp_Object font_object
;
3963 CHECK_FONT_GET_OBJECT (font_object
, font
);
3965 val
= Fmake_vector (make_number (9), Qnil
);
3966 if (font
->font
.full_name
)
3967 ASET (val
, 0, make_unibyte_string (font
->font
.full_name
,
3968 strlen (font
->font
.full_name
)));
3969 if (font
->file_name
)
3970 ASET (val
, 1, make_unibyte_string (font
->file_name
,
3971 strlen (font
->file_name
)));
3972 ASET (val
, 2, make_number (font
->pixel_size
));
3973 ASET (val
, 3, make_number (font
->font
.size
));
3974 ASET (val
, 4, make_number (font
->ascent
));
3975 ASET (val
, 5, make_number (font
->descent
));
3976 ASET (val
, 6, make_number (font
->font
.space_width
));
3977 ASET (val
, 7, make_number (font
->font
.average_width
));
3978 if (font
->driver
->otf_capability
)
3979 ASET (val
, 8, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
3981 ASET (val
, 8, Fcons (font
->format
, Qnil
));
3985 DEFUN ("get-font-glyphs", Fget_font_glyphs
, Sget_font_glyphs
, 2, 2, 0,
3986 doc
: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
3987 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
3988 (font_object
, string
)
3989 Lisp_Object font_object
, string
;
3995 CHECK_FONT_GET_OBJECT (font_object
, font
);
3996 CHECK_STRING (string
);
3997 len
= SCHARS (string
);
3998 vec
= Fmake_vector (make_number (len
), Qnil
);
3999 for (i
= 0; i
< len
; i
++)
4001 Lisp_Object ch
= Faref (string
, make_number (i
));
4006 struct font_metrics metrics
;
4008 cod
= code
= font
->driver
->encode_char (font
, c
);
4009 if (code
== FONT_INVALID_CODE
)
4011 val
= Fmake_vector (make_number (6), Qnil
);
4012 if (cod
<= MOST_POSITIVE_FIXNUM
)
4013 ASET (val
, 0, make_number (code
));
4015 ASET (val
, 0, Fcons (make_number (code
>> 16),
4016 make_number (code
& 0xFFFF)));
4017 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4018 ASET (val
, 1, make_number (metrics
.lbearing
));
4019 ASET (val
, 2, make_number (metrics
.rbearing
));
4020 ASET (val
, 3, make_number (metrics
.width
));
4021 ASET (val
, 4, make_number (metrics
.ascent
));
4022 ASET (val
, 5, make_number (metrics
.descent
));
4028 DEFUN ("font-match-p", Ffont_match_p
, Sfont_match_p
, 2, 2, 0,
4029 doc
: /* Return t iff font-spec SPEC matches with FONT.
4030 FONT is a font-spec, font-entity, or font-object. */)
4032 Lisp_Object spec
, font
;
4034 CHECK_FONT_SPEC (spec
);
4035 if (FONT_OBJECT_P (font
))
4036 font
= ((struct font
*) XSAVE_VALUE (font
)->pointer
)->entity
;
4037 else if (! FONT_ENTITY_P (font
))
4038 CHECK_FONT_SPEC (font
);
4040 return (font_match_p (spec
, font
) ? Qt
: Qnil
);
4043 DEFUN ("font-at", Ffont_at
, Sfont_at
, 1, 3, 0,
4044 doc
: /* Return a font-object for displaying a character at POSITION.
4045 Optional second arg WINDOW, if non-nil, is a window displaying
4046 the current buffer. It defaults to the currently selected window. */)
4047 (position
, window
, string
)
4048 Lisp_Object position
, window
, string
;
4055 CHECK_NUMBER_COERCE_MARKER (position
);
4056 pos
= XINT (position
);
4057 if (pos
< BEGV
|| pos
>= ZV
)
4058 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
4065 CHECK_NUMBER (position
);
4066 CHECK_STRING (string
);
4067 pos
= XINT (position
);
4068 if (pos
< 0 || pos
>= SCHARS (string
))
4069 args_out_of_range (string
, position
);
4072 window
= selected_window
;
4073 CHECK_LIVE_WINDOW (window
);
4074 w
= XWINDOW (window
);
4076 return font_at (-1, pos
, NULL
, w
, string
);
4080 DEFUN ("draw-string", Fdraw_string
, Sdraw_string
, 2, 2, 0,
4081 doc
: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4082 The value is a number of glyphs drawn.
4083 Type C-l to recover what previously shown. */)
4084 (font_object
, string
)
4085 Lisp_Object font_object
, string
;
4087 Lisp_Object frame
= selected_frame
;
4088 FRAME_PTR f
= XFRAME (frame
);
4094 CHECK_FONT_GET_OBJECT (font_object
, font
);
4095 CHECK_STRING (string
);
4096 len
= SCHARS (string
);
4097 code
= alloca (sizeof (unsigned) * len
);
4098 for (i
= 0; i
< len
; i
++)
4100 Lisp_Object ch
= Faref (string
, make_number (i
));
4104 code
[i
] = font
->driver
->encode_char (font
, c
);
4105 if (code
[i
] == FONT_INVALID_CODE
)
4108 face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4110 if (font
->driver
->prepare_face
)
4111 font
->driver
->prepare_face (f
, face
);
4112 width
= font
->driver
->text_extents (font
, code
, i
, NULL
);
4113 len
= font
->driver
->draw_text (f
, face
, 0, font
->ascent
, code
, i
, width
);
4114 if (font
->driver
->done_face
)
4115 font
->driver
->done_face (f
, face
);
4117 return make_number (len
);
4121 #endif /* FONT_DEBUG */
4124 extern void syms_of_ftfont
P_ (());
4125 extern void syms_of_xfont
P_ (());
4126 extern void syms_of_xftfont
P_ (());
4127 extern void syms_of_ftxfont
P_ (());
4128 extern void syms_of_bdffont
P_ (());
4129 extern void syms_of_w32font
P_ (());
4130 extern void syms_of_atmfont
P_ (());
4135 sort_shift_bits
[FONT_SLANT_INDEX
] = 0;
4136 sort_shift_bits
[FONT_WEIGHT_INDEX
] = 7;
4137 sort_shift_bits
[FONT_SIZE_INDEX
] = 14;
4138 sort_shift_bits
[FONT_WIDTH_INDEX
] = 21;
4139 sort_shift_bits
[FONT_ADSTYLE_INDEX
] = 28;
4140 sort_shift_bits
[FONT_FOUNDRY_INDEX
] = 29;
4141 sort_shift_bits
[FONT_FAMILY_INDEX
] = 30;
4142 sort_shift_bits
[FONT_REGISTRY_INDEX
] = 31;
4143 /* Note that sort_shift_bits[FONT_TYPE_INDEX] is never used. */
4145 staticpro (&font_style_table
);
4146 font_style_table
= Fmake_vector (make_number (3), Qnil
);
4148 staticpro (&font_family_alist
);
4149 font_family_alist
= Qnil
;
4151 staticpro (&font_charset_alist
);
4152 font_charset_alist
= Qnil
;
4154 DEFSYM (Qopentype
, "opentype");
4156 DEFSYM (Qiso8859_1
, "iso8859-1");
4157 DEFSYM (Qiso10646_1
, "iso10646-1");
4158 DEFSYM (Qunicode_bmp
, "unicode-bmp");
4159 DEFSYM (Qunicode_sip
, "unicode-sip");
4161 DEFSYM (QCotf
, ":otf");
4162 DEFSYM (QClanguage
, ":language");
4163 DEFSYM (QCscript
, ":script");
4164 DEFSYM (QCantialias
, ":antialias");
4166 DEFSYM (QCfoundry
, ":foundry");
4167 DEFSYM (QCadstyle
, ":adstyle");
4168 DEFSYM (QCregistry
, ":registry");
4169 DEFSYM (QCspacing
, ":spacing");
4170 DEFSYM (QCdpi
, ":dpi");
4171 DEFSYM (QCscalable
, ":scalable");
4172 DEFSYM (QCextra
, ":extra");
4179 staticpro (&null_string
);
4180 null_string
= build_string ("");
4181 staticpro (&null_vector
);
4182 null_vector
= Fmake_vector (make_number (0), Qnil
);
4184 staticpro (&scratch_font_spec
);
4185 scratch_font_spec
= Ffont_spec (0, NULL
);
4186 staticpro (&scratch_font_prefer
);
4187 scratch_font_prefer
= Ffont_spec (0, NULL
);
4190 staticpro (&otf_list
);
4195 defsubr (&Sfont_spec
);
4196 defsubr (&Sfont_get
);
4197 defsubr (&Sfont_put
);
4198 defsubr (&Slist_fonts
);
4199 defsubr (&Slist_families
);
4200 defsubr (&Sfind_font
);
4201 defsubr (&Sfont_xlfd_name
);
4202 defsubr (&Sclear_font_cache
);
4203 defsubr (&Sinternal_set_font_style_table
);
4204 defsubr (&Sfont_make_gstring
);
4205 defsubr (&Sfont_fill_gstring
);
4206 defsubr (&Sfont_shape_text
);
4207 defsubr (&Sfont_drive_otf
);
4208 defsubr (&Sfont_otf_alternates
);
4211 defsubr (&Sopen_font
);
4212 defsubr (&Sclose_font
);
4213 defsubr (&Squery_font
);
4214 defsubr (&Sget_font_glyphs
);
4215 defsubr (&Sfont_match_p
);
4216 defsubr (&Sfont_at
);
4218 defsubr (&Sdraw_string
);
4220 #endif /* FONT_DEBUG */
4222 #ifdef USE_FONT_BACKEND
4223 if (enable_font_backend
)
4225 #ifdef HAVE_FREETYPE
4227 #ifdef HAVE_X_WINDOWS
4232 #endif /* HAVE_XFT */
4233 #endif /* HAVE_X_WINDOWS */
4234 #else /* not HAVE_FREETYPE */
4235 #ifdef HAVE_X_WINDOWS
4237 #endif /* HAVE_X_WINDOWS */
4238 #endif /* not HAVE_FREETYPE */
4241 #endif /* HAVE_BDFFONT */
4244 #endif /* WINDOWSNT */
4249 #endif /* USE_FONT_BACKEND */
4252 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
4253 (do not change this comment) */