diff options
author | Patrick Lam <plam@MIT.EDU> | 2006-08-04 16:13:00 +0000 |
---|---|---|
committer | Patrick Lam <plam@MIT.EDU> | 2006-08-04 16:13:00 +0000 |
commit | 7410e40bd93beb4ab1a577d084112413431cede2 (patch) | |
tree | 036eeeccf20ddd740b3c3a18e169951f5f45abdf | |
parent | 62a4a8459adaf26833e1dad0ee96ea5a4b8c3d54 (diff) |
2006-08-04 Keith Packard (keithp@keithp.com) reviewed by: plam
Make cache directories configurable. Simplify and correct some code which
deals with per-directory caches.
-rw-r--r-- | ChangeLog | 24 | ||||
-rw-r--r-- | configure.in | 22 | ||||
-rw-r--r-- | fc-cache/fc-cache.c | 7 | ||||
-rw-r--r-- | fontconfig/fontconfig.h | 4 | ||||
-rw-r--r-- | fonts.conf.in | 5 | ||||
-rw-r--r-- | fonts.dtd | 12 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/fccache.c | 323 | ||||
-rw-r--r-- | src/fccfg.c | 28 | ||||
-rw-r--r-- | src/fcdir.c | 6 | ||||
-rw-r--r-- | src/fcinit.c | 2 | ||||
-rw-r--r-- | src/fcint.h | 13 | ||||
-rw-r--r-- | src/fcxml.c | 17 | ||||
-rw-r--r-- | test/fonts.conf.in | 1 | ||||
-rw-r--r-- | test/run-test.sh | 6 |
15 files changed, 294 insertions, 179 deletions
@@ -1,3 +1,27 @@ +2006-08-04 Keith Packard (keithp@keithp.com) + reviewed by: plam + + * configure.in: + * fonts.conf.in: + * fonts.dtd: + * fc-cache/fc-cache.c (scanDirs): + * fontconfig/fontconfig.h: + * src/Makefile.am: + * src/fcint.h: + * src/fccache.c (FcDirCacheValid, FcDirHasCurrentArch, + FcDirCacheUnlink, FcDirCacheBasename, + FcCacheReadDirs, FcDirCacheOpen, FcDirCacheRead, + FcMakeDirectory, FcDirCacheWrite): + * src/fccfg.c (FcConfigCreate, FcConfigDestroy, FcConfigAddCacheDir, + FcConfigGetCacheDirs): + * src/fcdir.c (FcDirScanConfig, FcDirSave): + * src/fcinit.c (FcInitFallbackConfig): + * src/fcxml.c (fcElementMap, FcEndElement): + * test/fonts.conf.in, test/run-test.sh: + + Make cache directories configurable. Simplify and correct + some code which deals with per-directory caches. + 2006-07-19 Jon Burgess (jburgess@uklinux.net) reviewed by: plam diff --git a/configure.in b/configure.in index acdc1f1..a3d2c77 100644 --- a/configure.in +++ b/configure.in @@ -431,6 +431,22 @@ esac AC_SUBST(FC_FONTPATH) +# +# Set default cache directory path +# +AC_ARG_WITH(cache-dir, [ --with-cache-dir=DIR Use DIR to store cache files (default /var/cache/fontconfig)], fc_cachedir="$withval", fc_cachedir=yes) + +case $fc_cachedir in +no|yes) + fc_cachedir=`eval echo "${localstatedir}/cache/"${PACKAGE}` + ;; +*) + ;; +esac +AC_SUBST(fc_cachedir) +FC_CACHEDIR=${fc_cachedir} +AC_SUBST(FC_CACHEDIR) + FC_FONTDATE=`LC_ALL=C date` AC_SUBST(FC_FONTDATE) @@ -516,12 +532,6 @@ fi AC_SUBST(DOCDIR) -# -# Make /var/cache/fontconfig directory available to source code -# - -pkgcachedir='${localstatedir}/cache/'${PACKAGE} -AC_SUBST(pkgcachedir) AC_OUTPUT([ Makefile diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c index 5e4ada4..8519388 100644 --- a/fc-cache/fc-cache.c +++ b/fc-cache/fc-cache.c @@ -230,7 +230,8 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool ret++; continue; } - if (!force && FcDirCacheValid (dir) && FcDirCacheHasCurrentArch (dir)) + if (!force && FcDirCacheValid (dir, config) && + FcDirCacheHasCurrentArch (dir, config)) { if (verbose) printf ("skipping, %d fonts, %d dirs\n", @@ -244,14 +245,12 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool /* This is the only reason we can't combine * Valid w/HasCurrentArch... */ - if (!FcDirCacheValid (dir)) + if (!FcDirCacheValid (dir, config)) if (!FcDirCacheUnlink (dir, config)) ret++; if (!FcDirSave (set, subdirs, dir)) { - if (!ret) - fprintf (stderr, "Caches are currently saved to \"%s\"\n", PKGCACHEDIR); fprintf (stderr, "Can't save cache for \"%s\"\n", dir); ret++; } diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h index 2ddd42f..8ef2f7c 100644 --- a/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig.h @@ -276,10 +276,10 @@ typedef struct _FcStrSet FcStrSet; _FCFUNCPROTOBEGIN FcBool -FcDirCacheValid (const FcChar8 *cache_file); +FcDirCacheValid (const FcChar8 *cache_file, FcConfig *config); FcBool -FcDirCacheHasCurrentArch (const FcChar8 *dir); +FcDirCacheHasCurrentArch (const FcChar8 *dir, FcConfig *config); FcBool FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config); diff --git a/fonts.conf.in b/fonts.conf.in index 3329d7a..035ee32 100644 --- a/fonts.conf.in +++ b/fonts.conf.in @@ -27,6 +27,11 @@ @FC_FONTPATH@ <dir>~/.fonts</dir> +<!-- Font cache directory list --> + + <cachedir>@FC_CACHEDIR@</cachedir> + <cachedir>~/.fonts/fontconfig</cachedir> + <!-- Accept deprecated 'mono' alias, replacing it with 'monospace' --> @@ -23,6 +23,18 @@ <!ATTLIST cache xml:space (default|preserve) 'preserve'> <!-- + Add a directory that is searched for font cache files. + These hold per-directory cache data and are searched in + order for each directory. When writing cache files, the first + directory which allows the cache file to be created is used. + + A leading '~' in a directory name is replaced with the users + home directory path. +--> +<!ELEMENT cachedir (#PCDATA)> +<!ATTLIST cachedir xml:space (default|preserve) 'preserve'> + +<!-- Reference another configuration file; note that this is another complete font configuration file and not just a file included by the XML parser. diff --git a/src/Makefile.am b/src/Makefile.am index 01c9c5e..5d144bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,8 +63,6 @@ uninstall-ms-import-lib: endif -AM_CPPFLAGS = -DPKGCACHEDIR='"${pkgcachedir}"' - INCLUDES = \ -I$(top_srcdir) \ -I$(top_srcdir)/src \ @@ -72,6 +70,7 @@ INCLUDES = \ $(LIBXML2_CFLAGS) \ $(EXPAT_CFLAGS) \ $(WARN_CFLAGS) \ + -DFC_CACHEDIR='"$(FC_CACHEDIR)"' \ -DFONTCONFIG_PATH='"$(CONFDIR)"' EXTRA_DIST = fontconfig.def.in diff --git a/src/fccache.c b/src/fccache.c index a653085..eb0b647 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -45,10 +45,7 @@ #endif static int -FcDirCacheOpen (const FcChar8 * dir); - -static char * -FcDirCacheHashName (const FcChar8 * dir, int collisions); +FcDirCacheOpen (FcConfig *config, const FcChar8 *dir, FcChar8 **cache_path); static off_t FcCacheSkipToArch (int fd, const char * arch); @@ -748,7 +745,7 @@ FcCacheCopyOld (int fd, int fd_orig, off_t start) * cache, and the hashed location has an up-to-date cache. Oh well, * sucks to be you in that case! */ FcBool -FcDirCacheValid (const FcChar8 *dir) +FcDirCacheValid (const FcChar8 *dir, FcConfig *config) { struct stat file_stat, dir_stat; int fd; @@ -756,7 +753,7 @@ FcDirCacheValid (const FcChar8 *dir) if (stat ((char *) dir, &dir_stat) < 0) return FcFalse; - fd = FcDirCacheOpen (dir); + fd = FcDirCacheOpen (config, dir, NULL); if (fd < 0) return FcFalse; @@ -782,7 +779,7 @@ FcDirCacheValid (const FcChar8 *dir) /* Assumes that the cache file in 'dir' exists. * Checks that the cache has the appropriate arch section. */ FcBool -FcDirCacheHasCurrentArch (const FcChar8 *dir) +FcDirCacheHasCurrentArch (const FcChar8 *dir, FcConfig *config) { int fd; off_t current_arch_start; @@ -790,7 +787,7 @@ FcDirCacheHasCurrentArch (const FcChar8 *dir) FcCache metadata; char subdirName[FC_MAX_FILE_LEN + 1 + 12 + 1]; - fd = FcDirCacheOpen (dir); + fd = FcDirCacheOpen (config, dir, NULL); if (fd < 0) goto bail; @@ -827,57 +824,81 @@ FcDirCacheHasCurrentArch (const FcChar8 *dir) return FcFalse; } -FcBool -FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) +#define CACHEBASE_LEN (1 + 32 + sizeof (FC_CACHE_SUFFIX)) + +static const char bin2hex[] = { '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f' }; + +static FcChar8 * +FcDirCacheBasename (const FcChar8 * dir, FcChar8 cache_base[CACHEBASE_LEN]) { - char *cache_hashed = 0; - int fd, collisions; - struct stat cache_stat; - char dir_buf[FC_MAX_FILE_LEN]; + unsigned char hash[16]; + FcChar8 *hex_hash; + int cnt; + struct MD5Context ctx; - dir = FcConfigNormalizeFontDir (config, dir); + MD5Init (&ctx); + MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir)); - /* Remove any applicable hashed files. */ - fd = -1; collisions = 0; - do + MD5Final (hash, &ctx); + + cache_base[0] = '/'; + hex_hash = cache_base + 1; + for (cnt = 0; cnt < 16; ++cnt) { - if (cache_hashed) - FcStrFree ((FcChar8 *)cache_hashed); + hex_hash[2*cnt ] = bin2hex[hash[cnt] >> 4]; + hex_hash[2*cnt+1] = bin2hex[hash[cnt] & 0xf]; + } + hex_hash[2*cnt] = 0; + strcat ((char *) cache_base, FC_CACHE_SUFFIX); - cache_hashed = FcDirCacheHashName (dir, collisions++); - if (!cache_hashed) - goto bail; + return cache_base; +} - if (fd > 0) - close (fd); - fd = open(cache_hashed, O_RDONLY | O_BINARY); - if (fd == -1) - { - FcStrFree ((FcChar8 *)cache_hashed); - return FcTrue; - } +FcBool +FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) +{ + int fd = -1; + FcChar8 *cache_hashed = NULL; + FcChar8 cache_base[CACHEBASE_LEN]; + FcStrList *list; + FcChar8 *cache_dir; + char dir_buf[FC_MAX_FILE_LEN]; - if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || !strlen(dir_buf)) - { - FcStrFree ((FcChar8 *)cache_hashed); - goto bail; - } - } while (strcmp ((char *) dir_buf, (char *) dir) != 0); + dir = FcConfigNormalizeFontDir (config, dir); - close (fd); + FcDirCacheBasename (dir, cache_base); - if (stat ((char *) cache_hashed, &cache_stat) == 0 && - unlink ((char *)cache_hashed) != 0) + list = FcStrListCreate (config->cacheDirs); + if (!list) + return FcFalse; + + while ((cache_dir = FcStrListNext (list))) { - FcStrFree ((FcChar8 *)cache_hashed); - goto bail; + cache_hashed = FcStrPlus (cache_dir, cache_base); + if (!cache_hashed) + break; + fd = open((char *) cache_hashed, O_RDONLY | O_BINARY); + FcStrFree (cache_hashed); + if (fd >= 0) + { + if (FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) && + strcmp (dir_buf, (char *) dir) == 0) + { + close (fd); + if (unlink ((char *) cache_hashed) < 0) + break; + } else + close (fd); + } } - - FcStrFree ((FcChar8 *)cache_hashed); + FcStrListDone (list); + /* return FcFalse if something went wrong */ + if (cache_dir) + return FcFalse; return FcTrue; - - bail: - return FcFalse; } static int @@ -949,8 +970,8 @@ FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache, FcStrSetDestroy (subdirs); continue; } - if (FcDirCacheValid (dir) && - FcDirCacheHasCurrentArch (dir) && + if (FcDirCacheValid (dir, config) && + FcDirCacheHasCurrentArch (dir, config) && FcDirCacheRead (set, subdirs, dir, config)) { /* if an old entry is found in the global cache, disable it */ @@ -1009,87 +1030,53 @@ FcCacheRead (FcConfig *config, FcGlobalCache * cache) return 0; } -static const char bin2hex[] = { '0', '1', '2', '3', - '4', '5', '6', '7', - '8', '9', 'a', 'b', - 'c', 'd', 'e', 'f' }; - -static char * -FcDirCacheHashName (const FcChar8 * dir, int collisions) -{ - unsigned char hash[16], hex_hash[33]; - char *cache_hashed; - unsigned char uscore = '_'; - int cnt, i; - FcChar8 *tmp; - struct MD5Context ctx; - - MD5Init (&ctx); - MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir)); - - for (i = 0; i < collisions; i++) - MD5Update (&ctx, &uscore, 1); - - MD5Final (hash, &ctx); - - for (cnt = 0; cnt < 16; ++cnt) - { - hex_hash[2*cnt] = bin2hex[hash[cnt] >> 4]; - hex_hash[2*cnt+1] = bin2hex[hash[cnt] & 0xf]; - } - hex_hash[32] = 0; - - tmp = FcStrPlus ((FcChar8 *)hex_hash, (FcChar8 *)FC_CACHE_SUFFIX); - if (!tmp) - return 0; - - cache_hashed = (char *)FcStrPlus ((FcChar8 *)PKGCACHEDIR"/", tmp); - free (tmp); - - return cache_hashed; -} - -/* Opens the hashed name for cache_file. - * This would fail in the unlikely event of a collision and subsequent - * removal of the file which originally caused the collision. */ +/* Opens the cache file for 'dir' for reading. + * This searches the list of cache dirs for the relevant cache file, + * returning the first one found. + */ static int -FcDirCacheOpen (const FcChar8 *dir) +FcDirCacheOpen (FcConfig *config, const FcChar8 *dir, FcChar8 **cache_path) { - FcBool found; - int fd = -1, collisions = 0; - char *cache_hashed; + int fd = -1; + FcChar8 *cache_hashed = NULL; + FcChar8 cache_base[CACHEBASE_LEN]; + FcStrList *list; + FcChar8 *cache_dir; char dir_buf[FC_MAX_FILE_LEN]; - struct stat dir_stat; - if (stat ((char *)dir, &dir_stat) == -1) - return -1; + FcDirCacheBasename (dir, cache_base); - found = FcFalse; - do + list = FcStrListCreate (config->cacheDirs); + if (!list) + return -1; + + while ((cache_dir = FcStrListNext (list))) { - struct stat c; - - if (fd >= 0) - close (fd); - - cache_hashed = FcDirCacheHashName (dir, collisions++); - if (!cache_hashed) - return -1; - - fd = open(cache_hashed, O_RDONLY | O_BINARY); - FcStrFree ((FcChar8 *)cache_hashed); - - if (fd == -1) + cache_hashed = FcStrPlus (cache_dir, cache_base); + if (!cache_hashed) break; - if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || - !strlen(dir_buf)) + fd = open((char *) cache_hashed, O_RDONLY | O_BINARY); + if (fd >= 0) break; + FcStrFree (cache_hashed); + } + FcStrListDone (list); - if (stat ((char *)dir_buf, &c) == -1) - continue; - - found = (c.st_ino == dir_stat.st_ino) && (c.st_dev == dir_stat.st_dev); - } while (!found); + if (fd < 0) + return -1; + + if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || + strcmp (dir_buf, (char *) dir) != 0) + { + close (fd); + FcStrFree (cache_hashed); + return -1; + } + + if (cache_path) + *cache_path = cache_hashed; + else + FcStrFree (cache_hashed); return fd; } @@ -1104,7 +1091,7 @@ FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig * off_t current_arch_start = 0; char subdirName[FC_MAX_FILE_LEN + 1 + 12 + 1]; - fd = FcDirCacheOpen (dir); + fd = FcDirCacheOpen (config, dir, NULL); if (fd < 0) goto bail; @@ -1278,56 +1265,77 @@ FcDirCacheProduce (FcFontSet *set, FcCache *metadata) return 0; } +static FcBool +FcMakeDirectory (const FcChar8 *dir) +{ + FcChar8 *parent; + FcBool ret; + + if (strlen ((char *) dir) == 0) + return FcFalse; + + parent = FcStrDirname (dir); + if (!parent) + return FcFalse; + if (access ((char *) parent, W_OK|X_OK) == 0) + ret = mkdir ((char *) dir, 0777) == 0; + else if (access ((char *) parent, F_OK) == -1) + ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0777) == 0); + else + ret = FcFalse; + FcStrFree (parent); + return ret; +} + /* write serialized state to the cache file */ FcBool -FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir) +FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *config) { - char *cache_hashed; + FcChar8 cache_base[CACHEBASE_LEN]; + FcChar8 *cache_hashed; int fd, fd_orig, i, dirs_count; FcAtomic *atomic; FcCache metadata; off_t current_arch_start = 0, truncate_to; - char dir_buf[FC_MAX_FILE_LEN]; - int collisions; - + FcStrList *list; char *current_arch_machine_name, * header; void *current_dir_block = 0; + FcChar8 *cache_dir; dir = FcConfigNormalizeFontDir (FcConfigGetCurrent(), dir); if (!dir) return FcFalse; - /* Ensure that we're not trampling a cache for some other dir. */ - /* This is slightly different from FcDirCacheOpen, since it - * needs the filename, not the file descriptor. */ - fd = -1; collisions = 0; - do - { - cache_hashed = FcDirCacheHashName (dir, collisions++); - if (!cache_hashed) - goto bail0; - - if (fd > 0) - close (fd); - fd = open(cache_hashed, O_RDONLY | O_BINARY); - if (fd == -1) - break; - if(!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || !strlen(dir_buf)) - { - close (fd); - FcStrFree ((FcChar8 *)cache_hashed); - continue; - } - close (fd); - - if (strcmp (dir_buf, (char *) dir) != 0) - { - FcStrFree ((FcChar8 *)cache_hashed); - continue; - } + /* + * Check for an existing cache file and dump stuff in the same place + */ + fd = FcDirCacheOpen (config, dir, &cache_hashed); - break; - } while (1); + if (fd >= 0) + close (fd); + else { + list = FcStrListCreate (config->cacheDirs); + if (!list) + return FcFalse; + while ((cache_dir = FcStrListNext (list))) { + if (access ((char *) cache_dir, W_OK|X_OK) == 0) + break; + /* + * If the directory doesn't exist, try to create it + */ + if (access ((char *) cache_dir, F_OK) == -1) { + if (FcMakeDirectory (cache_dir)) + break; + } + } + FcStrListDone (list); + if (!cache_dir) + return FcFalse; + FcDirCacheBasename (dir, cache_base); + cache_hashed = FcStrPlus (cache_dir, cache_base); + if (!cache_hashed) + return FcFalse; + } current_dir_block = FcDirCacheProduce (set, &metadata); @@ -1455,7 +1463,6 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir) FcAtomicDestroy (atomic); bail1: FcStrFree ((FcChar8 *)cache_hashed); - bail0: if (current_dir_block) free (current_dir_block); return FcFalse; diff --git a/src/fccfg.c b/src/fccfg.c index 32e0084..8eb82e5 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -100,13 +100,17 @@ FcConfigCreate (void) if (!FcConfigSetCache (config, cache_dir)) { FcStrFree (cache_dir); - goto bail6; + goto bail8; } FcStrFree (cache_dir); } } #endif + config->cacheDirs = FcStrSetCreate (); + if (!config->cacheDirs) + goto bail9; + config->blanks = 0; config->substPattern = 0; @@ -120,6 +124,8 @@ FcConfigCreate (void) return config; +bail9: + FcStrFree (config->cache); bail8: FcFontSetDestroy (config->rejectPatterns); bail7: @@ -226,6 +232,7 @@ FcConfigDestroy (FcConfig *config) FcStrSetDestroy (config->configDirs); FcStrSetDestroy (config->fontDirs); + FcStrSetDestroy (config->cacheDirs); FcStrSetDestroy (config->configFiles); FcStrSetDestroy (config->acceptGlobs); FcStrSetDestroy (config->rejectGlobs); @@ -513,6 +520,25 @@ FcConfigGetFontDirs (FcConfig *config) } FcBool +FcConfigAddCacheDir (FcConfig *config, + const FcChar8 *d) +{ + return FcStrSetAddFilename (config->cacheDirs, d); +} + +FcStrList * +FcConfigGetCacheDirs (FcConfig *config) +{ + if (!config) + { + config = FcConfigGetCurrent (); + if (!config) + return 0; + } + return FcStrListCreate (config->cacheDirs); +} + +FcBool FcConfigAddConfigFile (FcConfig *config, const FcChar8 *f) { diff --git a/src/fcdir.c b/src/fcdir.c index 4463b31..1545955 100644 --- a/src/fcdir.c +++ b/src/fcdir.c @@ -151,8 +151,8 @@ FcDirScanConfig (FcFontSet *set, if (cache && FcGlobalCacheReadDir (set, dirs, cache, (char *)dir, config)) return FcTrue; - if (FcDirCacheValid (dir) && - FcDirCacheHasCurrentArch (dir) && + if (FcDirCacheValid (dir, config) && + FcDirCacheHasCurrentArch (dir, config) && FcDirCacheRead (set, dirs, dir, config)) return FcTrue; } @@ -277,5 +277,5 @@ FcDirScan (FcFontSet *set, FcBool FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir) { - return FcDirCacheWrite (set, dirs, dir); + return FcDirCacheWrite (set, dirs, dir, FcConfigGetCurrent ()); } diff --git a/src/fcinit.c b/src/fcinit.c index ac6dad7..8f60cd8 100644 --- a/src/fcinit.c +++ b/src/fcinit.c @@ -35,6 +35,8 @@ FcInitFallbackConfig (void) goto bail0; if (!FcConfigAddDir (config, (FcChar8 *) FC_DEFAULT_FONTS)) goto bail1; + if (!FcConfigAddCacheDir (config, (FcChar8 *) FC_CACHEDIR)) + goto bail1; return config; bail1: diff --git a/src/fcint.h b/src/fcint.h index 6d8ae5d..6a61b39 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -389,6 +389,10 @@ struct _FcConfig { */ FcStrSet *fontDirs; /* + * List of directories containing cache files. + */ + FcStrSet *cacheDirs; + /* * Names of all of the configuration files used * to create this configuration */ @@ -476,7 +480,7 @@ FcFontSet * FcCacheRead (FcConfig *config, FcGlobalCache * cache); FcBool -FcDirCacheWrite (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir); +FcDirCacheWrite (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config); FcBool FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config); @@ -509,6 +513,13 @@ FcConfigAddDir (FcConfig *config, const FcChar8 *d); FcBool +FcConfigAddCacheDir (FcConfig *config, + const FcChar8 *d); + +FcStrList * +FcConfigGetCacheDirs (FcConfig *config); + +FcBool FcConfigAddConfigFile (FcConfig *config, const FcChar8 *f); diff --git a/src/fcxml.c b/src/fcxml.c index 2438193..c5c9065 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -285,6 +285,7 @@ typedef enum _FcElement { FcElementNone, FcElementFontconfig, FcElementDir, + FcElementCacheDir, FcElementCache, FcElementInclude, FcElementConfig, @@ -345,6 +346,7 @@ static const struct { } fcElementMap[] = { { "fontconfig", FcElementFontconfig }, { "dir", FcElementDir }, + { "cachedir", FcElementCacheDir }, { "cache", FcElementCache }, { "include", FcElementInclude }, { "config", FcElementConfig }, @@ -2053,6 +2055,21 @@ FcEndElement(void *userData, const XML_Char *name) } FcStrFree (data); break; + case FcElementCacheDir: + data = FcStrBufDone (&parse->pstack->str); + if (!data) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + break; + } + if (!FcStrUsesHome (data) || FcConfigHome ()) + { + if (!FcConfigAddCacheDir (parse->config, data)) + FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data); + } + FcStrFree (data); + break; + case FcElementCache: data = FcStrBufDone (&parse->pstack->str); if (!data) diff --git a/test/fonts.conf.in b/test/fonts.conf.in index 492e36f..5ad85c9 100644 --- a/test/fonts.conf.in +++ b/test/fonts.conf.in @@ -1,4 +1,5 @@ <fontconfig> <dir>@FONTDIR@</dir> <cache>@CACHEFILE@</cache> +<cachedir>@CACHEDIR@</cachedir> </fontconfig> diff --git a/test/run-test.sh b/test/run-test.sh index 428503b..8b817c0 100644 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -3,6 +3,7 @@ TESTDIR=${srcdir-`pwd`} FONTDIR=`pwd`/fonts CACHEFILE=`pwd`/fonts.cache +CACHEDIR=`pwd`/cache.dir ECHO=true @@ -39,7 +40,8 @@ dotest () { } sed "s!@FONTDIR@!$FONTDIR! -s!@CACHEFILE@!$CACHEFILE!" < $TESTDIR/fonts.conf.in > fonts.conf +s!@CACHEFILE@!$CACHEFILE! +s!@CACHEDIR@!$CACHEDIR!" < $TESTDIR/fonts.conf.in > fonts.conf FONTCONFIG_FILE=`pwd`/fonts.conf export FONTCONFIG_FILE @@ -89,4 +91,4 @@ mkdir $FONTDIR/a cp $FONT2 $FONTDIR/a check -rm -rf $FONTDIR $CACHEFILE $FONTCONFIG_FILE out +rm -rf $FONTDIR $CACHEFILE $CACHEDIR $FONTCONFIG_FILE out |