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