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
));
1465 len
+= (strlen (style_names
[i
- FONT_WEIGHT_INDEX
])
1466 + 2 + SBYTES (SYMBOL_NAME (val
))); /* :xxx=NAME */
1468 styles
[i
- FONT_WEIGHT_INDEX
] = val
;
1471 val
= AREF (font
, FONT_EXTRA_INDEX
);
1472 if (FONT_ENTITY_P (font
)
1473 && EQ (AREF (font
, FONT_TYPE_INDEX
), Qx
))
1477 /* VAL is a symbol of name `RESX-RESY-SPACING-AVWIDTH'. */
1478 p
= (char *) SDATA (SYMBOL_NAME (val
));
1480 for (p
++; *p
!= '-'; p
++); /* skip RESX */
1481 for (p
++; *p
!= '-'; p
++); /* skip RESY */
1482 spacing
= (*p
== 'c' ? FONT_SPACING_CHARCELL
1483 : *p
== 'm' ? FONT_SPACING_MONO
1484 : FONT_SPACING_PROPORTIONAL
);
1485 for (p
++; *p
!= '-'; p
++); /* skip SPACING */
1486 scalable
= (atoi (p
) == 0);
1487 /* The longest pattern is ":dpi=NUM:scalable=False:spacing=100" */
1494 dpi
= spacing
= scalable
= -1;
1495 elt
= assq_no_quit (QCdpi
, val
);
1497 dpi
= XINT (XCDR (elt
)), len
+= 15; /* for ":dpi=NUM" */
1498 elt
= assq_no_quit (QCspacing
, val
);
1500 spacing
= XINT (XCDR (elt
)), len
+= 12; /* for ":spacing=100" */
1501 elt
= assq_no_quit (QCscalable
, val
);
1503 scalable
= ! NILP (XCDR (elt
)), len
+= 15; /* for ":scalable=False" */
1509 if (! NILP (AREF (font
, FONT_FAMILY_INDEX
)))
1510 p
+= sprintf(p
, "%s",
1511 SDATA (SYMBOL_NAME (AREF (font
, FONT_FAMILY_INDEX
))));
1515 p
+= sprintf (p
, "%d", point_size
);
1517 p
+= sprintf (p
, "-%d", point_size
);
1519 else if (pixel_size
> 0)
1520 p
+= sprintf (p
, ":pixelsize=%d", pixel_size
);
1521 if (SYMBOLP (AREF (font
, FONT_FOUNDRY_INDEX
))
1522 && ! NILP (AREF (font
, FONT_FOUNDRY_INDEX
)))
1523 p
+= sprintf (p
, ":foundry=%s",
1524 SDATA (SYMBOL_NAME (AREF (font
, FONT_FOUNDRY_INDEX
))));
1525 for (i
= 0; i
< 3; i
++)
1526 if (SYMBOLP (styles
[i
]) && ! NILP (styles
[i
]))
1527 p
+= sprintf (p
, ":%s=%s", style_names
[i
],
1528 SDATA (SYMBOL_NAME (styles
[i
])));
1530 p
+= sprintf (p
, ":dpi=%d", dpi
);
1532 p
+= sprintf (p
, ":spacing=%d", spacing
);
1534 p
+= sprintf (p
, ":scalable=True");
1535 else if (scalable
== 0)
1536 p
+= sprintf (p
, ":scalable=False");
1540 /* Parse NAME (null terminated) and store information in FONT
1541 (font-spec or font-entity). If NAME is successfully parsed, return
1542 0. Otherwise return -1.
1544 If NAME is XLFD and FONT is a font-entity, store
1545 RESX-RESY-SPACING-AVWIDTH information as a symbol in
1546 FONT_EXTRA_INDEX. */
1549 font_parse_name (name
, font
)
1553 if (name
[0] == '-' || index (name
, '*'))
1554 return font_parse_xlfd (name
, font
);
1555 return font_parse_fcname (name
, font
);
1558 /* Merge old style font specification (either a font name NAME or a
1559 combination of a family name FAMILY and a registry name REGISTRY
1560 into the font specification SPEC. */
1563 font_merge_old_spec (name
, family
, registry
, spec
)
1564 Lisp_Object name
, family
, registry
, spec
;
1568 if (font_parse_xlfd ((char *) SDATA (name
), spec
) < 0)
1570 Lisp_Object extra
= Fcons (Fcons (QCname
, name
), Qnil
);
1572 ASET (spec
, FONT_EXTRA_INDEX
, extra
);
1577 if (! NILP (family
))
1582 xassert (STRINGP (family
));
1583 len
= SBYTES (family
);
1584 p0
= (char *) SDATA (family
);
1585 p1
= index (p0
, '-');
1588 if ((*p0
!= '*' || p1
- p0
> 1)
1589 && NILP (AREF (spec
, FONT_FOUNDRY_INDEX
)))
1590 ASET (spec
, FONT_FOUNDRY_INDEX
,
1591 intern_downcase (p0
, p1
- p0
));
1592 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
1593 ASET (spec
, FONT_FAMILY_INDEX
,
1594 intern_downcase (p1
+ 1, len
- (p1
+ 1 - p0
)));
1596 else if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
1597 ASET (spec
, FONT_FAMILY_INDEX
, intern_downcase (p0
, len
));
1599 if (! NILP (registry
)
1600 && NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
1601 ASET (spec
, FONT_REGISTRY_INDEX
,
1602 intern_downcase ((char *) SDATA (registry
), SBYTES (registry
)));
1607 /* This part (through the next ^L) is still experimental and never
1608 tested. We may drastically change codes. */
1612 #define LGSTRING_HEADER_SIZE 6
1613 #define LGSTRING_GLYPH_SIZE 8
1616 check_gstring (gstring
)
1617 Lisp_Object gstring
;
1622 CHECK_VECTOR (gstring
);
1623 val
= AREF (gstring
, 0);
1625 if (ASIZE (val
) < LGSTRING_HEADER_SIZE
)
1627 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring
));
1628 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
)))
1629 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
));
1630 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
)))
1631 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
));
1632 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
)))
1633 CHECK_NATNUM (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
));
1634 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1635 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1636 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1637 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1639 for (i
= 0; i
< LGSTRING_LENGTH (gstring
); i
++)
1641 val
= LGSTRING_GLYPH (gstring
, i
);
1643 if (ASIZE (val
) < LGSTRING_GLYPH_SIZE
)
1645 if (NILP (AREF (val
, LGLYPH_IX_CHAR
)))
1647 CHECK_NATNUM (AREF (val
, LGLYPH_IX_FROM
));
1648 CHECK_NATNUM (AREF (val
, LGLYPH_IX_TO
));
1649 CHECK_CHARACTER (AREF (val
, LGLYPH_IX_CHAR
));
1650 if (!NILP (AREF (val
, LGLYPH_IX_CODE
)))
1651 CHECK_NATNUM (AREF (val
, LGLYPH_IX_CODE
));
1652 if (!NILP (AREF (val
, LGLYPH_IX_WIDTH
)))
1653 CHECK_NATNUM (AREF (val
, LGLYPH_IX_WIDTH
));
1654 if (!NILP (AREF (val
, LGLYPH_IX_ADJUSTMENT
)))
1656 val
= AREF (val
, LGLYPH_IX_ADJUSTMENT
);
1658 if (ASIZE (val
) < 3)
1660 for (j
= 0; j
< 3; j
++)
1661 CHECK_NUMBER (AREF (val
, j
));
1666 error ("Invalid glyph-string format");
1671 check_otf_features (otf_features
)
1672 Lisp_Object otf_features
;
1674 Lisp_Object val
, elt
;
1676 CHECK_CONS (otf_features
);
1677 CHECK_SYMBOL (XCAR (otf_features
));
1678 otf_features
= XCDR (otf_features
);
1679 CHECK_CONS (otf_features
);
1680 CHECK_SYMBOL (XCAR (otf_features
));
1681 otf_features
= XCDR (otf_features
);
1682 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1684 CHECK_SYMBOL (Fcar (val
));
1685 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1686 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val
)));
1688 otf_features
= XCDR (otf_features
);
1689 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1691 CHECK_SYMBOL (Fcar (val
));
1692 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1693 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val
)));
1700 Lisp_Object otf_list
;
1703 otf_tag_symbol (tag
)
1708 OTF_tag_name (tag
, name
);
1709 return Fintern (make_unibyte_string (name
, 4), Qnil
);
1713 otf_open (entity
, file
)
1717 Lisp_Object val
= Fassoc (entity
, otf_list
);
1721 otf
= XSAVE_VALUE (XCDR (val
))->pointer
;
1724 otf
= file
? OTF_open (file
) : NULL
;
1725 val
= make_save_value (otf
, 0);
1726 otf_list
= Fcons (Fcons (entity
, val
), otf_list
);
1732 /* Return a list describing which scripts/languages FONT supports by
1733 which GSUB/GPOS features of OpenType tables. See the comment of
1734 (struct font_driver).otf_capability. */
1737 font_otf_capability (font
)
1741 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
1744 otf
= otf_open (font
->entity
, font
->file_name
);
1747 for (i
= 0; i
< 2; i
++)
1749 OTF_GSUB_GPOS
*gsub_gpos
;
1750 Lisp_Object script_list
= Qnil
;
1753 if (OTF_get_features (otf
, i
== 0) < 0)
1755 gsub_gpos
= i
== 0 ? otf
->gsub
: otf
->gpos
;
1756 for (j
= gsub_gpos
->ScriptList
.ScriptCount
- 1; j
>= 0; j
--)
1758 OTF_Script
*script
= gsub_gpos
->ScriptList
.Script
+ j
;
1759 Lisp_Object langsys_list
= Qnil
;
1760 Lisp_Object script_tag
= otf_tag_symbol (script
->ScriptTag
);
1763 for (k
= script
->LangSysCount
; k
>= 0; k
--)
1765 OTF_LangSys
*langsys
;
1766 Lisp_Object feature_list
= Qnil
;
1767 Lisp_Object langsys_tag
;
1770 if (k
== script
->LangSysCount
)
1772 langsys
= &script
->DefaultLangSys
;
1777 langsys
= script
->LangSys
+ k
;
1779 = otf_tag_symbol (script
->LangSysRecord
[k
].LangSysTag
);
1781 for (l
= langsys
->FeatureCount
- 1; l
>= 0; l
--)
1783 OTF_Feature
*feature
1784 = gsub_gpos
->FeatureList
.Feature
+ langsys
->FeatureIndex
[l
];
1785 Lisp_Object feature_tag
1786 = otf_tag_symbol (feature
->FeatureTag
);
1788 feature_list
= Fcons (feature_tag
, feature_list
);
1790 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
1793 script_list
= Fcons (Fcons (script_tag
, langsys_list
),
1798 XSETCAR (capability
, script_list
);
1800 XSETCDR (capability
, script_list
);
1806 /* Parse OTF features in SPEC and write a proper features spec string
1807 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1808 assured that the sufficient memory has already allocated for
1812 generate_otf_features (spec
, features
)
1822 for (asterisk
= 0; CONSP (spec
); spec
= XCDR (spec
))
1828 if (SREF (SYMBOL_NAME (val
), 0) == '*')
1833 else if (! asterisk
)
1835 val
= SYMBOL_NAME (val
);
1836 p
+= sprintf (p
, "%s", SDATA (val
));
1840 val
= SYMBOL_NAME (val
);
1841 p
+= sprintf (p
, "~%s", SDATA (val
));
1845 error ("OTF spec too long");
1850 font_otf_DeviceTable (device_table
)
1851 OTF_DeviceTable
*device_table
;
1853 int len
= device_table
->StartSize
- device_table
->EndSize
+ 1;
1855 return Fcons (make_number (len
),
1856 make_unibyte_string (device_table
->DeltaValue
, len
));
1860 font_otf_ValueRecord (value_format
, value_record
)
1862 OTF_ValueRecord
*value_record
;
1864 Lisp_Object val
= Fmake_vector (make_number (8), Qnil
);
1866 if (value_format
& OTF_XPlacement
)
1867 ASET (val
, 0, make_number (value_record
->XPlacement
));
1868 if (value_format
& OTF_YPlacement
)
1869 ASET (val
, 1, make_number (value_record
->YPlacement
));
1870 if (value_format
& OTF_XAdvance
)
1871 ASET (val
, 2, make_number (value_record
->XAdvance
));
1872 if (value_format
& OTF_YAdvance
)
1873 ASET (val
, 3, make_number (value_record
->YAdvance
));
1874 if (value_format
& OTF_XPlaDevice
)
1875 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XPlaDevice
));
1876 if (value_format
& OTF_YPlaDevice
)
1877 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YPlaDevice
));
1878 if (value_format
& OTF_XAdvDevice
)
1879 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XAdvDevice
));
1880 if (value_format
& OTF_YAdvDevice
)
1881 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YAdvDevice
));
1886 font_otf_Anchor (anchor
)
1891 val
= Fmake_vector (make_number (anchor
->AnchorFormat
+ 1), Qnil
);
1892 ASET (val
, 0, make_number (anchor
->XCoordinate
));
1893 ASET (val
, 1, make_number (anchor
->YCoordinate
));
1894 if (anchor
->AnchorFormat
== 2)
1895 ASET (val
, 2, make_number (anchor
->f
.f1
.AnchorPoint
));
1898 ASET (val
, 3, font_otf_DeviceTable (&anchor
->f
.f2
.XDeviceTable
));
1899 ASET (val
, 4, font_otf_DeviceTable (&anchor
->f
.f2
.YDeviceTable
));
1904 #endif /* HAVE_LIBOTF */
1906 /* G-string (glyph string) handler */
1908 /* G-string is a vector of the form [HEADER GLYPH ...].
1909 See the docstring of `font-make-gstring' for more detail. */
1912 font_prepare_composition (cmp
, f
)
1913 struct composition
*cmp
;
1917 = AREF (XHASH_TABLE (composition_hash_table
)->key_and_value
,
1918 cmp
->hash_index
* 2);
1920 cmp
->font
= XSAVE_VALUE (LGSTRING_FONT (gstring
))->pointer
;
1921 cmp
->glyph_len
= LGSTRING_LENGTH (gstring
);
1922 cmp
->pixel_width
= LGSTRING_WIDTH (gstring
);
1923 cmp
->lbearing
= LGSTRING_LBEARING (gstring
);
1924 cmp
->rbearing
= LGSTRING_RBEARING (gstring
);
1925 cmp
->ascent
= LGSTRING_ASCENT (gstring
);
1926 cmp
->descent
= LGSTRING_DESCENT (gstring
);
1927 cmp
->width
= cmp
->pixel_width
/ FRAME_COLUMN_WIDTH (f
);
1928 if (cmp
->width
== 0)
1937 static unsigned font_score
P_ ((Lisp_Object
, Lisp_Object
*));
1938 static int font_compare
P_ ((const void *, const void *));
1939 static Lisp_Object font_sort_entites
P_ ((Lisp_Object
, Lisp_Object
,
1940 Lisp_Object
, Lisp_Object
));
1942 /* We sort fonts by scoring each of them against a specified
1943 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1944 the value is, the closer the font is to the font-spec.
1946 Each 1-bit of the highest 4 bits of the score is used for atomic
1947 properties FOUNDRY, FAMILY, ADSTYLE, and REGISTRY.
1949 Each 7-bit in the lowest 28 bits are used for numeric properties
1950 WEIGHT, SLANT, WIDTH, and SIZE. */
1952 /* How many bits to shift to store the difference value of each font
1953 property in a score. */
1954 static int sort_shift_bits
[FONT_SIZE_INDEX
+ 1];
1956 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1957 The return value indicates how different ENTITY is compared with
1961 font_score (entity
, spec_prop
)
1962 Lisp_Object entity
, *spec_prop
;
1966 /* Score four atomic fields. Maximum difference is 1. */
1967 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
1968 if (! NILP (spec_prop
[i
])
1969 && ! EQ (spec_prop
[i
], AREF (entity
, i
)))
1970 score
|= 1 << sort_shift_bits
[i
];
1972 /* Score four numeric fields. Maximum difference is 127. */
1973 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
1975 Lisp_Object entity_val
= AREF (entity
, i
);
1976 Lisp_Object spec_val
= spec_prop
[i
];
1978 /* If weight and slant are unspecified, score normal lower (low wins). */
1979 if (NILP (spec_val
))
1981 if (i
== FONT_WEIGHT_INDEX
|| i
== FONT_SLANT_INDEX
)
1982 spec_val
= prop_name_to_numeric (i
, build_string ("normal"));
1985 if (! NILP (spec_val
) && ! EQ (spec_val
, entity_val
))
1987 if (! INTEGERP (entity_val
))
1988 score
|= 127 << sort_shift_bits
[i
];
1991 int diff
= XINT (entity_val
) - XINT (spec_val
);
1995 if (i
== FONT_SIZE_INDEX
)
1997 if (XINT (entity_val
) > 0
1998 && diff
> FONT_PIXEL_SIZE_QUANTUM
)
1999 score
|= min (diff
, 127) << sort_shift_bits
[i
];
2002 else if (i
== FONT_WEIGHT_INDEX
)
2004 /* Windows uses a much wider range for weight (100-900)
2005 compared with freetype (0-210), so scale down the
2006 difference. A more general way of doing this
2007 would be to look up the values of regular and bold
2008 and/or light and calculate the scale factor from them,
2009 but the lookup would be expensive, and if only Windows
2010 needs it, not worth the effort. */
2011 score
|= min (diff
/ 4, 127) << sort_shift_bits
[i
];
2015 score
|= min (diff
, 127) << sort_shift_bits
[i
];
2024 /* The comparison function for qsort. */
2027 font_compare (d1
, d2
)
2028 const void *d1
, *d2
;
2030 return (*(unsigned *) d1
< *(unsigned *) d2
2031 ? -1 : *(unsigned *) d1
> *(unsigned *) d2
);
2035 /* The structure for elements being sorted by qsort. */
2036 struct font_sort_data
2043 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2044 If PREFER specifies a point-size, calculate the corresponding
2045 pixel-size from QCdpi property of PREFER or from the Y-resolution
2046 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
2047 get the font-entities in VEC. */
2050 font_sort_entites (vec
, prefer
, frame
, spec
)
2051 Lisp_Object vec
, prefer
, frame
, spec
;
2053 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2055 struct font_sort_data
*data
;
2062 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
2063 prefer_prop
[i
] = AREF (prefer
, i
);
2067 /* As it is assured that all fonts in VEC match with SPEC, we
2068 should ignore properties specified in SPEC. So, set the
2069 corresponding properties in PREFER_PROP to nil. */
2070 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
2071 if (! NILP (AREF (spec
, i
)))
2072 prefer_prop
[i
++] = Qnil
;
2075 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2076 prefer_prop
[FONT_SIZE_INDEX
]
2077 = make_number (font_pixel_size (XFRAME (frame
), prefer
));
2079 /* Scoring and sorting. */
2080 SAFE_ALLOCA (data
, struct font_sort_data
*, (sizeof *data
) * len
);
2081 for (i
= 0; i
< len
; i
++)
2083 data
[i
].entity
= AREF (vec
, i
);
2084 data
[i
].score
= font_score (data
[i
].entity
, prefer_prop
);
2086 qsort (data
, len
, sizeof *data
, font_compare
);
2087 for (i
= 0; i
< len
; i
++)
2088 ASET (vec
, i
, data
[i
].entity
);
2095 /* API of Font Service Layer. */
2097 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2098 sort_shift_bits. Finternal_set_font_selection_order calls this
2099 function with font_sort_order after setting up it. */
2102 font_update_sort_order (order
)
2105 int i
, shift_bits
= 21;
2107 for (i
= 0; i
< 4; i
++, shift_bits
-= 7)
2109 int xlfd_idx
= order
[i
];
2111 if (xlfd_idx
== XLFD_WEIGHT_INDEX
)
2112 sort_shift_bits
[FONT_WEIGHT_INDEX
] = shift_bits
;
2113 else if (xlfd_idx
== XLFD_SLANT_INDEX
)
2114 sort_shift_bits
[FONT_SLANT_INDEX
] = shift_bits
;
2115 else if (xlfd_idx
== XLFD_SWIDTH_INDEX
)
2116 sort_shift_bits
[FONT_WIDTH_INDEX
] = shift_bits
;
2118 sort_shift_bits
[FONT_SIZE_INDEX
] = shift_bits
;
2123 /* Return weight property of FONT as symbol. */
2126 font_symbolic_weight (font
)
2129 Lisp_Object weight
= AREF (font
, FONT_WEIGHT_INDEX
);
2131 if (INTEGERP (weight
))
2132 weight
= prop_numeric_to_name (FONT_WEIGHT_INDEX
, XINT (weight
));
2137 /* Return slant property of FONT as symbol. */
2140 font_symbolic_slant (font
)
2143 Lisp_Object slant
= AREF (font
, FONT_SLANT_INDEX
);
2145 if (INTEGERP (slant
))
2146 slant
= prop_numeric_to_name (FONT_SLANT_INDEX
, XINT (slant
));
2151 /* Return width property of FONT as symbol. */
2154 font_symbolic_width (font
)
2157 Lisp_Object width
= AREF (font
, FONT_WIDTH_INDEX
);
2159 if (INTEGERP (width
))
2160 width
= prop_numeric_to_name (FONT_WIDTH_INDEX
, XINT (width
));
2165 /* Check if ENTITY matches with the font specification SPEC. */
2168 font_match_p (spec
, entity
)
2169 Lisp_Object spec
, entity
;
2173 for (i
= FONT_FOUNDRY_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2174 if (! NILP (AREF (spec
, i
))
2175 && ! EQ (AREF (spec
, i
), AREF (entity
, i
)))
2177 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
))
2178 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0
2179 && (XINT (AREF (spec
, FONT_SIZE_INDEX
))
2180 != XINT (AREF (entity
, FONT_SIZE_INDEX
))))
2186 /* Return a lispy font object corresponding to FONT. */
2189 font_find_object (font
)
2192 Lisp_Object tail
, elt
;
2194 for (tail
= AREF (font
->entity
, FONT_OBJLIST_INDEX
); CONSP (tail
);
2198 if (font
== XSAVE_VALUE (elt
)->pointer
2199 && XSAVE_VALUE (elt
)->integer
> 0)
2209 Each font backend has the callback function get_cache, and it
2210 returns a cons cell of which cdr part can be freely used for
2211 caching fonts. The cons cell may be shared by multiple frames
2212 and/or multiple font drivers. So, we arrange the cdr part as this:
2214 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2216 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2217 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2218 cons (FONT-SPEC FONT-ENTITY ...). */
2220 static void font_prepare_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2221 static void font_finish_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2222 static Lisp_Object font_get_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2223 static void font_clear_cache
P_ ((FRAME_PTR
, Lisp_Object
,
2224 struct font_driver
*));
2227 font_prepare_cache (f
, driver
)
2229 struct font_driver
*driver
;
2231 Lisp_Object cache
, val
;
2233 cache
= driver
->get_cache (f
);
2235 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2239 val
= Fcons (driver
->type
, Fcons (make_number (1), Qnil
));
2240 XSETCDR (cache
, Fcons (val
, XCDR (cache
)));
2244 val
= XCDR (XCAR (val
));
2245 XSETCAR (val
, make_number (XINT (XCAR (val
)) + 1));
2251 font_finish_cache (f
, driver
)
2253 struct font_driver
*driver
;
2255 Lisp_Object cache
, val
, tmp
;
2258 cache
= driver
->get_cache (f
);
2260 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2261 cache
= val
, val
= XCDR (val
);
2262 xassert (! NILP (val
));
2263 tmp
= XCDR (XCAR (val
));
2264 XSETCAR (tmp
, make_number (XINT (XCAR (tmp
)) - 1));
2265 if (XINT (XCAR (tmp
)) == 0)
2267 font_clear_cache (f
, XCAR (val
), driver
);
2268 XSETCDR (cache
, XCDR (val
));
2274 font_get_cache (f
, driver
)
2276 struct font_driver
*driver
;
2278 Lisp_Object val
= driver
->get_cache (f
);
2279 Lisp_Object type
= driver
->type
;
2281 xassert (CONSP (val
));
2282 for (val
= XCDR (val
); ! EQ (XCAR (XCAR (val
)), type
); val
= XCDR (val
));
2283 xassert (CONSP (val
));
2284 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2285 val
= XCDR (XCAR (val
));
2289 static int num_fonts
;
2292 font_clear_cache (f
, cache
, driver
)
2295 struct font_driver
*driver
;
2297 Lisp_Object tail
, elt
;
2299 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2300 for (tail
= XCDR (XCDR (cache
)); CONSP (tail
); tail
= XCDR (tail
))
2303 if (CONSP (elt
) && FONT_SPEC_P (XCAR (elt
)))
2305 Lisp_Object vec
= XCDR (elt
);
2308 for (i
= 0; i
< ASIZE (vec
); i
++)
2310 Lisp_Object entity
= AREF (vec
, i
);
2312 if (EQ (driver
->type
, AREF (entity
, FONT_TYPE_INDEX
)))
2314 Lisp_Object objlist
= AREF (entity
, FONT_OBJLIST_INDEX
);
2316 for (; CONSP (objlist
); objlist
= XCDR (objlist
))
2318 Lisp_Object val
= XCAR (objlist
);
2319 struct Lisp_Save_Value
*p
= XSAVE_VALUE (val
);
2320 struct font
*font
= p
->pointer
;
2322 xassert (font
&& driver
== font
->driver
);
2323 driver
->close (f
, font
);
2328 if (driver
->free_entity
)
2329 driver
->free_entity (entity
);
2334 XSETCDR (cache
, Qnil
);
2338 static Lisp_Object scratch_font_spec
, scratch_font_prefer
;
2341 /* Return a vector of font-entities matching with SPEC on frame F. */
2344 font_list_entities (frame
, spec
)
2345 Lisp_Object frame
, spec
;
2347 FRAME_PTR f
= XFRAME (frame
);
2348 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2349 Lisp_Object ftype
, family
, size
, alternate_familes
;
2350 Lisp_Object
*vec
= alloca (sizeof (Lisp_Object
) * num_font_drivers
);
2356 family
= AREF (spec
, FONT_FAMILY_INDEX
);
2358 alternate_familes
= Qnil
;
2361 if (NILP (font_family_alist
)
2362 && !NILP (Vface_alternative_font_family_alist
))
2363 build_font_family_alist ();
2364 alternate_familes
= assq_no_quit (family
, font_family_alist
);
2365 if (! NILP (alternate_familes
))
2366 alternate_familes
= XCDR (alternate_familes
);
2368 size
= AREF (spec
, FONT_SIZE_INDEX
);
2370 ASET (spec
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2372 xassert (ASIZE (spec
) == FONT_SPEC_MAX
);
2373 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2375 for (i
= 0; driver_list
; driver_list
= driver_list
->next
)
2377 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2379 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2380 Lisp_Object tail
= alternate_familes
;
2382 ASET (spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2383 ASET (spec
, FONT_FAMILY_INDEX
, family
);
2387 Lisp_Object val
= assoc_no_quit (spec
, XCDR (cache
));
2393 val
= driver_list
->driver
->list (frame
, spec
);
2395 XSETCDR (cache
, Fcons (Fcons (Fcopy_sequence (spec
), val
),
2398 if (VECTORP (val
) && ASIZE (val
) > 0)
2405 ASET (spec
, FONT_FAMILY_INDEX
, XCAR (tail
));
2409 ASET (spec
, FONT_TYPE_INDEX
, ftype
);
2410 ASET (spec
, FONT_FAMILY_INDEX
, family
);
2411 ASET (spec
, FONT_SIZE_INDEX
, size
);
2412 return (i
> 0 ? Fvconcat (i
, vec
) : null_vector
);
2416 /* Return a font entity matching with SPEC on FRAME. */
2419 font_matching_entity (frame
, spec
)
2420 Lisp_Object frame
, spec
;
2422 FRAME_PTR f
= XFRAME (frame
);
2423 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2424 Lisp_Object ftype
, size
, entity
;
2426 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2427 size
= AREF (spec
, FONT_SIZE_INDEX
);
2429 ASET (spec
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2431 for (; driver_list
; driver_list
= driver_list
->next
)
2433 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2435 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2438 ASET (spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2439 key
= Fcons (spec
, Qnil
);
2440 entity
= assoc_no_quit (key
, XCDR (cache
));
2442 entity
= XCDR (entity
);
2445 entity
= driver_list
->driver
->match (frame
, spec
);
2446 if (! NILP (entity
))
2448 XSETCAR (key
, Fcopy_sequence (spec
));
2449 XSETCDR (cache
, Fcons (Fcons (key
, entity
), XCDR (cache
)));
2452 if (! NILP (entity
))
2455 ASET (spec
, FONT_TYPE_INDEX
, ftype
);
2456 ASET (spec
, FONT_SIZE_INDEX
, size
);
2461 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2462 opened font object. */
2465 font_open_entity (f
, entity
, pixel_size
)
2470 struct font_driver_list
*driver_list
;
2471 Lisp_Object objlist
, size
, val
, font_object
;
2474 size
= AREF (entity
, FONT_SIZE_INDEX
);
2475 xassert (NATNUMP (size
));
2476 if (XINT (size
) != 0)
2477 pixel_size
= XINT (size
);
2480 for (objlist
= AREF (entity
, FONT_OBJLIST_INDEX
); CONSP (objlist
);
2481 objlist
= XCDR (objlist
))
2483 font
= XSAVE_VALUE (XCAR (objlist
))->pointer
;
2484 if (font
->pixel_size
== pixel_size
)
2486 font_object
= XCAR (objlist
);
2487 XSAVE_VALUE (font_object
)->integer
++;
2492 if (NILP (font_object
))
2494 val
= AREF (entity
, FONT_TYPE_INDEX
);
2495 for (driver_list
= f
->font_driver_list
;
2496 driver_list
&& ! EQ (driver_list
->driver
->type
, val
);
2497 driver_list
= driver_list
->next
);
2501 font
= driver_list
->driver
->open (f
, entity
, pixel_size
);
2504 font
->scalable
= XINT (size
) == 0;
2506 font_object
= make_save_value (font
, 1);
2507 ASET (entity
, FONT_OBJLIST_INDEX
,
2508 Fcons (font_object
, AREF (entity
, FONT_OBJLIST_INDEX
)));
2512 if (FRAME_SMALLEST_CHAR_WIDTH (f
) > font
->min_width
)
2513 FRAME_SMALLEST_CHAR_WIDTH (f
) = font
->min_width
;
2514 if (FRAME_SMALLEST_CHAR_WIDTH (f
) <= 0)
2515 FRAME_SMALLEST_CHAR_WIDTH (f
) = 1;
2516 if (FRAME_SMALLEST_FONT_HEIGHT (f
) > font
->font
.height
)
2517 FRAME_SMALLEST_FONT_HEIGHT (f
) = font
->font
.height
;
2518 if (FRAME_SMALLEST_FONT_HEIGHT (f
) <= 0)
2519 FRAME_SMALLEST_FONT_HEIGHT (f
) = 1;
2525 /* Close FONT_OBJECT that is opened on frame F. */
2528 font_close_object (f
, font_object
)
2530 Lisp_Object font_object
;
2532 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2533 Lisp_Object objlist
;
2534 Lisp_Object tail
, prev
= Qnil
;
2536 xassert (XSAVE_VALUE (font_object
)->integer
> 0);
2537 XSAVE_VALUE (font_object
)->integer
--;
2538 if (XSAVE_VALUE (font_object
)->integer
> 0)
2541 objlist
= AREF (font
->entity
, FONT_OBJLIST_INDEX
);
2542 for (prev
= Qnil
, tail
= objlist
; CONSP (tail
);
2543 prev
= tail
, tail
= XCDR (tail
))
2544 if (EQ (font_object
, XCAR (tail
)))
2546 if (font
->driver
->close
)
2547 font
->driver
->close (f
, font
);
2548 XSAVE_VALUE (font_object
)->pointer
= NULL
;
2550 ASET (font
->entity
, FONT_OBJLIST_INDEX
, XCDR (objlist
));
2552 XSETCDR (prev
, XCDR (objlist
));
2560 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2561 FONT is a font-entity and it must be opened to check. */
2564 font_has_char (f
, font
, c
)
2571 if (FONT_ENTITY_P (font
))
2573 Lisp_Object type
= AREF (font
, FONT_TYPE_INDEX
);
2574 struct font_driver_list
*driver_list
;
2576 for (driver_list
= f
->font_driver_list
;
2577 driver_list
&& ! EQ (driver_list
->driver
->type
, type
);
2578 driver_list
= driver_list
->next
);
2581 if (! driver_list
->driver
->has_char
)
2583 return driver_list
->driver
->has_char (font
, c
);
2586 xassert (FONT_OBJECT_P (font
));
2587 fontp
= XSAVE_VALUE (font
)->pointer
;
2589 if (fontp
->driver
->has_char
)
2591 int result
= fontp
->driver
->has_char (fontp
->entity
, c
);
2596 return (fontp
->driver
->encode_char (fontp
, c
) != FONT_INVALID_CODE
);
2600 /* Return the glyph ID of FONT_OBJECT for character C. */
2603 font_encode_char (font_object
, c
)
2604 Lisp_Object font_object
;
2607 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2609 return font
->driver
->encode_char (font
, c
);
2613 /* Return the name of FONT_OBJECT. */
2616 font_get_name (font_object
)
2617 Lisp_Object font_object
;
2619 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2620 char *name
= (font
->font
.full_name
? font
->font
.full_name
2621 : font
->font
.name
? font
->font
.name
2624 return (name
? make_unibyte_string (name
, strlen (name
)) : null_string
);
2628 /* Return the specification of FONT_OBJECT. */
2631 font_get_spec (font_object
)
2632 Lisp_Object font_object
;
2634 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2635 Lisp_Object spec
= Ffont_spec (0, NULL
);
2638 for (i
= 0; i
< FONT_SIZE_INDEX
; i
++)
2639 ASET (spec
, i
, AREF (font
->entity
, i
));
2640 ASET (spec
, FONT_SIZE_INDEX
, make_number (font
->pixel_size
));
2645 /* Return the frame on which FONT exists. FONT is a font object or a
2649 font_get_frame (font
)
2652 if (FONT_OBJECT_P (font
))
2653 font
= ((struct font
*) XSAVE_VALUE (font
)->pointer
)->entity
;
2654 xassert (FONT_ENTITY_P (font
));
2655 return AREF (font
, FONT_FRAME_INDEX
);
2659 /* Find a font entity best matching with LFACE. If SPEC is non-nil,
2660 the font must exactly match with it. C, if not negative, is a
2661 character that the entity must support. */
2664 font_find_for_lface (f
, lface
, spec
, c
)
2670 Lisp_Object frame
, entities
, val
;
2673 XSETFRAME (frame
, f
);
2679 for (i
= 0; i
< FONT_SPEC_MAX
; i
++)
2680 ASET (scratch_font_spec
, i
, Qnil
);
2681 ASET (scratch_font_spec
, FONT_REGISTRY_INDEX
, Qiso8859_1
);
2683 if (! NILP (lface
[LFACE_FAMILY_INDEX
]))
2684 font_merge_old_spec (Qnil
, lface
[LFACE_FAMILY_INDEX
], Qnil
,
2686 entities
= font_list_entities (frame
, scratch_font_spec
);
2687 while (ASIZE (entities
) == 0)
2689 /* Try without FOUNDRY or FAMILY. */
2690 if (! NILP (AREF (scratch_font_spec
, FONT_FOUNDRY_INDEX
)))
2692 ASET (scratch_font_spec
, FONT_FOUNDRY_INDEX
, Qnil
);
2693 entities
= font_list_entities (frame
, scratch_font_spec
);
2695 else if (! NILP (AREF (scratch_font_spec
, FONT_FAMILY_INDEX
)))
2697 ASET (scratch_font_spec
, FONT_FAMILY_INDEX
, Qnil
);
2698 entities
= font_list_entities (frame
, scratch_font_spec
);
2706 Lisp_Object registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
2708 if (NILP (registry
))
2709 registry
= Qiso8859_1
;
2713 struct charset
*encoding
, *repertory
;
2715 if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
2719 if (ENCODE_CHAR (repertory
, c
)
2720 == CHARSET_INVALID_CODE (repertory
))
2722 /* Any font of this registry support C. So, let's
2723 suppress the further checking. */
2726 else if (c
> encoding
->max_char
)
2729 for (i
= 0; i
< FONT_SPEC_MAX
; i
++)
2730 ASET (scratch_font_spec
, i
, AREF (spec
, i
));
2731 ASET (scratch_font_spec
, FONT_REGISTRY_INDEX
, registry
);
2732 entities
= font_list_entities (frame
, scratch_font_spec
);
2735 if (ASIZE (entities
) == 0)
2737 if (ASIZE (entities
) > 1)
2739 /* Sort fonts by properties specified in LFACE. */
2740 Lisp_Object prefer
= scratch_font_prefer
;
2743 if (! NILP (lface
[LFACE_FAMILY_INDEX
]))
2744 font_merge_old_spec (Qnil
, lface
[LFACE_FAMILY_INDEX
], Qnil
, prefer
);
2745 ASET (prefer
, FONT_WEIGHT_INDEX
,
2746 font_prop_validate_style (QCweight
, lface
[LFACE_WEIGHT_INDEX
]));
2747 ASET (prefer
, FONT_SLANT_INDEX
,
2748 font_prop_validate_style (QCslant
, lface
[LFACE_SLANT_INDEX
]));
2749 ASET (prefer
, FONT_WIDTH_INDEX
,
2750 font_prop_validate_style (QCwidth
, lface
[LFACE_SWIDTH_INDEX
]));
2751 pt
= XINT (lface
[LFACE_HEIGHT_INDEX
]);
2752 ASET (prefer
, FONT_SIZE_INDEX
, make_float (pt
/ 10));
2754 font_sort_entites (entities
, prefer
, frame
, spec
);
2758 return AREF (entities
, 0);
2760 val
= AREF (entities
, 0);
2761 result
= font_has_char (f
, val
, c
);
2766 val
= font_open_for_lface (f
, val
, lface
, spec
);
2769 result
= font_has_char (f
, val
, c
);
2770 font_close_object (f
, val
);
2778 font_open_for_lface (f
, entity
, lface
, spec
)
2786 if (FONT_SPEC_P (spec
) && INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2787 size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
2790 double pt
= XINT (lface
[LFACE_HEIGHT_INDEX
]);
2793 size
= POINT_TO_PIXEL (pt
, f
->resy
);
2795 return font_open_entity (f
, entity
, size
);
2799 /* Load a font best matching with FACE's font-related properties into
2800 FACE on frame F. If no proper font is found, record that FACE has
2804 font_load_for_face (f
, face
)
2808 Lisp_Object font_object
= face
->lface
[LFACE_FONT_INDEX
];
2810 if (NILP (font_object
))
2812 Lisp_Object entity
= font_find_for_lface (f
, face
->lface
, Qnil
, -1);
2814 if (! NILP (entity
))
2815 font_object
= font_open_for_lface (f
, entity
, face
->lface
, Qnil
);
2817 else if (STRINGP (font_object
))
2819 font_object
= font_open_by_name (f
, SDATA (font_object
));
2822 if (! NILP (font_object
))
2824 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2826 face
->font
= font
->font
.font
;
2827 face
->font_info
= (struct font_info
*) font
;
2828 face
->font_info_id
= 0;
2829 face
->font_name
= font
->font
.full_name
;
2834 face
->font_info
= NULL
;
2835 face
->font_info_id
= -1;
2836 face
->font_name
= NULL
;
2837 add_to_log ("Unable to load font for a face%s", null_string
, Qnil
);
2842 /* Make FACE on frame F ready to use the font opened for FACE. */
2845 font_prepare_for_face (f
, face
)
2849 struct font
*font
= (struct font
*) face
->font_info
;
2851 if (font
->driver
->prepare_face
)
2852 font
->driver
->prepare_face (f
, face
);
2856 /* Make FACE on frame F stop using the font opened for FACE. */
2859 font_done_for_face (f
, face
)
2863 struct font
*font
= (struct font
*) face
->font_info
;
2865 if (font
->driver
->done_face
)
2866 font
->driver
->done_face (f
, face
);
2871 /* Open a font best matching with NAME on frame F. If no proper font
2872 is found, return Qnil. */
2875 font_open_by_name (f
, name
)
2879 Lisp_Object args
[2];
2880 Lisp_Object spec
, prefer
, size
, entity
, entity_list
;
2885 XSETFRAME (frame
, f
);
2888 args
[1] = make_unibyte_string (name
, strlen (name
));
2889 spec
= Ffont_spec (2, args
);
2890 prefer
= scratch_font_prefer
;
2891 for (i
= FONT_WEIGHT_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2892 if (NILP (AREF (spec
, i
)))
2893 ASET (prefer
, i
, make_number (100));
2894 size
= AREF (spec
, FONT_SIZE_INDEX
);
2897 else if (INTEGERP (size
))
2898 pixel_size
= XINT (size
);
2899 else /* FLOATP (size) */
2901 double pt
= XFLOAT_DATA (size
);
2903 pixel_size
= POINT_TO_PIXEL (pt
, f
->resy
);
2904 size
= make_number (pixel_size
);
2905 ASET (spec
, FONT_SIZE_INDEX
, size
);
2907 if (pixel_size
== 0)
2909 pixel_size
= POINT_TO_PIXEL (12.0, f
->resy
);
2910 size
= make_number (pixel_size
);
2912 ASET (prefer
, FONT_SIZE_INDEX
, size
);
2913 if (NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
2914 ASET (spec
, FONT_REGISTRY_INDEX
, Qiso8859_1
);
2916 entity_list
= Flist_fonts (spec
, frame
, make_number (1), prefer
);
2917 if (NILP (entity_list
))
2918 entity
= font_matching_entity (frame
, spec
);
2920 entity
= XCAR (entity_list
);
2921 return (NILP (entity
)
2923 : font_open_entity (f
, entity
, pixel_size
));
2927 /* Register font-driver DRIVER. This function is used in two ways.
2929 The first is with frame F non-NULL. In this case, make DRIVER
2930 available (but not yet activated) on F. All frame creaters
2931 (e.g. Fx_create_frame) must call this function at least once with
2932 an available font-driver.
2934 The second is with frame F NULL. In this case, DRIVER is globally
2935 registered in the variable `font_driver_list'. All font-driver
2936 implementations must call this function in its syms_of_XXXX
2937 (e.g. syms_of_xfont). */
2940 register_font_driver (driver
, f
)
2941 struct font_driver
*driver
;
2944 struct font_driver_list
*root
= f
? f
->font_driver_list
: font_driver_list
;
2945 struct font_driver_list
*prev
, *list
;
2947 if (f
&& ! driver
->draw
)
2948 error ("Unusable font driver for a frame: %s",
2949 SDATA (SYMBOL_NAME (driver
->type
)));
2951 for (prev
= NULL
, list
= root
; list
; prev
= list
, list
= list
->next
)
2952 if (EQ (list
->driver
->type
, driver
->type
))
2953 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver
->type
)));
2955 list
= malloc (sizeof (struct font_driver_list
));
2957 list
->driver
= driver
;
2962 f
->font_driver_list
= list
;
2964 font_driver_list
= list
;
2969 /* Free font-driver list on frame F. It doesn't free font-drivers
2973 free_font_driver_list (f
)
2976 while (f
->font_driver_list
)
2978 struct font_driver_list
*next
= f
->font_driver_list
->next
;
2980 free (f
->font_driver_list
);
2981 f
->font_driver_list
= next
;
2986 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
2987 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
2988 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
2990 A caller must free all realized faces if any in advance. The
2991 return value is a list of font backends actually made used on
2995 font_update_drivers (f
, new_drivers
)
2997 Lisp_Object new_drivers
;
2999 Lisp_Object active_drivers
= Qnil
;
3000 struct font_driver_list
*list
;
3002 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
3005 if (! EQ (new_drivers
, Qt
)
3006 && NILP (Fmemq (list
->driver
->type
, new_drivers
)))
3008 if (list
->driver
->end_for_frame
)
3009 list
->driver
->end_for_frame (f
);
3010 font_finish_cache (f
, list
->driver
);
3016 if (EQ (new_drivers
, Qt
)
3017 || ! NILP (Fmemq (list
->driver
->type
, new_drivers
)))
3019 if (! list
->driver
->start_for_frame
3020 || list
->driver
->start_for_frame (f
) == 0)
3022 font_prepare_cache (f
, list
->driver
);
3024 active_drivers
= nconc2 (active_drivers
,
3025 Fcons (list
->driver
->type
, Qnil
));
3030 return active_drivers
;
3034 font_put_frame_data (f
, driver
, data
)
3036 struct font_driver
*driver
;
3039 struct font_data_list
*list
, *prev
;
3041 for (prev
= NULL
, list
= f
->font_data_list
; list
;
3042 prev
= list
, list
= list
->next
)
3043 if (list
->driver
== driver
)
3050 prev
->next
= list
->next
;
3052 f
->font_data_list
= list
->next
;
3060 list
= malloc (sizeof (struct font_data_list
));
3063 list
->driver
= driver
;
3064 list
->next
= f
->font_data_list
;
3065 f
->font_data_list
= list
;
3073 font_get_frame_data (f
, driver
)
3075 struct font_driver
*driver
;
3077 struct font_data_list
*list
;
3079 for (list
= f
->font_data_list
; list
; list
= list
->next
)
3080 if (list
->driver
== driver
)
3088 /* Return the font used to draw character C by FACE at buffer position
3089 POS in window W. If STRING is non-nil, it is a string containing C
3090 at index POS. If C is negative, get C from the current buffer or
3094 font_at (c
, pos
, face
, w
, string
)
3108 multibyte
= ! NILP (current_buffer
->enable_multibyte_characters
);
3111 EMACS_INT pos_byte
= CHAR_TO_BYTE (pos
);
3113 c
= FETCH_CHAR (pos_byte
);
3116 c
= FETCH_BYTE (pos
);
3122 multibyte
= STRING_MULTIBYTE (string
);
3125 EMACS_INT pos_byte
= string_char_to_byte (string
, pos
);
3127 str
= SDATA (string
) + pos_byte
;
3128 c
= STRING_CHAR (str
, 0);
3131 c
= SDATA (string
)[pos
];
3135 f
= XFRAME (w
->frame
);
3136 if (! FRAME_WINDOW_P (f
))
3143 if (STRINGP (string
))
3144 face_id
= face_at_string_position (w
, string
, pos
, 0, -1, -1, &endptr
,
3145 DEFAULT_FACE_ID
, 0);
3147 face_id
= face_at_buffer_position (w
, pos
, -1, -1, &endptr
,
3149 face
= FACE_FROM_ID (f
, face_id
);
3153 int face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3154 face
= FACE_FROM_ID (f
, face_id
);
3156 if (! face
->font_info
)
3158 return font_find_object ((struct font
*) face
->font_info
);
3164 DEFUN ("fontp", Ffontp
, Sfontp
, 1, 1, 0,
3165 doc
: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3166 Return nil otherwise. */)
3170 return (FONTP (object
) ? Qt
: Qnil
);
3173 DEFUN ("font-spec", Ffont_spec
, Sfont_spec
, 0, MANY
, 0,
3174 doc
: /* Return a newly created font-spec with arguments as properties.
3176 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3177 valid font property name listed below:
3179 `:family', `:weight', `:slant', `:width'
3181 They are the same as face attributes of the same name. See
3182 `set-face-attribute'.
3186 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3190 VALUE must be a string or a symbol specifying the additional
3191 typographic style information of a font, e.g. ``sans''. Usually null.
3195 VALUE must be a string or a symbol specifying the charset registry and
3196 encoding of a font, e.g. ``iso8859-1''.
3200 VALUE must be a non-negative integer or a floating point number
3201 specifying the font size. It specifies the font size in 1/10 pixels
3202 (if VALUE is an integer), or in points (if VALUE is a float).
3203 usage: (font-spec ARGS ...) */)
3208 Lisp_Object spec
= Fmake_vector (make_number (FONT_SPEC_MAX
), Qnil
);
3211 for (i
= 0; i
< nargs
; i
+= 2)
3213 enum font_property_index prop
;
3214 Lisp_Object key
= args
[i
], val
= args
[i
+ 1];
3216 prop
= get_font_prop_index (key
, 0);
3217 if (prop
< FONT_EXTRA_INDEX
)
3218 ASET (spec
, prop
, val
);
3221 if (EQ (key
, QCname
))
3224 font_parse_name ((char *) SDATA (val
), spec
);
3226 font_put_extra (spec
, key
, val
);
3229 CHECK_VALIDATE_FONT_SPEC (spec
);
3234 DEFUN ("font-get", Ffont_get
, Sfont_get
, 2, 2, 0,
3235 doc
: /* Return the value of FONT's property KEY.
3236 FONT is a font-spec, a font-entity, or a font-object. */)
3238 Lisp_Object font
, key
;
3240 enum font_property_index idx
;
3242 if (FONT_OBJECT_P (font
))
3244 struct font
*fontp
= XSAVE_VALUE (font
)->pointer
;
3246 if (EQ (key
, QCotf
))
3248 if (fontp
->driver
->otf_capability
)
3249 return fontp
->driver
->otf_capability (fontp
);
3253 font
= fontp
->entity
;
3257 idx
= get_font_prop_index (key
, 0);
3258 if (idx
< FONT_EXTRA_INDEX
)
3259 return AREF (font
, idx
);
3260 if (FONT_ENTITY_P (font
))
3262 return Fcdr (Fassoc (key
, AREF (font
, FONT_EXTRA_INDEX
)));
3266 DEFUN ("font-put", Ffont_put
, Sfont_put
, 3, 3, 0,
3267 doc
: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
3268 (font_spec
, prop
, val
)
3269 Lisp_Object font_spec
, prop
, val
;
3271 enum font_property_index idx
;
3272 Lisp_Object extra
, slot
;
3274 CHECK_FONT_SPEC (font_spec
);
3275 idx
= get_font_prop_index (prop
, 0);
3276 if (idx
< FONT_EXTRA_INDEX
)
3277 return ASET (font_spec
, idx
, val
);
3278 extra
= AREF (font_spec
, FONT_EXTRA_INDEX
);
3279 slot
= Fassoc (extra
, prop
);
3281 extra
= Fcons (Fcons (prop
, val
), extra
);
3283 Fsetcdr (slot
, val
);
3287 DEFUN ("list-fonts", Flist_fonts
, Slist_fonts
, 1, 4, 0,
3288 doc
: /* List available fonts matching FONT-SPEC on the current frame.
3289 Optional 2nd argument FRAME specifies the target frame.
3290 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
3291 Optional 4th argument PREFER, if non-nil, is a font-spec to
3292 control the order of the returned list. Fonts are sorted by
3293 how they are close to PREFER. */)
3294 (font_spec
, frame
, num
, prefer
)
3295 Lisp_Object font_spec
, frame
, num
, prefer
;
3297 Lisp_Object vec
, list
, tail
;
3301 frame
= selected_frame
;
3302 CHECK_LIVE_FRAME (frame
);
3303 CHECK_VALIDATE_FONT_SPEC (font_spec
);
3311 if (! NILP (prefer
))
3312 CHECK_FONT (prefer
);
3314 vec
= font_list_entities (frame
, font_spec
);
3319 return Fcons (AREF (vec
, 0), Qnil
);
3321 if (! NILP (prefer
))
3322 vec
= font_sort_entites (vec
, prefer
, frame
, font_spec
);
3324 list
= tail
= Fcons (AREF (vec
, 0), Qnil
);
3325 if (n
== 0 || n
> len
)
3327 for (i
= 1; i
< n
; i
++)
3329 Lisp_Object val
= Fcons (AREF (vec
, i
), Qnil
);
3331 XSETCDR (tail
, val
);
3337 DEFUN ("list-families", Flist_families
, Slist_families
, 0, 1, 0,
3338 doc
: /* List available font families on the current frame.
3339 Optional argument FRAME specifies the target frame. */)
3344 struct font_driver_list
*driver_list
;
3348 frame
= selected_frame
;
3349 CHECK_LIVE_FRAME (frame
);
3352 for (driver_list
= f
->font_driver_list
; driver_list
;
3353 driver_list
= driver_list
->next
)
3354 if (driver_list
->driver
->list_family
)
3356 Lisp_Object val
= driver_list
->driver
->list_family (frame
);
3362 Lisp_Object tail
= list
;
3364 for (; CONSP (val
); val
= XCDR (val
))
3365 if (NILP (Fmemq (XCAR (val
), tail
)))
3366 list
= Fcons (XCAR (val
), list
);
3372 DEFUN ("find-font", Ffind_font
, Sfind_font
, 1, 2, 0,
3373 doc
: /* Return a font-entity matching with FONT-SPEC on the current frame.
3374 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
3376 Lisp_Object font_spec
, frame
;
3378 Lisp_Object val
= Flist_fonts (font_spec
, frame
, make_number (1), Qnil
);
3385 DEFUN ("font-xlfd-name", Ffont_xlfd_name
, Sfont_xlfd_name
, 1, 1, 0,
3386 doc
: /* Return XLFD name of FONT.
3387 FONT is a font-spec, font-entity, or font-object.
3388 If the name is too long for XLFD (maximum 255 chars), return nil. */)
3395 if (FONT_SPEC_P (font
))
3396 CHECK_VALIDATE_FONT_SPEC (font
);
3397 else if (FONT_ENTITY_P (font
))
3403 CHECK_FONT_GET_OBJECT (font
, fontp
);
3404 font
= fontp
->entity
;
3405 pixel_size
= fontp
->pixel_size
;
3408 if (font_unparse_xlfd (font
, pixel_size
, name
, 256) < 0)
3410 return build_string (name
);
3413 DEFUN ("clear-font-cache", Fclear_font_cache
, Sclear_font_cache
, 0, 0, 0,
3414 doc
: /* Clear font cache. */)
3417 Lisp_Object list
, frame
;
3419 FOR_EACH_FRAME (list
, frame
)
3421 FRAME_PTR f
= XFRAME (frame
);
3422 struct font_driver_list
*driver_list
= f
->font_driver_list
;
3424 for (; driver_list
; driver_list
= driver_list
->next
)
3425 if (driver_list
->on
)
3427 Lisp_Object cache
= driver_list
->driver
->get_cache (f
);
3432 && ! EQ (XCAR (XCAR (val
)), driver_list
->driver
->type
))
3434 xassert (! NILP (val
));
3435 val
= XCDR (XCAR (val
));
3436 if (XINT (XCAR (val
)) == 0)
3438 font_clear_cache (f
, XCAR (val
), driver_list
->driver
);
3439 XSETCDR (cache
, XCDR (val
));
3447 DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table
,
3448 Sinternal_set_font_style_table
, 2, 2, 0,
3449 doc
: /* Set font style table for PROP to TABLE.
3450 PROP must be `:weight', `:slant', or `:width'.
3451 TABLE must be an alist of symbols vs the corresponding numeric values
3452 sorted by numeric values. */)
3454 Lisp_Object prop
, table
;
3458 Lisp_Object tail
, val
;
3460 CHECK_SYMBOL (prop
);
3461 table_index
= (EQ (prop
, QCweight
) ? 0
3462 : EQ (prop
, QCslant
) ? 1
3463 : EQ (prop
, QCwidth
) ? 2
3465 if (table_index
>= ASIZE (font_style_table
))
3466 error ("Invalid font style property: %s", SDATA (SYMBOL_NAME (prop
)));
3467 table
= Fcopy_sequence (table
);
3469 for (tail
= table
; CONSP (tail
); tail
= XCDR (tail
))
3471 prop
= Fcar (XCAR (tail
));
3472 val
= Fcdr (XCAR (tail
));
3473 CHECK_SYMBOL (prop
);
3475 if (numeric
> XINT (val
))
3476 error ("Numeric values not sorted for %s", SDATA (SYMBOL_NAME (prop
)));
3477 else if (numeric
== XINT (val
))
3478 error ("Duplicate numeric values for %s", SDATA (SYMBOL_NAME (prop
)));
3479 numeric
= XINT (val
);
3480 XSETCAR (tail
, Fcons (prop
, val
));
3482 ASET (font_style_table
, table_index
, table
);
3486 /* The following three functions are still expremental. */
3488 DEFUN ("font-make-gstring", Ffont_make_gstring
, Sfont_make_gstring
, 2, 2, 0,
3489 doc
: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
3490 FONT-OBJECT may be nil if it is not yet known.
3492 G-string is sequence of glyphs of a specific font,
3493 and is a vector of this form:
3494 [ HEADER GLYPH ... ]
3495 HEADER is a vector of this form:
3496 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
3498 FONT-OBJECT is a font-object for all glyphs in the g-string,
3499 WIDTH thry DESCENT are the metrics (in pixels) of the whole G-string.
3500 GLYPH is a vector of this form:
3501 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
3502 [ [X-OFF Y-OFF WADJUST] | nil] ]
3504 FROM-IDX and TO-IDX are used internally and should not be touched.
3505 C is the character of the glyph.
3506 CODE is the glyph-code of C in FONT-OBJECT.
3507 WIDTH thry DESCENT are the metrics (in pixels) of the glyph.
3508 X-OFF and Y-OFF are offests to the base position for the glyph.
3509 WADJUST is the adjustment to the normal width of the glyph. */)
3511 Lisp_Object font_object
, num
;
3513 Lisp_Object gstring
, g
;
3517 if (! NILP (font_object
))
3518 CHECK_FONT_OBJECT (font_object
);
3521 len
= XINT (num
) + 1;
3522 gstring
= Fmake_vector (make_number (len
), Qnil
);
3523 g
= Fmake_vector (make_number (6), Qnil
);
3524 ASET (g
, 0, font_object
);
3525 ASET (gstring
, 0, g
);
3526 for (i
= 1; i
< len
; i
++)
3527 ASET (gstring
, i
, Fmake_vector (make_number (10), Qnil
));
3531 DEFUN ("font-fill-gstring", Ffont_fill_gstring
, Sfont_fill_gstring
, 4, 5, 0,
3532 doc
: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
3533 START and END specify the region to extract characters.
3534 If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
3535 where to extract characters.
3536 FONT-OBJECT may be nil if GSTRING already already contains one. */)
3537 (gstring
, font_object
, start
, end
, object
)
3538 Lisp_Object gstring
, font_object
, start
, end
, object
;
3544 CHECK_VECTOR (gstring
);
3545 if (NILP (font_object
))
3546 font_object
= LGSTRING_FONT (gstring
);
3547 CHECK_FONT_GET_OBJECT (font_object
, font
);
3549 if (STRINGP (object
))
3551 const unsigned char *p
;
3553 CHECK_NATNUM (start
);
3555 if (XINT (start
) > XINT (end
)
3556 || XINT (end
) > ASIZE (object
)
3557 || XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
3558 args_out_of_range_3 (object
, start
, end
);
3560 len
= XINT (end
) - XINT (start
);
3561 p
= SDATA (object
) + string_char_to_byte (object
, XINT (start
));
3562 for (i
= 0; i
< len
; i
++)
3564 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3565 /* Shut up GCC warning in comparison with
3566 MOST_POSITIVE_FIXNUM below. */
3569 c
= STRING_CHAR_ADVANCE (p
);
3570 cod
= code
= font
->driver
->encode_char (font
, c
);
3571 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
3573 LGLYPH_SET_FROM (g
, i
);
3574 LGLYPH_SET_TO (g
, i
);
3575 LGLYPH_SET_CHAR (g
, c
);
3576 LGLYPH_SET_CODE (g
, code
);
3583 if (! NILP (object
))
3584 Fset_buffer (object
);
3585 validate_region (&start
, &end
);
3586 if (XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
3587 args_out_of_range (start
, end
);
3588 len
= XINT (end
) - XINT (start
);
3590 pos_byte
= CHAR_TO_BYTE (pos
);
3591 for (i
= 0; i
< len
; i
++)
3593 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3594 /* Shut up GCC warning in comparison with
3595 MOST_POSITIVE_FIXNUM below. */
3598 FETCH_CHAR_ADVANCE (c
, pos
, pos_byte
);
3599 cod
= code
= font
->driver
->encode_char (font
, c
);
3600 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
3602 LGLYPH_SET_FROM (g
, i
);
3603 LGLYPH_SET_TO (g
, i
);
3604 LGLYPH_SET_CHAR (g
, c
);
3605 LGLYPH_SET_CODE (g
, code
);
3608 for (; i
< LGSTRING_LENGTH (gstring
); i
++)
3609 LGSTRING_SET_GLYPH (gstring
, i
, Qnil
);
3613 DEFUN ("font-shape-text", Ffont_shape_text
, Sfont_shape_text
, 3, 4, 0,
3614 doc
: /* Shape text between FROM and TO by FONT-OBJECT.
3615 If optional 4th argument STRING is non-nil, it is a string to shape,
3616 and FROM and TO are indices to the string.
3617 The value is the end position of the text that can be shaped by
3619 (from
, to
, font_object
, string
)
3620 Lisp_Object from
, to
, font_object
, string
;
3623 struct font_metrics metrics
;
3624 EMACS_INT start
, end
;
3625 Lisp_Object gstring
, n
;
3628 if (! FONT_OBJECT_P (font_object
))
3630 CHECK_FONT_GET_OBJECT (font_object
, font
);
3631 if (! font
->driver
->shape
)
3636 validate_region (&from
, &to
);
3637 start
= XFASTINT (from
);
3638 end
= XFASTINT (to
);
3639 modify_region (current_buffer
, start
, end
, 0);
3643 CHECK_STRING (string
);
3644 start
= XINT (from
);
3646 if (start
< 0 || start
> end
|| end
> SCHARS (string
))
3647 args_out_of_range_3 (string
, from
, to
);
3651 gstring
= Ffont_make_gstring (font_object
, make_number (len
));
3652 Ffont_fill_gstring (gstring
, font_object
, from
, to
, string
);
3654 /* Try at most three times with larger gstring each time. */
3655 for (i
= 0; i
< 3; i
++)
3657 Lisp_Object args
[2];
3659 n
= font
->driver
->shape (gstring
);
3663 args
[1] = Fmake_vector (make_number (len
), Qnil
);
3664 gstring
= Fvconcat (2, args
);
3666 if (! INTEGERP (n
) || XINT (n
) == 0)
3670 for (i
= 0; i
< len
;)
3673 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3674 EMACS_INT this_from
= LGLYPH_FROM (g
);
3675 EMACS_INT this_to
= LGLYPH_TO (g
) + 1;
3677 int need_composition
= 0;
3679 metrics
.lbearing
= LGLYPH_LBEARING (g
);
3680 metrics
.rbearing
= LGLYPH_RBEARING (g
);
3681 metrics
.ascent
= LGLYPH_ASCENT (g
);
3682 metrics
.descent
= LGLYPH_DESCENT (g
);
3683 if (NILP (LGLYPH_ADJUSTMENT (g
)))
3685 metrics
.width
= LGLYPH_WIDTH (g
);
3686 if (LGLYPH_CHAR (g
) == 0 || metrics
.width
== 0)
3687 need_composition
= 1;
3691 metrics
.width
= LGLYPH_WADJUST (g
);
3692 metrics
.lbearing
+= LGLYPH_XOFF (g
);
3693 metrics
.rbearing
+= LGLYPH_XOFF (g
);
3694 metrics
.ascent
-= LGLYPH_YOFF (g
);
3695 metrics
.descent
+= LGLYPH_YOFF (g
);
3696 need_composition
= 1;
3698 for (j
= i
+ 1; j
< len
; j
++)
3702 g
= LGSTRING_GLYPH (gstring
, j
);
3703 if (this_from
!= LGLYPH_FROM (g
))
3705 need_composition
= 1;
3706 x
= metrics
.width
+ LGLYPH_LBEARING (g
) + LGLYPH_XOFF (g
);
3707 if (metrics
.lbearing
> x
)
3708 metrics
.lbearing
= x
;
3709 x
= metrics
.width
+ LGLYPH_RBEARING (g
) + LGLYPH_XOFF (g
);
3710 if (metrics
.rbearing
< x
)
3711 metrics
.rbearing
= x
;
3712 x
= LGLYPH_ASCENT (g
) - LGLYPH_YOFF (g
);
3713 if (metrics
.ascent
< x
)
3715 x
= LGLYPH_DESCENT (g
) - LGLYPH_YOFF (g
);
3716 if (metrics
.descent
< x
)
3717 metrics
.descent
= x
;
3718 if (NILP (LGLYPH_ADJUSTMENT (g
)))
3719 metrics
.width
+= LGLYPH_WIDTH (g
);
3721 metrics
.width
+= LGLYPH_WADJUST (g
);
3724 if (need_composition
)
3726 gstr
= Ffont_make_gstring (font_object
, make_number (j
- i
));
3727 LGSTRING_SET_WIDTH (gstr
, metrics
.width
);
3728 LGSTRING_SET_LBEARING (gstr
, metrics
.lbearing
);
3729 LGSTRING_SET_RBEARING (gstr
, metrics
.rbearing
);
3730 LGSTRING_SET_ASCENT (gstr
, metrics
.ascent
);
3731 LGSTRING_SET_DESCENT (gstr
, metrics
.descent
);
3732 for (k
= i
; i
< j
; i
++)
3734 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3736 LGLYPH_SET_FROM (g
, LGLYPH_FROM (g
) - this_from
);
3737 LGLYPH_SET_TO (g
, LGLYPH_TO (g
) - this_from
);
3738 LGSTRING_SET_GLYPH (gstr
, i
- k
, LGSTRING_GLYPH (gstring
, i
));
3740 from
= make_number (start
+ this_from
);
3741 to
= make_number (start
+ this_to
);
3743 Fcompose_region_internal (from
, to
, gstr
, Qnil
);
3745 Fcompose_string_internal (string
, from
, to
, gstr
, Qnil
);
3754 DEFUN ("font-drive-otf", Ffont_drive_otf
, Sfont_drive_otf
, 6, 6, 0,
3755 doc
: /* Apply OpenType features on glyph-string GSTRING-IN.
3756 OTF-FEATURES specifies which features to apply in this format:
3757 (SCRIPT LANGSYS GSUB GPOS)
3759 SCRIPT is a symbol specifying a script tag of OpenType,
3760 LANGSYS is a symbol specifying a langsys tag of OpenType,
3761 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
3763 If LANGYS is nil, the default langsys is selected.
3765 The features are applied in the order they appear in the list. The
3766 symbol `*' means to apply all available features not present in this
3767 list, and the remaining features are ignored. For instance, (vatu
3768 pstf * haln) is to apply vatu and pstf in this order, then to apply
3769 all available features other than vatu, pstf, and haln.
3771 The features are applied to the glyphs in the range FROM and TO of
3772 the glyph-string GSTRING-IN.
3774 If some feature is actually applicable, the resulting glyphs are
3775 produced in the glyph-string GSTRING-OUT from the index INDEX. In
3776 this case, the value is the number of produced glyphs.
3778 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
3781 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
3782 produced in GSTRING-OUT, and the value is nil.
3784 See the documentation of `font-make-gstring' for the format of
3786 (otf_features
, gstring_in
, from
, to
, gstring_out
, index
)
3787 Lisp_Object otf_features
, gstring_in
, from
, to
, gstring_out
, index
;
3789 Lisp_Object font_object
= LGSTRING_FONT (gstring_in
);
3794 check_otf_features (otf_features
);
3795 CHECK_FONT_GET_OBJECT (font_object
, font
);
3796 if (! font
->driver
->otf_drive
)
3797 error ("Font backend %s can't drive OpenType GSUB table",
3798 SDATA (SYMBOL_NAME (font
->driver
->type
)));
3799 CHECK_CONS (otf_features
);
3800 CHECK_SYMBOL (XCAR (otf_features
));
3801 val
= XCDR (otf_features
);
3802 CHECK_SYMBOL (XCAR (val
));
3803 val
= XCDR (otf_features
);
3806 len
= check_gstring (gstring_in
);
3807 CHECK_VECTOR (gstring_out
);
3808 CHECK_NATNUM (from
);
3810 CHECK_NATNUM (index
);
3812 if (XINT (from
) >= XINT (to
) || XINT (to
) > len
)
3813 args_out_of_range_3 (from
, to
, make_number (len
));
3814 if (XINT (index
) >= ASIZE (gstring_out
))
3815 args_out_of_range (index
, make_number (ASIZE (gstring_out
)));
3816 num
= font
->driver
->otf_drive (font
, otf_features
,
3817 gstring_in
, XINT (from
), XINT (to
),
3818 gstring_out
, XINT (index
), 0);
3821 return make_number (num
);
3824 DEFUN ("font-otf-alternates", Ffont_otf_alternates
, Sfont_otf_alternates
,
3826 doc
: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
3827 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
3829 (SCRIPT LANGSYS FEATURE ...)
3830 See the documentation of `font-otf-gsub' for more detail.
3832 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
3833 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
3834 character code corresponding to the glyph or nil if there's no
3835 corresponding character. */)
3836 (font_object
, character
, otf_features
)
3837 Lisp_Object font_object
, character
, otf_features
;
3840 Lisp_Object gstring_in
, gstring_out
, g
;
3841 Lisp_Object alternates
;
3844 CHECK_FONT_GET_OBJECT (font_object
, font
);
3845 if (! font
->driver
->otf_drive
)
3846 error ("Font backend %s can't drive OpenType GSUB table",
3847 SDATA (SYMBOL_NAME (font
->driver
->type
)));
3848 CHECK_CHARACTER (character
);
3849 CHECK_CONS (otf_features
);
3851 gstring_in
= Ffont_make_gstring (font_object
, make_number (1));
3852 g
= LGSTRING_GLYPH (gstring_in
, 0);
3853 LGLYPH_SET_CHAR (g
, XINT (character
));
3854 gstring_out
= Ffont_make_gstring (font_object
, make_number (10));
3855 while ((num
= font
->driver
->otf_drive (font
, otf_features
, gstring_in
, 0, 1,
3856 gstring_out
, 0, 1)) < 0)
3857 gstring_out
= Ffont_make_gstring (font_object
,
3858 make_number (ASIZE (gstring_out
) * 2));
3860 for (i
= 0; i
< num
; i
++)
3862 Lisp_Object g
= LGSTRING_GLYPH (gstring_out
, i
);
3863 int c
= LGLYPH_CHAR (g
);
3864 unsigned code
= LGLYPH_CODE (g
);
3866 alternates
= Fcons (Fcons (make_number (code
),
3867 c
> 0 ? make_number (c
) : Qnil
),
3870 return Fnreverse (alternates
);
3876 DEFUN ("open-font", Fopen_font
, Sopen_font
, 1, 3, 0,
3877 doc
: /* Open FONT-ENTITY. */)
3878 (font_entity
, size
, frame
)
3879 Lisp_Object font_entity
;
3885 CHECK_FONT_ENTITY (font_entity
);
3887 size
= AREF (font_entity
, FONT_SIZE_INDEX
);
3888 CHECK_NUMBER (size
);
3890 frame
= selected_frame
;
3891 CHECK_LIVE_FRAME (frame
);
3893 isize
= XINT (size
);
3897 isize
= POINT_TO_PIXEL (- isize
, XFRAME (frame
)->resy
);
3899 return font_open_entity (XFRAME (frame
), font_entity
, isize
);
3902 DEFUN ("close-font", Fclose_font
, Sclose_font
, 1, 2, 0,
3903 doc
: /* Close FONT-OBJECT. */)
3904 (font_object
, frame
)
3905 Lisp_Object font_object
, frame
;
3907 CHECK_FONT_OBJECT (font_object
);
3909 frame
= selected_frame
;
3910 CHECK_LIVE_FRAME (frame
);
3911 font_close_object (XFRAME (frame
), font_object
);
3915 DEFUN ("query-font", Fquery_font
, Squery_font
, 1, 1, 0,
3916 doc
: /* Return information about FONT-OBJECT.
3917 The value is a vector:
3918 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
3921 NAME is a string of the font name (or nil if the font backend doesn't
3924 FILENAME is a string of the font file (or nil if the font backend
3925 doesn't provide a file name).
3927 PIXEL-SIZE is a pixel size by which the font is opened.
3929 SIZE is a maximum advance width of the font in pixel.
3931 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
3934 CAPABILITY is a list whose first element is a symbol representing the
3935 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
3936 remaining elements describes a detail of the font capability.
3938 If the font is OpenType font, the form of the list is
3939 \(opentype GSUB GPOS)
3940 where GSUB shows which "GSUB" features the font supports, and GPOS
3941 shows which "GPOS" features the font supports. Both GSUB and GPOS are
3942 lists of the format:
3943 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
3945 If the font is not OpenType font, currently the length of the form is
3948 SCRIPT is a symbol representing OpenType script tag.
3950 LANGSYS is a symbol representing OpenType langsys tag, or nil
3951 representing the default langsys.
3953 FEATURE is a symbol representing OpenType feature tag.
3955 If the font is not OpenType font, CAPABILITY is nil. */)
3957 Lisp_Object font_object
;
3962 CHECK_FONT_GET_OBJECT (font_object
, font
);
3964 val
= Fmake_vector (make_number (9), Qnil
);
3965 if (font
->font
.full_name
)
3966 ASET (val
, 0, make_unibyte_string (font
->font
.full_name
,
3967 strlen (font
->font
.full_name
)));
3968 if (font
->file_name
)
3969 ASET (val
, 1, make_unibyte_string (font
->file_name
,
3970 strlen (font
->file_name
)));
3971 ASET (val
, 2, make_number (font
->pixel_size
));
3972 ASET (val
, 3, make_number (font
->font
.size
));
3973 ASET (val
, 4, make_number (font
->ascent
));
3974 ASET (val
, 5, make_number (font
->descent
));
3975 ASET (val
, 6, make_number (font
->font
.space_width
));
3976 ASET (val
, 7, make_number (font
->font
.average_width
));
3977 if (font
->driver
->otf_capability
)
3978 ASET (val
, 8, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
3980 ASET (val
, 8, Fcons (font
->format
, Qnil
));
3984 DEFUN ("get-font-glyphs", Fget_font_glyphs
, Sget_font_glyphs
, 2, 2, 0,
3985 doc
: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
3986 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
3987 (font_object
, string
)
3988 Lisp_Object font_object
, string
;
3994 CHECK_FONT_GET_OBJECT (font_object
, font
);
3995 CHECK_STRING (string
);
3996 len
= SCHARS (string
);
3997 vec
= Fmake_vector (make_number (len
), Qnil
);
3998 for (i
= 0; i
< len
; i
++)
4000 Lisp_Object ch
= Faref (string
, make_number (i
));
4005 struct font_metrics metrics
;
4007 cod
= code
= font
->driver
->encode_char (font
, c
);
4008 if (code
== FONT_INVALID_CODE
)
4010 val
= Fmake_vector (make_number (6), Qnil
);
4011 if (cod
<= MOST_POSITIVE_FIXNUM
)
4012 ASET (val
, 0, make_number (code
));
4014 ASET (val
, 0, Fcons (make_number (code
>> 16),
4015 make_number (code
& 0xFFFF)));
4016 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4017 ASET (val
, 1, make_number (metrics
.lbearing
));
4018 ASET (val
, 2, make_number (metrics
.rbearing
));
4019 ASET (val
, 3, make_number (metrics
.width
));
4020 ASET (val
, 4, make_number (metrics
.ascent
));
4021 ASET (val
, 5, make_number (metrics
.descent
));
4027 DEFUN ("font-match-p", Ffont_match_p
, Sfont_match_p
, 2, 2, 0,
4028 doc
: /* Return t iff font-spec SPEC matches with FONT.
4029 FONT is a font-spec, font-entity, or font-object. */)
4031 Lisp_Object spec
, font
;
4033 CHECK_FONT_SPEC (spec
);
4034 if (FONT_OBJECT_P (font
))
4035 font
= ((struct font
*) XSAVE_VALUE (font
)->pointer
)->entity
;
4036 else if (! FONT_ENTITY_P (font
))
4037 CHECK_FONT_SPEC (font
);
4039 return (font_match_p (spec
, font
) ? Qt
: Qnil
);
4042 DEFUN ("font-at", Ffont_at
, Sfont_at
, 1, 3, 0,
4043 doc
: /* Return a font-object for displaying a character at POSITION.
4044 Optional second arg WINDOW, if non-nil, is a window displaying
4045 the current buffer. It defaults to the currently selected window. */)
4046 (position
, window
, string
)
4047 Lisp_Object position
, window
, string
;
4054 CHECK_NUMBER_COERCE_MARKER (position
);
4055 pos
= XINT (position
);
4056 if (pos
< BEGV
|| pos
>= ZV
)
4057 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
4064 CHECK_NUMBER (position
);
4065 CHECK_STRING (string
);
4066 pos
= XINT (position
);
4067 if (pos
< 0 || pos
>= SCHARS (string
))
4068 args_out_of_range (string
, position
);
4071 window
= selected_window
;
4072 CHECK_LIVE_WINDOW (window
);
4073 w
= XWINDOW (window
);
4075 return font_at (-1, pos
, NULL
, w
, string
);
4079 DEFUN ("draw-string", Fdraw_string
, Sdraw_string
, 2, 2, 0,
4080 doc
: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4081 The value is a number of glyphs drawn.
4082 Type C-l to recover what previously shown. */)
4083 (font_object
, string
)
4084 Lisp_Object font_object
, string
;
4086 Lisp_Object frame
= selected_frame
;
4087 FRAME_PTR f
= XFRAME (frame
);
4093 CHECK_FONT_GET_OBJECT (font_object
, font
);
4094 CHECK_STRING (string
);
4095 len
= SCHARS (string
);
4096 code
= alloca (sizeof (unsigned) * len
);
4097 for (i
= 0; i
< len
; i
++)
4099 Lisp_Object ch
= Faref (string
, make_number (i
));
4103 code
[i
] = font
->driver
->encode_char (font
, c
);
4104 if (code
[i
] == FONT_INVALID_CODE
)
4107 face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4109 if (font
->driver
->prepare_face
)
4110 font
->driver
->prepare_face (f
, face
);
4111 width
= font
->driver
->text_extents (font
, code
, i
, NULL
);
4112 len
= font
->driver
->draw_text (f
, face
, 0, font
->ascent
, code
, i
, width
);
4113 if (font
->driver
->done_face
)
4114 font
->driver
->done_face (f
, face
);
4116 return make_number (len
);
4120 #endif /* FONT_DEBUG */
4123 extern void syms_of_ftfont
P_ (());
4124 extern void syms_of_xfont
P_ (());
4125 extern void syms_of_xftfont
P_ (());
4126 extern void syms_of_ftxfont
P_ (());
4127 extern void syms_of_bdffont
P_ (());
4128 extern void syms_of_w32font
P_ (());
4129 extern void syms_of_atmfont
P_ (());
4134 sort_shift_bits
[FONT_SLANT_INDEX
] = 0;
4135 sort_shift_bits
[FONT_WEIGHT_INDEX
] = 7;
4136 sort_shift_bits
[FONT_SIZE_INDEX
] = 14;
4137 sort_shift_bits
[FONT_WIDTH_INDEX
] = 21;
4138 sort_shift_bits
[FONT_ADSTYLE_INDEX
] = 28;
4139 sort_shift_bits
[FONT_FOUNDRY_INDEX
] = 29;
4140 sort_shift_bits
[FONT_FAMILY_INDEX
] = 30;
4141 sort_shift_bits
[FONT_REGISTRY_INDEX
] = 31;
4142 /* Note that sort_shift_bits[FONT_TYPE_INDEX] is never used. */
4144 staticpro (&font_style_table
);
4145 font_style_table
= Fmake_vector (make_number (3), Qnil
);
4147 staticpro (&font_family_alist
);
4148 font_family_alist
= Qnil
;
4150 staticpro (&font_charset_alist
);
4151 font_charset_alist
= Qnil
;
4153 DEFSYM (Qopentype
, "opentype");
4155 DEFSYM (Qiso8859_1
, "iso8859-1");
4156 DEFSYM (Qiso10646_1
, "iso10646-1");
4157 DEFSYM (Qunicode_bmp
, "unicode-bmp");
4158 DEFSYM (Qunicode_sip
, "unicode-sip");
4160 DEFSYM (QCotf
, ":otf");
4161 DEFSYM (QClanguage
, ":language");
4162 DEFSYM (QCscript
, ":script");
4163 DEFSYM (QCantialias
, ":antialias");
4165 DEFSYM (QCfoundry
, ":foundry");
4166 DEFSYM (QCadstyle
, ":adstyle");
4167 DEFSYM (QCregistry
, ":registry");
4168 DEFSYM (QCspacing
, ":spacing");
4169 DEFSYM (QCdpi
, ":dpi");
4170 DEFSYM (QCscalable
, ":scalable");
4171 DEFSYM (QCextra
, ":extra");
4178 staticpro (&null_string
);
4179 null_string
= build_string ("");
4180 staticpro (&null_vector
);
4181 null_vector
= Fmake_vector (make_number (0), Qnil
);
4183 staticpro (&scratch_font_spec
);
4184 scratch_font_spec
= Ffont_spec (0, NULL
);
4185 staticpro (&scratch_font_prefer
);
4186 scratch_font_prefer
= Ffont_spec (0, NULL
);
4189 staticpro (&otf_list
);
4194 defsubr (&Sfont_spec
);
4195 defsubr (&Sfont_get
);
4196 defsubr (&Sfont_put
);
4197 defsubr (&Slist_fonts
);
4198 defsubr (&Slist_families
);
4199 defsubr (&Sfind_font
);
4200 defsubr (&Sfont_xlfd_name
);
4201 defsubr (&Sclear_font_cache
);
4202 defsubr (&Sinternal_set_font_style_table
);
4203 defsubr (&Sfont_make_gstring
);
4204 defsubr (&Sfont_fill_gstring
);
4205 defsubr (&Sfont_shape_text
);
4206 defsubr (&Sfont_drive_otf
);
4207 defsubr (&Sfont_otf_alternates
);
4210 defsubr (&Sopen_font
);
4211 defsubr (&Sclose_font
);
4212 defsubr (&Squery_font
);
4213 defsubr (&Sget_font_glyphs
);
4214 defsubr (&Sfont_match_p
);
4215 defsubr (&Sfont_at
);
4217 defsubr (&Sdraw_string
);
4219 #endif /* FONT_DEBUG */
4221 #ifdef USE_FONT_BACKEND
4222 if (enable_font_backend
)
4224 #ifdef HAVE_FREETYPE
4226 #ifdef HAVE_X_WINDOWS
4231 #endif /* HAVE_XFT */
4232 #endif /* HAVE_X_WINDOWS */
4233 #else /* not HAVE_FREETYPE */
4234 #ifdef HAVE_X_WINDOWS
4236 #endif /* HAVE_X_WINDOWS */
4237 #endif /* not HAVE_FREETYPE */
4240 #endif /* HAVE_BDFFONT */
4243 #endif /* WINDOWSNT */
4248 #endif /* USE_FONT_BACKEND */
4251 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
4252 (do not change this comment) */