summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Lam <plam@MIT.EDU>2006-08-04 16:13:00 +0000
committerPatrick Lam <plam@MIT.EDU>2006-08-04 16:13:00 +0000
commit7410e40bd93beb4ab1a577d084112413431cede2 (patch)
tree036eeeccf20ddd740b3c3a18e169951f5f45abdf
parent62a4a8459adaf26833e1dad0ee96ea5a4b8c3d54 (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--ChangeLog24
-rw-r--r--configure.in22
-rw-r--r--fc-cache/fc-cache.c7
-rw-r--r--fontconfig/fontconfig.h4
-rw-r--r--fonts.conf.in5
-rw-r--r--fonts.dtd12
-rw-r--r--src/Makefile.am3
-rw-r--r--src/fccache.c323
-rw-r--r--src/fccfg.c28
-rw-r--r--src/fcdir.c6
-rw-r--r--src/fcinit.c2
-rw-r--r--src/fcint.h13
-rw-r--r--src/fcxml.c17
-rw-r--r--test/fonts.conf.in1
-rw-r--r--test/run-test.sh6
15 files changed, 294 insertions, 179 deletions
diff --git a/ChangeLog b/ChangeLog
index d8e6404..5e4b1f4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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'
-->
diff --git a/fonts.dtd b/fonts.dtd
index 6c9a33d..cd016d3 100644
--- a/fonts.dtd
+++ b/fonts.dtd
@@ -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