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