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 */
72 FTFONT_CACHE_FOR_FACE
,
73 FTFONT_CACHE_FOR_CHARSET
,
74 FTFONT_CACHE_FOR_ENTITY
77 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
79 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
81 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
82 enum ftfont_cache_for
);
84 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
86 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
92 /* characters to distinguish the charset from the others */
94 /* additional constraint by language */
97 FcCharSet
*fc_charset
;
98 } fc_charset_table
[] =
99 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
100 { "iso8859-2", { 0x00A0, 0x010E }},
101 { "iso8859-3", { 0x00A0, 0x0108 }},
102 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
103 { "iso8859-5", { 0x00A0, 0x0401 }},
104 { "iso8859-6", { 0x00A0, 0x060C }},
105 { "iso8859-7", { 0x00A0, 0x0384 }},
106 { "iso8859-8", { 0x00A0, 0x05D0 }},
107 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
108 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
109 { "iso8859-11", { 0x00A0, 0x0E01 }},
110 { "iso8859-13", { 0x00A0, 0x201C }},
111 { "iso8859-14", { 0x00A0, 0x0174 }},
112 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
113 { "iso8859-16", { 0x00A0, 0x0218}},
114 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
115 { "big5-0", { 0xF6B1 }, "zh-tw" },
116 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
117 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
118 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
119 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
120 { "cns11643.1992-3", { 0x201A9 }},
121 { "cns11643.1992-4", { 0x20057 }},
122 { "cns11643.1992-5", { 0x20000 }},
123 { "cns11643.1992-6", { 0x20003 }},
124 { "cns11643.1992-7", { 0x20055 }},
125 { "gbk-0", { 0x4E06 }, "zh-cn"},
126 { "jisx0212.1990-0", { 0x4E44 }},
127 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
128 { "jisx0213.2000-2", { 0xFA49 }},
129 { "jisx0213.2004-1", { 0x20B9F }},
130 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
131 { "tis620.2529-1", { 0x0E01 }, "th"},
132 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
133 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
134 { "mulelao-1", { 0x0E81 }, "lo"},
135 { "unicode-sip", { 0x20000 }},
140 matching_prefix (char const *str
, ptrdiff_t len
, char const *pat
)
142 return len
== strlen (pat
) && c_strncasecmp (str
, pat
, len
) == 0;
145 /* Dirty hack for handing ADSTYLE property.
147 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
148 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
149 "Oblique", "Italic", or any non-normal SWIDTH property names
150 (e.g. SemiCondensed) are appended. In addition, if there's no
151 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
152 "Regular" is used for FC_STYLE (see the function
153 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
155 Unfortunately this behavior is not documented, so the following
156 code may fail if FreeType changes the behavior in the future. */
159 get_adstyle_property (FcPattern
*p
)
166 if ((FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fcstr
) == FcResultMatch
)
167 && xstrcasecmp ((char *) fcstr
, "bdf") != 0
168 && xstrcasecmp ((char *) fcstr
, "pcf") != 0)
169 /* Not a BDF nor PCF font. */
172 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
174 str
= (char *) fcstr
;
175 for (end
= str
; *end
&& *end
!= ' '; end
++);
176 if (matching_prefix (str
, end
- str
, "Regular")
177 || matching_prefix (str
, end
- str
, "Bold")
178 || matching_prefix (str
, end
- str
, "Oblique")
179 || matching_prefix (str
, end
- str
, "Italic"))
181 adstyle
= font_intern_prop (str
, end
- str
, 1);
182 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
188 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
190 Lisp_Object key
, cache
, entity
;
198 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
200 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
204 key
= Fcons (build_unibyte_string (file
), make_number (idx
));
205 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
206 entity
= XCAR (cache
);
209 Lisp_Object val
= font_make_entity ();
212 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
213 ASET (val
, i
, AREF (entity
, i
));
215 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
216 font_put_extra (val
, QCfont_entity
, key
);
220 entity
= font_make_entity ();
221 XSETCAR (cache
, entity
);
223 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
224 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
226 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
228 char *s
= (char *) str
;
229 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
231 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
233 char *s
= (char *) str
;
234 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
236 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
238 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
239 numeric
= FC_WEIGHT_MEDIUM
;
240 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
242 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
245 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
247 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
249 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
251 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
253 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
256 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
257 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
258 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
259 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
262 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
264 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
267 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
268 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
272 /* As this font is not scalable, perhaps this is a BDF or PCF
276 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
277 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
278 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
282 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
283 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
284 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
285 FT_Done_Face (ft_face
);
289 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
290 font_put_extra (entity
, QCfont_entity
, key
);
295 static Lisp_Object ftfont_generic_family_list
;
298 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
305 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
306 if (EQ (family
, Qmono
))
308 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
309 family
= Qsans_serif
;
310 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
313 if (! EQ (XCDR (slot
), Qt
))
315 pattern
= FcPatternDuplicate (pattern
);
318 FcPatternDel (pattern
, FC_FOUNDRY
);
319 FcPatternDel (pattern
, FC_FAMILY
);
320 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
321 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
323 /* This is to avoid the effect of locale. */
324 static const FcChar8 lang
[] = "en";
325 langset
= FcLangSetCreate ();
326 FcLangSetAdd (langset
, lang
);
327 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
328 FcLangSetDestroy (langset
);
330 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
331 FcDefaultSubstitute (pattern
);
332 match
= FcFontMatch (NULL
, pattern
, &result
);
337 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
338 family
= intern ((char *) fam
);
342 XSETCDR (slot
, family
);
343 if (match
) FcPatternDestroy (match
);
345 if (pattern
) FcPatternDestroy (pattern
);
349 struct ftfont_cache_data
352 FcCharSet
*fc_charset
;
356 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
358 Lisp_Object cache
, val
, entity
;
359 struct ftfont_cache_data
*cache_data
;
361 if (FONT_ENTITY_P (key
))
364 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
365 eassert (CONSP (val
));
371 if (NILP (ft_face_cache
))
374 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
377 if (NILP (ft_face_cache
))
383 ft_face_cache
= Fmake_hash_table (2, args
);
385 cache_data
= xmalloc (sizeof *cache_data
);
386 cache_data
->ft_face
= NULL
;
387 cache_data
->fc_charset
= NULL
;
388 val
= make_save_ptr_int (cache_data
, 0);
389 cache
= Fcons (Qnil
, val
);
390 Fputhash (key
, cache
, ft_face_cache
);
395 cache_data
= XSAVE_POINTER (val
, 0);
398 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
401 if (cache_for
== FTFONT_CACHE_FOR_FACE
402 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
404 char *filename
= SSDATA (XCAR (key
));
405 int idx
= XINT (XCDR (key
));
407 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
410 && FT_Init_FreeType (&ft_library
) != 0)
412 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
418 FcPattern
*pat
= NULL
;
419 FcFontSet
*fontset
= NULL
;
420 FcObjectSet
*objset
= NULL
;
421 FcCharSet
*charset
= NULL
;
423 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
424 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
427 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
430 fontset
= FcFontList (NULL
, pat
, objset
);
433 if (fontset
&& fontset
->nfont
> 0
434 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
437 cache_data
->fc_charset
= FcCharSetCopy (charset
);
439 cache_data
->fc_charset
= FcCharSetCreate ();
443 FcFontSetDestroy (fontset
);
445 FcObjectSetDestroy (objset
);
447 FcPatternDestroy (pat
);
454 ftfont_get_fc_charset (Lisp_Object entity
)
456 Lisp_Object val
, cache
;
457 struct ftfont_cache_data
*cache_data
;
459 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
461 cache_data
= XSAVE_POINTER (val
, 0);
462 return cache_data
->fc_charset
;
467 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
471 if (ftfont_info
->otf
)
472 return ftfont_info
->otf
;
473 if (! ftfont_info
->maybe_otf
)
475 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
476 if (! otf
|| OTF_get_table (otf
, "head") < 0)
480 ftfont_info
->maybe_otf
= 0;
483 ftfont_info
->otf
= otf
;
486 #endif /* HAVE_LIBOTF */
488 static Lisp_Object
ftfont_get_cache (struct frame
*);
489 static Lisp_Object
ftfont_list (struct frame
*, Lisp_Object
);
490 static Lisp_Object
ftfont_match (struct frame
*, Lisp_Object
);
491 static Lisp_Object
ftfont_list_family (struct frame
*);
492 static Lisp_Object
ftfont_open (struct frame
*, Lisp_Object
, int);
493 static void ftfont_close (struct font
*);
494 static int ftfont_has_char (Lisp_Object
, int);
495 static unsigned ftfont_encode_char (struct font
*, int);
496 static void ftfont_text_extents (struct font
*, unsigned *, int,
497 struct font_metrics
*);
498 static int ftfont_get_bitmap (struct font
*, unsigned,
499 struct font_bitmap
*, int);
500 static int ftfont_anchor_point (struct font
*, unsigned, int,
503 static Lisp_Object
ftfont_otf_capability (struct font
*);
504 # ifdef HAVE_M17N_FLT
505 static Lisp_Object
ftfont_shape (Lisp_Object
);
509 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
510 static int ftfont_variation_glyphs (struct font
*, int c
,
511 unsigned variations
[256]);
512 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
514 struct font_driver ftfont_driver
=
516 LISP_INITIALLY_ZERO
, /* Qfreetype */
517 0, /* case insensitive */
522 NULL
, /* free_entity */
525 /* We can't draw a text without device dependent functions. */
526 NULL
, /* prepare_face */
527 NULL
, /* done_face */
531 /* We can't draw a text without device dependent functions. */
534 NULL
, /* free_bitmap */
537 ftfont_otf_capability
,
538 #else /* not HAVE_LIBOTF */
540 #endif /* not HAVE_LIBOTF */
541 NULL
, /* otf_drive */
542 NULL
, /* start_for_frame */
543 NULL
, /* end_for_frame */
544 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
546 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
548 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
551 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
552 ftfont_variation_glyphs
,
557 ftfont_filter_properties
, /* filter_properties */
561 ftfont_get_cache (struct frame
*f
)
563 return freetype_font_cache
;
567 ftfont_get_charset (Lisp_Object registry
)
569 char *str
= SSDATA (SYMBOL_NAME (registry
));
571 char *re
= SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
575 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
579 else if (str
[i
] == '*')
586 regexp
= make_unibyte_string (re
, j
);
588 for (i
= 0; fc_charset_table
[i
].name
; i
++)
589 if (fast_c_string_match_ignore_case
590 (regexp
, fc_charset_table
[i
].name
,
591 strlen (fc_charset_table
[i
].name
)) >= 0)
593 if (! fc_charset_table
[i
].name
)
595 if (! fc_charset_table
[i
].fc_charset
)
597 FcCharSet
*charset
= FcCharSetCreate ();
598 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
602 for (j
= 0; uniquifier
[j
]; j
++)
603 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
605 FcCharSetDestroy (charset
);
608 fc_charset_table
[i
].fc_charset
= charset
;
616 unsigned int script_tag
, langsys_tag
;
618 unsigned int *features
[2];
621 #define OTF_SYM_TAG(SYM, TAG) \
623 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
624 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
627 #define OTF_TAG_STR(TAG, P) \
629 (P)[0] = (char) (TAG >> 24); \
630 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
631 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
632 (P)[3] = (char) (TAG & 0xFF); \
637 #define OTF_TAG_SYM(SYM, TAG) \
641 OTF_TAG_STR (TAG, str); \
642 (SYM) = font_intern_prop (str, 4, 1); \
647 static struct OpenTypeSpec
*
648 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
650 struct OpenTypeSpec
*spec
= malloc (sizeof *spec
);
657 spec
->script
= XCAR (otf_spec
);
658 if (! NILP (spec
->script
))
660 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
661 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
662 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
663 spec
->script
= XCDR (val
);
668 spec
->script_tag
= 0x44464C54; /* "DFLT" */
669 otf_spec
= XCDR (otf_spec
);
670 spec
->langsys_tag
= 0;
671 if (! NILP (otf_spec
))
673 val
= XCAR (otf_spec
);
675 OTF_SYM_TAG (val
, spec
->langsys_tag
);
676 otf_spec
= XCDR (otf_spec
);
678 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
679 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
683 val
= XCAR (otf_spec
);
688 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
690 : malloc (XINT (len
) * sizeof *spec
->features
[i
]));
691 if (! spec
->features
[i
])
693 if (i
> 0 && spec
->features
[0])
694 free (spec
->features
[0]);
698 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
700 if (NILP (XCAR (val
)))
706 OTF_SYM_TAG (XCAR (val
), tag
);
707 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
710 spec
->nfeatures
[i
] = j
;
716 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
718 Lisp_Object tmp
, extra
;
719 FcPattern
*pattern
= NULL
;
720 FcCharSet
*charset
= NULL
;
721 FcLangSet
*langset
= NULL
;
725 Lisp_Object script
= Qnil
;
726 Lisp_Object registry
;
729 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
731 /* Fontconfig doesn't support reverse-italic/oblique. */
734 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
735 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
736 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
737 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
740 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
742 || EQ (registry
, Qascii_0
)
743 || EQ (registry
, Qiso10646_1
)
744 || EQ (registry
, Qunicode_bmp
))
750 fc_charset_idx
= ftfont_get_charset (registry
);
751 if (fc_charset_idx
< 0)
753 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
754 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
755 lang
= (FcChar8
*) *langname
;
758 langset
= FcLangSetCreate ();
761 FcLangSetAdd (langset
, lang
);
766 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
767 CONSP (extra
); extra
= XCDR (extra
))
769 Lisp_Object key
, val
;
771 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
777 else if (EQ (key
, QClang
))
780 langset
= FcLangSetCreate ();
785 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
789 for (; CONSP (val
); val
= XCDR (val
))
790 if (SYMBOLP (XCAR (val
))
791 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
794 else if (EQ (key
, QCotf
))
798 *otspec
= ftfont_get_open_type_spec (val
);
801 strcpy (otlayout
, "otlayout:");
802 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
803 script
= (*otspec
)->script
;
806 else if (EQ (key
, QCscript
))
808 else if (EQ (key
, QCscalable
))
809 scalable
= ! NILP (val
);
812 if (! NILP (script
) && ! charset
)
814 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
816 if (CONSP (chars
) && CONSP (CDR (chars
)))
818 charset
= FcCharSetCreate ();
821 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
822 if (CHARACTERP (XCAR (chars
))
823 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
828 pattern
= FcPatternCreate ();
831 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
833 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
835 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
837 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
840 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
843 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
846 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
849 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
855 /* We come here because of unexpected error in fontconfig API call
856 (usually insufficient memory). */
859 FcPatternDestroy (pattern
);
864 if ((*otspec
)->nfeatures
[0] > 0)
865 free ((*otspec
)->features
[0]);
866 if ((*otspec
)->nfeatures
[1] > 0)
867 free ((*otspec
)->features
[1]);
873 if (langset
) FcLangSetDestroy (langset
);
874 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
879 ftfont_list (struct frame
*f
, Lisp_Object spec
)
881 Lisp_Object val
= Qnil
, family
, adstyle
;
884 FcFontSet
*fontset
= NULL
;
885 FcObjectSet
*objset
= NULL
;
887 Lisp_Object chars
= Qnil
;
888 char otlayout
[15]; /* For "otlayout:XXXX" */
889 struct OpenTypeSpec
*otspec
= NULL
;
891 const char *langname
= NULL
;
893 if (! fc_initialized
)
899 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
902 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
904 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
907 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
908 if (CONSP (val
) && VECTORP (XCDR (val
)))
913 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
914 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
915 family
= AREF (spec
, FONT_FAMILY_INDEX
);
918 Lisp_Object resolved
;
920 resolved
= ftfont_resolve_generic_family (family
, pattern
);
921 if (! NILP (resolved
))
923 FcPatternDel (pattern
, FC_FAMILY
);
924 if (! FcPatternAddString (pattern
, FC_FAMILY
,
925 SYMBOL_FcChar8 (resolved
)))
929 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
930 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
932 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
933 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
934 FC_STYLE
, FC_FILE
, FC_INDEX
,
937 #endif /* FC_CAPABILITY */
945 FcObjectSetAdd (objset
, FC_CHARSET
);
947 fontset
= FcFontList (NULL
, pattern
, objset
);
948 if (! fontset
|| fontset
->nfont
== 0)
951 /* Need fix because this finds any fonts. */
952 if (fontset
->nfont
== 0 && ! NILP (family
))
954 /* Try matching with configuration. For instance, the
955 configuration may specify "Nimbus Mono L" as an alias of
957 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
958 SYMBOL_FcChar8 (family
), NULL
);
961 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
964 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
967 FcPatternDel (pattern
, FC_FAMILY
);
968 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
969 FcFontSetDestroy (fontset
);
970 fontset
= FcFontList (NULL
, pattern
, objset
);
971 if (fontset
&& fontset
->nfont
> 0)
977 for (i
= 0; i
< fontset
->nfont
; i
++)
985 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
996 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
998 || ! strstr ((char *) this, otlayout
))
1001 #endif /* FC_CAPABILITY */
1009 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1012 otf
= OTF_open ((char *) file
);
1015 passed
= (OTF_check_features (otf
, 1, otspec
->script_tag
,
1016 otspec
->langsys_tag
,
1017 otspec
->features
[0],
1018 otspec
->nfeatures
[0]) == 1
1019 && OTF_check_features (otf
, 0, otspec
->script_tag
,
1020 otspec
->langsys_tag
,
1021 otspec
->features
[1],
1022 otspec
->nfeatures
[1]) == 1);
1027 #endif /* HAVE_LIBOTF */
1028 if (VECTORP (chars
))
1032 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1035 for (j
= 0; j
< ASIZE (chars
); j
++)
1036 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1037 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1039 if (j
== ASIZE (chars
))
1042 if (! NILP (adstyle
) || langname
)
1044 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1046 if (! NILP (adstyle
)
1047 && (NILP (this_adstyle
)
1048 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1049 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1052 && ! NILP (this_adstyle
)
1053 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1056 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1057 AREF (spec
, FONT_EXTRA_INDEX
));
1058 if (! NILP (entity
))
1059 val
= Fcons (entity
, val
);
1061 val
= Fnreverse (val
);
1065 /* We come here because of unexpected error in fontconfig API call
1066 (usually insufficient memory). */
1070 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1071 if (objset
) FcObjectSetDestroy (objset
);
1072 if (fontset
) FcFontSetDestroy (fontset
);
1073 if (pattern
) FcPatternDestroy (pattern
);
1078 ftfont_match (struct frame
*f
, Lisp_Object spec
)
1080 Lisp_Object entity
= Qnil
;
1081 FcPattern
*pattern
, *match
= NULL
;
1083 char otlayout
[15]; /* For "otlayout:XXXX" */
1084 struct OpenTypeSpec
*otspec
= NULL
;
1085 const char *langname
= NULL
;
1087 if (! fc_initialized
)
1093 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1097 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1101 value
.type
= FcTypeDouble
;
1102 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1103 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1105 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1107 FcDefaultSubstitute (pattern
);
1108 match
= FcFontMatch (NULL
, pattern
, &result
);
1111 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1112 FcPatternDestroy (match
);
1113 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1114 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1115 ftfont_generic_family_list
))
1116 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1117 AREF (entity
, FONT_FAMILY_INDEX
))))
1121 FcPatternDestroy (pattern
);
1123 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1128 ftfont_list_family (struct frame
*f
)
1130 Lisp_Object list
= Qnil
;
1131 FcPattern
*pattern
= NULL
;
1132 FcFontSet
*fontset
= NULL
;
1133 FcObjectSet
*objset
= NULL
;
1136 if (! fc_initialized
)
1142 pattern
= FcPatternCreate ();
1145 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1148 fontset
= FcFontList (NULL
, pattern
, objset
);
1152 for (i
= 0; i
< fontset
->nfont
; i
++)
1154 FcPattern
*pat
= fontset
->fonts
[i
];
1157 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1158 list
= Fcons (intern ((char *) str
), list
);
1162 if (objset
) FcObjectSetDestroy (objset
);
1163 if (fontset
) FcFontSetDestroy (fontset
);
1164 if (pattern
) FcPatternDestroy (pattern
);
1171 ftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
1173 struct ftfont_info
*ftfont_info
;
1175 struct ftfont_cache_data
*cache_data
;
1179 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1185 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1189 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1192 filename
= XCAR (val
);
1195 cache_data
= XSAVE_POINTER (XCDR (cache
), 0);
1196 ft_face
= cache_data
->ft_face
;
1197 if (XSAVE_INTEGER (val
, 1) > 0)
1199 /* FT_Face in this cache is already used by the different size. */
1200 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1202 if (FT_Activate_Size (ft_size
) != 0)
1204 FT_Done_Size (ft_size
);
1208 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) + 1);
1209 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1212 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1214 if (XSAVE_INTEGER (val
, 1) == 0)
1215 FT_Done_Face (ft_face
);
1219 font_object
= font_build_object (VECSIZE (struct ftfont_info
),
1220 Qfreetype
, entity
, size
);
1221 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1222 font
= XFONT_OBJECT (font_object
);
1223 ftfont_info
= (struct ftfont_info
*) font
;
1224 ftfont_info
->ft_size
= ft_face
->size
;
1225 ftfont_info
->index
= XINT (idx
);
1227 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1228 ftfont_info
->otf
= NULL
;
1229 #endif /* HAVE_LIBOTF */
1230 /* This means that there's no need of transformation. */
1231 ftfont_info
->matrix
.xx
= 0;
1232 font
->pixel_size
= size
;
1233 font
->driver
= &ftfont_driver
;
1234 font
->encoding_charset
= font
->repertory_charset
= -1;
1236 upEM
= ft_face
->units_per_EM
;
1237 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1238 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1241 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1242 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1243 font
->height
= ft_face
->height
* size
/ upEM
;
1247 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1248 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1249 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1251 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1252 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1254 spacing
= FC_PROPORTIONAL
;
1255 if (spacing
!= FC_PROPORTIONAL
1257 && spacing
!= FC_DUAL
1258 #endif /* FC_DUAL */
1260 font
->min_width
= font
->average_width
= font
->space_width
1261 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1262 : ft_face
->size
->metrics
.max_advance
>> 6);
1267 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1268 for (i
= 32, n
= 0; i
< 127; i
++)
1269 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1271 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1274 && (! font
->min_width
|| font
->min_width
> this_width
))
1275 font
->min_width
= this_width
;
1277 font
->space_width
= this_width
;
1278 font
->average_width
+= this_width
;
1282 font
->average_width
/= n
;
1285 font
->baseline_offset
= 0;
1286 font
->relative_compose
= 0;
1287 font
->default_ascent
= 0;
1288 font
->vertical_centering
= 0;
1291 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1292 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1296 font
->underline_position
= -1;
1297 font
->underline_thickness
= 0;
1304 ftfont_close (struct font
*font
)
1306 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1307 Lisp_Object val
, cache
;
1309 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1310 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1311 eassert (CONSP (cache
));
1313 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) - 1);
1314 if (XSAVE_INTEGER (val
, 1) == 0)
1316 struct ftfont_cache_data
*cache_data
= XSAVE_POINTER (val
, 0);
1318 FT_Done_Face (cache_data
->ft_face
);
1320 if (ftfont_info
->otf
)
1321 OTF_close (ftfont_info
->otf
);
1323 cache_data
->ft_face
= NULL
;
1326 FT_Done_Size (ftfont_info
->ft_size
);
1330 ftfont_has_char (Lisp_Object font
, int c
)
1332 struct charset
*cs
= NULL
;
1334 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1335 && charset_jisx0208
>= 0)
1336 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1337 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1338 && charset_ksc5601
>= 0)
1339 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1341 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1343 if (FONT_ENTITY_P (font
))
1345 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1347 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1351 struct ftfont_info
*ftfont_info
;
1353 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1354 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1360 ftfont_encode_char (struct font
*font
, int c
)
1362 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1363 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1364 FT_ULong charcode
= c
;
1365 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1367 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1371 ftfont_text_extents (struct font
*font
, unsigned int *code
,
1372 int nglyphs
, struct font_metrics
*metrics
)
1374 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1375 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1379 if (ftfont_info
->ft_size
!= ft_face
->size
)
1380 FT_Activate_Size (ftfont_info
->ft_size
);
1382 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1384 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1386 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1390 metrics
->lbearing
= m
->horiBearingX
>> 6;
1391 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1392 metrics
->ascent
= m
->horiBearingY
>> 6;
1393 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1396 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1397 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1398 if (metrics
->rbearing
1399 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1401 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1402 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1403 metrics
->ascent
= m
->horiBearingY
>> 6;
1404 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1405 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1406 width
+= m
->horiAdvance
>> 6;
1409 width
+= font
->space_width
;
1411 metrics
->width
= width
;
1415 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1417 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1418 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1419 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1421 if (ftfont_info
->ft_size
!= ft_face
->size
)
1422 FT_Activate_Size (ftfont_info
->ft_size
);
1423 if (bits_per_pixel
== 1)
1425 #ifdef FT_LOAD_TARGET_MONO
1426 load_flags
|= FT_LOAD_TARGET_MONO
;
1428 load_flags
|= FT_LOAD_MONOCHROME
;
1431 else if (bits_per_pixel
!= 8)
1432 /* We don't support such a rendering. */
1435 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1437 bitmap
->bits_per_pixel
1438 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1439 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1440 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1441 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1443 if (bitmap
->bits_per_pixel
< 0)
1444 /* We don't support that kind of pixel mode. */
1446 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1447 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1448 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1449 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1450 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1451 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1452 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1458 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1461 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1462 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1464 if (ftfont_info
->ft_size
!= ft_face
->size
)
1465 FT_Activate_Size (ftfont_info
->ft_size
);
1466 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1468 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1470 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1472 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1473 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1480 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1482 Lisp_Object scripts
, langsyses
, features
, sym
;
1485 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1487 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1489 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1491 OTF_LangSys
*otf_langsys
;
1494 otf_langsys
= otf_script
->LangSys
+ j
;
1495 else if (otf_script
->DefaultLangSysOffset
)
1496 otf_langsys
= &otf_script
->DefaultLangSys
;
1500 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1502 l
= otf_langsys
->FeatureIndex
[k
];
1503 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1505 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1506 features
= Fcons (sym
, features
);
1509 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1512 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1515 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1516 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1524 ftfont_otf_capability (struct font
*font
)
1526 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1527 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1528 Lisp_Object gsub_gpos
;
1532 gsub_gpos
= Fcons (Qnil
, Qnil
);
1533 if (OTF_get_table (otf
, "GSUB") == 0
1534 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1535 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1536 if (OTF_get_table (otf
, "GPOS") == 0
1537 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1538 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1542 #ifdef HAVE_M17N_FLT
1544 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1545 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1546 /* We can use the new feature of libotf and m17n-flt to handle the
1547 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1548 some Agian scripts. */
1549 #define M17N_FLT_USE_NEW_FEATURE
1562 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1565 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1566 FT_Face ft_face
= flt_font_ft
->ft_face
;
1569 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1572 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1574 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1580 /* Operators for 26.6 fixed fractional pixel format */
1582 #define FLOOR(x) ((x) & -64)
1583 #define CEIL(x) (((x)+63) & -64)
1584 #define ROUND(x) (((x)+32) & -64)
1587 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1590 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1591 FT_Face ft_face
= flt_font_ft
->ft_face
;
1594 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1597 if (g
->code
!= FONT_INVALID_CODE
)
1599 FT_Glyph_Metrics
*m
;
1601 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1603 m
= &ft_face
->glyph
->metrics
;
1604 if (flt_font_ft
->matrix
)
1609 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1610 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1611 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1612 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1613 for (i
= 0; i
< 4; i
++)
1614 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1615 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1616 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1617 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1618 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1622 g
->lbearing
= FLOOR (m
->horiBearingX
);
1623 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1624 g
->ascent
= CEIL (m
->horiBearingY
);
1625 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1627 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1632 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1633 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1634 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1643 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1645 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1647 #define FEATURE_ANY(IDX) \
1648 (spec->features[IDX] \
1649 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1651 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1652 OTF
*otf
= flt_font_ft
->otf
;
1657 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1658 /* Return true iff any of GSUB or GPOS support the script (and
1661 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1663 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1666 for (i
= 0; i
< 2; i
++)
1667 if (! FEATURE_ANY (i
))
1669 if (FEATURE_NONE (i
))
1672 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1677 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1680 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1686 for (n
= 1; spec
->features
[i
][n
]; n
++);
1688 SAFE_NALLOCA (tags
, 1, n
);
1689 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1691 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1694 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1696 tags
[n
] = spec
->features
[i
][n
];
1699 #ifndef M17N_FLT_USE_NEW_FEATURE
1700 passed
= n
- negative
> 0;
1703 passed
= (OTF_check_features (otf
, i
== 0, spec
->script
,
1704 spec
->langsys
, tags
, n
- negative
)
1715 #define DEVICE_DELTA(table, size) \
1716 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1717 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1721 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1722 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1724 if (anchor
->AnchorFormat
== 2)
1726 FT_Outline
*outline
;
1727 int ap
= anchor
->f
.f1
.AnchorPoint
;
1729 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1730 outline
= &ft_face
->glyph
->outline
;
1731 if (ap
< outline
->n_points
)
1733 *x
= outline
->points
[ap
].x
<< 6;
1734 *y
= outline
->points
[ap
].y
<< 6;
1737 else if (anchor
->AnchorFormat
== 3)
1739 if (anchor
->f
.f2
.XDeviceTable
.offset
1740 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1741 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1742 if (anchor
->f
.f2
.YDeviceTable
.offset
1743 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1744 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1748 static OTF_GlyphString otf_gstring
;
1751 setup_otf_gstring (int size
)
1753 if (otf_gstring
.size
< size
)
1755 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1756 size
, sizeof (OTF_Glyph
));
1757 otf_gstring
.size
= size
;
1759 otf_gstring
.used
= size
;
1760 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1763 #ifdef M17N_FLT_USE_NEW_FEATURE
1765 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1766 #define PACK_OTF_TAG(TAG) \
1767 ((((TAG) & 0x7F000000) >> 3) \
1768 | (((TAG) & 0x7F0000) >> 2) \
1769 | (((TAG) & 0x7F00) >> 1) \
1772 /* Assuming that FONT is an OpenType font, apply OpenType features
1773 specified in SPEC on glyphs between FROM and TO of IN, and record
1774 the lastly applied feature in each glyph of IN. If OUT is not
1775 NULL, append the resulting glyphs to OUT while storing glyph
1776 position adjustment information in ADJUSTMENT. */
1779 ftfont_drive_otf (MFLTFont
*font
,
1781 MFLTGlyphString
*in
,
1784 MFLTGlyphString
*out
,
1785 MFLTGlyphAdjustment
*adjustment
)
1787 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1788 FT_Face ft_face
= flt_font_ft
->ft_face
;
1789 OTF
*otf
= flt_font_ft
->otf
;
1790 int len
= to
- from
;
1793 char script
[5], *langsys
= NULL
;
1794 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1795 OTF_Feature
*features
;
1799 OTF_tag_name (spec
->script
, script
);
1804 langsys
= langsysbuf
;
1805 OTF_tag_name (spec
->langsys
, langsys
);
1809 for (i
= 0; i
< 2; i
++)
1813 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1815 for (j
= 0; spec
->features
[i
][j
]; j
++);
1816 SAFE_NALLOCA (p
, 6, j
);
1821 for (j
= 0; spec
->features
[i
][j
]; j
++)
1823 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1824 *p
++ = '*', *p
++ = ',';
1827 OTF_tag_name (spec
->features
[i
][j
], p
);
1836 setup_otf_gstring (len
);
1837 for (i
= 0; i
< len
; i
++)
1839 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
& 0x11FFFF;
1840 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1843 OTF_drive_gdef (otf
, &otf_gstring
);
1844 gidx
= out
? out
->used
: from
;
1846 if (gsub_features
&& out
)
1848 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1851 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1856 features
= otf
->gsub
->FeatureList
.Feature
;
1857 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1860 int min_from
, max_to
;
1861 int feature_idx
= otfg
->positioning_type
>> 4;
1863 g
= out
->glyphs
+ out
->used
;
1864 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1865 if (g
->code
!= otfg
->glyph_id
)
1868 g
->code
= otfg
->glyph_id
;
1874 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1876 /* OTFG substitutes multiple glyphs in IN. */
1877 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1878 j
<= from
+ otfg
->f
.index
.to
; j
++)
1880 if (min_from
> in
->glyphs
[j
].from
)
1881 min_from
= in
->glyphs
[j
].from
;
1882 if (max_to
< in
->glyphs
[j
].to
)
1883 max_to
= in
->glyphs
[j
].to
;
1890 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1891 tag
= PACK_OTF_TAG (tag
);
1892 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1894 for (i
++, otfg
++; (i
< otf_gstring
.used
1895 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1898 g
= out
->glyphs
+ out
->used
;
1899 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1900 if (g
->code
!= otfg
->glyph_id
)
1903 g
->code
= otfg
->glyph_id
;
1906 feature_idx
= otfg
->positioning_type
>> 4;
1909 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1910 tag
= PACK_OTF_TAG (tag
);
1911 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1917 else if (gsub_features
)
1919 /* Just for checking which features will be applied. */
1920 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1923 features
= otf
->gsub
->FeatureList
.Feature
;
1924 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1927 int feature_idx
= otfg
->positioning_type
>> 4;
1931 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1932 tag
= PACK_OTF_TAG (tag
);
1933 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1935 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1936 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1943 if (out
->allocated
< out
->used
+ len
)
1948 for (i
= 0; i
< len
; i
++)
1949 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1952 if (gpos_features
&& out
)
1954 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1955 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1957 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1963 features
= otf
->gpos
->FeatureList
.Feature
;
1964 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1965 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1966 x_scale
= ft_face
->size
->metrics
.x_scale
;
1967 y_scale
= ft_face
->size
->metrics
.y_scale
;
1969 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1970 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1973 int feature_idx
= otfg
->positioning_type
>> 4;
1977 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1978 tag
= PACK_OTF_TAG (tag
);
1979 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1982 if (! otfg
->glyph_id
)
1984 switch (otfg
->positioning_type
& 0xF)
1988 case 1: /* Single */
1991 int format
= otfg
->f
.f1
.format
;
1993 if (format
& OTF_XPlacement
)
1995 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1996 if (format
& OTF_XPlaDevice
)
1998 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1999 if (format
& OTF_YPlacement
)
2001 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2002 if (format
& OTF_YPlaDevice
)
2004 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2005 if (format
& OTF_XAdvance
)
2007 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2008 if (format
& OTF_XAdvDevice
)
2010 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2011 if (format
& OTF_YAdvance
)
2013 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2014 if (format
& OTF_YAdvDevice
)
2016 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2017 adjustment
[i
].set
= 1;
2020 case 3: /* Cursive */
2021 /* Not yet supported. */
2023 case 4: /* Mark-to-Base */
2024 case 5: /* Mark-to-Ligature */
2028 goto label_adjust_anchor
;
2029 default: /* i.e. case 6 Mark-to-Mark */
2034 label_adjust_anchor
:
2036 int base_x
, base_y
, mark_x
, mark_y
;
2037 int this_from
, this_to
;
2039 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2040 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2041 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2042 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2044 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2045 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2046 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2047 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2048 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2049 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2050 adjustment
[i
].xoff
= (base_x
- mark_x
);
2051 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2052 adjustment
[i
].back
= (g
- prev
);
2053 adjustment
[i
].xadv
= 0;
2054 adjustment
[i
].advance_is_absolute
= 1;
2055 adjustment
[i
].set
= 1;
2056 this_from
= g
->from
;
2058 for (j
= 0; prev
+ j
< g
; j
++)
2060 if (this_from
> prev
[j
].from
)
2061 this_from
= prev
[j
].from
;
2062 if (this_to
< prev
[j
].to
)
2063 this_to
= prev
[j
].to
;
2065 for (; prev
<= g
; prev
++)
2067 prev
->from
= this_from
;
2072 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2074 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2080 else if (gpos_features
)
2082 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2088 features
= otf
->gpos
->FeatureList
.Feature
;
2089 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2091 if (otfg
->positioning_type
& 0xF)
2093 int feature_idx
= otfg
->positioning_type
>> 4;
2097 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2098 tag
= PACK_OTF_TAG (tag
);
2099 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2101 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2102 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2114 if (out
->allocated
< out
->used
+ len
)
2116 font
->get_metrics (font
, in
, from
, to
);
2117 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2118 sizeof (MFLTGlyph
) * len
);
2124 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2125 MFLTGlyphString
*in
, int from
, int to
)
2127 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2130 #else /* not M17N_FLT_USE_NEW_FEATURE */
2133 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2135 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2137 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2138 FT_Face ft_face
= flt_font_ft
->ft_face
;
2139 OTF
*otf
= flt_font_ft
->otf
;
2140 int len
= to
- from
;
2143 char script
[5], *langsys
= NULL
;
2144 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2148 OTF_tag_name (spec
->script
, script
);
2153 langsys
= langsysbuf
;
2154 OTF_tag_name (spec
->langsys
, langsys
);
2158 for (i
= 0; i
< 2; i
++)
2162 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2164 for (j
= 0; spec
->features
[i
][j
]; j
++);
2165 SAFE_NALLOCA (p
, 6, j
);
2170 for (j
= 0; spec
->features
[i
][j
]; j
++)
2172 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2173 *p
++ = '*', *p
++ = ',';
2176 OTF_tag_name (spec
->features
[i
][j
], p
);
2185 setup_otf_gstring (len
);
2186 for (i
= 0; i
< len
; i
++)
2188 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2189 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2192 OTF_drive_gdef (otf
, &otf_gstring
);
2197 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2200 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2205 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2208 int min_from
, max_to
;
2211 g
= out
->glyphs
+ out
->used
;
2212 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2213 if (g
->code
!= otfg
->glyph_id
)
2216 g
->code
= otfg
->glyph_id
;
2222 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2224 /* OTFG substitutes multiple glyphs in IN. */
2225 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2226 j
<= from
+ otfg
->f
.index
.to
; j
++)
2228 if (min_from
> in
->glyphs
[j
].from
)
2229 min_from
= in
->glyphs
[j
].from
;
2230 if (max_to
< in
->glyphs
[j
].to
)
2231 max_to
= in
->glyphs
[j
].to
;
2236 for (i
++, otfg
++; (i
< otf_gstring
.used
2237 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2240 g
= out
->glyphs
+ out
->used
;
2241 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2242 if (g
->code
!= otfg
->glyph_id
)
2245 g
->code
= otfg
->glyph_id
;
2254 if (out
->allocated
< out
->used
+ len
)
2259 for (i
= 0; i
< len
; i
++)
2260 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2265 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2266 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2268 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2275 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2276 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2277 x_scale
= ft_face
->size
->metrics
.x_scale
;
2278 y_scale
= ft_face
->size
->metrics
.y_scale
;
2280 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2281 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2285 if (! otfg
->glyph_id
)
2287 switch (otfg
->positioning_type
)
2291 case 1: /* Single */
2294 int format
= otfg
->f
.f1
.format
;
2296 if (format
& OTF_XPlacement
)
2298 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2299 if (format
& OTF_XPlaDevice
)
2301 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2302 if (format
& OTF_YPlacement
)
2304 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2305 if (format
& OTF_YPlaDevice
)
2307 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2308 if (format
& OTF_XAdvance
)
2310 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2311 if (format
& OTF_XAdvDevice
)
2313 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2314 if (format
& OTF_YAdvance
)
2316 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2317 if (format
& OTF_YAdvDevice
)
2319 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2320 adjustment
[i
].set
= 1;
2323 case 3: /* Cursive */
2324 /* Not yet supported. */
2326 case 4: /* Mark-to-Base */
2327 case 5: /* Mark-to-Ligature */
2331 goto label_adjust_anchor
;
2332 default: /* i.e. case 6 Mark-to-Mark */
2337 label_adjust_anchor
:
2339 int base_x
, base_y
, mark_x
, mark_y
;
2340 int this_from
, this_to
;
2342 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2343 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2344 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2345 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2347 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2348 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2349 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2350 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2351 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2352 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2353 adjustment
[i
].xoff
= (base_x
- mark_x
);
2354 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2355 adjustment
[i
].back
= (g
- prev
);
2356 adjustment
[i
].xadv
= 0;
2357 adjustment
[i
].advance_is_absolute
= 1;
2358 adjustment
[i
].set
= 1;
2359 this_from
= g
->from
;
2361 for (j
= 0; prev
+ j
< g
; j
++)
2363 if (this_from
> prev
[j
].from
)
2364 this_from
= prev
[j
].from
;
2365 if (this_to
< prev
[j
].to
)
2366 this_to
= prev
[j
].to
;
2368 for (; prev
<= g
; prev
++)
2370 prev
->from
= this_from
;
2375 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2377 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2388 if (out
->allocated
< out
->used
+ len
)
2390 font
->get_metrics (font
, in
, from
, to
);
2391 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2392 sizeof (MFLTGlyph
) * len
);
2397 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2399 static MFLTGlyphString gstring
;
2401 static bool m17n_flt_initialized
;
2404 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2405 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2407 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2409 struct MFLTFontFT flt_font_ft
;
2411 bool with_variation_selector
= 0;
2413 if (! m17n_flt_initialized
)
2416 #ifdef M17N_FLT_USE_NEW_FEATURE
2417 mflt_enable_new_feature
= 1;
2418 mflt_try_otf
= ftfont_try_otf
;
2419 #endif /* M17N_FLT_USE_NEW_FEATURE */
2420 m17n_flt_initialized
= 1;
2423 for (i
= 0; i
< len
; i
++)
2425 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2430 c
= LGLYPH_CHAR (g
);
2431 if (CHAR_VARIATION_SELECTOR_P (c
))
2432 with_variation_selector
= 1;
2437 if (with_variation_selector
)
2439 setup_otf_gstring (len
);
2440 for (i
= 0; i
< len
; i
++)
2442 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2444 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2445 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2446 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2448 OTF_drive_cmap (otf
, &otf_gstring
);
2449 for (i
= 0; i
< otf_gstring
.used
; i
++)
2451 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2452 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2453 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2455 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2456 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2457 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2459 if (len
> otf_gstring
.used
)
2461 len
= otf_gstring
.used
;
2462 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2466 if (INT_MAX
/ 2 < len
)
2467 memory_full (SIZE_MAX
);
2469 if (gstring
.allocated
== 0)
2471 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2472 gstring
.glyphs
= xnmalloc (len
* 2, sizeof *gstring
.glyphs
);
2473 gstring
.allocated
= len
* 2;
2475 else if (gstring
.allocated
< len
* 2)
2477 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2478 sizeof *gstring
.glyphs
);
2479 gstring
.allocated
= len
* 2;
2481 memset (gstring
.glyphs
, 0, len
* sizeof *gstring
.glyphs
);
2482 for (i
= 0; i
< len
; i
++)
2484 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2486 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2487 if (with_variation_selector
)
2489 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2490 gstring
.glyphs
[i
].encoded
= 1;
2498 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2501 flt_font_ft
.flt_font
.family
= Mnil
;
2503 flt_font_ft
.flt_font
.family
2504 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2506 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2507 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2508 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2509 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2510 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2511 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2512 flt_font_ft
.flt_font
.internal
= NULL
;
2513 flt_font_ft
.font
= font
;
2514 flt_font_ft
.ft_face
= ft_face
;
2515 flt_font_ft
.otf
= otf
;
2516 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2518 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2519 /* A little bit ad hoc. Perhaps, shaper must get script and
2520 language information, and select a proper flt for them
2522 flt
= mflt_get (msymbol ("combining"));
2523 for (i
= 0; i
< 3; i
++)
2525 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2528 if (INT_MAX
/ 2 < gstring
.allocated
)
2529 memory_full (SIZE_MAX
);
2530 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2531 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2532 gstring
.allocated
*= 2;
2534 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2536 for (i
= 0; i
< gstring
.used
; i
++)
2538 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2540 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2541 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2544 for (i
= 0; i
< gstring
.used
; i
++)
2546 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2547 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2551 lglyph
= LGLYPH_NEW ();
2552 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2554 LGLYPH_SET_FROM (lglyph
, g
->from
);
2555 LGLYPH_SET_TO (lglyph
, g
->to
);
2556 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2557 LGLYPH_SET_CODE (lglyph
, g
->code
);
2558 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2559 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2560 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2561 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2562 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2565 Lisp_Object vec
= make_uninit_vector (3);
2567 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2568 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2569 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2570 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2573 return make_number (i
);
2577 ftfont_shape (Lisp_Object lgstring
)
2580 struct ftfont_info
*ftfont_info
;
2583 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2584 ftfont_info
= (struct ftfont_info
*) font
;
2585 otf
= ftfont_get_otf (ftfont_info
);
2587 return make_number (0);
2588 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2589 &ftfont_info
->matrix
);
2592 #endif /* HAVE_M17N_FLT */
2594 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2597 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2599 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2600 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2604 return OTF_get_variation_glyphs (otf
, c
, variations
);
2607 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2608 #endif /* HAVE_LIBOTF */
2610 static const char *const ftfont_booleans
[] = {
2623 static const char *const ftfont_non_booleans
[] = {
2655 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2657 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2662 syms_of_ftfont (void)
2664 /* Symbolic type of this font-driver. */
2665 DEFSYM (Qfreetype
, "freetype");
2667 /* Fontconfig's generic families and their aliases. */
2668 DEFSYM (Qmonospace
, "monospace");
2669 DEFSYM (Qsans_serif
, "sans-serif");
2670 DEFSYM (Qserif
, "serif");
2671 DEFSYM (Qmono
, "mono");
2672 DEFSYM (Qsans
, "sans");
2673 DEFSYM (Qsans__serif
, "sans serif");
2675 staticpro (&freetype_font_cache
);
2676 freetype_font_cache
= list1 (Qt
);
2678 staticpro (&ftfont_generic_family_list
);
2679 ftfont_generic_family_list
= list3 (Fcons (Qmonospace
, Qt
),
2680 Fcons (Qsans_serif
, Qt
),
2683 staticpro (&ft_face_cache
);
2684 ft_face_cache
= Qnil
;
2686 ftfont_driver
.type
= Qfreetype
;
2687 register_font_driver (&ftfont_driver
, NULL
);