1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010
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 *p
= alloca (end
- str
+ 1);
172 memcpy (p
, str
, end
- str
);
174 end
= p
+ (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, &index
) != FcResultMatch
)
203 key
= Fcons (make_unibyte_string ((char *) file
, strlen ((char *) file
)),
204 make_number (index
));
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
, index
, &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 langset
= FcLangSetCreate ();
315 FcLangSetAdd (langset
, "en");
316 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
317 FcLangSetDestroy (langset
);
319 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
320 FcDefaultSubstitute (pattern
);
321 match
= FcFontMatch (NULL
, pattern
, &result
);
326 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
327 family
= intern ((char *) fam
);
331 XSETCDR (slot
, family
);
332 if (match
) FcPatternDestroy (match
);
334 if (pattern
) FcPatternDestroy (pattern
);
338 struct ftfont_cache_data
341 FcCharSet
*fc_charset
;
345 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
347 Lisp_Object cache
, val
, entity
;
348 struct ftfont_cache_data
*cache_data
;
350 if (FONT_ENTITY_P (key
))
353 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
354 xassert (CONSP (val
));
360 if (NILP (ft_face_cache
))
363 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
366 if (NILP (ft_face_cache
))
372 ft_face_cache
= Fmake_hash_table (2, args
);
374 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
375 cache_data
->ft_face
= NULL
;
376 cache_data
->fc_charset
= NULL
;
377 val
= make_save_value (NULL
, 0);
378 XSAVE_VALUE (val
)->integer
= 0;
379 XSAVE_VALUE (val
)->pointer
= cache_data
;
380 cache
= Fcons (Qnil
, val
);
381 Fputhash (key
, cache
, ft_face_cache
);
386 cache_data
= XSAVE_VALUE (val
)->pointer
;
389 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
392 if (cache_for
== FTFONT_CACHE_FOR_FACE
393 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
395 char *filename
= (char *) SDATA (XCAR (key
));
396 int index
= XINT (XCDR (key
));
398 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
401 && FT_Init_FreeType (&ft_library
) != 0)
403 if (FT_New_Face (ft_library
, filename
, index
, &cache_data
->ft_face
)
409 FcPattern
*pat
= NULL
;
410 FcFontSet
*fontset
= NULL
;
411 FcObjectSet
*objset
= NULL
;
412 FcCharSet
*charset
= NULL
;
414 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
415 FC_INDEX
, FcTypeInteger
, index
, NULL
);
418 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
421 fontset
= FcFontList (NULL
, pat
, objset
);
424 if (fontset
&& fontset
->nfont
> 0
425 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
428 cache_data
->fc_charset
= FcCharSetCopy (charset
);
430 cache_data
->fc_charset
= FcCharSetCreate ();
434 FcFontSetDestroy (fontset
);
436 FcObjectSetDestroy (objset
);
438 FcPatternDestroy (pat
);
445 ftfont_get_fc_charset (Lisp_Object entity
)
447 Lisp_Object val
, cache
;
448 struct ftfont_cache_data
*cache_data
;
450 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
452 cache_data
= XSAVE_VALUE (val
)->pointer
;
453 return cache_data
->fc_charset
;
458 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
462 if (ftfont_info
->otf
)
463 return ftfont_info
->otf
;
464 if (! ftfont_info
->maybe_otf
)
466 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
467 if (! otf
|| OTF_get_table (otf
, "head") < 0)
471 ftfont_info
->maybe_otf
= 0;
474 ftfont_info
->otf
= otf
;
477 #endif /* HAVE_LIBOTF */
479 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
480 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
481 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
482 static Lisp_Object
ftfont_list_family (Lisp_Object
);
483 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
484 static void ftfont_close (FRAME_PTR
, struct font
*);
485 static int ftfont_has_char (Lisp_Object
, int);
486 static unsigned ftfont_encode_char (struct font
*, int);
487 static int ftfont_text_extents (struct font
*, unsigned *, int,
488 struct font_metrics
*);
489 static int ftfont_get_bitmap (struct font
*, unsigned,
490 struct font_bitmap
*, int);
491 static int ftfont_anchor_point (struct font
*, unsigned, int,
493 static Lisp_Object
ftfont_otf_capability (struct font
*);
494 static Lisp_Object
ftfont_shape (Lisp_Object
);
496 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
497 static int ftfont_variation_glyphs (struct font
*, int c
,
498 unsigned variations
[256]);
499 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
501 struct font_driver ftfont_driver
=
504 0, /* case insensitive */
509 NULL
, /* free_entity */
512 /* We can't draw a text without device dependent functions. */
513 NULL
, /* prepare_face */
514 NULL
, /* done_face */
518 /* We can't draw a text without device dependent functions. */
521 NULL
, /* get_bitmap */
522 NULL
, /* free_bitmap */
523 NULL
, /* get_outline */
526 ftfont_otf_capability
,
527 #else /* not HAVE_LIBOTF */
529 #endif /* not HAVE_LIBOTF */
530 NULL
, /* otf_drive */
531 NULL
, /* start_for_frame */
532 NULL
, /* end_for_frame */
533 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
535 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
537 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
540 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
541 ftfont_variation_glyphs
,
546 ftfont_filter_properties
, /* filter_properties */
550 ftfont_get_cache (FRAME_PTR f
)
552 return freetype_font_cache
;
556 ftfont_get_charset (Lisp_Object registry
)
558 char *str
= (char *) SDATA (SYMBOL_NAME (registry
));
559 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
563 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
567 else if (str
[i
] == '*')
574 regexp
= make_unibyte_string (re
, j
);
575 for (i
= 0; fc_charset_table
[i
].name
; i
++)
576 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
578 if (! fc_charset_table
[i
].name
)
580 if (! fc_charset_table
[i
].fc_charset
)
582 FcCharSet
*charset
= FcCharSetCreate ();
583 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
587 for (j
= 0; uniquifier
[j
]; j
++)
588 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
590 FcCharSetDestroy (charset
);
593 fc_charset_table
[i
].fc_charset
= charset
;
601 unsigned int script_tag
, langsys_tag
;
603 unsigned int *features
[2];
606 #define OTF_SYM_TAG(SYM, TAG) \
608 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
609 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
612 #define OTF_TAG_STR(TAG, P) \
614 (P)[0] = (char) (TAG >> 24); \
615 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
616 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
617 (P)[3] = (char) (TAG & 0xFF); \
621 #define OTF_TAG_SYM(SYM, TAG) \
625 OTF_TAG_STR (TAG, str); \
626 (SYM) = font_intern_prop (str, 4, 1); \
630 static struct OpenTypeSpec
*
631 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
633 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
639 spec
->script
= XCAR (otf_spec
);
640 if (! NILP (spec
->script
))
642 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
643 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
644 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
645 spec
->script
= XCDR (val
);
650 spec
->script_tag
= 0x44464C54; /* "DFLT" */
651 otf_spec
= XCDR (otf_spec
);
652 spec
->langsys_tag
= 0;
653 if (! NILP (otf_spec
))
655 val
= XCAR (otf_spec
);
657 OTF_SYM_TAG (val
, spec
->langsys_tag
);
658 otf_spec
= XCDR (otf_spec
);
660 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
661 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
665 val
= XCAR (otf_spec
);
669 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
670 if (! spec
->features
[i
])
672 if (i
> 0 && spec
->features
[0])
673 free (spec
->features
[0]);
677 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
679 if (NILP (XCAR (val
)))
685 OTF_SYM_TAG (XCAR (val
), tag
);
686 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
689 spec
->nfeatures
[i
] = j
;
695 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
697 Lisp_Object tmp
, extra
;
698 FcPattern
*pattern
= NULL
;
699 FcCharSet
*charset
= NULL
;
700 FcLangSet
*langset
= NULL
;
704 Lisp_Object script
= Qnil
;
705 Lisp_Object registry
;
708 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
710 /* Fontconfig doesn't support reverse-italic/obligue. */
713 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
714 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
715 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
716 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
719 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
721 || EQ (registry
, Qascii_0
)
722 || EQ (registry
, Qiso10646_1
)
723 || EQ (registry
, Qunicode_bmp
))
729 fc_charset_idx
= ftfont_get_charset (registry
);
730 if (fc_charset_idx
< 0)
732 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
733 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
734 lang
= (FcChar8
*) *langname
;
737 langset
= FcLangSetCreate ();
740 FcLangSetAdd (langset
, lang
);
745 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
746 CONSP (extra
); extra
= XCDR (extra
))
748 Lisp_Object key
, val
;
750 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
753 else if (EQ (key
, QClang
))
756 langset
= FcLangSetCreate ();
761 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
765 for (; CONSP (val
); val
= XCDR (val
))
766 if (SYMBOLP (XCAR (val
))
767 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
770 else if (EQ (key
, QCotf
))
772 *otspec
= ftfont_get_open_type_spec (val
);
775 strcat (otlayout
, "otlayout:");
776 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
777 script
= (*otspec
)->script
;
779 else if (EQ (key
, QCscript
))
781 else if (EQ (key
, QCscalable
))
782 scalable
= ! NILP (val
);
785 if (! NILP (script
) && ! charset
)
787 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
789 if (CONSP (chars
) && CONSP (CDR (chars
)))
791 charset
= FcCharSetCreate ();
794 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
795 if (CHARACTERP (XCAR (chars
))
796 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
801 pattern
= FcPatternCreate ();
804 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
806 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
808 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
810 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
813 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
816 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
819 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
822 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
828 /* We come here because of unexpected error in fontconfig API call
829 (usually insufficient memory). */
832 FcPatternDestroy (pattern
);
837 if ((*otspec
)->nfeatures
[0] > 0)
838 free ((*otspec
)->features
[0]);
839 if ((*otspec
)->nfeatures
[1] > 0)
840 free ((*otspec
)->features
[1]);
846 if (langset
) FcLangSetDestroy (langset
);
847 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
852 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
854 Lisp_Object val
= Qnil
, family
, adstyle
;
857 FcFontSet
*fontset
= NULL
;
858 FcObjectSet
*objset
= NULL
;
860 Lisp_Object chars
= Qnil
;
862 char otlayout
[15]; /* For "otlayout:XXXX" */
863 struct OpenTypeSpec
*otspec
= NULL
;
865 const char *langname
= NULL
;
867 if (! fc_initialized
)
873 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
876 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
878 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
881 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
882 if (CONSP (val
) && VECTORP (XCDR (val
)))
887 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
888 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
889 family
= AREF (spec
, FONT_FAMILY_INDEX
);
892 Lisp_Object resolved
;
894 resolved
= ftfont_resolve_generic_family (family
, pattern
);
895 if (! NILP (resolved
))
897 FcPatternDel (pattern
, FC_FAMILY
);
898 if (! FcPatternAddString (pattern
, FC_FAMILY
,
899 SYMBOL_FcChar8 (resolved
)))
903 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
904 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
906 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
907 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
908 FC_STYLE
, FC_FILE
, FC_INDEX
,
911 #endif /* FC_CAPABILITY */
919 FcObjectSetAdd (objset
, FC_CHARSET
);
921 fontset
= FcFontList (NULL
, pattern
, objset
);
922 if (! fontset
|| fontset
->nfont
== 0)
925 /* Need fix because this finds any fonts. */
926 if (fontset
->nfont
== 0 && ! NILP (family
))
928 /* Try maching with configuration. For instance, the
929 configuration may specify "Nimbus Mono L" as an alias of
931 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
932 SYMBOL_FcChar8 (family
), NULL
);
935 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
938 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
941 FcPatternDel (pattern
, FC_FAMILY
);
942 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
943 FcFontSetDestroy (fontset
);
944 fontset
= FcFontList (NULL
, pattern
, objset
);
945 if (fontset
&& fontset
->nfont
> 0)
951 for (i
= 0; i
< fontset
->nfont
; i
++)
959 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
970 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
972 || ! strstr ((char *) this, otlayout
))
975 #endif /* FC_CAPABILITY */
982 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
985 otf
= OTF_open ((char *) file
);
988 if (OTF_check_features (otf
, 1,
989 otspec
->script_tag
, otspec
->langsys_tag
,
991 otspec
->nfeatures
[0]) != 1
992 || OTF_check_features (otf
, 0,
993 otspec
->script_tag
, otspec
->langsys_tag
,
995 otspec
->nfeatures
[1]) != 1)
998 #endif /* HAVE_LIBOTF */
1003 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1006 for (j
= 0; j
< ASIZE (chars
); j
++)
1007 if (NATNUMP (AREF (chars
, j
))
1008 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1010 if (j
== ASIZE (chars
))
1013 if (! NILP (adstyle
) || langname
)
1015 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1017 if (! NILP (adstyle
)
1018 && (NILP (this_adstyle
)
1019 || xstrcasecmp (SDATA (SYMBOL_NAME (adstyle
)),
1020 SDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1023 && ! NILP (this_adstyle
)
1024 && xstrcasecmp (langname
, SDATA (SYMBOL_NAME (this_adstyle
))))
1027 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1028 AREF (spec
, FONT_EXTRA_INDEX
));
1029 if (! NILP (entity
))
1030 val
= Fcons (entity
, val
);
1032 val
= Fnreverse (val
);
1036 /* We come here because of unexpected error in fontconfig API call
1037 (usually insufficient memory). */
1041 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1042 if (objset
) FcObjectSetDestroy (objset
);
1043 if (fontset
) FcFontSetDestroy (fontset
);
1044 if (pattern
) FcPatternDestroy (pattern
);
1049 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1051 Lisp_Object entity
= Qnil
;
1052 FcPattern
*pattern
, *match
= NULL
;
1054 char otlayout
[15]; /* For "otlayout:XXXX" */
1055 struct OpenTypeSpec
*otspec
= NULL
;
1056 const char *langname
= NULL
;
1058 if (! fc_initialized
)
1064 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1068 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1072 value
.type
= FcTypeDouble
;
1073 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1074 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1076 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1078 FcDefaultSubstitute (pattern
);
1079 match
= FcFontMatch (NULL
, pattern
, &result
);
1082 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1083 FcPatternDestroy (match
);
1084 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1085 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1086 ftfont_generic_family_list
))
1087 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1088 AREF (entity
, FONT_FAMILY_INDEX
))))
1092 FcPatternDestroy (pattern
);
1094 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1099 ftfont_list_family (Lisp_Object frame
)
1101 Lisp_Object list
= Qnil
;
1102 FcPattern
*pattern
= NULL
;
1103 FcFontSet
*fontset
= NULL
;
1104 FcObjectSet
*objset
= NULL
;
1107 if (! fc_initialized
)
1113 pattern
= FcPatternCreate ();
1116 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1119 fontset
= FcFontList (NULL
, pattern
, objset
);
1123 for (i
= 0; i
< fontset
->nfont
; i
++)
1125 FcPattern
*pat
= fontset
->fonts
[i
];
1128 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1129 list
= Fcons (intern ((char *) str
), list
);
1133 if (objset
) FcObjectSetDestroy (objset
);
1134 if (fontset
) FcFontSetDestroy (fontset
);
1135 if (pattern
) FcPatternDestroy (pattern
);
1142 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1144 struct ftfont_info
*ftfont_info
;
1146 struct ftfont_cache_data
*cache_data
;
1150 Lisp_Object val
, filename
, index
, cache
, font_object
;
1157 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1161 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1164 filename
= XCAR (val
);
1167 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1168 ft_face
= cache_data
->ft_face
;
1169 if (XSAVE_VALUE (val
)->integer
> 0)
1171 /* FT_Face in this cache is already used by the different size. */
1172 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1174 if (FT_Activate_Size (ft_size
) != 0)
1176 FT_Done_Size (ft_size
);
1180 XSAVE_VALUE (val
)->integer
++;
1181 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1184 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1186 if (XSAVE_VALUE (val
)->integer
== 0)
1187 FT_Done_Face (ft_face
);
1191 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1192 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1193 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1195 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1196 len
= font_unparse_fcname (entity
, size
, name
, 256);
1198 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1200 ASET (font_object
, FONT_FULLNAME_INDEX
,
1201 AREF (font_object
, FONT_NAME_INDEX
));
1202 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1203 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1204 font
= XFONT_OBJECT (font_object
);
1205 ftfont_info
= (struct ftfont_info
*) font
;
1206 ftfont_info
->ft_size
= ft_face
->size
;
1207 ftfont_info
->index
= XINT (index
);
1209 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1210 ftfont_info
->otf
= NULL
;
1211 #endif /* HAVE_LIBOTF */
1212 /* This means that there's no need of transformation. */
1213 ftfont_info
->matrix
.xx
= 0;
1214 font
->pixel_size
= size
;
1215 font
->driver
= &ftfont_driver
;
1216 font
->encoding_charset
= font
->repertory_charset
= -1;
1218 upEM
= ft_face
->units_per_EM
;
1219 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1220 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1223 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1224 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1225 font
->height
= ft_face
->height
* size
/ upEM
;
1229 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1230 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1231 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1233 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1234 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1236 spacing
= FC_PROPORTIONAL
;
1237 if (spacing
!= FC_PROPORTIONAL
&& spacing
!= FC_DUAL
)
1238 font
->min_width
= font
->average_width
= font
->space_width
1239 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1240 : ft_face
->size
->metrics
.max_advance
>> 6);
1245 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1246 for (i
= 32, n
= 0; i
< 127; i
++)
1247 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1249 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1252 && (! font
->min_width
|| font
->min_width
> this_width
))
1253 font
->min_width
= this_width
;
1255 font
->space_width
= this_width
;
1256 font
->average_width
+= this_width
;
1260 font
->average_width
/= n
;
1263 font
->baseline_offset
= 0;
1264 font
->relative_compose
= 0;
1265 font
->default_ascent
= 0;
1266 font
->vertical_centering
= 0;
1269 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1270 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1274 font
->underline_position
= -1;
1275 font
->underline_thickness
= 0;
1282 ftfont_close (FRAME_PTR f
, struct font
*font
)
1284 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1285 Lisp_Object val
, cache
;
1287 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1288 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1289 xassert (CONSP (cache
));
1291 (XSAVE_VALUE (val
)->integer
)--;
1292 if (XSAVE_VALUE (val
)->integer
== 0)
1294 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1296 FT_Done_Face (cache_data
->ft_face
);
1298 if (ftfont_info
->otf
)
1299 OTF_close (ftfont_info
->otf
);
1301 cache_data
->ft_face
= NULL
;
1304 FT_Done_Size (ftfont_info
->ft_size
);
1308 ftfont_has_char (Lisp_Object font
, int c
)
1310 struct charset
*cs
= NULL
;
1312 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1313 && charset_jisx0208
>= 0)
1314 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1315 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1316 && charset_ksc5601
>= 0)
1317 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1319 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1321 if (FONT_ENTITY_P (font
))
1323 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1325 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1329 struct ftfont_info
*ftfont_info
;
1331 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1332 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1338 ftfont_encode_char (struct font
*font
, int c
)
1340 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1341 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1342 FT_ULong charcode
= c
;
1343 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1345 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1349 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1351 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1352 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1356 if (ftfont_info
->ft_size
!= ft_face
->size
)
1357 FT_Activate_Size (ftfont_info
->ft_size
);
1359 memset (metrics
, 0, sizeof (struct font_metrics
));
1360 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1362 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1364 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1370 metrics
->lbearing
= m
->horiBearingX
>> 6;
1371 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1372 metrics
->ascent
= m
->horiBearingY
>> 6;
1373 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1379 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1380 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1381 if (metrics
->rbearing
1382 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1384 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1385 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1386 metrics
->ascent
= m
->horiBearingY
>> 6;
1387 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1388 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1390 width
+= m
->horiAdvance
>> 6;
1394 width
+= font
->space_width
;
1398 metrics
->width
= width
;
1404 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1406 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1407 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1408 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1410 if (ftfont_info
->ft_size
!= ft_face
->size
)
1411 FT_Activate_Size (ftfont_info
->ft_size
);
1412 if (bits_per_pixel
== 1)
1414 #ifdef FT_LOAD_TARGET_MONO
1415 load_flags
|= FT_LOAD_TARGET_MONO
;
1417 load_flags
|= FT_LOAD_MONOCHROME
;
1420 else if (bits_per_pixel
!= 8)
1421 /* We don't support such a rendering. */
1424 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1426 bitmap
->bits_per_pixel
1427 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1428 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1429 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1430 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1432 if (bitmap
->bits_per_pixel
< 0)
1433 /* We don't suport that kind of pixel mode. */
1435 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1436 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1437 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1438 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1439 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1440 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1441 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1442 bitmap
->extra
= NULL
;
1448 ftfont_anchor_point (struct font
*font
, unsigned int code
, int index
, int *x
, int *y
)
1450 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1451 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1453 if (ftfont_info
->ft_size
!= ft_face
->size
)
1454 FT_Activate_Size (ftfont_info
->ft_size
);
1455 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1457 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1459 if (index
>= ft_face
->glyph
->outline
.n_points
)
1461 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
1462 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
1469 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1471 Lisp_Object scripts
, langsyses
, features
, sym
;
1474 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1476 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1478 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1480 OTF_LangSys
*otf_langsys
;
1483 otf_langsys
= otf_script
->LangSys
+ j
;
1484 else if (otf_script
->DefaultLangSysOffset
)
1485 otf_langsys
= &otf_script
->DefaultLangSys
;
1489 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1491 l
= otf_langsys
->FeatureIndex
[k
];
1492 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1494 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1495 features
= Fcons (sym
, features
);
1498 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1501 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1504 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1505 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1513 ftfont_otf_capability (struct font
*font
)
1515 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1516 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1517 Lisp_Object gsub_gpos
;
1521 gsub_gpos
= Fcons (Qnil
, Qnil
);
1522 if (OTF_get_table (otf
, "GSUB") == 0
1523 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1524 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1525 if (OTF_get_table (otf
, "GPOS") == 0
1526 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1527 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1531 #ifdef HAVE_M17N_FLT
1533 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1534 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1535 /* We can use the new feature of libotf and m17n-flt to handle the
1536 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1537 some Agian scripts. */
1538 #define M17N_FLT_USE_NEW_FEATURE
1551 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1554 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1555 FT_Face ft_face
= flt_font_ft
->ft_face
;
1558 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1561 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1563 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1569 /* Operators for 26.6 fixed fractional pixel format */
1571 #define FLOOR(x) ((x) & -64)
1572 #define CEIL(x) (((x)+63) & -64)
1573 #define ROUND(x) (((x)+32) & -64)
1576 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1579 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1580 FT_Face ft_face
= flt_font_ft
->ft_face
;
1583 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1586 if (g
->code
!= FONT_INVALID_CODE
)
1588 FT_Glyph_Metrics
*m
;
1589 int lbearing
, rbearing
, ascent
, descent
, xadv
;
1591 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1593 m
= &ft_face
->glyph
->metrics
;
1594 if (flt_font_ft
->matrix
)
1599 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1600 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1601 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1602 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1603 for (i
= 0; i
< 4; i
++)
1604 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1605 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1606 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1607 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1608 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1612 g
->lbearing
= FLOOR (m
->horiBearingX
);
1613 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1614 g
->ascent
= CEIL (m
->horiBearingY
);
1615 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1617 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1622 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1623 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1624 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1633 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1635 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1636 OTF
*otf
= flt_font_ft
->otf
;
1640 for (i
= 0; i
< 2; i
++)
1642 if (! spec
->features
[i
])
1644 for (n
= 0; spec
->features
[i
][n
]; n
++);
1645 tags
= alloca (sizeof (OTF_Tag
) * n
);
1646 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1648 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1651 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1653 tags
[n
] = spec
->features
[i
][n
];
1655 #ifdef M17N_FLT_USE_NEW_FEATURE
1656 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1657 tags
, n
- negative
) != 1)
1659 #else /* not M17N_FLT_USE_NEW_FEATURE */
1660 if (n
- negative
> 0
1661 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1662 tags
, n
- negative
) != 1)
1664 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1669 #define DEVICE_DELTA(table, size) \
1670 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1671 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1675 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1676 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1678 if (anchor
->AnchorFormat
== 2)
1680 FT_Outline
*outline
;
1681 int ap
= anchor
->f
.f1
.AnchorPoint
;
1683 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1684 outline
= &ft_face
->glyph
->outline
;
1685 if (ap
< outline
->n_points
)
1687 *x
= outline
->points
[ap
].x
<< 6;
1688 *y
= outline
->points
[ap
].y
<< 6;
1691 else if (anchor
->AnchorFormat
== 3)
1693 if (anchor
->f
.f2
.XDeviceTable
.offset
1694 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1695 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1696 if (anchor
->f
.f2
.YDeviceTable
.offset
1697 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1698 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1702 static OTF_GlyphString otf_gstring
;
1705 setup_otf_gstring (int size
)
1707 if (otf_gstring
.size
== 0)
1709 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1710 otf_gstring
.size
= size
;
1712 else if (otf_gstring
.size
< size
)
1714 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1715 sizeof (OTF_Glyph
) * size
);
1716 otf_gstring
.size
= size
;
1718 otf_gstring
.used
= size
;
1719 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1722 #ifdef M17N_FLT_USE_NEW_FEATURE
1724 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1725 #define PACK_OTF_TAG(TAG) \
1726 ((((TAG) & 0x7F000000) >> 3) \
1727 | (((TAG) & 0x7F0000) >> 2) \
1728 | (((TAG) & 0x7F00) >> 1) \
1731 /* Assuming that FONT is an OpenType font, apply OpenType features
1732 specified in SPEC on glyphs between FROM and TO of IN, and record
1733 the lastly applied feature in each glyph of IN. If OUT is not
1734 NULL, append the resulting glyphs to OUT while storing glyph
1735 position adjustment information in ADJUSTMENT. */
1738 ftfont_drive_otf (font
, spec
, in
, from
, to
, out
, adjustment
)
1741 MFLTGlyphString
*in
;
1743 MFLTGlyphString
*out
;
1744 MFLTGlyphAdjustment
*adjustment
;
1746 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1747 FT_Face ft_face
= flt_font_ft
->ft_face
;
1748 OTF
*otf
= flt_font_ft
->otf
;
1749 int len
= to
- from
;
1752 char script
[5], *langsys
= NULL
;
1753 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1754 OTF_Feature
*features
;
1758 OTF_tag_name (spec
->script
, script
);
1761 langsys
= alloca (5);
1762 OTF_tag_name (spec
->langsys
, langsys
);
1764 for (i
= 0; i
< 2; i
++)
1768 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1770 for (j
= 0; spec
->features
[i
][j
]; j
++);
1772 p
= gsub_features
= alloca (6 * j
);
1774 p
= gpos_features
= alloca (6 * j
);
1775 for (j
= 0; spec
->features
[i
][j
]; j
++)
1777 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1778 *p
++ = '*', *p
++ = ',';
1781 OTF_tag_name (spec
->features
[i
][j
], p
);
1790 setup_otf_gstring (len
);
1791 for (i
= 0; i
< len
; i
++)
1793 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1794 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1797 OTF_drive_gdef (otf
, &otf_gstring
);
1798 gidx
= out
? out
->used
: from
;
1800 if (gsub_features
&& out
)
1802 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1805 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1807 features
= otf
->gsub
->FeatureList
.Feature
;
1808 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1811 int min_from
, max_to
;
1813 int feature_idx
= otfg
->positioning_type
>> 4;
1815 g
= out
->glyphs
+ out
->used
;
1816 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1817 if (g
->code
!= otfg
->glyph_id
)
1820 g
->code
= otfg
->glyph_id
;
1826 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1828 /* OTFG substitutes multiple glyphs in IN. */
1829 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1830 j
<= from
+ otfg
->f
.index
.to
; j
++)
1832 if (min_from
> in
->glyphs
[j
].from
)
1833 min_from
= in
->glyphs
[j
].from
;
1834 if (max_to
< in
->glyphs
[j
].to
)
1835 max_to
= in
->glyphs
[j
].to
;
1842 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1843 tag
= PACK_OTF_TAG (tag
);
1844 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1846 for (i
++, otfg
++; (i
< otf_gstring
.used
1847 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1850 g
= out
->glyphs
+ out
->used
;
1851 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1852 if (g
->code
!= otfg
->glyph_id
)
1855 g
->code
= otfg
->glyph_id
;
1858 feature_idx
= otfg
->positioning_type
>> 4;
1861 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1862 tag
= PACK_OTF_TAG (tag
);
1863 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1869 else if (gsub_features
)
1871 /* Just for checking which features will be applied. */
1872 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1875 features
= otf
->gsub
->FeatureList
.Feature
;
1876 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1879 int feature_idx
= otfg
->positioning_type
>> 4;
1883 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1884 tag
= PACK_OTF_TAG (tag
);
1885 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1887 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1888 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1895 if (out
->allocated
< out
->used
+ len
)
1897 for (i
= 0; i
< len
; i
++)
1898 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1901 if (gpos_features
&& out
)
1903 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1904 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1906 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1909 features
= otf
->gpos
->FeatureList
.Feature
;
1910 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1911 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1912 x_scale
= ft_face
->size
->metrics
.x_scale
;
1913 y_scale
= ft_face
->size
->metrics
.y_scale
;
1915 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1916 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1919 int feature_idx
= otfg
->positioning_type
>> 4;
1923 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1924 tag
= PACK_OTF_TAG (tag
);
1925 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1928 if (! otfg
->glyph_id
)
1930 switch (otfg
->positioning_type
& 0xF)
1934 case 1: /* Single */
1937 int format
= otfg
->f
.f1
.format
;
1939 if (format
& OTF_XPlacement
)
1941 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1942 if (format
& OTF_XPlaDevice
)
1944 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1945 if (format
& OTF_YPlacement
)
1947 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
1948 if (format
& OTF_YPlaDevice
)
1950 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
1951 if (format
& OTF_XAdvance
)
1953 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
1954 if (format
& OTF_XAdvDevice
)
1956 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
1957 if (format
& OTF_YAdvance
)
1959 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
1960 if (format
& OTF_YAdvDevice
)
1962 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
1963 adjustment
[i
].set
= 1;
1966 case 3: /* Cursive */
1967 /* Not yet supported. */
1969 case 4: /* Mark-to-Base */
1970 case 5: /* Mark-to-Ligature */
1974 goto label_adjust_anchor
;
1975 default: /* i.e. case 6 Mark-to-Mark */
1980 label_adjust_anchor
:
1982 int base_x
, base_y
, mark_x
, mark_y
;
1983 int this_from
, this_to
;
1985 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
1986 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
1987 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
1988 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
1990 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
1991 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
1992 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
1993 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
1994 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
1995 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
1996 adjustment
[i
].xoff
= (base_x
- mark_x
);
1997 adjustment
[i
].yoff
= - (base_y
- mark_y
);
1998 adjustment
[i
].back
= (g
- prev
);
1999 adjustment
[i
].xadv
= 0;
2000 adjustment
[i
].advance_is_absolute
= 1;
2001 adjustment
[i
].set
= 1;
2002 this_from
= g
->from
;
2004 for (j
= 0; prev
+ j
< g
; j
++)
2006 if (this_from
> prev
[j
].from
)
2007 this_from
= prev
[j
].from
;
2008 if (this_to
< prev
[j
].to
)
2009 this_to
= prev
[j
].to
;
2011 for (; prev
<= g
; prev
++)
2013 prev
->from
= this_from
;
2018 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2020 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2026 else if (gpos_features
)
2028 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2031 features
= otf
->gpos
->FeatureList
.Feature
;
2032 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2034 if (otfg
->positioning_type
& 0xF)
2036 int feature_idx
= otfg
->positioning_type
>> 4;
2040 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2041 tag
= PACK_OTF_TAG (tag
);
2042 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2044 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2045 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2055 if (out
->allocated
< out
->used
+ len
)
2057 font
->get_metrics (font
, in
, from
, to
);
2058 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2059 sizeof (MFLTGlyph
) * len
);
2065 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2066 MFLTGlyphString
*in
, int from
, int to
)
2068 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2071 #else /* not M17N_FLT_USE_NEW_FEATURE */
2074 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2076 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2078 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2079 FT_Face ft_face
= flt_font_ft
->ft_face
;
2080 OTF
*otf
= flt_font_ft
->otf
;
2081 int len
= to
- from
;
2084 char script
[5], *langsys
= NULL
;
2085 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2089 OTF_tag_name (spec
->script
, script
);
2092 langsys
= alloca (5);
2093 OTF_tag_name (spec
->langsys
, langsys
);
2095 for (i
= 0; i
< 2; i
++)
2099 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2101 for (j
= 0; spec
->features
[i
][j
]; j
++);
2103 p
= gsub_features
= alloca (6 * j
);
2105 p
= gpos_features
= alloca (6 * j
);
2106 for (j
= 0; spec
->features
[i
][j
]; j
++)
2108 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2109 *p
++ = '*', *p
++ = ',';
2112 OTF_tag_name (spec
->features
[i
][j
], p
);
2121 setup_otf_gstring (len
);
2122 for (i
= 0; i
< len
; i
++)
2124 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2125 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2128 OTF_drive_gdef (otf
, &otf_gstring
);
2133 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2136 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2138 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2141 int min_from
, max_to
;
2144 g
= out
->glyphs
+ out
->used
;
2145 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2146 if (g
->code
!= otfg
->glyph_id
)
2149 g
->code
= otfg
->glyph_id
;
2155 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2157 /* OTFG substitutes multiple glyphs in IN. */
2158 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2159 j
<= from
+ otfg
->f
.index
.to
; j
++)
2161 if (min_from
> in
->glyphs
[j
].from
)
2162 min_from
= in
->glyphs
[j
].from
;
2163 if (max_to
< in
->glyphs
[j
].to
)
2164 max_to
= in
->glyphs
[j
].to
;
2169 for (i
++, otfg
++; (i
< otf_gstring
.used
2170 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2173 g
= out
->glyphs
+ out
->used
;
2174 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2175 if (g
->code
!= otfg
->glyph_id
)
2178 g
->code
= otfg
->glyph_id
;
2187 if (out
->allocated
< out
->used
+ len
)
2189 for (i
= 0; i
< len
; i
++)
2190 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2195 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2196 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2198 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2202 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2203 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2204 x_scale
= ft_face
->size
->metrics
.x_scale
;
2205 y_scale
= ft_face
->size
->metrics
.y_scale
;
2207 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2208 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2212 if (! otfg
->glyph_id
)
2214 switch (otfg
->positioning_type
)
2218 case 1: /* Single */
2221 int format
= otfg
->f
.f1
.format
;
2223 if (format
& OTF_XPlacement
)
2225 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2226 if (format
& OTF_XPlaDevice
)
2228 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2229 if (format
& OTF_YPlacement
)
2231 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2232 if (format
& OTF_YPlaDevice
)
2234 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2235 if (format
& OTF_XAdvance
)
2237 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2238 if (format
& OTF_XAdvDevice
)
2240 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2241 if (format
& OTF_YAdvance
)
2243 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2244 if (format
& OTF_YAdvDevice
)
2246 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2247 adjustment
[i
].set
= 1;
2250 case 3: /* Cursive */
2251 /* Not yet supported. */
2253 case 4: /* Mark-to-Base */
2254 case 5: /* Mark-to-Ligature */
2258 goto label_adjust_anchor
;
2259 default: /* i.e. case 6 Mark-to-Mark */
2264 label_adjust_anchor
:
2266 int base_x
, base_y
, mark_x
, mark_y
;
2267 int this_from
, this_to
;
2269 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2270 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2271 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2272 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2274 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2275 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2276 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2277 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2278 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2279 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2280 adjustment
[i
].xoff
= (base_x
- mark_x
);
2281 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2282 adjustment
[i
].back
= (g
- prev
);
2283 adjustment
[i
].xadv
= 0;
2284 adjustment
[i
].advance_is_absolute
= 1;
2285 adjustment
[i
].set
= 1;
2286 this_from
= g
->from
;
2288 for (j
= 0; prev
+ j
< g
; j
++)
2290 if (this_from
> prev
[j
].from
)
2291 this_from
= prev
[j
].from
;
2292 if (this_to
< prev
[j
].to
)
2293 this_to
= prev
[j
].to
;
2295 for (; prev
<= g
; prev
++)
2297 prev
->from
= this_from
;
2302 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2304 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2313 if (out
->allocated
< out
->used
+ len
)
2315 font
->get_metrics (font
, in
, from
, to
);
2316 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2317 sizeof (MFLTGlyph
) * len
);
2322 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2324 static MFLTGlyphString gstring
;
2326 static int m17n_flt_initialized
;
2329 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2330 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2332 EMACS_UINT len
= LGSTRING_GLYPH_LEN (lgstring
);
2334 struct MFLTFontFT flt_font_ft
;
2336 int with_variation_selector
= 0;
2338 if (! m17n_flt_initialized
)
2341 #ifdef M17N_FLT_USE_NEW_FEATURE
2342 mflt_enable_new_feature
= 1;
2343 mflt_try_otf
= ftfont_try_otf
;
2344 #endif /* M17N_FLT_USE_NEW_FEATURE */
2345 m17n_flt_initialized
= 1;
2348 for (i
= 0; i
< len
; i
++)
2350 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2355 c
= LGLYPH_CHAR (g
);
2356 if (CHAR_VARIATION_SELECTOR_P (c
))
2357 with_variation_selector
++;
2360 if (with_variation_selector
)
2362 setup_otf_gstring (len
);
2363 for (i
= 0; i
< len
; i
++)
2365 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2367 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2368 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2369 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2371 OTF_drive_cmap (otf
, &otf_gstring
);
2372 for (i
= 0; i
< otf_gstring
.used
; i
++)
2374 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2375 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2376 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2378 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2379 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2380 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2382 if (len
> otf_gstring
.used
)
2384 len
= otf_gstring
.used
;
2385 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2389 if (gstring
.allocated
== 0)
2391 gstring
.allocated
= len
* 2;
2392 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2393 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2395 else if (gstring
.allocated
< len
* 2)
2397 gstring
.allocated
= len
* 2;
2398 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2399 sizeof (MFLTGlyph
) * gstring
.allocated
);
2401 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2402 for (i
= 0; i
< len
; i
++)
2404 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2406 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2407 if (with_variation_selector
)
2409 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2410 gstring
.glyphs
[i
].encoded
= 1;
2418 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2421 flt_font_ft
.flt_font
.family
= Mnil
;
2423 flt_font_ft
.flt_font
.family
2424 = msymbol ((char *) SDATA (Fdowncase (SYMBOL_NAME (family
))));
2426 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2427 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2428 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2429 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2430 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2431 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2432 flt_font_ft
.flt_font
.internal
= NULL
;
2433 flt_font_ft
.font
= font
;
2434 flt_font_ft
.ft_face
= ft_face
;
2435 flt_font_ft
.otf
= otf
;
2436 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2438 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2439 /* A little bit ad hoc. Perhaps, shaper must get script and
2440 language information, and select a proper flt for them
2442 flt
= mflt_get (msymbol ("combining"));
2443 for (i
= 0; i
< 3; i
++)
2445 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2448 gstring
.allocated
+= gstring
.allocated
;
2449 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2450 sizeof (MFLTGlyph
) * gstring
.allocated
);
2452 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2454 for (i
= 0; i
< gstring
.used
; i
++)
2456 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2458 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2459 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2462 for (i
= 0; i
< gstring
.used
; i
++)
2464 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2465 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2469 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2470 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2472 LGLYPH_SET_FROM (lglyph
, g
->from
);
2473 LGLYPH_SET_TO (lglyph
, g
->to
);
2474 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2475 LGLYPH_SET_CODE (lglyph
, g
->code
);
2476 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2477 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2478 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2479 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2480 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2485 vec
= Fmake_vector (make_number (3), Qnil
);
2486 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2487 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2488 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2489 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2492 return make_number (i
);
2496 ftfont_shape (Lisp_Object lgstring
)
2499 struct ftfont_info
*ftfont_info
;
2502 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2503 ftfont_info
= (struct ftfont_info
*) font
;
2504 otf
= ftfont_get_otf (ftfont_info
);
2506 return make_number (0);
2507 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2508 &ftfont_info
->matrix
);
2511 #endif /* HAVE_M17N_FLT */
2513 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2516 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2518 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2519 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2523 return OTF_get_variation_glyphs (otf
, c
, variations
);
2526 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2527 #endif /* HAVE_LIBOTF */
2530 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2534 #ifdef FC_FONTFORMAT
2537 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2539 if (strcmp ((char *) str
, "TrueType") == 0)
2540 return intern ("truetype");
2541 if (strcmp ((char *) str
, "Type 1") == 0)
2542 return intern ("type1");
2543 if (strcmp ((char *) str
, "PCF") == 0)
2544 return intern ("pcf");
2545 if (strcmp ((char *) str
, "BDF") == 0)
2546 return intern ("bdf");
2548 #endif /* FC_FONTFORMAT */
2549 if (STRINGP (filename
))
2551 int len
= SBYTES (filename
);
2555 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2556 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2557 return intern ("truetype");
2558 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2559 return intern ("type1");
2560 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2561 return intern ("pcf");
2562 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2563 return intern ("bdf");
2566 return intern ("unknown");
2569 static const char *ftfont_booleans
[] = {
2582 static const char *ftfont_non_booleans
[] = {
2614 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2619 /* Set boolean values to Qt or Qnil */
2620 for (i
= 0; ftfont_booleans
[i
] != NULL
; ++i
)
2621 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
2623 Lisp_Object key
= XCAR (XCAR (it
));
2624 Lisp_Object val
= XCDR (XCAR (it
));
2625 char *keystr
= SDATA (SYMBOL_NAME (key
));
2627 if (strcmp (ftfont_booleans
[i
], keystr
) == 0)
2629 const char *str
= SYMBOLP (val
) ? SDATA (SYMBOL_NAME (val
)) : NULL
;
2630 if (INTEGERP (val
)) str
= XINT (val
) != 0 ? "true" : "false";
2631 if (str
== NULL
) str
= "true";
2634 if (strcmp ("false", str
) == 0 || strcmp ("False", str
) == 0
2635 || strcmp ("FALSE", str
) == 0 || strcmp ("FcFalse", str
) == 0
2636 || strcmp ("off", str
) == 0 || strcmp ("OFF", str
) == 0
2637 || strcmp ("Off", str
) == 0)
2639 Ffont_put (font
, key
, val
);
2643 for (i
= 0; ftfont_non_booleans
[i
] != NULL
; ++i
)
2644 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
2646 Lisp_Object key
= XCAR (XCAR (it
));
2647 Lisp_Object val
= XCDR (XCAR (it
));
2648 char *keystr
= SDATA (SYMBOL_NAME (key
));
2649 if (strcmp (ftfont_non_booleans
[i
], keystr
) == 0)
2650 Ffont_put (font
, key
, val
);
2656 syms_of_ftfont (void)
2658 DEFSYM (Qfreetype
, "freetype");
2659 DEFSYM (Qmonospace
, "monospace");
2660 DEFSYM (Qsans_serif
, "sans-serif");
2661 DEFSYM (Qserif
, "serif");
2662 DEFSYM (Qmono
, "mono");
2663 DEFSYM (Qsans
, "sans");
2664 DEFSYM (Qsans__serif
, "sans serif");
2666 staticpro (&freetype_font_cache
);
2667 freetype_font_cache
= Fcons (Qt
, Qnil
);
2669 staticpro (&ftfont_generic_family_list
);
2670 ftfont_generic_family_list
2671 = Fcons (Fcons (Qmonospace
, Qt
),
2672 Fcons (Fcons (Qsans_serif
, Qt
),
2673 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2675 staticpro (&ft_face_cache
);
2676 ft_face_cache
= Qnil
;
2678 ftfont_driver
.type
= Qfreetype
;
2679 register_font_driver (&ftfont_driver
, NULL
);
2682 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
2683 (do not change this comment) */