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
))
378 ft_face_cache
= CALLN (Fmake_hash_table
, QCtest
, Qequal
);
379 cache_data
= xmalloc (sizeof *cache_data
);
380 cache_data
->ft_face
= NULL
;
381 cache_data
->fc_charset
= NULL
;
382 val
= make_save_ptr_int (cache_data
, 0);
383 cache
= Fcons (Qnil
, val
);
384 Fputhash (key
, cache
, ft_face_cache
);
389 cache_data
= XSAVE_POINTER (val
, 0);
392 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
395 if (cache_for
== FTFONT_CACHE_FOR_FACE
396 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
398 char *filename
= SSDATA (XCAR (key
));
399 int idx
= XINT (XCDR (key
));
401 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
404 && FT_Init_FreeType (&ft_library
) != 0)
406 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
412 FcPattern
*pat
= NULL
;
413 FcFontSet
*fontset
= NULL
;
414 FcObjectSet
*objset
= NULL
;
415 FcCharSet
*charset
= NULL
;
417 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
418 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
421 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
424 fontset
= FcFontList (NULL
, pat
, objset
);
427 if (fontset
&& fontset
->nfont
> 0
428 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
431 cache_data
->fc_charset
= FcCharSetCopy (charset
);
433 cache_data
->fc_charset
= FcCharSetCreate ();
437 FcFontSetDestroy (fontset
);
439 FcObjectSetDestroy (objset
);
441 FcPatternDestroy (pat
);
448 ftfont_get_fc_charset (Lisp_Object entity
)
450 Lisp_Object val
, cache
;
451 struct ftfont_cache_data
*cache_data
;
453 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
455 cache_data
= XSAVE_POINTER (val
, 0);
456 return cache_data
->fc_charset
;
461 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
465 if (ftfont_info
->otf
)
466 return ftfont_info
->otf
;
467 if (! ftfont_info
->maybe_otf
)
469 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
470 if (! otf
|| OTF_get_table (otf
, "head") < 0)
474 ftfont_info
->maybe_otf
= 0;
477 ftfont_info
->otf
= otf
;
480 #endif /* HAVE_LIBOTF */
482 static Lisp_Object
ftfont_get_cache (struct frame
*);
483 static Lisp_Object
ftfont_list (struct frame
*, Lisp_Object
);
484 static Lisp_Object
ftfont_match (struct frame
*, Lisp_Object
);
485 static Lisp_Object
ftfont_list_family (struct frame
*);
486 static Lisp_Object
ftfont_open (struct frame
*, Lisp_Object
, int);
487 static void ftfont_close (struct font
*);
488 static int ftfont_has_char (Lisp_Object
, int);
489 static unsigned ftfont_encode_char (struct font
*, int);
490 static void ftfont_text_extents (struct font
*, unsigned *, int,
491 struct font_metrics
*);
492 static int ftfont_get_bitmap (struct font
*, unsigned,
493 struct font_bitmap
*, int);
494 static int ftfont_anchor_point (struct font
*, unsigned, int,
497 static Lisp_Object
ftfont_otf_capability (struct font
*);
498 # ifdef HAVE_M17N_FLT
499 static Lisp_Object
ftfont_shape (Lisp_Object
);
503 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
504 static int ftfont_variation_glyphs (struct font
*, int c
,
505 unsigned variations
[256]);
506 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
508 struct font_driver ftfont_driver
=
510 LISP_INITIALLY_ZERO
, /* Qfreetype */
511 0, /* case insensitive */
516 NULL
, /* free_entity */
519 /* We can't draw a text without device dependent functions. */
520 NULL
, /* prepare_face */
521 NULL
, /* done_face */
525 /* We can't draw a text without device dependent functions. */
528 NULL
, /* free_bitmap */
531 ftfont_otf_capability
,
532 #else /* not HAVE_LIBOTF */
534 #endif /* not HAVE_LIBOTF */
535 NULL
, /* otf_drive */
536 NULL
, /* start_for_frame */
537 NULL
, /* end_for_frame */
538 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
540 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
542 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
545 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
546 ftfont_variation_glyphs
,
551 ftfont_filter_properties
, /* filter_properties */
555 ftfont_get_cache (struct frame
*f
)
557 return freetype_font_cache
;
561 ftfont_get_charset (Lisp_Object registry
)
563 char *str
= SSDATA (SYMBOL_NAME (registry
));
565 char *re
= SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
569 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
573 else if (str
[i
] == '*')
580 regexp
= make_unibyte_string (re
, j
);
582 for (i
= 0; fc_charset_table
[i
].name
; i
++)
583 if (fast_c_string_match_ignore_case
584 (regexp
, fc_charset_table
[i
].name
,
585 strlen (fc_charset_table
[i
].name
)) >= 0)
587 if (! fc_charset_table
[i
].name
)
589 if (! fc_charset_table
[i
].fc_charset
)
591 FcCharSet
*charset
= FcCharSetCreate ();
592 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
596 for (j
= 0; uniquifier
[j
]; j
++)
597 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
599 FcCharSetDestroy (charset
);
602 fc_charset_table
[i
].fc_charset
= charset
;
610 unsigned int script_tag
, langsys_tag
;
612 unsigned int *features
[2];
615 #define OTF_SYM_TAG(SYM, TAG) \
617 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
618 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
621 #define OTF_TAG_STR(TAG, P) \
623 (P)[0] = (char) (TAG >> 24); \
624 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
625 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
626 (P)[3] = (char) (TAG & 0xFF); \
631 #define OTF_TAG_SYM(SYM, TAG) \
635 OTF_TAG_STR (TAG, str); \
636 (SYM) = font_intern_prop (str, 4, 1); \
641 static struct OpenTypeSpec
*
642 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
644 struct OpenTypeSpec
*spec
= malloc (sizeof *spec
);
651 spec
->script
= XCAR (otf_spec
);
652 if (! NILP (spec
->script
))
654 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
655 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
656 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
657 spec
->script
= XCDR (val
);
662 spec
->script_tag
= 0x44464C54; /* "DFLT" */
663 otf_spec
= XCDR (otf_spec
);
664 spec
->langsys_tag
= 0;
665 if (! NILP (otf_spec
))
667 val
= XCAR (otf_spec
);
669 OTF_SYM_TAG (val
, spec
->langsys_tag
);
670 otf_spec
= XCDR (otf_spec
);
672 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
673 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
677 val
= XCAR (otf_spec
);
682 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
684 : malloc (XINT (len
) * sizeof *spec
->features
[i
]));
685 if (! spec
->features
[i
])
687 if (i
> 0 && spec
->features
[0])
688 free (spec
->features
[0]);
692 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
694 if (NILP (XCAR (val
)))
700 OTF_SYM_TAG (XCAR (val
), tag
);
701 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
704 spec
->nfeatures
[i
] = j
;
710 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
712 Lisp_Object tmp
, extra
;
713 FcPattern
*pattern
= NULL
;
714 FcCharSet
*charset
= NULL
;
715 FcLangSet
*langset
= NULL
;
719 Lisp_Object script
= Qnil
;
720 Lisp_Object registry
;
723 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
725 /* Fontconfig doesn't support reverse-italic/oblique. */
728 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
729 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
730 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
731 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
734 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
736 || EQ (registry
, Qascii_0
)
737 || EQ (registry
, Qiso10646_1
)
738 || EQ (registry
, Qunicode_bmp
))
744 fc_charset_idx
= ftfont_get_charset (registry
);
745 if (fc_charset_idx
< 0)
747 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
748 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
749 lang
= (FcChar8
*) *langname
;
752 langset
= FcLangSetCreate ();
755 FcLangSetAdd (langset
, lang
);
760 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
761 CONSP (extra
); extra
= XCDR (extra
))
763 Lisp_Object key
, val
;
765 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
771 else if (EQ (key
, QClang
))
774 langset
= FcLangSetCreate ();
779 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
783 for (; CONSP (val
); val
= XCDR (val
))
784 if (SYMBOLP (XCAR (val
))
785 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
788 else if (EQ (key
, QCotf
))
792 *otspec
= ftfont_get_open_type_spec (val
);
795 strcpy (otlayout
, "otlayout:");
796 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
797 script
= (*otspec
)->script
;
800 else if (EQ (key
, QCscript
))
802 else if (EQ (key
, QCscalable
))
803 scalable
= ! NILP (val
);
806 if (! NILP (script
) && ! charset
)
808 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
810 if (CONSP (chars
) && CONSP (CDR (chars
)))
812 charset
= FcCharSetCreate ();
815 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
816 if (CHARACTERP (XCAR (chars
))
817 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
822 pattern
= FcPatternCreate ();
825 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
827 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
829 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
831 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
834 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
837 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
840 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
843 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
849 /* We come here because of unexpected error in fontconfig API call
850 (usually insufficient memory). */
853 FcPatternDestroy (pattern
);
858 if ((*otspec
)->nfeatures
[0] > 0)
859 free ((*otspec
)->features
[0]);
860 if ((*otspec
)->nfeatures
[1] > 0)
861 free ((*otspec
)->features
[1]);
867 if (langset
) FcLangSetDestroy (langset
);
868 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
873 ftfont_list (struct frame
*f
, Lisp_Object spec
)
875 Lisp_Object val
= Qnil
, family
, adstyle
;
878 FcFontSet
*fontset
= NULL
;
879 FcObjectSet
*objset
= NULL
;
881 Lisp_Object chars
= Qnil
;
882 char otlayout
[15]; /* For "otlayout:XXXX" */
883 struct OpenTypeSpec
*otspec
= NULL
;
885 const char *langname
= NULL
;
887 if (! fc_initialized
)
893 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
896 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
898 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
901 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
902 if (CONSP (val
) && VECTORP (XCDR (val
)))
907 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
908 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
909 family
= AREF (spec
, FONT_FAMILY_INDEX
);
912 Lisp_Object resolved
;
914 resolved
= ftfont_resolve_generic_family (family
, pattern
);
915 if (! NILP (resolved
))
917 FcPatternDel (pattern
, FC_FAMILY
);
918 if (! FcPatternAddString (pattern
, FC_FAMILY
,
919 SYMBOL_FcChar8 (resolved
)))
923 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
924 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
926 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
927 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
928 FC_STYLE
, FC_FILE
, FC_INDEX
,
931 #endif /* FC_CAPABILITY */
939 FcObjectSetAdd (objset
, FC_CHARSET
);
941 fontset
= FcFontList (NULL
, pattern
, objset
);
942 if (! fontset
|| fontset
->nfont
== 0)
945 /* Need fix because this finds any fonts. */
946 if (fontset
->nfont
== 0 && ! NILP (family
))
948 /* Try matching with configuration. For instance, the
949 configuration may specify "Nimbus Mono L" as an alias of
951 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
952 SYMBOL_FcChar8 (family
), NULL
);
955 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
958 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
961 FcPatternDel (pattern
, FC_FAMILY
);
962 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
963 FcFontSetDestroy (fontset
);
964 fontset
= FcFontList (NULL
, pattern
, objset
);
965 if (fontset
&& fontset
->nfont
> 0)
971 for (i
= 0; i
< fontset
->nfont
; i
++)
979 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
990 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
992 || ! strstr ((char *) this, otlayout
))
995 #endif /* FC_CAPABILITY */
1003 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1006 otf
= OTF_open ((char *) file
);
1009 passed
= (OTF_check_features (otf
, 1, otspec
->script_tag
,
1010 otspec
->langsys_tag
,
1011 otspec
->features
[0],
1012 otspec
->nfeatures
[0]) == 1
1013 && OTF_check_features (otf
, 0, otspec
->script_tag
,
1014 otspec
->langsys_tag
,
1015 otspec
->features
[1],
1016 otspec
->nfeatures
[1]) == 1);
1021 #endif /* HAVE_LIBOTF */
1022 if (VECTORP (chars
))
1026 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1029 for (j
= 0; j
< ASIZE (chars
); j
++)
1030 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1031 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1033 if (j
== ASIZE (chars
))
1036 if (! NILP (adstyle
) || langname
)
1038 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1040 if (! NILP (adstyle
)
1041 && (NILP (this_adstyle
)
1042 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1043 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1046 && ! NILP (this_adstyle
)
1047 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1050 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1051 AREF (spec
, FONT_EXTRA_INDEX
));
1052 if (! NILP (entity
))
1053 val
= Fcons (entity
, val
);
1055 val
= Fnreverse (val
);
1059 /* We come here because of unexpected error in fontconfig API call
1060 (usually insufficient memory). */
1064 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1065 if (objset
) FcObjectSetDestroy (objset
);
1066 if (fontset
) FcFontSetDestroy (fontset
);
1067 if (pattern
) FcPatternDestroy (pattern
);
1072 ftfont_match (struct frame
*f
, Lisp_Object spec
)
1074 Lisp_Object entity
= Qnil
;
1075 FcPattern
*pattern
, *match
= NULL
;
1077 char otlayout
[15]; /* For "otlayout:XXXX" */
1078 struct OpenTypeSpec
*otspec
= NULL
;
1079 const char *langname
= NULL
;
1081 if (! fc_initialized
)
1087 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1091 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1095 value
.type
= FcTypeDouble
;
1096 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1097 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1099 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1101 FcDefaultSubstitute (pattern
);
1102 match
= FcFontMatch (NULL
, pattern
, &result
);
1105 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1106 FcPatternDestroy (match
);
1107 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1108 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1109 ftfont_generic_family_list
))
1110 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1111 AREF (entity
, FONT_FAMILY_INDEX
))))
1115 FcPatternDestroy (pattern
);
1117 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1122 ftfont_list_family (struct frame
*f
)
1124 Lisp_Object list
= Qnil
;
1125 FcPattern
*pattern
= NULL
;
1126 FcFontSet
*fontset
= NULL
;
1127 FcObjectSet
*objset
= NULL
;
1130 if (! fc_initialized
)
1136 pattern
= FcPatternCreate ();
1139 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1142 fontset
= FcFontList (NULL
, pattern
, objset
);
1146 for (i
= 0; i
< fontset
->nfont
; i
++)
1148 FcPattern
*pat
= fontset
->fonts
[i
];
1151 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1152 list
= Fcons (intern ((char *) str
), list
);
1156 if (objset
) FcObjectSetDestroy (objset
);
1157 if (fontset
) FcFontSetDestroy (fontset
);
1158 if (pattern
) FcPatternDestroy (pattern
);
1165 ftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
1167 struct ftfont_info
*ftfont_info
;
1169 struct ftfont_cache_data
*cache_data
;
1173 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1179 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1183 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1186 filename
= XCAR (val
);
1189 cache_data
= XSAVE_POINTER (XCDR (cache
), 0);
1190 ft_face
= cache_data
->ft_face
;
1191 if (XSAVE_INTEGER (val
, 1) > 0)
1193 /* FT_Face in this cache is already used by the different size. */
1194 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1196 if (FT_Activate_Size (ft_size
) != 0)
1198 FT_Done_Size (ft_size
);
1202 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) + 1);
1203 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1206 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1208 if (XSAVE_INTEGER (val
, 1) == 0)
1209 FT_Done_Face (ft_face
);
1213 font_object
= font_build_object (VECSIZE (struct ftfont_info
),
1214 Qfreetype
, entity
, size
);
1215 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1216 font
= XFONT_OBJECT (font_object
);
1217 ftfont_info
= (struct ftfont_info
*) font
;
1218 ftfont_info
->ft_size
= ft_face
->size
;
1219 ftfont_info
->index
= XINT (idx
);
1221 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1222 ftfont_info
->otf
= NULL
;
1223 #endif /* HAVE_LIBOTF */
1224 /* This means that there's no need of transformation. */
1225 ftfont_info
->matrix
.xx
= 0;
1226 font
->pixel_size
= size
;
1227 font
->driver
= &ftfont_driver
;
1228 font
->encoding_charset
= font
->repertory_charset
= -1;
1230 upEM
= ft_face
->units_per_EM
;
1231 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1232 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1235 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1236 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1237 font
->height
= ft_face
->height
* size
/ upEM
;
1241 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1242 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1243 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1245 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1246 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1248 spacing
= FC_PROPORTIONAL
;
1249 if (spacing
!= FC_PROPORTIONAL
1251 && spacing
!= FC_DUAL
1252 #endif /* FC_DUAL */
1254 font
->min_width
= font
->average_width
= font
->space_width
1255 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1256 : ft_face
->size
->metrics
.max_advance
>> 6);
1261 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1262 for (i
= 32, n
= 0; i
< 127; i
++)
1263 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1265 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1268 && (! font
->min_width
|| font
->min_width
> this_width
))
1269 font
->min_width
= this_width
;
1271 font
->space_width
= this_width
;
1272 font
->average_width
+= this_width
;
1276 font
->average_width
/= n
;
1279 font
->baseline_offset
= 0;
1280 font
->relative_compose
= 0;
1281 font
->default_ascent
= 0;
1282 font
->vertical_centering
= 0;
1285 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1286 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1290 font
->underline_position
= -1;
1291 font
->underline_thickness
= 0;
1298 ftfont_close (struct font
*font
)
1300 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1301 Lisp_Object val
, cache
;
1303 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1304 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1305 eassert (CONSP (cache
));
1307 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) - 1);
1308 if (XSAVE_INTEGER (val
, 1) == 0)
1310 struct ftfont_cache_data
*cache_data
= XSAVE_POINTER (val
, 0);
1312 FT_Done_Face (cache_data
->ft_face
);
1314 if (ftfont_info
->otf
)
1315 OTF_close (ftfont_info
->otf
);
1317 cache_data
->ft_face
= NULL
;
1320 FT_Done_Size (ftfont_info
->ft_size
);
1324 ftfont_has_char (Lisp_Object font
, int c
)
1326 struct charset
*cs
= NULL
;
1328 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1329 && charset_jisx0208
>= 0)
1330 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1331 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1332 && charset_ksc5601
>= 0)
1333 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1335 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1337 if (FONT_ENTITY_P (font
))
1339 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1341 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1345 struct ftfont_info
*ftfont_info
;
1347 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1348 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1354 ftfont_encode_char (struct font
*font
, int c
)
1356 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1357 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1358 FT_ULong charcode
= c
;
1359 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1361 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1365 ftfont_text_extents (struct font
*font
, unsigned int *code
,
1366 int nglyphs
, struct font_metrics
*metrics
)
1368 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1369 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1373 if (ftfont_info
->ft_size
!= ft_face
->size
)
1374 FT_Activate_Size (ftfont_info
->ft_size
);
1376 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1378 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1380 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1384 metrics
->lbearing
= m
->horiBearingX
>> 6;
1385 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1386 metrics
->ascent
= m
->horiBearingY
>> 6;
1387 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1390 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1391 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1392 if (metrics
->rbearing
1393 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1395 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1396 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1397 metrics
->ascent
= m
->horiBearingY
>> 6;
1398 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1399 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1400 width
+= m
->horiAdvance
>> 6;
1403 width
+= font
->space_width
;
1405 metrics
->width
= width
;
1409 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1411 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1412 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1413 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1415 if (ftfont_info
->ft_size
!= ft_face
->size
)
1416 FT_Activate_Size (ftfont_info
->ft_size
);
1417 if (bits_per_pixel
== 1)
1419 #ifdef FT_LOAD_TARGET_MONO
1420 load_flags
|= FT_LOAD_TARGET_MONO
;
1422 load_flags
|= FT_LOAD_MONOCHROME
;
1425 else if (bits_per_pixel
!= 8)
1426 /* We don't support such a rendering. */
1429 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1431 bitmap
->bits_per_pixel
1432 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1433 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1434 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1435 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1437 if (bitmap
->bits_per_pixel
< 0)
1438 /* We don't support that kind of pixel mode. */
1440 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1441 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1442 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1443 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1444 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1445 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1446 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1452 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1455 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1456 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1458 if (ftfont_info
->ft_size
!= ft_face
->size
)
1459 FT_Activate_Size (ftfont_info
->ft_size
);
1460 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1462 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1464 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1466 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1467 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1474 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1476 Lisp_Object scripts
, langsyses
, features
, sym
;
1479 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1481 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1483 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1485 OTF_LangSys
*otf_langsys
;
1488 otf_langsys
= otf_script
->LangSys
+ j
;
1489 else if (otf_script
->DefaultLangSysOffset
)
1490 otf_langsys
= &otf_script
->DefaultLangSys
;
1494 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1496 l
= otf_langsys
->FeatureIndex
[k
];
1497 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1499 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1500 features
= Fcons (sym
, features
);
1503 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1506 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1509 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1510 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1518 ftfont_otf_capability (struct font
*font
)
1520 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1521 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1522 Lisp_Object gsub_gpos
;
1526 gsub_gpos
= Fcons (Qnil
, Qnil
);
1527 if (OTF_get_table (otf
, "GSUB") == 0
1528 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1529 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1530 if (OTF_get_table (otf
, "GPOS") == 0
1531 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1532 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1536 #ifdef HAVE_M17N_FLT
1538 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1539 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1540 /* We can use the new feature of libotf and m17n-flt to handle the
1541 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1542 some Agian scripts. */
1543 #define M17N_FLT_USE_NEW_FEATURE
1556 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1559 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1560 FT_Face ft_face
= flt_font_ft
->ft_face
;
1563 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1566 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1568 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1574 /* Operators for 26.6 fixed fractional pixel format */
1576 #define FLOOR(x) ((x) & -64)
1577 #define CEIL(x) (((x)+63) & -64)
1578 #define ROUND(x) (((x)+32) & -64)
1581 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1584 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1585 FT_Face ft_face
= flt_font_ft
->ft_face
;
1588 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1591 if (g
->code
!= FONT_INVALID_CODE
)
1593 FT_Glyph_Metrics
*m
;
1595 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1597 m
= &ft_face
->glyph
->metrics
;
1598 if (flt_font_ft
->matrix
)
1603 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1604 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1605 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1606 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1607 for (i
= 0; i
< 4; i
++)
1608 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1609 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1610 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1611 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1612 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1616 g
->lbearing
= FLOOR (m
->horiBearingX
);
1617 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1618 g
->ascent
= CEIL (m
->horiBearingY
);
1619 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1621 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1626 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1627 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1628 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1637 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1639 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1641 #define FEATURE_ANY(IDX) \
1642 (spec->features[IDX] \
1643 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1645 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1646 OTF
*otf
= flt_font_ft
->otf
;
1651 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1652 /* Return true iff any of GSUB or GPOS support the script (and
1655 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1657 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1660 for (i
= 0; i
< 2; i
++)
1661 if (! FEATURE_ANY (i
))
1663 if (FEATURE_NONE (i
))
1666 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1671 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1674 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1680 for (n
= 1; spec
->features
[i
][n
]; n
++);
1682 SAFE_NALLOCA (tags
, 1, n
);
1683 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1685 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1688 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1690 tags
[n
] = spec
->features
[i
][n
];
1693 #ifndef M17N_FLT_USE_NEW_FEATURE
1694 passed
= n
- negative
> 0;
1697 passed
= (OTF_check_features (otf
, i
== 0, spec
->script
,
1698 spec
->langsys
, tags
, n
- negative
)
1709 #define DEVICE_DELTA(table, size) \
1710 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1711 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1715 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1716 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1718 if (anchor
->AnchorFormat
== 2)
1720 FT_Outline
*outline
;
1721 int ap
= anchor
->f
.f1
.AnchorPoint
;
1723 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1724 outline
= &ft_face
->glyph
->outline
;
1725 if (ap
< outline
->n_points
)
1727 *x
= outline
->points
[ap
].x
<< 6;
1728 *y
= outline
->points
[ap
].y
<< 6;
1731 else if (anchor
->AnchorFormat
== 3)
1733 if (anchor
->f
.f2
.XDeviceTable
.offset
1734 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1735 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1736 if (anchor
->f
.f2
.YDeviceTable
.offset
1737 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1738 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1742 static OTF_GlyphString otf_gstring
;
1745 setup_otf_gstring (int size
)
1747 if (otf_gstring
.size
< size
)
1749 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1750 size
, sizeof (OTF_Glyph
));
1751 otf_gstring
.size
= size
;
1753 otf_gstring
.used
= size
;
1754 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1757 #ifdef M17N_FLT_USE_NEW_FEATURE
1759 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1760 #define PACK_OTF_TAG(TAG) \
1761 ((((TAG) & 0x7F000000) >> 3) \
1762 | (((TAG) & 0x7F0000) >> 2) \
1763 | (((TAG) & 0x7F00) >> 1) \
1766 /* Assuming that FONT is an OpenType font, apply OpenType features
1767 specified in SPEC on glyphs between FROM and TO of IN, and record
1768 the lastly applied feature in each glyph of IN. If OUT is not
1769 NULL, append the resulting glyphs to OUT while storing glyph
1770 position adjustment information in ADJUSTMENT. */
1773 ftfont_drive_otf (MFLTFont
*font
,
1775 MFLTGlyphString
*in
,
1778 MFLTGlyphString
*out
,
1779 MFLTGlyphAdjustment
*adjustment
)
1781 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1782 FT_Face ft_face
= flt_font_ft
->ft_face
;
1783 OTF
*otf
= flt_font_ft
->otf
;
1784 int len
= to
- from
;
1787 char script
[5], *langsys
= NULL
;
1788 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1789 OTF_Feature
*features
;
1793 OTF_tag_name (spec
->script
, script
);
1798 langsys
= langsysbuf
;
1799 OTF_tag_name (spec
->langsys
, langsys
);
1803 for (i
= 0; i
< 2; i
++)
1807 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1809 for (j
= 0; spec
->features
[i
][j
]; j
++);
1810 SAFE_NALLOCA (p
, 6, j
);
1815 for (j
= 0; spec
->features
[i
][j
]; j
++)
1817 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1818 *p
++ = '*', *p
++ = ',';
1821 OTF_tag_name (spec
->features
[i
][j
], p
);
1830 setup_otf_gstring (len
);
1831 for (i
= 0; i
< len
; i
++)
1833 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
& 0x11FFFF;
1834 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1837 OTF_drive_gdef (otf
, &otf_gstring
);
1838 gidx
= out
? out
->used
: from
;
1840 if (gsub_features
&& out
)
1842 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1845 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1850 features
= otf
->gsub
->FeatureList
.Feature
;
1851 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1854 int min_from
, max_to
;
1855 int feature_idx
= otfg
->positioning_type
>> 4;
1857 g
= out
->glyphs
+ out
->used
;
1858 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1859 if (g
->code
!= otfg
->glyph_id
)
1862 g
->code
= otfg
->glyph_id
;
1868 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1870 /* OTFG substitutes multiple glyphs in IN. */
1871 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1872 j
<= from
+ otfg
->f
.index
.to
; j
++)
1874 if (min_from
> in
->glyphs
[j
].from
)
1875 min_from
= in
->glyphs
[j
].from
;
1876 if (max_to
< in
->glyphs
[j
].to
)
1877 max_to
= in
->glyphs
[j
].to
;
1884 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1885 tag
= PACK_OTF_TAG (tag
);
1886 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1888 for (i
++, otfg
++; (i
< otf_gstring
.used
1889 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1892 g
= out
->glyphs
+ out
->used
;
1893 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1894 if (g
->code
!= otfg
->glyph_id
)
1897 g
->code
= otfg
->glyph_id
;
1900 feature_idx
= otfg
->positioning_type
>> 4;
1903 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1904 tag
= PACK_OTF_TAG (tag
);
1905 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1911 else if (gsub_features
)
1913 /* Just for checking which features will be applied. */
1914 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1917 features
= otf
->gsub
->FeatureList
.Feature
;
1918 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1921 int feature_idx
= otfg
->positioning_type
>> 4;
1925 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1926 tag
= PACK_OTF_TAG (tag
);
1927 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1929 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1930 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1937 if (out
->allocated
< out
->used
+ len
)
1942 for (i
= 0; i
< len
; i
++)
1943 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1946 if (gpos_features
&& out
)
1948 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1949 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1951 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1957 features
= otf
->gpos
->FeatureList
.Feature
;
1958 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1959 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1960 x_scale
= ft_face
->size
->metrics
.x_scale
;
1961 y_scale
= ft_face
->size
->metrics
.y_scale
;
1963 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1964 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1967 int feature_idx
= otfg
->positioning_type
>> 4;
1971 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1972 tag
= PACK_OTF_TAG (tag
);
1973 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1976 if (! otfg
->glyph_id
)
1978 switch (otfg
->positioning_type
& 0xF)
1982 case 1: /* Single */
1985 int format
= otfg
->f
.f1
.format
;
1987 if (format
& OTF_XPlacement
)
1989 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1990 if (format
& OTF_XPlaDevice
)
1992 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1993 if (format
& OTF_YPlacement
)
1995 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
1996 if (format
& OTF_YPlaDevice
)
1998 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
1999 if (format
& OTF_XAdvance
)
2001 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2002 if (format
& OTF_XAdvDevice
)
2004 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2005 if (format
& OTF_YAdvance
)
2007 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2008 if (format
& OTF_YAdvDevice
)
2010 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2011 adjustment
[i
].set
= 1;
2014 case 3: /* Cursive */
2015 /* Not yet supported. */
2017 case 4: /* Mark-to-Base */
2018 case 5: /* Mark-to-Ligature */
2022 goto label_adjust_anchor
;
2023 default: /* i.e. case 6 Mark-to-Mark */
2028 label_adjust_anchor
:
2030 int base_x
, base_y
, mark_x
, mark_y
;
2031 int this_from
, this_to
;
2033 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2034 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2035 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2036 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2038 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2039 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2040 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2041 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2042 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2043 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2044 adjustment
[i
].xoff
= (base_x
- mark_x
);
2045 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2046 adjustment
[i
].back
= (g
- prev
);
2047 adjustment
[i
].xadv
= 0;
2048 adjustment
[i
].advance_is_absolute
= 1;
2049 adjustment
[i
].set
= 1;
2050 this_from
= g
->from
;
2052 for (j
= 0; prev
+ j
< g
; j
++)
2054 if (this_from
> prev
[j
].from
)
2055 this_from
= prev
[j
].from
;
2056 if (this_to
< prev
[j
].to
)
2057 this_to
= prev
[j
].to
;
2059 for (; prev
<= g
; prev
++)
2061 prev
->from
= this_from
;
2066 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2068 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2074 else if (gpos_features
)
2076 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2082 features
= otf
->gpos
->FeatureList
.Feature
;
2083 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2085 if (otfg
->positioning_type
& 0xF)
2087 int feature_idx
= otfg
->positioning_type
>> 4;
2091 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2092 tag
= PACK_OTF_TAG (tag
);
2093 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2095 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2096 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2108 if (out
->allocated
< out
->used
+ len
)
2110 font
->get_metrics (font
, in
, from
, to
);
2111 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2112 sizeof (MFLTGlyph
) * len
);
2118 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2119 MFLTGlyphString
*in
, int from
, int to
)
2121 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2124 #else /* not M17N_FLT_USE_NEW_FEATURE */
2127 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2129 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2131 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2132 FT_Face ft_face
= flt_font_ft
->ft_face
;
2133 OTF
*otf
= flt_font_ft
->otf
;
2134 int len
= to
- from
;
2137 char script
[5], *langsys
= NULL
;
2138 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2142 OTF_tag_name (spec
->script
, script
);
2147 langsys
= langsysbuf
;
2148 OTF_tag_name (spec
->langsys
, langsys
);
2152 for (i
= 0; i
< 2; i
++)
2156 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2158 for (j
= 0; spec
->features
[i
][j
]; j
++);
2159 SAFE_NALLOCA (p
, 6, j
);
2164 for (j
= 0; spec
->features
[i
][j
]; j
++)
2166 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2167 *p
++ = '*', *p
++ = ',';
2170 OTF_tag_name (spec
->features
[i
][j
], p
);
2179 setup_otf_gstring (len
);
2180 for (i
= 0; i
< len
; i
++)
2182 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2183 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2186 OTF_drive_gdef (otf
, &otf_gstring
);
2191 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2194 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2199 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2202 int min_from
, max_to
;
2205 g
= out
->glyphs
+ out
->used
;
2206 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2207 if (g
->code
!= otfg
->glyph_id
)
2210 g
->code
= otfg
->glyph_id
;
2216 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2218 /* OTFG substitutes multiple glyphs in IN. */
2219 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2220 j
<= from
+ otfg
->f
.index
.to
; j
++)
2222 if (min_from
> in
->glyphs
[j
].from
)
2223 min_from
= in
->glyphs
[j
].from
;
2224 if (max_to
< in
->glyphs
[j
].to
)
2225 max_to
= in
->glyphs
[j
].to
;
2230 for (i
++, otfg
++; (i
< otf_gstring
.used
2231 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2234 g
= out
->glyphs
+ out
->used
;
2235 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2236 if (g
->code
!= otfg
->glyph_id
)
2239 g
->code
= otfg
->glyph_id
;
2248 if (out
->allocated
< out
->used
+ len
)
2253 for (i
= 0; i
< len
; i
++)
2254 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2259 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2260 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2262 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2269 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2270 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2271 x_scale
= ft_face
->size
->metrics
.x_scale
;
2272 y_scale
= ft_face
->size
->metrics
.y_scale
;
2274 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2275 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2279 if (! otfg
->glyph_id
)
2281 switch (otfg
->positioning_type
)
2285 case 1: /* Single */
2288 int format
= otfg
->f
.f1
.format
;
2290 if (format
& OTF_XPlacement
)
2292 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2293 if (format
& OTF_XPlaDevice
)
2295 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2296 if (format
& OTF_YPlacement
)
2298 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2299 if (format
& OTF_YPlaDevice
)
2301 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2302 if (format
& OTF_XAdvance
)
2304 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2305 if (format
& OTF_XAdvDevice
)
2307 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2308 if (format
& OTF_YAdvance
)
2310 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2311 if (format
& OTF_YAdvDevice
)
2313 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2314 adjustment
[i
].set
= 1;
2317 case 3: /* Cursive */
2318 /* Not yet supported. */
2320 case 4: /* Mark-to-Base */
2321 case 5: /* Mark-to-Ligature */
2325 goto label_adjust_anchor
;
2326 default: /* i.e. case 6 Mark-to-Mark */
2331 label_adjust_anchor
:
2333 int base_x
, base_y
, mark_x
, mark_y
;
2334 int this_from
, this_to
;
2336 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2337 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2338 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2339 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2341 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2342 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2343 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2344 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2345 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2346 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2347 adjustment
[i
].xoff
= (base_x
- mark_x
);
2348 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2349 adjustment
[i
].back
= (g
- prev
);
2350 adjustment
[i
].xadv
= 0;
2351 adjustment
[i
].advance_is_absolute
= 1;
2352 adjustment
[i
].set
= 1;
2353 this_from
= g
->from
;
2355 for (j
= 0; prev
+ j
< g
; j
++)
2357 if (this_from
> prev
[j
].from
)
2358 this_from
= prev
[j
].from
;
2359 if (this_to
< prev
[j
].to
)
2360 this_to
= prev
[j
].to
;
2362 for (; prev
<= g
; prev
++)
2364 prev
->from
= this_from
;
2369 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2371 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2382 if (out
->allocated
< out
->used
+ len
)
2384 font
->get_metrics (font
, in
, from
, to
);
2385 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2386 sizeof (MFLTGlyph
) * len
);
2391 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2393 static MFLTGlyphString gstring
;
2395 static bool m17n_flt_initialized
;
2398 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2399 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2401 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2403 struct MFLTFontFT flt_font_ft
;
2405 bool with_variation_selector
= 0;
2407 if (! m17n_flt_initialized
)
2410 #ifdef M17N_FLT_USE_NEW_FEATURE
2411 mflt_enable_new_feature
= 1;
2412 mflt_try_otf
= ftfont_try_otf
;
2413 #endif /* M17N_FLT_USE_NEW_FEATURE */
2414 m17n_flt_initialized
= 1;
2417 for (i
= 0; i
< len
; i
++)
2419 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2424 c
= LGLYPH_CHAR (g
);
2425 if (CHAR_VARIATION_SELECTOR_P (c
))
2426 with_variation_selector
= 1;
2431 if (with_variation_selector
)
2433 setup_otf_gstring (len
);
2434 for (i
= 0; i
< len
; i
++)
2436 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2438 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2439 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2440 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2442 OTF_drive_cmap (otf
, &otf_gstring
);
2443 for (i
= 0; i
< otf_gstring
.used
; i
++)
2445 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2446 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2447 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2449 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2450 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2451 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2453 if (len
> otf_gstring
.used
)
2455 len
= otf_gstring
.used
;
2456 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2460 if (INT_MAX
/ 2 < len
)
2461 memory_full (SIZE_MAX
);
2463 if (gstring
.allocated
== 0)
2465 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2466 gstring
.glyphs
= xnmalloc (len
* 2, sizeof *gstring
.glyphs
);
2467 gstring
.allocated
= len
* 2;
2469 else if (gstring
.allocated
< len
* 2)
2471 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2472 sizeof *gstring
.glyphs
);
2473 gstring
.allocated
= len
* 2;
2475 memset (gstring
.glyphs
, 0, len
* sizeof *gstring
.glyphs
);
2476 for (i
= 0; i
< len
; i
++)
2478 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2480 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2481 if (with_variation_selector
)
2483 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2484 gstring
.glyphs
[i
].encoded
= 1;
2492 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2495 flt_font_ft
.flt_font
.family
= Mnil
;
2497 flt_font_ft
.flt_font
.family
2498 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2500 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2501 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2502 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2503 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2504 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2505 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2506 flt_font_ft
.flt_font
.internal
= NULL
;
2507 flt_font_ft
.font
= font
;
2508 flt_font_ft
.ft_face
= ft_face
;
2509 flt_font_ft
.otf
= otf
;
2510 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2512 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2513 /* A little bit ad hoc. Perhaps, shaper must get script and
2514 language information, and select a proper flt for them
2516 flt
= mflt_get (msymbol ("combining"));
2517 for (i
= 0; i
< 3; i
++)
2519 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2522 if (INT_MAX
/ 2 < gstring
.allocated
)
2523 memory_full (SIZE_MAX
);
2524 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2525 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2526 gstring
.allocated
*= 2;
2528 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2530 for (i
= 0; i
< gstring
.used
; i
++)
2532 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2534 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2535 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2538 for (i
= 0; i
< gstring
.used
; i
++)
2540 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2541 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2545 lglyph
= LGLYPH_NEW ();
2546 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2548 LGLYPH_SET_FROM (lglyph
, g
->from
);
2549 LGLYPH_SET_TO (lglyph
, g
->to
);
2550 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2551 LGLYPH_SET_CODE (lglyph
, g
->code
);
2552 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2553 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2554 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2555 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2556 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2559 Lisp_Object vec
= make_uninit_vector (3);
2561 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2562 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2563 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2564 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2567 return make_number (i
);
2571 ftfont_shape (Lisp_Object lgstring
)
2573 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
2574 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2575 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2578 return make_number (0);
2579 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2580 &ftfont_info
->matrix
);
2583 #endif /* HAVE_M17N_FLT */
2585 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2588 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2590 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2591 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2595 return OTF_get_variation_glyphs (otf
, c
, variations
);
2598 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2599 #endif /* HAVE_LIBOTF */
2601 static const char *const ftfont_booleans
[] = {
2614 static const char *const ftfont_non_booleans
[] = {
2646 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2648 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2653 syms_of_ftfont (void)
2655 /* Symbolic type of this font-driver. */
2656 DEFSYM (Qfreetype
, "freetype");
2658 /* Fontconfig's generic families and their aliases. */
2659 DEFSYM (Qmonospace
, "monospace");
2660 DEFSYM (Qsans_serif
, "sans-serif");
2661 DEFSYM (Qserif
, "serif");
2662 DEFSYM (Qsans
, "sans");
2663 DEFSYM (Qsans__serif
, "sans serif");
2665 staticpro (&freetype_font_cache
);
2666 freetype_font_cache
= list1 (Qt
);
2668 staticpro (&ftfont_generic_family_list
);
2669 ftfont_generic_family_list
= list3 (Fcons (Qmonospace
, Qt
),
2670 Fcons (Qsans_serif
, Qt
),
2673 staticpro (&ft_face_cache
);
2674 ft_face_cache
= Qnil
;
2676 ftfont_driver
.type
= Qfreetype
;
2677 register_font_driver (&ftfont_driver
, NULL
);