[Fontconfig] fontconfig: Branch 'fc-2_4-keithp'

Keith Packard keithp at kemper.freedesktop.org
Wed Aug 30 22:00:13 PDT 2006


 fc-cache/fc-cache.c |   25 ++++----
 fc-match/fc-match.c |    1 
 src/fccache.c       |  148 +++++++++++++++++++++++++++-------------------------
 src/fccfg.c         |   80 ++++++++--------------------
 src/fccharset.c     |   56 +++++++++++--------
 src/fcdir.c         |    2 
 src/fcint.h         |   19 ++++--
 src/fcxml.c         |   19 ++----
 8 files changed, 169 insertions(+), 181 deletions(-)

New commits:
diff-tree 2d3387fd720f33f80847ae6cbb83d94c9a52fde3 (from 09f9f6f62ac94f7b1a6df649a00c64f78ab132f5)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Aug 30 21:59:53 2006 -0700

    Skip broken caches. Cache files are auto-written, don't rewrite in fc-cache.
    
    Validate cache contents and skip broken caches, looking down cache path for
    valid ones.
    
    Every time a directory is scanned, it will be written to a cache file if
    possible, so fc-cache doesn't need to re-write the cache file. This makes
    detecting when the cache was generated a bit tricky, so we guess that if the
    cache wasn't valid before running and is valid afterwards, the cache file
    was written.
    
    Also, allow empty charsets to be serialized with null leaves/numbers.
    
    Eliminate a leak in FcEdit by switching to FcObject sooner.
    
    Call FcFini from fc-match to make valgrind happy.

diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index 134d33d..9df90cc 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -130,6 +130,7 @@ scanDirs (FcStrList *list, FcConfig *con
     FcStrSet	*subdirs;
     FcStrList	*sublist;
     struct stat	statb;
+    FcBool	was_valid;
     
     /*
      * Now scan all of the directories into separate databases
@@ -160,14 +161,14 @@ scanDirs (FcStrList *list, FcConfig *con
 	set = FcFontSetCreate ();
 	if (!set)
 	{
-	    fprintf (stderr, "Can't create font set\n");
+	    fprintf (stderr, "%s: Can't create font set\n", dir);
 	    ret++;
 	    continue;
 	}
 	subdirs = FcStrSetCreate ();
 	if (!subdirs)
 	{
-	    fprintf (stderr, "Can't create directory set\n");
+	    fprintf (stderr, "%s: Can't create directory set\n", dir);
 	    ret++;
 	    FcFontSetDestroy (set);
 	    continue;
@@ -219,15 +220,18 @@ scanDirs (FcStrList *list, FcConfig *con
 	if (really_force)
 	    FcDirCacheUnlink (dir, config);
 
+	if (!force)
+	    was_valid = FcDirCacheValid (dir, config);
+	
 	if (!FcDirScanConfig (set, subdirs, FcConfigGetBlanks (config), dir, force, config))
 	{
-	    fprintf (stderr, "\"%s\": error scanning\n", dir);
+	    fprintf (stderr, "%s: error scanning\n", dir);
 	    FcFontSetDestroy (set);
 	    FcStrSetDestroy (subdirs);
 	    ret++;
 	    continue;
 	}
-	if (!force && FcDirCacheValid (dir, config))
+	if (!force && was_valid)
 	{
 	    if (verbose)
 		printf ("skipping, %d fonts, %d dirs\n",
@@ -239,15 +243,10 @@ scanDirs (FcStrList *list, FcConfig *con
 		printf ("caching, %d fonts, %d dirs\n", 
 			set->nfont, nsubdirs (subdirs));
 
-	    /* This is the only reason we can't combine 
-	     * Valid w/HasCurrentArch... */
-            if (!FcDirCacheValid (dir, config))
-                if (!FcDirCacheUnlink (dir, config))
-                    ret++;
-
-	    if (!FcDirSave (set, subdirs, dir))
+	    if (!FcDirCacheValid (dir, config))
 	    {
-		fprintf (stderr, "Can't save cache for \"%s\"\n", dir);
+		fprintf (stderr, "%s: failed to write cache\n", dir);
+		(void) FcDirCacheUnlink (dir, config);
 		ret++;
 	    }
 	}
@@ -256,7 +255,7 @@ scanDirs (FcStrList *list, FcConfig *con
 	FcStrSetDestroy (subdirs);
 	if (!sublist)
 	{
-	    fprintf (stderr, "Can't create subdir list in \"%s\"\n", dir);
+	    fprintf (stderr, "%s: Can't create subdir list\n", dir);
 	    ret++;
 	    continue;
 	}
diff --git a/fc-match/fc-match.c b/fc-match/fc-match.c
index d9742c9..5f36f00 100644
--- a/fc-match/fc-match.c
+++ b/fc-match/fc-match.c
@@ -187,5 +187,6 @@ main (int argc, char **argv)
 	}
 	FcFontSetDestroy (fs);
     }
+    FcFini ();
     return 0;
 }
diff --git a/src/fccache.c b/src/fccache.c
index 9f35f29..1411766 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -39,9 +39,6 @@
 #define O_BINARY 0
 #endif
 
-static int
-FcDirCacheOpen (FcConfig *config, const FcChar8 *dir, off_t *size);
-
 struct MD5Context {
         FcChar32 buf[4];
         FcChar32 bits[2];
@@ -53,23 +50,6 @@ static void MD5Update(struct MD5Context 
 static void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
 static void MD5Transform(FcChar32 buf[4], FcChar32 in[16]);
 
-#define FC_DBG_CACHE_REF    1024
-
-/* Does not check that the cache has the appropriate arch section. */
-FcBool
-FcDirCacheValid (const FcChar8 *dir, FcConfig *config)
-{
-    int fd;
-
-    fd = FcDirCacheOpen (config, dir, NULL);
-
-    if (fd < 0)
-	return FcFalse;
-    close (fd);
-
-    return FcTrue;
-}
-
 #define CACHEBASE_LEN (1 + 32 + 1 + sizeof (FC_ARCHITECTURE) + sizeof (FC_CACHE_SUFFIX))
 
 static const char bin2hex[] = { '0', '1', '2', '3',
@@ -209,27 +189,31 @@ FcCacheRead (FcConfig *config)
     return 0;
 }
 
-/* Opens the cache file for 'dir' for reading.
- * This searches the list of cache dirs for the relevant cache file,
- * returning the first one found.
+/* 
+ * Look for a cache file for the specified dir. Attempt
+ * to use each one we find, stopping when the callback
+ * indicates success
  */
-static int
-FcDirCacheOpen (FcConfig *config, const FcChar8 *dir, off_t *size)
+static FcBool
+FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, 
+		   FcBool (*callback) (int fd, off_t size, void *closure),
+		   void *closure)
 {
     int		fd = -1;
     FcChar8	cache_base[CACHEBASE_LEN];
     FcStrList	*list;
     FcChar8	*cache_dir;
     struct stat file_stat, dir_stat;
+    FcBool	ret = FcFalse;
 
     if (stat ((char *) dir, &dir_stat) < 0)
-        return -1;
+        return FcFalse;
 
     FcDirCacheBasename (dir, cache_base);
 
     list = FcStrListCreate (config->cacheDirs);
     if (!list)
-        return -1;
+        return FcFalse;
 	
     while ((cache_dir = FcStrListNext (list)))
     {
@@ -242,43 +226,29 @@ FcDirCacheOpen (FcConfig *config, const 
 	    if (fstat (fd, &file_stat) >= 0 &&
 		dir_stat.st_mtime <= file_stat.st_mtime)
 	    {
-		if (size)
-		    *size = file_stat.st_size;
-		break;
+		ret = (*callback) (fd, file_stat.st_size, closure);
+		if (ret)
+		{
+		    close (fd);
+		    break;
+		}
 	    }
 	    close (fd);
-	    fd = -1;
 	}
     }
     FcStrListDone (list);
     
-    return fd;
-}
-
-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
+    return ret;
 }
 
-/* read serialized state from the cache file */
-FcCache *
-FcDirCacheMap (int fd, off_t size)
+static FcBool
+FcDirCacheLoad (int fd, off_t size, void *closure)
 {
     FcCache	*cache;
     FcBool	allocated = FcFalse;
 
     if (size < sizeof (FcCache))
-	return NULL;
+	return FcFalse;
 #if defined(HAVE_MMAP) || defined(__CYGWIN__)
     cache = mmap (0, size, PROT_READ, MAP_SHARED, fd, 0);
 #elif defined(_WIN32)
@@ -299,12 +269,12 @@ FcDirCacheMap (int fd, off_t size)
     {
 	cache = malloc (size);
 	if (!cache)
-	    return NULL;
+	    return FcFalse;
 
 	if (read (fd, cache, size) != size)
 	{
 	    free (cache);
-	    return NULL;
+	    return FcFalse;
 	}
 	allocated = FcTrue;
     } 
@@ -321,41 +291,41 @@ FcDirCacheMap (int fd, off_t size)
 	    UnmapViewOfFile (cache);
 #endif
 	}
-	return NULL;
+	return FcFalse;
     }
 
     /* Mark allocated caches so they're freed rather than unmapped */
     if (allocated)
 	cache->magic = FC_CACHE_MAGIC_COPY;
 	
-    return cache;
+    *((FcCache **) closure) = cache;
+    return FcTrue;
+}
+
+FcCache *
+FcDirCacheMap (int fd, off_t size)
+{
+    FcCache *cache;
+
+    if (FcDirCacheLoad (fd, size, &cache))
+	return cache;
+    return NULL;
 }
 
 FcBool
 FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, 
 		const FcChar8 *dir, FcConfig *config)
 {
-    int		fd;
     FcCache	*cache;
-    off_t	size;
     int		i;
     FcFontSet	*cache_set;
     intptr_t	*cache_dirs;
     FcPattern   **cache_fonts;
 
-    fd = FcDirCacheOpen (config, dir, &size);
-    if (fd < 0)
+    if (!FcDirCacheProcess (config, dir, 
+			    FcDirCacheLoad,
+			    &cache))
 	return FcFalse;
-
-    cache = FcDirCacheMap (fd, size);
-    
-    if (!cache)
-    {
-	if (FcDebug() & FC_DBG_CACHE)
-	    printf ("FcDirCacheRead failed to map cache for %s\n", dir);
-	close (fd);
-	return FcFalse;
-    }
     
     cache_set = FcCacheSet (cache);
     cache_fonts = FcFontSetFonts(cache_set);
@@ -383,10 +353,48 @@ FcDirCacheRead (FcFontSet * set, FcStrSe
     if (config)
 	FcConfigAddFontDir (config, (FcChar8 *)dir);
     
-    close (fd);
     return FcTrue;
 }
     
+static FcBool
+FcDirCacheValidate (int fd, off_t size, void *closure)
+{
+    FcBool  ret = FcTrue;
+    FcCache	c;
+    struct stat	file_stat;
+    
+    if (read (fd, &c, sizeof (FcCache)) != sizeof (FcCache))
+	ret = FcFalse;
+    else if (fstat (fd, &file_stat) < 0)
+	ret = FcFalse;
+    else if (c.magic != FC_CACHE_MAGIC)
+	ret = FcFalse;
+    else if (file_stat.st_size != c.size)
+	ret = FcFalse;
+    return ret;
+}
+
+FcBool
+FcDirCacheValid (const FcChar8 *dir, FcConfig *config)
+{
+    return FcDirCacheProcess (config, dir, FcDirCacheValidate, NULL);
+}
+
+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:
  *
diff --git a/src/fccfg.c b/src/fccfg.c
index 4377ce6..bcc3bd2 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -77,39 +77,9 @@ FcConfigCreate (void)
     if (!config->rejectPatterns)
 	goto bail7;
 
-    config->cache = 0;
-    if (FcConfigHome())
-	if (!FcConfigSetCache (config, (FcChar8 *) ("~/" FC_USER_CACHE_FILE)))
-	    goto bail8;
-
-#ifdef _WIN32
-    if (config->cache == 0)
-    {
-	/* If no home, use the temp folder. */
-	FcChar8	    dummy[1];
-	int	    templen = GetTempPath (1, dummy);
-	FcChar8     *temp = malloc (templen + 1);
-
-	if (temp)
-	{
-	    FcChar8 *cache_dir;
-
-	    GetTempPath (templen + 1, temp);
-	    cache_dir = FcStrPlus (temp, FC_USER_CACHE_FILE);
-	    free (temp);
-	    if (!FcConfigSetCache (config, cache_dir))
-	    {
-		FcStrFree (cache_dir);
-		goto bail8;
-	    }
-	    FcStrFree (cache_dir);
-	}
-    }
-#endif
-
     config->cacheDirs = FcStrSetCreate ();
     if (!config->cacheDirs)
-	goto bail9;
+	goto bail8;
     
     config->blanks = 0;
 
@@ -119,13 +89,13 @@ FcConfigCreate (void)
     for (set = FcSetSystem; set <= FcSetApplication; set++)
 	config->fonts[set] = 0;
 
+    config->caches = NULL;
+
     config->rescanTime = time(0);
     config->rescanInterval = 30;    
     
     return config;
 
-bail9:
-    FcStrFree (config->cache);
 bail8:
     FcFontSetDestroy (config->rejectPatterns);
 bail7:
@@ -226,6 +196,7 @@ void
 FcConfigDestroy (FcConfig *config)
 {
     FcSetName	set;
+    FcCacheList	*cl, *cl_next;
 
     if (config == _fcConfig)
 	_fcConfig = 0;
@@ -242,15 +213,19 @@ FcConfigDestroy (FcConfig *config)
     if (config->blanks)
 	FcBlanksDestroy (config->blanks);
 
-    if (config->cache)
-	FcStrFree (config->cache);
-
     FcSubstDestroy (config->substPattern);
     FcSubstDestroy (config->substFont);
     for (set = FcSetSystem; set <= FcSetApplication; set++)
 	if (config->fonts[set])
 	    FcFontSetDestroy (config->fonts[set]);
 
+    for (cl = config->caches; cl; cl = cl_next)
+    {
+	cl_next = cl->next;
+	FcDirCacheUnmap (cl->cache);
+	free (cl);
+    }
+
     free (config);
     FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
 }
@@ -453,30 +428,10 @@ FcConfigGetConfigFiles (FcConfig    *con
     return FcStrListCreate (config->configFiles);
 }
 
-FcBool
-FcConfigSetCache (FcConfig	*config,
-		  const FcChar8	*c)
-{
-    FcChar8    *new = FcStrCopyFilename (c);
-    
-    if (!new)
-	return FcFalse;
-    if (config->cache)
-	FcStrFree (config->cache);
-    config->cache = new;
-    return FcTrue;
-}
-
 FcChar8 *
 FcConfigGetCache (FcConfig  *config)
 {
-    if (!config)
-    {
-	config = FcConfigGetCurrent ();
-	if (!config)
-	    return 0;
-    }
-    return config->cache;
+    return NULL;
 }
 
 FcFontSet *
@@ -502,7 +457,18 @@ 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)
diff --git a/src/fccharset.c b/src/fccharset.c
index 96dcbe7..3a93c4a 100644
--- a/src/fccharset.c
+++ b/src/fccharset.c
@@ -1297,32 +1297,40 @@ FcCharSetSerialize(FcSerialize *serializ
     cs_serialized->ref = FC_REF_CONSTANT;
     cs_serialized->num = cs->num;
 
-    leaves = FcCharSetLeaves (cs);
-    leaves_serialized = FcSerializePtr (serialize, leaves);
-    if (!leaves_serialized)
-	return NULL;
-
-    cs_serialized->leaves_offset = FcPtrToOffset (cs_serialized,
-						  leaves_serialized);
-    
-    numbers = FcCharSetNumbers (cs);
-    numbers_serialized = FcSerializePtr (serialize, numbers);
-    if (!numbers)
-	return NULL;
-
-    cs_serialized->numbers_offset = FcPtrToOffset (cs_serialized,
-						   numbers_serialized);
-
-    for (i = 0; i < cs->num; i++)
+    if (cs->num)
     {
-	leaf = FcCharSetLeaf (cs, i);
-	leaf_serialized = FcSerializePtr (serialize, leaf);
-	if (!leaf_serialized)
+	leaves = FcCharSetLeaves (cs);
+	leaves_serialized = FcSerializePtr (serialize, leaves);
+	if (!leaves_serialized)
+	    return NULL;
+    
+	cs_serialized->leaves_offset = FcPtrToOffset (cs_serialized,
+						      leaves_serialized);
+	
+	numbers = FcCharSetNumbers (cs);
+	numbers_serialized = FcSerializePtr (serialize, numbers);
+	if (!numbers)
 	    return NULL;
-	*leaf_serialized = *leaf;
-	leaves_serialized[i] = FcPtrToOffset (leaves_serialized, 
-					      leaf_serialized);
-	numbers_serialized[i] = numbers[i];
+    
+	cs_serialized->numbers_offset = FcPtrToOffset (cs_serialized,
+						       numbers_serialized);
+    
+	for (i = 0; i < cs->num; i++)
+	{
+	    leaf = FcCharSetLeaf (cs, i);
+	    leaf_serialized = FcSerializePtr (serialize, leaf);
+	    if (!leaf_serialized)
+		return NULL;
+	    *leaf_serialized = *leaf;
+	    leaves_serialized[i] = FcPtrToOffset (leaves_serialized, 
+						  leaf_serialized);
+	    numbers_serialized[i] = numbers[i];
+	}
+    }
+    else
+    {
+	cs_serialized->leaves_offset = 0;
+	cs_serialized->numbers_offset = 0;
     }
     
     return cs_serialized;
diff --git a/src/fcdir.c b/src/fcdir.c
index 0136867..3aeb4c9 100644
--- a/src/fcdir.c
+++ b/src/fcdir.c
@@ -288,5 +288,5 @@ FcDirScan (FcFontSet	    *set,
 FcBool
 FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
 {
-    return FcDirCacheWrite (set, dirs, dir, FcConfigGetCurrent ());
+    return FcFalse;
 }
diff --git a/src/fcint.h b/src/fcint.h
index c62a5bb..96de695 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -405,6 +405,11 @@ struct _FcBlanks {
     FcChar32	*blanks;
 };
 
+typedef struct _FcCacheList {
+    struct _FcCacheList *next;
+    FcCache		*cache;
+} FcCacheList;
+
 struct _FcConfig {
     /*
      * File names loaded from the configuration -- saved here as the
@@ -412,7 +417,6 @@ struct _FcConfig {
      * and those directives may occur in any order
      */
     FcStrSet	*configDirs;	    /* directories to scan for fonts */
-    FcChar8	*cache;		    /* name of per-user cache file */
     /*
      * Set of allowed blank chars -- used to
      * trim fonts of bogus glyphs
@@ -456,6 +460,11 @@ struct _FcConfig {
      */
     FcFontSet	*fonts[FcSetApplication + 1];
     /*
+     * Font cache information is mapped from cache files
+     * the configuration is destroyed, the files need to be unmapped
+     */
+    FcCacheList	*caches;
+    /*
      * Fontconfig can periodically rescan the system configuration
      * and font directories.  This rescanning occurs when font
      * listing requests are made, but no more often than rescanInterval
@@ -526,10 +535,6 @@ FcConfigAddConfigFile (FcConfig		*config
 		       const FcChar8	*f);
 
 FcBool
-FcConfigSetCache (FcConfig	*config,
-		  const FcChar8	*c);
-
-FcBool
 FcConfigAddBlank (FcConfig	*config,
 		  FcChar32    	blank);
 
@@ -570,6 +575,10 @@ FcConfigAcceptFont (FcConfig	    *config
 FcFileTime
 FcConfigModifiedTime (FcConfig *config);
 
+FcBool
+FcConfigAddCache (FcConfig *config, FcCache *cache);
+
+/* fcserialize.c */
 intptr_t
 FcAlignSize (intptr_t size);
     
diff --git a/src/fcxml.c b/src/fcxml.c
index 608f834..5b7e191 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -668,7 +668,7 @@ FcTestCreate (FcConfigParse *parse,
 
 static FcEdit *
 FcEditCreate (FcConfigParse	*parse,
-	      const char	*field,
+	      FcObject		object,
 	      FcOp		op,
 	      FcExpr		*expr,
 	      FcValueBinding	binding)
@@ -680,7 +680,7 @@ FcEditCreate (FcConfigParse	*parse,
 	const FcObjectType	*o;
 
 	e->next = 0;
-	e->object = FcObjectFromName (field);
+	e->object = object;
 	e->op = op;
 	e->expr = expr;
 	e->binding = binding;
@@ -1410,7 +1410,7 @@ FcParseAlias (FcConfigParse *parse)
     if (prefer)
     {
 	edit = FcEditCreate (parse, 
-			     FcConfigSaveField ("family"),
+			     FC_FAMILY_OBJECT,
 			     FcOpPrepend,
 			     prefer,
 			     FcValueBindingWeak);
@@ -1423,7 +1423,7 @@ FcParseAlias (FcConfigParse *parse)
     {
 	next = edit;
 	edit = FcEditCreate (parse,
-			     FcConfigSaveField ("family"),
+			     FC_FAMILY_OBJECT,
 			     FcOpAppend,
 			     accept,
 			     FcValueBindingWeak);
@@ -1436,7 +1436,7 @@ FcParseAlias (FcConfigParse *parse)
     {
 	next = edit;
 	edit = FcEditCreate (parse,
-			     FcConfigSaveField ("family"),
+			     FC_FAMILY_OBJECT,
 			     FcOpAppendLast,
 			     def,
 			     FcValueBindingWeak);
@@ -1791,7 +1791,8 @@ FcParseEdit (FcConfigParse *parse)
 	}
     }
     expr = FcPopBinary (parse, FcOpComma);
-    edit = FcEditCreate (parse, (char *) FcStrCopy (name), mode, expr, binding);
+    edit = FcEditCreate (parse, FcObjectFromName ((char *) name),
+			 mode, expr, binding);
     if (!edit)
     {
 	FcConfigMessage (parse, FcSevereError, "out of memory");
@@ -2074,11 +2075,7 @@ FcEndElement(void *userData, const XML_C
 	    FcConfigMessage (parse, FcSevereError, "out of memory");
 	    break;
 	}
-	if (!FcStrUsesHome (data) || FcConfigHome ())
-	{
-	    if (!FcConfigSetCache (parse->config, data))
-		FcConfigMessage (parse, FcSevereError, "out of memory");
-	}
+	/* discard this data; no longer used */
 	FcStrFree (data);
 	break;
     case FcElementInclude:


More information about the Fontconfig mailing list