aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ftfont.c416
1 files changed, 273 insertions, 143 deletions
diff --git a/src/ftfont.c b/src/ftfont.c
index 62bbb9bca4c..ba157119936 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -51,7 +51,7 @@ static FT_Library ft_library;
51/* Cache for FreeType fonts. */ 51/* Cache for FreeType fonts. */
52static Lisp_Object freetype_font_cache; 52static Lisp_Object freetype_font_cache;
53 53
54/* Cache for FT_Face */ 54/* Cache for FT_Face and FcCharSet. */
55static Lisp_Object ft_face_cache; 55static Lisp_Object ft_face_cache;
56 56
57/* The actual structure for FreeType font that can be casted to struct 57/* The actual structure for FreeType font that can be casted to struct
@@ -60,96 +60,99 @@ static Lisp_Object ft_face_cache;
60struct ftfont_info 60struct ftfont_info
61{ 61{
62 struct font font; 62 struct font font;
63 FT_Size ft_size;
64 int fc_charset_idx;
65#ifdef HAVE_LIBOTF 63#ifdef HAVE_LIBOTF
64 /* The following three members must be here in this order to be
65 compatible with struct xftfont_info (in xftfont.c). */
66 int maybe_otf; /* Flag to tell if this may be OTF or not. */ 66 int maybe_otf; /* Flag to tell if this may be OTF or not. */
67 OTF *otf; 67 OTF *otf;
68#endif /* HAVE_LIBOTF */ 68#endif /* HAVE_LIBOTF */
69 FT_Size ft_size;
70 int index;
69}; 71};
70 72
71static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object, 73static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object));
72 Lisp_Object, int));
73 74
74static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object, 75static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object,
75 FcPattern *)); 76 FcPattern *));
77static Lisp_Object ftfont_lookup_cache P_ ((Lisp_Object, int));
78
76Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object)); 79Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
77 80
78#define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM)) 81#define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
79 82
80static struct 83static struct
81{ 84{
82 /* charset name */ 85 /* registry name */
83 char *name; 86 char *name;
84 /* characters to distinguish the charset from the others */ 87 /* characters to distinguish the charset from the others */
85 int uniquifier[6]; 88 int uniquifier[6];
86 /* additional constraint by language */ 89 /* additional constraint by language */
87 char *lang; 90 char *lang;
88 /* set in syms_of_ftfont */
89 int charset_id;
90 /* set on demand */ 91 /* set on demand */
91 FcCharSet *fc_charset; 92 FcCharSet *fc_charset;
92} fc_charset_table[] = 93} fc_charset_table[] =
93 { { "iso-8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 }, "en", -1 }, 94 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
94 { "iso-8859-2", { 0x00A0, 0x010E }}, 95 { "iso8859-2", { 0x00A0, 0x010E }},
95 { "iso-8859-3", { 0x00A0, 0x0108 }}, 96 { "iso8859-3", { 0x00A0, 0x0108 }},
96 { "iso-8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }}, 97 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
97 { "iso-8859-5", { 0x00A0, 0x0401 }}, 98 { "iso8859-5", { 0x00A0, 0x0401 }},
98 { "iso-8859-6", { 0x00A0, 0x060C }}, 99 { "iso8859-6", { 0x00A0, 0x060C }},
99 { "iso-8859-7", { 0x00A0, 0x0384 }}, 100 { "iso8859-7", { 0x00A0, 0x0384 }},
100 { "iso-8859-8", { 0x00A0, 0x05D0 }}, 101 { "iso8859-8", { 0x00A0, 0x05D0 }},
101 { "iso-8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }}, 102 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
102 { "iso-8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }}, 103 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
103 { "iso-8859-11", { 0x00A0, 0x0E01 }}, 104 { "iso8859-11", { 0x00A0, 0x0E01 }},
104 { "iso-8859-13", { 0x00A0, 0x201C }}, 105 { "iso8859-13", { 0x00A0, 0x201C }},
105 { "iso-8859-14", { 0x00A0, 0x0174 }}, 106 { "iso8859-14", { 0x00A0, 0x0174 }},
106 { "iso-8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }}, 107 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
107 { "iso-8859-16", { 0x00A0, 0x0218}}, 108 { "iso8859-16", { 0x00A0, 0x0218}},
108 { "chinese-gb2312", { 0x4E13 }, "zh-cn"}, 109 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
109 { "big5", { 0xF6B1 }, "zh-tw" }, 110 { "big5-0", { 0xF6B1 }, "zh-tw" },
110 { "japanese-jisx0208", { 0x4E55 }, "ja"}, 111 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
111 { "korean-ksc5601", { 0xAC00 }, "ko"}, 112 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
112 { "chinese-cns11643-1", { 0xFE32 }, "zh-tw"}, 113 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
113 { "chinese-cns11643-2", { 0x4E33, 0x7934 }}, 114 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
114 { "chinese-cns11643-3", { 0x201A9 }}, 115 { "cns11643.1992-3", { 0x201A9 }},
115 { "chinese-cns11643-4", { 0x20057 }}, 116 { "cns11643.1992-4", { 0x20057 }},
116 { "chinese-cns11643-5", { 0x20000 }}, 117 { "cns11643.1992-5", { 0x20000 }},
117 { "chinese-cns11643-6", { 0x20003 }}, 118 { "cns11643.1992-6", { 0x20003 }},
118 { "chinese-cns11643-7", { 0x20055 }}, 119 { "cns11643.1992-7", { 0x20055 }},
119 { "chinese-gbk", { 0x4E06 }, "zh-cn"}, 120 { "gbk-0", { 0x4E06 }, "zh-cn"},
120 { "japanese-jisx0212", { 0x4E44 }}, 121 { "jisx0212.1990-0", { 0x4E44 }},
121 { "japanese-jisx0213-1", { 0xFA10 }, "ja"}, 122 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
122 { "japanese-jisx0213-2", { 0xFA49 }}, 123 { "jisx0213.2000-2", { 0xFA49 }},
123 { "japanese-jisx0213.2004-1", { 0x20B9F }}, 124 { "jisx0213.2004-1", { 0x20B9F }},
124 { "viscii", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"}, 125 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
125 { "tis620", { 0x0E01 }, "th"}, 126 { "tis620.2529-1", { 0x0E01 }, "th"},
126 { "windows-1251", { 0x0401, 0x0490 }, "ru"}, 127 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
127 { "koi8-r", { 0x0401, 0x2219 }, "ru"}, 128 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
128 { "mule-lao", { 0x0E81 }, "lo"}, 129 { "mulelao-1", { 0x0E81 }, "lo"},
129 { NULL } 130 { NULL }
130 }; 131 };
131 132
132extern Lisp_Object Qc, Qm, Qp, Qd; 133extern Lisp_Object Qc, Qm, Qp, Qd;
133 134
134static Lisp_Object 135static Lisp_Object
135ftfont_pattern_entity (p, registry, extra, fc_charset_idx) 136ftfont_pattern_entity (p, extra)
136 FcPattern *p; 137 FcPattern *p;
137 Lisp_Object registry, extra; 138 Lisp_Object extra;
138 int fc_charset_idx;
139{ 139{
140 Lisp_Object entity; 140 Lisp_Object entity;
141 char *file, *str; 141 char *file, *str;
142 int index;
142 int numeric; 143 int numeric;
143 double dbl; 144 double dbl;
144 FcBool b; 145 FcBool b;
145 146
146 if (FcPatternGetString (p, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch) 147 if (FcPatternGetString (p, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
147 return Qnil; 148 return Qnil;
149 if (FcPatternGetInteger (p, FC_INDEX, 0, &index) != FcResultMatch)
150 return Qnil;
148 151
149 entity = font_make_entity (); 152 entity = font_make_entity ();
150 153
151 ASET (entity, FONT_TYPE_INDEX, Qfreetype); 154 ASET (entity, FONT_TYPE_INDEX, Qfreetype);
152 ASET (entity, FONT_REGISTRY_INDEX, registry); 155 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
153 156
154 if (FcPatternGetString (p, FC_FOUNDRY, 0, (FcChar8 **) &str) == FcResultMatch) 157 if (FcPatternGetString (p, FC_FOUNDRY, 0, (FcChar8 **) &str) == FcResultMatch)
155 ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (str, strlen (str), 1)); 158 ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (str, strlen (str), 1));
@@ -189,7 +192,7 @@ ftfont_pattern_entity (p, registry, extra, fc_charset_idx)
189 font_put_extra (entity, QCfont_entity, 192 font_put_extra (entity, QCfont_entity,
190 Fcons (make_unibyte_string ((char *) file, 193 Fcons (make_unibyte_string ((char *) file,
191 strlen ((char *) file)), 194 strlen ((char *) file)),
192 make_number (fc_charset_idx))); 195 make_number (index)));
193 return entity; 196 return entity;
194} 197}
195 198
@@ -239,35 +242,116 @@ ftfont_resolve_generic_family (family, pattern)
239 return family; 242 return family;
240} 243}
241 244
242Lisp_Object 245struct ftfont_cache_data
243ftfont_lookup_cache (filename) 246{
244 Lisp_Object filename; 247 FT_Face ft_face;
248 FcCharSet *fc_charset;
249};
250
251static Lisp_Object
252ftfont_lookup_cache (key, for_face)
253 Lisp_Object key;
254 int for_face;
245{ 255{
246 Lisp_Object cache, val; 256 Lisp_Object cache, val;
257 struct ftfont_cache_data *cache_data;
247 258
248 cache = assoc_no_quit (filename, ft_face_cache); 259 cache = assoc_no_quit (key, ft_face_cache);
249 if (NILP (cache)) 260 if (NILP (cache))
250 { 261 {
262 cache_data = xmalloc (sizeof (struct ftfont_cache_data));
263 cache_data->ft_face = NULL;
264 cache_data->fc_charset = NULL;
251 val = make_save_value (NULL, 0); 265 val = make_save_value (NULL, 0);
252 cache = Fcons (filename, val); 266 XSAVE_VALUE (val)->integer = 0;
267 XSAVE_VALUE (val)->pointer = cache_data;
268 cache = Fcons (key, val);
253 ft_face_cache = Fcons (cache, ft_face_cache); 269 ft_face_cache = Fcons (cache, ft_face_cache);
254 } 270 }
255 else 271 else
256 val = XCDR (cache);
257 if (! XSAVE_VALUE (val)->pointer)
258 { 272 {
259 FT_Face ft_face; 273 val = XCDR (cache);
274 cache_data = XSAVE_VALUE (val)->pointer;
275 }
276 if (for_face ? ! cache_data->ft_face : ! cache_data->fc_charset)
277 {
278 char *filename = (char *) SDATA (XCAR (key));
279 int index = XINT (XCDR (key));
260 280
261 if (! ft_library 281 if (for_face)
262 && FT_Init_FreeType (&ft_library) != 0) 282 {
263 return Qnil; 283 if (! ft_library
264 if (FT_New_Face (ft_library, (char *) SDATA (filename), 0, &ft_face) != 0) 284 && FT_Init_FreeType (&ft_library) != 0)
265 return Qnil; 285 return Qnil;
266 XSAVE_VALUE (val)->pointer = ft_face; 286 if (FT_New_Face (ft_library, filename, index, &cache_data->ft_face)
287 != 0)
288 return Qnil;
289 }
290 else
291 {
292 FcPattern *pat;
293 FcFontSet *fontset;
294 FcObjectSet *objset;
295 FcCharSet *charset;
296
297 pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename,
298 FC_INDEX, FcTypeInteger, index, NULL);
299 objset = FcObjectSetBuild (FC_CHARSET, NULL);
300 fontset = FcFontList (NULL, pat, objset);
301 xassert (fontset && fontset->nfont > 0);
302 if (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0, &charset)
303 == FcResultMatch)
304 cache_data->fc_charset = FcCharSetCopy (charset);
305 else
306 cache_data->fc_charset = FcCharSetCreate ();
307 FcFontSetDestroy (fontset);
308 FcObjectSetDestroy (objset);
309 FcPatternDestroy (pat);
310 }
267 } 311 }
268 return cache; 312 return cache;
269} 313}
270 314
315FcCharSet *
316ftfont_get_fc_charset (entity)
317 Lisp_Object entity;
318{
319 Lisp_Object val, cache;
320 struct ftfont_cache_data *cache_data;
321
322 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
323 xassert (CONSP (val));
324 val = XCDR (val);
325 cache = ftfont_lookup_cache (val, 0);
326 val = XCDR (cache);
327 cache_data = XSAVE_VALUE (val)->pointer;
328 return cache_data->fc_charset;
329}
330
331#ifdef HAVE_LIBOTF
332static OTF *
333ftfont_get_otf (ftfont_info)
334 struct ftfont_info *ftfont_info;
335{
336 OTF *otf;
337
338 if (ftfont_info->otf)
339 return ftfont_info->otf;
340 if (! ftfont_info->maybe_otf)
341 return NULL;
342 otf = OTF_open_ft_face (ftfont_info->ft_size->face);
343 if (! otf || OTF_get_table (otf, "head") < 0)
344 {
345 if (otf)
346 OTF_close (otf);
347 ftfont_info->maybe_otf = 0;
348 return NULL;
349 }
350 ftfont_info->otf = otf;
351 return otf;
352}
353#endif /* HAVE_LIBOTF */
354
271static Lisp_Object ftfont_get_cache P_ ((FRAME_PTR)); 355static Lisp_Object ftfont_get_cache P_ ((FRAME_PTR));
272static Lisp_Object ftfont_list P_ ((Lisp_Object, Lisp_Object)); 356static Lisp_Object ftfont_list P_ ((Lisp_Object, Lisp_Object));
273static Lisp_Object ftfont_match P_ ((Lisp_Object, Lisp_Object)); 357static Lisp_Object ftfont_match P_ ((Lisp_Object, Lisp_Object));
@@ -282,6 +366,7 @@ static int ftfont_get_bitmap P_ ((struct font *, unsigned,
282 struct font_bitmap *, int)); 366 struct font_bitmap *, int));
283static int ftfont_anchor_point P_ ((struct font *, unsigned, int, 367static int ftfont_anchor_point P_ ((struct font *, unsigned, int,
284 int *, int *)); 368 int *, int *));
369static Lisp_Object ftfont_otf_capability P_ ((struct font *));
285static Lisp_Object ftfont_shape P_ ((Lisp_Object)); 370static Lisp_Object ftfont_shape P_ ((Lisp_Object));
286 371
287struct font_driver ftfont_driver = 372struct font_driver ftfont_driver =
@@ -308,7 +393,11 @@ struct font_driver ftfont_driver =
308 NULL, 393 NULL,
309 NULL, 394 NULL,
310 ftfont_anchor_point, 395 ftfont_anchor_point,
396#ifdef HAVE_LIBOTF
397 ftfont_otf_capability,
398#else /* not HAVE_LIBOTF */
311 NULL, 399 NULL,
400#endif /* not HAVE_LIBOTF */
312 NULL, 401 NULL,
313 NULL, 402 NULL,
314 NULL, 403 NULL,
@@ -332,25 +421,25 @@ static int
332ftfont_get_charset (registry) 421ftfont_get_charset (registry)
333 Lisp_Object registry; 422 Lisp_Object registry;
334{ 423{
335 struct charset *encoding; 424 char *str = (char *) SDATA (SYMBOL_NAME (registry));
425 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
426 Lisp_Object regexp;
336 int i, j; 427 int i, j;
337 428
338 if (font_registry_charsets (registry, &encoding, NULL) < 0) 429 for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
339 return -1; 430 {
340 if (fc_charset_table[0].charset_id < 0) 431 if (str[i] == '.')
341 /* Setup charset_id field of all elements. */ 432 re[j++] = '\\';
342 for (i = 0; fc_charset_table[i].name; i++) 433 else if (str[i] == '*')
343 { 434 re[j++] = '.';
344 Lisp_Object sym = intern (fc_charset_table[i].name); 435 re[j] = str[i];
345 436 if (re[j] == '?')
346 if (CHARSETP (sym)) 437 re[j] = '.';
347 fc_charset_table[i].charset_id = XINT (CHARSET_SYMBOL_ID (sym)); 438 }
348 else 439 re[j] = '\0';
349 fc_charset_table[i].charset_id = -1; 440 regexp = make_unibyte_string (re, j);
350 }
351
352 for (i = 0; fc_charset_table[i].name; i++) 441 for (i = 0; fc_charset_table[i].name; i++)
353 if (encoding->id == fc_charset_table[i].charset_id) 442 if (fast_c_string_match_ignore_case (regexp, fc_charset_table[i].name) >= 0)
354 break; 443 break;
355 if (! fc_charset_table[i].name) 444 if (! fc_charset_table[i].name)
356 return -1; 445 return -1;
@@ -395,6 +484,15 @@ struct OpenTypeSpec
395 (P)[4] = '\0'; \ 484 (P)[4] = '\0'; \
396 } while (0) 485 } while (0)
397 486
487#define OTF_TAG_SYM(SYM, TAG) \
488 do { \
489 char str[5]; \
490 \
491 OTF_TAG_STR (TAG, str); \
492 (SYM) = font_intern_prop (str, 4, 1); \
493 } while (0)
494
495
398static struct OpenTypeSpec * 496static struct OpenTypeSpec *
399ftfont_get_open_type_spec (Lisp_Object otf_spec) 497ftfont_get_open_type_spec (Lisp_Object otf_spec)
400{ 498{
@@ -459,13 +557,12 @@ ftfont_get_open_type_spec (Lisp_Object otf_spec)
459 return spec; 557 return spec;
460} 558}
461 559
462static FcPattern *ftfont_spec_pattern P_ ((Lisp_Object, int *, char *, 560static FcPattern *ftfont_spec_pattern P_ ((Lisp_Object, char *,
463 struct OpenTypeSpec **)); 561 struct OpenTypeSpec **));
464 562
465static FcPattern * 563static FcPattern *
466ftfont_spec_pattern (spec, fc_charset_idx, otlayout, otspec) 564ftfont_spec_pattern (spec, otlayout, otspec)
467 Lisp_Object spec; 565 Lisp_Object spec;
468 int *fc_charset_idx;
469 char *otlayout; 566 char *otlayout;
470 struct OpenTypeSpec **otspec; 567 struct OpenTypeSpec **otspec;
471{ 568{
@@ -478,6 +575,7 @@ ftfont_spec_pattern (spec, fc_charset_idx, otlayout, otspec)
478 int scalable = -1; 575 int scalable = -1;
479 Lisp_Object script = Qnil; 576 Lisp_Object script = Qnil;
480 Lisp_Object registry; 577 Lisp_Object registry;
578 int fc_charset_idx;
481 579
482 if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX)) 580 if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX))
483 && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0) 581 && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0)
@@ -500,16 +598,16 @@ ftfont_spec_pattern (spec, fc_charset_idx, otlayout, otspec)
500 || EQ (registry, Qiso10646_1) 598 || EQ (registry, Qiso10646_1)
501 || EQ (registry, Qunicode_bmp) 599 || EQ (registry, Qunicode_bmp)
502 || EQ (registry, Qunicode_sip)) 600 || EQ (registry, Qunicode_sip))
503 *fc_charset_idx = -1; 601 fc_charset_idx = -1;
504 else 602 else
505 { 603 {
506 FcChar8 *lang; 604 FcChar8 *lang;
507 605
508 *fc_charset_idx = ftfont_get_charset (registry); 606 fc_charset_idx = ftfont_get_charset (registry);
509 if (*fc_charset_idx < 0) 607 if (fc_charset_idx < 0)
510 return NULL; 608 return NULL;
511 charset = fc_charset_table[*fc_charset_idx].fc_charset; 609 charset = fc_charset_table[fc_charset_idx].fc_charset;
512 lang = (FcChar8 *) fc_charset_table[*fc_charset_idx].lang; 610 lang = (FcChar8 *) fc_charset_table[fc_charset_idx].lang;
513 if (lang) 611 if (lang)
514 { 612 {
515 langset = FcLangSetCreate (); 613 langset = FcLangSetCreate ();
@@ -622,7 +720,7 @@ ftfont_spec_pattern (spec, fc_charset_idx, otlayout, otspec)
622 720
623 finish: 721 finish:
624 if (langset) FcLangSetDestroy (langset); 722 if (langset) FcLangSetDestroy (langset);
625 if (charset && *fc_charset_idx < 0) FcCharSetDestroy (charset); 723 if (charset && fc_charset_idx < 0) FcCharSetDestroy (charset);
626 return pattern; 724 return pattern;
627} 725}
628 726
@@ -630,12 +728,11 @@ static Lisp_Object
630ftfont_list (frame, spec) 728ftfont_list (frame, spec)
631 Lisp_Object frame, spec; 729 Lisp_Object frame, spec;
632{ 730{
633 Lisp_Object val = Qnil, registry, family; 731 Lisp_Object val = Qnil, family;
634 int i; 732 int i;
635 FcPattern *pattern; 733 FcPattern *pattern;
636 FcFontSet *fontset = NULL; 734 FcFontSet *fontset = NULL;
637 FcObjectSet *objset = NULL; 735 FcObjectSet *objset = NULL;
638 int fc_charset_idx;
639 char otlayout[15]; /* For "otlayout:XXXX" */ 736 char otlayout[15]; /* For "otlayout:XXXX" */
640 struct OpenTypeSpec *otspec = NULL; 737 struct OpenTypeSpec *otspec = NULL;
641 int spacing = -1; 738 int spacing = -1;
@@ -646,12 +743,11 @@ ftfont_list (frame, spec)
646 fc_initialized = 1; 743 fc_initialized = 1;
647 } 744 }
648 745
649 pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec); 746 pattern = ftfont_spec_pattern (spec, otlayout, &otspec);
650 if (! pattern) 747 if (! pattern)
651 return Qnil; 748 return Qnil;
652 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX))) 749 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
653 spacing = XINT (AREF (spec, FONT_SPACING_INDEX)); 750 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
654 registry = AREF (spec, FONT_REGISTRY_INDEX);
655 family = AREF (spec, FONT_FAMILY_INDEX); 751 family = AREF (spec, FONT_FAMILY_INDEX);
656 if (! NILP (family)) 752 if (! NILP (family))
657 { 753 {
@@ -669,7 +765,7 @@ ftfont_list (frame, spec)
669 765
670 objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT, 766 objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
671 FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE, 767 FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
672 FC_FILE, 768 FC_FILE, FC_INDEX,
673#ifdef FC_CAPABILITY 769#ifdef FC_CAPABILITY
674 FC_CAPABILITY, 770 FC_CAPABILITY,
675#endif /* FC_CAPABILITY */ 771#endif /* FC_CAPABILITY */
@@ -758,9 +854,8 @@ ftfont_list (frame, spec)
758 continue; 854 continue;
759 } 855 }
760#endif /* HAVE_LIBOTF */ 856#endif /* HAVE_LIBOTF */
761 entity = ftfont_pattern_entity (fontset->fonts[i], registry, 857 entity = ftfont_pattern_entity (fontset->fonts[i],
762 AREF (spec, FONT_EXTRA_INDEX), 858 AREF (spec, FONT_EXTRA_INDEX));
763 fc_charset_idx);
764 if (! NILP (entity)) 859 if (! NILP (entity))
765 val = Fcons (entity, val); 860 val = Fcons (entity, val);
766 } 861 }
@@ -788,7 +883,6 @@ ftfont_match (frame, spec)
788 FcResult result; 883 FcResult result;
789 char otlayout[15]; /* For "otlayout:XXXX" */ 884 char otlayout[15]; /* For "otlayout:XXXX" */
790 struct OpenTypeSpec *otspec = NULL; 885 struct OpenTypeSpec *otspec = NULL;
791 int fc_charset_idx;
792 886
793 if (! fc_initialized) 887 if (! fc_initialized)
794 { 888 {
@@ -796,7 +890,7 @@ ftfont_match (frame, spec)
796 fc_initialized = 1; 890 fc_initialized = 1;
797 } 891 }
798 892
799 pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec); 893 pattern = ftfont_spec_pattern (spec, otlayout, &otspec);
800 if (! pattern) 894 if (! pattern)
801 return Qnil; 895 return Qnil;
802 896
@@ -814,9 +908,7 @@ ftfont_match (frame, spec)
814 match = FcFontMatch (NULL, pattern, &result); 908 match = FcFontMatch (NULL, pattern, &result);
815 if (match) 909 if (match)
816 { 910 {
817 entity = ftfont_pattern_entity (match, Qunicode_bmp, 911 entity = ftfont_pattern_entity (match, AREF (spec, FONT_EXTRA_INDEX));
818 AREF (spec, FONT_EXTRA_INDEX),
819 fc_charset_idx);
820 FcPatternDestroy (match); 912 FcPatternDestroy (match);
821 if (! NILP (AREF (spec, FONT_FAMILY_INDEX)) 913 if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
822 && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX), 914 && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
@@ -885,12 +977,11 @@ ftfont_open (f, entity, pixel_size)
885{ 977{
886 struct ftfont_info *ftfont_info; 978 struct ftfont_info *ftfont_info;
887 struct font *font; 979 struct font *font;
980 struct ftfont_cache_data *cache_data;
888 FT_Face ft_face; 981 FT_Face ft_face;
889 FT_Size ft_size; 982 FT_Size ft_size;
890 FT_UInt size; 983 FT_UInt size;
891 Lisp_Object val, filename, cache, font_object; 984 Lisp_Object val, filename, index, cache, font_object;
892 int fc_charset_idx;
893 FcPattern *pattern;
894 int scalable; 985 int scalable;
895 int spacing; 986 int spacing;
896 char name[256]; 987 char name[256];
@@ -901,14 +992,14 @@ ftfont_open (f, entity, pixel_size)
901 if (! CONSP (val)) 992 if (! CONSP (val))
902 return Qnil; 993 return Qnil;
903 val = XCDR (val); 994 val = XCDR (val);
904 filename = XCAR (val); 995 cache = ftfont_lookup_cache (val, 1);
905 fc_charset_idx = XINT (XCDR (val));
906 cache = ftfont_lookup_cache (filename);
907 if (NILP (cache)) 996 if (NILP (cache))
908 return Qnil; 997 return Qnil;
909 filename = XCAR (cache); 998 filename = XCAR (val);
999 index = XCDR (val);
910 val = XCDR (cache); 1000 val = XCDR (cache);
911 ft_face = XSAVE_VALUE (val)->pointer; 1001 cache_data = XSAVE_VALUE (XCDR (cache))->pointer;
1002 ft_face = cache_data->ft_face;
912 if (XSAVE_VALUE (val)->integer > 0) 1003 if (XSAVE_VALUE (val)->integer > 0)
913 { 1004 {
914 /* FT_Face in this cache is already used by the different size. */ 1005 /* FT_Face in this cache is already used by the different size. */
@@ -931,11 +1022,8 @@ ftfont_open (f, entity, pixel_size)
931 return Qnil; 1022 return Qnil;
932 } 1023 }
933 1024
934 font_object = font_make_object (VECSIZE (struct ftfont_info)); 1025 font_object = font_make_object (VECSIZE (struct ftfont_info), entity, size);
935 ASET (font_object, FONT_TYPE_INDEX, Qfreetype); 1026 ASET (font_object, FONT_TYPE_INDEX, Qfreetype);
936 for (i = 1;i < FONT_ENTITY_MAX; i++)
937 ASET (font_object, i, AREF (entity, i));
938 ASET (font_object, FONT_SIZE_INDEX, make_number (size));
939 len = font_unparse_xlfd (entity, size, name, 256); 1027 len = font_unparse_xlfd (entity, size, name, 256);
940 if (len > 0) 1028 if (len > 0)
941 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len)); 1029 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
@@ -950,7 +1038,7 @@ ftfont_open (f, entity, pixel_size)
950 font = XFONT_OBJECT (font_object); 1038 font = XFONT_OBJECT (font_object);
951 ftfont_info = (struct ftfont_info *) font; 1039 ftfont_info = (struct ftfont_info *) font;
952 ftfont_info->ft_size = ft_face->size; 1040 ftfont_info->ft_size = ft_face->size;
953 ftfont_info->fc_charset_idx = fc_charset_idx; 1041 ftfont_info->index = XINT (index);
954#ifdef HAVE_LIBOTF 1042#ifdef HAVE_LIBOTF
955 ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT; 1043 ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
956 ftfont_info->otf = NULL; 1044 ftfont_info->otf = NULL;
@@ -1030,19 +1118,21 @@ ftfont_close (f, font)
1030 struct ftfont_info *ftfont_info = (struct ftfont_info *) font; 1118 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1031 Lisp_Object val, cache; 1119 Lisp_Object val, cache;
1032 1120
1033 cache = ftfont_lookup_cache (font->props[FONT_FILE_INDEX]); 1121 val = Fcons (font->props[FONT_FILE_INDEX], make_number (ftfont_info->index));
1122 cache = ftfont_lookup_cache (val, 1);
1123 xassert (CONSP (cache));
1034 val = XCDR (cache); 1124 val = XCDR (cache);
1035 (XSAVE_VALUE (val)->integer)--; 1125 (XSAVE_VALUE (val)->integer)--;
1036 if (XSAVE_VALUE (val)->integer == 0) 1126 if (XSAVE_VALUE (val)->integer == 0)
1037 { 1127 {
1038 FT_Face ft_face = XSAVE_VALUE (val)->pointer; 1128 struct ftfont_cache_data *cache_data = XSAVE_VALUE (val)->pointer;
1039 1129
1040 FT_Done_Face (ft_face); 1130 FT_Done_Face (cache_data->ft_face);
1041#ifdef HAVE_LIBOTF 1131#ifdef HAVE_LIBOTF
1042 if (ftfont_info->otf) 1132 if (ftfont_info->otf)
1043 OTF_close (ftfont_info->otf); 1133 OTF_close (ftfont_info->otf);
1044#endif 1134#endif
1045 XSAVE_VALUE (val)->pointer = NULL; 1135 cache_data->ft_face = NULL;
1046 } 1136 }
1047 else 1137 else
1048 FT_Done_Size (ftfont_info->ft_size); 1138 FT_Done_Size (ftfont_info->ft_size);
@@ -1053,16 +1143,9 @@ ftfont_has_char (entity, c)
1053 Lisp_Object entity; 1143 Lisp_Object entity;
1054 int c; 1144 int c;
1055{ 1145{
1056 Lisp_Object val; 1146 FcCharSet *charset = ftfont_get_fc_charset (entity);
1057 int fc_charset_idx;
1058 struct charset *charset;
1059 1147
1060 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); 1148 return (FcCharSetHasChar (charset, c) == FcTrue);
1061 fc_charset_idx = XINT (XCDR (XCDR (val)));
1062 if (fc_charset_idx < 0)
1063 return -1;
1064 charset = CHARSET_FROM_ID (fc_charset_table[fc_charset_idx].charset_id);
1065 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset));
1066} 1149}
1067 1150
1068static unsigned 1151static unsigned
@@ -1198,6 +1281,67 @@ ftfont_anchor_point (font, code, index, x, y)
1198} 1281}
1199 1282
1200#ifdef HAVE_LIBOTF 1283#ifdef HAVE_LIBOTF
1284
1285static Lisp_Object
1286ftfont_otf_features (gsub_gpos)
1287 OTF_GSUB_GPOS *gsub_gpos;
1288{
1289 Lisp_Object scripts, langsyses, features, sym;
1290 int i, j, k;
1291
1292 for (scripts = Qnil, i = gsub_gpos->ScriptList.ScriptCount - 1; i >= 0; i--)
1293 {
1294 OTF_Script *otf_script = gsub_gpos->ScriptList.Script + i;
1295
1296 for (langsyses = Qnil, j = otf_script->LangSysCount - 1; j >= -1; j--)
1297 {
1298 OTF_LangSys *otf_langsys;
1299
1300 if (j >= 0)
1301 otf_langsys = otf_script->LangSys + j;
1302 else if (otf_script->DefaultLangSysOffset)
1303 otf_langsys = &otf_script->DefaultLangSys;
1304 else
1305 break;
1306
1307 for (features = Qnil, k = otf_langsys->FeatureCount - 1; k >= 0; k--)
1308 {
1309 OTF_TAG_SYM (sym, gsub_gpos->FeatureList.Feature[k].FeatureTag);
1310 features = Fcons (sym, features);
1311 }
1312 if (j >= 0)
1313 OTF_TAG_SYM (sym, otf_script->LangSysRecord[j].LangSysTag);
1314 else
1315 sym = Qnil;
1316 langsyses = Fcons (Fcons (sym, features), langsyses);
1317 }
1318
1319 OTF_TAG_SYM (sym, gsub_gpos->ScriptList.Script[i].ScriptTag);
1320 scripts = Fcons (Fcons (sym, langsyses), scripts);
1321 }
1322 return scripts;
1323
1324}
1325
1326
1327static Lisp_Object
1328ftfont_otf_capability (font)
1329 struct font *font;
1330{
1331 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1332 OTF *otf = ftfont_get_otf (ftfont_info);
1333 Lisp_Object gsub_gpos;
1334
1335 if (! otf)
1336 return Qnil;
1337 gsub_gpos = Fcons (Qnil, Qnil);
1338 if (OTF_get_table (otf, "GSUB") == 0)
1339 XSETCAR (gsub_gpos, ftfont_otf_features (otf->gsub));
1340 if (OTF_get_table (otf, "GPOS") == 0)
1341 XSETCDR (gsub_gpos, ftfont_otf_features (otf->gpos));
1342 return gsub_gpos;
1343}
1344
1201#ifdef HAVE_M17N_FLT 1345#ifdef HAVE_M17N_FLT
1202 1346
1203struct MFLTFontFT 1347struct MFLTFontFT
@@ -1720,28 +1864,14 @@ ftfont_shape (lgstring)
1720{ 1864{
1721 struct font *font; 1865 struct font *font;
1722 struct ftfont_info *ftfont_info; 1866 struct ftfont_info *ftfont_info;
1867 OTF *otf;
1723 1868
1724 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font); 1869 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
1725 ftfont_info = (struct ftfont_info *) font; 1870 ftfont_info = (struct ftfont_info *) font;
1726 if (! ftfont_info->maybe_otf) 1871 otf = ftfont_get_otf (ftfont_info);
1872 if (! otf)
1727 return make_number (0); 1873 return make_number (0);
1728 if (! ftfont_info->otf) 1874 return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf);
1729 {
1730 OTF *otf = OTF_open_ft_face (ftfont_info->ft_size->face);
1731
1732 if (! otf || OTF_get_table (otf, "head") < 0)
1733 {
1734 if (otf)
1735 OTF_close (otf);
1736 ftfont_info->maybe_otf = 0;
1737 return make_number (0);
1738 }
1739
1740 ftfont_info->otf = otf;
1741 }
1742
1743 return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face,
1744 ftfont_info->otf);
1745} 1875}
1746 1876
1747#endif /* HAVE_M17N_FLT */ 1877#endif /* HAVE_M17N_FLT */