1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006-2011 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
26 #include <fontconfig/fontconfig.h>
27 #include <fontconfig/fcfreetype.h>
30 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
36 #include "composite.h"
41 /* Symbolic type of this font-driver. */
42 static Lisp_Object Qfreetype
;
44 /* Fontconfig's generic families and their aliases. */
45 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
47 /* Flag to tell if FcInit is already called or not. */
48 static int fc_initialized
;
50 /* Handle to a FreeType library instance. */
51 static FT_Library ft_library
;
53 /* Cache for FreeType fonts. */
54 static Lisp_Object freetype_font_cache
;
56 /* Cache for FT_Face and FcCharSet. */
57 static Lisp_Object ft_face_cache
;
59 /* The actual structure for FreeType font that can be casted to struct
66 /* The following four members must be here in this order to be
67 compatible with struct xftfont_info (in xftfont.c). */
68 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
70 #endif /* HAVE_LIBOTF */
78 FTFONT_CACHE_FOR_FACE
,
79 FTFONT_CACHE_FOR_CHARSET
,
80 FTFONT_CACHE_FOR_ENTITY
83 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
85 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
87 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
88 enum ftfont_cache_for
);
90 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
92 Lisp_Object
ftfont_font_format (FcPattern
*, Lisp_Object
);
94 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
100 /* characters to distinguish the charset from the others */
102 /* additional constraint by language */
105 FcCharSet
*fc_charset
;
106 } fc_charset_table
[] =
107 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
108 { "iso8859-2", { 0x00A0, 0x010E }},
109 { "iso8859-3", { 0x00A0, 0x0108 }},
110 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
111 { "iso8859-5", { 0x00A0, 0x0401 }},
112 { "iso8859-6", { 0x00A0, 0x060C }},
113 { "iso8859-7", { 0x00A0, 0x0384 }},
114 { "iso8859-8", { 0x00A0, 0x05D0 }},
115 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
116 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
117 { "iso8859-11", { 0x00A0, 0x0E01 }},
118 { "iso8859-13", { 0x00A0, 0x201C }},
119 { "iso8859-14", { 0x00A0, 0x0174 }},
120 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
121 { "iso8859-16", { 0x00A0, 0x0218}},
122 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
123 { "big5-0", { 0xF6B1 }, "zh-tw" },
124 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
125 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
126 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
127 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
128 { "cns11643.1992-3", { 0x201A9 }},
129 { "cns11643.1992-4", { 0x20057 }},
130 { "cns11643.1992-5", { 0x20000 }},
131 { "cns11643.1992-6", { 0x20003 }},
132 { "cns11643.1992-7", { 0x20055 }},
133 { "gbk-0", { 0x4E06 }, "zh-cn"},
134 { "jisx0212.1990-0", { 0x4E44 }},
135 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
136 { "jisx0213.2000-2", { 0xFA49 }},
137 { "jisx0213.2004-1", { 0x20B9F }},
138 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
139 { "tis620.2529-1", { 0x0E01 }, "th"},
140 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
141 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
142 { "mulelao-1", { 0x0E81 }, "lo"},
143 { "unicode-sip", { 0x20000 }},
147 /* Dirty hack for handing ADSTYLE property.
149 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
150 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
151 "Oblique", "Italic", or any non-normal SWIDTH property names
152 (e.g. SemiCondensed) are appended. In addition, if there's no
153 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
154 "Regular" is used for FC_STYLE (see the function
155 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
157 Unfortunately this behavior is not documented, so the following
158 code may fail if FreeType changes the behavior in the future. */
161 get_adstyle_property (FcPattern
*p
)
167 if (FcPatternGetString (p
, FC_STYLE
, 0, &fcstr
) != FcResultMatch
)
169 str
= (char *) fcstr
;
170 for (end
= str
; *end
&& *end
!= ' '; end
++);
173 char *newstr
= alloca (end
- str
+ 1);
174 memcpy (newstr
, str
, end
- str
);
175 newstr
[end
- str
] = '\0';
176 end
= newstr
+ (end
- str
);
179 if (xstrcasecmp (str
, "Regular") == 0
180 || xstrcasecmp (str
, "Bold") == 0
181 || xstrcasecmp (str
, "Oblique") == 0
182 || xstrcasecmp (str
, "Italic") == 0)
184 adstyle
= font_intern_prop (str
, end
- str
, 1);
185 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
191 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
193 Lisp_Object key
, cache
, entity
;
201 if (FcPatternGetString (p
, FC_FILE
, 0, &str
) != FcResultMatch
)
203 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &idx
) != FcResultMatch
)
207 key
= Fcons (make_unibyte_string (file
, strlen (file
)), make_number (idx
));
208 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
209 entity
= XCAR (cache
);
212 Lisp_Object val
= font_make_entity ();
215 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
216 ASET (val
, i
, AREF (entity
, i
));
218 ASET (val
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
219 font_put_extra (val
, QCfont_entity
, key
);
223 entity
= font_make_entity ();
224 XSETCAR (cache
, entity
);
226 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
227 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
229 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, &str
) == FcResultMatch
)
231 char *s
= (char *) str
;
232 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
234 if (FcPatternGetString (p
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
236 char *s
= (char *) str
;
237 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (s
, strlen (s
), 1));
239 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
241 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
242 numeric
= FC_WEIGHT_MEDIUM
;
243 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
245 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
248 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
250 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
252 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
254 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
256 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
259 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
260 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
261 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
262 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
265 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
267 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
270 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
271 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
275 /* As this font is not scalable, parhaps this is a BDF or PCF
279 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
280 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
281 && FT_New_Face (ft_library
, file
, idx
, &ft_face
) == 0)
285 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
286 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
287 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
288 FT_Done_Face (ft_face
);
292 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
293 font_put_extra (entity
, QCfont_entity
, key
);
298 static Lisp_Object ftfont_generic_family_list
;
301 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
308 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
309 if (EQ (family
, Qmono
))
311 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
312 family
= Qsans_serif
;
313 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
316 if (! EQ (XCDR (slot
), Qt
))
318 pattern
= FcPatternDuplicate (pattern
);
321 FcPatternDel (pattern
, FC_FOUNDRY
);
322 FcPatternDel (pattern
, FC_FAMILY
);
323 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
324 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
326 /* This is to avoid the effect of locale. */
327 static const FcChar8 lang
[] = "en";
328 langset
= FcLangSetCreate ();
329 FcLangSetAdd (langset
, lang
);
330 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
331 FcLangSetDestroy (langset
);
333 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
334 FcDefaultSubstitute (pattern
);
335 match
= FcFontMatch (NULL
, pattern
, &result
);
340 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
341 family
= intern ((char *) fam
);
345 XSETCDR (slot
, family
);
346 if (match
) FcPatternDestroy (match
);
348 if (pattern
) FcPatternDestroy (pattern
);
352 struct ftfont_cache_data
355 FcCharSet
*fc_charset
;
359 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
361 Lisp_Object cache
, val
, entity
;
362 struct ftfont_cache_data
*cache_data
;
364 if (FONT_ENTITY_P (key
))
367 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
368 xassert (CONSP (val
));
374 if (NILP (ft_face_cache
))
377 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
380 if (NILP (ft_face_cache
))
386 ft_face_cache
= Fmake_hash_table (2, args
);
388 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
389 cache_data
->ft_face
= NULL
;
390 cache_data
->fc_charset
= NULL
;
391 val
= make_save_value (NULL
, 0);
392 XSAVE_VALUE (val
)->integer
= 0;
393 XSAVE_VALUE (val
)->pointer
= cache_data
;
394 cache
= Fcons (Qnil
, val
);
395 Fputhash (key
, cache
, ft_face_cache
);
400 cache_data
= XSAVE_VALUE (val
)->pointer
;
403 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
406 if (cache_for
== FTFONT_CACHE_FOR_FACE
407 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
409 char *filename
= SSDATA (XCAR (key
));
410 int idx
= XINT (XCDR (key
));
412 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
415 && FT_Init_FreeType (&ft_library
) != 0)
417 if (FT_New_Face (ft_library
, filename
, idx
, &cache_data
->ft_face
)
423 FcPattern
*pat
= NULL
;
424 FcFontSet
*fontset
= NULL
;
425 FcObjectSet
*objset
= NULL
;
426 FcCharSet
*charset
= NULL
;
428 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
429 FC_INDEX
, FcTypeInteger
, idx
, NULL
);
432 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
435 fontset
= FcFontList (NULL
, pat
, objset
);
438 if (fontset
&& fontset
->nfont
> 0
439 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
442 cache_data
->fc_charset
= FcCharSetCopy (charset
);
444 cache_data
->fc_charset
= FcCharSetCreate ();
448 FcFontSetDestroy (fontset
);
450 FcObjectSetDestroy (objset
);
452 FcPatternDestroy (pat
);
459 ftfont_get_fc_charset (Lisp_Object entity
)
461 Lisp_Object val
, cache
;
462 struct ftfont_cache_data
*cache_data
;
464 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
466 cache_data
= XSAVE_VALUE (val
)->pointer
;
467 return cache_data
->fc_charset
;
472 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
476 if (ftfont_info
->otf
)
477 return ftfont_info
->otf
;
478 if (! ftfont_info
->maybe_otf
)
480 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
481 if (! otf
|| OTF_get_table (otf
, "head") < 0)
485 ftfont_info
->maybe_otf
= 0;
488 ftfont_info
->otf
= otf
;
491 #endif /* HAVE_LIBOTF */
493 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
494 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
495 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
496 static Lisp_Object
ftfont_list_family (Lisp_Object
);
497 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
498 static void ftfont_close (FRAME_PTR
, struct font
*);
499 static int ftfont_has_char (Lisp_Object
, int);
500 static unsigned ftfont_encode_char (struct font
*, int);
501 static int ftfont_text_extents (struct font
*, unsigned *, int,
502 struct font_metrics
*);
503 static int ftfont_get_bitmap (struct font
*, unsigned,
504 struct font_bitmap
*, int);
505 static int ftfont_anchor_point (struct font
*, unsigned, int,
508 static Lisp_Object
ftfont_otf_capability (struct font
*);
509 # ifdef HAVE_M17N_FLT
510 static Lisp_Object
ftfont_shape (Lisp_Object
);
514 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
515 static int ftfont_variation_glyphs (struct font
*, int c
,
516 unsigned variations
[256]);
517 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
519 struct font_driver ftfont_driver
=
522 0, /* case insensitive */
527 NULL
, /* free_entity */
530 /* We can't draw a text without device dependent functions. */
531 NULL
, /* prepare_face */
532 NULL
, /* done_face */
536 /* We can't draw a text without device dependent functions. */
539 NULL
, /* get_bitmap */
540 NULL
, /* free_bitmap */
541 NULL
, /* get_outline */
544 ftfont_otf_capability
,
545 #else /* not HAVE_LIBOTF */
547 #endif /* not HAVE_LIBOTF */
548 NULL
, /* otf_drive */
549 NULL
, /* start_for_frame */
550 NULL
, /* end_for_frame */
551 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
553 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
555 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
558 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
559 ftfont_variation_glyphs
,
564 ftfont_filter_properties
, /* filter_properties */
568 ftfont_get_cache (FRAME_PTR f
)
570 return freetype_font_cache
;
574 ftfont_get_charset (Lisp_Object registry
)
576 char *str
= SSDATA (SYMBOL_NAME (registry
));
577 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
581 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
585 else if (str
[i
] == '*')
592 regexp
= make_unibyte_string (re
, j
);
593 for (i
= 0; fc_charset_table
[i
].name
; i
++)
594 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
596 if (! fc_charset_table
[i
].name
)
598 if (! fc_charset_table
[i
].fc_charset
)
600 FcCharSet
*charset
= FcCharSetCreate ();
601 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
605 for (j
= 0; uniquifier
[j
]; j
++)
606 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
608 FcCharSetDestroy (charset
);
611 fc_charset_table
[i
].fc_charset
= charset
;
619 unsigned int script_tag
, langsys_tag
;
621 unsigned int *features
[2];
624 #define OTF_SYM_TAG(SYM, TAG) \
626 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
627 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
630 #define OTF_TAG_STR(TAG, P) \
632 (P)[0] = (char) (TAG >> 24); \
633 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
634 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
635 (P)[3] = (char) (TAG & 0xFF); \
640 #define OTF_TAG_SYM(SYM, TAG) \
644 OTF_TAG_STR (TAG, str); \
645 (SYM) = font_intern_prop (str, 4, 1); \
650 static struct OpenTypeSpec
*
651 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
653 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
659 spec
->script
= XCAR (otf_spec
);
660 if (! NILP (spec
->script
))
662 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
663 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
664 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
665 spec
->script
= XCDR (val
);
670 spec
->script_tag
= 0x44464C54; /* "DFLT" */
671 otf_spec
= XCDR (otf_spec
);
672 spec
->langsys_tag
= 0;
673 if (! NILP (otf_spec
))
675 val
= XCAR (otf_spec
);
677 OTF_SYM_TAG (val
, spec
->langsys_tag
);
678 otf_spec
= XCDR (otf_spec
);
680 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
681 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
685 val
= XCAR (otf_spec
);
689 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
690 if (! spec
->features
[i
])
692 if (i
> 0 && spec
->features
[0])
693 free (spec
->features
[0]);
697 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
699 if (NILP (XCAR (val
)))
705 OTF_SYM_TAG (XCAR (val
), tag
);
706 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
709 spec
->nfeatures
[i
] = j
;
715 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, const char **langname
)
717 Lisp_Object tmp
, extra
;
718 FcPattern
*pattern
= NULL
;
719 FcCharSet
*charset
= NULL
;
720 FcLangSet
*langset
= NULL
;
724 Lisp_Object script
= Qnil
;
725 Lisp_Object registry
;
728 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
730 /* Fontconfig doesn't support reverse-italic/obligue. */
733 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
734 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
735 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
736 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
739 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
741 || EQ (registry
, Qascii_0
)
742 || EQ (registry
, Qiso10646_1
)
743 || EQ (registry
, Qunicode_bmp
))
749 fc_charset_idx
= ftfont_get_charset (registry
);
750 if (fc_charset_idx
< 0)
752 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
753 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
754 lang
= (FcChar8
*) *langname
;
757 langset
= FcLangSetCreate ();
760 FcLangSetAdd (langset
, lang
);
765 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
766 CONSP (extra
); extra
= XCDR (extra
))
768 Lisp_Object key
, val
;
770 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
776 else if (EQ (key
, QClang
))
779 langset
= FcLangSetCreate ();
784 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
788 for (; CONSP (val
); val
= XCDR (val
))
789 if (SYMBOLP (XCAR (val
))
790 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
793 else if (EQ (key
, QCotf
))
797 *otspec
= ftfont_get_open_type_spec (val
);
800 strcat (otlayout
, "otlayout:");
801 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
802 script
= (*otspec
)->script
;
805 else if (EQ (key
, QCscript
))
807 else if (EQ (key
, QCscalable
))
808 scalable
= ! NILP (val
);
811 if (! NILP (script
) && ! charset
)
813 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
815 if (CONSP (chars
) && CONSP (CDR (chars
)))
817 charset
= FcCharSetCreate ();
820 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
821 if (CHARACTERP (XCAR (chars
))
822 && ! FcCharSetAddChar (charset
, XFASTINT (XCAR (chars
))))
827 pattern
= FcPatternCreate ();
830 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
832 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
834 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
836 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
839 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
842 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
845 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
848 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
854 /* We come here because of unexpected error in fontconfig API call
855 (usually insufficient memory). */
858 FcPatternDestroy (pattern
);
863 if ((*otspec
)->nfeatures
[0] > 0)
864 free ((*otspec
)->features
[0]);
865 if ((*otspec
)->nfeatures
[1] > 0)
866 free ((*otspec
)->features
[1]);
872 if (langset
) FcLangSetDestroy (langset
);
873 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
878 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
880 Lisp_Object val
= Qnil
, family
, adstyle
;
883 FcFontSet
*fontset
= NULL
;
884 FcObjectSet
*objset
= NULL
;
886 Lisp_Object chars
= Qnil
;
887 char otlayout
[15]; /* For "otlayout:XXXX" */
888 struct OpenTypeSpec
*otspec
= NULL
;
890 const char *langname
= NULL
;
892 if (! fc_initialized
)
898 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
901 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
903 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
906 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
907 if (CONSP (val
) && VECTORP (XCDR (val
)))
912 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
913 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
914 family
= AREF (spec
, FONT_FAMILY_INDEX
);
917 Lisp_Object resolved
;
919 resolved
= ftfont_resolve_generic_family (family
, pattern
);
920 if (! NILP (resolved
))
922 FcPatternDel (pattern
, FC_FAMILY
);
923 if (! FcPatternAddString (pattern
, FC_FAMILY
,
924 SYMBOL_FcChar8 (resolved
)))
928 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
929 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
931 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
932 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
933 FC_STYLE
, FC_FILE
, FC_INDEX
,
936 #endif /* FC_CAPABILITY */
944 FcObjectSetAdd (objset
, FC_CHARSET
);
946 fontset
= FcFontList (NULL
, pattern
, objset
);
947 if (! fontset
|| fontset
->nfont
== 0)
950 /* Need fix because this finds any fonts. */
951 if (fontset
->nfont
== 0 && ! NILP (family
))
953 /* Try maching with configuration. For instance, the
954 configuration may specify "Nimbus Mono L" as an alias of
956 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
957 SYMBOL_FcChar8 (family
), NULL
);
960 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
963 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
966 FcPatternDel (pattern
, FC_FAMILY
);
967 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
968 FcFontSetDestroy (fontset
);
969 fontset
= FcFontList (NULL
, pattern
, objset
);
970 if (fontset
&& fontset
->nfont
> 0)
976 for (i
= 0; i
< fontset
->nfont
; i
++)
984 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
995 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
997 || ! strstr ((char *) this, otlayout
))
1000 #endif /* FC_CAPABILITY */
1007 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1010 otf
= OTF_open ((char *) file
);
1013 if (OTF_check_features (otf
, 1,
1014 otspec
->script_tag
, otspec
->langsys_tag
,
1015 otspec
->features
[0],
1016 otspec
->nfeatures
[0]) != 1
1017 || OTF_check_features (otf
, 0,
1018 otspec
->script_tag
, otspec
->langsys_tag
,
1019 otspec
->features
[1],
1020 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 (NATNUMP (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 (Lisp_Object frame
, 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 (Lisp_Object frame
)
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_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1169 struct ftfont_info
*ftfont_info
;
1171 struct ftfont_cache_data
*cache_data
;
1175 Lisp_Object val
, filename
, idx
, cache
, font_object
;
1182 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1186 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1189 filename
= XCAR (val
);
1192 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1193 ft_face
= cache_data
->ft_face
;
1194 if (XSAVE_VALUE (val
)->integer
> 0)
1196 /* FT_Face in this cache is already used by the different size. */
1197 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1199 if (FT_Activate_Size (ft_size
) != 0)
1201 FT_Done_Size (ft_size
);
1205 XSAVE_VALUE (val
)->integer
++;
1206 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1209 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1211 if (XSAVE_VALUE (val
)->integer
== 0)
1212 FT_Done_Face (ft_face
);
1216 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1217 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1218 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1220 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1221 len
= font_unparse_fcname (entity
, size
, name
, 256);
1223 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1225 ASET (font_object
, FONT_FULLNAME_INDEX
,
1226 AREF (font_object
, FONT_NAME_INDEX
));
1227 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1228 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1229 font
= XFONT_OBJECT (font_object
);
1230 ftfont_info
= (struct ftfont_info
*) font
;
1231 ftfont_info
->ft_size
= ft_face
->size
;
1232 ftfont_info
->index
= XINT (idx
);
1234 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1235 ftfont_info
->otf
= NULL
;
1236 #endif /* HAVE_LIBOTF */
1237 /* This means that there's no need of transformation. */
1238 ftfont_info
->matrix
.xx
= 0;
1239 font
->pixel_size
= size
;
1240 font
->driver
= &ftfont_driver
;
1241 font
->encoding_charset
= font
->repertory_charset
= -1;
1243 upEM
= ft_face
->units_per_EM
;
1244 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1245 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1248 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1249 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1250 font
->height
= ft_face
->height
* size
/ upEM
;
1254 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1255 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1256 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1258 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1259 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1261 spacing
= FC_PROPORTIONAL
;
1262 if (spacing
!= FC_PROPORTIONAL
1264 && spacing
!= FC_DUAL
1265 #endif /* FC_DUAL */
1267 font
->min_width
= font
->average_width
= font
->space_width
1268 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1269 : ft_face
->size
->metrics
.max_advance
>> 6);
1274 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1275 for (i
= 32, n
= 0; i
< 127; i
++)
1276 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1278 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1281 && (! font
->min_width
|| font
->min_width
> this_width
))
1282 font
->min_width
= this_width
;
1284 font
->space_width
= this_width
;
1285 font
->average_width
+= this_width
;
1289 font
->average_width
/= n
;
1292 font
->baseline_offset
= 0;
1293 font
->relative_compose
= 0;
1294 font
->default_ascent
= 0;
1295 font
->vertical_centering
= 0;
1298 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1299 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1303 font
->underline_position
= -1;
1304 font
->underline_thickness
= 0;
1311 ftfont_close (FRAME_PTR f
, struct font
*font
)
1313 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1314 Lisp_Object val
, cache
;
1316 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1317 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1318 xassert (CONSP (cache
));
1320 (XSAVE_VALUE (val
)->integer
)--;
1321 if (XSAVE_VALUE (val
)->integer
== 0)
1323 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1325 FT_Done_Face (cache_data
->ft_face
);
1327 if (ftfont_info
->otf
)
1328 OTF_close (ftfont_info
->otf
);
1330 cache_data
->ft_face
= NULL
;
1333 FT_Done_Size (ftfont_info
->ft_size
);
1337 ftfont_has_char (Lisp_Object font
, int c
)
1339 struct charset
*cs
= NULL
;
1341 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1342 && charset_jisx0208
>= 0)
1343 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1344 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1345 && charset_ksc5601
>= 0)
1346 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1348 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1350 if (FONT_ENTITY_P (font
))
1352 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1354 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1358 struct ftfont_info
*ftfont_info
;
1360 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1361 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1367 ftfont_encode_char (struct font
*font
, int c
)
1369 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1370 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1371 FT_ULong charcode
= c
;
1372 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1374 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1378 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1380 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1381 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1385 if (ftfont_info
->ft_size
!= ft_face
->size
)
1386 FT_Activate_Size (ftfont_info
->ft_size
);
1388 memset (metrics
, 0, sizeof (struct font_metrics
));
1389 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1391 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1393 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1399 metrics
->lbearing
= m
->horiBearingX
>> 6;
1400 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1401 metrics
->ascent
= m
->horiBearingY
>> 6;
1402 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1408 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1409 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1410 if (metrics
->rbearing
1411 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1413 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1414 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1415 metrics
->ascent
= m
->horiBearingY
>> 6;
1416 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1417 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1419 width
+= m
->horiAdvance
>> 6;
1423 width
+= font
->space_width
;
1427 metrics
->width
= width
;
1433 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1435 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1436 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1437 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1439 if (ftfont_info
->ft_size
!= ft_face
->size
)
1440 FT_Activate_Size (ftfont_info
->ft_size
);
1441 if (bits_per_pixel
== 1)
1443 #ifdef FT_LOAD_TARGET_MONO
1444 load_flags
|= FT_LOAD_TARGET_MONO
;
1446 load_flags
|= FT_LOAD_MONOCHROME
;
1449 else if (bits_per_pixel
!= 8)
1450 /* We don't support such a rendering. */
1453 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1455 bitmap
->bits_per_pixel
1456 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1457 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1458 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1459 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1461 if (bitmap
->bits_per_pixel
< 0)
1462 /* We don't suport that kind of pixel mode. */
1464 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1465 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1466 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1467 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1468 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1469 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1470 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1471 bitmap
->extra
= NULL
;
1477 ftfont_anchor_point (struct font
*font
, unsigned int code
, int idx
,
1480 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1481 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1483 if (ftfont_info
->ft_size
!= ft_face
->size
)
1484 FT_Activate_Size (ftfont_info
->ft_size
);
1485 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1487 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1489 if (idx
>= ft_face
->glyph
->outline
.n_points
)
1491 *x
= ft_face
->glyph
->outline
.points
[idx
].x
;
1492 *y
= ft_face
->glyph
->outline
.points
[idx
].y
;
1499 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1501 Lisp_Object scripts
, langsyses
, features
, sym
;
1504 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1506 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1508 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1510 OTF_LangSys
*otf_langsys
;
1513 otf_langsys
= otf_script
->LangSys
+ j
;
1514 else if (otf_script
->DefaultLangSysOffset
)
1515 otf_langsys
= &otf_script
->DefaultLangSys
;
1519 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1521 l
= otf_langsys
->FeatureIndex
[k
];
1522 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1524 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1525 features
= Fcons (sym
, features
);
1528 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1531 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1534 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1535 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1543 ftfont_otf_capability (struct font
*font
)
1545 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1546 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1547 Lisp_Object gsub_gpos
;
1551 gsub_gpos
= Fcons (Qnil
, Qnil
);
1552 if (OTF_get_table (otf
, "GSUB") == 0
1553 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1554 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1555 if (OTF_get_table (otf
, "GPOS") == 0
1556 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1557 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1561 #ifdef HAVE_M17N_FLT
1563 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1564 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1565 /* We can use the new feature of libotf and m17n-flt to handle the
1566 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1567 some Agian scripts. */
1568 #define M17N_FLT_USE_NEW_FEATURE
1581 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1584 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1585 FT_Face ft_face
= flt_font_ft
->ft_face
;
1588 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1591 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1593 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1599 /* Operators for 26.6 fixed fractional pixel format */
1601 #define FLOOR(x) ((x) & -64)
1602 #define CEIL(x) (((x)+63) & -64)
1603 #define ROUND(x) (((x)+32) & -64)
1606 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1609 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1610 FT_Face ft_face
= flt_font_ft
->ft_face
;
1613 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1616 if (g
->code
!= FONT_INVALID_CODE
)
1618 FT_Glyph_Metrics
*m
;
1620 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1622 m
= &ft_face
->glyph
->metrics
;
1623 if (flt_font_ft
->matrix
)
1628 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1629 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1630 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1631 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1632 for (i
= 0; i
< 4; i
++)
1633 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1634 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1635 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1636 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1637 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1641 g
->lbearing
= FLOOR (m
->horiBearingX
);
1642 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1643 g
->ascent
= CEIL (m
->horiBearingY
);
1644 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1646 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1651 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1652 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1653 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1662 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1664 #define FEATURE_NONE(IDX) (! spec->features[IDX])
1666 #define FEATURE_ANY(IDX) \
1667 (spec->features[IDX] \
1668 && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0)
1670 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1671 OTF
*otf
= flt_font_ft
->otf
;
1675 if (FEATURE_ANY (0) && FEATURE_ANY (1))
1676 /* Return 1 iff any of GSUB or GPOS support the script (and language). */
1678 && (OTF_check_features (otf
, 0, spec
->script
, spec
->langsys
,
1680 || OTF_check_features (otf
, 1, spec
->script
, spec
->langsys
,
1683 for (i
= 0; i
< 2; i
++)
1684 if (! FEATURE_ANY (i
))
1686 if (FEATURE_NONE (i
))
1689 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1694 if (spec
->features
[i
][0] == 0xFFFFFFFF)
1697 || OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1703 for (n
= 1; spec
->features
[i
][n
]; n
++);
1704 tags
= alloca (sizeof (OTF_Tag
) * n
);
1705 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1707 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1710 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1712 tags
[n
] = spec
->features
[i
][n
];
1714 #ifdef M17N_FLT_USE_NEW_FEATURE
1715 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1716 tags
, n
- negative
) != 1)
1718 #else /* not M17N_FLT_USE_NEW_FEATURE */
1719 if (n
- negative
> 0
1720 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1721 tags
, n
- negative
) != 1)
1723 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1730 #define DEVICE_DELTA(table, size) \
1731 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1732 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1736 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1737 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1739 if (anchor
->AnchorFormat
== 2)
1741 FT_Outline
*outline
;
1742 int ap
= anchor
->f
.f1
.AnchorPoint
;
1744 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1745 outline
= &ft_face
->glyph
->outline
;
1746 if (ap
< outline
->n_points
)
1748 *x
= outline
->points
[ap
].x
<< 6;
1749 *y
= outline
->points
[ap
].y
<< 6;
1752 else if (anchor
->AnchorFormat
== 3)
1754 if (anchor
->f
.f2
.XDeviceTable
.offset
1755 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1756 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1757 if (anchor
->f
.f2
.YDeviceTable
.offset
1758 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1759 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1763 static OTF_GlyphString otf_gstring
;
1766 setup_otf_gstring (int size
)
1768 if (otf_gstring
.size
== 0)
1770 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1771 otf_gstring
.size
= size
;
1773 else if (otf_gstring
.size
< size
)
1775 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1776 sizeof (OTF_Glyph
) * size
);
1777 otf_gstring
.size
= size
;
1779 otf_gstring
.used
= size
;
1780 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1783 #ifdef M17N_FLT_USE_NEW_FEATURE
1785 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1786 #define PACK_OTF_TAG(TAG) \
1787 ((((TAG) & 0x7F000000) >> 3) \
1788 | (((TAG) & 0x7F0000) >> 2) \
1789 | (((TAG) & 0x7F00) >> 1) \
1792 /* Assuming that FONT is an OpenType font, apply OpenType features
1793 specified in SPEC on glyphs between FROM and TO of IN, and record
1794 the lastly applied feature in each glyph of IN. If OUT is not
1795 NULL, append the resulting glyphs to OUT while storing glyph
1796 position adjustment information in ADJUSTMENT. */
1799 ftfont_drive_otf (MFLTFont
*font
,
1801 MFLTGlyphString
*in
,
1804 MFLTGlyphString
*out
,
1805 MFLTGlyphAdjustment
*adjustment
)
1807 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1808 FT_Face ft_face
= flt_font_ft
->ft_face
;
1809 OTF
*otf
= flt_font_ft
->otf
;
1810 int len
= to
- from
;
1813 char script
[5], *langsys
= NULL
;
1814 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1815 OTF_Feature
*features
;
1819 OTF_tag_name (spec
->script
, script
);
1822 langsys
= alloca (5);
1823 OTF_tag_name (spec
->langsys
, langsys
);
1825 for (i
= 0; i
< 2; i
++)
1829 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1831 for (j
= 0; spec
->features
[i
][j
]; j
++);
1833 p
= gsub_features
= alloca (6 * j
);
1835 p
= gpos_features
= alloca (6 * j
);
1836 for (j
= 0; spec
->features
[i
][j
]; j
++)
1838 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1839 *p
++ = '*', *p
++ = ',';
1842 OTF_tag_name (spec
->features
[i
][j
], p
);
1851 setup_otf_gstring (len
);
1852 for (i
= 0; i
< len
; i
++)
1854 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1855 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1858 OTF_drive_gdef (otf
, &otf_gstring
);
1859 gidx
= out
? out
->used
: from
;
1861 if (gsub_features
&& out
)
1863 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1866 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1868 features
= otf
->gsub
->FeatureList
.Feature
;
1869 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1872 int min_from
, max_to
;
1873 int feature_idx
= otfg
->positioning_type
>> 4;
1875 g
= out
->glyphs
+ out
->used
;
1876 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1877 if (g
->code
!= otfg
->glyph_id
)
1880 g
->code
= otfg
->glyph_id
;
1886 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1888 /* OTFG substitutes multiple glyphs in IN. */
1889 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1890 j
<= from
+ otfg
->f
.index
.to
; j
++)
1892 if (min_from
> in
->glyphs
[j
].from
)
1893 min_from
= in
->glyphs
[j
].from
;
1894 if (max_to
< in
->glyphs
[j
].to
)
1895 max_to
= in
->glyphs
[j
].to
;
1902 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1903 tag
= PACK_OTF_TAG (tag
);
1904 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1906 for (i
++, otfg
++; (i
< otf_gstring
.used
1907 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1910 g
= out
->glyphs
+ out
->used
;
1911 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1912 if (g
->code
!= otfg
->glyph_id
)
1915 g
->code
= otfg
->glyph_id
;
1918 feature_idx
= otfg
->positioning_type
>> 4;
1921 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1922 tag
= PACK_OTF_TAG (tag
);
1923 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1929 else if (gsub_features
)
1931 /* Just for checking which features will be applied. */
1932 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1935 features
= otf
->gsub
->FeatureList
.Feature
;
1936 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1939 int feature_idx
= otfg
->positioning_type
>> 4;
1943 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1944 tag
= PACK_OTF_TAG (tag
);
1945 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1947 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1948 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1955 if (out
->allocated
< out
->used
+ len
)
1957 for (i
= 0; i
< len
; i
++)
1958 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1961 if (gpos_features
&& out
)
1963 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1964 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1966 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1969 features
= otf
->gpos
->FeatureList
.Feature
;
1970 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1971 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1972 x_scale
= ft_face
->size
->metrics
.x_scale
;
1973 y_scale
= ft_face
->size
->metrics
.y_scale
;
1975 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1976 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1979 int feature_idx
= otfg
->positioning_type
>> 4;
1983 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1984 tag
= PACK_OTF_TAG (tag
);
1985 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1988 if (! otfg
->glyph_id
)
1990 switch (otfg
->positioning_type
& 0xF)
1994 case 1: /* Single */
1997 int format
= otfg
->f
.f1
.format
;
1999 if (format
& OTF_XPlacement
)
2001 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2002 if (format
& OTF_XPlaDevice
)
2004 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2005 if (format
& OTF_YPlacement
)
2007 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2008 if (format
& OTF_YPlaDevice
)
2010 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2011 if (format
& OTF_XAdvance
)
2013 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2014 if (format
& OTF_XAdvDevice
)
2016 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2017 if (format
& OTF_YAdvance
)
2019 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2020 if (format
& OTF_YAdvDevice
)
2022 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2023 adjustment
[i
].set
= 1;
2026 case 3: /* Cursive */
2027 /* Not yet supported. */
2029 case 4: /* Mark-to-Base */
2030 case 5: /* Mark-to-Ligature */
2034 goto label_adjust_anchor
;
2035 default: /* i.e. case 6 Mark-to-Mark */
2040 label_adjust_anchor
:
2042 int base_x
, base_y
, mark_x
, mark_y
;
2043 int this_from
, this_to
;
2045 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2046 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2047 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2048 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2050 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2051 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2052 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2053 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2054 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2055 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2056 adjustment
[i
].xoff
= (base_x
- mark_x
);
2057 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2058 adjustment
[i
].back
= (g
- prev
);
2059 adjustment
[i
].xadv
= 0;
2060 adjustment
[i
].advance_is_absolute
= 1;
2061 adjustment
[i
].set
= 1;
2062 this_from
= g
->from
;
2064 for (j
= 0; prev
+ j
< g
; j
++)
2066 if (this_from
> prev
[j
].from
)
2067 this_from
= prev
[j
].from
;
2068 if (this_to
< prev
[j
].to
)
2069 this_to
= prev
[j
].to
;
2071 for (; prev
<= g
; prev
++)
2073 prev
->from
= this_from
;
2078 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2080 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2086 else if (gpos_features
)
2088 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2091 features
= otf
->gpos
->FeatureList
.Feature
;
2092 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2094 if (otfg
->positioning_type
& 0xF)
2096 int feature_idx
= otfg
->positioning_type
>> 4;
2100 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2101 tag
= PACK_OTF_TAG (tag
);
2102 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2104 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2105 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2115 if (out
->allocated
< out
->used
+ len
)
2117 font
->get_metrics (font
, in
, from
, to
);
2118 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2119 sizeof (MFLTGlyph
) * len
);
2125 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2126 MFLTGlyphString
*in
, int from
, int to
)
2128 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2131 #else /* not M17N_FLT_USE_NEW_FEATURE */
2134 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2136 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2138 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2139 FT_Face ft_face
= flt_font_ft
->ft_face
;
2140 OTF
*otf
= flt_font_ft
->otf
;
2141 int len
= to
- from
;
2144 char script
[5], *langsys
= NULL
;
2145 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2149 OTF_tag_name (spec
->script
, script
);
2152 langsys
= alloca (5);
2153 OTF_tag_name (spec
->langsys
, langsys
);
2155 for (i
= 0; i
< 2; i
++)
2159 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2161 for (j
= 0; spec
->features
[i
][j
]; j
++);
2163 p
= gsub_features
= alloca (6 * j
);
2165 p
= gpos_features
= alloca (6 * j
);
2166 for (j
= 0; spec
->features
[i
][j
]; j
++)
2168 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2169 *p
++ = '*', *p
++ = ',';
2172 OTF_tag_name (spec
->features
[i
][j
], p
);
2181 setup_otf_gstring (len
);
2182 for (i
= 0; i
< len
; i
++)
2184 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2185 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2188 OTF_drive_gdef (otf
, &otf_gstring
);
2193 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2196 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2198 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2201 int min_from
, max_to
;
2204 g
= out
->glyphs
+ out
->used
;
2205 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2206 if (g
->code
!= otfg
->glyph_id
)
2209 g
->code
= otfg
->glyph_id
;
2215 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2217 /* OTFG substitutes multiple glyphs in IN. */
2218 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2219 j
<= from
+ otfg
->f
.index
.to
; j
++)
2221 if (min_from
> in
->glyphs
[j
].from
)
2222 min_from
= in
->glyphs
[j
].from
;
2223 if (max_to
< in
->glyphs
[j
].to
)
2224 max_to
= in
->glyphs
[j
].to
;
2229 for (i
++, otfg
++; (i
< otf_gstring
.used
2230 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2233 g
= out
->glyphs
+ out
->used
;
2234 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2235 if (g
->code
!= otfg
->glyph_id
)
2238 g
->code
= otfg
->glyph_id
;
2247 if (out
->allocated
< out
->used
+ len
)
2249 for (i
= 0; i
< len
; i
++)
2250 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2255 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2256 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2258 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2262 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2263 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2264 x_scale
= ft_face
->size
->metrics
.x_scale
;
2265 y_scale
= ft_face
->size
->metrics
.y_scale
;
2267 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2268 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2272 if (! otfg
->glyph_id
)
2274 switch (otfg
->positioning_type
)
2278 case 1: /* Single */
2281 int format
= otfg
->f
.f1
.format
;
2283 if (format
& OTF_XPlacement
)
2285 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2286 if (format
& OTF_XPlaDevice
)
2288 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2289 if (format
& OTF_YPlacement
)
2291 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2292 if (format
& OTF_YPlaDevice
)
2294 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2295 if (format
& OTF_XAdvance
)
2297 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2298 if (format
& OTF_XAdvDevice
)
2300 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2301 if (format
& OTF_YAdvance
)
2303 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2304 if (format
& OTF_YAdvDevice
)
2306 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2307 adjustment
[i
].set
= 1;
2310 case 3: /* Cursive */
2311 /* Not yet supported. */
2313 case 4: /* Mark-to-Base */
2314 case 5: /* Mark-to-Ligature */
2318 goto label_adjust_anchor
;
2319 default: /* i.e. case 6 Mark-to-Mark */
2324 label_adjust_anchor
:
2326 int base_x
, base_y
, mark_x
, mark_y
;
2327 int this_from
, this_to
;
2329 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2330 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2331 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2332 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2334 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2335 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2336 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2337 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2338 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2339 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2340 adjustment
[i
].xoff
= (base_x
- mark_x
);
2341 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2342 adjustment
[i
].back
= (g
- prev
);
2343 adjustment
[i
].xadv
= 0;
2344 adjustment
[i
].advance_is_absolute
= 1;
2345 adjustment
[i
].set
= 1;
2346 this_from
= g
->from
;
2348 for (j
= 0; prev
+ j
< g
; j
++)
2350 if (this_from
> prev
[j
].from
)
2351 this_from
= prev
[j
].from
;
2352 if (this_to
< prev
[j
].to
)
2353 this_to
= prev
[j
].to
;
2355 for (; prev
<= g
; prev
++)
2357 prev
->from
= this_from
;
2362 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2364 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2373 if (out
->allocated
< out
->used
+ len
)
2375 font
->get_metrics (font
, in
, from
, to
);
2376 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2377 sizeof (MFLTGlyph
) * len
);
2382 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2384 static MFLTGlyphString gstring
;
2386 static int m17n_flt_initialized
;
2389 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2390 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2392 EMACS_INT len
= LGSTRING_GLYPH_LEN (lgstring
);
2394 struct MFLTFontFT flt_font_ft
;
2396 int with_variation_selector
= 0;
2398 if (! m17n_flt_initialized
)
2401 #ifdef M17N_FLT_USE_NEW_FEATURE
2402 mflt_enable_new_feature
= 1;
2403 mflt_try_otf
= ftfont_try_otf
;
2404 #endif /* M17N_FLT_USE_NEW_FEATURE */
2405 m17n_flt_initialized
= 1;
2408 for (i
= 0; i
< len
; i
++)
2410 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2415 c
= LGLYPH_CHAR (g
);
2416 if (CHAR_VARIATION_SELECTOR_P (c
))
2417 with_variation_selector
++;
2421 lint_assume (len
<= TYPE_MAXIMUM (EMACS_INT
) - 2);
2423 if (with_variation_selector
)
2425 setup_otf_gstring (len
);
2426 for (i
= 0; i
< len
; i
++)
2428 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2430 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2431 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2432 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2434 OTF_drive_cmap (otf
, &otf_gstring
);
2435 for (i
= 0; i
< otf_gstring
.used
; i
++)
2437 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2438 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2439 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2441 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2442 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2443 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2445 if (len
> otf_gstring
.used
)
2447 len
= otf_gstring
.used
;
2448 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2452 if (gstring
.allocated
== 0)
2454 gstring
.allocated
= len
* 2;
2455 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2456 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2458 else if (gstring
.allocated
< len
* 2)
2460 gstring
.allocated
= len
* 2;
2461 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2462 sizeof (MFLTGlyph
) * gstring
.allocated
);
2464 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2465 for (i
= 0; i
< len
; i
++)
2467 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2469 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2470 if (with_variation_selector
)
2472 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2473 gstring
.glyphs
[i
].encoded
= 1;
2481 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2484 flt_font_ft
.flt_font
.family
= Mnil
;
2486 flt_font_ft
.flt_font
.family
2487 = msymbol (SSDATA (Fdowncase (SYMBOL_NAME (family
))));
2489 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2490 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2491 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2492 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2493 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2494 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2495 flt_font_ft
.flt_font
.internal
= NULL
;
2496 flt_font_ft
.font
= font
;
2497 flt_font_ft
.ft_face
= ft_face
;
2498 flt_font_ft
.otf
= otf
;
2499 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2501 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2502 /* A little bit ad hoc. Perhaps, shaper must get script and
2503 language information, and select a proper flt for them
2505 flt
= mflt_get (msymbol ("combining"));
2506 for (i
= 0; i
< 3; i
++)
2508 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2511 gstring
.allocated
+= gstring
.allocated
;
2512 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2513 sizeof (MFLTGlyph
) * gstring
.allocated
);
2515 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2517 for (i
= 0; i
< gstring
.used
; i
++)
2519 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2521 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2522 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2525 for (i
= 0; i
< gstring
.used
; i
++)
2527 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2528 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2532 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2533 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2535 LGLYPH_SET_FROM (lglyph
, g
->from
);
2536 LGLYPH_SET_TO (lglyph
, g
->to
);
2537 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2538 LGLYPH_SET_CODE (lglyph
, g
->code
);
2539 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2540 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2541 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2542 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2543 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2548 vec
= Fmake_vector (make_number (3), Qnil
);
2549 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2550 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2551 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2552 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2555 return make_number (i
);
2559 ftfont_shape (Lisp_Object lgstring
)
2562 struct ftfont_info
*ftfont_info
;
2565 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2566 ftfont_info
= (struct ftfont_info
*) font
;
2567 otf
= ftfont_get_otf (ftfont_info
);
2569 return make_number (0);
2570 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2571 &ftfont_info
->matrix
);
2574 #endif /* HAVE_M17N_FLT */
2576 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2579 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2581 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2582 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2586 return OTF_get_variation_glyphs (otf
, c
, variations
);
2589 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2590 #endif /* HAVE_LIBOTF */
2593 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2597 #ifdef FC_FONTFORMAT
2600 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2602 if (strcmp ((char *) str
, "TrueType") == 0)
2603 return intern ("truetype");
2604 if (strcmp ((char *) str
, "Type 1") == 0)
2605 return intern ("type1");
2606 if (strcmp ((char *) str
, "PCF") == 0)
2607 return intern ("pcf");
2608 if (strcmp ((char *) str
, "BDF") == 0)
2609 return intern ("bdf");
2611 #endif /* FC_FONTFORMAT */
2612 if (STRINGP (filename
))
2614 int len
= SBYTES (filename
);
2618 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2619 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2620 return intern ("truetype");
2621 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2622 return intern ("type1");
2623 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2624 return intern ("pcf");
2625 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2626 return intern ("bdf");
2629 return intern ("unknown");
2632 static const char *const ftfont_booleans
[] = {
2645 static const char *const ftfont_non_booleans
[] = {
2677 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2679 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2684 syms_of_ftfont (void)
2686 DEFSYM (Qfreetype
, "freetype");
2687 DEFSYM (Qmonospace
, "monospace");
2688 DEFSYM (Qsans_serif
, "sans-serif");
2689 DEFSYM (Qserif
, "serif");
2690 DEFSYM (Qmono
, "mono");
2691 DEFSYM (Qsans
, "sans");
2692 DEFSYM (Qsans__serif
, "sans serif");
2694 staticpro (&freetype_font_cache
);
2695 freetype_font_cache
= Fcons (Qt
, Qnil
);
2697 staticpro (&ftfont_generic_family_list
);
2698 ftfont_generic_family_list
2699 = Fcons (Fcons (Qmonospace
, Qt
),
2700 Fcons (Fcons (Qsans_serif
, Qt
),
2701 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2703 staticpro (&ft_face_cache
);
2704 ft_face_cache
= Qnil
;
2706 ftfont_driver
.type
= Qfreetype
;
2707 register_font_driver (&ftfont_driver
, NULL
);