This source file includes following definitions.
- matching_prefix
- get_adstyle_property
- ftfont_pattern_entity
- ftfont_resolve_generic_family
- ftfont_lookup_cache
- ftfont_get_fc_charset
- ftfont_get_otf
- ftfont_get_cache
- ftfont_get_charset
- ftfont_get_open_type_spec
- xft_color_font_whitelisted_p
- ftfont_spec_pattern
- ftfont_list
- ftfont_list2
- ftfont_match
- ftfont_match2
- ftfont_list_family
- ftfont_fix_match
- ftfont_add_rendering_parameters
- ftfont_entity_pattern
- ftfont_open
- ftfont_close
- ftfont_has_char
- ftfont_encode_char
- ftfont_glyph_metrics
- ftfont_text_extents
- ftfont_get_bitmap
- ftfont_anchor_point
- ftfont_otf_features
- ftfont_otf_capability
- ftfont_get_glyph_id
- ftfont_get_metrics
- ftfont_check_otf
- adjust_anchor
- setup_otf_gstring
- ftfont_drive_otf
- ftfont_try_otf
- ftfont_drive_otf
- ftfont_shape_by_flt
- ftfont_shape
- ftfont_variation_glyphs
- fthbfont_begin_hb_font
- hbotf_open
- hbotf_check_features
- ftfont_filter_properties
- ftfont_combining_capability
- syms_of_ftfont
- syms_of_ftfont_for_pdumper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <config.h>
23 #include <fontconfig/fontconfig.h>
24 #include <fontconfig/fcfreetype.h>
25
26
27
28
29 #ifdef HAVE_XFT
30 # include <X11/Xlib.h>
31 # include <X11/Xft/Xft.h>
32 #endif
33 #ifdef USE_CAIRO
34 # include <cairo-ft.h>
35 #endif
36
37 #include <c-strcase.h>
38
39 #include "lisp.h"
40 #include "dispextern.h"
41 #include "character.h"
42 #include "charset.h"
43 #include "category.h"
44 #include "composite.h"
45 #include "font.h"
46 #include "ftfont.h"
47 #include "pdumper.h"
48
49 static struct font_driver const ftfont_driver;
50 #ifdef HAVE_HARFBUZZ
51 static struct font_driver fthbfont_driver;
52 #endif
53
54
55 static bool fc_initialized;
56
57
58 static FT_Library ft_library;
59
60
61 static Lisp_Object freetype_font_cache;
62
63
64 static Lisp_Object ft_face_cache;
65
66 enum ftfont_cache_for
67 {
68 FTFONT_CACHE_FOR_FACE,
69 FTFONT_CACHE_FOR_CHARSET,
70 FTFONT_CACHE_FOR_ENTITY
71 };
72
73 static Lisp_Object ftfont_lookup_cache (Lisp_Object,
74 enum ftfont_cache_for);
75
76 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
77
78 static struct
79 {
80
81 const char *name;
82
83 int uniquifier[6];
84
85 const char *lang;
86
87 FcCharSet *fc_charset;
88 } fc_charset_table[] =
89 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
90 { "iso8859-2", { 0x00A0, 0x010E }},
91 { "iso8859-3", { 0x00A0, 0x0108 }},
92 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
93 { "iso8859-5", { 0x00A0, 0x0401 }},
94 { "iso8859-6", { 0x00A0, 0x060C }},
95 { "iso8859-7", { 0x00A0, 0x0384 }},
96 { "iso8859-8", { 0x00A0, 0x05D0 }},
97 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
98 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
99 { "iso8859-11", { 0x00A0, 0x0E01 }},
100 { "iso8859-13", { 0x00A0, 0x201C }},
101 { "iso8859-14", { 0x00A0, 0x0174 }},
102 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
103 { "iso8859-16", { 0x00A0, 0x0218}},
104 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
105 { "big5-0", { 0x9C21 }, "zh-tw" },
106 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
107 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
108 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
109 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
110 { "cns11643.1992-3", { 0x201A9 }},
111 { "cns11643.1992-4", { 0x20057 }},
112 { "cns11643.1992-5", { 0x20000 }},
113 { "cns11643.1992-6", { 0x20003 }},
114 { "cns11643.1992-7", { 0x20055 }},
115 { "gbk-0", { 0x4E06 }, "zh-cn"},
116 { "jisx0212.1990-0", { 0x4E44 }},
117 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
118 { "jisx0213.2000-2", { 0xFA49 }},
119 { "jisx0213.2004-1", { 0x20B9F }},
120 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
121 { "tis620.2529-1", { 0x0E01 }, "th"},
122 { "microsoft-cp1251", { 0x0401, 0x0490 }, "ru"},
123 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
124 { "mulelao-1", { 0x0E81 }, "lo"},
125 { "unicode-sip", { 0x20000 }},
126 { NULL }
127 };
128
129 static bool
130 matching_prefix (char const *str, ptrdiff_t len, char const *pat)
131 {
132 return len == strlen (pat) && c_strncasecmp (str, pat, len) == 0;
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148 static Lisp_Object
149 get_adstyle_property (FcPattern *p)
150 {
151 FcChar8 *fcstr;
152 char *str, *end;
153 Lisp_Object adstyle;
154
155 #ifdef FC_FONTFORMAT
156 if ((FcPatternGetString (p, FC_FONTFORMAT, 0, &fcstr) == FcResultMatch)
157 && xstrcasecmp ((char *) fcstr, "bdf") != 0
158 && xstrcasecmp ((char *) fcstr, "pcf") != 0)
159
160 return Qnil;
161 #endif
162 if (FcPatternGetString (p, FC_STYLE, 0, &fcstr) != FcResultMatch)
163 return Qnil;
164 str = (char *) fcstr;
165 for (end = str; *end && *end != ' '; end++);
166 if (matching_prefix (str, end - str, "Regular")
167 || matching_prefix (str, end - str, "Bold")
168 || matching_prefix (str, end - str, "Oblique")
169 || matching_prefix (str, end - str, "Italic"))
170 return Qnil;
171 adstyle = font_intern_prop (str, end - str, 1);
172 if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
173 return Qnil;
174 return adstyle;
175 }
176
177 static Lisp_Object
178 ftfont_pattern_entity (FcPattern *p, Lisp_Object extra)
179 {
180 Lisp_Object key, cache, entity;
181 FcChar8 *str;
182 char *file;
183 int idx;
184 int numeric;
185 double dbl;
186 FcBool b;
187
188 if (FcPatternGetString (p, FC_FILE, 0, &str) != FcResultMatch)
189 return Qnil;
190 if (FcPatternGetInteger (p, FC_INDEX, 0, &idx) != FcResultMatch)
191 return Qnil;
192 #ifdef FC_VARIABLE
193
194
195
196
197
198
199
200
201
202
203
204 FcRange *range;
205 if (FcPatternGetRange (p, FC_WEIGHT, 0, &range) == FcResultMatch
206 && FcPatternGetBool (p, FC_VARIABLE, 0, &b) == FcResultMatch
207 && b == FcTrue)
208 return Qnil;
209 #endif
210
211 file = (char *) str;
212 key = Fcons (build_unibyte_string (file), make_fixnum (idx));
213 cache = ftfont_lookup_cache (key, FTFONT_CACHE_FOR_ENTITY);
214 entity = XCAR (cache);
215 if (! NILP (entity))
216 {
217 Lisp_Object val = font_make_entity ();
218 int i;
219
220 for (i = 0; i < FONT_OBJLIST_INDEX; i++)
221 ASET (val, i, AREF (entity, i));
222
223 ASET (val, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
224 font_put_extra (val, QCfont_entity, key);
225
226 return val;
227 }
228 entity = font_make_entity ();
229 XSETCAR (cache, entity);
230
231 ASET (entity, FONT_TYPE_INDEX, Qfreetype);
232 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
233
234 if (FcPatternGetString (p, FC_FOUNDRY, 0, &str) == FcResultMatch)
235 {
236 char *s = (char *) str;
237 ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (s, strlen (s), 1));
238 }
239 if (FcPatternGetString (p, FC_FAMILY, 0, &str) == FcResultMatch)
240 {
241 char *s = (char *) str;
242 ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (s, strlen (s), 1));
243 }
244 if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
245 {
246 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, make_fixnum (numeric));
247 }
248 if (FcPatternGetInteger (p, FC_SLANT, 0, &numeric) == FcResultMatch)
249 {
250 numeric += 100;
251 FONT_SET_STYLE (entity, FONT_SLANT_INDEX, make_fixnum (numeric));
252 }
253 if (FcPatternGetInteger (p, FC_WIDTH, 0, &numeric) == FcResultMatch)
254 {
255 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_fixnum (numeric));
256 }
257 if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
258 {
259 ASET (entity, FONT_SIZE_INDEX, make_fixnum (dbl));
260 }
261 else
262 ASET (entity, FONT_SIZE_INDEX, make_fixnum (0));
263 if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch)
264 ASET (entity, FONT_SPACING_INDEX, make_fixnum (numeric));
265 if (FcPatternGetDouble (p, FC_DPI, 0, &dbl) == FcResultMatch)
266 {
267 int dpi = dbl;
268 ASET (entity, FONT_DPI_INDEX, make_fixnum (dpi));
269 }
270 if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
271 && b == FcTrue)
272 {
273 ASET (entity, FONT_SIZE_INDEX, make_fixnum (0));
274 ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0));
275 }
276 else
277 {
278
279
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_fixnum (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
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 intptr_t face_refcount;
360 };
361
362 static Lisp_Object
363 ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for)
364 {
365 Lisp_Object cache, val;
366 struct ftfont_cache_data *cache_data;
367
368 if (FONT_ENTITY_P (key))
369 {
370 val = assq_no_quit (QCfont_entity, AREF (key, FONT_EXTRA_INDEX));
371 eassert (CONSP (val));
372 key = XCDR (val);
373 }
374
375 if (NILP (ft_face_cache))
376 cache = Qnil;
377 else
378 cache = Fgethash (key, ft_face_cache, Qnil);
379 if (NILP (cache))
380 {
381 if (NILP (ft_face_cache))
382 ft_face_cache = CALLN (Fmake_hash_table, QCtest, Qequal);
383 cache_data = xzalloc (sizeof *cache_data);
384 val = make_mint_ptr (cache_data);
385 cache = Fcons (Qnil, val);
386 Fputhash (key, cache, ft_face_cache);
387 }
388 else
389 {
390 val = XCDR (cache);
391 cache_data = xmint_pointer (val);
392 }
393
394 if (cache_for == FTFONT_CACHE_FOR_ENTITY)
395 return cache;
396
397 if (cache_for == FTFONT_CACHE_FOR_FACE
398 ? ! cache_data->ft_face : ! cache_data->fc_charset)
399 {
400 char *filename = SSDATA (XCAR (key));
401 int idx = XFIXNUM (XCDR (key));
402
403 if (cache_for == FTFONT_CACHE_FOR_FACE)
404 {
405 if (! ft_library
406 && FT_Init_FreeType (&ft_library) != 0)
407 return Qnil;
408 if (FT_New_Face (ft_library, filename, idx, &cache_data->ft_face)
409 != 0)
410 return Qnil;
411 }
412 else
413 {
414 FcPattern *pat = NULL;
415 FcFontSet *fontset = NULL;
416 FcObjectSet *objset = NULL;
417 FcCharSet *charset = NULL;
418
419 pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename,
420 FC_INDEX, FcTypeInteger, idx, NULL);
421 if (! pat)
422 goto finish;
423 objset = FcObjectSetBuild (FC_CHARSET, FC_STYLE, NULL);
424 if (! objset)
425 goto finish;
426 fontset = FcFontList (NULL, pat, objset);
427 if (! fontset)
428 goto finish;
429 if (fontset && fontset->nfont > 0
430 && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
431 &charset)
432 == FcResultMatch))
433 cache_data->fc_charset = FcCharSetCopy (charset);
434 else
435 cache_data->fc_charset = FcCharSetCreate ();
436
437 finish:
438 if (fontset)
439 FcFontSetDestroy (fontset);
440 if (objset)
441 FcObjectSetDestroy (objset);
442 if (pat)
443 FcPatternDestroy (pat);
444 }
445 }
446 return cache;
447 }
448
449 static FcCharSet *
450 ftfont_get_fc_charset (Lisp_Object entity)
451 {
452 Lisp_Object val, cache;
453 struct ftfont_cache_data *cache_data;
454
455 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
456 val = XCDR (cache);
457 cache_data = xmint_pointer (val);
458 return cache_data->fc_charset;
459 }
460
461 #ifdef HAVE_LIBOTF
462 static OTF *
463 ftfont_get_otf (struct font_info *ftfont_info)
464 {
465 OTF *otf;
466
467 if (ftfont_info->otf)
468 return ftfont_info->otf;
469 if (! ftfont_info->maybe_otf)
470 return NULL;
471 otf = OTF_open_ft_face (ftfont_info->ft_size->face);
472 if (! otf || OTF_get_table (otf, "head") < 0)
473 {
474 if (otf)
475 OTF_close (otf);
476 ftfont_info->maybe_otf = 0;
477 return NULL;
478 }
479 ftfont_info->otf = otf;
480 return otf;
481 }
482 #endif
483
484 Lisp_Object
485 ftfont_get_cache (struct frame *f)
486 {
487 return freetype_font_cache;
488 }
489
490 static int
491 ftfont_get_charset (Lisp_Object registry)
492 {
493 char *str = SSDATA (SYMBOL_NAME (registry));
494 USE_SAFE_ALLOCA;
495 char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
496 int i, j;
497
498 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
499 {
500 if (str[i] == '.')
501 re[j++] = '\\';
502 else if (str[i] == '*')
503 re[j++] = '.';
504 re[j] = str[i];
505 if (re[j] == '?')
506 re[j] = '.';
507 }
508 re[j] = '\0';
509 AUTO_STRING_WITH_LEN (regexp, re, j);
510 for (i = 0; fc_charset_table[i].name; i++)
511 if (fast_c_string_match_ignore_case
512 (regexp, fc_charset_table[i].name,
513 strlen (fc_charset_table[i].name)) >= 0)
514 break;
515 SAFE_FREE ();
516 if (! fc_charset_table[i].name)
517 return -1;
518 if (! fc_charset_table[i].fc_charset)
519 {
520 FcCharSet *charset = FcCharSetCreate ();
521 int *uniquifier = fc_charset_table[i].uniquifier;
522
523 if (! charset)
524 return -1;
525 for (j = 0; uniquifier[j]; j++)
526 if (! FcCharSetAddChar (charset, uniquifier[j]))
527 {
528 FcCharSetDestroy (charset);
529 return -1;
530 }
531 fc_charset_table[i].fc_charset = charset;
532 }
533 return i;
534 }
535
536 struct OpenTypeSpec
537 {
538 Lisp_Object script;
539 unsigned int script_tag, langsys_tag;
540 int nfeatures[2];
541 unsigned int *features[2];
542 };
543
544 #define OTF_SYM_TAG(SYM, TAG) \
545 do { \
546 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
547 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
548 } while (0)
549
550 #define OTF_TAG_STR(TAG, P) \
551 do { \
552 (P)[0] = (char) (TAG >> 24); \
553 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
554 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
555 (P)[3] = (char) (TAG & 0xFF); \
556 (P)[4] = '\0'; \
557 } while (0)
558
559 #ifdef HAVE_LIBOTF
560 #define OTF_TAG_SYM(SYM, TAG) \
561 do { \
562 char str[5]; \
563 \
564 OTF_TAG_STR (TAG, str); \
565 (SYM) = font_intern_prop (str, 4, 1); \
566 } while (0)
567 #elif defined HAVE_HARFBUZZ
568
569
570
571 typedef hb_face_t OTF;
572 typedef unsigned int OTF_tag;
573 static OTF *hbotf_open (const char *);
574 static int hbotf_check_features (OTF *, int, OTF_tag, OTF_tag,
575 const OTF_tag *, int);
576 #define OTF_open hbotf_open
577 #define OTF_close hb_face_destroy
578 #define OTF_check_features hbotf_check_features
579 #endif
580
581
582 static struct OpenTypeSpec *
583 ftfont_get_open_type_spec (Lisp_Object otf_spec)
584 {
585 struct OpenTypeSpec *spec = malloc (sizeof *spec);
586 Lisp_Object val;
587 int i, j;
588 bool negative;
589
590 if (! spec)
591 return NULL;
592 spec->script = XCAR (otf_spec);
593 if (! NILP (spec->script))
594 {
595 OTF_SYM_TAG (spec->script, spec->script_tag);
596 val = assq_no_quit (spec->script, Votf_script_alist);
597 if (CONSP (val) && SYMBOLP (XCDR (val)))
598 spec->script = XCDR (val);
599 else
600 spec->script = Qnil;
601 }
602 else
603 spec->script_tag = 0x44464C54;
604 otf_spec = XCDR (otf_spec);
605 spec->langsys_tag = 0;
606 if (! NILP (otf_spec))
607 {
608 val = XCAR (otf_spec);
609 if (! NILP (val))
610 OTF_SYM_TAG (val, spec->langsys_tag);
611 otf_spec = XCDR (otf_spec);
612 }
613 spec->nfeatures[0] = spec->nfeatures[1] = 0;
614 for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
615 {
616 val = XCAR (otf_spec);
617 if (NILP (val))
618 continue;
619 ptrdiff_t len = list_length (val);
620 spec->features[i] =
621 (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < len
622 ? 0
623 : malloc (len * sizeof *spec->features[i]));
624 if (! spec->features[i])
625 {
626 if (i > 0 && spec->features[0])
627 free (spec->features[0]);
628 free (spec);
629 return NULL;
630 }
631 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
632 {
633 if (NILP (XCAR (val)))
634 negative = 1;
635 else
636 {
637 unsigned int tag;
638
639 OTF_SYM_TAG (XCAR (val), tag);
640 spec->features[i][j++] = negative ? tag | 0x80000000 : tag;
641 }
642 }
643 spec->nfeatures[i] = j;
644 }
645 return spec;
646 }
647
648 #if defined HAVE_XFT && defined FC_COLOR
649 static bool
650 xft_color_font_whitelisted_p (const char *family)
651 {
652 Lisp_Object tem, name;
653
654 tem = Vxft_color_font_whitelist;
655
656 FOR_EACH_TAIL_SAFE (tem)
657 {
658 name = XCAR (tem);
659
660 if (STRINGP (name) && !strcmp (family, SSDATA (name)))
661 return true;
662 }
663
664 return false;
665 }
666 #endif
667
668 static FcPattern *
669 ftfont_spec_pattern (Lisp_Object spec, char *otlayout,
670 struct OpenTypeSpec **otspec, const char **langname)
671 {
672 Lisp_Object tmp, extra;
673 FcPattern *pattern = NULL;
674 FcCharSet *charset = NULL;
675 FcLangSet *langset = NULL;
676 int n;
677 int dpi = -1;
678 int scalable = -1;
679 Lisp_Object script = Qnil;
680 Lisp_Object registry;
681 int fc_charset_idx;
682
683 if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
684 && n < 100)
685
686 return NULL;
687
688 if (FIXNUMP (AREF (spec, FONT_DPI_INDEX)))
689 dpi = XFIXNUM (AREF (spec, FONT_DPI_INDEX));
690 if (FIXNUMP (AREF (spec, FONT_AVGWIDTH_INDEX))
691 && XFIXNUM (AREF (spec, FONT_AVGWIDTH_INDEX)) == 0)
692 scalable = 1;
693
694 registry = AREF (spec, FONT_REGISTRY_INDEX);
695 if (NILP (registry)
696 || EQ (registry, Qascii_0)
697 || EQ (registry, Qiso10646_1)
698 || EQ (registry, Qunicode_bmp))
699 fc_charset_idx = -1;
700 else
701 {
702 FcChar8 *lang;
703
704 fc_charset_idx = ftfont_get_charset (registry);
705 if (fc_charset_idx < 0)
706 return NULL;
707 charset = fc_charset_table[fc_charset_idx].fc_charset;
708 *langname = fc_charset_table[fc_charset_idx].lang;
709 lang = (FcChar8 *) *langname;
710 if (lang)
711 {
712 langset = FcLangSetCreate ();
713 if (! langset)
714 goto err;
715 FcLangSetAdd (langset, lang);
716 }
717 }
718
719 otlayout[0] = '\0';
720 for (extra = AREF (spec, FONT_EXTRA_INDEX);
721 CONSP (extra); extra = XCDR (extra))
722 {
723 Lisp_Object key, val;
724
725 key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
726 if (EQ (key, QCdpi))
727 {
728 if (FIXNUMP (val))
729 dpi = XFIXNUM (val);
730 }
731 else if (EQ (key, QClang))
732 {
733 if (! langset)
734 langset = FcLangSetCreate ();
735 if (! langset)
736 goto err;
737 if (SYMBOLP (val))
738 {
739 if (! FcLangSetAdd (langset, SYMBOL_FcChar8 (val)))
740 goto err;
741 }
742 else
743 for (; CONSP (val); val = XCDR (val))
744 if (SYMBOLP (XCAR (val))
745 && ! FcLangSetAdd (langset, SYMBOL_FcChar8 (XCAR (val))))
746 goto err;
747 }
748 else if (EQ (key, QCotf))
749 {
750 if (CONSP (val))
751 {
752 *otspec = ftfont_get_open_type_spec (val);
753 if (! *otspec)
754 return NULL;
755 strcpy (otlayout, "otlayout:");
756 OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
757 script = (*otspec)->script;
758 }
759 }
760 else if (EQ (key, QCscript))
761 script = val;
762 else if (EQ (key, QCscalable))
763 scalable = ! NILP (val);
764 }
765
766 if (! NILP (script) && ! charset)
767 {
768 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
769
770 if (CONSP (chars) && CONSP (CDR (chars)))
771 {
772 charset = FcCharSetCreate ();
773 if (! charset)
774 goto err;
775 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
776 if (CHARACTERP (XCAR (chars))
777 && ! FcCharSetAddChar (charset, XFIXNAT (XCAR (chars))))
778 goto err;
779 }
780 }
781
782 pattern = FcPatternCreate ();
783 if (! pattern)
784 goto err;
785 tmp = AREF (spec, FONT_FOUNDRY_INDEX);
786 if (! NILP (tmp)
787 && ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
788 goto err;
789 tmp = AREF (spec, FONT_FAMILY_INDEX);
790 if (! NILP (tmp)
791 && ! FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (tmp)))
792 goto err;
793 if (charset
794 && ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
795 goto err;
796 if (langset
797 && ! FcPatternAddLangSet (pattern, FC_LANG, langset))
798 goto err;
799 if (dpi >= 0
800 && ! FcPatternAddDouble (pattern, FC_DPI, dpi))
801 goto err;
802 if (scalable >= 0
803 && ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
804 goto err;
805 #if defined HAVE_XFT && defined FC_COLOR
806
807
808 if (xft_ignore_color_fonts
809 && (NILP (AREF (spec, FONT_FAMILY_INDEX))
810 || NILP (Vxft_color_font_whitelist))
811 && ! FcPatternAddBool (pattern, FC_COLOR, FcFalse))
812 goto err;
813 #endif
814
815 goto finish;
816
817 err:
818
819
820 if (pattern)
821 {
822 FcPatternDestroy (pattern);
823 pattern = NULL;
824 }
825 if (*otspec)
826 {
827 if ((*otspec)->nfeatures[0] > 0)
828 free ((*otspec)->features[0]);
829 if ((*otspec)->nfeatures[1] > 0)
830 free ((*otspec)->features[1]);
831 free (*otspec);
832 *otspec = NULL;
833 }
834
835 finish:
836 if (langset) FcLangSetDestroy (langset);
837 if (charset && fc_charset_idx < 0) FcCharSetDestroy (charset);
838 return pattern;
839 }
840
841 static Lisp_Object
842 ftfont_list (struct frame *f, Lisp_Object spec)
843 {
844 Lisp_Object val = Qnil, family, adstyle;
845 int i;
846 FcPattern *pattern;
847 FcFontSet *fontset = NULL;
848 FcObjectSet *objset = NULL;
849 FcCharSet *charset;
850 Lisp_Object chars = Qnil;
851 char otlayout[15];
852 struct OpenTypeSpec *otspec = NULL;
853 int spacing = -1;
854 const char *langname = NULL;
855
856 if (! fc_initialized)
857 {
858 FcInit ();
859 fc_initialized = 1;
860 }
861
862 pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
863 if (! pattern)
864 return Qnil;
865 if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
866 {
867 val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
868 if (! NILP (val))
869 {
870 val = assq_no_quit (XCDR (val), Vscript_representative_chars);
871 if (CONSP (val) && VECTORP (XCDR (val)))
872 chars = XCDR (val);
873 }
874 val = Qnil;
875 }
876 if (FIXNUMP (AREF (spec, FONT_SPACING_INDEX)))
877 spacing = XFIXNUM (AREF (spec, FONT_SPACING_INDEX));
878 family = AREF (spec, FONT_FAMILY_INDEX);
879 if (! NILP (family))
880 {
881 Lisp_Object resolved;
882
883 resolved = ftfont_resolve_generic_family (family, pattern);
884 if (! NILP (resolved))
885 {
886 FcPatternDel (pattern, FC_FAMILY);
887 if (! FcPatternAddString (pattern, FC_FAMILY,
888 SYMBOL_FcChar8 (resolved)))
889 goto err;
890 }
891 }
892 adstyle = AREF (spec, FONT_ADSTYLE_INDEX);
893 if (! NILP (adstyle) && SBYTES (SYMBOL_NAME (adstyle)) == 0)
894 adstyle = Qnil;
895 objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
896 FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
897 FC_STYLE, FC_FILE, FC_INDEX,
898 #ifdef FC_CAPABILITY
899 FC_CAPABILITY,
900 #endif
901 #ifdef FC_FONTFORMAT
902 FC_FONTFORMAT,
903 #endif
904 #if defined HAVE_XFT && defined FC_COLOR
905 FC_COLOR,
906 #endif
907 #ifdef FC_VARIABLE
908 FC_VARIABLE,
909 #endif
910 NULL);
911 if (! objset)
912 goto err;
913 if (! NILP (chars))
914 FcObjectSetAdd (objset, FC_CHARSET);
915
916 fontset = FcFontList (NULL, pattern, objset);
917 if (! fontset || fontset->nfont == 0)
918 goto finish;
919 #if 0
920
921 if (fontset->nfont == 0 && ! NILP (family))
922 {
923
924
925
926 FcPattern *pat = FcPatternBuild (0, FC_FAMILY, FcTypeString,
927 SYMBOL_FcChar8 (family), NULL);
928 FcChar8 *fam;
929
930 if (FcConfigSubstitute (NULL, pat, FcMatchPattern) == FcTrue)
931 {
932 for (i = 0;
933 FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
934 i++)
935 {
936 FcPatternDel (pattern, FC_FAMILY);
937 FcPatternAddString (pattern, FC_FAMILY, fam);
938 FcFontSetDestroy (fontset);
939 fontset = FcFontList (NULL, pattern, objset);
940 if (fontset && fontset->nfont > 0)
941 break;
942 }
943 }
944 }
945 #endif
946 for (i = 0; i < fontset->nfont; i++)
947 {
948 Lisp_Object entity;
949 #if defined HAVE_XFT && defined FC_COLOR
950 {
951
952
953
954
955 FcBool b;
956 FcChar8 *str;
957
958 if (xft_ignore_color_fonts
959 && (FcPatternGetString (fontset->fonts[i], FC_FAMILY,
960 0, &str) != FcResultMatch
961 || !xft_color_font_whitelisted_p ((char *) str))
962 && FcPatternGetBool (fontset->fonts[i], FC_COLOR, 0, &b)
963 == FcResultMatch && b != FcFalse)
964 continue;
965 }
966 #endif
967 if (spacing >= 0)
968 {
969 int this;
970
971 if ((FcPatternGetInteger (fontset->fonts[i], FC_SPACING, 0, &this)
972 == FcResultMatch)
973 && spacing != this)
974 continue;
975 }
976
977 #ifdef FC_CAPABILITY
978 if (otlayout[0])
979 {
980 FcChar8 *this;
981
982 if (FcPatternGetString (fontset->fonts[i], FC_CAPABILITY, 0, &this)
983 != FcResultMatch
984 || ! strstr ((char *) this, otlayout))
985 continue;
986 }
987 #endif
988 #if defined HAVE_LIBOTF || defined HAVE_HARFBUZZ
989 if (otspec)
990 {
991 FcChar8 *file;
992 bool passed;
993 OTF *otf;
994
995 if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file)
996 != FcResultMatch)
997 continue;
998 otf = OTF_open ((char *) file);
999 if (! otf)
1000 continue;
1001 passed = (OTF_check_features (otf, 1, otspec->script_tag,
1002 otspec->langsys_tag,
1003 otspec->features[0],
1004 otspec->nfeatures[0]) == 1
1005 && OTF_check_features (otf, 0, otspec->script_tag,
1006 otspec->langsys_tag,
1007 otspec->features[1],
1008 otspec->nfeatures[1]) == 1);
1009 OTF_close (otf);
1010 if (!passed)
1011 continue;
1012 }
1013 #endif
1014 if (VECTORP (chars))
1015 {
1016 ptrdiff_t j;
1017
1018 if (FcPatternGetCharSet (fontset->fonts[i], FC_CHARSET, 0, &charset)
1019 != FcResultMatch)
1020 continue;
1021 for (j = 0; j < ASIZE (chars); j++)
1022 if (TYPE_RANGED_FIXNUMP (FcChar32, AREF (chars, j))
1023 && FcCharSetHasChar (charset, XFIXNAT (AREF (chars, j))))
1024 break;
1025 if (j == ASIZE (chars))
1026 continue;
1027 }
1028 if (! NILP (adstyle) || langname)
1029 {
1030 Lisp_Object this_adstyle = get_adstyle_property (fontset->fonts[i]);
1031
1032 if (! NILP (adstyle)
1033 && (NILP (this_adstyle)
1034 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle)),
1035 SSDATA (SYMBOL_NAME (this_adstyle))) != 0))
1036 continue;
1037 if (langname
1038 && ! NILP (this_adstyle)
1039 && xstrcasecmp (langname, SSDATA (SYMBOL_NAME (this_adstyle))))
1040 continue;
1041 }
1042 entity = ftfont_pattern_entity (fontset->fonts[i],
1043 AREF (spec, FONT_EXTRA_INDEX));
1044 if (! NILP (entity))
1045 val = Fcons (entity, val);
1046 }
1047 val = Fnreverse (val);
1048 goto finish;
1049
1050 err:
1051
1052
1053 val = Qnil;
1054
1055 finish:
1056 FONT_ADD_LOG ("ftfont-list", spec, val);
1057 if (objset) FcObjectSetDestroy (objset);
1058 if (fontset) FcFontSetDestroy (fontset);
1059 if (pattern) FcPatternDestroy (pattern);
1060 return val;
1061 }
1062
1063 Lisp_Object
1064 ftfont_list2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
1065 {
1066 Lisp_Object list = ftfont_list (f, spec);
1067
1068 for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
1069 ASET (XCAR (tail), FONT_TYPE_INDEX, type);
1070 return list;
1071 }
1072
1073 static Lisp_Object
1074 ftfont_match (struct frame *f, Lisp_Object spec)
1075 {
1076 Lisp_Object entity = Qnil;
1077 FcPattern *pattern, *match = NULL;
1078 FcResult result;
1079 char otlayout[15];
1080 struct OpenTypeSpec *otspec = NULL;
1081 const char *langname = NULL;
1082
1083 if (! fc_initialized)
1084 {
1085 FcInit ();
1086 fc_initialized = 1;
1087 }
1088
1089 pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
1090 if (! pattern)
1091 return Qnil;
1092
1093 if (FIXNUMP (AREF (spec, FONT_SIZE_INDEX)))
1094 {
1095 FcValue value;
1096
1097 value.type = FcTypeDouble;
1098 value.u.d = XFIXNUM (AREF (spec, FONT_SIZE_INDEX));
1099 FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse);
1100 }
1101 if (FcConfigSubstitute (NULL, pattern, FcMatchPattern) == FcTrue)
1102 {
1103 FcDefaultSubstitute (pattern);
1104 match = FcFontMatch (NULL, pattern, &result);
1105 if (match)
1106 {
1107 entity = ftfont_pattern_entity (match, AREF (spec, FONT_EXTRA_INDEX));
1108 FcPatternDestroy (match);
1109 if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
1110 && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
1111 ftfont_generic_family_list))
1112 && NILP (Fstring_equal (AREF (spec, FONT_FAMILY_INDEX),
1113 AREF (entity, FONT_FAMILY_INDEX))))
1114 entity = Qnil;
1115 }
1116 }
1117 FcPatternDestroy (pattern);
1118
1119 FONT_ADD_LOG ("ftfont-match", spec, entity);
1120 return entity;
1121 }
1122
1123 Lisp_Object
1124 ftfont_match2 (struct frame *f, Lisp_Object spec, Lisp_Object type)
1125 {
1126 Lisp_Object entity = ftfont_match (f, spec);
1127
1128 if (! NILP (entity))
1129 ASET (entity, FONT_TYPE_INDEX, type);
1130 return entity;
1131 }
1132
1133 Lisp_Object
1134 ftfont_list_family (struct frame *f)
1135 {
1136 Lisp_Object list = Qnil;
1137 FcPattern *pattern = NULL;
1138 FcFontSet *fontset = NULL;
1139 FcObjectSet *objset = NULL;
1140 int i;
1141
1142 if (! fc_initialized)
1143 {
1144 FcInit ();
1145 fc_initialized = 1;
1146 }
1147
1148 pattern = FcPatternCreate ();
1149 if (! pattern)
1150 goto finish;
1151 objset = FcObjectSetBuild (FC_FAMILY, NULL);
1152 if (! objset)
1153 goto finish;
1154 fontset = FcFontList (NULL, pattern, objset);
1155 if (! fontset)
1156 goto finish;
1157
1158 for (i = 0; i < fontset->nfont; i++)
1159 {
1160 FcPattern *pat = fontset->fonts[i];
1161 FcChar8 *str;
1162
1163 if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
1164 list = Fcons (intern ((char *) str), list);
1165 }
1166
1167 finish:
1168 if (objset) FcObjectSetDestroy (objset);
1169 if (fontset) FcFontSetDestroy (fontset);
1170 if (pattern) FcPatternDestroy (pattern);
1171
1172 return list;
1173 }
1174
1175 void
1176 ftfont_fix_match (FcPattern *pat, FcPattern *match)
1177 {
1178
1179
1180
1181
1182
1183 FcBool b = FcTrue;
1184 int i;
1185 double dpi;
1186
1187 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
1188 if (! b)
1189 {
1190 FcPatternDel (match, FC_ANTIALIAS);
1191 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
1192 }
1193 FcPatternGetBool (pat, FC_HINTING, 0, &b);
1194 if (! b)
1195 {
1196 FcPatternDel (match, FC_HINTING);
1197 FcPatternAddBool (match, FC_HINTING, FcFalse);
1198 }
1199 #ifndef FC_HINT_STYLE
1200 # define FC_HINT_STYLE "hintstyle"
1201 #endif
1202 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
1203 {
1204 FcPatternDel (match, FC_HINT_STYLE);
1205 FcPatternAddInteger (match, FC_HINT_STYLE, i);
1206 }
1207 #ifndef FC_LCD_FILTER
1208
1209 #define FC_LCD_FILTER "lcdfilter"
1210 #endif
1211 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
1212 {
1213 FcPatternDel (match, FC_LCD_FILTER);
1214 FcPatternAddInteger (match, FC_LCD_FILTER, i);
1215 }
1216 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
1217 {
1218 FcPatternDel (match, FC_RGBA);
1219 FcPatternAddInteger (match, FC_RGBA, i);
1220 }
1221 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
1222 {
1223 FcPatternDel (match, FC_DPI);
1224 FcPatternAddDouble (match, FC_DPI, dpi);
1225 }
1226 }
1227
1228 void
1229 ftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
1230 {
1231 Lisp_Object tail;
1232 int ival;
1233
1234 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
1235 {
1236 Lisp_Object key = XCAR (XCAR (tail));
1237 Lisp_Object val = XCDR (XCAR (tail));
1238
1239 if (EQ (key, QCantialias))
1240 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
1241 else if (EQ (key, QChinting))
1242 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
1243 else if (EQ (key, QCautohint))
1244 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
1245 else if (EQ (key, QChintstyle))
1246 {
1247 if (FIXNUMP (val))
1248 FcPatternAddInteger (pat, FC_HINT_STYLE, XFIXNUM (val));
1249 else if (SYMBOLP (val)
1250 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
1251 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
1252 }
1253 else if (EQ (key, QCrgba))
1254 {
1255 if (FIXNUMP (val))
1256 FcPatternAddInteger (pat, FC_RGBA, XFIXNUM (val));
1257 else if (SYMBOLP (val)
1258 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
1259 FcPatternAddInteger (pat, FC_RGBA, ival);
1260 }
1261 else if (EQ (key, QClcdfilter))
1262 {
1263 if (FIXNUMP (val))
1264 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XFIXNUM (val));
1265 else if (SYMBOLP (val)
1266 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
1267 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
1268 }
1269 #ifdef FC_EMBOLDEN
1270 else if (EQ (key, QCembolden))
1271 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
1272 #endif
1273 }
1274 }
1275
1276 FcPattern *
1277 ftfont_entity_pattern (Lisp_Object entity, int pixel_size)
1278 {
1279 Lisp_Object val, filename, idx;
1280 FcPattern *pat;
1281 int i;
1282
1283 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
1284 eassert (CONSP (val));
1285 val = XCDR (val);
1286 filename = XCAR (val);
1287 idx = XCDR (val);
1288 pat = FcPatternCreate ();
1289 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
1290 i = FONT_SLANT_NUMERIC (entity) - 100;
1291 if (i < 0) i = 0;
1292 FcPatternAddInteger (pat, FC_SLANT, i);
1293 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
1294 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
1295 val = AREF (entity, FONT_FAMILY_INDEX);
1296 if (! NILP (val))
1297 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
1298 val = AREF (entity, FONT_FOUNDRY_INDEX);
1299 if (! NILP (val))
1300 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
1301 val = AREF (entity, FONT_SPACING_INDEX);
1302 if (! NILP (val))
1303 FcPatternAddInteger (pat, FC_SPACING, XFIXNUM (val));
1304 val = AREF (entity, FONT_DPI_INDEX);
1305 if (! NILP (val))
1306 {
1307 double dbl = XFIXNUM (val);
1308
1309 FcPatternAddDouble (pat, FC_DPI, dbl);
1310 }
1311 val = AREF (entity, FONT_AVGWIDTH_INDEX);
1312 if (FIXNUMP (val) && XFIXNUM (val) == 0)
1313 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
1314
1315
1316 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
1317
1318 ftfont_add_rendering_parameters (pat, entity);
1319
1320 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
1321 FcPatternAddInteger (pat, FC_INDEX, XFIXNUM (idx));
1322
1323 return pat;
1324 }
1325
1326 #ifndef USE_CAIRO
1327
1328 Lisp_Object
1329 ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1330 {
1331 struct font_info *ftfont_info;
1332 struct font *font;
1333 struct ftfont_cache_data *cache_data;
1334 FT_Face ft_face;
1335 FT_Size ft_size;
1336 FT_UInt size;
1337 Lisp_Object val, filename, idx, cache, font_object;
1338 bool scalable;
1339 int spacing;
1340 int i;
1341 double upEM;
1342
1343 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
1344 if (! CONSP (val))
1345 return Qnil;
1346 val = XCDR (val);
1347 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_FACE);
1348 if (NILP (cache))
1349 return Qnil;
1350 filename = XCAR (val);
1351 idx = XCDR (val);
1352 cache_data = xmint_pointer (XCDR (cache));
1353 ft_face = cache_data->ft_face;
1354 if (cache_data->face_refcount > 0)
1355 {
1356
1357 if (FT_New_Size (ft_face, &ft_size) != 0)
1358 return Qnil;
1359 if (FT_Activate_Size (ft_size) != 0)
1360 {
1361 FT_Done_Size (ft_size);
1362 return Qnil;
1363 }
1364 }
1365 size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
1366 if (size == 0)
1367 size = pixel_size;
1368 if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
1369 {
1370 if (cache_data->face_refcount == 0)
1371 {
1372 FT_Done_Face (ft_face);
1373 cache_data->ft_face = NULL;
1374 }
1375 return Qnil;
1376 }
1377 cache_data->face_refcount++;
1378
1379 font_object = font_build_object (VECSIZE (struct font_info),
1380 Qfreetype, entity, size);
1381 ASET (font_object, FONT_FILE_INDEX, filename);
1382 font = XFONT_OBJECT (font_object);
1383 ftfont_info = (struct font_info *) font;
1384 ftfont_info->ft_size = ft_face->size;
1385 ftfont_info->index = XFIXNUM (idx);
1386 #ifdef HAVE_LIBOTF
1387 ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
1388 ftfont_info->otf = NULL;
1389 #endif
1390 #ifdef HAVE_HARFBUZZ
1391 ftfont_info->hb_font = NULL;
1392 #endif
1393
1394 ftfont_info->matrix.xx = 0;
1395 font->pixel_size = size;
1396 #ifdef HAVE_HARFBUZZ
1397 if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qfreetypehb))
1398 font->driver = &fthbfont_driver;
1399 else
1400 #endif
1401 font->driver = &ftfont_driver;
1402 font->encoding_charset = font->repertory_charset = -1;
1403
1404 val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
1405 bool no_leading_p = !(CONSP (val) && NILP (XCDR (val)));
1406 upEM = ft_face->units_per_EM;
1407 scalable = (FIXNUMP (AREF (entity, FONT_AVGWIDTH_INDEX))
1408 && XFIXNUM (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0);
1409 if (scalable)
1410 {
1411 font->ascent = ft_face->ascender * size / upEM + 0.5;
1412 if (no_leading_p)
1413 {
1414 font->descent = - ft_face->descender * size / upEM + 0.5;
1415 font->height = font->ascent + font->descent;
1416 }
1417 else
1418 {
1419 font->height = ft_face->height * size / upEM + 0.5;
1420 font->descent = font->height - font->ascent;
1421 }
1422 }
1423 else
1424 {
1425 font->ascent = ft_face->size->metrics.ascender >> 6;
1426 if (no_leading_p)
1427 {
1428 font->descent = - ft_face->size->metrics.descender >> 6;
1429 font->height = font->ascent + font->descent;
1430 }
1431 else
1432 {
1433 font->height = ft_face->size->metrics.height >> 6;
1434 font->descent = font->height - font->ascent;
1435 }
1436 }
1437 if (FIXNUMP (AREF (entity, FONT_SPACING_INDEX)))
1438 spacing = XFIXNUM (AREF (entity, FONT_SPACING_INDEX));
1439 else
1440 spacing = FC_PROPORTIONAL;
1441 if (spacing != FC_PROPORTIONAL
1442 #ifdef FC_DUAL
1443 && spacing != FC_DUAL
1444 #endif
1445 )
1446 font->min_width = font->average_width = font->space_width
1447 = (scalable ? ft_face->max_advance_width * size / upEM + 0.5
1448 : ft_face->size->metrics.max_advance >> 6);
1449 else
1450 {
1451 int n;
1452
1453 font->min_width = font->average_width = font->space_width = 0;
1454 for (i = 32, n = 0; i < 127; i++)
1455 if (FT_Load_Char (ft_face, i, FT_LOAD_DEFAULT) == 0)
1456 {
1457 int this_width = ft_face->glyph->metrics.horiAdvance >> 6;
1458
1459 if (this_width > 0
1460 && (! font->min_width || font->min_width > this_width))
1461 font->min_width = this_width;
1462 if (i == 32)
1463 font->space_width = this_width;
1464 font->average_width += this_width;
1465 n++;
1466 }
1467 if (n > 0)
1468 font->average_width /= n;
1469 }
1470
1471 font->baseline_offset = 0;
1472 font->relative_compose = 0;
1473 font->default_ascent = 0;
1474 font->vertical_centering = 0;
1475 if (scalable)
1476 {
1477 font->underline_position = (-ft_face->underline_position * size / upEM
1478 + 0.5);
1479 font->underline_thickness = (ft_face->underline_thickness * size / upEM
1480 + 0.5);
1481 }
1482 else
1483 {
1484 font->underline_position = -1;
1485 font->underline_thickness = 0;
1486 }
1487
1488 return font_object;
1489 }
1490
1491 void
1492 ftfont_close (struct font *font)
1493 {
1494 if (font_data_structures_may_be_ill_formed ())
1495 return;
1496
1497 struct font_info *ftfont_info = (struct font_info *) font;
1498 Lisp_Object val, cache;
1499
1500 val = Fcons (font->props[FONT_FILE_INDEX], make_fixnum (ftfont_info->index));
1501 cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE);
1502 eassert (CONSP (cache));
1503 val = XCDR (cache);
1504 struct ftfont_cache_data *cache_data = xmint_pointer (val);
1505 cache_data->face_refcount--;
1506 if (cache_data->face_refcount == 0)
1507 {
1508 FT_Done_Face (cache_data->ft_face);
1509 #ifdef HAVE_LIBOTF
1510 if (ftfont_info->otf)
1511 OTF_close (ftfont_info->otf);
1512 #endif
1513 #ifdef HAVE_HARFBUZZ
1514 if (ftfont_info->hb_font)
1515 hb_font_destroy (ftfont_info->hb_font);
1516 #endif
1517 cache_data->ft_face = NULL;
1518 }
1519 else
1520 FT_Done_Size (ftfont_info->ft_size);
1521 }
1522
1523 #endif
1524
1525 int
1526 ftfont_has_char (Lisp_Object font, int c)
1527 {
1528 struct charset *cs = NULL;
1529
1530 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
1531 && charset_jisx0208 >= 0)
1532 cs = CHARSET_FROM_ID (charset_jisx0208);
1533 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
1534 && charset_ksc5601 >= 0)
1535 cs = CHARSET_FROM_ID (charset_ksc5601);
1536 if (cs)
1537 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
1538
1539 if (FONT_ENTITY_P (font))
1540 {
1541 FcCharSet *charset = ftfont_get_fc_charset (font);
1542
1543 return (FcCharSetHasChar (charset, c) == FcTrue);
1544 }
1545 else
1546 {
1547 struct font_info *ftfont_info;
1548
1549 ftfont_info = (struct font_info *) XFONT_OBJECT (font);
1550 return (FT_Get_Char_Index (ftfont_info->ft_size->face, (FT_ULong) c)
1551 != 0);
1552 }
1553 }
1554
1555 #ifndef USE_CAIRO
1556
1557 unsigned
1558 ftfont_encode_char (struct font *font, int c)
1559 {
1560 struct font_info *ftfont_info = (struct font_info *) font;
1561 FT_Face ft_face = ftfont_info->ft_size->face;
1562 FT_ULong charcode = c;
1563 FT_UInt code = FT_Get_Char_Index (ft_face, charcode);
1564
1565 return (code > 0 ? code : FONT_INVALID_CODE);
1566 }
1567
1568 static bool
1569 ftfont_glyph_metrics (FT_Face ft_face, int c, int *advance, int *lbearing,
1570 int *rbearing, int *ascent, int *descent)
1571 {
1572 if (FT_Load_Glyph (ft_face, c, FT_LOAD_DEFAULT) == 0)
1573 {
1574 FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
1575 *advance = m->horiAdvance >> 6;
1576 *lbearing = m->horiBearingX >> 6;
1577 *rbearing = (m->horiBearingX + m->width) >> 6;
1578 *ascent = m->horiBearingY >> 6;
1579 *descent = (m->height - m->horiBearingY) >> 6;
1580 return true;
1581 }
1582
1583 return false;
1584 }
1585
1586 void
1587 ftfont_text_extents (struct font *font, const unsigned int *code,
1588 int nglyphs, struct font_metrics *metrics)
1589 {
1590 struct font_info *ftfont_info = (struct font_info *) font;
1591 FT_Face ft_face = ftfont_info->ft_size->face;
1592 int i, width = 0;
1593 bool first;
1594
1595 if (ftfont_info->ft_size != ft_face->size)
1596 FT_Activate_Size (ftfont_info->ft_size);
1597
1598 for (i = 0, first = 1; i < nglyphs; i++)
1599 {
1600 int advance, lbearing, rbearing, ascent, descent;
1601 if (ftfont_glyph_metrics (ft_face, code[i], &advance, &lbearing,
1602 &rbearing, &ascent, &descent))
1603 {
1604 if (first)
1605 {
1606 metrics->lbearing = lbearing;
1607 metrics->rbearing = rbearing;
1608 metrics->ascent = ascent;
1609 metrics->descent = descent;
1610 first = 0;
1611 }
1612 if (metrics->lbearing > width + lbearing)
1613 metrics->lbearing = width + lbearing;
1614 if (metrics->rbearing < width + rbearing)
1615 metrics->rbearing = width + rbearing;
1616 if (metrics->ascent < ascent)
1617 metrics->ascent = ascent;
1618 if (metrics->descent > descent)
1619 metrics->descent = descent;
1620 width += advance;
1621 }
1622 else
1623 width += font->space_width;
1624 }
1625 metrics->width = width;
1626 }
1627
1628 #endif
1629
1630 int
1631 ftfont_get_bitmap (struct font *font, unsigned int code, struct font_bitmap *bitmap, int bits_per_pixel)
1632 {
1633 struct font_info *ftfont_info = (struct font_info *) font;
1634 FT_Face ft_face = ftfont_info->ft_size->face;
1635 FT_Int32 load_flags = FT_LOAD_RENDER;
1636
1637 if (ftfont_info->ft_size != ft_face->size)
1638 FT_Activate_Size (ftfont_info->ft_size);
1639 if (bits_per_pixel == 1)
1640 {
1641 #ifdef FT_LOAD_TARGET_MONO
1642 load_flags |= FT_LOAD_TARGET_MONO;
1643 #else
1644 load_flags |= FT_LOAD_MONOCHROME;
1645 #endif
1646 }
1647 else if (bits_per_pixel != 8)
1648
1649 return -1;
1650
1651 if (FT_Load_Glyph (ft_face, code, load_flags) != 0)
1652 return -1;
1653 bitmap->bits_per_pixel
1654 = (ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 1
1655 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY ? 8
1656 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD ? 8
1657 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V ? 8
1658 : -1);
1659 if (bitmap->bits_per_pixel < 0)
1660
1661 return -1;
1662 bitmap->rows = ft_face->glyph->bitmap.rows;
1663 bitmap->width = ft_face->glyph->bitmap.width;
1664 bitmap->pitch = ft_face->glyph->bitmap.pitch;
1665 bitmap->buffer = ft_face->glyph->bitmap.buffer;
1666 bitmap->left = ft_face->glyph->bitmap_left;
1667 bitmap->top = ft_face->glyph->bitmap_top;
1668 bitmap->advance = ft_face->glyph->metrics.horiAdvance >> 6;
1669
1670 return 0;
1671 }
1672
1673 int
1674 ftfont_anchor_point (struct font *font, unsigned int code, int idx,
1675 int *x, int *y)
1676 {
1677 struct font_info *ftfont_info = (struct font_info *) font;
1678 FT_Face ft_face = ftfont_info->ft_size->face;
1679
1680 if (ftfont_info->ft_size != ft_face->size)
1681 FT_Activate_Size (ftfont_info->ft_size);
1682 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
1683 return -1;
1684 if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
1685 return -1;
1686 if (idx >= ft_face->glyph->outline.n_points)
1687 return -1;
1688 *x = ft_face->glyph->outline.points[idx].x;
1689 *y = ft_face->glyph->outline.points[idx].y;
1690 return 0;
1691 }
1692
1693 #ifdef HAVE_LIBOTF
1694
1695 static Lisp_Object
1696 ftfont_otf_features (OTF_GSUB_GPOS *gsub_gpos)
1697 {
1698 Lisp_Object scripts, langsyses, features, sym;
1699 int i, j, k, l;
1700
1701 for (scripts = Qnil, i = gsub_gpos->ScriptList.ScriptCount - 1; i >= 0; i--)
1702 {
1703 OTF_Script *otf_script = gsub_gpos->ScriptList.Script + i;
1704
1705 for (langsyses = Qnil, j = otf_script->LangSysCount - 1; j >= -1; j--)
1706 {
1707 OTF_LangSys *otf_langsys;
1708
1709 if (j >= 0)
1710 otf_langsys = otf_script->LangSys + j;
1711 else if (otf_script->DefaultLangSysOffset)
1712 otf_langsys = &otf_script->DefaultLangSys;
1713 else
1714 break;
1715
1716 for (features = Qnil, k = otf_langsys->FeatureCount - 1; k >= 0; k--)
1717 {
1718 l = otf_langsys->FeatureIndex[k];
1719 if (l >= gsub_gpos->FeatureList.FeatureCount)
1720 continue;
1721 OTF_TAG_SYM (sym, gsub_gpos->FeatureList.Feature[l].FeatureTag);
1722 features = Fcons (sym, features);
1723 }
1724 if (j >= 0)
1725 OTF_TAG_SYM (sym, otf_script->LangSysRecord[j].LangSysTag);
1726 else
1727 sym = Qnil;
1728 langsyses = Fcons (Fcons (sym, features), langsyses);
1729 }
1730
1731 OTF_TAG_SYM (sym, gsub_gpos->ScriptList.Script[i].ScriptTag);
1732 scripts = Fcons (Fcons (sym, langsyses), scripts);
1733 }
1734 return scripts;
1735
1736 }
1737
1738
1739 Lisp_Object
1740 ftfont_otf_capability (struct font *font)
1741 {
1742 struct font_info *ftfont_info = (struct font_info *) font;
1743 OTF *otf = ftfont_get_otf (ftfont_info);
1744 Lisp_Object gsub_gpos;
1745
1746 if (! otf)
1747 return Qnil;
1748 gsub_gpos = Fcons (Qnil, Qnil);
1749 if (OTF_get_table (otf, "GSUB") == 0
1750 && otf->gsub->FeatureList.FeatureCount > 0)
1751 XSETCAR (gsub_gpos, ftfont_otf_features (otf->gsub));
1752 if (OTF_get_table (otf, "GPOS") == 0
1753 && otf->gpos->FeatureList.FeatureCount > 0)
1754 XSETCDR (gsub_gpos, ftfont_otf_features (otf->gpos));
1755 return gsub_gpos;
1756 }
1757
1758 #ifdef HAVE_M17N_FLT
1759
1760 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1761 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1762
1763
1764
1765 #define M17N_FLT_USE_NEW_FEATURE
1766 #endif
1767
1768 struct MFLTFontFT
1769 {
1770 MFLTFont flt_font;
1771 struct font *font;
1772 FT_Face ft_face;
1773 OTF *otf;
1774 FT_Matrix *matrix;
1775 };
1776
1777
1778
1779
1780
1781
1782
1783
1784 typedef struct {
1785 MFLTGlyph g;
1786 unsigned int libotf_positioning_type;
1787 } MFLTGlyphFT;
1788
1789 static int
1790 ftfont_get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring,
1791 int from, int to)
1792 {
1793 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1794 FT_Face ft_face = flt_font_ft->ft_face;
1795 MFLTGlyphFT *g;
1796
1797 for (g = (MFLTGlyphFT *) (gstring->glyphs) + from; from < to; g++, from++)
1798 if (! g->g.encoded)
1799 {
1800 FT_UInt code = FT_Get_Char_Index (ft_face, g->g.code);
1801
1802 g->g.code = code > 0 ? code : FONT_INVALID_CODE;
1803 g->g.encoded = 1;
1804 }
1805 return 0;
1806 }
1807
1808
1809
1810 #define FLOOR(x) ((x) & -64)
1811 #define CEIL(x) (((x)+63) & -64)
1812 #define ROUND(x) (((x)+32) & -64)
1813
1814 static int
1815 ftfont_get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
1816 int from, int to)
1817 {
1818 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1819 FT_Face ft_face = flt_font_ft->ft_face;
1820 MFLTGlyphFT *g;
1821
1822 for (g = (MFLTGlyphFT *) (gstring->glyphs) + from; from < to; g++, from++)
1823 if (! g->g.measured)
1824 {
1825 if (g->g.code != FONT_INVALID_CODE)
1826 {
1827 FT_Glyph_Metrics *m;
1828
1829 if (FT_Load_Glyph (ft_face, g->g.code, FT_LOAD_DEFAULT) != 0
1830 && FT_Load_Glyph (ft_face, g->g.code, FT_LOAD_NO_HINTING) != 0)
1831 emacs_abort ();
1832 m = &ft_face->glyph->metrics;
1833 if (flt_font_ft->matrix)
1834 {
1835 FT_Vector v[4];
1836 int i;
1837
1838 v[0].x = v[1].x = m->horiBearingX;
1839 v[2].x = v[3].x = m->horiBearingX + m->width;
1840 v[0].y = v[2].y = m->horiBearingY;
1841 v[1].y = v[3].y = m->horiBearingY - m->height;
1842 for (i = 0; i < 4; i++)
1843 FT_Vector_Transform (v + i, flt_font_ft->matrix);
1844 g->g.lbearing = v[0].x < v[1].x ? FLOOR (v[0].x) : FLOOR (v[1].x);
1845 g->g.rbearing = v[2].x > v[3].x ? CEIL (v[2].x) : CEIL (v[3].x);
1846 g->g.ascent = v[0].y > v[2].y ? CEIL (v[0].y) : CEIL (v[2].y);
1847 g->g.descent = v[1].y < v[3].y ? - FLOOR (v[1].y) : - FLOOR (v[3].y);
1848 }
1849 else
1850 {
1851 g->g.lbearing = FLOOR (m->horiBearingX);
1852 g->g.rbearing = CEIL (m->horiBearingX + m->width);
1853 g->g.ascent = CEIL (m->horiBearingY);
1854 g->g.descent = - FLOOR (m->horiBearingY - m->height);
1855 }
1856 g->g.xadv = ROUND (ft_face->glyph->advance.x);
1857 }
1858 else
1859 {
1860 g->g.lbearing = 0;
1861 g->g.rbearing = g->g.xadv = flt_font_ft->font->space_width << 6;
1862 g->g.ascent = flt_font_ft->font->ascent << 6;
1863 g->g.descent = flt_font_ft->font->descent << 6;
1864 }
1865 g->g.yadv = 0;
1866 g->g.measured = 1;
1867 }
1868 return 0;
1869 }
1870
1871 static int
1872 ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1873 {
1874 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1875
1876 #define FEATURE_ANY(IDX) \
1877 (spec->features[IDX] \
1878 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1879
1880 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1881 OTF *otf = flt_font_ft->otf;
1882 OTF_Tag *tags;
1883 int i, n;
1884 bool negative;
1885
1886 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1887
1888
1889 return (otf
1890 && (OTF_check_features (otf, 0, spec->script, spec->langsys,
1891 NULL, 0) > 0
1892 || OTF_check_features (otf, 1, spec->script, spec->langsys,
1893 NULL, 0) > 0));
1894
1895 for (i = 0; i < 2; i++)
1896 if (! FEATURE_ANY (i))
1897 {
1898 if (FEATURE_NONE (i))
1899 {
1900 if (otf
1901 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1902 NULL, 0) > 0)
1903 return 0;
1904 continue;
1905 }
1906 if (spec->features[i][0] == 0xFFFFFFFF)
1907 {
1908 if (! otf
1909 || OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1910 NULL, 0) <= 0)
1911 continue;
1912 }
1913 else if (! otf)
1914 return 0;
1915 for (n = 1; spec->features[i][n]; n++);
1916 USE_SAFE_ALLOCA;
1917 SAFE_NALLOCA (tags, 1, n);
1918 for (n = 0, negative = 0; spec->features[i][n]; n++)
1919 {
1920 if (spec->features[i][n] == 0xFFFFFFFF)
1921 negative = 1;
1922 else if (negative)
1923 tags[n - 1] = spec->features[i][n] | 0x80000000;
1924 else
1925 tags[n] = spec->features[i][n];
1926 }
1927 bool passed = true;
1928 #ifndef M17N_FLT_USE_NEW_FEATURE
1929 passed = n - negative > 0;
1930 #endif
1931 if (passed)
1932 passed = (OTF_check_features (otf, i == 0, spec->script,
1933 spec->langsys, tags, n - negative)
1934 != 1);
1935 SAFE_FREE ();
1936 if (passed)
1937 return 0;
1938 }
1939 return 1;
1940 #undef FEATURE_NONE
1941 #undef FEATURE_ANY
1942 }
1943
1944 #define DEVICE_DELTA(table, size) \
1945 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1946 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1947 : 0)
1948
1949 static void
1950 adjust_anchor (FT_Face ft_face, OTF_Anchor *anchor,
1951 unsigned code, int x_ppem, int y_ppem, int *x, int *y)
1952 {
1953 if (anchor->AnchorFormat == 2)
1954 {
1955 FT_Outline *outline;
1956 int ap = anchor->f.f1.AnchorPoint;
1957
1958 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
1959 outline = &ft_face->glyph->outline;
1960 if (ap < outline->n_points)
1961 {
1962 *x = outline->points[ap].x << 6;
1963 *y = outline->points[ap].y << 6;
1964 }
1965 }
1966 else if (anchor->AnchorFormat == 3)
1967 {
1968 if (anchor->f.f2.XDeviceTable.offset
1969 && anchor->f.f2.XDeviceTable.DeltaValue)
1970 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
1971 if (anchor->f.f2.YDeviceTable.offset
1972 && anchor->f.f2.YDeviceTable.DeltaValue)
1973 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
1974 }
1975 }
1976
1977 static OTF_GlyphString otf_gstring;
1978
1979 static void
1980 setup_otf_gstring (int size)
1981 {
1982 if (otf_gstring.size < size)
1983 {
1984 ptrdiff_t new_size = otf_gstring.size;
1985 xfree (otf_gstring.glyphs);
1986 otf_gstring.glyphs = xpalloc (NULL, &new_size, size - otf_gstring.size,
1987 INT_MAX, sizeof *otf_gstring.glyphs);
1988 otf_gstring.size = new_size;
1989 }
1990 otf_gstring.used = size;
1991 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size);
1992 }
1993
1994 #ifdef M17N_FLT_USE_NEW_FEATURE
1995
1996
1997 #define PACK_OTF_TAG(TAG) \
1998 ((((TAG) & 0x7F000000) >> 3) \
1999 | (((TAG) & 0x7F0000) >> 2) \
2000 | (((TAG) & 0x7F00) >> 1) \
2001 | ((TAG) & 0x7F))
2002
2003
2004
2005
2006
2007
2008
2009 static int
2010 ftfont_drive_otf (MFLTFont *font,
2011 MFLTOtfSpec *spec,
2012 MFLTGlyphString *in,
2013 int from,
2014 int to,
2015 MFLTGlyphString *out,
2016 MFLTGlyphAdjustment *adjustment)
2017 {
2018 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
2019 MFLTGlyphFT *in_glyphs = (MFLTGlyphFT *) (in->glyphs) + from;
2020 MFLTGlyphFT *out_glyphs = out ? (MFLTGlyphFT *) (out->glyphs) : NULL;
2021 FT_Face ft_face = flt_font_ft->ft_face;
2022 OTF *otf = flt_font_ft->otf;
2023 int len = to - from;
2024 int i, j, gidx;
2025 OTF_Glyph *otfg;
2026 char script[5], *langsys = NULL;
2027 char *gsub_features = NULL, *gpos_features = NULL;
2028 OTF_Feature *features;
2029
2030 if (len == 0)
2031 return from;
2032 OTF_tag_name (spec->script, script);
2033
2034 char langsysbuf[5];
2035 if (spec->langsys)
2036 {
2037 langsys = langsysbuf;
2038 OTF_tag_name (spec->langsys, langsys);
2039 }
2040
2041 USE_SAFE_ALLOCA;
2042 for (i = 0; i < 2; i++)
2043 {
2044 char *p;
2045
2046 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
2047 {
2048 for (j = 0; spec->features[i][j]; j++);
2049 SAFE_NALLOCA (p, 6, j);
2050 if (i == 0)
2051 gsub_features = p;
2052 else
2053 gpos_features = p;
2054 for (j = 0; spec->features[i][j]; j++)
2055 {
2056 if (spec->features[i][j] == 0xFFFFFFFF)
2057 *p++ = '*', *p++ = ',';
2058 else
2059 {
2060 OTF_tag_name (spec->features[i][j], p);
2061 p[4] = ',';
2062 p += 5;
2063 }
2064 }
2065 *--p = '\0';
2066 }
2067 }
2068
2069 setup_otf_gstring (len);
2070 for (i = 0; i < len; i++)
2071 {
2072 otf_gstring.glyphs[i].c = in_glyphs[i].g.c & 0x11FFFF;
2073 otf_gstring.glyphs[i].glyph_id = in_glyphs[i].g.code;
2074 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2075 otf_gstring.glyphs[i].positioning_type = in_glyphs[i].libotf_positioning_type;
2076 #endif
2077 }
2078
2079 OTF_drive_gdef (otf, &otf_gstring);
2080 gidx = out ? out->used : from;
2081
2082 if (gsub_features && out)
2083 {
2084 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2085 if (OTF_drive_gsub_features (otf, &otf_gstring, script, langsys,
2086 gsub_features) < 0)
2087 goto simple_copy;
2088 #else
2089 if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
2090 gsub_features) < 0)
2091 goto simple_copy;
2092 #endif
2093 if (out->allocated < out->used + otf_gstring.used)
2094 {
2095 SAFE_FREE ();
2096 return -2;
2097 }
2098 features = otf->gsub->FeatureList.Feature;
2099 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
2100 {
2101 MFLTGlyphFT *g;
2102 int min_from, max_to;
2103 int feature_idx;
2104
2105 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2106 feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg);
2107 #else
2108 feature_idx = otfg->positioning_type >> 4;
2109 #endif
2110 g = out_glyphs + out->used;
2111 *g = in_glyphs[otfg->f.index.from];
2112 if (g->g.code != otfg->glyph_id)
2113 {
2114 g->g.c = 0;
2115 g->g.code = otfg->glyph_id;
2116 g->g.measured = 0;
2117 }
2118 out->used++;
2119 min_from = g->g.from;
2120 max_to = g->g.to;
2121 if (otfg->f.index.from < otfg->f.index.to)
2122 {
2123
2124 for (j = otfg->f.index.from + 1; j <= otfg->f.index.to; j++)
2125 {
2126 if (min_from > in_glyphs[j].g.from)
2127 min_from = in_glyphs[j].g.from;
2128 if (max_to < in_glyphs[j].g.to)
2129 max_to = in_glyphs[j].g.to;
2130 }
2131 g->g.from = min_from;
2132 g->g.to = max_to;
2133 }
2134 if (feature_idx)
2135 {
2136 unsigned int tag = features[feature_idx - 1].FeatureTag;
2137 tag = PACK_OTF_TAG (tag);
2138 g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
2139 }
2140 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2141 g->libotf_positioning_type
2142 = otfg->positioning_type & OTF_positioning_type_components_mask;
2143 #endif
2144 for (i++, otfg++; (i < otf_gstring.used
2145 && otfg->f.index.from == otfg[-1].f.index.from);
2146 i++, otfg++)
2147 {
2148 g = out_glyphs + out->used;
2149 *g = in_glyphs[otfg->f.index.to];
2150 if (g->g.code != otfg->glyph_id)
2151 {
2152 g->g.c = 0;
2153 g->g.code = otfg->glyph_id;
2154 g->g.measured = 0;
2155 }
2156 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2157 feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg);
2158 #else
2159 feature_idx = otfg->positioning_type >> 4;
2160 #endif
2161 if (feature_idx)
2162 {
2163 unsigned int tag = features[feature_idx - 1].FeatureTag;
2164 tag = PACK_OTF_TAG (tag);
2165 g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
2166 }
2167 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2168 g->libotf_positioning_type
2169 = otfg->positioning_type & OTF_positioning_type_components_mask;
2170 #endif
2171 out->used++;
2172 }
2173 }
2174 }
2175 else if (gsub_features)
2176 {
2177
2178 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2179 if (OTF_drive_gsub_features (otf, &otf_gstring, script, langsys,
2180 gsub_features) < 0)
2181 goto simple_copy;
2182 #else
2183 if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
2184 gsub_features) < 0)
2185 goto simple_copy;
2186 #endif
2187 features = otf->gsub->FeatureList.Feature;
2188 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++,
2189 otfg++)
2190 {
2191 int feature_idx;
2192 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2193 feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg);
2194 #else
2195 feature_idx = otfg->positioning_type >> 4;
2196 #endif
2197 if (feature_idx)
2198 {
2199 unsigned int tag = features[feature_idx - 1].FeatureTag;
2200 tag = PACK_OTF_TAG (tag);
2201 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
2202 {
2203 MFLTGlyphFT *g = in_glyphs + j;
2204 g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
2205 }
2206 }
2207 }
2208 }
2209 else if (out)
2210 {
2211 if (out->allocated < out->used + len)
2212 {
2213 SAFE_FREE ();
2214 return -2;
2215 }
2216 for (i = 0; i < len; i++)
2217 out_glyphs[out->used++] = in_glyphs[i];
2218 }
2219
2220 if (gpos_features && out)
2221 {
2222 MFLTGlyphFT *base = NULL, *mark = NULL, *g;
2223 int x_ppem, y_ppem, x_scale, y_scale;
2224
2225 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2226 if (OTF_drive_gpos_features (otf, &otf_gstring, script, langsys,
2227 gpos_features) < 0)
2228 {
2229 SAFE_FREE ();
2230 return to;
2231 }
2232 #else
2233 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
2234 gpos_features) < 0)
2235 {
2236 SAFE_FREE ();
2237 return to;
2238 }
2239 #endif
2240 features = otf->gpos->FeatureList.Feature;
2241 x_ppem = ft_face->size->metrics.x_ppem;
2242 y_ppem = ft_face->size->metrics.y_ppem;
2243 x_scale = ft_face->size->metrics.x_scale;
2244 y_scale = ft_face->size->metrics.y_scale;
2245
2246 for (i = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx;
2247 i < otf_gstring.used; i++, otfg++)
2248 {
2249 MFLTGlyphAdjustment *adjust = adjustment;
2250 MFLTGlyphFT *prev;
2251 int positioning_type, feature_idx;
2252
2253 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2254 positioning_type = OTF_POSITIONING_TYPE_GET_FORMAT (otfg);
2255 feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg);
2256 #else
2257 positioning_type = otfg->positioning_type & 0xF;
2258 feature_idx = otfg->positioning_type >> 4;
2259 #endif
2260 if (feature_idx)
2261 {
2262 unsigned int tag = features[feature_idx - 1].FeatureTag;
2263 tag = PACK_OTF_TAG (tag);
2264 g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
2265 }
2266
2267 if (! otfg->glyph_id)
2268
2269
2270 adjust--;
2271 switch (positioning_type)
2272 {
2273 case 0:
2274 break;
2275 case 1:
2276 case 2:
2277 {
2278 int format = otfg->f.f1.format;
2279
2280 if (format & OTF_XPlacement)
2281 adjust->xoff
2282 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
2283 if (format & OTF_XPlaDevice)
2284 adjust->xoff
2285 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
2286 if (format & OTF_YPlacement)
2287 adjust->yoff
2288 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
2289 if (format & OTF_YPlaDevice)
2290 adjust->yoff
2291 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
2292 if (format & OTF_XAdvance)
2293 adjust->xadv
2294 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
2295 if (format & OTF_XAdvDevice)
2296 adjust->xadv
2297 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
2298 if (format & OTF_YAdvance)
2299 adjust->yadv
2300 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
2301 if (format & OTF_YAdvDevice)
2302 adjust->yadv
2303 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
2304 adjust->set = 1;
2305 }
2306 break;
2307 case 3:
2308
2309 break;
2310 case 4:
2311 case 5:
2312 if (! base)
2313 break;
2314 prev = base;
2315 goto label_adjust_anchor;
2316 default:
2317 if (! mark)
2318 break;
2319 prev = mark;
2320 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2321 {
2322 int distance = OTF_POSITIONING_TYPE_GET_MARKDISTANCE (otfg);
2323
2324 if (distance > 0)
2325 {
2326 prev = g - distance;
2327 if (prev < out_glyphs)
2328 prev = mark;
2329 }
2330 }
2331 #endif
2332
2333 label_adjust_anchor:
2334 {
2335 int base_x, base_y, mark_x, mark_y;
2336 int this_from, this_to;
2337
2338 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
2339 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
2340 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
2341 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
2342
2343 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2344 adjust_anchor (ft_face, otfg->f.f4.base_anchor, prev->g.code,
2345 x_ppem, y_ppem, &base_x, &base_y);
2346 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2347 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->g.code,
2348 x_ppem, y_ppem, &mark_x, &mark_y);
2349 adjust->xoff = (base_x - mark_x);
2350 adjust->yoff = - (base_y - mark_y);
2351 adjust->back = (g - prev);
2352 adjust->xadv = 0;
2353 adjust->advance_is_absolute = 1;
2354 adjust->set = 1;
2355 this_from = g->g.from;
2356 this_to = g->g.to;
2357 for (j = 0; prev + j < g; j++)
2358 {
2359 if (this_from > prev[j].g.from)
2360 this_from = prev[j].g.from;
2361 if (this_to < prev[j].g.to)
2362 this_to = prev[j].g.to;
2363 }
2364 for (; prev <= g; prev++)
2365 {
2366 prev->g.from = this_from;
2367 prev->g.to = this_to;
2368 }
2369 }
2370 }
2371 if (otfg->glyph_id)
2372 {
2373 if (otfg->GlyphClass == OTF_GlyphClass0)
2374 base = mark = g;
2375 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2376 mark = g;
2377 else
2378 base = g;
2379 g++, adjustment++;
2380 }
2381 }
2382 }
2383 else if (gpos_features)
2384 {
2385 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
2386 gpos_features) < 0)
2387 {
2388 SAFE_FREE ();
2389 return to;
2390 }
2391 features = otf->gpos->FeatureList.Feature;
2392 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
2393 i++, otfg++)
2394 if (otfg->positioning_type & 0xF)
2395 {
2396 int feature_idx = otfg->positioning_type >> 4;
2397
2398 if (feature_idx)
2399 {
2400 unsigned int tag = features[feature_idx - 1].FeatureTag;
2401 tag = PACK_OTF_TAG (tag);
2402 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
2403 {
2404 MFLTGlyphFT *g = in_glyphs + j;
2405 g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
2406 }
2407 }
2408 }
2409 }
2410 SAFE_FREE ();
2411 return to;
2412
2413 simple_copy:
2414 SAFE_FREE ();
2415 if (! out)
2416 return to;
2417 if (out->allocated < out->used + len)
2418 return -2;
2419 font->get_metrics (font, in, from, to);
2420 memcpy (out->glyphs + out->used, in_glyphs, sizeof (MFLTGlyphFT) * len);
2421 out->used += len;
2422 return to;
2423 }
2424
2425 static int
2426 ftfont_try_otf (MFLTFont *font, MFLTOtfSpec *spec,
2427 MFLTGlyphString *in, int from, int to)
2428 {
2429 return ftfont_drive_otf (font, spec, in, from, to, NULL, NULL);
2430 }
2431
2432 #else
2433
2434 static int
2435 ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2436 int from, int to,
2437 MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
2438 {
2439 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
2440 MFLTGlyphFT *in_glyphs = (MFLTGlyphFT *) (in->glyphs) + from;
2441 MFLTGlyphFT *out_glyphs = out ? (MFLTGlyphFT *) (out->glyphs) : NULL;
2442 FT_Face ft_face = flt_font_ft->ft_face;
2443 OTF *otf = flt_font_ft->otf;
2444 int len = to - from;
2445 int i, j, gidx;
2446 OTF_Glyph *otfg;
2447 char script[5], *langsys = NULL;
2448 char *gsub_features = NULL, *gpos_features = NULL;
2449
2450 if (len == 0)
2451 return from;
2452 OTF_tag_name (spec->script, script);
2453
2454 char langsysbuf[5];
2455 if (spec->langsys)
2456 {
2457 langsys = langsysbuf;
2458 OTF_tag_name (spec->langsys, langsys);
2459 }
2460
2461 USE_SAFE_ALLOCA;
2462 for (i = 0; i < 2; i++)
2463 {
2464 char *p;
2465
2466 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
2467 {
2468 for (j = 0; spec->features[i][j]; j++);
2469 SAFE_NALLOCA (p, 6, j);
2470 if (i == 0)
2471 gsub_features = p;
2472 else
2473 gpos_features = p;
2474 for (j = 0; spec->features[i][j]; j++)
2475 {
2476 if (spec->features[i][j] == 0xFFFFFFFF)
2477 *p++ = '*', *p++ = ',';
2478 else
2479 {
2480 OTF_tag_name (spec->features[i][j], p);
2481 p[4] = ',';
2482 p += 5;
2483 }
2484 }
2485 *--p = '\0';
2486 }
2487 }
2488
2489 setup_otf_gstring (len);
2490 for (i = 0; i < len; i++)
2491 {
2492 otf_gstring.glyphs[i].c = in_glyphs[i].g.c;
2493 otf_gstring.glyphs[i].glyph_id = in_glyphs[i].g.code;
2494 }
2495
2496 OTF_drive_gdef (otf, &otf_gstring);
2497 gidx = out->used;
2498
2499 if (gsub_features)
2500 {
2501 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
2502 < 0)
2503 goto simple_copy;
2504 if (out->allocated < out->used + otf_gstring.used)
2505 {
2506 SAFE_FREE ();
2507 return -2;
2508 }
2509 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
2510 {
2511 MFLTGlyphFT *g;
2512 int min_from, max_to;
2513 int j;
2514
2515 g = out_glyphs + out->used;
2516 *g = in_glyphs[otfg->f.index.from];
2517 if (g->g.code != otfg->glyph_id)
2518 {
2519 g->g.c = 0;
2520 g->g.code = otfg->glyph_id;
2521 g->g.measured = 0;
2522 }
2523 out->used++;
2524 min_from = g->g.from;
2525 max_to = g->g.to;
2526 if (otfg->f.index.from < otfg->f.index.to)
2527 {
2528
2529 for (j = from + otfg->f.index.from + 1;
2530 j <= from + otfg->f.index.to; j++)
2531 {
2532 if (min_from > in->glyphs[j].from)
2533 min_from = in->glyphs[j].from;
2534 if (max_to < in->glyphs[j].to)
2535 max_to = in->glyphs[j].to;
2536 }
2537 g->g.from = min_from;
2538 g->g.to = max_to;
2539 }
2540 for (i++, otfg++; (i < otf_gstring.used
2541 && otfg->f.index.from == otfg[-1].f.index.from);
2542 i++, otfg++)
2543 {
2544 g = out_glyphs + out->used;
2545 *g = in_glyphs[otfg->f.index.to];
2546 if (g->g.code != otfg->glyph_id)
2547 {
2548 g->g.c = 0;
2549 g->g.code = otfg->glyph_id;
2550 g->g.measured = 0;
2551 }
2552 out->used++;
2553 }
2554 }
2555 }
2556 else
2557 {
2558 if (out->allocated < out->used + len)
2559 {
2560 SAFE_FREE ();
2561 return -2;
2562 }
2563 for (i = 0; i < len; i++)
2564 out_glyphs[out->used++] = in_glyphs[i];
2565 }
2566
2567 if (gpos_features)
2568 {
2569 MFLTGlyphFT *base = NULL, *mark = NULL, *g;
2570 int x_ppem, y_ppem, x_scale, y_scale;
2571
2572 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
2573 < 0)
2574 {
2575 SAFE_FREE ();
2576 return to;
2577 }
2578
2579 x_ppem = ft_face->size->metrics.x_ppem;
2580 y_ppem = ft_face->size->metrics.y_ppem;
2581 x_scale = ft_face->size->metrics.x_scale;
2582 y_scale = ft_face->size->metrics.y_scale;
2583
2584 for (i = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx;
2585 i < otf_gstring.used; i++, otfg++, g++)
2586 {
2587 MFLTGlyphFT *prev;
2588
2589 if (! otfg->glyph_id)
2590 continue;
2591 switch (otfg->positioning_type)
2592 {
2593 case 0:
2594 break;
2595 case 1:
2596 case 2:
2597 {
2598 int format = otfg->f.f1.format;
2599
2600 if (format & OTF_XPlacement)
2601 adjustment[i].xoff
2602 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
2603 if (format & OTF_XPlaDevice)
2604 adjustment[i].xoff
2605 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
2606 if (format & OTF_YPlacement)
2607 adjustment[i].yoff
2608 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
2609 if (format & OTF_YPlaDevice)
2610 adjustment[i].yoff
2611 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
2612 if (format & OTF_XAdvance)
2613 adjustment[i].xadv
2614 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
2615 if (format & OTF_XAdvDevice)
2616 adjustment[i].xadv
2617 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
2618 if (format & OTF_YAdvance)
2619 adjustment[i].yadv
2620 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
2621 if (format & OTF_YAdvDevice)
2622 adjustment[i].yadv
2623 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
2624 adjustment[i].set = 1;
2625 }
2626 break;
2627 case 3:
2628
2629 break;
2630 case 4:
2631 case 5:
2632 if (! base)
2633 break;
2634 prev = base;
2635 goto label_adjust_anchor;
2636 default:
2637 if (! mark)
2638 break;
2639 prev = mark;
2640
2641 label_adjust_anchor:
2642 {
2643 int base_x, base_y, mark_x, mark_y;
2644 int this_from, this_to;
2645
2646 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
2647 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
2648 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
2649 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
2650
2651 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2652 adjust_anchor (ft_face, otfg->f.f4.base_anchor, prev->g.code,
2653 x_ppem, y_ppem, &base_x, &base_y);
2654 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2655 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->g.code,
2656 x_ppem, y_ppem, &mark_x, &mark_y);
2657 adjustment[i].xoff = (base_x - mark_x);
2658 adjustment[i].yoff = - (base_y - mark_y);
2659 adjustment[i].back = (g - prev);
2660 adjustment[i].xadv = 0;
2661 adjustment[i].advance_is_absolute = 1;
2662 adjustment[i].set = 1;
2663 this_from = g->g.from;
2664 this_to = g->g.to;
2665 for (j = 0; prev + j < g; j++)
2666 {
2667 if (this_from > prev[j].g.from)
2668 this_from = prev[j].g.from;
2669 if (this_to < prev[j].g.to)
2670 this_to = prev[j].g.to;
2671 }
2672 for (; prev <= g; prev++)
2673 {
2674 prev->g.from = this_from;
2675 prev->g.to = this_to;
2676 }
2677 }
2678 }
2679 if (otfg->GlyphClass == OTF_GlyphClass0)
2680 base = mark = g;
2681 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2682 mark = g;
2683 else
2684 base = g;
2685 }
2686 }
2687 SAFE_FREE ();
2688 return to;
2689
2690 simple_copy:
2691 SAFE_FREE ();
2692 if (out->allocated < out->used + len)
2693 return -2;
2694 font->get_metrics (font, in, from, to);
2695 memcpy (out_glyphs + out->used, in_glyphs,
2696 sizeof (MFLTGlyphFT) * len);
2697 out->used += len;
2698 return to;
2699 }
2700
2701 #endif
2702
2703 static MFLTGlyphString gstring;
2704
2705 static bool m17n_flt_initialized;
2706
2707 static Lisp_Object
2708 ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
2709 FT_Face ft_face, OTF *otf, FT_Matrix *matrix)
2710 {
2711 ptrdiff_t len = LGSTRING_GLYPH_LEN (lgstring);
2712 ptrdiff_t i;
2713 struct MFLTFontFT flt_font_ft;
2714 MFLT *flt = NULL;
2715 bool with_variation_selector = false;
2716
2717 if (! m17n_flt_initialized)
2718 {
2719 M17N_INIT ();
2720 #ifdef M17N_FLT_USE_NEW_FEATURE
2721 mflt_enable_new_feature = 1;
2722 mflt_try_otf = ftfont_try_otf;
2723 #endif
2724 m17n_flt_initialized = 1;
2725 }
2726
2727 for (i = 0; i < len; i++)
2728 {
2729 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
2730 int c;
2731
2732 if (NILP (g))
2733 break;
2734 c = LGLYPH_CHAR (g);
2735 if (CHAR_VARIATION_SELECTOR_P (c))
2736 with_variation_selector = true;
2737 }
2738
2739 len = i;
2740
2741 if (otf && with_variation_selector)
2742 {
2743 setup_otf_gstring (len);
2744 for (i = 0; i < len; i++)
2745 {
2746 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
2747
2748 otf_gstring.glyphs[i].c = LGLYPH_CHAR (g);
2749 otf_gstring.glyphs[i].f.index.from = LGLYPH_FROM (g);
2750 otf_gstring.glyphs[i].f.index.to = LGLYPH_TO (g);
2751 }
2752 OTF_drive_cmap (otf, &otf_gstring);
2753 for (i = 0; i < otf_gstring.used; i++)
2754 {
2755 OTF_Glyph *otfg = otf_gstring.glyphs + i;
2756 Lisp_Object g0 = LGSTRING_GLYPH (lgstring, otfg->f.index.from);
2757 Lisp_Object g1 = LGSTRING_GLYPH (lgstring, otfg->f.index.to);
2758
2759 LGLYPH_SET_CODE (g0, otfg->glyph_id);
2760 LGLYPH_SET_TO (g0, LGLYPH_TO (g1));
2761 LGSTRING_SET_GLYPH (lgstring, i, g0);
2762 }
2763 if (len > otf_gstring.used)
2764 {
2765 len = otf_gstring.used;
2766 LGSTRING_SET_GLYPH (lgstring, len, Qnil);
2767 }
2768 }
2769
2770 {
2771 Lisp_Object family = Ffont_get (LGSTRING_FONT (lgstring), QCfamily);
2772
2773 if (NILP (family))
2774 flt_font_ft.flt_font.family = Mnil;
2775 else
2776 flt_font_ft.flt_font.family
2777 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family))));
2778 }
2779 flt_font_ft.flt_font.x_ppem = ft_face->size->metrics.x_ppem;
2780 flt_font_ft.flt_font.y_ppem = ft_face->size->metrics.y_ppem;
2781 flt_font_ft.flt_font.get_glyph_id = ftfont_get_glyph_id;
2782 flt_font_ft.flt_font.get_metrics = ftfont_get_metrics;
2783 flt_font_ft.flt_font.check_otf = ftfont_check_otf;
2784 flt_font_ft.flt_font.drive_otf = ftfont_drive_otf;
2785 flt_font_ft.flt_font.internal = NULL;
2786 flt_font_ft.font = font;
2787 flt_font_ft.ft_face = ft_face;
2788 flt_font_ft.otf = otf;
2789 flt_font_ft.matrix = matrix->xx != 0 ? matrix : 0;
2790
2791 if (1 < len)
2792 {
2793
2794
2795
2796 int c1 = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 1));
2797
2798
2799
2800
2801 if ((0x300 <= c1 && c1 <= 0x36F)
2802 || (! otf && CHAR_HAS_CATEGORY (c1, '^')))
2803 flt = mflt_get (msymbol ("combining"));
2804 }
2805 if (! flt && ! otf)
2806 {
2807 flt = mflt_find (LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 0)),
2808 &flt_font_ft.flt_font);
2809 if (! flt)
2810 return make_fixnum (0);
2811 }
2812
2813 MFLTGlyphFT *glyphs = (MFLTGlyphFT *) gstring.glyphs;
2814 ptrdiff_t allocated = gstring.allocated;
2815 ptrdiff_t incr_min = len - allocated;
2816
2817 do
2818 {
2819 if (0 < incr_min)
2820 {
2821 xfree (glyphs);
2822 glyphs = xpalloc (NULL, &allocated, incr_min, INT_MAX, sizeof *glyphs);
2823 }
2824 incr_min = 1;
2825
2826 for (i = 0; i < len; i++)
2827 {
2828 Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
2829 memset (&glyphs[i], 0, sizeof glyphs[i]);
2830 glyphs[i].g.c = LGLYPH_CHAR (g);
2831 if (with_variation_selector)
2832 {
2833 glyphs[i].g.code = LGLYPH_CODE (g);
2834 glyphs[i].g.encoded = 1;
2835 }
2836 }
2837
2838 gstring.glyph_size = sizeof *glyphs;
2839 gstring.glyphs = (MFLTGlyph *) glyphs;
2840 gstring.allocated = allocated;
2841 gstring.used = len;
2842 gstring.r2l = 0;
2843 }
2844 while (mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt) == -2);
2845
2846 if (gstring.used > LGSTRING_GLYPH_LEN (lgstring))
2847 return Qnil;
2848
2849
2850
2851
2852 for (i = 0; i < gstring.used; i++)
2853 {
2854 MFLTGlyphFT *g = (MFLTGlyphFT *) (gstring.glyphs) + i;
2855 if (g->g.to >= len)
2856 {
2857
2858 g->g.to = len - 1;
2859 int from = g->g.from;
2860
2861 for (++i; i < gstring.used; i++)
2862 {
2863 g = (MFLTGlyphFT *) (gstring.glyphs) + i;
2864 g->g.from = from;
2865 g->g.to = len - 1;
2866 }
2867 }
2868 }
2869
2870 for (i = 0; i < gstring.used; i++)
2871 {
2872 MFLTGlyphFT *g = (MFLTGlyphFT *) (gstring.glyphs) + i;
2873 g->g.from = LGLYPH_FROM (LGSTRING_GLYPH (lgstring, g->g.from));
2874 g->g.to = LGLYPH_TO (LGSTRING_GLYPH (lgstring, g->g.to));
2875 }
2876
2877 for (i = 0; i < gstring.used; i++)
2878 {
2879 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
2880 MFLTGlyphFT *g = (MFLTGlyphFT *) (gstring.glyphs) + i;
2881
2882 if (NILP (lglyph))
2883 {
2884 lglyph = LGLYPH_NEW ();
2885 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
2886 }
2887 LGLYPH_SET_FROM (lglyph, g->g.from);
2888 LGLYPH_SET_TO (lglyph, g->g.to);
2889 LGLYPH_SET_CHAR (lglyph, g->g.c);
2890 LGLYPH_SET_CODE (lglyph, g->g.code);
2891 LGLYPH_SET_WIDTH (lglyph, g->g.xadv >> 6);
2892 LGLYPH_SET_LBEARING (lglyph, g->g.lbearing >> 6);
2893 LGLYPH_SET_RBEARING (lglyph, g->g.rbearing >> 6);
2894 LGLYPH_SET_ASCENT (lglyph, g->g.ascent >> 6);
2895 LGLYPH_SET_DESCENT (lglyph, g->g.descent >> 6);
2896 if (g->g.adjusted)
2897 LGLYPH_SET_ADJUSTMENT (lglyph, CALLN (Fvector,
2898 make_fixnum (g->g.xoff >> 6),
2899 make_fixnum (g->g.yoff >> 6),
2900 make_fixnum (g->g.xadv >> 6)));
2901 }
2902 return make_fixnum (i);
2903 }
2904
2905 Lisp_Object
2906 ftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
2907 {
2908 struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
2909 struct font_info *ftfont_info = (struct font_info *) font;
2910 OTF *otf = ftfont_get_otf (ftfont_info);
2911
2912 return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf,
2913 &ftfont_info->matrix);
2914 }
2915
2916 #endif
2917
2918 #endif
2919
2920 #if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
2921 int
2922 ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
2923 {
2924 struct font_info *ftfont_info = (struct font_info *) font;
2925 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2926 OTF *otf = ftfont_get_otf (ftfont_info);
2927
2928 if (! otf)
2929 return 0;
2930 return OTF_get_variation_glyphs (otf, c, variations);
2931 #else
2932 FT_Face ft_face = ftfont_info->ft_size->face;
2933 int i, n = 0;
2934
2935 for (i = 0; i < 16; i++)
2936 {
2937 variations[i] = FT_Face_GetCharVariantIndex (ft_face, c, 0xFE00 + i);
2938 if (variations[i])
2939 n++;
2940 }
2941 for (; i < 256; i++)
2942 {
2943 variations[i] = FT_Face_GetCharVariantIndex (ft_face, c,
2944 0xE0100 + (i - 16));
2945 if (variations[i])
2946 n++;
2947 }
2948
2949 return n;
2950 #endif
2951 }
2952 #endif
2953
2954 #ifdef HAVE_HARFBUZZ
2955
2956 hb_font_t *
2957 fthbfont_begin_hb_font (struct font *font, double *position_unit)
2958 {
2959 struct font_info *ftfont_info = (struct font_info *) font;
2960
2961 *position_unit = 1.0 / (1 << 6);
2962 if (! ftfont_info->hb_font)
2963 ftfont_info->hb_font
2964 = hb_ft_font_create_referenced (ftfont_info->ft_size->face);
2965 return ftfont_info->hb_font;
2966 }
2967
2968 #ifndef HAVE_LIBOTF
2969 #include <hb-ot.h>
2970
2971 static OTF *
2972 hbotf_open (const char *name)
2973 {
2974 FT_Face ft_face;
2975
2976 if (! ft_library
2977 && FT_Init_FreeType (&ft_library) != 0)
2978 return NULL;
2979 if (FT_New_Face (ft_library, name, 0, &ft_face)
2980 != 0)
2981 return NULL;
2982
2983 hb_face_t *face = hb_ft_face_create_referenced (ft_face);
2984 FT_Done_Face (ft_face);
2985
2986 return face;
2987 }
2988
2989 static int
2990 hbotf_check_features (OTF *otf, int gsubp,
2991 OTF_tag script, OTF_tag language,
2992 const OTF_tag *features, int n_features)
2993 {
2994 hb_face_t *face = otf;
2995 hb_tag_t table_tag = gsubp ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS;
2996 hb_tag_t script_tag = script, language_tag = language;
2997
2998 unsigned int script_count
2999 = hb_ot_layout_table_get_script_tags (face, table_tag, 0, NULL, NULL);
3000 hb_tag_t *script_tags = xnmalloc (script_count, sizeof *script_tags);
3001 hb_ot_layout_table_get_script_tags (face, table_tag, 0, &script_count,
3002 script_tags);
3003 unsigned int script_index;
3004 for (script_index = 0; script_index < script_count; script_index++)
3005 if (script_tags[script_index] == script_tag)
3006 break;
3007 xfree (script_tags);
3008 if (script_index == script_count)
3009 return 0;
3010
3011 unsigned int language_index;
3012 if (language_tag == 0)
3013 language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
3014 else
3015 {
3016 unsigned int language_count
3017 = hb_ot_layout_script_get_language_tags (face, table_tag, script_index,
3018 0, NULL, NULL);
3019 hb_tag_t *language_tags = xnmalloc (language_count,
3020 sizeof *language_tags);
3021 hb_ot_layout_script_get_language_tags (face, table_tag, script_index, 0,
3022 &language_count, language_tags);
3023 for (language_index = 0; language_index < script_count; language_index++)
3024 if (language_tags[language_index] == language_tag)
3025 break;
3026 xfree (language_tags);
3027 if (language_index == language_count)
3028 return 0;
3029 }
3030
3031 for (int j = 0; j < n_features; j++)
3032 {
3033 hb_tag_t feature_tag = features[j];
3034 hb_bool_t negate = 0;
3035
3036 if (feature_tag == 0)
3037 continue;
3038 if (feature_tag & 0x80000000)
3039 {
3040 feature_tag &= 0x7FFFFFFF;
3041 negate = 1;
3042 }
3043
3044 unsigned int feature_index;
3045 if (hb_ot_layout_language_find_feature (face, table_tag, script_index,
3046 language_index, feature_tag,
3047 &feature_index) == negate)
3048 return 0;
3049 }
3050 return 1;
3051 }
3052 #endif
3053 #endif
3054
3055 static const char *const ftfont_booleans [] = {
3056 ":antialias",
3057 ":hinting",
3058 ":verticallayout",
3059 ":autohint",
3060 ":globaladvance",
3061 ":outline",
3062 ":scalable",
3063 ":minspace",
3064 ":embolden",
3065 NULL,
3066 };
3067
3068 static const char *const ftfont_non_booleans [] = {
3069 ":family",
3070 ":familylang",
3071 ":style",
3072 ":stylelang",
3073 ":fullname",
3074 ":fullnamelang",
3075 ":slant",
3076 ":weight",
3077 ":size",
3078 ":width",
3079 ":aspect",
3080 ":pixelsize",
3081 ":spacing",
3082 ":foundry",
3083 ":hintstyle",
3084 ":file",
3085 ":index",
3086 ":ftface",
3087 ":rasterizer",
3088 ":scale",
3089 ":dpi",
3090 ":rgba",
3091 ":lcdfilter",
3092 ":charset",
3093 ":lang",
3094 ":fontversion",
3095 ":capability",
3096 NULL,
3097 };
3098
3099 void
3100 ftfont_filter_properties (Lisp_Object font, Lisp_Object alist)
3101 {
3102 font_filter_properties (font, alist, ftfont_booleans, ftfont_non_booleans);
3103 }
3104
3105
3106 Lisp_Object
3107 ftfont_combining_capability (struct font *font)
3108 {
3109 #ifdef HAVE_M17N_FLT
3110 return Qt;
3111 #else
3112 return Qnil;
3113 #endif
3114 }
3115
3116 static void syms_of_ftfont_for_pdumper (void);
3117
3118 #ifndef USE_CAIRO
3119
3120 static struct font_driver const ftfont_driver =
3121 {
3122
3123 .type = LISPSYM_INITIALLY (Qfreetype),
3124 .get_cache = ftfont_get_cache,
3125 .list = ftfont_list,
3126 .match = ftfont_match,
3127 .list_family = ftfont_list_family,
3128 .open_font = ftfont_open,
3129 .close_font = ftfont_close,
3130 .has_char = ftfont_has_char,
3131 .encode_char = ftfont_encode_char,
3132 .text_extents = ftfont_text_extents,
3133 .get_bitmap = ftfont_get_bitmap,
3134 .anchor_point = ftfont_anchor_point,
3135 #ifdef HAVE_LIBOTF
3136 .otf_capability = ftfont_otf_capability,
3137 #endif
3138 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
3139 .shape = ftfont_shape,
3140 #endif
3141 #if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
3142 .get_variation_glyphs = ftfont_variation_glyphs,
3143 #endif
3144 .filter_properties = ftfont_filter_properties,
3145 .combining_capability = ftfont_combining_capability,
3146 };
3147
3148 #endif
3149
3150 void
3151 syms_of_ftfont (void)
3152 {
3153
3154 DEFSYM (Qfreetype, "freetype");
3155 #ifdef HAVE_HARFBUZZ
3156 DEFSYM (Qfreetypehb, "freetypehb");
3157 Fput (Qfreetype, Qfont_driver_superseded_by, Qfreetypehb);
3158 #endif
3159
3160 #ifdef HAVE_HAIKU
3161 DEFSYM (Qmono, "mono");
3162 #endif
3163
3164
3165 DEFSYM (Qmonospace, "monospace");
3166 DEFSYM (Qsans_serif, "sans-serif");
3167 DEFSYM (Qsans, "sans");
3168 DEFSYM (Qsans__serif, "sans serif");
3169
3170
3171 DEFSYM (QCminspace, ":minspace");
3172
3173
3174 DEFSYM (QChinting, ":hinting");
3175 DEFSYM (QCautohint, ":autohint");
3176 DEFSYM (QChintstyle, ":hintstyle");
3177 DEFSYM (QCrgba, ":rgba");
3178 DEFSYM (QCembolden, ":embolden");
3179 DEFSYM (QClcdfilter, ":lcdfilter");
3180
3181 staticpro (&freetype_font_cache);
3182 freetype_font_cache = list1 (Qt);
3183
3184 staticpro (&ftfont_generic_family_list);
3185 ftfont_generic_family_list = list3 (Fcons (Qmonospace, Qt),
3186 Fcons (Qsans_serif, Qt),
3187 Fcons (Qsans, Qt));
3188
3189 staticpro (&ft_face_cache);
3190 ft_face_cache = Qnil;
3191
3192 pdumper_do_now_and_after_load (syms_of_ftfont_for_pdumper);
3193 }
3194
3195 static void
3196 syms_of_ftfont_for_pdumper (void)
3197 {
3198 PDUMPER_RESET_LV (ft_face_cache, Qnil);
3199 register_font_driver (&ftfont_driver, NULL);
3200 #ifdef HAVE_HARFBUZZ
3201 fthbfont_driver = ftfont_driver;
3202 fthbfont_driver.type = Qfreetypehb;
3203 fthbfont_driver.otf_capability = hbfont_otf_capability;
3204 fthbfont_driver.shape = hbfont_shape;
3205 fthbfont_driver.combining_capability = hbfont_combining_capability;
3206 fthbfont_driver.begin_hb_font = fthbfont_begin_hb_font;
3207 register_font_driver (&fthbfont_driver, NULL);
3208 #endif
3209 }