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