1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
26 #include <fontconfig/fontconfig.h>
27 #include <fontconfig/fcfreetype.h>
30 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
36 #include "composite.h"
41 /* Symbolic type of this font-driver. */
42 Lisp_Object Qfreetype
;
44 /* Fontconfig's generic families and their aliases. */
45 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
47 /* Flag to tell if FcInit is already called or not. */
48 static int fc_initialized
;
50 /* Handle to a FreeType library instance. */
51 static FT_Library ft_library
;
53 /* Cache for FreeType fonts. */
54 static Lisp_Object freetype_font_cache
;
56 /* Cache for FT_Face and FcCharSet. */
57 static Lisp_Object ft_face_cache
;
59 /* The actual structure for FreeType font that can be casted to struct
66 /* The following four members must be here in this order to be
67 compatible with struct xftfont_info (in xftfont.c). */
68 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
70 #endif /* HAVE_LIBOTF */
78 FTFONT_CACHE_FOR_FACE
,
79 FTFONT_CACHE_FOR_CHARSET
,
80 FTFONT_CACHE_FOR_ENTITY
83 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
85 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
87 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
88 enum ftfont_cache_for
);
90 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
92 Lisp_Object
ftfont_font_format (FcPattern
*, Lisp_Object
);
94 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
100 /* characters to distinguish the charset from the others */
102 /* additional constraint by language */
105 FcCharSet
*fc_charset
;
106 } fc_charset_table
[] =
107 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
108 { "iso8859-2", { 0x00A0, 0x010E }},
109 { "iso8859-3", { 0x00A0, 0x0108 }},
110 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
111 { "iso8859-5", { 0x00A0, 0x0401 }},
112 { "iso8859-6", { 0x00A0, 0x060C }},
113 { "iso8859-7", { 0x00A0, 0x0384 }},
114 { "iso8859-8", { 0x00A0, 0x05D0 }},
115 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
116 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
117 { "iso8859-11", { 0x00A0, 0x0E01 }},
118 { "iso8859-13", { 0x00A0, 0x201C }},
119 { "iso8859-14", { 0x00A0, 0x0174 }},
120 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
121 { "iso8859-16", { 0x00A0, 0x0218}},
122 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
123 { "big5-0", { 0xF6B1 }, "zh-tw" },
124 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
125 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
126 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
127 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
128 { "cns11643.1992-3", { 0x201A9 }},
129 { "cns11643.1992-4", { 0x20057 }},
130 { "cns11643.1992-5", { 0x20000 }},
131 { "cns11643.1992-6", { 0x20003 }},
132 { "cns11643.1992-7", { 0x20055 }},
133 { "gbk-0", { 0x4E06 }, "zh-cn"},
134 { "jisx0212.1990-0", { 0x4E44 }},
135 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
136 { "jisx0213.2000-2", { 0xFA49 }},
137 { "jisx0213.2004-1", { 0x20B9F }},
138 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
139 { "tis620.2529-1", { 0x0E01 }, "th"},
140 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
141 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
142 { "mulelao-1", { 0x0E81 }, "lo"},
143 { "unicode-sip", { 0x20000 }},
147 extern Lisp_Object Qc
, Qm
, Qp
, Qd
;
149 /* Dirty hack for handing ADSTYLE property.
151 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
152 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
153 "Oblique", "Italic", or any non-normal SWIDTH property names
154 (e.g. SemiCondensed) are appended. In addition, if there's no
155 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
156 "Regular" is used for FC_STYLE (see the function
157 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
159 Unfortunately this behavior is not documented, so the following
160 code may fail if FreeType changes the behavior in the future. */
163 get_adstyle_property (FcPattern
*p
)
168 if (FcPatternGetString (p
, FC_STYLE
, 0, (FcChar8
**) &str
) != FcResultMatch
)
170 for (end
= str
; *end
&& *end
!= ' '; end
++);
173 char *p
= alloca (end
- str
+ 1);
174 memcpy (p
, str
, end
- str
);
176 end
= p
+ (end
- str
);
179 if (xstrcasecmp (str
, "Regular") == 0
180 || xstrcasecmp (str
, "Bold") == 0
181 || xstrcasecmp (str
, "Oblique") == 0
182 || xstrcasecmp (str
, "Italic") == 0)
184 adstyle
= font_intern_prop (str
, end
- str
, 1);
185 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
191 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
193 Lisp_Object key
, cache
, entity
;
200 if (FcPatternGetString (p
, FC_FILE
, 0, (FcChar8
**) &file
) != FcResultMatch
)
202 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &index
) != FcResultMatch
)
205 key
= Fcons (make_unibyte_string ((char *) file
, strlen ((char *) file
)),
206 make_number (index
));
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
));
218 entity
= font_make_entity ();
219 XSETCAR (cache
, entity
);
221 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
222 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
224 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
225 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
226 if (FcPatternGetString (p
, FC_FAMILY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
227 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
228 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
230 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
231 numeric
= FC_WEIGHT_MEDIUM
;
232 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
234 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
237 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
239 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
241 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
243 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
245 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
248 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
249 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
250 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
251 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
254 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
256 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
259 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
260 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
264 /* As this font is not scalable, parhaps this is a BDF or PCF
268 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
269 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
270 && FT_New_Face (ft_library
, file
, index
, &ft_face
) == 0)
274 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
275 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
276 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
277 FT_Done_Face (ft_face
);
281 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
282 font_put_extra (entity
, QCfont_entity
, key
);
287 static Lisp_Object ftfont_generic_family_list
;
290 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
297 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
298 if (EQ (family
, Qmono
))
300 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
301 family
= Qsans_serif
;
302 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
305 if (! EQ (XCDR (slot
), Qt
))
307 pattern
= FcPatternDuplicate (pattern
);
310 FcPatternDel (pattern
, FC_FOUNDRY
);
311 FcPatternDel (pattern
, FC_FAMILY
);
312 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
313 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
315 /* This is to avoid the effect of locale. */
316 langset
= FcLangSetCreate ();
317 FcLangSetAdd (langset
, "en");
318 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
319 FcLangSetDestroy (langset
);
321 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
322 FcDefaultSubstitute (pattern
);
323 match
= FcFontMatch (NULL
, pattern
, &result
);
328 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
329 family
= intern ((char *) fam
);
333 XSETCDR (slot
, family
);
334 if (match
) FcPatternDestroy (match
);
336 if (pattern
) FcPatternDestroy (pattern
);
340 struct ftfont_cache_data
343 FcCharSet
*fc_charset
;
347 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
349 Lisp_Object cache
, val
, entity
;
350 struct ftfont_cache_data
*cache_data
;
352 if (FONT_ENTITY_P (key
))
355 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
356 xassert (CONSP (val
));
362 if (NILP (ft_face_cache
))
365 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
368 if (NILP (ft_face_cache
))
374 ft_face_cache
= Fmake_hash_table (2, args
);
376 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
377 cache_data
->ft_face
= NULL
;
378 cache_data
->fc_charset
= NULL
;
379 val
= make_save_value (NULL
, 0);
380 XSAVE_VALUE (val
)->integer
= 0;
381 XSAVE_VALUE (val
)->pointer
= cache_data
;
382 cache
= Fcons (Qnil
, val
);
383 Fputhash (key
, cache
, ft_face_cache
);
388 cache_data
= XSAVE_VALUE (val
)->pointer
;
391 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
394 if (cache_for
== FTFONT_CACHE_FOR_FACE
395 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
397 char *filename
= (char *) SDATA (XCAR (key
));
398 int index
= XINT (XCDR (key
));
400 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
403 && FT_Init_FreeType (&ft_library
) != 0)
405 if (FT_New_Face (ft_library
, filename
, index
, &cache_data
->ft_face
)
411 FcPattern
*pat
= NULL
;
412 FcFontSet
*fontset
= NULL
;
413 FcObjectSet
*objset
= NULL
;
414 FcCharSet
*charset
= NULL
;
416 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
417 FC_INDEX
, FcTypeInteger
, index
, NULL
);
420 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
423 fontset
= FcFontList (NULL
, pat
, objset
);
426 if (fontset
&& fontset
->nfont
> 0
427 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
430 cache_data
->fc_charset
= FcCharSetCopy (charset
);
432 cache_data
->fc_charset
= FcCharSetCreate ();
436 FcFontSetDestroy (fontset
);
438 FcObjectSetDestroy (objset
);
440 FcPatternDestroy (pat
);
447 ftfont_get_fc_charset (Lisp_Object entity
)
449 Lisp_Object val
, cache
;
450 struct ftfont_cache_data
*cache_data
;
452 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
454 cache_data
= XSAVE_VALUE (val
)->pointer
;
455 return cache_data
->fc_charset
;
460 ftfont_get_otf (ftfont_info
)
461 struct ftfont_info
*ftfont_info
;
465 if (ftfont_info
->otf
)
466 return ftfont_info
->otf
;
467 if (! ftfont_info
->maybe_otf
)
469 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
470 if (! otf
|| OTF_get_table (otf
, "head") < 0)
474 ftfont_info
->maybe_otf
= 0;
477 ftfont_info
->otf
= otf
;
480 #endif /* HAVE_LIBOTF */
482 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
483 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
484 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
485 static Lisp_Object
ftfont_list_family (Lisp_Object
);
486 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
487 static void ftfont_close (FRAME_PTR
, struct font
*);
488 static int ftfont_has_char (Lisp_Object
, int);
489 static unsigned ftfont_encode_char (struct font
*, int);
490 static int ftfont_text_extents (struct font
*, unsigned *, int,
491 struct font_metrics
*);
492 static int ftfont_get_bitmap (struct font
*, unsigned,
493 struct font_bitmap
*, int);
494 static int ftfont_anchor_point (struct font
*, unsigned, int,
496 static Lisp_Object
ftfont_otf_capability (struct font
*);
497 static Lisp_Object
ftfont_shape (Lisp_Object
);
499 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
500 static int ftfont_variation_glyphs (struct font
*, int c
,
501 unsigned variations
[256]);
502 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
504 struct font_driver ftfont_driver
=
507 0, /* case insensitive */
512 NULL
, /* free_entity */
515 /* We can't draw a text without device dependent functions. */
516 NULL
, /* prepare_face */
517 NULL
, /* done_face */
521 /* We can't draw a text without device dependent functions. */
524 NULL
, /* get_bitmap */
525 NULL
, /* free_bitmap */
526 NULL
, /* get_outline */
529 ftfont_otf_capability
,
530 #else /* not HAVE_LIBOTF */
532 #endif /* not HAVE_LIBOTF */
533 NULL
, /* otf_drive */
534 NULL
, /* start_for_frame */
535 NULL
, /* end_for_frame */
536 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
538 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
540 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
543 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
544 ftfont_variation_glyphs
,
549 ftfont_filter_properties
, /* filter_properties */
552 extern Lisp_Object QCname
;
555 ftfont_get_cache (FRAME_PTR f
)
557 return freetype_font_cache
;
561 ftfont_get_charset (Lisp_Object registry
)
563 char *str
= (char *) SDATA (SYMBOL_NAME (registry
));
564 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
568 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
572 else if (str
[i
] == '*')
579 regexp
= make_unibyte_string (re
, j
);
580 for (i
= 0; fc_charset_table
[i
].name
; i
++)
581 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
583 if (! fc_charset_table
[i
].name
)
585 if (! fc_charset_table
[i
].fc_charset
)
587 FcCharSet
*charset
= FcCharSetCreate ();
588 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
592 for (j
= 0; uniquifier
[j
]; j
++)
593 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
595 FcCharSetDestroy (charset
);
598 fc_charset_table
[i
].fc_charset
= charset
;
606 unsigned int script_tag
, langsys_tag
;
608 unsigned int *features
[2];
611 #define OTF_SYM_TAG(SYM, TAG) \
613 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
614 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
617 #define OTF_TAG_STR(TAG, P) \
619 (P)[0] = (char) (TAG >> 24); \
620 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
621 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
622 (P)[3] = (char) (TAG & 0xFF); \
626 #define OTF_TAG_SYM(SYM, TAG) \
630 OTF_TAG_STR (TAG, str); \
631 (SYM) = font_intern_prop (str, 4, 1); \
635 static struct OpenTypeSpec
*
636 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
638 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
644 spec
->script
= XCAR (otf_spec
);
645 if (! NILP (spec
->script
))
647 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
648 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
649 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
650 spec
->script
= XCDR (val
);
655 spec
->script_tag
= 0x44464C54; /* "DFLT" */
656 otf_spec
= XCDR (otf_spec
);
657 spec
->langsys_tag
= 0;
658 if (! NILP (otf_spec
))
660 val
= XCAR (otf_spec
);
662 OTF_SYM_TAG (val
, spec
->langsys_tag
);
663 otf_spec
= XCDR (otf_spec
);
665 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
666 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
670 val
= XCAR (otf_spec
);
674 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
675 if (! spec
->features
[i
])
677 if (i
> 0 && spec
->features
[0])
678 free (spec
->features
[0]);
682 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
684 if (NILP (XCAR (val
)))
690 OTF_SYM_TAG (XCAR (val
), tag
);
691 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
694 spec
->nfeatures
[i
] = j
;
699 static FcPattern
*ftfont_spec_pattern (Lisp_Object
, char *,
700 struct OpenTypeSpec
**,
704 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, char **langname
)
706 Lisp_Object tmp
, extra
;
707 FcPattern
*pattern
= NULL
;
708 FcCharSet
*charset
= NULL
;
709 FcLangSet
*langset
= NULL
;
713 Lisp_Object script
= Qnil
;
714 Lisp_Object registry
;
717 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
719 /* Fontconfig doesn't support reverse-italic/obligue. */
722 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
723 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
724 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
725 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
728 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
730 || EQ (registry
, Qascii_0
)
731 || EQ (registry
, Qiso10646_1
)
732 || EQ (registry
, Qunicode_bmp
))
738 fc_charset_idx
= ftfont_get_charset (registry
);
739 if (fc_charset_idx
< 0)
741 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
742 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
743 lang
= (FcChar8
*) *langname
;
746 langset
= FcLangSetCreate ();
749 FcLangSetAdd (langset
, lang
);
754 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
755 CONSP (extra
); extra
= XCDR (extra
))
757 Lisp_Object key
, val
;
759 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
762 else if (EQ (key
, QClang
))
765 langset
= FcLangSetCreate ();
770 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
774 for (; CONSP (val
); val
= XCDR (val
))
775 if (SYMBOLP (XCAR (val
))
776 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
779 else if (EQ (key
, QCotf
))
781 *otspec
= ftfont_get_open_type_spec (val
);
784 strcat (otlayout
, "otlayout:");
785 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
786 script
= (*otspec
)->script
;
788 else if (EQ (key
, QCscript
))
790 else if (EQ (key
, QCscalable
))
791 scalable
= ! NILP (val
);
794 if (! NILP (script
) && ! charset
)
796 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
798 if (CONSP (chars
) && CONSP (CDR (chars
)))
800 charset
= FcCharSetCreate ();
803 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
804 if (CHARACTERP (XCAR (chars
))
805 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
810 pattern
= FcPatternCreate ();
813 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
815 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
817 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
819 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
822 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
825 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
828 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
831 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
837 /* We come here because of unexpected error in fontconfig API call
838 (usually insufficient memory). */
841 FcPatternDestroy (pattern
);
846 if ((*otspec
)->nfeatures
[0] > 0)
847 free ((*otspec
)->features
[0]);
848 if ((*otspec
)->nfeatures
[1] > 0)
849 free ((*otspec
)->features
[1]);
855 if (langset
) FcLangSetDestroy (langset
);
856 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
861 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
863 Lisp_Object val
= Qnil
, family
, adstyle
;
866 FcFontSet
*fontset
= NULL
;
867 FcObjectSet
*objset
= NULL
;
869 Lisp_Object chars
= Qnil
;
871 char otlayout
[15]; /* For "otlayout:XXXX" */
872 struct OpenTypeSpec
*otspec
= NULL
;
874 char *langname
= NULL
;
876 if (! fc_initialized
)
882 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
885 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
887 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
890 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
891 if (CONSP (val
) && VECTORP (XCDR (val
)))
896 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
897 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
898 family
= AREF (spec
, FONT_FAMILY_INDEX
);
901 Lisp_Object resolved
;
903 resolved
= ftfont_resolve_generic_family (family
, pattern
);
904 if (! NILP (resolved
))
906 FcPatternDel (pattern
, FC_FAMILY
);
907 if (! FcPatternAddString (pattern
, FC_FAMILY
,
908 SYMBOL_FcChar8 (resolved
)))
912 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
913 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
915 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
916 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
917 FC_STYLE
, FC_FILE
, FC_INDEX
,
920 #endif /* FC_CAPABILITY */
928 FcObjectSetAdd (objset
, FC_CHARSET
);
930 fontset
= FcFontList (NULL
, pattern
, objset
);
931 if (! fontset
|| fontset
->nfont
== 0)
934 /* Need fix because this finds any fonts. */
935 if (fontset
->nfont
== 0 && ! NILP (family
))
937 /* Try maching with configuration. For instance, the
938 configuration may specify "Nimbus Mono L" as an alias of
940 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
941 SYMBOL_FcChar8 (family
), NULL
);
944 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
947 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
950 FcPatternDel (pattern
, FC_FAMILY
);
951 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
952 FcFontSetDestroy (fontset
);
953 fontset
= FcFontList (NULL
, pattern
, objset
);
954 if (fontset
&& fontset
->nfont
> 0)
960 for (i
= 0; i
< fontset
->nfont
; i
++)
968 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
979 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
981 || ! strstr ((char *) this, otlayout
))
984 #endif /* FC_CAPABILITY */
991 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
994 otf
= OTF_open ((char *) file
);
997 if (OTF_check_features (otf
, 1,
998 otspec
->script_tag
, otspec
->langsys_tag
,
1000 otspec
->nfeatures
[0]) != 1
1001 || OTF_check_features (otf
, 0,
1002 otspec
->script_tag
, otspec
->langsys_tag
,
1003 otspec
->features
[1],
1004 otspec
->nfeatures
[1]) != 1)
1007 #endif /* HAVE_LIBOTF */
1008 if (VECTORP (chars
))
1012 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1015 for (j
= 0; j
< ASIZE (chars
); j
++)
1016 if (NATNUMP (AREF (chars
, j
))
1017 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1019 if (j
== ASIZE (chars
))
1022 if (! NILP (adstyle
) || langname
)
1024 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1026 if (! NILP (adstyle
)
1027 && (NILP (this_adstyle
)
1028 || xstrcasecmp (SDATA (SYMBOL_NAME (adstyle
)),
1029 SDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1032 && ! NILP (this_adstyle
)
1033 && xstrcasecmp (langname
, SDATA (SYMBOL_NAME (this_adstyle
))))
1036 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1037 AREF (spec
, FONT_EXTRA_INDEX
));
1038 if (! NILP (entity
))
1039 val
= Fcons (entity
, val
);
1041 val
= Fnreverse (val
);
1045 /* We come here because of unexpected error in fontconfig API call
1046 (usually insufficient memory). */
1050 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1051 if (objset
) FcObjectSetDestroy (objset
);
1052 if (fontset
) FcFontSetDestroy (fontset
);
1053 if (pattern
) FcPatternDestroy (pattern
);
1058 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1060 Lisp_Object entity
= Qnil
;
1061 FcPattern
*pattern
, *match
= NULL
;
1063 char otlayout
[15]; /* For "otlayout:XXXX" */
1064 struct OpenTypeSpec
*otspec
= NULL
;
1065 char *langname
= NULL
;
1067 if (! fc_initialized
)
1073 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1077 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1081 value
.type
= FcTypeDouble
;
1082 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1083 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1085 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1087 FcDefaultSubstitute (pattern
);
1088 match
= FcFontMatch (NULL
, pattern
, &result
);
1091 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1092 FcPatternDestroy (match
);
1093 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1094 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1095 ftfont_generic_family_list
))
1096 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1097 AREF (entity
, FONT_FAMILY_INDEX
))))
1101 FcPatternDestroy (pattern
);
1103 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1108 ftfont_list_family (Lisp_Object frame
)
1110 Lisp_Object list
= Qnil
;
1111 FcPattern
*pattern
= NULL
;
1112 FcFontSet
*fontset
= NULL
;
1113 FcObjectSet
*objset
= NULL
;
1116 if (! fc_initialized
)
1122 pattern
= FcPatternCreate ();
1125 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1128 fontset
= FcFontList (NULL
, pattern
, objset
);
1132 for (i
= 0; i
< fontset
->nfont
; i
++)
1134 FcPattern
*pat
= fontset
->fonts
[i
];
1137 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1138 list
= Fcons (intern ((char *) str
), list
);
1142 if (objset
) FcObjectSetDestroy (objset
);
1143 if (fontset
) FcFontSetDestroy (fontset
);
1144 if (pattern
) FcPatternDestroy (pattern
);
1151 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1153 struct ftfont_info
*ftfont_info
;
1155 struct ftfont_cache_data
*cache_data
;
1159 Lisp_Object val
, filename
, index
, cache
, font_object
;
1166 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1170 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1173 filename
= XCAR (val
);
1176 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1177 ft_face
= cache_data
->ft_face
;
1178 if (XSAVE_VALUE (val
)->integer
> 0)
1180 /* FT_Face in this cache is already used by the different size. */
1181 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1183 if (FT_Activate_Size (ft_size
) != 0)
1185 FT_Done_Size (ft_size
);
1189 XSAVE_VALUE (val
)->integer
++;
1190 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1193 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1195 if (XSAVE_VALUE (val
)->integer
== 0)
1196 FT_Done_Face (ft_face
);
1200 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1201 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1202 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1204 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1205 len
= font_unparse_fcname (entity
, size
, name
, 256);
1207 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1209 ASET (font_object
, FONT_FULLNAME_INDEX
,
1210 AREF (font_object
, FONT_NAME_INDEX
));
1211 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1212 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1213 font
= XFONT_OBJECT (font_object
);
1214 ftfont_info
= (struct ftfont_info
*) font
;
1215 ftfont_info
->ft_size
= ft_face
->size
;
1216 ftfont_info
->index
= XINT (index
);
1218 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1219 ftfont_info
->otf
= NULL
;
1220 #endif /* HAVE_LIBOTF */
1221 /* This means that there's no need of transformation. */
1222 ftfont_info
->matrix
.xx
= 0;
1223 font
->pixel_size
= size
;
1224 font
->driver
= &ftfont_driver
;
1225 font
->encoding_charset
= font
->repertory_charset
= -1;
1227 upEM
= ft_face
->units_per_EM
;
1228 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1229 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1232 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1233 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1234 font
->height
= ft_face
->height
* size
/ upEM
;
1238 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1239 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1240 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1242 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1243 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1245 spacing
= FC_PROPORTIONAL
;
1246 if (spacing
!= FC_PROPORTIONAL
&& spacing
!= FC_DUAL
)
1247 font
->min_width
= font
->average_width
= font
->space_width
1248 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1249 : ft_face
->size
->metrics
.max_advance
>> 6);
1254 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1255 for (i
= 32, n
= 0; i
< 127; i
++)
1256 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1258 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1261 && (! font
->min_width
|| font
->min_width
> this_width
))
1262 font
->min_width
= this_width
;
1264 font
->space_width
= this_width
;
1265 font
->average_width
+= this_width
;
1269 font
->average_width
/= n
;
1272 font
->baseline_offset
= 0;
1273 font
->relative_compose
= 0;
1274 font
->default_ascent
= 0;
1275 font
->vertical_centering
= 0;
1278 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1279 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1283 font
->underline_position
= -1;
1284 font
->underline_thickness
= 0;
1291 ftfont_close (FRAME_PTR f
, struct font
*font
)
1293 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1294 Lisp_Object val
, cache
;
1296 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1297 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1298 xassert (CONSP (cache
));
1300 (XSAVE_VALUE (val
)->integer
)--;
1301 if (XSAVE_VALUE (val
)->integer
== 0)
1303 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1305 FT_Done_Face (cache_data
->ft_face
);
1307 if (ftfont_info
->otf
)
1308 OTF_close (ftfont_info
->otf
);
1310 cache_data
->ft_face
= NULL
;
1313 FT_Done_Size (ftfont_info
->ft_size
);
1317 ftfont_has_char (Lisp_Object font
, int c
)
1319 struct charset
*cs
= NULL
;
1321 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1322 && charset_jisx0208
>= 0)
1323 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1324 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1325 && charset_ksc5601
>= 0)
1326 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1328 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1330 if (FONT_ENTITY_P (font
))
1332 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1334 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1338 struct ftfont_info
*ftfont_info
;
1340 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1341 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1347 ftfont_encode_char (struct font
*font
, int c
)
1349 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1350 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1351 FT_ULong charcode
= c
;
1352 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1354 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1358 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1360 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1361 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1365 if (ftfont_info
->ft_size
!= ft_face
->size
)
1366 FT_Activate_Size (ftfont_info
->ft_size
);
1368 memset (metrics
, 0, sizeof (struct font_metrics
));
1369 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1371 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1373 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1379 metrics
->lbearing
= m
->horiBearingX
>> 6;
1380 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1381 metrics
->ascent
= m
->horiBearingY
>> 6;
1382 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1388 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1389 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1390 if (metrics
->rbearing
1391 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1393 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1394 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1395 metrics
->ascent
= m
->horiBearingY
>> 6;
1396 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1397 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1399 width
+= m
->horiAdvance
>> 6;
1403 width
+= font
->space_width
;
1407 metrics
->width
= width
;
1413 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1415 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1416 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1417 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1419 if (ftfont_info
->ft_size
!= ft_face
->size
)
1420 FT_Activate_Size (ftfont_info
->ft_size
);
1421 if (bits_per_pixel
== 1)
1423 #ifdef FT_LOAD_TARGET_MONO
1424 load_flags
|= FT_LOAD_TARGET_MONO
;
1426 load_flags
|= FT_LOAD_MONOCHROME
;
1429 else if (bits_per_pixel
!= 8)
1430 /* We don't support such a rendering. */
1433 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1435 bitmap
->bits_per_pixel
1436 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1437 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1438 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1439 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1441 if (bitmap
->bits_per_pixel
< 0)
1442 /* We don't suport that kind of pixel mode. */
1444 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1445 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1446 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1447 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1448 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1449 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1450 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1451 bitmap
->extra
= NULL
;
1457 ftfont_anchor_point (struct font
*font
, unsigned int code
, int index
, int *x
, int *y
)
1459 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1460 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1462 if (ftfont_info
->ft_size
!= ft_face
->size
)
1463 FT_Activate_Size (ftfont_info
->ft_size
);
1464 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1466 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1468 if (index
>= ft_face
->glyph
->outline
.n_points
)
1470 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
1471 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
1478 ftfont_otf_features (gsub_gpos
)
1479 OTF_GSUB_GPOS
*gsub_gpos
;
1481 Lisp_Object scripts
, langsyses
, features
, sym
;
1484 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1486 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1488 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1490 OTF_LangSys
*otf_langsys
;
1493 otf_langsys
= otf_script
->LangSys
+ j
;
1494 else if (otf_script
->DefaultLangSysOffset
)
1495 otf_langsys
= &otf_script
->DefaultLangSys
;
1499 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1501 l
= otf_langsys
->FeatureIndex
[k
];
1502 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1504 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1505 features
= Fcons (sym
, features
);
1508 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1511 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1514 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1515 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1523 ftfont_otf_capability (font
)
1526 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1527 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1528 Lisp_Object gsub_gpos
;
1532 gsub_gpos
= Fcons (Qnil
, Qnil
);
1533 if (OTF_get_table (otf
, "GSUB") == 0
1534 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1535 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1536 if (OTF_get_table (otf
, "GPOS") == 0
1537 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1538 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1542 #ifdef HAVE_M17N_FLT
1544 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1545 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1546 /* We can use the new feature of libotf and m17n-flt to handle the
1547 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1548 some Agian scripts. */
1549 #define M17N_FLT_USE_NEW_FEATURE
1562 ftfont_get_glyph_id (font
, gstring
, from
, to
)
1564 MFLTGlyphString
*gstring
;
1567 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1568 FT_Face ft_face
= flt_font_ft
->ft_face
;
1571 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1574 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1576 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1582 /* Operators for 26.6 fixed fractional pixel format */
1584 #define FLOOR(x) ((x) & -64)
1585 #define CEIL(x) (((x)+63) & -64)
1586 #define ROUND(x) (((x)+32) & -64)
1589 ftfont_get_metrics (font
, gstring
, from
, to
)
1591 MFLTGlyphString
*gstring
;
1594 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1595 FT_Face ft_face
= flt_font_ft
->ft_face
;
1598 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1601 if (g
->code
!= FONT_INVALID_CODE
)
1603 FT_Glyph_Metrics
*m
;
1604 int lbearing
, rbearing
, ascent
, descent
, xadv
;
1606 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1608 m
= &ft_face
->glyph
->metrics
;
1609 if (flt_font_ft
->matrix
)
1614 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1615 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1616 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1617 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1618 for (i
= 0; i
< 4; i
++)
1619 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1620 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1621 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1622 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1623 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1627 g
->lbearing
= FLOOR (m
->horiBearingX
);
1628 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1629 g
->ascent
= CEIL (m
->horiBearingY
);
1630 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1632 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1637 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1638 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1639 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1648 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1650 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1651 OTF
*otf
= flt_font_ft
->otf
;
1655 for (i
= 0; i
< 2; i
++)
1657 if (! spec
->features
[i
])
1659 for (n
= 0; spec
->features
[i
][n
]; n
++);
1660 tags
= alloca (sizeof (OTF_Tag
) * n
);
1661 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1663 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1666 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1668 tags
[n
] = spec
->features
[i
][n
];
1670 #ifdef M17N_FLT_USE_NEW_FEATURE
1671 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1672 tags
, n
- negative
) != 1)
1674 #else /* not M17N_FLT_USE_NEW_FEATURE */
1675 if (n
- negative
> 0
1676 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1677 tags
, n
- negative
) != 1)
1679 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1684 #define DEVICE_DELTA(table, size) \
1685 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1686 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1690 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1691 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1693 if (anchor
->AnchorFormat
== 2)
1695 FT_Outline
*outline
;
1696 int ap
= anchor
->f
.f1
.AnchorPoint
;
1698 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1699 outline
= &ft_face
->glyph
->outline
;
1700 if (ap
< outline
->n_points
)
1702 *x
= outline
->points
[ap
].x
<< 6;
1703 *y
= outline
->points
[ap
].y
<< 6;
1706 else if (anchor
->AnchorFormat
== 3)
1708 if (anchor
->f
.f2
.XDeviceTable
.offset
1709 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1710 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1711 if (anchor
->f
.f2
.YDeviceTable
.offset
1712 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1713 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1717 static OTF_GlyphString otf_gstring
;
1720 setup_otf_gstring (int size
)
1722 if (otf_gstring
.size
== 0)
1724 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1725 otf_gstring
.size
= size
;
1727 else if (otf_gstring
.size
< size
)
1729 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1730 sizeof (OTF_Glyph
) * size
);
1731 otf_gstring
.size
= size
;
1733 otf_gstring
.used
= size
;
1734 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1737 #ifdef M17N_FLT_USE_NEW_FEATURE
1739 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1740 #define PACK_OTF_TAG(TAG) \
1741 ((((TAG) & 0x7F000000) >> 3) \
1742 | (((TAG) & 0x7F0000) >> 2) \
1743 | (((TAG) & 0x7F00) >> 1) \
1746 /* Assuming that FONT is an OpenType font, apply OpenType features
1747 specified in SPEC on glyphs between FROM and TO of IN, and record
1748 the lastly applied feature in each glyph of IN. If OUT is not
1749 NULL, append the resulting glyphs to OUT while storing glyph
1750 position adjustment information in ADJUSTMENT. */
1753 ftfont_drive_otf (font
, spec
, in
, from
, to
, out
, adjustment
)
1756 MFLTGlyphString
*in
;
1758 MFLTGlyphString
*out
;
1759 MFLTGlyphAdjustment
*adjustment
;
1761 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1762 FT_Face ft_face
= flt_font_ft
->ft_face
;
1763 OTF
*otf
= flt_font_ft
->otf
;
1764 int len
= to
- from
;
1767 char script
[5], *langsys
= NULL
;
1768 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1769 OTF_Feature
*features
;
1773 OTF_tag_name (spec
->script
, script
);
1776 langsys
= alloca (5);
1777 OTF_tag_name (spec
->langsys
, langsys
);
1779 for (i
= 0; i
< 2; i
++)
1783 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1785 for (j
= 0; spec
->features
[i
][j
]; j
++);
1787 p
= gsub_features
= alloca (6 * j
);
1789 p
= gpos_features
= alloca (6 * j
);
1790 for (j
= 0; spec
->features
[i
][j
]; j
++)
1792 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1793 *p
++ = '*', *p
++ = ',';
1796 OTF_tag_name (spec
->features
[i
][j
], p
);
1805 setup_otf_gstring (len
);
1806 for (i
= 0; i
< len
; i
++)
1808 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1809 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1812 OTF_drive_gdef (otf
, &otf_gstring
);
1813 gidx
= out
? out
->used
: from
;
1815 if (gsub_features
&& out
)
1817 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1820 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1822 features
= otf
->gsub
->FeatureList
.Feature
;
1823 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1826 int min_from
, max_to
;
1828 int feature_idx
= otfg
->positioning_type
>> 4;
1830 g
= out
->glyphs
+ out
->used
;
1831 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1832 if (g
->code
!= otfg
->glyph_id
)
1835 g
->code
= otfg
->glyph_id
;
1841 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1843 /* OTFG substitutes multiple glyphs in IN. */
1844 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1845 j
<= from
+ otfg
->f
.index
.to
; j
++)
1847 if (min_from
> in
->glyphs
[j
].from
)
1848 min_from
= in
->glyphs
[j
].from
;
1849 if (max_to
< in
->glyphs
[j
].to
)
1850 max_to
= in
->glyphs
[j
].to
;
1857 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1858 tag
= PACK_OTF_TAG (tag
);
1859 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1861 for (i
++, otfg
++; (i
< otf_gstring
.used
1862 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1865 g
= out
->glyphs
+ out
->used
;
1866 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1867 if (g
->code
!= otfg
->glyph_id
)
1870 g
->code
= otfg
->glyph_id
;
1873 feature_idx
= otfg
->positioning_type
>> 4;
1876 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1877 tag
= PACK_OTF_TAG (tag
);
1878 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1884 else if (gsub_features
)
1886 /* Just for checking which features will be applied. */
1887 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1890 features
= otf
->gsub
->FeatureList
.Feature
;
1891 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1894 int feature_idx
= otfg
->positioning_type
>> 4;
1898 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1899 tag
= PACK_OTF_TAG (tag
);
1900 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1902 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1903 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1910 if (out
->allocated
< out
->used
+ len
)
1912 for (i
= 0; i
< len
; i
++)
1913 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1916 if (gpos_features
&& out
)
1918 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1919 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1921 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1924 features
= otf
->gpos
->FeatureList
.Feature
;
1925 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1926 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1927 x_scale
= ft_face
->size
->metrics
.x_scale
;
1928 y_scale
= ft_face
->size
->metrics
.y_scale
;
1930 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1931 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1934 int feature_idx
= otfg
->positioning_type
>> 4;
1938 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1939 tag
= PACK_OTF_TAG (tag
);
1940 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1943 if (! otfg
->glyph_id
)
1945 switch (otfg
->positioning_type
& 0xF)
1949 case 1: /* Single */
1952 int format
= otfg
->f
.f1
.format
;
1954 if (format
& OTF_XPlacement
)
1956 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1957 if (format
& OTF_XPlaDevice
)
1959 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1960 if (format
& OTF_YPlacement
)
1962 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
1963 if (format
& OTF_YPlaDevice
)
1965 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
1966 if (format
& OTF_XAdvance
)
1968 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
1969 if (format
& OTF_XAdvDevice
)
1971 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
1972 if (format
& OTF_YAdvance
)
1974 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
1975 if (format
& OTF_YAdvDevice
)
1977 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
1978 adjustment
[i
].set
= 1;
1981 case 3: /* Cursive */
1982 /* Not yet supported. */
1984 case 4: /* Mark-to-Base */
1985 case 5: /* Mark-to-Ligature */
1989 goto label_adjust_anchor
;
1990 default: /* i.e. case 6 Mark-to-Mark */
1995 label_adjust_anchor
:
1997 int base_x
, base_y
, mark_x
, mark_y
;
1998 int this_from
, this_to
;
2000 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2001 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2002 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2003 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2005 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2006 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2007 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2008 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2009 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2010 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2011 adjustment
[i
].xoff
= (base_x
- mark_x
);
2012 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2013 adjustment
[i
].back
= (g
- prev
);
2014 adjustment
[i
].xadv
= 0;
2015 adjustment
[i
].advance_is_absolute
= 1;
2016 adjustment
[i
].set
= 1;
2017 this_from
= g
->from
;
2019 for (j
= 0; prev
+ j
< g
; j
++)
2021 if (this_from
> prev
[j
].from
)
2022 this_from
= prev
[j
].from
;
2023 if (this_to
< prev
[j
].to
)
2024 this_to
= prev
[j
].to
;
2026 for (; prev
<= g
; prev
++)
2028 prev
->from
= this_from
;
2033 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2035 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2041 else if (gpos_features
)
2043 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2046 features
= otf
->gpos
->FeatureList
.Feature
;
2047 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2049 if (otfg
->positioning_type
& 0xF)
2051 int feature_idx
= otfg
->positioning_type
>> 4;
2055 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2056 tag
= PACK_OTF_TAG (tag
);
2057 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2059 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2060 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2070 if (out
->allocated
< out
->used
+ len
)
2072 font
->get_metrics (font
, in
, from
, to
);
2073 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2074 sizeof (MFLTGlyph
) * len
);
2080 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2081 MFLTGlyphString
*in
, int from
, int to
)
2083 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2086 #else /* not M17N_FLT_USE_NEW_FEATURE */
2089 ftfont_drive_otf (font
, spec
, in
, from
, to
, out
, adjustment
)
2092 MFLTGlyphString
*in
;
2094 MFLTGlyphString
*out
;
2095 MFLTGlyphAdjustment
*adjustment
;
2097 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2098 FT_Face ft_face
= flt_font_ft
->ft_face
;
2099 OTF
*otf
= flt_font_ft
->otf
;
2100 int len
= to
- from
;
2103 char script
[5], *langsys
= NULL
;
2104 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2108 OTF_tag_name (spec
->script
, script
);
2111 langsys
= alloca (5);
2112 OTF_tag_name (spec
->langsys
, langsys
);
2114 for (i
= 0; i
< 2; i
++)
2118 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2120 for (j
= 0; spec
->features
[i
][j
]; j
++);
2122 p
= gsub_features
= alloca (6 * j
);
2124 p
= gpos_features
= alloca (6 * j
);
2125 for (j
= 0; spec
->features
[i
][j
]; j
++)
2127 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2128 *p
++ = '*', *p
++ = ',';
2131 OTF_tag_name (spec
->features
[i
][j
], p
);
2140 setup_otf_gstring (len
);
2141 for (i
= 0; i
< len
; i
++)
2143 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2144 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2147 OTF_drive_gdef (otf
, &otf_gstring
);
2152 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2155 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2157 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2160 int min_from
, max_to
;
2163 g
= out
->glyphs
+ out
->used
;
2164 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2165 if (g
->code
!= otfg
->glyph_id
)
2168 g
->code
= otfg
->glyph_id
;
2174 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2176 /* OTFG substitutes multiple glyphs in IN. */
2177 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2178 j
<= from
+ otfg
->f
.index
.to
; j
++)
2180 if (min_from
> in
->glyphs
[j
].from
)
2181 min_from
= in
->glyphs
[j
].from
;
2182 if (max_to
< in
->glyphs
[j
].to
)
2183 max_to
= in
->glyphs
[j
].to
;
2188 for (i
++, otfg
++; (i
< otf_gstring
.used
2189 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2192 g
= out
->glyphs
+ out
->used
;
2193 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2194 if (g
->code
!= otfg
->glyph_id
)
2197 g
->code
= otfg
->glyph_id
;
2206 if (out
->allocated
< out
->used
+ len
)
2208 for (i
= 0; i
< len
; i
++)
2209 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2214 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2215 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2217 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2221 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2222 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2223 x_scale
= ft_face
->size
->metrics
.x_scale
;
2224 y_scale
= ft_face
->size
->metrics
.y_scale
;
2226 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2227 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2231 if (! otfg
->glyph_id
)
2233 switch (otfg
->positioning_type
)
2237 case 1: /* Single */
2240 int format
= otfg
->f
.f1
.format
;
2242 if (format
& OTF_XPlacement
)
2244 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2245 if (format
& OTF_XPlaDevice
)
2247 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2248 if (format
& OTF_YPlacement
)
2250 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2251 if (format
& OTF_YPlaDevice
)
2253 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2254 if (format
& OTF_XAdvance
)
2256 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2257 if (format
& OTF_XAdvDevice
)
2259 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2260 if (format
& OTF_YAdvance
)
2262 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2263 if (format
& OTF_YAdvDevice
)
2265 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2266 adjustment
[i
].set
= 1;
2269 case 3: /* Cursive */
2270 /* Not yet supported. */
2272 case 4: /* Mark-to-Base */
2273 case 5: /* Mark-to-Ligature */
2277 goto label_adjust_anchor
;
2278 default: /* i.e. case 6 Mark-to-Mark */
2283 label_adjust_anchor
:
2285 int base_x
, base_y
, mark_x
, mark_y
;
2286 int this_from
, this_to
;
2288 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2289 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2290 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2291 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2293 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2294 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2295 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2296 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2297 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2298 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2299 adjustment
[i
].xoff
= (base_x
- mark_x
);
2300 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2301 adjustment
[i
].back
= (g
- prev
);
2302 adjustment
[i
].xadv
= 0;
2303 adjustment
[i
].advance_is_absolute
= 1;
2304 adjustment
[i
].set
= 1;
2305 this_from
= g
->from
;
2307 for (j
= 0; prev
+ j
< g
; j
++)
2309 if (this_from
> prev
[j
].from
)
2310 this_from
= prev
[j
].from
;
2311 if (this_to
< prev
[j
].to
)
2312 this_to
= prev
[j
].to
;
2314 for (; prev
<= g
; prev
++)
2316 prev
->from
= this_from
;
2321 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2323 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2332 if (out
->allocated
< out
->used
+ len
)
2334 font
->get_metrics (font
, in
, from
, to
);
2335 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2336 sizeof (MFLTGlyph
) * len
);
2341 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2343 static MFLTGlyphString gstring
;
2345 static int m17n_flt_initialized
;
2347 extern Lisp_Object QCfamily
;
2350 ftfont_shape_by_flt (lgstring
, font
, ft_face
, otf
, matrix
)
2351 Lisp_Object lgstring
;
2357 EMACS_UINT len
= LGSTRING_GLYPH_LEN (lgstring
);
2359 struct MFLTFontFT flt_font_ft
;
2361 int with_variation_selector
= 0;
2363 if (! m17n_flt_initialized
)
2366 #ifdef M17N_FLT_USE_NEW_FEATURE
2367 mflt_enable_new_feature
= 1;
2368 mflt_try_otf
= ftfont_try_otf
;
2369 #endif /* M17N_FLT_USE_NEW_FEATURE */
2370 m17n_flt_initialized
= 1;
2373 for (i
= 0; i
< len
; i
++)
2375 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2380 c
= LGLYPH_CHAR (g
);
2381 if (CHAR_VARIATION_SELECTOR_P (c
))
2382 with_variation_selector
++;
2385 if (with_variation_selector
)
2387 setup_otf_gstring (len
);
2388 for (i
= 0; i
< len
; i
++)
2390 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2392 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2393 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2394 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2396 OTF_drive_cmap (otf
, &otf_gstring
);
2397 for (i
= 0; i
< otf_gstring
.used
; i
++)
2399 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2400 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2401 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2403 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2404 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2405 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2407 if (len
> otf_gstring
.used
)
2409 len
= otf_gstring
.used
;
2410 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2414 if (gstring
.allocated
== 0)
2416 gstring
.allocated
= len
* 2;
2417 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2418 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2420 else if (gstring
.allocated
< len
* 2)
2422 gstring
.allocated
= len
* 2;
2423 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2424 sizeof (MFLTGlyph
) * gstring
.allocated
);
2426 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2427 for (i
= 0; i
< len
; i
++)
2429 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2431 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2432 if (with_variation_selector
)
2434 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2435 gstring
.glyphs
[i
].encoded
= 1;
2443 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2446 flt_font_ft
.flt_font
.family
= Mnil
;
2448 flt_font_ft
.flt_font
.family
2449 = msymbol ((char *) SDATA (Fdowncase (SYMBOL_NAME (family
))));
2451 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2452 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2453 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2454 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2455 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2456 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2457 flt_font_ft
.flt_font
.internal
= NULL
;
2458 flt_font_ft
.font
= font
;
2459 flt_font_ft
.ft_face
= ft_face
;
2460 flt_font_ft
.otf
= otf
;
2461 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2463 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2464 /* A little bit ad hoc. Perhaps, shaper must get script and
2465 language information, and select a proper flt for them
2467 flt
= mflt_get (msymbol ("combining"));
2468 for (i
= 0; i
< 3; i
++)
2470 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2473 gstring
.allocated
+= gstring
.allocated
;
2474 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2475 sizeof (MFLTGlyph
) * gstring
.allocated
);
2477 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2479 for (i
= 0; i
< gstring
.used
; i
++)
2481 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2483 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2484 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2487 for (i
= 0; i
< gstring
.used
; i
++)
2489 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2490 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2494 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2495 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2497 LGLYPH_SET_FROM (lglyph
, g
->from
);
2498 LGLYPH_SET_TO (lglyph
, g
->to
);
2499 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2500 LGLYPH_SET_CODE (lglyph
, g
->code
);
2501 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2502 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2503 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2504 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2505 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2510 vec
= Fmake_vector (make_number (3), Qnil
);
2511 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2512 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2513 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2514 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2517 return make_number (i
);
2521 ftfont_shape (lgstring
)
2522 Lisp_Object lgstring
;
2525 struct ftfont_info
*ftfont_info
;
2528 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2529 ftfont_info
= (struct ftfont_info
*) font
;
2530 otf
= ftfont_get_otf (ftfont_info
);
2532 return make_number (0);
2533 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2534 &ftfont_info
->matrix
);
2537 #endif /* HAVE_M17N_FLT */
2539 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2542 ftfont_variation_glyphs (font
, c
, variations
)
2545 unsigned variations
[256];
2547 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2548 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2552 return OTF_get_variation_glyphs (otf
, c
, variations
);
2555 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2556 #endif /* HAVE_LIBOTF */
2559 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2563 #ifdef FC_FONTFORMAT
2566 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2568 if (strcmp ((char *) str
, "TrueType") == 0)
2569 return intern ("truetype");
2570 if (strcmp ((char *) str
, "Type 1") == 0)
2571 return intern ("type1");
2572 if (strcmp ((char *) str
, "PCF") == 0)
2573 return intern ("pcf");
2574 if (strcmp ((char *) str
, "BDF") == 0)
2575 return intern ("bdf");
2577 #endif /* FC_FONTFORMAT */
2578 if (STRINGP (filename
))
2580 int len
= SBYTES (filename
);
2584 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2585 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2586 return intern ("truetype");
2587 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2588 return intern ("type1");
2589 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2590 return intern ("pcf");
2591 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2592 return intern ("bdf");
2595 return intern ("unknown");
2598 static const char *ftfont_booleans
[] = {
2611 static const char *ftfont_non_booleans
[] = {
2643 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2648 /* Set boolean values to Qt or Qnil */
2649 for (i
= 0; ftfont_booleans
[i
] != NULL
; ++i
)
2650 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
2652 Lisp_Object key
= XCAR (XCAR (it
));
2653 Lisp_Object val
= XCDR (XCAR (it
));
2654 char *keystr
= SDATA (SYMBOL_NAME (key
));
2656 if (strcmp (ftfont_booleans
[i
], keystr
) == 0)
2658 char *str
= SYMBOLP (val
) ? SDATA (SYMBOL_NAME (val
)) : NULL
;
2659 if (INTEGERP (val
)) str
= XINT (val
) != 0 ? "true" : "false";
2660 if (str
== NULL
) str
= "true";
2663 if (strcmp ("false", str
) == 0 || strcmp ("False", str
) == 0
2664 || strcmp ("FALSE", str
) == 0 || strcmp ("FcFalse", str
) == 0
2665 || strcmp ("off", str
) == 0 || strcmp ("OFF", str
) == 0
2666 || strcmp ("Off", str
) == 0)
2668 Ffont_put (font
, key
, val
);
2672 for (i
= 0; ftfont_non_booleans
[i
] != NULL
; ++i
)
2673 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
2675 Lisp_Object key
= XCAR (XCAR (it
));
2676 Lisp_Object val
= XCDR (XCAR (it
));
2677 char *keystr
= SDATA (SYMBOL_NAME (key
));
2678 if (strcmp (ftfont_non_booleans
[i
], keystr
) == 0)
2679 Ffont_put (font
, key
, val
);
2685 syms_of_ftfont (void)
2687 DEFSYM (Qfreetype
, "freetype");
2688 DEFSYM (Qmonospace
, "monospace");
2689 DEFSYM (Qsans_serif
, "sans-serif");
2690 DEFSYM (Qserif
, "serif");
2691 DEFSYM (Qmono
, "mono");
2692 DEFSYM (Qsans
, "sans");
2693 DEFSYM (Qsans__serif
, "sans serif");
2695 staticpro (&freetype_font_cache
);
2696 freetype_font_cache
= Fcons (Qt
, Qnil
);
2698 staticpro (&ftfont_generic_family_list
);
2699 ftfont_generic_family_list
2700 = Fcons (Fcons (Qmonospace
, Qt
),
2701 Fcons (Fcons (Qsans_serif
, Qt
),
2702 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2704 staticpro (&ft_face_cache
);
2705 ft_face_cache
= Qnil
;
2707 ftfont_driver
.type
= Qfreetype
;
2708 register_font_driver (&ftfont_driver
, NULL
);
2711 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
2712 (do not change this comment) */