Add functionality to allow fontconfig data structure serialization.

This patch allows the fundamental fontconfig data structures to be
    serialized. I've converted everything from FcPattern down to be able to
    use *Ptr objects, which can be either static or dynamic (using a union
    which either contains a pointer or an index) and replaced storage of
    pointers in the heap with the appropriate *Ptr object. I then changed
    all writes of pointers to the heap with a *CreateDynamic call, which
    creates a dynamic Ptr object pointing to the same object as before.
    This way, the fundamental fontconfig semantics should be unchanged; I
    did not have to change external signatures this way, although I did
    change some internal signatures. When given a *Ptr object, just run *U
    to get back to a normal pointer; it gives the right answer regardless
    of whether we're using static or dynamic storage.
I've also implemented a Fc*Serialize call. Calling FcFontSetSerialize
    converts the dynamic FcFontSets contained in the config object to
    static FcFontSets and also converts its dependencies (e.g. everything
    you'd need to write to disk) to static objects. Note that you have to
    call Fc*PrepareSerialize first; this call will count the number of
    objects that actually needs to be allocated, so that we can avoid
    realloc. The Fc*Serialize calls then check the static pointers for
    nullness, and allocate the buffers if necessary. I've tested the
    execution of fc-list and fc-match after Fc*Serialize and they appear to
    work the same way.
This commit is contained in:
Patrick Lam 2005-06-28 03:41:02 +00:00
parent f1a42f6b5f
commit cd2ec1a940
17 changed files with 1902 additions and 526 deletions

View File

@ -220,7 +220,7 @@ main (int argc, char **argv)
FILE *f; FILE *f;
int ncountry = 0; int ncountry = 0;
int i = 0; int i = 0;
FcCharLeaf **leaves, **sleaves; FcCharLeaf **leaves;
int total_leaves = 0; int total_leaves = 0;
int l, sl, tl; int l, sl, tl;
int c; int c;
@ -268,14 +268,13 @@ main (int argc, char **argv)
*/ */
for (i = 0; sets[i]; i++) for (i = 0; sets[i]; i++)
{ {
sleaves = sets[i]->leaves;
for (sl = 0; sl < sets[i]->num; sl++) for (sl = 0; sl < sets[i]->num; sl++)
{ {
for (l = 0; l < tl; l++) for (l = 0; l < tl; l++)
if (leaves[l] == sleaves[sl]) if (leaves[l] == FcCharSetGetLeaf(sets[i], sl))
break; break;
if (l == tl) if (l == tl)
leaves[tl++] = sleaves[sl]; leaves[tl++] = FcCharSetGetLeaf(sets[i], sl);
} }
} }
@ -358,7 +357,7 @@ main (int argc, char **argv)
if (n % 8 == 0) if (n % 8 == 0)
printf (" "); printf (" ");
for (l = 0; l < tl; l++) for (l = 0; l < tl; l++)
if (leaves[l] == sets[i]->leaves[n]) if (leaves[l] == FcCharSetGetLeaf(sets[i], n))
break; break;
if (l == tl) if (l == tl)
fatal (names[i], 0, "can't find leaf"); fatal (names[i], 0, "can't find leaf");
@ -377,7 +376,7 @@ main (int argc, char **argv)
{ {
if (n % 8 == 0) if (n % 8 == 0)
printf (" "); printf (" ");
printf (" 0x%04x,", sets[i]->numbers[n]); printf (" 0x%04x,", FcCharSetGetNumbers(sets[i])[n]);
if (n % 8 == 7) if (n % 8 == 7)
printf ("\n"); printf ("\n");
} }
@ -399,9 +398,9 @@ 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, " " { FC_REF_CONSTANT, %d, FcStorageDynamic, "
"(FcCharLeaf **) leaves_%s, " "{ { (FcCharLeaf **) leaves_%s, "
"(FcChar16 *) numbers_%s } },\n", "(FcChar16 *) numbers_%s } } } },\n",
langs[i], langs[i],
sets[j]->num, names[j], names[j]); sets[j]->num, names[j], names[j]);
} }

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.s = va_arg (va, FcChar8 *); \ __v__.u.si = va_arg (va, FcObjectPtr); \
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.m = va_arg (va, FcMatrix *); \ __v__.u.mi = va_arg (va, FcMatrixPtr); \
break; \ break; \
case FcTypeCharSet: \ case FcTypeCharSet: \
__v__.u.c = va_arg (va, FcCharSet *); \ __v__.u.ci = va_arg (va, FcCharSetPtr); \
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.l = va_arg (va, FcLangSet *); \ __v__.u.li = va_arg (va, FcLangSetPtr); \
break; \ break; \
} \ } \
if (!FcPatternAdd (__p__, __o__, __v__, FcTrue)) \ if (!FcPatternAdd (__p__, __o__, __v__, FcTrue)) \

View File

@ -196,22 +196,59 @@ 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 {
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 struct _FcObjectPtr {
FcStorage storage;
union {
int stat;
const FcChar8 * dyn;
} u;
FcChar32 hash;
} FcObjectPtr;
typedef struct _FcValue { typedef struct _FcValue {
FcType type; FcType type;
union { union {
const FcChar8 *s; FcObjectPtr si;
int i; int i;
FcBool b; FcBool b;
double d; double d;
const FcMatrix *m; FcMatrixPtr mi;
const FcCharSet *c; FcCharSetPtr ci;
void *f; void *f;
const FcPattern *p; const FcPattern *p;
const FcLangSet *l; FcLangSetPtr li;
} u; } u;
} FcValue; } FcValue;
@ -224,7 +261,7 @@ typedef struct _FcFontSet {
typedef struct _FcObjectSet { typedef struct _FcObjectSet {
int nobject; int nobject;
int sobject; int sobject;
const char **objects; FcObjectPtr *objects;
} FcObjectSet; } FcObjectSet;
typedef enum _FcMatchKind { typedef enum _FcMatchKind {
@ -618,6 +655,9 @@ 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

@ -1166,3 +1166,35 @@ bail1:
bail0: bail0:
return FcFalse; return FcFalse;
} }
void
FcCacheClearStatic()
{
FcFontSetClearStatic();
FcPatternClearStatic();
FcValueListClearStatic();
FcObjectClearStatic();
FcMatrixClearStatic();
FcCharSetClearStatic();
FcLangSetClearStatic();
}
FcBool
FcCachePrepareSerialize (FcConfig * config)
{
int i;
for (i = FcSetSystem; i <= FcSetApplication; i++)
if (config->fonts[i] && !FcFontSetPrepareSerialize(config->fonts[i]))
return FcFalse;
return FcTrue;
}
FcBool
FcCacheSerialize (FcConfig * config)
{
int i;
for (i = FcSetSystem; i <= FcSetApplication; i++)
if (config->fonts[i] && !FcFontSetSerialize(config->fonts[i]))
return FcFalse;
return FcTrue;
}

View File

@ -550,12 +550,13 @@ FcConfigPromote (FcValue v, FcValue u)
} }
else if (v.type == FcTypeVoid && u.type == FcTypeMatrix) else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
{ {
v.u.m = &FcIdentityMatrix; v.u.mi = 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.l = FcLangSetPromote (v.u.s); v.u.li = FcLangSetPtrCreateDynamic(FcLangSetPromote
(FcObjectPtrU(v.u.si)));
v.type = FcTypeLangSet; v.type = FcTypeLangSet;
} }
return v; return v;
@ -623,16 +624,19 @@ FcConfigCompareValue (const FcValue left_o,
switch (op) { switch (op) {
case FcOpEqual: case FcOpEqual:
case FcOpListing: case FcOpListing:
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0; ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si),
FcObjectPtrU(right.u.si)) == 0;
break; break;
case FcOpContains: case FcOpContains:
ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0; ret = FcStrStrIgnoreCase (FcObjectPtrU(left.u.si),
FcObjectPtrU(right.u.si)) != 0;
break; break;
case FcOpNotEqual: case FcOpNotEqual:
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0; ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
break; break;
case FcOpNotContains: case FcOpNotContains:
ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0; ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si),
FcObjectPtrU(right.u.si)) == 0;
break; break;
default: default:
break; break;
@ -643,11 +647,11 @@ FcConfigCompareValue (const FcValue left_o,
case FcOpEqual: case FcOpEqual:
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = FcMatrixEqual (left.u.m, right.u.m); ret = FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi));
break; break;
case FcOpNotEqual: case FcOpNotEqual:
case FcOpNotContains: case FcOpNotContains:
ret = !FcMatrixEqual (left.u.m, right.u.m); ret = !FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi));
break; break;
default: default:
break; break;
@ -658,17 +662,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 (right.u.c, left.u.c); ret = FcCharSetIsSubset (FcCharSetPtrU(right.u.ci), FcCharSetPtrU(left.u.ci));
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 (right.u.c, left.u.c); ret = !FcCharSetIsSubset (FcCharSetPtrU(right.u.ci), FcCharSetPtrU(left.u.ci));
break; break;
case FcOpEqual: case FcOpEqual:
ret = FcCharSetEqual (left.u.c, right.u.c); ret = FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci));
break; break;
case FcOpNotEqual: case FcOpNotEqual:
ret = !FcCharSetEqual (left.u.c, right.u.c); ret = !FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci));
break; break;
default: default:
break; break;
@ -678,16 +682,16 @@ FcConfigCompareValue (const FcValue left_o,
switch (op) { switch (op) {
case FcOpContains: case FcOpContains:
case FcOpListing: case FcOpListing:
ret = FcLangSetContains (left.u.l, right.u.l); ret = FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
break; break;
case FcOpNotContains: case FcOpNotContains:
ret = !FcLangSetContains (left.u.l, right.u.l); ret = !FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
break; break;
case FcOpEqual: case FcOpEqual:
ret = FcLangSetEqual (left.u.l, right.u.l); ret = FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
break; break;
case FcOpNotEqual: case FcOpNotEqual:
ret = !FcLangSetEqual (left.u.l, right.u.l); ret = !FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
break; break;
default: default:
break; break;
@ -755,17 +759,17 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
break; break;
case FcOpString: case FcOpString:
v.type = FcTypeString; v.type = FcTypeString;
v.u.s = e->u.sval; v.u.si = FcObjectPtrCreateDynamic(e->u.sval);
v = FcValueSave (v); v = FcValueSave (v);
break; break;
case FcOpMatrix: case FcOpMatrix:
v.type = FcTypeMatrix; v.type = FcTypeMatrix;
v.u.m = e->u.mval; v.u.mi = FcMatrixPtrCreateDynamic(e->u.mval);
v = FcValueSave (v); v = FcValueSave (v);
break; break;
case FcOpCharSet: case FcOpCharSet:
v.type = FcTypeCharSet; v.type = FcTypeCharSet;
v.u.c = e->u.cval; v.u.ci = FcCharSetPtrCreateDynamic(e->u.cval);
v = FcValueSave (v); v = FcValueSave (v);
break; break;
case FcOpBool: case FcOpBool:
@ -873,8 +877,11 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
switch (e->op) { switch (e->op) {
case FcOpPlus: case FcOpPlus:
v.type = FcTypeString; v.type = FcTypeString;
v.u.s = FcStrPlus (vl.u.s, vr.u.s); v.u.si = FcObjectPtrCreateDynamic
if (!v.u.s) (FcStrPlus (FcObjectPtrU(vl.u.si),
FcObjectPtrU(vr.u.si)));
if (!FcObjectPtrU(v.u.si))
v.type = FcTypeVoid; v.type = FcTypeVoid;
break; break;
default: default:
@ -890,8 +897,9 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
if (m) if (m)
{ {
FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix)); FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
FcMatrixMultiply (m, vl.u.m, vr.u.m); FcMatrixMultiply (m, FcMatrixPtrU(vl.u.mi),
v.u.m = m; FcMatrixPtrU(vr.u.mi));
v.u.mi = FcMatrixPtrCreateDynamic(m);
} }
else else
{ {
@ -1021,7 +1029,7 @@ FcConfigMatchValueList (FcPattern *p,
e = 0; e = 0;
} }
for (v = values; v; v = 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))
@ -1047,6 +1055,7 @@ static FcValueList *
FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding) FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
{ {
FcValueList *l; FcValueList *l;
FcValueListPtr lp;
if (!e) if (!e)
return 0; return 0;
@ -1057,56 +1066,63 @@ FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
if (e->op == FcOpComma) if (e->op == FcOpComma)
{ {
l->value = FcConfigEvaluate (p, e->u.tree.left); l->value = FcConfigEvaluate (p, e->u.tree.left);
l->next = FcConfigValues (p, e->u.tree.right, binding); l->next = FcValueListPtrCreateDynamic(FcConfigValues (p, e->u.tree.right, binding));
} }
else else
{ {
l->value = FcConfigEvaluate (p, e); l->value = FcConfigEvaluate (p, e);
l->next = 0; l->next = FcValueListPtrCreateDynamic(0);
} }
l->binding = binding; l->binding = binding;
while (l && l->value.type == FcTypeVoid) lp = FcValueListPtrCreateDynamic(l);
while (FcValueListPtrU(lp) && FcValueListPtrU(lp)->value.type == FcTypeVoid)
{ {
FcValueList *next = l->next; FcValueListPtr next = FcValueListPtrU(lp)->next;
FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); if (lp.storage == FcStorageDynamic)
free (l); {
l = next; FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
free (l);
}
lp = next;
} }
return l; return l;
} }
static FcBool static FcBool
FcConfigAdd (FcValueList **head, FcConfigAdd (FcValueListPtr *head,
FcValueList *position, FcValueList *position,
FcBool append, FcBool append,
FcValueList *new) FcValueList *new)
{ {
FcValueList **prev, *last, *v; FcValueListPtr *prev, last, v;
FcValueBinding sameBinding; FcValueBinding sameBinding;
if (position) if (position)
sameBinding = position->binding; sameBinding = position->binding;
else else
sameBinding = FcValueBindingWeak; sameBinding = FcValueBindingWeak;
for (v = new; v; v = v->next) for (v = FcValueListPtrCreateDynamic(new); FcValueListPtrU(v);
if (v->binding == FcValueBindingSame) v = FcValueListPtrU(v)->next)
v->binding = sameBinding; if (FcValueListPtrU(v)->binding == FcValueBindingSame)
FcValueListPtrU(v)->binding = sameBinding;
if (append) if (append)
{ {
if (position) if (position)
prev = &position->next; prev = &position->next;
else else
for (prev = head; *prev; prev = &(*prev)->next) for (prev = head; FcValueListPtrU(*prev);
prev = &(FcValueListPtrU(*prev)->next))
; ;
} }
else else
{ {
if (position) if (position)
{ {
for (prev = head; *prev; prev = &(*prev)->next) for (prev = head; FcValueListPtrU(*prev);
prev = &(FcValueListPtrU(*prev)->next))
{ {
if (*prev == position) if (FcValueListPtrU(*prev) == position)
break; break;
} }
} }
@ -1115,7 +1131,7 @@ FcConfigAdd (FcValueList **head,
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
{ {
if (!*prev) if (!FcValueListPtrU(*prev))
printf ("position not on list\n"); printf ("position not on list\n");
} }
} }
@ -1129,12 +1145,12 @@ FcConfigAdd (FcValueList **head,
if (new) if (new)
{ {
last = new; last = FcValueListPtrCreateDynamic(new);
while (last->next) while (FcValueListPtrU(FcValueListPtrU(last)->next))
last = last->next; last = FcValueListPtrU(last)->next;
last->next = *prev; FcValueListPtrU(last)->next = *prev;
*prev = new; *prev = FcValueListPtrCreateDynamic(new);
} }
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
@ -1148,18 +1164,19 @@ FcConfigAdd (FcValueList **head,
} }
static void static void
FcConfigDel (FcValueList **head, FcConfigDel (FcValueListPtr *head,
FcValueList *position) FcValueList *position)
{ {
FcValueList **prev; FcValueListPtr *prev;
for (prev = head; *prev; prev = &(*prev)->next) for (prev = head; FcValueListPtrU(*prev);
prev = &(FcValueListPtrU(*prev)->next))
{ {
if (*prev == position) if (FcValueListPtrU(*prev) == position)
{ {
*prev = position->next; *prev = position->next;
position->next = 0; position->next = FcValueListPtrCreateDynamic(0);
FcValueListDestroy (position); FcValueListDestroy (FcValueListPtrCreateDynamic(position));
break; break;
} }
} }
@ -1191,8 +1208,8 @@ FcConfigPatternDel (FcPattern *p,
FcPatternElt *e = FcPatternFindElt (p, object); FcPatternElt *e = FcPatternFindElt (p, object);
if (!e) if (!e)
return; return;
while (e->values) while (FcValueListPtrU(e->values))
FcConfigDel (&e->values, e->values); FcConfigDel (&e->values, FcValueListPtrU(e->values));
} }
static void static void
@ -1202,7 +1219,7 @@ FcConfigPatternCanon (FcPattern *p,
FcPatternElt *e = FcPatternFindElt (p, object); FcPatternElt *e = FcPatternFindElt (p, object);
if (!e) if (!e)
return; return;
if (!e->values) if (!FcValueListPtrU(e->values))
FcPatternDel (p, object); FcPatternDel (p, object);
} }
@ -1281,12 +1298,12 @@ FcConfigSubstituteWithPat (FcConfig *config,
* Check to see if there is a match, mark the location * Check to see if there is a match, mark the location
* to apply match-relative edits * to apply match-relative edits
*/ */
st[i].value = FcConfigMatchValueList (m, t, st[i].elt->values); st[i].value = FcConfigMatchValueList (m, t, FcValueListPtrU(st[i].elt->values));
if (!st[i].value) if (!st[i].value)
break; break;
if (t->qual == FcQualFirst && st[i].value != st[i].elt->values) if (t->qual == FcQualFirst && st[i].value != FcValueListPtrU(st[i].elt->values))
break; break;
if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values) if (t->qual == FcQualNotFirst && st[i].value == FcValueListPtrU(st[i].elt->values))
break; break;
} }
if (t) if (t)
@ -1339,7 +1356,7 @@ FcConfigSubstituteWithPat (FcConfig *config,
if (t) if (t)
{ {
FcValueList *thisValue = st[i].value; FcValueList *thisValue = st[i].value;
FcValueList *nextValue = thisValue ? thisValue->next : 0; FcValueList *nextValue = thisValue ? FcValueListPtrU(thisValue->next) : 0;
/* /*
* Append the new list of values after the current value * Append the new list of values after the current value
@ -1840,7 +1857,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 (globs->strs[i], string)) if (FcConfigGlobMatch (FcStrSetGet(globs, i), string))
return FcTrue; return FcTrue;
return FcFalse; return FcFalse;
} }

View File

@ -29,6 +29,27 @@
/* #define CHATTY */ /* #define CHATTY */
static FcCharSet * charsets = 0;
static FcChar16 * numbers = 0;
static int charset_ptr, charset_count;
static int charset_numbers_ptr, charset_numbers_count;
static FcCharLeaf * leaves = 0;
static int charset_leaf_ptr, charset_leaf_count;
static int * leaf_idx = 0;
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)
{ {
@ -40,8 +61,9 @@ FcCharSetCreate (void)
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet)); FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
fcs->ref = 1; fcs->ref = 1;
fcs->num = 0; fcs->num = 0;
fcs->leaves = 0; fcs->storage = FcStorageDynamic;
fcs->numbers = 0; fcs->u.dyn.leaves = 0;
fcs->u.dyn.numbers = 0;
return fcs; return fcs;
} }
@ -54,6 +76,17 @@ 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)
@ -63,20 +96,23 @@ FcCharSetDestroy (FcCharSet *fcs)
return; return;
if (--fcs->ref > 0) if (--fcs->ref > 0)
return; return;
for (i = 0; i < fcs->num; i++) if (fcs->storage == FcStorageDynamic)
{ {
FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf)); for (i = 0; i < fcs->num; i++)
free (fcs->leaves[i]); {
} FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
if (fcs->leaves) free (fcs->u.dyn.leaves[i]);
{ }
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *)); if (fcs->u.dyn.leaves)
free (fcs->leaves); {
} FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
if (fcs->numbers) free (fcs->u.dyn.leaves);
{ }
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16)); if (fcs->u.dyn.numbers)
free (fcs->numbers); {
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
free (fcs->u.dyn.numbers);
}
} }
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet)); FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (fcs); free (fcs);
@ -91,7 +127,7 @@ FcCharSetDestroy (FcCharSet *fcs)
static int static int
FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4) FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
{ {
FcChar16 *numbers = fcs->numbers; FcChar16 *numbers = FcCharSetGetNumbers(fcs);
FcChar16 page; FcChar16 page;
int low = 0; int low = 0;
int high = fcs->num - 1; int high = fcs->num - 1;
@ -120,7 +156,7 @@ FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4)
{ {
int pos = FcCharSetFindLeafPos (fcs, ucs4); int pos = FcCharSetFindLeafPos (fcs, ucs4);
if (pos >= 0) if (pos >= 0)
return fcs->leaves[pos]; return FcCharSetGetLeaf(fcs, pos);
return 0; return 0;
} }
@ -136,33 +172,55 @@ FcCharSetPutLeaf (FcCharSet *fcs,
ucs4 >>= 8; ucs4 >>= 8;
if (ucs4 >= 0x10000) if (ucs4 >= 0x10000)
return FcFalse; return FcFalse;
if (!fcs->leaves) if (fcs->storage == FcStorageStatic)
leaves = malloc (sizeof (FcCharLeaf *)); {
else int i;
leaves = realloc (fcs->leaves, (fcs->num + 1) * sizeof (FcCharLeaf *));
if (!leaves)
return FcFalse;
if (fcs->num)
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcCharLeaf *));
fcs->leaves = leaves;
if (!fcs->numbers)
numbers = malloc (sizeof (FcChar16));
else
numbers = realloc (fcs->numbers, (fcs->num + 1) * sizeof (FcChar16));
if (!numbers)
return FcFalse;
if (fcs->num)
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcChar16));
fcs->numbers = numbers;
memmove (fcs->leaves + pos + 1, fcs->leaves + pos, leaves = malloc ((fcs->num + 1) * sizeof (FcCharLeaf *));
if (!leaves)
return FcFalse;
FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcCharLeaf *));
numbers = malloc ((fcs->num + 1) * sizeof (FcChar16));
if (!numbers)
return FcFalse;
FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcChar16));
for (i = 0; i < fcs->num; i++)
leaves[i] = FcCharSetGetLeaf(fcs, i);
memcpy (numbers, FcCharSetGetNumbers(fcs),
fcs->num * sizeof (FcChar16));
fcs->storage = FcStorageDynamic;
}
else
{
if (!fcs->u.dyn.leaves)
leaves = malloc (sizeof (FcCharLeaf *));
else
leaves = realloc (fcs->u.dyn.leaves, (fcs->num + 1) * sizeof (FcCharLeaf *));
if (!leaves)
return FcFalse;
if (fcs->num)
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcCharLeaf *));
fcs->u.dyn.leaves = leaves;
if (!fcs->u.dyn.numbers)
numbers = malloc (sizeof (FcChar16));
else
numbers = realloc (fcs->u.dyn.numbers, (fcs->num + 1) * sizeof (FcChar16));
if (!numbers)
return FcFalse;
if (fcs->num)
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcChar16));
fcs->u.dyn.numbers = numbers;
}
memmove (fcs->u.dyn.leaves + pos + 1, fcs->u.dyn.leaves + pos,
(fcs->num - pos) * sizeof (FcCharLeaf *)); (fcs->num - pos) * sizeof (FcCharLeaf *));
memmove (fcs->numbers + pos + 1, fcs->numbers + pos, memmove (fcs->u.dyn.numbers + pos + 1, fcs->u.dyn.numbers + pos,
(fcs->num - pos) * sizeof (FcChar16)); (fcs->num - pos) * sizeof (FcChar16));
fcs->numbers[pos] = (FcChar16) ucs4; fcs->u.dyn.numbers[pos] = (FcChar16) ucs4;
fcs->leaves[pos] = leaf; fcs->u.dyn.leaves[pos] = leaf;
fcs->num++; fcs->num++;
return FcTrue; return FcTrue;
} }
@ -180,7 +238,7 @@ FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4)
pos = FcCharSetFindLeafPos (fcs, ucs4); pos = FcCharSetFindLeafPos (fcs, ucs4);
if (pos >= 0) if (pos >= 0)
return fcs->leaves[pos]; return FcCharSetGetLeaf(fcs, pos);
leaf = calloc (1, sizeof (FcCharLeaf)); leaf = calloc (1, sizeof (FcCharLeaf));
if (!leaf) if (!leaf)
@ -205,8 +263,15 @@ 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));
free (fcs->leaves[pos]); if (fcs->storage == FcStorageDynamic)
fcs->leaves[pos] = leaf; {
free (fcs->u.dyn.leaves[pos]);
fcs->u.dyn.leaves[pos] = leaf;
}
else
{
leaves[leaf_idx[fcs->u.stat.leafidx_offset]+pos] = *leaf;
}
return FcTrue; return FcTrue;
} }
pos = -pos - 1; pos = -pos - 1;
@ -257,9 +322,9 @@ FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter)
iter->leaf = 0; iter->leaf = 0;
return; return;
} }
iter->ucs4 = (FcChar32) fcs->numbers[pos] << 8; iter->ucs4 = (FcChar32) FcCharSetGetNumbers(fcs)[pos] << 8;
} }
iter->leaf = fcs->leaves[pos]; iter->leaf = FcCharSetGetLeaf(fcs, pos);
iter->pos = pos; iter->pos = pos;
#ifdef CHATTY #ifdef CHATTY
printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf); printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf);
@ -277,8 +342,8 @@ FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter)
} }
else else
{ {
iter->ucs4 = (FcChar32) fcs->numbers[pos] << 8; iter->ucs4 = (FcChar32) FcCharSetGetNumbers(fcs)[pos] << 8;
iter->leaf = fcs->leaves[pos]; iter->leaf = FcCharSetGetLeaf(fcs, pos);
iter->pos = pos; iter->pos = pos;
} }
} }
@ -594,15 +659,15 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
ai = 0; ai = 0;
while (ai < a->num && bi < b->num) while (ai < a->num && bi < b->num)
{ {
an = a->numbers[ai]; an = FcCharSetGetNumbers(a)[ai];
bn = b->numbers[bi]; bn = FcCharSetGetNumbers(b)[bi];
/* /*
* Check matching pages * Check matching pages
*/ */
if (an == bn) if (an == bn)
{ {
FcChar32 *am = a->leaves[ai]->map; FcChar32 *am = FcCharSetGetLeaf(a, ai)->map;
FcChar32 *bm = b->leaves[bi]->map; FcChar32 *bm = FcCharSetGetLeaf(b, bi)->map;
if (am != bm) if (am != bm)
{ {
@ -633,7 +698,7 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
while (low <= high) while (low <= high)
{ {
int mid = (low + high) >> 1; int mid = (low + high) >> 1;
bn = b->numbers[mid]; bn = FcCharSetGetNumbers(b)[mid];
if (bn == an) if (bn == an)
{ {
high = mid; high = mid;
@ -645,7 +710,7 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
high = mid - 1; high = mid - 1;
} }
bi = high; bi = high;
while (bi < b->num && b->numbers[bi] < an) while (bi < b->num && FcCharSetGetNumbers(b)[bi] < an)
bi++; bi++;
} }
} }
@ -949,16 +1014,14 @@ static FcChar32
FcCharSetHash (FcCharSet *fcs) FcCharSetHash (FcCharSet *fcs)
{ {
FcChar32 hash = 0; FcChar32 hash = 0;
FcChar32 *p;
int i; int i;
/* hash in leaves */ /* hash in leaves */
p = (FcChar32 *) fcs->leaves;
for (i = 0; i < fcs->num * sizeof (FcCharLeaf *) / sizeof (FcChar32); i++) for (i = 0; i < fcs->num * sizeof (FcCharLeaf *) / sizeof (FcChar32); i++)
hash = ((hash << 1) | (hash >> 31)) ^ *p++; hash = ((hash << 1) | (hash >> 31)) ^ (FcChar32)(FcCharSetGetLeaf(fcs, i)->map);
/* hash in numbers */ /* hash in numbers */
for (i = 0; i < fcs->num; i++) for (i = 0; i < fcs->num; i++)
hash = ((hash << 1) | (hash >> 31)) ^ fcs->numbers[i]; hash = ((hash << 1) | (hash >> 31)) ^ *FcCharSetGetNumbers(fcs);
return hash; return hash;
} }
@ -982,12 +1045,18 @@ FcCharSetFreezeBase (FcCharSet *fcs)
{ {
if (ent->hash == hash && if (ent->hash == hash &&
ent->set.num == fcs->num && ent->set.num == fcs->num &&
!memcmp (ent->set.leaves, fcs->leaves, !memcmp (FcCharSetGetNumbers(&ent->set),
fcs->num * sizeof (FcCharLeaf *)) && FcCharSetGetNumbers(fcs),
!memcmp (ent->set.numbers, fcs->numbers,
fcs->num * sizeof (FcChar16))) fcs->num * sizeof (FcChar16)))
{ {
return &ent->set; FcBool ok = FcTrue;
int i;
for (i = 0; i < fcs->num; i++)
if (FcCharSetGetLeaf(&ent->set, i) != FcCharSetGetLeaf(fcs, i))
ok = FcFalse;
if (ok)
return &ent->set;
} }
} }
@ -1003,17 +1072,26 @@ 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;
if (fcs->num) ent->set.storage = fcs->storage;
if (fcs->storage == FcStorageDynamic)
{ {
ent->set.leaves = (FcCharLeaf **) (ent + 1); if (fcs->num)
ent->set.numbers = (FcChar16 *) (ent->set.leaves + fcs->num); {
memcpy (ent->set.leaves, fcs->leaves, fcs->num * sizeof (FcCharLeaf *)); ent->set.u.dyn.leaves = (FcCharLeaf **) (ent + 1);
memcpy (ent->set.numbers, fcs->numbers, fcs->num * sizeof (FcChar16)); ent->set.u.dyn.numbers = (FcChar16 *) (ent->set.u.dyn.leaves + fcs->num);
memcpy (ent->set.u.dyn.leaves, fcs->u.dyn.leaves, fcs->num * sizeof (FcCharLeaf *));
memcpy (ent->set.u.dyn.numbers, fcs->u.dyn.numbers, fcs->num * sizeof (FcChar16));
}
else
{
ent->set.u.dyn.leaves = 0;
ent->set.u.dyn.numbers = 0;
}
} }
else else
{ {
ent->set.leaves = 0; ent->set.u.stat.leafidx_offset = fcs->u.stat.leafidx_offset;
ent->set.numbers = 0; ent->set.u.stat.numbers_offset = fcs->u.stat.numbers_offset;
} }
ent->hash = hash; ent->hash = hash;
@ -1059,23 +1137,26 @@ FcCharSetFreeze (FcCharSet *fcs)
goto bail0; goto bail0;
for (i = 0; i < fcs->num; i++) for (i = 0; i < fcs->num; i++)
{ {
l = FcCharSetFreezeLeaf (fcs->leaves[i]); l = FcCharSetFreezeLeaf (FcCharSetGetLeaf(fcs, i));
if (!l) if (!l)
goto bail1; goto bail1;
if (!FcCharSetInsertLeaf (b, fcs->numbers[i] << 8, l)) if (!FcCharSetInsertLeaf (b, FcCharSetGetNumbers(fcs)[i] << 8, l))
goto bail1; goto bail1;
} }
n = FcCharSetFreezeBase (b); n = FcCharSetFreezeBase (b);
bail1: bail1:
if (b->leaves) if (b->storage == FcStorageDynamic)
{ {
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *)); if (b->u.dyn.leaves)
free (b->leaves); {
} FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
if (b->numbers) free (b->u.dyn.leaves);
{ }
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16)); if (b->u.dyn.numbers)
free (b->numbers); {
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
free (b->u.dyn.numbers);
}
} }
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet)); FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (b); free (b);
@ -1141,17 +1222,20 @@ FcNameParseCharSet (FcChar8 *string)
#endif #endif
n = FcCharSetFreezeBase (c); n = FcCharSetFreezeBase (c);
bail1: bail1:
if (c->leaves) if (c->storage == FcStorageDynamic)
{ {
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *)); if (c->u.dyn.leaves)
free (c->leaves); {
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
free (c->u.dyn.leaves);
}
if (c->u.dyn.numbers)
{
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
free (c->u.dyn.numbers);
}
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
} }
if (c->numbers)
{
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
free (c->numbers);
}
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (c); free (c);
bail0: bail0:
return n; return n;
@ -1229,3 +1313,116 @@ FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
return FcTrue; return FcTrue;
} }
FcCharSet *
FcCharSetPtrU (FcCharSetPtr ci)
{
switch (ci.storage)
{
case FcStorageDynamic:
return ci.u.dyn;
case FcStorageStatic:
return &charsets[ci.u.stat];
default:
return 0;
}
}
FcCharSetPtr
FcCharSetPtrCreateDynamic(FcCharSet *c)
{
FcCharSetPtr new;
new.storage = FcStorageDynamic;
new.u.dyn = c;
return new;
}
FcBool
FcCharSetPrepareSerialize(FcCharSet *c)
{
/* note the redundancy */
charset_count++;
charset_leaf_idx_count++;
charset_leaf_count += c->num;
charset_numbers_count += c->num;
return FcTrue;
}
FcCharSetPtr
FcCharSetSerialize(FcCharSet *c)
{
int i;
FcCharSetPtr newp;
FcCharSet new;
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 = c->ref;
new.storage = FcStorageStatic;
new.u.stat.leafidx_offset = charset_leaf_ptr;
new.u.stat.numbers_offset = charset_numbers_ptr;
newp.storage = FcStorageStatic;
newp.u.stat = charset_ptr;
charsets[charset_ptr++] = new;
leaf_idx[charset_leaf_idx_ptr++] = charset_leaf_ptr;
for (i = 0; i < c->num; i++)
{
memcpy (&leaves[charset_leaf_ptr++],
c->u.dyn.leaves[i], sizeof(FcCharLeaf));
numbers[charset_numbers_ptr++] = c->u.dyn.numbers[i];
}
return newp;
bail3:
free (leaves);
bail2:
free (numbers);
bail1:
free (charsets);
bail:
return FcCharSetPtrCreateDynamic(0);
}
FcCharLeaf *
FcCharSetGetLeaf(const FcCharSet *c, int i)
{
switch (c->storage)
{
case FcStorageDynamic:
return c->u.dyn.leaves[i];
case FcStorageStatic:
return &leaves[leaf_idx[c->u.stat.leafidx_offset]+i];
default:
return 0;
}
}
FcChar16 *
FcCharSetGetNumbers(const FcCharSet *c)
{
switch (c->storage)
{
case FcStorageDynamic:
return c->u.dyn.numbers;
case FcStorageStatic:
return &numbers[c->u.stat.numbers_offset];
default:
return 0;
}
}

View File

@ -40,20 +40,24 @@ FcValuePrint (const FcValue v)
printf (" %g(f)", v.u.d); printf (" %g(f)", v.u.d);
break; break;
case FcTypeString: case FcTypeString:
printf (" \"%s\"", v.u.s); printf (" \"%s\"", FcObjectPtrU(v.u.si));
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 (v.u.l); FcLangSetPrint (FcLangSetPtrU(v.u.li));
break; break;
case FcTypeFTFace: case FcTypeFTFace:
printf (" face"); printf (" face");
@ -62,12 +66,12 @@ FcValuePrint (const FcValue v)
} }
void void
FcValueListPrint (const FcValueList *l) FcValueListPrint (FcValueListPtr l)
{ {
for (; l; l = l->next) for (; FcValueListPtrU(l); l = FcValueListPtrU(l)->next)
{ {
FcValuePrint (l->value); FcValuePrint (FcValueListPtrU(l)->value);
switch (l->binding) { switch (FcValueListPtrU(l)->binding) {
case FcValueBindingWeak: case FcValueBindingWeak:
printf ("(w)"); printf ("(w)");
break; break;
@ -89,9 +93,9 @@ FcLangSetPrint (const FcLangSet *ls)
FcStrBufInit (&buf, init_buf, sizeof (init_buf)); FcStrBufInit (&buf, init_buf, sizeof (init_buf));
if (FcNameUnparseLangSet (&buf, ls) && FcStrBufChar (&buf,'\0')) if (FcNameUnparseLangSet (&buf, ls) && FcStrBufChar (&buf,'\0'))
printf ("%s", buf.buf); printf ("%s", buf.buf);
else else
printf ("langset (alloc error)"); printf ("langset (alloc error)");
FcStrBufDestroy (&buf); FcStrBufDestroy (&buf);
} }
@ -109,8 +113,8 @@ FcPatternPrint (const FcPattern *p)
printf ("Pattern %d of %d\n", p->num, p->size); printf ("Pattern %d of %d\n", p->num, p->size);
for (i = 0; i < p->num; i++) for (i = 0; i < p->num; i++)
{ {
e = &p->elts[i]; e = FcPatternEltU(p->elts) + i;
printf ("\t%s:", e->object); printf ("\t%s:", FcObjectPtrU(e->object));
FcValueListPrint (e->values); FcValueListPrint (e->values);
printf ("\n"); printf ("\n");
} }

View File

@ -80,3 +80,39 @@ FcFontSetAdd (FcFontSet *s, FcPattern *font)
s->fonts[s->nfont++] = font; s->fonts[s->nfont++] = font;
return FcTrue; return FcTrue;
} }
FcBool
FcFontSetPrepareSerialize (FcFontSet *s)
{
int i;
for (i = 0; i < s->nfont; i++)
if (!FcPatternPrepareSerialize(s->fonts[i]))
return FcFalse;
return FcTrue;
}
FcBool
FcFontSetSerialize (FcFontSet * s)
{
int i;
FcPattern * p;
for (i = 0; i < s->nfont; i++)
{
p = FcPatternSerialize (s->fonts[i]);
if (!p) return FcFalse;
FcPatternDestroy (s->fonts[i]);
s->fonts[i] = p;
}
return FcTrue;
}
void
FcFontSetClearStatic (void)
{
FcPatternClearStatic();
}

View File

@ -41,6 +41,7 @@
#include <config.h> #include <config.h>
#endif #endif
/* unused */
typedef struct _FcSymbolic { typedef struct _FcSymbolic {
const char *name; const char *name;
int value; int value;
@ -108,22 +109,46 @@ 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 {
FcStorage storage;
union {
int stat;
struct _FcValueList *dyn;
} u;
} FcValueListPtr;
typedef struct _FcValueList { typedef struct _FcValueList {
struct _FcValueList *next; FcValueListPtr next;
FcValue value; FcValue value;
FcValueBinding binding; FcValueBinding binding;
} FcValueList; } FcValueList;
typedef struct _FcPatternElt { typedef struct _FcPatternEltPtr {
const char *object; FcStorage storage;
FcValueList *values; union {
} FcPatternElt; int stat;
struct _FcPatternElt *dyn;
} u;
} FcPatternEltPtr;
typedef struct _FcPatternElt {
FcObjectPtr object;
FcValueListPtr values;
} FcPatternElt;
struct _FcPattern { struct _FcPattern {
int num; int num;
int size; int size;
FcPatternElt *elts; FcPatternEltPtr elts;
int ref; int ref;
}; };
@ -197,15 +222,28 @@ 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 */
FcCharLeaf **leaves; FcStorage storage;
FcChar16 *numbers; union {
struct {
FcCharLeaf **leaves;
FcChar16 *numbers;
} dyn;
struct {
int leafidx_offset;
int numbers_offset;
} stat;
} u;
}; };
struct _FcStrSet { struct _FcStrSet {
int ref; /* reference count */ int ref; /* reference count */
int num; int num;
int size; int size;
FcChar8 **strs; FcStorage storage;
union {
FcChar8 **strs;
int stridx_offset;
} u;
}; };
struct _FcStrList { struct _FcStrList {
@ -527,9 +565,30 @@ FcNameParseCharSet (FcChar8 *string);
FcCharLeaf * FcCharLeaf *
FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4); FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4);
void
FcCharSetPtrDestroy (FcCharSetPtr fcs);
void
FcCharSetClearStatic(void);
FcBool
FcCharSetPrepareSerialize(FcCharSet *c);
FcCharSetPtr
FcCharSetSerialize(FcCharSet *c);
FcCharSetPtr
FcCharSetPtrCreateDynamic(FcCharSet *c);
FcCharLeaf *
FcCharSetGetLeaf(const FcCharSet *c, int i);
FcChar16 *
FcCharSetGetNumbers(const FcCharSet *c);
/* fcdbg.c */ /* fcdbg.c */
void void
FcValueListPrint (const FcValueList *l); FcValueListPrint (const FcValueListPtr l);
void void
FcLangSetPrint (const FcLangSet *ls); FcLangSetPrint (const FcLangSet *ls);
@ -552,6 +611,9 @@ FcSubstPrint (const FcSubst *subst);
int int
FcDebug (void); FcDebug (void);
FcCharSet *
FcCharSetPtrU (FcCharSetPtr mi);
/* fcdir.c */ /* fcdir.c */
FcBool FcBool
@ -596,6 +658,16 @@ const FcCharMap *
FcFreeTypeGetPrivateMap (FT_Encoding encoding); FcFreeTypeGetPrivateMap (FT_Encoding encoding);
/* fcfs.c */ /* fcfs.c */
void
FcFontSetClearStatic (void);
FcBool
FcFontSetPrepareSerialize (FcFontSet * s);
FcBool
FcFontSetSerialize (FcFontSet * s);
/* fcgram.y */ /* fcgram.y */
int int
FcConfigparse (void); FcConfigparse (void);
@ -676,6 +748,24 @@ FcNameParseLangSet (const FcChar8 *string);
FcBool FcBool
FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls); FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls);
void
FcLangSetClearStatic (void);
FcBool
FcLangSetPrepareSerialize (FcLangSet *l);
FcLangSetPtr
FcLangSetSerialize (FcLangSet *l);
FcLangSet *
FcLangSetPtrU (FcLangSetPtr li);
FcLangSetPtr
FcLangSetPtrCreateDynamic (FcLangSet *l);
void
FcLangSetPtrDestroy (FcLangSetPtr li);
/* fclist.c */ /* fclist.c */
FcBool FcBool
@ -684,6 +774,18 @@ FcListPatternMatchAny (const FcPattern *p,
/* fcmatch.c */ /* fcmatch.c */
/* fcmmap.c */
void
FcCacheClearStatic(void);
FcBool
FcCachePrepareSerialize(FcConfig * config);
FcBool
FcCacheSerialize (FcConfig * config);
/* fcname.c */ /* fcname.c */
FcBool FcBool
@ -691,7 +793,7 @@ FcNameBool (const FcChar8 *v, FcBool *result);
/* fcpat.c */ /* fcpat.c */
void void
FcValueListDestroy (FcValueList *l); FcValueListDestroy (FcValueListPtr l);
FcPatternElt * FcPatternElt *
FcPatternFindElt (const FcPattern *p, const char *object); FcPatternFindElt (const FcPattern *p, const char *object);
@ -715,19 +817,100 @@ FcPatternThawAll (void);
FcBool FcBool
FcPatternAppend (FcPattern *p, FcPattern *s); FcPatternAppend (FcPattern *p, FcPattern *s);
const char * void
FcObjectClearStatic(void);
FcObjectPtr
FcObjectStaticName (const char *name); FcObjectStaticName (const char *name);
FcBool
FcObjectPrepareSerialize (FcObjectPtr si);
const char *
FcObjectPtrU (FcObjectPtr p);
int
FcObjectPtrCompare (FcObjectPtr a, FcObjectPtr b);
FcObjectPtr
FcObjectPtrCreateDynamic (const char * s);
void
FcObjectPtrDestroy (FcObjectPtr p);
FcBool
FcPatternPrepareSerialize (FcPattern *p);
void
FcValueListClearStatic (void);
void
FcPatternClearStatic (void);
FcValueList *
FcValueListPtrU(FcValueListPtr p);
FcPatternElt *
FcPatternEltU (FcPatternEltPtr pei);
FcValueListPtr
FcValueListPtrCreateDynamic(FcValueList * p);
FcBool
FcValueListPrepareSerialize (FcValueList *p);
FcValueListPtr
FcValueListSerialize(FcValueList *pi);
FcPattern *
FcPatternSerialize (FcPattern * p);
/* fcrender.c */ /* fcrender.c */
/* fcmatrix.c */ /* fcmatrix.c */
extern const FcMatrix FcIdentityMatrix; extern const FcMatrixPtr 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);
/* fcstr.c */ /* fcstr.c */
FcStrSet *
FcStrSetPtrU (const FcStrSetPtr set);
FcStrSetPtr
FcStrSetPtrCreateDynamic (const FcStrSet * set);
void
FcStrSetClearStatic (void);
FcBool
FcStrSetPrepareSerialize (const FcStrSet *set);
void
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);
@ -752,6 +935,9 @@ 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);
int int
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2); FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);

View File

@ -22,6 +22,8 @@
* 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 {
@ -38,7 +40,7 @@ typedef struct {
struct _FcLangSet { struct _FcLangSet {
FcChar32 map[NUM_LANG_SET_MAP]; FcChar32 map[NUM_LANG_SET_MAP];
FcStrSet *extra; FcStrSetPtr 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)))
@ -48,7 +50,7 @@ FcLangSet *
FcFreeTypeLangSet (const FcCharSet *charset, FcFreeTypeLangSet (const FcCharSet *charset,
const FcChar8 *exclusiveLang) const FcChar8 *exclusiveLang)
{ {
int i; int i, j;
FcChar32 missing; FcChar32 missing;
const FcCharSet *exclusiveCharset = 0; const FcCharSet *exclusiveCharset = 0;
FcLangSet *ls; FcLangSet *ls;
@ -67,10 +69,15 @@ FcFreeTypeLangSet (const FcCharSet *charset,
* not support other Han languages * not support other Han languages
*/ */
if (exclusiveCharset && if (exclusiveCharset &&
FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang) && FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang))
fcLangCharSets[i].charset.leaves != exclusiveCharset->leaves)
{ {
continue; if (fcLangCharSets[i].charset.num != exclusiveCharset->num)
continue;
for (j = 0; j < fcLangCharSets[i].charset.num; j++)
if (FcCharSetGetLeaf(&fcLangCharSets[i].charset, j) !=
FcCharSetGetLeaf(exclusiveCharset, j))
continue;
} }
missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset); missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset);
if (FcDebug() & FC_DBG_SCANV) if (FcDebug() & FC_DBG_SCANV)
@ -210,15 +217,22 @@ 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 = 0; ls->extra = FcStrSetPtrCreateDynamic(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 (ls->extra) if (FcStrSetPtrU(ls->extra))
FcStrSetDestroy (ls->extra); FcStrSetDestroy (FcStrSetPtrU(ls->extra));
FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet)); FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet));
free (ls); free (ls);
} }
@ -232,21 +246,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 (ls->extra) if (FcStrSetPtrU(ls->extra))
{ {
FcStrList *list; FcStrList *list;
FcChar8 *extra; FcChar8 *extra;
new->extra = FcStrSetCreate (); new->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ());
if (!new->extra) if (!FcStrSetPtrU(new->extra))
goto bail1; goto bail1;
list = FcStrListCreate (ls->extra); list = FcStrListCreate (FcStrSetPtrU(ls->extra));
if (!list) if (!list)
goto bail1; goto bail1;
while ((extra = FcStrListNext (list))) while ((extra = FcStrListNext (list)))
if (!FcStrSetAdd (new->extra, extra)) if (!FcStrSetAdd (FcStrSetPtrU(new->extra), extra))
{ {
FcStrListDone (list); FcStrListDone (list);
goto bail1; goto bail1;
@ -327,13 +341,13 @@ FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
FcLangSetBitSet (ls, id); FcLangSetBitSet (ls, id);
return FcTrue; return FcTrue;
} }
if (!ls->extra) if (!FcStrSetPtrU(ls->extra))
{ {
ls->extra = FcStrSetCreate (); ls->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ());
if (!ls->extra) if (!FcStrSetPtrU(ls->extra))
return FcFalse; return FcFalse;
} }
return FcStrSetAdd (ls->extra, lang); return FcStrSetAdd (FcStrSetPtrU(ls->extra), lang);
} }
FcLangResult FcLangResult
@ -365,9 +379,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 (ls->extra) if (FcStrSetPtrU(ls->extra))
{ {
FcStrList *list = FcStrListCreate (ls->extra); FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
FcChar8 *extra; FcChar8 *extra;
FcLangResult r; FcLangResult r;
@ -423,15 +437,15 @@ FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
best = FcLangDifferentCountry; best = FcLangDifferentCountry;
break; break;
} }
if (lsa->extra) if (FcStrSetPtrU(lsa->extra))
{ {
r = FcLangSetCompareStrSet (lsb, lsa->extra); r = FcLangSetCompareStrSet (lsb, FcStrSetPtrU(lsa->extra));
if (r < best) if (r < best)
best = r; best = r;
} }
if (best > FcLangEqual && lsb->extra) if (best > FcLangEqual && FcStrSetPtrU(lsb->extra))
{ {
r = FcLangSetCompareStrSet (lsa, lsb->extra); r = FcLangSetCompareStrSet (lsa, FcStrSetPtrU(lsb->extra));
if (r < best) if (r < best)
best = r; best = r;
} }
@ -450,7 +464,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 = 0; ls.extra = FcStrSetPtrCreateDynamic(0);
id = FcLangSetIndex (lang); id = FcLangSetIndex (lang);
if (id > 0) if (id > 0)
{ {
@ -458,10 +472,11 @@ FcLangSetPromote (const FcChar8 *lang)
} }
else else
{ {
ls.extra = &strs; ls.extra = FcStrSetPtrCreateDynamic(&strs);
strs.num = 1; strs.num = 1;
strs.size = 1; strs.size = 1;
strs.strs = &str; strs.storage = FcStorageDynamic;
strs.u.strs = &str;
strs.ref = 1; strs.ref = 1;
str = (FcChar8 *) lang; str = (FcChar8 *) lang;
} }
@ -476,8 +491,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 (ls->extra) if (FcStrSetPtrU(ls->extra))
h ^= ls->extra->num; h ^= FcStrSetPtrU(ls->extra)->num;
return h; return h;
} }
@ -538,9 +553,9 @@ FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
} }
} }
} }
if (ls->extra) if (FcStrSetPtrU(ls->extra))
{ {
FcStrList *list = FcStrListCreate (ls->extra); FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
FcChar8 *extra; FcChar8 *extra;
if (!list) if (!list)
@ -568,10 +583,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 (!lsa->extra && !lsb->extra) if (!FcStrSetPtrU(lsa->extra) && !FcStrSetPtrU(lsb->extra))
return FcTrue; return FcTrue;
if (lsa->extra && lsb->extra) if (FcStrSetPtrU(lsa->extra) && FcStrSetPtrU(lsb->extra))
return FcStrSetEqual (lsa->extra, lsb->extra); return FcStrSetEqual (FcStrSetPtrU(lsa->extra), FcStrSetPtrU(lsb->extra));
return FcFalse; return FcFalse;
} }
@ -605,9 +620,9 @@ FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
FcLangContains (fcLangCharSets[i].lang, lang)) FcLangContains (fcLangCharSets[i].lang, lang))
return FcTrue; return FcTrue;
} }
if (ls->extra) if (FcStrSetPtrU(ls->extra))
{ {
FcStrList *list = FcStrListCreate (ls->extra); FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
FcChar8 *extra; FcChar8 *extra;
if (list) if (list)
@ -661,9 +676,9 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
} }
} }
} }
if (lsb->extra) if (FcStrSetPtrU(lsb->extra))
{ {
FcStrList *list = FcStrListCreate (lsb->extra); FcStrList *list = FcStrListCreate (FcStrSetPtrU(lsb->extra));
FcChar8 *extra; FcChar8 *extra;
if (list) if (list)
@ -684,3 +699,78 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
} }
return FcTrue; return FcTrue;
} }
static FcLangSet * langsets = 0;
static int 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
FcLangSetClearStatic (void)
{
FcStrSetClearStatic();
langset_ptr = 0;
langset_count = 0;
}
/* should only write one copy of any particular FcLangSet */
FcBool
FcLangSetPrepareSerialize (FcLangSet *l)
{
langset_count++;
if (l && FcStrSetPtrU(l->extra))
return FcStrSetPrepareSerialize (FcStrSetPtrU(l->extra));
return FcTrue;
}
FcLangSetPtr
FcLangSetSerialize(FcLangSet *l)
{
FcLangSetPtr new;
int p = langset_ptr;
if (!l) return FcLangSetPtrCreateDynamic(0);
if (!langsets)
{
FcLangSet* t;
t = (FcLangSet *)malloc(langset_count * sizeof(FcLangSet));
if (!t)
return FcLangSetPtrCreateDynamic(0);
langsets = t;
langset_ptr = 0;
}
langsets[langset_ptr] = *l;
if (FcStrSetPtrU(l->extra))
langsets[langset_ptr].extra =
FcStrSetSerialize(FcStrSetPtrU(l->extra));
else
langsets[langset_ptr].extra = FcStrSetPtrCreateDynamic(0);
langset_ptr++;
new.storage = FcStorageStatic;
new.u.stat = p;
return new;
}

View File

@ -23,6 +23,9 @@
*/ */
#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 *
@ -44,17 +47,18 @@ FcBool
FcObjectSetAdd (FcObjectSet *os, const char *object) FcObjectSetAdd (FcObjectSet *os, const char *object)
{ {
int s; int s;
const char **objects; FcObjectPtr *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 = (const char **) realloc ((void *) os->objects, objects = (FcObjectPtr *) realloc ((void *) os->objects,
s * sizeof (const char *)); s * sizeof (FcObjectPtr));
else else
objects = (const char **) malloc (s * sizeof (const char *)); objects = (FcObjectPtr *) malloc (s * sizeof (FcObjectPtr));
if (!objects) if (!objects)
return FcFalse; return FcFalse;
if (os->sobject) if (os->sobject)
@ -67,11 +71,11 @@ FcObjectSetAdd (FcObjectSet *os, const char *object)
low = 0; low = 0;
mid = 0; mid = 0;
c = 1; c = 1;
object = FcObjectStaticName (object); obj = FcObjectStaticName (object);
while (low <= high) while (low <= high)
{ {
mid = (low + high) >> 1; mid = (low + high) >> 1;
c = os->objects[mid] - object; c = FcObjectPtrCompare(os->objects[mid], obj);
if (c == 0) if (c == 0)
return FcTrue; return FcTrue;
if (c < 0) if (c < 0)
@ -82,8 +86,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 (const char *)); (os->nobject - mid) * sizeof (FcObjectPtr));
os->objects[mid] = object; os->objects[mid] = obj;
os->nobject++; os->nobject++;
return FcTrue; return FcTrue;
} }
@ -125,51 +129,59 @@ FcObjectSetBuild (const char *first, ...)
* Font must have a containing value for every value in the pattern * Font must have a containing value for every value in the pattern
*/ */
static FcBool static FcBool
FcListValueListMatchAny (FcValueList *patOrig, /* pattern */ FcListValueListMatchAny (FcValueListPtr patOrig, /* pattern */
FcValueList *fntOrig) /* font */ FcValueListPtr fntOrig) /* font */
{ {
FcValueList *pat, *fnt; FcValueListPtr pat, fnt;
for (pat = patOrig; pat; pat = pat->next) for (pat = patOrig; FcValueListPtrU(pat);
pat = FcValueListPtrU(pat)->next)
{ {
for (fnt = fntOrig; fnt; fnt = fnt->next) for (fnt = fntOrig; FcValueListPtrU(fnt);
fnt = FcValueListPtrU(fnt)->next)
{ {
/* /*
* make sure the font 'contains' the pattern. * make sure the font 'contains' the 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 (fnt->value, if (FcConfigCompareValue (FcValueListPtrU(fnt)->value,
FcOpListing, FcOpListing,
pat->value)) FcValueListPtrU(pat)->value))
break; break;
} }
if (!fnt) if (!FcValueListPtrU(fnt))
return FcFalse; return FcFalse;
} }
return FcTrue; return FcTrue;
} }
static FcBool static FcBool
FcListValueListEqual (FcValueList *v1orig, FcListValueListEqual (FcValueListPtr v1orig,
FcValueList *v2orig) FcValueListPtr v2orig)
{ {
FcValueList *v1, *v2; FcValueListPtr v1, v2;
for (v1 = v1orig; v1; v1 = v1->next) for (v1 = v1orig; FcValueListPtrU(v1);
v1 = FcValueListPtrU(v1)->next)
{ {
for (v2 = v2orig; v2; v2 = v2->next) for (v2 = v2orig; FcValueListPtrU(v2);
if (FcValueEqual (v1->value, v2->value)) v2 = FcValueListPtrU(v2)->next)
if (FcValueEqual (FcValueListPtrU(v1)->value,
FcValueListPtrU(v2)->value))
break; break;
if (!v2) if (!FcValueListPtrU(v2))
return FcFalse; return FcFalse;
} }
for (v2 = v2orig; v2; v2 = v2->next) for (v2 = v2orig; FcValueListPtrU(v2);
v2 = FcValueListPtrU(v2)->next)
{ {
for (v1 = v1orig; v1; v1 = v1->next) for (v1 = v1orig; FcValueListPtrU(v1);
if (FcValueEqual (v1->value, v2->value)) v1 = FcValueListPtrU(v1)->next)
if (FcValueEqual (FcValueListPtrU(v1)->value,
FcValueListPtrU(v2)->value))
break; break;
if (!v1) if (!FcValueListPtrU(v1))
return FcFalse; return FcFalse;
} }
return FcTrue; return FcTrue;
@ -185,8 +197,8 @@ FcListPatternEqual (FcPattern *p1,
for (i = 0; i < os->nobject; i++) for (i = 0; i < os->nobject; i++)
{ {
e1 = FcPatternFindElt (p1, os->objects[i]); e1 = FcPatternFindElt (p1, FcObjectPtrU(os->objects[i]));
e2 = FcPatternFindElt (p2, os->objects[i]); e2 = FcPatternFindElt (p2, FcObjectPtrU(os->objects[i]));
if (!e1 && !e2) if (!e1 && !e2)
continue; continue;
if (!e1 || !e2) if (!e1 || !e2)
@ -210,10 +222,11 @@ FcListPatternMatchAny (const FcPattern *p,
for (i = 0; i < p->num; i++) for (i = 0; i < p->num; i++)
{ {
e = FcPatternFindElt (font, p->elts[i].object); e = FcPatternFindElt (font,
FcObjectPtrU((FcPatternEltU(p->elts)+i)->object));
if (!e) if (!e)
return FcFalse; return FcFalse;
if (!FcListValueListMatchAny (p->elts[i].values, /* pat elts */ if (!FcListValueListMatchAny ((FcPatternEltU(p->elts)+i)->values, /* pat elts */
e->values)) /* font elts */ e->values)) /* font elts */
return FcFalse; return FcFalse;
} }
@ -242,30 +255,30 @@ 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 (v.u.s); return FcStrHashIgnoreCase (FcObjectPtrU(v.u.si));
case FcTypeBool: case FcTypeBool:
return (FcChar32) v.u.b; return (FcChar32) v.u.b;
case FcTypeMatrix: case FcTypeMatrix:
return FcListMatrixHash (v.u.m); return FcListMatrixHash (FcMatrixPtrU(v.u.mi));
case FcTypeCharSet: case FcTypeCharSet:
return FcCharSetCount (v.u.c); return FcCharSetCount (FcCharSetPtrU(v.u.ci));
case FcTypeFTFace: case FcTypeFTFace:
return (long) v.u.f; return (long) v.u.f;
case FcTypeLangSet: case FcTypeLangSet:
return FcLangSetHash (v.u.l); return FcLangSetHash (FcLangSetPtrU(v.u.li));
} }
return 0; return 0;
} }
static FcChar32 static FcChar32
FcListValueListHash (FcValueList *list) FcListValueListHash (FcValueListPtr list)
{ {
FcChar32 h = 0; FcChar32 h = 0;
while (list) while (FcValueListPtrU(list))
{ {
h = h ^ FcListValueHash (list->value); h = h ^ FcListValueHash (FcValueListPtrU(list)->value);
list = list->next; list = FcValueListPtrU(list)->next;
} }
return h; return h;
} }
@ -280,7 +293,7 @@ FcListPatternHash (FcPattern *font,
for (n = 0; n < os->nobject; n++) for (n = 0; n < os->nobject; n++)
{ {
e = FcPatternFindElt (font, os->objects[n]); e = FcPatternFindElt (font, FcObjectPtrU(os->objects[n]));
if (e) if (e)
h = h ^ FcListValueListHash (e->values); h = h ^ FcListValueListHash (e->values);
} }
@ -334,7 +347,7 @@ FcListAppend (FcListHashTable *table,
{ {
int o; int o;
FcPatternElt *e; FcPatternElt *e;
FcValueList *v; FcValueListPtr v;
FcChar32 hash; FcChar32 hash;
FcListBucket **prev, *bucket; FcListBucket **prev, *bucket;
@ -358,14 +371,15 @@ FcListAppend (FcListHashTable *table,
for (o = 0; o < os->nobject; o++) for (o = 0; o < os->nobject; o++)
{ {
e = FcPatternFindElt (font, os->objects[o]); e = FcPatternFindElt (font, FcObjectPtrU(os->objects[o]));
if (e) if (e)
{ {
for (v = e->values; v; v = v->next) for (v = e->values; FcValueListPtrU(v);
v = FcValueListPtrU(v)->next)
{ {
if (!FcPatternAdd (bucket->pattern, if (!FcPatternAdd (bucket->pattern,
os->objects[o], FcObjectPtrU(os->objects[o]),
v->value, FcTrue)) FcValueListPtrU(v)->value, FcTrue))
goto bail2; goto bail2;
} }
} }

View File

@ -63,7 +63,8 @@ FcCompareString (char *object, FcValue value1, FcValue value2)
{ {
if (value2.type != FcTypeString || value1.type != FcTypeString) if (value2.type != FcTypeString || value1.type != FcTypeString)
return -1.0; return -1.0;
return (double) FcStrCmpIgnoreCase (value1.u.s, value2.u.s) != 0; return (double) FcStrCmpIgnoreCase
(FcObjectPtrU(value1.u.si), FcObjectPtrU(value2.u.si)) != 0;
} }
static double static double
@ -71,7 +72,8 @@ FcCompareFamily (char *object, FcValue value1, FcValue value2)
{ {
if (value2.type != FcTypeString || value1.type != FcTypeString) if (value2.type != FcTypeString || value1.type != FcTypeString)
return -1.0; return -1.0;
return (double) FcStrCmpIgnoreBlanksAndCase (value1.u.s, value2.u.s) != 0; return (double) FcStrCmpIgnoreBlanksAndCase
(FcObjectPtrU(value1.u.si), FcObjectPtrU(value2.u.si)) != 0;
} }
static double static double
@ -83,10 +85,12 @@ FcCompareLang (char *object, FcValue value1, FcValue value2)
case FcTypeLangSet: case FcTypeLangSet:
switch (value2.type) { switch (value2.type) {
case FcTypeLangSet: case FcTypeLangSet:
result = FcLangSetCompare (value1.u.l, value2.u.l); result = FcLangSetCompare (FcLangSetPtrU(value1.u.li),
FcLangSetPtrU(value2.u.li));
break; break;
case FcTypeString: case FcTypeString:
result = FcLangSetHasLang (value1.u.l, value2.u.s); result = FcLangSetHasLang (FcLangSetPtrU(value1.u.li),
FcObjectPtrU(value2.u.si));
break; break;
default: default:
return -1.0; return -1.0;
@ -95,10 +99,12 @@ FcCompareLang (char *object, FcValue value1, FcValue value2)
case FcTypeString: case FcTypeString:
switch (value2.type) { switch (value2.type) {
case FcTypeLangSet: case FcTypeLangSet:
result = FcLangSetHasLang (value2.u.l, value1.u.s); result = FcLangSetHasLang (FcLangSetPtrU(value2.u.li),
FcObjectPtrU(value1.u.si));
break; break;
case FcTypeString: case FcTypeString:
result = FcLangCompare (value1.u.s, value2.u.s); result = FcLangCompare (FcObjectPtrU(value1.u.si),
FcObjectPtrU(value2.u.si));
break; break;
default: default:
return -1.0; return -1.0;
@ -131,7 +137,8 @@ FcCompareCharSet (char *object, FcValue value1, FcValue value2)
{ {
if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet) if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet)
return -1.0; return -1.0;
return (double) FcCharSetSubtractCount (value1.u.c, value2.u.c); return (double) FcCharSetSubtractCount (FcCharSetPtrU(value1.u.ci),
FcCharSetPtrU(value2.u.ci));
} }
static double static double
@ -241,13 +248,13 @@ static FcMatcher _FcMatchers [] = {
static FcBool static FcBool
FcCompareValueList (const char *object, FcCompareValueList (const char *object,
FcValueList *v1orig, /* pattern */ FcValueListPtr v1orig, /* pattern */
FcValueList *v2orig, /* target */ FcValueListPtr v2orig, /* target */
FcValue *bestValue, FcValue *bestValue,
double *value, double *value,
FcResult *result) FcResult *result)
{ {
FcValueList *v1, *v2; FcValueListPtr v1, v2;
double v, best, bestStrong, bestWeak; double v, best, bestStrong, bestWeak;
int i; int i;
int j; int j;
@ -308,7 +315,7 @@ FcCompareValueList (const char *object,
(FcChar8 *) object) != 0) (FcChar8 *) object) != 0)
{ {
if (bestValue) if (bestValue)
*bestValue = v2orig->value; *bestValue = FcValueListPtrU(v2orig)->value;
return FcTrue; return FcTrue;
} }
#if 0 #if 0
@ -329,13 +336,15 @@ FcCompareValueList (const char *object,
bestStrong = 1e99; bestStrong = 1e99;
bestWeak = 1e99; bestWeak = 1e99;
j = 0; j = 0;
for (v1 = v1orig; v1; v1 = v1->next) for (v1 = v1orig; FcValueListPtrU(v1);
v1 = FcValueListPtrU(v1)->next)
{ {
for (v2 = v2orig; v2; v2 = v2->next) for (v2 = v2orig; FcValueListPtrU(v2);
v2 = FcValueListPtrU(v2)->next)
{ {
v = (*_FcMatchers[i].compare) (_FcMatchers[i].object, v = (*_FcMatchers[i].compare) (_FcMatchers[i].object,
v1->value, FcValueListPtrU(v1)->value,
v2->value); FcValueListPtrU(v2)->value);
if (v < 0) if (v < 0)
{ {
*result = FcResultTypeMismatch; *result = FcResultTypeMismatch;
@ -347,10 +356,10 @@ FcCompareValueList (const char *object,
if (v < best) if (v < best)
{ {
if (bestValue) if (bestValue)
*bestValue = v2->value; *bestValue = FcValueListPtrU(v2)->value;
best = v; best = v;
} }
if (v1->binding == FcValueBindingStrong) if (FcValueListPtrU(v1)->binding == FcValueBindingStrong)
{ {
if (v < bestStrong) if (v < bestStrong)
bestStrong = v; bestStrong = v;
@ -406,16 +415,17 @@ FcCompare (FcPattern *pat,
i2 = 0; i2 = 0;
while (i1 < pat->num && i2 < fnt->num) while (i1 < pat->num && i2 < fnt->num)
{ {
i = pat->elts[i1].object - fnt->elts[i2].object; i = FcObjectPtrCompare((FcPatternEltU(pat->elts)+i1)->object,
(FcPatternEltU(fnt->elts)+i2)->object);
if (i > 0) if (i > 0)
i2++; i2++;
else if (i < 0) else if (i < 0)
i1++; i1++;
else else
{ {
if (!FcCompareValueList (pat->elts[i1].object, if (!FcCompareValueList (FcObjectPtrU((FcPatternEltU(pat->elts)+i1)->object),
pat->elts[i1].values, (FcPatternEltU(pat->elts)+i1)->values,
fnt->elts[i2].values, (FcPatternEltU(fnt->elts)+i2)->values,
0, 0,
value, value,
result)) result))
@ -456,11 +466,11 @@ FcFontRenderPrepare (FcConfig *config,
return 0; return 0;
for (i = 0; i < font->num; i++) for (i = 0; i < font->num; i++)
{ {
fe = &font->elts[i]; fe = FcPatternEltU(font->elts)+i;
pe = FcPatternFindElt (pat, fe->object); pe = FcPatternFindElt (pat, FcObjectPtrU(fe->object));
if (pe) if (pe)
{ {
if (!FcCompareValueList (pe->object, pe->values, if (!FcCompareValueList (FcObjectPtrU(pe->object), pe->values,
fe->values, &v, 0, &result)) fe->values, &v, 0, &result))
{ {
FcPatternDestroy (new); FcPatternDestroy (new);
@ -468,15 +478,16 @@ FcFontRenderPrepare (FcConfig *config,
} }
} }
else else
v = fe->values->value; v = FcValueListPtrU(fe->values)->value;
FcPatternAdd (new, 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++)
{ {
pe = &pat->elts[i]; pe = FcPatternEltU(pat->elts)+i;
fe = FcPatternFindElt (font, pe->object); fe = FcPatternFindElt (font, FcObjectPtrU(pe->object));
if (!fe) if (!fe)
FcPatternAdd (new, pe->object, pe->values->value, FcTrue); FcPatternAdd (new, FcObjectPtrU(pe->object),
FcValueListPtrU(pe->values)->value, FcTrue);
} }
FcConfigSubstituteWithPat (config, new, pat, FcMatchFont); FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
return new; return new;

View File

@ -27,7 +27,11 @@
#include <ctype.h> #include <ctype.h>
#include "fcint.h" #include "fcint.h"
const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 }; FcMatrix _id = { 1, 0, 0, 1 };
const FcMatrixPtr FcIdentityMatrix = {
.storage = FcStorageDynamic,
.u.dyn = &_id
};
FcMatrix * FcMatrix *
FcMatrixCopy (const FcMatrix *mat) FcMatrixCopy (const FcMatrix *mat)
@ -43,10 +47,17 @@ 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 != &FcIdentityMatrix) if (mat != FcMatrixPtrU(FcIdentityMatrix))
{ {
FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix)); FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix));
free (mat); free (mat);
@ -115,3 +126,59 @@ 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;
}

View File

@ -321,7 +321,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.s = string; v.u.si = FcObjectPtrCreateDynamic(string);
break; break;
case FcTypeBool: case FcTypeBool:
if (!FcNameBool (string, &v.u.b)) if (!FcNameBool (string, &v.u.b))
@ -331,14 +331,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.m = m; v.u.mi = FcMatrixPtrCreateDynamic(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.c = FcNameParseCharSet (string); v.u.ci = FcCharSetPtrCreateDynamic(FcNameParseCharSet (string));
break; break;
case FcTypeLangSet: case FcTypeLangSet:
v.u.l = FcNameParseLangSet (string); v.u.li = FcLangSetPtrCreateDynamic(FcNameParseLangSet (string));
break; break;
default: default:
break; break;
@ -436,10 +436,10 @@ FcNameParse (const FcChar8 *name)
{ {
switch (v.type) { switch (v.type) {
case FcTypeCharSet: case FcTypeCharSet:
FcCharSetDestroy ((FcCharSet *) v.u.c); FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci));
break; break;
case FcTypeLangSet: case FcTypeLangSet:
FcLangSetDestroy ((FcLangSet *) v.u.l); FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li));
break; break;
default: default:
break; break;
@ -448,10 +448,10 @@ FcNameParse (const FcChar8 *name)
} }
switch (v.type) { switch (v.type) {
case FcTypeCharSet: case FcTypeCharSet:
FcCharSetDestroy ((FcCharSet *) v.u.c); FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci));
break; break;
case FcTypeLangSet: case FcTypeLangSet:
FcLangSetDestroy ((FcLangSet *) v.u.l); FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li));
break; break;
default: default:
break; break;
@ -518,17 +518,20 @@ 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, v.u.s, escape); return FcNameUnparseString (buf, FcObjectPtrU(v.u.si), 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",
v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy); m->xx, m->xy, m->yx, m->yy);
return FcNameUnparseString (buf, temp, 0); return FcNameUnparseString (buf, temp, 0);
}
case FcTypeCharSet: case FcTypeCharSet:
return FcNameUnparseCharSet (buf, v.u.c); return FcNameUnparseCharSet (buf, FcCharSetPtrU(v.u.ci));
case FcTypeLangSet: case FcTypeLangSet:
return FcNameUnparseLangSet (buf, v.u.l); return FcNameUnparseLangSet (buf, FcLangSetPtrU(v.u.li));
case FcTypeFTFace: case FcTypeFTFace:
return FcTrue; return FcTrue;
} }
@ -537,14 +540,14 @@ FcNameUnparseValue (FcStrBuf *buf,
static FcBool static FcBool
FcNameUnparseValueList (FcStrBuf *buf, FcNameUnparseValueList (FcStrBuf *buf,
FcValueList *v, FcValueListPtr v,
FcChar8 *escape) FcChar8 *escape)
{ {
while (v) while (FcValueListPtrU(v))
{ {
if (!FcNameUnparseValue (buf, v->value, escape)) if (!FcNameUnparseValue (buf, FcValueListPtrU(v)->value, escape))
return FcFalse; return FcFalse;
if ((v = v->next)) if (FcValueListPtrU(v = FcValueListPtrU(v)->next))
if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0)) if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
return FcFalse; return FcFalse;
} }

File diff suppressed because it is too large Load Diff

View File

@ -848,10 +848,67 @@ FcStrSetCreate (void)
set->ref = 1; set->ref = 1;
set->num = 0; set->num = 0;
set->size = 0; set->size = 0;
set->strs = 0; set->storage = FcStorageDynamic;
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)
{ {
@ -860,7 +917,7 @@ _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
FcStrFree (s); FcStrFree (s);
return FcTrue; return FcTrue;
} }
if (set->num == set->size) if (set->num == set->size || set->storage == FcStorageStatic)
{ {
FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *)); FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
@ -868,14 +925,24 @@ _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->num) if (set->storage == FcStorageDynamic)
memcpy (strs, set->strs, set->num * sizeof (FcChar8 *)); {
if (set->strs) if (set->num)
free (set->strs); memcpy (strs, set->u.strs, set->num * sizeof (FcChar8 *));
set->strs = strs; if (set->u.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->strs[set->num++] = s; set->u.strs[set->num++] = s;
set->strs[set->num] = 0; set->u.strs[set->num] = 0;
return FcTrue; return FcTrue;
} }
@ -885,7 +952,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 (set->strs[i], s)) if (!FcStrCmp (FcStrSetGet(set, i), s))
return FcTrue; return FcTrue;
return FcFalse; return FcFalse;
} }
@ -897,7 +964,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, sa->strs[i])) if (!FcStrSetMember (sb, FcStrSetGet(sa, i)))
return FcFalse; return FcFalse;
return FcTrue; return FcTrue;
} }
@ -936,14 +1003,15 @@ 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 (set->strs[i], s)) if (!FcStrCmp (FcStrSetGet(set, i), s))
{ {
FcStrFree (set->strs[i]); if (set->storage == FcStorageDynamic)
FcStrFree (set->u.strs[i]);
/* /*
* copy remaining string pointers and trailing * copy remaining string pointers and trailing
* NULL * NULL
*/ */
memmove (&set->strs[i], &set->strs[i+1], memmove (FcStrSetGet(set, i), FcStrSetGet(set, i+1),
(set->num - i) * sizeof (FcChar8 *)); (set->num - i) * sizeof (FcChar8 *));
set->num--; set->num--;
return FcTrue; return FcTrue;
@ -958,16 +1026,123 @@ FcStrSetDestroy (FcStrSet *set)
{ {
int i; int i;
for (i = 0; i < set->num; i++) if (set->storage == FcStorageDynamic)
FcStrFree (set->strs[i]); {
FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *)); for (i = 0; i < set->num; i++)
if (set->strs) FcStrFree (set->u.strs[i]);
free (set->strs); FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet)); if (set->u.strs)
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 LangSet.
// should hash LangSets or something.
// FcStrSetDestroy (set);
return newp;
bail3:
free (strset_idx);
bail2:
free (strsets);
bail1:
return FcStrSetPtrCreateDynamic(0);
}
FcStrList * FcStrList *
FcStrListCreate (FcStrSet *set) FcStrListCreate (FcStrSet *set)
{ {
@ -988,7 +1163,7 @@ FcStrListNext (FcStrList *list)
{ {
if (list->n >= list->set->num) if (list->n >= list->set->num)
return 0; return 0;
return list->set->strs[list->n++]; return FcStrSetGet(list->set, 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.s = FcStrCopy (vstack->u.string); value.u.si = FcObjectPtrCreateDynamic(FcStrCopy (vstack->u.string));
if (value.u.s) if (FcObjectPtrU(value.u.si))
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.m = FcMatrixCopy (vstack->u.matrix); value.u.mi = FcMatrixPtrCreateDynamic(FcMatrixCopy (vstack->u.matrix));
if (value.u.m) if (FcMatrixPtrU(value.u.mi))
value.type = FcTypeMatrix; value.type = FcTypeMatrix;
break; break;
case FcVStackBool: case FcVStackBool:
@ -2281,10 +2281,9 @@ FcConfigParseAndLoadDir (FcConfig *config,
if (ret) if (ret)
{ {
int i; int i;
qsort (files->strs, files->num, sizeof (FcChar8 *), FcStrSetSort (files);
(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, files->strs[i], complain); ret = FcConfigParseAndLoad (config, FcStrSetGet(files, i), complain);
} }
bail3: bail3:
FcStrSetDestroy (files); FcStrSetDestroy (files);