[Fontconfig] fontconfig: Branch 'master' - 16 commits

Keith Packard keithp at kemper.freedesktop.org
Wed Oct 24 17:14:14 PDT 2007


 Makefile.am                 |   11 +----
 conf.d/65-nonlatin.conf     |   11 +++++
 doc/fcconfig.fncs           |    2 
 fc-arch/fcarch.tmpl.h       |   14 +++---
 fc-cache/fc-cache.c         |   61 ++++++++++++-----------------
 fc-glyphname/fc-glyphname.c |   28 +++++++++----
 fc-lang/fc-lang.c           |    2 
 src/fccache.c               |   69 +++++++++++++++++++++------------
 src/fcdir.c                 |    8 +++
 src/fcfreetype.c            |   92 ++++++--------------------------------------
 src/fcint.h                 |    5 +-
 src/fclang.c                |    2 
 src/fcxml.c                 |    4 +
 13 files changed, 143 insertions(+), 166 deletions(-)

New commits:
commit 1bd0b5ba7365fc7b4ef39e46efc66a6f25c052c5
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 09:48:31 2007 -0700

    Eliminate relocations from FcCodePageRange structure (bug 10982).
    
    FcCodePageRange was using char pointers; replace them with char arrays.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index c9c58c7..7773c83 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -80,13 +80,13 @@
  */
 
 static const struct {
-    int		    bit;
-    const FcChar8   *lang;
+    char    	    bit;
+    const FcChar8   lang[6];
 } FcCodePageRange[] = {
-    { 17,	(const FcChar8 *) "ja" },
-    { 18,	(const FcChar8 *) "zh-cn" },
-    { 19,	(const FcChar8 *) "ko" },
-    { 20,	(const FcChar8 *) "zh-tw" },
+    { 17,	"ja" },
+    { 18,	"zh-cn" },
+    { 19,	"ko" },
+    { 20,	"zh-tw" },
 };
 
 #define NUM_CODE_PAGE_RANGE (int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
commit 96925b99c0551c4ed6bf7099473d0d36964f52cd
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 09:43:22 2007 -0700

    Eliminate relocations for glyph name table.
    
    Glyph names (now used only for dingbats) were using many relocations,
    causing startup latency plus per-process memory usage. Replace pointers with
    table indices, shrinking table size and elimninating relocations.

diff --git a/fc-glyphname/fc-glyphname.c b/fc-glyphname/fc-glyphname.c
index d4d0b99..b63ed24 100644
--- a/fc-glyphname/fc-glyphname.c
+++ b/fc-glyphname/fc-glyphname.c
@@ -217,15 +217,15 @@ insert (FcGlyphName *gn, FcGlyphName **table, FcChar32 h)
 static void
 dump (FcGlyphName * const *table, const char *name)
 {
-    int	i;
+    int	    i;
     
-    printf ("static const FcGlyphName	*%s[%d] = {\n", name, hash);
+    printf ("static const FcGlyphId %s[%d] = {\n", name, hash);
 
     for (i = 0; i < hash; i++)
 	if (table[i])
-	    printf ("(FcGlyphName *) &glyph%d,\n", rawindex(table[i]));
+	    printf ("    %d,\n", rawindex(table[i]));
 	else
-	    printf ("0,\n");
+	    printf ("    -1,\n");
     
     printf ("};\n");
 }
@@ -237,6 +237,7 @@ main (int argc, char **argv)
     char	line[1024];
     FILE	*f;
     int		i;
+    char	*type;
     
     i = 0;
     while (argv[i+1])
@@ -283,16 +284,27 @@ main (int argc, char **argv)
     printf ("#define FC_GLYPHNAME_HASH %u\n", hash);
     printf ("#define FC_GLYPHNAME_REHASH %u\n", rehash);
     printf ("#define FC_GLYPHNAME_MAXLEN %d\n\n", max_name_len);
+    if (nraw < 128)
+	type = "int8_t";
+    else if (nraw < 32768)
+	type = "int16_t";
+    else
+	type = "int32_t";
+    
+    printf ("typedef %s FcGlyphId;\n\n", type);
     
     /*
      * Dump out entries
      */
     
+    printf ("static const struct { const FcChar32 ucs; const FcChar8 name[%d]; } glyphs[%d] = {\n",
+	    max_name_len + 1, nraw);
+    
     for (i = 0; i < nraw; i++)
-	printf ("static const struct { const FcChar32 ucs; const FcChar8 name[%d]; }"
-	        " glyph%d = { 0x%lx, \"%s\" };\n",
-	        (int) strlen ((char *) raw[i]->name) + 1,
-		i, (unsigned long) raw[i]->ucs, raw[i]->name);
+	printf ("    { 0x%lx, \"%s\" },\n",
+		(unsigned long) raw[i]->ucs, raw[i]->name);
+
+    printf ("};\n");
 
     /*
      * Dump out name_to_ucs table
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index fb2e01b..c9c58c7 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -2304,12 +2304,12 @@ FcUcs4ToGlyphName (FcChar32 ucs4)
 {
     int		i = (int) (ucs4 % FC_GLYPHNAME_HASH);
     int		r = 0;
-    const FcGlyphName	*gn;
+    FcGlyphId	gn;
 
-    while ((gn = ucs_to_name[i]))
+    while ((gn = ucs_to_name[i]) != -1)
     {
-	if (gn->ucs == ucs4)
-	    return gn->name;
+	if (glyphs[gn].ucs == ucs4)
+	    return glyphs[gn].name;
 	if (!r) 
 	{
 	    r = (int) (ucs4 % FC_GLYPHNAME_REHASH);
@@ -2329,12 +2329,12 @@ FcGlyphNameToUcs4 (FcChar8 *name)
     FcChar32	h = FcHashGlyphName (name);
     int		i = (int) (h % FC_GLYPHNAME_HASH);
     int		r = 0;
-    const FcGlyphName	*gn;
+    FcGlyphId	gn;
 
-    while ((gn = name_to_ucs[i]))
+    while ((gn = name_to_ucs[i]) != -1)
     {
-	if (!strcmp ((char *) name, (char *) gn->name))
-	    return gn->ucs;
+	if (!strcmp ((char *) name, (char *) glyphs[gn].name))
+	    return glyphs[gn].ucs;
 	if (!r) 
 	{
 	    r = (int) (h % FC_GLYPHNAME_REHASH);
commit bc5e8adb4d05d1d03007951f46aaacc63c3b2197
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 09:41:00 2007 -0700

    Must not insert cache into hash table before completely validating.
    
    The cache was inserted into the hash table before the timestamps in the
    cache were verified; if that verification failed, an extra pointer to the
    now freed cache would be left in the hash table. FcFini would fail an
    assertion as a result.

diff --git a/src/fccache.c b/src/fccache.c
index c43609c..bd8db46 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -493,8 +493,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
     if (cache->magic != FC_CACHE_MAGIC_MMAP || 
 	cache->version < FC_CACHE_CONTENT_VERSION ||
 	cache->size != fd_stat->st_size ||
-	!FcCacheInsert (cache, fd_stat) ||
-	!FcCacheTimeValid (cache, dir_stat))
+	!FcCacheTimeValid (cache, dir_stat) ||
+	!FcCacheInsert (cache, fd_stat))
     {
 	if (allocated)
 	    free (cache);
commit e85789a99770dbd1a4abe9da3eadb355c19f5216
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 08:58:14 2007 -0700

    Place language name in constant array instead of pointer.
    
    Constant char array of 8 bytes is the same size as a pointer plus a short
    string, so this actually saves memory and eliminates a pile of relocations.

diff --git a/fc-lang/fc-lang.c b/fc-lang/fc-lang.c
index 92a62ce..989a823 100644
--- a/fc-lang/fc-lang.c
+++ b/fc-lang/fc-lang.c
@@ -377,7 +377,7 @@ main (int argc, char **argv)
 	if (j < 0)
 	    j = i;
 
-	printf ("    { (FcChar8 *) \"%s\", "
+	printf ("    { \"%s\", "
 		" { FC_REF_CONSTANT, %d, OFF(%d,%d), NUM(%d,%d) } }, /* %d */\n",
 		langs[i],
 		sets[j]->num, i, off[j], i, off[j], i);
diff --git a/src/fclang.c b/src/fclang.c
index de08622..13f0ca2 100644
--- a/src/fclang.c
+++ b/src/fclang.c
@@ -25,7 +25,7 @@
 #include "fcint.h"
 
 typedef struct {
-    const FcChar8	*lang;
+    const FcChar8    	lang[8];
     const FcCharSet	charset;
 } FcLangCharSet;
 
commit 26437d4924b0f53f03915e5f3616992eb1fb72e7
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 08:56:42 2007 -0700

    FcConfigParseAndLoad doc was missing the last param.
    
    Typo lost the last param to this function.

diff --git a/doc/fcconfig.fncs b/doc/fcconfig.fncs
index e29c392..0ee391e 100644
--- a/doc/fcconfig.fncs
+++ b/doc/fcconfig.fncs
@@ -282,7 +282,7 @@ FC_CONFIG_DIR environment variable.
 @FUNC@		FcConfigParseAndLoad
 @TYPE1@		FcConfig *			@ARG1@		config
 @TYPE2@		const FcChar8 *			@ARG2@		file
- at TYPE2@		FcBool%				@ARG3@		complain
+ at TYPE3@		FcBool%				@ARG3@		complain
 @PURPOSE@	load a configuration file
 @DESC@
 Walks the configuration in 'file' and constructs the internal representation
commit 07e646cc8422bda778ecf1c084129556a39a0f2a
Author: Mike FABIAN <mfabian at suse.de>
Date:   Thu Oct 18 05:44:28 2007 -0700

    Avoid crashes if config files contain junk.
    
    If ~/.fonts.conf contains:
    
      <edit mode="assign_replace" name="spacing">
         <int>mono</int>
           </edit>
    
    fontconfig crashes:
    
        mfabian at magellan:~$ fc-match sans
            Fontconfig error: "~/.fonts.conf", line 46: "mono": not a valid
    	integer
    	    セグメンテーション違反です (core dumped)
    	        mfabian at magellan:~$
    
    Of course the above is nonsense, “mono” is no valid integer indeed.
    
    But I think nevertheless fontconfig should not crash in that case.
    
    The problem was caused by partially truncated expression trees caused by
    parse errors -- typechecking these walked the tree without verifying the
    integrity of the structure. Of course, the whole tree will be discarded
    shortly after being loaded as it contained an error.

diff --git a/src/fcxml.c b/src/fcxml.c
index 156599c..3b08fea 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -558,6 +558,10 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
     const FcObjectType	*o;
     const FcConstant	*c;
     
+    /* If parsing the expression failed, some nodes may be NULL */
+    if (!expr)
+	return;
+
     switch (expr->op) {
     case FcOpInteger:
     case FcOpDouble:
commit fa9a7448d83da498b3494fd0ff7d756569f94425
Author: Hideki Yamane <henrich at iijmio-mail.jp>
Date:   Thu Oct 18 05:17:36 2007 -0700

    Handle Japanese fonts better. (debian bug #435971)
    
    Add some commonly available Japanese fonts to the standard aliases.

diff --git a/conf.d/65-nonlatin.conf b/conf.d/65-nonlatin.conf
index f8dbb64..2d2cf2f 100644
--- a/conf.d/65-nonlatin.conf
+++ b/conf.d/65-nonlatin.conf
@@ -6,6 +6,9 @@
 		<prefer>
 			<family>Frank Ruehl</family>
 			<family>MgOpen Canonica</family>
+			<family>Sazanami Mincho</family>
+			<family>IPAMonaMincho</family>
+			<family>IPAMincho</family>
 			<family>Kochi Mincho</family>
 			<family>AR PL SungtiL GB</family>
 			<family>AR PL Mingti2L Big5</family>
@@ -18,6 +21,10 @@
 		<prefer>
 			<family>Nachlieli</family>
 			<family>MgOpen Modata</family>
+			<family>VL Gothic</family>
+			<family>IPAMonaGothic</family>
+			<family>IPAGothic</family>
+			<family>Sazanami Gothic</family>
 			<family>Kochi Gothic</family>
 			<family>AR PL KaitiM GB</family>
 			<family>AR PL KaitiM Big5</family>
@@ -30,6 +37,10 @@
 		<family>monospace</family>
 		<prefer>
 			<family>Miriam Mono</family>
+			<family>VL Gothic</family>
+			<family>IPAMonaGothic</family>
+			<family>IPAGothic</family>
+			<family>Sazanami Gothic</family>
 			<family>Kochi Gothic</family>
 			<family>AR PL KaitiM GB</family>
 			<family>Baekmuk Dotum</family>
commit 2a3e3c442de4c675e28e754dea0fe2f7f0686ade
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 05:05:59 2007 -0700

    Have fc-cache remove invalid cache files from cache directories.
    
    Old cache file versions, or corrupted cache files should be removed when
    cleaning cache directories with fc-cache. This only affects filenames which
    match the fontconfig cache file format, so other files will be left alone.

diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index dda40c1..b4d4988 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -301,29 +301,31 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
 	    ret = FcFalse;
 	    break;
 	}
+	remove = FcFalse;
 	cache = FcDirCacheLoadFile (file_name, &file_stat);
 	if (!cache)
 	{
-	    fprintf (stderr, "%s: invalid cache file: %s\n", dir, ent->d_name);
-	    FcStrFree (file_name);
-	    ret = FcFalse;
-	    continue;
-	}
-	target_dir = FcCacheDir (cache);
-	remove = FcFalse;
-	if (stat ((char *) target_dir, &target_stat) < 0)
-	{
 	    if (verbose)
-		printf ("%s: %s: missing directory: %s \n",
-			dir, ent->d_name, target_dir);
+		printf ("%s: invalid cache file: %s\n", dir, ent->d_name);
 	    remove = FcTrue;
 	}
-	else if (target_stat.st_mtime > file_stat.st_mtime)
+	else
 	{
-	    if (verbose)
-		printf ("%s: %s: cache outdated: %s\n",
-			dir, ent->d_name, target_dir);
-	    remove = FcTrue;
+	    target_dir = FcCacheDir (cache);
+	    if (stat ((char *) target_dir, &target_stat) < 0)
+	    {
+		if (verbose)
+		    printf ("%s: %s: missing directory: %s \n",
+			    dir, ent->d_name, target_dir);
+		remove = FcTrue;
+	    }
+	    else if (target_stat.st_mtime > file_stat.st_mtime)
+	    {
+		if (verbose)
+		    printf ("%s: %s: cache outdated: %s\n",
+			    dir, ent->d_name, target_dir);
+		remove = FcTrue;
+	    }
 	}
 	if (remove)
 	{
commit 238489030a64fa883f8f9fc3d73247b7f7257899
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 05:04:39 2007 -0700

    Don't use X_OK bit when checking for writable directories (bug 12438)
    
    Some mingw versions have broken X_OK checking; instead of trying to work
    around this in a system-depedent manner, simply don't bother checking for
    X_OK along with W_OK as such cases are expected to be mistakes, and not
    sensible access control.

diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index 531e8fb..dda40c1 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -264,7 +264,7 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
 	fprintf (stderr, "%s: out of memory\n", dir);
 	return FcFalse;
     }
-    if (access ((char *) dir, W_OK|X_OK) != 0)
+    if (access ((char *) dir, W_OK) != 0)
     {
 	if (verbose)
 	    printf ("%s: not cleaning %s cache directory\n", dir,
diff --git a/src/fccache.c b/src/fccache.c
index a6b532f..c43609c 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -727,7 +727,7 @@ FcMakeDirectory (const FcChar8 *dir)
     parent = FcStrDirname (dir);
     if (!parent)
 	return FcFalse;
-    if (access ((char *) parent, W_OK|X_OK) == 0)
+    if (access ((char *) parent, F_OK) == 0)
 	ret = mkdir ((char *) dir, 0777) == 0;
     else if (access ((char *) parent, F_OK) == -1)
 	ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0777) == 0);
@@ -760,7 +760,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     if (!list)
 	return FcFalse;
     while ((test_dir = FcStrListNext (list))) {
-	if (access ((char *) test_dir, W_OK|X_OK) == 0)
+	if (access ((char *) test_dir, W_OK) == 0)
 	{
 	    cache_dir = test_dir;
 	    break;
commit 2b0d3d8af5a83604972e4e0fe80802e448d6dd11
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 05:01:41 2007 -0700

    Verbose message about cleaning directories was imprecise
    
    Non-existent directories are now described as 'non-existent' instead of
    'unwritable'.

diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index 7de952d..531e8fb 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -267,7 +267,8 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
     if (access ((char *) dir, W_OK|X_OK) != 0)
     {
 	if (verbose)
-	    printf ("%s: not cleaning unwritable cache directory\n", dir);
+	    printf ("%s: not cleaning %s cache directory\n", dir,
+		    access ((char *) dir, F_OK) == 0 ? "unwritable" : "non-existent");
 	FcStrFree (dir_base);
 	return FcTrue;
     }
commit 50124d1e484b84796abb7d8a6c1995edaff23e80
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 04:58:31 2007 -0700

    Improve verbose messages from fc-cache.
    
    fc-cache would say 'skipping: %d fonts, %d dirs' or 'caching: %d fonts, %d
    dirs', which could easily mislead the user. Add 'existing cache is valid' or
    'new cache contents' to these messages to explain what it is doing.

diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index 0415b54..7de952d 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -201,13 +201,13 @@ scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force,
 	if (was_valid)
 	{
 	    if (verbose)
-		printf ("skipping, %d fonts, %d dirs\n",
+		printf ("skipping, existing cache is valid: %d fonts, %d dirs\n",
 			FcCacheNumFont (cache), FcCacheNumSubdir (cache));
 	}
 	else
 	{
 	    if (verbose)
-		printf ("caching, %d fonts, %d dirs\n", 
+		printf ("caching, new cache contents: %d fonts, %d dirs\n", 
 			FcCacheNumFont (cache), FcCacheNumSubdir (cache));
 
 	    if (!FcDirCacheValid (dir))
commit e12f718f65fc874e9170761f670930124815663e
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 04:54:51 2007 -0700

    Remove unneeded call to access(2) in fc-cache.
    
    This call was followed by a call to stat(2) which provided the necessary
    information. This call to access(2) was necessary when cache files were
    stored in the font directory as that would check for write permission
    correctly.

diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index acaa8ba..0415b54 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -153,35 +153,23 @@ scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force,
 	    continue;
 	}
 
-	if (access ((char *) dir, W_OK) < 0)
+	if (stat ((char *) dir, &statb) == -1)
 	{
 	    switch (errno) {
 	    case ENOENT:
 	    case ENOTDIR:
 		if (verbose)
 		    printf ("skipping, no such directory\n");
-		continue;
-	    case EACCES:
-	    case EROFS:
-		/* That's ok, caches go to /var anyway. */
-		/* Ideally we'd do an access on the hashed_name. */
-		/* But we hid that behind an abstraction barrier. */
 		break;
 	    default:
 		fprintf (stderr, "\"%s\": ", dir);
 		perror ("");
 		ret++;
-
-		continue;
+		break;
 	    }
-	}
-	if (stat ((char *) dir, &statb) == -1)
-	{
-	    fprintf (stderr, "\"%s\": ", dir);
-	    perror ("");
-	    ret++;
 	    continue;
 	}
+
 	if (!S_ISDIR (statb.st_mode))
 	{
 	    fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
commit f7da903d370dcf662a301930b003485f25db618f
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 04:31:33 2007 -0700

    Make FC_FULLNAME include all fullname entries, elide nothing. [bug 12827]
    
    The old policy of eliding fullname entries which matched FC_FAMILY or
    FC_FAMILY + FC_STYLE meant that applications could not know what the
    font foundry set as the fullname of the font. Hiding information is not
    helpful.

diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index c79ab3b..fb2e01b 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1330,70 +1330,6 @@ FcFreeTypeQueryFace (const FT_Face  face,
 	++nfamily;
     }
 
-    /*
-     * Walk through FC_FULLNAME entries eliding those in FC_FAMILY
-     * or which are simply a FC_FAMILY and FC_STYLE glued together
-     */
-    {
-	int	fn, fa;
-	FcChar8	*full;
-	FcChar8	*fam;
-	FcChar8	*style;
-
-	for (fn = 0; FcPatternGetString (pat, FC_FULLNAME, fn, &full) == FcResultMatch; fn++)
-	{
-	    FcBool  remove = FcFalse;
-	    /*
-	     * Check each family
-	     */
-	    for (fa = 0; !remove && 
-		 FcPatternGetString (pat, FC_FAMILY, 
-				     fa, &fam) == FcResultMatch;
-		 fa++)
-	    {
-		/*
-		 * for exact match
-		 */
-		if (!FcStrCmpIgnoreBlanksAndCase (full, fam))
-		{
-		    remove = FcTrue;
-		    break;
-		}
-		/*
-		 * If the family is in the full name, check the
-		 * combination of this family with every style
-		 */
-		if (!FcStrContainsIgnoreBlanksAndCase (full, fam))
-		    continue;
-		for (st = 0; !remove && 
-		     FcPatternGetString (pat, FC_STYLE, 
-					 st, &style) == FcResultMatch;
-		     st++)
-		{
-		    FcChar8	*both = FcStrPlus (fam, style);
-
-		    if (both)
-		    {
-			if (FcStrCmpIgnoreBlanksAndCase (full, both) == 0)
-			    remove = FcTrue;
-			free (both);
-		    }
-		}
-	    }
-	    if (remove)
-	    {
-		FcPatternRemove (pat, FC_FULLNAME, fn);
-		FcPatternRemove (pat, FC_FULLNAMELANG, fn);
-		fn--;
-		nfullname--;
-		nfullname_lang--;
-	    }
-	}
-	if (FcDebug () & FC_DBG_SCANV)
-	    for (fn = 0; FcPatternGetString (pat, FC_FULLNAME, fn, &full) == FcResultMatch; fn++)
-		printf ("Saving unique fullname %s\n", full);
-    }
-
     if (!FcPatternAddString (pat, FC_FILE, file))
 	goto bail1;
 
commit 144ca878311af885db820a35db31563ba87ee6ad
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 04:29:13 2007 -0700

    Comment about mmaping cache files was misleading.

diff --git a/src/fccache.c b/src/fccache.c
index 42c7082..a6b532f 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -454,7 +454,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
     if (cache)
 	return cache;
     /*
-     * For small cache files, just read them into memory
+     * Lage cache files are mmap'ed, smaller cache files are read. This
+     * balances the system cost of mmap against per-process memory usage.
      */
     if (fd_stat->st_size >= FC_CACHE_MIN_MMAP)
     {
commit db6f19f13b1719617c54a1658b8faa31da56e1d4
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 04:13:51 2007 -0700

    Store font directory mtime in cache file.
    
    Instead of relying on mtime ordering between a directory and its associated
    cache file, write the directory mtime into the cache file itself. This makes
    cache file checks more reliable across file systems.
    
    This change is made in a way that old programs can use new cache files, but
    new programs will need new cache files.

diff --git a/fc-arch/fcarch.tmpl.h b/fc-arch/fcarch.tmpl.h
index 0843a64..96dccb4 100644
--- a/fc-arch/fcarch.tmpl.h
+++ b/fc-arch/fcarch.tmpl.h
@@ -29,10 +29,10 @@
 @@@ use something reasonable and don't include any spaces
 @@@
 @@@ name    endian   char     char*    int      intptr_t Pattern  EltPtr   Elt *    Elt      ObjPtr   VLPtr    Value    Binding  VL *     CharSet  Leaf**   Char16 * Char16   Leaf     Char32   Cache
-x86	    78563412_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_0000000c_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_0000001c
-x86-64	    78563412_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000030
-ppc	    12345678_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_00000010_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_0000001c
-ppc64	    12345678_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000030
-m68k	    12345678_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_0000000c_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_0000001c
-mipsel	    78563412_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_00000010_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_0000001c
-sparc64     12345678_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000030
+x86	    78563412_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_0000000c_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_00000020
+x86-64	    78563412_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000038
+ppc	    12345678_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_00000010_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_00000020
+ppc64	    12345678_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000038
+m68k	    12345678_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_0000000c_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_00000020
+mipsel	    78563412_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_00000010_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_00000020
+sparc64     12345678_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000038
diff --git a/src/fccache.c b/src/fccache.c
index 9e8819c..42c7082 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -47,7 +47,7 @@ struct MD5Context {
 };
 
 static void MD5Init(struct MD5Context *ctx);
-static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len);
+static void MD5Update(struct MD5Context *ctx, const unsigned char *buf, unsigned len);
 static void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
 static void MD5Transform(FcChar32 buf[4], FcChar32 in[16]);
 
@@ -67,7 +67,7 @@ FcDirCacheBasename (const FcChar8 * dir, FcChar8 cache_base[CACHEBASE_LEN])
     struct MD5Context 	ctx;
 
     MD5Init (&ctx);
-    MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir));
+    MD5Update (&ctx, (const unsigned char *)dir, strlen ((const char *) dir));
 
     MD5Final (hash, &ctx);
 
@@ -136,7 +136,8 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
  */
 static FcBool
 FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, 
-		   FcBool (*callback) (int fd, struct stat *stat, void *closure),
+		   FcBool (*callback) (int fd, struct stat *fd_stat,
+				       struct stat *dir_stat, void *closure),
 		   void *closure, FcChar8 **cache_file_ret)
 {
     int		fd = -1;
@@ -162,20 +163,16 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
 	    break;
         fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
         if (fd >= 0) {
-	    if (dir_stat.st_mtime <= file_stat.st_mtime)
+	    ret = (*callback) (fd, &file_stat, &dir_stat, closure);
+	    close (fd);
+	    if (ret)
 	    {
-		ret = (*callback) (fd, &file_stat, closure);
-		if (ret)
-		{
-		    if (cache_file_ret)
-			*cache_file_ret = cache_hashed;
-		    else
-			FcStrFree (cache_hashed);
-		    close (fd);
-		    break;
-		}
+		if (cache_file_ret)
+		    *cache_file_ret = cache_hashed;
+		else
+		    FcStrFree (cache_hashed);
+		break;
 	    }
-	    close (fd);
 	}
     	FcStrFree (cache_hashed);
     }
@@ -425,11 +422,28 @@ FcCacheFini (void)
     assert (fcCacheMaxLevel == 0);
 }
 
+static FcBool
+FcCacheTimeValid (FcCache *cache, struct stat *dir_stat)
+{
+    struct stat	dir_static;
+
+    if (!dir_stat)
+    {
+	if (stat ((const char *) FcCacheDir (cache), &dir_static) < 0)
+	    return FcFalse;
+	dir_stat = &dir_static;
+    }
+    if (FcDebug () & FC_DBG_CACHE)
+	printf ("FcCacheTimeValid dir \"%s\" cache time %d dir time %d\n",
+		FcCacheDir (cache), cache->mtime, (int) dir_stat->st_mtime);
+    return cache->mtime == (int) dir_stat->st_mtime;
+}
+
 /*
  * Map a cache file into memory
  */
 static FcCache *
-FcDirCacheMapFd (int fd, struct stat *fd_stat)
+FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
 {
     FcCache	*cache;
     FcBool	allocated = FcFalse;
@@ -478,7 +492,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat)
     if (cache->magic != FC_CACHE_MAGIC_MMAP || 
 	cache->version < FC_CACHE_CONTENT_VERSION ||
 	cache->size != fd_stat->st_size ||
-	!FcCacheInsert (cache, fd_stat))
+	!FcCacheInsert (cache, fd_stat) ||
+	!FcCacheTimeValid (cache, dir_stat))
     {
 	if (allocated)
 	    free (cache);
@@ -516,9 +531,9 @@ FcDirCacheUnload (FcCache *cache)
 }
 
 static FcBool
-FcDirCacheMapHelper (int fd, struct stat *fd_stat, void *closure)
+FcDirCacheMapHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
 {
-    FcCache *cache = FcDirCacheMapFd (fd, fd_stat);
+    FcCache *cache = FcDirCacheMapFd (fd, fd_stat, dir_stat);
 
     if (!cache)
 	return FcFalse;
@@ -547,7 +562,7 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
     fd = FcDirCacheOpenFile (cache_file, file_stat);
     if (fd < 0)
 	return NULL;
-    cache = FcDirCacheMapFd (fd, file_stat);
+    cache = FcDirCacheMapFd (fd, file_stat, NULL);
     close (fd);
     return cache;
 }
@@ -557,7 +572,7 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
  * the magic number and the size field
  */
 static FcBool
-FcDirCacheValidateHelper (int fd, struct stat *fd_stat, void *closure)
+FcDirCacheValidateHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
 {
     FcBool  ret = FcTrue;
     FcCache	c;
@@ -570,6 +585,8 @@ FcDirCacheValidateHelper (int fd, struct stat *fd_stat, void *closure)
 	ret = FcFalse;
     else if (fd_stat->st_size != c.size)
 	ret = FcFalse;
+    else if (c.mtime != (int) dir_stat->st_mtime)
+	ret = FcFalse;
     return ret;
 }
 
@@ -597,7 +614,7 @@ FcDirCacheValid (const FcChar8 *dir)
  * Build a cache structure from the given contents
  */
 FcCache *
-FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
+FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcStrSet *dirs)
 {
     FcSerialize	*serialize = FcSerializeCreate ();
     FcCache *cache;
@@ -645,6 +662,7 @@ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
     cache->magic = FC_CACHE_MAGIC_ALLOC;
     cache->version = FC_CACHE_CONTENT_VERSION;
     cache->size = serialize->size;
+    cache->mtime = (int) dir_stat->st_mtime;
 
     /*
      * Serialize directory name
@@ -931,7 +949,7 @@ static void MD5Init(struct MD5Context *ctx)
  * Update context to reflect the concatenation of another buffer full
  * of bytes.
  */
-static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len)
+static void MD5Update(struct MD5Context *ctx, const unsigned char *buf, unsigned len)
 {
     FcChar32 t;
 
diff --git a/src/fcdir.c b/src/fcdir.c
index e9e9d19..48755de 100644
--- a/src/fcdir.c
+++ b/src/fcdir.c
@@ -146,6 +146,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
     int			i;
     FcBlanks		*blanks = FcConfigGetBlanks (config);
     FcCache		*cache = NULL;
+    struct stat		dir_stat;
 
     if (FcDebug () & FC_DBG_FONTSET)
     	printf ("cache scan dir %s\n", dir);
@@ -174,6 +175,11 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
 	    ret = FcFalse;
 	goto bail_1;
     }
+    if (stat ((char *) dir, &dir_stat) < 0)
+    {
+	ret = FcFalse;
+	goto bail_1;
+    }
 
     set = FcFontSetCreate();
     if (!set) 
@@ -218,7 +224,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
     /*
      * Build the cache object
      */
-    cache = FcDirCacheBuild (set, dir, dirs);
+    cache = FcDirCacheBuild (set, dir, &dir_stat, dirs);
     if (!cache)
 	goto bail3;
     
diff --git a/src/fcint.h b/src/fcint.h
index 4ab4a74..73bf875 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -322,6 +322,7 @@ struct _FcCache {
     intptr_t	dirs;		    /* offset to subdirs */
     int		dirs_count;	    /* number of subdir strings */
     intptr_t	set;		    /* offset to font set */
+    int		mtime;		    /* low bits of directory mtime */
 };
 
 #undef FcCacheDir
@@ -408,7 +409,7 @@ typedef struct _FcCaseFold {
 
 #define FC_CACHE_MAGIC_MMAP	    0xFC02FC04
 #define FC_CACHE_MAGIC_ALLOC	    0xFC02FC05
-#define FC_CACHE_CONTENT_VERSION    1
+#define FC_CACHE_CONTENT_VERSION    2
 
 struct _FcAtomic {
     FcChar8	*file;		/* original file name */
@@ -503,7 +504,7 @@ FcPrivate FcCache *
 FcDirCacheScan (const FcChar8 *dir, FcConfig *config);
 
 FcPrivate FcCache *
-FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs);
+FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcStrSet *dirs);
 
 FcPrivate FcBool
 FcDirCacheWrite (FcCache *cache, FcConfig *config);
commit 00268a50e8b99e80ff25ee2a77a925398f89693f
Author: Keith Packard <keithp at koto.keithp.com>
Date:   Thu Oct 18 03:52:29 2007 -0700

    Fix ChangeLog generation to avoid circular make dependency

diff --git a/Makefile.am b/Makefile.am
index 88e55af..e053902 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -66,12 +66,9 @@ MAINTAINERCLEANFILES += ChangeLog
 
 EXTRA_DIST += ChangeLog
 
-ChangeLog: $(srcdir)/ChangeLog
-
-$(srcdir)/ChangeLog:
-	@if test -d "$(srcdir)/.git"; then \
-	  (cd "$(srcdir)" && \
-	  ./missing --run git-log --stat) | fmt --split-only > $@.tmp \
+ChangeLog:
+	if test -d "$(srcdir)/.git"; then \
+	  (GIT_DIR=$(top_srcdir)/.git ./missing --run git-log --stat) | fmt --split-only > $@.tmp \
 	  && mv -f $@.tmp $@ \
 	  || ($(RM) $@.tmp; \
 	      echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
@@ -82,7 +79,7 @@ $(srcdir)/ChangeLog:
 	  echo A git checkout and git-log is required to generate this file >> $@); \
 	fi
 
-.PHONY: ChangeLog $(srcdir)/ChangeLog
+.PHONY: ChangeLog
 
 install-data-local:
 	$(mkinstalldirs) $(DESTDIR)$(configdir) $(DESTDIR)$(fc_cachedir)


More information about the Fontconfig mailing list