]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcname.c
Properly convert static charsets to dynamic charsets.
[fontconfig.git] / src / fcname.c
index a2524ad82d22116506c9685e6ec8786cffc7453d..a0a84a394237ceb1f83742a1f8175645ab05f0a0 100644 (file)
 #include <stdio.h>
 #include "fcint.h"
 
+/* Please do not revoke any of these bindings. */
+/* The __DUMMY__ object enables callers to distinguish the error return
+ * of FcObjectToPtrLookup from FC_FAMILY's FcObjectPtr, which would
+ * otherwise be 0. */
 static const FcObjectType _FcBaseObjectTypes[] = {
+    { "__DUMMY__",      FcTypeVoid, }, 
     { FC_FAMILY,       FcTypeString, },
     { FC_FAMILYLANG,   FcTypeString, },
     { FC_STYLE,                FcTypeString, },
@@ -59,8 +64,8 @@ static const FcObjectType _FcBaseObjectTypes[] = {
     { FC_DPI,          FcTypeDouble },
     { FC_RGBA,         FcTypeInteger, },
     { FC_SCALE,                FcTypeDouble, },
-/*    { FC_RENDER,     FcTypeBool, },*/
     { FC_MINSPACE,     FcTypeBool, },
+/*    { FC_RENDER,     FcTypeBool, },*/
     { FC_CHAR_WIDTH,   FcTypeInteger },
     { FC_CHAR_HEIGHT,  FcTypeInteger },
     { FC_MATRIX,       FcTypeMatrix },
@@ -70,22 +75,29 @@ static const FcObjectType _FcBaseObjectTypes[] = {
     { FC_CAPABILITY,   FcTypeString },
     { FC_FONTFORMAT,   FcTypeString },
     { FC_EMBOLDEN,     FcTypeBool },
+    { FC_EMBEDDED_BITMAP,   FcTypeBool },
 };
 
 #define NUM_OBJECT_TYPES    (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
 
+static FcObjectType * _FcUserObjectNames = 0;
+static int user_obj_alloc = 0;
+static int next_basic_offset = NUM_OBJECT_TYPES;
+
 typedef struct _FcObjectTypeList    FcObjectTypeList;
 
 struct _FcObjectTypeList {
     const FcObjectTypeList  *next;
     const FcObjectType     *types;
     int                            ntypes;
+    int                            basic_offset;
 };
 
 static const FcObjectTypeList _FcBaseObjectTypesList = {
     0,
     _FcBaseObjectTypes,
-    NUM_OBJECT_TYPES
+    NUM_OBJECT_TYPES,
+    0
 };
 
 static const FcObjectTypeList  *_FcObjectTypes = &_FcBaseObjectTypesList;
@@ -102,12 +114,15 @@ FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
     l->types = types;
     l->ntypes = ntypes;
     l->next = _FcObjectTypes;
+    l->basic_offset = next_basic_offset;
+    next_basic_offset += ntypes;
     _FcObjectTypes = l;
     return FcTrue;
 }
 
-FcBool
-FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
+static FcBool
+FcNameUnregisterObjectTypesFree (const FcObjectType *types, int ntypes, 
+                                FcBool do_free)
 {
     const FcObjectTypeList     *l, **prev;
 
@@ -118,14 +133,22 @@ FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
        if (l->types == types && l->ntypes == ntypes)
        {
            *prev = l->next;
-           FcMemFree (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
-           free ((void *) l);
+           if (do_free) {
+               FcMemFree (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
+               free ((void *) l);
+           }
            return FcTrue;
        }
     }
     return FcFalse;
 }
 
+FcBool
+FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
+{
+    return FcNameUnregisterObjectTypesFree (types, ntypes, FcTrue);
+}
+
 const FcObjectType *
 FcNameGetObjectType (const char *object)
 {
@@ -135,6 +158,9 @@ FcNameGetObjectType (const char *object)
     
     for (l = _FcObjectTypes; l; l = l->next)
     {
+        if (l == (FcObjectTypeList*)_FcUserObjectNames)
+            continue;
+
        for (i = 0; i < l->ntypes; i++)
        {
            t = &l->types[i];
@@ -145,6 +171,249 @@ FcNameGetObjectType (const char *object)
     return 0;
 }
 
+#define OBJECT_HASH_SIZE    31
+struct objectBucket {
+    struct objectBucket        *next;
+    FcChar32           hash;
+    int                        id;
+};
+static struct objectBucket *FcObjectBuckets[OBJECT_HASH_SIZE];
+
+/* Design constraint: biggest_known_ntypes must never change
+ * after any call to FcNameRegisterObjectTypes. */
+static const FcObjectType *biggest_known_types = _FcBaseObjectTypes; 
+static FcBool allocated_biggest_known_types;
+static int biggest_known_ntypes = NUM_OBJECT_TYPES;
+static int biggest_known_count = 0;
+static char * biggest_ptr;
+
+
+static FcObjectPtr
+FcObjectToPtrLookup (const char * object)
+{
+    FcObjectPtr                    i = 0, n;
+    const FcObjectTypeList  *l;
+    FcObjectType           *t = _FcUserObjectNames;
+
+    for (l = _FcObjectTypes; l; l = l->next)
+    {
+       for (i = 0; i < l->ntypes; i++)
+       {
+           t = (FcObjectType *)&l->types[i];
+           if (!strcmp (object, t->object))
+           {
+               if (l == (FcObjectTypeList*)_FcUserObjectNames)
+                    return -i;
+               else
+                   return l->basic_offset + i;
+           }
+       }
+    }
+
+    /* We didn't match.  Look for the application's FcObjectTypeList
+     * and replace it in-place. */
+    for (l = _FcObjectTypes; l; l = l->next)
+    {
+       if (l->types == _FcUserObjectNames)
+           break;
+    }
+
+    if (!_FcUserObjectNames || 
+        (l && l->types == _FcUserObjectNames && user_obj_alloc < l->ntypes))
+    {
+       int nt = user_obj_alloc + 4;
+        FcObjectType * t = realloc (_FcUserObjectNames, 
+                                   nt * sizeof (FcObjectType));
+        if (!t)
+            return 0;
+       _FcUserObjectNames = t;
+       user_obj_alloc = nt;
+    }
+
+    if (l && l->types == _FcUserObjectNames)
+    {
+       n = l->ntypes;
+       FcNameUnregisterObjectTypesFree (l->types, l->ntypes, FcFalse);
+    }
+    else
+       n = 0;
+
+    FcNameRegisterObjectTypes (_FcUserObjectNames, n+1);
+
+    for (l = _FcObjectTypes; l; l = l->next)
+    {
+       if (l->types == _FcUserObjectNames)
+       {
+           t = (FcObjectType *)l->types;
+           break;
+       }
+    }
+
+    if (!t)
+       return 0;
+
+    t[n].object = object;
+    t[n].type = FcTypeVoid;
+
+    return -n;
+}
+
+FcObjectPtr
+FcObjectToPtr (const char * name)
+{
+    FcChar32            hash = FcStringHash ((const FcChar8 *) name);
+    struct objectBucket **p;
+    struct objectBucket *b;
+    int                 size;
+
+    for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next)
+)
+        if (b->hash == hash && !strcmp (name, (char *) (b + 1)))
+            return b->id;
+    size = sizeof (struct objectBucket) + strlen (name) + 1;
+    /* workaround glibc bug which reads strlen in groups of 4 */
+    b = malloc (size + sizeof (int));
+    FcMemAlloc (FC_MEM_STATICSTR, size + sizeof(int));
+    if (!b)
+        return 0;
+    b->next = 0;
+    b->hash = hash;
+    b->id = FcObjectToPtrLookup (name);
+    strcpy ((char *) (b + 1), name);
+    *p = b;
+    return b->id;
+}
+
+void
+FcObjectStaticNameFini (void)
+{
+    int i, size;
+    struct objectBucket *b, *next;
+    char *name;
+
+    for (i = 0; i < OBJECT_HASH_SIZE; i++)
+    {
+       for (b = FcObjectBuckets[i]; b; b = next)
+       {
+           next = b->next;
+           name = (char *) (b + 1);
+           size = sizeof (struct objectBucket) + strlen (name) + 1;
+           FcMemFree (FC_MEM_STATICSTR, size);
+           free (b);
+       }
+       FcObjectBuckets[i] = 0;
+    }
+}
+
+const char *
+FcObjectPtrU (FcObjectPtr si)
+{
+    const FcObjectTypeList  *l;
+    int i, j;
+
+    if (si > 0)
+    {
+        if (si < biggest_known_ntypes)
+            return biggest_known_types[si].object;
+
+        j = 0;
+        for (l = _FcObjectTypes; l; l = l->next)
+            for (i = 0; i < l->ntypes; i++, j++)
+                if (j == si)
+                    return l->types[i].object;
+    }
+
+    return _FcUserObjectNames[-si].object;
+}
+
+int
+FcObjectNeededBytes ()
+{
+    int num = 0, i;
+    for (i = 0; i < biggest_known_ntypes; i++)
+    {
+       const char * t = biggest_known_types[i].object;
+       num = num + strlen(t) + 1;
+    }
+    biggest_known_count = num;
+    return num + sizeof(int);
+}
+
+int
+FcObjectNeededBytesAlign (void)
+{
+    return fc_alignof (int) + fc_alignof (char);
+}
+
+void *
+FcObjectDistributeBytes (FcCache * metadata, void * block_ptr)
+{
+    block_ptr = ALIGN (block_ptr, int);
+    *(int *)block_ptr = biggest_known_ntypes;
+    block_ptr = (int *) block_ptr + 1;
+    block_ptr = ALIGN (block_ptr, char);
+    biggest_ptr = block_ptr;
+    block_ptr = (char *) block_ptr + biggest_known_count;
+    return block_ptr;
+}
+
+void
+FcObjectSerialize (void)
+{
+    int i;
+    for (i = 0; i < biggest_known_ntypes; i++)
+    {
+       const char * t = biggest_known_types[i].object;
+       strcpy (biggest_ptr, t);
+       biggest_ptr = biggest_ptr + strlen(t) + 1;
+    }
+}
+
+void *
+FcObjectUnserialize (FcCache * metadata, void *block_ptr)
+{
+    int new_biggest;
+    block_ptr = ALIGN (block_ptr, int);
+    new_biggest = *(int *)block_ptr;
+    block_ptr = (int *) block_ptr + 1;
+    if (biggest_known_ntypes < new_biggest)
+    {
+       int i;
+       char * bp = (char *)block_ptr;
+       FcObjectType * bn;
+
+       bn = malloc (sizeof (const FcObjectType) * (new_biggest + 1));
+       if (!bn)
+           return 0;
+
+       for (i = 0; i < new_biggest; i++)
+       {
+           const FcObjectType * t = FcNameGetObjectType(bp);
+           if (t)
+               bn[i].type = t->type;
+           else
+               bn[i].type = FcTypeVoid;
+           bn[i].object = bp;
+           bp = bp + strlen(bp) + 1;
+       }
+
+       FcNameUnregisterObjectTypesFree (biggest_known_types, biggest_known_ntypes, FcFalse);
+       if (allocated_biggest_known_types)
+       {
+           free ((FcObjectTypeList *)biggest_known_types);
+       }
+       else
+           allocated_biggest_known_types = FcTrue;
+
+       FcNameRegisterObjectTypes (bn, new_biggest);
+       biggest_known_ntypes = new_biggest;
+       biggest_known_types = (const FcObjectType *)bn;
+    }
+    block_ptr = ALIGN (block_ptr, char);
+    block_ptr = (char *) block_ptr + biggest_known_count;
+    return block_ptr;
+}
+
 static const FcConstant _FcBaseConstants[] = {
     { (FcChar8 *) "thin",          "weight",   FC_WEIGHT_THIN, },
     { (FcChar8 *) "extralight",            "weight",   FC_WEIGHT_EXTRALIGHT, },
@@ -321,7 +590,7 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
            v.u.i = atoi ((char *) string);
        break;
     case FcTypeString:
-       v.u.si = FcObjectStaticName(string);
+       v.u.s = FcStrStaticName(string);
        break;
     case FcTypeBool:
        if (!FcNameBool (string, &v.u.b))
@@ -331,14 +600,14 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
        v.u.d = strtod ((char *) string, 0);
        break;
     case FcTypeMatrix:
-       v.u.mi = FcMatrixPtrCreateDynamic(m);
+       v.u.m = m;
        sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
        break;
     case FcTypeCharSet:
-       v.u.ci = FcCharSetPtrCreateDynamic(FcNameParseCharSet (string));
+       v.u.c = FcNameParseCharSet (string);
        break;
     case FcTypeLangSet:
-       v.u.li = FcLangSetPtrCreateDynamic(FcNameParseLangSet (string));
+       v.u.l = FcNameParseLangSet (string);
        break;
     default:
        break;
@@ -429,17 +698,17 @@ FcNameParse (const FcChar8 *name)
                for (;;)
                {
                    name = FcNameFindNext (name, ":,", save, &delim);
-                   if (t)
+                   if (t && strcmp (t->object, _FcBaseObjectTypes[0].object))
                    {
                        v = FcNameConvert (t->type, save, &m);
                        if (!FcPatternAdd (pat, t->object, v, FcTrue))
                        {
                            switch (v.type) {
                            case FcTypeCharSet:
-                               FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci));
+                               FcCharSetDestroy ((FcCharSet *) v.u.c);
                                break;
                            case FcTypeLangSet:
-                               FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li));
+                               FcLangSetDestroy ((FcLangSet *) v.u.l);
                                break;
                            default:
                                break;
@@ -448,10 +717,10 @@ FcNameParse (const FcChar8 *name)
                        }
                        switch (v.type) {
                        case FcTypeCharSet:
-                           FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci));
+                           FcCharSetDestroy ((FcCharSet *) v.u.c);
                            break;
                        case FcTypeLangSet:
-                           FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li));
+                           FcLangSetDestroy ((FcLangSet *) v.u.l);
                            break;
                        default:
                            break;
@@ -503,10 +772,11 @@ FcNameUnparseString (FcStrBuf         *buf,
 
 static FcBool
 FcNameUnparseValue (FcStrBuf   *buf,
-                   FcValue     v,
+                   FcValue     *v0,
                    FcChar8     *escape)
 {
     FcChar8    temp[1024];
+    FcValue v = FcValueCanonicalize(v0);
     
     switch (v.type) {
     case FcTypeVoid:
@@ -518,20 +788,17 @@ FcNameUnparseValue (FcStrBuf      *buf,
        sprintf ((char *) temp, "%g", v.u.d);
        return FcNameUnparseString (buf, temp, 0);
     case FcTypeString:
-       return FcNameUnparseString (buf, FcObjectPtrU(v.u.si), escape);
+       return FcNameUnparseString (buf, v.u.s, 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", 
-                m->xx, m->xy, m->yx, m->yy);
+                v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
        return FcNameUnparseString (buf, temp, 0);
-    }
     case FcTypeCharSet:
-       return FcNameUnparseCharSet (buf, FcCharSetPtrU(v.u.ci));
+       return FcNameUnparseCharSet (buf, v.u.c);
     case FcTypeLangSet:
-       return FcNameUnparseLangSet (buf, FcLangSetPtrU(v.u.li));
+       return FcNameUnparseLangSet (buf, v.u.l);
     case FcTypeFTFace:
        return FcTrue;
     }
@@ -545,7 +812,7 @@ FcNameUnparseValueList (FcStrBuf    *buf,
 {
     while (FcValueListPtrU(v))
     {
-       if (!FcNameUnparseValue (buf, FcValueListPtrU(v)->value, escape))
+       if (!FcNameUnparseValue (buf, &FcValueListPtrU(v)->value, escape))
            return FcFalse;
        if (FcValueListPtrU(v = FcValueListPtrU(v)->next))
            if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
@@ -559,6 +826,12 @@ FcNameUnparseValueList (FcStrBuf   *buf,
 
 FcChar8 *
 FcNameUnparse (FcPattern *pat)
+{
+    return FcNameUnparseEscaped (pat, FcTrue);
+}
+
+FcChar8 *
+FcNameUnparseEscaped (FcPattern *pat, FcBool escape)
 {
     FcStrBuf               buf;
     FcChar8                buf_static[8192];
@@ -571,7 +844,7 @@ FcNameUnparse (FcPattern *pat)
     e = FcPatternFindElt (pat, FC_FAMILY);
     if (e)
     {
-       if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
+        if (!FcNameUnparseValueList (&buf, e->values, escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
            goto bail0;
     }
     e = FcPatternFindElt (pat, FC_SIZE);
@@ -579,7 +852,7 @@ FcNameUnparse (FcPattern *pat)
     {
        if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
            goto bail0;
-       if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
+       if (!FcNameUnparseValueList (&buf, e->values, escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
            goto bail0;
     }
     for (l = _FcObjectTypes; l; l = l->next)
@@ -597,12 +870,12 @@ FcNameUnparse (FcPattern *pat)
            {
                if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
                    goto bail0;
-               if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, (FcChar8 *) FC_ESCAPE_VARIABLE))
+               if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
                    goto bail0;
                if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
                    goto bail0;
-               if (!FcNameUnparseValueList (&buf, e->values, 
-                                            (FcChar8 *) FC_ESCAPE_VARIABLE))
+               if (!FcNameUnparseValueList (&buf, e->values, escape ? 
+                                            (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
                    goto bail0;
            }
        }