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