X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/57bfa499674d3ce34f44368f75a44f7bd7cfc4b8..5f2d79e0539460080b61c752fc943fee880e3367:/src/fontset.c diff --git a/src/fontset.c b/src/fontset.c index 82d1445f1a..82e5b4e65d 100644 --- a/src/fontset.c +++ b/src/fontset.c @@ -1,8 +1,8 @@ /* 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 @@ -11,10 +11,10 @@ This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,9 +22,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ /* #define FONTSET_DEBUG */ @@ -94,36 +92,16 @@ EXFUN (Fclear_face_cache, 1); An element of a base fontset is a vector of FONT-DEFs which itself is a vector [ FONT-SPEC ENCODING REPERTORY ]. - FONT-SPEC is a font-spec created by `font-spec' or - ( FAMILY . REGISTRY ) - or - FONT-NAME - where FAMILY, REGISTRY, and FONT-NAME are strings. + An element of a realized fontset is nil, t, or a vector of this form: - ENCODING is a charset ID that can convert characters to glyph codes - of the corresponding font. - - REPERTORY is a charset ID, a char-table, or nil. If REPERTORY is a - charset ID, the repertory of the charset exactly matches with that - of the font. If REPERTORY is a char-table, all characters who have - a non-nil value in the table are supported. If REPERTORY is nil, - we consult with the font itself to get the repertory. - - ENCODING and REPERTORY are extracted from the variable - Vfont_encoding_alist by using a font name generated from FONT-SPEC - (if it is a vector) or FONT-NAME as a matching target. - - - 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-RFONT-DEF + RFONT-DEF0 RFONT-DEF1 ... ] RFONT-DEFn (i.e. Realized FONT-DEF) has this form: - [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ] + [ FACE-ID FONT-DEF FONT-OBJECT SORTING-SCORE ] - RFONT-DEFn is automatically reordered by the current charset + RFONT-DEFn are automatically reordered by the current charset priority list. The value nil means that we have not yet generated the above vector @@ -214,6 +192,7 @@ static int next_fontset_id; 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; @@ -221,40 +200,6 @@ Lisp_Object Vfontset_alias_alist; Lisp_Object Vvertical_centering_font_regexp; Lisp_Object Votf_script_alist; -/* The following six are declarations of callback functions depending - on window system. See the comments in src/fontset.h for more - detail. */ - -/* Return a pointer to struct font_info of font FONT_IDX of frame F. */ -struct font_info *(*get_font_info_func) P_ ((FRAME_PTR f, int font_idx)); - -/* Return a list of font names which matches PATTERN. See the documentation - of `x-list-fonts' for more details. */ -Lisp_Object (*list_fonts_func) P_ ((struct frame *f, - Lisp_Object pattern, - int size, - int maxnames)); - -/* Load a font named NAME for frame F and return a pointer to the - information of the loaded font. If loading is failed, return 0. */ -struct font_info *(*load_font_func) P_ ((FRAME_PTR f, char *name, int)); - -/* Return a pointer to struct font_info of a font named NAME for frame F. */ -struct font_info *(*query_font_func) P_ ((FRAME_PTR f, char *name)); - -/* Additional function for setting fontset or changing fontset - contents of frame F. */ -void (*set_frame_fontset_func) P_ ((FRAME_PTR f, Lisp_Object arg, - Lisp_Object oldval)); - -/* To find a CCL program, fs_load_font calls this function. - The argument is a pointer to the struct font_info. - This function set the member `encoder' of the structure. */ -void (*find_ccl_program_func) P_ ((struct font_info *)); - -Lisp_Object (*get_font_repertory_func) P_ ((struct frame *, - struct font_info *)); - /* Check if any window system is used now. */ void (*check_window_system_func) P_ ((void)); @@ -262,6 +207,9 @@ void (*check_window_system_func) P_ ((void)); /* Prototype declarations for static functions. */ static Lisp_Object fontset_add P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)); +static Lisp_Object fontset_find_font P_ ((Lisp_Object, int, struct face *, + int, int)); +static void reorder_font_vector P_ ((Lisp_Object, 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)); @@ -297,10 +245,12 @@ fontset_id_valid_p (id) /* Macros to access special values of (base) FONTSET. */ #define FONTSET_NAME(fontset) XCHAR_TABLE (fontset)->extras[1] #define FONTSET_ASCII(fontset) XCHAR_TABLE (fontset)->extras[4] +#define FONTSET_SPEC(fontset) XCHAR_TABLE (fontset)->extras[5] /* 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] @@ -311,6 +261,38 @@ fontset_id_valid_p (id) #define BASE_FONTSET_P(fontset) (NILP (FONTSET_BASE (fontset))) +/* Macros for FONT-DEF and RFONT-DEF of fontset. */ +#define FONT_DEF_NEW(font_def, font_spec, encoding, repertory) \ + do { \ + (font_def) = Fmake_vector (make_number (3), (font_spec)); \ + ASET ((font_def), 1, encoding); \ + ASET ((font_def), 2, repertory); \ + } while (0) + +#define FONT_DEF_SPEC(font_def) AREF (font_def, 0) +#define FONT_DEF_ENCODING(font_def) AREF (font_def, 1) +#define FONT_DEF_REPERTORY(font_def) AREF (font_def, 2) + +#define RFONT_DEF_FACE(rfont_def) AREF (rfont_def, 0) +#define RFONT_DEF_SET_FACE(rfont_def, face_id) \ + ASET ((rfont_def), 0, make_number (face_id)) +#define RFONT_DEF_FONT_DEF(rfont_def) AREF (rfont_def, 1) +#define RFONT_DEF_SPEC(rfont_def) FONT_DEF_SPEC (AREF (rfont_def, 1)) +#define RFONT_DEF_REPERTORY(rfont_def) FONT_DEF_REPERTORY (AREF (rfont_def, 1)) +#define RFONT_DEF_OBJECT(rfont_def) AREF (rfont_def, 2) +#define RFONT_DEF_SET_OBJECT(rfont_def, object) \ + ASET ((rfont_def), 2, (object)) +#define RFONT_DEF_SCORE(rfont_def) XINT (AREF (rfont_def, 3)) +#define RFONT_DEF_SET_SCORE(rfont_def, score) \ + ASET ((rfont_def), 3, make_number (score)) +#define RFONT_DEF_NEW(rfont_def, font_def) \ + do { \ + (rfont_def) = Fmake_vector (make_number (4), Qnil); \ + ASET ((rfont_def), 1, (font_def)); \ + RFONT_DEF_SET_SCORE ((rfont_def), 0); \ + } while (0) + + /* Return the element of FONTSET for the character 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 @@ -336,43 +318,6 @@ fontset_ref (fontset, c) 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. */ @@ -429,113 +374,101 @@ fontset_add (fontset, range, elt, add) return Qnil; } +static int +fontset_compare_rfontdef (val1, val2) + const void *val1, *val2; +{ + return (RFONT_DEF_SCORE (*(Lisp_Object *) val2) + - RFONT_DEF_SCORE (*(Lisp_Object *) val1)); +} + +/* Update FONT-GROUP which has this form: + [ CHARSET-ORDERED-LIST-TICK PREFERRED-RFONT-DEF + RFONT-DEF0 RFONT-DEF1 ... ] + Reorder RFONT-DEFs according to the current langauge, and update + CHARSET-ORDERED-LIST-TICK. + + If PREFERRED_FAMILY is not nil, that family has the higher priority + if the encoding charsets or languages in font-specs are the same. */ -/* Update FONTSET_ELEMENT which has this form: - [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-RFONT-DEF - 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. */ +extern Lisp_Object Fassoc_string (); static void -reorder_font_vector (fontset_element) - Lisp_Object fontset_element; +reorder_font_vector (font_group, preferred_family) + Lisp_Object font_group; + Lisp_Object preferred_family; { - Lisp_Object list, *new_vec; - Lisp_Object font_def; int size; - int *charset_id_table; - int i, idx; + int i; + int score_changed = 0; - ASET (fontset_element, 0, make_number (charset_ordered_list_tick)); - size = ASIZE (fontset_element) - 3; - if (size <= 1) - /* No need to reorder VEC. */ - return; - charset_id_table = (int *) alloca (sizeof (int) * size); - new_vec = (Lisp_Object *) alloca (sizeof (Lisp_Object) * size); + size = ASIZE (font_group); + /* Exclude the tailing nil elements from the reordering. */ + while (NILP (AREF (font_group, size - 1))) size--; + size -= 2; - /* 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++) { - 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; - } - - /* 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)) - { - for (i = 0; i < size; i++) - if (charset_id_table[i] == XINT (XCAR (list))) - new_vec[idx++] = AREF (fontset_element, i + 3); - } - for (i = 0; i < size; i++) - if (charset_id_table[i] < 0) - new_vec[idx++] = AREF (fontset_element, i + 3); + Lisp_Object rfont_def = AREF (font_group, i + 2); + Lisp_Object font_def = RFONT_DEF_FONT_DEF (rfont_def); + Lisp_Object font_spec = FONT_DEF_SPEC (font_def); + Lisp_Object lang = Ffont_get (font_spec, QClang); + Lisp_Object family = AREF (font_spec, FONT_FAMILY_INDEX); + Lisp_Object repertory = FONT_DEF_REPERTORY (font_def); + int score = 0; + + if (! NILP (repertory)) + { + Lisp_Object tail; - /* At last, update FONT-DEFs. */ - for (i = 0; i < size; i++) - ASET (fontset_element, i + 3, new_vec[i]); -} + for (score = 0xFFFF, tail = Vcharset_ordered_list; + ! EQ (tail, Vcharset_non_preferred_head) && CONSP (tail); + score--, tail = XCDR (tail)) + if (EQ (repertory, XCAR (tail))) + break; + if (EQ (tail, Vcharset_non_preferred_head)) + score = 0; + } + else if (! NILP (lang)) + { + if (EQ (lang, Vcurrent_iso639_language)) + score = 0xFFFF; + else if (CONSP (Vcurrent_iso639_language)) + score = ! NILP (Fmemq (lang, Vcurrent_iso639_language)); + } + if (! NILP (preferred_family) && ! NILP (family)) + { + if (fast_string_match_ignore_case (preferred_family, + SYMBOL_NAME (family)) < 0) + score |= 0x10000; + } + if (RFONT_DEF_SCORE (rfont_def) != score) + { + RFONT_DEF_SET_SCORE (rfont_def, score); + score_changed = 1; + } + } -/* Load a font matching the font related attributes in FACE->lface and - font pattern in FONT_DEF of FONTSET, and return an index of the - font. FONT_DEF has this form: - [ FONT-SPEC ENCODING REPERTORY ] - If REPERTORY is nil, generate a char-table representing the font - repertory by looking into the font itself. */ + if (score_changed) + qsort (XVECTOR (font_group)->contents + 2, size, sizeof (Lisp_Object), + fontset_compare_rfontdef); -static int -load_font_get_repertory (f, face, font_def, fontset) - FRAME_PTR f; - struct face *face; - Lisp_Object font_def; - Lisp_Object fontset; -{ - char *font_name; - struct font_info *font_info; - int charset; - - font_name = choose_face_font (f, face->lface, AREF (font_def, 0), NULL); - charset = XINT (AREF (font_def, 1)); - if (! (font_info = fs_load_font (f, font_name, charset))) - return -1; - - if (NILP (AREF (font_def, 2)) - && NILP (Fassq (make_number (font_info->font_idx), - FONTSET_REPERTORY (fontset)))) - { - /* We must look into the font to get the correct repertory as a - char-table. */ - Lisp_Object repertory; - - repertory = (*get_font_repertory_func) (f, font_info); - FONTSET_REPERTORY (fontset) - = Fcons (Fcons (make_number (font_info->font_idx), repertory), - FONTSET_REPERTORY (fontset)); - } - - return font_info->font_idx; + ASET (font_group, 0, make_number (charset_ordered_list_tick)); } -static Lisp_Object fontset_find_font P_ ((Lisp_Object, int, struct face *, - 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) @@ -544,9 +477,8 @@ fontset_find_font (fontset, c, face, id, fallback) struct face *face; int id, fallback; { - Lisp_Object base_fontset, elt, vec, font_def; + Lisp_Object base_fontset, elt, vec; int i, from, to; - int font_idx; FRAME_PTR f = XFRAME (FONTSET_FRAME (fontset)); base_fontset = FONTSET_BASE (fontset); @@ -554,110 +486,92 @@ 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); - 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 */ + /* Build a font-group vector [ -1 nil RFONT-DEF0 RFONT-DEF1 ... ], + where the first -1 is to force reordering of RFONT-DEFs. */ + int size = ASIZE (elt); + int j; - /* Then store it in the fontset. */ - if (! fallback) - FONTSET_SET (fontset, range, vec); - else - FONTSET_FALLBACK (fontset) = vec; + vec = Fmake_vector (make_number (size + 2), Qnil); + ASET (vec, 0, make_number (-1)); + for (i = j = 0; i < size; i++) + if (! NILP (AREF (elt, i))) + { + Lisp_Object rfont_def; + + RFONT_DEF_NEW (rfont_def, AREF (elt, i)); + ASET (vec, j + 2, rfont_def); + j++; + } } - } - 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); + /* Then store it in the fontset. */ + if (! fallback) + FONTSET_SET (fontset, range, vec); + else + FONTSET_FALLBACK (fontset) = vec; - if (id < 0) - i = 3; - else + } + if (! VECTORP (vec)) + return (EQ (vec, Qt) ? Qt : Qnil); + + if (ASIZE (vec) > 4 /* multiple RFONT-DEFs */ + && XINT (AREF (vec, 0)) != charset_ordered_list_tick) + /* We have just created VEC, + or the charset priorities were changed. */ + reorder_font_vector (vec, face->lface[LFACE_FAMILY_INDEX]); + i = 2; + if (id >= 0) { - struct charset *charset = CHARSET_FROM_ID (id); - - if (charset->supplementary_p) - i = 3; - else if (id == XFASTINT (AREF (vec, 1))) - i = 2; + elt = AREF (vec, 1); + if (! NILP (elt) + && EQ (make_number (id), RFONT_DEF_REPERTORY (elt))) + i = 1; 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; + for (; i < ASIZE (vec); i++) + { + elt = AREF (vec, i); + if (! NILP (elt) + && EQ (make_number (id), RFONT_DEF_REPERTORY (elt))) + break; + } if (i < ASIZE (vec)) { - ASET (vec, 2, AREF (vec, i)); - i = 2; + ASET (vec, 1, elt); + i = 1; } else { - ASET (vec, 2, Qnil); - i = 3; + ASET (vec, 1, Qnil); + i = 2; } } } @@ -665,168 +579,91 @@ fontset_find_font (fontset, c, face, id, fallback) /* Find the first available font in the vector of RFONT-DEF. */ for (; i < ASIZE (vec); i++) { + Lisp_Object font_def, font_entity, font_object; + elt = AREF (vec, i); if (NILP (elt)) + /* This is the sign of not to try fallback fonts. */ + return Qt; + if (id >= 0 && i > 1 && EQ (AREF (vec, 1), elt)) + /* This is already checked. */ continue; - /* ELT == [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ] */ - if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0) + if (INTEGERP (RFONT_DEF_FACE (elt)) + && XINT (AREF (elt, 1)) < 0) /* We couldn't open this font last time. */ continue; - if (!face && NILP (AREF (elt, 1))) - /* We have not yet opened the font. */ - return Qnil; - - font_def = AREF (elt, 2); - /* FONT_DEF == [ FONT-SPEC ENCODING REPERTORY ] */ - -#ifdef USE_FONT_BACKEND - if (enable_font_backend) + font_object = RFONT_DEF_OBJECT (elt); + if (NILP (font_object)) { - /* ELT == [ FACE-ID FONT-INDEX FONT-DEF FONT-LIST ] - where FONT-LIST is a list of font-entity or font-object. */ - Lisp_Object font_list = AREF (elt, 3), prev = Qnil; - Lisp_Object font_object; - int has_char; - - for (; CONSP (font_list); - prev = font_list, font_list = XCDR (font_list)) + Lisp_Object font_def = RFONT_DEF_FONT_DEF (elt); + + if (! face) + /* We have not yet opened the font. */ + return Qnil; + font_entity = font_find_for_lface (f, face->lface, + FONT_DEF_SPEC (font_def), -1); + if (NILP (font_entity)) { - font_object = XCAR (font_list); - if (! (FONT_ENTITY_P (font_object) - && FONT_ENTITY_NOT_LOADABLE (font_object)) - && (has_char = font_has_char (f, font_object, c)) != 0) - { - if (has_char < 0) - { - Lisp_Object obj = font_open_for_lface (f, font_object, - face->lface, Qnil); - if (NILP (obj)) - { - FONT_ENTITY_SET_NOT_LOADABLE (font_object); - continue; - } - font_object = obj; - XSETCAR (font_list, font_object); - if (! font_has_char (f, font_object, c)) - continue; - } - if (! NILP (prev)) - { - /* Move this element to the head. */ - XSETCDR (prev, XCDR (font_list)); - ASET (elt, 3, Fcons (XCAR (font_list), AREF (elt, 3))); - } - break; - } + /* Record that no font matches the spec. */ + RFONT_DEF_SET_FACE (elt, -1); + continue; } - if (NILP (font_list)) + font_object = font_open_for_lface (f, font_entity, face->lface, Qnil); + if (NILP (font_object)) { - Lisp_Object font_spec = AREF (font_def, 0); - Lisp_Object 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, c); - if (NILP (font_entity)) - continue; - font_list = Fcons (font_entity, AREF (elt, 3)); - ASET (elt, 3, font_list); + /* Record that the font is unsable. */ + RFONT_DEF_SET_FACE (elt, -1); + continue; } - font_object = XCAR (font_list); - if (FONT_ENTITY_P (font_object)) - { - font_object = font_open_for_lface (f, font_object, - face->lface, Qnil); - if (NILP (font_object)) - { - FONT_ENTITY_SET_NOT_LOADABLE (XCAR (font_list)); - continue; - } - XSETCAR (font_list, font_object); - } - ASET (elt, 1, make_number (0)); + RFONT_DEF_SET_OBJECT (elt, font_object); } - else -#endif /* USE_FONT_BACKEND */ - - if (INTEGERP (AREF (font_def, 2))) - { - /* The repertory is specified by charset ID. */ - struct charset *charset - = CHARSET_FROM_ID (XINT (AREF (font_def, 2))); + + if (font_has_char (f, font_object, c)) + return elt; - if (! CHAR_CHARSET_P (c, charset)) - /* This font can't display C. */ - continue; - } - else if (CHAR_TABLE_P (AREF (font_def, 2))) +#if 0 + /* The following code makes Emacs to find a font for C by fairly + exhausitive search. But, that takes long time especially for + X font backend. */ + + /* Try to find the different font maching with the current spec + and support C. */ + font_def = RFONT_DEF_FONT_DEF (elt); + for (i++; i < ASIZE (vec); i++) { - /* The repertory is specified by a char table. */ - if (NILP (CHAR_TABLE_REF (AREF (font_def, 2), c))) - /* This font can't display C. */ - continue; + if (! EQ (RFONT_DEF_FONT_DEF (AREF (vec, i)), font_def)) + break; + if (font_has_char (f, RFONT_DEF_OBJECT (AREF (vec, i)), c)) + return AREF (vec, i); } - else + /* Find an font-entity that support C. */ + font_entity = font_find_for_lface (f, face->lface, + FONT_DEF_SPEC (font_def), c); + if (! NILP (font_entity)) { - Lisp_Object slot; - - if (! INTEGERP (AREF (elt, 1))) - { - /* We have not yet opened a font matching this spec. - Open the best matching font now and register the - repertory. */ - struct font_info *font_info; - - font_idx = load_font_get_repertory (f, face, font_def, fontset); - ASET (elt, 1, make_number (font_idx)); - if (font_idx < 0) - /* This means that we couldn't find a font matching - FONT_DEF. */ - continue; - font_info = (*get_font_info_func) (f, font_idx); - ASET (elt, 3, build_string (font_info->full_name)); - } - - slot = Fassq (AREF (elt, 1), FONTSET_REPERTORY (fontset)); - xassert (CONSP (slot)); - if (NILP (CHAR_TABLE_REF (XCDR (slot), c))) - /* This font can't display C. */ - continue; + Lisp_Object rfont_def, new_vec; + int j; + + font_object = font_open_for_lface (f, font_entity, face->lface, + Qnil); + RFONT_DEF_NEW (rfont_def, font_def); + RFONT_DEF_SET_OBJECT (rfont_def, font_object); + RFONT_DEF_SET_SCORE (rfont_def, RFONT_DEF_SCORE (elt)); + new_vec = Fmake_vector (make_number (ASIZE (vec) + 1), Qnil); + for (j = 0; j < i; j++) + ASET (new_vec, j, AREF (vec, j)); + ASET (new_vec, j, rfont_def); + for (j++; j < ASIZE (new_vec); j++) + ASET (new_vec, j, AREF (vec, j - 1)); + vec = new_vec; + return rfont_def; } - - /* Now we have decided to use this font spec to display C. */ - if (! INTEGERP (AREF (elt, 1))) - { - /* But not yet opened the best matching font. */ - struct font_info *font_info; - - font_idx = load_font_get_repertory (f, face, font_def, fontset); - ASET (elt, 1, make_number (font_idx)); - if (font_idx < 0) - /* Can't open it. Try the other one. */ - continue; - 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; + i--; +#endif /* 0 */ } + + FONTSET_SET (fontset, make_number (c), make_number (0)); return Qnil; } @@ -843,8 +680,10 @@ fontset_font (fontset, c, face, id) /* 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)) @@ -853,16 +692,21 @@ fontset_font (fontset, c, face, id) 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)) - 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; } @@ -950,15 +794,25 @@ fontset_ascii (id) fontset= FONTSET_FROM_ID (id); elt = FONTSET_ASCII (fontset); -#ifdef USE_FONT_BACKEND if (CONSP (elt)) elt = XCAR (elt); -#endif /* USE_FONT_BACKEND */ - /* It is assured that ELT is always a string (i.e. fontname - pattern). */ return elt; } +void +free_realized_fontset (f, fontset) + FRAME_PTR f; + Lisp_Object fontset; +{ + 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. */ @@ -970,9 +824,12 @@ free_face_fontset (f, face) { Lisp_Object fontset; - fontset = AREF (Vfontset_table, face->fontset); - xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset)); + fontset = FONTSET_FROM_ID (face->fontset); + if (NILP (fontset)) + return; + xassert (! 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; @@ -983,10 +840,12 @@ free_face_fontset (f, face) 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; } + face->fontset = -1; } @@ -1004,8 +863,8 @@ face_suitable_for_char_p (face, c) fontset = FONTSET_FROM_ID (face->fontset); rfont_def = fontset_font (fontset, c, NULL, -1); return (VECTORP (rfont_def) - && INTEGERP (AREF (rfont_def, 0)) - && face->id == XINT (AREF (rfont_def, 0))); + && INTEGERP (RFONT_DEF_FACE (rfont_def)) + && face->id == XINT (RFONT_DEF_FACE (rfont_def))); } @@ -1020,7 +879,7 @@ face_for_char (f, face, c, pos, object) int c, pos; Lisp_Object object; { - Lisp_Object fontset, charset, rfont_def; + Lisp_Object fontset, rfont_def; int face_id; int id; @@ -1034,43 +893,47 @@ face_for_char (f, face, c, pos, object) id = -1; else { + Lisp_Object charset; + charset = Fget_char_property (make_number (pos), Qcharset, object); 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)) { -#ifdef USE_FONT_BACKEND - if (enable_font_backend - && NILP (AREF (rfont_def, 0))) - { - struct font *font = XSAVE_VALUE (XCAR (AREF (rfont_def, 3)))->pointer; - - face_id = face_for_font (f, font, face); - ASET (rfont_def, 0, make_number (face_id)); - } + if (INTEGERP (RFONT_DEF_FACE (rfont_def))) + face_id = XINT (RFONT_DEF_FACE (rfont_def)); else -#endif /* USE_FONT_BACKEND */ - if (NILP (AREF (rfont_def, 0))) { - /* We have not yet made a realized face that uses this font. */ - int font_idx = XINT (AREF (rfont_def, 1)); + Lisp_Object font_object; - face_id = lookup_non_ascii_face (f, font_idx, face); - ASET (rfont_def, 0, make_number (face_id)); + font_object = RFONT_DEF_OBJECT (rfont_def); + face_id = face_for_font (f, font_object, face); + RFONT_DEF_SET_FACE (rfont_def, face_id); } - return XINT (AREF (rfont_def, 0)); } - - if (NILP (FONTSET_NOFONT_FACE (fontset))) + else { - face_id = lookup_non_ascii_face (f, -1, face); - FONTSET_NOFONT_FACE (fontset) = make_number (face_id); + if (INTEGERP (FONTSET_NOFONT_FACE (fontset))) + face_id = XINT (FONTSET_NOFONT_FACE (fontset)); + else + { + face_id = face_for_font (f, Qnil, face); + FONTSET_NOFONT_FACE (fontset) = make_number (face_id); + } } - return XINT (FONTSET_NOFONT_FACE (fontset)); + xassert (face_id >= 0); + return face_id; } @@ -1093,7 +956,6 @@ make_fontset_for_ascii_face (f, base_fontset_id, face) 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 (); } @@ -1101,111 +963,14 @@ make_fontset_for_ascii_face (f, base_fontset_id, face) 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); - rfont_def = Fmake_vector (make_number (4), Qnil); -#ifdef USE_FONT_BACKEND - if (enable_font_backend && face->font_info) - { - struct font *font = (struct font *) face->font_info; - - ASET (rfont_def, 3, Fcons (font->entity, Qnil)); - } - else -#endif /* USE_FONT_BACKEND */ - { - 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)); } - -#if defined(WINDOWSNT) && defined (_MSC_VER) -#pragma optimize("", off) -#endif - -/* Load a font named FONTNAME on frame F. Return a pointer to the - struct font_info of the loaded font. If loading fails, return - NULL. CHARSET is an ID of charset to encode characters for this - font. If it is -1, find one from Vfont_encoding_alist. */ - -struct font_info * -fs_load_font (f, fontname, charset) - FRAME_PTR f; - char *fontname; - int charset; -{ - struct font_info *fontp; - Lisp_Object fullname; - - if (!fontname) - /* No way to get fontname. */ - return NULL; - - fontp = (*load_font_func) (f, fontname, 0); - if (! fontp || fontp->charset >= 0) - return fontp; - - fontname = fontp->full_name; - fullname = build_string (fontp->full_name); - - if (charset < 0) - { - Lisp_Object charset_symbol; - - charset_symbol = find_font_encoding (fullname); - if (CONSP (charset_symbol)) - charset_symbol = XCAR (charset_symbol); - if (NILP (charset_symbol)) - charset_symbol = Qascii; - charset = XINT (CHARSET_SYMBOL_ID (charset_symbol)); - } - fontp->charset = charset; - fontp->vertical_centering = 0; - fontp->font_encoder = NULL; - - if (charset != charset_ascii) - { - fontp->vertical_centering - = (STRINGP (Vvertical_centering_font_regexp) - && (fast_string_match_ignore_case - (Vvertical_centering_font_regexp, fullname) >= 0)); - - if (find_ccl_program_func) - (*find_ccl_program_func) (fontp); - } - - return fontp; -} - -#if defined(WINDOWSNT) && defined (_MSC_VER) -#pragma optimize("", on) -#endif - /* Return ENCODING or a cons of ENCODING and REPERTORY of the font FONTNAME. ENCODING is a charset symbol that specifies the encoding of the font. REPERTORY is a charset symbol or nil. */ - Lisp_Object find_font_encoding (fontname) Lisp_Object fontname; @@ -1342,8 +1107,8 @@ fs_query_fontset (name, name_pattern) this_name = FONTSET_NAME (fontset); if (name_pattern == 1 - ? fast_string_match (name, this_name) >= 0 - : !strcmp (SDATA (name), SDATA (this_name))) + ? fast_string_match_ignore_case (name, this_name) >= 0 + : !strcasecmp (SDATA (name), SDATA (this_name))) return i; } return -1; @@ -1520,7 +1285,7 @@ generate_ascii_font_name (name, ascii_spec) 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++) + for (i = FONT_FOUNDRY_INDEX; i < FONT_EXTRA_INDEX; i++) if (! NILP (AREF (ascii_spec, i))) ASET (font_spec, i, AREF (ascii_spec, i)); i = font_unparse_xlfd (font_spec, 0, xlfd, 256); @@ -1591,10 +1356,12 @@ TARGET may be nil. In that case, use FONT-SPEC for any characters for that no FONT-SPEC is specified. FONT-SPEC may one of these: + * A font-spec object made by the function `font-spec' (which see). * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and - REGISTRY is a font registry name. FAMILY may contains foundry - name, and REGISTRY may contains encoding name. + REGISTRY is a font registry name. FAMILY may contain foundry + name, and REGISTRY may contain 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. @@ -1608,7 +1375,6 @@ appended. By default, FONT-SPEC overrides the previous settings. */) { Lisp_Object fontset; Lisp_Object font_def, registry, family; - Lisp_Object encoding, repertory; Lisp_Object range_list; struct charset *charset = NULL; @@ -1619,69 +1385,61 @@ appended. By default, FONT-SPEC overrides the previous settings. */) if (!NILP (frame)) CHECK_LIVE_FRAME (frame); - if (VECTORP (font_spec)) + if (CONSP (font_spec)) { - if (! FONT_SPEC_P (font_spec)) - Fsignal (Qfont, list2 (build_string ("invalid font-spec"), font_spec)); - family = Ffont_get (font_spec, QCfamily); - if (! NILP (family) && SYMBOLP (family)) - family = SYMBOL_NAME (family); - registry = Ffont_get (font_spec, QCregistry); - if (! NILP (registry) && SYMBOLP (registry)) - registry = SYMBOL_NAME (registry); - } - else if (CONSP (font_spec)) - { - Lisp_Object args[4]; - int i= 0; - - family = XCAR (font_spec); - registry = XCDR (font_spec); + Lisp_Object spec = Ffont_spec (0, NULL); - if (! NILP (family)) - { - CHECK_STRING (family); - args[i++] = QCfamily; - args[i++] = family; - } - CHECK_STRING (registry); - args[i++] = QCregistry; - args[i++] = registry; - font_spec = Ffont_spec (i, args); + font_parse_family_registry (XCAR (font_spec), XCDR (font_spec), spec); + font_spec = spec; } - else + else if (STRINGP (font_spec)) { - CHECK_STRING (font_spec); - font_spec = Fdowncase (font_spec); - } + Lisp_Object args[2]; + extern Lisp_Object QCname; - if (STRINGP (font_spec)) - encoding = find_font_encoding (font_spec); - else - encoding = find_font_encoding (concat2 (family, registry)); - if (NILP (encoding)) - encoding = Qascii; - - 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) && ! FONT_SPEC_P (font_spec)) + Fsignal (Qfont, list2 (build_string ("Invalid 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)) + Lisp_Object encoding, repertory; + + family = AREF (font_spec, FONT_FAMILY_INDEX); + if (! NILP (family) ) + family = SYMBOL_NAME (family); + registry = AREF (font_spec, FONT_REGISTRY_INDEX); + if (! NILP (registry)) + registry = Fdowncase (SYMBOL_NAME (registry)); + encoding = find_font_encoding (concat3 (family, build_string ("-"), + registry)); + if (NILP (encoding)) + encoding = Qascii; + + if (SYMBOLP (encoding)) { - CHECK_CHARSET (repertory); - repertory = CHARSET_SYMBOL_ID (repertory); + CHECK_CHARSET (encoding); + encoding = repertory = CHARSET_SYMBOL_ID (encoding); } + else + { + 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_NEW (font_def, font_spec, encoding, 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); @@ -1708,7 +1466,7 @@ appended. By default, FONT-SPEC overrides the previous settings. */) 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), @@ -1720,7 +1478,7 @@ appended. By default, FONT-SPEC overrides the previous settings. */) } 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), @@ -1793,23 +1551,29 @@ FONT-SPEC is a vector, a cons, or a string. See the documentation of CHECK_STRING (name); CHECK_LIST (fontlist); + name = Fdowncase (name); id = fs_query_fontset (name, 0); if (id < 0) { - name = Fdowncase (name); - val = split_font_name_into_vector (name); - if (NILP (val) || NILP (AREF (val, 12)) || NILP (AREF (val, 13))) + Lisp_Object font_spec = Ffont_spec (0, NULL); + Lisp_Object short_name; + char xlfd[256]; + int len; + + if (font_parse_xlfd (SDATA (name), font_spec) < 0) error ("Fontset name must be in XLFD format"); - if (strcmp (SDATA (AREF (val, 12)), "fontset")) - error ("Registry field of fontset name must be \"fontset\""); - Vfontset_alias_alist - = Fcons (Fcons (name, - concat2 (concat2 (AREF (val, 12), build_string ("-")), - AREF (val, 13))), - Vfontset_alias_alist); - ASET (val, 12, build_string ("iso8859-1")); + short_name = AREF (font_spec, FONT_REGISTRY_INDEX); + if (strncmp (SDATA (SYMBOL_NAME (short_name)), "fontset-", 8) + || SBYTES (SYMBOL_NAME (short_name)) < 9) + error ("Registry field of fontset name must be \"fontset-*\""); + Vfontset_alias_alist = Fcons (Fcons (name, SYMBOL_NAME (short_name)), + Vfontset_alias_alist); + ASET (font_spec, FONT_REGISTRY_INDEX, Qiso8859_1); fontset = make_fontset (Qnil, name, Qnil); - FONTSET_ASCII (fontset) = build_font_name_from_vector (val); + len = font_unparse_xlfd (font_spec, 0, xlfd, 256); + if (len < 0) + error ("Invalid fontset name (perhaps too long): %s", SDATA (name)); + FONTSET_ASCII (fontset) = make_unibyte_string (xlfd, len); } else { @@ -1836,139 +1600,55 @@ FONT-SPEC is a vector, a cons, or a string. See the documentation of /* Alist of automatically created fontsets. Each element is a cons - (FONTNAME . FONTSET-ID). */ + (FONT-SPEC . FONTSET-ID). */ static Lisp_Object auto_fontset_alist; int -new_fontset_from_font_name (Lisp_Object fontname) -{ - Lisp_Object val; - Lisp_Object name; - Lisp_Object vec; - int id; - - fontname = Fdowncase (fontname); - val = Fassoc (fontname, auto_fontset_alist); - if (CONSP (val)) - return XINT (XCDR (val)); - - vec = split_font_name_into_vector (fontname); - if ( NILP (vec)) - vec = Fmake_vector (make_number (14), build_string ("")); - ASET (vec, 12, build_string ("fontset")); - if (NILP (auto_fontset_alist)) - { - ASET (vec, 13, build_string ("startup")); - name = build_font_name_from_vector (vec); - } - else - { - char temp[20]; - int len = XINT (Flength (auto_fontset_alist)); - - sprintf (temp, "auto%d", len); - ASET (vec, 13, build_string (temp)); - name = build_font_name_from_vector (vec); - } - name = Fnew_fontset (name, list2 (list2 (Qascii, fontname), - list2 (Fcons (make_number (0), - make_number (MAX_CHAR)), - fontname))); - id = fs_query_fontset (name, 0); - auto_fontset_alist - = Fcons (Fcons (fontname, make_number (id)), auto_fontset_alist); - return id; -} - -#ifdef USE_FONT_BACKEND -int -new_fontset_from_font (font_object) +fontset_from_font (font_object) Lisp_Object font_object; { Lisp_Object font_name = font_get_name (font_object); - Lisp_Object font_spec = font_get_spec (font_object); - Lisp_Object fontset_spec, short_name, name, fontset; + Lisp_Object font_spec = Fcopy_font_spec (font_object); + Lisp_Object fontset_spec, alias, name, fontset; + Lisp_Object val; + int i; + val = assoc_no_quit (font_spec, auto_fontset_alist); + if (CONSP (val)) + return XINT (FONTSET_ID (XCDR (val))); if (NILP (auto_fontset_alist)) - short_name = build_string ("fontset-startup"); + alias = intern ("fontset-startup"); else { char temp[32]; int len = XINT (Flength (auto_fontset_alist)); sprintf (temp, "fontset-auto%d", len); - short_name = build_string (temp); + alias = intern (temp); } - fontset_spec = Fcopy_sequence (font_spec); - ASET (fontset_spec, FONT_REGISTRY_INDEX, short_name); + fontset_spec = Fcopy_font_spec (font_spec); + ASET (fontset_spec, FONT_REGISTRY_INDEX, alias); name = Ffont_xlfd_name (fontset_spec); if (NILP (name)) - { - int i; - - for (i = 0; i < FONT_SIZE_INDEX; i++) - if ((i != FONT_FAMILY_INDEX) && (i != FONT_REGISTRY_INDEX)) - ASET (fontset_spec, i, Qnil); - name = Ffont_xlfd_name (fontset_spec); - if (NILP (name)) - abort (); - } + abort (); fontset = make_fontset (Qnil, name, Qnil); + Vfontset_alias_alist = Fcons (Fcons (name, SYMBOL_NAME (alias)), + Vfontset_alias_alist); + alias = Fdowncase (AREF (font_object, FONT_NAME_INDEX)); + Vfontset_alias_alist = Fcons (Fcons (name, alias), Vfontset_alias_alist); + auto_fontset_alist = Fcons (Fcons (font_spec, fontset), auto_fontset_alist); FONTSET_ASCII (fontset) = font_name; - font_spec = Fcons (SYMBOL_NAME (AREF (font_spec, FONT_FAMILY_INDEX)), - SYMBOL_NAME (AREF (font_spec, FONT_REGISTRY_INDEX))); + ASET (font_spec, FONT_FOUNDRY_INDEX, Qnil); + ASET (font_spec, FONT_ADSTYLE_INDEX, Qnil); + for (i = FONT_WEIGHT_INDEX; i < FONT_EXTRA_INDEX; i++) + ASET (font_spec, i, Qnil); Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil); + font_spec = Fcopy_font_spec (font_spec); + ASET (font_spec, FONT_REGISTRY_INDEX, Qiso10646_1); Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil); return XINT (FONTSET_ID (fontset)); } -struct font * -fontset_ascii_font (f, id) - FRAME_PTR f; - int id; -{ - Lisp_Object fontset = FONTSET_FROM_ID (id); - Lisp_Object ascii_slot = FONTSET_ASCII (fontset); - Lisp_Object val, font_object; - - if (CONSP (ascii_slot)) - { - Lisp_Object ascii_font_name = XCAR (ascii_slot); - - font_object = Qnil; - for (val = XCDR (ascii_slot); ! NILP (val); val = XCDR (val)) - { - Lisp_Object frame = font_get_frame (XCAR (val)); - - if (NILP (frame) || XFRAME (frame) == f) - { - font_object = XCAR (val); - if (XSAVE_VALUE (font_object)->integer == 0) - { - font_object = font_open_by_name (f, SDATA (ascii_font_name)); - XSETCAR (val, font_object); - } - break; - } - } - if (NILP (font_object)) - { - font_object = font_open_by_name (f, SDATA (ascii_font_name)); - XSETCDR (ascii_slot, Fcons (font_object, XCDR (ascii_slot))); - } - } - else - { - font_object = font_open_by_name (f, SDATA (ascii_slot)); - FONTSET_ASCII (fontset) = Fcons (ascii_slot, Fcons (font_object, Qnil)); - } - if (NILP (font_object)) - return NULL; - return XSAVE_VALUE (font_object)->pointer; -} - -#endif /* USE_FONT_BACKEND */ - DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0, doc: /* Return information about a font named NAME on frame FRAME. If FRAME is omitted or nil, use the selected frame. @@ -1987,7 +1667,7 @@ If the named font is not yet loaded, return nil. */) Lisp_Object name, frame; { FRAME_PTR f; - struct font_info *fontp; + struct font *font; Lisp_Object info; Lisp_Object font_object; @@ -2000,38 +1680,21 @@ If the named font is not yet loaded, return nil. */) CHECK_LIVE_FRAME (frame); f = XFRAME (frame); - if (!query_font_func) - error ("Font query function is not supported"); - -#ifdef USE_FONT_BACKEND - if (enable_font_backend) - { - font_object = font_open_by_name (f, SDATA (name)); - if (NILP (font_object)) - fontp = NULL; - else - fontp = (struct font_info *) XSAVE_VALUE (font_object)->pointer; - } - else -#endif /* USE_FONT_BACKEND */ - fontp = (*query_font_func) (f, SDATA (name)); - if (!fontp) + font_object = font_open_by_name (f, SDATA (name)); + if (NILP (font_object)) return Qnil; + font = XFONT_OBJECT (font_object); info = Fmake_vector (make_number (7), Qnil); - - XVECTOR (info)->contents[0] = build_string (fontp->name); - XVECTOR (info)->contents[1] = build_string (fontp->full_name); - XVECTOR (info)->contents[2] = make_number (fontp->size); - XVECTOR (info)->contents[3] = make_number (fontp->height); - XVECTOR (info)->contents[4] = make_number (fontp->baseline_offset); - XVECTOR (info)->contents[5] = make_number (fontp->relative_compose); - XVECTOR (info)->contents[6] = make_number (fontp->default_ascent); - -#ifdef USE_FONT_BACKEND - if (! NILP (font_object)) - font_close_object (f, font_object); -#endif /* USE_FONT_BACKEND */ + XVECTOR (info)->contents[0] = AREF (font_object, FONT_NAME_INDEX); + XVECTOR (info)->contents[1] = AREF (font_object, FONT_NAME_INDEX); + XVECTOR (info)->contents[2] = make_number (font->pixel_size); + XVECTOR (info)->contents[3] = make_number (font->height); + XVECTOR (info)->contents[4] = make_number (font->baseline_offset); + XVECTOR (info)->contents[5] = make_number (font->relative_compose); + XVECTOR (info)->contents[6] = make_number (font->default_ascent); + + font_close_object (f, font_object); return info; } @@ -2068,12 +1731,12 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0, (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; struct face *face; - Lisp_Object charset, rfont_def; + Lisp_Object rfont_def; int cs_id; if (NILP (position)) @@ -2118,45 +1781,21 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0, return Qnil; face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil); face = FACE_FROM_ID (f, face_id); - rfont_def = fontset_font (FONTSET_FROM_ID (face->fontset), c, face, cs_id); -#ifdef USE_FONT_BACKEND - if (enable_font_backend) - { - if (VECTORP (rfont_def) && ! NILP (AREF (rfont_def, 3))) - { - Lisp_Object font_object = XCAR (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); - - if (code == FONT_INVALID_CODE) - return Fcons (fontname, Qnil); - if (code <= MOST_POSITIVE_FIXNUM) - return Fcons (fontname, make_number (code)); - return Fcons (fontname, Fcons (make_number (code >> 16), - make_number (code & 0xFFFF))); - } - return Qnil; - } -#endif /* USE_FONT_BACKEND */ - if (VECTORP (rfont_def) && STRINGP (AREF (rfont_def, 3))) + if (face->font) { - Lisp_Object font_def; - struct font_info *fontp; - struct charset *charset; - XChar2b char2b; - int code; - - font_def = AREF (rfont_def, 2); - charset = CHARSET_FROM_ID (XINT (AREF (font_def, 1))); - code = ENCODE_CHAR (charset, c); - if (code == CHARSET_INVALID_CODE (charset)) - return (Fcons (AREF (rfont_def, 3), Qnil)); - STORE_XCHAR2B (&char2b, ((code >> 8) & 0xFF), (code & 0xFF)); - fontp = (*get_font_info_func) (f, XINT (AREF (rfont_def, 1))); - FRAME_RIF (f)->encode_char (c, &char2b, fontp, charset, NULL); - code = (XCHAR2B_BYTE1 (&char2b) << 8) | XCHAR2B_BYTE2 (&char2b); - return (Fcons (AREF (rfont_def, 3), make_number (code))); + struct font *font = face->font; + unsigned code = font->driver->encode_char (font, c); + Lisp_Object fontname = font->props[FONT_NAME_INDEX]; + /* Assignment to EMACS_INT stops GCC whining about limited range + of data type. */ + EMACS_INT cod = code; + + if (code == FONT_INVALID_CODE) + 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))); } return Qnil; } @@ -2251,7 +1890,9 @@ fontset. The format is the same as abobe. */) /* 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 (Fcons (FONT_DEF_SPEC (AREF (val, i)), Qnil), + alist); alist = Fnreverse (alist); /* Then store opend font names to cdr of each elements. */ @@ -2263,35 +1904,35 @@ fontset. The format is the same as abobe. */) 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))) - { - 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)); - } + /* VAL: [int ? [FACE-ID FONT-DEF FONT-OBJECT int] ... ] */ + for (j = 2; j < ASIZE (val); j++) + { + elt = AREF (val, j); + if (FONT_OBJECT_P (RFONT_DEF_OBJECT (elt))) + { + Lisp_Object font_object = RFONT_DEF_OBJECT (elt); + Lisp_Object slot, name; + + slot = Fassq (RFONT_DEF_SPEC (elt), alist); + name = AREF (font_object, FONT_NAME_INDEX); + if (NILP (Fmember (name, XCDR (slot)))) + nconc2 (slot, Fcons (name, 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)); - } /* Store ALIST in TBL for characters C..TO. */ if (c <= MAX_5_BYTE_CHAR) char_table_set_range (tables[k], c, to, alist); else XCHAR_TABLE (tables[k])->defalt = alist; + + /* At last, change each elements to font names. */ + for (; CONSP (alist); alist = XCDR (alist)) + { + elt = XCAR (alist); + XSETCAR (elt, Ffont_xlfd_name (XCAR (elt))); + } } c = to + 1; } @@ -2432,10 +2073,6 @@ DEFUN ("fontset-list-all", Ffontset_list_all, Sfontset_list_all, 0, 0, 0, void syms_of_fontset () { - if (!load_font_func) - /* Window system initializer should have set proper functions. */ - abort (); - DEFSYM (Qfontset, "fontset"); Fput (Qfontset, Qchar_table_extra_slots, make_number (9)); DEFSYM (Qfontset_info, "fontset-info"); @@ -2456,7 +2093,7 @@ syms_of_fontset () 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; @@ -2469,6 +2106,9 @@ Each element looks like (REGEXP . (ENCODING . REPERTORY)), 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 @@ -2481,6 +2121,17 @@ non-nil value in the table are supported. It REPERTORY is nil, Emacs 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.