1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 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 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
P_ ((FcPattern
*, Lisp_Object
));
85 static Lisp_Object ftfont_resolve_generic_family
P_ ((Lisp_Object
,
87 static Lisp_Object ftfont_lookup_cache
P_ ((Lisp_Object
,
88 enum ftfont_cache_for
));
90 static void ftfont_filter_properties
P_ ((Lisp_Object font
, Lisp_Object alist
));
92 Lisp_Object ftfont_font_format
P_ ((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 (p
, extra
)
195 Lisp_Object key
, cache
, entity
;
202 if (FcPatternGetString (p
, FC_FILE
, 0, (FcChar8
**) &file
) != FcResultMatch
)
204 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &index
) != FcResultMatch
)
207 key
= Fcons (make_unibyte_string ((char *) file
, strlen ((char *) file
)),
208 make_number (index
));
209 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
210 entity
= XCAR (cache
);
213 Lisp_Object val
= font_make_entity ();
216 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
217 ASET (val
, i
, AREF (entity
, i
));
220 entity
= font_make_entity ();
221 XSETCAR (cache
, entity
);
223 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
224 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
226 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
227 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
228 if (FcPatternGetString (p
, FC_FAMILY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
229 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
230 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
232 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
233 numeric
= FC_WEIGHT_MEDIUM
;
234 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
236 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
239 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
241 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
243 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
245 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
247 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
250 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
251 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
252 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
253 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
256 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
258 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
261 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
262 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
266 /* As this font is not scalable, parhaps this is a BDF or PCF
270 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
271 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
272 && FT_New_Face (ft_library
, file
, index
, &ft_face
) == 0)
276 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
277 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
278 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
279 FT_Done_Face (ft_face
);
283 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
284 font_put_extra (entity
, QCfont_entity
, key
);
289 static Lisp_Object ftfont_generic_family_list
;
292 ftfont_resolve_generic_family (family
, pattern
)
301 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
302 if (EQ (family
, Qmono
))
304 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
305 family
= Qsans_serif
;
306 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
309 if (! EQ (XCDR (slot
), Qt
))
311 pattern
= FcPatternDuplicate (pattern
);
314 FcPatternDel (pattern
, FC_FOUNDRY
);
315 FcPatternDel (pattern
, FC_FAMILY
);
316 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
317 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
319 /* This is to avoid the effect of locale. */
320 langset
= FcLangSetCreate ();
321 FcLangSetAdd (langset
, "en");
322 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
323 FcLangSetDestroy (langset
);
325 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
326 FcDefaultSubstitute (pattern
);
327 match
= FcFontMatch (NULL
, pattern
, &result
);
332 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
333 family
= intern ((char *) fam
);
337 XSETCDR (slot
, family
);
338 if (match
) FcPatternDestroy (match
);
340 if (pattern
) FcPatternDestroy (pattern
);
344 struct ftfont_cache_data
347 FcCharSet
*fc_charset
;
351 ftfont_lookup_cache (key
, cache_for
)
353 enum ftfont_cache_for cache_for
;
355 Lisp_Object cache
, val
, entity
;
356 struct ftfont_cache_data
*cache_data
;
358 if (FONT_ENTITY_P (key
))
361 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
362 xassert (CONSP (val
));
368 if (NILP (ft_face_cache
))
371 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
374 if (NILP (ft_face_cache
))
380 ft_face_cache
= Fmake_hash_table (2, args
);
382 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
383 cache_data
->ft_face
= NULL
;
384 cache_data
->fc_charset
= NULL
;
385 val
= make_save_value (NULL
, 0);
386 XSAVE_VALUE (val
)->integer
= 0;
387 XSAVE_VALUE (val
)->pointer
= cache_data
;
388 cache
= Fcons (Qnil
, val
);
389 Fputhash (key
, cache
, ft_face_cache
);
394 cache_data
= XSAVE_VALUE (val
)->pointer
;
397 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
400 if (cache_for
== FTFONT_CACHE_FOR_FACE
401 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
403 char *filename
= (char *) SDATA (XCAR (key
));
404 int index
= XINT (XCDR (key
));
406 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
409 && FT_Init_FreeType (&ft_library
) != 0)
411 if (FT_New_Face (ft_library
, filename
, index
, &cache_data
->ft_face
)
417 FcPattern
*pat
= NULL
;
418 FcFontSet
*fontset
= NULL
;
419 FcObjectSet
*objset
= NULL
;
420 FcCharSet
*charset
= NULL
;
422 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
423 FC_INDEX
, FcTypeInteger
, index
, NULL
);
426 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
429 fontset
= FcFontList (NULL
, pat
, objset
);
432 if (fontset
&& fontset
->nfont
> 0
433 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
436 cache_data
->fc_charset
= FcCharSetCopy (charset
);
438 cache_data
->fc_charset
= FcCharSetCreate ();
442 FcFontSetDestroy (fontset
);
444 FcObjectSetDestroy (objset
);
446 FcPatternDestroy (pat
);
453 ftfont_get_fc_charset (entity
)
456 Lisp_Object val
, cache
;
457 struct ftfont_cache_data
*cache_data
;
459 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
461 cache_data
= XSAVE_VALUE (val
)->pointer
;
462 return cache_data
->fc_charset
;
467 ftfont_get_otf (ftfont_info
)
468 struct ftfont_info
*ftfont_info
;
472 if (ftfont_info
->otf
)
473 return ftfont_info
->otf
;
474 if (! ftfont_info
->maybe_otf
)
476 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
477 if (! otf
|| OTF_get_table (otf
, "head") < 0)
481 ftfont_info
->maybe_otf
= 0;
484 ftfont_info
->otf
= otf
;
487 #endif /* HAVE_LIBOTF */
489 static Lisp_Object ftfont_get_cache
P_ ((FRAME_PTR
));
490 static Lisp_Object ftfont_list
P_ ((Lisp_Object
, Lisp_Object
));
491 static Lisp_Object ftfont_match
P_ ((Lisp_Object
, Lisp_Object
));
492 static Lisp_Object ftfont_list_family
P_ ((Lisp_Object
));
493 static Lisp_Object ftfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
494 static void ftfont_close
P_ ((FRAME_PTR
, struct font
*));
495 static int ftfont_has_char
P_ ((Lisp_Object
, int));
496 static unsigned ftfont_encode_char
P_ ((struct font
*, int));
497 static int ftfont_text_extents
P_ ((struct font
*, unsigned *, int,
498 struct font_metrics
*));
499 static int ftfont_get_bitmap
P_ ((struct font
*, unsigned,
500 struct font_bitmap
*, int));
501 static int ftfont_anchor_point
P_ ((struct font
*, unsigned, int,
503 static Lisp_Object ftfont_otf_capability
P_ ((struct font
*));
504 static Lisp_Object ftfont_shape
P_ ((Lisp_Object
));
506 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
507 static int ftfont_variation_glyphs
P_ ((struct font
*, int c
,
508 unsigned variations
[256]));
509 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
511 struct font_driver ftfont_driver
=
514 0, /* case insensitive */
519 NULL
, /* free_entity */
522 /* We can't draw a text without device dependent functions. */
523 NULL
, /* prepare_face */
524 NULL
, /* done_face */
528 /* We can't draw a text without device dependent functions. */
531 NULL
, /* get_bitmap */
532 NULL
, /* free_bitmap */
533 NULL
, /* get_outline */
536 ftfont_otf_capability
,
537 #else /* not HAVE_LIBOTF */
539 #endif /* not HAVE_LIBOTF */
540 NULL
, /* otf_drive */
541 NULL
, /* start_for_frame */
542 NULL
, /* end_for_frame */
543 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
545 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
547 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
550 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
551 ftfont_variation_glyphs
,
556 ftfont_filter_properties
, /* filter_properties */
559 extern Lisp_Object QCname
;
565 return freetype_font_cache
;
569 ftfont_get_charset (registry
)
570 Lisp_Object registry
;
572 char *str
= (char *) SDATA (SYMBOL_NAME (registry
));
573 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
577 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
581 else if (str
[i
] == '*')
588 regexp
= make_unibyte_string (re
, j
);
589 for (i
= 0; fc_charset_table
[i
].name
; i
++)
590 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
592 if (! fc_charset_table
[i
].name
)
594 if (! fc_charset_table
[i
].fc_charset
)
596 FcCharSet
*charset
= FcCharSetCreate ();
597 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
601 for (j
= 0; uniquifier
[j
]; j
++)
602 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
604 FcCharSetDestroy (charset
);
607 fc_charset_table
[i
].fc_charset
= charset
;
615 unsigned int script_tag
, langsys_tag
;
617 unsigned int *features
[2];
620 #define OTF_SYM_TAG(SYM, TAG) \
622 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
623 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
626 #define OTF_TAG_STR(TAG, P) \
628 (P)[0] = (char) (TAG >> 24); \
629 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
630 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
631 (P)[3] = (char) (TAG & 0xFF); \
635 #define OTF_TAG_SYM(SYM, TAG) \
639 OTF_TAG_STR (TAG, str); \
640 (SYM) = font_intern_prop (str, 4, 1); \
644 static struct OpenTypeSpec
*
645 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
647 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
653 spec
->script
= XCAR (otf_spec
);
654 if (! NILP (spec
->script
))
656 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
657 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
658 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
659 spec
->script
= XCDR (val
);
664 spec
->script_tag
= 0x44464C54; /* "DFLT" */
665 otf_spec
= XCDR (otf_spec
);
666 spec
->langsys_tag
= 0;
667 if (! NILP (otf_spec
))
669 val
= XCAR (otf_spec
);
671 OTF_SYM_TAG (val
, spec
->langsys_tag
);
672 otf_spec
= XCDR (otf_spec
);
674 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
675 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
679 val
= XCAR (otf_spec
);
683 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
684 if (! spec
->features
[i
])
686 if (i
> 0 && spec
->features
[0])
687 free (spec
->features
[0]);
691 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
693 if (NILP (XCAR (val
)))
699 OTF_SYM_TAG (XCAR (val
), tag
);
700 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
703 spec
->nfeatures
[i
] = j
;
708 static FcPattern
*ftfont_spec_pattern
P_ ((Lisp_Object
, char *,
709 struct OpenTypeSpec
**,
713 ftfont_spec_pattern (spec
, otlayout
, otspec
, langname
)
716 struct OpenTypeSpec
**otspec
;
719 Lisp_Object tmp
, extra
;
720 FcPattern
*pattern
= NULL
;
721 FcCharSet
*charset
= NULL
;
722 FcLangSet
*langset
= NULL
;
726 Lisp_Object script
= Qnil
;
727 Lisp_Object registry
;
730 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
732 /* Fontconfig doesn't support reverse-italic/obligue. */
735 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
736 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
737 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
738 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
741 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
743 || EQ (registry
, Qascii_0
)
744 || EQ (registry
, Qiso10646_1
)
745 || EQ (registry
, Qunicode_bmp
))
751 fc_charset_idx
= ftfont_get_charset (registry
);
752 if (fc_charset_idx
< 0)
754 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
755 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
756 lang
= (FcChar8
*) *langname
;
759 langset
= FcLangSetCreate ();
762 FcLangSetAdd (langset
, lang
);
767 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
768 CONSP (extra
); extra
= XCDR (extra
))
770 Lisp_Object key
, val
;
772 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
775 else if (EQ (key
, QClang
))
778 langset
= FcLangSetCreate ();
783 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
787 for (; CONSP (val
); val
= XCDR (val
))
788 if (SYMBOLP (XCAR (val
))
789 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
792 else if (EQ (key
, QCotf
))
794 *otspec
= ftfont_get_open_type_spec (val
);
797 strcat (otlayout
, "otlayout:");
798 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
799 script
= (*otspec
)->script
;
801 else if (EQ (key
, QCscript
))
803 else if (EQ (key
, QCscalable
))
804 scalable
= ! NILP (val
);
807 if (! NILP (script
) && ! charset
)
809 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
811 if (CONSP (chars
) && CONSP (CDR (chars
)))
813 charset
= FcCharSetCreate ();
816 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
817 if (CHARACTERP (XCAR (chars
))
818 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
823 pattern
= FcPatternCreate ();
826 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
828 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
830 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
832 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
835 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
838 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
841 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
844 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
850 /* We come here because of unexpected error in fontconfig API call
851 (usually insufficient memory). */
854 FcPatternDestroy (pattern
);
859 if ((*otspec
)->nfeatures
[0] > 0)
860 free ((*otspec
)->features
[0]);
861 if ((*otspec
)->nfeatures
[1] > 0)
862 free ((*otspec
)->features
[1]);
868 if (langset
) FcLangSetDestroy (langset
);
869 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
874 ftfont_list (frame
, spec
)
875 Lisp_Object frame
, spec
;
877 Lisp_Object val
= Qnil
, family
, adstyle
;
880 FcFontSet
*fontset
= NULL
;
881 FcObjectSet
*objset
= NULL
;
883 Lisp_Object chars
= Qnil
;
885 char otlayout
[15]; /* For "otlayout:XXXX" */
886 struct OpenTypeSpec
*otspec
= NULL
;
888 char *langname
= NULL
;
890 if (! fc_initialized
)
896 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
899 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
901 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
904 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
905 if (CONSP (val
) && VECTORP (XCDR (val
)))
910 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
911 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
912 family
= AREF (spec
, FONT_FAMILY_INDEX
);
915 Lisp_Object resolved
;
917 resolved
= ftfont_resolve_generic_family (family
, pattern
);
918 if (! NILP (resolved
))
920 FcPatternDel (pattern
, FC_FAMILY
);
921 if (! FcPatternAddString (pattern
, FC_FAMILY
,
922 SYMBOL_FcChar8 (resolved
)))
926 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
927 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
929 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
930 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
931 FC_STYLE
, FC_FILE
, FC_INDEX
,
934 #endif /* FC_CAPABILITY */
942 FcObjectSetAdd (objset
, FC_CHARSET
);
944 fontset
= FcFontList (NULL
, pattern
, objset
);
945 if (! fontset
|| fontset
->nfont
== 0)
948 /* Need fix because this finds any fonts. */
949 if (fontset
->nfont
== 0 && ! NILP (family
))
951 /* Try maching with configuration. For instance, the
952 configuration may specify "Nimbus Mono L" as an alias of
954 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
955 SYMBOL_FcChar8 (family
), NULL
);
958 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
961 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
964 FcPatternDel (pattern
, FC_FAMILY
);
965 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
966 FcFontSetDestroy (fontset
);
967 fontset
= FcFontList (NULL
, pattern
, objset
);
968 if (fontset
&& fontset
->nfont
> 0)
974 for (i
= 0; i
< fontset
->nfont
; i
++)
982 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
993 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
995 || ! strstr ((char *) this, otlayout
))
998 #endif /* FC_CAPABILITY */
1005 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
1008 otf
= OTF_open ((char *) file
);
1011 if (OTF_check_features (otf
, 1,
1012 otspec
->script_tag
, otspec
->langsys_tag
,
1013 otspec
->features
[0],
1014 otspec
->nfeatures
[0]) != 1
1015 || OTF_check_features (otf
, 0,
1016 otspec
->script_tag
, otspec
->langsys_tag
,
1017 otspec
->features
[1],
1018 otspec
->nfeatures
[1]) != 1)
1021 #endif /* HAVE_LIBOTF */
1022 if (VECTORP (chars
))
1026 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1029 for (j
= 0; j
< ASIZE (chars
); j
++)
1030 if (NATNUMP (AREF (chars
, j
))
1031 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1033 if (j
== ASIZE (chars
))
1036 if (! NILP (adstyle
) || langname
)
1038 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1040 if (! NILP (adstyle
)
1041 && (NILP (this_adstyle
)
1042 || xstrcasecmp (SDATA (SYMBOL_NAME (adstyle
)),
1043 SDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1046 && ! NILP (this_adstyle
)
1047 && xstrcasecmp (langname
, SDATA (SYMBOL_NAME (this_adstyle
))))
1050 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1051 AREF (spec
, FONT_EXTRA_INDEX
));
1052 if (! NILP (entity
))
1053 val
= Fcons (entity
, val
);
1055 val
= Fnreverse (val
);
1059 /* We come here because of unexpected error in fontconfig API call
1060 (usually insufficient memory). */
1064 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1065 if (objset
) FcObjectSetDestroy (objset
);
1066 if (fontset
) FcFontSetDestroy (fontset
);
1067 if (pattern
) FcPatternDestroy (pattern
);
1072 ftfont_match (frame
, spec
)
1073 Lisp_Object frame
, spec
;
1075 Lisp_Object entity
= Qnil
;
1076 FcPattern
*pattern
, *match
= NULL
;
1078 char otlayout
[15]; /* For "otlayout:XXXX" */
1079 struct OpenTypeSpec
*otspec
= NULL
;
1080 char *langname
= NULL
;
1082 if (! fc_initialized
)
1088 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1092 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1096 value
.type
= FcTypeDouble
;
1097 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1098 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1100 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1102 FcDefaultSubstitute (pattern
);
1103 match
= FcFontMatch (NULL
, pattern
, &result
);
1106 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1107 FcPatternDestroy (match
);
1108 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1109 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1110 ftfont_generic_family_list
))
1111 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1112 AREF (entity
, FONT_FAMILY_INDEX
))))
1116 FcPatternDestroy (pattern
);
1118 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1123 ftfont_list_family (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 (f
, entity
, pixel_size
)
1172 struct ftfont_info
*ftfont_info
;
1174 struct ftfont_cache_data
*cache_data
;
1178 Lisp_Object val
, filename
, index
, cache
, font_object
;
1185 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1189 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1192 filename
= XCAR (val
);
1195 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1196 ft_face
= cache_data
->ft_face
;
1197 if (XSAVE_VALUE (val
)->integer
> 0)
1199 /* FT_Face in this cache is already used by the different size. */
1200 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1202 if (FT_Activate_Size (ft_size
) != 0)
1204 FT_Done_Size (ft_size
);
1208 XSAVE_VALUE (val
)->integer
++;
1209 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1212 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1214 if (XSAVE_VALUE (val
)->integer
== 0)
1215 FT_Done_Face (ft_face
);
1219 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1220 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1221 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1223 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1224 len
= font_unparse_fcname (entity
, size
, name
, 256);
1226 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1228 ASET (font_object
, FONT_FULLNAME_INDEX
,
1229 AREF (font_object
, FONT_NAME_INDEX
));
1230 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1231 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1232 font
= XFONT_OBJECT (font_object
);
1233 ftfont_info
= (struct ftfont_info
*) font
;
1234 ftfont_info
->ft_size
= ft_face
->size
;
1235 ftfont_info
->index
= XINT (index
);
1237 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1238 ftfont_info
->otf
= NULL
;
1239 #endif /* HAVE_LIBOTF */
1240 /* This means that there's no need of transformation. */
1241 ftfont_info
->matrix
.xx
= 0;
1242 font
->pixel_size
= size
;
1243 font
->driver
= &ftfont_driver
;
1244 font
->encoding_charset
= font
->repertory_charset
= -1;
1246 upEM
= ft_face
->units_per_EM
;
1247 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1248 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1251 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1252 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1253 font
->height
= ft_face
->height
* size
/ upEM
;
1257 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1258 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1259 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1261 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1262 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1264 spacing
= FC_PROPORTIONAL
;
1265 if (spacing
!= FC_PROPORTIONAL
&& spacing
!= FC_DUAL
)
1266 font
->min_width
= font
->average_width
= font
->space_width
1267 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1268 : ft_face
->size
->metrics
.max_advance
>> 6);
1273 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1274 for (i
= 32, n
= 0; i
< 127; i
++)
1275 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1277 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1280 && (! font
->min_width
|| font
->min_width
> this_width
))
1281 font
->min_width
= this_width
;
1283 font
->space_width
= this_width
;
1284 font
->average_width
+= this_width
;
1288 font
->average_width
/= n
;
1291 font
->baseline_offset
= 0;
1292 font
->relative_compose
= 0;
1293 font
->default_ascent
= 0;
1294 font
->vertical_centering
= 0;
1297 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1298 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1302 font
->underline_position
= -1;
1303 font
->underline_thickness
= 0;
1310 ftfont_close (f
, font
)
1314 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1315 Lisp_Object val
, cache
;
1317 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1318 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1319 xassert (CONSP (cache
));
1321 (XSAVE_VALUE (val
)->integer
)--;
1322 if (XSAVE_VALUE (val
)->integer
== 0)
1324 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1326 FT_Done_Face (cache_data
->ft_face
);
1328 if (ftfont_info
->otf
)
1329 OTF_close (ftfont_info
->otf
);
1331 cache_data
->ft_face
= NULL
;
1334 FT_Done_Size (ftfont_info
->ft_size
);
1338 ftfont_has_char (font
, c
)
1342 struct charset
*cs
= NULL
;
1344 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1345 && charset_jisx0208
>= 0)
1346 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1347 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1348 && charset_ksc5601
>= 0)
1349 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1351 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1353 if (FONT_ENTITY_P (font
))
1355 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1357 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1361 struct ftfont_info
*ftfont_info
;
1363 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1364 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1370 ftfont_encode_char (font
, c
)
1374 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1375 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1376 FT_ULong charcode
= c
;
1377 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1379 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1383 ftfont_text_extents (font
, code
, nglyphs
, metrics
)
1387 struct font_metrics
*metrics
;
1389 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1390 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1394 if (ftfont_info
->ft_size
!= ft_face
->size
)
1395 FT_Activate_Size (ftfont_info
->ft_size
);
1397 bzero (metrics
, sizeof (struct font_metrics
));
1398 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1400 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1402 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1408 metrics
->lbearing
= m
->horiBearingX
>> 6;
1409 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1410 metrics
->ascent
= m
->horiBearingY
>> 6;
1411 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1417 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1418 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1419 if (metrics
->rbearing
1420 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1422 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1423 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1424 metrics
->ascent
= m
->horiBearingY
>> 6;
1425 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1426 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1428 width
+= m
->horiAdvance
>> 6;
1432 width
+= font
->space_width
;
1436 metrics
->width
= width
;
1442 ftfont_get_bitmap (font
, code
, bitmap
, bits_per_pixel
)
1445 struct font_bitmap
*bitmap
;
1448 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1449 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1450 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1452 if (ftfont_info
->ft_size
!= ft_face
->size
)
1453 FT_Activate_Size (ftfont_info
->ft_size
);
1454 if (bits_per_pixel
== 1)
1456 #ifdef FT_LOAD_TARGET_MONO
1457 load_flags
|= FT_LOAD_TARGET_MONO
;
1459 load_flags
|= FT_LOAD_MONOCHROME
;
1462 else if (bits_per_pixel
!= 8)
1463 /* We don't support such a rendering. */
1466 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1468 bitmap
->bits_per_pixel
1469 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1470 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1471 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1472 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1474 if (bitmap
->bits_per_pixel
< 0)
1475 /* We don't suport that kind of pixel mode. */
1477 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1478 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1479 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1480 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1481 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1482 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1483 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1484 bitmap
->extra
= NULL
;
1490 ftfont_anchor_point (font
, code
, index
, x
, y
)
1496 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1497 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1499 if (ftfont_info
->ft_size
!= ft_face
->size
)
1500 FT_Activate_Size (ftfont_info
->ft_size
);
1501 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1503 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1505 if (index
>= ft_face
->glyph
->outline
.n_points
)
1507 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
1508 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
1515 ftfont_otf_features (gsub_gpos
)
1516 OTF_GSUB_GPOS
*gsub_gpos
;
1518 Lisp_Object scripts
, langsyses
, features
, sym
;
1521 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1523 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1525 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1527 OTF_LangSys
*otf_langsys
;
1530 otf_langsys
= otf_script
->LangSys
+ j
;
1531 else if (otf_script
->DefaultLangSysOffset
)
1532 otf_langsys
= &otf_script
->DefaultLangSys
;
1536 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1538 l
= otf_langsys
->FeatureIndex
[k
];
1539 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1541 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1542 features
= Fcons (sym
, features
);
1545 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1548 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1551 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1552 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1560 ftfont_otf_capability (font
)
1563 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1564 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1565 Lisp_Object gsub_gpos
;
1569 gsub_gpos
= Fcons (Qnil
, Qnil
);
1570 if (OTF_get_table (otf
, "GSUB") == 0
1571 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1572 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1573 if (OTF_get_table (otf
, "GPOS") == 0
1574 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1575 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1579 #ifdef HAVE_M17N_FLT
1581 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1582 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1583 /* We can use the new feature of libotf and m17n-flt to handle the
1584 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1585 some Agian scripts. */
1586 #define M17N_FLT_USE_NEW_FEATURE
1599 ftfont_get_glyph_id (font
, gstring
, from
, to
)
1601 MFLTGlyphString
*gstring
;
1604 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1605 FT_Face ft_face
= flt_font_ft
->ft_face
;
1608 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1611 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1613 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1619 /* Operators for 26.6 fixed fractional pixel format */
1621 #define FLOOR(x) ((x) & -64)
1622 #define CEIL(x) (((x)+63) & -64)
1623 #define ROUND(x) (((x)+32) & -64)
1626 ftfont_get_metrics (font
, gstring
, from
, to
)
1628 MFLTGlyphString
*gstring
;
1631 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1632 FT_Face ft_face
= flt_font_ft
->ft_face
;
1635 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1638 if (g
->code
!= FONT_INVALID_CODE
)
1640 FT_Glyph_Metrics
*m
;
1641 int lbearing
, rbearing
, ascent
, descent
, xadv
;
1643 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1645 m
= &ft_face
->glyph
->metrics
;
1646 if (flt_font_ft
->matrix
)
1651 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1652 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1653 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1654 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1655 for (i
= 0; i
< 4; i
++)
1656 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1657 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1658 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1659 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1660 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1664 g
->lbearing
= FLOOR (m
->horiBearingX
);
1665 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1666 g
->ascent
= CEIL (m
->horiBearingY
);
1667 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1669 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1674 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1675 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1676 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1685 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1687 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1688 OTF
*otf
= flt_font_ft
->otf
;
1692 for (i
= 0; i
< 2; i
++)
1694 if (! spec
->features
[i
])
1696 for (n
= 0; spec
->features
[i
][n
]; n
++);
1697 tags
= alloca (sizeof (OTF_Tag
) * n
);
1698 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1700 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1703 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1705 tags
[n
] = spec
->features
[i
][n
];
1707 #ifdef M17N_FLT_USE_NEW_FEATURE
1708 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1709 tags
, n
- negative
) != 1)
1711 #else /* not M17N_FLT_USE_NEW_FEATURE */
1712 if (n
- negative
> 0
1713 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1714 tags
, n
- negative
) != 1)
1716 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1721 #define DEVICE_DELTA(table, size) \
1722 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1723 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1727 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1728 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1730 if (anchor
->AnchorFormat
== 2)
1732 FT_Outline
*outline
;
1733 int ap
= anchor
->f
.f1
.AnchorPoint
;
1735 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1736 outline
= &ft_face
->glyph
->outline
;
1737 if (ap
< outline
->n_points
)
1739 *x
= outline
->points
[ap
].x
<< 6;
1740 *y
= outline
->points
[ap
].y
<< 6;
1743 else if (anchor
->AnchorFormat
== 3)
1745 if (anchor
->f
.f2
.XDeviceTable
.offset
1746 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1747 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1748 if (anchor
->f
.f2
.YDeviceTable
.offset
1749 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1750 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1754 static OTF_GlyphString otf_gstring
;
1757 setup_otf_gstring (int size
)
1759 if (otf_gstring
.size
== 0)
1761 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1762 otf_gstring
.size
= size
;
1764 else if (otf_gstring
.size
< size
)
1766 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1767 sizeof (OTF_Glyph
) * size
);
1768 otf_gstring
.size
= size
;
1770 otf_gstring
.used
= size
;
1771 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1774 #ifdef M17N_FLT_USE_NEW_FEATURE
1776 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1777 #define PACK_OTF_TAG(TAG) \
1778 ((((TAG) & 0x7F000000) >> 3) \
1779 | (((TAG) & 0x7F0000) >> 2) \
1780 | (((TAG) & 0x7F00) >> 1) \
1783 /* Assuming that FONT is an OpenType font, apply OpenType features
1784 specified in SPEC on glyphs between FROM and TO of IN, and record
1785 the lastly applied feature in each glyph of IN. If OUT is not
1786 NULL, append the resulting glyphs to OUT while storing glyph
1787 position adjustment information in ADJUSTMENT. */
1790 ftfont_drive_otf (font
, spec
, in
, from
, to
, out
, adjustment
)
1793 MFLTGlyphString
*in
;
1795 MFLTGlyphString
*out
;
1796 MFLTGlyphAdjustment
*adjustment
;
1798 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1799 FT_Face ft_face
= flt_font_ft
->ft_face
;
1800 OTF
*otf
= flt_font_ft
->otf
;
1801 int len
= to
- from
;
1804 char script
[5], *langsys
= NULL
;
1805 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1806 OTF_Feature
*features
;
1810 OTF_tag_name (spec
->script
, script
);
1813 langsys
= alloca (5);
1814 OTF_tag_name (spec
->langsys
, langsys
);
1816 for (i
= 0; i
< 2; i
++)
1820 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1822 for (j
= 0; spec
->features
[i
][j
]; j
++);
1824 p
= gsub_features
= alloca (6 * j
);
1826 p
= gpos_features
= alloca (6 * j
);
1827 for (j
= 0; spec
->features
[i
][j
]; j
++)
1829 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1830 *p
++ = '*', *p
++ = ',';
1833 OTF_tag_name (spec
->features
[i
][j
], p
);
1842 setup_otf_gstring (len
);
1843 for (i
= 0; i
< len
; i
++)
1845 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1846 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1849 OTF_drive_gdef (otf
, &otf_gstring
);
1850 gidx
= out
? out
->used
: from
;
1852 if (gsub_features
&& out
)
1854 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1857 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1859 features
= otf
->gsub
->FeatureList
.Feature
;
1860 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1863 int min_from
, max_to
;
1865 int feature_idx
= otfg
->positioning_type
>> 4;
1867 g
= out
->glyphs
+ out
->used
;
1868 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1869 if (g
->code
!= otfg
->glyph_id
)
1872 g
->code
= otfg
->glyph_id
;
1878 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1880 /* OTFG substitutes multiple glyphs in IN. */
1881 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1882 j
<= from
+ otfg
->f
.index
.to
; j
++)
1884 if (min_from
> in
->glyphs
[j
].from
)
1885 min_from
= in
->glyphs
[j
].from
;
1886 if (max_to
< in
->glyphs
[j
].to
)
1887 max_to
= in
->glyphs
[j
].to
;
1894 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1895 tag
= PACK_OTF_TAG (tag
);
1896 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1898 for (i
++, otfg
++; (i
< otf_gstring
.used
1899 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1902 g
= out
->glyphs
+ out
->used
;
1903 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1904 if (g
->code
!= otfg
->glyph_id
)
1907 g
->code
= otfg
->glyph_id
;
1910 feature_idx
= otfg
->positioning_type
>> 4;
1913 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1914 tag
= PACK_OTF_TAG (tag
);
1915 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1921 else if (gsub_features
)
1923 /* Just for checking which features will be applied. */
1924 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1927 features
= otf
->gsub
->FeatureList
.Feature
;
1928 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1931 int feature_idx
= otfg
->positioning_type
>> 4;
1935 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1936 tag
= PACK_OTF_TAG (tag
);
1937 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1939 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1940 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1947 if (out
->allocated
< out
->used
+ len
)
1949 for (i
= 0; i
< len
; i
++)
1950 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1953 if (gpos_features
&& out
)
1955 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1956 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1958 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1961 features
= otf
->gpos
->FeatureList
.Feature
;
1962 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1963 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1964 x_scale
= ft_face
->size
->metrics
.x_scale
;
1965 y_scale
= ft_face
->size
->metrics
.y_scale
;
1967 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1968 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1971 int feature_idx
= otfg
->positioning_type
>> 4;
1975 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1976 tag
= PACK_OTF_TAG (tag
);
1977 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1980 if (! otfg
->glyph_id
)
1982 switch (otfg
->positioning_type
& 0xF)
1986 case 1: /* Single */
1989 int format
= otfg
->f
.f1
.format
;
1991 if (format
& OTF_XPlacement
)
1993 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1994 if (format
& OTF_XPlaDevice
)
1996 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1997 if (format
& OTF_YPlacement
)
1999 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2000 if (format
& OTF_YPlaDevice
)
2002 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2003 if (format
& OTF_XAdvance
)
2005 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2006 if (format
& OTF_XAdvDevice
)
2008 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2009 if (format
& OTF_YAdvance
)
2011 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2012 if (format
& OTF_YAdvDevice
)
2014 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2015 adjustment
[i
].set
= 1;
2018 case 3: /* Cursive */
2019 /* Not yet supported. */
2021 case 4: /* Mark-to-Base */
2022 case 5: /* Mark-to-Ligature */
2026 goto label_adjust_anchor
;
2027 default: /* i.e. case 6 Mark-to-Mark */
2032 label_adjust_anchor
:
2034 int base_x
, base_y
, mark_x
, mark_y
;
2035 int this_from
, this_to
;
2037 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2038 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2039 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2040 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2042 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2043 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2044 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2045 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2046 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2047 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2048 adjustment
[i
].xoff
= (base_x
- mark_x
);
2049 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2050 adjustment
[i
].back
= (g
- prev
);
2051 adjustment
[i
].xadv
= 0;
2052 adjustment
[i
].advance_is_absolute
= 1;
2053 adjustment
[i
].set
= 1;
2054 this_from
= g
->from
;
2056 for (j
= 0; prev
+ j
< g
; j
++)
2058 if (this_from
> prev
[j
].from
)
2059 this_from
= prev
[j
].from
;
2060 if (this_to
< prev
[j
].to
)
2061 this_to
= prev
[j
].to
;
2063 for (; prev
<= g
; prev
++)
2065 prev
->from
= this_from
;
2070 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2072 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2078 else if (gpos_features
)
2080 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2083 features
= otf
->gpos
->FeatureList
.Feature
;
2084 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2086 if (otfg
->positioning_type
& 0xF)
2088 int feature_idx
= otfg
->positioning_type
>> 4;
2092 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2093 tag
= PACK_OTF_TAG (tag
);
2094 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2096 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2097 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2107 if (out
->allocated
< out
->used
+ len
)
2109 font
->get_metrics (font
, in
, from
, to
);
2110 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2111 sizeof (MFLTGlyph
) * len
);
2117 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2118 MFLTGlyphString
*in
, int from
, int to
)
2120 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2123 #else /* not M17N_FLT_USE_NEW_FEATURE */
2126 ftfont_drive_otf (font
, spec
, in
, from
, to
, out
, adjustment
)
2129 MFLTGlyphString
*in
;
2131 MFLTGlyphString
*out
;
2132 MFLTGlyphAdjustment
*adjustment
;
2134 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2135 FT_Face ft_face
= flt_font_ft
->ft_face
;
2136 OTF
*otf
= flt_font_ft
->otf
;
2137 int len
= to
- from
;
2140 char script
[5], *langsys
= NULL
;
2141 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2145 OTF_tag_name (spec
->script
, script
);
2148 langsys
= alloca (5);
2149 OTF_tag_name (spec
->langsys
, langsys
);
2151 for (i
= 0; i
< 2; i
++)
2155 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2157 for (j
= 0; spec
->features
[i
][j
]; j
++);
2159 p
= gsub_features
= alloca (6 * j
);
2161 p
= gpos_features
= alloca (6 * j
);
2162 for (j
= 0; spec
->features
[i
][j
]; j
++)
2164 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2165 *p
++ = '*', *p
++ = ',';
2168 OTF_tag_name (spec
->features
[i
][j
], p
);
2177 setup_otf_gstring (len
);
2178 for (i
= 0; i
< len
; i
++)
2180 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2181 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2184 OTF_drive_gdef (otf
, &otf_gstring
);
2189 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2192 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2194 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2197 int min_from
, max_to
;
2200 g
= out
->glyphs
+ out
->used
;
2201 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2202 if (g
->code
!= otfg
->glyph_id
)
2205 g
->code
= otfg
->glyph_id
;
2211 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2213 /* OTFG substitutes multiple glyphs in IN. */
2214 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2215 j
<= from
+ otfg
->f
.index
.to
; j
++)
2217 if (min_from
> in
->glyphs
[j
].from
)
2218 min_from
= in
->glyphs
[j
].from
;
2219 if (max_to
< in
->glyphs
[j
].to
)
2220 max_to
= in
->glyphs
[j
].to
;
2225 for (i
++, otfg
++; (i
< otf_gstring
.used
2226 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2229 g
= out
->glyphs
+ out
->used
;
2230 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2231 if (g
->code
!= otfg
->glyph_id
)
2234 g
->code
= otfg
->glyph_id
;
2243 if (out
->allocated
< out
->used
+ len
)
2245 for (i
= 0; i
< len
; i
++)
2246 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2251 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2252 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2254 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2258 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2259 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2260 x_scale
= ft_face
->size
->metrics
.x_scale
;
2261 y_scale
= ft_face
->size
->metrics
.y_scale
;
2263 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2264 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2268 if (! otfg
->glyph_id
)
2270 switch (otfg
->positioning_type
)
2274 case 1: /* Single */
2277 int format
= otfg
->f
.f1
.format
;
2279 if (format
& OTF_XPlacement
)
2281 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2282 if (format
& OTF_XPlaDevice
)
2284 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2285 if (format
& OTF_YPlacement
)
2287 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2288 if (format
& OTF_YPlaDevice
)
2290 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2291 if (format
& OTF_XAdvance
)
2293 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2294 if (format
& OTF_XAdvDevice
)
2296 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2297 if (format
& OTF_YAdvance
)
2299 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2300 if (format
& OTF_YAdvDevice
)
2302 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2303 adjustment
[i
].set
= 1;
2306 case 3: /* Cursive */
2307 /* Not yet supported. */
2309 case 4: /* Mark-to-Base */
2310 case 5: /* Mark-to-Ligature */
2314 goto label_adjust_anchor
;
2315 default: /* i.e. case 6 Mark-to-Mark */
2320 label_adjust_anchor
:
2322 int base_x
, base_y
, mark_x
, mark_y
;
2323 int this_from
, this_to
;
2325 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2326 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2327 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2328 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2330 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2331 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2332 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2333 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2334 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2335 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2336 adjustment
[i
].xoff
= (base_x
- mark_x
);
2337 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2338 adjustment
[i
].back
= (g
- prev
);
2339 adjustment
[i
].xadv
= 0;
2340 adjustment
[i
].advance_is_absolute
= 1;
2341 adjustment
[i
].set
= 1;
2342 this_from
= g
->from
;
2344 for (j
= 0; prev
+ j
< g
; j
++)
2346 if (this_from
> prev
[j
].from
)
2347 this_from
= prev
[j
].from
;
2348 if (this_to
< prev
[j
].to
)
2349 this_to
= prev
[j
].to
;
2351 for (; prev
<= g
; prev
++)
2353 prev
->from
= this_from
;
2358 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2360 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2369 if (out
->allocated
< out
->used
+ len
)
2371 font
->get_metrics (font
, in
, from
, to
);
2372 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2373 sizeof (MFLTGlyph
) * len
);
2378 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2380 static MFLTGlyphString gstring
;
2382 static int m17n_flt_initialized
;
2384 extern Lisp_Object QCfamily
;
2387 ftfont_shape_by_flt (lgstring
, font
, ft_face
, otf
, matrix
)
2388 Lisp_Object lgstring
;
2394 EMACS_UINT len
= LGSTRING_GLYPH_LEN (lgstring
);
2396 struct MFLTFontFT flt_font_ft
;
2398 int with_variation_selector
= 0;
2400 if (! m17n_flt_initialized
)
2403 #ifdef M17N_FLT_USE_NEW_FEATURE
2404 mflt_enable_new_feature
= 1;
2405 mflt_try_otf
= ftfont_try_otf
;
2406 #endif /* M17N_FLT_USE_NEW_FEATURE */
2407 m17n_flt_initialized
= 1;
2410 for (i
= 0; i
< len
; i
++)
2412 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2417 c
= LGLYPH_CHAR (g
);
2418 if (CHAR_VARIATION_SELECTOR_P (c
))
2419 with_variation_selector
++;
2422 if (with_variation_selector
)
2424 setup_otf_gstring (len
);
2425 for (i
= 0; i
< len
; i
++)
2427 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2429 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2430 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2431 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2433 OTF_drive_cmap (otf
, &otf_gstring
);
2434 for (i
= 0; i
< otf_gstring
.used
; i
++)
2436 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2437 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2438 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2440 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2441 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2442 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2444 if (len
> otf_gstring
.used
)
2446 len
= otf_gstring
.used
;
2447 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2451 if (gstring
.allocated
== 0)
2453 gstring
.allocated
= len
* 2;
2454 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2455 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2457 else if (gstring
.allocated
< len
* 2)
2459 gstring
.allocated
= len
* 2;
2460 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2461 sizeof (MFLTGlyph
) * gstring
.allocated
);
2463 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2464 for (i
= 0; i
< len
; i
++)
2466 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2468 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2469 if (with_variation_selector
)
2471 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2472 gstring
.glyphs
[i
].encoded
= 1;
2480 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2483 flt_font_ft
.flt_font
.family
= Mnil
;
2485 flt_font_ft
.flt_font
.family
2486 = msymbol ((char *) SDATA (Fdowncase (SYMBOL_NAME (family
))));
2488 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2489 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2490 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2491 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2492 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2493 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2494 flt_font_ft
.flt_font
.internal
= NULL
;
2495 flt_font_ft
.font
= font
;
2496 flt_font_ft
.ft_face
= ft_face
;
2497 flt_font_ft
.otf
= otf
;
2498 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2500 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2501 /* A little bit ad hoc. Perhaps, shaper must get script and
2502 language information, and select a proper flt for them
2504 flt
= mflt_get (msymbol ("combining"));
2505 for (i
= 0; i
< 3; i
++)
2507 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2510 gstring
.allocated
+= gstring
.allocated
;
2511 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2512 sizeof (MFLTGlyph
) * gstring
.allocated
);
2514 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2516 for (i
= 0; i
< gstring
.used
; i
++)
2518 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2520 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2521 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2524 for (i
= 0; i
< gstring
.used
; i
++)
2526 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2527 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2531 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2532 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2534 LGLYPH_SET_FROM (lglyph
, g
->from
);
2535 LGLYPH_SET_TO (lglyph
, g
->to
);
2536 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2537 LGLYPH_SET_CODE (lglyph
, g
->code
);
2538 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2539 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2540 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2541 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2542 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2547 vec
= Fmake_vector (make_number (3), Qnil
);
2548 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2549 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2550 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2551 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2554 return make_number (i
);
2558 ftfont_shape (lgstring
)
2559 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 (font
, c
, variations
)
2582 unsigned variations
[256];
2584 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2585 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2589 return OTF_get_variation_glyphs (otf
, c
, variations
);
2592 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2593 #endif /* HAVE_LIBOTF */
2596 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2600 #ifdef FC_FONTFORMAT
2603 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2605 if (strcmp ((char *) str
, "TrueType") == 0)
2606 return intern ("truetype");
2607 if (strcmp ((char *) str
, "Type 1") == 0)
2608 return intern ("type1");
2609 if (strcmp ((char *) str
, "PCF") == 0)
2610 return intern ("pcf");
2611 if (strcmp ((char *) str
, "BDF") == 0)
2612 return intern ("bdf");
2614 #endif /* FC_FONTFORMAT */
2615 if (STRINGP (filename
))
2617 int len
= SBYTES (filename
);
2621 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2622 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2623 return intern ("truetype");
2624 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2625 return intern ("type1");
2626 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2627 return intern ("pcf");
2628 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2629 return intern ("bdf");
2632 return intern ("unknown");
2635 static const char *ftfont_booleans
[] = {
2648 static const char *ftfont_non_booleans
[] = {
2680 ftfont_filter_properties (font
, alist
)
2684 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2691 DEFSYM (Qfreetype
, "freetype");
2692 DEFSYM (Qmonospace
, "monospace");
2693 DEFSYM (Qsans_serif
, "sans-serif");
2694 DEFSYM (Qserif
, "serif");
2695 DEFSYM (Qmono
, "mono");
2696 DEFSYM (Qsans
, "sans");
2697 DEFSYM (Qsans__serif
, "sans serif");
2699 staticpro (&freetype_font_cache
);
2700 freetype_font_cache
= Fcons (Qt
, Qnil
);
2702 staticpro (&ftfont_generic_family_list
);
2703 ftfont_generic_family_list
2704 = Fcons (Fcons (Qmonospace
, Qt
),
2705 Fcons (Fcons (Qsans_serif
, Qt
),
2706 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2708 staticpro (&ft_face_cache
);
2709 ft_face_cache
= Qnil
;
2711 ftfont_driver
.type
= Qfreetype
;
2712 register_font_driver (&ftfont_driver
, NULL
);
2715 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
2716 (do not change this comment) */