Overhaul the serialization system to create one mmapable file per directory

and distribute bytes for each directory from a single malloc for that
    directory. Store pointers as differences between the data pointed to
    and the pointer's address (s_off = s - v). Don't serialize data
    structures that never actually get serialized. Separate strings used
    for keys from strings used for values (in FcPatternElt and FcValue,
    respectively). Bump FC_CACHE_VERSION to 2.
This commit is contained in:
Patrick Lam 2005-08-24 06:21:30 +00:00
parent 212c9f437e
commit 4262e0b385
20 changed files with 1588 additions and 2259 deletions

View File

@ -93,7 +93,6 @@ usage (char *program)
exit (1); exit (1);
} }
#if 0
static int static int
nsubdirs (FcStrSet *set) nsubdirs (FcStrSet *set)
{ {
@ -192,6 +191,7 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
ret++; ret++;
continue; continue;
} }
#if 0 // put this back later after fixing DirCacheValid
if (!force && FcDirCacheValid (dir)) if (!force && FcDirCacheValid (dir))
{ {
if (verbose) if (verbose)
@ -199,11 +199,13 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
set->nfont, nsubdirs(subdirs)); set->nfont, nsubdirs(subdirs));
} }
else else
#endif
{ {
if (verbose) if (verbose)
printf ("caching, %d fonts, %d dirs\n", printf ("caching, %d fonts, %d dirs\n",
set->nfont, nsubdirs (subdirs)); set->nfont, nsubdirs (subdirs));
if (!FcDirSave (set, subdirs, dir))
if (!FcDirSave (set, dir))
{ {
fprintf (stderr, "Can't save cache in \"%s\"\n", dir); fprintf (stderr, "Can't save cache in \"%s\"\n", dir);
ret++; ret++;
@ -223,7 +225,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
FcStrListDone (list); FcStrListDone (list);
return ret; return ret;
} }
#endif
int int
main (int argc, char **argv) main (int argc, char **argv)
@ -280,10 +281,6 @@ main (int argc, char **argv)
return 1; return 1;
} }
/* We don't yet have per-directory caches. */
ret = (FcCacheWrite (config) == FcFalse);
#if 0
if (argv[i]) if (argv[i])
{ {
dirs = FcStrSetCreate (); dirs = FcStrSetCreate ();
@ -308,7 +305,6 @@ main (int argc, char **argv)
else else
list = FcConfigGetConfigDirs (config); list = FcConfigGetConfigDirs (config);
ret = scanDirs (list, config, argv[0], force, verbose); ret = scanDirs (list, config, argv[0], force, verbose);
#endif
/* /*
* Now we need to sleep a second (or two, to be extra sure), to make * Now we need to sleep a second (or two, to be extra sure), to make
* sure that timestamps for changes after this run of fc-cache are later * sure that timestamps for changes after this run of fc-cache are later

View File

@ -48,7 +48,7 @@ FcMemFree (int kind, int size)
} }
int int
FcCacheNextOffset (int fd) FcCacheBankToIndex (int bank)
{ {
return -1; return -1;
} }
@ -404,7 +404,7 @@ main (int argc, char **argv)
if (j < 0) if (j < 0)
j = i; j = i;
printf (" { (FcChar8 *) \"%s\",\n" printf (" { (FcChar8 *) \"%s\",\n"
" { FC_REF_CONSTANT, %d, FcStorageDynamic, " " { FC_REF_CONSTANT, %d, FC_BANK_DYNAMIC, "
"{ { (FcCharLeaf **) leaves_%s, " "{ { (FcCharLeaf **) leaves_%s, "
"(FcChar16 *) numbers_%s } } } },\n", "(FcChar16 *) numbers_%s } } } },\n",
langs[i], langs[i],

View File

@ -59,22 +59,22 @@
__v__.u.d = va_arg (va, double); \ __v__.u.d = va_arg (va, double); \
break; \ break; \
case FcTypeString: \ case FcTypeString: \
__v__.u.si = va_arg (va, FcObjectPtr); \ __v__.u.s = va_arg (va, const char *); \
break; \ break; \
case FcTypeBool: \ case FcTypeBool: \
__v__.u.b = va_arg (va, FcBool); \ __v__.u.b = va_arg (va, FcBool); \
break; \ break; \
case FcTypeMatrix: \ case FcTypeMatrix: \
__v__.u.mi = va_arg (va, FcMatrixPtr); \ __v__.u.m = va_arg (va, const FcMatrix *); \
break; \ break; \
case FcTypeCharSet: \ case FcTypeCharSet: \
__v__.u.ci = va_arg (va, FcCharSetPtr); \ __v__.u.c = va_arg (va, const FcCharSet *); \
break; \ break; \
case FcTypeFTFace: \ case FcTypeFTFace: \
__v__.u.f = va_arg (va, FT_Face); \ __v__.u.f = va_arg (va, FT_Face); \
break; \ break; \
case FcTypeLangSet: \ case FcTypeLangSet: \
__v__.u.li = va_arg (va, FcLangSetPtr); \ __v__.u.l = va_arg (va, const FcLangSet *); \
break; \ break; \
} \ } \
if (!FcPatternAdd (__p__, __o__, __v__, FcTrue)) \ if (!FcPatternAdd (__p__, __o__, __v__, FcTrue)) \

View File

@ -54,7 +54,7 @@ typedef int FcBool;
* it means multiple copies of the font information. * it means multiple copies of the font information.
*/ */
#define FC_CACHE_VERSION "1" #define FC_CACHE_VERSION "2"
#define FcTrue 1 #define FcTrue 1
#define FcFalse 0 #define FcFalse 0
@ -196,52 +196,28 @@ typedef enum _FcResult {
FcResultOutOfMemory FcResultOutOfMemory
} FcResult; } FcResult;
typedef enum _FcStorage {
FcStorageStatic, FcStorageDynamic
} FcStorage;
typedef struct _FcPattern FcPattern; typedef struct _FcPattern FcPattern;
typedef struct _FcLangSet FcLangSet; typedef struct _FcLangSet FcLangSet;
typedef struct _FcMatrixPtr { #define FC_BANK_DYNAMIC 0
FcStorage storage; #define FC_BANK_FIRST 1
union {
int stat;
FcMatrix *dyn;
} u;
} FcMatrixPtr;
typedef struct _FcCharSetPtr {
FcStorage storage;
union {
int stat;
FcCharSet *dyn;
} u;
} FcCharSetPtr;
typedef struct _FcLangSetPtr {
FcStorage storage;
union {
int stat;
FcLangSet *dyn;
} u;
} FcLangSetPtr;
typedef int FcObjectPtr;
typedef struct _FcValue { typedef struct _FcValue {
FcType type; FcType type;
union { union {
FcObjectPtr si; const FcChar8 *s;
int s_off;
int i; int i;
FcBool b; FcBool b;
double d; double d;
FcMatrixPtr mi; const FcMatrix *m;
FcCharSetPtr ci; const FcCharSet *c;
int c_off;
void *f; void *f;
const FcPattern *p; const FcPattern *p;
FcLangSetPtr li; const FcLangSet *l;
int l_off; // this is a difference of char *s
} u; } u;
} FcValue; } FcValue;
@ -254,7 +230,7 @@ typedef struct _FcFontSet {
typedef struct _FcObjectSet { typedef struct _FcObjectSet {
int nobject; int nobject;
int sobject; int sobject;
FcObjectPtr *objects; const char **objects;
} FcObjectSet; } FcObjectSet;
typedef enum _FcMatchKind { typedef enum _FcMatchKind {
@ -471,7 +447,7 @@ FcDirScan (FcFontSet *set,
FcBool force); FcBool force);
FcBool FcBool
FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir); FcDirSave (FcFontSet *set, const FcChar8 *dir);
/* fcfreetype.c */ /* fcfreetype.c */
FcPattern * FcPattern *
@ -648,9 +624,6 @@ FcMatrixScale (FcMatrix *m, double sx, double sy);
void void
FcMatrixShear (FcMatrix *m, double sh, double sv); FcMatrixShear (FcMatrix *m, double sh, double sv);
FcMatrix *
FcMatrixPtrU (FcMatrixPtr mi);
/* fcname.c */ /* fcname.c */
FcBool FcBool

View File

@ -23,6 +23,7 @@
*/ */
#include <fcntl.h> #include <fcntl.h>
#include <dirent.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include "fcint.h" #include "fcint.h"
@ -192,12 +193,6 @@ FcGlobalCacheDestroy (FcGlobalCache *cache)
free (cache); free (cache);
} }
/*
* Cache file syntax is quite simple:
*
* "file_name" id time "font_name" \n
*/
void void
FcGlobalCacheLoad (FcGlobalCache *cache, FcGlobalCacheLoad (FcGlobalCache *cache,
const FcChar8 *cache_file) const FcChar8 *cache_file)
@ -388,89 +383,15 @@ bail0:
* Find the next presumably-mmapable offset after the current file * Find the next presumably-mmapable offset after the current file
* pointer. * pointer.
*/ */
int static int
FcCacheNextOffset(int fd) FcCacheNextOffset(off_t w)
{ {
off_t w;
w = lseek(fd, 0, SEEK_END);
if (w % PAGESIZE == 0) if (w % PAGESIZE == 0)
return w; return w;
else else
return ((w / PAGESIZE)+1)*PAGESIZE; return ((w / PAGESIZE)+1)*PAGESIZE;
} }
/* will go away once we use config->cache */
#define CACHE_DEFAULT_TMPDIR "/tmp"
#define CACHE_DEFAULT_NAME "/fontconfig-mmap"
static char *
FcCacheFilename(void)
{
struct utsname b;
static char * name = 0;
if (name)
return name;
if (uname(&b) == -1)
name = CACHE_DEFAULT_NAME;
else
{
char * tmpname = getenv("TMPDIR");
char * logname = getenv("LOGNAME");
if (!tmpname)
tmpname = CACHE_DEFAULT_TMPDIR;
name = malloc(strlen(CACHE_DEFAULT_NAME) +
strlen(tmpname) +
(logname ? strlen(logname) : 0) + 5);
strcpy(name, tmpname);
strcat(name, CACHE_DEFAULT_NAME);
strcat(name, "-");
strcat(name, logname ? logname : "");
}
return name;
}
/*
* Wipe out static state.
*/
void
FcCacheClearStatic()
{
FcFontSetClearStatic();
FcPatternClearStatic();
FcValueListClearStatic();
FcObjectClearStatic();
FcMatrixClearStatic();
FcCharSetClearStatic();
FcLangSetClearStatic();
}
/*
* Trigger the counting phase: this tells us how much to allocate.
*/
FcBool
FcCachePrepareSerialize (FcConfig * config)
{
int i;
for (i = FcSetSystem; i <= FcSetApplication; i++)
if (config->fonts[i] && !FcFontSetPrepareSerialize(config->fonts[i]))
return FcFalse;
return FcTrue;
}
/* allocate and populate static structures */
FcBool
FcCacheSerialize (FcConfig * config)
{
int i;
for (i = FcSetSystem; i <= FcSetApplication; i++)
if (config->fonts[i] && !FcFontSetSerialize(config->fonts[i]))
return FcFalse;
return FcTrue;
}
/* get the current arch name */ /* get the current arch name */
/* caller is responsible for freeing returned pointer */ /* caller is responsible for freeing returned pointer */
static char * static char *
@ -531,7 +452,7 @@ FcCacheMoveDown (int fd, off_t start)
{ {
char * buf = malloc (BUF_SIZE); char * buf = malloc (BUF_SIZE);
char candidate_arch_machine_name[64], bytes_to_skip[7]; char candidate_arch_machine_name[64], bytes_to_skip[7];
long bs; off_t pos; long bs;
int c, bytes_skipped; int c, bytes_skipped;
if (!buf) if (!buf)
@ -571,131 +492,294 @@ FcCacheMoveDown (int fd, off_t start)
return FcFalse; return FcFalse;
} }
/* read serialized state from the cache file */ static int
FcBool FcCacheReadDirs (FcStrList *list, FcFontSet * set)
{
DIR *d;
struct dirent *e;
int ret = 0;
FcChar8 *dir;
FcChar8 *file, *base;
FcStrSet *subdirs;
FcStrList *sublist;
struct stat statb;
/*
* Now scan all of the directories into separate databases
* and write out the results
*/
while ((dir = FcStrListNext (list)))
{
/* freed below */
file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
if (!file)
return FcFalse;
strcpy ((char *) file, (char *) dir);
strcat ((char *) file, "/");
base = file + strlen ((char *) file);
subdirs = FcStrSetCreate ();
if (!subdirs)
{
fprintf (stderr, "Can't create directory set\n");
ret++;
free (file);
continue;
}
if (access ((char *) dir, X_OK) < 0)
{
switch (errno) {
case ENOENT:
case ENOTDIR:
case EACCES:
break;
default:
fprintf (stderr, "\"%s\": ", dir);
perror ("");
ret++;
}
FcStrSetDestroy (subdirs);
free (file);
continue;
}
if (stat ((char *) dir, &statb) == -1)
{
fprintf (stderr, "\"%s\": ", dir);
perror ("");
FcStrSetDestroy (subdirs);
ret++;
free (file);
continue;
}
if (!S_ISDIR (statb.st_mode))
{
fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
FcStrSetDestroy (subdirs);
free (file);
continue;
}
d = opendir ((char *) dir);
if (!d)
{
FcStrSetDestroy (subdirs);
free (file);
continue;
}
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) && !FcStrSetAdd (subdirs, file))
ret++;
}
}
closedir (d);
if (1 || FcDirCacheValid (dir))
{
FcDirCacheRead (set, dir);
}
else
{
ret++;
#if 0 // (implement per-dir loading)
if (verbose)
printf ("caching, %d fonts, %d dirs\n",
set->nfont, nsubdirs (subdirs));
if (!FcDirSave (set, dir))
{
fprintf (stderr, "Can't save cache in \"%s\"\n", dir);
ret++;
}
#endif
}
sublist = FcStrListCreate (subdirs);
FcStrSetDestroy (subdirs);
if (!sublist)
{
fprintf (stderr, "Can't create subdir list in \"%s\"\n", dir);
ret++;
free (file);
continue;
}
ret += FcCacheReadDirs (sublist, set);
free (file);
}
FcStrListDone (list);
return ret;
}
FcFontSet *
FcCacheRead (FcConfig *config) FcCacheRead (FcConfig *config)
{ {
int fd, i; FcFontSet * s = FcFontSetCreate();
if (!s)
return 0;
if (force)
goto bail;
if (FcCacheReadDirs (FcConfigGetConfigDirs (config), s))
goto bail;
return s;
bail:
FcFontSetDestroy (s);
return 0;
}
/* read serialized state from the cache file */
FcBool
FcDirCacheRead (FcFontSet * set, const FcChar8 *dir)
{
FcChar8 *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
int fd;
FcCache metadata; FcCache metadata;
void * current_dir_block;
char * current_arch_machine_name; char * current_arch_machine_name;
char candidate_arch_machine_name[64], bytes_in_block[7]; char candidate_arch_machine_name[64], bytes_in_block[7];
off_t current_arch_start = 0; off_t current_arch_start = 0;
if (force) if (force)
return FcFalse; goto bail;
if (!cache_file)
fd = open(FcCacheFilename(), O_RDONLY); goto bail;
if (fd == -1)
return FcFalse;
current_arch_machine_name = FcCacheGetCurrentArch(); current_arch_machine_name = FcCacheGetCurrentArch();
fd = open(cache_file, O_RDONLY);
if (fd == -1)
goto bail0;
current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name); current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name);
if (current_arch_start < 0) if (current_arch_start < 0)
goto bail; goto bail1;
lseek (fd, current_arch_start, SEEK_SET); lseek (fd, current_arch_start, SEEK_SET);
if (FcCacheReadString (fd, candidate_arch_machine_name, if (FcCacheReadString (fd, candidate_arch_machine_name,
sizeof (candidate_arch_machine_name)) == 0) sizeof (candidate_arch_machine_name)) == 0)
goto bail; goto bail1;
if (FcCacheReadString (fd, bytes_in_block, 7) == 0) if (FcCacheReadString (fd, bytes_in_block, 7) == 0)
goto bail; goto bail1;
// sanity check for endianness issues // sanity check for endianness issues
read(fd, &metadata, sizeof(FcCache)); read(fd, &metadata, sizeof(FcCache));
if (metadata.magic != FC_CACHE_MAGIC) if (metadata.magic != FC_CACHE_MAGIC)
goto bail; goto bail1;
if (!FcObjectRead(fd, metadata)) goto bail1; if (metadata.count)
if (!FcStrSetRead(fd, metadata)) goto bail1; {
if (!FcCharSetRead(fd, metadata)) goto bail1; off_t pos = FcCacheNextOffset (lseek(fd, 0, SEEK_CUR));
if (!FcMatrixRead(fd, metadata)) goto bail1; current_dir_block = mmap (0, metadata.count,
if (!FcLangSetRead(fd, metadata)) goto bail1; PROT_READ, MAP_SHARED, fd, pos);
if (!FcValueListRead(fd, metadata)) goto bail1; if (current_dir_block == MAP_FAILED)
if (!FcPatternEltRead(fd, metadata)) goto bail1; perror("");
if (!FcPatternRead(fd, metadata)) goto bail1;
if (!FcFontSetRead(fd, config, metadata)) goto bail1; if (!FcFontSetUnserialize (metadata, set, current_dir_block))
goto bail1;
}
close(fd); close(fd);
free (current_arch_machine_name); free (current_arch_machine_name);
free (cache_file);
return FcTrue; return FcTrue;
bail1: bail1:
for (i = FcSetSystem; i <= FcSetApplication; i++)
config->fonts[i] = 0;
close(fd); close(fd);
bail: bail0:
free (current_arch_machine_name); free (current_arch_machine_name);
bail:
free (cache_file);
return FcFalse; return FcFalse;
} }
/* write serialized state to the cache file */ /* write serialized state to the cache file */
FcBool FcBool
FcCacheWrite (FcConfig * config) FcDirCacheWrite (int bank, FcFontSet *set, const FcChar8 *dir)
{ {
int fd; FcChar8 *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
int fd, bytes_to_write, metadata_bytes;
FcCache metadata; FcCache metadata;
off_t current_arch_start = 0, truncate_to; off_t current_arch_start = 0, truncate_to;
char * current_arch_machine_name, bytes_written[7] = "dedbef"; char * current_arch_machine_name, bytes_written[7] = "dedbef";
void * current_dir_block, *final_dir_block;
if (!FcCachePrepareSerialize (config)) if (!cache_file)
goto bail;
FcFontSetNewBank();
bytes_to_write = FcFontSetNeededBytes (set);
metadata_bytes = FcCacheNextOffset (sizeof (FcCache));
if (!bytes_to_write)
{
unlink (cache_file);
free (cache_file);
return FcTrue;
}
current_dir_block = malloc (bytes_to_write);
memset (&metadata, 0, sizeof(FcCache));
metadata.count = bytes_to_write;
metadata.bank = bank;
if (!current_dir_block)
goto bail;
final_dir_block = FcFontSetDistributeBytes (&metadata, current_dir_block);
if (!FcFontSetSerialize (bank, set))
return FcFalse; return FcFalse;
if (!FcCacheSerialize (config)) if (FcDebug () & FC_DBG_CACHE)
return FcFalse; printf ("FcDirCacheWriteDir cache_file \"%s\"\n", cache_file);
fd = open(FcCacheFilename(), O_RDWR | O_CREAT, 0666); fd = open(cache_file, O_RDWR | O_CREAT, 0666);
if (fd == -1) if (fd == -1)
return FcFalse; return FcFalse;
current_arch_machine_name = FcCacheGetCurrentArch(); current_arch_machine_name = FcCacheGetCurrentArch();
current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name); current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name);
if (current_arch_start < 0) if (current_arch_start < 0)
current_arch_start = FcCacheNextOffset (fd); current_arch_start = FcCacheNextOffset (lseek(fd, 0, SEEK_END));
if (!FcCacheMoveDown(fd, current_arch_start)) if (!FcCacheMoveDown(fd, current_arch_start))
goto bail; goto bail1;
current_arch_start = lseek(fd, 0, SEEK_CUR); current_arch_start = lseek(fd, 0, SEEK_CUR);
if (ftruncate (fd, current_arch_start) == -1) if (ftruncate (fd, current_arch_start) == -1)
goto bail; goto bail1;
/* reserve space for arch, count & metadata */ /* reserve space for arch, count & metadata */
if (!FcCacheWriteString (fd, current_arch_machine_name)) if (!FcCacheWriteString (fd, current_arch_machine_name))
goto bail; goto bail1;
if (!FcCacheWriteString (fd, bytes_written))
goto bail;
memset (&metadata, 0, sizeof(FcCache));
metadata.magic = FC_CACHE_MAGIC;
write(fd, &metadata, sizeof(FcCache));
if (!FcFontSetWrite(fd, config, &metadata)) goto bail;
if (!FcPatternWrite(fd, &metadata)) goto bail;
if (!FcPatternEltWrite(fd, &metadata)) goto bail;
if (!FcValueListWrite(fd, &metadata)) goto bail;
if (!FcLangSetWrite(fd, &metadata)) goto bail;
if (!FcCharSetWrite(fd, &metadata)) goto bail;
if (!FcMatrixWrite(fd, &metadata)) goto bail;
if (!FcStrSetWrite(fd, &metadata)) goto bail;
if (!FcObjectWrite(fd, &metadata)) goto bail;
/* now write the address of the next offset */ /* now write the address of the next offset */
truncate_to = FcCacheNextOffset(fd) - current_arch_start; truncate_to = FcCacheNextOffset(current_arch_start + bytes_to_write + metadata_bytes) -
lseek(fd, current_arch_start + strlen(current_arch_machine_name)+1, current_arch_start;
SEEK_SET);
strcpy (bytes_written, l64a(truncate_to)); strcpy (bytes_written, l64a(truncate_to));
if (!FcCacheWriteString (fd, bytes_written)) if (!FcCacheWriteString (fd, bytes_written))
goto bail; goto bail1;
/* now rewrite metadata & truncate file */ metadata.magic = FC_CACHE_MAGIC;
if (write(fd, &metadata, sizeof(FcCache)) != sizeof (FcCache)) write (fd, &metadata, sizeof(FcCache));
goto bail; lseek (fd, FcCacheNextOffset (lseek(fd, 0, SEEK_END)), SEEK_SET);
write (fd, current_dir_block, bytes_to_write);
/* this actually serves to pad out the cache file */
if (ftruncate (fd, current_arch_start + truncate_to) == -1) if (ftruncate (fd, current_arch_start + truncate_to) == -1)
goto bail; goto bail1;
close(fd); close(fd);
return FcTrue; return FcTrue;
bail: bail1:
free (current_dir_block);
free (current_arch_machine_name); free (current_arch_machine_name);
bail:
unlink (cache_file);
free (cache_file);
return FcFalse; return FcFalse;
} }
@ -705,3 +789,56 @@ FcCacheForce (FcBool f)
{ {
force = f; force = f;
} }
static int banks_ptr = 0, banks_alloc = 0;
static int * bankId = 0;
int
FcCacheBankCount (void)
{
return banks_ptr;
}
FcBool
FcCacheHaveBank (int bank)
{
int i;
if (bank < FC_BANK_FIRST)
return FcTrue;
for (i = 0; i < banks_ptr; i++)
if (bankId[i] == bank)
return FcTrue;
return FcFalse;
}
int
FcCacheBankToIndex (int bank)
{
static int lastBank = FC_BANK_DYNAMIC, lastIndex = -1;
int i;
int * b;
if (bank == lastBank)
return lastIndex;
for (i = 0; i < banks_ptr; i++)
if (bankId[i] == bank)
return i;
if (banks_ptr <= banks_alloc)
{
b = realloc (bankId, banks_alloc + 4);
if (!b)
return -1;
bankId = b;
banks_alloc += 4;
}
i = banks_ptr++;
bankId[i] = bank;
return i;
}

View File

@ -247,7 +247,7 @@ FcConfigDestroy (FcConfig *config)
FcBool FcBool
FcConfigBuildFonts (FcConfig *config) FcConfigBuildFonts (FcConfig *config)
{ {
FcFontSet *fonts; FcFontSet *fonts, *cached_fonts;
FcGlobalCache *cache; FcGlobalCache *cache;
FcStrList *list; FcStrList *list;
FcChar8 *dir; FcChar8 *dir;
@ -269,19 +269,34 @@ FcConfigBuildFonts (FcConfig *config)
goto bail1; goto bail1;
#endif #endif
list = FcConfigGetFontDirs (config); cached_fonts = FcCacheRead(config);
if (!list) if (!cached_fonts)
goto bail1;
while ((dir = FcStrListNext (list)))
{ {
if (FcDebug () & FC_DBG_FONTSET) list = FcConfigGetFontDirs (config);
printf ("scan dir %s\n", dir); if (!list)
FcDirScanConfig (fonts, config->fontDirs, cache, goto bail1;
config->blanks, dir, FcFalse, config);
while ((dir = FcStrListNext (list)))
{
if (FcDebug () & FC_DBG_FONTSET)
printf ("scan dir %s\n", dir);
FcDirScanConfig (fonts, config->fontDirs, cache,
config->blanks, dir, FcFalse, config);
}
FcStrListDone (list);
}
else
{
int i;
for (i = 0; i < cached_fonts->nfont; i++)
{
if (FcConfigAcceptFont (config, cached_fonts->fonts[i]))
FcFontSetAdd (fonts, cached_fonts->fonts[i]);
}
FcFontSetDestroy (cached_fonts);
} }
FcStrListDone (list);
if (FcDebug () & FC_DBG_FONTSET) if (FcDebug () & FC_DBG_FONTSET)
FcFontSetPrint (fonts); FcFontSetPrint (fonts);
@ -558,25 +573,24 @@ FcConfigPromote (FcValue v, FcValue u)
} }
else if (v.type == FcTypeVoid && u.type == FcTypeMatrix) else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
{ {
v.u.mi = FcIdentityMatrix; v.u.m = &FcIdentityMatrix;
v.type = FcTypeMatrix; v.type = FcTypeMatrix;
} }
else if (v.type == FcTypeString && u.type == FcTypeLangSet) else if (v.type == FcTypeString && u.type == FcTypeLangSet)
{ {
v.u.li = FcLangSetPtrCreateDynamic(FcLangSetPromote v.u.l = FcLangSetPromote (v.u.s);
(FcObjectPtrU(v.u.si)));
v.type = FcTypeLangSet; v.type = FcTypeLangSet;
} }
return v; return v;
} }
FcBool FcBool
FcConfigCompareValue (const FcValue left_o, FcConfigCompareValue (const FcValue *left_o,
FcOp op, FcOp op,
const FcValue right_o) const FcValue *right_o)
{ {
FcValue left = left_o; FcValue left = FcValueCanonicalize(left_o);
FcValue right = right_o; FcValue right = FcValueCanonicalize(right_o);
FcBool ret = FcFalse; FcBool ret = FcFalse;
left = FcConfigPromote (left, right); left = FcConfigPromote (left, right);
@ -632,20 +646,16 @@ FcConfigCompareValue (const FcValue left_o,
switch (op) { switch (op) {
case FcOpEqual: case FcOpEqual:
case FcOpListing: case FcOpListing:
ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si), ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
FcObjectPtrU(right.u.si)) == 0;
break; break;
case FcOpContains: case FcOpContains:
ret = FcStrStrIgnoreCase (FcObjectPtrU(left.u.si), ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
FcObjectPtrU(right.u.si)) != 0;
break; break;
case FcOpNotEqual: case FcOpNotEqual:
ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si), ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
FcObjectPtrU(right.u.si)) != 0;
break; break;
case FcOpNotContains: case FcOpNotContains:
ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si), ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
FcObjectPtrU(right.u.si)) == 0;
break; break;
default: default:
break; break;
@ -656,11 +666,11 @@ FcConfigCompareValue (const FcValue left_o,
case FcOpEqual: case FcOpEqual:
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi)); ret = FcMatrixEqual (left.u.m, right.u.m);
break; break;
case FcOpNotEqual: case FcOpNotEqual:
case FcOpNotContains: case FcOpNotContains:
ret = !FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi)); ret = !FcMatrixEqual (left.u.m, right.u.m);
break; break;
default: default:
break; break;
@ -671,17 +681,17 @@ FcConfigCompareValue (const FcValue left_o,
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
/* left contains right if right is a subset of left */ /* left contains right if right is a subset of left */
ret = FcCharSetIsSubset (FcCharSetPtrU(right.u.ci), FcCharSetPtrU(left.u.ci)); ret = FcCharSetIsSubset (right.u.c, left.u.c);
break; break;
case FcOpNotContains: case FcOpNotContains:
/* left contains right if right is a subset of left */ /* left contains right if right is a subset of left */
ret = !FcCharSetIsSubset (FcCharSetPtrU(right.u.ci), FcCharSetPtrU(left.u.ci)); ret = !FcCharSetIsSubset (right.u.c, left.u.c);
break; break;
case FcOpEqual: case FcOpEqual:
ret = FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci)); ret = FcCharSetEqual (left.u.c, right.u.c);
break; break;
case FcOpNotEqual: case FcOpNotEqual:
ret = !FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci)); ret = !FcCharSetEqual (left.u.c, right.u.c);
break; break;
default: default:
break; break;
@ -691,16 +701,16 @@ FcConfigCompareValue (const FcValue left_o,
switch (op) { switch (op) {
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li)); ret = FcLangSetContains (left.u.l, right.u.l);
break; break;
case FcOpNotContains: case FcOpNotContains:
ret = !FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li)); ret = !FcLangSetContains (left.u.l, right.u.l);
break; break;
case FcOpEqual: case FcOpEqual:
ret = FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li)); ret = FcLangSetEqual (left.u.l, right.u.l);
break; break;
case FcOpNotEqual: case FcOpNotEqual:
ret = !FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li)); ret = !FcLangSetEqual (left.u.l, right.u.l);
break; break;
default: default:
break; break;
@ -768,17 +778,17 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
break; break;
case FcOpString: case FcOpString:
v.type = FcTypeString; v.type = FcTypeString;
v.u.si = FcObjectStaticName(e->u.sval); v.u.s = FcObjectStaticName(e->u.sval);
v = FcValueSave (v); v = FcValueSave (v);
break; break;
case FcOpMatrix: case FcOpMatrix:
v.type = FcTypeMatrix; v.type = FcTypeMatrix;
v.u.mi = FcMatrixPtrCreateDynamic(e->u.mval); v.u.m = e->u.mval;
v = FcValueSave (v); v = FcValueSave (v);
break; break;
case FcOpCharSet: case FcOpCharSet:
v.type = FcTypeCharSet; v.type = FcTypeCharSet;
v.u.ci = FcCharSetPtrCreateDynamic(e->u.cval); v.u.c = e->u.cval;
v = FcValueSave (v); v = FcValueSave (v);
break; break;
case FcOpBool: case FcOpBool:
@ -821,7 +831,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
vl = FcConfigEvaluate (p, e->u.tree.left); vl = FcConfigEvaluate (p, e->u.tree.left);
vr = FcConfigEvaluate (p, e->u.tree.right); vr = FcConfigEvaluate (p, e->u.tree.right);
v.type = FcTypeBool; v.type = FcTypeBool;
v.u.b = FcConfigCompareValue (vl, e->op, vr); v.u.b = FcConfigCompareValue (&vl, e->op, &vr);
FcValueDestroy (vl); FcValueDestroy (vl);
FcValueDestroy (vr); FcValueDestroy (vr);
break; break;
@ -886,11 +896,9 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
switch (e->op) { switch (e->op) {
case FcOpPlus: case FcOpPlus:
v.type = FcTypeString; v.type = FcTypeString;
v.u.si = FcObjectStaticName v.u.s = FcObjectStaticName (FcStrPlus (vl.u.s, vr.u.s));
(FcStrPlus (FcObjectPtrU(vl.u.si),
FcObjectPtrU(vr.u.si)));
if (!FcObjectPtrU(v.u.si)) if (!v.u.s)
v.type = FcTypeVoid; v.type = FcTypeVoid;
break; break;
default: default:
@ -906,9 +914,8 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
if (m) if (m)
{ {
FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix)); FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
FcMatrixMultiply (m, FcMatrixPtrU(vl.u.mi), FcMatrixMultiply (m, vl.u.m, vr.u.m);
FcMatrixPtrU(vr.u.mi)); v.u.m = m;
v.u.mi = FcMatrixPtrCreateDynamic(m);
} }
else else
{ {
@ -1041,7 +1048,7 @@ FcConfigMatchValueList (FcPattern *p,
for (v = values; v; v = FcValueListPtrU(v->next)) for (v = values; v; v = FcValueListPtrU(v->next))
{ {
/* Compare the pattern value to the match expression value */ /* Compare the pattern value to the match expression value */
if (FcConfigCompareValue (v->value, t->op, value)) if (FcConfigCompareValue (&v->value, t->op, &value))
{ {
if (!ret) if (!ret)
ret = v; ret = v;
@ -1088,7 +1095,7 @@ FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
{ {
FcValueListPtr next = FcValueListPtrU(lp)->next; FcValueListPtr next = FcValueListPtrU(lp)->next;
if (lp.storage == FcStorageDynamic) if (lp.bank == FC_BANK_DYNAMIC)
{ {
FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
free (l); free (l);
@ -1866,7 +1873,7 @@ FcConfigGlobsMatch (const FcStrSet *globs,
int i; int i;
for (i = 0; i < globs->num; i++) for (i = 0; i < globs->num; i++)
if (FcConfigGlobMatch (FcStrSetGet(globs, i), string)) if (FcConfigGlobMatch (globs->strs[i], string))
return FcTrue; return FcTrue;
return FcFalse; return FcFalse;
} }

View File

@ -23,34 +23,21 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <sys/mman.h>
#include "fcint.h" #include "fcint.h"
/* #define CHECK */ /* #define CHECK */
/* #define CHATTY */ /* #define CHATTY */
static FcCharSet * charsets = 0; static FcCharSet ** charsets = 0;
static FcChar16 * numbers = 0; static FcChar16 ** numbers = 0;
static int charset_ptr, charset_count; static int charset_bank_count = 0, charset_ptr, charset_count;
static int charset_numbers_ptr, charset_numbers_count; static int charset_numbers_ptr, charset_numbers_count;
static FcCharLeaf * leaves = 0; static FcCharLeaf ** leaves = 0;
static int charset_leaf_ptr, charset_leaf_count; static int charset_leaf_ptr, charset_leaf_count;
static int * leaf_idx = 0; static int ** leaf_idx = 0;
static int charset_leaf_idx_ptr, charset_leaf_idx_count; static int charset_leaf_idx_ptr, charset_leaf_idx_count;
void
FcCharSetClearStatic()
{
charsets = 0;
numbers = 0;
charset_ptr = 0; charset_count = 0;
leaves = 0;
charset_leaf_ptr = 0; charset_leaf_count = 0;
leaf_idx = 0;
charset_leaf_idx_ptr = 0; charset_leaf_idx_count = 0;
}
FcCharSet * FcCharSet *
FcCharSetCreate (void) FcCharSetCreate (void)
{ {
@ -62,7 +49,7 @@ 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->storage = FcStorageDynamic; fcs->bank = FC_BANK_DYNAMIC;
fcs->u.dyn.leaves = 0; fcs->u.dyn.leaves = 0;
fcs->u.dyn.numbers = 0; fcs->u.dyn.numbers = 0;
return fcs; return fcs;
@ -77,18 +64,6 @@ FcCharSetNew (void)
return FcCharSetCreate (); return FcCharSetCreate ();
} }
void
FcCharSetPtrDestroy (FcCharSetPtr fcs)
{
FcCharSetDestroy (FcCharSetPtrU(fcs));
if (fcs.storage == FcStorageDynamic &&
FcCharSetPtrU(fcs)->ref != FC_REF_CONSTANT)
{
free (fcs.u.dyn);
FcMemFree (FC_MEM_CHARSET, sizeof(FcCharSet));
}
}
void void
FcCharSetDestroy (FcCharSet *fcs) FcCharSetDestroy (FcCharSet *fcs)
{ {
@ -97,7 +72,7 @@ FcCharSetDestroy (FcCharSet *fcs)
return; return;
if (--fcs->ref > 0) if (--fcs->ref > 0)
return; return;
if (fcs->storage == FcStorageDynamic) if (fcs->bank == FC_BANK_DYNAMIC)
{ {
for (i = 0; i < fcs->num; i++) for (i = 0; i < fcs->num; i++)
{ {
@ -173,7 +148,7 @@ FcCharSetPutLeaf (FcCharSet *fcs,
ucs4 >>= 8; ucs4 >>= 8;
if (ucs4 >= 0x10000) if (ucs4 >= 0x10000)
return FcFalse; return FcFalse;
if (fcs->storage == FcStorageStatic) if (fcs->bank != FC_BANK_DYNAMIC)
{ {
int i; int i;
@ -190,7 +165,6 @@ FcCharSetPutLeaf (FcCharSet *fcs,
leaves[i] = FcCharSetGetLeaf(fcs, i); leaves[i] = FcCharSetGetLeaf(fcs, i);
memcpy (numbers, FcCharSetGetNumbers(fcs), memcpy (numbers, FcCharSetGetNumbers(fcs),
fcs->num * sizeof (FcChar16)); fcs->num * sizeof (FcChar16));
fcs->storage = FcStorageDynamic;
} }
else else
{ {
@ -264,14 +238,14 @@ FcCharSetInsertLeaf (FcCharSet *fcs, FcChar32 ucs4, FcCharLeaf *leaf)
if (pos >= 0) if (pos >= 0)
{ {
FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf)); FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
if (fcs->storage == FcStorageDynamic) if (fcs->bank == FC_BANK_DYNAMIC)
{ {
free (fcs->u.dyn.leaves[pos]); free (fcs->u.dyn.leaves[pos]);
fcs->u.dyn.leaves[pos] = leaf; fcs->u.dyn.leaves[pos] = leaf;
} }
else else
{ {
leaves[leaf_idx[fcs->u.stat.leafidx_offset]+pos] = *leaf; leaves[fcs->bank][leaf_idx[fcs->bank][fcs->u.stat.leafidx_offset]+pos] = *leaf;
} }
return FcTrue; return FcTrue;
} }
@ -384,14 +358,6 @@ FcCharSetCopy (FcCharSet *src)
return src; return src;
} }
FcCharSetPtr
FcCharSetCopyPtr (FcCharSetPtr src)
{
if (FcCharSetPtrU(src)->ref != FC_REF_CONSTANT)
FcCharSetPtrU(src)->ref++;
return src;
}
FcBool FcBool
FcCharSetEqual (const FcCharSet *a, const FcCharSet *b) FcCharSetEqual (const FcCharSet *a, const FcCharSet *b)
{ {
@ -1081,8 +1047,8 @@ FcCharSetFreezeBase (FcCharSet *fcs)
ent->set.ref = FC_REF_CONSTANT; ent->set.ref = FC_REF_CONSTANT;
ent->set.num = fcs->num; ent->set.num = fcs->num;
ent->set.storage = fcs->storage; ent->set.bank = fcs->bank;
if (fcs->storage == FcStorageDynamic) if (fcs->bank == FC_BANK_DYNAMIC)
{ {
if (fcs->num) if (fcs->num)
{ {
@ -1154,7 +1120,7 @@ FcCharSetFreeze (FcCharSet *fcs)
} }
n = FcCharSetFreezeBase (b); n = FcCharSetFreezeBase (b);
bail1: bail1:
if (b->storage == FcStorageDynamic) if (b->bank == FC_BANK_DYNAMIC)
{ {
if (b->u.dyn.leaves) if (b->u.dyn.leaves)
{ {
@ -1231,7 +1197,7 @@ FcNameParseCharSet (FcChar8 *string)
#endif #endif
n = FcCharSetFreezeBase (c); n = FcCharSetFreezeBase (c);
bail1: bail1:
if (c->storage == FcStorageDynamic) if (c->bank == FC_BANK_DYNAMIC)
{ {
if (c->u.dyn.leaves) if (c->u.dyn.leaves)
{ {
@ -1323,205 +1289,160 @@ FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
return FcTrue; return FcTrue;
} }
void
FcCharSet * FcCharSetNewBank(void)
FcCharSetPtrU (FcCharSetPtr ci)
{ {
switch (ci.storage) charset_count = 0;
{ charset_numbers_count = 0;
case FcStorageDynamic: charset_leaf_count = 0;
return ci.u.dyn; charset_leaf_idx_count = 0;
case FcStorageStatic:
return &charsets[ci.u.stat];
default:
return 0;
}
} }
FcCharSetPtr int
FcCharSetPtrCreateDynamic(FcCharSet *c) FcCharSetNeededBytes (const FcCharSet *c)
{ {
FcCharSetPtr new; /* yes, there's redundancy */
new.storage = FcStorageDynamic;
new.u.dyn = c;
return new;
}
FcBool
FcCharSetPrepareSerialize(FcCharSet *c)
{
/* note the redundancy */
charset_count++; charset_count++;
charset_leaf_idx_count++; charset_leaf_idx_count++;
charset_leaf_count += c->num; charset_leaf_count += c->num;
charset_numbers_count += c->num; charset_numbers_count += c->num;
return sizeof (FcCharSet) +
sizeof (int) + /* leaf_idx */
sizeof (FcCharLeaf) * c->num + /* leaf */
sizeof (FcChar16) * c->num; /* number */
}
static FcBool
FcCharSetEnsureBank (int bi)
{
if (!charsets || charset_bank_count <= bi)
{
int new_count = charset_bank_count + 2;
FcCharSet ** cs;
FcChar16 ** n;
FcCharLeaf ** lvs;
int ** lvi;
int i;
cs = realloc(charsets, sizeof(FcCharSet*) * new_count);
if (!cs) return 0;
n = realloc(numbers, sizeof(FcChar16*) * new_count);
if (!n) return 0;
lvs = realloc(leaves, sizeof(FcCharLeaf*) * new_count);
if (!lvs) return 0;
lvi = realloc(leaf_idx, sizeof(int*) * new_count);
if (!lvi) return 0;
charsets = cs; numbers = n; leaves = lvs; leaf_idx = lvi;
for (i = charset_bank_count; i < new_count; i++)
{
charsets[i] = 0;
numbers[i] = 0;
leaves[i] = 0;
leaf_idx[i] = 0;
}
charset_bank_count = new_count;
}
return FcTrue; return FcTrue;
} }
FcCharSetPtr void *
FcCharSetSerialize(FcCharSet *c) FcCharSetDistributeBytes (FcCache * metadata, void * block_ptr)
{
int bi = FcCacheBankToIndex(metadata->bank);
if (!FcCharSetEnsureBank(bi))
return 0;
charsets[bi] = (FcCharSet *)block_ptr;
block_ptr = (void *)((char *)block_ptr +
(sizeof (FcCharSet) * charset_count));
numbers[bi] = (FcChar16 *)block_ptr;
block_ptr = (void *)((char *)block_ptr +
(sizeof(FcChar16) * charset_numbers_count));
leaves[bi] = (FcCharLeaf *)block_ptr;
block_ptr = (void *)((char *)block_ptr +
(sizeof(FcCharLeaf) * charset_leaf_count));
leaf_idx[bi] = (int *)block_ptr;
block_ptr = (void *)((char *)block_ptr +
(sizeof(int) * charset_leaf_idx_count));
metadata->charset_count = charset_count;
metadata->charset_numbers_count = charset_numbers_count;
metadata->charset_leaf_count = charset_leaf_count;
metadata->charset_leaf_idx_count = charset_leaf_idx_count;
charset_ptr = 0; charset_leaf_ptr = 0;
charset_leaf_idx_ptr = 0; charset_numbers_ptr = 0;
return block_ptr;
}
FcCharSet *
FcCharSetSerialize(int bank, FcCharSet *c)
{ {
int i; int i;
FcCharSetPtr newp;
FcCharSet new; FcCharSet new;
int bi = FcCacheBankToIndex(bank), cp = charset_ptr;
if (!charsets)
{
charsets = malloc(sizeof(FcCharSet) * charset_count);
if (!charsets) goto bail;
numbers = malloc(sizeof(FcChar16) * charset_numbers_count);
if (!numbers) goto bail1;
leaves = malloc(sizeof(FcCharLeaf) * charset_leaf_count);
if (!leaves) goto bail2;
leaf_idx = malloc(sizeof(int)*charset_leaf_idx_count);
if (!leaf_idx) goto bail3;
}
new.ref = FC_REF_CONSTANT; new.ref = FC_REF_CONSTANT;
new.storage = FcStorageStatic; new.bank = bank;
new.u.stat.leafidx_offset = charset_leaf_idx_ptr; new.u.stat.leafidx_offset = charset_leaf_idx_ptr;
new.u.stat.numbers_offset = charset_numbers_ptr; new.u.stat.numbers_offset = charset_numbers_ptr;
new.num = c->num; new.num = c->num;
newp.storage = FcStorageStatic; charsets[bi][charset_ptr++] = new;
newp.u.stat = charset_ptr;
charsets[charset_ptr++] = new;
leaf_idx[charset_leaf_idx_ptr++] = charset_leaf_ptr; leaf_idx[bi][charset_leaf_idx_ptr++] = charset_leaf_ptr;
for (i = 0; i < c->num; i++) for (i = 0; i < c->num; i++)
{ {
memcpy (&leaves[charset_leaf_ptr++], memcpy (&leaves[bi][charset_leaf_ptr++],
c->u.dyn.leaves[i], sizeof(FcCharLeaf)); c->u.dyn.leaves[i], sizeof(FcCharLeaf));
numbers[charset_numbers_ptr++] = c->u.dyn.numbers[i]; numbers[bi][charset_numbers_ptr++] = c->u.dyn.numbers[i];
} }
return newp; return &charsets[bi][cp];
bail3:
free (leaves);
bail2:
free (numbers);
bail1:
free (charsets);
bail:
return FcCharSetPtrCreateDynamic(0);
} }
FcBool void *
FcCharSetRead (int fd, FcCache metadata) FcCharSetUnserialize (FcCache metadata, void *block_ptr)
{ {
charsets = mmap(NULL, int bi = FcCacheBankToIndex(metadata.bank);
metadata.charsets_length * sizeof (FcCharSet), if (!FcCharSetEnsureBank(bi))
PROT_READ, return 0;
MAP_SHARED, fd, metadata.charsets_offset);
if (charsets == MAP_FAILED)
goto bail;
charset_count = charset_ptr = metadata.charsets_length;
leaves = mmap(NULL, charsets[bi] = (FcCharSet *)block_ptr;
metadata.charset_num_sum * sizeof (FcCharLeaf), block_ptr = (void *)((char *)block_ptr +
PROT_READ, (sizeof (FcCharSet) * metadata.charset_count));
MAP_SHARED, fd, metadata.charset_leaf_offset); numbers[bi] = (FcChar16 *)block_ptr;
if (leaves == MAP_FAILED) block_ptr = (void *)((char *)block_ptr +
goto bail1; (sizeof(FcChar16) * metadata.charset_numbers_count));
charset_leaf_count = charset_leaf_ptr = metadata.charset_num_sum; leaves[bi] = (FcCharLeaf *)block_ptr;
block_ptr = (void *)((char *)block_ptr +
(sizeof(FcCharLeaf) * metadata.charset_leaf_count));
leaf_idx[bi] = (int *)block_ptr;
block_ptr = (void *)((char *)block_ptr +
(sizeof(int) * metadata.charset_leaf_idx_count));
leaf_idx = mmap(NULL, return block_ptr;
metadata.charsets_length * sizeof (FcCharLeaf*),
PROT_READ,
MAP_SHARED, fd, metadata.charset_leafidx_offset);
if (leaf_idx == MAP_FAILED)
goto bail2;
charset_leaf_idx_count = charset_leaf_idx_ptr = metadata.charsets_length;
numbers = mmap(NULL,
metadata.charset_num_sum * sizeof (FcChar16),
PROT_READ,
MAP_SHARED, fd, metadata.charset_numbers_offset);
if (numbers == MAP_FAILED)
goto bail3;
charset_numbers_count = charset_numbers_ptr = metadata.charset_num_sum;
return FcTrue;
bail3:
munmap (leaf_idx, metadata.charsets_length * sizeof (FcCharLeaf*));
bail2:
munmap (leaves, metadata.charset_num_sum * sizeof (FcCharLeaf));
bail1:
munmap (charsets, metadata.charsets_length * sizeof (FcCharSet));
bail:
return FcFalse;
}
FcBool
FcCharSetWrite (int fd, FcCache *metadata)
{
metadata->charsets_length = charset_ptr;
metadata->charsets_offset = FcCacheNextOffset(fd);
if (charset_ptr > 0)
{
lseek (fd, metadata->charsets_offset, SEEK_SET);
if (write (fd, charsets, charset_ptr * sizeof(FcCharSet)) == -1)
return FcFalse;
}
metadata->charset_leaf_offset = FcCacheNextOffset(fd);
metadata->charset_num_sum = charset_leaf_ptr;
if (charset_leaf_ptr > 0)
{
lseek (fd, metadata->charset_leaf_offset, SEEK_SET);
if (write (fd, leaves, charset_leaf_ptr * sizeof(FcCharLeaf)) == -1)
return FcFalse;
}
metadata->charset_leafidx_offset = FcCacheNextOffset(fd);
if (charset_leaf_idx_ptr > 0)
{
lseek (fd, metadata->charset_leafidx_offset, SEEK_SET);
if (write (fd, leaf_idx, charset_leaf_idx_ptr * sizeof(FcCharLeaf*)) == -1)
return FcFalse;
}
metadata->charset_numbers_offset = FcCacheNextOffset(fd);
if (charset_leaf_ptr > 0)
{
lseek (fd, metadata->charset_numbers_offset, SEEK_SET);
if (write (fd, numbers, charset_leaf_ptr * sizeof(FcChar16)) == -1)
return FcFalse;
}
return FcTrue;
} }
FcCharLeaf * FcCharLeaf *
FcCharSetGetLeaf(const FcCharSet *c, int i) FcCharSetGetLeaf(const FcCharSet *c, int i)
{ {
switch (c->storage) int bi;
{ if (c->bank == FC_BANK_DYNAMIC)
case FcStorageDynamic:
return c->u.dyn.leaves[i]; return c->u.dyn.leaves[i];
case FcStorageStatic: bi = FcCacheBankToIndex(c->bank);
return &leaves[leaf_idx[c->u.stat.leafidx_offset]+i];
default: return &leaves[bi][leaf_idx[bi][c->u.stat.leafidx_offset]+i];
return 0;
}
} }
FcChar16 * FcChar16 *
FcCharSetGetNumbers(const FcCharSet *c) FcCharSetGetNumbers(const FcCharSet *c)
{ {
switch (c->storage) int bi;
{ if (c->bank == FC_BANK_DYNAMIC)
case FcStorageDynamic:
return c->u.dyn.numbers; return c->u.dyn.numbers;
case FcStorageStatic: bi = FcCacheBankToIndex(c->bank);
return &numbers[c->u.stat.numbers_offset];
default: return &numbers[bi][c->u.stat.numbers_offset];
return 0;
}
} }

View File

@ -40,24 +40,20 @@ FcValuePrint (const FcValue v)
printf (" %g(f)", v.u.d); printf (" %g(f)", v.u.d);
break; break;
case FcTypeString: case FcTypeString:
printf (" \"%s\"", FcObjectPtrU(v.u.si)); printf (" \"%s\"", v.u.s);
break; break;
case FcTypeBool: case FcTypeBool:
printf (" %s", v.u.b ? "FcTrue" : "FcFalse"); printf (" %s", v.u.b ? "FcTrue" : "FcFalse");
break; break;
case FcTypeMatrix: case FcTypeMatrix:
{ printf (" (%f %f; %f %f)", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
FcMatrix *m = FcMatrixPtrU(v.u.mi);
printf (" (%f %f; %f %f)", m->xx, m->xy, m->yx, m->yy);
break; break;
}
case FcTypeCharSet: /* XXX */ case FcTypeCharSet: /* XXX */
printf (" set"); printf (" set");
break; break;
case FcTypeLangSet: case FcTypeLangSet:
printf (" "); printf (" ");
FcLangSetPrint (FcLangSetPtrU(v.u.li)); FcLangSetPrint (v.u.l);
break; break;
case FcTypeFTFace: case FcTypeFTFace:
printf (" face"); printf (" face");
@ -70,7 +66,7 @@ FcValueListPrint (FcValueListPtr l)
{ {
for (; FcValueListPtrU(l); l = FcValueListPtrU(l)->next) for (; FcValueListPtrU(l); l = FcValueListPtrU(l)->next)
{ {
FcValuePrint (FcValueListPtrU(l)->value); FcValuePrint (FcValueCanonicalize(&FcValueListPtrU(l)->value));
switch (FcValueListPtrU(l)->binding) { switch (FcValueListPtrU(l)->binding) {
case FcValueBindingWeak: case FcValueBindingWeak:
printf ("(w)"); printf ("(w)");

View File

@ -274,10 +274,17 @@ FcDirScan (FcFontSet *set,
} }
FcBool FcBool
FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir) FcDirSave (FcFontSet *set, const FcChar8 *dir)
{ {
#if 0 static int rand_state = 0;
return FcDirCacheWriteDir (set, dirs, dir); int bank;
#endif
return FcTrue; if (!rand_state)
rand_state = time(0L);
bank = rand_r(&rand_state);
while (FcCacheHaveBank(bank))
bank = rand_r(&rand_state);
return FcDirCacheWrite (bank, set, dir);
} }

View File

@ -81,27 +81,58 @@ FcFontSetAdd (FcFontSet *s, FcPattern *font)
return FcTrue; return FcTrue;
} }
FcBool static int * fcfs_pat_count;
FcFontSetPrepareSerialize (FcFontSet *s)
void
FcFontSetNewBank (void)
{ {
int i; FcPatternNewBank();
FcObjectNewBank();
for (i = 0; i < s->nfont; i++)
if (!FcPatternPrepareSerialize(s->fonts[i]))
return FcFalse;
return FcTrue;
} }
FcBool int
FcFontSetSerialize (FcFontSet * s) FcFontSetNeededBytes (FcFontSet *s)
{ {
int i; int i, c, cum = 0;
FcPattern * p;
for (i = 0; i < s->nfont; i++) for (i = 0; i < s->nfont; i++)
{ {
p = FcPatternSerialize (s->fonts[i]); c = FcPatternNeededBytes(s->fonts[i]);
if (c < 0)
return c;
cum += c;
}
if (cum > 0)
return cum + sizeof(int);
else
return 0;
}
void *
FcFontSetDistributeBytes (FcCache * metadata, void * block_ptr)
{
fcfs_pat_count = (int *)block_ptr;
block_ptr = (int *)block_ptr + 1;
// we don't consume any bytes for the fontset itself,
// since we don't allocate it statically.
block_ptr = FcPatternDistributeBytes (metadata, block_ptr);
// for good measure, write out the object ids used for
// this bank to the file.
return FcObjectDistributeBytes (metadata, block_ptr);
}
FcBool
FcFontSetSerialize (int bank, FcFontSet * s)
{
int i;
FcPattern * p;
*fcfs_pat_count = s->nfont;
for (i = 0; i < s->nfont; i++)
{
p = FcPatternSerialize (bank, s->fonts[i]);
if (!p) return FcFalse; if (!p) return FcFalse;
FcPatternDestroy (s->fonts[i]); FcPatternDestroy (s->fonts[i]);
@ -111,103 +142,34 @@ FcFontSetSerialize (FcFontSet * s)
return FcTrue; return FcTrue;
} }
void
FcFontSetClearStatic (void)
{
FcPatternClearStatic();
}
FcBool FcBool
FcFontSetRead(int fd, FcConfig * config, FcCache metadata) FcFontSetUnserialize(FcCache metadata, FcFontSet * s, void * block_ptr)
{ {
int i, mz, j; int nfont;
FcPattern * buf; int i, n;
lseek(fd, metadata.fontsets_offset, SEEK_SET); nfont = *(int *)block_ptr;
for (i = FcSetSystem; i <= FcSetApplication; i++) block_ptr = (int *)block_ptr + 1;
if (s->sfont < s->nfont + nfont)
{ {
if (config->fonts[i]) int sfont = s->nfont + nfont;
{ FcPattern ** pp;
if (config->fonts[i]->nfont > 0 && config->fonts[i]->fonts) pp = realloc (s->fonts, sfont * sizeof (FcPattern));
free (config->fonts[i]->fonts); if (!pp)
free (config->fonts[i]); return FcFalse;
} s->fonts = pp;
s->sfont = sfont;
} }
n = s->nfont;
s->nfont += nfont;
for (i = FcSetSystem; i <= FcSetApplication; i++) if (nfont > 0)
{ {
read(fd, &mz, sizeof(int)); FcPattern * p = FcPatternUnserialize (metadata, block_ptr);
if (mz != FC_CACHE_MAGIC) for (i = 0; i < nfont; i++)
continue; s->fonts[n + i] = p+i;
config->fonts[i] = malloc(sizeof(FcFontSet));
if (!config->fonts[i])
return FcFalse;
FcMemAlloc(FC_MEM_FONTSET, sizeof(FcFontSet));
if (read(fd, config->fonts[i], sizeof(FcFontSet)) == -1)
goto bail;
if (config->fonts[i]->sfont > 0)
{
config->fonts[i]->fonts = malloc
(config->fonts[i]->sfont*sizeof(FcPattern *));
buf = malloc (config->fonts[i]->sfont * sizeof(FcPattern));
if (!config->fonts[i]->fonts || !buf)
goto bail;
for (j = 0; j < config->fonts[i]->nfont; j++)
{
config->fonts[i]->fonts[j] = buf+j;
if (read(fd, buf+j, sizeof(FcPattern)) == -1)
goto bail;
}
}
} }
return FcTrue;
bail:
for (i = FcSetSystem; i <= FcSetApplication; i++)
{
if (config->fonts[i])
{
if (config->fonts[i]->fonts)
free (config->fonts[i]->fonts);
free(config->fonts[i]);
}
config->fonts[i] = 0;
}
return FcFalse;
}
FcBool
FcFontSetWrite(int fd, FcConfig * config, FcCache * metadata)
{
int c, t, i, j;
int m = FC_CACHE_MAGIC, z = 0;
metadata->fontsets_offset = FcCacheNextOffset(fd);
lseek(fd, metadata->fontsets_offset, SEEK_SET);
for (i = FcSetSystem; i <= FcSetApplication; i++)
{
if (!config->fonts[i])
{
write(fd, &z, sizeof(int));
continue;
}
else
write(fd, &m, sizeof(int));
if ((c = write(fd, config->fonts[i], sizeof(FcFontSet))) == -1)
return FcFalse;
t = c;
if (config->fonts[i]->nfont > 0)
{
for (j = 0; j < config->fonts[i]->nfont; j++)
{
if ((c = write(fd, config->fonts[i]->fonts[j],
sizeof(FcPattern))) == -1)
return FcFalse;
}
}
}
return FcTrue; return FcTrue;
} }

View File

@ -61,9 +61,6 @@ FcInitLoadConfig (void)
if (!config) if (!config)
return FcFalse; return FcFalse;
if (!FcCacheRead(config))
FcCacheForce(FcTrue);
if (!FcConfigParseAndLoad (config, 0, FcTrue)) if (!FcConfigParseAndLoad (config, 0, FcTrue))
{ {
FcConfigDestroy (config); FcConfigDestroy (config);

View File

@ -109,16 +109,8 @@ typedef enum _FcValueBinding {
FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame
} FcValueBinding; } FcValueBinding;
typedef struct _FcStrSetPtr {
FcStorage storage;
union {
int stat;
struct _FcStrSet *dyn;
} u;
} FcStrSetPtr;
typedef struct _FcValueListPtr { typedef struct _FcValueListPtr {
FcStorage storage; int bank;
union { union {
int stat; int stat;
struct _FcValueList *dyn; struct _FcValueList *dyn;
@ -132,8 +124,10 @@ typedef struct _FcValueList {
FcValueBinding binding; FcValueBinding binding;
} FcValueList; } FcValueList;
typedef int FcObjectPtr;
typedef struct _FcPatternEltPtr { typedef struct _FcPatternEltPtr {
FcStorage storage; int bank;
union { union {
int stat; int stat;
struct _FcPatternElt *dyn; struct _FcPatternElt *dyn;
@ -150,6 +144,7 @@ struct _FcPattern {
int size; int size;
FcPatternEltPtr elts; FcPatternEltPtr elts;
int ref; int ref;
int bank;
}; };
typedef enum _FcOp { typedef enum _FcOp {
@ -222,7 +217,7 @@ typedef struct _FcCharLeaf {
struct _FcCharSet { struct _FcCharSet {
int ref; /* reference count */ int ref; /* reference count */
int num; /* size of leaves and numbers arrays */ int num; /* size of leaves and numbers arrays */
FcStorage storage; int bank;
union { union {
struct { struct {
FcCharLeaf **leaves; FcCharLeaf **leaves;
@ -239,11 +234,7 @@ struct _FcStrSet {
int ref; /* reference count */ int ref; /* reference count */
int num; int num;
int size; int size;
FcStorage storage; FcChar8 **strs;
union {
FcChar8 **strs;
int stridx_offset;
} u;
}; };
struct _FcStrList { struct _FcStrList {
@ -261,21 +252,17 @@ typedef struct _FcStrBuf {
typedef struct _FcCache { typedef struct _FcCache {
int magic; int magic;
off_t fontsets_offset; int count;
off_t pattern_offset; int pattern_length; int bank;
off_t patternelt_offset; int patternelt_length; int pattern_count;
off_t valuelist_offset; int valuelist_length; int patternelt_count;
off_t object_offset; int object_length; int valuelist_count;
off_t objectcontent_offset; int objectcontent_length; int str_count;
off_t langsets_offset; int langsets_length; int langset_count;
off_t charsets_offset; int charsets_length; int charset_count;
off_t charset_leaf_offset; int charset_num_sum; int charset_numbers_count;
off_t charset_leafidx_offset; int charset_leaf_count;
off_t charset_numbers_offset; int charset_leaf_idx_count;
off_t matrices_offset; int matrices_length;
off_t strsets_offset; int strsets_length;
off_t strsets_idx_offset; int strsets_idx_length;
off_t strset_buf_offset; int strset_buf_length;
} FcCache; } FcCache;
/* /*
@ -321,6 +308,11 @@ typedef struct _FcCaseFold {
#define FC_MAX_FILE_LEN 4096 #define FC_MAX_FILE_LEN 4096
#define FC_STORAGE_STATIC 0x80
#define fc_value_string(v) (((v)->type & FC_STORAGE_STATIC) ? ((FcChar8 *) v) + (v)->u.s_off : (v) -> u.s)
#define fc_value_charset(v) (((v)->type & FC_STORAGE_STATIC) ? (const FcCharSet *)(((char *) v) + (v)->u.c_off) : (v) -> u.c)
#define fc_value_langset(v) (((v)->type & FC_STORAGE_STATIC) ? (const FcLangSet *)(((char *) v) + (v)->u.l_off) : (v) -> u.l)
/* /*
* The per-user ~/.fonts.cache-<version> file is loaded into * The per-user ~/.fonts.cache-<version> file is loaded into
* this data structure. Each directory gets a substructure * this data structure. Each directory gets a substructure
@ -449,26 +441,29 @@ typedef struct _FcCharMap FcCharMap;
/* fccache.c */ /* fccache.c */
int
FcCacheNextOffset(int fd);
void void
FcCacheForce(FcBool force); FcCacheForce(FcBool force);
void
FcCacheClearStatic(void);
FcBool FcBool
FcCachePrepareSerialize(FcConfig * config); FcCacheSerialize (int bank, FcConfig * config);
FcBool FcFontSet *
FcCacheSerialize (FcConfig * config);
FcBool
FcCacheRead (FcConfig *config); FcCacheRead (FcConfig *config);
FcBool FcBool
FcCacheWrite (FcConfig * config); FcDirCacheRead (FcFontSet * set, const FcChar8 *dir);
FcBool
FcDirCacheWrite (int bank, FcFontSet *set, const FcChar8 *dir);
int
FcCacheBankCount (void);
FcBool
FcCacheHaveBank (int bank);
int
FcCacheBankToIndex (int bank);
/* fccfg.c */ /* fccfg.c */
@ -508,9 +503,9 @@ FcConfigSetFonts (FcConfig *config,
FcSetName set); FcSetName set);
FcBool FcBool
FcConfigCompareValue (const FcValue m, FcConfigCompareValue (const FcValue *m,
FcOp op, FcOp op,
const FcValue v); const FcValue *v);
FcBool FcBool
FcConfigGlobAdd (FcConfig *config, FcConfigGlobAdd (FcConfig *config,
@ -534,9 +529,6 @@ FcConfigAcceptFont (FcConfig *config,
FcCharSet * FcCharSet *
FcCharSetFreeze (FcCharSet *cs); FcCharSetFreeze (FcCharSet *cs);
FcCharSetPtr
FcCharSetCopyPtr (FcCharSetPtr src);
void void
FcCharSetThawAll (void); FcCharSetThawAll (void);
@ -550,19 +542,20 @@ FcCharLeaf *
FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4); FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4);
void void
FcCharSetPtrDestroy (FcCharSetPtr fcs); FcCharSetNewBank (void);
void int
FcCharSetClearStatic(void); FcCharSetNeededBytes (const FcCharSet *c);
FcBool void *
FcCharSetPrepareSerialize(FcCharSet *c); FcCharSetDistributeBytes (FcCache * metadata,
void * block_ptr);
FcCharSetPtr FcCharSet *
FcCharSetSerialize(FcCharSet *c); FcCharSetSerialize(int bank, FcCharSet *c);
FcCharSetPtr void *
FcCharSetPtrCreateDynamic(FcCharSet *c); FcCharSetUnserialize (FcCache metadata, void *block_ptr);
FcCharLeaf * FcCharLeaf *
FcCharSetGetLeaf(const FcCharSet *c, int i); FcCharSetGetLeaf(const FcCharSet *c, int i);
@ -570,12 +563,6 @@ FcCharSetGetLeaf(const FcCharSet *c, int i);
FcChar16 * FcChar16 *
FcCharSetGetNumbers(const FcCharSet *c); FcCharSetGetNumbers(const FcCharSet *c);
FcBool
FcCharSetRead (int fd, FcCache metadata);
FcBool
FcCharSetWrite (int fd, FcCache *metadata);
/* fcdbg.c */ /* fcdbg.c */
void void
FcValueListPrint (const FcValueListPtr l); FcValueListPrint (const FcValueListPtr l);
@ -601,9 +588,6 @@ FcSubstPrint (const FcSubst *subst);
int int
FcDebug (void); FcDebug (void);
FcCharSet *
FcCharSetPtrU (FcCharSetPtr mi);
/* fcdir.c */ /* fcdir.c */
FcBool FcBool
@ -650,19 +634,19 @@ FcFreeTypeGetPrivateMap (FT_Encoding encoding);
/* fcfs.c */ /* fcfs.c */
void void
FcFontSetClearStatic (void); FcFontSetNewBank (void);
int
FcFontSetNeededBytes (FcFontSet *s);
void *
FcFontSetDistributeBytes (FcCache * metadata, void * block_ptr);
FcBool FcBool
FcFontSetPrepareSerialize (FcFontSet * s); FcFontSetSerialize (int bank, FcFontSet * s);
FcBool FcBool
FcFontSetSerialize (FcFontSet * s); FcFontSetUnserialize(FcCache metadata, FcFontSet * s, void * block_ptr);
FcBool
FcFontSetRead(int fd, FcConfig * config, FcCache metadata);
FcBool
FcFontSetWrite(int fd, FcConfig * config, FcCache * metadata);
/* fcgram.y */ /* fcgram.y */
int int
@ -745,28 +729,20 @@ FcBool
FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls); FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls);
void void
FcLangSetClearStatic (void); FcLangSetNewBank (void);
FcBool int
FcLangSetPrepareSerialize (FcLangSet *l); FcLangSetNeededBytes (const FcLangSet *l);
FcLangSetPtr void *
FcLangSetSerialize (FcLangSet *l); FcLangSetDistributeBytes (FcCache * metadata,
void * block_ptr);
FcLangSet * FcLangSet *
FcLangSetPtrU (FcLangSetPtr li); FcLangSetSerialize (int bank, FcLangSet *l);
FcLangSetPtr void *
FcLangSetPtrCreateDynamic (FcLangSet *l); FcLangSetUnserialize (FcCache metadata, void *block_ptr);
void
FcLangSetPtrDestroy (FcLangSetPtr li);
FcBool
FcLangSetRead (int fd, FcCache metadata);
FcBool
FcLangSetWrite (int fd, FcCache *metadata);
/* fclist.c */ /* fclist.c */
@ -781,7 +757,30 @@ FcListPatternMatchAny (const FcPattern *p,
FcBool FcBool
FcNameBool (const FcChar8 *v, FcBool *result); FcNameBool (const FcChar8 *v, FcBool *result);
void
FcObjectNewBank(void);
void *
FcObjectDistributeBytes (FcCache * metadata,
void * block_ptr);
FcObjectPtr
FcObjectToPtr (const char * si);
int
FcObjectNeededBytes (FcObjectPtr p);
void
FcObjectUnserialize (FcCache metadata, FcConfig * config, void *block_ptr);
FcObjectPtr
FcObjectSerialize (FcObjectPtr s);
/* fcpat.c */ /* fcpat.c */
FcValue
FcValueCanonicalize (const FcValue *v);
void void
FcValueListDestroy (FcValueListPtr l); FcValueListDestroy (FcValueListPtr l);
@ -807,18 +806,9 @@ FcPatternFini (void);
FcBool FcBool
FcPatternAppend (FcPattern *p, FcPattern *s); FcPatternAppend (FcPattern *p, FcPattern *s);
void const char *
FcObjectClearStatic(void);
FcObjectPtr
FcObjectStaticName (const char *name); FcObjectStaticName (const char *name);
FcBool
FcObjectRead (int fd, FcCache metadata);
FcBool
FcObjectWrite (int fd, FcCache * metadata);
const char * const char *
FcObjectPtrU (FcObjectPtr p); FcObjectPtrU (FcObjectPtr p);
@ -826,16 +816,13 @@ int
FcObjectPtrCompare (FcObjectPtr a, FcObjectPtr b); FcObjectPtrCompare (FcObjectPtr a, FcObjectPtr b);
void void
FcObjectPtrDestroy (FcObjectPtr p); FcPatternNewBank (void);
FcBool int
FcPatternPrepareSerialize (FcPattern *p); FcPatternNeededBytes (FcPattern *p);
void void *
FcValueListClearStatic (void); FcPatternDistributeBytes (FcCache * metadata, void * block_ptr);
void
FcPatternClearStatic (void);
FcValueList * FcValueList *
FcValueListPtrU(FcValueListPtr p); FcValueListPtrU(FcValueListPtr p);
@ -846,85 +833,25 @@ FcPatternEltU (FcPatternEltPtr pei);
FcValueListPtr FcValueListPtr
FcValueListPtrCreateDynamic(FcValueList * p); FcValueListPtrCreateDynamic(FcValueList * p);
FcBool FcPattern *
FcValueListPrepareSerialize (FcValueList *p); FcPatternSerialize (int bank, FcPattern * p);
FcValueListPtr
FcValueListSerialize(FcValueList *pi);
FcPattern * FcPattern *
FcPatternSerialize (FcPattern * p); FcPatternUnserialize (FcCache metadata, void *block_ptr);
FcBool
FcPatternRead (int fd, FcCache metadata);
FcBool
FcPatternWrite (int fd, FcCache *metadata);
FcBool
FcPatternEltRead (int fd, FcCache metadata);
FcBool
FcPatternEltWrite (int fd, FcCache *metadata);
FcBool
FcValueListRead (int fd, FcCache metadata);
FcBool
FcValueListWrite (int fd, FcCache *metadata);
/* fcrender.c */ /* fcrender.c */
/* fcmatrix.c */ /* fcmatrix.c */
extern const FcMatrixPtr FcIdentityMatrix; extern const FcMatrix FcIdentityMatrix;
void void
FcMatrixFree (FcMatrix *mat); FcMatrixFree (FcMatrix *mat);
void
FcMatrixPtrDestroy (FcMatrixPtr mi);
FcBool
FcMatrixPrepareSerialize(FcMatrix *m);
FcMatrixPtr
FcMatrixSerialize(FcMatrix *m);
FcMatrix *
FcMatrixPtrU (FcMatrixPtr mi);
FcMatrixPtr
FcMatrixPtrCreateDynamic (FcMatrix *m);
void
FcMatrixClearStatic (void);
FcBool
FcMatrixWrite (int fd, FcCache *metadata);
FcBool
FcMatrixRead (int fd, FcCache metadata);
/* fcstr.c */ /* fcstr.c */
FcStrSet *
FcStrSetPtrU (const FcStrSetPtr set);
FcStrSetPtr
FcStrSetPtrCreateDynamic (const FcStrSet * set);
void
FcStrSetClearStatic (void);
FcBool
FcStrSetPrepareSerialize (const FcStrSet *set);
void void
FcStrSetSort (FcStrSet * set); FcStrSetSort (FcStrSet * set);
FcChar8 *
FcStrSetGet (const FcStrSet *set, int i);
FcChar8 * FcChar8 *
FcStrPlus (const FcChar8 *s1, const FcChar8 *s2); FcStrPlus (const FcChar8 *s1, const FcChar8 *s2);
@ -949,15 +876,6 @@ FcStrBufString (FcStrBuf *buf, const FcChar8 *s);
FcBool FcBool
FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len); FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len);
FcStrSetPtr
FcStrSetSerialize (FcStrSet *set);
FcBool
FcStrSetRead (int fd, FcCache metadata);
FcBool
FcStrSetWrite (int fd, FcCache *metadata);
int int
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2); FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);

View File

@ -22,8 +22,6 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <fcntl.h>
#include <sys/mman.h>
#include "fcint.h" #include "fcint.h"
typedef struct { typedef struct {
@ -40,7 +38,7 @@ typedef struct {
struct _FcLangSet { struct _FcLangSet {
FcChar32 map[NUM_LANG_SET_MAP]; FcChar32 map[NUM_LANG_SET_MAP];
FcStrSetPtr extra; FcStrSet *extra;
}; };
#define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f))) #define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
@ -217,22 +215,15 @@ FcLangSetCreate (void)
return 0; return 0;
FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet)); FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
memset (ls->map, '\0', sizeof (ls->map)); memset (ls->map, '\0', sizeof (ls->map));
ls->extra = FcStrSetPtrCreateDynamic(0); ls->extra = 0;
return ls; return ls;
} }
void
FcLangSetPtrDestroy (FcLangSetPtr li)
{
if (li.storage == FcStorageDynamic)
FcLangSetDestroy(FcLangSetPtrU(li));
}
void void
FcLangSetDestroy (FcLangSet *ls) FcLangSetDestroy (FcLangSet *ls)
{ {
if (FcStrSetPtrU(ls->extra)) if (ls->extra)
FcStrSetDestroy (FcStrSetPtrU(ls->extra)); FcStrSetDestroy (ls->extra);
FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet)); FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet));
free (ls); free (ls);
} }
@ -246,21 +237,21 @@ FcLangSetCopy (const FcLangSet *ls)
if (!new) if (!new)
goto bail0; goto bail0;
memcpy (new->map, ls->map, sizeof (new->map)); memcpy (new->map, ls->map, sizeof (new->map));
if (FcStrSetPtrU(ls->extra)) if (ls->extra)
{ {
FcStrList *list; FcStrList *list;
FcChar8 *extra; FcChar8 *extra;
new->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ()); new->extra = FcStrSetCreate ();
if (!FcStrSetPtrU(new->extra)) if (!new->extra)
goto bail1; goto bail1;
list = FcStrListCreate (FcStrSetPtrU(ls->extra)); list = FcStrListCreate (ls->extra);
if (!list) if (!list)
goto bail1; goto bail1;
while ((extra = FcStrListNext (list))) while ((extra = FcStrListNext (list)))
if (!FcStrSetAdd (FcStrSetPtrU(new->extra), extra)) if (!FcStrSetAdd (new->extra, extra))
{ {
FcStrListDone (list); FcStrListDone (list);
goto bail1; goto bail1;
@ -341,13 +332,13 @@ FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
FcLangSetBitSet (ls, id); FcLangSetBitSet (ls, id);
return FcTrue; return FcTrue;
} }
if (!FcStrSetPtrU(ls->extra)) if (!ls->extra)
{ {
ls->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ()); ls->extra = FcStrSetCreate ();
if (!FcStrSetPtrU(ls->extra)) if (!ls->extra)
return FcFalse; return FcFalse;
} }
return FcStrSetAdd (FcStrSetPtrU(ls->extra), lang); return FcStrSetAdd (ls->extra, lang);
} }
FcLangResult FcLangResult
@ -379,9 +370,9 @@ FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
if (FcLangSetBitGet (ls, i) && r < best) if (FcLangSetBitGet (ls, i) && r < best)
best = r; best = r;
} }
if (FcStrSetPtrU(ls->extra)) if (ls->extra)
{ {
FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra)); FcStrList *list = FcStrListCreate (ls->extra);
FcChar8 *extra; FcChar8 *extra;
FcLangResult r; FcLangResult r;
@ -437,15 +428,15 @@ FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
best = FcLangDifferentCountry; best = FcLangDifferentCountry;
break; break;
} }
if (FcStrSetPtrU(lsa->extra)) if (lsa->extra)
{ {
r = FcLangSetCompareStrSet (lsb, FcStrSetPtrU(lsa->extra)); r = FcLangSetCompareStrSet (lsb, lsa->extra);
if (r < best) if (r < best)
best = r; best = r;
} }
if (best > FcLangEqual && FcStrSetPtrU(lsb->extra)) if (best > FcLangEqual && lsb->extra)
{ {
r = FcLangSetCompareStrSet (lsa, FcStrSetPtrU(lsb->extra)); r = FcLangSetCompareStrSet (lsa, lsb->extra);
if (r < best) if (r < best)
best = r; best = r;
} }
@ -464,7 +455,7 @@ FcLangSetPromote (const FcChar8 *lang)
int id; int id;
memset (ls.map, '\0', sizeof (ls.map)); memset (ls.map, '\0', sizeof (ls.map));
ls.extra = FcStrSetPtrCreateDynamic(0); ls.extra = 0;
id = FcLangSetIndex (lang); id = FcLangSetIndex (lang);
if (id > 0) if (id > 0)
{ {
@ -472,11 +463,10 @@ FcLangSetPromote (const FcChar8 *lang)
} }
else else
{ {
ls.extra = FcStrSetPtrCreateDynamic(&strs); ls.extra = &strs;
strs.num = 1; strs.num = 1;
strs.size = 1; strs.size = 1;
strs.storage = FcStorageDynamic; strs.strs = &str;
strs.u.strs = &str;
strs.ref = 1; strs.ref = 1;
str = (FcChar8 *) lang; str = (FcChar8 *) lang;
} }
@ -491,8 +481,8 @@ FcLangSetHash (const FcLangSet *ls)
for (i = 0; i < NUM_LANG_SET_MAP; i++) for (i = 0; i < NUM_LANG_SET_MAP; i++)
h ^= ls->map[i]; h ^= ls->map[i];
if (FcStrSetPtrU(ls->extra)) if (ls->extra)
h ^= FcStrSetPtrU(ls->extra)->num; h ^= ls->extra->num;
return h; return h;
} }
@ -553,9 +543,9 @@ FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
} }
} }
} }
if (FcStrSetPtrU(ls->extra)) if (ls->extra)
{ {
FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra)); FcStrList *list = FcStrListCreate (ls->extra);
FcChar8 *extra; FcChar8 *extra;
if (!list) if (!list)
@ -583,10 +573,10 @@ FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
if (lsa->map[i] != lsb->map[i]) if (lsa->map[i] != lsb->map[i])
return FcFalse; return FcFalse;
} }
if (!FcStrSetPtrU(lsa->extra) && !FcStrSetPtrU(lsb->extra)) if (!lsa->extra && !lsb->extra)
return FcTrue; return FcTrue;
if (FcStrSetPtrU(lsa->extra) && FcStrSetPtrU(lsb->extra)) if (lsa->extra && lsb->extra)
return FcStrSetEqual (FcStrSetPtrU(lsa->extra), FcStrSetPtrU(lsb->extra)); return FcStrSetEqual (lsa->extra, lsb->extra);
return FcFalse; return FcFalse;
} }
@ -620,9 +610,9 @@ FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
FcLangContains (fcLangCharSets[i].lang, lang)) FcLangContains (fcLangCharSets[i].lang, lang))
return FcTrue; return FcTrue;
} }
if (FcStrSetPtrU(ls->extra)) if (ls->extra)
{ {
FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra)); FcStrList *list = FcStrListCreate (ls->extra);
FcChar8 *extra; FcChar8 *extra;
if (list) if (list)
@ -676,9 +666,9 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
} }
} }
} }
if (FcStrSetPtrU(lsb->extra)) if (lsb->extra)
{ {
FcStrList *list = FcStrListCreate (FcStrSetPtrU(lsb->extra)); FcStrList *list = FcStrListCreate (lsb->extra);
FcChar8 *extra; FcChar8 *extra;
if (list) if (list)
@ -700,105 +690,82 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
return FcTrue; return FcTrue;
} }
static FcLangSet * langsets = 0; static FcLangSet ** langsets = 0;
static int langset_ptr = 0, langset_count = 0; static int langset_bank_count = 0, langset_ptr = 0, langset_count = 0;
FcLangSet *
FcLangSetPtrU (FcLangSetPtr li)
{
switch (li.storage)
{
case FcStorageDynamic:
return li.u.dyn;
case FcStorageStatic:
return &langsets[li.u.stat];
default:
return 0;
}
}
FcLangSetPtr
FcLangSetPtrCreateDynamic (FcLangSet *li)
{
FcLangSetPtr new;
new.storage = FcStorageDynamic;
new.u.dyn = li;
return new;
}
void void
FcLangSetClearStatic (void) FcLangSetNewBank (void)
{ {
FcStrSetClearStatic();
langset_ptr = 0;
langset_count = 0; langset_count = 0;
} }
/* should only write one copy of any particular FcLangSet */ /* ideally, should only write one copy of any particular FcLangSet */
FcBool int
FcLangSetPrepareSerialize (FcLangSet *l) FcLangSetNeededBytes (const FcLangSet *l)
{ {
langset_count++; langset_count++;
if (l && FcStrSetPtrU(l->extra)) return sizeof (FcLangSet);
return FcStrSetPrepareSerialize (FcStrSetPtrU(l->extra)); }
static FcBool
FcLangSetEnsureBank (int bi)
{
if (!langsets || bi >= langset_bank_count)
{
int new_count = langset_bank_count + 2;
int i;
FcLangSet** tt;
tt = realloc(langsets, new_count * sizeof(FcLangSet *));
if (!tt)
return FcFalse;
langsets = tt;
for (i = langset_bank_count; i < new_count; i++)
langsets[i] = 0;
langset_bank_count = new_count;
}
return FcTrue; return FcTrue;
} }
FcLangSetPtr void *
FcLangSetSerialize(FcLangSet *l) FcLangSetDistributeBytes (FcCache * metadata, void * block_ptr)
{ {
FcLangSetPtr new; int bi = FcCacheBankToIndex(metadata->bank);
int p = langset_ptr; if (!FcLangSetEnsureBank(bi))
return 0;
if (!l) return FcLangSetPtrCreateDynamic(0); langsets[bi] = block_ptr;
block_ptr = (void *)((char *)block_ptr +
langset_count * sizeof(FcLangSet));
langset_ptr = 0;
metadata->langset_count = langset_count;
return block_ptr;
}
if (!langsets) FcLangSet *
{ FcLangSetSerialize(int bank, FcLangSet *l)
FcLangSet* t; {
t = (FcLangSet *)malloc(langset_count * sizeof(FcLangSet)); int p = langset_ptr, bi = FcCacheBankToIndex(bank);
if (!t)
return FcLangSetPtrCreateDynamic(0);
langsets = t;
langset_ptr = 0;
}
langsets[langset_ptr] = *l; if (!l) return 0;
if (FcStrSetPtrU(l->extra))
langsets[langset_ptr].extra = langsets[bi][langset_ptr] = *l;
FcStrSetSerialize(FcStrSetPtrU(l->extra)); langsets[bi][langset_ptr].extra = 0;
else
langsets[langset_ptr].extra = FcStrSetPtrCreateDynamic(0);
langset_ptr++; langset_ptr++;
new.storage = FcStorageStatic; return &langsets[bi][p];
new.u.stat = p;
return new;
} }
FcBool void *
FcLangSetWrite (int fd, FcCache *metadata) FcLangSetUnserialize (FcCache metadata, void *block_ptr)
{ {
metadata->langsets_length = langset_ptr; int bi = FcCacheBankToIndex(metadata.bank);
metadata->langsets_offset = FcCacheNextOffset(fd); if (!FcLangSetEnsureBank(bi))
return 0;
if (langset_ptr > 0) FcMemAlloc (FC_MEM_LANGSET, metadata.langset_count * sizeof(FcLangSet));
{ langsets[bi] = (FcLangSet *)block_ptr;
lseek (fd, metadata->langsets_offset, SEEK_SET); block_ptr = (void *)((char *)block_ptr +
return write(fd, langsets, metadata.langset_count * sizeof(FcLangSet));
metadata->langsets_length * sizeof(FcLangSet)) != -1; return block_ptr;
}
return FcTrue;
}
FcBool
FcLangSetRead (int fd, FcCache metadata)
{
langsets = mmap(NULL,
metadata.langsets_length * sizeof (FcLangSet),
PROT_READ,
MAP_SHARED, fd, metadata.langsets_offset);
if (langsets == MAP_FAILED)
return FcFalse;
langset_count = langset_ptr = metadata.langsets_length;
return FcTrue;
} }

View File

@ -23,9 +23,6 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include "fcint.h" #include "fcint.h"
FcObjectSet * FcObjectSet *
@ -47,18 +44,17 @@ FcBool
FcObjectSetAdd (FcObjectSet *os, const char *object) FcObjectSetAdd (FcObjectSet *os, const char *object)
{ {
int s; int s;
FcObjectPtr *objects; const char **objects;
FcObjectPtr obj;
int high, low, mid, c; int high, low, mid, c;
if (os->nobject == os->sobject) if (os->nobject == os->sobject)
{ {
s = os->sobject + 4; s = os->sobject + 4;
if (os->objects) if (os->objects)
objects = (FcObjectPtr *) realloc ((void *) os->objects, objects = (const char **) realloc ((void *) os->objects,
s * sizeof (FcObjectPtr)); s * sizeof (const char *));
else else
objects = (FcObjectPtr *) malloc (s * sizeof (FcObjectPtr)); objects = (const char **) malloc (s * sizeof (const char *));
if (!objects) if (!objects)
return FcFalse; return FcFalse;
if (os->sobject) if (os->sobject)
@ -71,11 +67,11 @@ FcObjectSetAdd (FcObjectSet *os, const char *object)
low = 0; low = 0;
mid = 0; mid = 0;
c = 1; c = 1;
obj = FcObjectStaticName (object); object = FcObjectStaticName (object);
while (low <= high) while (low <= high)
{ {
mid = (low + high) >> 1; mid = (low + high) >> 1;
c = FcObjectPtrCompare(os->objects[mid], obj); c = os->objects[mid] - object;
if (c == 0) if (c == 0)
return FcTrue; return FcTrue;
if (c < 0) if (c < 0)
@ -86,8 +82,8 @@ FcObjectSetAdd (FcObjectSet *os, const char *object)
if (c < 0) if (c < 0)
mid++; mid++;
memmove (os->objects + mid + 1, os->objects + mid, memmove (os->objects + mid + 1, os->objects + mid,
(os->nobject - mid) * sizeof (FcObjectPtr)); (os->nobject - mid) * sizeof (const char *));
os->objects[mid] = obj; os->objects[mid] = object;
os->nobject++; os->nobject++;
return FcTrue; return FcTrue;
} }
@ -145,9 +141,9 @@ FcListValueListMatchAny (FcValueListPtr patOrig, /* pattern */
* (OpListing is OpContains except for strings * (OpListing is OpContains except for strings
* where it requires an exact match) * where it requires an exact match)
*/ */
if (FcConfigCompareValue (FcValueListPtrU(fnt)->value, if (FcConfigCompareValue (&FcValueListPtrU(fnt)->value,
FcOpListing, FcOpListing,
FcValueListPtrU(pat)->value)) &FcValueListPtrU(pat)->value))
break; break;
} }
if (!FcValueListPtrU(fnt)) if (!FcValueListPtrU(fnt))
@ -167,8 +163,8 @@ FcListValueListEqual (FcValueListPtr v1orig,
{ {
for (v2 = v2orig; FcValueListPtrU(v2); for (v2 = v2orig; FcValueListPtrU(v2);
v2 = FcValueListPtrU(v2)->next) v2 = FcValueListPtrU(v2)->next)
if (FcValueEqual (FcValueListPtrU(v1)->value, if (FcValueEqual (FcValueCanonicalize(&FcValueListPtrU(v1)->value),
FcValueListPtrU(v2)->value)) FcValueCanonicalize(&FcValueListPtrU(v2)->value)))
break; break;
if (!FcValueListPtrU(v2)) if (!FcValueListPtrU(v2))
return FcFalse; return FcFalse;
@ -178,8 +174,8 @@ FcListValueListEqual (FcValueListPtr v1orig,
{ {
for (v1 = v1orig; FcValueListPtrU(v1); for (v1 = v1orig; FcValueListPtrU(v1);
v1 = FcValueListPtrU(v1)->next) v1 = FcValueListPtrU(v1)->next)
if (FcValueEqual (FcValueListPtrU(v1)->value, if (FcValueEqual (FcValueCanonicalize(&FcValueListPtrU(v1)->value),
FcValueListPtrU(v2)->value)) FcValueCanonicalize(&FcValueListPtrU(v2)->value)))
break; break;
if (!FcValueListPtrU(v1)) if (!FcValueListPtrU(v1))
return FcFalse; return FcFalse;
@ -197,8 +193,8 @@ FcListPatternEqual (FcPattern *p1,
for (i = 0; i < os->nobject; i++) for (i = 0; i < os->nobject; i++)
{ {
e1 = FcPatternFindElt (p1, FcObjectPtrU(os->objects[i])); e1 = FcPatternFindElt (p1, os->objects[i]);
e2 = FcPatternFindElt (p2, FcObjectPtrU(os->objects[i])); e2 = FcPatternFindElt (p2, os->objects[i]);
if (!e1 && !e2) if (!e1 && !e2)
continue; continue;
if (!e1 || !e2) if (!e1 || !e2)
@ -245,8 +241,9 @@ FcListMatrixHash (const FcMatrix *m)
} }
static FcChar32 static FcChar32
FcListValueHash (FcValue v) FcListValueHash (FcValue *value)
{ {
FcValue v = FcValueCanonicalize(value);
switch (v.type) { switch (v.type) {
case FcTypeVoid: case FcTypeVoid:
return 0; return 0;
@ -255,17 +252,17 @@ FcListValueHash (FcValue v)
case FcTypeDouble: case FcTypeDouble:
return (FcChar32) (int) v.u.d; return (FcChar32) (int) v.u.d;
case FcTypeString: case FcTypeString:
return FcStrHashIgnoreCase (FcObjectPtrU(v.u.si)); return FcStrHashIgnoreCase (v.u.s);
case FcTypeBool: case FcTypeBool:
return (FcChar32) v.u.b; return (FcChar32) v.u.b;
case FcTypeMatrix: case FcTypeMatrix:
return FcListMatrixHash (FcMatrixPtrU(v.u.mi)); return FcListMatrixHash (v.u.m);
case FcTypeCharSet: case FcTypeCharSet:
return FcCharSetCount (FcCharSetPtrU(v.u.ci)); return FcCharSetCount (v.u.c);
case FcTypeFTFace: case FcTypeFTFace:
return (long) v.u.f; return (long) v.u.f;
case FcTypeLangSet: case FcTypeLangSet:
return FcLangSetHash (FcLangSetPtrU(v.u.li)); return FcLangSetHash (v.u.l);
} }
return 0; return 0;
} }
@ -277,7 +274,7 @@ FcListValueListHash (FcValueListPtr list)
while (FcValueListPtrU(list)) while (FcValueListPtrU(list))
{ {
h = h ^ FcListValueHash (FcValueListPtrU(list)->value); h = h ^ FcListValueHash (&FcValueListPtrU(list)->value);
list = FcValueListPtrU(list)->next; list = FcValueListPtrU(list)->next;
} }
return h; return h;
@ -293,7 +290,7 @@ FcListPatternHash (FcPattern *font,
for (n = 0; n < os->nobject; n++) for (n = 0; n < os->nobject; n++)
{ {
e = FcPatternFindElt (font, FcObjectPtrU(os->objects[n])); e = FcPatternFindElt (font, os->objects[n]);
if (e) if (e)
h = h ^ FcListValueListHash (e->values); h = h ^ FcListValueListHash (e->values);
} }
@ -371,15 +368,15 @@ FcListAppend (FcListHashTable *table,
for (o = 0; o < os->nobject; o++) for (o = 0; o < os->nobject; o++)
{ {
e = FcPatternFindElt (font, FcObjectPtrU(os->objects[o])); e = FcPatternFindElt (font, os->objects[o]);
if (e) if (e)
{ {
for (v = e->values; FcValueListPtrU(v); for (v = e->values; FcValueListPtrU(v);
v = FcValueListPtrU(v)->next) v = FcValueListPtrU(v)->next)
{ {
if (!FcPatternAdd (bucket->pattern, if (!FcPatternAdd (bucket->pattern,
FcObjectPtrU(os->objects[o]), os->objects[o],
FcValueListPtrU(v)->value, FcTrue)) FcValueCanonicalize(&FcValueListPtrU(v)->value), FcTrue))
goto bail2; goto bail2;
} }
} }

View File

@ -28,26 +28,26 @@
#include <stdio.h> #include <stdio.h>
static double static double
FcCompareNumber (char *object, FcValue value1, FcValue value2) FcCompareNumber (char *object, FcValue *value1, FcValue *value2)
{ {
double v1, v2, v; double v1, v2, v;
switch (value1.type) { switch (value1->type) {
case FcTypeInteger: case FcTypeInteger:
v1 = (double) value1.u.i; v1 = (double) value1->u.i;
break; break;
case FcTypeDouble: case FcTypeDouble:
v1 = value1.u.d; v1 = value1->u.d;
break; break;
default: default:
return -1.0; return -1.0;
} }
switch (value2.type) { switch (value2->type) {
case FcTypeInteger: case FcTypeInteger:
v2 = (double) value2.u.i; v2 = (double) value2->u.i;
break; break;
case FcTypeDouble: case FcTypeDouble:
v2 = value2.u.d; v2 = value2->u.d;
break; break;
default: default:
return -1.0; return -1.0;
@ -59,38 +59,38 @@ FcCompareNumber (char *object, FcValue value1, FcValue value2)
} }
static double static double
FcCompareString (char *object, FcValue value1, FcValue value2) FcCompareString (char *object, FcValue *v1, FcValue *v2)
{ {
FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
if (value2.type != FcTypeString || value1.type != FcTypeString) if (value2.type != FcTypeString || value1.type != FcTypeString)
return -1.0; return -1.0;
return (double) FcStrCmpIgnoreCase return (double) FcStrCmpIgnoreCase (value1.u.s, value2.u.s) != 0;
(FcObjectPtrU(value1.u.si), FcObjectPtrU(value2.u.si)) != 0;
} }
static double static double
FcCompareFamily (char *object, FcValue value1, FcValue value2) FcCompareFamily (char *object, FcValue *v1, FcValue *v2)
{ {
FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
if (value2.type != FcTypeString || value1.type != FcTypeString) if (value2.type != FcTypeString || value1.type != FcTypeString)
return -1.0; return -1.0;
return (double) FcStrCmpIgnoreBlanksAndCase return (double) FcStrCmpIgnoreBlanksAndCase (value1.u.s, value2.u.s) != 0;
(FcObjectPtrU(value1.u.si), FcObjectPtrU(value2.u.si)) != 0;
} }
static double static double
FcCompareLang (char *object, FcValue value1, FcValue value2) FcCompareLang (char *object, FcValue *v1, FcValue *v2)
{ {
FcLangResult result; FcLangResult result;
FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
switch (value1.type) { switch (value1.type) {
case FcTypeLangSet: case FcTypeLangSet:
switch (value2.type) { switch (value2.type) {
case FcTypeLangSet: case FcTypeLangSet:
result = FcLangSetCompare (FcLangSetPtrU(value1.u.li), result = FcLangSetCompare (value1.u.l, value2.u.l);
FcLangSetPtrU(value2.u.li));
break; break;
case FcTypeString: case FcTypeString:
result = FcLangSetHasLang (FcLangSetPtrU(value1.u.li), result = FcLangSetHasLang (value1.u.l,
FcObjectPtrU(value2.u.si)); value2.u.s);
break; break;
default: default:
return -1.0; return -1.0;
@ -99,12 +99,11 @@ FcCompareLang (char *object, FcValue value1, FcValue value2)
case FcTypeString: case FcTypeString:
switch (value2.type) { switch (value2.type) {
case FcTypeLangSet: case FcTypeLangSet:
result = FcLangSetHasLang (FcLangSetPtrU(value2.u.li), result = FcLangSetHasLang (value2.u.l, value1.u.s);
FcObjectPtrU(value1.u.si));
break; break;
case FcTypeString: case FcTypeString:
result = FcLangCompare (FcObjectPtrU(value1.u.si), result = FcLangCompare (value1.u.s,
FcObjectPtrU(value2.u.si)); value2.u.s);
break; break;
default: default:
return -1.0; return -1.0;
@ -125,43 +124,44 @@ FcCompareLang (char *object, FcValue value1, FcValue value2)
} }
static double static double
FcCompareBool (char *object, FcValue value1, FcValue value2) FcCompareBool (char *object, FcValue *value1, FcValue *value2)
{ {
if (value2.type != FcTypeBool || value1.type != FcTypeBool) if (value2->type != FcTypeBool || value1->type != FcTypeBool)
return -1.0; return -1.0;
return (double) value2.u.b != value1.u.b; return (double) value2->u.b != value1->u.b;
} }
static double static double
FcCompareCharSet (char *object, FcValue value1, FcValue value2) FcCompareCharSet (char *object, FcValue *v1, FcValue *v2)
{ {
FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet) if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet)
return -1.0; return -1.0;
return (double) FcCharSetSubtractCount (FcCharSetPtrU(value1.u.ci), return (double) FcCharSetSubtractCount (value1.u.c, value2.u.c);
FcCharSetPtrU(value2.u.ci));
} }
static double static double
FcCompareSize (char *object, FcValue value1, FcValue value2) FcCompareSize (char *object, FcValue *value1, FcValue *value2)
{ {
double v1, v2, v; double v1, v2, v;
switch (value1.type) { switch (value1->type) {
case FcTypeInteger: case FcTypeInteger:
v1 = value1.u.i; v1 = value1->u.i;
break; break;
case FcTypeDouble: case FcTypeDouble:
v1 = value1.u.d; v1 = value1->u.d;
break; break;
default: default:
return -1; return -1;
} }
switch (value2.type) { switch (value2->type) {
case FcTypeInteger: case FcTypeInteger:
v2 = value2.u.i; v2 = value2->u.i;
break; break;
case FcTypeDouble: case FcTypeDouble:
v2 = value2.u.d; v2 = value2->u.d;
break; break;
default: default:
return -1; return -1;
@ -176,7 +176,7 @@ FcCompareSize (char *object, FcValue value1, FcValue value2)
typedef struct _FcMatcher { typedef struct _FcMatcher {
char *object; char *object;
double (*compare) (char *object, FcValue value1, FcValue value2); double (*compare) (char *object, FcValue *value1, FcValue *value2);
int strong, weak; int strong, weak;
} FcMatcher; } FcMatcher;
@ -315,7 +315,7 @@ FcCompareValueList (const char *object,
(FcChar8 *) object) != 0) (FcChar8 *) object) != 0)
{ {
if (bestValue) if (bestValue)
*bestValue = FcValueListPtrU(v2orig)->value; *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2orig)->value);
return FcTrue; return FcTrue;
} }
#if 0 #if 0
@ -343,8 +343,8 @@ FcCompareValueList (const char *object,
v2 = FcValueListPtrU(v2)->next) v2 = FcValueListPtrU(v2)->next)
{ {
v = (*_FcMatchers[i].compare) (_FcMatchers[i].object, v = (*_FcMatchers[i].compare) (_FcMatchers[i].object,
FcValueListPtrU(v1)->value, &FcValueListPtrU(v1)->value,
FcValueListPtrU(v2)->value); &FcValueListPtrU(v2)->value);
if (v < 0) if (v < 0)
{ {
*result = FcResultTypeMismatch; *result = FcResultTypeMismatch;
@ -356,7 +356,7 @@ FcCompareValueList (const char *object,
if (v < best) if (v < best)
{ {
if (bestValue) if (bestValue)
*bestValue = FcValueListPtrU(v2)->value; *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2)->value);
best = v; best = v;
} }
if (FcValueListPtrU(v1)->binding == FcValueBindingStrong) if (FcValueListPtrU(v1)->binding == FcValueBindingStrong)
@ -478,7 +478,7 @@ FcFontRenderPrepare (FcConfig *config,
} }
} }
else else
v = FcValueListPtrU(fe->values)->value; v = FcValueCanonicalize(&FcValueListPtrU(fe->values)->value);
FcPatternAdd (new, FcObjectPtrU(fe->object), v, FcFalse); FcPatternAdd (new, FcObjectPtrU(fe->object), v, FcFalse);
} }
for (i = 0; i < pat->num; i++) for (i = 0; i < pat->num; i++)
@ -487,7 +487,7 @@ FcFontRenderPrepare (FcConfig *config,
fe = FcPatternFindElt (font, FcObjectPtrU(pe->object)); fe = FcPatternFindElt (font, FcObjectPtrU(pe->object));
if (!fe) if (!fe)
FcPatternAdd (new, FcObjectPtrU(pe->object), FcPatternAdd (new, FcObjectPtrU(pe->object),
FcValueListPtrU(pe->values)->value, FcTrue); FcValueCanonicalize(&FcValueListPtrU(pe->values)->value), FcTrue);
} }
FcConfigSubstituteWithPat (config, new, pat, FcMatchFont); FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
return new; return new;
@ -780,8 +780,8 @@ FcFontSetSort (FcConfig *config,
FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch && FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch &&
FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == FcResultMatch) FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == FcResultMatch)
{ {
double compare = FcCompareLang (FC_LANG, patternLang, double compare = FcCompareLang (FC_LANG, &patternLang,
nodeLang); &nodeLang);
if (compare >= 0 && compare < 2) if (compare >= 0 && compare < 2)
{ {
if (FcDebug () & FC_DBG_MATCHV) if (FcDebug () & FC_DBG_MATCHV)

View File

@ -25,14 +25,9 @@
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <sys/mman.h>
#include "fcint.h" #include "fcint.h"
FcMatrix _id = { 1, 0, 0, 1 }; const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 };
const FcMatrixPtr FcIdentityMatrix = {
.storage = FcStorageDynamic,
.u.dyn = &_id
};
FcMatrix * FcMatrix *
FcMatrixCopy (const FcMatrix *mat) FcMatrixCopy (const FcMatrix *mat)
@ -48,17 +43,10 @@ FcMatrixCopy (const FcMatrix *mat)
return r; return r;
} }
void
FcMatrixPtrDestroy (FcMatrixPtr mi)
{
if (mi.storage == FcStorageDynamic)
FcMatrixFree (mi.u.dyn);
}
void void
FcMatrixFree (FcMatrix *mat) FcMatrixFree (FcMatrix *mat)
{ {
if (mat != FcMatrixPtrU(FcIdentityMatrix)) if (mat != &FcIdentityMatrix)
{ {
FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix)); FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix));
free (mat); free (mat);
@ -127,87 +115,3 @@ FcMatrixShear (FcMatrix *m, double sh, double sv)
r.yy = 1; r.yy = 1;
FcMatrixMultiply (m, &r, m); FcMatrixMultiply (m, &r, m);
} }
static FcMatrix * matrices = 0;
static int matrix_ptr = 0, matrix_count = 0;
void
FcMatrixClearStatic (void)
{
matrices = 0;
matrix_ptr = 0;
matrix_count = 0;
}
FcMatrix *
FcMatrixPtrU (FcMatrixPtr mi)
{
switch (mi.storage)
{
case FcStorageDynamic:
return mi.u.dyn;
case FcStorageStatic:
return &matrices[mi.u.stat];
default:
return 0;
}
}
FcMatrixPtr
FcMatrixPtrCreateDynamic (FcMatrix *mi)
{
FcMatrixPtr new;
new.storage = FcStorageDynamic;
new.u.dyn = mi;
return new;
}
FcBool
FcMatrixPrepareSerialize(FcMatrix *m)
{
matrix_count++;
return FcTrue;
}
FcMatrixPtr
FcMatrixSerialize(FcMatrix *m)
{
FcMatrixPtr new;
if (matrix_count == matrix_ptr)
return FcMatrixPtrCreateDynamic(0);
new.storage = FcStorageStatic;
new.u.stat = matrix_ptr++;
return new;
}
FcBool
FcMatrixRead (int fd, FcCache metadata)
{
matrices = mmap(NULL,
metadata.matrices_length * sizeof (FcMatrix),
PROT_READ,
MAP_SHARED, fd, metadata.matrices_offset);
if (matrices == MAP_FAILED)
return FcFalse;
matrix_count = matrix_ptr = metadata.matrices_length;
return FcTrue;
}
FcBool
FcMatrixWrite (int fd, FcCache *metadata)
{
metadata->matrices_length = matrix_ptr;
metadata->matrices_offset = FcCacheNextOffset(fd);
if (matrix_ptr > 0)
{
lseek(fd, metadata->matrices_offset, SEEK_SET);
return write(fd, matrices,
metadata->matrices_length * sizeof(FcMatrix)) != -1;
}
return FcTrue;
}

View File

@ -145,6 +145,74 @@ FcNameGetObjectType (const char *object)
return 0; return 0;
} }
static int objectptr_count = 1;
static int objectptr_alloc = 0;
static int * objectptr_indices = 0;
void
FcObjectNewBank(void)
{
objectptr_count = 1;
objectptr_alloc = 0;
objectptr_indices = 0;
}
// XXX todo: introduce a hashtable for faster lookup
FcObjectPtr
FcObjectToPtr (const char * object)
{
int i;
const FcObjectTypeList *l;
const FcObjectType *t;
for (l = _FcObjectTypes; l; l = l->next)
{
for (i = 0; i < l->ntypes; i++)
{
t = &l->types[i];
if (!strcmp (object, t->object))
return i;
}
}
abort();
return 0;
}
const char *
FcObjectPtrU (FcObjectPtr si)
{
return _FcObjectTypes->types[si].object;
}
int
FcObjectNeededBytes (FcObjectPtr si)
{
return 0;
}
void *
FcObjectDistributeBytes (FcCache * metadata, void * block_ptr)
{
return block_ptr;
}
FcObjectPtr
FcObjectSerialize (FcObjectPtr si)
{
return si;
}
void
FcObjectUnserialize (FcCache metadata, FcConfig * config, void *block_ptr)
{
}
int
FcObjectPtrCompare (const FcObjectPtr a, const FcObjectPtr b)
{
return a - b;
}
static const FcConstant _FcBaseConstants[] = { static const FcConstant _FcBaseConstants[] = {
{ (FcChar8 *) "thin", "weight", FC_WEIGHT_THIN, }, { (FcChar8 *) "thin", "weight", FC_WEIGHT_THIN, },
{ (FcChar8 *) "extralight", "weight", FC_WEIGHT_EXTRALIGHT, }, { (FcChar8 *) "extralight", "weight", FC_WEIGHT_EXTRALIGHT, },
@ -321,7 +389,7 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
v.u.i = atoi ((char *) string); v.u.i = atoi ((char *) string);
break; break;
case FcTypeString: case FcTypeString:
v.u.si = FcObjectStaticName(string); v.u.s = FcObjectStaticName(string);
break; break;
case FcTypeBool: case FcTypeBool:
if (!FcNameBool (string, &v.u.b)) if (!FcNameBool (string, &v.u.b))
@ -331,14 +399,14 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
v.u.d = strtod ((char *) string, 0); v.u.d = strtod ((char *) string, 0);
break; break;
case FcTypeMatrix: case FcTypeMatrix:
v.u.mi = FcMatrixPtrCreateDynamic(m); v.u.m = m;
sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy); sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
break; break;
case FcTypeCharSet: case FcTypeCharSet:
v.u.ci = FcCharSetPtrCreateDynamic(FcNameParseCharSet (string)); v.u.c = FcNameParseCharSet (string);
break; break;
case FcTypeLangSet: case FcTypeLangSet:
v.u.li = FcLangSetPtrCreateDynamic(FcNameParseLangSet (string)); v.u.l = FcNameParseLangSet (string);
break; break;
default: default:
break; break;
@ -436,10 +504,10 @@ FcNameParse (const FcChar8 *name)
{ {
switch (v.type) { switch (v.type) {
case FcTypeCharSet: case FcTypeCharSet:
FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci)); FcCharSetDestroy ((FcCharSet *) v.u.c);
break; break;
case FcTypeLangSet: case FcTypeLangSet:
FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li)); FcLangSetDestroy ((FcLangSet *) v.u.l);
break; break;
default: default:
break; break;
@ -448,10 +516,10 @@ FcNameParse (const FcChar8 *name)
} }
switch (v.type) { switch (v.type) {
case FcTypeCharSet: case FcTypeCharSet:
FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci)); FcCharSetDestroy ((FcCharSet *) v.u.c);
break; break;
case FcTypeLangSet: case FcTypeLangSet:
FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li)); FcLangSetDestroy ((FcLangSet *) v.u.l);
break; break;
default: default:
break; break;
@ -503,10 +571,12 @@ FcNameUnparseString (FcStrBuf *buf,
static FcBool static FcBool
FcNameUnparseValue (FcStrBuf *buf, FcNameUnparseValue (FcStrBuf *buf,
FcValue v, int bank,
FcValue *v0,
FcChar8 *escape) FcChar8 *escape)
{ {
FcChar8 temp[1024]; FcChar8 temp[1024];
FcValue v = FcValueCanonicalize(v0);
switch (v.type) { switch (v.type) {
case FcTypeVoid: case FcTypeVoid:
@ -518,20 +588,17 @@ FcNameUnparseValue (FcStrBuf *buf,
sprintf ((char *) temp, "%g", v.u.d); sprintf ((char *) temp, "%g", v.u.d);
return FcNameUnparseString (buf, temp, 0); return FcNameUnparseString (buf, temp, 0);
case FcTypeString: case FcTypeString:
return FcNameUnparseString (buf, FcObjectPtrU(v.u.si), escape); return FcNameUnparseString (buf, v.u.s, escape);
case FcTypeBool: case FcTypeBool:
return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0); return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
case FcTypeMatrix: case FcTypeMatrix:
{
FcMatrix * m = FcMatrixPtrU(v.u.mi);
sprintf ((char *) temp, "%g %g %g %g", sprintf ((char *) temp, "%g %g %g %g",
m->xx, m->xy, m->yx, m->yy); v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
return FcNameUnparseString (buf, temp, 0); return FcNameUnparseString (buf, temp, 0);
}
case FcTypeCharSet: case FcTypeCharSet:
return FcNameUnparseCharSet (buf, FcCharSetPtrU(v.u.ci)); return FcNameUnparseCharSet (buf, v.u.c);
case FcTypeLangSet: case FcTypeLangSet:
return FcNameUnparseLangSet (buf, FcLangSetPtrU(v.u.li)); return FcNameUnparseLangSet (buf, v.u.l);
case FcTypeFTFace: case FcTypeFTFace:
return FcTrue; return FcTrue;
} }
@ -545,7 +612,7 @@ FcNameUnparseValueList (FcStrBuf *buf,
{ {
while (FcValueListPtrU(v)) while (FcValueListPtrU(v))
{ {
if (!FcNameUnparseValue (buf, FcValueListPtrU(v)->value, escape)) if (!FcNameUnparseValue (buf, v.bank, &FcValueListPtrU(v)->value, escape))
return FcFalse; return FcFalse;
if (FcValueListPtrU(v = FcValueListPtrU(v)->next)) if (FcValueListPtrU(v = FcValueListPtrU(v)->next))
if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0)) if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <sys/mman.h>
#include "fcint.h" #include "fcint.h"
FcChar8 * FcChar8 *
@ -849,67 +848,10 @@ FcStrSetCreate (void)
set->ref = 1; set->ref = 1;
set->num = 0; set->num = 0;
set->size = 0; set->size = 0;
set->storage = FcStorageDynamic; set->strs = 0;
set->u.strs = 0;
return set; return set;
} }
static FcChar8 * strset_buf = 0;
static int strset_buf_ptr = 0, strset_buf_count = 0;
static int * strset_idx = 0;
static int strset_idx_ptr = 0, strset_idx_count = 0;
static FcStrSet * strsets = 0;
static int strset_ptr = 0, strset_count = 0;
void FcStrSetClearStatic()
{
strset_buf = 0; strset_buf_ptr = 0; strset_buf_count = 0;
strset_idx = 0; strset_idx_ptr = 0; strset_idx_count = 0;
strsets = 0; strset_ptr = 0; strset_count = 0;
}
FcChar8 *
FcStrSetGet (const FcStrSet *set, int i)
{
int index;
switch (set->storage)
{
case FcStorageStatic:
index = strset_idx[set->u.stridx_offset];
if (index == -1)
return 0;
return &strset_buf[index];
case FcStorageDynamic:
return set->u.strs[i];
default:
return 0;
}
}
FcStrSet *
FcStrSetPtrU (const FcStrSetPtr set)
{
switch (set.storage)
{
case FcStorageStatic:
return &strsets[set.u.stat];
case FcStorageDynamic:
return (FcStrSet *)set.u.dyn;
default:
return 0;
}
}
FcStrSetPtr
FcStrSetPtrCreateDynamic (const FcStrSet * set)
{
FcStrSetPtr new;
new.storage = FcStorageDynamic;
new.u.dyn = (FcStrSet *)set;
return new;
}
static FcBool static FcBool
_FcStrSetAppend (FcStrSet *set, FcChar8 *s) _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
{ {
@ -918,7 +860,7 @@ _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
FcStrFree (s); FcStrFree (s);
return FcTrue; return FcTrue;
} }
if (set->num == set->size || set->storage == FcStorageStatic) if (set->num == set->size)
{ {
FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *)); FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
@ -926,24 +868,14 @@ _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
return FcFalse; return FcFalse;
FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *)); FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *));
set->size = set->size + 1; set->size = set->size + 1;
if (set->storage == FcStorageDynamic) if (set->num)
{ memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
if (set->num) if (set->strs)
memcpy (strs, set->u.strs, set->num * sizeof (FcChar8 *)); free (set->strs);
if (set->u.strs) set->strs = strs;
free (set->u.strs);
}
else
{
if (set->num)
memcpy (strs, strset_idx+set->u.stridx_offset,
set->num * sizeof (FcChar8 *));
set->storage = FcStorageDynamic;
}
set->u.strs = strs;
} }
set->u.strs[set->num++] = s; set->strs[set->num++] = s;
set->u.strs[set->num] = 0; set->strs[set->num] = 0;
return FcTrue; return FcTrue;
} }
@ -953,7 +885,7 @@ FcStrSetMember (FcStrSet *set, const FcChar8 *s)
int i; int i;
for (i = 0; i < set->num; i++) for (i = 0; i < set->num; i++)
if (!FcStrCmp (FcStrSetGet(set, i), s)) if (!FcStrCmp (set->strs[i], s))
return FcTrue; return FcTrue;
return FcFalse; return FcFalse;
} }
@ -965,7 +897,7 @@ FcStrSetEqual (FcStrSet *sa, FcStrSet *sb)
if (sa->num != sb->num) if (sa->num != sb->num)
return FcFalse; return FcFalse;
for (i = 0; i < sa->num; i++) for (i = 0; i < sa->num; i++)
if (!FcStrSetMember (sb, FcStrSetGet(sa, i))) if (!FcStrSetMember (sb, sa->strs[i]))
return FcFalse; return FcFalse;
return FcTrue; return FcTrue;
} }
@ -1004,15 +936,14 @@ FcStrSetDel (FcStrSet *set, const FcChar8 *s)
int i; int i;
for (i = 0; i < set->num; i++) for (i = 0; i < set->num; i++)
if (!FcStrCmp (FcStrSetGet(set, i), s)) if (!FcStrCmp (set->strs[i], s))
{ {
if (set->storage == FcStorageDynamic) FcStrFree (set->strs[i]);
FcStrFree (set->u.strs[i]);
/* /*
* copy remaining string pointers and trailing * copy remaining string pointers and trailing
* NULL * NULL
*/ */
memmove (FcStrSetGet(set, i), FcStrSetGet(set, i+1), memmove (&set->strs[i], &set->strs[i+1],
(set->num - i) * sizeof (FcChar8 *)); (set->num - i) * sizeof (FcChar8 *));
set->num--; set->num--;
return FcTrue; return FcTrue;
@ -1027,194 +958,16 @@ FcStrSetDestroy (FcStrSet *set)
{ {
int i; int i;
if (set->storage == FcStorageDynamic) for (i = 0; i < set->num; i++)
{ FcStrFree (set->strs[i]);
for (i = 0; i < set->num; i++) FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
FcStrFree (set->u.strs[i]); if (set->strs)
FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *)); free (set->strs);
if (set->u.strs) FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
free (set->u.strs);
FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
}
free (set); free (set);
} }
} }
static int _FcStrSetSort_helper (const void * a, const void * b)
{
return FcStrCmp (&strset_buf[(int)a],
&strset_buf[(int)b]);
}
void
FcStrSetSort (FcStrSet * set)
{
switch (set->storage)
{
case FcStorageDynamic:
qsort (set->u.strs, set->num, sizeof (FcChar8 *),
(int (*)(const void *, const void *)) FcStrCmp);
break;
case FcStorageStatic:
qsort (strset_idx+set->u.stridx_offset, set->num, sizeof (int),
_FcStrSetSort_helper);
break;
default:
break;
}
}
FcBool
FcStrSetPrepareSerialize (const FcStrSet *set)
{
int i;
if (!set)
return FcTrue;
strset_count ++;
strset_idx_count += set->num;
for (i = 0; i < set->num; i++)
{
if (FcStrSetGet(set, i))
strset_buf_count += strlen(FcStrSetGet(set, i));
}
return FcTrue;
}
FcStrSetPtr
FcStrSetSerialize (FcStrSet *set)
{
FcStrSet * new;
FcStrSetPtr newp;
int i;
if (!strsets)
{
strsets = malloc (strset_count * sizeof(FcStrSet));
if (!strsets) goto bail1;
strset_idx = malloc (strset_idx_count * sizeof(int));
if (!strset_idx) goto bail2;
strset_buf = malloc (strset_buf_count * sizeof (FcChar8));
if (!strset_buf) goto bail3;
}
if (!set)
return FcStrSetPtrCreateDynamic(0);
newp.storage = FcStorageStatic;
newp.u.stat = strset_ptr;
new = &strsets[strset_ptr++];
new->ref = set->ref;
new->num = set->num;
new->size = set->num;
new->storage = FcStorageStatic;
new->u.stridx_offset = strset_idx_ptr;
for (i = 0; i < set->num; i++)
{
FcChar8 * s = FcStrSetGet(set, i);
if (s)
{
memcpy(strset_buf+strset_buf_ptr, s,
strlen((char *)s));
strset_idx[strset_idx_ptr++] = strset_buf_ptr;
strset_buf_ptr += strlen((char *)s)+1;
}
else
strset_idx[strset_idx_ptr++] = -1;
}
if (strset_ptr > strset_count || strset_idx_ptr > strset_idx_count)
return FcStrSetPtrCreateDynamic(0);
// problem with multiple ptrs to the same StrSet.
// should hash StrSets or something.
// FcStrSetDestroy (set);
return newp;
bail3:
free (strset_idx);
bail2:
free (strsets);
bail1:
return FcStrSetPtrCreateDynamic(0);
}
FcBool
FcStrSetRead (int fd, FcCache metadata)
{
strsets = mmap(NULL,
metadata.strsets_length * sizeof (FcStrSet),
PROT_READ,
MAP_SHARED, fd, metadata.strsets_offset);
if (strsets == MAP_FAILED)
goto bail;
strset_count = strset_ptr = metadata.strsets_length;
strset_idx = mmap(NULL,
metadata.strsets_idx_length * sizeof (int),
PROT_READ,
MAP_SHARED, fd, metadata.strsets_idx_offset);
if (strset_idx == MAP_FAILED)
goto bail1;
strset_idx_count = strset_idx_ptr = metadata.strsets_length;
strset_buf = mmap(NULL,
metadata.strset_buf_length * sizeof (char),
PROT_READ,
MAP_SHARED, fd, metadata.strset_buf_offset);
if (strset_buf == MAP_FAILED)
goto bail2;
strset_buf_count = strset_buf_ptr = metadata.strset_buf_length;
return FcTrue;
bail2:
munmap (strset_idx, metadata.strsets_idx_length * sizeof (int));
bail1:
munmap (strsets, metadata.strsets_length * sizeof (FcStrSet));
bail:
return FcFalse;
}
FcBool
FcStrSetWrite (int fd, FcCache *metadata)
{
metadata->strsets_length = strset_ptr;
metadata->strsets_offset = FcCacheNextOffset(fd);
if (strset_ptr > 0)
{
lseek (fd, metadata->strsets_offset, SEEK_SET);
if (write (fd, strsets, strset_ptr * sizeof(FcStrSet)) == -1)
return FcFalse;
}
metadata->strsets_idx_length = strset_idx_ptr;
metadata->strsets_idx_offset = FcCacheNextOffset(fd);
if (strset_idx_ptr > 0)
{
lseek (fd, metadata->strsets_idx_offset, SEEK_SET);
if (write (fd, strset_idx, strset_idx_ptr * sizeof (int)) == -1)
return FcFalse;
}
metadata->strset_buf_offset = FcCacheNextOffset(fd);
metadata->strset_buf_length = strset_buf_ptr;
if (strset_buf_ptr > 0)
{
lseek (fd, metadata->strset_buf_offset, SEEK_SET);
if (write (fd, strset_buf,
metadata->strset_buf_length * sizeof (char)) == -1)
return FcFalse;
}
return FcTrue;
}
FcStrList * FcStrList *
FcStrListCreate (FcStrSet *set) FcStrListCreate (FcStrSet *set)
{ {
@ -1235,7 +988,7 @@ FcStrListNext (FcStrList *list)
{ {
if (list->n >= list->set->num) if (list->n >= list->set->num)
return 0; return 0;
return FcStrSetGet(list->set, list->n++); return list->set->strs[list->n++];
} }
void void

View File

@ -1878,8 +1878,8 @@ FcPopValue (FcConfigParse *parse)
switch (vstack->tag) { switch (vstack->tag) {
case FcVStackString: case FcVStackString:
value.u.si = FcObjectStaticName(FcStrCopy (vstack->u.string)); value.u.s = FcStrCopy (vstack->u.string);
if (FcObjectPtrU(value.u.si)) if (value.u.s)
value.type = FcTypeString; value.type = FcTypeString;
break; break;
case FcVStackConstant: case FcVStackConstant:
@ -1895,8 +1895,8 @@ FcPopValue (FcConfigParse *parse)
value.type = FcTypeInteger; value.type = FcTypeInteger;
break; break;
case FcVStackMatrix: case FcVStackMatrix:
value.u.mi = FcMatrixPtrCreateDynamic(FcMatrixCopy (vstack->u.matrix)); value.u.m = FcMatrixCopy (vstack->u.matrix);
if (FcMatrixPtrU(value.u.mi)) if (value.u.m)
value.type = FcTypeMatrix; value.type = FcTypeMatrix;
break; break;
case FcVStackBool: case FcVStackBool:
@ -2281,9 +2281,10 @@ FcConfigParseAndLoadDir (FcConfig *config,
if (ret) if (ret)
{ {
int i; int i;
FcStrSetSort (files); qsort (files->strs, files->num, sizeof (FcChar8 *),
(int (*)(const void *, const void *)) FcStrCmp);
for (i = 0; ret && i < files->num; i++) for (i = 0; ret && i < files->num; i++)
ret = FcConfigParseAndLoad (config, FcStrSetGet(files, i), complain); ret = FcConfigParseAndLoad (config, files->strs[i], complain);
} }
bail3: bail3:
FcStrSetDestroy (files); FcStrSetDestroy (files);