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
);
873 /* Parse NAME (null terminated) as XLFD and store information in FONT
874 (font-spec or font-entity). Size property of FONT is set as
876 specified XLFD fields FONT property
877 --------------------- -------------
878 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
879 POINT_SIZE and RESY calculated pixel size (Lisp integer)
880 POINT_SIZE POINT_SIZE/10 (Lisp float)
882 If NAME is successfully parsed, return 0. Otherwise return -1.
884 FONT is usually a font-spec, but when this function is called from
885 X font backend driver, it is a font-entity. In that case, NAME is
886 a fully specified XLFD, and we set FONT_EXTRA_INDEX of FONT to a
887 symbol RESX-RESY-SPACING-AVGWIDTH.
891 font_parse_xlfd (name
, font
)
895 int len
= strlen (name
);
897 Lisp_Object dpi
, spacing
;
899 char *f
[XLFD_LAST_INDEX
+ 1];
904 /* Maximum XLFD name length is 255. */
906 /* Accept "*-.." as a fully specified XLFD. */
907 if (name
[0] == '*' && name
[1] == '-')
908 i
= 1, f
[XLFD_FOUNDRY_INDEX
] = name
;
911 for (p
= name
+ i
; *p
; p
++)
912 if (*p
== '-' && i
< XLFD_LAST_INDEX
)
916 dpi
= spacing
= Qnil
;
919 if (i
== XLFD_LAST_INDEX
)
923 /* Fully specified XLFD. */
924 for (i
= 0, j
= FONT_FOUNDRY_INDEX
; i
< XLFD_WEIGHT_INDEX
; i
++, j
++)
926 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
930 for (j
= FONT_WEIGHT_INDEX
; i
< XLFD_ADSTYLE_INDEX
; i
++, j
++)
932 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
935 Lisp_Object numeric
= prop_name_to_numeric (j
, val
);
937 if (INTEGERP (numeric
))
942 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
944 ASET (font
, FONT_ADSTYLE_INDEX
, val
);
945 i
= XLFD_REGISTRY_INDEX
;
946 val
= intern_font_field (f
[i
], f
[i
+ 2] - f
[i
]);
948 ASET (font
, FONT_REGISTRY_INDEX
, val
);
950 p
= f
[XLFD_PIXEL_INDEX
];
951 if (*p
== '[' && (pixel_size
= parse_matrix (p
)) >= 0)
952 ASET (font
, FONT_SIZE_INDEX
, make_number (pixel_size
));
955 i
= XLFD_PIXEL_INDEX
;
956 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
958 ASET (font
, FONT_SIZE_INDEX
, val
);
961 double point_size
= -1;
963 xassert (FONT_SPEC_P (font
));
964 p
= f
[XLFD_POINT_INDEX
];
966 point_size
= parse_matrix (p
);
967 else if (isdigit (*p
))
968 point_size
= atoi (p
), point_size
/= 10;
970 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
973 i
= XLFD_PIXEL_INDEX
;
974 val
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
976 ASET (font
, FONT_SIZE_INDEX
, val
);
981 /* Parse RESX, RESY, SPACING, and AVGWIDTH. */
982 if (FONT_ENTITY_P (font
))
985 ASET (font
, FONT_EXTRA_INDEX
,
986 intern_font_field (f
[i
], f
[XLFD_REGISTRY_INDEX
] - 1 - f
[i
]));
990 /* Here we just setup DPI, SPACING, and AVGWIDTH. They are set
991 in FONT_EXTRA_INDEX later. */
993 dpi
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
994 i
= XLFD_SPACING_INDEX
;
995 spacing
= intern_font_field (f
[i
], f
[i
+ 1] - 1 - f
[i
]);
996 p
= f
[XLFD_AVGWIDTH_INDEX
];
1000 avgwidth
= atoi (p
);
1004 int wild_card_found
= 0;
1005 Lisp_Object prop
[XLFD_LAST_INDEX
];
1007 for (j
= 0; j
< i
; j
++)
1011 if (f
[j
][1] && f
[j
][1] != '-')
1014 wild_card_found
= 1;
1016 else if (isdigit (*f
[j
]))
1018 for (p
= f
[j
] + 1; isdigit (*p
); p
++);
1019 if (*p
&& *p
!= '-')
1020 prop
[j
] = intern_downcase (f
[j
], p
- f
[j
]);
1022 prop
[j
] = make_number (atoi (f
[j
]));
1025 prop
[j
] = intern_font_field (f
[j
], f
[j
+ 1] - 1 - f
[j
]);
1027 prop
[j
] = intern_font_field (f
[j
], f
[i
] - f
[j
]);
1029 if (! wild_card_found
)
1031 if (font_expand_wildcards (prop
, i
) < 0)
1034 for (i
= 0, j
= FONT_FOUNDRY_INDEX
; i
< XLFD_WEIGHT_INDEX
; i
++, j
++)
1035 if (! NILP (prop
[i
]))
1036 ASET (font
, j
, prop
[i
]);
1037 for (j
= FONT_WEIGHT_INDEX
; i
< XLFD_ADSTYLE_INDEX
; i
++, j
++)
1038 if (! NILP (prop
[i
]))
1039 ASET (font
, j
, prop
[i
]);
1040 if (! NILP (prop
[XLFD_ADSTYLE_INDEX
]))
1041 ASET (font
, FONT_ADSTYLE_INDEX
, prop
[XLFD_ADSTYLE_INDEX
]);
1042 val
= prop
[XLFD_REGISTRY_INDEX
];
1045 val
= prop
[XLFD_ENCODING_INDEX
];
1047 val
= Fintern (concat2 (build_string ("*-"), SYMBOL_NAME (val
)),
1050 else if (NILP (prop
[XLFD_ENCODING_INDEX
]))
1051 val
= Fintern (concat2 (SYMBOL_NAME (val
), build_string ("-*")),
1054 val
= Fintern (concat3 (SYMBOL_NAME (val
), build_string ("-"),
1055 SYMBOL_NAME (prop
[XLFD_ENCODING_INDEX
])),
1058 ASET (font
, FONT_REGISTRY_INDEX
, val
);
1060 if (INTEGERP (prop
[XLFD_PIXEL_INDEX
]))
1061 ASET (font
, FONT_SIZE_INDEX
, prop
[XLFD_PIXEL_INDEX
]);
1062 else if (INTEGERP (prop
[XLFD_POINT_INDEX
]))
1064 double point_size
= XINT (prop
[XLFD_POINT_INDEX
]);
1066 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
/ 10));
1069 dpi
= prop
[XLFD_RESX_INDEX
];
1070 spacing
= prop
[XLFD_SPACING_INDEX
];
1071 if (INTEGERP (prop
[XLFD_AVGWIDTH_INDEX
]))
1072 avgwidth
= XINT (prop
[XLFD_AVGWIDTH_INDEX
]);
1076 font_put_extra (font
, QCdpi
, dpi
);
1077 if (! NILP (spacing
))
1078 font_put_extra (font
, QCspacing
, spacing
);
1080 font_put_extra (font
, QCscalable
, avgwidth
== 0 ? Qt
: Qnil
);
1085 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1086 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1087 0, use PIXEL_SIZE instead. */
1090 font_unparse_xlfd (font
, pixel_size
, name
, nbytes
)
1096 char *f
[XLFD_REGISTRY_INDEX
+ 1];
1100 xassert (FONTP (font
));
1102 for (i
= FONT_FOUNDRY_INDEX
, j
= XLFD_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
;
1105 if (i
== FONT_ADSTYLE_INDEX
)
1106 j
= XLFD_ADSTYLE_INDEX
;
1107 else if (i
== FONT_REGISTRY_INDEX
)
1108 j
= XLFD_REGISTRY_INDEX
;
1109 val
= AREF (font
, i
);
1112 if (j
== XLFD_REGISTRY_INDEX
)
1113 f
[j
] = "*-*", len
+= 4;
1115 f
[j
] = "*", len
+= 2;
1120 val
= SYMBOL_NAME (val
);
1121 if (j
== XLFD_REGISTRY_INDEX
1122 && ! strchr ((char *) SDATA (val
), '-'))
1124 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1125 if (SDATA (val
)[SBYTES (val
) - 1] == '*')
1127 f
[j
] = alloca (SBYTES (val
) + 3);
1128 sprintf (f
[j
], "%s-*", SDATA (val
));
1129 len
+= SBYTES (val
) + 3;
1133 f
[j
] = alloca (SBYTES (val
) + 4);
1134 sprintf (f
[j
], "%s*-*", SDATA (val
));
1135 len
+= SBYTES (val
) + 4;
1139 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1143 for (i
= FONT_WEIGHT_INDEX
, j
= XLFD_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
;
1146 val
= AREF (font
, i
);
1148 f
[j
] = "*", len
+= 2;
1152 val
= prop_numeric_to_name (i
, XINT (val
));
1154 val
= SYMBOL_NAME (val
);
1155 xassert (STRINGP (val
));
1156 f
[j
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1160 val
= AREF (font
, FONT_SIZE_INDEX
);
1161 xassert (NUMBERP (val
) || NILP (val
));
1169 f
[XLFD_PIXEL_INDEX
] = alloca (22);
1170 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "%d-*", i
) + 1;
1173 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1175 else if (FLOATP (val
))
1177 int i
= XFLOAT_DATA (val
) * 10;
1178 f
[XLFD_PIXEL_INDEX
] = alloca (12);
1179 len
+= sprintf (f
[XLFD_PIXEL_INDEX
], "*-%d", i
) + 1;
1182 f
[XLFD_PIXEL_INDEX
] = "*-*", len
+= 4;
1184 val
= AREF (font
, FONT_EXTRA_INDEX
);
1186 if (FONT_ENTITY_P (font
)
1187 && EQ (AREF (font
, FONT_TYPE_INDEX
), Qx
))
1189 /* Setup names for RESX-RESY-SPACING-AVWIDTH. */
1190 if (SYMBOLP (val
) && ! NILP (val
))
1192 val
= SYMBOL_NAME (val
);
1193 f
[XLFD_RESX_INDEX
] = (char *) SDATA (val
), len
+= SBYTES (val
) + 1;
1196 f
[XLFD_RESX_INDEX
] = "*-*-*-*", len
+= 6;
1200 Lisp_Object dpi
= assq_no_quit (QCdpi
, val
);
1201 Lisp_Object spacing
= assq_no_quit (QCspacing
, val
);
1202 Lisp_Object scalable
= assq_no_quit (QCscalable
, val
);
1204 if (CONSP (dpi
) || CONSP (spacing
) || CONSP (scalable
))
1206 char *str
= alloca (24);
1209 if (CONSP (dpi
) && INTEGERP (XCDR (dpi
)))
1210 this_len
= sprintf (str
, "%d-%d",
1211 XINT (XCDR (dpi
)), XINT (XCDR (dpi
)));
1213 this_len
= sprintf (str
, "*-*");
1214 if (CONSP (spacing
) && ! NILP (XCDR (spacing
)))
1216 val
= XCDR (spacing
);
1219 if (XINT (val
) < FONT_SPACING_MONO
)
1221 else if (XINT (val
) < FONT_SPACING_CHARCELL
)
1226 xassert (SYMBOLP (val
));
1227 this_len
+= sprintf (str
+ this_len
, "-%c",
1228 SDATA (SYMBOL_NAME (val
))[0]);
1231 this_len
+= sprintf (str
+ this_len
, "-*");
1232 if (CONSP (scalable
) && ! NILP (XCDR (spacing
)))
1233 this_len
+= sprintf (str
+ this_len
, "-0");
1235 this_len
+= sprintf (str
+ this_len
, "-*");
1236 f
[XLFD_RESX_INDEX
] = str
;
1240 f
[XLFD_RESX_INDEX
] = "*-*-*-*", len
+= 8;
1243 len
++; /* for terminating '\0'. */
1246 return sprintf (name
, "-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1247 f
[XLFD_FOUNDRY_INDEX
], f
[XLFD_FAMILY_INDEX
],
1248 f
[XLFD_WEIGHT_INDEX
], f
[XLFD_SLANT_INDEX
],
1249 f
[XLFD_SWIDTH_INDEX
],
1250 f
[XLFD_ADSTYLE_INDEX
], f
[XLFD_PIXEL_INDEX
],
1251 f
[XLFD_RESX_INDEX
], f
[XLFD_REGISTRY_INDEX
]);
1254 /* Parse NAME (null terminated) as Fonconfig's name format and store
1255 information in FONT (font-spec or font-entity). If NAME is
1256 successfully parsed, return 0. Otherwise return -1. */
1259 font_parse_fcname (name
, font
)
1264 int len
= strlen (name
);
1271 /* It is assured that (name[0] && name[0] != '-'). */
1279 for (p0
= name
+ 1; *p0
&& (*p0
!= '-' && *p0
!= ':'); p0
++)
1280 if (*p0
== '\\' && p0
[1])
1282 family
= intern_font_field (name
, p0
- name
);
1285 if (! isdigit (p0
[1]))
1287 point_size
= strtod (p0
+ 1, &p1
);
1288 if (*p1
&& *p1
!= ':')
1290 ASET (font
, FONT_SIZE_INDEX
, make_float (point_size
));
1293 ASET (font
, FONT_FAMILY_INDEX
, family
);
1297 copy
= alloca (len
+ 1);
1302 /* Now parse ":KEY=VAL" patterns. Store known keys and values in
1303 extra, copy unknown ones to COPY. */
1306 Lisp_Object key
, val
;
1309 for (p1
= p0
+ 1; *p1
&& *p1
!= '=' && *p1
!= ':'; p1
++);
1312 /* Must be an enumerated value. */
1313 val
= intern_font_field (p0
+ 1, p1
- p0
- 1);
1314 if (memcmp (p0
+ 1, "light", 5) == 0
1315 || memcmp (p0
+ 1, "medium", 6) == 0
1316 || memcmp (p0
+ 1, "demibold", 8) == 0
1317 || memcmp (p0
+ 1, "bold", 4) == 0
1318 || memcmp (p0
+ 1, "black", 5) == 0)
1320 ASET (font
, FONT_WEIGHT_INDEX
, val
);
1323 else if (memcmp (p0
+ 1, "roman", 5) == 0
1324 || memcmp (p0
+ 1, "italic", 6) == 0
1325 || memcmp (p0
+ 1, "oblique", 7) == 0)
1327 ASET (font
, FONT_SLANT_INDEX
, val
);
1330 else if (memcmp (p0
+ 1, "charcell", 8) == 0
1331 || memcmp (p0
+ 1, "mono", 4) == 0
1332 || memcmp (p0
+ 1, "proportional", 12) == 0)
1334 font_put_extra (font
, QCspacing
,
1335 (p0
[1] == 'c' ? Qc
: p0
[1] == 'm' ? Qm
: Qp
));
1340 bcopy (p0
, copy
, p1
- p0
);
1346 if (memcmp (p0
+ 1, "pixelsize=", 10) == 0)
1347 prop
= FONT_SIZE_INDEX
;
1350 key
= intern_font_field (p0
, p1
- p0
);
1351 prop
= get_font_prop_index (key
, 0);
1354 for (p1
= p0
; *p1
&& *p1
!= ':'; p1
++);
1355 val
= intern_font_field (p0
, p1
- p0
);
1358 if (prop
>= 0 && prop
< FONT_EXTRA_INDEX
)
1360 if (prop
== FONT_WEIGHT_INDEX
)
1362 else if (prop
== FONT_SLANT_INDEX
)
1365 ASET (font
, prop
, val
);
1368 font_put_extra (font
, key
, val
);
1375 ASET (font
, FONT_WEIGHT_INDEX
, build_string ("normal"));
1377 ASET (font
, FONT_SLANT_INDEX
, build_string ("normal"));
1382 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1383 NAME (NBYTES length), and return the name length. If
1384 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1387 font_unparse_fcname (font
, pixel_size
, name
, nbytes
)
1395 int dpi
, spacing
, scalable
;
1398 Lisp_Object styles
[3];
1399 char *style_names
[3] = { "weight", "slant", "width" };
1401 val
= AREF (font
, FONT_FAMILY_INDEX
);
1402 if (SYMBOLP (val
) && ! NILP (val
))
1403 len
+= SBYTES (SYMBOL_NAME (val
));
1405 val
= AREF (font
, FONT_SIZE_INDEX
);
1408 if (XINT (val
) != 0)
1409 pixel_size
= XINT (val
);
1411 len
+= 21; /* for ":pixelsize=NUM" */
1413 else if (FLOATP (val
))
1416 point_size
= (int) XFLOAT_DATA (val
);
1417 len
+= 11; /* for "-NUM" */
1420 val
= AREF (font
, FONT_FOUNDRY_INDEX
);
1421 if (SYMBOLP (val
) && ! NILP (val
))
1422 /* ":foundry=NAME" */
1423 len
+= 9 + SBYTES (SYMBOL_NAME (val
));
1425 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_WIDTH_INDEX
; i
++)
1427 val
= AREF (font
, i
);
1430 val
= prop_numeric_to_name (i
, XINT (val
));
1431 len
+= (strlen (style_names
[i
- FONT_WEIGHT_INDEX
])
1432 + 2 + SBYTES (SYMBOL_NAME (val
))); /* :xxx=NAME */
1434 styles
[i
- FONT_WEIGHT_INDEX
] = val
;
1437 val
= AREF (font
, FONT_EXTRA_INDEX
);
1438 if (FONT_ENTITY_P (font
)
1439 && EQ (AREF (font
, FONT_TYPE_INDEX
), Qx
))
1443 /* VAL is a symbol of name `RESX-RESY-SPACING-AVWIDTH'. */
1444 p
= (char *) SDATA (SYMBOL_NAME (val
));
1446 for (p
++; *p
!= '-'; p
++); /* skip RESX */
1447 for (p
++; *p
!= '-'; p
++); /* skip RESY */
1448 spacing
= (*p
== 'c' ? FONT_SPACING_CHARCELL
1449 : *p
== 'm' ? FONT_SPACING_MONO
1450 : FONT_SPACING_PROPORTIONAL
);
1451 for (p
++; *p
!= '-'; p
++); /* skip SPACING */
1452 scalable
= (atoi (p
) == 0);
1453 /* The longest pattern is ":dpi=NUM:scalable=False:spacing=100" */
1460 dpi
= spacing
= scalable
= -1;
1461 elt
= assq_no_quit (QCdpi
, val
);
1463 dpi
= XINT (XCDR (elt
)), len
+= 15; /* for ":dpi=NUM" */
1464 elt
= assq_no_quit (QCspacing
, val
);
1466 spacing
= XINT (XCDR (elt
)), len
+= 12; /* for ":spacing=100" */
1467 elt
= assq_no_quit (QCscalable
, val
);
1469 scalable
= ! NILP (XCDR (elt
)), len
+= 15; /* for ":scalable=False" */
1475 if (! NILP (AREF (font
, FONT_FAMILY_INDEX
)))
1476 p
+= sprintf(p
, "%s",
1477 SDATA (SYMBOL_NAME (AREF (font
, FONT_FAMILY_INDEX
))));
1481 p
+= sprintf (p
, "%d", point_size
);
1483 p
+= sprintf (p
, "-%d", point_size
);
1485 else if (pixel_size
> 0)
1486 p
+= sprintf (p
, ":pixelsize=%d", pixel_size
);
1487 if (SYMBOLP (AREF (font
, FONT_FOUNDRY_INDEX
))
1488 && ! NILP (AREF (font
, FONT_FOUNDRY_INDEX
)))
1489 p
+= sprintf (p
, ":foundry=%s",
1490 SDATA (SYMBOL_NAME (AREF (font
, FONT_FOUNDRY_INDEX
))));
1491 for (i
= 0; i
< 3; i
++)
1492 if (SYMBOLP (styles
[i
]) && ! NILP (styles
[i
]))
1493 p
+= sprintf (p
, ":%s=%s", style_names
[i
],
1494 SDATA (SYMBOL_NAME (styles
[i
])));
1496 p
+= sprintf (p
, ":dpi=%d", dpi
);
1498 p
+= sprintf (p
, ":spacing=%d", spacing
);
1500 p
+= sprintf (p
, ":scalable=True");
1501 else if (scalable
== 0)
1502 p
+= sprintf (p
, ":scalable=False");
1506 /* Parse NAME (null terminated) and store information in FONT
1507 (font-spec or font-entity). If NAME is successfully parsed, return
1508 0. Otherwise return -1.
1510 If NAME is XLFD and FONT is a font-entity, store
1511 RESX-RESY-SPACING-AVWIDTH information as a symbol in
1512 FONT_EXTRA_INDEX. */
1515 font_parse_name (name
, font
)
1519 if (name
[0] == '-' || index (name
, '*'))
1520 return font_parse_xlfd (name
, font
);
1521 return font_parse_fcname (name
, font
);
1524 /* Merge old style font specification (either a font name NAME or a
1525 combination of a family name FAMILY and a registry name REGISTRY
1526 into the font specification SPEC. */
1529 font_merge_old_spec (name
, family
, registry
, spec
)
1530 Lisp_Object name
, family
, registry
, spec
;
1534 if (font_parse_xlfd ((char *) SDATA (name
), spec
) < 0)
1536 Lisp_Object extra
= Fcons (Fcons (QCname
, name
), Qnil
);
1538 ASET (spec
, FONT_EXTRA_INDEX
, extra
);
1543 if (! NILP (family
))
1548 xassert (STRINGP (family
));
1549 len
= SBYTES (family
);
1550 p0
= (char *) SDATA (family
);
1551 p1
= index (p0
, '-');
1554 if ((*p0
!= '*' || p1
- p0
> 1)
1555 && NILP (AREF (spec
, FONT_FOUNDRY_INDEX
)))
1556 ASET (spec
, FONT_FOUNDRY_INDEX
,
1557 intern_downcase (p0
, p1
- p0
));
1558 if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
1559 ASET (spec
, FONT_FAMILY_INDEX
,
1560 intern_downcase (p1
+ 1, len
- (p1
+ 1 - p0
)));
1562 else if (NILP (AREF (spec
, FONT_FAMILY_INDEX
)))
1563 ASET (spec
, FONT_FAMILY_INDEX
, intern_downcase (p0
, len
));
1565 if (! NILP (registry
)
1566 && NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
1567 ASET (spec
, FONT_REGISTRY_INDEX
,
1568 intern_downcase ((char *) SDATA (registry
), SBYTES (registry
)));
1573 /* This part (through the next ^L) is still experimental and never
1574 tested. We may drastically change codes. */
1578 #define LGSTRING_HEADER_SIZE 6
1579 #define LGSTRING_GLYPH_SIZE 8
1582 check_gstring (gstring
)
1583 Lisp_Object gstring
;
1588 CHECK_VECTOR (gstring
);
1589 val
= AREF (gstring
, 0);
1591 if (ASIZE (val
) < LGSTRING_HEADER_SIZE
)
1593 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring
));
1594 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
)))
1595 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_LBEARING
));
1596 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
)))
1597 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_RBEARING
));
1598 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
)))
1599 CHECK_NATNUM (LGSTRING_SLOT (gstring
, LGSTRING_IX_WIDTH
));
1600 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1601 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1602 if (!NILP (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
)))
1603 CHECK_NUMBER (LGSTRING_SLOT (gstring
, LGSTRING_IX_ASCENT
));
1605 for (i
= 0; i
< LGSTRING_LENGTH (gstring
); i
++)
1607 val
= LGSTRING_GLYPH (gstring
, i
);
1609 if (ASIZE (val
) < LGSTRING_GLYPH_SIZE
)
1611 if (NILP (AREF (val
, LGLYPH_IX_CHAR
)))
1613 CHECK_NATNUM (AREF (val
, LGLYPH_IX_FROM
));
1614 CHECK_NATNUM (AREF (val
, LGLYPH_IX_TO
));
1615 CHECK_CHARACTER (AREF (val
, LGLYPH_IX_CHAR
));
1616 if (!NILP (AREF (val
, LGLYPH_IX_CODE
)))
1617 CHECK_NATNUM (AREF (val
, LGLYPH_IX_CODE
));
1618 if (!NILP (AREF (val
, LGLYPH_IX_WIDTH
)))
1619 CHECK_NATNUM (AREF (val
, LGLYPH_IX_WIDTH
));
1620 if (!NILP (AREF (val
, LGLYPH_IX_ADJUSTMENT
)))
1622 val
= AREF (val
, LGLYPH_IX_ADJUSTMENT
);
1624 if (ASIZE (val
) < 3)
1626 for (j
= 0; j
< 3; j
++)
1627 CHECK_NUMBER (AREF (val
, j
));
1632 error ("Invalid glyph-string format");
1637 check_otf_features (otf_features
)
1638 Lisp_Object otf_features
;
1640 Lisp_Object val
, elt
;
1642 CHECK_CONS (otf_features
);
1643 CHECK_SYMBOL (XCAR (otf_features
));
1644 otf_features
= XCDR (otf_features
);
1645 CHECK_CONS (otf_features
);
1646 CHECK_SYMBOL (XCAR (otf_features
));
1647 otf_features
= XCDR (otf_features
);
1648 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1650 CHECK_SYMBOL (Fcar (val
));
1651 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1652 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val
)));
1654 otf_features
= XCDR (otf_features
);
1655 for (val
= Fcar (otf_features
); ! NILP (val
); val
= Fcdr (val
))
1657 CHECK_SYMBOL (Fcar (val
));
1658 if (SBYTES (SYMBOL_NAME (XCAR (val
))) > 4)
1659 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val
)));
1666 Lisp_Object otf_list
;
1669 otf_tag_symbol (tag
)
1674 OTF_tag_name (tag
, name
);
1675 return Fintern (make_unibyte_string (name
, 4), Qnil
);
1679 otf_open (entity
, file
)
1683 Lisp_Object val
= Fassoc (entity
, otf_list
);
1687 otf
= XSAVE_VALUE (XCDR (val
))->pointer
;
1690 otf
= file
? OTF_open (file
) : NULL
;
1691 val
= make_save_value (otf
, 0);
1692 otf_list
= Fcons (Fcons (entity
, val
), otf_list
);
1698 /* Return a list describing which scripts/languages FONT supports by
1699 which GSUB/GPOS features of OpenType tables. See the comment of
1700 (sturct font_driver).otf_capability. */
1703 font_otf_capability (font
)
1707 Lisp_Object capability
= Fcons (Qnil
, Qnil
);
1710 otf
= otf_open (font
->entity
, font
->file_name
);
1713 for (i
= 0; i
< 2; i
++)
1715 OTF_GSUB_GPOS
*gsub_gpos
;
1716 Lisp_Object script_list
= Qnil
;
1719 if (OTF_get_features (otf
, i
== 0) < 0)
1721 gsub_gpos
= i
== 0 ? otf
->gsub
: otf
->gpos
;
1722 for (j
= gsub_gpos
->ScriptList
.ScriptCount
- 1; j
>= 0; j
--)
1724 OTF_Script
*script
= gsub_gpos
->ScriptList
.Script
+ j
;
1725 Lisp_Object langsys_list
= Qnil
;
1726 Lisp_Object script_tag
= otf_tag_symbol (script
->ScriptTag
);
1729 for (k
= script
->LangSysCount
; k
>= 0; k
--)
1731 OTF_LangSys
*langsys
;
1732 Lisp_Object feature_list
= Qnil
;
1733 Lisp_Object langsys_tag
;
1736 if (k
== script
->LangSysCount
)
1738 langsys
= &script
->DefaultLangSys
;
1743 langsys
= script
->LangSys
+ k
;
1745 = otf_tag_symbol (script
->LangSysRecord
[k
].LangSysTag
);
1747 for (l
= langsys
->FeatureCount
- 1; l
>= 0; l
--)
1749 OTF_Feature
*feature
1750 = gsub_gpos
->FeatureList
.Feature
+ langsys
->FeatureIndex
[l
];
1751 Lisp_Object feature_tag
1752 = otf_tag_symbol (feature
->FeatureTag
);
1754 feature_list
= Fcons (feature_tag
, feature_list
);
1756 langsys_list
= Fcons (Fcons (langsys_tag
, feature_list
),
1759 script_list
= Fcons (Fcons (script_tag
, langsys_list
),
1764 XSETCAR (capability
, script_list
);
1766 XSETCDR (capability
, script_list
);
1772 /* Parse OTF features in SPEC and write a proper features spec string
1773 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1774 assured that the sufficient memory has already allocated for
1778 generate_otf_features (spec
, features
)
1788 for (asterisk
= 0; CONSP (spec
); spec
= XCDR (spec
))
1794 if (SREF (SYMBOL_NAME (val
), 0) == '*')
1799 else if (! asterisk
)
1801 val
= SYMBOL_NAME (val
);
1802 p
+= sprintf (p
, "%s", SDATA (val
));
1806 val
= SYMBOL_NAME (val
);
1807 p
+= sprintf (p
, "~%s", SDATA (val
));
1811 error ("OTF spec too long");
1816 font_otf_DeviceTable (device_table
)
1817 OTF_DeviceTable
*device_table
;
1819 int len
= device_table
->StartSize
- device_table
->EndSize
+ 1;
1821 return Fcons (make_number (len
),
1822 make_unibyte_string (device_table
->DeltaValue
, len
));
1826 font_otf_ValueRecord (value_format
, value_record
)
1828 OTF_ValueRecord
*value_record
;
1830 Lisp_Object val
= Fmake_vector (make_number (8), Qnil
);
1832 if (value_format
& OTF_XPlacement
)
1833 ASET (val
, 0, make_number (value_record
->XPlacement
));
1834 if (value_format
& OTF_YPlacement
)
1835 ASET (val
, 1, make_number (value_record
->YPlacement
));
1836 if (value_format
& OTF_XAdvance
)
1837 ASET (val
, 2, make_number (value_record
->XAdvance
));
1838 if (value_format
& OTF_YAdvance
)
1839 ASET (val
, 3, make_number (value_record
->YAdvance
));
1840 if (value_format
& OTF_XPlaDevice
)
1841 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XPlaDevice
));
1842 if (value_format
& OTF_YPlaDevice
)
1843 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YPlaDevice
));
1844 if (value_format
& OTF_XAdvDevice
)
1845 ASET (val
, 4, font_otf_DeviceTable (&value_record
->XAdvDevice
));
1846 if (value_format
& OTF_YAdvDevice
)
1847 ASET (val
, 4, font_otf_DeviceTable (&value_record
->YAdvDevice
));
1852 font_otf_Anchor (anchor
)
1857 val
= Fmake_vector (make_number (anchor
->AnchorFormat
+ 1), Qnil
);
1858 ASET (val
, 0, make_number (anchor
->XCoordinate
));
1859 ASET (val
, 1, make_number (anchor
->YCoordinate
));
1860 if (anchor
->AnchorFormat
== 2)
1861 ASET (val
, 2, make_number (anchor
->f
.f1
.AnchorPoint
));
1864 ASET (val
, 3, font_otf_DeviceTable (&anchor
->f
.f2
.XDeviceTable
));
1865 ASET (val
, 4, font_otf_DeviceTable (&anchor
->f
.f2
.YDeviceTable
));
1870 #endif /* HAVE_LIBOTF */
1872 /* G-string (glyph string) handler */
1874 /* G-string is a vector of the form [HEADER GLYPH ...].
1875 See the docstring of `font-make-gstring' for more detail. */
1878 font_prepare_composition (cmp
, f
)
1879 struct composition
*cmp
;
1883 = AREF (XHASH_TABLE (composition_hash_table
)->key_and_value
,
1884 cmp
->hash_index
* 2);
1886 cmp
->font
= XSAVE_VALUE (LGSTRING_FONT (gstring
))->pointer
;
1887 cmp
->glyph_len
= LGSTRING_LENGTH (gstring
);
1888 cmp
->pixel_width
= LGSTRING_WIDTH (gstring
);
1889 cmp
->lbearing
= LGSTRING_LBEARING (gstring
);
1890 cmp
->rbearing
= LGSTRING_RBEARING (gstring
);
1891 cmp
->ascent
= LGSTRING_ASCENT (gstring
);
1892 cmp
->descent
= LGSTRING_DESCENT (gstring
);
1893 cmp
->width
= cmp
->pixel_width
/ FRAME_COLUMN_WIDTH (f
);
1894 if (cmp
->width
== 0)
1903 static unsigned font_score
P_ ((Lisp_Object
, Lisp_Object
*));
1904 static int font_compare
P_ ((const void *, const void *));
1905 static Lisp_Object font_sort_entites
P_ ((Lisp_Object
, Lisp_Object
,
1906 Lisp_Object
, Lisp_Object
));
1908 /* We sort fonts by scoring each of them against a specified
1909 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1910 the value is, the closer the font is to the font-spec.
1912 Each 1-bit of the highest 4 bits of the score is used for atomic
1913 properties FOUNDRY, FAMILY, ADSTYLE, and REGISTRY.
1915 Each 7-bit in the lowest 28 bits are used for numeric properties
1916 WEIGHT, SLANT, WIDTH, and SIZE. */
1918 /* How many bits to shift to store the difference value of each font
1919 property in a score. */
1920 static int sort_shift_bits
[FONT_SIZE_INDEX
+ 1];
1922 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1923 The return value indicates how different ENTITY is compared with
1927 font_score (entity
, spec_prop
)
1928 Lisp_Object entity
, *spec_prop
;
1932 /* Score four atomic fields. Maximum difference is 1. */
1933 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_REGISTRY_INDEX
; i
++)
1934 if (! NILP (spec_prop
[i
])
1935 && ! EQ (spec_prop
[i
], AREF (entity
, i
)))
1936 score
|= 1 << sort_shift_bits
[i
];
1938 /* Score four numeric fields. Maximum difference is 127. */
1939 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
1941 Lisp_Object entity_val
= AREF (entity
, i
);
1942 Lisp_Object spec_val
= spec_prop
[i
];
1944 /* If weight and slant are unspecified, score normal lower (low wins). */
1945 if (NILP (spec_val
))
1947 if (i
== FONT_WEIGHT_INDEX
|| i
== FONT_SLANT_INDEX
)
1948 spec_val
= prop_name_to_numeric (i
, build_string ("normal"));
1951 if (! NILP (spec_val
) && ! EQ (spec_val
, entity_val
))
1953 if (! INTEGERP (entity_val
))
1954 score
|= 127 << sort_shift_bits
[i
];
1957 int diff
= XINT (entity_val
) - XINT (spec_val
);
1961 if (i
== FONT_SIZE_INDEX
)
1963 if (XINT (entity_val
) > 0
1964 && diff
> FONT_PIXEL_SIZE_QUANTUM
)
1965 score
|= min (diff
, 127) << sort_shift_bits
[i
];
1968 else if (i
== FONT_WEIGHT_INDEX
)
1970 /* Windows uses a much wider range for weight (100-900)
1971 compared with freetype (0-210), so scale down the
1972 difference. A more general way of doing this
1973 would be to look up the values of regular and bold
1974 and/or light and calculate the scale factor from them,
1975 but the lookup would be expensive, and if only Windows
1976 needs it, not worth the effort. */
1977 score
|= min (diff
/ 4, 127) << sort_shift_bits
[i
];
1981 score
|= min (diff
, 127) << sort_shift_bits
[i
];
1990 /* The comparison function for qsort. */
1993 font_compare (d1
, d2
)
1994 const void *d1
, *d2
;
1996 return (*(unsigned *) d1
< *(unsigned *) d2
1997 ? -1 : *(unsigned *) d1
> *(unsigned *) d2
);
2001 /* The structure for elements being sorted by qsort. */
2002 struct font_sort_data
2009 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
2010 If PREFER specifies a point-size, calculate the corresponding
2011 pixel-size from QCdpi property of PREFER or from the Y-resolution
2012 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
2013 get the font-entities in VEC. */
2016 font_sort_entites (vec
, prefer
, frame
, spec
)
2017 Lisp_Object vec
, prefer
, frame
, spec
;
2019 Lisp_Object prefer_prop
[FONT_SPEC_MAX
];
2021 struct font_sort_data
*data
;
2028 for (i
= FONT_FOUNDRY_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
2029 prefer_prop
[i
] = AREF (prefer
, i
);
2033 /* As it is assured that all fonts in VEC match with SPEC, we
2034 should ignore properties specified in SPEC. So, set the
2035 corresponding properties in PREFER_PROP to nil. */
2036 for (i
= FONT_WEIGHT_INDEX
; i
<= FONT_SIZE_INDEX
; i
++)
2037 if (! NILP (AREF (spec
, i
)))
2038 prefer_prop
[i
++] = Qnil
;
2041 if (FLOATP (prefer_prop
[FONT_SIZE_INDEX
]))
2042 prefer_prop
[FONT_SIZE_INDEX
]
2043 = make_number (font_pixel_size (XFRAME (frame
), prefer
));
2045 /* Scoring and sorting. */
2046 SAFE_ALLOCA (data
, struct font_sort_data
*, (sizeof *data
) * len
);
2047 for (i
= 0; i
< len
; i
++)
2049 data
[i
].entity
= AREF (vec
, i
);
2050 data
[i
].score
= font_score (data
[i
].entity
, prefer_prop
);
2052 qsort (data
, len
, sizeof *data
, font_compare
);
2053 for (i
= 0; i
< len
; i
++)
2054 ASET (vec
, i
, data
[i
].entity
);
2061 /* API of Font Service Layer. */
2063 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2064 sort_shift_bits. Finternal_set_font_selection_order calls this
2065 function with font_sort_order after setting up it. */
2068 font_update_sort_order (order
)
2071 int i
, shift_bits
= 21;
2073 for (i
= 0; i
< 4; i
++, shift_bits
-= 7)
2075 int xlfd_idx
= order
[i
];
2077 if (xlfd_idx
== XLFD_WEIGHT_INDEX
)
2078 sort_shift_bits
[FONT_WEIGHT_INDEX
] = shift_bits
;
2079 else if (xlfd_idx
== XLFD_SLANT_INDEX
)
2080 sort_shift_bits
[FONT_SLANT_INDEX
] = shift_bits
;
2081 else if (xlfd_idx
== XLFD_SWIDTH_INDEX
)
2082 sort_shift_bits
[FONT_WIDTH_INDEX
] = shift_bits
;
2084 sort_shift_bits
[FONT_SIZE_INDEX
] = shift_bits
;
2089 /* Return weight property of FONT as symbol. */
2092 font_symbolic_weight (font
)
2095 Lisp_Object weight
= AREF (font
, FONT_WEIGHT_INDEX
);
2097 if (INTEGERP (weight
))
2098 weight
= prop_numeric_to_name (FONT_WEIGHT_INDEX
, XINT (weight
));
2103 /* Return slant property of FONT as symbol. */
2106 font_symbolic_slant (font
)
2109 Lisp_Object slant
= AREF (font
, FONT_SLANT_INDEX
);
2111 if (INTEGERP (slant
))
2112 slant
= prop_numeric_to_name (FONT_SLANT_INDEX
, XINT (slant
));
2117 /* Return width property of FONT as symbol. */
2120 font_symbolic_width (font
)
2123 Lisp_Object width
= AREF (font
, FONT_WIDTH_INDEX
);
2125 if (INTEGERP (width
))
2126 width
= prop_numeric_to_name (FONT_WIDTH_INDEX
, XINT (width
));
2131 /* Check if ENTITY matches with the font specification SPEC. */
2134 font_match_p (spec
, entity
)
2135 Lisp_Object spec
, entity
;
2139 for (i
= FONT_FOUNDRY_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2140 if (! NILP (AREF (spec
, i
))
2141 && ! EQ (AREF (spec
, i
), AREF (entity
, i
)))
2143 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
))
2144 && XINT (AREF (entity
, FONT_SIZE_INDEX
)) > 0
2145 && (XINT (AREF (spec
, FONT_SIZE_INDEX
))
2146 != XINT (AREF (entity
, FONT_SIZE_INDEX
))))
2152 /* Return a lispy font object corresponding to FONT. */
2155 font_find_object (font
)
2158 Lisp_Object tail
, elt
;
2160 for (tail
= AREF (font
->entity
, FONT_OBJLIST_INDEX
); CONSP (tail
);
2164 if (font
== XSAVE_VALUE (elt
)->pointer
2165 && XSAVE_VALUE (elt
)->integer
> 0)
2175 Each font backend has the callback function get_cache, and it
2176 returns a cons cell of which cdr part can be freely used for
2177 caching fonts. The cons cell may be shared by multiple frames
2178 and/or multiple font drivers. So, we arrange the cdr part as this:
2180 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2182 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2183 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2184 cons (FONT-SPEC FONT-ENTITY ...). */
2186 static void font_prepare_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2187 static void font_finish_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2188 static Lisp_Object font_get_cache
P_ ((FRAME_PTR
, struct font_driver
*));
2189 static void font_clear_cache
P_ ((FRAME_PTR
, Lisp_Object
,
2190 struct font_driver
*));
2193 font_prepare_cache (f
, driver
)
2195 struct font_driver
*driver
;
2197 Lisp_Object cache
, val
;
2199 cache
= driver
->get_cache (f
);
2201 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2205 val
= Fcons (driver
->type
, Fcons (make_number (1), Qnil
));
2206 XSETCDR (cache
, Fcons (val
, XCDR (cache
)));
2210 val
= XCDR (XCAR (val
));
2211 XSETCAR (val
, make_number (XINT (XCAR (val
)) + 1));
2217 font_finish_cache (f
, driver
)
2219 struct font_driver
*driver
;
2221 Lisp_Object cache
, val
, tmp
;
2224 cache
= driver
->get_cache (f
);
2226 while (CONSP (val
) && ! EQ (XCAR (XCAR (val
)), driver
->type
))
2227 cache
= val
, val
= XCDR (val
);
2228 xassert (! NILP (val
));
2229 tmp
= XCDR (XCAR (val
));
2230 XSETCAR (tmp
, make_number (XINT (XCAR (tmp
)) - 1));
2231 if (XINT (XCAR (tmp
)) == 0)
2233 font_clear_cache (f
, XCAR (val
), driver
);
2234 XSETCDR (cache
, XCDR (val
));
2240 font_get_cache (f
, driver
)
2242 struct font_driver
*driver
;
2244 Lisp_Object val
= driver
->get_cache (f
);
2245 Lisp_Object type
= driver
->type
;
2247 xassert (CONSP (val
));
2248 for (val
= XCDR (val
); ! EQ (XCAR (XCAR (val
)), type
); val
= XCDR (val
));
2249 xassert (CONSP (val
));
2250 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2251 val
= XCDR (XCAR (val
));
2255 static int num_fonts
;
2258 font_clear_cache (f
, cache
, driver
)
2261 struct font_driver
*driver
;
2263 Lisp_Object tail
, elt
;
2265 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2266 for (tail
= XCDR (XCDR (cache
)); CONSP (tail
); tail
= XCDR (tail
))
2269 if (CONSP (elt
) && FONT_SPEC_P (XCAR (elt
)))
2271 Lisp_Object vec
= XCDR (elt
);
2274 for (i
= 0; i
< ASIZE (vec
); i
++)
2276 Lisp_Object entity
= AREF (vec
, i
);
2278 if (EQ (driver
->type
, AREF (entity
, FONT_TYPE_INDEX
)))
2280 Lisp_Object objlist
= AREF (entity
, FONT_OBJLIST_INDEX
);
2282 for (; CONSP (objlist
); objlist
= XCDR (objlist
))
2284 Lisp_Object val
= XCAR (objlist
);
2285 struct Lisp_Save_Value
*p
= XSAVE_VALUE (val
);
2286 struct font
*font
= p
->pointer
;
2288 xassert (font
&& driver
== font
->driver
);
2289 driver
->close (f
, font
);
2294 if (driver
->free_entity
)
2295 driver
->free_entity (entity
);
2300 XSETCDR (cache
, Qnil
);
2304 static Lisp_Object scratch_font_spec
, scratch_font_prefer
;
2307 /* Return a vector of font-entities matching with SPEC on frame F. */
2310 font_list_entities (frame
, spec
)
2311 Lisp_Object frame
, spec
;
2313 FRAME_PTR f
= XFRAME (frame
);
2314 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2315 Lisp_Object ftype
, family
, size
, alternate_familes
;
2316 Lisp_Object
*vec
= alloca (sizeof (Lisp_Object
) * num_font_drivers
);
2322 family
= AREF (spec
, FONT_FAMILY_INDEX
);
2324 alternate_familes
= Qnil
;
2327 if (NILP (font_family_alist
)
2328 && !NILP (Vface_alternative_font_family_alist
))
2329 build_font_family_alist ();
2330 alternate_familes
= assq_no_quit (family
, font_family_alist
);
2331 if (! NILP (alternate_familes
))
2332 alternate_familes
= XCDR (alternate_familes
);
2334 size
= AREF (spec
, FONT_SIZE_INDEX
);
2336 ASET (spec
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2338 xassert (ASIZE (spec
) == FONT_SPEC_MAX
);
2339 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2341 for (i
= 0; driver_list
; driver_list
= driver_list
->next
)
2343 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2345 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2346 Lisp_Object tail
= alternate_familes
;
2348 ASET (spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2349 ASET (spec
, FONT_FAMILY_INDEX
, family
);
2353 Lisp_Object val
= assoc_no_quit (spec
, XCDR (cache
));
2359 val
= driver_list
->driver
->list (frame
, spec
);
2361 XSETCDR (cache
, Fcons (Fcons (Fcopy_sequence (spec
), val
),
2364 if (VECTORP (val
) && ASIZE (val
) > 0)
2371 ASET (spec
, FONT_FAMILY_INDEX
, XCAR (tail
));
2375 ASET (spec
, FONT_TYPE_INDEX
, ftype
);
2376 ASET (spec
, FONT_FAMILY_INDEX
, family
);
2377 ASET (spec
, FONT_SIZE_INDEX
, size
);
2378 return (i
> 0 ? Fvconcat (i
, vec
) : null_vector
);
2382 /* Return a font entity matching with SPEC on FRAME. */
2385 font_matching_entity (frame
, spec
)
2386 Lisp_Object frame
, spec
;
2388 FRAME_PTR f
= XFRAME (frame
);
2389 struct font_driver_list
*driver_list
= f
->font_driver_list
;
2390 Lisp_Object ftype
, size
, entity
;
2392 ftype
= AREF (spec
, FONT_TYPE_INDEX
);
2393 size
= AREF (spec
, FONT_SIZE_INDEX
);
2395 ASET (spec
, FONT_SIZE_INDEX
, make_number (font_pixel_size (f
, spec
)));
2397 for (; driver_list
; driver_list
= driver_list
->next
)
2399 && (NILP (ftype
) || EQ (driver_list
->driver
->type
, ftype
)))
2401 Lisp_Object cache
= font_get_cache (f
, driver_list
->driver
);
2404 ASET (spec
, FONT_TYPE_INDEX
, driver_list
->driver
->type
);
2405 key
= Fcons (spec
, Qnil
);
2406 entity
= assoc_no_quit (key
, XCDR (cache
));
2408 entity
= XCDR (entity
);
2411 entity
= driver_list
->driver
->match (frame
, spec
);
2412 if (! NILP (entity
))
2414 XSETCAR (key
, Fcopy_sequence (spec
));
2415 XSETCDR (cache
, Fcons (Fcons (key
, entity
), XCDR (cache
)));
2418 if (! NILP (entity
))
2421 ASET (spec
, FONT_TYPE_INDEX
, ftype
);
2422 ASET (spec
, FONT_SIZE_INDEX
, size
);
2427 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2428 opened font object. */
2431 font_open_entity (f
, entity
, pixel_size
)
2436 struct font_driver_list
*driver_list
;
2437 Lisp_Object objlist
, size
, val
, font_object
;
2440 size
= AREF (entity
, FONT_SIZE_INDEX
);
2441 xassert (NATNUMP (size
));
2442 if (XINT (size
) != 0)
2443 pixel_size
= XINT (size
);
2446 for (objlist
= AREF (entity
, FONT_OBJLIST_INDEX
); CONSP (objlist
);
2447 objlist
= XCDR (objlist
))
2449 font
= XSAVE_VALUE (XCAR (objlist
))->pointer
;
2450 if (font
->pixel_size
== pixel_size
)
2452 font_object
= XCAR (objlist
);
2453 XSAVE_VALUE (font_object
)->integer
++;
2458 if (NILP (font_object
))
2460 val
= AREF (entity
, FONT_TYPE_INDEX
);
2461 for (driver_list
= f
->font_driver_list
;
2462 driver_list
&& ! EQ (driver_list
->driver
->type
, val
);
2463 driver_list
= driver_list
->next
);
2467 font
= driver_list
->driver
->open (f
, entity
, pixel_size
);
2470 font
->scalable
= XINT (size
) == 0;
2472 font_object
= make_save_value (font
, 1);
2473 ASET (entity
, FONT_OBJLIST_INDEX
,
2474 Fcons (font_object
, AREF (entity
, FONT_OBJLIST_INDEX
)));
2478 if (FRAME_SMALLEST_CHAR_WIDTH (f
) > font
->min_width
)
2479 FRAME_SMALLEST_CHAR_WIDTH (f
) = font
->min_width
;
2480 if (FRAME_SMALLEST_CHAR_WIDTH (f
) <= 0)
2481 FRAME_SMALLEST_CHAR_WIDTH (f
) = 1;
2482 if (FRAME_SMALLEST_FONT_HEIGHT (f
) > font
->font
.height
)
2483 FRAME_SMALLEST_FONT_HEIGHT (f
) = font
->font
.height
;
2484 if (FRAME_SMALLEST_FONT_HEIGHT (f
) <= 0)
2485 FRAME_SMALLEST_FONT_HEIGHT (f
) = 1;
2491 /* Close FONT_OBJECT that is opened on frame F. */
2494 font_close_object (f
, font_object
)
2496 Lisp_Object font_object
;
2498 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2499 Lisp_Object objlist
;
2500 Lisp_Object tail
, prev
= Qnil
;
2502 xassert (XSAVE_VALUE (font_object
)->integer
> 0);
2503 XSAVE_VALUE (font_object
)->integer
--;
2504 if (XSAVE_VALUE (font_object
)->integer
> 0)
2507 objlist
= AREF (font
->entity
, FONT_OBJLIST_INDEX
);
2508 for (prev
= Qnil
, tail
= objlist
; CONSP (tail
);
2509 prev
= tail
, tail
= XCDR (tail
))
2510 if (EQ (font_object
, XCAR (tail
)))
2512 if (font
->driver
->close
)
2513 font
->driver
->close (f
, font
);
2514 XSAVE_VALUE (font_object
)->pointer
= NULL
;
2516 ASET (font
->entity
, FONT_OBJLIST_INDEX
, XCDR (objlist
));
2518 XSETCDR (prev
, XCDR (objlist
));
2526 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2527 FONT is a font-entity and it must be opened to check. */
2530 font_has_char (f
, font
, c
)
2537 if (FONT_ENTITY_P (font
))
2539 Lisp_Object type
= AREF (font
, FONT_TYPE_INDEX
);
2540 struct font_driver_list
*driver_list
;
2542 for (driver_list
= f
->font_driver_list
;
2543 driver_list
&& ! EQ (driver_list
->driver
->type
, type
);
2544 driver_list
= driver_list
->next
);
2547 if (! driver_list
->driver
->has_char
)
2549 return driver_list
->driver
->has_char (font
, c
);
2552 xassert (FONT_OBJECT_P (font
));
2553 fontp
= XSAVE_VALUE (font
)->pointer
;
2555 if (fontp
->driver
->has_char
)
2557 int result
= fontp
->driver
->has_char (fontp
->entity
, c
);
2562 return (fontp
->driver
->encode_char (fontp
, c
) != FONT_INVALID_CODE
);
2566 /* Return the glyph ID of FONT_OBJECT for character C. */
2569 font_encode_char (font_object
, c
)
2570 Lisp_Object font_object
;
2573 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2575 return font
->driver
->encode_char (font
, c
);
2579 /* Return the name of FONT_OBJECT. */
2582 font_get_name (font_object
)
2583 Lisp_Object font_object
;
2585 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2586 char *name
= (font
->font
.full_name
? font
->font
.full_name
2587 : font
->font
.name
? font
->font
.name
2590 return (name
? make_unibyte_string (name
, strlen (name
)) : null_string
);
2594 /* Return the specification of FONT_OBJECT. */
2597 font_get_spec (font_object
)
2598 Lisp_Object font_object
;
2600 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2601 Lisp_Object spec
= Ffont_spec (0, NULL
);
2604 for (i
= 0; i
< FONT_SIZE_INDEX
; i
++)
2605 ASET (spec
, i
, AREF (font
->entity
, i
));
2606 ASET (spec
, FONT_SIZE_INDEX
, make_number (font
->pixel_size
));
2611 /* Return the frame on which FONT exists. FONT is a font object or a
2615 font_get_frame (font
)
2618 if (FONT_OBJECT_P (font
))
2619 font
= ((struct font
*) XSAVE_VALUE (font
)->pointer
)->entity
;
2620 xassert (FONT_ENTITY_P (font
));
2621 return AREF (font
, FONT_FRAME_INDEX
);
2625 /* Find a font entity best matching with LFACE. If SPEC is non-nil,
2626 the font must exactly match with it. C, if not negative, is a
2627 character that the entity must support. */
2630 font_find_for_lface (f
, lface
, spec
, c
)
2636 Lisp_Object frame
, entities
, val
;
2639 XSETFRAME (frame
, f
);
2645 for (i
= 0; i
< FONT_SPEC_MAX
; i
++)
2646 ASET (scratch_font_spec
, i
, Qnil
);
2647 ASET (scratch_font_spec
, FONT_REGISTRY_INDEX
, Qiso8859_1
);
2649 if (! NILP (lface
[LFACE_FAMILY_INDEX
]))
2650 font_merge_old_spec (Qnil
, lface
[LFACE_FAMILY_INDEX
], Qnil
,
2652 entities
= font_list_entities (frame
, scratch_font_spec
);
2653 while (ASIZE (entities
) == 0)
2655 /* Try without FOUNDRY or FAMILY. */
2656 if (! NILP (AREF (scratch_font_spec
, FONT_FOUNDRY_INDEX
)))
2658 ASET (scratch_font_spec
, FONT_FOUNDRY_INDEX
, Qnil
);
2659 entities
= font_list_entities (frame
, scratch_font_spec
);
2661 else if (! NILP (AREF (scratch_font_spec
, FONT_FAMILY_INDEX
)))
2663 ASET (scratch_font_spec
, FONT_FAMILY_INDEX
, Qnil
);
2664 entities
= font_list_entities (frame
, scratch_font_spec
);
2672 Lisp_Object registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
2674 if (NILP (registry
))
2675 registry
= Qiso8859_1
;
2679 struct charset
*encoding
, *repertory
;
2681 if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
2685 if (ENCODE_CHAR (repertory
, c
)
2686 == CHARSET_INVALID_CODE (repertory
))
2688 /* Any font of this registry support C. So, let's
2689 suppress the further checking. */
2692 else if (c
> encoding
->max_char
)
2695 for (i
= 0; i
< FONT_SPEC_MAX
; i
++)
2696 ASET (scratch_font_spec
, i
, AREF (spec
, i
));
2697 ASET (scratch_font_spec
, FONT_REGISTRY_INDEX
, registry
);
2698 entities
= font_list_entities (frame
, scratch_font_spec
);
2701 if (ASIZE (entities
) == 0)
2703 if (ASIZE (entities
) > 1)
2705 /* Sort fonts by properties specified in LFACE. */
2706 Lisp_Object prefer
= scratch_font_prefer
;
2709 if (! NILP (lface
[LFACE_FAMILY_INDEX
]))
2710 font_merge_old_spec (Qnil
, lface
[LFACE_FAMILY_INDEX
], Qnil
, prefer
);
2711 ASET (prefer
, FONT_WEIGHT_INDEX
,
2712 font_prop_validate_style (QCweight
, lface
[LFACE_WEIGHT_INDEX
]));
2713 ASET (prefer
, FONT_SLANT_INDEX
,
2714 font_prop_validate_style (QCslant
, lface
[LFACE_SLANT_INDEX
]));
2715 ASET (prefer
, FONT_WIDTH_INDEX
,
2716 font_prop_validate_style (QCwidth
, lface
[LFACE_SWIDTH_INDEX
]));
2717 pt
= XINT (lface
[LFACE_HEIGHT_INDEX
]);
2718 ASET (prefer
, FONT_SIZE_INDEX
, make_float (pt
/ 10));
2720 font_sort_entites (entities
, prefer
, frame
, spec
);
2724 return AREF (entities
, 0);
2726 val
= AREF (entities
, 0);
2727 result
= font_has_char (f
, val
, c
);
2732 val
= font_open_for_lface (f
, val
, lface
, spec
);
2735 result
= font_has_char (f
, val
, c
);
2736 font_close_object (f
, val
);
2744 font_open_for_lface (f
, entity
, lface
, spec
)
2752 if (FONT_SPEC_P (spec
) && INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
2753 size
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
2756 double pt
= XINT (lface
[LFACE_HEIGHT_INDEX
]);
2759 size
= POINT_TO_PIXEL (pt
, f
->resy
);
2761 return font_open_entity (f
, entity
, size
);
2765 /* Load a font best matching with FACE's font-related properties into
2766 FACE on frame F. If no proper font is found, record that FACE has
2770 font_load_for_face (f
, face
)
2774 Lisp_Object font_object
= face
->lface
[LFACE_FONT_INDEX
];
2776 if (NILP (font_object
))
2778 Lisp_Object entity
= font_find_for_lface (f
, face
->lface
, Qnil
, -1);
2780 if (! NILP (entity
))
2781 font_object
= font_open_for_lface (f
, entity
, face
->lface
, Qnil
);
2783 else if (STRINGP (font_object
))
2785 font_object
= font_open_by_name (f
, SDATA (font_object
));
2788 if (! NILP (font_object
))
2790 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
2792 face
->font
= font
->font
.font
;
2793 face
->font_info
= (struct font_info
*) font
;
2794 face
->font_info_id
= 0;
2795 face
->font_name
= font
->font
.full_name
;
2800 face
->font_info
= NULL
;
2801 face
->font_info_id
= -1;
2802 face
->font_name
= NULL
;
2803 add_to_log ("Unable to load font for a face%s", null_string
, Qnil
);
2808 /* Make FACE on frame F ready to use the font opened for FACE. */
2811 font_prepare_for_face (f
, face
)
2815 struct font
*font
= (struct font
*) face
->font_info
;
2817 if (font
->driver
->prepare_face
)
2818 font
->driver
->prepare_face (f
, face
);
2822 /* Make FACE on frame F stop using the font opened for FACE. */
2825 font_done_for_face (f
, face
)
2829 struct font
*font
= (struct font
*) face
->font_info
;
2831 if (font
->driver
->done_face
)
2832 font
->driver
->done_face (f
, face
);
2837 /* Open a font best matching with NAME on frame F. If no proper font
2838 is found, return Qnil. */
2841 font_open_by_name (f
, name
)
2845 Lisp_Object args
[2];
2846 Lisp_Object spec
, prefer
, size
, entity
, entity_list
;
2851 XSETFRAME (frame
, f
);
2854 args
[1] = make_unibyte_string (name
, strlen (name
));
2855 spec
= Ffont_spec (2, args
);
2856 prefer
= scratch_font_prefer
;
2857 for (i
= FONT_WEIGHT_INDEX
; i
< FONT_SIZE_INDEX
; i
++)
2858 if (NILP (AREF (spec
, i
)))
2859 ASET (prefer
, i
, make_number (100));
2860 size
= AREF (spec
, FONT_SIZE_INDEX
);
2863 else if (INTEGERP (size
))
2864 pixel_size
= XINT (size
);
2865 else /* FLOATP (size) */
2867 double pt
= XFLOAT_DATA (size
);
2869 pixel_size
= POINT_TO_PIXEL (pt
, f
->resy
);
2870 size
= make_number (pixel_size
);
2871 ASET (spec
, FONT_SIZE_INDEX
, size
);
2873 if (pixel_size
== 0)
2875 pixel_size
= POINT_TO_PIXEL (12.0, f
->resy
);
2876 size
= make_number (pixel_size
);
2878 ASET (prefer
, FONT_SIZE_INDEX
, size
);
2879 if (NILP (AREF (spec
, FONT_REGISTRY_INDEX
)))
2880 ASET (spec
, FONT_REGISTRY_INDEX
, Qiso8859_1
);
2882 entity_list
= Flist_fonts (spec
, frame
, make_number (1), prefer
);
2883 if (NILP (entity_list
))
2884 entity
= font_matching_entity (frame
, spec
);
2886 entity
= XCAR (entity_list
);
2887 return (NILP (entity
)
2889 : font_open_entity (f
, entity
, pixel_size
));
2893 /* Register font-driver DRIVER. This function is used in two ways.
2895 The first is with frame F non-NULL. In this case, make DRIVER
2896 available (but not yet activated) on F. All frame creaters
2897 (e.g. Fx_create_frame) must call this function at least once with
2898 an available font-driver.
2900 The second is with frame F NULL. In this case, DRIVER is globally
2901 registered in the variable `font_driver_list'. All font-driver
2902 implementations must call this function in its syms_of_XXXX
2903 (e.g. syms_of_xfont). */
2906 register_font_driver (driver
, f
)
2907 struct font_driver
*driver
;
2910 struct font_driver_list
*root
= f
? f
->font_driver_list
: font_driver_list
;
2911 struct font_driver_list
*prev
, *list
;
2913 if (f
&& ! driver
->draw
)
2914 error ("Unsable font driver for a frame: %s",
2915 SDATA (SYMBOL_NAME (driver
->type
)));
2917 for (prev
= NULL
, list
= root
; list
; prev
= list
, list
= list
->next
)
2918 if (EQ (list
->driver
->type
, driver
->type
))
2919 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver
->type
)));
2921 list
= malloc (sizeof (struct font_driver_list
));
2923 list
->driver
= driver
;
2928 f
->font_driver_list
= list
;
2930 font_driver_list
= list
;
2935 /* Free font-driver list on frame F. It doesn't free font-drivers
2939 free_font_driver_list (f
)
2942 while (f
->font_driver_list
)
2944 struct font_driver_list
*next
= f
->font_driver_list
->next
;
2946 free (f
->font_driver_list
);
2947 f
->font_driver_list
= next
;
2952 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
2953 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
2954 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
2956 A caller must free all realized faces if any in advance. The
2957 return value is a list of font backends actually made used on
2961 font_update_drivers (f
, new_drivers
)
2963 Lisp_Object new_drivers
;
2965 Lisp_Object active_drivers
= Qnil
;
2966 struct font_driver_list
*list
;
2968 for (list
= f
->font_driver_list
; list
; list
= list
->next
)
2971 if (! EQ (new_drivers
, Qt
)
2972 && NILP (Fmemq (list
->driver
->type
, new_drivers
)))
2974 if (list
->driver
->end_for_frame
)
2975 list
->driver
->end_for_frame (f
);
2976 font_finish_cache (f
, list
->driver
);
2982 if (EQ (new_drivers
, Qt
)
2983 || ! NILP (Fmemq (list
->driver
->type
, new_drivers
)))
2985 if (! list
->driver
->start_for_frame
2986 || list
->driver
->start_for_frame (f
) == 0)
2988 font_prepare_cache (f
, list
->driver
);
2990 active_drivers
= nconc2 (active_drivers
,
2991 Fcons (list
->driver
->type
, Qnil
));
2996 return active_drivers
;
3000 font_put_frame_data (f
, driver
, data
)
3002 struct font_driver
*driver
;
3005 struct font_data_list
*list
, *prev
;
3007 for (prev
= NULL
, list
= f
->font_data_list
; list
;
3008 prev
= list
, list
= list
->next
)
3009 if (list
->driver
== driver
)
3016 prev
->next
= list
->next
;
3018 f
->font_data_list
= list
->next
;
3026 list
= malloc (sizeof (struct font_data_list
));
3029 list
->driver
= driver
;
3030 list
->next
= f
->font_data_list
;
3031 f
->font_data_list
= list
;
3039 font_get_frame_data (f
, driver
)
3041 struct font_driver
*driver
;
3043 struct font_data_list
*list
;
3045 for (list
= f
->font_data_list
; list
; list
= list
->next
)
3046 if (list
->driver
== driver
)
3054 /* Return the font used to draw character C by FACE at buffer position
3055 POS in window W. If STRING is non-nil, it is a string containing C
3056 at index POS. If C is negative, get C from the current buffer or
3060 font_at (c
, pos
, face
, w
, string
)
3074 multibyte
= ! NILP (current_buffer
->enable_multibyte_characters
);
3077 EMACS_INT pos_byte
= CHAR_TO_BYTE (pos
);
3079 c
= FETCH_CHAR (pos_byte
);
3082 c
= FETCH_BYTE (pos
);
3088 multibyte
= STRING_MULTIBYTE (string
);
3091 EMACS_INT pos_byte
= string_char_to_byte (string
, pos
);
3093 str
= SDATA (string
) + pos_byte
;
3094 c
= STRING_CHAR (str
, 0);
3097 c
= SDATA (string
)[pos
];
3101 f
= XFRAME (w
->frame
);
3102 if (! FRAME_WINDOW_P (f
))
3109 if (STRINGP (string
))
3110 face_id
= face_at_string_position (w
, string
, pos
, 0, -1, -1, &endptr
,
3111 DEFAULT_FACE_ID
, 0);
3113 face_id
= face_at_buffer_position (w
, pos
, -1, -1, &endptr
,
3115 face
= FACE_FROM_ID (f
, face_id
);
3119 int face_id
= FACE_FOR_CHAR (f
, face
, c
, pos
, string
);
3120 face
= FACE_FROM_ID (f
, face_id
);
3122 if (! face
->font_info
)
3124 return font_find_object ((struct font
*) face
->font_info
);
3130 DEFUN ("fontp", Ffontp
, Sfontp
, 1, 1, 0,
3131 doc
: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3132 Return nil otherwise. */)
3136 return (FONTP (object
) ? Qt
: Qnil
);
3139 DEFUN ("font-spec", Ffont_spec
, Sfont_spec
, 0, MANY
, 0,
3140 doc
: /* Return a newly created font-spec with arguments as properties.
3142 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3143 valid font property name listed below:
3145 `:family', `:weight', `:slant', `:width'
3147 They are the same as face attributes of the same name. See
3148 `set-face-attribute.
3152 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3156 VALUE must be a string or a symbol specifying the additional
3157 typographic style information of a font, e.g. ``sans''. Usually null.
3161 VALUE must be a string or a symbol specifying the charset registry and
3162 encoding of a font, e.g. ``iso8859-1''.
3166 VALUE must be a non-negative integer or a floating point number
3167 specifying the font size. It specifies the font size in 1/10 pixels
3168 (if VALUE is an integer), or in points (if VALUE is a float).
3169 usage: (font-spec ARGS ...) */)
3174 Lisp_Object spec
= Fmake_vector (make_number (FONT_SPEC_MAX
), Qnil
);
3177 for (i
= 0; i
< nargs
; i
+= 2)
3179 enum font_property_index prop
;
3180 Lisp_Object key
= args
[i
], val
= args
[i
+ 1];
3182 prop
= get_font_prop_index (key
, 0);
3183 if (prop
< FONT_EXTRA_INDEX
)
3184 ASET (spec
, prop
, val
);
3187 if (EQ (key
, QCname
))
3190 font_parse_name ((char *) SDATA (val
), spec
);
3192 font_put_extra (spec
, key
, val
);
3195 CHECK_VALIDATE_FONT_SPEC (spec
);
3200 DEFUN ("font-get", Ffont_get
, Sfont_get
, 2, 2, 0,
3201 doc
: /* Return the value of FONT's property KEY.
3202 FONT is a font-spec, a font-entity, or a font-object. */)
3204 Lisp_Object font
, key
;
3206 enum font_property_index idx
;
3208 if (FONT_OBJECT_P (font
))
3210 struct font
*fontp
= XSAVE_VALUE (font
)->pointer
;
3212 if (EQ (key
, QCotf
))
3214 if (fontp
->driver
->otf_capability
)
3215 return fontp
->driver
->otf_capability (fontp
);
3219 font
= fontp
->entity
;
3223 idx
= get_font_prop_index (key
, 0);
3224 if (idx
< FONT_EXTRA_INDEX
)
3225 return AREF (font
, idx
);
3226 if (FONT_ENTITY_P (font
))
3228 return Fcdr (Fassoc (key
, AREF (font
, FONT_EXTRA_INDEX
)));
3232 DEFUN ("font-put", Ffont_put
, Sfont_put
, 3, 3, 0,
3233 doc
: /* Set one property of FONT-SPEC: give property KEY value VALUE. */)
3234 (font_spec
, prop
, val
)
3235 Lisp_Object font_spec
, prop
, val
;
3237 enum font_property_index idx
;
3238 Lisp_Object extra
, slot
;
3240 CHECK_FONT_SPEC (font_spec
);
3241 idx
= get_font_prop_index (prop
, 0);
3242 if (idx
< FONT_EXTRA_INDEX
)
3243 return ASET (font_spec
, idx
, val
);
3244 extra
= AREF (font_spec
, FONT_EXTRA_INDEX
);
3245 slot
= Fassoc (extra
, prop
);
3247 extra
= Fcons (Fcons (prop
, val
), extra
);
3249 Fsetcdr (slot
, val
);
3253 DEFUN ("list-fonts", Flist_fonts
, Slist_fonts
, 1, 4, 0,
3254 doc
: /* List available fonts matching FONT-SPEC on the current frame.
3255 Optional 2nd argument FRAME specifies the target frame.
3256 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
3257 Optional 4th argument PREFER, if non-nil, is a font-spec to
3258 control the order of the returned list. Fonts are sorted by
3259 how they are close to PREFER. */)
3260 (font_spec
, frame
, num
, prefer
)
3261 Lisp_Object font_spec
, frame
, num
, prefer
;
3263 Lisp_Object vec
, list
, tail
;
3267 frame
= selected_frame
;
3268 CHECK_LIVE_FRAME (frame
);
3269 CHECK_VALIDATE_FONT_SPEC (font_spec
);
3277 if (! NILP (prefer
))
3278 CHECK_FONT (prefer
);
3280 vec
= font_list_entities (frame
, font_spec
);
3285 return Fcons (AREF (vec
, 0), Qnil
);
3287 if (! NILP (prefer
))
3288 vec
= font_sort_entites (vec
, prefer
, frame
, font_spec
);
3290 list
= tail
= Fcons (AREF (vec
, 0), Qnil
);
3291 if (n
== 0 || n
> len
)
3293 for (i
= 1; i
< n
; i
++)
3295 Lisp_Object val
= Fcons (AREF (vec
, i
), Qnil
);
3297 XSETCDR (tail
, val
);
3303 DEFUN ("list-families", Flist_families
, Slist_families
, 0, 1, 0,
3304 doc
: /* List available font families on the current frame.
3305 Optional 2nd argument FRAME specifies the target frame. */)
3310 struct font_driver_list
*driver_list
;
3314 frame
= selected_frame
;
3315 CHECK_LIVE_FRAME (frame
);
3318 for (driver_list
= f
->font_driver_list
; driver_list
;
3319 driver_list
= driver_list
->next
)
3320 if (driver_list
->driver
->list_family
)
3322 Lisp_Object val
= driver_list
->driver
->list_family (frame
);
3328 Lisp_Object tail
= list
;
3330 for (; CONSP (val
); val
= XCDR (val
))
3331 if (NILP (Fmemq (XCAR (val
), tail
)))
3332 list
= Fcons (XCAR (val
), list
);
3338 DEFUN ("find-font", Ffind_font
, Sfind_font
, 1, 2, 0,
3339 doc
: /* Return a font-entity matching with FONT-SPEC on the current frame.
3340 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
3342 Lisp_Object font_spec
, frame
;
3344 Lisp_Object val
= Flist_fonts (font_spec
, frame
, make_number (1), Qnil
);
3351 DEFUN ("font-xlfd-name", Ffont_xlfd_name
, Sfont_xlfd_name
, 1, 1, 0,
3352 doc
: /* Return XLFD name of FONT.
3353 FONT is a font-spec, font-entity, or font-object.
3354 If the name is too long for XLFD (maximum 255 chars), return nil. */)
3361 if (FONT_SPEC_P (font
))
3362 CHECK_VALIDATE_FONT_SPEC (font
);
3363 else if (FONT_ENTITY_P (font
))
3369 CHECK_FONT_GET_OBJECT (font
, fontp
);
3370 font
= fontp
->entity
;
3371 pixel_size
= fontp
->pixel_size
;
3374 if (font_unparse_xlfd (font
, pixel_size
, name
, 256) < 0)
3376 return build_string (name
);
3379 DEFUN ("clear-font-cache", Fclear_font_cache
, Sclear_font_cache
, 0, 0, 0,
3380 doc
: /* Clear font cache. */)
3383 Lisp_Object list
, frame
;
3385 FOR_EACH_FRAME (list
, frame
)
3387 FRAME_PTR f
= XFRAME (frame
);
3388 struct font_driver_list
*driver_list
= f
->font_driver_list
;
3390 for (; driver_list
; driver_list
= driver_list
->next
)
3391 if (driver_list
->on
)
3393 Lisp_Object cache
= driver_list
->driver
->get_cache (f
);
3398 && ! EQ (XCAR (XCAR (val
)), driver_list
->driver
->type
))
3400 xassert (! NILP (val
));
3401 val
= XCDR (XCAR (val
));
3402 if (XINT (XCAR (val
)) == 0)
3404 font_clear_cache (f
, XCAR (val
), driver_list
->driver
);
3405 XSETCDR (cache
, XCDR (val
));
3413 DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table
,
3414 Sinternal_set_font_style_table
, 2, 2, 0,
3415 doc
: /* Set font style table for PROP to TABLE.
3416 PROP must be `:weight', `:slant', or `:width'.
3417 TABLE must be an alist of symbols vs the corresponding numeric values
3418 sorted by numeric values. */)
3420 Lisp_Object prop
, table
;
3424 Lisp_Object tail
, val
;
3426 CHECK_SYMBOL (prop
);
3427 table_index
= (EQ (prop
, QCweight
) ? 0
3428 : EQ (prop
, QCslant
) ? 1
3429 : EQ (prop
, QCwidth
) ? 2
3431 if (table_index
>= ASIZE (font_style_table
))
3432 error ("Invalid font style property: %s", SDATA (SYMBOL_NAME (prop
)));
3433 table
= Fcopy_sequence (table
);
3435 for (tail
= table
; ! NILP (tail
); tail
= Fcdr (tail
))
3437 prop
= Fcar (Fcar (tail
));
3438 val
= Fcdr (Fcar (tail
));
3439 CHECK_SYMBOL (prop
);
3441 if (numeric
> XINT (val
))
3442 error ("Numeric values not sorted for %s", SDATA (SYMBOL_NAME (prop
)));
3443 numeric
= XINT (val
);
3444 XSETCAR (tail
, Fcons (prop
, val
));
3446 ASET (font_style_table
, table_index
, table
);
3450 /* The following three functions are still expremental. */
3452 DEFUN ("font-make-gstring", Ffont_make_gstring
, Sfont_make_gstring
, 2, 2, 0,
3453 doc
: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
3454 FONT-OBJECT may be nil if it is not yet known.
3456 G-string is sequence of glyphs of a specific font,
3457 and is a vector of this form:
3458 [ HEADER GLYPH ... ]
3459 HEADER is a vector of this form:
3460 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
3462 FONT-OBJECT is a font-object for all glyphs in the g-string,
3463 WIDTH thry DESCENT are the metrics (in pixels) of the whole G-string.
3464 GLYPH is a vector of this form:
3465 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
3466 [ [X-OFF Y-OFF WADJUST] | nil] ]
3468 FROM-IDX and TO-IDX are used internally and should not be touched.
3469 C is the character of the glyph.
3470 CODE is the glyph-code of C in FONT-OBJECT.
3471 WIDTH thry DESCENT are the metrics (in pixels) of the glyph.
3472 X-OFF and Y-OFF are offests to the base position for the glyph.
3473 WADJUST is the adjustment to the normal width of the glyph. */)
3475 Lisp_Object font_object
, num
;
3477 Lisp_Object gstring
, g
;
3481 if (! NILP (font_object
))
3482 CHECK_FONT_OBJECT (font_object
);
3485 len
= XINT (num
) + 1;
3486 gstring
= Fmake_vector (make_number (len
), Qnil
);
3487 g
= Fmake_vector (make_number (6), Qnil
);
3488 ASET (g
, 0, font_object
);
3489 ASET (gstring
, 0, g
);
3490 for (i
= 1; i
< len
; i
++)
3491 ASET (gstring
, i
, Fmake_vector (make_number (10), Qnil
));
3495 DEFUN ("font-fill-gstring", Ffont_fill_gstring
, Sfont_fill_gstring
, 4, 5, 0,
3496 doc
: /* Fillin glyph-string GSTRING by characters for FONT-OBJECT.
3497 START and END specifies the region to extract characters.
3498 If optional 3rd argument OBJECT is non-nil, it is a buffer or a string from
3499 where to extract characters.
3500 FONT-OBJECT may be nil if GSTRING already already contains one. */)
3501 (gstring
, font_object
, start
, end
, object
)
3502 Lisp_Object gstring
, font_object
, start
, end
, object
;
3508 CHECK_VECTOR (gstring
);
3509 if (NILP (font_object
))
3510 font_object
= LGSTRING_FONT (gstring
);
3511 CHECK_FONT_GET_OBJECT (font_object
, font
);
3513 if (STRINGP (object
))
3515 const unsigned char *p
;
3517 CHECK_NATNUM (start
);
3519 if (XINT (start
) > XINT (end
)
3520 || XINT (end
) > ASIZE (object
)
3521 || XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
3522 args_out_of_range_3 (object
, start
, end
);
3524 len
= XINT (end
) - XINT (start
);
3525 p
= SDATA (object
) + string_char_to_byte (object
, XINT (start
));
3526 for (i
= 0; i
< len
; i
++)
3528 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3529 /* Shut up GCC warning in comparison with
3530 MOST_POSITIVE_FIXNUM below. */
3533 c
= STRING_CHAR_ADVANCE (p
);
3534 cod
= code
= font
->driver
->encode_char (font
, c
);
3535 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
3537 LGLYPH_SET_FROM (g
, i
);
3538 LGLYPH_SET_TO (g
, i
);
3539 LGLYPH_SET_CHAR (g
, c
);
3540 LGLYPH_SET_CODE (g
, code
);
3547 if (! NILP (object
))
3548 Fset_buffer (object
);
3549 validate_region (&start
, &end
);
3550 if (XINT (end
) - XINT (start
) > LGSTRING_LENGTH (gstring
))
3551 args_out_of_range (start
, end
);
3552 len
= XINT (end
) - XINT (start
);
3554 pos_byte
= CHAR_TO_BYTE (pos
);
3555 for (i
= 0; i
< len
; i
++)
3557 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3558 /* Shut up GCC warning in comparison with
3559 MOST_POSITIVE_FIXNUM below. */
3562 FETCH_CHAR_ADVANCE (c
, pos
, pos_byte
);
3563 cod
= code
= font
->driver
->encode_char (font
, c
);
3564 if (cod
> MOST_POSITIVE_FIXNUM
|| code
== FONT_INVALID_CODE
)
3566 LGLYPH_SET_FROM (g
, i
);
3567 LGLYPH_SET_TO (g
, i
);
3568 LGLYPH_SET_CHAR (g
, c
);
3569 LGLYPH_SET_CODE (g
, code
);
3572 for (; i
< LGSTRING_LENGTH (gstring
); i
++)
3573 LGSTRING_SET_GLYPH (gstring
, i
, Qnil
);
3577 DEFUN ("font-shape-text", Ffont_shape_text
, Sfont_shape_text
, 3, 4, 0,
3578 doc
: /* Shape text between FROM and TO by FONT-OBJECT.
3579 If optional 4th argument STRING is non-nil, it is a string to shape,
3580 and FROM and TO are indices to the string.
3581 The value is the end position of the text that can be shaped by
3583 (from
, to
, font_object
, string
)
3584 Lisp_Object from
, to
, font_object
, string
;
3587 struct font_metrics metrics
;
3588 EMACS_INT start
, end
;
3589 Lisp_Object gstring
, n
;
3594 validate_region (&from
, &to
);
3595 start
= XFASTINT (from
);
3596 end
= XFASTINT (to
);
3597 modify_region (current_buffer
, start
, end
, 0);
3601 CHECK_STRING (string
);
3602 start
= XINT (from
);
3604 if (start
< 0 || start
> end
|| end
> SCHARS (string
))
3605 args_out_of_range_3 (string
, from
, to
);
3608 if (! FONT_OBJECT_P (font_object
))
3611 CHECK_FONT_GET_OBJECT (font_object
, font
);
3613 gstring
= Ffont_make_gstring (font_object
, make_number (len
));
3614 Ffont_fill_gstring (gstring
, font_object
, from
, to
, string
);
3615 if (! font
->driver
->shape
)
3617 /* Make zero-width glyphs to have one pixel width to make the
3618 display routine not lose the cursor. */
3619 for (i
= 0; i
< len
; i
++)
3621 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3623 struct font_metrics metrics
;
3627 code
= LGLYPH_CODE (g
);
3628 if (font
->driver
->text_extents (font
, &code
, 1, &metrics
) == 0)
3630 Lisp_Object gstr
= Ffont_make_gstring (font_object
,
3632 LGSTRING_SET_WIDTH (gstr
, 1);
3633 LGSTRING_SET_LBEARING (gstr
, metrics
.lbearing
);
3634 LGSTRING_SET_RBEARING (gstr
, metrics
.rbearing
+ 1);
3635 LGSTRING_SET_ASCENT (gstr
, metrics
.ascent
);
3636 LGSTRING_SET_DESCENT (gstr
, metrics
.descent
);
3637 LGLYPH_SET_FROM (g
, 0);
3638 LGLYPH_SET_TO (g
, 1);
3639 LGSTRING_SET_GLYPH (gstr
, 0, g
);
3640 from
= make_number (start
+ i
);
3641 to
= make_number (start
+ i
+ 1);
3643 Fcompose_region_internal (from
, to
, gstr
, Qnil
);
3645 Fcompose_string_internal (string
, from
, to
, gstr
, Qnil
);
3648 return make_number (end
);
3652 /* Try at most three times with larger gstring each time. */
3653 for (i
= 0; i
< 3; i
++)
3655 Lisp_Object args
[2];
3657 n
= font
->driver
->shape (gstring
);
3661 args
[1] = Fmake_vector (make_number (len
), Qnil
);
3662 gstring
= Fvconcat (2, args
);
3664 if (! INTEGERP (n
) || XINT (n
) == 0)
3668 for (i
= 0; i
< len
;)
3671 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3672 EMACS_INT this_from
= LGLYPH_FROM (g
);
3673 EMACS_INT this_to
= LGLYPH_TO (g
) + 1;
3675 int need_composition
= 0;
3677 metrics
.lbearing
= LGLYPH_LBEARING (g
);
3678 metrics
.rbearing
= LGLYPH_RBEARING (g
);
3679 metrics
.ascent
= LGLYPH_ASCENT (g
);
3680 metrics
.descent
= LGLYPH_DESCENT (g
);
3681 if (NILP (LGLYPH_ADJUSTMENT (g
)))
3683 metrics
.width
= LGLYPH_WIDTH (g
);
3684 if (LGLYPH_CHAR (g
) == 0 || metrics
.width
== 0)
3685 need_composition
= 1;
3689 metrics
.width
= LGLYPH_WADJUST (g
);
3690 metrics
.lbearing
+= LGLYPH_XOFF (g
);
3691 metrics
.rbearing
+= LGLYPH_XOFF (g
);
3692 metrics
.ascent
-= LGLYPH_YOFF (g
);
3693 metrics
.descent
+= LGLYPH_YOFF (g
);
3694 need_composition
= 1;
3696 for (j
= i
+ 1; j
< len
; j
++)
3700 g
= LGSTRING_GLYPH (gstring
, j
);
3701 if (this_from
!= LGLYPH_FROM (g
))
3703 need_composition
= 1;
3704 x
= metrics
.width
+ LGLYPH_LBEARING (g
) + LGLYPH_XOFF (g
);
3705 if (metrics
.lbearing
> x
)
3706 metrics
.lbearing
= x
;
3707 x
= metrics
.width
+ LGLYPH_RBEARING (g
) + LGLYPH_XOFF (g
);
3708 if (metrics
.rbearing
< x
)
3709 metrics
.rbearing
= x
;
3710 x
= LGLYPH_ASCENT (g
) - LGLYPH_YOFF (g
);
3711 if (metrics
.ascent
< x
)
3713 x
= LGLYPH_DESCENT (g
) - LGLYPH_YOFF (g
);
3714 if (metrics
.descent
< x
)
3715 metrics
.descent
= x
;
3716 if (NILP (LGLYPH_ADJUSTMENT (g
)))
3717 metrics
.width
+= LGLYPH_WIDTH (g
);
3719 metrics
.width
+= LGLYPH_WADJUST (g
);
3722 if (need_composition
)
3724 gstr
= Ffont_make_gstring (font_object
, make_number (j
- i
));
3725 LGSTRING_SET_WIDTH (gstr
, metrics
.width
);
3726 LGSTRING_SET_LBEARING (gstr
, metrics
.lbearing
);
3727 LGSTRING_SET_RBEARING (gstr
, metrics
.rbearing
);
3728 LGSTRING_SET_ASCENT (gstr
, metrics
.ascent
);
3729 LGSTRING_SET_DESCENT (gstr
, metrics
.descent
);
3730 for (k
= i
; i
< j
; i
++)
3732 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
3734 LGLYPH_SET_FROM (g
, LGLYPH_FROM (g
) - this_from
);
3735 LGLYPH_SET_TO (g
, LGLYPH_TO (g
) - this_from
);
3736 LGSTRING_SET_GLYPH (gstr
, i
- k
, LGSTRING_GLYPH (gstring
, i
));
3738 from
= make_number (start
+ this_from
);
3739 to
= make_number (start
+ this_to
);
3741 Fcompose_region_internal (from
, to
, gstr
, Qnil
);
3743 Fcompose_string_internal (string
, from
, to
, gstr
, Qnil
);
3752 DEFUN ("font-drive-otf", Ffont_drive_otf
, Sfont_drive_otf
, 6, 6, 0,
3753 doc
: /* Apply OpenType features on glyph-string GSTRING-IN.
3754 OTF-SPEC specifies which featuress to apply in this format:
3755 (SCRIPT LANGSYS GSUB GPOS)
3757 SCRIPT is a symbol specifying a script tag of OpenType,
3758 LANGSYS is a symbol specifying a langsys tag of OpenType,
3759 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
3761 If LANGYS is nil, the default langsys is selected.
3763 The features are applied in the order appeared in the list. The
3764 symbol `*' means to apply all available features not appeared in this
3765 list, and the remaining features are ignored. For instance, (vatu
3766 pstf * haln) is to apply vatu and pstf in this order, then to apply
3767 all available features other than vatu, pstf, and haln.
3769 The features are applied to the glyphs in the range FROM and TO of
3770 the glyph-string GSTRING-IN.
3772 If some of a feature is actually applicable, the resulting glyphs are
3773 produced in the glyph-string GSTRING-OUT from the index INDEX. In
3774 this case, the value is the number of produced glyphs.
3776 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
3779 If GSTRING-OUT is too short to hold produced glyphs, no glyphs is
3780 produced in GSTRING-OUT, and the value is nil.
3782 See the documentation of `font-make-gstring' for the format of
3784 (otf_features
, gstring_in
, from
, to
, gstring_out
, index
)
3785 Lisp_Object otf_features
, gstring_in
, from
, to
, gstring_out
, index
;
3787 Lisp_Object font_object
= LGSTRING_FONT (gstring_in
);
3792 check_otf_features (otf_features
);
3793 CHECK_FONT_GET_OBJECT (font_object
, font
);
3794 if (! font
->driver
->otf_drive
)
3795 error ("Font backend %s can't drive OpenType GSUB table",
3796 SDATA (SYMBOL_NAME (font
->driver
->type
)));
3797 CHECK_CONS (otf_features
);
3798 CHECK_SYMBOL (XCAR (otf_features
));
3799 val
= XCDR (otf_features
);
3800 CHECK_SYMBOL (XCAR (val
));
3801 val
= XCDR (otf_features
);
3804 len
= check_gstring (gstring_in
);
3805 CHECK_VECTOR (gstring_out
);
3806 CHECK_NATNUM (from
);
3808 CHECK_NATNUM (index
);
3810 if (XINT (from
) >= XINT (to
) || XINT (to
) > len
)
3811 args_out_of_range_3 (from
, to
, make_number (len
));
3812 if (XINT (index
) >= ASIZE (gstring_out
))
3813 args_out_of_range (index
, make_number (ASIZE (gstring_out
)));
3814 num
= font
->driver
->otf_drive (font
, otf_features
,
3815 gstring_in
, XINT (from
), XINT (to
),
3816 gstring_out
, XINT (index
), 0);
3819 return make_number (num
);
3822 DEFUN ("font-otf-alternates", Ffont_otf_alternates
, Sfont_otf_alternates
,
3824 doc
: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
3825 FEATURE-SPEC specifies which features of the font FONT-OBJECT to apply
3827 (SCRIPT LANGSYS FEATURE ...)
3828 See the documentation of `font-otf-gsub' for more detail.
3830 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
3831 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
3832 character code corresponding to the glyph or nil if there's no
3833 corresponding character. */)
3834 (font_object
, character
, otf_features
)
3835 Lisp_Object font_object
, character
, otf_features
;
3838 Lisp_Object gstring_in
, gstring_out
, g
;
3839 Lisp_Object alternates
;
3842 CHECK_FONT_GET_OBJECT (font_object
, font
);
3843 if (! font
->driver
->otf_drive
)
3844 error ("Font backend %s can't drive OpenType GSUB table",
3845 SDATA (SYMBOL_NAME (font
->driver
->type
)));
3846 CHECK_CHARACTER (character
);
3847 CHECK_CONS (otf_features
);
3849 gstring_in
= Ffont_make_gstring (font_object
, make_number (1));
3850 g
= LGSTRING_GLYPH (gstring_in
, 0);
3851 LGLYPH_SET_CHAR (g
, XINT (character
));
3852 gstring_out
= Ffont_make_gstring (font_object
, make_number (10));
3853 while ((num
= font
->driver
->otf_drive (font
, otf_features
, gstring_in
, 0, 1,
3854 gstring_out
, 0, 1)) < 0)
3855 gstring_out
= Ffont_make_gstring (font_object
,
3856 make_number (ASIZE (gstring_out
) * 2));
3858 for (i
= 0; i
< num
; i
++)
3860 Lisp_Object g
= LGSTRING_GLYPH (gstring_out
, i
);
3861 int c
= LGLYPH_CHAR (g
);
3862 unsigned code
= LGLYPH_CODE (g
);
3864 alternates
= Fcons (Fcons (make_number (code
),
3865 c
> 0 ? make_number (c
) : Qnil
),
3868 return Fnreverse (alternates
);
3874 DEFUN ("open-font", Fopen_font
, Sopen_font
, 1, 3, 0,
3875 doc
: /* Open FONT-ENTITY. */)
3876 (font_entity
, size
, frame
)
3877 Lisp_Object font_entity
;
3883 CHECK_FONT_ENTITY (font_entity
);
3885 size
= AREF (font_entity
, FONT_SIZE_INDEX
);
3886 CHECK_NUMBER (size
);
3888 frame
= selected_frame
;
3889 CHECK_LIVE_FRAME (frame
);
3891 isize
= XINT (size
);
3895 isize
= POINT_TO_PIXEL (- isize
, XFRAME (frame
)->resy
);
3897 return font_open_entity (XFRAME (frame
), font_entity
, isize
);
3900 DEFUN ("close-font", Fclose_font
, Sclose_font
, 1, 2, 0,
3901 doc
: /* Close FONT-OBJECT. */)
3902 (font_object
, frame
)
3903 Lisp_Object font_object
, frame
;
3905 CHECK_FONT_OBJECT (font_object
);
3907 frame
= selected_frame
;
3908 CHECK_LIVE_FRAME (frame
);
3909 font_close_object (XFRAME (frame
), font_object
);
3913 DEFUN ("query-font", Fquery_font
, Squery_font
, 1, 1, 0,
3914 doc
: /* Return information about FONT-OBJECT.
3915 The value is a vector:
3916 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
3919 NAME is a string of the font name (or nil if the font backend doesn't
3922 FILENAME is a string of the font file (or nil if the font backend
3923 doesn't provide a file name).
3925 PIXEL-SIZE is a pixel size by which the font is opened.
3927 SIZE is a maximum advance width of the font in pixel.
3929 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
3932 CAPABILITY is a list whose first element is a symbol representing the
3933 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
3934 remaining elements describes a detail of the font capability.
3936 If the font is OpenType font, the form of the list is
3937 \(opentype GSUB GPOS)
3938 where GSUB shows which "GSUB" features the font supports, and GPOS
3939 shows which "GPOS" features the font supports. Both GSUB and GPOS are
3940 lists of the format:
3941 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
3943 If the font is not OpenType font, currently the length of the form is
3946 SCRIPT is a symbol representing OpenType script tag.
3948 LANGSYS is a symbol representing OpenType langsys tag, or nil
3949 representing the default langsys.
3951 FEATURE is a symbol representing OpenType feature tag.
3953 If the font is not OpenType font, OTF-CAPABILITY is nil. */)
3955 Lisp_Object font_object
;
3960 CHECK_FONT_GET_OBJECT (font_object
, font
);
3962 val
= Fmake_vector (make_number (9), Qnil
);
3963 if (font
->font
.full_name
)
3964 ASET (val
, 0, make_unibyte_string (font
->font
.full_name
,
3965 strlen (font
->font
.full_name
)));
3966 if (font
->file_name
)
3967 ASET (val
, 1, make_unibyte_string (font
->file_name
,
3968 strlen (font
->file_name
)));
3969 ASET (val
, 2, make_number (font
->pixel_size
));
3970 ASET (val
, 3, make_number (font
->font
.size
));
3971 ASET (val
, 4, make_number (font
->ascent
));
3972 ASET (val
, 5, make_number (font
->descent
));
3973 ASET (val
, 6, make_number (font
->font
.space_width
));
3974 ASET (val
, 7, make_number (font
->font
.average_width
));
3975 if (font
->driver
->otf_capability
)
3976 ASET (val
, 8, Fcons (Qopentype
, font
->driver
->otf_capability (font
)));
3978 ASET (val
, 8, Fcons (font
->format
, Qnil
));
3982 DEFUN ("get-font-glyphs", Fget_font_glyphs
, Sget_font_glyphs
, 2, 2, 0,
3983 doc
: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
3984 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
3985 (font_object
, string
)
3986 Lisp_Object font_object
, string
;
3992 CHECK_FONT_GET_OBJECT (font_object
, font
);
3993 CHECK_STRING (string
);
3994 len
= SCHARS (string
);
3995 vec
= Fmake_vector (make_number (len
), Qnil
);
3996 for (i
= 0; i
< len
; i
++)
3998 Lisp_Object ch
= Faref (string
, make_number (i
));
4003 struct font_metrics metrics
;
4005 cod
= code
= font
->driver
->encode_char (font
, c
);
4006 if (code
== FONT_INVALID_CODE
)
4008 val
= Fmake_vector (make_number (6), Qnil
);
4009 if (cod
<= MOST_POSITIVE_FIXNUM
)
4010 ASET (val
, 0, make_number (code
));
4012 ASET (val
, 0, Fcons (make_number (code
>> 16),
4013 make_number (code
& 0xFFFF)));
4014 font
->driver
->text_extents (font
, &code
, 1, &metrics
);
4015 ASET (val
, 1, make_number (metrics
.lbearing
));
4016 ASET (val
, 2, make_number (metrics
.rbearing
));
4017 ASET (val
, 3, make_number (metrics
.width
));
4018 ASET (val
, 4, make_number (metrics
.ascent
));
4019 ASET (val
, 5, make_number (metrics
.descent
));
4025 DEFUN ("font-match-p", Ffont_match_p
, Sfont_match_p
, 2, 2, 0,
4026 doc
: /* Return t iff font-spec SPEC matches with FONT.
4027 FONT is a font-spec, font-entity, or font-object. */)
4029 Lisp_Object spec
, font
;
4031 CHECK_FONT_SPEC (spec
);
4032 if (FONT_OBJECT_P (font
))
4033 font
= ((struct font
*) XSAVE_VALUE (font
)->pointer
)->entity
;
4034 else if (! FONT_ENTITY_P (font
))
4035 CHECK_FONT_SPEC (font
);
4037 return (font_match_p (spec
, font
) ? Qt
: Qnil
);
4040 DEFUN ("font-at", Ffont_at
, Sfont_at
, 1, 3, 0,
4041 doc
: /* Return a font-object for displaying a character at POSISTION.
4042 Optional second arg WINDOW, if non-nil, is a window displaying
4043 the current buffer. It defaults to the currently selected window. */)
4044 (position
, window
, string
)
4045 Lisp_Object position
, window
, string
;
4052 CHECK_NUMBER_COERCE_MARKER (position
);
4053 pos
= XINT (position
);
4054 if (pos
< BEGV
|| pos
>= ZV
)
4055 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
4062 CHECK_NUMBER (position
);
4063 CHECK_STRING (string
);
4064 pos
= XINT (position
);
4065 if (pos
< 0 || pos
>= SCHARS (string
))
4066 args_out_of_range (string
, position
);
4069 window
= selected_window
;
4070 CHECK_LIVE_WINDOW (window
);
4071 w
= XWINDOW (window
);
4073 return font_at (-1, pos
, NULL
, w
, string
);
4077 DEFUN ("draw-string", Fdraw_string
, Sdraw_string
, 2, 2, 0,
4078 doc
: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4079 The value is a number of glyphs drawn.
4080 Type C-l to recover what previously shown. */)
4081 (font_object
, string
)
4082 Lisp_Object font_object
, string
;
4084 Lisp_Object frame
= selected_frame
;
4085 FRAME_PTR f
= XFRAME (frame
);
4091 CHECK_FONT_GET_OBJECT (font_object
, font
);
4092 CHECK_STRING (string
);
4093 len
= SCHARS (string
);
4094 code
= alloca (sizeof (unsigned) * len
);
4095 for (i
= 0; i
< len
; i
++)
4097 Lisp_Object ch
= Faref (string
, make_number (i
));
4101 code
[i
] = font
->driver
->encode_char (font
, c
);
4102 if (code
[i
] == FONT_INVALID_CODE
)
4105 face
= FACE_FROM_ID (f
, DEFAULT_FACE_ID
);
4107 if (font
->driver
->prepare_face
)
4108 font
->driver
->prepare_face (f
, face
);
4109 width
= font
->driver
->text_extents (font
, code
, i
, NULL
);
4110 len
= font
->driver
->draw_text (f
, face
, 0, font
->ascent
, code
, i
, width
);
4111 if (font
->driver
->done_face
)
4112 font
->driver
->done_face (f
, face
);
4114 return make_number (len
);
4118 #endif /* FONT_DEBUG */
4121 extern void syms_of_ftfont
P_ (());
4122 extern void syms_of_xfont
P_ (());
4123 extern void syms_of_xftfont
P_ (());
4124 extern void syms_of_ftxfont
P_ (());
4125 extern void syms_of_bdffont
P_ (());
4126 extern void syms_of_w32font
P_ (());
4127 extern void syms_of_atmfont
P_ (());
4132 sort_shift_bits
[FONT_SLANT_INDEX
] = 0;
4133 sort_shift_bits
[FONT_WEIGHT_INDEX
] = 7;
4134 sort_shift_bits
[FONT_SIZE_INDEX
] = 14;
4135 sort_shift_bits
[FONT_WIDTH_INDEX
] = 21;
4136 sort_shift_bits
[FONT_ADSTYLE_INDEX
] = 28;
4137 sort_shift_bits
[FONT_FOUNDRY_INDEX
] = 29;
4138 sort_shift_bits
[FONT_FAMILY_INDEX
] = 30;
4139 sort_shift_bits
[FONT_REGISTRY_INDEX
] = 31;
4140 /* Note that sort_shift_bits[FONT_TYPE_INDEX] is never used. */
4142 staticpro (&font_style_table
);
4143 font_style_table
= Fmake_vector (make_number (3), Qnil
);
4145 staticpro (&font_family_alist
);
4146 font_family_alist
= Qnil
;
4148 staticpro (&font_charset_alist
);
4149 font_charset_alist
= Qnil
;
4151 DEFSYM (Qopentype
, "opentype");
4153 DEFSYM (Qiso8859_1
, "iso8859-1");
4154 DEFSYM (Qiso10646_1
, "iso10646-1");
4155 DEFSYM (Qunicode_bmp
, "unicode-bmp");
4156 DEFSYM (Qunicode_sip
, "unicode-sip");
4158 DEFSYM (QCotf
, ":otf");
4159 DEFSYM (QClanguage
, ":language");
4160 DEFSYM (QCscript
, ":script");
4161 DEFSYM (QCantialias
, ":antialias");
4163 DEFSYM (QCfoundry
, ":foundry");
4164 DEFSYM (QCadstyle
, ":adstyle");
4165 DEFSYM (QCregistry
, ":registry");
4166 DEFSYM (QCspacing
, ":spacing");
4167 DEFSYM (QCdpi
, ":dpi");
4168 DEFSYM (QCscalable
, ":scalable");
4169 DEFSYM (QCextra
, ":extra");
4176 staticpro (&null_string
);
4177 null_string
= build_string ("");
4178 staticpro (&null_vector
);
4179 null_vector
= Fmake_vector (make_number (0), Qnil
);
4181 staticpro (&scratch_font_spec
);
4182 scratch_font_spec
= Ffont_spec (0, NULL
);
4183 staticpro (&scratch_font_prefer
);
4184 scratch_font_prefer
= Ffont_spec (0, NULL
);
4187 staticpro (&otf_list
);
4192 defsubr (&Sfont_spec
);
4193 defsubr (&Sfont_get
);
4194 defsubr (&Sfont_put
);
4195 defsubr (&Slist_fonts
);
4196 defsubr (&Slist_families
);
4197 defsubr (&Sfind_font
);
4198 defsubr (&Sfont_xlfd_name
);
4199 defsubr (&Sclear_font_cache
);
4200 defsubr (&Sinternal_set_font_style_table
);
4201 defsubr (&Sfont_make_gstring
);
4202 defsubr (&Sfont_fill_gstring
);
4203 defsubr (&Sfont_shape_text
);
4204 defsubr (&Sfont_drive_otf
);
4205 defsubr (&Sfont_otf_alternates
);
4208 defsubr (&Sopen_font
);
4209 defsubr (&Sclose_font
);
4210 defsubr (&Squery_font
);
4211 defsubr (&Sget_font_glyphs
);
4212 defsubr (&Sfont_match_p
);
4213 defsubr (&Sfont_at
);
4215 defsubr (&Sdraw_string
);
4217 #endif /* FONT_DEBUG */
4219 #ifdef USE_FONT_BACKEND
4220 if (enable_font_backend
)
4222 #ifdef HAVE_FREETYPE
4224 #ifdef HAVE_X_WINDOWS
4229 #endif /* HAVE_XFT */
4230 #endif /* HAVE_X_WINDOWS */
4231 #else /* not HAVE_FREETYPE */
4232 #ifdef HAVE_X_WINDOWS
4234 #endif /* HAVE_X_WINDOWS */
4235 #endif /* not HAVE_FREETYPE */
4238 #endif /* HAVE_BDFFONT */
4241 #endif /* WINDOWSNT */
4246 #endif /* USE_FONT_BACKEND */
4249 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
4250 (do not change this comment) */