X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffccfg.c;h=d9502f0d341f691deaa5b3c1825f6924bb1908f5;hb=17389539a046f7231447d531ef7f3d131c1d7515;hp=91373d39da3fc584df96b34d0bcf3d3172c3edba;hpb=c5350655bef34cc08739bed324a482473b2a01b8;p=fontconfig.git diff --git a/src/fccfg.c b/src/fccfg.c index 91373d3..d9502f0 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -1,7 +1,7 @@ /* - * $XFree86: xc/lib/fontconfig/src/fccfg.c,v 1.3 2002/02/19 08:33:23 keithp Exp $ + * $RCSId: xc/lib/fontconfig/src/fccfg.c,v 1.23 2002/08/31 22:17:32 keithp Exp $ * - * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * Copyright © 2000 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -22,10 +22,19 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include #include "fcint.h" +#include +#include + +#if defined (_WIN32) && (defined (PIC) || defined (DLL_EXPORT)) +#define STRICT +#include +#undef STRICT +#endif + +#if defined (_WIN32) && !defined (R_OK) +#define R_OK 4 +#endif FcConfig *_fcConfig; @@ -38,144 +47,291 @@ FcConfigCreate (void) config = malloc (sizeof (FcConfig)); if (!config) goto bail0; + FcMemAlloc (FC_MEM_CONFIG, sizeof (FcConfig)); - config->dirs = malloc (sizeof (char *)); - if (!config->dirs) + config->configDirs = FcStrSetCreate (); + if (!config->configDirs) goto bail1; - config->dirs[0] = 0; - config->configFiles = malloc (sizeof (char *)); + config->configFiles = FcStrSetCreate (); if (!config->configFiles) goto bail2; - config->configFiles[0] = 0; - config->cache = 0; - if (!FcConfigSetCache (config, (FcChar8 *) ("~/" FC_USER_CACHE_FILE))) + config->fontDirs = FcStrSetCreate (); + if (!config->fontDirs) goto bail3; + + config->acceptGlobs = FcStrSetCreate (); + if (!config->acceptGlobs) + goto bail4; + + config->rejectGlobs = FcStrSetCreate (); + if (!config->rejectGlobs) + goto bail5; + + config->acceptPatterns = FcFontSetCreate (); + if (!config->acceptPatterns) + goto bail6; + + config->rejectPatterns = FcFontSetCreate (); + if (!config->rejectPatterns) + goto bail7; + config->cacheDirs = FcStrSetCreate (); + if (!config->cacheDirs) + goto bail8; + config->blanks = 0; config->substPattern = 0; config->substFont = 0; + config->substScan = 0; config->maxObjects = 0; for (set = FcSetSystem; set <= FcSetApplication; set++) config->fonts[set] = 0; + + config->rescanTime = time(0); + config->rescanInterval = 30; return config; +bail8: + FcFontSetDestroy (config->rejectPatterns); +bail7: + FcFontSetDestroy (config->acceptPatterns); +bail6: + FcStrSetDestroy (config->rejectGlobs); +bail5: + FcStrSetDestroy (config->acceptGlobs); +bail4: + FcStrSetDestroy (config->fontDirs); bail3: - free (config->configFiles); + FcStrSetDestroy (config->configFiles); bail2: - free (config->dirs); + FcStrSetDestroy (config->configDirs); bail1: free (config); + FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig)); bail0: return 0; } -static void -FcSubstDestroy (FcSubst *s) +static FcFileTime +FcConfigNewestFile (FcStrSet *files) { - FcSubst *n; - - while (s) + FcStrList *list = FcStrListCreate (files); + FcFileTime newest = { 0, FcFalse }; + FcChar8 *file; + struct stat statb; + + if (list) { - n = s->next; - FcTestDestroy (s->test); - FcEditDestroy (s->edit); - s = n; + while ((file = FcStrListNext (list))) + if (stat ((char *) file, &statb) == 0) + if (!newest.set || statb.st_mtime - newest.time > 0) + { + newest.set = FcTrue; + newest.time = statb.st_mtime; + } + FcStrListDone (list); } + return newest; } -static void -FcConfigDestroyStrings (FcChar8 **strings) +FcFileTime +FcConfigModifiedTime (FcConfig *config) { - FcChar8 **s; - - for (s = strings; s && *s; s++) - free (*s); - if (strings) - free (strings); + if (!config) + { + FcFileTime v = { 0, FcFalse }; + config = FcConfigGetCurrent (); + if (!config) + return v; + } + return FcConfigNewestFile (config->configFiles); } - -static FcBool -FcConfigAddString (FcChar8 ***strings, FcChar8 *string) + +FcBool +FcConfigUptoDate (FcConfig *config) { - int n; - FcChar8 **s; - - n = 0; - for (s = *strings; s && *s; s++) - n++; - s = malloc ((n + 2) * sizeof (FcChar8 *)); - if (!s) + FcFileTime config_time, font_time; + time_t now = time(0); + if (!config) + { + config = FcConfigGetCurrent (); + if (!config) + return FcFalse; + } + config_time = FcConfigNewestFile (config->configFiles); + font_time = FcConfigNewestFile (config->fontDirs); + if ((config_time.set && config_time.time - config->rescanTime > 0) || + (font_time.set && (font_time.time - config->rescanTime) > 0)) + { return FcFalse; - s[n] = string; - s[n+1] = 0; - memcpy (s, *strings, n * sizeof (FcChar8 *)); - free (*strings); - *strings = s; + } + config->rescanTime = now; return FcTrue; } +static void +FcSubstDestroy (FcSubst *s) +{ + FcSubst *n; + + while (s) + { + n = s->next; + if (s->test) + FcTestDestroy (s->test); + if (s->edit) + FcEditDestroy (s->edit); + free (s); + FcMemFree (FC_MEM_SUBST, sizeof (FcSubst)); + s = n; + } +} + void FcConfigDestroy (FcConfig *config) { FcSetName set; - FcConfigDestroyStrings (config->dirs); - FcConfigDestroyStrings (config->configFiles); - free (config->cache); + if (config == _fcConfig) + _fcConfig = 0; + + FcStrSetDestroy (config->configDirs); + FcStrSetDestroy (config->fontDirs); + FcStrSetDestroy (config->cacheDirs); + FcStrSetDestroy (config->configFiles); + FcStrSetDestroy (config->acceptGlobs); + FcStrSetDestroy (config->rejectGlobs); + FcFontSetDestroy (config->acceptPatterns); + FcFontSetDestroy (config->rejectPatterns); + + if (config->blanks) + FcBlanksDestroy (config->blanks); FcSubstDestroy (config->substPattern); FcSubstDestroy (config->substFont); + FcSubstDestroy (config->substScan); for (set = FcSetSystem; set <= FcSetApplication; set++) if (config->fonts[set]) FcFontSetDestroy (config->fonts[set]); + + free (config); + FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig)); +} + +/* + * Add cache to configuration, adding fonts and directories + */ + +FcBool +FcConfigAddCache (FcConfig *config, FcCache *cache) +{ + FcFontSet *fs; + intptr_t *dirs; + int i; + + /* + * Add fonts + */ + fs = FcCacheSet (cache); + if (fs) + { + int nref = 0; + + for (i = 0; i < fs->nfont; i++) + { + FcPattern *font = FcFontSetFont (fs, i); + FcChar8 *font_file; + + /* + * Check to see if font is banned by filename + */ + if (FcPatternObjectGetString (font, FC_FILE_OBJECT, + 0, &font_file) == FcResultMatch && + !FcConfigAcceptFilename (config, font_file)) + { + continue; + } + + /* + * Check to see if font is banned by pattern + */ + if (!FcConfigAcceptFont (config, font)) + continue; + + nref++; + FcFontSetAdd (config->fonts[FcSetSystem], font); + } + FcDirCacheReference (cache, nref); + } + + /* + * Add directories + */ + dirs = FcCacheDirs (cache); + if (dirs) + { + for (i = 0; i < cache->dirs_count; i++) + { + FcChar8 *dir = FcOffsetToPtr (dirs, dirs[i], FcChar8); + if (FcConfigAcceptFilename (config, dir)) + FcConfigAddFontDir (config, dir); + } + } + return FcTrue; } /* * Scan the current list of directories in the configuration - * and build the set of available fonts. Update the - * per-user cache file to reflect the new configuration + * and build the set of available fonts. */ FcBool FcConfigBuildFonts (FcConfig *config) { - FcFontSet *fonts; - FcFileCache *cache; - FcChar8 **d; + FcFontSet *fonts; + FcStrList *dirlist; + FcChar8 *dir; + FcCache *cache; + if (!config) + { + config = FcConfigGetCurrent (); + if (!config) + return FcFalse; + } + fonts = FcFontSetCreate (); if (!fonts) - goto bail0; + goto bail; - cache = FcFileCacheCreate (); - if (!cache) - goto bail1; - - FcFileCacheLoad (cache, config->cache); - - for (d = config->dirs; d && *d; d++) + FcConfigSetFonts (config, fonts, FcSetSystem); + + dirlist = FcStrListCreate (config->fontDirs); + if (!dirlist) + goto bail; + + while ((dir = FcStrListNext (dirlist))) { if (FcDebug () & FC_DBG_FONTSET) - printf ("scan dir %s\n", *d); - FcDirScan (fonts, cache, config->blanks, *d, FcFalse); + printf ("adding fonts from%s\n", dir); + cache = FcDirCacheRead (dir, FcFalse, config); + if (!cache) + continue; + FcConfigAddCache (config, cache); + FcDirCacheUnload (cache); } + FcStrListDone (dirlist); + if (FcDebug () & FC_DBG_FONTSET) FcFontSetPrint (fonts); - FcFileCacheSave (cache, config->cache); - FcFileCacheDestroy (cache); - - FcConfigSetFonts (config, fonts, FcSetSystem); - return FcTrue; -bail1: - FcFontSetDestroy (fonts); -bail0: +bail: return FcFalse; } @@ -202,40 +358,14 @@ FcConfigGetCurrent (void) } FcBool -FcConfigAddDir (FcConfig *config, - const FcChar8 *d) +FcConfigAddConfigDir (FcConfig *config, + const FcChar8 *d) { - FcChar8 *dir; - FcChar8 *h; - - if (*d == '~') - { - h = (FcChar8 *) getenv ("HOME"); - if (!h) - return FcFalse; - dir = (FcChar8 *) malloc (strlen ((char *) h) + strlen ((char *) d)); - if (!dir) - return FcFalse; - strcpy ((char *) dir, (char *) h); - strcat ((char *) dir, (char *) d+1); - } - else - { - dir = (FcChar8 *) malloc (strlen ((char *) d) + 1); - if (!dir) - return FcFalse; - strcpy (dir, d); - } - if (!FcConfigAddString (&config->dirs, dir)) - { - free (dir); - return FcFalse; - } - return FcTrue; + return FcStrSetAddFilename (config->configDirs, d); } -FcChar8 ** -FcConfigGetDirs (FcConfig *config) +FcStrList * +FcConfigGetConfigDirs (FcConfig *config) { if (!config) { @@ -243,27 +373,26 @@ FcConfigGetDirs (FcConfig *config) if (!config) return 0; } - return config->dirs; + return FcStrListCreate (config->configDirs); } FcBool -FcConfigAddConfigFile (FcConfig *config, - const FcChar8 *f) +FcConfigAddFontDir (FcConfig *config, + const FcChar8 *d) { - FcChar8 *file; - file = FcConfigFilename (f); - if (!file) - return FcFalse; - if (!FcConfigAddString (&config->configFiles, file)) - { - free (file); - return FcFalse; - } - return FcTrue; + return FcStrSetAddFilename (config->fontDirs, d); } -FcChar8 ** -FcConfigGetConfigFiles (FcConfig *config) +FcBool +FcConfigAddDir (FcConfig *config, + const FcChar8 *d) +{ + return (FcConfigAddConfigDir (config, d) && + FcConfigAddFontDir (config, d)); +} + +FcStrList * +FcConfigGetFontDirs (FcConfig *config) { if (!config) { @@ -271,39 +400,45 @@ FcConfigGetConfigFiles (FcConfig *config) if (!config) return 0; } - return config->configFiles; + return FcStrListCreate (config->fontDirs); } FcBool -FcConfigSetCache (FcConfig *config, - const FcChar8 *c) +FcConfigAddCacheDir (FcConfig *config, + const FcChar8 *d) { - FcChar8 *new; - FcChar8 *h; + return FcStrSetAddFilename (config->cacheDirs, d); +} - if (*c == '~') - { - h = (FcChar8 *) getenv ("HOME"); - if (!h) - return FcFalse; - new = (FcChar8 *) malloc (strlen ((char *) h) + strlen ((char *) c)); - if (!new) - return FcFalse; - strcpy ((char *) new, (char *) h); - strcat ((char *) new, (char *) c+1); - } - else +FcStrList * +FcConfigGetCacheDirs (FcConfig *config) +{ + if (!config) { - new = FcStrCopy (c); + config = FcConfigGetCurrent (); + if (!config) + return 0; } - if (config->cache) - free (config->cache); - config->cache = new; - return FcTrue; + return FcStrListCreate (config->cacheDirs); +} + +FcBool +FcConfigAddConfigFile (FcConfig *config, + const FcChar8 *f) +{ + FcBool ret; + FcChar8 *file = FcConfigFilename (f); + + if (!file) + return FcFalse; + + ret = FcStrSetAdd (config->configFiles, file); + FcStrFree (file); + return ret; } -FcChar8 * -FcConfigGetCache (FcConfig *config) +FcStrList * +FcConfigGetConfigFiles (FcConfig *config) { if (!config) { @@ -311,7 +446,13 @@ FcConfigGetCache (FcConfig *config) if (!config) return 0; } - return config->cache; + return FcStrListCreate (config->configFiles); +} + +FcChar8 * +FcConfigGetCache (FcConfig *config) +{ + return NULL; } FcFontSet * @@ -353,21 +494,50 @@ FcBool FcConfigAddBlank (FcConfig *config, FcChar32 blank) { - FcBlanks *b; + FcBlanks *b, *freeme = 0; b = config->blanks; if (!b) { - b = FcBlanksCreate (); + freeme = b = FcBlanksCreate (); if (!b) return FcFalse; } if (!FcBlanksAdd (b, blank)) + { + if (freeme) + FcBlanksDestroy (freeme); return FcFalse; + } config->blanks = b; return FcTrue; } +int +FcConfigGetRescanInverval (FcConfig *config) +{ + if (!config) + { + config = FcConfigGetCurrent (); + if (!config) + return 0; + } + return config->rescanInterval; +} + +FcBool +FcConfigSetRescanInverval (FcConfig *config, int rescanInterval) +{ + if (!config) + { + config = FcConfigGetCurrent (); + if (!config) + return FcFalse; + } + config->rescanInterval = rescanInterval; + return FcTrue; +} + FcBool FcConfigAddEdit (FcConfig *config, FcTest *test, @@ -378,28 +548,42 @@ FcConfigAddEdit (FcConfig *config, FcTest *t; int num; + switch (kind) { + case FcMatchPattern: + prev = &config->substPattern; + break; + case FcMatchFont: + prev = &config->substFont; + break; + case FcMatchScan: + prev = &config->substScan; + break; + default: + return FcFalse; + } subst = (FcSubst *) malloc (sizeof (FcSubst)); if (!subst) return FcFalse; - if (kind == FcMatchPattern) - prev = &config->substPattern; - else - prev = &config->substFont; + FcMemAlloc (FC_MEM_SUBST, sizeof (FcSubst)); for (; *prev; prev = &(*prev)->next); *prev = subst; subst->next = 0; subst->test = test; subst->edit = edit; - if (FcDebug () & FC_DBG_EDIT) - { - printf ("Add Subst "); - FcSubstPrint (subst); - } num = 0; for (t = test; t; t = t->next) + { + if (t->kind == FcMatchDefault) + t->kind = kind; num++; + } if (config->maxObjects < num) config->maxObjects = num; + if (FcDebug () & FC_DBG_EDIT) + { + printf ("Add Subst "); + FcSubstPrint (subst); + } return FcTrue; } @@ -408,8 +592,6 @@ typedef struct _FcSubState { FcValueList *value; } FcSubState; -static const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 }; - static FcValue FcConfigPromote (FcValue v, FcValue u) { @@ -420,47 +602,55 @@ FcConfigPromote (FcValue v, FcValue u) } else if (v.type == FcTypeVoid && u.type == FcTypeMatrix) { - v.u.m = (FcMatrix *) &FcIdentityMatrix; + v.u.m = &FcIdentityMatrix; v.type = FcTypeMatrix; } + else if (v.type == FcTypeString && u.type == FcTypeLangSet) + { + v.u.l = FcLangSetPromote (v.u.s); + v.type = FcTypeLangSet; + } return v; } FcBool -FcConfigCompareValue (FcValue m, - FcOp op, - FcValue v) +FcConfigCompareValue (const FcValue *left_o, + FcOp op, + const FcValue *right_o) { - FcBool ret = FcFalse; + FcValue left = FcValueCanonicalize(left_o); + FcValue right = FcValueCanonicalize(right_o); + FcBool ret = FcFalse; - m = FcConfigPromote (m, v); - v = FcConfigPromote (v, m); - if (m.type == v.type) + left = FcConfigPromote (left, right); + right = FcConfigPromote (right, left); + if (left.type == right.type) { - ret = FcFalse; - switch (m.type) { + switch (left.type) { case FcTypeInteger: break; /* FcConfigPromote prevents this from happening */ case FcTypeDouble: switch (op) { case FcOpEqual: case FcOpContains: - ret = m.u.d == v.u.d; + case FcOpListing: + ret = left.u.d == right.u.d; break; - case FcOpNotEqual: - ret = m.u.d != v.u.d; + case FcOpNotEqual: + case FcOpNotContains: + ret = left.u.d != right.u.d; break; case FcOpLess: - ret = m.u.d < v.u.d; + ret = left.u.d < right.u.d; break; case FcOpLessEqual: - ret = m.u.d <= v.u.d; + ret = left.u.d <= right.u.d; break; case FcOpMore: - ret = m.u.d > v.u.d; + ret = left.u.d > right.u.d; break; case FcOpMoreEqual: - ret = m.u.d >= v.u.d; + ret = left.u.d >= right.u.d; break; default: break; @@ -470,10 +660,12 @@ FcConfigCompareValue (FcValue m, switch (op) { case FcOpEqual: case FcOpContains: - ret = m.u.b == v.u.b; + case FcOpListing: + ret = left.u.b == right.u.b; break; - case FcOpNotEqual: - ret = m.u.b != v.u.b; + case FcOpNotEqual: + case FcOpNotContains: + ret = left.u.b != right.u.b; break; default: break; @@ -482,11 +674,17 @@ FcConfigCompareValue (FcValue m, case FcTypeString: switch (op) { case FcOpEqual: + case FcOpListing: + ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0; + break; case FcOpContains: - ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) == 0; + ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0; + break; + case FcOpNotEqual: + ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0; break; - case FcOpNotEqual: - ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) != 0; + case FcOpNotContains: + ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0; break; default: break; @@ -496,10 +694,12 @@ FcConfigCompareValue (FcValue m, switch (op) { case FcOpEqual: case FcOpContains: - ret = FcMatrixEqual (m.u.m, v.u.m); + case FcOpListing: + ret = FcMatrixEqual (left.u.m, right.u.m); break; case FcOpNotEqual: - ret = !FcMatrixEqual (m.u.m, v.u.m); + case FcOpNotContains: + ret = !FcMatrixEqual (left.u.m, right.u.m); break; default: break; @@ -508,14 +708,38 @@ FcConfigCompareValue (FcValue m, case FcTypeCharSet: switch (op) { case FcOpContains: - /* m contains v if v - m is empty */ - ret = FcCharSetSubtractCount (v.u.c, m.u.c) == 0; + case FcOpListing: + /* left contains right if right is a subset of left */ + ret = FcCharSetIsSubset (right.u.c, left.u.c); + break; + case FcOpNotContains: + /* left contains right if right is a subset of left */ + ret = !FcCharSetIsSubset (right.u.c, left.u.c); + break; + case FcOpEqual: + ret = FcCharSetEqual (left.u.c, right.u.c); + break; + case FcOpNotEqual: + ret = !FcCharSetEqual (left.u.c, right.u.c); + break; + default: + break; + } + break; + case FcTypeLangSet: + switch (op) { + case FcOpContains: + case FcOpListing: + ret = FcLangSetContains (left.u.l, right.u.l); + break; + case FcOpNotContains: + ret = !FcLangSetContains (left.u.l, right.u.l); break; case FcOpEqual: - ret = FcCharSetEqual (m.u.c, v.u.c); + ret = FcLangSetEqual (left.u.l, right.u.l); break; case FcOpNotEqual: - ret = !FcCharSetEqual (m.u.c, v.u.c); + ret = !FcLangSetEqual (left.u.l, right.u.l); break; default: break; @@ -525,29 +749,53 @@ FcConfigCompareValue (FcValue m, switch (op) { case FcOpEqual: case FcOpContains: + case FcOpListing: ret = FcTrue; break; default: break; } break; + case FcTypeFTFace: + switch (op) { + case FcOpEqual: + case FcOpContains: + case FcOpListing: + ret = left.u.f == right.u.f; + break; + case FcOpNotEqual: + case FcOpNotContains: + ret = left.u.f != right.u.f; + break; + default: + break; + } + break; } } else { - if (op == FcOpNotEqual) + if (op == FcOpNotEqual || op == FcOpNotContains) ret = FcTrue; } return ret; } +#define _FcDoubleFloor(d) ((int) (d)) +#define _FcDoubleCeil(d) ((double) (int) (d) == (d) ? (int) (d) : (int) ((d) + 1)) +#define FcDoubleFloor(d) ((d) >= 0 ? _FcDoubleFloor(d) : -_FcDoubleCeil(-(d))) +#define FcDoubleCeil(d) ((d) >= 0 ? _FcDoubleCeil(d) : -_FcDoubleFloor(-(d))) +#define FcDoubleRound(d) FcDoubleFloor ((d) + 0.5) +#define FcDoubleTrunc(d) ((d) >= 0 ? _FcDoubleFloor (d) : -_FcDoubleFloor (-(d))) + static FcValue FcConfigEvaluate (FcPattern *p, FcExpr *e) { FcValue v, vl, vr; FcResult r; FcMatrix *m; + FcChar8 *str; switch (e->op) { case FcOpInteger: @@ -560,8 +808,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) break; case FcOpString: v.type = FcTypeString; - v.u.s = e->u.sval; - v = FcValueSave (v); + v.u.s = FcStrStaticName(e->u.sval); break; case FcOpMatrix: v.type = FcTypeMatrix; @@ -578,9 +825,10 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) v.u.b = e->u.bval; break; case FcOpField: - r = FcPatternGet (p, e->u.field, 0, &v); + r = FcPatternObjectGet (p, e->u.object, 0, &v); if (r != FcResultMatch) v.type = FcTypeVoid; + v = FcValueSave (v); break; case FcOpConst: if (FcNameConstant (e->u.constant, &v.u.i)) @@ -601,15 +849,24 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) v.type = FcTypeVoid; FcValueDestroy (vl); break; - case FcOpOr: - case FcOpAnd: case FcOpEqual: - case FcOpContains: case FcOpNotEqual: case FcOpLess: case FcOpLessEqual: case FcOpMore: case FcOpMoreEqual: + case FcOpContains: + case FcOpNotContains: + case FcOpListing: + vl = FcConfigEvaluate (p, e->u.tree.left); + vr = FcConfigEvaluate (p, e->u.tree.right); + v.type = FcTypeBool; + v.u.b = FcConfigCompareValue (&vl, e->op, &vr); + FcValueDestroy (vl); + FcValueDestroy (vr); + break; + case FcOpOr: + case FcOpAnd: case FcOpPlus: case FcOpMinus: case FcOpTimes: @@ -639,31 +896,6 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) v.type = FcTypeDouble; v.u.d = vl.u.d / vr.u.d; break; - case FcOpEqual: - case FcOpContains: - v.type = FcTypeBool; - v.u.b = vl.u.d == vr.u.d; - break; - case FcOpNotEqual: - v.type = FcTypeBool; - v.u.b = vl.u.d != vr.u.d; - break; - case FcOpLess: - v.type = FcTypeBool; - v.u.b = vl.u.d < vr.u.d; - break; - case FcOpLessEqual: - v.type = FcTypeBool; - v.u.b = vl.u.d <= vr.u.d; - break; - case FcOpMore: - v.type = FcTypeBool; - v.u.b = vl.u.d > vr.u.d; - break; - case FcOpMoreEqual: - v.type = FcTypeBool; - v.u.b = vl.u.d >= vr.u.d; - break; default: v.type = FcTypeVoid; break; @@ -685,15 +917,6 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) v.type = FcTypeBool; v.u.b = vl.u.b && vr.u.b; break; - case FcOpEqual: - case FcOpContains: - v.type = FcTypeBool; - v.u.b = vl.u.b == vr.u.b; - break; - case FcOpNotEqual: - v.type = FcTypeBool; - v.u.b = vl.u.b != vr.u.b; - break; default: v.type = FcTypeVoid; break; @@ -701,18 +924,12 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) break; case FcTypeString: switch (e->op) { - case FcOpEqual: - case FcOpContains: - v.type = FcTypeBool; - v.u.b = FcStrCmpIgnoreCase (vl.u.s, vr.u.s) == 0; - break; - case FcOpNotEqual: - v.type = FcTypeBool; - v.u.b = FcStrCmpIgnoreCase (vl.u.s, vr.u.s) != 0; - break; case FcOpPlus: v.type = FcTypeString; - v.u.s = FcStrPlus (vl.u.s, vr.u.s); + str = FcStrPlus (vl.u.s, vr.u.s); + v.u.s = FcStrStaticName (str); + FcStrFree (str); + if (!v.u.s) v.type = FcTypeVoid; break; @@ -720,17 +937,9 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) v.type = FcTypeVoid; break; } + break; case FcTypeMatrix: switch (e->op) { - case FcOpEqual: - case FcOpContains: - v.type = FcTypeBool; - v.u.b = FcMatrixEqual (vl.u.m, vr.u.m); - break; - case FcOpNotEqual: - v.type = FcTypeBool; - v.u.b = FcMatrixEqual (vl.u.m, vr.u.m); - break; case FcOpTimes: v.type = FcTypeMatrix; m = malloc (sizeof (FcMatrix)); @@ -750,26 +959,6 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) break; } break; - case FcTypeCharSet: - switch (e->op) { - case FcOpContains: - /* vl contains vr if vr - vl is empty */ - v.type = FcTypeBool; - v.u.b = FcCharSetSubtractCount (vr.u.c, vl.u.c) == 0; - break; - case FcOpEqual: - v.type = FcTypeBool; - v.u.b = FcCharSetEqual (vl.u.c, vr.u.c); - break; - case FcOpNotEqual: - v.type = FcTypeBool; - v.u.b = !FcCharSetEqual (vl.u.c, vr.u.c); - break; - default: - v.type = FcTypeVoid; - break; - } - break; default: v.type = FcTypeVoid; break; @@ -793,6 +982,70 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) } FcValueDestroy (vl); break; + case FcOpFloor: + vl = FcConfigEvaluate (p, e->u.tree.left); + switch (vl.type) { + case FcTypeInteger: + v = vl; + break; + case FcTypeDouble: + v.type = FcTypeInteger; + v.u.i = FcDoubleFloor (vl.u.d); + break; + default: + v.type = FcTypeVoid; + break; + } + FcValueDestroy (vl); + break; + case FcOpCeil: + vl = FcConfigEvaluate (p, e->u.tree.left); + switch (vl.type) { + case FcTypeInteger: + v = vl; + break; + case FcTypeDouble: + v.type = FcTypeInteger; + v.u.i = FcDoubleCeil (vl.u.d); + break; + default: + v.type = FcTypeVoid; + break; + } + FcValueDestroy (vl); + break; + case FcOpRound: + vl = FcConfigEvaluate (p, e->u.tree.left); + switch (vl.type) { + case FcTypeInteger: + v = vl; + break; + case FcTypeDouble: + v.type = FcTypeInteger; + v.u.i = FcDoubleRound (vl.u.d); + break; + default: + v.type = FcTypeVoid; + break; + } + FcValueDestroy (vl); + break; + case FcOpTrunc: + vl = FcConfigEvaluate (p, e->u.tree.left); + switch (vl.type) { + case FcTypeInteger: + v = vl; + break; + case FcTypeDouble: + v.type = FcTypeInteger; + v.u.i = FcDoubleTrunc (vl.u.d); + break; + default: + v.type = FcTypeVoid; + break; + } + FcValueDestroy (vl); + break; default: v.type = FcTypeVoid; break; @@ -803,33 +1056,51 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) static FcValueList * FcConfigMatchValueList (FcPattern *p, FcTest *t, - FcValueList *v) + FcValueList *values) { - FcValueList *ret = 0; - FcValue value = FcConfigEvaluate (p, t->expr); + FcValueList *ret = 0; + FcExpr *e = t->expr; + FcValue value; + FcValueList *v; - for (; v; v = v->next) + while (e) { - if (FcConfigCompareValue (v->value, t->op, value)) + /* Compute the value of the match expression */ + if (e->op == FcOpComma) { - if (!ret) - ret = v; + value = FcConfigEvaluate (p, e->u.tree.left); + e = e->u.tree.right; } else { - if (t->qual == FcQualAll) + value = FcConfigEvaluate (p, e); + e = 0; + } + + for (v = values; v; v = FcValueListNext(v)) + { + /* Compare the pattern value to the match expression value */ + if (FcConfigCompareValue (&v->value, t->op, &value)) { - ret = 0; - break; + if (!ret) + ret = v; + } + else + { + if (t->qual == FcQualAll) + { + ret = 0; + break; + } } } + FcValueDestroy (value); } - FcValueDestroy (value); return ret; } static FcValueList * -FcConfigValues (FcPattern *p, FcExpr *e) +FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding) { FcValueList *l; @@ -842,45 +1113,57 @@ FcConfigValues (FcPattern *p, FcExpr *e) if (e->op == FcOpComma) { l->value = FcConfigEvaluate (p, e->u.tree.left); - l->next = FcConfigValues (p, e->u.tree.right); + l->next = FcConfigValues (p, e->u.tree.right, binding); } else { l->value = FcConfigEvaluate (p, e); - l->next = 0; + l->next = NULL; } - while (l && l->value.type == FcTypeVoid) + l->binding = binding; + if (l->value.type == FcTypeVoid) { - FcValueList *next = l->next; - + FcValueList *next = FcValueListNext(l); + FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); free (l); l = next; } + return l; } static FcBool -FcConfigAdd (FcValueList **head, +FcConfigAdd (FcValueListPtr *head, FcValueList *position, FcBool append, FcValueList *new) { - FcValueList **prev, *last; + FcValueListPtr *prev, last, v; + FcValueBinding sameBinding; + if (position) + sameBinding = position->binding; + else + sameBinding = FcValueBindingWeak; + for (v = new; v != NULL; v = FcValueListNext(v)) + if (v->binding == FcValueBindingSame) + v->binding = sameBinding; if (append) { if (position) prev = &position->next; else - for (prev = head; *prev; prev = &(*prev)->next) + for (prev = head; *prev != NULL; + prev = &(*prev)->next) ; } else { if (position) { - for (prev = head; *prev; prev = &(*prev)->next) + for (prev = head; *prev != NULL; + prev = &(*prev)->next) { if (*prev == position) break; @@ -891,7 +1174,7 @@ FcConfigAdd (FcValueList **head, if (FcDebug () & FC_DBG_EDIT) { - if (!*prev) + if (*prev == NULL) printf ("position not on list\n"); } } @@ -906,7 +1189,7 @@ FcConfigAdd (FcValueList **head, if (new) { last = new; - while (last->next) + while (last->next != NULL) last = last->next; last->next = *prev; @@ -924,17 +1207,17 @@ FcConfigAdd (FcValueList **head, } static void -FcConfigDel (FcValueList **head, +FcConfigDel (FcValueListPtr *head, FcValueList *position) { - FcValueList **prev; + FcValueListPtr *prev; - for (prev = head; *prev; prev = &(*prev)->next) + for (prev = head; *prev != NULL; prev = &(*prev)->next) { if (*prev == position) { *prev = position->next; - position->next = 0; + position->next = NULL; FcValueListDestroy (position); break; } @@ -943,13 +1226,13 @@ FcConfigDel (FcValueList **head, static void FcConfigPatternAdd (FcPattern *p, - const char *object, + FcObject object, FcValueList *list, FcBool append) { if (list) { - FcPatternElt *e = FcPatternFind (p, object, FcTrue); + FcPatternElt *e = FcPatternObjectInsertElt (p, object); if (!e) return; @@ -962,30 +1245,31 @@ FcConfigPatternAdd (FcPattern *p, */ static void FcConfigPatternDel (FcPattern *p, - const char *object) + FcObject object) { - FcPatternElt *e = FcPatternFind (p, object, FcFalse); + FcPatternElt *e = FcPatternObjectFindElt (p, object); if (!e) return; - while (e->values) + while (e->values != NULL) FcConfigDel (&e->values, e->values); } static void FcConfigPatternCanon (FcPattern *p, - const char *object) + FcObject object) { - FcPatternElt *e = FcPatternFind (p, object, FcFalse); + FcPatternElt *e = FcPatternObjectFindElt (p, object); if (!e) return; - if (!e->values) - FcPatternDel (p, object); + if (e->values == NULL) + FcPatternObjectDel (p, object); } FcBool -FcConfigSubstitute (FcConfig *config, - FcPattern *p, - FcMatchKind kind) +FcConfigSubstituteWithPat (FcConfig *config, + FcPattern *p, + FcPattern *p_pat, + FcMatchKind kind) { FcSubst *s; FcSubState *st; @@ -993,6 +1277,7 @@ FcConfigSubstitute (FcConfig *config, FcTest *t; FcEdit *e; FcValueList *l; + FcPattern *m; if (!config) { @@ -1001,6 +1286,20 @@ FcConfigSubstitute (FcConfig *config, return FcFalse; } + switch (kind) { + case FcMatchPattern: + s = config->substPattern; + break; + case FcMatchFont: + s = config->substFont; + break; + case FcMatchScan: + s = config->substScan; + break; + default: + return FcFalse; + } + st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState)); if (!st && config->maxObjects) return FcFalse; @@ -1011,10 +1310,6 @@ FcConfigSubstitute (FcConfig *config, printf ("FcConfigSubstitute "); FcPatternPrint (p); } - if (kind == FcMatchPattern) - s = config->substPattern; - else - s = config->substFont; for (; s; s = s->next) { /* @@ -1028,7 +1323,15 @@ FcConfigSubstitute (FcConfig *config, printf ("FcConfigSubstitute test "); FcTestPrint (t); } - st[i].elt = FcPatternFind (p, t->field, FcFalse); + st[i].elt = 0; + if (kind == FcMatchFont && t->kind == FcMatchPattern) + m = p_pat; + else + m = p; + if (m) + st[i].elt = FcPatternObjectFindElt (m, t->object); + else + st[i].elt = 0; /* * If there's no such field in the font, * then FcQualAll matches while FcQualAny does not @@ -1047,9 +1350,13 @@ FcConfigSubstitute (FcConfig *config, * Check to see if there is a match, mark the location * to apply match-relative edits */ - st[i].value = FcConfigMatchValueList (p, t, st[i].elt->values); + st[i].value = FcConfigMatchValueList (m, t, st[i].elt->values); if (!st[i].value) break; + if (t->qual == FcQualFirst && st[i].value != st[i].elt->values) + break; + if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values) + break; } if (t) { @@ -1067,13 +1374,30 @@ FcConfigSubstitute (FcConfig *config, /* * Evaluate the list of expressions */ - l = FcConfigValues (p, e->expr); + l = FcConfigValues (p, e->expr, e->binding); /* - * Locate any test associated with this field + * Locate any test associated with this field, skipping + * tests associated with the pattern when substituting in + * the font */ for (t = s->test, i = 0; t; t = t->next, i++) - if (!FcStrCmpIgnoreCase ((FcChar8 *) t->field, (FcChar8 *) e->field)) + { + if ((t->kind == FcMatchFont || kind == FcMatchPattern) && + t->object == e->object) + { + /* + * KLUDGE - the pattern may have been reallocated or + * things may have been inserted or deleted above + * this element by other edits. Go back and find + * the element again + */ + if (e != s->edit && st[i].elt) + st[i].elt = FcPatternObjectFindElt (p, t->object); + if (!st[i].elt) + t = 0; break; + } + } switch (e->op) { case FcOpAssign: /* @@ -1083,7 +1407,7 @@ FcConfigSubstitute (FcConfig *config, if (t) { FcValueList *thisValue = st[i].value; - FcValueList *nextValue = thisValue ? thisValue->next : 0; + FcValueList *nextValue = thisValue; /* * Append the new list of values after the current value @@ -1092,7 +1416,8 @@ FcConfigSubstitute (FcConfig *config, /* * Delete the marked value */ - FcConfigDel (&st[i].elt->values, thisValue); + if (thisValue) + FcConfigDel (&st[i].elt->values, thisValue); /* * Adjust any pointers into the value list to ensure * future edits occur at the same place @@ -1110,8 +1435,8 @@ FcConfigSubstitute (FcConfig *config, * Delete all of the values and insert * the new set */ - FcConfigPatternDel (p, e->field); - FcConfigPatternAdd (p, e->field, l, FcTrue); + FcConfigPatternDel (p, e->object); + FcConfigPatternAdd (p, e->object, l, FcTrue); /* * Adjust any pointers into the value list as they no * longer point to anything valid @@ -1134,7 +1459,7 @@ FcConfigSubstitute (FcConfig *config, } /* fall through ... */ case FcOpPrependFirst: - FcConfigPatternAdd (p, e->field, l, FcFalse); + FcConfigPatternAdd (p, e->object, l, FcFalse); break; case FcOpAppend: if (t) @@ -1144,9 +1469,10 @@ FcConfigSubstitute (FcConfig *config, } /* fall through ... */ case FcOpAppendLast: - FcConfigPatternAdd (p, e->field, l, FcTrue); + FcConfigPatternAdd (p, e->object, l, FcTrue); break; default: + FcValueListDestroy (l); break; } } @@ -1155,7 +1481,7 @@ FcConfigSubstitute (FcConfig *config, * any properties without data */ for (e = s->edit; e; e = e->next) - FcConfigPatternCanon (p, e->field); + FcConfigPatternCanon (p, e->object); if (FcDebug () & FC_DBG_EDIT) { @@ -1173,9 +1499,61 @@ FcConfigSubstitute (FcConfig *config, return FcTrue; } -#ifndef FONTCONFIG_PATH -#define FONTCONFIG_PATH "/etc/fonts" -#endif +FcBool +FcConfigSubstitute (FcConfig *config, + FcPattern *p, + FcMatchKind kind) +{ + return FcConfigSubstituteWithPat (config, p, 0, kind); +} + +#if defined (_WIN32) && (defined (PIC) || defined (DLL_EXPORT)) + +static FcChar8 fontconfig_path[1000] = ""; + +BOOL WINAPI +DllMain (HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) +{ + FcChar8 *p; + + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + if (!GetModuleFileName ((HMODULE) hinstDLL, fontconfig_path, + sizeof (fontconfig_path))) + break; + + /* If the fontconfig DLL is in a "bin" or "lib" subfolder, + * assume it's a Unix-style installation tree, and use + * "etc/fonts" in there as FONTCONFIG_PATH. Otherwise use the + * folder where the DLL is as FONTCONFIG_PATH. + */ + p = strrchr (fontconfig_path, '\\'); + if (p) + { + *p = '\0'; + p = strrchr (fontconfig_path, '\\'); + if (p && (FcStrCmpIgnoreCase (p + 1, "bin") == 0 || + FcStrCmpIgnoreCase (p + 1, "lib") == 0)) + *p = '\0'; + strcat (fontconfig_path, "\\etc\\fonts"); + } + else + fontconfig_path[0] = '\0'; + + break; + } + + return TRUE; +} + +#undef FONTCONFIG_PATH +#define FONTCONFIG_PATH fontconfig_path + +#else /* !(_WIN32 && PIC) */ + +#endif /* !(_WIN32 && PIC) */ #ifndef FONTCONFIG_FILE #define FONTCONFIG_FILE "fonts.conf" @@ -1192,16 +1570,26 @@ FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file) if (!path) return 0; - strcpy (path, dir); - /* make sure there's a single separating / */ + strcpy ((char *) path, (const char *) dir); + /* make sure there's a single separator */ +#ifdef _WIN32 + if ((!path[0] || (path[strlen((char *) path)-1] != '/' && + path[strlen((char *) path)-1] != '\\')) && + !(file[0] == '/' || + file[0] == '\\' || + (isalpha (file[0]) && file[1] == ':' && (file[2] == '/' || file[2] == '\\')))) + strcat ((char *) path, "\\"); +#else if ((!path[0] || path[strlen((char *) path)-1] != '/') && file[0] != '/') strcat ((char *) path, "/"); +#endif strcat ((char *) path, (char *) file); + FcMemAlloc (FC_MEM_STRING, strlen ((char *) path) + 1); if (access ((char *) path, R_OK) == 0) return path; - free (path); + FcStrFree (path); return 0; } @@ -1221,7 +1609,7 @@ FcConfigGetPath (void) e = env; npath++; while (*e) - if (*e++ == ':') + if (*e++ == FC_SEARCH_PATH_SEPARATOR) npath++; } path = calloc (npath, sizeof (FcChar8 *)); @@ -1234,13 +1622,13 @@ FcConfigGetPath (void) e = env; while (*e) { - colon = (FcChar8 *) strchr ((char *) e, ':'); + colon = (FcChar8 *) strchr ((char *) e, FC_SEARCH_PATH_SEPARATOR); if (!colon) colon = e + strlen ((char *) e); path[i] = malloc (colon - e + 1); if (!path[i]) goto bail1; - strncpy (path[i], e, colon - e); + strncpy ((char *) path[i], (const char *) e, colon - e); path[i][colon - e] = '\0'; if (*colon) e = colon + 1; @@ -1254,7 +1642,7 @@ FcConfigGetPath (void) path[i] = malloc (strlen ((char *) dir) + 1); if (!path[i]) goto bail1; - strcpy (path[i], dir); + strcpy ((char *) path[i], (const char *) dir); return path; bail1: @@ -1275,6 +1663,33 @@ FcConfigFreePath (FcChar8 **path) free (path); } +static FcBool _FcConfigHomeEnabled = FcTrue; + +FcChar8 * +FcConfigHome (void) +{ + if (_FcConfigHomeEnabled) + { + char *home = getenv ("HOME"); + +#ifdef _WIN32 + if (home == NULL) + home = getenv ("USERPROFILE"); +#endif + + return (FcChar8 *) home; + } + return 0; +} + +FcBool +FcConfigEnableHome (FcBool enable) +{ + FcBool prev = _FcConfigHomeEnabled; + _FcConfigHomeEnabled = enable; + return prev; +} + FcChar8 * FcConfigFilename (const FcChar8 *url) { @@ -1287,14 +1702,26 @@ FcConfigFilename (const FcChar8 *url) url = (FcChar8 *) FONTCONFIG_FILE; } file = 0; + +#ifdef _WIN32 + if (isalpha (*url) && + url[1] == ':' && + (url[2] == '/' || url[2] == '\\')) + goto absolute_path; +#endif + switch (*url) { case '~': - dir = (FcChar8 *) getenv ("HOME"); + dir = FcConfigHome (); if (dir) file = FcConfigFileExists (dir, url + 1); else file = 0; break; +#ifdef _WIN32 + case '\\': + absolute_path: +#endif case '/': file = FcConfigFileExists (0, url); break; @@ -1323,6 +1750,9 @@ FcConfigAppFontAddFile (FcConfig *config, const FcChar8 *file) { FcFontSet *set; + FcStrSet *subdirs; + FcStrList *sublist; + FcChar8 *subdir; if (!config) { @@ -1331,15 +1761,37 @@ FcConfigAppFontAddFile (FcConfig *config, return FcFalse; } + subdirs = FcStrSetCreate (); + if (!subdirs) + return FcFalse; + set = FcConfigGetFonts (config, FcSetApplication); if (!set) { set = FcFontSetCreate (); if (!set) + { + FcStrSetDestroy (subdirs); return FcFalse; + } FcConfigSetFonts (config, set, FcSetApplication); } - return FcFileScan (set, 0, config->blanks, file, FcFalse); + + if (!FcFileScanConfig (set, subdirs, config->blanks, file, config)) + { + FcStrSetDestroy (subdirs); + return FcFalse; + } + if ((sublist = FcStrListCreate (subdirs))) + { + while ((subdir = FcStrListNext (sublist))) + { + FcConfigAppFontAddDir (config, subdir); + } + FcStrListDone (sublist); + } + FcStrSetDestroy (subdirs); + return FcTrue; } FcBool @@ -1347,6 +1799,9 @@ FcConfigAppFontAddDir (FcConfig *config, const FcChar8 *dir) { FcFontSet *set; + FcStrSet *subdirs; + FcStrList *sublist; + FcChar8 *subdir; if (!config) { @@ -1354,19 +1809,158 @@ FcConfigAppFontAddDir (FcConfig *config, if (!config) return FcFalse; } + subdirs = FcStrSetCreate (); + if (!subdirs) + return FcFalse; + set = FcConfigGetFonts (config, FcSetApplication); if (!set) { set = FcFontSetCreate (); if (!set) + { + FcStrSetDestroy (subdirs); return FcFalse; + } FcConfigSetFonts (config, set, FcSetApplication); } - return FcDirScan (set, 0, config->blanks, dir, FcFalse); + + if (!FcDirScanConfig (set, subdirs, config->blanks, dir, FcFalse, config)) + { + FcStrSetDestroy (subdirs); + return FcFalse; + } + if ((sublist = FcStrListCreate (subdirs))) + { + while ((subdir = FcStrListNext (sublist))) + { + FcConfigAppFontAddDir (config, subdir); + } + FcStrListDone (sublist); + } + FcStrSetDestroy (subdirs); + return FcTrue; } void FcConfigAppFontClear (FcConfig *config) { + if (!config) + { + config = FcConfigGetCurrent (); + if (!config) + return; + } + 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; +} + +/* + * Manage font-pattern based font source selectors + */ + +FcBool +FcConfigPatternsAdd (FcConfig *config, + FcPattern *pattern, + FcBool accept) +{ + FcFontSet *set = accept ? config->acceptPatterns : config->rejectPatterns; + + return FcFontSetAdd (set, pattern); +} + +static FcBool +FcConfigPatternsMatch (const FcFontSet *patterns, + const FcPattern *font) +{ + int i; + + for (i = 0; i < patterns->nfont; i++) + if (FcListPatternMatchAny (patterns->fonts[i], font)) + return FcTrue; + return FcFalse; +} + +FcBool +FcConfigAcceptFont (FcConfig *config, + const FcPattern *font) +{ + if (FcConfigPatternsMatch (config->acceptPatterns, font)) + return FcTrue; + if (FcConfigPatternsMatch (config->rejectPatterns, font)) + return FcFalse; + return FcTrue; +}