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
));
218 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
219 font_put_extra (val
, QCfont_entity
, key
);
223 entity
= font_make_entity ();
224 XSETCAR (cache
, entity
);
226 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
227 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
229 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
231 char *s
= (char *) str
;
232 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
234 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
236 char *s
= (char *) str
;
237 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
239 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
241 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
242 numeric
= FC_WEIGHT_MEDIUM
;
243 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
245 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
248 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
250 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
252 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
254 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
256 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
259 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
260 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
261 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
262 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
265 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
267 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
270 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
271 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
275 /* As this font is not scalable, parhaps this is a BDF or PCF
279 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
280 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
281 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
285 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
286 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
287 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
288 FT_Done_Face (ft_face
);
292 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
293 font_put_extra (entity
, QCfont_entity
, key
);
298 static Lisp_Object ftfont_generic_family_list
;
301 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
308 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
309 if (EQ (family
, Qmono
))
311 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
312 family
= Qsans_serif
;
313 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
316 if (! EQ (XCDR (slot
), Qt
))
318 pattern
= FcPatternDuplicate (pattern
);
321 FcPatternDel (pattern
, FC_FOUNDRY
);
322 FcPatternDel (pattern
, FC_FAMILY
);
323 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
324 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
326 /* This is to avoid the effect of locale. */
327 static const FcChar8 lang
[] = "en";
328 langset
= FcLangSetCreate ();
329 FcLangSetAdd (langset
, lang
);
330 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
331 FcLangSetDestroy (langset
);
333 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
334 FcDefaultSubstitute (pattern
);
335 match
= FcFontMatch (NULL
, pattern
, &result
);
340 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
341 family
= intern ((char *) fam
);
345 XSETCDR (slot
, family
);
346 if (match
) FcPatternDestroy (match
);
348 if (pattern
) FcPatternDestroy (pattern
);
352 struct ftfont_cache_data
355 FcCharSet
*fc_charset
;
359 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
361 Lisp_Object cache
, val
, entity
;
362 struct ftfont_cache_data
*cache_data
;
364 if (FONT_ENTITY_P (key
))
367 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
368 xassert (CONSP (val
));
374 if (NILP (ft_face_cache
))
377 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
380 if (NILP (ft_face_cache
))
386 ft_face_cache
= Fmake_hash_table (2, args
);
388 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
389 cache_data
->ft_face
= NULL
;
390 cache_data
->fc_charset
= NULL
;
391 val
= make_save_value (NULL
, 0);
392 XSAVE_VALUE (val
)->integer
= 0;
393 XSAVE_VALUE (val
)->pointer
= cache_data
;
394 cache
= Fcons (Qnil
, val
);
395 Fputhash (key
, cache
, ft_face_cache
);
400 cache_data
= XSAVE_VALUE (val
)->pointer
;
403 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
406 if (cache_for
== FTFONT_CACHE_FOR_FACE
407 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
409 char *filename
= SSDATA (XCAR (key
));
410 int idx
= XINT (XCDR (key
));
412 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
415 && FT_Init_FreeType (&ft_library
) != 0)
417 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
423 FcPattern
*pat
= NULL
;
424 FcFontSet
*fontset
= NULL
;
425 FcObjectSet
*objset
= NULL
;
426 FcCharSet
*charset
= NULL
;
428 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
429 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
432 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
435 fontset
= FcFontList (NULL
, pat
, objset
);
438 if (fontset
&& fontset
->nfont
> 0
439 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
442 cache_data
->fc_charset
= FcCharSetCopy (charset
);
444 cache_data
->fc_charset
= FcCharSetCreate ();
448 FcFontSetDestroy (fontset
);
450 FcObjectSetDestroy (objset
);
452 FcPatternDestroy (pat
);
459 ftfont_get_fc_charset (Lisp_Object entity
)
461 Lisp_Object val
, cache
;
462 struct ftfont_cache_data
*cache_data
;
464 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
466 cache_data
= XSAVE_VALUE (val
)->pointer
;
467 return cache_data
->fc_charset
;
472 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
476 if (ftfont_info
->otf
)
477 return ftfont_info
->otf
;
478 if (! ftfont_info
->maybe_otf
)
480 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
481 if (! otf
|| OTF_get_table (otf
, "head") < 0)
485 ftfont_info
->maybe_otf
= 0;
488 ftfont_info
->otf
= otf
;
491 #endif /* HAVE_LIBOTF */
493 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
494 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
495 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
496 static Lisp_Object
ftfont_list_family (Lisp_Object
);
497 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
498 static void ftfont_close (FRAME_PTR
, struct font
*);
499 static int ftfont_has_char (Lisp_Object
, int);
500 static unsigned ftfont_encode_char (struct font
*, int);
501 static int ftfont_text_extents (struct font
*, unsigned *, int,
502 struct font_metrics
*);
503 static int ftfont_get_bitmap (struct font
*, unsigned,
504 struct font_bitmap
*, int);
505 static int ftfont_anchor_point (struct font
*, unsigned, int,
508 static Lisp_Object
ftfont_otf_capability (struct font
*);
509 # ifdef HAVE_M17N_FLT
510 static Lisp_Object
ftfont_shape (Lisp_Object
);
514 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
515 static int ftfont_variation_glyphs (struct font
*, int c
,
516 unsigned variations
[256]);
517 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
519 struct font_driver ftfont_driver
=
522 0, /* case insensitive */
527 NULL
, /* free_entity */
530 /* We can't draw a text without device dependent functions. */
531 NULL
, /* prepare_face */
532 NULL
, /* done_face */
536 /* We can't draw a text without device dependent functions. */
539 NULL
, /* get_bitmap */
540 NULL
, /* free_bitmap */
541 NULL
, /* get_outline */
544 ftfont_otf_capability
,
545 #else /* not HAVE_LIBOTF */
547 #endif /* not HAVE_LIBOTF */
548 NULL
, /* otf_drive */
549 NULL
, /* start_for_frame */
550 NULL
, /* end_for_frame */
551 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
553 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
555 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
558 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
559 ftfont_variation_glyphs
,
564 ftfont_filter_properties
, /* filter_properties */
568 ftfont_get_cache (FRAME_PTR f
)
570 return freetype_font_cache
;
574 ftfont_get_charset (Lisp_Object registry
)
576 char *str
= SSDATA (SYMBOL_NAME (registry
));
577 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
581 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
585 else if (str
[i
] == '*')
592 regexp
= make_unibyte_string (re
, j
);
593 for (i
= 0; fc_charset_table
[i
].name
; i
++)
594 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
596 if (! fc_charset_table
[i
].name
)
598 if (! fc_charset_table
[i
].fc_charset
)
600 FcCharSet
*charset
= FcCharSetCreate ();
601 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
605 for (j
= 0; uniquifier
[j
]; j
++)
606 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
608 FcCharSetDestroy (charset
);
611 fc_charset_table
[i
].fc_charset
= charset
;
619 unsigned int script_tag
, langsys_tag
;
621 unsigned int *features
[2];
624 #define OTF_SYM_TAG(SYM, TAG) \
626 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
627 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
630 #define OTF_TAG_STR(TAG, P) \
632 (P)[0] = (char) (TAG >> 24); \
633 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
634 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
635 (P)[3] = (char) (TAG & 0xFF); \
640 #define OTF_TAG_SYM(SYM, TAG) \
644 OTF_TAG_STR (TAG, str); \
645 (SYM) = font_intern_prop (str, 4, 1); \
650 static struct OpenTypeSpec
*
651 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
653 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
659 spec
->script
= XCAR (otf_spec
);
660 if (! NILP (spec
->script
))
662 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
663 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
664 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
665 spec
->script
= XCDR (val
);
670 spec
->script_tag
= 0x44464C54; /* "DFLT" */
671 otf_spec
= XCDR (otf_spec
);
672 spec
->langsys_tag
= 0;
673 if (! NILP (otf_spec
))
675 val
= XCAR (otf_spec
);
677 OTF_SYM_TAG (val
, spec
->langsys_tag
);
678 otf_spec
= XCDR (otf_spec
);
680 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
681 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
685 val
= XCAR (otf_spec
);
690 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
692 : malloc (sizeof (int) * XINT (len
)));
693 if (! spec
->features
[i
])
695 if (i
> 0 && spec
->features
[0])
696 free (spec
->features
[0]);
700 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
702 if (NILP (XCAR (val
)))
708 OTF_SYM_TAG (XCAR (val
), tag
);
709 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
712 spec
->nfeatures
[i
] = j
;
718 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
720 Lisp_Object tmp
, extra
;
721 FcPattern
*pattern
= NULL
;
722 FcCharSet
*charset
= NULL
;
723 FcLangSet
*langset
= NULL
;
727 Lisp_Object script
= Qnil
;
728 Lisp_Object registry
;
731 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
733 /* Fontconfig doesn't support reverse-italic/obligue. */
736 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
737 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
738 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
739 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
742 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
744 || EQ (registry
, Qascii_0
)
745 || EQ (registry
, Qiso10646_1
)
746 || EQ (registry
, Qunicode_bmp
))
752 fc_charset_idx
= ftfont_get_charset (registry
);
753 if (fc_charset_idx
< 0)
755 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
756 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
757 lang
= (FcChar8
*) *langname
;
760 langset
= FcLangSetCreate ();
763 FcLangSetAdd (langset
, lang
);
768 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
769 CONSP (extra
); extra
= XCDR (extra
))
771 Lisp_Object key
, val
;
773 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
779 else if (EQ (key
, QClang
))
782 langset
= FcLangSetCreate ();
787 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
791 for (; CONSP (val
); val
= XCDR (val
))
792 if (SYMBOLP (XCAR (val
))
793 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
796 else if (EQ (key
, QCotf
))
800 *otspec
= ftfont_get_open_type_spec (val
);
803 strcat (otlayout
, "otlayout:");
804 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
805 script
= (*otspec
)->script
;
808 else if (EQ (key
, QCscript
))
810 else if (EQ (key
, QCscalable
))
811 scalable
= ! NILP (val
);
814 if (! NILP (script
) && ! charset
)
816 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
818 if (CONSP (chars
) && CONSP (CDR (chars
)))
820 charset
= FcCharSetCreate ();
823 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
824 if (CHARACTERP (XCAR (chars
))
825 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
830 pattern
= FcPatternCreate ();
833 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
835 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
837 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
839 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
842 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
845 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
848 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
851 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
857 /* We come here because of unexpected error in fontconfig API call
858 (usually insufficient memory). */
861 FcPatternDestroy (pattern
);
866 if ((*otspec
)->nfeatures
[0] > 0)
867 free ((*otspec
)->features
[0]);
868 if ((*otspec
)->nfeatures
[1] > 0)
869 free ((*otspec
)->features
[1]);
875 if (langset
) FcLangSetDestroy (langset
);
876 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
881 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
883 Lisp_Object val
= Qnil
, family
, adstyle
;
886 FcFontSet
*fontset
= NULL
;
887 FcObjectSet
*objset
= NULL
;
889 Lisp_Object chars
= Qnil
;
890 char otlayout
[15]; /* For "otlayout:XXXX" */
891 struct OpenTypeSpec
*otspec
= NULL
;
893 const char *langname
= NULL
;
895 if (! fc_initialized
)
901 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
904 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
906 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
909 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
910 if (CONSP (val
) && VECTORP (XCDR (val
)))
915 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
916 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
917 family
= AREF (spec
, FONT_FAMILY_INDEX
);
920 Lisp_Object resolved
;
922 resolved
= ftfont_resolve_generic_family (family
, pattern
);
923 if (! NILP (resolved
))
925 FcPatternDel (pattern
, FC_FAMILY
);
926 if (! FcPatternAddString (pattern
, FC_FAMILY
,
927 SYMBOL_FcChar8 (resolved
)))
931 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
932 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
934 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
935 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
936 FC_STYLE
, FC_FILE
, FC_INDEX
,
939 #endif /* FC_CAPABILITY */
947 FcObjectSetAdd (objset
, FC_CHARSET
);
949 fontset
= FcFontList (NULL
, pattern
, objset
);
950 if (! fontset
|| fontset
->nfont
== 0)
953 /* Need fix because this finds any fonts. */
954 if (fontset
->nfont
== 0 && ! NILP (family
))
956 /* Try maching with configuration. For instance, the
957 configuration may specify "Nimbus Mono L" as an alias of
959 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
960 SYMBOL_FcChar8 (family
), NULL
);
963 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
966 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
969 FcPatternDel (pattern
, FC_FAMILY
);
970 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
971 FcFontSetDestroy (fontset
);
972 fontset
= FcFontList (NULL
, pattern
, objset
);
973 if (fontset
&& fontset
->nfont
> 0)
979 for (i
= 0; i
< fontset
->nfont
; i
++)
987 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
998 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
1000 || ! strstr ((char *) this, otlayout
))
1003 #endif /* FC_CAPABILITY */
1010 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1013 otf
= OTF_open ((char *) file
);
1016 if (OTF_check_features (otf
, 1,
1017 otspec
->script_tag
, otspec
->langsys_tag
,
1018 otspec
->features
[0],
1019 otspec
->nfeatures
[0]) != 1
1020 || OTF_check_features (otf
, 0,
1021 otspec
->script_tag
, otspec
->langsys_tag
,
1022 otspec
->features
[1],
1023 otspec
->nfeatures
[1]) != 1)
1026 #endif /* HAVE_LIBOTF */
1027 if (VECTORP (chars
))
1031 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1034 for (j
= 0; j
< ASIZE (chars
); j
++)
1035 if (NATNUMP (AREF (chars
, j
))
1036 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1038 if (j
== ASIZE (chars
))
1041 if (! NILP (adstyle
) || langname
)
1043 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1045 if (! NILP (adstyle
)
1046 && (NILP (this_adstyle
)
1047 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1048 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1051 && ! NILP (this_adstyle
)
1052 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1055 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1056 AREF (spec
, FONT_EXTRA_INDEX
));
1057 if (! NILP (entity
))
1058 val
= Fcons (entity
, val
);
1060 val
= Fnreverse (val
);
1064 /* We come here because of unexpected error in fontconfig API call
1065 (usually insufficient memory). */
1069 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1070 if (objset
) FcObjectSetDestroy (objset
);
1071 if (fontset
) FcFontSetDestroy (fontset
);
1072 if (pattern
) FcPatternDestroy (pattern
);
1077 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1079 Lisp_Object entity
= Qnil
;
1080 FcPattern
*pattern
, *match
= NULL
;
1082 char otlayout
[15]; /* For "otlayout:XXXX" */
1083 struct OpenTypeSpec
*otspec
= NULL
;
1084 const char *langname
= NULL
;
1086 if (! fc_initialized
)
1092 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1096 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1100 value
.type
= FcTypeDouble
;
1101 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1102 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1104 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1106 FcDefaultSubstitute (pattern
);
1107 match
= FcFontMatch (NULL
, pattern
, &result
);
1110 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1111 FcPatternDestroy (match
);
1112 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1113 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1114 ftfont_generic_family_list
))
1115 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1116 AREF (entity
, FONT_FAMILY_INDEX
))))
1120 FcPatternDestroy (pattern
);
1122 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1127 ftfont_list_family (Lisp_Object frame
)
1129 Lisp_Object list
= Qnil
;
1130 FcPattern
*pattern
= NULL
;
1131 FcFontSet
*fontset
= NULL
;
1132 FcObjectSet
*objset
= NULL
;
1135 if (! fc_initialized
)
1141 pattern
= FcPatternCreate ();
1144 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1147 fontset
= FcFontList (NULL
, pattern
, objset
);
1151 for (i
= 0; i
< fontset
->nfont
; i
++)
1153 FcPattern
*pat
= fontset
->fonts
[i
];
1156 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1157 list
= Fcons (intern ((char *) str
), list
);
1161 if (objset
) FcObjectSetDestroy (objset
);
1162 if (fontset
) FcFontSetDestroy (fontset
);
1163 if (pattern
) FcPatternDestroy (pattern
);
1170 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1172 struct ftfont_info
*ftfont_info
;
1174 struct ftfont_cache_data
*cache_data
;
1178 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1185 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1189 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1192 filename
= XCAR (val
);
1195 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1196 ft_face
= cache_data
->ft_face
;
1197 if (XSAVE_VALUE (val
)->integer
> 0)
1199 /* FT_Face in this cache is already used by the different size. */
1200 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1202 if (FT_Activate_Size (ft_size
) != 0)
1204 FT_Done_Size (ft_size
);
1208 XSAVE_VALUE (val
)->integer
++;
1209 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1212 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1214 if (XSAVE_VALUE (val
)->integer
== 0)
1215 FT_Done_Face (ft_face
);
1219 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1220 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1221 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1223 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1224 len
= font_unparse_fcname (entity
, size
, name
, 256);
1226 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1228 ASET (font_object
, FONT_FULLNAME_INDEX
,
1229 AREF (font_object
, FONT_NAME_INDEX
));
1230 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1231 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1232 font
= XFONT_OBJECT (font_object
);
1233 ftfont_info
= (struct ftfont_info
*) font
;
1234 ftfont_info
->ft_size
= ft_face
->size
;
1235 ftfont_info
->index
= XINT (idx
);
1237 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1238 ftfont_info
->otf
= NULL
;
1239 #endif /* HAVE_LIBOTF */
1240 /* This means that there's no need of transformation. */
1241 ftfont_info
->matrix
.xx
= 0;
1242 font
->pixel_size
= size
;
1243 font
->driver
= &ftfont_driver
;
1244 font
->encoding_charset
= font
->repertory_charset
= -1;
1246 upEM
= ft_face
->units_per_EM
;
1247 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1248 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1251 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1252 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1253 font
->height
= ft_face
->height
* size
/ upEM
;
1257 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1258 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1259 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1261 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1262 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1264 spacing
= FC_PROPORTIONAL
;
1265 if (spacing
!= FC_PROPORTIONAL
1267 && spacing
!= FC_DUAL
1268 #endif /* FC_DUAL */
1270 font
->min_width
= font
->average_width
= font
->space_width
1271 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1272 : ft_face
->size
->metrics
.max_advance
>> 6);
1277 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1278 for (i
= 32, n
= 0; i
< 127; i
++)
1279 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1281 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1284 && (! font
->min_width
|| font
->min_width
> this_width
))
1285 font
->min_width
= this_width
;
1287 font
->space_width
= this_width
;
1288 font
->average_width
+= this_width
;
1292 font
->average_width
/= n
;
1295 font
->baseline_offset
= 0;
1296 font
->relative_compose
= 0;
1297 font
->default_ascent
= 0;
1298 font
->vertical_centering
= 0;
1301 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1302 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1306 font
->underline_position
= -1;
1307 font
->underline_thickness
= 0;
1314 ftfont_close (FRAME_PTR f
, struct font
*font
)
1316 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1317 Lisp_Object val
, cache
;
1319 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1320 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1321 xassert (CONSP (cache
));
1323 (XSAVE_VALUE (val
)->integer
)--;
1324 if (XSAVE_VALUE (val
)->integer
== 0)
1326 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1328 FT_Done_Face (cache_data
->ft_face
);
1330 if (ftfont_info
->otf
)
1331 OTF_close (ftfont_info
->otf
);
1333 cache_data
->ft_face
= NULL
;
1336 FT_Done_Size (ftfont_info
->ft_size
);
1340 ftfont_has_char (Lisp_Object font
, int c
)
1342 struct charset
*cs
= NULL
;
1344 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1345 && charset_jisx0208
>= 0)
1346 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1347 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1348 && charset_ksc5601
>= 0)
1349 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1351 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1353 if (FONT_ENTITY_P (font
))
1355 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1357 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1361 struct ftfont_info
*ftfont_info
;
1363 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1364 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1370 ftfont_encode_char (struct font
*font
, int c
)
1372 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1373 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1374 FT_ULong charcode
= c
;
1375 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1377 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1381 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1383 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1384 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1388 if (ftfont_info
->ft_size
!= ft_face
->size
)
1389 FT_Activate_Size (ftfont_info
->ft_size
);
1391 memset (metrics
, 0, sizeof (struct font_metrics
));
1392 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1394 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1396 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1402 metrics
->lbearing
= m
->horiBearingX
>> 6;
1403 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1404 metrics
->ascent
= m
->horiBearingY
>> 6;
1405 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1411 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1412 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1413 if (metrics
->rbearing
1414 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1416 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1417 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1418 metrics
->ascent
= m
->horiBearingY
>> 6;
1419 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1420 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1422 width
+= m
->horiAdvance
>> 6;
1426 width
+= font
->space_width
;
1430 metrics
->width
= width
;
1436 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1438 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1439 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1440 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1442 if (ftfont_info
->ft_size
!= ft_face
->size
)
1443 FT_Activate_Size (ftfont_info
->ft_size
);
1444 if (bits_per_pixel
== 1)
1446 #ifdef FT_LOAD_TARGET_MONO
1447 load_flags
|= FT_LOAD_TARGET_MONO
;
1449 load_flags
|= FT_LOAD_MONOCHROME
;
1452 else if (bits_per_pixel
!= 8)
1453 /* We don't support such a rendering. */
1456 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1458 bitmap
->bits_per_pixel
1459 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1460 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1461 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1462 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1464 if (bitmap
->bits_per_pixel
< 0)
1465 /* We don't suport that kind of pixel mode. */
1467 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1468 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1469 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1470 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1471 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1472 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1473 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1474 bitmap
->extra
= NULL
;
1480 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1483 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1484 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1486 if (ftfont_info
->ft_size
!= ft_face
->size
)
1487 FT_Activate_Size (ftfont_info
->ft_size
);
1488 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1490 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1492 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1494 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1495 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1502 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1504 Lisp_Object scripts
, langsyses
, features
, sym
;
1507 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1509 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1511 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1513 OTF_LangSys
*otf_langsys
;
1516 otf_langsys
= otf_script
->LangSys
+ j
;
1517 else if (otf_script
->DefaultLangSysOffset
)
1518 otf_langsys
= &otf_script
->DefaultLangSys
;
1522 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1524 l
= otf_langsys
->FeatureIndex
[k
];
1525 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1527 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1528 features
= Fcons (sym
, features
);
1531 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1534 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1537 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1538 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1546 ftfont_otf_capability (struct font
*font
)
1548 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1549 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1550 Lisp_Object gsub_gpos
;
1554 gsub_gpos
= Fcons (Qnil
, Qnil
);
1555 if (OTF_get_table (otf
, "GSUB") == 0
1556 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1557 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1558 if (OTF_get_table (otf
, "GPOS") == 0
1559 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1560 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1564 #ifdef HAVE_M17N_FLT
1566 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1567 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1568 /* We can use the new feature of libotf and m17n-flt to handle the
1569 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1570 some Agian scripts. */
1571 #define M17N_FLT_USE_NEW_FEATURE
1584 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1587 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1588 FT_Face ft_face
= flt_font_ft
->ft_face
;
1591 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1594 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1596 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1602 /* Operators for 26.6 fixed fractional pixel format */
1604 #define FLOOR(x) ((x) & -64)
1605 #define CEIL(x) (((x)+63) & -64)
1606 #define ROUND(x) (((x)+32) & -64)
1609 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1612 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1613 FT_Face ft_face
= flt_font_ft
->ft_face
;
1616 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1619 if (g
->code
!= FONT_INVALID_CODE
)
1621 FT_Glyph_Metrics
*m
;
1623 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1625 m
= &ft_face
->glyph
->metrics
;
1626 if (flt_font_ft
->matrix
)
1631 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1632 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1633 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1634 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1635 for (i
= 0; i
< 4; i
++)
1636 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1637 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1638 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1639 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1640 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1644 g
->lbearing
= FLOOR (m
->horiBearingX
);
1645 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1646 g
->ascent
= CEIL (m
->horiBearingY
);
1647 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1649 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1654 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1655 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1656 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1665 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1667 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1669 #define FEATURE_ANY(IDX) \
1670 (spec->features[IDX] \
1671 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1673 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1674 OTF
*otf
= flt_font_ft
->otf
;
1678 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1679 /* Return 1 iff any of GSUB or GPOS support the script (and language). */
1681 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1683 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1686 for (i
= 0; i
< 2; i
++)
1687 if (! FEATURE_ANY (i
))
1689 if (FEATURE_NONE (i
))
1692 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1697 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1700 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1706 for (n
= 1; spec
->features
[i
][n
]; n
++);
1707 tags
= alloca (sizeof (OTF_Tag
) * n
);
1708 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1710 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1713 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1715 tags
[n
] = spec
->features
[i
][n
];
1717 #ifdef M17N_FLT_USE_NEW_FEATURE
1718 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1719 tags
, n
- negative
) != 1)
1721 #else /* not M17N_FLT_USE_NEW_FEATURE */
1722 if (n
- negative
> 0
1723 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1724 tags
, n
- negative
) != 1)
1726 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1733 #define DEVICE_DELTA(table, size) \
1734 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1735 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1739 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1740 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1742 if (anchor
->AnchorFormat
== 2)
1744 FT_Outline
*outline
;
1745 int ap
= anchor
->f
.f1
.AnchorPoint
;
1747 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1748 outline
= &ft_face
->glyph
->outline
;
1749 if (ap
< outline
->n_points
)
1751 *x
= outline
->points
[ap
].x
<< 6;
1752 *y
= outline
->points
[ap
].y
<< 6;
1755 else if (anchor
->AnchorFormat
== 3)
1757 if (anchor
->f
.f2
.XDeviceTable
.offset
1758 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1759 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1760 if (anchor
->f
.f2
.YDeviceTable
.offset
1761 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1762 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1766 static OTF_GlyphString otf_gstring
;
1769 setup_otf_gstring (int size
)
1771 if (otf_gstring
.size
< size
)
1773 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1774 size
, sizeof (OTF_Glyph
));
1775 otf_gstring
.size
= size
;
1777 otf_gstring
.used
= size
;
1778 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1781 #ifdef M17N_FLT_USE_NEW_FEATURE
1783 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1784 #define PACK_OTF_TAG(TAG) \
1785 ((((TAG) & 0x7F000000) >> 3) \
1786 | (((TAG) & 0x7F0000) >> 2) \
1787 | (((TAG) & 0x7F00) >> 1) \
1790 /* Assuming that FONT is an OpenType font, apply OpenType features
1791 specified in SPEC on glyphs between FROM and TO of IN, and record
1792 the lastly applied feature in each glyph of IN. If OUT is not
1793 NULL, append the resulting glyphs to OUT while storing glyph
1794 position adjustment information in ADJUSTMENT. */
1797 ftfont_drive_otf (MFLTFont
*font
,
1799 MFLTGlyphString
*in
,
1802 MFLTGlyphString
*out
,
1803 MFLTGlyphAdjustment
*adjustment
)
1805 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1806 FT_Face ft_face
= flt_font_ft
->ft_face
;
1807 OTF
*otf
= flt_font_ft
->otf
;
1808 int len
= to
- from
;
1811 char script
[5], *langsys
= NULL
;
1812 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1813 OTF_Feature
*features
;
1817 OTF_tag_name (spec
->script
, script
);
1820 langsys
= alloca (5);
1821 OTF_tag_name (spec
->langsys
, langsys
);
1823 for (i
= 0; i
< 2; i
++)
1827 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1829 for (j
= 0; spec
->features
[i
][j
]; j
++);
1831 p
= gsub_features
= alloca (6 * j
);
1833 p
= gpos_features
= alloca (6 * j
);
1834 for (j
= 0; spec
->features
[i
][j
]; j
++)
1836 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1837 *p
++ = '*', *p
++ = ',';
1840 OTF_tag_name (spec
->features
[i
][j
], p
);
1849 setup_otf_gstring (len
);
1850 for (i
= 0; i
< len
; i
++)
1852 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1853 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1856 OTF_drive_gdef (otf
, &otf_gstring
);
1857 gidx
= out
? out
->used
: from
;
1859 if (gsub_features
&& out
)
1861 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1864 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1866 features
= otf
->gsub
->FeatureList
.Feature
;
1867 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1870 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_INT 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
++;
2419 lint_assume (len
<= TYPE_MAXIMUM (EMACS_INT
) - 2);
2421 if (with_variation_selector
)
2423 setup_otf_gstring (len
);
2424 for (i
= 0; i
< len
; i
++)
2426 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2428 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2429 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2430 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2432 OTF_drive_cmap (otf
, &otf_gstring
);
2433 for (i
= 0; i
< otf_gstring
.used
; i
++)
2435 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2436 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2437 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2439 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2440 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2441 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2443 if (len
> otf_gstring
.used
)
2445 len
= otf_gstring
.used
;
2446 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2450 if (INT_MAX
/ 2 < len
)
2451 memory_full (SIZE_MAX
);
2453 if (gstring
.allocated
== 0)
2455 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2456 gstring
.glyphs
= xnmalloc (len
* 2, sizeof (MFLTGlyph
));
2457 gstring
.allocated
= len
* 2;
2459 else if (gstring
.allocated
< len
* 2)
2461 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2, sizeof (MFLTGlyph
));
2462 gstring
.allocated
= len
* 2;
2464 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2465 for (i
= 0; i
< len
; i
++)
2467 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2469 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2470 if (with_variation_selector
)
2472 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2473 gstring
.glyphs
[i
].encoded
= 1;
2481 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2484 flt_font_ft
.flt_font
.family
= Mnil
;
2486 flt_font_ft
.flt_font
.family
2487 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2489 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2490 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2491 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2492 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2493 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2494 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2495 flt_font_ft
.flt_font
.internal
= NULL
;
2496 flt_font_ft
.font
= font
;
2497 flt_font_ft
.ft_face
= ft_face
;
2498 flt_font_ft
.otf
= otf
;
2499 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2501 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2502 /* A little bit ad hoc. Perhaps, shaper must get script and
2503 language information, and select a proper flt for them
2505 flt
= mflt_get (msymbol ("combining"));
2506 for (i
= 0; i
< 3; i
++)
2508 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2511 if (INT_MAX
/ 2 < gstring
.allocated
)
2512 memory_full (SIZE_MAX
);
2513 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2514 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2515 gstring
.allocated
*= 2;
2517 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2519 for (i
= 0; i
< gstring
.used
; i
++)
2521 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2523 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2524 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2527 for (i
= 0; i
< gstring
.used
; i
++)
2529 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2530 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2534 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2535 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2537 LGLYPH_SET_FROM (lglyph
, g
->from
);
2538 LGLYPH_SET_TO (lglyph
, g
->to
);
2539 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2540 LGLYPH_SET_CODE (lglyph
, g
->code
);
2541 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2542 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2543 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2544 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2545 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2550 vec
= Fmake_vector (make_number (3), Qnil
);
2551 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2552 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2553 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2554 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2557 return make_number (i
);
2561 ftfont_shape (Lisp_Object lgstring
)
2564 struct ftfont_info
*ftfont_info
;
2567 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2568 ftfont_info
= (struct ftfont_info
*) font
;
2569 otf
= ftfont_get_otf (ftfont_info
);
2571 return make_number (0);
2572 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2573 &ftfont_info
->matrix
);
2576 #endif /* HAVE_M17N_FLT */
2578 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2581 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2583 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2584 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2588 return OTF_get_variation_glyphs (otf
, c
, variations
);
2591 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2592 #endif /* HAVE_LIBOTF */
2595 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2599 #ifdef FC_FONTFORMAT
2602 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2604 if (strcmp ((char *) str
, "TrueType") == 0)
2605 return intern ("truetype");
2606 if (strcmp ((char *) str
, "Type 1") == 0)
2607 return intern ("type1");
2608 if (strcmp ((char *) str
, "PCF") == 0)
2609 return intern ("pcf");
2610 if (strcmp ((char *) str
, "BDF") == 0)
2611 return intern ("bdf");
2613 #endif /* FC_FONTFORMAT */
2614 if (STRINGP (filename
))
2616 int len
= SBYTES (filename
);
2620 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2621 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2622 return intern ("truetype");
2623 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2624 return intern ("type1");
2625 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2626 return intern ("pcf");
2627 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2628 return intern ("bdf");
2631 return intern ("unknown");
2634 static const char *const ftfont_booleans
[] = {
2647 static const char *const ftfont_non_booleans
[] = {
2679 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2681 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2686 syms_of_ftfont (void)
2688 DEFSYM (Qfreetype
, "freetype");
2689 DEFSYM (Qmonospace
, "monospace");
2690 DEFSYM (Qsans_serif
, "sans-serif");
2691 DEFSYM (Qserif
, "serif");
2692 DEFSYM (Qmono
, "mono");
2693 DEFSYM (Qsans
, "sans");
2694 DEFSYM (Qsans__serif
, "sans serif");
2696 staticpro (&freetype_font_cache
);
2697 freetype_font_cache
= Fcons (Qt
, Qnil
);
2699 staticpro (&ftfont_generic_family_list
);
2700 ftfont_generic_family_list
2701 = Fcons (Fcons (Qmonospace
, Qt
),
2702 Fcons (Fcons (Qsans_serif
, Qt
),
2703 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2705 staticpro (&ft_face_cache
);
2706 ft_face_cache
= Qnil
;
2708 ftfont_driver
.type
= Qfreetype
;
2709 register_font_driver (&ftfont_driver
, NULL
);