Commit 4262e0b3 authored by Patrick Lam's avatar Patrick Lam

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.
parent 212c9f43
......@@ -93,7 +93,6 @@ usage (char *program)
exit (1);
}
#if 0
static int
nsubdirs (FcStrSet *set)
{
......@@ -192,6 +191,7 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
ret++;
continue;
}
#if 0 // put this back later after fixing DirCacheValid
if (!force && FcDirCacheValid (dir))
{
if (verbose)
......@@ -199,11 +199,13 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
set->nfont, nsubdirs(subdirs));
}
else
#endif
{
if (verbose)
printf ("caching, %d fonts, %d dirs\n",
set->nfont, nsubdirs (subdirs));
if (!FcDirSave (set, subdirs, dir))
if (!FcDirSave (set, dir))
{
fprintf (stderr, "Can't save cache in \"%s\"\n", dir);
ret++;
......@@ -223,7 +225,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
FcStrListDone (list);
return ret;
}
#endif
int
main (int argc, char **argv)
......@@ -280,10 +281,6 @@ main (int argc, char **argv)
return 1;
}
/* We don't yet have per-directory caches. */
ret = (FcCacheWrite (config) == FcFalse);
#if 0
if (argv[i])
{
dirs = FcStrSetCreate ();
......@@ -308,7 +305,6 @@ main (int argc, char **argv)
else
list = FcConfigGetConfigDirs (config);
ret = scanDirs (list, config, argv[0], force, verbose);
#endif
/*
* 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
......
......@@ -48,7 +48,7 @@ FcMemFree (int kind, int size)
}
int
FcCacheNextOffset (int fd)
FcCacheBankToIndex (int bank)
{
return -1;
}
......@@ -404,7 +404,7 @@ main (int argc, char **argv)
if (j < 0)
j = i;
printf (" { (FcChar8 *) \"%s\",\n"
" { FC_REF_CONSTANT, %d, FcStorageDynamic, "
" { FC_REF_CONSTANT, %d, FC_BANK_DYNAMIC, "
"{ { (FcCharLeaf **) leaves_%s, "
"(FcChar16 *) numbers_%s } } } },\n",
langs[i],
......
......@@ -59,22 +59,22 @@
__v__.u.d = va_arg (va, double); \
break; \
case FcTypeString: \
__v__.u.si = va_arg (va, FcObjectPtr); \
__v__.u.s = va_arg (va, const char *); \
break; \
case FcTypeBool: \
__v__.u.b = va_arg (va, FcBool); \
break; \
case FcTypeMatrix: \
__v__.u.mi = va_arg (va, FcMatrixPtr); \
__v__.u.m = va_arg (va, const FcMatrix *); \
break; \
case FcTypeCharSet: \
__v__.u.ci = va_arg (va, FcCharSetPtr); \
__v__.u.c = va_arg (va, const FcCharSet *); \
break; \
case FcTypeFTFace: \
__v__.u.f = va_arg (va, FT_Face); \
break; \
case FcTypeLangSet: \
__v__.u.li = va_arg (va, FcLangSetPtr); \
__v__.u.l = va_arg (va, const FcLangSet *); \
break; \
} \
if (!FcPatternAdd (__p__, __o__, __v__, FcTrue)) \
......
......@@ -54,7 +54,7 @@ typedef int FcBool;
* it means multiple copies of the font information.
*/
#define FC_CACHE_VERSION "1"
#define FC_CACHE_VERSION "2"
#define FcTrue 1
#define FcFalse 0
......@@ -196,52 +196,28 @@ typedef enum _FcResult {
FcResultOutOfMemory
} FcResult;
typedef enum _FcStorage {
FcStorageStatic, FcStorageDynamic
} FcStorage;
typedef struct _FcPattern FcPattern;
typedef struct _FcLangSet FcLangSet;
typedef struct _FcMatrixPtr {
FcStorage storage;
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;
#define FC_BANK_DYNAMIC 0
#define FC_BANK_FIRST 1
typedef struct _FcValue {
FcType type;
union {
FcObjectPtr si;
const FcChar8 *s;
int s_off;
int i;
FcBool b;
double d;
FcMatrixPtr mi;
FcCharSetPtr ci;
const FcMatrix *m;
const FcCharSet *c;
int c_off;
void *f;
const FcPattern *p;
FcLangSetPtr li;
const FcLangSet *l;
int l_off; // this is a difference of char *s
} u;
} FcValue;
......@@ -254,7 +230,7 @@ typedef struct _FcFontSet {
typedef struct _FcObjectSet {
int nobject;
int sobject;
FcObjectPtr *objects;
const char **objects;
} FcObjectSet;
typedef enum _FcMatchKind {
......@@ -471,7 +447,7 @@ FcDirScan (FcFontSet *set,
FcBool force);
FcBool
FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
FcDirSave (FcFontSet *set, const FcChar8 *dir);
/* fcfreetype.c */
FcPattern *
......@@ -648,9 +624,6 @@ FcMatrixScale (FcMatrix *m, double sx, double sy);
void
FcMatrixShear (FcMatrix *m, double sh, double sv);
FcMatrix *
FcMatrixPtrU (FcMatrixPtr mi);
/* fcname.c */
FcBool
......
This diff is collapsed.
......@@ -247,7 +247,7 @@ FcConfigDestroy (FcConfig *config)
FcBool
FcConfigBuildFonts (FcConfig *config)
{
FcFontSet *fonts;
FcFontSet *fonts, *cached_fonts;
FcGlobalCache *cache;
FcStrList *list;
FcChar8 *dir;
......@@ -269,20 +269,35 @@ FcConfigBuildFonts (FcConfig *config)
goto bail1;
#endif
list = FcConfigGetFontDirs (config);
if (!list)
goto bail1;
while ((dir = FcStrListNext (list)))
cached_fonts = FcCacheRead(config);
if (!cached_fonts)
{
list = FcConfigGetFontDirs (config);
if (!list)
goto bail1;
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
{
if (FcDebug () & FC_DBG_FONTSET)
printf ("scan dir %s\n", dir);
FcDirScanConfig (fonts, config->fontDirs, cache,
config->blanks, dir, FcFalse, config);
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)
FcFontSetPrint (fonts);
......@@ -558,25 +573,24 @@ FcConfigPromote (FcValue v, FcValue u)
}
else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
{
v.u.mi = FcIdentityMatrix;
v.u.m = &FcIdentityMatrix;
v.type = FcTypeMatrix;
}
else if (v.type == FcTypeString && u.type == FcTypeLangSet)
{
v.u.li = FcLangSetPtrCreateDynamic(FcLangSetPromote
(FcObjectPtrU(v.u.si)));
v.u.l = FcLangSetPromote (v.u.s);
v.type = FcTypeLangSet;
}
return v;
}
FcBool
FcConfigCompareValue (const FcValue left_o,
FcConfigCompareValue (const FcValue *left_o,
FcOp op,
const FcValue right_o)
const FcValue *right_o)
{
FcValue left = left_o;
FcValue right = right_o;
FcValue left = FcValueCanonicalize(left_o);
FcValue right = FcValueCanonicalize(right_o);
FcBool ret = FcFalse;
left = FcConfigPromote (left, right);
......@@ -632,20 +646,16 @@ FcConfigCompareValue (const FcValue left_o,
switch (op) {
case FcOpEqual:
case FcOpListing:
ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si),
FcObjectPtrU(right.u.si)) == 0;
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
break;
case FcOpContains:
ret = FcStrStrIgnoreCase (FcObjectPtrU(left.u.si),
FcObjectPtrU(right.u.si)) != 0;
ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
break;
case FcOpNotEqual:
ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si),
FcObjectPtrU(right.u.si)) != 0;
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
break;
case FcOpNotContains:
ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si),
FcObjectPtrU(right.u.si)) == 0;
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
break;
default:
break;
......@@ -656,11 +666,11 @@ FcConfigCompareValue (const FcValue left_o,
case FcOpEqual:
case FcOpContains:
case FcOpListing:
ret = FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi));
ret = FcMatrixEqual (left.u.m, right.u.m);
break;
case FcOpNotEqual:
case FcOpNotContains:
ret = !FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi));
ret = !FcMatrixEqual (left.u.m, right.u.m);
break;
default:
break;
......@@ -671,17 +681,17 @@ FcConfigCompareValue (const FcValue left_o,
case FcOpContains:
case FcOpListing:
/* 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;
case FcOpNotContains:
/* 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;
case FcOpEqual:
ret = FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci));
ret = FcCharSetEqual (left.u.c, right.u.c);
break;
case FcOpNotEqual:
ret = !FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci));
ret = !FcCharSetEqual (left.u.c, right.u.c);
break;
default:
break;
......@@ -691,16 +701,16 @@ FcConfigCompareValue (const FcValue left_o,
switch (op) {
case FcOpContains:
case FcOpListing:
ret = FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
ret = FcLangSetContains (left.u.l, right.u.l);
break;
case FcOpNotContains:
ret = !FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
ret = !FcLangSetContains (left.u.l, right.u.l);
break;
case FcOpEqual:
ret = FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
ret = FcLangSetEqual (left.u.l, right.u.l);
break;
case FcOpNotEqual:
ret = !FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
ret = !FcLangSetEqual (left.u.l, right.u.l);
break;
default:
break;
......@@ -768,17 +778,17 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
break;
case FcOpString:
v.type = FcTypeString;
v.u.si = FcObjectStaticName(e->u.sval);
v.u.s = FcObjectStaticName(e->u.sval);
v = FcValueSave (v);
break;
case FcOpMatrix:
v.type = FcTypeMatrix;
v.u.mi = FcMatrixPtrCreateDynamic(e->u.mval);
v.u.m = e->u.mval;
v = FcValueSave (v);
break;
case FcOpCharSet:
v.type = FcTypeCharSet;
v.u.ci = FcCharSetPtrCreateDynamic(e->u.cval);
v.u.c = e->u.cval;
v = FcValueSave (v);
break;
case FcOpBool:
......@@ -821,7 +831,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
vl = FcConfigEvaluate (p, e->u.tree.left);
vr = FcConfigEvaluate (p, e->u.tree.right);
v.type = FcTypeBool;
v.u.b = FcConfigCompareValue (vl, e->op, vr);
v.u.b = FcConfigCompareValue (&vl, e->op, &vr);
FcValueDestroy (vl);
FcValueDestroy (vr);
break;
......@@ -886,11 +896,9 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
switch (e->op) {
case FcOpPlus:
v.type = FcTypeString;
v.u.si = FcObjectStaticName
(FcStrPlus (FcObjectPtrU(vl.u.si),
FcObjectPtrU(vr.u.si)));
v.u.s = FcObjectStaticName (FcStrPlus (vl.u.s, vr.u.s));
if (!FcObjectPtrU(v.u.si))
if (!v.u.s)
v.type = FcTypeVoid;
break;
default:
......@@ -906,9 +914,8 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
if (m)
{
FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
FcMatrixMultiply (m, FcMatrixPtrU(vl.u.mi),
FcMatrixPtrU(vr.u.mi));
v.u.mi = FcMatrixPtrCreateDynamic(m);
FcMatrixMultiply (m, vl.u.m, vr.u.m);
v.u.m = m;
}
else
{
......@@ -1041,7 +1048,7 @@ FcConfigMatchValueList (FcPattern *p,
for (v = values; v; v = FcValueListPtrU(v->next))
{
/* 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)
ret = v;
......@@ -1088,7 +1095,7 @@ FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
{
FcValueListPtr next = FcValueListPtrU(lp)->next;
if (lp.storage == FcStorageDynamic)
if (lp.bank == FC_BANK_DYNAMIC)
{
FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
free (l);
......@@ -1866,7 +1873,7 @@ FcConfigGlobsMatch (const FcStrSet *globs,
int i;
for (i = 0; i < globs->num; i++)
if (FcConfigGlobMatch (FcStrSetGet(globs, i), string))
if (FcConfigGlobMatch (globs->strs[i], string))
return FcTrue;
return FcFalse;
}
......
This diff is collapsed.
......@@ -40,24 +40,20 @@ FcValuePrint (const FcValue v)
printf (" %g(f)", v.u.d);
break;
case FcTypeString:
printf (" \"%s\"", FcObjectPtrU(v.u.si));
printf (" \"%s\"", v.u.s);
break;
case FcTypeBool:
printf (" %s", v.u.b ? "FcTrue" : "FcFalse");
break;
case FcTypeMatrix:
{
FcMatrix *m = FcMatrixPtrU(v.u.mi);
printf (" (%f %f; %f %f)", m->xx, m->xy, m->yx, m->yy);
printf (" (%f %f; %f %f)", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
break;
}
case FcTypeCharSet: /* XXX */
printf (" set");
break;
case FcTypeLangSet:
printf (" ");
FcLangSetPrint (FcLangSetPtrU(v.u.li));
FcLangSetPrint (v.u.l);
break;
case FcTypeFTFace:
printf (" face");
......@@ -70,7 +66,7 @@ FcValueListPrint (FcValueListPtr l)
{
for (; FcValueListPtrU(l); l = FcValueListPtrU(l)->next)
{
FcValuePrint (FcValueListPtrU(l)->value);
FcValuePrint (FcValueCanonicalize(&FcValueListPtrU(l)->value));
switch (FcValueListPtrU(l)->binding) {
case FcValueBindingWeak:
printf ("(w)");
......
......@@ -274,10 +274,17 @@ FcDirScan (FcFontSet *set,
}
FcBool
FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
FcDirSave (FcFontSet *set, const FcChar8 *dir)
{
#if 0
return FcDirCacheWriteDir (set, dirs, dir);
#endif
return FcTrue;
static int rand_state = 0;
int bank;
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);
}
......@@ -81,27 +81,58 @@ FcFontSetAdd (FcFontSet *s, FcPattern *font)
return FcTrue;
}
FcBool
FcFontSetPrepareSerialize (FcFontSet *s)
static int * fcfs_pat_count;
void
FcFontSetNewBank (void)
{
int i;
FcPatternNewBank();
FcObjectNewBank();
}
int
FcFontSetNeededBytes (FcFontSet *s)
{
int i, c, cum = 0;
for (i = 0; i < s->nfont; i++)
if (!FcPatternPrepareSerialize(s->fonts[i]))
return FcFalse;
{
c = FcPatternNeededBytes(s->fonts[i]);
if (c < 0)
return c;
cum += c;
}
return FcTrue;
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 (FcFontSet * s)
FcFontSetSerialize (int bank, FcFontSet * s)
{
int i;
FcPattern * p;
*fcfs_pat_count = s->nfont;
for (i = 0; i < s->nfont; i++)
{
p = FcPatternSerialize (s->fonts[i]);
p = FcPatternSerialize (bank, s->fonts[i]);
if (!p) return FcFalse;
FcPatternDestroy (s->fonts[i]);
......@@ -111,103 +142,34 @@ FcFontSetSerialize (FcFontSet * s)
return FcTrue;
}
void
FcFontSetClearStatic (void)
{
FcPatternClearStatic();
}
FcBool
FcFontSetRead(int fd, FcConfig * config, FcCache metadata)
FcFontSetUnserialize(FcCache metadata, FcFontSet * s, void * block_ptr)
{
int i, mz, j;
FcPattern * buf;
int nfont;
int i, n;
lseek(fd, metadata.fontsets_offset, SEEK_SET);
for (i = FcSetSystem; i <= FcSetApplication; i++)
{
if (config->fonts[i])
{
if (config->fonts[i]->nfont > 0 && config->fonts[i]->fonts)
free (config->fonts[i]->fonts);
free (config->fonts[i]);
}
}
nfont = *(int *)block_ptr;
block_ptr = (int *)block_ptr + 1;
for (i = FcSetSystem; i <= FcSetApplication; i++)
if (s->sfont < s->nfont + nfont)
{
read(fd, &mz, sizeof(int));
if (mz != FC_CACHE_MAGIC)
continue;
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;
}
}
int sfont = s->nfont + nfont;
FcPattern ** pp;
pp = realloc (s->fonts, sfont * sizeof (FcPattern));
if (!pp)
return FcFalse;
s->fonts = pp;
s->sfont = sfont;
}
n = s->nfont;
s->nfont += nfont;
return FcTrue;
bail:
for (i = FcSetSystem; i <= FcSetApplication; i++)
if (nfont > 0)
{
if (config->fonts[i])
{
if (config->fonts[i]->fonts)
free (config->fonts[i]->fonts);
free(config->fonts[i]);
}
config->fonts[i] = 0;
FcPattern * p = FcPatternUnserialize (metadata, block_ptr);
for (i = 0; i < nfont; i++)
s->fonts[n + i] = p+i;
}
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;
}
......@@ -61,9 +61,6 @@ FcInitLoadConfig (void)
if (!config)
return FcFalse;
if (!FcCacheRead(config))
FcCacheForce(FcTrue);
if (!FcConfigParseAndLoad (config, 0, FcTrue))
{
FcConfigDestroy (config);
......
This diff is collapsed.
......@@ -22,8 +22,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/