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); \
144 static MPlist *ft_list_family (MSymbol, int);
147 free_ft_rfont (void *object)
149 MRealizedFontFT *ft_rfont = object;
151 if (! ft_rfont->face_encapsulated)
153 M17N_OBJECT_UNREF (ft_rfont->charmap_list);
154 FT_Done_Face (ft_rfont->ft_face);
160 free_ft_info (MFontFT *ft_info)
163 if (ft_info->otf && ft_info->otf != invalid_otf)
164 OTF_close (ft_info->otf);
165 #endif /* HAVE_OTF */
166 #ifdef HAVE_FONTCONFIG
167 if (ft_info->langset)
168 FcLangSetDestroy (ft_info->langset);
169 if (ft_info->charset)
170 FcCharSetDestroy (ft_info->charset);
171 #endif /* HAVE_FONTCONFIG */
176 ft_get_charmaps (FT_Face ft_face)
178 MPlist *plist = mplist ();
179 int unicode_bmp = -1, unicode_full = -1;
182 mplist_add (plist, Mt, (void *) -1);
183 for (i = 0; i < ft_face->num_charmaps; i++)
185 MSymbol registry = Mnil;
187 if (ft_face->charmaps[i]->platform_id == 0)
189 if (ft_face->charmaps[i]->encoding_id <= 4)
190 registry = M0[ft_face->charmaps[i]->encoding_id], unicode_bmp = i;
191 if (ft_face->charmaps[i]->encoding_id == 4)
192 unicode_bmp = unicode_full = i;
194 else if (ft_face->charmaps[i]->platform_id == 3)
196 if (ft_face->charmaps[i]->encoding_id == 1)
197 registry = M3_1, unicode_bmp = i;
198 else if (ft_face->charmaps[i]->encoding_id == 10)
199 unicode_bmp = unicode_full = i;
201 else if (ft_face->charmaps[i]->platform_id == 1
202 && ft_face->charmaps[i]->encoding_id == 0)
205 mplist_add (plist, Mapple_roman, (void *) i);
207 if (registry == Mnil)
209 char registry_buf[16];
211 sprintf (registry_buf, "%d-%d",
212 ft_face->charmaps[i]->platform_id,
213 ft_face->charmaps[i]->encoding_id);
214 registry = msymbol (registry_buf);
216 mplist_add (plist, registry, (void *) i);
218 if (unicode_full >= 0)
219 mplist_add (plist, Municode_full, (void *) unicode_full);
220 if (unicode_bmp >= 0)
224 mplist_add (plist, Municode_bmp, (void *) unicode_bmp);
225 FT_Set_Charmap (ft_face, ft_face->charmaps[unicode_bmp]);
226 for (i = 0x21; i < 0x7F && FT_Get_Char_Index (ft_face, i) > 0; i++);
229 for (i = 0xC0; i < 0x100 && FT_Get_Char_Index (ft_face, i) > 0; i++);
231 mplist_add (plist, Miso8859_1, (void *) unicode_bmp);
239 ft_gen_font (FT_Face ft_face)
249 if (FT_IS_SCALABLE (ft_face))
250 size = ft_face->size->metrics.y_ppem;
251 else if (ft_face->num_fixed_sizes == 0)
254 size = ft_face->available_sizes[0].height;
256 MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT);
257 font = &ft_info->font;
258 STRDUP_LOWER (buf, bufsize, ft_face->family_name);
259 family = msymbol (buf);
260 mfont__set_property (font, MFONT_FAMILY, family);
261 mfont__set_property (font, MFONT_WEIGHT, Mmedium);
262 mfont__set_property (font, MFONT_STYLE, Mr);
263 mfont__set_property (font, MFONT_STRETCH, Mnormal);
264 mfont__set_property (font, MFONT_ADSTYLE, Mnull);
265 mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
266 font->size = size * 10;
267 font->type = MFONT_TYPE_OBJECT;
268 font->source = MFONT_SOURCE_FT;
271 stylename = ft_face->style_name;
276 for (i = 0; i < ft_to_prop_size; i++)
277 if (! strncasecmp (ft_to_prop[i].ft_style, stylename,
280 mfont__set_property (font, ft_to_prop[i].prop,
281 msymbol (ft_to_prop[i].val));
282 stylename += ft_to_prop[i].len;
285 if (i == ft_to_prop_size)
287 char *p1 = stylename + 1;
290 while (*p1 >= 'a' && *p1 <= 'z') p1++;
291 sym = msymbol__with_len (stylename, p1 - stylename);
292 for (i = MFONT_WEIGHT; i <= MFONT_STRETCH; i++)
293 if (msymbol_get (sym, mfont__property_table[i].property))
295 mfont__set_property (font, i, sym);
300 while (*stylename && ! isalpha (*stylename))
306 #ifdef HAVE_FONTCONFIG
313 } FC_vs_M17N_font_prop;
315 static FC_vs_M17N_font_prop fc_weight_table[] =
316 { { FC_WEIGHT_THIN, "thin" },
317 { FC_WEIGHT_ULTRALIGHT, "extralight" },
318 { FC_WEIGHT_LIGHT, "light" },
319 #ifdef FC_WEIGHT_BOOK
320 { FC_WEIGHT_BOOK, "book" },
321 #endif /* FC_WEIGHT_BOOK */
322 { FC_WEIGHT_REGULAR, "normal" },
323 { FC_WEIGHT_NORMAL, "normal" },
324 { FC_WEIGHT_MEDIUM, "medium" },
325 { FC_WEIGHT_DEMIBOLD, "demibold" },
326 { FC_WEIGHT_BOLD, "bold" },
327 { FC_WEIGHT_EXTRABOLD, "extrabold" },
328 { FC_WEIGHT_BLACK, "black" },
329 { FC_WEIGHT_HEAVY, "heavy" },
330 { FC_WEIGHT_MEDIUM, NULL } };
331 int fc_weight_table_size =
332 sizeof fc_weight_table / sizeof (FC_vs_M17N_font_prop);
334 static FC_vs_M17N_font_prop fc_slant_table[] =
335 { { FC_SLANT_ROMAN, "r" },
336 { FC_SLANT_ITALIC, "i" },
337 { FC_SLANT_OBLIQUE, "o" },
338 { FC_SLANT_ROMAN, NULL } };
339 int fc_slant_table_size =
340 sizeof fc_slant_table / sizeof (FC_vs_M17N_font_prop);
342 static FC_vs_M17N_font_prop fc_width_table[] =
343 { { FC_WIDTH_ULTRACONDENSED, "ultracondensed" },
344 { FC_WIDTH_EXTRACONDENSED, "extracondensed" },
345 { FC_WIDTH_CONDENSED, "condensed" },
346 { FC_WIDTH_SEMICONDENSED, "semicondensed" },
347 { FC_WIDTH_NORMAL, "normal" },
348 { FC_WIDTH_SEMIEXPANDED, "semiexpanded" },
349 { FC_WIDTH_EXPANDED, "expanded" },
350 { FC_WIDTH_EXTRAEXPANDED, "extraexpanded" },
351 { FC_WIDTH_ULTRAEXPANDED, "ultraexpanded" },
352 { FC_WIDTH_NORMAL, NULL } };
353 int fc_width_table_size =
354 sizeof fc_width_table / sizeof (FC_vs_M17N_font_prop);
357 static FC_vs_M17N_font_prop *fc_all_table[] =
358 { fc_weight_table, fc_slant_table, fc_width_table };
361 fc_decode_prop (int val, FC_vs_M17N_font_prop *table, int size)
365 if (val < table[i].fc_value)
367 for (i--; i >= 0; i--)
368 if (val > table[i].fc_value)
374 for (; i < size; i++)
375 if (val <= table[i].fc_value)
382 fc_encode_prop (MSymbol sym, FC_vs_M17N_font_prop *table)
386 for (i = 0; table[i].m17n_value; i++)
387 if (table[i].sym == sym)
389 return table[i].fc_value;
393 fc_get_pattern (MFont *font)
395 FcPattern *pat = FcPatternCreate ();
396 MSymbol sym, weight, style, stretch;
399 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FOUNDRY)) != Mnil)
400 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) MSYMBOL_NAME (sym));
401 if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FAMILY)) != Mnil)
402 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) MSYMBOL_NAME (sym));
403 if ((weight = (MSymbol) FONT_PROPERTY (font, MFONT_WEIGHT)) != Mnil)
404 FcPatternAddInteger (pat, FC_WEIGHT,
405 fc_encode_prop (weight, fc_weight_table));
406 if ((style = (MSymbol) FONT_PROPERTY (font, MFONT_STYLE)) != Mnil)
407 FcPatternAddInteger (pat, FC_SLANT,
408 fc_encode_prop (style, fc_slant_table));
409 if ((stretch = (MSymbol) FONT_PROPERTY (font, MFONT_STRETCH)) != Mnil)
410 FcPatternAddInteger (pat, FC_WIDTH,
411 fc_encode_prop (stretch, fc_width_table));
414 double size = font->size;
415 FcPatternAddDouble (pat, FC_PIXEL_SIZE, size / 10);
417 else if (font->size < 0)
419 double size = - font->size;
420 FcPatternAddDouble (pat, FC_SIZE, size / 10);
426 fc_parse_pattern (FcPattern *pat, char *family, MFontFT *ft_info)
436 MFont *font = &ft_info->font;
439 if (FcPatternGetString (pat, FC_FOUNDRY, 0, &str) == FcResultMatch)
441 STRDUP_LOWER (buf, bufsize, (char *) str);
442 mfont__set_property (font, MFONT_FOUNDRY, msymbol (buf));
445 mfont__set_property (font, MFONT_FAMILY, msymbol (family));
446 else if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
448 STRDUP_LOWER (buf, bufsize, (char *) str);
449 mfont__set_property (font, MFONT_FAMILY, msymbol (buf));
451 if (FcPatternGetInteger (pat, FC_WEIGHT, 0, &val) == FcResultMatch)
453 sym = fc_decode_prop (val, fc_weight_table, fc_weight_table_size);
454 mfont__set_property (font, MFONT_WEIGHT, sym);
456 if (FcPatternGetInteger (pat, FC_SLANT, 0, &val) == FcResultMatch)
458 sym = fc_decode_prop (val, fc_slant_table, fc_slant_table_size);
459 mfont__set_property (font, MFONT_STYLE, sym);
461 if (FcPatternGetInteger (pat, FC_WIDTH, 0, &val) == FcResultMatch)
463 sym = fc_decode_prop (val, fc_width_table, fc_width_table_size);
464 mfont__set_property (font, MFONT_STRETCH, sym);
466 if (FcPatternGetLangSet (pat, FC_LANG, 0, &ls) == FcResultMatch)
468 if (FcLangSetHasLang (ls, (FcChar8 *) "ja") != FcLangDifferentLang
469 || FcLangSetHasLang (ls, (FcChar8 *) "zh") != FcLangDifferentLang
470 || FcLangSetHasLang (ls, (FcChar8 *) "ko") != FcLangDifferentLang)
471 font->for_full_width = 1;
472 ft_info->langset = FcLangSetCopy (ls);
474 if (FcPatternGetCharSet (pat, FC_CHARSET, 0, &cs) == FcResultMatch)
475 ft_info->charset = FcCharSetCopy (cs);
477 mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
478 font->type = MFONT_TYPE_SPEC;
479 font->source = MFONT_SOURCE_FT;
480 if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
481 font->size = size * 10;
482 if (FcPatternGetString (pat, FC_FILE, 0, &str) == FcResultMatch)
483 font->file = msymbol ((char *) str);
488 fc_gen_font (FcPattern *pat, char *family)
492 MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT);
493 fc_parse_pattern (pat, family, ft_info);
494 ft_info->font.type = MFONT_TYPE_OBJECT;
499 fc_init_font_list (void)
501 FcPattern *pattern = FcPatternCreate ();
502 FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, NULL);
503 FcFontSet *fs = FcFontList (fc_config, pattern, os);
504 MPlist *plist = mplist ();
509 ft_font_list = plist;
510 for (i = 0; i < fs->nfont; i++)
514 if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
515 (FcChar8 **) &fam) != FcResultMatch)
517 STRDUP_LOWER (buf, bufsize, fam);
518 plist = mplist_add (plist, msymbol (buf), NULL);
520 FcFontSetDestroy (fs);
521 FcObjectSetDestroy (os);
522 FcPatternDestroy (pattern);
526 fc_list_pattern (FcPattern *pattern)
528 FcObjectSet *os = NULL;
529 FcFontSet *fs = NULL;
530 MSymbol last_family = Mnil;
531 MPlist *plist = NULL, *pl = NULL;
536 if (! (os = FcObjectSetBuild (FC_FAMILY, FC_FILE, NULL)))
538 if (! (fs = FcFontList (fc_config, pattern, os)))
541 for (i = 0; i < fs->nfont; i++)
543 MSymbol family, file;
544 char *fam, *filename;
547 if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
548 (FcChar8 **) &fam) != FcResultMatch)
550 if (FcPatternGetString (fs->fonts[i], FC_FILE, 0,
551 (FcChar8 **) &filename) != FcResultMatch)
553 STRDUP_LOWER (buf, bufsize, fam);
554 family = msymbol (buf);
555 file = msymbol (filename);
556 if (family != last_family)
558 pl = MPLIST_PLIST (ft_list_family (family, 0));
559 last_family = family;
561 ft_info = mplist_get (pl, file);
566 mplist_add (plist, family, ft_info);
571 if (fs) FcFontSetDestroy (fs);
572 if (os) FcObjectSetDestroy (os);
576 /* Return FcCharSet object built from CHAR_LIST or MT. In the latter
577 case, it is assured that the M-text contains at least one
581 fc_build_charset (MPlist *char_list, MText *mt)
583 FcCharSet *cs = FcCharSetCreate ();
589 for (; ! MPLIST_TAIL_P (char_list); char_list = MPLIST_NEXT (char_list))
590 if (! FcCharSetAddChar (cs, (FcChar32) MPLIST_INTEGER (char_list)))
592 FcCharSetDestroy (cs);
600 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
601 if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i)))
603 FcCharSetDestroy (cs);
606 if (mtext_nchars (mt) > 0
607 && (mt = mtext_get_prop (mt, 0, Mtext)))
608 for (i = mtext_nchars (mt) - 1; i >= 0; i--)
609 if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i)))
611 FcCharSetDestroy (cs);
618 #else /* not HAVE_FONTCONFIG */
621 ft_add_font (char *filename)
634 if (FT_New_Face (ft_library, filename, 0, &ft_face) != 0)
636 ft_info = ft_gen_font (ft_face);
637 FT_Done_Face (ft_face);
641 font = &ft_info->font;
642 font->file = msymbol (filename);
644 plist = mplist_find_by_key (ft_font_list, family);
646 mplist_push (MPLIST_PLIST (plist), font->file, ft_info);
650 mplist_add (plist, font->file, ft_info);
651 plist = mplist_push (ft_font_list, family, plist);
657 ft_init_font_list (void)
665 ft_font_list = mplist ();
666 MPLIST_DO (plist, mfont_freetype_path)
667 if (MPLIST_STRING_P (plist)
668 && (pathname = MPLIST_STRING (plist))
669 && stat (pathname, &buf) == 0)
671 if (S_ISREG (buf.st_mode))
672 ft_add_font (pathname);
673 else if (S_ISDIR (buf.st_mode))
675 DIR *dir = opendir (pathname);
679 int len = strlen (pathname);
682 while ((dp = readdir (dir)) != NULL)
684 SAFE_ALLOCA (path, len + strlen (dp->d_name) + 2);
685 strcpy (path, pathname);
687 strcpy (path + len + 1, dp->d_name);
697 /* Return 1 iff the font pointed by FT_INFO has all characters in
701 ft_has_char_list_p (MFontFT *ft_info, MPlist *char_list)
706 if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0, &ft_face))
708 MPLIST_DO (cl, char_list)
709 if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (cl)) == 0)
711 FT_Done_Face (ft_face);
712 return MPLIST_TAIL_P (cl);
715 /* Return ((FAMILY . FONT) ...) where FONT is a pointer to MFontFT
716 that supports characters in CHAR_LIST or MT. One of CHAR_LIST or
720 ft_list_char_list (MPlist *char_list, MText *mt)
722 MPlist *plist = NULL, *pl, *p;
725 ft_list_family (Mnil, 0);
729 int len = mtext_nchars (mt);
730 MText *extra = mtext_get_prop (mt, 0, Mtext);
731 int total_len = len + (extra ? mtext_nchars (extra) : 0);
734 char_list = mplist ();
735 for (i = 0; i < total_len; i++)
737 int c = (i < len ? mtext_ref_char (mt, i)
738 : mtext_ref_char (extra, i - len));
740 if (! mplist_find_by_value (char_list, (void *) c))
741 mplist_push (char_list, Minteger, (void *) c);
745 MPLIST_DO (pl, ft_font_list)
747 MPLIST_DO (p, MPLIST_PLIST (pl))
749 MFontFT *ft_info = MPLIST_VAL (p);
751 if (ft_has_char_list_p (ft_info, char_list))
753 MSymbol family = mfont_get_prop (&ft_info->font, Mfamily);
757 mplist_push (plist, family, ft_info);
762 M17N_OBJECT_UNREF (char_list);
765 #endif /* not HAVE_FONTCONFIG */
768 /* Return an element of ft_font_list for FAMILY. If FAMILY is Mnil,
769 scan all fonts and return ft_font_list. */
772 ft_list_family (MSymbol family, int check_generic)
775 #ifdef HAVE_FONTCONFIG
790 plist = ft_font_list = mplist ();
791 pattern = FcPatternCreate ();
792 os = FcObjectSetBuild (FC_FAMILY, NULL);
793 fs = FcFontList (fc_config, pattern, os);
794 for (i = 0; i < fs->nfont; i++)
796 if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
797 (FcChar8 **) &fam) != FcResultMatch)
799 STRDUP_LOWER (buf, bufsize, fam);
801 if (! mplist_find_by_key (ft_font_list, sym))
802 plist = mplist_add (plist, sym, NULL);
804 FcFontSetDestroy (fs);
805 FcObjectSetDestroy (os);
806 FcPatternDestroy (pattern);
811 if (! all_fonts_scaned)
813 MPLIST_DO (plist, ft_font_list)
815 if (! MPLIST_VAL (plist))
816 ft_list_family (MPLIST_KEY (plist), 0);
818 all_fonts_scaned = 1;
823 plist = mplist_find_by_key (ft_font_list, family);
826 if (! MPLIST_VAL (plist))
828 fam = MSYMBOL_NAME (family);
829 pattern = FcPatternCreate ();
830 FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *) fam);
831 os = FcObjectSetBuild (FC_FOUNDRY, FC_WEIGHT, FC_SLANT, FC_WIDTH,
832 FC_PIXEL_SIZE, FC_LANG, FC_CHARSET, FC_FILE,
834 fs = FcFontList (fc_config, pattern, os);
836 for (i = 0; i < fs->nfont; i++)
838 MFontFT *ft_info = fc_gen_font (fs->fonts[i], fam);
839 p = mplist_add (p, ft_info->font.file, ft_info);
841 MPLIST_VAL (plist) = pl;
842 FcFontSetDestroy (fs);
843 FcObjectSetDestroy (os);
844 FcPatternDestroy (pattern);
847 else if (check_generic
848 && (generic = msymbol_get (family, Mgeneric_family)) != Mnil)
850 /* Check if FAMILY is a geneneric family (e.g. `serif'). */
853 if (family != generic)
854 plist = ft_list_family (generic, 1);
857 fam = MSYMBOL_NAME (family);
859 mplist_push (ft_font_list, family, plist);
860 pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, fam, NULL);
861 FcConfigSubstitute (fc_config, pattern, FcMatchPattern);
864 if (FcPatternGetString (pattern, FC_FAMILY, i, &fam8)
867 STRDUP_LOWER (buf, bufsize, (char *) fam8);
868 family = msymbol (buf);
869 if (msymbol_get (family, Mgeneric_family))
871 pl = ft_list_family (family, 0);
874 MPLIST_DO (pl, MPLIST_PLIST (pl))
875 plist = mplist_add (plist, Mt, MPLIST_VAL (pl));
877 plist = ft_font_list;
882 /* Check if there exist an alias. */
884 plist = mplist_add (ft_font_list, family, pl);
886 pattern = FcPatternBuild (NULL,
887 FC_FAMILY, FcTypeString, MSYMBOL_NAME (family),
889 FcConfigSubstitute (fc_config, pattern, FcMatchPattern);
891 for (i = 0; FcPatternGetString (pattern, FC_FAMILY, i,
892 (FcChar8 **) &fam) == FcResultMatch;
896 /* The last one is a generic family. */
899 FcPattern *pat = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, fam,
902 FcConfigSubstitute (fc_config, pat, FcMatchPattern);
903 for (j = 0; FcPatternGetString (pat, FC_FAMILY, j,
904 (FcChar8 **) &fam) == FcResultMatch;
907 /* Now we know that the last J fonts in PATTERN are from
908 generic font, and the first one is not available. So,
909 the remaining ones are aliases. */
911 for (i = 1; i < j; i++)
913 FcPatternGetString (pattern, FC_FAMILY, i, (FcChar8 **) &fam);
914 STRDUP_LOWER (buf, bufsize, fam);
916 p = MPLIST_PLIST (ft_list_family (sym, 0));
917 if (! MPLIST_TAIL_P (p))
919 mplist_push (pl, Mt, MPLIST_VAL (p));
924 #else /* not HAVE_FONTCONFIG */
926 if (! all_fonts_scaned)
928 ft_init_font_list ();
929 all_fonts_scaned = 1;
932 plist = ft_font_list;
935 plist = mplist_find_by_key (ft_font_list, family);
937 plist = mplist_push (ft_font_list, family, mplist ());
939 #endif /* not HAVE_FONTCONFIG */
945 ft_list_language (MSymbol language)
947 MPlist *plist = NULL;
950 if (! ft_language_list)
951 ft_language_list = mplist ();
952 else if ((plist = mplist_find_by_key (ft_language_list, language)))
953 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
955 mt = mlanguage_text (language);
957 #ifdef HAVE_FONTCONFIG
959 FcPattern *pattern = NULL;
960 FcCharSet *cs = NULL;
961 FcLangSet *ls = NULL;
963 if (! (pattern = FcPatternCreate ()))
966 if (mt && mtext_nchars (mt) > 0)
968 cs = fc_build_charset (NULL, mt);
969 if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs))
974 if (! (ls = FcLangSetCreate ()))
976 if (! FcLangSetAdd (ls, (FcChar8 *) MSYMBOL_NAME (language))
977 || ! FcPatternAddLangSet (pattern, FC_LANG, ls))
981 plist = fc_list_pattern (pattern);
983 if (cs) FcCharSetDestroy (cs);
984 if (ls) FcLangSetDestroy (ls);
985 if (pattern) FcPatternDestroy (pattern);
987 #else /* not HAVE_FONTCONFIG */
988 if (mt && mtext_nchars (mt) > 0)
989 plist = ft_list_char_list (NULL, mt);
990 #endif /* not HAVE_FONTCONFIG */
992 mplist_push (ft_language_list, language, plist);
997 ft_list_script (MSymbol script)
999 MPlist *plist = NULL;
1002 if (! ft_script_list)
1003 ft_script_list = mplist ();
1004 else if ((plist = mplist_find_by_key (ft_script_list, script)))
1005 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
1007 char_list = mscript__char_list (script);
1009 #ifdef HAVE_FONTCONFIG
1012 FcPattern *pattern = NULL;
1015 if (! (pattern = FcPatternCreate ()))
1017 cs = fc_build_charset (char_list, NULL);
1018 if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs))
1020 plist = fc_list_pattern (pattern);
1022 if (cs) FcCharSetDestroy (cs);
1023 if (pattern) FcPatternDestroy (pattern);
1025 #else /* not HAVE_FONTCONFIG */
1027 plist = ft_list_char_list (char_list, NULL);
1028 #endif /* not HAVE_FONTCONFIG */
1030 mplist_push (ft_script_list, script, plist);
1035 ft_check_otf (MFontFT *ft_info, MFontCapability *cap, FT_Face ft_face)
1038 if (ft_info->otf == invalid_otf)
1042 #if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
1044 ft_info->otf = OTF_open_ft_face (ft_face);
1047 ft_info->otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
1050 ft_info->otf = invalid_otf;
1054 if (cap->features[MFONT_OTT_GSUB].nfeatures
1055 && cap->features[MFONT_OTT_GSUB].tags[0]
1056 && (OTF_check_features
1058 cap->script_tag, cap->langsys_tag,
1059 cap->features[MFONT_OTT_GSUB].tags,
1060 cap->features[MFONT_OTT_GSUB].nfeatures) != 1))
1062 if (cap->features[MFONT_OTT_GPOS].nfeatures
1063 && cap->features[MFONT_OTT_GPOS].tags[0]
1064 && (OTF_check_features
1066 cap->script_tag, cap->langsys_tag,
1067 cap->features[MFONT_OTT_GPOS].tags,
1068 cap->features[MFONT_OTT_GPOS].nfeatures) != 1))
1071 #else /* not HAVE_OTF */
1073 #endif /* not HAVE_OTF */
1077 ft_check_language (MFontFT *ft_info, MSymbol language, FT_Face ft_face)
1081 int ft_face_allocaed = 0;
1085 #ifdef HAVE_FONTCONFIG
1086 if (ft_info->langset
1087 && (FcLangSetHasLang (ft_info->langset,
1088 (FcChar8 *) MSYMBOL_NAME (language))
1089 != FcLangDifferentLang))
1091 #endif /* HAVE_FONTCONFIG */
1093 mt = mlanguage_text (language);
1094 if (! mt || mtext_nchars (mt) == 0)
1099 char *filename = MSYMBOL_NAME (ft_info->font.file);
1101 if (FT_New_Face (ft_library, filename, 0, &ft_face))
1103 ft_face_allocaed = 1;
1106 len = mtext_nchars (mt);
1107 extra = mtext_get_prop (mt, 0, Mtext);
1108 total_len = len + (extra ? mtext_nchars (extra) : 0);
1110 for (i = 0; i < total_len; i++)
1112 int c = (i < len ? mtext_ref_char (mt, i)
1113 : mtext_ref_char (extra, i - len));
1115 #ifdef HAVE_FONTCONFIG
1116 if (ft_info->charset
1117 && FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcFalse)
1119 #endif /* HAVE_FONTCONFIG */
1120 if (FT_Get_Char_Index (ft_face, (FT_ULong) c) == 0)
1124 if (ft_face_allocaed)
1125 FT_Done_Face (ft_face);
1127 return (i == total_len ? 0 : -1);
1131 ft_check_script (MFontFT *ft_info, MSymbol script, FT_Face ft_face)
1133 MPlist *char_list = mscript__char_list (script);
1137 #ifdef HAVE_FONTCONFIG
1138 if (ft_info->charset)
1140 MPLIST_DO (char_list, char_list)
1141 if (FcCharSetHasChar (ft_info->charset,
1142 (FcChar32) MPLIST_INTEGER (char_list)) == FcFalse)
1146 #endif /* HAVE_FONTCONFIG */
1148 int ft_face_allocaed = 0;
1152 char *filename = MSYMBOL_NAME (ft_info->font.file);
1154 if (FT_New_Face (ft_library, filename, 0, &ft_face))
1156 ft_face_allocaed = 1;
1159 MPLIST_DO (char_list, char_list)
1160 if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (char_list))
1163 if (ft_face_allocaed)
1164 FT_Done_Face (ft_face);
1167 return (MPLIST_TAIL_P (char_list) ? 0 : -1);
1170 static MPlist *ft_default_list;
1175 if (ft_default_list)
1176 return ft_default_list;
1177 ft_default_list = mplist ();
1178 #ifdef HAVE_FONTCONFIG
1180 FcPattern *pat = FcPatternCreate ();
1186 FcConfigSubstitute (fc_config, pat, FcMatchPattern);
1187 for (i = 0; FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
1193 STRDUP_LOWER (buf, bufsize, (char *) fam);
1194 family = msymbol (buf);
1195 if (msymbol_get (family, Mgeneric_family))
1197 plist = MPLIST_PLIST (ft_list_family (family, 0));
1198 MPLIST_DO (plist, plist)
1199 mplist_add (ft_default_list, family, MPLIST_VAL (plist));
1202 #else /* not HAVE_FONTCONFIG */
1206 MPLIST_DO (plist, ft_list_family (Mnil, 0))
1208 pl = MPLIST_PLIST (plist);
1209 if (! MPLIST_TAIL_P (pl))
1210 mplist_add (ft_default_list, MPLIST_KEY (plist), pl);
1213 #endif /* not HAVE_FONTCONFIG */
1214 return ft_default_list;
1218 static MPlist *ft_capability_list;
1221 ft_list_capability (MSymbol capability)
1223 MFontCapability *cap;
1224 MPlist *plist = NULL, *pl;
1226 if (! ft_capability_list)
1227 ft_capability_list = mplist ();
1228 else if ((plist = mplist_find_by_key (ft_capability_list, capability)))
1229 return (MPLIST_VAL (plist) ? MPLIST_VAL (plist) : NULL);
1231 cap = mfont__get_capability (capability);
1233 if (cap && cap->language != Mnil)
1235 plist = ft_list_language (cap->language);
1238 plist = mplist_copy (plist);
1241 if (cap && cap->script != Mnil)
1245 plist = ft_list_script (cap->script);
1248 plist = mplist_copy (plist);
1252 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1254 if (ft_check_script (MPLIST_VAL (pl), cap->script, NULL) < 0)
1257 pl = MPLIST_NEXT (pl);
1261 if (cap->script_tag)
1263 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1265 if (ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0)
1268 pl = MPLIST_NEXT (pl);
1272 if (MPLIST_TAIL_P (plist))
1274 M17N_OBJECT_UNREF (plist);
1279 mplist_push (ft_capability_list, capability, plist);
1285 ft_list_file (MSymbol filename)
1287 MPlist *plist = NULL;
1290 ft_file_list = mplist ();
1291 else if ((plist = mplist_find_by_key (ft_file_list, filename)))
1292 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
1294 #ifdef HAVE_FONTCONFIG
1296 FcPattern *pattern = FcPatternCreate ();
1300 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) MSYMBOL_NAME (filename));
1301 os = FcObjectSetBuild (FC_FAMILY, NULL);
1302 fs = FcFontList (fc_config, pattern, os);
1309 if (FcPatternGetString (fs->fonts[0], FC_FAMILY, 0,
1310 (FcChar8 **) &fam) == FcResultMatch)
1315 STRDUP_LOWER (buf, bufsize, fam);
1316 family = msymbol (buf);
1317 pl = ft_list_family (family, 0);
1318 MPLIST_DO (pl, MPLIST_PLIST (pl))
1320 MFontFT *ft_info = MPLIST_VAL (pl);
1322 if (ft_info->font.file == filename)
1325 mplist_add (plist, family, ft_info);
1332 #else /* not HAVE_FONTCONFIG */
1336 MPLIST_DO (pl, ft_list_family (Mnil, 0))
1338 MPLIST_DO (p, MPLIST_PLIST (pl))
1340 MFontFT *ft_info = MPLIST_VAL (pl);
1342 if (ft_info->font.file == filename)
1345 mplist_add (plist, MPLIST_KEY (pl), ft_info);
1353 #endif /* not HAVE_FONTCONFIG */
1355 mplist_push (ft_file_list, filename, plist);
1359 /* The FreeType font driver function SELECT. */
1362 ft_select (MFrame *frame, MFont *font, int limited_size)
1364 MFont *found = NULL;
1365 #ifdef HAVE_FONTCONFIG
1368 int check_font_property = 1;
1370 if (font->file != Mnil)
1372 plist = ft_list_file (font->file);
1375 check_font_property = 0;
1379 MSymbol family = FONT_PROPERTY (font, MFONT_FAMILY);
1382 plist = MPLIST_PLIST (ft_list_family (family, 1));
1384 plist = ft_list_default ();
1385 if (MPLIST_TAIL_P (plist))
1389 plist = mplist_copy (plist);
1391 if (font->capability != Mnil)
1393 MFontCapability *cap = mfont__get_capability (font->capability);
1395 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1397 if (cap->script_tag && ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0)
1403 && ft_check_language (MPLIST_VAL (pl), cap->language, NULL) < 0)
1406 pl = MPLIST_NEXT (pl);
1410 if (check_font_property)
1412 MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT);
1413 MSymbol style = FONT_PROPERTY (font, MFONT_STYLE);
1414 MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH);
1415 MSymbol alternate_weight = Mnil;
1417 if (weight == Mnormal)
1418 alternate_weight = Mmedium;
1419 else if (weight == Mmedium)
1420 alternate_weight = Mnormal;
1421 if (weight != Mnil || style != Mnil || stretch != Mnil || font->size > 0)
1422 for (pl = plist; ! MPLIST_TAIL_P (pl); )
1424 ft_info = MPLIST_VAL (pl);
1426 && (weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT)
1427 && alternate_weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT)))
1429 && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE))
1431 && stretch != FONT_PROPERTY (&ft_info->font,
1434 && ft_info->font.size > 0
1435 && ft_info->font.size != font->size))
1438 pl = MPLIST_NEXT (pl);
1442 MPLIST_DO (pl, plist)
1444 font = MPLIST_VAL (plist);
1445 if (limited_size == 0
1447 || font->size <= limited_size)
1453 M17N_OBJECT_UNREF (plist);
1454 #endif /* HAVE_FONTCONFIG */
1459 static MRealizedFont *
1460 ft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1462 MFontFT *ft_info = (MFontFT *) font;
1463 int reg = spec->property[MFONT_REGISTRY];
1464 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
1465 MRealizedFontFT *ft_rfont;
1467 MPlist *plist, *charmap_list = NULL;
1472 /* non-scalable font */
1474 else if (spec->size)
1476 int ratio = mfont_resize_ratio (font);
1478 size = ratio == 100 ? spec->size : spec->size * ratio / 100;
1485 charmap_list = ((MRealizedFontFT *) rfont->info)->charmap_list;
1486 for (; rfont; rfont = rfont->next)
1487 if (rfont->font == font
1488 && (rfont->font->size ? rfont->font->size == size
1489 : rfont->spec.size == size)
1490 && rfont->spec.property[MFONT_REGISTRY] == reg
1491 && rfont->driver == &mfont__ft_driver)
1495 MDEBUG_DUMP (" [FONT-FT] opening ", "", mdebug_dump_font (&ft_info->font));
1497 if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0,
1500 font->type = MFONT_TYPE_FAILURE;
1501 MDEBUG_PRINT (" no (FT_New_Face)\n");
1505 M17N_OBJECT_REF (charmap_list);
1507 charmap_list = ft_get_charmaps (ft_face);
1508 if (registry == Mnil)
1509 registry = Municode_bmp;
1510 plist = mplist_find_by_key (charmap_list, registry);
1513 FT_Done_Face (ft_face);
1514 M17N_OBJECT_UNREF (charmap_list);
1515 MDEBUG_PRINT1 (" no (%s)\n", MSYMBOL_NAME (registry));
1518 charmap_index = (int) MPLIST_VAL (plist);
1519 if ((charmap_index >= 0
1520 && FT_Set_Charmap (ft_face, ft_face->charmaps[charmap_index]))
1521 || FT_Set_Pixel_Sizes (ft_face, 0, size / 10))
1523 FT_Done_Face (ft_face);
1524 M17N_OBJECT_UNREF (charmap_list);
1525 font->type = MFONT_TYPE_FAILURE;
1526 MDEBUG_PRINT1 (" no (size %d)\n", size);
1530 M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
1531 ft_rfont->ft_face = ft_face;
1532 ft_rfont->charmap_list = charmap_list;
1533 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
1534 rfont->spec = *font;
1535 rfont->spec.type = MFONT_TYPE_REALIZED;
1536 rfont->spec.property[MFONT_REGISTRY] = reg;
1537 rfont->spec.size = size;
1538 rfont->frame = frame;
1540 rfont->driver = &mfont__ft_driver;
1541 rfont->info = ft_rfont;
1542 rfont->fontp = ft_face;
1543 rfont->ascent = ft_face->size->metrics.ascender >> 6;
1544 rfont->descent = - ft_face->size->metrics.descender >> 6;
1545 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
1546 rfont->baseline_offset = 0;
1549 BDF_PropertyRec prop;
1551 if (! FT_IS_SCALABLE (ft_face)
1552 && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
1554 rfont->baseline_offset = prop.u.integer;
1555 rfont->ascent += prop.u.integer;
1556 rfont->descent -= prop.u.integer;
1559 #endif /* HAVE_FTBDF_H */
1560 if (FT_IS_SCALABLE (ft_face))
1561 rfont->average_width = 0;
1563 rfont->average_width = ft_face->available_sizes->width;
1564 rfont->next = MPLIST_VAL (frame->realized_font_list);
1565 MPLIST_VAL (frame->realized_font_list) = rfont;
1566 MDEBUG_PRINT (" ok\n");
1570 /* The FreeType font driver function FIND_METRIC. */
1573 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1576 FT_Face ft_face = rfont->fontp;
1577 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1579 for (; g != gend; g++)
1581 if (g->code == MCHAR_INVALID_CODE)
1583 if (FT_IS_SCALABLE (ft_face))
1585 unsigned unitsPerEm10 = ft_face->units_per_EM * 10;
1586 int size = rfont->spec.size;
1589 g->rbearing = ft_face->max_advance_width * size / unitsPerEm10;
1590 g->width = g->rbearing;
1591 g->ascent = ft_face->ascender * size / unitsPerEm10;
1592 g->descent = (- ft_face->descender) * size / unitsPerEm10;
1597 BDF_PropertyRec prop;
1598 #endif /* HAVE_FTBDF_H */
1601 g->rbearing = g->width = ft_face->available_sizes->width;
1603 if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
1605 g->ascent = prop.u.integer;
1606 FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
1607 g->descent = prop.u.integer;
1608 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET",
1611 g->ascent += prop.u.integer;
1612 g->descent -= prop.u.integer;
1616 #endif /* HAVE_FTBDF_H */
1618 g->ascent = ft_face->available_sizes->height;
1625 FT_Glyph_Metrics *metrics;
1627 FT_Load_Glyph (ft_face, (FT_UInt) g->code, FT_LOAD_DEFAULT);
1628 metrics = &ft_face->glyph->metrics;
1629 g->lbearing = (metrics->horiBearingX >> 6);
1630 g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
1631 g->width = metrics->horiAdvance >> 6;
1632 g->ascent = metrics->horiBearingY >> 6;
1633 g->descent = (metrics->height - metrics->horiBearingY) >> 6;
1635 g->ascent += rfont->baseline_offset;
1636 g->descent -= rfont->baseline_offset;
1641 ft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1643 MRealizedFont *rfont = NULL;
1644 MRealizedFontFT *ft_rfont;
1647 if (font->type == MFONT_TYPE_REALIZED)
1648 rfont = (MRealizedFont *) font;
1649 else if (font->type == MFONT_TYPE_OBJECT)
1651 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1652 rfont = rfont->next)
1653 if (rfont->font == font && rfont->driver == &mfont__ft_driver)
1657 #ifdef HAVE_FONTCONFIG
1658 MFontFT *ft_info = (MFontFT *) font;
1660 if (! ft_info->charset)
1662 FcPattern *pat = FcPatternBuild (NULL, FC_FILE, FcTypeString,
1663 MSYMBOL_NAME (font->file),
1665 FcObjectSet *os = FcObjectSetBuild (FC_CHARSET, NULL);
1666 FcFontSet *fs = FcFontList (fc_config, pat, os);
1669 && FcPatternGetCharSet (fs->fonts[0], FC_CHARSET, 0,
1670 &ft_info->charset) == FcResultMatch)
1671 ft_info->charset = FcCharSetCopy (ft_info->charset);
1673 ft_info->charset = FcCharSetCreate ();
1674 FcFontSetDestroy (fs);
1675 FcObjectSetDestroy (os);
1676 FcPatternDestroy (pat);
1678 return (FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcTrue);
1679 #else /* not HAVE_FONTCONFIG */
1680 rfont = ft_open (frame, font, spec, NULL);
1681 #endif /* not HAVE_FONTCONFIG */
1685 MFATAL (MERROR_FONT_FT);
1689 ft_rfont = rfont->info;
1690 idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code);
1694 /* The FreeType font driver function ENCODE_CHAR. */
1697 ft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1699 MRealizedFont *rfont;
1700 MRealizedFontFT *ft_rfont;
1703 if (font->type == MFONT_TYPE_REALIZED)
1704 rfont = (MRealizedFont *) font;
1705 else if (font->type == MFONT_TYPE_OBJECT)
1707 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1708 rfont = rfont->next)
1709 if (rfont->font == font && rfont->driver == &mfont__ft_driver)
1713 rfont = ft_open (frame, font, spec, NULL);
1719 MFATAL (MERROR_FONT_FT);
1721 ft_rfont = rfont->info;
1722 idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code);
1723 return (idx ? (unsigned) idx : MCHAR_INVALID_CODE);
1726 /* The FreeType font driver function RENDER. */
1728 #define NUM_POINTS 0x1000
1731 MDrawPoint points[NUM_POINTS];
1736 ft_render (MDrawWindow win, int x, int y,
1737 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1738 int reverse, MDrawRegion region)
1741 MRealizedFace *rface = from->rface;
1742 MFrame *frame = rface->frame;
1743 FT_Int32 load_flags = FT_LOAD_RENDER;
1746 MPointTable point_table[8];
1747 int baseline_offset;
1752 /* It is assured that the all glyphs in the current range use the
1753 same realized face. */
1754 ft_face = rface->rfont->fontp;
1755 baseline_offset = rface->rfont->baseline_offset;
1757 if (! gstring->anti_alias)
1759 #ifdef FT_LOAD_TARGET_MONO
1760 load_flags |= FT_LOAD_TARGET_MONO;
1762 load_flags |= FT_LOAD_MONOCHROME;
1766 for (i = 0; i < 8; i++)
1767 point_table[i].p = point_table[i].points;
1769 for (g = from; g < to; x += g++->width)
1773 MPointTable *ptable;
1777 FT_Load_Glyph (ft_face, (FT_UInt) g->code, load_flags);
1778 yoff = y - ft_face->glyph->bitmap_top + g->yoff;
1779 bmp = ft_face->glyph->bitmap.buffer;
1780 width = ft_face->glyph->bitmap.width;
1781 pitch = ft_face->glyph->bitmap.pitch;
1782 if (! gstring->anti_alias)
1787 if (gstring->anti_alias)
1788 for (i = 0; i < ft_face->glyph->bitmap.rows;
1789 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
1791 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
1792 for (j = 0; j < width; j++, xoff++)
1794 intensity = bmp[j] >> 5;
1797 ptable = point_table + intensity;
1798 ptable->p->x = xoff;
1799 ptable->p->y = yoff - baseline_offset;
1801 if (ptable->p - ptable->points == NUM_POINTS)
1803 (*frame->driver->draw_points)
1805 reverse ? 7 - intensity : intensity,
1806 ptable->points, NUM_POINTS, region);
1807 ptable->p = ptable->points;
1813 for (i = 0; i < ft_face->glyph->bitmap.rows;
1814 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
1816 xoff = x + ft_face->glyph->bitmap_left + g->xoff;
1817 for (j = 0; j < width; j++, xoff++)
1819 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
1822 ptable = point_table;
1823 ptable->p->x = xoff;
1824 ptable->p->y = yoff - baseline_offset;
1826 if (ptable->p - ptable->points == NUM_POINTS)
1828 (*frame->driver->draw_points) (frame, win, rface,
1830 ptable->points, NUM_POINTS, region);
1831 ptable->p = ptable->points;
1838 if (gstring->anti_alias)
1840 for (i = 1; i < 8; i++)
1841 if (point_table[i].p != point_table[i].points)
1842 (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i,
1843 point_table[i].points,
1844 point_table[i].p - point_table[i].points, region);
1848 if (point_table[0].p != point_table[0].points)
1849 (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7,
1850 point_table[0].points,
1851 point_table[0].p - point_table[0].points, region);
1856 ft_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
1858 MPlist *pl = NULL, *p;
1860 MPlist *file_list = NULL;
1861 MPlist *family_list = NULL, *capability_list = NULL;
1862 MSymbol registry = Mnil;
1864 MDEBUG_DUMP (" [FONT-FT] listing ", "", mdebug_dump_font (font));
1870 registry = FONT_PROPERTY (font, MFONT_REGISTRY);
1871 if (registry != Mnil && registry != Miso8859_1)
1873 char *reg = MSYMBOL_NAME (registry);
1875 if (strncmp (reg, "unicode-", 8)
1876 && strncmp (reg, "apple-roman", 11)
1877 && (reg[0] < '0' || reg[0] > '9' || reg[1] != '-'))
1881 if (font->file != Mnil
1882 && ! (file_list = ft_list_file (font->file)))
1884 family = FONT_PROPERTY (font, MFONT_FAMILY);
1886 && (family_list = MPLIST_PLIST (ft_list_family (family, 1)))
1887 && MPLIST_TAIL_P (family_list))
1889 if (font->capability != Mnil)
1891 capability_list = ft_list_capability (font->capability);
1892 if (! capability_list || MPLIST_TAIL_P (capability_list))
1897 if (! file_list && ! family_list && ! capability_list)
1899 /* No restriction. Get all fonts. */
1901 MPLIST_DO (family_list, ft_list_family (Mnil, 0))
1903 MPLIST_DO (p, MPLIST_PLIST (family_list))
1904 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1912 mplist_push (pl, MPLIST_KEY (file_list), MPLIST_VAL (file_list));
1917 for (p = pl; ! MPLIST_TAIL_P (p);)
1919 if (mplist_find_by_value (family_list, MPLIST_VAL (p)))
1920 p = MPLIST_NEXT (p);
1927 MPLIST_DO (p, family_list)
1928 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1931 if (capability_list)
1934 for (p = pl; ! MPLIST_TAIL_P (p);)
1936 if (mplist_find_by_value (capability_list, MPLIST_VAL (p)))
1937 p = MPLIST_NEXT (p);
1944 MPLIST_DO (p, capability_list)
1945 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1951 && (font->property[MFONT_WEIGHT] + font->property[MFONT_STYLE]
1952 + font->property[MFONT_STRETCH] + font->size) > 0)
1954 MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT);
1955 MSymbol style = FONT_PROPERTY (font, MFONT_STYLE);
1956 MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH);
1957 int size = font->size;
1959 for (p = pl; ! MPLIST_TAIL_P (p); )
1961 MFontFT *ft_info = MPLIST_VAL (p);
1964 && weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT))
1966 && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE))
1968 && stretch != FONT_PROPERTY (&ft_info->font,
1971 && ft_info->font.size > 0
1972 && ft_info->font.size != size))
1975 p = MPLIST_NEXT (p);
1981 mplist_push (plist, MPLIST_KEY (p), MPLIST_VAL (p));
1983 if (maxnum && maxnum <= num)
1986 M17N_OBJECT_UNREF (pl);
1989 MDEBUG_PRINT1 (" %d found\n", num);
1994 ft_list_family_names (MFrame *frame, MPlist *plist)
2000 #ifdef HAVE_FONTCONFIG
2001 fc_init_font_list ();
2002 #else /* not HAVE_FONTCONFIG */
2003 ft_init_font_list ();
2004 #endif /* not HAVE_FONTCONFIG */
2007 MPLIST_DO (pl, ft_font_list)
2009 MSymbol family = MPLIST_KEY (pl);
2012 #ifdef HAVE_FONTCONFIG
2013 if (msymbol_get (family, Mgeneric_family) != Mnil)
2015 #endif /* HAVE_FONTCONFIG */
2016 MPLIST_DO (p, plist)
2018 MSymbol sym = MPLIST_SYMBOL (p);
2022 if (strcmp (MSYMBOL_NAME (sym), MSYMBOL_NAME (family)) > 0)
2024 mplist_push (p, Msymbol, family);
2028 if (MPLIST_TAIL_P (p))
2029 mplist_push (p, Msymbol, family);
2034 ft_check_capability (MRealizedFont *rfont, MSymbol capability)
2036 MFontFT *ft_info = (MFontFT *) rfont->font;
2037 MRealizedFontFT *ft_rfont = rfont->info;
2038 MFontCapability *cap = mfont__get_capability (capability);
2040 if (cap->script != Mnil
2041 && ft_check_script (ft_info, cap->script, ft_rfont->ft_face) < 0)
2043 if (cap->language != Mnil
2044 && ft_check_language (ft_info, cap->language, ft_rfont->ft_face) < 0)
2046 if (cap->script_tag && ft_check_otf (ft_info, cap, ft_rfont->ft_face) < 0)
2051 static MRealizedFont *
2052 ft_encapsulate (MFrame *frame, MSymbol data_type, void *data)
2055 MRealizedFont *rfont;
2056 MRealizedFontFT *ft_rfont;
2059 if (data_type == Mfontconfig)
2061 #ifdef HAVE_FONTCONFIG
2062 FcPattern *pattern = data;
2064 if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &ft_face)
2067 ft_info = fc_gen_font (pattern, NULL);
2068 #else /* not HAVE_FONTCONFIG */
2070 #endif /* not HAVE_FONTCONFIG */
2072 else if (data_type == Mfreetype)
2075 ft_info = ft_gen_font (ft_face);
2080 M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
2081 ft_rfont->ft_face = ft_face;
2082 ft_rfont->face_encapsulated = 1;
2084 MDEBUG_DUMP (" [FONT-FT] encapsulating ", (char *) ft_face->family_name,);
2086 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
2087 rfont->font = (MFont *) ft_info;
2088 rfont->info = ft_rfont;
2089 rfont->fontp = ft_face;
2090 rfont->driver = &mfont__ft_driver;
2091 rfont->spec = ft_info->font;
2092 rfont->spec.type = MFONT_TYPE_REALIZED;
2093 rfont->frame = frame;
2094 rfont->ascent = ft_face->size->metrics.ascender >> 6;
2095 rfont->descent = - ft_face->size->metrics.descender >> 6;
2096 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
2097 rfont->baseline_offset = 0;
2100 BDF_PropertyRec prop;
2102 if (! FT_IS_SCALABLE (ft_face)
2103 && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
2105 rfont->baseline_offset = prop.u.integer;
2106 rfont->ascent += prop.u.integer;
2107 rfont->descent -= prop.u.integer;
2110 #endif /* HAVE_FTBDF_H */
2111 if (FT_IS_SCALABLE (ft_face))
2112 rfont->average_width = 0;
2114 rfont->average_width = ft_face->available_sizes->width;
2115 rfont->next = MPLIST_VAL (frame->realized_font_list);
2116 MPLIST_VAL (frame->realized_font_list) = rfont;
2122 ft_close (MRealizedFont *rfont)
2124 if (! rfont->encapsulating)
2127 M17N_OBJECT_UNREF (rfont->info);
2135 MFontDriver mfont__ft_driver =
2136 { ft_select, ft_open, ft_find_metric, ft_has_char, ft_encode_char,
2137 ft_render, ft_list, ft_list_family_names, ft_check_capability,
2138 ft_encapsulate, ft_close };
2145 if (FT_Init_FreeType (&ft_library) != 0)
2146 MERROR (MERROR_FONT_FT, -1);
2148 for (i = 0; i < ft_to_prop_size; i++)
2149 ft_to_prop[i].len = strlen (ft_to_prop[i].ft_style);
2151 Mmedium = msymbol ("medium");
2153 Mnull = msymbol ("");
2155 M0[0] = msymbol ("0-0");
2156 M0[1] = msymbol ("0-1");
2157 M0[2] = msymbol ("0-2");
2158 M0[3] = msymbol ("0-3");
2159 M0[4] = msymbol ("0-4");
2160 M3_1 = msymbol ("3-1");
2161 M1_0 = msymbol ("1-0");
2163 #ifdef HAVE_FONTCONFIG
2164 for (i = 0; i < (sizeof (fc_all_table) / sizeof fc_all_table[0]); i++)
2166 FC_vs_M17N_font_prop *table = fc_all_table[i];
2169 for (j = 0; table[j].m17n_value; j++)
2170 table[j].sym = msymbol (table[j].m17n_value);
2171 table[j].sym = table[j - 1].sym;
2178 MSymbol serif, sans_serif, monospace;
2180 fc_config = FcInitLoadConfigAndFonts ();
2181 if (mfont_freetype_path)
2183 MPLIST_DO (plist, mfont_freetype_path)
2184 if (MPLIST_STRING_P (plist)
2185 && (pathname = MPLIST_STRING (plist))
2186 && stat (pathname, &buf) == 0)
2188 FcStrList *strlist = FcConfigGetFontDirs (fc_config);
2191 while ((dir = FcStrListNext (strlist)))
2192 if (strcmp ((char *) dir, pathname) == 0)
2195 FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname);
2196 FcStrListDone (strlist);
2199 Mgeneric_family = msymbol ("generic famly");
2200 serif = msymbol ("serif");
2201 msymbol_put (serif, Mgeneric_family, serif);
2202 sans_serif = msymbol ("sans-serif");
2203 msymbol_put (sans_serif, Mgeneric_family, sans_serif);
2204 msymbol_put (msymbol ("sans serif"), Mgeneric_family, sans_serif);
2205 msymbol_put (msymbol ("sans"), Mgeneric_family, sans_serif);
2206 monospace = msymbol ("monospace");
2207 msymbol_put (monospace, Mgeneric_family, monospace);
2208 msymbol_put (msymbol ("mono"), Mgeneric_family, monospace);
2220 if (ft_default_list)
2222 M17N_OBJECT_UNREF (ft_default_list);
2223 ft_default_list = NULL;
2228 MPLIST_DO (plist, ft_font_list)
2230 if (MPLIST_VAL (plist))
2231 MPLIST_DO (p, MPLIST_VAL (plist))
2233 if (MPLIST_KEY (p) != Mt)
2234 free_ft_info (MPLIST_VAL (p));
2236 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2238 M17N_OBJECT_UNREF (ft_font_list);
2239 ft_font_list = NULL;
2241 if (ft_language_list)
2243 MPLIST_DO (plist, ft_language_list)
2244 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2245 M17N_OBJECT_UNREF (ft_language_list);
2246 ft_language_list = NULL;
2251 MPLIST_DO (plist, ft_script_list)
2252 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2253 M17N_OBJECT_UNREF (ft_script_list);
2254 ft_script_list = NULL;
2257 if (ft_capability_list)
2259 MPLIST_DO (plist, ft_capability_list)
2260 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2261 M17N_OBJECT_UNREF (ft_capability_list);
2262 ft_capability_list = NULL;
2267 MPLIST_DO (plist, ft_file_list)
2268 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2269 M17N_OBJECT_UNREF (ft_file_list);
2270 ft_file_list = NULL;
2273 FT_Done_FreeType (ft_library);
2274 #ifdef HAVE_FONTCONFIG
2275 FcConfigDestroy (fc_config);
2277 #endif /* HAVE_FONTCONFIG */
2278 all_fonts_scaned = 0;
2281 #ifdef HAVE_FONTCONFIG
2284 mfont__ft_parse_name (const char *name, MFont *font)
2286 FcPattern *pat = FcNameParse ((FcChar8 *) name);
2295 if (FcPatternGetString (pat, FC_FOUNDRY, 0, &str) == FcResultMatch)
2297 STRDUP_LOWER (buf, bufsize, (char *) str);
2298 mfont__set_property (font, MFONT_FOUNDRY, msymbol (buf));
2300 if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
2302 STRDUP_LOWER (buf, bufsize, (char *) str);
2303 mfont__set_property (font, MFONT_FAMILY, msymbol (buf));
2305 if (FcPatternGetInteger (pat, FC_WEIGHT, 0, &val) == FcResultMatch)
2306 mfont__set_property (font, MFONT_WEIGHT,
2307 fc_decode_prop (val, fc_weight_table,
2308 fc_weight_table_size));
2309 if (FcPatternGetInteger (pat, FC_SLANT, 0, &val) == FcResultMatch)
2310 mfont__set_property (font, MFONT_STYLE,
2311 fc_decode_prop (val, fc_slant_table,
2312 fc_slant_table_size));
2313 if (FcPatternGetInteger (pat, FC_WIDTH, 0, &val) == FcResultMatch)
2314 mfont__set_property (font, MFONT_STRETCH,
2315 fc_decode_prop (val, fc_width_table,
2316 fc_width_table_size));
2317 if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
2318 font->size = size * 10 + 0.5;
2319 else if (FcPatternGetDouble (pat, FC_SIZE, 0, &size) == FcResultMatch)
2320 font->size = - (size * 10 + 0.5);
2321 if (FcPatternGetString (pat, FC_FILE, 0, &str) == FcResultMatch)
2323 font->file = msymbol ((char *) str);
2325 mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
2326 font->type = MFONT_TYPE_SPEC;
2327 FcPatternDestroy (pat);
2332 mfont__ft_unparse_name (MFont *font)
2334 FcPattern *pat = fc_get_pattern (font);
2335 char *name = (char *) FcNameUnparse (pat);
2337 FcPatternDestroy (pat);
2340 #endif /* HAVE_FONTCONFIG */
2345 #define DEVICE_DELTA(table, size) \
2346 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
2347 ? (table).DeltaValue[(size) - (table).StartSize] \
2351 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
2352 unsigned code, int size, int *x, int *y)
2354 if (anchor->AnchorFormat == 2)
2356 FT_Outline *outline;
2357 int ap = anchor->f.f1.AnchorPoint;
2359 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
2360 outline = &ft_face->glyph->outline;
2361 if (ap < outline->n_points)
2363 *x = outline->points[ap].x;
2364 *y = outline->points[ap].y;
2367 else if (anchor->AnchorFormat == 3)
2369 if (anchor->f.f2.XDeviceTable.offset)
2370 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size);
2371 if (anchor->f.f2.YDeviceTable.offset)
2372 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size);
2377 mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
2378 MFontCapability *cap)
2380 int len = to - from;
2381 MGlyph *g = MGLYPH (from);
2383 MRealizedFont *rfont;
2386 OTF_GlyphString otf_gstring;
2388 char *script, *langsys;
2389 char *gsub_features, *gpos_features;
2395 otf_gstring.glyphs = NULL;
2396 rfont = g->rface->rfont;
2397 ft_info = (MFontFT *) rfont->font;
2398 if (ft_info->otf == invalid_otf)
2403 MRealizedFontFT *ft_rfont = rfont->info;
2405 #if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
2406 otf = OTF_open_ft_face (ft_rfont->ft_face);
2408 otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
2412 ft_info->otf = invalid_otf;
2417 if (OTF_get_table (otf, "head") < 0)
2420 ft_info->otf = invalid_otf;
2424 if (cap->script_tag)
2426 script = alloca (5);
2427 OTF_tag_name (cap->script_tag, script);
2431 if (cap->langsys_tag)
2433 langsys = alloca (5);
2434 OTF_tag_name (cap->langsys_tag, langsys);
2438 gsub_features = cap->features[MFONT_OTT_GSUB].str;
2439 if (gsub_features && OTF_check_table (otf, "GSUB") < 0)
2440 gsub_features = NULL;
2441 gpos_features = cap->features[MFONT_OTT_GPOS].str;
2442 if (gpos_features && OTF_check_table (otf, "GPOS") < 0)
2443 gpos_features = NULL;
2445 otf_gstring.size = otf_gstring.used = len;
2446 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
2447 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
2448 for (i = 0, need_cmap = 0; i < len; i++)
2450 if (gstring->glyphs[from + i].otf_encoded)
2452 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
2453 otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
2457 otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
2462 && OTF_drive_cmap (otf, &otf_gstring) < 0)
2465 OTF_drive_gdef (otf, &otf_gstring);
2466 gidx = gstring->used;
2470 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
2473 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
2475 MGlyph temp = *(MGLYPH (from + otfg->f.index.from));
2478 temp.combining_code = 0;
2481 temp.code = otfg->glyph_id;
2482 temp.otf_encoded = 1;
2487 temp.otf_encoded = 0;
2489 temp.to = MGLYPH (from + otfg->f.index.to)->to;
2490 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
2494 for (i = 0; i < len; i++)
2496 MGlyph temp = gstring->glyphs[from + i];
2498 if (otf_gstring.glyphs[i].glyph_id)
2500 temp.code = otf_gstring.glyphs[i].glyph_id;
2501 temp.otf_encoded = 1;
2503 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
2506 (rfont->driver->find_metric) (rfont, gstring, gidx, gstring->used);
2512 MGlyph *base = NULL, *mark = NULL;
2514 if (OTF_check_features (otf, 0,
2515 cap->script_tag, cap->langsys_tag,
2516 cap->features[MFONT_OTT_GPOS].tags,
2517 cap->features[MFONT_OTT_GPOS].nfeatures) != 1
2518 || (OTF_drive_gpos (otf, &otf_gstring, script, langsys,
2519 gpos_features) < 0))
2522 u = otf->head->unitsPerEm;
2523 size10 = rfont->spec.size;
2526 for (i = 0, otfg = otf_gstring.glyphs, g = MGLYPH (gidx);
2527 i < otf_gstring.used; i++, otfg++, g++)
2531 if (! otfg->glyph_id)
2533 switch (otfg->positioning_type)
2539 int format = otfg->f.f1.format;
2541 if (format & OTF_XPlacement)
2542 g->xoff = otfg->f.f1.value->XPlacement * size10 / u / 10;
2543 if (format & OTF_XPlaDevice)
2544 g->xoff += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, size);
2545 if (format & OTF_YPlacement)
2546 g->yoff = - (otfg->f.f1.value->YPlacement * size10 / u / 10);
2547 if (format & OTF_YPlaDevice)
2548 g->yoff -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, size);
2549 if (format & OTF_XAdvance)
2550 g->width += otfg->f.f1.value->XAdvance * size10 / u / 10;
2551 if (format & OTF_XAdvDevice)
2552 g->width += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, size);
2556 /* Not yet supported. */
2562 goto label_adjust_anchor;
2563 default: /* i.e. case 6 */
2568 label_adjust_anchor:
2570 int base_x, base_y, mark_x, mark_y;
2572 base_x = otfg->f.f4.base_anchor->XCoordinate * size10 / u / 10;
2573 base_y = otfg->f.f4.base_anchor->YCoordinate * size10 / u / 10;
2574 mark_x = otfg->f.f4.mark_anchor->XCoordinate * size10 / u / 10;
2575 mark_y = otfg->f.f4.mark_anchor->YCoordinate * size10 / u / 10;
2577 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2578 adjust_anchor (otfg->f.f4.base_anchor, rfont->fontp,
2579 prev->code, size, &base_x, &base_y);
2580 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2581 adjust_anchor (otfg->f.f4.mark_anchor, rfont->fontp,
2582 g->code, size, &mark_x, &mark_y);
2583 g->xoff = prev->xoff + (base_x - prev->width) - mark_x;
2584 g->yoff = prev->yoff + mark_y - base_y;
2585 g->combining_code = MAKE_PRECOMPUTED_COMBINDING_CODE ();
2588 if (otfg->GlyphClass == OTF_GlyphClass0)
2590 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2596 free (otf_gstring.glyphs);
2600 for (i = 0; i < len; i++)
2602 MGlyph *g = MGLYPH (from + i);
2604 if (! g->otf_encoded)
2606 g->code = rfont->driver->encode_char (gstring->frame, (MFont *) rfont,
2612 rfont->driver->find_metric (rfont, gstring, from, to);
2613 for (i = 0; i < len; i++)
2615 MGlyph temp = gstring->glyphs[from + i];
2616 MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
2618 if (otf_gstring.glyphs)
2619 free (otf_gstring.glyphs);
2625 mfont__ft_decode_otf (MGlyph *g)
2627 MFontFT *ft_info = (MFontFT *) g->rface->rfont->font;
2628 int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
2630 return (c ? c : -1);
2633 #endif /* HAVE_OTF */
2635 #endif /* HAVE_FREETYPE */