]> code.delx.au - gnu-emacs/blob - src/ftfont.c
Fix missing prototypes for HAVE_NS (caused crash) and vrious warnings.
[gnu-emacs] / src / ftfont.c
1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7 This file is part of GNU Emacs.
8
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <setjmp.h>
25
26 #include <fontconfig/fontconfig.h>
27 #include <fontconfig/fcfreetype.h>
28
29 #include "lisp.h"
30 #include "dispextern.h"
31 #include "frame.h"
32 #include "blockinput.h"
33 #include "character.h"
34 #include "charset.h"
35 #include "coding.h"
36 #include "composite.h"
37 #include "fontset.h"
38 #include "font.h"
39 #include "ftfont.h"
40
41 /* Symbolic type of this font-driver. */
42 Lisp_Object Qfreetype;
43
44 /* Fontconfig's generic families and their aliases. */
45 static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
46
47 /* Flag to tell if FcInit is already called or not. */
48 static int fc_initialized;
49
50 /* Handle to a FreeType library instance. */
51 static FT_Library ft_library;
52
53 /* Cache for FreeType fonts. */
54 static Lisp_Object freetype_font_cache;
55
56 /* Cache for FT_Face and FcCharSet. */
57 static Lisp_Object ft_face_cache;
58
59 /* The actual structure for FreeType font that can be casted to struct
60 font. */
61
62 struct ftfont_info
63 {
64 struct font font;
65 #ifdef HAVE_LIBOTF
66 /* The following four members must be here in this order to be
67 compatible with struct xftfont_info (in xftfont.c). */
68 int maybe_otf; /* Flag to tell if this may be OTF or not. */
69 OTF *otf;
70 #endif /* HAVE_LIBOTF */
71 FT_Size ft_size;
72 int index;
73 FT_Matrix matrix;
74 };
75
76 enum ftfont_cache_for
77 {
78 FTFONT_CACHE_FOR_FACE,
79 FTFONT_CACHE_FOR_CHARSET,
80 FTFONT_CACHE_FOR_ENTITY
81 };
82
83 static Lisp_Object ftfont_pattern_entity (FcPattern *, Lisp_Object);
84
85 static Lisp_Object ftfont_resolve_generic_family (Lisp_Object,
86 FcPattern *);
87 static Lisp_Object ftfont_lookup_cache (Lisp_Object,
88 enum ftfont_cache_for);
89
90 static void ftfont_filter_properties (Lisp_Object font, Lisp_Object alist);
91
92 Lisp_Object ftfont_font_format (FcPattern *, Lisp_Object);
93
94 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
95
96 static struct
97 {
98 /* registry name */
99 char *name;
100 /* characters to distinguish the charset from the others */
101 int uniquifier[6];
102 /* additional constraint by language */
103 char *lang;
104 /* set on demand */
105 FcCharSet *fc_charset;
106 } fc_charset_table[] =
107 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
108 { "iso8859-2", { 0x00A0, 0x010E }},
109 { "iso8859-3", { 0x00A0, 0x0108 }},
110 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
111 { "iso8859-5", { 0x00A0, 0x0401 }},
112 { "iso8859-6", { 0x00A0, 0x060C }},
113 { "iso8859-7", { 0x00A0, 0x0384 }},
114 { "iso8859-8", { 0x00A0, 0x05D0 }},
115 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
116 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
117 { "iso8859-11", { 0x00A0, 0x0E01 }},
118 { "iso8859-13", { 0x00A0, 0x201C }},
119 { "iso8859-14", { 0x00A0, 0x0174 }},
120 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
121 { "iso8859-16", { 0x00A0, 0x0218}},
122 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
123 { "big5-0", { 0xF6B1 }, "zh-tw" },
124 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
125 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
126 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
127 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
128 { "cns11643.1992-3", { 0x201A9 }},
129 { "cns11643.1992-4", { 0x20057 }},
130 { "cns11643.1992-5", { 0x20000 }},
131 { "cns11643.1992-6", { 0x20003 }},
132 { "cns11643.1992-7", { 0x20055 }},
133 { "gbk-0", { 0x4E06 }, "zh-cn"},
134 { "jisx0212.1990-0", { 0x4E44 }},
135 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
136 { "jisx0213.2000-2", { 0xFA49 }},
137 { "jisx0213.2004-1", { 0x20B9F }},
138 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
139 { "tis620.2529-1", { 0x0E01 }, "th"},
140 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
141 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
142 { "mulelao-1", { 0x0E81 }, "lo"},
143 { "unicode-sip", { 0x20000 }},
144 { NULL }
145 };
146
147 /* Dirty hack for handing ADSTYLE property.
148
149 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
150 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
151 "Oblique", "Italic", or any non-normal SWIDTH property names
152 (e.g. SemiCondensed) are appended. In addition, if there's no
153 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
154 "Regular" is used for FC_STYLE (see the function
155 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
156
157 Unfortunately this behavior is not documented, so the following
158 code may fail if FreeType changes the behavior in the future. */
159
160 static Lisp_Object
161 get_adstyle_property (FcPattern *p)
162 {
163 char *str, *end;
164 Lisp_Object adstyle;
165
166 if (FcPatternGetString (p, FC_STYLE, 0, (FcChar8 **) &str) != FcResultMatch)
167 return Qnil;
168 for (end = str; *end && *end != ' '; end++);
169 if (*end)
170 {
171 char *p = alloca (end - str + 1);
172 memcpy (p, str, end - str);
173 p[end - str] = '\0';
174 end = p + (end - str);
175 str = p;
176 }
177 if (xstrcasecmp (str, "Regular") == 0
178 || xstrcasecmp (str, "Bold") == 0
179 || xstrcasecmp (str, "Oblique") == 0
180 || xstrcasecmp (str, "Italic") == 0)
181 return Qnil;
182 adstyle = font_intern_prop (str, end - str, 1);
183 if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
184 return Qnil;
185 return adstyle;
186 }
187
188 static Lisp_Object
189 ftfont_pattern_entity (FcPattern *p, Lisp_Object extra)
190 {
191 Lisp_Object key, cache, entity;
192 char *file, *str;
193 int index;
194 int numeric;
195 double dbl;
196 FcBool b;
197
198 if (FcPatternGetString (p, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
199 return Qnil;
200 if (FcPatternGetInteger (p, FC_INDEX, 0, &index) != FcResultMatch)
201 return Qnil;
202
203 key = Fcons (make_unibyte_string ((char *) file, strlen ((char *) file)),
204 make_number (index));
205 cache = ftfont_lookup_cache (key, FTFONT_CACHE_FOR_ENTITY);
206 entity = XCAR (cache);
207 if (! NILP (entity))
208 {
209 Lisp_Object val = font_make_entity ();
210 int i;
211
212 for (i = 0; i < FONT_OBJLIST_INDEX; i++)
213 ASET (val, i, AREF (entity, i));
214 return val;
215 }
216 entity = font_make_entity ();
217 XSETCAR (cache, entity);
218
219 ASET (entity, FONT_TYPE_INDEX, Qfreetype);
220 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
221
222 if (FcPatternGetString (p, FC_FOUNDRY, 0, (FcChar8 **) &str) == FcResultMatch)
223 ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (str, strlen (str), 1));
224 if (FcPatternGetString (p, FC_FAMILY, 0, (FcChar8 **) &str) == FcResultMatch)
225 ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (str, strlen (str), 1));
226 if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
227 {
228 if (numeric >= FC_WEIGHT_REGULAR && numeric < FC_WEIGHT_MEDIUM)
229 numeric = FC_WEIGHT_MEDIUM;
230 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, make_number (numeric));
231 }
232 if (FcPatternGetInteger (p, FC_SLANT, 0, &numeric) == FcResultMatch)
233 {
234 numeric += 100;
235 FONT_SET_STYLE (entity, FONT_SLANT_INDEX, make_number (numeric));
236 }
237 if (FcPatternGetInteger (p, FC_WIDTH, 0, &numeric) == FcResultMatch)
238 {
239 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric));
240 }
241 if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
242 {
243 ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
244 }
245 else
246 ASET (entity, FONT_SIZE_INDEX, make_number (0));
247 if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch)
248 ASET (entity, FONT_SPACING_INDEX, make_number (numeric));
249 if (FcPatternGetDouble (p, FC_DPI, 0, &dbl) == FcResultMatch)
250 {
251 int dpi = dbl;
252 ASET (entity, FONT_DPI_INDEX, make_number (dpi));
253 }
254 if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
255 && b == FcTrue)
256 {
257 ASET (entity, FONT_SIZE_INDEX, make_number (0));
258 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
259 }
260 else
261 {
262 /* As this font is not scalable, parhaps this is a BDF or PCF
263 font. */
264 FT_Face ft_face;
265
266 ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
267 if ((ft_library || FT_Init_FreeType (&ft_library) == 0)
268 && FT_New_Face (ft_library, file, index, &ft_face) == 0)
269 {
270 BDF_PropertyRec rec;
271
272 if (FT_Get_BDF_Property (ft_face, "AVERAGE_WIDTH", &rec) == 0
273 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
274 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (rec.u.integer));
275 FT_Done_Face (ft_face);
276 }
277 }
278
279 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
280 font_put_extra (entity, QCfont_entity, key);
281 return entity;
282 }
283
284
285 static Lisp_Object ftfont_generic_family_list;
286
287 static Lisp_Object
288 ftfont_resolve_generic_family (Lisp_Object family, FcPattern *pattern)
289 {
290 Lisp_Object slot;
291 FcPattern *match;
292 FcResult result;
293 FcLangSet *langset;
294
295 family = Fintern (Fdowncase (SYMBOL_NAME (family)), Qnil);
296 if (EQ (family, Qmono))
297 family = Qmonospace;
298 else if (EQ (family, Qsans) || EQ (family, Qsans__serif))
299 family = Qsans_serif;
300 slot = assq_no_quit (family, ftfont_generic_family_list);
301 if (! CONSP (slot))
302 return Qnil;
303 if (! EQ (XCDR (slot), Qt))
304 return XCDR (slot);
305 pattern = FcPatternDuplicate (pattern);
306 if (! pattern)
307 goto err;
308 FcPatternDel (pattern, FC_FOUNDRY);
309 FcPatternDel (pattern, FC_FAMILY);
310 FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (family));
311 if (FcPatternGetLangSet (pattern, FC_LANG, 0, &langset) != FcResultMatch)
312 {
313 /* This is to avoid the effect of locale. */
314 langset = FcLangSetCreate ();
315 FcLangSetAdd (langset, "en");
316 FcPatternAddLangSet (pattern, FC_LANG, langset);
317 FcLangSetDestroy (langset);
318 }
319 FcConfigSubstitute (NULL, pattern, FcMatchPattern);
320 FcDefaultSubstitute (pattern);
321 match = FcFontMatch (NULL, pattern, &result);
322 if (match)
323 {
324 FcChar8 *fam;
325
326 if (FcPatternGetString (match, FC_FAMILY, 0, &fam) == FcResultMatch)
327 family = intern ((char *) fam);
328 }
329 else
330 family = Qnil;
331 XSETCDR (slot, family);
332 if (match) FcPatternDestroy (match);
333 err:
334 if (pattern) FcPatternDestroy (pattern);
335 return family;
336 }
337
338 struct ftfont_cache_data
339 {
340 FT_Face ft_face;
341 FcCharSet *fc_charset;
342 };
343
344 static Lisp_Object
345 ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for)
346 {
347 Lisp_Object cache, val, entity;
348 struct ftfont_cache_data *cache_data;
349
350 if (FONT_ENTITY_P (key))
351 {
352 entity = key;
353 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
354 xassert (CONSP (val));
355 key = XCDR (val);
356 }
357 else
358 entity = Qnil;
359
360 if (NILP (ft_face_cache))
361 cache = Qnil;
362 else
363 cache = Fgethash (key, ft_face_cache, Qnil);
364 if (NILP (cache))
365 {
366 if (NILP (ft_face_cache))
367 {
368 Lisp_Object args[2];
369
370 args[0] = QCtest;
371 args[1] = Qequal;
372 ft_face_cache = Fmake_hash_table (2, args);
373 }
374 cache_data = xmalloc (sizeof (struct ftfont_cache_data));
375 cache_data->ft_face = NULL;
376 cache_data->fc_charset = NULL;
377 val = make_save_value (NULL, 0);
378 XSAVE_VALUE (val)->integer = 0;
379 XSAVE_VALUE (val)->pointer = cache_data;
380 cache = Fcons (Qnil, val);
381 Fputhash (key, cache, ft_face_cache);
382 }
383 else
384 {
385 val = XCDR (cache);
386 cache_data = XSAVE_VALUE (val)->pointer;
387 }
388
389 if (cache_for == FTFONT_CACHE_FOR_ENTITY)
390 return cache;
391
392 if (cache_for == FTFONT_CACHE_FOR_FACE
393 ? ! cache_data->ft_face : ! cache_data->fc_charset)
394 {
395 char *filename = (char *) SDATA (XCAR (key));
396 int index = XINT (XCDR (key));
397
398 if (cache_for == FTFONT_CACHE_FOR_FACE)
399 {
400 if (! ft_library
401 && FT_Init_FreeType (&ft_library) != 0)
402 return Qnil;
403 if (FT_New_Face (ft_library, filename, index, &cache_data->ft_face)
404 != 0)
405 return Qnil;
406 }
407 else
408 {
409 FcPattern *pat = NULL;
410 FcFontSet *fontset = NULL;
411 FcObjectSet *objset = NULL;
412 FcCharSet *charset = NULL;
413
414 pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename,
415 FC_INDEX, FcTypeInteger, index, NULL);
416 if (! pat)
417 goto finish;
418 objset = FcObjectSetBuild (FC_CHARSET, FC_STYLE, NULL);
419 if (! objset)
420 goto finish;
421 fontset = FcFontList (NULL, pat, objset);
422 if (! fontset)
423 goto finish;
424 if (fontset && fontset->nfont > 0
425 && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
426 &charset)
427 == FcResultMatch))
428 cache_data->fc_charset = FcCharSetCopy (charset);
429 else
430 cache_data->fc_charset = FcCharSetCreate ();
431
432 finish:
433 if (fontset)
434 FcFontSetDestroy (fontset);
435 if (objset)
436 FcObjectSetDestroy (objset);
437 if (pat)
438 FcPatternDestroy (pat);
439 }
440 }
441 return cache;
442 }
443
444 FcCharSet *
445 ftfont_get_fc_charset (Lisp_Object entity)
446 {
447 Lisp_Object val, cache;
448 struct ftfont_cache_data *cache_data;
449
450 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
451 val = XCDR (cache);
452 cache_data = XSAVE_VALUE (val)->pointer;
453 return cache_data->fc_charset;
454 }
455
456 #ifdef HAVE_LIBOTF
457 static OTF *
458 ftfont_get_otf (struct ftfont_info *ftfont_info)
459 {
460 OTF *otf;
461
462 if (ftfont_info->otf)
463 return ftfont_info->otf;
464 if (! ftfont_info->maybe_otf)
465 return NULL;
466 otf = OTF_open_ft_face (ftfont_info->ft_size->face);
467 if (! otf || OTF_get_table (otf, "head") < 0)
468 {
469 if (otf)
470 OTF_close (otf);
471 ftfont_info->maybe_otf = 0;
472 return NULL;
473 }
474 ftfont_info->otf = otf;
475 return otf;
476 }
477 #endif /* HAVE_LIBOTF */
478
479 static Lisp_Object ftfont_get_cache (FRAME_PTR);
480 static Lisp_Object ftfont_list (Lisp_Object, Lisp_Object);
481 static Lisp_Object ftfont_match (Lisp_Object, Lisp_Object);
482 static Lisp_Object ftfont_list_family (Lisp_Object);
483 static Lisp_Object ftfont_open (FRAME_PTR, Lisp_Object, int);
484 static void ftfont_close (FRAME_PTR, struct font *);
485 static int ftfont_has_char (Lisp_Object, int);
486 static unsigned ftfont_encode_char (struct font *, int);
487 static int ftfont_text_extents (struct font *, unsigned *, int,
488 struct font_metrics *);
489 static int ftfont_get_bitmap (struct font *, unsigned,
490 struct font_bitmap *, int);
491 static int ftfont_anchor_point (struct font *, unsigned, int,
492 int *, int *);
493 static Lisp_Object ftfont_otf_capability (struct font *);
494 static Lisp_Object ftfont_shape (Lisp_Object);
495
496 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
497 static int ftfont_variation_glyphs (struct font *, int c,
498 unsigned variations[256]);
499 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
500
501 struct font_driver ftfont_driver =
502 {
503 0, /* Qfreetype */
504 0, /* case insensitive */
505 ftfont_get_cache,
506 ftfont_list,
507 ftfont_match,
508 ftfont_list_family,
509 NULL, /* free_entity */
510 ftfont_open,
511 ftfont_close,
512 /* We can't draw a text without device dependent functions. */
513 NULL, /* prepare_face */
514 NULL, /* done_face */
515 ftfont_has_char,
516 ftfont_encode_char,
517 ftfont_text_extents,
518 /* We can't draw a text without device dependent functions. */
519 NULL, /* draw */
520 ftfont_get_bitmap,
521 NULL, /* get_bitmap */
522 NULL, /* free_bitmap */
523 NULL, /* get_outline */
524 ftfont_anchor_point,
525 #ifdef HAVE_LIBOTF
526 ftfont_otf_capability,
527 #else /* not HAVE_LIBOTF */
528 NULL,
529 #endif /* not HAVE_LIBOTF */
530 NULL, /* otf_drive */
531 NULL, /* start_for_frame */
532 NULL, /* end_for_frame */
533 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
534 ftfont_shape,
535 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
536 NULL,
537 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
538 NULL, /* check */
539
540 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
541 ftfont_variation_glyphs,
542 #else
543 NULL,
544 #endif
545
546 ftfont_filter_properties, /* filter_properties */
547 };
548
549 static Lisp_Object
550 ftfont_get_cache (FRAME_PTR f)
551 {
552 return freetype_font_cache;
553 }
554
555 static int
556 ftfont_get_charset (Lisp_Object registry)
557 {
558 char *str = (char *) SDATA (SYMBOL_NAME (registry));
559 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
560 Lisp_Object regexp;
561 int i, j;
562
563 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
564 {
565 if (str[i] == '.')
566 re[j++] = '\\';
567 else if (str[i] == '*')
568 re[j++] = '.';
569 re[j] = str[i];
570 if (re[j] == '?')
571 re[j] = '.';
572 }
573 re[j] = '\0';
574 regexp = make_unibyte_string (re, j);
575 for (i = 0; fc_charset_table[i].name; i++)
576 if (fast_c_string_match_ignore_case (regexp, fc_charset_table[i].name) >= 0)
577 break;
578 if (! fc_charset_table[i].name)
579 return -1;
580 if (! fc_charset_table[i].fc_charset)
581 {
582 FcCharSet *charset = FcCharSetCreate ();
583 int *uniquifier = fc_charset_table[i].uniquifier;
584
585 if (! charset)
586 return -1;
587 for (j = 0; uniquifier[j]; j++)
588 if (! FcCharSetAddChar (charset, uniquifier[j]))
589 {
590 FcCharSetDestroy (charset);
591 return -1;
592 }
593 fc_charset_table[i].fc_charset = charset;
594 }
595 return i;
596 }
597
598 struct OpenTypeSpec
599 {
600 Lisp_Object script;
601 unsigned int script_tag, langsys_tag;
602 int nfeatures[2];
603 unsigned int *features[2];
604 };
605
606 #define OTF_SYM_TAG(SYM, TAG) \
607 do { \
608 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
609 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
610 } while (0)
611
612 #define OTF_TAG_STR(TAG, P) \
613 do { \
614 (P)[0] = (char) (TAG >> 24); \
615 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
616 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
617 (P)[3] = (char) (TAG & 0xFF); \
618 (P)[4] = '\0'; \
619 } while (0)
620
621 #define OTF_TAG_SYM(SYM, TAG) \
622 do { \
623 char str[5]; \
624 \
625 OTF_TAG_STR (TAG, str); \
626 (SYM) = font_intern_prop (str, 4, 1); \
627 } while (0)
628
629
630 static struct OpenTypeSpec *
631 ftfont_get_open_type_spec (Lisp_Object otf_spec)
632 {
633 struct OpenTypeSpec *spec = malloc (sizeof (struct OpenTypeSpec));
634 Lisp_Object val;
635 int i, j, negative;
636
637 if (! spec)
638 return NULL;
639 spec->script = XCAR (otf_spec);
640 if (! NILP (spec->script))
641 {
642 OTF_SYM_TAG (spec->script, spec->script_tag);
643 val = assq_no_quit (spec->script, Votf_script_alist);
644 if (CONSP (val) && SYMBOLP (XCDR (val)))
645 spec->script = XCDR (val);
646 else
647 spec->script = Qnil;
648 }
649 else
650 spec->script_tag = 0x44464C54; /* "DFLT" */
651 otf_spec = XCDR (otf_spec);
652 spec->langsys_tag = 0;
653 if (! NILP (otf_spec))
654 {
655 val = XCAR (otf_spec);
656 if (! NILP (val))
657 OTF_SYM_TAG (val, spec->langsys_tag);
658 otf_spec = XCDR (otf_spec);
659 }
660 spec->nfeatures[0] = spec->nfeatures[1] = 0;
661 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
662 {
663 Lisp_Object len;
664
665 val = XCAR (otf_spec);
666 if (NILP (val))
667 continue;
668 len = Flength (val);
669 spec->features[i] = malloc (sizeof (int) * XINT (len));
670 if (! spec->features[i])
671 {
672 if (i > 0 && spec->features[0])
673 free (spec->features[0]);
674 free (spec);
675 return NULL;
676 }
677 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
678 {
679 if (NILP (XCAR (val)))
680 negative = 1;
681 else
682 {
683 unsigned int tag;
684
685 OTF_SYM_TAG (XCAR (val), tag);
686 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
687 }
688 }
689 spec->nfeatures[i] = j;
690 }
691 return spec;
692 }
693
694 static FcPattern *ftfont_spec_pattern (Lisp_Object, char *,
695 struct OpenTypeSpec **,
696 char **langname);
697
698 static FcPattern *
699 ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **otspec, char **langname)
700 {
701 Lisp_Object tmp, extra;
702 FcPattern *pattern = NULL;
703 FcCharSet *charset = NULL;
704 FcLangSet *langset = NULL;
705 int n;
706 int dpi = -1;
707 int scalable = -1;
708 Lisp_Object script = Qnil;
709 Lisp_Object registry;
710 int fc_charset_idx;
711
712 if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
713 && n < 100)
714 /* Fontconfig doesn't support reverse-italic/obligue. */
715 return NULL;
716
717 if (INTEGERP (AREF (spec, FONT_DPI_INDEX)))
718 dpi = XINT (AREF (spec, FONT_DPI_INDEX));
719 if (INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
720 && XINT (AREF (spec, FONT_AVGWIDTH_INDEX)) == 0)
721 scalable = 1;
722
723 registry = AREF (spec, FONT_REGISTRY_INDEX);
724 if (NILP (registry)
725 || EQ (registry, Qascii_0)
726 || EQ (registry, Qiso10646_1)
727 || EQ (registry, Qunicode_bmp))
728 fc_charset_idx = -1;
729 else
730 {
731 FcChar8 *lang;
732
733 fc_charset_idx = ftfont_get_charset (registry);
734 if (fc_charset_idx < 0)
735 return NULL;
736 charset = fc_charset_table[fc_charset_idx].fc_charset;
737 *langname = fc_charset_table[fc_charset_idx].lang;
738 lang = (FcChar8 *) *langname;
739 if (lang)
740 {
741 langset = FcLangSetCreate ();
742 if (! langset)
743 goto err;
744 FcLangSetAdd (langset, lang);
745 }
746 }
747
748 otlayout[0] = '\0';
749 for (extra = AREF (spec, FONT_EXTRA_INDEX);
750 CONSP (extra); extra = XCDR (extra))
751 {
752 Lisp_Object key, val;
753
754 key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
755 if (EQ (key, QCdpi))
756 dpi = XINT (val);
757 else if (EQ (key, QClang))
758 {
759 if (! langset)
760 langset = FcLangSetCreate ();
761 if (! langset)
762 goto err;
763 if (SYMBOLP (val))
764 {
765 if (! FcLangSetAdd (langset, SYMBOL_FcChar8 (val)))
766 goto err;
767 }
768 else
769 for (; CONSP (val); val = XCDR (val))
770 if (SYMBOLP (XCAR (val))
771 && ! FcLangSetAdd (langset, SYMBOL_FcChar8 (XCAR (val))))
772 goto err;
773 }
774 else if (EQ (key, QCotf))
775 {
776 *otspec = ftfont_get_open_type_spec (val);
777 if (! *otspec)
778 return NULL;
779 strcat (otlayout, "otlayout:");
780 OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
781 script = (*otspec)->script;
782 }
783 else if (EQ (key, QCscript))
784 script = val;
785 else if (EQ (key, QCscalable))
786 scalable = ! NILP (val);
787 }
788
789 if (! NILP (script) && ! charset)
790 {
791 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
792
793 if (CONSP (chars) && CONSP (CDR (chars)))
794 {
795 charset = FcCharSetCreate ();
796 if (! charset)
797 goto err;
798 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
799 if (CHARACTERP (XCAR (chars))
800 && ! FcCharSetAddChar (charset, XUINT (XCAR (chars))))
801 goto err;
802 }
803 }
804
805 pattern = FcPatternCreate ();
806 if (! pattern)
807 goto err;
808 tmp = AREF (spec, FONT_FOUNDRY_INDEX);
809 if (! NILP (tmp)
810 && ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
811 goto err;
812 tmp = AREF (spec, FONT_FAMILY_INDEX);
813 if (! NILP (tmp)
814 && ! FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (tmp)))
815 goto err;
816 if (charset
817 && ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
818 goto err;
819 if (langset
820 && ! FcPatternAddLangSet (pattern, FC_LANG, langset))
821 goto err;
822 if (dpi >= 0
823 && ! FcPatternAddDouble (pattern, FC_DPI, dpi))
824 goto err;
825 if (scalable >= 0
826 && ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
827 goto err;
828
829 goto finish;
830
831 err:
832 /* We come here because of unexpected error in fontconfig API call
833 (usually insufficient memory). */
834 if (pattern)
835 {
836 FcPatternDestroy (pattern);
837 pattern = NULL;
838 }
839 if (*otspec)
840 {
841 if ((*otspec)->nfeatures[0] > 0)
842 free ((*otspec)->features[0]);
843 if ((*otspec)->nfeatures[1] > 0)
844 free ((*otspec)->features[1]);
845 free (*otspec);
846 *otspec = NULL;
847 }
848
849 finish:
850 if (langset) FcLangSetDestroy (langset);
851 if (charset && fc_charset_idx < 0) FcCharSetDestroy (charset);
852 return pattern;
853 }
854
855 static Lisp_Object
856 ftfont_list (Lisp_Object frame, Lisp_Object spec)
857 {
858 Lisp_Object val = Qnil, family, adstyle;
859 int i;
860 FcPattern *pattern;
861 FcFontSet *fontset = NULL;
862 FcObjectSet *objset = NULL;
863 FcCharSet *charset;
864 Lisp_Object chars = Qnil;
865 FcResult result;
866 char otlayout[15]; /* For "otlayout:XXXX" */
867 struct OpenTypeSpec *otspec = NULL;
868 int spacing = -1;
869 char *langname = NULL;
870
871 if (! fc_initialized)
872 {
873 FcInit ();
874 fc_initialized = 1;
875 }
876
877 pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
878 if (! pattern)
879 return Qnil;
880 if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
881 {
882 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
883 if (! NILP (val))
884 {
885 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
886 if (CONSP (val) && VECTORP (XCDR (val)))
887 chars = XCDR (val);
888 }
889 val = Qnil;
890 }
891 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
892 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
893 family = AREF (spec, FONT_FAMILY_INDEX);
894 if (! NILP (family))
895 {
896 Lisp_Object resolved;
897
898 resolved = ftfont_resolve_generic_family (family, pattern);
899 if (! NILP (resolved))
900 {
901 FcPatternDel (pattern, FC_FAMILY);
902 if (! FcPatternAddString (pattern, FC_FAMILY,
903 SYMBOL_FcChar8 (resolved)))
904 goto err;
905 }
906 }
907 adstyle = AREF (spec, FONT_ADSTYLE_INDEX);
908 if (! NILP (adstyle) && SBYTES (SYMBOL_NAME (adstyle)) == 0)
909 adstyle = Qnil;
910 objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
911 FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
912 FC_STYLE, FC_FILE, FC_INDEX,
913 #ifdef FC_CAPABILITY
914 FC_CAPABILITY,
915 #endif /* FC_CAPABILITY */
916 #ifdef FC_FONTFORMAT
917 FC_FONTFORMAT,
918 #endif
919 NULL);
920 if (! objset)
921 goto err;
922 if (! NILP (chars))
923 FcObjectSetAdd (objset, FC_CHARSET);
924
925 fontset = FcFontList (NULL, pattern, objset);
926 if (! fontset || fontset->nfont == 0)
927 goto finish;
928 #if 0
929 /* Need fix because this finds any fonts. */
930 if (fontset->nfont == 0 && ! NILP (family))
931 {
932 /* Try maching with configuration. For instance, the
933 configuration may specify "Nimbus Mono L" as an alias of
934 "Courier". */
935 FcPattern *pat = FcPatternBuild (0, FC_FAMILY, FcTypeString,
936 SYMBOL_FcChar8 (family), NULL);
937 FcChar8 *fam;
938
939 if (FcConfigSubstitute (NULL, pat, FcMatchPattern) == FcTrue)
940 {
941 for (i = 0;
942 FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
943 i++)
944 {
945 FcPatternDel (pattern, FC_FAMILY);
946 FcPatternAddString (pattern, FC_FAMILY, fam);
947 FcFontSetDestroy (fontset);
948 fontset = FcFontList (NULL, pattern, objset);
949 if (fontset && fontset->nfont > 0)
950 break;
951 }
952 }
953 }
954 #endif
955 for (i = 0; i < fontset->nfont; i++)
956 {
957 Lisp_Object entity;
958
959 if (spacing >= 0)
960 {
961 int this;
962
963 if ((FcPatternGetInteger (fontset->fonts[i], FC_SPACING, 0, &this)
964 == FcResultMatch)
965 && spacing != this)
966 continue;
967 }
968
969 #ifdef FC_CAPABILITY
970 if (otlayout[0])
971 {
972 FcChar8 *this;
973
974 if (FcPatternGetString (fontset->fonts[i], FC_CAPABILITY, 0, &this)
975 != FcResultMatch
976 || ! strstr ((char *) this, otlayout))
977 continue;
978 }
979 #endif /* FC_CAPABILITY */
980 #ifdef HAVE_LIBOTF
981 if (otspec)
982 {
983 FcChar8 *file;
984 OTF *otf;
985
986 if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file)
987 != FcResultMatch)
988 continue;
989 otf = OTF_open ((char *) file);
990 if (! otf)
991 continue;
992 if (OTF_check_features (otf, 1,
993 otspec->script_tag, otspec->langsys_tag,
994 otspec->features[0],
995 otspec->nfeatures[0]) != 1
996 || OTF_check_features (otf, 0,
997 otspec->script_tag, otspec->langsys_tag,
998 otspec->features[1],
999 otspec->nfeatures[1]) != 1)
1000 continue;
1001 }
1002 #endif /* HAVE_LIBOTF */
1003 if (VECTORP (chars))
1004 {
1005 int j;
1006
1007 if (FcPatternGetCharSet (fontset->fonts[i], FC_CHARSET, 0, &charset)
1008 != FcResultMatch)
1009 continue;
1010 for (j = 0; j < ASIZE (chars); j++)
1011 if (NATNUMP (AREF (chars, j))
1012 && FcCharSetHasChar (charset, XFASTINT (AREF (chars, j))))
1013 break;
1014 if (j == ASIZE (chars))
1015 continue;
1016 }
1017 if (! NILP (adstyle) || langname)
1018 {
1019 Lisp_Object this_adstyle = get_adstyle_property (fontset->fonts[i]);
1020
1021 if (! NILP (adstyle)
1022 && (NILP (this_adstyle)
1023 || xstrcasecmp (SDATA (SYMBOL_NAME (adstyle)),
1024 SDATA (SYMBOL_NAME (this_adstyle))) != 0))
1025 continue;
1026 if (langname
1027 && ! NILP (this_adstyle)
1028 && xstrcasecmp (langname, SDATA (SYMBOL_NAME (this_adstyle))))
1029 continue;
1030 }
1031 entity = ftfont_pattern_entity (fontset->fonts[i],
1032 AREF (spec, FONT_EXTRA_INDEX));
1033 if (! NILP (entity))
1034 val = Fcons (entity, val);
1035 }
1036 val = Fnreverse (val);
1037 goto finish;
1038
1039 err:
1040 /* We come here because of unexpected error in fontconfig API call
1041 (usually insufficient memory). */
1042 val = Qnil;
1043
1044 finish:
1045 FONT_ADD_LOG ("ftfont-list", spec, val);
1046 if (objset) FcObjectSetDestroy (objset);
1047 if (fontset) FcFontSetDestroy (fontset);
1048 if (pattern) FcPatternDestroy (pattern);
1049 return val;
1050 }
1051
1052 static Lisp_Object
1053 ftfont_match (Lisp_Object frame, Lisp_Object spec)
1054 {
1055 Lisp_Object entity = Qnil;
1056 FcPattern *pattern, *match = NULL;
1057 FcResult result;
1058 char otlayout[15]; /* For "otlayout:XXXX" */
1059 struct OpenTypeSpec *otspec = NULL;
1060 char *langname = NULL;
1061
1062 if (! fc_initialized)
1063 {
1064 FcInit ();
1065 fc_initialized = 1;
1066 }
1067
1068 pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
1069 if (! pattern)
1070 return Qnil;
1071
1072 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
1073 {
1074 FcValue value;
1075
1076 value.type = FcTypeDouble;
1077 value.u.d = XINT (AREF (spec, FONT_SIZE_INDEX));
1078 FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse);
1079 }
1080 if (FcConfigSubstitute (NULL, pattern, FcMatchPattern) == FcTrue)
1081 {
1082 FcDefaultSubstitute (pattern);
1083 match = FcFontMatch (NULL, pattern, &result);
1084 if (match)
1085 {
1086 entity = ftfont_pattern_entity (match, AREF (spec, FONT_EXTRA_INDEX));
1087 FcPatternDestroy (match);
1088 if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
1089 && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
1090 ftfont_generic_family_list))
1091 && NILP (Fstring_equal (AREF (spec, FONT_FAMILY_INDEX),
1092 AREF (entity, FONT_FAMILY_INDEX))))
1093 entity = Qnil;
1094 }
1095 }
1096 FcPatternDestroy (pattern);
1097
1098 FONT_ADD_LOG ("ftfont-match", spec, entity);
1099 return entity;
1100 }
1101
1102 static Lisp_Object
1103 ftfont_list_family (Lisp_Object frame)
1104 {
1105 Lisp_Object list = Qnil;
1106 FcPattern *pattern = NULL;
1107 FcFontSet *fontset = NULL;
1108 FcObjectSet *objset = NULL;
1109 int i;
1110
1111 if (! fc_initialized)
1112 {
1113 FcInit ();
1114 fc_initialized = 1;
1115 }
1116
1117 pattern = FcPatternCreate ();
1118 if (! pattern)
1119 goto finish;
1120 objset = FcObjectSetBuild (FC_FAMILY, NULL);
1121 if (! objset)
1122 goto finish;
1123 fontset = FcFontList (NULL, pattern, objset);
1124 if (! fontset)
1125 goto finish;
1126
1127 for (i = 0; i < fontset->nfont; i++)
1128 {
1129 FcPattern *pat = fontset->fonts[i];
1130 FcChar8 *str;
1131
1132 if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
1133 list = Fcons (intern ((char *) str), list);
1134 }
1135
1136 finish:
1137 if (objset) FcObjectSetDestroy (objset);
1138 if (fontset) FcFontSetDestroy (fontset);
1139 if (pattern) FcPatternDestroy (pattern);
1140
1141 return list;
1142 }
1143
1144
1145 static Lisp_Object
1146 ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
1147 {
1148 struct ftfont_info *ftfont_info;
1149 struct font *font;
1150 struct ftfont_cache_data *cache_data;
1151 FT_Face ft_face;
1152 FT_Size ft_size;
1153 FT_UInt size;
1154 Lisp_Object val, filename, index, cache, font_object;
1155 int scalable;
1156 int spacing;
1157 char name[256];
1158 int i, len;
1159 int upEM;
1160
1161 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
1162 if (! CONSP (val))
1163 return Qnil;
1164 val = XCDR (val);
1165 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_FACE);
1166 if (NILP (cache))
1167 return Qnil;
1168 filename = XCAR (val);
1169 index = XCDR (val);
1170 val = XCDR (cache);
1171 cache_data = XSAVE_VALUE (XCDR (cache))->pointer;
1172 ft_face = cache_data->ft_face;
1173 if (XSAVE_VALUE (val)->integer > 0)
1174 {
1175 /* FT_Face in this cache is already used by the different size. */
1176 if (FT_New_Size (ft_face, &ft_size) != 0)
1177 return Qnil;
1178 if (FT_Activate_Size (ft_size) != 0)
1179 {
1180 FT_Done_Size (ft_size);
1181 return Qnil;
1182 }
1183 }
1184 XSAVE_VALUE (val)->integer++;
1185 size = XINT (AREF (entity, FONT_SIZE_INDEX));
1186 if (size == 0)
1187 size = pixel_size;
1188 if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
1189 {
1190 if (XSAVE_VALUE (val)->integer == 0)
1191 FT_Done_Face (ft_face);
1192 return Qnil;
1193 }
1194
1195 font_object = font_make_object (VECSIZE (struct ftfont_info), entity, size);
1196 ASET (font_object, FONT_TYPE_INDEX, Qfreetype);
1197 len = font_unparse_xlfd (entity, size, name, 256);
1198 if (len > 0)
1199 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
1200 len = font_unparse_fcname (entity, size, name, 256);
1201 if (len > 0)
1202 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
1203 else
1204 ASET (font_object, FONT_FULLNAME_INDEX,
1205 AREF (font_object, FONT_NAME_INDEX));
1206 ASET (font_object, FONT_FILE_INDEX, filename);
1207 ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (NULL, filename));
1208 font = XFONT_OBJECT (font_object);
1209 ftfont_info = (struct ftfont_info *) font;
1210 ftfont_info->ft_size = ft_face->size;
1211 ftfont_info->index = XINT (index);
1212 #ifdef HAVE_LIBOTF
1213 ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
1214 ftfont_info->otf = NULL;
1215 #endif /* HAVE_LIBOTF */
1216 /* This means that there's no need of transformation. */
1217 ftfont_info->matrix.xx = 0;
1218 font->pixel_size = size;
1219 font->driver = &ftfont_driver;
1220 font->encoding_charset = font->repertory_charset = -1;
1221
1222 upEM = ft_face->units_per_EM;
1223 scalable = (INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
1224 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0);
1225 if (scalable)
1226 {
1227 font->ascent = ft_face->ascender * size / upEM;
1228 font->descent = - ft_face->descender * size / upEM;
1229 font->height = ft_face->height * size / upEM;
1230 }
1231 else
1232 {
1233 font->ascent = ft_face->size->metrics.ascender >> 6;
1234 font->descent = - ft_face->size->metrics.descender >> 6;
1235 font->height = ft_face->size->metrics.height >> 6;
1236 }
1237 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
1238 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
1239 else
1240 spacing = FC_PROPORTIONAL;
1241 if (spacing != FC_PROPORTIONAL && spacing != FC_DUAL)
1242 font->min_width = font->average_width = font->space_width
1243 = (scalable ? ft_face->max_advance_width * size / upEM
1244 : ft_face->size->metrics.max_advance >> 6);
1245 else
1246 {
1247 int n;
1248
1249 font->min_width = font->average_width = font->space_width = 0;
1250 for (i = 32, n = 0; i < 127; i++)
1251 if (FT_Load_Char (ft_face, i, FT_LOAD_DEFAULT) == 0)
1252 {
1253 int this_width = ft_face->glyph->metrics.horiAdvance >> 6;
1254
1255 if (this_width > 0
1256 && (! font->min_width || font->min_width > this_width))
1257 font->min_width = this_width;
1258 if (i == 32)
1259 font->space_width = this_width;
1260 font->average_width += this_width;
1261 n++;
1262 }
1263 if (n > 0)
1264 font->average_width /= n;
1265 }
1266
1267 font->baseline_offset = 0;
1268 font->relative_compose = 0;
1269 font->default_ascent = 0;
1270 font->vertical_centering = 0;
1271 if (scalable)
1272 {
1273 font->underline_position = -ft_face->underline_position * size / upEM;
1274 font->underline_thickness = ft_face->underline_thickness * size / upEM;
1275 }
1276 else
1277 {
1278 font->underline_position = -1;
1279 font->underline_thickness = 0;
1280 }
1281
1282 return font_object;
1283 }
1284
1285 static void
1286 ftfont_close (FRAME_PTR f, struct font *font)
1287 {
1288 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1289 Lisp_Object val, cache;
1290
1291 val = Fcons (font->props[FONT_FILE_INDEX], make_number (ftfont_info->index));
1292 cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE);
1293 xassert (CONSP (cache));
1294 val = XCDR (cache);
1295 (XSAVE_VALUE (val)->integer)--;
1296 if (XSAVE_VALUE (val)->integer == 0)
1297 {
1298 struct ftfont_cache_data *cache_data = XSAVE_VALUE (val)->pointer;
1299
1300 FT_Done_Face (cache_data->ft_face);
1301 #ifdef HAVE_LIBOTF
1302 if (ftfont_info->otf)
1303 OTF_close (ftfont_info->otf);
1304 #endif
1305 cache_data->ft_face = NULL;
1306 }
1307 else
1308 FT_Done_Size (ftfont_info->ft_size);
1309 }
1310
1311 static int
1312 ftfont_has_char (Lisp_Object font, int c)
1313 {
1314 struct charset *cs = NULL;
1315
1316 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
1317 && charset_jisx0208 >= 0)
1318 cs = CHARSET_FROM_ID (charset_jisx0208);
1319 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
1320 && charset_ksc5601 >= 0)
1321 cs = CHARSET_FROM_ID (charset_ksc5601);
1322 if (cs)
1323 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
1324
1325 if (FONT_ENTITY_P (font))
1326 {
1327 FcCharSet *charset = ftfont_get_fc_charset (font);
1328
1329 return (FcCharSetHasChar (charset, c) == FcTrue);
1330 }
1331 else
1332 {
1333 struct ftfont_info *ftfont_info;
1334
1335 ftfont_info = (struct ftfont_info *) XFONT_OBJECT (font);
1336 return (FT_Get_Char_Index (ftfont_info->ft_size->face, (FT_ULong) c)
1337 != 0);
1338 }
1339 }
1340
1341 static unsigned
1342 ftfont_encode_char (struct font *font, int c)
1343 {
1344 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1345 FT_Face ft_face = ftfont_info->ft_size->face;
1346 FT_ULong charcode = c;
1347 FT_UInt code = FT_Get_Char_Index (ft_face, charcode);
1348
1349 return (code > 0 ? code : FONT_INVALID_CODE);
1350 }
1351
1352 static int
1353 ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
1354 {
1355 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1356 FT_Face ft_face = ftfont_info->ft_size->face;
1357 int width = 0;
1358 int i, first;
1359
1360 if (ftfont_info->ft_size != ft_face->size)
1361 FT_Activate_Size (ftfont_info->ft_size);
1362 if (metrics)
1363 memset (metrics, 0, sizeof (struct font_metrics));
1364 for (i = 0, first = 1; i < nglyphs; i++)
1365 {
1366 if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0)
1367 {
1368 FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
1369
1370 if (first)
1371 {
1372 if (metrics)
1373 {
1374 metrics->lbearing = m->horiBearingX >> 6;
1375 metrics->rbearing = (m->horiBearingX + m->width) >> 6;
1376 metrics->ascent = m->horiBearingY >> 6;
1377 metrics->descent = (m->height - m->horiBearingY) >> 6;
1378 }
1379 first = 0;
1380 }
1381 if (metrics)
1382 {
1383 if (metrics->lbearing > width + (m->horiBearingX >> 6))
1384 metrics->lbearing = width + (m->horiBearingX >> 6);
1385 if (metrics->rbearing
1386 < width + ((m->horiBearingX + m->width) >> 6))
1387 metrics->rbearing
1388 = width + ((m->horiBearingX + m->width) >> 6);
1389 if (metrics->ascent < (m->horiBearingY >> 6))
1390 metrics->ascent = m->horiBearingY >> 6;
1391 if (metrics->descent > ((m->height - m->horiBearingY) >> 6))
1392 metrics->descent = (m->height - m->horiBearingY) >> 6;
1393 }
1394 width += m->horiAdvance >> 6;
1395 }
1396 else
1397 {
1398 width += font->space_width;
1399 }
1400 }
1401 if (metrics)
1402 metrics->width = width;
1403
1404 return width;
1405 }
1406
1407 static int
1408 ftfont_get_bitmap (struct font *font, unsigned int code, struct font_bitmap *bitmap, int bits_per_pixel)
1409 {
1410 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1411 FT_Face ft_face = ftfont_info->ft_size->face;
1412 FT_Int32 load_flags = FT_LOAD_RENDER;
1413
1414 if (ftfont_info->ft_size != ft_face->size)
1415 FT_Activate_Size (ftfont_info->ft_size);
1416 if (bits_per_pixel == 1)
1417 {
1418 #ifdef FT_LOAD_TARGET_MONO
1419 load_flags |= FT_LOAD_TARGET_MONO;
1420 #else
1421 load_flags |= FT_LOAD_MONOCHROME;
1422 #endif
1423 }
1424 else if (bits_per_pixel != 8)
1425 /* We don't support such a rendering. */
1426 return -1;
1427
1428 if (FT_Load_Glyph (ft_face, code, load_flags) != 0)
1429 return -1;
1430 bitmap->bits_per_pixel
1431 = (ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 1
1432 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY ? 8
1433 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD ? 8
1434 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V ? 8
1435 : -1);
1436 if (bitmap->bits_per_pixel < 0)
1437 /* We don't suport that kind of pixel mode. */
1438 return -1;
1439 bitmap->rows = ft_face->glyph->bitmap.rows;
1440 bitmap->width = ft_face->glyph->bitmap.width;
1441 bitmap->pitch = ft_face->glyph->bitmap.pitch;
1442 bitmap->buffer = ft_face->glyph->bitmap.buffer;
1443 bitmap->left = ft_face->glyph->bitmap_left;
1444 bitmap->top = ft_face->glyph->bitmap_top;
1445 bitmap->advance = ft_face->glyph->metrics.horiAdvance >> 6;
1446 bitmap->extra = NULL;
1447
1448 return 0;
1449 }
1450
1451 static int
1452 ftfont_anchor_point (struct font *font, unsigned int code, int index, int *x, int *y)
1453 {
1454 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1455 FT_Face ft_face = ftfont_info->ft_size->face;
1456
1457 if (ftfont_info->ft_size != ft_face->size)
1458 FT_Activate_Size (ftfont_info->ft_size);
1459 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
1460 return -1;
1461 if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
1462 return -1;
1463 if (index >= ft_face->glyph->outline.n_points)
1464 return -1;
1465 *x = ft_face->glyph->outline.points[index].x;
1466 *y = ft_face->glyph->outline.points[index].y;
1467 return 0;
1468 }
1469
1470 #ifdef HAVE_LIBOTF
1471
1472 static Lisp_Object
1473 ftfont_otf_features (OTF_GSUB_GPOS *gsub_gpos)
1474 {
1475 Lisp_Object scripts, langsyses, features, sym;
1476 int i, j, k, l;
1477
1478 for (scripts = Qnil, i = gsub_gpos->ScriptList.ScriptCount - 1; i >= 0; i--)
1479 {
1480 OTF_Script *otf_script = gsub_gpos->ScriptList.Script + i;
1481
1482 for (langsyses = Qnil, j = otf_script->LangSysCount - 1; j >= -1; j--)
1483 {
1484 OTF_LangSys *otf_langsys;
1485
1486 if (j >= 0)
1487 otf_langsys = otf_script->LangSys + j;
1488 else if (otf_script->DefaultLangSysOffset)
1489 otf_langsys = &otf_script->DefaultLangSys;
1490 else
1491 break;
1492
1493 for (features = Qnil, k = otf_langsys->FeatureCount - 1; k >= 0; k--)
1494 {
1495 l = otf_langsys->FeatureIndex[k];
1496 if (l >= gsub_gpos->FeatureList.FeatureCount)
1497 continue;
1498 OTF_TAG_SYM (sym, gsub_gpos->FeatureList.Feature[l].FeatureTag);
1499 features = Fcons (sym, features);
1500 }
1501 if (j >= 0)
1502 OTF_TAG_SYM (sym, otf_script->LangSysRecord[j].LangSysTag);
1503 else
1504 sym = Qnil;
1505 langsyses = Fcons (Fcons (sym, features), langsyses);
1506 }
1507
1508 OTF_TAG_SYM (sym, gsub_gpos->ScriptList.Script[i].ScriptTag);
1509 scripts = Fcons (Fcons (sym, langsyses), scripts);
1510 }
1511 return scripts;
1512
1513 }
1514
1515
1516 static Lisp_Object
1517 ftfont_otf_capability (struct font *font)
1518 {
1519 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1520 OTF *otf = ftfont_get_otf (ftfont_info);
1521 Lisp_Object gsub_gpos;
1522
1523 if (! otf)
1524 return Qnil;
1525 gsub_gpos = Fcons (Qnil, Qnil);
1526 if (OTF_get_table (otf, "GSUB") == 0
1527 && otf->gsub->FeatureList.FeatureCount > 0)
1528 XSETCAR (gsub_gpos, ftfont_otf_features (otf->gsub));
1529 if (OTF_get_table (otf, "GPOS") == 0
1530 && otf->gpos->FeatureList.FeatureCount > 0)
1531 XSETCDR (gsub_gpos, ftfont_otf_features (otf->gpos));
1532 return gsub_gpos;
1533 }
1534
1535 #ifdef HAVE_M17N_FLT
1536
1537 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1538 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1539 /* We can use the new feature of libotf and m17n-flt to handle the
1540 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1541 some Agian scripts. */
1542 #define M17N_FLT_USE_NEW_FEATURE
1543 #endif
1544
1545 struct MFLTFontFT
1546 {
1547 MFLTFont flt_font;
1548 struct font *font;
1549 FT_Face ft_face;
1550 OTF *otf;
1551 FT_Matrix *matrix;
1552 };
1553
1554 static int
1555 ftfont_get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring,
1556 int from, int to)
1557 {
1558 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1559 FT_Face ft_face = flt_font_ft->ft_face;
1560 MFLTGlyph *g;
1561
1562 for (g = gstring->glyphs + from; from < to; g++, from++)
1563 if (! g->encoded)
1564 {
1565 FT_UInt code = FT_Get_Char_Index (ft_face, g->code);
1566
1567 g->code = code > 0 ? code : FONT_INVALID_CODE;
1568 g->encoded = 1;
1569 }
1570 return 0;
1571 }
1572
1573 /* Operators for 26.6 fixed fractional pixel format */
1574
1575 #define FLOOR(x) ((x) & -64)
1576 #define CEIL(x) (((x)+63) & -64)
1577 #define ROUND(x) (((x)+32) & -64)
1578
1579 static int
1580 ftfont_get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
1581 int from, int to)
1582 {
1583 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1584 FT_Face ft_face = flt_font_ft->ft_face;
1585 MFLTGlyph *g;
1586
1587 for (g = gstring->glyphs + from; from < to; g++, from++)
1588 if (! g->measured)
1589 {
1590 if (g->code != FONT_INVALID_CODE)
1591 {
1592 FT_Glyph_Metrics *m;
1593 int lbearing, rbearing, ascent, descent, xadv;
1594
1595 if (FT_Load_Glyph (ft_face, g->code, FT_LOAD_DEFAULT) != 0)
1596 abort ();
1597 m = &ft_face->glyph->metrics;
1598 if (flt_font_ft->matrix)
1599 {
1600 FT_Vector v[4];
1601 int i;
1602
1603 v[0].x = v[1].x = m->horiBearingX;
1604 v[2].x = v[3].x = m->horiBearingX + m->width;
1605 v[0].y = v[2].y = m->horiBearingY;
1606 v[1].y = v[3].y = m->horiBearingY - m->height;
1607 for (i = 0; i < 4; i++)
1608 FT_Vector_Transform (v + i, flt_font_ft->matrix);
1609 g->lbearing = v[0].x < v[1].x ? FLOOR (v[0].x) : FLOOR (v[1].x);
1610 g->rbearing = v[2].x > v[3].x ? CEIL (v[2].x) : CEIL (v[3].x);
1611 g->ascent = v[0].y > v[2].y ? CEIL (v[0].y) : CEIL (v[2].y);
1612 g->descent = v[1].y < v[3].y ? - FLOOR (v[1].y) : - FLOOR (v[3].y);
1613 }
1614 else
1615 {
1616 g->lbearing = FLOOR (m->horiBearingX);
1617 g->rbearing = CEIL (m->horiBearingX + m->width);
1618 g->ascent = CEIL (m->horiBearingY);
1619 g->descent = - FLOOR (m->horiBearingY - m->height);
1620 }
1621 g->xadv = ROUND (ft_face->glyph->advance.x);
1622 }
1623 else
1624 {
1625 g->lbearing = 0;
1626 g->rbearing = g->xadv = flt_font_ft->font->space_width << 6;
1627 g->ascent = flt_font_ft->font->ascent << 6;
1628 g->descent = flt_font_ft->font->descent << 6;
1629 }
1630 g->yadv = 0;
1631 g->measured = 1;
1632 }
1633 return 0;
1634 }
1635
1636 static int
1637 ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1638 {
1639 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1640 OTF *otf = flt_font_ft->otf;
1641 OTF_Tag *tags;
1642 int i, n, negative;
1643
1644 for (i = 0; i < 2; i++)
1645 {
1646 if (! spec->features[i])
1647 continue;
1648 for (n = 0; spec->features[i][n]; n++);
1649 tags = alloca (sizeof (OTF_Tag) * n);
1650 for (n = 0, negative = 0; spec->features[i][n]; n++)
1651 {
1652 if (spec->features[i][n] == 0xFFFFFFFF)
1653 negative = 1;
1654 else if (negative)
1655 tags[n - 1] = spec->features[i][n] | 0x80000000;
1656 else
1657 tags[n] = spec->features[i][n];
1658 }
1659 #ifdef M17N_FLT_USE_NEW_FEATURE
1660 if (OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1661 tags, n - negative) != 1)
1662 return 0;
1663 #else /* not M17N_FLT_USE_NEW_FEATURE */
1664 if (n - negative > 0
1665 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1666 tags, n - negative) != 1)
1667 return 0;
1668 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1669 }
1670 return 1;
1671 }
1672
1673 #define DEVICE_DELTA(table, size) \
1674 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1675 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1676 : 0)
1677
1678 static void
1679 adjust_anchor (FT_Face ft_face, OTF_Anchor *anchor,
1680 unsigned code, int x_ppem, int y_ppem, int *x, int *y)
1681 {
1682 if (anchor->AnchorFormat == 2)
1683 {
1684 FT_Outline *outline;
1685 int ap = anchor->f.f1.AnchorPoint;
1686
1687 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
1688 outline = &ft_face->glyph->outline;
1689 if (ap < outline->n_points)
1690 {
1691 *x = outline->points[ap].x << 6;
1692 *y = outline->points[ap].y << 6;
1693 }
1694 }
1695 else if (anchor->AnchorFormat == 3)
1696 {
1697 if (anchor->f.f2.XDeviceTable.offset
1698 && anchor->f.f2.XDeviceTable.DeltaValue)
1699 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
1700 if (anchor->f.f2.YDeviceTable.offset
1701 && anchor->f.f2.YDeviceTable.DeltaValue)
1702 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
1703 }
1704 }
1705
1706 static OTF_GlyphString otf_gstring;
1707
1708 static void
1709 setup_otf_gstring (int size)
1710 {
1711 if (otf_gstring.size == 0)
1712 {
1713 otf_gstring.glyphs = (OTF_Glyph *) xmalloc (sizeof (OTF_Glyph) * size);
1714 otf_gstring.size = size;
1715 }
1716 else if (otf_gstring.size < size)
1717 {
1718 otf_gstring.glyphs = xrealloc (otf_gstring.glyphs,
1719 sizeof (OTF_Glyph) * size);
1720 otf_gstring.size = size;
1721 }
1722 otf_gstring.used = size;
1723 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size);
1724 }
1725
1726 #ifdef M17N_FLT_USE_NEW_FEATURE
1727
1728 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1729 #define PACK_OTF_TAG(TAG) \
1730 ((((TAG) & 0x7F000000) >> 3) \
1731 | (((TAG) & 0x7F0000) >> 2) \
1732 | (((TAG) & 0x7F00) >> 1) \
1733 | ((TAG) & 0x7F))
1734
1735 /* Assuming that FONT is an OpenType font, apply OpenType features
1736 specified in SPEC on glyphs between FROM and TO of IN, and record
1737 the lastly applied feature in each glyph of IN. If OUT is not
1738 NULL, append the resulting glyphs to OUT while storing glyph
1739 position adjustment information in ADJUSTMENT. */
1740
1741 static int
1742 ftfont_drive_otf (font, spec, in, from, to, out, adjustment)
1743 MFLTFont *font;
1744 MFLTOtfSpec *spec;
1745 MFLTGlyphString *in;
1746 int from, to;
1747 MFLTGlyphString *out;
1748 MFLTGlyphAdjustment *adjustment;
1749 {
1750 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1751 FT_Face ft_face = flt_font_ft->ft_face;
1752 OTF *otf = flt_font_ft->otf;
1753 int len = to - from;
1754 int i, j, gidx;
1755 OTF_Glyph *otfg;
1756 char script[5], *langsys = NULL;
1757 char *gsub_features = NULL, *gpos_features = NULL;
1758 OTF_Feature *features;
1759
1760 if (len == 0)
1761 return from;
1762 OTF_tag_name (spec->script, script);
1763 if (spec->langsys)
1764 {
1765 langsys = alloca (5);
1766 OTF_tag_name (spec->langsys, langsys);
1767 }
1768 for (i = 0; i < 2; i++)
1769 {
1770 char *p;
1771
1772 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
1773 {
1774 for (j = 0; spec->features[i][j]; j++);
1775 if (i == 0)
1776 p = gsub_features = alloca (6 * j);
1777 else
1778 p = gpos_features = alloca (6 * j);
1779 for (j = 0; spec->features[i][j]; j++)
1780 {
1781 if (spec->features[i][j] == 0xFFFFFFFF)
1782 *p++ = '*', *p++ = ',';
1783 else
1784 {
1785 OTF_tag_name (spec->features[i][j], p);
1786 p[4] = ',';
1787 p += 5;
1788 }
1789 }
1790 *--p = '\0';
1791 }
1792 }
1793
1794 setup_otf_gstring (len);
1795 for (i = 0; i < len; i++)
1796 {
1797 otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
1798 otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code;
1799 }
1800
1801 OTF_drive_gdef (otf, &otf_gstring);
1802 gidx = out ? out->used : from;
1803
1804 if (gsub_features && out)
1805 {
1806 if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
1807 gsub_features) < 0)
1808 goto simple_copy;
1809 if (out->allocated < out->used + otf_gstring.used)
1810 return -2;
1811 features = otf->gsub->FeatureList.Feature;
1812 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
1813 {
1814 MFLTGlyph *g;
1815 int min_from, max_to;
1816 int j;
1817 int feature_idx = otfg->positioning_type >> 4;
1818
1819 g = out->glyphs + out->used;
1820 *g = in->glyphs[from + otfg->f.index.from];
1821 if (g->code != otfg->glyph_id)
1822 {
1823 g->c = 0;
1824 g->code = otfg->glyph_id;
1825 g->measured = 0;
1826 }
1827 out->used++;
1828 min_from = g->from;
1829 max_to = g->to;
1830 if (otfg->f.index.from < otfg->f.index.to)
1831 {
1832 /* OTFG substitutes multiple glyphs in IN. */
1833 for (j = from + otfg->f.index.from + 1;
1834 j <= from + otfg->f.index.to; j++)
1835 {
1836 if (min_from > in->glyphs[j].from)
1837 min_from = in->glyphs[j].from;
1838 if (max_to < in->glyphs[j].to)
1839 max_to = in->glyphs[j].to;
1840 }
1841 g->from = min_from;
1842 g->to = max_to;
1843 }
1844 if (feature_idx)
1845 {
1846 unsigned int tag = features[feature_idx - 1].FeatureTag;
1847 tag = PACK_OTF_TAG (tag);
1848 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1849 }
1850 for (i++, otfg++; (i < otf_gstring.used
1851 && otfg->f.index.from == otfg[-1].f.index.from);
1852 i++, otfg++)
1853 {
1854 g = out->glyphs + out->used;
1855 *g = in->glyphs[from + otfg->f.index.to];
1856 if (g->code != otfg->glyph_id)
1857 {
1858 g->c = 0;
1859 g->code = otfg->glyph_id;
1860 g->measured = 0;
1861 }
1862 feature_idx = otfg->positioning_type >> 4;
1863 if (feature_idx)
1864 {
1865 unsigned int tag = features[feature_idx - 1].FeatureTag;
1866 tag = PACK_OTF_TAG (tag);
1867 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1868 }
1869 out->used++;
1870 }
1871 }
1872 }
1873 else if (gsub_features)
1874 {
1875 /* Just for checking which features will be applied. */
1876 if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
1877 gsub_features) < 0)
1878 goto simple_copy;
1879 features = otf->gsub->FeatureList.Feature;
1880 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++,
1881 otfg++)
1882 {
1883 int feature_idx = otfg->positioning_type >> 4;
1884
1885 if (feature_idx)
1886 {
1887 unsigned int tag = features[feature_idx - 1].FeatureTag;
1888 tag = PACK_OTF_TAG (tag);
1889 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
1890 {
1891 MFLTGlyph *g = in->glyphs + (from + j);
1892 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1893 }
1894 }
1895 }
1896 }
1897 else if (out)
1898 {
1899 if (out->allocated < out->used + len)
1900 return -2;
1901 for (i = 0; i < len; i++)
1902 out->glyphs[out->used++] = in->glyphs[from + i];
1903 }
1904
1905 if (gpos_features && out)
1906 {
1907 MFLTGlyph *base = NULL, *mark = NULL, *g;
1908 int x_ppem, y_ppem, x_scale, y_scale;
1909
1910 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
1911 gpos_features) < 0)
1912 return to;
1913 features = otf->gpos->FeatureList.Feature;
1914 x_ppem = ft_face->size->metrics.x_ppem;
1915 y_ppem = ft_face->size->metrics.y_ppem;
1916 x_scale = ft_face->size->metrics.x_scale;
1917 y_scale = ft_face->size->metrics.y_scale;
1918
1919 for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx;
1920 i < otf_gstring.used; i++, otfg++, g++)
1921 {
1922 MFLTGlyph *prev;
1923 int feature_idx = otfg->positioning_type >> 4;
1924
1925 if (feature_idx)
1926 {
1927 unsigned int tag = features[feature_idx - 1].FeatureTag;
1928 tag = PACK_OTF_TAG (tag);
1929 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1930 }
1931
1932 if (! otfg->glyph_id)
1933 continue;
1934 switch (otfg->positioning_type & 0xF)
1935 {
1936 case 0:
1937 break;
1938 case 1: /* Single */
1939 case 2: /* Pair */
1940 {
1941 int format = otfg->f.f1.format;
1942
1943 if (format & OTF_XPlacement)
1944 adjustment[i].xoff
1945 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
1946 if (format & OTF_XPlaDevice)
1947 adjustment[i].xoff
1948 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
1949 if (format & OTF_YPlacement)
1950 adjustment[i].yoff
1951 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
1952 if (format & OTF_YPlaDevice)
1953 adjustment[i].yoff
1954 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
1955 if (format & OTF_XAdvance)
1956 adjustment[i].xadv
1957 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
1958 if (format & OTF_XAdvDevice)
1959 adjustment[i].xadv
1960 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
1961 if (format & OTF_YAdvance)
1962 adjustment[i].yadv
1963 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
1964 if (format & OTF_YAdvDevice)
1965 adjustment[i].yadv
1966 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
1967 adjustment[i].set = 1;
1968 }
1969 break;
1970 case 3: /* Cursive */
1971 /* Not yet supported. */
1972 break;
1973 case 4: /* Mark-to-Base */
1974 case 5: /* Mark-to-Ligature */
1975 if (! base)
1976 break;
1977 prev = base;
1978 goto label_adjust_anchor;
1979 default: /* i.e. case 6 Mark-to-Mark */
1980 if (! mark)
1981 break;
1982 prev = mark;
1983
1984 label_adjust_anchor:
1985 {
1986 int base_x, base_y, mark_x, mark_y;
1987 int this_from, this_to;
1988
1989 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
1990 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
1991 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
1992 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
1993
1994 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
1995 adjust_anchor (ft_face, otfg->f.f4.base_anchor,
1996 prev->code, x_ppem, y_ppem, &base_x, &base_y);
1997 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
1998 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->code,
1999 x_ppem, y_ppem, &mark_x, &mark_y);
2000 adjustment[i].xoff = (base_x - mark_x);
2001 adjustment[i].yoff = - (base_y - mark_y);
2002 adjustment[i].back = (g - prev);
2003 adjustment[i].xadv = 0;
2004 adjustment[i].advance_is_absolute = 1;
2005 adjustment[i].set = 1;
2006 this_from = g->from;
2007 this_to = g->to;
2008 for (j = 0; prev + j < g; j++)
2009 {
2010 if (this_from > prev[j].from)
2011 this_from = prev[j].from;
2012 if (this_to < prev[j].to)
2013 this_to = prev[j].to;
2014 }
2015 for (; prev <= g; prev++)
2016 {
2017 prev->from = this_from;
2018 prev->to = this_to;
2019 }
2020 }
2021 }
2022 if (otfg->GlyphClass == OTF_GlyphClass0)
2023 base = mark = g;
2024 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2025 mark = g;
2026 else
2027 base = g;
2028 }
2029 }
2030 else if (gpos_features)
2031 {
2032 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
2033 gpos_features) < 0)
2034 return to;
2035 features = otf->gpos->FeatureList.Feature;
2036 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
2037 i++, otfg++)
2038 if (otfg->positioning_type & 0xF)
2039 {
2040 int feature_idx = otfg->positioning_type >> 4;
2041
2042 if (feature_idx)
2043 {
2044 unsigned int tag = features[feature_idx - 1].FeatureTag;
2045 tag = PACK_OTF_TAG (tag);
2046 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
2047 {
2048 MFLTGlyph *g = in->glyphs + (from + j);
2049 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
2050 }
2051 }
2052 }
2053 }
2054 return to;
2055
2056 simple_copy:
2057 if (! out)
2058 return to;
2059 if (out->allocated < out->used + len)
2060 return -2;
2061 font->get_metrics (font, in, from, to);
2062 memcpy (out->glyphs + out->used, in->glyphs + from,
2063 sizeof (MFLTGlyph) * len);
2064 out->used += len;
2065 return to;
2066 }
2067
2068 static int
2069 ftfont_try_otf (MFLTFont *font, MFLTOtfSpec *spec,
2070 MFLTGlyphString *in, int from, int to)
2071 {
2072 return ftfont_drive_otf (font, spec, in, from, to, NULL, NULL);
2073 }
2074
2075 #else /* not M17N_FLT_USE_NEW_FEATURE */
2076
2077 static int
2078 ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2079 int from, int to,
2080 MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
2081 {
2082 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
2083 FT_Face ft_face = flt_font_ft->ft_face;
2084 OTF *otf = flt_font_ft->otf;
2085 int len = to - from;
2086 int i, j, gidx;
2087 OTF_Glyph *otfg;
2088 char script[5], *langsys = NULL;
2089 char *gsub_features = NULL, *gpos_features = NULL;
2090
2091 if (len == 0)
2092 return from;
2093 OTF_tag_name (spec->script, script);
2094 if (spec->langsys)
2095 {
2096 langsys = alloca (5);
2097 OTF_tag_name (spec->langsys, langsys);
2098 }
2099 for (i = 0; i < 2; i++)
2100 {
2101 char *p;
2102
2103 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
2104 {
2105 for (j = 0; spec->features[i][j]; j++);
2106 if (i == 0)
2107 p = gsub_features = alloca (6 * j);
2108 else
2109 p = gpos_features = alloca (6 * j);
2110 for (j = 0; spec->features[i][j]; j++)
2111 {
2112 if (spec->features[i][j] == 0xFFFFFFFF)
2113 *p++ = '*', *p++ = ',';
2114 else
2115 {
2116 OTF_tag_name (spec->features[i][j], p);
2117 p[4] = ',';
2118 p += 5;
2119 }
2120 }
2121 *--p = '\0';
2122 }
2123 }
2124
2125 setup_otf_gstring (len);
2126 for (i = 0; i < len; i++)
2127 {
2128 otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
2129 otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code;
2130 }
2131
2132 OTF_drive_gdef (otf, &otf_gstring);
2133 gidx = out->used;
2134
2135 if (gsub_features)
2136 {
2137 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
2138 < 0)
2139 goto simple_copy;
2140 if (out->allocated < out->used + otf_gstring.used)
2141 return -2;
2142 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
2143 {
2144 MFLTGlyph *g;
2145 int min_from, max_to;
2146 int j;
2147
2148 g = out->glyphs + out->used;
2149 *g = in->glyphs[from + otfg->f.index.from];
2150 if (g->code != otfg->glyph_id)
2151 {
2152 g->c = 0;
2153 g->code = otfg->glyph_id;
2154 g->measured = 0;
2155 }
2156 out->used++;
2157 min_from = g->from;
2158 max_to = g->to;
2159 if (otfg->f.index.from < otfg->f.index.to)
2160 {
2161 /* OTFG substitutes multiple glyphs in IN. */
2162 for (j = from + otfg->f.index.from + 1;
2163 j <= from + otfg->f.index.to; j++)
2164 {
2165 if (min_from > in->glyphs[j].from)
2166 min_from = in->glyphs[j].from;
2167 if (max_to < in->glyphs[j].to)
2168 max_to = in->glyphs[j].to;
2169 }
2170 g->from = min_from;
2171 g->to = max_to;
2172 }
2173 for (i++, otfg++; (i < otf_gstring.used
2174 && otfg->f.index.from == otfg[-1].f.index.from);
2175 i++, otfg++)
2176 {
2177 g = out->glyphs + out->used;
2178 *g = in->glyphs[from + otfg->f.index.to];
2179 if (g->code != otfg->glyph_id)
2180 {
2181 g->c = 0;
2182 g->code = otfg->glyph_id;
2183 g->measured = 0;
2184 }
2185 out->used++;
2186 }
2187 }
2188 }
2189 else
2190 {
2191 if (out->allocated < out->used + len)
2192 return -2;
2193 for (i = 0; i < len; i++)
2194 out->glyphs[out->used++] = in->glyphs[from + i];
2195 }
2196
2197 if (gpos_features)
2198 {
2199 MFLTGlyph *base = NULL, *mark = NULL, *g;
2200 int x_ppem, y_ppem, x_scale, y_scale;
2201
2202 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
2203 < 0)
2204 return to;
2205
2206 x_ppem = ft_face->size->metrics.x_ppem;
2207 y_ppem = ft_face->size->metrics.y_ppem;
2208 x_scale = ft_face->size->metrics.x_scale;
2209 y_scale = ft_face->size->metrics.y_scale;
2210
2211 for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx;
2212 i < otf_gstring.used; i++, otfg++, g++)
2213 {
2214 MFLTGlyph *prev;
2215
2216 if (! otfg->glyph_id)
2217 continue;
2218 switch (otfg->positioning_type)
2219 {
2220 case 0:
2221 break;
2222 case 1: /* Single */
2223 case 2: /* Pair */
2224 {
2225 int format = otfg->f.f1.format;
2226
2227 if (format & OTF_XPlacement)
2228 adjustment[i].xoff
2229 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
2230 if (format & OTF_XPlaDevice)
2231 adjustment[i].xoff
2232 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
2233 if (format & OTF_YPlacement)
2234 adjustment[i].yoff
2235 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
2236 if (format & OTF_YPlaDevice)
2237 adjustment[i].yoff
2238 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
2239 if (format & OTF_XAdvance)
2240 adjustment[i].xadv
2241 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
2242 if (format & OTF_XAdvDevice)
2243 adjustment[i].xadv
2244 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
2245 if (format & OTF_YAdvance)
2246 adjustment[i].yadv
2247 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
2248 if (format & OTF_YAdvDevice)
2249 adjustment[i].yadv
2250 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
2251 adjustment[i].set = 1;
2252 }
2253 break;
2254 case 3: /* Cursive */
2255 /* Not yet supported. */
2256 break;
2257 case 4: /* Mark-to-Base */
2258 case 5: /* Mark-to-Ligature */
2259 if (! base)
2260 break;
2261 prev = base;
2262 goto label_adjust_anchor;
2263 default: /* i.e. case 6 Mark-to-Mark */
2264 if (! mark)
2265 break;
2266 prev = mark;
2267
2268 label_adjust_anchor:
2269 {
2270 int base_x, base_y, mark_x, mark_y;
2271 int this_from, this_to;
2272
2273 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
2274 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
2275 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
2276 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
2277
2278 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2279 adjust_anchor (ft_face, otfg->f.f4.base_anchor,
2280 prev->code, x_ppem, y_ppem, &base_x, &base_y);
2281 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2282 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->code,
2283 x_ppem, y_ppem, &mark_x, &mark_y);
2284 adjustment[i].xoff = (base_x - mark_x);
2285 adjustment[i].yoff = - (base_y - mark_y);
2286 adjustment[i].back = (g - prev);
2287 adjustment[i].xadv = 0;
2288 adjustment[i].advance_is_absolute = 1;
2289 adjustment[i].set = 1;
2290 this_from = g->from;
2291 this_to = g->to;
2292 for (j = 0; prev + j < g; j++)
2293 {
2294 if (this_from > prev[j].from)
2295 this_from = prev[j].from;
2296 if (this_to < prev[j].to)
2297 this_to = prev[j].to;
2298 }
2299 for (; prev <= g; prev++)
2300 {
2301 prev->from = this_from;
2302 prev->to = this_to;
2303 }
2304 }
2305 }
2306 if (otfg->GlyphClass == OTF_GlyphClass0)
2307 base = mark = g;
2308 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2309 mark = g;
2310 else
2311 base = g;
2312 }
2313 }
2314 return to;
2315
2316 simple_copy:
2317 if (out->allocated < out->used + len)
2318 return -2;
2319 font->get_metrics (font, in, from, to);
2320 memcpy (out->glyphs + out->used, in->glyphs + from,
2321 sizeof (MFLTGlyph) * len);
2322 out->used += len;
2323 return to;
2324 }
2325
2326 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2327
2328 static MFLTGlyphString gstring;
2329
2330 static int m17n_flt_initialized;
2331
2332 static Lisp_Object
2333 ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
2334 FT_Face ft_face, OTF *otf, FT_Matrix *matrix)
2335 {
2336 EMACS_UINT len = LGSTRING_GLYPH_LEN (lgstring);
2337 EMACS_UINT i;
2338 struct MFLTFontFT flt_font_ft;
2339 MFLT *flt = NULL;
2340 int with_variation_selector = 0;
2341
2342 if (! m17n_flt_initialized)
2343 {
2344 M17N_INIT ();
2345 #ifdef M17N_FLT_USE_NEW_FEATURE
2346 mflt_enable_new_feature = 1;
2347 mflt_try_otf = ftfont_try_otf;
2348 #endif /* M17N_FLT_USE_NEW_FEATURE */
2349 m17n_flt_initialized = 1;
2350 }
2351
2352 for (i = 0; i < len; i++)
2353 {
2354 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
2355 int c;
2356
2357 if (NILP (g))
2358 break;
2359 c = LGLYPH_CHAR (g);
2360 if (CHAR_VARIATION_SELECTOR_P (c))
2361 with_variation_selector++;
2362 }
2363 len = i;
2364 if (with_variation_selector)
2365 {
2366 setup_otf_gstring (len);
2367 for (i = 0; i < len; i++)
2368 {
2369 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
2370
2371 otf_gstring.glyphs[i].c = LGLYPH_CHAR (g);
2372 otf_gstring.glyphs[i].f.index.from = LGLYPH_FROM (g);
2373 otf_gstring.glyphs[i].f.index.to = LGLYPH_TO (g);
2374 }
2375 OTF_drive_cmap (otf, &otf_gstring);
2376 for (i = 0; i < otf_gstring.used; i++)
2377 {
2378 OTF_Glyph *otfg = otf_gstring.glyphs + i;
2379 Lisp_Object g0 = LGSTRING_GLYPH (lgstring, otfg->f.index.from);
2380 Lisp_Object g1 = LGSTRING_GLYPH (lgstring, otfg->f.index.to);
2381
2382 LGLYPH_SET_CODE (g0, otfg->glyph_id);
2383 LGLYPH_SET_TO (g0, LGLYPH_TO (g1));
2384 LGSTRING_SET_GLYPH (lgstring, i, g0);
2385 }
2386 if (len > otf_gstring.used)
2387 {
2388 len = otf_gstring.used;
2389 LGSTRING_SET_GLYPH (lgstring, len, Qnil);
2390 }
2391 }
2392
2393 if (gstring.allocated == 0)
2394 {
2395 gstring.allocated = len * 2;
2396 gstring.glyph_size = sizeof (MFLTGlyph);
2397 gstring.glyphs = xmalloc (sizeof (MFLTGlyph) * gstring.allocated);
2398 }
2399 else if (gstring.allocated < len * 2)
2400 {
2401 gstring.allocated = len * 2;
2402 gstring.glyphs = xrealloc (gstring.glyphs,
2403 sizeof (MFLTGlyph) * gstring.allocated);
2404 }
2405 memset (gstring.glyphs, 0, sizeof (MFLTGlyph) * len);
2406 for (i = 0; i < len; i++)
2407 {
2408 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
2409
2410 gstring.glyphs[i].c = LGLYPH_CHAR (g);
2411 if (with_variation_selector)
2412 {
2413 gstring.glyphs[i].code = LGLYPH_CODE (g);
2414 gstring.glyphs[i].encoded = 1;
2415 }
2416 }
2417
2418 gstring.used = len;
2419 gstring.r2l = 0;
2420
2421 {
2422 Lisp_Object family = Ffont_get (LGSTRING_FONT (lgstring), QCfamily);
2423
2424 if (NILP (family))
2425 flt_font_ft.flt_font.family = Mnil;
2426 else
2427 flt_font_ft.flt_font.family
2428 = msymbol ((char *) SDATA (Fdowncase (SYMBOL_NAME (family))));
2429 }
2430 flt_font_ft.flt_font.x_ppem = ft_face->size->metrics.x_ppem;
2431 flt_font_ft.flt_font.y_ppem = ft_face->size->metrics.y_ppem;
2432 flt_font_ft.flt_font.get_glyph_id = ftfont_get_glyph_id;
2433 flt_font_ft.flt_font.get_metrics = ftfont_get_metrics;
2434 flt_font_ft.flt_font.check_otf = ftfont_check_otf;
2435 flt_font_ft.flt_font.drive_otf = ftfont_drive_otf;
2436 flt_font_ft.flt_font.internal = NULL;
2437 flt_font_ft.font = font;
2438 flt_font_ft.ft_face = ft_face;
2439 flt_font_ft.otf = otf;
2440 flt_font_ft.matrix = matrix->xx != 0 ? matrix : 0;
2441 if (len > 1
2442 && gstring.glyphs[1].c >= 0x300 && gstring.glyphs[1].c <= 0x36F)
2443 /* A little bit ad hoc. Perhaps, shaper must get script and
2444 language information, and select a proper flt for them
2445 here. */
2446 flt = mflt_get (msymbol ("combining"));
2447 for (i = 0; i < 3; i++)
2448 {
2449 int result = mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt);
2450 if (result != -2)
2451 break;
2452 gstring.allocated += gstring.allocated;
2453 gstring.glyphs = xrealloc (gstring.glyphs,
2454 sizeof (MFLTGlyph) * gstring.allocated);
2455 }
2456 if (gstring.used > LGSTRING_GLYPH_LEN (lgstring))
2457 return Qnil;
2458 for (i = 0; i < gstring.used; i++)
2459 {
2460 MFLTGlyph *g = gstring.glyphs + i;
2461
2462 g->from = LGLYPH_FROM (LGSTRING_GLYPH (lgstring, g->from));
2463 g->to = LGLYPH_TO (LGSTRING_GLYPH (lgstring, g->to));
2464 }
2465
2466 for (i = 0; i < gstring.used; i++)
2467 {
2468 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2469 MFLTGlyph *g = gstring.glyphs + i;
2470
2471 if (NILP (lglyph))
2472 {
2473 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
2474 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2475 }
2476 LGLYPH_SET_FROM (lglyph, g->from);
2477 LGLYPH_SET_TO (lglyph, g->to);
2478 LGLYPH_SET_CHAR (lglyph, g->c);
2479 LGLYPH_SET_CODE (lglyph, g->code);
2480 LGLYPH_SET_WIDTH (lglyph, g->xadv >> 6);
2481 LGLYPH_SET_LBEARING (lglyph, g->lbearing >> 6);
2482 LGLYPH_SET_RBEARING (lglyph, g->rbearing >> 6);
2483 LGLYPH_SET_ASCENT (lglyph, g->ascent >> 6);
2484 LGLYPH_SET_DESCENT (lglyph, g->descent >> 6);
2485 if (g->adjusted)
2486 {
2487 Lisp_Object vec;
2488
2489 vec = Fmake_vector (make_number (3), Qnil);
2490 ASET (vec, 0, make_number (g->xoff >> 6));
2491 ASET (vec, 1, make_number (g->yoff >> 6));
2492 ASET (vec, 2, make_number (g->xadv >> 6));
2493 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2494 }
2495 }
2496 return make_number (i);
2497 }
2498
2499 Lisp_Object
2500 ftfont_shape (Lisp_Object lgstring)
2501 {
2502 struct font *font;
2503 struct ftfont_info *ftfont_info;
2504 OTF *otf;
2505
2506 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2507 ftfont_info = (struct ftfont_info *) font;
2508 otf = ftfont_get_otf (ftfont_info);
2509 if (! otf)
2510 return make_number (0);
2511 return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf,
2512 &ftfont_info->matrix);
2513 }
2514
2515 #endif /* HAVE_M17N_FLT */
2516
2517 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2518
2519 static int
2520 ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
2521 {
2522 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
2523 OTF *otf = ftfont_get_otf (ftfont_info);
2524
2525 if (! otf)
2526 return 0;
2527 return OTF_get_variation_glyphs (otf, c, variations);
2528 }
2529
2530 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2531 #endif /* HAVE_LIBOTF */
2532
2533 Lisp_Object
2534 ftfont_font_format (FcPattern *pattern, Lisp_Object filename)
2535 {
2536 FcChar8 *str;
2537
2538 #ifdef FC_FONTFORMAT
2539 if (pattern)
2540 {
2541 if (FcPatternGetString (pattern, FC_FONTFORMAT, 0, &str) != FcResultMatch)
2542 return Qnil;
2543 if (strcmp ((char *) str, "TrueType") == 0)
2544 return intern ("truetype");
2545 if (strcmp ((char *) str, "Type 1") == 0)
2546 return intern ("type1");
2547 if (strcmp ((char *) str, "PCF") == 0)
2548 return intern ("pcf");
2549 if (strcmp ((char *) str, "BDF") == 0)
2550 return intern ("bdf");
2551 }
2552 #endif /* FC_FONTFORMAT */
2553 if (STRINGP (filename))
2554 {
2555 int len = SBYTES (filename);
2556
2557 if (len >= 4)
2558 {
2559 str = (FcChar8 *) (SDATA (filename) + len - 4);
2560 if (xstrcasecmp ((char *) str, ".ttf") == 0)
2561 return intern ("truetype");
2562 if (xstrcasecmp ((char *) str, ".pfb") == 0)
2563 return intern ("type1");
2564 if (xstrcasecmp ((char *) str, ".pcf") == 0)
2565 return intern ("pcf");
2566 if (xstrcasecmp ((char *) str, ".bdf") == 0)
2567 return intern ("bdf");
2568 }
2569 }
2570 return intern ("unknown");
2571 }
2572
2573 static const char *ftfont_booleans [] = {
2574 ":antialias",
2575 ":hinting",
2576 ":verticallayout",
2577 ":autohint",
2578 ":globaladvance",
2579 ":outline",
2580 ":scalable",
2581 ":minspace",
2582 ":embolden",
2583 NULL,
2584 };
2585
2586 static const char *ftfont_non_booleans [] = {
2587 ":family",
2588 ":familylang",
2589 ":style",
2590 ":stylelang",
2591 ":fullname",
2592 ":fullnamelang",
2593 ":slant",
2594 ":weight",
2595 ":size",
2596 ":width",
2597 ":aspect",
2598 ":pixelsize",
2599 ":spacing",
2600 ":foundry",
2601 ":hintstyle",
2602 ":file",
2603 ":index",
2604 ":ftface",
2605 ":rasterizer",
2606 ":scale",
2607 ":dpi",
2608 ":rgba",
2609 ":lcdfilter",
2610 ":charset",
2611 ":lang",
2612 ":fontversion",
2613 ":capability",
2614 NULL,
2615 };
2616
2617 static void
2618 ftfont_filter_properties (Lisp_Object font, Lisp_Object alist)
2619 {
2620 Lisp_Object it;
2621 int i;
2622
2623 /* Set boolean values to Qt or Qnil */
2624 for (i = 0; ftfont_booleans[i] != NULL; ++i)
2625 for (it = alist; ! NILP (it); it = XCDR (it))
2626 {
2627 Lisp_Object key = XCAR (XCAR (it));
2628 Lisp_Object val = XCDR (XCAR (it));
2629 char *keystr = SDATA (SYMBOL_NAME (key));
2630
2631 if (strcmp (ftfont_booleans[i], keystr) == 0)
2632 {
2633 char *str = SYMBOLP (val) ? SDATA (SYMBOL_NAME (val)) : NULL;
2634 if (INTEGERP (val)) str = XINT (val) != 0 ? "true" : "false";
2635 if (str == NULL) str = "true";
2636
2637 val = Qt;
2638 if (strcmp ("false", str) == 0 || strcmp ("False", str) == 0
2639 || strcmp ("FALSE", str) == 0 || strcmp ("FcFalse", str) == 0
2640 || strcmp ("off", str) == 0 || strcmp ("OFF", str) == 0
2641 || strcmp ("Off", str) == 0)
2642 val = Qnil;
2643 Ffont_put (font, key, val);
2644 }
2645 }
2646
2647 for (i = 0; ftfont_non_booleans[i] != NULL; ++i)
2648 for (it = alist; ! NILP (it); it = XCDR (it))
2649 {
2650 Lisp_Object key = XCAR (XCAR (it));
2651 Lisp_Object val = XCDR (XCAR (it));
2652 char *keystr = SDATA (SYMBOL_NAME (key));
2653 if (strcmp (ftfont_non_booleans[i], keystr) == 0)
2654 Ffont_put (font, key, val);
2655 }
2656 }
2657
2658
2659 void
2660 syms_of_ftfont (void)
2661 {
2662 DEFSYM (Qfreetype, "freetype");
2663 DEFSYM (Qmonospace, "monospace");
2664 DEFSYM (Qsans_serif, "sans-serif");
2665 DEFSYM (Qserif, "serif");
2666 DEFSYM (Qmono, "mono");
2667 DEFSYM (Qsans, "sans");
2668 DEFSYM (Qsans__serif, "sans serif");
2669
2670 staticpro (&freetype_font_cache);
2671 freetype_font_cache = Fcons (Qt, Qnil);
2672
2673 staticpro (&ftfont_generic_family_list);
2674 ftfont_generic_family_list
2675 = Fcons (Fcons (Qmonospace, Qt),
2676 Fcons (Fcons (Qsans_serif, Qt),
2677 Fcons (Fcons (Qsans, Qt), Qnil)));
2678
2679 staticpro (&ft_face_cache);
2680 ft_face_cache = Qnil;
2681
2682 ftfont_driver.type = Qfreetype;
2683 register_font_driver (&ftfont_driver, NULL);
2684 }
2685
2686 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
2687 (do not change this comment) */