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"
31 #include "character.h"
33 #include "composite.h"
37 /* Flag to tell if FcInit is already called or not. */
38 static bool fc_initialized
;
40 /* Handle to a FreeType library instance. */
41 static FT_Library ft_library
;
43 /* Cache for FreeType fonts. */
44 static Lisp_Object freetype_font_cache
;
46 /* Cache for FT_Face and FcCharSet. */
47 static Lisp_Object ft_face_cache
;
49 /* The actual structure for FreeType font that can be cast to struct
56 /* The following four members must be here in this order to be
57 compatible with struct xftfont_info (in xftfont.c). */
58 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
60 #endif /* HAVE_LIBOTF */
66 size_t ftfont_info_size
= sizeof (struct ftfont_info
);
70 FTFONT_CACHE_FOR_FACE
,
71 FTFONT_CACHE_FOR_CHARSET
,
72 FTFONT_CACHE_FOR_ENTITY
75 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
77 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
79 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
80 enum ftfont_cache_for
);
82 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
84 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
90 /* characters to distinguish the charset from the others */
92 /* additional constraint by language */
95 FcCharSet
*fc_charset
;
96 } fc_charset_table
[] =
97 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
98 { "iso8859-2", { 0x00A0, 0x010E }},
99 { "iso8859-3", { 0x00A0, 0x0108 }},
100 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
101 { "iso8859-5", { 0x00A0, 0x0401 }},
102 { "iso8859-6", { 0x00A0, 0x060C }},
103 { "iso8859-7", { 0x00A0, 0x0384 }},
104 { "iso8859-8", { 0x00A0, 0x05D0 }},
105 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
106 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
107 { "iso8859-11", { 0x00A0, 0x0E01 }},
108 { "iso8859-13", { 0x00A0, 0x201C }},
109 { "iso8859-14", { 0x00A0, 0x0174 }},
110 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
111 { "iso8859-16", { 0x00A0, 0x0218}},
112 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
113 { "big5-0", { 0xF6B1 }, "zh-tw" },
114 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
115 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
116 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
117 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
118 { "cns11643.1992-3", { 0x201A9 }},
119 { "cns11643.1992-4", { 0x20057 }},
120 { "cns11643.1992-5", { 0x20000 }},
121 { "cns11643.1992-6", { 0x20003 }},
122 { "cns11643.1992-7", { 0x20055 }},
123 { "gbk-0", { 0x4E06 }, "zh-cn"},
124 { "jisx0212.1990-0", { 0x4E44 }},
125 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
126 { "jisx0213.2000-2", { 0xFA49 }},
127 { "jisx0213.2004-1", { 0x20B9F }},
128 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
129 { "tis620.2529-1", { 0x0E01 }, "th"},
130 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
131 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
132 { "mulelao-1", { 0x0E81 }, "lo"},
133 { "unicode-sip", { 0x20000 }},
138 matching_prefix (char const *str
, ptrdiff_t len
, char const *pat
)
140 return len
== strlen (pat
) && c_strncasecmp (str
, pat
, len
) == 0;
143 /* Dirty hack for handing ADSTYLE property.
145 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
146 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
147 "Oblique", "Italic", or any non-normal SWIDTH property names
148 (e.g. SemiCondensed) are appended. In addition, if there's no
149 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
150 "Regular" is used for FC_STYLE (see the function
151 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
153 Unfortunately this behavior is not documented, so the following
154 code may fail if FreeType changes the behavior in the future. */
157 get_adstyle_property (FcPattern
*p
)
164 if ((FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fcstr
) == FcResultMatch
)
165 && xstrcasecmp ((char *) fcstr
, "bdf") != 0
166 && xstrcasecmp ((char *) fcstr
, "pcf") != 0)
167 /* Not a BDF nor PCF font. */
170 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
172 str
= (char *) fcstr
;
173 for (end
= str
; *end
&& *end
!= ' '; end
++);
174 if (matching_prefix (str
, end
- str
, "Regular")
175 || matching_prefix (str
, end
- str
, "Bold")
176 || matching_prefix (str
, end
- str
, "Oblique")
177 || matching_prefix (str
, end
- str
, "Italic"))
179 adstyle
= font_intern_prop (str
, end
- str
, 1);
180 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
186 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
188 Lisp_Object key
, cache
, entity
;
196 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
198 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
202 key
= Fcons (build_unibyte_string (file
), make_number (idx
));
203 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
204 entity
= XCAR (cache
);
207 Lisp_Object val
= font_make_entity ();
210 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
211 ASET (val
, i
, AREF (entity
, i
));
213 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
214 font_put_extra (val
, QCfont_entity
, key
);
218 entity
= font_make_entity ();
219 XSETCAR (cache
, entity
);
221 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
222 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
224 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
226 char *s
= (char *) str
;
227 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
229 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
231 char *s
= (char *) str
;
232 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
234 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
236 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
237 numeric
= FC_WEIGHT_MEDIUM
;
238 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
240 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
243 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
245 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
247 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
249 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
251 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
254 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
255 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
256 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
257 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
260 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
262 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
265 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
266 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
270 /* As this font is not scalable, perhaps this is a BDF or PCF
274 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
275 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
276 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
280 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
281 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
282 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
283 FT_Done_Face (ft_face
);
287 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
288 font_put_extra (entity
, QCfont_entity
, key
);
293 static Lisp_Object ftfont_generic_family_list
;
296 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
303 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
304 if (EQ (family
, Qmono
))
306 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
307 family
= Qsans_serif
;
308 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
311 if (! EQ (XCDR (slot
), Qt
))
313 pattern
= FcPatternDuplicate (pattern
);
316 FcPatternDel (pattern
, FC_FOUNDRY
);
317 FcPatternDel (pattern
, FC_FAMILY
);
318 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
319 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
321 /* This is to avoid the effect of locale. */
322 static const FcChar8 lang
[] = "en";
323 langset
= FcLangSetCreate ();
324 FcLangSetAdd (langset
, lang
);
325 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
326 FcLangSetDestroy (langset
);
328 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
329 FcDefaultSubstitute (pattern
);
330 match
= FcFontMatch (NULL
, pattern
, &result
);
335 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
336 family
= intern ((char *) fam
);
340 XSETCDR (slot
, family
);
341 if (match
) FcPatternDestroy (match
);
343 if (pattern
) FcPatternDestroy (pattern
);
347 struct ftfont_cache_data
350 FcCharSet
*fc_charset
;
354 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
356 Lisp_Object cache
, val
, entity
;
357 struct ftfont_cache_data
*cache_data
;
359 if (FONT_ENTITY_P (key
))
362 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
363 eassert (CONSP (val
));
369 if (NILP (ft_face_cache
))
372 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
375 if (NILP (ft_face_cache
))
376 ft_face_cache
= CALLN (Fmake_hash_table
, QCtest
, Qequal
);
377 cache_data
= xmalloc (sizeof *cache_data
);
378 cache_data
->ft_face
= NULL
;
379 cache_data
->fc_charset
= NULL
;
380 val
= make_save_ptr_int (cache_data
, 0);
381 cache
= Fcons (Qnil
, val
);
382 Fputhash (key
, cache
, ft_face_cache
);
387 cache_data
= XSAVE_POINTER (val
, 0);
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 idx
= 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
, idx
, &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
, idx
, 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_POINTER (val
, 0);
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 (struct frame
*);
481 static Lisp_Object
ftfont_list (struct frame
*, Lisp_Object
);
482 static Lisp_Object
ftfont_match (struct frame
*, Lisp_Object
);
483 static Lisp_Object
ftfont_list_family (struct frame
*);
484 static Lisp_Object
ftfont_open (struct frame
*, Lisp_Object
, int);
485 static void ftfont_close (struct font
*);
486 static int ftfont_has_char (Lisp_Object
, int);
487 static unsigned ftfont_encode_char (struct font
*, int);
488 static void 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,
495 static Lisp_Object
ftfont_otf_capability (struct font
*);
496 # ifdef HAVE_M17N_FLT
497 static Lisp_Object
ftfont_shape (Lisp_Object
);
501 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
502 static int ftfont_variation_glyphs (struct font
*, int c
,
503 unsigned variations
[256]);
504 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
506 struct font_driver ftfont_driver
=
508 LISP_INITIALLY_ZERO
, /* Qfreetype */
509 0, /* case insensitive */
514 NULL
, /* free_entity */
517 /* We can't draw a text without device dependent functions. */
518 NULL
, /* prepare_face */
519 NULL
, /* done_face */
523 /* We can't draw a text without device dependent functions. */
526 NULL
, /* free_bitmap */
529 ftfont_otf_capability
,
530 #else /* not HAVE_LIBOTF */
532 #endif /* not HAVE_LIBOTF */
533 NULL
, /* otf_drive */
534 NULL
, /* start_for_frame */
535 NULL
, /* end_for_frame */
536 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
538 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
540 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
543 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
544 ftfont_variation_glyphs
,
549 ftfont_filter_properties
, /* filter_properties */
553 ftfont_get_cache (struct frame
*f
)
555 return freetype_font_cache
;
559 ftfont_get_charset (Lisp_Object registry
)
561 char *str
= SSDATA (SYMBOL_NAME (registry
));
563 char *re
= SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
567 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
571 else if (str
[i
] == '*')
578 regexp
= make_unibyte_string (re
, j
);
580 for (i
= 0; fc_charset_table
[i
].name
; i
++)
581 if (fast_c_string_match_ignore_case
582 (regexp
, fc_charset_table
[i
].name
,
583 strlen (fc_charset_table
[i
].name
)) >= 0)
585 if (! fc_charset_table
[i
].name
)
587 if (! fc_charset_table
[i
].fc_charset
)
589 FcCharSet
*charset
= FcCharSetCreate ();
590 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
594 for (j
= 0; uniquifier
[j
]; j
++)
595 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
597 FcCharSetDestroy (charset
);
600 fc_charset_table
[i
].fc_charset
= charset
;
608 unsigned int script_tag
, langsys_tag
;
610 unsigned int *features
[2];
613 #define OTF_SYM_TAG(SYM, TAG) \
615 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
616 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
619 #define OTF_TAG_STR(TAG, P) \
621 (P)[0] = (char) (TAG >> 24); \
622 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
623 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
624 (P)[3] = (char) (TAG & 0xFF); \
629 #define OTF_TAG_SYM(SYM, TAG) \
633 OTF_TAG_STR (TAG, str); \
634 (SYM) = font_intern_prop (str, 4, 1); \
639 static struct OpenTypeSpec
*
640 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
642 struct OpenTypeSpec
*spec
= malloc (sizeof *spec
);
649 spec
->script
= XCAR (otf_spec
);
650 if (! NILP (spec
->script
))
652 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
653 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
654 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
655 spec
->script
= XCDR (val
);
660 spec
->script_tag
= 0x44464C54; /* "DFLT" */
661 otf_spec
= XCDR (otf_spec
);
662 spec
->langsys_tag
= 0;
663 if (! NILP (otf_spec
))
665 val
= XCAR (otf_spec
);
667 OTF_SYM_TAG (val
, spec
->langsys_tag
);
668 otf_spec
= XCDR (otf_spec
);
670 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
671 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
675 val
= XCAR (otf_spec
);
680 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
682 : malloc (XINT (len
) * sizeof *spec
->features
[i
]));
683 if (! spec
->features
[i
])
685 if (i
> 0 && spec
->features
[0])
686 free (spec
->features
[0]);
690 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
692 if (NILP (XCAR (val
)))
698 OTF_SYM_TAG (XCAR (val
), tag
);
699 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
702 spec
->nfeatures
[i
] = j
;
708 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
710 Lisp_Object tmp
, extra
;
711 FcPattern
*pattern
= NULL
;
712 FcCharSet
*charset
= NULL
;
713 FcLangSet
*langset
= NULL
;
717 Lisp_Object script
= Qnil
;
718 Lisp_Object registry
;
721 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
723 /* Fontconfig doesn't support reverse-italic/oblique. */
726 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
727 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
728 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
729 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
732 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
734 || EQ (registry
, Qascii_0
)
735 || EQ (registry
, Qiso10646_1
)
736 || EQ (registry
, Qunicode_bmp
))
742 fc_charset_idx
= ftfont_get_charset (registry
);
743 if (fc_charset_idx
< 0)
745 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
746 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
747 lang
= (FcChar8
*) *langname
;
750 langset
= FcLangSetCreate ();
753 FcLangSetAdd (langset
, lang
);
758 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
759 CONSP (extra
); extra
= XCDR (extra
))
761 Lisp_Object key
, val
;
763 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
769 else if (EQ (key
, QClang
))
772 langset
= FcLangSetCreate ();
777 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
781 for (; CONSP (val
); val
= XCDR (val
))
782 if (SYMBOLP (XCAR (val
))
783 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
786 else if (EQ (key
, QCotf
))
790 *otspec
= ftfont_get_open_type_spec (val
);
793 strcpy (otlayout
, "otlayout:");
794 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
795 script
= (*otspec
)->script
;
798 else if (EQ (key
, QCscript
))
800 else if (EQ (key
, QCscalable
))
801 scalable
= ! NILP (val
);
804 if (! NILP (script
) && ! charset
)
806 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
808 if (CONSP (chars
) && CONSP (CDR (chars
)))
810 charset
= FcCharSetCreate ();
813 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
814 if (CHARACTERP (XCAR (chars
))
815 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
820 pattern
= FcPatternCreate ();
823 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
825 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
827 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
829 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
832 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
835 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
838 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
841 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
847 /* We come here because of unexpected error in fontconfig API call
848 (usually insufficient memory). */
851 FcPatternDestroy (pattern
);
856 if ((*otspec
)->nfeatures
[0] > 0)
857 free ((*otspec
)->features
[0]);
858 if ((*otspec
)->nfeatures
[1] > 0)
859 free ((*otspec
)->features
[1]);
865 if (langset
) FcLangSetDestroy (langset
);
866 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
871 ftfont_list (struct frame
*f
, Lisp_Object spec
)
873 Lisp_Object val
= Qnil
, family
, adstyle
;
876 FcFontSet
*fontset
= NULL
;
877 FcObjectSet
*objset
= NULL
;
879 Lisp_Object chars
= Qnil
;
880 char otlayout
[15]; /* For "otlayout:XXXX" */
881 struct OpenTypeSpec
*otspec
= NULL
;
883 const char *langname
= NULL
;
885 if (! fc_initialized
)
891 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
894 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
896 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
899 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
900 if (CONSP (val
) && VECTORP (XCDR (val
)))
905 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
906 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
907 family
= AREF (spec
, FONT_FAMILY_INDEX
);
910 Lisp_Object resolved
;
912 resolved
= ftfont_resolve_generic_family (family
, pattern
);
913 if (! NILP (resolved
))
915 FcPatternDel (pattern
, FC_FAMILY
);
916 if (! FcPatternAddString (pattern
, FC_FAMILY
,
917 SYMBOL_FcChar8 (resolved
)))
921 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
922 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
924 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
925 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
926 FC_STYLE
, FC_FILE
, FC_INDEX
,
929 #endif /* FC_CAPABILITY */
937 FcObjectSetAdd (objset
, FC_CHARSET
);
939 fontset
= FcFontList (NULL
, pattern
, objset
);
940 if (! fontset
|| fontset
->nfont
== 0)
943 /* Need fix because this finds any fonts. */
944 if (fontset
->nfont
== 0 && ! NILP (family
))
946 /* Try matching with configuration. For instance, the
947 configuration may specify "Nimbus Mono L" as an alias of
949 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
950 SYMBOL_FcChar8 (family
), NULL
);
953 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
956 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
959 FcPatternDel (pattern
, FC_FAMILY
);
960 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
961 FcFontSetDestroy (fontset
);
962 fontset
= FcFontList (NULL
, pattern
, objset
);
963 if (fontset
&& fontset
->nfont
> 0)
969 for (i
= 0; i
< fontset
->nfont
; i
++)
977 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
988 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
990 || ! strstr ((char *) this, otlayout
))
993 #endif /* FC_CAPABILITY */
1001 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1004 otf
= OTF_open ((char *) file
);
1007 passed
= (OTF_check_features (otf
, 1, otspec
->script_tag
,
1008 otspec
->langsys_tag
,
1009 otspec
->features
[0],
1010 otspec
->nfeatures
[0]) == 1
1011 && OTF_check_features (otf
, 0, otspec
->script_tag
,
1012 otspec
->langsys_tag
,
1013 otspec
->features
[1],
1014 otspec
->nfeatures
[1]) == 1);
1019 #endif /* HAVE_LIBOTF */
1020 if (VECTORP (chars
))
1024 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1027 for (j
= 0; j
< ASIZE (chars
); j
++)
1028 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1029 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1031 if (j
== ASIZE (chars
))
1034 if (! NILP (adstyle
) || langname
)
1036 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1038 if (! NILP (adstyle
)
1039 && (NILP (this_adstyle
)
1040 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1041 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1044 && ! NILP (this_adstyle
)
1045 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1048 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1049 AREF (spec
, FONT_EXTRA_INDEX
));
1050 if (! NILP (entity
))
1051 val
= Fcons (entity
, val
);
1053 val
= Fnreverse (val
);
1057 /* We come here because of unexpected error in fontconfig API call
1058 (usually insufficient memory). */
1062 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1063 if (objset
) FcObjectSetDestroy (objset
);
1064 if (fontset
) FcFontSetDestroy (fontset
);
1065 if (pattern
) FcPatternDestroy (pattern
);
1070 ftfont_match (struct frame
*f
, Lisp_Object spec
)
1072 Lisp_Object entity
= Qnil
;
1073 FcPattern
*pattern
, *match
= NULL
;
1075 char otlayout
[15]; /* For "otlayout:XXXX" */
1076 struct OpenTypeSpec
*otspec
= NULL
;
1077 const char *langname
= NULL
;
1079 if (! fc_initialized
)
1085 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1089 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1093 value
.type
= FcTypeDouble
;
1094 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1095 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1097 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1099 FcDefaultSubstitute (pattern
);
1100 match
= FcFontMatch (NULL
, pattern
, &result
);
1103 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1104 FcPatternDestroy (match
);
1105 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1106 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1107 ftfont_generic_family_list
))
1108 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1109 AREF (entity
, FONT_FAMILY_INDEX
))))
1113 FcPatternDestroy (pattern
);
1115 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1120 ftfont_list_family (struct frame
*f
)
1122 Lisp_Object list
= Qnil
;
1123 FcPattern
*pattern
= NULL
;
1124 FcFontSet
*fontset
= NULL
;
1125 FcObjectSet
*objset
= NULL
;
1128 if (! fc_initialized
)
1134 pattern
= FcPatternCreate ();
1137 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1140 fontset
= FcFontList (NULL
, pattern
, objset
);
1144 for (i
= 0; i
< fontset
->nfont
; i
++)
1146 FcPattern
*pat
= fontset
->fonts
[i
];
1149 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1150 list
= Fcons (intern ((char *) str
), list
);
1154 if (objset
) FcObjectSetDestroy (objset
);
1155 if (fontset
) FcFontSetDestroy (fontset
);
1156 if (pattern
) FcPatternDestroy (pattern
);
1163 ftfont_open2 (struct frame
*f
,
1166 Lisp_Object font_object
)
1168 struct ftfont_info
*ftfont_info
;
1170 struct ftfont_cache_data
*cache_data
;
1174 Lisp_Object val
, filename
, idx
, cache
;
1180 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1184 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1187 filename
= XCAR (val
);
1190 cache_data
= XSAVE_POINTER (XCDR (cache
), 0);
1191 ft_face
= cache_data
->ft_face
;
1192 if (XSAVE_INTEGER (val
, 1) > 0)
1194 /* FT_Face in this cache is already used by the different size. */
1195 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1197 if (FT_Activate_Size (ft_size
) != 0)
1199 FT_Done_Size (ft_size
);
1203 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) + 1);
1204 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1207 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1209 if (XSAVE_INTEGER (val
, 1) == 0)
1210 FT_Done_Face (ft_face
);
1214 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1215 font
= XFONT_OBJECT (font_object
);
1216 ftfont_info
= (struct ftfont_info
*) font
;
1217 ftfont_info
->ft_size
= ft_face
->size
;
1218 ftfont_info
->index
= XINT (idx
);
1220 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1221 ftfont_info
->otf
= NULL
;
1222 #endif /* HAVE_LIBOTF */
1223 /* This means that there's no need of transformation. */
1224 ftfont_info
->matrix
.xx
= 0;
1225 font
->pixel_size
= size
;
1226 font
->driver
= &ftfont_driver
;
1227 font
->encoding_charset
= font
->repertory_charset
= -1;
1229 upEM
= ft_face
->units_per_EM
;
1230 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1231 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1234 font
->ascent
= ft_face
->ascender
* size
/ upEM
+ 0.5;
1235 font
->descent
= - ft_face
->descender
* size
/ upEM
+ 0.5;
1236 font
->height
= ft_face
->height
* size
/ upEM
+ 0.5;
1240 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1241 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1242 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1244 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1245 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1247 spacing
= FC_PROPORTIONAL
;
1248 if (spacing
!= FC_PROPORTIONAL
1250 && spacing
!= FC_DUAL
1251 #endif /* FC_DUAL */
1253 font
->min_width
= font
->average_width
= font
->space_width
1254 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
+ 0.5
1255 : ft_face
->size
->metrics
.max_advance
>> 6);
1260 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1261 for (i
= 32, n
= 0; i
< 127; i
++)
1262 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1264 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1267 && (! font
->min_width
|| font
->min_width
> this_width
))
1268 font
->min_width
= this_width
;
1270 font
->space_width
= this_width
;
1271 font
->average_width
+= this_width
;
1275 font
->average_width
/= n
;
1278 font
->baseline_offset
= 0;
1279 font
->relative_compose
= 0;
1280 font
->default_ascent
= 0;
1281 font
->vertical_centering
= 0;
1284 font
->underline_position
= (-ft_face
->underline_position
* size
/ upEM
1286 font
->underline_thickness
= (ft_face
->underline_thickness
* size
/ upEM
1291 font
->underline_position
= -1;
1292 font
->underline_thickness
= 0;
1299 ftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
1301 Lisp_Object font_object
;
1303 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1306 font_object
= font_build_object (VECSIZE (struct ftfont_info
),
1307 Qfreetype
, entity
, size
);
1308 return ftfont_open2 (f
, entity
, pixel_size
, font_object
);
1312 ftfont_close (struct font
*font
)
1314 /* FIXME: Although this function can be called while garbage-collecting,
1315 the function assumes that Lisp data structures are properly-formed.
1316 This invalid assumption can lead to core dumps (Bug#20890). */
1318 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1319 Lisp_Object val
, cache
;
1321 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1322 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1323 eassert (CONSP (cache
));
1325 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) - 1);
1326 if (XSAVE_INTEGER (val
, 1) == 0)
1328 struct ftfont_cache_data
*cache_data
= XSAVE_POINTER (val
, 0);
1330 FT_Done_Face (cache_data
->ft_face
);
1332 if (ftfont_info
->otf
)
1333 OTF_close (ftfont_info
->otf
);
1335 cache_data
->ft_face
= NULL
;
1338 FT_Done_Size (ftfont_info
->ft_size
);
1342 ftfont_has_char (Lisp_Object font
, int c
)
1344 struct charset
*cs
= NULL
;
1346 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1347 && charset_jisx0208
>= 0)
1348 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1349 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1350 && charset_ksc5601
>= 0)
1351 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1353 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1355 if (FONT_ENTITY_P (font
))
1357 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1359 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1363 struct ftfont_info
*ftfont_info
;
1365 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1366 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1372 ftfont_encode_char (struct font
*font
, int c
)
1374 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1375 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1376 FT_ULong charcode
= c
;
1377 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1379 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1383 ftfont_text_extents (struct font
*font
, unsigned int *code
,
1384 int nglyphs
, struct font_metrics
*metrics
)
1386 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1387 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1391 if (ftfont_info
->ft_size
!= ft_face
->size
)
1392 FT_Activate_Size (ftfont_info
->ft_size
);
1394 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1396 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1398 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1402 metrics
->lbearing
= m
->horiBearingX
>> 6;
1403 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1404 metrics
->ascent
= m
->horiBearingY
>> 6;
1405 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1408 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1409 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1410 if (metrics
->rbearing
1411 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1413 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1414 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1415 metrics
->ascent
= m
->horiBearingY
>> 6;
1416 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1417 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1418 width
+= m
->horiAdvance
>> 6;
1421 width
+= font
->space_width
;
1423 metrics
->width
= width
;
1427 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1429 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1430 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1431 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1433 if (ftfont_info
->ft_size
!= ft_face
->size
)
1434 FT_Activate_Size (ftfont_info
->ft_size
);
1435 if (bits_per_pixel
== 1)
1437 #ifdef FT_LOAD_TARGET_MONO
1438 load_flags
|= FT_LOAD_TARGET_MONO
;
1440 load_flags
|= FT_LOAD_MONOCHROME
;
1443 else if (bits_per_pixel
!= 8)
1444 /* We don't support such a rendering. */
1447 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1449 bitmap
->bits_per_pixel
1450 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1451 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1452 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1453 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1455 if (bitmap
->bits_per_pixel
< 0)
1456 /* We don't support that kind of pixel mode. */
1458 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1459 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1460 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1461 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1462 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1463 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1464 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1470 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1473 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1474 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1476 if (ftfont_info
->ft_size
!= ft_face
->size
)
1477 FT_Activate_Size (ftfont_info
->ft_size
);
1478 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1480 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1482 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1484 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1485 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1492 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1494 Lisp_Object scripts
, langsyses
, features
, sym
;
1497 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1499 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1501 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1503 OTF_LangSys
*otf_langsys
;
1506 otf_langsys
= otf_script
->LangSys
+ j
;
1507 else if (otf_script
->DefaultLangSysOffset
)
1508 otf_langsys
= &otf_script
->DefaultLangSys
;
1512 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1514 l
= otf_langsys
->FeatureIndex
[k
];
1515 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1517 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1518 features
= Fcons (sym
, features
);
1521 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1524 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1527 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1528 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1536 ftfont_otf_capability (struct font
*font
)
1538 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1539 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1540 Lisp_Object gsub_gpos
;
1544 gsub_gpos
= Fcons (Qnil
, Qnil
);
1545 if (OTF_get_table (otf
, "GSUB") == 0
1546 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1547 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1548 if (OTF_get_table (otf
, "GPOS") == 0
1549 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1550 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1554 #ifdef HAVE_M17N_FLT
1556 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1557 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1558 /* We can use the new feature of libotf and m17n-flt to handle the
1559 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1560 some Agian scripts. */
1561 #define M17N_FLT_USE_NEW_FEATURE
1573 /* The actual type of elements in the array MFLTGlyphString.glyphs.
1574 We use this structure instead of MFLTGlyph to utilize the new
1575 feature of libotf ver.0.9.15 which requires saving and restoring
1576 the value of OTF_GlyphString.positioning_type in the succeeding
1577 calls of the callback function MFLTFont.drive_otf (which is set to
1578 ftfont_drive_otf). */
1582 unsigned int libotf_positioning_type
;
1586 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1589 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1590 FT_Face ft_face
= flt_font_ft
->ft_face
;
1593 for (g
= (MFLTGlyphFT
*) (gstring
->glyphs
) + from
; from
< to
; g
++, from
++)
1596 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->g
.code
);
1598 g
->g
.code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1604 /* Operators for 26.6 fixed fractional pixel format */
1606 #define FLOOR(x) ((x) & -64)
1607 #define CEIL(x) (((x)+63) & -64)
1608 #define ROUND(x) (((x)+32) & -64)
1611 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1614 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1615 FT_Face ft_face
= flt_font_ft
->ft_face
;
1618 for (g
= (MFLTGlyphFT
*) (gstring
->glyphs
) + from
; from
< to
; g
++, from
++)
1619 if (! g
->g
.measured
)
1621 if (g
->g
.code
!= FONT_INVALID_CODE
)
1623 FT_Glyph_Metrics
*m
;
1625 if (FT_Load_Glyph (ft_face
, g
->g
.code
, FT_LOAD_DEFAULT
) != 0)
1627 m
= &ft_face
->glyph
->metrics
;
1628 if (flt_font_ft
->matrix
)
1633 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1634 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1635 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1636 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1637 for (i
= 0; i
< 4; i
++)
1638 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1639 g
->g
.lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1640 g
->g
.rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1641 g
->g
.ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1642 g
->g
.descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1646 g
->g
.lbearing
= FLOOR (m
->horiBearingX
);
1647 g
->g
.rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1648 g
->g
.ascent
= CEIL (m
->horiBearingY
);
1649 g
->g
.descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1651 g
->g
.xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1656 g
->g
.rbearing
= g
->g
.xadv
= flt_font_ft
->font
->space_width
<< 6;
1657 g
->g
.ascent
= flt_font_ft
->font
->ascent
<< 6;
1658 g
->g
.descent
= flt_font_ft
->font
->descent
<< 6;
1667 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1669 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1671 #define FEATURE_ANY(IDX) \
1672 (spec->features[IDX] \
1673 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1675 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1676 OTF
*otf
= flt_font_ft
->otf
;
1681 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1682 /* Return true iff any of GSUB or GPOS support the script (and
1685 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1687 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1690 for (i
= 0; i
< 2; i
++)
1691 if (! FEATURE_ANY (i
))
1693 if (FEATURE_NONE (i
))
1696 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1701 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1704 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1710 for (n
= 1; spec
->features
[i
][n
]; n
++);
1712 SAFE_NALLOCA (tags
, 1, n
);
1713 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1715 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1718 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1720 tags
[n
] = spec
->features
[i
][n
];
1723 #ifndef M17N_FLT_USE_NEW_FEATURE
1724 passed
= n
- negative
> 0;
1727 passed
= (OTF_check_features (otf
, i
== 0, spec
->script
,
1728 spec
->langsys
, tags
, n
- negative
)
1739 #define DEVICE_DELTA(table, size) \
1740 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1741 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1745 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1746 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1748 if (anchor
->AnchorFormat
== 2)
1750 FT_Outline
*outline
;
1751 int ap
= anchor
->f
.f1
.AnchorPoint
;
1753 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1754 outline
= &ft_face
->glyph
->outline
;
1755 if (ap
< outline
->n_points
)
1757 *x
= outline
->points
[ap
].x
<< 6;
1758 *y
= outline
->points
[ap
].y
<< 6;
1761 else if (anchor
->AnchorFormat
== 3)
1763 if (anchor
->f
.f2
.XDeviceTable
.offset
1764 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1765 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1766 if (anchor
->f
.f2
.YDeviceTable
.offset
1767 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1768 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1772 static OTF_GlyphString otf_gstring
;
1775 setup_otf_gstring (int size
)
1777 if (otf_gstring
.size
< size
)
1779 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1780 size
, sizeof (OTF_Glyph
));
1781 otf_gstring
.size
= size
;
1783 otf_gstring
.used
= size
;
1784 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1787 #ifdef M17N_FLT_USE_NEW_FEATURE
1789 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1790 #define PACK_OTF_TAG(TAG) \
1791 ((((TAG) & 0x7F000000) >> 3) \
1792 | (((TAG) & 0x7F0000) >> 2) \
1793 | (((TAG) & 0x7F00) >> 1) \
1796 /* Assuming that FONT is an OpenType font, apply OpenType features
1797 specified in SPEC on glyphs between FROM and TO of IN, and record
1798 the lastly applied feature in each glyph of IN. If OUT is not
1799 NULL, append the resulting glyphs to OUT while storing glyph
1800 position adjustment information in ADJUSTMENT. */
1803 ftfont_drive_otf (MFLTFont
*font
,
1805 MFLTGlyphString
*in
,
1808 MFLTGlyphString
*out
,
1809 MFLTGlyphAdjustment
*adjustment
)
1811 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1812 MFLTGlyphFT
*in_glyphs
= (MFLTGlyphFT
*) (in
->glyphs
) + from
;
1813 MFLTGlyphFT
*out_glyphs
= out
? (MFLTGlyphFT
*) (out
->glyphs
) : NULL
;
1814 FT_Face ft_face
= flt_font_ft
->ft_face
;
1815 OTF
*otf
= flt_font_ft
->otf
;
1816 int len
= to
- from
;
1819 char script
[5], *langsys
= NULL
;
1820 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1821 OTF_Feature
*features
;
1825 OTF_tag_name (spec
->script
, script
);
1830 langsys
= langsysbuf
;
1831 OTF_tag_name (spec
->langsys
, langsys
);
1835 for (i
= 0; i
< 2; i
++)
1839 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1841 for (j
= 0; spec
->features
[i
][j
]; j
++);
1842 SAFE_NALLOCA (p
, 6, j
);
1847 for (j
= 0; spec
->features
[i
][j
]; j
++)
1849 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1850 *p
++ = '*', *p
++ = ',';
1853 OTF_tag_name (spec
->features
[i
][j
], p
);
1862 setup_otf_gstring (len
);
1863 for (i
= 0; i
< len
; i
++)
1865 otf_gstring
.glyphs
[i
].c
= in_glyphs
[i
].g
.c
& 0x11FFFF;
1866 otf_gstring
.glyphs
[i
].glyph_id
= in_glyphs
[i
].g
.code
;
1867 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1868 otf_gstring
.glyphs
[i
].positioning_type
= in_glyphs
[i
].libotf_positioning_type
;
1872 OTF_drive_gdef (otf
, &otf_gstring
);
1873 gidx
= out
? out
->used
: from
;
1875 if (gsub_features
&& out
)
1877 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1878 if (OTF_drive_gsub_features (otf
, &otf_gstring
, script
, langsys
,
1882 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1886 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1891 features
= otf
->gsub
->FeatureList
.Feature
;
1892 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1895 int min_from
, max_to
;
1898 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1899 feature_idx
= OTF_POSITIONING_TYPE_GET_FEATURE (otfg
);
1901 feature_idx
= otfg
->positioning_type
>> 4;
1903 g
= out_glyphs
+ out
->used
;
1904 *g
= in_glyphs
[otfg
->f
.index
.from
];
1905 if (g
->g
.code
!= otfg
->glyph_id
)
1908 g
->g
.code
= otfg
->glyph_id
;
1912 min_from
= g
->g
.from
;
1914 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1916 /* OTFG substitutes multiple glyphs in IN. */
1917 for (j
= otfg
->f
.index
.from
+ 1; j
<= otfg
->f
.index
.to
; j
++)
1919 if (min_from
> in_glyphs
[j
].g
.from
)
1920 min_from
= in_glyphs
[j
].g
.from
;
1921 if (max_to
< in_glyphs
[j
].g
.to
)
1922 max_to
= in_glyphs
[j
].g
.to
;
1924 g
->g
.from
= min_from
;
1929 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1930 tag
= PACK_OTF_TAG (tag
);
1931 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
1933 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1934 g
->libotf_positioning_type
1935 = otfg
->positioning_type
& OTF_positioning_type_components_mask
;
1937 for (i
++, otfg
++; (i
< otf_gstring
.used
1938 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1941 g
= out_glyphs
+ out
->used
;
1942 *g
= in_glyphs
[otfg
->f
.index
.to
];
1943 if (g
->g
.code
!= otfg
->glyph_id
)
1946 g
->g
.code
= otfg
->glyph_id
;
1949 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1950 feature_idx
= OTF_POSITIONING_TYPE_GET_FEATURE (otfg
);
1952 feature_idx
= otfg
->positioning_type
>> 4;
1956 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1957 tag
= PACK_OTF_TAG (tag
);
1958 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
1960 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1961 g
->libotf_positioning_type
1962 = otfg
->positioning_type
& OTF_positioning_type_components_mask
;
1968 else if (gsub_features
)
1970 /* Just for checking which features will be applied. */
1971 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1972 if (OTF_drive_gsub_features (otf
, &otf_gstring
, script
, langsys
,
1976 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1980 features
= otf
->gsub
->FeatureList
.Feature
;
1981 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1985 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
1986 feature_idx
= OTF_POSITIONING_TYPE_GET_FEATURE (otfg
);
1988 feature_idx
= otfg
->positioning_type
>> 4;
1992 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1993 tag
= PACK_OTF_TAG (tag
);
1994 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1996 MFLTGlyphFT
*g
= in_glyphs
+ j
;
1997 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
2004 if (out
->allocated
< out
->used
+ len
)
2009 for (i
= 0; i
< len
; i
++)
2010 out_glyphs
[out
->used
++] = in_glyphs
[i
];
2013 if (gpos_features
&& out
)
2015 MFLTGlyphFT
*base
= NULL
, *mark
= NULL
, *g
;
2016 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2018 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2019 if (OTF_drive_gpos_features (otf
, &otf_gstring
, script
, langsys
,
2026 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2033 features
= otf
->gpos
->FeatureList
.Feature
;
2034 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2035 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2036 x_scale
= ft_face
->size
->metrics
.x_scale
;
2037 y_scale
= ft_face
->size
->metrics
.y_scale
;
2039 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out_glyphs
+ gidx
;
2040 i
< otf_gstring
.used
; i
++, otfg
++)
2042 MFLTGlyphAdjustment
*adjust
= adjustment
;
2044 int positioning_type
, feature_idx
;
2046 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2047 positioning_type
= OTF_POSITIONING_TYPE_GET_FORMAT (otfg
);
2048 feature_idx
= OTF_POSITIONING_TYPE_GET_FEATURE (otfg
);
2050 positioning_type
= otfg
->positioning_type
& 0xF;
2051 feature_idx
= otfg
->positioning_type
>> 4;
2055 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2056 tag
= PACK_OTF_TAG (tag
);
2057 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
2060 if (! otfg
->glyph_id
)
2061 /* This is a pseudo glyph that contains positioning
2062 information to be accumulated to a real glyph. */
2064 switch (positioning_type
)
2068 case 1: /* Single */
2071 int format
= otfg
->f
.f1
.format
;
2073 if (format
& OTF_XPlacement
)
2075 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2076 if (format
& OTF_XPlaDevice
)
2078 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2079 if (format
& OTF_YPlacement
)
2081 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2082 if (format
& OTF_YPlaDevice
)
2084 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2085 if (format
& OTF_XAdvance
)
2087 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2088 if (format
& OTF_XAdvDevice
)
2090 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2091 if (format
& OTF_YAdvance
)
2093 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2094 if (format
& OTF_YAdvDevice
)
2096 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2100 case 3: /* Cursive */
2101 /* Not yet supported. */
2103 case 4: /* Mark-to-Base */
2104 case 5: /* Mark-to-Ligature */
2108 goto label_adjust_anchor
;
2109 default: /* i.e. case 6 Mark-to-Mark */
2113 #ifdef OTF_POSITIONING_TYPE_GET_FORMAT
2115 int distance
= OTF_POSITIONING_TYPE_GET_MARKDISTANCE (otfg
);
2119 prev
= g
- distance
;
2120 if (prev
< out_glyphs
)
2126 label_adjust_anchor
:
2128 int base_x
, base_y
, mark_x
, mark_y
;
2129 int this_from
, this_to
;
2131 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2132 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2133 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2134 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2136 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2137 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
, prev
->g
.code
,
2138 x_ppem
, y_ppem
, &base_x
, &base_y
);
2139 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2140 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->g
.code
,
2141 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2142 adjust
->xoff
= (base_x
- mark_x
);
2143 adjust
->yoff
= - (base_y
- mark_y
);
2144 adjust
->back
= (g
- prev
);
2146 adjust
->advance_is_absolute
= 1;
2148 this_from
= g
->g
.from
;
2150 for (j
= 0; prev
+ j
< g
; j
++)
2152 if (this_from
> prev
[j
].g
.from
)
2153 this_from
= prev
[j
].g
.from
;
2154 if (this_to
< prev
[j
].g
.to
)
2155 this_to
= prev
[j
].g
.to
;
2157 for (; prev
<= g
; prev
++)
2159 prev
->g
.from
= this_from
;
2160 prev
->g
.to
= this_to
;
2166 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2168 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2176 else if (gpos_features
)
2178 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2184 features
= otf
->gpos
->FeatureList
.Feature
;
2185 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2187 if (otfg
->positioning_type
& 0xF)
2189 int feature_idx
= otfg
->positioning_type
>> 4;
2193 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2194 tag
= PACK_OTF_TAG (tag
);
2195 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2197 MFLTGlyphFT
*g
= in_glyphs
+ j
;
2198 g
->g
.internal
= (g
->g
.internal
& ~0x1FFFFFFF) | tag
;
2210 if (out
->allocated
< out
->used
+ len
)
2212 font
->get_metrics (font
, in
, from
, to
);
2213 memcpy (out
->glyphs
+ out
->used
, in_glyphs
, sizeof (MFLTGlyphFT
) * len
);
2219 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2220 MFLTGlyphString
*in
, int from
, int to
)
2222 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2225 #else /* not M17N_FLT_USE_NEW_FEATURE */
2228 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2230 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2232 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2233 MFLTGlyphFT
*in_glyphs
= (MFLTGlyphFT
*) (in
->glyphs
) + from
;
2234 MFLTGlyphFT
*out_glyphs
= out
? (MFLTGlyphFT
*) (out
->glyphs
) : NULL
;
2235 FT_Face ft_face
= flt_font_ft
->ft_face
;
2236 OTF
*otf
= flt_font_ft
->otf
;
2237 int len
= to
- from
;
2240 char script
[5], *langsys
= NULL
;
2241 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2245 OTF_tag_name (spec
->script
, script
);
2250 langsys
= langsysbuf
;
2251 OTF_tag_name (spec
->langsys
, langsys
);
2255 for (i
= 0; i
< 2; i
++)
2259 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2261 for (j
= 0; spec
->features
[i
][j
]; j
++);
2262 SAFE_NALLOCA (p
, 6, j
);
2267 for (j
= 0; spec
->features
[i
][j
]; j
++)
2269 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2270 *p
++ = '*', *p
++ = ',';
2273 OTF_tag_name (spec
->features
[i
][j
], p
);
2282 setup_otf_gstring (len
);
2283 for (i
= 0; i
< len
; i
++)
2285 otf_gstring
.glyphs
[i
].c
= in_glyphs
[i
].g
.c
;
2286 otf_gstring
.glyphs
[i
].glyph_id
= in_glyphs
[i
].g
.code
;
2289 OTF_drive_gdef (otf
, &otf_gstring
);
2294 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2297 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2302 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2305 int min_from
, max_to
;
2308 g
= out_glyphs
+ out
->used
;
2309 *g
= in_glyphs
[otfg
->f
.index
.from
];
2310 if (g
->g
.code
!= otfg
->glyph_id
)
2313 g
->g
.code
= otfg
->glyph_id
;
2317 min_from
= g
->g
.from
;
2319 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2321 /* OTFG substitutes multiple glyphs in IN. */
2322 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2323 j
<= from
+ otfg
->f
.index
.to
; j
++)
2325 if (min_from
> in
->glyphs
[j
].from
)
2326 min_from
= in
->glyphs
[j
].from
;
2327 if (max_to
< in
->glyphs
[j
].to
)
2328 max_to
= in
->glyphs
[j
].to
;
2330 g
->g
.from
= min_from
;
2333 for (i
++, otfg
++; (i
< otf_gstring
.used
2334 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2337 g
= out_glyphs
+ out
->used
;
2338 *g
= in_glyphs
[otfg
->f
.index
.to
];
2339 if (g
->g
.code
!= otfg
->glyph_id
)
2342 g
->g
.code
= otfg
->glyph_id
;
2351 if (out
->allocated
< out
->used
+ len
)
2356 for (i
= 0; i
< len
; i
++)
2357 out_glyphs
[out
->used
++] = in_glyphs
[i
];
2362 MFLTGlyphFT
*base
= NULL
, *mark
= NULL
, *g
;
2363 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2365 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2372 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2373 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2374 x_scale
= ft_face
->size
->metrics
.x_scale
;
2375 y_scale
= ft_face
->size
->metrics
.y_scale
;
2377 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out_glyphs
+ gidx
;
2378 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2382 if (! otfg
->glyph_id
)
2384 switch (otfg
->positioning_type
)
2388 case 1: /* Single */
2391 int format
= otfg
->f
.f1
.format
;
2393 if (format
& OTF_XPlacement
)
2395 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2396 if (format
& OTF_XPlaDevice
)
2398 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2399 if (format
& OTF_YPlacement
)
2401 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2402 if (format
& OTF_YPlaDevice
)
2404 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2405 if (format
& OTF_XAdvance
)
2407 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2408 if (format
& OTF_XAdvDevice
)
2410 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2411 if (format
& OTF_YAdvance
)
2413 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2414 if (format
& OTF_YAdvDevice
)
2416 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2417 adjustment
[i
].set
= 1;
2420 case 3: /* Cursive */
2421 /* Not yet supported. */
2423 case 4: /* Mark-to-Base */
2424 case 5: /* Mark-to-Ligature */
2428 goto label_adjust_anchor
;
2429 default: /* i.e. case 6 Mark-to-Mark */
2434 label_adjust_anchor
:
2436 int base_x
, base_y
, mark_x
, mark_y
;
2437 int this_from
, this_to
;
2439 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2440 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2441 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2442 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2444 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2445 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
, prev
->g
.code
,
2446 x_ppem
, y_ppem
, &base_x
, &base_y
);
2447 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2448 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->g
.code
,
2449 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2450 adjustment
[i
].xoff
= (base_x
- mark_x
);
2451 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2452 adjustment
[i
].back
= (g
- prev
);
2453 adjustment
[i
].xadv
= 0;
2454 adjustment
[i
].advance_is_absolute
= 1;
2455 adjustment
[i
].set
= 1;
2456 this_from
= g
->g
.from
;
2458 for (j
= 0; prev
+ j
< g
; j
++)
2460 if (this_from
> prev
[j
].g
.from
)
2461 this_from
= prev
[j
].g
.from
;
2462 if (this_to
< prev
[j
].g
.to
)
2463 this_to
= prev
[j
].g
.to
;
2465 for (; prev
<= g
; prev
++)
2467 prev
->g
.from
= this_from
;
2468 prev
->g
.to
= this_to
;
2472 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2474 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2485 if (out
->allocated
< out
->used
+ len
)
2487 font
->get_metrics (font
, in
, from
, to
);
2488 memcpy (out_glyphs
+ out
->used
, in_glyphs
,
2489 sizeof (MFLTGlyphFT
) * len
);
2494 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2496 static MFLTGlyphString gstring
;
2498 static bool m17n_flt_initialized
;
2501 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2502 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2504 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2506 struct MFLTFontFT flt_font_ft
;
2508 bool with_variation_selector
= 0;
2509 MFLTGlyphFT
*glyphs
;
2511 if (! m17n_flt_initialized
)
2514 #ifdef M17N_FLT_USE_NEW_FEATURE
2515 mflt_enable_new_feature
= 1;
2516 mflt_try_otf
= ftfont_try_otf
;
2517 #endif /* M17N_FLT_USE_NEW_FEATURE */
2518 m17n_flt_initialized
= 1;
2521 for (i
= 0; i
< len
; i
++)
2523 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2528 c
= LGLYPH_CHAR (g
);
2529 if (CHAR_VARIATION_SELECTOR_P (c
))
2530 with_variation_selector
= 1;
2535 if (with_variation_selector
)
2537 setup_otf_gstring (len
);
2538 for (i
= 0; i
< len
; i
++)
2540 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2542 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2543 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2544 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2546 OTF_drive_cmap (otf
, &otf_gstring
);
2547 for (i
= 0; i
< otf_gstring
.used
; i
++)
2549 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2550 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2551 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2553 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2554 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2555 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2557 if (len
> otf_gstring
.used
)
2559 len
= otf_gstring
.used
;
2560 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2564 if (INT_MAX
/ 2 < len
)
2565 memory_full (SIZE_MAX
);
2567 if (gstring
.allocated
== 0)
2569 gstring
.glyph_size
= sizeof (MFLTGlyphFT
);
2570 gstring
.glyphs
= xnmalloc (len
* 2, sizeof (MFLTGlyphFT
));
2571 gstring
.allocated
= len
* 2;
2573 else if (gstring
.allocated
< len
* 2)
2575 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2576 sizeof (MFLTGlyphFT
));
2577 gstring
.allocated
= len
* 2;
2579 glyphs
= (MFLTGlyphFT
*) (gstring
.glyphs
);
2580 memset (glyphs
, 0, len
* sizeof (MFLTGlyphFT
));
2581 for (i
= 0; i
< len
; i
++)
2583 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2585 glyphs
[i
].g
.c
= LGLYPH_CHAR (g
);
2586 if (with_variation_selector
)
2588 glyphs
[i
].g
.code
= LGLYPH_CODE (g
);
2589 glyphs
[i
].g
.encoded
= 1;
2597 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2600 flt_font_ft
.flt_font
.family
= Mnil
;
2602 flt_font_ft
.flt_font
.family
2603 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2605 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2606 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2607 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2608 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2609 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2610 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2611 flt_font_ft
.flt_font
.internal
= NULL
;
2612 flt_font_ft
.font
= font
;
2613 flt_font_ft
.ft_face
= ft_face
;
2614 flt_font_ft
.otf
= otf
;
2615 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2617 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2618 /* A little bit ad hoc. Perhaps, shaper must get script and
2619 language information, and select a proper flt for them
2621 flt
= mflt_get (msymbol ("combining"));
2622 for (i
= 0; i
< 3; i
++)
2624 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2627 if (INT_MAX
/ 2 < gstring
.allocated
)
2628 memory_full (SIZE_MAX
);
2629 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2630 gstring
.allocated
, 2 * sizeof (MFLTGlyphFT
));
2631 gstring
.allocated
*= 2;
2633 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2635 for (i
= 0; i
< gstring
.used
; i
++)
2637 MFLTGlyphFT
*g
= (MFLTGlyphFT
*) (gstring
.glyphs
) + i
;
2639 g
->g
.from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->g
.from
));
2640 g
->g
.to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->g
.to
));
2643 for (i
= 0; i
< gstring
.used
; i
++)
2645 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2646 MFLTGlyphFT
*g
= (MFLTGlyphFT
*) (gstring
.glyphs
) + i
;
2650 lglyph
= LGLYPH_NEW ();
2651 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2653 LGLYPH_SET_FROM (lglyph
, g
->g
.from
);
2654 LGLYPH_SET_TO (lglyph
, g
->g
.to
);
2655 LGLYPH_SET_CHAR (lglyph
, g
->g
.c
);
2656 LGLYPH_SET_CODE (lglyph
, g
->g
.code
);
2657 LGLYPH_SET_WIDTH (lglyph
, g
->g
.xadv
>> 6);
2658 LGLYPH_SET_LBEARING (lglyph
, g
->g
.lbearing
>> 6);
2659 LGLYPH_SET_RBEARING (lglyph
, g
->g
.rbearing
>> 6);
2660 LGLYPH_SET_ASCENT (lglyph
, g
->g
.ascent
>> 6);
2661 LGLYPH_SET_DESCENT (lglyph
, g
->g
.descent
>> 6);
2664 Lisp_Object vec
= make_uninit_vector (3);
2666 ASET (vec
, 0, make_number (g
->g
.xoff
>> 6));
2667 ASET (vec
, 1, make_number (g
->g
.yoff
>> 6));
2668 ASET (vec
, 2, make_number (g
->g
.xadv
>> 6));
2669 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2672 return make_number (i
);
2676 ftfont_shape (Lisp_Object lgstring
)
2678 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
2679 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2680 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2683 return make_number (0);
2684 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2685 &ftfont_info
->matrix
);
2688 #endif /* HAVE_M17N_FLT */
2690 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2693 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2695 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2696 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2700 return OTF_get_variation_glyphs (otf
, c
, variations
);
2703 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2704 #endif /* HAVE_LIBOTF */
2706 static const char *const ftfont_booleans
[] = {
2719 static const char *const ftfont_non_booleans
[] = {
2751 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2753 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2758 syms_of_ftfont (void)
2760 /* Symbolic type of this font-driver. */
2761 DEFSYM (Qfreetype
, "freetype");
2763 /* Fontconfig's generic families and their aliases. */
2764 DEFSYM (Qmonospace
, "monospace");
2765 DEFSYM (Qsans_serif
, "sans-serif");
2766 DEFSYM (Qsans
, "sans");
2767 DEFSYM (Qsans__serif
, "sans serif");
2769 staticpro (&freetype_font_cache
);
2770 freetype_font_cache
= list1 (Qt
);
2772 staticpro (&ftfont_generic_family_list
);
2773 ftfont_generic_family_list
= list3 (Fcons (Qmonospace
, Qt
),
2774 Fcons (Qsans_serif
, Qt
),
2777 staticpro (&ft_face_cache
);
2778 ft_face_cache
= Qnil
;
2780 ftfont_driver
.type
= Qfreetype
;
2781 register_font_driver (&ftfont_driver
, NULL
);