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