Merge from emacs--rel--22
[bpt/emacs.git] / src / font.c
1 /* font.c -- "Font" primitives.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7 This file is part of GNU Emacs.
8
9 GNU Emacs is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
23
24 #include <config.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <strings.h>
28 #include <ctype.h>
29 #ifdef HAVE_M17N_FLT
30 #include <m17n-flt.h>
31 #endif
32
33 #include "lisp.h"
34 #include "buffer.h"
35 #include "frame.h"
36 #include "window.h"
37 #include "dispextern.h"
38 #include "charset.h"
39 #include "character.h"
40 #include "composite.h"
41 #include "fontset.h"
42 #include "font.h"
43
44 #ifdef HAVE_X_WINDOWS
45 #include "xterm.h"
46 #endif /* HAVE_X_WINDOWS */
47
48 #ifdef HAVE_NTGUI
49 #include "w32term.h"
50 #endif /* HAVE_NTGUI */
51
52 #ifdef MAC_OS
53 #include "macterm.h"
54 #endif /* MAC_OS */
55
56 #ifndef FONT_DEBUG
57 #define FONT_DEBUG
58 #endif
59
60 #ifdef FONT_DEBUG
61 #undef xassert
62 #define xassert(X) do {if (!(X)) abort ();} while (0)
63 #else
64 #define xassert(X) (void) 0
65 #endif
66
67 Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
68
69 Lisp_Object Qopentype;
70
71 /* Important character set strings. */
72 Lisp_Object Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
73
74 /* Special vector of zero length. This is repeatedly used by (struct
75 font_driver *)->list when a specified font is not found. */
76 static Lisp_Object null_vector;
77
78 /* Vector of 3 elements. Each element is a vector for one of font
79 style properties (weight, slant, width). The vector contains a
80 mapping between symbolic property values (e.g. `medium' for weight)
81 and numeric property values (e.g. 100). So, it looks like this:
82 [[(ultra-light . 20) ... (black . 210)]
83 [(reverse-oblique . 0) ... (oblique . 210)]
84 [(ultra-contains . 50) ... (wide . 200)]] */
85 static Lisp_Object font_style_table;
86
87 extern Lisp_Object Qnormal;
88
89 /* Symbols representing keys of normal font properties. */
90 extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth, QCsize, QCname;
91 Lisp_Object QCfoundry, QCadstyle, QCregistry;
92 /* Symbols representing keys of font extra info. */
93 Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
94 Lisp_Object QCantialias, QCfont_entity, QCfc_unknown_spec;
95 /* Symbols representing values of font spacing property. */
96 Lisp_Object Qc, Qm, Qp, Qd;
97
98 /* Alist of font registry symbol and the corresponding charsets
99 information. The information is retrieved from
100 Vfont_encoding_alist on demand.
101
102 Eash element has the form:
103 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
104 or
105 (REGISTRY . nil)
106
107 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
108 encodes a character code to a glyph code of a font, and
109 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
110 character is supported by a font.
111
112 The latter form means that the information for REGISTRY couldn't be
113 retrieved. */
114 static Lisp_Object font_charset_alist;
115
116 /* List of all font drivers. Each font-backend (XXXfont.c) calls
117 register_font_driver in syms_of_XXXfont to register its font-driver
118 here. */
119 static struct font_driver_list *font_driver_list;
120
121 \f
122
123 /* Creaters of font-related Lisp object. */
124
125 Lisp_Object
126 font_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
137 Lisp_Object
138 font_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
149 Lisp_Object
150 font_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 \f
162
163 static int font_pixel_size P_ ((FRAME_PTR f, Lisp_Object));
164 static Lisp_Object font_open_entity P_ ((FRAME_PTR, Lisp_Object, int));
165 static Lisp_Object font_matching_entity P_ ((FRAME_PTR, Lisp_Object *,
166 Lisp_Object));
167
168 /* Number of registered font drivers. */
169 static int num_font_drivers;
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
177 Lisp_Object
178 font_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
207 /* Return a pixel size of font-spec SPEC on frame F. */
208
209 static int
210 font_pixel_size (f, spec)
211 FRAME_PTR f;
212 Lisp_Object spec;
213 {
214 Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
215 double point_size;
216 int dpi, pixel_size;
217 Lisp_Object extra, val;
218
219 if (INTEGERP (size))
220 return XINT (size);
221 if (NILP (size))
222 return 0; xassert (FLOATP (size));
223 point_size = XFLOAT_DATA (size);
224 val = AREF (spec, FONT_DPI_INDEX);
225 if (INTEGERP (val))
226 dpi = XINT (XCDR (val));
227 else
228 dpi = f->resy;
229 pixel_size = POINT_TO_PIXEL (point_size, dpi);
230 return pixel_size;
231 }
232
233
234 /* Return a value of PROP's VAL (symbol or integer) to be stored in a
235 font vector. If VAL is not valid (i.e. not registered in
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. */
240
241 int
242 font_style_to_value (prop, val, noerror)
243 enum font_property_index prop;
244 Lisp_Object val;
245 int noerror;
246 {
247 Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
248 int len = ASIZE (table);
249 int i;
250
251 if (SYMBOLP (val))
252 {
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++)
263 {
264 elt = XCAR (AREF (table, i));
265 if (strcasecmp (s, (char *) SDATA (SYMBOL_NAME (elt))) == 0)
266 return i;
267 }
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;
276 }
277 else
278 {
279 int last_i, i, last_n;
280 int numeric = XINT (val);
281
282 for (i = 1, last_i = last_n = -1; i < len;)
283 {
284 int n = XINT (XCDR (AREF (table, i)));
285
286 if (numeric == n)
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 }
304
305 Lisp_Object
306 font_style_symbolic (font, prop, for_face)
307 Lisp_Object font;
308 enum font_property_index prop;
309 int for_face;
310 {
311 Lisp_Object val = AREF (font, prop);
312 Lisp_Object table;
313 int i, numeric;
314
315 if (NILP (val))
316 return Qnil;
317 table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
318 if (! for_face)
319 return XCAR (AREF (table, XINT (val) & 0xFF));
320 numeric = XINT (val) >> 8;
321 for (i = 0; i < ASIZE (table); i++)
322 if (XINT (XCDR (AREF (table, i))) == numeric)
323 return XCAR (AREF (table, i));
324 abort ();
325 return Qnil;
326 }
327
328 extern Lisp_Object Vface_alternative_font_family_alist;
329
330 extern Lisp_Object find_font_encoding P_ ((Lisp_Object));
331
332
333 /* Return encoding charset and repertory charset for REGISTRY in
334 ENCODING and REPERTORY correspondingly. If correct information for
335 REGISTRY is available, return 0. Otherwise return -1. */
336
337 int
338 font_registry_charsets (registry, encoding, repertory)
339 Lisp_Object registry;
340 struct charset **encoding, **repertory;
341 {
342 Lisp_Object val;
343 int encoding_id, repertory_id;
344
345 val = Fassoc_string (registry, font_charset_alist, Qt);
346 if (! NILP (val))
347 {
348 val = XCDR (val);
349 if (NILP (val))
350 return -1;
351 encoding_id = XINT (XCAR (val));
352 repertory_id = XINT (XCDR (val));
353 }
354 else
355 {
356 val = find_font_encoding (SYMBOL_NAME (registry));
357 if (SYMBOLP (val) && CHARSETP (val))
358 {
359 encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val));
360 }
361 else if (CONSP (val))
362 {
363 if (! CHARSETP (XCAR (val)))
364 goto invalid_entry;
365 encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val)));
366 if (NILP (XCDR (val)))
367 repertory_id = -1;
368 else
369 {
370 if (! CHARSETP (XCDR (val)))
371 goto invalid_entry;
372 repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val)));
373 }
374 }
375 else
376 goto invalid_entry;
377 val = Fcons (make_number (encoding_id), make_number (repertory_id));
378 font_charset_alist
379 = nconc2 (font_charset_alist, Fcons (Fcons (registry, val), Qnil));
380 }
381
382 if (encoding)
383 *encoding = CHARSET_FROM_ID (encoding_id);
384 if (repertory)
385 *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL;
386 return 0;
387
388 invalid_entry:
389 font_charset_alist
390 = nconc2 (font_charset_alist, Fcons (Fcons (registry, Qnil), Qnil));
391 return -1;
392 }
393
394 \f
395 /* Font property value validaters. See the comment of
396 font_property_table for the meaning of the arguments. */
397
398 static Lisp_Object font_prop_validate P_ ((int, Lisp_Object, Lisp_Object));
399 static Lisp_Object font_prop_validate_symbol P_ ((Lisp_Object, Lisp_Object));
400 static Lisp_Object font_prop_validate_style P_ ((Lisp_Object, Lisp_Object));
401 static Lisp_Object font_prop_validate_non_neg P_ ((Lisp_Object, Lisp_Object));
402 static Lisp_Object font_prop_validate_spacing P_ ((Lisp_Object, Lisp_Object));
403 static int get_font_prop_index P_ ((Lisp_Object));
404
405 static Lisp_Object
406 font_prop_validate_symbol (prop, val)
407 Lisp_Object prop, val;
408 {
409 if (STRINGP (val))
410 val = Fintern (val, Qnil);
411 if (! SYMBOLP (val))
412 val = Qerror;
413 else if (EQ (prop, QCregistry))
414 val = Fintern (Fdowncase (SYMBOL_NAME (val)), Qnil);
415 return val;
416 }
417
418
419 static Lisp_Object
420 font_prop_validate_style (style, val)
421 Lisp_Object style, val;
422 {
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))
428 {
429 n = XINT (val);
430 if ((n & 0xFF)
431 >= ASIZE (AREF (font_style_table, prop - FONT_WEIGHT_INDEX)))
432 val = Qerror;
433 else
434 {
435 Lisp_Object elt = AREF (AREF (font_style_table, prop - FONT_WEIGHT_INDEX), n & 0xFF);
436 if (XINT (XCDR (elt)) != (n >> 8))
437 val = Qerror;
438 }
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;
448 return val;
449 }
450
451 static Lisp_Object
452 font_prop_validate_non_neg (prop, val)
453 Lisp_Object prop, val;
454 {
455 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
456 ? val : Qerror);
457 }
458
459 static Lisp_Object
460 font_prop_validate_spacing (prop, val)
461 Lisp_Object prop, val;
462 {
463 if (NILP (val) || (NATNUMP (val) && XINT (val) <= FONT_SPACING_CHARCELL))
464 return val;
465 if (EQ (val, Qc))
466 return make_number (FONT_SPACING_CHARCELL);
467 if (EQ (val, Qm))
468 return make_number (FONT_SPACING_MONO);
469 if (EQ (val, Qp))
470 return make_number (FONT_SPACING_PROPORTIONAL);
471 if (EQ (val, Qd))
472 return make_number (FONT_SPACING_DUAL);
473 return Qerror;
474 }
475
476 static Lisp_Object
477 font_prop_validate_otf (prop, val)
478 Lisp_Object prop, val;
479 {
480 Lisp_Object tail, tmp;
481 int i;
482
483 /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]])
484 GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil
485 GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */
486 if (! CONSP (val))
487 return Qerror;
488 if (! SYMBOLP (XCAR (val)))
489 return Qerror;
490 tail = XCDR (val);
491 if (NILP (tail))
492 return val;
493 if (! CONSP (tail) || ! SYMBOLP (XCAR (val)))
494 return Qerror;
495 for (i = 0; i < 2; i++)
496 {
497 tail = XCDR (tail);
498 if (NILP (tail))
499 return val;
500 if (! CONSP (tail))
501 return Qerror;
502 for (tmp = XCAR (tail); CONSP (tmp); tmp = XCDR (tmp))
503 if (! SYMBOLP (XCAR (tmp)))
504 return Qerror;
505 if (! NILP (tmp))
506 return Qerror;
507 }
508 return val;
509 }
510
511 /* Structure of known font property keys and validater of the
512 values. */
513 struct
514 {
515 /* Pointer to the key symbol. */
516 Lisp_Object *key;
517 /* Function to validate PROP's value VAL, or NULL if any value is
518 ok. The value is VAL or its regularized value if VAL is valid,
519 and Qerror if not. */
520 Lisp_Object (*validater) P_ ((Lisp_Object prop, Lisp_Object val));
521 } font_property_table[] =
522 { { &QCtype, font_prop_validate_symbol },
523 { &QCfoundry, font_prop_validate_symbol },
524 { &QCfamily, font_prop_validate_symbol },
525 { &QCadstyle, font_prop_validate_symbol },
526 { &QCregistry, font_prop_validate_symbol },
527 { &QCweight, font_prop_validate_style },
528 { &QCslant, font_prop_validate_style },
529 { &QCwidth, font_prop_validate_style },
530 { &QCsize, font_prop_validate_non_neg },
531 { &QCdpi, font_prop_validate_non_neg },
532 { &QCspacing, font_prop_validate_spacing },
533 { &QCavgwidth, font_prop_validate_non_neg },
534 /* The order of the above entries must match with enum
535 font_property_index. */
536 { &QClang, font_prop_validate_symbol },
537 { &QCscript, font_prop_validate_symbol },
538 { &QCotf, font_prop_validate_otf }
539 };
540
541 /* Size (number of elements) of the above table. */
542 #define FONT_PROPERTY_TABLE_SIZE \
543 ((sizeof font_property_table) / (sizeof *font_property_table))
544
545 /* Return an index number of font property KEY or -1 if KEY is not an
546 already known property. */
547
548 static int
549 get_font_prop_index (key)
550 Lisp_Object key;
551 {
552 int i;
553
554 for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++)
555 if (EQ (key, *font_property_table[i].key))
556 return i;
557 return -1;
558 }
559
560 /* Validate the font property. The property key is specified by the
561 symbol PROP, or the index IDX (if PROP is nil). If VAL is invalid,
562 signal an error. The value is VAL or the regularized one. */
563
564 static Lisp_Object
565 font_prop_validate (idx, prop, val)
566 int idx;
567 Lisp_Object prop, val;
568 {
569 Lisp_Object validated;
570
571 if (NILP (prop))
572 prop = *font_property_table[idx].key;
573 else
574 {
575 idx = get_font_prop_index (prop);
576 if (idx < 0)
577 return val;
578 }
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;
583 }
584
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. */
588
589 Lisp_Object
590 font_put_extra (font, prop, val)
591 Lisp_Object font, prop, val;
592 {
593 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
594 Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
595
596 if (NILP (slot))
597 {
598 Lisp_Object prev = Qnil;
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));
607 return val;
608 }
609 XSETCDR (slot, val);
610 return val;
611 }
612
613 \f
614 /* Font name parser and unparser */
615
616 static int parse_matrix P_ ((char *));
617 static int font_expand_wildcards P_ ((Lisp_Object *, int));
618 static int font_parse_name P_ ((char *, Lisp_Object));
619
620 /* An enumerator for each field of an XLFD font name. */
621 enum xlfd_field_index
622 {
623 XLFD_FOUNDRY_INDEX,
624 XLFD_FAMILY_INDEX,
625 XLFD_WEIGHT_INDEX,
626 XLFD_SLANT_INDEX,
627 XLFD_SWIDTH_INDEX,
628 XLFD_ADSTYLE_INDEX,
629 XLFD_PIXEL_INDEX,
630 XLFD_POINT_INDEX,
631 XLFD_RESX_INDEX,
632 XLFD_RESY_INDEX,
633 XLFD_SPACING_INDEX,
634 XLFD_AVGWIDTH_INDEX,
635 XLFD_REGISTRY_INDEX,
636 XLFD_ENCODING_INDEX,
637 XLFD_LAST_INDEX
638 };
639
640 /* An enumerator for mask bit corresponding to each XLFD field. */
641 enum xlfd_field_mask
642 {
643 XLFD_FOUNDRY_MASK = 0x0001,
644 XLFD_FAMILY_MASK = 0x0002,
645 XLFD_WEIGHT_MASK = 0x0004,
646 XLFD_SLANT_MASK = 0x0008,
647 XLFD_SWIDTH_MASK = 0x0010,
648 XLFD_ADSTYLE_MASK = 0x0020,
649 XLFD_PIXEL_MASK = 0x0040,
650 XLFD_POINT_MASK = 0x0080,
651 XLFD_RESX_MASK = 0x0100,
652 XLFD_RESY_MASK = 0x0200,
653 XLFD_SPACING_MASK = 0x0400,
654 XLFD_AVGWIDTH_MASK = 0x0800,
655 XLFD_REGISTRY_MASK = 0x1000,
656 XLFD_ENCODING_MASK = 0x2000
657 };
658
659
660 /* Parse P pointing the pixel/point size field of the form
661 `[A B C D]' which specifies a transformation matrix:
662
663 A B 0
664 C D 0
665 0 0 1
666
667 by which all glyphs of the font are transformed. The spec says
668 that scalar value N for the pixel/point size is equivalent to:
669 A = N * resx/resy, B = C = 0, D = N.
670
671 Return the scalar value N if the form is valid. Otherwise return
672 -1. */
673
674 static int
675 parse_matrix (p)
676 char *p;
677 {
678 double matrix[4];
679 char *end;
680 int i;
681
682 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
683 {
684 if (*p == '~')
685 matrix[i] = - strtod (p + 1, &end);
686 else
687 matrix[i] = strtod (p, &end);
688 p = end;
689 }
690 return (i == 4 ? (int) matrix[3] : -1);
691 }
692
693 /* Expand a wildcard field in FIELD (the first N fields are filled) to
694 multiple fields to fill in all 14 XLFD fields while restring a
695 field position by its contents. */
696
697 static int
698 font_expand_wildcards (field, n)
699 Lisp_Object field[XLFD_LAST_INDEX];
700 int n;
701 {
702 /* Copy of FIELD. */
703 Lisp_Object tmp[XLFD_LAST_INDEX];
704 /* Array of information about where this element can go. Nth
705 element is for Nth element of FIELD. */
706 struct {
707 /* Minimum possible field. */
708 int from;
709 /* Maxinum possible field. */
710 int to;
711 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
712 int mask;
713 } range[XLFD_LAST_INDEX];
714 int i, j;
715 int range_from, range_to;
716 unsigned range_mask;
717
718 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
719 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
720 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
721 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
722 | XLFD_AVGWIDTH_MASK)
723 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
724
725 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
726 field. The value is shifted to left one bit by one in the
727 following loop. */
728 for (i = 0, range_mask = 0; i <= 14 - n; i++)
729 range_mask = (range_mask << 1) | 1;
730
731 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
732 position-based retriction for FIELD[I]. */
733 for (i = 0, range_from = 0, range_to = 14 - n; i < n;
734 i++, range_from++, range_to++, range_mask <<= 1)
735 {
736 Lisp_Object val = field[i];
737
738 tmp[i] = val;
739 if (NILP (val))
740 {
741 /* Wildcard. */
742 range[i].from = range_from;
743 range[i].to = range_to;
744 range[i].mask = range_mask;
745 }
746 else
747 {
748 /* The triplet FROM, TO, and MASK is a value-based
749 retriction for FIELD[I]. */
750 int from, to;
751 unsigned mask;
752
753 if (INTEGERP (val))
754 {
755 int numeric = XINT (val);
756
757 if (i + 1 == n)
758 from = to = XLFD_ENCODING_INDEX,
759 mask = XLFD_ENCODING_MASK;
760 else if (numeric == 0)
761 from = XLFD_PIXEL_INDEX, to = XLFD_AVGWIDTH_INDEX,
762 mask = XLFD_PIXEL_MASK | XLFD_LARGENUM_MASK;
763 else if (numeric <= 48)
764 from = to = XLFD_PIXEL_INDEX,
765 mask = XLFD_PIXEL_MASK;
766 else
767 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_INDEX,
768 mask = XLFD_LARGENUM_MASK;
769 }
770 else if (SBYTES (SYMBOL_NAME (val)) == 0)
771 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
772 mask = XLFD_NULL_MASK;
773 else if (i == 0)
774 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
775 else if (i + 1 == n)
776 {
777 Lisp_Object name = SYMBOL_NAME (val);
778
779 if (SDATA (name)[SBYTES (name) - 1] == '*')
780 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
781 mask = XLFD_REGENC_MASK;
782 else
783 from = to = XLFD_ENCODING_INDEX,
784 mask = XLFD_ENCODING_MASK;
785 }
786 else if (range_from <= XLFD_WEIGHT_INDEX
787 && range_to >= XLFD_WEIGHT_INDEX
788 && FONT_WEIGHT_NAME_NUMERIC (val) >= 0)
789 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
790 else if (range_from <= XLFD_SLANT_INDEX
791 && range_to >= XLFD_SLANT_INDEX
792 && FONT_SLANT_NAME_NUMERIC (val) >= 0)
793 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
794 else if (range_from <= XLFD_SWIDTH_INDEX
795 && range_to >= XLFD_SWIDTH_INDEX
796 && FONT_WIDTH_NAME_NUMERIC (val) >= 0)
797 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
798 else
799 {
800 if (EQ (val, Qc) || EQ (val, Qm) || EQ (val, Qp) || EQ (val, Qd))
801 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
802 else
803 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
804 mask = XLFD_SYMBOL_MASK;
805 }
806
807 /* Merge position-based and value-based restrictions. */
808 mask &= range_mask;
809 while (from < range_from)
810 mask &= ~(1 << from++);
811 while (from < 14 && ! (mask & (1 << from)))
812 from++;
813 while (to > range_to)
814 mask &= ~(1 << to--);
815 while (to >= 0 && ! (mask & (1 << to)))
816 to--;
817 if (from > to)
818 return -1;
819 range[i].from = from;
820 range[i].to = to;
821 range[i].mask = mask;
822
823 if (from > range_from || to < range_to)
824 {
825 /* The range is narrowed by value-based restrictions.
826 Reflect it to the other fields. */
827
828 /* Following fields should be after FROM. */
829 range_from = from;
830 /* Preceding fields should be before TO. */
831 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
832 {
833 /* Check FROM for non-wildcard field. */
834 if (! NILP (tmp[j]) && range[j].from < from)
835 {
836 while (range[j].from < from)
837 range[j].mask &= ~(1 << range[j].from++);
838 while (from < 14 && ! (range[j].mask & (1 << from)))
839 from++;
840 range[j].from = from;
841 }
842 else
843 from = range[j].from;
844 if (range[j].to > to)
845 {
846 while (range[j].to > to)
847 range[j].mask &= ~(1 << range[j].to--);
848 while (to >= 0 && ! (range[j].mask & (1 << to)))
849 to--;
850 range[j].to = to;
851 }
852 else
853 to = range[j].to;
854 if (from > to)
855 return -1;
856 }
857 }
858 }
859 }
860
861 /* Decide all fileds from restrictions in RANGE. */
862 for (i = j = 0; i < n ; i++)
863 {
864 if (j < range[i].from)
865 {
866 if (i == 0 || ! NILP (tmp[i - 1]))
867 /* None of TMP[X] corresponds to Jth field. */
868 return -1;
869 for (; j < range[i].from; j++)
870 field[j] = Qnil;
871 }
872 field[j++] = tmp[i];
873 }
874 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
875 return -1;
876 for (; j < XLFD_LAST_INDEX; j++)
877 field[j] = Qnil;
878 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
879 field[XLFD_ENCODING_INDEX]
880 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
881 return 0;
882 }
883
884
885 #ifdef ENABLE_CHECKING
886 /* Match a 14-field XLFD pattern against a full XLFD font name. */
887 static int
888 font_match_xlfd (char *pattern, char *name)
889 {
890 while (*pattern && *name)
891 {
892 if (*pattern == *name)
893 pattern++;
894 else if (*pattern == '*')
895 if (*name == pattern[1])
896 pattern += 2;
897 else
898 ;
899 else
900 return 0;
901 name++;
902 }
903 return 1;
904 }
905
906 /* Make sure the font object matches the XLFD font name. */
907 static int
908 font_check_xlfd_parse (Lisp_Object font, char *name)
909 {
910 char name_check[256];
911 font_unparse_xlfd (font, 0, name_check, 255);
912 return font_match_xlfd (name_check, name);
913 }
914
915 #endif
916
917
918 /* Parse NAME (null terminated) as XLFD and store information in FONT
919 (font-spec or font-entity). Size property of FONT is set as
920 follows:
921 specified XLFD fields FONT property
922 --------------------- -------------
923 PIXEL_SIZE PIXEL_SIZE (Lisp integer)
924 POINT_SIZE and RESY calculated pixel size (Lisp integer)
925 POINT_SIZE POINT_SIZE/10 (Lisp float)
926
927 If NAME is successfully parsed, return 0. Otherwise return -1.
928
929 FONT is usually a font-spec, but when this function is called from
930 X font backend driver, it is a font-entity. In that case, NAME is
931 a fully specified XLFD. */
932
933 int
934 font_parse_xlfd (name, font)
935 char *name;
936 Lisp_Object font;
937 {
938 int len = strlen (name);
939 int i, j, n;
940 char *f[XLFD_LAST_INDEX + 1];
941 Lisp_Object val;
942 char *p;
943
944 if (len > 255)
945 /* Maximum XLFD name length is 255. */
946 return -1;
947 /* Accept "*-.." as a fully specified XLFD. */
948 if (name[0] == '*' && name[1] == '-')
949 i = 1, f[XLFD_FOUNDRY_INDEX] = name;
950 else
951 i = 0;
952 for (p = name + i; *p; p++)
953 if (*p == '-')
954 {
955 f[i++] = p + 1;
956 if (i == XLFD_LAST_INDEX)
957 break;
958 }
959 f[i] = name + len;
960
961 #define INTERN_FIELD(N) font_intern_prop (f[N], f[(N) + 1] - 1 - f[N])
962
963 if (i == XLFD_LAST_INDEX)
964 {
965 /* Fully specified XLFD. */
966 int pixel_size;
967 int spacing_char;
968
969 ASET (font, FONT_FOUNDRY_INDEX, INTERN_FIELD (XLFD_FOUNDRY_INDEX));
970 ASET (font, FONT_FAMILY_INDEX, INTERN_FIELD (XLFD_FAMILY_INDEX));
971 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
972 i <= XLFD_SWIDTH_INDEX; i++, j++)
973 {
974 val = INTERN_FIELD (i);
975 if (! NILP (val))
976 {
977 if ((n = font_style_to_value (j, INTERN_FIELD (i), 0)) < 0)
978 return -1;
979 ASET (font, j, make_number (n));
980 }
981 }
982 ASET (font, FONT_ADSTYLE_INDEX, INTERN_FIELD (XLFD_ADSTYLE_INDEX));
983 if (strcmp (f[XLFD_REGISTRY_INDEX], "*-*") == 0)
984 ASET (font, FONT_REGISTRY_INDEX, Qnil);
985 else
986 ASET (font, FONT_REGISTRY_INDEX,
987 font_intern_prop (f[XLFD_REGISTRY_INDEX],
988 f[XLFD_LAST_INDEX] - f[XLFD_REGISTRY_INDEX]));
989 p = f[XLFD_PIXEL_INDEX];
990 if (*p == '[' && (pixel_size = parse_matrix (p)) >= 0)
991 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
992 else
993 {
994 val = INTERN_FIELD (XLFD_PIXEL_INDEX);
995 if (INTEGERP (val))
996 ASET (font, FONT_SIZE_INDEX, val);
997 else
998 {
999 double point_size = -1;
1000
1001 xassert (FONT_SPEC_P (font));
1002 p = f[XLFD_POINT_INDEX];
1003 if (*p == '[')
1004 point_size = parse_matrix (p);
1005 else if (isdigit (*p))
1006 point_size = atoi (p), point_size /= 10;
1007 if (point_size >= 0)
1008 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1009 }
1010 }
1011
1012 ASET (font, FONT_DPI_INDEX, INTERN_FIELD (XLFD_RESY_INDEX));
1013 val = INTERN_FIELD (XLFD_SPACING_INDEX);
1014 if (! NILP (val))
1015 {
1016 val = font_prop_validate_spacing (QCspacing, val);
1017 if (! INTEGERP (val))
1018 return -1;
1019 ASET (font, FONT_SPACING_INDEX, val);
1020 }
1021 p = f[XLFD_AVGWIDTH_INDEX];
1022 if (*p == '~')
1023 p++;
1024 ASET (font, FONT_AVGWIDTH_INDEX,
1025 font_intern_prop (p, f[XLFD_REGISTRY_INDEX] - 1 - p));
1026 }
1027 else
1028 {
1029 int wild_card_found = 0;
1030 Lisp_Object prop[XLFD_LAST_INDEX];
1031
1032 if (FONT_ENTITY_P (font))
1033 return -1;
1034 for (j = 0; j < i; j++)
1035 {
1036 if (*f[j] == '*')
1037 {
1038 if (f[j][1] && f[j][1] != '-')
1039 return -1;
1040 prop[j] = Qnil;
1041 wild_card_found = 1;
1042 }
1043 else if (j + 1 < i)
1044 prop[j] = INTERN_FIELD (j);
1045 else
1046 prop[j] = font_intern_prop (f[j], f[i] - f[j]);
1047 }
1048 if (! wild_card_found)
1049 return -1;
1050 if (font_expand_wildcards (prop, i) < 0)
1051 return -1;
1052
1053 ASET (font, FONT_FOUNDRY_INDEX, prop[XLFD_FOUNDRY_INDEX]);
1054 ASET (font, FONT_FAMILY_INDEX, prop[XLFD_FAMILY_INDEX]);
1055 for (i = XLFD_WEIGHT_INDEX, j = FONT_WEIGHT_INDEX;
1056 i <= XLFD_SWIDTH_INDEX; i++, j++)
1057 if (! NILP (prop[i]))
1058 {
1059 if ((n = font_style_to_value (j, prop[i], 1)) < 0)
1060 return -1;
1061 ASET (font, j, make_number (n));
1062 }
1063 ASET (font, FONT_ADSTYLE_INDEX, prop[XLFD_ADSTYLE_INDEX]);
1064 val = prop[XLFD_REGISTRY_INDEX];
1065 if (NILP (val))
1066 {
1067 val = prop[XLFD_ENCODING_INDEX];
1068 if (! NILP (val))
1069 val = concat2 (build_string ("*-"), SYMBOL_NAME (val));
1070 }
1071 else if (NILP (prop[XLFD_ENCODING_INDEX]))
1072 val = concat2 (SYMBOL_NAME (val), build_string ("-*"));
1073 else
1074 val = concat3 (SYMBOL_NAME (val), build_string ("-"),
1075 SYMBOL_NAME (prop[XLFD_ENCODING_INDEX]));
1076 if (! NILP (val))
1077 ASET (font, FONT_REGISTRY_INDEX, Fintern (val, Qnil));
1078
1079 if (INTEGERP (prop[XLFD_PIXEL_INDEX]))
1080 ASET (font, FONT_SIZE_INDEX, prop[XLFD_PIXEL_INDEX]);
1081 else if (INTEGERP (prop[XLFD_POINT_INDEX]))
1082 {
1083 double point_size = XINT (prop[XLFD_POINT_INDEX]);
1084
1085 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
1086 }
1087
1088 if (INTEGERP (prop[XLFD_RESX_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 }
1098 if (INTEGERP (prop[XLFD_AVGWIDTH_INDEX]))
1099 ASET (font, FONT_AVGWIDTH_INDEX, prop[XLFD_AVGWIDTH_INDEX]);
1100 }
1101
1102 return 0;
1103 }
1104
1105 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
1106 length), and return the name length. If FONT_SIZE_INDEX of FONT is
1107 0, use PIXEL_SIZE instead. */
1108
1109 int
1110 font_unparse_xlfd (font, pixel_size, name, nbytes)
1111 Lisp_Object font;
1112 int pixel_size;
1113 char *name;
1114 int nbytes;
1115 {
1116 char *f[XLFD_REGISTRY_INDEX + 1];
1117 Lisp_Object val;
1118 int i, j, len = 0;
1119
1120 xassert (FONTP (font));
1121
1122 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
1123 i++, j++)
1124 {
1125 if (i == FONT_ADSTYLE_INDEX)
1126 j = XLFD_ADSTYLE_INDEX;
1127 else if (i == FONT_REGISTRY_INDEX)
1128 j = XLFD_REGISTRY_INDEX;
1129 val = AREF (font, i);
1130 if (NILP (val))
1131 {
1132 if (j == XLFD_REGISTRY_INDEX)
1133 f[j] = "*-*", len += 4;
1134 else
1135 f[j] = "*", len += 2;
1136 }
1137 else
1138 {
1139 if (SYMBOLP (val))
1140 val = SYMBOL_NAME (val);
1141 if (j == XLFD_REGISTRY_INDEX
1142 && ! strchr ((char *) SDATA (val), '-'))
1143 {
1144 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
1145 if (SDATA (val)[SBYTES (val) - 1] == '*')
1146 {
1147 f[j] = alloca (SBYTES (val) + 3);
1148 sprintf (f[j], "%s-*", SDATA (val));
1149 len += SBYTES (val) + 3;
1150 }
1151 else
1152 {
1153 f[j] = alloca (SBYTES (val) + 4);
1154 sprintf (f[j], "%s*-*", SDATA (val));
1155 len += SBYTES (val) + 4;
1156 }
1157 }
1158 else
1159 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1160 }
1161 }
1162
1163 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
1164 i++, j++)
1165 {
1166 val = font_style_symbolic (font, i, 0);
1167 if (NILP (val))
1168 f[j] = "*", len += 2;
1169 else
1170 {
1171 val = SYMBOL_NAME (val);
1172 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
1173 }
1174 }
1175
1176 val = AREF (font, FONT_SIZE_INDEX);
1177 xassert (NUMBERP (val) || NILP (val));
1178 if (INTEGERP (val))
1179 {
1180 i = XINT (val);
1181 if (i <= 0)
1182 i = pixel_size;
1183 if (i > 0)
1184 {
1185 f[XLFD_PIXEL_INDEX] = alloca (22);
1186 len += sprintf (f[XLFD_PIXEL_INDEX], "%d-*", i) + 1;
1187 }
1188 else
1189 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1190 }
1191 else if (FLOATP (val))
1192 {
1193 i = XFLOAT_DATA (val) * 10;
1194 f[XLFD_PIXEL_INDEX] = alloca (12);
1195 len += sprintf (f[XLFD_PIXEL_INDEX], "*-%d", i) + 1;
1196 }
1197 else
1198 f[XLFD_PIXEL_INDEX] = "*-*", len += 4;
1199
1200 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1201 {
1202 i = XINT (AREF (font, FONT_DPI_INDEX));
1203 f[XLFD_RESX_INDEX] = alloca (22);
1204 len += sprintf (f[XLFD_RESX_INDEX],
1205 "%d-%d", i, i) + 1;
1206 }
1207 else
1208 f[XLFD_RESX_INDEX] = "*-*", len += 4;
1209 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1210 {
1211 int spacing = XINT (AREF (font, FONT_SPACING_INDEX));
1212
1213 f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
1214 : spacing <= FONT_SPACING_DUAL ? "d"
1215 : spacing <= FONT_SPACING_MONO ? "m"
1216 : "c");
1217 len += 2;
1218 }
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;
1229 len++; /* for terminating '\0'. */
1230 if (len >= nbytes)
1231 return -1;
1232 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1233 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
1234 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
1235 f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
1236 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
1237 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
1238 f[XLFD_REGISTRY_INDEX]);
1239 }
1240
1241 /* Parse NAME (null terminated) as Fonconfig's name format and store
1242 information in FONT (font-spec or font-entity). If NAME is
1243 successfully parsed, return 0. Otherwise return -1. */
1244
1245 int
1246 font_parse_fcname (name, font)
1247 char *name;
1248 Lisp_Object font;
1249 {
1250 char *p0, *p1;
1251 int len = strlen (name);
1252 char *copy;
1253
1254 if (len == 0)
1255 return -1;
1256 /* It is assured that (name[0] && name[0] != '-'). */
1257 if (name[0] == ':')
1258 p0 = name;
1259 else
1260 {
1261 Lisp_Object family;
1262 double point_size;
1263
1264 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++)
1265 if (*p0 == '\\' && p0[1])
1266 p0++;
1267 family = font_intern_prop (name, p0 - name);
1268 if (*p0 == '-')
1269 {
1270 if (! isdigit (p0[1]))
1271 return -1;
1272 point_size = strtod (p0 + 1, &p1);
1273 if (*p1 && *p1 != ':')
1274 return -1;
1275 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1276 p0 = p1;
1277 }
1278 ASET (font, FONT_FAMILY_INDEX, family);
1279 }
1280
1281 len -= p0 - name;
1282 copy = alloca (len + 1);
1283 if (! copy)
1284 return -1;
1285 name = copy;
1286
1287 /* Now parse ":KEY=VAL" patterns. Store known keys and values in
1288 extra, copy unknown ones to COPY. It is stored in extra slot by
1289 the key QCfc_unknown_spec. */
1290 while (*p0)
1291 {
1292 Lisp_Object key, val;
1293 int prop;
1294
1295 for (p1 = p0 + 1; *p1 && *p1 != '=' && *p1 != ':'; p1++);
1296 if (*p1 != '=')
1297 {
1298 /* Must be an enumerated value. */
1299 val = font_intern_prop (p0 + 1, p1 - p0 - 1);
1300 if (memcmp (p0 + 1, "light", 5) == 0
1301 || memcmp (p0 + 1, "medium", 6) == 0
1302 || memcmp (p0 + 1, "demibold", 8) == 0
1303 || memcmp (p0 + 1, "bold", 4) == 0
1304 || memcmp (p0 + 1, "black", 5) == 0)
1305 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
1306 else if (memcmp (p0 + 1, "roman", 5) == 0
1307 || memcmp (p0 + 1, "italic", 6) == 0
1308 || memcmp (p0 + 1, "oblique", 7) == 0)
1309 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
1310 else if (memcmp (p0 + 1, "charcell", 8) == 0
1311 || memcmp (p0 + 1, "mono", 4) == 0
1312 || memcmp (p0 + 1, "proportional", 12) == 0)
1313 {
1314 int spacing = (p0[1] == 'c' ? FONT_SPACING_CHARCELL
1315 : p0[1] == 'm' ? FONT_SPACING_MONO
1316 : FONT_SPACING_PROPORTIONAL);
1317 ASET (font, FONT_SPACING_INDEX, make_number (spacing));
1318 }
1319 else
1320 {
1321 /* unknown key */
1322 bcopy (p0, copy, p1 - p0);
1323 copy += p1 - p0;
1324 }
1325 }
1326 else
1327 {
1328 if (memcmp (p0 + 1, "pixelsize=", 10) == 0)
1329 prop = FONT_SIZE_INDEX;
1330 else
1331 {
1332 key = font_intern_prop (p0, p1 - p0);
1333 prop = get_font_prop_index (key);
1334 }
1335 p0 = p1 + 1;
1336 for (p1 = p0; *p1 && *p1 != ':'; p1++);
1337 val = font_intern_prop (p0, p1 - p0);
1338 if (! NILP (val))
1339 {
1340 if (prop >= FONT_FOUNDRY_INDEX && prop < FONT_EXTRA_INDEX)
1341 ASET (font, prop, font_prop_validate (prop, Qnil, val));
1342 else if (prop >= 0)
1343 Ffont_put (font, key, val);
1344 else
1345 bcopy (p0 - 1, copy, p1 - p0 + 1);
1346 copy += p1 - p0 + 1;
1347 }
1348 }
1349 p0 = p1;
1350 }
1351 if (name != copy)
1352 font_put_extra (font, QCfc_unknown_spec,
1353 make_unibyte_string (name, copy - name));
1354
1355 return 0;
1356 }
1357
1358 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1359 NAME (NBYTES length), and return the name length. If
1360 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1361
1362 int
1363 font_unparse_fcname (font, pixel_size, name, nbytes)
1364 Lisp_Object font;
1365 int pixel_size;
1366 char *name;
1367 int nbytes;
1368 {
1369 Lisp_Object tail, val;
1370 int point_size;
1371 int dpi, spacing, avgwidth;
1372 int i, len = 1;
1373 char *p;
1374 Lisp_Object styles[3];
1375 char *style_names[3] = { "weight", "slant", "width" };
1376 char work[256];
1377
1378 val = AREF (font, FONT_FAMILY_INDEX);
1379 if (STRINGP (val))
1380 len += SBYTES (val);
1381
1382 val = AREF (font, FONT_SIZE_INDEX);
1383 if (INTEGERP (val))
1384 {
1385 if (XINT (val) != 0)
1386 pixel_size = XINT (val);
1387 point_size = -1;
1388 len += 21; /* for ":pixelsize=NUM" */
1389 }
1390 else if (FLOATP (val))
1391 {
1392 pixel_size = -1;
1393 point_size = (int) XFLOAT_DATA (val);
1394 len += 11; /* for "-NUM" */
1395 }
1396
1397 val = AREF (font, FONT_FOUNDRY_INDEX);
1398 if (STRINGP (val))
1399 /* ":foundry=NAME" */
1400 len += 9 + SBYTES (val);
1401
1402 for (i = 0; i < 3; i++)
1403 {
1404 int this_len;
1405
1406 styles[i] = font_style_symbolic (font, FONT_WEIGHT_INDEX + i, 0);
1407 if (! NILP (styles[i]))
1408 len += sprintf (work, ":%s=%s", style_names[i],
1409 SDATA (SYMBOL_NAME (styles[i])));
1410 }
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))
1419 {
1420 Lisp_Object key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
1421
1422 len += SBYTES (SYMBOL_NAME (key)) + 1; /* for :KEY= */
1423 if (STRINGP (val))
1424 len += SBYTES (val);
1425 else if (INTEGERP (val))
1426 len += sprintf (work, "%d", XINT (val));
1427 else if (SYMBOLP (val))
1428 len += (NILP (val) ? 5 : 4); /* for "false" or "true" */
1429 }
1430
1431 if (len > nbytes)
1432 return -1;
1433 p = name;
1434 if (! NILP (AREF (font, FONT_FAMILY_INDEX)))
1435 p += sprintf(p, "%s", SDATA (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX))));
1436 if (point_size > 0)
1437 {
1438 if (p == name)
1439 p += sprintf (p, "%d", point_size);
1440 else
1441 p += sprintf (p, "-%d", point_size);
1442 }
1443 else if (pixel_size > 0)
1444 p += sprintf (p, ":pixelsize=%d", pixel_size);
1445 if (! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1446 p += sprintf (p, ":foundry=%s",
1447 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1448 for (i = 0; i < 3; i++)
1449 if (! NILP (styles[i]))
1450 p += sprintf (p, ":%s=%s", style_names[i],
1451 SDATA (SYMBOL_NAME (styles[i])));
1452 if (INTEGERP (AREF (font, FONT_DPI_INDEX)))
1453 p += sprintf (p, ":dpi=%d", XINT (AREF (font, FONT_DPI_INDEX)));
1454 if (INTEGERP (AREF (font, FONT_SPACING_INDEX)))
1455 p += sprintf (p, ":spacing=%d", XINT (AREF (font, FONT_SPACING_INDEX)));
1456 if (INTEGERP (AREF (font, FONT_AVGWIDTH_INDEX)))
1457 {
1458 if (XINT (AREF (font, FONT_AVGWIDTH_INDEX)) == 0)
1459 p += sprintf (p, ":scalable=true");
1460 else
1461 p += sprintf (p, ":scalable=false");
1462 }
1463 return (p - name);
1464 }
1465
1466 /* Parse NAME (null terminated) and store information in FONT
1467 (font-spec or font-entity). If NAME is successfully parsed, return
1468 0. Otherwise return -1. */
1469
1470 static int
1471 font_parse_name (name, font)
1472 char *name;
1473 Lisp_Object font;
1474 {
1475 if (name[0] == '-' || index (name, '*'))
1476 return font_parse_xlfd (name, font);
1477 return font_parse_fcname (name, font);
1478 }
1479
1480
1481 /* Merge FAMILY and REGISTRY into FONT_SPEC. FAMILY may have the form
1482 "FAMILY-FOUNDRY". REGISTRY may not contain charset-encoding
1483 part. */
1484
1485 void
1486 font_parse_family_registry (family, registry, font_spec)
1487 Lisp_Object family, registry, font_spec;
1488 {
1489 int len;
1490 char *p0, *p1;
1491
1492 if (! NILP (family))
1493 {
1494 CHECK_STRING (family);
1495 len = SBYTES (family);
1496 p0 = (char *) SDATA (family);
1497 p1 = index (p0, '-');
1498 if (p1)
1499 {
1500 if (*p0 != '*' || p1 - p0 > 1)
1501 ASET (font_spec, FONT_FOUNDRY_INDEX,
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));
1506 }
1507 else
1508 ASET (font_spec, FONT_FAMILY_INDEX, Fintern (family, Qnil));
1509 }
1510 if (! NILP (registry))
1511 {
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)
1518 {
1519 if (SDATA (registry)[len - 1] == '*')
1520 registry = concat2 (registry, build_string ("-*"));
1521 else
1522 registry = concat2 (registry, build_string ("*-*"));
1523 }
1524 registry = Fdowncase (registry);
1525 ASET (font_spec, FONT_REGISTRY_INDEX, Fintern (registry, Qnil));
1526 }
1527 }
1528
1529 \f
1530 /* This part (through the next ^L) is still experimental and not
1531 tested much. We may drastically change codes. */
1532
1533 /* OTF handler */
1534
1535 #define LGSTRING_HEADER_SIZE 6
1536 #define LGSTRING_GLYPH_SIZE 8
1537
1538 static int
1539 check_gstring (gstring)
1540 Lisp_Object gstring;
1541 {
1542 Lisp_Object val;
1543 int i, j;
1544
1545 CHECK_VECTOR (gstring);
1546 val = AREF (gstring, 0);
1547 CHECK_VECTOR (val);
1548 if (ASIZE (val) < LGSTRING_HEADER_SIZE)
1549 goto err;
1550 CHECK_FONT_OBJECT (LGSTRING_FONT (gstring));
1551 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING)))
1552 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_LBEARING));
1553 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING)))
1554 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_RBEARING));
1555 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH)))
1556 CHECK_NATNUM (LGSTRING_SLOT (gstring, LGSTRING_IX_WIDTH));
1557 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1558 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1559 if (!NILP (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT)))
1560 CHECK_NUMBER (LGSTRING_SLOT (gstring, LGSTRING_IX_ASCENT));
1561
1562 for (i = 0; i < LGSTRING_LENGTH (gstring); i++)
1563 {
1564 val = LGSTRING_GLYPH (gstring, i);
1565 CHECK_VECTOR (val);
1566 if (ASIZE (val) < LGSTRING_GLYPH_SIZE)
1567 goto err;
1568 if (NILP (AREF (val, LGLYPH_IX_CHAR)))
1569 break;
1570 CHECK_NATNUM (AREF (val, LGLYPH_IX_FROM));
1571 CHECK_NATNUM (AREF (val, LGLYPH_IX_TO));
1572 CHECK_CHARACTER (AREF (val, LGLYPH_IX_CHAR));
1573 if (!NILP (AREF (val, LGLYPH_IX_CODE)))
1574 CHECK_NATNUM (AREF (val, LGLYPH_IX_CODE));
1575 if (!NILP (AREF (val, LGLYPH_IX_WIDTH)))
1576 CHECK_NATNUM (AREF (val, LGLYPH_IX_WIDTH));
1577 if (!NILP (AREF (val, LGLYPH_IX_ADJUSTMENT)))
1578 {
1579 val = AREF (val, LGLYPH_IX_ADJUSTMENT);
1580 CHECK_VECTOR (val);
1581 if (ASIZE (val) < 3)
1582 goto err;
1583 for (j = 0; j < 3; j++)
1584 CHECK_NUMBER (AREF (val, j));
1585 }
1586 }
1587 return i;
1588 err:
1589 error ("Invalid glyph-string format");
1590 return -1;
1591 }
1592
1593 static void
1594 check_otf_features (otf_features)
1595 Lisp_Object otf_features;
1596 {
1597 Lisp_Object val;
1598
1599 CHECK_CONS (otf_features);
1600 CHECK_SYMBOL (XCAR (otf_features));
1601 otf_features = XCDR (otf_features);
1602 CHECK_CONS (otf_features);
1603 CHECK_SYMBOL (XCAR (otf_features));
1604 otf_features = XCDR (otf_features);
1605 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1606 {
1607 CHECK_SYMBOL (Fcar (val));
1608 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1609 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val)));
1610 }
1611 otf_features = XCDR (otf_features);
1612 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1613 {
1614 CHECK_SYMBOL (Fcar (val));
1615 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1616 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val)));
1617 }
1618 }
1619
1620 #ifdef HAVE_LIBOTF
1621 #include <otf.h>
1622
1623 Lisp_Object otf_list;
1624
1625 static Lisp_Object
1626 otf_tag_symbol (tag)
1627 OTF_Tag tag;
1628 {
1629 char name[5];
1630
1631 OTF_tag_name (tag, name);
1632 return Fintern (make_unibyte_string (name, 4), Qnil);
1633 }
1634
1635 static OTF *
1636 otf_open (file)
1637 Lisp_Object file;
1638 {
1639 Lisp_Object val = Fassoc (file, otf_list);
1640 OTF *otf;
1641
1642 if (! NILP (val))
1643 otf = XSAVE_VALUE (XCDR (val))->pointer;
1644 else
1645 {
1646 otf = STRINGP (file) ? OTF_open ((char *) SDATA (file)) : NULL;
1647 val = make_save_value (otf, 0);
1648 otf_list = Fcons (Fcons (file, val), otf_list);
1649 }
1650 return otf;
1651 }
1652
1653
1654 /* Return a list describing which scripts/languages FONT supports by
1655 which GSUB/GPOS features of OpenType tables. See the comment of
1656 (struct font_driver).otf_capability. */
1657
1658 Lisp_Object
1659 font_otf_capability (font)
1660 struct font *font;
1661 {
1662 OTF *otf;
1663 Lisp_Object capability = Fcons (Qnil, Qnil);
1664 int i;
1665
1666 otf = otf_open (font->props[FONT_FILE_INDEX]);
1667 if (! otf)
1668 return Qnil;
1669 for (i = 0; i < 2; i++)
1670 {
1671 OTF_GSUB_GPOS *gsub_gpos;
1672 Lisp_Object script_list = Qnil;
1673 int j;
1674
1675 if (OTF_get_features (otf, i == 0) < 0)
1676 continue;
1677 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1678 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1679 {
1680 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1681 Lisp_Object langsys_list = Qnil;
1682 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1683 int k;
1684
1685 for (k = script->LangSysCount; k >= 0; k--)
1686 {
1687 OTF_LangSys *langsys;
1688 Lisp_Object feature_list = Qnil;
1689 Lisp_Object langsys_tag;
1690 int l;
1691
1692 if (k == script->LangSysCount)
1693 {
1694 langsys = &script->DefaultLangSys;
1695 langsys_tag = Qnil;
1696 }
1697 else
1698 {
1699 langsys = script->LangSys + k;
1700 langsys_tag
1701 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
1702 }
1703 for (l = langsys->FeatureCount - 1; l >= 0; l--)
1704 {
1705 OTF_Feature *feature
1706 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
1707 Lisp_Object feature_tag
1708 = otf_tag_symbol (feature->FeatureTag);
1709
1710 feature_list = Fcons (feature_tag, feature_list);
1711 }
1712 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1713 langsys_list);
1714 }
1715 script_list = Fcons (Fcons (script_tag, langsys_list),
1716 script_list);
1717 }
1718
1719 if (i == 0)
1720 XSETCAR (capability, script_list);
1721 else
1722 XSETCDR (capability, script_list);
1723 }
1724
1725 return capability;
1726 }
1727
1728 /* Parse OTF features in SPEC and write a proper features spec string
1729 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1730 assured that the sufficient memory has already allocated for
1731 FEATURES. */
1732
1733 static void
1734 generate_otf_features (spec, features)
1735 Lisp_Object spec;
1736 char *features;
1737 {
1738 Lisp_Object val;
1739 char *p;
1740 int asterisk;
1741
1742 p = features;
1743 *p = '\0';
1744 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
1745 {
1746 val = XCAR (spec);
1747 CHECK_SYMBOL (val);
1748 if (p > features)
1749 *p++ = ',';
1750 if (SREF (SYMBOL_NAME (val), 0) == '*')
1751 {
1752 asterisk = 1;
1753 *p++ = '*';
1754 }
1755 else if (! asterisk)
1756 {
1757 val = SYMBOL_NAME (val);
1758 p += sprintf (p, "%s", SDATA (val));
1759 }
1760 else
1761 {
1762 val = SYMBOL_NAME (val);
1763 p += sprintf (p, "~%s", SDATA (val));
1764 }
1765 }
1766 if (CONSP (spec))
1767 error ("OTF spec too long");
1768 }
1769
1770
1771 Lisp_Object
1772 font_otf_DeviceTable (device_table)
1773 OTF_DeviceTable *device_table;
1774 {
1775 int len = device_table->StartSize - device_table->EndSize + 1;
1776
1777 return Fcons (make_number (len),
1778 make_unibyte_string (device_table->DeltaValue, len));
1779 }
1780
1781 Lisp_Object
1782 font_otf_ValueRecord (value_format, value_record)
1783 int value_format;
1784 OTF_ValueRecord *value_record;
1785 {
1786 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
1787
1788 if (value_format & OTF_XPlacement)
1789 ASET (val, 0, make_number (value_record->XPlacement));
1790 if (value_format & OTF_YPlacement)
1791 ASET (val, 1, make_number (value_record->YPlacement));
1792 if (value_format & OTF_XAdvance)
1793 ASET (val, 2, make_number (value_record->XAdvance));
1794 if (value_format & OTF_YAdvance)
1795 ASET (val, 3, make_number (value_record->YAdvance));
1796 if (value_format & OTF_XPlaDevice)
1797 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
1798 if (value_format & OTF_YPlaDevice)
1799 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
1800 if (value_format & OTF_XAdvDevice)
1801 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
1802 if (value_format & OTF_YAdvDevice)
1803 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
1804 return val;
1805 }
1806
1807 Lisp_Object
1808 font_otf_Anchor (anchor)
1809 OTF_Anchor *anchor;
1810 {
1811 Lisp_Object val;
1812
1813 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
1814 ASET (val, 0, make_number (anchor->XCoordinate));
1815 ASET (val, 1, make_number (anchor->YCoordinate));
1816 if (anchor->AnchorFormat == 2)
1817 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
1818 else
1819 {
1820 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
1821 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
1822 }
1823 return val;
1824 }
1825
1826 #endif /* HAVE_LIBOTF */
1827
1828 /* G-string (glyph string) handler */
1829
1830 /* G-string is a vector of the form [HEADER GLYPH ...].
1831 See the docstring of `font-make-gstring' for more detail. */
1832
1833 struct font *
1834 font_prepare_composition (cmp, f)
1835 struct composition *cmp;
1836 FRAME_PTR f;
1837 {
1838 Lisp_Object gstring
1839 = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
1840 cmp->hash_index * 2);
1841
1842 cmp->font = XFONT_OBJECT (LGSTRING_FONT (gstring));
1843 cmp->glyph_len = LGSTRING_LENGTH (gstring);
1844 cmp->pixel_width = LGSTRING_WIDTH (gstring);
1845 cmp->lbearing = LGSTRING_LBEARING (gstring);
1846 cmp->rbearing = LGSTRING_RBEARING (gstring);
1847 cmp->ascent = LGSTRING_ASCENT (gstring);
1848 cmp->descent = LGSTRING_DESCENT (gstring);
1849 cmp->width = cmp->pixel_width / FRAME_COLUMN_WIDTH (f);
1850 if (cmp->width == 0)
1851 cmp->width = 1;
1852
1853 return cmp->font;
1854 }
1855
1856 \f
1857 /* Font sorting */
1858
1859 static unsigned font_score P_ ((Lisp_Object, Lisp_Object *, Lisp_Object));
1860 static int font_compare P_ ((const void *, const void *));
1861 static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object,
1862 Lisp_Object, Lisp_Object,
1863 int));
1864
1865 /* We sort fonts by scoring each of them against a specified
1866 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1867 the value is, the closer the font is to the font-spec.
1868
1869 The highest 2 bits of the score is used for FAMILY. The exact
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.
1875
1876 Each 7-bit in the lower 28 bits are used for numeric properties
1877 WEIGHT, SLANT, WIDTH, and SIZE. */
1878
1879 /* How many bits to shift to store the difference value of each font
1880 property in a score. Note that flots for FONT_TYPE_INDEX and
1881 FONT_REGISTRY_INDEX are not used. */
1882 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
1883
1884 /* Score font-entity ENTITY against properties of font-spec SPEC_PROP.
1885 The return value indicates how different ENTITY is compared with
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). */
1890
1891 static unsigned
1892 font_score (entity, spec_prop, alternate_families)
1893 Lisp_Object entity, *spec_prop;
1894 Lisp_Object alternate_families;
1895 {
1896 unsigned score = 0;
1897 int i;
1898
1899 /* Score three atomic fields. Maximum difference is 1 (family is 3). */
1900 for (i = FONT_FOUNDRY_INDEX; i <= FONT_ADSTYLE_INDEX; i++)
1901 if (i != FONT_REGISTRY_INDEX
1902 && ! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
1903 {
1904 Lisp_Object entity_str = SYMBOL_NAME (AREF (entity, i));
1905 Lisp_Object spec_str = SYMBOL_NAME (spec_prop[i]);
1906
1907 if (strcasecmp (SDATA (spec_str), SDATA (entity_str)))
1908 {
1909 if (i == FONT_FAMILY_INDEX && CONSP (alternate_families))
1910 {
1911 int j;
1912
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 }
1929
1930 /* Score three style numeric fields. Maximum difference is 127. */
1931 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
1932 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i]))
1933 {
1934 int diff = (XINT (AREF (entity, i)) >> 8) - (XINT (spec_prop[i]) >> 8);
1935
1936 if (diff < 0)
1937 diff = - diff;
1938 /* This is to prefer the exact symbol style. */
1939 diff++;
1940 score |= min (diff, 127) << sort_shift_bits[i];
1941 }
1942
1943 /* Score the size. Maximum difference is 127. */
1944 i = FONT_SIZE_INDEX;
1945 if (! NILP (spec_prop[i]) && ! EQ (AREF (entity, i), spec_prop[i])
1946 && XINT (AREF (entity, i)) > 0)
1947 {
1948 /* We use the higher 6-bit for the actual size difference. The
1949 lowest bit is set if the DPI is different. */
1950 int diff = XINT (spec_prop[i]) - XINT (AREF (entity, i));
1951
1952 if (diff < 0)
1953 diff = - diff;
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];
1959 }
1960
1961 return score;
1962 }
1963
1964
1965 /* The comparison function for qsort. */
1966
1967 static int
1968 font_compare (d1, d2)
1969 const void *d1, *d2;
1970 {
1971 return (*(unsigned *) d1 - *(unsigned *) d2);
1972 }
1973
1974
1975 /* The structure for elements being sorted by qsort. */
1976 struct font_sort_data
1977 {
1978 unsigned score;
1979 Lisp_Object entity;
1980 };
1981
1982
1983 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
1984 If PREFER specifies a point-size, calculate the corresponding
1985 pixel-size from QCdpi property of PREFER or from the Y-resolution
1986 of FRAME before sorting. If SPEC is not nil, it is a font-spec to
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. */
1991
1992 static Lisp_Object
1993 font_sort_entites (vec, prefer, frame, spec, best_only)
1994 Lisp_Object vec, prefer, frame, spec;
1995 int best_only;
1996 {
1997 Lisp_Object prefer_prop[FONT_SPEC_MAX];
1998 int len, i;
1999 struct font_sort_data *data;
2000 Lisp_Object alternate_families = Qnil;
2001 unsigned best_score;
2002 Lisp_Object best_entity;
2003 USE_SAFE_ALLOCA;
2004
2005 len = ASIZE (vec);
2006 if (len <= 1)
2007 return best_only ? AREF (vec, 0) : vec;
2008
2009 for (i = FONT_FOUNDRY_INDEX; i <= FONT_DPI_INDEX; i++)
2010 prefer_prop[i] = AREF (prefer, i);
2011
2012 if (! NILP (spec))
2013 {
2014 /* A font driver may return a font that has a property value
2015 different from the value specified in SPEC if the driver
2016 thinks they are the same. That happens, for instance, such a
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++)
2021 if (! NILP (AREF (spec, i)))
2022 prefer_prop[i] = Qnil;
2023 }
2024
2025 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2026 prefer_prop[FONT_SIZE_INDEX]
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 }
2036
2037 /* Scoring and sorting. */
2038 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
2039 best_score = 0xFFFFFFFF;
2040 best_entity = Qnil;
2041 for (i = 0; i < len; i++)
2042 {
2043 data[i].entity = AREF (vec, i);
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 }
2053 }
2054 if (NILP (best_entity))
2055 {
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;
2062 SAFE_FREE ();
2063
2064 return vec;
2065 }
2066
2067 \f
2068 /* API of Font Service Layer. */
2069
2070 /* Reflect ORDER (see the variable font_sort_order in xfaces.c) to
2071 sort_shift_bits. Finternal_set_font_selection_order calls this
2072 function with font_sort_order after setting up it. */
2073
2074 void
2075 font_update_sort_order (order)
2076 int *order;
2077 {
2078 int i, shift_bits;
2079
2080 for (i = 0, shift_bits = 21; i < 4; i++, shift_bits -= 7)
2081 {
2082 int xlfd_idx = order[i];
2083
2084 if (xlfd_idx == XLFD_WEIGHT_INDEX)
2085 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
2086 else if (xlfd_idx == XLFD_SLANT_INDEX)
2087 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
2088 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
2089 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
2090 else
2091 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
2092 }
2093 }
2094
2095
2096 /* Check if ENTITY matches with the font specification SPEC. */
2097
2098 int
2099 font_match_p (spec, entity)
2100 Lisp_Object spec, entity;
2101 {
2102 Lisp_Object prefer_prop[FONT_SPEC_MAX];
2103 Lisp_Object alternate_families = Qnil;
2104 int prefer_style[3];
2105 int i;
2106
2107 for (i = FONT_FOUNDRY_INDEX; i <= FONT_SIZE_INDEX; i++)
2108 prefer_prop[i] = AREF (spec, i);
2109 if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
2110 prefer_prop[FONT_SIZE_INDEX]
2111 = make_number (font_pixel_size (XFRAME (selected_frame), spec));
2112 if (! NILP (prefer_prop[FONT_FAMILY_INDEX]))
2113 {
2114 alternate_families
2115 = Fassoc_string (prefer_prop[FONT_FAMILY_INDEX],
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);
2122 }
2123
2124
2125 /* CHeck a lispy font object corresponding to FONT. */
2126
2127 int
2128 font_check_object (font)
2129 struct font *font;
2130 {
2131 Lisp_Object tail, elt;
2132
2133 for (tail = font->props[FONT_OBJLIST_INDEX]; CONSP (tail);
2134 tail = XCDR (tail))
2135 {
2136 elt = XCAR (tail);
2137 if (font == XFONT_OBJECT (elt))
2138 return 1;
2139 }
2140 return 0;
2141 }
2142
2143 \f
2144 /* Font cache
2145
2146 Each font backend has the callback function get_cache, and it
2147 returns a cons cell of which cdr part can be freely used for
2148 caching fonts. The cons cell may be shared by multiple frames
2149 and/or multiple font drivers. So, we arrange the cdr part as this:
2150
2151 ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...)
2152
2153 where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
2154 is a number frames sharing this cache, and FONT-CACHE-DATA is a
2155 cons (FONT-SPEC FONT-ENTITY ...). */
2156
2157 static void font_prepare_cache P_ ((FRAME_PTR, struct font_driver *));
2158 static void font_finish_cache P_ ((FRAME_PTR, struct font_driver *));
2159 static Lisp_Object font_get_cache P_ ((FRAME_PTR, struct font_driver *));
2160 static void font_clear_cache P_ ((FRAME_PTR, Lisp_Object,
2161 struct font_driver *));
2162
2163 static void
2164 font_prepare_cache (f, driver)
2165 FRAME_PTR f;
2166 struct font_driver *driver;
2167 {
2168 Lisp_Object cache, val;
2169
2170 cache = driver->get_cache (f);
2171 val = XCDR (cache);
2172 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2173 val = XCDR (val);
2174 if (NILP (val))
2175 {
2176 val = Fcons (driver->type, Fcons (make_number (1), Qnil));
2177 XSETCDR (cache, Fcons (val, XCDR (cache)));
2178 }
2179 else
2180 {
2181 val = XCDR (XCAR (val));
2182 XSETCAR (val, make_number (XINT (XCAR (val)) + 1));
2183 }
2184 }
2185
2186
2187 static void
2188 font_finish_cache (f, driver)
2189 FRAME_PTR f;
2190 struct font_driver *driver;
2191 {
2192 Lisp_Object cache, val, tmp;
2193
2194
2195 cache = driver->get_cache (f);
2196 val = XCDR (cache);
2197 while (CONSP (val) && ! EQ (XCAR (XCAR (val)), driver->type))
2198 cache = val, val = XCDR (val);
2199 xassert (! NILP (val));
2200 tmp = XCDR (XCAR (val));
2201 XSETCAR (tmp, make_number (XINT (XCAR (tmp)) - 1));
2202 if (XINT (XCAR (tmp)) == 0)
2203 {
2204 font_clear_cache (f, XCAR (val), driver);
2205 XSETCDR (cache, XCDR (val));
2206 }
2207 }
2208
2209
2210 static Lisp_Object
2211 font_get_cache (f, driver)
2212 FRAME_PTR f;
2213 struct font_driver *driver;
2214 {
2215 Lisp_Object val = driver->get_cache (f);
2216 Lisp_Object type = driver->type;
2217
2218 xassert (CONSP (val));
2219 for (val = XCDR (val); ! EQ (XCAR (XCAR (val)), type); val = XCDR (val));
2220 xassert (CONSP (val));
2221 /* VAL = ((DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) ...) */
2222 val = XCDR (XCAR (val));
2223 return val;
2224 }
2225
2226 static int num_fonts;
2227
2228 static void
2229 font_clear_cache (f, cache, driver)
2230 FRAME_PTR f;
2231 Lisp_Object cache;
2232 struct font_driver *driver;
2233 {
2234 Lisp_Object tail, elt;
2235
2236 /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
2237 for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
2238 {
2239 elt = XCAR (tail);
2240 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2241 {
2242 Lisp_Object vec = XCDR (elt);
2243 int i;
2244
2245 for (i = 0; i < ASIZE (vec); i++)
2246 {
2247 Lisp_Object entity = AREF (vec, i);
2248
2249 if (EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
2250 {
2251 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2252
2253 for (; CONSP (objlist); objlist = XCDR (objlist))
2254 {
2255 Lisp_Object val = XCAR (objlist);
2256 struct font *font = XFONT_OBJECT (val);
2257
2258 xassert (font && driver == font->driver);
2259 driver->close (f, font);
2260 num_fonts--;
2261 }
2262 if (driver->free_entity)
2263 driver->free_entity (entity);
2264 }
2265 }
2266 }
2267 }
2268 XSETCDR (cache, Qnil);
2269 }
2270 \f
2271
2272 static Lisp_Object scratch_font_spec, scratch_font_prefer;
2273
2274 Lisp_Object
2275 font_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;
2281
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;
2295
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
2319 Lisp_Object
2320 font_list_entities (frame, spec)
2321 Lisp_Object frame, spec;
2322 {
2323 FRAME_PTR f = XFRAME (frame);
2324 struct font_driver_list *driver_list = f->font_driver_list;
2325 Lisp_Object ftype, family, alternate_familes;
2326 Lisp_Object *vec;
2327 int size;
2328 int need_filtering = 0;
2329 int n_family = 1;
2330 int i;
2331
2332 xassert (FONT_SPEC_P (spec));
2333
2334 family = AREF (spec, FONT_FAMILY_INDEX);
2335 if (NILP (family))
2336 alternate_familes = Qnil;
2337 else
2338 {
2339 alternate_familes = Fassoc_string (family,
2340 Vface_alternative_font_family_alist,
2341 Qt);
2342 if (! NILP (alternate_familes))
2343 alternate_familes = XCDR (alternate_familes);
2344 n_family += XINT (Flength (alternate_familes));
2345 }
2346
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
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;
2368
2369 for (i = 0; driver_list; driver_list = driver_list->next)
2370 if (driver_list->on
2371 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2372 {
2373 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2374 Lisp_Object tail = alternate_familes;
2375
2376 while (1)
2377 {
2378 Lisp_Object val = assoc_no_quit (scratch_font_spec, XCDR (cache));
2379
2380 if (CONSP (val) && VECTORP (XCDR (val)))
2381 val = XCDR (val);
2382 else
2383 {
2384 Lisp_Object copy;
2385
2386 val = driver_list->driver->list (frame, scratch_font_spec);
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)));
2391 }
2392 if (! NILP (val))
2393 {
2394 vec[i++] = val;
2395 break;
2396 }
2397 if (NILP (tail))
2398 break;
2399 ASET (scratch_font_spec, FONT_FAMILY_INDEX,
2400 Fintern (XCAR (tail), Qnil));
2401 tail = XCDR (tail);
2402 }
2403 }
2404
2405 return (i > 0 ? Fvconcat (i, vec) : null_vector);
2406 }
2407
2408
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. */
2412
2413 static Lisp_Object
2414 font_matching_entity (f, attrs, spec)
2415 FRAME_PTR f;
2416 Lisp_Object *attrs, spec;
2417 {
2418 struct font_driver_list *driver_list = f->font_driver_list;
2419 Lisp_Object ftype, size, entity;
2420 Lisp_Object frame;
2421
2422 XSETFRAME (frame, f);
2423 ftype = AREF (spec, FONT_TYPE_INDEX);
2424 size = AREF (spec, FONT_SIZE_INDEX);
2425 if (FLOATP (size))
2426 ASET (spec, FONT_SIZE_INDEX, make_number (font_pixel_size (f, spec)));
2427 entity = Qnil;
2428 for (; driver_list; driver_list = driver_list->next)
2429 if (driver_list->on
2430 && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
2431 {
2432 Lisp_Object cache = font_get_cache (f, driver_list->driver);
2433
2434 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2435 entity = assoc_no_quit (spec, XCDR (cache));
2436 if (CONSP (entity) && ! VECTORP (XCDR (entity)))
2437 entity = XCDR (entity);
2438 else
2439 {
2440 entity = driver_list->driver->match (frame, spec);
2441 XSETCDR (cache, Fcons (Fcons (Fcopy_font_spec (spec), entity),
2442 XCDR (cache)));
2443 }
2444 if (! NILP (entity))
2445 break;
2446 }
2447 ASET (spec, FONT_TYPE_INDEX, ftype);
2448 ASET (spec, FONT_SIZE_INDEX, size);
2449 return entity;
2450 }
2451
2452
2453 /* Open a font of ENTITY and PIXEL_SIZE on frame F, and return the
2454 opened font object. */
2455
2456 static Lisp_Object
2457 font_open_entity (f, entity, pixel_size)
2458 FRAME_PTR f;
2459 Lisp_Object entity;
2460 int pixel_size;
2461 {
2462 struct font_driver_list *driver_list;
2463 Lisp_Object objlist, size, val, font_object;
2464 struct font *font;
2465 int min_width;
2466
2467 xassert (FONT_ENTITY_P (entity));
2468 size = AREF (entity, FONT_SIZE_INDEX);
2469 if (XINT (size) != 0)
2470 pixel_size = XINT (size);
2471
2472 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2473 objlist = XCDR (objlist))
2474 if (XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size)
2475 return XCAR (objlist);
2476
2477 val = AREF (entity, FONT_TYPE_INDEX);
2478 for (driver_list = f->font_driver_list;
2479 driver_list && ! EQ (driver_list->driver->type, val);
2480 driver_list = driver_list->next);
2481 if (! driver_list)
2482 return Qnil;
2483
2484 font_object = driver_list->driver->open (f, entity, pixel_size);
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)
2499 {
2500 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
2501 FRAME_SMALLEST_FONT_HEIGHT (f) = font->height;
2502 fonts_changed_p = 1;
2503 }
2504 else
2505 {
2506 if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
2507 FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
2508 if (FRAME_SMALLEST_FONT_HEIGHT (f) > font->height)
2509 FRAME_SMALLEST_FONT_HEIGHT (f) = font->height, fonts_changed_p = 1;
2510 }
2511
2512 return font_object;
2513 }
2514
2515
2516 /* Close FONT_OBJECT that is opened on frame F. */
2517
2518 void
2519 font_close_object (f, font_object)
2520 FRAME_PTR f;
2521 Lisp_Object font_object;
2522 {
2523 struct font *font = XFONT_OBJECT (font_object);
2524 Lisp_Object objlist;
2525 Lisp_Object tail, prev = Qnil;
2526
2527 objlist = AREF (font_object, FONT_OBJLIST_INDEX);
2528 for (prev = Qnil, tail = objlist; CONSP (tail);
2529 prev = tail, tail = XCDR (tail))
2530 if (EQ (font_object, XCAR (tail)))
2531 {
2532 xassert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
2533 font->driver->close (f, font);
2534 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
2535 if (NILP (prev))
2536 ASET (font_object, FONT_OBJLIST_INDEX, XCDR (objlist));
2537 else
2538 XSETCDR (prev, XCDR (objlist));
2539 num_fonts--;
2540 return;
2541 }
2542 abort ();
2543 }
2544
2545
2546 /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if
2547 FONT is a font-entity and it must be opened to check. */
2548
2549 int
2550 font_has_char (f, font, c)
2551 FRAME_PTR f;
2552 Lisp_Object font;
2553 int c;
2554 {
2555 struct font *fontp;
2556
2557 if (FONT_ENTITY_P (font))
2558 {
2559 Lisp_Object type = AREF (font, FONT_TYPE_INDEX);
2560 struct font_driver_list *driver_list;
2561
2562 for (driver_list = f->font_driver_list;
2563 driver_list && ! EQ (driver_list->driver->type, type);
2564 driver_list = driver_list->next);
2565 if (! driver_list)
2566 return 0;
2567 if (! driver_list->driver->has_char)
2568 return -1;
2569 return driver_list->driver->has_char (font, c);
2570 }
2571
2572 xassert (FONT_OBJECT_P (font));
2573 fontp = XFONT_OBJECT (font);
2574 if (fontp->driver->has_char)
2575 {
2576 int result = fontp->driver->has_char (font, c);
2577
2578 if (result >= 0)
2579 return result;
2580 }
2581 return (fontp->driver->encode_char (fontp, c) != FONT_INVALID_CODE);
2582 }
2583
2584
2585 /* Return the glyph ID of FONT_OBJECT for character C. */
2586
2587 unsigned
2588 font_encode_char (font_object, c)
2589 Lisp_Object font_object;
2590 int c;
2591 {
2592 struct font *font;
2593
2594 xassert (FONT_OBJECT_P (font_object));
2595 font = XFONT_OBJECT (font_object);
2596 return font->driver->encode_char (font, c);
2597 }
2598
2599
2600 /* Return the name of FONT_OBJECT. */
2601
2602 Lisp_Object
2603 font_get_name (font_object)
2604 Lisp_Object font_object;
2605 {
2606 Lisp_Object name;
2607
2608 xassert (FONT_OBJECT_P (font_object));
2609 return AREF (font_object, FONT_NAME_INDEX);
2610 }
2611
2612
2613 /* Return the specification of FONT_OBJECT. */
2614
2615 Lisp_Object
2616 font_get_spec (font_object)
2617 Lisp_Object font_object;
2618 {
2619 Lisp_Object spec = font_make_spec ();
2620 int i;
2621
2622 for (i = 0; i < FONT_SIZE_INDEX; i++)
2623 ASET (spec, i, AREF (font_object, i));
2624 ASET (spec, FONT_SIZE_INDEX,
2625 make_number (XFONT_OBJECT (font_object)->pixel_size));
2626 return spec;
2627 }
2628
2629 Lisp_Object
2630 font_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 }
2639
2640
2641 void
2642 font_clear_prop (attrs, prop)
2643 Lisp_Object *attrs;
2644 enum font_property_index prop;
2645 {
2646 Lisp_Object font = attrs[LFACE_FONT_INDEX];
2647 Lisp_Object extra, prev;
2648
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;
2672 }
2673
2674 void
2675 font_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;
2711
2712 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
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
2732 character that the entity must support. */
2733
2734 Lisp_Object
2735 font_find_for_lface (f, attrs, spec, c)
2736 FRAME_PTR f;
2737 Lisp_Object *attrs;
2738 Lisp_Object spec;
2739 int c;
2740 {
2741 Lisp_Object frame, entities, val, props[FONT_REGISTRY_INDEX + 1] ;
2742 Lisp_Object size;
2743 int i, result;
2744
2745 if (c >= 0)
2746 {
2747 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
2748 struct charset *encoding, *repertory;
2749
2750 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
2751 return Qnil;
2752 if (repertory)
2753 {
2754 if (ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory))
2755 return Qnil;
2756 /* Any font of this registry support C. So, let's
2757 suppress the further checking. */
2758 c = -1;
2759 }
2760 else if (c > encoding->max_char)
2761 return Qnil;
2762 }
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);
2769 if (ASIZE (entities) == 0)
2770 return Qnil;
2771 if (ASIZE (entities) == 1)
2772 {
2773 if (c < 0)
2774 return AREF (entities, 0);
2775 }
2776 else
2777 {
2778 /* Sort fonts by properties specified in LFACE. */
2779 Lisp_Object prefer = scratch_font_prefer;
2780 double pt;
2781 for (i = 0; i < FONT_EXTRA_INDEX; i++)
2782 ASET (prefer, i, AREF (spec, i));
2783 if (NILP (AREF (prefer, FONT_FAMILY_INDEX)))
2784 font_parse_family_registry (attrs[LFACE_FAMILY_INDEX], Qnil, prefer);
2785 if (NILP (AREF (prefer, FONT_WEIGHT_INDEX)))
2786 FONT_SET_STYLE (prefer, FONT_WEIGHT_INDEX, attrs[LFACE_WEIGHT_INDEX]);
2787 if (NILP (AREF (prefer, FONT_SLANT_INDEX)))
2788 FONT_SET_STYLE (prefer, FONT_SLANT_INDEX, attrs[LFACE_SLANT_INDEX]);
2789 if (NILP (AREF (prefer, FONT_WIDTH_INDEX)))
2790 FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
2791 if (INTEGERP (size))
2792 ASET (prefer, FONT_SIZE_INDEX, size);
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);
2804 }
2805 if (c < 0)
2806 return entities;
2807
2808 for (i = 0; i < ASIZE (entities); i++)
2809 {
2810 int j;
2811
2812 val = AREF (entities, i);
2813 if (i > 0)
2814 {
2815 for (j = FONT_FOUNDRY_INDEX; j <= FONT_REGISTRY_INDEX; j++)
2816 if (! EQ (AREF (val, j), props[j]))
2817 break;
2818 if (j > FONT_REGISTRY_INDEX)
2819 continue;
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 }
2836 return Qnil;
2837 }
2838
2839
2840 Lisp_Object
2841 font_open_for_lface (f, entity, attrs, spec)
2842 FRAME_PTR f;
2843 Lisp_Object entity;
2844 Lisp_Object *attrs;
2845 Lisp_Object spec;
2846 {
2847 int size;
2848
2849 if (FONT_SPEC_P (spec) && INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2850 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2851 else
2852 {
2853 double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
2854
2855 pt /= 10;
2856 size = POINT_TO_PIXEL (pt, f->resy);
2857 }
2858 return font_open_entity (f, entity, size);
2859 }
2860
2861
2862 /* Find a font satisfying SPEC and best matching with face's
2863 attributes in ATTRS on FRAME, and return the opened
2864 font-object. */
2865
2866 Lisp_Object
2867 font_load_for_lface (f, attrs, spec)
2868 FRAME_PTR f;
2869 Lisp_Object *attrs, spec;
2870 {
2871 Lisp_Object entity;
2872
2873 entity = font_find_for_lface (f, attrs, spec, -1);
2874 if (NILP (entity))
2875 {
2876 /* No font is listed for SPEC, but each font-backend may have
2877 the different criteria about "font matching". So, try
2878 it. */
2879 entity = font_matching_entity (f, attrs, spec);
2880 if (NILP (entity))
2881 return Qnil;
2882 }
2883 return font_open_for_lface (f, entity, attrs, spec);
2884 }
2885
2886
2887 /* Make FACE on frame F ready to use the font opened for FACE. */
2888
2889 void
2890 font_prepare_for_face (f, face)
2891 FRAME_PTR f;
2892 struct face *face;
2893 {
2894 if (face->font->driver->prepare_face)
2895 face->font->driver->prepare_face (f, face);
2896 }
2897
2898
2899 /* Make FACE on frame F stop using the font opened for FACE. */
2900
2901 void
2902 font_done_for_face (f, face)
2903 FRAME_PTR f;
2904 struct face *face;
2905 {
2906 if (face->font->driver->done_face)
2907 face->font->driver->done_face (f, face);
2908 face->extra = NULL;
2909 }
2910
2911
2912 /* Open a font best matching with NAME on frame F. If no proper font
2913 is found, return Qnil. */
2914
2915 Lisp_Object
2916 font_open_by_name (f, name)
2917 FRAME_PTR f;
2918 char *name;
2919 {
2920 Lisp_Object args[2];
2921 Lisp_Object spec, prefer, size, entity, entity_list;
2922 Lisp_Object frame;
2923 int i;
2924 int pixel_size;
2925
2926 XSETFRAME (frame, f);
2927
2928 args[0] = QCname;
2929 args[1] = make_unibyte_string (name, strlen (name));
2930 spec = Ffont_spec (2, args);
2931 prefer = scratch_font_prefer;
2932 for (i = 0; i < FONT_SPEC_MAX; i++)
2933 {
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 }
2939 size = AREF (spec, FONT_SIZE_INDEX);
2940 if (NILP (size))
2941 pixel_size = 0;
2942 else
2943 {
2944 if (INTEGERP (size))
2945 pixel_size = XINT (size);
2946 else /* FLOATP (size) */
2947 {
2948 double pt = XFLOAT_DATA (size);
2949
2950 pixel_size = POINT_TO_PIXEL (pt, f->resy);
2951 }
2952 if (pixel_size == 0)
2953 ASET (spec, FONT_SIZE_INDEX, Qnil);
2954 }
2955 if (pixel_size == 0)
2956 {
2957 pixel_size = POINT_TO_PIXEL (12.0, f->resy);
2958 size = make_number (pixel_size);
2959 ASET (prefer, FONT_SIZE_INDEX, size);
2960 }
2961 if (NILP (AREF (spec, FONT_REGISTRY_INDEX)))
2962 ASET (spec, FONT_REGISTRY_INDEX, Qiso8859_1);
2963
2964 entity_list = Flist_fonts (spec, frame, make_number (1), prefer);
2965 if (NILP (entity_list))
2966 entity = font_matching_entity (f, NULL, spec);
2967 else
2968 entity = XCAR (entity_list);
2969 return (NILP (entity)
2970 ? Qnil
2971 : font_open_entity (f, entity, pixel_size));
2972 }
2973
2974
2975 /* Register font-driver DRIVER. This function is used in two ways.
2976
2977 The first is with frame F non-NULL. In this case, make DRIVER
2978 available (but not yet activated) on F. All frame creaters
2979 (e.g. Fx_create_frame) must call this function at least once with
2980 an available font-driver.
2981
2982 The second is with frame F NULL. In this case, DRIVER is globally
2983 registered in the variable `font_driver_list'. All font-driver
2984 implementations must call this function in its syms_of_XXXX
2985 (e.g. syms_of_xfont). */
2986
2987 void
2988 register_font_driver (driver, f)
2989 struct font_driver *driver;
2990 FRAME_PTR f;
2991 {
2992 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
2993 struct font_driver_list *prev, *list;
2994
2995 if (f && ! driver->draw)
2996 error ("Unusable font driver for a frame: %s",
2997 SDATA (SYMBOL_NAME (driver->type)));
2998
2999 for (prev = NULL, list = root; list; prev = list, list = list->next)
3000 if (EQ (list->driver->type, driver->type))
3001 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
3002
3003 list = malloc (sizeof (struct font_driver_list));
3004 list->on = 0;
3005 list->driver = driver;
3006 list->next = NULL;
3007 if (prev)
3008 prev->next = list;
3009 else if (f)
3010 f->font_driver_list = list;
3011 else
3012 font_driver_list = list;
3013 num_font_drivers++;
3014 }
3015
3016
3017 /* Free font-driver list on frame F. It doesn't free font-drivers
3018 themselves. */
3019
3020 void
3021 free_font_driver_list (f)
3022 FRAME_PTR f;
3023 {
3024 while (f->font_driver_list)
3025 {
3026 struct font_driver_list *next = f->font_driver_list->next;
3027
3028 free (f->font_driver_list);
3029 f->font_driver_list = next;
3030 }
3031 }
3032
3033
3034 /* Make the frame F use font backends listed in NEW_DRIVERS (list of
3035 symbols, e.g. xft, x). If NEW_DRIVERS is t, make F use all
3036 available font drivers. If NEW_DRIVERS is nil, finalize all drivers.
3037
3038 A caller must free all realized faces if any in advance. The
3039 return value is a list of font backends actually made used on
3040 F. */
3041
3042 Lisp_Object
3043 font_update_drivers (f, new_drivers)
3044 FRAME_PTR f;
3045 Lisp_Object new_drivers;
3046 {
3047 Lisp_Object active_drivers = Qnil;
3048 struct font_driver_list *list;
3049
3050 for (list = f->font_driver_list; list; list = list->next)
3051 if (list->on)
3052 {
3053 if (! EQ (new_drivers, Qt)
3054 && NILP (Fmemq (list->driver->type, new_drivers)))
3055 {
3056 if (list->driver->end_for_frame)
3057 list->driver->end_for_frame (f);
3058 font_finish_cache (f, list->driver);
3059 list->on = 0;
3060 }
3061 }
3062 else
3063 {
3064 if (EQ (new_drivers, Qt)
3065 || ! NILP (Fmemq (list->driver->type, new_drivers)))
3066 {
3067 if (! list->driver->start_for_frame
3068 || list->driver->start_for_frame (f) == 0)
3069 {
3070 font_prepare_cache (f, list->driver);
3071 list->on = 1;
3072 active_drivers = nconc2 (active_drivers,
3073 Fcons (list->driver->type, Qnil));
3074 }
3075 }
3076 }
3077
3078 return active_drivers;
3079 }
3080
3081 int
3082 font_put_frame_data (f, driver, data)
3083 FRAME_PTR f;
3084 struct font_driver *driver;
3085 void *data;
3086 {
3087 struct font_data_list *list, *prev;
3088
3089 for (prev = NULL, list = f->font_data_list; list;
3090 prev = list, list = list->next)
3091 if (list->driver == driver)
3092 break;
3093 if (! data)
3094 {
3095 if (list)
3096 {
3097 if (prev)
3098 prev->next = list->next;
3099 else
3100 f->font_data_list = list->next;
3101 free (list);
3102 }
3103 return 0;
3104 }
3105
3106 if (! list)
3107 {
3108 list = malloc (sizeof (struct font_data_list));
3109 if (! list)
3110 return -1;
3111 list->driver = driver;
3112 list->next = f->font_data_list;
3113 f->font_data_list = list;
3114 }
3115 list->data = data;
3116 return 0;
3117 }
3118
3119
3120 void *
3121 font_get_frame_data (f, driver)
3122 FRAME_PTR f;
3123 struct font_driver *driver;
3124 {
3125 struct font_data_list *list;
3126
3127 for (list = f->font_data_list; list; list = list->next)
3128 if (list->driver == driver)
3129 break;
3130 if (! list)
3131 return NULL;
3132 return list->data;
3133 }
3134
3135
3136 /* Return the font used to draw character C by FACE at buffer position
3137 POS in window W. If STRING is non-nil, it is a string containing C
3138 at index POS. If C is negative, get C from the current buffer or
3139 STRING. */
3140
3141 Lisp_Object
3142 font_at (c, pos, face, w, string)
3143 int c;
3144 EMACS_INT pos;
3145 struct face *face;
3146 struct window *w;
3147 Lisp_Object string;
3148 {
3149 FRAME_PTR f;
3150 int multibyte;
3151 Lisp_Object font_object;
3152
3153 if (c < 0)
3154 {
3155 if (NILP (string))
3156 {
3157 multibyte = ! NILP (current_buffer->enable_multibyte_characters);
3158 if (multibyte)
3159 {
3160 EMACS_INT pos_byte = CHAR_TO_BYTE (pos);
3161
3162 c = FETCH_CHAR (pos_byte);
3163 }
3164 else
3165 c = FETCH_BYTE (pos);
3166 }
3167 else
3168 {
3169 unsigned char *str;
3170
3171 multibyte = STRING_MULTIBYTE (string);
3172 if (multibyte)
3173 {
3174 EMACS_INT pos_byte = string_char_to_byte (string, pos);
3175
3176 str = SDATA (string) + pos_byte;
3177 c = STRING_CHAR (str, 0);
3178 }
3179 else
3180 c = SDATA (string)[pos];
3181 }
3182 }
3183
3184 f = XFRAME (w->frame);
3185 if (! FRAME_WINDOW_P (f))
3186 return Qnil;
3187 if (! face)
3188 {
3189 int face_id;
3190 EMACS_INT endptr;
3191
3192 if (STRINGP (string))
3193 face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
3194 DEFAULT_FACE_ID, 0);
3195 else
3196 face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
3197 pos + 100, 0);
3198 face = FACE_FROM_ID (f, face_id);
3199 }
3200 if (multibyte)
3201 {
3202 int face_id = FACE_FOR_CHAR (f, face, c, pos, string);
3203 face = FACE_FROM_ID (f, face_id);
3204 }
3205 if (! face->font)
3206 return Qnil;
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
3222 EMACS_INT
3223 font_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;
3273 }
3274
3275 \f
3276 /* Lisp API */
3277
3278 DEFUN ("fontp", Ffontp, Sfontp, 1, 2, 0,
3279 doc: /* Return t if OBJECT is a font-spec, font-entity, or font-object.
3280 Return nil otherwise.
3281 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
3282 which 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;
3286 {
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);
3296 }
3297
3298 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
3299 doc: /* Return a newly created font-spec with arguments as properties.
3300
3301 ARGS must come in pairs KEY VALUE of font properties. KEY must be a
3302 valid font property name listed below:
3303
3304 `:family', `:weight', `:slant', `:width'
3305
3306 They are the same as face attributes of the same name. See
3307 `set-face-attribute'.
3308
3309 `:foundry'
3310
3311 VALUE must be a string or a symbol specifying the font foundry, e.g. ``misc''.
3312
3313 `:adstyle'
3314
3315 VALUE must be a string or a symbol specifying the additional
3316 typographic style information of a font, e.g. ``sans''.
3317
3318 `:registry'
3319
3320 VALUE must be a string or a symbol specifying the charset registry and
3321 encoding of a font, e.g. ``iso8859-1''.
3322
3323 `:size'
3324
3325 VALUE must be a non-negative integer or a floating point number
3326 specifying the font size. It specifies the font size in pixels
3327 (if VALUE is an integer), or in points (if VALUE is a float).
3328 usage: (font-spec ARGS ...) */)
3329 (nargs, args)
3330 int nargs;
3331 Lisp_Object *args;
3332 {
3333 Lisp_Object spec = font_make_spec ();
3334 int i;
3335
3336 for (i = 0; i < nargs; i += 2)
3337 {
3338 Lisp_Object key = args[i], val = args[i + 1];
3339
3340 if (EQ (key, QCname))
3341 {
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 }
3351 else
3352 {
3353 int idx = get_font_prop_index (key);
3354
3355 if (idx >= 0)
3356 {
3357 val = font_prop_validate (idx, Qnil, val);
3358 if (idx < FONT_EXTRA_INDEX)
3359 ASET (spec, idx, val);
3360 else
3361 font_put_extra (spec, key, val);
3362 }
3363 else
3364 font_put_extra (spec, key, font_prop_validate (0, key, val));
3365 }
3366 }
3367 return spec;
3368 }
3369
3370 DEFUN ("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
3392 DEFUN ("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.
3394 Every specified properties in FROM override the corresponding
3395 properties 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 }
3421
3422 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
3423 doc: /* Return the value of FONT's property KEY.
3424 FONT is a font-spec, a font-entity, or a font-object. */)
3425 (font, key)
3426 Lisp_Object font, key;
3427 {
3428 int idx;
3429
3430 CHECK_FONT (font);
3431 CHECK_SYMBOL (key);
3432
3433 idx = get_font_prop_index (key);
3434 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3435 return AREF (font, idx);
3436 return Fcdr (Fassq (key, AREF (font, FONT_EXTRA_INDEX)));
3437 }
3438
3439
3440 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
3441 doc: /* Set one property of FONT-SPEC: give property PROP value VAL. */)
3442 (font_spec, prop, val)
3443 Lisp_Object font_spec, prop, val;
3444 {
3445 int idx;
3446 Lisp_Object extra, slot;
3447
3448 CHECK_FONT_SPEC (font_spec);
3449 idx = get_font_prop_index (prop);
3450 if (idx >= 0 && idx < FONT_EXTRA_INDEX)
3451 {
3452 if (idx == FONT_FAMILY_INDEX
3453 && STRINGP (val))
3454 font_parse_family_registry (val, Qnil, font_spec);
3455 else
3456 ASET (font_spec, idx, font_prop_validate (idx, Qnil, val));
3457 }
3458 else
3459 font_put_extra (font_spec, prop, font_prop_validate (0, prop, val));
3460 return val;
3461 }
3462
3463 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
3464 doc: /* List available fonts matching FONT-SPEC on the current frame.
3465 Optional 2nd argument FRAME specifies the target frame.
3466 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
3467 Optional 4th argument PREFER, if non-nil, is a font-spec to
3468 control the order of the returned list. Fonts are sorted by
3469 how they are close to PREFER. */)
3470 (font_spec, frame, num, prefer)
3471 Lisp_Object font_spec, frame, num, prefer;
3472 {
3473 Lisp_Object vec, list, tail;
3474 int n = 0, i, len;
3475
3476 if (NILP (frame))
3477 frame = selected_frame;
3478 CHECK_LIVE_FRAME (frame);
3479 CHECK_FONT_SPEC (font_spec);
3480 if (! NILP (num))
3481 {
3482 CHECK_NUMBER (num);
3483 n = XINT (num);
3484 if (n <= 0)
3485 return Qnil;
3486 }
3487 if (! NILP (prefer))
3488 CHECK_FONT_SPEC (prefer);
3489
3490 vec = font_list_entities (frame, font_spec);
3491 len = ASIZE (vec);
3492 if (len == 0)
3493 return Qnil;
3494 if (len == 1)
3495 return Fcons (AREF (vec, 0), Qnil);
3496
3497 if (! NILP (prefer))
3498 vec = font_sort_entites (vec, prefer, frame, font_spec, 0);
3499
3500 list = tail = Fcons (AREF (vec, 0), Qnil);
3501 if (n == 0 || n > len)
3502 n = len;
3503 for (i = 1; i < n; i++)
3504 {
3505 Lisp_Object val = Fcons (AREF (vec, i), Qnil);
3506
3507 XSETCDR (tail, val);
3508 tail = val;
3509 }
3510 return list;
3511 }
3512
3513 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
3514 doc: /* List available font families on the current frame.
3515 Optional argument FRAME specifies the target frame. */)
3516 (frame)
3517 Lisp_Object frame;
3518 {
3519 FRAME_PTR f;
3520 struct font_driver_list *driver_list;
3521 Lisp_Object list;
3522
3523 if (NILP (frame))
3524 frame = selected_frame;
3525 CHECK_LIVE_FRAME (frame);
3526 f = XFRAME (frame);
3527 list = Qnil;
3528 for (driver_list = f->font_driver_list; driver_list;
3529 driver_list = driver_list->next)
3530 if (driver_list->driver->list_family)
3531 {
3532 Lisp_Object val = driver_list->driver->list_family (frame);
3533
3534 if (NILP (list))
3535 list = val;
3536 else
3537 {
3538 Lisp_Object tail = list;
3539
3540 for (; CONSP (val); val = XCDR (val))
3541 if (NILP (Fmemq (XCAR (val), tail)))
3542 list = Fcons (XCAR (val), list);
3543 }
3544 }
3545 return list;
3546 }
3547
3548 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
3549 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
3550 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
3551 (font_spec, frame)
3552 Lisp_Object font_spec, frame;
3553 {
3554 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
3555
3556 if (CONSP (val))
3557 val = XCAR (val);
3558 return val;
3559 }
3560
3561 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 1, 0,
3562 doc: /* Return XLFD name of FONT.
3563 FONT is a font-spec, font-entity, or font-object.
3564 If the name is too long for XLFD (maximum 255 chars), return nil. */)
3565 (font)
3566 Lisp_Object font;
3567 {
3568 char name[256];
3569 int pixel_size = 0;
3570
3571 CHECK_FONT (font);
3572
3573 if (FONT_OBJECT_P (font))
3574 {
3575 Lisp_Object font_name = AREF (font, FONT_NAME_INDEX);
3576
3577 if (STRINGP (font_name)
3578 && SDATA (font_name)[0] == '-')
3579 return font_name;
3580 pixel_size = XFONT_OBJECT (font)->pixel_size;
3581 }
3582 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
3583 return Qnil;
3584 return build_string (name);
3585 }
3586
3587 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
3588 doc: /* Clear font cache. */)
3589 ()
3590 {
3591 Lisp_Object list, frame;
3592
3593 FOR_EACH_FRAME (list, frame)
3594 {
3595 FRAME_PTR f = XFRAME (frame);
3596 struct font_driver_list *driver_list = f->font_driver_list;
3597
3598 for (; driver_list; driver_list = driver_list->next)
3599 if (driver_list->on)
3600 {
3601 Lisp_Object cache = driver_list->driver->get_cache (f);
3602 Lisp_Object val;
3603
3604 val = XCDR (cache);
3605 while (! NILP (val)
3606 && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
3607 val = XCDR (val);
3608 xassert (! NILP (val));
3609 val = XCDR (XCAR (val));
3610 if (XINT (XCAR (val)) == 0)
3611 {
3612 font_clear_cache (f, XCAR (val), driver_list->driver);
3613 XSETCDR (cache, XCDR (val));
3614 }
3615 }
3616 }
3617
3618 return Qnil;
3619 }
3620
3621 DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table,
3622 Sinternal_set_font_style_table, 3, 3, 0,
3623 doc: /* Setup font style table from WEIGHT, SLANT, and WIDTH tables.
3624 WEIGHT, SLANT, WIDTH must be `font-weight-table', `font-slant-table',
3625 `font-width-table' respectivly.
3626 This function is called after those tables are initialized. */)
3627 (weight, slant, width)
3628 Lisp_Object weight, slant, width;
3629 {
3630 Lisp_Object tables[3];
3631 int i;
3632
3633 tables[0] = weight, tables[1] = slant, tables[2] = width;
3634
3635 font_style_table = Fmake_vector (make_number (3), Qnil);
3636 /* In the following loop, we don't use XCAR and XCDR until assuring
3637 the argument is a cons cell so that the error in the tables can
3638 be detected. */
3639 for (i = 0; i < 3; i++)
3640 {
3641 Lisp_Object tail, elt, list, val;
3642
3643 for (tail = tables[i], list = Qnil; CONSP (tail); tail = XCDR (tail))
3644 {
3645 int numeric = -1;
3646
3647 elt = Fcar (tail);
3648 CHECK_SYMBOL (Fcar (elt));
3649 val = Fcons (XCAR (elt), Qnil);
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));
3669 }
3670
3671 return Qnil;
3672 }
3673
3674 /* The following three functions are still expremental. */
3675
3676 DEFUN ("font-make-gstring", Ffont_make_gstring, Sfont_make_gstring, 2, 2, 0,
3677 doc: /* Return a newly created g-string for FONT-OBJECT with NUM glyphs.
3678 FONT-OBJECT may be nil if it is not yet known.
3679
3680 G-string is sequence of glyphs of a specific font,
3681 and is a vector of this form:
3682 [ HEADER GLYPH ... ]
3683 HEADER is a vector of this form:
3684 [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT]
3685 where
3686 FONT-OBJECT is a font-object for all glyphs in the g-string,
3687 WIDTH thry DESCENT are the metrics (in pixels) of the whole G-string.
3688 GLYPH is a vector of this form:
3689 [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT
3690 [ [X-OFF Y-OFF WADJUST] | nil] ]
3691 where
3692 FROM-IDX and TO-IDX are used internally and should not be touched.
3693 C is the character of the glyph.
3694 CODE is the glyph-code of C in FONT-OBJECT.
3695 WIDTH thry DESCENT are the metrics (in pixels) of the glyph.
3696 X-OFF and Y-OFF are offests to the base position for the glyph.
3697 WADJUST is the adjustment to the normal width of the glyph. */)
3698 (font_object, num)
3699 Lisp_Object font_object, num;
3700 {
3701 Lisp_Object gstring, g;
3702 int len;
3703 int i;
3704
3705 if (! NILP (font_object))
3706 CHECK_FONT_OBJECT (font_object);
3707 CHECK_NATNUM (num);
3708
3709 len = XINT (num) + 1;
3710 gstring = Fmake_vector (make_number (len), Qnil);
3711 g = Fmake_vector (make_number (6), Qnil);
3712 ASET (g, 0, font_object);
3713 ASET (gstring, 0, g);
3714 for (i = 1; i < len; i++)
3715 ASET (gstring, i, Fmake_vector (make_number (10), Qnil));
3716 return gstring;
3717 }
3718
3719 DEFUN ("font-fill-gstring", Ffont_fill_gstring, Sfont_fill_gstring, 4, 5, 0,
3720 doc: /* Fill in glyph-string GSTRING by characters for FONT-OBJECT.
3721 START and END specify the region to extract characters.
3722 If optional 5rd argument OBJECT is non-nil, it is a buffer or a string from
3723 where to extract characters.
3724 FONT-OBJECT may be nil if GSTRING already already contains one. */)
3725 (gstring, font_object, start, end, object)
3726 Lisp_Object gstring, font_object, start, end, object;
3727 {
3728 int len, i, c;
3729 unsigned code;
3730 struct font *font;
3731
3732 CHECK_VECTOR (gstring);
3733 if (NILP (font_object))
3734 font_object = LGSTRING_FONT (gstring);
3735 font = XFONT_OBJECT (font_object);
3736
3737 if (STRINGP (object))
3738 {
3739 const unsigned char *p;
3740
3741 CHECK_NATNUM (start);
3742 CHECK_NATNUM (end);
3743 if (XINT (start) > XINT (end)
3744 || XINT (end) > ASIZE (object)
3745 || XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3746 args_out_of_range_3 (object, start, end);
3747
3748 len = XINT (end) - XINT (start);
3749 p = SDATA (object) + string_char_to_byte (object, XINT (start));
3750 for (i = 0; i < len; i++)
3751 {
3752 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3753 /* Shut up GCC warning in comparison with
3754 MOST_POSITIVE_FIXNUM below. */
3755 EMACS_INT cod;
3756
3757 c = STRING_CHAR_ADVANCE (p);
3758 cod = code = font->driver->encode_char (font, c);
3759 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3760 break;
3761 LGLYPH_SET_FROM (g, i);
3762 LGLYPH_SET_TO (g, i);
3763 LGLYPH_SET_CHAR (g, c);
3764 LGLYPH_SET_CODE (g, code);
3765 }
3766 }
3767 else
3768 {
3769 int pos, pos_byte;
3770
3771 if (! NILP (object))
3772 Fset_buffer (object);
3773 validate_region (&start, &end);
3774 if (XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring))
3775 args_out_of_range (start, end);
3776 len = XINT (end) - XINT (start);
3777 pos = XINT (start);
3778 pos_byte = CHAR_TO_BYTE (pos);
3779 for (i = 0; i < len; i++)
3780 {
3781 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3782 /* Shut up GCC warning in comparison with
3783 MOST_POSITIVE_FIXNUM below. */
3784 EMACS_INT cod;
3785
3786 FETCH_CHAR_ADVANCE (c, pos, pos_byte);
3787 cod = code = font->driver->encode_char (font, c);
3788 if (cod > MOST_POSITIVE_FIXNUM || code == FONT_INVALID_CODE)
3789 break;
3790 LGLYPH_SET_FROM (g, i);
3791 LGLYPH_SET_TO (g, i);
3792 LGLYPH_SET_CHAR (g, c);
3793 LGLYPH_SET_CODE (g, code);
3794 }
3795 }
3796 for (; i < LGSTRING_LENGTH (gstring); i++)
3797 LGSTRING_SET_GLYPH (gstring, i, Qnil);
3798 return Qnil;
3799 }
3800
3801 DEFUN ("font-shape-text", Ffont_shape_text, Sfont_shape_text, 3, 4, 0,
3802 doc: /* Shape text between FROM and TO by FONT-OBJECT.
3803 If optional 4th argument STRING is non-nil, it is a string to shape,
3804 and FROM and TO are indices to the string.
3805 The value is the end position of the text that can be shaped by
3806 FONT-OBJECT. */)
3807 (from, to, font_object, string)
3808 Lisp_Object from, to, font_object, string;
3809 {
3810 struct font *font;
3811 struct font_metrics metrics;
3812 EMACS_INT start, end;
3813 Lisp_Object gstring, n;
3814 int len, i;
3815
3816 if (! FONT_OBJECT_P (font_object))
3817 return Qnil;
3818 font = XFONT_OBJECT (font_object);
3819 if (! font->driver->shape)
3820 return Qnil;
3821
3822 if (NILP (string))
3823 {
3824 validate_region (&from, &to);
3825 start = XFASTINT (from);
3826 end = XFASTINT (to);
3827 modify_region (current_buffer, start, end, 0);
3828 }
3829 else
3830 {
3831 CHECK_STRING (string);
3832 start = XINT (from);
3833 end = XINT (to);
3834 if (start < 0 || start > end || end > SCHARS (string))
3835 args_out_of_range_3 (string, from, to);
3836 }
3837
3838 len = end - start;
3839 gstring = Ffont_make_gstring (font_object, make_number (len));
3840 Ffont_fill_gstring (gstring, font_object, from, to, string);
3841
3842 /* Try at most three times with larger gstring each time. */
3843 for (i = 0; i < 3; i++)
3844 {
3845 Lisp_Object args[2];
3846
3847 n = font->driver->shape (gstring);
3848 if (INTEGERP (n))
3849 break;
3850 args[0] = gstring;
3851 args[1] = Fmake_vector (make_number (len), Qnil);
3852 gstring = Fvconcat (2, args);
3853 }
3854 if (! INTEGERP (n) || XINT (n) == 0)
3855 return Qnil;
3856 len = XINT (n);
3857
3858 for (i = 0; i < len;)
3859 {
3860 Lisp_Object gstr;
3861 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3862 EMACS_INT this_from = LGLYPH_FROM (g);
3863 EMACS_INT this_to = LGLYPH_TO (g) + 1;
3864 int j, k;
3865 int need_composition = 0;
3866
3867 metrics.lbearing = LGLYPH_LBEARING (g);
3868 metrics.rbearing = LGLYPH_RBEARING (g);
3869 metrics.ascent = LGLYPH_ASCENT (g);
3870 metrics.descent = LGLYPH_DESCENT (g);
3871 if (NILP (LGLYPH_ADJUSTMENT (g)))
3872 {
3873 metrics.width = LGLYPH_WIDTH (g);
3874 if (LGLYPH_CHAR (g) == 0 || metrics.width == 0)
3875 need_composition = 1;
3876 }
3877 else
3878 {
3879 metrics.width = LGLYPH_WADJUST (g);
3880 metrics.lbearing += LGLYPH_XOFF (g);
3881 metrics.rbearing += LGLYPH_XOFF (g);
3882 metrics.ascent -= LGLYPH_YOFF (g);
3883 metrics.descent += LGLYPH_YOFF (g);
3884 need_composition = 1;
3885 }
3886 for (j = i + 1; j < len; j++)
3887 {
3888 int x;
3889
3890 g = LGSTRING_GLYPH (gstring, j);
3891 if (this_from != LGLYPH_FROM (g))
3892 break;
3893 need_composition = 1;
3894 x = metrics.width + LGLYPH_LBEARING (g) + LGLYPH_XOFF (g);
3895 if (metrics.lbearing > x)
3896 metrics.lbearing = x;
3897 x = metrics.width + LGLYPH_RBEARING (g) + LGLYPH_XOFF (g);
3898 if (metrics.rbearing < x)
3899 metrics.rbearing = x;
3900 x = LGLYPH_ASCENT (g) - LGLYPH_YOFF (g);
3901 if (metrics.ascent < x)
3902 metrics.ascent = x;
3903 x = LGLYPH_DESCENT (g) - LGLYPH_YOFF (g);
3904 if (metrics.descent < x)
3905 metrics.descent = x;
3906 if (NILP (LGLYPH_ADJUSTMENT (g)))
3907 metrics.width += LGLYPH_WIDTH (g);
3908 else
3909 metrics.width += LGLYPH_WADJUST (g);
3910 }
3911
3912 if (need_composition)
3913 {
3914 gstr = Ffont_make_gstring (font_object, make_number (j - i));
3915 LGSTRING_SET_WIDTH (gstr, metrics.width);
3916 LGSTRING_SET_LBEARING (gstr, metrics.lbearing);
3917 LGSTRING_SET_RBEARING (gstr, metrics.rbearing);
3918 LGSTRING_SET_ASCENT (gstr, metrics.ascent);
3919 LGSTRING_SET_DESCENT (gstr, metrics.descent);
3920 for (k = i; i < j; i++)
3921 {
3922 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
3923
3924 LGLYPH_SET_FROM (g, LGLYPH_FROM (g) - this_from);
3925 LGLYPH_SET_TO (g, LGLYPH_TO (g) - this_from);
3926 LGSTRING_SET_GLYPH (gstr, i - k, LGSTRING_GLYPH (gstring, i));
3927 }
3928 from = make_number (start + this_from);
3929 to = make_number (start + this_to);
3930 if (NILP (string))
3931 Fcompose_region_internal (from, to, gstr, Qnil);
3932 else
3933 Fcompose_string_internal (string, from, to, gstr, Qnil);
3934 }
3935 else
3936 i = j;
3937 }
3938
3939 return to;
3940 }
3941
3942 DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
3943 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
3944 OTF-FEATURES specifies which features to apply in this format:
3945 (SCRIPT LANGSYS GSUB GPOS)
3946 where
3947 SCRIPT is a symbol specifying a script tag of OpenType,
3948 LANGSYS is a symbol specifying a langsys tag of OpenType,
3949 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
3950
3951 If LANGYS is nil, the default langsys is selected.
3952
3953 The features are applied in the order they appear in the list. The
3954 symbol `*' means to apply all available features not present in this
3955 list, and the remaining features are ignored. For instance, (vatu
3956 pstf * haln) is to apply vatu and pstf in this order, then to apply
3957 all available features other than vatu, pstf, and haln.
3958
3959 The features are applied to the glyphs in the range FROM and TO of
3960 the glyph-string GSTRING-IN.
3961
3962 If some feature is actually applicable, the resulting glyphs are
3963 produced in the glyph-string GSTRING-OUT from the index INDEX. In
3964 this case, the value is the number of produced glyphs.
3965
3966 If no feature is applicable, no glyph is produced in GSTRING-OUT, and
3967 the value is 0.
3968
3969 If GSTRING-OUT is too short to hold produced glyphs, no glyphs are
3970 produced in GSTRING-OUT, and the value is nil.
3971
3972 See the documentation of `font-make-gstring' for the format of
3973 glyph-string. */)
3974 (otf_features, gstring_in, from, to, gstring_out, index)
3975 Lisp_Object otf_features, gstring_in, from, to, gstring_out, index;
3976 {
3977 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
3978 Lisp_Object val;
3979 struct font *font;
3980 int len, num;
3981
3982 check_otf_features (otf_features);
3983 CHECK_FONT_OBJECT (font_object);
3984 font = XFONT_OBJECT (font_object);
3985 if (! font->driver->otf_drive)
3986 error ("Font backend %s can't drive OpenType GSUB table",
3987 SDATA (SYMBOL_NAME (font->driver->type)));
3988 CHECK_CONS (otf_features);
3989 CHECK_SYMBOL (XCAR (otf_features));
3990 val = XCDR (otf_features);
3991 CHECK_SYMBOL (XCAR (val));
3992 val = XCDR (otf_features);
3993 if (! NILP (val))
3994 CHECK_CONS (val);
3995 len = check_gstring (gstring_in);
3996 CHECK_VECTOR (gstring_out);
3997 CHECK_NATNUM (from);
3998 CHECK_NATNUM (to);
3999 CHECK_NATNUM (index);
4000
4001 if (XINT (from) >= XINT (to) || XINT (to) > len)
4002 args_out_of_range_3 (from, to, make_number (len));
4003 if (XINT (index) >= ASIZE (gstring_out))
4004 args_out_of_range (index, make_number (ASIZE (gstring_out)));
4005 num = font->driver->otf_drive (font, otf_features,
4006 gstring_in, XINT (from), XINT (to),
4007 gstring_out, XINT (index), 0);
4008 if (num < 0)
4009 return Qnil;
4010 return make_number (num);
4011 }
4012
4013 DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
4014 3, 3, 0,
4015 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
4016 OTF-FEATURES specifies which features of the font FONT-OBJECT to apply
4017 in this format:
4018 (SCRIPT LANGSYS FEATURE ...)
4019 See the documentation of `font-otf-gsub' for more detail.
4020
4021 The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
4022 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
4023 character code corresponding to the glyph or nil if there's no
4024 corresponding character. */)
4025 (font_object, character, otf_features)
4026 Lisp_Object font_object, character, otf_features;
4027 {
4028 struct font *font;
4029 Lisp_Object gstring_in, gstring_out, g;
4030 Lisp_Object alternates;
4031 int i, num;
4032
4033 CHECK_FONT_GET_OBJECT (font_object, font);
4034 if (! font->driver->otf_drive)
4035 error ("Font backend %s can't drive OpenType GSUB table",
4036 SDATA (SYMBOL_NAME (font->driver->type)));
4037 CHECK_CHARACTER (character);
4038 CHECK_CONS (otf_features);
4039
4040 gstring_in = Ffont_make_gstring (font_object, make_number (1));
4041 g = LGSTRING_GLYPH (gstring_in, 0);
4042 LGLYPH_SET_CHAR (g, XINT (character));
4043 gstring_out = Ffont_make_gstring (font_object, make_number (10));
4044 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
4045 gstring_out, 0, 1)) < 0)
4046 gstring_out = Ffont_make_gstring (font_object,
4047 make_number (ASIZE (gstring_out) * 2));
4048 alternates = Qnil;
4049 for (i = 0; i < num; i++)
4050 {
4051 Lisp_Object g = LGSTRING_GLYPH (gstring_out, i);
4052 int c = LGLYPH_CHAR (g);
4053 unsigned code = LGLYPH_CODE (g);
4054
4055 alternates = Fcons (Fcons (make_number (code),
4056 c > 0 ? make_number (c) : Qnil),
4057 alternates);
4058 }
4059 return Fnreverse (alternates);
4060 }
4061
4062
4063 #ifdef FONT_DEBUG
4064
4065 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
4066 doc: /* Open FONT-ENTITY. */)
4067 (font_entity, size, frame)
4068 Lisp_Object font_entity;
4069 Lisp_Object size;
4070 Lisp_Object frame;
4071 {
4072 int isize;
4073
4074 CHECK_FONT_ENTITY (font_entity);
4075 if (NILP (frame))
4076 frame = selected_frame;
4077 CHECK_LIVE_FRAME (frame);
4078
4079 if (NILP (size))
4080 isize = XINT (AREF (font_entity, FONT_SIZE_INDEX));
4081 else
4082 {
4083 CHECK_NUMBER_OR_FLOAT (size);
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 }
4091 return font_open_entity (XFRAME (frame), font_entity, isize);
4092 }
4093
4094 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
4095 doc: /* Close FONT-OBJECT. */)
4096 (font_object, frame)
4097 Lisp_Object font_object, frame;
4098 {
4099 CHECK_FONT_OBJECT (font_object);
4100 if (NILP (frame))
4101 frame = selected_frame;
4102 CHECK_LIVE_FRAME (frame);
4103 font_close_object (XFRAME (frame), font_object);
4104 return Qnil;
4105 }
4106
4107 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
4108 doc: /* Return information about FONT-OBJECT.
4109 The value is a vector:
4110 [ NAME FILENAME PIXEL-SIZE SIZE ASCENT DESCENT SPACE-WIDTH AVERAGE-WIDTH
4111 CAPABILITY ]
4112
4113 NAME is a string of the font name (or nil if the font backend doesn't
4114 provide a name).
4115
4116 FILENAME is a string of the font file (or nil if the font backend
4117 doesn't provide a file name).
4118
4119 PIXEL-SIZE is a pixel size by which the font is opened.
4120
4121 SIZE is a maximum advance width of the font in pixel.
4122
4123 ASCENT, DESCENT, SPACE-WIDTH, AVERAGE-WIDTH are metrics of the font in
4124 pixel.
4125
4126 CAPABILITY is a list whose first element is a symbol representing the
4127 font format \(x, opentype, truetype, type1, pcf, or bdf) and the
4128 remaining elements describes a detail of the font capability.
4129
4130 If the font is OpenType font, the form of the list is
4131 \(opentype GSUB GPOS)
4132 where GSUB shows which "GSUB" features the font supports, and GPOS
4133 shows which "GPOS" features the font supports. Both GSUB and GPOS are
4134 lists of the format:
4135 \((SCRIPT (LANGSYS FEATURE ...) ...) ...)
4136
4137 If the font is not OpenType font, currently the length of the form is
4138 one.
4139
4140 SCRIPT is a symbol representing OpenType script tag.
4141
4142 LANGSYS is a symbol representing OpenType langsys tag, or nil
4143 representing the default langsys.
4144
4145 FEATURE is a symbol representing OpenType feature tag.
4146
4147 If the font is not OpenType font, CAPABILITY is nil. */)
4148 (font_object)
4149 Lisp_Object font_object;
4150 {
4151 struct font *font;
4152 Lisp_Object val;
4153
4154 CHECK_FONT_GET_OBJECT (font_object, font);
4155
4156 val = Fmake_vector (make_number (9), Qnil);
4157 ASET (val, 0, AREF (font_object, FONT_NAME_INDEX));
4158 ASET (val, 1, AREF (font_object, FONT_FILE_INDEX));
4159 ASET (val, 2, make_number (font->pixel_size));
4160 ASET (val, 3, make_number (font->max_width));
4161 ASET (val, 4, make_number (font->ascent));
4162 ASET (val, 5, make_number (font->descent));
4163 ASET (val, 6, make_number (font->space_width));
4164 ASET (val, 7, make_number (font->average_width));
4165 if (font->driver->otf_capability)
4166 ASET (val, 8, Fcons (Qopentype, font->driver->otf_capability (font)));
4167 return val;
4168 }
4169
4170 DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
4171 doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
4172 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
4173 (font_object, string)
4174 Lisp_Object font_object, string;
4175 {
4176 struct font *font;
4177 int i, len;
4178 Lisp_Object vec;
4179
4180 CHECK_FONT_GET_OBJECT (font_object, font);
4181 CHECK_STRING (string);
4182 len = SCHARS (string);
4183 vec = Fmake_vector (make_number (len), Qnil);
4184 for (i = 0; i < len; i++)
4185 {
4186 Lisp_Object ch = Faref (string, make_number (i));
4187 Lisp_Object val;
4188 int c = XINT (ch);
4189 unsigned code;
4190 EMACS_INT cod;
4191 struct font_metrics metrics;
4192
4193 cod = code = font->driver->encode_char (font, c);
4194 if (code == FONT_INVALID_CODE)
4195 continue;
4196 val = Fmake_vector (make_number (6), Qnil);
4197 if (cod <= MOST_POSITIVE_FIXNUM)
4198 ASET (val, 0, make_number (code));
4199 else
4200 ASET (val, 0, Fcons (make_number (code >> 16),
4201 make_number (code & 0xFFFF)));
4202 font->driver->text_extents (font, &code, 1, &metrics);
4203 ASET (val, 1, make_number (metrics.lbearing));
4204 ASET (val, 2, make_number (metrics.rbearing));
4205 ASET (val, 3, make_number (metrics.width));
4206 ASET (val, 4, make_number (metrics.ascent));
4207 ASET (val, 5, make_number (metrics.descent));
4208 ASET (vec, i, val);
4209 }
4210 return vec;
4211 }
4212
4213 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
4214 doc: /* Return t if and only if font-spec SPEC matches with FONT.
4215 FONT is a font-spec, font-entity, or font-object. */)
4216 (spec, font)
4217 Lisp_Object spec, font;
4218 {
4219 CHECK_FONT_SPEC (spec);
4220 CHECK_FONT (font);
4221
4222 return (font_match_p (spec, font) ? Qt : Qnil);
4223 }
4224
4225 DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
4226 doc: /* Return a font-object for displaying a character at POSITION.
4227 Optional second arg WINDOW, if non-nil, is a window displaying
4228 the current buffer. It defaults to the currently selected window. */)
4229 (position, window, string)
4230 Lisp_Object position, window, string;
4231 {
4232 struct window *w;
4233 EMACS_INT pos;
4234
4235 if (NILP (string))
4236 {
4237 CHECK_NUMBER_COERCE_MARKER (position);
4238 pos = XINT (position);
4239 if (pos < BEGV || pos >= ZV)
4240 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
4241 }
4242 else
4243 {
4244 CHECK_NUMBER (position);
4245 CHECK_STRING (string);
4246 pos = XINT (position);
4247 if (pos < 0 || pos >= SCHARS (string))
4248 args_out_of_range (string, position);
4249 }
4250 if (NILP (window))
4251 window = selected_window;
4252 CHECK_LIVE_WINDOW (window);
4253 w = XWINDOW (window);
4254
4255 return font_at (-1, pos, NULL, w, string);
4256 }
4257
4258 #if 0
4259 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
4260 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
4261 The value is a number of glyphs drawn.
4262 Type C-l to recover what previously shown. */)
4263 (font_object, string)
4264 Lisp_Object font_object, string;
4265 {
4266 Lisp_Object frame = selected_frame;
4267 FRAME_PTR f = XFRAME (frame);
4268 struct font *font;
4269 struct face *face;
4270 int i, len, width;
4271 unsigned *code;
4272
4273 CHECK_FONT_GET_OBJECT (font_object, font);
4274 CHECK_STRING (string);
4275 len = SCHARS (string);
4276 code = alloca (sizeof (unsigned) * len);
4277 for (i = 0; i < len; i++)
4278 {
4279 Lisp_Object ch = Faref (string, make_number (i));
4280 Lisp_Object val;
4281 int c = XINT (ch);
4282
4283 code[i] = font->driver->encode_char (font, c);
4284 if (code[i] == FONT_INVALID_CODE)
4285 break;
4286 }
4287 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4288 face->fontp = font;
4289 if (font->driver->prepare_face)
4290 font->driver->prepare_face (f, face);
4291 width = font->driver->text_extents (font, code, i, NULL);
4292 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
4293 if (font->driver->done_face)
4294 font->driver->done_face (f, face);
4295 face->fontp = NULL;
4296 return make_number (len);
4297 }
4298 #endif
4299
4300 #endif /* FONT_DEBUG */
4301
4302 \f
4303 extern void syms_of_ftfont P_ (());
4304 extern void syms_of_xfont P_ (());
4305 extern void syms_of_xftfont P_ (());
4306 extern void syms_of_ftxfont P_ (());
4307 extern void syms_of_bdffont P_ (());
4308 extern void syms_of_w32font P_ (());
4309 extern void syms_of_atmfont P_ (());
4310
4311 void
4312 syms_of_font ()
4313 {
4314 sort_shift_bits[FONT_SLANT_INDEX] = 0;
4315 sort_shift_bits[FONT_WEIGHT_INDEX] = 7;
4316 sort_shift_bits[FONT_SIZE_INDEX] = 14;
4317 sort_shift_bits[FONT_WIDTH_INDEX] = 21;
4318 sort_shift_bits[FONT_ADSTYLE_INDEX] = 28;
4319 sort_shift_bits[FONT_FOUNDRY_INDEX] = 29;
4320 sort_shift_bits[FONT_FAMILY_INDEX] = 30;
4321 /* Note that sort_shift_bits[FONT_SORT_TYPE] and
4322 sort_shift_bits[FONT_SORT_REGISTRY] are never used. */
4323
4324 staticpro (&font_style_table);
4325 font_style_table = Fmake_vector (make_number (3), Qnil);
4326
4327 staticpro (&font_charset_alist);
4328 font_charset_alist = Qnil;
4329
4330 DEFSYM (Qfont_spec, "font-spec");
4331 DEFSYM (Qfont_entity, "font-entity");
4332 DEFSYM (Qfont_object, "font-object");
4333
4334 DEFSYM (Qopentype, "opentype");
4335
4336 DEFSYM (Qiso8859_1, "iso8859-1");
4337 DEFSYM (Qiso10646_1, "iso10646-1");
4338 DEFSYM (Qunicode_bmp, "unicode-bmp");
4339 DEFSYM (Qunicode_sip, "unicode-sip");
4340
4341 DEFSYM (QCotf, ":otf");
4342 DEFSYM (QClang, ":lang");
4343 DEFSYM (QCscript, ":script");
4344 DEFSYM (QCantialias, ":antialias");
4345
4346 DEFSYM (QCfoundry, ":foundry");
4347 DEFSYM (QCadstyle, ":adstyle");
4348 DEFSYM (QCregistry, ":registry");
4349 DEFSYM (QCspacing, ":spacing");
4350 DEFSYM (QCdpi, ":dpi");
4351 DEFSYM (QCscalable, ":scalable");
4352 DEFSYM (QCavgwidth, ":avgwidth");
4353 DEFSYM (QCfont_entity, ":font-entity");
4354 DEFSYM (QCfc_unknown_spec, ":fc-unknown-spec");
4355
4356 DEFSYM (Qc, "c");
4357 DEFSYM (Qm, "m");
4358 DEFSYM (Qp, "p");
4359 DEFSYM (Qd, "d");
4360
4361 staticpro (&null_vector);
4362 null_vector = Fmake_vector (make_number (0), Qnil);
4363
4364 staticpro (&scratch_font_spec);
4365 scratch_font_spec = Ffont_spec (0, NULL);
4366 staticpro (&scratch_font_prefer);
4367 scratch_font_prefer = Ffont_spec (0, NULL);
4368
4369 #ifdef HAVE_LIBOTF
4370 staticpro (&otf_list);
4371 otf_list = Qnil;
4372 #endif
4373
4374 defsubr (&Sfontp);
4375 defsubr (&Sfont_spec);
4376 defsubr (&Sfont_get);
4377 defsubr (&Sfont_put);
4378 defsubr (&Slist_fonts);
4379 defsubr (&Sfont_family_list);
4380 defsubr (&Sfind_font);
4381 defsubr (&Sfont_xlfd_name);
4382 defsubr (&Sclear_font_cache);
4383 defsubr (&Sinternal_set_font_style_table);
4384 defsubr (&Sfont_make_gstring);
4385 defsubr (&Sfont_fill_gstring);
4386 defsubr (&Sfont_shape_text);
4387 defsubr (&Sfont_drive_otf);
4388 defsubr (&Sfont_otf_alternates);
4389
4390 #ifdef FONT_DEBUG
4391 defsubr (&Sopen_font);
4392 defsubr (&Sclose_font);
4393 defsubr (&Squery_font);
4394 defsubr (&Sget_font_glyphs);
4395 defsubr (&Sfont_match_p);
4396 defsubr (&Sfont_at);
4397 #if 0
4398 defsubr (&Sdraw_string);
4399 #endif
4400 #endif /* FONT_DEBUG */
4401
4402 #ifdef HAVE_FREETYPE
4403 syms_of_ftfont ();
4404 #ifdef HAVE_X_WINDOWS
4405 syms_of_xfont ();
4406 syms_of_ftxfont ();
4407 #ifdef HAVE_XFT
4408 syms_of_xftfont ();
4409 #endif /* HAVE_XFT */
4410 #endif /* HAVE_X_WINDOWS */
4411 #else /* not HAVE_FREETYPE */
4412 #ifdef HAVE_X_WINDOWS
4413 syms_of_xfont ();
4414 #endif /* HAVE_X_WINDOWS */
4415 #endif /* not HAVE_FREETYPE */
4416 #ifdef HAVE_BDFFONT
4417 syms_of_bdffont ();
4418 #endif /* HAVE_BDFFONT */
4419 #ifdef WINDOWSNT
4420 syms_of_w32font ();
4421 #endif /* WINDOWSNT */
4422 #ifdef MAC_OS
4423 syms_of_atmfont ();
4424 #endif /* MAC_OS */
4425 }
4426
4427 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
4428 (do not change this comment) */