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