Merge from gnus--devo--0
[emacs.git] / src / ftfont.c
blob62bbb9bca4c08975df81e7a1675bd2f76900c4c7
1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
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.
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.
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/>. */
22 #include <config.h>
23 #include <stdio.h>
25 #include <fontconfig/fontconfig.h>
26 #include <fontconfig/fcfreetype.h>
28 #include "lisp.h"
29 #include "dispextern.h"
30 #include "frame.h"
31 #include "blockinput.h"
32 #include "character.h"
33 #include "charset.h"
34 #include "coding.h"
35 #include "fontset.h"
36 #include "font.h"
37 #include "ftfont.h"
39 /* Symbolic type of this font-driver. */
40 Lisp_Object Qfreetype;
42 /* Fontconfig's generic families and their aliases. */
43 static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
45 /* Flag to tell if FcInit is already called or not. */
46 static int fc_initialized;
48 /* Handle to a FreeType library instance. */
49 static FT_Library ft_library;
51 /* Cache for FreeType fonts. */
52 static Lisp_Object freetype_font_cache;
54 /* Cache for FT_Face */
55 static Lisp_Object ft_face_cache;
57 /* The actual structure for FreeType font that can be casted to struct
58 font. */
60 struct ftfont_info
62 struct font font;
63 FT_Size ft_size;
64 int fc_charset_idx;
65 #ifdef HAVE_LIBOTF
66 int maybe_otf; /* Flag to tell if this may be OTF or not. */
67 OTF *otf;
68 #endif /* HAVE_LIBOTF */
71 static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object,
72 Lisp_Object, int));
74 static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object,
75 FcPattern *));
76 Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
78 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
80 static struct
82 /* charset name */
83 char *name;
84 /* characters to distinguish the charset from the others */
85 int uniquifier[6];
86 /* additional constraint by language */
87 char *lang;
88 /* set in syms_of_ftfont */
89 int charset_id;
90 /* set on demand */
91 FcCharSet *fc_charset;
92 } fc_charset_table[] =
93 { { "iso-8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 }, "en", -1 },
94 { "iso-8859-2", { 0x00A0, 0x010E }},
95 { "iso-8859-3", { 0x00A0, 0x0108 }},
96 { "iso-8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
97 { "iso-8859-5", { 0x00A0, 0x0401 }},
98 { "iso-8859-6", { 0x00A0, 0x060C }},
99 { "iso-8859-7", { 0x00A0, 0x0384 }},
100 { "iso-8859-8", { 0x00A0, 0x05D0 }},
101 { "iso-8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
102 { "iso-8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
103 { "iso-8859-11", { 0x00A0, 0x0E01 }},
104 { "iso-8859-13", { 0x00A0, 0x201C }},
105 { "iso-8859-14", { 0x00A0, 0x0174 }},
106 { "iso-8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
107 { "iso-8859-16", { 0x00A0, 0x0218}},
108 { "chinese-gb2312", { 0x4E13 }, "zh-cn"},
109 { "big5", { 0xF6B1 }, "zh-tw" },
110 { "japanese-jisx0208", { 0x4E55 }, "ja"},
111 { "korean-ksc5601", { 0xAC00 }, "ko"},
112 { "chinese-cns11643-1", { 0xFE32 }, "zh-tw"},
113 { "chinese-cns11643-2", { 0x4E33, 0x7934 }},
114 { "chinese-cns11643-3", { 0x201A9 }},
115 { "chinese-cns11643-4", { 0x20057 }},
116 { "chinese-cns11643-5", { 0x20000 }},
117 { "chinese-cns11643-6", { 0x20003 }},
118 { "chinese-cns11643-7", { 0x20055 }},
119 { "chinese-gbk", { 0x4E06 }, "zh-cn"},
120 { "japanese-jisx0212", { 0x4E44 }},
121 { "japanese-jisx0213-1", { 0xFA10 }, "ja"},
122 { "japanese-jisx0213-2", { 0xFA49 }},
123 { "japanese-jisx0213.2004-1", { 0x20B9F }},
124 { "viscii", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
125 { "tis620", { 0x0E01 }, "th"},
126 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
127 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
128 { "mule-lao", { 0x0E81 }, "lo"},
129 { NULL }
132 extern Lisp_Object Qc, Qm, Qp, Qd;
134 static Lisp_Object
135 ftfont_pattern_entity (p, registry, extra, fc_charset_idx)
136 FcPattern *p;
137 Lisp_Object registry, extra;
138 int fc_charset_idx;
140 Lisp_Object entity;
141 char *file, *str;
142 int numeric;
143 double dbl;
144 FcBool b;
146 if (FcPatternGetString (p, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
147 return Qnil;
149 entity = font_make_entity ();
151 ASET (entity, FONT_TYPE_INDEX, Qfreetype);
152 ASET (entity, FONT_REGISTRY_INDEX, registry);
154 if (FcPatternGetString (p, FC_FOUNDRY, 0, (FcChar8 **) &str) == FcResultMatch)
155 ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (str, strlen (str), 1));
156 if (FcPatternGetString (p, FC_FAMILY, 0, (FcChar8 **) &str) == FcResultMatch)
157 ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (str, strlen (str), 1));
158 if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
160 if (numeric >= FC_WEIGHT_REGULAR && numeric < FC_WEIGHT_MEDIUM)
161 numeric = FC_WEIGHT_MEDIUM;
162 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, make_number (numeric));
164 if (FcPatternGetInteger (p, FC_SLANT, 0, &numeric) == FcResultMatch)
166 numeric += 100;
167 FONT_SET_STYLE (entity, FONT_SLANT_INDEX, make_number (numeric));
169 if (FcPatternGetInteger (p, FC_WIDTH, 0, &numeric) == FcResultMatch)
171 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric));
173 if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
174 ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
175 else
176 ASET (entity, FONT_SIZE_INDEX, make_number (0));
177 if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch)
178 ASET (entity, FONT_SPACING_INDEX, make_number (numeric));
179 if (FcPatternGetDouble (p, FC_DPI, 0, &dbl) == FcResultMatch)
181 int dpi = dbl;
182 ASET (entity, FONT_DPI_INDEX, make_number (dpi));
184 if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
185 && b == FcTrue)
186 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
188 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
189 font_put_extra (entity, QCfont_entity,
190 Fcons (make_unibyte_string ((char *) file,
191 strlen ((char *) file)),
192 make_number (fc_charset_idx)));
193 return entity;
197 static Lisp_Object ftfont_generic_family_list;
199 static Lisp_Object
200 ftfont_resolve_generic_family (family, pattern)
201 Lisp_Object family;
202 FcPattern *pattern;
204 Lisp_Object slot;
205 FcPattern *match;
206 FcResult result;
208 family = Fintern (Fdowncase (SYMBOL_NAME (family)), Qnil);
209 if (EQ (family, Qmono))
210 family = Qmonospace;
211 else if (EQ (family, Qsans) || EQ (family, Qsans__serif))
212 family = Qsans_serif;
213 slot = assq_no_quit (family, ftfont_generic_family_list);
214 if (! CONSP (slot))
215 return Qnil;
216 if (! EQ (XCDR (slot), Qt))
217 return XCDR (slot);
218 pattern = FcPatternDuplicate (pattern);
219 if (! pattern)
220 goto err;
221 FcPatternDel (pattern, FC_FAMILY);
222 FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (family));
223 FcConfigSubstitute (NULL, pattern, FcMatchPattern);
224 FcDefaultSubstitute (pattern);
225 match = FcFontMatch (NULL, pattern, &result);
226 if (match)
228 FcChar8 *fam;
230 if (FcPatternGetString (match, FC_FAMILY, 0, &fam) == FcResultMatch)
231 family = intern ((char *) fam);
233 else
234 family = Qnil;
235 XSETCDR (slot, family);
236 err:
237 if (match) FcPatternDestroy (match);
238 if (pattern) FcPatternDestroy (pattern);
239 return family;
242 Lisp_Object
243 ftfont_lookup_cache (filename)
244 Lisp_Object filename;
246 Lisp_Object cache, val;
248 cache = assoc_no_quit (filename, ft_face_cache);
249 if (NILP (cache))
251 val = make_save_value (NULL, 0);
252 cache = Fcons (filename, val);
253 ft_face_cache = Fcons (cache, ft_face_cache);
255 else
256 val = XCDR (cache);
257 if (! XSAVE_VALUE (val)->pointer)
259 FT_Face ft_face;
261 if (! ft_library
262 && FT_Init_FreeType (&ft_library) != 0)
263 return Qnil;
264 if (FT_New_Face (ft_library, (char *) SDATA (filename), 0, &ft_face) != 0)
265 return Qnil;
266 XSAVE_VALUE (val)->pointer = ft_face;
268 return cache;
271 static Lisp_Object ftfont_get_cache P_ ((FRAME_PTR));
272 static Lisp_Object ftfont_list P_ ((Lisp_Object, Lisp_Object));
273 static Lisp_Object ftfont_match P_ ((Lisp_Object, Lisp_Object));
274 static Lisp_Object ftfont_list_family P_ ((Lisp_Object));
275 static Lisp_Object ftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
276 static void ftfont_close P_ ((FRAME_PTR, struct font *));
277 static int ftfont_has_char P_ ((Lisp_Object, int));
278 static unsigned ftfont_encode_char P_ ((struct font *, int));
279 static int ftfont_text_extents P_ ((struct font *, unsigned *, int,
280 struct font_metrics *));
281 static int ftfont_get_bitmap P_ ((struct font *, unsigned,
282 struct font_bitmap *, int));
283 static int ftfont_anchor_point P_ ((struct font *, unsigned, int,
284 int *, int *));
285 static Lisp_Object ftfont_shape P_ ((Lisp_Object));
287 struct font_driver ftfont_driver =
289 0, /* Qfreetype */
290 0, /* case insensitive */
291 ftfont_get_cache,
292 ftfont_list,
293 ftfont_match,
294 ftfont_list_family,
295 NULL,
296 ftfont_open,
297 ftfont_close,
298 /* We can't draw a text without device dependent functions. */
299 NULL,
300 NULL,
301 ftfont_has_char,
302 ftfont_encode_char,
303 ftfont_text_extents,
304 /* We can't draw a text without device dependent functions. */
305 NULL,
306 ftfont_get_bitmap,
307 NULL,
308 NULL,
309 NULL,
310 ftfont_anchor_point,
311 NULL,
312 NULL,
313 NULL,
314 NULL,
315 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
316 ftfont_shape
317 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
318 NULL
319 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
322 extern Lisp_Object QCname;
324 static Lisp_Object
325 ftfont_get_cache (f)
326 FRAME_PTR f;
328 return freetype_font_cache;
331 static int
332 ftfont_get_charset (registry)
333 Lisp_Object registry;
335 struct charset *encoding;
336 int i, j;
338 if (font_registry_charsets (registry, &encoding, NULL) < 0)
339 return -1;
340 if (fc_charset_table[0].charset_id < 0)
341 /* Setup charset_id field of all elements. */
342 for (i = 0; fc_charset_table[i].name; i++)
344 Lisp_Object sym = intern (fc_charset_table[i].name);
346 if (CHARSETP (sym))
347 fc_charset_table[i].charset_id = XINT (CHARSET_SYMBOL_ID (sym));
348 else
349 fc_charset_table[i].charset_id = -1;
352 for (i = 0; fc_charset_table[i].name; i++)
353 if (encoding->id == fc_charset_table[i].charset_id)
354 break;
355 if (! fc_charset_table[i].name)
356 return -1;
357 if (! fc_charset_table[i].fc_charset)
359 FcCharSet *charset = FcCharSetCreate ();
360 int *uniquifier = fc_charset_table[i].uniquifier;
362 if (! charset)
363 return -1;
364 for (j = 0; uniquifier[j]; j++)
365 if (! FcCharSetAddChar (charset, uniquifier[j]))
367 FcCharSetDestroy (charset);
368 return -1;
370 fc_charset_table[i].fc_charset = charset;
372 return i;
375 struct OpenTypeSpec
377 Lisp_Object script;
378 unsigned int script_tag, langsys_tag;
379 int nfeatures[2];
380 unsigned int *features[2];
383 #define OTF_SYM_TAG(SYM, TAG) \
384 do { \
385 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
386 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
387 } while (0)
389 #define OTF_TAG_STR(TAG, P) \
390 do { \
391 (P)[0] = (char) (TAG >> 24); \
392 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
393 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
394 (P)[3] = (char) (TAG & 0xFF); \
395 (P)[4] = '\0'; \
396 } while (0)
398 static struct OpenTypeSpec *
399 ftfont_get_open_type_spec (Lisp_Object otf_spec)
401 struct OpenTypeSpec *spec = malloc (sizeof (struct OpenTypeSpec));
402 Lisp_Object val;
403 int i, j, negative;
405 if (! spec)
406 return NULL;
407 spec->script = XCAR (otf_spec);
408 if (! NILP (spec->script))
410 OTF_SYM_TAG (spec->script, spec->script_tag);
411 val = assq_no_quit (spec->script, Votf_script_alist);
412 if (CONSP (val) && SYMBOLP (XCDR (val)))
413 spec->script = XCDR (val);
414 else
415 spec->script = Qnil;
417 else
418 spec->script_tag = 0x44464C54; /* "DFLT" */
419 otf_spec = XCDR (otf_spec);
420 val = XCAR (otf_spec);
421 if (! NILP (val))
422 OTF_SYM_TAG (val, spec->langsys_tag);
423 else
424 spec->langsys_tag = 0;
425 spec->nfeatures[0] = spec->nfeatures[1] = 0;
426 for (i = 0; i < 2; i++)
428 Lisp_Object len;
430 otf_spec = XCDR (otf_spec);
431 if (NILP (otf_spec))
432 break;
433 val = XCAR (otf_spec);
434 if (NILP (val))
435 continue;
436 len = Flength (val);
437 spec->features[i] = malloc (sizeof (int) * XINT (len));
438 if (! spec->features[i])
440 if (i > 0 && spec->features[0])
441 free (spec->features[0]);
442 free (spec);
443 return NULL;
445 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
447 if (NILP (XCAR (val)))
448 negative = 1;
449 else
451 unsigned int tag;
453 OTF_SYM_TAG (XCAR (val), tag);
454 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
457 spec->nfeatures[i] = j;
459 return spec;
462 static FcPattern *ftfont_spec_pattern P_ ((Lisp_Object, int *, char *,
463 struct OpenTypeSpec **));
465 static FcPattern *
466 ftfont_spec_pattern (spec, fc_charset_idx, otlayout, otspec)
467 Lisp_Object spec;
468 int *fc_charset_idx;
469 char *otlayout;
470 struct OpenTypeSpec **otspec;
472 Lisp_Object tmp, extra;
473 FcPattern *pattern = NULL;
474 FcCharSet *charset = NULL;
475 FcLangSet *langset = NULL;
476 int n;
477 int dpi = -1;
478 int scalable = -1;
479 Lisp_Object script = Qnil;
480 Lisp_Object registry;
482 if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX))
483 && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0)
484 /* Fontconfig doesn't support adstyle property. */
485 return NULL;
486 if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
487 && n < 100)
488 /* Fontconfig doesn't support reverse-italic/obligue. */
489 return NULL;
491 if (INTEGERP (AREF (spec, FONT_DPI_INDEX)))
492 dpi = XINT (AREF (spec, FONT_DPI_INDEX));
493 if (INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
494 && XINT (AREF (spec, FONT_AVGWIDTH_INDEX)) == 0)
495 scalable = 1;
497 registry = AREF (spec, FONT_REGISTRY_INDEX);
498 if (NILP (registry)
499 || EQ (registry, Qascii_0)
500 || EQ (registry, Qiso10646_1)
501 || EQ (registry, Qunicode_bmp)
502 || EQ (registry, Qunicode_sip))
503 *fc_charset_idx = -1;
504 else
506 FcChar8 *lang;
508 *fc_charset_idx = ftfont_get_charset (registry);
509 if (*fc_charset_idx < 0)
510 return NULL;
511 charset = fc_charset_table[*fc_charset_idx].fc_charset;
512 lang = (FcChar8 *) fc_charset_table[*fc_charset_idx].lang;
513 if (lang)
515 langset = FcLangSetCreate ();
516 if (! langset)
517 goto err;
518 FcLangSetAdd (langset, lang);
522 otlayout[0] = '\0';
523 for (extra = AREF (spec, FONT_EXTRA_INDEX);
524 CONSP (extra); extra = XCDR (extra))
526 Lisp_Object key, val;
528 key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
529 if (EQ (key, QCdpi))
530 dpi = XINT (val);
531 else if (EQ (key, QClang))
533 if (! langset)
534 langset = FcLangSetCreate ();
535 if (! langset)
536 goto err;
537 if (SYMBOLP (val))
539 if (! FcLangSetAdd (langset, SYMBOL_FcChar8 (val)))
540 goto err;
542 else
543 for (; CONSP (val); val = XCDR (val))
544 if (SYMBOLP (XCAR (val))
545 && ! FcLangSetAdd (langset, SYMBOL_FcChar8 (XCAR (val))))
546 goto err;
548 else if (EQ (key, QCotf))
550 *otspec = ftfont_get_open_type_spec (val);
551 if (! *otspec)
552 return NULL;
553 strcat (otlayout, "otlayout:");
554 OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
555 script = (*otspec)->script;
557 else if (EQ (key, QCscript))
558 script = val;
559 else if (EQ (key, QCscalable))
560 scalable = ! NILP (val);
563 if (! NILP (script) && ! charset)
565 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
567 if (CONSP (chars))
569 charset = FcCharSetCreate ();
570 if (! charset)
571 goto err;
572 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
573 if (CHARACTERP (XCAR (chars))
574 && ! FcCharSetAddChar (charset, XUINT (XCAR (chars))))
575 goto err;
579 pattern = FcPatternCreate ();
580 if (! pattern)
581 goto err;
582 tmp = AREF (spec, FONT_FOUNDRY_INDEX);
583 if (! NILP (tmp)
584 && ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
585 goto err;
586 tmp = AREF (spec, FONT_FAMILY_INDEX);
587 if (! NILP (tmp)
588 && ! FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (tmp)))
589 goto err;
590 if (charset
591 && ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
592 goto err;
593 if (langset
594 && ! FcPatternAddLangSet (pattern, FC_LANG, langset))
595 goto err;
596 if (dpi >= 0
597 && ! FcPatternAddDouble (pattern, FC_DPI, dpi))
598 goto err;
599 if (scalable >= 0
600 && ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
601 goto err;
603 goto finish;
605 err:
606 /* We come here because of unexpected error in fontconfig API call
607 (usually insufficient memory). */
608 if (pattern)
610 FcPatternDestroy (pattern);
611 pattern = NULL;
613 if (*otspec)
615 if ((*otspec)->nfeatures[0] > 0)
616 free ((*otspec)->features[0]);
617 if ((*otspec)->nfeatures[1] > 0)
618 free ((*otspec)->features[1]);
619 free (*otspec);
620 *otspec = NULL;
623 finish:
624 if (langset) FcLangSetDestroy (langset);
625 if (charset && *fc_charset_idx < 0) FcCharSetDestroy (charset);
626 return pattern;
629 static Lisp_Object
630 ftfont_list (frame, spec)
631 Lisp_Object frame, spec;
633 Lisp_Object val = Qnil, registry, family;
634 int i;
635 FcPattern *pattern;
636 FcFontSet *fontset = NULL;
637 FcObjectSet *objset = NULL;
638 int fc_charset_idx;
639 char otlayout[15]; /* For "otlayout:XXXX" */
640 struct OpenTypeSpec *otspec = NULL;
641 int spacing = -1;
643 if (! fc_initialized)
645 FcInit ();
646 fc_initialized = 1;
649 pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec);
650 if (! pattern)
651 return Qnil;
652 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
653 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
654 registry = AREF (spec, FONT_REGISTRY_INDEX);
655 family = AREF (spec, FONT_FAMILY_INDEX);
656 if (! NILP (family))
658 Lisp_Object resolved;
660 resolved = ftfont_resolve_generic_family (family, pattern);
661 if (! NILP (resolved))
663 FcPatternDel (pattern, FC_FAMILY);
664 if (! FcPatternAddString (pattern, FC_FAMILY,
665 SYMBOL_FcChar8 (resolved)))
666 goto err;
670 objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
671 FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
672 FC_FILE,
673 #ifdef FC_CAPABILITY
674 FC_CAPABILITY,
675 #endif /* FC_CAPABILITY */
676 #ifdef FC_FONTFORMAT
677 FC_FONTFORMAT,
678 #endif
679 NULL);
680 if (! objset)
681 goto err;
683 fontset = FcFontList (NULL, pattern, objset);
684 if (! fontset)
685 goto err;
686 #if 0
687 /* Need fix because this finds any fonts. */
688 if (fontset->nfont == 0 && ! NILP (family))
690 /* Try maching with configuration. For instance, the
691 configuration may specify "Nimbus Mono L" as an alias of
692 "Courier". */
693 FcPattern *pat = FcPatternBuild (0, FC_FAMILY, FcTypeString,
694 SYMBOL_FcChar8 (family), NULL);
695 FcChar8 *fam;
697 if (FcConfigSubstitute (NULL, pat, FcMatchPattern) == FcTrue)
699 for (i = 0;
700 FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
701 i++)
703 FcPatternDel (pattern, FC_FAMILY);
704 FcPatternAddString (pattern, FC_FAMILY, fam);
705 FcFontSetDestroy (fontset);
706 fontset = FcFontList (NULL, pattern, objset);
707 if (fontset->nfont > 0)
708 break;
712 #endif
713 for (i = 0; i < fontset->nfont; i++)
715 Lisp_Object entity;
717 if (spacing >= 0)
719 int this;
721 if ((FcPatternGetInteger (fontset->fonts[i], FC_SPACING, 0, &this)
722 == FcResultMatch)
723 && spacing != this)
724 continue;
727 #ifdef FC_CAPABILITY
728 if (otlayout[0])
730 FcChar8 *this;
732 if (FcPatternGetString (fontset->fonts[i], FC_CAPABILITY, 0,
733 &this) != FcResultMatch
734 || ! strstr ((char *) this, otlayout))
735 continue;
737 #endif /* FC_CAPABILITY */
738 #ifdef HAVE_LIBOTF
739 if (otspec)
741 FcChar8 *file;
742 OTF *otf;
744 if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file)
745 != FcResultMatch)
746 continue;
747 otf = OTF_open ((char *) file);
748 if (! otf)
749 continue;
750 if (OTF_check_features (otf, 1,
751 otspec->script_tag, otspec->langsys_tag,
752 otspec->features[0],
753 otspec->nfeatures[0]) != 1
754 || OTF_check_features (otf, 0,
755 otspec->script_tag, otspec->langsys_tag,
756 otspec->features[1],
757 otspec->nfeatures[1]) != 1)
758 continue;
760 #endif /* HAVE_LIBOTF */
761 entity = ftfont_pattern_entity (fontset->fonts[i], registry,
762 AREF (spec, FONT_EXTRA_INDEX),
763 fc_charset_idx);
764 if (! NILP (entity))
765 val = Fcons (entity, val);
767 font_add_log ("ftfont-list", spec, val);
768 goto finish;
770 err:
771 /* We come here because of unexpected error in fontconfig API call
772 (usually insufficient memory). */
773 val = Qnil;
775 finish:
776 if (objset) FcObjectSetDestroy (objset);
777 if (fontset) FcFontSetDestroy (fontset);
778 if (pattern) FcPatternDestroy (pattern);
779 return val;
782 static Lisp_Object
783 ftfont_match (frame, spec)
784 Lisp_Object frame, spec;
786 Lisp_Object entity;
787 FcPattern *pattern, *match = NULL;
788 FcResult result;
789 char otlayout[15]; /* For "otlayout:XXXX" */
790 struct OpenTypeSpec *otspec = NULL;
791 int fc_charset_idx;
793 if (! fc_initialized)
795 FcInit ();
796 fc_initialized = 1;
799 pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec);
800 if (! pattern)
801 return Qnil;
803 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
805 FcValue value;
807 value.type = FcTypeDouble;
808 value.u.d = XINT (AREF (spec, FONT_SIZE_INDEX));
809 FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse);
811 if (FcConfigSubstitute (NULL, pattern, FcMatchPattern) == FcTrue)
813 FcDefaultSubstitute (pattern);
814 match = FcFontMatch (NULL, pattern, &result);
815 if (match)
817 entity = ftfont_pattern_entity (match, Qunicode_bmp,
818 AREF (spec, FONT_EXTRA_INDEX),
819 fc_charset_idx);
820 FcPatternDestroy (match);
821 if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
822 && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
823 ftfont_generic_family_list))
824 && NILP (Fstring_equal (AREF (spec, FONT_FAMILY_INDEX),
825 AREF (entity, FONT_FAMILY_INDEX))))
826 entity = Qnil;
829 FcPatternDestroy (pattern);
831 font_add_log ("ftfont-match", spec, entity);
832 return entity;
835 static Lisp_Object
836 ftfont_list_family (frame)
837 Lisp_Object frame;
839 Lisp_Object list;
840 FcPattern *pattern = NULL;
841 FcFontSet *fontset = NULL;
842 FcObjectSet *objset = NULL;
843 int i;
845 if (! fc_initialized)
847 FcInit ();
848 fc_initialized = 1;
851 pattern = FcPatternCreate ();
852 if (! pattern)
853 goto finish;
854 objset = FcObjectSetBuild (FC_FAMILY, NULL);
855 if (! objset)
856 goto finish;
857 fontset = FcFontList (NULL, pattern, objset);
858 if (! fontset)
859 goto finish;
861 list = Qnil;
862 for (i = 0; i < fontset->nfont; i++)
864 FcPattern *pat = fontset->fonts[i];
865 FcChar8 *str;
867 if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
868 list = Fcons (intern ((char *) str), list);
871 finish:
872 if (objset) FcObjectSetDestroy (objset);
873 if (fontset) FcFontSetDestroy (fontset);
874 if (pattern) FcPatternDestroy (pattern);
876 return list;
880 static Lisp_Object
881 ftfont_open (f, entity, pixel_size)
882 FRAME_PTR f;
883 Lisp_Object entity;
884 int pixel_size;
886 struct ftfont_info *ftfont_info;
887 struct font *font;
888 FT_Face ft_face;
889 FT_Size ft_size;
890 FT_UInt size;
891 Lisp_Object val, filename, cache, font_object;
892 int fc_charset_idx;
893 FcPattern *pattern;
894 int scalable;
895 int spacing;
896 char name[256];
897 int i, len;
898 int upEM;
900 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
901 if (! CONSP (val))
902 return Qnil;
903 val = XCDR (val);
904 filename = XCAR (val);
905 fc_charset_idx = XINT (XCDR (val));
906 cache = ftfont_lookup_cache (filename);
907 if (NILP (cache))
908 return Qnil;
909 filename = XCAR (cache);
910 val = XCDR (cache);
911 ft_face = XSAVE_VALUE (val)->pointer;
912 if (XSAVE_VALUE (val)->integer > 0)
914 /* FT_Face in this cache is already used by the different size. */
915 if (FT_New_Size (ft_face, &ft_size) != 0)
916 return Qnil;
917 if (FT_Activate_Size (ft_size) != 0)
919 FT_Done_Size (ft_size);
920 return Qnil;
923 XSAVE_VALUE (val)->integer++;
924 size = XINT (AREF (entity, FONT_SIZE_INDEX));
925 if (size == 0)
926 size = pixel_size;
927 if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
929 if (XSAVE_VALUE (val)->integer == 0)
930 FT_Done_Face (ft_face);
931 return Qnil;
934 font_object = font_make_object (VECSIZE (struct ftfont_info));
935 ASET (font_object, FONT_TYPE_INDEX, Qfreetype);
936 for (i = 1;i < FONT_ENTITY_MAX; i++)
937 ASET (font_object, i, AREF (entity, i));
938 ASET (font_object, FONT_SIZE_INDEX, make_number (size));
939 len = font_unparse_xlfd (entity, size, name, 256);
940 if (len > 0)
941 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
942 len = font_unparse_fcname (entity, size, name, 256);
943 if (len > 0)
944 ASET (font_object, FONT_FULLNAME_INDEX, make_unibyte_string (name, len));
945 else
946 ASET (font_object, FONT_FULLNAME_INDEX,
947 AREF (font_object, FONT_NAME_INDEX));
948 ASET (font_object, FONT_FILE_INDEX, filename);
949 ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (NULL, filename));
950 font = XFONT_OBJECT (font_object);
951 ftfont_info = (struct ftfont_info *) font;
952 ftfont_info->ft_size = ft_face->size;
953 ftfont_info->fc_charset_idx = fc_charset_idx;
954 #ifdef HAVE_LIBOTF
955 ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
956 ftfont_info->otf = NULL;
957 #endif /* HAVE_LIBOTF */
958 font->pixel_size = size;
959 font->driver = &ftfont_driver;
960 font->encoding_charset = font->repertory_charset = -1;
962 upEM = ft_face->units_per_EM;
963 scalable = (INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
964 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0);
965 if (scalable)
967 font->ascent = ft_face->ascender * size / upEM;
968 font->descent = - ft_face->descender * size / upEM;
969 font->height = ft_face->height * size / upEM;
971 else
973 font->ascent = ft_face->size->metrics.ascender >> 6;
974 font->descent = - ft_face->size->metrics.descender >> 6;
975 font->height = ft_face->size->metrics.height >> 6;
977 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
978 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
979 else
980 spacing = FC_PROPORTIONAL;
981 if (spacing != FC_PROPORTIONAL)
982 font->min_width = font->average_width = font->space_width
983 = (scalable ? ft_face->max_advance_width * size / upEM
984 : ft_face->size->metrics.max_advance >> 6);
985 else
987 int n;
989 font->min_width = font->average_width = font->space_width = 0;
990 for (i = 32, n = 0; i < 127; i++)
991 if (FT_Load_Char (ft_face, i, FT_LOAD_DEFAULT) != 0)
993 int this_width = ft_face->glyph->metrics.horiAdvance >> 6;
995 if (this_width > 0
996 && (! font->min_width || font->min_width > this_width))
997 font->min_width = this_width;
998 if (i == 32)
999 font->space_width = this_width;
1000 font->average_width += this_width;
1001 n++;
1003 if (n > 0)
1004 font->average_width /= n;
1007 font->baseline_offset = 0;
1008 font->relative_compose = 0;
1009 font->default_ascent = 0;
1010 font->vertical_centering = 0;
1011 if (scalable)
1013 font->underline_position = -ft_face->underline_position * size / upEM;
1014 font->underline_thickness = -ft_face->underline_thickness * size / upEM;
1016 else
1018 font->underline_position = -1;
1019 font->underline_thickness = 0;
1022 return font_object;
1025 static void
1026 ftfont_close (f, font)
1027 FRAME_PTR f;
1028 struct font *font;
1030 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1031 Lisp_Object val, cache;
1033 cache = ftfont_lookup_cache (font->props[FONT_FILE_INDEX]);
1034 val = XCDR (cache);
1035 (XSAVE_VALUE (val)->integer)--;
1036 if (XSAVE_VALUE (val)->integer == 0)
1038 FT_Face ft_face = XSAVE_VALUE (val)->pointer;
1040 FT_Done_Face (ft_face);
1041 #ifdef HAVE_LIBOTF
1042 if (ftfont_info->otf)
1043 OTF_close (ftfont_info->otf);
1044 #endif
1045 XSAVE_VALUE (val)->pointer = NULL;
1047 else
1048 FT_Done_Size (ftfont_info->ft_size);
1051 static int
1052 ftfont_has_char (entity, c)
1053 Lisp_Object entity;
1054 int c;
1056 Lisp_Object val;
1057 int fc_charset_idx;
1058 struct charset *charset;
1060 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
1061 fc_charset_idx = XINT (XCDR (XCDR (val)));
1062 if (fc_charset_idx < 0)
1063 return -1;
1064 charset = CHARSET_FROM_ID (fc_charset_table[fc_charset_idx].charset_id);
1065 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset));
1068 static unsigned
1069 ftfont_encode_char (font, c)
1070 struct font *font;
1071 int c;
1073 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1074 FT_Face ft_face = ftfont_info->ft_size->face;
1075 FT_ULong charcode = c;
1076 FT_UInt code = FT_Get_Char_Index (ft_face, charcode);
1078 return (code > 0 ? code : FONT_INVALID_CODE);
1081 static int
1082 ftfont_text_extents (font, code, nglyphs, metrics)
1083 struct font *font;
1084 unsigned *code;
1085 int nglyphs;
1086 struct font_metrics *metrics;
1088 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1089 FT_Face ft_face = ftfont_info->ft_size->face;
1090 int width = 0;
1091 int i;
1093 if (ftfont_info->ft_size != ft_face->size)
1094 FT_Activate_Size (ftfont_info->ft_size);
1095 if (metrics)
1096 bzero (metrics, sizeof (struct font_metrics));
1097 for (i = 0; i < nglyphs; i++)
1099 if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0)
1101 FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
1103 if (metrics)
1105 if (metrics->lbearing > width + (m->horiBearingX >> 6))
1106 metrics->lbearing = width + (m->horiBearingX >> 6);
1107 if (metrics->rbearing
1108 < width + ((m->horiBearingX + m->width) >> 6))
1109 metrics->rbearing
1110 = width + ((m->horiBearingX + m->width) >> 6);
1111 if (metrics->ascent < (m->horiBearingY >> 6))
1112 metrics->ascent = m->horiBearingY >> 6;
1113 if (metrics->descent > ((m->horiBearingY + m->height) >> 6))
1114 metrics->descent = (m->horiBearingY + m->height) >> 6;
1116 width += m->horiAdvance >> 6;
1118 else
1120 width += font->space_width;
1123 if (metrics)
1124 metrics->width = width;
1126 return width;
1129 static int
1130 ftfont_get_bitmap (font, code, bitmap, bits_per_pixel)
1131 struct font *font;
1132 unsigned code;
1133 struct font_bitmap *bitmap;
1134 int bits_per_pixel;
1136 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1137 FT_Face ft_face = ftfont_info->ft_size->face;
1138 FT_Int32 load_flags = FT_LOAD_RENDER;
1140 if (ftfont_info->ft_size != ft_face->size)
1141 FT_Activate_Size (ftfont_info->ft_size);
1142 if (bits_per_pixel == 1)
1144 #ifdef FT_LOAD_TARGET_MONO
1145 load_flags |= FT_LOAD_TARGET_MONO;
1146 #else
1147 load_flags |= FT_LOAD_MONOCHROME;
1148 #endif
1150 else if (bits_per_pixel != 8)
1151 /* We don't support such a rendering. */
1152 return -1;
1154 if (FT_Load_Glyph (ft_face, code, load_flags) != 0)
1155 return -1;
1156 bitmap->bits_per_pixel
1157 = (ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 1
1158 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY ? 8
1159 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD ? 8
1160 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V ? 8
1161 : -1);
1162 if (bitmap->bits_per_pixel < 0)
1163 /* We don't suport that kind of pixel mode. */
1164 return -1;
1165 bitmap->rows = ft_face->glyph->bitmap.rows;
1166 bitmap->width = ft_face->glyph->bitmap.width;
1167 bitmap->pitch = ft_face->glyph->bitmap.pitch;
1168 bitmap->buffer = ft_face->glyph->bitmap.buffer;
1169 bitmap->left = ft_face->glyph->bitmap_left;
1170 bitmap->top = ft_face->glyph->bitmap_top;
1171 bitmap->advance = ft_face->glyph->metrics.horiAdvance >> 6;
1172 bitmap->extra = NULL;
1174 return 0;
1177 static int
1178 ftfont_anchor_point (font, code, index, x, y)
1179 struct font *font;
1180 unsigned code;
1181 int index;
1182 int *x, *y;
1184 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1185 FT_Face ft_face = ftfont_info->ft_size->face;
1187 if (ftfont_info->ft_size != ft_face->size)
1188 FT_Activate_Size (ftfont_info->ft_size);
1189 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
1190 return -1;
1191 if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
1192 return -1;
1193 if (index >= ft_face->glyph->outline.n_points)
1194 return -1;
1195 *x = ft_face->glyph->outline.points[index].x;
1196 *y = ft_face->glyph->outline.points[index].y;
1197 return 0;
1200 #ifdef HAVE_LIBOTF
1201 #ifdef HAVE_M17N_FLT
1203 struct MFLTFontFT
1205 MFLTFont flt_font;
1206 struct font *font;
1207 FT_Face ft_face;
1208 OTF *otf;
1211 static int
1212 ftfont_get_glyph_id (font, gstring, from, to)
1213 MFLTFont *font;
1214 MFLTGlyphString *gstring;
1215 int from, to;
1217 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1218 FT_Face ft_face = flt_font_ft->ft_face;
1219 MFLTGlyph *g;
1221 for (g = gstring->glyphs + from; from < to; g++, from++)
1222 if (! g->encoded)
1224 FT_UInt code = FT_Get_Char_Index (ft_face, g->code);
1226 g->code = code > 0 ? code : FONT_INVALID_CODE;
1227 g->encoded = 1;
1229 return 0;
1232 static int
1233 ftfont_get_metrics (font, gstring, from, to)
1234 MFLTFont *font;
1235 MFLTGlyphString *gstring;
1236 int from, to;
1238 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1239 FT_Face ft_face = flt_font_ft->ft_face;
1240 MFLTGlyph *g;
1242 for (g = gstring->glyphs + from; from < to; g++, from++)
1243 if (! g->measured)
1245 if (g->code != FONT_INVALID_CODE)
1247 FT_Glyph_Metrics *m;
1249 if (FT_Load_Glyph (ft_face, g->code, FT_LOAD_DEFAULT) != 0)
1250 abort ();
1251 m = &ft_face->glyph->metrics;
1253 g->lbearing = m->horiBearingX;
1254 g->rbearing = m->horiBearingX + m->width;
1255 g->ascent = m->horiBearingY;
1256 g->descent = m->height - m->horiBearingY;
1257 g->xadv = m->horiAdvance;
1259 else
1261 g->lbearing = 0;
1262 g->rbearing = g->xadv = flt_font_ft->font->space_width << 6;
1263 g->ascent = flt_font_ft->font->ascent << 6;
1264 g->descent = flt_font_ft->font->descent << 6;
1266 g->yadv = 0;
1267 g->measured = 1;
1269 return 0;
1272 static int
1273 ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1275 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1276 OTF *otf = flt_font_ft->otf;
1277 OTF_Tag *tags;
1278 int i, n, negative;
1280 for (i = 0; i < 2; i++)
1282 if (! spec->features[i])
1283 continue;
1284 for (n = 0; spec->features[i][n]; n++);
1285 tags = alloca (sizeof (OTF_Tag) * n);
1286 for (n = 0, negative = 0; spec->features[i][n]; n++)
1288 if (spec->features[i][n] == 0xFFFFFFFF)
1289 negative = 1;
1290 else if (negative)
1291 tags[n - 1] = spec->features[i][n] | 0x80000000;
1292 else
1293 tags[n] = spec->features[i][n];
1295 if (n - negative > 0
1296 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1297 tags, n - negative) != 1)
1298 return 0;
1300 return 1;
1303 #define DEVICE_DELTA(table, size) \
1304 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1305 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1306 : 0)
1308 static void
1309 adjust_anchor (FT_Face ft_face, OTF_Anchor *anchor,
1310 unsigned code, int x_ppem, int y_ppem, int *x, int *y)
1312 if (anchor->AnchorFormat == 2)
1314 FT_Outline *outline;
1315 int ap = anchor->f.f1.AnchorPoint;
1317 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
1318 outline = &ft_face->glyph->outline;
1319 if (ap < outline->n_points)
1321 *x = outline->points[ap].x << 6;
1322 *y = outline->points[ap].y << 6;
1325 else if (anchor->AnchorFormat == 3)
1327 if (anchor->f.f2.XDeviceTable.offset)
1328 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
1329 if (anchor->f.f2.YDeviceTable.offset)
1330 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
1334 static OTF_GlyphString otf_gstring;
1336 static int
1337 ftfont_drive_otf (font, spec, in, from, to, out, adjustment)
1338 MFLTFont *font;
1339 MFLTOtfSpec *spec;
1340 MFLTGlyphString *in;
1341 int from, to;
1342 MFLTGlyphString *out;
1343 MFLTGlyphAdjustment *adjustment;
1345 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1346 FT_Face ft_face = flt_font_ft->ft_face;
1347 OTF *otf = flt_font_ft->otf;
1348 int len = to - from;
1349 int i, j, gidx;
1350 OTF_Glyph *otfg;
1351 char script[5], *langsys = NULL;
1352 char *gsub_features = NULL, *gpos_features = NULL;
1354 if (len == 0)
1355 return from;
1356 OTF_tag_name (spec->script, script);
1357 if (spec->langsys)
1359 langsys = alloca (5);
1360 OTF_tag_name (spec->langsys, langsys);
1362 for (i = 0; i < 2; i++)
1364 char *p;
1366 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
1368 for (j = 0; spec->features[i][j]; j++);
1369 if (i == 0)
1370 p = gsub_features = alloca (6 * j);
1371 else
1372 p = gpos_features = alloca (6 * j);
1373 for (j = 0; spec->features[i][j]; j++)
1375 if (spec->features[i][j] == 0xFFFFFFFF)
1376 *p++ = '*', *p++ = ',';
1377 else
1379 OTF_tag_name (spec->features[i][j], p);
1380 p[4] = ',';
1381 p += 5;
1384 *--p = '\0';
1388 if (otf_gstring.size == 0)
1390 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
1391 otf_gstring.size = len;
1393 else if (otf_gstring.size < len)
1395 otf_gstring.glyphs = (OTF_Glyph *) realloc (otf_gstring.glyphs,
1396 sizeof (OTF_Glyph) * len);
1397 otf_gstring.size = len;
1399 otf_gstring.used = len;
1400 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
1401 for (i = 0; i < len; i++)
1403 otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
1404 otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code;
1407 OTF_drive_gdef (otf, &otf_gstring);
1408 gidx = out->used;
1410 if (gsub_features)
1412 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
1413 < 0)
1414 goto simple_copy;
1415 if (out->allocated < out->used + otf_gstring.used)
1416 return -2;
1417 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
1419 MFLTGlyph *g;
1420 int min_from, max_to;
1421 int j;
1423 g = out->glyphs + out->used;
1424 *g = in->glyphs[from + otfg->f.index.from];
1425 if (g->code != otfg->glyph_id)
1427 g->c = 0;
1428 g->code = otfg->glyph_id;
1429 g->measured = 0;
1431 out->used++;
1432 min_from = g->from;
1433 max_to = g->to;
1434 if (otfg->f.index.from < otfg->f.index.to)
1436 /* OTFG substitutes multiple glyphs in IN. */
1437 for (j = from + otfg->f.index.from + 1;
1438 j <= from + otfg->f.index.to; j++)
1440 if (min_from > in->glyphs[j].from)
1441 min_from = in->glyphs[j].from;
1442 if (max_to < in->glyphs[j].to)
1443 max_to = in->glyphs[j].to;
1445 g->from = min_from;
1446 g->to = max_to;
1448 for (i++, otfg++; (i < otf_gstring.used
1449 && otfg->f.index.from == otfg[-1].f.index.from);
1450 i++, otfg++)
1452 g = out->glyphs + out->used;
1453 *g = in->glyphs[from + otfg->f.index.to];
1454 if (g->code != otfg->glyph_id)
1456 g->c = 0;
1457 g->code = otfg->glyph_id;
1458 g->measured = 0;
1460 out->used++;
1464 else
1466 if (out->allocated < out->used + len)
1467 return -2;
1468 for (i = 0; i < len; i++)
1469 out->glyphs[out->used++] = in->glyphs[from + i];
1472 if (gpos_features)
1474 MFLTGlyph *base = NULL, *mark = NULL, *g;
1475 int x_ppem, y_ppem, x_scale, y_scale;
1477 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
1478 < 0)
1479 return to;
1481 x_ppem = ft_face->size->metrics.x_ppem;
1482 y_ppem = ft_face->size->metrics.y_ppem;
1483 x_scale = ft_face->size->metrics.x_scale;
1484 y_scale = ft_face->size->metrics.y_scale;
1486 for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx;
1487 i < otf_gstring.used; i++, otfg++, g++)
1489 MFLTGlyph *prev;
1491 if (! otfg->glyph_id)
1492 continue;
1493 switch (otfg->positioning_type)
1495 case 0:
1496 break;
1497 case 1: /* Single */
1498 case 2: /* Pair */
1500 int format = otfg->f.f1.format;
1502 if (format & OTF_XPlacement)
1503 adjustment[i].xoff
1504 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
1505 if (format & OTF_XPlaDevice)
1506 adjustment[i].xoff
1507 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
1508 if (format & OTF_YPlacement)
1509 adjustment[i].yoff
1510 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
1511 if (format & OTF_YPlaDevice)
1512 adjustment[i].yoff
1513 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
1514 if (format & OTF_XAdvance)
1515 adjustment[i].xadv
1516 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
1517 if (format & OTF_XAdvDevice)
1518 adjustment[i].xadv
1519 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
1520 if (format & OTF_YAdvance)
1521 adjustment[i].yadv
1522 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
1523 if (format & OTF_YAdvDevice)
1524 adjustment[i].yadv
1525 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
1526 adjustment[i].set = 1;
1528 break;
1529 case 3: /* Cursive */
1530 /* Not yet supported. */
1531 break;
1532 case 4: /* Mark-to-Base */
1533 case 5: /* Mark-to-Ligature */
1534 if (! base)
1535 break;
1536 prev = base;
1537 goto label_adjust_anchor;
1538 default: /* i.e. case 6 Mark-to-Mark */
1539 if (! mark)
1540 break;
1541 prev = mark;
1543 label_adjust_anchor:
1545 int base_x, base_y, mark_x, mark_y;
1546 int this_from, this_to;
1548 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
1549 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
1550 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
1551 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;;
1553 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
1554 adjust_anchor (ft_face, otfg->f.f4.base_anchor,
1555 prev->code, x_ppem, y_ppem, &base_x, &base_y);
1556 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
1557 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->code,
1558 x_ppem, y_ppem, &mark_x, &mark_y);
1559 adjustment[i].xoff = (base_x - mark_x);
1560 adjustment[i].yoff = - (base_y - mark_y);
1561 adjustment[i].back = (g - prev);
1562 adjustment[i].xadv = 0;
1563 adjustment[i].advance_is_absolute = 1;
1564 adjustment[i].set = 1;
1565 this_from = g->from;
1566 this_to = g->to;
1567 for (j = 0; prev + j < g; j++)
1569 if (this_from > prev[j].from)
1570 this_from = prev[j].from;
1571 if (this_to < prev[j].to)
1572 this_to = prev[j].to;
1574 for (; prev <= g; prev++)
1576 prev->from = this_from;
1577 prev->to = this_to;
1581 if (otfg->GlyphClass == OTF_GlyphClass0)
1582 base = mark = g;
1583 else if (otfg->GlyphClass == OTF_GlyphClassMark)
1584 mark = g;
1585 else
1586 base = g;
1589 return to;
1591 simple_copy:
1592 if (out->allocated < out->used + len)
1593 return -2;
1594 font->get_metrics (font, in, from, to);
1595 memcpy (out->glyphs + out->used, in->glyphs + from,
1596 sizeof (MFLTGlyph) * len);
1597 out->used += len;
1598 return to;
1601 static MFLTGlyphString gstring;
1603 static int m17n_flt_initialized;
1605 extern Lisp_Object QCfamily;
1607 Lisp_Object
1608 ftfont_shape_by_flt (lgstring, font, ft_face, otf)
1609 Lisp_Object lgstring;
1610 struct font *font;
1611 FT_Face ft_face;
1612 OTF *otf;
1614 EMACS_UINT len = LGSTRING_LENGTH (lgstring);
1615 EMACS_UINT i;
1616 struct MFLTFontFT flt_font_ft;
1618 if (! m17n_flt_initialized)
1620 M17N_INIT ();
1621 m17n_flt_initialized = 1;
1624 for (i = 0; i < len; i++)
1625 if (NILP (LGSTRING_GLYPH (lgstring, i)))
1626 break;
1627 len = i;
1629 if (gstring.allocated == 0)
1631 gstring.allocated = len * 2;
1632 gstring.glyph_size = sizeof (MFLTGlyph);
1633 gstring.glyphs = malloc (sizeof (MFLTGlyph) * gstring.allocated);
1635 else if (gstring.allocated < len * 2)
1637 gstring.allocated = len * 2;
1638 gstring.glyphs = realloc (gstring.glyphs,
1639 sizeof (MFLTGlyph) * gstring.allocated);
1641 for (i = 0; i < len; i++)
1642 gstring.glyphs[i].c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
1643 gstring.used = len;
1644 gstring.r2l = 0;
1647 Lisp_Object family = Ffont_get (LGSTRING_FONT (lgstring), QCfamily);
1649 if (NILP (family))
1650 flt_font_ft.flt_font.family = Mnil;
1651 else
1652 flt_font_ft.flt_font.family
1653 = msymbol ((char *) SDATA (SYMBOL_NAME (family)));
1655 flt_font_ft.flt_font.x_ppem = ft_face->size->metrics.x_ppem;
1656 flt_font_ft.flt_font.y_ppem = ft_face->size->metrics.y_ppem;
1657 flt_font_ft.flt_font.get_glyph_id = ftfont_get_glyph_id;
1658 flt_font_ft.flt_font.get_metrics = ftfont_get_metrics;
1659 flt_font_ft.flt_font.check_otf = ftfont_check_otf;
1660 flt_font_ft.flt_font.drive_otf = ftfont_drive_otf;
1661 flt_font_ft.flt_font.internal = NULL;
1662 flt_font_ft.font = font;
1663 flt_font_ft.ft_face = ft_face;
1664 flt_font_ft.otf = otf;
1665 for (i = 0; i < 3; i++)
1667 int result = mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, NULL);
1668 if (result != -2)
1669 break;
1670 gstring.allocated += gstring.allocated;
1671 gstring.glyphs = realloc (gstring.glyphs,
1672 sizeof (MFLTGlyph) * gstring.allocated);
1674 if (gstring.used > LGSTRING_LENGTH (lgstring))
1675 return Qnil;
1676 for (i = 0; i < gstring.used; i++)
1678 MFLTGlyph *g = gstring.glyphs + i;
1680 g->from = LGLYPH_FROM (LGSTRING_GLYPH (lgstring, g->from));
1681 g->to = LGLYPH_TO (LGSTRING_GLYPH (lgstring, g->to));
1684 for (i = 0; i < gstring.used; i++)
1686 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
1687 MFLTGlyph *g = gstring.glyphs + i;
1689 if (NILP (lglyph))
1691 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
1692 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
1694 LGLYPH_SET_FROM (lglyph, g->from);
1695 LGLYPH_SET_TO (lglyph, g->to);
1696 LGLYPH_SET_CHAR (lglyph, g->c);
1697 LGLYPH_SET_CODE (lglyph, g->code);
1698 LGLYPH_SET_WIDTH (lglyph, g->xadv >> 6);
1699 LGLYPH_SET_LBEARING (lglyph, g->lbearing >> 6);
1700 LGLYPH_SET_RBEARING (lglyph, g->rbearing >> 6);
1701 LGLYPH_SET_ASCENT (lglyph, g->ascent >> 6);
1702 LGLYPH_SET_DESCENT (lglyph, g->descent >> 6);
1703 if (g->adjusted)
1705 Lisp_Object vec;
1707 vec = Fmake_vector (make_number (3), Qnil);
1708 ASET (vec, 0, make_number (g->xoff >> 6));
1709 ASET (vec, 1, make_number (g->yoff >> 6));
1710 ASET (vec, 2, make_number (g->xadv >> 6));
1711 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
1714 return make_number (i);
1717 Lisp_Object
1718 ftfont_shape (lgstring)
1719 Lisp_Object lgstring;
1721 struct font *font;
1722 struct ftfont_info *ftfont_info;
1724 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
1725 ftfont_info = (struct ftfont_info *) font;
1726 if (! ftfont_info->maybe_otf)
1727 return make_number (0);
1728 if (! ftfont_info->otf)
1730 OTF *otf = OTF_open_ft_face (ftfont_info->ft_size->face);
1732 if (! otf || OTF_get_table (otf, "head") < 0)
1734 if (otf)
1735 OTF_close (otf);
1736 ftfont_info->maybe_otf = 0;
1737 return make_number (0);
1740 ftfont_info->otf = otf;
1743 return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face,
1744 ftfont_info->otf);
1747 #endif /* HAVE_M17N_FLT */
1748 #endif /* HAVE_LIBOTF */
1750 Lisp_Object
1751 ftfont_font_format (FcPattern *pattern, Lisp_Object filename)
1753 FcChar8 *str;
1755 #ifdef FC_FONTFORMAT
1756 if (pattern)
1758 if (FcPatternGetString (pattern, FC_FONTFORMAT, 0, &str) != FcResultMatch)
1759 return Qnil;
1760 if (strcmp ((char *) str, "TrueType") == 0)
1761 return intern ("truetype");
1762 if (strcmp ((char *) str, "Type 1") == 0)
1763 return intern ("type1");
1764 if (strcmp ((char *) str, "PCF") == 0)
1765 return intern ("pcf");
1766 if (strcmp ((char *) str, "BDF") == 0)
1767 return intern ("bdf");
1769 #endif /* FC_FONTFORMAT */
1770 if (STRINGP (filename))
1772 int len = SBYTES (filename);
1774 if (len >= 4)
1776 str = (FcChar8 *) (SDATA (filename) + len - 4);
1777 if (xstrcasecmp ((char *) str, ".ttf") == 0)
1778 return intern ("truetype");
1779 if (xstrcasecmp ((char *) str, ".pfb") == 0)
1780 return intern ("type1");
1781 if (xstrcasecmp ((char *) str, ".pcf") == 0)
1782 return intern ("pcf");
1783 if (xstrcasecmp ((char *) str, ".bdf") == 0)
1784 return intern ("bdf");
1787 return intern ("unknown");
1791 void
1792 syms_of_ftfont ()
1794 DEFSYM (Qfreetype, "freetype");
1795 DEFSYM (Qmonospace, "monospace");
1796 DEFSYM (Qsans_serif, "sans-serif");
1797 DEFSYM (Qserif, "serif");
1798 DEFSYM (Qmono, "mono");
1799 DEFSYM (Qsans, "sans");
1800 DEFSYM (Qsans__serif, "sans serif");
1802 staticpro (&freetype_font_cache);
1803 freetype_font_cache = Fcons (Qt, Qnil);
1805 staticpro (&ftfont_generic_family_list);
1806 ftfont_generic_family_list
1807 = Fcons (Fcons (Qmonospace, Qt),
1808 Fcons (Fcons (Qsans_serif, Qt),
1809 Fcons (Fcons (Qsans, Qt), Qnil)));
1811 staticpro (&ft_face_cache);
1812 ft_face_cache = Qnil;
1814 ftfont_driver.type = Qfreetype;
1815 register_font_driver (&ftfont_driver, NULL);
1818 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
1819 (do not change this comment) */