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 int 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 int 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 (make_unibyte_string (file
, strlen (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 xassert (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 (struct ftfont_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
=
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
, /* get_bitmap */
547 NULL
, /* free_bitmap */
548 NULL
, /* get_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 (regexp
, fc_charset_table
[i
].name
) >= 0)
603 if (! fc_charset_table
[i
].name
)
605 if (! fc_charset_table
[i
].fc_charset
)
607 FcCharSet
*charset
= FcCharSetCreate ();
608 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
612 for (j
= 0; uniquifier
[j
]; j
++)
613 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
615 FcCharSetDestroy (charset
);
618 fc_charset_table
[i
].fc_charset
= charset
;
626 unsigned int script_tag
, langsys_tag
;
628 unsigned int *features
[2];
631 #define OTF_SYM_TAG(SYM, TAG) \
633 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
634 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
637 #define OTF_TAG_STR(TAG, P) \
639 (P)[0] = (char) (TAG >> 24); \
640 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
641 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
642 (P)[3] = (char) (TAG & 0xFF); \
647 #define OTF_TAG_SYM(SYM, TAG) \
651 OTF_TAG_STR (TAG, str); \
652 (SYM) = font_intern_prop (str, 4, 1); \
657 static struct OpenTypeSpec
*
658 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
660 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
666 spec
->script
= XCAR (otf_spec
);
667 if (! NILP (spec
->script
))
669 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
670 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
671 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
672 spec
->script
= XCDR (val
);
677 spec
->script_tag
= 0x44464C54; /* "DFLT" */
678 otf_spec
= XCDR (otf_spec
);
679 spec
->langsys_tag
= 0;
680 if (! NILP (otf_spec
))
682 val
= XCAR (otf_spec
);
684 OTF_SYM_TAG (val
, spec
->langsys_tag
);
685 otf_spec
= XCDR (otf_spec
);
687 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
688 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
692 val
= XCAR (otf_spec
);
697 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
699 : malloc (sizeof (int) * XINT (len
)));
700 if (! spec
->features
[i
])
702 if (i
> 0 && spec
->features
[0])
703 free (spec
->features
[0]);
707 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
709 if (NILP (XCAR (val
)))
715 OTF_SYM_TAG (XCAR (val
), tag
);
716 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
719 spec
->nfeatures
[i
] = j
;
725 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
727 Lisp_Object tmp
, extra
;
728 FcPattern
*pattern
= NULL
;
729 FcCharSet
*charset
= NULL
;
730 FcLangSet
*langset
= NULL
;
734 Lisp_Object script
= Qnil
;
735 Lisp_Object registry
;
738 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
740 /* Fontconfig doesn't support reverse-italic/oblique. */
743 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
744 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
745 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
746 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
749 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
751 || EQ (registry
, Qascii_0
)
752 || EQ (registry
, Qiso10646_1
)
753 || EQ (registry
, Qunicode_bmp
))
759 fc_charset_idx
= ftfont_get_charset (registry
);
760 if (fc_charset_idx
< 0)
762 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
763 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
764 lang
= (FcChar8
*) *langname
;
767 langset
= FcLangSetCreate ();
770 FcLangSetAdd (langset
, lang
);
775 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
776 CONSP (extra
); extra
= XCDR (extra
))
778 Lisp_Object key
, val
;
780 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
786 else if (EQ (key
, QClang
))
789 langset
= FcLangSetCreate ();
794 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
798 for (; CONSP (val
); val
= XCDR (val
))
799 if (SYMBOLP (XCAR (val
))
800 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
803 else if (EQ (key
, QCotf
))
807 *otspec
= ftfont_get_open_type_spec (val
);
810 strcat (otlayout
, "otlayout:");
811 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
812 script
= (*otspec
)->script
;
815 else if (EQ (key
, QCscript
))
817 else if (EQ (key
, QCscalable
))
818 scalable
= ! NILP (val
);
821 if (! NILP (script
) && ! charset
)
823 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
825 if (CONSP (chars
) && CONSP (CDR (chars
)))
827 charset
= FcCharSetCreate ();
830 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
831 if (CHARACTERP (XCAR (chars
))
832 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
837 pattern
= FcPatternCreate ();
840 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
842 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
844 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
846 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
849 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
852 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
855 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
858 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
864 /* We come here because of unexpected error in fontconfig API call
865 (usually insufficient memory). */
868 FcPatternDestroy (pattern
);
873 if ((*otspec
)->nfeatures
[0] > 0)
874 free ((*otspec
)->features
[0]);
875 if ((*otspec
)->nfeatures
[1] > 0)
876 free ((*otspec
)->features
[1]);
882 if (langset
) FcLangSetDestroy (langset
);
883 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
888 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
890 Lisp_Object val
= Qnil
, family
, adstyle
;
893 FcFontSet
*fontset
= NULL
;
894 FcObjectSet
*objset
= NULL
;
896 Lisp_Object chars
= Qnil
;
897 char otlayout
[15]; /* For "otlayout:XXXX" */
898 struct OpenTypeSpec
*otspec
= NULL
;
900 const char *langname
= NULL
;
902 if (! fc_initialized
)
908 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
911 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
913 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
916 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
917 if (CONSP (val
) && VECTORP (XCDR (val
)))
922 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
923 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
924 family
= AREF (spec
, FONT_FAMILY_INDEX
);
927 Lisp_Object resolved
;
929 resolved
= ftfont_resolve_generic_family (family
, pattern
);
930 if (! NILP (resolved
))
932 FcPatternDel (pattern
, FC_FAMILY
);
933 if (! FcPatternAddString (pattern
, FC_FAMILY
,
934 SYMBOL_FcChar8 (resolved
)))
938 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
939 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
941 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
942 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
943 FC_STYLE
, FC_FILE
, FC_INDEX
,
946 #endif /* FC_CAPABILITY */
954 FcObjectSetAdd (objset
, FC_CHARSET
);
956 fontset
= FcFontList (NULL
, pattern
, objset
);
957 if (! fontset
|| fontset
->nfont
== 0)
960 /* Need fix because this finds any fonts. */
961 if (fontset
->nfont
== 0 && ! NILP (family
))
963 /* Try matching with configuration. For instance, the
964 configuration may specify "Nimbus Mono L" as an alias of
966 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
967 SYMBOL_FcChar8 (family
), NULL
);
970 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
973 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
976 FcPatternDel (pattern
, FC_FAMILY
);
977 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
978 FcFontSetDestroy (fontset
);
979 fontset
= FcFontList (NULL
, pattern
, objset
);
980 if (fontset
&& fontset
->nfont
> 0)
986 for (i
= 0; i
< fontset
->nfont
; i
++)
994 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
1000 #ifdef FC_CAPABILITY
1005 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
1007 || ! strstr ((char *) this, otlayout
))
1010 #endif /* FC_CAPABILITY */
1017 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1020 otf
= OTF_open ((char *) file
);
1023 if (OTF_check_features (otf
, 1,
1024 otspec
->script_tag
, otspec
->langsys_tag
,
1025 otspec
->features
[0],
1026 otspec
->nfeatures
[0]) != 1
1027 || OTF_check_features (otf
, 0,
1028 otspec
->script_tag
, otspec
->langsys_tag
,
1029 otspec
->features
[1],
1030 otspec
->nfeatures
[1]) != 1)
1033 #endif /* HAVE_LIBOTF */
1034 if (VECTORP (chars
))
1038 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1041 for (j
= 0; j
< ASIZE (chars
); j
++)
1042 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1043 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1045 if (j
== ASIZE (chars
))
1048 if (! NILP (adstyle
) || langname
)
1050 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1052 if (! NILP (adstyle
)
1053 && (NILP (this_adstyle
)
1054 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1055 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1058 && ! NILP (this_adstyle
)
1059 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1062 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1063 AREF (spec
, FONT_EXTRA_INDEX
));
1064 if (! NILP (entity
))
1065 val
= Fcons (entity
, val
);
1067 val
= Fnreverse (val
);
1071 /* We come here because of unexpected error in fontconfig API call
1072 (usually insufficient memory). */
1076 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1077 if (objset
) FcObjectSetDestroy (objset
);
1078 if (fontset
) FcFontSetDestroy (fontset
);
1079 if (pattern
) FcPatternDestroy (pattern
);
1084 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1086 Lisp_Object entity
= Qnil
;
1087 FcPattern
*pattern
, *match
= NULL
;
1089 char otlayout
[15]; /* For "otlayout:XXXX" */
1090 struct OpenTypeSpec
*otspec
= NULL
;
1091 const char *langname
= NULL
;
1093 if (! fc_initialized
)
1099 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1103 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1107 value
.type
= FcTypeDouble
;
1108 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1109 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1111 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1113 FcDefaultSubstitute (pattern
);
1114 match
= FcFontMatch (NULL
, pattern
, &result
);
1117 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1118 FcPatternDestroy (match
);
1119 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1120 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1121 ftfont_generic_family_list
))
1122 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1123 AREF (entity
, FONT_FAMILY_INDEX
))))
1127 FcPatternDestroy (pattern
);
1129 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1134 ftfont_list_family (Lisp_Object frame
)
1136 Lisp_Object list
= Qnil
;
1137 FcPattern
*pattern
= NULL
;
1138 FcFontSet
*fontset
= NULL
;
1139 FcObjectSet
*objset
= NULL
;
1142 if (! fc_initialized
)
1148 pattern
= FcPatternCreate ();
1151 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1154 fontset
= FcFontList (NULL
, pattern
, objset
);
1158 for (i
= 0; i
< fontset
->nfont
; i
++)
1160 FcPattern
*pat
= fontset
->fonts
[i
];
1163 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1164 list
= Fcons (intern ((char *) str
), list
);
1168 if (objset
) FcObjectSetDestroy (objset
);
1169 if (fontset
) FcFontSetDestroy (fontset
);
1170 if (pattern
) FcPatternDestroy (pattern
);
1177 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1179 struct ftfont_info
*ftfont_info
;
1181 struct ftfont_cache_data
*cache_data
;
1185 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1192 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1196 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1199 filename
= XCAR (val
);
1202 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1203 ft_face
= cache_data
->ft_face
;
1204 if (XSAVE_VALUE (val
)->integer
> 0)
1206 /* FT_Face in this cache is already used by the different size. */
1207 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1209 if (FT_Activate_Size (ft_size
) != 0)
1211 FT_Done_Size (ft_size
);
1215 XSAVE_VALUE (val
)->integer
++;
1216 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1219 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1221 if (XSAVE_VALUE (val
)->integer
== 0)
1222 FT_Done_Face (ft_face
);
1226 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1227 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1228 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1230 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1231 len
= font_unparse_fcname (entity
, size
, name
, 256);
1233 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1235 ASET (font_object
, FONT_FULLNAME_INDEX
,
1236 AREF (font_object
, FONT_NAME_INDEX
));
1237 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1238 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1239 font
= XFONT_OBJECT (font_object
);
1240 ftfont_info
= (struct ftfont_info
*) font
;
1241 ftfont_info
->ft_size
= ft_face
->size
;
1242 ftfont_info
->index
= XINT (idx
);
1244 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1245 ftfont_info
->otf
= NULL
;
1246 #endif /* HAVE_LIBOTF */
1247 /* This means that there's no need of transformation. */
1248 ftfont_info
->matrix
.xx
= 0;
1249 font
->pixel_size
= size
;
1250 font
->driver
= &ftfont_driver
;
1251 font
->encoding_charset
= font
->repertory_charset
= -1;
1253 upEM
= ft_face
->units_per_EM
;
1254 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1255 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1258 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1259 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1260 font
->height
= ft_face
->height
* size
/ upEM
;
1264 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1265 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1266 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1268 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1269 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1271 spacing
= FC_PROPORTIONAL
;
1272 if (spacing
!= FC_PROPORTIONAL
1274 && spacing
!= FC_DUAL
1275 #endif /* FC_DUAL */
1277 font
->min_width
= font
->average_width
= font
->space_width
1278 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1279 : ft_face
->size
->metrics
.max_advance
>> 6);
1284 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1285 for (i
= 32, n
= 0; i
< 127; i
++)
1286 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1288 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1291 && (! font
->min_width
|| font
->min_width
> this_width
))
1292 font
->min_width
= this_width
;
1294 font
->space_width
= this_width
;
1295 font
->average_width
+= this_width
;
1299 font
->average_width
/= n
;
1302 font
->baseline_offset
= 0;
1303 font
->relative_compose
= 0;
1304 font
->default_ascent
= 0;
1305 font
->vertical_centering
= 0;
1308 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1309 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1313 font
->underline_position
= -1;
1314 font
->underline_thickness
= 0;
1321 ftfont_close (FRAME_PTR f
, struct font
*font
)
1323 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1324 Lisp_Object val
, cache
;
1326 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1327 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1328 xassert (CONSP (cache
));
1330 (XSAVE_VALUE (val
)->integer
)--;
1331 if (XSAVE_VALUE (val
)->integer
== 0)
1333 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1335 FT_Done_Face (cache_data
->ft_face
);
1337 if (ftfont_info
->otf
)
1338 OTF_close (ftfont_info
->otf
);
1340 cache_data
->ft_face
= NULL
;
1343 FT_Done_Size (ftfont_info
->ft_size
);
1347 ftfont_has_char (Lisp_Object font
, int c
)
1349 struct charset
*cs
= NULL
;
1351 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1352 && charset_jisx0208
>= 0)
1353 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1354 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1355 && charset_ksc5601
>= 0)
1356 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1358 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1360 if (FONT_ENTITY_P (font
))
1362 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1364 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1368 struct ftfont_info
*ftfont_info
;
1370 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1371 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1377 ftfont_encode_char (struct font
*font
, int c
)
1379 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1380 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1381 FT_ULong charcode
= c
;
1382 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1384 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1388 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1390 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1391 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1395 if (ftfont_info
->ft_size
!= ft_face
->size
)
1396 FT_Activate_Size (ftfont_info
->ft_size
);
1398 memset (metrics
, 0, sizeof (struct font_metrics
));
1399 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1401 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1403 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1409 metrics
->lbearing
= m
->horiBearingX
>> 6;
1410 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1411 metrics
->ascent
= m
->horiBearingY
>> 6;
1412 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1418 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1419 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1420 if (metrics
->rbearing
1421 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1423 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1424 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1425 metrics
->ascent
= m
->horiBearingY
>> 6;
1426 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1427 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1429 width
+= m
->horiAdvance
>> 6;
1433 width
+= font
->space_width
;
1437 metrics
->width
= width
;
1443 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1445 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1446 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1447 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1449 if (ftfont_info
->ft_size
!= ft_face
->size
)
1450 FT_Activate_Size (ftfont_info
->ft_size
);
1451 if (bits_per_pixel
== 1)
1453 #ifdef FT_LOAD_TARGET_MONO
1454 load_flags
|= FT_LOAD_TARGET_MONO
;
1456 load_flags
|= FT_LOAD_MONOCHROME
;
1459 else if (bits_per_pixel
!= 8)
1460 /* We don't support such a rendering. */
1463 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1465 bitmap
->bits_per_pixel
1466 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1467 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1468 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1469 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1471 if (bitmap
->bits_per_pixel
< 0)
1472 /* We don't support that kind of pixel mode. */
1474 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1475 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1476 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1477 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1478 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1479 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1480 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1481 bitmap
->extra
= NULL
;
1487 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1490 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1491 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1493 if (ftfont_info
->ft_size
!= ft_face
->size
)
1494 FT_Activate_Size (ftfont_info
->ft_size
);
1495 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1497 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1499 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1501 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1502 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1509 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1511 Lisp_Object scripts
, langsyses
, features
, sym
;
1514 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1516 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1518 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1520 OTF_LangSys
*otf_langsys
;
1523 otf_langsys
= otf_script
->LangSys
+ j
;
1524 else if (otf_script
->DefaultLangSysOffset
)
1525 otf_langsys
= &otf_script
->DefaultLangSys
;
1529 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1531 l
= otf_langsys
->FeatureIndex
[k
];
1532 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1534 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1535 features
= Fcons (sym
, features
);
1538 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1541 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1544 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1545 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1553 ftfont_otf_capability (struct font
*font
)
1555 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1556 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1557 Lisp_Object gsub_gpos
;
1561 gsub_gpos
= Fcons (Qnil
, Qnil
);
1562 if (OTF_get_table (otf
, "GSUB") == 0
1563 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1564 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1565 if (OTF_get_table (otf
, "GPOS") == 0
1566 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1567 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1571 #ifdef HAVE_M17N_FLT
1573 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1574 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1575 /* We can use the new feature of libotf and m17n-flt to handle the
1576 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1577 some Agian scripts. */
1578 #define M17N_FLT_USE_NEW_FEATURE
1591 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1594 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1595 FT_Face ft_face
= flt_font_ft
->ft_face
;
1598 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1601 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1603 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1609 /* Operators for 26.6 fixed fractional pixel format */
1611 #define FLOOR(x) ((x) & -64)
1612 #define CEIL(x) (((x)+63) & -64)
1613 #define ROUND(x) (((x)+32) & -64)
1616 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1619 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1620 FT_Face ft_face
= flt_font_ft
->ft_face
;
1623 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1626 if (g
->code
!= FONT_INVALID_CODE
)
1628 FT_Glyph_Metrics
*m
;
1630 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1632 m
= &ft_face
->glyph
->metrics
;
1633 if (flt_font_ft
->matrix
)
1638 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1639 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1640 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1641 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1642 for (i
= 0; i
< 4; i
++)
1643 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1644 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1645 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1646 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1647 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1651 g
->lbearing
= FLOOR (m
->horiBearingX
);
1652 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1653 g
->ascent
= CEIL (m
->horiBearingY
);
1654 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1656 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1661 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1662 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1663 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1672 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1674 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1676 #define FEATURE_ANY(IDX) \
1677 (spec->features[IDX] \
1678 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1680 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1681 OTF
*otf
= flt_font_ft
->otf
;
1685 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1686 /* Return 1 iff any of GSUB or GPOS support the script (and language). */
1688 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1690 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1693 for (i
= 0; i
< 2; i
++)
1694 if (! FEATURE_ANY (i
))
1696 if (FEATURE_NONE (i
))
1699 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1704 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1707 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1713 for (n
= 1; spec
->features
[i
][n
]; n
++);
1714 tags
= alloca (sizeof (OTF_Tag
) * n
);
1715 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1717 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1720 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1722 tags
[n
] = spec
->features
[i
][n
];
1724 #ifdef M17N_FLT_USE_NEW_FEATURE
1725 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1726 tags
, n
- negative
) != 1)
1728 #else /* not M17N_FLT_USE_NEW_FEATURE */
1729 if (n
- negative
> 0
1730 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1731 tags
, n
- negative
) != 1)
1733 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1740 #define DEVICE_DELTA(table, size) \
1741 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1742 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1746 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1747 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1749 if (anchor
->AnchorFormat
== 2)
1751 FT_Outline
*outline
;
1752 int ap
= anchor
->f
.f1
.AnchorPoint
;
1754 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1755 outline
= &ft_face
->glyph
->outline
;
1756 if (ap
< outline
->n_points
)
1758 *x
= outline
->points
[ap
].x
<< 6;
1759 *y
= outline
->points
[ap
].y
<< 6;
1762 else if (anchor
->AnchorFormat
== 3)
1764 if (anchor
->f
.f2
.XDeviceTable
.offset
1765 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1766 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1767 if (anchor
->f
.f2
.YDeviceTable
.offset
1768 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1769 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1773 static OTF_GlyphString otf_gstring
;
1776 setup_otf_gstring (int size
)
1778 if (otf_gstring
.size
< size
)
1780 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1781 size
, sizeof (OTF_Glyph
));
1782 otf_gstring
.size
= size
;
1784 otf_gstring
.used
= size
;
1785 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1788 #ifdef M17N_FLT_USE_NEW_FEATURE
1790 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1791 #define PACK_OTF_TAG(TAG) \
1792 ((((TAG) & 0x7F000000) >> 3) \
1793 | (((TAG) & 0x7F0000) >> 2) \
1794 | (((TAG) & 0x7F00) >> 1) \
1797 /* Assuming that FONT is an OpenType font, apply OpenType features
1798 specified in SPEC on glyphs between FROM and TO of IN, and record
1799 the lastly applied feature in each glyph of IN. If OUT is not
1800 NULL, append the resulting glyphs to OUT while storing glyph
1801 position adjustment information in ADJUSTMENT. */
1804 ftfont_drive_otf (MFLTFont
*font
,
1806 MFLTGlyphString
*in
,
1809 MFLTGlyphString
*out
,
1810 MFLTGlyphAdjustment
*adjustment
)
1812 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1813 FT_Face ft_face
= flt_font_ft
->ft_face
;
1814 OTF
*otf
= flt_font_ft
->otf
;
1815 int len
= to
- from
;
1818 char script
[5], *langsys
= NULL
;
1819 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1820 OTF_Feature
*features
;
1824 OTF_tag_name (spec
->script
, script
);
1827 langsys
= alloca (5);
1828 OTF_tag_name (spec
->langsys
, langsys
);
1830 for (i
= 0; i
< 2; i
++)
1834 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1836 for (j
= 0; spec
->features
[i
][j
]; j
++);
1838 p
= gsub_features
= alloca (6 * j
);
1840 p
= gpos_features
= alloca (6 * j
);
1841 for (j
= 0; spec
->features
[i
][j
]; j
++)
1843 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1844 *p
++ = '*', *p
++ = ',';
1847 OTF_tag_name (spec
->features
[i
][j
], p
);
1856 setup_otf_gstring (len
);
1857 for (i
= 0; i
< len
; i
++)
1859 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
& 0x11FFFF;
1860 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1863 OTF_drive_gdef (otf
, &otf_gstring
);
1864 gidx
= out
? out
->used
: from
;
1866 if (gsub_features
&& out
)
1868 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1871 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1873 features
= otf
->gsub
->FeatureList
.Feature
;
1874 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1877 int min_from
, max_to
;
1878 int feature_idx
= otfg
->positioning_type
>> 4;
1880 g
= out
->glyphs
+ out
->used
;
1881 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1882 if (g
->code
!= otfg
->glyph_id
)
1885 g
->code
= otfg
->glyph_id
;
1891 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1893 /* OTFG substitutes multiple glyphs in IN. */
1894 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1895 j
<= from
+ otfg
->f
.index
.to
; j
++)
1897 if (min_from
> in
->glyphs
[j
].from
)
1898 min_from
= in
->glyphs
[j
].from
;
1899 if (max_to
< in
->glyphs
[j
].to
)
1900 max_to
= in
->glyphs
[j
].to
;
1907 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1908 tag
= PACK_OTF_TAG (tag
);
1909 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1911 for (i
++, otfg
++; (i
< otf_gstring
.used
1912 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1915 g
= out
->glyphs
+ out
->used
;
1916 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1917 if (g
->code
!= otfg
->glyph_id
)
1920 g
->code
= otfg
->glyph_id
;
1923 feature_idx
= otfg
->positioning_type
>> 4;
1926 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1927 tag
= PACK_OTF_TAG (tag
);
1928 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1934 else if (gsub_features
)
1936 /* Just for checking which features will be applied. */
1937 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1940 features
= otf
->gsub
->FeatureList
.Feature
;
1941 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1944 int feature_idx
= otfg
->positioning_type
>> 4;
1948 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1949 tag
= PACK_OTF_TAG (tag
);
1950 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1952 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1953 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1960 if (out
->allocated
< out
->used
+ len
)
1962 for (i
= 0; i
< len
; i
++)
1963 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1966 if (gpos_features
&& out
)
1968 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1969 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1971 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1974 features
= otf
->gpos
->FeatureList
.Feature
;
1975 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1976 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1977 x_scale
= ft_face
->size
->metrics
.x_scale
;
1978 y_scale
= ft_face
->size
->metrics
.y_scale
;
1980 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1981 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1984 int feature_idx
= otfg
->positioning_type
>> 4;
1988 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1989 tag
= PACK_OTF_TAG (tag
);
1990 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1993 if (! otfg
->glyph_id
)
1995 switch (otfg
->positioning_type
& 0xF)
1999 case 1: /* Single */
2002 int format
= otfg
->f
.f1
.format
;
2004 if (format
& OTF_XPlacement
)
2006 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2007 if (format
& OTF_XPlaDevice
)
2009 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2010 if (format
& OTF_YPlacement
)
2012 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2013 if (format
& OTF_YPlaDevice
)
2015 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2016 if (format
& OTF_XAdvance
)
2018 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2019 if (format
& OTF_XAdvDevice
)
2021 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2022 if (format
& OTF_YAdvance
)
2024 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2025 if (format
& OTF_YAdvDevice
)
2027 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2028 adjustment
[i
].set
= 1;
2031 case 3: /* Cursive */
2032 /* Not yet supported. */
2034 case 4: /* Mark-to-Base */
2035 case 5: /* Mark-to-Ligature */
2039 goto label_adjust_anchor
;
2040 default: /* i.e. case 6 Mark-to-Mark */
2045 label_adjust_anchor
:
2047 int base_x
, base_y
, mark_x
, mark_y
;
2048 int this_from
, this_to
;
2050 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2051 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2052 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2053 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2055 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2056 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2057 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2058 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2059 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2060 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2061 adjustment
[i
].xoff
= (base_x
- mark_x
);
2062 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2063 adjustment
[i
].back
= (g
- prev
);
2064 adjustment
[i
].xadv
= 0;
2065 adjustment
[i
].advance_is_absolute
= 1;
2066 adjustment
[i
].set
= 1;
2067 this_from
= g
->from
;
2069 for (j
= 0; prev
+ j
< g
; j
++)
2071 if (this_from
> prev
[j
].from
)
2072 this_from
= prev
[j
].from
;
2073 if (this_to
< prev
[j
].to
)
2074 this_to
= prev
[j
].to
;
2076 for (; prev
<= g
; prev
++)
2078 prev
->from
= this_from
;
2083 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2085 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2091 else if (gpos_features
)
2093 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2096 features
= otf
->gpos
->FeatureList
.Feature
;
2097 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2099 if (otfg
->positioning_type
& 0xF)
2101 int feature_idx
= otfg
->positioning_type
>> 4;
2105 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2106 tag
= PACK_OTF_TAG (tag
);
2107 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2109 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2110 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2120 if (out
->allocated
< out
->used
+ len
)
2122 font
->get_metrics (font
, in
, from
, to
);
2123 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2124 sizeof (MFLTGlyph
) * len
);
2130 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2131 MFLTGlyphString
*in
, int from
, int to
)
2133 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2136 #else /* not M17N_FLT_USE_NEW_FEATURE */
2139 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2141 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2143 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2144 FT_Face ft_face
= flt_font_ft
->ft_face
;
2145 OTF
*otf
= flt_font_ft
->otf
;
2146 int len
= to
- from
;
2149 char script
[5], *langsys
= NULL
;
2150 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2154 OTF_tag_name (spec
->script
, script
);
2157 langsys
= alloca (5);
2158 OTF_tag_name (spec
->langsys
, langsys
);
2160 for (i
= 0; i
< 2; i
++)
2164 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2166 for (j
= 0; spec
->features
[i
][j
]; j
++);
2168 p
= gsub_features
= alloca (6 * j
);
2170 p
= gpos_features
= alloca (6 * j
);
2171 for (j
= 0; spec
->features
[i
][j
]; j
++)
2173 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2174 *p
++ = '*', *p
++ = ',';
2177 OTF_tag_name (spec
->features
[i
][j
], p
);
2186 setup_otf_gstring (len
);
2187 for (i
= 0; i
< len
; i
++)
2189 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2190 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2193 OTF_drive_gdef (otf
, &otf_gstring
);
2198 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2201 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2203 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2206 int min_from
, max_to
;
2209 g
= out
->glyphs
+ out
->used
;
2210 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2211 if (g
->code
!= otfg
->glyph_id
)
2214 g
->code
= otfg
->glyph_id
;
2220 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2222 /* OTFG substitutes multiple glyphs in IN. */
2223 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2224 j
<= from
+ otfg
->f
.index
.to
; j
++)
2226 if (min_from
> in
->glyphs
[j
].from
)
2227 min_from
= in
->glyphs
[j
].from
;
2228 if (max_to
< in
->glyphs
[j
].to
)
2229 max_to
= in
->glyphs
[j
].to
;
2234 for (i
++, otfg
++; (i
< otf_gstring
.used
2235 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2238 g
= out
->glyphs
+ out
->used
;
2239 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2240 if (g
->code
!= otfg
->glyph_id
)
2243 g
->code
= otfg
->glyph_id
;
2252 if (out
->allocated
< out
->used
+ len
)
2254 for (i
= 0; i
< len
; i
++)
2255 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2260 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2261 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2263 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2267 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2268 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2269 x_scale
= ft_face
->size
->metrics
.x_scale
;
2270 y_scale
= ft_face
->size
->metrics
.y_scale
;
2272 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2273 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2277 if (! otfg
->glyph_id
)
2279 switch (otfg
->positioning_type
)
2283 case 1: /* Single */
2286 int format
= otfg
->f
.f1
.format
;
2288 if (format
& OTF_XPlacement
)
2290 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2291 if (format
& OTF_XPlaDevice
)
2293 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2294 if (format
& OTF_YPlacement
)
2296 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2297 if (format
& OTF_YPlaDevice
)
2299 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2300 if (format
& OTF_XAdvance
)
2302 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2303 if (format
& OTF_XAdvDevice
)
2305 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2306 if (format
& OTF_YAdvance
)
2308 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2309 if (format
& OTF_YAdvDevice
)
2311 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2312 adjustment
[i
].set
= 1;
2315 case 3: /* Cursive */
2316 /* Not yet supported. */
2318 case 4: /* Mark-to-Base */
2319 case 5: /* Mark-to-Ligature */
2323 goto label_adjust_anchor
;
2324 default: /* i.e. case 6 Mark-to-Mark */
2329 label_adjust_anchor
:
2331 int base_x
, base_y
, mark_x
, mark_y
;
2332 int this_from
, this_to
;
2334 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2335 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2336 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2337 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2339 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2340 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2341 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2342 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2343 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2344 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2345 adjustment
[i
].xoff
= (base_x
- mark_x
);
2346 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2347 adjustment
[i
].back
= (g
- prev
);
2348 adjustment
[i
].xadv
= 0;
2349 adjustment
[i
].advance_is_absolute
= 1;
2350 adjustment
[i
].set
= 1;
2351 this_from
= g
->from
;
2353 for (j
= 0; prev
+ j
< g
; j
++)
2355 if (this_from
> prev
[j
].from
)
2356 this_from
= prev
[j
].from
;
2357 if (this_to
< prev
[j
].to
)
2358 this_to
= prev
[j
].to
;
2360 for (; prev
<= g
; prev
++)
2362 prev
->from
= this_from
;
2367 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2369 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2378 if (out
->allocated
< out
->used
+ len
)
2380 font
->get_metrics (font
, in
, from
, to
);
2381 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2382 sizeof (MFLTGlyph
) * len
);
2387 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2389 static MFLTGlyphString gstring
;
2391 static int m17n_flt_initialized
;
2394 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2395 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2397 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2399 struct MFLTFontFT flt_font_ft
;
2401 int with_variation_selector
= 0;
2403 if (! m17n_flt_initialized
)
2406 #ifdef M17N_FLT_USE_NEW_FEATURE
2407 mflt_enable_new_feature
= 1;
2408 mflt_try_otf
= ftfont_try_otf
;
2409 #endif /* M17N_FLT_USE_NEW_FEATURE */
2410 m17n_flt_initialized
= 1;
2413 for (i
= 0; i
< len
; i
++)
2415 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2420 c
= LGLYPH_CHAR (g
);
2421 if (CHAR_VARIATION_SELECTOR_P (c
))
2422 with_variation_selector
++;
2426 lint_assume (len
<= STRING_BYTES_BOUND
);
2428 if (with_variation_selector
)
2430 setup_otf_gstring (len
);
2431 for (i
= 0; i
< len
; i
++)
2433 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2435 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2436 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2437 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2439 OTF_drive_cmap (otf
, &otf_gstring
);
2440 for (i
= 0; i
< otf_gstring
.used
; i
++)
2442 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2443 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2444 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2446 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2447 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2448 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2450 if (len
> otf_gstring
.used
)
2452 len
= otf_gstring
.used
;
2453 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2457 if (INT_MAX
/ 2 < len
)
2458 memory_full (SIZE_MAX
);
2460 if (gstring
.allocated
== 0)
2462 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2463 gstring
.glyphs
= xnmalloc (len
* 2, sizeof (MFLTGlyph
));
2464 gstring
.allocated
= len
* 2;
2466 else if (gstring
.allocated
< len
* 2)
2468 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2, sizeof (MFLTGlyph
));
2469 gstring
.allocated
= len
* 2;
2471 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2472 for (i
= 0; i
< len
; i
++)
2474 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2476 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2477 if (with_variation_selector
)
2479 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2480 gstring
.glyphs
[i
].encoded
= 1;
2488 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2491 flt_font_ft
.flt_font
.family
= Mnil
;
2493 flt_font_ft
.flt_font
.family
2494 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2496 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2497 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2498 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2499 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2500 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2501 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2502 flt_font_ft
.flt_font
.internal
= NULL
;
2503 flt_font_ft
.font
= font
;
2504 flt_font_ft
.ft_face
= ft_face
;
2505 flt_font_ft
.otf
= otf
;
2506 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2508 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2509 /* A little bit ad hoc. Perhaps, shaper must get script and
2510 language information, and select a proper flt for them
2512 flt
= mflt_get (msymbol ("combining"));
2513 for (i
= 0; i
< 3; i
++)
2515 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2518 if (INT_MAX
/ 2 < gstring
.allocated
)
2519 memory_full (SIZE_MAX
);
2520 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2521 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2522 gstring
.allocated
*= 2;
2524 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2526 for (i
= 0; i
< gstring
.used
; i
++)
2528 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2530 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2531 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2534 for (i
= 0; i
< gstring
.used
; i
++)
2536 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2537 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2541 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2542 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2544 LGLYPH_SET_FROM (lglyph
, g
->from
);
2545 LGLYPH_SET_TO (lglyph
, g
->to
);
2546 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2547 LGLYPH_SET_CODE (lglyph
, g
->code
);
2548 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2549 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2550 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2551 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2552 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2557 vec
= Fmake_vector (make_number (3), Qnil
);
2558 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2559 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2560 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2561 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2564 return make_number (i
);
2568 ftfont_shape (Lisp_Object lgstring
)
2571 struct ftfont_info
*ftfont_info
;
2574 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2575 ftfont_info
= (struct ftfont_info
*) font
;
2576 otf
= ftfont_get_otf (ftfont_info
);
2578 return make_number (0);
2579 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2580 &ftfont_info
->matrix
);
2583 #endif /* HAVE_M17N_FLT */
2585 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2588 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2590 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2591 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2595 return OTF_get_variation_glyphs (otf
, c
, variations
);
2598 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2599 #endif /* HAVE_LIBOTF */
2602 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2606 #ifdef FC_FONTFORMAT
2609 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2611 if (strcmp ((char *) str
, "TrueType") == 0)
2612 return intern ("truetype");
2613 if (strcmp ((char *) str
, "Type 1") == 0)
2614 return intern ("type1");
2615 if (strcmp ((char *) str
, "PCF") == 0)
2616 return intern ("pcf");
2617 if (strcmp ((char *) str
, "BDF") == 0)
2618 return intern ("bdf");
2620 #endif /* FC_FONTFORMAT */
2621 if (STRINGP (filename
))
2623 int len
= SBYTES (filename
);
2627 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2628 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2629 return intern ("truetype");
2630 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2631 return intern ("type1");
2632 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2633 return intern ("pcf");
2634 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2635 return intern ("bdf");
2638 return intern ("unknown");
2641 static const char *const ftfont_booleans
[] = {
2654 static const char *const ftfont_non_booleans
[] = {
2686 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2688 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2693 syms_of_ftfont (void)
2695 DEFSYM (Qfreetype
, "freetype");
2696 DEFSYM (Qmonospace
, "monospace");
2697 DEFSYM (Qsans_serif
, "sans-serif");
2698 DEFSYM (Qserif
, "serif");
2699 DEFSYM (Qmono
, "mono");
2700 DEFSYM (Qsans
, "sans");
2701 DEFSYM (Qsans__serif
, "sans serif");
2703 staticpro (&freetype_font_cache
);
2704 freetype_font_cache
= Fcons (Qt
, Qnil
);
2706 staticpro (&ftfont_generic_family_list
);
2707 ftfont_generic_family_list
2708 = Fcons (Fcons (Qmonospace
, Qt
),
2709 Fcons (Fcons (Qsans_serif
, Qt
),
2710 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2712 staticpro (&ft_face_cache
);
2713 ft_face_cache
= Qnil
;
2715 ftfont_driver
.type
= Qfreetype
;
2716 register_font_driver (&ftfont_driver
, NULL
);