}
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;
const FcChar8 *dir;
FcFontSet *set;
FcStrSet *subdirs;
FcStrList *sublist;
+ FcCache *cache;
struct stat statb;
FcBool was_valid;
+ int i;
/*
* Now scan all of the directories into separate databases
{
if (verbose)
{
- printf ("%s: \"%s\": ", program, dir);
+ printf ("%s: ", dir);
fflush (stdout);
}
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)
{
switch (errno) {
case ENOTDIR:
if (verbose)
printf ("skipping, no such directory\n");
- FcFontSetDestroy (set);
- FcStrSetDestroy (subdirs);
continue;
case EACCES:
case EROFS:
perror ("");
ret++;
- FcFontSetDestroy (set);
- FcStrSetDestroy (subdirs);
continue;
}
}
{
fprintf (stderr, "\"%s\": ", dir);
perror ("");
- FcFontSetDestroy (set);
- FcStrSetDestroy (subdirs);
ret++;
continue;
}
if (!S_ISDIR (statb.st_mode))
{
fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
- FcFontSetDestroy (set);
- FcStrSetDestroy (subdirs);
continue;
}
if (really_force)
FcDirCacheUnlink (dir, config);
- if (!force)
- was_valid = FcDirCacheValid (dir);
+ cache = NULL;
+ was_valid = FcFalse;
+ if (!force) {
+ cache = FcDirCacheLoad (dir, config, NULL);
+ if (cache)
+ was_valid = FcTrue;
+ }
- if (!FcDirScanConfig (set, subdirs, FcConfigGetBlanks (config), dir, force, config))
+ if (!cache)
{
- fprintf (stderr, "%s: error scanning\n", dir);
- FcFontSetDestroy (set);
- FcStrSetDestroy (subdirs);
- ret++;
- continue;
+ cache = FcDirCacheRead (dir, FcTrue, config);
+ if (!cache)
+ {
+ fprintf (stderr, "%s: error scanning\n", dir);
+ ret++;
+ continue;
+ }
}
- if (!force && was_valid)
+
+ set = FcCacheSet (cache);
+
+ if (was_valid)
{
if (verbose)
printf ("skipping, %d fonts, %d dirs\n",
- set->nfont, nsubdirs(subdirs));
+ set->nfont, cache->dirs_count);
}
else
{
if (verbose)
printf ("caching, %d fonts, %d dirs\n",
- set->nfont, nsubdirs (subdirs));
+ set->nfont, cache->dirs_count);
if (!FcDirCacheValid (dir))
{
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);
FcStrSetDestroy (subdirs);
if (!sublist)
{
fprintf (stderr, "%s: Can't create subdir list\n", dir);
ret++;
+ FcDirCacheUnload (cache);
continue;
}
FcStrSetAdd (processed_dirs, dir);
- ret += scanDirs (sublist, config, program, force, really_force, verbose);
+ ret += scanDirs (sublist, config, force, really_force, verbose);
}
FcStrListDone (list);
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
cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose)
{
if (access ((char *) dir, W_OK|X_OK) != 0)
{
if (verbose)
- printf ("%s: skipping unwritable cache directory\n", dir);
+ printf ("%s: not cleaning unwritable cache directory\n", dir);
return FcTrue;
}
+ if (verbose)
+ printf ("%s: cleaning cache directory\n", dir);
d = opendir (dir);
if (!d)
{
ret = FcFalse;
break;
}
- cache = FcCacheFileMap (file_name, &file_stat);
+ cache = FcDirCacheLoadFile (file_name, &file_stat);
if (!cache)
{
fprintf (stderr, "%s: invalid cache file: %s\n", dir, ent->d_name);
return 1;
}
- ret = scanDirs (list, config, argv[0], force, really_force, verbose);
+ ret = scanDirs (list, config, force, really_force, verbose);
FcStrSetDestroy (processed_dirs);
#endif
static FcBool
-FcCacheWriteChars (FILE *f, const FcChar8 *chars)
+write_chars (FILE *f, const FcChar8 *chars)
{
FcChar8 c;
while ((c = *chars++))
}
static FcBool
-FcCacheWriteUlong (FILE *f, unsigned long t)
+write_ulong (FILE *f, unsigned long t)
{
int pow;
unsigned long temp, digit;
}
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
-FcCacheWriteStringOld (FILE *f, const FcChar8 *string)
+write_string (FILE *f, const FcChar8 *string)
{
if (PUTC ('"', f) == EOF)
return FcFalse;
- if (!FcCacheWriteChars (f, string))
+ if (!write_chars (f, string))
return FcFalse;
if (PUTC ('"', f) == EOF)
return FcFalse;
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'
*/
static const FcChar8 *
-FcFileBaseName (const char *cache, const FcChar8 *file)
+file_base_name (const char *cache, const FcChar8 *file)
{
const FcChar8 *cache_slash;
int cache_len = strlen (cache);
return file;
}
-FcBool
-FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose)
+static FcBool
+cache_print_set (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose)
{
FcPattern *font;
FcChar8 *name, *dir;
while ((dir = FcStrListNext (list)))
{
- base = FcFileBaseName (base_name, dir);
- if (!FcCacheWriteStringOld (stdout, base))
+ base = file_base_name (base_name, dir);
+ if (!write_string (stdout, base))
goto bail3;
if (PUTC (' ', stdout) == EOF)
goto bail3;
- if (!FcCacheWriteInt (stdout, 0))
+ if (!write_int (stdout, 0))
goto bail3;
if (PUTC (' ', stdout) == EOF)
goto bail3;
- if (!FcCacheWriteStringOld (stdout, FC_FONT_FILE_DIR))
+ if (!write_string (stdout, FC_FONT_FILE_DIR))
goto bail3;
if (PUTC ('\n', stdout) == EOF)
goto bail3;
if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
goto bail3;
- base = FcFileBaseName (base_name, file);
+ base = file_base_name (base_name, file);
if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
goto bail3;
- if (!FcCacheWriteStringOld (stdout, base))
+ if (!write_string (stdout, base))
goto bail3;
if (PUTC (' ', stdout) == EOF)
goto bail3;
- if (!FcCacheWriteInt (stdout, id))
+ if (!write_int (stdout, id))
goto bail3;
if (PUTC (' ', stdout) == EOF)
goto bail3;
name = FcNameUnparse (font);
if (!name)
goto bail3;
- ret = FcCacheWriteStringOld (stdout, name);
+ ret = write_string (stdout, name);
FcStrFree (name);
if (!ret)
goto bail3;
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
main (int argc, char **argv)
{
off_t size;
intptr_t *cache_dirs;
FcChar8 *cache_file = NULL;
+ struct stat file_stat;
if (FcFileIsDir (arg))
- cache = FcDirCacheMap (arg, config, &cache_file);
+ cache = FcDirCacheLoad (arg, config, &cache_file);
else
- cache = FcCacheFileMap (arg);
+ cache = FcDirCacheLoadFile (arg, &file_stat);
if (!cache)
{
perror ((char *) arg);
FcCacheDir(cache), cache_file ? cache_file : arg);
first = FcFalse;
}
- FcCachePrintSet (fs, dirs, FcCacheDir (cache), verbose);
+ cache_print_set (fs, dirs, FcCacheDir (cache), verbose);
FcStrSetDestroy (dirs);
- FcDirCacheUnmap (cache);
+ FcDirCacheUnload (cache);
if (cache_file)
FcStrFree (cache_file);
}
#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
rawindex (const FcGlyphName *gn);
}
static int
-FcCacheReadDirs (FcConfig * config,
- FcStrList *list, FcFontSet * set, FcStrSet *processed_dirs)
+FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
{
- int ret = 0;
- FcChar8 *dir;
- FcStrSet *subdirs;
- FcStrList *sublist;
+ int fd;
- /*
- * Read in the results from 'list'.
- */
- while ((dir = FcStrListNext (list)))
+ fd = open((char *) cache_file, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ return fd;
+ if (fstat (fd, file_stat) < 0)
{
- if (!FcConfigAcceptFilename (config, dir))
- continue;
-
- /* 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);
+ close (fd);
+ return -1;
}
- FcStrListDone (list);
- 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;
+ return fd;
}
/*
FcChar8 *cache_hashed = FcStrPlus (cache_dir, cache_base);
if (!cache_hashed)
break;
- fd = open((char *) cache_hashed, O_RDONLY | O_BINARY);
+ fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
if (fd >= 0) {
- if (fstat (fd, &file_stat) >= 0 &&
- dir_stat.st_mtime <= file_stat.st_mtime)
+ if (dir_stat.st_mtime <= file_stat.st_mtime)
{
ret = (*callback) (fd, file_stat.st_size, closure);
if (ret)
return ret;
}
-FcBool
-FcDirCacheLoad (int fd, off_t size, void *closure)
+#define FC_CACHE_MIN_MMAP 1024
+
+/*
+ * Map a cache file into memory
+ */
+static FcCache *
+FcDirCacheMapFd (int fd, off_t size)
{
- FcCache *cache;
+ FcCache *cache = NULL;
FcBool allocated = FcFalse;
if (size < sizeof (FcCache))
- return FcFalse;
+ return NULL;
+ /*
+ * For small cache files, just read them into memory
+ */
+ if (size >= FC_CACHE_MIN_MMAP)
+ {
#if defined(HAVE_MMAP) || defined(__CYGWIN__)
- cache = mmap (0, size, PROT_READ, MAP_SHARED, fd, 0);
+ cache = mmap (0, size, PROT_READ, MAP_SHARED, fd, 0);
#elif defined(_WIN32)
- {
- HANDLE 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);
+ HANDLE 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
+ }
if (!cache)
{
cache = malloc (size);
if (!cache)
- return FcFalse;
+ return NULL;
if (read (fd, cache, size) != size)
{
free (cache);
- return FcFalse;
+ return NULL;
}
allocated = FcTrue;
}
- if (cache->magic != FC_CACHE_MAGIC ||
+ if (cache->magic != FC_CACHE_MAGIC_MMAP ||
+ cache->version != FC_CACHE_CONTENT_VERSION ||
cache->size != size)
{
if (allocated)
UnmapViewOfFile (cache);
#endif
}
- return FcFalse;
+ return NULL;
}
/* Mark allocated caches so they're freed rather than unmapped */
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;
return FcTrue;
}
FcCache *
-FcDirCacheMap (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
+FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
{
FcCache *cache = NULL;
if (!FcDirCacheProcess (config, dir,
- FcDirCacheLoad,
+ FcDirCacheMapHelper,
&cache, cache_file))
return NULL;
return cache;
}
-FcBool
-FcDirCacheRead (FcFontSet * set, FcStrSet * dirs,
- const FcChar8 *dir, FcConfig *config)
+FcCache *
+FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
{
- FcCache *cache;
- int i;
- FcFontSet *cache_set;
- intptr_t *cache_dirs;
- FcPattern **cache_fonts;
+ int fd;
+ FcCache *cache;
- cache = FcDirCacheMap (dir, config, NULL);
- if (!cache)
- return FcFalse;
-
- cache_set = FcCacheSet (cache);
- cache_fonts = FcFontSetFonts(cache_set);
- 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;
+ fd = FcDirCacheOpenFile (cache_file, file_stat);
+ if (fd < 0)
+ return NULL;
+ cache = FcDirCacheMapFd (fd, file_stat->st_size);
+ close (fd);
+ return cache;
}
-
+
+/*
+ * Validate a cache file by reading the header and checking
+ * the magic number and the size field
+ */
static FcBool
-FcDirCacheValidate (int fd, off_t size, void *closure)
+FcDirCacheValidateHelper (int fd, off_t size, void *closure)
{
FcBool ret = FcTrue;
FcCache c;
if (read (fd, &c, sizeof (FcCache)) != sizeof (FcCache))
ret = FcFalse;
- else if (fstat (fd, &file_stat) < 0)
+ else if (c.magic != FC_CACHE_MAGIC_MMAP)
+ ret = FcFalse;
+ else if (c.version != FC_CACHE_CONTENT_VERSION)
ret = FcFalse;
- else if (c.magic != FC_CACHE_MAGIC)
+ else if (fstat (fd, &file_stat) < 0)
ret = FcFalse;
else if (file_stat.st_size != c.size)
ret = FcFalse;
static FcBool
FcDirCacheValidConfig (const FcChar8 *dir, FcConfig *config)
{
- return FcDirCacheProcess (config, dir, FcDirCacheValidate, NULL, NULL);
+ return FcDirCacheProcess (config, dir,
+ FcDirCacheValidateHelper,
+ NULL, NULL);
}
FcBool
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:
- *
- * FcCache
- * dir name
- * subdirs
- * FcFontSet
+ * Build a cache structure from the given contents
*/
-
-static FcCache *
-FcDirCacheProduce (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
+FcCache *
+FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
{
FcSerialize *serialize = FcSerializeCreate ();
FcCache *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;
/*
/* write serialized state to the cache file */
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_hashed;
int fd;
FcAtomic *atomic;
- FcCache *cache;
FcStrList *list;
FcChar8 *cache_dir = NULL;
FcChar8 *test_dir;
+ int magic;
+ int written;
/*
* Write it to the first directory in the list which is writable
if (!cache_hashed)
return FcFalse;
- cache = FcDirCacheProduce (set, dir, dirs);
-
- if (!cache)
- goto bail1;
-
if (FcDebug () & FC_DBG_CACHE)
printf ("FcDirCacheWriteDir dir \"%s\" file \"%s\"\n",
dir, cache_hashed);
atomic = FcAtomicCreate ((FcChar8 *)cache_hashed);
if (!atomic)
- goto bail2;
+ goto bail1;
if (!FcAtomicLock (atomic))
goto bail3;
if (fd == -1)
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");
goto bail5;
close(fd);
if (!FcAtomicReplaceOrig(atomic))
goto bail4;
- FcStrFree ((FcChar8 *)cache_hashed);
+ FcStrFree (cache_hashed);
FcAtomicUnlock (atomic);
FcAtomicDestroy (atomic);
return FcTrue;
FcAtomicUnlock (atomic);
bail3:
FcAtomicDestroy (atomic);
- bail2:
- free (cache);
bail1:
- FcStrFree ((FcChar8 *)cache_hashed);
+ FcStrFree (cache_hashed);
return FcFalse;
}
for (cl = config->caches; cl; cl = cl_next)
{
cl_next = cl->next;
- FcDirCacheUnmap (cl->cache);
+ FcDirCacheUnload (cl->cache);
free (cl);
}
}
/*
- * Scan the current list of directories in the configuration
- * and build the set of available fonts. Update the
- * per-user cache file to reflect the new configuration
+ * Add cache to configuration, adding fonts and directories
*/
FcBool
-FcConfigBuildFonts (FcConfig *config)
+FcConfigAddCache (FcConfig *config, FcCache *cache)
{
- FcFontSet *fonts, *cached_fonts;
- FcStrList *list;
- FcStrSet *oldDirs;
- FcChar8 *dir;
+ FcCacheList *cl = malloc (sizeof (FcCacheList));
+ FcFontSet *fs;
+ intptr_t *dirs;
+ int i;
- fonts = FcFontSetCreate ();
- if (!fonts)
- goto bail0;
-
- oldDirs = FcStrSetCreate ();
- if (!oldDirs)
- goto bail2;
+ /*
+ * Add to cache list
+ */
+ if (!cl)
+ return FcFalse;
+ cl->cache = cache;
+ cl->next = config->caches;
+ config->caches = cl;
- cached_fonts = FcCacheRead(config);
- if (!cached_fonts)
+ /*
+ * Add fonts
+ */
+ fs = FcCacheSet (cache);
+ if (fs)
{
- list = FcConfigGetFontDirs (config);
- if (!list)
- goto bail3;
-
- while ((dir = FcStrListNext (list)))
+ for (i = 0; i < fs->nfont; i++)
{
- if (FcDebug () & FC_DBG_FONTSET)
- printf ("build scan dir %s\n", dir);
- FcDirScanConfig (fonts, config->fontDirs,
- config->blanks, dir, FcFalse, config);
+ 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);
}
-
- FcStrListDone (list);
}
- else
+
+ /*
+ * Add directories
+ */
+ dirs = FcCacheDirs (cache);
+ if (dirs)
{
- int i;
-
- for (i = 0; i < oldDirs->num; i++)
- {
- if (FcDebug () & FC_DBG_FONTSET)
- printf ("scan dir %s\n", oldDirs->strs[i]);
- FcDirScanConfig (fonts, config->fontDirs,
- config->blanks, oldDirs->strs[i],
- FcFalse, config);
+ for (i = 0; i < cache->dirs_count; i++)
+ {
+ FcChar8 *dir = FcOffsetToPtr (dirs, dirs[i], FcChar8);
+ if (FcConfigAcceptFilename (config, dir))
+ FcConfigAddFontDir (config, dir);
}
+ }
+ return FcTrue;
+}
- for (i = 0; i < cached_fonts->nfont; i++)
- {
- FcChar8 *cfn;
- FcPattern *font = cached_fonts->fonts[i];
- FcPatternObjectGetString (font, FC_FILE_OBJECT, 0, &cfn);
+/*
+ * Scan the current list of directories in the configuration
+ * and build the set of available fonts.
+ */
- if (FcConfigAcceptFont (config, font) &&
- (cfn && FcConfigAcceptFilename (config, cfn)))
- FcFontSetAdd (fonts, font);
+FcBool
+FcConfigBuildFonts (FcConfig *config)
+{
+ FcFontSet *fonts;
+ FcStrList *dirlist;
+ FcChar8 *dir;
+ FcCache *cache;
- cached_fonts->fonts[i] = 0; /* prevent free in FcFontSetDestroy */
- }
- cached_fonts->nfont = 0;
- FcFontSetDestroy (cached_fonts);
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return FcFalse;
}
+
+ fonts = FcFontSetCreate ();
+ if (!fonts)
+ goto bail;
+
+ FcConfigSetFonts (config, fonts, FcSetSystem);
+
+ dirlist = FcStrListCreate (config->fontDirs);
+ if (!dirlist)
+ goto bail;
+
+ while ((dir = FcStrListNext (dirlist)))
+ {
+ if (FcDebug () & FC_DBG_FONTSET)
+ printf ("adding fonts from%s\n", dir);
+ cache = FcDirCacheRead (dir, FcFalse, config);
+ if (!cache)
+ continue;
+ FcConfigAddCache (config, cache);
+ }
+
+ FcStrListDone (dirlist);
if (FcDebug () & FC_DBG_FONTSET)
FcFontSetPrint (fonts);
- FcStrSetDestroy (oldDirs);
-
- FcConfigSetFonts (config, fonts, FcSetSystem);
-
return FcTrue;
-bail3:
- FcStrSetDestroy (oldDirs);
-bail2:
- FcFontSetDestroy (fonts);
-bail0:
+bail:
return FcFalse;
}
config->fonts[set] = fonts;
}
-FcBool
-FcConfigAddCache (FcConfig *config, FcCache *cache)
-{
- FcCacheList *cl = malloc (sizeof (FcCacheList));
-
- if (!cl)
- return FcFalse;
- cl->cache = cache;
- cl->next = config->caches;
- config->caches = cl;
- return FcTrue;
-}
-
FcBlanks *
FcConfigGetBlanks (FcConfig *config)
{
FcConfigSetFonts (config, set, FcSetApplication);
}
- if (!FcFileScanConfig (set, subdirs, config->blanks, file, FcFalse, config))
+ if (!FcFileScanConfig (set, subdirs, config->blanks, file, config))
{
FcStrSetDestroy (subdirs);
return FcFalse;
/* #define CHECK */
-/* #define CHATTY */
-
FcCharSet *
FcCharSetCreate (void)
{
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
fcs->ref = 1;
fcs->num = 0;
- fcs->leaves_offset = FcPtrToOffset (fcs, NULL);
- fcs->numbers_offset = FcPtrToOffset (fcs, NULL);
+ fcs->leaves_offset = 0;
+ fcs->numbers_offset = 0;
return fcs;
}
FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
free (FcCharSetLeaf (fcs, i));
}
- if (FcCharSetLeaves (fcs))
+ if (fcs->num)
{
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (intptr_t));
free (FcCharSetLeaves (fcs));
}
- if (FcCharSetNumbers (fcs))
+ if (fcs->num)
{
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
free (FcCharSetNumbers (fcs));
ucs4 >>= 8;
if (ucs4 >= 0x10000)
return FcFalse;
- if (!leaves)
+ if (!fcs->num)
leaves = malloc (sizeof (*leaves));
else
{
FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (intptr_t));
fcs->leaves_offset = FcPtrToOffset (fcs, leaves);
- if (!numbers)
+ if (!fcs->num)
numbers = malloc (sizeof (FcChar16));
else
numbers = realloc (numbers, (fcs->num + 1) * sizeof (FcChar16));
}
iter->leaf = FcCharSetLeaf(fcs, pos);
iter->pos = pos;
-#ifdef CHATTY
- printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf);
-#endif
}
static void
}
}
-#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
FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
{
-#ifdef CHATTY
- FcCharSetDump (fcs);
-#endif
iter->ucs4 = 0;
iter->pos = 0;
FcCharSetIterSet (fcs, iter);
return FcTrue;
}
+FcCharSet *
+FcNameParseCharSet (FcChar8 *string)
+{
+ FcCharSet *c;
+ FcChar32 ucs4;
+ FcCharLeaf *leaf;
+ FcCharLeaf temp;
+ FcChar32 bits;
+ int i;
+
+ c = FcCharSetCreate ();
+ if (!c)
+ goto bail0;
+ while (*string)
+ {
+ string = FcCharSetParseValue (string, &ucs4);
+ if (!string)
+ goto bail1;
+ bits = 0;
+ for (i = 0; i < 256/32; i++)
+ {
+ string = FcCharSetParseValue (string, &temp.map[i]);
+ if (!string)
+ goto bail1;
+ bits |= temp.map[i];
+ }
+ if (bits)
+ {
+ leaf = malloc (sizeof (FcCharLeaf));
+ if (!leaf)
+ goto bail1;
+ *leaf = temp;
+ if (!FcCharSetInsertLeaf (c, ucs4, leaf))
+ goto bail1;
+ }
+ }
+ return c;
+bail1:
+ if (c->num)
+ {
+ FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
+ free (FcCharSetLeaves (c));
+ }
+ if (c->num)
+ {
+ FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
+ free (FcCharSetNumbers (c));
+ }
+ FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
+ free (c);
+bail0:
+ return NULL;
+}
+
+FcBool
+FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
+{
+ FcCharSetIter ci;
+ int i;
+#ifdef CHECK
+ int len = buf->len;
+#endif
+
+ for (FcCharSetIterStart (c, &ci);
+ ci.leaf;
+ FcCharSetIterNext (c, &ci))
+ {
+ if (!FcCharSetUnparseValue (buf, ci.ucs4))
+ return FcFalse;
+ for (i = 0; i < 256/32; i++)
+ if (!FcCharSetUnparseValue (buf, ci.leaf->map[i]))
+ return FcFalse;
+ }
+#ifdef CHECK
+ {
+ FcCharSet *check;
+ FcChar32 missing;
+ FcCharSetIter ci, checki;
+
+ /* null terminate for parser */
+ FcStrBufChar (buf, '\0');
+ /* step back over null for life after test */
+ buf->len--;
+ check = FcNameParseCharSet (buf->buf + len);
+ FcCharSetIterStart (c, &ci);
+ FcCharSetIterStart (check, &checki);
+ while (ci.leaf || checki.leaf)
+ {
+ if (ci.ucs4 < checki.ucs4)
+ {
+ printf ("Missing leaf node at 0x%x\n", ci.ucs4);
+ FcCharSetIterNext (c, &ci);
+ }
+ else if (checki.ucs4 < ci.ucs4)
+ {
+ printf ("Extra leaf node at 0x%x\n", checki.ucs4);
+ FcCharSetIterNext (check, &checki);
+ }
+ else
+ {
+ int i = 256/32;
+ FcChar32 *cm = ci.leaf->map;
+ FcChar32 *checkm = checki.leaf->map;
+
+ for (i = 0; i < 256; i += 32)
+ {
+ if (*cm != *checkm)
+ printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n",
+ ci.ucs4 + i, *cm, *checkm);
+ cm++;
+ checkm++;
+ }
+ FcCharSetIterNext (c, &ci);
+ FcCharSetIterNext (check, &checki);
+ }
+ }
+ if ((missing = FcCharSetSubtractCount (c, check)))
+ printf ("%d missing in reparsed result\n", missing);
+ if ((missing = FcCharSetSubtractCount (check, c)))
+ printf ("%d extra in reparsed result\n", missing);
+ FcCharSetDestroy (check);
+ }
+#endif
+
+ return FcTrue;
+}
+
typedef struct _FcCharLeafEnt FcCharLeafEnt;
struct _FcCharLeafEnt {
};
#define FC_CHAR_LEAF_BLOCK (4096 / sizeof (FcCharLeafEnt))
-static FcCharLeafEnt **FcCharLeafBlocks;
-static int FcCharLeafBlockCount;
+#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 (void)
+FcCharLeafEntCreate (FcCharSetFreezer *freezer)
{
- static FcCharLeafEnt *block;
- static int remain;
-
- if (!remain)
+ if (!freezer->leaf_remain)
{
FcCharLeafEnt **newBlocks;
- FcCharLeafBlockCount++;
- newBlocks = realloc (FcCharLeafBlocks, FcCharLeafBlockCount * sizeof (FcCharLeafEnt *));
+ freezer->leaf_block_count++;
+ newBlocks = realloc (freezer->leaf_blocks, freezer->leaf_block_count * sizeof (FcCharLeafEnt *));
if (!newBlocks)
return 0;
- FcCharLeafBlocks = newBlocks;
- block = FcCharLeafBlocks[FcCharLeafBlockCount-1] = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
- if (!block)
+ 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));
- remain = FC_CHAR_LEAF_BLOCK;
+ freezer->leaf_remain = FC_CHAR_LEAF_BLOCK;
}
- remain--;
- return block++;
+ freezer->leaf_remain--;
+ freezer->leaves_allocated++;
+ return freezer->current_block++;
}
-#define FC_CHAR_LEAF_HASH_SIZE 257
-
static FcChar32
FcCharLeafHash (FcCharLeaf *leaf)
{
return hash;
}
-static int FcCharLeafTotal;
-static int FcCharLeafUsed;
-
-static FcCharLeafEnt *FcCharLeafHashTable[FC_CHAR_LEAF_HASH_SIZE];
-
static FcCharLeaf *
-FcCharSetFreezeLeaf (FcCharLeaf *leaf)
+FcCharSetFreezeLeaf (FcCharSetFreezer *freezer, FcCharLeaf *leaf)
{
FcChar32 hash = FcCharLeafHash (leaf);
- FcCharLeafEnt **bucket = &FcCharLeafHashTable[hash % FC_CHAR_LEAF_HASH_SIZE];
+ FcCharLeafEnt **bucket = &freezer->leaf_hash_table[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();
+ ent = FcCharLeafEntCreate(freezer);
if (!ent)
return 0;
- FcCharLeafUsed++;
ent->leaf = *leaf;
ent->hash = hash;
ent->next = *bucket;
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)
{
return hash;
}
-static int FcCharSetTotal;
-static int FcCharSetUsed;
-static int FcCharSetTotalEnts, FcCharSetUsedEnts;
-
-static FcCharSetEnt *FcCharSetHashTable[FC_CHAR_SET_HASH_SIZE];
+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 (FcCharSet *fcs)
+FcCharSetFreezeBase (FcCharSetFreezer *freezer, FcCharSet *fcs, const FcCharSet *orig)
{
FcChar32 hash = FcCharSetHash (fcs);
- FcCharSetEnt **bucket = &FcCharSetHashTable[hash % FC_CHAR_SET_HASH_SIZE];
+ FcCharSetEnt **bucket = &freezer->set_hash_table[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 &&
if (!ent)
return 0;
FcMemAlloc (FC_MEM_CHARSET, size);
- FcCharSetUsed++;
- FcCharSetUsedEnts += fcs->num;
+
+ freezer->charsets_allocated++;
ent->set.ref = FC_REF_CONSTANT;
ent->set.num = fcs->num;
ent->hash = hash;
ent->next = *bucket;
*bucket = ent;
+
return &ent->set;
}
-void
-FcCharSetThawAll (void)
+static const FcCharSet *
+FcCharSetFindFrozen (FcCharSetFreezer *freezer, const FcCharSet *orig)
{
- 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 ();
+ 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;
}
-FcCharSet *
-FcCharSetFreeze (FcCharSet *fcs)
+static const FcCharSet *
+FcCharSetFreeze (FcCharSetFreezer *freezer, const FcCharSet *fcs)
{
- FcCharSet *b;
- FcCharSet *n = 0;
- FcCharLeaf *l;
- int i;
+ 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 (FcCharSetLeaf(fcs, i));
+ l = FcCharSetFreezeLeaf (freezer, FcCharSetLeaf(fcs, i));
if (!l)
goto bail1;
if (!FcCharSetInsertLeaf (b, FcCharSetNumbers(fcs)[i] << 8, l))
goto bail1;
}
- n = FcCharSetFreezeBase (b);
+ n = FcCharSetFreezeBase (freezer, b, fcs);
+ if (!FcCharSetFreezeOrig (freezer, fcs, n))
+ {
+ n = NULL;
+ goto bail1;
+ }
+ freezer->charsets_seen++;
+ freezer->leaves_seen += fcs->num;
bail1:
- if (FcCharSetLeaves (b))
+ if (b->num)
{
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
free (FcCharSetLeaves (b));
}
- if (FcCharSetNumbers (b))
+ if (b->num)
{
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
free (FcCharSetNumbers (b));
return n;
}
-FcCharSet *
-FcNameParseCharSet (FcChar8 *string)
+static FcCharSetFreezer *
+FcCharSetFreezerCreate (void)
{
- FcCharSet *c, *n = 0;
- FcChar32 ucs4;
- FcCharLeaf *leaf;
- FcCharLeaf temp;
- FcChar32 bits;
- int i;
+ FcCharSetFreezer *freezer;
- c = FcCharSetCreate ();
- if (!c)
- goto bail0;
- while (*string)
- {
- string = FcCharSetParseValue (string, &ucs4);
- if (!string)
- goto bail1;
- bits = 0;
- for (i = 0; i < 256/32; i++)
- {
- string = FcCharSetParseValue (string, &temp.map[i]);
- if (!string)
- goto bail1;
- bits |= temp.map[i];
- }
- if (bits)
- {
- leaf = FcCharSetFreezeLeaf (&temp);
- if (!leaf)
- goto bail1;
- if (!FcCharSetInsertLeaf (c, ucs4, leaf))
- goto bail1;
- }
- }
-#ifdef CHATTY
- 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:
- if (FcCharSetLeaves (c))
- {
- FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
- free (FcCharSetLeaves (c));
- }
- if (FcCharSetNumbers (c))
- {
- FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
- free (FcCharSetNumbers (c));
- }
- FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
- free (c);
-bail0:
- return n;
+ freezer = calloc (1, sizeof (FcCharSetFreezer));
+ return freezer;
}
-FcBool
-FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
+void
+FcCharSetFreezerDestroy (FcCharSetFreezer *freezer)
{
- FcCharSetIter ci;
- int i;
-#ifdef CHECK
- int len = buf->len;
-#endif
+ int i;
- for (FcCharSetIterStart (c, &ci);
- ci.leaf;
- FcCharSetIterNext (c, &ci))
+ if (FcDebug() & FC_DBG_CACHE)
{
- if (!FcCharSetUnparseValue (buf, ci.ucs4))
- return FcFalse;
- for (i = 0; i < 256/32; i++)
- if (!FcCharSetUnparseValue (buf, ci.leaf->map[i]))
- return FcFalse;
+ printf ("\ncharsets %d -> %d leaves %d -> %d\n",
+ freezer->charsets_seen, freezer->charsets_allocated,
+ freezer->leaves_seen, freezer->leaves_allocated);
}
-#ifdef CHECK
+ for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
{
- FcCharSet *check;
- FcChar32 missing;
- FcCharSetIter ci, checki;
-
- /* null terminate for parser */
- FcStrBufChar (buf, '\0');
- /* step back over null for life after test */
- buf->len--;
- check = FcNameParseCharSet (buf->buf + len);
- FcCharSetIterStart (c, &ci);
- FcCharSetIterStart (check, &checki);
- while (ci.leaf || checki.leaf)
+ FcCharSetEnt *ent, *next;
+ for (ent = freezer->set_hash_table[i]; ent; ent = next)
{
- if (ci.ucs4 < checki.ucs4)
- {
- printf ("Missing leaf node at 0x%x\n", ci.ucs4);
- FcCharSetIterNext (c, &ci);
- }
- else if (checki.ucs4 < ci.ucs4)
- {
- printf ("Extra leaf node at 0x%x\n", checki.ucs4);
- FcCharSetIterNext (check, &checki);
- }
- else
- {
- int i = 256/32;
- FcChar32 *cm = ci.leaf->map;
- FcChar32 *checkm = checki.leaf->map;
+ next = ent->next;
+ free (ent);
+ }
+ }
- for (i = 0; i < 256; i += 32)
- {
- if (*cm != *checkm)
- printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n",
- ci.ucs4 + i, *cm, *checkm);
- cm++;
- checkm++;
- }
- FcCharSetIterNext (c, &ci);
- FcCharSetIterNext (check, &checki);
- }
+ 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);
}
- if ((missing = FcCharSetSubtractCount (c, check)))
- printf ("%d missing in reparsed result\n", missing);
- if ((missing = FcCharSetSubtractCount (check, c)))
- printf ("%d extra in reparsed result\n", missing);
- FcCharSetDestroy (check);
}
-#endif
-
- return FcTrue;
+
+ for (i = 0; i < freezer->leaf_block_count; i++)
+ free (freezer->leaf_blocks[i]);
+
+ free (freezer->leaf_blocks);
+ free (freezer);
}
FcBool
FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
{
- intptr_t *leaves = FcCharSetLeaves (cs);
- FcChar16 *numbers = FcCharSetNumbers (cs);
+ intptr_t *leaves;
+ FcChar16 *numbers;
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)))
return FcFalse;
if (!FcSerializeAlloc (serialize, leaves, cs->num * sizeof (intptr_t)))
FcCharSet *
FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
{
- FcCharSet *cs_serialized = FcSerializePtr (serialize, cs);
+ FcCharSet *cs_serialized;
intptr_t *leaves, *leaves_serialized;
FcChar16 *numbers, *numbers_serialized;
FcCharLeaf *leaf, *leaf_serialized;
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)
return NULL;
FcStrSet *dirs,
FcBlanks *blanks,
const FcChar8 *file,
- FcBool force,
FcConfig *config)
{
- if (config && !FcConfigAcceptFilename (config, file))
- return FcTrue;
-
if (FcFileIsDir (file))
return FcStrSetAdd (dirs, file);
else
const FcChar8 *file,
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
*/
-
static int
cmpstringp(const void *p1, const void *p2)
{
}
/*
- * Scan 'dir', adding font files to 'set' and
- * subdirectories to 'dirs'
+ * Scan the specified directory and construct a cache of its contents
*/
-
-FcBool
-FcDirScanConfig (FcFontSet *set,
- FcStrSet *dirs,
- FcBlanks *blanks,
- const FcChar8 *dir,
- FcBool force,
- FcConfig *config)
+FcCache *
+FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
{
DIR *d;
- FcChar8 *canon_dir;
struct dirent *e;
- FcStrSet *dirlist, *filelist;
+ FcStrSet *files;
+ FcStrSet *dirs;
FcChar8 *file;
FcChar8 *base;
FcBool ret = FcTrue;
- FcFontSet *tmpSet;
+ FcFontSet *set;
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)
- printf ("cache scan dir %s\n", canon_dir);
+ printf ("cache scan dir %s\n", dir);
/* 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) {
ret = FcFalse;
goto bail;
}
- strcpy ((char *) file, (char *) canon_dir);
+ strcpy ((char *) file, (char *) dir);
strcat ((char *) file, "/");
base = file + strlen ((char *) file);
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)
{
/* Don't complain about missing directories */
goto bail_1;
}
- tmpSet = FcFontSetCreate();
- if (!tmpSet)
+ set = FcFontSetCreate();
+ if (!set)
{
ret = FcFalse;
goto bail0;
}
- dirlist = FcStrSetCreate ();
- if (!dirlist)
+ files = FcStrSetCreate ();
+ if (!files)
{
ret = FcFalse;
goto bail1;
}
- filelist = FcStrSetCreate ();
- if (!filelist)
- {
- ret = FcFalse;
- goto bail2;
- }
while ((e = readdir (d)))
{
if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
{
strcpy ((char *) base, (char *) e->d_name);
- if (FcFileIsDir (file)) {
- if (!FcStrSetAdd (dirlist, file)) {
- ret = FcFalse;
- goto bail3;
- }
- } else {
- if (!FcStrSetAdd (filelist, file)) {
- ret = FcFalse;
- goto bail3;
- }
+ if (!FcStrSetAdd (files, file)) {
+ ret = FcFalse;
+ goto bail2;
}
}
}
+
/*
- * Sort files and dirs to make things prettier
+ * Sort files to make things prettier
*/
- qsort(dirlist->strs, dirlist->num, sizeof(FcChar8 *), cmpstringp);
- qsort(filelist->strs, filelist->num, sizeof(FcChar8 *), cmpstringp);
+ qsort(files->strs, files->num, sizeof(FcChar8 *), cmpstringp);
- for (i = 0; i < filelist->num; i++)
- FcFileScanFontConfig (tmpSet, blanks, filelist->strs[i], config);
+ dirs = FcStrSetCreate ();
+ if (!dirs)
+ goto bail2;
/*
- * Now that the directory has been scanned,
- * write out the cache file
+ * Scan file files to build font patterns
*/
- FcDirCacheWrite (tmpSet, dirlist, canon_dir, config);
-
- /*
- * Add the discovered fonts to our internal non-cache list
- */
- for (i = 0; i < tmpSet->nfont; i++)
- FcFontSetAdd (set, tmpSet->fonts[i]);
-
+ for (i = 0; i < files->num; i++)
+ FcFileScanConfig (set, dirs, blanks, files->strs[i], config);
+
/*
- * the patterns in tmpset now belong to set; don't free them
+ * Build the cache object
*/
- tmpSet->nfont = 0;
-
+ cache = FcDirCacheBuild (set, dir, dirs);
+ if (!cache)
+ goto bail3;
+
/*
- * Add the discovered directories to the list to be scanned
+ * Write out the cache file, ignoring any troubles
*/
- for (i = 0; i < dirlist->num; i++)
- if (!FcStrSetAdd (dirs, dirlist->strs[i])) {
- ret = FcFalse;
- goto bail3;
- }
+ FcDirCacheWrite (cache, config);
bail3:
- FcStrSetDestroy (filelist);
+ FcStrSetDestroy (dirs);
bail2:
- FcStrSetDestroy (dirlist);
+ FcStrSetDestroy (files);
bail1:
- FcFontSetDestroy (tmpSet);
+ FcFontSetDestroy (set);
bail0:
closedir (d);
bail_1:
free (file);
bail:
- if (canon_dir != dir) free (canon_dir);
- return ret;
+ return cache;
+}
+
+/*
+ * 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
const FcChar8 *dir,
FcBool force)
{
- return FcDirScanConfig (set, dirs, blanks, dir, force, 0);
+ return FcDirScanConfig (set, dirs, blanks, dir, force, NULL);
}
FcBool
FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
{
- return FcFalse;
+ return FcFalse; /* XXX deprecated */
}
FcConfigDestroy (_fcConfig);
FcPatternFini ();
- FcCharSetThawAll ();
}
/*
#define FC_FONT_FILE_INVALID ((FcChar8 *) ".")
#define FC_FONT_FILE_DIR ((FcChar8 *) ".dir")
-#define FC_GLOBAL_MAGIC_COOKIE "GLOBAL"
#ifdef _WIN32
#define FC_SEARCH_PATH_SEPARATOR ';'
#define FC_DBG_MEMORY 512
#define FC_DBG_CONFIG 1024
#define FC_DBG_LANGSET 2048
+#define FC_DBG_OBJTYPES 4096
#define FC_MEM_CHARSET 0
#define FC_MEM_CHARLEAF 1
} FcStrBuf;
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 dir; /* offset to dir name */
intptr_t dirs; /* offset to subdirs */
#define FcCacheDir(c) FcOffsetMember(c,dir,FcChar8)
#define FcCacheDirs(c) FcOffsetMember(c,dirs,intptr_t)
#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
intptr_t offset;
} FcSerializeBucket;
+typedef struct _FcCharSetFreezer FcCharSetFreezer;
+
typedef struct _FcSerialize {
intptr_t size;
+ FcCharSetFreezer *cs_freezer;
void *linear;
FcSerializeBucket *buckets[FC_SERIALIZE_HASH_SIZE];
} FcSerialize;
#define fc_alignof(type) offsetof (struct { char c; type member; }, member)
-#define FC_CACHE_MAGIC 0xFC02FC04
-#define FC_CACHE_MAGIC_COPY 0xFC02FC05
+#define FC_CACHE_MAGIC_MMAP 0xFC02FC04
+#define FC_CACHE_MAGIC_ALLOC 0xFC02FC05
+#define FC_CACHE_CONTENT_VERSION 1
struct _FcAtomic {
FcChar8 *file; /* original file name */
/* fccache.c */
-FcFontSet *
-FcCacheRead (FcConfig *config);
-
FcBool
-FcDirCacheWrite (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config);
+FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config);
-FcBool
-FcDirCacheConsume (FILE *file, FcFontSet *set, FcStrSet *dirs,
- const FcChar8 *dir, char *dirname);
-
void
-FcDirCacheUnmap (FcCache *cache);
+FcDirCacheUnload (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);
+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
-FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config);
+FcDirCacheValid (const FcChar8 *dir);
+FcCache *
+FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs);
+
+FcBool
+FcDirCacheWrite (FcCache *cache, FcConfig *config);
+
/* fccfg.c */
FcBool
void
FcLangCharSetPopulate (void);
-FcCharSet *
-FcCharSetFreeze (FcCharSet *cs);
-
void
-FcCharSetThawAll (void);
+FcCharSetFreezerDestroy (FcCharSetFreezer *freezer);
FcBool
FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c);
FcStrSet *dirs,
FcBlanks *blanks,
const FcChar8 *file,
- FcBool force,
FcConfig *config);
FcBool
FcDirScanConfig (FcFontSet *set,
FcStrSet *dirs,
FcBlanks *blanks,
- const FcChar8 *dir,
+ const FcChar8 *dir,
FcBool force,
FcConfig *config);
+FcCache *
+FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config);
+
/* fcfont.c */
int
FcFontDebug (void);
* Make sure the stored type is valid for built-in objects
*/
if (!FcObjectValidType (object, value.type))
+ {
+ if (FcDebug() & FC_DBG_OBJTYPES)
+ {
+ printf ("FcPattern object %s does not accept value ",
+ FcObjectName (object));
+ FcValuePrint (value);
+ }
goto bail1;
+ }
new->value = value;
new->binding = binding;
return NULL;
serialize->size = 0;
serialize->linear = NULL;
+ serialize->cs_freezer = NULL;
memset (serialize->buckets, '\0', sizeof (serialize->buckets));
return serialize;
}
free (buck);
}
}
+ if (serialize->cs_freezer)
+ FcCharSetFreezerDestroy (serialize->cs_freezer);
free (serialize);
}