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
)
165 unsigned char *str
, *end
;
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
;
196 unsigned char *file
, *str
;
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
1267 && spacing
!= FC_DUAL
1268 #endif /* FC_DUAL */
1270 font
->min_width
= font
->average_width
= font
->space_width
1271 = (scalable
? ft_face
->max_advance_width
* size
/ upEM
1272 : ft_face
->size
->metrics
.max_advance
>> 6);
1277 font
->min_width
= font
->average_width
= font
->space_width
= 0;
1278 for (i
= 32, n
= 0; i
< 127; i
++)
1279 if (FT_Load_Char (ft_face
, i
, FT_LOAD_DEFAULT
) == 0)
1281 int this_width
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1284 && (! font
->min_width
|| font
->min_width
> this_width
))
1285 font
->min_width
= this_width
;
1287 font
->space_width
= this_width
;
1288 font
->average_width
+= this_width
;
1292 font
->average_width
/= n
;
1295 font
->baseline_offset
= 0;
1296 font
->relative_compose
= 0;
1297 font
->default_ascent
= 0;
1298 font
->vertical_centering
= 0;
1301 font
->underline_position
= -ft_face
->underline_position
* size
/ upEM
;
1302 font
->underline_thickness
= ft_face
->underline_thickness
* size
/ upEM
;
1306 font
->underline_position
= -1;
1307 font
->underline_thickness
= 0;
1314 ftfont_close (f
, font
)
1318 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1319 Lisp_Object val
, cache
;
1321 val
= Fcons (font
->props
[FONT_FILE_INDEX
], make_number (ftfont_info
->index
));
1322 cache
= ftfont_lookup_cache (val
, FTFONT_CACHE_FOR_FACE
);
1323 xassert (CONSP (cache
));
1325 (XSAVE_VALUE (val
)->integer
)--;
1326 if (XSAVE_VALUE (val
)->integer
== 0)
1328 struct ftfont_cache_data
*cache_data
= XSAVE_VALUE (val
)->pointer
;
1330 FT_Done_Face (cache_data
->ft_face
);
1332 if (ftfont_info
->otf
)
1333 OTF_close (ftfont_info
->otf
);
1335 cache_data
->ft_face
= NULL
;
1338 FT_Done_Size (ftfont_info
->ft_size
);
1342 ftfont_has_char (font
, c
)
1346 struct charset
*cs
= NULL
;
1348 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
1349 && charset_jisx0208
>= 0)
1350 cs
= CHARSET_FROM_ID (charset_jisx0208
);
1351 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
1352 && charset_ksc5601
>= 0)
1353 cs
= CHARSET_FROM_ID (charset_ksc5601
);
1355 return (ENCODE_CHAR (cs
, c
) != CHARSET_INVALID_CODE (cs
));
1357 if (FONT_ENTITY_P (font
))
1359 FcCharSet
*charset
= ftfont_get_fc_charset (font
);
1361 return (FcCharSetHasChar (charset
, c
) == FcTrue
);
1365 struct ftfont_info
*ftfont_info
;
1367 ftfont_info
= (struct ftfont_info
*) XFONT_OBJECT (font
);
1368 return (FT_Get_Char_Index (ftfont_info
->ft_size
->face
, (FT_ULong
) c
)
1374 ftfont_encode_char (font
, c
)
1378 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1379 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1380 FT_ULong charcode
= c
;
1381 FT_UInt code
= FT_Get_Char_Index (ft_face
, charcode
);
1383 return (code
> 0 ? code
: FONT_INVALID_CODE
);
1387 ftfont_text_extents (font
, code
, nglyphs
, metrics
)
1391 struct font_metrics
*metrics
;
1393 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1394 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1398 if (ftfont_info
->ft_size
!= ft_face
->size
)
1399 FT_Activate_Size (ftfont_info
->ft_size
);
1401 bzero (metrics
, sizeof (struct font_metrics
));
1402 for (i
= 0, first
= 1; i
< nglyphs
; i
++)
1404 if (FT_Load_Glyph (ft_face
, code
[i
], FT_LOAD_DEFAULT
) == 0)
1406 FT_Glyph_Metrics
*m
= &ft_face
->glyph
->metrics
;
1412 metrics
->lbearing
= m
->horiBearingX
>> 6;
1413 metrics
->rbearing
= (m
->horiBearingX
+ m
->width
) >> 6;
1414 metrics
->ascent
= m
->horiBearingY
>> 6;
1415 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1421 if (metrics
->lbearing
> width
+ (m
->horiBearingX
>> 6))
1422 metrics
->lbearing
= width
+ (m
->horiBearingX
>> 6);
1423 if (metrics
->rbearing
1424 < width
+ ((m
->horiBearingX
+ m
->width
) >> 6))
1426 = width
+ ((m
->horiBearingX
+ m
->width
) >> 6);
1427 if (metrics
->ascent
< (m
->horiBearingY
>> 6))
1428 metrics
->ascent
= m
->horiBearingY
>> 6;
1429 if (metrics
->descent
> ((m
->height
- m
->horiBearingY
) >> 6))
1430 metrics
->descent
= (m
->height
- m
->horiBearingY
) >> 6;
1432 width
+= m
->horiAdvance
>> 6;
1436 width
+= font
->space_width
;
1440 metrics
->width
= width
;
1446 ftfont_get_bitmap (font
, code
, bitmap
, bits_per_pixel
)
1449 struct font_bitmap
*bitmap
;
1452 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1453 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1454 FT_Int32 load_flags
= FT_LOAD_RENDER
;
1456 if (ftfont_info
->ft_size
!= ft_face
->size
)
1457 FT_Activate_Size (ftfont_info
->ft_size
);
1458 if (bits_per_pixel
== 1)
1460 #ifdef FT_LOAD_TARGET_MONO
1461 load_flags
|= FT_LOAD_TARGET_MONO
;
1463 load_flags
|= FT_LOAD_MONOCHROME
;
1466 else if (bits_per_pixel
!= 8)
1467 /* We don't support such a rendering. */
1470 if (FT_Load_Glyph (ft_face
, code
, load_flags
) != 0)
1472 bitmap
->bits_per_pixel
1473 = (ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_MONO
? 1
1474 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_GRAY
? 8
1475 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD
? 8
1476 : ft_face
->glyph
->bitmap
.pixel_mode
== FT_PIXEL_MODE_LCD_V
? 8
1478 if (bitmap
->bits_per_pixel
< 0)
1479 /* We don't suport that kind of pixel mode. */
1481 bitmap
->rows
= ft_face
->glyph
->bitmap
.rows
;
1482 bitmap
->width
= ft_face
->glyph
->bitmap
.width
;
1483 bitmap
->pitch
= ft_face
->glyph
->bitmap
.pitch
;
1484 bitmap
->buffer
= ft_face
->glyph
->bitmap
.buffer
;
1485 bitmap
->left
= ft_face
->glyph
->bitmap_left
;
1486 bitmap
->top
= ft_face
->glyph
->bitmap_top
;
1487 bitmap
->advance
= ft_face
->glyph
->metrics
.horiAdvance
>> 6;
1488 bitmap
->extra
= NULL
;
1494 ftfont_anchor_point (font
, code
, index
, x
, y
)
1500 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1501 FT_Face ft_face
= ftfont_info
->ft_size
->face
;
1503 if (ftfont_info
->ft_size
!= ft_face
->size
)
1504 FT_Activate_Size (ftfont_info
->ft_size
);
1505 if (FT_Load_Glyph (ft_face
, code
, FT_LOAD_DEFAULT
) != 0)
1507 if (ft_face
->glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1509 if (index
>= ft_face
->glyph
->outline
.n_points
)
1511 *x
= ft_face
->glyph
->outline
.points
[index
].x
;
1512 *y
= ft_face
->glyph
->outline
.points
[index
].y
;
1519 ftfont_otf_features (gsub_gpos
)
1520 OTF_GSUB_GPOS
*gsub_gpos
;
1522 Lisp_Object scripts
, langsyses
, features
, sym
;
1525 for (scripts
= Qnil
, i
= gsub_gpos
->ScriptList
.ScriptCount
- 1; i
>= 0; i
--)
1527 OTF_Script
*otf_script
= gsub_gpos
->ScriptList
.Script
+ i
;
1529 for (langsyses
= Qnil
, j
= otf_script
->LangSysCount
- 1; j
>= -1; j
--)
1531 OTF_LangSys
*otf_langsys
;
1534 otf_langsys
= otf_script
->LangSys
+ j
;
1535 else if (otf_script
->DefaultLangSysOffset
)
1536 otf_langsys
= &otf_script
->DefaultLangSys
;
1540 for (features
= Qnil
, k
= otf_langsys
->FeatureCount
- 1; k
>= 0; k
--)
1542 l
= otf_langsys
->FeatureIndex
[k
];
1543 if (l
>= gsub_gpos
->FeatureList
.FeatureCount
)
1545 OTF_TAG_SYM (sym
, gsub_gpos
->FeatureList
.Feature
[l
].FeatureTag
);
1546 features
= Fcons (sym
, features
);
1549 OTF_TAG_SYM (sym
, otf_script
->LangSysRecord
[j
].LangSysTag
);
1552 langsyses
= Fcons (Fcons (sym
, features
), langsyses
);
1555 OTF_TAG_SYM (sym
, gsub_gpos
->ScriptList
.Script
[i
].ScriptTag
);
1556 scripts
= Fcons (Fcons (sym
, langsyses
), scripts
);
1564 ftfont_otf_capability (font
)
1567 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
1568 OTF
*otf
= ftfont_get_otf (ftfont_info
);
1569 Lisp_Object gsub_gpos
;
1573 gsub_gpos
= Fcons (Qnil
, Qnil
);
1574 if (OTF_get_table (otf
, "GSUB") == 0
1575 && otf
->gsub
->FeatureList
.FeatureCount
> 0)
1576 XSETCAR (gsub_gpos
, ftfont_otf_features (otf
->gsub
));
1577 if (OTF_get_table (otf
, "GPOS") == 0
1578 && otf
->gpos
->FeatureList
.FeatureCount
> 0)
1579 XSETCDR (gsub_gpos
, ftfont_otf_features (otf
->gpos
));
1583 #ifdef HAVE_M17N_FLT
1585 #if (((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10)) \
1586 && ((M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6)))
1587 /* We can use the new feature of libotf and m17n-flt to handle the
1588 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1589 some Agian scripts. */
1590 #define M17N_FLT_USE_NEW_FEATURE
1603 ftfont_get_glyph_id (font
, gstring
, from
, to
)
1605 MFLTGlyphString
*gstring
;
1608 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1609 FT_Face ft_face
= flt_font_ft
->ft_face
;
1612 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1615 FT_UInt code
= FT_Get_Char_Index (ft_face
, g
->code
);
1617 g
->code
= code
> 0 ? code
: FONT_INVALID_CODE
;
1623 /* Operators for 26.6 fixed fractional pixel format */
1625 #define FLOOR(x) ((x) & -64)
1626 #define CEIL(x) (((x)+63) & -64)
1627 #define ROUND(x) (((x)+32) & -64)
1630 ftfont_get_metrics (font
, gstring
, from
, to
)
1632 MFLTGlyphString
*gstring
;
1635 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1636 FT_Face ft_face
= flt_font_ft
->ft_face
;
1639 for (g
= gstring
->glyphs
+ from
; from
< to
; g
++, from
++)
1642 if (g
->code
!= FONT_INVALID_CODE
)
1644 FT_Glyph_Metrics
*m
;
1645 int lbearing
, rbearing
, ascent
, descent
, xadv
;
1647 if (FT_Load_Glyph (ft_face
, g
->code
, FT_LOAD_DEFAULT
) != 0)
1649 m
= &ft_face
->glyph
->metrics
;
1650 if (flt_font_ft
->matrix
)
1655 v
[0].x
= v
[1].x
= m
->horiBearingX
;
1656 v
[2].x
= v
[3].x
= m
->horiBearingX
+ m
->width
;
1657 v
[0].y
= v
[2].y
= m
->horiBearingY
;
1658 v
[1].y
= v
[3].y
= m
->horiBearingY
- m
->height
;
1659 for (i
= 0; i
< 4; i
++)
1660 FT_Vector_Transform (v
+ i
, flt_font_ft
->matrix
);
1661 g
->lbearing
= v
[0].x
< v
[1].x
? FLOOR (v
[0].x
) : FLOOR (v
[1].x
);
1662 g
->rbearing
= v
[2].x
> v
[3].x
? CEIL (v
[2].x
) : CEIL (v
[3].x
);
1663 g
->ascent
= v
[0].y
> v
[2].y
? CEIL (v
[0].y
) : CEIL (v
[2].y
);
1664 g
->descent
= v
[1].y
< v
[3].y
? - FLOOR (v
[1].y
) : - FLOOR (v
[3].y
);
1668 g
->lbearing
= FLOOR (m
->horiBearingX
);
1669 g
->rbearing
= CEIL (m
->horiBearingX
+ m
->width
);
1670 g
->ascent
= CEIL (m
->horiBearingY
);
1671 g
->descent
= - FLOOR (m
->horiBearingY
- m
->height
);
1673 g
->xadv
= ROUND (ft_face
->glyph
->advance
.x
);
1678 g
->rbearing
= g
->xadv
= flt_font_ft
->font
->space_width
<< 6;
1679 g
->ascent
= flt_font_ft
->font
->ascent
<< 6;
1680 g
->descent
= flt_font_ft
->font
->descent
<< 6;
1689 ftfont_check_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
)
1691 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1692 OTF
*otf
= flt_font_ft
->otf
;
1696 for (i
= 0; i
< 2; i
++)
1698 if (! spec
->features
[i
])
1700 for (n
= 0; spec
->features
[i
][n
]; n
++);
1701 tags
= alloca (sizeof (OTF_Tag
) * n
);
1702 for (n
= 0, negative
= 0; spec
->features
[i
][n
]; n
++)
1704 if (spec
->features
[i
][n
] == 0xFFFFFFFF)
1707 tags
[n
- 1] = spec
->features
[i
][n
] | 0x80000000;
1709 tags
[n
] = spec
->features
[i
][n
];
1711 #ifdef M17N_FLT_USE_NEW_FEATURE
1712 if (OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1713 tags
, n
- negative
) != 1)
1715 #else /* not M17N_FLT_USE_NEW_FEATURE */
1716 if (n
- negative
> 0
1717 && OTF_check_features (otf
, i
== 0, spec
->script
, spec
->langsys
,
1718 tags
, n
- negative
) != 1)
1720 #endif /* not M17N_FLT_USE_NEW_FEATURE */
1725 #define DEVICE_DELTA(table, size) \
1726 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1727 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1731 adjust_anchor (FT_Face ft_face
, OTF_Anchor
*anchor
,
1732 unsigned code
, int x_ppem
, int y_ppem
, int *x
, int *y
)
1734 if (anchor
->AnchorFormat
== 2)
1736 FT_Outline
*outline
;
1737 int ap
= anchor
->f
.f1
.AnchorPoint
;
1739 FT_Load_Glyph (ft_face
, (FT_UInt
) code
, FT_LOAD_MONOCHROME
);
1740 outline
= &ft_face
->glyph
->outline
;
1741 if (ap
< outline
->n_points
)
1743 *x
= outline
->points
[ap
].x
<< 6;
1744 *y
= outline
->points
[ap
].y
<< 6;
1747 else if (anchor
->AnchorFormat
== 3)
1749 if (anchor
->f
.f2
.XDeviceTable
.offset
1750 && anchor
->f
.f2
.XDeviceTable
.DeltaValue
)
1751 *x
+= DEVICE_DELTA (anchor
->f
.f2
.XDeviceTable
, x_ppem
);
1752 if (anchor
->f
.f2
.YDeviceTable
.offset
1753 && anchor
->f
.f2
.YDeviceTable
.DeltaValue
)
1754 *y
+= DEVICE_DELTA (anchor
->f
.f2
.YDeviceTable
, y_ppem
);
1758 static OTF_GlyphString otf_gstring
;
1761 setup_otf_gstring (int size
)
1763 if (otf_gstring
.size
== 0)
1765 otf_gstring
.glyphs
= (OTF_Glyph
*) xmalloc (sizeof (OTF_Glyph
) * size
);
1766 otf_gstring
.size
= size
;
1768 else if (otf_gstring
.size
< size
)
1770 otf_gstring
.glyphs
= xrealloc (otf_gstring
.glyphs
,
1771 sizeof (OTF_Glyph
) * size
);
1772 otf_gstring
.size
= size
;
1774 otf_gstring
.used
= size
;
1775 memset (otf_gstring
.glyphs
, 0, sizeof (OTF_Glyph
) * size
);
1778 #ifdef M17N_FLT_USE_NEW_FEATURE
1780 /* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1781 #define PACK_OTF_TAG(TAG) \
1782 ((((TAG) & 0x7F000000) >> 3) \
1783 | (((TAG) & 0x7F0000) >> 2) \
1784 | (((TAG) & 0x7F00) >> 1) \
1787 /* Assuming that FONT is an OpenType font, apply OpenType features
1788 specified in SPEC on glyphs between FROM and TO of IN, and record
1789 the lastly applied feature in each glyph of IN. If OUT is not
1790 NULL, append the resulting glyphs to OUT while storing glyph
1791 position adjustment information in ADJUSTMENT. */
1794 ftfont_drive_otf (font
, spec
, in
, from
, to
, out
, adjustment
)
1797 MFLTGlyphString
*in
;
1799 MFLTGlyphString
*out
;
1800 MFLTGlyphAdjustment
*adjustment
;
1802 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
1803 FT_Face ft_face
= flt_font_ft
->ft_face
;
1804 OTF
*otf
= flt_font_ft
->otf
;
1805 int len
= to
- from
;
1808 char script
[5], *langsys
= NULL
;
1809 char *gsub_features
= NULL
, *gpos_features
= NULL
;
1810 OTF_Feature
*features
;
1814 OTF_tag_name (spec
->script
, script
);
1817 langsys
= alloca (5);
1818 OTF_tag_name (spec
->langsys
, langsys
);
1820 for (i
= 0; i
< 2; i
++)
1824 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
1826 for (j
= 0; spec
->features
[i
][j
]; j
++);
1828 p
= gsub_features
= alloca (6 * j
);
1830 p
= gpos_features
= alloca (6 * j
);
1831 for (j
= 0; spec
->features
[i
][j
]; j
++)
1833 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
1834 *p
++ = '*', *p
++ = ',';
1837 OTF_tag_name (spec
->features
[i
][j
], p
);
1846 setup_otf_gstring (len
);
1847 for (i
= 0; i
< len
; i
++)
1849 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
1850 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
1853 OTF_drive_gdef (otf
, &otf_gstring
);
1854 gidx
= out
? out
->used
: from
;
1856 if (gsub_features
&& out
)
1858 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1861 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
1863 features
= otf
->gsub
->FeatureList
.Feature
;
1864 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
1867 int min_from
, max_to
;
1869 int feature_idx
= otfg
->positioning_type
>> 4;
1871 g
= out
->glyphs
+ out
->used
;
1872 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
1873 if (g
->code
!= otfg
->glyph_id
)
1876 g
->code
= otfg
->glyph_id
;
1882 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
1884 /* OTFG substitutes multiple glyphs in IN. */
1885 for (j
= from
+ otfg
->f
.index
.from
+ 1;
1886 j
<= from
+ otfg
->f
.index
.to
; j
++)
1888 if (min_from
> in
->glyphs
[j
].from
)
1889 min_from
= in
->glyphs
[j
].from
;
1890 if (max_to
< in
->glyphs
[j
].to
)
1891 max_to
= in
->glyphs
[j
].to
;
1898 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1899 tag
= PACK_OTF_TAG (tag
);
1900 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1902 for (i
++, otfg
++; (i
< otf_gstring
.used
1903 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
1906 g
= out
->glyphs
+ out
->used
;
1907 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
1908 if (g
->code
!= otfg
->glyph_id
)
1911 g
->code
= otfg
->glyph_id
;
1914 feature_idx
= otfg
->positioning_type
>> 4;
1917 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1918 tag
= PACK_OTF_TAG (tag
);
1919 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1925 else if (gsub_features
)
1927 /* Just for checking which features will be applied. */
1928 if (OTF_drive_gsub_with_log (otf
, &otf_gstring
, script
, langsys
,
1931 features
= otf
->gsub
->FeatureList
.Feature
;
1932 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; i
++,
1935 int feature_idx
= otfg
->positioning_type
>> 4;
1939 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1940 tag
= PACK_OTF_TAG (tag
);
1941 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
1943 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
1944 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1951 if (out
->allocated
< out
->used
+ len
)
1953 for (i
= 0; i
< len
; i
++)
1954 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
1957 if (gpos_features
&& out
)
1959 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
1960 int x_ppem
, y_ppem
, x_scale
, y_scale
;
1962 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
1965 features
= otf
->gpos
->FeatureList
.Feature
;
1966 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
1967 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
1968 x_scale
= ft_face
->size
->metrics
.x_scale
;
1969 y_scale
= ft_face
->size
->metrics
.y_scale
;
1971 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
1972 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
1975 int feature_idx
= otfg
->positioning_type
>> 4;
1979 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
1980 tag
= PACK_OTF_TAG (tag
);
1981 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
1984 if (! otfg
->glyph_id
)
1986 switch (otfg
->positioning_type
& 0xF)
1990 case 1: /* Single */
1993 int format
= otfg
->f
.f1
.format
;
1995 if (format
& OTF_XPlacement
)
1997 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
1998 if (format
& OTF_XPlaDevice
)
2000 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2001 if (format
& OTF_YPlacement
)
2003 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2004 if (format
& OTF_YPlaDevice
)
2006 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2007 if (format
& OTF_XAdvance
)
2009 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2010 if (format
& OTF_XAdvDevice
)
2012 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2013 if (format
& OTF_YAdvance
)
2015 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2016 if (format
& OTF_YAdvDevice
)
2018 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2019 adjustment
[i
].set
= 1;
2022 case 3: /* Cursive */
2023 /* Not yet supported. */
2025 case 4: /* Mark-to-Base */
2026 case 5: /* Mark-to-Ligature */
2030 goto label_adjust_anchor
;
2031 default: /* i.e. case 6 Mark-to-Mark */
2036 label_adjust_anchor
:
2038 int base_x
, base_y
, mark_x
, mark_y
;
2039 int this_from
, this_to
;
2041 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2042 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2043 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2044 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2046 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2047 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2048 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2049 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2050 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2051 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2052 adjustment
[i
].xoff
= (base_x
- mark_x
);
2053 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2054 adjustment
[i
].back
= (g
- prev
);
2055 adjustment
[i
].xadv
= 0;
2056 adjustment
[i
].advance_is_absolute
= 1;
2057 adjustment
[i
].set
= 1;
2058 this_from
= g
->from
;
2060 for (j
= 0; prev
+ j
< g
; j
++)
2062 if (this_from
> prev
[j
].from
)
2063 this_from
= prev
[j
].from
;
2064 if (this_to
< prev
[j
].to
)
2065 this_to
= prev
[j
].to
;
2067 for (; prev
<= g
; prev
++)
2069 prev
->from
= this_from
;
2074 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2076 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2082 else if (gpos_features
)
2084 if (OTF_drive_gpos_with_log (otf
, &otf_gstring
, script
, langsys
,
2087 features
= otf
->gpos
->FeatureList
.Feature
;
2088 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
;
2090 if (otfg
->positioning_type
& 0xF)
2092 int feature_idx
= otfg
->positioning_type
>> 4;
2096 unsigned int tag
= features
[feature_idx
- 1].FeatureTag
;
2097 tag
= PACK_OTF_TAG (tag
);
2098 for (j
= otfg
->f
.index
.from
; j
<= otfg
->f
.index
.to
; j
++)
2100 MFLTGlyph
*g
= in
->glyphs
+ (from
+ j
);
2101 g
->internal
= (g
->internal
& ~0x1FFFFFFF) | tag
;
2111 if (out
->allocated
< out
->used
+ len
)
2113 font
->get_metrics (font
, in
, from
, to
);
2114 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2115 sizeof (MFLTGlyph
) * len
);
2121 ftfont_try_otf (MFLTFont
*font
, MFLTOtfSpec
*spec
,
2122 MFLTGlyphString
*in
, int from
, int to
)
2124 return ftfont_drive_otf (font
, spec
, in
, from
, to
, NULL
, NULL
);
2127 #else /* not M17N_FLT_USE_NEW_FEATURE */
2130 ftfont_drive_otf (font
, spec
, in
, from
, to
, out
, adjustment
)
2133 MFLTGlyphString
*in
;
2135 MFLTGlyphString
*out
;
2136 MFLTGlyphAdjustment
*adjustment
;
2138 struct MFLTFontFT
*flt_font_ft
= (struct MFLTFontFT
*) font
;
2139 FT_Face ft_face
= flt_font_ft
->ft_face
;
2140 OTF
*otf
= flt_font_ft
->otf
;
2141 int len
= to
- from
;
2144 char script
[5], *langsys
= NULL
;
2145 char *gsub_features
= NULL
, *gpos_features
= NULL
;
2149 OTF_tag_name (spec
->script
, script
);
2152 langsys
= alloca (5);
2153 OTF_tag_name (spec
->langsys
, langsys
);
2155 for (i
= 0; i
< 2; i
++)
2159 if (spec
->features
[i
] && spec
->features
[i
][1] != 0xFFFFFFFF)
2161 for (j
= 0; spec
->features
[i
][j
]; j
++);
2163 p
= gsub_features
= alloca (6 * j
);
2165 p
= gpos_features
= alloca (6 * j
);
2166 for (j
= 0; spec
->features
[i
][j
]; j
++)
2168 if (spec
->features
[i
][j
] == 0xFFFFFFFF)
2169 *p
++ = '*', *p
++ = ',';
2172 OTF_tag_name (spec
->features
[i
][j
], p
);
2181 setup_otf_gstring (len
);
2182 for (i
= 0; i
< len
; i
++)
2184 otf_gstring
.glyphs
[i
].c
= in
->glyphs
[from
+ i
].c
;
2185 otf_gstring
.glyphs
[i
].glyph_id
= in
->glyphs
[from
+ i
].code
;
2188 OTF_drive_gdef (otf
, &otf_gstring
);
2193 if (OTF_drive_gsub (otf
, &otf_gstring
, script
, langsys
, gsub_features
)
2196 if (out
->allocated
< out
->used
+ otf_gstring
.used
)
2198 for (i
= 0, otfg
= otf_gstring
.glyphs
; i
< otf_gstring
.used
; )
2201 int min_from
, max_to
;
2204 g
= out
->glyphs
+ out
->used
;
2205 *g
= in
->glyphs
[from
+ otfg
->f
.index
.from
];
2206 if (g
->code
!= otfg
->glyph_id
)
2209 g
->code
= otfg
->glyph_id
;
2215 if (otfg
->f
.index
.from
< otfg
->f
.index
.to
)
2217 /* OTFG substitutes multiple glyphs in IN. */
2218 for (j
= from
+ otfg
->f
.index
.from
+ 1;
2219 j
<= from
+ otfg
->f
.index
.to
; j
++)
2221 if (min_from
> in
->glyphs
[j
].from
)
2222 min_from
= in
->glyphs
[j
].from
;
2223 if (max_to
< in
->glyphs
[j
].to
)
2224 max_to
= in
->glyphs
[j
].to
;
2229 for (i
++, otfg
++; (i
< otf_gstring
.used
2230 && otfg
->f
.index
.from
== otfg
[-1].f
.index
.from
);
2233 g
= out
->glyphs
+ out
->used
;
2234 *g
= in
->glyphs
[from
+ otfg
->f
.index
.to
];
2235 if (g
->code
!= otfg
->glyph_id
)
2238 g
->code
= otfg
->glyph_id
;
2247 if (out
->allocated
< out
->used
+ len
)
2249 for (i
= 0; i
< len
; i
++)
2250 out
->glyphs
[out
->used
++] = in
->glyphs
[from
+ i
];
2255 MFLTGlyph
*base
= NULL
, *mark
= NULL
, *g
;
2256 int x_ppem
, y_ppem
, x_scale
, y_scale
;
2258 if (OTF_drive_gpos (otf
, &otf_gstring
, script
, langsys
, gpos_features
)
2262 x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2263 y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2264 x_scale
= ft_face
->size
->metrics
.x_scale
;
2265 y_scale
= ft_face
->size
->metrics
.y_scale
;
2267 for (i
= 0, otfg
= otf_gstring
.glyphs
, g
= out
->glyphs
+ gidx
;
2268 i
< otf_gstring
.used
; i
++, otfg
++, g
++)
2272 if (! otfg
->glyph_id
)
2274 switch (otfg
->positioning_type
)
2278 case 1: /* Single */
2281 int format
= otfg
->f
.f1
.format
;
2283 if (format
& OTF_XPlacement
)
2285 = otfg
->f
.f1
.value
->XPlacement
* x_scale
/ 0x10000;
2286 if (format
& OTF_XPlaDevice
)
2288 += DEVICE_DELTA (otfg
->f
.f1
.value
->XPlaDevice
, x_ppem
);
2289 if (format
& OTF_YPlacement
)
2291 = - (otfg
->f
.f1
.value
->YPlacement
* y_scale
/ 0x10000);
2292 if (format
& OTF_YPlaDevice
)
2294 -= DEVICE_DELTA (otfg
->f
.f1
.value
->YPlaDevice
, y_ppem
);
2295 if (format
& OTF_XAdvance
)
2297 += otfg
->f
.f1
.value
->XAdvance
* x_scale
/ 0x10000;
2298 if (format
& OTF_XAdvDevice
)
2300 += DEVICE_DELTA (otfg
->f
.f1
.value
->XAdvDevice
, x_ppem
);
2301 if (format
& OTF_YAdvance
)
2303 += otfg
->f
.f1
.value
->YAdvance
* y_scale
/ 0x10000;
2304 if (format
& OTF_YAdvDevice
)
2306 += DEVICE_DELTA (otfg
->f
.f1
.value
->YAdvDevice
, y_ppem
);
2307 adjustment
[i
].set
= 1;
2310 case 3: /* Cursive */
2311 /* Not yet supported. */
2313 case 4: /* Mark-to-Base */
2314 case 5: /* Mark-to-Ligature */
2318 goto label_adjust_anchor
;
2319 default: /* i.e. case 6 Mark-to-Mark */
2324 label_adjust_anchor
:
2326 int base_x
, base_y
, mark_x
, mark_y
;
2327 int this_from
, this_to
;
2329 base_x
= otfg
->f
.f4
.base_anchor
->XCoordinate
* x_scale
/ 0x10000;
2330 base_y
= otfg
->f
.f4
.base_anchor
->YCoordinate
* y_scale
/ 0x10000;
2331 mark_x
= otfg
->f
.f4
.mark_anchor
->XCoordinate
* x_scale
/ 0x10000;
2332 mark_y
= otfg
->f
.f4
.mark_anchor
->YCoordinate
* y_scale
/ 0x10000;
2334 if (otfg
->f
.f4
.base_anchor
->AnchorFormat
!= 1)
2335 adjust_anchor (ft_face
, otfg
->f
.f4
.base_anchor
,
2336 prev
->code
, x_ppem
, y_ppem
, &base_x
, &base_y
);
2337 if (otfg
->f
.f4
.mark_anchor
->AnchorFormat
!= 1)
2338 adjust_anchor (ft_face
, otfg
->f
.f4
.mark_anchor
, g
->code
,
2339 x_ppem
, y_ppem
, &mark_x
, &mark_y
);
2340 adjustment
[i
].xoff
= (base_x
- mark_x
);
2341 adjustment
[i
].yoff
= - (base_y
- mark_y
);
2342 adjustment
[i
].back
= (g
- prev
);
2343 adjustment
[i
].xadv
= 0;
2344 adjustment
[i
].advance_is_absolute
= 1;
2345 adjustment
[i
].set
= 1;
2346 this_from
= g
->from
;
2348 for (j
= 0; prev
+ j
< g
; j
++)
2350 if (this_from
> prev
[j
].from
)
2351 this_from
= prev
[j
].from
;
2352 if (this_to
< prev
[j
].to
)
2353 this_to
= prev
[j
].to
;
2355 for (; prev
<= g
; prev
++)
2357 prev
->from
= this_from
;
2362 if (otfg
->GlyphClass
== OTF_GlyphClass0
)
2364 else if (otfg
->GlyphClass
== OTF_GlyphClassMark
)
2373 if (out
->allocated
< out
->used
+ len
)
2375 font
->get_metrics (font
, in
, from
, to
);
2376 memcpy (out
->glyphs
+ out
->used
, in
->glyphs
+ from
,
2377 sizeof (MFLTGlyph
) * len
);
2382 #endif /* not M17N_FLT_USE_NEW_FEATURE */
2384 static MFLTGlyphString gstring
;
2386 static int m17n_flt_initialized
;
2388 extern Lisp_Object QCfamily
;
2391 ftfont_shape_by_flt (lgstring
, font
, ft_face
, otf
, matrix
)
2392 Lisp_Object lgstring
;
2398 EMACS_UINT len
= LGSTRING_GLYPH_LEN (lgstring
);
2400 struct MFLTFontFT flt_font_ft
;
2402 int with_variation_selector
= 0;
2404 if (! m17n_flt_initialized
)
2407 #ifdef M17N_FLT_USE_NEW_FEATURE
2408 mflt_enable_new_feature
= 1;
2409 mflt_try_otf
= ftfont_try_otf
;
2410 #endif /* M17N_FLT_USE_NEW_FEATURE */
2411 m17n_flt_initialized
= 1;
2414 for (i
= 0; i
< len
; i
++)
2416 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2421 c
= LGLYPH_CHAR (g
);
2422 if (CHAR_VARIATION_SELECTOR_P (c
))
2423 with_variation_selector
++;
2426 if (with_variation_selector
)
2428 setup_otf_gstring (len
);
2429 for (i
= 0; i
< len
; i
++)
2431 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2433 otf_gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2434 otf_gstring
.glyphs
[i
].f
.index
.from
= LGLYPH_FROM (g
);
2435 otf_gstring
.glyphs
[i
].f
.index
.to
= LGLYPH_TO (g
);
2437 OTF_drive_cmap (otf
, &otf_gstring
);
2438 for (i
= 0; i
< otf_gstring
.used
; i
++)
2440 OTF_Glyph
*otfg
= otf_gstring
.glyphs
+ i
;
2441 Lisp_Object g0
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.from
);
2442 Lisp_Object g1
= LGSTRING_GLYPH (lgstring
, otfg
->f
.index
.to
);
2444 LGLYPH_SET_CODE (g0
, otfg
->glyph_id
);
2445 LGLYPH_SET_TO (g0
, LGLYPH_TO (g1
));
2446 LGSTRING_SET_GLYPH (lgstring
, i
, g0
);
2448 if (len
> otf_gstring
.used
)
2450 len
= otf_gstring
.used
;
2451 LGSTRING_SET_GLYPH (lgstring
, len
, Qnil
);
2455 if (gstring
.allocated
== 0)
2457 gstring
.allocated
= len
* 2;
2458 gstring
.glyph_size
= sizeof (MFLTGlyph
);
2459 gstring
.glyphs
= xmalloc (sizeof (MFLTGlyph
) * gstring
.allocated
);
2461 else if (gstring
.allocated
< len
* 2)
2463 gstring
.allocated
= len
* 2;
2464 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2465 sizeof (MFLTGlyph
) * gstring
.allocated
);
2467 memset (gstring
.glyphs
, 0, sizeof (MFLTGlyph
) * len
);
2468 for (i
= 0; i
< len
; i
++)
2470 Lisp_Object g
= LGSTRING_GLYPH (lgstring
, i
);
2472 gstring
.glyphs
[i
].c
= LGLYPH_CHAR (g
);
2473 if (with_variation_selector
)
2475 gstring
.glyphs
[i
].code
= LGLYPH_CODE (g
);
2476 gstring
.glyphs
[i
].encoded
= 1;
2484 Lisp_Object family
= Ffont_get (LGSTRING_FONT (lgstring
), QCfamily
);
2487 flt_font_ft
.flt_font
.family
= Mnil
;
2489 flt_font_ft
.flt_font
.family
2490 = msymbol ((char *) SDATA (Fdowncase (SYMBOL_NAME (family
))));
2492 flt_font_ft
.flt_font
.x_ppem
= ft_face
->size
->metrics
.x_ppem
;
2493 flt_font_ft
.flt_font
.y_ppem
= ft_face
->size
->metrics
.y_ppem
;
2494 flt_font_ft
.flt_font
.get_glyph_id
= ftfont_get_glyph_id
;
2495 flt_font_ft
.flt_font
.get_metrics
= ftfont_get_metrics
;
2496 flt_font_ft
.flt_font
.check_otf
= ftfont_check_otf
;
2497 flt_font_ft
.flt_font
.drive_otf
= ftfont_drive_otf
;
2498 flt_font_ft
.flt_font
.internal
= NULL
;
2499 flt_font_ft
.font
= font
;
2500 flt_font_ft
.ft_face
= ft_face
;
2501 flt_font_ft
.otf
= otf
;
2502 flt_font_ft
.matrix
= matrix
->xx
!= 0 ? matrix
: 0;
2504 && gstring
.glyphs
[1].c
>= 0x300 && gstring
.glyphs
[1].c
<= 0x36F)
2505 /* A little bit ad hoc. Perhaps, shaper must get script and
2506 language information, and select a proper flt for them
2508 flt
= mflt_get (msymbol ("combining"));
2509 for (i
= 0; i
< 3; i
++)
2511 int result
= mflt_run (&gstring
, 0, len
, &flt_font_ft
.flt_font
, flt
);
2514 gstring
.allocated
+= gstring
.allocated
;
2515 gstring
.glyphs
= xrealloc (gstring
.glyphs
,
2516 sizeof (MFLTGlyph
) * gstring
.allocated
);
2518 if (gstring
.used
> LGSTRING_GLYPH_LEN (lgstring
))
2520 for (i
= 0; i
< gstring
.used
; i
++)
2522 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2524 g
->from
= LGLYPH_FROM (LGSTRING_GLYPH (lgstring
, g
->from
));
2525 g
->to
= LGLYPH_TO (LGSTRING_GLYPH (lgstring
, g
->to
));
2528 for (i
= 0; i
< gstring
.used
; i
++)
2530 Lisp_Object lglyph
= LGSTRING_GLYPH (lgstring
, i
);
2531 MFLTGlyph
*g
= gstring
.glyphs
+ i
;
2535 lglyph
= Fmake_vector (make_number (LGLYPH_SIZE
), Qnil
);
2536 LGSTRING_SET_GLYPH (lgstring
, i
, lglyph
);
2538 LGLYPH_SET_FROM (lglyph
, g
->from
);
2539 LGLYPH_SET_TO (lglyph
, g
->to
);
2540 LGLYPH_SET_CHAR (lglyph
, g
->c
);
2541 LGLYPH_SET_CODE (lglyph
, g
->code
);
2542 LGLYPH_SET_WIDTH (lglyph
, g
->xadv
>> 6);
2543 LGLYPH_SET_LBEARING (lglyph
, g
->lbearing
>> 6);
2544 LGLYPH_SET_RBEARING (lglyph
, g
->rbearing
>> 6);
2545 LGLYPH_SET_ASCENT (lglyph
, g
->ascent
>> 6);
2546 LGLYPH_SET_DESCENT (lglyph
, g
->descent
>> 6);
2551 vec
= Fmake_vector (make_number (3), Qnil
);
2552 ASET (vec
, 0, make_number (g
->xoff
>> 6));
2553 ASET (vec
, 1, make_number (g
->yoff
>> 6));
2554 ASET (vec
, 2, make_number (g
->xadv
>> 6));
2555 LGLYPH_SET_ADJUSTMENT (lglyph
, vec
);
2558 return make_number (i
);
2562 ftfont_shape (lgstring
)
2563 Lisp_Object lgstring
;
2566 struct ftfont_info
*ftfont_info
;
2569 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring
), font
);
2570 ftfont_info
= (struct ftfont_info
*) font
;
2571 otf
= ftfont_get_otf (ftfont_info
);
2573 return make_number (0);
2574 return ftfont_shape_by_flt (lgstring
, font
, ftfont_info
->ft_size
->face
, otf
,
2575 &ftfont_info
->matrix
);
2578 #endif /* HAVE_M17N_FLT */
2580 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
2583 ftfont_variation_glyphs (font
, c
, variations
)
2586 unsigned variations
[256];
2588 struct ftfont_info
*ftfont_info
= (struct ftfont_info
*) font
;
2589 OTF
*otf
= ftfont_get_otf (ftfont_info
);
2593 return OTF_get_variation_glyphs (otf
, c
, variations
);
2596 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
2597 #endif /* HAVE_LIBOTF */
2600 ftfont_font_format (FcPattern
*pattern
, Lisp_Object filename
)
2604 #ifdef FC_FONTFORMAT
2607 if (FcPatternGetString (pattern
, FC_FONTFORMAT
, 0, &str
) != FcResultMatch
)
2609 if (strcmp ((char *) str
, "TrueType") == 0)
2610 return intern ("truetype");
2611 if (strcmp ((char *) str
, "Type 1") == 0)
2612 return intern ("type1");
2613 if (strcmp ((char *) str
, "PCF") == 0)
2614 return intern ("pcf");
2615 if (strcmp ((char *) str
, "BDF") == 0)
2616 return intern ("bdf");
2618 #endif /* FC_FONTFORMAT */
2619 if (STRINGP (filename
))
2621 int len
= SBYTES (filename
);
2625 str
= (FcChar8
*) (SDATA (filename
) + len
- 4);
2626 if (xstrcasecmp ((char *) str
, ".ttf") == 0)
2627 return intern ("truetype");
2628 if (xstrcasecmp ((char *) str
, ".pfb") == 0)
2629 return intern ("type1");
2630 if (xstrcasecmp ((char *) str
, ".pcf") == 0)
2631 return intern ("pcf");
2632 if (xstrcasecmp ((char *) str
, ".bdf") == 0)
2633 return intern ("bdf");
2636 return intern ("unknown");
2639 static const char *ftfont_booleans
[] = {
2652 static const char *ftfont_non_booleans
[] = {
2684 ftfont_filter_properties (font
, alist
)
2688 font_filter_properties (font
, alist
, ftfont_booleans
, ftfont_non_booleans
);
2695 DEFSYM (Qfreetype
, "freetype");
2696 DEFSYM (Qmonospace
, "monospace");
2697 DEFSYM (Qsans_serif
, "sans-serif");
2698 DEFSYM (Qserif
, "serif");
2699 DEFSYM (Qmono
, "mono");
2700 DEFSYM (Qsans
, "sans");
2701 DEFSYM (Qsans__serif
, "sans serif");
2703 staticpro (&freetype_font_cache
);
2704 freetype_font_cache
= Fcons (Qt
, Qnil
);
2706 staticpro (&ftfont_generic_family_list
);
2707 ftfont_generic_family_list
2708 = Fcons (Fcons (Qmonospace
, Qt
),
2709 Fcons (Fcons (Qsans_serif
, Qt
),
2710 Fcons (Fcons (Qsans
, Qt
), Qnil
)));
2712 staticpro (&ft_face_cache
);
2713 ft_face_cache
= Qnil
;
2715 ftfont_driver
.type
= Qfreetype
;
2716 register_font_driver (&ftfont_driver
, NULL
);
2719 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
2720 (do not change this comment) */