]> git.wh0rd.org - fontconfig.git/commitdiff
Pass directory information around in FcCache structure. Freeze charsets.
authorKeith Packard <keithp@neko.keithp.com>
Fri, 1 Sep 2006 08:15:14 +0000 (01:15 -0700)
committerKeith Packard <keithp@neko.keithp.com>
Fri, 1 Sep 2006 08:15:14 +0000 (01:15 -0700)
Instead of passing directory information around in separate variables,
collect it all in an FcCache structure. Numerous internal and tool
interfaces changed as a result of this.

Charsets are now pre-frozen before being serialized. This causes them to
share across multiple fonts in the same cache.

fc-cache/fc-cache.c
fc-cat/fc-cat.c
fc-glyphname/fc-glyphname.c
src/fccache.c
src/fccfg.c
src/fccharset.c
src/fcdir.c
src/fcinit.c
src/fcint.h
src/fcpat.c
src/fcserialize.c

index 5fc409200b88c46cf1c185600bd0138bd6e566b3..6957a65b9ba8d28b685dc12f6f94b7f3ee0c8b60 100644 (file)
@@ -128,15 +128,17 @@ nsubdirs (FcStrSet *set)
 }
 
 static int
-scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool really_force, FcBool verbose)
+scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose)
 {
     int                ret = 0;
     const FcChar8 *dir;
     FcFontSet  *set;
     FcStrSet   *subdirs;
     FcStrList  *sublist;
+    FcCache    *cache;
     struct stat        statb;
     FcBool     was_valid;
+    int                i;
     
     /*
      * Now scan all of the directories into separate databases
@@ -146,7 +148,7 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
     {
        if (verbose)
        {
-           printf ("%s: \"%s\": ", program, dir);
+           printf ("%s: ", dir);
            fflush (stdout);
        }
        
@@ -164,22 +166,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
            continue;
        }
 
-       set = FcFontSetCreate ();
-       if (!set)
-       {
-           fprintf (stderr, "%s: Can't create font set\n", dir);
-           ret++;
-           continue;
-       }
-       subdirs = FcStrSetCreate ();
-       if (!subdirs)
-       {
-           fprintf (stderr, "%s: Can't create directory set\n", dir);
-           ret++;
-           FcFontSetDestroy (set);
-           continue;
-       }
-       
        if (access ((char *) dir, W_OK) < 0)
        {
            switch (errno) {
@@ -187,8 +173,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
            case ENOTDIR:
                if (verbose)
                    printf ("skipping, no such directory\n");
-               FcFontSetDestroy (set);
-               FcStrSetDestroy (subdirs);
                continue;
            case EACCES:
            case EROFS:
@@ -201,8 +185,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
                perror ("");
                ret++;
 
-               FcFontSetDestroy (set);
-               FcStrSetDestroy (subdirs);
                continue;
            }
        }
@@ -210,44 +192,50 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
        {
            fprintf (stderr, "\"%s\": ", dir);
            perror ("");
-           FcFontSetDestroy (set);
-           FcStrSetDestroy (subdirs);
            ret++;
            continue;
        }
        if (!S_ISDIR (statb.st_mode))
        {
            fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
-           FcFontSetDestroy (set);
-           FcStrSetDestroy (subdirs);
            continue;
        }
 
        if (really_force)
            FcDirCacheUnlink (dir, config);
 
-       if (!force)
-           was_valid = FcDirCacheValid (dir);
+       cache = NULL;
+       was_valid = FcFalse;
+       if (!force) {
+           cache = FcDirCacheLoad (dir, config, NULL);
+           if (cache)
+               was_valid = FcTrue;
+       }
        
-       if (!FcDirScanConfig (set, subdirs, FcConfigGetBlanks (config), dir, force, config))
+       if (!cache)
        {
-           fprintf (stderr, "%s: error scanning\n", dir);
-           FcFontSetDestroy (set);
-           FcStrSetDestroy (subdirs);
-           ret++;
-           continue;
+           cache = FcDirCacheRead (dir, FcTrue, config);
+           if (!cache)
+           {
+               fprintf (stderr, "%s: error scanning\n", dir);
+               ret++;
+               continue;
+           }
        }
-       if (!force && was_valid)
+
+       set = FcCacheSet (cache);
+
+       if (was_valid)
        {
            if (verbose)
                printf ("skipping, %d fonts, %d dirs\n",
-                       set->nfont, nsubdirs(subdirs));
+                       set->nfont, cache->dirs_count);
        }
        else
        {
            if (verbose)
                printf ("caching, %d fonts, %d dirs\n", 
-                       set->nfont, nsubdirs (subdirs));
+                       set->nfont, cache->dirs_count);
 
            if (!FcDirCacheValid (dir))
            {
@@ -256,43 +244,36 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
                ret++;
            }
        }
-       FcFontSetDestroy (set);
+       
+       subdirs = FcStrSetCreate ();
+       if (!subdirs)
+       {
+           fprintf (stderr, "%s: Can't create subdir set\n", dir);
+           ret++;
+           FcDirCacheUnload (cache);
+           continue;
+       }
+       for (i = 0; i < cache->dirs_count; i++)
+           FcStrSetAdd (subdirs, FcCacheSubdir (cache, i));
+       
+       FcDirCacheUnload (cache);
+       
        sublist = FcStrListCreate (subdirs);
        FcStrSetDestroy (subdirs);
        if (!sublist)
        {
            fprintf (stderr, "%s: Can't create subdir list\n", dir);
            ret++;
+           FcDirCacheUnload (cache);
            continue;
        }
        FcStrSetAdd (processed_dirs, dir);
-       ret += scanDirs (sublist, config, program, force, really_force, verbose);
+       ret += scanDirs (sublist, config, force, really_force, verbose);
     }
     FcStrListDone (list);
     return ret;
 }
 
-FcCache *
-FcCacheFileMap (const FcChar8 *file, struct stat *file_stat)
-{
-    FcCache *cache;
-    int            fd;
-
-    fd = open (file, O_RDONLY | O_BINARY);
-    if (fd < 0)
-       return NULL;
-    if (fstat (fd, file_stat) < 0) {
-       close (fd);
-       return NULL;
-    }
-    if (FcDirCacheLoad (fd, file_stat->st_size, &cache)) {
-       close (fd);
-       return cache;
-    }
-    close (fd);
-    return NULL;
-}
-
 static FcBool
 cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
 {
@@ -309,9 +290,11 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
     if (access ((char *) dir, W_OK|X_OK) != 0)
     {
        if (verbose)
-           printf ("%s: skipping unwritable cache directory\n", dir);
+           printf ("%s: not cleaning unwritable cache directory\n", dir);
        return FcTrue;
     }
+    if (verbose)
+       printf ("%s: cleaning cache directory\n", dir);
     d = opendir (dir);
     if (!d)
     {
@@ -332,7 +315,7 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
            ret = FcFalse;
            break;
        }
-       cache = FcCacheFileMap (file_name, &file_stat);
+       cache = FcDirCacheLoadFile (file_name, &file_stat);
        if (!cache)
        {
            fprintf (stderr, "%s: invalid cache file: %s\n", dir, ent->d_name);
@@ -478,7 +461,7 @@ main (int argc, char **argv)
        return 1;
     }
        
-    ret = scanDirs (list, config, argv[0], force, really_force, verbose);
+    ret = scanDirs (list, config, force, really_force, verbose);
 
     FcStrSetDestroy (processed_dirs);
 
index 6074f1d92f1fe81670fa15e877979dccb82fb1fc..71b416f1222365c988b55dbecb482a36a30089c6 100644 (file)
@@ -81,7 +81,7 @@ extern int optind, opterr, optopt;
 #endif
 
 static FcBool
-FcCacheWriteChars (FILE *f, const FcChar8 *chars)
+write_chars (FILE *f, const FcChar8 *chars)
 {
     FcChar8    c;
     while ((c = *chars++))
@@ -101,7 +101,7 @@ FcCacheWriteChars (FILE *f, const FcChar8 *chars)
 }
 
 static FcBool
-FcCacheWriteUlong (FILE *f, unsigned long t)
+write_ulong (FILE *f, unsigned long t)
 {
     int            pow;
     unsigned long   temp, digit;
@@ -126,18 +126,18 @@ FcCacheWriteUlong (FILE *f, unsigned long t)
 }
 
 static FcBool
-FcCacheWriteInt (FILE *f, int i)
+write_int (FILE *f, int i)
 {
-    return FcCacheWriteUlong (f, (unsigned long) i);
+    return write_ulong (f, (unsigned long) i);
 }
 
 static FcBool
-FcCacheWriteStringOld (FILE *f, const FcChar8 *string)
+write_string (FILE *f, const FcChar8 *string)
 {
 
     if (PUTC ('"', f) == EOF)
        return FcFalse;
-    if (!FcCacheWriteChars (f, string))
+    if (!write_chars (f, string))
        return FcFalse;
     if (PUTC ('"', f) == EOF)
        return FcFalse;
@@ -168,30 +168,12 @@ usage (char *program)
     exit (1);
 }
 
-static int
-FcCacheFileOpen (char *cache_file, off_t *size)
-{
-    int fd;
-    struct stat file_stat;
-
-    fd = open(cache_file, O_RDONLY | O_BINARY);
-    if (fd < 0)
-        return -1;
-
-    if (fstat (fd, &file_stat) < 0) {
-       close (fd); 
-       return -1;
-    }
-    *size = file_stat.st_size;
-    return fd;
-}
-
 /*
  * return the path from the directory containing 'cache' to 'file'
  */
 
 static const FcChar8 *
-FcFileBaseName (const char *cache, const FcChar8 *file)
+file_base_name (const char *cache, const FcChar8 *file)
 {
     const FcChar8   *cache_slash;
     int                    cache_len = strlen (cache);
@@ -201,8 +183,8 @@ FcFileBaseName (const char *cache, const FcChar8 *file)
     return file;
 }
 
-FcBool
-FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose)
+static FcBool
+cache_print_set (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose)
 {
     FcPattern      *font;
     FcChar8        *name, *dir;
@@ -219,16 +201,16 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose
     
     while ((dir = FcStrListNext (list)))
     {
-       base = FcFileBaseName (base_name, dir);
-       if (!FcCacheWriteStringOld (stdout, base))
+       base = file_base_name (base_name, dir);
+       if (!write_string (stdout, base))
            goto bail3;
        if (PUTC (' ', stdout) == EOF)
            goto bail3;
-       if (!FcCacheWriteInt (stdout, 0))
+       if (!write_int (stdout, 0))
            goto bail3;
         if (PUTC (' ', stdout) == EOF)
            goto bail3;
-       if (!FcCacheWriteStringOld (stdout, FC_FONT_FILE_DIR))
+       if (!write_string (stdout, FC_FONT_FILE_DIR))
            goto bail3;
        if (PUTC ('\n', stdout) == EOF)
            goto bail3;
@@ -243,21 +225,21 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose
 
        if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
            goto bail3;
-       base = FcFileBaseName (base_name, file);
+       base = file_base_name (base_name, file);
        if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
            goto bail3;
-       if (!FcCacheWriteStringOld (stdout, base))
+       if (!write_string (stdout, base))
            goto bail3;
        if (PUTC (' ', stdout) == EOF)
            goto bail3;
-       if (!FcCacheWriteInt (stdout, id))
+       if (!write_int (stdout, id))
            goto bail3;
         if (PUTC (' ', stdout) == EOF)
            goto bail3;
        name = FcNameUnparse (font);
        if (!name)
            goto bail3;
-       ret = FcCacheWriteStringOld (stdout, name);
+       ret = write_string (stdout, name);
        FcStrFree (name);
        if (!ret)
            goto bail3;
@@ -277,28 +259,6 @@ bail2:
     return FcFalse;
 }
 
-FcCache *
-FcCacheFileMap (const FcChar8 *file)
-{
-    FcCache *cache;
-    int            fd;
-    struct stat file_stat;
-
-    fd = open (file, O_RDONLY | O_BINARY);
-    if (fd < 0)
-       return NULL;
-    if (fstat (fd, &file_stat) < 0) {
-       close (fd);
-       return NULL;
-    }
-    if (!FcDirCacheLoad (fd, file_stat.st_size, &cache)) {
-       close (fd);
-       return NULL;
-    }
-    close (fd);
-    return cache;
-}
-
 int
 main (int argc, char **argv)
 {
@@ -399,11 +359,12 @@ main (int argc, char **argv)
        off_t       size;
        intptr_t    *cache_dirs;
        FcChar8     *cache_file = NULL;
+       struct stat file_stat;
        
        if (FcFileIsDir (arg))
-           cache = FcDirCacheMap (arg, config, &cache_file);
+           cache = FcDirCacheLoad (arg, config, &cache_file);
        else
-           cache = FcCacheFileMap (arg);
+           cache = FcDirCacheLoadFile (arg, &file_stat);
        if (!cache)
        {
            perror ((char *) arg);
@@ -433,11 +394,11 @@ main (int argc, char **argv)
                    FcCacheDir(cache), cache_file ? cache_file : arg);
            first = FcFalse;
        }
-        FcCachePrintSet (fs, dirs, FcCacheDir (cache), verbose);
+        cache_print_set (fs, dirs, FcCacheDir (cache), verbose);
 
        FcStrSetDestroy (dirs);
 
-       FcDirCacheUnmap (cache);
+       FcDirCacheUnload (cache);
        if (cache_file)
            FcStrFree (cache_file);
     }
index 8b265e4ea0106e7661ed63868edd78ebe8f9b9e9..faaa63b47c0f1cf9f62efc23cfab46f029824fb4 100644 (file)
 
 #include "fcint.h"
 
-/* stub definitions for declarations from fcint.h.. */
-int * _fcBankId = 0, * _fcBankIdx = 0;
-FcValueList ** _fcValueLists = 0;
-FcPatternElt ** _fcPatternElts = 0;
-int FcDebugVal = 0;
-
-int
-FcCacheBankToIndexMTF (int bank)
-{
-    return 0;
-}
-/* end stub definitions */
-
 static int
 rawindex (const FcGlyphName *gn);
 
index dd0896bd833e67e0e2753df6921e873b39f2e05c..af2c68fa88ebcd3348db24f9b270fc985edd7c5a 100644 (file)
@@ -112,81 +112,19 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
 }
 
 static int
-FcCacheReadDirs (FcConfig * config,
-                FcStrList *list, FcFontSet * set, FcStrSet *processed_dirs)
+FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
 {
-    int                        ret = 0;
-    FcChar8            *dir;
-    FcStrSet           *subdirs;
-    FcStrList          *sublist;
+    int        fd;
 
-    /*
-     * Read in the results from 'list'.
-     */
-    while ((dir = FcStrListNext (list)))
+    fd = open((char *) cache_file, O_RDONLY | O_BINARY);
+    if (fd < 0)
+       return fd;
+    if (fstat (fd, file_stat) < 0)
     {
-       if (!FcConfigAcceptFilename (config, dir))
-           continue;
-
-       /* Skip this directory if already updated
-        * to avoid the looped directories via symlinks
-        * Clearly a dir not in fonts.conf shouldn't be globally cached.
-        */
-
-       if (FcStrSetMember (processed_dirs, dir))
-           continue;
-       if (!FcStrSetAdd (processed_dirs, dir))
-           continue;
-
-       subdirs = FcStrSetCreate ();
-       if (!subdirs)
-       {
-           fprintf (stderr, "Can't create directory set\n");
-           ret++;
-           continue;
-       }
-       
-       FcDirScanConfig (set, subdirs,
-                        config->blanks, dir, FcFalse, config);
-       
-       sublist = FcStrListCreate (subdirs);
-       FcStrSetDestroy (subdirs);
-       if (!sublist)
-       {
-           fprintf (stderr, "Can't create subdir list in \"%s\"\n", dir);
-           ret++;
-           continue;
-       }
-       ret += FcCacheReadDirs (config, sublist, set, processed_dirs);
+       close (fd);
+       return -1;
     }
-    FcStrListDone (list);
-    return ret;
-}
-
-FcFontSet *
-FcCacheRead (FcConfig *config)
-{
-    FcFontSet  *s = FcFontSetCreate();
-    FcStrSet   *processed_dirs;
-
-    if (!s) 
-       return 0;
-
-    processed_dirs = FcStrSetCreate();
-    if (!processed_dirs)
-       goto bail;
-
-    if (FcCacheReadDirs (config, FcConfigGetConfigDirs (config), s, processed_dirs))
-       goto bail1;
-
-    FcStrSetDestroy (processed_dirs);
-    return s;
-
- bail1:
-    FcStrSetDestroy (processed_dirs);
- bail:
-    FcFontSetDestroy (s);
-    return 0;
+    return fd;
 }
 
 /* 
@@ -220,10 +158,9 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
         FcChar8        *cache_hashed = FcStrPlus (cache_dir, cache_base);
         if (!cache_hashed)
            break;
-        fd = open((char *) cache_hashed, O_RDONLY | O_BINARY);
+        fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
         if (fd >= 0) {
-           if (fstat (fd, &file_stat) >= 0 &&
-               dir_stat.st_mtime <= file_stat.st_mtime)
+           if (dir_stat.st_mtime <= file_stat.st_mtime)
            {
                ret = (*callback) (fd, file_stat.st_size, closure);
                if (ret)
@@ -245,44 +182,56 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
     return ret;
 }
 
-FcBool
-FcDirCacheLoad (int fd, off_t size, void *closure)
+#define FC_CACHE_MIN_MMAP   1024
+
+/*
+ * Map a cache file into memory
+ */
+static FcCache *
+FcDirCacheMapFd (int fd, off_t size)
 {
-    FcCache    *cache;
+    FcCache    *cache = NULL;
     FcBool     allocated = FcFalse;
 
     if (size < sizeof (FcCache))
-       return FcFalse;
+       return NULL;
+    /*
+     * For small cache files, just read them into memory
+     */
+    if (size >= FC_CACHE_MIN_MMAP)
+    {
 #if defined(HAVE_MMAP) || defined(__CYGWIN__)
-    cache = mmap (0, size, PROT_READ, MAP_SHARED, fd, 0);
+       cache = mmap (0, size, PROT_READ, MAP_SHARED, fd, 0);
 #elif defined(_WIN32)
-    {
-       HANDLE hFileMap;
-
-       cache = NULL;
-       hFileMap = CreateFileMapping((HANDLE) _get_osfhandle(fd), NULL,
-                                    PAGE_READONLY, 0, 0, NULL);
-       if (hFileMap != NULL)
        {
-           cache = MapViewOfFile (hFileMap, FILE_MAP_READ, 0, 0, size);
-           CloseHandle (hFileMap);
+           HANDLE hFileMap;
+
+           cache = NULL;
+           hFileMap = CreateFileMapping((HANDLE) _get_osfhandle(fd), NULL,
+                                        PAGE_READONLY, 0, 0, NULL);
+           if (hFileMap != NULL)
+           {
+               cache = MapViewOfFile (hFileMap, FILE_MAP_READ, 0, 0, size);
+               CloseHandle (hFileMap);
+           }
        }
-    }
 #endif
+    }
     if (!cache)
     {
        cache = malloc (size);
        if (!cache)
-           return FcFalse;
+           return NULL;
 
        if (read (fd, cache, size) != size)
        {
            free (cache);
-           return FcFalse;
+           return NULL;
        }
        allocated = FcTrue;
     } 
-    if (cache->magic != FC_CACHE_MAGIC ||
+    if (cache->magic != FC_CACHE_MAGIC_MMAP || 
+       cache->version != FC_CACHE_CONTENT_VERSION ||
        cache->size != size)
     {
        if (allocated)
@@ -295,74 +244,76 @@ FcDirCacheLoad (int fd, off_t size, void *closure)
            UnmapViewOfFile (cache);
 #endif
        }
-       return FcFalse;
+       return NULL;
     }
 
     /* Mark allocated caches so they're freed rather than unmapped */
     if (allocated)
-       cache->magic = FC_CACHE_MAGIC_COPY;
+       cache->magic = FC_CACHE_MAGIC_ALLOC;
        
+    return cache;
+}
+
+void
+FcDirCacheUnload (FcCache *cache)
+{
+    switch (cache->magic) {
+    case FC_CACHE_MAGIC_ALLOC:
+       free (cache);
+       break;
+    case FC_CACHE_MAGIC_MMAP:
+#if defined(HAVE_MMAP) || defined(__CYGWIN__)
+       munmap (cache, cache->size);
+#elif defined(_WIN32)
+       UnmapViewOfFile (cache);
+#endif
+       break;
+    }
+}
+
+static FcBool
+FcDirCacheMapHelper (int fd, off_t size, void *closure)
+{
+    FcCache *cache = FcDirCacheMapFd (fd, size);
+
+    if (!cache)
+       return FcFalse;
     *((FcCache **) closure) = cache;
     return FcTrue;
 }
 
 FcCache *
-FcDirCacheMap (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
+FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
 {
     FcCache *cache = NULL;
 
     if (!FcDirCacheProcess (config, dir,
-                           FcDirCacheLoad,
+                           FcDirCacheMapHelper,
                            &cache, cache_file))
        return NULL;
     return cache;
 }
 
-FcBool
-FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, 
-               const FcChar8 *dir, FcConfig *config)
+FcCache *
+FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
 {
-    FcCache    *cache;
-    int                i;
-    FcFontSet  *cache_set;
-    intptr_t   *cache_dirs;
-    FcPattern   **cache_fonts;
+    int        fd;
+    FcCache *cache;
 
-    cache = FcDirCacheMap (dir, config, NULL);
-    if (!cache)
-       return FcFalse;
-    
-    cache_set = FcCacheSet (cache);
-    cache_fonts = FcFontSetFonts(cache_set);
-    if (FcDebug() & FC_DBG_CACHE)
-        printf ("FcDirCacheRead mapped cache for %s (%d fonts %d subdirs)\n",
-               dir, cache_set->nfont, cache->dirs_count);
-    for (i = 0; i < cache_set->nfont; i++)
-    {
-       FcPattern   *font = FcEncodedOffsetToPtr (cache_set,
-                                                 cache_fonts[i],
-                                                 FcPattern);
-       if (FcDebug() & FC_DBG_CACHEV) {
-           printf ("Mapped font %d\n", i);
-           FcPatternPrint (font);
-       }
-       FcFontSetAdd (set, font);
-    }
-    
-    cache_dirs = FcCacheDirs (cache);
-    for (i = 0; i < cache->dirs_count; i++) 
-       FcStrSetAdd (dirs, FcOffsetToPtr (cache_dirs,
-                                         cache_dirs[i],
-                                         FcChar8));
-        
-    if (config)
-       FcConfigAddFontDir (config, (FcChar8 *)dir);
-    
-    return FcTrue;
+    fd = FcDirCacheOpenFile (cache_file, file_stat);
+    if (fd < 0)
+       return NULL;
+    cache = FcDirCacheMapFd (fd, file_stat->st_size);
+    close (fd);
+    return cache;
 }
-    
+
+/*
+ * Validate a cache file by reading the header and checking
+ * the magic number and the size field
+ */
 static FcBool
-FcDirCacheValidate (int fd, off_t size, void *closure)
+FcDirCacheValidateHelper (int fd, off_t size, void *closure)
 {
     FcBool  ret = FcTrue;
     FcCache    c;
@@ -370,9 +321,11 @@ FcDirCacheValidate (int fd, off_t size, void *closure)
     
     if (read (fd, &c, sizeof (FcCache)) != sizeof (FcCache))
        ret = FcFalse;
-    else if (fstat (fd, &file_stat) < 0)
+    else if (c.magic != FC_CACHE_MAGIC_MMAP)
+       ret = FcFalse;
+    else if (c.version != FC_CACHE_CONTENT_VERSION)
        ret = FcFalse;
-    else if (c.magic != FC_CACHE_MAGIC)
+    else if (fstat (fd, &file_stat) < 0)
        ret = FcFalse;
     else if (file_stat.st_size != c.size)
        ret = FcFalse;
@@ -382,7 +335,9 @@ FcDirCacheValidate (int fd, off_t size, void *closure)
 static FcBool
 FcDirCacheValidConfig (const FcChar8 *dir, FcConfig *config)
 {
-    return FcDirCacheProcess (config, dir, FcDirCacheValidate, NULL, NULL);
+    return FcDirCacheProcess (config, dir, 
+                             FcDirCacheValidateHelper,
+                             NULL, NULL);
 }
 
 FcBool
@@ -397,32 +352,11 @@ FcDirCacheValid (const FcChar8 *dir)
     return FcDirCacheValidConfig (dir, config);
 }
 
-void
-FcDirCacheUnmap (FcCache *cache)
-{
-    if (cache->magic == FC_CACHE_MAGIC_COPY)
-    {
-       free (cache);
-       return;
-    }
-#if defined(HAVE_MMAP) || defined(__CYGWIN__)
-    munmap (cache, cache->size);
-#elif defined(_WIN32)
-    UnmapViewOfFile (cache);
-#endif
-}
-
 /*
- * Cache file is:
- *
- * FcCache
- * dir name
- * subdirs
- * FcFontSet
+ * Build a cache structure from the given contents
  */
-
-static FcCache *
-FcDirCacheProduce (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
+FcCache *
+FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
 {
     FcSerialize        *serialize = FcSerializeCreate ();
     FcCache *cache;
@@ -467,7 +401,8 @@ FcDirCacheProduce (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
 
     serialize->linear = cache;
 
-    cache->magic = FC_CACHE_MAGIC;
+    cache->magic = FC_CACHE_MAGIC_ALLOC;
+    cache->version = FC_CACHE_CONTENT_VERSION;
     cache->size = serialize->size;
 
     /*
@@ -537,16 +472,18 @@ FcMakeDirectory (const FcChar8 *dir)
 
 /* write serialized state to the cache file */
 FcBool
-FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *config)
+FcDirCacheWrite (FcCache *cache, FcConfig *config)
 {
+    FcChar8        *dir = FcCacheDir (cache);
     FcChar8        cache_base[CACHEBASE_LEN];
     FcChar8        *cache_hashed;
     int            fd;
     FcAtomic       *atomic;
-    FcCache        *cache;
     FcStrList      *list;
     FcChar8        *cache_dir = NULL;
     FcChar8        *test_dir;
+    int                    magic;
+    int                    written;
 
     /*
      * Write it to the first directory in the list which is writable
@@ -584,18 +521,13 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *c
     if (!cache_hashed)
         return FcFalse;
 
-    cache = FcDirCacheProduce (set, dir, dirs);
-
-    if (!cache)
-       goto bail1;
-
     if (FcDebug () & FC_DBG_CACHE)
         printf ("FcDirCacheWriteDir dir \"%s\" file \"%s\"\n",
                dir, cache_hashed);
 
     atomic = FcAtomicCreate ((FcChar8 *)cache_hashed);
     if (!atomic)
-       goto bail2;
+       goto bail1;
 
     if (!FcAtomicLock (atomic))
        goto bail3;
@@ -604,7 +536,21 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *c
     if (fd == -1)
        goto bail4;
     
-    if (write (fd, cache, cache->size) != cache->size)
+    /* Temporarily switch magic to MMAP while writing to file */
+    magic = cache->magic;
+    if (magic != FC_CACHE_MAGIC_MMAP)
+       cache->magic = FC_CACHE_MAGIC_MMAP;
+    
+    /*
+     * Write cache contents to file
+     */
+    written = write (fd, cache, cache->size);
+    
+    /* Switch magic back */
+    if (magic != FC_CACHE_MAGIC_MMAP)
+       cache->magic = magic;
+    
+    if (written != cache->size)
     {
        perror ("write cache");
        goto bail5;
@@ -613,7 +559,7 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *c
     close(fd);
     if (!FcAtomicReplaceOrig(atomic))
         goto bail4;
-    FcStrFree ((FcChar8 *)cache_hashed);
+    FcStrFree (cache_hashed);
     FcAtomicUnlock (atomic);
     FcAtomicDestroy (atomic);
     return FcTrue;
@@ -624,10 +570,8 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *c
     FcAtomicUnlock (atomic);
  bail3:
     FcAtomicDestroy (atomic);
- bail2:
-    free (cache);
  bail1:
-    FcStrFree ((FcChar8 *)cache_hashed);
+    FcStrFree (cache_hashed);
     return FcFalse;
 }
 
index bcc3bd28d5525839c600b574beace725967648b9..cec0e4a795b2d6b82ce0989a6b0b1cff4e20ad98 100644 (file)
@@ -222,7 +222,7 @@ FcConfigDestroy (FcConfig *config)
     for (cl = config->caches; cl; cl = cl_next)
     {
        cl_next = cl->next;
-       FcDirCacheUnmap (cl->cache);
+       FcDirCacheUnload (cl->cache);
        free (cl);
     }
 
@@ -231,86 +231,120 @@ FcConfigDestroy (FcConfig *config)
 }
 
 /*
- * 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
+ * Add cache to configuration, adding fonts and directories
  */
 
 FcBool
-FcConfigBuildFonts (FcConfig *config)
+FcConfigAddCache (FcConfig *config, FcCache *cache)
 {
-    FcFontSet      *fonts, *cached_fonts;
-    FcStrList      *list;
-    FcStrSet       *oldDirs;
-    FcChar8        *dir;
+    FcCacheList        *cl = malloc (sizeof (FcCacheList));
+    FcFontSet  *fs;
+    intptr_t   *dirs;
+    int                i;
 
-    fonts = FcFontSetCreate ();
-    if (!fonts)
-       goto bail0;
-    
-    oldDirs = FcStrSetCreate ();
-    if (!oldDirs)
-        goto bail2;
+    /*
+     * Add to cache list
+     */
+    if (!cl)
+       return FcFalse;
+    cl->cache = cache;
+    cl->next = config->caches;
+    config->caches = cl;
 
-    cached_fonts = FcCacheRead(config);
-    if (!cached_fonts)
+    /*
+     * Add fonts
+     */
+    fs = FcCacheSet (cache);
+    if (fs)
     {
-       list = FcConfigGetFontDirs (config);
-       if (!list)
-           goto bail3;
-       
-       while ((dir = FcStrListNext (list)))
+       for (i = 0; i < fs->nfont; i++)
        {
-           if (FcDebug () & FC_DBG_FONTSET)
-               printf ("build scan dir %s\n", dir);
-           FcDirScanConfig (fonts, config->fontDirs,
-                            config->blanks, dir, FcFalse, config);
+           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;
+               
+           FcFontSetAdd (config->fonts[FcSetSystem], font);
        }
-       
-       FcStrListDone (list);
     }
-    else
+
+    /*
+     * Add directories
+     */
+    dirs = FcCacheDirs (cache);
+    if (dirs)
     {
-       int i;
-
-        for (i = 0; i < oldDirs->num; i++)
-        {
-           if (FcDebug () & FC_DBG_FONTSET)
-               printf ("scan dir %s\n", oldDirs->strs[i]);
-           FcDirScanConfig (fonts, config->fontDirs,
-                            config->blanks, oldDirs->strs[i], 
-                             FcFalse, config);
+       for (i = 0; i < cache->dirs_count; i++)
+       {
+           FcChar8     *dir = FcOffsetToPtr (dirs, dirs[i], FcChar8);
+           if (FcConfigAcceptFilename (config, dir))
+               FcConfigAddFontDir (config, dir);
        }
+    }
+    return FcTrue;
+}
 
-       for (i = 0; i < cached_fonts->nfont; i++)
-       {
-           FcChar8     *cfn; 
-           FcPattern   *font = cached_fonts->fonts[i];
-           FcPatternObjectGetString (font, FC_FILE_OBJECT, 0, &cfn);
+/*
+ * Scan the current list of directories in the configuration
+ * and build the set of available fonts.
+ */
 
-           if (FcConfigAcceptFont (config, font) &&
-                (cfn && FcConfigAcceptFilename (config, cfn)))
-               FcFontSetAdd (fonts, font);
+FcBool
+FcConfigBuildFonts (FcConfig *config)
+{
+    FcFontSet      *fonts;
+    FcStrList      *dirlist;
+    FcChar8        *dir;
+    FcCache        *cache;
 
-           cached_fonts->fonts[i] = 0; /* prevent free in FcFontSetDestroy */
-       }
-       cached_fonts->nfont = 0;
-       FcFontSetDestroy (cached_fonts);
+    if (!config)
+    {
+       config = FcConfigGetCurrent ();
+       if (!config)
+           return FcFalse;
     }
+       
+    fonts = FcFontSetCreate ();
+    if (!fonts)
+       goto bail;
+    
+    FcConfigSetFonts (config, fonts, FcSetSystem);
+    
+    dirlist = FcStrListCreate (config->fontDirs);
+    if (!dirlist)
+        goto bail;
+       
+    while ((dir = FcStrListNext (dirlist)))
+    {
+       if (FcDebug () & FC_DBG_FONTSET)
+           printf ("adding fonts from%s\n", dir);
+       cache = FcDirCacheRead (dir, FcFalse, config);
+       if (!cache)
+           continue;
+       FcConfigAddCache (config, cache);
+    }
+    
+    FcStrListDone (dirlist);
     
     if (FcDebug () & FC_DBG_FONTSET)
        FcFontSetPrint (fonts);
 
-    FcStrSetDestroy (oldDirs);
-
-    FcConfigSetFonts (config, fonts, FcSetSystem);
-    
     return FcTrue;
-bail3:
-    FcStrSetDestroy (oldDirs);
-bail2:
-    FcFontSetDestroy (fonts);
-bail0:
+bail:
     return FcFalse;
 }
 
@@ -457,19 +491,6 @@ FcConfigSetFonts (FcConfig *config,
     config->fonts[set] = fonts;
 }
 
-FcBool
-FcConfigAddCache (FcConfig *config, FcCache *cache)
-{
-    FcCacheList        *cl = malloc (sizeof (FcCacheList));
-
-    if (!cl)
-       return FcFalse;
-    cl->cache = cache;
-    cl->next = config->caches;
-    config->caches = cl;
-    return FcTrue;
-}
-
 FcBlanks *
 FcConfigGetBlanks (FcConfig    *config)
 {
@@ -1750,7 +1771,7 @@ FcConfigAppFontAddFile (FcConfig    *config,
        FcConfigSetFonts (config, set, FcSetApplication);
     }
        
-    if (!FcFileScanConfig (set, subdirs, config->blanks, file, FcFalse, config))
+    if (!FcFileScanConfig (set, subdirs, config->blanks, file, config))
     {
        FcStrSetDestroy (subdirs);
        return FcFalse;
index 3a93c4a96cec00723e6a696a817f3530a2803507..43aa22c46d873ccc55288047a222db1dba07bd3d 100644 (file)
@@ -27,8 +27,6 @@
 
 /* #define CHECK */
 
-/* #define CHATTY */
-
 FcCharSet *
 FcCharSetCreate (void)
 {
@@ -40,8 +38,8 @@ FcCharSetCreate (void)
     FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
     fcs->ref = 1;
     fcs->num = 0;
-    fcs->leaves_offset = FcPtrToOffset (fcs, NULL);
-    fcs->numbers_offset = FcPtrToOffset (fcs, NULL);
+    fcs->leaves_offset = 0;
+    fcs->numbers_offset = 0;
     return fcs;
 }
 
@@ -68,12 +66,12 @@ FcCharSetDestroy (FcCharSet *fcs)
        FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
        free (FcCharSetLeaf (fcs, i));
     }
-    if (FcCharSetLeaves (fcs))
+    if (fcs->num)
     {
        FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (intptr_t));
        free (FcCharSetLeaves (fcs));
     }
-    if (FcCharSetNumbers (fcs))
+    if (fcs->num)
     {
        FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
        free (FcCharSetNumbers (fcs));
@@ -136,7 +134,7 @@ FcCharSetPutLeaf (FcCharSet *fcs,
     ucs4 >>= 8;
     if (ucs4 >= 0x10000)
        return FcFalse;
-    if (!leaves)
+    if (!fcs->num)
        leaves = malloc (sizeof (*leaves));
     else
     {
@@ -161,7 +159,7 @@ FcCharSetPutLeaf (FcCharSet *fcs,
     FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (intptr_t));
     fcs->leaves_offset = FcPtrToOffset (fcs, leaves);
     
-    if (!numbers)
+    if (!fcs->num)
        numbers = malloc (sizeof (FcChar16));
     else
        numbers = realloc (numbers, (fcs->num + 1) * sizeof (FcChar16));
@@ -278,9 +276,6 @@ FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter)
     }
     iter->leaf = FcCharSetLeaf(fcs, pos);
     iter->pos = pos;
-#ifdef CHATTY
-    printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf);
-#endif
 }
 
 static void
@@ -300,29 +295,10 @@ FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter)
     }
 }
 
-#ifdef CHATTY
-static void
-FcCharSetDump (const FcCharSet *fcs)
-{
-    int                pos;
-
-    printf ("fcs %08x:\n", (FcChar32) fcs);
-    for (pos = 0; pos < fcs->num; pos++)
-    {
-       FcCharLeaf      *leaf = fcs->leaves[pos];
-       FcChar32        ucs4 = (FcChar32) fcs->numbers[pos] << 8;
-       
-       printf ("    %08x: %08x\n", ucs4, (FcChar32) leaf);
-    }
-}
-#endif
 
 static void
 FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
 {
-#ifdef CHATTY
-    FcCharSetDump (fcs);
-#endif
     iter->ucs4 = 0;
     iter->pos = 0;
     FcCharSetIterSet (fcs, iter);
@@ -854,6 +830,133 @@ FcCharSetUnparseValue (FcStrBuf *buf, FcChar32 value)
     return FcTrue;
 }
 
+FcCharSet *
+FcNameParseCharSet (FcChar8 *string)
+{
+    FcCharSet  *c;
+    FcChar32   ucs4;
+    FcCharLeaf *leaf;
+    FcCharLeaf temp;
+    FcChar32   bits;
+    int                i;
+
+    c = FcCharSetCreate ();
+    if (!c)
+       goto bail0;
+    while (*string)
+    {
+       string = FcCharSetParseValue (string, &ucs4);
+       if (!string)
+           goto bail1;
+       bits = 0;
+       for (i = 0; i < 256/32; i++)
+       {
+           string = FcCharSetParseValue (string, &temp.map[i]);
+           if (!string)
+               goto bail1;
+           bits |= temp.map[i];
+       }
+       if (bits)
+       {
+           leaf = malloc (sizeof (FcCharLeaf));
+           if (!leaf)
+               goto bail1;
+           *leaf = temp;
+           if (!FcCharSetInsertLeaf (c, ucs4, leaf))
+               goto bail1;
+       }
+    }
+    return c;
+bail1:
+    if (c->num)
+    {
+       FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
+       free (FcCharSetLeaves (c));
+    }
+    if (c->num)
+    {
+       FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
+       free (FcCharSetNumbers (c));
+    }
+    FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
+    free (c);
+bail0:
+    return NULL;
+}
+
+FcBool
+FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
+{
+    FcCharSetIter   ci;
+    int                    i;
+#ifdef CHECK
+    int                    len = buf->len;
+#endif
+
+    for (FcCharSetIterStart (c, &ci);
+        ci.leaf;
+        FcCharSetIterNext (c, &ci))
+    {
+       if (!FcCharSetUnparseValue (buf, ci.ucs4))
+           return FcFalse;
+       for (i = 0; i < 256/32; i++)
+           if (!FcCharSetUnparseValue (buf, ci.leaf->map[i]))
+               return FcFalse;
+    }
+#ifdef CHECK
+    {
+       FcCharSet       *check;
+       FcChar32        missing;
+       FcCharSetIter   ci, checki;
+       
+       /* null terminate for parser */
+       FcStrBufChar (buf, '\0');
+       /* step back over null for life after test */
+       buf->len--;
+       check = FcNameParseCharSet (buf->buf + len);
+       FcCharSetIterStart (c, &ci);
+       FcCharSetIterStart (check, &checki);
+       while (ci.leaf || checki.leaf)
+       {
+           if (ci.ucs4 < checki.ucs4)
+           {
+               printf ("Missing leaf node at 0x%x\n", ci.ucs4);
+               FcCharSetIterNext (c, &ci);
+           }
+           else if (checki.ucs4 < ci.ucs4)
+           {
+               printf ("Extra leaf node at 0x%x\n", checki.ucs4);
+               FcCharSetIterNext (check, &checki);
+           }
+           else
+           {
+               int         i = 256/32;
+               FcChar32    *cm = ci.leaf->map;
+               FcChar32    *checkm = checki.leaf->map;
+
+               for (i = 0; i < 256; i += 32)
+               {
+                   if (*cm != *checkm)
+                       printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n",
+                               ci.ucs4 + i, *cm, *checkm);
+                   cm++;
+                   checkm++;
+               }
+               FcCharSetIterNext (c, &ci);
+               FcCharSetIterNext (check, &checki);
+           }
+       }
+       if ((missing = FcCharSetSubtractCount (c, check)))
+           printf ("%d missing in reparsed result\n", missing);
+       if ((missing = FcCharSetSubtractCount (check, c)))
+           printf ("%d extra in reparsed result\n", missing);
+       FcCharSetDestroy (check);
+    }
+#endif
+    
+    return FcTrue;
+}
+
 typedef struct _FcCharLeafEnt FcCharLeafEnt;
 
 struct _FcCharLeafEnt {
@@ -863,36 +966,63 @@ struct _FcCharLeafEnt {
 };
 
 #define FC_CHAR_LEAF_BLOCK     (4096 / sizeof (FcCharLeafEnt))
-static FcCharLeafEnt **FcCharLeafBlocks;
-static int FcCharLeafBlockCount;
+#define FC_CHAR_LEAF_HASH_SIZE 257
+
+typedef struct _FcCharSetEnt FcCharSetEnt;
+
+struct _FcCharSetEnt {
+    FcCharSetEnt       *next;
+    FcChar32           hash;
+    FcCharSet          set;
+};
+
+typedef struct _FcCharSetOrigEnt FcCharSetOrigEnt;
+
+struct _FcCharSetOrigEnt {
+    FcCharSetOrigEnt   *next;
+    const FcCharSet            *orig;
+    const FcCharSet            *frozen;
+};
+
+#define FC_CHAR_SET_HASH_SIZE    67
+
+struct _FcCharSetFreezer {
+    FcCharLeafEnt   *leaf_hash_table[FC_CHAR_LEAF_HASH_SIZE];
+    FcCharLeafEnt   **leaf_blocks;
+    int                    leaf_block_count;
+    FcCharSetEnt    *set_hash_table[FC_CHAR_SET_HASH_SIZE];
+    FcCharSetOrigEnt   *orig_hash_table[FC_CHAR_SET_HASH_SIZE];
+    FcCharLeafEnt   *current_block;
+    int                    leaf_remain;
+    int                    leaves_seen;
+    int                    charsets_seen;
+    int                    leaves_allocated;
+    int                    charsets_allocated;
+};
 
 static FcCharLeafEnt *
-FcCharLeafEntCreate (void)
+FcCharLeafEntCreate (FcCharSetFreezer *freezer)
 {
-    static FcCharLeafEnt    *block;
-    static int             remain;
-
-    if (!remain)
+    if (!freezer->leaf_remain)
     {
        FcCharLeafEnt **newBlocks;
 
-       FcCharLeafBlockCount++;
-       newBlocks = realloc (FcCharLeafBlocks, FcCharLeafBlockCount * sizeof (FcCharLeafEnt *));
+       freezer->leaf_block_count++;
+       newBlocks = realloc (freezer->leaf_blocks, freezer->leaf_block_count * sizeof (FcCharLeafEnt *));
        if (!newBlocks)
            return 0;
-       FcCharLeafBlocks = newBlocks;
-       block = FcCharLeafBlocks[FcCharLeafBlockCount-1] = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
-       if (!block)
+       freezer->leaf_blocks = newBlocks;
+       freezer->current_block = freezer->leaf_blocks[freezer->leaf_block_count-1] = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
+       if (!freezer->current_block)
            return 0;
        FcMemAlloc (FC_MEM_CHARLEAF, FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
-       remain = FC_CHAR_LEAF_BLOCK;
+       freezer->leaf_remain = FC_CHAR_LEAF_BLOCK;
     }
-    remain--;
-    return block++;
+    freezer->leaf_remain--;
+    freezer->leaves_allocated++;
+    return freezer->current_block++;
 }
 
-#define FC_CHAR_LEAF_HASH_SIZE 257
-
 static FcChar32
 FcCharLeafHash (FcCharLeaf *leaf)
 {
@@ -904,29 +1034,22 @@ FcCharLeafHash (FcCharLeaf *leaf)
     return hash;
 }
 
-static int     FcCharLeafTotal;
-static int     FcCharLeafUsed;
-
-static FcCharLeafEnt   *FcCharLeafHashTable[FC_CHAR_LEAF_HASH_SIZE];
-
 static FcCharLeaf *
-FcCharSetFreezeLeaf (FcCharLeaf *leaf)
+FcCharSetFreezeLeaf (FcCharSetFreezer *freezer, FcCharLeaf *leaf)
 {
     FcChar32                   hash = FcCharLeafHash (leaf);
-    FcCharLeafEnt              **bucket = &FcCharLeafHashTable[hash % FC_CHAR_LEAF_HASH_SIZE];
+    FcCharLeafEnt              **bucket = &freezer->leaf_hash_table[hash % FC_CHAR_LEAF_HASH_SIZE];
     FcCharLeafEnt              *ent;
     
-    FcCharLeafTotal++;
     for (ent = *bucket; ent; ent = ent->next)
     {
        if (ent->hash == hash && !memcmp (&ent->leaf, leaf, sizeof (FcCharLeaf)))
            return &ent->leaf;
     }
 
-    ent = FcCharLeafEntCreate();
+    ent = FcCharLeafEntCreate(freezer);
     if (!ent)
        return 0;
-    FcCharLeafUsed++;
     ent->leaf = *leaf;
     ent->hash = hash;
     ent->next = *bucket;
@@ -934,35 +1057,6 @@ FcCharSetFreezeLeaf (FcCharLeaf *leaf)
     return &ent->leaf;
 }
 
-static void
-FcCharSetThawAllLeaf (void)
-{
-    int i;
-
-    for (i = 0; i < FC_CHAR_LEAF_HASH_SIZE; i++)
-       FcCharLeafHashTable[i] = 0;
-
-    FcCharLeafTotal = 0;
-    FcCharLeafUsed = 0;
-
-    for (i = 0; i < FcCharLeafBlockCount; i++)
-       free (FcCharLeafBlocks[i]);
-
-    free (FcCharLeafBlocks);
-    FcCharLeafBlocks = 0;
-    FcCharLeafBlockCount = 0;
-}
-
-typedef struct _FcCharSetEnt FcCharSetEnt;
-
-struct _FcCharSetEnt {
-    FcCharSetEnt       *next;
-    FcChar32           hash;
-    FcCharSet          set;
-};
-
-#define FC_CHAR_SET_HASH_SIZE    67
-
 static FcChar32
 FcCharSetHash (FcCharSet *fcs)
 {
@@ -978,23 +1072,31 @@ FcCharSetHash (FcCharSet *fcs)
     return hash;
 }
 
-static int     FcCharSetTotal;
-static int     FcCharSetUsed;
-static int     FcCharSetTotalEnts, FcCharSetUsedEnts;
-
-static FcCharSetEnt    *FcCharSetHashTable[FC_CHAR_SET_HASH_SIZE];
+static FcBool
+FcCharSetFreezeOrig (FcCharSetFreezer *freezer, const FcCharSet *orig, const FcCharSet *frozen)
+{
+    FcCharSetOrigEnt   **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE];
+    FcCharSetOrigEnt   *ent;
+    
+    ent = malloc (sizeof (FcCharSetOrigEnt));
+    if (!ent)
+       return FcFalse;
+    ent->orig = orig;
+    ent->frozen = frozen;
+    ent->next = *bucket;
+    *bucket = ent;
+    return FcTrue;
+}
 
 static FcCharSet *
-FcCharSetFreezeBase (FcCharSet *fcs)
+FcCharSetFreezeBase (FcCharSetFreezer *freezer, FcCharSet *fcs, const FcCharSet *orig)
 {
     FcChar32           hash = FcCharSetHash (fcs);
-    FcCharSetEnt       **bucket = &FcCharSetHashTable[hash % FC_CHAR_SET_HASH_SIZE];
+    FcCharSetEnt       **bucket = &freezer->set_hash_table[hash % FC_CHAR_SET_HASH_SIZE];
     FcCharSetEnt       *ent;
     int                        size;
     int                        i;
 
-    FcCharSetTotal++;
-    FcCharSetTotalEnts += fcs->num;
     for (ent = *bucket; ent; ent = ent->next)
     {
        if (ent->hash == hash &&
@@ -1021,8 +1123,8 @@ FcCharSetFreezeBase (FcCharSet *fcs)
     if (!ent)
        return 0;
     FcMemAlloc (FC_MEM_CHARSET, size);
-    FcCharSetUsed++;
-    FcCharSetUsedEnts += fcs->num;
+    
+    freezer->charsets_allocated++;
     
     ent->set.ref = FC_REF_CONSTANT;
     ent->set.num = fcs->num;
@@ -1051,60 +1153,60 @@ FcCharSetFreezeBase (FcCharSet *fcs)
     ent->hash = hash;
     ent->next = *bucket;
     *bucket = ent;
+
     return &ent->set;
 }
 
-void
-FcCharSetThawAll (void)
+static const FcCharSet *
+FcCharSetFindFrozen (FcCharSetFreezer *freezer, const FcCharSet *orig)
 {
-    int i;
-    FcCharSetEnt       *ent, *next;
-
-    for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
-    {
-       for (ent = FcCharSetHashTable[i]; ent; ent = next)
-       {
-           next = ent->next;
-           free (ent);
-       }
-       FcCharSetHashTable[i] = 0;
-    }
-
-    FcCharSetTotal = 0;
-    FcCharSetTotalEnts = 0;
-    FcCharSetUsed = 0;
-    FcCharSetUsedEnts = 0;
-
-    FcCharSetThawAllLeaf ();
+    FcCharSetOrigEnt    **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE];
+    FcCharSetOrigEnt   *ent;
+    
+    for (ent = *bucket; ent; ent = ent->next)
+       if (ent->orig == orig)
+           return ent->frozen;
+    return NULL;
 }
 
-FcCharSet *
-FcCharSetFreeze (FcCharSet *fcs)
+static const FcCharSet *
+FcCharSetFreeze (FcCharSetFreezer *freezer, const FcCharSet *fcs)
 {
-    FcCharSet  *b;
-    FcCharSet  *n = 0;
-    FcCharLeaf *l;
-    int                i;
+    FcCharSet      *b;
+    const FcCharSet *n = 0;
+    FcCharLeaf     *l;
+    int                    i;
 
+    n = FcCharSetFindFrozen (freezer, fcs);
+    if (n)
+       return n;
+    
     b = FcCharSetCreate ();
     if (!b)
        goto bail0;
     for (i = 0; i < fcs->num; i++)
     {
-       l = FcCharSetFreezeLeaf (FcCharSetLeaf(fcs, i));
+       l = FcCharSetFreezeLeaf (freezer, FcCharSetLeaf(fcs, i));
        if (!l)
            goto bail1;
        if (!FcCharSetInsertLeaf (b, FcCharSetNumbers(fcs)[i] << 8, l))
            goto bail1;
     }
-    n = FcCharSetFreezeBase (b);
+    n = FcCharSetFreezeBase (freezer, b, fcs);
+    if (!FcCharSetFreezeOrig (freezer, fcs, n))
+    {
+       n = NULL;
+       goto bail1;
+    }
+    freezer->charsets_seen++;
+    freezer->leaves_seen += fcs->num;
 bail1:
-    if (FcCharSetLeaves (b))
+    if (b->num)
     {
        FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
        free (FcCharSetLeaves (b));
     }
-    if (FcCharSetNumbers (b))
+    if (b->num)
     {
        FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
        free (FcCharSetNumbers (b));
@@ -1115,160 +1217,74 @@ bail0:
     return n;
 }
 
-FcCharSet *
-FcNameParseCharSet (FcChar8 *string)
+static FcCharSetFreezer *
+FcCharSetFreezerCreate (void)
 {
-    FcCharSet  *c, *n = 0;
-    FcChar32   ucs4;
-    FcCharLeaf *leaf;
-    FcCharLeaf temp;
-    FcChar32   bits;
-    int                i;
+    FcCharSetFreezer   *freezer;
 
-    c = FcCharSetCreate ();
-    if (!c)
-       goto bail0;
-    while (*string)
-    {
-       string = FcCharSetParseValue (string, &ucs4);
-       if (!string)
-           goto bail1;
-       bits = 0;
-       for (i = 0; i < 256/32; i++)
-       {
-           string = FcCharSetParseValue (string, &temp.map[i]);
-           if (!string)
-               goto bail1;
-           bits |= temp.map[i];
-       }
-       if (bits)
-       {
-           leaf = FcCharSetFreezeLeaf (&temp);
-           if (!leaf)
-               goto bail1;
-           if (!FcCharSetInsertLeaf (c, ucs4, leaf))
-               goto bail1;
-       }
-    }
-#ifdef CHATTY
-    printf ("          %8s %8s %8s %8s\n", "total", "totalmem", "new", "newmem");
-    printf ("Leaves:   %8d %8d %8d %8d\n",
-           FcCharLeafTotal, sizeof (FcCharLeaf) * FcCharLeafTotal,
-           FcCharLeafUsed, sizeof (FcCharLeaf) * FcCharLeafUsed);
-    printf ("Charsets: %8d %8d %8d %8d\n",
-           FcCharSetTotal, sizeof (FcCharSet) * FcCharSetTotal,
-           FcCharSetUsed, sizeof (FcCharSet) * FcCharSetUsed);
-    printf ("Tables:   %8d %8d %8d %8d\n",
-           FcCharSetTotalEnts, FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
-           FcCharSetUsedEnts, FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
-    printf ("Total:    %8s %8d %8s %8d\n", 
-           "", 
-           sizeof (FcCharLeaf) * FcCharLeafTotal +
-           sizeof (FcCharSet) * FcCharSetTotal +
-           FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
-           "",
-           sizeof (FcCharLeaf) * FcCharLeafUsed +
-           sizeof (FcCharSet) * FcCharSetUsed +
-           FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
-#endif
-    n = FcCharSetFreezeBase (c);
-bail1:
-    if (FcCharSetLeaves (c))
-    {
-       FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
-       free (FcCharSetLeaves (c));
-    }
-    if (FcCharSetNumbers (c))
-    {
-       FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
-       free (FcCharSetNumbers (c));
-    }
-    FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
-    free (c);
-bail0:
-    return n;
+    freezer = calloc (1, sizeof (FcCharSetFreezer));
+    return freezer;
 }
 
-FcBool
-FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
+void
+FcCharSetFreezerDestroy (FcCharSetFreezer *freezer)
 {
-    FcCharSetIter   ci;
-    int                    i;
-#ifdef CHECK
-    int                    len = buf->len;
-#endif
+    int i;
 
-    for (FcCharSetIterStart (c, &ci);
-        ci.leaf;
-        FcCharSetIterNext (c, &ci))
+    if (FcDebug() & FC_DBG_CACHE)
     {
-       if (!FcCharSetUnparseValue (buf, ci.ucs4))
-           return FcFalse;
-       for (i = 0; i < 256/32; i++)
-           if (!FcCharSetUnparseValue (buf, ci.leaf->map[i]))
-               return FcFalse;
+       printf ("\ncharsets %d -> %d leaves %d -> %d\n",
+               freezer->charsets_seen, freezer->charsets_allocated,
+               freezer->leaves_seen, freezer->leaves_allocated);
     }
-#ifdef CHECK
+    for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
     {
-       FcCharSet       *check;
-       FcChar32        missing;
-       FcCharSetIter   ci, checki;
-       
-       /* null terminate for parser */
-       FcStrBufChar (buf, '\0');
-       /* step back over null for life after test */
-       buf->len--;
-       check = FcNameParseCharSet (buf->buf + len);
-       FcCharSetIterStart (c, &ci);
-       FcCharSetIterStart (check, &checki);
-       while (ci.leaf || checki.leaf)
+       FcCharSetEnt    *ent, *next;
+       for (ent = freezer->set_hash_table[i]; ent; ent = next)
        {
-           if (ci.ucs4 < checki.ucs4)
-           {
-               printf ("Missing leaf node at 0x%x\n", ci.ucs4);
-               FcCharSetIterNext (c, &ci);
-           }
-           else if (checki.ucs4 < ci.ucs4)
-           {
-               printf ("Extra leaf node at 0x%x\n", checki.ucs4);
-               FcCharSetIterNext (check, &checki);
-           }
-           else
-           {
-               int         i = 256/32;
-               FcChar32    *cm = ci.leaf->map;
-               FcChar32    *checkm = checki.leaf->map;
+           next = ent->next;
+           free (ent);
+       }
+    }
 
-               for (i = 0; i < 256; i += 32)
-               {
-                   if (*cm != *checkm)
-                       printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n",
-                               ci.ucs4 + i, *cm, *checkm);
-                   cm++;
-                   checkm++;
-               }
-               FcCharSetIterNext (c, &ci);
-               FcCharSetIterNext (check, &checki);
-           }
+    for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
+    {
+       FcCharSetOrigEnt        *ent, *next;
+       for (ent = freezer->orig_hash_table[i]; ent; ent = next)
+       {
+           next = ent->next;
+           free (ent);
        }
-       if ((missing = FcCharSetSubtractCount (c, check)))
-           printf ("%d missing in reparsed result\n", missing);
-       if ((missing = FcCharSetSubtractCount (check, c)))
-           printf ("%d extra in reparsed result\n", missing);
-       FcCharSetDestroy (check);
     }
-#endif
-    
-    return FcTrue;
+
+    for (i = 0; i < freezer->leaf_block_count; i++)
+       free (freezer->leaf_blocks[i]);
+
+    free (freezer->leaf_blocks);
+    free (freezer);
 }
 
 FcBool
 FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
 {
-    intptr_t       *leaves = FcCharSetLeaves (cs);
-    FcChar16       *numbers = FcCharSetNumbers (cs);
+    intptr_t       *leaves;
+    FcChar16       *numbers;
     int                    i;
     
+    if (cs->ref != FC_REF_CONSTANT)
+    {
+       if (!serialize->cs_freezer)
+       {
+           serialize->cs_freezer = FcCharSetFreezerCreate ();
+           if (!serialize->cs_freezer)
+               return FcFalse;
+       }
+        cs = FcCharSetFreeze (serialize->cs_freezer, cs);
+    }
+    
+    leaves = FcCharSetLeaves (cs);
+    numbers = FcCharSetNumbers (cs);
+    
     if (!FcSerializeAlloc (serialize, cs, sizeof (FcCharSet)))
        return FcFalse;
     if (!FcSerializeAlloc (serialize, leaves, cs->num * sizeof (intptr_t)))
@@ -1285,12 +1301,20 @@ FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
 FcCharSet *
 FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
 {
-    FcCharSet  *cs_serialized = FcSerializePtr (serialize, cs);
+    FcCharSet  *cs_serialized;
     intptr_t   *leaves, *leaves_serialized;
     FcChar16   *numbers, *numbers_serialized;
     FcCharLeaf *leaf, *leaf_serialized;
     int                i;
 
+    if (cs->ref != FC_REF_CONSTANT && serialize->cs_freezer)
+    {
+       cs = FcCharSetFindFrozen (serialize->cs_freezer, cs);
+       if (!cs)
+           return NULL;
+    }
+                   
+    cs_serialized = FcSerializePtr (serialize, cs);
     if (!cs_serialized)
        return NULL;
     
index 3aeb4c98da80f5a0529262a2628244c864b29e78..0b7c8d8c9290401dd4149fe05e9abc6ac897c8f0 100644 (file)
@@ -85,12 +85,8 @@ FcFileScanConfig (FcFontSet  *set,
                  FcStrSet      *dirs,
                  FcBlanks      *blanks,
                  const FcChar8 *file,
-                 FcBool        force,
                  FcConfig      *config)
 {
-    if (config && !FcConfigAcceptFilename (config, file))
-       return FcTrue;
-
     if (FcFileIsDir (file))
        return FcStrSetAdd (dirs, file);
     else
@@ -105,13 +101,12 @@ FcFileScan (FcFontSet         *set,
            const FcChar8   *file,
            FcBool          force)
 {
-    return FcFileScanConfig (set, dirs, blanks, file, force, 0);
+    return FcFileScanConfig (set, dirs, blanks, file, NULL);
 }
 
 /*
  * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
  */
-
 static int
 cmpstringp(const void *p1, const void *p2)
 {
@@ -119,62 +114,41 @@ cmpstringp(const void *p1, const void *p2)
 }
 
 /*
- * Scan 'dir', adding font files to 'set' and
- * subdirectories to 'dirs'
+ * Scan the specified directory and construct a cache of its contents
  */
-
-FcBool
-FcDirScanConfig (FcFontSet     *set,
-                FcStrSet       *dirs,
-                FcBlanks       *blanks,
-                const FcChar8  *dir,
-                FcBool         force,
-                FcConfig       *config)
+FcCache *
+FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
 {
     DIR                        *d;
-    FcChar8            *canon_dir;
     struct dirent      *e;
-    FcStrSet           *dirlist, *filelist;
+    FcStrSet           *files;
+    FcStrSet           *dirs;
     FcChar8            *file;
     FcChar8            *base;
     FcBool             ret = FcTrue;
-    FcFontSet          *tmpSet;
+    FcFontSet          *set;
     int                        i;
+    FcBlanks           *blanks = FcConfigGetBlanks (config);
+    FcCache            *cache = NULL;
 
-    canon_dir = FcStrCanonFilename (dir);
-    if (!canon_dir) canon_dir = (FcChar8 *) dir;
-    
-    if (config && !FcConfigAcceptFilename (config, canon_dir)) {
-       ret = FcTrue;
-       goto bail;
-    }
-
-    if (!force)
-    {
-       if (FcDirCacheRead (set, dirs, canon_dir, config)) {
-           ret = FcTrue;
-           goto bail;
-       }
-    }
-    
     if (FcDebug () & FC_DBG_FONTSET)
-       printf ("cache scan dir %s\n", canon_dir);
+       printf ("cache scan dir %s\n", dir);
 
     /* freed below */
-    file = (FcChar8 *) malloc (strlen ((char *) canon_dir) + 1 + FC_MAX_FILE_LEN + 1);
+    file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
     if (!file) {
        ret = FcFalse;
        goto bail;
     }
 
-    strcpy ((char *) file, (char *) canon_dir);
+    strcpy ((char *) file, (char *) dir);
     strcat ((char *) file, "/");
     base = file + strlen ((char *) file);
     
     if (FcDebug () & FC_DBG_SCAN)
-       printf ("\tScanning dir %s\n", canon_dir);
+       printf ("\tScanning dir %s\n", dir);
        
-    d = opendir ((char *) canon_dir);
+    d = opendir ((char *) dir);
     if (!d)
     {
        /* Don't complain about missing directories */
@@ -185,84 +159,64 @@ FcDirScanConfig (FcFontSet        *set,
        goto bail_1;
     }
 
-    tmpSet = FcFontSetCreate();
-    if (!tmpSet) 
+    set = FcFontSetCreate();
+    if (!set) 
     {
        ret = FcFalse;
        goto bail0;
     }
 
-    dirlist = FcStrSetCreate ();
-    if (!dirlist) 
+    files = FcStrSetCreate ();
+    if (!files)
     {
        ret = FcFalse;
        goto bail1;
     }
-    filelist = FcStrSetCreate ();
-    if (!filelist)
-    {
-       ret = FcFalse;
-       goto bail2;
-    }
     while ((e = readdir (d)))
     {
        if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
        {
            strcpy ((char *) base, (char *) e->d_name);
-           if (FcFileIsDir (file)) {
-               if (!FcStrSetAdd (dirlist, file)) {
-                   ret = FcFalse;
-                   goto bail3;
-               }
-           } else {
-               if (!FcStrSetAdd (filelist, file)) {
-                   ret = FcFalse;
-                   goto bail3;
-               }
+           if (!FcStrSetAdd (files, file)) {
+               ret = FcFalse;
+               goto bail2;
            }
        }
     }
+
     /*
-     * Sort files and dirs to make things prettier
+     * Sort files to make things prettier
      */
-    qsort(dirlist->strs, dirlist->num, sizeof(FcChar8 *), cmpstringp);
-    qsort(filelist->strs, filelist->num, sizeof(FcChar8 *), cmpstringp);
+    qsort(files->strs, files->num, sizeof(FcChar8 *), cmpstringp);
     
-    for (i = 0; i < filelist->num; i++)
-       FcFileScanFontConfig (tmpSet, blanks, filelist->strs[i], config);
+    dirs = FcStrSetCreate ();
+    if (!dirs)
+       goto bail2;
     
     /*
-     * Now that the directory has been scanned,
-     * write out the cache file
+     * Scan file files to build font patterns
      */
-    FcDirCacheWrite (tmpSet, dirlist, canon_dir, config);
-
-    /*
-     * Add the discovered fonts to our internal non-cache list
-     */
-    for (i = 0; i < tmpSet->nfont; i++)
-       FcFontSetAdd (set, tmpSet->fonts[i]);
-
+    for (i = 0; i < files->num; i++)
+       FcFileScanConfig (set, dirs, blanks, files->strs[i], config);
+    
     /*
-     * the patterns in tmpset now belong to set; don't free them 
+     * Build the cache object
      */
-    tmpSet->nfont = 0;
-
+    cache = FcDirCacheBuild (set, dir, dirs);
+    if (!cache)
+       goto bail3;
+    
     /*
-     * Add the discovered directories to the list to be scanned
+     * Write out the cache file, ignoring any troubles
      */
-    for (i = 0; i < dirlist->num; i++)
-       if (!FcStrSetAdd (dirs, dirlist->strs[i])) {
-           ret = FcFalse;
-           goto bail3;
-       }
+    FcDirCacheWrite (cache, config);
     
  bail3:
-    FcStrSetDestroy (filelist);
+    FcStrSetDestroy (dirs);
  bail2:
-    FcStrSetDestroy (dirlist);
+    FcStrSetDestroy (files);
  bail1:
-    FcFontSetDestroy (tmpSet);
+    FcFontSetDestroy (set);
     
  bail0:
     closedir (d);
@@ -270,8 +224,49 @@ FcDirScanConfig (FcFontSet *set,
  bail_1:
     free (file);
  bail:
-    if (canon_dir != dir) free (canon_dir);
-    return ret;
+    return cache;
+}
+
+/*
+ * Read (or construct) the cache for a directory
+ */
+FcCache *
+FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config)
+{
+    FcCache            *cache = NULL;
+    FcChar8            *canon_dir;
+
+    canon_dir = FcStrCanonFilename (dir);
+    if (!canon_dir) canon_dir = (FcChar8 *) dir;
+    
+    if (config && !FcConfigAcceptFilename (config, canon_dir)) {
+       goto bail;
+    }
+
+    /* Try to use existing cache file */
+    if (!force)
+       cache = FcDirCacheLoad (canon_dir, config, NULL);
+    
+    /* Not using existing cache file, construct new cache */
+    if (!cache)
+       cache = FcDirCacheScan (canon_dir, config);
+    
+bail:
+    if (canon_dir != dir) 
+       free (canon_dir);
+    
+    return cache;
+}
+
+FcBool
+FcDirScanConfig (FcFontSet     *set,
+                FcStrSet       *dirs,
+                FcBlanks       *blanks,
+                const FcChar8  *dir,
+                FcBool         force,
+                FcConfig       *config)
+{
+    return FcFalse; /* XXX fixme */
 }
 
 FcBool
@@ -282,11 +277,11 @@ FcDirScan (FcFontSet          *set,
           const FcChar8    *dir,
           FcBool           force)
 {
-    return FcDirScanConfig (set, dirs, blanks, dir, force, 0);
+    return FcDirScanConfig (set, dirs, blanks, dir, force, NULL);
 }
 
 FcBool
 FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
 {
-    return FcFalse;
+    return FcFalse; /* XXX deprecated */
 }
index 8f60cd8cd2637254927f51c137ee0b89bd649e8a..65702b4421991ca73ec8ae89a54bc5be355adf89 100644 (file)
@@ -121,7 +121,6 @@ FcFini (void)
        FcConfigDestroy (_fcConfig);
 
     FcPatternFini ();
-    FcCharSetThawAll ();
 }
 
 /*
index 0bc5df2b47e679fce828652351e0daa8b1df8187..ce0ac7c845b7b02a483c8a0d4e691e03ac5787af 100644 (file)
@@ -55,7 +55,6 @@
 
 #define FC_FONT_FILE_INVALID   ((FcChar8 *) ".")
 #define FC_FONT_FILE_DIR       ((FcChar8 *) ".dir")
-#define FC_GLOBAL_MAGIC_COOKIE "GLOBAL"
 
 #ifdef _WIN32
 #define FC_SEARCH_PATH_SEPARATOR ';'
@@ -75,6 +74,7 @@
 #define FC_DBG_MEMORY  512
 #define FC_DBG_CONFIG  1024
 #define FC_DBG_LANGSET 2048
+#define FC_DBG_OBJTYPES        4096
 
 #define FC_MEM_CHARSET     0
 #define FC_MEM_CHARLEAF            1
@@ -307,7 +307,8 @@ typedef struct _FcStrBuf {
 } FcStrBuf;
 
 typedef struct _FcCache {
-    int                magic;              /* FC_CACHE_MAGIC */
+    int                magic;              /* FC_CACHE_MAGIC_MMAP or FC_CACHE_ALLOC */
+    int                version;            /* FC_CACHE_CONTENT_VERSION */
     intptr_t   size;               /* size of file */
     intptr_t   dir;                /* offset to dir name */
     intptr_t   dirs;               /* offset to subdirs */
@@ -318,6 +319,9 @@ typedef struct _FcCache {
 #define FcCacheDir(c)  FcOffsetMember(c,dir,FcChar8)
 #define FcCacheDirs(c) FcOffsetMember(c,dirs,intptr_t)
 #define FcCacheSet(c)  FcOffsetMember(c,set,FcFontSet)
+#define FcCacheSubdir(c,i)  FcOffsetToPtr (FcCacheDirs(cache),\
+                                          FcCacheDirs(cache)[i], \
+                                          FcChar8)
 
 /*
  * Used while constructing a directory cache object
@@ -331,8 +335,11 @@ typedef struct _FcSerializeBucket {
     intptr_t   offset;
 } FcSerializeBucket;
 
+typedef struct _FcCharSetFreezer FcCharSetFreezer;
+
 typedef struct _FcSerialize {
     intptr_t           size;
+    FcCharSetFreezer   *cs_freezer;
     void               *linear;
     FcSerializeBucket  *buckets[FC_SERIALIZE_HASH_SIZE];
 } FcSerialize;
@@ -389,8 +396,9 @@ typedef struct _FcCaseFold {
 
 #define fc_alignof(type) offsetof (struct { char c; type member; }, member)
 
-#define FC_CACHE_MAGIC     0xFC02FC04
-#define FC_CACHE_MAGIC_COPY 0xFC02FC05
+#define FC_CACHE_MAGIC_MMAP        0xFC02FC04
+#define FC_CACHE_MAGIC_ALLOC       0xFC02FC05
+#define FC_CACHE_CONTENT_VERSION    1
 
 struct _FcAtomic {
     FcChar8    *file;          /* original file name */
@@ -490,31 +498,30 @@ typedef struct _FcCharMap FcCharMap;
 
 /* fccache.c */
 
-FcFontSet *
-FcCacheRead (FcConfig *config);
-
 FcBool
-FcDirCacheWrite (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config);
+FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config);
 
-FcBool
-FcDirCacheConsume (FILE *file, FcFontSet *set, FcStrSet *dirs,
-                  const FcChar8 *dir, char *dirname);
-    
 void
-FcDirCacheUnmap (FcCache *cache);
+FcDirCacheUnload (FcCache *cache);
 
-FcBool
-FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config);
 FcCache *
-FcDirCacheMap (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file);
-    
-FcBool
-FcDirCacheLoad (int fd, off_t size, void *closure);
+FcDirCacheScan (const FcChar8 *dir, FcConfig *config);
+
+FcCache *
+FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file);
     
+FcCache *
+FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat);
+
 FcBool
-FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config);
+FcDirCacheValid (const FcChar8 *dir);
 
+FcCache *
+FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs);
+
+FcBool
+FcDirCacheWrite (FcCache *cache, FcConfig *config);
+    
 /* fccfg.c */
 
 FcBool
@@ -616,11 +623,8 @@ FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l);
 void
 FcLangCharSetPopulate (void);
 
-FcCharSet *
-FcCharSetFreeze (FcCharSet *cs);
-
 void
-FcCharSetThawAll (void);
+FcCharSetFreezerDestroy (FcCharSetFreezer *freezer);
 
 FcBool
 FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c);
@@ -687,17 +691,19 @@ FcFileScanConfig (FcFontSet       *set,
                  FcStrSet      *dirs,
                  FcBlanks      *blanks,
                  const FcChar8 *file,
-                 FcBool        force,
                  FcConfig      *config);
 
 FcBool
 FcDirScanConfig (FcFontSet     *set,
                 FcStrSet       *dirs,
                 FcBlanks       *blanks,
-                const FcChar8  *dir,
+                const FcChar8  *dir,
                 FcBool         force,
                 FcConfig       *config);
 
+FcCache *
+FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config);
+
 /* fcfont.c */
 int
 FcFontDebug (void);
index b40d3c0752e3d788be583afcd4a0ed4953347810..9cd01a02a9303c10ed0d9c578ed850b5d7df8dda 100644 (file)
@@ -491,7 +491,15 @@ FcPatternObjectAddWithBinding  (FcPattern  *p,
      * Make sure the stored type is valid for built-in objects
      */
     if (!FcObjectValidType (object, value.type))
+    {
+       if (FcDebug() & FC_DBG_OBJTYPES)
+       {
+           printf ("FcPattern object %s does not accept value ",
+                   FcObjectName (object));
+           FcValuePrint (value);
+       }
        goto bail1;
+    }
 
     new->value = value;
     new->binding = binding;
index a8c10b87d0592adecb2719b35ca5dedae79f7acc..d0d35e3413a3c10834839d29e7fb48dcc04de2ea 100644 (file)
@@ -54,6 +54,7 @@ FcSerializeCreate (void)
        return NULL;
     serialize->size = 0;
     serialize->linear = NULL;
+    serialize->cs_freezer = NULL;
     memset (serialize->buckets, '\0', sizeof (serialize->buckets));
     return serialize;
 }
@@ -72,6 +73,8 @@ FcSerializeDestroy (FcSerialize *serialize)
            free (buck);
        }
     }
+    if (serialize->cs_freezer)
+       FcCharSetFreezerDestroy (serialize->cs_freezer);
     free (serialize);
 }