1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006-2013 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 casted 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 */
1016 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1019 otf
= OTF_open ((char *) file
);
1022 if (OTF_check_features (otf
, 1,
1023 otspec
->script_tag
, otspec
->langsys_tag
,
1024 otspec
->features
[0],
1025 otspec
->nfeatures
[0]) != 1
1026 || OTF_check_features (otf
, 0,
1027 otspec
->script_tag
, otspec
->langsys_tag
,
1028 otspec
->features
[1],
1029 otspec
->nfeatures
[1]) != 1)
1032 #endif /* HAVE_LIBOTF */
1033 if (VECTORP (chars
))
1037 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1040 for (j
= 0; j
< ASIZE (chars
); j
++)
1041 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1042 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1044 if (j
== ASIZE (chars
))
1047 if (! NILP (adstyle
) || langname
)
1049 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1051 if (! NILP (adstyle
)
1052 && (NILP (this_adstyle
)
1053 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1054 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1057 && ! NILP (this_adstyle
)
1058 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1061 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1062 AREF (spec
, FONT_EXTRA_INDEX
));
1063 if (! NILP (entity
))
1064 val
= Fcons (entity
, val
);
1066 val
= Fnreverse (val
);
1070 /* We come here because of unexpected error in fontconfig API call
1071 (usually insufficient memory). */
1075 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1076 if (objset
) FcObjectSetDestroy (objset
);
1077 if (fontset
) FcFontSetDestroy (fontset
);
1078 if (pattern
) FcPatternDestroy (pattern
);
1083 ftfont_match (struct frame
*f
, Lisp_Object spec
)
1085 Lisp_Object entity
= Qnil
;
1086 FcPattern
*pattern
, *match
= NULL
;
1088 char otlayout
[15]; /* For "otlayout:XXXX" */
1089 struct OpenTypeSpec
*otspec
= NULL
;
1090 const char *langname
= NULL
;
1092 if (! fc_initialized
)
1098 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1102 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1106 value
.type
= FcTypeDouble
;
1107 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1108 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1110 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1112 FcDefaultSubstitute (pattern
);
1113 match
= FcFontMatch (NULL
, pattern
, &result
);
1116 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1117 FcPatternDestroy (match
);
1118 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1119 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1120 ftfont_generic_family_list
))
1121 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1122 AREF (entity
, FONT_FAMILY_INDEX
))))
1126 FcPatternDestroy (pattern
);
1128 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1133 ftfont_list_family (struct frame
*f
)
1135 Lisp_Object list
= Qnil
;
1136 FcPattern
*pattern
= NULL
;
1137 FcFontSet
*fontset
= NULL
;
1138 FcObjectSet
*objset
= NULL
;
1141 if (! fc_initialized
)
1147 pattern
= FcPatternCreate ();
1150 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1153 fontset
= FcFontList (NULL
, pattern
, objset
);
1157 for (i
= 0; i
< fontset
->nfont
; i
++)
1159 FcPattern
*pat
= fontset
->fonts
[i
];
1162 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1163 list
= Fcons (intern ((char *) str
), list
);
1167 if (objset
) FcObjectSetDestroy (objset
);
1168 if (fontset
) FcFontSetDestroy (fontset
);
1169 if (pattern
) FcPatternDestroy (pattern
);
1176 ftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
1178 struct ftfont_info
*ftfont_info
;
1180 struct ftfont_cache_data
*cache_data
;
1184 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1191 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1195 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1198 filename
= XCAR (val
);
1201 cache_data
= XSAVE_POINTER (XCDR (cache
), 0);
1202 ft_face
= cache_data
->ft_face
;
1203 if (XSAVE_INTEGER (val
, 1) > 0)
1205 /* FT_Face in this cache is already used by the different size. */
1206 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1208 if (FT_Activate_Size (ft_size
) != 0)
1210 FT_Done_Size (ft_size
);
1214 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) + 1);
1215 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1218 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1220 if (XSAVE_INTEGER (val
, 1) == 0)
1221 FT_Done_Face (ft_face
);
1225 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1226 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1227 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1229 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1230 len
= font_unparse_fcname (entity
, size
, name
, 256);
1232 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1234 ASET (font_object
, FONT_FULLNAME_INDEX
,
1235 AREF (font_object
, FONT_NAME_INDEX
));
1236 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1237 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1238 font
= XFONT_OBJECT (font_object
);
1239 ftfont_info
= (struct ftfont_info
*) font
;
1240 ftfont_info
->ft_size
= ft_face
->size
;
1241 ftfont_info
->index
= XINT (idx
);
1243 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1244 ftfont_info
->otf
= NULL
;
1245 #endif /* HAVE_LIBOTF */
1246 /* This means that there's no need of transformation. */
1247 ftfont_info
->matrix
.xx
= 0;
1248 font
->pixel_size
= size
;
1249 font
->driver
= &ftfont_driver
;
1250 font
->encoding_charset
= font
->repertory_charset
= -1;
1252 upEM
= ft_face
->units_per_EM
;
1253 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1254 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1257 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1258 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1259 font
->height
= ft_face
->height
* size
/ upEM
;
1263 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1264 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1265 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1267 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1268 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1270 spacing
= FC_PROPORTIONAL
;
1271 if (spacing
!= FC_PROPORTIONAL
1273 && spacing
!= FC_DUAL
1274 #endif /* FC_DUAL */
1276 font
->min_width
= font
->average_width
= font
->space_width
1277 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1278 : ft_face
->size
->metrics
.max_advance
>> 6);
1283 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1284 for (i
= 32, n
= 0; i
< 127; i
++)
1285 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1287 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1290 && (! font
->min_width
|| font
->min_width
> this_width
))
1291 font
->min_width
= this_width
;
1293 font
->space_width
= this_width
;
1294 font
->average_width
+= this_width
;
1298 font
->average_width
/= n
;
1301 font
->baseline_offset
= 0;
1302 font
->relative_compose
= 0;
1303 font
->default_ascent
= 0;
1304 font
->vertical_centering
= 0;
1307 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1308 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1312 font
->underline_position
= -1;
1313 font
->underline_thickness
= 0;
1320 ftfont_close (struct font
*font
)
1322 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1323 Lisp_Object val
, cache
;
1325 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1326 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1327 eassert (CONSP (cache
));
1329 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) - 1);
1330 if (XSAVE_INTEGER (val
, 1) == 0)
1332 struct ftfont_cache_data
*cache_data
= XSAVE_POINTER (val
, 0);
1334 FT_Done_Face (cache_data
->ft_face
);
1336 if (ftfont_info
->otf
)
1337 OTF_close (ftfont_info
->otf
);
1339 cache_data
->ft_face
= NULL
;
1342 FT_Done_Size (ftfont_info
->ft_size
);
1346 ftfont_has_char (Lisp_Object font
, int c
)
1348 struct charset
*cs
= NULL
;
1350 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1351 && charset_jisx0208
>= 0)
1352 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1353 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1354 && charset_ksc5601
>= 0)
1355 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1357 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1359 if (FONT_ENTITY_P (font
))
1361 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1363 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1367 struct ftfont_info
*ftfont_info
;
1369 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1370 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1376 ftfont_encode_char (struct font
*font
, int c
)
1378 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1379 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1380 FT_ULong charcode
= c
;
1381 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1383 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1387 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1389 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1390 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1395 if (ftfont_info
->ft_size
!= ft_face
->size
)
1396 FT_Activate_Size (ftfont_info
->ft_size
);
1398 memset (metrics
, 0, sizeof (struct font_metrics
));
1399 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1401 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1403 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1409 metrics
->lbearing
= m
->horiBearingX
>> 6;
1410 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1411 metrics
->ascent
= m
->horiBearingY
>> 6;
1412 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1418 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1419 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1420 if (metrics
->rbearing
1421 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1423 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1424 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1425 metrics
->ascent
= m
->horiBearingY
>> 6;
1426 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1427 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1429 width
+= m
->horiAdvance
>> 6;
1433 width
+= font
->space_width
;
1437 metrics
->width
= width
;
1443 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1445 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1446 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1447 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1449 if (ftfont_info
->ft_size
!= ft_face
->size
)
1450 FT_Activate_Size (ftfont_info
->ft_size
);
1451 if (bits_per_pixel
== 1)
1453 #ifdef FT_LOAD_TARGET_MONO
1454 load_flags
|= FT_LOAD_TARGET_MONO
;
1456 load_flags
|= FT_LOAD_MONOCHROME
;
1459 else if (bits_per_pixel
!= 8)
1460 /* We don't support such a rendering. */
1463 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1465 bitmap
->bits_per_pixel
1466 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1467 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1468 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1469 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1471 if (bitmap
->bits_per_pixel
< 0)
1472 /* We don't support that kind of pixel mode. */
1474 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1475 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1476 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1477 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1478 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1479 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1480 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1486 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1489 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1490 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1492 if (ftfont_info
->ft_size
!= ft_face
->size
)
1493 FT_Activate_Size (ftfont_info
->ft_size
);
1494 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1496 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1498 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1500 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1501 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1508 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1510 Lisp_Object scripts
, langsyses
, features
, sym
;
1513 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1515 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1517 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1519 OTF_LangSys
*otf_langsys
;
1522 otf_langsys
= otf_script
->LangSys
+ j
;
1523 else if (otf_script
->DefaultLangSysOffset
)
1524 otf_langsys
= &otf_script
->DefaultLangSys
;
1528 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1530 l
= otf_langsys
->FeatureIndex
[k
];
1531 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1533 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1534 features
= Fcons (sym
, features
);
1537 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1540 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1543 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1544 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1552 ftfont_otf_capability (struct font
*font
)
1554 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1555 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1556 Lisp_Object gsub_gpos
;
1560 gsub_gpos
= Fcons (Qnil
, Qnil
);
1561 if (OTF_get_table (otf
, "GSUB") == 0
1562 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1563 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1564 if (OTF_get_table (otf
, "GPOS") == 0
1565 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1566 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1570 #ifdef HAVE_M17N_FLT
1572 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1573 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1574 /* We can use the new feature of libotf and m17n-flt to handle the
1575 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1576 some Agian scripts. */
1577 #define M17N_FLT_USE_NEW_FEATURE
1590 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1593 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1594 FT_Face ft_face
= flt_font_ft
->ft_face
;
1597 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1600 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1602 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1608 /* Operators for 26.6 fixed fractional pixel format */
1610 #define FLOOR(x) ((x) & -64)
1611 #define CEIL(x) (((x)+63) & -64)
1612 #define ROUND(x) (((x)+32) & -64)
1615 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1618 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1619 FT_Face ft_face
= flt_font_ft
->ft_face
;
1622 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1625 if (g
->code
!= FONT_INVALID_CODE
)
1627 FT_Glyph_Metrics
*m
;
1629 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1631 m
= &ft_face
->glyph
->metrics
;
1632 if (flt_font_ft
->matrix
)
1637 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1638 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1639 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1640 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1641 for (i
= 0; i
< 4; i
++)
1642 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1643 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1644 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1645 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1646 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1650 g
->lbearing
= FLOOR (m
->horiBearingX
);
1651 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1652 g
->ascent
= CEIL (m
->horiBearingY
);
1653 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1655 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1660 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1661 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1662 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1671 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1673 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1675 #define FEATURE_ANY(IDX) \
1676 (spec->features[IDX] \
1677 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1679 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1680 OTF
*otf
= flt_font_ft
->otf
;
1685 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1686 /* Return true iff any of GSUB or GPOS support the script (and
1689 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1691 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1694 for (i
= 0; i
< 2; i
++)
1695 if (! FEATURE_ANY (i
))
1697 if (FEATURE_NONE (i
))
1700 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1705 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1708 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1714 for (n
= 1; spec
->features
[i
][n
]; n
++);
1715 tags
= alloca (sizeof (OTF_Tag
) * n
);
1716 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1718 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1721 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1723 tags
[n
] = spec
->features
[i
][n
];
1725 #ifdef M17N_FLT_USE_NEW_FEATURE
1726 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1727 tags
, n
- negative
) != 1)
1729 #else /* not M17N_FLT_USE_NEW_FEATURE */
1730 if (n
- negative
> 0
1731 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1732 tags
, n
- negative
) != 1)
1734 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1741 #define DEVICE_DELTA(table, size) \
1742 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1743 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1747 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1748 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1750 if (anchor
->AnchorFormat
== 2)
1752 FT_Outline
*outline
;
1753 int ap
= anchor
->f
.f1
.AnchorPoint
;
1755 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1756 outline
= &ft_face
->glyph
->outline
;
1757 if (ap
< outline
->n_points
)
1759 *x
= outline
->points
[ap
].x
<< 6;
1760 *y
= outline
->points
[ap
].y
<< 6;
1763 else if (anchor
->AnchorFormat
== 3)
1765 if (anchor
->f
.f2
.XDeviceTable
.offset
1766 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1767 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1768 if (anchor
->f
.f2
.YDeviceTable
.offset
1769 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1770 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1774 static OTF_GlyphString otf_gstring
;
1777 setup_otf_gstring (int size
)
1779 if (otf_gstring
.size
< size
)
1781 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1782 size
, sizeof (OTF_Glyph
));
1783 otf_gstring
.size
= size
;
1785 otf_gstring
.used
= size
;
1786 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1789 #ifdef M17N_FLT_USE_NEW_FEATURE
1791 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1792 #define PACK_OTF_TAG(TAG) \
1793 ((((TAG) & 0x7F000000) >> 3) \
1794 | (((TAG) & 0x7F0000) >> 2) \
1795 | (((TAG) & 0x7F00) >> 1) \
1798 /* Assuming that FONT is an OpenType font, apply OpenType features
1799 specified in SPEC on glyphs between FROM and TO of IN, and record
1800 the lastly applied feature in each glyph of IN. If OUT is not
1801 NULL, append the resulting glyphs to OUT while storing glyph
1802 position adjustment information in ADJUSTMENT. */
1805 ftfont_drive_otf (MFLTFont
*font
,
1807 MFLTGlyphString
*in
,
1810 MFLTGlyphString
*out
,
1811 MFLTGlyphAdjustment
*adjustment
)
1813 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1814 FT_Face ft_face
= flt_font_ft
->ft_face
;
1815 OTF
*otf
= flt_font_ft
->otf
;
1816 int len
= to
- from
;
1819 char script
[5], *langsys
= NULL
;
1820 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1821 OTF_Feature
*features
;
1825 OTF_tag_name (spec
->script
, script
);
1828 langsys
= alloca (5);
1829 OTF_tag_name (spec
->langsys
, langsys
);
1831 for (i
= 0; i
< 2; i
++)
1835 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1837 for (j
= 0; spec
->features
[i
][j
]; j
++);
1839 p
= gsub_features
= alloca (6 * j
);
1841 p
= gpos_features
= alloca (6 * j
);
1842 for (j
= 0; spec
->features
[i
][j
]; j
++)
1844 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1845 *p
++ = '*', *p
++ = ',';
1848 OTF_tag_name (spec
->features
[i
][j
], p
);
1857 setup_otf_gstring (len
);
1858 for (i
= 0; i
< len
; i
++)
1860 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
& 0x11FFFF;
1861 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1864 OTF_drive_gdef (otf
, &otf_gstring
);
1865 gidx
= out
? out
->used
: from
;
1867 if (gsub_features
&& out
)
1869 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1872 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1874 features
= otf
->gsub
->FeatureList
.Feature
;
1875 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1878 int min_from
, max_to
;
1879 int feature_idx
= otfg
->positioning_type
>> 4;
1881 g
= out
->glyphs
+ out
->used
;
1882 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1883 if (g
->code
!= otfg
->glyph_id
)
1886 g
->code
= otfg
->glyph_id
;
1892 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1894 /* OTFG substitutes multiple glyphs in IN. */
1895 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1896 j
<= from
+ otfg
->f
.index
.to
; j
++)
1898 if (min_from
> in
->glyphs
[j
].from
)
1899 min_from
= in
->glyphs
[j
].from
;
1900 if (max_to
< in
->glyphs
[j
].to
)
1901 max_to
= in
->glyphs
[j
].to
;
1908 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1909 tag
= PACK_OTF_TAG (tag
);
1910 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1912 for (i
++, otfg
++; (i
< otf_gstring
.used
1913 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1916 g
= out
->glyphs
+ out
->used
;
1917 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1918 if (g
->code
!= otfg
->glyph_id
)
1921 g
->code
= otfg
->glyph_id
;
1924 feature_idx
= otfg
->positioning_type
>> 4;
1927 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1928 tag
= PACK_OTF_TAG (tag
);
1929 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1935 else if (gsub_features
)
1937 /* Just for checking which features will be applied. */
1938 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1941 features
= otf
->gsub
->FeatureList
.Feature
;
1942 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1945 int feature_idx
= otfg
->positioning_type
>> 4;
1949 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1950 tag
= PACK_OTF_TAG (tag
);
1951 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1953 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1954 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1961 if (out
->allocated
< out
->used
+ len
)
1963 for (i
= 0; i
< len
; i
++)
1964 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1967 if (gpos_features
&& out
)
1969 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1970 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1972 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1975 features
= otf
->gpos
->FeatureList
.Feature
;
1976 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1977 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1978 x_scale
= ft_face
->size
->metrics
.x_scale
;
1979 y_scale
= ft_face
->size
->metrics
.y_scale
;
1981 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1982 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1985 int feature_idx
= otfg
->positioning_type
>> 4;
1989 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1990 tag
= PACK_OTF_TAG (tag
);
1991 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1994 if (! otfg
->glyph_id
)
1996 switch (otfg
->positioning_type
& 0xF)
2000 case 1: /* Single */
2003 int format
= otfg
->f
.f1
.format
;
2005 if (format
& OTF_XPlacement
)
2007 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2008 if (format
& OTF_XPlaDevice
)
2010 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2011 if (format
& OTF_YPlacement
)
2013 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2014 if (format
& OTF_YPlaDevice
)
2016 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2017 if (format
& OTF_XAdvance
)
2019 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2020 if (format
& OTF_XAdvDevice
)
2022 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2023 if (format
& OTF_YAdvance
)
2025 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2026 if (format
& OTF_YAdvDevice
)
2028 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2029 adjustment
[i
].set
= 1;
2032 case 3: /* Cursive */
2033 /* Not yet supported. */
2035 case 4: /* Mark-to-Base */
2036 case 5: /* Mark-to-Ligature */
2040 goto label_adjust_anchor
;
2041 default: /* i.e. case 6 Mark-to-Mark */
2046 label_adjust_anchor
:
2048 int base_x
, base_y
, mark_x
, mark_y
;
2049 int this_from
, this_to
;
2051 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2052 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2053 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2054 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2056 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2057 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2058 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2059 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2060 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2061 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2062 adjustment
[i
].xoff
= (base_x
- mark_x
);
2063 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2064 adjustment
[i
].back
= (g
- prev
);
2065 adjustment
[i
].xadv
= 0;
2066 adjustment
[i
].advance_is_absolute
= 1;
2067 adjustment
[i
].set
= 1;
2068 this_from
= g
->from
;
2070 for (j
= 0; prev
+ j
< g
; j
++)
2072 if (this_from
> prev
[j
].from
)
2073 this_from
= prev
[j
].from
;
2074 if (this_to
< prev
[j
].to
)
2075 this_to
= prev
[j
].to
;
2077 for (; prev
<= g
; prev
++)
2079 prev
->from
= this_from
;
2084 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2086 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2092 else if (gpos_features
)
2094 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2097 features
= otf
->gpos
->FeatureList
.Feature
;
2098 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2100 if (otfg
->positioning_type
& 0xF)
2102 int feature_idx
= otfg
->positioning_type
>> 4;
2106 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2107 tag
= PACK_OTF_TAG (tag
);
2108 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2110 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2111 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2121 if (out
->allocated
< out
->used
+ len
)
2123 font
->get_metrics (font
, in
, from
, to
);
2124 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2125 sizeof (MFLTGlyph
) * len
);
2131 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2132 MFLTGlyphString
*in
, int from
, int to
)
2134 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2137 #else /* not M17N_FLT_USE_NEW_FEATURE */
2140 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2142 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2144 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2145 FT_Face ft_face
= flt_font_ft
->ft_face
;
2146 OTF
*otf
= flt_font_ft
->otf
;
2147 int len
= to
- from
;
2150 char script
[5], *langsys
= NULL
;
2151 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2155 OTF_tag_name (spec
->script
, script
);
2158 langsys
= alloca (5);
2159 OTF_tag_name (spec
->langsys
, langsys
);
2161 for (i
= 0; i
< 2; i
++)
2165 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2167 for (j
= 0; spec
->features
[i
][j
]; j
++);
2169 p
= gsub_features
= alloca (6 * j
);
2171 p
= gpos_features
= alloca (6 * j
);
2172 for (j
= 0; spec
->features
[i
][j
]; j
++)
2174 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2175 *p
++ = '*', *p
++ = ',';
2178 OTF_tag_name (spec
->features
[i
][j
], p
);
2187 setup_otf_gstring (len
);
2188 for (i
= 0; i
< len
; i
++)
2190 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2191 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2194 OTF_drive_gdef (otf
, &otf_gstring
);
2199 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2202 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2204 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2207 int min_from
, max_to
;
2210 g
= out
->glyphs
+ out
->used
;
2211 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2212 if (g
->code
!= otfg
->glyph_id
)
2215 g
->code
= otfg
->glyph_id
;
2221 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2223 /* OTFG substitutes multiple glyphs in IN. */
2224 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2225 j
<= from
+ otfg
->f
.index
.to
; j
++)
2227 if (min_from
> in
->glyphs
[j
].from
)
2228 min_from
= in
->glyphs
[j
].from
;
2229 if (max_to
< in
->glyphs
[j
].to
)
2230 max_to
= in
->glyphs
[j
].to
;
2235 for (i
++, otfg
++; (i
< otf_gstring
.used
2236 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2239 g
= out
->glyphs
+ out
->used
;
2240 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2241 if (g
->code
!= otfg
->glyph_id
)
2244 g
->code
= otfg
->glyph_id
;
2253 if (out
->allocated
< out
->used
+ len
)
2255 for (i
= 0; i
< len
; i
++)
2256 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2261 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2262 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2264 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2268 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2269 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2270 x_scale
= ft_face
->size
->metrics
.x_scale
;
2271 y_scale
= ft_face
->size
->metrics
.y_scale
;
2273 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2274 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2278 if (! otfg
->glyph_id
)
2280 switch (otfg
->positioning_type
)
2284 case 1: /* Single */
2287 int format
= otfg
->f
.f1
.format
;
2289 if (format
& OTF_XPlacement
)
2291 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2292 if (format
& OTF_XPlaDevice
)
2294 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2295 if (format
& OTF_YPlacement
)
2297 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2298 if (format
& OTF_YPlaDevice
)
2300 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2301 if (format
& OTF_XAdvance
)
2303 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2304 if (format
& OTF_XAdvDevice
)
2306 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2307 if (format
& OTF_YAdvance
)
2309 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2310 if (format
& OTF_YAdvDevice
)
2312 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2313 adjustment
[i
].set
= 1;
2316 case 3: /* Cursive */
2317 /* Not yet supported. */
2319 case 4: /* Mark-to-Base */
2320 case 5: /* Mark-to-Ligature */
2324 goto label_adjust_anchor
;
2325 default: /* i.e. case 6 Mark-to-Mark */
2330 label_adjust_anchor
:
2332 int base_x
, base_y
, mark_x
, mark_y
;
2333 int this_from
, this_to
;
2335 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2336 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2337 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2338 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2340 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2341 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2342 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2343 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2344 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2345 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2346 adjustment
[i
].xoff
= (base_x
- mark_x
);
2347 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2348 adjustment
[i
].back
= (g
- prev
);
2349 adjustment
[i
].xadv
= 0;
2350 adjustment
[i
].advance_is_absolute
= 1;
2351 adjustment
[i
].set
= 1;
2352 this_from
= g
->from
;
2354 for (j
= 0; prev
+ j
< g
; j
++)
2356 if (this_from
> prev
[j
].from
)
2357 this_from
= prev
[j
].from
;
2358 if (this_to
< prev
[j
].to
)
2359 this_to
= prev
[j
].to
;
2361 for (; prev
<= g
; prev
++)
2363 prev
->from
= this_from
;
2368 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2370 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2379 if (out
->allocated
< out
->used
+ len
)
2381 font
->get_metrics (font
, in
, from
, to
);
2382 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2383 sizeof (MFLTGlyph
) * len
);
2388 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2390 static MFLTGlyphString gstring
;
2392 static bool m17n_flt_initialized
;
2395 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2396 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2398 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2400 struct MFLTFontFT flt_font_ft
;
2402 bool with_variation_selector
= 0;
2404 if (! m17n_flt_initialized
)
2407 #ifdef M17N_FLT_USE_NEW_FEATURE
2408 mflt_enable_new_feature
= 1;
2409 mflt_try_otf
= ftfont_try_otf
;
2410 #endif /* M17N_FLT_USE_NEW_FEATURE */
2411 m17n_flt_initialized
= 1;
2414 for (i
= 0; i
< len
; i
++)
2416 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2421 c
= LGLYPH_CHAR (g
);
2422 if (CHAR_VARIATION_SELECTOR_P (c
))
2423 with_variation_selector
= 1;
2428 if (with_variation_selector
)
2430 setup_otf_gstring (len
);
2431 for (i
= 0; i
< len
; i
++)
2433 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2435 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2436 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2437 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2439 OTF_drive_cmap (otf
, &otf_gstring
);
2440 for (i
= 0; i
< otf_gstring
.used
; i
++)
2442 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2443 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2444 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2446 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2447 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2448 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2450 if (len
> otf_gstring
.used
)
2452 len
= otf_gstring
.used
;
2453 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2457 if (INT_MAX
/ 2 < len
)
2458 memory_full (SIZE_MAX
);
2460 if (gstring
.allocated
== 0)
2462 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2463 gstring
.glyphs
= xnmalloc (len
* 2, sizeof *gstring
.glyphs
);
2464 gstring
.allocated
= len
* 2;
2466 else if (gstring
.allocated
< len
* 2)
2468 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2469 sizeof *gstring
.glyphs
);
2470 gstring
.allocated
= len
* 2;
2472 memset (gstring
.glyphs
, 0, len
* sizeof *gstring
.glyphs
);
2473 for (i
= 0; i
< len
; i
++)
2475 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2477 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2478 if (with_variation_selector
)
2480 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2481 gstring
.glyphs
[i
].encoded
= 1;
2489 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2492 flt_font_ft
.flt_font
.family
= Mnil
;
2494 flt_font_ft
.flt_font
.family
2495 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2497 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2498 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2499 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2500 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2501 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2502 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2503 flt_font_ft
.flt_font
.internal
= NULL
;
2504 flt_font_ft
.font
= font
;
2505 flt_font_ft
.ft_face
= ft_face
;
2506 flt_font_ft
.otf
= otf
;
2507 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2509 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2510 /* A little bit ad hoc. Perhaps, shaper must get script and
2511 language information, and select a proper flt for them
2513 flt
= mflt_get (msymbol ("combining"));
2514 for (i
= 0; i
< 3; i
++)
2516 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2519 if (INT_MAX
/ 2 < gstring
.allocated
)
2520 memory_full (SIZE_MAX
);
2521 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2522 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2523 gstring
.allocated
*= 2;
2525 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2527 for (i
= 0; i
< gstring
.used
; i
++)
2529 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2531 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2532 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2535 for (i
= 0; i
< gstring
.used
; i
++)
2537 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2538 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2542 lglyph
= LGLYPH_NEW ();
2543 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2545 LGLYPH_SET_FROM (lglyph
, g
->from
);
2546 LGLYPH_SET_TO (lglyph
, g
->to
);
2547 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2548 LGLYPH_SET_CODE (lglyph
, g
->code
);
2549 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2550 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2551 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2552 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2553 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2556 Lisp_Object vec
= make_uninit_vector (3);
2558 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2559 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2560 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2561 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2564 return make_number (i
);
2568 ftfont_shape (Lisp_Object lgstring
)
2571 struct ftfont_info
*ftfont_info
;
2574 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2575 ftfont_info
= (struct ftfont_info
*) font
;
2576 otf
= ftfont_get_otf (ftfont_info
);
2578 return make_number (0);
2579 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2580 &ftfont_info
->matrix
);
2583 #endif /* HAVE_M17N_FLT */
2585 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2588 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2590 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2591 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2595 return OTF_get_variation_glyphs (otf
, c
, variations
);
2598 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2599 #endif /* HAVE_LIBOTF */
2602 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2606 #ifdef FC_FONTFORMAT
2609 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2611 if (strcmp ((char *) str
, "TrueType") == 0)
2612 return intern ("truetype");
2613 if (strcmp ((char *) str
, "Type 1") == 0)
2614 return intern ("type1");
2615 if (strcmp ((char *) str
, "PCF") == 0)
2616 return intern ("pcf");
2617 if (strcmp ((char *) str
, "BDF") == 0)
2618 return intern ("bdf");
2620 #endif /* FC_FONTFORMAT */
2621 if (STRINGP (filename
))
2623 int len
= SBYTES (filename
);
2627 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2628 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2629 return intern ("truetype");
2630 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2631 return intern ("type1");
2632 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2633 return intern ("pcf");
2634 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2635 return intern ("bdf");
2638 return intern ("unknown");
2641 static const char *const ftfont_booleans
[] = {
2654 static const char *const ftfont_non_booleans
[] = {
2686 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2688 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2693 syms_of_ftfont (void)
2695 DEFSYM (Qfreetype
, "freetype");
2696 DEFSYM (Qmonospace
, "monospace");
2697 DEFSYM (Qsans_serif
, "sans-serif");
2698 DEFSYM (Qserif
, "serif");
2699 DEFSYM (Qmono
, "mono");
2700 DEFSYM (Qsans
, "sans");
2701 DEFSYM (Qsans__serif
, "sans serif");
2703 staticpro (&freetype_font_cache
);
2704 freetype_font_cache
= list1 (Qt
);
2706 staticpro (&ftfont_generic_family_list
);
2707 ftfont_generic_family_list
= list3 (Fcons (Qmonospace
, Qt
),
2708 Fcons (Qsans_serif
, Qt
),
2711 staticpro (&ft_face_cache
);
2712 ft_face_cache
= Qnil
;
2714 ftfont_driver
.type
= Qfreetype
;
2715 register_font_driver (&ftfont_driver
, NULL
);