1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006-2014 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>
28 #include "dispextern.h"
30 #include "blockinput.h"
31 #include "character.h"
34 #include "composite.h"
39 /* Symbolic type of this font-driver. */
40 static Lisp_Object Qfreetype
;
42 /* Fontconfig's generic families and their aliases. */
43 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
45 /* Flag to tell if FcInit is already called or not. */
46 static bool fc_initialized
;
48 /* Handle to a FreeType library instance. */
49 static FT_Library ft_library
;
51 /* Cache for FreeType fonts. */
52 static Lisp_Object freetype_font_cache
;
54 /* Cache for FT_Face and FcCharSet. */
55 static Lisp_Object ft_face_cache
;
57 /* The actual structure for FreeType font that can be cast to struct
64 /* The following four members must be here in this order to be
65 compatible with struct xftfont_info (in xftfont.c). */
66 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
68 #endif /* HAVE_LIBOTF */
76 FTFONT_CACHE_FOR_FACE
,
77 FTFONT_CACHE_FOR_CHARSET
,
78 FTFONT_CACHE_FOR_ENTITY
81 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
83 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
85 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
86 enum ftfont_cache_for
);
88 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
90 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
96 /* characters to distinguish the charset from the others */
98 /* additional constraint by language */
101 FcCharSet
*fc_charset
;
102 } fc_charset_table
[] =
103 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
104 { "iso8859-2", { 0x00A0, 0x010E }},
105 { "iso8859-3", { 0x00A0, 0x0108 }},
106 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
107 { "iso8859-5", { 0x00A0, 0x0401 }},
108 { "iso8859-6", { 0x00A0, 0x060C }},
109 { "iso8859-7", { 0x00A0, 0x0384 }},
110 { "iso8859-8", { 0x00A0, 0x05D0 }},
111 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
112 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
113 { "iso8859-11", { 0x00A0, 0x0E01 }},
114 { "iso8859-13", { 0x00A0, 0x201C }},
115 { "iso8859-14", { 0x00A0, 0x0174 }},
116 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
117 { "iso8859-16", { 0x00A0, 0x0218}},
118 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
119 { "big5-0", { 0xF6B1 }, "zh-tw" },
120 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
121 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
122 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
123 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
124 { "cns11643.1992-3", { 0x201A9 }},
125 { "cns11643.1992-4", { 0x20057 }},
126 { "cns11643.1992-5", { 0x20000 }},
127 { "cns11643.1992-6", { 0x20003 }},
128 { "cns11643.1992-7", { 0x20055 }},
129 { "gbk-0", { 0x4E06 }, "zh-cn"},
130 { "jisx0212.1990-0", { 0x4E44 }},
131 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
132 { "jisx0213.2000-2", { 0xFA49 }},
133 { "jisx0213.2004-1", { 0x20B9F }},
134 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
135 { "tis620.2529-1", { 0x0E01 }, "th"},
136 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
137 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
138 { "mulelao-1", { 0x0E81 }, "lo"},
139 { "unicode-sip", { 0x20000 }},
143 /* Dirty hack for handing ADSTYLE property.
145 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
146 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
147 "Oblique", "Italic", or any non-normal SWIDTH property names
148 (e.g. SemiCondensed) are appended. In addition, if there's no
149 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
150 "Regular" is used for FC_STYLE (see the function
151 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
153 Unfortunately this behavior is not documented, so the following
154 code may fail if FreeType changes the behavior in the future. */
157 get_adstyle_property (FcPattern
*p
)
164 if ((FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fcstr
) == FcResultMatch
)
165 && xstrcasecmp ((char *) fcstr
, "bdf") != 0
166 && xstrcasecmp ((char *) fcstr
, "pcf") != 0)
167 /* Not a BDF nor PCF font. */
170 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
172 str
= (char *) fcstr
;
173 for (end
= str
; *end
&& *end
!= ' '; end
++);
176 char *newstr
= alloca (end
- str
+ 1);
177 memcpy (newstr
, str
, end
- str
);
178 newstr
[end
- str
] = '\0';
179 end
= newstr
+ (end
- str
);
182 if (xstrcasecmp (str
, "Regular") == 0
183 || xstrcasecmp (str
, "Bold") == 0
184 || xstrcasecmp (str
, "Oblique") == 0
185 || xstrcasecmp (str
, "Italic") == 0)
187 adstyle
= font_intern_prop (str
, end
- str
, 1);
188 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
194 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
196 Lisp_Object key
, cache
, entity
;
204 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
206 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
210 key
= Fcons (build_unibyte_string (file
), make_number (idx
));
211 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
212 entity
= XCAR (cache
);
215 Lisp_Object val
= font_make_entity ();
218 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
219 ASET (val
, i
, AREF (entity
, i
));
221 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
222 font_put_extra (val
, QCfont_entity
, key
);
226 entity
= font_make_entity ();
227 XSETCAR (cache
, entity
);
229 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
230 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
232 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
234 char *s
= (char *) str
;
235 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
237 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
239 char *s
= (char *) str
;
240 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
242 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
244 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
245 numeric
= FC_WEIGHT_MEDIUM
;
246 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
248 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
251 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
253 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
255 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
257 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
259 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
262 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
263 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
264 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
265 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
268 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
270 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
273 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
274 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
278 /* As this font is not scalable, perhaps this is a BDF or PCF
282 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
283 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
284 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
288 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
289 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
290 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
291 FT_Done_Face (ft_face
);
295 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
296 font_put_extra (entity
, QCfont_entity
, key
);
301 static Lisp_Object ftfont_generic_family_list
;
304 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
311 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
312 if (EQ (family
, Qmono
))
314 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
315 family
= Qsans_serif
;
316 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
319 if (! EQ (XCDR (slot
), Qt
))
321 pattern
= FcPatternDuplicate (pattern
);
324 FcPatternDel (pattern
, FC_FOUNDRY
);
325 FcPatternDel (pattern
, FC_FAMILY
);
326 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
327 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
329 /* This is to avoid the effect of locale. */
330 static const FcChar8 lang
[] = "en";
331 langset
= FcLangSetCreate ();
332 FcLangSetAdd (langset
, lang
);
333 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
334 FcLangSetDestroy (langset
);
336 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
337 FcDefaultSubstitute (pattern
);
338 match
= FcFontMatch (NULL
, pattern
, &result
);
343 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
344 family
= intern ((char *) fam
);
348 XSETCDR (slot
, family
);
349 if (match
) FcPatternDestroy (match
);
351 if (pattern
) FcPatternDestroy (pattern
);
355 struct ftfont_cache_data
358 FcCharSet
*fc_charset
;
362 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
364 Lisp_Object cache
, val
, entity
;
365 struct ftfont_cache_data
*cache_data
;
367 if (FONT_ENTITY_P (key
))
370 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
371 eassert (CONSP (val
));
377 if (NILP (ft_face_cache
))
380 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
383 if (NILP (ft_face_cache
))
389 ft_face_cache
= Fmake_hash_table (2, args
);
391 cache_data
= xmalloc (sizeof *cache_data
);
392 cache_data
->ft_face
= NULL
;
393 cache_data
->fc_charset
= NULL
;
394 val
= make_save_ptr_int (cache_data
, 0);
395 cache
= Fcons (Qnil
, val
);
396 Fputhash (key
, cache
, ft_face_cache
);
401 cache_data
= XSAVE_POINTER (val
, 0);
404 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
407 if (cache_for
== FTFONT_CACHE_FOR_FACE
408 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
410 char *filename
= SSDATA (XCAR (key
));
411 int idx
= XINT (XCDR (key
));
413 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
416 && FT_Init_FreeType (&ft_library
) != 0)
418 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
424 FcPattern
*pat
= NULL
;
425 FcFontSet
*fontset
= NULL
;
426 FcObjectSet
*objset
= NULL
;
427 FcCharSet
*charset
= NULL
;
429 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
430 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
433 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
436 fontset
= FcFontList (NULL
, pat
, objset
);
439 if (fontset
&& fontset
->nfont
> 0
440 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
443 cache_data
->fc_charset
= FcCharSetCopy (charset
);
445 cache_data
->fc_charset
= FcCharSetCreate ();
449 FcFontSetDestroy (fontset
);
451 FcObjectSetDestroy (objset
);
453 FcPatternDestroy (pat
);
460 ftfont_get_fc_charset (Lisp_Object entity
)
462 Lisp_Object val
, cache
;
463 struct ftfont_cache_data
*cache_data
;
465 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
467 cache_data
= XSAVE_POINTER (val
, 0);
468 return cache_data
->fc_charset
;
473 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
477 if (ftfont_info
->otf
)
478 return ftfont_info
->otf
;
479 if (! ftfont_info
->maybe_otf
)
481 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
482 if (! otf
|| OTF_get_table (otf
, "head") < 0)
486 ftfont_info
->maybe_otf
= 0;
489 ftfont_info
->otf
= otf
;
492 #endif /* HAVE_LIBOTF */
494 static Lisp_Object
ftfont_get_cache (struct frame
*);
495 static Lisp_Object
ftfont_list (struct frame
*, Lisp_Object
);
496 static Lisp_Object
ftfont_match (struct frame
*, Lisp_Object
);
497 static Lisp_Object
ftfont_list_family (struct frame
*);
498 static Lisp_Object
ftfont_open (struct frame
*, Lisp_Object
, int);
499 static void ftfont_close (struct font
*);
500 static int ftfont_has_char (Lisp_Object
, int);
501 static unsigned ftfont_encode_char (struct font
*, int);
502 static int ftfont_text_extents (struct font
*, unsigned *, int,
503 struct font_metrics
*);
504 static int ftfont_get_bitmap (struct font
*, unsigned,
505 struct font_bitmap
*, int);
506 static int ftfont_anchor_point (struct font
*, unsigned, int,
509 static Lisp_Object
ftfont_otf_capability (struct font
*);
510 # ifdef HAVE_M17N_FLT
511 static Lisp_Object
ftfont_shape (Lisp_Object
);
515 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
516 static int ftfont_variation_glyphs (struct font
*, int c
,
517 unsigned variations
[256]);
518 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
520 struct font_driver ftfont_driver
=
522 LISP_INITIALLY_ZERO
, /* Qfreetype */
523 0, /* case insensitive */
528 NULL
, /* free_entity */
531 /* We can't draw a text without device dependent functions. */
532 NULL
, /* prepare_face */
533 NULL
, /* done_face */
537 /* We can't draw a text without device dependent functions. */
540 NULL
, /* free_bitmap */
541 NULL
, /* get_outline */
542 NULL
, /* free_outline */
545 ftfont_otf_capability
,
546 #else /* not HAVE_LIBOTF */
548 #endif /* not HAVE_LIBOTF */
549 NULL
, /* otf_drive */
550 NULL
, /* start_for_frame */
551 NULL
, /* end_for_frame */
552 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
554 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
556 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
559 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
560 ftfont_variation_glyphs
,
565 ftfont_filter_properties
, /* filter_properties */
569 ftfont_get_cache (struct frame
*f
)
571 return freetype_font_cache
;
575 ftfont_get_charset (Lisp_Object registry
)
577 char *str
= SSDATA (SYMBOL_NAME (registry
));
578 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
582 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
586 else if (str
[i
] == '*')
593 regexp
= make_unibyte_string (re
, j
);
594 for (i
= 0; fc_charset_table
[i
].name
; i
++)
595 if (fast_c_string_match_ignore_case
596 (regexp
, fc_charset_table
[i
].name
,
597 strlen (fc_charset_table
[i
].name
)) >= 0)
599 if (! fc_charset_table
[i
].name
)
601 if (! fc_charset_table
[i
].fc_charset
)
603 FcCharSet
*charset
= FcCharSetCreate ();
604 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
608 for (j
= 0; uniquifier
[j
]; j
++)
609 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
611 FcCharSetDestroy (charset
);
614 fc_charset_table
[i
].fc_charset
= charset
;
622 unsigned int script_tag
, langsys_tag
;
624 unsigned int *features
[2];
627 #define OTF_SYM_TAG(SYM, TAG) \
629 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
630 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
633 #define OTF_TAG_STR(TAG, P) \
635 (P)[0] = (char) (TAG >> 24); \
636 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
637 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
638 (P)[3] = (char) (TAG & 0xFF); \
643 #define OTF_TAG_SYM(SYM, TAG) \
647 OTF_TAG_STR (TAG, str); \
648 (SYM) = font_intern_prop (str, 4, 1); \
653 static struct OpenTypeSpec
*
654 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
656 struct OpenTypeSpec
*spec
= xmalloc_unsafe (sizeof *spec
);
663 spec
->script
= XCAR (otf_spec
);
664 if (! NILP (spec
->script
))
666 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
667 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
668 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
669 spec
->script
= XCDR (val
);
674 spec
->script_tag
= 0x44464C54; /* "DFLT" */
675 otf_spec
= XCDR (otf_spec
);
676 spec
->langsys_tag
= 0;
677 if (! NILP (otf_spec
))
679 val
= XCAR (otf_spec
);
681 OTF_SYM_TAG (val
, spec
->langsys_tag
);
682 otf_spec
= XCDR (otf_spec
);
684 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
685 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
689 val
= XCAR (otf_spec
);
694 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
696 : xmalloc_atomic_unsafe (XINT (len
) * sizeof *spec
->features
[i
]));
697 if (! spec
->features
[i
])
699 if (i
> 0 && spec
->features
[0])
700 xfree (spec
->features
[0]);
704 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
706 if (NILP (XCAR (val
)))
712 OTF_SYM_TAG (XCAR (val
), tag
);
713 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
716 spec
->nfeatures
[i
] = j
;
722 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
724 Lisp_Object tmp
, extra
;
725 FcPattern
*pattern
= NULL
;
726 FcCharSet
*charset
= NULL
;
727 FcLangSet
*langset
= NULL
;
731 Lisp_Object script
= Qnil
;
732 Lisp_Object registry
;
735 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
737 /* Fontconfig doesn't support reverse-italic/oblique. */
740 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
741 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
742 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
743 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
746 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
748 || EQ (registry
, Qascii_0
)
749 || EQ (registry
, Qiso10646_1
)
750 || EQ (registry
, Qunicode_bmp
))
756 fc_charset_idx
= ftfont_get_charset (registry
);
757 if (fc_charset_idx
< 0)
759 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
760 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
761 lang
= (FcChar8
*) *langname
;
764 langset
= FcLangSetCreate ();
767 FcLangSetAdd (langset
, lang
);
772 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
773 CONSP (extra
); extra
= XCDR (extra
))
775 Lisp_Object key
, val
;
777 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
783 else if (EQ (key
, QClang
))
786 langset
= FcLangSetCreate ();
791 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
795 for (; CONSP (val
); val
= XCDR (val
))
796 if (SYMBOLP (XCAR (val
))
797 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
800 else if (EQ (key
, QCotf
))
804 *otspec
= ftfont_get_open_type_spec (val
);
807 strcat (otlayout
, "otlayout:");
808 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
809 script
= (*otspec
)->script
;
812 else if (EQ (key
, QCscript
))
814 else if (EQ (key
, QCscalable
))
815 scalable
= ! NILP (val
);
818 if (! NILP (script
) && ! charset
)
820 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
822 if (CONSP (chars
) && CONSP (CDR (chars
)))
824 charset
= FcCharSetCreate ();
827 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
828 if (CHARACTERP (XCAR (chars
))
829 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
834 pattern
= FcPatternCreate ();
837 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
839 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
841 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
843 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
846 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
849 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
852 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
855 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
861 /* We come here because of unexpected error in fontconfig API call
862 (usually insufficient memory). */
865 FcPatternDestroy (pattern
);
870 if ((*otspec
)->nfeatures
[0] > 0)
871 xfree ((*otspec
)->features
[0]);
872 if ((*otspec
)->nfeatures
[1] > 0)
873 xfree ((*otspec
)->features
[1]);
879 if (langset
) FcLangSetDestroy (langset
);
880 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
885 ftfont_list (struct frame
*f
, Lisp_Object spec
)
887 Lisp_Object val
= Qnil
, family
, adstyle
;
890 FcFontSet
*fontset
= NULL
;
891 FcObjectSet
*objset
= NULL
;
893 Lisp_Object chars
= Qnil
;
894 char otlayout
[15]; /* For "otlayout:XXXX" */
895 struct OpenTypeSpec
*otspec
= NULL
;
897 const char *langname
= NULL
;
899 if (! fc_initialized
)
905 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
908 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
910 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
913 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
914 if (CONSP (val
) && VECTORP (XCDR (val
)))
919 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
920 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
921 family
= AREF (spec
, FONT_FAMILY_INDEX
);
924 Lisp_Object resolved
;
926 resolved
= ftfont_resolve_generic_family (family
, pattern
);
927 if (! NILP (resolved
))
929 FcPatternDel (pattern
, FC_FAMILY
);
930 if (! FcPatternAddString (pattern
, FC_FAMILY
,
931 SYMBOL_FcChar8 (resolved
)))
935 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
936 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
938 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
939 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
940 FC_STYLE
, FC_FILE
, FC_INDEX
,
943 #endif /* FC_CAPABILITY */
951 FcObjectSetAdd (objset
, FC_CHARSET
);
953 fontset
= FcFontList (NULL
, pattern
, objset
);
954 if (! fontset
|| fontset
->nfont
== 0)
957 /* Need fix because this finds any fonts. */
958 if (fontset
->nfont
== 0 && ! NILP (family
))
960 /* Try matching with configuration. For instance, the
961 configuration may specify "Nimbus Mono L" as an alias of
963 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
964 SYMBOL_FcChar8 (family
), NULL
);
967 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
970 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
973 FcPatternDel (pattern
, FC_FAMILY
);
974 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
975 FcFontSetDestroy (fontset
);
976 fontset
= FcFontList (NULL
, pattern
, objset
);
977 if (fontset
&& fontset
->nfont
> 0)
983 for (i
= 0; i
< fontset
->nfont
; i
++)
991 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
1002 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
1004 || ! strstr ((char *) this, otlayout
))
1007 #endif /* FC_CAPABILITY */
1015 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1018 otf
= OTF_open ((char *) file
);
1021 passed
= (OTF_check_features (otf
, 1, otspec
->script_tag
,
1022 otspec
->langsys_tag
,
1023 otspec
->features
[0],
1024 otspec
->nfeatures
[0]) == 1
1025 && OTF_check_features (otf
, 0, otspec
->script_tag
,
1026 otspec
->langsys_tag
,
1027 otspec
->features
[1],
1028 otspec
->nfeatures
[1]) == 1);
1033 #endif /* HAVE_LIBOTF */
1034 if (VECTORP (chars
))
1038 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1041 for (j
= 0; j
< ASIZE (chars
); j
++)
1042 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1043 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1045 if (j
== ASIZE (chars
))
1048 if (! NILP (adstyle
) || langname
)
1050 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1052 if (! NILP (adstyle
)
1053 && (NILP (this_adstyle
)
1054 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1055 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1058 && ! NILP (this_adstyle
)
1059 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1062 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1063 AREF (spec
, FONT_EXTRA_INDEX
));
1064 if (! NILP (entity
))
1065 val
= Fcons (entity
, val
);
1067 val
= Fnreverse (val
);
1071 /* We come here because of unexpected error in fontconfig API call
1072 (usually insufficient memory). */
1076 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1077 if (objset
) FcObjectSetDestroy (objset
);
1078 if (fontset
) FcFontSetDestroy (fontset
);
1079 if (pattern
) FcPatternDestroy (pattern
);
1084 ftfont_match (struct frame
*f
, Lisp_Object spec
)
1086 Lisp_Object entity
= Qnil
;
1087 FcPattern
*pattern
, *match
= NULL
;
1089 char otlayout
[15]; /* For "otlayout:XXXX" */
1090 struct OpenTypeSpec
*otspec
= NULL
;
1091 const char *langname
= NULL
;
1093 if (! fc_initialized
)
1099 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1103 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1107 value
.type
= FcTypeDouble
;
1108 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1109 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1111 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1113 FcDefaultSubstitute (pattern
);
1114 match
= FcFontMatch (NULL
, pattern
, &result
);
1117 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1118 FcPatternDestroy (match
);
1119 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1120 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1121 ftfont_generic_family_list
))
1122 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1123 AREF (entity
, FONT_FAMILY_INDEX
))))
1127 FcPatternDestroy (pattern
);
1129 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1134 ftfont_list_family (struct frame
*f
)
1136 Lisp_Object list
= Qnil
;
1137 FcPattern
*pattern
= NULL
;
1138 FcFontSet
*fontset
= NULL
;
1139 FcObjectSet
*objset
= NULL
;
1142 if (! fc_initialized
)
1148 pattern
= FcPatternCreate ();
1151 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1154 fontset
= FcFontList (NULL
, pattern
, objset
);
1158 for (i
= 0; i
< fontset
->nfont
; i
++)
1160 FcPattern
*pat
= fontset
->fonts
[i
];
1163 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1164 list
= Fcons (intern ((char *) str
), list
);
1168 if (objset
) FcObjectSetDestroy (objset
);
1169 if (fontset
) FcFontSetDestroy (fontset
);
1170 if (pattern
) FcPatternDestroy (pattern
);
1177 ftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
1179 struct ftfont_info
*ftfont_info
;
1181 struct ftfont_cache_data
*cache_data
;
1185 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1192 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1196 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1199 filename
= XCAR (val
);
1202 cache_data
= XSAVE_POINTER (XCDR (cache
), 0);
1203 ft_face
= cache_data
->ft_face
;
1204 if (XSAVE_INTEGER (val
, 1) > 0)
1206 /* FT_Face in this cache is already used by the different size. */
1207 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1209 if (FT_Activate_Size (ft_size
) != 0)
1211 FT_Done_Size (ft_size
);
1215 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) + 1);
1216 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1219 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1221 if (XSAVE_INTEGER (val
, 1) == 0)
1222 FT_Done_Face (ft_face
);
1226 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1227 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1228 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1230 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1231 len
= font_unparse_fcname (entity
, size
, name
, 256);
1233 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1235 ASET (font_object
, FONT_FULLNAME_INDEX
,
1236 AREF (font_object
, FONT_NAME_INDEX
));
1237 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1238 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1239 font
= XFONT_OBJECT (font_object
);
1240 ftfont_info
= (struct ftfont_info
*) font
;
1241 ftfont_info
->ft_size
= ft_face
->size
;
1242 ftfont_info
->index
= XINT (idx
);
1244 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1245 ftfont_info
->otf
= NULL
;
1246 #endif /* HAVE_LIBOTF */
1247 /* This means that there's no need of transformation. */
1248 ftfont_info
->matrix
.xx
= 0;
1249 font
->pixel_size
= size
;
1250 font
->driver
= &ftfont_driver
;
1251 font
->encoding_charset
= font
->repertory_charset
= -1;
1253 upEM
= ft_face
->units_per_EM
;
1254 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1255 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1258 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1259 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1260 font
->height
= ft_face
->height
* size
/ upEM
;
1264 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1265 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1266 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1268 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1269 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1271 spacing
= FC_PROPORTIONAL
;
1272 if (spacing
!= FC_PROPORTIONAL
1274 && spacing
!= FC_DUAL
1275 #endif /* FC_DUAL */
1277 font
->min_width
= font
->average_width
= font
->space_width
1278 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1279 : ft_face
->size
->metrics
.max_advance
>> 6);
1284 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1285 for (i
= 32, n
= 0; i
< 127; i
++)
1286 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1288 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1291 && (! font
->min_width
|| font
->min_width
> this_width
))
1292 font
->min_width
= this_width
;
1294 font
->space_width
= this_width
;
1295 font
->average_width
+= this_width
;
1299 font
->average_width
/= n
;
1302 font
->baseline_offset
= 0;
1303 font
->relative_compose
= 0;
1304 font
->default_ascent
= 0;
1305 font
->vertical_centering
= 0;
1308 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1309 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1313 font
->underline_position
= -1;
1314 font
->underline_thickness
= 0;
1321 ftfont_close (struct font
*font
)
1323 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1324 Lisp_Object val
, cache
;
1326 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1327 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1328 eassert (CONSP (cache
));
1330 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) - 1);
1331 if (XSAVE_INTEGER (val
, 1) == 0)
1333 struct ftfont_cache_data
*cache_data
= XSAVE_POINTER (val
, 0);
1335 FT_Done_Face (cache_data
->ft_face
);
1337 if (ftfont_info
->otf
)
1338 OTF_close (ftfont_info
->otf
);
1340 cache_data
->ft_face
= NULL
;
1343 FT_Done_Size (ftfont_info
->ft_size
);
1347 ftfont_has_char (Lisp_Object font
, int c
)
1349 struct charset
*cs
= NULL
;
1351 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1352 && charset_jisx0208
>= 0)
1353 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1354 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1355 && charset_ksc5601
>= 0)
1356 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1358 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1360 if (FONT_ENTITY_P (font
))
1362 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1364 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1368 struct ftfont_info
*ftfont_info
;
1370 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1371 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1377 ftfont_encode_char (struct font
*font
, int c
)
1379 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1380 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1381 FT_ULong charcode
= c
;
1382 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1384 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1388 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1390 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1391 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1396 if (ftfont_info
->ft_size
!= ft_face
->size
)
1397 FT_Activate_Size (ftfont_info
->ft_size
);
1399 memset (metrics
, 0, sizeof (struct font_metrics
));
1400 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1402 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1404 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1410 metrics
->lbearing
= m
->horiBearingX
>> 6;
1411 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1412 metrics
->ascent
= m
->horiBearingY
>> 6;
1413 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1419 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1420 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1421 if (metrics
->rbearing
1422 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1424 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1425 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1426 metrics
->ascent
= m
->horiBearingY
>> 6;
1427 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1428 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1430 width
+= m
->horiAdvance
>> 6;
1434 width
+= font
->space_width
;
1438 metrics
->width
= width
;
1444 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1446 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1447 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1448 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1450 if (ftfont_info
->ft_size
!= ft_face
->size
)
1451 FT_Activate_Size (ftfont_info
->ft_size
);
1452 if (bits_per_pixel
== 1)
1454 #ifdef FT_LOAD_TARGET_MONO
1455 load_flags
|= FT_LOAD_TARGET_MONO
;
1457 load_flags
|= FT_LOAD_MONOCHROME
;
1460 else if (bits_per_pixel
!= 8)
1461 /* We don't support such a rendering. */
1464 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1466 bitmap
->bits_per_pixel
1467 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1468 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1469 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1470 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1472 if (bitmap
->bits_per_pixel
< 0)
1473 /* We don't support that kind of pixel mode. */
1475 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1476 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1477 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1478 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1479 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1480 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1481 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1487 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1490 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1491 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1493 if (ftfont_info
->ft_size
!= ft_face
->size
)
1494 FT_Activate_Size (ftfont_info
->ft_size
);
1495 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1497 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1499 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1501 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1502 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1509 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1511 Lisp_Object scripts
, langsyses
, features
, sym
;
1514 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1516 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1518 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1520 OTF_LangSys
*otf_langsys
;
1523 otf_langsys
= otf_script
->LangSys
+ j
;
1524 else if (otf_script
->DefaultLangSysOffset
)
1525 otf_langsys
= &otf_script
->DefaultLangSys
;
1529 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1531 l
= otf_langsys
->FeatureIndex
[k
];
1532 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1534 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1535 features
= Fcons (sym
, features
);
1538 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1541 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1544 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1545 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1553 ftfont_otf_capability (struct font
*font
)
1555 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1556 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1557 Lisp_Object gsub_gpos
;
1561 gsub_gpos
= Fcons (Qnil
, Qnil
);
1562 if (OTF_get_table (otf
, "GSUB") == 0
1563 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1564 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1565 if (OTF_get_table (otf
, "GPOS") == 0
1566 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1567 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1571 #ifdef HAVE_M17N_FLT
1573 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1574 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1575 /* We can use the new feature of libotf and m17n-flt to handle the
1576 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1577 some Agian scripts. */
1578 #define M17N_FLT_USE_NEW_FEATURE
1591 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1594 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1595 FT_Face ft_face
= flt_font_ft
->ft_face
;
1598 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1601 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1603 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1609 /* Operators for 26.6 fixed fractional pixel format */
1611 #define FLOOR(x) ((x) & -64)
1612 #define CEIL(x) (((x)+63) & -64)
1613 #define ROUND(x) (((x)+32) & -64)
1616 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1619 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1620 FT_Face ft_face
= flt_font_ft
->ft_face
;
1623 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1626 if (g
->code
!= FONT_INVALID_CODE
)
1628 FT_Glyph_Metrics
*m
;
1630 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1632 m
= &ft_face
->glyph
->metrics
;
1633 if (flt_font_ft
->matrix
)
1638 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1639 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1640 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1641 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1642 for (i
= 0; i
< 4; i
++)
1643 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1644 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1645 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1646 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1647 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1651 g
->lbearing
= FLOOR (m
->horiBearingX
);
1652 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1653 g
->ascent
= CEIL (m
->horiBearingY
);
1654 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1656 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1661 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1662 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1663 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1672 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1674 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1676 #define FEATURE_ANY(IDX) \
1677 (spec->features[IDX] \
1678 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1680 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1681 OTF
*otf
= flt_font_ft
->otf
;
1686 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1687 /* Return true iff any of GSUB or GPOS support the script (and
1690 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1692 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1695 for (i
= 0; i
< 2; i
++)
1696 if (! FEATURE_ANY (i
))
1698 if (FEATURE_NONE (i
))
1701 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1706 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1709 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1715 for (n
= 1; spec
->features
[i
][n
]; n
++);
1716 tags
= alloca (sizeof (OTF_Tag
) * n
);
1717 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1719 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1722 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1724 tags
[n
] = spec
->features
[i
][n
];
1726 #ifdef M17N_FLT_USE_NEW_FEATURE
1727 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1728 tags
, n
- negative
) != 1)
1730 #else /* not M17N_FLT_USE_NEW_FEATURE */
1731 if (n
- negative
> 0
1732 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1733 tags
, n
- negative
) != 1)
1735 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1742 #define DEVICE_DELTA(table, size) \
1743 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1744 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1748 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1749 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1751 if (anchor
->AnchorFormat
== 2)
1753 FT_Outline
*outline
;
1754 int ap
= anchor
->f
.f1
.AnchorPoint
;
1756 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1757 outline
= &ft_face
->glyph
->outline
;
1758 if (ap
< outline
->n_points
)
1760 *x
= outline
->points
[ap
].x
<< 6;
1761 *y
= outline
->points
[ap
].y
<< 6;
1764 else if (anchor
->AnchorFormat
== 3)
1766 if (anchor
->f
.f2
.XDeviceTable
.offset
1767 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1768 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1769 if (anchor
->f
.f2
.YDeviceTable
.offset
1770 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1771 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1775 static OTF_GlyphString otf_gstring
;
1778 setup_otf_gstring (int size
)
1780 if (otf_gstring
.size
< size
)
1782 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1783 size
, sizeof (OTF_Glyph
));
1784 otf_gstring
.size
= size
;
1786 otf_gstring
.used
= size
;
1787 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1790 #ifdef M17N_FLT_USE_NEW_FEATURE
1792 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1793 #define PACK_OTF_TAG(TAG) \
1794 ((((TAG) & 0x7F000000) >> 3) \
1795 | (((TAG) & 0x7F0000) >> 2) \
1796 | (((TAG) & 0x7F00) >> 1) \
1799 /* Assuming that FONT is an OpenType font, apply OpenType features
1800 specified in SPEC on glyphs between FROM and TO of IN, and record
1801 the lastly applied feature in each glyph of IN. If OUT is not
1802 NULL, append the resulting glyphs to OUT while storing glyph
1803 position adjustment information in ADJUSTMENT. */
1806 ftfont_drive_otf (MFLTFont
*font
,
1808 MFLTGlyphString
*in
,
1811 MFLTGlyphString
*out
,
1812 MFLTGlyphAdjustment
*adjustment
)
1814 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1815 FT_Face ft_face
= flt_font_ft
->ft_face
;
1816 OTF
*otf
= flt_font_ft
->otf
;
1817 int len
= to
- from
;
1820 char script
[5], *langsys
= NULL
;
1821 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1822 OTF_Feature
*features
;
1826 OTF_tag_name (spec
->script
, script
);
1829 langsys
= alloca (5);
1830 OTF_tag_name (spec
->langsys
, langsys
);
1832 for (i
= 0; i
< 2; i
++)
1836 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1838 for (j
= 0; spec
->features
[i
][j
]; j
++);
1840 p
= gsub_features
= alloca (6 * j
);
1842 p
= gpos_features
= alloca (6 * j
);
1843 for (j
= 0; spec
->features
[i
][j
]; j
++)
1845 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1846 *p
++ = '*', *p
++ = ',';
1849 OTF_tag_name (spec
->features
[i
][j
], p
);
1858 setup_otf_gstring (len
);
1859 for (i
= 0; i
< len
; i
++)
1861 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
& 0x11FFFF;
1862 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1865 OTF_drive_gdef (otf
, &otf_gstring
);
1866 gidx
= out
? out
->used
: from
;
1868 if (gsub_features
&& out
)
1870 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1873 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1875 features
= otf
->gsub
->FeatureList
.Feature
;
1876 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1879 int min_from
, max_to
;
1880 int feature_idx
= otfg
->positioning_type
>> 4;
1882 g
= out
->glyphs
+ out
->used
;
1883 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1884 if (g
->code
!= otfg
->glyph_id
)
1887 g
->code
= otfg
->glyph_id
;
1893 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1895 /* OTFG substitutes multiple glyphs in IN. */
1896 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1897 j
<= from
+ otfg
->f
.index
.to
; j
++)
1899 if (min_from
> in
->glyphs
[j
].from
)
1900 min_from
= in
->glyphs
[j
].from
;
1901 if (max_to
< in
->glyphs
[j
].to
)
1902 max_to
= in
->glyphs
[j
].to
;
1909 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1910 tag
= PACK_OTF_TAG (tag
);
1911 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1913 for (i
++, otfg
++; (i
< otf_gstring
.used
1914 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1917 g
= out
->glyphs
+ out
->used
;
1918 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1919 if (g
->code
!= otfg
->glyph_id
)
1922 g
->code
= otfg
->glyph_id
;
1925 feature_idx
= otfg
->positioning_type
>> 4;
1928 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1929 tag
= PACK_OTF_TAG (tag
);
1930 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1936 else if (gsub_features
)
1938 /* Just for checking which features will be applied. */
1939 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1942 features
= otf
->gsub
->FeatureList
.Feature
;
1943 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1946 int feature_idx
= otfg
->positioning_type
>> 4;
1950 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1951 tag
= PACK_OTF_TAG (tag
);
1952 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1954 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1955 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1962 if (out
->allocated
< out
->used
+ len
)
1964 for (i
= 0; i
< len
; i
++)
1965 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1968 if (gpos_features
&& out
)
1970 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1971 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1973 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1976 features
= otf
->gpos
->FeatureList
.Feature
;
1977 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1978 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1979 x_scale
= ft_face
->size
->metrics
.x_scale
;
1980 y_scale
= ft_face
->size
->metrics
.y_scale
;
1982 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1983 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1986 int feature_idx
= otfg
->positioning_type
>> 4;
1990 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1991 tag
= PACK_OTF_TAG (tag
);
1992 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1995 if (! otfg
->glyph_id
)
1997 switch (otfg
->positioning_type
& 0xF)
2001 case 1: /* Single */
2004 int format
= otfg
->f
.f1
.format
;
2006 if (format
& OTF_XPlacement
)
2008 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2009 if (format
& OTF_XPlaDevice
)
2011 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2012 if (format
& OTF_YPlacement
)
2014 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2015 if (format
& OTF_YPlaDevice
)
2017 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2018 if (format
& OTF_XAdvance
)
2020 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2021 if (format
& OTF_XAdvDevice
)
2023 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2024 if (format
& OTF_YAdvance
)
2026 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2027 if (format
& OTF_YAdvDevice
)
2029 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2030 adjustment
[i
].set
= 1;
2033 case 3: /* Cursive */
2034 /* Not yet supported. */
2036 case 4: /* Mark-to-Base */
2037 case 5: /* Mark-to-Ligature */
2041 goto label_adjust_anchor
;
2042 default: /* i.e. case 6 Mark-to-Mark */
2047 label_adjust_anchor
:
2049 int base_x
, base_y
, mark_x
, mark_y
;
2050 int this_from
, this_to
;
2052 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2053 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2054 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2055 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2057 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2058 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2059 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2060 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2061 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2062 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2063 adjustment
[i
].xoff
= (base_x
- mark_x
);
2064 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2065 adjustment
[i
].back
= (g
- prev
);
2066 adjustment
[i
].xadv
= 0;
2067 adjustment
[i
].advance_is_absolute
= 1;
2068 adjustment
[i
].set
= 1;
2069 this_from
= g
->from
;
2071 for (j
= 0; prev
+ j
< g
; j
++)
2073 if (this_from
> prev
[j
].from
)
2074 this_from
= prev
[j
].from
;
2075 if (this_to
< prev
[j
].to
)
2076 this_to
= prev
[j
].to
;
2078 for (; prev
<= g
; prev
++)
2080 prev
->from
= this_from
;
2085 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2087 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2093 else if (gpos_features
)
2095 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2098 features
= otf
->gpos
->FeatureList
.Feature
;
2099 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2101 if (otfg
->positioning_type
& 0xF)
2103 int feature_idx
= otfg
->positioning_type
>> 4;
2107 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2108 tag
= PACK_OTF_TAG (tag
);
2109 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2111 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2112 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2122 if (out
->allocated
< out
->used
+ len
)
2124 font
->get_metrics (font
, in
, from
, to
);
2125 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2126 sizeof (MFLTGlyph
) * len
);
2132 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2133 MFLTGlyphString
*in
, int from
, int to
)
2135 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2138 #else /* not M17N_FLT_USE_NEW_FEATURE */
2141 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2143 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2145 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2146 FT_Face ft_face
= flt_font_ft
->ft_face
;
2147 OTF
*otf
= flt_font_ft
->otf
;
2148 int len
= to
- from
;
2151 char script
[5], *langsys
= NULL
;
2152 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2156 OTF_tag_name (spec
->script
, script
);
2159 langsys
= alloca (5);
2160 OTF_tag_name (spec
->langsys
, langsys
);
2162 for (i
= 0; i
< 2; i
++)
2166 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2168 for (j
= 0; spec
->features
[i
][j
]; j
++);
2170 p
= gsub_features
= alloca (6 * j
);
2172 p
= gpos_features
= alloca (6 * j
);
2173 for (j
= 0; spec
->features
[i
][j
]; j
++)
2175 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2176 *p
++ = '*', *p
++ = ',';
2179 OTF_tag_name (spec
->features
[i
][j
], p
);
2188 setup_otf_gstring (len
);
2189 for (i
= 0; i
< len
; i
++)
2191 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2192 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2195 OTF_drive_gdef (otf
, &otf_gstring
);
2200 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2203 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
)
2256 for (i
= 0; i
< len
; i
++)
2257 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2262 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2263 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2265 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
)
2380 if (out
->allocated
< out
->used
+ len
)
2382 font
->get_metrics (font
, in
, from
, to
);
2383 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2384 sizeof (MFLTGlyph
) * len
);
2389 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2391 static MFLTGlyphString gstring
;
2393 static bool m17n_flt_initialized
;
2396 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2397 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2399 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2401 struct MFLTFontFT flt_font_ft
;
2403 bool with_variation_selector
= 0;
2405 if (! m17n_flt_initialized
)
2408 #ifdef M17N_FLT_USE_NEW_FEATURE
2409 mflt_enable_new_feature
= 1;
2410 mflt_try_otf
= ftfont_try_otf
;
2411 #endif /* M17N_FLT_USE_NEW_FEATURE */
2412 m17n_flt_initialized
= 1;
2415 for (i
= 0; i
< len
; i
++)
2417 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2422 c
= LGLYPH_CHAR (g
);
2423 if (CHAR_VARIATION_SELECTOR_P (c
))
2424 with_variation_selector
= 1;
2429 if (with_variation_selector
)
2431 setup_otf_gstring (len
);
2432 for (i
= 0; i
< len
; i
++)
2434 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2436 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2437 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2438 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2440 OTF_drive_cmap (otf
, &otf_gstring
);
2441 for (i
= 0; i
< otf_gstring
.used
; i
++)
2443 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2444 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2445 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2447 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2448 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2449 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2451 if (len
> otf_gstring
.used
)
2453 len
= otf_gstring
.used
;
2454 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2458 if (INT_MAX
/ 2 < len
)
2459 memory_full (SIZE_MAX
);
2461 if (gstring
.allocated
== 0)
2463 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2464 gstring
.glyphs
= xnmalloc (len
* 2, sizeof *gstring
.glyphs
);
2465 gstring
.allocated
= len
* 2;
2467 else if (gstring
.allocated
< len
* 2)
2469 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2470 sizeof *gstring
.glyphs
);
2471 gstring
.allocated
= len
* 2;
2473 memset (gstring
.glyphs
, 0, len
* sizeof *gstring
.glyphs
);
2474 for (i
= 0; i
< len
; i
++)
2476 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2478 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2479 if (with_variation_selector
)
2481 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2482 gstring
.glyphs
[i
].encoded
= 1;
2490 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2493 flt_font_ft
.flt_font
.family
= Mnil
;
2495 flt_font_ft
.flt_font
.family
2496 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2498 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2499 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2500 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2501 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2502 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2503 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2504 flt_font_ft
.flt_font
.internal
= NULL
;
2505 flt_font_ft
.font
= font
;
2506 flt_font_ft
.ft_face
= ft_face
;
2507 flt_font_ft
.otf
= otf
;
2508 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2510 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2511 /* A little bit ad hoc. Perhaps, shaper must get script and
2512 language information, and select a proper flt for them
2514 flt
= mflt_get (msymbol ("combining"));
2515 for (i
= 0; i
< 3; i
++)
2517 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2520 if (INT_MAX
/ 2 < gstring
.allocated
)
2521 memory_full (SIZE_MAX
);
2522 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2523 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2524 gstring
.allocated
*= 2;
2526 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2528 for (i
= 0; i
< gstring
.used
; i
++)
2530 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2532 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2533 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2536 for (i
= 0; i
< gstring
.used
; i
++)
2538 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2539 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2543 lglyph
= LGLYPH_NEW ();
2544 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2546 LGLYPH_SET_FROM (lglyph
, g
->from
);
2547 LGLYPH_SET_TO (lglyph
, g
->to
);
2548 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2549 LGLYPH_SET_CODE (lglyph
, g
->code
);
2550 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2551 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2552 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2553 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2554 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2557 Lisp_Object vec
= make_uninit_vector (3);
2559 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2560 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2561 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2562 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2565 return make_number (i
);
2569 ftfont_shape (Lisp_Object lgstring
)
2572 struct ftfont_info
*ftfont_info
;
2575 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2576 ftfont_info
= (struct ftfont_info
*) font
;
2577 otf
= ftfont_get_otf (ftfont_info
);
2579 return make_number (0);
2580 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2581 &ftfont_info
->matrix
);
2584 #endif /* HAVE_M17N_FLT */
2586 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2589 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2591 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2592 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2596 return OTF_get_variation_glyphs (otf
, c
, variations
);
2599 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2600 #endif /* HAVE_LIBOTF */
2603 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2607 #ifdef FC_FONTFORMAT
2610 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2612 if (strcmp ((char *) str
, "TrueType") == 0)
2613 return intern ("truetype");
2614 if (strcmp ((char *) str
, "Type 1") == 0)
2615 return intern ("type1");
2616 if (strcmp ((char *) str
, "PCF") == 0)
2617 return intern ("pcf");
2618 if (strcmp ((char *) str
, "BDF") == 0)
2619 return intern ("bdf");
2621 #endif /* FC_FONTFORMAT */
2622 if (STRINGP (filename
))
2624 int len
= SBYTES (filename
);
2628 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2629 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2630 return intern ("truetype");
2631 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2632 return intern ("type1");
2633 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2634 return intern ("pcf");
2635 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2636 return intern ("bdf");
2639 return intern ("unknown");
2642 static const char *const ftfont_booleans
[] = {
2655 static const char *const ftfont_non_booleans
[] = {
2687 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2689 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2694 syms_of_ftfont (void)
2696 DEFSYM (Qfreetype
, "freetype");
2697 DEFSYM (Qmonospace
, "monospace");
2698 DEFSYM (Qsans_serif
, "sans-serif");
2699 DEFSYM (Qserif
, "serif");
2700 DEFSYM (Qmono
, "mono");
2701 DEFSYM (Qsans
, "sans");
2702 DEFSYM (Qsans__serif
, "sans serif");
2704 staticpro (&freetype_font_cache
);
2705 freetype_font_cache
= list1 (Qt
);
2707 staticpro (&ftfont_generic_family_list
);
2708 ftfont_generic_family_list
= list3 (Fcons (Qmonospace
, Qt
),
2709 Fcons (Qsans_serif
, Qt
),
2712 staticpro (&ft_face_cache
);
2713 ft_face_cache
= Qnil
;
2715 ftfont_driver
.type
= Qfreetype
;
2716 register_font_driver (&ftfont_driver
, NULL
);