/*
- * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.2 2002/02/15 06:01:28 keithp Exp $
+ * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.7 2002/06/03 08:31:15 keithp Exp $
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
*
p->num = 0;
p->size = 0;
p->elts = 0;
+ p->ref = 1;
return p;
}
}
}
+FcBool
+FcValueEqual (FcValue va, FcValue vb)
+{
+ if (va.type != vb.type)
+ {
+ if (va.type == FcTypeInteger)
+ {
+ va.type = FcTypeDouble;
+ va.u.d = va.u.i;
+ }
+ if (vb.type == FcTypeInteger)
+ {
+ vb.type = FcTypeDouble;
+ vb.u.d = vb.u.i;
+ }
+ if (va.type != vb.type)
+ return FcFalse;
+ }
+ switch (va.type) {
+ case FcTypeVoid:
+ return FcTrue;
+ case FcTypeInteger:
+ return va.u.i == vb.u.i;
+ case FcTypeDouble:
+ return va.u.d == vb.u.d;
+ case FcTypeString:
+ return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
+ case FcTypeBool:
+ return va.u.b == vb.u.b;
+ case FcTypeMatrix:
+ return FcMatrixEqual (va.u.m, vb.u.m);
+ case FcTypeCharSet:
+ return FcCharSetEqual (va.u.c, vb.u.c);
+ case FcTypeFTFace:
+ return va.u.f == vb.u.f;
+ }
+ return FcFalse;
+}
+
+static FcChar32
+FcDoubleHash (double d)
+{
+ if (d < 0)
+ d = -d;
+ if (d > 0xffffffff)
+ d = 0xffffffff;
+ return (FcChar32) d;
+}
+
+static FcChar32
+FcStringHash (const FcChar8 *s)
+{
+ FcChar8 c;
+ FcChar32 h = 0;
+
+ if (s)
+ while ((c = *s++))
+ h = ((h << 1) | (h >> 31)) ^ c;
+ return h;
+}
+
+static FcChar32
+FcValueHash (FcValue v)
+{
+ switch (v.type) {
+ case FcTypeVoid:
+ return 0;
+ case FcTypeInteger:
+ return (FcChar32) v.u.i;
+ case FcTypeDouble:
+ return FcDoubleHash (v.u.d);
+ case FcTypeString:
+ return FcStringHash (v.u.s);
+ 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));
+ case FcTypeCharSet:
+ return (FcChar32) v.u.c->num;
+ case FcTypeFTFace:
+ return FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->family_name) ^
+ FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->style_name);
+ }
+ return FcFalse;
+}
+
+static FcBool
+FcValueListEqual (FcValueList *la, FcValueList *lb)
+{
+ while (la && lb)
+ {
+ if (!FcValueEqual (la->value, lb->value))
+ return FcFalse;
+ la = la->next;
+ lb = lb->next;
+ }
+ if (la || lb)
+ return FcFalse;
+ return FcTrue;
+}
+
+static FcChar32
+FcValueListHash (FcValueList *l)
+{
+ FcChar32 hash = 0;
+
+ while (l)
+ {
+ hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (l->value);
+ l = l->next;
+ }
+ return hash;
+}
+
void
FcPatternDestroy (FcPattern *p)
{
int i;
+ if (--p->ref > 0)
+ return;
+
for (i = 0; i < p->num; i++)
FcValueListDestroy (p->elts[i].values);
free (p);
}
+static int
+FcPatternPosition (const FcPattern *p, const char *object)
+{
+ int low, high, mid, c;
+
+ low = 0;
+ high = p->num - 1;
+ c = 1;
+ mid = 0;
+ while (low <= high)
+ {
+ mid = (low + high) >> 1;
+ c = strcmp (p->elts[mid].object, object);
+ if (c == 0)
+ return mid;
+ if (c < 0)
+ low = mid + 1;
+ else
+ high = mid - 1;
+ }
+ if (c < 0)
+ mid++;
+ return -(mid + 1);
+}
+
+FcPatternElt *
+FcPatternFindElt (const FcPattern *p, const char *object)
+{
+ int i = FcPatternPosition (p, object);
+ if (i < 0)
+ return 0;
+ return &p->elts[i];
+}
+
FcPatternElt *
-FcPatternFind (FcPattern *p, const char *object, FcBool insert)
+FcPatternInsertElt (FcPattern *p, const char *object)
{
int i;
- int s;
FcPatternElt *e;
- /* match existing */
- for (i = 0; i < p->num; i++)
+ i = FcPatternPosition (p, object);
+ if (i < 0)
{
- if (!FcStrCmpIgnoreCase ((FcChar8 *) object, (FcChar8 *) p->elts[i].object))
- return &p->elts[i];
+ i = -i - 1;
+
+ /* grow array */
+ if (p->num + 1 >= p->size)
+ {
+ int s = p->size + 16;
+ if (p->elts)
+ e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
+ else
+ e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
+ if (!e)
+ return FcFalse;
+ p->elts = 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;
+ p->size++;
+ }
+ }
+
+ /* move elts up */
+ memmove (p->elts + i + 1,
+ p->elts + i,
+ sizeof (FcPatternElt) *
+ (p->num - i));
+
+ /* bump count */
+ p->num++;
+
+ p->elts[i].object = object;
+ p->elts[i].values = 0;
}
+
+ return &p->elts[i];
+}
+
+FcBool
+FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
+{
+ int i;
- if (!insert)
+ if (pa->num != pb->num)
return FcFalse;
+ for (i = 0; i < pa->num; i++)
+ {
+ if (strcmp (pa->elts[i].object, pb->elts[i].object) != 0)
+ return FcFalse;
+ if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values))
+ return FcFalse;
+ }
+ return FcTrue;
+}
- /* grow array */
- if (i == p->size)
+FcChar32
+FcPatternHash (const FcPattern *p)
+{
+ int i;
+ FcChar32 h = 0;
+
+ for (i = 0; i < p->num; i++)
+ {
+ h = (((h << 1) | (h >> 31)) ^
+ FcStringHash ((const FcChar8 *) p->elts[i].object) ^
+ FcValueListHash (p->elts[i].values));
+ }
+ return h;
+}
+
+FcBool
+FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os)
+{
+ FcPatternElt *ea, *eb;
+ int i;
+
+ for (i = 0; i < os->nobject; i++)
{
- s = p->size + 16;
- if (p->elts)
- e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
+ ea = FcPatternFindElt (pa, os->objects[i]);
+ eb = FcPatternFindElt (pb, os->objects[i]);
+ if (ea)
+ {
+ if (!eb)
+ return FcFalse;
+ if (!FcValueListEqual (ea->values, eb->values))
+ return FcFalse;
+ }
else
- e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
- if (!e)
- return FcFalse;
- p->elts = 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;
- p->size++;
+ if (eb)
+ return FcFalse;
}
}
-
- /* bump count */
- p->num++;
-
- p->elts[i].object = object;
-
- return &p->elts[i];
+ return FcTrue;
}
FcBool
new->value = value;
new->next = 0;
- e = FcPatternFind (p, object, FcTrue);
+ e = FcPatternInsertElt (p, object);
if (!e)
goto bail2;
FcPatternElt *e;
int i;
- e = FcPatternFind (p, object, FcFalse);
+ e = FcPatternFindElt (p, object);
if (!e)
return FcFalse;
return FcPatternAdd (p, object, v, FcTrue);
}
+FcBool
+FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
+{
+ FcValue v;
+
+ v.type = FcTypeFTFace;
+ v.u.f = (void *) f;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
FcResult
FcPatternGet (FcPattern *p, const char *object, int id, FcValue *v)
{
FcPatternElt *e;
FcValueList *l;
- e = FcPatternFind (p, object, FcFalse);
+ e = FcPatternFindElt (p, object);
if (!e)
return FcResultNoMatch;
for (l = e->values; l; l = l->next)
return FcResultMatch;
}
+FcResult
+FcPatternGetFTFace (FcPattern *p, const char *object, int id, FT_Face *f)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ if (v.type != FcTypeFTFace)
+ return FcResultTypeMismatch;
+ *f = (FT_Face) v.u.f;
+ return FcResultMatch;
+}
+
FcPattern *
FcPatternDuplicate (FcPattern *orig)
{
return 0;
}
+void
+FcPatternReference (FcPattern *p)
+{
+ p->ref++;
+}
+
FcPattern *
FcPatternVaBuild (FcPattern *orig, va_list va)
{