diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/extras/fontconfig/src/fcpat.c | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/extras/fontconfig/src/fcpat.c')
-rw-r--r-- | nx-X11/extras/fontconfig/src/fcpat.c | 1202 |
1 files changed, 1202 insertions, 0 deletions
diff --git a/nx-X11/extras/fontconfig/src/fcpat.c b/nx-X11/extras/fontconfig/src/fcpat.c new file mode 100644 index 000000000..c886c9258 --- /dev/null +++ b/nx-X11/extras/fontconfig/src/fcpat.c @@ -0,0 +1,1202 @@ +/* + * $RCSId: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $ + * + * 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 + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "fcint.h" + +FcPattern * +FcPatternCreate (void) +{ + FcPattern *p; + + p = (FcPattern *) malloc (sizeof (FcPattern)); + if (!p) + return 0; + FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern)); + p->num = 0; + p->size = 0; + p->elts = 0; + p->ref = 1; + return p; +} + +void +FcValueDestroy (FcValue v) +{ + switch (v.type) { + case FcTypeString: + FcStrFree ((FcChar8 *) v.u.s); + break; + case FcTypeMatrix: + FcMatrixFree ((FcMatrix *) v.u.m); + break; + case FcTypeCharSet: + FcCharSetDestroy ((FcCharSet *) v.u.c); + break; + case FcTypeLangSet: + FcLangSetDestroy ((FcLangSet *) v.u.l); + break; + default: + break; + } +} + +FcValue +FcValueSave (FcValue v) +{ + switch (v.type) { + case FcTypeString: + v.u.s = FcStrCopy (v.u.s); + if (!v.u.s) + v.type = FcTypeVoid; + break; + case FcTypeMatrix: + v.u.m = FcMatrixCopy (v.u.m); + if (!v.u.m) + v.type = FcTypeVoid; + break; + case FcTypeCharSet: + v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c); + 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; + } + return v; +} + +void +FcValueListDestroy (FcValueList *l) +{ + FcValueList *next; + for (; l; l = next) + { + switch (l->value.type) { + case FcTypeString: + FcStrFree ((FcChar8 *) l->value.u.s); + break; + case FcTypeMatrix: + FcMatrixFree ((FcMatrix *) l->value.u.m); + break; + case FcTypeCharSet: + FcCharSetDestroy ((FcCharSet *) l->value.u.c); + break; + case FcTypeLangSet: + FcLangSetDestroy ((FcLangSet *) l->value.u.l); + break; + default: + break; + } + next = l->next; + FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); + free (l); + } +} + +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; + 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; +} + +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); + 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)) + 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 == FC_REF_CONSTANT || --p->ref > 0) + return; + + for (i = 0; i < p->num; i++) + FcValueListDestroy (p->elts[i].values); + + 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_PATTERN, sizeof (FcPattern)); + 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 size; + + n = 0; + for (l = h; l; l = l->next) + n++; + size = sizeof (FcValueListAlign) + n * sizeof (FcValueList); + 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); + new = e->list; + for (l = h; l; l = l->next, new++) + { + if (l->value.type == FcTypeString) + { + new->value.type = FcTypeString; + new->value.u.s = FcObjectStaticName (l->value.u.s); + } + else + { + new->value = FcValueSave (l->value); + } + new->binding = l->binding; + if (l->next) + new->next = new + 1; + else + new->next = 0; + } + return e; +} + +static void +FcValueListEntDestroy (FcValueListEnt *e) +{ + FcValueList *l; + + FcValueListFrozenCount[e->list->value.type]--; + + /* XXX: We should perform these two operations with "size" as + computed in FcValueListEntCreate, but we don't have access to + that value here. Without this, the FcValueListFrozenBytes + values will be wrong as will the FcMemFree counts. + + FcValueListFrozenBytes[e->list->value.type] -= size; + FcMemFree (FC_MEM_VALLIST, size); + */ + + for (l = e->list; l; l = l->next) + { + if (l->value.type != FcTypeString) + FcValueDestroy (l->value); + } + /* XXX: Are we being too chummy with the implementation here to + free(e) when it was actually the enclosing FcValueListAlign + that was allocated? */ + free (e); +} + +static int FcValueListTotal; +static int FcValueListUsed; + +static FcValueListEnt *FcValueListHashTable[FC_VALUE_LIST_HASH_SIZE]; + +static FcValueList * +FcValueListFreeze (FcValueList *l) +{ + FcChar32 hash = FcValueListHash (l); + FcValueListEnt **bucket = &FcValueListHashTable[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 void +FcValueListThawAll (void) +{ + int i; + FcValueListEnt *ent, *next; + + for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++) + { + for (ent = FcValueListHashTable[i]; ent; ent = next) + { + next = ent->next; + FcValueListEntDestroy (ent); + } + FcValueListHashTable[i] = 0; + } + + FcValueListTotal = 0; + FcValueListUsed = 0; +} + +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 FcPatternEnt *FcPatternHashTable[FC_VALUE_LIST_HASH_SIZE]; + +static FcPattern * +FcPatternBaseFreeze (FcPattern *b) +{ + FcChar32 hash = FcPatternBaseHash (b); + FcPatternEnt **bucket = &FcPatternHashTable[hash % FC_VALUE_LIST_HASH_SIZE]; + FcPatternEnt *ent; + int i; + 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 (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 + */ + size = sizeof (FcPatternEnt) + b->num*sizeof (FcPatternElt); + 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; + + for (i = 0; i < b->num; i++) + { + ent->pattern.elts[i].values = b->elts[i].values; + ent->pattern.elts[i].object = b->elts[i].object; + } + + ent->hash = hash; + ent->next = *bucket; + *bucket = ent; + return &ent->pattern; +} + +static void +FcPatternBaseThawAll (void) +{ + int i; + FcPatternEnt *ent, *next; + + for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++) + { + for (ent = FcPatternHashTable[i]; ent; ent = next) + { + next = ent->next; + free (ent); + } + FcPatternHashTable[i] = 0; + } + + FcPatternTotal = 0; + FcPatternUsed = 0; +} + +FcPattern * +FcPatternFreeze (FcPattern *p) +{ + FcPattern *b, *n = 0; + int size; + int i; + + if (p->ref == FC_REF_CONSTANT) + return p; + + 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; +} + +void +FcPatternThawAll (void) +{ + FcPatternBaseThawAll (); + FcValueListThawAll (); +} + +static int +FcPatternPosition (const FcPattern *p, const char *object) +{ + int low, high, mid, c; + + object = FcObjectStaticName(object); + low = 0; + high = p->num - 1; + c = 1; + mid = 0; + while (low <= high) + { + mid = (low + high) >> 1; + c = 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 * +FcPatternInsertElt (FcPattern *p, const char *object) +{ + int i; + FcPatternElt *e; + + i = FcPatternPosition (p, object); + if (i < 0) + { + 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 = FcObjectStaticName (object); + p->elts[i].values = 0; + } + + return &p->elts[i]; +} + +FcBool +FcPatternEqual (const FcPattern *pa, const FcPattern *pb) +{ + int i; + + if (pa == pb) + return FcTrue; + + if (pa->num != pb->num) + return FcFalse; + for (i = 0; i < pa->num; i++) + { + if (pa->elts[i].object != pb->elts[i].object) + return FcFalse; + if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values)) + return FcFalse; + } + return FcTrue; +} + +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++) + { + 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 + { + if (eb) + return FcFalse; + } + } + return FcTrue; +} + +FcBool +FcPatternAddWithBinding (FcPattern *p, + const char *object, + FcValue value, + FcValueBinding binding, + FcBool append) +{ + FcPatternElt *e; + FcValueList *new, **prev; + + if (p->ref == FC_REF_CONSTANT) + goto bail0; + + new = (FcValueList *) malloc (sizeof (FcValueList)); + if (!new) + goto bail0; + + FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList)); + /* dup string */ + value = FcValueSave (value); + if (value.type == FcTypeVoid) + goto bail1; + + new->value = value; + new->binding = binding; + new->next = 0; + + e = FcPatternInsertElt (p, object); + if (!e) + goto bail2; + + if (append) + { + for (prev = &e->values; *prev; prev = &(*prev)->next); + *prev = new; + } + else + { + new->next = e->values; + e->values = new; + } + + 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 FcTypeLangSet: + FcLangSetDestroy ((FcLangSet *) value.u.l); + break; + default: + break; + } +bail1: + FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); + free (new); +bail0: + return FcFalse; +} + +FcBool +FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append) +{ + return FcPatternAddWithBinding (p, object, value, FcValueBindingStrong, append); +} + +FcBool +FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append) +{ + return FcPatternAddWithBinding (p, object, value, FcValueBindingWeak, append); +} + +FcBool +FcPatternDel (FcPattern *p, const char *object) +{ + FcPatternElt *e; + int i; + + e = FcPatternFindElt (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)); + p->num--; + p->elts[p->num].object = 0; + p->elts[p->num].values = 0; + return FcTrue; +} + +FcBool +FcPatternRemove (FcPattern *p, const char *object, int id) +{ + FcPatternElt *e; + FcValueList **prev, *l; + + e = FcPatternFindElt (p, object); + if (!e) + return FcFalse; + for (prev = &e->values; (l = *prev); prev = &l->next) + { + if (!id) + { + *prev = l->next; + l->next = 0; + FcValueListDestroy (l); + if (!e->values) + FcPatternDel (p, object); + return FcTrue; + } + id--; + } + return FcFalse; +} + +FcBool +FcPatternAddInteger (FcPattern *p, const char *object, int i) +{ + FcValue v; + + v.type = FcTypeInteger; + v.u.i = i; + return FcPatternAdd (p, object, v, FcTrue); +} + +FcBool +FcPatternAddDouble (FcPattern *p, const char *object, double d) +{ + FcValue v; + + v.type = FcTypeDouble; + v.u.d = d; + return FcPatternAdd (p, object, v, FcTrue); +} + + +FcBool +FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s) +{ + FcValue v; + + v.type = FcTypeString; + v.u.s = s; + return FcPatternAdd (p, object, v, FcTrue); +} + +FcBool +FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s) +{ + FcValue v; + + v.type = FcTypeMatrix; + v.u.m = (FcMatrix *) s; + return FcPatternAdd (p, object, v, FcTrue); +} + + +FcBool +FcPatternAddBool (FcPattern *p, const char *object, FcBool b) +{ + FcValue v; + + v.type = FcTypeBool; + v.u.b = b; + return FcPatternAdd (p, object, v, FcTrue); +} + +FcBool +FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c) +{ + FcValue v; + + v.type = FcTypeCharSet; + v.u.c = (FcCharSet *) c; + 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); +} + +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 (const FcPattern *p, const char *object, int id, FcValue *v) +{ + FcPatternElt *e; + FcValueList *l; + + e = FcPatternFindElt (p, object); + if (!e) + return FcResultNoMatch; + for (l = e->values; l; l = l->next) + { + if (!id) + { + *v = l->value; + return FcResultMatch; + } + id--; + } + return FcResultNoId; +} + +FcResult +FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i) +{ + FcValue v; + FcResult r; + + r = FcPatternGet (p, object, id, &v); + if (r != FcResultMatch) + return r; + switch (v.type) { + case FcTypeDouble: + *i = (int) v.u.d; + break; + case FcTypeInteger: + *i = v.u.i; + break; + default: + return FcResultTypeMismatch; + } + return FcResultMatch; +} + +FcResult +FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d) +{ + FcValue v; + FcResult r; + + r = FcPatternGet (p, object, id, &v); + if (r != FcResultMatch) + return r; + switch (v.type) { + case FcTypeDouble: + *d = v.u.d; + break; + case FcTypeInteger: + *d = (double) v.u.i; + break; + default: + return FcResultTypeMismatch; + } + return FcResultMatch; +} + +FcResult +FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s) +{ + FcValue v; + FcResult r; + + r = FcPatternGet (p, object, id, &v); + if (r != FcResultMatch) + return r; + if (v.type != FcTypeString) + return FcResultTypeMismatch; + *s = (FcChar8 *) v.u.s; + return FcResultMatch; +} + +FcResult +FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m) +{ + FcValue v; + FcResult r; + + r = FcPatternGet (p, object, id, &v); + if (r != FcResultMatch) + return r; + if (v.type != FcTypeMatrix) + return FcResultTypeMismatch; + *m = (FcMatrix *) v.u.m; + return FcResultMatch; +} + + +FcResult +FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b) +{ + FcValue v; + FcResult r; + + r = FcPatternGet (p, object, id, &v); + if (r != FcResultMatch) + return r; + if (v.type != FcTypeBool) + return FcResultTypeMismatch; + *b = v.u.b; + return FcResultMatch; +} + +FcResult +FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c) +{ + FcValue v; + FcResult r; + + r = FcPatternGet (p, object, id, &v); + if (r != FcResultMatch) + return r; + if (v.type != FcTypeCharSet) + return FcResultTypeMismatch; + *c = (FcCharSet *) v.u.c; + return FcResultMatch; +} + +FcResult +FcPatternGetFTFace(const 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; +} + +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 (const FcPattern *orig) +{ + FcPattern *new; + int i; + FcValueList *l; + + new = FcPatternCreate (); + if (!new) + goto bail0; + + 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)) + goto bail1; + } + + return new; + +bail1: + FcPatternDestroy (new); +bail0: + return 0; +} + +void +FcPatternReference (FcPattern *p) +{ + if (p->ref != FC_REF_CONSTANT) + p->ref++; +} + +FcPattern * +FcPatternVaBuild (FcPattern *orig, va_list va) +{ + FcPattern *ret; + + FcPatternVapBuild (ret, orig, va); + return ret; +} + +FcPattern * +FcPatternBuild (FcPattern *orig, ...) +{ + va_list va; + + va_start (va, orig); + FcPatternVapBuild (orig, orig, 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; + FcValueList *v; + + for (i = 0; i < s->num; i++) + { + e = &s->elts[i]; + for (v = e->values; v; v = v->next) + { + if (!FcPatternAddWithBinding (p, e->object, + v->value, v->binding, FcTrue)) + return FcFalse; + } + } + return FcTrue; +} + +const char * +FcObjectStaticName (const char *name) +{ +#define OBJECT_HASH_SIZE 31 + static struct objectBucket { + struct objectBucket *next; + FcChar32 hash; + } *buckets[OBJECT_HASH_SIZE]; + FcChar32 hash = FcStringHash ((const FcChar8 *) name); + struct objectBucket **p; + struct objectBucket *b; + int size; + + for (p = &buckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next)) + if (b->hash == hash && !strcmp (name, (char *) (b + 1))) + return (char *) (b + 1); + size = sizeof (struct objectBucket) + strlen (name) + 1; + b = malloc (size); + FcMemAlloc (FC_MEM_STATICSTR, size); + if (!b) + return NULL; + b->next = 0; + b->hash = hash; + strcpy ((char *) (b + 1), name); + *p = b; + return (char *) (b + 1); +} |