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