1 /* font-ft.c -- FreeType interface sub-module.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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-flt.h"
41 #include "internal-gui.h"
51 static int mdebug_flag = MDEBUG_FONT;
53 #ifdef HAVE_FONTCONFIG
54 #include <fontconfig/fcfreetype.h>
56 static FcConfig *fc_config;
57 static MSymbol Mgeneric_family;
58 #endif /* HAVE_FONTCONFIG */
60 /* Font properties; Mnormal is already defined in face.c. */
61 static MSymbol Mmedium, Mr, Mnull;
63 static MSymbol M0[5], M3_1, M1_0;
65 static FT_Library ft_library;
68 static OTF *invalid_otf = (OTF *) "";
75 /* NULL if not yet opened. invalid_otf if not OTF. */
78 #ifdef HAVE_FONTCONFIG
81 #endif /* HAVE_FONTCONFIG */
87 FT_Face ft_face; /* This must be the 2nd member. */
89 int face_encapsulated;
96 enum MFontProperty prop;
100 static MFTtoProp ft_to_prop[] =
101 { { "italic", 0, MFONT_STYLE, "i" },
102 { "roman", 0, MFONT_STYLE, "r" },
103 { "oblique", 0, MFONT_STYLE, "o" },
104 { "regular", 0, MFONT_WEIGHT, "normal" },
105 { "normal", 0, MFONT_WEIGHT, "normal" },
106 /* We need this entry even if "bold" is in commone_weight[] to
107 handle such style names as "bolditalic" and "boldoblique". */
108 { "bold", 0, MFONT_WEIGHT, "bold" },
109 { "demi bold", 0, MFONT_WEIGHT, "demibold" },
110 { "demi", 0, MFONT_WEIGHT, "demibold" } };
111 static int ft_to_prop_size = sizeof ft_to_prop / sizeof ft_to_prop[0];
113 /** List of FreeType fonts. Keys are family names, values are plists
114 containing fonts of the corresponding family. In the deeper
115 plist, keys are file names, values are (MFontFT *). */
116 static MPlist *ft_font_list;
118 /** List of FreeType fonts. Keys are script names, values are plists
119 containing fonts supporting the corresponding script. In the
120 deeper plist, keys are family names, values are (MFontFT *). */
121 static MPlist *ft_script_list;
123 /** List of FreeType fonts. Keys are language names, values are
124 plists containing fonts supporting the corresponding language. In
125 the deeper plist, keys are family names, values are (MFontFT *). */
126 static MPlist *ft_language_list;
128 static MPlist *ft_file_list;
130 static int all_fonts_scaned;
132 #define STRDUP_LOWER(s1, size, s2) \
134 int len = strlen (s2) + 1; \
138 (s1) = alloca (len), (size) = len; \
139 for (p1 = (s1), p2 = (s2); *p2; p1++, p2++) \
140 *p1 = (*p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2); \
145 static MPlist *ft_list_family (MSymbol, int, 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, 1));
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, 1);
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, int check_alias)
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, 1);
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, 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, 1);
875 MPLIST_DO (pl, MPLIST_PLIST (pl))
876 plist = mplist_add (plist, Mt, MPLIST_VAL (pl));
878 plist = ft_font_list;
881 else if (check_alias)
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, 0));
918 if (! MPLIST_TAIL_P (p))
920 mplist_push (pl, Mt, MPLIST_VAL (p));
927 plist = mplist_add (ft_font_list, family, pl);
930 #else /* not HAVE_FONTCONFIG */
932 if (! all_fonts_scaned)
934 ft_init_font_list ();
935 all_fonts_scaned = 1;
938 plist = ft_font_list;
941 plist = mplist_find_by_key (ft_font_list, family);
943 plist = mplist_push (ft_font_list, family, mplist ());
945 #endif /* not HAVE_FONTCONFIG */
951 ft_list_language (MSymbol language)
953 MPlist *plist = NULL;
956 if (! ft_language_list)
957 ft_language_list = mplist ();
958 else if ((plist = mplist_find_by_key (ft_language_list, language)))
959 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
961 mt = mlanguage_text (language);
963 #ifdef HAVE_FONTCONFIG
965 FcPattern *pattern = NULL;
966 FcCharSet *cs = NULL;
967 FcLangSet *ls = NULL;
969 if (! (pattern = FcPatternCreate ()))
972 if (mt && mtext_nchars (mt) > 0)
974 cs = fc_build_charset (NULL, mt);
975 if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs))
980 if (! (ls = FcLangSetCreate ()))
982 if (! FcLangSetAdd (ls, (FcChar8 *) MSYMBOL_NAME (language))
983 || ! FcPatternAddLangSet (pattern, FC_LANG, ls))
987 plist = fc_list_pattern (pattern);
989 if (cs) FcCharSetDestroy (cs);
990 if (ls) FcLangSetDestroy (ls);
991 if (pattern) FcPatternDestroy (pattern);
993 #else /* not HAVE_FONTCONFIG */
994 if (mt && mtext_nchars (mt) > 0)
995 plist = ft_list_char_list (NULL, mt);
996 #endif /* not HAVE_FONTCONFIG */
998 mplist_push (ft_language_list, language, plist);
1003 ft_list_script (MSymbol script)
1005 MPlist *plist = NULL;
1008 if (! ft_script_list)
1009 ft_script_list = mplist ();
1010 else if ((plist = mplist_find_by_key (ft_script_list, script)))
1011 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
1013 char_list = mscript__char_list (script);
1015 #ifdef HAVE_FONTCONFIG
1018 FcPattern *pattern = NULL;
1021 if (! (pattern = FcPatternCreate ()))
1023 cs = fc_build_charset (char_list, NULL);
1024 if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs))
1026 plist = fc_list_pattern (pattern);
1028 if (cs) FcCharSetDestroy (cs);
1029 if (pattern) FcPatternDestroy (pattern);
1031 #else /* not HAVE_FONTCONFIG */
1033 plist = ft_list_char_list (char_list, NULL);
1034 #endif /* not HAVE_FONTCONFIG */
1036 mplist_push (ft_script_list, script, plist);
1041 ft_check_cap_otf (MFontFT *ft_info, MFontCapability *cap, FT_Face ft_face)
1044 if (ft_info->otf == invalid_otf)
1048 #if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
1050 ft_info->otf = OTF_open_ft_face (ft_face);
1053 ft_info->otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
1056 ft_info->otf = invalid_otf;
1060 if (cap->features[MFONT_OTT_GSUB].nfeatures
1061 && (OTF_check_features
1063 cap->script_tag, cap->langsys_tag,
1064 cap->features[MFONT_OTT_GSUB].tags,
1065 cap->features[MFONT_OTT_GSUB].nfeatures) != 1))
1067 if (cap->features[MFONT_OTT_GPOS].nfeatures
1068 && (OTF_check_features
1070 cap->script_tag, cap->langsys_tag,
1071 cap->features[MFONT_OTT_GPOS].tags,
1072 cap->features[MFONT_OTT_GPOS].nfeatures) != 1))
1075 #else /* not HAVE_OTF */
1077 #endif /* not HAVE_OTF */
1081 ft_check_language (MFontFT *ft_info, MSymbol language, FT_Face ft_face)
1085 int ft_face_allocaed = 0;
1089 #ifdef HAVE_FONTCONFIG
1090 if (ft_info->langset
1091 && (FcLangSetHasLang (ft_info->langset,
1092 (FcChar8 *) MSYMBOL_NAME (language))
1093 != FcLangDifferentLang))
1095 #endif /* HAVE_FONTCONFIG */
1097 mt = mlanguage_text (language);
1098 if (! mt || mtext_nchars (mt) == 0)
1103 char *filename = MSYMBOL_NAME (ft_info->font.file);
1105 if (FT_New_Face (ft_library, filename, 0, &ft_face))
1107 ft_face_allocaed = 1;
1110 len = mtext_nchars (mt);
1111 extra = mtext_get_prop (mt, 0, Mtext);
1112 total_len = len + (extra ? mtext_nchars (extra) : 0);
1114 for (i = 0; i < total_len; i++)
1116 int c = (i < len ? mtext_ref_char (mt, i)
1117 : mtext_ref_char (extra, i - len));
1119 #ifdef HAVE_FONTCONFIG
1120 if (ft_info->charset
1121 && FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcFalse)
1123 #endif /* HAVE_FONTCONFIG */
1124 if (FT_Get_Char_Index (ft_face, (FT_ULong) c) == 0)
1128 if (ft_face_allocaed)
1129 FT_Done_Face (ft_face);
1131 return (i == total_len ? 0 : -1);
1135 ft_check_script (MFontFT *ft_info, MSymbol script, FT_Face ft_face)
1137 MPlist *char_list = mscript__char_list (script);
1141 #ifdef HAVE_FONTCONFIG
1142 if (ft_info->charset)
1144 MPLIST_DO (char_list, char_list)
1145 if (FcCharSetHasChar (ft_info->charset,
1146 (FcChar32) MPLIST_INTEGER (char_list)) == FcFalse)
1150 #endif /* HAVE_FONTCONFIG */
1152 int ft_face_allocaed = 0;
1156 char *filename = MSYMBOL_NAME (ft_info->font.file);
1158 if (FT_New_Face (ft_library, filename, 0, &ft_face))
1160 ft_face_allocaed = 1;
1163 MPLIST_DO (char_list, char_list)
1164 if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (char_list))
1167 if (ft_face_allocaed)
1168 FT_Done_Face (ft_face);
1171 return (MPLIST_TAIL_P (char_list) ? 0 : -1);
1174 static MPlist *ft_default_list;
1179 if (ft_default_list)
1180 return ft_default_list;
1181 ft_default_list = mplist ();
1182 #ifdef HAVE_FONTCONFIG
1184 FcPattern *pat = FcPatternCreate ();
1190 FcConfigSubstitute (fc_config, pat, FcMatchPattern);
1191 for (i = 0; FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
1197 STRDUP_LOWER (buf, bufsize, (char *) fam);
1198 family = msymbol (buf);
1199 if (msymbol_get (family, Mgeneric_family))
1201 plist = MPLIST_PLIST (ft_list_family (family, 0, 1));
1202 MPLIST_DO (plist, plist)
1203 mplist_add (ft_default_list, family, MPLIST_VAL (plist));
1206 #else /* not HAVE_FONTCONFIG */
1210 MPLIST_DO (plist, ft_list_family (Mnil, 0, 1))
1212 pl = MPLIST_PLIST (plist);
1213 if (! MPLIST_TAIL_P (pl))
1214 mplist_add (ft_default_list, MPLIST_KEY (plist), pl);
1217 #endif /* not HAVE_FONTCONFIG */
1218 return ft_default_list;
1222 static MPlist *ft_capability_list;
1225 ft_list_capability (MSymbol capability)
1227 MFontCapability *cap;
1228 MPlist *plist = NULL, *pl;
1230 if (! ft_capability_list)
1231 ft_capability_list = mplist ();
1232 else if ((plist = mplist_find_by_key (ft_capability_list, capability)))
1233 return (MPLIST_VAL (plist) ? MPLIST_VAL (plist) : NULL);
1235 cap = mfont__get_capability (capability);
1237 if (cap && cap->language != Mnil)
1239 plist = ft_list_language (cap->language);
1242 plist = mplist_copy (plist);
1245 if (cap && cap->script != Mnil)
1249 plist = ft_list_script (cap->script);
1252 plist = mplist_copy (plist);
1256 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1258 if (ft_check_script (MPLIST_VAL (pl), cap->script, NULL) < 0)
1261 pl = MPLIST_NEXT (pl);
1265 if (cap->script_tag)
1267 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1269 if (ft_check_cap_otf (MPLIST_VAL (pl), cap, NULL) < 0)
1272 pl = MPLIST_NEXT (pl);
1276 if (MPLIST_TAIL_P (plist))
1278 M17N_OBJECT_UNREF (plist);
1283 mplist_push (ft_capability_list, capability, plist);
1289 ft_list_file (MSymbol filename)
1291 MPlist *plist = NULL;
1294 ft_file_list = mplist ();
1295 else if ((plist = mplist_find_by_key (ft_file_list, filename)))
1296 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
1298 #ifdef HAVE_FONTCONFIG
1300 FcPattern *pattern = FcPatternCreate ();
1304 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) MSYMBOL_NAME (filename));
1305 os = FcObjectSetBuild (FC_FAMILY, NULL);
1306 fs = FcFontList (fc_config, pattern, os);
1313 if (FcPatternGetString (fs->fonts[0], FC_FAMILY, 0,
1314 (FcChar8 **) &fam) == FcResultMatch)
1319 STRDUP_LOWER (buf, bufsize, fam);
1320 family = msymbol (buf);
1321 pl = ft_list_family (family, 0, 1);
1322 MPLIST_DO (pl, MPLIST_PLIST (pl))
1324 MFontFT *ft_info = MPLIST_VAL (pl);
1326 if (ft_info->font.file == filename)
1329 mplist_add (plist, family, ft_info);
1336 #else /* not HAVE_FONTCONFIG */
1340 MPLIST_DO (pl, ft_list_family (Mnil, 0, 1))
1342 MPLIST_DO (p, MPLIST_PLIST (pl))
1344 MFontFT *ft_info = MPLIST_VAL (pl);
1346 if (ft_info->font.file == filename)
1349 mplist_add (plist, MPLIST_KEY (pl), ft_info);
1357 #endif /* not HAVE_FONTCONFIG */
1359 mplist_push (ft_file_list, filename, plist);
1363 /* The FreeType font driver function SELECT. */
1366 ft_select (MFrame *frame, MFont *font, int limited_size)
1368 MFont *found = NULL;
1369 #ifdef HAVE_FONTCONFIG
1372 int check_font_property = 1;
1374 if (font->file != Mnil)
1376 plist = ft_list_file (font->file);
1379 check_font_property = 0;
1383 MSymbol family = FONT_PROPERTY (font, MFONT_FAMILY);
1386 plist = MPLIST_PLIST (ft_list_family (family, 1, 1));
1388 plist = ft_list_default ();
1389 if (MPLIST_TAIL_P (plist))
1393 plist = mplist_copy (plist);
1395 if (font->capability != Mnil)
1397 MFontCapability *cap = mfont__get_capability (font->capability);
1399 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1401 if (cap->script_tag && ft_check_cap_otf (MPLIST_VAL (pl), cap, NULL) < 0)
1407 && ft_check_language (MPLIST_VAL (pl), cap->language, NULL) < 0)
1410 pl = MPLIST_NEXT (pl);
1414 if (check_font_property)
1416 MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT);
1417 MSymbol style = FONT_PROPERTY (font, MFONT_STYLE);
1418 MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH);
1419 MSymbol alternate_weight = Mnil;
1421 if (weight == Mnormal)
1422 alternate_weight = Mmedium;
1423 else if (weight == Mmedium)
1424 alternate_weight = Mnormal;
1425 if (weight != Mnil || style != Mnil || stretch != Mnil || font->size > 0)
1426 for (pl = plist; ! MPLIST_TAIL_P (pl); )
1428 ft_info = MPLIST_VAL (pl);
1430 && (weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT)
1431 && alternate_weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT)))
1433 && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE))
1435 && stretch != FONT_PROPERTY (&ft_info->font,
1438 && ft_info->font.size > 0
1439 && ft_info->font.size != font->size))
1442 pl = MPLIST_NEXT (pl);
1446 MPLIST_DO (pl, plist)
1448 font = MPLIST_VAL (plist);
1449 if (limited_size == 0
1451 || font->size <= limited_size)
1457 M17N_OBJECT_UNREF (plist);
1458 #endif /* HAVE_FONTCONFIG */
1463 static MRealizedFont *
1464 ft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1466 MFontFT *ft_info = (MFontFT *) font;
1467 int reg = spec->property[MFONT_REGISTRY];
1468 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
1469 MRealizedFontFT *ft_rfont;
1471 MPlist *plist, *charmap_list = NULL;
1476 /* non-scalable font */
1478 else if (spec->size)
1480 int ratio = mfont_resize_ratio (font);
1482 size = ratio == 100 ? spec->size : spec->size * ratio / 100;
1489 charmap_list = ((MRealizedFontFT *) rfont->info)->charmap_list;
1490 for (; rfont; rfont = rfont->next)
1491 if (rfont->font == font
1492 && (rfont->font->size ? rfont->font->size == size
1493 : rfont->spec.size == size)
1494 && rfont->spec.property[MFONT_REGISTRY] == reg
1495 && rfont->driver == &mfont__ft_driver)
1499 MDEBUG_DUMP (" [FONT-FT] opening ", "", mdebug_dump_font (&ft_info->font));
1501 if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0,
1504 font->type = MFONT_TYPE_FAILURE;
1505 MDEBUG_PRINT (" no (FT_New_Face)\n");
1509 M17N_OBJECT_REF (charmap_list);
1511 charmap_list = ft_get_charmaps (ft_face);
1512 if (registry == Mnil)
1513 registry = Municode_bmp;
1514 plist = mplist_find_by_key (charmap_list, registry);
1517 FT_Done_Face (ft_face);
1518 M17N_OBJECT_UNREF (charmap_list);
1519 MDEBUG_PRINT1 (" no (%s)\n", MSYMBOL_NAME (registry));
1522 charmap_index = (int) MPLIST_VAL (plist);
1523 if ((charmap_index >= 0
1524 && FT_Set_Charmap (ft_face, ft_face->charmaps[charmap_index]))
1525 || FT_Set_Pixel_Sizes (ft_face, 0, size / 10))
1527 FT_Done_Face (ft_face);
1528 M17N_OBJECT_UNREF (charmap_list);
1529 font->type = MFONT_TYPE_FAILURE;
1530 MDEBUG_PRINT1 (" no (size %d)\n", size);
1534 M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
1535 ft_rfont->ft_face = ft_face;
1536 ft_rfont->charmap_list = charmap_list;
1537 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
1538 rfont->id = ft_info->font.file;
1539 rfont->spec = *font;
1540 rfont->spec.type = MFONT_TYPE_REALIZED;
1541 rfont->spec.property[MFONT_REGISTRY] = reg;
1542 rfont->spec.size = size;
1543 rfont->frame = frame;
1545 rfont->driver = &mfont__ft_driver;
1546 rfont->info = ft_rfont;
1547 rfont->fontp = ft_face;
1548 rfont->ascent = ft_face->size->metrics.ascender;
1549 rfont->descent = - ft_face->size->metrics.descender;
1550 rfont->max_advance = ft_face->size->metrics.max_advance;
1551 rfont->baseline_offset = 0;
1552 rfont->x_ppem = ft_face->size->metrics.x_ppem;
1553 rfont->y_ppem = ft_face->size->metrics.y_ppem;
1556 BDF_PropertyRec prop;
1558 if (! FT_IS_SCALABLE (ft_face)
1559 && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
1561 rfont->baseline_offset = prop.u.integer << 6;
1562 rfont->ascent += prop.u.integer << 6;
1563 rfont->descent -= prop.u.integer << 6;
1566 #endif /* HAVE_FTBDF_H */
1567 if (FT_IS_SCALABLE (ft_face))
1568 rfont->average_width = 0;
1570 rfont->average_width = ft_face->available_sizes->width << 6;
1571 rfont->next = MPLIST_VAL (frame->realized_font_list);
1572 MPLIST_VAL (frame->realized_font_list) = rfont;
1573 MDEBUG_PRINT (" ok\n");
1577 /* The FreeType font driver function FIND_METRIC. */
1580 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1583 FT_Face ft_face = rfont->fontp;
1584 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1586 for (; g != gend; g++)
1590 if (g->g.code == MCHAR_INVALID_CODE)
1592 if (FT_IS_SCALABLE (ft_face))
1595 g->g.rbearing = ft_face->size->metrics.max_advance;
1596 g->g.xadv = g->g.rbearing;
1597 g->g.ascent = ft_face->size->metrics.ascender;
1598 g->g.descent = - ft_face->size->metrics.descender;
1603 BDF_PropertyRec prop;
1604 #endif /* HAVE_FTBDF_H */
1607 g->g.rbearing = g->g.xadv = ft_face->available_sizes->width << 6;
1609 if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
1611 g->g.ascent = prop.u.integer << 6;
1612 FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
1613 g->g.descent = prop.u.integer << 6;
1614 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET",
1617 g->g.ascent += prop.u.integer << 6;
1618 g->g.descent -= prop.u.integer << 6;
1622 #endif /* HAVE_FTBDF_H */
1624 g->g.ascent = ft_face->available_sizes->height << 6;
1631 FT_Glyph_Metrics *metrics;
1633 FT_Load_Glyph (ft_face, (FT_UInt) g->g.code, FT_LOAD_DEFAULT);
1634 metrics = &ft_face->glyph->metrics;
1635 g->g.lbearing = metrics->horiBearingX;
1636 g->g.rbearing = metrics->horiBearingX + metrics->width;
1637 g->g.xadv = metrics->horiAdvance;
1638 g->g.ascent = metrics->horiBearingY;
1639 g->g.descent = metrics->height - metrics->horiBearingY;
1642 g->g.ascent += rfont->baseline_offset;
1643 g->g.descent -= rfont->baseline_offset;
1649 ft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1651 MRealizedFont *rfont = NULL;
1652 MRealizedFontFT *ft_rfont;
1655 if (font->type == MFONT_TYPE_REALIZED)
1656 rfont = (MRealizedFont *) font;
1657 else if (font->type == MFONT_TYPE_OBJECT)
1659 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1660 rfont = rfont->next)
1661 if (rfont->font == font && rfont->driver == &mfont__ft_driver)
1665 #ifdef HAVE_FONTCONFIG
1666 MFontFT *ft_info = (MFontFT *) font;
1668 if (! ft_info->charset)
1670 FcPattern *pat = FcPatternBuild (NULL, FC_FILE, FcTypeString,
1671 MSYMBOL_NAME (font->file),
1673 FcObjectSet *os = FcObjectSetBuild (FC_CHARSET, NULL);
1674 FcFontSet *fs = FcFontList (fc_config, pat, os);
1677 && FcPatternGetCharSet (fs->fonts[0], FC_CHARSET, 0,
1678 &ft_info->charset) == FcResultMatch)
1679 ft_info->charset = FcCharSetCopy (ft_info->charset);
1681 ft_info->charset = FcCharSetCreate ();
1682 FcFontSetDestroy (fs);
1683 FcObjectSetDestroy (os);
1684 FcPatternDestroy (pat);
1686 return (FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcTrue);
1687 #else /* not HAVE_FONTCONFIG */
1688 rfont = ft_open (frame, font, spec, NULL);
1689 #endif /* not HAVE_FONTCONFIG */
1693 MFATAL (MERROR_FONT_FT);
1697 ft_rfont = rfont->info;
1698 idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code);
1702 /* The FreeType font driver function ENCODE_CHAR. */
1705 ft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1707 MRealizedFont *rfont;
1708 MRealizedFontFT *ft_rfont;
1711 if (font->type == MFONT_TYPE_REALIZED)
1712 rfont = (MRealizedFont *) font;
1713 else if (font->type == MFONT_TYPE_OBJECT)
1715 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1716 rfont = rfont->next)
1717 if (rfont->font == font && rfont->driver == &mfont__ft_driver)
1721 rfont = ft_open (frame, font, spec, NULL);
1727 MFATAL (MERROR_FONT_FT);
1729 ft_rfont = rfont->info;
1730 idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code);
1731 return (idx ? (unsigned) idx : MCHAR_INVALID_CODE);
1734 /* The FreeType font driver function RENDER. */
1736 #define NUM_POINTS 0x1000
1739 MDrawPoint points[NUM_POINTS];
1744 ft_render (MDrawWindow win, int x, int y,
1745 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1746 int reverse, MDrawRegion region)
1749 MRealizedFace *rface = from->rface;
1750 MFrame *frame = rface->frame;
1751 FT_Int32 load_flags = FT_LOAD_RENDER;
1754 MPointTable point_table[8];
1755 int baseline_offset;
1756 int pixel_mode = -1;
1761 /* It is assured that the all glyphs in the current range use the
1762 same realized face. */
1763 ft_face = rface->rfont->fontp;
1764 baseline_offset = rface->rfont->baseline_offset >> 6;
1766 if (! gstring->anti_alias)
1768 #ifdef FT_LOAD_TARGET_MONO
1769 load_flags |= FT_LOAD_TARGET_MONO;
1771 load_flags |= FT_LOAD_MONOCHROME;
1775 for (i = 0; i < 8; i++)
1776 point_table[i].p = point_table[i].points;
1778 for (g = from; g < to; x += g++->g.xadv)
1782 MPointTable *ptable;
1786 FT_Load_Glyph (ft_face, (FT_UInt) g->g.code, load_flags);
1788 pixel_mode = ft_face->glyph->bitmap.pixel_mode;
1789 yoff = y - ft_face->glyph->bitmap_top + g->g.yoff;
1790 bmp = ft_face->glyph->bitmap.buffer;
1791 width = ft_face->glyph->bitmap.width;
1792 pitch = ft_face->glyph->bitmap.pitch;
1794 if (pixel_mode != FT_PIXEL_MODE_MONO)
1795 for (i = 0; i < ft_face->glyph->bitmap.rows;
1796 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
1798 xoff = x + ft_face->glyph->bitmap_left + g->g.xoff;
1799 for (j = 0; j < width; j++, xoff++)
1801 intensity = bmp[j] >> 5;
1804 ptable = point_table + intensity;
1805 ptable->p->x = xoff;
1806 ptable->p->y = yoff - baseline_offset;
1808 if (ptable->p - ptable->points == NUM_POINTS)
1810 (*frame->driver->draw_points)
1812 reverse ? 7 - intensity : intensity,
1813 ptable->points, NUM_POINTS, region);
1814 ptable->p = ptable->points;
1820 for (i = 0; i < ft_face->glyph->bitmap.rows;
1821 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
1823 xoff = x + ft_face->glyph->bitmap_left + g->g.xoff;
1824 for (j = 0; j < width; j++, xoff++)
1826 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
1829 ptable = point_table;
1830 ptable->p->x = xoff;
1831 ptable->p->y = yoff - baseline_offset;
1833 if (ptable->p - ptable->points == NUM_POINTS)
1835 (*frame->driver->draw_points) (frame, win, rface,
1837 ptable->points, NUM_POINTS, region);
1838 ptable->p = ptable->points;
1845 if (pixel_mode != FT_PIXEL_MODE_MONO)
1847 for (i = 1; i < 8; i++)
1848 if (point_table[i].p != point_table[i].points)
1849 (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i,
1850 point_table[i].points,
1851 point_table[i].p - point_table[i].points, region);
1855 if (point_table[0].p != point_table[0].points)
1856 (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7,
1857 point_table[0].points,
1858 point_table[0].p - point_table[0].points, region);
1863 ft_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
1865 MPlist *pl = NULL, *p;
1867 MPlist *file_list = NULL;
1868 MPlist *family_list = NULL, *capability_list = NULL;
1869 MSymbol registry = Mnil;
1871 MDEBUG_DUMP (" [FONT-FT] listing ", "", mdebug_dump_font (font));
1877 registry = FONT_PROPERTY (font, MFONT_REGISTRY);
1878 if (registry != Mnil && registry != Miso8859_1)
1880 char *reg = MSYMBOL_NAME (registry);
1882 if (strncmp (reg, "unicode-", 8)
1883 && strncmp (reg, "apple-roman", 11)
1884 && (reg[0] < '0' || reg[0] > '9' || reg[1] != '-'))
1888 if (font->file != Mnil
1889 && ! (file_list = ft_list_file (font->file)))
1891 family = FONT_PROPERTY (font, MFONT_FAMILY);
1893 && (family_list = MPLIST_PLIST (ft_list_family (family, 1, 1)))
1894 && MPLIST_TAIL_P (family_list))
1896 if (font->capability != Mnil)
1898 capability_list = ft_list_capability (font->capability);
1899 if (! capability_list || MPLIST_TAIL_P (capability_list))
1904 if (! file_list && ! family_list && ! capability_list)
1906 /* No restriction. Get all fonts. */
1908 MPLIST_DO (family_list, ft_list_family (Mnil, 0, 1))
1910 MPLIST_DO (p, MPLIST_PLIST (family_list))
1911 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1919 mplist_push (pl, MPLIST_KEY (file_list), MPLIST_VAL (file_list));
1924 for (p = pl; ! MPLIST_TAIL_P (p);)
1926 if (mplist_find_by_value (family_list, MPLIST_VAL (p)))
1927 p = MPLIST_NEXT (p);
1934 MPLIST_DO (p, family_list)
1935 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1938 if (capability_list)
1941 for (p = pl; ! MPLIST_TAIL_P (p);)
1943 if (mplist_find_by_value (capability_list, MPLIST_VAL (p)))
1944 p = MPLIST_NEXT (p);
1951 MPLIST_DO (p, capability_list)
1952 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1958 && (font->property[MFONT_WEIGHT] + font->property[MFONT_STYLE]
1959 + font->property[MFONT_STRETCH] + font->size) > 0)
1961 MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT);
1962 MSymbol style = FONT_PROPERTY (font, MFONT_STYLE);
1963 MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH);
1964 int size = font->size;
1966 for (p = pl; ! MPLIST_TAIL_P (p); )
1968 MFontFT *ft_info = MPLIST_VAL (p);
1971 && weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT))
1973 && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE))
1975 && stretch != FONT_PROPERTY (&ft_info->font,
1978 && ft_info->font.size > 0
1979 && ft_info->font.size != size))
1982 p = MPLIST_NEXT (p);
1988 mplist_push (plist, MPLIST_KEY (p), MPLIST_VAL (p));
1990 if (maxnum && maxnum <= num)
1993 M17N_OBJECT_UNREF (pl);
1996 MDEBUG_PRINT1 (" %d found\n", num);
2001 ft_list_family_names (MFrame *frame, MPlist *plist)
2007 #ifdef HAVE_FONTCONFIG
2008 fc_init_font_list ();
2009 #else /* not HAVE_FONTCONFIG */
2010 ft_init_font_list ();
2011 #endif /* not HAVE_FONTCONFIG */
2014 MPLIST_DO (pl, ft_font_list)
2016 MSymbol family = MPLIST_KEY (pl);
2019 #ifdef HAVE_FONTCONFIG
2020 if (msymbol_get (family, Mgeneric_family) != Mnil)
2022 #endif /* HAVE_FONTCONFIG */
2023 MPLIST_DO (p, plist)
2025 MSymbol sym = MPLIST_SYMBOL (p);
2029 if (strcmp (MSYMBOL_NAME (sym), MSYMBOL_NAME (family)) > 0)
2031 mplist_push (p, Msymbol, family);
2035 if (MPLIST_TAIL_P (p))
2036 mplist_push (p, Msymbol, family);
2041 ft_check_capability (MRealizedFont *rfont, MSymbol capability)
2043 MFontFT *ft_info = (MFontFT *) rfont->font;
2044 MRealizedFontFT *ft_rfont = rfont->info;
2045 MFontCapability *cap = mfont__get_capability (capability);
2047 if (cap->script_tag)
2049 if (ft_check_cap_otf (ft_info, cap, ft_rfont->ft_face) < 0)
2052 else if (cap->script != Mnil
2053 && ft_check_script (ft_info, cap->script, ft_rfont->ft_face) < 0)
2055 if (cap->language != Mnil
2056 && ft_check_language (ft_info, cap->language, ft_rfont->ft_face) < 0)
2061 static MRealizedFont *
2062 ft_encapsulate (MFrame *frame, MSymbol data_type, void *data)
2065 MRealizedFont *rfont;
2066 MRealizedFontFT *ft_rfont;
2069 if (data_type == Mfontconfig)
2071 #ifdef HAVE_FONTCONFIG
2072 FcPattern *pattern = data;
2074 if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &ft_face)
2077 ft_info = fc_gen_font (pattern, NULL);
2078 #else /* not HAVE_FONTCONFIG */
2080 #endif /* not HAVE_FONTCONFIG */
2082 else if (data_type == Mfreetype)
2085 ft_info = ft_gen_font (ft_face);
2090 M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
2091 ft_rfont->ft_face = ft_face;
2092 ft_rfont->face_encapsulated = 1;
2094 MDEBUG_DUMP (" [FONT-FT] encapsulating ", (char *) ft_face->family_name,);
2096 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
2097 rfont->id = ft_info->font.file;
2098 rfont->font = (MFont *) ft_info;
2099 rfont->info = ft_rfont;
2100 rfont->fontp = ft_face;
2101 rfont->driver = &mfont__ft_driver;
2102 rfont->spec = ft_info->font;
2103 rfont->spec.type = MFONT_TYPE_REALIZED;
2104 rfont->frame = frame;
2105 rfont->ascent = ft_face->size->metrics.ascender >> 6;
2106 rfont->descent = - ft_face->size->metrics.descender >> 6;
2107 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
2108 rfont->baseline_offset = 0;
2109 rfont->x_ppem = ft_face->size->metrics.x_ppem;
2110 rfont->y_ppem = ft_face->size->metrics.y_ppem;
2113 BDF_PropertyRec prop;
2115 if (! FT_IS_SCALABLE (ft_face)
2116 && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
2118 rfont->baseline_offset = prop.u.integer << 6;
2119 rfont->ascent += prop.u.integer << 6;
2120 rfont->descent -= prop.u.integer << 6;
2123 #endif /* HAVE_FTBDF_H */
2124 if (FT_IS_SCALABLE (ft_face))
2125 rfont->average_width = 0;
2127 rfont->average_width = ft_face->available_sizes->width << 6;
2128 rfont->next = MPLIST_VAL (frame->realized_font_list);
2129 MPLIST_VAL (frame->realized_font_list) = rfont;
2135 ft_close (MRealizedFont *rfont)
2137 if (! rfont->encapsulating)
2140 M17N_OBJECT_UNREF (rfont->info);
2145 get_otf (MFLTFont *font, FT_Face *ft_face)
2147 MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
2148 MFontFT *ft_info = (MFontFT *) rfont->font;
2149 MRealizedFontFT *ft_rfont = rfont->info;
2150 OTF *otf = ft_info->otf;
2154 #if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
2155 otf = OTF_open_ft_face (ft_rfont->ft_face);
2157 otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
2159 if (! otf || OTF_get_table (otf, "head") < 0)
2164 *ft_face = ft_rfont->ft_face;
2165 return (otf == invalid_otf ? NULL : otf);
2169 ft_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
2174 OTF *otf = get_otf (font, NULL);
2178 for (i = 0; i < 2; i++)
2180 if (! spec->features[i])
2182 for (n = 0; spec->features[i][n]; n++);
2183 tags = alloca (sizeof (OTF_Tag) * n);
2184 for (n = 0, negative = 0; spec->features[i][n]; n++)
2186 if (spec->features[i][n] == 0xFFFFFFFF)
2189 tags[n - 1] = spec->features[i][n] | 0x80000000;
2191 tags[n] = spec->features[i][n];
2193 if (n - negative > 0
2194 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
2195 tags, n - negative) != 1)
2199 #endif /* HAVE_OTF */
2201 return ((! spec->features[0] || spec->features[0][0] == 0xFFFFFFFF)
2202 && (! spec->features[1] || spec->features[1][0] == 0xFFFFFFFF));
2207 #define DEVICE_DELTA(table, size) \
2208 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
2209 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
2213 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
2214 unsigned code, int x_ppem, int y_ppem, int *x, int *y)
2216 if (anchor->AnchorFormat == 2)
2218 FT_Outline *outline;
2219 int ap = anchor->f.f1.AnchorPoint;
2221 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
2222 outline = &ft_face->glyph->outline;
2223 if (ap < outline->n_points)
2225 *x = outline->points[ap].x << 6;
2226 *y = outline->points[ap].y << 6;
2229 else if (anchor->AnchorFormat == 3)
2231 if (anchor->f.f2.XDeviceTable.offset)
2232 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
2233 if (anchor->f.f2.YDeviceTable.offset)
2234 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
2237 #endif /* HAVE_OTF */
2240 ft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
2241 MFLTGlyphString *in, int from, int to,
2242 MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
2244 int len = to - from;
2247 MGlyph *in_glyphs = (MGlyph *) (in->glyphs);
2248 MGlyph *out_glyphs = out ? (MGlyph *) (out->glyphs) : NULL;
2251 OTF_GlyphString otf_gstring;
2253 char script[5], *langsys = NULL;
2254 char *gsub_features = NULL, *gpos_features = NULL;
2259 otf = get_otf (font, &face);
2262 OTF_tag_name (spec->script, script);
2265 langsys = alloca (5);
2266 OTF_tag_name (spec->langsys, langsys);
2268 for (i = 0; i < 2; i++)
2272 if (spec->features[i])
2274 for (j = 0; spec->features[i][j]; j++);
2276 p = gsub_features = alloca (6 * j);
2278 p = gpos_features = alloca (6 * j);
2279 for (j = 0; spec->features[i][j]; j++)
2281 if (spec->features[i][j] == 0xFFFFFFFF)
2282 *p++ = '*', *p++ = ',';
2285 OTF_tag_name (spec->features[i][j], p);
2294 otf_gstring.size = otf_gstring.used = len;
2295 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
2296 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
2297 for (i = 0; i < len; i++)
2299 otf_gstring.glyphs[i].c = ((MGlyph *)in->glyphs)[from + i].g.c & 0x11FFFF;
2300 otf_gstring.glyphs[i].glyph_id = ((MGlyph *)in->glyphs)[from + i].g.code;
2303 OTF_drive_gdef (otf, &otf_gstring);
2304 gidx = out ? out->used : from;
2308 OTF_Feature *features;
2311 if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
2314 features = otf->gsub->FeatureList.Feature;
2317 if (out->allocated < gidx + otf_gstring.used)
2319 for (i = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx;
2320 i < otf_gstring.used; i++, otfg++, g++, out->used++)
2322 int feature_idx = otfg->positioning_type >> 4;
2324 int min_from, max_to;
2326 *g = in_glyphs[from + otfg->f.index.from];
2327 min_from = g->g.from, max_to = g->g.to;
2329 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
2330 if (in_glyphs[from + j].g.code == otfg->glyph_id)
2332 g->g.c = in_glyphs[from + j].g.c;
2337 tag = features[feature_idx - 1].FeatureTag;
2338 tag = PACK_OTF_TAG (tag);
2339 g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
2341 for (j = otfg->f.index.from + 1; j <= otfg->f.index.to; j++)
2343 if (min_from > in_glyphs[from + j].g.from)
2344 min_from = in_glyphs[from + j].g.from;
2345 if (max_to < in_glyphs[from + j].g.to)
2346 max_to = in_glyphs[from + j].g.to;
2348 if (g->g.code != otfg->glyph_id)
2350 g->g.code = otfg->glyph_id;
2353 g->g.from = min_from, g->g.to = max_to;
2358 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
2361 int feature_idx = otfg->positioning_type >> 4;
2365 tag = features[feature_idx - 1].FeatureTag;
2366 tag = PACK_OTF_TAG (tag);
2367 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
2369 g = in_glyphs + (from + j);
2370 g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
2378 if (out->allocated < gidx + len)
2380 for (i = 0; i < len; i++)
2381 out_glyphs[out->used++] = in_glyphs[from + i];
2386 OTF_Feature *features;
2389 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
2392 features = otf->gpos->FeatureList.Feature;
2395 MGlyph *base = NULL, *mark = NULL;
2396 int x_ppem = face->size->metrics.x_ppem;
2397 int y_ppem = face->size->metrics.y_ppem;
2398 int x_scale = face->size->metrics.x_scale;
2399 int y_scale = face->size->metrics.y_scale;
2401 for (i = j = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx;
2402 i < otf_gstring.used; i++, otfg++)
2405 int adjust_idx = otfg->glyph_id ? j : j - 1;
2406 int feature_idx = otfg->positioning_type >> 4;
2410 tag = features[feature_idx - 1].FeatureTag;
2411 tag = PACK_OTF_TAG (tag);
2412 g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
2414 switch (otfg->positioning_type & 0xF)
2418 case 1: /* Single */
2421 int format = otfg->f.f1.format;
2423 if (format & OTF_XPlacement)
2424 adjustment[adjust_idx].xoff
2425 += otfg->f.f1.value->XPlacement * x_scale / 0x10000;
2426 if (format & OTF_XPlaDevice)
2427 adjustment[adjust_idx].xoff
2428 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
2429 if (format & OTF_YPlacement)
2430 adjustment[adjust_idx].yoff
2431 -= otfg->f.f1.value->YPlacement * y_scale / 0x10000;
2432 if (format & OTF_YPlaDevice)
2433 adjustment[adjust_idx].yoff
2434 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
2435 if (format & OTF_XAdvance)
2436 adjustment[adjust_idx].xadv
2437 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
2438 if (format & OTF_XAdvDevice)
2439 adjustment[adjust_idx].xadv
2440 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
2441 if (format & OTF_YAdvance)
2442 adjustment[adjust_idx].yadv
2443 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
2444 if (format & OTF_YAdvDevice)
2445 adjustment[adjust_idx].yadv
2446 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
2447 adjustment[adjust_idx].set = 1;
2450 case 3: /* Cursive */
2451 /* Not yet supported. */
2453 case 4: /* Mark-to-Base */
2454 case 5: /* Mark-to-Ligature */
2458 goto label_adjust_anchor;
2459 default: /* i.e. case 6 Mark-to-Mark */
2464 label_adjust_anchor:
2466 int base_x, base_y, mark_x, mark_y;
2467 int this_from, this_to;
2470 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
2471 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
2472 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
2473 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;;
2475 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2476 adjust_anchor (otfg->f.f4.base_anchor, face, prev->g.code,
2477 x_ppem, y_ppem, &base_x, &base_y);
2478 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2479 adjust_anchor (otfg->f.f4.mark_anchor, face, g->g.code,
2480 x_ppem, y_ppem, &mark_x, &mark_y);
2481 adjustment[adjust_idx].xoff = base_x - mark_x;
2482 adjustment[adjust_idx].yoff = - (base_y - mark_y);
2483 adjustment[adjust_idx].back = (g - prev);
2484 adjustment[adjust_idx].xadv = 0;
2485 adjustment[adjust_idx].advance_is_absolute = 1;
2486 adjustment[adjust_idx].set = 1;
2487 this_from = g->g.from;
2489 for (k = 0; prev + k < g; k++)
2491 if (this_from > prev[k].g.from)
2492 this_from = prev[k].g.from;
2493 if (this_to < prev[k].g.to)
2494 this_to = prev[k].g.to;
2496 for (; prev <= g; prev++)
2498 prev->g.from = this_from;
2499 prev->g.to = this_to;
2505 if (otfg->GlyphClass == OTF_GlyphClass0)
2507 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2517 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
2519 if (otfg->positioning_type & 0xF)
2521 int feature_idx = otfg->positioning_type >> 4;
2525 tag = features[feature_idx - 1].FeatureTag;
2526 tag = PACK_OTF_TAG (tag);
2527 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
2529 g = in_glyphs + (from + j);
2530 g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
2537 free (otf_gstring.glyphs);
2541 if (otf_gstring.glyphs)
2542 free (otf_gstring.glyphs);
2543 #endif /* HAVE_OTF */
2546 if (out->allocated < out->used + len)
2548 font->get_metrics (font, in, from, to);
2549 memcpy ((MGlyph *)out->glyphs + out->used, (MGlyph *) in->glyphs + from,
2550 sizeof (MGlyph) * len);
2557 ft_try_otf (MFLTFont *font, MFLTOtfSpec *spec,
2558 MFLTGlyphString *in, int from, int to)
2560 return ft_drive_otf (font, spec, in, from, to, NULL, NULL);
2565 static unsigned char *iterate_bitmap;
2568 iterate_callback (OTF *otf, const char *feature, unsigned glyph_id)
2570 if (glyph_id <= otf->cmap->max_glyph_id)
2571 iterate_bitmap[glyph_id / 8] |= 1 << (glyph_id % 8);
2576 ft_iterate_otf_feature (MFLTFont *font, MFLTOtfSpec *spec,
2577 int from, int to, unsigned char *table)
2579 OTF *otf = get_otf (font, NULL);
2582 unsigned char *bitmap = NULL;
2584 char script[5], *langsys = NULL;
2588 if (OTF_get_table (otf, "cmap") < 0)
2590 if (! spec->features[0])
2592 strcpy (id, "feature-");
2594 OTF_tag_name (spec->script, script);
2597 langsys = alloca (5);
2598 OTF_tag_name (spec->langsys, langsys);
2600 bmp_size = (otf->cmap->max_glyph_id / 8) + 1;
2601 for (i = 0; spec->features[0][i]; i++)
2605 OTF_tag_name (spec->features[0][i], id + 8);
2606 bmp = OTF_get_data (otf, id);
2609 iterate_bitmap = bmp = calloc (bmp_size, 1);
2610 OTF_iterate_gsub_feature (otf, iterate_callback,
2611 script, langsys, id + 8);
2612 OTF_put_data (otf, id, bmp, free);
2614 if (i == 0 && ! spec->features[0][1])
2615 /* Single feature */
2621 bitmap = alloca (bmp_size);
2622 memcpy (bitmap, bmp, bmp_size);
2628 for (j = 0; j < bmp_size; j++)
2629 bitmap[j] &= bmp[j];
2633 for (i = 0; i < bmp_size; i++)
2636 for (j = 0; j < 8; j++)
2637 if (bitmap[i] & (1 << j))
2639 int c = OTF_get_unicode (otf, (i * 8) + j);
2641 if (c >= from && c <= to)
2642 table[c - from] = 1;
2653 MFontDriver mfont__ft_driver =
2654 { ft_select, ft_open, ft_find_metric, ft_has_char, ft_encode_char,
2655 ft_render, ft_list, ft_list_family_names, ft_check_capability,
2656 ft_encapsulate, ft_close, ft_check_otf, ft_drive_otf, ft_try_otf,
2658 ft_iterate_otf_feature
2659 #endif /* HAVE_OTF */
2667 if (FT_Init_FreeType (&ft_library) != 0)
2668 MERROR (MERROR_FONT_FT, -1);
2670 for (i = 0; i < ft_to_prop_size; i++)
2671 ft_to_prop[i].len = strlen (ft_to_prop[i].ft_style);
2673 Mmedium = msymbol ("medium");
2675 Mnull = msymbol ("");
2677 M0[0] = msymbol ("0-0");
2678 M0[1] = msymbol ("0-1");
2679 M0[2] = msymbol ("0-2");
2680 M0[3] = msymbol ("0-3");
2681 M0[4] = msymbol ("0-4");
2682 M3_1 = msymbol ("3-1");
2683 M1_0 = msymbol ("1-0");
2685 #ifdef HAVE_FONTCONFIG
2686 for (i = 0; i < (sizeof (fc_all_table) / sizeof fc_all_table[0]); i++)
2688 FC_vs_M17N_font_prop *table = fc_all_table[i];
2691 for (j = 0; table[j].m17n_value; j++)
2692 table[j].sym = msymbol (table[j].m17n_value);
2693 table[j].sym = table[j - 1].sym;
2700 MSymbol serif, sans_serif, monospace;
2702 fc_config = FcInitLoadConfigAndFonts ();
2703 if (mfont_freetype_path)
2705 MPLIST_DO (plist, mfont_freetype_path)
2706 if (MPLIST_STRING_P (plist)
2707 && (pathname = MPLIST_STRING (plist))
2708 && stat (pathname, &buf) == 0)
2710 FcStrList *strlist = FcConfigGetFontDirs (fc_config);
2713 while ((dir = FcStrListNext (strlist)))
2714 if (strcmp ((char *) dir, pathname) == 0)
2717 FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname);
2718 FcStrListDone (strlist);
2721 Mgeneric_family = msymbol ("generic famly");
2722 serif = msymbol ("serif");
2723 msymbol_put (serif, Mgeneric_family, serif);
2724 sans_serif = msymbol ("sans-serif");
2725 msymbol_put (sans_serif, Mgeneric_family, sans_serif);
2726 msymbol_put (msymbol ("sans serif"), Mgeneric_family, sans_serif);
2727 msymbol_put (msymbol ("sans"), Mgeneric_family, sans_serif);
2728 monospace = msymbol ("monospace");
2729 msymbol_put (monospace, Mgeneric_family, monospace);
2730 msymbol_put (msymbol ("mono"), Mgeneric_family, monospace);
2732 #endif /* HAVE_FONTCONFIG */
2742 if (ft_default_list)
2744 M17N_OBJECT_UNREF (ft_default_list);
2745 ft_default_list = NULL;
2750 MPLIST_DO (plist, ft_font_list)
2752 if (MPLIST_VAL (plist))
2753 MPLIST_DO (p, MPLIST_VAL (plist))
2755 if (MPLIST_KEY (p) != Mt)
2756 free_ft_info (MPLIST_VAL (p));
2758 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2760 M17N_OBJECT_UNREF (ft_font_list);
2761 ft_font_list = NULL;
2763 if (ft_language_list)
2765 MPLIST_DO (plist, ft_language_list)
2766 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2767 M17N_OBJECT_UNREF (ft_language_list);
2768 ft_language_list = NULL;
2773 MPLIST_DO (plist, ft_script_list)
2774 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2775 M17N_OBJECT_UNREF (ft_script_list);
2776 ft_script_list = NULL;
2779 if (ft_capability_list)
2781 MPLIST_DO (plist, ft_capability_list)
2782 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2783 M17N_OBJECT_UNREF (ft_capability_list);
2784 ft_capability_list = NULL;
2789 MPLIST_DO (plist, ft_file_list)
2790 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2791 M17N_OBJECT_UNREF (ft_file_list);
2792 ft_file_list = NULL;
2795 FT_Done_FreeType (ft_library);
2796 #ifdef HAVE_FONTCONFIG
2797 FcConfigDestroy (fc_config);
2799 #endif /* HAVE_FONTCONFIG */
2800 all_fonts_scaned = 0;
2803 #ifdef HAVE_FONTCONFIG
2806 mfont__ft_parse_name (const char *name, MFont *font)
2808 FcPattern *pat = FcNameParse ((FcChar8 *) name);
2817 if (FcPatternGetString (pat, FC_FOUNDRY, 0, &str) == FcResultMatch)
2819 STRDUP_LOWER (buf, bufsize, (char *) str);
2820 mfont__set_property (font, MFONT_FOUNDRY, msymbol (buf));
2822 if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
2824 STRDUP_LOWER (buf, bufsize, (char *) str);
2825 mfont__set_property (font, MFONT_FAMILY, msymbol (buf));
2827 if (FcPatternGetInteger (pat, FC_WEIGHT, 0, &val) == FcResultMatch)
2828 mfont__set_property (font, MFONT_WEIGHT,
2829 fc_decode_prop (val, fc_weight_table,
2830 fc_weight_table_size));
2831 if (FcPatternGetInteger (pat, FC_SLANT, 0, &val) == FcResultMatch)
2832 mfont__set_property (font, MFONT_STYLE,
2833 fc_decode_prop (val, fc_slant_table,
2834 fc_slant_table_size));
2835 if (FcPatternGetInteger (pat, FC_WIDTH, 0, &val) == FcResultMatch)
2836 mfont__set_property (font, MFONT_STRETCH,
2837 fc_decode_prop (val, fc_width_table,
2838 fc_width_table_size));
2839 if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
2840 font->size = size * 10 + 0.5;
2841 else if (FcPatternGetDouble (pat, FC_SIZE, 0, &size) == FcResultMatch)
2842 font->size = - (size * 10 + 0.5);
2843 if (FcPatternGetString (pat, FC_FILE, 0, &str) == FcResultMatch)
2845 font->file = msymbol ((char *) str);
2847 mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
2848 font->type = MFONT_TYPE_SPEC;
2849 FcPatternDestroy (pat);
2854 mfont__ft_unparse_name (MFont *font)
2856 FcPattern *pat = fc_get_pattern (font);
2857 char *name = (char *) FcNameUnparse (pat);
2859 FcPatternDestroy (pat);
2862 #endif /* HAVE_FONTCONFIG */
2864 #endif /* HAVE_FREETYPE */