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