Pass directory information around in FcCache structure. Freeze charsets.
Instead of passing directory information around in separate variables, collect it all in an FcCache structure. Numerous internal and tool interfaces changed as a result of this. Charsets are now pre-frozen before being serialized. This causes them to share across multiple fonts in the same cache.
This commit is contained in:
parent
aec8c90b45
commit
bc5e487f2a
|
@ -128,15 +128,17 @@ nsubdirs (FcStrSet *set)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool really_force, FcBool verbose)
|
scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
const FcChar8 *dir;
|
const FcChar8 *dir;
|
||||||
FcFontSet *set;
|
FcFontSet *set;
|
||||||
FcStrSet *subdirs;
|
FcStrSet *subdirs;
|
||||||
FcStrList *sublist;
|
FcStrList *sublist;
|
||||||
|
FcCache *cache;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
FcBool was_valid;
|
FcBool was_valid;
|
||||||
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now scan all of the directories into separate databases
|
* Now scan all of the directories into separate databases
|
||||||
|
@ -146,7 +148,7 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
printf ("%s: \"%s\": ", program, dir);
|
printf ("%s: ", dir);
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,22 +166,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
set = FcFontSetCreate ();
|
|
||||||
if (!set)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: Can't create font set\n", dir);
|
|
||||||
ret++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
subdirs = FcStrSetCreate ();
|
|
||||||
if (!subdirs)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: Can't create directory set\n", dir);
|
|
||||||
ret++;
|
|
||||||
FcFontSetDestroy (set);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access ((char *) dir, W_OK) < 0)
|
if (access ((char *) dir, W_OK) < 0)
|
||||||
{
|
{
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
|
@ -187,8 +173,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
|
||||||
case ENOTDIR:
|
case ENOTDIR:
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf ("skipping, no such directory\n");
|
printf ("skipping, no such directory\n");
|
||||||
FcFontSetDestroy (set);
|
|
||||||
FcStrSetDestroy (subdirs);
|
|
||||||
continue;
|
continue;
|
||||||
case EACCES:
|
case EACCES:
|
||||||
case EROFS:
|
case EROFS:
|
||||||
|
@ -201,8 +185,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
|
||||||
perror ("");
|
perror ("");
|
||||||
ret++;
|
ret++;
|
||||||
|
|
||||||
FcFontSetDestroy (set);
|
|
||||||
FcStrSetDestroy (subdirs);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,44 +192,50 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
|
||||||
{
|
{
|
||||||
fprintf (stderr, "\"%s\": ", dir);
|
fprintf (stderr, "\"%s\": ", dir);
|
||||||
perror ("");
|
perror ("");
|
||||||
FcFontSetDestroy (set);
|
|
||||||
FcStrSetDestroy (subdirs);
|
|
||||||
ret++;
|
ret++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!S_ISDIR (statb.st_mode))
|
if (!S_ISDIR (statb.st_mode))
|
||||||
{
|
{
|
||||||
fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
|
fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
|
||||||
FcFontSetDestroy (set);
|
|
||||||
FcStrSetDestroy (subdirs);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (really_force)
|
if (really_force)
|
||||||
FcDirCacheUnlink (dir, config);
|
FcDirCacheUnlink (dir, config);
|
||||||
|
|
||||||
if (!force)
|
cache = NULL;
|
||||||
was_valid = FcDirCacheValid (dir);
|
was_valid = FcFalse;
|
||||||
|
if (!force) {
|
||||||
if (!FcDirScanConfig (set, subdirs, FcConfigGetBlanks (config), dir, force, config))
|
cache = FcDirCacheLoad (dir, config, NULL);
|
||||||
{
|
if (cache)
|
||||||
fprintf (stderr, "%s: error scanning\n", dir);
|
was_valid = FcTrue;
|
||||||
FcFontSetDestroy (set);
|
|
||||||
FcStrSetDestroy (subdirs);
|
|
||||||
ret++;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (!force && was_valid)
|
|
||||||
|
if (!cache)
|
||||||
|
{
|
||||||
|
cache = FcDirCacheRead (dir, FcTrue, config);
|
||||||
|
if (!cache)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s: error scanning\n", dir);
|
||||||
|
ret++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set = FcCacheSet (cache);
|
||||||
|
|
||||||
|
if (was_valid)
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf ("skipping, %d fonts, %d dirs\n",
|
printf ("skipping, %d fonts, %d dirs\n",
|
||||||
set->nfont, nsubdirs(subdirs));
|
set->nfont, cache->dirs_count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf ("caching, %d fonts, %d dirs\n",
|
printf ("caching, %d fonts, %d dirs\n",
|
||||||
set->nfont, nsubdirs (subdirs));
|
set->nfont, cache->dirs_count);
|
||||||
|
|
||||||
if (!FcDirCacheValid (dir))
|
if (!FcDirCacheValid (dir))
|
||||||
{
|
{
|
||||||
|
@ -256,43 +244,36 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FcFontSetDestroy (set);
|
|
||||||
|
subdirs = FcStrSetCreate ();
|
||||||
|
if (!subdirs)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s: Can't create subdir set\n", dir);
|
||||||
|
ret++;
|
||||||
|
FcDirCacheUnload (cache);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (i = 0; i < cache->dirs_count; i++)
|
||||||
|
FcStrSetAdd (subdirs, FcCacheSubdir (cache, i));
|
||||||
|
|
||||||
|
FcDirCacheUnload (cache);
|
||||||
|
|
||||||
sublist = FcStrListCreate (subdirs);
|
sublist = FcStrListCreate (subdirs);
|
||||||
FcStrSetDestroy (subdirs);
|
FcStrSetDestroy (subdirs);
|
||||||
if (!sublist)
|
if (!sublist)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s: Can't create subdir list\n", dir);
|
fprintf (stderr, "%s: Can't create subdir list\n", dir);
|
||||||
ret++;
|
ret++;
|
||||||
|
FcDirCacheUnload (cache);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FcStrSetAdd (processed_dirs, dir);
|
FcStrSetAdd (processed_dirs, dir);
|
||||||
ret += scanDirs (sublist, config, program, force, really_force, verbose);
|
ret += scanDirs (sublist, config, force, really_force, verbose);
|
||||||
}
|
}
|
||||||
FcStrListDone (list);
|
FcStrListDone (list);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
FcCache *
|
|
||||||
FcCacheFileMap (const FcChar8 *file, struct stat *file_stat)
|
|
||||||
{
|
|
||||||
FcCache *cache;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = open (file, O_RDONLY | O_BINARY);
|
|
||||||
if (fd < 0)
|
|
||||||
return NULL;
|
|
||||||
if (fstat (fd, file_stat) < 0) {
|
|
||||||
close (fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (FcDirCacheLoad (fd, file_stat->st_size, &cache)) {
|
|
||||||
close (fd);
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
close (fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
|
cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
|
||||||
{
|
{
|
||||||
|
@ -309,9 +290,11 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
|
||||||
if (access ((char *) dir, W_OK|X_OK) != 0)
|
if (access ((char *) dir, W_OK|X_OK) != 0)
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf ("%s: skipping unwritable cache directory\n", dir);
|
printf ("%s: not cleaning unwritable cache directory\n", dir);
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
}
|
}
|
||||||
|
if (verbose)
|
||||||
|
printf ("%s: cleaning cache directory\n", dir);
|
||||||
d = opendir (dir);
|
d = opendir (dir);
|
||||||
if (!d)
|
if (!d)
|
||||||
{
|
{
|
||||||
|
@ -332,7 +315,7 @@ cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
|
||||||
ret = FcFalse;
|
ret = FcFalse;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cache = FcCacheFileMap (file_name, &file_stat);
|
cache = FcDirCacheLoadFile (file_name, &file_stat);
|
||||||
if (!cache)
|
if (!cache)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s: invalid cache file: %s\n", dir, ent->d_name);
|
fprintf (stderr, "%s: invalid cache file: %s\n", dir, ent->d_name);
|
||||||
|
@ -478,7 +461,7 @@ main (int argc, char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = scanDirs (list, config, argv[0], force, really_force, verbose);
|
ret = scanDirs (list, config, force, really_force, verbose);
|
||||||
|
|
||||||
FcStrSetDestroy (processed_dirs);
|
FcStrSetDestroy (processed_dirs);
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ extern int optind, opterr, optopt;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
FcCacheWriteChars (FILE *f, const FcChar8 *chars)
|
write_chars (FILE *f, const FcChar8 *chars)
|
||||||
{
|
{
|
||||||
FcChar8 c;
|
FcChar8 c;
|
||||||
while ((c = *chars++))
|
while ((c = *chars++))
|
||||||
|
@ -101,7 +101,7 @@ FcCacheWriteChars (FILE *f, const FcChar8 *chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
FcCacheWriteUlong (FILE *f, unsigned long t)
|
write_ulong (FILE *f, unsigned long t)
|
||||||
{
|
{
|
||||||
int pow;
|
int pow;
|
||||||
unsigned long temp, digit;
|
unsigned long temp, digit;
|
||||||
|
@ -126,18 +126,18 @@ FcCacheWriteUlong (FILE *f, unsigned long t)
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
FcCacheWriteInt (FILE *f, int i)
|
write_int (FILE *f, int i)
|
||||||
{
|
{
|
||||||
return FcCacheWriteUlong (f, (unsigned long) i);
|
return write_ulong (f, (unsigned long) i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
FcCacheWriteStringOld (FILE *f, const FcChar8 *string)
|
write_string (FILE *f, const FcChar8 *string)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (PUTC ('"', f) == EOF)
|
if (PUTC ('"', f) == EOF)
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
if (!FcCacheWriteChars (f, string))
|
if (!write_chars (f, string))
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
if (PUTC ('"', f) == EOF)
|
if (PUTC ('"', f) == EOF)
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
|
@ -168,30 +168,12 @@ usage (char *program)
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
FcCacheFileOpen (char *cache_file, off_t *size)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
struct stat file_stat;
|
|
||||||
|
|
||||||
fd = open(cache_file, O_RDONLY | O_BINARY);
|
|
||||||
if (fd < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (fstat (fd, &file_stat) < 0) {
|
|
||||||
close (fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*size = file_stat.st_size;
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return the path from the directory containing 'cache' to 'file'
|
* return the path from the directory containing 'cache' to 'file'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const FcChar8 *
|
static const FcChar8 *
|
||||||
FcFileBaseName (const char *cache, const FcChar8 *file)
|
file_base_name (const char *cache, const FcChar8 *file)
|
||||||
{
|
{
|
||||||
const FcChar8 *cache_slash;
|
const FcChar8 *cache_slash;
|
||||||
int cache_len = strlen (cache);
|
int cache_len = strlen (cache);
|
||||||
|
@ -201,8 +183,8 @@ FcFileBaseName (const char *cache, const FcChar8 *file)
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
FcBool
|
static FcBool
|
||||||
FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose)
|
cache_print_set (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose)
|
||||||
{
|
{
|
||||||
FcPattern *font;
|
FcPattern *font;
|
||||||
FcChar8 *name, *dir;
|
FcChar8 *name, *dir;
|
||||||
|
@ -219,16 +201,16 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose
|
||||||
|
|
||||||
while ((dir = FcStrListNext (list)))
|
while ((dir = FcStrListNext (list)))
|
||||||
{
|
{
|
||||||
base = FcFileBaseName (base_name, dir);
|
base = file_base_name (base_name, dir);
|
||||||
if (!FcCacheWriteStringOld (stdout, base))
|
if (!write_string (stdout, base))
|
||||||
goto bail3;
|
goto bail3;
|
||||||
if (PUTC (' ', stdout) == EOF)
|
if (PUTC (' ', stdout) == EOF)
|
||||||
goto bail3;
|
goto bail3;
|
||||||
if (!FcCacheWriteInt (stdout, 0))
|
if (!write_int (stdout, 0))
|
||||||
goto bail3;
|
goto bail3;
|
||||||
if (PUTC (' ', stdout) == EOF)
|
if (PUTC (' ', stdout) == EOF)
|
||||||
goto bail3;
|
goto bail3;
|
||||||
if (!FcCacheWriteStringOld (stdout, FC_FONT_FILE_DIR))
|
if (!write_string (stdout, FC_FONT_FILE_DIR))
|
||||||
goto bail3;
|
goto bail3;
|
||||||
if (PUTC ('\n', stdout) == EOF)
|
if (PUTC ('\n', stdout) == EOF)
|
||||||
goto bail3;
|
goto bail3;
|
||||||
|
@ -243,21 +225,21 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose
|
||||||
|
|
||||||
if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
|
if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
|
||||||
goto bail3;
|
goto bail3;
|
||||||
base = FcFileBaseName (base_name, file);
|
base = file_base_name (base_name, file);
|
||||||
if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
|
if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
|
||||||
goto bail3;
|
goto bail3;
|
||||||
if (!FcCacheWriteStringOld (stdout, base))
|
if (!write_string (stdout, base))
|
||||||
goto bail3;
|
goto bail3;
|
||||||
if (PUTC (' ', stdout) == EOF)
|
if (PUTC (' ', stdout) == EOF)
|
||||||
goto bail3;
|
goto bail3;
|
||||||
if (!FcCacheWriteInt (stdout, id))
|
if (!write_int (stdout, id))
|
||||||
goto bail3;
|
goto bail3;
|
||||||
if (PUTC (' ', stdout) == EOF)
|
if (PUTC (' ', stdout) == EOF)
|
||||||
goto bail3;
|
goto bail3;
|
||||||
name = FcNameUnparse (font);
|
name = FcNameUnparse (font);
|
||||||
if (!name)
|
if (!name)
|
||||||
goto bail3;
|
goto bail3;
|
||||||
ret = FcCacheWriteStringOld (stdout, name);
|
ret = write_string (stdout, name);
|
||||||
FcStrFree (name);
|
FcStrFree (name);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto bail3;
|
goto bail3;
|
||||||
|
@ -277,28 +259,6 @@ bail2:
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
FcCache *
|
|
||||||
FcCacheFileMap (const FcChar8 *file)
|
|
||||||
{
|
|
||||||
FcCache *cache;
|
|
||||||
int fd;
|
|
||||||
struct stat file_stat;
|
|
||||||
|
|
||||||
fd = open (file, O_RDONLY | O_BINARY);
|
|
||||||
if (fd < 0)
|
|
||||||
return NULL;
|
|
||||||
if (fstat (fd, &file_stat) < 0) {
|
|
||||||
close (fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (!FcDirCacheLoad (fd, file_stat.st_size, &cache)) {
|
|
||||||
close (fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
close (fd);
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -399,11 +359,12 @@ main (int argc, char **argv)
|
||||||
off_t size;
|
off_t size;
|
||||||
intptr_t *cache_dirs;
|
intptr_t *cache_dirs;
|
||||||
FcChar8 *cache_file = NULL;
|
FcChar8 *cache_file = NULL;
|
||||||
|
struct stat file_stat;
|
||||||
|
|
||||||
if (FcFileIsDir (arg))
|
if (FcFileIsDir (arg))
|
||||||
cache = FcDirCacheMap (arg, config, &cache_file);
|
cache = FcDirCacheLoad (arg, config, &cache_file);
|
||||||
else
|
else
|
||||||
cache = FcCacheFileMap (arg);
|
cache = FcDirCacheLoadFile (arg, &file_stat);
|
||||||
if (!cache)
|
if (!cache)
|
||||||
{
|
{
|
||||||
perror ((char *) arg);
|
perror ((char *) arg);
|
||||||
|
@ -433,11 +394,11 @@ main (int argc, char **argv)
|
||||||
FcCacheDir(cache), cache_file ? cache_file : arg);
|
FcCacheDir(cache), cache_file ? cache_file : arg);
|
||||||
first = FcFalse;
|
first = FcFalse;
|
||||||
}
|
}
|
||||||
FcCachePrintSet (fs, dirs, FcCacheDir (cache), verbose);
|
cache_print_set (fs, dirs, FcCacheDir (cache), verbose);
|
||||||
|
|
||||||
FcStrSetDestroy (dirs);
|
FcStrSetDestroy (dirs);
|
||||||
|
|
||||||
FcDirCacheUnmap (cache);
|
FcDirCacheUnload (cache);
|
||||||
if (cache_file)
|
if (cache_file)
|
||||||
FcStrFree (cache_file);
|
FcStrFree (cache_file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,19 +24,6 @@
|
||||||
|
|
||||||
#include "fcint.h"
|
#include "fcint.h"
|
||||||
|
|
||||||
/* stub definitions for declarations from fcint.h.. */
|
|
||||||
int * _fcBankId = 0, * _fcBankIdx = 0;
|
|
||||||
FcValueList ** _fcValueLists = 0;
|
|
||||||
FcPatternElt ** _fcPatternElts = 0;
|
|
||||||
int FcDebugVal = 0;
|
|
||||||
|
|
||||||
int
|
|
||||||
FcCacheBankToIndexMTF (int bank)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* end stub definitions */
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rawindex (const FcGlyphName *gn);
|
rawindex (const FcGlyphName *gn);
|
||||||
|
|
||||||
|
|
302
src/fccache.c
302
src/fccache.c
|
@ -112,81 +112,19 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
FcCacheReadDirs (FcConfig * config,
|
FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
|
||||||
FcStrList *list, FcFontSet * set, FcStrSet *processed_dirs)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int fd;
|
||||||
FcChar8 *dir;
|
|
||||||
FcStrSet *subdirs;
|
|
||||||
FcStrList *sublist;
|
|
||||||
|
|
||||||
/*
|
fd = open((char *) cache_file, O_RDONLY | O_BINARY);
|
||||||
* Read in the results from 'list'.
|
if (fd < 0)
|
||||||
*/
|
return fd;
|
||||||
while ((dir = FcStrListNext (list)))
|
if (fstat (fd, file_stat) < 0)
|
||||||
{
|
{
|
||||||
if (!FcConfigAcceptFilename (config, dir))
|
close (fd);
|
||||||
continue;
|
return -1;
|
||||||
|
|
||||||
/* Skip this directory if already updated
|
|
||||||
* to avoid the looped directories via symlinks
|
|
||||||
* Clearly a dir not in fonts.conf shouldn't be globally cached.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (FcStrSetMember (processed_dirs, dir))
|
|
||||||
continue;
|
|
||||||
if (!FcStrSetAdd (processed_dirs, dir))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
subdirs = FcStrSetCreate ();
|
|
||||||
if (!subdirs)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "Can't create directory set\n");
|
|
||||||
ret++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
FcDirScanConfig (set, subdirs,
|
|
||||||
config->blanks, dir, FcFalse, config);
|
|
||||||
|
|
||||||
sublist = FcStrListCreate (subdirs);
|
|
||||||
FcStrSetDestroy (subdirs);
|
|
||||||
if (!sublist)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "Can't create subdir list in \"%s\"\n", dir);
|
|
||||||
ret++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ret += FcCacheReadDirs (config, sublist, set, processed_dirs);
|
|
||||||
}
|
}
|
||||||
FcStrListDone (list);
|
return fd;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
FcFontSet *
|
|
||||||
FcCacheRead (FcConfig *config)
|
|
||||||
{
|
|
||||||
FcFontSet *s = FcFontSetCreate();
|
|
||||||
FcStrSet *processed_dirs;
|
|
||||||
|
|
||||||
if (!s)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
processed_dirs = FcStrSetCreate();
|
|
||||||
if (!processed_dirs)
|
|
||||||
goto bail;
|
|
||||||
|
|
||||||
if (FcCacheReadDirs (config, FcConfigGetConfigDirs (config), s, processed_dirs))
|
|
||||||
goto bail1;
|
|
||||||
|
|
||||||
FcStrSetDestroy (processed_dirs);
|
|
||||||
return s;
|
|
||||||
|
|
||||||
bail1:
|
|
||||||
FcStrSetDestroy (processed_dirs);
|
|
||||||
bail:
|
|
||||||
FcFontSetDestroy (s);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -220,10 +158,9 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
|
||||||
FcChar8 *cache_hashed = FcStrPlus (cache_dir, cache_base);
|
FcChar8 *cache_hashed = FcStrPlus (cache_dir, cache_base);
|
||||||
if (!cache_hashed)
|
if (!cache_hashed)
|
||||||
break;
|
break;
|
||||||
fd = open((char *) cache_hashed, O_RDONLY | O_BINARY);
|
fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
if (fstat (fd, &file_stat) >= 0 &&
|
if (dir_stat.st_mtime <= file_stat.st_mtime)
|
||||||
dir_stat.st_mtime <= file_stat.st_mtime)
|
|
||||||
{
|
{
|
||||||
ret = (*callback) (fd, file_stat.st_size, closure);
|
ret = (*callback) (fd, file_stat.st_size, closure);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -245,44 +182,56 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
FcBool
|
#define FC_CACHE_MIN_MMAP 1024
|
||||||
FcDirCacheLoad (int fd, off_t size, void *closure)
|
|
||||||
|
/*
|
||||||
|
* Map a cache file into memory
|
||||||
|
*/
|
||||||
|
static FcCache *
|
||||||
|
FcDirCacheMapFd (int fd, off_t size)
|
||||||
{
|
{
|
||||||
FcCache *cache;
|
FcCache *cache = NULL;
|
||||||
FcBool allocated = FcFalse;
|
FcBool allocated = FcFalse;
|
||||||
|
|
||||||
if (size < sizeof (FcCache))
|
if (size < sizeof (FcCache))
|
||||||
return FcFalse;
|
return NULL;
|
||||||
#if defined(HAVE_MMAP) || defined(__CYGWIN__)
|
/*
|
||||||
cache = mmap (0, size, PROT_READ, MAP_SHARED, fd, 0);
|
* For small cache files, just read them into memory
|
||||||
#elif defined(_WIN32)
|
*/
|
||||||
|
if (size >= FC_CACHE_MIN_MMAP)
|
||||||
{
|
{
|
||||||
HANDLE hFileMap;
|
#if defined(HAVE_MMAP) || defined(__CYGWIN__)
|
||||||
|
cache = mmap (0, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
cache = NULL;
|
#elif defined(_WIN32)
|
||||||
hFileMap = CreateFileMapping((HANDLE) _get_osfhandle(fd), NULL,
|
|
||||||
PAGE_READONLY, 0, 0, NULL);
|
|
||||||
if (hFileMap != NULL)
|
|
||||||
{
|
{
|
||||||
cache = MapViewOfFile (hFileMap, FILE_MAP_READ, 0, 0, size);
|
HANDLE hFileMap;
|
||||||
CloseHandle (hFileMap);
|
|
||||||
|
cache = NULL;
|
||||||
|
hFileMap = CreateFileMapping((HANDLE) _get_osfhandle(fd), NULL,
|
||||||
|
PAGE_READONLY, 0, 0, NULL);
|
||||||
|
if (hFileMap != NULL)
|
||||||
|
{
|
||||||
|
cache = MapViewOfFile (hFileMap, FILE_MAP_READ, 0, 0, size);
|
||||||
|
CloseHandle (hFileMap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
if (!cache)
|
if (!cache)
|
||||||
{
|
{
|
||||||
cache = malloc (size);
|
cache = malloc (size);
|
||||||
if (!cache)
|
if (!cache)
|
||||||
return FcFalse;
|
return NULL;
|
||||||
|
|
||||||
if (read (fd, cache, size) != size)
|
if (read (fd, cache, size) != size)
|
||||||
{
|
{
|
||||||
free (cache);
|
free (cache);
|
||||||
return FcFalse;
|
return NULL;
|
||||||
}
|
}
|
||||||
allocated = FcTrue;
|
allocated = FcTrue;
|
||||||
}
|
}
|
||||||
if (cache->magic != FC_CACHE_MAGIC ||
|
if (cache->magic != FC_CACHE_MAGIC_MMAP ||
|
||||||
|
cache->version != FC_CACHE_CONTENT_VERSION ||
|
||||||
cache->size != size)
|
cache->size != size)
|
||||||
{
|
{
|
||||||
if (allocated)
|
if (allocated)
|
||||||
|
@ -295,74 +244,76 @@ FcDirCacheLoad (int fd, off_t size, void *closure)
|
||||||
UnmapViewOfFile (cache);
|
UnmapViewOfFile (cache);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return FcFalse;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark allocated caches so they're freed rather than unmapped */
|
/* Mark allocated caches so they're freed rather than unmapped */
|
||||||
if (allocated)
|
if (allocated)
|
||||||
cache->magic = FC_CACHE_MAGIC_COPY;
|
cache->magic = FC_CACHE_MAGIC_ALLOC;
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FcDirCacheUnload (FcCache *cache)
|
||||||
|
{
|
||||||
|
switch (cache->magic) {
|
||||||
|
case FC_CACHE_MAGIC_ALLOC:
|
||||||
|
free (cache);
|
||||||
|
break;
|
||||||
|
case FC_CACHE_MAGIC_MMAP:
|
||||||
|
#if defined(HAVE_MMAP) || defined(__CYGWIN__)
|
||||||
|
munmap (cache, cache->size);
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
UnmapViewOfFile (cache);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
FcDirCacheMapHelper (int fd, off_t size, void *closure)
|
||||||
|
{
|
||||||
|
FcCache *cache = FcDirCacheMapFd (fd, size);
|
||||||
|
|
||||||
|
if (!cache)
|
||||||
|
return FcFalse;
|
||||||
*((FcCache **) closure) = cache;
|
*((FcCache **) closure) = cache;
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
FcCache *
|
FcCache *
|
||||||
FcDirCacheMap (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
|
FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
|
||||||
{
|
{
|
||||||
FcCache *cache = NULL;
|
FcCache *cache = NULL;
|
||||||
|
|
||||||
if (!FcDirCacheProcess (config, dir,
|
if (!FcDirCacheProcess (config, dir,
|
||||||
FcDirCacheLoad,
|
FcDirCacheMapHelper,
|
||||||
&cache, cache_file))
|
&cache, cache_file))
|
||||||
return NULL;
|
return NULL;
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
FcBool
|
FcCache *
|
||||||
FcDirCacheRead (FcFontSet * set, FcStrSet * dirs,
|
FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
|
||||||
const FcChar8 *dir, FcConfig *config)
|
|
||||||
{
|
{
|
||||||
FcCache *cache;
|
int fd;
|
||||||
int i;
|
FcCache *cache;
|
||||||
FcFontSet *cache_set;
|
|
||||||
intptr_t *cache_dirs;
|
|
||||||
FcPattern **cache_fonts;
|
|
||||||
|
|
||||||
cache = FcDirCacheMap (dir, config, NULL);
|
fd = FcDirCacheOpenFile (cache_file, file_stat);
|
||||||
if (!cache)
|
if (fd < 0)
|
||||||
return FcFalse;
|
return NULL;
|
||||||
|
cache = FcDirCacheMapFd (fd, file_stat->st_size);
|
||||||
cache_set = FcCacheSet (cache);
|
close (fd);
|
||||||
cache_fonts = FcFontSetFonts(cache_set);
|
return cache;
|
||||||
if (FcDebug() & FC_DBG_CACHE)
|
|
||||||
printf ("FcDirCacheRead mapped cache for %s (%d fonts %d subdirs)\n",
|
|
||||||
dir, cache_set->nfont, cache->dirs_count);
|
|
||||||
for (i = 0; i < cache_set->nfont; i++)
|
|
||||||
{
|
|
||||||
FcPattern *font = FcEncodedOffsetToPtr (cache_set,
|
|
||||||
cache_fonts[i],
|
|
||||||
FcPattern);
|
|
||||||
if (FcDebug() & FC_DBG_CACHEV) {
|
|
||||||
printf ("Mapped font %d\n", i);
|
|
||||||
FcPatternPrint (font);
|
|
||||||
}
|
|
||||||
FcFontSetAdd (set, font);
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_dirs = FcCacheDirs (cache);
|
|
||||||
for (i = 0; i < cache->dirs_count; i++)
|
|
||||||
FcStrSetAdd (dirs, FcOffsetToPtr (cache_dirs,
|
|
||||||
cache_dirs[i],
|
|
||||||
FcChar8));
|
|
||||||
|
|
||||||
if (config)
|
|
||||||
FcConfigAddFontDir (config, (FcChar8 *)dir);
|
|
||||||
|
|
||||||
return FcTrue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate a cache file by reading the header and checking
|
||||||
|
* the magic number and the size field
|
||||||
|
*/
|
||||||
static FcBool
|
static FcBool
|
||||||
FcDirCacheValidate (int fd, off_t size, void *closure)
|
FcDirCacheValidateHelper (int fd, off_t size, void *closure)
|
||||||
{
|
{
|
||||||
FcBool ret = FcTrue;
|
FcBool ret = FcTrue;
|
||||||
FcCache c;
|
FcCache c;
|
||||||
|
@ -370,9 +321,11 @@ FcDirCacheValidate (int fd, off_t size, void *closure)
|
||||||
|
|
||||||
if (read (fd, &c, sizeof (FcCache)) != sizeof (FcCache))
|
if (read (fd, &c, sizeof (FcCache)) != sizeof (FcCache))
|
||||||
ret = FcFalse;
|
ret = FcFalse;
|
||||||
else if (fstat (fd, &file_stat) < 0)
|
else if (c.magic != FC_CACHE_MAGIC_MMAP)
|
||||||
ret = FcFalse;
|
ret = FcFalse;
|
||||||
else if (c.magic != FC_CACHE_MAGIC)
|
else if (c.version != FC_CACHE_CONTENT_VERSION)
|
||||||
|
ret = FcFalse;
|
||||||
|
else if (fstat (fd, &file_stat) < 0)
|
||||||
ret = FcFalse;
|
ret = FcFalse;
|
||||||
else if (file_stat.st_size != c.size)
|
else if (file_stat.st_size != c.size)
|
||||||
ret = FcFalse;
|
ret = FcFalse;
|
||||||
|
@ -382,7 +335,9 @@ FcDirCacheValidate (int fd, off_t size, void *closure)
|
||||||
static FcBool
|
static FcBool
|
||||||
FcDirCacheValidConfig (const FcChar8 *dir, FcConfig *config)
|
FcDirCacheValidConfig (const FcChar8 *dir, FcConfig *config)
|
||||||
{
|
{
|
||||||
return FcDirCacheProcess (config, dir, FcDirCacheValidate, NULL, NULL);
|
return FcDirCacheProcess (config, dir,
|
||||||
|
FcDirCacheValidateHelper,
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
|
@ -397,32 +352,11 @@ FcDirCacheValid (const FcChar8 *dir)
|
||||||
return FcDirCacheValidConfig (dir, config);
|
return FcDirCacheValidConfig (dir, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
* Build a cache structure from the given contents
|
||||||
*
|
|
||||||
* FcCache
|
|
||||||
* dir name
|
|
||||||
* subdirs
|
|
||||||
* FcFontSet
|
|
||||||
*/
|
*/
|
||||||
|
FcCache *
|
||||||
static FcCache *
|
FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
|
||||||
FcDirCacheProduce (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
|
|
||||||
{
|
{
|
||||||
FcSerialize *serialize = FcSerializeCreate ();
|
FcSerialize *serialize = FcSerializeCreate ();
|
||||||
FcCache *cache;
|
FcCache *cache;
|
||||||
|
@ -467,7 +401,8 @@ FcDirCacheProduce (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
|
||||||
|
|
||||||
serialize->linear = cache;
|
serialize->linear = cache;
|
||||||
|
|
||||||
cache->magic = FC_CACHE_MAGIC;
|
cache->magic = FC_CACHE_MAGIC_ALLOC;
|
||||||
|
cache->version = FC_CACHE_CONTENT_VERSION;
|
||||||
cache->size = serialize->size;
|
cache->size = serialize->size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -537,16 +472,18 @@ FcMakeDirectory (const FcChar8 *dir)
|
||||||
|
|
||||||
/* write serialized state to the cache file */
|
/* write serialized state to the cache file */
|
||||||
FcBool
|
FcBool
|
||||||
FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *config)
|
FcDirCacheWrite (FcCache *cache, FcConfig *config)
|
||||||
{
|
{
|
||||||
|
FcChar8 *dir = FcCacheDir (cache);
|
||||||
FcChar8 cache_base[CACHEBASE_LEN];
|
FcChar8 cache_base[CACHEBASE_LEN];
|
||||||
FcChar8 *cache_hashed;
|
FcChar8 *cache_hashed;
|
||||||
int fd;
|
int fd;
|
||||||
FcAtomic *atomic;
|
FcAtomic *atomic;
|
||||||
FcCache *cache;
|
|
||||||
FcStrList *list;
|
FcStrList *list;
|
||||||
FcChar8 *cache_dir = NULL;
|
FcChar8 *cache_dir = NULL;
|
||||||
FcChar8 *test_dir;
|
FcChar8 *test_dir;
|
||||||
|
int magic;
|
||||||
|
int written;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write it to the first directory in the list which is writable
|
* Write it to the first directory in the list which is writable
|
||||||
|
@ -584,18 +521,13 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *c
|
||||||
if (!cache_hashed)
|
if (!cache_hashed)
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
|
|
||||||
cache = FcDirCacheProduce (set, dir, dirs);
|
|
||||||
|
|
||||||
if (!cache)
|
|
||||||
goto bail1;
|
|
||||||
|
|
||||||
if (FcDebug () & FC_DBG_CACHE)
|
if (FcDebug () & FC_DBG_CACHE)
|
||||||
printf ("FcDirCacheWriteDir dir \"%s\" file \"%s\"\n",
|
printf ("FcDirCacheWriteDir dir \"%s\" file \"%s\"\n",
|
||||||
dir, cache_hashed);
|
dir, cache_hashed);
|
||||||
|
|
||||||
atomic = FcAtomicCreate ((FcChar8 *)cache_hashed);
|
atomic = FcAtomicCreate ((FcChar8 *)cache_hashed);
|
||||||
if (!atomic)
|
if (!atomic)
|
||||||
goto bail2;
|
goto bail1;
|
||||||
|
|
||||||
if (!FcAtomicLock (atomic))
|
if (!FcAtomicLock (atomic))
|
||||||
goto bail3;
|
goto bail3;
|
||||||
|
@ -604,7 +536,21 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *c
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
goto bail4;
|
goto bail4;
|
||||||
|
|
||||||
if (write (fd, cache, cache->size) != cache->size)
|
/* Temporarily switch magic to MMAP while writing to file */
|
||||||
|
magic = cache->magic;
|
||||||
|
if (magic != FC_CACHE_MAGIC_MMAP)
|
||||||
|
cache->magic = FC_CACHE_MAGIC_MMAP;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write cache contents to file
|
||||||
|
*/
|
||||||
|
written = write (fd, cache, cache->size);
|
||||||
|
|
||||||
|
/* Switch magic back */
|
||||||
|
if (magic != FC_CACHE_MAGIC_MMAP)
|
||||||
|
cache->magic = magic;
|
||||||
|
|
||||||
|
if (written != cache->size)
|
||||||
{
|
{
|
||||||
perror ("write cache");
|
perror ("write cache");
|
||||||
goto bail5;
|
goto bail5;
|
||||||
|
@ -613,7 +559,7 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *c
|
||||||
close(fd);
|
close(fd);
|
||||||
if (!FcAtomicReplaceOrig(atomic))
|
if (!FcAtomicReplaceOrig(atomic))
|
||||||
goto bail4;
|
goto bail4;
|
||||||
FcStrFree ((FcChar8 *)cache_hashed);
|
FcStrFree (cache_hashed);
|
||||||
FcAtomicUnlock (atomic);
|
FcAtomicUnlock (atomic);
|
||||||
FcAtomicDestroy (atomic);
|
FcAtomicDestroy (atomic);
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
|
@ -624,10 +570,8 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *c
|
||||||
FcAtomicUnlock (atomic);
|
FcAtomicUnlock (atomic);
|
||||||
bail3:
|
bail3:
|
||||||
FcAtomicDestroy (atomic);
|
FcAtomicDestroy (atomic);
|
||||||
bail2:
|
|
||||||
free (cache);
|
|
||||||
bail1:
|
bail1:
|
||||||
FcStrFree ((FcChar8 *)cache_hashed);
|
FcStrFree (cache_hashed);
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
173
src/fccfg.c
173
src/fccfg.c
|
@ -222,7 +222,7 @@ FcConfigDestroy (FcConfig *config)
|
||||||
for (cl = config->caches; cl; cl = cl_next)
|
for (cl = config->caches; cl; cl = cl_next)
|
||||||
{
|
{
|
||||||
cl_next = cl->next;
|
cl_next = cl->next;
|
||||||
FcDirCacheUnmap (cl->cache);
|
FcDirCacheUnload (cl->cache);
|
||||||
free (cl);
|
free (cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,87 +230,121 @@ FcConfigDestroy (FcConfig *config)
|
||||||
FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
|
FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add cache to configuration, adding fonts and directories
|
||||||
|
*/
|
||||||
|
|
||||||
|
FcBool
|
||||||
|
FcConfigAddCache (FcConfig *config, FcCache *cache)
|
||||||
|
{
|
||||||
|
FcCacheList *cl = malloc (sizeof (FcCacheList));
|
||||||
|
FcFontSet *fs;
|
||||||
|
intptr_t *dirs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add to cache list
|
||||||
|
*/
|
||||||
|
if (!cl)
|
||||||
|
return FcFalse;
|
||||||
|
cl->cache = cache;
|
||||||
|
cl->next = config->caches;
|
||||||
|
config->caches = cl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add fonts
|
||||||
|
*/
|
||||||
|
fs = FcCacheSet (cache);
|
||||||
|
if (fs)
|
||||||
|
{
|
||||||
|
for (i = 0; i < fs->nfont; i++)
|
||||||
|
{
|
||||||
|
FcPattern *font = FcFontSetFont (fs, i);
|
||||||
|
FcChar8 *font_file;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if font is banned by filename
|
||||||
|
*/
|
||||||
|
if (FcPatternObjectGetString (font, FC_FILE_OBJECT,
|
||||||
|
0, &font_file) == FcResultMatch &&
|
||||||
|
!FcConfigAcceptFilename (config, font_file))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if font is banned by pattern
|
||||||
|
*/
|
||||||
|
if (!FcConfigAcceptFont (config, font))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
FcFontSetAdd (config->fonts[FcSetSystem], font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add directories
|
||||||
|
*/
|
||||||
|
dirs = FcCacheDirs (cache);
|
||||||
|
if (dirs)
|
||||||
|
{
|
||||||
|
for (i = 0; i < cache->dirs_count; i++)
|
||||||
|
{
|
||||||
|
FcChar8 *dir = FcOffsetToPtr (dirs, dirs[i], FcChar8);
|
||||||
|
if (FcConfigAcceptFilename (config, dir))
|
||||||
|
FcConfigAddFontDir (config, dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the current list of directories in the configuration
|
* Scan the current list of directories in the configuration
|
||||||
* and build the set of available fonts. Update the
|
* and build the set of available fonts.
|
||||||
* per-user cache file to reflect the new configuration
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcConfigBuildFonts (FcConfig *config)
|
FcConfigBuildFonts (FcConfig *config)
|
||||||
{
|
{
|
||||||
FcFontSet *fonts, *cached_fonts;
|
FcFontSet *fonts;
|
||||||
FcStrList *list;
|
FcStrList *dirlist;
|
||||||
FcStrSet *oldDirs;
|
|
||||||
FcChar8 *dir;
|
FcChar8 *dir;
|
||||||
|
FcCache *cache;
|
||||||
|
|
||||||
|
if (!config)
|
||||||
|
{
|
||||||
|
config = FcConfigGetCurrent ();
|
||||||
|
if (!config)
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
|
||||||
fonts = FcFontSetCreate ();
|
fonts = FcFontSetCreate ();
|
||||||
if (!fonts)
|
if (!fonts)
|
||||||
goto bail0;
|
goto bail;
|
||||||
|
|
||||||
oldDirs = FcStrSetCreate ();
|
FcConfigSetFonts (config, fonts, FcSetSystem);
|
||||||
if (!oldDirs)
|
|
||||||
goto bail2;
|
dirlist = FcStrListCreate (config->fontDirs);
|
||||||
|
if (!dirlist)
|
||||||
cached_fonts = FcCacheRead(config);
|
goto bail;
|
||||||
if (!cached_fonts)
|
|
||||||
{
|
|
||||||
list = FcConfigGetFontDirs (config);
|
|
||||||
if (!list)
|
|
||||||
goto bail3;
|
|
||||||
|
|
||||||
while ((dir = FcStrListNext (list)))
|
while ((dir = FcStrListNext (dirlist)))
|
||||||
{
|
|
||||||
if (FcDebug () & FC_DBG_FONTSET)
|
|
||||||
printf ("build scan dir %s\n", dir);
|
|
||||||
FcDirScanConfig (fonts, config->fontDirs,
|
|
||||||
config->blanks, dir, FcFalse, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
FcStrListDone (list);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
int i;
|
if (FcDebug () & FC_DBG_FONTSET)
|
||||||
|
printf ("adding fonts from%s\n", dir);
|
||||||
for (i = 0; i < oldDirs->num; i++)
|
cache = FcDirCacheRead (dir, FcFalse, config);
|
||||||
{
|
if (!cache)
|
||||||
if (FcDebug () & FC_DBG_FONTSET)
|
continue;
|
||||||
printf ("scan dir %s\n", oldDirs->strs[i]);
|
FcConfigAddCache (config, cache);
|
||||||
FcDirScanConfig (fonts, config->fontDirs,
|
|
||||||
config->blanks, oldDirs->strs[i],
|
|
||||||
FcFalse, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < cached_fonts->nfont; i++)
|
|
||||||
{
|
|
||||||
FcChar8 *cfn;
|
|
||||||
FcPattern *font = cached_fonts->fonts[i];
|
|
||||||
FcPatternObjectGetString (font, FC_FILE_OBJECT, 0, &cfn);
|
|
||||||
|
|
||||||
if (FcConfigAcceptFont (config, font) &&
|
|
||||||
(cfn && FcConfigAcceptFilename (config, cfn)))
|
|
||||||
FcFontSetAdd (fonts, font);
|
|
||||||
|
|
||||||
cached_fonts->fonts[i] = 0; /* prevent free in FcFontSetDestroy */
|
|
||||||
}
|
|
||||||
cached_fonts->nfont = 0;
|
|
||||||
FcFontSetDestroy (cached_fonts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FcStrListDone (dirlist);
|
||||||
|
|
||||||
if (FcDebug () & FC_DBG_FONTSET)
|
if (FcDebug () & FC_DBG_FONTSET)
|
||||||
FcFontSetPrint (fonts);
|
FcFontSetPrint (fonts);
|
||||||
|
|
||||||
FcStrSetDestroy (oldDirs);
|
|
||||||
|
|
||||||
FcConfigSetFonts (config, fonts, FcSetSystem);
|
|
||||||
|
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
bail3:
|
bail:
|
||||||
FcStrSetDestroy (oldDirs);
|
|
||||||
bail2:
|
|
||||||
FcFontSetDestroy (fonts);
|
|
||||||
bail0:
|
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,19 +491,6 @@ FcConfigSetFonts (FcConfig *config,
|
||||||
config->fonts[set] = fonts;
|
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 *
|
FcBlanks *
|
||||||
FcConfigGetBlanks (FcConfig *config)
|
FcConfigGetBlanks (FcConfig *config)
|
||||||
{
|
{
|
||||||
|
@ -1750,7 +1771,7 @@ FcConfigAppFontAddFile (FcConfig *config,
|
||||||
FcConfigSetFonts (config, set, FcSetApplication);
|
FcConfigSetFonts (config, set, FcSetApplication);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FcFileScanConfig (set, subdirs, config->blanks, file, FcFalse, config))
|
if (!FcFileScanConfig (set, subdirs, config->blanks, file, config))
|
||||||
{
|
{
|
||||||
FcStrSetDestroy (subdirs);
|
FcStrSetDestroy (subdirs);
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
|
|
666
src/fccharset.c
666
src/fccharset.c
|
@ -27,8 +27,6 @@
|
||||||
|
|
||||||
/* #define CHECK */
|
/* #define CHECK */
|
||||||
|
|
||||||
/* #define CHATTY */
|
|
||||||
|
|
||||||
FcCharSet *
|
FcCharSet *
|
||||||
FcCharSetCreate (void)
|
FcCharSetCreate (void)
|
||||||
{
|
{
|
||||||
|
@ -40,8 +38,8 @@ FcCharSetCreate (void)
|
||||||
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
|
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
|
||||||
fcs->ref = 1;
|
fcs->ref = 1;
|
||||||
fcs->num = 0;
|
fcs->num = 0;
|
||||||
fcs->leaves_offset = FcPtrToOffset (fcs, NULL);
|
fcs->leaves_offset = 0;
|
||||||
fcs->numbers_offset = FcPtrToOffset (fcs, NULL);
|
fcs->numbers_offset = 0;
|
||||||
return fcs;
|
return fcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,12 +66,12 @@ FcCharSetDestroy (FcCharSet *fcs)
|
||||||
FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
|
FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
|
||||||
free (FcCharSetLeaf (fcs, i));
|
free (FcCharSetLeaf (fcs, i));
|
||||||
}
|
}
|
||||||
if (FcCharSetLeaves (fcs))
|
if (fcs->num)
|
||||||
{
|
{
|
||||||
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (intptr_t));
|
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (intptr_t));
|
||||||
free (FcCharSetLeaves (fcs));
|
free (FcCharSetLeaves (fcs));
|
||||||
}
|
}
|
||||||
if (FcCharSetNumbers (fcs))
|
if (fcs->num)
|
||||||
{
|
{
|
||||||
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
|
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
|
||||||
free (FcCharSetNumbers (fcs));
|
free (FcCharSetNumbers (fcs));
|
||||||
|
@ -136,7 +134,7 @@ FcCharSetPutLeaf (FcCharSet *fcs,
|
||||||
ucs4 >>= 8;
|
ucs4 >>= 8;
|
||||||
if (ucs4 >= 0x10000)
|
if (ucs4 >= 0x10000)
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
if (!leaves)
|
if (!fcs->num)
|
||||||
leaves = malloc (sizeof (*leaves));
|
leaves = malloc (sizeof (*leaves));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -161,7 +159,7 @@ FcCharSetPutLeaf (FcCharSet *fcs,
|
||||||
FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (intptr_t));
|
FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (intptr_t));
|
||||||
fcs->leaves_offset = FcPtrToOffset (fcs, leaves);
|
fcs->leaves_offset = FcPtrToOffset (fcs, leaves);
|
||||||
|
|
||||||
if (!numbers)
|
if (!fcs->num)
|
||||||
numbers = malloc (sizeof (FcChar16));
|
numbers = malloc (sizeof (FcChar16));
|
||||||
else
|
else
|
||||||
numbers = realloc (numbers, (fcs->num + 1) * sizeof (FcChar16));
|
numbers = realloc (numbers, (fcs->num + 1) * sizeof (FcChar16));
|
||||||
|
@ -278,9 +276,6 @@ FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter)
|
||||||
}
|
}
|
||||||
iter->leaf = FcCharSetLeaf(fcs, pos);
|
iter->leaf = FcCharSetLeaf(fcs, pos);
|
||||||
iter->pos = pos;
|
iter->pos = pos;
|
||||||
#ifdef CHATTY
|
|
||||||
printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -300,29 +295,10 @@ FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CHATTY
|
|
||||||
static void
|
|
||||||
FcCharSetDump (const FcCharSet *fcs)
|
|
||||||
{
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
printf ("fcs %08x:\n", (FcChar32) fcs);
|
|
||||||
for (pos = 0; pos < fcs->num; pos++)
|
|
||||||
{
|
|
||||||
FcCharLeaf *leaf = fcs->leaves[pos];
|
|
||||||
FcChar32 ucs4 = (FcChar32) fcs->numbers[pos] << 8;
|
|
||||||
|
|
||||||
printf (" %08x: %08x\n", ucs4, (FcChar32) leaf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
|
FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
|
||||||
{
|
{
|
||||||
#ifdef CHATTY
|
|
||||||
FcCharSetDump (fcs);
|
|
||||||
#endif
|
|
||||||
iter->ucs4 = 0;
|
iter->ucs4 = 0;
|
||||||
iter->pos = 0;
|
iter->pos = 0;
|
||||||
FcCharSetIterSet (fcs, iter);
|
FcCharSetIterSet (fcs, iter);
|
||||||
|
@ -854,271 +830,10 @@ FcCharSetUnparseValue (FcStrBuf *buf, FcChar32 value)
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _FcCharLeafEnt FcCharLeafEnt;
|
|
||||||
|
|
||||||
struct _FcCharLeafEnt {
|
|
||||||
FcCharLeafEnt *next;
|
|
||||||
FcChar32 hash;
|
|
||||||
FcCharLeaf leaf;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define FC_CHAR_LEAF_BLOCK (4096 / sizeof (FcCharLeafEnt))
|
|
||||||
static FcCharLeafEnt **FcCharLeafBlocks;
|
|
||||||
static int FcCharLeafBlockCount;
|
|
||||||
|
|
||||||
static FcCharLeafEnt *
|
|
||||||
FcCharLeafEntCreate (void)
|
|
||||||
{
|
|
||||||
static FcCharLeafEnt *block;
|
|
||||||
static int remain;
|
|
||||||
|
|
||||||
if (!remain)
|
|
||||||
{
|
|
||||||
FcCharLeafEnt **newBlocks;
|
|
||||||
|
|
||||||
FcCharLeafBlockCount++;
|
|
||||||
newBlocks = realloc (FcCharLeafBlocks, FcCharLeafBlockCount * sizeof (FcCharLeafEnt *));
|
|
||||||
if (!newBlocks)
|
|
||||||
return 0;
|
|
||||||
FcCharLeafBlocks = newBlocks;
|
|
||||||
block = FcCharLeafBlocks[FcCharLeafBlockCount-1] = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
|
|
||||||
if (!block)
|
|
||||||
return 0;
|
|
||||||
FcMemAlloc (FC_MEM_CHARLEAF, FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
|
|
||||||
remain = FC_CHAR_LEAF_BLOCK;
|
|
||||||
}
|
|
||||||
remain--;
|
|
||||||
return block++;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FC_CHAR_LEAF_HASH_SIZE 257
|
|
||||||
|
|
||||||
static FcChar32
|
|
||||||
FcCharLeafHash (FcCharLeaf *leaf)
|
|
||||||
{
|
|
||||||
FcChar32 hash = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < 256/32; i++)
|
|
||||||
hash = ((hash << 1) | (hash >> 31)) ^ leaf->map[i];
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int FcCharLeafTotal;
|
|
||||||
static int FcCharLeafUsed;
|
|
||||||
|
|
||||||
static FcCharLeafEnt *FcCharLeafHashTable[FC_CHAR_LEAF_HASH_SIZE];
|
|
||||||
|
|
||||||
static FcCharLeaf *
|
|
||||||
FcCharSetFreezeLeaf (FcCharLeaf *leaf)
|
|
||||||
{
|
|
||||||
FcChar32 hash = FcCharLeafHash (leaf);
|
|
||||||
FcCharLeafEnt **bucket = &FcCharLeafHashTable[hash % FC_CHAR_LEAF_HASH_SIZE];
|
|
||||||
FcCharLeafEnt *ent;
|
|
||||||
|
|
||||||
FcCharLeafTotal++;
|
|
||||||
for (ent = *bucket; ent; ent = ent->next)
|
|
||||||
{
|
|
||||||
if (ent->hash == hash && !memcmp (&ent->leaf, leaf, sizeof (FcCharLeaf)))
|
|
||||||
return &ent->leaf;
|
|
||||||
}
|
|
||||||
|
|
||||||
ent = FcCharLeafEntCreate();
|
|
||||||
if (!ent)
|
|
||||||
return 0;
|
|
||||||
FcCharLeafUsed++;
|
|
||||||
ent->leaf = *leaf;
|
|
||||||
ent->hash = hash;
|
|
||||||
ent->next = *bucket;
|
|
||||||
*bucket = ent;
|
|
||||||
return &ent->leaf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
FcCharSetThawAllLeaf (void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < FC_CHAR_LEAF_HASH_SIZE; i++)
|
|
||||||
FcCharLeafHashTable[i] = 0;
|
|
||||||
|
|
||||||
FcCharLeafTotal = 0;
|
|
||||||
FcCharLeafUsed = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < FcCharLeafBlockCount; i++)
|
|
||||||
free (FcCharLeafBlocks[i]);
|
|
||||||
|
|
||||||
free (FcCharLeafBlocks);
|
|
||||||
FcCharLeafBlocks = 0;
|
|
||||||
FcCharLeafBlockCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct _FcCharSetEnt FcCharSetEnt;
|
|
||||||
|
|
||||||
struct _FcCharSetEnt {
|
|
||||||
FcCharSetEnt *next;
|
|
||||||
FcChar32 hash;
|
|
||||||
FcCharSet set;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define FC_CHAR_SET_HASH_SIZE 67
|
|
||||||
|
|
||||||
static FcChar32
|
|
||||||
FcCharSetHash (FcCharSet *fcs)
|
|
||||||
{
|
|
||||||
FcChar32 hash = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* hash in leaves */
|
|
||||||
for (i = 0; i < fcs->num * (int) (sizeof (FcCharLeaf *) / sizeof (FcChar32)); i++)
|
|
||||||
hash = ((hash << 1) | (hash >> 31)) ^ (FcChar32)(FcCharSetLeaf(fcs, i)->map);
|
|
||||||
/* hash in numbers */
|
|
||||||
for (i = 0; i < fcs->num; i++)
|
|
||||||
hash = ((hash << 1) | (hash >> 31)) ^ *FcCharSetNumbers(fcs);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int FcCharSetTotal;
|
|
||||||
static int FcCharSetUsed;
|
|
||||||
static int FcCharSetTotalEnts, FcCharSetUsedEnts;
|
|
||||||
|
|
||||||
static FcCharSetEnt *FcCharSetHashTable[FC_CHAR_SET_HASH_SIZE];
|
|
||||||
|
|
||||||
static FcCharSet *
|
|
||||||
FcCharSetFreezeBase (FcCharSet *fcs)
|
|
||||||
{
|
|
||||||
FcChar32 hash = FcCharSetHash (fcs);
|
|
||||||
FcCharSetEnt **bucket = &FcCharSetHashTable[hash % FC_CHAR_SET_HASH_SIZE];
|
|
||||||
FcCharSetEnt *ent;
|
|
||||||
int size;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
FcCharSetTotal++;
|
|
||||||
FcCharSetTotalEnts += fcs->num;
|
|
||||||
for (ent = *bucket; ent; ent = ent->next)
|
|
||||||
{
|
|
||||||
if (ent->hash == hash &&
|
|
||||||
ent->set.num == fcs->num &&
|
|
||||||
!memcmp (FcCharSetNumbers(&ent->set),
|
|
||||||
FcCharSetNumbers(fcs),
|
|
||||||
fcs->num * sizeof (FcChar16)))
|
|
||||||
{
|
|
||||||
FcBool ok = FcTrue;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < fcs->num; i++)
|
|
||||||
if (FcCharSetLeaf(&ent->set, i) != FcCharSetLeaf(fcs, i))
|
|
||||||
ok = FcFalse;
|
|
||||||
if (ok)
|
|
||||||
return &ent->set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size = (sizeof (FcCharSetEnt) +
|
|
||||||
fcs->num * sizeof (FcCharLeaf *) +
|
|
||||||
fcs->num * sizeof (FcChar16));
|
|
||||||
ent = malloc (size);
|
|
||||||
if (!ent)
|
|
||||||
return 0;
|
|
||||||
FcMemAlloc (FC_MEM_CHARSET, size);
|
|
||||||
FcCharSetUsed++;
|
|
||||||
FcCharSetUsedEnts += fcs->num;
|
|
||||||
|
|
||||||
ent->set.ref = FC_REF_CONSTANT;
|
|
||||||
ent->set.num = fcs->num;
|
|
||||||
if (fcs->num)
|
|
||||||
{
|
|
||||||
intptr_t *ent_leaves;
|
|
||||||
|
|
||||||
ent->set.leaves_offset = sizeof (ent->set);
|
|
||||||
ent->set.numbers_offset = (ent->set.leaves_offset +
|
|
||||||
fcs->num * sizeof (intptr_t));
|
|
||||||
|
|
||||||
ent_leaves = FcCharSetLeaves (&ent->set);
|
|
||||||
for (i = 0; i < fcs->num; i++)
|
|
||||||
ent_leaves[i] = FcPtrToOffset (ent_leaves,
|
|
||||||
FcCharSetLeaf (fcs, i));
|
|
||||||
memcpy (FcCharSetNumbers (&ent->set),
|
|
||||||
FcCharSetNumbers (fcs),
|
|
||||||
fcs->num * sizeof (FcChar16));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ent->set.leaves_offset = 0;
|
|
||||||
ent->set.numbers_offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ent->hash = hash;
|
|
||||||
ent->next = *bucket;
|
|
||||||
*bucket = ent;
|
|
||||||
return &ent->set;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FcCharSetThawAll (void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
FcCharSetEnt *ent, *next;
|
|
||||||
|
|
||||||
for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
|
|
||||||
{
|
|
||||||
for (ent = FcCharSetHashTable[i]; ent; ent = next)
|
|
||||||
{
|
|
||||||
next = ent->next;
|
|
||||||
free (ent);
|
|
||||||
}
|
|
||||||
FcCharSetHashTable[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
FcCharSetTotal = 0;
|
|
||||||
FcCharSetTotalEnts = 0;
|
|
||||||
FcCharSetUsed = 0;
|
|
||||||
FcCharSetUsedEnts = 0;
|
|
||||||
|
|
||||||
FcCharSetThawAllLeaf ();
|
|
||||||
}
|
|
||||||
|
|
||||||
FcCharSet *
|
|
||||||
FcCharSetFreeze (FcCharSet *fcs)
|
|
||||||
{
|
|
||||||
FcCharSet *b;
|
|
||||||
FcCharSet *n = 0;
|
|
||||||
FcCharLeaf *l;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
b = FcCharSetCreate ();
|
|
||||||
if (!b)
|
|
||||||
goto bail0;
|
|
||||||
for (i = 0; i < fcs->num; i++)
|
|
||||||
{
|
|
||||||
l = FcCharSetFreezeLeaf (FcCharSetLeaf(fcs, i));
|
|
||||||
if (!l)
|
|
||||||
goto bail1;
|
|
||||||
if (!FcCharSetInsertLeaf (b, FcCharSetNumbers(fcs)[i] << 8, l))
|
|
||||||
goto bail1;
|
|
||||||
}
|
|
||||||
n = FcCharSetFreezeBase (b);
|
|
||||||
bail1:
|
|
||||||
if (FcCharSetLeaves (b))
|
|
||||||
{
|
|
||||||
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
|
|
||||||
free (FcCharSetLeaves (b));
|
|
||||||
}
|
|
||||||
if (FcCharSetNumbers (b))
|
|
||||||
{
|
|
||||||
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
|
|
||||||
free (FcCharSetNumbers (b));
|
|
||||||
}
|
|
||||||
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
|
|
||||||
free (b);
|
|
||||||
bail0:
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
FcCharSet *
|
FcCharSet *
|
||||||
FcNameParseCharSet (FcChar8 *string)
|
FcNameParseCharSet (FcChar8 *string)
|
||||||
{
|
{
|
||||||
FcCharSet *c, *n = 0;
|
FcCharSet *c;
|
||||||
FcChar32 ucs4;
|
FcChar32 ucs4;
|
||||||
FcCharLeaf *leaf;
|
FcCharLeaf *leaf;
|
||||||
FcCharLeaf temp;
|
FcCharLeaf temp;
|
||||||
|
@ -1143,42 +858,22 @@ FcNameParseCharSet (FcChar8 *string)
|
||||||
}
|
}
|
||||||
if (bits)
|
if (bits)
|
||||||
{
|
{
|
||||||
leaf = FcCharSetFreezeLeaf (&temp);
|
leaf = malloc (sizeof (FcCharLeaf));
|
||||||
if (!leaf)
|
if (!leaf)
|
||||||
goto bail1;
|
goto bail1;
|
||||||
|
*leaf = temp;
|
||||||
if (!FcCharSetInsertLeaf (c, ucs4, leaf))
|
if (!FcCharSetInsertLeaf (c, ucs4, leaf))
|
||||||
goto bail1;
|
goto bail1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef CHATTY
|
return c;
|
||||||
printf (" %8s %8s %8s %8s\n", "total", "totalmem", "new", "newmem");
|
|
||||||
printf ("Leaves: %8d %8d %8d %8d\n",
|
|
||||||
FcCharLeafTotal, sizeof (FcCharLeaf) * FcCharLeafTotal,
|
|
||||||
FcCharLeafUsed, sizeof (FcCharLeaf) * FcCharLeafUsed);
|
|
||||||
printf ("Charsets: %8d %8d %8d %8d\n",
|
|
||||||
FcCharSetTotal, sizeof (FcCharSet) * FcCharSetTotal,
|
|
||||||
FcCharSetUsed, sizeof (FcCharSet) * FcCharSetUsed);
|
|
||||||
printf ("Tables: %8d %8d %8d %8d\n",
|
|
||||||
FcCharSetTotalEnts, FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
|
|
||||||
FcCharSetUsedEnts, FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
|
|
||||||
printf ("Total: %8s %8d %8s %8d\n",
|
|
||||||
"",
|
|
||||||
sizeof (FcCharLeaf) * FcCharLeafTotal +
|
|
||||||
sizeof (FcCharSet) * FcCharSetTotal +
|
|
||||||
FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
|
|
||||||
"",
|
|
||||||
sizeof (FcCharLeaf) * FcCharLeafUsed +
|
|
||||||
sizeof (FcCharSet) * FcCharSetUsed +
|
|
||||||
FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
|
|
||||||
#endif
|
|
||||||
n = FcCharSetFreezeBase (c);
|
|
||||||
bail1:
|
bail1:
|
||||||
if (FcCharSetLeaves (c))
|
if (c->num)
|
||||||
{
|
{
|
||||||
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
|
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
|
||||||
free (FcCharSetLeaves (c));
|
free (FcCharSetLeaves (c));
|
||||||
}
|
}
|
||||||
if (FcCharSetNumbers (c))
|
if (c->num)
|
||||||
{
|
{
|
||||||
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
|
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
|
||||||
free (FcCharSetNumbers (c));
|
free (FcCharSetNumbers (c));
|
||||||
|
@ -1186,7 +881,7 @@ bail1:
|
||||||
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
|
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
|
||||||
free (c);
|
free (c);
|
||||||
bail0:
|
bail0:
|
||||||
return n;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
|
@ -1262,13 +957,334 @@ FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _FcCharLeafEnt FcCharLeafEnt;
|
||||||
|
|
||||||
|
struct _FcCharLeafEnt {
|
||||||
|
FcCharLeafEnt *next;
|
||||||
|
FcChar32 hash;
|
||||||
|
FcCharLeaf leaf;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FC_CHAR_LEAF_BLOCK (4096 / sizeof (FcCharLeafEnt))
|
||||||
|
#define FC_CHAR_LEAF_HASH_SIZE 257
|
||||||
|
|
||||||
|
typedef struct _FcCharSetEnt FcCharSetEnt;
|
||||||
|
|
||||||
|
struct _FcCharSetEnt {
|
||||||
|
FcCharSetEnt *next;
|
||||||
|
FcChar32 hash;
|
||||||
|
FcCharSet set;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _FcCharSetOrigEnt FcCharSetOrigEnt;
|
||||||
|
|
||||||
|
struct _FcCharSetOrigEnt {
|
||||||
|
FcCharSetOrigEnt *next;
|
||||||
|
const FcCharSet *orig;
|
||||||
|
const FcCharSet *frozen;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FC_CHAR_SET_HASH_SIZE 67
|
||||||
|
|
||||||
|
struct _FcCharSetFreezer {
|
||||||
|
FcCharLeafEnt *leaf_hash_table[FC_CHAR_LEAF_HASH_SIZE];
|
||||||
|
FcCharLeafEnt **leaf_blocks;
|
||||||
|
int leaf_block_count;
|
||||||
|
FcCharSetEnt *set_hash_table[FC_CHAR_SET_HASH_SIZE];
|
||||||
|
FcCharSetOrigEnt *orig_hash_table[FC_CHAR_SET_HASH_SIZE];
|
||||||
|
FcCharLeafEnt *current_block;
|
||||||
|
int leaf_remain;
|
||||||
|
int leaves_seen;
|
||||||
|
int charsets_seen;
|
||||||
|
int leaves_allocated;
|
||||||
|
int charsets_allocated;
|
||||||
|
};
|
||||||
|
|
||||||
|
static FcCharLeafEnt *
|
||||||
|
FcCharLeafEntCreate (FcCharSetFreezer *freezer)
|
||||||
|
{
|
||||||
|
if (!freezer->leaf_remain)
|
||||||
|
{
|
||||||
|
FcCharLeafEnt **newBlocks;
|
||||||
|
|
||||||
|
freezer->leaf_block_count++;
|
||||||
|
newBlocks = realloc (freezer->leaf_blocks, freezer->leaf_block_count * sizeof (FcCharLeafEnt *));
|
||||||
|
if (!newBlocks)
|
||||||
|
return 0;
|
||||||
|
freezer->leaf_blocks = newBlocks;
|
||||||
|
freezer->current_block = freezer->leaf_blocks[freezer->leaf_block_count-1] = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
|
||||||
|
if (!freezer->current_block)
|
||||||
|
return 0;
|
||||||
|
FcMemAlloc (FC_MEM_CHARLEAF, FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
|
||||||
|
freezer->leaf_remain = FC_CHAR_LEAF_BLOCK;
|
||||||
|
}
|
||||||
|
freezer->leaf_remain--;
|
||||||
|
freezer->leaves_allocated++;
|
||||||
|
return freezer->current_block++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcChar32
|
||||||
|
FcCharLeafHash (FcCharLeaf *leaf)
|
||||||
|
{
|
||||||
|
FcChar32 hash = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 256/32; i++)
|
||||||
|
hash = ((hash << 1) | (hash >> 31)) ^ leaf->map[i];
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcCharLeaf *
|
||||||
|
FcCharSetFreezeLeaf (FcCharSetFreezer *freezer, FcCharLeaf *leaf)
|
||||||
|
{
|
||||||
|
FcChar32 hash = FcCharLeafHash (leaf);
|
||||||
|
FcCharLeafEnt **bucket = &freezer->leaf_hash_table[hash % FC_CHAR_LEAF_HASH_SIZE];
|
||||||
|
FcCharLeafEnt *ent;
|
||||||
|
|
||||||
|
for (ent = *bucket; ent; ent = ent->next)
|
||||||
|
{
|
||||||
|
if (ent->hash == hash && !memcmp (&ent->leaf, leaf, sizeof (FcCharLeaf)))
|
||||||
|
return &ent->leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent = FcCharLeafEntCreate(freezer);
|
||||||
|
if (!ent)
|
||||||
|
return 0;
|
||||||
|
ent->leaf = *leaf;
|
||||||
|
ent->hash = hash;
|
||||||
|
ent->next = *bucket;
|
||||||
|
*bucket = ent;
|
||||||
|
return &ent->leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcChar32
|
||||||
|
FcCharSetHash (FcCharSet *fcs)
|
||||||
|
{
|
||||||
|
FcChar32 hash = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* hash in leaves */
|
||||||
|
for (i = 0; i < fcs->num * (int) (sizeof (FcCharLeaf *) / sizeof (FcChar32)); i++)
|
||||||
|
hash = ((hash << 1) | (hash >> 31)) ^ (FcChar32)(FcCharSetLeaf(fcs, i)->map);
|
||||||
|
/* hash in numbers */
|
||||||
|
for (i = 0; i < fcs->num; i++)
|
||||||
|
hash = ((hash << 1) | (hash >> 31)) ^ *FcCharSetNumbers(fcs);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
FcCharSetFreezeOrig (FcCharSetFreezer *freezer, const FcCharSet *orig, const FcCharSet *frozen)
|
||||||
|
{
|
||||||
|
FcCharSetOrigEnt **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE];
|
||||||
|
FcCharSetOrigEnt *ent;
|
||||||
|
|
||||||
|
ent = malloc (sizeof (FcCharSetOrigEnt));
|
||||||
|
if (!ent)
|
||||||
|
return FcFalse;
|
||||||
|
ent->orig = orig;
|
||||||
|
ent->frozen = frozen;
|
||||||
|
ent->next = *bucket;
|
||||||
|
*bucket = ent;
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcCharSet *
|
||||||
|
FcCharSetFreezeBase (FcCharSetFreezer *freezer, FcCharSet *fcs, const FcCharSet *orig)
|
||||||
|
{
|
||||||
|
FcChar32 hash = FcCharSetHash (fcs);
|
||||||
|
FcCharSetEnt **bucket = &freezer->set_hash_table[hash % FC_CHAR_SET_HASH_SIZE];
|
||||||
|
FcCharSetEnt *ent;
|
||||||
|
int size;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (ent = *bucket; ent; ent = ent->next)
|
||||||
|
{
|
||||||
|
if (ent->hash == hash &&
|
||||||
|
ent->set.num == fcs->num &&
|
||||||
|
!memcmp (FcCharSetNumbers(&ent->set),
|
||||||
|
FcCharSetNumbers(fcs),
|
||||||
|
fcs->num * sizeof (FcChar16)))
|
||||||
|
{
|
||||||
|
FcBool ok = FcTrue;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < fcs->num; i++)
|
||||||
|
if (FcCharSetLeaf(&ent->set, i) != FcCharSetLeaf(fcs, i))
|
||||||
|
ok = FcFalse;
|
||||||
|
if (ok)
|
||||||
|
return &ent->set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size = (sizeof (FcCharSetEnt) +
|
||||||
|
fcs->num * sizeof (FcCharLeaf *) +
|
||||||
|
fcs->num * sizeof (FcChar16));
|
||||||
|
ent = malloc (size);
|
||||||
|
if (!ent)
|
||||||
|
return 0;
|
||||||
|
FcMemAlloc (FC_MEM_CHARSET, size);
|
||||||
|
|
||||||
|
freezer->charsets_allocated++;
|
||||||
|
|
||||||
|
ent->set.ref = FC_REF_CONSTANT;
|
||||||
|
ent->set.num = fcs->num;
|
||||||
|
if (fcs->num)
|
||||||
|
{
|
||||||
|
intptr_t *ent_leaves;
|
||||||
|
|
||||||
|
ent->set.leaves_offset = sizeof (ent->set);
|
||||||
|
ent->set.numbers_offset = (ent->set.leaves_offset +
|
||||||
|
fcs->num * sizeof (intptr_t));
|
||||||
|
|
||||||
|
ent_leaves = FcCharSetLeaves (&ent->set);
|
||||||
|
for (i = 0; i < fcs->num; i++)
|
||||||
|
ent_leaves[i] = FcPtrToOffset (ent_leaves,
|
||||||
|
FcCharSetLeaf (fcs, i));
|
||||||
|
memcpy (FcCharSetNumbers (&ent->set),
|
||||||
|
FcCharSetNumbers (fcs),
|
||||||
|
fcs->num * sizeof (FcChar16));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ent->set.leaves_offset = 0;
|
||||||
|
ent->set.numbers_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent->hash = hash;
|
||||||
|
ent->next = *bucket;
|
||||||
|
*bucket = ent;
|
||||||
|
|
||||||
|
return &ent->set;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const FcCharSet *
|
||||||
|
FcCharSetFindFrozen (FcCharSetFreezer *freezer, const FcCharSet *orig)
|
||||||
|
{
|
||||||
|
FcCharSetOrigEnt **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE];
|
||||||
|
FcCharSetOrigEnt *ent;
|
||||||
|
|
||||||
|
for (ent = *bucket; ent; ent = ent->next)
|
||||||
|
if (ent->orig == orig)
|
||||||
|
return ent->frozen;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const FcCharSet *
|
||||||
|
FcCharSetFreeze (FcCharSetFreezer *freezer, const FcCharSet *fcs)
|
||||||
|
{
|
||||||
|
FcCharSet *b;
|
||||||
|
const FcCharSet *n = 0;
|
||||||
|
FcCharLeaf *l;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
n = FcCharSetFindFrozen (freezer, fcs);
|
||||||
|
if (n)
|
||||||
|
return n;
|
||||||
|
|
||||||
|
b = FcCharSetCreate ();
|
||||||
|
if (!b)
|
||||||
|
goto bail0;
|
||||||
|
for (i = 0; i < fcs->num; i++)
|
||||||
|
{
|
||||||
|
l = FcCharSetFreezeLeaf (freezer, FcCharSetLeaf(fcs, i));
|
||||||
|
if (!l)
|
||||||
|
goto bail1;
|
||||||
|
if (!FcCharSetInsertLeaf (b, FcCharSetNumbers(fcs)[i] << 8, l))
|
||||||
|
goto bail1;
|
||||||
|
}
|
||||||
|
n = FcCharSetFreezeBase (freezer, b, fcs);
|
||||||
|
if (!FcCharSetFreezeOrig (freezer, fcs, n))
|
||||||
|
{
|
||||||
|
n = NULL;
|
||||||
|
goto bail1;
|
||||||
|
}
|
||||||
|
freezer->charsets_seen++;
|
||||||
|
freezer->leaves_seen += fcs->num;
|
||||||
|
bail1:
|
||||||
|
if (b->num)
|
||||||
|
{
|
||||||
|
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
|
||||||
|
free (FcCharSetLeaves (b));
|
||||||
|
}
|
||||||
|
if (b->num)
|
||||||
|
{
|
||||||
|
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
|
||||||
|
free (FcCharSetNumbers (b));
|
||||||
|
}
|
||||||
|
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
|
||||||
|
free (b);
|
||||||
|
bail0:
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FcCharSetFreezer *
|
||||||
|
FcCharSetFreezerCreate (void)
|
||||||
|
{
|
||||||
|
FcCharSetFreezer *freezer;
|
||||||
|
|
||||||
|
freezer = calloc (1, sizeof (FcCharSetFreezer));
|
||||||
|
return freezer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FcCharSetFreezerDestroy (FcCharSetFreezer *freezer)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (FcDebug() & FC_DBG_CACHE)
|
||||||
|
{
|
||||||
|
printf ("\ncharsets %d -> %d leaves %d -> %d\n",
|
||||||
|
freezer->charsets_seen, freezer->charsets_allocated,
|
||||||
|
freezer->leaves_seen, freezer->leaves_allocated);
|
||||||
|
}
|
||||||
|
for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
|
||||||
|
{
|
||||||
|
FcCharSetEnt *ent, *next;
|
||||||
|
for (ent = freezer->set_hash_table[i]; ent; ent = next)
|
||||||
|
{
|
||||||
|
next = ent->next;
|
||||||
|
free (ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
|
||||||
|
{
|
||||||
|
FcCharSetOrigEnt *ent, *next;
|
||||||
|
for (ent = freezer->orig_hash_table[i]; ent; ent = next)
|
||||||
|
{
|
||||||
|
next = ent->next;
|
||||||
|
free (ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < freezer->leaf_block_count; i++)
|
||||||
|
free (freezer->leaf_blocks[i]);
|
||||||
|
|
||||||
|
free (freezer->leaf_blocks);
|
||||||
|
free (freezer);
|
||||||
|
}
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
|
FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
|
||||||
{
|
{
|
||||||
intptr_t *leaves = FcCharSetLeaves (cs);
|
intptr_t *leaves;
|
||||||
FcChar16 *numbers = FcCharSetNumbers (cs);
|
FcChar16 *numbers;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (cs->ref != FC_REF_CONSTANT)
|
||||||
|
{
|
||||||
|
if (!serialize->cs_freezer)
|
||||||
|
{
|
||||||
|
serialize->cs_freezer = FcCharSetFreezerCreate ();
|
||||||
|
if (!serialize->cs_freezer)
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
cs = FcCharSetFreeze (serialize->cs_freezer, cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
leaves = FcCharSetLeaves (cs);
|
||||||
|
numbers = FcCharSetNumbers (cs);
|
||||||
|
|
||||||
if (!FcSerializeAlloc (serialize, cs, sizeof (FcCharSet)))
|
if (!FcSerializeAlloc (serialize, cs, sizeof (FcCharSet)))
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
if (!FcSerializeAlloc (serialize, leaves, cs->num * sizeof (intptr_t)))
|
if (!FcSerializeAlloc (serialize, leaves, cs->num * sizeof (intptr_t)))
|
||||||
|
@ -1285,12 +1301,20 @@ FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
|
||||||
FcCharSet *
|
FcCharSet *
|
||||||
FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
|
FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
|
||||||
{
|
{
|
||||||
FcCharSet *cs_serialized = FcSerializePtr (serialize, cs);
|
FcCharSet *cs_serialized;
|
||||||
intptr_t *leaves, *leaves_serialized;
|
intptr_t *leaves, *leaves_serialized;
|
||||||
FcChar16 *numbers, *numbers_serialized;
|
FcChar16 *numbers, *numbers_serialized;
|
||||||
FcCharLeaf *leaf, *leaf_serialized;
|
FcCharLeaf *leaf, *leaf_serialized;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (cs->ref != FC_REF_CONSTANT && serialize->cs_freezer)
|
||||||
|
{
|
||||||
|
cs = FcCharSetFindFrozen (serialize->cs_freezer, cs);
|
||||||
|
if (!cs)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cs_serialized = FcSerializePtr (serialize, cs);
|
||||||
if (!cs_serialized)
|
if (!cs_serialized)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
177
src/fcdir.c
177
src/fcdir.c
|
@ -85,12 +85,8 @@ FcFileScanConfig (FcFontSet *set,
|
||||||
FcStrSet *dirs,
|
FcStrSet *dirs,
|
||||||
FcBlanks *blanks,
|
FcBlanks *blanks,
|
||||||
const FcChar8 *file,
|
const FcChar8 *file,
|
||||||
FcBool force,
|
|
||||||
FcConfig *config)
|
FcConfig *config)
|
||||||
{
|
{
|
||||||
if (config && !FcConfigAcceptFilename (config, file))
|
|
||||||
return FcTrue;
|
|
||||||
|
|
||||||
if (FcFileIsDir (file))
|
if (FcFileIsDir (file))
|
||||||
return FcStrSetAdd (dirs, file);
|
return FcStrSetAdd (dirs, file);
|
||||||
else
|
else
|
||||||
|
@ -105,13 +101,12 @@ FcFileScan (FcFontSet *set,
|
||||||
const FcChar8 *file,
|
const FcChar8 *file,
|
||||||
FcBool force)
|
FcBool force)
|
||||||
{
|
{
|
||||||
return FcFileScanConfig (set, dirs, blanks, file, force, 0);
|
return FcFileScanConfig (set, dirs, blanks, file, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
|
* Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmpstringp(const void *p1, const void *p2)
|
cmpstringp(const void *p1, const void *p2)
|
||||||
{
|
{
|
||||||
|
@ -119,62 +114,41 @@ cmpstringp(const void *p1, const void *p2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan 'dir', adding font files to 'set' and
|
* Scan the specified directory and construct a cache of its contents
|
||||||
* subdirectories to 'dirs'
|
|
||||||
*/
|
*/
|
||||||
|
FcCache *
|
||||||
FcBool
|
FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
|
||||||
FcDirScanConfig (FcFontSet *set,
|
|
||||||
FcStrSet *dirs,
|
|
||||||
FcBlanks *blanks,
|
|
||||||
const FcChar8 *dir,
|
|
||||||
FcBool force,
|
|
||||||
FcConfig *config)
|
|
||||||
{
|
{
|
||||||
DIR *d;
|
DIR *d;
|
||||||
FcChar8 *canon_dir;
|
|
||||||
struct dirent *e;
|
struct dirent *e;
|
||||||
FcStrSet *dirlist, *filelist;
|
FcStrSet *files;
|
||||||
|
FcStrSet *dirs;
|
||||||
FcChar8 *file;
|
FcChar8 *file;
|
||||||
FcChar8 *base;
|
FcChar8 *base;
|
||||||
FcBool ret = FcTrue;
|
FcBool ret = FcTrue;
|
||||||
FcFontSet *tmpSet;
|
FcFontSet *set;
|
||||||
int i;
|
int i;
|
||||||
|
FcBlanks *blanks = FcConfigGetBlanks (config);
|
||||||
|
FcCache *cache = NULL;
|
||||||
|
|
||||||
canon_dir = FcStrCanonFilename (dir);
|
|
||||||
if (!canon_dir) canon_dir = (FcChar8 *) dir;
|
|
||||||
|
|
||||||
if (config && !FcConfigAcceptFilename (config, canon_dir)) {
|
|
||||||
ret = FcTrue;
|
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!force)
|
|
||||||
{
|
|
||||||
if (FcDirCacheRead (set, dirs, canon_dir, config)) {
|
|
||||||
ret = FcTrue;
|
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FcDebug () & FC_DBG_FONTSET)
|
if (FcDebug () & FC_DBG_FONTSET)
|
||||||
printf ("cache scan dir %s\n", canon_dir);
|
printf ("cache scan dir %s\n", dir);
|
||||||
|
|
||||||
/* freed below */
|
/* freed below */
|
||||||
file = (FcChar8 *) malloc (strlen ((char *) canon_dir) + 1 + FC_MAX_FILE_LEN + 1);
|
file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
ret = FcFalse;
|
ret = FcFalse;
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy ((char *) file, (char *) canon_dir);
|
strcpy ((char *) file, (char *) dir);
|
||||||
strcat ((char *) file, "/");
|
strcat ((char *) file, "/");
|
||||||
base = file + strlen ((char *) file);
|
base = file + strlen ((char *) file);
|
||||||
|
|
||||||
if (FcDebug () & FC_DBG_SCAN)
|
if (FcDebug () & FC_DBG_SCAN)
|
||||||
printf ("\tScanning dir %s\n", canon_dir);
|
printf ("\tScanning dir %s\n", dir);
|
||||||
|
|
||||||
d = opendir ((char *) canon_dir);
|
d = opendir ((char *) dir);
|
||||||
if (!d)
|
if (!d)
|
||||||
{
|
{
|
||||||
/* Don't complain about missing directories */
|
/* Don't complain about missing directories */
|
||||||
|
@ -185,84 +159,64 @@ FcDirScanConfig (FcFontSet *set,
|
||||||
goto bail_1;
|
goto bail_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpSet = FcFontSetCreate();
|
set = FcFontSetCreate();
|
||||||
if (!tmpSet)
|
if (!set)
|
||||||
{
|
{
|
||||||
ret = FcFalse;
|
ret = FcFalse;
|
||||||
goto bail0;
|
goto bail0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirlist = FcStrSetCreate ();
|
files = FcStrSetCreate ();
|
||||||
if (!dirlist)
|
if (!files)
|
||||||
{
|
{
|
||||||
ret = FcFalse;
|
ret = FcFalse;
|
||||||
goto bail1;
|
goto bail1;
|
||||||
}
|
}
|
||||||
filelist = FcStrSetCreate ();
|
|
||||||
if (!filelist)
|
|
||||||
{
|
|
||||||
ret = FcFalse;
|
|
||||||
goto bail2;
|
|
||||||
}
|
|
||||||
while ((e = readdir (d)))
|
while ((e = readdir (d)))
|
||||||
{
|
{
|
||||||
if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
|
if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
|
||||||
{
|
{
|
||||||
strcpy ((char *) base, (char *) e->d_name);
|
strcpy ((char *) base, (char *) e->d_name);
|
||||||
if (FcFileIsDir (file)) {
|
if (!FcStrSetAdd (files, file)) {
|
||||||
if (!FcStrSetAdd (dirlist, file)) {
|
ret = FcFalse;
|
||||||
ret = FcFalse;
|
goto bail2;
|
||||||
goto bail3;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!FcStrSetAdd (filelist, file)) {
|
|
||||||
ret = FcFalse;
|
|
||||||
goto bail3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sort files and dirs to make things prettier
|
* Sort files to make things prettier
|
||||||
*/
|
*/
|
||||||
qsort(dirlist->strs, dirlist->num, sizeof(FcChar8 *), cmpstringp);
|
qsort(files->strs, files->num, sizeof(FcChar8 *), cmpstringp);
|
||||||
qsort(filelist->strs, filelist->num, sizeof(FcChar8 *), cmpstringp);
|
|
||||||
|
|
||||||
for (i = 0; i < filelist->num; i++)
|
dirs = FcStrSetCreate ();
|
||||||
FcFileScanFontConfig (tmpSet, blanks, filelist->strs[i], config);
|
if (!dirs)
|
||||||
|
goto bail2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that the directory has been scanned,
|
* Scan file files to build font patterns
|
||||||
* write out the cache file
|
|
||||||
*/
|
*/
|
||||||
FcDirCacheWrite (tmpSet, dirlist, canon_dir, config);
|
for (i = 0; i < files->num; i++)
|
||||||
|
FcFileScanConfig (set, dirs, blanks, files->strs[i], config);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the discovered fonts to our internal non-cache list
|
* Build the cache object
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < tmpSet->nfont; i++)
|
cache = FcDirCacheBuild (set, dir, dirs);
|
||||||
FcFontSetAdd (set, tmpSet->fonts[i]);
|
if (!cache)
|
||||||
|
goto bail3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the patterns in tmpset now belong to set; don't free them
|
* Write out the cache file, ignoring any troubles
|
||||||
*/
|
*/
|
||||||
tmpSet->nfont = 0;
|
FcDirCacheWrite (cache, config);
|
||||||
|
|
||||||
/*
|
|
||||||
* Add the discovered directories to the list to be scanned
|
|
||||||
*/
|
|
||||||
for (i = 0; i < dirlist->num; i++)
|
|
||||||
if (!FcStrSetAdd (dirs, dirlist->strs[i])) {
|
|
||||||
ret = FcFalse;
|
|
||||||
goto bail3;
|
|
||||||
}
|
|
||||||
|
|
||||||
bail3:
|
bail3:
|
||||||
FcStrSetDestroy (filelist);
|
FcStrSetDestroy (dirs);
|
||||||
bail2:
|
bail2:
|
||||||
FcStrSetDestroy (dirlist);
|
FcStrSetDestroy (files);
|
||||||
bail1:
|
bail1:
|
||||||
FcFontSetDestroy (tmpSet);
|
FcFontSetDestroy (set);
|
||||||
|
|
||||||
bail0:
|
bail0:
|
||||||
closedir (d);
|
closedir (d);
|
||||||
|
@ -270,8 +224,49 @@ FcDirScanConfig (FcFontSet *set,
|
||||||
bail_1:
|
bail_1:
|
||||||
free (file);
|
free (file);
|
||||||
bail:
|
bail:
|
||||||
if (canon_dir != dir) free (canon_dir);
|
return cache;
|
||||||
return ret;
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read (or construct) the cache for a directory
|
||||||
|
*/
|
||||||
|
FcCache *
|
||||||
|
FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config)
|
||||||
|
{
|
||||||
|
FcCache *cache = NULL;
|
||||||
|
FcChar8 *canon_dir;
|
||||||
|
|
||||||
|
canon_dir = FcStrCanonFilename (dir);
|
||||||
|
if (!canon_dir) canon_dir = (FcChar8 *) dir;
|
||||||
|
|
||||||
|
if (config && !FcConfigAcceptFilename (config, canon_dir)) {
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to use existing cache file */
|
||||||
|
if (!force)
|
||||||
|
cache = FcDirCacheLoad (canon_dir, config, NULL);
|
||||||
|
|
||||||
|
/* Not using existing cache file, construct new cache */
|
||||||
|
if (!cache)
|
||||||
|
cache = FcDirCacheScan (canon_dir, config);
|
||||||
|
|
||||||
|
bail:
|
||||||
|
if (canon_dir != dir)
|
||||||
|
free (canon_dir);
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
FcBool
|
||||||
|
FcDirScanConfig (FcFontSet *set,
|
||||||
|
FcStrSet *dirs,
|
||||||
|
FcBlanks *blanks,
|
||||||
|
const FcChar8 *dir,
|
||||||
|
FcBool force,
|
||||||
|
FcConfig *config)
|
||||||
|
{
|
||||||
|
return FcFalse; /* XXX fixme */
|
||||||
}
|
}
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
|
@ -282,11 +277,11 @@ FcDirScan (FcFontSet *set,
|
||||||
const FcChar8 *dir,
|
const FcChar8 *dir,
|
||||||
FcBool force)
|
FcBool force)
|
||||||
{
|
{
|
||||||
return FcDirScanConfig (set, dirs, blanks, dir, force, 0);
|
return FcDirScanConfig (set, dirs, blanks, dir, force, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
|
FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
|
||||||
{
|
{
|
||||||
return FcFalse;
|
return FcFalse; /* XXX deprecated */
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,6 @@ FcFini (void)
|
||||||
FcConfigDestroy (_fcConfig);
|
FcConfigDestroy (_fcConfig);
|
||||||
|
|
||||||
FcPatternFini ();
|
FcPatternFini ();
|
||||||
FcCharSetThawAll ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
70
src/fcint.h
70
src/fcint.h
|
@ -55,7 +55,6 @@
|
||||||
|
|
||||||
#define FC_FONT_FILE_INVALID ((FcChar8 *) ".")
|
#define FC_FONT_FILE_INVALID ((FcChar8 *) ".")
|
||||||
#define FC_FONT_FILE_DIR ((FcChar8 *) ".dir")
|
#define FC_FONT_FILE_DIR ((FcChar8 *) ".dir")
|
||||||
#define FC_GLOBAL_MAGIC_COOKIE "GLOBAL"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define FC_SEARCH_PATH_SEPARATOR ';'
|
#define FC_SEARCH_PATH_SEPARATOR ';'
|
||||||
|
@ -75,6 +74,7 @@
|
||||||
#define FC_DBG_MEMORY 512
|
#define FC_DBG_MEMORY 512
|
||||||
#define FC_DBG_CONFIG 1024
|
#define FC_DBG_CONFIG 1024
|
||||||
#define FC_DBG_LANGSET 2048
|
#define FC_DBG_LANGSET 2048
|
||||||
|
#define FC_DBG_OBJTYPES 4096
|
||||||
|
|
||||||
#define FC_MEM_CHARSET 0
|
#define FC_MEM_CHARSET 0
|
||||||
#define FC_MEM_CHARLEAF 1
|
#define FC_MEM_CHARLEAF 1
|
||||||
|
@ -307,7 +307,8 @@ typedef struct _FcStrBuf {
|
||||||
} FcStrBuf;
|
} FcStrBuf;
|
||||||
|
|
||||||
typedef struct _FcCache {
|
typedef struct _FcCache {
|
||||||
int magic; /* FC_CACHE_MAGIC */
|
int magic; /* FC_CACHE_MAGIC_MMAP or FC_CACHE_ALLOC */
|
||||||
|
int version; /* FC_CACHE_CONTENT_VERSION */
|
||||||
intptr_t size; /* size of file */
|
intptr_t size; /* size of file */
|
||||||
intptr_t dir; /* offset to dir name */
|
intptr_t dir; /* offset to dir name */
|
||||||
intptr_t dirs; /* offset to subdirs */
|
intptr_t dirs; /* offset to subdirs */
|
||||||
|
@ -318,6 +319,9 @@ typedef struct _FcCache {
|
||||||
#define FcCacheDir(c) FcOffsetMember(c,dir,FcChar8)
|
#define FcCacheDir(c) FcOffsetMember(c,dir,FcChar8)
|
||||||
#define FcCacheDirs(c) FcOffsetMember(c,dirs,intptr_t)
|
#define FcCacheDirs(c) FcOffsetMember(c,dirs,intptr_t)
|
||||||
#define FcCacheSet(c) FcOffsetMember(c,set,FcFontSet)
|
#define FcCacheSet(c) FcOffsetMember(c,set,FcFontSet)
|
||||||
|
#define FcCacheSubdir(c,i) FcOffsetToPtr (FcCacheDirs(cache),\
|
||||||
|
FcCacheDirs(cache)[i], \
|
||||||
|
FcChar8)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used while constructing a directory cache object
|
* Used while constructing a directory cache object
|
||||||
|
@ -331,8 +335,11 @@ typedef struct _FcSerializeBucket {
|
||||||
intptr_t offset;
|
intptr_t offset;
|
||||||
} FcSerializeBucket;
|
} FcSerializeBucket;
|
||||||
|
|
||||||
|
typedef struct _FcCharSetFreezer FcCharSetFreezer;
|
||||||
|
|
||||||
typedef struct _FcSerialize {
|
typedef struct _FcSerialize {
|
||||||
intptr_t size;
|
intptr_t size;
|
||||||
|
FcCharSetFreezer *cs_freezer;
|
||||||
void *linear;
|
void *linear;
|
||||||
FcSerializeBucket *buckets[FC_SERIALIZE_HASH_SIZE];
|
FcSerializeBucket *buckets[FC_SERIALIZE_HASH_SIZE];
|
||||||
} FcSerialize;
|
} FcSerialize;
|
||||||
|
@ -389,8 +396,9 @@ typedef struct _FcCaseFold {
|
||||||
|
|
||||||
#define fc_alignof(type) offsetof (struct { char c; type member; }, member)
|
#define fc_alignof(type) offsetof (struct { char c; type member; }, member)
|
||||||
|
|
||||||
#define FC_CACHE_MAGIC 0xFC02FC04
|
#define FC_CACHE_MAGIC_MMAP 0xFC02FC04
|
||||||
#define FC_CACHE_MAGIC_COPY 0xFC02FC05
|
#define FC_CACHE_MAGIC_ALLOC 0xFC02FC05
|
||||||
|
#define FC_CACHE_CONTENT_VERSION 1
|
||||||
|
|
||||||
struct _FcAtomic {
|
struct _FcAtomic {
|
||||||
FcChar8 *file; /* original file name */
|
FcChar8 *file; /* original file name */
|
||||||
|
@ -490,31 +498,30 @@ typedef struct _FcCharMap FcCharMap;
|
||||||
|
|
||||||
/* fccache.c */
|
/* fccache.c */
|
||||||
|
|
||||||
FcFontSet *
|
|
||||||
FcCacheRead (FcConfig *config);
|
|
||||||
|
|
||||||
FcBool
|
|
||||||
FcDirCacheWrite (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config);
|
|
||||||
|
|
||||||
FcBool
|
|
||||||
FcDirCacheConsume (FILE *file, FcFontSet *set, FcStrSet *dirs,
|
|
||||||
const FcChar8 *dir, char *dirname);
|
|
||||||
|
|
||||||
void
|
|
||||||
FcDirCacheUnmap (FcCache *cache);
|
|
||||||
|
|
||||||
FcBool
|
|
||||||
FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config);
|
|
||||||
|
|
||||||
FcCache *
|
|
||||||
FcDirCacheMap (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file);
|
|
||||||
|
|
||||||
FcBool
|
|
||||||
FcDirCacheLoad (int fd, off_t size, void *closure);
|
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config);
|
FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config);
|
||||||
|
|
||||||
|
void
|
||||||
|
FcDirCacheUnload (FcCache *cache);
|
||||||
|
|
||||||
|
FcCache *
|
||||||
|
FcDirCacheScan (const FcChar8 *dir, FcConfig *config);
|
||||||
|
|
||||||
|
FcCache *
|
||||||
|
FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file);
|
||||||
|
|
||||||
|
FcCache *
|
||||||
|
FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat);
|
||||||
|
|
||||||
|
FcBool
|
||||||
|
FcDirCacheValid (const FcChar8 *dir);
|
||||||
|
|
||||||
|
FcCache *
|
||||||
|
FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs);
|
||||||
|
|
||||||
|
FcBool
|
||||||
|
FcDirCacheWrite (FcCache *cache, FcConfig *config);
|
||||||
|
|
||||||
/* fccfg.c */
|
/* fccfg.c */
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
|
@ -616,11 +623,8 @@ FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l);
|
||||||
void
|
void
|
||||||
FcLangCharSetPopulate (void);
|
FcLangCharSetPopulate (void);
|
||||||
|
|
||||||
FcCharSet *
|
|
||||||
FcCharSetFreeze (FcCharSet *cs);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FcCharSetThawAll (void);
|
FcCharSetFreezerDestroy (FcCharSetFreezer *freezer);
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c);
|
FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c);
|
||||||
|
@ -687,17 +691,19 @@ FcFileScanConfig (FcFontSet *set,
|
||||||
FcStrSet *dirs,
|
FcStrSet *dirs,
|
||||||
FcBlanks *blanks,
|
FcBlanks *blanks,
|
||||||
const FcChar8 *file,
|
const FcChar8 *file,
|
||||||
FcBool force,
|
|
||||||
FcConfig *config);
|
FcConfig *config);
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcDirScanConfig (FcFontSet *set,
|
FcDirScanConfig (FcFontSet *set,
|
||||||
FcStrSet *dirs,
|
FcStrSet *dirs,
|
||||||
FcBlanks *blanks,
|
FcBlanks *blanks,
|
||||||
const FcChar8 *dir,
|
const FcChar8 *dir,
|
||||||
FcBool force,
|
FcBool force,
|
||||||
FcConfig *config);
|
FcConfig *config);
|
||||||
|
|
||||||
|
FcCache *
|
||||||
|
FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config);
|
||||||
|
|
||||||
/* fcfont.c */
|
/* fcfont.c */
|
||||||
int
|
int
|
||||||
FcFontDebug (void);
|
FcFontDebug (void);
|
||||||
|
|
|
@ -491,7 +491,15 @@ FcPatternObjectAddWithBinding (FcPattern *p,
|
||||||
* Make sure the stored type is valid for built-in objects
|
* Make sure the stored type is valid for built-in objects
|
||||||
*/
|
*/
|
||||||
if (!FcObjectValidType (object, value.type))
|
if (!FcObjectValidType (object, value.type))
|
||||||
|
{
|
||||||
|
if (FcDebug() & FC_DBG_OBJTYPES)
|
||||||
|
{
|
||||||
|
printf ("FcPattern object %s does not accept value ",
|
||||||
|
FcObjectName (object));
|
||||||
|
FcValuePrint (value);
|
||||||
|
}
|
||||||
goto bail1;
|
goto bail1;
|
||||||
|
}
|
||||||
|
|
||||||
new->value = value;
|
new->value = value;
|
||||||
new->binding = binding;
|
new->binding = binding;
|
||||||
|
|
|
@ -54,6 +54,7 @@ FcSerializeCreate (void)
|
||||||
return NULL;
|
return NULL;
|
||||||
serialize->size = 0;
|
serialize->size = 0;
|
||||||
serialize->linear = NULL;
|
serialize->linear = NULL;
|
||||||
|
serialize->cs_freezer = NULL;
|
||||||
memset (serialize->buckets, '\0', sizeof (serialize->buckets));
|
memset (serialize->buckets, '\0', sizeof (serialize->buckets));
|
||||||
return serialize;
|
return serialize;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +73,8 @@ FcSerializeDestroy (FcSerialize *serialize)
|
||||||
free (buck);
|
free (buck);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (serialize->cs_freezer)
|
||||||
|
FcCharSetFreezerDestroy (serialize->cs_freezer);
|
||||||
free (serialize);
|
free (serialize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue