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