/* Fontset handler.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007
+ 2005, 2006, 2007, 2008
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H14PRO021
Copyright (C) 2003, 2006
#endif
#include "termhooks.h"
-#ifdef USE_FONT_BACKEND
#include "font.h"
-#endif /* USE_FONT_BACKEND */
#undef xassert
#ifdef FONTSET_DEBUG
An element of a base fontset is a vector of FONT-DEFs which itself
is a vector [ FONT-SPEC ENCODING REPERTORY ].
- FONT-SPEC is:
- [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
+ FONT-SPEC is a font-spec created by `font-spec' or
+ ( FAMILY . REGISTRY )
or
FONT-NAME
- where FAMILY, WEIGHT, SLANT, SWIDTH, ADSTYLE, REGISTRY, and
- FONT-NAME are strings.
-
- Note: Currently WEIGHT through ADSTYLE are ignored.
+ where FAMILY, REGISTRY, and FONT-NAME are strings.
ENCODING is a charset ID that can convert characters to glyph codes
of the corresponding font.
An element of a realized fontset is nil or t, or has this form:
- [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID
- PREFERRED-RFONT-DEF RFONT-DEF0 RFONT-DEF1 ...].
+ [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-FAMILY
+ RFONT-DEF0 RFONT-DEF1 ...].
RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
static Lisp_Object Vdefault_fontset;
Lisp_Object Vfont_encoding_alist;
+Lisp_Object Vfont_encoding_charset_alist;
Lisp_Object Vuse_default_ascent;
Lisp_Object Vignore_relative_composition;
Lisp_Object Valternate_fontname_alist;
/* Prototype declarations for static functions. */
static Lisp_Object fontset_add P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object));
+static void reorder_font_vector P_ ((Lisp_Object, int, Lisp_Object));
static Lisp_Object fontset_font P_ ((Lisp_Object, int, struct face *, int));
static Lisp_Object make_fontset P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
static Lisp_Object fontset_pattern_regexp P_ ((Lisp_Object));
/* Macros to access special values of (realized) FONTSET. */
#define FONTSET_BASE(fontset) XCHAR_TABLE (fontset)->extras[2]
#define FONTSET_FRAME(fontset) XCHAR_TABLE (fontset)->extras[3]
+#define FONTSET_OBJLIST(fontset) XCHAR_TABLE (fontset)->extras[4]
#define FONTSET_NOFONT_FACE(fontset) XCHAR_TABLE (fontset)->extras[5]
#define FONTSET_REPERTORY(fontset) XCHAR_TABLE (fontset)->extras[6]
#define FONTSET_DEFAULT(fontset) XCHAR_TABLE (fontset)->extras[7]
return elt;
}
-
-/* Return the element of FONTSET for the character C, set FROM and TO
- to the range of characters around C that have the same value as C.
- If FONTSET is a base fontset other then the default fontset and
- FONTSET doesn't contain information for C, return the information
- in the default fontset. */
-
-#define FONTSET_REF_AND_RANGE(fontset, c, form, to) \
- (EQ (fontset, Vdefault_fontset) \
- ? char_table_ref_and_range (fontset, c, &from, &to) \
- : fontset_ref_and_range (fontset, c, &from, &to))
-
-static Lisp_Object
-fontset_ref_and_range (fontset, c, from, to)
- Lisp_Object fontset;
- int c;
- int *from, *to;
-{
- Lisp_Object elt;
-
- elt = char_table_ref_and_range (fontset, c, from, to);
- if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
- /* Don't check Vdefault_fontset for a realized fontset. */
- && NILP (FONTSET_BASE (fontset)))
- {
- int from1, to1;
-
- elt = char_table_ref_and_range (Vdefault_fontset, c, &from1, &to1);
- if (*from < from1)
- *from = from1;
- if (*to > to1)
- *to = to1;
- }
- return elt;
-}
-
-
/* Set elements of FONTSET for characters in RANGE to the value ELT.
RANGE is a cons (FROM . TO), where FROM and TO are character codes
specifying a range. */
}
-/* Update FONTSET_ELEMENT which has this form:
- [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-RFONT-DEF
+/* Update FONT-GROUP which has this form:
+ [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-FAMILY
RFONT-DEF0 RFONT-DEF1 ...].
Reorder RFONT-DEFs according to the current order of charset
(Vcharset_ordered_list), and update CHARSET-ORDERED-LIST-TICK to
the latest value. */
static void
-reorder_font_vector (fontset_element)
- Lisp_Object fontset_element;
+reorder_font_vector (font_group, charset_id, family)
+ Lisp_Object font_group;
+ int charset_id;
+ Lisp_Object family;
{
Lisp_Object list, *new_vec;
- Lisp_Object font_def;
int size;
int *charset_id_table;
int i, idx;
+ Lisp_Object preferred_by_charset, preferred_by_family;
- ASET (fontset_element, 0, make_number (charset_ordered_list_tick));
- size = ASIZE (fontset_element) - 3;
- if (size <= 1)
- /* No need to reorder VEC. */
- return;
+ size = ASIZE (font_group) - 3;
+ /* Exclude the tailing nil elements from the reordering. */
+ while (NILP (AREF (font_group, size - 1))) size--;
charset_id_table = (int *) alloca (sizeof (int) * size);
new_vec = (Lisp_Object *) alloca (sizeof (Lisp_Object) * size);
- /* At first, extract ENCODING (a chaset ID) from each FONT-DEF.
- FONT-DEF has this form:
- [FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]] */
- for (i = 0; i < size; i++)
+ /* At first, extract ENCODING (a chaset ID) from RFONT_DEF which
+ has this form:
+ [FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]]
+ In addtion, if RFONT_DEF is preferred by family or charset, store
+ it from the start of new_vec. */
+ for (i = 0, idx = 0; i < size; i++)
{
- font_def = AREF (fontset_element, i + 3);
- if (VECTORP (AREF (font_def, 2))
- && INTEGERP (AREF (AREF (font_def, 2), 1)))
- charset_id_table[i] = XINT (AREF (AREF (font_def, 2), 1));
- else
- charset_id_table[i] = -1;
+ Lisp_Object rfont_def = AREF (font_group, i + 3);
+ Lisp_Object font_spec = AREF (AREF (rfont_def, 2), 0);
+ Lisp_Object this_family = AREF (font_spec, FONT_FAMILY_INDEX);
+ int id = XINT (AREF (AREF (rfont_def, 2), 1));
+ struct charset *charset = CHARSET_FROM_ID (id);
+
+ charset_id_table[i] = -1;
+ if (! NILP (this_family)
+ && (fast_string_match_ignore_case (family, SYMBOL_NAME (this_family))
+ >= 0))
+ {
+ if (idx > 0)
+ memmove (new_vec + 1, new_vec, sizeof (Lisp_Object) * idx);
+ new_vec[0] = rfont_def;
+ idx++;
+ ASET (font_group, i + 3, Qnil);
+ }
+ else if (id == charset_id)
+ {
+ new_vec[idx++] = rfont_def;
+ ASET (font_group, i + 3, Qnil);
+ }
+ else if (! charset->supplementary_p)
+ charset_id_table[i] = id;
}
- /* Then, store FONT-DEFs in NEW_VEC in the correct order. */
- for (idx = 0, list = Vcharset_ordered_list;
- idx < size && CONSP (list); list = XCDR (list))
+ if (idx == 0
+ && (XINT (AREF (font_group, 0)) == charset_ordered_list_tick))
+ /* No need of reordering. */
+ return;
+
+ ASET (font_group, 0, make_number (charset_ordered_list_tick));
+ ASET (font_group, 1, make_number (charset_id));
+ ASET (font_group, 2, family);
+
+ /* Then, store the remaining RFONT-DEFs in NEW_VEC in the correct
+ order. */
+ for (list = Vcharset_ordered_list; idx < size; list = XCDR (list))
{
+ int id = XINT (XCAR (list));
+ struct charset *charset = CHARSET_FROM_ID (id);
+
+ if (charset->supplementary_p)
+ break;
for (i = 0; i < size; i++)
- if (charset_id_table[i] == XINT (XCAR (list)))
- new_vec[idx++] = AREF (fontset_element, i + 3);
+ if (charset_id_table[i] == XINT (XCAR (list))
+ && ! NILP (AREF (font_group, i + 3)))
+ {
+ new_vec[idx++] = AREF (font_group, i + 3);
+ ASET (font_group, i + 3, Qnil);
+ }
}
for (i = 0; i < size; i++)
- if (charset_id_table[i] < 0)
- new_vec[idx++] = AREF (fontset_element, i + 3);
+ if (! NILP (AREF (font_group, i + 3)))
+ new_vec[idx++] = AREF (font_group, i + 3);
- /* At last, update FONT-DEFs. */
+ /* At last, update elements of FONT-GROUP. */
for (i = 0; i < size; i++)
- ASET (fontset_element, i + 3, new_vec[i]);
+ ASET (font_group, i + 3, new_vec[i]);
}
If REPERTORY is nil, generate a char-table representing the font
repertory by looking into the font itself. */
+extern Lisp_Object QCname;
+
static int
load_font_get_repertory (f, face, font_def, fontset)
FRAME_PTR f;
char *font_name;
struct font_info *font_info;
int charset;
+ Lisp_Object font_spec, name;
- font_name = choose_face_font (f, face->lface, AREF (font_def, 0), NULL);
+ font_spec = AREF (font_def, 0);
+ name = Ffont_get (font_spec, QCname);
+ if (! NILP (name))
+ font_name = choose_face_font (f, face->lface, name, NULL);
+ else
+ font_name = choose_face_font (f, face->lface, font_spec, NULL);
charset = XINT (AREF (font_def, 1));
if (! (font_info = fs_load_font (f, font_name, charset)))
return -1;
int, int));
/* Return RFONT-DEF (vector) in the realized fontset FONTSET for the
- character C. If the corresponding font is not yet opened, open it
- (if FACE is not NULL) or return Qnil (if FACE is NULL).
- If no proper font is found for C, return Qnil.
+ character C. If no font is found, return Qnil if there's a
+ possibility that the default fontset or the fallback font groups
+ have a proper font, and return Qt if not.
+
+ If a font is found but is not yet opened, open it (if FACE is not
+ NULL) or return Qnil (if FACE is NULL).
+
ID is a charset-id that must be preferred, or -1 meaning no
preference.
- If FALLBACK if nonzero, search only fallback fonts. */
+
+ If FALLBACK is nonzero, search only fallback fonts. */
static Lisp_Object
fontset_find_font (fontset, c, face, id, fallback)
vec = CHAR_TABLE_REF (fontset, c);
else
vec = FONTSET_FALLBACK (fontset);
+
if (NILP (vec))
{
- /* We have not yet decided a font for C. */
Lisp_Object range;
+ /* We have not yet decided a font for C. */
if (! face)
return Qnil;
if (! fallback)
- elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
+ {
+ elt = char_table_ref_and_range (base_fontset, c, &from, &to);
+ range = Fcons (make_number (from), make_number (to));
+ }
else
- elt = FONTSET_FALLBACK (base_fontset);
- range = Fcons (make_number (from), make_number (to));
+ {
+ elt = FONTSET_FALLBACK (base_fontset);
+ }
if (NILP (elt))
{
- /* Qt means we have no font for characters of this range. */
+ /* This fontset doesn't specify any font for C. */
+ vec = make_number (0);
+ }
+ else if (ASIZE (elt) == 1 && NILP (AREF (elt, 0)))
+ {
+ /* Explicitly specified no font. */
vec = Qt;
}
else
/* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
where the first -1 is to force reordering of NEW-ELTn,
NEW-ELTn is [nil nil AREF (elt, n) nil]. */
-#ifdef USE_FONT_BACKEND
- if (! fallback
- && enable_font_backend
- && EQ (base_fontset, Vdefault_fontset))
- /* Extra one element is for an automatically added
- font-def specifying only a script. */
- vec = Fmake_vector (make_number (ASIZE (elt) + 4), Qnil);
- else
-#endif /* not USE_FONT_BACKEND */
- vec = Fmake_vector (make_number (ASIZE (elt) + 3), Qnil);
+ int size = ASIZE (elt);
+ int j;
+
+ vec = Fmake_vector (make_number (size + 3), Qnil);
ASET (vec, 0, make_number (-1));
ASET (vec, 1, make_number (-1));
- for (i = 0; i < ASIZE (elt); i++)
- {
- Lisp_Object tmp;
-
- tmp = Fmake_vector (make_number (5), Qnil);
- ASET (tmp, 2, AREF (elt, i));
- ASET (vec, 3 + i, tmp);
- }
-#ifdef USE_FONT_BACKEND
- if (! fallback
- && enable_font_backend
- && EQ (base_fontset, Vdefault_fontset))
- {
- Lisp_Object script, font_spec;
-
- script = CHAR_TABLE_REF (Vchar_script_table, c);
- if (NILP (script))
- script = intern ("latin");
- font_spec = Ffont_spec (0, NULL);
- ASET (font_spec, FONT_REGISTRY_INDEX, Qiso10646_1);
- ASET (font_spec, FONT_EXTRA_INDEX,
- Fcons (Fcons (QCscript, script), Qnil));
- font_def = Fmake_vector (make_number (3), Qnil);
- ASET (font_def, 0, font_spec);
- elt = Fmake_vector (make_number (5), Qnil);
- ASET (elt, 2, font_def);
- ASET (vec, 3 + i, elt);
- }
-#endif /* USE_FONT_BACKEND */
-
- /* Then store it in the fontset. */
- if (! fallback)
- FONTSET_SET (fontset, range, vec);
- else
- FONTSET_FALLBACK (fontset) = vec;
- }
- }
- if (EQ (vec, Qt))
- return Qnil;
-
- if (XINT (AREF (vec, 0)) != charset_ordered_list_tick)
- /* The priority of charsets is changed after we selected a face
- for C last time. */
- reorder_font_vector (vec);
-
- if (id < 0)
- i = 3;
- else if (id == XFASTINT (AREF (vec, 1)))
- i = 2;
- else
- {
- ASET (vec, 1, make_number (id));
- for (i = 3; i < ASIZE (vec); i++)
- if (id == XFASTINT (AREF (AREF (AREF (vec, i), 2), 1)))
- break;
- if (i < ASIZE (vec))
- {
- ASET (vec, 2, AREF (vec, i));
- i = 2;
+ for (i = j = 0; i < size; i++)
+ if (! NILP (AREF (elt, i)))
+ {
+ Lisp_Object tmp;
+ tmp = Fmake_vector (make_number (5), Qnil);
+ ASET (tmp, 2, AREF (elt, i));
+ ASET (vec, j + 3, tmp);
+ j++;
+ }
}
+ /* Then store it in the fontset. */
+ if (! fallback)
+ FONTSET_SET (fontset, range, vec);
else
- {
- ASET (vec, 2, Qnil);
- i = 3;
- }
+ FONTSET_FALLBACK (fontset) = vec;
+
}
+ if (! VECTORP (vec))
+ return (EQ (vec, Qt) ? Qt : Qnil);
+
+ if (ASIZE (vec) > 4
+ && (XINT (AREF (vec, 0)) != charset_ordered_list_tick
+ || (id >= 0 && XINT (AREF (vec, 1)) != id)
+ || NILP (Fequal (AREF (vec, 2), face->lface[LFACE_FAMILY_INDEX]))))
+ /* We have just created VEC,
+ or the charset priorities were changed,
+ or the preferred charset was changed,
+ or the preferred family was changed. */
+ reorder_font_vector (vec, id, face->lface[LFACE_FAMILY_INDEX]);
/* Find the first available font in the vector of RFONT-DEF. */
- for (; i < ASIZE (vec); i++)
+ for (i = 3; i < ASIZE (vec); i++)
{
elt = AREF (vec, i);
if (NILP (elt))
- continue;
- /* ELT == [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ] */
+ /* This is the sign of not to try fallback fonts. */
+ return Qt;
+ /* ELT == [ FACE-ID FONT-INDEX FONT-DEF ... ] */
if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
/* We couldn't open this font last time. */
continue;
#ifdef USE_FONT_BACKEND
if (enable_font_backend)
{
- /* ELT == [ FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY FONT-OBJECT ] */
+ /* ELT == [ FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY ]
+ where FONT-ENTITY turns to a font-object once opened. */
Lisp_Object font_entity = AREF (elt, 3);
- Lisp_Object font_object = AREF (elt, 4);
- Lisp_Object font_spec = AREF (font_def, 0);
- int has_char;
+ int has_char = 0;
if (NILP (font_entity))
{
- if (! FONT_SPEC_P (font_spec))
- {
- /* FONT_SPEC is FONT-NAME or (FAMILY . REGISTRY). */
- font_spec = Ffont_spec (0, NULL);
- if (STRINGP (AREF (font_def, 0)))
- font_merge_old_spec (AREF (font_def, 0), Qnil, Qnil,
- font_spec);
- else
- {
- Lisp_Object family = AREF (AREF (font_def, 0), 0);
- Lisp_Object registry = AREF (AREF (font_def, 0), 5);;
-
- font_merge_old_spec (Qnil, family, registry, font_spec);
- }
- ASET (font_def, 0, font_spec);
- }
- font_entity = font_find_for_lface (f, face->lface, font_spec);
- ASET (elt, 3, font_entity);
+ font_entity = font_find_for_lface (f, face->lface,
+ AREF (font_def, 0), -1);
if (NILP (font_entity))
{
ASET (elt, 1, make_number (-1));
continue;
}
- font_object = Qnil;
+ ASET (elt, 3, font_entity);
+ }
+ else if (FONT_ENTITY_P (font_entity))
+ {
+ if (FONT_ENTITY_NOT_LOADABLE (font_entity))
+ continue;
}
has_char = font_has_char (f, font_entity, c);
- if (has_char == 0)
+ if (! has_char)
continue;
- if (NILP (font_object))
+ if (! FONT_OBJECT_P (font_entity))
{
- font_object = font_open_for_lface (f, font_entity,
- face->lface, font_spec);
- ASET (elt, 4, font_object);
+ Lisp_Object font_object
+ = font_open_for_lface (f, font_entity, face->lface, Qnil);
+
if (NILP (font_object))
{
- ASET (elt, 1, make_number (-1));
+ FONT_ENTITY_SET_NOT_LOADABLE (font_entity);
continue;
}
+ FONTSET_OBJLIST (fontset)
+ = Fcons (font_object, FONTSET_OBJLIST (fontset));
+ ASET (elt, 3, font_object);
+ if (has_char < 0)
+ {
+ has_char = font_has_char (f, font_object, c);
+ if (! has_char)
+ continue;
+ }
}
+ /* Decide to use this font. */
ASET (elt, 1, make_number (0));
- ASET (elt, 4, font_object);
- if (has_char < 0
- && font_encode_char (font_object, c) == FONT_INVALID_CODE)
- continue;
}
else
#endif /* USE_FONT_BACKEND */
font_info = (*get_font_info_func) (f, font_idx);
ASET (elt, 3, build_string (font_info->full_name));
}
-
- /* Now we have the opened font. */
return elt;
}
+
return Qnil;
}
/* Try a font-group for C. */
rfont_def = fontset_find_font (fontset, c, face, id, 0);
- if (! NILP (rfont_def))
+ if (VECTORP (rfont_def))
return rfont_def;
+ if (EQ (rfont_def, Qt))
+ return Qnil;
base_fontset = FONTSET_BASE (fontset);
/* Try a font-group for C of the default fontset. */
if (! EQ (base_fontset, Vdefault_fontset))
FONTSET_DEFAULT (fontset)
= make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 0);
+ if (VECTORP (rfont_def))
+ return (rfont_def);
+ if (! NILP (rfont_def))
+ /* Remeber that we have no font for C. */
+ FONTSET_SET (fontset, make_number (c), Qt);
}
- if (! NILP (rfont_def))
- return rfont_def;
+
/* Try a fallback font-group. */
rfont_def = fontset_find_font (fontset, c, face, id, 1);
- if (! NILP (rfont_def))
- return rfont_def;
- /* Try a fallback font-group of the default fontset . */
- if (! EQ (base_fontset, Vdefault_fontset))
+ if (! VECTORP (rfont_def)
+ && ! EQ (base_fontset, Vdefault_fontset))
+ /* Try a fallback font-group of the default fontset . */
rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 1);
+
+ if (! VECTORP (rfont_def))
+ /* Remeber that we have no font for C. */
+ FONTSET_SET (fontset, make_number (c), Qt);
+
return rfont_def;
}
return elt;
}
+void
+free_realized_fontset (f, fontset)
+ FRAME_PTR f;
+ Lisp_Object fontset;
+{
+ int i;
+ Lisp_Object tail;
+
+ return;
+ for (tail = FONTSET_OBJLIST (fontset); CONSP (tail); tail = XCDR (tail))
+ {
+ xassert (FONT_OBJECT_P (XCAR (tail)));
+ font_close_object (f, XCAR (tail));
+ }
+}
/* Free fontset of FACE defined on frame F. Called from
free_realized_face. */
{
Lisp_Object fontset;
- fontset = AREF (Vfontset_table, face->fontset);
+ fontset = FONTSET_FROM_ID (face->fontset);
xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
xassert (f == XFRAME (FONTSET_FRAME (fontset)));
+ free_realized_fontset (f, fontset);
ASET (Vfontset_table, face->fontset, Qnil);
if (face->fontset < next_fontset_id)
next_fontset_id = face->fontset;
fontset = AREF (Vfontset_table, id);
xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
xassert (f == XFRAME (FONTSET_FRAME (fontset)));
+ free_realized_fontset (f, fontset);
ASET (Vfontset_table, id, Qnil);
if (id < next_fontset_id)
next_fontset_id = face->fontset;
if (NILP (charset))
id = -1;
else if (CHARSETP (charset))
- id = XINT (CHARSET_SYMBOL_ID (charset));
+ {
+ Lisp_Object val;
+
+ val = assoc_no_quit (charset, Vfont_encoding_charset_alist);
+ if (CONSP (val) && CHARSETP (XCDR (val)))
+ charset = XCDR (val);
+ id = XINT (CHARSET_SYMBOL_ID (charset));
+ }
}
rfont_def = fontset_font (fontset, c, face, id);
if (VECTORP (rfont_def))
if (enable_font_backend
&& NILP (AREF (rfont_def, 0)))
{
- struct font *font = XSAVE_VALUE (AREF (rfont_def, 4))->pointer;
+ struct font *font = XSAVE_VALUE (AREF (rfont_def, 3))->pointer;
face_id = face_for_font (f, font, face);
ASET (rfont_def, 0, make_number (face_id));
base_fontset = FONTSET_FROM_ID (base_fontset_id);
if (!BASE_FONTSET_P (base_fontset))
base_fontset = FONTSET_BASE (base_fontset);
- xassert (BASE_FONTSET_P (base_fontset));
if (! BASE_FONTSET_P (base_fontset))
abort ();
}
base_fontset = Vdefault_fontset;
fontset = make_fontset (frame, Qnil, base_fontset);
- {
- Lisp_Object elt, rfont_def, val;
-
- elt = FONTSET_REF (base_fontset, 0);
- xassert (VECTORP (elt) && ASIZE (elt) > 0);
-#ifdef USE_FONT_BACKEND
- rfont_def = Fmake_vector (make_number (5), Qnil);
- if (enable_font_backend && face->font_info)
- {
- struct font *font = (struct font *) face->font_info;
-
- ASET (rfont_def, 3, font->entity);
- ASET (rfont_def, 4, font_find_object (font));
- }
- else
-#endif /* USE_FONT_BACKEND */
- {
- rfont_def = Fmake_vector (make_number (4), Qnil);
- ASET (rfont_def, 3, build_string (face->font_name));
- }
- ASET (rfont_def, 1, make_number (face->font_info_id));
- ASET (rfont_def, 2, AREF (elt, 0));
- elt = Fmake_vector (make_number (4), Qnil);
- ASET (elt, 0, make_number (charset_ordered_list_tick));
- ASET (elt, 1, make_number (charset_ascii));
- ASET (elt, 2, rfont_def);
- ASET (elt, 3, rfont_def);
-
- val = Fcons (Qlatin, Qnil);
- map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table, val);
- for (val = XCDR (val); CONSP (val); val = XCDR (val))
- char_table_set_range (fontset, XINT (XCAR (XCAR (val))),
- XINT (XCDR (XCAR (val))), elt);
- FONTSET_FALLBACK (fontset) = elt;
- }
return XINT (FONTSET_ID (fontset));
}
/* Return an ASCII font name generated from fontset name NAME and
- ASCII font specification ASCII_SPEC. NAME is a string conforming
- to XLFD. ASCII_SPEC is a vector:
- [FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY]. */
+ font-spec ASCII_SPEC. NAME is a string conforming to XLFD. */
static INLINE Lisp_Object
generate_ascii_font_name (name, ascii_spec)
Lisp_Object name, ascii_spec;
{
+ Lisp_Object font_spec = Ffont_spec (0, NULL);
Lisp_Object vec;
int i;
+ char xlfd[256];
- vec = split_font_name_into_vector (name);
- for (i = FONT_SPEC_FAMILY_INDEX; i <= FONT_SPEC_ADSTYLE_INDEX; i++)
+ if (font_parse_xlfd (SDATA (name), font_spec) < 0)
+ error ("Not an XLFD font name: %s", SDATA (name));
+ for (i = FONT_FOUNDRY_INDEX; i <= FONT_WIDTH_INDEX; i++)
if (! NILP (AREF (ascii_spec, i)))
- ASET (vec, 1 + i, AREF (ascii_spec, i));
- if (! NILP (AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX)))
- ASET (vec, 12, AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX));
- return build_font_name_from_vector (vec);
+ ASET (font_spec, i, AREF (ascii_spec, i));
+ i = font_unparse_xlfd (font_spec, 0, xlfd, 256);
+ if (i < 0)
+ error ("Not an XLFD font name: %s", SDATA (name));
+ return make_unibyte_string (xlfd, i);
}
/* Variables referred in set_fontset_font. They are set before
FONTSET_ADD (fontset, range, font_def_arg, add_arg);
}
+extern Lisp_Object QCfamily, QCregistry;
DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
doc: /*
REGISTRY is a font registry name. FAMILY may contains foundry
name, and REGISTRY may contains encoding name.
* A font name string.
+ * nil, which explicitly specifies that there's no font for TARGET.
Optional 4th argument FRAME, if non-nil, is a frame. This argument is
kept for backward compatibility and has no meaning.
if (VECTORP (font_spec))
{
- /* FONT_SPEC should have this form:
- [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ]
- This is a feature not yet documented because WEIGHT thru
- ADSTYLE are ignored for the moment. */
- int j;
-
- if (ASIZE (font_spec) != FONT_SPEC_MAX_INDEX)
- args_out_of_range (make_number (FONT_SPEC_MAX_INDEX),
- make_number (ASIZE (font_spec)));
-
- font_spec = Fcopy_sequence (font_spec);
- for (j = 0; j < FONT_SPEC_MAX_INDEX - 1; j++)
- if (! NILP (AREF (font_spec, j)))
- {
- CHECK_STRING (AREF (font_spec, j));
- ASET (font_spec, j, Fdowncase (AREF (font_spec, j)));
- }
- family = AREF (font_spec, FONT_SPEC_FAMILY_INDEX);
- /* REGISTRY should not be omitted. */
- CHECK_STRING (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX));
- registry = AREF (font_spec, FONT_SPEC_REGISTRY_INDEX);
+ if (! FONT_SPEC_P (font_spec))
+ Fsignal (Qfont, list2 (build_string ("invalid font-spec"), font_spec));
}
else if (CONSP (font_spec))
{
+ Lisp_Object args[4];
+ int i= 0;
+
family = XCAR (font_spec);
registry = XCDR (font_spec);
if (! NILP (family))
{
CHECK_STRING (family);
- family = Fdowncase (family);
+ args[i++] = QCfamily;
+ args[i++] = family;
}
CHECK_STRING (registry);
- registry = Fdowncase (registry);
- font_spec = Fmake_vector (make_number (FONT_SPEC_MAX_INDEX), Qnil);
- ASET (font_spec, FONT_SPEC_FAMILY_INDEX, family);
- ASET (font_spec, FONT_SPEC_REGISTRY_INDEX, registry);
+ args[i++] = QCregistry;
+ args[i++] = registry;
+ font_spec = Ffont_spec (i, args);
}
- else
+ else if (STRINGP (font_spec))
{
- CHECK_STRING (font_spec);
- font_spec = Fdowncase (font_spec);
- }
-
- if (STRINGP (font_spec))
- encoding = find_font_encoding (font_spec);
- else
- encoding = find_font_encoding (concat2 (family, registry));
- if (NILP (encoding))
- encoding = Qascii;
+ Lisp_Object args[2];
- if (SYMBOLP (encoding))
- {
- CHECK_CHARSET (encoding);
- encoding = repertory = CHARSET_SYMBOL_ID (encoding);
+ args[0] = QCname;
+ args[1] = font_spec;
+ font_spec = Ffont_spec (2, args);
}
- else
+ else if (! NILP (font_spec))
+ wrong_type_argument (intern ("font-spec"), font_spec);
+
+ if (! NILP (font_spec))
{
- repertory = XCDR (encoding);
- encoding = XCAR (encoding);
- CHECK_CHARSET (encoding);
- encoding = CHARSET_SYMBOL_ID (encoding);
- if (! NILP (repertory) && SYMBOLP (repertory))
+ family = AREF (font_spec, FONT_FAMILY_INDEX);
+ if (! NILP (family) && SYMBOLP (family))
+ family = SYMBOL_NAME (family);
+ registry = AREF (font_spec, FONT_REGISTRY_INDEX);
+ if (! NILP (registry) && SYMBOLP (registry))
+ registry = SYMBOL_NAME (registry);
+
+ encoding = find_font_encoding (concat2 (family, registry));
+ if (NILP (encoding))
+ encoding = Qascii;
+
+ if (SYMBOLP (encoding))
+ {
+ CHECK_CHARSET (encoding);
+ encoding = repertory = CHARSET_SYMBOL_ID (encoding);
+ }
+ else
{
- CHECK_CHARSET (repertory);
- repertory = CHARSET_SYMBOL_ID (repertory);
+ repertory = XCDR (encoding);
+ encoding = XCAR (encoding);
+ CHECK_CHARSET (encoding);
+ encoding = CHARSET_SYMBOL_ID (encoding);
+ if (! NILP (repertory) && SYMBOLP (repertory))
+ {
+ CHECK_CHARSET (repertory);
+ repertory = CHARSET_SYMBOL_ID (repertory);
+ }
}
+ font_def = Fmake_vector (make_number (3), font_spec);
+ ASET (font_def, 1, encoding);
+ ASET (font_def, 2, repertory);
}
- font_def = Fmake_vector (make_number (3), font_spec);
- ASET (font_def, 1, encoding);
- ASET (font_def, 2, repertory);
+ else
+ font_def = Qnil;
if (CHARACTERP (target))
range_list = Fcons (Fcons (target, target), Qnil);
map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
val);
range_list = XCDR (val);
- if (EQ (target, Qlatin))
+ if (EQ (target, Qlatin) && NILP (FONTSET_ASCII (fontset)))
{
if (VECTORP (font_spec))
val = generate_ascii_font_name (FONTSET_NAME (fontset),
}
if (CHARSETP (target))
{
- if (EQ (target, Qascii))
+ if (EQ (target, Qascii) && NILP (FONTSET_ASCII (fontset)))
{
if (VECTORP (font_spec))
font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
font_spec = Fcons (SYMBOL_NAME (AREF (font_spec, FONT_FAMILY_INDEX)),
SYMBOL_NAME (AREF (font_spec, FONT_REGISTRY_INDEX)));
Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil);
+ XSETCDR (font_spec, build_string ("iso10646-1"));
+ Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qappend);
Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
return XINT (FONTSET_ID (fontset));
}
XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
#ifdef USE_FONT_BACKEND
- if (! NILP (font_object))
+ if (enable_font_backend && ! NILP (font_object))
font_close_object (f, font_object);
#endif /* USE_FONT_BACKEND */
return info;
(position, ch)
Lisp_Object position, ch;
{
- int pos, pos_byte, dummy;
+ EMACS_INT pos, pos_byte, dummy;
int face_id;
int c;
struct frame *f;
#ifdef USE_FONT_BACKEND
if (enable_font_backend)
{
- if (VECTORP (rfont_def) && ! NILP (AREF (rfont_def, 4)))
+ if (VECTORP (rfont_def) && ! NILP (AREF (rfont_def, 3)))
{
- Lisp_Object font_object = AREF (rfont_def, 4);
+ Lisp_Object font_object = AREF (rfont_def, 3);
struct font *font = XSAVE_VALUE (font_object)->pointer;
unsigned code = font->driver->encode_char (font, c);
Lisp_Object fontname = font_get_name (font_object);
+ /* Assignment to EMACS_INT stops GCC whining about limited range
+ of data type. */
+ EMACS_INT cod = code;
if (code == FONT_INVALID_CODE)
- return Fcons (fontname, Qnil);
- if (code <= MOST_POSITIVE_FIXNUM)
+ return Qnil;
+ if (cod <= MOST_POSITIVE_FIXNUM)
return Fcons (fontname, make_number (code));
return Fcons (fontname, Fcons (make_number (code >> 16),
make_number (code & 0xFFFF)));
/* At first, set ALIST to ((FONT-SPEC) ...). */
for (alist = Qnil, i = 0; i < ASIZE (val); i++)
- alist = Fcons (Fcons (AREF (AREF (val, i), 0), Qnil), alist);
+ {
+ if (NILP (AREF (val, i)))
+ alist = Fcons (Qnil, alist);
+ else
+ alist = Fcons (Fcons (AREF (AREF (val, i), 0), Qnil), alist);
+ }
alist = Fnreverse (alist);
/* Then store opend font names to cdr of each elements. */
val = FONTSET_FALLBACK (realized[k][i]);
if (! VECTORP (val))
continue;
- /* VAL is [int int ?
- [FACE-ID FONT-INDEX FONT-DEF FONT-NAME] ...].
- If a font of an element is already opened,
- FONT-NAME is the name of a opened font. */
- for (j = 3; j < ASIZE (val); j++)
- if (STRINGP (AREF (AREF (val, j), 3)))
+#ifdef USE_FONT_BACKEND
+ /* VAL: [int int ?
+ [FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY/OBJECT]
+ ...] */
+ if (enable_font_backend)
+ for (j = 3; j < ASIZE (val); j++)
{
- Lisp_Object font_idx;
-
- font_idx = AREF (AREF (val, j), 1);
- elt = Fassq (AREF (AREF (AREF (val, j), 2), 0), alist);
- if (CONSP (elt)
- && NILP (Fmemq (font_idx, XCDR(elt))))
- nconc2 (elt, Fcons (font_idx, Qnil));
+ elt = AREF (val, j);
+ if (INTEGERP (AREF (elt, 1))
+ && XINT (AREF (elt, 1)) >= 0)
+ {
+ Lisp_Object font_object = AREF (elt, 3);
+
+ if (FONT_OBJECT_P (font_object))
+ {
+ struct font *font
+ = XSAVE_VALUE (font_object)->pointer;
+ char *name = font->font.full_name;
+ int len = strlen (name);
+ Lisp_Object slot;
+
+ slot = Fassq (AREF (AREF (elt, 2), 0), alist);
+ nconc2 (slot,
+ Fcons (make_unibyte_string (name, len),
+ Qnil));
+ }
+ }
}
+ else
+#endif /* not USE_FONT_BACKEND */
+ {
+ /* VAL is [int int ?
+ [FACE-ID FONT-INDEX FONT-DEF FONT-NAME] ...].
+ If a font of an element is already opened,
+ FONT-NAME is the name of a opened font. */
+ for (j = 3; j < ASIZE (val); j++)
+ if (STRINGP (AREF (AREF (val, j), 3)))
+ {
+ Lisp_Object font_idx;
+
+ font_idx = AREF (AREF (val, j), 1);
+ elt = Fassq (AREF (AREF (AREF (val, j), 2), 0),
+ alist);
+ if (CONSP (elt)
+ && NILP (Fmemq (font_idx, XCDR(elt))))
+ nconc2 (elt, Fcons (font_idx, Qnil));
+ }
+ for (val = alist; CONSP (val); val = XCDR (val))
+ for (elt = XCDR (XCAR (val)); CONSP (elt);
+ elt = XCDR (elt))
+ {
+ struct font_info *font_info
+ = (*get_font_info_func) (f, XINT (XCAR (elt)));
+ XSETCAR (elt, build_string (font_info->full_name));
+ }
+ }
}
- for (val = alist; CONSP (val); val = XCDR (val))
- for (elt = XCDR (XCAR (val)); CONSP (elt); elt = XCDR (elt))
- {
- struct font_info *font_info
- = (*get_font_info_func) (f, XINT (XCAR (elt)));
- XSETCAR (elt, build_string (font_info->full_name));
- }
/* Store ALIST in TBL for characters C..TO. */
if (c <= MAX_5_BYTE_CHAR)
FONTSET_ID (Vdefault_fontset) = make_number (0);
FONTSET_NAME (Vdefault_fontset)
= build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
- AREF (Vfontset_table, 0) = Vdefault_fontset;
+ ASET (Vfontset_table, 0, Vdefault_fontset);
next_fontset_id = 1;
auto_fontset_alist = Qnil;
where ENCODING is a charset or a char-table,
and REPERTORY is a charset, a char-table, or nil.
+If ENCDING and REPERTORY are the same, the element can have the form
+\(REGEXP . ENCODING).
+
ENCODING is for converting a character to a glyph code of the font.
If ENCODING is a charset, encoding a character by the charset gives
the corresponding glyph code. If ENCODING is a char-table, looking up
gets the repertory information by an opened font and ENCODING. */);
Vfont_encoding_alist = Qnil;
+ DEFVAR_LISP ("font-encoding-charset-alist", &Vfont_encoding_charset_alist,
+ doc: /*
+Alist of charsets vs the charsets to determine the preferred font encoding.
+Each element looks like (CHARSET . ENCDOING-CHARSET),
+where ENCODING-CHARSET is a charset registered in the variable
+`font-encoding-alist' as ENCODING.
+
+When a text has a property `charset' and the value is CHARSET, a font
+whose encoding corresponds to ENCODING-CHARSET is preferred. */);
+ Vfont_encoding_charset_alist = Qnil;
+
DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
doc: /*
Char table of characters whose ascent values should be ignored.