* alloc.c, font.c, font.h, ftfont.c, ftxfont.c, macfont.m,
[bpt/emacs.git] / src / ftfont.c
CommitLineData
c2f5bfd6 1/* ftfont.c -- FreeType font driver.
ab422c4d 2 Copyright (C) 2006-2013 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
KH
56
57/* The actual structure for FreeType font that can be casted to struct
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;
1014 OTF *otf;
1015
1016 if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file)
1017 != FcResultMatch)
1018 continue;
1019 otf = OTF_open ((char *) file);
1020 if (! otf)
1021 continue;
1022 if (OTF_check_features (otf, 1,
1023 otspec->script_tag, otspec->langsys_tag,
1024 otspec->features[0],
1025 otspec->nfeatures[0]) != 1
1026 || OTF_check_features (otf, 0,
1027 otspec->script_tag, otspec->langsys_tag,
1028 otspec->features[1],
1029 otspec->nfeatures[1]) != 1)
1030 continue;
c2f5bfd6 1031 }
318548be 1032#endif /* HAVE_LIBOTF */
7c4bd58d
KH
1033 if (VECTORP (chars))
1034 {
d311d28c 1035 ptrdiff_t j;
7c4bd58d
KH
1036
1037 if (FcPatternGetCharSet (fontset->fonts[i], FC_CHARSET, 0, &charset)
1038 != FcResultMatch)
1039 continue;
1040 for (j = 0; j < ASIZE (chars); j++)
d311d28c 1041 if (TYPE_RANGED_INTEGERP (FcChar32, AREF (chars, j))
7c4bd58d
KH
1042 && FcCharSetHasChar (charset, XFASTINT (AREF (chars, j))))
1043 break;
1044 if (j == ASIZE (chars))
1045 continue;
1046 }
497e54d8 1047 if (! NILP (adstyle) || langname)
99c4d65d
KH
1048 {
1049 Lisp_Object this_adstyle = get_adstyle_property (fontset->fonts[i]);
1050
497e54d8
KH
1051 if (! NILP (adstyle)
1052 && (NILP (this_adstyle)
25a48bd0
PE
1053 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle)),
1054 SSDATA (SYMBOL_NAME (this_adstyle))) != 0))
497e54d8
KH
1055 continue;
1056 if (langname
1057 && ! NILP (this_adstyle)
25a48bd0 1058 && xstrcasecmp (langname, SSDATA (SYMBOL_NAME (this_adstyle))))
99c4d65d
KH
1059 continue;
1060 }
e302a291
KH
1061 entity = ftfont_pattern_entity (fontset->fonts[i],
1062 AREF (spec, FONT_EXTRA_INDEX));
318548be
KH
1063 if (! NILP (entity))
1064 val = Fcons (entity, val);
c2f5bfd6 1065 }
7c4bd58d 1066 val = Fnreverse (val);
c2f5bfd6
KH
1067 goto finish;
1068
1069 err:
1070 /* We come here because of unexpected error in fontconfig API call
706b6995 1071 (usually insufficient memory). */
c2f5bfd6
KH
1072 val = Qnil;
1073
1074 finish:
678dca3d 1075 FONT_ADD_LOG ("ftfont-list", spec, val);
c2f5bfd6
KH
1076 if (objset) FcObjectSetDestroy (objset);
1077 if (fontset) FcFontSetDestroy (fontset);
c2f5bfd6 1078 if (pattern) FcPatternDestroy (pattern);
c2f5bfd6
KH
1079 return val;
1080}
1081
8daf5667 1082static Lisp_Object
fdb396e2 1083ftfont_match (struct frame *f, Lisp_Object spec)
8daf5667 1084{
a3c15670 1085 Lisp_Object entity = Qnil;
42984a74 1086 FcPattern *pattern, *match = NULL;
8daf5667 1087 FcResult result;
42984a74
KH
1088 char otlayout[15]; /* For "otlayout:XXXX" */
1089 struct OpenTypeSpec *otspec = NULL;
675e2c69 1090 const char *langname = NULL;
8daf5667
KH
1091
1092 if (! fc_initialized)
1093 {
1094 FcInit ();
1095 fc_initialized = 1;
1096 }
1097
497e54d8 1098 pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
42984a74 1099 if (! pattern)
8daf5667
KH
1100 return Qnil;
1101
42984a74 1102 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
8daf5667 1103 {
42984a74 1104 FcValue value;
55082642 1105
42984a74
KH
1106 value.type = FcTypeDouble;
1107 value.u.d = XINT (AREF (spec, FONT_SIZE_INDEX));
1108 FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse);
1109 }
1110 if (FcConfigSubstitute (NULL, pattern, FcMatchPattern) == FcTrue)
1111 {
1112 FcDefaultSubstitute (pattern);
1113 match = FcFontMatch (NULL, pattern, &result);
1114 if (match)
8daf5667 1115 {
e302a291 1116 entity = ftfont_pattern_entity (match, AREF (spec, FONT_EXTRA_INDEX));
42984a74
KH
1117 FcPatternDestroy (match);
1118 if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
1119 && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
1120 ftfont_generic_family_list))
1121 && NILP (Fstring_equal (AREF (spec, FONT_FAMILY_INDEX),
1122 AREF (entity, FONT_FAMILY_INDEX))))
1123 entity = Qnil;
8daf5667 1124 }
8daf5667 1125 }
42984a74 1126 FcPatternDestroy (pattern);
8daf5667 1127
678dca3d 1128 FONT_ADD_LOG ("ftfont-match", spec, entity);
8daf5667
KH
1129 return entity;
1130}
1131
c2f5bfd6 1132static Lisp_Object
fdb396e2 1133ftfont_list_family (struct frame *f)
c2f5bfd6 1134{
76d126ec 1135 Lisp_Object list = Qnil;
c2f5bfd6
KH
1136 FcPattern *pattern = NULL;
1137 FcFontSet *fontset = NULL;
1138 FcObjectSet *objset = NULL;
1139 int i;
1140
1141 if (! fc_initialized)
1142 {
1143 FcInit ();
1144 fc_initialized = 1;
1145 }
1146
1147 pattern = FcPatternCreate ();
1148 if (! pattern)
1149 goto finish;
706b6995 1150 objset = FcObjectSetBuild (FC_FAMILY, NULL);
c2f5bfd6
KH
1151 if (! objset)
1152 goto finish;
1153 fontset = FcFontList (NULL, pattern, objset);
1154 if (! fontset)
1155 goto finish;
1156
c2f5bfd6
KH
1157 for (i = 0; i < fontset->nfont; i++)
1158 {
1159 FcPattern *pat = fontset->fonts[i];
1160 FcChar8 *str;
1161
1162 if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
42984a74 1163 list = Fcons (intern ((char *) str), list);
c2f5bfd6
KH
1164 }
1165
1166 finish:
1167 if (objset) FcObjectSetDestroy (objset);
1168 if (fontset) FcFontSetDestroy (fontset);
1169 if (pattern) FcPatternDestroy (pattern);
1170
1171 return list;
1172}
1173
1174
42984a74 1175static Lisp_Object
a10c8269 1176ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
c2f5bfd6
KH
1177{
1178 struct ftfont_info *ftfont_info;
1179 struct font *font;
e302a291 1180 struct ftfont_cache_data *cache_data;
c2f5bfd6
KH
1181 FT_Face ft_face;
1182 FT_Size ft_size;
1183 FT_UInt size;
49eaafba 1184 Lisp_Object val, filename, idx, cache, font_object;
a864ef14 1185 bool scalable;
c2f5bfd6 1186 int spacing;
42984a74
KH
1187 char name[256];
1188 int i, len;
1189 int upEM;
c2f5bfd6 1190
42984a74
KH
1191 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
1192 if (! CONSP (val))
1193 return Qnil;
1194 val = XCDR (val);
d7782105 1195 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_FACE);
21988a08
KH
1196 if (NILP (cache))
1197 return Qnil;
e302a291 1198 filename = XCAR (val);
49eaafba 1199 idx = XCDR (val);
21988a08 1200 val = XCDR (cache);
2b30549c 1201 cache_data = XSAVE_POINTER (XCDR (cache), 0);
e302a291 1202 ft_face = cache_data->ft_face;
2b30549c 1203 if (XSAVE_INTEGER (val, 1) > 0)
c2f5bfd6 1204 {
21988a08 1205 /* FT_Face in this cache is already used by the different size. */
c2f5bfd6 1206 if (FT_New_Size (ft_face, &ft_size) != 0)
42984a74 1207 return Qnil;
c2f5bfd6
KH
1208 if (FT_Activate_Size (ft_size) != 0)
1209 {
1210 FT_Done_Size (ft_size);
42984a74 1211 return Qnil;
c2f5bfd6 1212 }
21988a08 1213 }
7b1123d8 1214 set_save_integer (val, 1, XSAVE_INTEGER (val, 1) + 1);
c2f5bfd6
KH
1215 size = XINT (AREF (entity, FONT_SIZE_INDEX));
1216 if (size == 0)
1217 size = pixel_size;
1218 if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
1219 {
2b30549c 1220 if (XSAVE_INTEGER (val, 1) == 0)
c2f5bfd6 1221 FT_Done_Face (ft_face);
42984a74 1222 return Qnil;
c2f5bfd6
KH
1223 }
1224
e302a291 1225 font_object = font_make_object (VECSIZE (struct ftfont_info), entity, size);
42984a74 1226 ASET (font_object, FONT_TYPE_INDEX, Qfreetype);
42984a74
KH
1227 len = font_unparse_xlfd (entity, size, name, 256);
1228 if (len > 0)
3299c552 1229 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
42984a74
KH
1230 len = font_unparse_fcname (entity, size, name, 256);
1231 if (len > 0)
3299c552 1232 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
42984a74
KH
1233 else
1234 ASET (font_object, FONT_FULLNAME_INDEX,
1235 AREF (font_object, FONT_NAME_INDEX));
21988a08 1236 ASET (font_object, FONT_FILE_INDEX, filename);
7d7ad10e 1237 ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (NULL, filename));
42984a74
KH
1238 font = XFONT_OBJECT (font_object);
1239 ftfont_info = (struct ftfont_info *) font;
21988a08 1240 ftfont_info->ft_size = ft_face->size;
49eaafba 1241 ftfont_info->index = XINT (idx);
0d674a05 1242#ifdef HAVE_LIBOTF
a864ef14 1243 ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
de023c40 1244 ftfont_info->otf = NULL;
0d674a05 1245#endif /* HAVE_LIBOTF */
d0db2ec8
KH
1246 /* This means that there's no need of transformation. */
1247 ftfont_info->matrix.xx = 0;
c2f5bfd6
KH
1248 font->pixel_size = size;
1249 font->driver = &ftfont_driver;
42984a74 1250 font->encoding_charset = font->repertory_charset = -1;
c9c0c429 1251
42984a74 1252 upEM = ft_face->units_per_EM;
21988a08
KH
1253 scalable = (INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
1254 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0);
42984a74
KH
1255 if (scalable)
1256 {
1257 font->ascent = ft_face->ascender * size / upEM;
1258 font->descent = - ft_face->descender * size / upEM;
1259 font->height = ft_face->height * size / upEM;
1260 }
1261 else
1262 {
1263 font->ascent = ft_face->size->metrics.ascender >> 6;
1264 font->descent = - ft_face->size->metrics.descender >> 6;
1265 font->height = ft_face->size->metrics.height >> 6;
c9c0c429 1266 }
21988a08
KH
1267 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
1268 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
1269 else
c9c0c429 1270 spacing = FC_PROPORTIONAL;
ea2460a0
KH
1271 if (spacing != FC_PROPORTIONAL
1272#ifdef FC_DUAL
1273 && spacing != FC_DUAL
1274#endif /* FC_DUAL */
1275 )
42984a74
KH
1276 font->min_width = font->average_width = font->space_width
1277 = (scalable ? ft_face->max_advance_width * size / upEM
1278 : ft_face->size->metrics.max_advance >> 6);
c2f5bfd6
KH
1279 else
1280 {
42984a74 1281 int n;
c2f5bfd6 1282
42984a74
KH
1283 font->min_width = font->average_width = font->space_width = 0;
1284 for (i = 32, n = 0; i < 127; i++)
0c26f026 1285 if (FT_Load_Char (ft_face, i, FT_LOAD_DEFAULT) == 0)
42984a74
KH
1286 {
1287 int this_width = ft_face->glyph->metrics.horiAdvance >> 6;
1288
1289 if (this_width > 0
1290 && (! font->min_width || font->min_width > this_width))
1291 font->min_width = this_width;
1292 if (i == 32)
1293 font->space_width = this_width;
1294 font->average_width += this_width;
1295 n++;
1296 }
1297 if (n > 0)
1298 font->average_width /= n;
c2f5bfd6
KH
1299 }
1300
42984a74
KH
1301 font->baseline_offset = 0;
1302 font->relative_compose = 0;
1303 font->default_ascent = 0;
1304 font->vertical_centering = 0;
1305 if (scalable)
1306 {
1307 font->underline_position = -ft_face->underline_position * size / upEM;
0c26f026 1308 font->underline_thickness = ft_face->underline_thickness * size / upEM;
42984a74
KH
1309 }
1310 else
1311 {
1312 font->underline_position = -1;
1313 font->underline_thickness = 0;
1314 }
c2f5bfd6 1315
42984a74 1316 return font_object;
c2f5bfd6
KH
1317}
1318
1319static void
78e0b35c 1320ftfont_close (struct font *font)
c2f5bfd6
KH
1321{
1322 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
21988a08 1323 Lisp_Object val, cache;
c2f5bfd6 1324
e302a291 1325 val = Fcons (font->props[FONT_FILE_INDEX], make_number (ftfont_info->index));
d7782105 1326 cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE);
a54e2c05 1327 eassert (CONSP (cache));
21988a08 1328 val = XCDR (cache);
7b1123d8 1329 set_save_integer (val, 1, XSAVE_INTEGER (val, 1) - 1);
2b30549c 1330 if (XSAVE_INTEGER (val, 1) == 0)
de023c40 1331 {
2b30549c 1332 struct ftfont_cache_data *cache_data = XSAVE_POINTER (val, 0);
21988a08 1333
e302a291 1334 FT_Done_Face (cache_data->ft_face);
de023c40
KH
1335#ifdef HAVE_LIBOTF
1336 if (ftfont_info->otf)
1337 OTF_close (ftfont_info->otf);
1338#endif
e302a291 1339 cache_data->ft_face = NULL;
de023c40 1340 }
c2f5bfd6
KH
1341 else
1342 FT_Done_Size (ftfont_info->ft_size);
c2f5bfd6
KH
1343}
1344
2a46904e 1345static int
971de7fb 1346ftfont_has_char (Lisp_Object font, int c)
c2f5bfd6 1347{
d7782105
KH
1348 struct charset *cs = NULL;
1349
1350 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
1351 && charset_jisx0208 >= 0)
1352 cs = CHARSET_FROM_ID (charset_jisx0208);
1353 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
1354 && charset_ksc5601 >= 0)
1355 cs = CHARSET_FROM_ID (charset_ksc5601);
1356 if (cs)
1357 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
1358
7179ce7b
KH
1359 if (FONT_ENTITY_P (font))
1360 {
1361 FcCharSet *charset = ftfont_get_fc_charset (font);
c2f5bfd6 1362
7179ce7b
KH
1363 return (FcCharSetHasChar (charset, c) == FcTrue);
1364 }
1365 else
1366 {
1367 struct ftfont_info *ftfont_info;
1368
1369 ftfont_info = (struct ftfont_info *) XFONT_OBJECT (font);
1370 return (FT_Get_Char_Index (ftfont_info->ft_size->face, (FT_ULong) c)
1371 != 0);
1372 }
c2f5bfd6
KH
1373}
1374
1375static unsigned
971de7fb 1376ftfont_encode_char (struct font *font, int c)
c2f5bfd6
KH
1377{
1378 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1379 FT_Face ft_face = ftfont_info->ft_size->face;
1380 FT_ULong charcode = c;
1381 FT_UInt code = FT_Get_Char_Index (ft_face, charcode);
1382
4cec6061 1383 return (code > 0 ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
1384}
1385
1386static int
971de7fb 1387ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
c2f5bfd6
KH
1388{
1389 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1390 FT_Face ft_face = ftfont_info->ft_size->face;
1391 int width = 0;
a864ef14
PE
1392 int i;
1393 bool first;
c2f5bfd6
KH
1394
1395 if (ftfont_info->ft_size != ft_face->size)
1396 FT_Activate_Size (ftfont_info->ft_size);
1397 if (metrics)
72af86bd 1398 memset (metrics, 0, sizeof (struct font_metrics));
e5d05978 1399 for (i = 0, first = 1; i < nglyphs; i++)
c2f5bfd6
KH
1400 {
1401 if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0)
1402 {
1403 FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
1404
e5d05978
KH
1405 if (first)
1406 {
1407 if (metrics)
1408 {
1409 metrics->lbearing = m->horiBearingX >> 6;
1410 metrics->rbearing = (m->horiBearingX + m->width) >> 6;
1411 metrics->ascent = m->horiBearingY >> 6;
57d3b93b 1412 metrics->descent = (m->height - m->horiBearingY) >> 6;
e5d05978
KH
1413 }
1414 first = 0;
1415 }
c2f5bfd6
KH
1416 if (metrics)
1417 {
1418 if (metrics->lbearing > width + (m->horiBearingX >> 6))
1419 metrics->lbearing = width + (m->horiBearingX >> 6);
1420 if (metrics->rbearing
1421 < width + ((m->horiBearingX + m->width) >> 6))
1422 metrics->rbearing
1423 = width + ((m->horiBearingX + m->width) >> 6);
1424 if (metrics->ascent < (m->horiBearingY >> 6))
1425 metrics->ascent = m->horiBearingY >> 6;
57d3b93b
KH
1426 if (metrics->descent > ((m->height - m->horiBearingY) >> 6))
1427 metrics->descent = (m->height - m->horiBearingY) >> 6;
c2f5bfd6
KH
1428 }
1429 width += m->horiAdvance >> 6;
1430 }
1431 else
1432 {
42984a74 1433 width += font->space_width;
c2f5bfd6
KH
1434 }
1435 }
1436 if (metrics)
1437 metrics->width = width;
1438
1439 return width;
1440}
1441
1442static int
971de7fb 1443ftfont_get_bitmap (struct font *font, unsigned int code, struct font_bitmap *bitmap, int bits_per_pixel)
c2f5bfd6
KH
1444{
1445 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1446 FT_Face ft_face = ftfont_info->ft_size->face;
1447 FT_Int32 load_flags = FT_LOAD_RENDER;
1448
1449 if (ftfont_info->ft_size != ft_face->size)
1450 FT_Activate_Size (ftfont_info->ft_size);
1451 if (bits_per_pixel == 1)
1452 {
1453#ifdef FT_LOAD_TARGET_MONO
1454 load_flags |= FT_LOAD_TARGET_MONO;
1455#else
1456 load_flags |= FT_LOAD_MONOCHROME;
1457#endif
1458 }
1459 else if (bits_per_pixel != 8)
1460 /* We don't support such a rendering. */
1461 return -1;
1462
1463 if (FT_Load_Glyph (ft_face, code, load_flags) != 0)
1464 return -1;
b51e5112
KH
1465 bitmap->bits_per_pixel
1466 = (ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 1
1467 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY ? 8
1468 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD ? 8
1469 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V ? 8
1470 : -1);
1471 if (bitmap->bits_per_pixel < 0)
5c32d3f2 1472 /* We don't support that kind of pixel mode. */
b51e5112 1473 return -1;
c2f5bfd6
KH
1474 bitmap->rows = ft_face->glyph->bitmap.rows;
1475 bitmap->width = ft_face->glyph->bitmap.width;
1476 bitmap->pitch = ft_face->glyph->bitmap.pitch;
1477 bitmap->buffer = ft_face->glyph->bitmap.buffer;
1478 bitmap->left = ft_face->glyph->bitmap_left;
1479 bitmap->top = ft_face->glyph->bitmap_top;
1480 bitmap->advance = ft_face->glyph->metrics.horiAdvance >> 6;
c2f5bfd6
KH
1481
1482 return 0;
1483}
1484
1485static int
49eaafba
PE
1486ftfont_anchor_point (struct font *font, unsigned int code, int idx,
1487 int *x, int *y)
c2f5bfd6
KH
1488{
1489 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1490 FT_Face ft_face = ftfont_info->ft_size->face;
1491
1492 if (ftfont_info->ft_size != ft_face->size)
1493 FT_Activate_Size (ftfont_info->ft_size);
1494 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
1495 return -1;
1496 if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
1497 return -1;
49eaafba 1498 if (idx >= ft_face->glyph->outline.n_points)
c2f5bfd6 1499 return -1;
49eaafba
PE
1500 *x = ft_face->glyph->outline.points[idx].x;
1501 *y = ft_face->glyph->outline.points[idx].y;
c2f5bfd6
KH
1502 return 0;
1503}
1504
de023c40 1505#ifdef HAVE_LIBOTF
e302a291
KH
1506
1507static Lisp_Object
d5a3eaaf 1508ftfont_otf_features (OTF_GSUB_GPOS *gsub_gpos)
e302a291
KH
1509{
1510 Lisp_Object scripts, langsyses, features, sym;
39356621 1511 int i, j, k, l;
e302a291
KH
1512
1513 for (scripts = Qnil, i = gsub_gpos->ScriptList.ScriptCount - 1; i >= 0; i--)
1514 {
1515 OTF_Script *otf_script = gsub_gpos->ScriptList.Script + i;
1516
1517 for (langsyses = Qnil, j = otf_script->LangSysCount - 1; j >= -1; j--)
1518 {
1519 OTF_LangSys *otf_langsys;
1520
1521 if (j >= 0)
1522 otf_langsys = otf_script->LangSys + j;
1523 else if (otf_script->DefaultLangSysOffset)
1524 otf_langsys = &otf_script->DefaultLangSys;
1525 else
1526 break;
1527
1528 for (features = Qnil, k = otf_langsys->FeatureCount - 1; k >= 0; k--)
1529 {
39356621 1530 l = otf_langsys->FeatureIndex[k];
064766f2 1531 if (l >= gsub_gpos->FeatureList.FeatureCount)
39356621
KH
1532 continue;
1533 OTF_TAG_SYM (sym, gsub_gpos->FeatureList.Feature[l].FeatureTag);
e302a291
KH
1534 features = Fcons (sym, features);
1535 }
1536 if (j >= 0)
1537 OTF_TAG_SYM (sym, otf_script->LangSysRecord[j].LangSysTag);
1538 else
1539 sym = Qnil;
1540 langsyses = Fcons (Fcons (sym, features), langsyses);
1541 }
8510724d 1542
e302a291
KH
1543 OTF_TAG_SYM (sym, gsub_gpos->ScriptList.Script[i].ScriptTag);
1544 scripts = Fcons (Fcons (sym, langsyses), scripts);
1545 }
1546 return scripts;
1547
1548}
1549
1550
1551static Lisp_Object
d5a3eaaf 1552ftfont_otf_capability (struct font *font)
e302a291
KH
1553{
1554 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1555 OTF *otf = ftfont_get_otf (ftfont_info);
1556 Lisp_Object gsub_gpos;
1557
1558 if (! otf)
1559 return Qnil;
1560 gsub_gpos = Fcons (Qnil, Qnil);
064766f2
KH
1561 if (OTF_get_table (otf, "GSUB") == 0
1562 && otf->gsub->FeatureList.FeatureCount > 0)
e302a291 1563 XSETCAR (gsub_gpos, ftfont_otf_features (otf->gsub));
064766f2
KH
1564 if (OTF_get_table (otf, "GPOS") == 0
1565 && otf->gpos->FeatureList.FeatureCount > 0)
e302a291
KH
1566 XSETCDR (gsub_gpos, ftfont_otf_features (otf->gpos));
1567 return gsub_gpos;
1568}
1569
de023c40
KH
1570#ifdef HAVE_M17N_FLT
1571
c90ca7b7
KH
1572#if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1573 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
c4170e32
KH
1574/* We can use the new feature of libotf and m17n-flt to handle the
1575 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1576 some Agian scripts. */
1577#define M17N_FLT_USE_NEW_FEATURE
1578#endif
1579
de023c40
KH
1580struct MFLTFontFT
1581{
1582 MFLTFont flt_font;
1583 struct font *font;
1584 FT_Face ft_face;
1585 OTF *otf;
d0db2ec8 1586 FT_Matrix *matrix;
de023c40
KH
1587};
1588
1589static int
d5a3eaaf
AS
1590ftfont_get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring,
1591 int from, int to)
de023c40
KH
1592{
1593 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1594 FT_Face ft_face = flt_font_ft->ft_face;
1595 MFLTGlyph *g;
1596
1597 for (g = gstring->glyphs + from; from < to; g++, from++)
1598 if (! g->encoded)
1599 {
1600 FT_UInt code = FT_Get_Char_Index (ft_face, g->code);
1601
1602 g->code = code > 0 ? code : FONT_INVALID_CODE;
1603 g->encoded = 1;
1604 }
1605 return 0;
1606}
1607
d0db2ec8
KH
1608/* Operators for 26.6 fixed fractional pixel format */
1609
1610#define FLOOR(x) ((x) & -64)
1611#define CEIL(x) (((x)+63) & -64)
1612#define ROUND(x) (((x)+32) & -64)
1613
de023c40 1614static int
d5a3eaaf
AS
1615ftfont_get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
1616 int from, int to)
de023c40
KH
1617{
1618 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1619 FT_Face ft_face = flt_font_ft->ft_face;
1620 MFLTGlyph *g;
1621
1622 for (g = gstring->glyphs + from; from < to; g++, from++)
1623 if (! g->measured)
1624 {
1625 if (g->code != FONT_INVALID_CODE)
1626 {
1627 FT_Glyph_Metrics *m;
1628
1629 if (FT_Load_Glyph (ft_face, g->code, FT_LOAD_DEFAULT) != 0)
1088b922 1630 emacs_abort ();
de023c40 1631 m = &ft_face->glyph->metrics;
d0db2ec8
KH
1632 if (flt_font_ft->matrix)
1633 {
1634 FT_Vector v[4];
1635 int i;
1636
1637 v[0].x = v[1].x = m->horiBearingX;
1638 v[2].x = v[3].x = m->horiBearingX + m->width;
1639 v[0].y = v[2].y = m->horiBearingY;
1640 v[1].y = v[3].y = m->horiBearingY - m->height;
1641 for (i = 0; i < 4; i++)
1642 FT_Vector_Transform (v + i, flt_font_ft->matrix);
1643 g->lbearing = v[0].x < v[1].x ? FLOOR (v[0].x) : FLOOR (v[1].x);
1644 g->rbearing = v[2].x > v[3].x ? CEIL (v[2].x) : CEIL (v[3].x);
1645 g->ascent = v[0].y > v[2].y ? CEIL (v[0].y) : CEIL (v[2].y);
1646 g->descent = v[1].y < v[3].y ? - FLOOR (v[1].y) : - FLOOR (v[3].y);
1647 }
1648 else
1649 {
1650 g->lbearing = FLOOR (m->horiBearingX);
1651 g->rbearing = CEIL (m->horiBearingX + m->width);
1652 g->ascent = CEIL (m->horiBearingY);
1653 g->descent = - FLOOR (m->horiBearingY - m->height);
1654 }
1655 g->xadv = ROUND (ft_face->glyph->advance.x);
de023c40
KH
1656 }
1657 else
1658 {
1659 g->lbearing = 0;
42984a74 1660 g->rbearing = g->xadv = flt_font_ft->font->space_width << 6;
de023c40
KH
1661 g->ascent = flt_font_ft->font->ascent << 6;
1662 g->descent = flt_font_ft->font->descent << 6;
1663 }
1664 g->yadv = 0;
1665 g->measured = 1;
1666 }
1667 return 0;
1668}
1669
2a46904e 1670static int
de023c40
KH
1671ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1672{
78a21772
KH
1673#define FEATURE_NONE(IDX) (! spec->features[IDX])
1674
1675#define FEATURE_ANY(IDX) \
1676 (spec->features[IDX] \
1677 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1678
de023c40
KH
1679 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1680 OTF *otf = flt_font_ft->otf;
1681 OTF_Tag *tags;
a864ef14
PE
1682 int i, n;
1683 bool negative;
de023c40 1684
78a21772 1685 if (FEATURE_ANY (0) && FEATURE_ANY (1))
a864ef14
PE
1686 /* Return true iff any of GSUB or GPOS support the script (and
1687 language). */
fa3f6039
KH
1688 return (otf
1689 && (OTF_check_features (otf, 0, spec->script, spec->langsys,
1690 NULL, 0) > 0
1691 || OTF_check_features (otf, 1, spec->script, spec->langsys,
1692 NULL, 0) > 0));
1693
de023c40 1694 for (i = 0; i < 2; i++)
78a21772 1695 if (! FEATURE_ANY (i))
fa3f6039 1696 {
78a21772 1697 if (FEATURE_NONE (i))
fa3f6039 1698 {
78a21772
KH
1699 if (otf
1700 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1701 NULL, 0) > 0)
1702 return 0;
1703 continue;
fa3f6039
KH
1704 }
1705 if (spec->features[i][0] == 0xFFFFFFFF)
1706 {
78a21772
KH
1707 if (! otf
1708 || OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1709 NULL, 0) <= 0)
fa3f6039
KH
1710 continue;
1711 }
78a21772 1712 else if (! otf)
fa3f6039 1713 return 0;
fa3f6039
KH
1714 for (n = 1; spec->features[i][n]; n++);
1715 tags = alloca (sizeof (OTF_Tag) * n);
1716 for (n = 0, negative = 0; spec->features[i][n]; n++)
1717 {
1718 if (spec->features[i][n] == 0xFFFFFFFF)
1719 negative = 1;
1720 else if (negative)
1721 tags[n - 1] = spec->features[i][n] | 0x80000000;
1722 else
1723 tags[n] = spec->features[i][n];
1724 }
c4170e32 1725#ifdef M17N_FLT_USE_NEW_FEATURE
fa3f6039
KH
1726 if (OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1727 tags, n - negative) != 1)
1728 return 0;
c4170e32 1729#else /* not M17N_FLT_USE_NEW_FEATURE */
fa3f6039
KH
1730 if (n - negative > 0
1731 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1732 tags, n - negative) != 1)
1733 return 0;
c4170e32 1734#endif /* not M17N_FLT_USE_NEW_FEATURE */
fa3f6039 1735 }
de023c40 1736 return 1;
78a21772
KH
1737#undef FEATURE_NONE
1738#undef FEATURE_ANY
de023c40
KH
1739}
1740
1741#define DEVICE_DELTA(table, size) \
1742 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1743 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1744 : 0)
1745
1746static void
1747adjust_anchor (FT_Face ft_face, OTF_Anchor *anchor,
1748 unsigned code, int x_ppem, int y_ppem, int *x, int *y)
1749{
1750 if (anchor->AnchorFormat == 2)
1751 {
1752 FT_Outline *outline;
1753 int ap = anchor->f.f1.AnchorPoint;
1754
1755 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
1756 outline = &ft_face->glyph->outline;
1757 if (ap < outline->n_points)
1758 {
1759 *x = outline->points[ap].x << 6;
1760 *y = outline->points[ap].y << 6;
1761 }
1762 }
1763 else if (anchor->AnchorFormat == 3)
1764 {
d90bfd1c
KH
1765 if (anchor->f.f2.XDeviceTable.offset
1766 && anchor->f.f2.XDeviceTable.DeltaValue)
de023c40 1767 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
d90bfd1c
KH
1768 if (anchor->f.f2.YDeviceTable.offset
1769 && anchor->f.f2.YDeviceTable.DeltaValue)
de023c40
KH
1770 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
1771 }
1772}
1773
1774static OTF_GlyphString otf_gstring;
1775
2b33f1ef
KH
1776static void
1777setup_otf_gstring (int size)
1778{
0065d054 1779 if (otf_gstring.size < size)
2b33f1ef 1780 {
0065d054
PE
1781 otf_gstring.glyphs = xnrealloc (otf_gstring.glyphs,
1782 size, sizeof (OTF_Glyph));
2b33f1ef
KH
1783 otf_gstring.size = size;
1784 }
1785 otf_gstring.used = size;
1786 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size);
1787}
1788
c4170e32
KH
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
1804static int
ef1b0ba7
SM
1805ftfont_drive_otf (MFLTFont *font,
1806 MFLTOtfSpec *spec,
1807 MFLTGlyphString *in,
1808 int from,
1809 int to,
1810 MFLTGlyphString *out,
1811 MFLTGlyphAdjustment *adjustment)
c4170e32
KH
1812{
1813 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1814 FT_Face ft_face = flt_font_ft->ft_face;
1815 OTF *otf = flt_font_ft->otf;
1816 int len = to - from;
1817 int i, j, gidx;
1818 OTF_Glyph *otfg;
1819 char script[5], *langsys = NULL;
1820 char *gsub_features = NULL, *gpos_features = NULL;
1821 OTF_Feature *features;
1822
1823 if (len == 0)
1824 return from;
1825 OTF_tag_name (spec->script, script);
1826 if (spec->langsys)
1827 {
1828 langsys = alloca (5);
1829 OTF_tag_name (spec->langsys, langsys);
1830 }
1831 for (i = 0; i < 2; i++)
1832 {
1833 char *p;
1834
1835 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
1836 {
1837 for (j = 0; spec->features[i][j]; j++);
1838 if (i == 0)
1839 p = gsub_features = alloca (6 * j);
1840 else
1841 p = gpos_features = alloca (6 * j);
1842 for (j = 0; spec->features[i][j]; j++)
1843 {
1844 if (spec->features[i][j] == 0xFFFFFFFF)
1845 *p++ = '*', *p++ = ',';
1846 else
1847 {
1848 OTF_tag_name (spec->features[i][j], p);
1849 p[4] = ',';
1850 p += 5;
1851 }
1852 }
1853 *--p = '\0';
1854 }
1855 }
1856
1857 setup_otf_gstring (len);
1858 for (i = 0; i < len; i++)
1859 {
4827f94e 1860 otf_gstring.glyphs[i].c = in->glyphs[from + i].c & 0x11FFFF;
c4170e32
KH
1861 otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code;
1862 }
1863
1864 OTF_drive_gdef (otf, &otf_gstring);
1865 gidx = out ? out->used : from;
1866
1867 if (gsub_features && out)
1868 {
1869 if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
1870 gsub_features) < 0)
1871 goto simple_copy;
1872 if (out->allocated < out->used + otf_gstring.used)
1873 return -2;
1874 features = otf->gsub->FeatureList.Feature;
1875 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
1876 {
1877 MFLTGlyph *g;
1878 int min_from, max_to;
c4170e32
KH
1879 int feature_idx = otfg->positioning_type >> 4;
1880
1881 g = out->glyphs + out->used;
1882 *g = in->glyphs[from + otfg->f.index.from];
1883 if (g->code != otfg->glyph_id)
1884 {
1885 g->c = 0;
1886 g->code = otfg->glyph_id;
1887 g->measured = 0;
1888 }
1889 out->used++;
1890 min_from = g->from;
1891 max_to = g->to;
1892 if (otfg->f.index.from < otfg->f.index.to)
1893 {
1894 /* OTFG substitutes multiple glyphs in IN. */
1895 for (j = from + otfg->f.index.from + 1;
1896 j <= from + otfg->f.index.to; j++)
1897 {
1898 if (min_from > in->glyphs[j].from)
1899 min_from = in->glyphs[j].from;
1900 if (max_to < in->glyphs[j].to)
1901 max_to = in->glyphs[j].to;
1902 }
1903 g->from = min_from;
1904 g->to = max_to;
1905 }
1906 if (feature_idx)
1907 {
1908 unsigned int tag = features[feature_idx - 1].FeatureTag;
1909 tag = PACK_OTF_TAG (tag);
1910 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1911 }
1912 for (i++, otfg++; (i < otf_gstring.used
1913 && otfg->f.index.from == otfg[-1].f.index.from);
1914 i++, otfg++)
1915 {
1916 g = out->glyphs + out->used;
1917 *g = in->glyphs[from + otfg->f.index.to];
1918 if (g->code != otfg->glyph_id)
1919 {
1920 g->c = 0;
1921 g->code = otfg->glyph_id;
1922 g->measured = 0;
1923 }
1924 feature_idx = otfg->positioning_type >> 4;
1925 if (feature_idx)
1926 {
1927 unsigned int tag = features[feature_idx - 1].FeatureTag;
1928 tag = PACK_OTF_TAG (tag);
1929 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1930 }
1931 out->used++;
1932 }
1933 }
1934 }
1935 else if (gsub_features)
1936 {
1937 /* Just for checking which features will be applied. */
1938 if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
1939 gsub_features) < 0)
1940 goto simple_copy;
1941 features = otf->gsub->FeatureList.Feature;
1942 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++,
1943 otfg++)
1944 {
1945 int feature_idx = otfg->positioning_type >> 4;
1946
1947 if (feature_idx)
1948 {
1949 unsigned int tag = features[feature_idx - 1].FeatureTag;
1950 tag = PACK_OTF_TAG (tag);
1951 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
1952 {
1953 MFLTGlyph *g = in->glyphs + (from + j);
1954 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1955 }
1956 }
1957 }
1958 }
1959 else if (out)
1960 {
1961 if (out->allocated < out->used + len)
1962 return -2;
1963 for (i = 0; i < len; i++)
1964 out->glyphs[out->used++] = in->glyphs[from + i];
1965 }
1966
1967 if (gpos_features && out)
1968 {
1969 MFLTGlyph *base = NULL, *mark = NULL, *g;
1970 int x_ppem, y_ppem, x_scale, y_scale;
1971
1972 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
1973 gpos_features) < 0)
1974 return to;
1975 features = otf->gpos->FeatureList.Feature;
1976 x_ppem = ft_face->size->metrics.x_ppem;
1977 y_ppem = ft_face->size->metrics.y_ppem;
1978 x_scale = ft_face->size->metrics.x_scale;
1979 y_scale = ft_face->size->metrics.y_scale;
1980
1981 for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx;
1982 i < otf_gstring.used; i++, otfg++, g++)
1983 {
1984 MFLTGlyph *prev;
1985 int feature_idx = otfg->positioning_type >> 4;
1986
1987 if (feature_idx)
1988 {
1989 unsigned int tag = features[feature_idx - 1].FeatureTag;
1990 tag = PACK_OTF_TAG (tag);
1991 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1992 }
1993
1994 if (! otfg->glyph_id)
1995 continue;
1996 switch (otfg->positioning_type & 0xF)
1997 {
1998 case 0:
1999 break;
2000 case 1: /* Single */
2001 case 2: /* Pair */
2002 {
2003 int format = otfg->f.f1.format;
2004
2005 if (format & OTF_XPlacement)
2006 adjustment[i].xoff
2007 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
2008 if (format & OTF_XPlaDevice)
2009 adjustment[i].xoff
2010 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
2011 if (format & OTF_YPlacement)
2012 adjustment[i].yoff
2013 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
2014 if (format & OTF_YPlaDevice)
2015 adjustment[i].yoff
2016 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
2017 if (format & OTF_XAdvance)
2018 adjustment[i].xadv
2019 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
2020 if (format & OTF_XAdvDevice)
2021 adjustment[i].xadv
2022 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
2023 if (format & OTF_YAdvance)
2024 adjustment[i].yadv
2025 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
2026 if (format & OTF_YAdvDevice)
2027 adjustment[i].yadv
2028 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
2029 adjustment[i].set = 1;
2030 }
2031 break;
2032 case 3: /* Cursive */
2033 /* Not yet supported. */
2034 break;
2035 case 4: /* Mark-to-Base */
2036 case 5: /* Mark-to-Ligature */
2037 if (! base)
2038 break;
2039 prev = base;
2040 goto label_adjust_anchor;
2041 default: /* i.e. case 6 Mark-to-Mark */
2042 if (! mark)
2043 break;
2044 prev = mark;
2045
2046 label_adjust_anchor:
2047 {
2048 int base_x, base_y, mark_x, mark_y;
2049 int this_from, this_to;
2050
2051 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
2052 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
2053 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
2054 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
2055
2056 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2057 adjust_anchor (ft_face, otfg->f.f4.base_anchor,
2058 prev->code, x_ppem, y_ppem, &base_x, &base_y);
2059 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2060 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->code,
2061 x_ppem, y_ppem, &mark_x, &mark_y);
2062 adjustment[i].xoff = (base_x - mark_x);
2063 adjustment[i].yoff = - (base_y - mark_y);
2064 adjustment[i].back = (g - prev);
2065 adjustment[i].xadv = 0;
2066 adjustment[i].advance_is_absolute = 1;
2067 adjustment[i].set = 1;
2068 this_from = g->from;
2069 this_to = g->to;
2070 for (j = 0; prev + j < g; j++)
2071 {
2072 if (this_from > prev[j].from)
2073 this_from = prev[j].from;
2074 if (this_to < prev[j].to)
2075 this_to = prev[j].to;
2076 }
2077 for (; prev <= g; prev++)
2078 {
2079 prev->from = this_from;
2080 prev->to = this_to;
2081 }
2082 }
2083 }
2084 if (otfg->GlyphClass == OTF_GlyphClass0)
2085 base = mark = g;
2086 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2087 mark = g;
2088 else
2089 base = g;
2090 }
2091 }
2092 else if (gpos_features)
2093 {
2094 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
2095 gpos_features) < 0)
2096 return to;
2097 features = otf->gpos->FeatureList.Feature;
2098 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
2099 i++, otfg++)
2100 if (otfg->positioning_type & 0xF)
2101 {
2102 int feature_idx = otfg->positioning_type >> 4;
2103
2104 if (feature_idx)
2105 {
2106 unsigned int tag = features[feature_idx - 1].FeatureTag;
2107 tag = PACK_OTF_TAG (tag);
2108 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
2109 {
2110 MFLTGlyph *g = in->glyphs + (from + j);
2111 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
2112 }
2113 }
2114 }
2115 }
2116 return to;
2117
2118 simple_copy:
2119 if (! out)
2120 return to;
2121 if (out->allocated < out->used + len)
2122 return -2;
2123 font->get_metrics (font, in, from, to);
2124 memcpy (out->glyphs + out->used, in->glyphs + from,
2125 sizeof (MFLTGlyph) * len);
2126 out->used += len;
2127 return to;
2128}
2129
9fa82824 2130static int
c4170e32
KH
2131ftfont_try_otf (MFLTFont *font, MFLTOtfSpec *spec,
2132 MFLTGlyphString *in, int from, int to)
2133{
2134 return ftfont_drive_otf (font, spec, in, from, to, NULL, NULL);
2135}
2136
2137#else /* not M17N_FLT_USE_NEW_FEATURE */
2b33f1ef 2138
2a46904e 2139static int
d5a3eaaf
AS
2140ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2141 int from, int to,
2142 MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
de023c40
KH
2143{
2144 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
2145 FT_Face ft_face = flt_font_ft->ft_face;
2146 OTF *otf = flt_font_ft->otf;
2147 int len = to - from;
2148 int i, j, gidx;
2149 OTF_Glyph *otfg;
2150 char script[5], *langsys = NULL;
2151 char *gsub_features = NULL, *gpos_features = NULL;
2152
2153 if (len == 0)
2154 return from;
2155 OTF_tag_name (spec->script, script);
2156 if (spec->langsys)
2157 {
2158 langsys = alloca (5);
2159 OTF_tag_name (spec->langsys, langsys);
2160 }
2161 for (i = 0; i < 2; i++)
2162 {
2163 char *p;
2164
2165 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
2166 {
2167 for (j = 0; spec->features[i][j]; j++);
2168 if (i == 0)
2169 p = gsub_features = alloca (6 * j);
2170 else
2171 p = gpos_features = alloca (6 * j);
2172 for (j = 0; spec->features[i][j]; j++)
2173 {
2174 if (spec->features[i][j] == 0xFFFFFFFF)
2175 *p++ = '*', *p++ = ',';
2176 else
2177 {
2178 OTF_tag_name (spec->features[i][j], p);
2179 p[4] = ',';
2180 p += 5;
2181 }
2182 }
2183 *--p = '\0';
2184 }
2185 }
2186
2b33f1ef 2187 setup_otf_gstring (len);
de023c40
KH
2188 for (i = 0; i < len; i++)
2189 {
2190 otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
2191 otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code;
2192 }
2193
2194 OTF_drive_gdef (otf, &otf_gstring);
2195 gidx = out->used;
2196
2197 if (gsub_features)
2198 {
2199 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
2200 < 0)
2201 goto simple_copy;
2202 if (out->allocated < out->used + otf_gstring.used)
2203 return -2;
7d2fd545 2204 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
de023c40 2205 {
7d2fd545
KH
2206 MFLTGlyph *g;
2207 int min_from, max_to;
de023c40
KH
2208 int j;
2209
7d2fd545 2210 g = out->glyphs + out->used;
de023c40 2211 *g = in->glyphs[from + otfg->f.index.from];
de023c40
KH
2212 if (g->code != otfg->glyph_id)
2213 {
7d2fd545 2214 g->c = 0;
de023c40
KH
2215 g->code = otfg->glyph_id;
2216 g->measured = 0;
2217 }
2218 out->used++;
7d2fd545
KH
2219 min_from = g->from;
2220 max_to = g->to;
2221 if (otfg->f.index.from < otfg->f.index.to)
2222 {
2223 /* OTFG substitutes multiple glyphs in IN. */
2224 for (j = from + otfg->f.index.from + 1;
2225 j <= from + otfg->f.index.to; j++)
2226 {
2227 if (min_from > in->glyphs[j].from)
2228 min_from = in->glyphs[j].from;
2229 if (max_to < in->glyphs[j].to)
2230 max_to = in->glyphs[j].to;
2231 }
2232 g->from = min_from;
2233 g->to = max_to;
2234 }
2235 for (i++, otfg++; (i < otf_gstring.used
2236 && otfg->f.index.from == otfg[-1].f.index.from);
2237 i++, otfg++)
2238 {
2239 g = out->glyphs + out->used;
2240 *g = in->glyphs[from + otfg->f.index.to];
2241 if (g->code != otfg->glyph_id)
2242 {
2243 g->c = 0;
2244 g->code = otfg->glyph_id;
2245 g->measured = 0;
2246 }
2247 out->used++;
2248 }
de023c40
KH
2249 }
2250 }
2251 else
2252 {
2253 if (out->allocated < out->used + len)
2254 return -2;
2255 for (i = 0; i < len; i++)
2256 out->glyphs[out->used++] = in->glyphs[from + i];
2257 }
2258
2259 if (gpos_features)
2260 {
2261 MFLTGlyph *base = NULL, *mark = NULL, *g;
2262 int x_ppem, y_ppem, x_scale, y_scale;
2263
2264 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
2265 < 0)
2266 return to;
2267
2268 x_ppem = ft_face->size->metrics.x_ppem;
2269 y_ppem = ft_face->size->metrics.y_ppem;
2270 x_scale = ft_face->size->metrics.x_scale;
2271 y_scale = ft_face->size->metrics.y_scale;
2272
2273 for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx;
2274 i < otf_gstring.used; i++, otfg++, g++)
2275 {
2276 MFLTGlyph *prev;
2277
2278 if (! otfg->glyph_id)
2279 continue;
2280 switch (otfg->positioning_type)
2281 {
2282 case 0:
2283 break;
2284 case 1: /* Single */
2285 case 2: /* Pair */
2286 {
2287 int format = otfg->f.f1.format;
2288
2289 if (format & OTF_XPlacement)
2290 adjustment[i].xoff
2291 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
2292 if (format & OTF_XPlaDevice)
2293 adjustment[i].xoff
2294 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
2295 if (format & OTF_YPlacement)
2296 adjustment[i].yoff
2297 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
2298 if (format & OTF_YPlaDevice)
2299 adjustment[i].yoff
2300 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
2301 if (format & OTF_XAdvance)
2302 adjustment[i].xadv
2303 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
2304 if (format & OTF_XAdvDevice)
2305 adjustment[i].xadv
2306 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
2307 if (format & OTF_YAdvance)
2308 adjustment[i].yadv
2309 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
2310 if (format & OTF_YAdvDevice)
2311 adjustment[i].yadv
2312 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
2313 adjustment[i].set = 1;
2314 }
2315 break;
2316 case 3: /* Cursive */
2317 /* Not yet supported. */
2318 break;
2319 case 4: /* Mark-to-Base */
2320 case 5: /* Mark-to-Ligature */
2321 if (! base)
2322 break;
2323 prev = base;
2324 goto label_adjust_anchor;
2325 default: /* i.e. case 6 Mark-to-Mark */
2326 if (! mark)
2327 break;
2328 prev = mark;
2329
2330 label_adjust_anchor:
2331 {
2332 int base_x, base_y, mark_x, mark_y;
2333 int this_from, this_to;
2334
2335 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
2336 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
2337 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
8510724d 2338 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
de023c40
KH
2339
2340 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2341 adjust_anchor (ft_face, otfg->f.f4.base_anchor,
2342 prev->code, x_ppem, y_ppem, &base_x, &base_y);
2343 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2344 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->code,
2345 x_ppem, y_ppem, &mark_x, &mark_y);
2346 adjustment[i].xoff = (base_x - mark_x);
2347 adjustment[i].yoff = - (base_y - mark_y);
2348 adjustment[i].back = (g - prev);
2349 adjustment[i].xadv = 0;
2350 adjustment[i].advance_is_absolute = 1;
2351 adjustment[i].set = 1;
2352 this_from = g->from;
2353 this_to = g->to;
2354 for (j = 0; prev + j < g; j++)
2355 {
2356 if (this_from > prev[j].from)
2357 this_from = prev[j].from;
2358 if (this_to < prev[j].to)
2359 this_to = prev[j].to;
2360 }
2361 for (; prev <= g; prev++)
2362 {
2363 prev->from = this_from;
2364 prev->to = this_to;
2365 }
2366 }
2367 }
2368 if (otfg->GlyphClass == OTF_GlyphClass0)
2369 base = mark = g;
2370 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2371 mark = g;
2372 else
2373 base = g;
2374 }
2375 }
2376 return to;
2377
2378 simple_copy:
2379 if (out->allocated < out->used + len)
2380 return -2;
2381 font->get_metrics (font, in, from, to);
2382 memcpy (out->glyphs + out->used, in->glyphs + from,
2383 sizeof (MFLTGlyph) * len);
2384 out->used += len;
2385 return to;
2386}
2387
c4170e32
KH
2388#endif /* not M17N_FLT_USE_NEW_FEATURE */
2389
de023c40
KH
2390static MFLTGlyphString gstring;
2391
a864ef14 2392static bool m17n_flt_initialized;
de023c40 2393
990a73f0 2394static Lisp_Object
d5a3eaaf
AS
2395ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
2396 FT_Face ft_face, OTF *otf, FT_Matrix *matrix)
de023c40 2397{
d311d28c
PE
2398 ptrdiff_t len = LGSTRING_GLYPH_LEN (lgstring);
2399 ptrdiff_t i;
de023c40 2400 struct MFLTFontFT flt_font_ft;
da2cf488 2401 MFLT *flt = NULL;
a864ef14 2402 bool with_variation_selector = 0;
de023c40
KH
2403
2404 if (! m17n_flt_initialized)
2405 {
2406 M17N_INIT ();
c4170e32
KH
2407#ifdef M17N_FLT_USE_NEW_FEATURE
2408 mflt_enable_new_feature = 1;
2409 mflt_try_otf = ftfont_try_otf;
2410#endif /* M17N_FLT_USE_NEW_FEATURE */
de023c40
KH
2411 m17n_flt_initialized = 1;
2412 }
2413
2414 for (i = 0; i < len; i++)
2b33f1ef
KH
2415 {
2416 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
2417 int c;
2418
2419 if (NILP (g))
2420 break;
2421 c = LGLYPH_CHAR (g);
2422 if (CHAR_VARIATION_SELECTOR_P (c))
a864ef14 2423 with_variation_selector = 1;
2b33f1ef 2424 }
f2ed8a70 2425
de023c40 2426 len = i;
f2ed8a70 2427
2b33f1ef
KH
2428 if (with_variation_selector)
2429 {
2430 setup_otf_gstring (len);
2431 for (i = 0; i < len; i++)
2432 {
2433 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
2434
2435 otf_gstring.glyphs[i].c = LGLYPH_CHAR (g);
2436 otf_gstring.glyphs[i].f.index.from = LGLYPH_FROM (g);
2437 otf_gstring.glyphs[i].f.index.to = LGLYPH_TO (g);
2438 }
2439 OTF_drive_cmap (otf, &otf_gstring);
2440 for (i = 0; i < otf_gstring.used; i++)
2441 {
2442 OTF_Glyph *otfg = otf_gstring.glyphs + i;
2443 Lisp_Object g0 = LGSTRING_GLYPH (lgstring, otfg->f.index.from);
2444 Lisp_Object g1 = LGSTRING_GLYPH (lgstring, otfg->f.index.to);
2445
2446 LGLYPH_SET_CODE (g0, otfg->glyph_id);
2447 LGLYPH_SET_TO (g0, LGLYPH_TO (g1));
2448 LGSTRING_SET_GLYPH (lgstring, i, g0);
2449 }
2450 if (len > otf_gstring.used)
2451 {
2452 len = otf_gstring.used;
2453 LGSTRING_SET_GLYPH (lgstring, len, Qnil);
2454 }
2455 }
de023c40 2456
0065d054 2457 if (INT_MAX / 2 < len)
1ffd9c92
PE
2458 memory_full (SIZE_MAX);
2459
de023c40
KH
2460 if (gstring.allocated == 0)
2461 {
de023c40 2462 gstring.glyph_size = sizeof (MFLTGlyph);
38182d90 2463 gstring.glyphs = xnmalloc (len * 2, sizeof *gstring.glyphs);
0065d054 2464 gstring.allocated = len * 2;
de023c40
KH
2465 }
2466 else if (gstring.allocated < len * 2)
2467 {
38182d90
PE
2468 gstring.glyphs = xnrealloc (gstring.glyphs, len * 2,
2469 sizeof *gstring.glyphs);
de023c40 2470 gstring.allocated = len * 2;
de023c40 2471 }
38182d90 2472 memset (gstring.glyphs, 0, len * sizeof *gstring.glyphs);
de023c40 2473 for (i = 0; i < len; i++)
2b33f1ef
KH
2474 {
2475 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
2476
2477 gstring.glyphs[i].c = LGLYPH_CHAR (g);
2478 if (with_variation_selector)
2479 {
2480 gstring.glyphs[i].code = LGLYPH_CODE (g);
2481 gstring.glyphs[i].encoded = 1;
2482 }
2483 }
2484
de023c40
KH
2485 gstring.used = len;
2486 gstring.r2l = 0;
2487
2488 {
2489 Lisp_Object family = Ffont_get (LGSTRING_FONT (lgstring), QCfamily);
2490
2491 if (NILP (family))
2492 flt_font_ft.flt_font.family = Mnil;
2493 else
21988a08 2494 flt_font_ft.flt_font.family
51b59d79 2495 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family))));
de023c40
KH
2496 }
2497 flt_font_ft.flt_font.x_ppem = ft_face->size->metrics.x_ppem;
2498 flt_font_ft.flt_font.y_ppem = ft_face->size->metrics.y_ppem;
2499 flt_font_ft.flt_font.get_glyph_id = ftfont_get_glyph_id;
2500 flt_font_ft.flt_font.get_metrics = ftfont_get_metrics;
2501 flt_font_ft.flt_font.check_otf = ftfont_check_otf;
2502 flt_font_ft.flt_font.drive_otf = ftfont_drive_otf;
2503 flt_font_ft.flt_font.internal = NULL;
2504 flt_font_ft.font = font;
2505 flt_font_ft.ft_face = ft_face;
2506 flt_font_ft.otf = otf;
d0db2ec8 2507 flt_font_ft.matrix = matrix->xx != 0 ? matrix : 0;
7bf1bb21
KH
2508 if (len > 1
2509 && gstring.glyphs[1].c >= 0x300 && gstring.glyphs[1].c <= 0x36F)
da2cf488
KH
2510 /* A little bit ad hoc. Perhaps, shaper must get script and
2511 language information, and select a proper flt for them
2512 here. */
2513 flt = mflt_get (msymbol ("combining"));
de023c40
KH
2514 for (i = 0; i < 3; i++)
2515 {
da2cf488 2516 int result = mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt);
de023c40
KH
2517 if (result != -2)
2518 break;
0065d054 2519 if (INT_MAX / 2 < gstring.allocated)
1ffd9c92 2520 memory_full (SIZE_MAX);
0065d054
PE
2521 gstring.glyphs = xnrealloc (gstring.glyphs,
2522 gstring.allocated, 2 * sizeof (MFLTGlyph));
2523 gstring.allocated *= 2;
de023c40 2524 }
89a95b7c 2525 if (gstring.used > LGSTRING_GLYPH_LEN (lgstring))
de023c40
KH
2526 return Qnil;
2527 for (i = 0; i < gstring.used; i++)
2528 {
2529 MFLTGlyph *g = gstring.glyphs + i;
2530
2531 g->from = LGLYPH_FROM (LGSTRING_GLYPH (lgstring, g->from));
2532 g->to = LGLYPH_TO (LGSTRING_GLYPH (lgstring, g->to));
2533 }
2534
2535 for (i = 0; i < gstring.used; i++)
2536 {
2537 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2538 MFLTGlyph *g = gstring.glyphs + i;
2539
4cec6061
KH
2540 if (NILP (lglyph))
2541 {
42926ec8 2542 lglyph = LGLYPH_NEW ();
4cec6061
KH
2543 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2544 }
de023c40
KH
2545 LGLYPH_SET_FROM (lglyph, g->from);
2546 LGLYPH_SET_TO (lglyph, g->to);
2547 LGLYPH_SET_CHAR (lglyph, g->c);
2548 LGLYPH_SET_CODE (lglyph, g->code);
2549 LGLYPH_SET_WIDTH (lglyph, g->xadv >> 6);
2550 LGLYPH_SET_LBEARING (lglyph, g->lbearing >> 6);
2551 LGLYPH_SET_RBEARING (lglyph, g->rbearing >> 6);
2552 LGLYPH_SET_ASCENT (lglyph, g->ascent >> 6);
2553 LGLYPH_SET_DESCENT (lglyph, g->descent >> 6);
2554 if (g->adjusted)
2555 {
25721f5b 2556 Lisp_Object vec = make_uninit_vector (3);
de023c40 2557
de023c40
KH
2558 ASET (vec, 0, make_number (g->xoff >> 6));
2559 ASET (vec, 1, make_number (g->yoff >> 6));
2560 ASET (vec, 2, make_number (g->xadv >> 6));
2561 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
2562 }
2563 }
2564 return make_number (i);
2565}
2566
2567Lisp_Object
d5a3eaaf 2568ftfont_shape (Lisp_Object lgstring)
de023c40
KH
2569{
2570 struct font *font;
2571 struct ftfont_info *ftfont_info;
e302a291 2572 OTF *otf;
de023c40
KH
2573
2574 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
2575 ftfont_info = (struct ftfont_info *) font;
e302a291
KH
2576 otf = ftfont_get_otf (ftfont_info);
2577 if (! otf)
4cc1c806 2578 return make_number (0);
d0db2ec8
KH
2579 return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf,
2580 &ftfont_info->matrix);
de023c40
KH
2581}
2582
e3869731
KH
2583#endif /* HAVE_M17N_FLT */
2584
2b33f1ef
KH
2585#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2586
2587static int
d5a3eaaf 2588ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
2b33f1ef
KH
2589{
2590 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
2591 OTF *otf = ftfont_get_otf (ftfont_info);
2592
2593 if (! otf)
2594 return 0;
2595 return OTF_get_variation_glyphs (otf, c, variations);
2596}
2597
2598#endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
de023c40
KH
2599#endif /* HAVE_LIBOTF */
2600
0b966021 2601Lisp_Object
7d7ad10e 2602ftfont_font_format (FcPattern *pattern, Lisp_Object filename)
0b966021 2603{
e907d979 2604 FcChar8 *str;
0b966021 2605
e907d979 2606#ifdef FC_FONTFORMAT
7d7ad10e 2607 if (pattern)
719b3d63 2608 {
7d7ad10e
KH
2609 if (FcPatternGetString (pattern, FC_FONTFORMAT, 0, &str) != FcResultMatch)
2610 return Qnil;
2611 if (strcmp ((char *) str, "TrueType") == 0)
719b3d63 2612 return intern ("truetype");
7d7ad10e 2613 if (strcmp ((char *) str, "Type 1") == 0)
719b3d63 2614 return intern ("type1");
7d7ad10e 2615 if (strcmp ((char *) str, "PCF") == 0)
719b3d63 2616 return intern ("pcf");
7d7ad10e 2617 if (strcmp ((char *) str, "BDF") == 0)
719b3d63
KH
2618 return intern ("bdf");
2619 }
7d7ad10e
KH
2620#endif /* FC_FONTFORMAT */
2621 if (STRINGP (filename))
2622 {
2623 int len = SBYTES (filename);
2624
2625 if (len >= 4)
2626 {
2627 str = (FcChar8 *) (SDATA (filename) + len - 4);
2628 if (xstrcasecmp ((char *) str, ".ttf") == 0)
2629 return intern ("truetype");
2630 if (xstrcasecmp ((char *) str, ".pfb") == 0)
2631 return intern ("type1");
2632 if (xstrcasecmp ((char *) str, ".pcf") == 0)
2633 return intern ("pcf");
2634 if (xstrcasecmp ((char *) str, ".bdf") == 0)
2635 return intern ("bdf");
2636 }
2637 }
0b966021
KH
2638 return intern ("unknown");
2639}
2640
3106121c 2641static const char *const ftfont_booleans [] = {
637fa988
JD
2642 ":antialias",
2643 ":hinting",
2644 ":verticallayout",
2645 ":autohint",
2646 ":globaladvance",
2647 ":outline",
2648 ":scalable",
2649 ":minspace",
2650 ":embolden",
2651 NULL,
2652};
2653
3106121c 2654static const char *const ftfont_non_booleans [] = {
637fa988
JD
2655 ":family",
2656 ":familylang",
2657 ":style",
2658 ":stylelang",
2659 ":fullname",
2660 ":fullnamelang",
2661 ":slant",
2662 ":weight",
2663 ":size",
2664 ":width",
2665 ":aspect",
2666 ":pixelsize",
2667 ":spacing",
2668 ":foundry",
2669 ":hintstyle",
2670 ":file",
2671 ":index",
2672 ":ftface",
2673 ":rasterizer",
2674 ":scale",
2675 ":dpi",
2676 ":rgba",
2677 ":lcdfilter",
2678 ":charset",
2679 ":lang",
2680 ":fontversion",
2681 ":capability",
2682 NULL,
2683};
2684
2685static void
971de7fb 2686ftfont_filter_properties (Lisp_Object font, Lisp_Object alist)
637fa988 2687{
9fa82824 2688 font_filter_properties (font, alist, ftfont_booleans, ftfont_non_booleans);
637fa988
JD
2689}
2690
2691
c2f5bfd6 2692void
971de7fb 2693syms_of_ftfont (void)
c2f5bfd6 2694{
706b6995
KH
2695 DEFSYM (Qfreetype, "freetype");
2696 DEFSYM (Qmonospace, "monospace");
2697 DEFSYM (Qsans_serif, "sans-serif");
2698 DEFSYM (Qserif, "serif");
2699 DEFSYM (Qmono, "mono");
2700 DEFSYM (Qsans, "sans");
2701 DEFSYM (Qsans__serif, "sans serif");
2702
c2f5bfd6 2703 staticpro (&freetype_font_cache);
6c6f1994 2704 freetype_font_cache = list1 (Qt);
c2f5bfd6 2705
706b6995 2706 staticpro (&ftfont_generic_family_list);
6c6f1994
PE
2707 ftfont_generic_family_list = list3 (Fcons (Qmonospace, Qt),
2708 Fcons (Qsans_serif, Qt),
2709 Fcons (Qsans, Qt));
c2f5bfd6 2710
21988a08
KH
2711 staticpro (&ft_face_cache);
2712 ft_face_cache = Qnil;
2713
c2f5bfd6
KH
2714 ftfont_driver.type = Qfreetype;
2715 register_font_driver (&ftfont_driver, NULL);
2716}