[Fontconfig] fontconfig: Branch 'fc-2_4-keithp'

Keith Packard keithp at kemper.freedesktop.org
Wed Aug 30 18:51:18 PDT 2006


 fc-case/fc-case.c |   13 -
 src/fcint.h       |    7 
 src/fcmatch.c     |    9 -
 src/fcname.c      |  393 ++++++++++++++++++++++++++++++------------------------
 src/fcpat.c       |    2 
 5 files changed, 235 insertions(+), 189 deletions(-)

New commits:
diff-tree 09f9f6f62ac94f7b1a6df649a00c64f78ab132f5 (from c02886485b293179e8492cad9a34eb431dd4bfc9)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Aug 30 18:50:58 2006 -0700

    Rework Object name database to unify typechecking and object lookup.
    
    Eliminate ancient list of object name databases and load names into single
    hash table that includes type information. Typecheck all pattern values to
    avoid mis-typed pattern elements.

diff --git a/fc-case/fc-case.c b/fc-case/fc-case.c
index bd28517..a4fffde 100644
--- a/fc-case/fc-case.c
+++ b/fc-case/fc-case.c
@@ -28,19 +28,6 @@
 #define MAX_OUT	    32
 #define MAX_LINE    8192
 
-/* stub definitions for declarations from fcint.h.. */
-int * _fcBankId = 0, * _fcBankIdx = 0;
-FcValueList ** _fcValueLists = 0;
-FcPatternElt ** _fcPatternElts = 0;
-int FcDebugVal = 0;
-
-int
-FcCacheBankToIndexMTF (int bank)
-{
-    return 0;
-}
-/* end stub definitions */
-
 typedef enum _caseFoldClass { CaseFoldCommon, CaseFoldFull, CaseFoldSimple, CaseFoldTurkic } CaseFoldClass;
 
 typedef struct _caseFoldClassMap {
diff --git a/src/fcint.h b/src/fcint.h
index adb3b16..c62a5bb 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -858,10 +858,13 @@ FcObjectFromName (const char * name);
 const char *
 FcObjectName (FcObject object);
 
-#define FcObjectCompare(a, b)	((int) a - (int) b)
+FcBool
+FcObjectInit (void);
 
 void
-FcObjectStaticNameFini (void);
+FcObjectFini (void);
+
+#define FcObjectCompare(a, b)	((int) a - (int) b)
 
 /* fcpat.c */
 
diff --git a/src/fcmatch.c b/src/fcmatch.c
index 7e3353b..d688c98 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -313,7 +313,7 @@ FcCompareValueList (FcObject	 object,
     j = 0;
     for (v1 = v1orig; v1; v1 = FcValueListNext(v1))
     {
-	for (v2 = v1orig; v2; v2 = FcValueListNext(v2))
+	for (v2 = v2orig; v2; v2 = FcValueListNext(v2))
 	{
 	    v = (match->compare) (&v1->value, &v2->value);
 	    if (v < 0)
@@ -608,7 +608,7 @@ FcSortWalk (FcSortNode **n, int nnode, F
                 }
 
 		FcPatternReference (node->pattern);
-		if (FcDebug () & FC_DBG_MATCH)
+		if (FcDebug () & FC_DBG_MATCHV)
 		{
 		    printf ("Add ");
 		    FcPatternPrint (node->pattern);
@@ -788,6 +788,11 @@ FcFontSetSort (FcConfig	    *config,
 
     free (nodes);
 
+    if (FcDebug() & FC_DBG_MATCH)
+    {
+	printf ("First font ");
+	FcPatternPrint (ret->fonts[0]);
+    }
     return ret;
 
 bail2:
diff --git a/src/fcname.c b/src/fcname.c
index 96adc62..74411d7 100644
--- a/src/fcname.c
+++ b/src/fcname.c
@@ -28,13 +28,14 @@
 #include <string.h>
 #include <stdio.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 FcObject, which would
- * otherwise be 0. */
+/* 
+ * Please do not change this list, it is used to initialize the object
+ * list in this order to match the FC_foo_OBJECT constants. Those 
+ * constants are written into cache files.
+ */
+
 static const FcObjectType _FcBaseObjectTypes[] = {
-    { "__DUMMY__",      FcTypeVoid, }, 
-    { FC_FAMILY,	FcTypeString, },
+    { FC_FAMILY,	FcTypeString, },    /* 1 */
     { FC_FAMILYLANG,	FcTypeString, },
     { FC_STYLE,		FcTypeString, },
     { FC_STYLELANG,	FcTypeString, },
@@ -72,253 +73,303 @@ static const FcObjectType _FcBaseObjectT
     { FC_CAPABILITY,	FcTypeString },
     { FC_FONTFORMAT,	FcTypeString },
     { FC_EMBOLDEN,	FcTypeBool },
-    { FC_EMBEDDED_BITMAP,   FcTypeBool },
+    { FC_EMBEDDED_BITMAP,   FcTypeBool }, /* 39 */
 };
 
 #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,
-    0
 };
 
 static const FcObjectTypeList	*_FcObjectTypes = &_FcBaseObjectTypesList;
 
-FcBool
-FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
-{
-    FcObjectTypeList	*l;
+#define OBJECT_HASH_SIZE    31
 
-    l = (FcObjectTypeList *) malloc (sizeof (FcObjectTypeList));
-    if (!l)
-	return FcFalse;
-    FcMemAlloc (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
-    l->types = types;
-    l->ntypes = ntypes;
-    l->next = _FcObjectTypes;
-    l->basic_offset = next_basic_offset;
-    next_basic_offset += ntypes;
-    _FcObjectTypes = l;
-    return FcTrue;
+typedef struct _FcObjectBucket {
+    struct _FcObjectBucket  *next;
+    FcChar32		    hash;
+    FcObject		    id;
+} FcObjectBucket;
+
+static FcObjectBucket	*FcObjectBuckets[OBJECT_HASH_SIZE];
+
+static FcObjectType	*FcObjects = (FcObjectType *) _FcBaseObjectTypes;
+static int		FcObjectsNumber = NUM_OBJECT_TYPES;
+static int		FcObjectsSize = 0;
+static FcBool		FcObjectsInited;
+
+static FcObjectType *
+FcObjectInsert (const char *name, FcType type)
+{
+    FcObjectType    *o;
+    if (FcObjectsNumber >= FcObjectsSize)
+    {
+	int		newsize = FcObjectsNumber * 2;
+	FcObjectType	*newobjects;
+	
+	if (FcObjectsSize)
+	    newobjects = realloc (FcObjects, newsize * sizeof (FcObjectType));
+	else
+	{
+	    newobjects = malloc (newsize * sizeof (FcObjectType));
+	    if (newobjects)
+		memcpy (newobjects, FcObjects,
+			FcObjectsNumber * sizeof (FcObjectType));
+	}
+	if (!newobjects)
+	    return NULL;
+	FcObjects = newobjects;
+	FcObjectsSize = newsize;
+    }
+    o = &FcObjects[FcObjectsNumber];
+    o->object = name;
+    o->type = type;
+    ++FcObjectsNumber;
+    return o;
 }
 
-static FcBool
-FcNameUnregisterObjectTypesFree (const FcObjectType *types, int ntypes, 
-				 FcBool do_free)
+static FcObject
+FcObjectId (FcObjectType *o)
 {
-    const FcObjectTypeList	*l, **prev;
+    return o - FcObjects + 1;
+}
 
-    for (prev = &_FcObjectTypes; 
-	 (l = *prev); 
-	 prev = (const FcObjectTypeList **) &(l->next))
-    {
-	if (l->types == types && l->ntypes == ntypes)
-	{
-	    *prev = l->next;
-	    if (do_free) {
-		FcMemFree (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
-		free ((void *) l);
-	    }
-	    return FcTrue;
-	}
+static FcObjectType *
+FcObjectFindByName (const char *object, FcBool insert)
+{
+    FcChar32	    hash = FcStringHash ((const FcChar8 *) object);
+    FcObjectBucket  **p;
+    FcObjectBucket  *b;
+    FcObjectType    *o;
+
+    if (!FcObjectsInited)
+	FcObjectInit ();
+    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
+    {
+	o = FcObjects + b->id - 1;
+        if (b->hash == hash && !strcmp (object, (o->object)))
+            return o;
+    }
+    if (!insert)
+	return NULL;
+    /*
+     * Hook it into the hash chain
+     */
+    b = malloc (sizeof(FcObjectBucket));
+    if (!b) 
+	return NULL;
+    object = (const char *) FcStrCopy ((FcChar8 *) object);
+    if (!object) {
+	free (b);
+	return NULL;
     }
-    return FcFalse;
+    o = FcObjectInsert (object, -1);
+    b->next = NULL;
+    b->hash = hash;
+    b->id = FcObjectId (o);
+    *p = b;
+    return o;
 }
 
-FcBool
-FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
+static FcObjectType *
+FcObjectFindById (FcObject object)
 {
-    return FcNameUnregisterObjectTypesFree (types, ntypes, FcTrue);
+    if (1 <= object && object <= FcObjectsNumber)
+	return FcObjects + object - 1;
+    return NULL;
 }
 
-const FcObjectType *
-FcNameGetObjectType (const char *object)
+static FcBool
+FcObjectHashInsert (const FcObjectType *object, FcBool copy)
 {
-    int			    i;
-    const FcObjectTypeList  *l;
-    const FcObjectType	    *t;
-    
-    for (l = _FcObjectTypes; l; l = l->next)
+    FcChar32	    hash = FcStringHash ((const FcChar8 *) object->object);
+    FcObjectBucket  **p;
+    FcObjectBucket  *b;
+    FcObjectType    *o;
+
+    if (!FcObjectsInited)
+	FcObjectInit ();
+    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
+    {
+	o = FcObjects + b->id - 1;
+        if (b->hash == hash && !strcmp (object->object, o->object))
+            return FcFalse;
+    }
+    /*
+     * Hook it into the hash chain
+     */
+    b = malloc (sizeof(FcObjectBucket));
+    if (!b) 
+	return FcFalse;
+    if (copy)
     {
-        if (l == (FcObjectTypeList*)_FcUserObjectNames)
-            continue;
-
-	for (i = 0; i < l->ntypes; i++)
+	o = FcObjectInsert (object->object, object->type);
+	if (!o)
 	{
-	    t = &l->types[i];
-	    if (!strcmp (object, t->object))
-		return t;
+	    free (b);
+	    return FcFalse;
 	}
     }
-    return 0;
+    else
+	o = (FcObjectType *) object;
+    b->next = NULL;
+    b->hash = hash;
+    b->id = FcObjectId (o);
+    *p = b;
+    return FcTrue;
 }
 
-#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 int biggest_known_ntypes = NUM_OBJECT_TYPES;
-
-
-static FcObject
-FcObjectToPtrLookup (const char * object)
+static void
+FcObjectHashRemove (const FcObjectType *object, FcBool cleanobj)
 {
-    FcObject		    i = 0, n;
-    const FcObjectTypeList  *l;
-    FcObjectType	    *t = _FcUserObjectNames;
-    FcBool		    replace;
-
-    for (l = _FcObjectTypes; l; l = l->next)
+    FcChar32	    hash = FcStringHash ((const FcChar8 *) object->object);
+    FcObjectBucket  **p;
+    FcObjectBucket  *b;
+    FcObjectType    *o;
+
+    if (!FcObjectsInited)
+	FcObjectInit ();
+    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
     {
-	for (i = 0; i < l->ntypes; i++)
+	o = FcObjects + b->id - 1;
+        if (b->hash == hash && !strcmp (object->object, o->object))
 	{
-	    t = (FcObjectType *)&l->types[i];
-	    if (!strcmp (object, t->object))
+	    *p = b->next;
+	    free (b);
+	    if (cleanobj)
 	    {
-		if (l->types == _FcUserObjectNames)
-                    return -i;
-		else
-		    return l->basic_offset + i;
+		/* Clean up object array */
+		o->object = NULL;
+		o->type = -1;
+		while (FcObjects[FcObjectsNumber-1].object == NULL)
+		    --FcObjectsNumber;
 	    }
+            break;
 	}
     }
+}
 
-    /* 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;
-    }
-
-    replace = l && l->types == _FcUserObjectNames;
-    if (!_FcUserObjectNames || 
-        (replace && user_obj_alloc <= l->ntypes))
-    {
-	int nt = user_obj_alloc + 4;
-        FcObjectType * tt = realloc (_FcUserObjectNames, 
-				    nt * sizeof (FcObjectType));
-        if (!tt)
-            return 0;
-	_FcUserObjectNames = tt;
-	user_obj_alloc = nt;
-    }
-
-    if (replace)
-    {
-	n = l->ntypes;
-	FcNameUnregisterObjectTypesFree (l->types, l->ntypes, FcFalse);
-    }
-    else
-	n = 0;
+FcBool
+FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
+{
+    int	i;
 
-    FcNameRegisterObjectTypes (_FcUserObjectNames, n+1);
+    for (i = 0; i < ntypes; i++)
+	if (!FcObjectHashInsert (&types[i], FcTrue))
+	    return FcFalse;
+    return FcTrue;
+}
 
-    if (!_FcUserObjectNames)
-	return 0;
+FcBool
+FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
+{
+    int	i;
 
-    _FcUserObjectNames[n].object = object;
-    _FcUserObjectNames[n].type = FcTypeVoid;
+    for (i = 0; i < ntypes; i++)
+	FcObjectHashRemove (&types[i], FcTrue);
+    return FcTrue;
+}
 
-    return -n;
+const FcObjectType *
+FcNameGetObjectType (const char *object)
+{
+    return FcObjectFindByName (object, FcFalse);
 }
 
 FcBool
 FcObjectValidType (FcObject object, FcType type)
 {
-    if (object < NUM_OBJECT_TYPES && _FcBaseObjectTypes[object].type != type)
+    FcObjectType    *t = FcObjectFindById (object);
+
+    if (t) {
+	switch (t->type) {
+	case -1:
+	    return FcTrue;
+	case FcTypeDouble:
+	case FcTypeInteger:
+	    if (type == FcTypeDouble || type == FcTypeInteger)
+		return FcTrue;
+	    break;
+	default:
+	    if (type == t->type)
+		return FcTrue;
+	    break;
+	}
 	return FcFalse;
+    }
     return FcTrue;
 }
 
 FcObject
 FcObjectFromName (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;
+    FcObjectType    *o = FcObjectFindByName (name, FcTrue);
+
+    if (o)
+	return FcObjectId (o);
+    return 0;
+}
+
+FcBool
+FcObjectInit (void)
+{
+    int	i;
+
+    if (FcObjectsInited)
+	return FcTrue;
+
+    FcObjectsInited = FcTrue;
+    for (i = 0; i < NUM_OBJECT_TYPES; i++)
+	if (!FcObjectHashInsert (&_FcBaseObjectTypes[i], FcFalse))
+	    return FcFalse;
+    return FcTrue;
 }
 
 void
-FcObjectStaticNameFini (void)
+FcObjectFini (void)
 {
-    int i, size;
-    struct objectBucket *b, *next;
-    char *name;
+    int		    i;
+    FcObjectBucket  *b, *next;
 
     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;
     }
+    for (i = 0; i < FcObjectsNumber; i++)
+	if (FcObjects[i].type == -1)
+	    free ((void*) FcObjects[i].object);
+    if (FcObjects != _FcBaseObjectTypes)
+	free (FcObjects);
+    FcObjects = (FcObjectType *) _FcBaseObjectTypes;
+    FcObjectsNumber = NUM_OBJECT_TYPES;
+    FcObjectsSize = 0;
+    FcObjectsInited = FcFalse;
 }
 
 const char *
 FcObjectName (FcObject object)
 {
-    const FcObjectTypeList  *l;
-    int i, j;
-
-    if (object > 0)
-    {
-        if (object < biggest_known_ntypes)
-            return biggest_known_types[object].object;
-
-        j = 0;
-        for (l = _FcObjectTypes; l; l = l->next)
-            for (i = 0; i < l->ntypes; i++, j++)
-                if (j == object)
-                    return l->types[i].object;
-    }
+    FcObjectType    *o = FcObjectFindById (object);
 
-    return _FcUserObjectNames[-object].object;
+    if (o)
+	return o->object;
+    return NULL;
 }
 
 static const FcConstant _FcBaseConstants[] = {
diff --git a/src/fcpat.c b/src/fcpat.c
index 3eb8a73..bc0bab7 100644
--- a/src/fcpat.c
+++ b/src/fcpat.c
@@ -1044,7 +1044,7 @@ void
 FcPatternFini (void)
 {
     FcStrStaticNameFini ();
-    FcObjectStaticNameFini ();
+    FcObjectFini ();
 }
 
 FcBool


More information about the Fontconfig mailing list