/*
- * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.11 2002/07/06 23:47:44 keithp Exp $
+ * $RCSId: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $
*
- * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ * Copyright © 2000 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include "fcint.h"
FcPattern *
case FcTypeCharSet:
FcCharSetDestroy ((FcCharSet *) v.u.c);
break;
+ case FcTypeLangSet:
+ FcLangSetDestroy ((FcLangSet *) v.u.l);
+ break;
default:
break;
}
if (!v.u.c)
v.type = FcTypeVoid;
break;
+ case FcTypeLangSet:
+ v.u.l = FcLangSetCopy (v.u.l);
+ if (!v.u.l)
+ v.type = FcTypeVoid;
+ break;
default:
break;
}
case FcTypeCharSet:
FcCharSetDestroy ((FcCharSet *) l->value.u.c);
break;
+ case FcTypeLangSet:
+ FcLangSetDestroy ((FcLangSet *) l->value.u.l);
+ break;
default:
break;
}
return FcCharSetEqual (va.u.c, vb.u.c);
case FcTypeFTFace:
return va.u.f == vb.u.f;
+ case FcTypeLangSet:
+ return FcLangSetEqual (va.u.l, vb.u.l);
}
return FcFalse;
}
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 FcFalse;
}
static FcBool
FcValueListEqual (FcValueList *la, FcValueList *lb)
{
+ if (la == lb)
+ return FcTrue;
+
while (la && lb)
{
if (!FcValueEqual (la->value, lb->value))
{
int i;
- if (--p->ref > 0)
+ if (p->ref == FC_REF_CONSTANT || --p->ref > 0)
return;
for (i = 0; i < p->num; i++)
free (p);
}
+#define FC_VALUE_LIST_HASH_SIZE 257
+#define FC_PATTERN_HASH_SIZE 67
+
+typedef struct _FcValueListEnt FcValueListEnt;
+
+struct _FcValueListEnt {
+ FcValueListEnt *next;
+ FcValueList *list;
+ FcChar32 hash, pad;
+};
+
+typedef union _FcValueListAlign {
+ FcValueListEnt ent;
+ FcValueList list;
+} FcValueListAlign;
+
+static int FcValueListFrozenCount[FcTypeLangSet + 1];
+static int FcValueListFrozenBytes[FcTypeLangSet + 1];
+static char *FcValueListFrozenName[] = {
+ "Void",
+ "Integer",
+ "Double",
+ "String",
+ "Bool",
+ "Matrix",
+ "CharSet",
+ "FTFace",
+ "LangSet"
+};
+
+void
+FcValueListReport (void);
+
+void
+FcValueListReport (void)
+{
+ FcType t;
+
+ printf ("Fc Frozen Values:\n");
+ printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
+ for (t = FcTypeVoid; t <= FcTypeLangSet; t++)
+ printf ("\t%8s %9d %9d\n", FcValueListFrozenName[t],
+ FcValueListFrozenCount[t], FcValueListFrozenBytes[t]);
+}
+
+static FcValueListEnt *
+FcValueListEntCreate (FcValueList *h)
+{
+ FcValueListAlign *ea;
+ FcValueListEnt *e;
+ FcValueList *l, *new;
+ int n;
+ int string_size = 0;
+ FcChar8 *strs;
+ int size;
+
+ n = 0;
+ for (l = h; l; l = l->next)
+ {
+ if (l->value.type == FcTypeString)
+ string_size += strlen ((char *) l->value.u.s) + 1;
+ n++;
+ }
+ size = sizeof (FcValueListAlign) + n * sizeof (FcValueList) + string_size;
+ FcValueListFrozenCount[h->value.type]++;
+ FcValueListFrozenBytes[h->value.type] += size;
+ ea = malloc (size);
+ if (!ea)
+ return 0;
+ FcMemAlloc (FC_MEM_VALLIST, size);
+ e = &ea->ent;
+ e->list = (FcValueList *) (ea + 1);
+ strs = (FcChar8 *) (e->list + n);
+ new = e->list;
+ for (l = h; l; l = l->next, new++)
+ {
+ if (l->value.type == FcTypeString)
+ {
+ new->value.type = FcTypeString;
+ new->value.u.s = strs;
+ strcpy ((char *) strs, (char *) l->value.u.s);
+ strs += strlen ((char *) strs) + 1;
+ }
+ else
+ {
+ new->value = l->value;
+ new->value = FcValueSave (new->value);
+ }
+ new->binding = l->binding;
+ if (l->next)
+ new->next = new + 1;
+ else
+ new->next = 0;
+ }
+ return e;
+}
+
+static int FcValueListTotal;
+static int FcValueListUsed;
+
+static FcValueList *
+FcValueListFreeze (FcValueList *l)
+{
+ static FcValueListEnt *hashTable[FC_VALUE_LIST_HASH_SIZE];
+ FcChar32 hash = FcValueListHash (l);
+ FcValueListEnt **bucket = &hashTable[hash % FC_VALUE_LIST_HASH_SIZE];
+ FcValueListEnt *ent;
+
+ FcValueListTotal++;
+ for (ent = *bucket; ent; ent = ent->next)
+ {
+ if (ent->hash == hash && FcValueListEqual (ent->list, l))
+ return ent->list;
+ }
+
+ ent = FcValueListEntCreate (l);
+ if (!ent)
+ return 0;
+
+ FcValueListUsed++;
+ ent->hash = hash;
+ ent->next = *bucket;
+ *bucket = ent;
+ return ent->list;
+}
+
+static FcChar32
+FcPatternBaseHash (FcPattern *b)
+{
+ FcChar32 hash = b->num;
+ int i;
+
+ for (i = 0; i < b->num; i++)
+ hash = ((hash << 1) | (hash >> 31)) ^ ((long) b->elts[i].values);
+ return hash;
+}
+
+typedef struct _FcPatternEnt FcPatternEnt;
+
+struct _FcPatternEnt {
+ FcPatternEnt *next;
+ FcChar32 hash;
+ FcPattern pattern;
+};
+
+static int FcPatternTotal;
+static int FcPatternUsed;
+
+static FcPattern *
+FcPatternBaseFreeze (FcPattern *b)
+{
+ static FcPatternEnt *hashTable[FC_VALUE_LIST_HASH_SIZE];
+ FcChar32 hash = FcPatternBaseHash (b);
+ FcPatternEnt **bucket = &hashTable[hash % FC_VALUE_LIST_HASH_SIZE];
+ FcPatternEnt *ent;
+ int i;
+ char *objects;
+ int size_objects;
+ int size;
+
+ FcPatternTotal++;
+ for (ent = *bucket; ent; ent = ent->next)
+ {
+ if (ent->hash == hash && b->num == ent->pattern.num)
+ {
+ for (i = 0; i < b->num; i++)
+ {
+ if (strcmp (b->elts[i].object, ent->pattern.elts[i].object))
+ break;
+ if (b->elts[i].values != ent->pattern.elts[i].values)
+ break;
+ }
+ if (i == b->num)
+ return &ent->pattern;
+ }
+ }
+
+ /*
+ * Compute size of pattern + elts + object names
+ */
+ size_objects = 0;
+ for (i = 0; i < b->num; i++)
+ size_objects += strlen (b->elts[i].object) + 1;
+
+ size = sizeof (FcPatternEnt) + b->num*sizeof (FcPatternElt) + size_objects;
+ ent = malloc (size);
+ if (!ent)
+ return 0;
+
+ FcMemAlloc (FC_MEM_PATTERN, size);
+ FcPatternUsed++;
+
+ ent->pattern.elts = (FcPatternElt *) (ent + 1);
+ ent->pattern.num = b->num;
+ ent->pattern.size = b->num;
+ ent->pattern.ref = FC_REF_CONSTANT;
+
+ objects = (char *) (ent->pattern.elts + b->num);
+ for (i = 0; i < b->num; i++)
+ {
+ ent->pattern.elts[i].values = b->elts[i].values;
+ strcpy (objects, b->elts[i].object);
+ ent->pattern.elts[i].object = objects;
+ objects += strlen (objects) + 1;
+ }
+
+ ent->hash = hash;
+ ent->next = *bucket;
+ *bucket = ent;
+ return &ent->pattern;
+}
+
+FcPattern *
+FcPatternFreeze (FcPattern *p)
+{
+ FcPattern *b, *n = 0;
+ int size;
+ int i;
+
+ size = sizeof (FcPattern) + p->num * sizeof (FcPatternElt);
+ b = (FcPattern *) malloc (size);
+ if (!b)
+ return 0;
+ FcMemAlloc (FC_MEM_PATTERN, size);
+ b->num = p->num;
+ b->size = b->num;
+ b->ref = 1;
+ b->elts = (FcPatternElt *) (b + 1);
+ /*
+ * 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)
+ goto bail;
+ }
+ /*
+ * Freeze base
+ */
+ n = FcPatternBaseFreeze (b);
+#ifdef CHATTY
+ if (FcDebug() & FC_DBG_MEMORY)
+ {
+ printf ("ValueLists: total %9d used %9d\n", FcValueListTotal, FcValueListUsed);
+ printf ("Patterns: total %9d used %9d\n", FcPatternTotal, FcPatternUsed);
+ }
+#endif
+bail:
+ free (b);
+#ifdef DEBUG
+ assert (FcPatternEqual (n, p));
+#endif
+ return n;
+}
+
static int
FcPatternPosition (const FcPattern *p, const char *object)
{
FcPatternElt *e;
FcValueList *new, **prev;
+ if (p->ref == FC_REF_CONSTANT)
+ goto bail0;
+
new = (FcValueList *) malloc (sizeof (FcValueList));
if (!new)
goto bail0;
case FcTypeCharSet:
FcCharSetDestroy ((FcCharSet *) value.u.c);
break;
+ case FcTypeLangSet:
+ FcLangSetDestroy ((FcLangSet *) value.u.l);
+ break;
default:
break;
}
return FcPatternAdd (p, object, v, FcTrue);
}
+FcBool
+FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
+{
+ FcValue v;
+
+ v.type = FcTypeLangSet;
+ v.u.l = (FcLangSet *) ls;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
FcResult
-FcPatternGet (FcPattern *p, const char *object, int id, FcValue *v)
+FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
{
FcPatternElt *e;
FcValueList *l;
}
FcResult
-FcPatternGetInteger (FcPattern *p, const char *object, int id, int *i)
+FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
{
FcValue v;
FcResult r;
}
FcResult
-FcPatternGetDouble (FcPattern *p, const char *object, int id, double *d)
+FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
{
FcValue v;
FcResult r;
}
FcResult
-FcPatternGetString (FcPattern *p, const char *object, int id, FcChar8 ** s)
+FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
{
FcValue v;
FcResult r;
}
FcResult
-FcPatternGetMatrix (FcPattern *p, const char *object, int id, FcMatrix **m)
+FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
{
FcValue v;
FcResult r;
FcResult
-FcPatternGetBool (FcPattern *p, const char *object, int id, FcBool *b)
+FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
{
FcValue v;
FcResult r;
}
FcResult
-FcPatternGetCharSet (FcPattern *p, const char *object, int id, FcCharSet **c)
+FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
{
FcValue v;
FcResult r;
}
FcResult
-FcPatternGetFTFace (FcPattern *p, const char *object, int id, FT_Face *f)
+FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
{
FcValue v;
FcResult r;
return FcResultMatch;
}
+FcResult
+FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ if (v.type != FcTypeLangSet)
+ return FcResultTypeMismatch;
+ *ls = (FcLangSet *) v.u.l;
+ return FcResultMatch;
+}
+
FcPattern *
-FcPatternDuplicate (FcPattern *orig)
+FcPatternDuplicate (const FcPattern *orig)
{
FcPattern *new;
int i;
void
FcPatternReference (FcPattern *p)
{
- p->ref++;
+ if (p->ref != FC_REF_CONSTANT)
+ p->ref++;
}
FcPattern *