/*
- * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.5 2002/05/29 22:07:33 keithp 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
* PERFORMANCE OF THIS SOFTWARE.
*/
+#include "fcint.h"
#include <stdlib.h>
#include <string.h>
-#include "fcint.h"
+#include <assert.h>
+
+static FcBool
+FcStrHashed (const FcChar8 *name);
FcPattern *
FcPatternCreate (void)
FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern));
p->num = 0;
p->size = 0;
- p->elts = 0;
+ p->elts_offset = FcPtrToOffset (p, NULL);
+ p->ref = 1;
return p;
}
{
switch (v.type) {
case FcTypeString:
- FcStrFree ((FcChar8 *) v.u.s);
+ if (!FcStrHashed (v.u.s))
+ FcStrFree ((FcChar8 *) v.u.s);
break;
case FcTypeMatrix:
FcMatrixFree ((FcMatrix *) v.u.m);
case FcTypeCharSet:
FcCharSetDestroy ((FcCharSet *) v.u.c);
break;
+ case FcTypeLangSet:
+ FcLangSetDestroy ((FcLangSet *) v.u.l);
+ break;
+ default:
+ break;
+ }
+}
+
+FcValue
+FcValueCanonicalize (const FcValue *v)
+{
+ FcValue new;
+
+ switch (v->type)
+ {
+ case FcTypeString:
+ new.u.s = fc_value_string(v);
+ new.type = FcTypeString;
+ break;
+ case FcTypeCharSet:
+ new.u.c = fc_value_charset(v);
+ new.type = FcTypeCharSet;
+ break;
+ case FcTypeLangSet:
+ new.u.l = fc_value_langset(v);
+ new.type = FcTypeLangSet;
+ break;
default:
+ new = *v;
break;
}
+ return new;
}
FcValue
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;
}
}
void
-FcValueListDestroy (FcValueList *l)
+FcValueListDestroy (FcValueListPtr l)
{
- FcValueList *next;
+ FcValueListPtr next;
for (; l; l = next)
{
switch (l->value.type) {
case FcTypeString:
- FcStrFree ((FcChar8 *) l->value.u.s);
+ if (!FcStrHashed ((FcChar8 *)l->value.u.s))
+ FcStrFree ((FcChar8 *)l->value.u.s);
break;
case FcTypeMatrix:
- FcMatrixFree ((FcMatrix *) l->value.u.m);
+ FcMatrixFree ((FcMatrix *)l->value.u.m);
break;
case FcTypeCharSet:
- FcCharSetDestroy ((FcCharSet *) l->value.u.c);
+ FcCharSetDestroy
+ ((FcCharSet *) (l->value.u.c));
+ break;
+ case FcTypeLangSet:
+ FcLangSetDestroy
+ ((FcLangSet *) (l->value.u.l));
break;
default:
break;
}
- next = l->next;
+ next = FcValueListNext(l);
FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
- free (l);
+ free(l);
}
}
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;
+}
+
+static FcChar32
+FcDoubleHash (double d)
+{
+ if (d < 0)
+ d = -d;
+ if (d > 0xffffffff)
+ d = 0xffffffff;
+ return (FcChar32) d;
+}
+
+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 (const FcValue *v)
+{
+ switch (fc_storage_type(v)) {
+ case FcTypeVoid:
+ return 0;
+ case FcTypeInteger:
+ return (FcChar32) v->u.i;
+ case FcTypeDouble:
+ return FcDoubleHash (v->u.d);
+ case FcTypeString:
+ return FcStringHash (fc_value_string(v));
+ 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) fc_value_charset(v)->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 (fc_value_langset(v));
}
return FcFalse;
}
static FcBool
-FcValueListEqual (FcValueList *la, FcValueList *lb)
+FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
{
+ if (la == lb)
+ return FcTrue;
+
while (la && lb)
{
if (!FcValueEqual (la->value, lb->value))
return FcFalse;
- la = la->next;
- lb = lb->next;
+ la = FcValueListNext(la);
+ lb = FcValueListNext(lb);
}
if (la || lb)
return FcFalse;
return FcTrue;
}
+static FcChar32
+FcValueListHash (FcValueListPtr l)
+{
+ FcChar32 hash = 0;
+
+ for (; l; l = FcValueListNext(l))
+ {
+ hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
+ }
+ return hash;
+}
+
void
FcPatternDestroy (FcPattern *p)
{
int i;
+ FcPatternElt *elts;
+ if (p->ref == FC_REF_CONSTANT || --p->ref > 0)
+ return;
+
+ elts = FcPatternElts (p);
for (i = 0; i < p->num; i++)
- FcValueListDestroy (p->elts[i].values);
+ FcValueListDestroy (FcPatternEltValues(&elts[i]));
- p->num = 0;
- if (p->elts)
- {
- FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
- free (p->elts);
- p->elts = 0;
- }
- p->size = 0;
+ FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
+ free (elts);
FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern));
free (p);
}
-FcPatternElt *
-FcPatternFind (FcPattern *p, const char *object, FcBool insert)
+static int
+FcPatternObjectPosition (const FcPattern *p, FcObject object)
{
- int i;
- int s;
- FcPatternElt *e;
-
- int low, high;
+ int low, high, mid, c;
+ FcPatternElt *elts = FcPatternElts(p);
- /* match existing */
low = 0;
- high = p->num;
-
- while (low + 1 < high)
+ high = p->num - 1;
+ c = 1;
+ mid = 0;
+ while (low <= high)
{
- i = (low + high) >> 1;
- s = strcmp (object, p->elts[i].object);
- if (s == 0)
- return &p->elts[i];
- if (s > 0)
- low = i;
+ mid = (low + high) >> 1;
+ c = elts[mid].object - object;
+ if (c == 0)
+ return mid;
+ if (c < 0)
+ low = mid + 1;
else
- high = i;
- }
-
- i = low;
- while (i < high)
- {
- s = strcmp (object, p->elts[i].object);
- if (s == 0)
- return &p->elts[i];
- if (s < 0)
- break;
- i++;
+ high = mid - 1;
}
+ if (c < 0)
+ mid++;
+ return -(mid + 1);
+}
- if (!insert)
+FcPatternElt *
+FcPatternObjectFindElt (const FcPattern *p, FcObject object)
+{
+ int i = FcPatternObjectPosition (p, object);
+ if (i < 0)
return 0;
+ return &FcPatternElts(p)[i];
+}
- /* grow array */
- if (p->num + 1 >= p->size)
+FcPatternElt *
+FcPatternObjectInsertElt (FcPattern *p, FcObject object)
+{
+ int i;
+ FcPatternElt *e;
+
+ i = FcPatternObjectPosition (p, object);
+ if (i < 0)
{
- 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)
+ i = -i - 1;
+
+ /* reallocate array */
+ if (p->num + 1 >= p->size)
{
- p->elts[p->size].object = 0;
- p->elts[p->size].values = 0;
- p->size++;
+ int s = p->size + 16;
+ if (p->size)
+ {
+ FcPatternElt *e0 = FcPatternElts(p);
+ 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_offset = FcPtrToOffset (p, e);
+ if (p->size)
+ FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
+ FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
+ while (p->size < s)
+ {
+ e[p->size].object = 0;
+ e[p->size].values = NULL;
+ p->size++;
+ }
}
+
+ e = FcPatternElts(p);
+ /* move elts up */
+ memmove (e + i + 1,
+ e + i,
+ sizeof (FcPatternElt) *
+ (p->num - i));
+
+ /* bump count */
+ p->num++;
+
+ e[i].object = object;
+ e[i].values = NULL;
}
- /* 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];
+ return FcPatternElts(p) + i;
}
FcBool
-FcPatternEqual (FcPattern *pa, FcPattern *pb)
+FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
{
int i;
+ FcPatternElt *pae, *pbe;
+
+ if (pa == pb)
+ return FcTrue;
if (pa->num != pb->num)
return FcFalse;
+ pae = FcPatternElts(pa);
+ pbe = FcPatternElts(pb);
for (i = 0; i < pa->num; i++)
{
- if (strcmp (pa->elts[i].object, pb->elts[i].object) != 0)
+ if (pae[i].object != pbe[i].object)
return FcFalse;
- if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values))
+ if (!FcValueListEqual (FcPatternEltValues(&pae[i]),
+ FcPatternEltValues(&pbe[i])))
return FcFalse;
}
return FcTrue;
}
+FcChar32
+FcPatternHash (const FcPattern *p)
+{
+ int i;
+ FcChar32 h = 0;
+ FcPatternElt *pe = FcPatternElts(p);
+
+ for (i = 0; i < p->num; i++)
+ {
+ h = (((h << 1) | (h >> 31)) ^
+ pe[i].object ^
+ FcValueListHash (FcPatternEltValues(&pe[i])));
+ }
+ return h;
+}
+
FcBool
-FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
+FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
+{
+ FcPatternElt *ea, *eb;
+ int i;
+
+ for (i = 0; i < os->nobject; i++)
+ {
+ FcObject object = FcObjectFromName (os->objects[i]);
+ ea = FcPatternObjectFindElt (pai, object);
+ eb = FcPatternObjectFindElt (pbi, object);
+ if (ea)
+ {
+ if (!eb)
+ return FcFalse;
+ if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
+ return FcFalse;
+ }
+ else
+ {
+ if (eb)
+ return FcFalse;
+ }
+ }
+ return FcTrue;
+}
+
+FcBool
+FcPatternObjectAddWithBinding (FcPattern *p,
+ FcObject object,
+ FcValue value,
+ FcValueBinding binding,
+ FcBool append)
{
FcPatternElt *e;
- FcValueList *new, **prev;
+ FcValueListPtr new, *prev;
- new = (FcValueList *) malloc (sizeof (FcValueList));
+ if (p->ref == FC_REF_CONSTANT)
+ goto bail0;
+
+ new = malloc (sizeof (FcValueList));
if (!new)
goto bail0;
+ memset(new, 0, sizeof (FcValueList));
FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
/* dup string */
- value = FcValueSave (value);
+ if (value.type == FcTypeString)
+ {
+ value.u.s = FcStrStaticName (value.u.s);
+ if (!value.u.s)
+ value.type = FcTypeVoid;
+ }
+ else
+ value = FcValueSave (value);
if (value.type == FcTypeVoid)
goto bail1;
+ /*
+ * Make sure the stored type is valid for built-in objects
+ */
+ if (!FcObjectValidType (object, value.type))
+ goto bail1;
+
new->value = value;
- new->next = 0;
+ new->binding = binding;
+ new->next = NULL;
- e = FcPatternFind (p, object, FcTrue);
+ e = FcPatternObjectInsertElt (p, object);
if (!e)
goto bail2;
if (append)
{
- for (prev = &e->values; *prev; prev = &(*prev)->next);
+ for (prev = &e->values; *prev; prev = &(*prev)->next)
+ ;
*prev = new;
}
else
return FcTrue;
bail2:
- switch (value.type) {
- case FcTypeString:
- FcStrFree ((FcChar8 *) value.u.s);
- break;
- case FcTypeMatrix:
- FcMatrixFree ((FcMatrix *) value.u.m);
- break;
- case FcTypeCharSet:
- FcCharSetDestroy ((FcCharSet *) value.u.c);
- break;
- default:
- break;
- }
+ FcValueDestroy (value);
bail1:
FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
free (new);
}
FcBool
-FcPatternDel (FcPattern *p, const char *object)
+FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
+{
+ return FcPatternObjectAddWithBinding (p, object,
+ value, FcValueBindingStrong, append);
+}
+
+FcBool
+FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
+{
+ return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
+ value, FcValueBindingStrong, append);
+}
+
+FcBool
+FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
+{
+ return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
+ value, FcValueBindingWeak, append);
+}
+
+FcBool
+FcPatternObjectDel (FcPattern *p, FcObject object)
{
FcPatternElt *e;
- int i;
- e = FcPatternFind (p, object, FcFalse);
+ e = FcPatternObjectFindElt (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,
+ (FcPatternElts(p) + p->num - (e + 1)) *
+ sizeof (FcPatternElt));
p->num--;
- p->elts[p->num].object = 0;
- p->elts[p->num].values = 0;
+ e = FcPatternElts(p) + p->num;
+ e->object = 0;
+ e->values = NULL;
return FcTrue;
}
FcBool
-FcPatternAddInteger (FcPattern *p, const char *object, int i)
+FcPatternDel (FcPattern *p, const char *object)
+{
+ return FcPatternObjectDel (p, FcObjectFromName (object));
+}
+
+FcBool
+FcPatternRemove (FcPattern *p, const char *object, int id)
+{
+ FcPatternElt *e;
+ FcValueListPtr *prev, l;
+
+ e = FcPatternObjectFindElt (p, FcObjectFromName (object));
+ if (!e)
+ return FcFalse;
+ for (prev = &e->values; (l = *prev); prev = &l->next)
+ {
+ if (!id)
+ {
+ *prev = l->next;
+ l->next = NULL;
+ FcValueListDestroy (l);
+ if (!e->values)
+ FcPatternDel (p, object);
+ return FcTrue;
+ }
+ id--;
+ }
+ return FcFalse;
+}
+
+FcBool
+FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
{
FcValue v;
v.type = FcTypeInteger;
v.u.i = i;
- return FcPatternAdd (p, object, v, FcTrue);
+ return FcPatternObjectAdd (p, object, v, FcTrue);
}
FcBool
-FcPatternAddDouble (FcPattern *p, const char *object, double d)
+FcPatternAddInteger (FcPattern *p, const char *object, int i)
+{
+ return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
+}
+
+FcBool
+FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
{
FcValue v;
v.type = FcTypeDouble;
v.u.d = d;
- return FcPatternAdd (p, object, v, FcTrue);
+ return FcPatternObjectAdd (p, object, v, FcTrue);
}
FcBool
-FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
+FcPatternAddDouble (FcPattern *p, const char *object, double d)
+{
+ return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
+}
+
+FcBool
+FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
{
FcValue v;
+ if (!s)
+ {
+ v.type = FcTypeVoid;
+ v.u.s = 0;
+ return FcPatternObjectAdd (p, object, v, FcTrue);
+ }
+
v.type = FcTypeString;
- v.u.s = s;
- return FcPatternAdd (p, object, v, FcTrue);
+ v.u.s = FcStrStaticName(s);
+ return FcPatternObjectAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
+{
+ return FcPatternObjectAddString (p, FcObjectFromName (object), s);
}
FcBool
FcValue v;
v.type = FcTypeMatrix;
- v.u.m = (FcMatrix *) s;
+ v.u.m = s;
return FcPatternAdd (p, object, v, FcTrue);
}
FcBool
-FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
+FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
{
FcValue v;
v.type = FcTypeBool;
v.u.b = b;
- return FcPatternAdd (p, object, v, FcTrue);
+ return FcPatternObjectAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
+{
+ return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
}
FcBool
FcValue v;
v.type = FcTypeCharSet;
- v.u.c = (FcCharSet *) c;
+ v.u.c = (FcCharSet *)c;
return FcPatternAdd (p, object, v, FcTrue);
}
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)
+FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
{
FcPatternElt *e;
- FcValueList *l;
+ FcValueListPtr l;
- e = FcPatternFind (p, object, FcFalse);
+ e = FcPatternObjectFindElt (p, object);
if (!e)
return FcResultNoMatch;
- for (l = e->values; l; l = l->next)
+ for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
{
if (!id)
{
- *v = l->value;
+ *v = FcValueCanonicalize(&l->value);
return FcResultMatch;
}
id--;
}
FcResult
-FcPatternGetInteger (FcPattern *p, const char *object, int id, int *i)
+FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
+{
+ return FcPatternObjectGet (p, FcObjectFromName (object), id, v);
+}
+
+FcResult
+FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
{
FcValue v;
FcResult r;
- r = FcPatternGet (p, object, id, &v);
+ r = FcPatternObjectGet (p, object, id, &v);
if (r != FcResultMatch)
return r;
switch (v.type) {
}
FcResult
-FcPatternGetDouble (FcPattern *p, const char *object, int id, double *d)
+FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
+{
+ return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
+}
+
+
+FcResult
+FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
{
FcValue v;
FcResult r;
- r = FcPatternGet (p, object, id, &v);
+ r = FcPatternObjectGet (p, object, id, &v);
if (r != FcResultMatch)
return r;
switch (v.type) {
}
FcResult
-FcPatternGetString (FcPattern *p, const char *object, int id, FcChar8 ** s)
+FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
+{
+ return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
+}
+
+FcResult
+FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
{
FcValue v;
FcResult r;
- r = FcPatternGet (p, object, id, &v);
+ r = FcPatternObjectGet (p, object, id, &v);
if (r != FcResultMatch)
return r;
if (v.type != FcTypeString)
return FcResultTypeMismatch;
+
*s = (FcChar8 *) v.u.s;
return FcResultMatch;
}
FcResult
-FcPatternGetMatrix (FcPattern *p, const char *object, int id, FcMatrix **m)
+FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
+{
+ return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
+}
+
+FcResult
+FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
{
FcValue v;
FcResult r;
return r;
if (v.type != FcTypeMatrix)
return FcResultTypeMismatch;
- *m = (FcMatrix *) v.u.m;
+ *m = (FcMatrix *)v.u.m;
return FcResultMatch;
}
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;
return r;
if (v.type != FcTypeCharSet)
return FcResultTypeMismatch;
- *c = (FcCharSet *) v.u.c;
+ *c = (FcCharSet *)v.u.c;
return FcResultMatch;
}
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;
+ FcPatternElt *e;
int i;
- FcValueList *l;
+ FcValueListPtr l;
new = FcPatternCreate ();
if (!new)
goto bail0;
+ e = FcPatternElts(orig);
+
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 = FcPatternEltValues(e + i); l; l = FcValueListNext(l))
+ if (!FcPatternObjectAdd (new, e[i].object,
+ FcValueCanonicalize(&l->value),
+ FcTrue))
goto bail1;
}
return 0;
}
+void
+FcPatternReference (FcPattern *p)
+{
+ if (p->ref != FC_REF_CONSTANT)
+ p->ref++;
+}
+
FcPattern *
FcPatternVaBuild (FcPattern *orig, va_list va)
{
va_end (va);
return orig;
}
+
+/*
+ * Add all of the elements in 's' to 'p'
+ */
+FcBool
+FcPatternAppend (FcPattern *p, FcPattern *s)
+{
+ int i;
+ FcPatternElt *e;
+ FcValueListPtr v;
+
+ for (i = 0; i < s->num; i++)
+ {
+ e = FcPatternElts(s)+i;
+ for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
+ {
+ if (!FcPatternObjectAddWithBinding (p, e->object,
+ FcValueCanonicalize(&v->value),
+ v->binding, FcTrue))
+ return FcFalse;
+ }
+ }
+ return FcTrue;
+}
+
+#define OBJECT_HASH_SIZE 31
+static struct objectBucket {
+ struct objectBucket *next;
+ FcChar32 hash;
+} *FcObjectBuckets[OBJECT_HASH_SIZE];
+
+static FcBool
+FcStrHashed (const FcChar8 *name)
+{
+ FcChar32 hash = FcStringHash (name);
+ struct objectBucket **p;
+ struct objectBucket *b;
+
+ for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
+ if (b->hash == hash && !strcmp ((char *)name, (char *) (b + 1)))
+ return FcTrue;
+ return FcFalse;
+}
+
+const FcChar8 *
+FcStrStaticName (const FcChar8 *name)
+{
+ FcChar32 hash = FcStringHash (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 ((char *)name, (char *) (b + 1)))
+ return (FcChar8 *) (b + 1);
+ size = sizeof (struct objectBucket) + strlen ((char *)name) + 1;
+ b = malloc (size + sizeof (int));
+ /* workaround glibc bug which reads strlen in groups of 4 */
+ FcMemAlloc (FC_MEM_STATICSTR, size + sizeof (int));
+ if (!b)
+ return NULL;
+ b->next = 0;
+ b->hash = hash;
+ strcpy ((char *) (b + 1), (char *)name);
+ *p = b;
+ return (FcChar8 *) (b + 1);
+}
+
+static void
+FcStrStaticNameFini (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;
+ }
+}
+
+void
+FcPatternFini (void)
+{
+ FcStrStaticNameFini ();
+ FcObjectFini ();
+}
+
+FcBool
+FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
+{
+ int i;
+ FcPatternElt *elts = FcPatternElts(pat);
+
+ if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
+ return FcFalse;
+ if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt)))
+ return FcFalse;
+ for (i = 0; i < pat->num; i++)
+ if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
+ return FcFalse;
+ return FcTrue;
+}
+
+FcPattern *
+FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
+{
+ FcPattern *pat_serialized;
+ FcPatternElt *elts = FcPatternElts (pat);
+ FcPatternElt *elts_serialized;
+ FcValueList *values_serialized;
+ int i;
+
+ pat_serialized = FcSerializePtr (serialize, pat);
+ if (!pat_serialized)
+ return NULL;
+ *pat_serialized = *pat;
+ pat_serialized->size = pat->num;
+ pat_serialized->ref = FC_REF_CONSTANT;
+
+ elts_serialized = FcSerializePtr (serialize, elts);
+ if (!elts_serialized)
+ return NULL;
+
+ pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
+ elts_serialized);
+
+ for (i = 0; i < pat->num; i++)
+ {
+ values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
+ if (!values_serialized)
+ return NULL;
+ elts_serialized[i].object = elts[i].object;
+ elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
+ values_serialized,
+ FcValueList);
+ }
+ if (FcDebug() & FC_DBG_CACHEV) {
+ printf ("Raw pattern:\n");
+ FcPatternPrint (pat);
+ printf ("Serialized pattern:\n");
+ FcPatternPrint (pat_serialized);
+ printf ("\n");
+ }
+ return pat_serialized;
+}
+
+FcBool
+FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
+{
+ while (vl)
+ {
+ if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
+ return FcFalse;
+ switch (vl->value.type) {
+ case FcTypeString:
+ if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
+ return FcFalse;
+ break;
+ case FcTypeCharSet:
+ if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
+ return FcFalse;
+ break;
+ case FcTypeLangSet:
+ if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
+ return FcFalse;
+ break;
+ default:
+ break;
+ }
+ vl = vl->next;
+ }
+ return FcTrue;
+}
+
+FcValueList *
+FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
+{
+ FcValueList *vl_serialized;
+ FcChar8 *s_serialized;
+ FcCharSet *c_serialized;
+ FcLangSet *l_serialized;
+ FcValueList *head_serialized = NULL;
+ FcValueList *prev_serialized = NULL;
+
+ while (vl)
+ {
+ vl_serialized = FcSerializePtr (serialize, vl);
+ if (!vl_serialized)
+ return NULL;
+
+ if (prev_serialized)
+ prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
+ vl_serialized,
+ FcValueList);
+ else
+ head_serialized = vl_serialized;
+
+ vl_serialized->next = NULL;
+ vl_serialized->value = vl->value;
+ switch (vl->value.type) {
+ case FcTypeString:
+ s_serialized = FcStrSerialize (serialize, vl->value.u.s);
+ if (!s_serialized)
+ return NULL;
+ vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
+ s_serialized,
+ FcChar8);
+ break;
+ case FcTypeCharSet:
+ c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
+ if (!c_serialized)
+ return NULL;
+ vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
+ c_serialized,
+ FcCharSet);
+ break;
+ case FcTypeLangSet:
+ l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
+ if (!l_serialized)
+ return NULL;
+ vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
+ l_serialized,
+ FcLangSet);
+ break;
+ default:
+ break;
+ }
+ prev_serialized = vl_serialized;
+ vl = vl->next;
+ }
+ return head_serialized;
+}