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 static 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
)
167 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
169 str
= (char *) fcstr
;
170 for (end
= str
; *end
&& *end
!= ' '; end
++);
173 char *newstr
= alloca (end
- str
+ 1);
174 memcpy (newstr
, str
, end
- str
);
175 newstr
[end
- str
] = '\0';
176 end
= newstr
+ (end
- str
);
179 if (xstrcasecmp (str
, "Regular") == 0
180 || xstrcasecmp (str
, "Bold") == 0
181 || xstrcasecmp (str
, "Oblique") == 0
182 || xstrcasecmp (str
, "Italic") == 0)
184 adstyle
= font_intern_prop (str
, end
- str
, 1);
185 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
191 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
193 Lisp_Object key
, cache
, entity
;
201 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
203 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
207 key
= Fcons (make_unibyte_string (file
, strlen (file
)), make_number (idx
));
208 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
209 entity
= XCAR (cache
);
212 Lisp_Object val
= font_make_entity ();
215 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
216 ASET (val
, i
, AREF (entity
, i
));
219 entity
= font_make_entity ();
220 XSETCAR (cache
, entity
);
222 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
223 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
225 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
227 char *s
= (char *) str
;
228 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
230 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
232 char *s
= (char *) str
;
233 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
235 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
237 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
238 numeric
= FC_WEIGHT_MEDIUM
;
239 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
241 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
244 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
246 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
248 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
250 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
252 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
255 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
256 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
257 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
258 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
261 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
263 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
266 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
267 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
271 /* As this font is not scalable, parhaps this is a BDF or PCF
275 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
276 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
277 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
281 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
282 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
283 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
284 FT_Done_Face (ft_face
);
288 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
289 font_put_extra (entity
, QCfont_entity
, key
);
294 static Lisp_Object ftfont_generic_family_list
;
297 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
304 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
305 if (EQ (family
, Qmono
))
307 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
308 family
= Qsans_serif
;
309 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
312 if (! EQ (XCDR (slot
), Qt
))
314 pattern
= FcPatternDuplicate (pattern
);
317 FcPatternDel (pattern
, FC_FOUNDRY
);
318 FcPatternDel (pattern
, FC_FAMILY
);
319 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
320 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
322 /* This is to avoid the effect of locale. */
323 static const FcChar8 lang
[] = "en";
324 langset
= FcLangSetCreate ();
325 FcLangSetAdd (langset
, lang
);
326 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
327 FcLangSetDestroy (langset
);
329 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
330 FcDefaultSubstitute (pattern
);
331 match
= FcFontMatch (NULL
, pattern
, &result
);
336 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
337 family
= intern ((char *) fam
);
341 XSETCDR (slot
, family
);
342 if (match
) FcPatternDestroy (match
);
344 if (pattern
) FcPatternDestroy (pattern
);
348 struct ftfont_cache_data
351 FcCharSet
*fc_charset
;
355 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
357 Lisp_Object cache
, val
, entity
;
358 struct ftfont_cache_data
*cache_data
;
360 if (FONT_ENTITY_P (key
))
363 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
364 xassert (CONSP (val
));
370 if (NILP (ft_face_cache
))
373 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
376 if (NILP (ft_face_cache
))
382 ft_face_cache
= Fmake_hash_table (2, args
);
384 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
385 cache_data
->ft_face
= NULL
;
386 cache_data
->fc_charset
= NULL
;
387 val
= make_save_value (NULL
, 0);
388 XSAVE_VALUE (val
)->integer
= 0;
389 XSAVE_VALUE (val
)->pointer
= cache_data
;
390 cache
= Fcons (Qnil
, val
);
391 Fputhash (key
, cache
, ft_face_cache
);
396 cache_data
= XSAVE_VALUE (val
)->pointer
;
399 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
402 if (cache_for
== FTFONT_CACHE_FOR_FACE
403 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
405 char *filename
= SSDATA (XCAR (key
));
406 int idx
= XINT (XCDR (key
));
408 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
411 && FT_Init_FreeType (&ft_library
) != 0)
413 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
419 FcPattern
*pat
= NULL
;
420 FcFontSet
*fontset
= NULL
;
421 FcObjectSet
*objset
= NULL
;
422 FcCharSet
*charset
= NULL
;
424 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
425 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
428 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
431 fontset
= FcFontList (NULL
, pat
, objset
);
434 if (fontset
&& fontset
->nfont
> 0
435 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
438 cache_data
->fc_charset
= FcCharSetCopy (charset
);
440 cache_data
->fc_charset
= FcCharSetCreate ();
444 FcFontSetDestroy (fontset
);
446 FcObjectSetDestroy (objset
);
448 FcPatternDestroy (pat
);
455 ftfont_get_fc_charset (Lisp_Object entity
)
457 Lisp_Object val
, cache
;
458 struct ftfont_cache_data
*cache_data
;
460 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
462 cache_data
= XSAVE_VALUE (val
)->pointer
;
463 return cache_data
->fc_charset
;
468 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
472 if (ftfont_info
->otf
)
473 return ftfont_info
->otf
;
474 if (! ftfont_info
->maybe_otf
)
476 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
477 if (! otf
|| OTF_get_table (otf
, "head") < 0)
481 ftfont_info
->maybe_otf
= 0;
484 ftfont_info
->otf
= otf
;
487 #endif /* HAVE_LIBOTF */
489 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
490 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
491 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
492 static Lisp_Object
ftfont_list_family (Lisp_Object
);
493 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
494 static void ftfont_close (FRAME_PTR
, struct font
*);
495 static int ftfont_has_char (Lisp_Object
, int);
496 static unsigned ftfont_encode_char (struct font
*, int);
497 static int ftfont_text_extents (struct font
*, unsigned *, int,
498 struct font_metrics
*);
499 static int ftfont_get_bitmap (struct font
*, unsigned,
500 struct font_bitmap
*, int);
501 static int ftfont_anchor_point (struct font
*, unsigned, int,
504 static Lisp_Object
ftfont_otf_capability (struct font
*);
505 # ifdef HAVE_M17N_FLT
506 static Lisp_Object
ftfont_shape (Lisp_Object
);
510 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
511 static int ftfont_variation_glyphs (struct font
*, int c
,
512 unsigned variations
[256]);
513 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
515 struct font_driver ftfont_driver
=
518 0, /* case insensitive */
523 NULL
, /* free_entity */
526 /* We can't draw a text without device dependent functions. */
527 NULL
, /* prepare_face */
528 NULL
, /* done_face */
532 /* We can't draw a text without device dependent functions. */
535 NULL
, /* get_bitmap */
536 NULL
, /* free_bitmap */
537 NULL
, /* get_outline */
540 ftfont_otf_capability
,
541 #else /* not HAVE_LIBOTF */
543 #endif /* not HAVE_LIBOTF */
544 NULL
, /* otf_drive */
545 NULL
, /* start_for_frame */
546 NULL
, /* end_for_frame */
547 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
549 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
551 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
554 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
555 ftfont_variation_glyphs
,
560 ftfont_filter_properties
, /* filter_properties */
564 ftfont_get_cache (FRAME_PTR f
)
566 return freetype_font_cache
;
570 ftfont_get_charset (Lisp_Object registry
)
572 char *str
= SSDATA (SYMBOL_NAME (registry
));
573 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
577 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
581 else if (str
[i
] == '*')
588 regexp
= make_unibyte_string (re
, j
);
589 for (i
= 0; fc_charset_table
[i
].name
; i
++)
590 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
592 if (! fc_charset_table
[i
].name
)
594 if (! fc_charset_table
[i
].fc_charset
)
596 FcCharSet
*charset
= FcCharSetCreate ();
597 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
601 for (j
= 0; uniquifier
[j
]; j
++)
602 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
604 FcCharSetDestroy (charset
);
607 fc_charset_table
[i
].fc_charset
= charset
;
615 unsigned int script_tag
, langsys_tag
;
617 unsigned int *features
[2];
620 #define OTF_SYM_TAG(SYM, TAG) \
622 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
623 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
626 #define OTF_TAG_STR(TAG, P) \
628 (P)[0] = (char) (TAG >> 24); \
629 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
630 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
631 (P)[3] = (char) (TAG & 0xFF); \
636 #define OTF_TAG_SYM(SYM, TAG) \
640 OTF_TAG_STR (TAG, str); \
641 (SYM) = font_intern_prop (str, 4, 1); \
646 static struct OpenTypeSpec
*
647 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
649 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
655 spec
->script
= XCAR (otf_spec
);
656 if (! NILP (spec
->script
))
658 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
659 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
660 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
661 spec
->script
= XCDR (val
);
666 spec
->script_tag
= 0x44464C54; /* "DFLT" */
667 otf_spec
= XCDR (otf_spec
);
668 spec
->langsys_tag
= 0;
669 if (! NILP (otf_spec
))
671 val
= XCAR (otf_spec
);
673 OTF_SYM_TAG (val
, spec
->langsys_tag
);
674 otf_spec
= XCDR (otf_spec
);
676 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
677 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
681 val
= XCAR (otf_spec
);
685 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
686 if (! spec
->features
[i
])
688 if (i
> 0 && spec
->features
[0])
689 free (spec
->features
[0]);
693 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
695 if (NILP (XCAR (val
)))
701 OTF_SYM_TAG (XCAR (val
), tag
);
702 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
705 spec
->nfeatures
[i
] = j
;
711 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
713 Lisp_Object tmp
, extra
;
714 FcPattern
*pattern
= NULL
;
715 FcCharSet
*charset
= NULL
;
716 FcLangSet
*langset
= NULL
;
720 Lisp_Object script
= Qnil
;
721 Lisp_Object registry
;
724 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
726 /* Fontconfig doesn't support reverse-italic/obligue. */
729 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
730 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
731 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
732 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
735 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
737 || EQ (registry
, Qascii_0
)
738 || EQ (registry
, Qiso10646_1
)
739 || EQ (registry
, Qunicode_bmp
))
745 fc_charset_idx
= ftfont_get_charset (registry
);
746 if (fc_charset_idx
< 0)
748 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
749 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
750 lang
= (FcChar8
*) *langname
;
753 langset
= FcLangSetCreate ();
756 FcLangSetAdd (langset
, lang
);
761 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
762 CONSP (extra
); extra
= XCDR (extra
))
764 Lisp_Object key
, val
;
766 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
772 else if (EQ (key
, QClang
))
775 langset
= FcLangSetCreate ();
780 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
784 for (; CONSP (val
); val
= XCDR (val
))
785 if (SYMBOLP (XCAR (val
))
786 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
789 else if (EQ (key
, QCotf
))
793 *otspec
= ftfont_get_open_type_spec (val
);
796 strcat (otlayout
, "otlayout:");
797 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
798 script
= (*otspec
)->script
;
801 else if (EQ (key
, QCscript
))
803 else if (EQ (key
, QCscalable
))
804 scalable
= ! NILP (val
);
807 if (! NILP (script
) && ! charset
)
809 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
811 if (CONSP (chars
) && CONSP (CDR (chars
)))
813 charset
= FcCharSetCreate ();
816 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
817 if (CHARACTERP (XCAR (chars
))
818 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
823 pattern
= FcPatternCreate ();
826 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
828 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
830 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
832 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
835 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
838 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
841 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
844 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
850 /* We come here because of unexpected error in fontconfig API call
851 (usually insufficient memory). */
854 FcPatternDestroy (pattern
);
859 if ((*otspec
)->nfeatures
[0] > 0)
860 free ((*otspec
)->features
[0]);
861 if ((*otspec
)->nfeatures
[1] > 0)
862 free ((*otspec
)->features
[1]);
868 if (langset
) FcLangSetDestroy (langset
);
869 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
874 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
876 Lisp_Object val
= Qnil
, family
, adstyle
;
879 FcFontSet
*fontset
= NULL
;
880 FcObjectSet
*objset
= NULL
;
882 Lisp_Object chars
= Qnil
;
883 char otlayout
[15]; /* For "otlayout:XXXX" */
884 struct OpenTypeSpec
*otspec
= NULL
;
886 const char *langname
= NULL
;
888 if (! fc_initialized
)
894 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
897 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
899 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
902 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
903 if (CONSP (val
) && VECTORP (XCDR (val
)))
908 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
909 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
910 family
= AREF (spec
, FONT_FAMILY_INDEX
);
913 Lisp_Object resolved
;
915 resolved
= ftfont_resolve_generic_family (family
, pattern
);
916 if (! NILP (resolved
))
918 FcPatternDel (pattern
, FC_FAMILY
);
919 if (! FcPatternAddString (pattern
, FC_FAMILY
,
920 SYMBOL_FcChar8 (resolved
)))
924 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
925 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
927 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
928 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
929 FC_STYLE
, FC_FILE
, FC_INDEX
,
932 #endif /* FC_CAPABILITY */
940 FcObjectSetAdd (objset
, FC_CHARSET
);
942 fontset
= FcFontList (NULL
, pattern
, objset
);
943 if (! fontset
|| fontset
->nfont
== 0)
946 /* Need fix because this finds any fonts. */
947 if (fontset
->nfont
== 0 && ! NILP (family
))
949 /* Try maching with configuration. For instance, the
950 configuration may specify "Nimbus Mono L" as an alias of
952 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
953 SYMBOL_FcChar8 (family
), NULL
);
956 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
959 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
962 FcPatternDel (pattern
, FC_FAMILY
);
963 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
964 FcFontSetDestroy (fontset
);
965 fontset
= FcFontList (NULL
, pattern
, objset
);
966 if (fontset
&& fontset
->nfont
> 0)
972 for (i
= 0; i
< fontset
->nfont
; i
++)
980 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
991 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
993 || ! strstr ((char *) this, otlayout
))
996 #endif /* FC_CAPABILITY */
1003 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1006 otf
= OTF_open ((char *) file
);
1009 if (OTF_check_features (otf
, 1,
1010 otspec
->script_tag
, otspec
->langsys_tag
,
1011 otspec
->features
[0],
1012 otspec
->nfeatures
[0]) != 1
1013 || OTF_check_features (otf
, 0,
1014 otspec
->script_tag
, otspec
->langsys_tag
,
1015 otspec
->features
[1],
1016 otspec
->nfeatures
[1]) != 1)
1019 #endif /* HAVE_LIBOTF */
1020 if (VECTORP (chars
))
1024 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1027 for (j
= 0; j
< ASIZE (chars
); j
++)
1028 if (NATNUMP (AREF (chars
, j
))
1029 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1031 if (j
== ASIZE (chars
))
1034 if (! NILP (adstyle
) || langname
)
1036 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1038 if (! NILP (adstyle
)
1039 && (NILP (this_adstyle
)
1040 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1041 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1044 && ! NILP (this_adstyle
)
1045 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1048 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1049 AREF (spec
, FONT_EXTRA_INDEX
));
1050 if (! NILP (entity
))
1051 val
= Fcons (entity
, val
);
1053 val
= Fnreverse (val
);
1057 /* We come here because of unexpected error in fontconfig API call
1058 (usually insufficient memory). */
1062 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1063 if (objset
) FcObjectSetDestroy (objset
);
1064 if (fontset
) FcFontSetDestroy (fontset
);
1065 if (pattern
) FcPatternDestroy (pattern
);
1070 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1072 Lisp_Object entity
= Qnil
;
1073 FcPattern
*pattern
, *match
= NULL
;
1075 char otlayout
[15]; /* For "otlayout:XXXX" */
1076 struct OpenTypeSpec
*otspec
= NULL
;
1077 const char *langname
= NULL
;
1079 if (! fc_initialized
)
1085 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1089 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1093 value
.type
= FcTypeDouble
;
1094 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1095 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1097 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1099 FcDefaultSubstitute (pattern
);
1100 match
= FcFontMatch (NULL
, pattern
, &result
);
1103 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1104 FcPatternDestroy (match
);
1105 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1106 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1107 ftfont_generic_family_list
))
1108 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1109 AREF (entity
, FONT_FAMILY_INDEX
))))
1113 FcPatternDestroy (pattern
);
1115 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1120 ftfont_list_family (Lisp_Object frame
)
1122 Lisp_Object list
= Qnil
;
1123 FcPattern
*pattern
= NULL
;
1124 FcFontSet
*fontset
= NULL
;
1125 FcObjectSet
*objset
= NULL
;
1128 if (! fc_initialized
)
1134 pattern
= FcPatternCreate ();
1137 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1140 fontset
= FcFontList (NULL
, pattern
, objset
);
1144 for (i
= 0; i
< fontset
->nfont
; i
++)
1146 FcPattern
*pat
= fontset
->fonts
[i
];
1149 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1150 list
= Fcons (intern ((char *) str
), list
);
1154 if (objset
) FcObjectSetDestroy (objset
);
1155 if (fontset
) FcFontSetDestroy (fontset
);
1156 if (pattern
) FcPatternDestroy (pattern
);
1163 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1165 struct ftfont_info
*ftfont_info
;
1167 struct ftfont_cache_data
*cache_data
;
1171 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1178 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1182 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1185 filename
= XCAR (val
);
1188 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1189 ft_face
= cache_data
->ft_face
;
1190 if (XSAVE_VALUE (val
)->integer
> 0)
1192 /* FT_Face in this cache is already used by the different size. */
1193 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1195 if (FT_Activate_Size (ft_size
) != 0)
1197 FT_Done_Size (ft_size
);
1201 XSAVE_VALUE (val
)->integer
++;
1202 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1205 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1207 if (XSAVE_VALUE (val
)->integer
== 0)
1208 FT_Done_Face (ft_face
);
1212 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1213 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1214 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1216 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1217 len
= font_unparse_fcname (entity
, size
, name
, 256);
1219 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1221 ASET (font_object
, FONT_FULLNAME_INDEX
,
1222 AREF (font_object
, FONT_NAME_INDEX
));
1223 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1224 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1225 font
= XFONT_OBJECT (font_object
);
1226 ftfont_info
= (struct ftfont_info
*) font
;
1227 ftfont_info
->ft_size
= ft_face
->size
;
1228 ftfont_info
->index
= XINT (idx
);
1230 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1231 ftfont_info
->otf
= NULL
;
1232 #endif /* HAVE_LIBOTF */
1233 /* This means that there's no need of transformation. */
1234 ftfont_info
->matrix
.xx
= 0;
1235 font
->pixel_size
= size
;
1236 font
->driver
= &ftfont_driver
;
1237 font
->encoding_charset
= font
->repertory_charset
= -1;
1239 upEM
= ft_face
->units_per_EM
;
1240 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1241 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1244 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1245 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1246 font
->height
= ft_face
->height
* size
/ upEM
;
1250 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1251 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1252 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1254 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1255 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1257 spacing
= FC_PROPORTIONAL
;
1258 if (spacing
!= FC_PROPORTIONAL
1260 && spacing
!= FC_DUAL
1261 #endif /* FC_DUAL */
1263 font
->min_width
= font
->average_width
= font
->space_width
1264 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1265 : ft_face
->size
->metrics
.max_advance
>> 6);
1270 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1271 for (i
= 32, n
= 0; i
< 127; i
++)
1272 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1274 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1277 && (! font
->min_width
|| font
->min_width
> this_width
))
1278 font
->min_width
= this_width
;
1280 font
->space_width
= this_width
;
1281 font
->average_width
+= this_width
;
1285 font
->average_width
/= n
;
1288 font
->baseline_offset
= 0;
1289 font
->relative_compose
= 0;
1290 font
->default_ascent
= 0;
1291 font
->vertical_centering
= 0;
1294 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1295 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1299 font
->underline_position
= -1;
1300 font
->underline_thickness
= 0;
1307 ftfont_close (FRAME_PTR f
, struct font
*font
)
1309 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1310 Lisp_Object val
, cache
;
1312 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1313 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1314 xassert (CONSP (cache
));
1316 (XSAVE_VALUE (val
)->integer
)--;
1317 if (XSAVE_VALUE (val
)->integer
== 0)
1319 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1321 FT_Done_Face (cache_data
->ft_face
);
1323 if (ftfont_info
->otf
)
1324 OTF_close (ftfont_info
->otf
);
1326 cache_data
->ft_face
= NULL
;
1329 FT_Done_Size (ftfont_info
->ft_size
);
1333 ftfont_has_char (Lisp_Object font
, int c
)
1335 struct charset
*cs
= NULL
;
1337 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1338 && charset_jisx0208
>= 0)
1339 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1340 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1341 && charset_ksc5601
>= 0)
1342 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1344 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1346 if (FONT_ENTITY_P (font
))
1348 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1350 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1354 struct ftfont_info
*ftfont_info
;
1356 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1357 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1363 ftfont_encode_char (struct font
*font
, int c
)
1365 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1366 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1367 FT_ULong charcode
= c
;
1368 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1370 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1374 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1376 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1377 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1381 if (ftfont_info
->ft_size
!= ft_face
->size
)
1382 FT_Activate_Size (ftfont_info
->ft_size
);
1384 memset (metrics
, 0, sizeof (struct font_metrics
));
1385 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1387 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1389 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1395 metrics
->lbearing
= m
->horiBearingX
>> 6;
1396 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1397 metrics
->ascent
= m
->horiBearingY
>> 6;
1398 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1404 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1405 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1406 if (metrics
->rbearing
1407 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1409 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1410 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1411 metrics
->ascent
= m
->horiBearingY
>> 6;
1412 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1413 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1415 width
+= m
->horiAdvance
>> 6;
1419 width
+= font
->space_width
;
1423 metrics
->width
= width
;
1429 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1431 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1432 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1433 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1435 if (ftfont_info
->ft_size
!= ft_face
->size
)
1436 FT_Activate_Size (ftfont_info
->ft_size
);
1437 if (bits_per_pixel
== 1)
1439 #ifdef FT_LOAD_TARGET_MONO
1440 load_flags
|= FT_LOAD_TARGET_MONO
;
1442 load_flags
|= FT_LOAD_MONOCHROME
;
1445 else if (bits_per_pixel
!= 8)
1446 /* We don't support such a rendering. */
1449 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1451 bitmap
->bits_per_pixel
1452 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1453 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1454 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1455 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1457 if (bitmap
->bits_per_pixel
< 0)
1458 /* We don't suport that kind of pixel mode. */
1460 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1461 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1462 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1463 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1464 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1465 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1466 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1467 bitmap
->extra
= NULL
;
1473 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1476 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1477 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1479 if (ftfont_info
->ft_size
!= ft_face
->size
)
1480 FT_Activate_Size (ftfont_info
->ft_size
);
1481 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1483 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1485 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1487 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1488 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1495 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1497 Lisp_Object scripts
, langsyses
, features
, sym
;
1500 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1502 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1504 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1506 OTF_LangSys
*otf_langsys
;
1509 otf_langsys
= otf_script
->LangSys
+ j
;
1510 else if (otf_script
->DefaultLangSysOffset
)
1511 otf_langsys
= &otf_script
->DefaultLangSys
;
1515 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1517 l
= otf_langsys
->FeatureIndex
[k
];
1518 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1520 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1521 features
= Fcons (sym
, features
);
1524 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1527 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1530 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1531 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1539 ftfont_otf_capability (struct font
*font
)
1541 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1542 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1543 Lisp_Object gsub_gpos
;
1547 gsub_gpos
= Fcons (Qnil
, Qnil
);
1548 if (OTF_get_table (otf
, "GSUB") == 0
1549 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1550 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1551 if (OTF_get_table (otf
, "GPOS") == 0
1552 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1553 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1557 #ifdef HAVE_M17N_FLT
1559 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1560 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1561 /* We can use the new feature of libotf and m17n-flt to handle the
1562 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1563 some Agian scripts. */
1564 #define M17N_FLT_USE_NEW_FEATURE
1577 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1580 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1581 FT_Face ft_face
= flt_font_ft
->ft_face
;
1584 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1587 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1589 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1595 /* Operators for 26.6 fixed fractional pixel format */
1597 #define FLOOR(x) ((x) & -64)
1598 #define CEIL(x) (((x)+63) & -64)
1599 #define ROUND(x) (((x)+32) & -64)
1602 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1605 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1606 FT_Face ft_face
= flt_font_ft
->ft_face
;
1609 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1612 if (g
->code
!= FONT_INVALID_CODE
)
1614 FT_Glyph_Metrics
*m
;
1615 int lbearing
, rbearing
, ascent
, descent
, xadv
;
1617 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1619 m
= &ft_face
->glyph
->metrics
;
1620 if (flt_font_ft
->matrix
)
1625 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1626 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1627 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1628 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1629 for (i
= 0; i
< 4; i
++)
1630 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1631 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1632 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1633 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1634 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1638 g
->lbearing
= FLOOR (m
->horiBearingX
);
1639 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1640 g
->ascent
= CEIL (m
->horiBearingY
);
1641 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1643 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1648 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1649 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1650 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1659 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1661 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1663 #define FEATURE_ANY(IDX) \
1664 (spec->features[IDX] \
1665 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1667 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1668 OTF
*otf
= flt_font_ft
->otf
;
1672 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1673 /* Return 1 iff any of GSUB or GPOS support the script (and language). */
1675 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1677 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1680 for (i
= 0; i
< 2; i
++)
1681 if (! FEATURE_ANY (i
))
1683 if (FEATURE_NONE (i
))
1686 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1691 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1694 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1700 for (n
= 1; spec
->features
[i
][n
]; n
++);
1701 tags
= alloca (sizeof (OTF_Tag
) * n
);
1702 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1704 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1707 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1709 tags
[n
] = spec
->features
[i
][n
];
1711 #ifdef M17N_FLT_USE_NEW_FEATURE
1712 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1713 tags
, n
- negative
) != 1)
1715 #else /* not M17N_FLT_USE_NEW_FEATURE */
1716 if (n
- negative
> 0
1717 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1718 tags
, n
- negative
) != 1)
1720 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1727 #define DEVICE_DELTA(table, size) \
1728 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1729 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1733 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1734 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1736 if (anchor
->AnchorFormat
== 2)
1738 FT_Outline
*outline
;
1739 int ap
= anchor
->f
.f1
.AnchorPoint
;
1741 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1742 outline
= &ft_face
->glyph
->outline
;
1743 if (ap
< outline
->n_points
)
1745 *x
= outline
->points
[ap
].x
<< 6;
1746 *y
= outline
->points
[ap
].y
<< 6;
1749 else if (anchor
->AnchorFormat
== 3)
1751 if (anchor
->f
.f2
.XDeviceTable
.offset
1752 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1753 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1754 if (anchor
->f
.f2
.YDeviceTable
.offset
1755 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1756 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1760 static OTF_GlyphString otf_gstring
;
1763 setup_otf_gstring (int size
)
1765 if (otf_gstring
.size
== 0)
1767 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1768 otf_gstring
.size
= size
;
1770 else if (otf_gstring
.size
< size
)
1772 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1773 sizeof (OTF_Glyph
) * size
);
1774 otf_gstring
.size
= size
;
1776 otf_gstring
.used
= size
;
1777 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1780 #ifdef M17N_FLT_USE_NEW_FEATURE
1782 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1783 #define PACK_OTF_TAG(TAG) \
1784 ((((TAG) & 0x7F000000) >> 3) \
1785 | (((TAG) & 0x7F0000) >> 2) \
1786 | (((TAG) & 0x7F00) >> 1) \
1789 /* Assuming that FONT is an OpenType font, apply OpenType features
1790 specified in SPEC on glyphs between FROM and TO of IN, and record
1791 the lastly applied feature in each glyph of IN. If OUT is not
1792 NULL, append the resulting glyphs to OUT while storing glyph
1793 position adjustment information in ADJUSTMENT. */
1796 ftfont_drive_otf (MFLTFont
*font
,
1798 MFLTGlyphString
*in
,
1801 MFLTGlyphString
*out
,
1802 MFLTGlyphAdjustment
*adjustment
)
1804 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1805 FT_Face ft_face
= flt_font_ft
->ft_face
;
1806 OTF
*otf
= flt_font_ft
->otf
;
1807 int len
= to
- from
;
1810 char script
[5], *langsys
= NULL
;
1811 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1812 OTF_Feature
*features
;
1816 OTF_tag_name (spec
->script
, script
);
1819 langsys
= alloca (5);
1820 OTF_tag_name (spec
->langsys
, langsys
);
1822 for (i
= 0; i
< 2; i
++)
1826 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1828 for (j
= 0; spec
->features
[i
][j
]; j
++);
1830 p
= gsub_features
= alloca (6 * j
);
1832 p
= gpos_features
= alloca (6 * j
);
1833 for (j
= 0; spec
->features
[i
][j
]; j
++)
1835 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1836 *p
++ = '*', *p
++ = ',';
1839 OTF_tag_name (spec
->features
[i
][j
], p
);
1848 setup_otf_gstring (len
);
1849 for (i
= 0; i
< len
; i
++)
1851 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1852 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1855 OTF_drive_gdef (otf
, &otf_gstring
);
1856 gidx
= out
? out
->used
: from
;
1858 if (gsub_features
&& out
)
1860 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1863 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1865 features
= otf
->gsub
->FeatureList
.Feature
;
1866 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1869 int min_from
, max_to
;
1871 int feature_idx
= otfg
->positioning_type
>> 4;
1873 g
= out
->glyphs
+ out
->used
;
1874 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1875 if (g
->code
!= otfg
->glyph_id
)
1878 g
->code
= otfg
->glyph_id
;
1884 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1886 /* OTFG substitutes multiple glyphs in IN. */
1887 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1888 j
<= from
+ otfg
->f
.index
.to
; j
++)
1890 if (min_from
> in
->glyphs
[j
].from
)
1891 min_from
= in
->glyphs
[j
].from
;
1892 if (max_to
< in
->glyphs
[j
].to
)
1893 max_to
= in
->glyphs
[j
].to
;
1900 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1901 tag
= PACK_OTF_TAG (tag
);
1902 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1904 for (i
++, otfg
++; (i
< otf_gstring
.used
1905 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1908 g
= out
->glyphs
+ out
->used
;
1909 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1910 if (g
->code
!= otfg
->glyph_id
)
1913 g
->code
= otfg
->glyph_id
;
1916 feature_idx
= otfg
->positioning_type
>> 4;
1919 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1920 tag
= PACK_OTF_TAG (tag
);
1921 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1927 else if (gsub_features
)
1929 /* Just for checking which features will be applied. */
1930 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1933 features
= otf
->gsub
->FeatureList
.Feature
;
1934 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1937 int feature_idx
= otfg
->positioning_type
>> 4;
1941 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1942 tag
= PACK_OTF_TAG (tag
);
1943 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1945 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1946 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1953 if (out
->allocated
< out
->used
+ len
)
1955 for (i
= 0; i
< len
; i
++)
1956 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1959 if (gpos_features
&& out
)
1961 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1962 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1964 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1967 features
= otf
->gpos
->FeatureList
.Feature
;
1968 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1969 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1970 x_scale
= ft_face
->size
->metrics
.x_scale
;
1971 y_scale
= ft_face
->size
->metrics
.y_scale
;
1973 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1974 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1977 int feature_idx
= otfg
->positioning_type
>> 4;
1981 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1982 tag
= PACK_OTF_TAG (tag
);
1983 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1986 if (! otfg
->glyph_id
)
1988 switch (otfg
->positioning_type
& 0xF)
1992 case 1: /* Single */
1995 int format
= otfg
->f
.f1
.format
;
1997 if (format
& OTF_XPlacement
)
1999 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2000 if (format
& OTF_XPlaDevice
)
2002 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2003 if (format
& OTF_YPlacement
)
2005 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2006 if (format
& OTF_YPlaDevice
)
2008 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2009 if (format
& OTF_XAdvance
)
2011 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2012 if (format
& OTF_XAdvDevice
)
2014 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2015 if (format
& OTF_YAdvance
)
2017 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2018 if (format
& OTF_YAdvDevice
)
2020 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2021 adjustment
[i
].set
= 1;
2024 case 3: /* Cursive */
2025 /* Not yet supported. */
2027 case 4: /* Mark-to-Base */
2028 case 5: /* Mark-to-Ligature */
2032 goto label_adjust_anchor
;
2033 default: /* i.e. case 6 Mark-to-Mark */
2038 label_adjust_anchor
:
2040 int base_x
, base_y
, mark_x
, mark_y
;
2041 int this_from
, this_to
;
2043 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2044 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2045 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2046 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2048 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2049 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2050 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2051 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2052 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2053 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2054 adjustment
[i
].xoff
= (base_x
- mark_x
);
2055 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2056 adjustment
[i
].back
= (g
- prev
);
2057 adjustment
[i
].xadv
= 0;
2058 adjustment
[i
].advance_is_absolute
= 1;
2059 adjustment
[i
].set
= 1;
2060 this_from
= g
->from
;
2062 for (j
= 0; prev
+ j
< g
; j
++)
2064 if (this_from
> prev
[j
].from
)
2065 this_from
= prev
[j
].from
;
2066 if (this_to
< prev
[j
].to
)
2067 this_to
= prev
[j
].to
;
2069 for (; prev
<= g
; prev
++)
2071 prev
->from
= this_from
;
2076 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2078 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2084 else if (gpos_features
)
2086 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2089 features
= otf
->gpos
->FeatureList
.Feature
;
2090 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2092 if (otfg
->positioning_type
& 0xF)
2094 int feature_idx
= otfg
->positioning_type
>> 4;
2098 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2099 tag
= PACK_OTF_TAG (tag
);
2100 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2102 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2103 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2113 if (out
->allocated
< out
->used
+ len
)
2115 font
->get_metrics (font
, in
, from
, to
);
2116 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2117 sizeof (MFLTGlyph
) * len
);
2123 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2124 MFLTGlyphString
*in
, int from
, int to
)
2126 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2129 #else /* not M17N_FLT_USE_NEW_FEATURE */
2132 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2134 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2136 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2137 FT_Face ft_face
= flt_font_ft
->ft_face
;
2138 OTF
*otf
= flt_font_ft
->otf
;
2139 int len
= to
- from
;
2142 char script
[5], *langsys
= NULL
;
2143 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2147 OTF_tag_name (spec
->script
, script
);
2150 langsys
= alloca (5);
2151 OTF_tag_name (spec
->langsys
, langsys
);
2153 for (i
= 0; i
< 2; i
++)
2157 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2159 for (j
= 0; spec
->features
[i
][j
]; j
++);
2161 p
= gsub_features
= alloca (6 * j
);
2163 p
= gpos_features
= alloca (6 * j
);
2164 for (j
= 0; spec
->features
[i
][j
]; j
++)
2166 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2167 *p
++ = '*', *p
++ = ',';
2170 OTF_tag_name (spec
->features
[i
][j
], p
);
2179 setup_otf_gstring (len
);
2180 for (i
= 0; i
< len
; i
++)
2182 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2183 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2186 OTF_drive_gdef (otf
, &otf_gstring
);
2191 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2194 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2196 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2199 int min_from
, max_to
;
2202 g
= out
->glyphs
+ out
->used
;
2203 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2204 if (g
->code
!= otfg
->glyph_id
)
2207 g
->code
= otfg
->glyph_id
;
2213 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2215 /* OTFG substitutes multiple glyphs in IN. */
2216 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2217 j
<= from
+ otfg
->f
.index
.to
; j
++)
2219 if (min_from
> in
->glyphs
[j
].from
)
2220 min_from
= in
->glyphs
[j
].from
;
2221 if (max_to
< in
->glyphs
[j
].to
)
2222 max_to
= in
->glyphs
[j
].to
;
2227 for (i
++, otfg
++; (i
< otf_gstring
.used
2228 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2231 g
= out
->glyphs
+ out
->used
;
2232 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2233 if (g
->code
!= otfg
->glyph_id
)
2236 g
->code
= otfg
->glyph_id
;
2245 if (out
->allocated
< out
->used
+ len
)
2247 for (i
= 0; i
< len
; i
++)
2248 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2253 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2254 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2256 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2260 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2261 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2262 x_scale
= ft_face
->size
->metrics
.x_scale
;
2263 y_scale
= ft_face
->size
->metrics
.y_scale
;
2265 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2266 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2270 if (! otfg
->glyph_id
)
2272 switch (otfg
->positioning_type
)
2276 case 1: /* Single */
2279 int format
= otfg
->f
.f1
.format
;
2281 if (format
& OTF_XPlacement
)
2283 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2284 if (format
& OTF_XPlaDevice
)
2286 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2287 if (format
& OTF_YPlacement
)
2289 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2290 if (format
& OTF_YPlaDevice
)
2292 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2293 if (format
& OTF_XAdvance
)
2295 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2296 if (format
& OTF_XAdvDevice
)
2298 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2299 if (format
& OTF_YAdvance
)
2301 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2302 if (format
& OTF_YAdvDevice
)
2304 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2305 adjustment
[i
].set
= 1;
2308 case 3: /* Cursive */
2309 /* Not yet supported. */
2311 case 4: /* Mark-to-Base */
2312 case 5: /* Mark-to-Ligature */
2316 goto label_adjust_anchor
;
2317 default: /* i.e. case 6 Mark-to-Mark */
2322 label_adjust_anchor
:
2324 int base_x
, base_y
, mark_x
, mark_y
;
2325 int this_from
, this_to
;
2327 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2328 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2329 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2330 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2332 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2333 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2334 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2335 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2336 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2337 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2338 adjustment
[i
].xoff
= (base_x
- mark_x
);
2339 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2340 adjustment
[i
].back
= (g
- prev
);
2341 adjustment
[i
].xadv
= 0;
2342 adjustment
[i
].advance_is_absolute
= 1;
2343 adjustment
[i
].set
= 1;
2344 this_from
= g
->from
;
2346 for (j
= 0; prev
+ j
< g
; j
++)
2348 if (this_from
> prev
[j
].from
)
2349 this_from
= prev
[j
].from
;
2350 if (this_to
< prev
[j
].to
)
2351 this_to
= prev
[j
].to
;
2353 for (; prev
<= g
; prev
++)
2355 prev
->from
= this_from
;
2360 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2362 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2371 if (out
->allocated
< out
->used
+ len
)
2373 font
->get_metrics (font
, in
, from
, to
);
2374 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2375 sizeof (MFLTGlyph
) * len
);
2380 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2382 static MFLTGlyphString gstring
;
2384 static int m17n_flt_initialized
;
2387 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2388 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2390 EMACS_UINT len
= LGSTRING_GLYPH_LEN (lgstring
);
2392 struct MFLTFontFT flt_font_ft
;
2394 int with_variation_selector
= 0;
2396 if (! m17n_flt_initialized
)
2399 #ifdef M17N_FLT_USE_NEW_FEATURE
2400 mflt_enable_new_feature
= 1;
2401 mflt_try_otf
= ftfont_try_otf
;
2402 #endif /* M17N_FLT_USE_NEW_FEATURE */
2403 m17n_flt_initialized
= 1;
2406 for (i
= 0; i
< len
; i
++)
2408 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2413 c
= LGLYPH_CHAR (g
);
2414 if (CHAR_VARIATION_SELECTOR_P (c
))
2415 with_variation_selector
++;
2418 if (with_variation_selector
)
2420 setup_otf_gstring (len
);
2421 for (i
= 0; i
< len
; i
++)
2423 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2425 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2426 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2427 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2429 OTF_drive_cmap (otf
, &otf_gstring
);
2430 for (i
= 0; i
< otf_gstring
.used
; i
++)
2432 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2433 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2434 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2436 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2437 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2438 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2440 if (len
> otf_gstring
.used
)
2442 len
= otf_gstring
.used
;
2443 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2447 if (gstring
.allocated
== 0)
2449 gstring
.allocated
= len
* 2;
2450 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2451 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2453 else if (gstring
.allocated
< len
* 2)
2455 gstring
.allocated
= len
* 2;
2456 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2457 sizeof (MFLTGlyph
) * gstring
.allocated
);
2459 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2460 for (i
= 0; i
< len
; i
++)
2462 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2464 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2465 if (with_variation_selector
)
2467 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2468 gstring
.glyphs
[i
].encoded
= 1;
2476 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2479 flt_font_ft
.flt_font
.family
= Mnil
;
2481 flt_font_ft
.flt_font
.family
2482 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2484 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2485 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2486 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2487 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2488 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2489 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2490 flt_font_ft
.flt_font
.internal
= NULL
;
2491 flt_font_ft
.font
= font
;
2492 flt_font_ft
.ft_face
= ft_face
;
2493 flt_font_ft
.otf
= otf
;
2494 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2496 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2497 /* A little bit ad hoc. Perhaps, shaper must get script and
2498 language information, and select a proper flt for them
2500 flt
= mflt_get (msymbol ("combining"));
2501 for (i
= 0; i
< 3; i
++)
2503 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2506 gstring
.allocated
+= gstring
.allocated
;
2507 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2508 sizeof (MFLTGlyph
) * gstring
.allocated
);
2510 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2512 for (i
= 0; i
< gstring
.used
; i
++)
2514 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2516 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2517 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2520 for (i
= 0; i
< gstring
.used
; i
++)
2522 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2523 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2527 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2528 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2530 LGLYPH_SET_FROM (lglyph
, g
->from
);
2531 LGLYPH_SET_TO (lglyph
, g
->to
);
2532 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2533 LGLYPH_SET_CODE (lglyph
, g
->code
);
2534 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2535 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2536 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2537 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2538 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2543 vec
= Fmake_vector (make_number (3), Qnil
);
2544 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2545 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2546 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2547 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2550 return make_number (i
);
2554 ftfont_shape (Lisp_Object lgstring
)
2557 struct ftfont_info
*ftfont_info
;
2560 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2561 ftfont_info
= (struct ftfont_info
*) font
;
2562 otf
= ftfont_get_otf (ftfont_info
);
2564 return make_number (0);
2565 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2566 &ftfont_info
->matrix
);
2569 #endif /* HAVE_M17N_FLT */
2571 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2574 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2576 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2577 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2581 return OTF_get_variation_glyphs (otf
, c
, variations
);
2584 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2585 #endif /* HAVE_LIBOTF */
2588 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2592 #ifdef FC_FONTFORMAT
2595 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2597 if (strcmp ((char *) str
, "TrueType") == 0)
2598 return intern ("truetype");
2599 if (strcmp ((char *) str
, "Type 1") == 0)
2600 return intern ("type1");
2601 if (strcmp ((char *) str
, "PCF") == 0)
2602 return intern ("pcf");
2603 if (strcmp ((char *) str
, "BDF") == 0)
2604 return intern ("bdf");
2606 #endif /* FC_FONTFORMAT */
2607 if (STRINGP (filename
))
2609 int len
= SBYTES (filename
);
2613 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2614 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2615 return intern ("truetype");
2616 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2617 return intern ("type1");
2618 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2619 return intern ("pcf");
2620 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2621 return intern ("bdf");
2624 return intern ("unknown");
2627 static const char *const ftfont_booleans
[] = {
2640 static const char *const ftfont_non_booleans
[] = {
2672 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2674 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2679 syms_of_ftfont (void)
2681 DEFSYM (Qfreetype
, "freetype");
2682 DEFSYM (Qmonospace
, "monospace");
2683 DEFSYM (Qsans_serif
, "sans-serif");
2684 DEFSYM (Qserif
, "serif");
2685 DEFSYM (Qmono
, "mono");
2686 DEFSYM (Qsans
, "sans");
2687 DEFSYM (Qsans__serif
, "sans serif");
2689 staticpro (&freetype_font_cache
);
2690 freetype_font_cache
= Fcons (Qt
, Qnil
);
2692 staticpro (&ftfont_generic_family_list
);
2693 ftfont_generic_family_list
2694 = Fcons (Fcons (Qmonospace
, Qt
),
2695 Fcons (Fcons (Qsans_serif
, Qt
),
2696 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2698 staticpro (&ft_face_cache
);
2699 ft_face_cache
= Qnil
;
2701 ftfont_driver
.type
= Qfreetype
;
2702 register_font_driver (&ftfont_driver
, NULL
);