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