1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
26 #include <fontconfig/fontconfig.h>
27 #include <fontconfig/fcfreetype.h>
30 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
36 #include "composite.h"
41 /* Symbolic type of this font-driver. */
42 Lisp_Object Qfreetype
;
44 /* Fontconfig's generic families and their aliases. */
45 static Lisp_Object Qmonospace
, Qsans_serif
, Qserif
, Qmono
, Qsans
, Qsans__serif
;
47 /* Flag to tell if FcInit is already called or not. */
48 static int fc_initialized
;
50 /* Handle to a FreeType library instance. */
51 static FT_Library ft_library
;
53 /* Cache for FreeType fonts. */
54 static Lisp_Object freetype_font_cache
;
56 /* Cache for FT_Face and FcCharSet. */
57 static Lisp_Object ft_face_cache
;
59 /* The actual structure for FreeType font that can be casted to struct
66 /* The following four members must be here in this order to be
67 compatible with struct xftfont_info (in xftfont.c). */
68 int maybe_otf
; /* Flag to tell if this may be OTF or not. */
70 #endif /* HAVE_LIBOTF */
78 FTFONT_CACHE_FOR_FACE
,
79 FTFONT_CACHE_FOR_CHARSET
,
80 FTFONT_CACHE_FOR_ENTITY
83 static Lisp_Object
ftfont_pattern_entity (FcPattern
*, Lisp_Object
);
85 static Lisp_Object
ftfont_resolve_generic_family (Lisp_Object
,
87 static Lisp_Object
ftfont_lookup_cache (Lisp_Object
,
88 enum ftfont_cache_for
);
90 static void ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
);
92 Lisp_Object
ftfont_font_format (FcPattern
*, Lisp_Object
);
94 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
100 /* characters to distinguish the charset from the others */
102 /* additional constraint by language */
105 FcCharSet
*fc_charset
;
106 } fc_charset_table
[] =
107 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
108 { "iso8859-2", { 0x00A0, 0x010E }},
109 { "iso8859-3", { 0x00A0, 0x0108 }},
110 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
111 { "iso8859-5", { 0x00A0, 0x0401 }},
112 { "iso8859-6", { 0x00A0, 0x060C }},
113 { "iso8859-7", { 0x00A0, 0x0384 }},
114 { "iso8859-8", { 0x00A0, 0x05D0 }},
115 { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
116 { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
117 { "iso8859-11", { 0x00A0, 0x0E01 }},
118 { "iso8859-13", { 0x00A0, 0x201C }},
119 { "iso8859-14", { 0x00A0, 0x0174 }},
120 { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
121 { "iso8859-16", { 0x00A0, 0x0218}},
122 { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
123 { "big5-0", { 0xF6B1 }, "zh-tw" },
124 { "jisx0208.1983-0", { 0x4E55 }, "ja"},
125 { "ksc5601.1985-0", { 0xAC00 }, "ko"},
126 { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
127 { "cns11643.1992-2", { 0x4E33, 0x7934 }},
128 { "cns11643.1992-3", { 0x201A9 }},
129 { "cns11643.1992-4", { 0x20057 }},
130 { "cns11643.1992-5", { 0x20000 }},
131 { "cns11643.1992-6", { 0x20003 }},
132 { "cns11643.1992-7", { 0x20055 }},
133 { "gbk-0", { 0x4E06 }, "zh-cn"},
134 { "jisx0212.1990-0", { 0x4E44 }},
135 { "jisx0213.2000-1", { 0xFA10 }, "ja"},
136 { "jisx0213.2000-2", { 0xFA49 }},
137 { "jisx0213.2004-1", { 0x20B9F }},
138 { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
139 { "tis620.2529-1", { 0x0E01 }, "th"},
140 { "windows-1251", { 0x0401, 0x0490 }, "ru"},
141 { "koi8-r", { 0x0401, 0x2219 }, "ru"},
142 { "mulelao-1", { 0x0E81 }, "lo"},
143 { "unicode-sip", { 0x20000 }},
147 extern Lisp_Object Qc
, Qm
, Qp
, Qd
;
149 /* Dirty hack for handing ADSTYLE property.
151 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
152 font property of PCF/BDF fonts in FC_STYLE. And, "Bold",
153 "Oblique", "Italic", or any non-normal SWIDTH property names
154 (e.g. SemiCondensed) are appended. In addition, if there's no
155 ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
156 "Regular" is used for FC_STYLE (see the function
157 pcf_interpret_style in src/pcf/pcfread.c of FreeType).
159 Unfortunately this behavior is not documented, so the following
160 code may fail if FreeType changes the behavior in the future. */
163 get_adstyle_property (FcPattern
*p
)
168 if (FcPatternGetString (p
, FC_STYLE
, 0, (FcChar8
**) &str
) != FcResultMatch
)
170 for (end
= str
; *end
&& *end
!= ' '; end
++);
173 char *p
= alloca (end
- str
+ 1);
174 memcpy (p
, str
, end
- str
);
176 end
= p
+ (end
- str
);
179 if (xstrcasecmp (str
, "Regular") == 0
180 || xstrcasecmp (str
, "Bold") == 0
181 || xstrcasecmp (str
, "Oblique") == 0
182 || xstrcasecmp (str
, "Italic") == 0)
184 adstyle
= font_intern_prop (str
, end
- str
, 1);
185 if (font_style_to_value (FONT_WIDTH_INDEX
, adstyle
, 0) >= 0)
191 ftfont_pattern_entity (FcPattern
*p
, Lisp_Object extra
)
193 Lisp_Object key
, cache
, entity
;
200 if (FcPatternGetString (p
, FC_FILE
, 0, (FcChar8
**) &file
) != FcResultMatch
)
202 if (FcPatternGetInteger (p
, FC_INDEX
, 0, &index
) != FcResultMatch
)
205 key
= Fcons (make_unibyte_string ((char *) file
, strlen ((char *) file
)),
206 make_number (index
));
207 cache
= ftfont_lookup_cache (key
, FTFONT_CACHE_FOR_ENTITY
);
208 entity
= XCAR (cache
);
211 Lisp_Object val
= font_make_entity ();
214 for (i
= 0; i
< FONT_OBJLIST_INDEX
; i
++)
215 ASET (val
, i
, AREF (entity
, i
));
218 entity
= font_make_entity ();
219 XSETCAR (cache
, entity
);
221 ASET (entity
, FONT_TYPE_INDEX
, Qfreetype
);
222 ASET (entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
224 if (FcPatternGetString (p
, FC_FOUNDRY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
225 ASET (entity
, FONT_FOUNDRY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
226 if (FcPatternGetString (p
, FC_FAMILY
, 0, (FcChar8
**) &str
) == FcResultMatch
)
227 ASET (entity
, FONT_FAMILY_INDEX
, font_intern_prop (str
, strlen (str
), 1));
228 if (FcPatternGetInteger (p
, FC_WEIGHT
, 0, &numeric
) == FcResultMatch
)
230 if (numeric
>= FC_WEIGHT_REGULAR
&& numeric
< FC_WEIGHT_MEDIUM
)
231 numeric
= FC_WEIGHT_MEDIUM
;
232 FONT_SET_STYLE (entity
, FONT_WEIGHT_INDEX
, make_number (numeric
));
234 if (FcPatternGetInteger (p
, FC_SLANT
, 0, &numeric
) == FcResultMatch
)
237 FONT_SET_STYLE (entity
, FONT_SLANT_INDEX
, make_number (numeric
));
239 if (FcPatternGetInteger (p
, FC_WIDTH
, 0, &numeric
) == FcResultMatch
)
241 FONT_SET_STYLE (entity
, FONT_WIDTH_INDEX
, make_number (numeric
));
243 if (FcPatternGetDouble (p
, FC_PIXEL_SIZE
, 0, &dbl
) == FcResultMatch
)
245 ASET (entity
, FONT_SIZE_INDEX
, make_number (dbl
));
248 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
249 if (FcPatternGetInteger (p
, FC_SPACING
, 0, &numeric
) == FcResultMatch
)
250 ASET (entity
, FONT_SPACING_INDEX
, make_number (numeric
));
251 if (FcPatternGetDouble (p
, FC_DPI
, 0, &dbl
) == FcResultMatch
)
254 ASET (entity
, FONT_DPI_INDEX
, make_number (dpi
));
256 if (FcPatternGetBool (p
, FC_SCALABLE
, 0, &b
) == FcResultMatch
259 ASET (entity
, FONT_SIZE_INDEX
, make_number (0));
260 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (0));
264 /* As this font is not scalable, parhaps this is a BDF or PCF
268 ASET (entity
, FONT_ADSTYLE_INDEX
, get_adstyle_property (p
));
269 if ((ft_library
|| FT_Init_FreeType (&ft_library
) == 0)
270 && FT_New_Face (ft_library
, file
, index
, &ft_face
) == 0)
274 if (FT_Get_BDF_Property (ft_face
, "AVERAGE_WIDTH", &rec
) == 0
275 && rec
.type
== BDF_PROPERTY_TYPE_INTEGER
)
276 ASET (entity
, FONT_AVGWIDTH_INDEX
, make_number (rec
.u
.integer
));
277 FT_Done_Face (ft_face
);
281 ASET (entity
, FONT_EXTRA_INDEX
, Fcopy_sequence (extra
));
282 font_put_extra (entity
, QCfont_entity
, key
);
287 static Lisp_Object ftfont_generic_family_list
;
290 ftfont_resolve_generic_family (Lisp_Object family
, FcPattern
*pattern
)
297 family
= Fintern (Fdowncase (SYMBOL_NAME (family
)), Qnil
);
298 if (EQ (family
, Qmono
))
300 else if (EQ (family
, Qsans
) || EQ (family
, Qsans__serif
))
301 family
= Qsans_serif
;
302 slot
= assq_no_quit (family
, ftfont_generic_family_list
);
305 if (! EQ (XCDR (slot
), Qt
))
307 pattern
= FcPatternDuplicate (pattern
);
310 FcPatternDel (pattern
, FC_FOUNDRY
);
311 FcPatternDel (pattern
, FC_FAMILY
);
312 FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (family
));
313 if (FcPatternGetLangSet (pattern
, FC_LANG
, 0, &langset
) != FcResultMatch
)
315 /* This is to avoid the effect of locale. */
316 langset
= FcLangSetCreate ();
317 FcLangSetAdd (langset
, "en");
318 FcPatternAddLangSet (pattern
, FC_LANG
, langset
);
319 FcLangSetDestroy (langset
);
321 FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
);
322 FcDefaultSubstitute (pattern
);
323 match
= FcFontMatch (NULL
, pattern
, &result
);
328 if (FcPatternGetString (match
, FC_FAMILY
, 0, &fam
) == FcResultMatch
)
329 family
= intern ((char *) fam
);
333 XSETCDR (slot
, family
);
334 if (match
) FcPatternDestroy (match
);
336 if (pattern
) FcPatternDestroy (pattern
);
340 struct ftfont_cache_data
343 FcCharSet
*fc_charset
;
347 ftfont_lookup_cache (Lisp_Object key
, enum ftfont_cache_for cache_for
)
349 Lisp_Object cache
, val
, entity
;
350 struct ftfont_cache_data
*cache_data
;
352 if (FONT_ENTITY_P (key
))
355 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
356 xassert (CONSP (val
));
362 if (NILP (ft_face_cache
))
365 cache
= Fgethash (key
, ft_face_cache
, Qnil
);
368 if (NILP (ft_face_cache
))
374 ft_face_cache
= Fmake_hash_table (2, args
);
376 cache_data
= xmalloc (sizeof (struct ftfont_cache_data
));
377 cache_data
->ft_face
= NULL
;
378 cache_data
->fc_charset
= NULL
;
379 val
= make_save_value (NULL
, 0);
380 XSAVE_VALUE (val
)->integer
= 0;
381 XSAVE_VALUE (val
)->pointer
= cache_data
;
382 cache
= Fcons (Qnil
, val
);
383 Fputhash (key
, cache
, ft_face_cache
);
388 cache_data
= XSAVE_VALUE (val
)->pointer
;
391 if (cache_for
== FTFONT_CACHE_FOR_ENTITY
)
394 if (cache_for
== FTFONT_CACHE_FOR_FACE
395 ? ! cache_data
->ft_face
: ! cache_data
->fc_charset
)
397 char *filename
= (char *) SDATA (XCAR (key
));
398 int index
= XINT (XCDR (key
));
400 if (cache_for
== FTFONT_CACHE_FOR_FACE
)
403 && FT_Init_FreeType (&ft_library
) != 0)
405 if (FT_New_Face (ft_library
, filename
, index
, &cache_data
->ft_face
)
411 FcPattern
*pat
= NULL
;
412 FcFontSet
*fontset
= NULL
;
413 FcObjectSet
*objset
= NULL
;
414 FcCharSet
*charset
= NULL
;
416 pat
= FcPatternBuild (0, FC_FILE
, FcTypeString
, (FcChar8
*) filename
,
417 FC_INDEX
, FcTypeInteger
, index
, NULL
);
420 objset
= FcObjectSetBuild (FC_CHARSET
, FC_STYLE
, NULL
);
423 fontset
= FcFontList (NULL
, pat
, objset
);
426 if (fontset
&& fontset
->nfont
> 0
427 && (FcPatternGetCharSet (fontset
->fonts
[0], FC_CHARSET
, 0,
430 cache_data
->fc_charset
= FcCharSetCopy (charset
);
432 cache_data
->fc_charset
= FcCharSetCreate ();
436 FcFontSetDestroy (fontset
);
438 FcObjectSetDestroy (objset
);
440 FcPatternDestroy (pat
);
447 ftfont_get_fc_charset (Lisp_Object entity
)
449 Lisp_Object val
, cache
;
450 struct ftfont_cache_data
*cache_data
;
452 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_CHARSET
);
454 cache_data
= XSAVE_VALUE (val
)->pointer
;
455 return cache_data
->fc_charset
;
460 ftfont_get_otf (struct ftfont_info
*ftfont_info
)
464 if (ftfont_info
->otf
)
465 return ftfont_info
->otf
;
466 if (! ftfont_info
->maybe_otf
)
468 otf
= OTF_open_ft_face (ftfont_info
->ft_size
->face
);
469 if (! otf
|| OTF_get_table (otf
, "head") < 0)
473 ftfont_info
->maybe_otf
= 0;
476 ftfont_info
->otf
= otf
;
479 #endif /* HAVE_LIBOTF */
481 static Lisp_Object
ftfont_get_cache (FRAME_PTR
);
482 static Lisp_Object
ftfont_list (Lisp_Object
, Lisp_Object
);
483 static Lisp_Object
ftfont_match (Lisp_Object
, Lisp_Object
);
484 static Lisp_Object
ftfont_list_family (Lisp_Object
);
485 static Lisp_Object
ftfont_open (FRAME_PTR
, Lisp_Object
, int);
486 static void ftfont_close (FRAME_PTR
, struct font
*);
487 static int ftfont_has_char (Lisp_Object
, int);
488 static unsigned ftfont_encode_char (struct font
*, int);
489 static int ftfont_text_extents (struct font
*, unsigned *, int,
490 struct font_metrics
*);
491 static int ftfont_get_bitmap (struct font
*, unsigned,
492 struct font_bitmap
*, int);
493 static int ftfont_anchor_point (struct font
*, unsigned, int,
495 static Lisp_Object
ftfont_otf_capability (struct font
*);
496 static Lisp_Object
ftfont_shape (Lisp_Object
);
498 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
499 static int ftfont_variation_glyphs (struct font
*, int c
,
500 unsigned variations
[256]);
501 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
503 struct font_driver ftfont_driver
=
506 0, /* case insensitive */
511 NULL
, /* free_entity */
514 /* We can't draw a text without device dependent functions. */
515 NULL
, /* prepare_face */
516 NULL
, /* done_face */
520 /* We can't draw a text without device dependent functions. */
523 NULL
, /* get_bitmap */
524 NULL
, /* free_bitmap */
525 NULL
, /* get_outline */
528 ftfont_otf_capability
,
529 #else /* not HAVE_LIBOTF */
531 #endif /* not HAVE_LIBOTF */
532 NULL
, /* otf_drive */
533 NULL
, /* start_for_frame */
534 NULL
, /* end_for_frame */
535 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
537 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
539 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
542 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
543 ftfont_variation_glyphs
,
548 ftfont_filter_properties
, /* filter_properties */
551 extern Lisp_Object QCname
;
554 ftfont_get_cache (FRAME_PTR f
)
556 return freetype_font_cache
;
560 ftfont_get_charset (Lisp_Object registry
)
562 char *str
= (char *) SDATA (SYMBOL_NAME (registry
));
563 char *re
= alloca (SBYTES (SYMBOL_NAME (registry
)) * 2 + 1);
567 for (i
= j
= 0; i
< SBYTES (SYMBOL_NAME (registry
)); i
++, j
++)
571 else if (str
[i
] == '*')
578 regexp
= make_unibyte_string (re
, j
);
579 for (i
= 0; fc_charset_table
[i
].name
; i
++)
580 if (fast_c_string_match_ignore_case (regexp
, fc_charset_table
[i
].name
) >= 0)
582 if (! fc_charset_table
[i
].name
)
584 if (! fc_charset_table
[i
].fc_charset
)
586 FcCharSet
*charset
= FcCharSetCreate ();
587 int *uniquifier
= fc_charset_table
[i
].uniquifier
;
591 for (j
= 0; uniquifier
[j
]; j
++)
592 if (! FcCharSetAddChar (charset
, uniquifier
[j
]))
594 FcCharSetDestroy (charset
);
597 fc_charset_table
[i
].fc_charset
= charset
;
605 unsigned int script_tag
, langsys_tag
;
607 unsigned int *features
[2];
610 #define OTF_SYM_TAG(SYM, TAG) \
612 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
613 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
616 #define OTF_TAG_STR(TAG, P) \
618 (P)[0] = (char) (TAG >> 24); \
619 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
620 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
621 (P)[3] = (char) (TAG & 0xFF); \
625 #define OTF_TAG_SYM(SYM, TAG) \
629 OTF_TAG_STR (TAG, str); \
630 (SYM) = font_intern_prop (str, 4, 1); \
634 static struct OpenTypeSpec
*
635 ftfont_get_open_type_spec (Lisp_Object otf_spec
)
637 struct OpenTypeSpec
*spec
= malloc (sizeof (struct OpenTypeSpec
));
643 spec
->script
= XCAR (otf_spec
);
644 if (! NILP (spec
->script
))
646 OTF_SYM_TAG (spec
->script
, spec
->script_tag
);
647 val
= assq_no_quit (spec
->script
, Votf_script_alist
);
648 if (CONSP (val
) && SYMBOLP (XCDR (val
)))
649 spec
->script
= XCDR (val
);
654 spec
->script_tag
= 0x44464C54; /* "DFLT" */
655 otf_spec
= XCDR (otf_spec
);
656 spec
->langsys_tag
= 0;
657 if (! NILP (otf_spec
))
659 val
= XCAR (otf_spec
);
661 OTF_SYM_TAG (val
, spec
->langsys_tag
);
662 otf_spec
= XCDR (otf_spec
);
664 spec
->nfeatures
[0] = spec
->nfeatures
[1] = 0;
665 for (i
= 0; i
< 2 && ! NILP (otf_spec
); i
++, otf_spec
= XCDR (otf_spec
))
669 val
= XCAR (otf_spec
);
673 spec
->features
[i
] = malloc (sizeof (int) * XINT (len
));
674 if (! spec
->features
[i
])
676 if (i
> 0 && spec
->features
[0])
677 free (spec
->features
[0]);
681 for (j
= 0, negative
= 0; CONSP (val
); val
= XCDR (val
))
683 if (NILP (XCAR (val
)))
689 OTF_SYM_TAG (XCAR (val
), tag
);
690 spec
->features
[i
][j
++] = negative
? tag
& 0x80000000 : tag
;
693 spec
->nfeatures
[i
] = j
;
698 static FcPattern
*ftfont_spec_pattern (Lisp_Object
, char *,
699 struct OpenTypeSpec
**,
703 ftfont_spec_pattern (Lisp_Object spec
, char *otlayout
, struct OpenTypeSpec
**otspec
, char **langname
)
705 Lisp_Object tmp
, extra
;
706 FcPattern
*pattern
= NULL
;
707 FcCharSet
*charset
= NULL
;
708 FcLangSet
*langset
= NULL
;
712 Lisp_Object script
= Qnil
;
713 Lisp_Object registry
;
716 if ((n
= FONT_SLANT_NUMERIC (spec
)) >= 0
718 /* Fontconfig doesn't support reverse-italic/obligue. */
721 if (INTEGERP (AREF (spec
, FONT_DPI_INDEX
)))
722 dpi
= XINT (AREF (spec
, FONT_DPI_INDEX
));
723 if (INTEGERP (AREF (spec
, FONT_AVGWIDTH_INDEX
))
724 && XINT (AREF (spec
, FONT_AVGWIDTH_INDEX
)) == 0)
727 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
729 || EQ (registry
, Qascii_0
)
730 || EQ (registry
, Qiso10646_1
)
731 || EQ (registry
, Qunicode_bmp
))
737 fc_charset_idx
= ftfont_get_charset (registry
);
738 if (fc_charset_idx
< 0)
740 charset
= fc_charset_table
[fc_charset_idx
].fc_charset
;
741 *langname
= fc_charset_table
[fc_charset_idx
].lang
;
742 lang
= (FcChar8
*) *langname
;
745 langset
= FcLangSetCreate ();
748 FcLangSetAdd (langset
, lang
);
753 for (extra
= AREF (spec
, FONT_EXTRA_INDEX
);
754 CONSP (extra
); extra
= XCDR (extra
))
756 Lisp_Object key
, val
;
758 key
= XCAR (XCAR (extra
)), val
= XCDR (XCAR (extra
));
761 else if (EQ (key
, QClang
))
764 langset
= FcLangSetCreate ();
769 if (! FcLangSetAdd (langset
, SYMBOL_FcChar8 (val
)))
773 for (; CONSP (val
); val
= XCDR (val
))
774 if (SYMBOLP (XCAR (val
))
775 && ! FcLangSetAdd (langset
, SYMBOL_FcChar8 (XCAR (val
))))
778 else if (EQ (key
, QCotf
))
780 *otspec
= ftfont_get_open_type_spec (val
);
783 strcat (otlayout
, "otlayout:");
784 OTF_TAG_STR ((*otspec
)->script_tag
, otlayout
+ 9);
785 script
= (*otspec
)->script
;
787 else if (EQ (key
, QCscript
))
789 else if (EQ (key
, QCscalable
))
790 scalable
= ! NILP (val
);
793 if (! NILP (script
) && ! charset
)
795 Lisp_Object chars
= assq_no_quit (script
, Vscript_representative_chars
);
797 if (CONSP (chars
) && CONSP (CDR (chars
)))
799 charset
= FcCharSetCreate ();
802 for (chars
= XCDR (chars
); CONSP (chars
); chars
= XCDR (chars
))
803 if (CHARACTERP (XCAR (chars
))
804 && ! FcCharSetAddChar (charset
, XUINT (XCAR (chars
))))
809 pattern
= FcPatternCreate ();
812 tmp
= AREF (spec
, FONT_FOUNDRY_INDEX
);
814 && ! FcPatternAddString (pattern
, FC_FOUNDRY
, SYMBOL_FcChar8 (tmp
)))
816 tmp
= AREF (spec
, FONT_FAMILY_INDEX
);
818 && ! FcPatternAddString (pattern
, FC_FAMILY
, SYMBOL_FcChar8 (tmp
)))
821 && ! FcPatternAddCharSet (pattern
, FC_CHARSET
, charset
))
824 && ! FcPatternAddLangSet (pattern
, FC_LANG
, langset
))
827 && ! FcPatternAddDouble (pattern
, FC_DPI
, dpi
))
830 && ! FcPatternAddBool (pattern
, FC_SCALABLE
, scalable
? FcTrue
: FcFalse
))
836 /* We come here because of unexpected error in fontconfig API call
837 (usually insufficient memory). */
840 FcPatternDestroy (pattern
);
845 if ((*otspec
)->nfeatures
[0] > 0)
846 free ((*otspec
)->features
[0]);
847 if ((*otspec
)->nfeatures
[1] > 0)
848 free ((*otspec
)->features
[1]);
854 if (langset
) FcLangSetDestroy (langset
);
855 if (charset
&& fc_charset_idx
< 0) FcCharSetDestroy (charset
);
860 ftfont_list (Lisp_Object frame
, Lisp_Object spec
)
862 Lisp_Object val
= Qnil
, family
, adstyle
;
865 FcFontSet
*fontset
= NULL
;
866 FcObjectSet
*objset
= NULL
;
868 Lisp_Object chars
= Qnil
;
870 char otlayout
[15]; /* For "otlayout:XXXX" */
871 struct OpenTypeSpec
*otspec
= NULL
;
873 char *langname
= NULL
;
875 if (! fc_initialized
)
881 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
884 if (FcPatternGetCharSet (pattern
, FC_CHARSET
, 0, &charset
) != FcResultMatch
)
886 val
= assq_no_quit (QCscript
, AREF (spec
, FONT_EXTRA_INDEX
));
889 val
= assq_no_quit (XCDR (val
), Vscript_representative_chars
);
890 if (CONSP (val
) && VECTORP (XCDR (val
)))
895 if (INTEGERP (AREF (spec
, FONT_SPACING_INDEX
)))
896 spacing
= XINT (AREF (spec
, FONT_SPACING_INDEX
));
897 family
= AREF (spec
, FONT_FAMILY_INDEX
);
900 Lisp_Object resolved
;
902 resolved
= ftfont_resolve_generic_family (family
, pattern
);
903 if (! NILP (resolved
))
905 FcPatternDel (pattern
, FC_FAMILY
);
906 if (! FcPatternAddString (pattern
, FC_FAMILY
,
907 SYMBOL_FcChar8 (resolved
)))
911 adstyle
= AREF (spec
, FONT_ADSTYLE_INDEX
);
912 if (! NILP (adstyle
) && SBYTES (SYMBOL_NAME (adstyle
)) == 0)
914 objset
= FcObjectSetBuild (FC_FOUNDRY
, FC_FAMILY
, FC_WEIGHT
, FC_SLANT
,
915 FC_WIDTH
, FC_PIXEL_SIZE
, FC_SPACING
, FC_SCALABLE
,
916 FC_STYLE
, FC_FILE
, FC_INDEX
,
919 #endif /* FC_CAPABILITY */
927 FcObjectSetAdd (objset
, FC_CHARSET
);
929 fontset
= FcFontList (NULL
, pattern
, objset
);
930 if (! fontset
|| fontset
->nfont
== 0)
933 /* Need fix because this finds any fonts. */
934 if (fontset
->nfont
== 0 && ! NILP (family
))
936 /* Try maching with configuration. For instance, the
937 configuration may specify "Nimbus Mono L" as an alias of
939 FcPattern
*pat
= FcPatternBuild (0, FC_FAMILY
, FcTypeString
,
940 SYMBOL_FcChar8 (family
), NULL
);
943 if (FcConfigSubstitute (NULL
, pat
, FcMatchPattern
) == FcTrue
)
946 FcPatternGetString (pat
, FC_FAMILY
, i
, &fam
) == FcResultMatch
;
949 FcPatternDel (pattern
, FC_FAMILY
);
950 FcPatternAddString (pattern
, FC_FAMILY
, fam
);
951 FcFontSetDestroy (fontset
);
952 fontset
= FcFontList (NULL
, pattern
, objset
);
953 if (fontset
&& fontset
->nfont
> 0)
959 for (i
= 0; i
< fontset
->nfont
; i
++)
967 if ((FcPatternGetInteger (fontset
->fonts
[i
], FC_SPACING
, 0, &this)
978 if (FcPatternGetString (fontset
->fonts
[i
], FC_CAPABILITY
, 0, &this)
980 || ! strstr ((char *) this, otlayout
))
983 #endif /* FC_CAPABILITY */
990 if (FcPatternGetString (fontset
->fonts
[i
], FC_FILE
, 0, &file
)
993 otf
= OTF_open ((char *) file
);
996 if (OTF_check_features (otf
, 1,
997 otspec
->script_tag
, otspec
->langsys_tag
,
999 otspec
->nfeatures
[0]) != 1
1000 || OTF_check_features (otf
, 0,
1001 otspec
->script_tag
, otspec
->langsys_tag
,
1002 otspec
->features
[1],
1003 otspec
->nfeatures
[1]) != 1)
1006 #endif /* HAVE_LIBOTF */
1007 if (VECTORP (chars
))
1011 if (FcPatternGetCharSet (fontset
->fonts
[i
], FC_CHARSET
, 0, &charset
)
1014 for (j
= 0; j
< ASIZE (chars
); j
++)
1015 if (NATNUMP (AREF (chars
, j
))
1016 && FcCharSetHasChar (charset
, XFASTINT (AREF (chars
, j
))))
1018 if (j
== ASIZE (chars
))
1021 if (! NILP (adstyle
) || langname
)
1023 Lisp_Object this_adstyle
= get_adstyle_property (fontset
->fonts
[i
]);
1025 if (! NILP (adstyle
)
1026 && (NILP (this_adstyle
)
1027 || xstrcasecmp (SDATA (SYMBOL_NAME (adstyle
)),
1028 SDATA (SYMBOL_NAME (this_adstyle
))) != 0))
1031 && ! NILP (this_adstyle
)
1032 && xstrcasecmp (langname
, SDATA (SYMBOL_NAME (this_adstyle
))))
1035 entity
= ftfont_pattern_entity (fontset
->fonts
[i
],
1036 AREF (spec
, FONT_EXTRA_INDEX
));
1037 if (! NILP (entity
))
1038 val
= Fcons (entity
, val
);
1040 val
= Fnreverse (val
);
1044 /* We come here because of unexpected error in fontconfig API call
1045 (usually insufficient memory). */
1049 FONT_ADD_LOG ("ftfont-list", spec
, val
);
1050 if (objset
) FcObjectSetDestroy (objset
);
1051 if (fontset
) FcFontSetDestroy (fontset
);
1052 if (pattern
) FcPatternDestroy (pattern
);
1057 ftfont_match (Lisp_Object frame
, Lisp_Object spec
)
1059 Lisp_Object entity
= Qnil
;
1060 FcPattern
*pattern
, *match
= NULL
;
1062 char otlayout
[15]; /* For "otlayout:XXXX" */
1063 struct OpenTypeSpec
*otspec
= NULL
;
1064 char *langname
= NULL
;
1066 if (! fc_initialized
)
1072 pattern
= ftfont_spec_pattern (spec
, otlayout
, &otspec
, &langname
);
1076 if (INTEGERP (AREF (spec
, FONT_SIZE_INDEX
)))
1080 value
.type
= FcTypeDouble
;
1081 value
.u
.d
= XINT (AREF (spec
, FONT_SIZE_INDEX
));
1082 FcPatternAdd (pattern
, FC_PIXEL_SIZE
, value
, FcFalse
);
1084 if (FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
) == FcTrue
)
1086 FcDefaultSubstitute (pattern
);
1087 match
= FcFontMatch (NULL
, pattern
, &result
);
1090 entity
= ftfont_pattern_entity (match
, AREF (spec
, FONT_EXTRA_INDEX
));
1091 FcPatternDestroy (match
);
1092 if (! NILP (AREF (spec
, FONT_FAMILY_INDEX
))
1093 && NILP (assq_no_quit (AREF (spec
, FONT_FAMILY_INDEX
),
1094 ftfont_generic_family_list
))
1095 && NILP (Fstring_equal (AREF (spec
, FONT_FAMILY_INDEX
),
1096 AREF (entity
, FONT_FAMILY_INDEX
))))
1100 FcPatternDestroy (pattern
);
1102 FONT_ADD_LOG ("ftfont-match", spec
, entity
);
1107 ftfont_list_family (Lisp_Object frame
)
1109 Lisp_Object list
= Qnil
;
1110 FcPattern
*pattern
= NULL
;
1111 FcFontSet
*fontset
= NULL
;
1112 FcObjectSet
*objset
= NULL
;
1115 if (! fc_initialized
)
1121 pattern
= FcPatternCreate ();
1124 objset
= FcObjectSetBuild (FC_FAMILY
, NULL
);
1127 fontset
= FcFontList (NULL
, pattern
, objset
);
1131 for (i
= 0; i
< fontset
->nfont
; i
++)
1133 FcPattern
*pat
= fontset
->fonts
[i
];
1136 if (FcPatternGetString (pat
, FC_FAMILY
, 0, &str
) == FcResultMatch
)
1137 list
= Fcons (intern ((char *) str
), list
);
1141 if (objset
) FcObjectSetDestroy (objset
);
1142 if (fontset
) FcFontSetDestroy (fontset
);
1143 if (pattern
) FcPatternDestroy (pattern
);
1150 ftfont_open (FRAME_PTR f
, Lisp_Object entity
, int pixel_size
)
1152 struct ftfont_info
*ftfont_info
;
1154 struct ftfont_cache_data
*cache_data
;
1158 Lisp_Object val
, filename
, index
, cache
, font_object
;
1165 val
= assq_no_quit (QCfont_entity
, AREF (entity
, FONT_EXTRA_INDEX
));
1169 cache
= ftfont_lookup_cache (entity
, FTFONT_CACHE_FOR_FACE
);
1172 filename
= XCAR (val
);
1175 cache_data
= XSAVE_VALUE (XCDR (cache
))->pointer
;
1176 ft_face
= cache_data
->ft_face
;
1177 if (XSAVE_VALUE (val
)->integer
> 0)
1179 /* FT_Face in this cache is already used by the different size. */
1180 if (FT_New_Size (ft_face
, &ft_size
) != 0)
1182 if (FT_Activate_Size (ft_size
) != 0)
1184 FT_Done_Size (ft_size
);
1188 XSAVE_VALUE (val
)->integer
++;
1189 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
1192 if (FT_Set_Pixel_Sizes (ft_face
, size
, size
) != 0)
1194 if (XSAVE_VALUE (val
)->integer
== 0)
1195 FT_Done_Face (ft_face
);
1199 font_object
= font_make_object (VECSIZE (struct ftfont_info
), entity
, size
);
1200 ASET (font_object
, FONT_TYPE_INDEX
, Qfreetype
);
1201 len
= font_unparse_xlfd (entity
, size
, name
, 256);
1203 ASET (font_object
, FONT_NAME_INDEX
, make_string (name
, len
));
1204 len
= font_unparse_fcname (entity
, size
, name
, 256);
1206 ASET (font_object
, FONT_FULLNAME_INDEX
, make_string (name
, len
));
1208 ASET (font_object
, FONT_FULLNAME_INDEX
,
1209 AREF (font_object
, FONT_NAME_INDEX
));
1210 ASET (font_object
, FONT_FILE_INDEX
, filename
);
1211 ASET (font_object
, FONT_FORMAT_INDEX
, ftfont_font_format (NULL
, filename
));
1212 font
= XFONT_OBJECT (font_object
);
1213 ftfont_info
= (struct ftfont_info
*) font
;
1214 ftfont_info
->ft_size
= ft_face
->size
;
1215 ftfont_info
->index
= XINT (index
);
1217 ftfont_info
->maybe_otf
= ft_face
->face_flags
& FT_FACE_FLAG_SFNT
;
1218 ftfont_info
->otf
= NULL
;
1219 #endif /* HAVE_LIBOTF */
1220 /* This means that there's no need of transformation. */
1221 ftfont_info
->matrix
.xx
= 0;
1222 font
->pixel_size
= size
;
1223 font
->driver
= &ftfont_driver
;
1224 font
->encoding_charset
= font
->repertory_charset
= -1;
1226 upEM
= ft_face
->units_per_EM
;
1227 scalable
= (INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
1228 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0);
1231 font
->ascent
= ft_face
->ascender
* size
/ upEM
;
1232 font
->descent
= - ft_face
->descender
* size
/ upEM
;
1233 font
->height
= ft_face
->height
* size
/ upEM
;
1237 font
->ascent
= ft_face
->size
->metrics
.ascender
>> 6;
1238 font
->descent
= - ft_face
->size
->metrics
.descender
>> 6;
1239 font
->height
= ft_face
->size
->metrics
.height
>> 6;
1241 if (INTEGERP (AREF (entity
, FONT_SPACING_INDEX
)))
1242 spacing
= XINT (AREF (entity
, FONT_SPACING_INDEX
));
1244 spacing
= FC_PROPORTIONAL
;
1245 if (spacing
!= FC_PROPORTIONAL
&& spacing
!= FC_DUAL
)
1246 font
->min_width
= font
->average_width
= font
->space_width
1247 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1248 : ft_face
->size
->metrics
.max_advance
>> 6);
1253 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1254 for (i
= 32, n
= 0; i
< 127; i
++)
1255 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1257 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1260 && (! font
->min_width
|| font
->min_width
> this_width
))
1261 font
->min_width
= this_width
;
1263 font
->space_width
= this_width
;
1264 font
->average_width
+= this_width
;
1268 font
->average_width
/= n
;
1271 font
->baseline_offset
= 0;
1272 font
->relative_compose
= 0;
1273 font
->default_ascent
= 0;
1274 font
->vertical_centering
= 0;
1277 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1278 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1282 font
->underline_position
= -1;
1283 font
->underline_thickness
= 0;
1290 ftfont_close (FRAME_PTR f
, struct font
*font
)
1292 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1293 Lisp_Object val
, cache
;
1295 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1296 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1297 xassert (CONSP (cache
));
1299 (XSAVE_VALUE (val
)->integer
)--;
1300 if (XSAVE_VALUE (val
)->integer
== 0)
1302 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1304 FT_Done_Face (cache_data
->ft_face
);
1306 if (ftfont_info
->otf
)
1307 OTF_close (ftfont_info
->otf
);
1309 cache_data
->ft_face
= NULL
;
1312 FT_Done_Size (ftfont_info
->ft_size
);
1316 ftfont_has_char (Lisp_Object font
, int c
)
1318 struct charset
*cs
= NULL
;
1320 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1321 && charset_jisx0208
>= 0)
1322 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1323 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1324 && charset_ksc5601
>= 0)
1325 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1327 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1329 if (FONT_ENTITY_P (font
))
1331 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1333 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1337 struct ftfont_info
*ftfont_info
;
1339 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1340 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1346 ftfont_encode_char (struct font
*font
, int c
)
1348 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1349 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1350 FT_ULong charcode
= c
;
1351 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1353 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1357 ftfont_text_extents (struct font
*font
, unsigned int *code
, int nglyphs
, struct font_metrics
*metrics
)
1359 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1360 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1364 if (ftfont_info
->ft_size
!= ft_face
->size
)
1365 FT_Activate_Size (ftfont_info
->ft_size
);
1367 memset (metrics
, 0, sizeof (struct font_metrics
));
1368 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1370 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1372 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1378 metrics
->lbearing
= m
->horiBearingX
>> 6;
1379 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1380 metrics
->ascent
= m
->horiBearingY
>> 6;
1381 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1387 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1388 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1389 if (metrics
->rbearing
1390 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1392 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1393 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1394 metrics
->ascent
= m
->horiBearingY
>> 6;
1395 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1396 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1398 width
+= m
->horiAdvance
>> 6;
1402 width
+= font
->space_width
;
1406 metrics
->width
= width
;
1412 ftfont_get_bitmap (struct font
*font
, unsigned int code
, struct font_bitmap
*bitmap
, int bits_per_pixel
)
1414 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1415 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1416 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1418 if (ftfont_info
->ft_size
!= ft_face
->size
)
1419 FT_Activate_Size (ftfont_info
->ft_size
);
1420 if (bits_per_pixel
== 1)
1422 #ifdef FT_LOAD_TARGET_MONO
1423 load_flags
|= FT_LOAD_TARGET_MONO
;
1425 load_flags
|= FT_LOAD_MONOCHROME
;
1428 else if (bits_per_pixel
!= 8)
1429 /* We don't support such a rendering. */
1432 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1434 bitmap
->bits_per_pixel
1435 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1436 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1437 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1438 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1440 if (bitmap
->bits_per_pixel
< 0)
1441 /* We don't suport that kind of pixel mode. */
1443 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1444 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1445 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1446 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1447 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1448 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1449 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1450 bitmap
->extra
= NULL
;
1456 ftfont_anchor_point (struct font
*font
, unsigned int code
, int index
, int *x
, int *y
)
1458 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1459 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1461 if (ftfont_info
->ft_size
!= ft_face
->size
)
1462 FT_Activate_Size (ftfont_info
->ft_size
);
1463 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1465 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1467 if (index
>= ft_face
->glyph
->outline
.n_points
)
1469 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
1470 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
1477 ftfont_otf_features (OTF_GSUB_GPOS
*gsub_gpos
)
1479 Lisp_Object scripts
, langsyses
, features
, sym
;
1482 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1484 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1486 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1488 OTF_LangSys
*otf_langsys
;
1491 otf_langsys
= otf_script
->LangSys
+ j
;
1492 else if (otf_script
->DefaultLangSysOffset
)
1493 otf_langsys
= &otf_script
->DefaultLangSys
;
1497 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1499 l
= otf_langsys
->FeatureIndex
[k
];
1500 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1502 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1503 features
= Fcons (sym
, features
);
1506 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1509 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1512 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1513 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1521 ftfont_otf_capability (struct font
*font
)
1523 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1524 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1525 Lisp_Object gsub_gpos
;
1529 gsub_gpos
= Fcons (Qnil
, Qnil
);
1530 if (OTF_get_table (otf
, "GSUB") == 0
1531 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1532 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1533 if (OTF_get_table (otf
, "GPOS") == 0
1534 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1535 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1539 #ifdef HAVE_M17N_FLT
1541 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1542 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1543 /* We can use the new feature of libotf and m17n-flt to handle the
1544 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1545 some Agian scripts. */
1546 #define M17N_FLT_USE_NEW_FEATURE
1559 ftfont_get_glyph_id (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1562 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1563 FT_Face ft_face
= flt_font_ft
->ft_face
;
1566 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1569 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1571 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1577 /* Operators for 26.6 fixed fractional pixel format */
1579 #define FLOOR(x) ((x) & -64)
1580 #define CEIL(x) (((x)+63) & -64)
1581 #define ROUND(x) (((x)+32) & -64)
1584 ftfont_get_metrics (MFLTFont
*font
, MFLTGlyphString
*gstring
,
1587 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1588 FT_Face ft_face
= flt_font_ft
->ft_face
;
1591 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1594 if (g
->code
!= FONT_INVALID_CODE
)
1596 FT_Glyph_Metrics
*m
;
1597 int lbearing
, rbearing
, ascent
, descent
, xadv
;
1599 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1601 m
= &ft_face
->glyph
->metrics
;
1602 if (flt_font_ft
->matrix
)
1607 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1608 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1609 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1610 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1611 for (i
= 0; i
< 4; i
++)
1612 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1613 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1614 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1615 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1616 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1620 g
->lbearing
= FLOOR (m
->horiBearingX
);
1621 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1622 g
->ascent
= CEIL (m
->horiBearingY
);
1623 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1625 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1630 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1631 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1632 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1641 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1643 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1644 OTF
*otf
= flt_font_ft
->otf
;
1648 for (i
= 0; i
< 2; i
++)
1650 if (! spec
->features
[i
])
1652 for (n
= 0; spec
->features
[i
][n
]; n
++);
1653 tags
= alloca (sizeof (OTF_Tag
) * n
);
1654 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1656 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1659 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1661 tags
[n
] = spec
->features
[i
][n
];
1663 #ifdef M17N_FLT_USE_NEW_FEATURE
1664 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1665 tags
, n
- negative
) != 1)
1667 #else /* not M17N_FLT_USE_NEW_FEATURE */
1668 if (n
- negative
> 0
1669 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1670 tags
, n
- negative
) != 1)
1672 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1677 #define DEVICE_DELTA(table, size) \
1678 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1679 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1683 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1684 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1686 if (anchor
->AnchorFormat
== 2)
1688 FT_Outline
*outline
;
1689 int ap
= anchor
->f
.f1
.AnchorPoint
;
1691 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1692 outline
= &ft_face
->glyph
->outline
;
1693 if (ap
< outline
->n_points
)
1695 *x
= outline
->points
[ap
].x
<< 6;
1696 *y
= outline
->points
[ap
].y
<< 6;
1699 else if (anchor
->AnchorFormat
== 3)
1701 if (anchor
->f
.f2
.XDeviceTable
.offset
1702 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1703 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1704 if (anchor
->f
.f2
.YDeviceTable
.offset
1705 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1706 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1710 static OTF_GlyphString otf_gstring
;
1713 setup_otf_gstring (int size
)
1715 if (otf_gstring
.size
== 0)
1717 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1718 otf_gstring
.size
= size
;
1720 else if (otf_gstring
.size
< size
)
1722 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1723 sizeof (OTF_Glyph
) * size
);
1724 otf_gstring
.size
= size
;
1726 otf_gstring
.used
= size
;
1727 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1730 #ifdef M17N_FLT_USE_NEW_FEATURE
1732 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1733 #define PACK_OTF_TAG(TAG) \
1734 ((((TAG) & 0x7F000000) >> 3) \
1735 | (((TAG) & 0x7F0000) >> 2) \
1736 | (((TAG) & 0x7F00) >> 1) \
1739 /* Assuming that FONT is an OpenType font, apply OpenType features
1740 specified in SPEC on glyphs between FROM and TO of IN, and record
1741 the lastly applied feature in each glyph of IN. If OUT is not
1742 NULL, append the resulting glyphs to OUT while storing glyph
1743 position adjustment information in ADJUSTMENT. */
1746 ftfont_drive_otf (font
, spec
, in
, from
, to
, out
, adjustment
)
1749 MFLTGlyphString
*in
;
1751 MFLTGlyphString
*out
;
1752 MFLTGlyphAdjustment
*adjustment
;
1754 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1755 FT_Face ft_face
= flt_font_ft
->ft_face
;
1756 OTF
*otf
= flt_font_ft
->otf
;
1757 int len
= to
- from
;
1760 char script
[5], *langsys
= NULL
;
1761 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1762 OTF_Feature
*features
;
1766 OTF_tag_name (spec
->script
, script
);
1769 langsys
= alloca (5);
1770 OTF_tag_name (spec
->langsys
, langsys
);
1772 for (i
= 0; i
< 2; i
++)
1776 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1778 for (j
= 0; spec
->features
[i
][j
]; j
++);
1780 p
= gsub_features
= alloca (6 * j
);
1782 p
= gpos_features
= alloca (6 * j
);
1783 for (j
= 0; spec
->features
[i
][j
]; j
++)
1785 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1786 *p
++ = '*', *p
++ = ',';
1789 OTF_tag_name (spec
->features
[i
][j
], p
);
1798 setup_otf_gstring (len
);
1799 for (i
= 0; i
< len
; i
++)
1801 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1802 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1805 OTF_drive_gdef (otf
, &otf_gstring
);
1806 gidx
= out
? out
->used
: from
;
1808 if (gsub_features
&& out
)
1810 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1813 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1815 features
= otf
->gsub
->FeatureList
.Feature
;
1816 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1819 int min_from
, max_to
;
1821 int feature_idx
= otfg
->positioning_type
>> 4;
1823 g
= out
->glyphs
+ out
->used
;
1824 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1825 if (g
->code
!= otfg
->glyph_id
)
1828 g
->code
= otfg
->glyph_id
;
1834 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1836 /* OTFG substitutes multiple glyphs in IN. */
1837 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1838 j
<= from
+ otfg
->f
.index
.to
; j
++)
1840 if (min_from
> in
->glyphs
[j
].from
)
1841 min_from
= in
->glyphs
[j
].from
;
1842 if (max_to
< in
->glyphs
[j
].to
)
1843 max_to
= in
->glyphs
[j
].to
;
1850 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1851 tag
= PACK_OTF_TAG (tag
);
1852 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1854 for (i
++, otfg
++; (i
< otf_gstring
.used
1855 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1858 g
= out
->glyphs
+ out
->used
;
1859 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1860 if (g
->code
!= otfg
->glyph_id
)
1863 g
->code
= otfg
->glyph_id
;
1866 feature_idx
= otfg
->positioning_type
>> 4;
1869 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1870 tag
= PACK_OTF_TAG (tag
);
1871 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1877 else if (gsub_features
)
1879 /* Just for checking which features will be applied. */
1880 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1883 features
= otf
->gsub
->FeatureList
.Feature
;
1884 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1887 int feature_idx
= otfg
->positioning_type
>> 4;
1891 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1892 tag
= PACK_OTF_TAG (tag
);
1893 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1895 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1896 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1903 if (out
->allocated
< out
->used
+ len
)
1905 for (i
= 0; i
< len
; i
++)
1906 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1909 if (gpos_features
&& out
)
1911 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1912 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1914 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1917 features
= otf
->gpos
->FeatureList
.Feature
;
1918 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1919 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1920 x_scale
= ft_face
->size
->metrics
.x_scale
;
1921 y_scale
= ft_face
->size
->metrics
.y_scale
;
1923 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1924 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1927 int feature_idx
= otfg
->positioning_type
>> 4;
1931 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1932 tag
= PACK_OTF_TAG (tag
);
1933 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1936 if (! otfg
->glyph_id
)
1938 switch (otfg
->positioning_type
& 0xF)
1942 case 1: /* Single */
1945 int format
= otfg
->f
.f1
.format
;
1947 if (format
& OTF_XPlacement
)
1949 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1950 if (format
& OTF_XPlaDevice
)
1952 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
1953 if (format
& OTF_YPlacement
)
1955 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
1956 if (format
& OTF_YPlaDevice
)
1958 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
1959 if (format
& OTF_XAdvance
)
1961 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
1962 if (format
& OTF_XAdvDevice
)
1964 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
1965 if (format
& OTF_YAdvance
)
1967 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
1968 if (format
& OTF_YAdvDevice
)
1970 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
1971 adjustment
[i
].set
= 1;
1974 case 3: /* Cursive */
1975 /* Not yet supported. */
1977 case 4: /* Mark-to-Base */
1978 case 5: /* Mark-to-Ligature */
1982 goto label_adjust_anchor
;
1983 default: /* i.e. case 6 Mark-to-Mark */
1988 label_adjust_anchor
:
1990 int base_x
, base_y
, mark_x
, mark_y
;
1991 int this_from
, this_to
;
1993 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
1994 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
1995 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
1996 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
1998 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
1999 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2000 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2001 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2002 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2003 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2004 adjustment
[i
].xoff
= (base_x
- mark_x
);
2005 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2006 adjustment
[i
].back
= (g
- prev
);
2007 adjustment
[i
].xadv
= 0;
2008 adjustment
[i
].advance_is_absolute
= 1;
2009 adjustment
[i
].set
= 1;
2010 this_from
= g
->from
;
2012 for (j
= 0; prev
+ j
< g
; j
++)
2014 if (this_from
> prev
[j
].from
)
2015 this_from
= prev
[j
].from
;
2016 if (this_to
< prev
[j
].to
)
2017 this_to
= prev
[j
].to
;
2019 for (; prev
<= g
; prev
++)
2021 prev
->from
= this_from
;
2026 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2028 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2034 else if (gpos_features
)
2036 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2039 features
= otf
->gpos
->FeatureList
.Feature
;
2040 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2042 if (otfg
->positioning_type
& 0xF)
2044 int feature_idx
= otfg
->positioning_type
>> 4;
2048 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2049 tag
= PACK_OTF_TAG (tag
);
2050 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2052 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2053 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2063 if (out
->allocated
< out
->used
+ len
)
2065 font
->get_metrics (font
, in
, from
, to
);
2066 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2067 sizeof (MFLTGlyph
) * len
);
2073 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2074 MFLTGlyphString
*in
, int from
, int to
)
2076 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2079 #else /* not M17N_FLT_USE_NEW_FEATURE */
2082 ftfont_drive_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
, MFLTGlyphString
*in
,
2084 MFLTGlyphString
*out
, MFLTGlyphAdjustment
*adjustment
)
2086 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2087 FT_Face ft_face
= flt_font_ft
->ft_face
;
2088 OTF
*otf
= flt_font_ft
->otf
;
2089 int len
= to
- from
;
2092 char script
[5], *langsys
= NULL
;
2093 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2097 OTF_tag_name (spec
->script
, script
);
2100 langsys
= alloca (5);
2101 OTF_tag_name (spec
->langsys
, langsys
);
2103 for (i
= 0; i
< 2; i
++)
2107 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2109 for (j
= 0; spec
->features
[i
][j
]; j
++);
2111 p
= gsub_features
= alloca (6 * j
);
2113 p
= gpos_features
= alloca (6 * j
);
2114 for (j
= 0; spec
->features
[i
][j
]; j
++)
2116 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2117 *p
++ = '*', *p
++ = ',';
2120 OTF_tag_name (spec
->features
[i
][j
], p
);
2129 setup_otf_gstring (len
);
2130 for (i
= 0; i
< len
; i
++)
2132 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2133 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2136 OTF_drive_gdef (otf
, &otf_gstring
);
2141 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2144 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2146 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2149 int min_from
, max_to
;
2152 g
= out
->glyphs
+ out
->used
;
2153 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2154 if (g
->code
!= otfg
->glyph_id
)
2157 g
->code
= otfg
->glyph_id
;
2163 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2165 /* OTFG substitutes multiple glyphs in IN. */
2166 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2167 j
<= from
+ otfg
->f
.index
.to
; j
++)
2169 if (min_from
> in
->glyphs
[j
].from
)
2170 min_from
= in
->glyphs
[j
].from
;
2171 if (max_to
< in
->glyphs
[j
].to
)
2172 max_to
= in
->glyphs
[j
].to
;
2177 for (i
++, otfg
++; (i
< otf_gstring
.used
2178 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2181 g
= out
->glyphs
+ out
->used
;
2182 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2183 if (g
->code
!= otfg
->glyph_id
)
2186 g
->code
= otfg
->glyph_id
;
2195 if (out
->allocated
< out
->used
+ len
)
2197 for (i
= 0; i
< len
; i
++)
2198 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2203 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2204 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2206 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2210 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2211 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2212 x_scale
= ft_face
->size
->metrics
.x_scale
;
2213 y_scale
= ft_face
->size
->metrics
.y_scale
;
2215 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2216 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2220 if (! otfg
->glyph_id
)
2222 switch (otfg
->positioning_type
)
2226 case 1: /* Single */
2229 int format
= otfg
->f
.f1
.format
;
2231 if (format
& OTF_XPlacement
)
2233 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2234 if (format
& OTF_XPlaDevice
)
2236 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2237 if (format
& OTF_YPlacement
)
2239 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2240 if (format
& OTF_YPlaDevice
)
2242 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2243 if (format
& OTF_XAdvance
)
2245 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2246 if (format
& OTF_XAdvDevice
)
2248 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2249 if (format
& OTF_YAdvance
)
2251 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2252 if (format
& OTF_YAdvDevice
)
2254 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2255 adjustment
[i
].set
= 1;
2258 case 3: /* Cursive */
2259 /* Not yet supported. */
2261 case 4: /* Mark-to-Base */
2262 case 5: /* Mark-to-Ligature */
2266 goto label_adjust_anchor
;
2267 default: /* i.e. case 6 Mark-to-Mark */
2272 label_adjust_anchor
:
2274 int base_x
, base_y
, mark_x
, mark_y
;
2275 int this_from
, this_to
;
2277 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2278 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2279 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2280 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2282 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2283 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2284 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2285 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2286 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2287 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2288 adjustment
[i
].xoff
= (base_x
- mark_x
);
2289 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2290 adjustment
[i
].back
= (g
- prev
);
2291 adjustment
[i
].xadv
= 0;
2292 adjustment
[i
].advance_is_absolute
= 1;
2293 adjustment
[i
].set
= 1;
2294 this_from
= g
->from
;
2296 for (j
= 0; prev
+ j
< g
; j
++)
2298 if (this_from
> prev
[j
].from
)
2299 this_from
= prev
[j
].from
;
2300 if (this_to
< prev
[j
].to
)
2301 this_to
= prev
[j
].to
;
2303 for (; prev
<= g
; prev
++)
2305 prev
->from
= this_from
;
2310 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2312 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2321 if (out
->allocated
< out
->used
+ len
)
2323 font
->get_metrics (font
, in
, from
, to
);
2324 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2325 sizeof (MFLTGlyph
) * len
);
2330 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2332 static MFLTGlyphString gstring
;
2334 static int m17n_flt_initialized
;
2336 extern Lisp_Object QCfamily
;
2339 ftfont_shape_by_flt (Lisp_Object lgstring
, struct font
*font
,
2340 FT_Face ft_face
, OTF
*otf
, FT_Matrix
*matrix
)
2342 EMACS_UINT len
= LGSTRING_GLYPH_LEN (lgstring
);
2344 struct MFLTFontFT flt_font_ft
;
2346 int with_variation_selector
= 0;
2348 if (! m17n_flt_initialized
)
2351 #ifdef M17N_FLT_USE_NEW_FEATURE
2352 mflt_enable_new_feature
= 1;
2353 mflt_try_otf
= ftfont_try_otf
;
2354 #endif /* M17N_FLT_USE_NEW_FEATURE */
2355 m17n_flt_initialized
= 1;
2358 for (i
= 0; i
< len
; i
++)
2360 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2365 c
= LGLYPH_CHAR (g
);
2366 if (CHAR_VARIATION_SELECTOR_P (c
))
2367 with_variation_selector
++;
2370 if (with_variation_selector
)
2372 setup_otf_gstring (len
);
2373 for (i
= 0; i
< len
; i
++)
2375 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2377 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2378 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2379 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2381 OTF_drive_cmap (otf
, &otf_gstring
);
2382 for (i
= 0; i
< otf_gstring
.used
; i
++)
2384 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2385 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2386 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2388 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2389 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2390 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2392 if (len
> otf_gstring
.used
)
2394 len
= otf_gstring
.used
;
2395 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2399 if (gstring
.allocated
== 0)
2401 gstring
.allocated
= len
* 2;
2402 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2403 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2405 else if (gstring
.allocated
< len
* 2)
2407 gstring
.allocated
= len
* 2;
2408 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2409 sizeof (MFLTGlyph
) * gstring
.allocated
);
2411 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2412 for (i
= 0; i
< len
; i
++)
2414 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2416 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2417 if (with_variation_selector
)
2419 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2420 gstring
.glyphs
[i
].encoded
= 1;
2428 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2431 flt_font_ft
.flt_font
.family
= Mnil
;
2433 flt_font_ft
.flt_font
.family
2434 = msymbol ((char *) SDATA (Fdowncase (SYMBOL_NAME (family
))));
2436 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2437 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2438 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2439 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2440 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2441 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2442 flt_font_ft
.flt_font
.internal
= NULL
;
2443 flt_font_ft
.font
= font
;
2444 flt_font_ft
.ft_face
= ft_face
;
2445 flt_font_ft
.otf
= otf
;
2446 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2448 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2449 /* A little bit ad hoc. Perhaps, shaper must get script and
2450 language information, and select a proper flt for them
2452 flt
= mflt_get (msymbol ("combining"));
2453 for (i
= 0; i
< 3; i
++)
2455 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2458 gstring
.allocated
+= gstring
.allocated
;
2459 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2460 sizeof (MFLTGlyph
) * gstring
.allocated
);
2462 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2464 for (i
= 0; i
< gstring
.used
; i
++)
2466 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2468 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2469 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2472 for (i
= 0; i
< gstring
.used
; i
++)
2474 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2475 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2479 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2480 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2482 LGLYPH_SET_FROM (lglyph
, g
->from
);
2483 LGLYPH_SET_TO (lglyph
, g
->to
);
2484 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2485 LGLYPH_SET_CODE (lglyph
, g
->code
);
2486 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2487 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2488 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2489 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2490 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2495 vec
= Fmake_vector (make_number (3), Qnil
);
2496 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2497 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2498 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2499 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2502 return make_number (i
);
2506 ftfont_shape (Lisp_Object lgstring
)
2509 struct ftfont_info
*ftfont_info
;
2512 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2513 ftfont_info
= (struct ftfont_info
*) font
;
2514 otf
= ftfont_get_otf (ftfont_info
);
2516 return make_number (0);
2517 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2518 &ftfont_info
->matrix
);
2521 #endif /* HAVE_M17N_FLT */
2523 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2526 ftfont_variation_glyphs (struct font
*font
, int c
, unsigned variations
[256])
2528 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2529 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2533 return OTF_get_variation_glyphs (otf
, c
, variations
);
2536 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2537 #endif /* HAVE_LIBOTF */
2540 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2544 #ifdef FC_FONTFORMAT
2547 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2549 if (strcmp ((char *) str
, "TrueType") == 0)
2550 return intern ("truetype");
2551 if (strcmp ((char *) str
, "Type 1") == 0)
2552 return intern ("type1");
2553 if (strcmp ((char *) str
, "PCF") == 0)
2554 return intern ("pcf");
2555 if (strcmp ((char *) str
, "BDF") == 0)
2556 return intern ("bdf");
2558 #endif /* FC_FONTFORMAT */
2559 if (STRINGP (filename
))
2561 int len
= SBYTES (filename
);
2565 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2566 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2567 return intern ("truetype");
2568 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2569 return intern ("type1");
2570 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2571 return intern ("pcf");
2572 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2573 return intern ("bdf");
2576 return intern ("unknown");
2579 static const char *ftfont_booleans
[] = {
2592 static const char *ftfont_non_booleans
[] = {
2624 ftfont_filter_properties (Lisp_Object font
, Lisp_Object alist
)
2629 /* Set boolean values to Qt or Qnil */
2630 for (i
= 0; ftfont_booleans
[i
] != NULL
; ++i
)
2631 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
2633 Lisp_Object key
= XCAR (XCAR (it
));
2634 Lisp_Object val
= XCDR (XCAR (it
));
2635 char *keystr
= SDATA (SYMBOL_NAME (key
));
2637 if (strcmp (ftfont_booleans
[i
], keystr
) == 0)
2639 char *str
= SYMBOLP (val
) ? SDATA (SYMBOL_NAME (val
)) : NULL
;
2640 if (INTEGERP (val
)) str
= XINT (val
) != 0 ? "true" : "false";
2641 if (str
== NULL
) str
= "true";
2644 if (strcmp ("false", str
) == 0 || strcmp ("False", str
) == 0
2645 || strcmp ("FALSE", str
) == 0 || strcmp ("FcFalse", str
) == 0
2646 || strcmp ("off", str
) == 0 || strcmp ("OFF", str
) == 0
2647 || strcmp ("Off", str
) == 0)
2649 Ffont_put (font
, key
, val
);
2653 for (i
= 0; ftfont_non_booleans
[i
] != NULL
; ++i
)
2654 for (it
= alist
; ! NILP (it
); it
= XCDR (it
))
2656 Lisp_Object key
= XCAR (XCAR (it
));
2657 Lisp_Object val
= XCDR (XCAR (it
));
2658 char *keystr
= SDATA (SYMBOL_NAME (key
));
2659 if (strcmp (ftfont_non_booleans
[i
], keystr
) == 0)
2660 Ffont_put (font
, key
, val
);
2666 syms_of_ftfont (void)
2668 DEFSYM (Qfreetype
, "freetype");
2669 DEFSYM (Qmonospace
, "monospace");
2670 DEFSYM (Qsans_serif
, "sans-serif");
2671 DEFSYM (Qserif
, "serif");
2672 DEFSYM (Qmono
, "mono");
2673 DEFSYM (Qsans
, "sans");
2674 DEFSYM (Qsans__serif
, "sans serif");
2676 staticpro (&freetype_font_cache
);
2677 freetype_font_cache
= Fcons (Qt
, Qnil
);
2679 staticpro (&ftfont_generic_family_list
);
2680 ftfont_generic_family_list
2681 = Fcons (Fcons (Qmonospace
, Qt
),
2682 Fcons (Fcons (Qsans_serif
, Qt
),
2683 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2685 staticpro (&ft_face_cache
);
2686 ft_face_cache
= Qnil
;
2688 ftfont_driver
.type
= Qfreetype
;
2689 register_font_driver (&ftfont_driver
, NULL
);
2692 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
2693 (do not change this comment) */