(font_parse_fcname): Fix parsing of point-size.
[bpt/emacs.git] / src / font.c
1 /* font.c -- "Font" primitives.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3 Copyright (C) 2006
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 2, 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
29 #include "lisp.h"
30 #include "buffer.h"
31 #include "frame.h"
32 #include "dispextern.h"
33 #include "charset.h"
34 #include "character.h"
35 #include "composite.h"
36 #include "fontset.h"
37 #include "font.h"
38
39 #define FONT_DEBUG
40
41 #ifdef FONT_DEBUG
42 #undef xassert
43 #define xassert(X) do {if (!(X)) abort ();} while (0)
44 #else
45 #define xassert(X) (void) 0
46 #endif
47
48 int enable_font_backend;
49
50 Lisp_Object Qfontp;
51
52 /* Important character set symbols. */
53 Lisp_Object Qiso8859_1, Qiso10646_1, Qunicode_bmp;
54
55 /* Like CHECK_FONT_SPEC but also validate properties of the font-spec,
56 and set X to the validated result. */
57
58 #define CHECK_VALIDATE_FONT_SPEC(x) \
59 do { \
60 if (! FONT_SPEC_P (x)) x = wrong_type_argument (Qfont, x); \
61 x = font_prop_validate (x); \
62 } while (0)
63
64 /* Number of pt per inch (from the TeXbook). */
65 #define PT_PER_INCH 72.27
66
67 /* Return a pixel size corresponding to POINT size (1/10 pt unit) on
68 resolution RESY. */
69 #define POINT_TO_PIXEL(POINT, RESY) ((POINT) * (RESY) / PT_PER_INCH / 10 + 0.5)
70
71 #define PIXEL_TO_POINT(PIXEL, RESY) ((PIXEL) * PT_PER_INCH * 10 / (RESY) + 0.5)
72
73 /* Special string of zero length. It is used to specify a NULL name
74 in a font properties (e.g. adstyle). We don't use the symbol of
75 NULL name because it's confusing (Lisp printer prints nothing for
76 it). */
77 Lisp_Object null_string;
78
79 /* Special vector of zero length. This is repeatedly used by (struct
80 font_driver *)->list when a specified font is not found. */
81 Lisp_Object null_vector;
82
83 /* Vector of 3 elements. Each element is an alist for one of font
84 style properties (weight, slant, width). The alist contains a
85 mapping between symbolic property values (e.g. `medium' for weight)
86 and numeric property values (e.g. 100). So, it looks like this:
87 [((thin . 0) ... (heavy . 210))
88 ((ro . 0) ... (ot . 210))
89 ((ultracondensed . 50) ... (wide . 200))] */
90 static Lisp_Object font_style_table;
91
92 /* Alist of font family vs the corresponding aliases.
93 Each element has this form:
94 (FAMILY ALIAS1 ALIAS2 ...) */
95
96 static Lisp_Object font_family_alist;
97
98 /* Symbols representing keys of normal font properties. */
99 extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth, QCsize, QCname;
100 Lisp_Object QCfoundry, QCadstyle, QCregistry, QCextra;
101 /* Symbols representing keys of font extra info. */
102 Lisp_Object QCotf, QClanguage, QCscript;
103
104 /* List of all font drivers. All font-backends (XXXfont.c) call
105 add_font_driver in syms_of_XXXfont to register the font-driver
106 here. */
107 static struct font_driver_list *font_driver_list;
108
109 static Lisp_Object prop_name_to_numeric P_ ((enum font_property_index,
110 Lisp_Object));
111 static Lisp_Object prop_numeric_to_name P_ ((enum font_property_index, int));
112 static Lisp_Object font_open_entity P_ ((FRAME_PTR, Lisp_Object, int));
113
114 /* Number of registered font drivers. */
115 static int num_font_drivers;
116
117 /* Return a numeric value corresponding to PROP's NAME (symbol). If
118 NAME is not registered in font_style_table, return Qnil. PROP must
119 be one of FONT_{WEIGHT|SLANT|SWIDTH}_INDEX. */
120
121 static Lisp_Object
122 prop_name_to_numeric (prop, name)
123 enum font_property_index prop;
124 Lisp_Object name;
125 {
126 int table_index = prop - FONT_WEIGHT_INDEX;
127 Lisp_Object val;
128
129 val = assq_no_quit (name, AREF (font_style_table, table_index));
130 return (NILP (val) ? Qnil : XCDR (val));
131 }
132
133
134 /* Return a name (symbol) corresponding to PROP's NUMERIC value. If
135 no name is registered for NUMERIC in font_style_table, return a
136 symbol of integer name (e.g. `123'). PROP must be one of
137 FONT_{WEIGHT|SLANT|SWIDTH}_INDEX. */
138
139 static Lisp_Object
140 prop_numeric_to_name (prop, numeric)
141 enum font_property_index prop;
142 int numeric;
143 {
144 int table_index = prop - FONT_WEIGHT_INDEX;
145 Lisp_Object table = AREF (font_style_table, table_index);
146 char buf[10];
147
148 while (! NILP (table))
149 {
150 if (XINT (XCDR (XCAR (table))) >= numeric)
151 {
152 if (XINT (XCDR (XCAR (table))) == numeric)
153 return XCAR (XCAR (table));
154 else
155 break;
156 }
157 table = XCDR (table);
158 }
159 sprintf (buf, "%d", numeric);
160 return intern (buf);
161 }
162
163
164 /* Return a symbol whose name is STR (length LEN). If STR contains
165 uppercase letters, downcase them in advance. */
166
167 Lisp_Object
168 intern_downcase (str, len)
169 char *str;
170 int len;
171 {
172 char *buf;
173 int i;
174
175 for (i = 0; i < len; i++)
176 if (isupper (str[i]))
177 break;
178 if (i == len)
179 return Fintern (make_unibyte_string (str, len), Qnil);
180 buf = alloca (len);
181 if (! buf)
182 return Fintern (null_string, Qnil);
183 bcopy (str, buf, len);
184 for (; i < len; i++)
185 if (isascii (buf[i]))
186 buf[i] = tolower (buf[i]);
187 return Fintern (make_unibyte_string (buf, len), Qnil);
188 }
189
190 extern Lisp_Object Vface_alternative_font_family_alist;
191
192 static void
193 build_font_family_alist ()
194 {
195 Lisp_Object alist = Vface_alternative_font_family_alist;
196
197 for (; CONSP (alist); alist = XCDR (alist))
198 {
199 Lisp_Object tail, elt;
200
201 for (tail = XCAR (alist), elt = Qnil ; CONSP (tail); tail = XCDR (tail))
202 elt = nconc2 (elt, Fcons (Fintern (XCAR (tail), Qnil), Qnil));
203 font_family_alist = Fcons (elt, font_family_alist);
204 }
205 }
206
207 \f
208 /* Font property validater. */
209
210 static Lisp_Object
211 font_prop_validate_type (prop, val)
212 enum font_property_index prop;
213 Lisp_Object val;
214 {
215 return (SYMBOLP (val) ? val : Qerror);
216 }
217
218 static Lisp_Object
219 font_prop_validate_symbol (prop, val)
220 enum font_property_index prop;
221 Lisp_Object val;
222 {
223 if (STRINGP (val))
224 val = (SCHARS (val) == 0 ? null_string
225 : intern_downcase ((char *) SDATA (val), SBYTES (val)));
226 else if (SYMBOLP (val))
227 {
228 if (SCHARS (SYMBOL_NAME (val)) == 0)
229 val = null_string;
230 }
231 else
232 val = Qerror;
233 return val;
234 }
235
236 static Lisp_Object
237 font_prop_validate_style (prop, val)
238 enum font_property_index prop;
239 Lisp_Object val;
240 {
241 if (! INTEGERP (val))
242 {
243 if (STRINGP (val))
244 val = intern_downcase ((char *) SDATA (val), SBYTES (val));
245 if (! SYMBOLP (val))
246 val = Qerror;
247 else
248 {
249 val = prop_name_to_numeric (prop, val);
250 if (NILP (val))
251 val = Qerror;
252 }
253 }
254 return val;
255 }
256
257 static Lisp_Object
258 font_prop_validate_size (prop, val)
259 enum font_property_index prop;
260 Lisp_Object val;
261 {
262 return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
263 ? val : Qerror);
264 }
265
266 static Lisp_Object
267 font_prop_validate_extra (prop, val)
268 enum font_property_index prop;
269 Lisp_Object val;
270 {
271 Lisp_Object tail;
272
273 for (tail = val; CONSP (tail); tail = XCDR (tail))
274 {
275 Lisp_Object key = Fcar (XCAR (tail)), this_val = Fcdr (XCAR (tail));
276
277 if (NILP (this_val))
278 return Qnil;
279 if (EQ (key, QClanguage))
280 if (! SYMBOLP (this_val))
281 {
282 for (; CONSP (this_val); this_val = XCDR (this_val))
283 if (! SYMBOLP (XCAR (this_val)))
284 return Qerror;
285 if (! NILP (this_val))
286 return Qerror;
287 }
288 if (EQ (key, QCotf))
289 if (! STRINGP (this_val))
290 return Qerror;
291 }
292 return (NILP (tail) ? val : Qerror);
293 }
294
295
296 struct
297 {
298 Lisp_Object *key;
299 Lisp_Object (*validater) P_ ((enum font_property_index prop,
300 Lisp_Object val));
301 } font_property_table[FONT_SPEC_MAX] =
302 { { &QCtype, font_prop_validate_type },
303 { &QCfoundry, font_prop_validate_symbol },
304 { &QCfamily, font_prop_validate_symbol },
305 { &QCadstyle, font_prop_validate_symbol },
306 { &QCregistry, font_prop_validate_symbol },
307 { &QCweight, font_prop_validate_style },
308 { &QCslant, font_prop_validate_style },
309 { &QCwidth, font_prop_validate_style },
310 { &QCsize, font_prop_validate_size },
311 { &QCextra, font_prop_validate_extra }
312 };
313
314 static enum font_property_index
315 check_font_prop_name (key)
316 Lisp_Object key;
317 {
318 enum font_property_index i;
319
320 for (i = FONT_TYPE_INDEX; i < FONT_SPEC_MAX; i++)
321 if (EQ (key, *font_property_table[i].key))
322 break;
323 return i;
324 }
325
326 static Lisp_Object
327 font_prop_validate (spec)
328 Lisp_Object spec;
329 {
330 enum font_property_index i;
331 Lisp_Object val;
332
333 for (i = FONT_TYPE_INDEX; i <= FONT_EXTRA_INDEX; i++)
334 {
335 if (! NILP (AREF (spec, i)))
336 {
337 val = (font_property_table[i].validater) (i, AREF (spec, i));
338 if (EQ (val, Qerror))
339 Fsignal (Qerror, list3 (build_string ("invalid font property"),
340 *font_property_table[i].key,
341 AREF (spec, i)));
342 ASET (spec, i, val);
343 }
344 }
345 return spec;
346 }
347
348 \f
349 /* Font name parser and unparser */
350
351 /* An enumerator for each field of an XLFD font name. */
352
353 enum xlfd_field_index
354 {
355 XLFD_FOUNDRY_INDEX,
356 XLFD_FAMILY_INDEX,
357 XLFD_WEIGHT_INDEX,
358 XLFD_SLANT_INDEX,
359 XLFD_SWIDTH_INDEX,
360 XLFD_ADSTYLE_INDEX,
361 XLFD_PIXEL_INDEX,
362 XLFD_POINT_INDEX,
363 XLFD_RESX_INDEX,
364 XLFD_RESY_INDEX,
365 XLFD_SPACING_INDEX,
366 XLFD_AVGWIDTH_INDEX,
367 XLFD_REGISTRY_INDEX,
368 XLFD_ENCODING_INDEX,
369 XLFD_LAST_INDEX
370 };
371
372 enum xlfd_field_mask
373 {
374 XLFD_FOUNDRY_MASK = 0x0001,
375 XLFD_FAMILY_MASK = 0x0002,
376 XLFD_WEIGHT_MASK = 0x0004,
377 XLFD_SLANT_MASK = 0x0008,
378 XLFD_SWIDTH_MASK = 0x0010,
379 XLFD_ADSTYLE_MASK = 0x0020,
380 XLFD_PIXEL_MASK = 0x0040,
381 XLFD_POINT_MASK = 0x0080,
382 XLFD_RESX_MASK = 0x0100,
383 XLFD_RESY_MASK = 0x0200,
384 XLFD_SPACING_MASK = 0x0400,
385 XLFD_AVGWIDTH_MASK = 0x0800,
386 XLFD_REGISTRY_MASK = 0x1000,
387 XLFD_ENCODING_MASK = 0x2000
388 };
389
390
391 /* Return a Lispy value for string at STR and bytes LEN.
392 If LEN == 0, return a null string.
393 If the string is "*", return Qnil.
394 It is assured that LEN < 256. */
395
396 static Lisp_Object
397 intern_font_field (str, len)
398 char *str;
399 int len;
400 {
401 int i;
402
403 if (len == 0)
404 return null_string;
405 if (*str == '*' && len == 1)
406 return Qnil;
407 if (isdigit (*str))
408 {
409 for (i = 1; i < len; i++)
410 if (! isdigit (str[i]))
411 break;
412 if (i == len)
413 return make_number (atoi (str));
414 }
415 return intern_downcase (str, len);
416 }
417
418 /* Parse P pointing the pixel/point size field of the form
419 `[A B C D]' which specifies a transformation matrix:
420
421 A B 0
422 C D 0
423 0 0 1
424
425 by which all glyphs of the font are transformed. The spec says
426 that scalar value N for the pixel/point size is equivalent to:
427 A = N * resx/resy, B = C = 0, D = N.
428
429 Return the scalar value N if the form is valid. Otherwise return
430 -1. */
431
432 static int
433 parse_matrix (p)
434 char *p;
435 {
436 double matrix[4];
437 char *end;
438 int i;
439
440 for (i = 0, p++; i < 4 && *p && *p != ']'; i++)
441 {
442 if (*p == '~')
443 matrix[i] = - strtod (p + 1, &end);
444 else
445 matrix[i] = strtod (p, &end);
446 p = end;
447 }
448 return (i == 4 ? (int) matrix[3] : -1);
449 }
450
451 /* Expand a wildcard field in FIELD (the first N fields are filled) to
452 multiple fields to fill in all 14 XLFD fields while restring a
453 field position by its contents. */
454
455 int
456 font_expand_wildcards (field, n)
457 Lisp_Object field[XLFD_LAST_INDEX];
458 int n;
459 {
460 /* Copy of FIELD. */
461 Lisp_Object tmp[XLFD_LAST_INDEX];
462 /* Array of information about where this element can go. Nth
463 element is for Nth element of FIELD. */
464 struct {
465 /* Minimum possible field. */
466 int from;
467 /* Maxinum possible field. */
468 int to;
469 /* Bit mask of possible field. Nth bit corresponds to Nth field. */
470 int mask;
471 } range[XLFD_LAST_INDEX];
472 int i, j;
473 unsigned range_mask;
474
475 #define XLFD_SYMBOL_MASK (XLFD_FOUNDRY_MASK | XLFD_FAMILY_MASK \
476 | XLFD_ADSTYLE_MASK | XLFD_REGISTRY_MASK)
477 #define XLFD_NULL_MASK (XLFD_FOUNDRY_MASK | XLFD_ADSTYLE_MASK)
478 #define XLFD_LARGENUM_MASK (XLFD_POINT_MASK | XLFD_RESX_MASK | XLFD_RESY_MASK \
479 | XLFD_AVGWIDTH_MASK)
480 #define XLFD_REGENC_MASK (XLFD_REGISTRY_MASK | XLFD_ENCODING_MASK)
481
482 /* Initialize RANGE_MASK for FIELD[0] which can be 0th to (14 - N)th
483 field. The value is shifted to left one bit by one in the
484 following loop. */
485 for (i = 0, range_mask = 0; i <= 14 - n; i++)
486 range_mask = (range_mask << 1) | 1;
487
488 for (i = 0; i < n; i++, range_mask <<= 1)
489 {
490 /* The triplet RANGE_FROM, RANGE_TO, and RANGE_MASK is a
491 position-based retriction for FIELD[I]. */
492 int range_from = i, range_to = 14 - n + i;
493 Lisp_Object val = field[i];
494
495 tmp[i] = val;
496 if (NILP (val))
497 {
498 /* Wildcard. */
499 range[i].from = range_from;
500 range[i].to = range_to;
501 range[i].mask = range_mask;
502 }
503 else
504 {
505 /* The triplet FROM, TO, and MASK is a value-based
506 retriction for FIELD[I]. */
507 int from, to;
508 unsigned mask;
509
510 if (INTEGERP (val))
511 {
512 int numeric = XINT (val);
513
514 if (i + 1 == n)
515 from = to = XLFD_ENCODING_INDEX,
516 mask = XLFD_ENCODING_MASK;
517 else if (numeric <= 48)
518 from = to = XLFD_PIXEL_INDEX,
519 mask = XLFD_PIXEL_MASK;
520 else
521 from = XLFD_POINT_INDEX, to = XLFD_AVGWIDTH_MASK,
522 mask = XLFD_LARGENUM_MASK;
523 }
524 else if (EQ (val, null_string))
525 from = XLFD_FOUNDRY_INDEX, to = XLFD_ADSTYLE_INDEX,
526 mask = XLFD_NULL_MASK;
527 else if (i == 0)
528 from = to = XLFD_FOUNDRY_INDEX, mask = XLFD_FOUNDRY_MASK;
529 else if (i + 1 == n)
530 {
531 Lisp_Object name = SYMBOL_NAME (val);
532
533 if (SDATA (name)[SBYTES (name) - 1] == '*')
534 from = XLFD_REGISTRY_INDEX, to = XLFD_ENCODING_INDEX,
535 mask = XLFD_REGENC_MASK;
536 else
537 from = to = XLFD_ENCODING_INDEX,
538 mask = XLFD_ENCODING_MASK;
539 }
540 else if (range_from <= XLFD_WEIGHT_INDEX
541 && range_to >= XLFD_WEIGHT_INDEX
542 && !NILP (prop_name_to_numeric (FONT_WEIGHT_INDEX, val)))
543 from = to = XLFD_WEIGHT_INDEX, mask = XLFD_WEIGHT_MASK;
544 else if (range_from <= XLFD_SLANT_INDEX
545 && range_to >= XLFD_SLANT_INDEX
546 && !NILP (prop_name_to_numeric (FONT_SLANT_INDEX, val)))
547 from = to = XLFD_SLANT_INDEX, mask = XLFD_SLANT_MASK;
548 else if (range_from <= XLFD_SWIDTH_INDEX
549 && range_to >= XLFD_SWIDTH_INDEX
550 && !NILP (prop_name_to_numeric (FONT_WIDTH_INDEX, val)))
551 from = to = XLFD_SWIDTH_INDEX, mask = XLFD_SWIDTH_MASK;
552 else
553 {
554 Lisp_Object name = SYMBOL_NAME (val);
555
556 if (SBYTES (name) == 1
557 && (SDATA (name)[0] == 'c'
558 || SDATA (name)[0] == 'm'
559 || SDATA (name)[0] == 'p'))
560 from = to = XLFD_SPACING_INDEX, mask = XLFD_SPACING_MASK;
561 else
562 from = XLFD_FOUNDRY_INDEX, to = XLFD_ENCODING_INDEX,
563 mask = XLFD_SYMBOL_MASK;
564 }
565
566 /* Merge position-based and value-based restrictions. */
567 mask &= range_mask;
568 while (from < range_from)
569 mask &= ~(1 << from++);
570 while (from < 14 && ! (mask & (1 << from)))
571 from++;
572 while (to > range_to)
573 mask &= ~(1 << to--);
574 while (to >= 0 && ! (mask & (1 << to)))
575 to--;
576 if (from > to)
577 return -1;
578 range[i].from = from;
579 range[i].to = to;
580 range[i].mask = mask;
581
582 if (from > range_from || to < range_to)
583 /* The range is narrowed by value-based restrictions.
584 Reflect it to the previous fields. */
585 for (j = i - 1, from--, to--; j >= 0; j--, from--, to--)
586 {
587 /* Check FROM for non-wildcard field. */
588 if (! NILP (tmp[j]) && range[j].from < from)
589 {
590 while (range[j].from < from)
591 range[j].mask &= ~(1 << range[j].from++);
592 while (from < 14 && ! (range[j].mask & (1 << from)))
593 from++;
594 range[j].from = from;
595 }
596 else
597 from = range[j].from;
598 if (range[j].to > to)
599 {
600 while (range[j].to > to)
601 range[j].mask &= ~(1 << range[j].to--);
602 while (to >= 0 && ! (range[j].mask & (1 << to)))
603 to--;
604 range[j].to = to;
605 }
606 else
607 to = range[j].to;
608 if (from > to)
609 return -1;
610 }
611 }
612 }
613
614 /* Decide all fileds from restrictions in RANGE. */
615 for (i = j = 0; i < n ; i++)
616 {
617 if (j < range[i].from)
618 {
619 if (i == 0 || ! NILP (tmp[i - 1]))
620 /* None of TMP[X] corresponds to Jth field. */
621 return -1;
622 for (; j < range[i].from; j++)
623 field[j] = Qnil;
624 }
625 field[j++] = tmp[i];
626 }
627 if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX)
628 return -1;
629 for (; j < XLFD_LAST_INDEX; j++)
630 field[j] = Qnil;
631 if (INTEGERP (field[XLFD_ENCODING_INDEX]))
632 field[XLFD_ENCODING_INDEX]
633 = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil);
634 return 0;
635 }
636
637 /* Parse NAME (null terminated) as XLFD and store information in FONT
638 (font-spec or font-entity). See font_parse_name for more
639 detail. */
640
641 int
642 font_parse_xlfd (name, font, merge)
643 char *name;
644 Lisp_Object font;
645 int merge;
646 {
647 int len = strlen (name);
648 int i, j;
649 int pixel_size, resy, avgwidth;
650 double point_size;
651 Lisp_Object f[XLFD_LAST_INDEX];
652 Lisp_Object val;
653 char *p;
654
655 if (len > 255)
656 /* Maximum XLFD name length is 255. */
657 return -1;
658 i = (name[0] == '*' && name[1] == '-');
659 for (p = name + 1; *p; p++)
660 {
661 if (*p == '-')
662 {
663 i++;
664 if (i == XLFD_ENCODING_INDEX)
665 break;
666 }
667 }
668
669 pixel_size = resy = avgwidth = -1;
670 point_size = -1;
671
672 if (i == XLFD_ENCODING_INDEX)
673 {
674 /* Fully specified XLFD. */
675 if (name[0] == '-')
676 name++;
677 for (i = 0, p = name; ; p++)
678 {
679 if (*p == '-')
680 {
681 if (i < XLFD_PIXEL_INDEX)
682 f[i++] = intern_font_field (name, p - name);
683 else if (i == XLFD_PIXEL_INDEX)
684 {
685 if (isdigit (*name))
686 pixel_size = atoi (name);
687 else if (*name == '[')
688 pixel_size = parse_matrix (name);
689 i++;
690 }
691 else if (i == XLFD_POINT_INDEX)
692 {
693 if (pixel_size < 0)
694 {
695 if (isdigit (*name))
696 point_size = atoi (name);
697 else if (*name == '[')
698 point_size = parse_matrix (name);
699 }
700 i++;
701 }
702 else if (i == XLFD_RESX_INDEX)
703 {
704 /* Skip this field. */
705 f[i++] = Qnil;
706 }
707 else if (i == XLFD_RESY_INDEX)
708 {
709 /* Stuff RESY, SPACING, and AVGWIDTH. */
710 if (pixel_size < 0 && isdigit (*name))
711 resy = atoi (name);
712 for (p++; *p != '-'; p++);
713 if (isdigit (p[1]))
714 avgwidth = atoi (p + 1);
715 else if (p[1] == '~' && isdigit (p[2]))
716 avgwidth = atoi (p + 2);
717 for (p++; *p != '-'; p++);
718 if (FONT_ENTITY_P (font))
719 f[i] = intern_font_field (name, p - name);
720 else
721 f[i] = Qnil;
722 i = XLFD_REGISTRY_INDEX;
723 }
724 else
725 {
726 /* Stuff REGISTRY and ENCODING. */
727 for (p++; *p; p++);
728 f[i++] = intern_font_field (name, p - name);
729 break;
730 }
731 name = p + 1;
732 }
733 }
734 xassert (i == XLFD_ENCODING_INDEX);
735 }
736 else
737 {
738 int wild_card_found = 0;
739
740 if (name[0] == '-')
741 name++;
742 for (i = 0, p = name; ; p++)
743 {
744 if (*p == '-' || ! *p)
745 {
746 if (*name == '*')
747 {
748 if (name + 1 != p)
749 return -1;
750 f[i++] = Qnil;
751 wild_card_found = 1;
752 }
753 else if (isdigit (*name))
754 {
755 f[i++] = make_number (atoi (name));
756 /* Check if all chars in this field is number. */
757 name++;
758 while (isdigit (*name)) name++;
759 if (name != p)
760 return -1;
761 }
762 else if (p == name)
763 f[i++] = null_string;
764 else
765 {
766 f[i++] = intern_downcase (name, p - name);
767 }
768 if (! *p)
769 break;
770 name = p + 1;
771 }
772 }
773 if (! wild_card_found)
774 return -1;
775 if (font_expand_wildcards (f, i) < 0)
776 return -1;
777 if (! NILP (f[XLFD_PIXEL_INDEX]))
778 pixel_size = XINT (f[XLFD_PIXEL_INDEX]);
779 if (! NILP (f[XLFD_POINT_INDEX]))
780 point_size = XINT (f[XLFD_POINT_INDEX]);
781 if (! NILP (f[XLFD_RESY_INDEX]))
782 resy = XINT (f[XLFD_RESY_INDEX]);
783 if (! NILP (f[XLFD_AVGWIDTH_INDEX]))
784 avgwidth = XINT (f[XLFD_AVGWIDTH_INDEX]);
785 if (NILP (f[XLFD_REGISTRY_INDEX]))
786 {
787 if (! NILP (f[XLFD_ENCODING_INDEX]))
788 f[XLFD_REGISTRY_INDEX]
789 = Fintern (concat2 (build_string ("*-"),
790 SYMBOL_NAME (f[XLFD_ENCODING_INDEX])), Qnil);
791 }
792 else
793 {
794 if (! NILP (f[XLFD_ENCODING_INDEX]))
795 f[XLFD_REGISTRY_INDEX]
796 = Fintern (concat2 (SYMBOL_NAME (f[XLFD_REGISTRY_INDEX]),
797 SYMBOL_NAME (f[XLFD_ENCODING_INDEX])), Qnil);
798 }
799 }
800
801 if (! merge || NILP (AREF (font, FONT_FOUNDRY_INDEX)))
802 ASET (font, FONT_FOUNDRY_INDEX, f[XLFD_FOUNDRY_INDEX]);
803 if (! merge || NILP (AREF (font, FONT_FAMILY_INDEX)))
804 ASET (font, FONT_FAMILY_INDEX, f[XLFD_FAMILY_INDEX]);
805 if (! merge || NILP (AREF (font, FONT_ADSTYLE_INDEX)))
806 ASET (font, FONT_ADSTYLE_INDEX, f[XLFD_ADSTYLE_INDEX]);
807 if (! merge || NILP (AREF (font, FONT_REGISTRY_INDEX)))
808 ASET (font, FONT_REGISTRY_INDEX, f[XLFD_REGISTRY_INDEX]);
809
810 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX;
811 j <= XLFD_SWIDTH_INDEX; i++, j++)
812 if (! merge || NILP (AREF (font, i)))
813 {
814 if (! INTEGERP (f[j]))
815 {
816 val = prop_name_to_numeric (i, f[j]);
817 if (INTEGERP (val))
818 f[j] = val;
819 }
820 ASET (font, i, f[j]);
821 }
822
823 if (pixel_size < 0 && FONT_ENTITY_P (font))
824 return -1;
825
826 if (! merge || NILP (AREF (font, FONT_SIZE_INDEX)))
827 {
828 if (pixel_size >= 0)
829 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
830 else if (point_size >= 0)
831 {
832 if (resy > 0)
833 {
834 pixel_size = POINT_TO_PIXEL (point_size, resy);
835 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
836 }
837 else
838 {
839 ASET (font, FONT_SIZE_INDEX, make_float (point_size / 10));
840 }
841 }
842 }
843
844 if (FONT_ENTITY_P (font)
845 && EQ (AREF (font, FONT_TYPE_INDEX), Qx))
846 ASET (font, FONT_EXTRA_INDEX, f[XLFD_RESY_INDEX]);
847
848 return (avgwidth > 0 ? 2 : resy == 0);
849 }
850
851 /* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
852 length), and return the name length. If FONT_SIZE_INDEX of FONT is
853 0, use PIXEL_SIZE instead. */
854
855 int
856 font_unparse_xlfd (font, pixel_size, name, nbytes)
857 Lisp_Object font;
858 int pixel_size;
859 char *name;
860 int nbytes;
861 {
862 char *f[XLFD_REGISTRY_INDEX + 1], *pixel_point;
863 char work[256];
864 Lisp_Object val;
865 int i, j, len = 0;
866
867 xassert (FONTP (font));
868
869 for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
870 i++, j++)
871 {
872 if (i == FONT_ADSTYLE_INDEX)
873 j = XLFD_ADSTYLE_INDEX;
874 else if (i == FONT_REGISTRY_INDEX)
875 j = XLFD_REGISTRY_INDEX;
876 val = AREF (font, i);
877 if (NILP (val))
878 {
879 if (j == XLFD_REGISTRY_INDEX)
880 f[j] = "*-*", len += 4;
881 else
882 f[j] = "*", len += 2;
883 }
884 else
885 {
886 if (SYMBOLP (val))
887 val = SYMBOL_NAME (val);
888 if (j == XLFD_REGISTRY_INDEX
889 && ! strchr ((char *) SDATA (val), '-'))
890 {
891 /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
892 if (SDATA (val)[SBYTES (val) - 1] == '*')
893 {
894 f[j] = alloca (SBYTES (val) + 3);
895 sprintf (f[j], "%s-*", SDATA (val));
896 len += SBYTES (val) + 3;
897 }
898 else
899 {
900 f[j] = alloca (SBYTES (val) + 4);
901 sprintf (f[j], "%s*-*", SDATA (val));
902 len += SBYTES (val) + 4;
903 }
904 }
905 else
906 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
907 }
908 }
909
910 for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
911 i++, j++)
912 {
913 val = AREF (font, i);
914 if (NILP (val))
915 f[j] = "*", len += 2;
916 else
917 {
918 if (INTEGERP (val))
919 val = prop_numeric_to_name (i, XINT (val));
920 if (SYMBOLP (val))
921 val = SYMBOL_NAME (val);
922 xassert (STRINGP (val));
923 f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
924 }
925 }
926
927 val = AREF (font, FONT_SIZE_INDEX);
928 xassert (NUMBERP (val) || NILP (val));
929 if (INTEGERP (val))
930 {
931 i = XINT (val);
932 if (i > 0)
933 len += sprintf (work, "%d", i) + 1;
934 else /* i == 0 */
935 len += sprintf (work, "%d-*", pixel_size) + 1;
936 pixel_point = work;
937 }
938 else if (FLOATP (val))
939 {
940 i = XFLOAT_DATA (val) * 10;
941 len += sprintf (work, "*-%d", i) + 1;
942 pixel_point = work;
943 }
944 else
945 pixel_point = "*-*", len += 4;
946
947 if (FONT_ENTITY_P (font)
948 && EQ (AREF (font, FONT_TYPE_INDEX), Qx))
949 {
950 /* Setup names for RESY-SPACING-AVWIDTH. */
951 val = AREF (font, FONT_EXTRA_INDEX);
952 if (SYMBOLP (val) && ! NILP (val))
953 {
954 val = SYMBOL_NAME (val);
955 f[XLFD_RESY_INDEX] = (char *) SDATA (val), len += SBYTES (val) + 1;
956 }
957 else
958 f[XLFD_RESY_INDEX] = "*-*-*", len += 6;
959 }
960 else
961 f[XLFD_RESY_INDEX] = "*-*-*", len += 6;
962
963 len += 3; /* for "-*" of resx, and terminating '\0'. */
964 if (len >= nbytes)
965 return -1;
966 return sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-*-%s-%s",
967 f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
968 f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
969 f[XLFD_SWIDTH_INDEX],
970 f[XLFD_ADSTYLE_INDEX], pixel_point,
971 f[XLFD_RESY_INDEX], f[XLFD_REGISTRY_INDEX]);
972 }
973
974 /* Parse NAME (null terminated) as Fonconfig's name format and store
975 information in FONT (font-spec or font-entity). See
976 font_parse_name for more detail. */
977
978 int
979 font_parse_fcname (name, font, merge)
980 char *name;
981 Lisp_Object font;
982 int merge;
983 {
984 char *p0, *p1;
985 Lisp_Object family = Qnil;
986 double point_size = 0;
987 int pixel_size = 0;
988 Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
989
990 /* It is assured that (name[0] && name[0] != '-'). */
991 if (name[0] == ':')
992 p0 = name;
993 else
994 {
995 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++);
996 if (isdigit (name[0]) && *p0 != '-')
997 point_size = strtod (name, NULL);
998 else
999 {
1000 family = intern_font_field (name, p0 - name);
1001 if (*p0 == '-')
1002 {
1003 point_size = strtod (p0 + 1, &p1);
1004 if (*p1 && *p1 != ':')
1005 return -1;
1006 p0 = p1;
1007 }
1008 }
1009 if (! merge || NILP (AREF (font, FONT_FAMILY_INDEX)))
1010 ASET (font, FONT_FAMILY_INDEX, family);
1011 }
1012 while (*p0)
1013 {
1014 Lisp_Object key, val;
1015 enum font_property_index prop;
1016
1017 p1 = index (name, '=');
1018 if (! p1)
1019 return -1;
1020 if (memcmp (p0 + 1, "pixelsize=", 10) == 0)
1021 prop = FONT_SIZE_INDEX;
1022 else
1023 {
1024 key = intern_font_field (p0, p1 - p0);
1025 prop = check_font_prop_name (key);
1026 }
1027 p0 = p1 + 1;
1028 for (p1 = p0; *p1 && *p1 != ':'; p1++);
1029 if (prop == FONT_SIZE_INDEX)
1030 {
1031 pixel_size = atoi (p0);
1032 }
1033 else
1034 {
1035 val = intern_font_field (p0, p1 - p0);
1036 if (prop < FONT_EXTRA_INDEX)
1037 {
1038 if (! merge || NILP (AREF (font, prop)))
1039 {
1040 val = font_property_table[prop].validater (prop, val);
1041 if (! EQ (val, Qerror))
1042 ASET (font, prop, val);
1043 }
1044 }
1045 else
1046 {
1047 if (! merge || NILP (Fplist_get (extra, key)))
1048 extra = Fplist_put (extra, key, val);
1049 }
1050 }
1051 p0 = p1;
1052 }
1053 ASET (font, FONT_EXTRA_INDEX, extra);
1054 if (! merge || NILP (AREF (font, FONT_SIZE_INDEX)))
1055 {
1056 if (point_size > 0)
1057 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1058 else if (pixel_size > 0)
1059 ASET (font, FONT_SIZE_INDEX, make_number (pixel_size));
1060 }
1061
1062 return (NILP (AREF (font, FONT_SIZE_INDEX)) ? 1 : 2);
1063 }
1064
1065 /* Store fontconfig's font name of FONT (font-spec or font-entity) in
1066 NAME (NBYTES length), and return the name length. If
1067 FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead. */
1068
1069 int
1070 font_unparse_fcname (font, pixel_size, name, nbytes)
1071 Lisp_Object font;
1072 int pixel_size;
1073 char *name;
1074 int nbytes;
1075 {
1076 Lisp_Object val, size;
1077 int pt = 0;
1078 int i, j, len = 1;
1079 char *p;
1080 Lisp_Object styles[3];
1081 char *style_names[3] = { "weight", "slant", "swidth" };
1082
1083 if (SYMBOLP (AREF (font, FONT_FAMILY_INDEX))
1084 && ! NILP (AREF (font, FONT_FAMILY_INDEX)))
1085 len += SBYTES (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX)));
1086 size = AREF (font, FONT_SIZE_INDEX);
1087 if (INTEGERP (size))
1088 {
1089 if (XINT (size) > 0)
1090 pixel_size = XINT (size);
1091 if (pixel_size > 0)
1092 len += 21; /* for ":pixelsize=NUM" */
1093 }
1094 else if (FLOATP (size))
1095 {
1096 pt = (int) XFLOAT_DATA (size);
1097 if (pt > 0)
1098 len += 11; /* for "-NUM" */
1099 }
1100 if (SYMBOLP (AREF (font, FONT_FOUNDRY_INDEX))
1101 && ! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1102 /* ":foundry=NAME" */
1103 len += 9 + SBYTES (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX)));
1104 for (i = FONT_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX; i++)
1105 {
1106 val = AREF (font, i);
1107 if (INTEGERP (val))
1108 {
1109 val = prop_numeric_to_name (i, XINT (val));
1110 len += (strlen (style_names[i - FONT_WEIGHT_INDEX])
1111 + 2 + SBYTES (SYMBOL_NAME (val))); /* :xxx=NAME */
1112 }
1113 styles[i - FONT_WEIGHT_INDEX] = val;
1114 }
1115 if (len > nbytes)
1116 return -1;
1117 p = name;
1118 if (! NILP (AREF (font, FONT_FAMILY_INDEX)))
1119 p += sprintf(p, "%s",
1120 SDATA (SYMBOL_NAME (AREF (font, FONT_FAMILY_INDEX))));
1121 if (pt > 0)
1122 p += sprintf (p, "-%d", pt);
1123 else if (pixel_size > 0)
1124 p += sprintf (p, ":pixelsize=%d", pixel_size);
1125 if (SYMBOLP (AREF (font, FONT_FOUNDRY_INDEX))
1126 && ! NILP (AREF (font, FONT_FOUNDRY_INDEX)))
1127 p += sprintf (p, ":foundry=%s",
1128 SDATA (SYMBOL_NAME (AREF (font, FONT_FOUNDRY_INDEX))));
1129 for (i = 0; i < 3; i++)
1130 if (! NILP (styles [i]))
1131 p += sprintf (p, ":%s=%s", style_names[i],
1132 SDATA (SYMBOL_NAME (styles [i])));
1133 return (p - name);
1134 }
1135
1136 /* Parse NAME (null terminated) and store information in FONT
1137 (font-spec or font-entity). If NAME is successfully parsed, return
1138 2 (size is specified), 1 (size is not specified), or 0 (size is not
1139 specified but resolution is specified). Otherwise return -1.
1140
1141 If NAME is XLFD and FONT is a font-entity, store
1142 RESY-SPACING-AVWIDTH information as a symbol in FONT_EXTRA_INDEX.
1143
1144 If MERGE is nonzero, set a property of FONT only when it's nil. */
1145
1146 static int
1147 font_parse_name (name, font, merge)
1148 char *name;
1149 Lisp_Object font;
1150 int merge;
1151 {
1152 if (name[0] == '-' || index (name, '*'))
1153 return font_parse_xlfd (name, font, merge);
1154 if (name[0])
1155 return font_parse_fcname (name, font, merge);
1156 return -1;
1157 }
1158
1159 void
1160 font_merge_old_spec (name, family, registry, spec)
1161 Lisp_Object name, family, registry, spec;
1162 {
1163 if (STRINGP (name))
1164 {
1165 if (font_parse_xlfd ((char *) SDATA (name), spec, 1) < 0)
1166 {
1167 Lisp_Object extra = Fcons (Fcons (QCname, name), Qnil);
1168
1169 ASET (spec, FONT_EXTRA_INDEX, extra);
1170 }
1171 }
1172 else
1173 {
1174 if (! NILP (family))
1175 {
1176 int len;
1177 char *p0, *p1;
1178
1179 xassert (STRINGP (family));
1180 len = SBYTES (family);
1181 p0 = (char *) SDATA (family);
1182 p1 = index (p0, '-');
1183 if (p1)
1184 {
1185 if (NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
1186 ASET (spec, FONT_FOUNDRY_INDEX,
1187 intern_downcase (p0, p1 - p0));
1188 if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1189 ASET (spec, FONT_FAMILY_INDEX,
1190 intern_downcase (p1 + 1, len - (p1 + 1 - p0)));
1191 }
1192 else if (NILP (AREF (spec, FONT_FAMILY_INDEX)))
1193 ASET (spec, FONT_FAMILY_INDEX, intern_downcase (p0, len));
1194 }
1195 if (! NILP (registry)
1196 && NILP (AREF (spec, FONT_REGISTRY_INDEX)))
1197 ASET (spec, FONT_REGISTRY_INDEX,
1198 intern_downcase ((char *) SDATA (registry), SBYTES (registry)));
1199 }
1200 }
1201
1202 \f
1203 /* OTF handler */
1204
1205 #ifdef HAVE_LIBOTF
1206 #include <otf.h>
1207
1208 struct otf_list
1209 {
1210 Lisp_Object entity;
1211 OTF *otf;
1212 struct otf_list *next;
1213 };
1214
1215 static struct otf_list *otf_list;
1216
1217 static Lisp_Object
1218 otf_tag_symbol (tag)
1219 OTF_Tag tag;
1220 {
1221 char name[5];
1222
1223 OTF_tag_name (tag, name);
1224 return Fintern (make_unibyte_string (name, 4), Qnil);
1225 }
1226
1227 static OTF *
1228 otf_open (entity, file)
1229 Lisp_Object entity;
1230 char *file;
1231 {
1232 struct otf_list *list = otf_list;
1233
1234 while (list && ! EQ (list->entity, entity))
1235 list = list->next;
1236 if (! list)
1237 {
1238 list = malloc (sizeof (struct otf_list));
1239 list->entity = entity;
1240 list->otf = file ? OTF_open (file) : NULL;
1241 list->next = otf_list;
1242 otf_list = list;
1243 }
1244 return list->otf;
1245 }
1246
1247
1248 /* Return a list describing which scripts/languages FONT supports by
1249 which GSUB/GPOS features of OpenType tables. See the comment of
1250 (sturct font_driver).otf_capability. */
1251
1252 Lisp_Object
1253 font_otf_capability (font)
1254 struct font *font;
1255 {
1256 OTF *otf;
1257 Lisp_Object capability = Fcons (Qnil, Qnil);
1258 int i;
1259
1260 otf = otf_open (font->entity, font->file_name);
1261 if (! otf)
1262 return Qnil;
1263 for (i = 0; i < 2; i++)
1264 {
1265 OTF_GSUB_GPOS *gsub_gpos;
1266 Lisp_Object script_list = Qnil;
1267 int j;
1268
1269 if (OTF_get_features (otf, i == 0) < 0)
1270 continue;
1271 gsub_gpos = i == 0 ? otf->gsub : otf->gpos;
1272 for (j = gsub_gpos->ScriptList.ScriptCount - 1; j >= 0; j--)
1273 {
1274 OTF_Script *script = gsub_gpos->ScriptList.Script + j;
1275 Lisp_Object langsys_list = Qnil;
1276 Lisp_Object script_tag = otf_tag_symbol (script->ScriptTag);
1277 int k;
1278
1279 for (k = script->LangSysCount; k >= 0; k--)
1280 {
1281 OTF_LangSys *langsys;
1282 Lisp_Object feature_list = Qnil;
1283 Lisp_Object langsys_tag;
1284 int l;
1285
1286 if (j == script->LangSysCount)
1287 {
1288 langsys = &script->DefaultLangSys;
1289 langsys_tag = Qnil;
1290 }
1291 else
1292 {
1293 langsys = script->LangSys + k;
1294 langsys_tag
1295 = otf_tag_symbol (script->LangSysRecord[k].LangSysTag);
1296 }
1297 for (l = langsys->FeatureCount -1; l >= 0; l--)
1298 {
1299 OTF_Feature *feature
1300 = gsub_gpos->FeatureList.Feature + langsys->FeatureIndex[l];
1301 Lisp_Object feature_tag
1302 = otf_tag_symbol (feature->FeatureTag);
1303
1304 feature_list = Fcons (feature_tag, feature_list);
1305 }
1306 langsys_list = Fcons (Fcons (langsys_tag, feature_list),
1307 langsys_list);
1308 }
1309 script_list = Fcons (Fcons (script_tag, langsys_list),
1310 script_list);
1311 }
1312
1313 if (i == 0)
1314 XSETCAR (capability, script_list);
1315 else
1316 XSETCDR (capability, script_list);
1317 }
1318
1319 return capability;
1320 }
1321
1322 static int
1323 parse_gsub_gpos_spec (spec, script, langsys, features)
1324 Lisp_Object spec;
1325 char **script, **langsys, **features;
1326 {
1327 Lisp_Object val;
1328 int len;
1329 char *p;
1330 int asterisk;
1331
1332 val = XCAR (spec);
1333 *script = (char *) SDATA (SYMBOL_NAME (val));
1334 spec = XCDR (spec);
1335 val = XCAR (spec);
1336 *langsys = NILP (val) ? NULL : (char *) SDATA (SYMBOL_NAME (val));
1337 spec = XCDR (spec);
1338 len = XINT (Flength (spec));
1339 *features = p = malloc (6 * len);
1340 if (! p)
1341 return -1;
1342
1343 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
1344 {
1345 val = XCAR (spec);
1346 if (SREF (SYMBOL_NAME (val), 0) == '*')
1347 {
1348 asterisk = 1;
1349 p += sprintf (p, ",*");
1350 }
1351 else if (! asterisk)
1352 p += sprintf (p, ",%s", SDATA (SYMBOL_NAME (val)));
1353 else
1354 p += sprintf (p, ",~%s", SDATA (SYMBOL_NAME (val)));
1355 }
1356 return 0;
1357 }
1358
1359 #define DEVICE_DELTA(table, size) \
1360 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1361 ? (table).DeltaValue[(size) >= (table).StartSize] \
1362 : 0)
1363
1364 void
1365 adjust_anchor (struct font *font, OTF_Anchor *anchor,
1366 unsigned code, int size, int *x, int *y)
1367 {
1368 if (anchor->AnchorFormat == 2)
1369 {
1370 int x0, y0;
1371
1372 if (font->driver->anchor_point (font, code, anchor->f.f1.AnchorPoint,
1373 &x0, &y0) >= 0)
1374 *x = x0, *y = y0;
1375 }
1376 else if (anchor->AnchorFormat == 3)
1377 {
1378 if (anchor->f.f2.XDeviceTable.offset)
1379 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size);
1380 if (anchor->f.f2.YDeviceTable.offset)
1381 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size);
1382 }
1383 }
1384
1385
1386 /* Drive FONT's OTF GSUB features according to GSUB_SPEC. See the
1387 comment of (sturct font_driver).otf_gsub. */
1388
1389 int
1390 font_otf_gsub (font, gsub_spec, gstring_in, from, to, gstring_out, idx)
1391 struct font *font;
1392 Lisp_Object gsub_spec;
1393 Lisp_Object gstring_in;
1394 int from, to;
1395 Lisp_Object gstring_out;
1396 int idx;
1397 {
1398 int len;
1399 int i;
1400 OTF *otf;
1401 OTF_GlyphString otf_gstring;
1402 OTF_Glyph *g;
1403 char *script, *langsys, *features;
1404
1405 otf = otf_open (font->entity, font->file_name);
1406 if (! otf)
1407 return 0;
1408 if (OTF_get_table (otf, "head") < 0)
1409 return 0;
1410 if (OTF_check_table (otf, "GSUB") < 0)
1411 return 0;
1412 if (parse_gsub_gpos_spec (gsub_spec, &script, &langsys, &features) < 0)
1413 return 0;
1414 len = to - from;
1415 otf_gstring.size = otf_gstring.used = len;
1416 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
1417 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
1418 for (i = 0; i < len; i++)
1419 {
1420 Lisp_Object g = LGSTRING_GLYPH (gstring_in, from + i);
1421
1422 otf_gstring.glyphs[i].c = XINT (LGLYPH_CHAR (g));
1423 otf_gstring.glyphs[i].glyph_id = XINT (LGLYPH_CODE (g));
1424 }
1425
1426 OTF_drive_gdef (otf, &otf_gstring);
1427 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, features) < 0)
1428 {
1429 free (otf_gstring.glyphs);
1430 return 0;
1431 }
1432 if (ASIZE (gstring_out) < idx + otf_gstring.used)
1433 {
1434 free (otf_gstring.glyphs);
1435 return -1;
1436 }
1437
1438 for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used;)
1439 {
1440 int i0 = g->f.index.from, i1 = g->f.index.to;
1441 Lisp_Object glyph = LGSTRING_GLYPH (gstring_in, from + i0);
1442 Lisp_Object min_idx = AREF (glyph, 0);
1443 Lisp_Object max_idx = AREF (glyph, 1);
1444
1445 if (i0 < i1)
1446 {
1447 int min_idx_i = XINT (min_idx), max_idx_i = XINT (max_idx);
1448
1449 for (i0++; i0 <= i1; i0++)
1450 {
1451 glyph = LGSTRING_GLYPH (gstring_in, from + i0);
1452 if (min_idx_i > XINT (AREF (glyph, 0)))
1453 min_idx_i = XINT (AREF (glyph, 0));
1454 if (max_idx_i < XINT (AREF (glyph, 1)))
1455 max_idx_i = XINT (AREF (glyph, 1));
1456 }
1457 min_idx = make_number (min_idx_i);
1458 max_idx = make_number (max_idx_i);
1459 i0 = g->f.index.from;
1460 }
1461 for (; i < otf_gstring.used && g->f.index.from == i0; i++, g++)
1462 {
1463 glyph = LGSTRING_GLYPH (gstring_out, idx + i);
1464 ASET (glyph, 0, min_idx);
1465 ASET (glyph, 1, max_idx);
1466 LGLYPH_SET_CHAR (glyph, make_number (g->c));
1467 LGLYPH_SET_CODE (glyph, make_number (g->glyph_id));
1468 }
1469 }
1470
1471 free (otf_gstring.glyphs);
1472 return i;
1473 }
1474
1475 /* Drive FONT's OTF GPOS features according to GPOS_SPEC. See the
1476 comment of (sturct font_driver).otf_gpos. */
1477
1478 int
1479 font_otf_gpos (font, gpos_spec, gstring, from, to)
1480 struct font *font;
1481 Lisp_Object gpos_spec;
1482 Lisp_Object gstring;
1483 int from, to;
1484 {
1485 int len;
1486 int i;
1487 OTF *otf;
1488 OTF_GlyphString otf_gstring;
1489 OTF_Glyph *g;
1490 char *script, *langsys, *features;
1491 Lisp_Object glyph;
1492 int u, size;
1493 Lisp_Object base, mark;
1494
1495 otf = otf_open (font->entity, font->file_name);
1496 if (! otf)
1497 return 0;
1498 if (OTF_get_table (otf, "head") < 0)
1499 return 0;
1500 if (OTF_check_table (otf, "GPOS") < 0)
1501 return 0;
1502 if (parse_gsub_gpos_spec (gpos_spec, &script, &langsys, &features) < 0)
1503 return 0;
1504 len = to - from;
1505 otf_gstring.size = otf_gstring.used = len;
1506 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
1507 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
1508 for (i = 0; i < len; i++)
1509 {
1510 glyph = LGSTRING_GLYPH (gstring, from + i);
1511 otf_gstring.glyphs[i].glyph_id = XINT (LGLYPH_CODE (glyph));
1512 }
1513
1514 OTF_drive_gdef (otf, &otf_gstring);
1515
1516 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, features) < 0)
1517 {
1518 free (otf_gstring.glyphs);
1519 return 0;
1520 }
1521
1522 u = otf->head->unitsPerEm;
1523 size = font->pixel_size;
1524 base = mark = Qnil;
1525 for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used; i++, g++)
1526 {
1527 Lisp_Object prev;
1528 int xoff = 0, yoff = 0, width_adjust = 0;
1529
1530 if (! g->glyph_id)
1531 continue;
1532
1533 glyph = LGSTRING_GLYPH (gstring, from + i);
1534 switch (g->positioning_type)
1535 {
1536 case 0:
1537 break;
1538 case 1: case 2:
1539 {
1540 int format = g->f.f1.format;
1541
1542 if (format & OTF_XPlacement)
1543 xoff = g->f.f1.value->XPlacement * size / u;
1544 if (format & OTF_XPlaDevice)
1545 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, size);
1546 if (format & OTF_YPlacement)
1547 yoff = - (g->f.f1.value->YPlacement * size / u);
1548 if (format & OTF_YPlaDevice)
1549 yoff -= DEVICE_DELTA (g->f.f1.value->YPlaDevice, size);
1550 if (format & OTF_XAdvance)
1551 width_adjust += g->f.f1.value->XAdvance * size / u;
1552 if (format & OTF_XAdvDevice)
1553 width_adjust += DEVICE_DELTA (g->f.f1.value->XAdvDevice, size);
1554 }
1555 break;
1556 case 3:
1557 /* Not yet supported. */
1558 break;
1559 case 4: case 5:
1560 if (NILP (base))
1561 break;
1562 prev = base;
1563 goto label_adjust_anchor;
1564 default: /* i.e. case 6 */
1565 if (NILP (mark))
1566 break;
1567 prev = mark;
1568
1569 label_adjust_anchor:
1570 {
1571 int base_x, base_y, mark_x, mark_y, width;
1572 unsigned code;
1573
1574 base_x = g->f.f4.base_anchor->XCoordinate * size / u;
1575 base_y = g->f.f4.base_anchor->YCoordinate * size / u;
1576 mark_x = g->f.f4.mark_anchor->XCoordinate * size / u;
1577 mark_y = g->f.f4.mark_anchor->YCoordinate * size / u;
1578
1579 code = XINT (LGLYPH_CODE (prev));
1580 if (g->f.f4.base_anchor->AnchorFormat != 1)
1581 adjust_anchor (font, g->f.f4.base_anchor,
1582 code, size, &base_x, &base_y);
1583 if (g->f.f4.mark_anchor->AnchorFormat != 1)
1584 adjust_anchor (font, g->f.f4.mark_anchor,
1585 code, size, &mark_x, &mark_y);
1586
1587 if (NILP (LGLYPH_WIDTH (prev)))
1588 {
1589 width = font->driver->text_extents (font, &code, 1, NULL);
1590 LGLYPH_SET_WIDTH (prev, make_number (width));
1591 }
1592 xoff = XINT (LGLYPH_XOFF (prev)) + (base_x - width) - mark_x;
1593 yoff = XINT (LGLYPH_YOFF (prev)) + mark_y - base_y;
1594 }
1595 }
1596 if (g->GlyphClass == OTF_GlyphClass0)
1597 base = mark = glyph;
1598 else if (g->GlyphClass == OTF_GlyphClassMark)
1599 mark = glyph;
1600 else
1601 base = glyph;
1602
1603 LGLYPH_SET_XOFF (glyph, make_number (xoff));
1604 LGLYPH_SET_YOFF (glyph, make_number (yoff));
1605 LGLYPH_SET_WADJUST (glyph, make_number (width_adjust));
1606 }
1607
1608 free (otf_gstring.glyphs);
1609 return 0;
1610 }
1611
1612 #endif /* HAVE_LIBOTF */
1613
1614 \f
1615 /* glyph-string handler */
1616
1617 /* GSTRING is a vector of this form:
1618 [ [FONT-OBJECT LBEARING RBEARING WITH ASCENT DESCENT] GLYPH ... ]
1619 and GLYPH is a vector of this form:
1620 [ FROM-IDX TO-IDX C CODE X-OFF Y-OFF WIDTH WADJUST ]
1621 where
1622 FROM-IDX and TO-IDX are used internally and should not be touched.
1623 C is a character of the glyph.
1624 CODE is a glyph-code of C in FONT-OBJECT.
1625 X-OFF and Y-OFF are offests to the base position for the glyph.
1626 WIDTH is a normal width of the glyph.
1627 WADJUST is an adjustment to the normal width of the glyph. */
1628
1629 struct font *
1630 font_prepare_composition (cmp)
1631 struct composition *cmp;
1632 {
1633 Lisp_Object gstring
1634 = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
1635 cmp->hash_index * 2);
1636 struct font *font = XSAVE_VALUE (LGSTRING_FONT (gstring))->pointer;
1637 int len = LGSTRING_LENGTH (gstring);
1638 int i;
1639
1640 cmp->font = font;
1641 cmp->lbearing = cmp->rbearing = cmp->pixel_width = 0;
1642 cmp->ascent = font->ascent;
1643 cmp->descent = font->descent;
1644
1645 for (i = 0; i < len; i++)
1646 {
1647 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
1648 unsigned code = XINT (LGLYPH_CODE (g));
1649 struct font_metrics metrics;
1650
1651 font->driver->text_extents (font, &code, 1, &metrics);
1652 LGLYPH_SET_WIDTH (g, make_number (metrics.width));
1653 metrics.lbearing += XINT (LGLYPH_XOFF (g));
1654 metrics.rbearing += XINT (LGLYPH_XOFF (g));
1655 metrics.ascent += XINT (LGLYPH_YOFF (g));
1656 metrics.descent += XINT (LGLYPH_YOFF (g));
1657
1658 if (cmp->lbearing > cmp->pixel_width + metrics.lbearing)
1659 cmp->lbearing = cmp->pixel_width + metrics.lbearing;
1660 if (cmp->rbearing < cmp->pixel_width + metrics.rbearing)
1661 cmp->rbearing = cmp->pixel_width + metrics.rbearing;
1662 if (cmp->ascent < metrics.ascent)
1663 cmp->ascent = metrics.ascent;
1664 if (cmp->descent < metrics.descent)
1665 cmp->descent = metrics.descent;
1666 cmp->pixel_width += metrics.width + XINT (LGLYPH_WADJUST (g));
1667 }
1668 LGSTRING_SET_LBEARING (gstring, make_number (cmp->lbearing));
1669 LGSTRING_SET_RBEARING (gstring, make_number (cmp->rbearing));
1670 LGSTRING_SET_WIDTH (gstring, make_number (cmp->pixel_width));
1671 LGSTRING_SET_ASCENT (gstring, make_number (cmp->ascent));
1672 LGSTRING_SET_DESCENT (gstring, make_number (cmp->descent));
1673
1674 return font;
1675 }
1676
1677 int
1678 font_gstring_produce (old, from, to, new, idx, code, n)
1679 Lisp_Object old;
1680 int from, to;
1681 Lisp_Object new;
1682 int idx;
1683 unsigned *code;
1684 int n;
1685 {
1686 Lisp_Object min_idx, max_idx;
1687 int i;
1688
1689 if (idx + n > ASIZE (new))
1690 return -1;
1691 if (from == to)
1692 {
1693 if (from == 0)
1694 {
1695 min_idx = make_number (0);
1696 max_idx = make_number (1);
1697 }
1698 else
1699 {
1700 min_idx = AREF (AREF (old, from - 1), 0);
1701 max_idx = AREF (AREF (old, from - 1), 1);
1702 }
1703 }
1704 else if (from + 1 == to)
1705 {
1706 min_idx = AREF (AREF (old, from), 0);
1707 max_idx = AREF (AREF (old, from), 1);
1708 }
1709 else
1710 {
1711 int min_idx_i = XINT (AREF (AREF (old, from), 0));
1712 int max_idx_i = XINT (AREF (AREF (old, from), 1));
1713
1714 for (i = from + 1; i < to; i++)
1715 {
1716 if (min_idx_i > XINT (AREF (AREF (old, i), 0)))
1717 min_idx_i = XINT (AREF (AREF (old, i), 0));
1718 if (max_idx_i < XINT (AREF (AREF (old, i), 1)))
1719 max_idx_i = XINT (AREF (AREF (old, i), 1));
1720 }
1721 min_idx = make_number (min_idx_i);
1722 max_idx = make_number (max_idx_i);
1723 }
1724
1725 for (i = 0; i < n; i++)
1726 {
1727 ASET (AREF (new, idx + i), 0, min_idx);
1728 ASET (AREF (new, idx + i), 1, max_idx);
1729 ASET (AREF (new, idx + i), 2, make_number (code[i]));
1730 }
1731
1732 return 0;
1733 }
1734 \f
1735 /* Font sorting */
1736
1737 static unsigned font_score P_ ((Lisp_Object, Lisp_Object));
1738 static int font_compare P_ ((const void *, const void *));
1739 static Lisp_Object font_sort_entites P_ ((Lisp_Object, Lisp_Object,
1740 Lisp_Object, Lisp_Object));
1741
1742 /* We sort fonts by scoring each of them against a specified
1743 font-spec. The score value is 32 bit (`unsigned'), and the smaller
1744 the value is, the closer the font is to the font-spec.
1745
1746 Each 1-bit in the highest 4 bits of the score is used for atomic
1747 properties FOUNDRY, FAMILY, ADSTYLE, and REGISTRY.
1748
1749 Each 7-bit in the lowest 28 bits are used for numeric properties
1750 WEIGHT, SLANT, WIDTH, and SIZE. */
1751
1752 /* How many bits to shift to store the difference value of each font
1753 property in a score. */
1754 static int sort_shift_bits[FONT_SIZE_INDEX + 1];
1755
1756 /* Score font-entity ENTITY against font-spec SPEC. The return value
1757 indicates how different ENTITY is compared with SPEC. */
1758
1759 static unsigned
1760 font_score (entity, spec)
1761 Lisp_Object entity, spec;
1762 {
1763 unsigned score = 0;
1764 int i;
1765 /* Score atomic fields. Maximum difference is 1. */
1766 for (i = FONT_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX; i++)
1767 {
1768 Lisp_Object val = AREF (spec, i);
1769
1770 if (! NILP (val)
1771 && ! EQ (val, AREF (entity, i)))
1772 score |= 1 << sort_shift_bits[i];
1773 }
1774
1775 /* Score numeric fields. Maximum difference is 127. */
1776 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
1777 {
1778 Lisp_Object spec_val = AREF (spec, i);
1779 Lisp_Object entity_val = AREF (entity, i);
1780
1781 if (! NILP (spec_val) && ! EQ (spec_val, entity_val))
1782 {
1783 if (! INTEGERP (entity_val))
1784 score |= 127 << sort_shift_bits[i];
1785 else if (i < FONT_SIZE_INDEX
1786 || XINT (entity_val) != 0)
1787 {
1788 int diff = XINT (entity_val) - XINT (spec_val);
1789
1790 if (diff < 0)
1791 diff = - diff;
1792 score |= min (diff, 127) << sort_shift_bits[i];
1793 }
1794 }
1795 }
1796
1797 return score;
1798 }
1799
1800
1801 /* The comparison function for qsort. */
1802
1803 static int
1804 font_compare (d1, d2)
1805 const void *d1, *d2;
1806 {
1807 return (*(unsigned *) d1 < *(unsigned *) d2
1808 ? -1 : *(unsigned *) d1 > *(unsigned *) d2);
1809 }
1810
1811
1812 /* The structure for elements being sorted by qsort. */
1813 struct font_sort_data
1814 {
1815 unsigned score;
1816 Lisp_Object entity;
1817 };
1818
1819
1820 /* Sort font-entities in vector VEC by closeness to font-spec PREFER.
1821 If PREFER specifies a point-size, calculate the corresponding
1822 pixel-size from the Y-resolution of FRAME before sorting. If SPEC
1823 is not nil, it is a font-spec to get the font-entities in VEC. */
1824
1825 static Lisp_Object
1826 font_sort_entites (vec, prefer, frame, spec)
1827 Lisp_Object vec, prefer, frame, spec;
1828 {
1829 Lisp_Object size;
1830 int len, i;
1831 struct font_sort_data *data;
1832 int prefer_is_copy = 0;
1833 USE_SAFE_ALLOCA;
1834
1835 len = ASIZE (vec);
1836 if (len <= 1)
1837 return vec;
1838
1839 size = AREF (spec, FONT_SIZE_INDEX);
1840 if (FLOATP (size))
1841 {
1842 double point_size = XFLOAT_DATA (size) * 10;
1843 int pixel_size = POINT_TO_PIXEL (point_size, XFRAME (frame)->resy);
1844
1845 prefer = Fcopy_sequence (prefer);
1846 ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
1847 prefer_is_copy = 1;
1848 }
1849
1850 if (! NILP (spec))
1851 {
1852 /* As it is assured that all fonts in VEC match with SPEC, we
1853 should ignore properties specified in SPEC. So, set the
1854 corresponding properties in PREFER nil. */
1855 for (i = FONT_WEIGHT_INDEX; i <= FONT_SIZE_INDEX; i++)
1856 if (! NILP (AREF (spec, i)) && ! NILP (AREF (prefer, i)))
1857 break;
1858 if (i <= FONT_SIZE_INDEX)
1859 {
1860 if (! prefer_is_copy)
1861 prefer = Fcopy_sequence (prefer);
1862 for (; i <= FONT_SIZE_INDEX; i++)
1863 if (! NILP (AREF (spec, i)) && ! NILP (AREF (prefer, i)))
1864 ASET (prefer, i, Qnil);
1865 }
1866 }
1867
1868 /* Scoring and sorting. */
1869 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len);
1870 for (i = 0; i < len; i++)
1871 {
1872 data[i].entity = AREF (vec, i);
1873 data[i].score = font_score (data[i].entity, prefer);
1874 }
1875 qsort (data, len, sizeof *data, font_compare);
1876 for (i = 0; i < len; i++)
1877 ASET (vec, i, data[i].entity);
1878 SAFE_FREE ();
1879
1880 return vec;
1881 }
1882
1883 \f
1884 /* API of Font Service Layer. */
1885
1886 void
1887 font_update_sort_order (order)
1888 int *order;
1889 {
1890 int i, shift_bits = 21;
1891
1892 for (i = 0; i < 4; i++, shift_bits -= 7)
1893 {
1894 int xlfd_idx = order[i];
1895
1896 if (xlfd_idx == XLFD_WEIGHT_INDEX)
1897 sort_shift_bits[FONT_WEIGHT_INDEX] = shift_bits;
1898 else if (xlfd_idx == XLFD_SLANT_INDEX)
1899 sort_shift_bits[FONT_SLANT_INDEX] = shift_bits;
1900 else if (xlfd_idx == XLFD_SWIDTH_INDEX)
1901 sort_shift_bits[FONT_WIDTH_INDEX] = shift_bits;
1902 else
1903 sort_shift_bits[FONT_SIZE_INDEX] = shift_bits;
1904 }
1905 }
1906
1907 Lisp_Object
1908 font_symbolic_weight (font)
1909 Lisp_Object font;
1910 {
1911 Lisp_Object weight = AREF (font, FONT_WEIGHT_INDEX);
1912
1913 if (INTEGERP (weight))
1914 weight = prop_numeric_to_name (FONT_WEIGHT_INDEX, XINT (weight));
1915 return weight;
1916 }
1917
1918 Lisp_Object
1919 font_symbolic_slant (font)
1920 Lisp_Object font;
1921 {
1922 Lisp_Object slant = AREF (font, FONT_SLANT_INDEX);
1923
1924 if (INTEGERP (slant))
1925 slant = prop_numeric_to_name (FONT_SLANT_INDEX, XINT (slant));
1926 return slant;
1927 }
1928
1929 Lisp_Object
1930 font_symbolic_width (font)
1931 Lisp_Object font;
1932 {
1933 Lisp_Object width = AREF (font, FONT_WIDTH_INDEX);
1934
1935 if (INTEGERP (width))
1936 width = prop_numeric_to_name (FONT_WIDTH_INDEX, XINT (width));
1937 return width;
1938 }
1939
1940 int
1941 font_match_p (spec, entity)
1942 Lisp_Object spec, entity;
1943 {
1944 int i;
1945
1946 for (i = FONT_FOUNDRY_INDEX; i < FONT_SIZE_INDEX; i++)
1947 if (! NILP (AREF (spec, i))
1948 && ! EQ (AREF (spec, i), AREF (entity, i)))
1949 return 0;
1950 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX))
1951 && XINT (AREF (entity, FONT_SIZE_INDEX)) > 0
1952 && (XINT (AREF (spec, FONT_SIZE_INDEX))
1953 != XINT (AREF (entity, FONT_SIZE_INDEX))))
1954 return 0;
1955 return 1;
1956 }
1957
1958 Lisp_Object
1959 font_find_object (font)
1960 struct font *font;
1961 {
1962 Lisp_Object tail, elt;
1963
1964 for (tail = AREF (font->entity, FONT_OBJLIST_INDEX); CONSP (tail);
1965 tail = XCDR (tail))
1966 {
1967 elt = XCAR (tail);
1968 if (font == XSAVE_VALUE (elt)->pointer
1969 && XSAVE_VALUE (elt)->integer > 0)
1970 return elt;
1971 }
1972 abort ();
1973 return Qnil;
1974 }
1975
1976 static Lisp_Object scratch_font_spec, scratch_font_prefer;
1977
1978 /* Return a vector of font-entities matching with SPEC on frame F. */
1979
1980 static Lisp_Object
1981 font_list_entities (frame, spec)
1982 Lisp_Object frame, spec;
1983 {
1984 FRAME_PTR f = XFRAME (frame);
1985 struct font_driver_list *driver_list = f->font_driver_list;
1986 Lisp_Object ftype, family, size, alternate_familes;
1987 Lisp_Object *vec = alloca (sizeof (Lisp_Object) * num_font_drivers);
1988 int i;
1989
1990 if (! vec)
1991 return null_vector;
1992
1993 family = AREF (spec, FONT_FAMILY_INDEX);
1994 if (NILP (family))
1995 alternate_familes = Qnil;
1996 else
1997 {
1998 if (NILP (font_family_alist)
1999 && !NILP (Vface_alternative_font_family_alist))
2000 build_font_family_alist ();
2001 alternate_familes = assq_no_quit (family, font_family_alist);
2002 if (! NILP (alternate_familes))
2003 alternate_familes = XCDR (alternate_familes);
2004 }
2005 size = AREF (spec, FONT_SIZE_INDEX);
2006 if (FLOATP (size))
2007 ASET (spec, FONT_SIZE_INDEX, POINT_TO_PIXEL (size * 10, f->resy));
2008
2009 xassert (ASIZE (spec) == FONT_SPEC_MAX);
2010 ftype = AREF (spec, FONT_TYPE_INDEX);
2011
2012 for (i = 0; driver_list; driver_list = driver_list->next)
2013 if (NILP (ftype) || EQ (driver_list->driver->type, ftype))
2014 {
2015 Lisp_Object cache = driver_list->driver->get_cache (frame);
2016 Lisp_Object tail = alternate_familes;
2017 Lisp_Object val;
2018
2019 xassert (CONSP (cache));
2020 ASET (spec, FONT_TYPE_INDEX, driver_list->driver->type);
2021 ASET (spec, FONT_FAMILY_INDEX, family);
2022
2023 while (1)
2024 {
2025 val = assoc_no_quit (spec, XCDR (cache));
2026 if (CONSP (val))
2027 val = XCDR (val);
2028 else
2029 {
2030 val = driver_list->driver->list (frame, spec);
2031 if (VECTORP (val))
2032 XSETCDR (cache, Fcons (Fcons (Fcopy_sequence (spec), val),
2033 XCDR (cache)));
2034 }
2035 if (VECTORP (val) && ASIZE (val) > 0)
2036 {
2037 vec[i++] = val;
2038 break;
2039 }
2040 if (NILP (tail))
2041 break;
2042 ASET (spec, FONT_FAMILY_INDEX, XCAR (tail));
2043 tail = XCDR (tail);
2044 }
2045 }
2046 ASET (spec, FONT_TYPE_INDEX, ftype);
2047 ASET (spec, FONT_FAMILY_INDEX, family);
2048 ASET (spec, FONT_SIZE_INDEX, size);
2049 return (i > 0 ? Fvconcat (i, vec) : null_vector);
2050 }
2051
2052 static int num_fonts;
2053
2054 static Lisp_Object
2055 font_open_entity (f, entity, pixel_size)
2056 FRAME_PTR f;
2057 Lisp_Object entity;
2058 int pixel_size;
2059 {
2060 struct font_driver_list *driver_list;
2061 Lisp_Object objlist, size, val;
2062 struct font *font;
2063
2064 size = AREF (entity, FONT_SIZE_INDEX);
2065 xassert (NATNUMP (size));
2066 if (XINT (size) != 0)
2067 pixel_size = XINT (size);
2068
2069 for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
2070 objlist = XCDR (objlist))
2071 {
2072 font = XSAVE_VALUE (XCAR (objlist))->pointer;
2073 if (font->pixel_size == pixel_size)
2074 {
2075 XSAVE_VALUE (XCAR (objlist))->integer++;
2076 return XCAR (objlist);
2077 }
2078 }
2079
2080 xassert (FONT_ENTITY_P (entity));
2081 val = AREF (entity, FONT_TYPE_INDEX);
2082 for (driver_list = f->font_driver_list;
2083 driver_list && ! EQ (driver_list->driver->type, val);
2084 driver_list = driver_list->next);
2085 if (! driver_list)
2086 return Qnil;
2087
2088 font = driver_list->driver->open (f, entity, pixel_size);
2089 if (! font)
2090 return Qnil;
2091 val = make_save_value (font, 1);
2092 ASET (entity, FONT_OBJLIST_INDEX,
2093 Fcons (val, AREF (entity, FONT_OBJLIST_INDEX)));
2094 num_fonts++;
2095 return val;
2096 }
2097
2098 void
2099 font_close_object (f, font_object)
2100 FRAME_PTR f;
2101 Lisp_Object font_object;
2102 {
2103 struct font *font;
2104 Lisp_Object objlist = AREF (font->entity, FONT_OBJLIST_INDEX);
2105 Lisp_Object tail, prev = Qnil;
2106
2107 for (prev = Qnil, tail = objlist; CONSP (tail);
2108 prev = tail, tail = XCDR (tail))
2109 if (EQ (font_object, XCAR (tail)))
2110 {
2111 struct Lisp_Save_Value *p = XSAVE_VALUE (font_object);
2112
2113 xassert (p->integer > 0);
2114 p->integer--;
2115 if (p->integer == 0)
2116 {
2117 if (font->driver->close)
2118 font->driver->close (f, p->pointer);
2119 p->pointer = NULL;
2120 if (NILP (prev))
2121 ASET (font->entity, FONT_OBJLIST_INDEX, XCDR (objlist));
2122 else
2123 XSETCDR (prev, XCDR (objlist));
2124 }
2125 break;
2126 }
2127 }
2128
2129 int
2130 font_has_char (f, font_entity, c)
2131 FRAME_PTR f;
2132 Lisp_Object font_entity;
2133 int c;
2134 {
2135 Lisp_Object type = AREF (font_entity, FONT_TYPE_INDEX);
2136 struct font_driver_list *driver_list;
2137
2138 for (driver_list = f->font_driver_list;
2139 driver_list && ! EQ (driver_list->driver->type, type);
2140 driver_list = driver_list->next);
2141 if (! driver_list)
2142 return -1;
2143 return driver_list->driver->has_char (font_entity, c);
2144 }
2145
2146 unsigned
2147 font_encode_char (font_object, c)
2148 Lisp_Object font_object;
2149 int c;
2150 {
2151 struct font *font = XSAVE_VALUE (font_object)->pointer;
2152
2153 return font->driver->encode_char (font, c);
2154 }
2155
2156 Lisp_Object
2157 font_get_name (font_object)
2158 Lisp_Object font_object;
2159 {
2160 struct font *font = XSAVE_VALUE (font_object)->pointer;
2161 char *name = (font->font.full_name ? font->font.full_name
2162 : font->font.name ? font->font.name
2163 : NULL);
2164
2165 return (name ? make_unibyte_string (name, strlen (name)) : null_string);
2166 }
2167
2168 Lisp_Object
2169 font_get_spec (font_object)
2170 Lisp_Object font_object;
2171 {
2172 struct font *font = XSAVE_VALUE (font_object)->pointer;
2173 Lisp_Object spec = Ffont_spec (0, NULL);
2174 int i;
2175
2176 for (i = 0; i < FONT_SIZE_INDEX; i++)
2177 ASET (spec, i, AREF (font->entity, i));
2178 ASET (spec, FONT_SIZE_INDEX, make_number (font->pixel_size));
2179 return spec;
2180 }
2181
2182 Lisp_Object
2183 font_get_frame (font)
2184 Lisp_Object font;
2185 {
2186 if (FONT_OBJECT_P (font))
2187 font = ((struct font *) XSAVE_VALUE (font)->pointer)->entity;
2188 xassert (FONT_ENTITY_P (font));
2189 return AREF (font, FONT_FRAME_INDEX);
2190 }
2191
2192 /* Find a font entity best matching with LFACE. If SPEC is non-nil,
2193 the font must exactly match with it. */
2194
2195 Lisp_Object
2196 font_find_for_lface (f, lface, spec)
2197 FRAME_PTR f;
2198 Lisp_Object *lface;
2199 Lisp_Object spec;
2200 {
2201 Lisp_Object frame, entities;
2202 int i;
2203
2204 if (NILP (spec))
2205 for (i = 0; i < FONT_SPEC_MAX; i++)
2206 ASET (scratch_font_spec, i, Qnil);
2207 else
2208 for (i = 0; i < FONT_SPEC_MAX; i++)
2209 ASET (scratch_font_spec, i, AREF (spec, i));
2210
2211 if (NILP (AREF (scratch_font_spec, FONT_FAMILY_INDEX))
2212 && ! NILP (lface[LFACE_FAMILY_INDEX]))
2213 font_merge_old_spec (Qnil, lface[LFACE_FAMILY_INDEX], Qnil,
2214 scratch_font_spec);
2215 if (NILP (AREF (scratch_font_spec, FONT_REGISTRY_INDEX)))
2216 ASET (scratch_font_spec, FONT_REGISTRY_INDEX, intern ("iso8859-1"));
2217
2218 XSETFRAME (frame, f);
2219 entities = font_list_entities (frame, scratch_font_spec);
2220 while (ASIZE (entities) == 0)
2221 {
2222 if (! NILP (AREF (scratch_font_spec, FONT_FOUNDRY_INDEX))
2223 && (NILP (spec) || NILP (AREF (spec, FONT_FOUNDRY_INDEX))))
2224 {
2225 ASET (scratch_font_spec, FONT_FOUNDRY_INDEX, Qnil);
2226 entities = font_list_entities (frame, scratch_font_spec);
2227 }
2228 else if (! NILP (AREF (scratch_font_spec, FONT_FAMILY_INDEX))
2229 && (NILP (spec) || NILP (AREF (spec, FONT_FAMILY_INDEX))))
2230 {
2231 ASET (scratch_font_spec, FONT_FAMILY_INDEX, Qnil);
2232 entities = font_list_entities (frame, scratch_font_spec);
2233 }
2234 else
2235 return Qnil;
2236 }
2237
2238 if (ASIZE (entities) > 1)
2239 {
2240 Lisp_Object prefer = scratch_font_prefer, val;
2241 int size;
2242
2243 ASET (prefer, FONT_WEIGHT_INDEX,
2244 font_prop_validate_style (FONT_WEIGHT_INDEX,
2245 lface[LFACE_WEIGHT_INDEX]));
2246 ASET (prefer, FONT_SLANT_INDEX,
2247 font_prop_validate_style (FONT_SLANT_INDEX,
2248 lface[LFACE_SLANT_INDEX]));
2249 ASET (prefer, FONT_WIDTH_INDEX,
2250 font_prop_validate_style (FONT_WIDTH_INDEX,
2251 lface[LFACE_SWIDTH_INDEX]));
2252 val = lface[LFACE_HEIGHT_INDEX];
2253 size = POINT_TO_PIXEL (XINT (val), f->resy);
2254 ASET (prefer, FONT_SIZE_INDEX, make_number (size));
2255
2256 font_sort_entites (entities, prefer, frame, spec);
2257 }
2258
2259 return AREF (entities, 0);
2260 }
2261
2262 Lisp_Object
2263 font_open_for_lface (f, lface, entity)
2264 FRAME_PTR f;
2265 Lisp_Object *lface;
2266 Lisp_Object entity;
2267 {
2268 int pt = XINT (lface[LFACE_HEIGHT_INDEX]);
2269 int size = POINT_TO_PIXEL (pt, f->resy);
2270
2271 return font_open_entity (f, entity, size);
2272 }
2273
2274 void
2275 font_load_for_face (f, face)
2276 FRAME_PTR f;
2277 struct face *face;
2278 {
2279 Lisp_Object font_object = face->lface[LFACE_FONT_INDEX];
2280
2281 if (NILP (font_object))
2282 {
2283 Lisp_Object entity = font_find_for_lface (f, face->lface, Qnil);
2284
2285 if (! NILP (entity))
2286 font_object = font_open_for_lface (f, face->lface, entity);
2287 }
2288
2289 if (! NILP (font_object))
2290 {
2291 struct font *font = XSAVE_VALUE (font_object)->pointer;
2292
2293 face->font = font->font.font;
2294 face->font_info = (struct font_info *) font;
2295 face->font_info_id = 0;
2296 face->font_name = font->font.full_name;
2297 }
2298 else
2299 {
2300 face->font = NULL;
2301 face->font_info = NULL;
2302 face->font_info_id = -1;
2303 face->font_name = NULL;
2304 add_to_log ("Unable to load font for a face%s", null_string, Qnil);
2305 }
2306 }
2307
2308 void
2309 font_prepare_for_face (f, face)
2310 FRAME_PTR f;
2311 struct face *face;
2312 {
2313 struct font *font = (struct font *) face->font_info;
2314
2315 if (font->driver->prepare_face)
2316 font->driver->prepare_face (f, face);
2317 }
2318
2319 void
2320 font_done_for_face (f, face)
2321 FRAME_PTR f;
2322 struct face *face;
2323 {
2324 struct font *font = (struct font *) face->font_info;
2325
2326 if (font->driver->done_face)
2327 font->driver->done_face (f, face);
2328 face->extra = NULL;
2329 }
2330
2331 Lisp_Object
2332 font_open_by_name (f, name)
2333 FRAME_PTR f;
2334 char *name;
2335 {
2336 Lisp_Object args[2];
2337 Lisp_Object spec, prefer, size, entities;
2338 Lisp_Object frame;
2339 struct font_driver_list *dlist;
2340 int i;
2341 int pixel_size;
2342
2343 XSETFRAME (frame, f);
2344
2345 args[0] = QCname;
2346 args[1] = make_unibyte_string (name, strlen (name));
2347 spec = Ffont_spec (2, args);
2348 prefer = scratch_font_prefer;
2349 for (i = FONT_WEIGHT_INDEX; i < FONT_SIZE_INDEX; i++)
2350 if (NILP (AREF (spec, i)))
2351 ASET (prefer, i, make_number (100));
2352 size = AREF (spec, FONT_SIZE_INDEX);
2353 if (NILP (size))
2354 pixel_size = 0;
2355 else if (INTEGERP (size))
2356 pixel_size = XINT (size);
2357 else /* FLOATP (size) */
2358 {
2359 double pt = XFLOAT_DATA (size) * 10;
2360
2361 pixel_size = POINT_TO_PIXEL (pt, f->resy);
2362 size = make_number (pixel_size);
2363 ASET (spec, FONT_SIZE_INDEX, size);
2364 }
2365 if (pixel_size == 0)
2366 {
2367 pixel_size = POINT_TO_PIXEL (120.0, f->resy);
2368 size = make_number (pixel_size);
2369 }
2370 ASET (prefer, FONT_SIZE_INDEX, size);
2371
2372 entities = Flist_fonts (spec, frame, make_number (1), prefer);
2373 return (NILP (entities)
2374 ? Qnil
2375 : font_open_entity (f, XCAR (entities), pixel_size));
2376 }
2377
2378
2379 /* Register font-driver DRIVER. This function is used in two ways.
2380
2381 The first is with frame F non-NULL. In this case, DRIVER is
2382 registered to be used for drawing characters on F. All frame
2383 creaters (e.g. Fx_create_frame) must call this function at least
2384 once with an available font-driver.
2385
2386 The second is with frame F NULL. In this case, DRIVER is globally
2387 registered in the variable `font_driver_list'. All font-driver
2388 implementations must call this function in its syms_of_XXXX
2389 (e.g. syms_of_xfont). */
2390
2391 void
2392 register_font_driver (driver, f)
2393 struct font_driver *driver;
2394 FRAME_PTR f;
2395 {
2396 struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
2397 struct font_driver_list *prev, *list;
2398
2399 if (f && ! driver->draw)
2400 error ("Unsable font driver for a frame: %s",
2401 SDATA (SYMBOL_NAME (driver->type)));
2402
2403 for (prev = NULL, list = root; list; prev = list, list = list->next)
2404 if (list->driver->type == driver->type)
2405 error ("Duplicated font driver: %s", SDATA (SYMBOL_NAME (driver->type)));
2406
2407 list = malloc (sizeof (struct font_driver_list));
2408 list->driver = driver;
2409 list->next = NULL;
2410 if (prev)
2411 prev->next = list;
2412 else if (f)
2413 f->font_driver_list = list;
2414 else
2415 font_driver_list = list;
2416 num_font_drivers++;
2417 }
2418
2419 /* Free font-driver list on frame F. It doesn't free font-drivers
2420 themselves. */
2421
2422 void
2423 free_font_driver_list (f)
2424 FRAME_PTR f;
2425 {
2426 while (f->font_driver_list)
2427 {
2428 struct font_driver_list *next = f->font_driver_list->next;
2429
2430 free (f->font_driver_list);
2431 f->font_driver_list = next;
2432 }
2433 }
2434
2435 \f
2436 /* Lisp API */
2437
2438 DEFUN ("fontp", Ffontp, Sfontp, 1, 1, 0,
2439 doc: /* Return t if object is a font-spec or font-entity. */)
2440 (object)
2441 Lisp_Object object;
2442 {
2443 return (FONTP (object) ? Qt : Qnil);
2444 }
2445
2446 DEFUN ("font-spec", Ffont_spec, Sfont_spec, 0, MANY, 0,
2447 doc: /* Return a newly created font-spec with specified arguments as properties.
2448 usage: (font-spec &rest properties) */)
2449 (nargs, args)
2450 int nargs;
2451 Lisp_Object *args;
2452 {
2453 Lisp_Object spec = Fmake_vector (make_number (FONT_SPEC_MAX), Qnil);
2454 Lisp_Object extra = Qnil;
2455 int i;
2456
2457 for (i = 0; i < nargs; i += 2)
2458 {
2459 enum font_property_index prop;
2460 Lisp_Object key = args[i], val = args[i + 1];
2461
2462 prop = check_font_prop_name (key);
2463 if (prop < FONT_EXTRA_INDEX)
2464 ASET (spec, prop, (font_property_table[prop].validater) (prop, val));
2465 else
2466 {
2467 if (EQ (key, QCname))
2468 font_parse_name ((char *) SDATA (val), spec, 0);
2469 extra = Fcons (Fcons (key, val), extra);
2470 }
2471 }
2472 ASET (spec, FONT_EXTRA_INDEX, extra);
2473 return spec;
2474 }
2475
2476
2477 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
2478 doc: /* Return the value of FONT's PROP property.
2479 FONT may be a font-spec or font-entity.
2480 If FONT is font-entity and PROP is :extra, always nil is returned. */)
2481 (font, prop)
2482 Lisp_Object font, prop;
2483 {
2484 enum font_property_index idx;
2485
2486 CHECK_FONT (font);
2487 idx = check_font_prop_name (prop);
2488 if (idx < FONT_EXTRA_INDEX)
2489 return AREF (font, idx);
2490 if (FONT_ENTITY_P (font))
2491 return Qnil;
2492 return Fcdr (Fassoc (AREF (font, FONT_EXTRA_INDEX), prop));
2493 }
2494
2495
2496 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
2497 doc: /* Set one property of FONT-SPEC: give property PROP value VALUE. */)
2498 (font_spec, prop, val)
2499 Lisp_Object font_spec, prop, val;
2500 {
2501 enum font_property_index idx;
2502 Lisp_Object extra, slot;
2503
2504 CHECK_FONT_SPEC (font_spec);
2505 idx = check_font_prop_name (prop);
2506 if (idx < FONT_EXTRA_INDEX)
2507 return ASET (font_spec, idx, val);
2508 extra = AREF (font_spec, FONT_EXTRA_INDEX);
2509 slot = Fassoc (extra, prop);
2510 if (NILP (slot))
2511 extra = Fcons (Fcons (prop, val), extra);
2512 else
2513 Fsetcdr (slot, val);
2514 return val;
2515 }
2516
2517 DEFUN ("list-fonts", Flist_fonts, Slist_fonts, 1, 4, 0,
2518 doc: /* List available fonts matching FONT-SPEC on the current frame.
2519 Optional 2nd argument FRAME specifies the target frame.
2520 Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
2521 Optional 4th argument PREFER, if non-nil, is a font-spec to sort fonts
2522 by closeness to PREFER. */)
2523 (font_spec, frame, num, prefer)
2524 Lisp_Object font_spec, frame, num, prefer;
2525 {
2526 Lisp_Object vec, list, tail;
2527 int n = 0, i, len;
2528
2529 if (NILP (frame))
2530 frame = selected_frame;
2531 CHECK_LIVE_FRAME (frame);
2532 CHECK_VALIDATE_FONT_SPEC (font_spec);
2533 if (! NILP (num))
2534 {
2535 CHECK_NUMBER (num);
2536 n = XINT (num);
2537 if (n <= 0)
2538 return Qnil;
2539 }
2540 if (! NILP (prefer))
2541 CHECK_FONT (prefer);
2542
2543 vec = font_list_entities (frame, font_spec);
2544 len = ASIZE (vec);
2545 if (len == 0)
2546 return Qnil;
2547 if (len == 1)
2548 return Fcons (AREF (vec, 0), Qnil);
2549
2550 if (! NILP (prefer))
2551 vec = font_sort_entites (vec, prefer, frame, font_spec);
2552
2553 list = tail = Fcons (AREF (vec, 0), Qnil);
2554 if (n == 0 || n > len)
2555 n = len;
2556 for (i = 1; i < n; i++)
2557 {
2558 Lisp_Object val = Fcons (AREF (vec, i), Qnil);
2559
2560 XSETCDR (tail, val);
2561 tail = val;
2562 }
2563 return list;
2564 }
2565
2566 DEFUN ("list-families", Flist_families, Slist_families, 0, 1, 0,
2567 doc: /* List available font families on the current frame.
2568 Optional 2nd argument FRAME specifies the target frame. */)
2569 (frame)
2570 Lisp_Object frame;
2571 {
2572 FRAME_PTR f;
2573 struct font_driver_list *driver_list;
2574 Lisp_Object list;
2575
2576 if (NILP (frame))
2577 frame = selected_frame;
2578 CHECK_LIVE_FRAME (frame);
2579 f = XFRAME (frame);
2580 list = Qnil;
2581 for (driver_list = f->font_driver_list; driver_list;
2582 driver_list = driver_list->next)
2583 if (driver_list->driver->list_family)
2584 {
2585 Lisp_Object val = driver_list->driver->list_family (frame);
2586
2587 if (NILP (list))
2588 list = val;
2589 else
2590 {
2591 Lisp_Object tail = list;
2592
2593 for (; CONSP (val); val = XCDR (val))
2594 if (NILP (Fmemq (XCAR (val), tail)))
2595 list = Fcons (XCAR (val), list);
2596 }
2597 }
2598 return list;
2599 }
2600
2601 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
2602 doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
2603 Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
2604 (font_spec, frame)
2605 Lisp_Object font_spec, frame;
2606 {
2607 Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
2608
2609 if (CONSP (val))
2610 val = XCAR (val);
2611 return val;
2612 }
2613
2614 DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 1, 0,
2615 doc: /* Return XLFD name of FONT.
2616 FONT is a font-spec, font-entity, or font-object.
2617 If the name is too long for XLFD (maximum 255 chars), return nil. */)
2618 (font)
2619 Lisp_Object font;
2620 {
2621 char name[256];
2622 int pixel_size = 0;
2623
2624 if (FONT_SPEC_P (font))
2625 CHECK_VALIDATE_FONT_SPEC (font);
2626 else if (FONT_ENTITY_P (font))
2627 CHECK_FONT (font);
2628 else
2629 {
2630 struct font *fontp;
2631
2632 CHECK_FONT_GET_OBJECT (font, fontp);
2633 font = fontp->entity;
2634 pixel_size = fontp->pixel_size;
2635 }
2636
2637 if (font_unparse_xlfd (font, pixel_size, name, 256) < 0)
2638 return Qnil;
2639 return build_string (name);
2640 }
2641
2642 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
2643 doc: /* Clear font cache. */)
2644 ()
2645 {
2646 Lisp_Object list, frame;
2647
2648 FOR_EACH_FRAME (list, frame)
2649 {
2650 FRAME_PTR f = XFRAME (frame);
2651 struct font_driver_list *driver_list = f->font_driver_list;
2652
2653 for (; driver_list; driver_list = driver_list->next)
2654 {
2655 Lisp_Object cache = driver_list->driver->get_cache (frame);
2656 Lisp_Object tail, elt;
2657
2658 for (tail = XCDR (cache); CONSP (tail); tail = XCDR (tail))
2659 {
2660 elt = XCAR (tail);
2661 if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
2662 {
2663 Lisp_Object vec = XCDR (elt);
2664 int i;
2665
2666 for (i = 0; i < ASIZE (vec); i++)
2667 {
2668 Lisp_Object entity = AREF (vec, i);
2669 Lisp_Object objlist = AREF (entity, FONT_OBJLIST_INDEX);
2670
2671 for (; CONSP (objlist); objlist = XCDR (objlist))
2672 {
2673 Lisp_Object val = XCAR (objlist);
2674 struct Lisp_Save_Value *p = XSAVE_VALUE (val);
2675 struct font *font = p->pointer;
2676
2677 xassert (font
2678 && driver_list->driver == font->driver);
2679 driver_list->driver->close (f, font);
2680 p->pointer = NULL;
2681 p->integer = 0;
2682 }
2683 if (driver_list->driver->free_entity)
2684 driver_list->driver->free_entity (entity);
2685 }
2686 }
2687 }
2688 XSETCDR (cache, Qnil);
2689 }
2690 }
2691
2692 return Qnil;
2693 }
2694
2695 DEFUN ("internal-set-font-style-table", Finternal_set_font_style_table,
2696 Sinternal_set_font_style_table, 2, 2, 0,
2697 doc: /* Set font style table for PROP to TABLE.
2698 PROP must be `:weight', `:slant', or `:width'.
2699 TABLE must be an alist of symbols vs the corresponding numeric values
2700 sorted by numeric values. */)
2701 (prop, table)
2702 Lisp_Object prop, table;
2703 {
2704 int table_index;
2705 int numeric;
2706 Lisp_Object tail, val;
2707
2708 CHECK_SYMBOL (prop);
2709 table_index = (EQ (prop, QCweight) ? 0
2710 : EQ (prop, QCslant) ? 1
2711 : EQ (prop, QCwidth) ? 2
2712 : 3);
2713 if (table_index >= ASIZE (font_style_table))
2714 error ("Invalid font style property: %s", SDATA (SYMBOL_NAME (prop)));
2715 table = Fcopy_sequence (table);
2716 numeric = -1;
2717 for (tail = table; ! NILP (tail); tail = Fcdr (tail))
2718 {
2719 prop = Fcar (Fcar (tail));
2720 val = Fcdr (Fcar (tail));
2721 CHECK_SYMBOL (prop);
2722 CHECK_NATNUM (val);
2723 if (numeric > XINT (val))
2724 error ("Numeric values not sorted for %s", SDATA (SYMBOL_NAME (prop)));
2725 numeric = XINT (val);
2726 XSETCAR (tail, Fcons (prop, val));
2727 }
2728 ASET (font_style_table, table_index, table);
2729 return Qnil;
2730 }
2731
2732 DEFUN ("font-make-gstring", Ffont_make_gstring, Sfont_make_gstring, 2, 2, 0,
2733 doc: /* Return a newly created glyph-string for FONT-OBJECT with NUM glyphs.
2734 FONT-OBJECT may be nil if it is not yet known. */)
2735 (font_object, num)
2736 Lisp_Object font_object, num;
2737 {
2738 Lisp_Object gstring, g;
2739 int len;
2740 int i;
2741
2742 if (! NILP (font_object))
2743 CHECK_FONT_OBJECT (font_object);
2744 CHECK_NATNUM (num);
2745
2746 len = XINT (num) + 1;
2747 gstring = Fmake_vector (make_number (len), Qnil);
2748 g = Fmake_vector (make_number (6), Qnil);
2749 ASET (g, 0, font_object);
2750 ASET (gstring, 0, g);
2751 for (i = 1; i < len; i++)
2752 ASET (gstring, i, Fmake_vector (make_number (8), make_number (0)));
2753 return gstring;
2754 }
2755
2756 DEFUN ("font-fill-gstring", Ffont_fill_gstring, Sfont_fill_gstring, 4, 5, 0,
2757 doc: /* Fillin glyph-string GSTRING by characters for FONT-OBJECT.
2758 START and END specifies the region to extract characters.
2759 If optional 3rd argument OBJECT is non-nil, it is a buffer or a string from
2760 where to extract characters.
2761 FONT-OBJECT may be nil if GSTRING already already contains one. */)
2762 (gstring, font_object, start, end, object)
2763 Lisp_Object gstring, font_object, start, end, object;
2764 {
2765 int len, i, c;
2766 unsigned code;
2767 struct font *font;
2768
2769 CHECK_VECTOR (gstring);
2770 if (NILP (font_object))
2771 font_object = Faref (Faref (gstring, make_number (0)), make_number (0));
2772 CHECK_FONT_GET_OBJECT (font_object, font);
2773
2774 if (STRINGP (object))
2775 {
2776 const unsigned char *p;
2777
2778 CHECK_NATNUM (start);
2779 CHECK_NATNUM (end);
2780 if (XINT (start) > XINT (end)
2781 || XINT (end) > ASIZE (object)
2782 || XINT (end) - XINT (start) >= XINT (Flength (gstring)))
2783 args_out_of_range (start, end);
2784
2785 len = XINT (end) - XINT (start);
2786 p = SDATA (object) + string_char_to_byte (object, XINT (start));
2787 for (i = 0; i < len; i++)
2788 {
2789 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
2790
2791 c = STRING_CHAR_ADVANCE (p);
2792 code = font->driver->encode_char (font, c);
2793 if (code > MOST_POSITIVE_FIXNUM)
2794 error ("Glyph code 0x%X is too large", code);
2795 ASET (g, 0, make_number (i));
2796 ASET (g, 1, make_number (i + 1));
2797 LGLYPH_SET_CHAR (g, make_number (c));
2798 LGLYPH_SET_CODE (g, make_number (code));
2799 }
2800 }
2801 else
2802 {
2803 int pos, pos_byte;
2804
2805 if (! NILP (object))
2806 Fset_buffer (object);
2807 validate_region (&start, &end);
2808 if (XINT (end) - XINT (start) > len)
2809 args_out_of_range (start, end);
2810 len = XINT (end) - XINT (start);
2811 pos = XINT (start);
2812 pos_byte = CHAR_TO_BYTE (pos);
2813 for (i = 0; i < len; i++)
2814 {
2815 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
2816
2817 FETCH_CHAR_ADVANCE (c, pos, pos_byte);
2818 code = font->driver->encode_char (font, c);
2819 if (code > MOST_POSITIVE_FIXNUM)
2820 error ("Glyph code 0x%X is too large", code);
2821 ASET (g, 0, make_number (i));
2822 ASET (g, 1, make_number (i + 1));
2823 LGLYPH_SET_CHAR (g, make_number (c));
2824 LGLYPH_SET_CODE (g, make_number (code));
2825 }
2826 }
2827 return Qnil;
2828 }
2829
2830
2831 #ifdef FONT_DEBUG
2832
2833 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
2834 doc: /* Open FONT-ENTITY. */)
2835 (font_entity, size, frame)
2836 Lisp_Object font_entity;
2837 Lisp_Object size;
2838 Lisp_Object frame;
2839 {
2840 int isize;
2841
2842 CHECK_FONT_ENTITY (font_entity);
2843 if (NILP (size))
2844 size = AREF (font_entity, FONT_SIZE_INDEX);
2845 CHECK_NUMBER (size);
2846 if (NILP (frame))
2847 frame = selected_frame;
2848 CHECK_LIVE_FRAME (frame);
2849
2850 isize = XINT (size);
2851 if (isize < 0)
2852 isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy);
2853
2854 return font_open_entity (XFRAME (frame), font_entity, isize);
2855 }
2856
2857 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
2858 doc: /* Close FONT-OBJECT. */)
2859 (font_object, frame)
2860 Lisp_Object font_object, frame;
2861 {
2862 CHECK_FONT_OBJECT (font_object);
2863 if (NILP (frame))
2864 frame = selected_frame;
2865 CHECK_LIVE_FRAME (frame);
2866 font_close_object (XFRAME (frame), font_object);
2867 return Qnil;
2868 }
2869
2870 DEFUN ("query-font", Fquery_font, Squery_font, 1, 1, 0,
2871 doc: /* Return information about FONT-OBJECT. */)
2872 (font_object)
2873 Lisp_Object font_object;
2874 {
2875 struct font *font;
2876 Lisp_Object val;
2877
2878 CHECK_FONT_GET_OBJECT (font_object, font);
2879
2880 val = Fmake_vector (make_number (9), Qnil);
2881 ASET (val, 0, Ffont_xlfd_name (font_object));
2882 if (font->file_name)
2883 ASET (val, 1, make_unibyte_string (font->file_name,
2884 strlen (font->file_name)));
2885 ASET (val, 2, make_number (font->pixel_size));
2886 ASET (val, 3, make_number (font->font.size));
2887 ASET (val, 4, make_number (font->ascent));
2888 ASET (val, 5, make_number (font->descent));
2889 ASET (val, 6, make_number (font->font.space_width));
2890 ASET (val, 7, make_number (font->font.average_width));
2891 if (font->driver->otf_capability)
2892 ASET (val, 8, font->driver->otf_capability (font));
2893 return val;
2894 }
2895
2896 DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
2897 doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
2898 Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT]. */)
2899 (font_object, string)
2900 Lisp_Object font_object, string;
2901 {
2902 struct font *font;
2903 int i, len;
2904 Lisp_Object vec;
2905
2906 CHECK_FONT_GET_OBJECT (font_object, font);
2907 CHECK_STRING (string);
2908 len = SCHARS (string);
2909 vec = Fmake_vector (make_number (len), Qnil);
2910 for (i = 0; i < len; i++)
2911 {
2912 Lisp_Object ch = Faref (string, make_number (i));
2913 Lisp_Object val;
2914 int c = XINT (ch);
2915 unsigned code;
2916 struct font_metrics metrics;
2917
2918 code = font->driver->encode_char (font, c);
2919 if (code == FONT_INVALID_CODE)
2920 continue;
2921 val = Fmake_vector (make_number (6), Qnil);
2922 if (code <= MOST_POSITIVE_FIXNUM)
2923 ASET (val, 0, make_number (code));
2924 else
2925 ASET (val, 0, Fcons (make_number (code >> 16),
2926 make_number (code & 0xFFFF)));
2927 font->driver->text_extents (font, &code, 1, &metrics);
2928 ASET (val, 1, make_number (metrics.lbearing));
2929 ASET (val, 2, make_number (metrics.rbearing));
2930 ASET (val, 3, make_number (metrics.width));
2931 ASET (val, 4, make_number (metrics.ascent));
2932 ASET (val, 5, make_number (metrics.descent));
2933 ASET (vec, i, val);
2934 }
2935 return vec;
2936 }
2937
2938 #if 0
2939 DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
2940 doc: /* Draw STRING by FONT-OBJECT on the top left corner of the current frame.
2941 The value is a number of glyphs drawn.
2942 Type C-l to recover what previously shown. */)
2943 (font_object, string)
2944 Lisp_Object font_object, string;
2945 {
2946 Lisp_Object frame = selected_frame;
2947 FRAME_PTR f = XFRAME (frame);
2948 struct font *font;
2949 struct face *face;
2950 int i, len, width;
2951 unsigned *code;
2952
2953 CHECK_FONT_GET_OBJECT (font_object, font);
2954 CHECK_STRING (string);
2955 len = SCHARS (string);
2956 code = alloca (sizeof (unsigned) * len);
2957 for (i = 0; i < len; i++)
2958 {
2959 Lisp_Object ch = Faref (string, make_number (i));
2960 Lisp_Object val;
2961 int c = XINT (ch);
2962
2963 code[i] = font->driver->encode_char (font, c);
2964 if (code[i] == FONT_INVALID_CODE)
2965 break;
2966 }
2967 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
2968 face->fontp = font;
2969 if (font->driver->prepare_face)
2970 font->driver->prepare_face (f, face);
2971 width = font->driver->text_extents (font, code, i, NULL);
2972 len = font->driver->draw_text (f, face, 0, font->ascent, code, i, width);
2973 if (font->driver->done_face)
2974 font->driver->done_face (f, face);
2975 face->fontp = NULL;
2976 return make_number (len);
2977 }
2978 #endif
2979
2980 #endif /* FONT_DEBUG */
2981
2982 \f
2983 extern void syms_of_ftfont P_ (());
2984 extern void syms_of_xfont P_ (());
2985 extern void syms_of_xftfont P_ (());
2986 extern void syms_of_ftxfont P_ (());
2987 extern void syms_of_bdffont P_ (());
2988 extern void syms_of_w32font P_ (());
2989 extern void syms_of_atmfont P_ (());
2990
2991 void
2992 syms_of_font ()
2993 {
2994 sort_shift_bits[FONT_SLANT_INDEX] = 0;
2995 sort_shift_bits[FONT_WEIGHT_INDEX] = 7;
2996 sort_shift_bits[FONT_SIZE_INDEX] = 14;
2997 sort_shift_bits[FONT_WIDTH_INDEX] = 21;
2998 sort_shift_bits[FONT_ADSTYLE_INDEX] = 28;
2999 sort_shift_bits[FONT_FOUNDRY_INDEX] = 29;
3000 sort_shift_bits[FONT_FAMILY_INDEX] = 30;
3001 sort_shift_bits[FONT_REGISTRY_INDEX] = 31;
3002 /* Note that sort_shift_bits[FONT_SLANT_TYPE] is never used. */
3003
3004 staticpro (&font_style_table);
3005 font_style_table = Fmake_vector (make_number (3), Qnil);
3006
3007 staticpro (&font_family_alist);
3008 font_family_alist = Qnil;
3009
3010 DEFSYM (Qfontp, "fontp");
3011
3012 DEFSYM (Qiso8859_1, "iso8859-1");
3013 DEFSYM (Qiso10646_1, "iso10646-1");
3014 DEFSYM (Qunicode_bmp, "unicode-bmp");
3015
3016 DEFSYM (QCotf, ":otf");
3017 DEFSYM (QClanguage, ":language");
3018 DEFSYM (QCscript, ":script");
3019
3020 DEFSYM (QCfoundry, ":foundry");
3021 DEFSYM (QCadstyle, ":adstyle");
3022 DEFSYM (QCregistry, ":registry");
3023 DEFSYM (QCextra, ":extra");
3024
3025 staticpro (&null_string);
3026 null_string = build_string ("");
3027 staticpro (&null_vector);
3028 null_vector = Fmake_vector (make_number (0), Qnil);
3029
3030 staticpro (&scratch_font_spec);
3031 scratch_font_spec = Ffont_spec (0, NULL);
3032 staticpro (&scratch_font_prefer);
3033 scratch_font_prefer = Ffont_spec (0, NULL);
3034
3035 defsubr (&Sfontp);
3036 defsubr (&Sfont_spec);
3037 defsubr (&Sfont_get);
3038 defsubr (&Sfont_put);
3039 defsubr (&Slist_fonts);
3040 defsubr (&Slist_families);
3041 defsubr (&Sfind_font);
3042 defsubr (&Sfont_xlfd_name);
3043 defsubr (&Sclear_font_cache);
3044 defsubr (&Sinternal_set_font_style_table);
3045 defsubr (&Sfont_make_gstring);
3046 defsubr (&Sfont_fill_gstring);
3047
3048 #ifdef FONT_DEBUG
3049 defsubr (&Sopen_font);
3050 defsubr (&Sclose_font);
3051 defsubr (&Squery_font);
3052 defsubr (&Sget_font_glyphs);
3053 #if 0
3054 defsubr (&Sdraw_string);
3055 #endif
3056 #endif /* FONT_DEBUG */
3057
3058 #ifdef HAVE_FREETYPE
3059 syms_of_ftfont ();
3060 #ifdef HAVE_X_WINDOWS
3061 syms_of_xfont ();
3062 syms_of_ftxfont ();
3063 #ifdef HAVE_XFT
3064 syms_of_xftfont ();
3065 #endif /* HAVE_XFT */
3066 #endif /* HAVE_X_WINDOWS */
3067 #else /* not HAVE_FREETYPE */
3068 #ifdef HAVE_X_WINDOWS
3069 syms_of_xfont ();
3070 #endif /* HAVE_X_WINDOWS */
3071 #endif /* not HAVE_FREETYPE */
3072 #ifdef HAVE_BDFFONT
3073 syms_of_bdffont ();
3074 #endif /* HAVE_BDFFONT */
3075 #ifdef WINDOWSNT
3076 syms_of_w32font ();
3077 #endif /* WINDOWSNT */
3078 #ifdef MAC_OS
3079 syms_of_atmfont ();
3080 #endif /* MAC_OS */
3081 }
3082
3083 /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
3084 (do not change this comment) */