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 *config, char *program, FcBool force, FcBool 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 *config, char *program, FcBool force, FcBool 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 *config, char *program, FcBool force, FcBool 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 *config, char *program, FcBool force, FcBool 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 *config, char *program, FcBool force, FcBool 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 *ctx, unsigned char *buf, unsigned len); 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 FcChar8 *dir, off_t *size) 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; + return ret; } -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 -} - -/* 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, FcStrSet * dirs, 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 *config) 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 *serialize, const FcCharSet *cs) 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; - *leaf_serialized = *leaf; - leaves_serialized[i] = FcPtrToOffset (leaves_serialized, - leaf_serialized); - numbers_serialized[i] = numbers[i]; + + 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++) + { + 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 @@ -455,6 +459,11 @@ struct _FcConfig { * match preferrentially */ 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 @@ -525,10 +534,6 @@ FcBool 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_Char *name) 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: