Rewrite global cache handling code in fontconfig to eliminate per-file
syscalls
This commit is contained in:
parent
23cd70c4ef
commit
327a7fd491
|
@ -191,7 +191,7 @@ typedef enum { FcEndianBig, FcEndianLittle } FcEndian;
|
|||
|
||||
typedef struct _FcConfig FcConfig;
|
||||
|
||||
typedef struct _FcFileCache FcFileCache;
|
||||
typedef struct _FcGlobalCache FcFileCache;
|
||||
|
||||
typedef struct _FcBlanks FcBlanks;
|
||||
|
||||
|
@ -365,9 +365,6 @@ FcDirScan (FcFontSet *set,
|
|||
FcBool
|
||||
FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
|
||||
|
||||
FcBool
|
||||
FcDirCacheValid (const FcChar8 *dir);
|
||||
|
||||
/* fcfreetype.c */
|
||||
FcPattern *
|
||||
FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count);
|
||||
|
|
1014
src/fccache.c
1014
src/fccache.c
File diff suppressed because it is too large
Load Diff
23
src/fccfg.c
23
src/fccfg.c
|
@ -171,20 +171,20 @@ FcConfigDestroy (FcConfig *config)
|
|||
FcBool
|
||||
FcConfigBuildFonts (FcConfig *config)
|
||||
{
|
||||
FcFontSet *fonts;
|
||||
FcFileCache *cache;
|
||||
FcStrList *list;
|
||||
FcChar8 *dir;
|
||||
FcFontSet *fonts;
|
||||
FcGlobalCache *cache;
|
||||
FcStrList *list;
|
||||
FcChar8 *dir;
|
||||
|
||||
fonts = FcFontSetCreate ();
|
||||
if (!fonts)
|
||||
goto bail0;
|
||||
|
||||
cache = FcFileCacheCreate ();
|
||||
cache = FcGlobalCacheCreate ();
|
||||
if (!cache)
|
||||
goto bail1;
|
||||
|
||||
FcFileCacheLoad (cache, config->cache);
|
||||
FcGlobalCacheLoad (cache, config->cache);
|
||||
|
||||
list = FcConfigGetFontDirs (config);
|
||||
if (!list)
|
||||
|
@ -202,8 +202,8 @@ FcConfigBuildFonts (FcConfig *config)
|
|||
if (FcDebug () & FC_DBG_FONTSET)
|
||||
FcFontSetPrint (fonts);
|
||||
|
||||
FcFileCacheSave (cache, config->cache);
|
||||
FcFileCacheDestroy (cache);
|
||||
FcGlobalCacheSave (cache, config->cache);
|
||||
FcGlobalCacheDestroy (cache);
|
||||
|
||||
FcConfigSetFonts (config, fonts, FcSetSystem);
|
||||
|
||||
|
@ -456,8 +456,6 @@ typedef struct _FcSubState {
|
|||
FcValueList *value;
|
||||
} FcSubState;
|
||||
|
||||
static const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 };
|
||||
|
||||
static FcValue
|
||||
FcConfigPromote (FcValue v, FcValue u)
|
||||
{
|
||||
|
@ -468,9 +466,8 @@ FcConfigPromote (FcValue v, FcValue u)
|
|||
}
|
||||
else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
|
||||
{
|
||||
v.u.m = FcMatrixCopy (&FcIdentityMatrix);
|
||||
if (v.u.m)
|
||||
v.type = FcTypeMatrix;
|
||||
v.u.m = &FcIdentityMatrix;
|
||||
v.type = FcTypeMatrix;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
|
183
src/fcdir.c
183
src/fcdir.c
|
@ -38,44 +38,71 @@ FcFileIsDir (const FcChar8 *file)
|
|||
FcBool
|
||||
FcFileScan (FcFontSet *set,
|
||||
FcStrSet *dirs,
|
||||
FcFileCache *cache,
|
||||
FcGlobalCache *cache,
|
||||
FcBlanks *blanks,
|
||||
const FcChar8 *file,
|
||||
FcBool force)
|
||||
{
|
||||
int id;
|
||||
FcChar8 *name;
|
||||
FcPattern *font;
|
||||
FcBool ret = FcTrue;
|
||||
FcBool isDir;
|
||||
int count;
|
||||
int id;
|
||||
FcChar8 *name;
|
||||
FcPattern *font;
|
||||
FcBool ret = FcTrue;
|
||||
FcBool isDir;
|
||||
int count = 0;
|
||||
FcGlobalCacheFile *cache_file;
|
||||
FcGlobalCacheDir *cache_dir;
|
||||
FcBool need_scan;
|
||||
|
||||
if (force)
|
||||
cache = 0;
|
||||
id = 0;
|
||||
do
|
||||
{
|
||||
if (!force && cache)
|
||||
name = FcFileCacheFind (cache, file, id, &count);
|
||||
else
|
||||
name = 0;
|
||||
if (name)
|
||||
need_scan = FcTrue;
|
||||
font = 0;
|
||||
/*
|
||||
* Check the cache
|
||||
*/
|
||||
if (cache)
|
||||
{
|
||||
/* "." means the file doesn't contain a font */
|
||||
if (FcStrCmp (name, FC_FONT_FILE_INVALID) == 0)
|
||||
font = 0;
|
||||
else if (FcStrCmp (name, FC_FONT_FILE_DIR) == 0)
|
||||
if ((cache_file = FcGlobalCacheFileGet (cache, file, id, &count)))
|
||||
{
|
||||
ret = FcStrSetAdd (dirs, file);
|
||||
font = 0;
|
||||
/*
|
||||
* Found a cache entry for the file
|
||||
*/
|
||||
if (FcGlobalCacheCheckTime (&cache_file->info))
|
||||
{
|
||||
name = cache_file->name;
|
||||
need_scan = FcFalse;
|
||||
FcGlobalCacheReferenced (cache, &cache_file->info);
|
||||
/* "." means the file doesn't contain a font */
|
||||
if (FcStrCmp (name, FC_FONT_FILE_INVALID) != 0)
|
||||
{
|
||||
font = FcNameParse (name);
|
||||
if (font)
|
||||
if (!FcPatternAddString (font, FC_FILE, file))
|
||||
ret = FcFalse;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if ((cache_dir = FcGlobalCacheDirGet (cache, file,
|
||||
strlen ((const char *) file),
|
||||
FcFalse)))
|
||||
{
|
||||
font = FcNameParse (name);
|
||||
if (font)
|
||||
if (!FcPatternAddString (font, FC_FILE, file))
|
||||
if (FcGlobalCacheCheckTime (&cache_dir->info))
|
||||
{
|
||||
font = 0;
|
||||
need_scan = FcFalse;
|
||||
FcGlobalCacheReferenced (cache, &cache_dir->info);
|
||||
if (!FcStrSetAdd (dirs, file))
|
||||
ret = FcFalse;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
/*
|
||||
* Nothing in the cache, scan the file
|
||||
*/
|
||||
if (need_scan)
|
||||
{
|
||||
if (FcDebug () & FC_DBG_SCAN)
|
||||
{
|
||||
|
@ -91,35 +118,24 @@ FcFileScan (FcFontSet *set,
|
|||
isDir = FcTrue;
|
||||
ret = FcStrSetAdd (dirs, file);
|
||||
}
|
||||
if (!force && cache)
|
||||
/*
|
||||
* Update the cache
|
||||
*/
|
||||
if (cache && font)
|
||||
{
|
||||
if (font)
|
||||
{
|
||||
FcChar8 *unparse;
|
||||
FcChar8 *unparse;
|
||||
|
||||
unparse = FcNameUnparse (font);
|
||||
if (unparse)
|
||||
{
|
||||
(void) FcFileCacheUpdate (cache, file, id, unparse);
|
||||
free (unparse);
|
||||
}
|
||||
}
|
||||
else
|
||||
unparse = FcNameUnparse (font);
|
||||
if (unparse)
|
||||
{
|
||||
if (isDir)
|
||||
{
|
||||
FcFileCacheUpdate (cache, file, id, (FcChar8 *)
|
||||
FC_FONT_FILE_DIR);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* negative cache files not containing fonts */
|
||||
FcFileCacheUpdate (cache, file, id, (FcChar8 *)
|
||||
FC_FONT_FILE_INVALID);
|
||||
}
|
||||
(void) FcGlobalCacheUpdate (cache, file, id, unparse);
|
||||
free (unparse);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Add the font
|
||||
*/
|
||||
if (font)
|
||||
{
|
||||
if (!FcFontSetAdd (set, font))
|
||||
|
@ -134,40 +150,37 @@ FcFileScan (FcFontSet *set,
|
|||
return ret;
|
||||
}
|
||||
|
||||
FcBool
|
||||
FcDirCacheValid (const FcChar8 *dir)
|
||||
{
|
||||
FcChar8 *path;
|
||||
FcBool ret;
|
||||
|
||||
path = (FcChar8 *) malloc (strlen ((const char *) dir) + 1 +
|
||||
strlen ((const char *) FC_DIR_CACHE_FILE) + 1);
|
||||
if (!path)
|
||||
return FcFalse;
|
||||
strcpy ((char *) path, (const char *) dir);
|
||||
strcat ((char *) path, (const char *) "/");
|
||||
strcat ((char *) path, (const char *) FC_DIR_CACHE_FILE);
|
||||
ret = FcFileCacheValid (path);
|
||||
free (path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define FC_MAX_FILE_LEN 4096
|
||||
|
||||
FcBool
|
||||
FcDirScan (FcFontSet *set,
|
||||
FcStrSet *dirs,
|
||||
FcFileCache *cache,
|
||||
FcGlobalCache *cache,
|
||||
FcBlanks *blanks,
|
||||
const FcChar8 *dir,
|
||||
FcBool force)
|
||||
{
|
||||
DIR *d;
|
||||
struct dirent *e;
|
||||
FcChar8 *file;
|
||||
FcChar8 *base;
|
||||
FcBool ret = FcTrue;
|
||||
DIR *d;
|
||||
struct dirent *e;
|
||||
FcChar8 *file;
|
||||
FcChar8 *base;
|
||||
FcBool ret = FcTrue;
|
||||
|
||||
if (!force)
|
||||
{
|
||||
/*
|
||||
* Check fonts.cache file
|
||||
*/
|
||||
if (FcDirCacheReadDir (set, dirs, dir))
|
||||
return FcTrue;
|
||||
|
||||
/*
|
||||
* Check ~/.fonts.cache file
|
||||
*/
|
||||
if (cache && FcGlobalCacheScanDir (set, dirs, cache, dir))
|
||||
return FcTrue;
|
||||
}
|
||||
|
||||
file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
|
||||
if (!file)
|
||||
return FcFalse;
|
||||
|
@ -175,18 +188,9 @@ FcDirScan (FcFontSet *set,
|
|||
strcpy ((char *) file, (char *) dir);
|
||||
strcat ((char *) file, "/");
|
||||
base = file + strlen ((char *) file);
|
||||
if (!force)
|
||||
{
|
||||
strcpy ((char *) base, FC_DIR_CACHE_FILE);
|
||||
|
||||
if (FcFileCacheReadDir (set, dirs, file))
|
||||
{
|
||||
free (file);
|
||||
return FcTrue;
|
||||
}
|
||||
}
|
||||
|
||||
d = opendir ((char *) dir);
|
||||
|
||||
if (!d)
|
||||
{
|
||||
free (file);
|
||||
|
@ -205,25 +209,14 @@ FcDirScan (FcFontSet *set,
|
|||
}
|
||||
free (file);
|
||||
closedir (d);
|
||||
if (ret && cache)
|
||||
FcGlobalCacheUpdate (cache, dir, 0, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FcBool
|
||||
FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
||||
{
|
||||
FcChar8 *file;
|
||||
FcChar8 *base;
|
||||
FcBool ret;
|
||||
|
||||
file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + 256 + 1);
|
||||
if (!file)
|
||||
return FcFalse;
|
||||
|
||||
strcpy ((char *) file, (char *) dir);
|
||||
strcat ((char *) file, "/");
|
||||
base = file + strlen ((char *) file);
|
||||
strcpy ((char *) base, FC_DIR_CACHE_FILE);
|
||||
ret = FcFileCacheWriteDir (set, dirs, file);
|
||||
free (file);
|
||||
return ret;
|
||||
return FcDirCacheWriteDir (set, dirs, dir);
|
||||
}
|
||||
|
|
124
src/fcint.h
124
src/fcint.h
|
@ -195,24 +195,53 @@ typedef struct _FcStrBuf {
|
|||
int size;
|
||||
} FcStrBuf;
|
||||
|
||||
typedef struct _FcFileCacheEnt {
|
||||
struct _FcFileCacheEnt *next;
|
||||
unsigned int hash;
|
||||
FcChar8 *file;
|
||||
int id;
|
||||
time_t time;
|
||||
FcChar8 *name;
|
||||
FcBool referenced;
|
||||
} FcFileCacheEnt;
|
||||
/*
|
||||
* The per-user ~/.fonts.cache file is loaded into
|
||||
* this data structure. Each directory gets a substructure
|
||||
* which is validated by comparing the directory timestamp with
|
||||
* that saved in the cache. When valid, the entire directory cache
|
||||
* can be immediately loaded without reading the directory. Otherwise,
|
||||
* the files are checked individually; updated files are loaded into the
|
||||
* cache which is then rewritten to the users home directory
|
||||
*/
|
||||
|
||||
#define FC_FILE_CACHE_HASH_SIZE 509
|
||||
#define FC_GLOBAL_CACHE_DIR_HASH_SIZE 37
|
||||
#define FC_GLOBAL_CACHE_FILE_HASH_SIZE 67
|
||||
|
||||
struct _FcFileCache {
|
||||
FcFileCacheEnt *ents[FC_FILE_CACHE_HASH_SIZE];
|
||||
FcBool updated;
|
||||
int entries;
|
||||
int referenced;
|
||||
};
|
||||
typedef struct _FcGlobalCacheInfo {
|
||||
unsigned int hash;
|
||||
FcChar8 *file;
|
||||
time_t time;
|
||||
FcBool referenced;
|
||||
} FcGlobalCacheInfo;
|
||||
|
||||
typedef struct _FcGlobalCacheFile {
|
||||
struct _FcGlobalCacheFile *next;
|
||||
FcGlobalCacheInfo info;
|
||||
int id;
|
||||
FcChar8 *name;
|
||||
} FcGlobalCacheFile;
|
||||
|
||||
typedef struct _FcGlobalCacheSubdir {
|
||||
struct _FcGlobalCacheSubdir *next;
|
||||
FcChar8 *file;
|
||||
} FcGlobalCacheSubdir;
|
||||
|
||||
typedef struct _FcGlobalCacheDir {
|
||||
struct _FcGlobalCacheDir *next;
|
||||
FcGlobalCacheInfo info;
|
||||
int len;
|
||||
FcGlobalCacheFile *ents[FC_GLOBAL_CACHE_FILE_HASH_SIZE];
|
||||
FcGlobalCacheSubdir *subdirs;
|
||||
} FcGlobalCacheDir;
|
||||
|
||||
typedef struct _FcGlobalCache {
|
||||
FcGlobalCacheDir *ents[FC_GLOBAL_CACHE_DIR_HASH_SIZE];
|
||||
FcBool updated;
|
||||
FcBool broken;
|
||||
int entries;
|
||||
int referenced;
|
||||
} FcGlobalCache;
|
||||
|
||||
struct _FcAtomic {
|
||||
FcChar8 *file; /* original file name */
|
||||
|
@ -284,40 +313,60 @@ typedef struct _FcCharMap FcCharMap;
|
|||
|
||||
/* fccache.c */
|
||||
|
||||
FcFileCache *
|
||||
FcFileCacheCreate (void);
|
||||
|
||||
FcChar8 *
|
||||
FcFileCacheFind (FcFileCache *cache,
|
||||
const FcChar8 *file,
|
||||
int id,
|
||||
int *count);
|
||||
FcGlobalCache *
|
||||
FcGlobalCacheCreate (void);
|
||||
|
||||
void
|
||||
FcFileCacheDestroy (FcFileCache *cache);
|
||||
FcGlobalCacheDestroy (FcGlobalCache *cache);
|
||||
|
||||
FcBool
|
||||
FcFileCacheValid (const FcChar8 *cache_file);
|
||||
FcGlobalCacheCheckTime (FcGlobalCacheInfo *info);
|
||||
|
||||
void
|
||||
FcFileCacheLoad (FcFileCache *cache,
|
||||
const FcChar8 *cache_file);
|
||||
FcGlobalCacheReferenced (FcGlobalCache *cache,
|
||||
FcGlobalCacheInfo *info);
|
||||
|
||||
FcGlobalCacheDir *
|
||||
FcGlobalCacheDirGet (FcGlobalCache *cache,
|
||||
const FcChar8 *dir,
|
||||
int len,
|
||||
FcBool create_missing);
|
||||
|
||||
FcBool
|
||||
FcFileCacheUpdate (FcFileCache *cache,
|
||||
const FcChar8 *file,
|
||||
int id,
|
||||
const FcChar8 *name);
|
||||
FcGlobalCacheScanDir (FcFontSet *set,
|
||||
FcStrSet *dirs,
|
||||
FcGlobalCache *cache,
|
||||
const FcChar8 *dir);
|
||||
|
||||
FcGlobalCacheFile *
|
||||
FcGlobalCacheFileGet (FcGlobalCache *cache,
|
||||
const FcChar8 *file,
|
||||
int id,
|
||||
int *count);
|
||||
|
||||
|
||||
void
|
||||
FcGlobalCacheLoad (FcGlobalCache *cache,
|
||||
const FcChar8 *cache_file);
|
||||
|
||||
FcBool
|
||||
FcFileCacheSave (FcFileCache *cache,
|
||||
const FcChar8 *cache_file);
|
||||
FcGlobalCacheUpdate (FcGlobalCache *cache,
|
||||
const FcChar8 *file,
|
||||
int id,
|
||||
const FcChar8 *name);
|
||||
|
||||
FcBool
|
||||
FcFileCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *cache_file);
|
||||
FcGlobalCacheSave (FcGlobalCache *cache,
|
||||
const FcChar8 *cache_file);
|
||||
|
||||
FcBool
|
||||
FcFileCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *cache_file);
|
||||
FcDirCacheValid (const FcChar8 *cache_file);
|
||||
|
||||
FcBool
|
||||
FcDirCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
|
||||
|
||||
FcBool
|
||||
FcDirCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
|
||||
|
||||
/* fccfg.c */
|
||||
|
||||
|
@ -523,6 +572,9 @@ FcPatternAddWithBinding (FcPattern *p,
|
|||
/* fcrender.c */
|
||||
|
||||
/* fcmatrix.c */
|
||||
|
||||
extern const FcMatrix FcIdentityMatrix;
|
||||
|
||||
void
|
||||
FcMatrixFree (FcMatrix *mat);
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <ctype.h>
|
||||
#include "fcint.h"
|
||||
|
||||
const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 };
|
||||
|
||||
FcMatrix *
|
||||
FcMatrixCopy (const FcMatrix *mat)
|
||||
{
|
||||
|
@ -44,8 +46,11 @@ FcMatrixCopy (const FcMatrix *mat)
|
|||
void
|
||||
FcMatrixFree (FcMatrix *mat)
|
||||
{
|
||||
FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix));
|
||||
free (mat);
|
||||
if (mat != &FcIdentityMatrix)
|
||||
{
|
||||
FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix));
|
||||
free (mat);
|
||||
}
|
||||
}
|
||||
|
||||
FcBool
|
||||
|
|
Loading…
Reference in New Issue