1 /* font-ft.c -- FreeType interface sub-module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 #include <sys/types.h>
35 #include "m17n-misc.h"
40 #include "internal-gui.h"
50 static int mdebug_mask = MDEBUG_FONT;
52 #ifdef HAVE_FONTCONFIG
53 #include <fontconfig/fcfreetype.h>
55 static FcConfig *fc_config;
56 static MSymbol Mgeneric_family;
57 #endif /* HAVE_FONTCONFIG */
59 /* Font properties; Mnormal is already defined in face.c. */
60 static MSymbol Mmedium, Mr, Mnull;
62 static MSymbol M0[5], M3_1, M1_0;
64 static FT_Library ft_library;
67 static OTF *invalid_otf = (OTF *) "";
74 /* NULL if not yet opened. invalid_otf if not OTF. */
77 #ifdef HAVE_FONTCONFIG
80 #endif /* HAVE_FONTCONFIG */
86 FT_Face ft_face; /* This must be the 2nd member. */
88 int face_encapsulated;
95 enum MFontProperty prop;
99 static MFTtoProp ft_to_prop[] =
100 { { "italic", 0, MFONT_STYLE, "i" },
101 { "roman", 0, MFONT_STYLE, "r" },
102 { "oblique", 0, MFONT_STYLE, "o" },
103 { "regular", 0, MFONT_WEIGHT, "normal" },
104 { "normal", 0, MFONT_WEIGHT, "normal" },
105 /* We need this entry even if "bold" is in commone_weight[] to
106 handle such style names as "bolditalic" and "boldoblique". */
107 { "bold", 0, MFONT_WEIGHT, "bold" },
108 { "demi bold", 0, MFONT_WEIGHT, "demibold" },
109 { "demi", 0, MFONT_WEIGHT, "demibold" } };
110 static int ft_to_prop_size = sizeof ft_to_prop / sizeof ft_to_prop[0];
112 /** List of FreeType fonts. Keys are family names, values are plists
113 containing fonts of the corresponding family. In the deeper
114 plist, keys are file names, values are (MFontFT *). */
115 static MPlist *ft_font_list;
117 /** List of FreeType fonts. Keys are script names, values are plists
118 containing fonts supporting the corresponding script. In the
119 deeper plist, keys are family names, values are (MFontFT *). */
120 static MPlist *ft_script_list;
122 /** List of FreeType fonts. Keys are language names, values are
123 plists containing fonts supporting the corresponding language. In
124 the deeper plist, keys are family names, values are (MFontFT *). */
125 static MPlist *ft_language_list;
127 static MPlist *ft_file_list;
129 static int all_fonts_scaned;
131 #define STRDUP_LOWER(s1, size, s2) \
133 int len = strlen (s2) + 1; \
137 (s1) = alloca (len), (size) = len; \
138 for (p1 = (s1), p2 = (s2); *p2; p1++, p2++) \
139 *p1 = (*p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2); \
140 while (p1 > (s1) && p1[-1] == ' ') p1--; \
145 static MPlist *ft_list_family (MSymbol, int);
148 free_ft_rfont (void *object)
150 MRealizedFontFT *ft_rfont = object;
152 if (! ft_rfont->face_encapsulated)
154 M17N_OBJECT_UNREF (ft_rfont->charmap_list);
155 FT_Done_Face (ft_rfont->ft_face);
161 free_ft_info (MFontFT *ft_info)
164 if (ft_info->otf && ft_info->otf != invalid_otf)
165 OTF_close (ft_info->otf);
166 #endif /* HAVE_OTF */
167 #ifdef HAVE_FONTCONFIG
168 if (ft_info->langset)
169 FcLangSetDestroy (ft_info->langset);
170 if (ft_info->charset)
171 FcCharSetDestroy (ft_info->charset);
172 #endif /* HAVE_FONTCONFIG */
177 ft_get_charmaps (FT_Face ft_face)
179 MPlist *plist = mplist ();
180 int unicode_bmp = -1, unicode_full = -1;
183 mplist_add (plist, Mt, (void *) -1);
184 for (i = 0; i < ft_face->num_charmaps; i++)
186 MSymbol registry = Mnil;
188 if (ft_face->charmaps[i]->platform_id == 0)
190 if (ft_face->charmaps[i]->encoding_id <= 4)
191 registry = M0[ft_face->charmaps[i]->encoding_id], unicode_bmp = i;
192 if (ft_face->charmaps[i]->encoding_id == 4)
193 unicode_bmp = unicode_full = i;
195 else if (ft_face->charmaps[i]->platform_id == 3)
197 if (ft_face->charmaps[i]->encoding_id == 1)
198 registry = M3_1, unicode_bmp = i;
199 else if (ft_face->charmaps[i]->encoding_id == 10)
200 unicode_bmp = unicode_full = i;
202 else if (ft_face->charmaps[i]->platform_id == 1
203 && ft_face->charmaps[i]->encoding_id == 0)
206 mplist_add (plist, Mapple_roman, (void *) i);
208 if (registry == Mnil)
210 char registry_buf[16];
212 sprintf (registry_buf, "%d-%d",
213 ft_face->charmaps[i]->platform_id,
214 ft_face->charmaps[i]->encoding_id);
215 registry = msymbol (registry_buf);
217 mplist_add (plist, registry, (void *) i);
219 if (unicode_full >= 0)
220 mplist_add (plist, Municode_full, (void *) unicode_full);
221 if (unicode_bmp >= 0)
225 mplist_add (plist, Municode_bmp, (void *) unicode_bmp);
226 FT_Set_Charmap (ft_face, ft_face->charmaps[unicode_bmp]);
227 for (i = 0x21; i < 0x7F && FT_Get_Char_Index (ft_face, i) > 0; i++);
230 for (i = 0xC0; i < 0x100 && FT_Get_Char_Index (ft_face, i) > 0; i++);
232 mplist_add (plist, Miso8859_1, (void *) unicode_bmp);
240 ft_gen_font (FT_Face ft_face)
250 if (FT_IS_SCALABLE (ft_face))
251 size = ft_face->size->metrics.y_ppem;
252 else if (ft_face->num_fixed_sizes == 0)
255 size = ft_face->available_sizes[0].height;
257 MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT);
258 font = &ft_info->font;
259 STRDUP_LOWER (buf, bufsize, ft_face->family_name);
260 family = msymbol (buf);
261 mfont__set_property (font, MFONT_FAMILY, family);
262 mfont__set_property (font, MFONT_WEIGHT, Mmedium);
263 mfont__set_property (font, MFONT_STYLE, Mr);
264 mfont__set_property (font, MFONT_STRETCH, Mnormal);
265 mfont__set_property (font, MFONT_ADSTYLE, Mnull);
266 mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
267 font->size = size * 10;
268 font->type = MFONT_TYPE_OBJECT;
269 font->source = MFONT_SOURCE_FT;
272 stylename = ft_face->style_name;
277 for (i = 0; i < ft_to_prop_size; i++)
278 if (! strncasecmp (ft_to_prop[i].ft_style, stylename,
281 mfont__set_property (font, ft_to_prop[i].prop,
282 msymbol (ft_to_prop[i].val));
283 stylename += ft_to_prop[i].len;
286 if (i == ft_to_prop_size)
288 char *p1 = stylename + 1;
291 while (*p1 >= 'a' && *p1 <= 'z') p1++;
292 sym = msymbol__with_len (stylename, p1 - stylename);
293 for (i = MFONT_WEIGHT; i <= MFONT_STRETCH; i++)
294 if (msymbol_get (sym, mfont__property_table[i].property))
296 mfont__set_property (font, i, sym);
301 while (*stylename && ! isalpha (*stylename))
307 #ifdef HAVE_FONTCONFIG
314 } FC_vs_M17N_font_prop;
316 static FC_vs_M17N_font_prop fc_weight_table[] =
317 { { FC_WEIGHT_THIN, "thin" },
318 { FC_WEIGHT_ULTRALIGHT, "extralight" },
319 { FC_WEIGHT_LIGHT, "light" },
320 #ifdef FC_WEIGHT_BOOK
321 { FC_WEIGHT_BOOK, "book" },
322 #endif /* FC_WEIGHT_BOOK */
323 { FC_WEIGHT_REGULAR, "normal" },
324 { FC_WEIGHT_NORMAL, "normal" },
325 { FC_WEIGHT_MEDIUM, "medium" },
326 { FC_WEIGHT_DEMIBOLD, "demibold" },
327 { FC_WEIGHT_BOLD, "bold" },
328 { FC_WEIGHT_EXTRABOLD, "extrabold" },
329 { FC_WEIGHT_BLACK, "black" },
330 { FC_WEIGHT_HEAVY, "heavy" },
331 { FC_WEIGHT_MEDIUM, NULL } };
332 int fc_weight_table_size =
333 sizeof fc_weight_table / sizeof (FC_vs_M17N_font_prop);
335 static FC_vs_M17N_font_prop fc_slant_table[] =
336 { { FC_SLANT_ROMAN, "r" },
337 { FC_SLANT_ITALIC, "i" },
338 { FC_SLANT_OBLIQUE, "o" },
339 { FC_SLANT_ROMAN, NULL } };
340 int fc_slant_table_size =
341 sizeof fc_slant_table / sizeof (FC_vs_M17N_font_prop);
343 static FC_vs_M17N_font_prop fc_width_table[] =
344 { { FC_WIDTH_ULTRACONDENSED, "ultracondensed" },
345 { FC_WIDTH_EXTRACONDENSED, "extracondensed" },
346 { FC_WIDTH_CONDENSED, "condensed" },
347 { FC_WIDTH_SEMICONDENSED, "semicondensed" },
348 { FC_WIDTH_NORMAL, "normal" },
349 { FC_WIDTH_SEMIEXPANDED, "semiexpanded" },
350 { FC_WIDTH_EXPANDED, "expanded" },
351 { FC_WIDTH_EXTRAEXPANDED, "extraexpanded" },
352 { FC_WIDTH_ULTRAEXPANDED, "ultraexpanded" },
353 { FC_WIDTH_NORMAL, NULL } };
354 int fc_width_table_size =
355 sizeof fc_width_table / sizeof (FC_vs_M17N_font_prop);
358 static FC_vs_M17N_font_prop *fc_all_table[] =
359 { fc_weight_table, fc_slant_table, fc_width_table };
362 fc_decode_prop (int val, FC_vs_M17N_font_prop *table, int size)
366 if (val < table[i].fc_value)
368 for (i--; i >= 0; i--)
369 if (val > table[i].fc_value)
375 for (; i < size; i++)
376 if (val <= table[i].fc_value)
383 fc_encode_prop (MSymbol sym, FC_vs_M17N_font_prop *table)
387 for (i = 0; table[i].m17n_value; i++)
388 if (table[i].sym == sym)
390 return table[i].fc_value;
394 fc_get_pattern (MFont *font)
396 FcPattern *pat = FcPatternCreate ();
397 MSymbol sym, weight, style, stretch;
400 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FOUNDRY)) != Mnil)
401 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) MSYMBOL_NAME (sym));
402 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FAMILY)) != Mnil)
403 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) MSYMBOL_NAME (sym));
404 if ((weight = (MSymbol) FONT_PROPERTY (font, MFONT_WEIGHT)) != Mnil)
405 FcPatternAddInteger (pat, FC_WEIGHT,
406 fc_encode_prop (weight, fc_weight_table));
407 if ((style = (MSymbol) FONT_PROPERTY (font, MFONT_STYLE)) != Mnil)
408 FcPatternAddInteger (pat, FC_SLANT,
409 fc_encode_prop (style, fc_slant_table));
410 if ((stretch = (MSymbol) FONT_PROPERTY (font, MFONT_STRETCH)) != Mnil)
411 FcPatternAddInteger (pat, FC_WIDTH,
412 fc_encode_prop (stretch, fc_width_table));
415 double size = font->size;
416 FcPatternAddDouble (pat, FC_PIXEL_SIZE, size / 10);
418 else if (font->size < 0)
420 double size = - font->size;
421 FcPatternAddDouble (pat, FC_SIZE, size / 10);
427 fc_parse_pattern (FcPattern *pat, char *family, MFontFT *ft_info)
437 MFont *font = &ft_info->font;
440 if (FcPatternGetString (pat, FC_FOUNDRY, 0, &str) == FcResultMatch)
442 STRDUP_LOWER (buf, bufsize, (char *) str);
443 mfont__set_property (font, MFONT_FOUNDRY, msymbol (buf));
446 mfont__set_property (font, MFONT_FAMILY, msymbol (family));
447 else if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
449 STRDUP_LOWER (buf, bufsize, (char *) str);
450 mfont__set_property (font, MFONT_FAMILY, msymbol (buf));
452 if (FcPatternGetInteger (pat, FC_WEIGHT, 0, &val) == FcResultMatch)
454 sym = fc_decode_prop (val, fc_weight_table, fc_weight_table_size);
455 mfont__set_property (font, MFONT_WEIGHT, sym);
457 if (FcPatternGetInteger (pat, FC_SLANT, 0, &val) == FcResultMatch)
459 sym = fc_decode_prop (val, fc_slant_table, fc_slant_table_size);
460 mfont__set_property (font, MFONT_STYLE, sym);
462 if (FcPatternGetInteger (pat, FC_WIDTH, 0, &val) == FcResultMatch)
464 sym = fc_decode_prop (val, fc_width_table, fc_width_table_size);
465 mfont__set_property (font, MFONT_STRETCH, sym);
467 if (FcPatternGetLangSet (pat, FC_LANG, 0, &ls) == FcResultMatch)
469 if (FcLangSetHasLang (ls, (FcChar8 *) "ja") != FcLangDifferentLang
470 || FcLangSetHasLang (ls, (FcChar8 *) "zh") != FcLangDifferentLang
471 || FcLangSetHasLang (ls, (FcChar8 *) "ko") != FcLangDifferentLang)
472 font->for_full_width = 1;
473 ft_info->langset = FcLangSetCopy (ls);
475 if (FcPatternGetCharSet (pat, FC_CHARSET, 0, &cs) == FcResultMatch)
476 ft_info->charset = FcCharSetCopy (cs);
478 mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
479 font->type = MFONT_TYPE_SPEC;
480 font->source = MFONT_SOURCE_FT;
481 if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
482 font->size = size * 10;
483 if (FcPatternGetString (pat, FC_FILE, 0, &str) == FcResultMatch)
484 font->file = msymbol ((char *) str);
489 fc_gen_font (FcPattern *pat, char *family)
493 MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT);
494 fc_parse_pattern (pat, family, ft_info);
495 ft_info->font.type = MFONT_TYPE_OBJECT;
500 fc_init_font_list (void)
502 FcPattern *pattern = FcPatternCreate ();
503 FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, NULL);
504 FcFontSet *fs = FcFontList (fc_config, pattern, os);
505 MPlist *plist = mplist ();
510 ft_font_list = plist;
511 for (i = 0; i < fs->nfont; i++)
515 if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
516 (FcChar8 **) &fam) != FcResultMatch)
518 STRDUP_LOWER (buf, bufsize, fam);
519 plist = mplist_add (plist, msymbol (buf), NULL);
521 FcFontSetDestroy (fs);
522 FcObjectSetDestroy (os);
523 FcPatternDestroy (pattern);
527 fc_list_pattern (FcPattern *pattern)
529 FcObjectSet *os = NULL;
530 FcFontSet *fs = NULL;
531 MSymbol last_family = Mnil;
532 MPlist *plist = NULL, *pl = NULL;
537 if (! (os = FcObjectSetBuild (FC_FAMILY, FC_FILE, NULL)))
539 if (! (fs = FcFontList (fc_config, pattern, os)))
542 for (i = 0; i < fs->nfont; i++)
544 MSymbol family, file;
545 char *fam, *filename;
548 if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
549 (FcChar8 **) &fam) != FcResultMatch)
551 if (FcPatternGetString (fs->fonts[i], FC_FILE, 0,
552 (FcChar8 **) &filename) != FcResultMatch)
554 STRDUP_LOWER (buf, bufsize, fam);
555 family = msymbol (buf);
556 file = msymbol (filename);
557 if (family != last_family)
559 pl = MPLIST_PLIST (ft_list_family (family, 0));
560 last_family = family;
562 ft_info = mplist_get (pl, file);
567 mplist_add (plist, family, ft_info);
572 if (fs) FcFontSetDestroy (fs);
573 if (os) FcObjectSetDestroy (os);
577 /* Return FcCharSet object built from CHAR_LIST or MT. In the latter
578 case, it is assured that the M-text contains at least one
582 fc_build_charset (MPlist *char_list, MText *mt)
584 FcCharSet *cs = FcCharSetCreate ();
590 for (; ! MPLIST_TAIL_P (char_list); char_list = MPLIST_NEXT (char_list))
591 if (! FcCharSetAddChar (cs, (FcChar32) MPLIST_INTEGER (char_list)))
593 FcCharSetDestroy (cs);
601 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
602 if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i)))
604 FcCharSetDestroy (cs);
607 if (mtext_nchars (mt) > 0
608 && (mt = mtext_get_prop (mt, 0, Mtext)))
609 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
610 if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i)))
612 FcCharSetDestroy (cs);
619 #else /* not HAVE_FONTCONFIG */
622 ft_add_font (char *filename)
635 if (FT_New_Face (ft_library, filename, 0, &ft_face) != 0)
637 ft_info = ft_gen_font (ft_face);
638 FT_Done_Face (ft_face);
642 font = &ft_info->font;
643 font->file = msymbol (filename);
645 plist = mplist_find_by_key (ft_font_list, family);
647 mplist_push (MPLIST_PLIST (plist), font->file, ft_info);
651 mplist_add (plist, font->file, ft_info);
652 plist = mplist_push (ft_font_list, family, plist);
658 ft_init_font_list (void)
666 ft_font_list = mplist ();
667 MPLIST_DO (plist, mfont_freetype_path)
668 if (MPLIST_STRING_P (plist)
669 && (pathname = MPLIST_STRING (plist))
670 && stat (pathname, &buf) == 0)
672 if (S_ISREG (buf.st_mode))
673 ft_add_font (pathname);
674 else if (S_ISDIR (buf.st_mode))
676 DIR *dir = opendir (pathname);
680 int len = strlen (pathname);
683 while ((dp = readdir (dir)) != NULL)
685 SAFE_ALLOCA (path, len + strlen (dp->d_name) + 2);
686 strcpy (path, pathname);
688 strcpy (path + len + 1, dp->d_name);
698 /* Return 1 iff the font pointed by FT_INFO has all characters in
702 ft_has_char_list_p (MFontFT *ft_info, MPlist *char_list)
707 if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0, &ft_face))
709 MPLIST_DO (cl, char_list)
710 if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (cl)) == 0)
712 FT_Done_Face (ft_face);
713 return MPLIST_TAIL_P (cl);
716 /* Return ((FAMILY . FONT) ...) where FONT is a pointer to MFontFT
717 that supports characters in CHAR_LIST or MT. One of CHAR_LIST or
721 ft_list_char_list (MPlist *char_list, MText *mt)
723 MPlist *plist = NULL, *pl, *p;
726 ft_list_family (Mnil, 0);
730 int len = mtext_nchars (mt);
731 MText *extra = mtext_get_prop (mt, 0, Mtext);
732 int total_len = len + (extra ? mtext_nchars (extra) : 0);
735 char_list = mplist ();
736 for (i = 0; i < total_len; i++)
738 int c = (i < len ? mtext_ref_char (mt, i)
739 : mtext_ref_char (extra, i - len));
741 if (! mplist_find_by_value (char_list, (void *) c))
742 mplist_push (char_list, Minteger, (void *) c);
746 MPLIST_DO (pl, ft_font_list)
748 MPLIST_DO (p, MPLIST_PLIST (pl))
750 MFontFT *ft_info = MPLIST_VAL (p);
752 if (ft_has_char_list_p (ft_info, char_list))
754 MSymbol family = mfont_get_prop (&ft_info->font, Mfamily);
758 mplist_push (plist, family, ft_info);
763 M17N_OBJECT_UNREF (char_list);
766 #endif /* not HAVE_FONTCONFIG */
769 /* Return an element of ft_font_list for FAMILY. If FAMILY is Mnil,
770 scan all fonts and return ft_font_list. */
773 ft_list_family (MSymbol family, int check_generic)
776 #ifdef HAVE_FONTCONFIG
791 plist = ft_font_list = mplist ();
792 pattern = FcPatternCreate ();
793 os = FcObjectSetBuild (FC_FAMILY, NULL);
794 fs = FcFontList (fc_config, pattern, os);
795 for (i = 0; i < fs->nfont; i++)
797 if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
798 (FcChar8 **) &fam) != FcResultMatch)
800 STRDUP_LOWER (buf, bufsize, fam);
802 if (! mplist_find_by_key (ft_font_list, sym))
803 plist = mplist_add (plist, sym, NULL);
805 FcFontSetDestroy (fs);
806 FcObjectSetDestroy (os);
807 FcPatternDestroy (pattern);
812 if (! all_fonts_scaned)
814 MPLIST_DO (plist, ft_font_list)
816 if (! MPLIST_VAL (plist))
817 ft_list_family (MPLIST_KEY (plist), 0);
819 all_fonts_scaned = 1;
824 plist = mplist_find_by_key (ft_font_list, family);
827 if (! MPLIST_VAL (plist))
829 fam = MSYMBOL_NAME (family);
830 pattern = FcPatternCreate ();
831 FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *) fam);
832 os = FcObjectSetBuild (FC_FOUNDRY, FC_WEIGHT, FC_SLANT, FC_WIDTH,
833 FC_PIXEL_SIZE, FC_LANG, FC_CHARSET, FC_FILE,
835 fs = FcFontList (fc_config, pattern, os);
837 for (i = 0; i < fs->nfont; i++)
839 MFontFT *ft_info = fc_gen_font (fs->fonts[i], fam);
840 p = mplist_add (p, ft_info->font.file, ft_info);
842 MPLIST_VAL (plist) = pl;
843 FcFontSetDestroy (fs);
844 FcObjectSetDestroy (os);
845 FcPatternDestroy (pattern);
848 else if (check_generic
849 && (generic = msymbol_get (family, Mgeneric_family)) != Mnil)
851 /* Check if FAMILY is a geneneric family (e.g. `serif'). */
854 if (family != generic)
855 plist = ft_list_family (generic, 1);
858 fam = MSYMBOL_NAME (family);
860 mplist_push (ft_font_list, family, plist);
861 pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, fam, NULL);
862 FcConfigSubstitute (fc_config, pattern, FcMatchPattern);
865 if (FcPatternGetString (pattern, FC_FAMILY, i, &fam8)
868 STRDUP_LOWER (buf, bufsize, (char *) fam8);
869 family = msymbol (buf);
870 if (msymbol_get (family, Mgeneric_family))
872 pl = ft_list_family (family, 0);
875 MPLIST_DO (pl, MPLIST_PLIST (pl))
876 plist = mplist_add (plist, Mt, MPLIST_VAL (pl));
878 plist = ft_font_list;
883 /* Check if there exist an alias. */
885 plist = mplist_add (ft_font_list, family, pl);
887 pattern = FcPatternBuild (NULL,
888 FC_FAMILY, FcTypeString, MSYMBOL_NAME (family),
890 FcConfigSubstitute (fc_config, pattern, FcMatchPattern);
892 for (i = 0; FcPatternGetString (pattern, FC_FAMILY, i,
893 (FcChar8 **) &fam) == FcResultMatch;
897 /* The last one is a generic family. */
900 FcPattern *pat = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, fam,
903 FcConfigSubstitute (fc_config, pat, FcMatchPattern);
904 for (j = 0; FcPatternGetString (pat, FC_FAMILY, j,
905 (FcChar8 **) &fam) == FcResultMatch;
908 /* Now we know that the last J fonts in PATTERN are from
909 generic font, and the first one is not available. So,
910 the remaining ones are aliases. */
912 for (i = 1; i < j; i++)
914 FcPatternGetString (pattern, FC_FAMILY, i, (FcChar8 **) &fam);
915 STRDUP_LOWER (buf, bufsize, fam);
917 p = MPLIST_PLIST (ft_list_family (sym, 0));
918 if (! MPLIST_TAIL_P (p))
920 mplist_push (pl, Mt, MPLIST_VAL (p));
925 #else /* not HAVE_FONTCONFIG */
927 if (! all_fonts_scaned)
929 ft_init_font_list ();
930 all_fonts_scaned = 1;
933 plist = ft_font_list;
936 plist = mplist_find_by_key (ft_font_list, family);
938 plist = mplist_push (ft_font_list, family, mplist ());
940 #endif /* not HAVE_FONTCONFIG */
946 ft_list_language (MSymbol language)
948 MPlist *plist = NULL;
951 if (! ft_language_list)
952 ft_language_list = mplist ();
953 else if ((plist = mplist_find_by_key (ft_language_list, language)))
954 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
956 mt = mlanguage_text (language);
958 #ifdef HAVE_FONTCONFIG
960 FcPattern *pattern = NULL;
961 FcCharSet *cs = NULL;
962 FcLangSet *ls = NULL;
964 if (! (pattern = FcPatternCreate ()))
967 if (mt && mtext_nchars (mt) > 0)
969 cs = fc_build_charset (NULL, mt);
970 if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs))
975 if (! (ls = FcLangSetCreate ()))
977 if (! FcLangSetAdd (ls, (FcChar8 *) MSYMBOL_NAME (language))
978 || ! FcPatternAddLangSet (pattern, FC_LANG, ls))
982 plist = fc_list_pattern (pattern);
984 if (cs) FcCharSetDestroy (cs);
985 if (ls) FcLangSetDestroy (ls);
986 if (pattern) FcPatternDestroy (pattern);
988 #else /* not HAVE_FONTCONFIG */
989 if (mt && mtext_nchars (mt) > 0)
990 plist = ft_list_char_list (NULL, mt);
991 #endif /* not HAVE_FONTCONFIG */
993 mplist_push (ft_language_list, language, plist);
998 ft_list_script (MSymbol script)
1000 MPlist *plist = NULL;
1003 if (! ft_script_list)
1004 ft_script_list = mplist ();
1005 else if ((plist = mplist_find_by_key (ft_script_list, script)))
1006 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
1008 char_list = mscript__char_list (script);
1010 #ifdef HAVE_FONTCONFIG
1013 FcPattern *pattern = NULL;
1016 if (! (pattern = FcPatternCreate ()))
1018 cs = fc_build_charset (char_list, NULL);
1019 if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs))
1021 plist = fc_list_pattern (pattern);
1023 if (cs) FcCharSetDestroy (cs);
1024 if (pattern) FcPatternDestroy (pattern);
1026 #else /* not HAVE_FONTCONFIG */
1028 plist = ft_list_char_list (char_list, NULL);
1029 #endif /* not HAVE_FONTCONFIG */
1031 mplist_push (ft_script_list, script, plist);
1036 ft_check_otf (MFontFT *ft_info, MFontCapability *cap, FT_Face ft_face)
1039 if (ft_info->otf == invalid_otf)
1043 #if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
1045 ft_info->otf = OTF_open_ft_face (ft_face);
1048 ft_info->otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
1051 ft_info->otf = invalid_otf;
1055 if (cap->features[MFONT_OTT_GSUB].nfeatures
1056 && cap->features[MFONT_OTT_GSUB].tags[0]
1057 && (OTF_check_features
1059 cap->script_tag, cap->langsys_tag,
1060 cap->features[MFONT_OTT_GSUB].tags,
1061 cap->features[MFONT_OTT_GSUB].nfeatures) != 1))
1063 if (cap->features[MFONT_OTT_GPOS].nfeatures
1064 && cap->features[MFONT_OTT_GPOS].tags[0]
1065 && (OTF_check_features
1067 cap->script_tag, cap->langsys_tag,
1068 cap->features[MFONT_OTT_GPOS].tags,
1069 cap->features[MFONT_OTT_GPOS].nfeatures) != 1))
1072 #else /* not HAVE_OTF */
1074 #endif /* not HAVE_OTF */
1078 ft_check_language (MFontFT *ft_info, MSymbol language, FT_Face ft_face)
1082 int ft_face_allocaed = 0;
1086 #ifdef HAVE_FONTCONFIG
1087 if (ft_info->langset
1088 && (FcLangSetHasLang (ft_info->langset,
1089 (FcChar8 *) MSYMBOL_NAME (language))
1090 != FcLangDifferentLang))
1092 #endif /* HAVE_FONTCONFIG */
1094 mt = mlanguage_text (language);
1095 if (! mt || mtext_nchars (mt) == 0)
1100 char *filename = MSYMBOL_NAME (ft_info->font.file);
1102 if (FT_New_Face (ft_library, filename, 0, &ft_face))
1104 ft_face_allocaed = 1;
1107 len = mtext_nchars (mt);
1108 extra = mtext_get_prop (mt, 0, Mtext);
1109 total_len = len + (extra ? mtext_nchars (extra) : 0);
1111 for (i = 0; i < total_len; i++)
1113 int c = (i < len ? mtext_ref_char (mt, i)
1114 : mtext_ref_char (extra, i - len));
1116 #ifdef HAVE_FONTCONFIG
1117 if (ft_info->charset
1118 && FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcFalse)
1120 #endif /* HAVE_FONTCONFIG */
1121 if (FT_Get_Char_Index (ft_face, (FT_ULong) c) == 0)
1125 if (ft_face_allocaed)
1126 FT_Done_Face (ft_face);
1128 return (i == total_len ? 0 : -1);
1132 ft_check_script (MFontFT *ft_info, MSymbol script, FT_Face ft_face)
1134 MPlist *char_list = mscript__char_list (script);
1138 #ifdef HAVE_FONTCONFIG
1139 if (ft_info->charset)
1141 MPLIST_DO (char_list, char_list)
1142 if (FcCharSetHasChar (ft_info->charset,
1143 (FcChar32) MPLIST_INTEGER (char_list)) == FcFalse)
1147 #endif /* HAVE_FONTCONFIG */
1149 int ft_face_allocaed = 0;
1153 char *filename = MSYMBOL_NAME (ft_info->font.file);
1155 if (FT_New_Face (ft_library, filename, 0, &ft_face))
1157 ft_face_allocaed = 1;
1160 MPLIST_DO (char_list, char_list)
1161 if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (char_list))
1164 if (ft_face_allocaed)
1165 FT_Done_Face (ft_face);
1168 return (MPLIST_TAIL_P (char_list) ? 0 : -1);
1171 static MPlist *ft_default_list;
1176 if (ft_default_list)
1177 return ft_default_list;
1178 ft_default_list = mplist ();
1179 #ifdef HAVE_FONTCONFIG
1181 FcPattern *pat = FcPatternCreate ();
1187 FcConfigSubstitute (fc_config, pat, FcMatchPattern);
1188 for (i = 0; FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
1194 STRDUP_LOWER (buf, bufsize, (char *) fam);
1195 family = msymbol (buf);
1196 if (msymbol_get (family, Mgeneric_family))
1198 plist = MPLIST_PLIST (ft_list_family (family, 0));
1199 MPLIST_DO (plist, plist)
1200 mplist_add (ft_default_list, family, MPLIST_VAL (plist));
1203 #else /* not HAVE_FONTCONFIG */
1207 MPLIST_DO (plist, ft_list_family (Mnil, 0))
1209 pl = MPLIST_PLIST (plist);
1210 if (! MPLIST_TAIL_P (pl))
1211 mplist_add (ft_default_list, MPLIST_KEY (plist), pl);
1214 #endif /* not HAVE_FONTCONFIG */
1215 return ft_default_list;
1219 static MPlist *ft_capability_list;
1222 ft_list_capability (MSymbol capability)
1224 MFontCapability *cap;
1225 MPlist *plist = NULL, *pl;
1227 if (! ft_capability_list)
1228 ft_capability_list = mplist ();
1229 else if ((plist = mplist_find_by_key (ft_capability_list, capability)))
1230 return (MPLIST_VAL (plist) ? MPLIST_VAL (plist) : NULL);
1232 cap = mfont__get_capability (capability);
1234 if (cap && cap->language != Mnil)
1236 plist = ft_list_language (cap->language);
1239 plist = mplist_copy (plist);
1242 if (cap && cap->script != Mnil)
1246 plist = ft_list_script (cap->script);
1249 plist = mplist_copy (plist);
1253 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1255 if (ft_check_script (MPLIST_VAL (pl), cap->script, NULL) < 0)
1258 pl = MPLIST_NEXT (pl);
1262 if (cap->script_tag)
1264 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1266 if (ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0)
1269 pl = MPLIST_NEXT (pl);
1273 if (MPLIST_TAIL_P (plist))
1275 M17N_OBJECT_UNREF (plist);
1280 mplist_push (ft_capability_list, capability, plist);
1286 ft_list_file (MSymbol filename)
1288 MPlist *plist = NULL;
1291 ft_file_list = mplist ();
1292 else if ((plist = mplist_find_by_key (ft_file_list, filename)))
1293 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
1295 #ifdef HAVE_FONTCONFIG
1297 FcPattern *pattern = FcPatternCreate ();
1301 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) MSYMBOL_NAME (filename));
1302 os = FcObjectSetBuild (FC_FAMILY, NULL);
1303 fs = FcFontList (fc_config, pattern, os);
1310 if (FcPatternGetString (fs->fonts[0], FC_FAMILY, 0,
1311 (FcChar8 **) &fam) == FcResultMatch)
1316 STRDUP_LOWER (buf, bufsize, fam);
1317 family = msymbol (buf);
1318 pl = ft_list_family (family, 0);
1319 MPLIST_DO (pl, MPLIST_PLIST (pl))
1321 MFontFT *ft_info = MPLIST_VAL (pl);
1323 if (ft_info->font.file == filename)
1326 mplist_add (plist, family, ft_info);
1333 #else /* not HAVE_FONTCONFIG */
1337 MPLIST_DO (pl, ft_list_family (Mnil, 0))
1339 MPLIST_DO (p, MPLIST_PLIST (pl))
1341 MFontFT *ft_info = MPLIST_VAL (pl);
1343 if (ft_info->font.file == filename)
1346 mplist_add (plist, MPLIST_KEY (pl), ft_info);
1354 #endif /* not HAVE_FONTCONFIG */
1356 mplist_push (ft_file_list, filename, plist);
1360 /* The FreeType font driver function SELECT. */
1363 ft_select (MFrame *frame, MFont *font, int limited_size)
1365 MFont *found = NULL;
1366 #ifdef HAVE_FONTCONFIG
1369 int check_font_property = 1;
1371 if (font->file != Mnil)
1373 plist = ft_list_file (font->file);
1376 check_font_property = 0;
1380 MSymbol family = FONT_PROPERTY (font, MFONT_FAMILY);
1383 plist = MPLIST_PLIST (ft_list_family (family, 1));
1385 plist = ft_list_default ();
1386 if (MPLIST_TAIL_P (plist))
1390 plist = mplist_copy (plist);
1392 if (font->capability != Mnil)
1394 MFontCapability *cap = mfont__get_capability (font->capability);
1396 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1398 if (cap->script_tag && ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0)
1404 && ft_check_language (MPLIST_VAL (pl), cap->language, NULL) < 0)
1407 pl = MPLIST_NEXT (pl);
1411 if (check_font_property)
1413 MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT);
1414 MSymbol style = FONT_PROPERTY (font, MFONT_STYLE);
1415 MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH);
1416 MSymbol alternate_weight = Mnil;
1418 if (weight == Mnormal)
1419 alternate_weight = Mmedium;
1420 else if (weight == Mmedium)
1421 alternate_weight = Mnormal;
1422 if (weight != Mnil || style != Mnil || stretch != Mnil || font->size > 0)
1423 for (pl = plist; ! MPLIST_TAIL_P (pl); )
1425 ft_info = MPLIST_VAL (pl);
1427 && (weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT)
1428 && alternate_weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT)))
1430 && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE))
1432 && stretch != FONT_PROPERTY (&ft_info->font,
1435 && ft_info->font.size > 0
1436 && ft_info->font.size != font->size))
1439 pl = MPLIST_NEXT (pl);
1443 MPLIST_DO (pl, plist)
1445 font = MPLIST_VAL (plist);
1446 if (limited_size == 0
1448 || font->size <= limited_size)
1454 M17N_OBJECT_UNREF (plist);
1455 #endif /* HAVE_FONTCONFIG */
1460 static MRealizedFont *
1461 ft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1463 MFontFT *ft_info = (MFontFT *) font;
1464 int reg = spec->property[MFONT_REGISTRY];
1465 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
1466 MRealizedFontFT *ft_rfont;
1468 MPlist *plist, *charmap_list = NULL;
1473 /* non-scalable font */
1475 else if (spec->size)
1477 int ratio = mfont_resize_ratio (font);
1479 size = ratio == 100 ? spec->size : spec->size * ratio / 100;
1486 charmap_list = ((MRealizedFontFT *) rfont->info)->charmap_list;
1487 for (; rfont; rfont = rfont->next)
1488 if (rfont->font == font
1489 && (rfont->font->size ? rfont->font->size == size
1490 : rfont->spec.size == size)
1491 && rfont->spec.property[MFONT_REGISTRY] == reg
1492 && rfont->driver == &mfont__ft_driver)
1496 MDEBUG_DUMP (" [FONT-FT] opening ", "", mdebug_dump_font (&ft_info->font));
1498 if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0,
1501 font->type = MFONT_TYPE_FAILURE;
1502 MDEBUG_PRINT (" no (FT_New_Face)\n");
1506 M17N_OBJECT_REF (charmap_list);
1508 charmap_list = ft_get_charmaps (ft_face);
1509 if (registry == Mnil)
1510 registry = Municode_bmp;
1511 plist = mplist_find_by_key (charmap_list, registry);
1514 FT_Done_Face (ft_face);
1515 M17N_OBJECT_UNREF (charmap_list);
1516 MDEBUG_PRINT1 (" no (%s)\n", MSYMBOL_NAME (registry));
1519 charmap_index = (int) MPLIST_VAL (plist);
1520 if ((charmap_index >= 0
1521 && FT_Set_Charmap (ft_face, ft_face->charmaps[charmap_index]))
1522 || FT_Set_Pixel_Sizes (ft_face, 0, size / 10))
1524 FT_Done_Face (ft_face);
1525 M17N_OBJECT_UNREF (charmap_list);
1526 font->type = MFONT_TYPE_FAILURE;
1527 MDEBUG_PRINT1 (" no (size %d)\n", size);
1531 M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
1532 ft_rfont->ft_face = ft_face;
1533 ft_rfont->charmap_list = charmap_list;
1534 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
1535 rfont->spec = *font;
1536 rfont->spec.type = MFONT_TYPE_REALIZED;
1537 rfont->spec.property[MFONT_REGISTRY] = reg;
1538 rfont->spec.size = size;
1539 rfont->frame = frame;
1541 rfont->driver = &mfont__ft_driver;
1542 rfont->info = ft_rfont;
1543 rfont->fontp = ft_face;
1544 rfont->ascent = ft_face->size->metrics.ascender >> 6;
1545 rfont->descent = - ft_face->size->metrics.descender >> 6;
1546 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
1547 rfont->baseline_offset = 0;
1550 BDF_PropertyRec prop;
1552 if (! FT_IS_SCALABLE (ft_face)
1553 && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
1555 rfont->baseline_offset = prop.u.integer;
1556 rfont->ascent += prop.u.integer;
1557 rfont->descent -= prop.u.integer;
1560 #endif /* HAVE_FTBDF_H */
1561 if (FT_IS_SCALABLE (ft_face))
1562 rfont->average_width = 0;
1564 rfont->average_width = ft_face->available_sizes->width;
1565 rfont->next = MPLIST_VAL (frame->realized_font_list);
1566 MPLIST_VAL (frame->realized_font_list) = rfont;
1567 MDEBUG_PRINT (" ok\n");
1571 /* The FreeType font driver function FIND_METRIC. */
1574 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1577 FT_Face ft_face = rfont->fontp;
1578 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1580 for (; g != gend; g++)
1582 if (g->code == MCHAR_INVALID_CODE)
1584 if (FT_IS_SCALABLE (ft_face))
1586 unsigned unitsPerEm10 = ft_face->units_per_EM * 10;
1587 int size = rfont->spec.size;
1590 g->rbearing = ft_face->max_advance_width * size / unitsPerEm10;
1591 g->width = g->rbearing;
1592 g->ascent = ft_face->ascender * size / unitsPerEm10;
1593 g->descent = (- ft_face->descender) * size / unitsPerEm10;
1598 BDF_PropertyRec prop;
1599 #endif /* HAVE_FTBDF_H */
1602 g->rbearing = g->width = ft_face->available_sizes->width;
1604 if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
1606 g->ascent = prop.u.integer;
1607 FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
1608 g->descent = prop.u.integer;
1609 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET",
1612 g->ascent += prop.u.integer;
1613 g->descent -= prop.u.integer;
1617 #endif /* HAVE_FTBDF_H */
1619 g->ascent = ft_face->available_sizes->height;
1626 FT_Glyph_Metrics *metrics;
1628 FT_Load_Glyph (ft_face, (FT_UInt) g->code, FT_LOAD_DEFAULT);
1629 metrics = &ft_face->glyph->metrics;
1630 g->lbearing = (metrics->horiBearingX >> 6);
1631 g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
1632 g->width = metrics->horiAdvance >> 6;
1633 g->ascent = metrics->horiBearingY >> 6;
1634 g->descent = (metrics->height - metrics->horiBearingY) >> 6;
1636 g->ascent += rfont->baseline_offset;
1637 g->descent -= rfont->baseline_offset;
1642 ft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1644 MRealizedFont *rfont = NULL;
1645 MRealizedFontFT *ft_rfont;
1648 if (font->type == MFONT_TYPE_REALIZED)
1649 rfont = (MRealizedFont *) font;
1650 else if (font->type == MFONT_TYPE_OBJECT)
1652 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1653 rfont = rfont->next)
1654 if (rfont->font == font && rfont->driver == &mfont__ft_driver)
1658 #ifdef HAVE_FONTCONFIG
1659 MFontFT *ft_info = (MFontFT *) font;
1661 if (! ft_info->charset)
1663 FcPattern *pat = FcPatternBuild (NULL, FC_FILE, FcTypeString,
1664 MSYMBOL_NAME (font->file),
1666 FcObjectSet *os = FcObjectSetBuild (FC_CHARSET, NULL);
1667 FcFontSet *fs = FcFontList (fc_config, pat, os);
1670 && FcPatternGetCharSet (fs->fonts[0], FC_CHARSET, 0,
1671 &ft_info->charset) == FcResultMatch)
1672 ft_info->charset = FcCharSetCopy (ft_info->charset);
1674 ft_info->charset = FcCharSetCreate ();
1675 FcFontSetDestroy (fs);
1676 FcObjectSetDestroy (os);
1677 FcPatternDestroy (pat);
1679 return (FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcTrue);
1680 #else /* not HAVE_FONTCONFIG */
1681 rfont = ft_open (frame, font, spec, NULL);
1682 #endif /* not HAVE_FONTCONFIG */
1686 MFATAL (MERROR_FONT_FT);
1690 ft_rfont = rfont->info;
1691 idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code);
1695 /* The FreeType font driver function ENCODE_CHAR. */
1698 ft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1700 MRealizedFont *rfont;
1701 MRealizedFontFT *ft_rfont;
1704 if (font->type == MFONT_TYPE_REALIZED)
1705 rfont = (MRealizedFont *) font;
1706 else if (font->type == MFONT_TYPE_OBJECT)
1708 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1709 rfont = rfont->next)
1710 if (rfont->font == font && rfont->driver == &mfont__ft_driver)
1714 rfont = ft_open (frame, font, spec, NULL);
1720 MFATAL (MERROR_FONT_FT);
1722 ft_rfont = rfont->info;
1723 idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code);
1724 return (idx ? (unsigned) idx : MCHAR_INVALID_CODE);
1727 /* The FreeType font driver function RENDER. */
1729 #define NUM_POINTS 0x1000
1732 MDrawPoint points[NUM_POINTS];
1737 ft_render (MDrawWindow win, int x, int y,
1738 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1739 int reverse, MDrawRegion region)
1742 MRealizedFace *rface = from->rface;
1743 MFrame *frame = rface->frame;
1744 FT_Int32 load_flags = FT_LOAD_RENDER;
1747 MPointTable point_table[8];
1748 int baseline_offset;
1753 /* It is assured that the all glyphs in the current range use the
1754 same realized face. */
1755 ft_face = rface->rfont->fontp;
1756 baseline_offset = rface->rfont->baseline_offset;
1758 if (! gstring->anti_alias)
1760 #ifdef FT_LOAD_TARGET_MONO
1761 load_flags |= FT_LOAD_TARGET_MONO;
1763 load_flags |= FT_LOAD_MONOCHROME;
1767 for (i = 0; i < 8; i++)
1768 point_table[i].p = point_table[i].points;
1770 for (g = from; g < to; x += g++->width)
1774 MPointTable *ptable;
1778 FT_Load_Glyph (ft_face, (FT_UInt) g->code, load_flags);
1779 yoff = y - ft_face->glyph->bitmap_top + g->yoff;
1780 bmp = ft_face->glyph->bitmap.buffer;
1781 width = ft_face->glyph->bitmap.width;
1782 pitch = ft_face->glyph->bitmap.pitch;
1783 if (! gstring->anti_alias)
1788 if (gstring->anti_alias)
1789 for (i = 0; i < ft_face->glyph->bitmap.rows;
1790 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
1792 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
1793 for (j = 0; j < width; j++, xoff++)
1795 intensity = bmp[j] >> 5;
1798 ptable = point_table + intensity;
1799 ptable->p->x = xoff;
1800 ptable->p->y = yoff - baseline_offset;
1802 if (ptable->p - ptable->points == NUM_POINTS)
1804 (*frame->driver->draw_points)
1806 reverse ? 7 - intensity : intensity,
1807 ptable->points, NUM_POINTS, region);
1808 ptable->p = ptable->points;
1814 for (i = 0; i < ft_face->glyph->bitmap.rows;
1815 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
1817 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
1818 for (j = 0; j < width; j++, xoff++)
1820 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
1823 ptable = point_table;
1824 ptable->p->x = xoff;
1825 ptable->p->y = yoff - baseline_offset;
1827 if (ptable->p - ptable->points == NUM_POINTS)
1829 (*frame->driver->draw_points) (frame, win, rface,
1831 ptable->points, NUM_POINTS, region);
1832 ptable->p = ptable->points;
1839 if (gstring->anti_alias)
1841 for (i = 1; i < 8; i++)
1842 if (point_table[i].p != point_table[i].points)
1843 (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i,
1844 point_table[i].points,
1845 point_table[i].p - point_table[i].points, region);
1849 if (point_table[0].p != point_table[0].points)
1850 (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7,
1851 point_table[0].points,
1852 point_table[0].p - point_table[0].points, region);
1857 ft_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
1859 MPlist *pl = NULL, *p;
1861 MPlist *file_list = NULL;
1862 MPlist *family_list = NULL, *capability_list = NULL;
1863 MSymbol registry = Mnil;
1865 MDEBUG_DUMP (" [FONT-FT] listing ", "", mdebug_dump_font (font));
1871 registry = FONT_PROPERTY (font, MFONT_REGISTRY);
1872 if (registry != Mnil && registry != Miso8859_1)
1874 char *reg = MSYMBOL_NAME (registry);
1876 if (strncmp (reg, "unicode-", 8)
1877 && strncmp (reg, "apple-roman", 11)
1878 && (reg[0] < '0' || reg[0] > '9' || reg[1] != '-'))
1882 if (font->file != Mnil
1883 && ! (file_list = ft_list_file (font->file)))
1885 family = FONT_PROPERTY (font, MFONT_FAMILY);
1887 && (family_list = MPLIST_PLIST (ft_list_family (family, 1)))
1888 && MPLIST_TAIL_P (family_list))
1890 if (font->capability != Mnil)
1892 capability_list = ft_list_capability (font->capability);
1893 if (! capability_list || MPLIST_TAIL_P (capability_list))
1898 if (! file_list && ! family_list && ! capability_list)
1900 /* No restriction. Get all fonts. */
1902 MPLIST_DO (family_list, ft_list_family (Mnil, 0))
1904 MPLIST_DO (p, MPLIST_PLIST (family_list))
1905 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1913 mplist_push (pl, MPLIST_KEY (file_list), MPLIST_VAL (file_list));
1918 for (p = pl; ! MPLIST_TAIL_P (p);)
1920 if (mplist_find_by_value (family_list, MPLIST_VAL (p)))
1921 p = MPLIST_NEXT (p);
1928 MPLIST_DO (p, family_list)
1929 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1932 if (capability_list)
1935 for (p = pl; ! MPLIST_TAIL_P (p);)
1937 if (mplist_find_by_value (capability_list, MPLIST_VAL (p)))
1938 p = MPLIST_NEXT (p);
1945 MPLIST_DO (p, capability_list)
1946 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1952 && (font->property[MFONT_WEIGHT] + font->property[MFONT_STYLE]
1953 + font->property[MFONT_STRETCH] + font->size) > 0)
1955 MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT);
1956 MSymbol style = FONT_PROPERTY (font, MFONT_STYLE);
1957 MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH);
1958 int size = font->size;
1960 for (p = pl; ! MPLIST_TAIL_P (p); )
1962 MFontFT *ft_info = MPLIST_VAL (p);
1965 && weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT))
1967 && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE))
1969 && stretch != FONT_PROPERTY (&ft_info->font,
1972 && ft_info->font.size > 0
1973 && ft_info->font.size != size))
1976 p = MPLIST_NEXT (p);
1982 mplist_push (plist, MPLIST_KEY (p), MPLIST_VAL (p));
1984 if (maxnum && maxnum <= num)
1987 M17N_OBJECT_UNREF (pl);
1990 MDEBUG_PRINT1 (" %d found\n", num);
1995 ft_list_family_names (MFrame *frame, MPlist *plist)
2001 #ifdef HAVE_FONTCONFIG
2002 fc_init_font_list ();
2003 #else /* not HAVE_FONTCONFIG */
2004 ft_init_font_list ();
2005 #endif /* not HAVE_FONTCONFIG */
2008 MPLIST_DO (pl, ft_font_list)
2010 MSymbol family = MPLIST_KEY (pl);
2013 #ifdef HAVE_FONTCONFIG
2014 if (msymbol_get (family, Mgeneric_family) != Mnil)
2016 #endif /* HAVE_FONTCONFIG */
2017 MPLIST_DO (p, plist)
2019 MSymbol sym = MPLIST_SYMBOL (p);
2023 if (strcmp (MSYMBOL_NAME (sym), MSYMBOL_NAME (family)) > 0)
2025 mplist_push (p, Msymbol, family);
2029 if (MPLIST_TAIL_P (p))
2030 mplist_push (p, Msymbol, family);
2035 ft_check_capability (MRealizedFont *rfont, MSymbol capability)
2037 MFontFT *ft_info = (MFontFT *) rfont->font;
2038 MRealizedFontFT *ft_rfont = rfont->info;
2039 MFontCapability *cap = mfont__get_capability (capability);
2041 if (cap->script != Mnil
2042 && ft_check_script (ft_info, cap->script, ft_rfont->ft_face) < 0)
2044 if (cap->language != Mnil
2045 && ft_check_language (ft_info, cap->language, ft_rfont->ft_face) < 0)
2047 if (cap->script_tag && ft_check_otf (ft_info, cap, ft_rfont->ft_face) < 0)
2052 static MRealizedFont *
2053 ft_encapsulate (MFrame *frame, MSymbol data_type, void *data)
2056 MRealizedFont *rfont;
2057 MRealizedFontFT *ft_rfont;
2060 if (data_type == Mfontconfig)
2062 #ifdef HAVE_FONTCONFIG
2063 FcPattern *pattern = data;
2065 if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &ft_face)
2068 ft_info = fc_gen_font (pattern, NULL);
2069 #else /* not HAVE_FONTCONFIG */
2071 #endif /* not HAVE_FONTCONFIG */
2073 else if (data_type == Mfreetype)
2076 ft_info = ft_gen_font (ft_face);
2081 M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
2082 ft_rfont->ft_face = ft_face;
2083 ft_rfont->face_encapsulated = 1;
2085 MDEBUG_DUMP (" [FONT-FT] encapsulating ", (char *) ft_face->family_name,);
2087 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
2088 rfont->font = (MFont *) ft_info;
2089 rfont->info = ft_rfont;
2090 rfont->fontp = ft_face;
2091 rfont->driver = &mfont__ft_driver;
2092 rfont->spec = ft_info->font;
2093 rfont->spec.type = MFONT_TYPE_REALIZED;
2094 rfont->frame = frame;
2095 rfont->ascent = ft_face->size->metrics.ascender >> 6;
2096 rfont->descent = - ft_face->size->metrics.descender >> 6;
2097 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
2098 rfont->baseline_offset = 0;
2101 BDF_PropertyRec prop;
2103 if (! FT_IS_SCALABLE (ft_face)
2104 && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
2106 rfont->baseline_offset = prop.u.integer;
2107 rfont->ascent += prop.u.integer;
2108 rfont->descent -= prop.u.integer;
2111 #endif /* HAVE_FTBDF_H */
2112 if (FT_IS_SCALABLE (ft_face))
2113 rfont->average_width = 0;
2115 rfont->average_width = ft_face->available_sizes->width;
2116 rfont->next = MPLIST_VAL (frame->realized_font_list);
2117 MPLIST_VAL (frame->realized_font_list) = rfont;
2123 ft_close (MRealizedFont *rfont)
2125 if (! rfont->encapsulating)
2128 M17N_OBJECT_UNREF (rfont->info);
2136 MFontDriver mfont__ft_driver =
2137 { ft_select, ft_open, ft_find_metric, ft_has_char, ft_encode_char,
2138 ft_render, ft_list, ft_list_family_names, ft_check_capability,
2139 ft_encapsulate, ft_close };
2146 if (FT_Init_FreeType (&ft_library) != 0)
2147 MERROR (MERROR_FONT_FT, -1);
2149 for (i = 0; i < ft_to_prop_size; i++)
2150 ft_to_prop[i].len = strlen (ft_to_prop[i].ft_style);
2152 Mmedium = msymbol ("medium");
2154 Mnull = msymbol ("");
2156 M0[0] = msymbol ("0-0");
2157 M0[1] = msymbol ("0-1");
2158 M0[2] = msymbol ("0-2");
2159 M0[3] = msymbol ("0-3");
2160 M0[4] = msymbol ("0-4");
2161 M3_1 = msymbol ("3-1");
2162 M1_0 = msymbol ("1-0");
2164 #ifdef HAVE_FONTCONFIG
2165 for (i = 0; i < (sizeof (fc_all_table) / sizeof fc_all_table[0]); i++)
2167 FC_vs_M17N_font_prop *table = fc_all_table[i];
2170 for (j = 0; table[j].m17n_value; j++)
2171 table[j].sym = msymbol (table[j].m17n_value);
2172 table[j].sym = table[j - 1].sym;
2179 MSymbol serif, sans_serif, monospace;
2181 fc_config = FcInitLoadConfigAndFonts ();
2182 if (mfont_freetype_path)
2184 MPLIST_DO (plist, mfont_freetype_path)
2185 if (MPLIST_STRING_P (plist)
2186 && (pathname = MPLIST_STRING (plist))
2187 && stat (pathname, &buf) == 0)
2189 FcStrList *strlist = FcConfigGetFontDirs (fc_config);
2192 while ((dir = FcStrListNext (strlist)))
2193 if (strcmp ((char *) dir, pathname) == 0)
2196 FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname);
2197 FcStrListDone (strlist);
2200 Mgeneric_family = msymbol ("generic famly");
2201 serif = msymbol ("serif");
2202 msymbol_put (serif, Mgeneric_family, serif);
2203 sans_serif = msymbol ("sans-serif");
2204 msymbol_put (sans_serif, Mgeneric_family, sans_serif);
2205 msymbol_put (msymbol ("sans serif"), Mgeneric_family, sans_serif);
2206 msymbol_put (msymbol ("sans"), Mgeneric_family, sans_serif);
2207 monospace = msymbol ("monospace");
2208 msymbol_put (monospace, Mgeneric_family, monospace);
2209 msymbol_put (msymbol ("mono"), Mgeneric_family, monospace);
2221 if (ft_default_list)
2223 M17N_OBJECT_UNREF (ft_default_list);
2224 ft_default_list = NULL;
2229 MPLIST_DO (plist, ft_font_list)
2231 if (MPLIST_VAL (plist))
2232 MPLIST_DO (p, MPLIST_VAL (plist))
2234 if (MPLIST_KEY (p) != Mt)
2235 free_ft_info (MPLIST_VAL (p));
2237 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2239 M17N_OBJECT_UNREF (ft_font_list);
2240 ft_font_list = NULL;
2242 if (ft_language_list)
2244 MPLIST_DO (plist, ft_language_list)
2245 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2246 M17N_OBJECT_UNREF (ft_language_list);
2247 ft_language_list = NULL;
2252 MPLIST_DO (plist, ft_script_list)
2253 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2254 M17N_OBJECT_UNREF (ft_script_list);
2255 ft_script_list = NULL;
2258 if (ft_capability_list)
2260 MPLIST_DO (plist, ft_capability_list)
2261 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2262 M17N_OBJECT_UNREF (ft_capability_list);
2263 ft_capability_list = NULL;
2268 MPLIST_DO (plist, ft_file_list)
2269 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2270 M17N_OBJECT_UNREF (ft_file_list);
2271 ft_file_list = NULL;
2274 FT_Done_FreeType (ft_library);
2275 #ifdef HAVE_FONTCONFIG
2276 FcConfigDestroy (fc_config);
2278 #endif /* HAVE_FONTCONFIG */
2279 all_fonts_scaned = 0;
2282 #ifdef HAVE_FONTCONFIG
2285 mfont__ft_parse_name (const char *name, MFont *font)
2287 FcPattern *pat = FcNameParse ((FcChar8 *) name);
2296 if (FcPatternGetString (pat, FC_FOUNDRY, 0, &str) == FcResultMatch)
2298 STRDUP_LOWER (buf, bufsize, (char *) str);
2299 mfont__set_property (font, MFONT_FOUNDRY, msymbol (buf));
2301 if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
2303 STRDUP_LOWER (buf, bufsize, (char *) str);
2304 mfont__set_property (font, MFONT_FAMILY, msymbol (buf));
2306 if (FcPatternGetInteger (pat, FC_WEIGHT, 0, &val) == FcResultMatch)
2307 mfont__set_property (font, MFONT_WEIGHT,
2308 fc_decode_prop (val, fc_weight_table,
2309 fc_weight_table_size));
2310 if (FcPatternGetInteger (pat, FC_SLANT, 0, &val) == FcResultMatch)
2311 mfont__set_property (font, MFONT_STYLE,
2312 fc_decode_prop (val, fc_slant_table,
2313 fc_slant_table_size));
2314 if (FcPatternGetInteger (pat, FC_WIDTH, 0, &val) == FcResultMatch)
2315 mfont__set_property (font, MFONT_STRETCH,
2316 fc_decode_prop (val, fc_width_table,
2317 fc_width_table_size));
2318 if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
2319 font->size = size * 10 + 0.5;
2320 else if (FcPatternGetDouble (pat, FC_SIZE, 0, &size) == FcResultMatch)
2321 font->size = - (size * 10 + 0.5);
2322 if (FcPatternGetString (pat, FC_FILE, 0, &str) == FcResultMatch)
2324 font->file = msymbol ((char *) str);
2326 mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
2327 font->type = MFONT_TYPE_SPEC;
2328 FcPatternDestroy (pat);
2333 mfont__ft_unparse_name (MFont *font)
2335 FcPattern *pat = fc_get_pattern (font);
2336 char *name = (char *) FcNameUnparse (pat);
2338 FcPatternDestroy (pat);
2341 #endif /* HAVE_FONTCONFIG */
2346 #define DEVICE_DELTA(table, size) \
2347 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
2348 ? (table).DeltaValue[(size) - (table).StartSize] \
2352 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
2353 unsigned code, int size, int *x, int *y)
2355 if (anchor->AnchorFormat == 2)
2357 FT_Outline *outline;
2358 int ap = anchor->f.f1.AnchorPoint;
2360 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
2361 outline = &ft_face->glyph->outline;
2362 if (ap < outline->n_points)
2364 *x = outline->points[ap].x;
2365 *y = outline->points[ap].y;
2368 else if (anchor->AnchorFormat == 3)
2370 if (anchor->f.f2.XDeviceTable.offset)
2371 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size);
2372 if (anchor->f.f2.YDeviceTable.offset)
2373 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size);
2378 mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
2379 MFontCapability *cap)
2381 int len = to - from;
2382 MGlyph *g = MGLYPH (from);
2384 MRealizedFont *rfont;
2387 OTF_GlyphString otf_gstring;
2389 char *script, *langsys;
2390 char *gsub_features, *gpos_features;
2396 otf_gstring.glyphs = NULL;
2397 rfont = g->rface->rfont;
2398 ft_info = (MFontFT *) rfont->font;
2399 if (ft_info->otf == invalid_otf)
2404 MRealizedFontFT *ft_rfont = rfont->info;
2406 #if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
2407 otf = OTF_open_ft_face (ft_rfont->ft_face);
2409 otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
2413 ft_info->otf = invalid_otf;
2418 if (OTF_get_table (otf, "head") < 0)
2421 ft_info->otf = invalid_otf;
2425 if (cap->script_tag)
2427 script = alloca (5);
2428 OTF_tag_name (cap->script_tag, script);
2432 if (cap->langsys_tag)
2434 langsys = alloca (5);
2435 OTF_tag_name (cap->langsys_tag, langsys);
2439 gsub_features = cap->features[MFONT_OTT_GSUB].str;
2440 if (gsub_features && OTF_check_table (otf, "GSUB") < 0)
2441 gsub_features = NULL;
2442 gpos_features = cap->features[MFONT_OTT_GPOS].str;
2443 if (gpos_features && OTF_check_table (otf, "GPOS") < 0)
2444 gpos_features = NULL;
2446 otf_gstring.size = otf_gstring.used = len;
2447 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
2448 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
2449 for (i = 0, need_cmap = 0; i < len; i++)
2451 if (gstring->glyphs[from + i].otf_encoded)
2453 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
2454 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
2458 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
2463 && OTF_drive_cmap (otf, &otf_gstring) < 0)
2466 OTF_drive_gdef (otf, &otf_gstring);
2467 gidx = gstring->used;
2471 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
2474 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
2476 MGlyph temp = *(MGLYPH (from + otfg->f.index.from));
2479 temp.combining_code = 0;
2482 temp.code = otfg->glyph_id;
2483 temp.otf_encoded = 1;
2488 temp.otf_encoded = 0;
2490 temp.to = MGLYPH (from + otfg->f.index.to)->to;
2491 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
2495 for (i = 0; i < len; i++)
2497 MGlyph temp = gstring->glyphs[from + i];
2499 if (otf_gstring.glyphs[i].glyph_id)
2501 temp.code = otf_gstring.glyphs[i].glyph_id;
2502 temp.otf_encoded = 1;
2504 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
2507 (rfont->driver->find_metric) (rfont, gstring, gidx, gstring->used);
2513 MGlyph *base = NULL, *mark = NULL;
2515 if (OTF_check_features (otf, 1,
2516 cap->script_tag, cap->langsys_tag,
2517 cap->features[MFONT_OTT_GPOS].tags,
2518 cap->features[MFONT_OTT_GPOS].nfeatures) != 1
2519 || (OTF_drive_gpos (otf, &otf_gstring, script, langsys,
2520 gpos_features) < 0))
2523 u = otf->head->unitsPerEm;
2524 size10 = rfont->spec.size;
2527 for (i = 0, otfg = otf_gstring.glyphs, g = MGLYPH (gidx);
2528 i < otf_gstring.used; i++, otfg++, g++)
2532 if (! otfg->glyph_id)
2534 switch (otfg->positioning_type)
2540 int format = otfg->f.f1.format;
2542 if (format & OTF_XPlacement)
2543 g->xoff = otfg->f.f1.value->XPlacement * size10 / u / 10;
2544 if (format & OTF_XPlaDevice)
2545 g->xoff += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, size);
2546 if (format & OTF_YPlacement)
2547 g->yoff = - (otfg->f.f1.value->YPlacement * size10 / u / 10);
2548 if (format & OTF_YPlaDevice)
2549 g->yoff -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, size);
2550 if (format & OTF_XAdvance)
2551 g->width += otfg->f.f1.value->XAdvance * size10 / u / 10;
2552 if (format & OTF_XAdvDevice)
2553 g->width += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, size);
2557 /* Not yet supported. */
2563 goto label_adjust_anchor;
2564 default: /* i.e. case 6 */
2569 label_adjust_anchor:
2571 int base_x, base_y, mark_x, mark_y;
2573 base_x = otfg->f.f4.base_anchor->XCoordinate * size10 / u / 10;
2574 base_y = otfg->f.f4.base_anchor->YCoordinate * size10 / u / 10;
2575 mark_x = otfg->f.f4.mark_anchor->XCoordinate * size10 / u / 10;
2576 mark_y = otfg->f.f4.mark_anchor->YCoordinate * size10 / u / 10;
2578 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2579 adjust_anchor (otfg->f.f4.base_anchor, rfont->fontp,
2580 prev->code, size, &base_x, &base_y);
2581 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2582 adjust_anchor (otfg->f.f4.mark_anchor, rfont->fontp,
2583 g->code, size, &mark_x, &mark_y);
2584 g->xoff = prev->xoff + (base_x - prev->width) - mark_x;
2585 g->yoff = prev->yoff + mark_y - base_y;
2586 g->combining_code = MAKE_PRECOMPUTED_COMBINDING_CODE ();
2589 if (otfg->GlyphClass == OTF_GlyphClass0)
2591 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2597 free (otf_gstring.glyphs);
2601 for (i = 0; i < len; i++)
2603 MGlyph *g = MGLYPH (from + i);
2605 if (! g->otf_encoded)
2607 g->code = rfont->driver->encode_char (gstring->frame, (MFont *) rfont,
2613 rfont->driver->find_metric (rfont, gstring, from, to);
2614 for (i = 0; i < len; i++)
2616 MGlyph temp = gstring->glyphs[from + i];
2617 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
2619 if (otf_gstring.glyphs)
2620 free (otf_gstring.glyphs);
2626 mfont__ft_decode_otf (MGlyph *g)
2628 MFontFT *ft_info = (MFontFT *) g->rface->rfont->font;
2629 int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
2631 return (c ? c : -1);
2634 #endif /* HAVE_OTF */
2636 #endif /* HAVE_FREETYPE */