1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006-2015 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24 #include <fontconfig/fontconfig.h>
25 #include <fontconfig/fcfreetype.h>
27 #include <c-strcase.h>
30 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
36 #include "composite.h"
41 /* Flag to tell if FcInit is already called or not. */
42 static bool fc_initialized
;
44 /* Handle to a FreeType library instance. */
45 static FT_Library ft_library
;
47 /* Cache for FreeType fonts. */
48 static Lisp_Object freetype_font_cache
;
50 /* Cache for FT_Face and FcCharSet. */
51 static Lisp_Object ft_face_cache
;
53 /* The actual structure for FreeType font that can be cast to struct
60 /* The following four members must be here in this order to be
61 compatible with struct xftfont_info (in xftfont.c). */
62 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
64 #endif /* HAVE_LIBOTF */
70 size_t ftfont_info_size
= sizeof (struct ftfont_info
);
74 FTFONT_CACHE_FOR_FACE
,
75 FTFONT_CACHE_FOR_CHARSET
,
76 FTFONT_CACHE_FOR_ENTITY
79 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
81 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
83 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
84 enum ftfont_cache_for
);
86 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
88 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
94 /* characters to distinguish the charset from the others */
96 /* additional constraint by language */
99 FcCharSet
*fc_charset
;
100 } fc_charset_table
[] =
101 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
102 { "iso8859-2", { 0x00A0, 0x010E }},
103 { "iso8859-3", { 0x00A0, 0x0108 }},
104 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
105 { "iso8859-5", { 0x00A0, 0x0401 }},
106 { "iso8859-6", { 0x00A0, 0x060C }},
107 { "iso8859-7", { 0x00A0, 0x0384 }},
108 { "iso8859-8", { 0x00A0, 0x05D0 }},
109 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
110 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
111 { "iso8859-11", { 0x00A0, 0x0E01 }},
112 { "iso8859-13", { 0x00A0, 0x201C }},
113 { "iso8859-14", { 0x00A0, 0x0174 }},
114 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
115 { "iso8859-16", { 0x00A0, 0x0218}},
116 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
117 { "big5-0", { 0xF6B1 }, "zh-tw" },
118 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
119 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
120 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
121 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
122 { "cns11643.1992-3", { 0x201A9 }},
123 { "cns11643.1992-4", { 0x20057 }},
124 { "cns11643.1992-5", { 0x20000 }},
125 { "cns11643.1992-6", { 0x20003 }},
126 { "cns11643.1992-7", { 0x20055 }},
127 { "gbk-0", { 0x4E06 }, "zh-cn"},
128 { "jisx0212.1990-0", { 0x4E44 }},
129 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
130 { "jisx0213.2000-2", { 0xFA49 }},
131 { "jisx0213.2004-1", { 0x20B9F }},
132 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
133 { "tis620.2529-1", { 0x0E01 }, "th"},
134 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
135 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
136 { "mulelao-1", { 0x0E81 }, "lo"},
137 { "unicode-sip", { 0x20000 }},
142 matching_prefix (char const *str
, ptrdiff_t len
, char const *pat
)
144 return len
== strlen (pat
) && c_strncasecmp (str
, pat
, len
) == 0;
147 /* Dirty hack for handing ADSTYLE property.
149 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
150 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
151 "Oblique", "Italic", or any non-normal SWIDTH property names
152 (e.g. SemiCondensed) are appended. In addition, if there's no
153 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
154 "Regular" is used for FC_STYLE (see the function
155 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
157 Unfortunately this behavior is not documented, so the following
158 code may fail if FreeType changes the behavior in the future. */
161 get_adstyle_property (FcPattern
*p
)
168 if ((FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fcstr
) == FcResultMatch
)
169 && xstrcasecmp ((char *) fcstr
, "bdf") != 0
170 && xstrcasecmp ((char *) fcstr
, "pcf") != 0)
171 /* Not a BDF nor PCF font. */
174 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
176 str
= (char *) fcstr
;
177 for (end
= str
; *end
&& *end
!= ' '; end
++);
178 if (matching_prefix (str
, end
- str
, "Regular")
179 || matching_prefix (str
, end
- str
, "Bold")
180 || matching_prefix (str
, end
- str
, "Oblique")
181 || matching_prefix (str
, end
- str
, "Italic"))
183 adstyle
= font_intern_prop (str
, end
- str
, 1);
184 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
190 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
192 Lisp_Object key
, cache
, entity
;
200 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
202 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
206 key
= Fcons (build_unibyte_string (file
), make_number (idx
));
207 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
208 entity
= XCAR (cache
);
211 Lisp_Object val
= font_make_entity ();
214 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
215 ASET (val
, i
, AREF (entity
, i
));
217 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
218 font_put_extra (val
, QCfont_entity
, key
);
222 entity
= font_make_entity ();
223 XSETCAR (cache
, entity
);
225 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
226 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
228 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
230 char *s
= (char *) str
;
231 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
233 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
235 char *s
= (char *) str
;
236 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
238 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
240 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
241 numeric
= FC_WEIGHT_MEDIUM
;
242 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
244 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
247 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
249 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
251 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
253 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
255 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
258 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
259 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
260 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
261 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
264 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
266 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
269 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
270 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
274 /* As this font is not scalable, perhaps this is a BDF or PCF
278 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
279 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
280 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
284 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
285 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
286 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
287 FT_Done_Face (ft_face
);
291 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
292 font_put_extra (entity
, QCfont_entity
, key
);
297 static Lisp_Object ftfont_generic_family_list
;
300 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
307 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
308 if (EQ (family
, Qmono
))
310 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
311 family
= Qsans_serif
;
312 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
315 if (! EQ (XCDR (slot
), Qt
))
317 pattern
= FcPatternDuplicate (pattern
);
320 FcPatternDel (pattern
, FC_FOUNDRY
);
321 FcPatternDel (pattern
, FC_FAMILY
);
322 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
323 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
325 /* This is to avoid the effect of locale. */
326 static const FcChar8 lang
[] = "en";
327 langset
= FcLangSetCreate ();
328 FcLangSetAdd (langset
, lang
);
329 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
330 FcLangSetDestroy (langset
);
332 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
333 FcDefaultSubstitute (pattern
);
334 match
= FcFontMatch (NULL
, pattern
, &result
);
339 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
340 family
= intern ((char *) fam
);
344 XSETCDR (slot
, family
);
345 if (match
) FcPatternDestroy (match
);
347 if (pattern
) FcPatternDestroy (pattern
);
351 struct ftfont_cache_data
354 FcCharSet
*fc_charset
;
358 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
360 Lisp_Object cache
, val
, entity
;
361 struct ftfont_cache_data
*cache_data
;
363 if (FONT_ENTITY_P (key
))
366 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
367 eassert (CONSP (val
));
373 if (NILP (ft_face_cache
))
376 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
379 if (NILP (ft_face_cache
))
380 ft_face_cache
= CALLN (Fmake_hash_table
, QCtest
, Qequal
);
381 cache_data
= xmalloc (sizeof *cache_data
);
382 cache_data
->ft_face
= NULL
;
383 cache_data
->fc_charset
= NULL
;
384 val
= make_save_ptr_int (cache_data
, 0);
385 cache
= Fcons (Qnil
, val
);
386 Fputhash (key
, cache
, ft_face_cache
);
391 cache_data
= XSAVE_POINTER (val
, 0);
394 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
397 if (cache_for
== FTFONT_CACHE_FOR_FACE
398 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
400 char *filename
= SSDATA (XCAR (key
));
401 int idx
= XINT (XCDR (key
));
403 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
406 && FT_Init_FreeType (&ft_library
) != 0)
408 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
414 FcPattern
*pat
= NULL
;
415 FcFontSet
*fontset
= NULL
;
416 FcObjectSet
*objset
= NULL
;
417 FcCharSet
*charset
= NULL
;
419 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
420 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
423 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
426 fontset
= FcFontList (NULL
, pat
, objset
);
429 if (fontset
&& fontset
->nfont
> 0
430 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
433 cache_data
->fc_charset
= FcCharSetCopy (charset
);
435 cache_data
->fc_charset
= FcCharSetCreate ();
439 FcFontSetDestroy (fontset
);
441 FcObjectSetDestroy (objset
);
443 FcPatternDestroy (pat
);
450 ftfont_get_fc_charset (Lisp_Object entity
)
452 Lisp_Object val
, cache
;
453 struct ftfont_cache_data
*cache_data
;
455 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
457 cache_data
= XSAVE_POINTER (val
, 0);
458 return cache_data
->fc_charset
;
463 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
467 if (ftfont_info
->otf
)
468 return ftfont_info
->otf
;
469 if (! ftfont_info
->maybe_otf
)
471 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
472 if (! otf
|| OTF_get_table (otf
, "head") < 0)
476 ftfont_info
->maybe_otf
= 0;
479 ftfont_info
->otf
= otf
;
482 #endif /* HAVE_LIBOTF */
484 static Lisp_Object
ftfont_get_cache (struct frame
*);
485 static Lisp_Object
ftfont_list (struct frame
*, Lisp_Object
);
486 static Lisp_Object
ftfont_match (struct frame
*, Lisp_Object
);
487 static Lisp_Object
ftfont_list_family (struct frame
*);
488 static Lisp_Object
ftfont_open (struct frame
*, Lisp_Object
, int);
489 static void ftfont_close (struct font
*);
490 static int ftfont_has_char (Lisp_Object
, int);
491 static unsigned ftfont_encode_char (struct font
*, int);
492 static void ftfont_text_extents (struct font
*, unsigned *, int,
493 struct font_metrics
*);
494 static int ftfont_get_bitmap (struct font
*, unsigned,
495 struct font_bitmap
*, int);
496 static int ftfont_anchor_point (struct font
*, unsigned, int,
499 static Lisp_Object
ftfont_otf_capability (struct font
*);
500 # ifdef HAVE_M17N_FLT
501 static Lisp_Object
ftfont_shape (Lisp_Object
);
505 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
506 static int ftfont_variation_glyphs (struct font
*, int c
,
507 unsigned variations
[256]);
508 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
510 struct font_driver ftfont_driver
=
512 LISP_INITIALLY_ZERO
, /* Qfreetype */
513 0, /* case insensitive */
518 NULL
, /* free_entity */
521 /* We can't draw a text without device dependent functions. */
522 NULL
, /* prepare_face */
523 NULL
, /* done_face */
527 /* We can't draw a text without device dependent functions. */
530 NULL
, /* free_bitmap */
533 ftfont_otf_capability
,
534 #else /* not HAVE_LIBOTF */
536 #endif /* not HAVE_LIBOTF */
537 NULL
, /* otf_drive */
538 NULL
, /* start_for_frame */
539 NULL
, /* end_for_frame */
540 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
542 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
544 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
547 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
548 ftfont_variation_glyphs
,
553 ftfont_filter_properties
, /* filter_properties */
557 ftfont_get_cache (struct frame
*f
)
559 return freetype_font_cache
;
563 ftfont_get_charset (Lisp_Object registry
)
565 char *str
= SSDATA (SYMBOL_NAME (registry
));
567 char *re
= SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
571 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
575 else if (str
[i
] == '*')
582 regexp
= make_unibyte_string (re
, j
);
584 for (i
= 0; fc_charset_table
[i
].name
; i
++)
585 if (fast_c_string_match_ignore_case
586 (regexp
, fc_charset_table
[i
].name
,
587 strlen (fc_charset_table
[i
].name
)) >= 0)
589 if (! fc_charset_table
[i
].name
)
591 if (! fc_charset_table
[i
].fc_charset
)
593 FcCharSet
*charset
= FcCharSetCreate ();
594 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
598 for (j
= 0; uniquifier
[j
]; j
++)
599 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
601 FcCharSetDestroy (charset
);
604 fc_charset_table
[i
].fc_charset
= charset
;
612 unsigned int script_tag
, langsys_tag
;
614 unsigned int *features
[2];
617 #define OTF_SYM_TAG(SYM, TAG) \
619 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
620 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
623 #define OTF_TAG_STR(TAG, P) \
625 (P)[0] = (char) (TAG >> 24); \
626 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
627 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
628 (P)[3] = (char) (TAG & 0xFF); \
633 #define OTF_TAG_SYM(SYM, TAG) \
637 OTF_TAG_STR (TAG, str); \
638 (SYM) = font_intern_prop (str, 4, 1); \
643 static struct OpenTypeSpec
*
644 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
646 struct OpenTypeSpec
*spec
= malloc (sizeof *spec
);
653 spec
->script
= XCAR (otf_spec
);
654 if (! NILP (spec
->script
))
656 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
657 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
658 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
659 spec
->script
= XCDR (val
);
664 spec
->script_tag
= 0x44464C54; /* "DFLT" */
665 otf_spec
= XCDR (otf_spec
);
666 spec
->langsys_tag
= 0;
667 if (! NILP (otf_spec
))
669 val
= XCAR (otf_spec
);
671 OTF_SYM_TAG (val
, spec
->langsys_tag
);
672 otf_spec
= XCDR (otf_spec
);
674 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
675 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
679 val
= XCAR (otf_spec
);
684 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
686 : malloc (XINT (len
) * sizeof *spec
->features
[i
]));
687 if (! spec
->features
[i
])
689 if (i
> 0 && spec
->features
[0])
690 free (spec
->features
[0]);
694 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
696 if (NILP (XCAR (val
)))
702 OTF_SYM_TAG (XCAR (val
), tag
);
703 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
706 spec
->nfeatures
[i
] = j
;
712 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
714 Lisp_Object tmp
, extra
;
715 FcPattern
*pattern
= NULL
;
716 FcCharSet
*charset
= NULL
;
717 FcLangSet
*langset
= NULL
;
721 Lisp_Object script
= Qnil
;
722 Lisp_Object registry
;
725 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
727 /* Fontconfig doesn't support reverse-italic/oblique. */
730 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
731 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
732 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
733 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
736 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
738 || EQ (registry
, Qascii_0
)
739 || EQ (registry
, Qiso10646_1
)
740 || EQ (registry
, Qunicode_bmp
))
746 fc_charset_idx
= ftfont_get_charset (registry
);
747 if (fc_charset_idx
< 0)
749 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
750 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
751 lang
= (FcChar8
*) *langname
;
754 langset
= FcLangSetCreate ();
757 FcLangSetAdd (langset
, lang
);
762 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
763 CONSP (extra
); extra
= XCDR (extra
))
765 Lisp_Object key
, val
;
767 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
773 else if (EQ (key
, QClang
))
776 langset
= FcLangSetCreate ();
781 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
785 for (; CONSP (val
); val
= XCDR (val
))
786 if (SYMBOLP (XCAR (val
))
787 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
790 else if (EQ (key
, QCotf
))
794 *otspec
= ftfont_get_open_type_spec (val
);
797 strcpy (otlayout
, "otlayout:");
798 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
799 script
= (*otspec
)->script
;
802 else if (EQ (key
, QCscript
))
804 else if (EQ (key
, QCscalable
))
805 scalable
= ! NILP (val
);
808 if (! NILP (script
) && ! charset
)
810 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
812 if (CONSP (chars
) && CONSP (CDR (chars
)))
814 charset
= FcCharSetCreate ();
817 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
818 if (CHARACTERP (XCAR (chars
))
819 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
824 pattern
= FcPatternCreate ();
827 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
829 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
831 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
833 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
836 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
839 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
842 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
845 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
851 /* We come here because of unexpected error in fontconfig API call
852 (usually insufficient memory). */
855 FcPatternDestroy (pattern
);
860 if ((*otspec
)->nfeatures
[0] > 0)
861 free ((*otspec
)->features
[0]);
862 if ((*otspec
)->nfeatures
[1] > 0)
863 free ((*otspec
)->features
[1]);
869 if (langset
) FcLangSetDestroy (langset
);
870 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
875 ftfont_list (struct frame
*f
, Lisp_Object spec
)
877 Lisp_Object val
= Qnil
, family
, adstyle
;
880 FcFontSet
*fontset
= NULL
;
881 FcObjectSet
*objset
= NULL
;
883 Lisp_Object chars
= Qnil
;
884 char otlayout
[15]; /* For "otlayout:XXXX" */
885 struct OpenTypeSpec
*otspec
= NULL
;
887 const char *langname
= NULL
;
889 if (! fc_initialized
)
895 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
898 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
900 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
903 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
904 if (CONSP (val
) && VECTORP (XCDR (val
)))
909 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
910 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
911 family
= AREF (spec
, FONT_FAMILY_INDEX
);
914 Lisp_Object resolved
;
916 resolved
= ftfont_resolve_generic_family (family
, pattern
);
917 if (! NILP (resolved
))
919 FcPatternDel (pattern
, FC_FAMILY
);
920 if (! FcPatternAddString (pattern
, FC_FAMILY
,
921 SYMBOL_FcChar8 (resolved
)))
925 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
926 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
928 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
929 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
930 FC_STYLE
, FC_FILE
, FC_INDEX
,
933 #endif /* FC_CAPABILITY */
941 FcObjectSetAdd (objset
, FC_CHARSET
);
943 fontset
= FcFontList (NULL
, pattern
, objset
);
944 if (! fontset
|| fontset
->nfont
== 0)
947 /* Need fix because this finds any fonts. */
948 if (fontset
->nfont
== 0 && ! NILP (family
))
950 /* Try matching with configuration. For instance, the
951 configuration may specify "Nimbus Mono L" as an alias of
953 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
954 SYMBOL_FcChar8 (family
), NULL
);
957 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
960 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
963 FcPatternDel (pattern
, FC_FAMILY
);
964 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
965 FcFontSetDestroy (fontset
);
966 fontset
= FcFontList (NULL
, pattern
, objset
);
967 if (fontset
&& fontset
->nfont
> 0)
973 for (i
= 0; i
< fontset
->nfont
; i
++)
981 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
992 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
994 || ! strstr ((char *) this, otlayout
))
997 #endif /* FC_CAPABILITY */
1005 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1008 otf
= OTF_open ((char *) file
);
1011 passed
= (OTF_check_features (otf
, 1, otspec
->script_tag
,
1012 otspec
->langsys_tag
,
1013 otspec
->features
[0],
1014 otspec
->nfeatures
[0]) == 1
1015 && OTF_check_features (otf
, 0, otspec
->script_tag
,
1016 otspec
->langsys_tag
,
1017 otspec
->features
[1],
1018 otspec
->nfeatures
[1]) == 1);
1023 #endif /* HAVE_LIBOTF */
1024 if (VECTORP (chars
))
1028 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1031 for (j
= 0; j
< ASIZE (chars
); j
++)
1032 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1033 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1035 if (j
== ASIZE (chars
))
1038 if (! NILP (adstyle
) || langname
)
1040 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1042 if (! NILP (adstyle
)
1043 && (NILP (this_adstyle
)
1044 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1045 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1048 && ! NILP (this_adstyle
)
1049 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1052 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1053 AREF (spec
, FONT_EXTRA_INDEX
));
1054 if (! NILP (entity
))
1055 val
= Fcons (entity
, val
);
1057 val
= Fnreverse (val
);
1061 /* We come here because of unexpected error in fontconfig API call
1062 (usually insufficient memory). */
1066 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1067 if (objset
) FcObjectSetDestroy (objset
);
1068 if (fontset
) FcFontSetDestroy (fontset
);
1069 if (pattern
) FcPatternDestroy (pattern
);
1074 ftfont_match (struct frame
*f
, Lisp_Object spec
)
1076 Lisp_Object entity
= Qnil
;
1077 FcPattern
*pattern
, *match
= NULL
;
1079 char otlayout
[15]; /* For "otlayout:XXXX" */
1080 struct OpenTypeSpec
*otspec
= NULL
;
1081 const char *langname
= NULL
;
1083 if (! fc_initialized
)
1089 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1093 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1097 value
.type
= FcTypeDouble
;
1098 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1099 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1101 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1103 FcDefaultSubstitute (pattern
);
1104 match
= FcFontMatch (NULL
, pattern
, &result
);
1107 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1108 FcPatternDestroy (match
);
1109 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1110 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1111 ftfont_generic_family_list
))
1112 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1113 AREF (entity
, FONT_FAMILY_INDEX
))))
1117 FcPatternDestroy (pattern
);
1119 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1124 ftfont_list_family (struct frame
*f
)
1126 Lisp_Object list
= Qnil
;
1127 FcPattern
*pattern
= NULL
;
1128 FcFontSet
*fontset
= NULL
;
1129 FcObjectSet
*objset
= NULL
;
1132 if (! fc_initialized
)
1138 pattern
= FcPatternCreate ();
1141 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1144 fontset
= FcFontList (NULL
, pattern
, objset
);
1148 for (i
= 0; i
< fontset
->nfont
; i
++)
1150 FcPattern
*pat
= fontset
->fonts
[i
];
1153 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1154 list
= Fcons (intern ((char *) str
), list
);
1158 if (objset
) FcObjectSetDestroy (objset
);
1159 if (fontset
) FcFontSetDestroy (fontset
);
1160 if (pattern
) FcPatternDestroy (pattern
);
1167 ftfont_open2 (struct frame
*f
,
1170 Lisp_Object font_object
)
1172 struct ftfont_info
*ftfont_info
;
1174 struct ftfont_cache_data
*cache_data
;
1178 Lisp_Object val
, filename
, idx
, cache
;
1184 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1188 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1191 filename
= XCAR (val
);
1194 cache_data
= XSAVE_POINTER (XCDR (cache
), 0);
1195 ft_face
= cache_data
->ft_face
;
1196 if (XSAVE_INTEGER (val
, 1) > 0)
1198 /* FT_Face in this cache is already used by the different size. */
1199 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1201 if (FT_Activate_Size (ft_size
) != 0)
1203 FT_Done_Size (ft_size
);
1207 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) + 1);
1208 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1211 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1213 if (XSAVE_INTEGER (val
, 1) == 0)
1214 FT_Done_Face (ft_face
);
1218 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1219 font
= XFONT_OBJECT (font_object
);
1220 ftfont_info
= (struct ftfont_info
*) font
;
1221 ftfont_info
->ft_size
= ft_face
->size
;
1222 ftfont_info
->index
= XINT (idx
);
1224 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1225 ftfont_info
->otf
= NULL
;
1226 #endif /* HAVE_LIBOTF */
1227 /* This means that there's no need of transformation. */
1228 ftfont_info
->matrix
.xx
= 0;
1229 font
->pixel_size
= size
;
1230 font
->driver
= &ftfont_driver
;
1231 font
->encoding_charset
= font
->repertory_charset
= -1;
1233 upEM
= ft_face
->units_per_EM
;
1234 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1235 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1238 font
->ascent
= ft_face
->ascender
* size
/ upEM
+ 0.5;
1239 font
->descent
= - ft_face
->descender
* size
/ upEM
+ 0.5;
1240 font
->height
= ft_face
->height
* size
/ upEM
+ 0.5;
1244 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1245 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1246 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1248 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1249 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1251 spacing
= FC_PROPORTIONAL
;
1252 if (spacing
!= FC_PROPORTIONAL
1254 && spacing
!= FC_DUAL
1255 #endif /* FC_DUAL */
1257 font
->min_width
= font
->average_width
= font
->space_width
1258 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
+ 0.5
1259 : ft_face
->size
->metrics
.max_advance
>> 6);
1264 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1265 for (i
= 32, n
= 0; i
< 127; i
++)
1266 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1268 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1271 && (! font
->min_width
|| font
->min_width
> this_width
))
1272 font
->min_width
= this_width
;
1274 font
->space_width
= this_width
;
1275 font
->average_width
+= this_width
;
1279 font
->average_width
/= n
;
1282 font
->baseline_offset
= 0;
1283 font
->relative_compose
= 0;
1284 font
->default_ascent
= 0;
1285 font
->vertical_centering
= 0;
1288 font
->underline_position
= (-ft_face
->underline_position
* size
/ upEM
1290 font
->underline_thickness
= (ft_face
->underline_thickness
* size
/ upEM
1295 font
->underline_position
= -1;
1296 font
->underline_thickness
= 0;
1303 ftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
1305 Lisp_Object font_object
;
1307 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1310 font_object
= font_build_object (VECSIZE (struct ftfont_info
),
1311 Qfreetype
, entity
, size
);
1312 return ftfont_open2 (f
, entity
, pixel_size
, font_object
);
1316 ftfont_close (struct font
*font
)
1318 /* FIXME: Although this function can be called while garbage-collecting,
1319 the function assumes that Lisp data structures are properly-formed.
1320 This invalid assumption can lead to core dumps (Bug#20890). */
1322 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1323 Lisp_Object val
, cache
;
1325 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1326 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1327 eassert (CONSP (cache
));
1329 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) - 1);
1330 if (XSAVE_INTEGER (val
, 1) == 0)
1332 struct ftfont_cache_data
*cache_data
= XSAVE_POINTER (val
, 0);
1334 FT_Done_Face (cache_data
->ft_face
);
1336 if (ftfont_info
->otf
)
1337 OTF_close (ftfont_info
->otf
);
1339 cache_data
->ft_face
= NULL
;
1342 FT_Done_Size (ftfont_info
->ft_size
);
1346 ftfont_has_char (Lisp_Object font
, int c
)
1348 struct charset
*cs
= NULL
;
1350 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1351 && charset_jisx0208
>= 0)
1352 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1353 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1354 && charset_ksc5601
>= 0)
1355 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1357 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1359 if (FONT_ENTITY_P (font
))
1361 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1363 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1367 struct ftfont_info
*ftfont_info
;
1369 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1370 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1376 ftfont_encode_char (struct font
*font
, int c
)
1378 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1379 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1380 FT_ULong charcode
= c
;
1381 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1383 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1387 ftfont_text_extents (struct font
*font
, unsigned int *code
,
1388 int nglyphs
, struct font_metrics
*metrics
)
1390 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1391 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1395 if (ftfont_info
->ft_size
!= ft_face
->size
)
1396 FT_Activate_Size (ftfont_info
->ft_size
);
1398 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1400 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1402 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1406 metrics
->lbearing
= m
->horiBearingX
>> 6;
1407 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1408 metrics
->ascent
= m
->horiBearingY
>> 6;
1409 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1412 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1413 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1414 if (metrics
->rbearing
1415 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1417 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1418 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1419 metrics
->ascent
= m
->horiBearingY
>> 6;
1420 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1421 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1422 width
+= m
->horiAdvance
>> 6;
1425 width
+= font
->space_width
;
1427 metrics
->width
= width
;
1431 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1433 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1434 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1435 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1437 if (ftfont_info
->ft_size
!= ft_face
->size
)
1438 FT_Activate_Size (ftfont_info
->ft_size
);
1439 if (bits_per_pixel
== 1)
1441 #ifdef FT_LOAD_TARGET_MONO
1442 load_flags
|= FT_LOAD_TARGET_MONO
;
1444 load_flags
|= FT_LOAD_MONOCHROME
;
1447 else if (bits_per_pixel
!= 8)
1448 /* We don't support such a rendering. */
1451 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1453 bitmap
->bits_per_pixel
1454 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1455 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1456 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1457 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1459 if (bitmap
->bits_per_pixel
< 0)
1460 /* We don't support that kind of pixel mode. */
1462 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1463 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1464 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1465 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1466 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1467 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1468 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1474 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1477 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1478 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1480 if (ftfont_info
->ft_size
!= ft_face
->size
)
1481 FT_Activate_Size (ftfont_info
->ft_size
);
1482 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1484 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1486 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1488 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1489 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1496 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1498 Lisp_Object scripts
, langsyses
, features
, sym
;
1501 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1503 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1505 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1507 OTF_LangSys
*otf_langsys
;
1510 otf_langsys
= otf_script
->LangSys
+ j
;
1511 else if (otf_script
->DefaultLangSysOffset
)
1512 otf_langsys
= &otf_script
->DefaultLangSys
;
1516 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1518 l
= otf_langsys
->FeatureIndex
[k
];
1519 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1521 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1522 features
= Fcons (sym
, features
);
1525 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1528 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1531 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1532 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1540 ftfont_otf_capability (struct font
*font
)
1542 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1543 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1544 Lisp_Object gsub_gpos
;
1548 gsub_gpos
= Fcons (Qnil
, Qnil
);
1549 if (OTF_get_table (otf
, "GSUB") == 0
1550 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1551 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1552 if (OTF_get_table (otf
, "GPOS") == 0
1553 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1554 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1558 #ifdef HAVE_M17N_FLT
1560 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1561 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1562 /* We can use the new feature of libotf and m17n-flt to handle the
1563 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1564 some Agian scripts. */
1565 #define M17N_FLT_USE_NEW_FEATURE
1577 /* The actual type of elements in the array MFLTGlyphString.glyphs.
1578 We use this structure instead of MFLTGlyph to utilize the new
1579 feature of libotf ver.0.9.15 which requires saving and restoring
1580 the value of OTF_GlyphString.positioning_type in the succeeding
1581 calls of the callback function MFLTFont.drive_otf (which is set to
1582 ftfont_drive_otf). */
1586 unsigned int libotf_positioning_type
;
1590 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1593 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1594 FT_Face ft_face
= flt_font_ft
->ft_face
;
1597 for (g
= (MFLTGlyphFT
*) (gstring
->glyphs
) + from
; from
< to
; g
++, from
++)
1600 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->g
.code
);
1602 g
->g
.code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1608 /* Operators for 26.6 fixed fractional pixel format */
1610 #define FLOOR(x) ((x) & -64)
1611 #define CEIL(x) (((x)+63) & -64)
1612 #define ROUND(x) (((x)+32) & -64)
1615 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1618 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1619 FT_Face ft_face
= flt_font_ft
->ft_face
;
1622 for (g
= (MFLTGlyphFT
*) (gstring
->glyphs
) + from
; from
< to
; g
++, from
++)
1623 if (! g
->g
.measured
)
1625 if (g
->g
.code
!= FONT_INVALID_CODE
)
1627 FT_Glyph_Metrics
*m
;
1629 if (FT_Load_Glyph (ft_face
, g
->g
.code
, FT_LOAD_DEFAULT
) != 0)
1631 m
= &ft_face
->glyph
->metrics
;
1632 if (flt_font_ft
->matrix
)
1637 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1638 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1639 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1640 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1641 for (i
= 0; i
< 4; i
++)
1642 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1643 g
->g
.lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1644 g
->g
.rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1645 g
->g
.ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1646 g
->g
.descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1650 g
->g
.lbearing
= FLOOR (m
->horiBearingX
);
1651 g
->g
.rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1652 g
->g
.ascent
= CEIL (m
->horiBearingY
);
1653 g
->g
.descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1655 g
->g
.xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1660 g
->g
.rbearing
= g
->g
.xadv
= flt_font_ft
->font
->space_width
<< 6;
1661 g
->g
.ascent
= flt_font_ft
->font
->ascent
<< 6;
1662 g
->g
.descent
= flt_font_ft
->font
->descent
<< 6;
1671 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1673 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1675 #define FEATURE_ANY(IDX) \
1676 (spec->features[IDX] \
1677 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1679 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1680 OTF
*otf
= flt_font_ft
->otf
;
1685 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1686 /* Return true iff any of GSUB or GPOS support the script (and
1689 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1691 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1694 for (i
= 0; i
< 2; i
++)
1695 if (! FEATURE_ANY (i
))
1697 if (FEATURE_NONE (i
))
1700 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1705 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1708 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1714 for (n
= 1; spec
->features
[i
][n
]; n
++);
1716 SAFE_NALLOCA (tags
, 1, n
);
1717 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1719 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1722 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1724 tags
[n
] = spec
->features
[i
][n
];
1727 #ifndef M17N_FLT_USE_NEW_FEATURE
1728 passed
= n
- negative
> 0;
1731 passed
= (OTF_check_features (otf
, i
== 0, spec
->script
,
1732 spec
->langsys
, tags
, n
- negative
)
1743 #define DEVICE_DELTA(table, size) \
1744 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1745 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1749 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1750 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1752 if (anchor
->AnchorFormat
== 2)
1754 FT_Outline
*outline
;
1755 int ap
= anchor
->f
.f1
.AnchorPoint
;
1757 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1758 outline
= &ft_face
->glyph
->outline
;
1759 if (ap
< outline
->n_points
)
1761 *x
= outline
->points
[ap
].x
<< 6;
1762 *y
= outline
->points
[ap
].y
<< 6;
1765 else if (anchor
->AnchorFormat
== 3)
1767 if (anchor
->f
.f2
.XDeviceTable
.offset
1768 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1769 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1770 if (anchor
->f
.f2
.YDeviceTable
.offset
1771 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1772 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1776 static OTF_GlyphString otf_gstring
;
1779 setup_otf_gstring (int size
)
1781 if (otf_gstring
.size
< size
)
1783 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1784 size
, sizeof (OTF_Glyph
));
1785 otf_gstring
.size
= size
;
1787 otf_gstring
.used
= size
;
1788 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1791 #ifdef M17N_FLT_USE_NEW_FEATURE
1793 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1794 #define PACK_OTF_TAG(TAG) \
1795 ((((TAG) & 0x7F000000) >> 3) \
1796 | (((TAG) & 0x7F0000) >> 2) \
1797 | (((TAG) & 0x7F00) >> 1) \
1800 /* Assuming that FONT is an OpenType font, apply OpenType features
1801 specified in SPEC on glyphs between FROM and TO of IN, and record
1802 the lastly applied feature in each glyph of IN. If OUT is not
1803 NULL, append the resulting glyphs to OUT while storing glyph
1804 position adjustment information in ADJUSTMENT. */
1807 ftfont_drive_otf (MFLTFont
*font
,
1809 MFLTGlyphString
*in
,
1812 MFLTGlyphString
*out
,
1813 MFLTGlyphAdjustment
*adjustment
)
1815 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1816 MFLTGlyphFT
*in_glyphs
= (MFLTGlyphFT
*) (in
->glyphs
) + from
;
1817 MFLTGlyphFT
*out_glyphs
= out
? (MFLTGlyphFT
*) (out
->glyphs
) : NULL
;
1818 FT_Face ft_face
= flt_font_ft
->ft_face
;
1819 OTF
*otf
= flt_font_ft
->otf
;
1820 int len
= to
- from
;
1823 char script
[5], *langsys
= NULL
;
1824 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1825 OTF_Feature
*features
;
1829 OTF_tag_name (spec
->script
, script
);
1834 langsys
= langsysbuf
;
1835 OTF_tag_name (spec
->langsys
, langsys
);
1839 for (i
= 0; i
< 2; i
++)
1843 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1845 for (j
= 0; spec
->features
[i
][j
]; j
++);
1846 SAFE_NALLOCA (p
, 6, j
);
1851 for (j
= 0; spec
->features
[i
][j
]; j
++)
1853 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1854 *p
++ = '*', *p
++ = ',';
1857 OTF_tag_name (spec
->features
[i
][j
], p
);
1866 setup_otf_gstring (len
);
1867 for (i
= 0; i
< len
; i
++)
1869 otf_gstring
.glyphs
[i
].c
= in_glyphs
[i
].g
.c
& 0x11FFFF;
1870 otf_gstring
.glyphs
[i
].glyph_id
= in_glyphs
[i
].g
.code
;
1871 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1872 otf_gstring
.glyphs
[i
].positioning_type
= in_glyphs
[i
].libotf_positioning_type
;
1876 OTF_drive_gdef (otf
, &otf_gstring
);
1877 gidx
= out
? out
->used
: from
;
1879 if (gsub_features
&& out
)
1881 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1882 if (OTF_drive_gsub_features (otf
, &otf_gstring
, script
, langsys
,
1886 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1890 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1895 features
= otf
->gsub
->FeatureList
.Feature
;
1896 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1899 int min_from
, max_to
;
1902 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1903 feature_idx
= OTF_POSITIONING_TYPE_GET_FEATURE (otfg
);
1905 feature_idx
= otfg
->positioning_type
>> 4;
1907 g
= out_glyphs
+ out
->used
;
1908 *g
= in_glyphs
[otfg
->f
.index
.from
];
1909 if (g
->g
.code
!= otfg
->glyph_id
)
1912 g
->g
.code
= otfg
->glyph_id
;
1916 min_from
= g
->g
.from
;
1918 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1920 /* OTFG substitutes multiple glyphs in IN. */
1921 for (j
= otfg
->f
.index
.from
+ 1; j
<= otfg
->f
.index
.to
; j
++)
1923 if (min_from
> in_glyphs
[j
].g
.from
)
1924 min_from
= in_glyphs
[j
].g
.from
;
1925 if (max_to
< in_glyphs
[j
].g
.to
)
1926 max_to
= in_glyphs
[j
].g
.to
;
1928 g
->g
.from
= min_from
;
1933 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1934 tag
= PACK_OTF_TAG (tag
);
1935 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
1937 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1938 g
->libotf_positioning_type
1939 = otfg
->positioning_type
& OTF_positioning_type_components_mask
;
1941 for (i
++, otfg
++; (i
< otf_gstring
.used
1942 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1945 g
= out_glyphs
+ out
->used
;
1946 *g
= in_glyphs
[otfg
->f
.index
.to
];
1947 if (g
->g
.code
!= otfg
->glyph_id
)
1950 g
->g
.code
= otfg
->glyph_id
;
1953 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1954 feature_idx
= OTF_POSITIONING_TYPE_GET_FEATURE (otfg
);
1956 feature_idx
= otfg
->positioning_type
>> 4;
1960 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1961 tag
= PACK_OTF_TAG (tag
);
1962 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
1964 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1965 g
->libotf_positioning_type
1966 = otfg
->positioning_type
& OTF_positioning_type_components_mask
;
1972 else if (gsub_features
)
1974 /* Just for checking which features will be applied. */
1975 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1976 if (OTF_drive_gsub_features (otf
, &otf_gstring
, script
, langsys
,
1980 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1984 features
= otf
->gsub
->FeatureList
.Feature
;
1985 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1989 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1990 feature_idx
= OTF_POSITIONING_TYPE_GET_FEATURE (otfg
);
1992 feature_idx
= otfg
->positioning_type
>> 4;
1996 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1997 tag
= PACK_OTF_TAG (tag
);
1998 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2000 MFLTGlyphFT
*g
= in_glyphs
+ j
;
2001 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
2008 if (out
->allocated
< out
->used
+ len
)
2013 for (i
= 0; i
< len
; i
++)
2014 out_glyphs
[out
->used
++] = in_glyphs
[i
];
2017 if (gpos_features
&& out
)
2019 MFLTGlyphFT
*base
= NULL
, *mark
= NULL
, *g
;
2020 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2022 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2023 if (OTF_drive_gpos_features (otf
, &otf_gstring
, script
, langsys
,
2030 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2037 features
= otf
->gpos
->FeatureList
.Feature
;
2038 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2039 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2040 x_scale
= ft_face
->size
->metrics
.x_scale
;
2041 y_scale
= ft_face
->size
->metrics
.y_scale
;
2043 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out_glyphs
+ gidx
;
2044 i
< otf_gstring
.used
; i
++, otfg
++)
2046 MFLTGlyphAdjustment
*adjust
= adjustment
;
2048 int positioning_type
, feature_idx
;
2050 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2051 positioning_type
= OTF_POSITIONING_TYPE_GET_FORMAT (otfg
);
2052 feature_idx
= OTF_POSITIONING_TYPE_GET_FEATURE (otfg
);
2054 positioning_type
= otfg
->positioning_type
& 0xF;
2055 feature_idx
= otfg
->positioning_type
>> 4;
2059 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2060 tag
= PACK_OTF_TAG (tag
);
2061 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
2064 if (! otfg
->glyph_id
)
2065 /* This is a pseudo glyph that contains positioning
2066 information to be accumulated to a real glyph. */
2068 switch (positioning_type
)
2072 case 1: /* Single */
2075 int format
= otfg
->f
.f1
.format
;
2077 if (format
& OTF_XPlacement
)
2079 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2080 if (format
& OTF_XPlaDevice
)
2082 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2083 if (format
& OTF_YPlacement
)
2085 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2086 if (format
& OTF_YPlaDevice
)
2088 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2089 if (format
& OTF_XAdvance
)
2091 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2092 if (format
& OTF_XAdvDevice
)
2094 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2095 if (format
& OTF_YAdvance
)
2097 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2098 if (format
& OTF_YAdvDevice
)
2100 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2104 case 3: /* Cursive */
2105 /* Not yet supported. */
2107 case 4: /* Mark-to-Base */
2108 case 5: /* Mark-to-Ligature */
2112 goto label_adjust_anchor
;
2113 default: /* i.e. case 6 Mark-to-Mark */
2117 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2119 int distance
= OTF_POSITIONING_TYPE_GET_MARKDISTANCE (otfg
);
2123 prev
= g
- distance
;
2124 if (prev
< out_glyphs
)
2130 label_adjust_anchor
:
2132 int base_x
, base_y
, mark_x
, mark_y
;
2133 int this_from
, this_to
;
2135 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2136 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2137 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2138 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2140 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2141 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
, prev
->g
.code
,
2142 x_ppem
, y_ppem
, &base_x
, &base_y
);
2143 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2144 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->g
.code
,
2145 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2146 adjust
->xoff
= (base_x
- mark_x
);
2147 adjust
->yoff
= - (base_y
- mark_y
);
2148 adjust
->back
= (g
- prev
);
2150 adjust
->advance_is_absolute
= 1;
2152 this_from
= g
->g
.from
;
2154 for (j
= 0; prev
+ j
< g
; j
++)
2156 if (this_from
> prev
[j
].g
.from
)
2157 this_from
= prev
[j
].g
.from
;
2158 if (this_to
< prev
[j
].g
.to
)
2159 this_to
= prev
[j
].g
.to
;
2161 for (; prev
<= g
; prev
++)
2163 prev
->g
.from
= this_from
;
2164 prev
->g
.to
= this_to
;
2170 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2172 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2180 else if (gpos_features
)
2182 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2188 features
= otf
->gpos
->FeatureList
.Feature
;
2189 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2191 if (otfg
->positioning_type
& 0xF)
2193 int feature_idx
= otfg
->positioning_type
>> 4;
2197 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2198 tag
= PACK_OTF_TAG (tag
);
2199 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2201 MFLTGlyphFT
*g
= in_glyphs
+ j
;
2202 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
2214 if (out
->allocated
< out
->used
+ len
)
2216 font
->get_metrics (font
, in
, from
, to
);
2217 memcpy (out
->glyphs
+ out
->used
, in_glyphs
, sizeof (MFLTGlyphFT
) * len
);
2223 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2224 MFLTGlyphString
*in
, int from
, int to
)
2226 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2229 #else /* not M17N_FLT_USE_NEW_FEATURE */
2232 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2234 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2236 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2237 FT_Face ft_face
= flt_font_ft
->ft_face
;
2238 OTF
*otf
= flt_font_ft
->otf
;
2239 int len
= to
- from
;
2242 char script
[5], *langsys
= NULL
;
2243 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2247 OTF_tag_name (spec
->script
, script
);
2252 langsys
= langsysbuf
;
2253 OTF_tag_name (spec
->langsys
, langsys
);
2257 for (i
= 0; i
< 2; i
++)
2261 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2263 for (j
= 0; spec
->features
[i
][j
]; j
++);
2264 SAFE_NALLOCA (p
, 6, j
);
2269 for (j
= 0; spec
->features
[i
][j
]; j
++)
2271 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2272 *p
++ = '*', *p
++ = ',';
2275 OTF_tag_name (spec
->features
[i
][j
], p
);
2284 setup_otf_gstring (len
);
2285 for (i
= 0; i
< len
; i
++)
2287 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2288 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2291 OTF_drive_gdef (otf
, &otf_gstring
);
2296 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2299 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2304 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2307 int min_from
, max_to
;
2310 g
= out
->glyphs
+ out
->used
;
2311 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2312 if (g
->code
!= otfg
->glyph_id
)
2315 g
->code
= otfg
->glyph_id
;
2321 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2323 /* OTFG substitutes multiple glyphs in IN. */
2324 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2325 j
<= from
+ otfg
->f
.index
.to
; j
++)
2327 if (min_from
> in
->glyphs
[j
].from
)
2328 min_from
= in
->glyphs
[j
].from
;
2329 if (max_to
< in
->glyphs
[j
].to
)
2330 max_to
= in
->glyphs
[j
].to
;
2335 for (i
++, otfg
++; (i
< otf_gstring
.used
2336 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2339 g
= out
->glyphs
+ out
->used
;
2340 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2341 if (g
->code
!= otfg
->glyph_id
)
2344 g
->code
= otfg
->glyph_id
;
2353 if (out
->allocated
< out
->used
+ len
)
2358 for (i
= 0; i
< len
; i
++)
2359 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2364 MFLTGlyphFT
*base
= NULL
, *mark
= NULL
, *g
;
2365 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2367 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2374 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2375 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2376 x_scale
= ft_face
->size
->metrics
.x_scale
;
2377 y_scale
= ft_face
->size
->metrics
.y_scale
;
2379 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2380 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2384 if (! otfg
->glyph_id
)
2386 switch (otfg
->positioning_type
)
2390 case 1: /* Single */
2393 int format
= otfg
->f
.f1
.format
;
2395 if (format
& OTF_XPlacement
)
2397 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2398 if (format
& OTF_XPlaDevice
)
2400 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2401 if (format
& OTF_YPlacement
)
2403 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2404 if (format
& OTF_YPlaDevice
)
2406 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2407 if (format
& OTF_XAdvance
)
2409 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2410 if (format
& OTF_XAdvDevice
)
2412 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2413 if (format
& OTF_YAdvance
)
2415 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2416 if (format
& OTF_YAdvDevice
)
2418 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2419 adjustment
[i
].set
= 1;
2422 case 3: /* Cursive */
2423 /* Not yet supported. */
2425 case 4: /* Mark-to-Base */
2426 case 5: /* Mark-to-Ligature */
2430 goto label_adjust_anchor
;
2431 default: /* i.e. case 6 Mark-to-Mark */
2436 label_adjust_anchor
:
2438 int base_x
, base_y
, mark_x
, mark_y
;
2439 int this_from
, this_to
;
2441 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2442 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2443 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2444 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2446 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2447 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2448 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2449 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2450 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2451 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2452 adjustment
[i
].xoff
= (base_x
- mark_x
);
2453 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2454 adjustment
[i
].back
= (g
- prev
);
2455 adjustment
[i
].xadv
= 0;
2456 adjustment
[i
].advance_is_absolute
= 1;
2457 adjustment
[i
].set
= 1;
2458 this_from
= g
->from
;
2460 for (j
= 0; prev
+ j
< g
; j
++)
2462 if (this_from
> prev
[j
].from
)
2463 this_from
= prev
[j
].from
;
2464 if (this_to
< prev
[j
].to
)
2465 this_to
= prev
[j
].to
;
2467 for (; prev
<= g
; prev
++)
2469 prev
->from
= this_from
;
2474 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2476 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2487 if (out
->allocated
< out
->used
+ len
)
2489 font
->get_metrics (font
, in
, from
, to
);
2490 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2491 sizeof (MFLTGlyph
) * len
);
2496 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2498 static MFLTGlyphString gstring
;
2500 static bool m17n_flt_initialized
;
2503 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2504 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2506 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2508 struct MFLTFontFT flt_font_ft
;
2510 bool with_variation_selector
= 0;
2511 MFLTGlyphFT
*glyphs
;
2513 if (! m17n_flt_initialized
)
2516 #ifdef M17N_FLT_USE_NEW_FEATURE
2517 mflt_enable_new_feature
= 1;
2518 mflt_try_otf
= ftfont_try_otf
;
2519 #endif /* M17N_FLT_USE_NEW_FEATURE */
2520 m17n_flt_initialized
= 1;
2523 for (i
= 0; i
< len
; i
++)
2525 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2530 c
= LGLYPH_CHAR (g
);
2531 if (CHAR_VARIATION_SELECTOR_P (c
))
2532 with_variation_selector
= 1;
2537 if (with_variation_selector
)
2539 setup_otf_gstring (len
);
2540 for (i
= 0; i
< len
; i
++)
2542 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2544 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2545 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2546 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2548 OTF_drive_cmap (otf
, &otf_gstring
);
2549 for (i
= 0; i
< otf_gstring
.used
; i
++)
2551 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2552 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2553 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2555 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2556 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2557 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2559 if (len
> otf_gstring
.used
)
2561 len
= otf_gstring
.used
;
2562 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2566 if (INT_MAX
/ 2 < len
)
2567 memory_full (SIZE_MAX
);
2569 if (gstring
.allocated
== 0)
2571 gstring
.glyph_size
= sizeof (MFLTGlyphFT
);
2572 gstring
.glyphs
= xnmalloc (len
* 2, sizeof (MFLTGlyphFT
));
2573 gstring
.allocated
= len
* 2;
2575 else if (gstring
.allocated
< len
* 2)
2577 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2578 sizeof (MFLTGlyphFT
));
2579 gstring
.allocated
= len
* 2;
2581 glyphs
= (MFLTGlyphFT
*) (gstring
.glyphs
);
2582 memset (glyphs
, 0, len
* sizeof (MFLTGlyphFT
));
2583 for (i
= 0; i
< len
; i
++)
2585 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2587 glyphs
[i
].g
.c
= LGLYPH_CHAR (g
);
2588 if (with_variation_selector
)
2590 glyphs
[i
].g
.code
= LGLYPH_CODE (g
);
2591 glyphs
[i
].g
.encoded
= 1;
2599 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2602 flt_font_ft
.flt_font
.family
= Mnil
;
2604 flt_font_ft
.flt_font
.family
2605 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2607 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2608 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2609 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2610 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2611 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2612 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2613 flt_font_ft
.flt_font
.internal
= NULL
;
2614 flt_font_ft
.font
= font
;
2615 flt_font_ft
.ft_face
= ft_face
;
2616 flt_font_ft
.otf
= otf
;
2617 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2619 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2620 /* A little bit ad hoc. Perhaps, shaper must get script and
2621 language information, and select a proper flt for them
2623 flt
= mflt_get (msymbol ("combining"));
2624 for (i
= 0; i
< 3; i
++)
2626 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2629 if (INT_MAX
/ 2 < gstring
.allocated
)
2630 memory_full (SIZE_MAX
);
2631 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2632 gstring
.allocated
, 2 * sizeof (MFLTGlyphFT
));
2633 gstring
.allocated
*= 2;
2635 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2637 for (i
= 0; i
< gstring
.used
; i
++)
2639 MFLTGlyphFT
*g
= (MFLTGlyphFT
*) (gstring
.glyphs
) + i
;
2641 g
->g
.from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->g
.from
));
2642 g
->g
.to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->g
.to
));
2645 for (i
= 0; i
< gstring
.used
; i
++)
2647 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2648 MFLTGlyphFT
*g
= (MFLTGlyphFT
*) (gstring
.glyphs
) + i
;
2652 lglyph
= LGLYPH_NEW ();
2653 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2655 LGLYPH_SET_FROM (lglyph
, g
->g
.from
);
2656 LGLYPH_SET_TO (lglyph
, g
->g
.to
);
2657 LGLYPH_SET_CHAR (lglyph
, g
->g
.c
);
2658 LGLYPH_SET_CODE (lglyph
, g
->g
.code
);
2659 LGLYPH_SET_WIDTH (lglyph
, g
->g
.xadv
>> 6);
2660 LGLYPH_SET_LBEARING (lglyph
, g
->g
.lbearing
>> 6);
2661 LGLYPH_SET_RBEARING (lglyph
, g
->g
.rbearing
>> 6);
2662 LGLYPH_SET_ASCENT (lglyph
, g
->g
.ascent
>> 6);
2663 LGLYPH_SET_DESCENT (lglyph
, g
->g
.descent
>> 6);
2666 Lisp_Object vec
= make_uninit_vector (3);
2668 ASET (vec
, 0, make_number (g
->g
.xoff
>> 6));
2669 ASET (vec
, 1, make_number (g
->g
.yoff
>> 6));
2670 ASET (vec
, 2, make_number (g
->g
.xadv
>> 6));
2671 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2674 return make_number (i
);
2678 ftfont_shape (Lisp_Object lgstring
)
2680 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
2681 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2682 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2685 return make_number (0);
2686 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2687 &ftfont_info
->matrix
);
2690 #endif /* HAVE_M17N_FLT */
2692 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2695 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2697 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2698 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2702 return OTF_get_variation_glyphs (otf
, c
, variations
);
2705 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2706 #endif /* HAVE_LIBOTF */
2708 static const char *const ftfont_booleans
[] = {
2721 static const char *const ftfont_non_booleans
[] = {
2753 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2755 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2760 syms_of_ftfont (void)
2762 /* Symbolic type of this font-driver. */
2763 DEFSYM (Qfreetype
, "freetype");
2765 /* Fontconfig's generic families and their aliases. */
2766 DEFSYM (Qmonospace
, "monospace");
2767 DEFSYM (Qsans_serif
, "sans-serif");
2768 DEFSYM (Qsans
, "sans");
2769 DEFSYM (Qsans__serif
, "sans serif");
2771 staticpro (&freetype_font_cache
);
2772 freetype_font_cache
= list1 (Qt
);
2774 staticpro (&ftfont_generic_family_list
);
2775 ftfont_generic_family_list
= list3 (Fcons (Qmonospace
, Qt
),
2776 Fcons (Qsans_serif
, Qt
),
2779 staticpro (&ft_face_cache
);
2780 ft_face_cache
= Qnil
;
2782 ftfont_driver
.type
= Qfreetype
;
2783 register_font_driver (&ftfont_driver
, NULL
);