1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006-2011 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 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
)
166 if (FcPatternGetString (p
, FC_STYLE
, 0, (FcChar8
**) &str
) != FcResultMatch
)
168 for (end
= str
; *end
&& *end
!= ' '; end
++);
171 char *p
= alloca (end
- str
+ 1);
172 memcpy (p
, str
, end
- str
);
174 end
= p
+ (end
- str
);
177 if (xstrcasecmp (str
, "Regular") == 0
178 || xstrcasecmp (str
, "Bold") == 0
179 || xstrcasecmp (str
, "Oblique") == 0
180 || xstrcasecmp (str
, "Italic") == 0)
182 adstyle
= font_intern_prop (str
, end
- str
, 1);
183 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
189 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
191 Lisp_Object key
, cache
, entity
;
198 if (FcPatternGetString (p
, FC_FILE
, 0, (FcChar8
**) &file
) != FcResultMatch
)
200 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &index
) != FcResultMatch
)
203 key
= Fcons (make_unibyte_string ((char *) file
, strlen ((char *) file
)),
204 make_number (index
));
205 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
206 entity
= XCAR (cache
);
209 Lisp_Object val
= font_make_entity ();
212 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
213 ASET (val
, i
, AREF (entity
, i
));
216 entity
= font_make_entity ();
217 XSETCAR (cache
, entity
);
219 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
220 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
222 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
223 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
224 if (FcPatternGetString (p
, FC_FAMILY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
225 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
226 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
228 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
229 numeric
= FC_WEIGHT_MEDIUM
;
230 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
232 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
235 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
237 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
239 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
241 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
243 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
246 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
247 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
248 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
249 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
252 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
254 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
257 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
258 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
262 /* As this font is not scalable, parhaps this is a BDF or PCF
266 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
267 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
268 && FT_New_Face (ft_library
, file
, index
, &ft_face
) == 0)
272 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
273 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
274 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
275 FT_Done_Face (ft_face
);
279 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
280 font_put_extra (entity
, QCfont_entity
, key
);
285 static Lisp_Object ftfont_generic_family_list
;
288 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
295 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
296 if (EQ (family
, Qmono
))
298 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
299 family
= Qsans_serif
;
300 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
303 if (! EQ (XCDR (slot
), Qt
))
305 pattern
= FcPatternDuplicate (pattern
);
308 FcPatternDel (pattern
, FC_FOUNDRY
);
309 FcPatternDel (pattern
, FC_FAMILY
);
310 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
311 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
313 /* This is to avoid the effect of locale. */
314 langset
= FcLangSetCreate ();
315 FcLangSetAdd (langset
, "en");
316 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
317 FcLangSetDestroy (langset
);
319 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
320 FcDefaultSubstitute (pattern
);
321 match
= FcFontMatch (NULL
, pattern
, &result
);
326 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
327 family
= intern ((char *) fam
);
331 XSETCDR (slot
, family
);
332 if (match
) FcPatternDestroy (match
);
334 if (pattern
) FcPatternDestroy (pattern
);
338 struct ftfont_cache_data
341 FcCharSet
*fc_charset
;
345 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
347 Lisp_Object cache
, val
, entity
;
348 struct ftfont_cache_data
*cache_data
;
350 if (FONT_ENTITY_P (key
))
353 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
354 xassert (CONSP (val
));
360 if (NILP (ft_face_cache
))
363 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
366 if (NILP (ft_face_cache
))
372 ft_face_cache
= Fmake_hash_table (2, args
);
374 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
375 cache_data
->ft_face
= NULL
;
376 cache_data
->fc_charset
= NULL
;
377 val
= make_save_value (NULL
, 0);
378 XSAVE_VALUE (val
)->integer
= 0;
379 XSAVE_VALUE (val
)->pointer
= cache_data
;
380 cache
= Fcons (Qnil
, val
);
381 Fputhash (key
, cache
, ft_face_cache
);
386 cache_data
= XSAVE_VALUE (val
)->pointer
;
389 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
392 if (cache_for
== FTFONT_CACHE_FOR_FACE
393 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
395 char *filename
= SSDATA (XCAR (key
));
396 int index
= XINT (XCDR (key
));
398 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
401 && FT_Init_FreeType (&ft_library
) != 0)
403 if (FT_New_Face (ft_library
, filename
, index
, &cache_data
->ft_face
)
409 FcPattern
*pat
= NULL
;
410 FcFontSet
*fontset
= NULL
;
411 FcObjectSet
*objset
= NULL
;
412 FcCharSet
*charset
= NULL
;
414 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
415 FC_INDEX
, FcTypeInteger
, index
, NULL
);
418 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
421 fontset
= FcFontList (NULL
, pat
, objset
);
424 if (fontset
&& fontset
->nfont
> 0
425 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
428 cache_data
->fc_charset
= FcCharSetCopy (charset
);
430 cache_data
->fc_charset
= FcCharSetCreate ();
434 FcFontSetDestroy (fontset
);
436 FcObjectSetDestroy (objset
);
438 FcPatternDestroy (pat
);
445 ftfont_get_fc_charset (Lisp_Object entity
)
447 Lisp_Object val
, cache
;
448 struct ftfont_cache_data
*cache_data
;
450 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
452 cache_data
= XSAVE_VALUE (val
)->pointer
;
453 return cache_data
->fc_charset
;
458 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
462 if (ftfont_info
->otf
)
463 return ftfont_info
->otf
;
464 if (! ftfont_info
->maybe_otf
)
466 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
467 if (! otf
|| OTF_get_table (otf
, "head") < 0)
471 ftfont_info
->maybe_otf
= 0;
474 ftfont_info
->otf
= otf
;
477 #endif /* HAVE_LIBOTF */
479 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
480 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
481 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
482 static Lisp_Object
ftfont_list_family (Lisp_Object
);
483 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
484 static void ftfont_close (FRAME_PTR
, struct font
*);
485 static int ftfont_has_char (Lisp_Object
, int);
486 static unsigned ftfont_encode_char (struct font
*, int);
487 static int ftfont_text_extents (struct font
*, unsigned *, int,
488 struct font_metrics
*);
489 static int ftfont_get_bitmap (struct font
*, unsigned,
490 struct font_bitmap
*, int);
491 static int ftfont_anchor_point (struct font
*, unsigned, int,
493 static Lisp_Object
ftfont_otf_capability (struct font
*);
494 static Lisp_Object
ftfont_shape (Lisp_Object
);
496 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
497 static int ftfont_variation_glyphs (struct font
*, int c
,
498 unsigned variations
[256]);
499 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
501 struct font_driver ftfont_driver
=
504 0, /* case insensitive */
509 NULL
, /* free_entity */
512 /* We can't draw a text without device dependent functions. */
513 NULL
, /* prepare_face */
514 NULL
, /* done_face */
518 /* We can't draw a text without device dependent functions. */
521 NULL
, /* get_bitmap */
522 NULL
, /* free_bitmap */
523 NULL
, /* get_outline */
526 ftfont_otf_capability
,
527 #else /* not HAVE_LIBOTF */
529 #endif /* not HAVE_LIBOTF */
530 NULL
, /* otf_drive */
531 NULL
, /* start_for_frame */
532 NULL
, /* end_for_frame */
533 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
535 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
537 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
540 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
541 ftfont_variation_glyphs
,
546 ftfont_filter_properties
, /* filter_properties */
550 ftfont_get_cache (FRAME_PTR f
)
552 return freetype_font_cache
;
556 ftfont_get_charset (Lisp_Object registry
)
558 char *str
= SSDATA (SYMBOL_NAME (registry
));
559 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
563 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
567 else if (str
[i
] == '*')
574 regexp
= make_unibyte_string (re
, j
);
575 for (i
= 0; fc_charset_table
[i
].name
; i
++)
576 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
578 if (! fc_charset_table
[i
].name
)
580 if (! fc_charset_table
[i
].fc_charset
)
582 FcCharSet
*charset
= FcCharSetCreate ();
583 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
587 for (j
= 0; uniquifier
[j
]; j
++)
588 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
590 FcCharSetDestroy (charset
);
593 fc_charset_table
[i
].fc_charset
= charset
;
601 unsigned int script_tag
, langsys_tag
;
603 unsigned int *features
[2];
606 #define OTF_SYM_TAG(SYM, TAG) \
608 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
609 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
612 #define OTF_TAG_STR(TAG, P) \
614 (P)[0] = (char) (TAG >> 24); \
615 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
616 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
617 (P)[3] = (char) (TAG & 0xFF); \
621 #define OTF_TAG_SYM(SYM, TAG) \
625 OTF_TAG_STR (TAG, str); \
626 (SYM) = font_intern_prop (str, 4, 1); \
630 static struct OpenTypeSpec
*
631 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
633 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
639 spec
->script
= XCAR (otf_spec
);
640 if (! NILP (spec
->script
))
642 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
643 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
644 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
645 spec
->script
= XCDR (val
);
650 spec
->script_tag
= 0x44464C54; /* "DFLT" */
651 otf_spec
= XCDR (otf_spec
);
652 spec
->langsys_tag
= 0;
653 if (! NILP (otf_spec
))
655 val
= XCAR (otf_spec
);
657 OTF_SYM_TAG (val
, spec
->langsys_tag
);
658 otf_spec
= XCDR (otf_spec
);
660 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
661 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
665 val
= XCAR (otf_spec
);
669 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
670 if (! spec
->features
[i
])
672 if (i
> 0 && spec
->features
[0])
673 free (spec
->features
[0]);
677 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
679 if (NILP (XCAR (val
)))
685 OTF_SYM_TAG (XCAR (val
), tag
);
686 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
689 spec
->nfeatures
[i
] = j
;
695 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
697 Lisp_Object tmp
, extra
;
698 FcPattern
*pattern
= NULL
;
699 FcCharSet
*charset
= NULL
;
700 FcLangSet
*langset
= NULL
;
704 Lisp_Object script
= Qnil
;
705 Lisp_Object registry
;
708 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
710 /* Fontconfig doesn't support reverse-italic/obligue. */
713 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
714 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
715 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
716 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
719 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
721 || EQ (registry
, Qascii_0
)
722 || EQ (registry
, Qiso10646_1
)
723 || EQ (registry
, Qunicode_bmp
))
729 fc_charset_idx
= ftfont_get_charset (registry
);
730 if (fc_charset_idx
< 0)
732 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
733 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
734 lang
= (FcChar8
*) *langname
;
737 langset
= FcLangSetCreate ();
740 FcLangSetAdd (langset
, lang
);
745 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
746 CONSP (extra
); extra
= XCDR (extra
))
748 Lisp_Object key
, val
;
750 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
756 else if (EQ (key
, QClang
))
759 langset
= FcLangSetCreate ();
764 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
768 for (; CONSP (val
); val
= XCDR (val
))
769 if (SYMBOLP (XCAR (val
))
770 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
773 else if (EQ (key
, QCotf
))
777 *otspec
= ftfont_get_open_type_spec (val
);
780 strcat (otlayout
, "otlayout:");
781 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
782 script
= (*otspec
)->script
;
785 else if (EQ (key
, QCscript
))
787 else if (EQ (key
, QCscalable
))
788 scalable
= ! NILP (val
);
791 if (! NILP (script
) && ! charset
)
793 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
795 if (CONSP (chars
) && CONSP (CDR (chars
)))
797 charset
= FcCharSetCreate ();
800 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
801 if (CHARACTERP (XCAR (chars
))
802 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
807 pattern
= FcPatternCreate ();
810 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
812 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
814 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
816 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
819 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
822 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
825 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
828 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
834 /* We come here because of unexpected error in fontconfig API call
835 (usually insufficient memory). */
838 FcPatternDestroy (pattern
);
843 if ((*otspec
)->nfeatures
[0] > 0)
844 free ((*otspec
)->features
[0]);
845 if ((*otspec
)->nfeatures
[1] > 0)
846 free ((*otspec
)->features
[1]);
852 if (langset
) FcLangSetDestroy (langset
);
853 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
858 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
860 Lisp_Object val
= Qnil
, family
, adstyle
;
863 FcFontSet
*fontset
= NULL
;
864 FcObjectSet
*objset
= NULL
;
866 Lisp_Object chars
= Qnil
;
868 char otlayout
[15]; /* For "otlayout:XXXX" */
869 struct OpenTypeSpec
*otspec
= NULL
;
871 const char *langname
= NULL
;
873 if (! fc_initialized
)
879 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
882 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
884 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
887 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
888 if (CONSP (val
) && VECTORP (XCDR (val
)))
893 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
894 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
895 family
= AREF (spec
, FONT_FAMILY_INDEX
);
898 Lisp_Object resolved
;
900 resolved
= ftfont_resolve_generic_family (family
, pattern
);
901 if (! NILP (resolved
))
903 FcPatternDel (pattern
, FC_FAMILY
);
904 if (! FcPatternAddString (pattern
, FC_FAMILY
,
905 SYMBOL_FcChar8 (resolved
)))
909 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
910 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
912 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
913 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
914 FC_STYLE
, FC_FILE
, FC_INDEX
,
917 #endif /* FC_CAPABILITY */
925 FcObjectSetAdd (objset
, FC_CHARSET
);
927 fontset
= FcFontList (NULL
, pattern
, objset
);
928 if (! fontset
|| fontset
->nfont
== 0)
931 /* Need fix because this finds any fonts. */
932 if (fontset
->nfont
== 0 && ! NILP (family
))
934 /* Try maching with configuration. For instance, the
935 configuration may specify "Nimbus Mono L" as an alias of
937 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
938 SYMBOL_FcChar8 (family
), NULL
);
941 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
944 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
947 FcPatternDel (pattern
, FC_FAMILY
);
948 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
949 FcFontSetDestroy (fontset
);
950 fontset
= FcFontList (NULL
, pattern
, objset
);
951 if (fontset
&& fontset
->nfont
> 0)
957 for (i
= 0; i
< fontset
->nfont
; i
++)
965 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
976 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
978 || ! strstr ((char *) this, otlayout
))
981 #endif /* FC_CAPABILITY */
988 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
991 otf
= OTF_open ((char *) file
);
994 if (OTF_check_features (otf
, 1,
995 otspec
->script_tag
, otspec
->langsys_tag
,
997 otspec
->nfeatures
[0]) != 1
998 || OTF_check_features (otf
, 0,
999 otspec
->script_tag
, otspec
->langsys_tag
,
1000 otspec
->features
[1],
1001 otspec
->nfeatures
[1]) != 1)
1004 #endif /* HAVE_LIBOTF */
1005 if (VECTORP (chars
))
1009 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1012 for (j
= 0; j
< ASIZE (chars
); j
++)
1013 if (NATNUMP (AREF (chars
, j
))
1014 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1016 if (j
== ASIZE (chars
))
1019 if (! NILP (adstyle
) || langname
)
1021 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1023 if (! NILP (adstyle
)
1024 && (NILP (this_adstyle
)
1025 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1026 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1029 && ! NILP (this_adstyle
)
1030 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1033 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1034 AREF (spec
, FONT_EXTRA_INDEX
));
1035 if (! NILP (entity
))
1036 val
= Fcons (entity
, val
);
1038 val
= Fnreverse (val
);
1042 /* We come here because of unexpected error in fontconfig API call
1043 (usually insufficient memory). */
1047 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1048 if (objset
) FcObjectSetDestroy (objset
);
1049 if (fontset
) FcFontSetDestroy (fontset
);
1050 if (pattern
) FcPatternDestroy (pattern
);
1055 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1057 Lisp_Object entity
= Qnil
;
1058 FcPattern
*pattern
, *match
= NULL
;
1060 char otlayout
[15]; /* For "otlayout:XXXX" */
1061 struct OpenTypeSpec
*otspec
= NULL
;
1062 const char *langname
= NULL
;
1064 if (! fc_initialized
)
1070 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1074 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1078 value
.type
= FcTypeDouble
;
1079 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1080 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1082 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1084 FcDefaultSubstitute (pattern
);
1085 match
= FcFontMatch (NULL
, pattern
, &result
);
1088 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1089 FcPatternDestroy (match
);
1090 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1091 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1092 ftfont_generic_family_list
))
1093 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1094 AREF (entity
, FONT_FAMILY_INDEX
))))
1098 FcPatternDestroy (pattern
);
1100 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1105 ftfont_list_family (Lisp_Object frame
)
1107 Lisp_Object list
= Qnil
;
1108 FcPattern
*pattern
= NULL
;
1109 FcFontSet
*fontset
= NULL
;
1110 FcObjectSet
*objset
= NULL
;
1113 if (! fc_initialized
)
1119 pattern
= FcPatternCreate ();
1122 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1125 fontset
= FcFontList (NULL
, pattern
, objset
);
1129 for (i
= 0; i
< fontset
->nfont
; i
++)
1131 FcPattern
*pat
= fontset
->fonts
[i
];
1134 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1135 list
= Fcons (intern ((char *) str
), list
);
1139 if (objset
) FcObjectSetDestroy (objset
);
1140 if (fontset
) FcFontSetDestroy (fontset
);
1141 if (pattern
) FcPatternDestroy (pattern
);
1148 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1150 struct ftfont_info
*ftfont_info
;
1152 struct ftfont_cache_data
*cache_data
;
1156 Lisp_Object val
, filename
, index
, cache
, font_object
;
1163 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1167 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1170 filename
= XCAR (val
);
1173 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1174 ft_face
= cache_data
->ft_face
;
1175 if (XSAVE_VALUE (val
)->integer
> 0)
1177 /* FT_Face in this cache is already used by the different size. */
1178 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1180 if (FT_Activate_Size (ft_size
) != 0)
1182 FT_Done_Size (ft_size
);
1186 XSAVE_VALUE (val
)->integer
++;
1187 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1190 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1192 if (XSAVE_VALUE (val
)->integer
== 0)
1193 FT_Done_Face (ft_face
);
1197 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1198 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1199 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1201 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1202 len
= font_unparse_fcname (entity
, size
, name
, 256);
1204 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1206 ASET (font_object
, FONT_FULLNAME_INDEX
,
1207 AREF (font_object
, FONT_NAME_INDEX
));
1208 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1209 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1210 font
= XFONT_OBJECT (font_object
);
1211 ftfont_info
= (struct ftfont_info
*) font
;
1212 ftfont_info
->ft_size
= ft_face
->size
;
1213 ftfont_info
->index
= XINT (index
);
1215 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1216 ftfont_info
->otf
= NULL
;
1217 #endif /* HAVE_LIBOTF */
1218 /* This means that there's no need of transformation. */
1219 ftfont_info
->matrix
.xx
= 0;
1220 font
->pixel_size
= size
;
1221 font
->driver
= &ftfont_driver
;
1222 font
->encoding_charset
= font
->repertory_charset
= -1;
1224 upEM
= ft_face
->units_per_EM
;
1225 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1226 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1229 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1230 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1231 font
->height
= ft_face
->height
* size
/ upEM
;
1235 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1236 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1237 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1239 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1240 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1242 spacing
= FC_PROPORTIONAL
;
1243 if (spacing
!= FC_PROPORTIONAL
1245 && spacing
!= FC_DUAL
1246 #endif /* FC_DUAL */
1248 font
->min_width
= font
->average_width
= font
->space_width
1249 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1250 : ft_face
->size
->metrics
.max_advance
>> 6);
1255 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1256 for (i
= 32, n
= 0; i
< 127; i
++)
1257 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1259 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1262 && (! font
->min_width
|| font
->min_width
> this_width
))
1263 font
->min_width
= this_width
;
1265 font
->space_width
= this_width
;
1266 font
->average_width
+= this_width
;
1270 font
->average_width
/= n
;
1273 font
->baseline_offset
= 0;
1274 font
->relative_compose
= 0;
1275 font
->default_ascent
= 0;
1276 font
->vertical_centering
= 0;
1279 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1280 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1284 font
->underline_position
= -1;
1285 font
->underline_thickness
= 0;
1292 ftfont_close (FRAME_PTR f
, struct font
*font
)
1294 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1295 Lisp_Object val
, cache
;
1297 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1298 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1299 xassert (CONSP (cache
));
1301 (XSAVE_VALUE (val
)->integer
)--;
1302 if (XSAVE_VALUE (val
)->integer
== 0)
1304 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1306 FT_Done_Face (cache_data
->ft_face
);
1308 if (ftfont_info
->otf
)
1309 OTF_close (ftfont_info
->otf
);
1311 cache_data
->ft_face
= NULL
;
1314 FT_Done_Size (ftfont_info
->ft_size
);
1318 ftfont_has_char (Lisp_Object font
, int c
)
1320 struct charset
*cs
= NULL
;
1322 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1323 && charset_jisx0208
>= 0)
1324 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1325 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1326 && charset_ksc5601
>= 0)
1327 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1329 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1331 if (FONT_ENTITY_P (font
))
1333 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1335 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1339 struct ftfont_info
*ftfont_info
;
1341 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1342 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1348 ftfont_encode_char (struct font
*font
, int c
)
1350 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1351 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1352 FT_ULong charcode
= c
;
1353 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1355 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1359 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1361 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1362 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1366 if (ftfont_info
->ft_size
!= ft_face
->size
)
1367 FT_Activate_Size (ftfont_info
->ft_size
);
1369 memset (metrics
, 0, sizeof (struct font_metrics
));
1370 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1372 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1374 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1380 metrics
->lbearing
= m
->horiBearingX
>> 6;
1381 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1382 metrics
->ascent
= m
->horiBearingY
>> 6;
1383 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1389 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1390 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1391 if (metrics
->rbearing
1392 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1394 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1395 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1396 metrics
->ascent
= m
->horiBearingY
>> 6;
1397 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1398 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1400 width
+= m
->horiAdvance
>> 6;
1404 width
+= font
->space_width
;
1408 metrics
->width
= width
;
1414 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1416 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1417 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1418 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1420 if (ftfont_info
->ft_size
!= ft_face
->size
)
1421 FT_Activate_Size (ftfont_info
->ft_size
);
1422 if (bits_per_pixel
== 1)
1424 #ifdef FT_LOAD_TARGET_MONO
1425 load_flags
|= FT_LOAD_TARGET_MONO
;
1427 load_flags
|= FT_LOAD_MONOCHROME
;
1430 else if (bits_per_pixel
!= 8)
1431 /* We don't support such a rendering. */
1434 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1436 bitmap
->bits_per_pixel
1437 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1438 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1439 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1440 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1442 if (bitmap
->bits_per_pixel
< 0)
1443 /* We don't suport that kind of pixel mode. */
1445 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1446 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1447 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1448 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1449 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1450 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1451 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1452 bitmap
->extra
= NULL
;
1458 ftfont_anchor_point (struct font
*font
, unsigned int code
, int index
, int *x
, int *y
)
1460 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1461 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1463 if (ftfont_info
->ft_size
!= ft_face
->size
)
1464 FT_Activate_Size (ftfont_info
->ft_size
);
1465 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1467 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1469 if (index
>= ft_face
->glyph
->outline
.n_points
)
1471 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
1472 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
1479 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1481 Lisp_Object scripts
, langsyses
, features
, sym
;
1484 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1486 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1488 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1490 OTF_LangSys
*otf_langsys
;
1493 otf_langsys
= otf_script
->LangSys
+ j
;
1494 else if (otf_script
->DefaultLangSysOffset
)
1495 otf_langsys
= &otf_script
->DefaultLangSys
;
1499 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1501 l
= otf_langsys
->FeatureIndex
[k
];
1502 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1504 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1505 features
= Fcons (sym
, features
);
1508 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1511 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1514 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1515 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1523 ftfont_otf_capability (struct font
*font
)
1525 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1526 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1527 Lisp_Object gsub_gpos
;
1531 gsub_gpos
= Fcons (Qnil
, Qnil
);
1532 if (OTF_get_table (otf
, "GSUB") == 0
1533 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1534 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1535 if (OTF_get_table (otf
, "GPOS") == 0
1536 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1537 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1541 #ifdef HAVE_M17N_FLT
1543 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1544 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1545 /* We can use the new feature of libotf and m17n-flt to handle the
1546 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1547 some Agian scripts. */
1548 #define M17N_FLT_USE_NEW_FEATURE
1561 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1564 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1565 FT_Face ft_face
= flt_font_ft
->ft_face
;
1568 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1571 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1573 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1579 /* Operators for 26.6 fixed fractional pixel format */
1581 #define FLOOR(x) ((x) & -64)
1582 #define CEIL(x) (((x)+63) & -64)
1583 #define ROUND(x) (((x)+32) & -64)
1586 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1589 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1590 FT_Face ft_face
= flt_font_ft
->ft_face
;
1593 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1596 if (g
->code
!= FONT_INVALID_CODE
)
1598 FT_Glyph_Metrics
*m
;
1599 int lbearing
, rbearing
, ascent
, descent
, xadv
;
1601 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1603 m
= &ft_face
->glyph
->metrics
;
1604 if (flt_font_ft
->matrix
)
1609 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1610 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1611 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1612 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1613 for (i
= 0; i
< 4; i
++)
1614 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1615 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1616 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1617 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1618 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1622 g
->lbearing
= FLOOR (m
->horiBearingX
);
1623 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1624 g
->ascent
= CEIL (m
->horiBearingY
);
1625 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1627 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1632 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1633 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1634 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1643 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1645 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1647 #define FEATURE_ANY(IDX) \
1648 (spec->features[IDX] \
1649 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1651 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1652 OTF
*otf
= flt_font_ft
->otf
;
1656 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1657 /* Return 1 iff any of GSUB or GPOS support the script (and language). */
1659 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1661 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1664 for (i
= 0; i
< 2; i
++)
1665 if (! FEATURE_ANY (i
))
1667 if (FEATURE_NONE (i
))
1670 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1675 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1678 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1684 for (n
= 1; spec
->features
[i
][n
]; n
++);
1685 tags
= alloca (sizeof (OTF_Tag
) * n
);
1686 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1688 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1691 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1693 tags
[n
] = spec
->features
[i
][n
];
1695 #ifdef M17N_FLT_USE_NEW_FEATURE
1696 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1697 tags
, n
- negative
) != 1)
1699 #else /* not M17N_FLT_USE_NEW_FEATURE */
1700 if (n
- negative
> 0
1701 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1702 tags
, n
- negative
) != 1)
1704 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1711 #define DEVICE_DELTA(table, size) \
1712 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1713 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1717 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1718 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1720 if (anchor
->AnchorFormat
== 2)
1722 FT_Outline
*outline
;
1723 int ap
= anchor
->f
.f1
.AnchorPoint
;
1725 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1726 outline
= &ft_face
->glyph
->outline
;
1727 if (ap
< outline
->n_points
)
1729 *x
= outline
->points
[ap
].x
<< 6;
1730 *y
= outline
->points
[ap
].y
<< 6;
1733 else if (anchor
->AnchorFormat
== 3)
1735 if (anchor
->f
.f2
.XDeviceTable
.offset
1736 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1737 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1738 if (anchor
->f
.f2
.YDeviceTable
.offset
1739 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1740 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1744 static OTF_GlyphString otf_gstring
;
1747 setup_otf_gstring (int size
)
1749 if (otf_gstring
.size
== 0)
1751 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1752 otf_gstring
.size
= size
;
1754 else if (otf_gstring
.size
< size
)
1756 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1757 sizeof (OTF_Glyph
) * size
);
1758 otf_gstring
.size
= size
;
1760 otf_gstring
.used
= size
;
1761 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1764 #ifdef M17N_FLT_USE_NEW_FEATURE
1766 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1767 #define PACK_OTF_TAG(TAG) \
1768 ((((TAG) & 0x7F000000) >> 3) \
1769 | (((TAG) & 0x7F0000) >> 2) \
1770 | (((TAG) & 0x7F00) >> 1) \
1773 /* Assuming that FONT is an OpenType font, apply OpenType features
1774 specified in SPEC on glyphs between FROM and TO of IN, and record
1775 the lastly applied feature in each glyph of IN. If OUT is not
1776 NULL, append the resulting glyphs to OUT while storing glyph
1777 position adjustment information in ADJUSTMENT. */
1780 ftfont_drive_otf (MFLTFont
*font
,
1782 MFLTGlyphString
*in
,
1785 MFLTGlyphString
*out
,
1786 MFLTGlyphAdjustment
*adjustment
)
1788 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1789 FT_Face ft_face
= flt_font_ft
->ft_face
;
1790 OTF
*otf
= flt_font_ft
->otf
;
1791 int len
= to
- from
;
1794 char script
[5], *langsys
= NULL
;
1795 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1796 OTF_Feature
*features
;
1800 OTF_tag_name (spec
->script
, script
);
1803 langsys
= alloca (5);
1804 OTF_tag_name (spec
->langsys
, langsys
);
1806 for (i
= 0; i
< 2; i
++)
1810 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1812 for (j
= 0; spec
->features
[i
][j
]; j
++);
1814 p
= gsub_features
= alloca (6 * j
);
1816 p
= gpos_features
= alloca (6 * j
);
1817 for (j
= 0; spec
->features
[i
][j
]; j
++)
1819 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1820 *p
++ = '*', *p
++ = ',';
1823 OTF_tag_name (spec
->features
[i
][j
], p
);
1832 setup_otf_gstring (len
);
1833 for (i
= 0; i
< len
; i
++)
1835 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1836 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1839 OTF_drive_gdef (otf
, &otf_gstring
);
1840 gidx
= out
? out
->used
: from
;
1842 if (gsub_features
&& out
)
1844 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1847 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1849 features
= otf
->gsub
->FeatureList
.Feature
;
1850 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1853 int min_from
, max_to
;
1855 int feature_idx
= otfg
->positioning_type
>> 4;
1857 g
= out
->glyphs
+ out
->used
;
1858 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1859 if (g
->code
!= otfg
->glyph_id
)
1862 g
->code
= otfg
->glyph_id
;
1868 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1870 /* OTFG substitutes multiple glyphs in IN. */
1871 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1872 j
<= from
+ otfg
->f
.index
.to
; j
++)
1874 if (min_from
> in
->glyphs
[j
].from
)
1875 min_from
= in
->glyphs
[j
].from
;
1876 if (max_to
< in
->glyphs
[j
].to
)
1877 max_to
= in
->glyphs
[j
].to
;
1884 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1885 tag
= PACK_OTF_TAG (tag
);
1886 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1888 for (i
++, otfg
++; (i
< otf_gstring
.used
1889 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1892 g
= out
->glyphs
+ out
->used
;
1893 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1894 if (g
->code
!= otfg
->glyph_id
)
1897 g
->code
= otfg
->glyph_id
;
1900 feature_idx
= otfg
->positioning_type
>> 4;
1903 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1904 tag
= PACK_OTF_TAG (tag
);
1905 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1911 else if (gsub_features
)
1913 /* Just for checking which features will be applied. */
1914 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1917 features
= otf
->gsub
->FeatureList
.Feature
;
1918 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1921 int feature_idx
= otfg
->positioning_type
>> 4;
1925 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1926 tag
= PACK_OTF_TAG (tag
);
1927 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1929 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1930 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1937 if (out
->allocated
< out
->used
+ len
)
1939 for (i
= 0; i
< len
; i
++)
1940 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1943 if (gpos_features
&& out
)
1945 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1946 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1948 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1951 features
= otf
->gpos
->FeatureList
.Feature
;
1952 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1953 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1954 x_scale
= ft_face
->size
->metrics
.x_scale
;
1955 y_scale
= ft_face
->size
->metrics
.y_scale
;
1957 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1958 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1961 int feature_idx
= otfg
->positioning_type
>> 4;
1965 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1966 tag
= PACK_OTF_TAG (tag
);
1967 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1970 if (! otfg
->glyph_id
)
1972 switch (otfg
->positioning_type
& 0xF)
1976 case 1: /* Single */
1979 int format
= otfg
->f
.f1
.format
;
1981 if (format
& OTF_XPlacement
)
1983 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1984 if (format
& OTF_XPlaDevice
)
1986 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1987 if (format
& OTF_YPlacement
)
1989 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
1990 if (format
& OTF_YPlaDevice
)
1992 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
1993 if (format
& OTF_XAdvance
)
1995 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
1996 if (format
& OTF_XAdvDevice
)
1998 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
1999 if (format
& OTF_YAdvance
)
2001 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2002 if (format
& OTF_YAdvDevice
)
2004 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2005 adjustment
[i
].set
= 1;
2008 case 3: /* Cursive */
2009 /* Not yet supported. */
2011 case 4: /* Mark-to-Base */
2012 case 5: /* Mark-to-Ligature */
2016 goto label_adjust_anchor
;
2017 default: /* i.e. case 6 Mark-to-Mark */
2022 label_adjust_anchor
:
2024 int base_x
, base_y
, mark_x
, mark_y
;
2025 int this_from
, this_to
;
2027 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2028 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2029 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2030 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2032 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2033 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2034 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2035 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2036 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2037 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2038 adjustment
[i
].xoff
= (base_x
- mark_x
);
2039 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2040 adjustment
[i
].back
= (g
- prev
);
2041 adjustment
[i
].xadv
= 0;
2042 adjustment
[i
].advance_is_absolute
= 1;
2043 adjustment
[i
].set
= 1;
2044 this_from
= g
->from
;
2046 for (j
= 0; prev
+ j
< g
; j
++)
2048 if (this_from
> prev
[j
].from
)
2049 this_from
= prev
[j
].from
;
2050 if (this_to
< prev
[j
].to
)
2051 this_to
= prev
[j
].to
;
2053 for (; prev
<= g
; prev
++)
2055 prev
->from
= this_from
;
2060 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2062 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2068 else if (gpos_features
)
2070 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2073 features
= otf
->gpos
->FeatureList
.Feature
;
2074 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2076 if (otfg
->positioning_type
& 0xF)
2078 int feature_idx
= otfg
->positioning_type
>> 4;
2082 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2083 tag
= PACK_OTF_TAG (tag
);
2084 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2086 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2087 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2097 if (out
->allocated
< out
->used
+ len
)
2099 font
->get_metrics (font
, in
, from
, to
);
2100 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2101 sizeof (MFLTGlyph
) * len
);
2107 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2108 MFLTGlyphString
*in
, int from
, int to
)
2110 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2113 #else /* not M17N_FLT_USE_NEW_FEATURE */
2116 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2118 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2120 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2121 FT_Face ft_face
= flt_font_ft
->ft_face
;
2122 OTF
*otf
= flt_font_ft
->otf
;
2123 int len
= to
- from
;
2126 char script
[5], *langsys
= NULL
;
2127 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2131 OTF_tag_name (spec
->script
, script
);
2134 langsys
= alloca (5);
2135 OTF_tag_name (spec
->langsys
, langsys
);
2137 for (i
= 0; i
< 2; i
++)
2141 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2143 for (j
= 0; spec
->features
[i
][j
]; j
++);
2145 p
= gsub_features
= alloca (6 * j
);
2147 p
= gpos_features
= alloca (6 * j
);
2148 for (j
= 0; spec
->features
[i
][j
]; j
++)
2150 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2151 *p
++ = '*', *p
++ = ',';
2154 OTF_tag_name (spec
->features
[i
][j
], p
);
2163 setup_otf_gstring (len
);
2164 for (i
= 0; i
< len
; i
++)
2166 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2167 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2170 OTF_drive_gdef (otf
, &otf_gstring
);
2175 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2178 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2180 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2183 int min_from
, max_to
;
2186 g
= out
->glyphs
+ out
->used
;
2187 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2188 if (g
->code
!= otfg
->glyph_id
)
2191 g
->code
= otfg
->glyph_id
;
2197 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2199 /* OTFG substitutes multiple glyphs in IN. */
2200 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2201 j
<= from
+ otfg
->f
.index
.to
; j
++)
2203 if (min_from
> in
->glyphs
[j
].from
)
2204 min_from
= in
->glyphs
[j
].from
;
2205 if (max_to
< in
->glyphs
[j
].to
)
2206 max_to
= in
->glyphs
[j
].to
;
2211 for (i
++, otfg
++; (i
< otf_gstring
.used
2212 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2215 g
= out
->glyphs
+ out
->used
;
2216 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2217 if (g
->code
!= otfg
->glyph_id
)
2220 g
->code
= otfg
->glyph_id
;
2229 if (out
->allocated
< out
->used
+ len
)
2231 for (i
= 0; i
< len
; i
++)
2232 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2237 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2238 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2240 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2244 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2245 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2246 x_scale
= ft_face
->size
->metrics
.x_scale
;
2247 y_scale
= ft_face
->size
->metrics
.y_scale
;
2249 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2250 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2254 if (! otfg
->glyph_id
)
2256 switch (otfg
->positioning_type
)
2260 case 1: /* Single */
2263 int format
= otfg
->f
.f1
.format
;
2265 if (format
& OTF_XPlacement
)
2267 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2268 if (format
& OTF_XPlaDevice
)
2270 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2271 if (format
& OTF_YPlacement
)
2273 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2274 if (format
& OTF_YPlaDevice
)
2276 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2277 if (format
& OTF_XAdvance
)
2279 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2280 if (format
& OTF_XAdvDevice
)
2282 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2283 if (format
& OTF_YAdvance
)
2285 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2286 if (format
& OTF_YAdvDevice
)
2288 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2289 adjustment
[i
].set
= 1;
2292 case 3: /* Cursive */
2293 /* Not yet supported. */
2295 case 4: /* Mark-to-Base */
2296 case 5: /* Mark-to-Ligature */
2300 goto label_adjust_anchor
;
2301 default: /* i.e. case 6 Mark-to-Mark */
2306 label_adjust_anchor
:
2308 int base_x
, base_y
, mark_x
, mark_y
;
2309 int this_from
, this_to
;
2311 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2312 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2313 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2314 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2316 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2317 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2318 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2319 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2320 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2321 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2322 adjustment
[i
].xoff
= (base_x
- mark_x
);
2323 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2324 adjustment
[i
].back
= (g
- prev
);
2325 adjustment
[i
].xadv
= 0;
2326 adjustment
[i
].advance_is_absolute
= 1;
2327 adjustment
[i
].set
= 1;
2328 this_from
= g
->from
;
2330 for (j
= 0; prev
+ j
< g
; j
++)
2332 if (this_from
> prev
[j
].from
)
2333 this_from
= prev
[j
].from
;
2334 if (this_to
< prev
[j
].to
)
2335 this_to
= prev
[j
].to
;
2337 for (; prev
<= g
; prev
++)
2339 prev
->from
= this_from
;
2344 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2346 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2355 if (out
->allocated
< out
->used
+ len
)
2357 font
->get_metrics (font
, in
, from
, to
);
2358 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2359 sizeof (MFLTGlyph
) * len
);
2364 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2366 static MFLTGlyphString gstring
;
2368 static int m17n_flt_initialized
;
2371 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2372 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2374 EMACS_UINT len
= LGSTRING_GLYPH_LEN (lgstring
);
2376 struct MFLTFontFT flt_font_ft
;
2378 int with_variation_selector
= 0;
2380 if (! m17n_flt_initialized
)
2383 #ifdef M17N_FLT_USE_NEW_FEATURE
2384 mflt_enable_new_feature
= 1;
2385 mflt_try_otf
= ftfont_try_otf
;
2386 #endif /* M17N_FLT_USE_NEW_FEATURE */
2387 m17n_flt_initialized
= 1;
2390 for (i
= 0; i
< len
; i
++)
2392 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2397 c
= LGLYPH_CHAR (g
);
2398 if (CHAR_VARIATION_SELECTOR_P (c
))
2399 with_variation_selector
++;
2402 if (with_variation_selector
)
2404 setup_otf_gstring (len
);
2405 for (i
= 0; i
< len
; i
++)
2407 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2409 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2410 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2411 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2413 OTF_drive_cmap (otf
, &otf_gstring
);
2414 for (i
= 0; i
< otf_gstring
.used
; i
++)
2416 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2417 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2418 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2420 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2421 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2422 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2424 if (len
> otf_gstring
.used
)
2426 len
= otf_gstring
.used
;
2427 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2431 if (gstring
.allocated
== 0)
2433 gstring
.allocated
= len
* 2;
2434 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2435 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2437 else if (gstring
.allocated
< len
* 2)
2439 gstring
.allocated
= len
* 2;
2440 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2441 sizeof (MFLTGlyph
) * gstring
.allocated
);
2443 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2444 for (i
= 0; i
< len
; i
++)
2446 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2448 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2449 if (with_variation_selector
)
2451 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2452 gstring
.glyphs
[i
].encoded
= 1;
2460 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2463 flt_font_ft
.flt_font
.family
= Mnil
;
2465 flt_font_ft
.flt_font
.family
2466 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2468 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2469 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2470 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2471 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2472 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2473 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2474 flt_font_ft
.flt_font
.internal
= NULL
;
2475 flt_font_ft
.font
= font
;
2476 flt_font_ft
.ft_face
= ft_face
;
2477 flt_font_ft
.otf
= otf
;
2478 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2480 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2481 /* A little bit ad hoc. Perhaps, shaper must get script and
2482 language information, and select a proper flt for them
2484 flt
= mflt_get (msymbol ("combining"));
2485 for (i
= 0; i
< 3; i
++)
2487 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2490 gstring
.allocated
+= gstring
.allocated
;
2491 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2492 sizeof (MFLTGlyph
) * gstring
.allocated
);
2494 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2496 for (i
= 0; i
< gstring
.used
; i
++)
2498 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2500 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2501 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2504 for (i
= 0; i
< gstring
.used
; i
++)
2506 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2507 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2511 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2512 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2514 LGLYPH_SET_FROM (lglyph
, g
->from
);
2515 LGLYPH_SET_TO (lglyph
, g
->to
);
2516 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2517 LGLYPH_SET_CODE (lglyph
, g
->code
);
2518 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2519 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2520 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2521 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2522 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2527 vec
= Fmake_vector (make_number (3), Qnil
);
2528 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2529 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2530 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2531 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2534 return make_number (i
);
2538 ftfont_shape (Lisp_Object lgstring
)
2541 struct ftfont_info
*ftfont_info
;
2544 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2545 ftfont_info
= (struct ftfont_info
*) font
;
2546 otf
= ftfont_get_otf (ftfont_info
);
2548 return make_number (0);
2549 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2550 &ftfont_info
->matrix
);
2553 #endif /* HAVE_M17N_FLT */
2555 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2558 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2560 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2561 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2565 return OTF_get_variation_glyphs (otf
, c
, variations
);
2568 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2569 #endif /* HAVE_LIBOTF */
2572 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2576 #ifdef FC_FONTFORMAT
2579 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2581 if (strcmp ((char *) str
, "TrueType") == 0)
2582 return intern ("truetype");
2583 if (strcmp ((char *) str
, "Type 1") == 0)
2584 return intern ("type1");
2585 if (strcmp ((char *) str
, "PCF") == 0)
2586 return intern ("pcf");
2587 if (strcmp ((char *) str
, "BDF") == 0)
2588 return intern ("bdf");
2590 #endif /* FC_FONTFORMAT */
2591 if (STRINGP (filename
))
2593 int len
= SBYTES (filename
);
2597 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2598 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2599 return intern ("truetype");
2600 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2601 return intern ("type1");
2602 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2603 return intern ("pcf");
2604 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2605 return intern ("bdf");
2608 return intern ("unknown");
2611 static const char *const ftfont_booleans
[] = {
2624 static const char *const ftfont_non_booleans
[] = {
2656 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2658 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2663 syms_of_ftfont (void)
2665 DEFSYM (Qfreetype
, "freetype");
2666 DEFSYM (Qmonospace
, "monospace");
2667 DEFSYM (Qsans_serif
, "sans-serif");
2668 DEFSYM (Qserif
, "serif");
2669 DEFSYM (Qmono
, "mono");
2670 DEFSYM (Qsans
, "sans");
2671 DEFSYM (Qsans__serif
, "sans serif");
2673 staticpro (&freetype_font_cache
);
2674 freetype_font_cache
= Fcons (Qt
, Qnil
);
2676 staticpro (&ftfont_generic_family_list
);
2677 ftfont_generic_family_list
2678 = Fcons (Fcons (Qmonospace
, Qt
),
2679 Fcons (Fcons (Qsans_serif
, Qt
),
2680 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2682 staticpro (&ft_face_cache
);
2683 ft_face_cache
= Qnil
;
2685 ftfont_driver
.type
= Qfreetype
;
2686 register_font_driver (&ftfont_driver
, NULL
);