1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006-2012 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
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/>. */
26 #include <fontconfig/fontconfig.h>
27 #include <fontconfig/fcfreetype.h>
30 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
36 #include "composite.h"
41 /* Symbolic type of this font-driver. */
42 static Lisp_Object Qfreetype
;
44 /* Fontconfig's generic families and their aliases. */
45 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
47 /* Flag to tell if FcInit is already called or not. */
48 static bool fc_initialized
;
50 /* Handle to a FreeType library instance. */
51 static FT_Library ft_library
;
53 /* Cache for FreeType fonts. */
54 static Lisp_Object freetype_font_cache
;
56 /* Cache for FT_Face and FcCharSet. */
57 static Lisp_Object ft_face_cache
;
59 /* The actual structure for FreeType font that can be casted to struct
66 /* The following four members must be here in this order to be
67 compatible with struct xftfont_info (in xftfont.c). */
68 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
70 #endif /* HAVE_LIBOTF */
78 FTFONT_CACHE_FOR_FACE
,
79 FTFONT_CACHE_FOR_CHARSET
,
80 FTFONT_CACHE_FOR_ENTITY
83 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
85 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
87 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
88 enum ftfont_cache_for
);
90 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
92 Lisp_Object
ftfont_font_format (FcPattern
*, Lisp_Object
);
94 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
100 /* characters to distinguish the charset from the others */
102 /* additional constraint by language */
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 }},
147 /* Dirty hack for handing ADSTYLE property.
149 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
150 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
151 "Oblique", "Italic", or any non-normal SWIDTH property names
152 (e.g. SemiCondensed) are appended. In addition, if there's no
153 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
154 "Regular" is used for FC_STYLE (see the function
155 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
157 Unfortunately this behavior is not documented, so the following
158 code may fail if FreeType changes the behavior in the future. */
161 get_adstyle_property (FcPattern
*p
)
168 if ((FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fcstr
) == FcResultMatch
)
169 && xstrcasecmp ((char *) fcstr
, "bdf") != 0
170 && xstrcasecmp ((char *) fcstr
, "pcf") != 0)
171 /* Not a BDF nor PCF font. */
174 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
176 str
= (char *) fcstr
;
177 for (end
= str
; *end
&& *end
!= ' '; end
++);
180 char *newstr
= alloca (end
- str
+ 1);
181 memcpy (newstr
, str
, end
- str
);
182 newstr
[end
- str
] = '\0';
183 end
= newstr
+ (end
- str
);
186 if (xstrcasecmp (str
, "Regular") == 0
187 || xstrcasecmp (str
, "Bold") == 0
188 || xstrcasecmp (str
, "Oblique") == 0
189 || xstrcasecmp (str
, "Italic") == 0)
191 adstyle
= font_intern_prop (str
, end
- str
, 1);
192 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
198 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
200 Lisp_Object key
, cache
, entity
;
208 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
210 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
214 key
= Fcons (build_unibyte_string (file
), make_number (idx
));
215 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
216 entity
= XCAR (cache
);
219 Lisp_Object val
= font_make_entity ();
222 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
223 ASET (val
, i
, AREF (entity
, i
));
225 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
226 font_put_extra (val
, QCfont_entity
, key
);
230 entity
= font_make_entity ();
231 XSETCAR (cache
, entity
);
233 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
234 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
236 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
238 char *s
= (char *) str
;
239 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
241 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
243 char *s
= (char *) str
;
244 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
246 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
248 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
249 numeric
= FC_WEIGHT_MEDIUM
;
250 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
252 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
255 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
257 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
259 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
261 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
263 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
266 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
267 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
268 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
269 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
272 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
274 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
277 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
278 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
282 /* As this font is not scalable, perhaps this is a BDF or PCF
286 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
287 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
288 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
292 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
293 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
294 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
295 FT_Done_Face (ft_face
);
299 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
300 font_put_extra (entity
, QCfont_entity
, key
);
305 static Lisp_Object ftfont_generic_family_list
;
308 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
315 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
316 if (EQ (family
, Qmono
))
318 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
319 family
= Qsans_serif
;
320 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
323 if (! EQ (XCDR (slot
), Qt
))
325 pattern
= FcPatternDuplicate (pattern
);
328 FcPatternDel (pattern
, FC_FOUNDRY
);
329 FcPatternDel (pattern
, FC_FAMILY
);
330 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
331 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
333 /* This is to avoid the effect of locale. */
334 static const FcChar8 lang
[] = "en";
335 langset
= FcLangSetCreate ();
336 FcLangSetAdd (langset
, lang
);
337 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
338 FcLangSetDestroy (langset
);
340 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
341 FcDefaultSubstitute (pattern
);
342 match
= FcFontMatch (NULL
, pattern
, &result
);
347 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
348 family
= intern ((char *) fam
);
352 XSETCDR (slot
, family
);
353 if (match
) FcPatternDestroy (match
);
355 if (pattern
) FcPatternDestroy (pattern
);
359 struct ftfont_cache_data
362 FcCharSet
*fc_charset
;
366 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
368 Lisp_Object cache
, val
, entity
;
369 struct ftfont_cache_data
*cache_data
;
371 if (FONT_ENTITY_P (key
))
374 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
375 eassert (CONSP (val
));
381 if (NILP (ft_face_cache
))
384 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
387 if (NILP (ft_face_cache
))
393 ft_face_cache
= Fmake_hash_table (2, args
);
395 cache_data
= xmalloc (sizeof *cache_data
);
396 cache_data
->ft_face
= NULL
;
397 cache_data
->fc_charset
= NULL
;
398 val
= make_save_value (NULL
, 0);
399 XSAVE_VALUE (val
)->integer
= 0;
400 XSAVE_VALUE (val
)->pointer
= cache_data
;
401 cache
= Fcons (Qnil
, val
);
402 Fputhash (key
, cache
, ft_face_cache
);
407 cache_data
= XSAVE_VALUE (val
)->pointer
;
410 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
413 if (cache_for
== FTFONT_CACHE_FOR_FACE
414 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
416 char *filename
= SSDATA (XCAR (key
));
417 int idx
= XINT (XCDR (key
));
419 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
422 && FT_Init_FreeType (&ft_library
) != 0)
424 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
430 FcPattern
*pat
= NULL
;
431 FcFontSet
*fontset
= NULL
;
432 FcObjectSet
*objset
= NULL
;
433 FcCharSet
*charset
= NULL
;
435 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
436 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
439 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
442 fontset
= FcFontList (NULL
, pat
, objset
);
445 if (fontset
&& fontset
->nfont
> 0
446 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
449 cache_data
->fc_charset
= FcCharSetCopy (charset
);
451 cache_data
->fc_charset
= FcCharSetCreate ();
455 FcFontSetDestroy (fontset
);
457 FcObjectSetDestroy (objset
);
459 FcPatternDestroy (pat
);
466 ftfont_get_fc_charset (Lisp_Object entity
)
468 Lisp_Object val
, cache
;
469 struct ftfont_cache_data
*cache_data
;
471 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
473 cache_data
= XSAVE_VALUE (val
)->pointer
;
474 return cache_data
->fc_charset
;
479 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
483 if (ftfont_info
->otf
)
484 return ftfont_info
->otf
;
485 if (! ftfont_info
->maybe_otf
)
487 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
488 if (! otf
|| OTF_get_table (otf
, "head") < 0)
492 ftfont_info
->maybe_otf
= 0;
495 ftfont_info
->otf
= otf
;
498 #endif /* HAVE_LIBOTF */
500 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
501 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
502 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
503 static Lisp_Object
ftfont_list_family (Lisp_Object
);
504 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
505 static void ftfont_close (FRAME_PTR
, struct font
*);
506 static int ftfont_has_char (Lisp_Object
, int);
507 static unsigned ftfont_encode_char (struct font
*, int);
508 static int ftfont_text_extents (struct font
*, unsigned *, int,
509 struct font_metrics
*);
510 static int ftfont_get_bitmap (struct font
*, unsigned,
511 struct font_bitmap
*, int);
512 static int ftfont_anchor_point (struct font
*, unsigned, int,
515 static Lisp_Object
ftfont_otf_capability (struct font
*);
516 # ifdef HAVE_M17N_FLT
517 static Lisp_Object
ftfont_shape (Lisp_Object
);
521 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
522 static int ftfont_variation_glyphs (struct font
*, int c
,
523 unsigned variations
[256]);
524 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
526 struct font_driver ftfont_driver
=
528 LISP_INITIALLY_ZERO
, /* Qfreetype */
529 0, /* case insensitive */
534 NULL
, /* free_entity */
537 /* We can't draw a text without device dependent functions. */
538 NULL
, /* prepare_face */
539 NULL
, /* done_face */
543 /* We can't draw a text without device dependent functions. */
546 NULL
, /* free_bitmap */
547 NULL
, /* get_outline */
548 NULL
, /* free_outline */
551 ftfont_otf_capability
,
552 #else /* not HAVE_LIBOTF */
554 #endif /* not HAVE_LIBOTF */
555 NULL
, /* otf_drive */
556 NULL
, /* start_for_frame */
557 NULL
, /* end_for_frame */
558 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
560 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
562 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
565 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
566 ftfont_variation_glyphs
,
571 ftfont_filter_properties
, /* filter_properties */
575 ftfont_get_cache (FRAME_PTR f
)
577 return freetype_font_cache
;
581 ftfont_get_charset (Lisp_Object registry
)
583 char *str
= SSDATA (SYMBOL_NAME (registry
));
584 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
588 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
592 else if (str
[i
] == '*')
599 regexp
= make_unibyte_string (re
, j
);
600 for (i
= 0; fc_charset_table
[i
].name
; i
++)
601 if (fast_c_string_match_ignore_case
602 (regexp
, fc_charset_table
[i
].name
,
603 strlen (fc_charset_table
[i
].name
)) >= 0)
605 if (! fc_charset_table
[i
].name
)
607 if (! fc_charset_table
[i
].fc_charset
)
609 FcCharSet
*charset
= FcCharSetCreate ();
610 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
614 for (j
= 0; uniquifier
[j
]; j
++)
615 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
617 FcCharSetDestroy (charset
);
620 fc_charset_table
[i
].fc_charset
= charset
;
628 unsigned int script_tag
, langsys_tag
;
630 unsigned int *features
[2];
633 #define OTF_SYM_TAG(SYM, TAG) \
635 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
636 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
639 #define OTF_TAG_STR(TAG, P) \
641 (P)[0] = (char) (TAG >> 24); \
642 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
643 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
644 (P)[3] = (char) (TAG & 0xFF); \
649 #define OTF_TAG_SYM(SYM, TAG) \
653 OTF_TAG_STR (TAG, str); \
654 (SYM) = font_intern_prop (str, 4, 1); \
659 static struct OpenTypeSpec
*
660 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
662 struct OpenTypeSpec
*spec
= malloc (sizeof *spec
);
669 spec
->script
= XCAR (otf_spec
);
670 if (! NILP (spec
->script
))
672 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
673 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
674 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
675 spec
->script
= XCDR (val
);
680 spec
->script_tag
= 0x44464C54; /* "DFLT" */
681 otf_spec
= XCDR (otf_spec
);
682 spec
->langsys_tag
= 0;
683 if (! NILP (otf_spec
))
685 val
= XCAR (otf_spec
);
687 OTF_SYM_TAG (val
, spec
->langsys_tag
);
688 otf_spec
= XCDR (otf_spec
);
690 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
691 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
695 val
= XCAR (otf_spec
);
700 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
702 : malloc (XINT (len
) * sizeof *spec
->features
[i
]));
703 if (! spec
->features
[i
])
705 if (i
> 0 && spec
->features
[0])
706 free (spec
->features
[0]);
710 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
712 if (NILP (XCAR (val
)))
718 OTF_SYM_TAG (XCAR (val
), tag
);
719 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
722 spec
->nfeatures
[i
] = j
;
728 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
730 Lisp_Object tmp
, extra
;
731 FcPattern
*pattern
= NULL
;
732 FcCharSet
*charset
= NULL
;
733 FcLangSet
*langset
= NULL
;
737 Lisp_Object script
= Qnil
;
738 Lisp_Object registry
;
741 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
743 /* Fontconfig doesn't support reverse-italic/oblique. */
746 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
747 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
748 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
749 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
752 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
754 || EQ (registry
, Qascii_0
)
755 || EQ (registry
, Qiso10646_1
)
756 || EQ (registry
, Qunicode_bmp
))
762 fc_charset_idx
= ftfont_get_charset (registry
);
763 if (fc_charset_idx
< 0)
765 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
766 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
767 lang
= (FcChar8
*) *langname
;
770 langset
= FcLangSetCreate ();
773 FcLangSetAdd (langset
, lang
);
778 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
779 CONSP (extra
); extra
= XCDR (extra
))
781 Lisp_Object key
, val
;
783 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
789 else if (EQ (key
, QClang
))
792 langset
= FcLangSetCreate ();
797 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
801 for (; CONSP (val
); val
= XCDR (val
))
802 if (SYMBOLP (XCAR (val
))
803 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
806 else if (EQ (key
, QCotf
))
810 *otspec
= ftfont_get_open_type_spec (val
);
813 strcat (otlayout
, "otlayout:");
814 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
815 script
= (*otspec
)->script
;
818 else if (EQ (key
, QCscript
))
820 else if (EQ (key
, QCscalable
))
821 scalable
= ! NILP (val
);
824 if (! NILP (script
) && ! charset
)
826 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
828 if (CONSP (chars
) && CONSP (CDR (chars
)))
830 charset
= FcCharSetCreate ();
833 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
834 if (CHARACTERP (XCAR (chars
))
835 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
840 pattern
= FcPatternCreate ();
843 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
845 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
847 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
849 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
852 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
855 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
858 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
861 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
867 /* We come here because of unexpected error in fontconfig API call
868 (usually insufficient memory). */
871 FcPatternDestroy (pattern
);
876 if ((*otspec
)->nfeatures
[0] > 0)
877 free ((*otspec
)->features
[0]);
878 if ((*otspec
)->nfeatures
[1] > 0)
879 free ((*otspec
)->features
[1]);
885 if (langset
) FcLangSetDestroy (langset
);
886 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
891 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
893 Lisp_Object val
= Qnil
, family
, adstyle
;
896 FcFontSet
*fontset
= NULL
;
897 FcObjectSet
*objset
= NULL
;
899 Lisp_Object chars
= Qnil
;
900 char otlayout
[15]; /* For "otlayout:XXXX" */
901 struct OpenTypeSpec
*otspec
= NULL
;
903 const char *langname
= NULL
;
905 if (! fc_initialized
)
911 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
914 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
916 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
919 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
920 if (CONSP (val
) && VECTORP (XCDR (val
)))
925 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
926 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
927 family
= AREF (spec
, FONT_FAMILY_INDEX
);
930 Lisp_Object resolved
;
932 resolved
= ftfont_resolve_generic_family (family
, pattern
);
933 if (! NILP (resolved
))
935 FcPatternDel (pattern
, FC_FAMILY
);
936 if (! FcPatternAddString (pattern
, FC_FAMILY
,
937 SYMBOL_FcChar8 (resolved
)))
941 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
942 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
944 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
945 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
946 FC_STYLE
, FC_FILE
, FC_INDEX
,
949 #endif /* FC_CAPABILITY */
957 FcObjectSetAdd (objset
, FC_CHARSET
);
959 fontset
= FcFontList (NULL
, pattern
, objset
);
960 if (! fontset
|| fontset
->nfont
== 0)
963 /* Need fix because this finds any fonts. */
964 if (fontset
->nfont
== 0 && ! NILP (family
))
966 /* Try matching with configuration. For instance, the
967 configuration may specify "Nimbus Mono L" as an alias of
969 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
970 SYMBOL_FcChar8 (family
), NULL
);
973 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
976 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
979 FcPatternDel (pattern
, FC_FAMILY
);
980 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
981 FcFontSetDestroy (fontset
);
982 fontset
= FcFontList (NULL
, pattern
, objset
);
983 if (fontset
&& fontset
->nfont
> 0)
989 for (i
= 0; i
< fontset
->nfont
; i
++)
997 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
1003 #ifdef FC_CAPABILITY
1008 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
1010 || ! strstr ((char *) this, otlayout
))
1013 #endif /* FC_CAPABILITY */
1020 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1023 otf
= OTF_open ((char *) file
);
1026 if (OTF_check_features (otf
, 1,
1027 otspec
->script_tag
, otspec
->langsys_tag
,
1028 otspec
->features
[0],
1029 otspec
->nfeatures
[0]) != 1
1030 || OTF_check_features (otf
, 0,
1031 otspec
->script_tag
, otspec
->langsys_tag
,
1032 otspec
->features
[1],
1033 otspec
->nfeatures
[1]) != 1)
1036 #endif /* HAVE_LIBOTF */
1037 if (VECTORP (chars
))
1041 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1044 for (j
= 0; j
< ASIZE (chars
); j
++)
1045 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1046 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1048 if (j
== ASIZE (chars
))
1051 if (! NILP (adstyle
) || langname
)
1053 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1055 if (! NILP (adstyle
)
1056 && (NILP (this_adstyle
)
1057 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1058 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1061 && ! NILP (this_adstyle
)
1062 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1065 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1066 AREF (spec
, FONT_EXTRA_INDEX
));
1067 if (! NILP (entity
))
1068 val
= Fcons (entity
, val
);
1070 val
= Fnreverse (val
);
1074 /* We come here because of unexpected error in fontconfig API call
1075 (usually insufficient memory). */
1079 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1080 if (objset
) FcObjectSetDestroy (objset
);
1081 if (fontset
) FcFontSetDestroy (fontset
);
1082 if (pattern
) FcPatternDestroy (pattern
);
1087 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1089 Lisp_Object entity
= Qnil
;
1090 FcPattern
*pattern
, *match
= NULL
;
1092 char otlayout
[15]; /* For "otlayout:XXXX" */
1093 struct OpenTypeSpec
*otspec
= NULL
;
1094 const char *langname
= NULL
;
1096 if (! fc_initialized
)
1102 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1106 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1110 value
.type
= FcTypeDouble
;
1111 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1112 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1114 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1116 FcDefaultSubstitute (pattern
);
1117 match
= FcFontMatch (NULL
, pattern
, &result
);
1120 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1121 FcPatternDestroy (match
);
1122 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1123 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1124 ftfont_generic_family_list
))
1125 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1126 AREF (entity
, FONT_FAMILY_INDEX
))))
1130 FcPatternDestroy (pattern
);
1132 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1137 ftfont_list_family (Lisp_Object frame
)
1139 Lisp_Object list
= Qnil
;
1140 FcPattern
*pattern
= NULL
;
1141 FcFontSet
*fontset
= NULL
;
1142 FcObjectSet
*objset
= NULL
;
1145 if (! fc_initialized
)
1151 pattern
= FcPatternCreate ();
1154 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1157 fontset
= FcFontList (NULL
, pattern
, objset
);
1161 for (i
= 0; i
< fontset
->nfont
; i
++)
1163 FcPattern
*pat
= fontset
->fonts
[i
];
1166 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1167 list
= Fcons (intern ((char *) str
), list
);
1171 if (objset
) FcObjectSetDestroy (objset
);
1172 if (fontset
) FcFontSetDestroy (fontset
);
1173 if (pattern
) FcPatternDestroy (pattern
);
1180 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1182 struct ftfont_info
*ftfont_info
;
1184 struct ftfont_cache_data
*cache_data
;
1188 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1195 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1199 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1202 filename
= XCAR (val
);
1205 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1206 ft_face
= cache_data
->ft_face
;
1207 if (XSAVE_VALUE (val
)->integer
> 0)
1209 /* FT_Face in this cache is already used by the different size. */
1210 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1212 if (FT_Activate_Size (ft_size
) != 0)
1214 FT_Done_Size (ft_size
);
1218 XSAVE_VALUE (val
)->integer
++;
1219 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1222 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1224 if (XSAVE_VALUE (val
)->integer
== 0)
1225 FT_Done_Face (ft_face
);
1229 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1230 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1231 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1233 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1234 len
= font_unparse_fcname (entity
, size
, name
, 256);
1236 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1238 ASET (font_object
, FONT_FULLNAME_INDEX
,
1239 AREF (font_object
, FONT_NAME_INDEX
));
1240 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1241 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1242 font
= XFONT_OBJECT (font_object
);
1243 ftfont_info
= (struct ftfont_info
*) font
;
1244 ftfont_info
->ft_size
= ft_face
->size
;
1245 ftfont_info
->index
= XINT (idx
);
1247 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1248 ftfont_info
->otf
= NULL
;
1249 #endif /* HAVE_LIBOTF */
1250 /* This means that there's no need of transformation. */
1251 ftfont_info
->matrix
.xx
= 0;
1252 font
->pixel_size
= size
;
1253 font
->driver
= &ftfont_driver
;
1254 font
->encoding_charset
= font
->repertory_charset
= -1;
1256 upEM
= ft_face
->units_per_EM
;
1257 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1258 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1261 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1262 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1263 font
->height
= ft_face
->height
* size
/ upEM
;
1267 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1268 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1269 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1271 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1272 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1274 spacing
= FC_PROPORTIONAL
;
1275 if (spacing
!= FC_PROPORTIONAL
1277 && spacing
!= FC_DUAL
1278 #endif /* FC_DUAL */
1280 font
->min_width
= font
->average_width
= font
->space_width
1281 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1282 : ft_face
->size
->metrics
.max_advance
>> 6);
1287 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1288 for (i
= 32, n
= 0; i
< 127; i
++)
1289 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1291 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1294 && (! font
->min_width
|| font
->min_width
> this_width
))
1295 font
->min_width
= this_width
;
1297 font
->space_width
= this_width
;
1298 font
->average_width
+= this_width
;
1302 font
->average_width
/= n
;
1305 font
->baseline_offset
= 0;
1306 font
->relative_compose
= 0;
1307 font
->default_ascent
= 0;
1308 font
->vertical_centering
= 0;
1311 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1312 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1316 font
->underline_position
= -1;
1317 font
->underline_thickness
= 0;
1324 ftfont_close (FRAME_PTR f
, struct font
*font
)
1326 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1327 Lisp_Object val
, cache
;
1329 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1330 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1331 eassert (CONSP (cache
));
1333 (XSAVE_VALUE (val
)->integer
)--;
1334 if (XSAVE_VALUE (val
)->integer
== 0)
1336 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1338 FT_Done_Face (cache_data
->ft_face
);
1340 if (ftfont_info
->otf
)
1341 OTF_close (ftfont_info
->otf
);
1343 cache_data
->ft_face
= NULL
;
1346 FT_Done_Size (ftfont_info
->ft_size
);
1350 ftfont_has_char (Lisp_Object font
, int c
)
1352 struct charset
*cs
= NULL
;
1354 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1355 && charset_jisx0208
>= 0)
1356 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1357 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1358 && charset_ksc5601
>= 0)
1359 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1361 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1363 if (FONT_ENTITY_P (font
))
1365 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1367 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1371 struct ftfont_info
*ftfont_info
;
1373 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1374 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1380 ftfont_encode_char (struct font
*font
, int c
)
1382 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1383 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1384 FT_ULong charcode
= c
;
1385 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1387 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1391 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1393 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1394 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1399 if (ftfont_info
->ft_size
!= ft_face
->size
)
1400 FT_Activate_Size (ftfont_info
->ft_size
);
1402 memset (metrics
, 0, sizeof (struct font_metrics
));
1403 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1405 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1407 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1413 metrics
->lbearing
= m
->horiBearingX
>> 6;
1414 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1415 metrics
->ascent
= m
->horiBearingY
>> 6;
1416 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1422 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1423 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1424 if (metrics
->rbearing
1425 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1427 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1428 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1429 metrics
->ascent
= m
->horiBearingY
>> 6;
1430 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1431 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1433 width
+= m
->horiAdvance
>> 6;
1437 width
+= font
->space_width
;
1441 metrics
->width
= width
;
1447 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1449 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1450 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1451 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1453 if (ftfont_info
->ft_size
!= ft_face
->size
)
1454 FT_Activate_Size (ftfont_info
->ft_size
);
1455 if (bits_per_pixel
== 1)
1457 #ifdef FT_LOAD_TARGET_MONO
1458 load_flags
|= FT_LOAD_TARGET_MONO
;
1460 load_flags
|= FT_LOAD_MONOCHROME
;
1463 else if (bits_per_pixel
!= 8)
1464 /* We don't support such a rendering. */
1467 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1469 bitmap
->bits_per_pixel
1470 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1471 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1472 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1473 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1475 if (bitmap
->bits_per_pixel
< 0)
1476 /* We don't support that kind of pixel mode. */
1478 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1479 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1480 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1481 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1482 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1483 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1484 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1485 bitmap
->extra
= NULL
;
1491 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1494 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1495 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1497 if (ftfont_info
->ft_size
!= ft_face
->size
)
1498 FT_Activate_Size (ftfont_info
->ft_size
);
1499 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1501 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1503 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1505 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1506 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1513 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1515 Lisp_Object scripts
, langsyses
, features
, sym
;
1518 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1520 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1522 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1524 OTF_LangSys
*otf_langsys
;
1527 otf_langsys
= otf_script
->LangSys
+ j
;
1528 else if (otf_script
->DefaultLangSysOffset
)
1529 otf_langsys
= &otf_script
->DefaultLangSys
;
1533 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1535 l
= otf_langsys
->FeatureIndex
[k
];
1536 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1538 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1539 features
= Fcons (sym
, features
);
1542 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1545 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1548 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1549 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1557 ftfont_otf_capability (struct font
*font
)
1559 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1560 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1561 Lisp_Object gsub_gpos
;
1565 gsub_gpos
= Fcons (Qnil
, Qnil
);
1566 if (OTF_get_table (otf
, "GSUB") == 0
1567 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1568 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1569 if (OTF_get_table (otf
, "GPOS") == 0
1570 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1571 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1575 #ifdef HAVE_M17N_FLT
1577 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1578 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1579 /* We can use the new feature of libotf and m17n-flt to handle the
1580 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1581 some Agian scripts. */
1582 #define M17N_FLT_USE_NEW_FEATURE
1595 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1598 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1599 FT_Face ft_face
= flt_font_ft
->ft_face
;
1602 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1605 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1607 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1613 /* Operators for 26.6 fixed fractional pixel format */
1615 #define FLOOR(x) ((x) & -64)
1616 #define CEIL(x) (((x)+63) & -64)
1617 #define ROUND(x) (((x)+32) & -64)
1620 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1623 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1624 FT_Face ft_face
= flt_font_ft
->ft_face
;
1627 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1630 if (g
->code
!= FONT_INVALID_CODE
)
1632 FT_Glyph_Metrics
*m
;
1634 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1636 m
= &ft_face
->glyph
->metrics
;
1637 if (flt_font_ft
->matrix
)
1642 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1643 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1644 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1645 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1646 for (i
= 0; i
< 4; i
++)
1647 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1648 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1649 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1650 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1651 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1655 g
->lbearing
= FLOOR (m
->horiBearingX
);
1656 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1657 g
->ascent
= CEIL (m
->horiBearingY
);
1658 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1660 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1665 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1666 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1667 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1676 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1678 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1680 #define FEATURE_ANY(IDX) \
1681 (spec->features[IDX] \
1682 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1684 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1685 OTF
*otf
= flt_font_ft
->otf
;
1690 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1691 /* Return true iff any of GSUB or GPOS support the script (and
1694 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1696 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1699 for (i
= 0; i
< 2; i
++)
1700 if (! FEATURE_ANY (i
))
1702 if (FEATURE_NONE (i
))
1705 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1710 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1713 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1719 for (n
= 1; spec
->features
[i
][n
]; n
++);
1720 tags
= alloca (sizeof (OTF_Tag
) * n
);
1721 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1723 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1726 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1728 tags
[n
] = spec
->features
[i
][n
];
1730 #ifdef M17N_FLT_USE_NEW_FEATURE
1731 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1732 tags
, n
- negative
) != 1)
1734 #else /* not M17N_FLT_USE_NEW_FEATURE */
1735 if (n
- negative
> 0
1736 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1737 tags
, n
- negative
) != 1)
1739 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1746 #define DEVICE_DELTA(table, size) \
1747 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1748 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1752 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1753 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1755 if (anchor
->AnchorFormat
== 2)
1757 FT_Outline
*outline
;
1758 int ap
= anchor
->f
.f1
.AnchorPoint
;
1760 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1761 outline
= &ft_face
->glyph
->outline
;
1762 if (ap
< outline
->n_points
)
1764 *x
= outline
->points
[ap
].x
<< 6;
1765 *y
= outline
->points
[ap
].y
<< 6;
1768 else if (anchor
->AnchorFormat
== 3)
1770 if (anchor
->f
.f2
.XDeviceTable
.offset
1771 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1772 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1773 if (anchor
->f
.f2
.YDeviceTable
.offset
1774 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1775 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1779 static OTF_GlyphString otf_gstring
;
1782 setup_otf_gstring (int size
)
1784 if (otf_gstring
.size
< size
)
1786 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1787 size
, sizeof (OTF_Glyph
));
1788 otf_gstring
.size
= size
;
1790 otf_gstring
.used
= size
;
1791 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1794 #ifdef M17N_FLT_USE_NEW_FEATURE
1796 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1797 #define PACK_OTF_TAG(TAG) \
1798 ((((TAG) & 0x7F000000) >> 3) \
1799 | (((TAG) & 0x7F0000) >> 2) \
1800 | (((TAG) & 0x7F00) >> 1) \
1803 /* Assuming that FONT is an OpenType font, apply OpenType features
1804 specified in SPEC on glyphs between FROM and TO of IN, and record
1805 the lastly applied feature in each glyph of IN. If OUT is not
1806 NULL, append the resulting glyphs to OUT while storing glyph
1807 position adjustment information in ADJUSTMENT. */
1810 ftfont_drive_otf (MFLTFont
*font
,
1812 MFLTGlyphString
*in
,
1815 MFLTGlyphString
*out
,
1816 MFLTGlyphAdjustment
*adjustment
)
1818 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1819 FT_Face ft_face
= flt_font_ft
->ft_face
;
1820 OTF
*otf
= flt_font_ft
->otf
;
1821 int len
= to
- from
;
1824 char script
[5], *langsys
= NULL
;
1825 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1826 OTF_Feature
*features
;
1830 OTF_tag_name (spec
->script
, script
);
1833 langsys
= alloca (5);
1834 OTF_tag_name (spec
->langsys
, langsys
);
1836 for (i
= 0; i
< 2; i
++)
1840 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1842 for (j
= 0; spec
->features
[i
][j
]; j
++);
1844 p
= gsub_features
= alloca (6 * j
);
1846 p
= gpos_features
= alloca (6 * j
);
1847 for (j
= 0; spec
->features
[i
][j
]; j
++)
1849 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1850 *p
++ = '*', *p
++ = ',';
1853 OTF_tag_name (spec
->features
[i
][j
], p
);
1862 setup_otf_gstring (len
);
1863 for (i
= 0; i
< len
; i
++)
1865 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
& 0x11FFFF;
1866 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1869 OTF_drive_gdef (otf
, &otf_gstring
);
1870 gidx
= out
? out
->used
: from
;
1872 if (gsub_features
&& out
)
1874 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1877 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1879 features
= otf
->gsub
->FeatureList
.Feature
;
1880 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1883 int min_from
, max_to
;
1884 int feature_idx
= otfg
->positioning_type
>> 4;
1886 g
= out
->glyphs
+ out
->used
;
1887 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1888 if (g
->code
!= otfg
->glyph_id
)
1891 g
->code
= otfg
->glyph_id
;
1897 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1899 /* OTFG substitutes multiple glyphs in IN. */
1900 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1901 j
<= from
+ otfg
->f
.index
.to
; j
++)
1903 if (min_from
> in
->glyphs
[j
].from
)
1904 min_from
= in
->glyphs
[j
].from
;
1905 if (max_to
< in
->glyphs
[j
].to
)
1906 max_to
= in
->glyphs
[j
].to
;
1913 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1914 tag
= PACK_OTF_TAG (tag
);
1915 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1917 for (i
++, otfg
++; (i
< otf_gstring
.used
1918 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1921 g
= out
->glyphs
+ out
->used
;
1922 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1923 if (g
->code
!= otfg
->glyph_id
)
1926 g
->code
= otfg
->glyph_id
;
1929 feature_idx
= otfg
->positioning_type
>> 4;
1932 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1933 tag
= PACK_OTF_TAG (tag
);
1934 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1940 else if (gsub_features
)
1942 /* Just for checking which features will be applied. */
1943 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1946 features
= otf
->gsub
->FeatureList
.Feature
;
1947 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1950 int feature_idx
= otfg
->positioning_type
>> 4;
1954 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1955 tag
= PACK_OTF_TAG (tag
);
1956 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1958 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1959 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1966 if (out
->allocated
< out
->used
+ len
)
1968 for (i
= 0; i
< len
; i
++)
1969 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1972 if (gpos_features
&& out
)
1974 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1975 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1977 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1980 features
= otf
->gpos
->FeatureList
.Feature
;
1981 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1982 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1983 x_scale
= ft_face
->size
->metrics
.x_scale
;
1984 y_scale
= ft_face
->size
->metrics
.y_scale
;
1986 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1987 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1990 int feature_idx
= otfg
->positioning_type
>> 4;
1994 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1995 tag
= PACK_OTF_TAG (tag
);
1996 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1999 if (! otfg
->glyph_id
)
2001 switch (otfg
->positioning_type
& 0xF)
2005 case 1: /* Single */
2008 int format
= otfg
->f
.f1
.format
;
2010 if (format
& OTF_XPlacement
)
2012 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2013 if (format
& OTF_XPlaDevice
)
2015 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2016 if (format
& OTF_YPlacement
)
2018 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2019 if (format
& OTF_YPlaDevice
)
2021 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2022 if (format
& OTF_XAdvance
)
2024 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2025 if (format
& OTF_XAdvDevice
)
2027 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2028 if (format
& OTF_YAdvance
)
2030 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2031 if (format
& OTF_YAdvDevice
)
2033 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2034 adjustment
[i
].set
= 1;
2037 case 3: /* Cursive */
2038 /* Not yet supported. */
2040 case 4: /* Mark-to-Base */
2041 case 5: /* Mark-to-Ligature */
2045 goto label_adjust_anchor
;
2046 default: /* i.e. case 6 Mark-to-Mark */
2051 label_adjust_anchor
:
2053 int base_x
, base_y
, mark_x
, mark_y
;
2054 int this_from
, this_to
;
2056 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2057 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2058 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2059 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2061 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2062 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2063 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2064 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2065 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2066 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2067 adjustment
[i
].xoff
= (base_x
- mark_x
);
2068 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2069 adjustment
[i
].back
= (g
- prev
);
2070 adjustment
[i
].xadv
= 0;
2071 adjustment
[i
].advance_is_absolute
= 1;
2072 adjustment
[i
].set
= 1;
2073 this_from
= g
->from
;
2075 for (j
= 0; prev
+ j
< g
; j
++)
2077 if (this_from
> prev
[j
].from
)
2078 this_from
= prev
[j
].from
;
2079 if (this_to
< prev
[j
].to
)
2080 this_to
= prev
[j
].to
;
2082 for (; prev
<= g
; prev
++)
2084 prev
->from
= this_from
;
2089 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2091 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2097 else if (gpos_features
)
2099 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2102 features
= otf
->gpos
->FeatureList
.Feature
;
2103 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2105 if (otfg
->positioning_type
& 0xF)
2107 int feature_idx
= otfg
->positioning_type
>> 4;
2111 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2112 tag
= PACK_OTF_TAG (tag
);
2113 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2115 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2116 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2126 if (out
->allocated
< out
->used
+ len
)
2128 font
->get_metrics (font
, in
, from
, to
);
2129 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2130 sizeof (MFLTGlyph
) * len
);
2136 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2137 MFLTGlyphString
*in
, int from
, int to
)
2139 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2142 #else /* not M17N_FLT_USE_NEW_FEATURE */
2145 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2147 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2149 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2150 FT_Face ft_face
= flt_font_ft
->ft_face
;
2151 OTF
*otf
= flt_font_ft
->otf
;
2152 int len
= to
- from
;
2155 char script
[5], *langsys
= NULL
;
2156 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2160 OTF_tag_name (spec
->script
, script
);
2163 langsys
= alloca (5);
2164 OTF_tag_name (spec
->langsys
, langsys
);
2166 for (i
= 0; i
< 2; i
++)
2170 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2172 for (j
= 0; spec
->features
[i
][j
]; j
++);
2174 p
= gsub_features
= alloca (6 * j
);
2176 p
= gpos_features
= alloca (6 * j
);
2177 for (j
= 0; spec
->features
[i
][j
]; j
++)
2179 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2180 *p
++ = '*', *p
++ = ',';
2183 OTF_tag_name (spec
->features
[i
][j
], p
);
2192 setup_otf_gstring (len
);
2193 for (i
= 0; i
< len
; i
++)
2195 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2196 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2199 OTF_drive_gdef (otf
, &otf_gstring
);
2204 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2207 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2209 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2212 int min_from
, max_to
;
2215 g
= out
->glyphs
+ out
->used
;
2216 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2217 if (g
->code
!= otfg
->glyph_id
)
2220 g
->code
= otfg
->glyph_id
;
2226 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2228 /* OTFG substitutes multiple glyphs in IN. */
2229 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2230 j
<= from
+ otfg
->f
.index
.to
; j
++)
2232 if (min_from
> in
->glyphs
[j
].from
)
2233 min_from
= in
->glyphs
[j
].from
;
2234 if (max_to
< in
->glyphs
[j
].to
)
2235 max_to
= in
->glyphs
[j
].to
;
2240 for (i
++, otfg
++; (i
< otf_gstring
.used
2241 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2244 g
= out
->glyphs
+ out
->used
;
2245 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2246 if (g
->code
!= otfg
->glyph_id
)
2249 g
->code
= otfg
->glyph_id
;
2258 if (out
->allocated
< out
->used
+ len
)
2260 for (i
= 0; i
< len
; i
++)
2261 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2266 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2267 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2269 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2273 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2274 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2275 x_scale
= ft_face
->size
->metrics
.x_scale
;
2276 y_scale
= ft_face
->size
->metrics
.y_scale
;
2278 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2279 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2283 if (! otfg
->glyph_id
)
2285 switch (otfg
->positioning_type
)
2289 case 1: /* Single */
2292 int format
= otfg
->f
.f1
.format
;
2294 if (format
& OTF_XPlacement
)
2296 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2297 if (format
& OTF_XPlaDevice
)
2299 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2300 if (format
& OTF_YPlacement
)
2302 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2303 if (format
& OTF_YPlaDevice
)
2305 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2306 if (format
& OTF_XAdvance
)
2308 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2309 if (format
& OTF_XAdvDevice
)
2311 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2312 if (format
& OTF_YAdvance
)
2314 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2315 if (format
& OTF_YAdvDevice
)
2317 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2318 adjustment
[i
].set
= 1;
2321 case 3: /* Cursive */
2322 /* Not yet supported. */
2324 case 4: /* Mark-to-Base */
2325 case 5: /* Mark-to-Ligature */
2329 goto label_adjust_anchor
;
2330 default: /* i.e. case 6 Mark-to-Mark */
2335 label_adjust_anchor
:
2337 int base_x
, base_y
, mark_x
, mark_y
;
2338 int this_from
, this_to
;
2340 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2341 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2342 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2343 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2345 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2346 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2347 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2348 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2349 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2350 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2351 adjustment
[i
].xoff
= (base_x
- mark_x
);
2352 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2353 adjustment
[i
].back
= (g
- prev
);
2354 adjustment
[i
].xadv
= 0;
2355 adjustment
[i
].advance_is_absolute
= 1;
2356 adjustment
[i
].set
= 1;
2357 this_from
= g
->from
;
2359 for (j
= 0; prev
+ j
< g
; j
++)
2361 if (this_from
> prev
[j
].from
)
2362 this_from
= prev
[j
].from
;
2363 if (this_to
< prev
[j
].to
)
2364 this_to
= prev
[j
].to
;
2366 for (; prev
<= g
; prev
++)
2368 prev
->from
= this_from
;
2373 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2375 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2384 if (out
->allocated
< out
->used
+ len
)
2386 font
->get_metrics (font
, in
, from
, to
);
2387 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2388 sizeof (MFLTGlyph
) * len
);
2393 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2395 static MFLTGlyphString gstring
;
2397 static bool m17n_flt_initialized
;
2400 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2401 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2403 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2405 struct MFLTFontFT flt_font_ft
;
2407 bool with_variation_selector
= 0;
2409 if (! m17n_flt_initialized
)
2412 #ifdef M17N_FLT_USE_NEW_FEATURE
2413 mflt_enable_new_feature
= 1;
2414 mflt_try_otf
= ftfont_try_otf
;
2415 #endif /* M17N_FLT_USE_NEW_FEATURE */
2416 m17n_flt_initialized
= 1;
2419 for (i
= 0; i
< len
; i
++)
2421 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2426 c
= LGLYPH_CHAR (g
);
2427 if (CHAR_VARIATION_SELECTOR_P (c
))
2428 with_variation_selector
= 1;
2432 lint_assume (len
<= STRING_BYTES_BOUND
);
2434 if (with_variation_selector
)
2436 setup_otf_gstring (len
);
2437 for (i
= 0; i
< len
; i
++)
2439 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2441 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2442 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2443 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2445 OTF_drive_cmap (otf
, &otf_gstring
);
2446 for (i
= 0; i
< otf_gstring
.used
; i
++)
2448 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2449 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2450 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2452 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2453 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2454 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2456 if (len
> otf_gstring
.used
)
2458 len
= otf_gstring
.used
;
2459 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2463 if (INT_MAX
/ 2 < len
)
2464 memory_full (SIZE_MAX
);
2466 if (gstring
.allocated
== 0)
2468 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2469 gstring
.glyphs
= xnmalloc (len
* 2, sizeof *gstring
.glyphs
);
2470 gstring
.allocated
= len
* 2;
2472 else if (gstring
.allocated
< len
* 2)
2474 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2475 sizeof *gstring
.glyphs
);
2476 gstring
.allocated
= len
* 2;
2478 memset (gstring
.glyphs
, 0, len
* sizeof *gstring
.glyphs
);
2479 for (i
= 0; i
< len
; i
++)
2481 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2483 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2484 if (with_variation_selector
)
2486 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2487 gstring
.glyphs
[i
].encoded
= 1;
2495 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2498 flt_font_ft
.flt_font
.family
= Mnil
;
2500 flt_font_ft
.flt_font
.family
2501 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2503 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2504 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2505 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2506 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2507 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2508 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2509 flt_font_ft
.flt_font
.internal
= NULL
;
2510 flt_font_ft
.font
= font
;
2511 flt_font_ft
.ft_face
= ft_face
;
2512 flt_font_ft
.otf
= otf
;
2513 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2515 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2516 /* A little bit ad hoc. Perhaps, shaper must get script and
2517 language information, and select a proper flt for them
2519 flt
= mflt_get (msymbol ("combining"));
2520 for (i
= 0; i
< 3; i
++)
2522 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2525 if (INT_MAX
/ 2 < gstring
.allocated
)
2526 memory_full (SIZE_MAX
);
2527 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2528 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2529 gstring
.allocated
*= 2;
2531 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2533 for (i
= 0; i
< gstring
.used
; i
++)
2535 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2537 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2538 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2541 for (i
= 0; i
< gstring
.used
; i
++)
2543 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2544 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2548 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2549 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2551 LGLYPH_SET_FROM (lglyph
, g
->from
);
2552 LGLYPH_SET_TO (lglyph
, g
->to
);
2553 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2554 LGLYPH_SET_CODE (lglyph
, g
->code
);
2555 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2556 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2557 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2558 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2559 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2564 vec
= Fmake_vector (make_number (3), Qnil
);
2565 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2566 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2567 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2568 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2571 return make_number (i
);
2575 ftfont_shape (Lisp_Object lgstring
)
2578 struct ftfont_info
*ftfont_info
;
2581 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2582 ftfont_info
= (struct ftfont_info
*) font
;
2583 otf
= ftfont_get_otf (ftfont_info
);
2585 return make_number (0);
2586 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2587 &ftfont_info
->matrix
);
2590 #endif /* HAVE_M17N_FLT */
2592 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2595 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2597 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2598 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2602 return OTF_get_variation_glyphs (otf
, c
, variations
);
2605 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2606 #endif /* HAVE_LIBOTF */
2609 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2613 #ifdef FC_FONTFORMAT
2616 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2618 if (strcmp ((char *) str
, "TrueType") == 0)
2619 return intern ("truetype");
2620 if (strcmp ((char *) str
, "Type 1") == 0)
2621 return intern ("type1");
2622 if (strcmp ((char *) str
, "PCF") == 0)
2623 return intern ("pcf");
2624 if (strcmp ((char *) str
, "BDF") == 0)
2625 return intern ("bdf");
2627 #endif /* FC_FONTFORMAT */
2628 if (STRINGP (filename
))
2630 int len
= SBYTES (filename
);
2634 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2635 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2636 return intern ("truetype");
2637 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2638 return intern ("type1");
2639 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2640 return intern ("pcf");
2641 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2642 return intern ("bdf");
2645 return intern ("unknown");
2648 static const char *const ftfont_booleans
[] = {
2661 static const char *const ftfont_non_booleans
[] = {
2693 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2695 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2700 syms_of_ftfont (void)
2702 DEFSYM (Qfreetype
, "freetype");
2703 DEFSYM (Qmonospace
, "monospace");
2704 DEFSYM (Qsans_serif
, "sans-serif");
2705 DEFSYM (Qserif
, "serif");
2706 DEFSYM (Qmono
, "mono");
2707 DEFSYM (Qsans
, "sans");
2708 DEFSYM (Qsans__serif
, "sans serif");
2710 staticpro (&freetype_font_cache
);
2711 freetype_font_cache
= Fcons (Qt
, Qnil
);
2713 staticpro (&ftfont_generic_family_list
);
2714 ftfont_generic_family_list
2715 = Fcons (Fcons (Qmonospace
, Qt
),
2716 Fcons (Fcons (Qsans_serif
, Qt
),
2717 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2719 staticpro (&ft_face_cache
);
2720 ft_face_cache
= Qnil
;
2722 ftfont_driver
.type
= Qfreetype
;
2723 register_font_driver (&ftfont_driver
, NULL
);