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