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