/*
- * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.12 2002/08/07 01:45:59 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 FcTypePattern:
- FcPatternDestroy ((FcPattern *) v.u.p);
+ 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
FcValueSave (FcValue v)
{
if (!v.u.c)
v.type = FcTypeVoid;
break;
- case FcTypePattern:
- FcPatternReference ((FcPattern *) v.u.p);
+ 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 FcTypePattern:
- FcPatternDestroy ((FcPattern *) l->value.u.p);
+ 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 FcTypePattern:
- return FcPatternEqual (va.u.p, vb.u.p);
+ case FcTypeLangSet:
+ return FcLangSetEqual (va.u.l, vb.u.l);
}
return FcFalse;
}
return (FcChar32) d;
}
-static FcChar32
+FcChar32
FcStringHash (const FcChar8 *s)
{
FcChar8 c;
}
static FcChar32
-FcValueHash (FcValue v)
+FcValueHash (const FcValue *v)
{
- switch (v.type) {
+ switch (fc_storage_type(v)) {
case FcTypeVoid:
return 0;
case FcTypeInteger:
- return (FcChar32) v.u.i;
+ return (FcChar32) v->u.i;
case FcTypeDouble:
- return FcDoubleHash (v.u.d);
+ return FcDoubleHash (v->u.d);
case FcTypeString:
- return FcStringHash (v.u.s);
+ return FcStringHash (fc_value_string(v));
case FcTypeBool:
- return (FcChar32) v.u.b;
+ 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));
+ 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;
+ 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 FcTypePattern:
- return (FcChar32) v.u.p->num;
+ 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;
}
static FcChar32
-FcValueListHash (FcValueList *l)
+FcValueListHash (FcValueListPtr l)
{
FcChar32 hash = 0;
- while (l)
+ for (; l; l = FcValueListNext(l))
{
- hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (l->value);
- l = l->next;
+ hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
}
return hash;
}
FcPatternDestroy (FcPattern *p)
{
int i;
+ FcPatternElt *elts;
- if (--p->ref > 0)
+ 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);
}
static int
-FcPatternPosition (const FcPattern *p, const char *object)
+FcPatternObjectPosition (const FcPattern *p, FcObject object)
{
int low, high, mid, c;
+ FcPatternElt *elts = FcPatternElts(p);
low = 0;
high = p->num - 1;
while (low <= high)
{
mid = (low + high) >> 1;
- c = strcmp (p->elts[mid].object, object);
+ c = elts[mid].object - object;
if (c == 0)
return mid;
if (c < 0)
}
FcPatternElt *
-FcPatternFindElt (const FcPattern *p, const char *object)
+FcPatternObjectFindElt (const FcPattern *p, FcObject object)
{
- int i = FcPatternPosition (p, object);
+ int i = FcPatternObjectPosition (p, object);
if (i < 0)
return 0;
- return &p->elts[i];
+ return &FcPatternElts(p)[i];
}
FcPatternElt *
-FcPatternInsertElt (FcPattern *p, const char *object)
+FcPatternObjectInsertElt (FcPattern *p, FcObject object)
{
int i;
FcPatternElt *e;
- i = FcPatternPosition (p, object);
+ i = FcPatternObjectPosition (p, object);
if (i < 0)
{
i = -i - 1;
- /* grow array */
+ /* reallocate array */
if (p->num + 1 >= p->size)
{
int s = p->size + 16;
- if (p->elts)
- e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
+ 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 = e;
+ 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)
{
- p->elts[p->size].object = 0;
- p->elts[p->size].values = 0;
+ e[p->size].object = 0;
+ e[p->size].values = NULL;
p->size++;
}
}
+ e = FcPatternElts(p);
/* move elts up */
- memmove (p->elts + i + 1,
- p->elts + i,
+ memmove (e + i + 1,
+ e + i,
sizeof (FcPatternElt) *
(p->num - i));
/* bump count */
p->num++;
- p->elts[i].object = object;
- p->elts[i].values = 0;
+ e[i].object = object;
+ e[i].values = NULL;
}
- return &p->elts[i];
+ return FcPatternElts(p) + i;
}
FcBool
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;
{
int i;
FcChar32 h = 0;
+ FcPatternElt *pe = FcPatternElts(p);
for (i = 0; i < p->num; i++)
{
h = (((h << 1) | (h >> 31)) ^
- FcStringHash ((const FcChar8 *) p->elts[i].object) ^
- FcValueListHash (p->elts[i].values));
+ pe[i].object ^
+ FcValueListHash (FcPatternEltValues(&pe[i])));
}
return h;
}
FcBool
-FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os)
+FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
{
FcPatternElt *ea, *eb;
int i;
for (i = 0; i < os->nobject; i++)
{
- ea = FcPatternFindElt (pa, os->objects[i]);
- eb = FcPatternFindElt (pb, os->objects[i]);
+ FcObject object = FcObjectFromName (os->objects[i]);
+ ea = FcPatternObjectFindElt (pai, object);
+ eb = FcPatternObjectFindElt (pbi, object);
if (ea)
{
if (!eb)
return FcFalse;
- if (!FcValueListEqual (ea->values, eb->values))
+ if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
return FcFalse;
}
else
}
FcBool
-FcPatternAddWithBinding (FcPattern *p,
- const char *object,
- FcValue value,
- FcValueBinding binding,
- FcBool append)
+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))
+ {
+ if (FcDebug() & FC_DBG_OBJTYPES)
+ {
+ printf ("FcPattern object %s does not accept value ",
+ FcObjectName (object));
+ FcValuePrint (value);
+ }
+ goto bail1;
+ }
+
new->value = value;
new->binding = binding;
- new->next = 0;
+ new->next = NULL;
- e = FcPatternInsertElt (p, object);
+ 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;
- case FcTypePattern:
- FcPatternDestroy ((FcPattern *) value.u.p);
- break;
- default:
- break;
- }
+ FcValueDestroy (value);
bail1:
FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
free (new);
return FcFalse;
}
+FcBool
+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 FcPatternAddWithBinding (p, object, value, FcValueBindingStrong, append);
+ return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
+ value, FcValueBindingStrong, append);
}
FcBool
FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
{
- return FcPatternAddWithBinding (p, object, value, FcValueBindingWeak, append);
+ return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
+ value, FcValueBindingWeak, append);
}
FcBool
-FcPatternDel (FcPattern *p, const char *object)
+FcPatternObjectDel (FcPattern *p, FcObject object)
{
FcPatternElt *e;
- int i;
- e = FcPatternFindElt (p, object);
+ 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);
}
}
FcBool
-FcPatternAddPattern (FcPattern *p, const char *object, const FcPattern *pp)
+FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
{
FcValue v;
- v.type = FcTypePattern;
- v.u.p = pp;
+ 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 = FcPatternFindElt (p, object);
+ 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;
}
FcResult
-FcPatternGetPattern (FcPattern *p, const char *object, int id, FcPattern **pp)
+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 != FcTypePattern)
+ if (v.type != FcTypeLangSet)
return FcResultTypeMismatch;
- *pp = (FcPattern *) v.u.p;
+ *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;
}
void
FcPatternReference (FcPattern *p)
{
- p->ref++;
+ if (p->ref != FC_REF_CONSTANT)
+ p->ref++;
}
FcPattern *
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;
+}