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