1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006-2011 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/>. */
26 #include <fontconfig/fontconfig.h>
27 #include <fontconfig/fcfreetype.h>
30 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
36 #include "composite.h"
41 /* Symbolic type of this font-driver. */
42 Lisp_Object Qfreetype
;
44 /* Fontconfig's generic families and their aliases. */
45 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
47 /* Flag to tell if FcInit is already called or not. */
48 static int fc_initialized
;
50 /* Handle to a FreeType library instance. */
51 static FT_Library ft_library
;
53 /* Cache for FreeType fonts. */
54 static Lisp_Object freetype_font_cache
;
56 /* Cache for FT_Face and FcCharSet. */
57 static Lisp_Object ft_face_cache
;
59 /* The actual structure for FreeType font that can be casted to struct
66 /* The following four members must be here in this order to be
67 compatible with struct xftfont_info (in xftfont.c). */
68 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
70 #endif /* HAVE_LIBOTF */
78 FTFONT_CACHE_FOR_FACE
,
79 FTFONT_CACHE_FOR_CHARSET
,
80 FTFONT_CACHE_FOR_ENTITY
83 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
85 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
87 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
88 enum ftfont_cache_for
);
90 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
92 Lisp_Object
ftfont_font_format (FcPattern
*, Lisp_Object
);
94 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
100 /* characters to distinguish the charset from the others */
102 /* additional constraint by language */
105 FcCharSet
*fc_charset
;
106 } fc_charset_table
[] =
107 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
108 { "iso8859-2", { 0x00A0, 0x010E }},
109 { "iso8859-3", { 0x00A0, 0x0108 }},
110 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
111 { "iso8859-5", { 0x00A0, 0x0401 }},
112 { "iso8859-6", { 0x00A0, 0x060C }},
113 { "iso8859-7", { 0x00A0, 0x0384 }},
114 { "iso8859-8", { 0x00A0, 0x05D0 }},
115 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
116 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
117 { "iso8859-11", { 0x00A0, 0x0E01 }},
118 { "iso8859-13", { 0x00A0, 0x201C }},
119 { "iso8859-14", { 0x00A0, 0x0174 }},
120 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
121 { "iso8859-16", { 0x00A0, 0x0218}},
122 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
123 { "big5-0", { 0xF6B1 }, "zh-tw" },
124 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
125 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
126 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
127 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
128 { "cns11643.1992-3", { 0x201A9 }},
129 { "cns11643.1992-4", { 0x20057 }},
130 { "cns11643.1992-5", { 0x20000 }},
131 { "cns11643.1992-6", { 0x20003 }},
132 { "cns11643.1992-7", { 0x20055 }},
133 { "gbk-0", { 0x4E06 }, "zh-cn"},
134 { "jisx0212.1990-0", { 0x4E44 }},
135 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
136 { "jisx0213.2000-2", { 0xFA49 }},
137 { "jisx0213.2004-1", { 0x20B9F }},
138 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
139 { "tis620.2529-1", { 0x0E01 }, "th"},
140 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
141 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
142 { "mulelao-1", { 0x0E81 }, "lo"},
143 { "unicode-sip", { 0x20000 }},
147 /* Dirty hack for handing ADSTYLE property.
149 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
150 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
151 "Oblique", "Italic", or any non-normal SWIDTH property names
152 (e.g. SemiCondensed) are appended. In addition, if there's no
153 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
154 "Regular" is used for FC_STYLE (see the function
155 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
157 Unfortunately this behavior is not documented, so the following
158 code may fail if FreeType changes the behavior in the future. */
161 get_adstyle_property (FcPattern
*p
)
166 if (FcPatternGetString (p
, FC_STYLE
, 0, (FcChar8
**) &str
) != FcResultMatch
)
168 for (end
= str
; *end
&& *end
!= ' '; end
++);
171 char *newstr
= alloca (end
- str
+ 1);
172 memcpy (newstr
, str
, end
- str
);
173 newstr
[end
- str
] = '\0';
174 end
= newstr
+ (end
- str
);
177 if (xstrcasecmp (str
, "Regular") == 0
178 || xstrcasecmp (str
, "Bold") == 0
179 || xstrcasecmp (str
, "Oblique") == 0
180 || xstrcasecmp (str
, "Italic") == 0)
182 adstyle
= font_intern_prop (str
, end
- str
, 1);
183 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
189 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
191 Lisp_Object key
, cache
, entity
;
198 if (FcPatternGetString (p
, FC_FILE
, 0, (FcChar8
**) &file
) != FcResultMatch
)
200 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
203 key
= Fcons (make_unibyte_string ((char *) file
, strlen ((char *) file
)),
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
));
216 entity
= font_make_entity ();
217 XSETCAR (cache
, entity
);
219 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
220 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
222 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
223 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
224 if (FcPatternGetString (p
, FC_FAMILY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
225 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
226 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
228 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
229 numeric
= FC_WEIGHT_MEDIUM
;
230 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
232 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
235 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
237 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
239 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
241 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
243 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
246 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
247 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
248 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
249 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
252 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
254 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
257 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
258 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
262 /* As this font is not scalable, parhaps this is a BDF or PCF
266 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
267 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
268 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
272 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
273 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
274 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
275 FT_Done_Face (ft_face
);
279 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
280 font_put_extra (entity
, QCfont_entity
, key
);
285 static Lisp_Object ftfont_generic_family_list
;
288 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
295 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
296 if (EQ (family
, Qmono
))
298 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
299 family
= Qsans_serif
;
300 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
303 if (! EQ (XCDR (slot
), Qt
))
305 pattern
= FcPatternDuplicate (pattern
);
308 FcPatternDel (pattern
, FC_FOUNDRY
);
309 FcPatternDel (pattern
, FC_FAMILY
);
310 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
311 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
313 /* This is to avoid the effect of locale. */
314 static const FcChar8 lang
[] = "en";
315 langset
= FcLangSetCreate ();
316 FcLangSetAdd (langset
, lang
);
317 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
318 FcLangSetDestroy (langset
);
320 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
321 FcDefaultSubstitute (pattern
);
322 match
= FcFontMatch (NULL
, pattern
, &result
);
327 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
328 family
= intern ((char *) fam
);
332 XSETCDR (slot
, family
);
333 if (match
) FcPatternDestroy (match
);
335 if (pattern
) FcPatternDestroy (pattern
);
339 struct ftfont_cache_data
342 FcCharSet
*fc_charset
;
346 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
348 Lisp_Object cache
, val
, entity
;
349 struct ftfont_cache_data
*cache_data
;
351 if (FONT_ENTITY_P (key
))
354 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
355 xassert (CONSP (val
));
361 if (NILP (ft_face_cache
))
364 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
367 if (NILP (ft_face_cache
))
373 ft_face_cache
= Fmake_hash_table (2, args
);
375 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
376 cache_data
->ft_face
= NULL
;
377 cache_data
->fc_charset
= NULL
;
378 val
= make_save_value (NULL
, 0);
379 XSAVE_VALUE (val
)->integer
= 0;
380 XSAVE_VALUE (val
)->pointer
= cache_data
;
381 cache
= Fcons (Qnil
, val
);
382 Fputhash (key
, cache
, ft_face_cache
);
387 cache_data
= XSAVE_VALUE (val
)->pointer
;
390 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
393 if (cache_for
== FTFONT_CACHE_FOR_FACE
394 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
396 char *filename
= SSDATA (XCAR (key
));
397 int idx
= XINT (XCDR (key
));
399 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
402 && FT_Init_FreeType (&ft_library
) != 0)
404 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
410 FcPattern
*pat
= NULL
;
411 FcFontSet
*fontset
= NULL
;
412 FcObjectSet
*objset
= NULL
;
413 FcCharSet
*charset
= NULL
;
415 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
416 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
419 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
422 fontset
= FcFontList (NULL
, pat
, objset
);
425 if (fontset
&& fontset
->nfont
> 0
426 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
429 cache_data
->fc_charset
= FcCharSetCopy (charset
);
431 cache_data
->fc_charset
= FcCharSetCreate ();
435 FcFontSetDestroy (fontset
);
437 FcObjectSetDestroy (objset
);
439 FcPatternDestroy (pat
);
446 ftfont_get_fc_charset (Lisp_Object entity
)
448 Lisp_Object val
, cache
;
449 struct ftfont_cache_data
*cache_data
;
451 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
453 cache_data
= XSAVE_VALUE (val
)->pointer
;
454 return cache_data
->fc_charset
;
459 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
463 if (ftfont_info
->otf
)
464 return ftfont_info
->otf
;
465 if (! ftfont_info
->maybe_otf
)
467 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
468 if (! otf
|| OTF_get_table (otf
, "head") < 0)
472 ftfont_info
->maybe_otf
= 0;
475 ftfont_info
->otf
= otf
;
478 #endif /* HAVE_LIBOTF */
480 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
481 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
482 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
483 static Lisp_Object
ftfont_list_family (Lisp_Object
);
484 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
485 static void ftfont_close (FRAME_PTR
, struct font
*);
486 static int ftfont_has_char (Lisp_Object
, int);
487 static unsigned ftfont_encode_char (struct font
*, int);
488 static int ftfont_text_extents (struct font
*, unsigned *, int,
489 struct font_metrics
*);
490 static int ftfont_get_bitmap (struct font
*, unsigned,
491 struct font_bitmap
*, int);
492 static int ftfont_anchor_point (struct font
*, unsigned, int,
495 static Lisp_Object
ftfont_otf_capability (struct font
*);
496 # ifdef HAVE_M17N_FLT
497 static Lisp_Object
ftfont_shape (Lisp_Object
);
501 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
502 static int ftfont_variation_glyphs (struct font
*, int c
,
503 unsigned variations
[256]);
504 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
506 struct font_driver ftfont_driver
=
509 0, /* case insensitive */
514 NULL
, /* free_entity */
517 /* We can't draw a text without device dependent functions. */
518 NULL
, /* prepare_face */
519 NULL
, /* done_face */
523 /* We can't draw a text without device dependent functions. */
526 NULL
, /* get_bitmap */
527 NULL
, /* free_bitmap */
528 NULL
, /* get_outline */
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 (FRAME_PTR f
)
557 return freetype_font_cache
;
561 ftfont_get_charset (Lisp_Object registry
)
563 char *str
= SSDATA (SYMBOL_NAME (registry
));
564 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
568 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
572 else if (str
[i
] == '*')
579 regexp
= make_unibyte_string (re
, j
);
580 for (i
= 0; fc_charset_table
[i
].name
; i
++)
581 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
583 if (! fc_charset_table
[i
].name
)
585 if (! fc_charset_table
[i
].fc_charset
)
587 FcCharSet
*charset
= FcCharSetCreate ();
588 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
592 for (j
= 0; uniquifier
[j
]; j
++)
593 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
595 FcCharSetDestroy (charset
);
598 fc_charset_table
[i
].fc_charset
= charset
;
606 unsigned int script_tag
, langsys_tag
;
608 unsigned int *features
[2];
611 #define OTF_SYM_TAG(SYM, TAG) \
613 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
614 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
617 #define OTF_TAG_STR(TAG, P) \
619 (P)[0] = (char) (TAG >> 24); \
620 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
621 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
622 (P)[3] = (char) (TAG & 0xFF); \
627 #define OTF_TAG_SYM(SYM, TAG) \
631 OTF_TAG_STR (TAG, str); \
632 (SYM) = font_intern_prop (str, 4, 1); \
637 static struct OpenTypeSpec
*
638 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
640 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
646 spec
->script
= XCAR (otf_spec
);
647 if (! NILP (spec
->script
))
649 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
650 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
651 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
652 spec
->script
= XCDR (val
);
657 spec
->script_tag
= 0x44464C54; /* "DFLT" */
658 otf_spec
= XCDR (otf_spec
);
659 spec
->langsys_tag
= 0;
660 if (! NILP (otf_spec
))
662 val
= XCAR (otf_spec
);
664 OTF_SYM_TAG (val
, spec
->langsys_tag
);
665 otf_spec
= XCDR (otf_spec
);
667 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
668 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
672 val
= XCAR (otf_spec
);
676 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
677 if (! spec
->features
[i
])
679 if (i
> 0 && spec
->features
[0])
680 free (spec
->features
[0]);
684 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
686 if (NILP (XCAR (val
)))
692 OTF_SYM_TAG (XCAR (val
), tag
);
693 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
696 spec
->nfeatures
[i
] = j
;
702 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
704 Lisp_Object tmp
, extra
;
705 FcPattern
*pattern
= NULL
;
706 FcCharSet
*charset
= NULL
;
707 FcLangSet
*langset
= NULL
;
711 Lisp_Object script
= Qnil
;
712 Lisp_Object registry
;
715 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
717 /* Fontconfig doesn't support reverse-italic/obligue. */
720 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
721 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
722 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
723 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
726 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
728 || EQ (registry
, Qascii_0
)
729 || EQ (registry
, Qiso10646_1
)
730 || EQ (registry
, Qunicode_bmp
))
736 fc_charset_idx
= ftfont_get_charset (registry
);
737 if (fc_charset_idx
< 0)
739 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
740 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
741 lang
= (FcChar8
*) *langname
;
744 langset
= FcLangSetCreate ();
747 FcLangSetAdd (langset
, lang
);
752 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
753 CONSP (extra
); extra
= XCDR (extra
))
755 Lisp_Object key
, val
;
757 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
763 else if (EQ (key
, QClang
))
766 langset
= FcLangSetCreate ();
771 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
775 for (; CONSP (val
); val
= XCDR (val
))
776 if (SYMBOLP (XCAR (val
))
777 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
780 else if (EQ (key
, QCotf
))
784 *otspec
= ftfont_get_open_type_spec (val
);
787 strcat (otlayout
, "otlayout:");
788 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
789 script
= (*otspec
)->script
;
792 else if (EQ (key
, QCscript
))
794 else if (EQ (key
, QCscalable
))
795 scalable
= ! NILP (val
);
798 if (! NILP (script
) && ! charset
)
800 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
802 if (CONSP (chars
) && CONSP (CDR (chars
)))
804 charset
= FcCharSetCreate ();
807 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
808 if (CHARACTERP (XCAR (chars
))
809 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
814 pattern
= FcPatternCreate ();
817 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
819 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
821 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
823 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
826 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
829 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
832 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
835 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
841 /* We come here because of unexpected error in fontconfig API call
842 (usually insufficient memory). */
845 FcPatternDestroy (pattern
);
850 if ((*otspec
)->nfeatures
[0] > 0)
851 free ((*otspec
)->features
[0]);
852 if ((*otspec
)->nfeatures
[1] > 0)
853 free ((*otspec
)->features
[1]);
859 if (langset
) FcLangSetDestroy (langset
);
860 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
865 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
867 Lisp_Object val
= Qnil
, family
, adstyle
;
870 FcFontSet
*fontset
= NULL
;
871 FcObjectSet
*objset
= NULL
;
873 Lisp_Object chars
= Qnil
;
874 char otlayout
[15]; /* For "otlayout:XXXX" */
875 struct OpenTypeSpec
*otspec
= NULL
;
877 const char *langname
= NULL
;
879 if (! fc_initialized
)
885 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
888 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
890 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
893 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
894 if (CONSP (val
) && VECTORP (XCDR (val
)))
899 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
900 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
901 family
= AREF (spec
, FONT_FAMILY_INDEX
);
904 Lisp_Object resolved
;
906 resolved
= ftfont_resolve_generic_family (family
, pattern
);
907 if (! NILP (resolved
))
909 FcPatternDel (pattern
, FC_FAMILY
);
910 if (! FcPatternAddString (pattern
, FC_FAMILY
,
911 SYMBOL_FcChar8 (resolved
)))
915 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
916 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
918 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
919 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
920 FC_STYLE
, FC_FILE
, FC_INDEX
,
923 #endif /* FC_CAPABILITY */
931 FcObjectSetAdd (objset
, FC_CHARSET
);
933 fontset
= FcFontList (NULL
, pattern
, objset
);
934 if (! fontset
|| fontset
->nfont
== 0)
937 /* Need fix because this finds any fonts. */
938 if (fontset
->nfont
== 0 && ! NILP (family
))
940 /* Try maching with configuration. For instance, the
941 configuration may specify "Nimbus Mono L" as an alias of
943 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
944 SYMBOL_FcChar8 (family
), NULL
);
947 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
950 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
953 FcPatternDel (pattern
, FC_FAMILY
);
954 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
955 FcFontSetDestroy (fontset
);
956 fontset
= FcFontList (NULL
, pattern
, objset
);
957 if (fontset
&& fontset
->nfont
> 0)
963 for (i
= 0; i
< fontset
->nfont
; i
++)
971 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
982 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
984 || ! strstr ((char *) this, otlayout
))
987 #endif /* FC_CAPABILITY */
994 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
997 otf
= OTF_open ((char *) file
);
1000 if (OTF_check_features (otf
, 1,
1001 otspec
->script_tag
, otspec
->langsys_tag
,
1002 otspec
->features
[0],
1003 otspec
->nfeatures
[0]) != 1
1004 || OTF_check_features (otf
, 0,
1005 otspec
->script_tag
, otspec
->langsys_tag
,
1006 otspec
->features
[1],
1007 otspec
->nfeatures
[1]) != 1)
1010 #endif /* HAVE_LIBOTF */
1011 if (VECTORP (chars
))
1015 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1018 for (j
= 0; j
< ASIZE (chars
); j
++)
1019 if (NATNUMP (AREF (chars
, j
))
1020 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1022 if (j
== ASIZE (chars
))
1025 if (! NILP (adstyle
) || langname
)
1027 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1029 if (! NILP (adstyle
)
1030 && (NILP (this_adstyle
)
1031 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1032 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1035 && ! NILP (this_adstyle
)
1036 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1039 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1040 AREF (spec
, FONT_EXTRA_INDEX
));
1041 if (! NILP (entity
))
1042 val
= Fcons (entity
, val
);
1044 val
= Fnreverse (val
);
1048 /* We come here because of unexpected error in fontconfig API call
1049 (usually insufficient memory). */
1053 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1054 if (objset
) FcObjectSetDestroy (objset
);
1055 if (fontset
) FcFontSetDestroy (fontset
);
1056 if (pattern
) FcPatternDestroy (pattern
);
1061 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1063 Lisp_Object entity
= Qnil
;
1064 FcPattern
*pattern
, *match
= NULL
;
1066 char otlayout
[15]; /* For "otlayout:XXXX" */
1067 struct OpenTypeSpec
*otspec
= NULL
;
1068 const char *langname
= NULL
;
1070 if (! fc_initialized
)
1076 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1080 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1084 value
.type
= FcTypeDouble
;
1085 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1086 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1088 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1090 FcDefaultSubstitute (pattern
);
1091 match
= FcFontMatch (NULL
, pattern
, &result
);
1094 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1095 FcPatternDestroy (match
);
1096 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1097 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1098 ftfont_generic_family_list
))
1099 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1100 AREF (entity
, FONT_FAMILY_INDEX
))))
1104 FcPatternDestroy (pattern
);
1106 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1111 ftfont_list_family (Lisp_Object frame
)
1113 Lisp_Object list
= Qnil
;
1114 FcPattern
*pattern
= NULL
;
1115 FcFontSet
*fontset
= NULL
;
1116 FcObjectSet
*objset
= NULL
;
1119 if (! fc_initialized
)
1125 pattern
= FcPatternCreate ();
1128 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1131 fontset
= FcFontList (NULL
, pattern
, objset
);
1135 for (i
= 0; i
< fontset
->nfont
; i
++)
1137 FcPattern
*pat
= fontset
->fonts
[i
];
1140 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1141 list
= Fcons (intern ((char *) str
), list
);
1145 if (objset
) FcObjectSetDestroy (objset
);
1146 if (fontset
) FcFontSetDestroy (fontset
);
1147 if (pattern
) FcPatternDestroy (pattern
);
1154 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1156 struct ftfont_info
*ftfont_info
;
1158 struct ftfont_cache_data
*cache_data
;
1162 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1169 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1173 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1176 filename
= XCAR (val
);
1179 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1180 ft_face
= cache_data
->ft_face
;
1181 if (XSAVE_VALUE (val
)->integer
> 0)
1183 /* FT_Face in this cache is already used by the different size. */
1184 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1186 if (FT_Activate_Size (ft_size
) != 0)
1188 FT_Done_Size (ft_size
);
1192 XSAVE_VALUE (val
)->integer
++;
1193 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1196 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1198 if (XSAVE_VALUE (val
)->integer
== 0)
1199 FT_Done_Face (ft_face
);
1203 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1204 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1205 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1207 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1208 len
= font_unparse_fcname (entity
, size
, name
, 256);
1210 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1212 ASET (font_object
, FONT_FULLNAME_INDEX
,
1213 AREF (font_object
, FONT_NAME_INDEX
));
1214 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1215 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, 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
;
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 (FRAME_PTR f
, 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 xassert (CONSP (cache
));
1307 (XSAVE_VALUE (val
)->integer
)--;
1308 if (XSAVE_VALUE (val
)->integer
== 0)
1310 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
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
, int nglyphs
, struct font_metrics
*metrics
)
1367 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1368 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1372 if (ftfont_info
->ft_size
!= ft_face
->size
)
1373 FT_Activate_Size (ftfont_info
->ft_size
);
1375 memset (metrics
, 0, sizeof (struct font_metrics
));
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
;
1386 metrics
->lbearing
= m
->horiBearingX
>> 6;
1387 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1388 metrics
->ascent
= m
->horiBearingY
>> 6;
1389 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1395 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1396 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1397 if (metrics
->rbearing
1398 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1400 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1401 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1402 metrics
->ascent
= m
->horiBearingY
>> 6;
1403 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1404 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1406 width
+= m
->horiAdvance
>> 6;
1410 width
+= font
->space_width
;
1414 metrics
->width
= width
;
1420 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1422 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1423 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1424 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1426 if (ftfont_info
->ft_size
!= ft_face
->size
)
1427 FT_Activate_Size (ftfont_info
->ft_size
);
1428 if (bits_per_pixel
== 1)
1430 #ifdef FT_LOAD_TARGET_MONO
1431 load_flags
|= FT_LOAD_TARGET_MONO
;
1433 load_flags
|= FT_LOAD_MONOCHROME
;
1436 else if (bits_per_pixel
!= 8)
1437 /* We don't support such a rendering. */
1440 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1442 bitmap
->bits_per_pixel
1443 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1444 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1445 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1446 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1448 if (bitmap
->bits_per_pixel
< 0)
1449 /* We don't suport that kind of pixel mode. */
1451 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1452 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1453 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1454 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1455 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1456 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1457 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1458 bitmap
->extra
= NULL
;
1464 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1467 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1468 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1470 if (ftfont_info
->ft_size
!= ft_face
->size
)
1471 FT_Activate_Size (ftfont_info
->ft_size
);
1472 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1474 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1476 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1478 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1479 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1486 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1488 Lisp_Object scripts
, langsyses
, features
, sym
;
1491 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1493 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1495 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1497 OTF_LangSys
*otf_langsys
;
1500 otf_langsys
= otf_script
->LangSys
+ j
;
1501 else if (otf_script
->DefaultLangSysOffset
)
1502 otf_langsys
= &otf_script
->DefaultLangSys
;
1506 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1508 l
= otf_langsys
->FeatureIndex
[k
];
1509 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1511 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1512 features
= Fcons (sym
, features
);
1515 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1518 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1521 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1522 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1530 ftfont_otf_capability (struct font
*font
)
1532 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1533 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1534 Lisp_Object gsub_gpos
;
1538 gsub_gpos
= Fcons (Qnil
, Qnil
);
1539 if (OTF_get_table (otf
, "GSUB") == 0
1540 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1541 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1542 if (OTF_get_table (otf
, "GPOS") == 0
1543 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1544 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1548 #ifdef HAVE_M17N_FLT
1550 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1551 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1552 /* We can use the new feature of libotf and m17n-flt to handle the
1553 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1554 some Agian scripts. */
1555 #define M17N_FLT_USE_NEW_FEATURE
1568 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1571 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1572 FT_Face ft_face
= flt_font_ft
->ft_face
;
1575 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1578 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1580 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1586 /* Operators for 26.6 fixed fractional pixel format */
1588 #define FLOOR(x) ((x) & -64)
1589 #define CEIL(x) (((x)+63) & -64)
1590 #define ROUND(x) (((x)+32) & -64)
1593 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1596 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1597 FT_Face ft_face
= flt_font_ft
->ft_face
;
1600 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1603 if (g
->code
!= FONT_INVALID_CODE
)
1605 FT_Glyph_Metrics
*m
;
1606 int lbearing
, rbearing
, ascent
, descent
, xadv
;
1608 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1610 m
= &ft_face
->glyph
->metrics
;
1611 if (flt_font_ft
->matrix
)
1616 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1617 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1618 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1619 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1620 for (i
= 0; i
< 4; i
++)
1621 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1622 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1623 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1624 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1625 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1629 g
->lbearing
= FLOOR (m
->horiBearingX
);
1630 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1631 g
->ascent
= CEIL (m
->horiBearingY
);
1632 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1634 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1639 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1640 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1641 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1650 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1652 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1654 #define FEATURE_ANY(IDX) \
1655 (spec->features[IDX] \
1656 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1658 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1659 OTF
*otf
= flt_font_ft
->otf
;
1663 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1664 /* Return 1 iff any of GSUB or GPOS support the script (and language). */
1666 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1668 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1671 for (i
= 0; i
< 2; i
++)
1672 if (! FEATURE_ANY (i
))
1674 if (FEATURE_NONE (i
))
1677 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1682 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1685 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1691 for (n
= 1; spec
->features
[i
][n
]; n
++);
1692 tags
= alloca (sizeof (OTF_Tag
) * n
);
1693 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1695 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1698 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1700 tags
[n
] = spec
->features
[i
][n
];
1702 #ifdef M17N_FLT_USE_NEW_FEATURE
1703 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1704 tags
, n
- negative
) != 1)
1706 #else /* not M17N_FLT_USE_NEW_FEATURE */
1707 if (n
- negative
> 0
1708 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1709 tags
, n
- negative
) != 1)
1711 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1718 #define DEVICE_DELTA(table, size) \
1719 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1720 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1724 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1725 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1727 if (anchor
->AnchorFormat
== 2)
1729 FT_Outline
*outline
;
1730 int ap
= anchor
->f
.f1
.AnchorPoint
;
1732 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1733 outline
= &ft_face
->glyph
->outline
;
1734 if (ap
< outline
->n_points
)
1736 *x
= outline
->points
[ap
].x
<< 6;
1737 *y
= outline
->points
[ap
].y
<< 6;
1740 else if (anchor
->AnchorFormat
== 3)
1742 if (anchor
->f
.f2
.XDeviceTable
.offset
1743 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1744 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1745 if (anchor
->f
.f2
.YDeviceTable
.offset
1746 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1747 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1751 static OTF_GlyphString otf_gstring
;
1754 setup_otf_gstring (int size
)
1756 if (otf_gstring
.size
== 0)
1758 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1759 otf_gstring
.size
= size
;
1761 else if (otf_gstring
.size
< size
)
1763 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1764 sizeof (OTF_Glyph
) * size
);
1765 otf_gstring
.size
= size
;
1767 otf_gstring
.used
= size
;
1768 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1771 #ifdef M17N_FLT_USE_NEW_FEATURE
1773 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1774 #define PACK_OTF_TAG(TAG) \
1775 ((((TAG) & 0x7F000000) >> 3) \
1776 | (((TAG) & 0x7F0000) >> 2) \
1777 | (((TAG) & 0x7F00) >> 1) \
1780 /* Assuming that FONT is an OpenType font, apply OpenType features
1781 specified in SPEC on glyphs between FROM and TO of IN, and record
1782 the lastly applied feature in each glyph of IN. If OUT is not
1783 NULL, append the resulting glyphs to OUT while storing glyph
1784 position adjustment information in ADJUSTMENT. */
1787 ftfont_drive_otf (MFLTFont
*font
,
1789 MFLTGlyphString
*in
,
1792 MFLTGlyphString
*out
,
1793 MFLTGlyphAdjustment
*adjustment
)
1795 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1796 FT_Face ft_face
= flt_font_ft
->ft_face
;
1797 OTF
*otf
= flt_font_ft
->otf
;
1798 int len
= to
- from
;
1801 char script
[5], *langsys
= NULL
;
1802 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1803 OTF_Feature
*features
;
1807 OTF_tag_name (spec
->script
, script
);
1810 langsys
= alloca (5);
1811 OTF_tag_name (spec
->langsys
, langsys
);
1813 for (i
= 0; i
< 2; i
++)
1817 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1819 for (j
= 0; spec
->features
[i
][j
]; j
++);
1821 p
= gsub_features
= alloca (6 * j
);
1823 p
= gpos_features
= alloca (6 * j
);
1824 for (j
= 0; spec
->features
[i
][j
]; j
++)
1826 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1827 *p
++ = '*', *p
++ = ',';
1830 OTF_tag_name (spec
->features
[i
][j
], p
);
1839 setup_otf_gstring (len
);
1840 for (i
= 0; i
< len
; i
++)
1842 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1843 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1846 OTF_drive_gdef (otf
, &otf_gstring
);
1847 gidx
= out
? out
->used
: from
;
1849 if (gsub_features
&& out
)
1851 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1854 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1856 features
= otf
->gsub
->FeatureList
.Feature
;
1857 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1860 int min_from
, max_to
;
1862 int feature_idx
= otfg
->positioning_type
>> 4;
1864 g
= out
->glyphs
+ out
->used
;
1865 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1866 if (g
->code
!= otfg
->glyph_id
)
1869 g
->code
= otfg
->glyph_id
;
1875 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1877 /* OTFG substitutes multiple glyphs in IN. */
1878 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1879 j
<= from
+ otfg
->f
.index
.to
; j
++)
1881 if (min_from
> in
->glyphs
[j
].from
)
1882 min_from
= in
->glyphs
[j
].from
;
1883 if (max_to
< in
->glyphs
[j
].to
)
1884 max_to
= in
->glyphs
[j
].to
;
1891 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1892 tag
= PACK_OTF_TAG (tag
);
1893 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1895 for (i
++, otfg
++; (i
< otf_gstring
.used
1896 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1899 g
= out
->glyphs
+ out
->used
;
1900 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1901 if (g
->code
!= otfg
->glyph_id
)
1904 g
->code
= otfg
->glyph_id
;
1907 feature_idx
= otfg
->positioning_type
>> 4;
1910 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1911 tag
= PACK_OTF_TAG (tag
);
1912 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1918 else if (gsub_features
)
1920 /* Just for checking which features will be applied. */
1921 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1924 features
= otf
->gsub
->FeatureList
.Feature
;
1925 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1928 int feature_idx
= otfg
->positioning_type
>> 4;
1932 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1933 tag
= PACK_OTF_TAG (tag
);
1934 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1936 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1937 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1944 if (out
->allocated
< out
->used
+ len
)
1946 for (i
= 0; i
< len
; i
++)
1947 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1950 if (gpos_features
&& out
)
1952 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1953 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1955 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1958 features
= otf
->gpos
->FeatureList
.Feature
;
1959 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1960 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1961 x_scale
= ft_face
->size
->metrics
.x_scale
;
1962 y_scale
= ft_face
->size
->metrics
.y_scale
;
1964 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1965 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1968 int feature_idx
= otfg
->positioning_type
>> 4;
1972 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1973 tag
= PACK_OTF_TAG (tag
);
1974 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1977 if (! otfg
->glyph_id
)
1979 switch (otfg
->positioning_type
& 0xF)
1983 case 1: /* Single */
1986 int format
= otfg
->f
.f1
.format
;
1988 if (format
& OTF_XPlacement
)
1990 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1991 if (format
& OTF_XPlaDevice
)
1993 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1994 if (format
& OTF_YPlacement
)
1996 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
1997 if (format
& OTF_YPlaDevice
)
1999 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2000 if (format
& OTF_XAdvance
)
2002 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2003 if (format
& OTF_XAdvDevice
)
2005 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2006 if (format
& OTF_YAdvance
)
2008 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2009 if (format
& OTF_YAdvDevice
)
2011 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2012 adjustment
[i
].set
= 1;
2015 case 3: /* Cursive */
2016 /* Not yet supported. */
2018 case 4: /* Mark-to-Base */
2019 case 5: /* Mark-to-Ligature */
2023 goto label_adjust_anchor
;
2024 default: /* i.e. case 6 Mark-to-Mark */
2029 label_adjust_anchor
:
2031 int base_x
, base_y
, mark_x
, mark_y
;
2032 int this_from
, this_to
;
2034 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2035 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2036 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2037 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2039 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2040 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2041 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2042 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2043 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2044 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2045 adjustment
[i
].xoff
= (base_x
- mark_x
);
2046 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2047 adjustment
[i
].back
= (g
- prev
);
2048 adjustment
[i
].xadv
= 0;
2049 adjustment
[i
].advance_is_absolute
= 1;
2050 adjustment
[i
].set
= 1;
2051 this_from
= g
->from
;
2053 for (j
= 0; prev
+ j
< g
; j
++)
2055 if (this_from
> prev
[j
].from
)
2056 this_from
= prev
[j
].from
;
2057 if (this_to
< prev
[j
].to
)
2058 this_to
= prev
[j
].to
;
2060 for (; prev
<= g
; prev
++)
2062 prev
->from
= this_from
;
2067 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2069 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2075 else if (gpos_features
)
2077 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2080 features
= otf
->gpos
->FeatureList
.Feature
;
2081 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2083 if (otfg
->positioning_type
& 0xF)
2085 int feature_idx
= otfg
->positioning_type
>> 4;
2089 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2090 tag
= PACK_OTF_TAG (tag
);
2091 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2093 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2094 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2104 if (out
->allocated
< out
->used
+ len
)
2106 font
->get_metrics (font
, in
, from
, to
);
2107 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2108 sizeof (MFLTGlyph
) * len
);
2114 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2115 MFLTGlyphString
*in
, int from
, int to
)
2117 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2120 #else /* not M17N_FLT_USE_NEW_FEATURE */
2123 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2125 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2127 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2128 FT_Face ft_face
= flt_font_ft
->ft_face
;
2129 OTF
*otf
= flt_font_ft
->otf
;
2130 int len
= to
- from
;
2133 char script
[5], *langsys
= NULL
;
2134 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2138 OTF_tag_name (spec
->script
, script
);
2141 langsys
= alloca (5);
2142 OTF_tag_name (spec
->langsys
, langsys
);
2144 for (i
= 0; i
< 2; i
++)
2148 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2150 for (j
= 0; spec
->features
[i
][j
]; j
++);
2152 p
= gsub_features
= alloca (6 * j
);
2154 p
= gpos_features
= alloca (6 * j
);
2155 for (j
= 0; spec
->features
[i
][j
]; j
++)
2157 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2158 *p
++ = '*', *p
++ = ',';
2161 OTF_tag_name (spec
->features
[i
][j
], p
);
2170 setup_otf_gstring (len
);
2171 for (i
= 0; i
< len
; i
++)
2173 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2174 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2177 OTF_drive_gdef (otf
, &otf_gstring
);
2182 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2185 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2187 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2190 int min_from
, max_to
;
2193 g
= out
->glyphs
+ out
->used
;
2194 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2195 if (g
->code
!= otfg
->glyph_id
)
2198 g
->code
= otfg
->glyph_id
;
2204 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2206 /* OTFG substitutes multiple glyphs in IN. */
2207 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2208 j
<= from
+ otfg
->f
.index
.to
; j
++)
2210 if (min_from
> in
->glyphs
[j
].from
)
2211 min_from
= in
->glyphs
[j
].from
;
2212 if (max_to
< in
->glyphs
[j
].to
)
2213 max_to
= in
->glyphs
[j
].to
;
2218 for (i
++, otfg
++; (i
< otf_gstring
.used
2219 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2222 g
= out
->glyphs
+ out
->used
;
2223 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2224 if (g
->code
!= otfg
->glyph_id
)
2227 g
->code
= otfg
->glyph_id
;
2236 if (out
->allocated
< out
->used
+ len
)
2238 for (i
= 0; i
< len
; i
++)
2239 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2244 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2245 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2247 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2251 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2252 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2253 x_scale
= ft_face
->size
->metrics
.x_scale
;
2254 y_scale
= ft_face
->size
->metrics
.y_scale
;
2256 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2257 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2261 if (! otfg
->glyph_id
)
2263 switch (otfg
->positioning_type
)
2267 case 1: /* Single */
2270 int format
= otfg
->f
.f1
.format
;
2272 if (format
& OTF_XPlacement
)
2274 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2275 if (format
& OTF_XPlaDevice
)
2277 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2278 if (format
& OTF_YPlacement
)
2280 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2281 if (format
& OTF_YPlaDevice
)
2283 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2284 if (format
& OTF_XAdvance
)
2286 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2287 if (format
& OTF_XAdvDevice
)
2289 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2290 if (format
& OTF_YAdvance
)
2292 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2293 if (format
& OTF_YAdvDevice
)
2295 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2296 adjustment
[i
].set
= 1;
2299 case 3: /* Cursive */
2300 /* Not yet supported. */
2302 case 4: /* Mark-to-Base */
2303 case 5: /* Mark-to-Ligature */
2307 goto label_adjust_anchor
;
2308 default: /* i.e. case 6 Mark-to-Mark */
2313 label_adjust_anchor
:
2315 int base_x
, base_y
, mark_x
, mark_y
;
2316 int this_from
, this_to
;
2318 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2319 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2320 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2321 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2323 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2324 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2325 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2326 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2327 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2328 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2329 adjustment
[i
].xoff
= (base_x
- mark_x
);
2330 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2331 adjustment
[i
].back
= (g
- prev
);
2332 adjustment
[i
].xadv
= 0;
2333 adjustment
[i
].advance_is_absolute
= 1;
2334 adjustment
[i
].set
= 1;
2335 this_from
= g
->from
;
2337 for (j
= 0; prev
+ j
< g
; j
++)
2339 if (this_from
> prev
[j
].from
)
2340 this_from
= prev
[j
].from
;
2341 if (this_to
< prev
[j
].to
)
2342 this_to
= prev
[j
].to
;
2344 for (; prev
<= g
; prev
++)
2346 prev
->from
= this_from
;
2351 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2353 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2362 if (out
->allocated
< out
->used
+ len
)
2364 font
->get_metrics (font
, in
, from
, to
);
2365 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2366 sizeof (MFLTGlyph
) * len
);
2371 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2373 static MFLTGlyphString gstring
;
2375 static int m17n_flt_initialized
;
2378 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2379 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2381 EMACS_UINT len
= LGSTRING_GLYPH_LEN (lgstring
);
2383 struct MFLTFontFT flt_font_ft
;
2385 int with_variation_selector
= 0;
2387 if (! m17n_flt_initialized
)
2390 #ifdef M17N_FLT_USE_NEW_FEATURE
2391 mflt_enable_new_feature
= 1;
2392 mflt_try_otf
= ftfont_try_otf
;
2393 #endif /* M17N_FLT_USE_NEW_FEATURE */
2394 m17n_flt_initialized
= 1;
2397 for (i
= 0; i
< len
; i
++)
2399 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2404 c
= LGLYPH_CHAR (g
);
2405 if (CHAR_VARIATION_SELECTOR_P (c
))
2406 with_variation_selector
++;
2409 if (with_variation_selector
)
2411 setup_otf_gstring (len
);
2412 for (i
= 0; i
< len
; i
++)
2414 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2416 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2417 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2418 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2420 OTF_drive_cmap (otf
, &otf_gstring
);
2421 for (i
= 0; i
< otf_gstring
.used
; i
++)
2423 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2424 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2425 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2427 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2428 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2429 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2431 if (len
> otf_gstring
.used
)
2433 len
= otf_gstring
.used
;
2434 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2438 if (gstring
.allocated
== 0)
2440 gstring
.allocated
= len
* 2;
2441 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2442 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2444 else if (gstring
.allocated
< len
* 2)
2446 gstring
.allocated
= len
* 2;
2447 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2448 sizeof (MFLTGlyph
) * gstring
.allocated
);
2450 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2451 for (i
= 0; i
< len
; i
++)
2453 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2455 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2456 if (with_variation_selector
)
2458 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2459 gstring
.glyphs
[i
].encoded
= 1;
2467 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2470 flt_font_ft
.flt_font
.family
= Mnil
;
2472 flt_font_ft
.flt_font
.family
2473 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2475 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2476 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2477 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2478 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2479 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2480 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2481 flt_font_ft
.flt_font
.internal
= NULL
;
2482 flt_font_ft
.font
= font
;
2483 flt_font_ft
.ft_face
= ft_face
;
2484 flt_font_ft
.otf
= otf
;
2485 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2487 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2488 /* A little bit ad hoc. Perhaps, shaper must get script and
2489 language information, and select a proper flt for them
2491 flt
= mflt_get (msymbol ("combining"));
2492 for (i
= 0; i
< 3; i
++)
2494 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2497 gstring
.allocated
+= gstring
.allocated
;
2498 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2499 sizeof (MFLTGlyph
) * gstring
.allocated
);
2501 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2503 for (i
= 0; i
< gstring
.used
; i
++)
2505 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2507 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2508 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2511 for (i
= 0; i
< gstring
.used
; i
++)
2513 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2514 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2518 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2519 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2521 LGLYPH_SET_FROM (lglyph
, g
->from
);
2522 LGLYPH_SET_TO (lglyph
, g
->to
);
2523 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2524 LGLYPH_SET_CODE (lglyph
, g
->code
);
2525 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2526 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2527 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2528 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2529 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2534 vec
= Fmake_vector (make_number (3), Qnil
);
2535 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2536 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2537 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2538 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2541 return make_number (i
);
2545 ftfont_shape (Lisp_Object lgstring
)
2548 struct ftfont_info
*ftfont_info
;
2551 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2552 ftfont_info
= (struct ftfont_info
*) font
;
2553 otf
= ftfont_get_otf (ftfont_info
);
2555 return make_number (0);
2556 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2557 &ftfont_info
->matrix
);
2560 #endif /* HAVE_M17N_FLT */
2562 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2565 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2567 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2568 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2572 return OTF_get_variation_glyphs (otf
, c
, variations
);
2575 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2576 #endif /* HAVE_LIBOTF */
2579 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2583 #ifdef FC_FONTFORMAT
2586 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2588 if (strcmp ((char *) str
, "TrueType") == 0)
2589 return intern ("truetype");
2590 if (strcmp ((char *) str
, "Type 1") == 0)
2591 return intern ("type1");
2592 if (strcmp ((char *) str
, "PCF") == 0)
2593 return intern ("pcf");
2594 if (strcmp ((char *) str
, "BDF") == 0)
2595 return intern ("bdf");
2597 #endif /* FC_FONTFORMAT */
2598 if (STRINGP (filename
))
2600 int len
= SBYTES (filename
);
2604 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2605 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2606 return intern ("truetype");
2607 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2608 return intern ("type1");
2609 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2610 return intern ("pcf");
2611 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2612 return intern ("bdf");
2615 return intern ("unknown");
2618 static const char *const ftfont_booleans
[] = {
2631 static const char *const ftfont_non_booleans
[] = {
2663 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2665 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2670 syms_of_ftfont (void)
2672 DEFSYM (Qfreetype
, "freetype");
2673 DEFSYM (Qmonospace
, "monospace");
2674 DEFSYM (Qsans_serif
, "sans-serif");
2675 DEFSYM (Qserif
, "serif");
2676 DEFSYM (Qmono
, "mono");
2677 DEFSYM (Qsans
, "sans");
2678 DEFSYM (Qsans__serif
, "sans serif");
2680 staticpro (&freetype_font_cache
);
2681 freetype_font_cache
= Fcons (Qt
, Qnil
);
2683 staticpro (&ftfont_generic_family_list
);
2684 ftfont_generic_family_list
2685 = Fcons (Fcons (Qmonospace
, Qt
),
2686 Fcons (Fcons (Qsans_serif
, Qt
),
2687 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2689 staticpro (&ft_face_cache
);
2690 ft_face_cache
= Qnil
;
2692 ftfont_driver
.type
= Qfreetype
;
2693 register_font_driver (&ftfont_driver
, NULL
);