1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006-2015 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>
27 #include <c-strcase.h>
30 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
36 #include "composite.h"
41 /* Flag to tell if FcInit is already called or not. */
42 static bool fc_initialized
;
44 /* Handle to a FreeType library instance. */
45 static FT_Library ft_library
;
47 /* Cache for FreeType fonts. */
48 static Lisp_Object freetype_font_cache
;
50 /* Cache for FT_Face and FcCharSet. */
51 static Lisp_Object ft_face_cache
;
53 /* The actual structure for FreeType font that can be cast to struct
60 /* The following four members must be here in this order to be
61 compatible with struct xftfont_info (in xftfont.c). */
62 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
64 #endif /* HAVE_LIBOTF */
70 size_t ftfont_info_size
= sizeof (struct ftfont_info
);
74 FTFONT_CACHE_FOR_FACE
,
75 FTFONT_CACHE_FOR_CHARSET
,
76 FTFONT_CACHE_FOR_ENTITY
79 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
81 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
83 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
84 enum ftfont_cache_for
);
86 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
88 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
94 /* characters to distinguish the charset from the others */
96 /* additional constraint by language */
99 FcCharSet
*fc_charset
;
100 } fc_charset_table
[] =
101 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
102 { "iso8859-2", { 0x00A0, 0x010E }},
103 { "iso8859-3", { 0x00A0, 0x0108 }},
104 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
105 { "iso8859-5", { 0x00A0, 0x0401 }},
106 { "iso8859-6", { 0x00A0, 0x060C }},
107 { "iso8859-7", { 0x00A0, 0x0384 }},
108 { "iso8859-8", { 0x00A0, 0x05D0 }},
109 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
110 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
111 { "iso8859-11", { 0x00A0, 0x0E01 }},
112 { "iso8859-13", { 0x00A0, 0x201C }},
113 { "iso8859-14", { 0x00A0, 0x0174 }},
114 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
115 { "iso8859-16", { 0x00A0, 0x0218}},
116 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
117 { "big5-0", { 0xF6B1 }, "zh-tw" },
118 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
119 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
120 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
121 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
122 { "cns11643.1992-3", { 0x201A9 }},
123 { "cns11643.1992-4", { 0x20057 }},
124 { "cns11643.1992-5", { 0x20000 }},
125 { "cns11643.1992-6", { 0x20003 }},
126 { "cns11643.1992-7", { 0x20055 }},
127 { "gbk-0", { 0x4E06 }, "zh-cn"},
128 { "jisx0212.1990-0", { 0x4E44 }},
129 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
130 { "jisx0213.2000-2", { 0xFA49 }},
131 { "jisx0213.2004-1", { 0x20B9F }},
132 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
133 { "tis620.2529-1", { 0x0E01 }, "th"},
134 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
135 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
136 { "mulelao-1", { 0x0E81 }, "lo"},
137 { "unicode-sip", { 0x20000 }},
142 matching_prefix (char const *str
, ptrdiff_t len
, char const *pat
)
144 return len
== strlen (pat
) && c_strncasecmp (str
, pat
, len
) == 0;
147 /* Dirty hack for handing ADSTYLE property.
149 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
150 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
151 "Oblique", "Italic", or any non-normal SWIDTH property names
152 (e.g. SemiCondensed) are appended. In addition, if there's no
153 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
154 "Regular" is used for FC_STYLE (see the function
155 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
157 Unfortunately this behavior is not documented, so the following
158 code may fail if FreeType changes the behavior in the future. */
161 get_adstyle_property (FcPattern
*p
)
168 if ((FcPatternGetString (p
, FC_FONTFORMAT
, 0, &fcstr
) == FcResultMatch
)
169 && xstrcasecmp ((char *) fcstr
, "bdf") != 0
170 && xstrcasecmp ((char *) fcstr
, "pcf") != 0)
171 /* Not a BDF nor PCF font. */
174 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
176 str
= (char *) fcstr
;
177 for (end
= str
; *end
&& *end
!= ' '; end
++);
178 if (matching_prefix (str
, end
- str
, "Regular")
179 || matching_prefix (str
, end
- str
, "Bold")
180 || matching_prefix (str
, end
- str
, "Oblique")
181 || matching_prefix (str
, end
- str
, "Italic"))
183 adstyle
= font_intern_prop (str
, end
- str
, 1);
184 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
190 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
192 Lisp_Object key
, cache
, entity
;
200 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
202 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
206 key
= Fcons (build_unibyte_string (file
), make_number (idx
));
207 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
208 entity
= XCAR (cache
);
211 Lisp_Object val
= font_make_entity ();
214 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
215 ASET (val
, i
, AREF (entity
, i
));
217 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
218 font_put_extra (val
, QCfont_entity
, key
);
222 entity
= font_make_entity ();
223 XSETCAR (cache
, entity
);
225 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
226 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
228 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
230 char *s
= (char *) str
;
231 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
233 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
235 char *s
= (char *) str
;
236 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
238 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
240 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
241 numeric
= FC_WEIGHT_MEDIUM
;
242 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
244 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
247 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
249 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
251 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
253 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
255 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
258 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
259 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
260 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
261 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
264 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
266 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
269 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
270 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
274 /* As this font is not scalable, perhaps this is a BDF or PCF
278 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
279 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
280 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
284 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
285 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
286 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
287 FT_Done_Face (ft_face
);
291 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
292 font_put_extra (entity
, QCfont_entity
, key
);
297 static Lisp_Object ftfont_generic_family_list
;
300 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
307 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
308 if (EQ (family
, Qmono
))
310 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
311 family
= Qsans_serif
;
312 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
315 if (! EQ (XCDR (slot
), Qt
))
317 pattern
= FcPatternDuplicate (pattern
);
320 FcPatternDel (pattern
, FC_FOUNDRY
);
321 FcPatternDel (pattern
, FC_FAMILY
);
322 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
323 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
325 /* This is to avoid the effect of locale. */
326 static const FcChar8 lang
[] = "en";
327 langset
= FcLangSetCreate ();
328 FcLangSetAdd (langset
, lang
);
329 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
330 FcLangSetDestroy (langset
);
332 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
333 FcDefaultSubstitute (pattern
);
334 match
= FcFontMatch (NULL
, pattern
, &result
);
339 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
340 family
= intern ((char *) fam
);
344 XSETCDR (slot
, family
);
345 if (match
) FcPatternDestroy (match
);
347 if (pattern
) FcPatternDestroy (pattern
);
351 struct ftfont_cache_data
354 FcCharSet
*fc_charset
;
358 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
360 Lisp_Object cache
, val
, entity
;
361 struct ftfont_cache_data
*cache_data
;
363 if (FONT_ENTITY_P (key
))
366 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
367 eassert (CONSP (val
));
373 if (NILP (ft_face_cache
))
376 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
379 if (NILP (ft_face_cache
))
380 ft_face_cache
= CALLN (Fmake_hash_table
, QCtest
, Qequal
);
381 cache_data
= xmalloc (sizeof *cache_data
);
382 cache_data
->ft_face
= NULL
;
383 cache_data
->fc_charset
= NULL
;
384 val
= make_save_ptr_int (cache_data
, 0);
385 cache
= Fcons (Qnil
, val
);
386 Fputhash (key
, cache
, ft_face_cache
);
391 cache_data
= XSAVE_POINTER (val
, 0);
394 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
397 if (cache_for
== FTFONT_CACHE_FOR_FACE
398 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
400 char *filename
= SSDATA (XCAR (key
));
401 int idx
= XINT (XCDR (key
));
403 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
406 && FT_Init_FreeType (&ft_library
) != 0)
408 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
414 FcPattern
*pat
= NULL
;
415 FcFontSet
*fontset
= NULL
;
416 FcObjectSet
*objset
= NULL
;
417 FcCharSet
*charset
= NULL
;
419 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
420 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
423 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
426 fontset
= FcFontList (NULL
, pat
, objset
);
429 if (fontset
&& fontset
->nfont
> 0
430 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
433 cache_data
->fc_charset
= FcCharSetCopy (charset
);
435 cache_data
->fc_charset
= FcCharSetCreate ();
439 FcFontSetDestroy (fontset
);
441 FcObjectSetDestroy (objset
);
443 FcPatternDestroy (pat
);
450 ftfont_get_fc_charset (Lisp_Object entity
)
452 Lisp_Object val
, cache
;
453 struct ftfont_cache_data
*cache_data
;
455 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
457 cache_data
= XSAVE_POINTER (val
, 0);
458 return cache_data
->fc_charset
;
463 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
467 if (ftfont_info
->otf
)
468 return ftfont_info
->otf
;
469 if (! ftfont_info
->maybe_otf
)
471 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
472 if (! otf
|| OTF_get_table (otf
, "head") < 0)
476 ftfont_info
->maybe_otf
= 0;
479 ftfont_info
->otf
= otf
;
482 #endif /* HAVE_LIBOTF */
484 static Lisp_Object
ftfont_get_cache (struct frame
*);
485 static Lisp_Object
ftfont_list (struct frame
*, Lisp_Object
);
486 static Lisp_Object
ftfont_match (struct frame
*, Lisp_Object
);
487 static Lisp_Object
ftfont_list_family (struct frame
*);
488 static Lisp_Object
ftfont_open (struct frame
*, Lisp_Object
, int);
489 static void ftfont_close (struct font
*);
490 static int ftfont_has_char (Lisp_Object
, int);
491 static unsigned ftfont_encode_char (struct font
*, int);
492 static void ftfont_text_extents (struct font
*, unsigned *, int,
493 struct font_metrics
*);
494 static int ftfont_get_bitmap (struct font
*, unsigned,
495 struct font_bitmap
*, int);
496 static int ftfont_anchor_point (struct font
*, unsigned, int,
499 static Lisp_Object
ftfont_otf_capability (struct font
*);
500 # ifdef HAVE_M17N_FLT
501 static Lisp_Object
ftfont_shape (Lisp_Object
);
505 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
506 static int ftfont_variation_glyphs (struct font
*, int c
,
507 unsigned variations
[256]);
508 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
510 struct font_driver ftfont_driver
=
512 LISP_INITIALLY_ZERO
, /* Qfreetype */
513 0, /* case insensitive */
518 NULL
, /* free_entity */
521 /* We can't draw a text without device dependent functions. */
522 NULL
, /* prepare_face */
523 NULL
, /* done_face */
527 /* We can't draw a text without device dependent functions. */
530 NULL
, /* free_bitmap */
533 ftfont_otf_capability
,
534 #else /* not HAVE_LIBOTF */
536 #endif /* not HAVE_LIBOTF */
537 NULL
, /* otf_drive */
538 NULL
, /* start_for_frame */
539 NULL
, /* end_for_frame */
540 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
542 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
544 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
547 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
548 ftfont_variation_glyphs
,
553 ftfont_filter_properties
, /* filter_properties */
557 ftfont_get_cache (struct frame
*f
)
559 return freetype_font_cache
;
563 ftfont_get_charset (Lisp_Object registry
)
565 char *str
= SSDATA (SYMBOL_NAME (registry
));
567 char *re
= SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
571 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
575 else if (str
[i
] == '*')
582 regexp
= make_unibyte_string (re
, j
);
584 for (i
= 0; fc_charset_table
[i
].name
; i
++)
585 if (fast_c_string_match_ignore_case
586 (regexp
, fc_charset_table
[i
].name
,
587 strlen (fc_charset_table
[i
].name
)) >= 0)
589 if (! fc_charset_table
[i
].name
)
591 if (! fc_charset_table
[i
].fc_charset
)
593 FcCharSet
*charset
= FcCharSetCreate ();
594 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
598 for (j
= 0; uniquifier
[j
]; j
++)
599 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
601 FcCharSetDestroy (charset
);
604 fc_charset_table
[i
].fc_charset
= charset
;
612 unsigned int script_tag
, langsys_tag
;
614 unsigned int *features
[2];
617 #define OTF_SYM_TAG(SYM, TAG) \
619 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
620 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
623 #define OTF_TAG_STR(TAG, P) \
625 (P)[0] = (char) (TAG >> 24); \
626 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
627 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
628 (P)[3] = (char) (TAG & 0xFF); \
633 #define OTF_TAG_SYM(SYM, TAG) \
637 OTF_TAG_STR (TAG, str); \
638 (SYM) = font_intern_prop (str, 4, 1); \
643 static struct OpenTypeSpec
*
644 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
646 struct OpenTypeSpec
*spec
= malloc (sizeof *spec
);
653 spec
->script
= XCAR (otf_spec
);
654 if (! NILP (spec
->script
))
656 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
657 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
658 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
659 spec
->script
= XCDR (val
);
664 spec
->script_tag
= 0x44464C54; /* "DFLT" */
665 otf_spec
= XCDR (otf_spec
);
666 spec
->langsys_tag
= 0;
667 if (! NILP (otf_spec
))
669 val
= XCAR (otf_spec
);
671 OTF_SYM_TAG (val
, spec
->langsys_tag
);
672 otf_spec
= XCDR (otf_spec
);
674 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
675 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
679 val
= XCAR (otf_spec
);
684 (min (PTRDIFF_MAX
, SIZE_MAX
) / sizeof (int) < XINT (len
)
686 : malloc (XINT (len
) * sizeof *spec
->features
[i
]));
687 if (! spec
->features
[i
])
689 if (i
> 0 && spec
->features
[0])
690 free (spec
->features
[0]);
694 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
696 if (NILP (XCAR (val
)))
702 OTF_SYM_TAG (XCAR (val
), tag
);
703 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
706 spec
->nfeatures
[i
] = j
;
712 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
714 Lisp_Object tmp
, extra
;
715 FcPattern
*pattern
= NULL
;
716 FcCharSet
*charset
= NULL
;
717 FcLangSet
*langset
= NULL
;
721 Lisp_Object script
= Qnil
;
722 Lisp_Object registry
;
725 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
727 /* Fontconfig doesn't support reverse-italic/oblique. */
730 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
731 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
732 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
733 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
736 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
738 || EQ (registry
, Qascii_0
)
739 || EQ (registry
, Qiso10646_1
)
740 || EQ (registry
, Qunicode_bmp
))
746 fc_charset_idx
= ftfont_get_charset (registry
);
747 if (fc_charset_idx
< 0)
749 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
750 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
751 lang
= (FcChar8
*) *langname
;
754 langset
= FcLangSetCreate ();
757 FcLangSetAdd (langset
, lang
);
762 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
763 CONSP (extra
); extra
= XCDR (extra
))
765 Lisp_Object key
, val
;
767 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
773 else if (EQ (key
, QClang
))
776 langset
= FcLangSetCreate ();
781 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
785 for (; CONSP (val
); val
= XCDR (val
))
786 if (SYMBOLP (XCAR (val
))
787 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
790 else if (EQ (key
, QCotf
))
794 *otspec
= ftfont_get_open_type_spec (val
);
797 strcpy (otlayout
, "otlayout:");
798 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
799 script
= (*otspec
)->script
;
802 else if (EQ (key
, QCscript
))
804 else if (EQ (key
, QCscalable
))
805 scalable
= ! NILP (val
);
808 if (! NILP (script
) && ! charset
)
810 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
812 if (CONSP (chars
) && CONSP (CDR (chars
)))
814 charset
= FcCharSetCreate ();
817 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
818 if (CHARACTERP (XCAR (chars
))
819 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
824 pattern
= FcPatternCreate ();
827 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
829 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
831 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
833 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
836 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
839 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
842 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
845 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
851 /* We come here because of unexpected error in fontconfig API call
852 (usually insufficient memory). */
855 FcPatternDestroy (pattern
);
860 if ((*otspec
)->nfeatures
[0] > 0)
861 free ((*otspec
)->features
[0]);
862 if ((*otspec
)->nfeatures
[1] > 0)
863 free ((*otspec
)->features
[1]);
869 if (langset
) FcLangSetDestroy (langset
);
870 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
875 ftfont_list (struct frame
*f
, Lisp_Object spec
)
877 Lisp_Object val
= Qnil
, family
, adstyle
;
880 FcFontSet
*fontset
= NULL
;
881 FcObjectSet
*objset
= NULL
;
883 Lisp_Object chars
= Qnil
;
884 char otlayout
[15]; /* For "otlayout:XXXX" */
885 struct OpenTypeSpec
*otspec
= NULL
;
887 const char *langname
= NULL
;
889 if (! fc_initialized
)
895 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
898 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
900 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
903 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
904 if (CONSP (val
) && VECTORP (XCDR (val
)))
909 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
910 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
911 family
= AREF (spec
, FONT_FAMILY_INDEX
);
914 Lisp_Object resolved
;
916 resolved
= ftfont_resolve_generic_family (family
, pattern
);
917 if (! NILP (resolved
))
919 FcPatternDel (pattern
, FC_FAMILY
);
920 if (! FcPatternAddString (pattern
, FC_FAMILY
,
921 SYMBOL_FcChar8 (resolved
)))
925 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
926 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
928 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
929 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
930 FC_STYLE
, FC_FILE
, FC_INDEX
,
933 #endif /* FC_CAPABILITY */
941 FcObjectSetAdd (objset
, FC_CHARSET
);
943 fontset
= FcFontList (NULL
, pattern
, objset
);
944 if (! fontset
|| fontset
->nfont
== 0)
947 /* Need fix because this finds any fonts. */
948 if (fontset
->nfont
== 0 && ! NILP (family
))
950 /* Try matching with configuration. For instance, the
951 configuration may specify "Nimbus Mono L" as an alias of
953 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
954 SYMBOL_FcChar8 (family
), NULL
);
957 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
960 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
963 FcPatternDel (pattern
, FC_FAMILY
);
964 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
965 FcFontSetDestroy (fontset
);
966 fontset
= FcFontList (NULL
, pattern
, objset
);
967 if (fontset
&& fontset
->nfont
> 0)
973 for (i
= 0; i
< fontset
->nfont
; i
++)
981 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
992 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
994 || ! strstr ((char *) this, otlayout
))
997 #endif /* FC_CAPABILITY */
1005 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1008 otf
= OTF_open ((char *) file
);
1011 passed
= (OTF_check_features (otf
, 1, otspec
->script_tag
,
1012 otspec
->langsys_tag
,
1013 otspec
->features
[0],
1014 otspec
->nfeatures
[0]) == 1
1015 && OTF_check_features (otf
, 0, otspec
->script_tag
,
1016 otspec
->langsys_tag
,
1017 otspec
->features
[1],
1018 otspec
->nfeatures
[1]) == 1);
1023 #endif /* HAVE_LIBOTF */
1024 if (VECTORP (chars
))
1028 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1031 for (j
= 0; j
< ASIZE (chars
); j
++)
1032 if (TYPE_RANGED_INTEGERP (FcChar32
, AREF (chars
, j
))
1033 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1035 if (j
== ASIZE (chars
))
1038 if (! NILP (adstyle
) || langname
)
1040 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1042 if (! NILP (adstyle
)
1043 && (NILP (this_adstyle
)
1044 || xstrcasecmp (SSDATA (SYMBOL_NAME (adstyle
)),
1045 SSDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1048 && ! NILP (this_adstyle
)
1049 && xstrcasecmp (langname
, SSDATA (SYMBOL_NAME (this_adstyle
))))
1052 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1053 AREF (spec
, FONT_EXTRA_INDEX
));
1054 if (! NILP (entity
))
1055 val
= Fcons (entity
, val
);
1057 val
= Fnreverse (val
);
1061 /* We come here because of unexpected error in fontconfig API call
1062 (usually insufficient memory). */
1066 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1067 if (objset
) FcObjectSetDestroy (objset
);
1068 if (fontset
) FcFontSetDestroy (fontset
);
1069 if (pattern
) FcPatternDestroy (pattern
);
1074 ftfont_match (struct frame
*f
, Lisp_Object spec
)
1076 Lisp_Object entity
= Qnil
;
1077 FcPattern
*pattern
, *match
= NULL
;
1079 char otlayout
[15]; /* For "otlayout:XXXX" */
1080 struct OpenTypeSpec
*otspec
= NULL
;
1081 const char *langname
= NULL
;
1083 if (! fc_initialized
)
1089 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1093 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1097 value
.type
= FcTypeDouble
;
1098 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1099 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1101 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1103 FcDefaultSubstitute (pattern
);
1104 match
= FcFontMatch (NULL
, pattern
, &result
);
1107 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1108 FcPatternDestroy (match
);
1109 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1110 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1111 ftfont_generic_family_list
))
1112 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1113 AREF (entity
, FONT_FAMILY_INDEX
))))
1117 FcPatternDestroy (pattern
);
1119 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1124 ftfont_list_family (struct frame
*f
)
1126 Lisp_Object list
= Qnil
;
1127 FcPattern
*pattern
= NULL
;
1128 FcFontSet
*fontset
= NULL
;
1129 FcObjectSet
*objset
= NULL
;
1132 if (! fc_initialized
)
1138 pattern
= FcPatternCreate ();
1141 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1144 fontset
= FcFontList (NULL
, pattern
, objset
);
1148 for (i
= 0; i
< fontset
->nfont
; i
++)
1150 FcPattern
*pat
= fontset
->fonts
[i
];
1153 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1154 list
= Fcons (intern ((char *) str
), list
);
1158 if (objset
) FcObjectSetDestroy (objset
);
1159 if (fontset
) FcFontSetDestroy (fontset
);
1160 if (pattern
) FcPatternDestroy (pattern
);
1167 ftfont_open2 (struct frame
*f
,
1170 Lisp_Object font_object
)
1172 struct ftfont_info
*ftfont_info
;
1174 struct ftfont_cache_data
*cache_data
;
1178 Lisp_Object val
, filename
, idx
, cache
;
1184 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1188 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1191 filename
= XCAR (val
);
1194 cache_data
= XSAVE_POINTER (XCDR (cache
), 0);
1195 ft_face
= cache_data
->ft_face
;
1196 if (XSAVE_INTEGER (val
, 1) > 0)
1198 /* FT_Face in this cache is already used by the different size. */
1199 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1201 if (FT_Activate_Size (ft_size
) != 0)
1203 FT_Done_Size (ft_size
);
1207 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) + 1);
1208 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1211 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1213 if (XSAVE_INTEGER (val
, 1) == 0)
1214 FT_Done_Face (ft_face
);
1218 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1219 font
= XFONT_OBJECT (font_object
);
1220 ftfont_info
= (struct ftfont_info
*) font
;
1221 ftfont_info
->ft_size
= ft_face
->size
;
1222 ftfont_info
->index
= XINT (idx
);
1224 ftfont_info
->maybe_otf
= (ft_face
->face_flags
& FT_FACE_FLAG_SFNT
) != 0;
1225 ftfont_info
->otf
= NULL
;
1226 #endif /* HAVE_LIBOTF */
1227 /* This means that there's no need of transformation. */
1228 ftfont_info
->matrix
.xx
= 0;
1229 font
->pixel_size
= size
;
1230 font
->driver
= &ftfont_driver
;
1231 font
->encoding_charset
= font
->repertory_charset
= -1;
1233 upEM
= ft_face
->units_per_EM
;
1234 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1235 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1238 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1239 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1240 font
->height
= ft_face
->height
* size
/ upEM
;
1244 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1245 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1246 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1248 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1249 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1251 spacing
= FC_PROPORTIONAL
;
1252 if (spacing
!= FC_PROPORTIONAL
1254 && spacing
!= FC_DUAL
1255 #endif /* FC_DUAL */
1257 font
->min_width
= font
->average_width
= font
->space_width
1258 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1259 : ft_face
->size
->metrics
.max_advance
>> 6);
1264 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1265 for (i
= 32, n
= 0; i
< 127; i
++)
1266 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1268 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1271 && (! font
->min_width
|| font
->min_width
> this_width
))
1272 font
->min_width
= this_width
;
1274 font
->space_width
= this_width
;
1275 font
->average_width
+= this_width
;
1279 font
->average_width
/= n
;
1282 font
->baseline_offset
= 0;
1283 font
->relative_compose
= 0;
1284 font
->default_ascent
= 0;
1285 font
->vertical_centering
= 0;
1288 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1289 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1293 font
->underline_position
= -1;
1294 font
->underline_thickness
= 0;
1301 ftfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
1303 Lisp_Object font_object
;
1305 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1308 font_object
= font_build_object (VECSIZE (struct ftfont_info
),
1309 Qfreetype
, entity
, size
);
1310 return ftfont_open2 (f
, entity
, pixel_size
, font_object
);
1314 ftfont_close (struct font
*font
)
1316 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1317 Lisp_Object val
, cache
;
1319 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1320 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1321 eassert (CONSP (cache
));
1323 set_save_integer (val
, 1, XSAVE_INTEGER (val
, 1) - 1);
1324 if (XSAVE_INTEGER (val
, 1) == 0)
1326 struct ftfont_cache_data
*cache_data
= XSAVE_POINTER (val
, 0);
1328 FT_Done_Face (cache_data
->ft_face
);
1330 if (ftfont_info
->otf
)
1331 OTF_close (ftfont_info
->otf
);
1333 cache_data
->ft_face
= NULL
;
1336 FT_Done_Size (ftfont_info
->ft_size
);
1340 ftfont_has_char (Lisp_Object font
, int c
)
1342 struct charset
*cs
= NULL
;
1344 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1345 && charset_jisx0208
>= 0)
1346 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1347 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1348 && charset_ksc5601
>= 0)
1349 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1351 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1353 if (FONT_ENTITY_P (font
))
1355 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1357 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1361 struct ftfont_info
*ftfont_info
;
1363 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1364 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1370 ftfont_encode_char (struct font
*font
, int c
)
1372 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1373 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1374 FT_ULong charcode
= c
;
1375 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1377 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1381 ftfont_text_extents (struct font
*font
, unsigned int *code
,
1382 int nglyphs
, struct font_metrics
*metrics
)
1384 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1385 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1389 if (ftfont_info
->ft_size
!= ft_face
->size
)
1390 FT_Activate_Size (ftfont_info
->ft_size
);
1392 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1394 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1396 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1400 metrics
->lbearing
= m
->horiBearingX
>> 6;
1401 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1402 metrics
->ascent
= m
->horiBearingY
>> 6;
1403 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1406 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1407 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1408 if (metrics
->rbearing
1409 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1411 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1412 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1413 metrics
->ascent
= m
->horiBearingY
>> 6;
1414 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1415 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1416 width
+= m
->horiAdvance
>> 6;
1419 width
+= font
->space_width
;
1421 metrics
->width
= width
;
1425 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1427 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1428 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1429 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1431 if (ftfont_info
->ft_size
!= ft_face
->size
)
1432 FT_Activate_Size (ftfont_info
->ft_size
);
1433 if (bits_per_pixel
== 1)
1435 #ifdef FT_LOAD_TARGET_MONO
1436 load_flags
|= FT_LOAD_TARGET_MONO
;
1438 load_flags
|= FT_LOAD_MONOCHROME
;
1441 else if (bits_per_pixel
!= 8)
1442 /* We don't support such a rendering. */
1445 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1447 bitmap
->bits_per_pixel
1448 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1449 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1450 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1451 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1453 if (bitmap
->bits_per_pixel
< 0)
1454 /* We don't support that kind of pixel mode. */
1456 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1457 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1458 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1459 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1460 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1461 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1462 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1468 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1471 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1472 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1474 if (ftfont_info
->ft_size
!= ft_face
->size
)
1475 FT_Activate_Size (ftfont_info
->ft_size
);
1476 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1478 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1480 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1482 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1483 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1490 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1492 Lisp_Object scripts
, langsyses
, features
, sym
;
1495 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1497 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1499 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1501 OTF_LangSys
*otf_langsys
;
1504 otf_langsys
= otf_script
->LangSys
+ j
;
1505 else if (otf_script
->DefaultLangSysOffset
)
1506 otf_langsys
= &otf_script
->DefaultLangSys
;
1510 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1512 l
= otf_langsys
->FeatureIndex
[k
];
1513 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1515 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1516 features
= Fcons (sym
, features
);
1519 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1522 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1525 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1526 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1534 ftfont_otf_capability (struct font
*font
)
1536 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1537 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1538 Lisp_Object gsub_gpos
;
1542 gsub_gpos
= Fcons (Qnil
, Qnil
);
1543 if (OTF_get_table (otf
, "GSUB") == 0
1544 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1545 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1546 if (OTF_get_table (otf
, "GPOS") == 0
1547 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1548 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1552 #ifdef HAVE_M17N_FLT
1554 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1555 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1556 /* We can use the new feature of libotf and m17n-flt to handle the
1557 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1558 some Agian scripts. */
1559 #define M17N_FLT_USE_NEW_FEATURE
1572 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1575 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1576 FT_Face ft_face
= flt_font_ft
->ft_face
;
1579 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1582 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1584 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1590 /* Operators for 26.6 fixed fractional pixel format */
1592 #define FLOOR(x) ((x) & -64)
1593 #define CEIL(x) (((x)+63) & -64)
1594 #define ROUND(x) (((x)+32) & -64)
1597 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1600 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1601 FT_Face ft_face
= flt_font_ft
->ft_face
;
1604 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1607 if (g
->code
!= FONT_INVALID_CODE
)
1609 FT_Glyph_Metrics
*m
;
1611 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1613 m
= &ft_face
->glyph
->metrics
;
1614 if (flt_font_ft
->matrix
)
1619 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1620 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1621 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1622 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1623 for (i
= 0; i
< 4; i
++)
1624 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1625 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1626 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1627 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1628 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1632 g
->lbearing
= FLOOR (m
->horiBearingX
);
1633 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1634 g
->ascent
= CEIL (m
->horiBearingY
);
1635 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1637 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1642 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1643 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1644 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1653 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1655 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1657 #define FEATURE_ANY(IDX) \
1658 (spec->features[IDX] \
1659 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1661 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1662 OTF
*otf
= flt_font_ft
->otf
;
1667 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1668 /* Return true iff any of GSUB or GPOS support the script (and
1671 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1673 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1676 for (i
= 0; i
< 2; i
++)
1677 if (! FEATURE_ANY (i
))
1679 if (FEATURE_NONE (i
))
1682 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1687 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1690 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1696 for (n
= 1; spec
->features
[i
][n
]; n
++);
1698 SAFE_NALLOCA (tags
, 1, n
);
1699 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1701 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1704 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1706 tags
[n
] = spec
->features
[i
][n
];
1709 #ifndef M17N_FLT_USE_NEW_FEATURE
1710 passed
= n
- negative
> 0;
1713 passed
= (OTF_check_features (otf
, i
== 0, spec
->script
,
1714 spec
->langsys
, tags
, n
- negative
)
1725 #define DEVICE_DELTA(table, size) \
1726 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1727 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1731 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1732 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1734 if (anchor
->AnchorFormat
== 2)
1736 FT_Outline
*outline
;
1737 int ap
= anchor
->f
.f1
.AnchorPoint
;
1739 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1740 outline
= &ft_face
->glyph
->outline
;
1741 if (ap
< outline
->n_points
)
1743 *x
= outline
->points
[ap
].x
<< 6;
1744 *y
= outline
->points
[ap
].y
<< 6;
1747 else if (anchor
->AnchorFormat
== 3)
1749 if (anchor
->f
.f2
.XDeviceTable
.offset
1750 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1751 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1752 if (anchor
->f
.f2
.YDeviceTable
.offset
1753 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1754 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1758 static OTF_GlyphString otf_gstring
;
1761 setup_otf_gstring (int size
)
1763 if (otf_gstring
.size
< size
)
1765 otf_gstring
.glyphs
= xnrealloc (otf_gstring
.glyphs
,
1766 size
, sizeof (OTF_Glyph
));
1767 otf_gstring
.size
= size
;
1769 otf_gstring
.used
= size
;
1770 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1773 #ifdef M17N_FLT_USE_NEW_FEATURE
1775 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1776 #define PACK_OTF_TAG(TAG) \
1777 ((((TAG) & 0x7F000000) >> 3) \
1778 | (((TAG) & 0x7F0000) >> 2) \
1779 | (((TAG) & 0x7F00) >> 1) \
1782 /* Assuming that FONT is an OpenType font, apply OpenType features
1783 specified in SPEC on glyphs between FROM and TO of IN, and record
1784 the lastly applied feature in each glyph of IN. If OUT is not
1785 NULL, append the resulting glyphs to OUT while storing glyph
1786 position adjustment information in ADJUSTMENT. */
1789 ftfont_drive_otf (MFLTFont
*font
,
1791 MFLTGlyphString
*in
,
1794 MFLTGlyphString
*out
,
1795 MFLTGlyphAdjustment
*adjustment
)
1797 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1798 FT_Face ft_face
= flt_font_ft
->ft_face
;
1799 OTF
*otf
= flt_font_ft
->otf
;
1800 int len
= to
- from
;
1803 char script
[5], *langsys
= NULL
;
1804 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1805 OTF_Feature
*features
;
1809 OTF_tag_name (spec
->script
, script
);
1814 langsys
= langsysbuf
;
1815 OTF_tag_name (spec
->langsys
, langsys
);
1819 for (i
= 0; i
< 2; i
++)
1823 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1825 for (j
= 0; spec
->features
[i
][j
]; j
++);
1826 SAFE_NALLOCA (p
, 6, j
);
1831 for (j
= 0; spec
->features
[i
][j
]; j
++)
1833 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1834 *p
++ = '*', *p
++ = ',';
1837 OTF_tag_name (spec
->features
[i
][j
], p
);
1846 setup_otf_gstring (len
);
1847 for (i
= 0; i
< len
; i
++)
1849 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
& 0x11FFFF;
1850 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1853 OTF_drive_gdef (otf
, &otf_gstring
);
1854 gidx
= out
? out
->used
: from
;
1856 if (gsub_features
&& out
)
1858 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1861 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1866 features
= otf
->gsub
->FeatureList
.Feature
;
1867 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1870 int min_from
, max_to
;
1871 int feature_idx
= otfg
->positioning_type
>> 4;
1873 g
= out
->glyphs
+ out
->used
;
1874 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1875 if (g
->code
!= otfg
->glyph_id
)
1878 g
->code
= otfg
->glyph_id
;
1884 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1886 /* OTFG substitutes multiple glyphs in IN. */
1887 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1888 j
<= from
+ otfg
->f
.index
.to
; j
++)
1890 if (min_from
> in
->glyphs
[j
].from
)
1891 min_from
= in
->glyphs
[j
].from
;
1892 if (max_to
< in
->glyphs
[j
].to
)
1893 max_to
= in
->glyphs
[j
].to
;
1900 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1901 tag
= PACK_OTF_TAG (tag
);
1902 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1904 for (i
++, otfg
++; (i
< otf_gstring
.used
1905 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1908 g
= out
->glyphs
+ out
->used
;
1909 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1910 if (g
->code
!= otfg
->glyph_id
)
1913 g
->code
= otfg
->glyph_id
;
1916 feature_idx
= otfg
->positioning_type
>> 4;
1919 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1920 tag
= PACK_OTF_TAG (tag
);
1921 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1927 else if (gsub_features
)
1929 /* Just for checking which features will be applied. */
1930 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1933 features
= otf
->gsub
->FeatureList
.Feature
;
1934 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1937 int feature_idx
= otfg
->positioning_type
>> 4;
1941 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1942 tag
= PACK_OTF_TAG (tag
);
1943 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1945 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1946 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1953 if (out
->allocated
< out
->used
+ len
)
1958 for (i
= 0; i
< len
; i
++)
1959 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1962 if (gpos_features
&& out
)
1964 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1965 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1967 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1973 features
= otf
->gpos
->FeatureList
.Feature
;
1974 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1975 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1976 x_scale
= ft_face
->size
->metrics
.x_scale
;
1977 y_scale
= ft_face
->size
->metrics
.y_scale
;
1979 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1980 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1983 int feature_idx
= otfg
->positioning_type
>> 4;
1987 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1988 tag
= PACK_OTF_TAG (tag
);
1989 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1992 if (! otfg
->glyph_id
)
1994 switch (otfg
->positioning_type
& 0xF)
1998 case 1: /* Single */
2001 int format
= otfg
->f
.f1
.format
;
2003 if (format
& OTF_XPlacement
)
2005 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2006 if (format
& OTF_XPlaDevice
)
2008 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2009 if (format
& OTF_YPlacement
)
2011 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2012 if (format
& OTF_YPlaDevice
)
2014 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2015 if (format
& OTF_XAdvance
)
2017 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2018 if (format
& OTF_XAdvDevice
)
2020 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2021 if (format
& OTF_YAdvance
)
2023 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2024 if (format
& OTF_YAdvDevice
)
2026 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2027 adjustment
[i
].set
= 1;
2030 case 3: /* Cursive */
2031 /* Not yet supported. */
2033 case 4: /* Mark-to-Base */
2034 case 5: /* Mark-to-Ligature */
2038 goto label_adjust_anchor
;
2039 default: /* i.e. case 6 Mark-to-Mark */
2044 label_adjust_anchor
:
2046 int base_x
, base_y
, mark_x
, mark_y
;
2047 int this_from
, this_to
;
2049 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2050 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2051 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2052 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2054 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2055 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2056 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2057 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2058 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2059 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2060 adjustment
[i
].xoff
= (base_x
- mark_x
);
2061 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2062 adjustment
[i
].back
= (g
- prev
);
2063 adjustment
[i
].xadv
= 0;
2064 adjustment
[i
].advance_is_absolute
= 1;
2065 adjustment
[i
].set
= 1;
2066 this_from
= g
->from
;
2068 for (j
= 0; prev
+ j
< g
; j
++)
2070 if (this_from
> prev
[j
].from
)
2071 this_from
= prev
[j
].from
;
2072 if (this_to
< prev
[j
].to
)
2073 this_to
= prev
[j
].to
;
2075 for (; prev
<= g
; prev
++)
2077 prev
->from
= this_from
;
2082 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2084 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2090 else if (gpos_features
)
2092 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2098 features
= otf
->gpos
->FeatureList
.Feature
;
2099 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2101 if (otfg
->positioning_type
& 0xF)
2103 int feature_idx
= otfg
->positioning_type
>> 4;
2107 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2108 tag
= PACK_OTF_TAG (tag
);
2109 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2111 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2112 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
);
2163 langsys
= langsysbuf
;
2164 OTF_tag_name (spec
->langsys
, langsys
);
2168 for (i
= 0; i
< 2; i
++)
2172 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2174 for (j
= 0; spec
->features
[i
][j
]; j
++);
2175 SAFE_NALLOCA (p
, 6, j
);
2180 for (j
= 0; spec
->features
[i
][j
]; j
++)
2182 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2183 *p
++ = '*', *p
++ = ',';
2186 OTF_tag_name (spec
->features
[i
][j
], p
);
2195 setup_otf_gstring (len
);
2196 for (i
= 0; i
< len
; i
++)
2198 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2199 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2202 OTF_drive_gdef (otf
, &otf_gstring
);
2207 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2210 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2215 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2218 int min_from
, max_to
;
2221 g
= out
->glyphs
+ out
->used
;
2222 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2223 if (g
->code
!= otfg
->glyph_id
)
2226 g
->code
= otfg
->glyph_id
;
2232 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2234 /* OTFG substitutes multiple glyphs in IN. */
2235 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2236 j
<= from
+ otfg
->f
.index
.to
; j
++)
2238 if (min_from
> in
->glyphs
[j
].from
)
2239 min_from
= in
->glyphs
[j
].from
;
2240 if (max_to
< in
->glyphs
[j
].to
)
2241 max_to
= in
->glyphs
[j
].to
;
2246 for (i
++, otfg
++; (i
< otf_gstring
.used
2247 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2250 g
= out
->glyphs
+ out
->used
;
2251 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2252 if (g
->code
!= otfg
->glyph_id
)
2255 g
->code
= otfg
->glyph_id
;
2264 if (out
->allocated
< out
->used
+ len
)
2269 for (i
= 0; i
< len
; i
++)
2270 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2275 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2276 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2278 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2285 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2286 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2287 x_scale
= ft_face
->size
->metrics
.x_scale
;
2288 y_scale
= ft_face
->size
->metrics
.y_scale
;
2290 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2291 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2295 if (! otfg
->glyph_id
)
2297 switch (otfg
->positioning_type
)
2301 case 1: /* Single */
2304 int format
= otfg
->f
.f1
.format
;
2306 if (format
& OTF_XPlacement
)
2308 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2309 if (format
& OTF_XPlaDevice
)
2311 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2312 if (format
& OTF_YPlacement
)
2314 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2315 if (format
& OTF_YPlaDevice
)
2317 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2318 if (format
& OTF_XAdvance
)
2320 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2321 if (format
& OTF_XAdvDevice
)
2323 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2324 if (format
& OTF_YAdvance
)
2326 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2327 if (format
& OTF_YAdvDevice
)
2329 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2330 adjustment
[i
].set
= 1;
2333 case 3: /* Cursive */
2334 /* Not yet supported. */
2336 case 4: /* Mark-to-Base */
2337 case 5: /* Mark-to-Ligature */
2341 goto label_adjust_anchor
;
2342 default: /* i.e. case 6 Mark-to-Mark */
2347 label_adjust_anchor
:
2349 int base_x
, base_y
, mark_x
, mark_y
;
2350 int this_from
, this_to
;
2352 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2353 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2354 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2355 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2357 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2358 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2359 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2360 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2361 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2362 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2363 adjustment
[i
].xoff
= (base_x
- mark_x
);
2364 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2365 adjustment
[i
].back
= (g
- prev
);
2366 adjustment
[i
].xadv
= 0;
2367 adjustment
[i
].advance_is_absolute
= 1;
2368 adjustment
[i
].set
= 1;
2369 this_from
= g
->from
;
2371 for (j
= 0; prev
+ j
< g
; j
++)
2373 if (this_from
> prev
[j
].from
)
2374 this_from
= prev
[j
].from
;
2375 if (this_to
< prev
[j
].to
)
2376 this_to
= prev
[j
].to
;
2378 for (; prev
<= g
; prev
++)
2380 prev
->from
= this_from
;
2385 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2387 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2398 if (out
->allocated
< out
->used
+ len
)
2400 font
->get_metrics (font
, in
, from
, to
);
2401 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2402 sizeof (MFLTGlyph
) * len
);
2407 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2409 static MFLTGlyphString gstring
;
2411 static bool m17n_flt_initialized
;
2414 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2415 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2417 ptrdiff_t len
= LGSTRING_GLYPH_LEN (lgstring
);
2419 struct MFLTFontFT flt_font_ft
;
2421 bool with_variation_selector
= 0;
2423 if (! m17n_flt_initialized
)
2426 #ifdef M17N_FLT_USE_NEW_FEATURE
2427 mflt_enable_new_feature
= 1;
2428 mflt_try_otf
= ftfont_try_otf
;
2429 #endif /* M17N_FLT_USE_NEW_FEATURE */
2430 m17n_flt_initialized
= 1;
2433 for (i
= 0; i
< len
; i
++)
2435 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2440 c
= LGLYPH_CHAR (g
);
2441 if (CHAR_VARIATION_SELECTOR_P (c
))
2442 with_variation_selector
= 1;
2447 if (with_variation_selector
)
2449 setup_otf_gstring (len
);
2450 for (i
= 0; i
< len
; i
++)
2452 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2454 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2455 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2456 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2458 OTF_drive_cmap (otf
, &otf_gstring
);
2459 for (i
= 0; i
< otf_gstring
.used
; i
++)
2461 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2462 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2463 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2465 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2466 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2467 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2469 if (len
> otf_gstring
.used
)
2471 len
= otf_gstring
.used
;
2472 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2476 if (INT_MAX
/ 2 < len
)
2477 memory_full (SIZE_MAX
);
2479 if (gstring
.allocated
== 0)
2481 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2482 gstring
.glyphs
= xnmalloc (len
* 2, sizeof *gstring
.glyphs
);
2483 gstring
.allocated
= len
* 2;
2485 else if (gstring
.allocated
< len
* 2)
2487 gstring
.glyphs
= xnrealloc (gstring
.glyphs
, len
* 2,
2488 sizeof *gstring
.glyphs
);
2489 gstring
.allocated
= len
* 2;
2491 memset (gstring
.glyphs
, 0, len
* sizeof *gstring
.glyphs
);
2492 for (i
= 0; i
< len
; i
++)
2494 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2496 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2497 if (with_variation_selector
)
2499 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2500 gstring
.glyphs
[i
].encoded
= 1;
2508 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2511 flt_font_ft
.flt_font
.family
= Mnil
;
2513 flt_font_ft
.flt_font
.family
2514 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2516 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2517 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2518 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2519 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2520 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2521 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2522 flt_font_ft
.flt_font
.internal
= NULL
;
2523 flt_font_ft
.font
= font
;
2524 flt_font_ft
.ft_face
= ft_face
;
2525 flt_font_ft
.otf
= otf
;
2526 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2528 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2529 /* A little bit ad hoc. Perhaps, shaper must get script and
2530 language information, and select a proper flt for them
2532 flt
= mflt_get (msymbol ("combining"));
2533 for (i
= 0; i
< 3; i
++)
2535 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2538 if (INT_MAX
/ 2 < gstring
.allocated
)
2539 memory_full (SIZE_MAX
);
2540 gstring
.glyphs
= xnrealloc (gstring
.glyphs
,
2541 gstring
.allocated
, 2 * sizeof (MFLTGlyph
));
2542 gstring
.allocated
*= 2;
2544 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2546 for (i
= 0; i
< gstring
.used
; i
++)
2548 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2550 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2551 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2554 for (i
= 0; i
< gstring
.used
; i
++)
2556 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2557 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2561 lglyph
= LGLYPH_NEW ();
2562 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2564 LGLYPH_SET_FROM (lglyph
, g
->from
);
2565 LGLYPH_SET_TO (lglyph
, g
->to
);
2566 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2567 LGLYPH_SET_CODE (lglyph
, g
->code
);
2568 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2569 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2570 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2571 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2572 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2575 Lisp_Object vec
= make_uninit_vector (3);
2577 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2578 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2579 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2580 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2583 return make_number (i
);
2587 ftfont_shape (Lisp_Object lgstring
)
2589 struct font
*font
= CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
));
2590 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2591 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2594 return make_number (0);
2595 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2596 &ftfont_info
->matrix
);
2599 #endif /* HAVE_M17N_FLT */
2601 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2604 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2606 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2607 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2611 return OTF_get_variation_glyphs (otf
, c
, variations
);
2614 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2615 #endif /* HAVE_LIBOTF */
2617 static const char *const ftfont_booleans
[] = {
2630 static const char *const ftfont_non_booleans
[] = {
2662 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2664 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2669 syms_of_ftfont (void)
2671 /* Symbolic type of this font-driver. */
2672 DEFSYM (Qfreetype
, "freetype");
2674 /* Fontconfig's generic families and their aliases. */
2675 DEFSYM (Qmonospace
, "monospace");
2676 DEFSYM (Qsans_serif
, "sans-serif");
2677 DEFSYM (Qserif
, "serif");
2678 DEFSYM (Qsans
, "sans");
2679 DEFSYM (Qsans__serif
, "sans serif");
2681 staticpro (&freetype_font_cache
);
2682 freetype_font_cache
= list1 (Qt
);
2684 staticpro (&ftfont_generic_family_list
);
2685 ftfont_generic_family_list
= list3 (Fcons (Qmonospace
, Qt
),
2686 Fcons (Qsans_serif
, Qt
),
2689 staticpro (&ft_face_cache
);
2690 ft_face_cache
= Qnil
;
2692 ftfont_driver
.type
= Qfreetype
;
2693 register_font_driver (&ftfont_driver
, NULL
);