From d47c9d6efec6c3c086efc187c68d79ca0c077dfa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 7 May 2003 16:13:24 +0000 Subject: [PATCH] Add filename-based accept/reject to ammend available fonts. change FT_ENCODING_ADOBE_CUSTOM to ft_encoding_adobe_custom for older FreeType releases. --- src/fccache.c | 18 ++++++----- src/fccfg.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/fcdir.c | 60 ++++++++++++++++++++++++++--------- src/fcfreetype.c | 2 +- src/fcint.h | 40 +++++++++++++++++++++-- src/fcxml.c | 46 ++++++++++++++++++++++++++- 6 files changed, 232 insertions(+), 30 deletions(-) diff --git a/src/fccache.c b/src/fccache.c index 6ca235d..beb9ae5 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -251,7 +251,8 @@ FcCacheFontSetAdd (FcFontSet *set, const FcChar8 *dir, int dir_len, const FcChar8 *file, - const FcChar8 *name) + const FcChar8 *name, + FcConfig *config) { FcChar8 path_buf[8192], *path; int len; @@ -276,7 +277,9 @@ FcCacheFontSetAdd (FcFontSet *set, path[dir_len++] = '/'; #endif strcpy ((char *) path + dir_len, (const char *) file); - if (!FcStrCmp (name, FC_FONT_FILE_DIR)) + if (config && !FcConfigAcceptFilename (config, path)) + ret = FcTrue; + else if (!FcStrCmp (name, FC_FONT_FILE_DIR)) { if (FcDebug () & FC_DBG_CACHEV) printf (" dir cache dir \"%s\"\n", path); @@ -539,7 +542,8 @@ FcBool FcGlobalCacheScanDir (FcFontSet *set, FcStrSet *dirs, FcGlobalCache *cache, - const FcChar8 *dir) + const FcChar8 *dir, + FcConfig *config) { FcGlobalCacheDir *d = FcGlobalCacheDirGet (cache, dir, strlen ((const char *) dir), @@ -582,7 +586,7 @@ FcGlobalCacheScanDir (FcFontSet *set, printf ("FcGlobalCacheScanDir add file %s\n", f->info.file); any_in_cache = FcTrue; if (!FcCacheFontSetAdd (set, dirs, dir, dir_len, - f->info.file, f->name)) + f->info.file, f->name, config)) { cache->broken = FcTrue; return FcFalse; @@ -598,7 +602,7 @@ FcGlobalCacheScanDir (FcFontSet *set, any_in_cache = FcTrue; if (!FcCacheFontSetAdd (set, dirs, dir, dir_len, - info.base, FC_FONT_FILE_DIR)) + info.base, FC_FONT_FILE_DIR, config)) { cache->broken = FcTrue; return FcFalse; @@ -971,7 +975,7 @@ FcDirCacheValid (const FcChar8 *dir) } FcBool -FcDirCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir) +FcDirCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *config) { FcChar8 *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE); FILE *f; @@ -1016,7 +1020,7 @@ FcDirCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir) (name = FcCacheReadString (f, name_buf, sizeof (name_buf)))) { if (!FcCacheFontSetAdd (set, dirs, cache_file, dir_len, - file, name)) + file, name, config)) goto bail3; if (file != file_buf) free (file); diff --git a/src/fccfg.c b/src/fccfg.c index 238edd3..3684d79 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -55,10 +55,18 @@ FcConfigCreate (void) if (!config->fontDirs) goto bail3; + config->acceptGlobs = FcStrSetCreate (); + if (!config->acceptGlobs) + goto bail4; + + config->rejectGlobs = FcStrSetCreate (); + if (!config->rejectGlobs) + goto bail5; + config->cache = 0; if (FcConfigHome()) if (!FcConfigSetCache (config, (FcChar8 *) ("~/" FC_USER_CACHE_FILE))) - goto bail4; + goto bail6; config->blanks = 0; @@ -73,6 +81,10 @@ FcConfigCreate (void) return config; +bail6: + FcStrSetDestroy (config->rejectGlobs); +bail5: + FcStrSetDestroy (config->acceptGlobs); bail4: FcStrSetDestroy (config->fontDirs); bail3: @@ -159,6 +171,8 @@ FcConfigDestroy (FcConfig *config) FcStrSetDestroy (config->configDirs); FcStrSetDestroy (config->fontDirs); FcStrSetDestroy (config->configFiles); + FcStrSetDestroy (config->acceptGlobs); + FcStrSetDestroy (config->rejectGlobs); FcStrFree (config->cache); @@ -203,7 +217,8 @@ FcConfigBuildFonts (FcConfig *config) { if (FcDebug () & FC_DBG_FONTSET) printf ("scan dir %s\n", dir); - FcDirScan (fonts, config->fontDirs, cache, config->blanks, dir, FcFalse); + FcDirScanConfig (fonts, config->fontDirs, cache, + config->blanks, dir, FcFalse, config); } FcStrListDone (list); @@ -1620,7 +1635,7 @@ FcConfigAppFontAddFile (FcConfig *config, FcConfigSetFonts (config, set, FcSetApplication); } - if (!FcFileScan (set, subdirs, 0, config->blanks, file, FcFalse)) + if (!FcFileScanConfig (set, subdirs, 0, config->blanks, file, FcFalse, config)) { FcStrSetDestroy (subdirs); return FcFalse; @@ -1667,7 +1682,7 @@ FcConfigAppFontAddDir (FcConfig *config, FcConfigSetFonts (config, set, FcSetApplication); } - if (!FcDirScan (set, subdirs, 0, config->blanks, dir, FcFalse)) + if (!FcDirScanConfig (set, subdirs, 0, config->blanks, dir, FcFalse, config)) { FcStrSetDestroy (subdirs); return FcFalse; @@ -1688,3 +1703,76 @@ FcConfigAppFontClear (FcConfig *config) { FcConfigSetFonts (config, 0, FcSetApplication); } + +/* + * Manage filename-based font source selectors + */ + +FcBool +FcConfigGlobAdd (FcConfig *config, + const FcChar8 *glob, + FcBool accept) +{ + FcStrSet *set = accept ? config->acceptGlobs : config->rejectGlobs; + + return FcStrSetAdd (set, glob); +} + +static FcBool +FcConfigGlobMatch (const FcChar8 *glob, + const FcChar8 *string) +{ + FcChar8 c; + + while ((c = *glob++)) + { + switch (c) { + case '*': + /* short circuit common case */ + if (!*glob) + return FcTrue; + /* short circuit another common case */ + if (strchr ((char *) glob, '*') == 0) + string += strlen ((char *) string) - strlen ((char *) glob); + while (*string) + { + if (FcConfigGlobMatch (glob, string)) + return FcTrue; + string++; + } + return FcFalse; + case '?': + if (*string++ == '\0') + return FcFalse; + break; + default: + if (*string++ != c) + return FcFalse; + break; + } + } + return *string == '\0'; +} + +static FcBool +FcConfigGlobsMatch (const FcStrSet *globs, + const FcChar8 *string) +{ + int i; + + for (i = 0; i < globs->num; i++) + if (FcConfigGlobMatch (globs->strs[i], string)) + return FcTrue; + return FcFalse; +} + +FcBool +FcConfigAcceptFilename (FcConfig *config, + const FcChar8 *filename) +{ + if (FcConfigGlobsMatch (config->acceptGlobs, filename)) + return FcTrue; + if (FcConfigGlobsMatch (config->rejectGlobs, filename)) + return FcFalse; + return FcTrue; +} diff --git a/src/fcdir.c b/src/fcdir.c index 995a908..6ae7052 100644 --- a/src/fcdir.c +++ b/src/fcdir.c @@ -36,12 +36,13 @@ FcFileIsDir (const FcChar8 *file) } FcBool -FcFileScan (FcFontSet *set, - FcStrSet *dirs, - FcGlobalCache *cache, - FcBlanks *blanks, - const FcChar8 *file, - FcBool force) +FcFileScanConfig (FcFontSet *set, + FcStrSet *dirs, + FcGlobalCache *cache, + FcBlanks *blanks, + const FcChar8 *file, + FcBool force, + FcConfig *config) { int id; FcChar8 *name; @@ -53,6 +54,9 @@ FcFileScan (FcFontSet *set, FcGlobalCacheDir *cache_dir; FcBool need_scan; + if (config && !FcConfigAcceptFilename (config, file)) + return FcTrue; + if (force) cache = 0; id = 0; @@ -151,6 +155,17 @@ FcFileScan (FcFontSet *set, return ret; } +FcBool +FcFileScan (FcFontSet *set, + FcStrSet *dirs, + FcGlobalCache *cache, + FcBlanks *blanks, + const FcChar8 *file, + FcBool force) +{ + return FcFileScanConfig (set, dirs, cache, blanks, file, force, 0); +} + #define FC_MAX_FILE_LEN 4096 /* @@ -159,12 +174,13 @@ FcFileScan (FcFontSet *set, */ FcBool -FcDirScan (FcFontSet *set, - FcStrSet *dirs, - FcGlobalCache *cache, - FcBlanks *blanks, - const FcChar8 *dir, - FcBool force) +FcDirScanConfig (FcFontSet *set, + FcStrSet *dirs, + FcGlobalCache *cache, + FcBlanks *blanks, + const FcChar8 *dir, + FcBool force, + FcConfig *config) { DIR *d; struct dirent *e; @@ -172,12 +188,15 @@ FcDirScan (FcFontSet *set, FcChar8 *base; FcBool ret = FcTrue; + if (config && !FcConfigAcceptFilename (config, dir)) + return FcTrue; + if (!force) { /* * Check fonts.cache- file */ - if (FcDirCacheReadDir (set, dirs, dir)) + if (FcDirCacheReadDir (set, dirs, dir, config)) { if (cache) FcGlobalCacheReferenceSubdir (cache, dir); @@ -187,7 +206,7 @@ FcDirScan (FcFontSet *set, /* * Check ~/.fonts.cache- file */ - if (cache && FcGlobalCacheScanDir (set, dirs, cache, dir)) + if (cache && FcGlobalCacheScanDir (set, dirs, cache, dir, config)) return FcTrue; } @@ -218,7 +237,7 @@ FcDirScan (FcFontSet *set, if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN) { strcpy ((char *) base, (char *) e->d_name); - ret = FcFileScan (set, dirs, cache, blanks, file, force); + ret = FcFileScanConfig (set, dirs, cache, blanks, file, force, config); } } free (file); @@ -234,6 +253,17 @@ FcDirScan (FcFontSet *set, } FcBool +FcDirScan (FcFontSet *set, + FcStrSet *dirs, + FcGlobalCache *cache, + FcBlanks *blanks, + const FcChar8 *dir, + FcBool force) +{ + return FcDirScanConfig (set, dirs, cache, blanks, dir, force, 0); +} + +FcBool FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir) { return FcDirCacheWriteDir (set, dirs, dir); diff --git a/src/fcfreetype.c b/src/fcfreetype.c index 95be9cc..31da0c6 100644 --- a/src/fcfreetype.c +++ b/src/fcfreetype.c @@ -1575,7 +1575,7 @@ FcFreeTypeUseNames (FT_Face face) if (!FT_Has_PS_Glyph_Names (face)) return FcFalse; for (map = 0; map < face->num_charmaps; map++) - if (face->charmaps[map]->encoding == FT_ENCODING_ADOBE_CUSTOM) + if (face->charmaps[map]->encoding == ft_encoding_adobe_custom) return FcTrue; return FcFalse; } diff --git a/src/fcint.h b/src/fcint.h index 4652e36..790f0ba 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -324,6 +324,11 @@ struct _FcConfig { FcSubst *substFont; /* substitutions for fonts */ int maxObjects; /* maximum number of tests in all substs */ /* + * List of patterns used to control font file selection + */ + FcStrSet *acceptGlobs; + FcStrSet *rejectGlobs; + /* * The set of fonts loaded from the listed directories; the * order within the set does not determine the font selection, * except in the case of identical matches in which case earlier fonts @@ -375,7 +380,8 @@ FcBool FcGlobalCacheScanDir (FcFontSet *set, FcStrSet *dirs, FcGlobalCache *cache, - const FcChar8 *dir); + const FcChar8 *dir, + FcConfig *config); FcGlobalCacheFile * FcGlobalCacheFileGet (FcGlobalCache *cache, @@ -399,7 +405,10 @@ FcGlobalCacheSave (FcGlobalCache *cache, const FcChar8 *cache_file); FcBool -FcDirCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir); +FcDirCacheReadDir (FcFontSet *set, + FcStrSet *dirs, + const FcChar8 *dir, + FcConfig *config); FcBool FcDirCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir); @@ -446,6 +455,15 @@ FcConfigCompareValue (const FcValue m, FcOp op, const FcValue v); +FcBool +FcConfigGlobAdd (FcConfig *config, + const FcChar8 *glob, + FcBool accept); + +FcBool +FcConfigAcceptFilename (FcConfig *config, + const FcChar8 *filename); + /* fccharset.c */ FcCharSet * FcCharSetFreeze (FcCharSet *cs); @@ -486,6 +504,24 @@ FcDebug (void); /* fcdir.c */ +FcBool +FcFileScanConfig (FcFontSet *set, + FcStrSet *dirs, + FcFileCache *cache, + FcBlanks *blanks, + const FcChar8 *file, + FcBool force, + FcConfig *config); + +FcBool +FcDirScanConfig (FcFontSet *set, + FcStrSet *dirs, + FcFileCache *cache, + FcBlanks *blanks, + const FcChar8 *dir, + FcBool force, + FcConfig *config); + /* fcfont.c */ int FcFontDebug (void); diff --git a/src/fcxml.c b/src/fcxml.c index 657959c..3cdbaa4 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -317,6 +317,11 @@ typedef enum _FcElement { FcElementDefault, FcElementFamily, + FcElementSelectfont, + FcElementAcceptfont, + FcElementRejectfont, + FcElementGlob, + FcElementTest, FcElementEdit, FcElementInt, @@ -373,6 +378,11 @@ FcElementMap (const XML_Char *name) { "default", FcElementDefault }, { "family", FcElementFamily }, + { "selectfont", FcElementSelectfont }, + { "acceptfont", FcElementAcceptfont }, + { "rejectfont", FcElementRejectfont }, + { "glob", FcElementGlob }, + { "test", FcElementTest }, { "edit", FcElementEdit }, { "int", FcElementInt }, @@ -428,6 +438,7 @@ typedef enum _FcVStackTag { FcVStackFamily, FcVStackField, FcVStackConstant, + FcVStackGlob, FcVStackPrefer, FcVStackAccept, @@ -544,6 +555,7 @@ FcVStackDestroy (FcVStack *vstack) case FcVStackFamily: case FcVStackField: case FcVStackConstant: + case FcVStackGlob: FcStrFree (vstack->u.string); break; case FcVStackInteger: @@ -1640,6 +1652,30 @@ FcParseMatch (FcConfigParse *parse) } static void +FcParseAcceptRejectFont (FcConfigParse *parse, FcElement element) +{ + FcVStack *vstack; + + while ((vstack = FcVStackPop (parse))) + { + switch (vstack->tag) { + case FcVStackGlob: + if (!FcConfigGlobAdd (parse->config, + vstack->u.string, + element == FcElementAcceptfont)) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + } + break; + default: + FcConfigMessage (parse, FcSevereWarning, "bad font selector"); + break; + } + FcVStackDestroy (vstack); + } +} + +static void FcEndElement(void *userData, const XML_Char *name) { FcConfigParse *parse = userData; @@ -1761,7 +1797,15 @@ FcEndElement(void *userData, const XML_Char *name) case FcElementCharset: /* FcParseCharset (parse); */ break; - + case FcElementSelectfont: + break; + case FcElementAcceptfont: + case FcElementRejectfont: + FcParseAcceptRejectFont (parse, parse->pstack->element); + break; + case FcElementGlob: + FcParseString (parse, FcVStackGlob); + break; case FcElementName: FcParseString (parse, FcVStackField); break; -- 2.7.4