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