aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa2008-05-14 01:25:55 +0000
committerKenichi Handa2008-05-14 01:25:55 +0000
commit35027d0ca6108382edc5598d933f555808d43dfb (patch)
tree4eb6d888f8e02158f2d1db7ce1ebacf84155ff3c /src
parent875003e5bce60bfda5b853f8512099cf16e8b169 (diff)
downloademacs-35027d0ca6108382edc5598d933f555808d43dfb.tar.gz
emacs-35027d0ca6108382edc5598d933f555808d43dfb.zip
Include <strings.h>.
(enable_font_backend): Delete it. (Qfont_spec, Qfont_entity, Qfont_object): New variables. (CHECK_VALIDATE_FONT_SPEC): Delete it. (PT_PER_INCH, POINT_TO_PIXEL, PIXEL_TO_POINT): Moved to font.h. (null_string): Delete it. (null_vector): Make it static. (font_family_alist): Delete it. (Qnormal): Extern it. (QCextra, QClanguage): Delete it. (QClang, QCavgwidth, QCfont_entity, QCfc_unknown_spec): New variables. (font_make_spec, font_make_entity, font_make_object) (font_intern_prop): Renamed from intern_downcase. Don't downcase the string. Callers changed. (font_pixel_size): Adjusted for the format change of font-related objects. (prop_name_to_numeric, prop_numeric_to_name): Delete them. (font_style_to_value, font_style_symbolic): New function. (build_font_family_alist): Delete it. (font_registry_charsets): Use Fassoc_string instead of assq_no_quit. (font_prop_validate_symbol): Don't return null_string. (font_prop_validate_style): Adjusted for the change of style-related values in a font vector. (font_property_table): Delete entries for QClangauge and QCantialias, add entries for QCavgwidth. (get_font_prop_index): Delete the 2nd argument FROM. (font_prop_validate): Arguments changed. (font_put_extra): Adjusted for the change of font-related objects. (font_expand_wildcards, font_parse_xlfd, font_unparse_xlfd) (font_parse_fcname, font_unparse_fcname) (font_prepare_composition): Likewise. (font_parse_family_registry): Renamed from font_merge_old_spec. (otf_open): Delete the 1st arg entity. (font_otf_capability): Adjusted for the above change. (font_score): New arg alternate_families. Adjusted for the change of font-related objects. (font_sort_entites): New arg best_only. (font_symbolic_weight, font_symbolic_slant, font_symbolic_width): Delete them. (font_match_p): Check alternate families. (font_find_object): Delete it. (font_check_object): New function. (font_clear_cache): Adjusted for the change of font-related objects. (font_delete_unmatched): New arg. (font_list_entities): Call font_driver->list with a spec that doesn't specify style-related properties. (font_matching_entity): Arguments changed. Caller changed. (font_open_entity): Adjusted for the change of font-related objects. (font_close_object, font_has_char, font_encode_char) (font_get_name, font_get_spec): Likewise. (font_spec_from_name, font_clear_prop, font_update_lface): New functions. (font_find_for_lface, font_open_for_lface, font_load_for_lface): (font_prepare_for_face, font_done_for_face, font_open_by_name) (font_at): Adjusted for the change of font-related objects. (font_range): New function. (Ffontp, Ffont_spec, Ffont_get, Ffont_put, Flist_fonts) (Ffont_xlfd_name): Adjusted for the change of font-related objects. (Fcopy_font_spec, Fmerge_font_spec): New function. (Ffont_family_list): Renamed from list-families. (Finternal_set_font_style_table): Arguments changed. (Ffont_fill_gstring, Ffont_shape_text, Fopen_font) (Ffont_drive_otf, Fquery_font, Ffont_match_p): Adjusted for the change of font-related objects. (syms_of_font): Delete "ifdef USE_FONT_BACKEND". DEFSYM new symboles.
Diffstat (limited to 'src')
-rw-r--r--src/font.c2354
1 files changed, 1265 insertions, 1089 deletions
diff --git a/src/font.c b/src/font.c
index 5ed33fcf4b4..c3a4af928a5 100644
--- a/src/font.c
+++ b/src/font.c
@@ -24,6 +24,7 @@ Boston, MA 02110-1301, USA. */
24#include <config.h> 24#include <config.h>
25#include <stdio.h> 25#include <stdio.h>
26#include <stdlib.h> 26#include <stdlib.h>
27#include <strings.h>
27#include <ctype.h> 28#include <ctype.h>
28#ifdef HAVE_M17N_FLT 29#ifdef HAVE_M17N_FLT
29#include <m17n-flt.h> 30#include <m17n-flt.h>
@@ -63,64 +64,34 @@ Boston, MA 02110-1301, USA. */
63#define xassert(X) (void) 0 64#define xassert(X) (void) 0
64#endif 65#endif
65 66
66int enable_font_backend; 67Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
67 68
68Lisp_Object Qopentype; 69Lisp_Object Qopentype;
69 70
70/* Important character set symbols. */ 71/* Important character set strings. */
71Lisp_Object Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip; 72Lisp_Object Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
72 73
73/* Like CHECK_FONT_SPEC but also validate properties of the font-spec,
74 and set X to the validated result. */
75
76#define CHECK_VALIDATE_FONT_SPEC(x) \
77 do { \
78 if (! FONT_SPEC_P (x)) wrong_type_argument (Qfont, x); \
79 x = font_prop_validate (x); \
80 } while (0)
81
82/* Number of pt per inch (from the TeXbook). */
83#define PT_PER_INCH 72.27
84
85/* Return a pixel size (integer) corresponding to POINT size (double)
86 on resolution DPI. */
87#define POINT_TO_PIXEL(POINT, DPI) ((POINT) * (DPI) / PT_PER_INCH + 0.5)
88
89/* Return a point size (double) corresponding to POINT size (integer)
90 on resolution DPI. */
91#define PIXEL_TO_POINT(PIXEL, DPI) ((PIXEL) * PT_PER_INCH * 10 / (DPI) + 0.5)
92
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
96 it). */
97Lisp_Object null_string;
98
99/* Special vector of zero length. This is repeatedly used by (struct 74/* Special vector of zero length. This is repeatedly used by (struct
100 font_driver *)->list when a specified font is not found. */ 75 font_driver *)->list when a specified font is not found. */
101Lisp_Object null_vector; 76static Lisp_Object null_vector;
102 77
103/* Vector of 3 elements. Each element is an alist for one of font 78/* Vector of 3 elements. Each element is a vector for one of font
104 style properties (weight, slant, width). Each alist contains a 79 style properties (weight, slant, width). The vector contains a
105 mapping between symbolic property values (e.g. `medium' for weight) 80 mapping between symbolic property values (e.g. `medium' for weight)
106 and numeric property values (e.g. 100). So, it looks like this: 81 and numeric property values (e.g. 100). So, it looks like this:
107 [((thin . 0) ... (heavy . 210)) 82 [[(ultra-light . 20) ... (black . 210)]
108 ((ro . 0) ... (ot . 210)) 83 [(reverse-oblique . 0) ... (oblique . 210)]
109 ((ultracondensed . 50) ... (wide . 200))] */ 84 [(ultra-contains . 50) ... (wide . 200)]] */
110static Lisp_Object font_style_table; 85static Lisp_Object font_style_table;
111 86
112/* Alist of font family vs the corresponding aliases. 87extern Lisp_Object Qnormal;
113 Each element has this form:
114 (FAMILY ALIAS1 ALIAS2 ...) */
115
116static Lisp_Object font_family_alist;
117 88
118/* Symbols representing keys of normal font properties. */ 89/* Symbols representing keys of normal font properties. */
119extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth, QCsize, QCname; 90extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth, QCsize, QCname;
120Lisp_Object QCfoundry, QCadstyle, QCregistry, QCextra; 91Lisp_Object QCfoundry, QCadstyle, QCregistry;
121/* Symbols representing keys of font extra info. */ 92/* Symbols representing keys of font extra info. */
122Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClanguage, QCscript; 93Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
123Lisp_Object QCantialias; 94Lisp_Object QCantialias, QCfont_entity, QCfc_unknown_spec;
124/* Symbols representing values of font spacing property. */ 95/* Symbols representing values of font spacing property. */
125Lisp_Object Qc, Qm, Qp, Qd; 96Lisp_Object Qc, Qm, Qp, Qd;
126 97
@@ -147,16 +118,92 @@ static Lisp_Object font_charset_alist;
147 here. */ 118 here. */
148static struct font_driver_list *font_driver_list; 119static struct font_driver_list *font_driver_list;
149 120
121
122
123/* Creaters of font-related Lisp object. */
124
125Lisp_Object
126font_make_spec ()
127{
128 Lisp_Object font_spec;
129 struct font_spec *spec
130 = ((struct font_spec *)
131 allocate_pseudovector (VECSIZE (struct font_spec),
132 FONT_SPEC_MAX, PVEC_FONT));
133 XSETFONT (font_spec, spec);
134 return font_spec;
135}
136
137Lisp_Object
138font_make_entity ()
139{
140 Lisp_Object font_entity;
141 struct font_entity *entity
142 = ((struct font_entity *)
143 allocate_pseudovector (VECSIZE (struct font_entity),
144 FONT_ENTITY_MAX, PVEC_FONT));
145 XSETFONT (font_entity, entity);
146 return font_entity;
147}
148
149Lisp_Object
150font_make_object (size)
151 int size;
152{
153 Lisp_Object font_object;
154 struct font *font
155 = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX, PVEC_FONT);
156 XSETFONT (font_object, font);
157
158 return font_object;
159}
160
161
162
150static int font_pixel_size P_ ((FRAME_PTR f, Lisp_Object)); 163static int font_pixel_size P_ ((FRAME_PTR f, Lisp_Object));
151static Lisp_Object prop_name_to_numeric P_ ((enum font_property_index,
152 Lisp_Object));
153static Lisp_Object prop_numeric_to_name P_ ((enum font_property_index, int));
154static Lisp_Object font_open_entity P_ ((FRAME_PTR, Lisp_Object, int)); 164static Lisp_Object font_open_entity P_ ((FRAME_PTR, Lisp_Object, int));
155static void build_font_family_alist P_ ((void)); 165static Lisp_Object font_matching_entity P_ ((FRAME_PTR, Lisp_Object *,
166 Lisp_Object));
156 167
157/* Number of registered font drivers. */ 168/* Number of registered font drivers. */
158static int num_font_drivers; 169static int num_font_drivers;
159 170
171
172/* Return a Lispy value of a font property value at STR and LEN bytes.
173 If STR is "*", it returns nil.
174 If all characters in STR are digits, it returns an integer.
175 Otherwise, it returns a symbol interned from STR. */
176
177Lisp_Object
178font_intern_prop (str, len)
179 char *str;
180 int len;
181{
182 int i;
183 Lisp_Object tem, string;
184 Lisp_Object obarray;
185
186 if (len == 1 && *str == '*')
187 return Qnil;
188 if (len >=1 && isdigit (*str))
189 {
190 for (i = 1; i < len; i++)
191 if (! isdigit (str[i]))
192 break;
193 if (i == len)
194 return make_number (atoi (str));
195 }
196
197 /* The following code is copied from the function intern (in lread.c). */
198 obarray = Vobarray;
199 if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
200 obarray = check_obarray (obarray);
201 tem = oblookup (obarray, str, len, len);
202 if (SYMBOLP (tem))
203 return tem;
204 return Fintern (make_unibyte_string (str, len), obarray);
205}
206
160/* Return a pixel size of font-spec SPEC on frame F. */ 207/* Return a pixel size of font-spec SPEC on frame F. */
161 208
162static int 209static int
@@ -166,126 +213,123 @@ font_pixel_size (f, spec)
166{ 213{
167 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX); 214 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
168 double point_size; 215 double point_size;
169 int pixel_size, dpi; 216 int dpi, pixel_size;
170 Lisp_Object extra, val; 217 Lisp_Object extra, val;
171 218
172 if (INTEGERP (size)) 219 if (INTEGERP (size))
173 return XINT (size); 220 return XINT (size);
174 if (NILP (size)) 221 if (NILP (size))
175 return 0; 222 return 0; xassert (FLOATP (size));
176 point_size = XFLOAT_DATA (size); 223 point_size = XFLOAT_DATA (size);
177 extra = AREF (spec, FONT_EXTRA_INDEX); 224 val = AREF (spec, FONT_DPI_INDEX);
178 val = assq_no_quit (QCdpi, extra); 225 if (INTEGERP (val))
179 if (CONSP (val)) 226 dpi = XINT (XCDR (val));
180 {
181 if (INTEGERP (XCDR (val)))
182 dpi = XINT (XCDR (val));
183 else
184 dpi = XFLOAT_DATA (XCDR (val)) + 0.5;
185 }
186 else 227 else
187 dpi = f->resy; 228 dpi = f->resy;
188 pixel_size = POINT_TO_PIXEL (point_size, dpi); 229 pixel_size = POINT_TO_PIXEL (point_size, dpi);
189 return pixel_size; 230 return pixel_size;
190} 231}
191 232
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. */
195
196static Lisp_Object
197prop_name_to_numeric (prop, name)
198 enum font_property_index prop;
199 Lisp_Object name;
200{
201 int table_index = prop - FONT_WEIGHT_INDEX;
202 Lisp_Object val;
203 233
204 val = assq_no_quit (name, AREF (font_style_table, table_index)); 234/* Return a value of PROP's VAL (symbol or integer) to be stored in a
205 return (NILP (val) ? Qnil : XCDR (val)); 235 font vector. If VAL is not valid (i.e. not registered in
206} 236 font_style_table), return -1 if NOERROR is zero, and return a
237 proper index if NOERROR is nonzero. In that case, register VAL in
238 font_style_table if VAL is a symbol, and return a closest index if
239 VAL is an integer. */
207 240
208 241int
209/* Return a name (symbol) corresponding to PROP's NUMERIC value. If 242font_style_to_value (prop, val, noerror)
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. */
213
214static Lisp_Object
215prop_numeric_to_name (prop, numeric)
216 enum font_property_index prop; 243 enum font_property_index prop;
217 int numeric; 244 Lisp_Object val;
245 int noerror;
218{ 246{
219 int table_index = prop - FONT_WEIGHT_INDEX; 247 Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
220 Lisp_Object table = AREF (font_style_table, table_index); 248 int len = ASIZE (table);
221 char buf[10]; 249 int i;
222 250
223 while (! NILP (table)) 251 if (SYMBOLP (val))
224 { 252 {
225 if (XINT (XCDR (XCAR (table))) >= numeric) 253 char *s;
254 Lisp_Object args[2], elt;
255
256 /* At first try exact match. */
257 for (i = 0; i < len; i++)
258 if (EQ (val, XCAR (AREF (table, i))))
259 return (XINT (XCDR (AREF (table, i))) << 8) | i;
260 /* Try also with case-folding match. */
261 s = SDATA (SYMBOL_NAME (val));
262 for (i = 0; i < len; i++)
226 { 263 {
227 if (XINT (XCDR (XCAR (table))) == numeric) 264 elt = XCAR (AREF (table, i));
228 return XCAR (XCAR (table)); 265 if (strcasecmp (s, (char *) SDATA (SYMBOL_NAME (elt))) == 0)
229 else 266 return i;
230 break;
231 } 267 }
232 table = XCDR (table); 268 if (! noerror)
269 return -1;
270 if (len == 255)
271 abort ();
272 args[0] = table;
273 args[1] = Fmake_vector (make_number (1), Fcons (val, make_number (255)));
274 ASET (font_style_table, prop - FONT_WEIGHT_INDEX, Fvconcat (2, args));
275 return (255 << 8) | i;
233 } 276 }
234 sprintf (buf, "%d", numeric); 277 else
235 return intern (buf); 278 {
236} 279 int last_i, i, last_n;
280 int numeric = XINT (val);
237 281
282 for (i = 1, last_i = last_n = -1; i < len;)
283 {
284 int n = XINT (XCDR (AREF (table, i)));
238 285
239/* Return a symbol whose name is STR (length LEN). If STR contains 286 if (numeric == n)
240 uppercase letters, downcase them in advance. */ 287 return (n << 8) | i;
288 if (numeric < n)
289 {
290 if (! noerror)
291 return -1;
292 return ((last_i < 0 || n - numeric < numeric - last_n)
293 ? (n << 8) | i : (last_n << 8 | last_i));
294 }
295 last_i = i;
296 last_n = n;
297 for (i++; i < len && n == XINT (XCDR (AREF (table, i + 1))); i++);
298 }
299 if (! noerror)
300 return -1;
301 return (last_n << 8) | last_i;
302 }
303}
241 304
242Lisp_Object 305Lisp_Object
243intern_downcase (str, len) 306font_style_symbolic (font, prop, for_face)
244 char *str; 307 Lisp_Object font;
245 int len; 308 enum font_property_index prop;
309 int for_face;
246{ 310{
247 char *buf; 311 Lisp_Object val = AREF (font, prop);
248 int i; 312 Lisp_Object table;
313 int i, numeric;
249 314
250 for (i = 0; i < len; i++) 315 if (NILP (val))
251 if (isupper (str[i])) 316 return Qnil;
252 break; 317 table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
253 if (i == len) 318 if (! for_face)
254 return Fintern (make_unibyte_string (str, len), Qnil); 319 return XCAR (AREF (table, XINT (val) & 0xFF));
255 buf = alloca (len); 320 numeric = XINT (val) >> 8;
256 if (! buf) 321 for (i = 0; i < ASIZE (table); i++)
257 return Fintern (null_string, Qnil); 322 if (XINT (XCDR (AREF (table, i))) == numeric)
258 bcopy (str, buf, len); 323 return XCAR (AREF (table, i));
259 for (; i < len; i++) 324 abort ();
260 if (isascii (buf[i])) 325 return Qnil;
261 buf[i] = tolower (buf[i]);
262 return Fintern (make_unibyte_string (buf, len), Qnil);
263} 326}
264 327
265extern Lisp_Object Vface_alternative_font_family_alist; 328extern Lisp_Object Vface_alternative_font_family_alist;
266 329
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 ...) ...) */
271
272static void
273build_font_family_alist ()
274{
275 Lisp_Object alist = Vface_alternative_font_family_alist;
276
277 for (; CONSP (alist); alist = XCDR (alist))
278 {
279 Lisp_Object tail, elt;
280
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);
284 }
285}
286
287extern Lisp_Object find_font_encoding P_ ((Lisp_Object)); 330extern Lisp_Object find_font_encoding P_ ((Lisp_Object));
288 331
332
289/* Return encoding charset and repertory charset for REGISTRY in 333/* Return encoding charset and repertory charset for REGISTRY in
290 ENCODING and REPERTORY correspondingly. If correct information for 334 ENCODING and REPERTORY correspondingly. If correct information for
291 REGISTRY is available, return 0. Otherwise return -1. */ 335 REGISTRY is available, return 0. Otherwise return -1. */
@@ -298,7 +342,7 @@ font_registry_charsets (registry, encoding, repertory)
298 Lisp_Object val; 342 Lisp_Object val;
299 int encoding_id, repertory_id; 343 int encoding_id, repertory_id;
300 344
301 val = assq_no_quit (registry, font_charset_alist); 345 val = Fassoc_string (registry, font_charset_alist, Qt);
302 if (! NILP (val)) 346 if (! NILP (val))
303 { 347 {
304 val = XCDR (val); 348 val = XCDR (val);
@@ -351,54 +395,56 @@ font_registry_charsets (registry, encoding, repertory)
351/* Font property value validaters. See the comment of 395/* Font property value validaters. See the comment of
352 font_property_table for the meaning of the arguments. */ 396 font_property_table for the meaning of the arguments. */
353 397
398static Lisp_Object font_prop_validate P_ ((int, Lisp_Object, Lisp_Object));
354static Lisp_Object font_prop_validate_symbol P_ ((Lisp_Object, Lisp_Object)); 399static Lisp_Object font_prop_validate_symbol P_ ((Lisp_Object, Lisp_Object));
355static Lisp_Object font_prop_validate_style P_ ((Lisp_Object, Lisp_Object)); 400static Lisp_Object font_prop_validate_style P_ ((Lisp_Object, Lisp_Object));
356static Lisp_Object font_prop_validate_non_neg P_ ((Lisp_Object, Lisp_Object)); 401static Lisp_Object font_prop_validate_non_neg P_ ((Lisp_Object, Lisp_Object));
357static Lisp_Object font_prop_validate_spacing P_ ((Lisp_Object, Lisp_Object)); 402static Lisp_Object font_prop_validate_spacing P_ ((Lisp_Object, Lisp_Object));
358static int get_font_prop_index P_ ((Lisp_Object, int)); 403static int get_font_prop_index P_ ((Lisp_Object));
359static Lisp_Object font_prop_validate P_ ((Lisp_Object));
360 404
361static Lisp_Object 405static Lisp_Object
362font_prop_validate_symbol (prop, val) 406font_prop_validate_symbol (prop, val)
363 Lisp_Object prop, val; 407 Lisp_Object prop, val;
364{ 408{
365 if (EQ (prop, QCotf))
366 return (SYMBOLP (val) ? val : Qerror);
367 if (STRINGP (val)) 409 if (STRINGP (val))
368 val = (SCHARS (val) == 0 ? null_string 410 val = Fintern (val, Qnil);
369 : intern_downcase ((char *) SDATA (val), SBYTES (val))); 411 if (! SYMBOLP (val))
370 else if (SYMBOLP (val))
371 {
372 if (SCHARS (SYMBOL_NAME (val)) == 0)
373 val = null_string;
374 }
375 else
376 val = Qerror; 412 val = Qerror;
413 else if (EQ (prop, QCregistry))
414 val = Fintern (Fdowncase (SYMBOL_NAME (val)), Qnil);
377 return val; 415 return val;
378} 416}
379 417
418
380static Lisp_Object 419static Lisp_Object
381font_prop_validate_style (prop, val) 420font_prop_validate_style (style, val)
382 Lisp_Object prop, val; 421 Lisp_Object style, val;
383{ 422{
384 if (! INTEGERP (val)) 423 enum font_property_index prop = (EQ (style, QCweight) ? FONT_WEIGHT_INDEX
424 : EQ (style, QCslant) ? FONT_SLANT_INDEX
425 : FONT_WIDTH_INDEX);
426 int n;
427 if (INTEGERP (val))
385 { 428 {
386 if (STRINGP (val)) 429 n = XINT (val);
387 val = intern_downcase ((char *) SDATA (val), SBYTES (val)); 430 if ((n & 0xFF)
388 if (! SYMBOLP (val)) 431 >= ASIZE (AREF (font_style_table, prop - FONT_WEIGHT_INDEX)))
389 val = Qerror; 432 val = Qerror;
390 else 433 else
391 { 434 {
392 enum font_property_index prop_index 435 Lisp_Object elt = AREF (AREF (font_style_table, prop - FONT_WEIGHT_INDEX), n & 0xFF);
393 = (EQ (prop, QCweight) ? FONT_WEIGHT_INDEX 436 if (XINT (XCDR (elt)) != (n >> 8))
394 : EQ (prop, QCslant) ? FONT_SLANT_INDEX
395 : FONT_WIDTH_INDEX);
396
397 val = prop_name_to_numeric (prop_index, val);
398 if (NILP (val))
399 val = Qerror; 437 val = Qerror;
400 } 438 }
401 } 439 }
440 else if (SYMBOLP (val))
441 {
442 int n = font_style_to_value (prop, val, 0);
443
444 val = n >= 0 ? make_number (n) : Qerror;
445 }
446 else
447 val = Qerror;
402 return val; 448 return val;
403} 449}
404 450
@@ -422,6 +468,8 @@ font_prop_validate_spacing (prop, val)
422 return make_number (FONT_SPACING_MONO); 468 return make_number (FONT_SPACING_MONO);
423 if (EQ (val, Qp)) 469 if (EQ (val, Qp))
424 return make_number (FONT_SPACING_PROPORTIONAL); 470 return make_number (FONT_SPACING_PROPORTIONAL);
471 if (EQ (val, Qd))
472 return make_number (FONT_SPACING_DUAL);
425 return Qerror; 473 return Qerror;
426} 474}
427 475
@@ -480,13 +528,14 @@ struct
480 { &QCslant, font_prop_validate_style }, 528 { &QCslant, font_prop_validate_style },
481 { &QCwidth, font_prop_validate_style }, 529 { &QCwidth, font_prop_validate_style },
482 { &QCsize, font_prop_validate_non_neg }, 530 { &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 }, 531 { &QCdpi, font_prop_validate_non_neg },
486 { &QCspacing, font_prop_validate_spacing }, 532 { &QCspacing, font_prop_validate_spacing },
487 { &QCscalable, NULL }, 533 { &QCavgwidth, font_prop_validate_non_neg },
488 { &QCotf, font_prop_validate_otf }, 534 /* The order of the above entries must match with enum
489 { &QCantialias, font_prop_validate_symbol } 535 font_property_index. */
536 { &QClang, font_prop_validate_symbol },
537 { &QCscript, font_prop_validate_symbol },
538 { &QCotf, font_prop_validate_otf }
490 }; 539 };
491 540
492/* Size (number of elements) of the above table. */ 541/* Size (number of elements) of the above table. */
@@ -494,63 +543,48 @@ struct
494 ((sizeof font_property_table) / (sizeof *font_property_table)) 543 ((sizeof font_property_table) / (sizeof *font_property_table))
495 544
496/* Return an index number of font property KEY or -1 if KEY is not an 545/* 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 546 already known property. */
498 index FROM (which is 0 or FONT_EXTRA_INDEX). */
499 547
500static int 548static int
501get_font_prop_index (key, from) 549get_font_prop_index (key)
502 Lisp_Object key; 550 Lisp_Object key;
503 int from;
504{ 551{
505 for (; from < FONT_PROPERTY_TABLE_SIZE; from++) 552 int i;
506 if (EQ (key, *font_property_table[from].key)) 553
507 return from; 554 for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++)
555 if (EQ (key, *font_property_table[i].key))
556 return i;
508 return -1; 557 return -1;
509} 558}
510 559
511/* Validate font properties in SPEC (vector) while updating elements 560/* Validate the font property. The property key is specified by the
512 to regularized values. Signal an error if an invalid property is 561 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
513 found. */ 562 signal an error. The value is VAL or the regularized one. */
514 563
515static Lisp_Object 564static Lisp_Object
516font_prop_validate (spec) 565font_prop_validate (idx, prop, val)
517 Lisp_Object spec; 566 int idx;
567 Lisp_Object prop, val;
518{ 568{
519 int i; 569 Lisp_Object validated;
520 Lisp_Object prop, val, extra;
521 570
522 for (i = FONT_TYPE_INDEX; i < FONT_EXTRA_INDEX; i++) 571 if (NILP (prop))
523 { 572 prop = *font_property_table[idx].key;
524 if (! NILP (AREF (spec, i))) 573 else
525 {
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))));
531 ASET (spec, i, val);
532 }
533 }
534 for (extra = AREF (spec, FONT_EXTRA_INDEX);
535 CONSP (extra); extra = XCDR (extra))
536 { 574 {
537 Lisp_Object elt = XCAR (extra); 575 idx = get_font_prop_index (prop);
538 576 if (idx < 0)
539 prop = XCAR (elt); 577 return val;
540 i = get_font_prop_index (prop, FONT_EXTRA_INDEX);
541 if (i >= 0
542 && font_property_table[i].validater)
543 {
544 val = (font_property_table[i].validater) (prop, XCDR (elt));
545 if (EQ (val, Qerror))
546 signal_error ("invalid font property", elt);
547 XSETCDR (elt, val);
548 }
549 } 578 }
550 return spec; 579 validated = (font_property_table[idx].validater) (prop, val);
580 if (EQ (validated, Qerror))
581 signal_error ("invalid font property", Fcons (prop, val));
582 return validated;
551} 583}
552 584
553/* Store VAL as a value of extra font property PROP in FONT. */ 585
586/* Store VAL as a value of extra font property PROP in FONT while
587 keeping the sorting order. Don't check the validity of VAL. */
554 588
555Lisp_Object 589Lisp_Object
556font_put_extra (font, prop, val) 590font_put_extra (font, prop, val)
@@ -561,8 +595,15 @@ font_put_extra (font, prop, val)
561 595
562 if (NILP (slot)) 596 if (NILP (slot))
563 { 597 {
564 extra = Fcons (Fcons (prop, val), extra); 598 Lisp_Object prev = Qnil;
565 ASET (font, FONT_EXTRA_INDEX, extra); 599
600 while (CONSP (extra)
601 && NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
602 prev = extra, extra = XCDR (extra);
603 if (NILP (prev))
604 ASET (font, FONT_EXTRA_INDEX, Fcons (Fcons (prop, val), extra));
605 else
606 XSETCDR (prev, Fcons (Fcons (prop, val), extra));
566 return val; 607 return val;
567 } 608 }
568 XSETCDR (slot, val); 609 XSETCDR (slot, val);
@@ -572,7 +613,6 @@ font_put_extra (font, prop, val)
572 613
573/* Font name parser and unparser */ 614/* Font name parser and unparser */
574 615
575static Lisp_Object intern_font_field P_ ((char *, int));
576static int parse_matrix P_ ((char *)); 616static int parse_matrix P_ ((char *));
577static int font_expand_wildcards P_ ((Lisp_Object *, int)); 617static int font_expand_wildcards P_ ((Lisp_Object *, int));
578static int font_parse_name P_ ((char *, Lisp_Object)); 618static int font_parse_name P_ ((char *, Lisp_Object));
@@ -617,34 +657,6 @@ enum xlfd_field_mask
617}; 657};
618 658
619 659
620/* Return a Lispy value of a XLFD font field at STR and LEN bytes.
621 If LEN is zero, it returns `null_string'.
622 If STR is "*", it returns nil.
623 If all characters in STR are digits, it returns an integer.
624 Otherwise, it returns a symbol interned from downcased STR. */
625
626static Lisp_Object
627intern_font_field (str, len)
628 char *str;
629 int len;
630{
631 int i;
632
633 if (len == 0)
634 return null_string;
635 if (*str == '*' && len == 1)
636 return Qnil;
637 if (isdigit (*str))
638 {
639 for (i = 1; i < len; i++)
640 if (! isdigit (str[i]))
641 break;
642 if (i == len)
643 return make_number (atoi (str));
644 }
645 return intern_downcase (str, len);
646}
647
648/* Parse P pointing the pixel/point size field of the form 660/* Parse P pointing the pixel/point size field of the form
649 `[A B C D]' which specifies a transformation matrix: 661 `[A B C D]' which specifies a transformation matrix:
650 662
@@ -755,7 +767,7 @@ font_expand_wildcards (field, n)
755 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX, 767 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
756 mask = XLFD_LARGENUM_MASK; 768 mask = XLFD_LARGENUM_MASK;
757 } 769 }
758 else if (EQ (val, null_string)) 770 else if (SBYTES (SYMBOL_NAME (val)) == 0)
759 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX, 771 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
760 mask = XLFD_NULL_MASK; 772 mask = XLFD_NULL_MASK;
761 else if (i == 0) 773 else if (i == 0)
@@ -773,15 +785,15 @@ font_expand_wildcards (field, n)
773 } 785 }
774 else if (range_from <= XLFD_WEIGHT_INDEX 786 else if (range_from <= XLFD_WEIGHT_INDEX
775 && range_to >= XLFD_WEIGHT_INDEX 787 && range_to >= XLFD_WEIGHT_INDEX
776 && !NILP (prop_name_to_numeric (FONT_WEIGHT_INDEX, val))) 788 && FONT_WEIGHT_NAME_NUMERIC (val) >= 0)
777 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK; 789 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
778 else if (range_from <= XLFD_SLANT_INDEX 790 else if (range_from <= XLFD_SLANT_INDEX
779 && range_to >= XLFD_SLANT_INDEX 791 && range_to >= XLFD_SLANT_INDEX
780 && !NILP (prop_name_to_numeric (FONT_SLANT_INDEX, val))) 792 && FONT_SLANT_NAME_NUMERIC (val) >= 0)
781 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK; 793 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
782 else if (range_from <= XLFD_SWIDTH_INDEX 794 else if (range_from <= XLFD_SWIDTH_INDEX
783 && range_to >= XLFD_SWIDTH_INDEX 795 && range_to >= XLFD_SWIDTH_INDEX
784 && !NILP (prop_name_to_numeric (FONT_WIDTH_INDEX, val))) 796 && FONT_WIDTH_NAME_NUMERIC (val) >= 0)
785 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK; 797 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
786 else 798 else
787 { 799 {
@@ -902,6 +914,7 @@ font_check_xlfd_parse (Lisp_Object font, char *name)
902 914
903#endif 915#endif
904 916
917
905/* Parse NAME (null terminated) as XLFD and store information in FONT 918/* Parse NAME (null terminated) as XLFD and store information in FONT
906 (font-spec or font-entity). Size property of FONT is set as 919 (font-spec or font-entity). Size property of FONT is set as
907 follows: 920 follows:
@@ -915,9 +928,7 @@ font_check_xlfd_parse (Lisp_Object font, char *name)
915 928
916 FONT is usually a font-spec, but when this function is called from 929 FONT is usually a font-spec, but when this function is called from
917 X font backend driver, it is a font-entity. In that case, NAME is 930 X font backend driver, it is a font-entity. In that case, NAME is
918 a fully specified XLFD, and we set FONT_EXTRA_INDEX of FONT to a 931 a fully specified XLFD. */
919 symbol RESX-RESY-SPACING-AVGWIDTH.
920*/
921 932
922int 933int
923font_parse_xlfd (name, font) 934font_parse_xlfd (name, font)
@@ -925,9 +936,7 @@ font_parse_xlfd (name, font)
925 Lisp_Object font; 936 Lisp_Object font;
926{ 937{
927 int len = strlen (name); 938 int len = strlen (name);
928 int i, j; 939 int i, j, n;
929 Lisp_Object dpi, spacing;
930 int avgwidth;
931 char *f[XLFD_LAST_INDEX + 1]; 940 char *f[XLFD_LAST_INDEX + 1];
932 Lisp_Object val; 941 Lisp_Object val;
933 char *p; 942 char *p;
@@ -941,52 +950,49 @@ font_parse_xlfd (name, font)
941 else 950 else
942 i = 0; 951 i = 0;
943 for (p = name + i; *p; p++) 952 for (p = name + i; *p; p++)
944 if (*p == '-' && i < XLFD_LAST_INDEX) 953 if (*p == '-')
945 f[i++] = p + 1; 954 {
946 f[i] = p; 955 f[i++] = p + 1;
956 if (i == XLFD_LAST_INDEX)
957 break;
958 }
959 f[i] = name + len;
947 960
948 dpi = spacing = Qnil; 961#define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N])
949 avgwidth = -1;
950 962
951 if (i == XLFD_LAST_INDEX) 963 if (i == XLFD_LAST_INDEX)
952 { 964 {
965 /* Fully specified XLFD. */
953 int pixel_size; 966 int pixel_size;
967 int spacing_char;
954 968
955 /* Fully specified XLFD. */ 969 ASET (font, FONT_FOUNDRY_INDEX, INTERN_FIELD (XLFD_FOUNDRY_INDEX));
956 for (i = 0, j = FONT_FOUNDRY_INDEX; i < XLFD_WEIGHT_INDEX; i++, j++) 970 ASET (font, FONT_FAMILY_INDEX, INTERN_FIELD (XLFD_FAMILY_INDEX));
957 { 971 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
958 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]); 972 i <= XLFD_SWIDTH_INDEX; i++, j++)
959 if (! NILP (val))
960 ASET (font, j, val);
961 }
962 for (j = FONT_WEIGHT_INDEX; i < XLFD_ADSTYLE_INDEX; i++, j++)
963 { 973 {
964 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]); 974 val = INTERN_FIELD (i);
965 if (! NILP (val)) 975 if (! NILP (val))
966 { 976 {
967 Lisp_Object numeric = prop_name_to_numeric (j, val); 977 if ((n = font_style_to_value (j, INTERN_FIELD (i), 0)) < 0)
968 978 return -1;
969 if (INTEGERP (numeric)) 979 ASET (font, j, make_number (n));
970 val = numeric;
971 ASET (font, j, val);
972 } 980 }
973 } 981 }
974 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]); 982 ASET (font, FONT_ADSTYLE_INDEX, INTERN_FIELD (XLFD_ADSTYLE_INDEX));
975 if (! NILP (val)) 983 if (strcmp (f[XLFD_REGISTRY_INDEX], "*-*") == 0)
976 ASET (font, FONT_ADSTYLE_INDEX, val); 984 ASET (font, FONT_REGISTRY_INDEX, Qnil);
977 i = XLFD_REGISTRY_INDEX; 985 else
978 val = intern_font_field (f[i], f[i + 2] - f[i]); 986 ASET (font, FONT_REGISTRY_INDEX,
979 if (! NILP (val)) 987 font_intern_prop (f[XLFD_REGISTRY_INDEX],
980 ASET (font, FONT_REGISTRY_INDEX, val); 988 f[XLFD_LAST_INDEX] - f[XLFD_REGISTRY_INDEX]));
981
982 p = f[XLFD_PIXEL_INDEX]; 989 p = f[XLFD_PIXEL_INDEX];
983 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0) 990 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
984 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size)); 991 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
985 else 992 else
986 { 993 {
987 i = XLFD_PIXEL_INDEX; 994 val = INTERN_FIELD (XLFD_PIXEL_INDEX);
988 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]); 995 if (INTEGERP (val))
989 if (! NILP (val))
990 ASET (font, FONT_SIZE_INDEX, val); 996 ASET (font, FONT_SIZE_INDEX, val);
991 else 997 else
992 { 998 {
@@ -1000,43 +1006,31 @@ font_parse_xlfd (name, font)
1000 point_size = atoi (p), point_size /= 10; 1006 point_size = atoi (p), point_size /= 10;
1001 if (point_size >= 0) 1007 if (point_size >= 0)
1002 ASET (font, FONT_SIZE_INDEX, make_float (point_size)); 1008 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1003 else
1004 {
1005 i = XLFD_PIXEL_INDEX;
1006 val = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
1007 if (! NILP (val))
1008 ASET (font, FONT_SIZE_INDEX, val);
1009 }
1010 } 1009 }
1011 } 1010 }
1012 1011
1013 /* Parse RESX, RESY, SPACING, and AVGWIDTH. */ 1012 ASET (font, FONT_DPI_INDEX, INTERN_FIELD (XLFD_RESY_INDEX));
1014 if (FONT_ENTITY_P (font)) 1013 val = INTERN_FIELD (XLFD_SPACING_INDEX);
1014 if (! NILP (val))
1015 { 1015 {
1016 i = XLFD_RESX_INDEX; 1016 val = font_prop_validate_spacing (QCspacing, val);
1017 ASET (font, FONT_EXTRA_INDEX, 1017 if (! INTEGERP (val))
1018 intern_font_field (f[i], f[XLFD_REGISTRY_INDEX] - 1 - f[i])); 1018 return -1;
1019 eassert (font_check_xlfd_parse (font, name)); 1019 ASET (font, FONT_SPACING_INDEX, val);
1020 return 0;
1021 } 1020 }
1022
1023 /* Here we just setup DPI, SPACING, and AVGWIDTH. They are set
1024 in FONT_EXTRA_INDEX later. */
1025 i = XLFD_RESX_INDEX;
1026 dpi = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
1027 i = XLFD_SPACING_INDEX;
1028 spacing = intern_font_field (f[i], f[i + 1] - 1 - f[i]);
1029 p = f[XLFD_AVGWIDTH_INDEX]; 1021 p = f[XLFD_AVGWIDTH_INDEX];
1030 if (*p == '~') 1022 if (*p == '~')
1031 p++; 1023 p++;
1032 if (isdigit (*p)) 1024 ASET (font, FONT_AVGWIDTH_INDEX,
1033 avgwidth = atoi (p); 1025 font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p));
1034 } 1026 }
1035 else 1027 else
1036 { 1028 {
1037 int wild_card_found = 0; 1029 int wild_card_found = 0;
1038 Lisp_Object prop[XLFD_LAST_INDEX]; 1030 Lisp_Object prop[XLFD_LAST_INDEX];
1039 1031
1032 if (FONT_ENTITY_P (font))
1033 return -1;
1040 for (j = 0; j < i; j++) 1034 for (j = 0; j < i; j++)
1041 { 1035 {
1042 if (*f[j] == '*') 1036 if (*f[j] == '*')
@@ -1046,49 +1040,41 @@ font_parse_xlfd (name, font)
1046 prop[j] = Qnil; 1040 prop[j] = Qnil;
1047 wild_card_found = 1; 1041 wild_card_found = 1;
1048 } 1042 }
1049 else if (isdigit (*f[j]))
1050 {
1051 for (p = f[j] + 1; isdigit (*p); p++);
1052 if (*p && *p != '-')
1053 prop[j] = intern_downcase (f[j], p - f[j]);
1054 else
1055 prop[j] = make_number (atoi (f[j]));
1056 }
1057 else if (j + 1 < i) 1043 else if (j + 1 < i)
1058 prop[j] = intern_font_field (f[j], f[j + 1] - 1 - f[j]); 1044 prop[j] = INTERN_FIELD (j);
1059 else 1045 else
1060 prop[j] = intern_font_field (f[j], f[i] - f[j]); 1046 prop[j] = font_intern_prop (f[j], f[i] - f[j]);
1061 } 1047 }
1062 if (! wild_card_found) 1048 if (! wild_card_found)
1063 return -1; 1049 return -1;
1064 if (font_expand_wildcards (prop, i) < 0) 1050 if (font_expand_wildcards (prop, i) < 0)
1065 return -1; 1051 return -1;
1066 1052
1067 for (i = 0, j = FONT_FOUNDRY_INDEX; i < XLFD_WEIGHT_INDEX; i++, j++) 1053 ASET (font, FONT_FOUNDRY_INDEX, prop[XLFD_FOUNDRY_INDEX]);
1068 if (! NILP (prop[i])) 1054 ASET (font, FONT_FAMILY_INDEX, prop[XLFD_FAMILY_INDEX]);
1069 ASET (font, j, prop[i]); 1055 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1070 for (j = FONT_WEIGHT_INDEX; i < XLFD_ADSTYLE_INDEX; i++, j++) 1056 i <= XLFD_SWIDTH_INDEX; i++, j++)
1071 if (! NILP (prop[i])) 1057 if (! NILP (prop[i]))
1072 ASET (font, j, prop[i]); 1058 {
1073 if (! NILP (prop[XLFD_ADSTYLE_INDEX])) 1059 if ((n = font_style_to_value (j, prop[i], 1)) < 0)
1074 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]); 1060 return -1;
1061 ASET (font, j, make_number (n));
1062 }
1063 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1075 val = prop[XLFD_REGISTRY_INDEX]; 1064 val = prop[XLFD_REGISTRY_INDEX];
1076 if (NILP (val)) 1065 if (NILP (val))
1077 { 1066 {
1078 val = prop[XLFD_ENCODING_INDEX]; 1067 val = prop[XLFD_ENCODING_INDEX];
1079 if (! NILP (val)) 1068 if (! NILP (val))
1080 val = Fintern (concat2 (build_string ("*-"), SYMBOL_NAME (val)), 1069 val = concat2 (build_string ("*-"), SYMBOL_NAME (val));
1081 Qnil);
1082 } 1070 }
1083 else if (NILP (prop[XLFD_ENCODING_INDEX])) 1071 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1084 val = Fintern (concat2 (SYMBOL_NAME (val), build_string ("-*")), 1072 val = concat2 (SYMBOL_NAME (val), build_string ("-*"));
1085 Qnil);
1086 else 1073 else
1087 val = Fintern (concat3 (SYMBOL_NAME (val), build_string ("-"), 1074 val = concat3 (SYMBOL_NAME (val), build_string ("-"),
1088 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX])), 1075 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX]));
1089 Qnil);
1090 if (! NILP (val)) 1076 if (! NILP (val))
1091 ASET (font, FONT_REGISTRY_INDEX, val); 1077 ASET (font, FONT_REGISTRY_INDEX, Fintern (val, Qnil));
1092 1078
1093 if (INTEGERP (prop[XLFD_PIXEL_INDEX])) 1079 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1094 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]); 1080 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
@@ -1099,19 +1085,20 @@ font_parse_xlfd (name, font)
1099 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10)); 1085 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1100 } 1086 }
1101 1087
1102 dpi = prop[XLFD_RESX_INDEX]; 1088 if (INTEGERP (prop[XLFD_RESX_INDEX]))
1103 spacing = prop[XLFD_SPACING_INDEX]; 1089 ASET (font, FONT_DPI_INDEX, prop[XLFD_RESY_INDEX]);
1090 if (! NILP (prop[XLFD_SPACING_INDEX]))
1091 {
1092 val = font_prop_validate_spacing (QCspacing,
1093 prop[XLFD_SPACING_INDEX]);
1094 if (! INTEGERP (val))
1095 return -1;
1096 ASET (font, FONT_SPACING_INDEX, val);
1097 }
1104 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX])) 1098 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1105 avgwidth = XINT (prop[XLFD_AVGWIDTH_INDEX]); 1099 ASET (font, FONT_AVGWIDTH_INDEX, prop[XLFD_AVGWIDTH_INDEX]);
1106 } 1100 }
1107 1101
1108 if (! NILP (dpi))
1109 font_put_extra (font, QCdpi, dpi);
1110 if (! NILP (spacing))
1111 font_put_extra (font, QCspacing, spacing);
1112 if (avgwidth >= 0)
1113 font_put_extra (font, QCscalable, avgwidth == 0 ? Qt : Qnil);
1114
1115 return 0; 1102 return 0;
1116} 1103}
1117 1104
@@ -1176,16 +1163,12 @@ font_unparse_xlfd (font, pixel_size, name, nbytes)
1176 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; 1163 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1177 i++, j++) 1164 i++, j++)
1178 { 1165 {
1179 val = AREF (font, i); 1166 val = font_style_symbolic (font, i, 0);
1180 if (NILP (val)) 1167 if (NILP (val))
1181 f[j] = "*", len += 2; 1168 f[j] = "*", len += 2;
1182 else 1169 else
1183 { 1170 {
1184 if (INTEGERP (val)) 1171 val = SYMBOL_NAME (val);
1185 val = prop_numeric_to_name (i, XINT (val));
1186 if (SYMBOLP (val))
1187 val = SYMBOL_NAME (val);
1188 xassert (STRINGP (val));
1189 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1; 1172 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1190 } 1173 }
1191 } 1174 }
@@ -1194,7 +1177,7 @@ font_unparse_xlfd (font, pixel_size, name, nbytes)
1194 xassert (NUMBERP (val) || NILP (val)); 1177 xassert (NUMBERP (val) || NILP (val));
1195 if (INTEGERP (val)) 1178 if (INTEGERP (val))
1196 { 1179 {
1197 int i = XINT (val); 1180 i = XINT (val);
1198 if (i <= 0) 1181 if (i <= 0)
1199 i = pixel_size; 1182 i = pixel_size;
1200 if (i > 0) 1183 if (i > 0)
@@ -1207,81 +1190,52 @@ font_unparse_xlfd (font, pixel_size, name, nbytes)
1207 } 1190 }
1208 else if (FLOATP (val)) 1191 else if (FLOATP (val))
1209 { 1192 {
1210 int i = XFLOAT_DATA (val) * 10; 1193 i = XFLOAT_DATA (val) * 10;
1211 f[XLFD_PIXEL_INDEX] = alloca (12); 1194 f[XLFD_PIXEL_INDEX] = alloca (12);
1212 len += sprintf (f[XLFD_PIXEL_INDEX], "*-%d", i) + 1; 1195 len += sprintf (f[XLFD_PIXEL_INDEX], "*-%d", i) + 1;
1213 } 1196 }
1214 else 1197 else
1215 f[XLFD_PIXEL_INDEX] = "*-*", len += 4; 1198 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1216 1199
1217 val = AREF (font, FONT_EXTRA_INDEX); 1200 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1218
1219 if (FONT_ENTITY_P (font)
1220 && EQ (AREF (font, FONT_TYPE_INDEX), Qx))
1221 { 1201 {
1222 /* Setup names for RESX-RESY-SPACING-AVWIDTH. */ 1202 i = XINT (AREF (font, FONT_DPI_INDEX));
1223 if (SYMBOLP (val) && ! NILP (val)) 1203 f[XLFD_RESX_INDEX] = alloca (22);
1224 { 1204 len += sprintf (f[XLFD_RESX_INDEX],
1225 val = SYMBOL_NAME (val); 1205 "%d-%d", i, i) + 1;
1226 f[XLFD_RESX_INDEX] = (char *) SDATA (val), len += SBYTES (val) + 1;
1227 }
1228 else
1229 f[XLFD_RESX_INDEX] = "*-*-*-*", len += 6;
1230 } 1206 }
1231 else 1207 else
1208 f[XLFD_RESX_INDEX] = "*-*", len += 4;
1209 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1232 { 1210 {
1233 Lisp_Object dpi = assq_no_quit (QCdpi, val); 1211 int spacing = XINT (AREF (font, FONT_SPACING_INDEX));
1234 Lisp_Object spacing = assq_no_quit (QCspacing, val);
1235 Lisp_Object scalable = assq_no_quit (QCscalable, val);
1236
1237 if (CONSP (dpi) || CONSP (spacing) || CONSP (scalable))
1238 {
1239 char *str = alloca (24);
1240 int this_len;
1241 1212
1242 if (CONSP (dpi) && INTEGERP (XCDR (dpi))) 1213 f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
1243 this_len = sprintf (str, "%d-%d", 1214 : spacing <= FONT_SPACING_DUAL ? "d"
1244 XINT (XCDR (dpi)), XINT (XCDR (dpi))); 1215 : spacing <= FONT_SPACING_MONO ? "m"
1245 else 1216 : "c");
1246 this_len = sprintf (str, "*-*"); 1217 len += 2;
1247 if (CONSP (spacing) && ! NILP (XCDR (spacing)))
1248 {
1249 val = XCDR (spacing);
1250 if (INTEGERP (val))
1251 {
1252 if (XINT (val) < FONT_SPACING_MONO)
1253 val = Qp;
1254 else if (XINT (val) < FONT_SPACING_CHARCELL)
1255 val = Qm;
1256 else
1257 val = Qc;
1258 }
1259 xassert (SYMBOLP (val));
1260 this_len += sprintf (str + this_len, "-%c",
1261 SDATA (SYMBOL_NAME (val))[0]);
1262 }
1263 else
1264 this_len += sprintf (str + this_len, "-*");
1265 if (CONSP (scalable) && ! NILP (XCDR (spacing)))
1266 this_len += sprintf (str + this_len, "-0");
1267 else
1268 this_len += sprintf (str + this_len, "-*");
1269 f[XLFD_RESX_INDEX] = str;
1270 len += this_len;
1271 }
1272 else
1273 f[XLFD_RESX_INDEX] = "*-*-*-*", len += 8;
1274 } 1218 }
1275 1219 else
1220 f[XLFD_SPACING_INDEX] = "*", len += 2;
1221 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1222 {
1223 f[XLFD_AVGWIDTH_INDEX] = alloca (11);
1224 len += sprintf (f[XLFD_AVGWIDTH_INDEX],
1225 "%d", XINT (AREF (font, FONT_AVGWIDTH_INDEX))) + 1;
1226 }
1227 else
1228 f[XLFD_AVGWIDTH_INDEX] = "*", len += 2;
1276 len++; /* for terminating '\0'. */ 1229 len++; /* for terminating '\0'. */
1277 if (len >= nbytes) 1230 if (len >= nbytes)
1278 return -1; 1231 return -1;
1279 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s", 1232 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1280 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX], 1233 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1281 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX], 1234 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1282 f[XLFD_SWIDTH_INDEX], 1235 f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
1283 f[XLFD_ADSTYLE_INDEX], f[XLFD_PIXEL_INDEX], 1236 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
1284 f[XLFD_RESX_INDEX], f[XLFD_REGISTRY_INDEX]); 1237 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
1238 f[XLFD_REGISTRY_INDEX]);
1285} 1239}
1286 1240
1287/* Parse NAME (null terminated) as Fonconfig's name format and store 1241/* Parse NAME (null terminated) as Fonconfig's name format and store
@@ -1296,8 +1250,6 @@ font_parse_fcname (name, font)
1296 char *p0, *p1; 1250 char *p0, *p1;
1297 int len = strlen (name); 1251 int len = strlen (name);
1298 char *copy; 1252 char *copy;
1299 int weight_set = 0;
1300 int slant_set = 0;
1301 1253
1302 if (len == 0) 1254 if (len == 0)
1303 return -1; 1255 return -1;
@@ -1312,7 +1264,7 @@ font_parse_fcname (name, font)
1312 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++) 1264 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++)
1313 if (*p0 == '\\' && p0[1]) 1265 if (*p0 == '\\' && p0[1])
1314 p0++; 1266 p0++;
1315 family = intern_font_field (name, p0 - name); 1267 family = font_intern_prop (name, p0 - name);
1316 if (*p0 == '-') 1268 if (*p0 == '-')
1317 { 1269 {
1318 if (! isdigit (p0[1])) 1270 if (! isdigit (p0[1]))
@@ -1333,7 +1285,8 @@ font_parse_fcname (name, font)
1333 name = copy; 1285 name = copy;
1334 1286
1335 /* Now parse ":KEY=VAL" patterns. Store known keys and values in 1287 /* Now parse ":KEY=VAL" patterns. Store known keys and values in
1336 extra, copy unknown ones to COPY. */ 1288 extra, copy unknown ones to COPY. It is stored in extra slot by
1289 the key QCfc_unknown_spec. */
1337 while (*p0) 1290 while (*p0)
1338 { 1291 {
1339 Lisp_Object key, val; 1292 Lisp_Object key, val;
@@ -1343,30 +1296,26 @@ font_parse_fcname (name, font)
1343 if (*p1 != '=') 1296 if (*p1 != '=')
1344 { 1297 {
1345 /* Must be an enumerated value. */ 1298 /* Must be an enumerated value. */
1346 val = intern_font_field (p0 + 1, p1 - p0 - 1); 1299 val = font_intern_prop (p0 + 1, p1 - p0 - 1);
1347 if (memcmp (p0 + 1, "light", 5) == 0 1300 if (memcmp (p0 + 1, "light", 5) == 0
1348 || memcmp (p0 + 1, "medium", 6) == 0 1301 || memcmp (p0 + 1, "medium", 6) == 0
1349 || memcmp (p0 + 1, "demibold", 8) == 0 1302 || memcmp (p0 + 1, "demibold", 8) == 0
1350 || memcmp (p0 + 1, "bold", 4) == 0 1303 || memcmp (p0 + 1, "bold", 4) == 0
1351 || memcmp (p0 + 1, "black", 5) == 0) 1304 || memcmp (p0 + 1, "black", 5) == 0)
1352 { 1305 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
1353 ASET (font, FONT_WEIGHT_INDEX, val);
1354 weight_set = 1;
1355 }
1356 else if (memcmp (p0 + 1, "roman", 5) == 0 1306 else if (memcmp (p0 + 1, "roman", 5) == 0
1357 || memcmp (p0 + 1, "italic", 6) == 0 1307 || memcmp (p0 + 1, "italic", 6) == 0
1358 || memcmp (p0 + 1, "oblique", 7) == 0) 1308 || memcmp (p0 + 1, "oblique", 7) == 0)
1359 { 1309 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
1360 ASET (font, FONT_SLANT_INDEX, val);
1361 slant_set = 1;
1362 }
1363 else if (memcmp (p0 + 1, "charcell", 8) == 0 1310 else if (memcmp (p0 + 1, "charcell", 8) == 0
1364 || memcmp (p0 + 1, "mono", 4) == 0 1311 || memcmp (p0 + 1, "mono", 4) == 0
1365 || memcmp (p0 + 1, "proportional", 12) == 0) 1312 || memcmp (p0 + 1, "proportional", 12) == 0)
1366 { 1313 {
1367 font_put_extra (font, QCspacing, 1314 int spacing = (p0[1] == 'c' ? FONT_SPACING_CHARCELL
1368 (p0[1] == 'c' ? Qc : p0[1] == 'm' ? Qm : Qp)); 1315 : p0[1] == 'm' ? FONT_SPACING_MONO
1369 } 1316 : FONT_SPACING_PROPORTIONAL);
1317 ASET (font, FONT_SPACING_INDEX, make_number (spacing));
1318 }
1370 else 1319 else
1371 { 1320 {
1372 /* unknown key */ 1321 /* unknown key */
@@ -1380,34 +1329,28 @@ font_parse_fcname (name, font)
1380 prop = FONT_SIZE_INDEX; 1329 prop = FONT_SIZE_INDEX;
1381 else 1330 else
1382 { 1331 {
1383 key = intern_font_field (p0, p1 - p0); 1332 key = font_intern_prop (p0, p1 - p0);
1384 prop = get_font_prop_index (key, 0); 1333 prop = get_font_prop_index (key);
1385 } 1334 }
1386 p0 = p1 + 1; 1335 p0 = p1 + 1;
1387 for (p1 = p0; *p1 && *p1 != ':'; p1++); 1336 for (p1 = p0; *p1 && *p1 != ':'; p1++);
1388 val = intern_font_field (p0, p1 - p0); 1337 val = font_intern_prop (p0, p1 - p0);
1389 if (! NILP (val)) 1338 if (! NILP (val))
1390 { 1339 {
1391 if (prop >= 0 && prop < FONT_EXTRA_INDEX) 1340 if (prop >= FONT_FOUNDRY_INDEX && prop < FONT_EXTRA_INDEX)
1392 { 1341 ASET (font, prop, font_prop_validate (prop, Qnil, val));
1393 if (prop == FONT_WEIGHT_INDEX) 1342 else if (prop >= 0)
1394 weight_set = 1; 1343 Ffont_put (font, key, val);
1395 else if (prop == FONT_SLANT_INDEX)
1396 slant_set = 1;
1397
1398 ASET (font, prop, val);
1399 }
1400 else 1344 else
1401 font_put_extra (font, key, val); 1345 bcopy (p0 - 1, copy, p1 - p0 + 1);
1346 copy += p1 - p0 + 1;
1402 } 1347 }
1403 } 1348 }
1404 p0 = p1; 1349 p0 = p1;
1405 } 1350 }
1406 1351 if (name != copy)
1407 if (!weight_set) 1352 font_put_extra (font, QCfc_unknown_spec,
1408 ASET (font, FONT_WEIGHT_INDEX, build_string ("normal")); 1353 make_unibyte_string (name, copy - name));
1409 if (!slant_set)
1410 ASET (font, FONT_SLANT_INDEX, build_string ("normal"));
1411 1354
1412 return 0; 1355 return 0;
1413} 1356}
@@ -1423,17 +1366,18 @@ font_unparse_fcname (font, pixel_size, name, nbytes)
1423 char *name; 1366 char *name;
1424 int nbytes; 1367 int nbytes;
1425{ 1368{
1426 Lisp_Object val; 1369 Lisp_Object tail, val;
1427 int point_size; 1370 int point_size;
1428 int dpi, spacing, scalable; 1371 int dpi, spacing, avgwidth;
1429 int i, len = 1; 1372 int i, len = 1;
1430 char *p; 1373 char *p;
1431 Lisp_Object styles[3]; 1374 Lisp_Object styles[3];
1432 char *style_names[3] = { "weight", "slant", "width" }; 1375 char *style_names[3] = { "weight", "slant", "width" };
1376 char work[256];
1433 1377
1434 val = AREF (font, FONT_FAMILY_INDEX); 1378 val = AREF (font, FONT_FAMILY_INDEX);
1435 if (SYMBOLP (val) && ! NILP (val)) 1379 if (STRINGP (val))
1436 len += SBYTES (SYMBOL_NAME (val)); 1380 len += SBYTES (val);
1437 1381
1438 val = AREF (font, FONT_SIZE_INDEX); 1382 val = AREF (font, FONT_SIZE_INDEX);
1439 if (INTEGERP (val)) 1383 if (INTEGERP (val))
@@ -1451,64 +1395,44 @@ font_unparse_fcname (font, pixel_size, name, nbytes)
1451 } 1395 }
1452 1396
1453 val = AREF (font, FONT_FOUNDRY_INDEX); 1397 val = AREF (font, FONT_FOUNDRY_INDEX);
1454 if (SYMBOLP (val) && ! NILP (val)) 1398 if (STRINGP (val))
1455 /* ":foundry=NAME" */ 1399 /* ":foundry=NAME" */
1456 len += 9 + SBYTES (SYMBOL_NAME (val)); 1400 len += 9 + SBYTES (val);
1457 1401
1458 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++) 1402 for (i = 0; i < 3; i++)
1459 { 1403 {
1460 val = AREF (font, i); 1404 int this_len;
1461 if (INTEGERP (val))
1462 {
1463 val = prop_numeric_to_name (i, XINT (val));
1464 }
1465 if (SYMBOLP (val) && ! NILP (val))
1466 len += (strlen (style_names[i - FONT_WEIGHT_INDEX])
1467 + 2 + SBYTES (SYMBOL_NAME (val))); /* :xxx=NAME */
1468 styles[i - FONT_WEIGHT_INDEX] = val;
1469 }
1470 1405
1471 val = AREF (font, FONT_EXTRA_INDEX); 1406 styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
1472 if (FONT_ENTITY_P (font) 1407 if (! NILP (styles[i]))
1473 && EQ (AREF (font, FONT_TYPE_INDEX), Qx)) 1408 len += sprintf (work, ":%s=%s", style_names[i],
1474 { 1409 SDATA (SYMBOL_NAME (styles[i])));
1475 char *p;
1476
1477 /* VAL is a symbol of name `RESX-RESY-SPACING-AVWIDTH'. */
1478 p = (char *) SDATA (SYMBOL_NAME (val));
1479 dpi = atoi (p);
1480 for (p++; *p != '-'; p++); /* skip RESX */
1481 for (p++; *p != '-'; p++); /* skip RESY */
1482 spacing = (*p == 'c' ? FONT_SPACING_CHARCELL
1483 : *p == 'm' ? FONT_SPACING_MONO
1484 : FONT_SPACING_PROPORTIONAL);
1485 for (p++; *p != '-'; p++); /* skip SPACING */
1486 scalable = (atoi (p) == 0);
1487 /* The longest pattern is ":dpi=NUM:scalable=False:spacing=100" */
1488 len += 42;
1489 } 1410 }
1490 else 1411
1412 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1413 len += sprintf (work, ":dpi=%d", dpi);
1414 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1415 len += strlen (":spacing=100");
1416 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1417 len += strlen (":scalable=false"); /* or ":scalable=true" */
1418 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
1491 { 1419 {
1492 Lisp_Object elt; 1420 Lisp_Object key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
1493 1421
1494 dpi = spacing = scalable = -1; 1422 len += SBYTES (SYMBOL_NAME (key)) + 1; /* for :KEY= */
1495 elt = assq_no_quit (QCdpi, val); 1423 if (STRINGP (val))
1496 if (CONSP (elt)) 1424 len += SBYTES (val);
1497 dpi = XINT (XCDR (elt)), len += 15; /* for ":dpi=NUM" */ 1425 else if (INTEGERP (val))
1498 elt = assq_no_quit (QCspacing, val); 1426 len += sprintf (work, "%d", XINT (val));
1499 if (CONSP (elt)) 1427 else if (SYMBOLP (val))
1500 spacing = XINT (XCDR (elt)), len += 12; /* for ":spacing=100" */ 1428 len += (NILP (val) ? 5 : 4); /* for "false" or "true" */
1501 elt = assq_no_quit (QCscalable, val);
1502 if (CONSP (elt))
1503 scalable = ! NILP (XCDR (elt)), len += 15; /* for ":scalable=False" */
1504 } 1429 }
1505 1430
1506 if (len > nbytes) 1431 if (len > nbytes)
1507 return -1; 1432 return -1;
1508 p = name; 1433 p = name;
1509 if (! NILP (AREF (font, FONT_FAMILY_INDEX))) 1434 if (! NILP (AREF (font, FONT_FAMILY_INDEX)))
1510 p += sprintf(p, "%s", 1435 p += sprintf(p, "%s", SDATA (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX))));
1511 SDATA (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX))));
1512 if (point_size > 0) 1436 if (point_size > 0)
1513 { 1437 {
1514 if (p == name) 1438 if (p == name)
@@ -1518,32 +1442,30 @@ font_unparse_fcname (font, pixel_size, name, nbytes)
1518 } 1442 }
1519 else if (pixel_size > 0) 1443 else if (pixel_size > 0)
1520 p += sprintf (p, ":pixelsize=%d", pixel_size); 1444 p += sprintf (p, ":pixelsize=%d", pixel_size);
1521 if (SYMBOLP (AREF (font, FONT_FOUNDRY_INDEX)) 1445 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1522 && ! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1523 p += sprintf (p, ":foundry=%s", 1446 p += sprintf (p, ":foundry=%s",
1524 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX)))); 1447 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1525 for (i = 0; i < 3; i++) 1448 for (i = 0; i < 3; i++)
1526 if (SYMBOLP (styles[i]) && ! NILP (styles [i])) 1449 if (! NILP (styles[i]))
1527 p += sprintf (p, ":%s=%s", style_names[i], 1450 p += sprintf (p, ":%s=%s", style_names[i],
1528 SDATA (SYMBOL_NAME (styles [i]))); 1451 SDATA (SYMBOL_NAME (styles[i])));
1529 if (dpi >= 0) 1452 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1530 p += sprintf (p, ":dpi=%d", dpi); 1453 p += sprintf (p, ":dpi=%d", XINT (AREF (font, FONT_DPI_INDEX)));
1531 if (spacing >= 0) 1454 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1532 p += sprintf (p, ":spacing=%d", spacing); 1455 p += sprintf (p, ":spacing=%d", XINT (AREF (font, FONT_SPACING_INDEX)));
1533 if (scalable > 0) 1456 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1534 p += sprintf (p, ":scalable=True"); 1457 {
1535 else if (scalable == 0) 1458 if (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0)
1536 p += sprintf (p, ":scalable=False"); 1459 p += sprintf (p, ":scalable=true");
1460 else
1461 p += sprintf (p, ":scalable=false");
1462 }
1537 return (p - name); 1463 return (p - name);
1538} 1464}
1539 1465
1540/* Parse NAME (null terminated) and store information in FONT 1466/* Parse NAME (null terminated) and store information in FONT
1541 (font-spec or font-entity). If NAME is successfully parsed, return 1467 (font-spec or font-entity). If NAME is successfully parsed, return
1542 0. Otherwise return -1. 1468 0. Otherwise return -1. */
1543
1544 If NAME is XLFD and FONT is a font-entity, store
1545 RESX-RESY-SPACING-AVWIDTH information as a symbol in
1546 FONT_EXTRA_INDEX. */
1547 1469
1548static int 1470static int
1549font_parse_name (name, font) 1471font_parse_name (name, font)
@@ -1555,57 +1477,58 @@ font_parse_name (name, font)
1555 return font_parse_fcname (name, font); 1477 return font_parse_fcname (name, font);
1556} 1478}
1557 1479
1558/* Merge old style font specification (either a font name NAME or a 1480
1559 combination of a family name FAMILY and a registry name REGISTRY 1481/* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1560 into the font specification SPEC. */ 1482 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1483 part. */
1561 1484
1562void 1485void
1563font_merge_old_spec (name, family, registry, spec) 1486font_parse_family_registry (family, registry, font_spec)
1564 Lisp_Object name, family, registry, spec; 1487 Lisp_Object family, registry, font_spec;
1565{ 1488{
1566 if (STRINGP (name)) 1489 int len;
1490 char *p0, *p1;
1491
1492 if (! NILP (family))
1567 { 1493 {
1568 if (font_parse_xlfd ((char *) SDATA (name), spec) < 0) 1494 CHECK_STRING (family);
1495 len = SBYTES (family);
1496 p0 = (char *) SDATA (family);
1497 p1 = index (p0, '-');
1498 if (p1)
1569 { 1499 {
1570 Lisp_Object extra = Fcons (Fcons (QCname, name), Qnil); 1500 if (*p0 != '*' || p1 - p0 > 1)
1571 1501 ASET (font_spec, FONT_FOUNDRY_INDEX,
1572 ASET (spec, FONT_EXTRA_INDEX, extra); 1502 font_intern_prop (p0, p1 - p0));
1503 p1++;
1504 len -= p1 - p0;
1505 ASET (font_spec, FONT_FAMILY_INDEX, font_intern_prop (p1, len));
1573 } 1506 }
1507 else
1508 ASET (font_spec, FONT_FAMILY_INDEX, Fintern (family, Qnil));
1574 } 1509 }
1575 else 1510 if (! NILP (registry))
1576 { 1511 {
1577 if (! NILP (family)) 1512 /* Convert "XXX" and "XXX*" to "XXX*-*". */
1513 CHECK_STRING (registry);
1514 len = SBYTES (registry);
1515 p0 = (char *) SDATA (registry);
1516 p1 = index (p0, '-');
1517 if (! p1)
1578 { 1518 {
1579 int len; 1519 if (SDATA (registry)[len - 1] == '*')
1580 char *p0, *p1; 1520 registry = concat2 (registry, build_string ("-*"));
1581 1521 else
1582 xassert (STRINGP (family)); 1522 registry = concat2 (registry, build_string ("*-*"));
1583 len = SBYTES (family);
1584 p0 = (char *) SDATA (family);
1585 p1 = index (p0, '-');
1586 if (p1)
1587 {
1588 if ((*p0 != '*' || p1 - p0 > 1)
1589 && NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
1590 ASET (spec, FONT_FOUNDRY_INDEX,
1591 intern_downcase (p0, p1 - p0));
1592 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1593 ASET (spec, FONT_FAMILY_INDEX,
1594 intern_downcase (p1 + 1, len - (p1 + 1 - p0)));
1595 }
1596 else if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1597 ASET (spec, FONT_FAMILY_INDEX, intern_downcase (p0, len));
1598 } 1523 }
1599 if (! NILP (registry) 1524 registry = Fdowncase (registry);
1600 && NILP (AREF (spec, FONT_REGISTRY_INDEX))) 1525 ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil));
1601 ASET (spec, FONT_REGISTRY_INDEX,
1602 intern_downcase ((char *) SDATA (registry), SBYTES (registry)));
1603 } 1526 }
1604} 1527}
1605 1528
1606 1529
1607/* This part (through the next ^L) is still experimental and never 1530/* This part (through the next ^L) is still experimental and not
1608 tested. We may drastically change codes. */ 1531 tested much. We may drastically change codes. */
1609 1532
1610/* OTF handler */ 1533/* OTF handler */
1611 1534
@@ -1671,7 +1594,7 @@ static void
1671check_otf_features (otf_features) 1594check_otf_features (otf_features)
1672 Lisp_Object otf_features; 1595 Lisp_Object otf_features;
1673{ 1596{
1674 Lisp_Object val, elt; 1597 Lisp_Object val;
1675 1598
1676 CHECK_CONS (otf_features); 1599 CHECK_CONS (otf_features);
1677 CHECK_SYMBOL (XCAR (otf_features)); 1600 CHECK_SYMBOL (XCAR (otf_features));
@@ -1710,20 +1633,19 @@ otf_tag_symbol (tag)
1710} 1633}
1711 1634
1712static OTF * 1635static OTF *
1713otf_open (entity, file) 1636otf_open (file)
1714 Lisp_Object entity; 1637 Lisp_Object file;
1715 char *file;
1716{ 1638{
1717 Lisp_Object val = Fassoc (entity, otf_list); 1639 Lisp_Object val = Fassoc (file, otf_list);
1718 OTF *otf; 1640 OTF *otf;
1719 1641
1720 if (! NILP (val)) 1642 if (! NILP (val))
1721 otf = XSAVE_VALUE (XCDR (val))->pointer; 1643 otf = XSAVE_VALUE (XCDR (val))->pointer;
1722 else 1644 else
1723 { 1645 {
1724 otf = file ? OTF_open (file) : NULL; 1646 otf = STRINGP (file) ? OTF_open ((char *) SDATA (file)) : NULL;
1725 val = make_save_value (otf, 0); 1647 val = make_save_value (otf, 0);
1726 otf_list = Fcons (Fcons (entity, val), otf_list); 1648 otf_list = Fcons (Fcons (file, val), otf_list);
1727 } 1649 }
1728 return otf; 1650 return otf;
1729} 1651}
@@ -1741,7 +1663,7 @@ font_otf_capability (font)
1741 Lisp_Object capability = Fcons (Qnil, Qnil); 1663 Lisp_Object capability = Fcons (Qnil, Qnil);
1742 int i; 1664 int i;
1743 1665
1744 otf = otf_open (font->entity, font->file_name); 1666 otf = otf_open (font->props[FONT_FILE_INDEX]);
1745 if (! otf) 1667 if (! otf)
1746 return Qnil; 1668 return Qnil;
1747 for (i = 0; i < 2; i++) 1669 for (i = 0; i < 2; i++)
@@ -1814,7 +1736,7 @@ generate_otf_features (spec, features)
1814 char *features; 1736 char *features;
1815{ 1737{
1816 Lisp_Object val; 1738 Lisp_Object val;
1817 char *p, *pend; 1739 char *p;
1818 int asterisk; 1740 int asterisk;
1819 1741
1820 p = features; 1742 p = features;
@@ -1917,7 +1839,7 @@ font_prepare_composition (cmp, f)
1917 = AREF (XHASH_TABLE (composition_hash_table)->key_and_value, 1839 = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
1918 cmp->hash_index * 2); 1840 cmp->hash_index * 2);
1919 1841
1920 cmp->font = XSAVE_VALUE (LGSTRING_FONT (gstring))->pointer; 1842 cmp->font = XFONT_OBJECT (LGSTRING_FONT (gstring));
1921 cmp->glyph_len = LGSTRING_LENGTH (gstring); 1843 cmp->glyph_len = LGSTRING_LENGTH (gstring);
1922 cmp->pixel_width = LGSTRING_WIDTH (gstring); 1844 cmp->pixel_width = LGSTRING_WIDTH (gstring);
1923 cmp->lbearing = LGSTRING_LBEARING (gstring); 1845 cmp->lbearing = LGSTRING_LBEARING (gstring);
@@ -1934,87 +1856,106 @@ font_prepare_composition (cmp, f)
1934 1856
1935/* Font sorting */ 1857/* Font sorting */
1936 1858
1937static unsigned font_score P_ ((Lisp_Object, Lisp_Object *)); 1859static unsigned font_score P_ ((Lisp_Object, Lisp_Object *, Lisp_Object));
1938static int font_compare P_ ((const void *, const void *)); 1860static int font_compare P_ ((const void *, const void *));
1939static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object, 1861static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object,
1940 Lisp_Object, Lisp_Object)); 1862 Lisp_Object, Lisp_Object,
1863 int));
1941 1864
1942/* We sort fonts by scoring each of them against a specified 1865/* We sort fonts by scoring each of them against a specified
1943 font-spec. The score value is 32 bit (`unsigned'), and the smaller 1866 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1944 the value is, the closer the font is to the font-spec. 1867 the value is, the closer the font is to the font-spec.
1945 1868
1946 Each 1-bit of the highest 4 bits of the score is used for atomic 1869 The highest 2 bits of the score is used for FAMILY. The exact
1947 properties FOUNDRY, FAMILY, ADSTYLE, and REGISTRY. 1870 match is 0, match with one of face-font-family-alternatives is
1871 nonzero.
1872
1873 The next 2 bits of the score is used for the atomic properties
1874 FOUNDRY and ADSTYLE respectively.
1948 1875
1949 Each 7-bit in the lowest 28 bits are used for numeric properties 1876 Each 7-bit in the lower 28 bits are used for numeric properties
1950 WEIGHT, SLANT, WIDTH, and SIZE. */ 1877 WEIGHT, SLANT, WIDTH, and SIZE. */
1951 1878
1952/* How many bits to shift to store the difference value of each font 1879/* How many bits to shift to store the difference value of each font
1953 property in a score. */ 1880 property in a score. Note that flots for FONT_TYPE_INDEX and
1881 FONT_REGISTRY_INDEX are not used. */
1954static int sort_shift_bits[FONT_SIZE_INDEX + 1]; 1882static int sort_shift_bits[FONT_SIZE_INDEX + 1];
1955 1883
1956/* Score font-entity ENTITY against properties of font-spec SPEC_PROP. 1884/* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1957 The return value indicates how different ENTITY is compared with 1885 The return value indicates how different ENTITY is compared with
1958 SPEC_PROP. */ 1886 SPEC_PROP.
1887
1888 ALTERNATE_FAMILIES, if non-nil, is a pre-calculated list of
1889 alternate family names for AREF (SPEC_PROP, FONT_FAMILY_INDEX). */
1959 1890
1960static unsigned 1891static unsigned
1961font_score (entity, spec_prop) 1892font_score (entity, spec_prop, alternate_families)
1962 Lisp_Object entity, *spec_prop; 1893 Lisp_Object entity, *spec_prop;
1894 Lisp_Object alternate_families;
1963{ 1895{
1964 unsigned score = 0; 1896 unsigned score = 0;
1965 int i; 1897 int i;
1966 /* Score four atomic fields. Maximum difference is 1. */
1967 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
1968 if (! NILP (spec_prop[i])
1969 && ! EQ (spec_prop[i], AREF (entity, i)))
1970 score |= 1 << sort_shift_bits[i];
1971
1972 /* Score four numeric fields. Maximum difference is 127. */
1973 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
1974 {
1975 Lisp_Object entity_val = AREF (entity, i);
1976 Lisp_Object spec_val = spec_prop[i];
1977 1898
1978 /* If weight and slant are unspecified, score normal lower (low wins). */ 1899 /* Score three atomic fields. Maximum difference is 1 (family is 3). */
1979 if (NILP (spec_val)) 1900 for (i = FONT_FOUNDRY_INDEX; i <= FONT_ADSTYLE_INDEX; i++)
1980 { 1901 if (i != FONT_REGISTRY_INDEX
1981 if (i == FONT_WEIGHT_INDEX || i == FONT_SLANT_INDEX) 1902 && ! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
1982 spec_val = prop_name_to_numeric (i, build_string ("normal")); 1903 {
1983 } 1904 Lisp_Object entity_str = SYMBOL_NAME (AREF (entity, i));
1905 Lisp_Object spec_str = SYMBOL_NAME (spec_prop[i]);
1984 1906
1985 if (! NILP (spec_val) && ! EQ (spec_val, entity_val)) 1907 if (strcasecmp (SDATA (spec_str), SDATA (entity_str)))
1986 { 1908 {
1987 if (! INTEGERP (entity_val)) 1909 if (i == FONT_FAMILY_INDEX && CONSP (alternate_families))
1988 score |= 127 << sort_shift_bits[i]; 1910 {
1989 else 1911 int j;
1990 { 1912
1991 int diff = XINT (entity_val) - XINT (spec_val); 1913 for (j = 1; CONSP (alternate_families);
1914 j++, alternate_families = XCDR (alternate_families))
1915 {
1916 spec_str = XCAR (alternate_families);
1917 if (strcasecmp (SDATA (spec_str), SDATA (entity_str)) == 0)
1918 break;
1919
1920 }
1921 if (j > 3)
1922 j = 3;
1923 score |= j << sort_shift_bits[i];
1924 }
1925 else
1926 score |= 1 << sort_shift_bits[i];
1927 }
1928 }
1992 1929
1993 if (diff < 0) 1930 /* Score three style numeric fields. Maximum difference is 127. */
1994 diff = - diff; 1931 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
1995 if (i == FONT_SIZE_INDEX) 1932 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
1996 { 1933 {
1997 if (XINT (entity_val) > 0 1934 int diff = (XINT (AREF (entity, i)) >> 8) - (XINT (spec_prop[i]) >> 8);
1998 && diff > FONT_PIXEL_SIZE_QUANTUM) 1935
1999 score |= min (diff, 127) << sort_shift_bits[i]; 1936 if (diff < 0)
2000 } 1937 diff = - diff;
2001#ifdef WINDOWSNT 1938 /* This is to prefer the exact symbol style. */
2002 else if (i == FONT_WEIGHT_INDEX) 1939 diff++;
2003 { 1940 score |= min (diff, 127) << sort_shift_bits[i];
2004 /* Windows uses a much wider range for weight (100-900) 1941 }
2005 compared with freetype (0-210), so scale down the 1942
2006 difference. A more general way of doing this 1943 /* Score the size. Maximum difference is 127. */
2007 would be to look up the values of regular and bold 1944 i = FONT_SIZE_INDEX;
2008 and/or light and calculate the scale factor from them, 1945 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i])
2009 but the lookup would be expensive, and if only Windows 1946 && XINT (AREF (entity, i)) > 0)
2010 needs it, not worth the effort. */ 1947 {
2011 score |= min (diff / 4, 127) << sort_shift_bits[i]; 1948 /* We use the higher 6-bit for the actual size difference. The
2012 } 1949 lowest bit is set if the DPI is different. */
2013#endif 1950 int diff = XINT (spec_prop[i]) - XINT (AREF (entity, i));
2014 else 1951
2015 score |= min (diff, 127) << sort_shift_bits[i]; 1952 if (diff < 0)
2016 } 1953 diff = - diff;
2017 } 1954 diff << 1;
1955 if (! NILP (spec_prop[FONT_DPI_INDEX])
1956 && ! EQ (spec_prop[FONT_DPI_INDEX], AREF (entity, FONT_DPI_INDEX)))
1957 diff |= 1;
1958 score |= min (diff, 127) << sort_shift_bits[FONT_SIZE_INDEX];
2018 } 1959 }
2019 1960
2020 return score; 1961 return score;
@@ -2027,8 +1968,7 @@ static int
2027font_compare (d1, d2) 1968font_compare (d1, d2)
2028 const void *d1, *d2; 1969 const void *d1, *d2;
2029{ 1970{
2030 return (*(unsigned *) d1 < *(unsigned *) d2 1971 return (*(unsigned *) d1 - *(unsigned *) d2);
2031 ? -1 : *(unsigned *) d1 > *(unsigned *) d2);
2032} 1972}
2033 1973
2034 1974
@@ -2044,48 +1984,81 @@ struct font_sort_data
2044 If PREFER specifies a point-size, calculate the corresponding 1984 If PREFER specifies a point-size, calculate the corresponding
2045 pixel-size from QCdpi property of PREFER or from the Y-resolution 1985 pixel-size from QCdpi property of PREFER or from the Y-resolution
2046 of FRAME before sorting. If SPEC is not nil, it is a font-spec to 1986 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
2047 get the font-entities in VEC. */ 1987 get the font-entities in VEC.
1988
1989 If BEST-ONLY is nonzero, return the best matching entity. Otherwise,
1990 return the sorted VEC. */
2048 1991
2049static Lisp_Object 1992static Lisp_Object
2050font_sort_entites (vec, prefer, frame, spec) 1993font_sort_entites (vec, prefer, frame, spec, best_only)
2051 Lisp_Object vec, prefer, frame, spec; 1994 Lisp_Object vec, prefer, frame, spec;
1995 int best_only;
2052{ 1996{
2053 Lisp_Object prefer_prop[FONT_SPEC_MAX]; 1997 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2054 int len, i; 1998 int len, i;
2055 struct font_sort_data *data; 1999 struct font_sort_data *data;
2000 Lisp_Object alternate_families = Qnil;
2001 unsigned best_score;
2002 Lisp_Object best_entity;
2056 USE_SAFE_ALLOCA; 2003 USE_SAFE_ALLOCA;
2057 2004
2058 len = ASIZE (vec); 2005 len = ASIZE (vec);
2059 if (len <= 1) 2006 if (len <= 1)
2060 return vec; 2007 return best_only ? AREF (vec, 0) : vec;
2061 2008
2062 for (i = FONT_FOUNDRY_INDEX; i <= FONT_SIZE_INDEX; i++) 2009 for (i = FONT_FOUNDRY_INDEX; i <= FONT_DPI_INDEX; i++)
2063 prefer_prop[i] = AREF (prefer, i); 2010 prefer_prop[i] = AREF (prefer, i);
2064 2011
2065 if (! NILP (spec)) 2012 if (! NILP (spec))
2066 { 2013 {
2067 /* As it is assured that all fonts in VEC match with SPEC, we 2014 /* A font driver may return a font that has a property value
2068 should ignore properties specified in SPEC. So, set the 2015 different from the value specified in SPEC if the driver
2069 corresponding properties in PREFER_PROP to nil. */ 2016 thinks they are the same. That happens, for instance, such a
2070 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++) 2017 generic family name as "serif" is specified. So, to ignore
2018 such a difference, for all properties specified in SPEC, set
2019 the corresponding properties in PREFER_PROP to nil. */
2020 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
2071 if (! NILP (AREF (spec, i))) 2021 if (! NILP (AREF (spec, i)))
2072 prefer_prop[i++] = Qnil; 2022 prefer_prop[i] = Qnil;
2073 } 2023 }
2074 2024
2075 if (FLOATP (prefer_prop[FONT_SIZE_INDEX])) 2025 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2076 prefer_prop[FONT_SIZE_INDEX] 2026 prefer_prop[FONT_SIZE_INDEX]
2077 = make_number (font_pixel_size (XFRAME (frame), prefer)); 2027 = make_number (font_pixel_size (XFRAME (frame), prefer));
2028 if (! NILP (prefer_prop[FONT_FAMILY_INDEX]))
2029 {
2030 alternate_families
2031 = Fassoc_string (prefer_prop[FONT_FAMILY_INDEX],
2032 Vface_alternative_font_family_alist, Qt);
2033 if (CONSP (alternate_families))
2034 alternate_families = XCDR (alternate_families);
2035 }
2078 2036
2079 /* Scoring and sorting. */ 2037 /* Scoring and sorting. */
2080 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len); 2038 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
2039 best_score = 0xFFFFFFFF;
2040 best_entity = Qnil;
2081 for (i = 0; i < len; i++) 2041 for (i = 0; i < len; i++)
2082 { 2042 {
2083 data[i].entity = AREF (vec, i); 2043 data[i].entity = AREF (vec, i);
2084 data[i].score = font_score (data[i].entity, prefer_prop); 2044 data[i].score = font_score (data[i].entity, prefer_prop,
2045 alternate_families);
2046 if (best_only && best_score > data[i].score)
2047 {
2048 best_score = data[i].score;
2049 best_entity = data[i].entity;
2050 if (best_score == 0)
2051 break;
2052 }
2085 } 2053 }
2086 qsort (data, len, sizeof *data, font_compare); 2054 if (NILP (best_entity))
2087 for (i = 0; i < len; i++) 2055 {
2088 ASET (vec, i, data[i].entity); 2056 qsort (data, len, sizeof *data, font_compare);
2057 for (i = 0; i < len; i++)
2058 ASET (vec, i, data[i].entity);
2059 }
2060 else
2061 vec = best_entity;
2089 SAFE_FREE (); 2062 SAFE_FREE ();
2090 2063
2091 return vec; 2064 return vec;
@@ -2102,9 +2075,9 @@ void
2102font_update_sort_order (order) 2075font_update_sort_order (order)
2103 int *order; 2076 int *order;
2104{ 2077{
2105 int i, shift_bits = 21; 2078 int i, shift_bits;
2106 2079
2107 for (i = 0; i < 4; i++, shift_bits -= 7) 2080 for (i = 0, shift_bits = 21; i < 4; i++, shift_bits -= 7)
2108 { 2081 {
2109 int xlfd_idx = order[i]; 2082 int xlfd_idx = order[i];
2110 2083
@@ -2120,87 +2093,51 @@ font_update_sort_order (order)
2120} 2093}
2121 2094
2122 2095
2123/* Return weight property of FONT as symbol. */
2124
2125Lisp_Object
2126font_symbolic_weight (font)
2127 Lisp_Object font;
2128{
2129 Lisp_Object weight = AREF (font, FONT_WEIGHT_INDEX);
2130
2131 if (INTEGERP (weight))
2132 weight = prop_numeric_to_name (FONT_WEIGHT_INDEX, XINT (weight));
2133 return weight;
2134}
2135
2136
2137/* Return slant property of FONT as symbol. */
2138
2139Lisp_Object
2140font_symbolic_slant (font)
2141 Lisp_Object font;
2142{
2143 Lisp_Object slant = AREF (font, FONT_SLANT_INDEX);
2144
2145 if (INTEGERP (slant))
2146 slant = prop_numeric_to_name (FONT_SLANT_INDEX, XINT (slant));
2147 return slant;
2148}
2149
2150
2151/* Return width property of FONT as symbol. */
2152
2153Lisp_Object
2154font_symbolic_width (font)
2155 Lisp_Object font;
2156{
2157 Lisp_Object width = AREF (font, FONT_WIDTH_INDEX);
2158
2159 if (INTEGERP (width))
2160 width = prop_numeric_to_name (FONT_WIDTH_INDEX, XINT (width));
2161 return width;
2162}
2163
2164
2165/* Check if ENTITY matches with the font specification SPEC. */ 2096/* Check if ENTITY matches with the font specification SPEC. */
2166 2097
2167int 2098int
2168font_match_p (spec, entity) 2099font_match_p (spec, entity)
2169 Lisp_Object spec, entity; 2100 Lisp_Object spec, entity;
2170{ 2101{
2102 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2103 Lisp_Object alternate_families = Qnil;
2104 int prefer_style[3];
2171 int i; 2105 int i;
2172 2106
2173 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++) 2107 for (i = FONT_FOUNDRY_INDEX; i <= FONT_SIZE_INDEX; i++)
2174 if (! NILP (AREF (spec, i)) 2108 prefer_prop[i] = AREF (spec, i);
2175 && ! EQ (AREF (spec, i), AREF (entity, i))) 2109 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2176 return 0; 2110 prefer_prop[FONT_SIZE_INDEX]
2177 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)) 2111 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2178 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0 2112 if (! NILP (prefer_prop[FONT_FAMILY_INDEX]))
2179 && (XINT (AREF (spec, FONT_SIZE_INDEX)) 2113 {
2180 != XINT (AREF (entity, FONT_SIZE_INDEX)))) 2114 alternate_families
2181 return 0; 2115 = Fassoc_string (prefer_prop[FONT_FAMILY_INDEX],
2182 return 1; 2116 Vface_alternative_font_family_alist, Qt);
2117 if (CONSP (alternate_families))
2118 alternate_families = XCDR (alternate_families);
2119 }
2120
2121 return (font_score (entity, prefer_prop, alternate_families) == 0);
2183} 2122}
2184 2123
2185 2124
2186/* Return a lispy font object corresponding to FONT. */ 2125/* CHeck a lispy font object corresponding to FONT. */
2187 2126
2188Lisp_Object 2127int
2189font_find_object (font) 2128font_check_object (font)
2190 struct font *font; 2129 struct font *font;
2191{ 2130{
2192 Lisp_Object tail, elt; 2131 Lisp_Object tail, elt;
2193 2132
2194 for (tail = AREF (font->entity, FONT_OBJLIST_INDEX); CONSP (tail); 2133 for (tail = font->props[FONT_OBJLIST_INDEX]; CONSP (tail);
2195 tail = XCDR (tail)) 2134 tail = XCDR (tail))
2196 { 2135 {
2197 elt = XCAR (tail); 2136 elt = XCAR (tail);
2198 if (font == XSAVE_VALUE (elt)->pointer 2137 if (font == XFONT_OBJECT (elt))
2199 && XSAVE_VALUE (elt)->integer > 0) 2138 return 1;
2200 return elt;
2201 } 2139 }
2202 abort (); 2140 return 0;
2203 return Qnil;
2204} 2141}
2205 2142
2206 2143
@@ -2316,13 +2253,10 @@ font_clear_cache (f, cache, driver)
2316 for (; CONSP (objlist); objlist = XCDR (objlist)) 2253 for (; CONSP (objlist); objlist = XCDR (objlist))
2317 { 2254 {
2318 Lisp_Object val = XCAR (objlist); 2255 Lisp_Object val = XCAR (objlist);
2319 struct Lisp_Save_Value *p = XSAVE_VALUE (val); 2256 struct font *font = XFONT_OBJECT (val);
2320 struct font *font = p->pointer;
2321 2257
2322 xassert (font && driver == font->driver); 2258 xassert (font && driver == font->driver);
2323 driver->close (f, font); 2259 driver->close (f, font);
2324 p->pointer = NULL;
2325 p->integer = 0;
2326 num_fonts--; 2260 num_fonts--;
2327 } 2261 }
2328 if (driver->free_entity) 2262 if (driver->free_entity)
@@ -2337,40 +2271,100 @@ font_clear_cache (f, cache, driver)
2337 2271
2338static Lisp_Object scratch_font_spec, scratch_font_prefer; 2272static Lisp_Object scratch_font_spec, scratch_font_prefer;
2339 2273
2274Lisp_Object
2275font_delete_unmatched (list, spec, size)
2276 Lisp_Object list, spec;
2277 int size;
2278{
2279 Lisp_Object entity, prev, tail;
2280 enum font_property_index prop;
2340 2281
2341/* Return a vector of font-entities matching with SPEC on frame F. */ 2282 for (tail = list, prev = Qnil; CONSP (tail); )
2283 {
2284 entity = XCAR (tail);
2285 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++)
2286 if (INTEGERP (AREF (spec, prop))
2287 && ((XINT (AREF (spec, prop)) >> 8)
2288 != (XINT (AREF (entity, prop)) >> 8)))
2289 prop = FONT_SPEC_MAX;
2290 if (prop++ <= FONT_SIZE_INDEX
2291 && size
2292 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0)
2293 {
2294 int diff = XINT (AREF (entity, FONT_SIZE_INDEX)) - size;
2342 2295
2343static Lisp_Object 2296 if (diff != 0
2297 && (diff < 0 ? -diff > FONT_PIXEL_SIZE_QUANTUM
2298 : diff > FONT_PIXEL_SIZE_QUANTUM))
2299 prop = FONT_SPEC_MAX;
2300 }
2301 if (prop < FONT_SPEC_MAX
2302 && INTEGERP (AREF (spec, FONT_SPACING_INDEX))
2303 && ! EQ (AREF (spec, FONT_SPACING_INDEX),
2304 AREF (entity, FONT_SPACING_INDEX)))
2305 prop = FONT_SPEC_MAX;
2306 if (prop < FONT_SPEC_MAX)
2307 prev = tail, tail = XCDR (tail);
2308 else if (NILP (prev))
2309 list = tail = XCDR (tail);
2310 else
2311 tail = XCDR (tail), XSETCDR (prev, tail);
2312 }
2313 return list;
2314}
2315
2316
2317/* Return a vector of font-entities matching with SPEC on FRAME. */
2318
2319Lisp_Object
2344font_list_entities (frame, spec) 2320font_list_entities (frame, spec)
2345 Lisp_Object frame, spec; 2321 Lisp_Object frame, spec;
2346{ 2322{
2347 FRAME_PTR f = XFRAME (frame); 2323 FRAME_PTR f = XFRAME (frame);
2348 struct font_driver_list *driver_list = f->font_driver_list; 2324 struct font_driver_list *driver_list = f->font_driver_list;
2349 Lisp_Object ftype, family, size, alternate_familes; 2325 Lisp_Object ftype, family, alternate_familes;
2350 Lisp_Object *vec = alloca (sizeof (Lisp_Object) * num_font_drivers); 2326 Lisp_Object *vec;
2327 int size;
2328 int need_filtering = 0;
2329 int n_family = 1;
2351 int i; 2330 int i;
2352 2331
2353 if (! vec) 2332 xassert (FONT_SPEC_P (spec));
2354 return null_vector;
2355 2333
2356 family = AREF (spec, FONT_FAMILY_INDEX); 2334 family = AREF (spec, FONT_FAMILY_INDEX);
2357 if (NILP (family)) 2335 if (NILP (family))
2358 alternate_familes = Qnil; 2336 alternate_familes = Qnil;
2359 else 2337 else
2360 { 2338 {
2361 if (NILP (font_family_alist) 2339 alternate_familes = Fassoc_string (family,
2362 && !NILP (Vface_alternative_font_family_alist)) 2340 Vface_alternative_font_family_alist,
2363 build_font_family_alist (); 2341 Qt);
2364 alternate_familes = assq_no_quit (family, font_family_alist);
2365 if (! NILP (alternate_familes)) 2342 if (! NILP (alternate_familes))
2366 alternate_familes = XCDR (alternate_familes); 2343 alternate_familes = XCDR (alternate_familes);
2344 n_family += XINT (Flength (alternate_familes));
2367 } 2345 }
2368 size = AREF (spec, FONT_SIZE_INDEX);
2369 if (FLOATP (size))
2370 ASET (spec, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2371 2346
2372 xassert (ASIZE (spec) == FONT_SPEC_MAX); 2347 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2348 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2349 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2350 size = font_pixel_size (f, spec);
2351 else
2352 size = 0;
2353
2373 ftype = AREF (spec, FONT_TYPE_INDEX); 2354 ftype = AREF (spec, FONT_TYPE_INDEX);
2355 for (i = 0; i <= FONT_REGISTRY_INDEX; i++)
2356 ASET (scratch_font_spec, i, AREF (spec, i));
2357 for (; i < FONT_EXTRA_INDEX; i++)
2358 {
2359 ASET (scratch_font_spec, i, Qnil);
2360 if (! NILP (AREF (spec, i)))
2361 need_filtering = 1;
2362 }
2363 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
2364
2365 vec = alloca (sizeof (Lisp_Object) * num_font_drivers * n_family);
2366 if (! vec)
2367 return null_vector;
2374 2368
2375 for (i = 0; driver_list; driver_list = driver_list->next) 2369 for (i = 0; driver_list; driver_list = driver_list->next)
2376 if (driver_list->on 2370 if (driver_list->on
@@ -2379,50 +2373,53 @@ font_list_entities (frame, spec)
2379 Lisp_Object cache = font_get_cache (f, driver_list->driver); 2373 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2380 Lisp_Object tail = alternate_familes; 2374 Lisp_Object tail = alternate_familes;
2381 2375
2382 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2383 ASET (spec, FONT_FAMILY_INDEX, family);
2384
2385 while (1) 2376 while (1)
2386 { 2377 {
2387 Lisp_Object val = assoc_no_quit (spec, XCDR (cache)); 2378 Lisp_Object val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2388 2379
2389 if (CONSP (val)) 2380 if (CONSP (val) && VECTORP (XCDR (val)))
2390 val = XCDR (val); 2381 val = XCDR (val);
2391 else 2382 else
2392 { 2383 {
2393 val = driver_list->driver->list (frame, spec); 2384 Lisp_Object copy;
2394 if (VECTORP (val)) 2385
2395 XSETCDR (cache, Fcons (Fcons (Fcopy_sequence (spec), val), 2386 val = driver_list->driver->list (frame, scratch_font_spec);
2396 XCDR (cache))); 2387 if (! NILP (val) && need_filtering)
2388 val = font_delete_unmatched (val, spec, size);
2389 copy = Fcopy_font_spec (scratch_font_spec);
2390 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2397 } 2391 }
2398 if (VECTORP (val) && ASIZE (val) > 0) 2392 if (! NILP (val))
2399 { 2393 {
2400 vec[i++] = val; 2394 vec[i++] = val;
2401 break; 2395 break;
2402 } 2396 }
2403 if (NILP (tail)) 2397 if (NILP (tail))
2404 break; 2398 break;
2405 ASET (spec, FONT_FAMILY_INDEX, XCAR (tail)); 2399 ASET (scratch_font_spec, FONT_FAMILY_INDEX,
2400 Fintern (XCAR (tail), Qnil));
2406 tail = XCDR (tail); 2401 tail = XCDR (tail);
2407 } 2402 }
2408 } 2403 }
2409 ASET (spec, FONT_TYPE_INDEX, ftype); 2404
2410 ASET (spec, FONT_FAMILY_INDEX, family);
2411 ASET (spec, FONT_SIZE_INDEX, size);
2412 return (i > 0 ? Fvconcat (i, vec) : null_vector); 2405 return (i > 0 ? Fvconcat (i, vec) : null_vector);
2413} 2406}
2414 2407
2415 2408
2416/* Return a font entity matching with SPEC on FRAME. */ 2409/* Return a font entity matching with SPEC on FRAME. ATTRS, if non
2410 nil, is an array of face's attributes, which specifies preferred
2411 font-related attributes. */
2417 2412
2418static Lisp_Object 2413static Lisp_Object
2419font_matching_entity (frame, spec) 2414font_matching_entity (f, attrs, spec)
2420 Lisp_Object frame, spec; 2415 FRAME_PTR f;
2416 Lisp_Object *attrs, spec;
2421{ 2417{
2422 FRAME_PTR f = XFRAME (frame);
2423 struct font_driver_list *driver_list = f->font_driver_list; 2418 struct font_driver_list *driver_list = f->font_driver_list;
2424 Lisp_Object ftype, size, entity; 2419 Lisp_Object ftype, size, entity;
2420 Lisp_Object frame;
2425 2421
2422 XSETFRAME (frame, f);
2426 ftype = AREF (spec, FONT_TYPE_INDEX); 2423 ftype = AREF (spec, FONT_TYPE_INDEX);
2427 size = AREF (spec, FONT_SIZE_INDEX); 2424 size = AREF (spec, FONT_SIZE_INDEX);
2428 if (FLOATP (size)) 2425 if (FLOATP (size))
@@ -2433,21 +2430,16 @@ font_matching_entity (frame, spec)
2433 && (NILP (ftype) || EQ (driver_list->driver->type, ftype))) 2430 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2434 { 2431 {
2435 Lisp_Object cache = font_get_cache (f, driver_list->driver); 2432 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2436 Lisp_Object key;
2437 2433
2438 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type); 2434 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2439 key = Fcons (spec, Qnil); 2435 entity = assoc_no_quit (spec, XCDR (cache));
2440 entity = assoc_no_quit (key, XCDR (cache)); 2436 if (CONSP (entity) && ! VECTORP (XCDR (entity)))
2441 if (CONSP (entity))
2442 entity = XCDR (entity); 2437 entity = XCDR (entity);
2443 else 2438 else
2444 { 2439 {
2445 entity = driver_list->driver->match (frame, spec); 2440 entity = driver_list->driver->match (frame, spec);
2446 if (! NILP (entity)) 2441 XSETCDR (cache, Fcons (Fcons (Fcopy_font_spec (spec), entity),
2447 { 2442 XCDR (cache)));
2448 XSETCAR (key, Fcopy_sequence (spec));
2449 XSETCDR (cache, Fcons (Fcons (key, entity), XCDR (cache)));
2450 }
2451 } 2443 }
2452 if (! NILP (entity)) 2444 if (! NILP (entity))
2453 break; 2445 break;
@@ -2470,53 +2462,52 @@ font_open_entity (f, entity, pixel_size)
2470 struct font_driver_list *driver_list; 2462 struct font_driver_list *driver_list;
2471 Lisp_Object objlist, size, val, font_object; 2463 Lisp_Object objlist, size, val, font_object;
2472 struct font *font; 2464 struct font *font;
2465 int min_width;
2473 2466
2467 xassert (FONT_ENTITY_P (entity));
2474 size = AREF (entity, FONT_SIZE_INDEX); 2468 size = AREF (entity, FONT_SIZE_INDEX);
2475 xassert (NATNUMP (size));
2476 if (XINT (size) != 0) 2469 if (XINT (size) != 0)
2477 pixel_size = XINT (size); 2470 pixel_size = XINT (size);
2478 2471
2479 font_object = Qnil;
2480 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist); 2472 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2481 objlist = XCDR (objlist)) 2473 objlist = XCDR (objlist))
2482 { 2474 if (XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size)
2483 font = XSAVE_VALUE (XCAR (objlist))->pointer; 2475 return XCAR (objlist);
2484 if (font->pixel_size == pixel_size) 2476
2485 { 2477 val = AREF (entity, FONT_TYPE_INDEX);
2486 font_object = XCAR (objlist); 2478 for (driver_list = f->font_driver_list;
2487 XSAVE_VALUE (font_object)->integer++; 2479 driver_list && ! EQ (driver_list->driver->type, val);
2488 break; 2480 driver_list = driver_list->next);
2489 } 2481 if (! driver_list)
2490 } 2482 return Qnil;
2491 2483
2484 font_object = driver_list->driver->open (f, entity, pixel_size);
2492 if (NILP (font_object)) 2485 if (NILP (font_object))
2486 return Qnil;
2487 ASET (entity, FONT_OBJLIST_INDEX,
2488 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2489 ASET (font_object, FONT_OBJLIST_INDEX, AREF (entity, FONT_OBJLIST_INDEX));
2490 num_fonts++;
2491
2492 font = XFONT_OBJECT (font_object);
2493 min_width = (font->min_width ? font->min_width
2494 : font->average_width ? font->average_width
2495 : font->space_width ? font->space_width
2496 : 1);
2497 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
2498 if (FRAME_X_DISPLAY_INFO (f)->n_fonts == 1)
2493 { 2499 {
2494 val = AREF (entity, FONT_TYPE_INDEX); 2500 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
2495 for (driver_list = f->font_driver_list; 2501 FRAME_SMALLEST_FONT_HEIGHT (f) = font->height;
2496 driver_list && ! EQ (driver_list->driver->type, val); 2502 fonts_changed_p = 1;
2497 driver_list = driver_list->next); 2503 }
2498 if (! driver_list) 2504 else
2499 return Qnil; 2505 {
2500 2506 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
2501 font = driver_list->driver->open (f, entity, pixel_size); 2507 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
2502 if (! font) 2508 if (FRAME_SMALLEST_FONT_HEIGHT (f) > font->height)
2503 return Qnil; 2509 FRAME_SMALLEST_FONT_HEIGHT (f) = font->height, fonts_changed_p = 1;
2504 font->scalable = XINT (size) == 0;
2505
2506 font_object = make_save_value (font, 1);
2507 ASET (entity, FONT_OBJLIST_INDEX,
2508 Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
2509 num_fonts++;
2510 } 2510 }
2511
2512 if (FRAME_SMALLEST_CHAR_WIDTH (f) > font->min_width)
2513 FRAME_SMALLEST_CHAR_WIDTH (f) = font->min_width;
2514 if (FRAME_SMALLEST_CHAR_WIDTH (f) <= 0)
2515 FRAME_SMALLEST_CHAR_WIDTH (f) = 1;
2516 if (FRAME_SMALLEST_FONT_HEIGHT (f) > font->font.height)
2517 FRAME_SMALLEST_FONT_HEIGHT (f) = font->font.height;
2518 if (FRAME_SMALLEST_FONT_HEIGHT (f) <= 0)
2519 FRAME_SMALLEST_FONT_HEIGHT (f) = 1;
2520 2511
2521 return font_object; 2512 return font_object;
2522} 2513}
@@ -2529,25 +2520,20 @@ font_close_object (f, font_object)
2529 FRAME_PTR f; 2520 FRAME_PTR f;
2530 Lisp_Object font_object; 2521 Lisp_Object font_object;
2531{ 2522{
2532 struct font *font = XSAVE_VALUE (font_object)->pointer; 2523 struct font *font = XFONT_OBJECT (font_object);
2533 Lisp_Object objlist; 2524 Lisp_Object objlist;
2534 Lisp_Object tail, prev = Qnil; 2525 Lisp_Object tail, prev = Qnil;
2535 2526
2536 xassert (XSAVE_VALUE (font_object)->integer > 0); 2527 objlist = AREF (font_object, FONT_OBJLIST_INDEX);
2537 XSAVE_VALUE (font_object)->integer--;
2538 if (XSAVE_VALUE (font_object)->integer > 0)
2539 return;
2540
2541 objlist = AREF (font->entity, FONT_OBJLIST_INDEX);
2542 for (prev = Qnil, tail = objlist; CONSP (tail); 2528 for (prev = Qnil, tail = objlist; CONSP (tail);
2543 prev = tail, tail = XCDR (tail)) 2529 prev = tail, tail = XCDR (tail))
2544 if (EQ (font_object, XCAR (tail))) 2530 if (EQ (font_object, XCAR (tail)))
2545 { 2531 {
2546 if (font->driver->close) 2532 xassert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
2547 font->driver->close (f, font); 2533 font->driver->close (f, font);
2548 XSAVE_VALUE (font_object)->pointer = NULL; 2534 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
2549 if (NILP (prev)) 2535 if (NILP (prev))
2550 ASET (font->entity, FONT_OBJLIST_INDEX, XCDR (objlist)); 2536 ASET (font_object, FONT_OBJLIST_INDEX, XCDR (objlist));
2551 else 2537 else
2552 XSETCDR (prev, XCDR (objlist)); 2538 XSETCDR (prev, XCDR (objlist));
2553 num_fonts--; 2539 num_fonts--;
@@ -2584,11 +2570,10 @@ font_has_char (f, font, c)
2584 } 2570 }
2585 2571
2586 xassert (FONT_OBJECT_P (font)); 2572 xassert (FONT_OBJECT_P (font));
2587 fontp = XSAVE_VALUE (font)->pointer; 2573 fontp = XFONT_OBJECT (font);
2588
2589 if (fontp->driver->has_char) 2574 if (fontp->driver->has_char)
2590 { 2575 {
2591 int result = fontp->driver->has_char (fontp->entity, c); 2576 int result = fontp->driver->has_char (font, c);
2592 2577
2593 if (result >= 0) 2578 if (result >= 0)
2594 return result; 2579 return result;
@@ -2604,8 +2589,10 @@ font_encode_char (font_object, c)
2604 Lisp_Object font_object; 2589 Lisp_Object font_object;
2605 int c; 2590 int c;
2606{ 2591{
2607 struct font *font = XSAVE_VALUE (font_object)->pointer; 2592 struct font *font;
2608 2593
2594 xassert (FONT_OBJECT_P (font_object));
2595 font = XFONT_OBJECT (font_object);
2609 return font->driver->encode_char (font, c); 2596 return font->driver->encode_char (font, c);
2610} 2597}
2611 2598
@@ -2616,12 +2603,10 @@ Lisp_Object
2616font_get_name (font_object) 2603font_get_name (font_object)
2617 Lisp_Object font_object; 2604 Lisp_Object font_object;
2618{ 2605{
2619 struct font *font = XSAVE_VALUE (font_object)->pointer; 2606 Lisp_Object name;
2620 char *name = (font->font.full_name ? font->font.full_name
2621 : font->font.name ? font->font.name
2622 : NULL);
2623 2607
2624 return (name ? make_unibyte_string (name, strlen (name)) : null_string); 2608 xassert (FONT_OBJECT_P (font_object));
2609 return AREF (font_object, FONT_NAME_INDEX);
2625} 2610}
2626 2611
2627 2612
@@ -2631,154 +2616,232 @@ Lisp_Object
2631font_get_spec (font_object) 2616font_get_spec (font_object)
2632 Lisp_Object font_object; 2617 Lisp_Object font_object;
2633{ 2618{
2634 struct font *font = XSAVE_VALUE (font_object)->pointer; 2619 Lisp_Object spec = font_make_spec ();
2635 Lisp_Object spec = Ffont_spec (0, NULL);
2636 int i; 2620 int i;
2637 2621
2638 for (i = 0; i < FONT_SIZE_INDEX; i++) 2622 for (i = 0; i < FONT_SIZE_INDEX; i++)
2639 ASET (spec, i, AREF (font->entity, i)); 2623 ASET (spec, i, AREF (font_object, i));
2640 ASET (spec, FONT_SIZE_INDEX, make_number (font->pixel_size)); 2624 ASET (spec, FONT_SIZE_INDEX,
2625 make_number (XFONT_OBJECT (font_object)->pixel_size));
2641 return spec; 2626 return spec;
2642} 2627}
2643 2628
2629Lisp_Object
2630font_spec_from_name (font_name)
2631 Lisp_Object font_name;
2632{
2633 Lisp_Object args[2];
2634
2635 args[0] = QCname;
2636 args[1] = font_name;
2637 return Ffont_spec (2, args);
2638}
2644 2639
2645/* Return the frame on which FONT exists. FONT is a font object or a
2646 font entity. */
2647 2640
2648Lisp_Object 2641void
2649font_get_frame (font) 2642font_clear_prop (attrs, prop)
2650 Lisp_Object font; 2643 Lisp_Object *attrs;
2644 enum font_property_index prop;
2651{ 2645{
2652 if (FONT_OBJECT_P (font)) 2646 Lisp_Object font = attrs[LFACE_FONT_INDEX];
2653 font = ((struct font *) XSAVE_VALUE (font)->pointer)->entity; 2647 Lisp_Object extra, prev;
2654 xassert (FONT_ENTITY_P (font)); 2648
2655 return AREF (font, FONT_FRAME_INDEX); 2649 if (! FONTP (font))
2650 return;
2651 if (NILP (AREF (font, prop))
2652 && prop != FONT_FAMILY_INDEX && prop != FONT_FAMILY_INDEX)
2653 return;
2654 font = Fcopy_font_spec (font);
2655 ASET (font, prop, Qnil);
2656 if (prop == FONT_FAMILY_INDEX)
2657 {
2658 ASET (font, FONT_FOUNDRY_INDEX, Qnil);
2659 ASET (font, FONT_ADSTYLE_INDEX, Qnil);
2660 ASET (font, FONT_SIZE_INDEX, Qnil);
2661 ASET (font, FONT_DPI_INDEX, Qnil);
2662 ASET (font, FONT_SPACING_INDEX, Qnil);
2663 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
2664 }
2665 else if (prop == FONT_SIZE_INDEX)
2666 {
2667 ASET (font, FONT_DPI_INDEX, Qnil);
2668 ASET (font, FONT_SPACING_INDEX, Qnil);
2669 ASET (font, FONT_AVGWIDTH_INDEX, Qnil);
2670 }
2671 attrs[LFACE_FONT_INDEX] = font;
2656} 2672}
2657 2673
2674void
2675font_update_lface (f, attrs)
2676 FRAME_PTR f;
2677 Lisp_Object *attrs;
2678{
2679 Lisp_Object spec, val;
2680 int n;
2681
2682 spec = attrs[LFACE_FONT_INDEX];
2683 if (! FONT_SPEC_P (spec))
2684 return;
2685
2686 if (! NILP (AREF (spec, FONT_FOUNDRY_INDEX))
2687 || ! NILP (AREF (spec, FONT_FAMILY_INDEX)))
2688 {
2689 Lisp_Object family;
2690
2691 if (NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
2692 family = AREF (spec, FONT_FAMILY_INDEX);
2693 else if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
2694 family = concat2 (SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX)),
2695 build_string ("-*"));
2696 else
2697 family = concat3 (SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX)),
2698 build_string ("-"),
2699 SYMBOL_NAME (AREF (spec, FONT_FAMILY_INDEX)));
2700 attrs[LFACE_FAMILY_INDEX] = family;
2701 }
2702 if (! NILP (AREF (spec, FONT_WEIGHT_INDEX)))
2703 attrs[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (spec);
2704 if (! NILP (AREF (spec, FONT_SLANT_INDEX)))
2705 attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);;
2706 if (! NILP (AREF (spec, FONT_WIDTH_INDEX)))
2707 attrs[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (spec);
2708 if (! NILP (AREF (spec, FONT_SIZE_INDEX)))
2709 {
2710 int point;
2658 2711
2659/* Find a font entity best matching with LFACE. If SPEC is non-nil, 2712 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2660 the font must exactly match with it. C, if not negative, is a 2713 {
2714 Lisp_Object val;
2715 int dpi = f->resy;
2716
2717 val = Ffont_get (spec, QCdpi);
2718 if (! NILP (val))
2719 dpi = XINT (val);
2720 point = PIXEL_TO_POINT (XINT (AREF (spec, FONT_SIZE_INDEX)) * 10,
2721 dpi);
2722 }
2723 else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
2724 point = XFLOAT_DATA (AREF (spec, FONT_SIZE_INDEX)) * 10;
2725 attrs[LFACE_HEIGHT_INDEX] = make_number (point);
2726 }
2727}
2728
2729
2730/* Return a font-entity satisfying SPEC and best matching with face's
2731 font related attributes in ATTRS. C, if not negative, is a
2661 character that the entity must support. */ 2732 character that the entity must support. */
2662 2733
2663Lisp_Object 2734Lisp_Object
2664font_find_for_lface (f, lface, spec, c) 2735font_find_for_lface (f, attrs, spec, c)
2665 FRAME_PTR f; 2736 FRAME_PTR f;
2666 Lisp_Object *lface; 2737 Lisp_Object *attrs;
2667 Lisp_Object spec; 2738 Lisp_Object spec;
2668 int c; 2739 int c;
2669{ 2740{
2670 Lisp_Object frame, entities, val; 2741 Lisp_Object frame, entities, val, props[FONT_REGISTRY_INDEX + 1] ;
2742 Lisp_Object size;
2671 int i, result; 2743 int i, result;
2672 2744
2673 XSETFRAME (frame, f); 2745 if (c >= 0)
2674
2675 if (NILP (spec))
2676 {
2677 if (c >= 0x100)
2678 return Qnil;
2679 for (i = 0; i < FONT_SPEC_MAX; i++)
2680 ASET (scratch_font_spec, i, Qnil);
2681 ASET (scratch_font_spec, FONT_REGISTRY_INDEX, Qiso8859_1);
2682
2683 if (! NILP (lface[LFACE_FAMILY_INDEX]))
2684 font_merge_old_spec (Qnil, lface[LFACE_FAMILY_INDEX], Qnil,
2685 scratch_font_spec);
2686 entities = font_list_entities (frame, scratch_font_spec);
2687 while (ASIZE (entities) == 0)
2688 {
2689 /* Try without FOUNDRY or FAMILY. */
2690 if (! NILP (AREF (scratch_font_spec, FONT_FOUNDRY_INDEX)))
2691 {
2692 ASET (scratch_font_spec, FONT_FOUNDRY_INDEX, Qnil);
2693 entities = font_list_entities (frame, scratch_font_spec);
2694 }
2695 else if (! NILP (AREF (scratch_font_spec, FONT_FAMILY_INDEX)))
2696 {
2697 ASET (scratch_font_spec, FONT_FAMILY_INDEX, Qnil);
2698 entities = font_list_entities (frame, scratch_font_spec);
2699 }
2700 else
2701 break;
2702 }
2703 }
2704 else
2705 { 2746 {
2706 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX); 2747 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
2748 struct charset *encoding, *repertory;
2707 2749
2708 if (NILP (registry)) 2750 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
2709 registry = Qiso8859_1; 2751 return Qnil;
2710 2752 if (repertory)
2711 if (c >= 0)
2712 { 2753 {
2713 struct charset *encoding, *repertory; 2754 if (ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
2714
2715 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
2716 return Qnil;
2717 if (repertory)
2718 {
2719 if (ENCODE_CHAR (repertory, c)
2720 == CHARSET_INVALID_CODE (repertory))
2721 return Qnil;
2722 /* Any font of this registry support C. So, let's
2723 suppress the further checking. */
2724 c = -1;
2725 }
2726 else if (c > encoding->max_char)
2727 return Qnil; 2755 return Qnil;
2756 /* Any font of this registry support C. So, let's
2757 suppress the further checking. */
2758 c = -1;
2728 } 2759 }
2729 for (i = 0; i < FONT_SPEC_MAX; i++) 2760 else if (c > encoding->max_char)
2730 ASET (scratch_font_spec, i, AREF (spec, i)); 2761 return Qnil;
2731 ASET (scratch_font_spec, FONT_REGISTRY_INDEX, registry);
2732 entities = font_list_entities (frame, scratch_font_spec);
2733 } 2762 }
2734 2763
2764 XSETFRAME (frame, f);
2765 size = AREF (spec, FONT_SIZE_INDEX);
2766 ASET (spec, FONT_SIZE_INDEX, Qnil);
2767 entities = font_list_entities (frame, spec);
2768 ASET (spec, FONT_SIZE_INDEX, size);
2735 if (ASIZE (entities) == 0) 2769 if (ASIZE (entities) == 0)
2736 return Qnil; 2770 return Qnil;
2737 if (ASIZE (entities) > 1) 2771 if (ASIZE (entities) == 1)
2772 {
2773 if (c < 0)
2774 return AREF (entities, 0);
2775 }
2776 else
2738 { 2777 {
2739 /* Sort fonts by properties specified in LFACE. */ 2778 /* Sort fonts by properties specified in LFACE. */
2740 Lisp_Object prefer = scratch_font_prefer; 2779 Lisp_Object prefer = scratch_font_prefer;
2741 double pt; 2780 double pt;
2742 2781 for (i = 0; i < FONT_EXTRA_INDEX; i++)
2743 if (! NILP (lface[LFACE_FAMILY_INDEX])) 2782 ASET (prefer, i, AREF (spec, i));
2744 font_merge_old_spec (Qnil, lface[LFACE_FAMILY_INDEX], Qnil, prefer); 2783 if (NILP (AREF (prefer, FONT_FAMILY_INDEX)))
2745 ASET (prefer, FONT_WEIGHT_INDEX, 2784 font_parse_family_registry (attrs[LFACE_FAMILY_INDEX], Qnil, prefer);
2746 font_prop_validate_style (QCweight, lface[LFACE_WEIGHT_INDEX])); 2785 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
2747 ASET (prefer, FONT_SLANT_INDEX, 2786 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
2748 font_prop_validate_style (QCslant, lface[LFACE_SLANT_INDEX])); 2787 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
2749 ASET (prefer, FONT_WIDTH_INDEX, 2788 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
2750 font_prop_validate_style (QCwidth, lface[LFACE_SWIDTH_INDEX])); 2789 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
2751 pt = XINT (lface[LFACE_HEIGHT_INDEX]); 2790 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
2752 ASET (prefer, FONT_SIZE_INDEX, make_float (pt / 10)); 2791 if (INTEGERP (size))
2753 2792 ASET (prefer, FONT_SIZE_INDEX, size);
2754 font_sort_entites (entities, prefer, frame, spec); 2793 else if (FLOATP (size))
2794 ASET (prefer, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2795 else
2796 {
2797 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
2798 int pixel_size = POINT_TO_PIXEL (pt / 10, f->resy);
2799 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
2800 }
2801 ASET (spec, FONT_SIZE_INDEX, Qnil);
2802 entities = font_sort_entites (entities, prefer, frame, spec, c < 0);
2803 ASET (spec, FONT_SIZE_INDEX, size);
2755 } 2804 }
2756
2757 if (c < 0) 2805 if (c < 0)
2758 return AREF (entities, 0); 2806 return entities;
2759 2807
2760 val = AREF (entities, 0); 2808 for (i = 0; i < ASIZE (entities); i++)
2761 result = font_has_char (f, val, c); 2809 {
2762 if (result > 0) 2810 int j;
2763 return val; 2811
2764 if (result == 0) 2812 val = AREF (entities, i);
2765 return Qnil; 2813 if (i > 0)
2766 val = font_open_for_lface (f, val, lface, spec); 2814 {
2767 if (NILP (val)) 2815 for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
2768 return Qnil; 2816 if (! EQ (AREF (val, j), props[j]))
2769 result = font_has_char (f, val, c); 2817 break;
2770 font_close_object (f, val); 2818 if (j > FONT_REGISTRY_INDEX)
2771 if (result > 0) 2819 continue;
2772 return val; 2820 }
2821 for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
2822 props[j] = AREF (val, j);
2823 result = font_has_char (f, val, c);
2824 if (result > 0)
2825 return val;
2826 if (result == 0)
2827 return Qnil;
2828 val = font_open_for_lface (f, val, attrs, spec);
2829 if (NILP (val))
2830 continue;
2831 result = font_has_char (f, val, c);
2832 font_close_object (f, val);
2833 if (result > 0)
2834 return AREF (entities, i);
2835 }
2773 return Qnil; 2836 return Qnil;
2774} 2837}
2775 2838
2776 2839
2777Lisp_Object 2840Lisp_Object
2778font_open_for_lface (f, entity, lface, spec) 2841font_open_for_lface (f, entity, attrs, spec)
2779 FRAME_PTR f; 2842 FRAME_PTR f;
2780 Lisp_Object entity; 2843 Lisp_Object entity;
2781 Lisp_Object *lface; 2844 Lisp_Object *attrs;
2782 Lisp_Object spec; 2845 Lisp_Object spec;
2783{ 2846{
2784 int size; 2847 int size;
@@ -2787,7 +2850,7 @@ font_open_for_lface (f, entity, lface, spec)
2787 size = XINT (AREF (spec, FONT_SIZE_INDEX)); 2850 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2788 else 2851 else
2789 { 2852 {
2790 double pt = XINT (lface[LFACE_HEIGHT_INDEX]); 2853 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
2791 2854
2792 pt /= 10; 2855 pt /= 10;
2793 size = POINT_TO_PIXEL (pt, f->resy); 2856 size = POINT_TO_PIXEL (pt, f->resy);
@@ -2796,46 +2859,28 @@ font_open_for_lface (f, entity, lface, spec)
2796} 2859}
2797 2860
2798 2861
2799/* Load a font best matching with FACE's font-related properties into 2862/* Find a font satisfying SPEC and best matching with face's
2800 FACE on frame F. If no proper font is found, record that FACE has 2863 attributes in ATTRS on FRAME, and return the opened
2801 no font. */ 2864 font-object. */
2802 2865
2803void 2866Lisp_Object
2804font_load_for_face (f, face) 2867font_load_for_lface (f, attrs, spec)
2805 FRAME_PTR f; 2868 FRAME_PTR f;
2806 struct face *face; 2869 Lisp_Object *attrs, spec;
2807{ 2870{
2808 Lisp_Object font_object = face->lface[LFACE_FONT_INDEX]; 2871 Lisp_Object entity;
2809
2810 if (NILP (font_object))
2811 {
2812 Lisp_Object entity = font_find_for_lface (f, face->lface, Qnil, -1);
2813
2814 if (! NILP (entity))
2815 font_object = font_open_for_lface (f, entity, face->lface, Qnil);
2816 }
2817 else if (STRINGP (font_object))
2818 {
2819 font_object = font_open_by_name (f, SDATA (font_object));
2820 }
2821
2822 if (! NILP (font_object))
2823 {
2824 struct font *font = XSAVE_VALUE (font_object)->pointer;
2825 2872
2826 face->font = font->font.font; 2873 entity = font_find_for_lface (f, attrs, spec, -1);
2827 face->font_info = (struct font_info *) font; 2874 if (NILP (entity))
2828 face->font_info_id = 0;
2829 face->font_name = font->font.full_name;
2830 }
2831 else
2832 { 2875 {
2833 face->font = NULL; 2876 /* No font is listed for SPEC, but each font-backend may have
2834 face->font_info = NULL; 2877 the different criteria about "font matching". So, try
2835 face->font_info_id = -1; 2878 it. */
2836 face->font_name = NULL; 2879 entity = font_matching_entity (f, attrs, spec);
2837 add_to_log ("Unable to load font for a face%s", null_string, Qnil); 2880 if (NILP (entity))
2881 return Qnil;
2838 } 2882 }
2883 return font_open_for_lface (f, entity, attrs, spec);
2839} 2884}
2840 2885
2841 2886
@@ -2846,10 +2891,8 @@ font_prepare_for_face (f, face)
2846 FRAME_PTR f; 2891 FRAME_PTR f;
2847 struct face *face; 2892 struct face *face;
2848{ 2893{
2849 struct font *font = (struct font *) face->font_info; 2894 if (face->font->driver->prepare_face)
2850 2895 face->font->driver->prepare_face (f, face);
2851 if (font->driver->prepare_face)
2852 font->driver->prepare_face (f, face);
2853} 2896}
2854 2897
2855 2898
@@ -2860,10 +2903,8 @@ font_done_for_face (f, face)
2860 FRAME_PTR f; 2903 FRAME_PTR f;
2861 struct face *face; 2904 struct face *face;
2862{ 2905{
2863 struct font *font = (struct font *) face->font_info; 2906 if (face->font->driver->done_face)
2864 2907 face->font->driver->done_face (f, face);
2865 if (font->driver->done_face)
2866 font->driver->done_face (f, face);
2867 face->extra = NULL; 2908 face->extra = NULL;
2868} 2909}
2869 2910
@@ -2888,34 +2929,41 @@ font_open_by_name (f, name)
2888 args[1] = make_unibyte_string (name, strlen (name)); 2929 args[1] = make_unibyte_string (name, strlen (name));
2889 spec = Ffont_spec (2, args); 2930 spec = Ffont_spec (2, args);
2890 prefer = scratch_font_prefer; 2931 prefer = scratch_font_prefer;
2891 for (i = FONT_WEIGHT_INDEX; i < FONT_SIZE_INDEX; i++) 2932 for (i = 0; i < FONT_SPEC_MAX; i++)
2892 if (NILP (AREF (spec, i))) 2933 {
2893 ASET (prefer, i, make_number (100)); 2934 ASET (prefer, i, AREF (spec, i));
2935 if (NILP (AREF (prefer, i))
2936 && i >= FONT_WEIGHT_INDEX && i <= FONT_WIDTH_INDEX)
2937 FONT_SET_STYLE (prefer, i, make_number (100));
2938 }
2894 size = AREF (spec, FONT_SIZE_INDEX); 2939 size = AREF (spec, FONT_SIZE_INDEX);
2895 if (NILP (size)) 2940 if (NILP (size))
2896 pixel_size = 0; 2941 pixel_size = 0;
2897 else if (INTEGERP (size)) 2942 else
2898 pixel_size = XINT (size);
2899 else /* FLOATP (size) */
2900 { 2943 {
2901 double pt = XFLOAT_DATA (size); 2944 if (INTEGERP (size))
2945 pixel_size = XINT (size);
2946 else /* FLOATP (size) */
2947 {
2948 double pt = XFLOAT_DATA (size);
2902 2949
2903 pixel_size = POINT_TO_PIXEL (pt, f->resy); 2950 pixel_size = POINT_TO_PIXEL (pt, f->resy);
2904 size = make_number (pixel_size); 2951 }
2905 ASET (spec, FONT_SIZE_INDEX, size); 2952 if (pixel_size == 0)
2953 ASET (spec, FONT_SIZE_INDEX, Qnil);
2906 } 2954 }
2907 if (pixel_size == 0) 2955 if (pixel_size == 0)
2908 { 2956 {
2909 pixel_size = POINT_TO_PIXEL (12.0, f->resy); 2957 pixel_size = POINT_TO_PIXEL (12.0, f->resy);
2910 size = make_number (pixel_size); 2958 size = make_number (pixel_size);
2959 ASET (prefer, FONT_SIZE_INDEX, size);
2911 } 2960 }
2912 ASET (prefer, FONT_SIZE_INDEX, size);
2913 if (NILP (AREF (spec, FONT_REGISTRY_INDEX))) 2961 if (NILP (AREF (spec, FONT_REGISTRY_INDEX)))
2914 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1); 2962 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
2915 2963
2916 entity_list = Flist_fonts (spec, frame, make_number (1), prefer); 2964 entity_list = Flist_fonts (spec, frame, make_number (1), prefer);
2917 if (NILP (entity_list)) 2965 if (NILP (entity_list))
2918 entity = font_matching_entity (frame, spec); 2966 entity = font_matching_entity (f, NULL, spec);
2919 else 2967 else
2920 entity = XCAR (entity_list); 2968 entity = XCAR (entity_list);
2921 return (NILP (entity) 2969 return (NILP (entity)
@@ -3100,6 +3148,7 @@ font_at (c, pos, face, w, string)
3100{ 3148{
3101 FRAME_PTR f; 3149 FRAME_PTR f;
3102 int multibyte; 3150 int multibyte;
3151 Lisp_Object font_object;
3103 3152
3104 if (c < 0) 3153 if (c < 0)
3105 { 3154 {
@@ -3153,21 +3202,97 @@ font_at (c, pos, face, w, string)
3153 int face_id = FACE_FOR_CHAR (f, face, c, pos, string); 3202 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3154 face = FACE_FROM_ID (f, face_id); 3203 face = FACE_FROM_ID (f, face_id);
3155 } 3204 }
3156 if (! face->font_info) 3205 if (! face->font)
3157 return Qnil; 3206 return Qnil;
3158 return font_find_object ((struct font *) face->font_info); 3207
3208 xassert (font_check_object ((struct font *) face->font));
3209 XSETFONT (font_object, face->font);
3210 return font_object;
3211}
3212
3213
3214/* Check how many characters after POS (at most to LIMIT) can be
3215 displayed by the same font. FACE is the face selected for the
3216 character as POS on frame F. STRING, if not nil, is the string to
3217 check instead of the current buffer.
3218
3219 The return value is the position of the character that is displayed
3220 by the differnt font than that of the character as POS. */
3221
3222EMACS_INT
3223font_range (pos, limit, face, f, string)
3224 EMACS_INT pos, limit;
3225 struct face *face;
3226 FRAME_PTR f;
3227 Lisp_Object string;
3228{
3229 int multibyte;
3230 EMACS_INT pos_byte;
3231 int c;
3232 struct font *font;
3233 int first = 1;
3234
3235 if (NILP (string))
3236 {
3237 multibyte = ! NILP (current_buffer->enable_multibyte_characters);
3238 pos_byte = CHAR_TO_BYTE (pos);
3239 }
3240 else
3241 {
3242 multibyte = STRING_MULTIBYTE (string);
3243 pos_byte = string_char_to_byte (string, pos);
3244 }
3245
3246 if (! multibyte)
3247 /* All unibyte character are displayed by the same font. */
3248 return limit;
3249
3250 while (pos < limit)
3251 {
3252 int face_id;
3253
3254 if (NILP (string))
3255 FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
3256 else
3257 FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
3258 face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3259 face = FACE_FROM_ID (f, face_id);
3260 if (first)
3261 {
3262 font = face->font;
3263 first = 0;
3264 continue;
3265 }
3266 else if (font != face->font)
3267 {
3268 pos--;
3269 break;
3270 }
3271 }
3272 return pos;
3159} 3273}
3160 3274
3161 3275
3162/* Lisp API */ 3276/* Lisp API */
3163 3277
3164DEFUN ("fontp", Ffontp, Sfontp, 1, 1, 0, 3278DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3165 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object. 3279 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3166Return nil otherwise. */) 3280Return nil otherwise.
3167 (object) 3281Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3168 Lisp_Object object; 3282which kind of font it is. It must be one of `font-spec', `font-entity'
3283`font-object'. */)
3284 (object, extra_type)
3285 Lisp_Object object, extra_type;
3169{ 3286{
3170 return (FONTP (object) ? Qt : Qnil); 3287 if (NILP (extra_type))
3288 return (FONTP (object) ? Qt : Qnil);
3289 if (EQ (extra_type, Qfont_spec))
3290 return (FONT_SPEC_P (object) ? Qt : Qnil);
3291 if (EQ (extra_type, Qfont_entity))
3292 return (FONT_ENTITY_P (object) ? Qt : Qnil);
3293 if (EQ (extra_type, Qfont_object))
3294 return (FONT_OBJECT_P (object) ? Qt : Qnil);
3295 wrong_type_argument (intern ("font-extra-type"), extra_type);
3171} 3296}
3172 3297
3173DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0, 3298DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
@@ -3188,7 +3313,7 @@ VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3188`:adstyle' 3313`:adstyle'
3189 3314
3190VALUE must be a string or a symbol specifying the additional 3315VALUE must be a string or a symbol specifying the additional
3191typographic style information of a font, e.g. ``sans''. Usually null. 3316typographic style information of a font, e.g. ``sans''.
3192 3317
3193`:registry' 3318`:registry'
3194 3319
@@ -3198,38 +3323,101 @@ encoding of a font, e.g. ``iso8859-1''.
3198`:size' 3323`:size'
3199 3324
3200VALUE must be a non-negative integer or a floating point number 3325VALUE must be a non-negative integer or a floating point number
3201specifying the font size. It specifies the font size in 1/10 pixels 3326specifying the font size. It specifies the font size in pixels
3202(if VALUE is an integer), or in points (if VALUE is a float). 3327(if VALUE is an integer), or in points (if VALUE is a float).
3203usage: (font-spec ARGS ...) */) 3328usage: (font-spec ARGS ...) */)
3204 (nargs, args) 3329 (nargs, args)
3205 int nargs; 3330 int nargs;
3206 Lisp_Object *args; 3331 Lisp_Object *args;
3207{ 3332{
3208 Lisp_Object spec = Fmake_vector (make_number (FONT_SPEC_MAX), Qnil); 3333 Lisp_Object spec = font_make_spec ();
3209 int i; 3334 int i;
3210 3335
3211 for (i = 0; i < nargs; i += 2) 3336 for (i = 0; i < nargs; i += 2)
3212 { 3337 {
3213 enum font_property_index prop;
3214 Lisp_Object key = args[i], val = args[i + 1]; 3338 Lisp_Object key = args[i], val = args[i + 1];
3215 3339
3216 prop = get_font_prop_index (key, 0); 3340 if (EQ (key, QCname))
3217 if (prop < FONT_EXTRA_INDEX) 3341 {
3218 ASET (spec, prop, val); 3342 CHECK_STRING (val);
3343 font_parse_name ((char *) SDATA (val), spec);
3344 font_put_extra (spec, key, val);
3345 }
3346 else if (EQ (key, QCfamily))
3347 {
3348 CHECK_STRING (val);
3349 font_parse_family_registry (val, Qnil, spec);
3350 }
3219 else 3351 else
3220 { 3352 {
3221 if (EQ (key, QCname)) 3353 int idx = get_font_prop_index (key);
3354
3355 if (idx >= 0)
3222 { 3356 {
3223 CHECK_STRING (val); 3357 val = font_prop_validate (idx, Qnil, val);
3224 font_parse_name ((char *) SDATA (val), spec); 3358 if (idx < FONT_EXTRA_INDEX)
3359 ASET (spec, idx, val);
3360 else
3361 font_put_extra (spec, key, val);
3225 } 3362 }
3226 font_put_extra (spec, key, val); 3363 else
3364 font_put_extra (spec, key, font_prop_validate (0, key, val));
3227 } 3365 }
3228 } 3366 }
3229 CHECK_VALIDATE_FONT_SPEC (spec);
3230 return spec; 3367 return spec;
3231} 3368}
3232 3369
3370DEFUN ("copy-font-spec", Fcopy_font_spec, Scopy_font_spec, 1, 1, 0,
3371 doc: /* Return a copy of FONT as a font-spec. */)
3372 (font)
3373 Lisp_Object font;
3374{
3375 Lisp_Object new_spec, tail, extra;
3376 int i;
3377
3378 CHECK_FONT (font);
3379 new_spec = font_make_spec ();
3380 for (i = 1; i < FONT_EXTRA_INDEX; i++)
3381 ASET (new_spec, i, AREF (font, i));
3382 extra = Qnil;
3383 for (tail = AREF (font, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3384 {
3385 if (! EQ (XCAR (XCAR (tail)), QCfont_entity))
3386 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
3387 }
3388 ASET (new_spec, FONT_EXTRA_INDEX, extra);
3389 return new_spec;
3390}
3391
3392DEFUN ("merge-font-spec", Fmerge_font_spec, Smerge_font_spec, 2, 2, 0,
3393 doc: /* Merge font-specs FROM and TO, and return a new font-spec.
3394Every specified properties in FROM override the corresponding
3395properties in TO. */)
3396 (from, to)
3397 Lisp_Object from, to;
3398{
3399 Lisp_Object extra, tail;
3400 int i;
3401
3402 CHECK_FONT (from);
3403 CHECK_FONT (to);
3404 to = Fcopy_font_spec (to);
3405 for (i = 0; i < FONT_EXTRA_INDEX; i++)
3406 ASET (to, i, AREF (from, i));
3407 extra = AREF (to, FONT_EXTRA_INDEX);
3408 for (tail = AREF (from, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
3409 if (! EQ (XCAR (XCAR (tail)), Qfont_entity))
3410 {
3411 Lisp_Object slot = assq_no_quit (XCAR (XCAR (tail)), extra);
3412
3413 if (! NILP (slot))
3414 XSETCDR (slot, XCDR (XCAR (tail)));
3415 else
3416 extra = Fcons (Fcons (XCAR (XCAR (tail)), XCDR (XCAR (tail))), extra);
3417 }
3418 ASET (to, FONT_EXTRA_INDEX, extra);
3419 return to;
3420}
3233 3421
3234DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0, 3422DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
3235 doc: /* Return the value of FONT's property KEY. 3423 doc: /* Return the value of FONT's property KEY.
@@ -3237,29 +3425,15 @@ FONT is a font-spec, a font-entity, or a font-object. */)
3237 (font, key) 3425 (font, key)
3238 Lisp_Object font, key; 3426 Lisp_Object font, key;
3239{ 3427{
3240 enum font_property_index idx; 3428 int idx;
3241 3429
3242 if (FONT_OBJECT_P (font)) 3430 CHECK_FONT (font);
3243 { 3431 CHECK_SYMBOL (key);
3244 struct font *fontp = XSAVE_VALUE (font)->pointer;
3245 3432
3246 if (EQ (key, QCotf)) 3433 idx = get_font_prop_index (key);
3247 { 3434 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3248 if (fontp->driver->otf_capability)
3249 return fontp->driver->otf_capability (fontp);
3250 else
3251 return Qnil;
3252 }
3253 font = fontp->entity;
3254 }
3255 else
3256 CHECK_FONT (font);
3257 idx = get_font_prop_index (key, 0);
3258 if (idx < FONT_EXTRA_INDEX)
3259 return AREF (font, idx); 3435 return AREF (font, idx);
3260 if (FONT_ENTITY_P (font)) 3436 return Fcdr (Fassq (key, AREF (font, FONT_EXTRA_INDEX)));
3261 return Qnil;
3262 return Fcdr (Fassoc (key, AREF (font, FONT_EXTRA_INDEX)));
3263} 3437}
3264 3438
3265 3439
@@ -3268,19 +3442,21 @@ DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
3268 (font_spec, prop, val) 3442 (font_spec, prop, val)
3269 Lisp_Object font_spec, prop, val; 3443 Lisp_Object font_spec, prop, val;
3270{ 3444{
3271 enum font_property_index idx; 3445 int idx;
3272 Lisp_Object extra, slot; 3446 Lisp_Object extra, slot;
3273 3447
3274 CHECK_FONT_SPEC (font_spec); 3448 CHECK_FONT_SPEC (font_spec);
3275 idx = get_font_prop_index (prop, 0); 3449 idx = get_font_prop_index (prop);
3276 if (idx < FONT_EXTRA_INDEX) 3450 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3277 return ASET (font_spec, idx, val); 3451 {
3278 extra = AREF (font_spec, FONT_EXTRA_INDEX); 3452 if (idx == FONT_FAMILY_INDEX
3279 slot = Fassoc (extra, prop); 3453 && STRINGP (val))
3280 if (NILP (slot)) 3454 font_parse_family_registry (val, Qnil, font_spec);
3281 extra = Fcons (Fcons (prop, val), extra); 3455 else
3456 ASET (font_spec, idx, font_prop_validate (idx, Qnil, val));
3457 }
3282 else 3458 else
3283 Fsetcdr (slot, val); 3459 font_put_extra (font_spec, prop, font_prop_validate (0, prop, val));
3284 return val; 3460 return val;
3285} 3461}
3286 3462
@@ -3300,7 +3476,7 @@ how they are close to PREFER. */)
3300 if (NILP (frame)) 3476 if (NILP (frame))
3301 frame = selected_frame; 3477 frame = selected_frame;
3302 CHECK_LIVE_FRAME (frame); 3478 CHECK_LIVE_FRAME (frame);
3303 CHECK_VALIDATE_FONT_SPEC (font_spec); 3479 CHECK_FONT_SPEC (font_spec);
3304 if (! NILP (num)) 3480 if (! NILP (num))
3305 { 3481 {
3306 CHECK_NUMBER (num); 3482 CHECK_NUMBER (num);
@@ -3309,7 +3485,7 @@ how they are close to PREFER. */)
3309 return Qnil; 3485 return Qnil;
3310 } 3486 }
3311 if (! NILP (prefer)) 3487 if (! NILP (prefer))
3312 CHECK_FONT (prefer); 3488 CHECK_FONT_SPEC (prefer);
3313 3489
3314 vec = font_list_entities (frame, font_spec); 3490 vec = font_list_entities (frame, font_spec);
3315 len = ASIZE (vec); 3491 len = ASIZE (vec);
@@ -3319,7 +3495,7 @@ how they are close to PREFER. */)
3319 return Fcons (AREF (vec, 0), Qnil); 3495 return Fcons (AREF (vec, 0), Qnil);
3320 3496
3321 if (! NILP (prefer)) 3497 if (! NILP (prefer))
3322 vec = font_sort_entites (vec, prefer, frame, font_spec); 3498 vec = font_sort_entites (vec, prefer, frame, font_spec, 0);
3323 3499
3324 list = tail = Fcons (AREF (vec, 0), Qnil); 3500 list = tail = Fcons (AREF (vec, 0), Qnil);
3325 if (n == 0 || n > len) 3501 if (n == 0 || n > len)
@@ -3334,7 +3510,7 @@ how they are close to PREFER. */)
3334 return list; 3510 return list;
3335} 3511}
3336 3512
3337DEFUN ("list-families", Flist_families, Slist_families, 0, 1, 0, 3513DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
3338 doc: /* List available font families on the current frame. 3514 doc: /* List available font families on the current frame.
3339Optional argument FRAME specifies the target frame. */) 3515Optional argument FRAME specifies the target frame. */)
3340 (frame) 3516 (frame)
@@ -3392,19 +3568,17 @@ If the name is too long for XLFD (maximum 255 chars), return nil. */)
3392 char name[256]; 3568 char name[256];
3393 int pixel_size = 0; 3569 int pixel_size = 0;
3394 3570
3395 if (FONT_SPEC_P (font)) 3571 CHECK_FONT (font);
3396 CHECK_VALIDATE_FONT_SPEC (font); 3572
3397 else if (FONT_ENTITY_P (font)) 3573 if (FONT_OBJECT_P (font))
3398 CHECK_FONT (font);
3399 else
3400 { 3574 {
3401 struct font *fontp; 3575 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
3402 3576
3403 CHECK_FONT_GET_OBJECT (font, fontp); 3577 if (STRINGP (font_name)
3404 font = fontp->entity; 3578 && SDATA (font_name)[0] == '-')
3405 pixel_size = fontp->pixel_size; 3579 return font_name;
3580 pixel_size = XFONT_OBJECT (font)->pixel_size;
3406 } 3581 }
3407
3408 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0) 3582 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
3409 return Qnil; 3583 return Qnil;
3410 return build_string (name); 3584 return build_string (name);
@@ -3445,41 +3619,55 @@ DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
3445} 3619}
3446 3620
3447DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table, 3621DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table,
3448 Sinternal_set_font_style_table, 2, 2, 0, 3622 Sinternal_set_font_style_table, 3, 3, 0,
3449 doc: /* Set font style table for PROP to TABLE. 3623 doc: /* Setup font style table from WEIGHT, SLANT, and WIDTH tables.
3450PROP must be `:weight', `:slant', or `:width'. 3624WEIGHT, SLANT, WIDTH must be `font-weight-table', `font-slant-table',
3451TABLE must be an alist of symbols vs the corresponding numeric values 3625`font-width-table' respectivly.
3452sorted by numeric values. */) 3626This function is called after those tables are initialized. */)
3453 (prop, table) 3627 (weight, slant, width)
3454 Lisp_Object prop, table; 3628 Lisp_Object weight, slant, width;
3455{ 3629{
3456 int table_index; 3630 Lisp_Object tables[3];
3457 int numeric; 3631 int i;
3458 Lisp_Object tail, val; 3632
3633 tables[0] = weight, tables[1] = slant, tables[2] = width;
3459 3634
3460 CHECK_SYMBOL (prop); 3635 font_style_table = Fmake_vector (make_number (3), Qnil);
3461 table_index = (EQ (prop, QCweight) ? 0 3636 /* In the following loop, we don't use XCAR and XCDR until assuring
3462 : EQ (prop, QCslant) ? 1 3637 the argument is a cons cell so that the error in the tables can
3463 : EQ (prop, QCwidth) ? 2 3638 be detected. */
3464 : 3); 3639 for (i = 0; i < 3; i++)
3465 if (table_index >= ASIZE (font_style_table))
3466 error ("Invalid font style property: %s", SDATA (SYMBOL_NAME (prop)));
3467 table = Fcopy_sequence (table);
3468 numeric = -1;
3469 for (tail = table; CONSP (tail); tail = XCDR (tail))
3470 { 3640 {
3471 prop = Fcar (XCAR (tail)); 3641 Lisp_Object tail, elt, list, val;
3472 val = Fcdr (XCAR (tail)); 3642
3473 CHECK_SYMBOL (prop); 3643 for (tail = tables[i], list = Qnil; CONSP (tail); tail = XCDR (tail))
3474 CHECK_NATNUM (val); 3644 {
3475 if (numeric > XINT (val)) 3645 int numeric = -1;
3476 error ("Numeric values not sorted for %s", SDATA (SYMBOL_NAME (prop))); 3646
3477 else if (numeric == XINT (val)) 3647 elt = Fcar (tail);
3478 error ("Duplicate numeric values for %s", SDATA (SYMBOL_NAME (prop))); 3648 CHECK_SYMBOL (Fcar (elt));
3479 numeric = XINT (val); 3649 val = Fcons (XCAR (elt), Qnil);
3480 XSETCAR (tail, Fcons (prop, val)); 3650 elt = XCDR (elt);
3651 CHECK_NATNUM (Fcar (elt));
3652 if (numeric >= XINT (XCAR (elt)))
3653 error ("Numeric values not unique nor sorted in %s",
3654 (i == 0 ? "font-weight-table"
3655 : i == 1 ? "font-slant-table"
3656 : "font-width-table"));
3657 numeric = XINT (XCAR (elt));
3658 XSETCDR (val, XCAR (elt));
3659 list = Fcons (val, list);
3660 for (elt = XCDR (elt); CONSP (elt); elt = XCDR (elt))
3661 {
3662 val = XCAR (elt);
3663 CHECK_SYMBOL (val);
3664 list = Fcons (Fcons (XCAR (elt), make_number (numeric)), list);
3665 }
3666 }
3667 list = Fnreverse (list);
3668 ASET (font_style_table, i, Fvconcat (1, &list));
3481 } 3669 }
3482 ASET (font_style_table, table_index, table); 3670
3483 return Qnil; 3671 return Qnil;
3484} 3672}
3485 3673
@@ -3544,7 +3732,7 @@ FONT-OBJECT may be nil if GSTRING already already contains one. */)
3544 CHECK_VECTOR (gstring); 3732 CHECK_VECTOR (gstring);
3545 if (NILP (font_object)) 3733 if (NILP (font_object))
3546 font_object = LGSTRING_FONT (gstring); 3734 font_object = LGSTRING_FONT (gstring);
3547 CHECK_FONT_GET_OBJECT (font_object, font); 3735 font = XFONT_OBJECT (font_object);
3548 3736
3549 if (STRINGP (object)) 3737 if (STRINGP (object))
3550 { 3738 {
@@ -3623,11 +3811,11 @@ FONT-OBJECT. */)
3623 struct font_metrics metrics; 3811 struct font_metrics metrics;
3624 EMACS_INT start, end; 3812 EMACS_INT start, end;
3625 Lisp_Object gstring, n; 3813 Lisp_Object gstring, n;
3626 int len, i, j; 3814 int len, i;
3627 3815
3628 if (! FONT_OBJECT_P (font_object)) 3816 if (! FONT_OBJECT_P (font_object))
3629 return Qnil; 3817 return Qnil;
3630 CHECK_FONT_GET_OBJECT (font_object, font); 3818 font = XFONT_OBJECT (font_object);
3631 if (! font->driver->shape) 3819 if (! font->driver->shape)
3632 return Qnil; 3820 return Qnil;
3633 3821
@@ -3792,7 +3980,8 @@ glyph-string. */)
3792 int len, num; 3980 int len, num;
3793 3981
3794 check_otf_features (otf_features); 3982 check_otf_features (otf_features);
3795 CHECK_FONT_GET_OBJECT (font_object, font); 3983 CHECK_FONT_OBJECT (font_object);
3984 font = XFONT_OBJECT (font_object);
3796 if (! font->driver->otf_drive) 3985 if (! font->driver->otf_drive)
3797 error ("Font backend %s can't drive OpenType GSUB table", 3986 error ("Font backend %s can't drive OpenType GSUB table",
3798 SDATA (SYMBOL_NAME (font->driver->type))); 3987 SDATA (SYMBOL_NAME (font->driver->type)));
@@ -3883,19 +4072,22 @@ DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
3883 int isize; 4072 int isize;
3884 4073
3885 CHECK_FONT_ENTITY (font_entity); 4074 CHECK_FONT_ENTITY (font_entity);
3886 if (NILP (size))
3887 size = AREF (font_entity, FONT_SIZE_INDEX);
3888 CHECK_NUMBER (size);
3889 if (NILP (frame)) 4075 if (NILP (frame))
3890 frame = selected_frame; 4076 frame = selected_frame;
3891 CHECK_LIVE_FRAME (frame); 4077 CHECK_LIVE_FRAME (frame);
3892 4078
3893 isize = XINT (size); 4079 if (NILP (size))
3894 if (isize == 0) 4080 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
3895 isize = 120; 4081 else
3896 if (isize < 0) 4082 {
3897 isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy); 4083 CHECK_NUMBER_OR_FLOAT (size);
3898 4084 if (FLOATP (size))
4085 isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy);
4086 else
4087 isize = XINT (size);
4088 if (isize == 0)
4089 isize = 120;
4090 }
3899 return font_open_entity (XFRAME (frame), font_entity, isize); 4091 return font_open_entity (XFRAME (frame), font_entity, isize);
3900} 4092}
3901 4093
@@ -3962,22 +4154,16 @@ If the font is not OpenType font, CAPABILITY is nil. */)
3962 CHECK_FONT_GET_OBJECT (font_object, font); 4154 CHECK_FONT_GET_OBJECT (font_object, font);
3963 4155
3964 val = Fmake_vector (make_number (9), Qnil); 4156 val = Fmake_vector (make_number (9), Qnil);
3965 if (font->font.full_name) 4157 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
3966 ASET (val, 0, make_unibyte_string (font->font.full_name, 4158 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
3967 strlen (font->font.full_name)));
3968 if (font->file_name)
3969 ASET (val, 1, make_unibyte_string (font->file_name,
3970 strlen (font->file_name)));
3971 ASET (val, 2, make_number (font->pixel_size)); 4159 ASET (val, 2, make_number (font->pixel_size));
3972 ASET (val, 3, make_number (font->font.size)); 4160 ASET (val, 3, make_number (font->max_width));
3973 ASET (val, 4, make_number (font->ascent)); 4161 ASET (val, 4, make_number (font->ascent));
3974 ASET (val, 5, make_number (font->descent)); 4162 ASET (val, 5, make_number (font->descent));
3975 ASET (val, 6, make_number (font->font.space_width)); 4163 ASET (val, 6, make_number (font->space_width));
3976 ASET (val, 7, make_number (font->font.average_width)); 4164 ASET (val, 7, make_number (font->average_width));
3977 if (font->driver->otf_capability) 4165 if (font->driver->otf_capability)
3978 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font))); 4166 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
3979 else
3980 ASET (val, 8, Fcons (font->format, Qnil));
3981 return val; 4167 return val;
3982} 4168}
3983 4169
@@ -4031,10 +4217,7 @@ FONT is a font-spec, font-entity, or font-object. */)
4031 Lisp_Object spec, font; 4217 Lisp_Object spec, font;
4032{ 4218{
4033 CHECK_FONT_SPEC (spec); 4219 CHECK_FONT_SPEC (spec);
4034 if (FONT_OBJECT_P (font)) 4220 CHECK_FONT (font);
4035 font = ((struct font *) XSAVE_VALUE (font)->pointer)->entity;
4036 else if (! FONT_ENTITY_P (font))
4037 CHECK_FONT_SPEC (font);
4038 4221
4039 return (font_match_p (spec, font) ? Qt : Qnil); 4222 return (font_match_p (spec, font) ? Qt : Qnil);
4040} 4223}
@@ -4058,9 +4241,6 @@ the current buffer. It defaults to the currently selected window. */)
4058 } 4241 }
4059 else 4242 else
4060 { 4243 {
4061 EMACS_INT len;
4062 unsigned char *str;
4063
4064 CHECK_NUMBER (position); 4244 CHECK_NUMBER (position);
4065 CHECK_STRING (string); 4245 CHECK_STRING (string);
4066 pos = XINT (position); 4246 pos = XINT (position);
@@ -4138,18 +4318,19 @@ syms_of_font ()
4138 sort_shift_bits[FONT_ADSTYLE_INDEX] = 28; 4318 sort_shift_bits[FONT_ADSTYLE_INDEX] = 28;
4139 sort_shift_bits[FONT_FOUNDRY_INDEX] = 29; 4319 sort_shift_bits[FONT_FOUNDRY_INDEX] = 29;
4140 sort_shift_bits[FONT_FAMILY_INDEX] = 30; 4320 sort_shift_bits[FONT_FAMILY_INDEX] = 30;
4141 sort_shift_bits[FONT_REGISTRY_INDEX] = 31; 4321 /* Note that sort_shift_bits[FONT_SORT_TYPE] and
4142 /* Note that sort_shift_bits[FONT_TYPE_INDEX] is never used. */ 4322 sort_shift_bits[FONT_SORT_REGISTRY] are never used. */
4143 4323
4144 staticpro (&font_style_table); 4324 staticpro (&font_style_table);
4145 font_style_table = Fmake_vector (make_number (3), Qnil); 4325 font_style_table = Fmake_vector (make_number (3), Qnil);
4146 4326
4147 staticpro (&font_family_alist);
4148 font_family_alist = Qnil;
4149
4150 staticpro (&font_charset_alist); 4327 staticpro (&font_charset_alist);
4151 font_charset_alist = Qnil; 4328 font_charset_alist = Qnil;
4152 4329
4330 DEFSYM (Qfont_spec, "font-spec");
4331 DEFSYM (Qfont_entity, "font-entity");
4332 DEFSYM (Qfont_object, "font-object");
4333
4153 DEFSYM (Qopentype, "opentype"); 4334 DEFSYM (Qopentype, "opentype");
4154 4335
4155 DEFSYM (Qiso8859_1, "iso8859-1"); 4336 DEFSYM (Qiso8859_1, "iso8859-1");
@@ -4158,7 +4339,7 @@ syms_of_font ()
4158 DEFSYM (Qunicode_sip, "unicode-sip"); 4339 DEFSYM (Qunicode_sip, "unicode-sip");
4159 4340
4160 DEFSYM (QCotf, ":otf"); 4341 DEFSYM (QCotf, ":otf");
4161 DEFSYM (QClanguage, ":language"); 4342 DEFSYM (QClang, ":lang");
4162 DEFSYM (QCscript, ":script"); 4343 DEFSYM (QCscript, ":script");
4163 DEFSYM (QCantialias, ":antialias"); 4344 DEFSYM (QCantialias, ":antialias");
4164 4345
@@ -4168,15 +4349,15 @@ syms_of_font ()
4168 DEFSYM (QCspacing, ":spacing"); 4349 DEFSYM (QCspacing, ":spacing");
4169 DEFSYM (QCdpi, ":dpi"); 4350 DEFSYM (QCdpi, ":dpi");
4170 DEFSYM (QCscalable, ":scalable"); 4351 DEFSYM (QCscalable, ":scalable");
4171 DEFSYM (QCextra, ":extra"); 4352 DEFSYM (QCavgwidth, ":avgwidth");
4353 DEFSYM (QCfont_entity, ":font-entity");
4354 DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
4172 4355
4173 DEFSYM (Qc, "c"); 4356 DEFSYM (Qc, "c");
4174 DEFSYM (Qm, "m"); 4357 DEFSYM (Qm, "m");
4175 DEFSYM (Qp, "p"); 4358 DEFSYM (Qp, "p");
4176 DEFSYM (Qd, "d"); 4359 DEFSYM (Qd, "d");
4177 4360
4178 staticpro (&null_string);
4179 null_string = build_string ("");
4180 staticpro (&null_vector); 4361 staticpro (&null_vector);
4181 null_vector = Fmake_vector (make_number (0), Qnil); 4362 null_vector = Fmake_vector (make_number (0), Qnil);
4182 4363
@@ -4195,7 +4376,7 @@ syms_of_font ()
4195 defsubr (&Sfont_get); 4376 defsubr (&Sfont_get);
4196 defsubr (&Sfont_put); 4377 defsubr (&Sfont_put);
4197 defsubr (&Slist_fonts); 4378 defsubr (&Slist_fonts);
4198 defsubr (&Slist_families); 4379 defsubr (&Sfont_family_list);
4199 defsubr (&Sfind_font); 4380 defsubr (&Sfind_font);
4200 defsubr (&Sfont_xlfd_name); 4381 defsubr (&Sfont_xlfd_name);
4201 defsubr (&Sclear_font_cache); 4382 defsubr (&Sclear_font_cache);
@@ -4218,34 +4399,29 @@ syms_of_font ()
4218#endif 4399#endif
4219#endif /* FONT_DEBUG */ 4400#endif /* FONT_DEBUG */
4220 4401
4221#ifdef USE_FONT_BACKEND
4222 if (enable_font_backend)
4223 {
4224#ifdef HAVE_FREETYPE 4402#ifdef HAVE_FREETYPE
4225 syms_of_ftfont (); 4403 syms_of_ftfont ();
4226#ifdef HAVE_X_WINDOWS 4404#ifdef HAVE_X_WINDOWS
4227 syms_of_xfont (); 4405 syms_of_xfont ();
4228 syms_of_ftxfont (); 4406 syms_of_ftxfont ();
4229#ifdef HAVE_XFT 4407#ifdef HAVE_XFT
4230 syms_of_xftfont (); 4408 syms_of_xftfont ();
4231#endif /* HAVE_XFT */ 4409#endif /* HAVE_XFT */
4232#endif /* HAVE_X_WINDOWS */ 4410#endif /* HAVE_X_WINDOWS */
4233#else /* not HAVE_FREETYPE */ 4411#else /* not HAVE_FREETYPE */
4234#ifdef HAVE_X_WINDOWS 4412#ifdef HAVE_X_WINDOWS
4235 syms_of_xfont (); 4413 syms_of_xfont ();
4236#endif /* HAVE_X_WINDOWS */ 4414#endif /* HAVE_X_WINDOWS */
4237#endif /* not HAVE_FREETYPE */ 4415#endif /* not HAVE_FREETYPE */
4238#ifdef HAVE_BDFFONT 4416#ifdef HAVE_BDFFONT
4239 syms_of_bdffont (); 4417 syms_of_bdffont ();
4240#endif /* HAVE_BDFFONT */ 4418#endif /* HAVE_BDFFONT */
4241#ifdef WINDOWSNT 4419#ifdef WINDOWSNT
4242 syms_of_w32font (); 4420 syms_of_w32font ();
4243#endif /* WINDOWSNT */ 4421#endif /* WINDOWSNT */
4244#ifdef MAC_OS 4422#ifdef MAC_OS
4245 syms_of_atmfont (); 4423 syms_of_atmfont ();
4246#endif /* MAC_OS */ 4424#endif /* MAC_OS */
4247 }
4248#endif /* USE_FONT_BACKEND */
4249} 4425}
4250 4426
4251/* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846 4427/* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846