fcpat.c revision b09479dc
12c393a42Smrg/*
22c393a42Smrg * Copyright © 2000 Keith Packard
32c393a42Smrg *
42c393a42Smrg * Permission to use, copy, modify, distribute, and sell this software and its
52c393a42Smrg * documentation for any purpose is hereby granted without fee, provided that
62c393a42Smrg * the above copyright notice appear in all copies and that both that
72c393a42Smrg * copyright notice and this permission notice appear in supporting
8ca08ab68Smrg * documentation, and that the name of the author(s) not be used in
92c393a42Smrg * advertising or publicity pertaining to distribution of the software without
10ca08ab68Smrg * specific, written prior permission.  The authors make no
112c393a42Smrg * representations about the suitability of this software for any purpose.  It
122c393a42Smrg * is provided "as is" without express or implied warranty.
132c393a42Smrg *
14a6844aabSmrg * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
152c393a42Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16a6844aabSmrg * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
172c393a42Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
182c393a42Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
192c393a42Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
202c393a42Smrg * PERFORMANCE OF THIS SOFTWARE.
212c393a42Smrg */
222c393a42Smrg
232c393a42Smrg#include "fcint.h"
242c393a42Smrg#include "fcftint.h"
25c9710b42Smrg
26c9710b42Smrg/* Objects MT-safe for readonly access. */
272c393a42Smrg
282c393a42SmrgFcPattern *
292c393a42SmrgFcPatternCreate (void)
302c393a42Smrg{
312c393a42Smrg    FcPattern	*p;
322c393a42Smrg
332c393a42Smrg    p = (FcPattern *) malloc (sizeof (FcPattern));
342c393a42Smrg    if (!p)
352c393a42Smrg	return 0;
36b09479dcSmrg    memset (p, 0, sizeof (FcPattern));
372c393a42Smrg    p->num = 0;
382c393a42Smrg    p->size = 0;
392c393a42Smrg    p->elts_offset = FcPtrToOffset (p, NULL);
40c9710b42Smrg    FcRefInit (&p->ref, 1);
412c393a42Smrg    return p;
422c393a42Smrg}
432c393a42Smrg
442c393a42Smrgvoid
452c393a42SmrgFcValueDestroy (FcValue v)
462c393a42Smrg{
47c9710b42Smrg    switch ((int) v.type) {
482c393a42Smrg    case FcTypeString:
49c9710b42Smrg	FcFree (v.u.s);
502c393a42Smrg	break;
512c393a42Smrg    case FcTypeMatrix:
522c393a42Smrg	FcMatrixFree ((FcMatrix *) v.u.m);
532c393a42Smrg	break;
542c393a42Smrg    case FcTypeCharSet:
552c393a42Smrg	FcCharSetDestroy ((FcCharSet *) v.u.c);
562c393a42Smrg	break;
572c393a42Smrg    case FcTypeLangSet:
582c393a42Smrg	FcLangSetDestroy ((FcLangSet *) v.u.l);
592c393a42Smrg	break;
602c393a42Smrg    default:
612c393a42Smrg	break;
622c393a42Smrg    }
632c393a42Smrg}
642c393a42Smrg
652c393a42SmrgFcValue
662c393a42SmrgFcValueCanonicalize (const FcValue *v)
672c393a42Smrg{
682c393a42Smrg    FcValue new;
692c393a42Smrg
70c9710b42Smrg    switch ((int) v->type)
712c393a42Smrg    {
722c393a42Smrg    case FcTypeString:
73a6844aabSmrg	new.u.s = FcValueString(v);
742c393a42Smrg	new.type = FcTypeString;
752c393a42Smrg	break;
762c393a42Smrg    case FcTypeCharSet:
77a6844aabSmrg	new.u.c = FcValueCharSet(v);
782c393a42Smrg	new.type = FcTypeCharSet;
792c393a42Smrg	break;
802c393a42Smrg    case FcTypeLangSet:
81a6844aabSmrg	new.u.l = FcValueLangSet(v);
822c393a42Smrg	new.type = FcTypeLangSet;
832c393a42Smrg	break;
842c393a42Smrg    default:
852c393a42Smrg	new = *v;
862c393a42Smrg	break;
872c393a42Smrg    }
882c393a42Smrg    return new;
892c393a42Smrg}
902c393a42Smrg
912c393a42SmrgFcValue
922c393a42SmrgFcValueSave (FcValue v)
932c393a42Smrg{
94c9710b42Smrg    switch ((int) v.type) {
952c393a42Smrg    case FcTypeString:
96c9710b42Smrg	v.u.s = FcStrdup (v.u.s);
972c393a42Smrg	if (!v.u.s)
982c393a42Smrg	    v.type = FcTypeVoid;
992c393a42Smrg	break;
1002c393a42Smrg    case FcTypeMatrix:
1012c393a42Smrg	v.u.m = FcMatrixCopy (v.u.m);
1022c393a42Smrg	if (!v.u.m)
1032c393a42Smrg	    v.type = FcTypeVoid;
1042c393a42Smrg	break;
1052c393a42Smrg    case FcTypeCharSet:
1062c393a42Smrg	v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
1072c393a42Smrg	if (!v.u.c)
1082c393a42Smrg	    v.type = FcTypeVoid;
1092c393a42Smrg	break;
1102c393a42Smrg    case FcTypeLangSet:
1112c393a42Smrg	v.u.l = FcLangSetCopy (v.u.l);
1122c393a42Smrg	if (!v.u.l)
1132c393a42Smrg	    v.type = FcTypeVoid;
1142c393a42Smrg	break;
1152c393a42Smrg    default:
1162c393a42Smrg	break;
1172c393a42Smrg    }
1182c393a42Smrg    return v;
1192c393a42Smrg}
1202c393a42Smrg
121ca08ab68SmrgFcValueListPtr
122ca08ab68SmrgFcValueListCreate (void)
123ca08ab68Smrg{
124c9710b42Smrg    return calloc (1, sizeof (FcValueList));
125ca08ab68Smrg}
126ca08ab68Smrg
1272c393a42Smrgvoid
1282c393a42SmrgFcValueListDestroy (FcValueListPtr l)
1292c393a42Smrg{
1302c393a42Smrg    FcValueListPtr next;
1312c393a42Smrg    for (; l; l = next)
1322c393a42Smrg    {
133c9710b42Smrg	switch ((int) l->value.type) {
1342c393a42Smrg	case FcTypeString:
135c9710b42Smrg	    FcFree (l->value.u.s);
1362c393a42Smrg	    break;
1372c393a42Smrg	case FcTypeMatrix:
1382c393a42Smrg	    FcMatrixFree ((FcMatrix *)l->value.u.m);
1392c393a42Smrg	    break;
1402c393a42Smrg	case FcTypeCharSet:
141ca08ab68Smrg	    FcCharSetDestroy
1422c393a42Smrg		((FcCharSet *) (l->value.u.c));
1432c393a42Smrg	    break;
1442c393a42Smrg	case FcTypeLangSet:
145ca08ab68Smrg	    FcLangSetDestroy
1462c393a42Smrg		((FcLangSet *) (l->value.u.l));
1472c393a42Smrg	    break;
1482c393a42Smrg	default:
1492c393a42Smrg	    break;
1502c393a42Smrg	}
1512c393a42Smrg	next = FcValueListNext(l);
1522c393a42Smrg	free(l);
1532c393a42Smrg    }
1542c393a42Smrg}
1552c393a42Smrg
156ca08ab68SmrgFcValueListPtr
157ca08ab68SmrgFcValueListPrepend (FcValueListPtr vallist,
158ca08ab68Smrg		    FcValue        value,
159ca08ab68Smrg		    FcValueBinding binding)
160ca08ab68Smrg{
161ca08ab68Smrg    FcValueListPtr new;
162ca08ab68Smrg
163ca08ab68Smrg    if (value.type == FcTypeVoid)
164ca08ab68Smrg	return vallist;
165ca08ab68Smrg    new = FcValueListCreate ();
166ca08ab68Smrg    if (!new)
167ca08ab68Smrg	return vallist;
168ca08ab68Smrg
169ca08ab68Smrg    new->value = FcValueSave (value);
170ca08ab68Smrg    new->binding = binding;
171ca08ab68Smrg    new->next = vallist;
172ca08ab68Smrg
173ca08ab68Smrg    return new;
174ca08ab68Smrg}
175ca08ab68Smrg
176ca08ab68SmrgFcValueListPtr
177ca08ab68SmrgFcValueListAppend (FcValueListPtr vallist,
178ca08ab68Smrg		   FcValue        value,
179ca08ab68Smrg		   FcValueBinding binding)
180ca08ab68Smrg{
181ca08ab68Smrg    FcValueListPtr new, last;
182ca08ab68Smrg
183ca08ab68Smrg    if (value.type == FcTypeVoid)
184ca08ab68Smrg	return vallist;
185ca08ab68Smrg    new = FcValueListCreate ();
186ca08ab68Smrg    if (!new)
187ca08ab68Smrg	return vallist;
188ca08ab68Smrg
189ca08ab68Smrg    new->value = FcValueSave (value);
190ca08ab68Smrg    new->binding = binding;
191ca08ab68Smrg    new->next = NULL;
192ca08ab68Smrg
193ca08ab68Smrg    if (vallist)
194ca08ab68Smrg    {
195ca08ab68Smrg	for (last = vallist; FcValueListNext (last); last = FcValueListNext (last));
196ca08ab68Smrg
197ca08ab68Smrg	last->next = new;
198ca08ab68Smrg    }
199ca08ab68Smrg    else
200ca08ab68Smrg	vallist = new;
201ca08ab68Smrg
202ca08ab68Smrg    return vallist;
203ca08ab68Smrg}
204ca08ab68Smrg
205ca08ab68SmrgFcValueListPtr
206ca08ab68SmrgFcValueListDuplicate(FcValueListPtr orig)
207ca08ab68Smrg{
208ca08ab68Smrg    FcValueListPtr new = NULL, l, t = NULL;
209ca08ab68Smrg    FcValue v;
210ca08ab68Smrg
211ca08ab68Smrg    for (l = orig; l != NULL; l = FcValueListNext (l))
212ca08ab68Smrg    {
213ca08ab68Smrg	if (!new)
214ca08ab68Smrg	{
215ca08ab68Smrg	    t = new = FcValueListCreate();
216ca08ab68Smrg	}
217ca08ab68Smrg	else
218ca08ab68Smrg	{
219ca08ab68Smrg	    t->next = FcValueListCreate();
220ca08ab68Smrg	    t = FcValueListNext (t);
221ca08ab68Smrg	}
222ca08ab68Smrg	v = FcValueCanonicalize (&l->value);
223ca08ab68Smrg	t->value = FcValueSave (v);
224ca08ab68Smrg	t->binding = l->binding;
225ca08ab68Smrg	t->next = NULL;
226ca08ab68Smrg    }
227ca08ab68Smrg
228ca08ab68Smrg    return new;
229ca08ab68Smrg}
230ca08ab68Smrg
2312c393a42SmrgFcBool
2322c393a42SmrgFcValueEqual (FcValue va, FcValue vb)
2332c393a42Smrg{
2342c393a42Smrg    if (va.type != vb.type)
2352c393a42Smrg    {
2362c393a42Smrg	if (va.type == FcTypeInteger)
2372c393a42Smrg	{
2382c393a42Smrg	    va.type = FcTypeDouble;
2392c393a42Smrg	    va.u.d = va.u.i;
2402c393a42Smrg	}
2412c393a42Smrg	if (vb.type == FcTypeInteger)
2422c393a42Smrg	{
2432c393a42Smrg	    vb.type = FcTypeDouble;
2442c393a42Smrg	    vb.u.d = vb.u.i;
2452c393a42Smrg	}
2462c393a42Smrg	if (va.type != vb.type)
2472c393a42Smrg	    return FcFalse;
2482c393a42Smrg    }
2492c393a42Smrg    switch (va.type) {
2506fc018e4Smrg    case FcTypeUnknown:
2516fc018e4Smrg	return FcFalse;	/* don't know how to compare this object */
2522c393a42Smrg    case FcTypeVoid:
2532c393a42Smrg	return FcTrue;
2542c393a42Smrg    case FcTypeInteger:
2552c393a42Smrg	return va.u.i == vb.u.i;
2562c393a42Smrg    case FcTypeDouble:
2572c393a42Smrg	return va.u.d == vb.u.d;
2582c393a42Smrg    case FcTypeString:
2592c393a42Smrg	return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
2602c393a42Smrg    case FcTypeBool:
2612c393a42Smrg	return va.u.b == vb.u.b;
2622c393a42Smrg    case FcTypeMatrix:
2632c393a42Smrg	return FcMatrixEqual (va.u.m, vb.u.m);
2642c393a42Smrg    case FcTypeCharSet:
2652c393a42Smrg	return FcCharSetEqual (va.u.c, vb.u.c);
2662c393a42Smrg    case FcTypeFTFace:
2672c393a42Smrg	return va.u.f == vb.u.f;
2682c393a42Smrg    case FcTypeLangSet:
2692c393a42Smrg	return FcLangSetEqual (va.u.l, vb.u.l);
2702c393a42Smrg    }
2712c393a42Smrg    return FcFalse;
2722c393a42Smrg}
2732c393a42Smrg
2742c393a42Smrgstatic FcChar32
2752c393a42SmrgFcDoubleHash (double d)
2762c393a42Smrg{
2772c393a42Smrg    if (d < 0)
2782c393a42Smrg	d = -d;
2792c393a42Smrg    if (d > 0xffffffff)
2802c393a42Smrg	d = 0xffffffff;
2812c393a42Smrg    return (FcChar32) d;
2822c393a42Smrg}
2832c393a42Smrg
2842c393a42SmrgFcChar32
2852c393a42SmrgFcStringHash (const FcChar8 *s)
2862c393a42Smrg{
2872c393a42Smrg    FcChar8	c;
2882c393a42Smrg    FcChar32	h = 0;
289ca08ab68Smrg
2902c393a42Smrg    if (s)
2912c393a42Smrg	while ((c = *s++))
2922c393a42Smrg	    h = ((h << 1) | (h >> 31)) ^ c;
2932c393a42Smrg    return h;
2942c393a42Smrg}
2952c393a42Smrg
2962c393a42Smrgstatic FcChar32
2972c393a42SmrgFcValueHash (const FcValue *v)
2982c393a42Smrg{
299a6844aabSmrg    switch (v->type) {
3006fc018e4Smrg    case FcTypeUnknown:
3012c393a42Smrg    case FcTypeVoid:
3022c393a42Smrg	return 0;
3032c393a42Smrg    case FcTypeInteger:
3042c393a42Smrg	return (FcChar32) v->u.i;
3052c393a42Smrg    case FcTypeDouble:
3062c393a42Smrg	return FcDoubleHash (v->u.d);
3072c393a42Smrg    case FcTypeString:
308a6844aabSmrg	return FcStringHash (FcValueString(v));
3092c393a42Smrg    case FcTypeBool:
3102c393a42Smrg	return (FcChar32) v->u.b;
3112c393a42Smrg    case FcTypeMatrix:
312ca08ab68Smrg	return (FcDoubleHash (v->u.m->xx) ^
313ca08ab68Smrg		FcDoubleHash (v->u.m->xy) ^
314ca08ab68Smrg		FcDoubleHash (v->u.m->yx) ^
3152c393a42Smrg		FcDoubleHash (v->u.m->yy));
3162c393a42Smrg    case FcTypeCharSet:
317a6844aabSmrg	return (FcChar32) FcValueCharSet(v)->num;
3182c393a42Smrg    case FcTypeFTFace:
3192c393a42Smrg	return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
3202c393a42Smrg	       FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
3212c393a42Smrg    case FcTypeLangSet:
322a6844aabSmrg	return FcLangSetHash (FcValueLangSet(v));
3232c393a42Smrg    }
3246fc018e4Smrg    return 0;
3252c393a42Smrg}
3262c393a42Smrg
3272c393a42Smrgstatic FcBool
3282c393a42SmrgFcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
3292c393a42Smrg{
3302c393a42Smrg    if (la == lb)
3312c393a42Smrg	return FcTrue;
3322c393a42Smrg
3332c393a42Smrg    while (la && lb)
3342c393a42Smrg    {
3352c393a42Smrg	if (!FcValueEqual (la->value, lb->value))
3362c393a42Smrg	    return FcFalse;
3372c393a42Smrg	la = FcValueListNext(la);
3382c393a42Smrg	lb = FcValueListNext(lb);
3392c393a42Smrg    }
3402c393a42Smrg    if (la || lb)
3412c393a42Smrg	return FcFalse;
3422c393a42Smrg    return FcTrue;
3432c393a42Smrg}
3442c393a42Smrg
3452c393a42Smrgstatic FcChar32
3462c393a42SmrgFcValueListHash (FcValueListPtr l)
3472c393a42Smrg{
3482c393a42Smrg    FcChar32	hash = 0;
349ca08ab68Smrg
3502c393a42Smrg    for (; l; l = FcValueListNext(l))
3512c393a42Smrg    {
3522c393a42Smrg	hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
3532c393a42Smrg    }
3542c393a42Smrg    return hash;
3552c393a42Smrg}
3562c393a42Smrg
3572c393a42Smrgvoid
3582c393a42SmrgFcPatternDestroy (FcPattern *p)
3592c393a42Smrg{
3602c393a42Smrg    int		    i;
3612c393a42Smrg    FcPatternElt    *elts;
362ca08ab68Smrg
363c9710b42Smrg    if (!p)
364c9710b42Smrg	return;
365c9710b42Smrg
366c9710b42Smrg    if (FcRefIsConst (&p->ref))
3672c393a42Smrg    {
3682c393a42Smrg	FcCacheObjectDereference (p);
3692c393a42Smrg	return;
3702c393a42Smrg    }
3712c393a42Smrg
372c9710b42Smrg    if (FcRefDec (&p->ref) != 1)
3732c393a42Smrg	return;
3742c393a42Smrg
3752c393a42Smrg    elts = FcPatternElts (p);
3762c393a42Smrg    for (i = 0; i < p->num; i++)
3772c393a42Smrg	FcValueListDestroy (FcPatternEltValues(&elts[i]));
3782c393a42Smrg
3792c393a42Smrg    free (elts);
3802c393a42Smrg    free (p);
3812c393a42Smrg}
3822c393a42Smrg
3832c393a42Smrgstatic int
3842c393a42SmrgFcPatternObjectPosition (const FcPattern *p, FcObject object)
3852c393a42Smrg{
3862c393a42Smrg    int	    low, high, mid, c;
3872c393a42Smrg    FcPatternElt    *elts = FcPatternElts(p);
3882c393a42Smrg
3892c393a42Smrg    low = 0;
3902c393a42Smrg    high = p->num - 1;
3912c393a42Smrg    c = 1;
3922c393a42Smrg    mid = 0;
3932c393a42Smrg    while (low <= high)
3942c393a42Smrg    {
3952c393a42Smrg	mid = (low + high) >> 1;
3962c393a42Smrg	c = elts[mid].object - object;
3972c393a42Smrg	if (c == 0)
3982c393a42Smrg	    return mid;
3992c393a42Smrg	if (c < 0)
4002c393a42Smrg	    low = mid + 1;
4012c393a42Smrg	else
4022c393a42Smrg	    high = mid - 1;
4032c393a42Smrg    }
4042c393a42Smrg    if (c < 0)
4052c393a42Smrg	mid++;
4062c393a42Smrg    return -(mid + 1);
4072c393a42Smrg}
4082c393a42Smrg
4092c393a42SmrgFcPatternElt *
4102c393a42SmrgFcPatternObjectFindElt (const FcPattern *p, FcObject object)
4112c393a42Smrg{
4122c393a42Smrg    int	    i = FcPatternObjectPosition (p, object);
4132c393a42Smrg    if (i < 0)
4142c393a42Smrg	return 0;
4152c393a42Smrg    return &FcPatternElts(p)[i];
4162c393a42Smrg}
4172c393a42Smrg
4182c393a42SmrgFcPatternElt *
4192c393a42SmrgFcPatternObjectInsertElt (FcPattern *p, FcObject object)
4202c393a42Smrg{
4212c393a42Smrg    int		    i;
4222c393a42Smrg    FcPatternElt   *e;
423ca08ab68Smrg
4242c393a42Smrg    i = FcPatternObjectPosition (p, object);
4252c393a42Smrg    if (i < 0)
4262c393a42Smrg    {
4272c393a42Smrg	i = -i - 1;
428ca08ab68Smrg
4292c393a42Smrg	/* reallocate array */
4302c393a42Smrg	if (p->num + 1 >= p->size)
4312c393a42Smrg	{
4322c393a42Smrg	    int s = p->size + 16;
4332c393a42Smrg	    if (p->size)
4342c393a42Smrg	    {
4352c393a42Smrg		FcPatternElt *e0 = FcPatternElts(p);
4362c393a42Smrg		e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
4372c393a42Smrg		if (!e) /* maybe it was mmapped */
4382c393a42Smrg		{
4392c393a42Smrg		    e = malloc(s * sizeof (FcPatternElt));
4402c393a42Smrg		    if (e)
4412c393a42Smrg			memcpy(e, e0, p->num * sizeof (FcPatternElt));
4422c393a42Smrg		}
4432c393a42Smrg	    }
4442c393a42Smrg	    else
4452c393a42Smrg		e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
4462c393a42Smrg	    if (!e)
4472c393a42Smrg		return FcFalse;
4482c393a42Smrg	    p->elts_offset = FcPtrToOffset (p, e);
4492c393a42Smrg	    while (p->size < s)
4502c393a42Smrg	    {
4512c393a42Smrg		e[p->size].object = 0;
4522c393a42Smrg		e[p->size].values = NULL;
4532c393a42Smrg		p->size++;
4542c393a42Smrg	    }
4552c393a42Smrg	}
4562c393a42Smrg
4572c393a42Smrg	e = FcPatternElts(p);
4582c393a42Smrg	/* move elts up */
4592c393a42Smrg	memmove (e + i + 1,
4602c393a42Smrg		 e + i,
4612c393a42Smrg		 sizeof (FcPatternElt) *
4622c393a42Smrg		 (p->num - i));
463ca08ab68Smrg
4642c393a42Smrg	/* bump count */
4652c393a42Smrg	p->num++;
4662c393a42Smrg
4672c393a42Smrg	e[i].object = object;
4682c393a42Smrg	e[i].values = NULL;
4692c393a42Smrg    }
470ca08ab68Smrg
4712c393a42Smrg    return FcPatternElts(p) + i;
4722c393a42Smrg}
4732c393a42Smrg
4742c393a42SmrgFcBool
4752c393a42SmrgFcPatternEqual (const FcPattern *pa, const FcPattern *pb)
4762c393a42Smrg{
4772c393a42Smrg    int	i;
4782c393a42Smrg    FcPatternElt   *pae, *pbe;
4792c393a42Smrg
4802c393a42Smrg    if (pa == pb)
4812c393a42Smrg	return FcTrue;
4822c393a42Smrg
4832c393a42Smrg    if (pa->num != pb->num)
4842c393a42Smrg	return FcFalse;
4852c393a42Smrg    pae = FcPatternElts(pa);
4862c393a42Smrg    pbe = FcPatternElts(pb);
4872c393a42Smrg    for (i = 0; i < pa->num; i++)
4882c393a42Smrg    {
4892c393a42Smrg	if (pae[i].object != pbe[i].object)
4902c393a42Smrg	    return FcFalse;
4912c393a42Smrg	if (!FcValueListEqual (FcPatternEltValues(&pae[i]),
4922c393a42Smrg			       FcPatternEltValues(&pbe[i])))
4932c393a42Smrg	    return FcFalse;
4942c393a42Smrg    }
4952c393a42Smrg    return FcTrue;
4962c393a42Smrg}
4972c393a42Smrg
4982c393a42SmrgFcChar32
4992c393a42SmrgFcPatternHash (const FcPattern *p)
5002c393a42Smrg{
5012c393a42Smrg    int		i;
5022c393a42Smrg    FcChar32	h = 0;
5032c393a42Smrg    FcPatternElt    *pe = FcPatternElts(p);
5042c393a42Smrg
5052c393a42Smrg    for (i = 0; i < p->num; i++)
5062c393a42Smrg    {
507ca08ab68Smrg	h = (((h << 1) | (h >> 31)) ^
5082c393a42Smrg	     pe[i].object ^
5092c393a42Smrg	     FcValueListHash (FcPatternEltValues(&pe[i])));
5102c393a42Smrg    }
5112c393a42Smrg    return h;
5122c393a42Smrg}
5132c393a42Smrg
5142c393a42SmrgFcBool
5152c393a42SmrgFcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
5162c393a42Smrg{
5172c393a42Smrg    FcPatternElt    *ea, *eb;
5182c393a42Smrg    int		    i;
519ca08ab68Smrg
5202c393a42Smrg    for (i = 0; i < os->nobject; i++)
5212c393a42Smrg    {
5222c393a42Smrg	FcObject    object = FcObjectFromName (os->objects[i]);
5232c393a42Smrg	ea = FcPatternObjectFindElt (pai, object);
5242c393a42Smrg	eb = FcPatternObjectFindElt (pbi, object);
5252c393a42Smrg	if (ea)
5262c393a42Smrg	{
5272c393a42Smrg	    if (!eb)
5282c393a42Smrg		return FcFalse;
5292c393a42Smrg	    if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
5302c393a42Smrg		return FcFalse;
5312c393a42Smrg	}
5322c393a42Smrg	else
5332c393a42Smrg	{
5342c393a42Smrg	    if (eb)
5352c393a42Smrg		return FcFalse;
5362c393a42Smrg	}
5372c393a42Smrg    }
5382c393a42Smrg    return FcTrue;
5392c393a42Smrg}
5402c393a42Smrg
541ca08ab68SmrgFcBool
542ca08ab68SmrgFcPatternObjectListAdd (FcPattern	*p,
543ca08ab68Smrg			FcObject	object,
544ca08ab68Smrg			FcValueListPtr	list,
545ca08ab68Smrg			FcBool		append)
546ca08ab68Smrg{
547ca08ab68Smrg    FcPatternElt   *e;
548ca08ab68Smrg    FcValueListPtr l, *prev;
549ca08ab68Smrg
550c9710b42Smrg    if (FcRefIsConst (&p->ref))
551ca08ab68Smrg	goto bail0;
552ca08ab68Smrg
553ca08ab68Smrg    /*
554ca08ab68Smrg     * Make sure the stored type is valid for built-in objects
555ca08ab68Smrg     */
556ca08ab68Smrg    for (l = list; l != NULL; l = FcValueListNext (l))
557ca08ab68Smrg    {
558ca08ab68Smrg	if (!FcObjectValidType (object, l->value.type))
559ca08ab68Smrg	{
560c9710b42Smrg	    fprintf (stderr,
561c9710b42Smrg		     "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
562c9710b42Smrg	    FcValuePrintFile (stderr, l->value);
563c9710b42Smrg	    fprintf (stderr, "\n");
564ca08ab68Smrg	    goto bail0;
565ca08ab68Smrg	}
566ca08ab68Smrg    }
567ca08ab68Smrg
568ca08ab68Smrg    e = FcPatternObjectInsertElt (p, object);
569ca08ab68Smrg    if (!e)
570ca08ab68Smrg	goto bail0;
571ca08ab68Smrg
572ca08ab68Smrg    if (append)
573ca08ab68Smrg    {
574ca08ab68Smrg	for (prev = &e->values; *prev; prev = &(*prev)->next)
575ca08ab68Smrg	    ;
576ca08ab68Smrg	*prev = list;
577ca08ab68Smrg    }
578ca08ab68Smrg    else
579ca08ab68Smrg    {
580ca08ab68Smrg	for (prev = &list; *prev; prev = &(*prev)->next)
581ca08ab68Smrg	    ;
582ca08ab68Smrg	*prev = e->values;
583ca08ab68Smrg	e->values = list;
584ca08ab68Smrg    }
585ca08ab68Smrg
586ca08ab68Smrg    return FcTrue;
587ca08ab68Smrg
588ca08ab68Smrgbail0:
589ca08ab68Smrg    return FcFalse;
590ca08ab68Smrg}
591ca08ab68Smrg
5922c393a42SmrgFcBool
5932c393a42SmrgFcPatternObjectAddWithBinding  (FcPattern	*p,
5942c393a42Smrg				FcObject	object,
5952c393a42Smrg				FcValue		value,
5962c393a42Smrg				FcValueBinding  binding,
5972c393a42Smrg				FcBool		append)
5982c393a42Smrg{
5992c393a42Smrg    FcPatternElt   *e;
6002c393a42Smrg    FcValueListPtr new, *prev;
6012c393a42Smrg
602c9710b42Smrg    if (FcRefIsConst (&p->ref))
6032c393a42Smrg	goto bail0;
6042c393a42Smrg
605ca08ab68Smrg    new = FcValueListCreate ();
6062c393a42Smrg    if (!new)
6072c393a42Smrg	goto bail0;
6082c393a42Smrg
609a6844aabSmrg    value = FcValueSave (value);
6102c393a42Smrg    if (value.type == FcTypeVoid)
6112c393a42Smrg	goto bail1;
6122c393a42Smrg
6132c393a42Smrg    /*
6142c393a42Smrg     * Make sure the stored type is valid for built-in objects
6152c393a42Smrg     */
6162c393a42Smrg    if (!FcObjectValidType (object, value.type))
6172c393a42Smrg    {
618c9710b42Smrg	fprintf (stderr,
619c9710b42Smrg		 "Fontconfig warning: FcPattern object %s does not accept value",
620c9710b42Smrg		 FcObjectName (object));
621c9710b42Smrg	FcValuePrintFile (stderr, value);
622c9710b42Smrg	fprintf (stderr, "\n");
6232c393a42Smrg	goto bail1;
6242c393a42Smrg    }
6252c393a42Smrg
6262c393a42Smrg    new->value = value;
6272c393a42Smrg    new->binding = binding;
6282c393a42Smrg    new->next = NULL;
629ca08ab68Smrg
6302c393a42Smrg    e = FcPatternObjectInsertElt (p, object);
6312c393a42Smrg    if (!e)
6322c393a42Smrg	goto bail2;
633ca08ab68Smrg
6342c393a42Smrg    if (append)
6352c393a42Smrg    {
6362c393a42Smrg	for (prev = &e->values; *prev; prev = &(*prev)->next)
6372c393a42Smrg	    ;
6382c393a42Smrg	*prev = new;
6392c393a42Smrg    }
6402c393a42Smrg    else
6412c393a42Smrg    {
6422c393a42Smrg	new->next = e->values;
6432c393a42Smrg	e->values = new;
6442c393a42Smrg    }
645ca08ab68Smrg
6462c393a42Smrg    return FcTrue;
6472c393a42Smrg
648ca08ab68Smrgbail2:
6492c393a42Smrg    FcValueDestroy (value);
6502c393a42Smrgbail1:
6512c393a42Smrg    free (new);
6522c393a42Smrgbail0:
6532c393a42Smrg    return FcFalse;
6542c393a42Smrg}
6552c393a42Smrg
6562c393a42SmrgFcBool
6572c393a42SmrgFcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
6582c393a42Smrg{
6592c393a42Smrg    return FcPatternObjectAddWithBinding (p, object,
6602c393a42Smrg					  value, FcValueBindingStrong, append);
6612c393a42Smrg}
6622c393a42Smrg
6632c393a42SmrgFcBool
6642c393a42SmrgFcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
6652c393a42Smrg{
6662c393a42Smrg    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
6672c393a42Smrg					  value, FcValueBindingStrong, append);
6682c393a42Smrg}
6692c393a42Smrg
6702c393a42SmrgFcBool
6712c393a42SmrgFcPatternAddWeak  (FcPattern *p, const char *object, FcValue value, FcBool append)
6722c393a42Smrg{
6732c393a42Smrg    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
6742c393a42Smrg					  value, FcValueBindingWeak, append);
6752c393a42Smrg}
6762c393a42Smrg
6772c393a42SmrgFcBool
6782c393a42SmrgFcPatternObjectDel (FcPattern *p, FcObject object)
6792c393a42Smrg{
6802c393a42Smrg    FcPatternElt   *e;
6812c393a42Smrg
6822c393a42Smrg    e = FcPatternObjectFindElt (p, object);
6832c393a42Smrg    if (!e)
6842c393a42Smrg	return FcFalse;
6852c393a42Smrg
6862c393a42Smrg    /* destroy value */
6872c393a42Smrg    FcValueListDestroy (e->values);
688ca08ab68Smrg
6892c393a42Smrg    /* shuffle existing ones down */
690ca08ab68Smrg    memmove (e, e+1,
691ca08ab68Smrg	     (FcPatternElts(p) + p->num - (e + 1)) *
6922c393a42Smrg	     sizeof (FcPatternElt));
6932c393a42Smrg    p->num--;
6942c393a42Smrg    e = FcPatternElts(p) + p->num;
6952c393a42Smrg    e->object = 0;
6962c393a42Smrg    e->values = NULL;
6972c393a42Smrg    return FcTrue;
6982c393a42Smrg}
6992c393a42Smrg
7002c393a42SmrgFcBool
7012c393a42SmrgFcPatternDel (FcPattern *p, const char *object)
7022c393a42Smrg{
7032c393a42Smrg    return FcPatternObjectDel (p, FcObjectFromName (object));
7042c393a42Smrg}
705ca08ab68Smrg
7062c393a42SmrgFcBool
7072c393a42SmrgFcPatternRemove (FcPattern *p, const char *object, int id)
7082c393a42Smrg{
7092c393a42Smrg    FcPatternElt    *e;
7102c393a42Smrg    FcValueListPtr  *prev, l;
7112c393a42Smrg
7122c393a42Smrg    e = FcPatternObjectFindElt (p, FcObjectFromName (object));
7132c393a42Smrg    if (!e)
7142c393a42Smrg	return FcFalse;
7152c393a42Smrg    for (prev = &e->values; (l = *prev); prev = &l->next)
7162c393a42Smrg    {
7172c393a42Smrg	if (!id)
7182c393a42Smrg	{
7192c393a42Smrg	    *prev = l->next;
7202c393a42Smrg	    l->next = NULL;
7212c393a42Smrg	    FcValueListDestroy (l);
7222c393a42Smrg	    if (!e->values)
7232c393a42Smrg		FcPatternDel (p, object);
7242c393a42Smrg	    return FcTrue;
7252c393a42Smrg	}
7262c393a42Smrg	id--;
7272c393a42Smrg    }
7282c393a42Smrg    return FcFalse;
7292c393a42Smrg}
7302c393a42Smrg
7312c393a42SmrgFcBool
7322c393a42SmrgFcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
7332c393a42Smrg{
7342c393a42Smrg    FcValue	v;
7352c393a42Smrg
7362c393a42Smrg    v.type = FcTypeInteger;
7372c393a42Smrg    v.u.i = i;
7382c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
7392c393a42Smrg}
7402c393a42Smrg
7412c393a42SmrgFcBool
7422c393a42SmrgFcPatternAddInteger (FcPattern *p, const char *object, int i)
7432c393a42Smrg{
7442c393a42Smrg    return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
7452c393a42Smrg}
7462c393a42Smrg
7472c393a42SmrgFcBool
7482c393a42SmrgFcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
7492c393a42Smrg{
7502c393a42Smrg    FcValue	v;
7512c393a42Smrg
7522c393a42Smrg    v.type = FcTypeDouble;
7532c393a42Smrg    v.u.d = d;
7542c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
7552c393a42Smrg}
7562c393a42Smrg
7572c393a42Smrg
7582c393a42SmrgFcBool
7592c393a42SmrgFcPatternAddDouble (FcPattern *p, const char *object, double d)
7602c393a42Smrg{
7612c393a42Smrg    return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
7622c393a42Smrg}
7632c393a42Smrg
7642c393a42SmrgFcBool
7652c393a42SmrgFcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
7662c393a42Smrg{
7672c393a42Smrg    FcValue	v;
7682c393a42Smrg
7692c393a42Smrg    if (!s)
7702c393a42Smrg    {
7712c393a42Smrg	v.type = FcTypeVoid;
7722c393a42Smrg	v.u.s = 0;
7732c393a42Smrg	return FcPatternObjectAdd (p, object, v, FcTrue);
7742c393a42Smrg    }
7752c393a42Smrg
7762c393a42Smrg    v.type = FcTypeString;
777ca08ab68Smrg    v.u.s = s;
7782c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
7792c393a42Smrg}
7802c393a42Smrg
7812c393a42SmrgFcBool
7822c393a42SmrgFcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
7832c393a42Smrg{
7842c393a42Smrg    return FcPatternObjectAddString (p, FcObjectFromName (object), s);
7852c393a42Smrg}
7862c393a42Smrg
7872c393a42SmrgFcBool
7882c393a42SmrgFcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
7892c393a42Smrg{
7902c393a42Smrg    FcValue	v;
7912c393a42Smrg
7922c393a42Smrg    v.type = FcTypeMatrix;
7932c393a42Smrg    v.u.m = s;
7942c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
7952c393a42Smrg}
7962c393a42Smrg
7972c393a42Smrg
7982c393a42SmrgFcBool
7992c393a42SmrgFcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
8002c393a42Smrg{
8012c393a42Smrg    FcValue	v;
8022c393a42Smrg
8032c393a42Smrg    v.type = FcTypeBool;
8042c393a42Smrg    v.u.b = b;
8052c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
8062c393a42Smrg}
8072c393a42Smrg
8082c393a42SmrgFcBool
8092c393a42SmrgFcPatternAddBool (FcPattern *p, const char *object, FcBool b)
8102c393a42Smrg{
8112c393a42Smrg    return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
8122c393a42Smrg}
8132c393a42Smrg
8142c393a42SmrgFcBool
8152c393a42SmrgFcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
8162c393a42Smrg{
8172c393a42Smrg    FcValue	v;
8182c393a42Smrg
8192c393a42Smrg    v.type = FcTypeCharSet;
8202c393a42Smrg    v.u.c = (FcCharSet *)c;
8212c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8222c393a42Smrg}
8232c393a42Smrg
8242c393a42SmrgFcBool
8252c393a42SmrgFcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
8262c393a42Smrg{
8272c393a42Smrg    FcValue	v;
8282c393a42Smrg
8292c393a42Smrg    v.type = FcTypeFTFace;
8302c393a42Smrg    v.u.f = (void *) f;
8312c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8322c393a42Smrg}
8332c393a42Smrg
8342c393a42SmrgFcBool
8352c393a42SmrgFcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
8362c393a42Smrg{
8372c393a42Smrg    FcValue	v;
8382c393a42Smrg
8392c393a42Smrg    v.type = FcTypeLangSet;
8402c393a42Smrg    v.u.l = (FcLangSet *)ls;
8412c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8422c393a42Smrg}
8432c393a42Smrg
8442c393a42SmrgFcResult
8452c393a42SmrgFcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
8462c393a42Smrg{
8472c393a42Smrg    FcPatternElt   *e;
8482c393a42Smrg    FcValueListPtr l;
8492c393a42Smrg
850c9710b42Smrg    if (!p)
851c9710b42Smrg	return FcResultNoMatch;
8522c393a42Smrg    e = FcPatternObjectFindElt (p, object);
8532c393a42Smrg    if (!e)
8542c393a42Smrg	return FcResultNoMatch;
8552c393a42Smrg    for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
8562c393a42Smrg    {
8572c393a42Smrg	if (!id)
8582c393a42Smrg	{
8592c393a42Smrg	    *v = FcValueCanonicalize(&l->value);
8602c393a42Smrg	    return FcResultMatch;
8612c393a42Smrg	}
8622c393a42Smrg	id--;
8632c393a42Smrg    }
8642c393a42Smrg    return FcResultNoId;
8652c393a42Smrg}
8662c393a42Smrg
8672c393a42SmrgFcResult
8682c393a42SmrgFcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
8692c393a42Smrg{
8702c393a42Smrg    return FcPatternObjectGet (p, FcObjectFromName (object), id, v);
8712c393a42Smrg}
8722c393a42Smrg
8732c393a42SmrgFcResult
8742c393a42SmrgFcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
8752c393a42Smrg{
8762c393a42Smrg    FcValue	v;
8772c393a42Smrg    FcResult	r;
8782c393a42Smrg
8792c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
8802c393a42Smrg    if (r != FcResultMatch)
8812c393a42Smrg	return r;
882c9710b42Smrg    switch ((int) v.type) {
8832c393a42Smrg    case FcTypeDouble:
8842c393a42Smrg	*i = (int) v.u.d;
8852c393a42Smrg	break;
8862c393a42Smrg    case FcTypeInteger:
8872c393a42Smrg	*i = v.u.i;
8882c393a42Smrg	break;
8892c393a42Smrg    default:
8902c393a42Smrg        return FcResultTypeMismatch;
8912c393a42Smrg    }
8922c393a42Smrg    return FcResultMatch;
8932c393a42Smrg}
8942c393a42Smrg
8952c393a42SmrgFcResult
8962c393a42SmrgFcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
8972c393a42Smrg{
8982c393a42Smrg    return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
8992c393a42Smrg}
900ca08ab68Smrg
901ca08ab68Smrg
9022c393a42SmrgFcResult
9032c393a42SmrgFcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
9042c393a42Smrg{
9052c393a42Smrg    FcValue	v;
9062c393a42Smrg    FcResult	r;
9072c393a42Smrg
9082c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
9092c393a42Smrg    if (r != FcResultMatch)
9102c393a42Smrg	return r;
911c9710b42Smrg    switch ((int) v.type) {
9122c393a42Smrg    case FcTypeDouble:
9132c393a42Smrg	*d = v.u.d;
9142c393a42Smrg	break;
9152c393a42Smrg    case FcTypeInteger:
9162c393a42Smrg	*d = (double) v.u.i;
9172c393a42Smrg	break;
9182c393a42Smrg    default:
9192c393a42Smrg        return FcResultTypeMismatch;
9202c393a42Smrg    }
9212c393a42Smrg    return FcResultMatch;
9222c393a42Smrg}
9232c393a42Smrg
9242c393a42SmrgFcResult
9252c393a42SmrgFcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
9262c393a42Smrg{
9272c393a42Smrg    return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
9282c393a42Smrg}
9292c393a42Smrg
9302c393a42SmrgFcResult
9312c393a42SmrgFcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
9322c393a42Smrg{
9332c393a42Smrg    FcValue	v;
9342c393a42Smrg    FcResult	r;
9352c393a42Smrg
9362c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
9372c393a42Smrg    if (r != FcResultMatch)
9382c393a42Smrg	return r;
9392c393a42Smrg    if (v.type != FcTypeString)
9402c393a42Smrg        return FcResultTypeMismatch;
9412c393a42Smrg
9422c393a42Smrg    *s = (FcChar8 *) v.u.s;
9432c393a42Smrg    return FcResultMatch;
9442c393a42Smrg}
9452c393a42Smrg
9462c393a42SmrgFcResult
9472c393a42SmrgFcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
9482c393a42Smrg{
9492c393a42Smrg    return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
9502c393a42Smrg}
951ca08ab68Smrg
9522c393a42SmrgFcResult
9532c393a42SmrgFcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
9542c393a42Smrg{
9552c393a42Smrg    FcValue	v;
9562c393a42Smrg    FcResult	r;
9572c393a42Smrg
9582c393a42Smrg    r = FcPatternGet (p, object, id, &v);
9592c393a42Smrg    if (r != FcResultMatch)
9602c393a42Smrg	return r;
9612c393a42Smrg    if (v.type != FcTypeMatrix)
9622c393a42Smrg        return FcResultTypeMismatch;
9632c393a42Smrg    *m = (FcMatrix *)v.u.m;
9642c393a42Smrg    return FcResultMatch;
9652c393a42Smrg}
9662c393a42Smrg
9672c393a42Smrg
9682c393a42SmrgFcResult
9692c393a42SmrgFcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
9702c393a42Smrg{
9712c393a42Smrg    FcValue	v;
9722c393a42Smrg    FcResult	r;
9732c393a42Smrg
9742c393a42Smrg    r = FcPatternGet (p, object, id, &v);
9752c393a42Smrg    if (r != FcResultMatch)
9762c393a42Smrg	return r;
9772c393a42Smrg    if (v.type != FcTypeBool)
9782c393a42Smrg        return FcResultTypeMismatch;
9792c393a42Smrg    *b = v.u.b;
9802c393a42Smrg    return FcResultMatch;
9812c393a42Smrg}
9822c393a42Smrg
9832c393a42SmrgFcResult
9842c393a42SmrgFcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
9852c393a42Smrg{
9862c393a42Smrg    FcValue	v;
9872c393a42Smrg    FcResult	r;
9882c393a42Smrg
9892c393a42Smrg    r = FcPatternGet (p, object, id, &v);
9902c393a42Smrg    if (r != FcResultMatch)
9912c393a42Smrg	return r;
9922c393a42Smrg    if (v.type != FcTypeCharSet)
9932c393a42Smrg        return FcResultTypeMismatch;
9942c393a42Smrg    *c = (FcCharSet *)v.u.c;
9952c393a42Smrg    return FcResultMatch;
9962c393a42Smrg}
9972c393a42Smrg
9982c393a42SmrgFcResult
9992c393a42SmrgFcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
10002c393a42Smrg{
10012c393a42Smrg    FcValue	v;
10022c393a42Smrg    FcResult	r;
10032c393a42Smrg
10042c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10052c393a42Smrg    if (r != FcResultMatch)
10062c393a42Smrg	return r;
10072c393a42Smrg    if (v.type != FcTypeFTFace)
10082c393a42Smrg	return FcResultTypeMismatch;
10092c393a42Smrg    *f = (FT_Face) v.u.f;
10102c393a42Smrg    return FcResultMatch;
10112c393a42Smrg}
10122c393a42Smrg
10132c393a42SmrgFcResult
10142c393a42SmrgFcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
10152c393a42Smrg{
10162c393a42Smrg    FcValue	v;
10172c393a42Smrg    FcResult	r;
10182c393a42Smrg
10192c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10202c393a42Smrg    if (r != FcResultMatch)
10212c393a42Smrg	return r;
10222c393a42Smrg    if (v.type != FcTypeLangSet)
10232c393a42Smrg        return FcResultTypeMismatch;
10242c393a42Smrg    *ls = (FcLangSet *)v.u.l;
10252c393a42Smrg    return FcResultMatch;
10262c393a42Smrg}
10272c393a42Smrg
10282c393a42SmrgFcPattern *
10292c393a42SmrgFcPatternDuplicate (const FcPattern *orig)
10302c393a42Smrg{
10312c393a42Smrg    FcPattern	    *new;
10322c393a42Smrg    FcPatternElt    *e;
10332c393a42Smrg    int		    i;
10342c393a42Smrg    FcValueListPtr  l;
10352c393a42Smrg
10362c393a42Smrg    new = FcPatternCreate ();
10372c393a42Smrg    if (!new)
10382c393a42Smrg	goto bail0;
10392c393a42Smrg
10402c393a42Smrg    e = FcPatternElts(orig);
10412c393a42Smrg
10422c393a42Smrg    for (i = 0; i < orig->num; i++)
10432c393a42Smrg    {
10442c393a42Smrg	for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l))
10452c393a42Smrg	{
10462c393a42Smrg	    if (!FcPatternObjectAddWithBinding (new, e[i].object,
10472c393a42Smrg						FcValueCanonicalize(&l->value),
10482c393a42Smrg						l->binding,
10492c393a42Smrg						FcTrue))
10502c393a42Smrg		goto bail1;
1051ca08ab68Smrg
10522c393a42Smrg	}
10532c393a42Smrg    }
10542c393a42Smrg
10552c393a42Smrg    return new;
10562c393a42Smrg
10572c393a42Smrgbail1:
10582c393a42Smrg    FcPatternDestroy (new);
10592c393a42Smrgbail0:
10602c393a42Smrg    return 0;
10612c393a42Smrg}
10622c393a42Smrg
10632c393a42Smrgvoid
10642c393a42SmrgFcPatternReference (FcPattern *p)
10652c393a42Smrg{
1066c9710b42Smrg    if (!FcRefIsConst (&p->ref))
1067c9710b42Smrg	FcRefInc (&p->ref);
10682c393a42Smrg    else
10692c393a42Smrg	FcCacheObjectReference (p);
10702c393a42Smrg}
10712c393a42Smrg
10722c393a42SmrgFcPattern *
1073a6844aabSmrgFcPatternVaBuild (FcPattern *p, va_list va)
10742c393a42Smrg{
10752c393a42Smrg    FcPattern	*ret;
1076ca08ab68Smrg
1077a6844aabSmrg    FcPatternVapBuild (ret, p, va);
10782c393a42Smrg    return ret;
10792c393a42Smrg}
10802c393a42Smrg
10812c393a42SmrgFcPattern *
1082a6844aabSmrgFcPatternBuild (FcPattern *p, ...)
10832c393a42Smrg{
10842c393a42Smrg    va_list	va;
1085ca08ab68Smrg
1086a6844aabSmrg    va_start (va, p);
1087a6844aabSmrg    FcPatternVapBuild (p, p, va);
10882c393a42Smrg    va_end (va);
1089a6844aabSmrg    return p;
10902c393a42Smrg}
10912c393a42Smrg
10922c393a42Smrg/*
10932c393a42Smrg * Add all of the elements in 's' to 'p'
10942c393a42Smrg */
10952c393a42SmrgFcBool
10962c393a42SmrgFcPatternAppend (FcPattern *p, FcPattern *s)
10972c393a42Smrg{
10982c393a42Smrg    int		    i;
10992c393a42Smrg    FcPatternElt    *e;
11002c393a42Smrg    FcValueListPtr  v;
1101ca08ab68Smrg
11022c393a42Smrg    for (i = 0; i < s->num; i++)
11032c393a42Smrg    {
11042c393a42Smrg	e = FcPatternElts(s)+i;
11052c393a42Smrg	for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
11062c393a42Smrg	{
11072c393a42Smrg	    if (!FcPatternObjectAddWithBinding (p, e->object,
1108ca08ab68Smrg						FcValueCanonicalize(&v->value),
11092c393a42Smrg						v->binding, FcTrue))
11102c393a42Smrg		return FcFalse;
11112c393a42Smrg	}
11122c393a42Smrg    }
11132c393a42Smrg    return FcTrue;
11142c393a42Smrg}
11152c393a42Smrg
1116a6844aabSmrgFcPattern *
1117a6844aabSmrgFcPatternFilter (FcPattern *p, const FcObjectSet *os)
1118a6844aabSmrg{
1119a6844aabSmrg    int		    i;
1120a6844aabSmrg    FcPattern	    *ret;
1121a6844aabSmrg    FcPatternElt    *e;
1122a6844aabSmrg    FcValueListPtr  v;
1123a6844aabSmrg
1124a6844aabSmrg    if (!os)
1125a6844aabSmrg	return FcPatternDuplicate (p);
1126a6844aabSmrg
1127a6844aabSmrg    ret = FcPatternCreate ();
1128a6844aabSmrg    if (!ret)
1129a6844aabSmrg	return NULL;
1130a6844aabSmrg
1131a6844aabSmrg    for (i = 0; i < os->nobject; i++)
1132a6844aabSmrg    {
1133a6844aabSmrg	FcObject object = FcObjectFromName (os->objects[i]);
1134a6844aabSmrg	e = FcPatternObjectFindElt (p, object);
1135a6844aabSmrg	if (e)
1136a6844aabSmrg	{
1137a6844aabSmrg	    for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1138a6844aabSmrg	    {
1139a6844aabSmrg		if (!FcPatternObjectAddWithBinding (ret, e->object,
1140a6844aabSmrg						    FcValueCanonicalize(&v->value),
1141a6844aabSmrg						    v->binding, FcTrue))
1142a6844aabSmrg		    goto bail0;
1143a6844aabSmrg	    }
1144a6844aabSmrg	}
1145a6844aabSmrg    }
1146a6844aabSmrg    return ret;
1147a6844aabSmrg
1148a6844aabSmrgbail0:
1149a6844aabSmrg    FcPatternDestroy (ret);
1150a6844aabSmrg    return NULL;
1151a6844aabSmrg}
1152a6844aabSmrg
11532c393a42Smrg
11542c393a42SmrgFcBool
11552c393a42SmrgFcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
11562c393a42Smrg{
11572c393a42Smrg    int	i;
11582c393a42Smrg    FcPatternElt    *elts = FcPatternElts(pat);
1159ca08ab68Smrg
11602c393a42Smrg    if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
11612c393a42Smrg	return FcFalse;
11622c393a42Smrg    if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt)))
11632c393a42Smrg	return FcFalse;
11642c393a42Smrg    for (i = 0; i < pat->num; i++)
11652c393a42Smrg	if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
11662c393a42Smrg	    return FcFalse;
11672c393a42Smrg    return FcTrue;
11682c393a42Smrg}
11692c393a42Smrg
11702c393a42SmrgFcPattern *
11712c393a42SmrgFcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
11722c393a42Smrg{
11732c393a42Smrg    FcPattern	    *pat_serialized;
11742c393a42Smrg    FcPatternElt    *elts = FcPatternElts (pat);
11752c393a42Smrg    FcPatternElt    *elts_serialized;
11762c393a42Smrg    FcValueList	    *values_serialized;
11772c393a42Smrg    int		    i;
11782c393a42Smrg
11792c393a42Smrg    pat_serialized = FcSerializePtr (serialize, pat);
11802c393a42Smrg    if (!pat_serialized)
11812c393a42Smrg	return NULL;
11822c393a42Smrg    *pat_serialized = *pat;
11832c393a42Smrg    pat_serialized->size = pat->num;
1184c9710b42Smrg    FcRefSetConst (&pat_serialized->ref);
1185ca08ab68Smrg
11862c393a42Smrg    elts_serialized = FcSerializePtr (serialize, elts);
11872c393a42Smrg    if (!elts_serialized)
11882c393a42Smrg	return NULL;
1189ca08ab68Smrg
11902c393a42Smrg    pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
11912c393a42Smrg						 elts_serialized);
11922c393a42Smrg
11932c393a42Smrg    for (i = 0; i < pat->num; i++)
11942c393a42Smrg    {
11952c393a42Smrg	values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
11962c393a42Smrg	if (!values_serialized)
11972c393a42Smrg	    return NULL;
11982c393a42Smrg	elts_serialized[i].object = elts[i].object;
1199ca08ab68Smrg	elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
12002c393a42Smrg							  values_serialized,
12012c393a42Smrg							  FcValueList);
12022c393a42Smrg    }
12032c393a42Smrg    if (FcDebug() & FC_DBG_CACHEV) {
12042c393a42Smrg	printf ("Raw pattern:\n");
12052c393a42Smrg	FcPatternPrint (pat);
12062c393a42Smrg	printf ("Serialized pattern:\n");
12072c393a42Smrg	FcPatternPrint (pat_serialized);
12082c393a42Smrg	printf ("\n");
12092c393a42Smrg    }
12102c393a42Smrg    return pat_serialized;
12112c393a42Smrg}
12122c393a42Smrg
12132c393a42SmrgFcBool
12142c393a42SmrgFcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
12152c393a42Smrg{
12162c393a42Smrg    while (vl)
12172c393a42Smrg    {
12182c393a42Smrg	if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
12192c393a42Smrg	    return FcFalse;
1220c9710b42Smrg	switch ((int) vl->value.type) {
12212c393a42Smrg	case FcTypeString:
12222c393a42Smrg	    if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
12232c393a42Smrg		return FcFalse;
12242c393a42Smrg	    break;
12252c393a42Smrg	case FcTypeCharSet:
12262c393a42Smrg	    if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
12272c393a42Smrg		return FcFalse;
12282c393a42Smrg	    break;
12292c393a42Smrg	case FcTypeLangSet:
12302c393a42Smrg	    if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
12312c393a42Smrg		return FcFalse;
12322c393a42Smrg	    break;
12332c393a42Smrg	default:
12342c393a42Smrg	    break;
12352c393a42Smrg	}
12362c393a42Smrg	vl = vl->next;
12372c393a42Smrg    }
12382c393a42Smrg    return FcTrue;
12392c393a42Smrg}
12402c393a42Smrg
12412c393a42SmrgFcValueList *
12422c393a42SmrgFcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
12432c393a42Smrg{
12442c393a42Smrg    FcValueList	*vl_serialized;
12452c393a42Smrg    FcChar8	*s_serialized;
12462c393a42Smrg    FcCharSet	*c_serialized;
12472c393a42Smrg    FcLangSet	*l_serialized;
12482c393a42Smrg    FcValueList	*head_serialized = NULL;
12492c393a42Smrg    FcValueList	*prev_serialized = NULL;
12502c393a42Smrg
12512c393a42Smrg    while (vl)
12522c393a42Smrg    {
12532c393a42Smrg	vl_serialized = FcSerializePtr (serialize, vl);
12542c393a42Smrg	if (!vl_serialized)
12552c393a42Smrg	    return NULL;
1256ca08ab68Smrg
12572c393a42Smrg	if (prev_serialized)
12582c393a42Smrg	    prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
12592c393a42Smrg							  vl_serialized,
12602c393a42Smrg							  FcValueList);
12612c393a42Smrg	else
12622c393a42Smrg	    head_serialized = vl_serialized;
12632c393a42Smrg
12642c393a42Smrg	vl_serialized->next = NULL;
12652c393a42Smrg	vl_serialized->value.type = vl->value.type;
1266c9710b42Smrg	switch ((int) vl->value.type) {
12672c393a42Smrg	case FcTypeInteger:
12682c393a42Smrg	    vl_serialized->value.u.i = vl->value.u.i;
12692c393a42Smrg	    break;
12702c393a42Smrg	case FcTypeDouble:
12712c393a42Smrg	    vl_serialized->value.u.d = vl->value.u.d;
12722c393a42Smrg	    break;
12732c393a42Smrg	case FcTypeString:
12742c393a42Smrg	    s_serialized = FcStrSerialize (serialize, vl->value.u.s);
12752c393a42Smrg	    if (!s_serialized)
12762c393a42Smrg		return NULL;
12772c393a42Smrg	    vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
12782c393a42Smrg							     s_serialized,
12792c393a42Smrg							     FcChar8);
12802c393a42Smrg	    break;
12812c393a42Smrg	case FcTypeBool:
12822c393a42Smrg	    vl_serialized->value.u.b = vl->value.u.b;
12832c393a42Smrg	    break;
12842c393a42Smrg	case FcTypeMatrix:
12852c393a42Smrg	    /* can't happen */
12862c393a42Smrg	    break;
12872c393a42Smrg	case FcTypeCharSet:
12882c393a42Smrg	    c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
12892c393a42Smrg	    if (!c_serialized)
12902c393a42Smrg		return NULL;
12912c393a42Smrg	    vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
12922c393a42Smrg							     c_serialized,
12932c393a42Smrg							     FcCharSet);
12942c393a42Smrg	    break;
12952c393a42Smrg	case FcTypeFTFace:
12962c393a42Smrg	    /* can't happen */
12972c393a42Smrg	    break;
12982c393a42Smrg	case FcTypeLangSet:
12992c393a42Smrg	    l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
13002c393a42Smrg	    if (!l_serialized)
13012c393a42Smrg		return NULL;
13022c393a42Smrg	    vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
13032c393a42Smrg							     l_serialized,
13042c393a42Smrg							     FcLangSet);
13052c393a42Smrg	    break;
13062c393a42Smrg	default:
13072c393a42Smrg	    break;
13082c393a42Smrg	}
13092c393a42Smrg	prev_serialized = vl_serialized;
13102c393a42Smrg	vl = vl->next;
13112c393a42Smrg    }
13122c393a42Smrg    return head_serialized;
13132c393a42Smrg}
1314b09479dcSmrg
13152c393a42Smrg#define __fcpat__
13162c393a42Smrg#include "fcaliastail.h"
13172c393a42Smrg#include "fcftaliastail.h"
13182c393a42Smrg#undef __fcpat__
1319