From: handa Date: Thu, 30 Sep 2004 00:03:00 +0000 (+0000) Subject: Don't include here. X-Git-Tag: REL-1-2-0~165 X-Git-Url: http://git.chise.org/gitweb/?a=commitdiff_plain;h=94fd954d84893d2544311bfdab2ecd83580dbf24;p=m17n%2Fm17n-lib.git Don't include here. (Mserif, Msans_serif, Mmonospace, Mmedium, Mr, Mnull): New variables. (ft_family_list): New variable. (set_font_info): New arg basep. Callers changed. (fc_list): Check the return value of FcPatternGetString. (add_font_info): New arg plist. Callers changed. Update ft_family_list. (ft_list_family): New function (merged fc_list and ft_list_all). (ft_select): Use ft_list_family. (ft_list): Likewise. If FONT is not NULL, check all fonts. (mfont__ft_init): Initialize above new variables. (mfont__ft_fini): Free ft_family_list. --- diff --git a/src/font-ft.c b/src/font-ft.c index 901756d..898b2d9 100644 --- a/src/font-ft.c +++ b/src/font-ft.c @@ -45,13 +45,23 @@ #include #ifdef HAVE_FONTCONFIG -#include -int fontconfig_initialized = 0; -FcConfig *fc_config; +static FcConfig *fc_config; + +/** List of generic families supported by Fontconfig. Keys are + generic family names (including aliases) and values are real + generic family names. */ + +static MPlist *fc_generic_family_list; + #endif /* not HAVE_FONTCONFIG */ +/* Registries. */ static MSymbol Municode_bmp, Municode_full, Miso10646_1, Miso8859_1; +/* Fontconfig's generic font family names. */ +static MSymbol Mserif, Msans_serif, Mmonospace; +/* Font properties; Mnormal is already defined in face.c. */ +static MSymbol Mmedium, Mr, Mnull; static FT_Library ft_library; @@ -81,6 +91,10 @@ static int ft_to_prop_size = sizeof ft_to_prop / sizeof ft_to_prop[0]; plist, keys are Mt, values are (MFTInfo *). */ static MPlist *ft_font_list; +/** List of FreeType base fonts. Keys are family names, values are + (MFTInfo *). */ +static MPlist *ft_family_list; + static int all_fonts_scaned; /** Return 0 if NAME implies TrueType or OpenType fonts. Othersize @@ -101,10 +115,12 @@ check_otf_filename (const char *name) return 0; } -/** Setup members of FT_INFO from FT_FACE. Return the family name. */ +/** Setup members of FT_INFO from FT_FACE. If the font is a base one + (i.e. medium-r-normal), set BASEP to 1. Otherwise set BASEP to 0. + Return the family name. */ static MSymbol -set_font_info (FT_Face ft_face, MFTInfo *ft_info, MSymbol family) +set_font_info (FT_Face ft_face, MFTInfo *ft_info, MSymbol family, int *basep) { MFont *font = &ft_info->font; int len; @@ -126,10 +142,11 @@ set_font_info (FT_Face ft_face, MFTInfo *ft_info, MSymbol family) family = msymbol (buf); } mfont__set_property (font, MFONT_FAMILY, family); - mfont__set_property (font, MFONT_WEIGHT, msymbol ("medium")); - mfont__set_property (font, MFONT_STYLE, msymbol ("r")); - mfont__set_property (font, MFONT_STRETCH, msymbol ("normal")); - mfont__set_property (font, MFONT_ADSTYLE, msymbol ("")); + mfont__set_property (font, MFONT_WEIGHT, Mmedium); + mfont__set_property (font, MFONT_STYLE, Mr); + mfont__set_property (font, MFONT_STRETCH, Mnormal); + mfont__set_property (font, MFONT_ADSTYLE, Mnull); + *basep = 1; if (ft_face->style_name) { @@ -170,6 +187,10 @@ set_font_info (FT_Face ft_face, MFTInfo *ft_info, MSymbol family) } } + *basep = (FONT_PROPERTY (font, MFONT_WEIGHT) == Mmedium + && FONT_PROPERTY (font, MFONT_STYLE) == Mr + && FONT_PROPERTY (font, MFONT_STRETCH) == Mnormal); + charmap_list = mplist (); mplist_add (charmap_list, Mt, (void *) -1); for (i = 0; i < ft_face->num_charmaps; i++) @@ -267,7 +288,7 @@ close_ft (void *object) } static void -add_font_info (char *filename, MSymbol family, char *languages) +add_font_info (char *filename, MSymbol family, void *langset, MPlist *plist) { FT_Face ft_face; BDF_PropertyRec prop; @@ -279,151 +300,220 @@ add_font_info (char *filename, MSymbol family, char *languages) || FT_Get_BDF_Property (ft_face, "PIXEL_SIZE", &prop) == 0) { MSymbol fam; - MPlist *plist; + int basep; M17N_OBJECT (ft_info, close_ft, MERROR_FONT_FT); ft_info->filename = strdup (filename); - if (languages) - ft_info->languages = strdup (languages); ft_info->otf_flag = check_otf_filename (filename); - fam = set_font_info (ft_face, ft_info, family); - plist = mplist_get (ft_font_list, fam); - if (! plist) +#ifdef HAVE_FONTCONFIG + if (langset) + ft_info->langset = FcLangSetCopy (langset); +#endif + fam = set_font_info (ft_face, ft_info, family, &basep); + if (! plist + && ! (plist = mplist_get (ft_font_list, fam))) { plist = mplist (); - mplist_add (ft_font_list, fam, plist); + mplist_push (ft_font_list, fam, plist); } - mplist_add (plist, fam, ft_info); + mplist_push (plist, fam, ft_info); + + if (basep) + mplist_put (ft_family_list, fam, ft_info); + else if (! mplist_get (ft_family_list, fam)) + mplist_push (ft_family_list, fam, ft_info); } FT_Done_Face (ft_face); } } -#ifdef HAVE_FONTCONFIG - -static MPlist *fc_generic_family_list; - -static void -fc_list (MSymbol family) +/* Return an element of ft_font_list for FAMILY. If FAMILY is Mnil, + scan all fonts and return ft_font_list. */ +static MPlist * +ft_list_family (MSymbol family) { - FcPattern *pattern; - FcObjectSet *os; - FcFontSet *fs; - int i; + MPlist *plist; - if (! fc_config) + if (! ft_font_list) { - char *pathname; - struct stat buf; - MPlist *plist; - - FcInit (); - fc_config = FcConfigGetCurrent (); - MPLIST_DO (plist, mfont_freetype_path) - if (MPLIST_STRING_P (plist) - && (pathname = MPLIST_STRING (plist)) - && stat (pathname, &buf) == 0) - FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname); - /* TODO: avoid duplicate addition by checking the current font - directory list given by FcConfigGetFontDirs (). */ + ft_font_list = mplist (); + ft_family_list = mplist (); } - pattern = FcPatternCreate (); - if (family) - FcPatternAddString (pattern, FC_FAMILY, - (FcChar8 *) (msymbol_name (family))); - os = FcObjectSetBuild (FC_FILE, FC_FAMILY, FC_LANG, NULL); - fs = FcFontList (fc_config, pattern, os); - if (fs->nfont == 0 - && family != Mnil - && mplist_get (fc_generic_family_list, family) - && FcConfigSubstitute (fc_config, pattern, FcMatchPattern) == FcTrue) + if (family == Mnil) { - FcFontSetDestroy (fs); - fs = FcFontList (fc_config, pattern, os); + if (all_fonts_scaned) + return ft_font_list; } - for (i = 0; i < fs->nfont; i++) + else { - char *filename, *languages; - - if (FcPatternGetString (fs->fonts[i], FC_FILE, 0, (FcChar8 **) &filename) - != FcResultMatch) - continue; - if (FcPatternGetString (fs->fonts[i], FC_LANG, 0, (FcChar8 **) &languages) - != FcResultMatch) - languages = NULL; - if (family == Mnil) + plist = mplist_find_by_key (ft_font_list, family); + if (plist) + return plist; + if (all_fonts_scaned) { - MSymbol fam; - char *fname; - - FcPatternGetString (fs->fonts[i], FC_FAMILY, 0, (FcChar8 **) &fname); - fam = msymbol (fname); - if (! mplist_get (ft_font_list, fam)) - add_font_info (filename, fam, languages); + plist = mplist (); + mplist_push (ft_font_list, family, plist); + return ft_font_list; } - else - add_font_info (filename, family, languages); } - FcFontSetDestroy (fs); - FcObjectSetDestroy (os); - FcPatternDestroy (pattern); -} -#else /* not HAVE_FONTCONFIG */ +#ifdef HAVE_FONTCONFIG + { + FcPattern *pattern; + FcObjectSet *os; + FcFontSet *fs; + int i; -static void -ft_list_all () -{ - MPlist *plist; - struct stat buf; - char *pathname; + if (! fc_config) + { + char *pathname; + struct stat buf; + MPlist *plist; + + FcInit (); + fc_config = FcConfigGetCurrent (); + MPLIST_DO (plist, mfont_freetype_path) + if (MPLIST_STRING_P (plist) + && (pathname = MPLIST_STRING (plist)) + && stat (pathname, &buf) == 0) + FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname); + /* TODO: avoid duplicate addition by checking the current font + directory list given by FcConfigGetFontDirs (). */ + } + + pattern = FcPatternCreate (); + if (family) + { + MSymbol generic = mplist_get (fc_generic_family_list, family); + + if (generic != Mnil) + family = generic; + plist = mplist_find_by_key (ft_font_list, family); + if (plist) + return plist; + plist = mplist (); + mplist_push (ft_font_list, family, plist); + + FcPatternAddString (pattern, FC_FAMILY, + (FcChar8 *) (msymbol_name (family))); + if (generic != Mnil + && FcConfigSubstitute (fc_config, pattern, FcMatchPattern) + != FcTrue) + { + FcPatternDestroy (pattern); + return plist; + } + } - MPLIST_DO (plist, mfont_freetype_path) - if (MPLIST_STRING_P (plist) - && (pathname = MPLIST_STRING (plist)) - && stat (pathname, &buf) == 0) + os = FcObjectSetBuild (FC_FILE, FC_FAMILY, FC_LANG, NULL); + fs = FcFontList (fc_config, pattern, os); + + for (i = 0; i < fs->nfont; i++) { - if (S_ISREG (buf.st_mode)) - add_font_info (pathname, Mnil, NULL); - else if (S_ISDIR (buf.st_mode)) + FcChar8 *filename; + FcLangSet *langset; + + if (FcPatternGetString (fs->fonts[i], FC_FILE, 0, &filename) + != FcResultMatch) + continue; + if (FcPatternGetLangSet (fs->fonts[i], FC_LANG, 0, &langset) + != FcResultMatch) + langset = NULL; + if (family == Mnil) { - int len = strlen (pathname); - char path[PATH_MAX]; - DIR *dir = opendir (pathname); - struct dirent *dp; + MSymbol fam; + FcChar8 *fname; - if (dir) + FcPatternGetString (fs->fonts[i], FC_FAMILY, 0, &fname); + fam = msymbol ((char *) fname); + plist = mplist_get (ft_font_list, fam); + if (! plist) { - strcpy (path, pathname); - strcpy (path + len, "/"); - len++; - while ((dp = readdir (dir)) != NULL) - { - strcpy (path + len, dp->d_name); - add_font_info (path, Mnil, NULL); - } - closedir (dir); + plist = mplist (); + mplist_push (ft_font_list, fam, plist); + add_font_info ((char *) filename, fam, langset, plist); } } + else + add_font_info ((char *) filename, family, langset, plist); + } + FcFontSetDestroy (fs); + FcObjectSetDestroy (os); + FcPatternDestroy (pattern); + + if (family == Mnil) + { + MPLIST_DO (plist, fc_generic_family_list) + if (MPLIST_KEY (plist) == MPLIST_SYMBOL (plist) + && ! mplist_get (ft_font_list, MPLIST_KEY (plist))) + ft_list_family (MPLIST_KEY (plist)); + all_fonts_scaned = 1; } + } + +#else /* not HAVE_FONTCONFIG */ + + { + struct stat buf; + char *pathname; + + MPLIST_DO (plist, mfont_freetype_path) + if (MPLIST_STRING_P (plist) + && (pathname = MPLIST_STRING (plist)) + && stat (pathname, &buf) == 0) + { + if (S_ISREG (buf.st_mode)) + add_font_info (pathname, Mnil, NULL, NULL); + else if (S_ISDIR (buf.st_mode)) + { + int len = strlen (pathname); + char path[PATH_MAX]; + DIR *dir = opendir (pathname); + struct dirent *dp; + + if (dir) + { + strcpy (path, pathname); + strcpy (path + len, "/"); + len++; + while ((dp = readdir (dir)) != NULL) + { + strcpy (path + len, dp->d_name); + add_font_info (path, Mnil, NULL, NULL); + } + closedir (dir); + } + } + } + + if (family != Mnil) + { + plist = mplist_find_by_key (ft_font_list, family); + if (plist) + return plist; + plist = mplist (); + mplist_push (ft_font_list, family, plist); + } + } + +#endif /* not HAVE_FONTCONFIG */ + + return ft_font_list; } -#endif /* not HAVE_FONTCONFIG */ /* The FreeType font driver function SELECT. */ static MRealizedFont * ft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size) { - MPlist *plist, *pl; + MPlist *plist, *pl, *p; MFTInfo *best_font; int best_score; MRealizedFont *rfont; MSymbol family, registry; - best_font = NULL; - best_score = 0; family = FONT_PROPERTY (spec, MFONT_FAMILY); if (family == Mnil) family = FONT_PROPERTY (request, MFONT_FAMILY); @@ -431,74 +521,33 @@ ft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size) if (registry == Mnil) registry = Mt; - if (! ft_font_list) - ft_font_list = mplist (); -#ifdef HAVE_FONTCONFIG - if (family != Mnil) + plist = ft_list_family (family); + best_font = NULL; + best_score = -1; + MPLIST_DO (pl, plist) { - plist = mplist_get (ft_font_list, family); - if (! plist) + MPLIST_DO (p, MPLIST_VAL (pl)) { - fc_list (family); - plist = mplist_get (ft_font_list, family); - if (! plist) + MFTInfo *ft_info = MPLIST_VAL (p); + int score; + + if (! mplist_find_by_key (ft_info->charmap_list, registry)) + continue; + /* We always ignore FOUNDRY. */ + ft_info->font.property[MFONT_FOUNDRY] = spec->property[MFONT_FOUNDRY]; + score = mfont__score (&ft_info->font, spec, request, limited_size); + if (score >= 0 + && (! best_font + || best_score > score)) { - mplist_add (ft_font_list, family, plist = mplist ()); - return NULL; + best_font = ft_info; + best_score = score; + if (best_score == 0) + break; } } - } - else - { - if (! all_fonts_scaned) - { - fc_list (Mnil); - all_fonts_scaned = 1; - } - } -#else /* not HAVE_FONTCONFIG */ - if (! all_fonts_scaned) - { - ft_list_all (); - all_fonts_scaned = 1; - } - if (family != Mnil) - { - plist = mplist_get (ft_font_list, family); - if (! plist) - return NULL; - } -#endif /* not HAVE_FONTCONFIG */ - - if (family == Mnil) - plist = MPLIST_VAL (ft_font_list); - - retry: - MPLIST_DO (pl, plist) - { - MFTInfo *ft_info = MPLIST_VAL (pl); - int score; - - if (! mplist_find_by_key (ft_info->charmap_list, registry)) - continue; - /* We always ignore FOUNDRY. */ - ft_info->font.property[MFONT_FOUNDRY] = spec->property[MFONT_FOUNDRY]; - score = mfont__score (&ft_info->font, spec, request, limited_size); - if (score >= 0 - && (! best_font - || best_score > score)) - { - best_font = ft_info; - best_score = score; - if (score == 0) - break; - } - } - if (family == Mnil) - { - plist = MPLIST_NEXT (plist); - if (! MPLIST_TAIL_P (plist)) - goto retry; + if (best_score == 0 || family != Mnil) + break; } if (! best_font) return NULL; @@ -784,42 +833,46 @@ ft_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language) { MPlist *pl, *p; MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil; - char *lang = language != Mnil ? MSYMBOL_NAME (language) : NULL; +#ifdef HAVE_FONTCONFIG + FcChar8 *lang = (language != Mnil ? (FcChar8 *) MSYMBOL_NAME (language) + : NULL); +#endif - if (! all_fonts_scaned) + pl = ft_list_family (Mnil); + if (font) { + MPLIST_DO (pl, pl) + { + MPLIST_DO (p, MPLIST_PLIST (pl)) + { + MFTInfo *ft_info = MPLIST_VAL (p); + #ifdef HAVE_FONTCONFIG - fc_list (Mnil); -#else - ft_list_all (); + if (lang && ft_info->langset + && FcLangSetHasLang (ft_info->langset, lang) == FcLangEqual) + continue; #endif - all_fonts_scaned = 1; + if (! mfont__match_p (&ft_info->font, font, MFONT_REGISTRY)) + continue; + mplist_push (plist, MPLIST_KEY (pl), &ft_info->font); + } + if (family != Mnil) + break; + } } - - if (family == Mnil) - pl = ft_font_list; else { - pl = mplist_find_by_key (ft_font_list, family); - if (! pl) - return; - } - - MPLIST_DO (pl, pl) - { - MPLIST_DO (p, MPLIST_VAL (pl)) + MPLIST_DO (p, ft_family_list) { MFTInfo *ft_info = MPLIST_VAL (p); - if (lang && ft_info->languages && strstr (ft_info->languages, lang)) - continue; - if (font && ! mfont__match_p (&ft_info->font, font, MFONT_REGISTRY)) +#ifdef HAVE_FONTCONFIG + if (lang && ft_info->langset + && FcLangSetHasLang (ft_info->langset, lang) == FcLangEqual) continue; - mplist_push (plist, FONT_PROPERTY (&ft_info->font, MFONT_FAMILY), - &ft_info->font); +#endif + mplist_push (plist, MPLIST_KEY (p), &ft_info->font); } - if (family != Mnil) - break; } } @@ -845,14 +898,23 @@ mfont__ft_init () Miso10646_1 = msymbol ("iso10646-1"); Miso8859_1 = msymbol ("iso8859-1"); + Mserif = msymbol ("serif"); + Msans_serif = msymbol ("sans-serif"); + Mmonospace = msymbol ("monospace"); + + Mmedium = msymbol ("medium"); + Mr = msymbol ("r"); + Mnull = msymbol (""); + #ifdef HAVE_FONTCONFIG fc_generic_family_list = mplist (); - mplist_push (fc_generic_family_list, msymbol ("serif"), Mt); - mplist_push (fc_generic_family_list, msymbol ("sans-serif"), Mt); - mplist_push (fc_generic_family_list, msymbol ("monospace"), Mt); - mplist_push (fc_generic_family_list, msymbol ("sans"), Mt); - mplist_push (fc_generic_family_list, msymbol ("sans serif"), Mt); - mplist_push (fc_generic_family_list, msymbol ("mono"), Mt); + mplist_push (fc_generic_family_list, Mserif, Mserif); + mplist_push (fc_generic_family_list, Msans_serif, Msans_serif); + mplist_push (fc_generic_family_list, Mmonospace, Mmonospace); + /* These are (deprecated) aliases. */ + mplist_push (fc_generic_family_list, msymbol ("sans"), Msans_serif); + mplist_push (fc_generic_family_list, msymbol ("sans serif"), Msans_serif); + mplist_push (fc_generic_family_list, msymbol ("mono"), Mmonospace); #endif return 0; @@ -877,6 +939,9 @@ mfont__ft_fini () } M17N_OBJECT_UNREF (ft_font_list); ft_font_list = NULL; + + M17N_OBJECT_UNREF (ft_family_list); + ft_family_list = NULL; } FT_Done_FreeType (ft_library); all_fonts_scaned = 0;