1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006-2014 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24 #include <fontconfig/fontconfig.h>
25 #include <fontconfig/fcfreetype.h>
28 #include "dispextern.h"
30 #include "blockinput.h"
31 #include "character.h"
34 #include "composite.h"
39 /* Symbolic type of this font-driver. */
40 static Lisp_Object Qfreetype
;
42 /* Fontconfig's generic families and their aliases. */
43 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
45 /* Flag to tell if FcInit is already called or not. */
46 static bool fc_initialized
;
48 /* Handle to a FreeType library instance. */
49 static FT_Library ft_library
;
51 /* Cache for FreeType fonts. */
52 static Lisp_Object freetype_font_cache
;
54 /* Cache for FT_Face and FcCharSet. */
55 static Lisp_Object ft_face_cache
;
57 /* The actual structure for FreeType font that can be cast to struct
64 /* The following four members must be here in this order to be
65 compatible with struct xftfont_info (in xftfont.c). */
66 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
68 #endif /* HAVE_LIBOTF */
76 FTFONT_CACHE_FOR_FACE
,
77 FTFONT_CACHE_FOR_CHARSET
,
78 FTFONT_CACHE_FOR_ENTITY
81 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
83 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
85 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
86 enum ftfont_cache_for
);
88 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
90 Lisp_Object
ftfont_font_format (FcPattern
*, Lisp_Object
);
92 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
98 /* characters to distinguish the charset from the others */
100 /* additional constraint by language */
103 FcCharSet
*fc_charset
;
104 } fc_charset_table
[] =
105 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
106 { "iso8859-2", { 0x00A0, 0x010E }},
107 { "iso8859-3", { 0x00A0, 0x0108 }},
108 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
109 { "iso8859-5", { 0x00A0, 0x0401 }},
110 { "iso8859-6", { 0x00A0, 0x060C }},
111 { "iso8859-7", { 0x00A0, 0x0384 }},
112 { "iso8859-8", { 0x00A0, 0x05D0 }},
113 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
114 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
115 { "iso8859-11", { 0x00A0, 0x0E01 }},
116 { "iso8859-13", { 0x00A0, 0x201C }},
117 { "iso8859-14", { 0x00A0, 0x0174 }},
118 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
119 { "iso8859-16", { 0x00A0, 0x0218}},
120 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
121 { "big5-0", { 0xF6B1 }, "zh-tw" },
122 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
123 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
124 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
125 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
126 { "cns11643.1992-3", { 0x201A9 }},
127 { "cns11643.1992-4", { 0x20057 }},
128 { "cns11643.1992-5", { 0x20000 }},
129 { "cns11643.1992-6", { 0x20003 }},
130 { "cns11643.1992-7", { 0x20055 }},
131 { "gbk-0", { 0x4E06 }, "zh-cn"},
132 { "jisx0212.1990-0", { 0x4E44 }},
133 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
134 { "jisx0213.2000-2", { 0xFA49 }},
135 { "jisx0213.2004-1", { 0x20B9F }},
136 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
137 { "tis620.2529-1", { 0x0E01 }, "th"},
138 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
139 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
140 { "mulelao-1", { 0x0E81 }, "lo"},
141 { "unicode-sip", { 0x20000 }},
145 /* Dirty hack for handing ADSTYLE property.
147 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
148 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
149 "Oblique", "Italic", or any non-normal SWIDTH property names
150 (e.g. SemiCondensed) are appended. In addition, if there's no
151 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
152 "Regular" is used for FC_STYLE (see the function
153 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
155 Unfortunately this behavior is not documented, so the following
156 code may fail if FreeType changes the behavior in the future. */
159 get_adstyle_property (FcPattern
*p
)
166 if ((FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fcstr
) == FcResultMatch
)
167 && xstrcasecmp ((char *) fcstr
, "bdf") != 0
168 && xstrcasecmp ((char *) fcstr
, "pcf") != 0)
169 /* Not a BDF nor PCF font. */
172 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
174 str
= (char *) fcstr
;
175 for (end
= str
; *end
&& *end
!= ' '; end
++);
178 char *newstr
= alloca (end
- str
+ 1);
179 memcpy (newstr
, str
, end
- str
);
180 newstr
[end
- str
] = '\0';
181 end
= newstr
+ (end
- str
);
184 if (xstrcasecmp (str
, "Regular") == 0
185 || xstrcasecmp (str
, "Bold") == 0
186 || xstrcasecmp (str
, "Oblique") == 0
187 || xstrcasecmp (str
, "Italic") == 0)
189 adstyle
= font_intern_prop (str
, end
- str
, 1);
190 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
196 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
198 Lisp_Object key
, cache
, entity
;
206 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
208 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
212 key
= Fcons (build_unibyte_string (file
), make_number (idx
));
213 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
214 entity
= XCAR (cache
);
217 Lisp_Object val
= font_make_entity ();
220 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
221 ASET (val
, i
, AREF (entity
, i
));
223 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
224 font_put_extra (val
, QCfont_entity
, key
);
228 entity
= font_make_entity ();
229 XSETCAR (cache
, entity
);
231 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
232 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
234 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
236 char *s
= (char *) str
;
237 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
239 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
241 char *s
= (char *) str
;
242 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
244 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
246 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
247 numeric
= FC_WEIGHT_MEDIUM
;
248 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
250 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
253 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
255 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
257 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
259 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
261 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
264 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
265 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
266 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
267 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
270 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
272 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
275 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
276 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
280 /* As this font is not scalable, perhaps this is a BDF or PCF
284 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
285 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
286 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
290 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
291 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
292 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
293 FT_Done_Face (ft_face
);
297 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
298 font_put_extra (entity
, QCfont_entity
, key
);
303 static Lisp_Object ftfont_generic_family_list
;
306 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
313 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
314 if (EQ (family
, Qmono
))
316 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
317 family
= Qsans_serif
;
318 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
321 if (! EQ (XCDR (slot
), Qt
))
323 pattern
= FcPatternDuplicate (pattern
);
326 FcPatternDel (pattern
, FC_FOUNDRY
);
327 FcPatternDel (pattern
, FC_FAMILY
);
328 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
329 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
331 /* This is to avoid the effect of locale. */
332 static const FcChar8 lang
[] = "en";
333 langset
= FcLangSetCreate ();
334 FcLangSetAdd (langset
, lang
);
335 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
336 FcLangSetDestroy (langset
);
338 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
339 FcDefaultSubstitute (pattern
);
340 match
= FcFontMatch (NULL
, pattern
, &result
);
345 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
346 family
= intern ((char *) fam
);
350 XSETCDR (slot
, family
);
351 if (match
) FcPatternDestroy (match
);
353 if (pattern
) FcPatternDestroy (pattern
);
357 struct ftfont_cache_data
360 FcCharSet
*fc_charset
;
364 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
366 Lisp_Object cache
, val
, entity
;
367 struct ftfont_cache_data
*cache_data
;
369 if (FONT_ENTITY_P (key
))
372 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
373 eassert (CONSP (val
));
379 if (NILP (ft_face_cache
))
382 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
385 if (NILP (ft_face_cache
))
391 ft_face_cache
= Fmake_hash_table (2, args
);
393 cache_data
= xmalloc (sizeof *cache_data
);
394 cache_data
->ft_face
= NULL
;
395 cache_data
->fc_charset
= NULL
;
396 val
= make_save_ptr_int (cache_data
, 0);
397 cache
= Fcons (Qnil
, val
);
398 Fputhash (key
, cache
, ft_face_cache
);
403 cache_data
= XSAVE_POINTER (val
, 0);
406 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
409 if (cache_for
== FTFONT_CACHE_FOR_FACE
410 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
412 char *filename
= SSDATA (XCAR (key
));
413 int idx
= XINT (XCDR (key
));
415 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
418 && FT_Init_FreeType (&ft_library
) != 0)
420 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
426 FcPattern
*pat
= NULL
;
427 FcFontSet
*fontset
= NULL
;
428 FcObjectSet
*objset
= NULL
;
429 FcCharSet
*charset
= NULL
;
431 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
432 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
435 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
438 fontset
= FcFontList (NULL
, pat
, objset
);
441 if (fontset
&& fontset
->nfont
> 0
442 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
445 cache_data
->fc_charset
= FcCharSetCopy (charset
);
447 cache_data
->fc_charset
= FcCharSetCreate ();
451 FcFontSetDestroy (fontset
);
453 FcObjectSetDestroy (objset
);
455 FcPatternDestroy (pat
);
462 ftfont_get_fc_charset (Lisp_Object entity
)
464 Lisp_Object val
, cache
;
465 struct ftfont_cache_data
*cache_data
;
467 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
469 cache_data
= XSAVE_POINTER (val
, 0);
470 return cache_data
->fc_charset
;
475 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
479 if (ftfont_info
->otf
)
480 return ftfont_info
->otf
;
481 if (! ftfont_info
->maybe_otf
)
483 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
484 if (! otf
|| OTF_get_table (otf
, "head") < 0)
488 ftfont_info
->maybe_otf
= 0;
491 ftfont_info
->otf
= otf
;
494 #endif /* HAVE_LIBOTF */
496 static Lisp_Object
ftfont_get_cache (struct frame
*);
497 static Lisp_Object
ftfont_list (struct frame
*, Lisp_Object
);
498 static Lisp_Object
ftfont_match (struct frame
*, Lisp_Object
);
499 static Lisp_Object
ftfont_list_family (struct frame
*);
500 static Lisp_Object
ftfont_open (struct frame
*, Lisp_Object
, int);
501 static void ftfont_close (struct font
*);
502 static int ftfont_has_char (Lisp_Object
, int);
503 static unsigned ftfont_encode_char (struct font
*, int);
504 static int ftfont_text_extents (struct font
*, unsigned *, int,
505 struct font_metrics
*);
506 static int ftfont_get_bitmap (struct font
*, unsigned,
507 struct font_bitmap
*, int);
508 static int ftfont_anchor_point (struct font
*, unsigned, int,
511 static Lisp_Object
ftfont_otf_capability (struct font
*);
512 # ifdef HAVE_M17N_FLT
513 static Lisp_Object
ftfont_shape (Lisp_Object
);
517 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
518 static int ftfont_variation_glyphs (struct font
*, int c
,
519 unsigned variations
[256]);
520 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
522 struct font_driver ftfont_driver
=
524 LISP_INITIALLY_ZERO
, /* Qfreetype */
525 0, /* case insensitive */
530 NULL
, /* free_entity */
533 /* We can't draw a text without device dependent functions. */
534 NULL
, /* prepare_face */
535 NULL
, /* done_face */
539 /* We can't draw a text without device dependent functions. */
542 NULL
, /* free_bitmap */
543 NULL
, /* get_outline */
544 NULL
, /* free_outline */
547 ftfont_otf_capability
,
548 #else /* not HAVE_LIBOTF */
550 #endif /* not HAVE_LIBOTF */
551 NULL
, /* otf_drive */
552 NULL
, /* start_for_frame */
553 NULL
, /* end_for_frame */
554 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
556 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
558 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
561 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
562 ftfont_variation_glyphs
,
567 ftfont_filter_properties
, /* filter_properties */
571 ftfont_get_cache (struct frame
*f
)
573 return freetype_font_cache
;
577 ftfont_get_charset (Lisp_Object registry
)
579 char *str
= SSDATA (SYMBOL_NAME (registry
));
580 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
584 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
588 else if (str
[i
] == '*')
595 regexp
= make_unibyte_string (re
, j
);
596 for (i
= 0; fc_charset_table
[i
].name
; i
++)
597 if (fast_c_string_match_ignore_case
598 (regexp
, fc_charset_table
[i
].name
,
599 strlen (fc_charset_table
[i
].name
)) >= 0)
601 if (! fc_charset_table
[i
].name
)
603 if (! fc_charset_table
[i
].fc_charset
)
605 FcCharSet
*charset
= FcCharSetCreate ();
606 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
610 for (j
= 0; uniquifier
[j
]; j
++)
611 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
613 FcCharSetDestroy (charset
);
616 fc_charset_table
[i
].fc_charset
= charset
;
624 unsigned int script_tag
, langsys_tag
;
626 unsigned int *features
[2];
629 #define OTF_SYM_TAG(SYM, TAG) \
631 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
632 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
635 #define OTF_TAG_STR(TAG, P) \
637 (P)[0] = (char) (TAG >> 24); \
638 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
639 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
640 (P)[3] = (char) (TAG & 0xFF); \
645 #define OTF_TAG_SYM(SYM, TAG) \
649 OTF_TAG_STR (TAG, str); \
650 (SYM) = font_intern_prop (str, 4, 1); \
655 static struct OpenTypeSpec
*
656 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
658 struct OpenTypeSpec
*spec
= malloc (sizeof *spec
);
665 spec
->script
= XCAR (otf_spec
);
666 if (! NILP (spec
->script
))
668 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
669 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
670 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
671 spec
->script
= XCDR (val
);
676 spec
->script_tag
= 0x44464C54; /* "DFLT" */
677 otf_spec
= XCDR (otf_spec
);
678 spec
->langsys_tag
= 0;
679 if (! NILP (otf_spec
))
681 val
= XCAR (otf_spec
);
683 OTF_SYM_TAG (val
, spec
->langsys_tag
);
684 otf_spec
= XCDR (otf_spec
);
686 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
687 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
691 val
= XCAR (otf_spec
);
696 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
698 : malloc (XINT (len
) * sizeof *spec
->features
[i
]));
699 if (! spec
->features
[i
])
701 if (i
> 0 && spec
->features
[0])
702 free (spec
->features
[0]);
706 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
708 if (NILP (XCAR (val
)))
714 OTF_SYM_TAG (XCAR (val
), tag
);
715 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
718 spec
->nfeatures
[i
] = j
;
724 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
726 Lisp_Object tmp
, extra
;
727 FcPattern
*pattern
= NULL
;
728 FcCharSet
*charset
= NULL
;
729 FcLangSet
*langset
= NULL
;
733 Lisp_Object script
= Qnil
;
734 Lisp_Object registry
;
737 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
739 /* Fontconfig doesn't support reverse-italic/oblique. */
742 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
743 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
744 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
745 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
748 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
750 || EQ (registry
, Qascii_0
)
751 || EQ (registry
, Qiso10646_1
)
752 || EQ (registry
, Qunicode_bmp
))
758 fc_charset_idx
= ftfont_get_charset (registry
);
759 if (fc_charset_idx
< 0)
761 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
762 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
763 lang
= (FcChar8
*) *langname
;
766 langset
= FcLangSetCreate ();
769 FcLangSetAdd (langset
, lang
);
774 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
775 CONSP (extra
); extra
= XCDR (extra
))
777 Lisp_Object key
, val
;
779 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
785 else if (EQ (key
, QClang
))
788 langset
= FcLangSetCreate ();
793 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
797 for (; CONSP (val
); val
= XCDR (val
))
798 if (SYMBOLP (XCAR (val
))
799 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
802 else if (EQ (key
, QCotf
))
806 *otspec
= ftfont_get_open_type_spec (val
);
809 strcat (otlayout
, "otlayout:");
810 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
811 script
= (*otspec
)->script
;
814 else if (EQ (key
, QCscript
))
816 else if (EQ (key
, QCscalable
))
817 scalable
= ! NILP (val
);
820 if (! NILP (script
) && ! charset
)
822 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
824 if (CONSP (chars
) && CONSP (CDR (chars
)))
826 charset
= FcCharSetCreate ();
829 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
830 if (CHARACTERP (XCAR (chars
))
831 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
836 pattern
= FcPatternCreate ();
839 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
841 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
843 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
845 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
848 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
851 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
854 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
857 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
863 /* We come here because of unexpected error in fontconfig API call
864 (usually insufficient memory). */
867 FcPatternDestroy (pattern
);
872 if ((*otspec
)->nfeatures
[0] > 0)
873 free ((*otspec
)->features
[0]);
874 if ((*otspec
)->nfeatures
[1] > 0)
875 free ((*otspec
)->features
[1]);
881 if (langset
) FcLangSetDestroy (langset
);
882 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
887 ftfont_list (struct frame
*f
, Lisp_Object spec
)
889 Lisp_Object val
= Qnil
, family
, adstyle
;
892 FcFontSet
*fontset
= NULL
;
893 FcObjectSet
*objset
= NULL
;
895 Lisp_Object chars
= Qnil
;
896 char otlayout
[15]; /* For "otlayout:XXXX" */
897 struct OpenTypeSpec
*otspec
= NULL
;
899 const char *langname
= NULL
;
901 if (! fc_initialized
)
907 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
910 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
912 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
915 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
916 if (CONSP (val
) && VECTORP (XCDR (val
)))
921 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
922 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
923 family
= AREF (spec
, FONT_FAMILY_INDEX
);
926 Lisp_Object resolved
;
928 resolved
= ftfont_resolve_generic_family (family
, pattern
);
929 if (! NILP (resolved
))
931 FcPatternDel (pattern
, FC_FAMILY
);
932 if (! FcPatternAddString (pattern
, FC_FAMILY
,
933 SYMBOL_FcChar8 (resolved
)))
937 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
938 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
940 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
941 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
942 FC_STYLE
, FC_FILE
, FC_INDEX
,
945 #endif /* FC_CAPABILITY */
953 FcObjectSetAdd (objset
, FC_CHARSET
);
955 fontset
= FcFontList (NULL
, pattern
, objset
);
956 if (! fontset
|| fontset
->nfont
== 0)
959 /* Need fix because this finds any fonts. */
960 if (fontset
->nfont
== 0 && ! NILP (family
))
962 /* Try matching with configuration. For instance, the
963 configuration may specify "Nimbus Mono L" as an alias of
965 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
966 SYMBOL_FcChar8 (family
), NULL
);
969 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
972 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
975 FcPatternDel (pattern
, FC_FAMILY
);
976 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
977 FcFontSetDestroy (fontset
);
978 fontset
= FcFontList (NULL
, pattern
, objset
);
979 if (fontset
&& fontset
->nfont
> 0)
985 for (i
= 0; i
< fontset
->nfont
; i
++)
993 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
1004 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
1006 || ! strstr ((char *) this, otlayout
))
1009 #endif /* FC_CAPABILITY */
1017 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1020 otf
= OTF_open ((char *) file
);
1023 passed
= (OTF_check_features (otf
, 1, otspec
->script_tag
,
1024 otspec
->langsys_tag
,
1025 otspec
->features
[0],
1026 otspec
->nfeatures
[0]) == 1
1027 && OTF_check_features (otf
, 0, otspec
->script_tag
,
1028 otspec
->langsys_tag
,
1029 otspec
->features
[1],
1030 otspec
->nfeatures
[1]) == 1);
1035 #endif /* HAVE_LIBOTF */
1036 if (VECTORP (chars
))
1040 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1043 for (j
= 0; j
< ASIZE (chars
); j
++)
1044 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1045 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1047 if (j
== ASIZE (chars
))
1050 if (! NILP (adstyle
) || langname
)
1052 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1054 if (! NILP (adstyle
)
1055 && (NILP (this_adstyle
)
1056 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1057 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1060 && ! NILP (this_adstyle
)
1061 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1064 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1065 AREF (spec
, FONT_EXTRA_INDEX
));
1066 if (! NILP (entity
))
1067 val
= Fcons (entity
, val
);
1069 val
= Fnreverse (val
);
1073 /* We come here because of unexpected error in fontconfig API call
1074 (usually insufficient memory). */
1078 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1079 if (objset
) FcObjectSetDestroy (objset
);
1080 if (fontset
) FcFontSetDestroy (fontset
);
1081 if (pattern
) FcPatternDestroy (pattern
);
1086 ftfont_match (struct frame
*f
, Lisp_Object spec
)
1088 Lisp_Object entity
= Qnil
;
1089 FcPattern
*pattern
, *match
= NULL
;
1091 char otlayout
[15]; /* For "otlayout:XXXX" */
1092 struct OpenTypeSpec
*otspec
= NULL
;
1093 const char *langname
= NULL
;
1095 if (! fc_initialized
)
1101 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1105 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1109 value
.type
= FcTypeDouble
;
1110 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1111 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1113 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1115 FcDefaultSubstitute (pattern
);
1116 match
= FcFontMatch (NULL
, pattern
, &result
);
1119 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1120 FcPatternDestroy (match
);
1121 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1122 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1123 ftfont_generic_family_list
))
1124 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1125 AREF (entity
, FONT_FAMILY_INDEX
))))
1129 FcPatternDestroy (pattern
);
1131 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1136 ftfont_list_family (struct frame
*f
)
1138 Lisp_Object list
= Qnil
;
1139 FcPattern
*pattern
= NULL
;
1140 FcFontSet
*fontset
= NULL
;
1141 FcObjectSet
*objset
= NULL
;
1144 if (! fc_initialized
)
1150 pattern
= FcPatternCreate ();
1153 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1156 fontset
= FcFontList (NULL
, pattern
, objset
);
1160 for (i
= 0; i
< fontset
->nfont
; i
++)
1162 FcPattern
*pat
= fontset
->fonts
[i
];
1165 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1166 list
= Fcons (intern ((char *) str
), list
);
1170 if (objset
) FcObjectSetDestroy (objset
);
1171 if (fontset
) FcFontSetDestroy (fontset
);
1172 if (pattern
) FcPatternDestroy (pattern
);
1179 ftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
1181 struct ftfont_info
*ftfont_info
;
1183 struct ftfont_cache_data
*cache_data
;
1187 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1194 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1198 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1201 filename
= XCAR (val
);
1204 cache_data
= XSAVE_POINTER (XCDR (cache
), 0);
1205 ft_face
= cache_data
->ft_face
;
1206 if (XSAVE_INTEGER (val
, 1) > 0)
1208 /* FT_Face in this cache is already used by the different size. */
1209 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1211 if (FT_Activate_Size (ft_size
) != 0)
1213 FT_Done_Size (ft_size
);
1217 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) + 1);
1218 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1221 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1223 if (XSAVE_INTEGER (val
, 1) == 0)
1224 FT_Done_Face (ft_face
);
1228 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1229 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1230 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1232 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1233 len
= font_unparse_fcname (entity
, size
, name
, 256);
1235 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1237 ASET (font_object
, FONT_FULLNAME_INDEX
,
1238 AREF (font_object
, FONT_NAME_INDEX
));
1239 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1240 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1241 font
= XFONT_OBJECT (font_object
);
1242 ftfont_info
= (struct ftfont_info
*) font
;
1243 ftfont_info
->ft_size
= ft_face
->size
;
1244 ftfont_info
->index
= XINT (idx
);
1246 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1247 ftfont_info
->otf
= NULL
;
1248 #endif /* HAVE_LIBOTF */
1249 /* This means that there's no need of transformation. */
1250 ftfont_info
->matrix
.xx
= 0;
1251 font
->pixel_size
= size
;
1252 font
->driver
= &ftfont_driver
;
1253 font
->encoding_charset
= font
->repertory_charset
= -1;
1255 upEM
= ft_face
->units_per_EM
;
1256 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1257 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1260 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1261 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1262 font
->height
= ft_face
->height
* size
/ upEM
;
1266 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1267 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1268 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1270 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1271 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1273 spacing
= FC_PROPORTIONAL
;
1274 if (spacing
!= FC_PROPORTIONAL
1276 && spacing
!= FC_DUAL
1277 #endif /* FC_DUAL */
1279 font
->min_width
= font
->average_width
= font
->space_width
1280 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1281 : ft_face
->size
->metrics
.max_advance
>> 6);
1286 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1287 for (i
= 32, n
= 0; i
< 127; i
++)
1288 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1290 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1293 && (! font
->min_width
|| font
->min_width
> this_width
))
1294 font
->min_width
= this_width
;
1296 font
->space_width
= this_width
;
1297 font
->average_width
+= this_width
;
1301 font
->average_width
/= n
;
1304 font
->baseline_offset
= 0;
1305 font
->relative_compose
= 0;
1306 font
->default_ascent
= 0;
1307 font
->vertical_centering
= 0;
1310 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1311 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1315 font
->underline_position
= -1;
1316 font
->underline_thickness
= 0;
1323 ftfont_close (struct font
*font
)
1325 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1326 Lisp_Object val
, cache
;
1328 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1329 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1330 eassert (CONSP (cache
));
1332 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) - 1);
1333 if (XSAVE_INTEGER (val
, 1) == 0)
1335 struct ftfont_cache_data
*cache_data
= XSAVE_POINTER (val
, 0);
1337 FT_Done_Face (cache_data
->ft_face
);
1339 if (ftfont_info
->otf
)
1340 OTF_close (ftfont_info
->otf
);
1342 cache_data
->ft_face
= NULL
;
1345 FT_Done_Size (ftfont_info
->ft_size
);
1349 ftfont_has_char (Lisp_Object font
, int c
)
1351 struct charset
*cs
= NULL
;
1353 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1354 && charset_jisx0208
>= 0)
1355 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1356 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1357 && charset_ksc5601
>= 0)
1358 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1360 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1362 if (FONT_ENTITY_P (font
))
1364 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1366 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1370 struct ftfont_info
*ftfont_info
;
1372 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1373 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1379 ftfont_encode_char (struct font
*font
, int c
)
1381 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1382 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1383 FT_ULong charcode
= c
;
1384 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1386 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1390 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1392 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1393 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1398 if (ftfont_info
->ft_size
!= ft_face
->size
)
1399 FT_Activate_Size (ftfont_info
->ft_size
);
1401 memset (metrics
, 0, sizeof (struct font_metrics
));
1402 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1404 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1406 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1412 metrics
->lbearing
= m
->horiBearingX
>> 6;
1413 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1414 metrics
->ascent
= m
->horiBearingY
>> 6;
1415 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1421 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1422 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1423 if (metrics
->rbearing
1424 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1426 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1427 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1428 metrics
->ascent
= m
->horiBearingY
>> 6;
1429 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1430 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1432 width
+= m
->horiAdvance
>> 6;
1436 width
+= font
->space_width
;
1440 metrics
->width
= width
;
1446 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1448 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1449 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1450 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1452 if (ftfont_info
->ft_size
!= ft_face
->size
)
1453 FT_Activate_Size (ftfont_info
->ft_size
);
1454 if (bits_per_pixel
== 1)
1456 #ifdef FT_LOAD_TARGET_MONO
1457 load_flags
|= FT_LOAD_TARGET_MONO
;
1459 load_flags
|= FT_LOAD_MONOCHROME
;
1462 else if (bits_per_pixel
!= 8)
1463 /* We don't support such a rendering. */
1466 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1468 bitmap
->bits_per_pixel
1469 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1470 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1471 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1472 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1474 if (bitmap
->bits_per_pixel
< 0)
1475 /* We don't support that kind of pixel mode. */
1477 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1478 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1479 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1480 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1481 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1482 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1483 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1489 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1492 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1493 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1495 if (ftfont_info
->ft_size
!= ft_face
->size
)
1496 FT_Activate_Size (ftfont_info
->ft_size
);
1497 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1499 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1501 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1503 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1504 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1511 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1513 Lisp_Object scripts
, langsyses
, features
, sym
;
1516 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1518 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1520 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1522 OTF_LangSys
*otf_langsys
;
1525 otf_langsys
= otf_script
->LangSys
+ j
;
1526 else if (otf_script
->DefaultLangSysOffset
)
1527 otf_langsys
= &otf_script
->DefaultLangSys
;
1531 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1533 l
= otf_langsys
->FeatureIndex
[k
];
1534 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1536 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1537 features
= Fcons (sym
, features
);
1540 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1543 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1546 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1547 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1555 ftfont_otf_capability (struct font
*font
)
1557 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1558 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1559 Lisp_Object gsub_gpos
;
1563 gsub_gpos
= Fcons (Qnil
, Qnil
);
1564 if (OTF_get_table (otf
, "GSUB") == 0
1565 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1566 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1567 if (OTF_get_table (otf
, "GPOS") == 0
1568 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1569 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1573 #ifdef HAVE_M17N_FLT
1575 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1576 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1577 /* We can use the new feature of libotf and m17n-flt to handle the
1578 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1579 some Agian scripts. */
1580 #define M17N_FLT_USE_NEW_FEATURE
1593 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1596 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1597 FT_Face ft_face
= flt_font_ft
->ft_face
;
1600 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1603 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1605 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1611 /* Operators for 26.6 fixed fractional pixel format */
1613 #define FLOOR(x) ((x) & -64)
1614 #define CEIL(x) (((x)+63) & -64)
1615 #define ROUND(x) (((x)+32) & -64)
1618 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1621 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1622 FT_Face ft_face
= flt_font_ft
->ft_face
;
1625 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1628 if (g
->code
!= FONT_INVALID_CODE
)
1630 FT_Glyph_Metrics
*m
;
1632 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1634 m
= &ft_face
->glyph
->metrics
;
1635 if (flt_font_ft
->matrix
)
1640 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1641 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1642 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1643 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1644 for (i
= 0; i
< 4; i
++)
1645 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1646 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1647 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1648 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1649 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1653 g
->lbearing
= FLOOR (m
->horiBearingX
);
1654 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1655 g
->ascent
= CEIL (m
->horiBearingY
);
1656 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1658 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1663 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1664 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1665 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1674 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1676 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1678 #define FEATURE_ANY(IDX) \
1679 (spec->features[IDX] \
1680 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1682 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1683 OTF
*otf
= flt_font_ft
->otf
;
1688 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1689 /* Return true iff any of GSUB or GPOS support the script (and
1692 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1694 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1697 for (i
= 0; i
< 2; i
++)
1698 if (! FEATURE_ANY (i
))
1700 if (FEATURE_NONE (i
))
1703 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1708 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1711 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1717 for (n
= 1; spec
->features
[i
][n
]; n
++);
1718 tags
= alloca (sizeof (OTF_Tag
) * n
);
1719 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1721 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1724 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1726 tags
[n
] = spec
->features
[i
][n
];
1728 #ifdef M17N_FLT_USE_NEW_FEATURE
1729 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1730 tags
, n
- negative
) != 1)
1732 #else /* not M17N_FLT_USE_NEW_FEATURE */
1733 if (n
- negative
> 0
1734 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1735 tags
, n
- negative
) != 1)
1737 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1744 #define DEVICE_DELTA(table, size) \
1745 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1746 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1750 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1751 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1753 if (anchor
->AnchorFormat
== 2)
1755 FT_Outline
*outline
;
1756 int ap
= anchor
->f
.f1
.AnchorPoint
;
1758 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1759 outline
= &ft_face
->glyph
->outline
;
1760 if (ap
< outline
->n_points
)
1762 *x
= outline
->points
[ap
].x
<< 6;
1763 *y
= outline
->points
[ap
].y
<< 6;
1766 else if (anchor
->AnchorFormat
== 3)
1768 if (anchor
->f
.f2
.XDeviceTable
.offset
1769 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1770 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1771 if (anchor
->f
.f2
.YDeviceTable
.offset
1772 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1773 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1777 static OTF_GlyphString otf_gstring
;
1780 setup_otf_gstring (int size
)
1782 if (otf_gstring
.size
< size
)
1784 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1785 size
, sizeof (OTF_Glyph
));
1786 otf_gstring
.size
= size
;
1788 otf_gstring
.used
= size
;
1789 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1792 #ifdef M17N_FLT_USE_NEW_FEATURE
1794 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1795 #define PACK_OTF_TAG(TAG) \
1796 ((((TAG) & 0x7F000000) >> 3) \
1797 | (((TAG) & 0x7F0000) >> 2) \
1798 | (((TAG) & 0x7F00) >> 1) \
1801 /* Assuming that FONT is an OpenType font, apply OpenType features
1802 specified in SPEC on glyphs between FROM and TO of IN, and record
1803 the lastly applied feature in each glyph of IN. If OUT is not
1804 NULL, append the resulting glyphs to OUT while storing glyph
1805 position adjustment information in ADJUSTMENT. */
1808 ftfont_drive_otf (MFLTFont
*font
,
1810 MFLTGlyphString
*in
,
1813 MFLTGlyphString
*out
,
1814 MFLTGlyphAdjustment
*adjustment
)
1816 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1817 FT_Face ft_face
= flt_font_ft
->ft_face
;
1818 OTF
*otf
= flt_font_ft
->otf
;
1819 int len
= to
- from
;
1822 char script
[5], *langsys
= NULL
;
1823 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1824 OTF_Feature
*features
;
1828 OTF_tag_name (spec
->script
, script
);
1831 langsys
= alloca (5);
1832 OTF_tag_name (spec
->langsys
, langsys
);
1834 for (i
= 0; i
< 2; i
++)
1838 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1840 for (j
= 0; spec
->features
[i
][j
]; j
++);
1842 p
= gsub_features
= alloca (6 * j
);
1844 p
= gpos_features
= alloca (6 * j
);
1845 for (j
= 0; spec
->features
[i
][j
]; j
++)
1847 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1848 *p
++ = '*', *p
++ = ',';
1851 OTF_tag_name (spec
->features
[i
][j
], p
);
1860 setup_otf_gstring (len
);
1861 for (i
= 0; i
< len
; i
++)
1863 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
& 0x11FFFF;
1864 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1867 OTF_drive_gdef (otf
, &otf_gstring
);
1868 gidx
= out
? out
->used
: from
;
1870 if (gsub_features
&& out
)
1872 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1875 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1877 features
= otf
->gsub
->FeatureList
.Feature
;
1878 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1881 int min_from
, max_to
;
1882 int feature_idx
= otfg
->positioning_type
>> 4;
1884 g
= out
->glyphs
+ out
->used
;
1885 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1886 if (g
->code
!= otfg
->glyph_id
)
1889 g
->code
= otfg
->glyph_id
;
1895 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1897 /* OTFG substitutes multiple glyphs in IN. */
1898 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1899 j
<= from
+ otfg
->f
.index
.to
; j
++)
1901 if (min_from
> in
->glyphs
[j
].from
)
1902 min_from
= in
->glyphs
[j
].from
;
1903 if (max_to
< in
->glyphs
[j
].to
)
1904 max_to
= in
->glyphs
[j
].to
;
1911 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1912 tag
= PACK_OTF_TAG (tag
);
1913 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1915 for (i
++, otfg
++; (i
< otf_gstring
.used
1916 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1919 g
= out
->glyphs
+ out
->used
;
1920 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1921 if (g
->code
!= otfg
->glyph_id
)
1924 g
->code
= otfg
->glyph_id
;
1927 feature_idx
= otfg
->positioning_type
>> 4;
1930 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1931 tag
= PACK_OTF_TAG (tag
);
1932 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1938 else if (gsub_features
)
1940 /* Just for checking which features will be applied. */
1941 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1944 features
= otf
->gsub
->FeatureList
.Feature
;
1945 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1948 int feature_idx
= otfg
->positioning_type
>> 4;
1952 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1953 tag
= PACK_OTF_TAG (tag
);
1954 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1956 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1957 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1964 if (out
->allocated
< out
->used
+ len
)
1966 for (i
= 0; i
< len
; i
++)
1967 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1970 if (gpos_features
&& out
)
1972 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1973 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1975 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1978 features
= otf
->gpos
->FeatureList
.Feature
;
1979 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1980 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1981 x_scale
= ft_face
->size
->metrics
.x_scale
;
1982 y_scale
= ft_face
->size
->metrics
.y_scale
;
1984 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1985 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1988 int feature_idx
= otfg
->positioning_type
>> 4;
1992 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1993 tag
= PACK_OTF_TAG (tag
);
1994 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1997 if (! otfg
->glyph_id
)
1999 switch (otfg
->positioning_type
& 0xF)
2003 case 1: /* Single */
2006 int format
= otfg
->f
.f1
.format
;
2008 if (format
& OTF_XPlacement
)
2010 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2011 if (format
& OTF_XPlaDevice
)
2013 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2014 if (format
& OTF_YPlacement
)
2016 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2017 if (format
& OTF_YPlaDevice
)
2019 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2020 if (format
& OTF_XAdvance
)
2022 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2023 if (format
& OTF_XAdvDevice
)
2025 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2026 if (format
& OTF_YAdvance
)
2028 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2029 if (format
& OTF_YAdvDevice
)
2031 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2032 adjustment
[i
].set
= 1;
2035 case 3: /* Cursive */
2036 /* Not yet supported. */
2038 case 4: /* Mark-to-Base */
2039 case 5: /* Mark-to-Ligature */
2043 goto label_adjust_anchor
;
2044 default: /* i.e. case 6 Mark-to-Mark */
2049 label_adjust_anchor
:
2051 int base_x
, base_y
, mark_x
, mark_y
;
2052 int this_from
, this_to
;
2054 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2055 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2056 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2057 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2059 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2060 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2061 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2062 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2063 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2064 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2065 adjustment
[i
].xoff
= (base_x
- mark_x
);
2066 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2067 adjustment
[i
].back
= (g
- prev
);
2068 adjustment
[i
].xadv
= 0;
2069 adjustment
[i
].advance_is_absolute
= 1;
2070 adjustment
[i
].set
= 1;
2071 this_from
= g
->from
;
2073 for (j
= 0; prev
+ j
< g
; j
++)
2075 if (this_from
> prev
[j
].from
)
2076 this_from
= prev
[j
].from
;
2077 if (this_to
< prev
[j
].to
)
2078 this_to
= prev
[j
].to
;
2080 for (; prev
<= g
; prev
++)
2082 prev
->from
= this_from
;
2087 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2089 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2095 else if (gpos_features
)
2097 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2100 features
= otf
->gpos
->FeatureList
.Feature
;
2101 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2103 if (otfg
->positioning_type
& 0xF)
2105 int feature_idx
= otfg
->positioning_type
>> 4;
2109 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2110 tag
= PACK_OTF_TAG (tag
);
2111 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2113 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2114 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2124 if (out
->allocated
< out
->used
+ len
)
2126 font
->get_metrics (font
, in
, from
, to
);
2127 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2128 sizeof (MFLTGlyph
) * len
);
2134 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2135 MFLTGlyphString
*in
, int from
, int to
)
2137 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2140 #else /* not M17N_FLT_USE_NEW_FEATURE */
2143 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2145 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2147 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2148 FT_Face ft_face
= flt_font_ft
->ft_face
;
2149 OTF
*otf
= flt_font_ft
->otf
;
2150 int len
= to
- from
;
2153 char script
[5], *langsys
= NULL
;
2154 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2158 OTF_tag_name (spec
->script
, script
);
2161 langsys
= alloca (5);
2162 OTF_tag_name (spec
->langsys
, langsys
);
2164 for (i
= 0; i
< 2; i
++)
2168 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2170 for (j
= 0; spec
->features
[i
][j
]; j
++);
2172 p
= gsub_features
= alloca (6 * j
);
2174 p
= gpos_features
= alloca (6 * j
);
2175 for (j
= 0; spec
->features
[i
][j
]; j
++)
2177 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2178 *p
++ = '*', *p
++ = ',';
2181 OTF_tag_name (spec
->features
[i
][j
], p
);
2190 setup_otf_gstring (len
);
2191 for (i
= 0; i
< len
; i
++)
2193 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2194 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2197 OTF_drive_gdef (otf
, &otf_gstring
);
2202 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2205 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2207 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2210 int min_from
, max_to
;
2213 g
= out
->glyphs
+ out
->used
;
2214 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2215 if (g
->code
!= otfg
->glyph_id
)
2218 g
->code
= otfg
->glyph_id
;
2224 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2226 /* OTFG substitutes multiple glyphs in IN. */
2227 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2228 j
<= from
+ otfg
->f
.index
.to
; j
++)
2230 if (min_from
> in
->glyphs
[j
].from
)
2231 min_from
= in
->glyphs
[j
].from
;
2232 if (max_to
< in
->glyphs
[j
].to
)
2233 max_to
= in
->glyphs
[j
].to
;
2238 for (i
++, otfg
++; (i
< otf_gstring
.used
2239 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2242 g
= out
->glyphs
+ out
->used
;
2243 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2244 if (g
->code
!= otfg
->glyph_id
)
2247 g
->code
= otfg
->glyph_id
;
2256 if (out
->allocated
< out
->used
+ len
)
2258 for (i
= 0; i
< len
; i
++)
2259 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2264 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2265 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2267 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2271 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2272 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2273 x_scale
= ft_face
->size
->metrics
.x_scale
;
2274 y_scale
= ft_face
->size
->metrics
.y_scale
;
2276 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2277 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2281 if (! otfg
->glyph_id
)
2283 switch (otfg
->positioning_type
)
2287 case 1: /* Single */
2290 int format
= otfg
->f
.f1
.format
;
2292 if (format
& OTF_XPlacement
)
2294 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2295 if (format
& OTF_XPlaDevice
)
2297 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2298 if (format
& OTF_YPlacement
)
2300 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2301 if (format
& OTF_YPlaDevice
)
2303 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2304 if (format
& OTF_XAdvance
)
2306 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2307 if (format
& OTF_XAdvDevice
)
2309 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2310 if (format
& OTF_YAdvance
)
2312 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2313 if (format
& OTF_YAdvDevice
)
2315 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2316 adjustment
[i
].set
= 1;
2319 case 3: /* Cursive */
2320 /* Not yet supported. */
2322 case 4: /* Mark-to-Base */
2323 case 5: /* Mark-to-Ligature */
2327 goto label_adjust_anchor
;
2328 default: /* i.e. case 6 Mark-to-Mark */
2333 label_adjust_anchor
:
2335 int base_x
, base_y
, mark_x
, mark_y
;
2336 int this_from
, this_to
;
2338 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2339 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2340 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2341 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2343 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2344 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2345 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2346 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2347 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2348 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2349 adjustment
[i
].xoff
= (base_x
- mark_x
);
2350 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2351 adjustment
[i
].back
= (g
- prev
);
2352 adjustment
[i
].xadv
= 0;
2353 adjustment
[i
].advance_is_absolute
= 1;
2354 adjustment
[i
].set
= 1;
2355 this_from
= g
->from
;
2357 for (j
= 0; prev
+ j
< g
; j
++)
2359 if (this_from
> prev
[j
].from
)
2360 this_from
= prev
[j
].from
;
2361 if (this_to
< prev
[j
].to
)
2362 this_to
= prev
[j
].to
;
2364 for (; prev
<= g
; prev
++)
2366 prev
->from
= this_from
;
2371 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2373 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2382 if (out
->allocated
< out
->used
+ len
)
2384 font
->get_metrics (font
, in
, from
, to
);
2385 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2386 sizeof (MFLTGlyph
) * len
);
2391 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2393 static MFLTGlyphString gstring
;
2395 static bool m17n_flt_initialized
;
2398 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2399 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2401 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2403 struct MFLTFontFT flt_font_ft
;
2405 bool with_variation_selector
= 0;
2407 if (! m17n_flt_initialized
)
2410 #ifdef M17N_FLT_USE_NEW_FEATURE
2411 mflt_enable_new_feature
= 1;
2412 mflt_try_otf
= ftfont_try_otf
;
2413 #endif /* M17N_FLT_USE_NEW_FEATURE */
2414 m17n_flt_initialized
= 1;
2417 for (i
= 0; i
< len
; i
++)
2419 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2424 c
= LGLYPH_CHAR (g
);
2425 if (CHAR_VARIATION_SELECTOR_P (c
))
2426 with_variation_selector
= 1;
2431 if (with_variation_selector
)
2433 setup_otf_gstring (len
);
2434 for (i
= 0; i
< len
; i
++)
2436 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2438 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2439 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2440 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2442 OTF_drive_cmap (otf
, &otf_gstring
);
2443 for (i
= 0; i
< otf_gstring
.used
; i
++)
2445 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2446 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2447 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2449 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2450 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2451 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2453 if (len
> otf_gstring
.used
)
2455 len
= otf_gstring
.used
;
2456 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2460 if (INT_MAX
/ 2 < len
)
2461 memory_full (SIZE_MAX
);
2463 if (gstring
.allocated
== 0)
2465 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2466 gstring
.glyphs
= xnmalloc (len
* 2, sizeof *gstring
.glyphs
);
2467 gstring
.allocated
= len
* 2;
2469 else if (gstring
.allocated
< len
* 2)
2471 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2472 sizeof *gstring
.glyphs
);
2473 gstring
.allocated
= len
* 2;
2475 memset (gstring
.glyphs
, 0, len
* sizeof *gstring
.glyphs
);
2476 for (i
= 0; i
< len
; i
++)
2478 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2480 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2481 if (with_variation_selector
)
2483 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2484 gstring
.glyphs
[i
].encoded
= 1;
2492 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2495 flt_font_ft
.flt_font
.family
= Mnil
;
2497 flt_font_ft
.flt_font
.family
2498 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2500 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2501 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2502 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2503 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2504 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2505 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2506 flt_font_ft
.flt_font
.internal
= NULL
;
2507 flt_font_ft
.font
= font
;
2508 flt_font_ft
.ft_face
= ft_face
;
2509 flt_font_ft
.otf
= otf
;
2510 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2512 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2513 /* A little bit ad hoc. Perhaps, shaper must get script and
2514 language information, and select a proper flt for them
2516 flt
= mflt_get (msymbol ("combining"));
2517 for (i
= 0; i
< 3; i
++)
2519 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2522 if (INT_MAX
/ 2 < gstring
.allocated
)
2523 memory_full (SIZE_MAX
);
2524 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2525 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2526 gstring
.allocated
*= 2;
2528 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2530 for (i
= 0; i
< gstring
.used
; i
++)
2532 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2534 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2535 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2538 for (i
= 0; i
< gstring
.used
; i
++)
2540 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2541 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2545 lglyph
= LGLYPH_NEW ();
2546 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2548 LGLYPH_SET_FROM (lglyph
, g
->from
);
2549 LGLYPH_SET_TO (lglyph
, g
->to
);
2550 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2551 LGLYPH_SET_CODE (lglyph
, g
->code
);
2552 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2553 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2554 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2555 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2556 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2559 Lisp_Object vec
= make_uninit_vector (3);
2561 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2562 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2563 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2564 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2567 return make_number (i
);
2571 ftfont_shape (Lisp_Object lgstring
)
2574 struct ftfont_info
*ftfont_info
;
2577 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2578 ftfont_info
= (struct ftfont_info
*) font
;
2579 otf
= ftfont_get_otf (ftfont_info
);
2581 return make_number (0);
2582 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2583 &ftfont_info
->matrix
);
2586 #endif /* HAVE_M17N_FLT */
2588 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2591 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2593 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2594 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2598 return OTF_get_variation_glyphs (otf
, c
, variations
);
2601 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2602 #endif /* HAVE_LIBOTF */
2605 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2609 #ifdef FC_FONTFORMAT
2612 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2614 if (strcmp ((char *) str
, "TrueType") == 0)
2615 return intern ("truetype");
2616 if (strcmp ((char *) str
, "Type 1") == 0)
2617 return intern ("type1");
2618 if (strcmp ((char *) str
, "PCF") == 0)
2619 return intern ("pcf");
2620 if (strcmp ((char *) str
, "BDF") == 0)
2621 return intern ("bdf");
2623 #endif /* FC_FONTFORMAT */
2624 if (STRINGP (filename
))
2626 int len
= SBYTES (filename
);
2630 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2631 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2632 return intern ("truetype");
2633 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2634 return intern ("type1");
2635 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2636 return intern ("pcf");
2637 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2638 return intern ("bdf");
2641 return intern ("unknown");
2644 static const char *const ftfont_booleans
[] = {
2657 static const char *const ftfont_non_booleans
[] = {
2689 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2691 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2696 syms_of_ftfont (void)
2698 DEFSYM (Qfreetype
, "freetype");
2699 DEFSYM (Qmonospace
, "monospace");
2700 DEFSYM (Qsans_serif
, "sans-serif");
2701 DEFSYM (Qserif
, "serif");
2702 DEFSYM (Qmono
, "mono");
2703 DEFSYM (Qsans
, "sans");
2704 DEFSYM (Qsans__serif
, "sans serif");
2706 staticpro (&freetype_font_cache
);
2707 freetype_font_cache
= list1 (Qt
);
2709 staticpro (&ftfont_generic_family_list
);
2710 ftfont_generic_family_list
= list3 (Fcons (Qmonospace
, Qt
),
2711 Fcons (Qsans_serif
, Qt
),
2714 staticpro (&ft_face_cache
);
2715 ft_face_cache
= Qnil
;
2717 ftfont_driver
.type
= Qfreetype
;
2718 register_font_driver (&ftfont_driver
, NULL
);