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