1 /* font-ft.c -- FreeType interface sub-module.
2 Copyright (C) 2003, 2004, 2007, 2008
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 && cap->features[MFONT_OTT_GSUB].tags[0]
1062 && (OTF_check_features
1064 cap->script_tag, cap->langsys_tag,
1065 cap->features[MFONT_OTT_GSUB].tags,
1066 cap->features[MFONT_OTT_GSUB].nfeatures) != 1))
1068 if (cap->features[MFONT_OTT_GPOS].nfeatures
1069 && cap->features[MFONT_OTT_GPOS].tags[0]
1070 && (OTF_check_features
1072 cap->script_tag, cap->langsys_tag,
1073 cap->features[MFONT_OTT_GPOS].tags,
1074 cap->features[MFONT_OTT_GPOS].nfeatures) != 1))
1077 #else /* not HAVE_OTF */
1079 #endif /* not HAVE_OTF */
1083 ft_check_language (MFontFT *ft_info, MSymbol language, FT_Face ft_face)
1087 int ft_face_allocaed = 0;
1091 #ifdef HAVE_FONTCONFIG
1092 if (ft_info->langset
1093 && (FcLangSetHasLang (ft_info->langset,
1094 (FcChar8 *) MSYMBOL_NAME (language))
1095 != FcLangDifferentLang))
1097 #endif /* HAVE_FONTCONFIG */
1099 mt = mlanguage_text (language);
1100 if (! mt || mtext_nchars (mt) == 0)
1105 char *filename = MSYMBOL_NAME (ft_info->font.file);
1107 if (FT_New_Face (ft_library, filename, 0, &ft_face))
1109 ft_face_allocaed = 1;
1112 len = mtext_nchars (mt);
1113 extra = mtext_get_prop (mt, 0, Mtext);
1114 total_len = len + (extra ? mtext_nchars (extra) : 0);
1116 for (i = 0; i < total_len; i++)
1118 int c = (i < len ? mtext_ref_char (mt, i)
1119 : mtext_ref_char (extra, i - len));
1121 #ifdef HAVE_FONTCONFIG
1122 if (ft_info->charset
1123 && FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcFalse)
1125 #endif /* HAVE_FONTCONFIG */
1126 if (FT_Get_Char_Index (ft_face, (FT_ULong) c) == 0)
1130 if (ft_face_allocaed)
1131 FT_Done_Face (ft_face);
1133 return (i == total_len ? 0 : -1);
1137 ft_check_script (MFontFT *ft_info, MSymbol script, FT_Face ft_face)
1139 MPlist *char_list = mscript__char_list (script);
1143 #ifdef HAVE_FONTCONFIG
1144 if (ft_info->charset)
1146 MPLIST_DO (char_list, char_list)
1147 if (FcCharSetHasChar (ft_info->charset,
1148 (FcChar32) MPLIST_INTEGER (char_list)) == FcFalse)
1152 #endif /* HAVE_FONTCONFIG */
1154 int ft_face_allocaed = 0;
1158 char *filename = MSYMBOL_NAME (ft_info->font.file);
1160 if (FT_New_Face (ft_library, filename, 0, &ft_face))
1162 ft_face_allocaed = 1;
1165 MPLIST_DO (char_list, char_list)
1166 if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (char_list))
1169 if (ft_face_allocaed)
1170 FT_Done_Face (ft_face);
1173 return (MPLIST_TAIL_P (char_list) ? 0 : -1);
1176 static MPlist *ft_default_list;
1181 if (ft_default_list)
1182 return ft_default_list;
1183 ft_default_list = mplist ();
1184 #ifdef HAVE_FONTCONFIG
1186 FcPattern *pat = FcPatternCreate ();
1192 FcConfigSubstitute (fc_config, pat, FcMatchPattern);
1193 for (i = 0; FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
1199 STRDUP_LOWER (buf, bufsize, (char *) fam);
1200 family = msymbol (buf);
1201 if (msymbol_get (family, Mgeneric_family))
1203 plist = MPLIST_PLIST (ft_list_family (family, 0, 1));
1204 MPLIST_DO (plist, plist)
1205 mplist_add (ft_default_list, family, MPLIST_VAL (plist));
1208 #else /* not HAVE_FONTCONFIG */
1212 MPLIST_DO (plist, ft_list_family (Mnil, 0, 1))
1214 pl = MPLIST_PLIST (plist);
1215 if (! MPLIST_TAIL_P (pl))
1216 mplist_add (ft_default_list, MPLIST_KEY (plist), pl);
1219 #endif /* not HAVE_FONTCONFIG */
1220 return ft_default_list;
1224 static MPlist *ft_capability_list;
1227 ft_list_capability (MSymbol capability)
1229 MFontCapability *cap;
1230 MPlist *plist = NULL, *pl;
1232 if (! ft_capability_list)
1233 ft_capability_list = mplist ();
1234 else if ((plist = mplist_find_by_key (ft_capability_list, capability)))
1235 return (MPLIST_VAL (plist) ? MPLIST_VAL (plist) : NULL);
1237 cap = mfont__get_capability (capability);
1239 if (cap && cap->language != Mnil)
1241 plist = ft_list_language (cap->language);
1244 plist = mplist_copy (plist);
1247 if (cap && cap->script != Mnil)
1251 plist = ft_list_script (cap->script);
1254 plist = mplist_copy (plist);
1258 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1260 if (ft_check_script (MPLIST_VAL (pl), cap->script, NULL) < 0)
1263 pl = MPLIST_NEXT (pl);
1267 if (cap->script_tag)
1269 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1271 if (ft_check_cap_otf (MPLIST_VAL (pl), cap, NULL) < 0)
1274 pl = MPLIST_NEXT (pl);
1278 if (MPLIST_TAIL_P (plist))
1280 M17N_OBJECT_UNREF (plist);
1285 mplist_push (ft_capability_list, capability, plist);
1291 ft_list_file (MSymbol filename)
1293 MPlist *plist = NULL;
1296 ft_file_list = mplist ();
1297 else if ((plist = mplist_find_by_key (ft_file_list, filename)))
1298 return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
1300 #ifdef HAVE_FONTCONFIG
1302 FcPattern *pattern = FcPatternCreate ();
1306 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) MSYMBOL_NAME (filename));
1307 os = FcObjectSetBuild (FC_FAMILY, NULL);
1308 fs = FcFontList (fc_config, pattern, os);
1315 if (FcPatternGetString (fs->fonts[0], FC_FAMILY, 0,
1316 (FcChar8 **) &fam) == FcResultMatch)
1321 STRDUP_LOWER (buf, bufsize, fam);
1322 family = msymbol (buf);
1323 pl = ft_list_family (family, 0, 1);
1324 MPLIST_DO (pl, MPLIST_PLIST (pl))
1326 MFontFT *ft_info = MPLIST_VAL (pl);
1328 if (ft_info->font.file == filename)
1331 mplist_add (plist, family, ft_info);
1338 #else /* not HAVE_FONTCONFIG */
1342 MPLIST_DO (pl, ft_list_family (Mnil, 0, 1))
1344 MPLIST_DO (p, MPLIST_PLIST (pl))
1346 MFontFT *ft_info = MPLIST_VAL (pl);
1348 if (ft_info->font.file == filename)
1351 mplist_add (plist, MPLIST_KEY (pl), ft_info);
1359 #endif /* not HAVE_FONTCONFIG */
1361 mplist_push (ft_file_list, filename, plist);
1365 /* The FreeType font driver function SELECT. */
1368 ft_select (MFrame *frame, MFont *font, int limited_size)
1370 MFont *found = NULL;
1371 #ifdef HAVE_FONTCONFIG
1374 int check_font_property = 1;
1376 if (font->file != Mnil)
1378 plist = ft_list_file (font->file);
1381 check_font_property = 0;
1385 MSymbol family = FONT_PROPERTY (font, MFONT_FAMILY);
1388 plist = MPLIST_PLIST (ft_list_family (family, 1, 1));
1390 plist = ft_list_default ();
1391 if (MPLIST_TAIL_P (plist))
1395 plist = mplist_copy (plist);
1397 if (font->capability != Mnil)
1399 MFontCapability *cap = mfont__get_capability (font->capability);
1401 for (pl = plist; ! MPLIST_TAIL_P (pl);)
1403 if (cap->script_tag && ft_check_cap_otf (MPLIST_VAL (pl), cap, NULL) < 0)
1409 && ft_check_language (MPLIST_VAL (pl), cap->language, NULL) < 0)
1412 pl = MPLIST_NEXT (pl);
1416 if (check_font_property)
1418 MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT);
1419 MSymbol style = FONT_PROPERTY (font, MFONT_STYLE);
1420 MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH);
1421 MSymbol alternate_weight = Mnil;
1423 if (weight == Mnormal)
1424 alternate_weight = Mmedium;
1425 else if (weight == Mmedium)
1426 alternate_weight = Mnormal;
1427 if (weight != Mnil || style != Mnil || stretch != Mnil || font->size > 0)
1428 for (pl = plist; ! MPLIST_TAIL_P (pl); )
1430 ft_info = MPLIST_VAL (pl);
1432 && (weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT)
1433 && alternate_weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT)))
1435 && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE))
1437 && stretch != FONT_PROPERTY (&ft_info->font,
1440 && ft_info->font.size > 0
1441 && ft_info->font.size != font->size))
1444 pl = MPLIST_NEXT (pl);
1448 MPLIST_DO (pl, plist)
1450 font = MPLIST_VAL (plist);
1451 if (limited_size == 0
1453 || font->size <= limited_size)
1459 M17N_OBJECT_UNREF (plist);
1460 #endif /* HAVE_FONTCONFIG */
1465 static MRealizedFont *
1466 ft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1468 MFontFT *ft_info = (MFontFT *) font;
1469 int reg = spec->property[MFONT_REGISTRY];
1470 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
1471 MRealizedFontFT *ft_rfont;
1473 MPlist *plist, *charmap_list = NULL;
1478 /* non-scalable font */
1480 else if (spec->size)
1482 int ratio = mfont_resize_ratio (font);
1484 size = ratio == 100 ? spec->size : spec->size * ratio / 100;
1491 charmap_list = ((MRealizedFontFT *) rfont->info)->charmap_list;
1492 for (; rfont; rfont = rfont->next)
1493 if (rfont->font == font
1494 && (rfont->font->size ? rfont->font->size == size
1495 : rfont->spec.size == size)
1496 && rfont->spec.property[MFONT_REGISTRY] == reg
1497 && rfont->driver == &mfont__ft_driver)
1501 MDEBUG_DUMP (" [FONT-FT] opening ", "", mdebug_dump_font (&ft_info->font));
1503 if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0,
1506 font->type = MFONT_TYPE_FAILURE;
1507 MDEBUG_PRINT (" no (FT_New_Face)\n");
1511 M17N_OBJECT_REF (charmap_list);
1513 charmap_list = ft_get_charmaps (ft_face);
1514 if (registry == Mnil)
1515 registry = Municode_bmp;
1516 plist = mplist_find_by_key (charmap_list, registry);
1519 FT_Done_Face (ft_face);
1520 M17N_OBJECT_UNREF (charmap_list);
1521 MDEBUG_PRINT1 (" no (%s)\n", MSYMBOL_NAME (registry));
1524 charmap_index = (int) MPLIST_VAL (plist);
1525 if ((charmap_index >= 0
1526 && FT_Set_Charmap (ft_face, ft_face->charmaps[charmap_index]))
1527 || FT_Set_Pixel_Sizes (ft_face, 0, size / 10))
1529 FT_Done_Face (ft_face);
1530 M17N_OBJECT_UNREF (charmap_list);
1531 font->type = MFONT_TYPE_FAILURE;
1532 MDEBUG_PRINT1 (" no (size %d)\n", size);
1536 M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
1537 ft_rfont->ft_face = ft_face;
1538 ft_rfont->charmap_list = charmap_list;
1539 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
1540 rfont->id = ft_info->font.file;
1541 rfont->spec = *font;
1542 rfont->spec.type = MFONT_TYPE_REALIZED;
1543 rfont->spec.property[MFONT_REGISTRY] = reg;
1544 rfont->spec.size = size;
1545 rfont->frame = frame;
1547 rfont->driver = &mfont__ft_driver;
1548 rfont->info = ft_rfont;
1549 rfont->fontp = ft_face;
1550 rfont->ascent = ft_face->size->metrics.ascender;
1551 rfont->descent = - ft_face->size->metrics.descender;
1552 rfont->max_advance = ft_face->size->metrics.max_advance;
1553 rfont->baseline_offset = 0;
1554 rfont->x_ppem = ft_face->size->metrics.x_ppem;
1555 rfont->y_ppem = ft_face->size->metrics.y_ppem;
1558 BDF_PropertyRec prop;
1560 if (! FT_IS_SCALABLE (ft_face)
1561 && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
1563 rfont->baseline_offset = prop.u.integer << 6;
1564 rfont->ascent += prop.u.integer << 6;
1565 rfont->descent -= prop.u.integer << 6;
1568 #endif /* HAVE_FTBDF_H */
1569 if (FT_IS_SCALABLE (ft_face))
1570 rfont->average_width = 0;
1572 rfont->average_width = ft_face->available_sizes->width << 6;
1573 rfont->next = MPLIST_VAL (frame->realized_font_list);
1574 MPLIST_VAL (frame->realized_font_list) = rfont;
1575 MDEBUG_PRINT (" ok\n");
1579 /* The FreeType font driver function FIND_METRIC. */
1582 ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1585 FT_Face ft_face = rfont->fontp;
1586 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1588 for (; g != gend; g++)
1592 if (g->g.code == MCHAR_INVALID_CODE)
1594 if (FT_IS_SCALABLE (ft_face))
1597 g->g.rbearing = ft_face->size->metrics.max_advance;
1598 g->g.xadv = g->g.rbearing;
1599 g->g.ascent = ft_face->size->metrics.ascender;
1600 g->g.descent = - ft_face->size->metrics.descender;
1605 BDF_PropertyRec prop;
1606 #endif /* HAVE_FTBDF_H */
1609 g->g.rbearing = g->g.xadv = ft_face->available_sizes->width << 6;
1611 if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
1613 g->g.ascent = prop.u.integer << 6;
1614 FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
1615 g->g.descent = prop.u.integer << 6;
1616 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET",
1619 g->g.ascent += prop.u.integer << 6;
1620 g->g.descent -= prop.u.integer << 6;
1624 #endif /* HAVE_FTBDF_H */
1626 g->g.ascent = ft_face->available_sizes->height << 6;
1633 FT_Glyph_Metrics *metrics;
1635 FT_Load_Glyph (ft_face, (FT_UInt) g->g.code, FT_LOAD_DEFAULT);
1636 metrics = &ft_face->glyph->metrics;
1637 g->g.lbearing = metrics->horiBearingX;
1638 g->g.rbearing = metrics->horiBearingX + metrics->width;
1639 g->g.xadv = metrics->horiAdvance;
1640 g->g.ascent = metrics->horiBearingY;
1641 g->g.descent = metrics->height - metrics->horiBearingY;
1644 g->g.ascent += rfont->baseline_offset;
1645 g->g.descent -= rfont->baseline_offset;
1651 ft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1653 MRealizedFont *rfont = NULL;
1654 MRealizedFontFT *ft_rfont;
1657 if (font->type == MFONT_TYPE_REALIZED)
1658 rfont = (MRealizedFont *) font;
1659 else if (font->type == MFONT_TYPE_OBJECT)
1661 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1662 rfont = rfont->next)
1663 if (rfont->font == font && rfont->driver == &mfont__ft_driver)
1667 #ifdef HAVE_FONTCONFIG
1668 MFontFT *ft_info = (MFontFT *) font;
1670 if (! ft_info->charset)
1672 FcPattern *pat = FcPatternBuild (NULL, FC_FILE, FcTypeString,
1673 MSYMBOL_NAME (font->file),
1675 FcObjectSet *os = FcObjectSetBuild (FC_CHARSET, NULL);
1676 FcFontSet *fs = FcFontList (fc_config, pat, os);
1679 && FcPatternGetCharSet (fs->fonts[0], FC_CHARSET, 0,
1680 &ft_info->charset) == FcResultMatch)
1681 ft_info->charset = FcCharSetCopy (ft_info->charset);
1683 ft_info->charset = FcCharSetCreate ();
1684 FcFontSetDestroy (fs);
1685 FcObjectSetDestroy (os);
1686 FcPatternDestroy (pat);
1688 return (FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcTrue);
1689 #else /* not HAVE_FONTCONFIG */
1690 rfont = ft_open (frame, font, spec, NULL);
1691 #endif /* not HAVE_FONTCONFIG */
1695 MFATAL (MERROR_FONT_FT);
1699 ft_rfont = rfont->info;
1700 idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code);
1704 /* The FreeType font driver function ENCODE_CHAR. */
1707 ft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1709 MRealizedFont *rfont;
1710 MRealizedFontFT *ft_rfont;
1713 if (font->type == MFONT_TYPE_REALIZED)
1714 rfont = (MRealizedFont *) font;
1715 else if (font->type == MFONT_TYPE_OBJECT)
1717 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
1718 rfont = rfont->next)
1719 if (rfont->font == font && rfont->driver == &mfont__ft_driver)
1723 rfont = ft_open (frame, font, spec, NULL);
1729 MFATAL (MERROR_FONT_FT);
1731 ft_rfont = rfont->info;
1732 idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code);
1733 return (idx ? (unsigned) idx : MCHAR_INVALID_CODE);
1736 /* The FreeType font driver function RENDER. */
1738 #define NUM_POINTS 0x1000
1741 MDrawPoint points[NUM_POINTS];
1746 ft_render (MDrawWindow win, int x, int y,
1747 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1748 int reverse, MDrawRegion region)
1751 MRealizedFace *rface = from->rface;
1752 MFrame *frame = rface->frame;
1753 FT_Int32 load_flags = FT_LOAD_RENDER;
1756 MPointTable point_table[8];
1757 int baseline_offset;
1758 int pixel_mode = -1;
1763 /* It is assured that the all glyphs in the current range use the
1764 same realized face. */
1765 ft_face = rface->rfont->fontp;
1766 baseline_offset = rface->rfont->baseline_offset >> 6;
1768 if (! gstring->anti_alias)
1770 #ifdef FT_LOAD_TARGET_MONO
1771 load_flags |= FT_LOAD_TARGET_MONO;
1773 load_flags |= FT_LOAD_MONOCHROME;
1777 for (i = 0; i < 8; i++)
1778 point_table[i].p = point_table[i].points;
1780 for (g = from; g < to; x += g++->g.xadv)
1784 MPointTable *ptable;
1788 FT_Load_Glyph (ft_face, (FT_UInt) g->g.code, load_flags);
1790 pixel_mode = ft_face->glyph->bitmap.pixel_mode;
1791 yoff = y - ft_face->glyph->bitmap_top + g->g.yoff;
1792 bmp = ft_face->glyph->bitmap.buffer;
1793 width = ft_face->glyph->bitmap.width;
1794 pitch = ft_face->glyph->bitmap.pitch;
1796 if (pixel_mode != FT_PIXEL_MODE_MONO)
1797 for (i = 0; i < ft_face->glyph->bitmap.rows;
1798 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
1800 xoff = x + ft_face->glyph->bitmap_left + g->g.xoff;
1801 for (j = 0; j < width; j++, xoff++)
1803 intensity = bmp[j] >> 5;
1806 ptable = point_table + intensity;
1807 ptable->p->x = xoff;
1808 ptable->p->y = yoff - baseline_offset;
1810 if (ptable->p - ptable->points == NUM_POINTS)
1812 (*frame->driver->draw_points)
1814 reverse ? 7 - intensity : intensity,
1815 ptable->points, NUM_POINTS, region);
1816 ptable->p = ptable->points;
1822 for (i = 0; i < ft_face->glyph->bitmap.rows;
1823 i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
1825 xoff = x + ft_face->glyph->bitmap_left + g->g.xoff;
1826 for (j = 0; j < width; j++, xoff++)
1828 intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
1831 ptable = point_table;
1832 ptable->p->x = xoff;
1833 ptable->p->y = yoff - baseline_offset;
1835 if (ptable->p - ptable->points == NUM_POINTS)
1837 (*frame->driver->draw_points) (frame, win, rface,
1839 ptable->points, NUM_POINTS, region);
1840 ptable->p = ptable->points;
1847 if (pixel_mode != FT_PIXEL_MODE_MONO)
1849 for (i = 1; i < 8; i++)
1850 if (point_table[i].p != point_table[i].points)
1851 (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i,
1852 point_table[i].points,
1853 point_table[i].p - point_table[i].points, region);
1857 if (point_table[0].p != point_table[0].points)
1858 (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7,
1859 point_table[0].points,
1860 point_table[0].p - point_table[0].points, region);
1865 ft_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
1867 MPlist *pl = NULL, *p;
1869 MPlist *file_list = NULL;
1870 MPlist *family_list = NULL, *capability_list = NULL;
1871 MSymbol registry = Mnil;
1873 MDEBUG_DUMP (" [FONT-FT] listing ", "", mdebug_dump_font (font));
1879 registry = FONT_PROPERTY (font, MFONT_REGISTRY);
1880 if (registry != Mnil && registry != Miso8859_1)
1882 char *reg = MSYMBOL_NAME (registry);
1884 if (strncmp (reg, "unicode-", 8)
1885 && strncmp (reg, "apple-roman", 11)
1886 && (reg[0] < '0' || reg[0] > '9' || reg[1] != '-'))
1890 if (font->file != Mnil
1891 && ! (file_list = ft_list_file (font->file)))
1893 family = FONT_PROPERTY (font, MFONT_FAMILY);
1895 && (family_list = MPLIST_PLIST (ft_list_family (family, 1, 1)))
1896 && MPLIST_TAIL_P (family_list))
1898 if (font->capability != Mnil)
1900 capability_list = ft_list_capability (font->capability);
1901 if (! capability_list || MPLIST_TAIL_P (capability_list))
1906 if (! file_list && ! family_list && ! capability_list)
1908 /* No restriction. Get all fonts. */
1910 MPLIST_DO (family_list, ft_list_family (Mnil, 0, 1))
1912 MPLIST_DO (p, MPLIST_PLIST (family_list))
1913 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1921 mplist_push (pl, MPLIST_KEY (file_list), MPLIST_VAL (file_list));
1926 for (p = pl; ! MPLIST_TAIL_P (p);)
1928 if (mplist_find_by_value (family_list, MPLIST_VAL (p)))
1929 p = MPLIST_NEXT (p);
1936 MPLIST_DO (p, family_list)
1937 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1940 if (capability_list)
1943 for (p = pl; ! MPLIST_TAIL_P (p);)
1945 if (mplist_find_by_value (capability_list, MPLIST_VAL (p)))
1946 p = MPLIST_NEXT (p);
1953 MPLIST_DO (p, capability_list)
1954 mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p));
1960 && (font->property[MFONT_WEIGHT] + font->property[MFONT_STYLE]
1961 + font->property[MFONT_STRETCH] + font->size) > 0)
1963 MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT);
1964 MSymbol style = FONT_PROPERTY (font, MFONT_STYLE);
1965 MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH);
1966 int size = font->size;
1968 for (p = pl; ! MPLIST_TAIL_P (p); )
1970 MFontFT *ft_info = MPLIST_VAL (p);
1973 && weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT))
1975 && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE))
1977 && stretch != FONT_PROPERTY (&ft_info->font,
1980 && ft_info->font.size > 0
1981 && ft_info->font.size != size))
1984 p = MPLIST_NEXT (p);
1990 mplist_push (plist, MPLIST_KEY (p), MPLIST_VAL (p));
1992 if (maxnum && maxnum <= num)
1995 M17N_OBJECT_UNREF (pl);
1998 MDEBUG_PRINT1 (" %d found\n", num);
2003 ft_list_family_names (MFrame *frame, MPlist *plist)
2009 #ifdef HAVE_FONTCONFIG
2010 fc_init_font_list ();
2011 #else /* not HAVE_FONTCONFIG */
2012 ft_init_font_list ();
2013 #endif /* not HAVE_FONTCONFIG */
2016 MPLIST_DO (pl, ft_font_list)
2018 MSymbol family = MPLIST_KEY (pl);
2021 #ifdef HAVE_FONTCONFIG
2022 if (msymbol_get (family, Mgeneric_family) != Mnil)
2024 #endif /* HAVE_FONTCONFIG */
2025 MPLIST_DO (p, plist)
2027 MSymbol sym = MPLIST_SYMBOL (p);
2031 if (strcmp (MSYMBOL_NAME (sym), MSYMBOL_NAME (family)) > 0)
2033 mplist_push (p, Msymbol, family);
2037 if (MPLIST_TAIL_P (p))
2038 mplist_push (p, Msymbol, family);
2043 ft_check_capability (MRealizedFont *rfont, MSymbol capability)
2045 MFontFT *ft_info = (MFontFT *) rfont->font;
2046 MRealizedFontFT *ft_rfont = rfont->info;
2047 MFontCapability *cap = mfont__get_capability (capability);
2049 if (cap->script_tag)
2051 if (ft_check_cap_otf (ft_info, cap, ft_rfont->ft_face) < 0)
2054 else if (cap->script != Mnil
2055 && ft_check_script (ft_info, cap->script, ft_rfont->ft_face) < 0)
2057 if (cap->language != Mnil
2058 && ft_check_language (ft_info, cap->language, ft_rfont->ft_face) < 0)
2063 static MRealizedFont *
2064 ft_encapsulate (MFrame *frame, MSymbol data_type, void *data)
2067 MRealizedFont *rfont;
2068 MRealizedFontFT *ft_rfont;
2071 if (data_type == Mfontconfig)
2073 #ifdef HAVE_FONTCONFIG
2074 FcPattern *pattern = data;
2076 if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &ft_face)
2079 ft_info = fc_gen_font (pattern, NULL);
2080 #else /* not HAVE_FONTCONFIG */
2082 #endif /* not HAVE_FONTCONFIG */
2084 else if (data_type == Mfreetype)
2087 ft_info = ft_gen_font (ft_face);
2092 M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT);
2093 ft_rfont->ft_face = ft_face;
2094 ft_rfont->face_encapsulated = 1;
2096 MDEBUG_DUMP (" [FONT-FT] encapsulating ", (char *) ft_face->family_name,);
2098 MSTRUCT_CALLOC (rfont, MERROR_FONT_FT);
2099 rfont->id = ft_info->font.file;
2100 rfont->font = (MFont *) ft_info;
2101 rfont->info = ft_rfont;
2102 rfont->fontp = ft_face;
2103 rfont->driver = &mfont__ft_driver;
2104 rfont->spec = ft_info->font;
2105 rfont->spec.type = MFONT_TYPE_REALIZED;
2106 rfont->frame = frame;
2107 rfont->ascent = ft_face->size->metrics.ascender >> 6;
2108 rfont->descent = - ft_face->size->metrics.descender >> 6;
2109 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
2110 rfont->baseline_offset = 0;
2111 rfont->x_ppem = ft_face->size->metrics.x_ppem;
2112 rfont->y_ppem = ft_face->size->metrics.y_ppem;
2115 BDF_PropertyRec prop;
2117 if (! FT_IS_SCALABLE (ft_face)
2118 && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
2120 rfont->baseline_offset = prop.u.integer << 6;
2121 rfont->ascent += prop.u.integer << 6;
2122 rfont->descent -= prop.u.integer << 6;
2125 #endif /* HAVE_FTBDF_H */
2126 if (FT_IS_SCALABLE (ft_face))
2127 rfont->average_width = 0;
2129 rfont->average_width = ft_face->available_sizes->width << 6;
2130 rfont->next = MPLIST_VAL (frame->realized_font_list);
2131 MPLIST_VAL (frame->realized_font_list) = rfont;
2137 ft_close (MRealizedFont *rfont)
2139 if (! rfont->encapsulating)
2142 M17N_OBJECT_UNREF (rfont->info);
2147 get_otf (MFLTFont *font, FT_Face *ft_face)
2149 MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
2150 MFontFT *ft_info = (MFontFT *) rfont->font;
2151 MRealizedFontFT *ft_rfont = rfont->info;
2152 OTF *otf = ft_info->otf;
2156 #if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
2157 otf = OTF_open_ft_face (ft_rfont->ft_face);
2159 otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
2161 if (! otf || OTF_get_table (otf, "head") < 0)
2166 *ft_face = ft_rfont->ft_face;
2167 return (otf == invalid_otf ? NULL : otf);
2171 ft_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
2176 OTF *otf = get_otf (font, NULL);
2180 for (i = 0; i < 2; i++)
2182 if (! spec->features[i])
2184 for (n = 0; spec->features[i][n]; n++);
2185 tags = alloca (sizeof (OTF_Tag) * n);
2186 for (n = 0, negative = 0; spec->features[i][n]; n++)
2188 if (spec->features[i][n] == 0xFFFFFFFF)
2191 tags[n - 1] = spec->features[i][n] | 0x80000000;
2193 tags[n] = spec->features[i][n];
2195 if (n - negative > 0
2196 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
2197 tags, n - negative) != 1)
2201 #endif /* HAVE_OTF */
2203 return ((! spec->features[0] || spec->features[0][0] == 0xFFFFFFFF)
2204 && (! spec->features[1] || spec->features[1][0] == 0xFFFFFFFF));
2209 #define DEVICE_DELTA(table, size) \
2210 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
2211 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
2215 adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
2216 unsigned code, int x_ppem, int y_ppem, int *x, int *y)
2218 if (anchor->AnchorFormat == 2)
2220 FT_Outline *outline;
2221 int ap = anchor->f.f1.AnchorPoint;
2223 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
2224 outline = &ft_face->glyph->outline;
2225 if (ap < outline->n_points)
2227 *x = outline->points[ap].x << 6;
2228 *y = outline->points[ap].y << 6;
2231 else if (anchor->AnchorFormat == 3)
2233 if (anchor->f.f2.XDeviceTable.offset)
2234 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
2235 if (anchor->f.f2.YDeviceTable.offset)
2236 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
2239 #endif /* HAVE_OTF */
2242 ft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
2243 MFLTGlyphString *in, int from, int to,
2244 MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
2246 int len = to - from;
2249 MGlyph *in_glyphs = (MGlyph *) (in->glyphs);
2250 MGlyph *out_glyphs = (MGlyph *) (out->glyphs);
2253 OTF_GlyphString otf_gstring;
2255 char script[5], *langsys = NULL;
2256 char *gsub_features = NULL, *gpos_features = NULL;
2260 otf = get_otf (font, &face);
2263 OTF_tag_name (spec->script, script);
2266 langsys = alloca (5);
2267 OTF_tag_name (spec->langsys, langsys);
2269 for (i = 0; i < 2; i++)
2273 if (spec->features[i])
2275 for (j = 0; spec->features[i][j]; j++);
2277 p = gsub_features = alloca (6 * j);
2279 p = gpos_features = alloca (6 * j);
2280 for (j = 0; spec->features[i][j]; j++)
2282 if (spec->features[i][j] == 0xFFFFFFFF)
2283 *p++ = '*', *p++ = ',';
2286 OTF_tag_name (spec->features[i][j], p);
2295 otf_gstring.size = otf_gstring.used = len;
2296 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
2297 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
2298 for (i = 0; i < len; i++)
2300 otf_gstring.glyphs[i].c = ((MGlyph *)in->glyphs)[from + i].g.c;
2301 otf_gstring.glyphs[i].glyph_id = ((MGlyph *)in->glyphs)[from + i].g.code;
2304 OTF_drive_gdef (otf, &otf_gstring);
2309 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
2312 if (out->allocated < out->used + otf_gstring.used)
2314 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
2316 MGlyph *g = out_glyphs + out->used;
2318 int min_from, max_to;
2320 *g = in_glyphs[from + otfg->f.index.from];
2321 min_from = g->g.from, max_to = g->g.to;
2323 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
2324 if (in_glyphs[from + j].g.code == otfg->glyph_id)
2326 g->g.c = in_glyphs[from + j].g.c;
2329 for (j = otfg->f.index.from + 1; j <= otfg->f.index.to; j++)
2331 if (min_from > in_glyphs[from + j].g.from)
2332 min_from = in_glyphs[from + j].g.from;
2333 if (max_to < in_glyphs[from + j].g.to)
2334 max_to = in_glyphs[from + j].g.to;
2336 if (g->g.code != otfg->glyph_id)
2338 g->g.code = otfg->glyph_id;
2341 g->g.from = min_from, g->g.to = max_to;
2347 if (out->allocated < out->used + len)
2349 for (i = 0; i < len; i++)
2350 out_glyphs[out->used++] = in_glyphs[from + i];
2355 MGlyph *base = NULL, *mark = NULL, *g;
2356 int x_ppem, y_ppem, x_scale, y_scale;
2358 #ifdef HAVE_OTF_DRIVE_GPOS2
2359 if (OTF_drive_gpos2 (otf, &otf_gstring, script, langsys, gpos_features)
2362 #else /* not HAVE_OTF_DRIVE_GPOS2 */
2363 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
2366 #endif /* not HAVE_OTF_DRIVE_GPOS2 */
2368 x_ppem = face->size->metrics.x_ppem;
2369 y_ppem = face->size->metrics.y_ppem;
2370 x_scale = face->size->metrics.x_scale;
2371 y_scale = face->size->metrics.y_scale;
2373 for (i = j = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx;
2374 i < otf_gstring.used; i++, otfg++)
2377 int adjust_idx = otfg->glyph_id ? j : j - 1;
2379 switch (otfg->positioning_type)
2383 case 1: /* Single */
2386 int format = otfg->f.f1.format;
2388 if (format & OTF_XPlacement)
2389 adjustment[adjust_idx].xoff
2390 += otfg->f.f1.value->XPlacement * x_scale / 0x10000;
2391 if (format & OTF_XPlaDevice)
2392 adjustment[adjust_idx].xoff
2393 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
2394 if (format & OTF_YPlacement)
2395 adjustment[adjust_idx].yoff
2396 -= otfg->f.f1.value->YPlacement * y_scale / 0x10000;
2397 if (format & OTF_YPlaDevice)
2398 adjustment[adjust_idx].yoff
2399 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
2400 if (format & OTF_XAdvance)
2401 adjustment[adjust_idx].xadv
2402 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
2403 if (format & OTF_XAdvDevice)
2404 adjustment[adjust_idx].xadv
2405 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
2406 if (format & OTF_YAdvance)
2407 adjustment[adjust_idx].yadv
2408 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
2409 if (format & OTF_YAdvDevice)
2410 adjustment[adjust_idx].yadv
2411 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
2412 adjustment[adjust_idx].set = 1;
2415 case 3: /* Cursive */
2416 /* Not yet supported. */
2418 case 4: /* Mark-to-Base */
2419 case 5: /* Mark-to-Ligature */
2423 goto label_adjust_anchor;
2424 default: /* i.e. case 6 Mark-to-Mark */
2429 label_adjust_anchor:
2431 int base_x, base_y, mark_x, mark_y;
2432 int this_from, this_to;
2435 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
2436 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
2437 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
2438 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;;
2440 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2441 adjust_anchor (otfg->f.f4.base_anchor, face, prev->g.code,
2442 x_ppem, y_ppem, &base_x, &base_y);
2443 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2444 adjust_anchor (otfg->f.f4.mark_anchor, face, g->g.code,
2445 x_ppem, y_ppem, &mark_x, &mark_y);
2446 adjustment[adjust_idx].xoff = base_x - mark_x;
2447 adjustment[adjust_idx].yoff = - (base_y - mark_y);
2448 adjustment[adjust_idx].back = (g - prev);
2449 adjustment[adjust_idx].xadv = 0;
2450 adjustment[adjust_idx].advance_is_absolute = 1;
2451 adjustment[adjust_idx].set = 1;
2452 this_from = g->g.from;
2454 for (k = 0; prev + k < g; k++)
2456 if (this_from > prev[k].g.from)
2457 this_from = prev[k].g.from;
2458 if (this_to < prev[k].g.to)
2459 this_to = prev[k].g.to;
2461 for (; prev <= g; prev++)
2463 prev->g.from = this_from;
2464 prev->g.to = this_to;
2470 if (otfg->GlyphClass == OTF_GlyphClass0)
2472 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2480 free (otf_gstring.glyphs);
2484 if (otf_gstring.glyphs)
2485 free (otf_gstring.glyphs);
2486 #endif /* HAVE_OTF */
2487 if (out->allocated < out->used + len)
2489 font->get_metrics (font, in, from, to);
2490 memcpy ((MGlyph *)out->glyphs + out->used, (MGlyph *) in->glyphs + from,
2491 sizeof (MGlyph) * len);
2497 static unsigned char *iterate_bitmap;
2500 iterate_callback (OTF *otf, const char *feature, unsigned glyph_id)
2502 if (glyph_id <= otf->cmap->max_glyph_id)
2503 iterate_bitmap[glyph_id / 8] |= 1 << (glyph_id % 8);
2508 ft_iterate_otf_feature (MFLTFont *font, MFLTOtfSpec *spec,
2509 int from, int to, unsigned char *table)
2511 OTF *otf = get_otf (font, NULL);
2514 unsigned char *bitmap = NULL;
2516 char script[5], *langsys = NULL;
2520 if (OTF_get_table (otf, "cmap") < 0)
2522 if (! spec->features[0])
2524 strcpy (id, "feature-");
2526 OTF_tag_name (spec->script, script);
2529 langsys = alloca (5);
2530 OTF_tag_name (spec->langsys, langsys);
2532 bmp_size = (otf->cmap->max_glyph_id / 8) + 1;
2533 for (i = 0; spec->features[0][i]; i++)
2537 OTF_tag_name (spec->features[0][i], id + 8);
2538 bmp = OTF_get_data (otf, id);
2541 iterate_bitmap = bmp = calloc (bmp_size, 1);
2542 OTF_iterate_gsub_feature (otf, iterate_callback,
2543 script, langsys, id + 8);
2544 OTF_put_data (otf, id, bmp, free);
2546 if (i == 0 && ! spec->features[0][1])
2547 /* Single feature */
2553 bitmap = alloca (bmp_size);
2554 memcpy (bitmap, bmp, bmp_size);
2560 for (j = 0; j < bmp_size; j++)
2561 bitmap[j] &= bmp[j];
2565 for (i = 0; i < bmp_size; i++)
2568 for (j = 0; j < 8; j++)
2569 if (bitmap[i] & (1 << j))
2571 int c = OTF_get_unicode (otf, (i * 8) + j);
2573 if (c >= from && c <= to)
2574 table[c - from] = 1;
2585 MFontDriver mfont__ft_driver =
2586 { ft_select, ft_open, ft_find_metric, ft_has_char, ft_encode_char,
2587 ft_render, ft_list, ft_list_family_names, ft_check_capability,
2588 ft_encapsulate, ft_close, ft_check_otf, ft_drive_otf,
2590 ft_iterate_otf_feature
2591 #endif /* HAVE_OTF */
2599 if (FT_Init_FreeType (&ft_library) != 0)
2600 MERROR (MERROR_FONT_FT, -1);
2602 for (i = 0; i < ft_to_prop_size; i++)
2603 ft_to_prop[i].len = strlen (ft_to_prop[i].ft_style);
2605 Mmedium = msymbol ("medium");
2607 Mnull = msymbol ("");
2609 M0[0] = msymbol ("0-0");
2610 M0[1] = msymbol ("0-1");
2611 M0[2] = msymbol ("0-2");
2612 M0[3] = msymbol ("0-3");
2613 M0[4] = msymbol ("0-4");
2614 M3_1 = msymbol ("3-1");
2615 M1_0 = msymbol ("1-0");
2617 #ifdef HAVE_FONTCONFIG
2618 for (i = 0; i < (sizeof (fc_all_table) / sizeof fc_all_table[0]); i++)
2620 FC_vs_M17N_font_prop *table = fc_all_table[i];
2623 for (j = 0; table[j].m17n_value; j++)
2624 table[j].sym = msymbol (table[j].m17n_value);
2625 table[j].sym = table[j - 1].sym;
2632 MSymbol serif, sans_serif, monospace;
2634 fc_config = FcInitLoadConfigAndFonts ();
2635 if (mfont_freetype_path)
2637 MPLIST_DO (plist, mfont_freetype_path)
2638 if (MPLIST_STRING_P (plist)
2639 && (pathname = MPLIST_STRING (plist))
2640 && stat (pathname, &buf) == 0)
2642 FcStrList *strlist = FcConfigGetFontDirs (fc_config);
2645 while ((dir = FcStrListNext (strlist)))
2646 if (strcmp ((char *) dir, pathname) == 0)
2649 FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname);
2650 FcStrListDone (strlist);
2653 Mgeneric_family = msymbol ("generic famly");
2654 serif = msymbol ("serif");
2655 msymbol_put (serif, Mgeneric_family, serif);
2656 sans_serif = msymbol ("sans-serif");
2657 msymbol_put (sans_serif, Mgeneric_family, sans_serif);
2658 msymbol_put (msymbol ("sans serif"), Mgeneric_family, sans_serif);
2659 msymbol_put (msymbol ("sans"), Mgeneric_family, sans_serif);
2660 monospace = msymbol ("monospace");
2661 msymbol_put (monospace, Mgeneric_family, monospace);
2662 msymbol_put (msymbol ("mono"), Mgeneric_family, monospace);
2664 #endif /* HAVE_FONTCONFIG */
2674 if (ft_default_list)
2676 M17N_OBJECT_UNREF (ft_default_list);
2677 ft_default_list = NULL;
2682 MPLIST_DO (plist, ft_font_list)
2684 if (MPLIST_VAL (plist))
2685 MPLIST_DO (p, MPLIST_VAL (plist))
2687 if (MPLIST_KEY (p) != Mt)
2688 free_ft_info (MPLIST_VAL (p));
2690 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2692 M17N_OBJECT_UNREF (ft_font_list);
2693 ft_font_list = NULL;
2695 if (ft_language_list)
2697 MPLIST_DO (plist, ft_language_list)
2698 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2699 M17N_OBJECT_UNREF (ft_language_list);
2700 ft_language_list = NULL;
2705 MPLIST_DO (plist, ft_script_list)
2706 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2707 M17N_OBJECT_UNREF (ft_script_list);
2708 ft_script_list = NULL;
2711 if (ft_capability_list)
2713 MPLIST_DO (plist, ft_capability_list)
2714 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2715 M17N_OBJECT_UNREF (ft_capability_list);
2716 ft_capability_list = NULL;
2721 MPLIST_DO (plist, ft_file_list)
2722 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
2723 M17N_OBJECT_UNREF (ft_file_list);
2724 ft_file_list = NULL;
2727 FT_Done_FreeType (ft_library);
2728 #ifdef HAVE_FONTCONFIG
2729 FcConfigDestroy (fc_config);
2731 #endif /* HAVE_FONTCONFIG */
2732 all_fonts_scaned = 0;
2735 #ifdef HAVE_FONTCONFIG
2738 mfont__ft_parse_name (const char *name, MFont *font)
2740 FcPattern *pat = FcNameParse ((FcChar8 *) name);
2749 if (FcPatternGetString (pat, FC_FOUNDRY, 0, &str) == FcResultMatch)
2751 STRDUP_LOWER (buf, bufsize, (char *) str);
2752 mfont__set_property (font, MFONT_FOUNDRY, msymbol (buf));
2754 if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
2756 STRDUP_LOWER (buf, bufsize, (char *) str);
2757 mfont__set_property (font, MFONT_FAMILY, msymbol (buf));
2759 if (FcPatternGetInteger (pat, FC_WEIGHT, 0, &val) == FcResultMatch)
2760 mfont__set_property (font, MFONT_WEIGHT,
2761 fc_decode_prop (val, fc_weight_table,
2762 fc_weight_table_size));
2763 if (FcPatternGetInteger (pat, FC_SLANT, 0, &val) == FcResultMatch)
2764 mfont__set_property (font, MFONT_STYLE,
2765 fc_decode_prop (val, fc_slant_table,
2766 fc_slant_table_size));
2767 if (FcPatternGetInteger (pat, FC_WIDTH, 0, &val) == FcResultMatch)
2768 mfont__set_property (font, MFONT_STRETCH,
2769 fc_decode_prop (val, fc_width_table,
2770 fc_width_table_size));
2771 if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
2772 font->size = size * 10 + 0.5;
2773 else if (FcPatternGetDouble (pat, FC_SIZE, 0, &size) == FcResultMatch)
2774 font->size = - (size * 10 + 0.5);
2775 if (FcPatternGetString (pat, FC_FILE, 0, &str) == FcResultMatch)
2777 font->file = msymbol ((char *) str);
2779 mfont__set_property (font, MFONT_REGISTRY, Municode_bmp);
2780 font->type = MFONT_TYPE_SPEC;
2781 FcPatternDestroy (pat);
2786 mfont__ft_unparse_name (MFont *font)
2788 FcPattern *pat = fc_get_pattern (font);
2789 char *name = (char *) FcNameUnparse (pat);
2791 FcPatternDestroy (pat);
2794 #endif /* HAVE_FONTCONFIG */
2796 #endif /* HAVE_FREETYPE */