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 static const FcChar8 lang
[] = "en";
315 langset
= FcLangSetCreate ();
316 FcLangSetAdd (langset
, lang
);
317 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
318 FcLangSetDestroy (langset
);
320 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
321 FcDefaultSubstitute (pattern
);
322 match
= FcFontMatch (NULL
, pattern
, &result
);
327 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
328 family
= intern ((char *) fam
);
332 XSETCDR (slot
, family
);
333 if (match
) FcPatternDestroy (match
);
335 if (pattern
) FcPatternDestroy (pattern
);
339 struct ftfont_cache_data
342 FcCharSet
*fc_charset
;
346 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
348 Lisp_Object cache
, val
, entity
;
349 struct ftfont_cache_data
*cache_data
;
351 if (FONT_ENTITY_P (key
))
354 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
355 xassert (CONSP (val
));
361 if (NILP (ft_face_cache
))
364 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
367 if (NILP (ft_face_cache
))
373 ft_face_cache
= Fmake_hash_table (2, args
);
375 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
376 cache_data
->ft_face
= NULL
;
377 cache_data
->fc_charset
= NULL
;
378 val
= make_save_value (NULL
, 0);
379 XSAVE_VALUE (val
)->integer
= 0;
380 XSAVE_VALUE (val
)->pointer
= cache_data
;
381 cache
= Fcons (Qnil
, val
);
382 Fputhash (key
, cache
, ft_face_cache
);
387 cache_data
= XSAVE_VALUE (val
)->pointer
;
390 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
393 if (cache_for
== FTFONT_CACHE_FOR_FACE
394 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
396 char *filename
= SSDATA (XCAR (key
));
397 int index
= XINT (XCDR (key
));
399 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
402 && FT_Init_FreeType (&ft_library
) != 0)
404 if (FT_New_Face (ft_library
, filename
, index
, &cache_data
->ft_face
)
410 FcPattern
*pat
= NULL
;
411 FcFontSet
*fontset
= NULL
;
412 FcObjectSet
*objset
= NULL
;
413 FcCharSet
*charset
= NULL
;
415 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
416 FC_INDEX
, FcTypeInteger
, index
, NULL
);
419 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
422 fontset
= FcFontList (NULL
, pat
, objset
);
425 if (fontset
&& fontset
->nfont
> 0
426 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
429 cache_data
->fc_charset
= FcCharSetCopy (charset
);
431 cache_data
->fc_charset
= FcCharSetCreate ();
435 FcFontSetDestroy (fontset
);
437 FcObjectSetDestroy (objset
);
439 FcPatternDestroy (pat
);
446 ftfont_get_fc_charset (Lisp_Object entity
)
448 Lisp_Object val
, cache
;
449 struct ftfont_cache_data
*cache_data
;
451 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
453 cache_data
= XSAVE_VALUE (val
)->pointer
;
454 return cache_data
->fc_charset
;
459 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
463 if (ftfont_info
->otf
)
464 return ftfont_info
->otf
;
465 if (! ftfont_info
->maybe_otf
)
467 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
468 if (! otf
|| OTF_get_table (otf
, "head") < 0)
472 ftfont_info
->maybe_otf
= 0;
475 ftfont_info
->otf
= otf
;
478 #endif /* HAVE_LIBOTF */
480 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
481 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
482 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
483 static Lisp_Object
ftfont_list_family (Lisp_Object
);
484 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
485 static void ftfont_close (FRAME_PTR
, struct font
*);
486 static int ftfont_has_char (Lisp_Object
, int);
487 static unsigned ftfont_encode_char (struct font
*, int);
488 static int ftfont_text_extents (struct font
*, unsigned *, int,
489 struct font_metrics
*);
490 static int ftfont_get_bitmap (struct font
*, unsigned,
491 struct font_bitmap
*, int);
492 static int ftfont_anchor_point (struct font
*, unsigned, int,
494 static Lisp_Object
ftfont_otf_capability (struct font
*);
495 static Lisp_Object
ftfont_shape (Lisp_Object
);
497 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
498 static int ftfont_variation_glyphs (struct font
*, int c
,
499 unsigned variations
[256]);
500 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
502 struct font_driver ftfont_driver
=
505 0, /* case insensitive */
510 NULL
, /* free_entity */
513 /* We can't draw a text without device dependent functions. */
514 NULL
, /* prepare_face */
515 NULL
, /* done_face */
519 /* We can't draw a text without device dependent functions. */
522 NULL
, /* get_bitmap */
523 NULL
, /* free_bitmap */
524 NULL
, /* get_outline */
527 ftfont_otf_capability
,
528 #else /* not HAVE_LIBOTF */
530 #endif /* not HAVE_LIBOTF */
531 NULL
, /* otf_drive */
532 NULL
, /* start_for_frame */
533 NULL
, /* end_for_frame */
534 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
536 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
538 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
541 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
542 ftfont_variation_glyphs
,
547 ftfont_filter_properties
, /* filter_properties */
551 ftfont_get_cache (FRAME_PTR f
)
553 return freetype_font_cache
;
557 ftfont_get_charset (Lisp_Object registry
)
559 char *str
= SSDATA (SYMBOL_NAME (registry
));
560 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
564 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
568 else if (str
[i
] == '*')
575 regexp
= make_unibyte_string (re
, j
);
576 for (i
= 0; fc_charset_table
[i
].name
; i
++)
577 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
579 if (! fc_charset_table
[i
].name
)
581 if (! fc_charset_table
[i
].fc_charset
)
583 FcCharSet
*charset
= FcCharSetCreate ();
584 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
588 for (j
= 0; uniquifier
[j
]; j
++)
589 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
591 FcCharSetDestroy (charset
);
594 fc_charset_table
[i
].fc_charset
= charset
;
602 unsigned int script_tag
, langsys_tag
;
604 unsigned int *features
[2];
607 #define OTF_SYM_TAG(SYM, TAG) \
609 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
610 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
613 #define OTF_TAG_STR(TAG, P) \
615 (P)[0] = (char) (TAG >> 24); \
616 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
617 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
618 (P)[3] = (char) (TAG & 0xFF); \
622 #define OTF_TAG_SYM(SYM, TAG) \
626 OTF_TAG_STR (TAG, str); \
627 (SYM) = font_intern_prop (str, 4, 1); \
631 static struct OpenTypeSpec
*
632 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
634 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
640 spec
->script
= XCAR (otf_spec
);
641 if (! NILP (spec
->script
))
643 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
644 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
645 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
646 spec
->script
= XCDR (val
);
651 spec
->script_tag
= 0x44464C54; /* "DFLT" */
652 otf_spec
= XCDR (otf_spec
);
653 spec
->langsys_tag
= 0;
654 if (! NILP (otf_spec
))
656 val
= XCAR (otf_spec
);
658 OTF_SYM_TAG (val
, spec
->langsys_tag
);
659 otf_spec
= XCDR (otf_spec
);
661 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
662 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
666 val
= XCAR (otf_spec
);
670 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
671 if (! spec
->features
[i
])
673 if (i
> 0 && spec
->features
[0])
674 free (spec
->features
[0]);
678 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
680 if (NILP (XCAR (val
)))
686 OTF_SYM_TAG (XCAR (val
), tag
);
687 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
690 spec
->nfeatures
[i
] = j
;
696 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
698 Lisp_Object tmp
, extra
;
699 FcPattern
*pattern
= NULL
;
700 FcCharSet
*charset
= NULL
;
701 FcLangSet
*langset
= NULL
;
705 Lisp_Object script
= Qnil
;
706 Lisp_Object registry
;
709 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
711 /* Fontconfig doesn't support reverse-italic/obligue. */
714 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
715 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
716 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
717 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
720 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
722 || EQ (registry
, Qascii_0
)
723 || EQ (registry
, Qiso10646_1
)
724 || EQ (registry
, Qunicode_bmp
))
730 fc_charset_idx
= ftfont_get_charset (registry
);
731 if (fc_charset_idx
< 0)
733 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
734 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
735 lang
= (FcChar8
*) *langname
;
738 langset
= FcLangSetCreate ();
741 FcLangSetAdd (langset
, lang
);
746 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
747 CONSP (extra
); extra
= XCDR (extra
))
749 Lisp_Object key
, val
;
751 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
757 else if (EQ (key
, QClang
))
760 langset
= FcLangSetCreate ();
765 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
769 for (; CONSP (val
); val
= XCDR (val
))
770 if (SYMBOLP (XCAR (val
))
771 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
774 else if (EQ (key
, QCotf
))
778 *otspec
= ftfont_get_open_type_spec (val
);
781 strcat (otlayout
, "otlayout:");
782 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
783 script
= (*otspec
)->script
;
786 else if (EQ (key
, QCscript
))
788 else if (EQ (key
, QCscalable
))
789 scalable
= ! NILP (val
);
792 if (! NILP (script
) && ! charset
)
794 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
796 if (CONSP (chars
) && CONSP (CDR (chars
)))
798 charset
= FcCharSetCreate ();
801 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
802 if (CHARACTERP (XCAR (chars
))
803 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
808 pattern
= FcPatternCreate ();
811 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
813 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
815 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
817 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
820 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
823 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
826 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
829 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
835 /* We come here because of unexpected error in fontconfig API call
836 (usually insufficient memory). */
839 FcPatternDestroy (pattern
);
844 if ((*otspec
)->nfeatures
[0] > 0)
845 free ((*otspec
)->features
[0]);
846 if ((*otspec
)->nfeatures
[1] > 0)
847 free ((*otspec
)->features
[1]);
853 if (langset
) FcLangSetDestroy (langset
);
854 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
859 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
861 Lisp_Object val
= Qnil
, family
, adstyle
;
864 FcFontSet
*fontset
= NULL
;
865 FcObjectSet
*objset
= NULL
;
867 Lisp_Object chars
= Qnil
;
869 char otlayout
[15]; /* For "otlayout:XXXX" */
870 struct OpenTypeSpec
*otspec
= NULL
;
872 const char *langname
= NULL
;
874 if (! fc_initialized
)
880 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
883 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
885 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
888 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
889 if (CONSP (val
) && VECTORP (XCDR (val
)))
894 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
895 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
896 family
= AREF (spec
, FONT_FAMILY_INDEX
);
899 Lisp_Object resolved
;
901 resolved
= ftfont_resolve_generic_family (family
, pattern
);
902 if (! NILP (resolved
))
904 FcPatternDel (pattern
, FC_FAMILY
);
905 if (! FcPatternAddString (pattern
, FC_FAMILY
,
906 SYMBOL_FcChar8 (resolved
)))
910 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
911 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
913 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
914 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
915 FC_STYLE
, FC_FILE
, FC_INDEX
,
918 #endif /* FC_CAPABILITY */
926 FcObjectSetAdd (objset
, FC_CHARSET
);
928 fontset
= FcFontList (NULL
, pattern
, objset
);
929 if (! fontset
|| fontset
->nfont
== 0)
932 /* Need fix because this finds any fonts. */
933 if (fontset
->nfont
== 0 && ! NILP (family
))
935 /* Try maching with configuration. For instance, the
936 configuration may specify "Nimbus Mono L" as an alias of
938 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
939 SYMBOL_FcChar8 (family
), NULL
);
942 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
945 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
948 FcPatternDel (pattern
, FC_FAMILY
);
949 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
950 FcFontSetDestroy (fontset
);
951 fontset
= FcFontList (NULL
, pattern
, objset
);
952 if (fontset
&& fontset
->nfont
> 0)
958 for (i
= 0; i
< fontset
->nfont
; i
++)
966 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
977 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
979 || ! strstr ((char *) this, otlayout
))
982 #endif /* FC_CAPABILITY */
989 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
992 otf
= OTF_open ((char *) file
);
995 if (OTF_check_features (otf
, 1,
996 otspec
->script_tag
, otspec
->langsys_tag
,
998 otspec
->nfeatures
[0]) != 1
999 || OTF_check_features (otf
, 0,
1000 otspec
->script_tag
, otspec
->langsys_tag
,
1001 otspec
->features
[1],
1002 otspec
->nfeatures
[1]) != 1)
1005 #endif /* HAVE_LIBOTF */
1006 if (VECTORP (chars
))
1010 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1013 for (j
= 0; j
< ASIZE (chars
); j
++)
1014 if (NATNUMP (AREF (chars
, j
))
1015 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1017 if (j
== ASIZE (chars
))
1020 if (! NILP (adstyle
) || langname
)
1022 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1024 if (! NILP (adstyle
)
1025 && (NILP (this_adstyle
)
1026 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1027 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1030 && ! NILP (this_adstyle
)
1031 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1034 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1035 AREF (spec
, FONT_EXTRA_INDEX
));
1036 if (! NILP (entity
))
1037 val
= Fcons (entity
, val
);
1039 val
= Fnreverse (val
);
1043 /* We come here because of unexpected error in fontconfig API call
1044 (usually insufficient memory). */
1048 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1049 if (objset
) FcObjectSetDestroy (objset
);
1050 if (fontset
) FcFontSetDestroy (fontset
);
1051 if (pattern
) FcPatternDestroy (pattern
);
1056 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1058 Lisp_Object entity
= Qnil
;
1059 FcPattern
*pattern
, *match
= NULL
;
1061 char otlayout
[15]; /* For "otlayout:XXXX" */
1062 struct OpenTypeSpec
*otspec
= NULL
;
1063 const char *langname
= NULL
;
1065 if (! fc_initialized
)
1071 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1075 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1079 value
.type
= FcTypeDouble
;
1080 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1081 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1083 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1085 FcDefaultSubstitute (pattern
);
1086 match
= FcFontMatch (NULL
, pattern
, &result
);
1089 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1090 FcPatternDestroy (match
);
1091 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1092 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1093 ftfont_generic_family_list
))
1094 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1095 AREF (entity
, FONT_FAMILY_INDEX
))))
1099 FcPatternDestroy (pattern
);
1101 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1106 ftfont_list_family (Lisp_Object frame
)
1108 Lisp_Object list
= Qnil
;
1109 FcPattern
*pattern
= NULL
;
1110 FcFontSet
*fontset
= NULL
;
1111 FcObjectSet
*objset
= NULL
;
1114 if (! fc_initialized
)
1120 pattern
= FcPatternCreate ();
1123 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1126 fontset
= FcFontList (NULL
, pattern
, objset
);
1130 for (i
= 0; i
< fontset
->nfont
; i
++)
1132 FcPattern
*pat
= fontset
->fonts
[i
];
1135 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1136 list
= Fcons (intern ((char *) str
), list
);
1140 if (objset
) FcObjectSetDestroy (objset
);
1141 if (fontset
) FcFontSetDestroy (fontset
);
1142 if (pattern
) FcPatternDestroy (pattern
);
1149 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1151 struct ftfont_info
*ftfont_info
;
1153 struct ftfont_cache_data
*cache_data
;
1157 Lisp_Object val
, filename
, index
, cache
, font_object
;
1164 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1168 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1171 filename
= XCAR (val
);
1174 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1175 ft_face
= cache_data
->ft_face
;
1176 if (XSAVE_VALUE (val
)->integer
> 0)
1178 /* FT_Face in this cache is already used by the different size. */
1179 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1181 if (FT_Activate_Size (ft_size
) != 0)
1183 FT_Done_Size (ft_size
);
1187 XSAVE_VALUE (val
)->integer
++;
1188 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1191 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1193 if (XSAVE_VALUE (val
)->integer
== 0)
1194 FT_Done_Face (ft_face
);
1198 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1199 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1200 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1202 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1203 len
= font_unparse_fcname (entity
, size
, name
, 256);
1205 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1207 ASET (font_object
, FONT_FULLNAME_INDEX
,
1208 AREF (font_object
, FONT_NAME_INDEX
));
1209 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1210 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1211 font
= XFONT_OBJECT (font_object
);
1212 ftfont_info
= (struct ftfont_info
*) font
;
1213 ftfont_info
->ft_size
= ft_face
->size
;
1214 ftfont_info
->index
= XINT (index
);
1216 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1217 ftfont_info
->otf
= NULL
;
1218 #endif /* HAVE_LIBOTF */
1219 /* This means that there's no need of transformation. */
1220 ftfont_info
->matrix
.xx
= 0;
1221 font
->pixel_size
= size
;
1222 font
->driver
= &ftfont_driver
;
1223 font
->encoding_charset
= font
->repertory_charset
= -1;
1225 upEM
= ft_face
->units_per_EM
;
1226 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1227 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1230 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1231 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1232 font
->height
= ft_face
->height
* size
/ upEM
;
1236 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1237 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1238 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1240 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1241 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1243 spacing
= FC_PROPORTIONAL
;
1244 if (spacing
!= FC_PROPORTIONAL
1246 && spacing
!= FC_DUAL
1247 #endif /* FC_DUAL */
1249 font
->min_width
= font
->average_width
= font
->space_width
1250 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1251 : ft_face
->size
->metrics
.max_advance
>> 6);
1256 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1257 for (i
= 32, n
= 0; i
< 127; i
++)
1258 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1260 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1263 && (! font
->min_width
|| font
->min_width
> this_width
))
1264 font
->min_width
= this_width
;
1266 font
->space_width
= this_width
;
1267 font
->average_width
+= this_width
;
1271 font
->average_width
/= n
;
1274 font
->baseline_offset
= 0;
1275 font
->relative_compose
= 0;
1276 font
->default_ascent
= 0;
1277 font
->vertical_centering
= 0;
1280 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1281 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1285 font
->underline_position
= -1;
1286 font
->underline_thickness
= 0;
1293 ftfont_close (FRAME_PTR f
, struct font
*font
)
1295 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1296 Lisp_Object val
, cache
;
1298 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1299 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1300 xassert (CONSP (cache
));
1302 (XSAVE_VALUE (val
)->integer
)--;
1303 if (XSAVE_VALUE (val
)->integer
== 0)
1305 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1307 FT_Done_Face (cache_data
->ft_face
);
1309 if (ftfont_info
->otf
)
1310 OTF_close (ftfont_info
->otf
);
1312 cache_data
->ft_face
= NULL
;
1315 FT_Done_Size (ftfont_info
->ft_size
);
1319 ftfont_has_char (Lisp_Object font
, int c
)
1321 struct charset
*cs
= NULL
;
1323 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1324 && charset_jisx0208
>= 0)
1325 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1326 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1327 && charset_ksc5601
>= 0)
1328 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1330 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1332 if (FONT_ENTITY_P (font
))
1334 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1336 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1340 struct ftfont_info
*ftfont_info
;
1342 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1343 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1349 ftfont_encode_char (struct font
*font
, int c
)
1351 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1352 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1353 FT_ULong charcode
= c
;
1354 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1356 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1360 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1362 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1363 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1367 if (ftfont_info
->ft_size
!= ft_face
->size
)
1368 FT_Activate_Size (ftfont_info
->ft_size
);
1370 memset (metrics
, 0, sizeof (struct font_metrics
));
1371 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1373 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1375 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1381 metrics
->lbearing
= m
->horiBearingX
>> 6;
1382 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1383 metrics
->ascent
= m
->horiBearingY
>> 6;
1384 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1390 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1391 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1392 if (metrics
->rbearing
1393 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1395 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1396 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1397 metrics
->ascent
= m
->horiBearingY
>> 6;
1398 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1399 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1401 width
+= m
->horiAdvance
>> 6;
1405 width
+= font
->space_width
;
1409 metrics
->width
= width
;
1415 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1417 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1418 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1419 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1421 if (ftfont_info
->ft_size
!= ft_face
->size
)
1422 FT_Activate_Size (ftfont_info
->ft_size
);
1423 if (bits_per_pixel
== 1)
1425 #ifdef FT_LOAD_TARGET_MONO
1426 load_flags
|= FT_LOAD_TARGET_MONO
;
1428 load_flags
|= FT_LOAD_MONOCHROME
;
1431 else if (bits_per_pixel
!= 8)
1432 /* We don't support such a rendering. */
1435 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1437 bitmap
->bits_per_pixel
1438 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1439 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1440 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1441 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1443 if (bitmap
->bits_per_pixel
< 0)
1444 /* We don't suport that kind of pixel mode. */
1446 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1447 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1448 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1449 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1450 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1451 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1452 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1453 bitmap
->extra
= NULL
;
1459 ftfont_anchor_point (struct font
*font
, unsigned int code
, int index
, int *x
, int *y
)
1461 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1462 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1464 if (ftfont_info
->ft_size
!= ft_face
->size
)
1465 FT_Activate_Size (ftfont_info
->ft_size
);
1466 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1468 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1470 if (index
>= ft_face
->glyph
->outline
.n_points
)
1472 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
1473 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
1480 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1482 Lisp_Object scripts
, langsyses
, features
, sym
;
1485 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1487 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1489 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1491 OTF_LangSys
*otf_langsys
;
1494 otf_langsys
= otf_script
->LangSys
+ j
;
1495 else if (otf_script
->DefaultLangSysOffset
)
1496 otf_langsys
= &otf_script
->DefaultLangSys
;
1500 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1502 l
= otf_langsys
->FeatureIndex
[k
];
1503 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1505 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1506 features
= Fcons (sym
, features
);
1509 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1512 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1515 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1516 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1524 ftfont_otf_capability (struct font
*font
)
1526 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1527 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1528 Lisp_Object gsub_gpos
;
1532 gsub_gpos
= Fcons (Qnil
, Qnil
);
1533 if (OTF_get_table (otf
, "GSUB") == 0
1534 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1535 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1536 if (OTF_get_table (otf
, "GPOS") == 0
1537 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1538 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1542 #ifdef HAVE_M17N_FLT
1544 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1545 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1546 /* We can use the new feature of libotf and m17n-flt to handle the
1547 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1548 some Agian scripts. */
1549 #define M17N_FLT_USE_NEW_FEATURE
1562 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1565 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1566 FT_Face ft_face
= flt_font_ft
->ft_face
;
1569 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1572 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1574 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1580 /* Operators for 26.6 fixed fractional pixel format */
1582 #define FLOOR(x) ((x) & -64)
1583 #define CEIL(x) (((x)+63) & -64)
1584 #define ROUND(x) (((x)+32) & -64)
1587 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1590 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1591 FT_Face ft_face
= flt_font_ft
->ft_face
;
1594 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1597 if (g
->code
!= FONT_INVALID_CODE
)
1599 FT_Glyph_Metrics
*m
;
1600 int lbearing
, rbearing
, ascent
, descent
, xadv
;
1602 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1604 m
= &ft_face
->glyph
->metrics
;
1605 if (flt_font_ft
->matrix
)
1610 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1611 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1612 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1613 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1614 for (i
= 0; i
< 4; i
++)
1615 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1616 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1617 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1618 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1619 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1623 g
->lbearing
= FLOOR (m
->horiBearingX
);
1624 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1625 g
->ascent
= CEIL (m
->horiBearingY
);
1626 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1628 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1633 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1634 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1635 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1644 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1646 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1648 #define FEATURE_ANY(IDX) \
1649 (spec->features[IDX] \
1650 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1652 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1653 OTF
*otf
= flt_font_ft
->otf
;
1657 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1658 /* Return 1 iff any of GSUB or GPOS support the script (and language). */
1660 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1662 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1665 for (i
= 0; i
< 2; i
++)
1666 if (! FEATURE_ANY (i
))
1668 if (FEATURE_NONE (i
))
1671 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1676 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1679 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1685 for (n
= 1; spec
->features
[i
][n
]; n
++);
1686 tags
= alloca (sizeof (OTF_Tag
) * n
);
1687 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1689 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1692 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1694 tags
[n
] = spec
->features
[i
][n
];
1696 #ifdef M17N_FLT_USE_NEW_FEATURE
1697 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1698 tags
, n
- negative
) != 1)
1700 #else /* not M17N_FLT_USE_NEW_FEATURE */
1701 if (n
- negative
> 0
1702 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1703 tags
, n
- negative
) != 1)
1705 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1712 #define DEVICE_DELTA(table, size) \
1713 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1714 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1718 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1719 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1721 if (anchor
->AnchorFormat
== 2)
1723 FT_Outline
*outline
;
1724 int ap
= anchor
->f
.f1
.AnchorPoint
;
1726 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1727 outline
= &ft_face
->glyph
->outline
;
1728 if (ap
< outline
->n_points
)
1730 *x
= outline
->points
[ap
].x
<< 6;
1731 *y
= outline
->points
[ap
].y
<< 6;
1734 else if (anchor
->AnchorFormat
== 3)
1736 if (anchor
->f
.f2
.XDeviceTable
.offset
1737 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1738 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1739 if (anchor
->f
.f2
.YDeviceTable
.offset
1740 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1741 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1745 static OTF_GlyphString otf_gstring
;
1748 setup_otf_gstring (int size
)
1750 if (otf_gstring
.size
== 0)
1752 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1753 otf_gstring
.size
= size
;
1755 else if (otf_gstring
.size
< size
)
1757 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1758 sizeof (OTF_Glyph
) * size
);
1759 otf_gstring
.size
= size
;
1761 otf_gstring
.used
= size
;
1762 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1765 #ifdef M17N_FLT_USE_NEW_FEATURE
1767 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1768 #define PACK_OTF_TAG(TAG) \
1769 ((((TAG) & 0x7F000000) >> 3) \
1770 | (((TAG) & 0x7F0000) >> 2) \
1771 | (((TAG) & 0x7F00) >> 1) \
1774 /* Assuming that FONT is an OpenType font, apply OpenType features
1775 specified in SPEC on glyphs between FROM and TO of IN, and record
1776 the lastly applied feature in each glyph of IN. If OUT is not
1777 NULL, append the resulting glyphs to OUT while storing glyph
1778 position adjustment information in ADJUSTMENT. */
1781 ftfont_drive_otf (MFLTFont
*font
,
1783 MFLTGlyphString
*in
,
1786 MFLTGlyphString
*out
,
1787 MFLTGlyphAdjustment
*adjustment
)
1789 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1790 FT_Face ft_face
= flt_font_ft
->ft_face
;
1791 OTF
*otf
= flt_font_ft
->otf
;
1792 int len
= to
- from
;
1795 char script
[5], *langsys
= NULL
;
1796 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1797 OTF_Feature
*features
;
1801 OTF_tag_name (spec
->script
, script
);
1804 langsys
= alloca (5);
1805 OTF_tag_name (spec
->langsys
, langsys
);
1807 for (i
= 0; i
< 2; i
++)
1811 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1813 for (j
= 0; spec
->features
[i
][j
]; j
++);
1815 p
= gsub_features
= alloca (6 * j
);
1817 p
= gpos_features
= alloca (6 * j
);
1818 for (j
= 0; spec
->features
[i
][j
]; j
++)
1820 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1821 *p
++ = '*', *p
++ = ',';
1824 OTF_tag_name (spec
->features
[i
][j
], p
);
1833 setup_otf_gstring (len
);
1834 for (i
= 0; i
< len
; i
++)
1836 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1837 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1840 OTF_drive_gdef (otf
, &otf_gstring
);
1841 gidx
= out
? out
->used
: from
;
1843 if (gsub_features
&& out
)
1845 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1848 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1850 features
= otf
->gsub
->FeatureList
.Feature
;
1851 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1854 int min_from
, max_to
;
1856 int feature_idx
= otfg
->positioning_type
>> 4;
1858 g
= out
->glyphs
+ out
->used
;
1859 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1860 if (g
->code
!= otfg
->glyph_id
)
1863 g
->code
= otfg
->glyph_id
;
1869 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1871 /* OTFG substitutes multiple glyphs in IN. */
1872 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1873 j
<= from
+ otfg
->f
.index
.to
; j
++)
1875 if (min_from
> in
->glyphs
[j
].from
)
1876 min_from
= in
->glyphs
[j
].from
;
1877 if (max_to
< in
->glyphs
[j
].to
)
1878 max_to
= in
->glyphs
[j
].to
;
1885 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1886 tag
= PACK_OTF_TAG (tag
);
1887 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1889 for (i
++, otfg
++; (i
< otf_gstring
.used
1890 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1893 g
= out
->glyphs
+ out
->used
;
1894 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1895 if (g
->code
!= otfg
->glyph_id
)
1898 g
->code
= otfg
->glyph_id
;
1901 feature_idx
= otfg
->positioning_type
>> 4;
1904 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1905 tag
= PACK_OTF_TAG (tag
);
1906 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1912 else if (gsub_features
)
1914 /* Just for checking which features will be applied. */
1915 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1918 features
= otf
->gsub
->FeatureList
.Feature
;
1919 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1922 int feature_idx
= otfg
->positioning_type
>> 4;
1926 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1927 tag
= PACK_OTF_TAG (tag
);
1928 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1930 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1931 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1938 if (out
->allocated
< out
->used
+ len
)
1940 for (i
= 0; i
< len
; i
++)
1941 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1944 if (gpos_features
&& out
)
1946 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1947 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1949 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1952 features
= otf
->gpos
->FeatureList
.Feature
;
1953 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1954 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1955 x_scale
= ft_face
->size
->metrics
.x_scale
;
1956 y_scale
= ft_face
->size
->metrics
.y_scale
;
1958 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1959 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1962 int feature_idx
= otfg
->positioning_type
>> 4;
1966 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1967 tag
= PACK_OTF_TAG (tag
);
1968 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1971 if (! otfg
->glyph_id
)
1973 switch (otfg
->positioning_type
& 0xF)
1977 case 1: /* Single */
1980 int format
= otfg
->f
.f1
.format
;
1982 if (format
& OTF_XPlacement
)
1984 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1985 if (format
& OTF_XPlaDevice
)
1987 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1988 if (format
& OTF_YPlacement
)
1990 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
1991 if (format
& OTF_YPlaDevice
)
1993 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
1994 if (format
& OTF_XAdvance
)
1996 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
1997 if (format
& OTF_XAdvDevice
)
1999 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2000 if (format
& OTF_YAdvance
)
2002 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2003 if (format
& OTF_YAdvDevice
)
2005 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2006 adjustment
[i
].set
= 1;
2009 case 3: /* Cursive */
2010 /* Not yet supported. */
2012 case 4: /* Mark-to-Base */
2013 case 5: /* Mark-to-Ligature */
2017 goto label_adjust_anchor
;
2018 default: /* i.e. case 6 Mark-to-Mark */
2023 label_adjust_anchor
:
2025 int base_x
, base_y
, mark_x
, mark_y
;
2026 int this_from
, this_to
;
2028 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2029 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2030 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2031 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2033 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2034 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2035 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2036 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2037 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2038 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2039 adjustment
[i
].xoff
= (base_x
- mark_x
);
2040 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2041 adjustment
[i
].back
= (g
- prev
);
2042 adjustment
[i
].xadv
= 0;
2043 adjustment
[i
].advance_is_absolute
= 1;
2044 adjustment
[i
].set
= 1;
2045 this_from
= g
->from
;
2047 for (j
= 0; prev
+ j
< g
; j
++)
2049 if (this_from
> prev
[j
].from
)
2050 this_from
= prev
[j
].from
;
2051 if (this_to
< prev
[j
].to
)
2052 this_to
= prev
[j
].to
;
2054 for (; prev
<= g
; prev
++)
2056 prev
->from
= this_from
;
2061 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2063 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2069 else if (gpos_features
)
2071 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2074 features
= otf
->gpos
->FeatureList
.Feature
;
2075 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2077 if (otfg
->positioning_type
& 0xF)
2079 int feature_idx
= otfg
->positioning_type
>> 4;
2083 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2084 tag
= PACK_OTF_TAG (tag
);
2085 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2087 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2088 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2098 if (out
->allocated
< out
->used
+ len
)
2100 font
->get_metrics (font
, in
, from
, to
);
2101 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2102 sizeof (MFLTGlyph
) * len
);
2108 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2109 MFLTGlyphString
*in
, int from
, int to
)
2111 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2114 #else /* not M17N_FLT_USE_NEW_FEATURE */
2117 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2119 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2121 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2122 FT_Face ft_face
= flt_font_ft
->ft_face
;
2123 OTF
*otf
= flt_font_ft
->otf
;
2124 int len
= to
- from
;
2127 char script
[5], *langsys
= NULL
;
2128 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2132 OTF_tag_name (spec
->script
, script
);
2135 langsys
= alloca (5);
2136 OTF_tag_name (spec
->langsys
, langsys
);
2138 for (i
= 0; i
< 2; i
++)
2142 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2144 for (j
= 0; spec
->features
[i
][j
]; j
++);
2146 p
= gsub_features
= alloca (6 * j
);
2148 p
= gpos_features
= alloca (6 * j
);
2149 for (j
= 0; spec
->features
[i
][j
]; j
++)
2151 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2152 *p
++ = '*', *p
++ = ',';
2155 OTF_tag_name (spec
->features
[i
][j
], p
);
2164 setup_otf_gstring (len
);
2165 for (i
= 0; i
< len
; i
++)
2167 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2168 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2171 OTF_drive_gdef (otf
, &otf_gstring
);
2176 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2179 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2181 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2184 int min_from
, max_to
;
2187 g
= out
->glyphs
+ out
->used
;
2188 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2189 if (g
->code
!= otfg
->glyph_id
)
2192 g
->code
= otfg
->glyph_id
;
2198 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2200 /* OTFG substitutes multiple glyphs in IN. */
2201 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2202 j
<= from
+ otfg
->f
.index
.to
; j
++)
2204 if (min_from
> in
->glyphs
[j
].from
)
2205 min_from
= in
->glyphs
[j
].from
;
2206 if (max_to
< in
->glyphs
[j
].to
)
2207 max_to
= in
->glyphs
[j
].to
;
2212 for (i
++, otfg
++; (i
< otf_gstring
.used
2213 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2216 g
= out
->glyphs
+ out
->used
;
2217 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2218 if (g
->code
!= otfg
->glyph_id
)
2221 g
->code
= otfg
->glyph_id
;
2230 if (out
->allocated
< out
->used
+ len
)
2232 for (i
= 0; i
< len
; i
++)
2233 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2238 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2239 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2241 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2245 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2246 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2247 x_scale
= ft_face
->size
->metrics
.x_scale
;
2248 y_scale
= ft_face
->size
->metrics
.y_scale
;
2250 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2251 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2255 if (! otfg
->glyph_id
)
2257 switch (otfg
->positioning_type
)
2261 case 1: /* Single */
2264 int format
= otfg
->f
.f1
.format
;
2266 if (format
& OTF_XPlacement
)
2268 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2269 if (format
& OTF_XPlaDevice
)
2271 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2272 if (format
& OTF_YPlacement
)
2274 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2275 if (format
& OTF_YPlaDevice
)
2277 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2278 if (format
& OTF_XAdvance
)
2280 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2281 if (format
& OTF_XAdvDevice
)
2283 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2284 if (format
& OTF_YAdvance
)
2286 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2287 if (format
& OTF_YAdvDevice
)
2289 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2290 adjustment
[i
].set
= 1;
2293 case 3: /* Cursive */
2294 /* Not yet supported. */
2296 case 4: /* Mark-to-Base */
2297 case 5: /* Mark-to-Ligature */
2301 goto label_adjust_anchor
;
2302 default: /* i.e. case 6 Mark-to-Mark */
2307 label_adjust_anchor
:
2309 int base_x
, base_y
, mark_x
, mark_y
;
2310 int this_from
, this_to
;
2312 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2313 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2314 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2315 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2317 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2318 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2319 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2320 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2321 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2322 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2323 adjustment
[i
].xoff
= (base_x
- mark_x
);
2324 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2325 adjustment
[i
].back
= (g
- prev
);
2326 adjustment
[i
].xadv
= 0;
2327 adjustment
[i
].advance_is_absolute
= 1;
2328 adjustment
[i
].set
= 1;
2329 this_from
= g
->from
;
2331 for (j
= 0; prev
+ j
< g
; j
++)
2333 if (this_from
> prev
[j
].from
)
2334 this_from
= prev
[j
].from
;
2335 if (this_to
< prev
[j
].to
)
2336 this_to
= prev
[j
].to
;
2338 for (; prev
<= g
; prev
++)
2340 prev
->from
= this_from
;
2345 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2347 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2356 if (out
->allocated
< out
->used
+ len
)
2358 font
->get_metrics (font
, in
, from
, to
);
2359 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2360 sizeof (MFLTGlyph
) * len
);
2365 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2367 static MFLTGlyphString gstring
;
2369 static int m17n_flt_initialized
;
2372 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2373 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2375 EMACS_UINT len
= LGSTRING_GLYPH_LEN (lgstring
);
2377 struct MFLTFontFT flt_font_ft
;
2379 int with_variation_selector
= 0;
2381 if (! m17n_flt_initialized
)
2384 #ifdef M17N_FLT_USE_NEW_FEATURE
2385 mflt_enable_new_feature
= 1;
2386 mflt_try_otf
= ftfont_try_otf
;
2387 #endif /* M17N_FLT_USE_NEW_FEATURE */
2388 m17n_flt_initialized
= 1;
2391 for (i
= 0; i
< len
; i
++)
2393 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2398 c
= LGLYPH_CHAR (g
);
2399 if (CHAR_VARIATION_SELECTOR_P (c
))
2400 with_variation_selector
++;
2403 if (with_variation_selector
)
2405 setup_otf_gstring (len
);
2406 for (i
= 0; i
< len
; i
++)
2408 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2410 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2411 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2412 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2414 OTF_drive_cmap (otf
, &otf_gstring
);
2415 for (i
= 0; i
< otf_gstring
.used
; i
++)
2417 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2418 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2419 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2421 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2422 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2423 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2425 if (len
> otf_gstring
.used
)
2427 len
= otf_gstring
.used
;
2428 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2432 if (gstring
.allocated
== 0)
2434 gstring
.allocated
= len
* 2;
2435 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2436 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2438 else if (gstring
.allocated
< len
* 2)
2440 gstring
.allocated
= len
* 2;
2441 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2442 sizeof (MFLTGlyph
) * gstring
.allocated
);
2444 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2445 for (i
= 0; i
< len
; i
++)
2447 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2449 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2450 if (with_variation_selector
)
2452 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2453 gstring
.glyphs
[i
].encoded
= 1;
2461 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2464 flt_font_ft
.flt_font
.family
= Mnil
;
2466 flt_font_ft
.flt_font
.family
2467 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2469 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2470 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2471 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2472 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2473 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2474 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2475 flt_font_ft
.flt_font
.internal
= NULL
;
2476 flt_font_ft
.font
= font
;
2477 flt_font_ft
.ft_face
= ft_face
;
2478 flt_font_ft
.otf
= otf
;
2479 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2481 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2482 /* A little bit ad hoc. Perhaps, shaper must get script and
2483 language information, and select a proper flt for them
2485 flt
= mflt_get (msymbol ("combining"));
2486 for (i
= 0; i
< 3; i
++)
2488 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2491 gstring
.allocated
+= gstring
.allocated
;
2492 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2493 sizeof (MFLTGlyph
) * gstring
.allocated
);
2495 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2497 for (i
= 0; i
< gstring
.used
; i
++)
2499 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2501 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2502 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2505 for (i
= 0; i
< gstring
.used
; i
++)
2507 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2508 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2512 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2513 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2515 LGLYPH_SET_FROM (lglyph
, g
->from
);
2516 LGLYPH_SET_TO (lglyph
, g
->to
);
2517 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2518 LGLYPH_SET_CODE (lglyph
, g
->code
);
2519 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2520 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2521 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2522 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2523 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2528 vec
= Fmake_vector (make_number (3), Qnil
);
2529 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2530 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2531 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2532 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2535 return make_number (i
);
2539 ftfont_shape (Lisp_Object lgstring
)
2542 struct ftfont_info
*ftfont_info
;
2545 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2546 ftfont_info
= (struct ftfont_info
*) font
;
2547 otf
= ftfont_get_otf (ftfont_info
);
2549 return make_number (0);
2550 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2551 &ftfont_info
->matrix
);
2554 #endif /* HAVE_M17N_FLT */
2556 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2559 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2561 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2562 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2566 return OTF_get_variation_glyphs (otf
, c
, variations
);
2569 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2570 #endif /* HAVE_LIBOTF */
2573 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2577 #ifdef FC_FONTFORMAT
2580 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2582 if (strcmp ((char *) str
, "TrueType") == 0)
2583 return intern ("truetype");
2584 if (strcmp ((char *) str
, "Type 1") == 0)
2585 return intern ("type1");
2586 if (strcmp ((char *) str
, "PCF") == 0)
2587 return intern ("pcf");
2588 if (strcmp ((char *) str
, "BDF") == 0)
2589 return intern ("bdf");
2591 #endif /* FC_FONTFORMAT */
2592 if (STRINGP (filename
))
2594 int len
= SBYTES (filename
);
2598 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2599 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2600 return intern ("truetype");
2601 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2602 return intern ("type1");
2603 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2604 return intern ("pcf");
2605 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2606 return intern ("bdf");
2609 return intern ("unknown");
2612 static const char *const ftfont_booleans
[] = {
2625 static const char *const ftfont_non_booleans
[] = {
2657 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2659 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2664 syms_of_ftfont (void)
2666 DEFSYM (Qfreetype
, "freetype");
2667 DEFSYM (Qmonospace
, "monospace");
2668 DEFSYM (Qsans_serif
, "sans-serif");
2669 DEFSYM (Qserif
, "serif");
2670 DEFSYM (Qmono
, "mono");
2671 DEFSYM (Qsans
, "sans");
2672 DEFSYM (Qsans__serif
, "sans serif");
2674 staticpro (&freetype_font_cache
);
2675 freetype_font_cache
= Fcons (Qt
, Qnil
);
2677 staticpro (&ftfont_generic_family_list
);
2678 ftfont_generic_family_list
2679 = Fcons (Fcons (Qmonospace
, Qt
),
2680 Fcons (Fcons (Qsans_serif
, Qt
),
2681 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2683 staticpro (&ft_face_cache
);
2684 ft_face_cache
= Qnil
;
2686 ftfont_driver
.type
= Qfreetype
;
2687 register_font_driver (&ftfont_driver
, NULL
);