]> git.wh0rd.org Git - fontconfig.git/commitdiff
Reinstate the old global cache code. For the forseeable future, it's
authorPatrick Lam <plam@MIT.EDU>
Thu, 25 Aug 2005 07:38:02 +0000 (07:38 +0000)
committerPatrick Lam <plam@MIT.EDU>
Thu, 25 Aug 2005 07:38:02 +0000 (07:38 +0000)
    probably all right to use the global cache as it was previously and
    just store filenames and font info, as long as no mmap cache exists in
    the directory. Of course, if an mmap cache exists, use that instead.
If a directory cache does not exist or is invalid, load the fonts for just
    that directory using the old codepath.
Fix premature free of the FcPatterns belonging to the FcFontSet which we
    create from the mmapped files.

src/fccache.c
src/fccfg.c
src/fcint.h

index 55187c9a258f1d2ff54e0ef9070046893f98ed59..58adcb9da10a6090cde1fbb889f01dd3f023a70e 100644 (file)
 #include <sys/utsname.h>
 #include "fcint.h"
 
+/*
+ * POSIX has broken stdio so that getc must do thread-safe locking,
+ * this is a serious performance problem for applications doing large
+ * amounts of IO with getc (as is done here).  If available, use
+ * the getc_unlocked varient instead.
+ */
+#if defined(getc_unlocked) || defined(_IO_getc_unlocked)
+#define GETC(f) getc_unlocked(f)
+#define PUTC(c,f) putc_unlocked(c,f)
+#else
+#define GETC(f) getc(f)
+#define PUTC(c,f) putc(c,f)
+#endif
+
+#define FC_DBG_CACHE_REF    1024
+
 #define PAGESIZE 8192
 
 static FcBool force;
 
 static FcChar8 *
-FcCacheReadString (int fd, FcChar8 *dest, int len)
+FcCacheReadString (FILE *f, FcChar8 *dest, int len)
+{
+    int                c;
+    FcBool     escape;
+    FcChar8    *d;
+    int                size;
+    int                i;
+
+    while ((c = GETC (f)) != EOF)
+       if (c == '"')
+           break;
+    if (c == EOF)
+       return FcFalse;
+    if (len == 0)
+       return FcFalse;
+    
+    size = len;
+    i = 0;
+    d = dest;
+    escape = FcFalse;
+    while ((c = GETC (f)) != EOF)
+    {
+       if (!escape)
+       {
+           switch (c) {
+           case '"':
+               c = '\0';
+               break;
+           case '\\':
+               escape = FcTrue;
+               continue;
+           }
+       }
+       if (i == size)
+       {
+           FcChar8 *new = malloc (size * 2);   /* freed in caller */
+           if (!new)
+               break;
+           memcpy (new, d, size);
+           size *= 2;
+           if (d != dest)
+               free (d);
+           d = new;
+       }
+       d[i++] = c;
+       if (c == '\0')
+           return d;
+       escape = FcFalse;
+    }
+    if (d != dest)
+       free (d);
+    return 0;
+}
+
+static FcBool
+FcCacheReadUlong (FILE *f, unsigned long *dest)
+{
+    unsigned long   t;
+    int                    c;
+
+    while ((c = GETC (f)) != EOF)
+    {
+       if (!isspace (c))
+           break;
+    }
+    if (c == EOF)
+       return FcFalse;
+    t = 0;
+    for (;;)
+    {
+       if (c == EOF || isspace (c))
+           break;
+       if (!isdigit (c))
+           return FcFalse;
+       t = t * 10 + (c - '0');
+       c = GETC (f);
+    }
+    *dest = t;
+    return FcTrue;
+}
+
+static FcBool
+FcCacheReadInt (FILE *f, int *dest)
+{
+    unsigned long   t;
+    FcBool         ret;
+
+    ret = FcCacheReadUlong (f, &t);
+    if (ret)
+       *dest = (int) t;
+    return ret;
+}
+
+static FcBool
+FcCacheReadTime (FILE *f, time_t *dest)
+{
+    unsigned long   t;
+    FcBool         ret;
+
+    ret = FcCacheReadUlong (f, &t);
+    if (ret)
+       *dest = (time_t) t;
+    return ret;
+}
+
+static FcBool
+FcCacheWriteChars (FILE *f, const FcChar8 *chars)
+{
+    FcChar8    c;
+    while ((c = *chars++))
+    {
+       switch (c) {
+       case '"':
+       case '\\':
+           if (PUTC ('\\', f) == EOF)
+               return FcFalse;
+           /* fall through */
+       default:
+           if (PUTC (c, f) == EOF)
+               return FcFalse;
+       }
+    }
+    return FcTrue;
+}
+
+static FcBool
+FcCacheWriteString (FILE *f, const FcChar8 *string)
+{
+
+    if (PUTC ('"', f) == EOF)
+       return FcFalse;
+    if (!FcCacheWriteChars (f, string))
+       return FcFalse;
+    if (PUTC ('"', f) == EOF)
+       return FcFalse;
+    return FcTrue;
+}
+
+static FcBool
+FcCacheWritePath (FILE *f, const FcChar8 *dir, const FcChar8 *file)
+{
+    if (PUTC ('"', f) == EOF)
+       return FcFalse;
+    if (dir)
+       if (!FcCacheWriteChars (f, dir))
+           return FcFalse;
+#ifdef _WIN32
+    if (dir &&
+       dir[strlen((const char *) dir) - 1] != '/' &&
+       dir[strlen((const char *) dir) - 1] != '\\')
+    {
+       if (!FcCacheWriteChars (f, "\\"))
+           return FcFalse;
+    }
+#else
+    if (dir && dir[strlen((const char *) dir) - 1] != '/')
+       if (PUTC ('/', f) == EOF)
+           return FcFalse;
+#endif
+    if (!FcCacheWriteChars (f, file))
+       return FcFalse;
+    if (PUTC ('"', f) == EOF)
+       return FcFalse;
+    return FcTrue;
+}
+
+static FcBool
+FcCacheWriteUlong (FILE *f, unsigned long t)
+{
+    int            pow;
+    unsigned long   temp, digit;
+
+    temp = t;
+    pow = 1;
+    while (temp >= 10)
+    {
+       temp /= 10;
+       pow *= 10;
+    }
+    temp = t;
+    while (pow)
+    {
+       digit = temp / pow;
+       if (PUTC ((char) digit + '0', f) == EOF)
+           return FcFalse;
+       temp = temp - pow * digit;
+       pow = pow / 10;
+    }
+    return FcTrue;
+}
+
+static FcBool
+FcCacheWriteInt (FILE *f, int i)
+{
+    return FcCacheWriteUlong (f, (unsigned long) i);
+}
+
+static FcBool
+FcCacheWriteTime (FILE *f, time_t t)
+{
+    return FcCacheWriteUlong (f, (unsigned long) t);
+}
+
+static FcChar8 *
+FcCacheReadString2 (int fd, FcChar8 *dest, int len)
 {
     FcChar8    c;
     FcBool     escape;
@@ -73,14 +294,99 @@ FcCacheReadString (int fd, FcChar8 *dest, int len)
 }
 
 static FcBool
-FcCacheWriteString (int fd, const FcChar8 *chars)
+FcCacheWriteString2 (int fd, const FcChar8 *chars)
 {
     if (write (fd, chars, strlen(chars)+1) != strlen(chars)+1)
        return FcFalse;
     return FcTrue;
 }
 
-#if 0
+static FcBool
+FcCacheFontSetAdd (FcFontSet       *set,
+                  FcStrSet         *dirs,
+                  const FcChar8    *dir,
+                  int              dir_len,
+                  const FcChar8    *file,
+                  const FcChar8    *name,
+                  FcConfig         *config)
+{
+    FcChar8    path_buf[8192], *path;
+    int                len;
+    FcBool     ret = FcFalse;
+    FcPattern  *font;
+    FcPattern  *frozen;
+
+    path = path_buf;
+    len = (dir_len + 1 + strlen ((const char *) file) + 1);
+    if (len > sizeof (path_buf))
+    {
+       path = malloc (len);    /* freed down below */
+       if (!path)
+           return FcFalse;
+    }
+    strncpy ((char *) path, (const char *) dir, dir_len);
+#ifdef _WIN32
+    if (dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\' )
+       path[dir_len++] = '\\';
+#else
+    if (dir[dir_len - 1] != '/')
+       path[dir_len++] = '/';
+#endif
+    strcpy ((char *) path + dir_len, (const char *) file);
+    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);
+       ret = FcStrSetAdd (dirs, path);
+    }
+    else if (!FcStrCmp (name, FC_FONT_FILE_INVALID))
+    {
+       ret = FcTrue;
+    }
+    else
+    {
+       font = FcNameParse (name);
+       if (font)
+       {
+           FcChar8 *family;
+           
+           if (FcDebug () & FC_DBG_CACHEV)
+               printf (" dir cache file \"%s\"\n", file);
+           ret = FcPatternAddString (font, FC_FILE, path);
+           /*
+            * Make sure the pattern has the file name as well as
+            * already containing at least one family name.
+            */
+           if (ret && 
+               FcPatternGetString (font, FC_FAMILY, 0, &family) == FcResultMatch &&
+               (!config || FcConfigAcceptFont (config, font)))
+           {
+               frozen = FcPatternFreeze (font);
+               ret = (frozen != 0);
+               if (ret)
+                  ret = FcFontSetAdd (set, frozen);
+           }
+           FcPatternDestroy (font);
+       }
+    }
+    if (path != path_buf) free (path);
+    return ret;
+    
+}
+
+static unsigned int
+FcCacheHash (const FcChar8 *string, int len)
+{
+    unsigned int    h = 0;
+    FcChar8        c;
+
+    while (len-- && (c = *string++))
+       h = (h << 1) ^ c;
+    return h;
+}
+
 /*
  * Verify the saved timestamp for a file
  */
@@ -156,6 +462,328 @@ FcFilePathInfoGet (const FcChar8    *path)
     return i;
 }
 
+FcGlobalCacheDir *
+FcGlobalCacheDirGet (FcGlobalCache  *cache,
+                    const FcChar8  *dir,
+                    int            len,
+                    FcBool         create_missing)
+{
+    unsigned int       hash = FcCacheHash (dir, len);
+    FcGlobalCacheDir   *d, **prev;
+
+    for (prev = &cache->ents[hash % FC_GLOBAL_CACHE_DIR_HASH_SIZE];
+        (d = *prev);
+        prev = &(*prev)->next)
+    {
+       if (d->info.hash == hash && d->len == len &&
+           !strncmp ((const char *) d->info.file,
+                     (const char *) dir, len))
+           break;
+    }
+    if (!(d = *prev))
+    {
+       int     i;
+       if (!create_missing)
+           return 0;
+       d = malloc (sizeof (FcGlobalCacheDir) + len + 1);
+       if (!d)
+           return 0;
+       FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + len + 1);
+       d->next = *prev;
+       *prev = d;
+       d->info.hash = hash;
+       d->info.file = (FcChar8 *) (d + 1);
+       strncpy ((char *) d->info.file, (const char *) dir, len);
+       d->info.file[len] = '\0';
+       d->info.time = 0;
+       d->info.referenced = FcFalse;
+       d->len = len;
+       for (i = 0; i < FC_GLOBAL_CACHE_FILE_HASH_SIZE; i++)
+           d->ents[i] = 0;
+       d->subdirs = 0;
+    }
+    return d;
+}
+
+static FcGlobalCacheInfo *
+FcGlobalCacheDirAdd (FcGlobalCache  *cache,
+                    const FcChar8  *dir,
+                    time_t         time,
+                    FcBool         replace,
+                    FcBool         create_missing)
+{
+    FcGlobalCacheDir   *d;
+    FcFilePathInfo     i;
+    FcGlobalCacheSubdir        *subdir;
+    FcGlobalCacheDir   *parent;
+
+    i = FcFilePathInfoGet (dir);
+    parent = FcGlobalCacheDirGet (cache, i.dir, i.dir_len, create_missing);
+    /*
+     * Tricky here -- directories containing fonts.cache-1 files
+     * need entries only when the parent doesn't have a cache file.
+     * That is, when the parent already exists in the cache, is
+     * referenced and has a "real" timestamp.  The time of 0 is
+     * special and marks directories which got stuck in the
+     * global cache for this very reason.  Yes, it could
+     * use a separate boolean field, and probably should.
+     */
+    if (!parent || (!create_missing && 
+                   (!parent->info.referenced ||
+                   (parent->info.time == 0))))
+       return 0;
+    /*
+     * Add this directory to the cache
+     */
+    d = FcGlobalCacheDirGet (cache, dir, strlen ((const char *) dir), FcTrue);
+    if (!d)
+       return 0;
+    d->info.time = time;
+    /*
+     * Add this directory to the subdirectory list of the parent
+     */
+    subdir = malloc (sizeof (FcGlobalCacheSubdir));
+    if (!subdir)
+       return 0;
+    FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir));
+    subdir->ent = d;
+    subdir->next = parent->subdirs;
+    parent->subdirs = subdir;
+    return &d->info;
+}
+
+static void
+FcGlobalCacheDirDestroy (FcGlobalCacheDir *d)
+{
+    FcGlobalCacheFile  *f, *next;
+    int                        h;
+    FcGlobalCacheSubdir        *s, *nexts;
+
+    for (h = 0; h < FC_GLOBAL_CACHE_FILE_HASH_SIZE; h++)
+       for (f = d->ents[h]; f; f = next)
+       {
+           next = f->next;
+           FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
+                      strlen ((char *) f->info.file) + 1 +
+                      strlen ((char *) f->name) + 1);
+           free (f);
+       }
+    for (s = d->subdirs; s; s = nexts)
+    {
+       nexts = s->next;
+       FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir));
+       free (s);
+    }
+    FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + d->len + 1);
+    free (d);
+}
+
+/*
+ * If the parent is in the global cache and referenced, add
+ * an entry for 'dir' to the global cache.  This is used
+ * for directories with fonts.cache files
+ */
+
+void
+FcGlobalCacheReferenceSubdir (FcGlobalCache *cache,
+                             const FcChar8 *dir)
+{
+    FcGlobalCacheInfo  *info;
+    info = FcGlobalCacheDirAdd (cache, dir, 0, FcFalse, FcFalse);
+    if (info && !info->referenced)
+    {
+       info->referenced = FcTrue;
+       cache->referenced++;
+    }
+}
+
+/*
+ * Check to see if the global cache contains valid data for 'dir'.
+ * If so, scan the global cache for files and directories in 'dir'.
+ * else, return False.
+ */
+FcBool
+FcGlobalCacheScanDir (FcFontSet                *set,
+                     FcStrSet          *dirs,
+                     FcGlobalCache     *cache,
+                     const FcChar8     *dir,
+                     FcConfig          *config)
+{
+    FcGlobalCacheDir   *d = FcGlobalCacheDirGet (cache, dir,
+                                                 strlen ((const char *) dir),
+                                                 FcFalse);
+    FcGlobalCacheFile  *f;
+    int                        h;
+    int                        dir_len;
+    FcGlobalCacheSubdir        *subdir;
+    FcBool             any_in_cache = FcFalse;
+
+    if (FcDebug() & FC_DBG_CACHE)
+       printf ("FcGlobalCacheScanDir %s\n", dir);
+    
+    if (!d)
+    {
+       if (FcDebug () & FC_DBG_CACHE)
+           printf ("\tNo dir cache entry\n");
+       return FcFalse;
+    }
+
+    /*
+     * See if the timestamp recorded in the global cache
+     * matches the directory time, if not, return False
+     */
+    if (!FcGlobalCacheCheckTime (d->info.file, &d->info))
+    {
+       if (FcDebug () & FC_DBG_CACHE)
+           printf ("\tdir cache entry time mismatch\n");
+       return FcFalse;
+    }
+
+    /*
+     * Add files from 'dir' to the fontset
+     */
+    dir_len = strlen ((const char *) dir);
+    for (h = 0; h < FC_GLOBAL_CACHE_FILE_HASH_SIZE; h++)
+       for (f = d->ents[h]; f; f = f->next)
+       {
+           if (FcDebug() & FC_DBG_CACHEV)
+               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, config))
+           {
+               cache->broken = FcTrue;
+               return FcFalse;
+           }
+           FcGlobalCacheReferenced (cache, &f->info);
+       }
+    /*
+     * Add directories in 'dir' to 'dirs'
+     */
+    for (subdir = d->subdirs; subdir; subdir = subdir->next)
+    {
+       FcFilePathInfo  info = FcFilePathInfoGet (subdir->ent->info.file);
+       
+        any_in_cache = FcTrue;
+       if (!FcCacheFontSetAdd (set, dirs, dir, dir_len,
+                               info.base, FC_FONT_FILE_DIR, config))
+       {
+           cache->broken = FcTrue;
+           return FcFalse;
+       }
+       FcGlobalCacheReferenced (cache, &subdir->ent->info);
+    }
+    
+    FcGlobalCacheReferenced (cache, &d->info);
+
+    /*
+     * To recover from a bug in previous versions of fontconfig,
+     * return FcFalse if no entries in the cache were found
+     * for this directory.  This will cause any empty directories
+     * to get rescanned every time fontconfig is initialized.  This
+     * might get removed at some point when the older cache files are
+     * presumably fixed.
+     */
+    return any_in_cache;
+}
+
+/*
+ * Locate the cache entry for a particular file
+ */
+FcGlobalCacheFile *
+FcGlobalCacheFileGet (FcGlobalCache *cache,
+                     const FcChar8 *file,
+                     int           id,
+                     int           *count)
+{
+    FcFilePathInfo     i = FcFilePathInfoGet (file);
+    FcGlobalCacheDir   *d = FcGlobalCacheDirGet (cache, i.dir, 
+                                                 i.dir_len, FcFalse);
+    FcGlobalCacheFile  *f, *match = 0;
+    int                        max = -1;
+
+    if (!d)
+       return 0;
+    for (f = d->ents[i.base_hash % FC_GLOBAL_CACHE_FILE_HASH_SIZE]; f; f = f->next)
+    {
+       if (f->info.hash == i.base_hash &&
+           !strcmp ((const char *) f->info.file, (const char *) i.base))
+       {
+           if (f->id == id)
+               match = f;
+           if (f->id > max)
+               max = f->id;
+       }
+    }
+    if (count)
+       *count = max + 1;
+    return match;
+}
+    
+/*
+ * Add a file entry to the cache
+ */
+static FcGlobalCacheInfo *
+FcGlobalCacheFileAdd (FcGlobalCache *cache,
+                     const FcChar8 *path,
+                     int           id,
+                     time_t        time,
+                     const FcChar8 *name,
+                     FcBool        replace)
+{
+    FcFilePathInfo     i = FcFilePathInfoGet (path);
+    FcGlobalCacheDir   *d = FcGlobalCacheDirGet (cache, i.dir, 
+                                                 i.dir_len, FcTrue);
+    FcGlobalCacheFile  *f, **prev;
+    int                        size;
+
+    if (!d)
+       return 0;
+    for (prev = &d->ents[i.base_hash % FC_GLOBAL_CACHE_FILE_HASH_SIZE];
+        (f = *prev);
+        prev = &(*prev)->next)
+    {
+       if (f->info.hash == i.base_hash && 
+           f->id == id &&
+           !strcmp ((const char *) f->info.file, (const char *) i.base))
+       {
+           break;
+       }
+    }
+    if (*prev)
+    {
+       if (!replace)
+           return 0;
+
+       f = *prev;
+       if (f->info.referenced)
+           cache->referenced--;
+       *prev = f->next;
+       FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
+                  strlen ((char *) f->info.file) + 1 +
+                  strlen ((char *) f->name) + 1);
+       free (f);
+    }
+    size = (sizeof (FcGlobalCacheFile) +
+           strlen ((char *) i.base) + 1 +
+           strlen ((char *) name) + 1);
+    f = malloc (size);
+    if (!f)
+       return 0;
+    FcMemAlloc (FC_MEM_CACHE, size);
+    f->next = *prev;
+    *prev = f;
+    f->info.hash = i.base_hash;
+    f->info.file = (FcChar8 *) (f + 1);
+    f->info.time = time;
+    f->info.referenced = FcFalse;
+    f->id = id;
+    f->name = f->info.file + strlen ((char *) i.base) + 1;
+    strcpy ((char *) f->info.file, (const char *) i.base);
+    strcpy ((char *) f->name, (const char *) name);
+    return &f->info;
+}
+
 FcGlobalCache *
 FcGlobalCacheCreate (void)
 {
@@ -193,6 +821,12 @@ FcGlobalCacheDestroy (FcGlobalCache *cache)
     free (cache);
 }
 
+/*
+ * Cache file syntax is quite simple:
+ *
+ * "file_name" id time "font_name" \n
+ */
 void
 FcGlobalCacheLoad (FcGlobalCache    *cache,
                   const FcChar8    *cache_file)
@@ -377,7 +1011,6 @@ bail1:
 bail0:
     return FcFalse;
 }
-#endif
 
 /* 
  * Find the next presumably-mmapable offset after the current file
@@ -422,10 +1055,10 @@ FcCacheSkipToArch (int fd, const char * arch)
        long bs;
 
        lseek (fd, current_arch_start, SEEK_SET);
-       if (FcCacheReadString (fd, candidate_arch_machine_name, 
+       if (FcCacheReadString2 (fd, candidate_arch_machine_name, 
                               sizeof (candidate_arch_machine_name)) == 0)
            break;
-       if (FcCacheReadString (fd, bytes_to_skip, 7) == 0)
+       if (FcCacheReadString2 (fd, bytes_to_skip, 7) == 0)
            break;
        bs = a64l(bytes_to_skip);
        if (bs == 0)
@@ -459,10 +1092,10 @@ FcCacheMoveDown (int fd, off_t start)
        return FcFalse;
 
     lseek (fd, start, SEEK_SET);
-    if (FcCacheReadString (fd, candidate_arch_machine_name, 
+    if (FcCacheReadString2 (fd, candidate_arch_machine_name, 
                           sizeof (candidate_arch_machine_name)) == 0)
        goto done;
-    if (FcCacheReadString (fd, bytes_to_skip, 7) == 0)
+    if (FcCacheReadString2 (fd, bytes_to_skip, 7) == 0)
        goto done;
 
     bs = a64l(bytes_to_skip);
@@ -492,8 +1125,35 @@ FcCacheMoveDown (int fd, off_t start)
     return FcFalse;
 }
 
+FcBool
+FcDirCacheValid (const FcChar8 *dir)
+{
+    FcChar8     *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+    struct stat file_stat, dir_stat;
+
+    if (stat ((char *) dir, &dir_stat) < 0)
+    {
+        FcStrFree (cache_file);
+        return FcFalse;
+    }
+    if (stat ((char *) cache_file, &file_stat) < 0)
+    {
+        FcStrFree (cache_file);
+        return FcFalse;
+    }
+    FcStrFree (cache_file);
+    /*
+     * If the directory has been modified more recently than
+     * the cache file, the cache is not valid
+     */
+    if (dir_stat.st_mtime - file_stat.st_mtime > 0)
+        return FcFalse;
+    return FcTrue;
+}
+
 static int
-FcCacheReadDirs (FcStrList *list, FcFontSet * set)
+FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache, 
+                FcStrList *list, FcFontSet * set)
 {
     DIR                        *d;
     struct dirent      *e;
@@ -577,24 +1237,16 @@ FcCacheReadDirs (FcStrList *list, FcFontSet * set)
            }
        }
        closedir (d);
-       if (1 || FcDirCacheValid (dir))
+       if (FcDirCacheValid (dir))
        {
            FcDirCacheRead (set, dir);
        }
        else
        {
-           ret++;
-#if 0 // (implement per-dir loading)
-           if (verbose)
-               printf ("caching, %d fonts, %d dirs\n", 
-                       set->nfont, nsubdirs (subdirs));
-
-           if (!FcDirSave (set, dir))
-           {
-               fprintf (stderr, "Can't save cache in \"%s\"\n", dir);
-               ret++;
-           }
-#endif
+           if (FcDebug () & FC_DBG_FONTSET)
+               printf ("scan dir %s\n", dir);
+           FcDirScanConfig (set, subdirs, cache, 
+                            config->blanks, dir, FcFalse, config);
        }
        sublist = FcStrListCreate (subdirs);
        FcStrSetDestroy (subdirs);
@@ -605,7 +1257,7 @@ FcCacheReadDirs (FcStrList *list, FcFontSet * set)
            free (file);
            continue;
        }
-       ret += FcCacheReadDirs (sublist, set);
+       ret += FcCacheReadDirs (config, cache, sublist, set);
        free (file);
     }
     FcStrListDone (list);
@@ -613,7 +1265,7 @@ FcCacheReadDirs (FcStrList *list, FcFontSet * set)
 }
 
 FcFontSet *
-FcCacheRead (FcConfig *config)
+FcCacheRead (FcConfig *config, FcGlobalCache * cache)
 {
     FcFontSet * s = FcFontSetCreate();
     if (!s) 
@@ -622,7 +1274,7 @@ FcCacheRead (FcConfig *config)
     if (force)
        goto bail;
 
-    if (FcCacheReadDirs (FcConfigGetConfigDirs (config), s))
+    if (FcCacheReadDirs (config, cache, FcConfigGetConfigDirs (config), s))
        goto bail;
 
     return s;
@@ -659,10 +1311,10 @@ FcDirCacheRead (FcFontSet * set, const FcChar8 *dir)
         goto bail1;
 
     lseek (fd, current_arch_start, SEEK_SET);
-    if (FcCacheReadString (fd, candidate_arch_machine_name, 
+    if (FcCacheReadString2 (fd, candidate_arch_machine_name, 
                           sizeof (candidate_arch_machine_name)) == 0)
        goto bail1;
-    if (FcCacheReadString (fd, bytes_in_block, 7) == 0)
+    if (FcCacheReadString2 (fd, bytes_in_block, 7) == 0)
        goto bail1;
 
     // sanity check for endianness issues
@@ -752,14 +1404,14 @@ FcDirCacheWrite (int bank, FcFontSet *set, const FcChar8 *dir)
        goto bail1;
 
     /* reserve space for arch, count & metadata */
-    if (!FcCacheWriteString (fd, current_arch_machine_name))
+    if (!FcCacheWriteString2 (fd, current_arch_machine_name))
        goto bail1;
 
     /* now write the address of the next offset */
     truncate_to = FcCacheNextOffset(current_arch_start + bytes_to_write + metadata_bytes) -
        current_arch_start;
     strcpy (bytes_written, l64a(truncate_to));
-    if (!FcCacheWriteString (fd, bytes_written))
+    if (!FcCacheWriteString2 (fd, bytes_written))
        goto bail1;
 
     metadata.magic = FC_CACHE_MAGIC;
index aaa05f56b47341ca34a3fb07eb0faaa7c1778f5f..4d2e0243a31ccb9fb42de7f6d9beb4be1b14e304 100644 (file)
@@ -252,24 +252,18 @@ FcConfigBuildFonts (FcConfig *config)
     FcStrList      *list;
     FcChar8        *dir;
 
-#if 0
-    if (config->cache)
-       FcGlobalCacheLoad (cache, config->cache);
-#endif
-    if (config->fonts[FcSetSystem])
-       return FcTrue;
-
     fonts = FcFontSetCreate ();
     if (!fonts)
        goto bail0;
-
-#if 0
+    
     cache = FcGlobalCacheCreate ();
     if (!cache)
        goto bail1;
-#endif
 
-    cached_fonts = FcCacheRead(config);
+    if (config->cache)
+       FcGlobalCacheLoad (cache, config->cache);
+
+    cached_fonts = FcCacheRead(config, cache);
     if (!cached_fonts)
     {
        list = FcConfigGetFontDirs (config);
@@ -294,18 +288,19 @@ FcConfigBuildFonts (FcConfig *config)
        {
            if (FcConfigAcceptFont (config, cached_fonts->fonts[i]))
                FcFontSetAdd (fonts, cached_fonts->fonts[i]);
+
+           cached_fonts->fonts[i] = 0; /* prevent free in FcFontSetDestroy */
        }
+       cached_fonts->nfont = 0;
        FcFontSetDestroy (cached_fonts);
     }
     
     if (FcDebug () & FC_DBG_FONTSET)
        FcFontSetPrint (fonts);
 
-#if 0
     if (config->cache)
        FcGlobalCacheSave (cache, config->cache);
     FcGlobalCacheDestroy (cache);
-#endif
 
     FcConfigSetFonts (config, fonts, FcSetSystem);
     
index 529548c20eb47e49e4a6065dc7881418872a00f1..73039f4b2832b23641cd53d5595c9e8207158c77 100644 (file)
@@ -441,6 +441,57 @@ typedef struct _FcCharMap FcCharMap;
 
 /* fccache.c */
 
+FcGlobalCache *
+FcGlobalCacheCreate (void);
+
+void
+FcGlobalCacheDestroy (FcGlobalCache *cache);
+
+FcBool
+FcGlobalCacheCheckTime (const FcChar8*file, FcGlobalCacheInfo *info);
+
+void
+FcGlobalCacheReferenced (FcGlobalCache     *cache,
+                        FcGlobalCacheInfo  *info);
+
+void
+FcGlobalCacheReferenceSubdir (FcGlobalCache *cache,
+                             const FcChar8 *dir);
+
+FcGlobalCacheDir *
+FcGlobalCacheDirGet (FcGlobalCache  *cache,
+                    const FcChar8  *dir,
+                    int            len,
+                    FcBool         create_missing);
+
+FcBool
+FcGlobalCacheScanDir (FcFontSet                *set,
+                     FcStrSet          *dirs,
+                     FcGlobalCache     *cache,
+                     const FcChar8     *dir,
+                     FcConfig          *config);
+
+FcGlobalCacheFile *
+FcGlobalCacheFileGet (FcGlobalCache *cache,
+                     const FcChar8 *file,
+                     int           id,
+                     int           *count);
+
+
+void
+FcGlobalCacheLoad (FcGlobalCache    *cache,
+                  const FcChar8    *cache_file);
+
+FcBool
+FcGlobalCacheUpdate (FcGlobalCache  *cache,
+                    const FcChar8  *file,
+                    int            id,
+                    const FcChar8  *name);
+
+FcBool
+FcGlobalCacheSave (FcGlobalCache    *cache,
+                  const FcChar8    *cache_file);
+
 void
 FcCacheForce(FcBool force);
 
@@ -448,7 +499,7 @@ FcBool
 FcCacheSerialize (int bank, FcConfig * config);
 
 FcFontSet *
-FcCacheRead (FcConfig *config);
+FcCacheRead (FcConfig *config, FcGlobalCache * cache);
 
 FcBool
 FcDirCacheRead (FcFontSet * set, const FcChar8 *dir);