diff --git a/fc-lang/fc-lang.c b/fc-lang/fc-lang.c index e88d75f..a2699a3 100644 --- a/fc-lang/fc-lang.c +++ b/fc-lang/fc-lang.c @@ -220,7 +220,7 @@ main (int argc, char **argv) FILE *f; int ncountry = 0; int i = 0; - FcCharLeaf **leaves, **sleaves; + FcCharLeaf **leaves; int total_leaves = 0; int l, sl, tl; int c; @@ -268,14 +268,13 @@ main (int argc, char **argv) */ for (i = 0; sets[i]; i++) { - sleaves = sets[i]->leaves; for (sl = 0; sl < sets[i]->num; sl++) { for (l = 0; l < tl; l++) - if (leaves[l] == sleaves[sl]) + if (leaves[l] == FcCharSetGetLeaf(sets[i], sl)) break; 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) printf (" "); for (l = 0; l < tl; l++) - if (leaves[l] == sets[i]->leaves[n]) + if (leaves[l] == FcCharSetGetLeaf(sets[i], n)) break; if (l == tl) fatal (names[i], 0, "can't find leaf"); @@ -377,7 +376,7 @@ main (int argc, char **argv) { if (n % 8 == 0) printf (" "); - printf (" 0x%04x,", sets[i]->numbers[n]); + printf (" 0x%04x,", FcCharSetGetNumbers(sets[i])[n]); if (n % 8 == 7) printf ("\n"); } @@ -399,9 +398,9 @@ main (int argc, char **argv) if (j < 0) j = i; printf (" { (FcChar8 *) \"%s\",\n" - " { FC_REF_CONSTANT, %d, " - "(FcCharLeaf **) leaves_%s, " - "(FcChar16 *) numbers_%s } },\n", + " { FC_REF_CONSTANT, %d, FcStorageDynamic, " + "{ { (FcCharLeaf **) leaves_%s, " + "(FcChar16 *) numbers_%s } } } },\n", langs[i], sets[j]->num, names[j], names[j]); } diff --git a/fontconfig/fcprivate.h b/fontconfig/fcprivate.h index ac68bfc..2b73945 100644 --- a/fontconfig/fcprivate.h +++ b/fontconfig/fcprivate.h @@ -59,22 +59,22 @@ __v__.u.d = va_arg (va, double); \ break; \ case FcTypeString: \ - __v__.u.s = va_arg (va, FcChar8 *); \ + __v__.u.si = va_arg (va, FcObjectPtr); \ break; \ case FcTypeBool: \ __v__.u.b = va_arg (va, FcBool); \ break; \ case FcTypeMatrix: \ - __v__.u.m = va_arg (va, FcMatrix *); \ + __v__.u.mi = va_arg (va, FcMatrixPtr); \ break; \ case FcTypeCharSet: \ - __v__.u.c = va_arg (va, FcCharSet *); \ + __v__.u.ci = va_arg (va, FcCharSetPtr); \ break; \ case FcTypeFTFace: \ __v__.u.f = va_arg (va, FT_Face); \ break; \ case FcTypeLangSet: \ - __v__.u.l = va_arg (va, FcLangSet *); \ + __v__.u.li = va_arg (va, FcLangSetPtr); \ break; \ } \ if (!FcPatternAdd (__p__, __o__, __v__, FcTrue)) \ diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h index 79e9cfd..1bc7262 100644 --- a/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig.h @@ -196,22 +196,59 @@ 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 struct _FcObjectPtr { + FcStorage storage; + union { + int stat; + const FcChar8 * dyn; + } u; + FcChar32 hash; +} FcObjectPtr; + typedef struct _FcValue { FcType type; union { - const FcChar8 *s; + FcObjectPtr si; int i; FcBool b; double d; - const FcMatrix *m; - const FcCharSet *c; + FcMatrixPtr mi; + FcCharSetPtr ci; void *f; const FcPattern *p; - const FcLangSet *l; + FcLangSetPtr li; } u; } FcValue; @@ -224,7 +261,7 @@ typedef struct _FcFontSet { typedef struct _FcObjectSet { int nobject; int sobject; - const char **objects; + FcObjectPtr *objects; } FcObjectSet; typedef enum _FcMatchKind { @@ -618,6 +655,9 @@ FcMatrixScale (FcMatrix *m, double sx, double sy); void FcMatrixShear (FcMatrix *m, double sh, double sv); +FcMatrix * +FcMatrixPtrU (FcMatrixPtr mi); + /* fcname.c */ FcBool diff --git a/src/fccache.c b/src/fccache.c index 2845543..a9d8701 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -1166,3 +1166,35 @@ bail1: bail0: 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; +} diff --git a/src/fccfg.c b/src/fccfg.c index 84c21e7..1ce7cbe 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -550,12 +550,13 @@ FcConfigPromote (FcValue v, FcValue u) } else if (v.type == FcTypeVoid && u.type == FcTypeMatrix) { - v.u.m = &FcIdentityMatrix; + v.u.mi = FcIdentityMatrix; v.type = FcTypeMatrix; } 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; } return v; @@ -623,16 +624,19 @@ FcConfigCompareValue (const FcValue left_o, switch (op) { case FcOpEqual: case FcOpListing: - ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0; + ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si), + FcObjectPtrU(right.u.si)) == 0; break; case FcOpContains: - ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0; + ret = FcStrStrIgnoreCase (FcObjectPtrU(left.u.si), + FcObjectPtrU(right.u.si)) != 0; break; case FcOpNotEqual: ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0; break; case FcOpNotContains: - ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0; + ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si), + FcObjectPtrU(right.u.si)) == 0; break; default: break; @@ -643,11 +647,11 @@ FcConfigCompareValue (const FcValue left_o, case FcOpEqual: case FcOpContains: case FcOpListing: - ret = FcMatrixEqual (left.u.m, right.u.m); + ret = FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi)); break; case FcOpNotEqual: case FcOpNotContains: - ret = !FcMatrixEqual (left.u.m, right.u.m); + ret = !FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi)); break; default: break; @@ -658,17 +662,17 @@ FcConfigCompareValue (const FcValue left_o, case FcOpContains: case FcOpListing: /* 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; case FcOpNotContains: /* 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; case FcOpEqual: - ret = FcCharSetEqual (left.u.c, right.u.c); + ret = FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci)); break; case FcOpNotEqual: - ret = !FcCharSetEqual (left.u.c, right.u.c); + ret = !FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci)); break; default: break; @@ -678,16 +682,16 @@ FcConfigCompareValue (const FcValue left_o, switch (op) { case FcOpContains: case FcOpListing: - ret = FcLangSetContains (left.u.l, right.u.l); + ret = FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li)); break; case FcOpNotContains: - ret = !FcLangSetContains (left.u.l, right.u.l); + ret = !FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li)); break; case FcOpEqual: - ret = FcLangSetEqual (left.u.l, right.u.l); + ret = FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li)); break; case FcOpNotEqual: - ret = !FcLangSetEqual (left.u.l, right.u.l); + ret = !FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li)); break; default: break; @@ -755,17 +759,17 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) break; case FcOpString: v.type = FcTypeString; - v.u.s = e->u.sval; + v.u.si = FcObjectPtrCreateDynamic(e->u.sval); v = FcValueSave (v); break; case FcOpMatrix: v.type = FcTypeMatrix; - v.u.m = e->u.mval; + v.u.mi = FcMatrixPtrCreateDynamic(e->u.mval); v = FcValueSave (v); break; case FcOpCharSet: v.type = FcTypeCharSet; - v.u.c = e->u.cval; + v.u.ci = FcCharSetPtrCreateDynamic(e->u.cval); v = FcValueSave (v); break; case FcOpBool: @@ -873,8 +877,11 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) switch (e->op) { case FcOpPlus: v.type = FcTypeString; - v.u.s = FcStrPlus (vl.u.s, vr.u.s); - if (!v.u.s) + v.u.si = FcObjectPtrCreateDynamic + (FcStrPlus (FcObjectPtrU(vl.u.si), + FcObjectPtrU(vr.u.si))); + + if (!FcObjectPtrU(v.u.si)) v.type = FcTypeVoid; break; default: @@ -890,8 +897,9 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) if (m) { FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix)); - FcMatrixMultiply (m, vl.u.m, vr.u.m); - v.u.m = m; + FcMatrixMultiply (m, FcMatrixPtrU(vl.u.mi), + FcMatrixPtrU(vr.u.mi)); + v.u.mi = FcMatrixPtrCreateDynamic(m); } else { @@ -1021,7 +1029,7 @@ FcConfigMatchValueList (FcPattern *p, 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 */ if (FcConfigCompareValue (v->value, t->op, value)) @@ -1047,6 +1055,7 @@ static FcValueList * FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding) { FcValueList *l; + FcValueListPtr lp; if (!e) return 0; @@ -1057,56 +1066,63 @@ FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding) if (e->op == FcOpComma) { 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 { l->value = FcConfigEvaluate (p, e); - l->next = 0; + l->next = FcValueListPtrCreateDynamic(0); } l->binding = binding; - while (l && l->value.type == FcTypeVoid) + lp = FcValueListPtrCreateDynamic(l); + while (FcValueListPtrU(lp) && FcValueListPtrU(lp)->value.type == FcTypeVoid) { - FcValueList *next = l->next; - - FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); - free (l); - l = next; + FcValueListPtr next = FcValueListPtrU(lp)->next; + + if (lp.storage == FcStorageDynamic) + { + FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); + free (l); + } + lp = next; } return l; } static FcBool -FcConfigAdd (FcValueList **head, +FcConfigAdd (FcValueListPtr *head, FcValueList *position, FcBool append, FcValueList *new) { - FcValueList **prev, *last, *v; + FcValueListPtr *prev, last, v; FcValueBinding sameBinding; if (position) sameBinding = position->binding; else sameBinding = FcValueBindingWeak; - for (v = new; v; v = v->next) - if (v->binding == FcValueBindingSame) - v->binding = sameBinding; + for (v = FcValueListPtrCreateDynamic(new); FcValueListPtrU(v); + v = FcValueListPtrU(v)->next) + if (FcValueListPtrU(v)->binding == FcValueBindingSame) + FcValueListPtrU(v)->binding = sameBinding; if (append) { if (position) prev = &position->next; else - for (prev = head; *prev; prev = &(*prev)->next) + for (prev = head; FcValueListPtrU(*prev); + prev = &(FcValueListPtrU(*prev)->next)) ; } else { 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; } } @@ -1115,7 +1131,7 @@ FcConfigAdd (FcValueList **head, if (FcDebug () & FC_DBG_EDIT) { - if (!*prev) + if (!FcValueListPtrU(*prev)) printf ("position not on list\n"); } } @@ -1129,12 +1145,12 @@ FcConfigAdd (FcValueList **head, if (new) { - last = new; - while (last->next) - last = last->next; + last = FcValueListPtrCreateDynamic(new); + while (FcValueListPtrU(FcValueListPtrU(last)->next)) + last = FcValueListPtrU(last)->next; - last->next = *prev; - *prev = new; + FcValueListPtrU(last)->next = *prev; + *prev = FcValueListPtrCreateDynamic(new); } if (FcDebug () & FC_DBG_EDIT) @@ -1148,18 +1164,19 @@ FcConfigAdd (FcValueList **head, } static void -FcConfigDel (FcValueList **head, +FcConfigDel (FcValueListPtr *head, 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; - position->next = 0; - FcValueListDestroy (position); + position->next = FcValueListPtrCreateDynamic(0); + FcValueListDestroy (FcValueListPtrCreateDynamic(position)); break; } } @@ -1191,8 +1208,8 @@ FcConfigPatternDel (FcPattern *p, FcPatternElt *e = FcPatternFindElt (p, object); if (!e) return; - while (e->values) - FcConfigDel (&e->values, e->values); + while (FcValueListPtrU(e->values)) + FcConfigDel (&e->values, FcValueListPtrU(e->values)); } static void @@ -1202,7 +1219,7 @@ FcConfigPatternCanon (FcPattern *p, FcPatternElt *e = FcPatternFindElt (p, object); if (!e) return; - if (!e->values) + if (!FcValueListPtrU(e->values)) FcPatternDel (p, object); } @@ -1281,12 +1298,12 @@ FcConfigSubstituteWithPat (FcConfig *config, * Check to see if there is a match, mark the location * 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) 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; - if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values) + if (t->qual == FcQualNotFirst && st[i].value == FcValueListPtrU(st[i].elt->values)) break; } if (t) @@ -1339,7 +1356,7 @@ FcConfigSubstituteWithPat (FcConfig *config, if (t) { 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 @@ -1840,7 +1857,7 @@ FcConfigGlobsMatch (const FcStrSet *globs, int i; for (i = 0; i < globs->num; i++) - if (FcConfigGlobMatch (globs->strs[i], string)) + if (FcConfigGlobMatch (FcStrSetGet(globs, i), string)) return FcTrue; return FcFalse; } diff --git a/src/fccharset.c b/src/fccharset.c index 8003bcc..6c6f0f5 100644 --- a/src/fccharset.c +++ b/src/fccharset.c @@ -29,6 +29,27 @@ /* #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 * FcCharSetCreate (void) { @@ -40,8 +61,9 @@ FcCharSetCreate (void) FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet)); fcs->ref = 1; fcs->num = 0; - fcs->leaves = 0; - fcs->numbers = 0; + fcs->storage = FcStorageDynamic; + fcs->u.dyn.leaves = 0; + fcs->u.dyn.numbers = 0; return fcs; } @@ -54,6 +76,17 @@ FcCharSetNew (void) 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 FcCharSetDestroy (FcCharSet *fcs) @@ -63,20 +96,23 @@ FcCharSetDestroy (FcCharSet *fcs) return; if (--fcs->ref > 0) return; - for (i = 0; i < fcs->num; i++) + if (fcs->storage == FcStorageDynamic) { - FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf)); - free (fcs->leaves[i]); - } - if (fcs->leaves) - { - FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *)); - free (fcs->leaves); - } - if (fcs->numbers) - { - FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16)); - free (fcs->numbers); + for (i = 0; i < fcs->num; i++) + { + FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf)); + free (fcs->u.dyn.leaves[i]); + } + if (fcs->u.dyn.leaves) + { + FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *)); + free (fcs->u.dyn.leaves); + } + if (fcs->u.dyn.numbers) + { + FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16)); + free (fcs->u.dyn.numbers); + } } FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet)); free (fcs); @@ -91,7 +127,7 @@ FcCharSetDestroy (FcCharSet *fcs) static int FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4) { - FcChar16 *numbers = fcs->numbers; + FcChar16 *numbers = FcCharSetGetNumbers(fcs); FcChar16 page; int low = 0; int high = fcs->num - 1; @@ -120,7 +156,7 @@ FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4) { int pos = FcCharSetFindLeafPos (fcs, ucs4); if (pos >= 0) - return fcs->leaves[pos]; + return FcCharSetGetLeaf(fcs, pos); return 0; } @@ -136,33 +172,55 @@ FcCharSetPutLeaf (FcCharSet *fcs, ucs4 >>= 8; if (ucs4 >= 0x10000) return FcFalse; - if (!fcs->leaves) - leaves = malloc (sizeof (FcCharLeaf *)); + if (fcs->storage == FcStorageStatic) + { + int i; + + 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 - 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; + { + 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->leaves + pos + 1, fcs->leaves + pos, + memmove (fcs->u.dyn.leaves + pos + 1, fcs->u.dyn.leaves + pos, (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->numbers[pos] = (FcChar16) ucs4; - fcs->leaves[pos] = leaf; + fcs->u.dyn.numbers[pos] = (FcChar16) ucs4; + fcs->u.dyn.leaves[pos] = leaf; fcs->num++; return FcTrue; } @@ -180,7 +238,7 @@ FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4) pos = FcCharSetFindLeafPos (fcs, ucs4); if (pos >= 0) - return fcs->leaves[pos]; + return FcCharSetGetLeaf(fcs, pos); leaf = calloc (1, sizeof (FcCharLeaf)); if (!leaf) @@ -205,8 +263,15 @@ FcCharSetInsertLeaf (FcCharSet *fcs, FcChar32 ucs4, FcCharLeaf *leaf) if (pos >= 0) { FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf)); - free (fcs->leaves[pos]); - fcs->leaves[pos] = leaf; + if (fcs->storage == FcStorageDynamic) + { + 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; } pos = -pos - 1; @@ -257,9 +322,9 @@ FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter) iter->leaf = 0; 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; #ifdef CHATTY printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf); @@ -277,8 +342,8 @@ FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter) } else { - iter->ucs4 = (FcChar32) fcs->numbers[pos] << 8; - iter->leaf = fcs->leaves[pos]; + iter->ucs4 = (FcChar32) FcCharSetGetNumbers(fcs)[pos] << 8; + iter->leaf = FcCharSetGetLeaf(fcs, pos); iter->pos = pos; } } @@ -594,15 +659,15 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b) ai = 0; while (ai < a->num && bi < b->num) { - an = a->numbers[ai]; - bn = b->numbers[bi]; + an = FcCharSetGetNumbers(a)[ai]; + bn = FcCharSetGetNumbers(b)[bi]; /* * Check matching pages */ if (an == bn) { - FcChar32 *am = a->leaves[ai]->map; - FcChar32 *bm = b->leaves[bi]->map; + FcChar32 *am = FcCharSetGetLeaf(a, ai)->map; + FcChar32 *bm = FcCharSetGetLeaf(b, bi)->map; if (am != bm) { @@ -633,7 +698,7 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b) while (low <= high) { int mid = (low + high) >> 1; - bn = b->numbers[mid]; + bn = FcCharSetGetNumbers(b)[mid]; if (bn == an) { high = mid; @@ -645,7 +710,7 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b) high = mid - 1; } bi = high; - while (bi < b->num && b->numbers[bi] < an) + while (bi < b->num && FcCharSetGetNumbers(b)[bi] < an) bi++; } } @@ -949,16 +1014,14 @@ static FcChar32 FcCharSetHash (FcCharSet *fcs) { FcChar32 hash = 0; - FcChar32 *p; int i; /* hash in leaves */ - p = (FcChar32 *) fcs->leaves; 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 */ for (i = 0; i < fcs->num; i++) - hash = ((hash << 1) | (hash >> 31)) ^ fcs->numbers[i]; + hash = ((hash << 1) | (hash >> 31)) ^ *FcCharSetGetNumbers(fcs); return hash; } @@ -982,12 +1045,18 @@ FcCharSetFreezeBase (FcCharSet *fcs) { if (ent->hash == hash && ent->set.num == fcs->num && - !memcmp (ent->set.leaves, fcs->leaves, - fcs->num * sizeof (FcCharLeaf *)) && - !memcmp (ent->set.numbers, fcs->numbers, + !memcmp (FcCharSetGetNumbers(&ent->set), + FcCharSetGetNumbers(fcs), 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.num = fcs->num; - if (fcs->num) + ent->set.storage = fcs->storage; + if (fcs->storage == FcStorageDynamic) { - ent->set.leaves = (FcCharLeaf **) (ent + 1); - ent->set.numbers = (FcChar16 *) (ent->set.leaves + fcs->num); - memcpy (ent->set.leaves, fcs->leaves, fcs->num * sizeof (FcCharLeaf *)); - memcpy (ent->set.numbers, fcs->numbers, fcs->num * sizeof (FcChar16)); + if (fcs->num) + { + ent->set.u.dyn.leaves = (FcCharLeaf **) (ent + 1); + 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 { - ent->set.leaves = 0; - ent->set.numbers = 0; + ent->set.u.stat.leafidx_offset = fcs->u.stat.leafidx_offset; + ent->set.u.stat.numbers_offset = fcs->u.stat.numbers_offset; } ent->hash = hash; @@ -1059,23 +1137,26 @@ FcCharSetFreeze (FcCharSet *fcs) goto bail0; for (i = 0; i < fcs->num; i++) { - l = FcCharSetFreezeLeaf (fcs->leaves[i]); + l = FcCharSetFreezeLeaf (FcCharSetGetLeaf(fcs, i)); if (!l) goto bail1; - if (!FcCharSetInsertLeaf (b, fcs->numbers[i] << 8, l)) + if (!FcCharSetInsertLeaf (b, FcCharSetGetNumbers(fcs)[i] << 8, l)) goto bail1; } n = FcCharSetFreezeBase (b); bail1: - if (b->leaves) + if (b->storage == FcStorageDynamic) { - FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *)); - free (b->leaves); - } - if (b->numbers) - { - FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16)); - free (b->numbers); + if (b->u.dyn.leaves) + { + FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *)); + free (b->u.dyn.leaves); + } + if (b->u.dyn.numbers) + { + FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16)); + free (b->u.dyn.numbers); + } } FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet)); free (b); @@ -1141,17 +1222,20 @@ FcNameParseCharSet (FcChar8 *string) #endif n = FcCharSetFreezeBase (c); bail1: - if (c->leaves) + if (c->storage == FcStorageDynamic) { - FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *)); - free (c->leaves); + if (c->u.dyn.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); bail0: return n; @@ -1229,3 +1313,116 @@ FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c) 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; + } +} + diff --git a/src/fcdbg.c b/src/fcdbg.c index cd72eda..c8b7127 100644 --- a/src/fcdbg.c +++ b/src/fcdbg.c @@ -40,20 +40,24 @@ FcValuePrint (const FcValue v) printf (" %g(f)", v.u.d); break; case FcTypeString: - printf (" \"%s\"", v.u.s); + printf (" \"%s\"", FcObjectPtrU(v.u.si)); break; case FcTypeBool: printf (" %s", v.u.b ? "FcTrue" : "FcFalse"); break; 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; + } case FcTypeCharSet: /* XXX */ printf (" set"); break; case FcTypeLangSet: printf (" "); - FcLangSetPrint (v.u.l); + FcLangSetPrint (FcLangSetPtrU(v.u.li)); break; case FcTypeFTFace: printf (" face"); @@ -62,12 +66,12 @@ FcValuePrint (const FcValue v) } void -FcValueListPrint (const FcValueList *l) +FcValueListPrint (FcValueListPtr l) { - for (; l; l = l->next) + for (; FcValueListPtrU(l); l = FcValueListPtrU(l)->next) { - FcValuePrint (l->value); - switch (l->binding) { + FcValuePrint (FcValueListPtrU(l)->value); + switch (FcValueListPtrU(l)->binding) { case FcValueBindingWeak: printf ("(w)"); break; @@ -89,9 +93,9 @@ FcLangSetPrint (const FcLangSet *ls) FcStrBufInit (&buf, init_buf, sizeof (init_buf)); if (FcNameUnparseLangSet (&buf, ls) && FcStrBufChar (&buf,'\0')) - printf ("%s", buf.buf); + printf ("%s", buf.buf); else - printf ("langset (alloc error)"); + printf ("langset (alloc error)"); FcStrBufDestroy (&buf); } @@ -109,8 +113,8 @@ FcPatternPrint (const FcPattern *p) printf ("Pattern %d of %d\n", p->num, p->size); for (i = 0; i < p->num; i++) { - e = &p->elts[i]; - printf ("\t%s:", e->object); + e = FcPatternEltU(p->elts) + i; + printf ("\t%s:", FcObjectPtrU(e->object)); FcValueListPrint (e->values); printf ("\n"); } diff --git a/src/fcfs.c b/src/fcfs.c index b05688d..c202040 100644 --- a/src/fcfs.c +++ b/src/fcfs.c @@ -80,3 +80,39 @@ FcFontSetAdd (FcFontSet *s, FcPattern *font) s->fonts[s->nfont++] = font; 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(); +} diff --git a/src/fcint.h b/src/fcint.h index 24bf246..fe2c095 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -41,6 +41,7 @@ #include #endif +/* unused */ typedef struct _FcSymbolic { const char *name; int value; @@ -108,22 +109,46 @@ typedef enum _FcValueBinding { FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame } 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 { - struct _FcValueList *next; + FcValueListPtr next; + FcValue value; FcValueBinding binding; } FcValueList; -typedef struct _FcPatternElt { - const char *object; - FcValueList *values; -} FcPatternElt; +typedef struct _FcPatternEltPtr { + FcStorage storage; + union { + int stat; + struct _FcPatternElt *dyn; + } u; +} FcPatternEltPtr; +typedef struct _FcPatternElt { + FcObjectPtr object; + FcValueListPtr values; +} FcPatternElt; struct _FcPattern { int num; int size; - FcPatternElt *elts; + FcPatternEltPtr elts; int ref; }; @@ -197,15 +222,28 @@ typedef struct _FcCharLeaf { struct _FcCharSet { int ref; /* reference count */ int num; /* size of leaves and numbers arrays */ - FcCharLeaf **leaves; - FcChar16 *numbers; + FcStorage storage; + union { + struct { + FcCharLeaf **leaves; + FcChar16 *numbers; + } dyn; + struct { + int leafidx_offset; + int numbers_offset; + } stat; + } u; }; struct _FcStrSet { int ref; /* reference count */ int num; int size; - FcChar8 **strs; + FcStorage storage; + union { + FcChar8 **strs; + int stridx_offset; + } u; }; struct _FcStrList { @@ -527,9 +565,30 @@ FcNameParseCharSet (FcChar8 *string); FcCharLeaf * 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 */ void -FcValueListPrint (const FcValueList *l); +FcValueListPrint (const FcValueListPtr l); void FcLangSetPrint (const FcLangSet *ls); @@ -552,6 +611,9 @@ FcSubstPrint (const FcSubst *subst); int FcDebug (void); +FcCharSet * +FcCharSetPtrU (FcCharSetPtr mi); + /* fcdir.c */ FcBool @@ -596,6 +658,16 @@ const FcCharMap * FcFreeTypeGetPrivateMap (FT_Encoding encoding); /* fcfs.c */ + +void +FcFontSetClearStatic (void); + +FcBool +FcFontSetPrepareSerialize (FcFontSet * s); + +FcBool +FcFontSetSerialize (FcFontSet * s); + /* fcgram.y */ int FcConfigparse (void); @@ -676,6 +748,24 @@ FcNameParseLangSet (const FcChar8 *string); FcBool 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 */ FcBool @@ -684,6 +774,18 @@ FcListPatternMatchAny (const FcPattern *p, /* fcmatch.c */ +/* fcmmap.c */ + +void +FcCacheClearStatic(void); + +FcBool +FcCachePrepareSerialize(FcConfig * config); + +FcBool +FcCacheSerialize (FcConfig * config); + + /* fcname.c */ FcBool @@ -691,8 +793,8 @@ FcNameBool (const FcChar8 *v, FcBool *result); /* fcpat.c */ void -FcValueListDestroy (FcValueList *l); - +FcValueListDestroy (FcValueListPtr l); + FcPatternElt * FcPatternFindElt (const FcPattern *p, const char *object); @@ -715,19 +817,100 @@ FcPatternThawAll (void); FcBool FcPatternAppend (FcPattern *p, FcPattern *s); -const char * +void +FcObjectClearStatic(void); + +FcObjectPtr 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 */ /* fcmatrix.c */ -extern const FcMatrix FcIdentityMatrix; +extern const FcMatrixPtr FcIdentityMatrix; void 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 */ +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 * FcStrPlus (const FcChar8 *s1, const FcChar8 *s2); @@ -752,6 +935,9 @@ FcStrBufString (FcStrBuf *buf, const FcChar8 *s); FcBool FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len); +FcStrSetPtr +FcStrSetSerialize (FcStrSet *set); + int FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2); diff --git a/src/fclang.c b/src/fclang.c index fabf36a..28b2d9b 100644 --- a/src/fclang.c +++ b/src/fclang.c @@ -22,6 +22,8 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include +#include #include "fcint.h" typedef struct { @@ -38,7 +40,7 @@ typedef struct { struct _FcLangSet { FcChar32 map[NUM_LANG_SET_MAP]; - FcStrSet *extra; + FcStrSetPtr extra; }; #define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f))) @@ -48,7 +50,7 @@ FcLangSet * FcFreeTypeLangSet (const FcCharSet *charset, const FcChar8 *exclusiveLang) { - int i; + int i, j; FcChar32 missing; const FcCharSet *exclusiveCharset = 0; FcLangSet *ls; @@ -67,10 +69,15 @@ FcFreeTypeLangSet (const FcCharSet *charset, * not support other Han languages */ if (exclusiveCharset && - FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang) && - fcLangCharSets[i].charset.leaves != exclusiveCharset->leaves) + FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang)) { - 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); if (FcDebug() & FC_DBG_SCANV) @@ -210,15 +217,22 @@ FcLangSetCreate (void) return 0; FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet)); memset (ls->map, '\0', sizeof (ls->map)); - ls->extra = 0; + ls->extra = FcStrSetPtrCreateDynamic(0); return ls; } +void +FcLangSetPtrDestroy (FcLangSetPtr li) +{ + if (li.storage == FcStorageDynamic) + FcLangSetDestroy(FcLangSetPtrU(li)); +} + void FcLangSetDestroy (FcLangSet *ls) { - if (ls->extra) - FcStrSetDestroy (ls->extra); + if (FcStrSetPtrU(ls->extra)) + FcStrSetDestroy (FcStrSetPtrU(ls->extra)); FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet)); free (ls); } @@ -232,21 +246,21 @@ FcLangSetCopy (const FcLangSet *ls) if (!new) goto bail0; memcpy (new->map, ls->map, sizeof (new->map)); - if (ls->extra) + if (FcStrSetPtrU(ls->extra)) { FcStrList *list; FcChar8 *extra; - new->extra = FcStrSetCreate (); - if (!new->extra) + new->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ()); + if (!FcStrSetPtrU(new->extra)) goto bail1; - list = FcStrListCreate (ls->extra); + list = FcStrListCreate (FcStrSetPtrU(ls->extra)); if (!list) goto bail1; while ((extra = FcStrListNext (list))) - if (!FcStrSetAdd (new->extra, extra)) + if (!FcStrSetAdd (FcStrSetPtrU(new->extra), extra)) { FcStrListDone (list); goto bail1; @@ -327,13 +341,13 @@ FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang) FcLangSetBitSet (ls, id); return FcTrue; } - if (!ls->extra) + if (!FcStrSetPtrU(ls->extra)) { - ls->extra = FcStrSetCreate (); - if (!ls->extra) + ls->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ()); + if (!FcStrSetPtrU(ls->extra)) return FcFalse; } - return FcStrSetAdd (ls->extra, lang); + return FcStrSetAdd (FcStrSetPtrU(ls->extra), lang); } FcLangResult @@ -365,9 +379,9 @@ FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang) if (FcLangSetBitGet (ls, i) && r < best) best = r; } - if (ls->extra) + if (FcStrSetPtrU(ls->extra)) { - FcStrList *list = FcStrListCreate (ls->extra); + FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra)); FcChar8 *extra; FcLangResult r; @@ -423,15 +437,15 @@ FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb) best = FcLangDifferentCountry; break; } - if (lsa->extra) + if (FcStrSetPtrU(lsa->extra)) { - r = FcLangSetCompareStrSet (lsb, lsa->extra); + r = FcLangSetCompareStrSet (lsb, FcStrSetPtrU(lsa->extra)); if (r < best) 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) best = r; } @@ -450,7 +464,7 @@ FcLangSetPromote (const FcChar8 *lang) int id; memset (ls.map, '\0', sizeof (ls.map)); - ls.extra = 0; + ls.extra = FcStrSetPtrCreateDynamic(0); id = FcLangSetIndex (lang); if (id > 0) { @@ -458,10 +472,11 @@ FcLangSetPromote (const FcChar8 *lang) } else { - ls.extra = &strs; + ls.extra = FcStrSetPtrCreateDynamic(&strs); strs.num = 1; strs.size = 1; - strs.strs = &str; + strs.storage = FcStorageDynamic; + strs.u.strs = &str; strs.ref = 1; str = (FcChar8 *) lang; } @@ -476,8 +491,8 @@ FcLangSetHash (const FcLangSet *ls) for (i = 0; i < NUM_LANG_SET_MAP; i++) h ^= ls->map[i]; - if (ls->extra) - h ^= ls->extra->num; + if (FcStrSetPtrU(ls->extra)) + h ^= FcStrSetPtrU(ls->extra)->num; 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; if (!list) @@ -568,10 +583,10 @@ FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb) if (lsa->map[i] != lsb->map[i]) return FcFalse; } - if (!lsa->extra && !lsb->extra) + if (!FcStrSetPtrU(lsa->extra) && !FcStrSetPtrU(lsb->extra)) return FcTrue; - if (lsa->extra && lsb->extra) - return FcStrSetEqual (lsa->extra, lsb->extra); + if (FcStrSetPtrU(lsa->extra) && FcStrSetPtrU(lsb->extra)) + return FcStrSetEqual (FcStrSetPtrU(lsa->extra), FcStrSetPtrU(lsb->extra)); return FcFalse; } @@ -605,9 +620,9 @@ FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang) FcLangContains (fcLangCharSets[i].lang, lang)) return FcTrue; } - if (ls->extra) + if (FcStrSetPtrU(ls->extra)) { - FcStrList *list = FcStrListCreate (ls->extra); + FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra)); FcChar8 *extra; 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; if (list) @@ -684,3 +699,78 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb) } 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; +} diff --git a/src/fclist.c b/src/fclist.c index ec47ddc..b3ecdb8 100644 --- a/src/fclist.c +++ b/src/fclist.c @@ -23,6 +23,9 @@ */ #include +#include +#include +#include #include "fcint.h" FcObjectSet * @@ -44,17 +47,18 @@ FcBool FcObjectSetAdd (FcObjectSet *os, const char *object) { int s; - const char **objects; + FcObjectPtr *objects; + FcObjectPtr obj; int high, low, mid, c; if (os->nobject == os->sobject) { s = os->sobject + 4; if (os->objects) - objects = (const char **) realloc ((void *) os->objects, - s * sizeof (const char *)); + objects = (FcObjectPtr *) realloc ((void *) os->objects, + s * sizeof (FcObjectPtr)); else - objects = (const char **) malloc (s * sizeof (const char *)); + objects = (FcObjectPtr *) malloc (s * sizeof (FcObjectPtr)); if (!objects) return FcFalse; if (os->sobject) @@ -67,11 +71,11 @@ FcObjectSetAdd (FcObjectSet *os, const char *object) low = 0; mid = 0; c = 1; - object = FcObjectStaticName (object); + obj = FcObjectStaticName (object); while (low <= high) { mid = (low + high) >> 1; - c = os->objects[mid] - object; + c = FcObjectPtrCompare(os->objects[mid], obj); if (c == 0) return FcTrue; if (c < 0) @@ -82,8 +86,8 @@ FcObjectSetAdd (FcObjectSet *os, const char *object) if (c < 0) mid++; memmove (os->objects + mid + 1, os->objects + mid, - (os->nobject - mid) * sizeof (const char *)); - os->objects[mid] = object; + (os->nobject - mid) * sizeof (FcObjectPtr)); + os->objects[mid] = obj; os->nobject++; return FcTrue; } @@ -125,51 +129,59 @@ FcObjectSetBuild (const char *first, ...) * Font must have a containing value for every value in the pattern */ static FcBool -FcListValueListMatchAny (FcValueList *patOrig, /* pattern */ - FcValueList *fntOrig) /* font */ +FcListValueListMatchAny (FcValueListPtr patOrig, /* pattern */ + 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. * (OpListing is OpContains except for strings * where it requires an exact match) */ - if (FcConfigCompareValue (fnt->value, + if (FcConfigCompareValue (FcValueListPtrU(fnt)->value, FcOpListing, - pat->value)) + FcValueListPtrU(pat)->value)) break; } - if (!fnt) + if (!FcValueListPtrU(fnt)) return FcFalse; } return FcTrue; } static FcBool -FcListValueListEqual (FcValueList *v1orig, - FcValueList *v2orig) +FcListValueListEqual (FcValueListPtr v1orig, + 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) - if (FcValueEqual (v1->value, v2->value)) + for (v2 = v2orig; FcValueListPtrU(v2); + v2 = FcValueListPtrU(v2)->next) + if (FcValueEqual (FcValueListPtrU(v1)->value, + FcValueListPtrU(v2)->value)) break; - if (!v2) + if (!FcValueListPtrU(v2)) 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) - if (FcValueEqual (v1->value, v2->value)) + for (v1 = v1orig; FcValueListPtrU(v1); + v1 = FcValueListPtrU(v1)->next) + if (FcValueEqual (FcValueListPtrU(v1)->value, + FcValueListPtrU(v2)->value)) break; - if (!v1) + if (!FcValueListPtrU(v1)) return FcFalse; } return FcTrue; @@ -185,8 +197,8 @@ FcListPatternEqual (FcPattern *p1, for (i = 0; i < os->nobject; i++) { - e1 = FcPatternFindElt (p1, os->objects[i]); - e2 = FcPatternFindElt (p2, os->objects[i]); + e1 = FcPatternFindElt (p1, FcObjectPtrU(os->objects[i])); + e2 = FcPatternFindElt (p2, FcObjectPtrU(os->objects[i])); if (!e1 && !e2) continue; if (!e1 || !e2) @@ -210,10 +222,11 @@ FcListPatternMatchAny (const FcPattern *p, 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) return FcFalse; - if (!FcListValueListMatchAny (p->elts[i].values, /* pat elts */ + if (!FcListValueListMatchAny ((FcPatternEltU(p->elts)+i)->values, /* pat elts */ e->values)) /* font elts */ return FcFalse; } @@ -242,30 +255,30 @@ FcListValueHash (FcValue v) case FcTypeDouble: return (FcChar32) (int) v.u.d; case FcTypeString: - return FcStrHashIgnoreCase (v.u.s); + return FcStrHashIgnoreCase (FcObjectPtrU(v.u.si)); case FcTypeBool: return (FcChar32) v.u.b; case FcTypeMatrix: - return FcListMatrixHash (v.u.m); + return FcListMatrixHash (FcMatrixPtrU(v.u.mi)); case FcTypeCharSet: - return FcCharSetCount (v.u.c); + return FcCharSetCount (FcCharSetPtrU(v.u.ci)); case FcTypeFTFace: return (long) v.u.f; case FcTypeLangSet: - return FcLangSetHash (v.u.l); + return FcLangSetHash (FcLangSetPtrU(v.u.li)); } return 0; } static FcChar32 -FcListValueListHash (FcValueList *list) +FcListValueListHash (FcValueListPtr list) { FcChar32 h = 0; - while (list) + while (FcValueListPtrU(list)) { - h = h ^ FcListValueHash (list->value); - list = list->next; + h = h ^ FcListValueHash (FcValueListPtrU(list)->value); + list = FcValueListPtrU(list)->next; } return h; } @@ -280,7 +293,7 @@ FcListPatternHash (FcPattern *font, for (n = 0; n < os->nobject; n++) { - e = FcPatternFindElt (font, os->objects[n]); + e = FcPatternFindElt (font, FcObjectPtrU(os->objects[n])); if (e) h = h ^ FcListValueListHash (e->values); } @@ -334,7 +347,7 @@ FcListAppend (FcListHashTable *table, { int o; FcPatternElt *e; - FcValueList *v; + FcValueListPtr v; FcChar32 hash; FcListBucket **prev, *bucket; @@ -358,14 +371,15 @@ FcListAppend (FcListHashTable *table, for (o = 0; o < os->nobject; o++) { - e = FcPatternFindElt (font, os->objects[o]); + e = FcPatternFindElt (font, FcObjectPtrU(os->objects[o])); if (e) { - for (v = e->values; v; v = v->next) + for (v = e->values; FcValueListPtrU(v); + v = FcValueListPtrU(v)->next) { if (!FcPatternAdd (bucket->pattern, - os->objects[o], - v->value, FcTrue)) + FcObjectPtrU(os->objects[o]), + FcValueListPtrU(v)->value, FcTrue)) goto bail2; } } diff --git a/src/fcmatch.c b/src/fcmatch.c index 9a6b35f..9e70271 100644 --- a/src/fcmatch.c +++ b/src/fcmatch.c @@ -63,7 +63,8 @@ FcCompareString (char *object, FcValue value1, FcValue value2) { if (value2.type != FcTypeString || value1.type != FcTypeString) 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 @@ -71,7 +72,8 @@ FcCompareFamily (char *object, FcValue value1, FcValue value2) { if (value2.type != FcTypeString || value1.type != FcTypeString) 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 @@ -83,10 +85,12 @@ FcCompareLang (char *object, FcValue value1, FcValue value2) case FcTypeLangSet: switch (value2.type) { case FcTypeLangSet: - result = FcLangSetCompare (value1.u.l, value2.u.l); + result = FcLangSetCompare (FcLangSetPtrU(value1.u.li), + FcLangSetPtrU(value2.u.li)); break; case FcTypeString: - result = FcLangSetHasLang (value1.u.l, value2.u.s); + result = FcLangSetHasLang (FcLangSetPtrU(value1.u.li), + FcObjectPtrU(value2.u.si)); break; default: return -1.0; @@ -95,10 +99,12 @@ FcCompareLang (char *object, FcValue value1, FcValue value2) case FcTypeString: switch (value2.type) { case FcTypeLangSet: - result = FcLangSetHasLang (value2.u.l, value1.u.s); + result = FcLangSetHasLang (FcLangSetPtrU(value2.u.li), + FcObjectPtrU(value1.u.si)); break; case FcTypeString: - result = FcLangCompare (value1.u.s, value2.u.s); + result = FcLangCompare (FcObjectPtrU(value1.u.si), + FcObjectPtrU(value2.u.si)); break; default: return -1.0; @@ -131,7 +137,8 @@ FcCompareCharSet (char *object, FcValue value1, FcValue value2) { if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet) 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 @@ -241,13 +248,13 @@ static FcMatcher _FcMatchers [] = { static FcBool FcCompareValueList (const char *object, - FcValueList *v1orig, /* pattern */ - FcValueList *v2orig, /* target */ + FcValueListPtr v1orig, /* pattern */ + FcValueListPtr v2orig, /* target */ FcValue *bestValue, double *value, FcResult *result) { - FcValueList *v1, *v2; + FcValueListPtr v1, v2; double v, best, bestStrong, bestWeak; int i; int j; @@ -308,7 +315,7 @@ FcCompareValueList (const char *object, (FcChar8 *) object) != 0) { if (bestValue) - *bestValue = v2orig->value; + *bestValue = FcValueListPtrU(v2orig)->value; return FcTrue; } #if 0 @@ -329,13 +336,15 @@ FcCompareValueList (const char *object, bestStrong = 1e99; bestWeak = 1e99; 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, - v1->value, - v2->value); + FcValueListPtrU(v1)->value, + FcValueListPtrU(v2)->value); if (v < 0) { *result = FcResultTypeMismatch; @@ -347,10 +356,10 @@ FcCompareValueList (const char *object, if (v < best) { if (bestValue) - *bestValue = v2->value; + *bestValue = FcValueListPtrU(v2)->value; best = v; } - if (v1->binding == FcValueBindingStrong) + if (FcValueListPtrU(v1)->binding == FcValueBindingStrong) { if (v < bestStrong) bestStrong = v; @@ -406,16 +415,17 @@ FcCompare (FcPattern *pat, i2 = 0; 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) i2++; else if (i < 0) i1++; else { - if (!FcCompareValueList (pat->elts[i1].object, - pat->elts[i1].values, - fnt->elts[i2].values, + if (!FcCompareValueList (FcObjectPtrU((FcPatternEltU(pat->elts)+i1)->object), + (FcPatternEltU(pat->elts)+i1)->values, + (FcPatternEltU(fnt->elts)+i2)->values, 0, value, result)) @@ -456,11 +466,11 @@ FcFontRenderPrepare (FcConfig *config, return 0; for (i = 0; i < font->num; i++) { - fe = &font->elts[i]; - pe = FcPatternFindElt (pat, fe->object); + fe = FcPatternEltU(font->elts)+i; + pe = FcPatternFindElt (pat, FcObjectPtrU(fe->object)); if (pe) { - if (!FcCompareValueList (pe->object, pe->values, + if (!FcCompareValueList (FcObjectPtrU(pe->object), pe->values, fe->values, &v, 0, &result)) { FcPatternDestroy (new); @@ -468,15 +478,16 @@ FcFontRenderPrepare (FcConfig *config, } } else - v = fe->values->value; - FcPatternAdd (new, fe->object, v, FcFalse); + v = FcValueListPtrU(fe->values)->value; + FcPatternAdd (new, FcObjectPtrU(fe->object), v, FcFalse); } for (i = 0; i < pat->num; i++) { - pe = &pat->elts[i]; - fe = FcPatternFindElt (font, pe->object); + pe = FcPatternEltU(pat->elts)+i; + fe = FcPatternFindElt (font, FcObjectPtrU(pe->object)); 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); return new; diff --git a/src/fcmatrix.c b/src/fcmatrix.c index 863fe69..6a5aa5d 100644 --- a/src/fcmatrix.c +++ b/src/fcmatrix.c @@ -27,7 +27,11 @@ #include #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 * FcMatrixCopy (const FcMatrix *mat) @@ -43,10 +47,17 @@ FcMatrixCopy (const FcMatrix *mat) return r; } +void +FcMatrixPtrDestroy (FcMatrixPtr mi) +{ + if (mi.storage == FcStorageDynamic) + FcMatrixFree (mi.u.dyn); +} + void FcMatrixFree (FcMatrix *mat) { - if (mat != &FcIdentityMatrix) + if (mat != FcMatrixPtrU(FcIdentityMatrix)) { FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix)); free (mat); @@ -115,3 +126,59 @@ FcMatrixShear (FcMatrix *m, double sh, double sv) r.yy = 1; 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; +} + diff --git a/src/fcname.c b/src/fcname.c index 3b9454d..d49ec08 100644 --- a/src/fcname.c +++ b/src/fcname.c @@ -321,7 +321,7 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m) v.u.i = atoi ((char *) string); break; case FcTypeString: - v.u.s = string; + v.u.si = FcObjectPtrCreateDynamic(string); break; case FcTypeBool: if (!FcNameBool (string, &v.u.b)) @@ -331,14 +331,14 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m) v.u.d = strtod ((char *) string, 0); break; 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); break; case FcTypeCharSet: - v.u.c = FcNameParseCharSet (string); + v.u.ci = FcCharSetPtrCreateDynamic(FcNameParseCharSet (string)); break; case FcTypeLangSet: - v.u.l = FcNameParseLangSet (string); + v.u.li = FcLangSetPtrCreateDynamic(FcNameParseLangSet (string)); break; default: break; @@ -436,10 +436,10 @@ FcNameParse (const FcChar8 *name) { switch (v.type) { case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) v.u.c); + FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci)); break; case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) v.u.l); + FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li)); break; default: break; @@ -448,10 +448,10 @@ FcNameParse (const FcChar8 *name) } switch (v.type) { case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) v.u.c); + FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci)); break; case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) v.u.l); + FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li)); break; default: break; @@ -518,17 +518,20 @@ FcNameUnparseValue (FcStrBuf *buf, sprintf ((char *) temp, "%g", v.u.d); return FcNameUnparseString (buf, temp, 0); case FcTypeString: - return FcNameUnparseString (buf, v.u.s, escape); + return FcNameUnparseString (buf, FcObjectPtrU(v.u.si), escape); case FcTypeBool: return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0); case FcTypeMatrix: + { + FcMatrix * m = FcMatrixPtrU(v.u.mi); 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); + } case FcTypeCharSet: - return FcNameUnparseCharSet (buf, v.u.c); + return FcNameUnparseCharSet (buf, FcCharSetPtrU(v.u.ci)); case FcTypeLangSet: - return FcNameUnparseLangSet (buf, v.u.l); + return FcNameUnparseLangSet (buf, FcLangSetPtrU(v.u.li)); case FcTypeFTFace: return FcTrue; } @@ -537,14 +540,14 @@ FcNameUnparseValue (FcStrBuf *buf, static FcBool FcNameUnparseValueList (FcStrBuf *buf, - FcValueList *v, + FcValueListPtr v, FcChar8 *escape) { - while (v) + while (FcValueListPtrU(v)) { - if (!FcNameUnparseValue (buf, v->value, escape)) + if (!FcNameUnparseValue (buf, FcValueListPtrU(v)->value, escape)) return FcFalse; - if ((v = v->next)) + if (FcValueListPtrU(v = FcValueListPtrU(v)->next)) if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0)) return FcFalse; } diff --git a/src/fcpat.c b/src/fcpat.c index c886c92..af68205 100644 --- a/src/fcpat.c +++ b/src/fcpat.c @@ -25,8 +25,26 @@ #include #include #include +#include #include "fcint.h" +static FcPattern * fcpatterns = NULL; +static int fcpattern_ptr, fcpattern_count; +static FcPatternElt * fcpatternelts = NULL; +static int fcpatternelt_ptr, fcpatternelt_count; +static FcValueList * fcvaluelists = NULL; +static int fcvaluelist_ptr, fcvaluelist_count; + +static char * object_content; +static int object_content_count; +static int object_content_ptr; + +static FcBool +FcPatternEltIsDynamic (FcPatternEltPtr pei); + +static FcPatternEltPtr +FcPatternEltPtrCreateDynamic (FcPatternElt * e); + FcPattern * FcPatternCreate (void) { @@ -38,7 +56,7 @@ FcPatternCreate (void) FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern)); p->num = 0; p->size = 0; - p->elts = 0; + p->elts = FcPatternEltPtrCreateDynamic(0); p->ref = 1; return p; } @@ -48,16 +66,16 @@ FcValueDestroy (FcValue v) { switch (v.type) { case FcTypeString: - FcStrFree ((FcChar8 *) v.u.s); + FcObjectPtrDestroy (v.u.si); break; case FcTypeMatrix: - FcMatrixFree ((FcMatrix *) v.u.m); + FcMatrixPtrDestroy (v.u.mi); break; case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) v.u.c); + FcCharSetPtrDestroy (v.u.ci); break; case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) v.u.l); + FcLangSetPtrDestroy (v.u.li); break; default: break; @@ -69,23 +87,26 @@ FcValueSave (FcValue v) { switch (v.type) { case FcTypeString: - v.u.s = FcStrCopy (v.u.s); - if (!v.u.s) + v.u.si = FcObjectPtrCreateDynamic(FcStrCopy (FcObjectPtrU(v.u.si))); + if (!FcObjectPtrU(v.u.si)) v.type = FcTypeVoid; break; case FcTypeMatrix: - v.u.m = FcMatrixCopy (v.u.m); - if (!v.u.m) + v.u.mi = FcMatrixPtrCreateDynamic + (FcMatrixCopy (FcMatrixPtrU(v.u.mi))); + if (!FcMatrixPtrU(v.u.mi)) v.type = FcTypeVoid; break; case FcTypeCharSet: - v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c); - if (!v.u.c) + v.u.ci = FcCharSetPtrCreateDynamic + (FcCharSetCopy (FcCharSetPtrU(v.u.ci))); + if (!FcCharSetPtrU(v.u.ci)) v.type = FcTypeVoid; break; case FcTypeLangSet: - v.u.l = FcLangSetCopy (v.u.l); - if (!v.u.l) + v.u.li = FcLangSetPtrCreateDynamic + (FcLangSetCopy (FcLangSetPtrU(v.u.li))); + if (!FcLangSetPtrU(v.u.li)) v.type = FcTypeVoid; break; default: @@ -95,30 +116,34 @@ FcValueSave (FcValue v) } void -FcValueListDestroy (FcValueList *l) +FcValueListDestroy (FcValueListPtr l) { - FcValueList *next; - for (; l; l = next) + FcValueListPtr next; + for (; FcValueListPtrU(l); l = next) { - switch (l->value.type) { + switch (FcValueListPtrU(l)->value.type) { case FcTypeString: - FcStrFree ((FcChar8 *) l->value.u.s); + FcObjectPtrDestroy (FcValueListPtrU(l)->value.u.si); break; case FcTypeMatrix: - FcMatrixFree ((FcMatrix *) l->value.u.m); + FcMatrixPtrDestroy (FcValueListPtrU(l)->value.u.mi); break; case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) l->value.u.c); + FcCharSetDestroy + (FcCharSetPtrU (FcValueListPtrU(l)->value.u.ci)); break; case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) l->value.u.l); + FcLangSetDestroy + (FcLangSetPtrU (FcValueListPtrU(l)->value.u.li)); break; default: break; } - next = l->next; + next = FcValueListPtrU(l)->next; + FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); - free (l); + if (l.storage == FcStorageDynamic) + free(l.u.dyn); } } @@ -148,17 +173,21 @@ FcValueEqual (FcValue va, FcValue vb) case FcTypeDouble: return va.u.d == vb.u.d; case FcTypeString: - return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0; + return FcStrCmpIgnoreCase (FcObjectPtrU(va.u.si), + FcObjectPtrU(vb.u.si)) == 0; case FcTypeBool: return va.u.b == vb.u.b; case FcTypeMatrix: - return FcMatrixEqual (va.u.m, vb.u.m); + return FcMatrixEqual (FcMatrixPtrU(va.u.mi), + FcMatrixPtrU(vb.u.mi)); case FcTypeCharSet: - return FcCharSetEqual (va.u.c, vb.u.c); + return FcCharSetEqual (FcCharSetPtrU(va.u.ci), + FcCharSetPtrU(vb.u.ci)); case FcTypeFTFace: return va.u.f == vb.u.f; case FcTypeLangSet: - return FcLangSetEqual (va.u.l, vb.u.l); + return FcLangSetEqual (FcLangSetPtrU(va.u.li), + FcLangSetPtrU(vb.u.li)); } return FcFalse; } @@ -196,52 +225,57 @@ FcValueHash (FcValue v) case FcTypeDouble: return FcDoubleHash (v.u.d); case FcTypeString: - return FcStringHash (v.u.s); + return FcStringHash (FcObjectPtrU(v.u.si)); case FcTypeBool: return (FcChar32) v.u.b; case FcTypeMatrix: - return (FcDoubleHash (v.u.m->xx) ^ - FcDoubleHash (v.u.m->xy) ^ - FcDoubleHash (v.u.m->yx) ^ - FcDoubleHash (v.u.m->yy)); + { + FcMatrix * m = FcMatrixPtrU(v.u.mi); + return (FcDoubleHash (m->xx) ^ + FcDoubleHash (m->xy) ^ + FcDoubleHash (m->yx) ^ + FcDoubleHash (m->yy)); + } case FcTypeCharSet: - return (FcChar32) v.u.c->num; + return (FcChar32) (FcCharSetPtrU(v.u.ci))->num; case FcTypeFTFace: return FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->family_name) ^ FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->style_name); case FcTypeLangSet: - return FcLangSetHash (v.u.l); + return FcLangSetHash (FcLangSetPtrU(v.u.li)); } return FcFalse; } static FcBool -FcValueListEqual (FcValueList *la, FcValueList *lb) +FcValueListEqual (FcValueListPtr la, FcValueListPtr lb) { - if (la == lb) + if (FcValueListPtrU(la) == FcValueListPtrU(lb)) return FcTrue; - while (la && lb) + while (FcValueListPtrU(la) && FcValueListPtrU(lb)) { - if (!FcValueEqual (la->value, lb->value)) + if (!FcValueEqual (FcValueListPtrU(la)->value, + FcValueListPtrU(lb)->value)) return FcFalse; - la = la->next; - lb = lb->next; + la = FcValueListPtrU(la)->next; + lb = FcValueListPtrU(lb)->next; } - if (la || lb) + if (FcValueListPtrU(la) || FcValueListPtrU(lb)) return FcFalse; return FcTrue; } static FcChar32 -FcValueListHash (FcValueList *l) +FcValueListHash (FcValueListPtr l) { FcChar32 hash = 0; - while (l) + while (FcValueListPtrU(l)) { - hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (l->value); - l = l->next; + hash = ((hash << 1) | (hash >> 31)) ^ + FcValueHash (FcValueListPtrU(l)->value); + l = FcValueListPtrU(l)->next; } return hash; } @@ -255,14 +289,14 @@ FcPatternDestroy (FcPattern *p) return; for (i = 0; i < p->num; i++) - FcValueListDestroy (p->elts[i].values); + FcValueListDestroy ((FcPatternEltU(p->elts)+i)->values); p->num = 0; - if (p->elts) + if (FcPatternEltU(p->elts) && FcPatternEltIsDynamic(p->elts)) { FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt)); - free (p->elts); - p->elts = 0; + free (FcPatternEltU(p->elts)); + p->elts = FcPatternEltPtrCreateDynamic(0); } p->size = 0; FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern)); @@ -276,7 +310,7 @@ typedef struct _FcValueListEnt FcValueListEnt; struct _FcValueListEnt { FcValueListEnt *next; - FcValueList *list; + FcValueListPtr list; FcChar32 hash, pad; }; @@ -315,43 +349,54 @@ FcValueListReport (void) } static FcValueListEnt * -FcValueListEntCreate (FcValueList *h) +FcValueListEntCreate (FcValueListPtr h) { FcValueListAlign *ea; FcValueListEnt *e; - FcValueList *l, *new; + FcValueListPtr l; + FcValueList *new; int n; int size; n = 0; - for (l = h; l; l = l->next) + for (l = h; FcValueListPtrU(l); l = FcValueListPtrU(l)->next) n++; size = sizeof (FcValueListAlign) + n * sizeof (FcValueList); - FcValueListFrozenCount[h->value.type]++; - FcValueListFrozenBytes[h->value.type] += size; - ea = malloc (size); + FcValueListFrozenCount[FcValueListPtrU(h)->value.type]++; + FcValueListFrozenBytes[FcValueListPtrU(h)->value.type] += size; + // this leaks for some reason + ea = malloc (sizeof (FcValueListAlign)); if (!ea) return 0; + new = malloc (n * sizeof (FcValueList)); + if (!new) + return 0; + memset(new, 0, n * sizeof (FcValueList)); FcMemAlloc (FC_MEM_VALLIST, size); e = &ea->ent; - e->list = (FcValueList *) (ea + 1); - new = e->list; - for (l = h; l; l = l->next, new++) + e->list = (FcValueListPtr) FcValueListPtrCreateDynamic(new); + for (l = h; FcValueListPtrU(l); + l = FcValueListPtrU(l)->next, new++) { - if (l->value.type == FcTypeString) + if (FcValueListPtrU(l)->value.type == FcTypeString) { new->value.type = FcTypeString; - new->value.u.s = FcObjectStaticName (l->value.u.s); + new->value.u.si = FcObjectStaticName + (FcObjectPtrU(FcValueListPtrU(l)->value.u.si)); } else { - new->value = FcValueSave (l->value); + new->value = FcValueSave (FcValueListPtrU(l)->value); + } + new->binding = FcValueListPtrU(l)->binding; + if (FcValueListPtrU(FcValueListPtrU(l)->next)) + { + new->next = FcValueListPtrCreateDynamic(new + 1); } - new->binding = l->binding; - if (l->next) - new->next = new + 1; else - new->next = 0; + { + new->next = FcValueListPtrCreateDynamic(0); + } } return e; } @@ -359,9 +404,9 @@ FcValueListEntCreate (FcValueList *h) static void FcValueListEntDestroy (FcValueListEnt *e) { - FcValueList *l; + FcValueListPtr l; - FcValueListFrozenCount[e->list->value.type]--; + FcValueListFrozenCount[FcValueListPtrU(e->list)->value.type]--; /* XXX: We should perform these two operations with "size" as computed in FcValueListEntCreate, but we don't have access to @@ -372,10 +417,11 @@ FcValueListEntDestroy (FcValueListEnt *e) FcMemFree (FC_MEM_VALLIST, size); */ - for (l = e->list; l; l = l->next) + for (l = e->list; FcValueListPtrU(l); + l = FcValueListPtrU(l)->next) { - if (l->value.type != FcTypeString) - FcValueDestroy (l->value); + if (FcValueListPtrU(l)->value.type != FcTypeString) + FcValueDestroy (FcValueListPtrU(l)->value); } /* XXX: Are we being too chummy with the implementation here to free(e) when it was actually the enclosing FcValueListAlign @@ -388,8 +434,8 @@ static int FcValueListUsed; static FcValueListEnt *FcValueListHashTable[FC_VALUE_LIST_HASH_SIZE]; -static FcValueList * -FcValueListFreeze (FcValueList *l) +static FcValueListPtr +FcValueListFreeze (FcValueListPtr l) { FcChar32 hash = FcValueListHash (l); FcValueListEnt **bucket = &FcValueListHashTable[hash % FC_VALUE_LIST_HASH_SIZE]; @@ -404,7 +450,7 @@ FcValueListFreeze (FcValueList *l) ent = FcValueListEntCreate (l); if (!ent) - return 0; + return FcValueListPtrCreateDynamic(0); FcValueListUsed++; ent->hash = hash; @@ -440,7 +486,8 @@ FcPatternBaseHash (FcPattern *b) int i; for (i = 0; i < b->num; i++) - hash = ((hash << 1) | (hash >> 31)) ^ ((long) b->elts[i].values); + hash = ((hash << 1) | (hash >> 31)) ^ + (long) (FcValueListPtrU((FcPatternEltU(b->elts)+i)->values)); return hash; } @@ -449,7 +496,7 @@ typedef struct _FcPatternEnt FcPatternEnt; struct _FcPatternEnt { FcPatternEnt *next; FcChar32 hash; - FcPattern pattern; + FcPattern *pattern; }; static int FcPatternTotal; @@ -460,55 +507,74 @@ static FcPatternEnt *FcPatternHashTable[FC_VALUE_LIST_HASH_SIZE]; static FcPattern * FcPatternBaseFreeze (FcPattern *b) { + FcPattern *ep; + FcPatternElt *epp; FcChar32 hash = FcPatternBaseHash (b); FcPatternEnt **bucket = &FcPatternHashTable[hash % FC_VALUE_LIST_HASH_SIZE]; FcPatternEnt *ent; int i; - int size; FcPatternTotal++; for (ent = *bucket; ent; ent = ent->next) { - if (ent->hash == hash && b->num == ent->pattern.num) - { + if (ent->hash == hash && b->num == ent->pattern->num) + { for (i = 0; i < b->num; i++) { - if (b->elts[i].object != ent->pattern.elts[i].object) + if (FcObjectPtrCompare((FcPatternEltU(b->elts)+i)->object, + (FcPatternEltU(ent->pattern->elts)+i)->object) != 0) break; - if (b->elts[i].values != ent->pattern.elts[i].values) + if (FcValueListPtrU((FcPatternEltU(b->elts)+i)->values) != + FcValueListPtrU((FcPatternEltU(ent->pattern->elts)+i)->values)) break; } if (i == b->num) - return &ent->pattern; + return ent->pattern; } } /* * Compute size of pattern + elts */ - size = sizeof (FcPatternEnt) + b->num*sizeof (FcPatternElt); - ent = malloc (size); + ent = malloc (sizeof (FcPatternEnt)); if (!ent) return 0; - FcMemAlloc (FC_MEM_PATTERN, size); + FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPatternEnt)); FcPatternUsed++; - ent->pattern.elts = (FcPatternElt *) (ent + 1); - ent->pattern.num = b->num; - ent->pattern.size = b->num; - ent->pattern.ref = FC_REF_CONSTANT; + ep = FcPatternCreate(); + if (!ep) + return 0; + ent->pattern = ep; + epp = malloc(b->num * sizeof (FcPatternElt)); + if (!epp) + goto bail; + ep->elts = FcPatternEltPtrCreateDynamic(epp); + + FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num)); + + ep->num = b->num; + ep->size = b->num; + ep->ref = FC_REF_CONSTANT; for (i = 0; i < b->num; i++) { - ent->pattern.elts[i].values = b->elts[i].values; - ent->pattern.elts[i].object = b->elts[i].object; + (FcPatternEltU(ep->elts)+i)->values = + (FcPatternEltU(b->elts)+i)->values; + (FcPatternEltU(ep->elts)+i)->object = + (FcPatternEltU(b->elts)+i)->object; } ent->hash = hash; ent->next = *bucket; *bucket = ent; - return &ent->pattern; + return ent->pattern; + bail: + free(ent); + FcMemFree (FC_MEM_PATTERN, sizeof (FcPatternEnt)); + FcPatternUsed--; + return 0; } static void @@ -535,29 +601,36 @@ FcPattern * FcPatternFreeze (FcPattern *p) { FcPattern *b, *n = 0; - int size; + FcPatternElt *e; int i; if (p->ref == FC_REF_CONSTANT) return p; - size = sizeof (FcPattern) + p->num * sizeof (FcPatternElt); - b = (FcPattern *) malloc (size); + b = FcPatternCreate(); if (!b) - return 0; - FcMemAlloc (FC_MEM_PATTERN, size); + return 0; + b->num = p->num; b->size = b->num; b->ref = 1; - b->elts = (FcPatternElt *) (b + 1); + + e = malloc(b->num * sizeof (FcPatternElt)); + if (!e) + return 0; + b->elts = FcPatternEltPtrCreateDynamic(e); + FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num)); + /* * Freeze object lists */ for (i = 0; i < p->num; i++) { - b->elts[i].object = p->elts[i].object; - b->elts[i].values = FcValueListFreeze (p->elts[i].values); - if (!b->elts[i].values) + (FcPatternEltU(b->elts)+i)->object = + (FcPatternEltU(p->elts)+i)->object; + (FcPatternEltU(b->elts)+i)->values = + FcValueListFreeze((FcPatternEltU(p->elts)+i)->values); + if (!FcValueListPtrU((FcPatternEltU(p->elts)+i)->values)) goto bail; } /* @@ -571,8 +644,11 @@ FcPatternFreeze (FcPattern *p) printf ("Patterns: total %9d used %9d\n", FcPatternTotal, FcPatternUsed); } #endif -bail: - free (b); + bail: + free(FcPatternEltU(b->elts)); + b->elts = FcPatternEltPtrCreateDynamic(0); + FcMemFree (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num)); + b->num = -1; #ifdef DEBUG assert (FcPatternEqual (n, p)); #endif @@ -590,8 +666,9 @@ static int FcPatternPosition (const FcPattern *p, const char *object) { int low, high, mid, c; + FcObjectPtr obj; - object = FcObjectStaticName(object); + obj = FcObjectStaticName(object); low = 0; high = p->num - 1; c = 1; @@ -599,7 +676,7 @@ FcPatternPosition (const FcPattern *p, const char *object) while (low <= high) { mid = (low + high) >> 1; - c = p->elts[mid].object - object; + c = FcObjectPtrCompare((FcPatternEltU(p->elts)+mid)->object, obj); if (c == 0) return mid; if (c < 0) @@ -618,7 +695,7 @@ FcPatternFindElt (const FcPattern *p, const char *object) int i = FcPatternPosition (p, object); if (i < 0) return 0; - return &p->elts[i]; + return FcPatternEltU(p->elts)+i; } FcPatternElt * @@ -632,42 +709,52 @@ FcPatternInsertElt (FcPattern *p, const char *object) { i = -i - 1; - /* grow array */ + /* reallocate array */ if (p->num + 1 >= p->size) { int s = p->size + 16; - if (p->elts) - e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt)); + if (FcPatternEltU(p->elts)) + { + FcPatternElt *e0 = FcPatternEltU(p->elts); + e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt)); + if (!e) /* maybe it was mmapped */ + { + e = malloc(s * sizeof (FcPatternElt)); + if (e) + memcpy(e, e0, p->num * sizeof (FcPatternElt)); + } + } else e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt)); if (!e) return FcFalse; - p->elts = e; + p->elts = FcPatternEltPtrCreateDynamic(e); if (p->size) FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt)); FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt)); while (p->size < s) { - p->elts[p->size].object = 0; - p->elts[p->size].values = 0; + (FcPatternEltU(p->elts)+p->size)->object = FcObjectPtrCreateDynamic(0); + (FcPatternEltU(p->elts)+p->size)->values = + FcValueListPtrCreateDynamic(0); p->size++; } } /* move elts up */ - memmove (p->elts + i + 1, - p->elts + i, + memmove (FcPatternEltU(p->elts) + i + 1, + FcPatternEltU(p->elts) + i, sizeof (FcPatternElt) * (p->num - i)); /* bump count */ p->num++; - p->elts[i].object = FcObjectStaticName (object); - p->elts[i].values = 0; + (FcPatternEltU(p->elts)+i)->object = FcObjectStaticName (object); + (FcPatternEltU(p->elts)+i)->values = FcValueListPtrCreateDynamic(0); } - return &p->elts[i]; + return FcPatternEltU(p->elts)+i; } FcBool @@ -682,9 +769,11 @@ FcPatternEqual (const FcPattern *pa, const FcPattern *pb) return FcFalse; for (i = 0; i < pa->num; i++) { - if (pa->elts[i].object != pb->elts[i].object) + if (FcObjectPtrCompare((FcPatternEltU(pa->elts)+i)->object, + (FcPatternEltU(pb->elts)+i)->object) != 0) return FcFalse; - if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values)) + if (!FcValueListEqual ((FcPatternEltU(pa->elts)+i)->values, + (FcPatternEltU(pb->elts)+i)->values)) return FcFalse; } return FcTrue; @@ -699,22 +788,22 @@ FcPatternHash (const FcPattern *p) for (i = 0; i < p->num; i++) { h = (((h << 1) | (h >> 31)) ^ - FcStringHash ((const FcChar8 *) p->elts[i].object) ^ - FcValueListHash (p->elts[i].values)); + FcStringHash ((const FcChar8 *) FcObjectPtrU(((FcPatternEltU(p->elts)+i)->object))) ^ + FcValueListHash ((FcPatternEltU(p->elts)+i)->values)); } return h; } FcBool -FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os) +FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os) { FcPatternElt *ea, *eb; int i; for (i = 0; i < os->nobject; i++) { - ea = FcPatternFindElt (pa, os->objects[i]); - eb = FcPatternFindElt (pb, os->objects[i]); + ea = FcPatternFindElt (pai, FcObjectPtrU(os->objects[i])); + eb = FcPatternFindElt (pbi, FcObjectPtrU(os->objects[i])); if (ea) { if (!eb) @@ -739,24 +828,27 @@ FcPatternAddWithBinding (FcPattern *p, FcBool append) { FcPatternElt *e; - FcValueList *new, **prev; + FcValueListPtr new, *prev; + FcValueList * newp; if (p->ref == FC_REF_CONSTANT) goto bail0; - new = (FcValueList *) malloc (sizeof (FcValueList)); - if (!new) + newp = malloc (sizeof (FcValueList)); + if (!newp) goto bail0; + memset(newp, 0, sizeof (FcValueList)); + new = FcValueListPtrCreateDynamic(newp); FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList)); /* dup string */ value = FcValueSave (value); if (value.type == FcTypeVoid) goto bail1; - new->value = value; - new->binding = binding; - new->next = 0; + FcValueListPtrU(new)->value = value; + FcValueListPtrU(new)->binding = binding; + FcValueListPtrU(new)->next = FcValueListPtrCreateDynamic(0); e = FcPatternInsertElt (p, object); if (!e) @@ -764,12 +856,13 @@ FcPatternAddWithBinding (FcPattern *p, if (append) { - for (prev = &e->values; *prev; prev = &(*prev)->next); + for (prev = &e->values; FcValueListPtrU(*prev); prev = &FcValueListPtrU(*prev)->next) + ; *prev = new; } else { - new->next = e->values; + FcValueListPtrU(new)->next = e->values; e->values = new; } @@ -778,23 +871,23 @@ FcPatternAddWithBinding (FcPattern *p, bail2: switch (value.type) { case FcTypeString: - FcStrFree ((FcChar8 *) value.u.s); + FcStrFree ((FcChar8 *) FcObjectPtrU(value.u.si)); break; case FcTypeMatrix: - FcMatrixFree ((FcMatrix *) value.u.m); + FcMatrixFree (FcMatrixPtrU(value.u.mi)); break; case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) value.u.c); + FcCharSetDestroy (FcCharSetPtrU(value.u.ci)); break; case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) value.u.l); + FcLangSetDestroy (FcLangSetPtrU(value.u.li)); break; default: break; } bail1: FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); - free (new); + free (FcValueListPtrU(new)); bail0: return FcFalse; } @@ -815,42 +908,43 @@ FcBool FcPatternDel (FcPattern *p, const char *object) { FcPatternElt *e; - int i; e = FcPatternFindElt (p, object); if (!e) return FcFalse; - i = e - p->elts; - /* destroy value */ FcValueListDestroy (e->values); /* shuffle existing ones down */ - memmove (e, e+1, (p->elts + p->num - (e + 1)) * sizeof (FcPatternElt)); + memmove (e, e+1, + (FcPatternEltU(p->elts) + p->num - (e + 1)) * + sizeof (FcPatternElt)); p->num--; - p->elts[p->num].object = 0; - p->elts[p->num].values = 0; + (FcPatternEltU(p->elts)+p->num)->object = FcObjectPtrCreateDynamic(0); + (FcPatternEltU(p->elts)+p->num)->values = FcValueListPtrCreateDynamic(0); return FcTrue; } FcBool FcPatternRemove (FcPattern *p, const char *object, int id) { - FcPatternElt *e; - FcValueList **prev, *l; + FcPatternElt *e; + FcValueListPtr *prev, l; e = FcPatternFindElt (p, object); if (!e) return FcFalse; - for (prev = &e->values; (l = *prev); prev = &l->next) + for (prev = &e->values; + FcValueListPtrU(l = *prev); + prev = &FcValueListPtrU(l)->next) { if (!id) { - *prev = l->next; - l->next = 0; + *prev = FcValueListPtrU(l)->next; + FcValueListPtrU(l)->next = FcValueListPtrCreateDynamic(0); FcValueListDestroy (l); - if (!e->values) + if (!FcValueListPtrU(e->values)) FcPatternDel (p, object); return FcTrue; } @@ -886,7 +980,7 @@ FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s) FcValue v; v.type = FcTypeString; - v.u.s = s; + v.u.si = FcObjectPtrCreateDynamic(s); return FcPatternAdd (p, object, v, FcTrue); } @@ -896,7 +990,7 @@ FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s) FcValue v; v.type = FcTypeMatrix; - v.u.m = (FcMatrix *) s; + v.u.mi = FcMatrixPtrCreateDynamic((FcMatrix *) s); return FcPatternAdd (p, object, v, FcTrue); } @@ -917,7 +1011,7 @@ FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c) FcValue v; v.type = FcTypeCharSet; - v.u.c = (FcCharSet *) c; + v.u.ci = FcCharSetPtrCreateDynamic((FcCharSet *)c); return FcPatternAdd (p, object, v, FcTrue); } @@ -937,7 +1031,7 @@ FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls) FcValue v; v.type = FcTypeLangSet; - v.u.l = (FcLangSet *) ls; + v.u.li = FcLangSetPtrCreateDynamic((FcLangSet *)ls); return FcPatternAdd (p, object, v, FcTrue); } @@ -945,16 +1039,16 @@ FcResult FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v) { FcPatternElt *e; - FcValueList *l; + FcValueListPtr l; e = FcPatternFindElt (p, object); if (!e) return FcResultNoMatch; - for (l = e->values; l; l = l->next) + for (l = e->values; FcValueListPtrU(l); l = FcValueListPtrU(l)->next) { if (!id) { - *v = l->value; + *v = FcValueListPtrU(l)->value; return FcResultMatch; } id--; @@ -1017,7 +1111,7 @@ FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s return r; if (v.type != FcTypeString) return FcResultTypeMismatch; - *s = (FcChar8 *) v.u.s; + *s = (FcChar8 *) FcObjectPtrU(v.u.si); return FcResultMatch; } @@ -1032,7 +1126,7 @@ FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m) return r; if (v.type != FcTypeMatrix) return FcResultTypeMismatch; - *m = (FcMatrix *) v.u.m; + *m = FcMatrixPtrU(v.u.mi); return FcResultMatch; } @@ -1063,7 +1157,7 @@ FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet ** return r; if (v.type != FcTypeCharSet) return FcResultTypeMismatch; - *c = (FcCharSet *) v.u.c; + *c = FcCharSetPtrU(v.u.ci); return FcResultMatch; } @@ -1093,7 +1187,7 @@ FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet ** return r; if (v.type != FcTypeLangSet) return FcResultTypeMismatch; - *ls = (FcLangSet *) v.u.l; + *ls = FcLangSetPtrU(v.u.li); return FcResultMatch; } @@ -1101,17 +1195,23 @@ FcPattern * FcPatternDuplicate (const FcPattern *orig) { FcPattern *new; + FcPatternElt *e; int i; - FcValueList *l; + FcValueListPtr l; new = FcPatternCreate (); if (!new) goto bail0; + e = FcPatternEltU(orig->elts); + for (i = 0; i < orig->num; i++) { - for (l = orig->elts[i].values; l; l = l->next) - if (!FcPatternAdd (new, orig->elts[i].object, l->value, FcTrue)) + for (l = (e + i)->values; + FcValueListPtrU(l); + l = FcValueListPtrU(l)->next) + if (!FcPatternAdd (new, FcObjectPtrU((e + i)->object), + FcValueListPtrU(l)->value, FcTrue)) goto bail1; } @@ -1158,45 +1258,451 @@ FcPatternAppend (FcPattern *p, FcPattern *s) { int i; FcPatternElt *e; - FcValueList *v; + FcValueListPtr v; for (i = 0; i < s->num; i++) { - e = &s->elts[i]; - for (v = e->values; v; v = v->next) + e = FcPatternEltU(s->elts)+i; + for (v = e->values; FcValueListPtrU(v); + v = FcValueListPtrU(v)->next) { - if (!FcPatternAddWithBinding (p, e->object, - v->value, v->binding, FcTrue)) + if (!FcPatternAddWithBinding (p, FcObjectPtrU(e->object), + FcValueListPtrU(v)->value, + FcValueListPtrU(v)->binding, FcTrue)) return FcFalse; } } return FcTrue; } -const char * +#define OBJECT_HASH_SIZE 31 +struct objectBucket { + struct objectBucket *next; + FcChar32 hash; +}; +static struct objectBucket **buckets = 0; + +FcObjectPtr FcObjectStaticName (const char *name) { -#define OBJECT_HASH_SIZE 31 - static struct objectBucket { - struct objectBucket *next; - FcChar32 hash; - } *buckets[OBJECT_HASH_SIZE]; FcChar32 hash = FcStringHash ((const FcChar8 *) name); struct objectBucket **p; struct objectBucket *b; + const char * nn; int size; + FcObjectPtr new; + + if (!buckets) + { + buckets = malloc(sizeof (struct objectBucket *)*OBJECT_HASH_SIZE); + memset (buckets, 0, sizeof (struct objectBucket *)*OBJECT_HASH_SIZE); + } for (p = &buckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next)) - if (b->hash == hash && !strcmp (name, (char *) (b + 1))) - return (char *) (b + 1); - size = sizeof (struct objectBucket) + strlen (name) + 1; + if (b->hash == hash && !strcmp (name, FcObjectPtrU(*((FcObjectPtr *) (b + 1))))) + return *((FcObjectPtr *) (b + 1)); + size = sizeof (struct objectBucket) + sizeof (FcObjectPtr) + 1; b = malloc (size); FcMemAlloc (FC_MEM_STATICSTR, size); if (!b) - return NULL; + return FcObjectPtrCreateDynamic(0); b->next = 0; b->hash = hash; - strcpy ((char *) (b + 1), name); + nn = malloc(strlen(name)+1); + if (!nn) + goto bail; + strcpy ((char *)nn, name); + new = FcObjectPtrCreateDynamic ((char *) nn); + *((FcObjectPtr *)(b+1)) = new; *p = b; - return (char *) (b + 1); + return new; + + bail: + free(b); + return FcObjectPtrCreateDynamic(0); +} + +FcPatternElt * +FcPatternEltU (FcPatternEltPtr pei) +{ + switch (pei.storage) + { + case FcStorageStatic: + if (pei.u.stat == 0) return 0; + return &fcpatternelts[pei.u.stat]; + case FcStorageDynamic: + return pei.u.dyn; + default: + return 0; + } +} + +static FcPatternEltPtr +FcPatternEltPtrCreateDynamic (FcPatternElt * e) +{ + FcPatternEltPtr new; + new.storage = FcStorageDynamic; + new.u.dyn = e; + return new; +} + +static FcPatternEltPtr +FcPatternEltPtrCreateStatic (int i) +{ + FcPatternEltPtr new; + new.storage = FcStorageStatic; + new.u.stat = i; + return new; +} + +static FcBool +FcPatternEltIsDynamic (FcPatternEltPtr pei) +{ + return pei.storage == FcStorageDynamic; +} + +struct objectTree { + struct objectTree * left, * right; + char * s; +}; + +FcObjectPtr +FcObjectPtrCreateDynamic (const char * s) +{ + FcObjectPtr new; + new.storage = FcStorageDynamic; + new.u.dyn = s; + if (s) + new.hash = FcStringHash(s); + else + new.hash = 0; + return new; +} + +void +FcObjectPtrDestroy (FcObjectPtr p) +{ + if (p.storage == FcStorageDynamic) + FcStrFree ((char *)p.u.dyn); +} + +const char * +FcObjectPtrU (FcObjectPtr si) +{ + switch (si.storage) + { + case FcStorageStatic: + if (si.u.stat == 0) return 0; + return &object_content[si.u.stat]; + case FcStorageDynamic: + return si.u.dyn; + default: + return 0; + } +} + +int +FcObjectPtrCompare (const FcObjectPtr a, const FcObjectPtr b) +{ + int r = a.hash - b.hash; + + if (r == 0) + return strcmp (FcObjectPtrU(a), FcObjectPtrU(b)); + return r; +} + +void +FcObjectClearStatic(void) +{ + object_content = 0; + object_content_count = 0; + object_content_ptr = 0; +} + +static FcObjectPtr +FcObjectSerialize (FcObjectPtr si) +{ + struct objectBucket **p; + struct objectBucket *b; + + if (!object_content) + { + object_content = malloc(object_content_count * sizeof(char)); + if (!object_content) + return FcObjectPtrCreateDynamic(0); + } + + if (!buckets) + return FcObjectPtrCreateDynamic(0); + + for (p = &buckets[si.hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next)) + if (b->hash == si.hash && !strcmp (FcObjectPtrU(si), FcObjectPtrU(*((FcObjectPtr *) (b + 1))))) + { + FcObjectPtr *op = (FcObjectPtr *) (b + 1); + if (op->storage == FcStorageStatic) + return *op; + + if (object_content_ptr >= object_content_count) + return FcObjectPtrCreateDynamic(0); + + strcpy (object_content+object_content_ptr, + FcObjectPtrU(si)); + + op->storage = FcStorageStatic; + op->u.stat = object_content_ptr; + + object_content_ptr += strlen(FcObjectPtrU(si))+1; + + return *op; + } + + return FcObjectPtrCreateDynamic(0); +} + +FcBool +FcObjectPrepareSerialize (FcObjectPtr si) +{ + object_content_count += strlen(FcObjectPtrU(si)) + 1; + return FcTrue; +} + +void +FcPatternClearStatic (void) +{ + fcpatterns = 0; + fcpattern_ptr = 0; + fcpattern_count = 0; + + fcpatternelts = 0; + fcpatternelt_ptr = 0; + fcpatternelt_count = 0; +} + +void +FcValueListClearStatic (void) +{ + fcvaluelists = 0; + fcvaluelist_ptr = 0; + fcvaluelist_count = 0; +} + +FcBool +FcPatternPrepareSerialize (FcPattern * p) +{ + int i; + + fcpattern_count++; + fcpatternelt_count += p->num; + + for (i = 0; i < p->num; i++) + { + FcObjectPrepareSerialize + ((FcPatternEltU(p->elts)+i)->object); + if (!FcValueListPrepareSerialize + (FcValueListPtrU(((FcPatternEltU(p->elts)+i)->values)))) + return FcFalse; + } + + return FcTrue; +} + +FcBool +FcValueListPrepareSerialize (FcValueList *p) +{ + FcValueList *vl; + + for (vl = p; + vl; + vl = FcValueListPtrU(vl->next)) + { + FcValue v = vl->value; + + switch (v.type) + { + case FcTypeMatrix: + FcMatrixPrepareSerialize(FcMatrixPtrU(v.u.mi)); + break; + case FcTypeCharSet: + FcCharSetPrepareSerialize(FcCharSetPtrU(v.u.ci)); + break; + case FcTypeLangSet: + FcLangSetPrepareSerialize(FcLangSetPtrU(v.u.li)); + break; + case FcTypeString: + FcObjectPrepareSerialize(v.u.si); + default: + break; + } + fcvaluelist_count++; + } + + return FcTrue; +} + +FcPattern * +FcPatternSerialize (FcPattern *old) +{ + FcPattern *p; + FcPatternElt *e, *nep; + FcValueList * nv; + FcValueListPtr v, nv_head, nvp; + int i, elts; + + if (!fcpatterns) + { + p = malloc (sizeof (FcPattern) * fcpattern_count); + if (!p) + goto bail; + + FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern) * fcpattern_count); + fcpatterns = p; + fcpattern_ptr = 0; + + e = malloc (sizeof (FcPatternElt) * fcpatternelt_count); + if (!e) + goto bail1; + + FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt) * fcpatternelt_count); + fcpatternelts = e; + fcpatternelt_ptr = 0; + } + + p = FcPatternCreate(); + elts = fcpatternelt_ptr; + nep = &fcpatternelts[elts]; + if (!nep) + return FcFalse; + fcpatternelt_ptr += old->num; + + for (e = FcPatternEltU(old->elts), i=0; i < old->num; i++, e++) + { + v = e->values; + nvp = nv_head = FcValueListSerialize(FcValueListPtrU(v)); + if (!FcValueListPtrU(nv_head)) + goto bail2; + nv = FcValueListPtrU(nvp); + + for (; + FcValueListPtrU(v); + v = FcValueListPtrU(v)->next, + nv = FcValueListPtrU(nv->next)) + { + + if (FcValueListPtrU(FcValueListPtrU(v)->next)) + { + nvp = FcValueListSerialize + (FcValueListPtrU(FcValueListPtrU(v)->next)); + nv->next = nvp; + } + } + + nep[i].values = nv_head; + nep[i].object = FcObjectSerialize + (FcObjectStaticName(FcObjectPtrU(e->object))); + } + + p->elts = FcPatternEltPtrCreateStatic(elts); + p->size = old->num; + p->ref = FC_REF_CONSTANT; + return p; + + bail2: + free (fcpatternelts); + bail1: + free (fcpatterns); + bail: + return 0; + } + +FcValueListPtr +FcValueListSerialize(FcValueList *pi) +{ + FcValueListPtr new; + FcValue * v; + FcValueList * vl; + + if (!fcvaluelists) + { + vl = malloc (sizeof (FcValueList) * fcvaluelist_count); + if (!vl) + return FcValueListPtrCreateDynamic(0); + + FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList) * fcvaluelist_count); + fcvaluelists = vl; + fcvaluelist_ptr = 0; + } + + fcvaluelists[fcvaluelist_ptr] = *pi; + new.storage = FcStorageStatic; + new.u.stat = fcvaluelist_ptr++; + v = &fcvaluelists[new.u.stat].value; + switch (v->type) + { + case FcTypeString: + if (FcObjectPtrU(v->u.si)) + { + FcObjectPtr si = + FcObjectSerialize(FcObjectStaticName(FcObjectPtrU(v->u.si))); + if (!FcObjectPtrU(v->u.si)) + return FcValueListPtrCreateDynamic(pi); + v->u.si = si; + } + break; + case FcTypeMatrix: + if (FcMatrixPtrU(v->u.mi)) + { + FcMatrixPtr mi = FcMatrixSerialize(FcMatrixPtrU(v->u.mi)); + + if (!FcMatrixPtrU(mi)) + return FcValueListPtrCreateDynamic(pi); + v->u.mi = mi; + } + break; + case FcTypeCharSet: + if (FcCharSetPtrU(v->u.ci)) + { + FcCharSetPtr ci = FcCharSetSerialize(FcCharSetPtrU(v->u.ci)); + if (!FcCharSetPtrU(v->u.ci)) + return FcValueListPtrCreateDynamic(pi); + v->u.ci = ci; + } + break; + case FcTypeLangSet: + if (FcLangSetPtrU(v->u.li)) + { + FcLangSetPtr li = FcLangSetSerialize(FcLangSetPtrU(v->u.li)); + if (!FcLangSetPtrU(v->u.li)) + return FcValueListPtrCreateDynamic(pi); + v->u.li = li; + } + break; + default: + break; + } + return new; +} + +FcValueList * +FcValueListPtrU (FcValueListPtr pi) +{ + switch (pi.storage) + { + case FcStorageStatic: + if (pi.u.stat == 0) return 0; + return &fcvaluelists[pi.u.stat]; + case FcStorageDynamic: + return pi.u.dyn; + default: + return 0; + } +} + +FcValueListPtr +FcValueListPtrCreateDynamic(FcValueList * p) +{ + FcValueListPtr r; + + r.storage = FcStorageDynamic; + r.u.dyn = p; + return r; } diff --git a/src/fcstr.c b/src/fcstr.c index 730e440..1391b65 100644 --- a/src/fcstr.c +++ b/src/fcstr.c @@ -848,10 +848,67 @@ FcStrSetCreate (void) set->ref = 1; set->num = 0; set->size = 0; - set->strs = 0; + set->storage = FcStorageDynamic; + set->u.strs = 0; 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 _FcStrSetAppend (FcStrSet *set, FcChar8 *s) { @@ -860,7 +917,7 @@ _FcStrSetAppend (FcStrSet *set, FcChar8 *s) FcStrFree (s); return FcTrue; } - if (set->num == set->size) + if (set->num == set->size || set->storage == FcStorageStatic) { FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *)); @@ -868,14 +925,24 @@ _FcStrSetAppend (FcStrSet *set, FcChar8 *s) return FcFalse; FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *)); set->size = set->size + 1; - if (set->num) - memcpy (strs, set->strs, set->num * sizeof (FcChar8 *)); - if (set->strs) - free (set->strs); - set->strs = strs; + if (set->storage == FcStorageDynamic) + { + if (set->num) + memcpy (strs, set->u.strs, set->num * sizeof (FcChar8 *)); + 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->strs[set->num] = 0; + set->u.strs[set->num++] = s; + set->u.strs[set->num] = 0; return FcTrue; } @@ -885,7 +952,7 @@ FcStrSetMember (FcStrSet *set, const FcChar8 *s) int i; for (i = 0; i < set->num; i++) - if (!FcStrCmp (set->strs[i], s)) + if (!FcStrCmp (FcStrSetGet(set, i), s)) return FcTrue; return FcFalse; } @@ -897,7 +964,7 @@ FcStrSetEqual (FcStrSet *sa, FcStrSet *sb) if (sa->num != sb->num) return FcFalse; for (i = 0; i < sa->num; i++) - if (!FcStrSetMember (sb, sa->strs[i])) + if (!FcStrSetMember (sb, FcStrSetGet(sa, i))) return FcFalse; return FcTrue; } @@ -936,14 +1003,15 @@ FcStrSetDel (FcStrSet *set, const FcChar8 *s) int 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 * NULL */ - memmove (&set->strs[i], &set->strs[i+1], + memmove (FcStrSetGet(set, i), FcStrSetGet(set, i+1), (set->num - i) * sizeof (FcChar8 *)); set->num--; return FcTrue; @@ -958,16 +1026,123 @@ FcStrSetDestroy (FcStrSet *set) { int i; - for (i = 0; i < set->num; i++) - FcStrFree (set->strs[i]); - FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *)); - if (set->strs) - free (set->strs); - FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet)); + if (set->storage == FcStorageDynamic) + { + for (i = 0; i < set->num; i++) + FcStrFree (set->u.strs[i]); + FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *)); + if (set->u.strs) + free (set->u.strs); + FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet)); + } 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 * FcStrListCreate (FcStrSet *set) { @@ -988,7 +1163,7 @@ FcStrListNext (FcStrList *list) { if (list->n >= list->set->num) return 0; - return list->set->strs[list->n++]; + return FcStrSetGet(list->set, list->n++); } void diff --git a/src/fcxml.c b/src/fcxml.c index 539e57f..1a3270b 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -1878,8 +1878,8 @@ FcPopValue (FcConfigParse *parse) switch (vstack->tag) { case FcVStackString: - value.u.s = FcStrCopy (vstack->u.string); - if (value.u.s) + value.u.si = FcObjectPtrCreateDynamic(FcStrCopy (vstack->u.string)); + if (FcObjectPtrU(value.u.si)) value.type = FcTypeString; break; case FcVStackConstant: @@ -1895,8 +1895,8 @@ FcPopValue (FcConfigParse *parse) value.type = FcTypeInteger; break; case FcVStackMatrix: - value.u.m = FcMatrixCopy (vstack->u.matrix); - if (value.u.m) + value.u.mi = FcMatrixPtrCreateDynamic(FcMatrixCopy (vstack->u.matrix)); + if (FcMatrixPtrU(value.u.mi)) value.type = FcTypeMatrix; break; case FcVStackBool: @@ -2281,10 +2281,9 @@ FcConfigParseAndLoadDir (FcConfig *config, if (ret) { int i; - qsort (files->strs, files->num, sizeof (FcChar8 *), - (int (*)(const void *, const void *)) FcStrCmp); + FcStrSetSort (files); for (i = 0; ret && i < files->num; i++) - ret = FcConfigParseAndLoad (config, files->strs[i], complain); + ret = FcConfigParseAndLoad (config, FcStrSetGet(files, i), complain); } bail3: FcStrSetDestroy (files);