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

17 files changed:
fc-lang/fc-lang.c
fontconfig/fcprivate.h
fontconfig/fontconfig.h
src/fccache.c
src/fccfg.c
src/fccharset.c
src/fcdbg.c
src/fcfs.c
src/fcint.h
src/fclang.c
src/fclist.c
src/fcmatch.c
src/fcmatrix.c
src/fcname.c
src/fcpat.c
src/fcstr.c
src/fcxml.c

index e88d75fe0ccb8a0b6e4654543710d6638c7ddc49..a2699a3c7d23bc0065293101e1f89cb4438a15d0 100644 (file)
@@ -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]);
     }
index ac68bfc0fcd1f5b5472f149215d9dd74c298508f..2b73945bb71f88f4774c7233f034adc071538e0a 100644 (file)
            __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))            \
index 79e9cfd0cdeee8c220f78714616ca6639e0c0ead..1bc726216fb3f5369a9ba10a93cb599bcef8064d 100644 (file)
@@ -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
index 28455430a62a2777e6cf12a8df1437622653359e..a9d87019892527e23547931f31eec10d44458a7b 100644 (file)
@@ -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;
+}
index 84c21e791c43ac145909d300291e8a6443048173..1ce7cbe06dcf012787b4b0dc2810688dfc59bee1 100644 (file)
@@ -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;
 }
index 8003bccc3a009fcfefd1ea970434c76a4fd10c64..6c6f0f5d79b247f32824a75aaa9d952562f87a48 100644 (file)
 
 /* #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++)
-    {
-       FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
-       free (fcs->leaves[i]);
-    }
-    if (fcs->leaves)
+    if (fcs->storage == FcStorageDynamic)
     {
-       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 *));
-    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));
+    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
-       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)
-    {
-       FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
-       free (b->leaves);
-    }
-    if (b->numbers)
+    if (b->storage == FcStorageDynamic)
     {
-       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)
-    {
-       FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
-       free (c->leaves);
-    }
-    if (c->numbers)
+    if (c->storage == FcStorageDynamic)
     {
-       FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
-       free (c->numbers);
+       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));
     }
-    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;
+    }
+}
+
index cd72edad8f8cb41345ed2fa3aa0ebfcc5bebd581..c8b7127b356ae97fc5a5283ee7d41a5ff06aad45 100644 (file)
@@ -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");
     }
index b05688d97fcff8f27aafe8393945bec23bf00d25..c2020402e663093d1b8fbb8764e05e445c8f907a 100644 (file)
@@ -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();
+}
index 24bf246a5e45824784a41ee85f15b7cba97da631..fe2c095c3e5fc6c687f04553afbea091595f5480 100644 (file)
@@ -41,6 +41,7 @@
 #include <config.h>
 #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 _FcPatternEltPtr {
+    FcStorage               storage;
+    union {
+        int                stat;
+        struct _FcPatternElt *dyn;
+    } u;
+} FcPatternEltPtr;
+
 typedef struct _FcPatternElt {
-    const char     *object;
-    FcValueList            *values;
+    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);
 
index fabf36a15d7c15584e9a0840c2dbf5948c57c5ed..28b2d9b9c6965755b72b80981da54eafc7d3b1b3 100644 (file)
@@ -22,6 +22,8 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <fcntl.h>
+#include <sys/mman.h>
 #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;
+}
index ec47ddcabcec41fcf7780cdf59fc67c722af11a8..b3ecdb82cf2d71e792355093fd88fcad315475da 100644 (file)
@@ -23,6 +23,9 @@
  */
 
 #include <stdlib.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
 #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;
            }
        }
index 9a6b35fba06aaf42ed991c959ffeda0ff779a27f..9e70271687176ef8af900f5cff81643fe61b46e4 100644 (file)
@@ -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;
index 863fe692c9056a84aa5676d1114048ca7b8ef635..6a5aa5dd8fa6b71b79f298ae7ad9d0e1b7dcae8d 100644 (file)
 #include <ctype.h>
 #include "fcint.h"
 
-const FcMatrix    FcIdentityMatrix = { 1, 0, 0, 1 };
+FcMatrix    _id = { 1, 0, 0, 1 };
+const FcMatrixPtr    FcIdentityMatrix = {
+    .storage = FcStorageDynamic,
+    .u.dyn = &_id
+};
 
 FcMatrix *
 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;
+}
+
index 3b9454dd477abb682f930da391342e4c2a93920d..d49ec0812aac87420bb8d93fc0f12c260c0c92d5 100644 (file)
@@ -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;
     }
index c886c9258e0fa7887f9a592ffc10e9bcc4d8972c..af682059315e526a0abd8c7700ad58e11be6b732 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <sys/mman.h>
 #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;
 }
index 730e44061eecfaa475bf6a598bc1a42a70a22c06..1391b6554dbc5dede8a737e839853114448d8108 100644 (file)
@@ -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;
-    }
-    set->strs[set->num++] = s;
-    set->strs[set->num] = 0;
+       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->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
index 539e57fafb66b3567bc1cdc8ebfb5a2179b47c69..1a3270bb4a3a63792d75e58108e6173e42e97a76 100644 (file)
@@ -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);