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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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 -@TYPE2@ FcBool% @ARG3@ complain +@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@xxxxxxx> 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@magellan:~$ fc-match sans Fontconfig error: "~/.fonts.conf", line 46: "mono": not a valid integer ã?»ã?°ã?¡ã?³ã??ã?¼ã?·ã?§ã?³é??å??ã?§ã?? (core dumped) mfabian@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@xxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> 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)
_______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/fontconfig