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