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