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/>. */
24 #include <fontconfig/fontconfig.h>
25 #include <fontconfig/fcfreetype.h>
28 #include "dispextern.h"
30 #include "blockinput.h"
31 #include "character.h"
34 #include "composite.h"
39 /* Symbolic type of this font-driver. */
40 static Lisp_Object Qfreetype
;
42 /* Fontconfig's generic families and their aliases. */
43 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
45 /* Flag to tell if FcInit is already called or not. */
46 static bool fc_initialized
;
48 /* Handle to a FreeType library instance. */
49 static FT_Library ft_library
;
51 /* Cache for FreeType fonts. */
52 static Lisp_Object freetype_font_cache
;
54 /* Cache for FT_Face and FcCharSet. */
55 static Lisp_Object ft_face_cache
;
57 /* The actual structure for FreeType font that can be casted to struct
64 /* The following four members must be here in this order to be
65 compatible with struct xftfont_info (in xftfont.c). */
66 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
68 #endif /* HAVE_LIBOTF */
76 FTFONT_CACHE_FOR_FACE
,
77 FTFONT_CACHE_FOR_CHARSET
,
78 FTFONT_CACHE_FOR_ENTITY
81 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
83 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
85 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
86 enum ftfont_cache_for
);
88 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
90 Lisp_Object
ftfont_font_format (FcPattern
*, Lisp_Object
);
92 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
98 /* characters to distinguish the charset from the others */
100 /* additional constraint by language */
103 FcCharSet
*fc_charset
;
104 } fc_charset_table
[] =
105 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
106 { "iso8859-2", { 0x00A0, 0x010E }},
107 { "iso8859-3", { 0x00A0, 0x0108 }},
108 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
109 { "iso8859-5", { 0x00A0, 0x0401 }},
110 { "iso8859-6", { 0x00A0, 0x060C }},
111 { "iso8859-7", { 0x00A0, 0x0384 }},
112 { "iso8859-8", { 0x00A0, 0x05D0 }},
113 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
114 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
115 { "iso8859-11", { 0x00A0, 0x0E01 }},
116 { "iso8859-13", { 0x00A0, 0x201C }},
117 { "iso8859-14", { 0x00A0, 0x0174 }},
118 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
119 { "iso8859-16", { 0x00A0, 0x0218}},
120 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
121 { "big5-0", { 0xF6B1 }, "zh-tw" },
122 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
123 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
124 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
125 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
126 { "cns11643.1992-3", { 0x201A9 }},
127 { "cns11643.1992-4", { 0x20057 }},
128 { "cns11643.1992-5", { 0x20000 }},
129 { "cns11643.1992-6", { 0x20003 }},
130 { "cns11643.1992-7", { 0x20055 }},
131 { "gbk-0", { 0x4E06 }, "zh-cn"},
132 { "jisx0212.1990-0", { 0x4E44 }},
133 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
134 { "jisx0213.2000-2", { 0xFA49 }},
135 { "jisx0213.2004-1", { 0x20B9F }},
136 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
137 { "tis620.2529-1", { 0x0E01 }, "th"},
138 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
139 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
140 { "mulelao-1", { 0x0E81 }, "lo"},
141 { "unicode-sip", { 0x20000 }},
145 /* Dirty hack for handing ADSTYLE property.
147 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
148 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
149 "Oblique", "Italic", or any non-normal SWIDTH property names
150 (e.g. SemiCondensed) are appended. In addition, if there's no
151 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
152 "Regular" is used for FC_STYLE (see the function
153 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
155 Unfortunately this behavior is not documented, so the following
156 code may fail if FreeType changes the behavior in the future. */
159 get_adstyle_property (FcPattern
*p
)
166 if ((FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fcstr
) == FcResultMatch
)
167 && xstrcasecmp ((char *) fcstr
, "bdf") != 0
168 && xstrcasecmp ((char *) fcstr
, "pcf") != 0)
169 /* Not a BDF nor PCF font. */
172 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
174 str
= (char *) fcstr
;
175 for (end
= str
; *end
&& *end
!= ' '; end
++);
178 char *newstr
= alloca (end
- str
+ 1);
179 memcpy (newstr
, str
, end
- str
);
180 newstr
[end
- str
] = '\0';
181 end
= newstr
+ (end
- str
);
184 if (xstrcasecmp (str
, "Regular") == 0
185 || xstrcasecmp (str
, "Bold") == 0
186 || xstrcasecmp (str
, "Oblique") == 0
187 || xstrcasecmp (str
, "Italic") == 0)
189 adstyle
= font_intern_prop (str
, end
- str
, 1);
190 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
196 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
198 Lisp_Object key
, cache
, entity
;
206 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
208 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
212 key
= Fcons (build_unibyte_string (file
), make_number (idx
));
213 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
214 entity
= XCAR (cache
);
217 Lisp_Object val
= font_make_entity ();
220 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
221 ASET (val
, i
, AREF (entity
, i
));
223 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
224 font_put_extra (val
, QCfont_entity
, key
);
228 entity
= font_make_entity ();
229 XSETCAR (cache
, entity
);
231 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
232 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
234 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
236 char *s
= (char *) str
;
237 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
239 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
241 char *s
= (char *) str
;
242 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
244 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
246 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
247 numeric
= FC_WEIGHT_MEDIUM
;
248 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
250 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
253 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
255 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
257 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
259 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
261 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
264 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
265 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
266 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
267 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
270 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
272 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
275 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
276 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
280 /* As this font is not scalable, perhaps this is a BDF or PCF
284 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
285 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
286 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
290 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
291 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
292 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
293 FT_Done_Face (ft_face
);
297 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
298 font_put_extra (entity
, QCfont_entity
, key
);
303 static Lisp_Object ftfont_generic_family_list
;
306 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
313 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
314 if (EQ (family
, Qmono
))
316 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
317 family
= Qsans_serif
;
318 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
321 if (! EQ (XCDR (slot
), Qt
))
323 pattern
= FcPatternDuplicate (pattern
);
326 FcPatternDel (pattern
, FC_FOUNDRY
);
327 FcPatternDel (pattern
, FC_FAMILY
);
328 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
329 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
331 /* This is to avoid the effect of locale. */
332 static const FcChar8 lang
[] = "en";
333 langset
= FcLangSetCreate ();
334 FcLangSetAdd (langset
, lang
);
335 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
336 FcLangSetDestroy (langset
);
338 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
339 FcDefaultSubstitute (pattern
);
340 match
= FcFontMatch (NULL
, pattern
, &result
);
345 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
346 family
= intern ((char *) fam
);
350 XSETCDR (slot
, family
);
351 if (match
) FcPatternDestroy (match
);
353 if (pattern
) FcPatternDestroy (pattern
);
357 struct ftfont_cache_data
360 FcCharSet
*fc_charset
;
364 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
366 Lisp_Object cache
, val
, entity
;
367 struct ftfont_cache_data
*cache_data
;
369 if (FONT_ENTITY_P (key
))
372 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
373 eassert (CONSP (val
));
379 if (NILP (ft_face_cache
))
382 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
385 if (NILP (ft_face_cache
))
391 ft_face_cache
= Fmake_hash_table (2, args
);
393 cache_data
= xmalloc (sizeof *cache_data
);
394 cache_data
->ft_face
= NULL
;
395 cache_data
->fc_charset
= NULL
;
396 val
= make_save_value (NULL
, 0);
397 XSAVE_VALUE (val
)->integer
= 0;
398 XSAVE_VALUE (val
)->pointer
= cache_data
;
399 cache
= Fcons (Qnil
, val
);
400 Fputhash (key
, cache
, ft_face_cache
);
405 cache_data
= XSAVE_VALUE (val
)->pointer
;
408 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
411 if (cache_for
== FTFONT_CACHE_FOR_FACE
412 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
414 char *filename
= SSDATA (XCAR (key
));
415 int idx
= XINT (XCDR (key
));
417 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
420 && FT_Init_FreeType (&ft_library
) != 0)
422 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
428 FcPattern
*pat
= NULL
;
429 FcFontSet
*fontset
= NULL
;
430 FcObjectSet
*objset
= NULL
;
431 FcCharSet
*charset
= NULL
;
433 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
434 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
437 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
440 fontset
= FcFontList (NULL
, pat
, objset
);
443 if (fontset
&& fontset
->nfont
> 0
444 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
447 cache_data
->fc_charset
= FcCharSetCopy (charset
);
449 cache_data
->fc_charset
= FcCharSetCreate ();
453 FcFontSetDestroy (fontset
);
455 FcObjectSetDestroy (objset
);
457 FcPatternDestroy (pat
);
464 ftfont_get_fc_charset (Lisp_Object entity
)
466 Lisp_Object val
, cache
;
467 struct ftfont_cache_data
*cache_data
;
469 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
471 cache_data
= XSAVE_VALUE (val
)->pointer
;
472 return cache_data
->fc_charset
;
477 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
481 if (ftfont_info
->otf
)
482 return ftfont_info
->otf
;
483 if (! ftfont_info
->maybe_otf
)
485 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
486 if (! otf
|| OTF_get_table (otf
, "head") < 0)
490 ftfont_info
->maybe_otf
= 0;
493 ftfont_info
->otf
= otf
;
496 #endif /* HAVE_LIBOTF */
498 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
499 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
500 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
501 static Lisp_Object
ftfont_list_family (Lisp_Object
);
502 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
503 static void ftfont_close (FRAME_PTR
, struct font
*);
504 static int ftfont_has_char (Lisp_Object
, int);
505 static unsigned ftfont_encode_char (struct font
*, int);
506 static int ftfont_text_extents (struct font
*, unsigned *, int,
507 struct font_metrics
*);
508 static int ftfont_get_bitmap (struct font
*, unsigned,
509 struct font_bitmap
*, int);
510 static int ftfont_anchor_point (struct font
*, unsigned, int,
513 static Lisp_Object
ftfont_otf_capability (struct font
*);
514 # ifdef HAVE_M17N_FLT
515 static Lisp_Object
ftfont_shape (Lisp_Object
);
519 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
520 static int ftfont_variation_glyphs (struct font
*, int c
,
521 unsigned variations
[256]);
522 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
524 struct font_driver ftfont_driver
=
526 LISP_INITIALLY_ZERO
, /* Qfreetype */
527 0, /* case insensitive */
532 NULL
, /* free_entity */
535 /* We can't draw a text without device dependent functions. */
536 NULL
, /* prepare_face */
537 NULL
, /* done_face */
541 /* We can't draw a text without device dependent functions. */
544 NULL
, /* free_bitmap */
545 NULL
, /* get_outline */
546 NULL
, /* free_outline */
549 ftfont_otf_capability
,
550 #else /* not HAVE_LIBOTF */
552 #endif /* not HAVE_LIBOTF */
553 NULL
, /* otf_drive */
554 NULL
, /* start_for_frame */
555 NULL
, /* end_for_frame */
556 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
558 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
560 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
563 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
564 ftfont_variation_glyphs
,
569 ftfont_filter_properties
, /* filter_properties */
573 ftfont_get_cache (FRAME_PTR f
)
575 return freetype_font_cache
;
579 ftfont_get_charset (Lisp_Object registry
)
581 char *str
= SSDATA (SYMBOL_NAME (registry
));
582 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
586 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
590 else if (str
[i
] == '*')
597 regexp
= make_unibyte_string (re
, j
);
598 for (i
= 0; fc_charset_table
[i
].name
; i
++)
599 if (fast_c_string_match_ignore_case
600 (regexp
, fc_charset_table
[i
].name
,
601 strlen (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 *spec
);
667 spec
->script
= XCAR (otf_spec
);
668 if (! NILP (spec
->script
))
670 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
671 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
672 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
673 spec
->script
= XCDR (val
);
678 spec
->script_tag
= 0x44464C54; /* "DFLT" */
679 otf_spec
= XCDR (otf_spec
);
680 spec
->langsys_tag
= 0;
681 if (! NILP (otf_spec
))
683 val
= XCAR (otf_spec
);
685 OTF_SYM_TAG (val
, spec
->langsys_tag
);
686 otf_spec
= XCDR (otf_spec
);
688 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
689 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
693 val
= XCAR (otf_spec
);
698 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
700 : malloc (XINT (len
) * sizeof *spec
->features
[i
]));
701 if (! spec
->features
[i
])
703 if (i
> 0 && spec
->features
[0])
704 free (spec
->features
[0]);
708 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
710 if (NILP (XCAR (val
)))
716 OTF_SYM_TAG (XCAR (val
), tag
);
717 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
720 spec
->nfeatures
[i
] = j
;
726 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
728 Lisp_Object tmp
, extra
;
729 FcPattern
*pattern
= NULL
;
730 FcCharSet
*charset
= NULL
;
731 FcLangSet
*langset
= NULL
;
735 Lisp_Object script
= Qnil
;
736 Lisp_Object registry
;
739 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
741 /* Fontconfig doesn't support reverse-italic/oblique. */
744 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
745 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
746 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
747 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
750 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
752 || EQ (registry
, Qascii_0
)
753 || EQ (registry
, Qiso10646_1
)
754 || EQ (registry
, Qunicode_bmp
))
760 fc_charset_idx
= ftfont_get_charset (registry
);
761 if (fc_charset_idx
< 0)
763 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
764 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
765 lang
= (FcChar8
*) *langname
;
768 langset
= FcLangSetCreate ();
771 FcLangSetAdd (langset
, lang
);
776 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
777 CONSP (extra
); extra
= XCDR (extra
))
779 Lisp_Object key
, val
;
781 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
787 else if (EQ (key
, QClang
))
790 langset
= FcLangSetCreate ();
795 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
799 for (; CONSP (val
); val
= XCDR (val
))
800 if (SYMBOLP (XCAR (val
))
801 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
804 else if (EQ (key
, QCotf
))
808 *otspec
= ftfont_get_open_type_spec (val
);
811 strcat (otlayout
, "otlayout:");
812 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
813 script
= (*otspec
)->script
;
816 else if (EQ (key
, QCscript
))
818 else if (EQ (key
, QCscalable
))
819 scalable
= ! NILP (val
);
822 if (! NILP (script
) && ! charset
)
824 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
826 if (CONSP (chars
) && CONSP (CDR (chars
)))
828 charset
= FcCharSetCreate ();
831 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
832 if (CHARACTERP (XCAR (chars
))
833 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
838 pattern
= FcPatternCreate ();
841 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
843 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
845 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
847 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
850 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
853 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
856 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
859 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
865 /* We come here because of unexpected error in fontconfig API call
866 (usually insufficient memory). */
869 FcPatternDestroy (pattern
);
874 if ((*otspec
)->nfeatures
[0] > 0)
875 free ((*otspec
)->features
[0]);
876 if ((*otspec
)->nfeatures
[1] > 0)
877 free ((*otspec
)->features
[1]);
883 if (langset
) FcLangSetDestroy (langset
);
884 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
889 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
891 Lisp_Object val
= Qnil
, family
, adstyle
;
894 FcFontSet
*fontset
= NULL
;
895 FcObjectSet
*objset
= NULL
;
897 Lisp_Object chars
= Qnil
;
898 char otlayout
[15]; /* For "otlayout:XXXX" */
899 struct OpenTypeSpec
*otspec
= NULL
;
901 const char *langname
= NULL
;
903 if (! fc_initialized
)
909 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
912 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
914 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
917 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
918 if (CONSP (val
) && VECTORP (XCDR (val
)))
923 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
924 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
925 family
= AREF (spec
, FONT_FAMILY_INDEX
);
928 Lisp_Object resolved
;
930 resolved
= ftfont_resolve_generic_family (family
, pattern
);
931 if (! NILP (resolved
))
933 FcPatternDel (pattern
, FC_FAMILY
);
934 if (! FcPatternAddString (pattern
, FC_FAMILY
,
935 SYMBOL_FcChar8 (resolved
)))
939 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
940 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
942 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
943 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
944 FC_STYLE
, FC_FILE
, FC_INDEX
,
947 #endif /* FC_CAPABILITY */
955 FcObjectSetAdd (objset
, FC_CHARSET
);
957 fontset
= FcFontList (NULL
, pattern
, objset
);
958 if (! fontset
|| fontset
->nfont
== 0)
961 /* Need fix because this finds any fonts. */
962 if (fontset
->nfont
== 0 && ! NILP (family
))
964 /* Try matching with configuration. For instance, the
965 configuration may specify "Nimbus Mono L" as an alias of
967 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
968 SYMBOL_FcChar8 (family
), NULL
);
971 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
974 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
977 FcPatternDel (pattern
, FC_FAMILY
);
978 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
979 FcFontSetDestroy (fontset
);
980 fontset
= FcFontList (NULL
, pattern
, objset
);
981 if (fontset
&& fontset
->nfont
> 0)
987 for (i
= 0; i
< fontset
->nfont
; i
++)
995 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
1001 #ifdef FC_CAPABILITY
1006 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
1008 || ! strstr ((char *) this, otlayout
))
1011 #endif /* FC_CAPABILITY */
1018 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1021 otf
= OTF_open ((char *) file
);
1024 if (OTF_check_features (otf
, 1,
1025 otspec
->script_tag
, otspec
->langsys_tag
,
1026 otspec
->features
[0],
1027 otspec
->nfeatures
[0]) != 1
1028 || OTF_check_features (otf
, 0,
1029 otspec
->script_tag
, otspec
->langsys_tag
,
1030 otspec
->features
[1],
1031 otspec
->nfeatures
[1]) != 1)
1034 #endif /* HAVE_LIBOTF */
1035 if (VECTORP (chars
))
1039 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1042 for (j
= 0; j
< ASIZE (chars
); j
++)
1043 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1044 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1046 if (j
== ASIZE (chars
))
1049 if (! NILP (adstyle
) || langname
)
1051 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1053 if (! NILP (adstyle
)
1054 && (NILP (this_adstyle
)
1055 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1056 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1059 && ! NILP (this_adstyle
)
1060 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1063 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1064 AREF (spec
, FONT_EXTRA_INDEX
));
1065 if (! NILP (entity
))
1066 val
= Fcons (entity
, val
);
1068 val
= Fnreverse (val
);
1072 /* We come here because of unexpected error in fontconfig API call
1073 (usually insufficient memory). */
1077 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1078 if (objset
) FcObjectSetDestroy (objset
);
1079 if (fontset
) FcFontSetDestroy (fontset
);
1080 if (pattern
) FcPatternDestroy (pattern
);
1085 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1087 Lisp_Object entity
= Qnil
;
1088 FcPattern
*pattern
, *match
= NULL
;
1090 char otlayout
[15]; /* For "otlayout:XXXX" */
1091 struct OpenTypeSpec
*otspec
= NULL
;
1092 const char *langname
= NULL
;
1094 if (! fc_initialized
)
1100 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1104 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1108 value
.type
= FcTypeDouble
;
1109 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1110 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1112 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1114 FcDefaultSubstitute (pattern
);
1115 match
= FcFontMatch (NULL
, pattern
, &result
);
1118 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1119 FcPatternDestroy (match
);
1120 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1121 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1122 ftfont_generic_family_list
))
1123 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1124 AREF (entity
, FONT_FAMILY_INDEX
))))
1128 FcPatternDestroy (pattern
);
1130 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1135 ftfont_list_family (Lisp_Object frame
)
1137 Lisp_Object list
= Qnil
;
1138 FcPattern
*pattern
= NULL
;
1139 FcFontSet
*fontset
= NULL
;
1140 FcObjectSet
*objset
= NULL
;
1143 if (! fc_initialized
)
1149 pattern
= FcPatternCreate ();
1152 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1155 fontset
= FcFontList (NULL
, pattern
, objset
);
1159 for (i
= 0; i
< fontset
->nfont
; i
++)
1161 FcPattern
*pat
= fontset
->fonts
[i
];
1164 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1165 list
= Fcons (intern ((char *) str
), list
);
1169 if (objset
) FcObjectSetDestroy (objset
);
1170 if (fontset
) FcFontSetDestroy (fontset
);
1171 if (pattern
) FcPatternDestroy (pattern
);
1178 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1180 struct ftfont_info
*ftfont_info
;
1182 struct ftfont_cache_data
*cache_data
;
1186 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1193 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1197 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1200 filename
= XCAR (val
);
1203 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1204 ft_face
= cache_data
->ft_face
;
1205 if (XSAVE_VALUE (val
)->integer
> 0)
1207 /* FT_Face in this cache is already used by the different size. */
1208 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1210 if (FT_Activate_Size (ft_size
) != 0)
1212 FT_Done_Size (ft_size
);
1216 XSAVE_VALUE (val
)->integer
++;
1217 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1220 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1222 if (XSAVE_VALUE (val
)->integer
== 0)
1223 FT_Done_Face (ft_face
);
1227 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1228 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1229 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1231 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1232 len
= font_unparse_fcname (entity
, size
, name
, 256);
1234 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1236 ASET (font_object
, FONT_FULLNAME_INDEX
,
1237 AREF (font_object
, FONT_NAME_INDEX
));
1238 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1239 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1240 font
= XFONT_OBJECT (font_object
);
1241 ftfont_info
= (struct ftfont_info
*) font
;
1242 ftfont_info
->ft_size
= ft_face
->size
;
1243 ftfont_info
->index
= XINT (idx
);
1245 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1246 ftfont_info
->otf
= NULL
;
1247 #endif /* HAVE_LIBOTF */
1248 /* This means that there's no need of transformation. */
1249 ftfont_info
->matrix
.xx
= 0;
1250 font
->pixel_size
= size
;
1251 font
->driver
= &ftfont_driver
;
1252 font
->encoding_charset
= font
->repertory_charset
= -1;
1254 upEM
= ft_face
->units_per_EM
;
1255 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1256 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1259 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1260 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1261 font
->height
= ft_face
->height
* size
/ upEM
;
1265 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1266 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1267 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1269 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1270 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1272 spacing
= FC_PROPORTIONAL
;
1273 if (spacing
!= FC_PROPORTIONAL
1275 && spacing
!= FC_DUAL
1276 #endif /* FC_DUAL */
1278 font
->min_width
= font
->average_width
= font
->space_width
1279 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1280 : ft_face
->size
->metrics
.max_advance
>> 6);
1285 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1286 for (i
= 32, n
= 0; i
< 127; i
++)
1287 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1289 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1292 && (! font
->min_width
|| font
->min_width
> this_width
))
1293 font
->min_width
= this_width
;
1295 font
->space_width
= this_width
;
1296 font
->average_width
+= this_width
;
1300 font
->average_width
/= n
;
1303 font
->baseline_offset
= 0;
1304 font
->relative_compose
= 0;
1305 font
->default_ascent
= 0;
1306 font
->vertical_centering
= 0;
1309 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1310 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1314 font
->underline_position
= -1;
1315 font
->underline_thickness
= 0;
1322 ftfont_close (FRAME_PTR f
, struct font
*font
)
1324 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1325 Lisp_Object val
, cache
;
1327 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1328 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1329 eassert (CONSP (cache
));
1331 (XSAVE_VALUE (val
)->integer
)--;
1332 if (XSAVE_VALUE (val
)->integer
== 0)
1334 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1336 FT_Done_Face (cache_data
->ft_face
);
1338 if (ftfont_info
->otf
)
1339 OTF_close (ftfont_info
->otf
);
1341 cache_data
->ft_face
= NULL
;
1344 FT_Done_Size (ftfont_info
->ft_size
);
1348 ftfont_has_char (Lisp_Object font
, int c
)
1350 struct charset
*cs
= NULL
;
1352 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1353 && charset_jisx0208
>= 0)
1354 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1355 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1356 && charset_ksc5601
>= 0)
1357 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1359 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1361 if (FONT_ENTITY_P (font
))
1363 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1365 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1369 struct ftfont_info
*ftfont_info
;
1371 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1372 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1378 ftfont_encode_char (struct font
*font
, int c
)
1380 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1381 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1382 FT_ULong charcode
= c
;
1383 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1385 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1389 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1391 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1392 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1397 if (ftfont_info
->ft_size
!= ft_face
->size
)
1398 FT_Activate_Size (ftfont_info
->ft_size
);
1400 memset (metrics
, 0, sizeof (struct font_metrics
));
1401 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1403 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1405 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1411 metrics
->lbearing
= m
->horiBearingX
>> 6;
1412 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1413 metrics
->ascent
= m
->horiBearingY
>> 6;
1414 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1420 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1421 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1422 if (metrics
->rbearing
1423 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1425 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1426 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1427 metrics
->ascent
= m
->horiBearingY
>> 6;
1428 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1429 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1431 width
+= m
->horiAdvance
>> 6;
1435 width
+= font
->space_width
;
1439 metrics
->width
= width
;
1445 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1447 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1448 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1449 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1451 if (ftfont_info
->ft_size
!= ft_face
->size
)
1452 FT_Activate_Size (ftfont_info
->ft_size
);
1453 if (bits_per_pixel
== 1)
1455 #ifdef FT_LOAD_TARGET_MONO
1456 load_flags
|= FT_LOAD_TARGET_MONO
;
1458 load_flags
|= FT_LOAD_MONOCHROME
;
1461 else if (bits_per_pixel
!= 8)
1462 /* We don't support such a rendering. */
1465 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1467 bitmap
->bits_per_pixel
1468 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1469 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1470 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1471 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1473 if (bitmap
->bits_per_pixel
< 0)
1474 /* We don't support that kind of pixel mode. */
1476 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1477 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1478 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1479 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1480 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1481 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1482 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1483 bitmap
->extra
= NULL
;
1489 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1492 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1493 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1495 if (ftfont_info
->ft_size
!= ft_face
->size
)
1496 FT_Activate_Size (ftfont_info
->ft_size
);
1497 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1499 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1501 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1503 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1504 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1511 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1513 Lisp_Object scripts
, langsyses
, features
, sym
;
1516 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1518 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1520 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1522 OTF_LangSys
*otf_langsys
;
1525 otf_langsys
= otf_script
->LangSys
+ j
;
1526 else if (otf_script
->DefaultLangSysOffset
)
1527 otf_langsys
= &otf_script
->DefaultLangSys
;
1531 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1533 l
= otf_langsys
->FeatureIndex
[k
];
1534 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1536 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1537 features
= Fcons (sym
, features
);
1540 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1543 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1546 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1547 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1555 ftfont_otf_capability (struct font
*font
)
1557 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1558 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1559 Lisp_Object gsub_gpos
;
1563 gsub_gpos
= Fcons (Qnil
, Qnil
);
1564 if (OTF_get_table (otf
, "GSUB") == 0
1565 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1566 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1567 if (OTF_get_table (otf
, "GPOS") == 0
1568 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1569 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1573 #ifdef HAVE_M17N_FLT
1575 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1576 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1577 /* We can use the new feature of libotf and m17n-flt to handle the
1578 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1579 some Agian scripts. */
1580 #define M17N_FLT_USE_NEW_FEATURE
1593 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1596 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1597 FT_Face ft_face
= flt_font_ft
->ft_face
;
1600 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1603 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1605 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1611 /* Operators for 26.6 fixed fractional pixel format */
1613 #define FLOOR(x) ((x) & -64)
1614 #define CEIL(x) (((x)+63) & -64)
1615 #define ROUND(x) (((x)+32) & -64)
1618 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1621 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1622 FT_Face ft_face
= flt_font_ft
->ft_face
;
1625 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1628 if (g
->code
!= FONT_INVALID_CODE
)
1630 FT_Glyph_Metrics
*m
;
1632 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1634 m
= &ft_face
->glyph
->metrics
;
1635 if (flt_font_ft
->matrix
)
1640 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1641 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1642 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1643 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1644 for (i
= 0; i
< 4; i
++)
1645 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1646 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1647 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1648 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1649 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1653 g
->lbearing
= FLOOR (m
->horiBearingX
);
1654 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1655 g
->ascent
= CEIL (m
->horiBearingY
);
1656 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1658 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1663 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1664 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1665 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1674 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1676 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1678 #define FEATURE_ANY(IDX) \
1679 (spec->features[IDX] \
1680 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1682 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1683 OTF
*otf
= flt_font_ft
->otf
;
1688 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1689 /* Return true iff any of GSUB or GPOS support the script (and
1692 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1694 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1697 for (i
= 0; i
< 2; i
++)
1698 if (! FEATURE_ANY (i
))
1700 if (FEATURE_NONE (i
))
1703 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1708 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1711 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1717 for (n
= 1; spec
->features
[i
][n
]; n
++);
1718 tags
= alloca (sizeof (OTF_Tag
) * n
);
1719 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1721 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1724 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1726 tags
[n
] = spec
->features
[i
][n
];
1728 #ifdef M17N_FLT_USE_NEW_FEATURE
1729 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1730 tags
, n
- negative
) != 1)
1732 #else /* not M17N_FLT_USE_NEW_FEATURE */
1733 if (n
- negative
> 0
1734 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1735 tags
, n
- negative
) != 1)
1737 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1744 #define DEVICE_DELTA(table, size) \
1745 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1746 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1750 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1751 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1753 if (anchor
->AnchorFormat
== 2)
1755 FT_Outline
*outline
;
1756 int ap
= anchor
->f
.f1
.AnchorPoint
;
1758 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1759 outline
= &ft_face
->glyph
->outline
;
1760 if (ap
< outline
->n_points
)
1762 *x
= outline
->points
[ap
].x
<< 6;
1763 *y
= outline
->points
[ap
].y
<< 6;
1766 else if (anchor
->AnchorFormat
== 3)
1768 if (anchor
->f
.f2
.XDeviceTable
.offset
1769 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1770 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1771 if (anchor
->f
.f2
.YDeviceTable
.offset
1772 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1773 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1777 static OTF_GlyphString otf_gstring
;
1780 setup_otf_gstring (int size
)
1782 if (otf_gstring
.size
< size
)
1784 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1785 size
, sizeof (OTF_Glyph
));
1786 otf_gstring
.size
= size
;
1788 otf_gstring
.used
= size
;
1789 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1792 #ifdef M17N_FLT_USE_NEW_FEATURE
1794 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1795 #define PACK_OTF_TAG(TAG) \
1796 ((((TAG) & 0x7F000000) >> 3) \
1797 | (((TAG) & 0x7F0000) >> 2) \
1798 | (((TAG) & 0x7F00) >> 1) \
1801 /* Assuming that FONT is an OpenType font, apply OpenType features
1802 specified in SPEC on glyphs between FROM and TO of IN, and record
1803 the lastly applied feature in each glyph of IN. If OUT is not
1804 NULL, append the resulting glyphs to OUT while storing glyph
1805 position adjustment information in ADJUSTMENT. */
1808 ftfont_drive_otf (MFLTFont
*font
,
1810 MFLTGlyphString
*in
,
1813 MFLTGlyphString
*out
,
1814 MFLTGlyphAdjustment
*adjustment
)
1816 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1817 FT_Face ft_face
= flt_font_ft
->ft_face
;
1818 OTF
*otf
= flt_font_ft
->otf
;
1819 int len
= to
- from
;
1822 char script
[5], *langsys
= NULL
;
1823 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1824 OTF_Feature
*features
;
1828 OTF_tag_name (spec
->script
, script
);
1831 langsys
= alloca (5);
1832 OTF_tag_name (spec
->langsys
, langsys
);
1834 for (i
= 0; i
< 2; i
++)
1838 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1840 for (j
= 0; spec
->features
[i
][j
]; j
++);
1842 p
= gsub_features
= alloca (6 * j
);
1844 p
= gpos_features
= alloca (6 * j
);
1845 for (j
= 0; spec
->features
[i
][j
]; j
++)
1847 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1848 *p
++ = '*', *p
++ = ',';
1851 OTF_tag_name (spec
->features
[i
][j
], p
);
1860 setup_otf_gstring (len
);
1861 for (i
= 0; i
< len
; i
++)
1863 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
& 0x11FFFF;
1864 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1867 OTF_drive_gdef (otf
, &otf_gstring
);
1868 gidx
= out
? out
->used
: from
;
1870 if (gsub_features
&& out
)
1872 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1875 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1877 features
= otf
->gsub
->FeatureList
.Feature
;
1878 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1881 int min_from
, max_to
;
1882 int feature_idx
= otfg
->positioning_type
>> 4;
1884 g
= out
->glyphs
+ out
->used
;
1885 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1886 if (g
->code
!= otfg
->glyph_id
)
1889 g
->code
= otfg
->glyph_id
;
1895 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1897 /* OTFG substitutes multiple glyphs in IN. */
1898 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1899 j
<= from
+ otfg
->f
.index
.to
; j
++)
1901 if (min_from
> in
->glyphs
[j
].from
)
1902 min_from
= in
->glyphs
[j
].from
;
1903 if (max_to
< in
->glyphs
[j
].to
)
1904 max_to
= in
->glyphs
[j
].to
;
1911 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1912 tag
= PACK_OTF_TAG (tag
);
1913 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1915 for (i
++, otfg
++; (i
< otf_gstring
.used
1916 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1919 g
= out
->glyphs
+ out
->used
;
1920 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1921 if (g
->code
!= otfg
->glyph_id
)
1924 g
->code
= otfg
->glyph_id
;
1927 feature_idx
= otfg
->positioning_type
>> 4;
1930 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1931 tag
= PACK_OTF_TAG (tag
);
1932 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1938 else if (gsub_features
)
1940 /* Just for checking which features will be applied. */
1941 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1944 features
= otf
->gsub
->FeatureList
.Feature
;
1945 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1948 int feature_idx
= otfg
->positioning_type
>> 4;
1952 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1953 tag
= PACK_OTF_TAG (tag
);
1954 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1956 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1957 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1964 if (out
->allocated
< out
->used
+ len
)
1966 for (i
= 0; i
< len
; i
++)
1967 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1970 if (gpos_features
&& out
)
1972 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1973 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1975 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1978 features
= otf
->gpos
->FeatureList
.Feature
;
1979 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1980 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1981 x_scale
= ft_face
->size
->metrics
.x_scale
;
1982 y_scale
= ft_face
->size
->metrics
.y_scale
;
1984 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1985 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1988 int feature_idx
= otfg
->positioning_type
>> 4;
1992 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1993 tag
= PACK_OTF_TAG (tag
);
1994 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1997 if (! otfg
->glyph_id
)
1999 switch (otfg
->positioning_type
& 0xF)
2003 case 1: /* Single */
2006 int format
= otfg
->f
.f1
.format
;
2008 if (format
& OTF_XPlacement
)
2010 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2011 if (format
& OTF_XPlaDevice
)
2013 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2014 if (format
& OTF_YPlacement
)
2016 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2017 if (format
& OTF_YPlaDevice
)
2019 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2020 if (format
& OTF_XAdvance
)
2022 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2023 if (format
& OTF_XAdvDevice
)
2025 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2026 if (format
& OTF_YAdvance
)
2028 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2029 if (format
& OTF_YAdvDevice
)
2031 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2032 adjustment
[i
].set
= 1;
2035 case 3: /* Cursive */
2036 /* Not yet supported. */
2038 case 4: /* Mark-to-Base */
2039 case 5: /* Mark-to-Ligature */
2043 goto label_adjust_anchor
;
2044 default: /* i.e. case 6 Mark-to-Mark */
2049 label_adjust_anchor
:
2051 int base_x
, base_y
, mark_x
, mark_y
;
2052 int this_from
, this_to
;
2054 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2055 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2056 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2057 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2059 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2060 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2061 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2062 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2063 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2064 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2065 adjustment
[i
].xoff
= (base_x
- mark_x
);
2066 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2067 adjustment
[i
].back
= (g
- prev
);
2068 adjustment
[i
].xadv
= 0;
2069 adjustment
[i
].advance_is_absolute
= 1;
2070 adjustment
[i
].set
= 1;
2071 this_from
= g
->from
;
2073 for (j
= 0; prev
+ j
< g
; j
++)
2075 if (this_from
> prev
[j
].from
)
2076 this_from
= prev
[j
].from
;
2077 if (this_to
< prev
[j
].to
)
2078 this_to
= prev
[j
].to
;
2080 for (; prev
<= g
; prev
++)
2082 prev
->from
= this_from
;
2087 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2089 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2095 else if (gpos_features
)
2097 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2100 features
= otf
->gpos
->FeatureList
.Feature
;
2101 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2103 if (otfg
->positioning_type
& 0xF)
2105 int feature_idx
= otfg
->positioning_type
>> 4;
2109 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2110 tag
= PACK_OTF_TAG (tag
);
2111 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2113 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2114 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2124 if (out
->allocated
< out
->used
+ len
)
2126 font
->get_metrics (font
, in
, from
, to
);
2127 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2128 sizeof (MFLTGlyph
) * len
);
2134 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2135 MFLTGlyphString
*in
, int from
, int to
)
2137 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2140 #else /* not M17N_FLT_USE_NEW_FEATURE */
2143 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2145 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2147 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2148 FT_Face ft_face
= flt_font_ft
->ft_face
;
2149 OTF
*otf
= flt_font_ft
->otf
;
2150 int len
= to
- from
;
2153 char script
[5], *langsys
= NULL
;
2154 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2158 OTF_tag_name (spec
->script
, script
);
2161 langsys
= alloca (5);
2162 OTF_tag_name (spec
->langsys
, langsys
);
2164 for (i
= 0; i
< 2; i
++)
2168 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2170 for (j
= 0; spec
->features
[i
][j
]; j
++);
2172 p
= gsub_features
= alloca (6 * j
);
2174 p
= gpos_features
= alloca (6 * j
);
2175 for (j
= 0; spec
->features
[i
][j
]; j
++)
2177 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2178 *p
++ = '*', *p
++ = ',';
2181 OTF_tag_name (spec
->features
[i
][j
], p
);
2190 setup_otf_gstring (len
);
2191 for (i
= 0; i
< len
; i
++)
2193 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2194 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2197 OTF_drive_gdef (otf
, &otf_gstring
);
2202 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2205 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2207 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2210 int min_from
, max_to
;
2213 g
= out
->glyphs
+ out
->used
;
2214 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2215 if (g
->code
!= otfg
->glyph_id
)
2218 g
->code
= otfg
->glyph_id
;
2224 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2226 /* OTFG substitutes multiple glyphs in IN. */
2227 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2228 j
<= from
+ otfg
->f
.index
.to
; j
++)
2230 if (min_from
> in
->glyphs
[j
].from
)
2231 min_from
= in
->glyphs
[j
].from
;
2232 if (max_to
< in
->glyphs
[j
].to
)
2233 max_to
= in
->glyphs
[j
].to
;
2238 for (i
++, otfg
++; (i
< otf_gstring
.used
2239 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2242 g
= out
->glyphs
+ out
->used
;
2243 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2244 if (g
->code
!= otfg
->glyph_id
)
2247 g
->code
= otfg
->glyph_id
;
2256 if (out
->allocated
< out
->used
+ len
)
2258 for (i
= 0; i
< len
; i
++)
2259 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2264 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2265 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2267 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2271 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2272 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2273 x_scale
= ft_face
->size
->metrics
.x_scale
;
2274 y_scale
= ft_face
->size
->metrics
.y_scale
;
2276 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2277 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2281 if (! otfg
->glyph_id
)
2283 switch (otfg
->positioning_type
)
2287 case 1: /* Single */
2290 int format
= otfg
->f
.f1
.format
;
2292 if (format
& OTF_XPlacement
)
2294 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2295 if (format
& OTF_XPlaDevice
)
2297 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2298 if (format
& OTF_YPlacement
)
2300 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2301 if (format
& OTF_YPlaDevice
)
2303 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2304 if (format
& OTF_XAdvance
)
2306 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2307 if (format
& OTF_XAdvDevice
)
2309 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2310 if (format
& OTF_YAdvance
)
2312 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2313 if (format
& OTF_YAdvDevice
)
2315 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2316 adjustment
[i
].set
= 1;
2319 case 3: /* Cursive */
2320 /* Not yet supported. */
2322 case 4: /* Mark-to-Base */
2323 case 5: /* Mark-to-Ligature */
2327 goto label_adjust_anchor
;
2328 default: /* i.e. case 6 Mark-to-Mark */
2333 label_adjust_anchor
:
2335 int base_x
, base_y
, mark_x
, mark_y
;
2336 int this_from
, this_to
;
2338 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2339 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2340 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2341 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2343 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2344 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2345 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2346 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2347 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2348 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2349 adjustment
[i
].xoff
= (base_x
- mark_x
);
2350 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2351 adjustment
[i
].back
= (g
- prev
);
2352 adjustment
[i
].xadv
= 0;
2353 adjustment
[i
].advance_is_absolute
= 1;
2354 adjustment
[i
].set
= 1;
2355 this_from
= g
->from
;
2357 for (j
= 0; prev
+ j
< g
; j
++)
2359 if (this_from
> prev
[j
].from
)
2360 this_from
= prev
[j
].from
;
2361 if (this_to
< prev
[j
].to
)
2362 this_to
= prev
[j
].to
;
2364 for (; prev
<= g
; prev
++)
2366 prev
->from
= this_from
;
2371 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2373 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2382 if (out
->allocated
< out
->used
+ len
)
2384 font
->get_metrics (font
, in
, from
, to
);
2385 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2386 sizeof (MFLTGlyph
) * len
);
2391 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2393 static MFLTGlyphString gstring
;
2395 static bool m17n_flt_initialized
;
2398 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2399 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2401 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2403 struct MFLTFontFT flt_font_ft
;
2405 bool with_variation_selector
= 0;
2407 if (! m17n_flt_initialized
)
2410 #ifdef M17N_FLT_USE_NEW_FEATURE
2411 mflt_enable_new_feature
= 1;
2412 mflt_try_otf
= ftfont_try_otf
;
2413 #endif /* M17N_FLT_USE_NEW_FEATURE */
2414 m17n_flt_initialized
= 1;
2417 for (i
= 0; i
< len
; i
++)
2419 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2424 c
= LGLYPH_CHAR (g
);
2425 if (CHAR_VARIATION_SELECTOR_P (c
))
2426 with_variation_selector
= 1;
2430 lint_assume (len
<= STRING_BYTES_BOUND
);
2432 if (with_variation_selector
)
2434 setup_otf_gstring (len
);
2435 for (i
= 0; i
< len
; i
++)
2437 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2439 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2440 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2441 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2443 OTF_drive_cmap (otf
, &otf_gstring
);
2444 for (i
= 0; i
< otf_gstring
.used
; i
++)
2446 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2447 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2448 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2450 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2451 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2452 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2454 if (len
> otf_gstring
.used
)
2456 len
= otf_gstring
.used
;
2457 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2461 if (INT_MAX
/ 2 < len
)
2462 memory_full (SIZE_MAX
);
2464 if (gstring
.allocated
== 0)
2466 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2467 gstring
.glyphs
= xnmalloc (len
* 2, sizeof *gstring
.glyphs
);
2468 gstring
.allocated
= len
* 2;
2470 else if (gstring
.allocated
< len
* 2)
2472 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2473 sizeof *gstring
.glyphs
);
2474 gstring
.allocated
= len
* 2;
2476 memset (gstring
.glyphs
, 0, len
* sizeof *gstring
.glyphs
);
2477 for (i
= 0; i
< len
; i
++)
2479 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2481 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2482 if (with_variation_selector
)
2484 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2485 gstring
.glyphs
[i
].encoded
= 1;
2493 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2496 flt_font_ft
.flt_font
.family
= Mnil
;
2498 flt_font_ft
.flt_font
.family
2499 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2501 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2502 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2503 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2504 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2505 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2506 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2507 flt_font_ft
.flt_font
.internal
= NULL
;
2508 flt_font_ft
.font
= font
;
2509 flt_font_ft
.ft_face
= ft_face
;
2510 flt_font_ft
.otf
= otf
;
2511 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2513 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2514 /* A little bit ad hoc. Perhaps, shaper must get script and
2515 language information, and select a proper flt for them
2517 flt
= mflt_get (msymbol ("combining"));
2518 for (i
= 0; i
< 3; i
++)
2520 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2523 if (INT_MAX
/ 2 < gstring
.allocated
)
2524 memory_full (SIZE_MAX
);
2525 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2526 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2527 gstring
.allocated
*= 2;
2529 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2531 for (i
= 0; i
< gstring
.used
; i
++)
2533 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2535 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2536 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2539 for (i
= 0; i
< gstring
.used
; i
++)
2541 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2542 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2546 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2547 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2549 LGLYPH_SET_FROM (lglyph
, g
->from
);
2550 LGLYPH_SET_TO (lglyph
, g
->to
);
2551 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2552 LGLYPH_SET_CODE (lglyph
, g
->code
);
2553 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2554 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2555 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2556 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2557 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2562 vec
= Fmake_vector (make_number (3), Qnil
);
2563 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2564 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2565 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2566 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2569 return make_number (i
);
2573 ftfont_shape (Lisp_Object lgstring
)
2576 struct ftfont_info
*ftfont_info
;
2579 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2580 ftfont_info
= (struct ftfont_info
*) font
;
2581 otf
= ftfont_get_otf (ftfont_info
);
2583 return make_number (0);
2584 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2585 &ftfont_info
->matrix
);
2588 #endif /* HAVE_M17N_FLT */
2590 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2593 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2595 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2596 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2600 return OTF_get_variation_glyphs (otf
, c
, variations
);
2603 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2604 #endif /* HAVE_LIBOTF */
2607 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2611 #ifdef FC_FONTFORMAT
2614 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2616 if (strcmp ((char *) str
, "TrueType") == 0)
2617 return intern ("truetype");
2618 if (strcmp ((char *) str
, "Type 1") == 0)
2619 return intern ("type1");
2620 if (strcmp ((char *) str
, "PCF") == 0)
2621 return intern ("pcf");
2622 if (strcmp ((char *) str
, "BDF") == 0)
2623 return intern ("bdf");
2625 #endif /* FC_FONTFORMAT */
2626 if (STRINGP (filename
))
2628 int len
= SBYTES (filename
);
2632 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2633 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2634 return intern ("truetype");
2635 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2636 return intern ("type1");
2637 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2638 return intern ("pcf");
2639 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2640 return intern ("bdf");
2643 return intern ("unknown");
2646 static const char *const ftfont_booleans
[] = {
2659 static const char *const ftfont_non_booleans
[] = {
2691 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2693 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2698 syms_of_ftfont (void)
2700 DEFSYM (Qfreetype
, "freetype");
2701 DEFSYM (Qmonospace
, "monospace");
2702 DEFSYM (Qsans_serif
, "sans-serif");
2703 DEFSYM (Qserif
, "serif");
2704 DEFSYM (Qmono
, "mono");
2705 DEFSYM (Qsans
, "sans");
2706 DEFSYM (Qsans__serif
, "sans serif");
2708 staticpro (&freetype_font_cache
);
2709 freetype_font_cache
= Fcons (Qt
, Qnil
);
2711 staticpro (&ftfont_generic_family_list
);
2712 ftfont_generic_family_list
2713 = Fcons (Fcons (Qmonospace
, Qt
),
2714 Fcons (Fcons (Qsans_serif
, Qt
),
2715 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2717 staticpro (&ft_face_cache
);
2718 ft_face_cache
= Qnil
;
2720 ftfont_driver
.type
= Qfreetype
;
2721 register_font_driver (&ftfont_driver
, NULL
);