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