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