fcpat.c revision 953daeba
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;
60953daebaSmrg    case FcTypeRange:
61953daebaSmrg	FcRangeDestroy ((FcRange *) v.u.r);
62953daebaSmrg	break;
632c393a42Smrg    default:
642c393a42Smrg	break;
652c393a42Smrg    }
662c393a42Smrg}
672c393a42Smrg
682c393a42SmrgFcValue
692c393a42SmrgFcValueCanonicalize (const FcValue *v)
702c393a42Smrg{
712c393a42Smrg    FcValue new;
722c393a42Smrg
73c9710b42Smrg    switch ((int) v->type)
742c393a42Smrg    {
752c393a42Smrg    case FcTypeString:
76a6844aabSmrg	new.u.s = FcValueString(v);
772c393a42Smrg	new.type = FcTypeString;
782c393a42Smrg	break;
792c393a42Smrg    case FcTypeCharSet:
80a6844aabSmrg	new.u.c = FcValueCharSet(v);
812c393a42Smrg	new.type = FcTypeCharSet;
822c393a42Smrg	break;
832c393a42Smrg    case FcTypeLangSet:
84a6844aabSmrg	new.u.l = FcValueLangSet(v);
852c393a42Smrg	new.type = FcTypeLangSet;
862c393a42Smrg	break;
87953daebaSmrg    case FcTypeRange:
88953daebaSmrg	new.u.r = FcValueRange(v);
89953daebaSmrg	new.type = FcTypeRange;
90953daebaSmrg	break;
912c393a42Smrg    default:
922c393a42Smrg	new = *v;
932c393a42Smrg	break;
942c393a42Smrg    }
952c393a42Smrg    return new;
962c393a42Smrg}
972c393a42Smrg
982c393a42SmrgFcValue
992c393a42SmrgFcValueSave (FcValue v)
1002c393a42Smrg{
101c9710b42Smrg    switch ((int) v.type) {
1022c393a42Smrg    case FcTypeString:
103c9710b42Smrg	v.u.s = FcStrdup (v.u.s);
1042c393a42Smrg	if (!v.u.s)
1052c393a42Smrg	    v.type = FcTypeVoid;
1062c393a42Smrg	break;
1072c393a42Smrg    case FcTypeMatrix:
1082c393a42Smrg	v.u.m = FcMatrixCopy (v.u.m);
1092c393a42Smrg	if (!v.u.m)
1102c393a42Smrg	    v.type = FcTypeVoid;
1112c393a42Smrg	break;
1122c393a42Smrg    case FcTypeCharSet:
1132c393a42Smrg	v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
1142c393a42Smrg	if (!v.u.c)
1152c393a42Smrg	    v.type = FcTypeVoid;
1162c393a42Smrg	break;
1172c393a42Smrg    case FcTypeLangSet:
1182c393a42Smrg	v.u.l = FcLangSetCopy (v.u.l);
1192c393a42Smrg	if (!v.u.l)
1202c393a42Smrg	    v.type = FcTypeVoid;
1212c393a42Smrg	break;
122953daebaSmrg    case FcTypeRange:
123953daebaSmrg	v.u.r = FcRangeCopy (v.u.r);
124953daebaSmrg	if (!v.u.r)
125953daebaSmrg	    v.type = FcTypeVoid;
126953daebaSmrg	break;
1272c393a42Smrg    default:
1282c393a42Smrg	break;
1292c393a42Smrg    }
1302c393a42Smrg    return v;
1312c393a42Smrg}
1322c393a42Smrg
133ca08ab68SmrgFcValueListPtr
134ca08ab68SmrgFcValueListCreate (void)
135ca08ab68Smrg{
136c9710b42Smrg    return calloc (1, sizeof (FcValueList));
137ca08ab68Smrg}
138ca08ab68Smrg
1392c393a42Smrgvoid
1402c393a42SmrgFcValueListDestroy (FcValueListPtr l)
1412c393a42Smrg{
1422c393a42Smrg    FcValueListPtr next;
1432c393a42Smrg    for (; l; l = next)
1442c393a42Smrg    {
145c9710b42Smrg	switch ((int) l->value.type) {
1462c393a42Smrg	case FcTypeString:
147c9710b42Smrg	    FcFree (l->value.u.s);
1482c393a42Smrg	    break;
1492c393a42Smrg	case FcTypeMatrix:
1502c393a42Smrg	    FcMatrixFree ((FcMatrix *)l->value.u.m);
1512c393a42Smrg	    break;
1522c393a42Smrg	case FcTypeCharSet:
153ca08ab68Smrg	    FcCharSetDestroy
1542c393a42Smrg		((FcCharSet *) (l->value.u.c));
1552c393a42Smrg	    break;
1562c393a42Smrg	case FcTypeLangSet:
157ca08ab68Smrg	    FcLangSetDestroy
1582c393a42Smrg		((FcLangSet *) (l->value.u.l));
1592c393a42Smrg	    break;
160953daebaSmrg	case FcTypeRange:
161953daebaSmrg	    FcRangeDestroy ((FcRange *) (l->value.u.r));
162953daebaSmrg	    break;
1632c393a42Smrg	default:
1642c393a42Smrg	    break;
1652c393a42Smrg	}
1662c393a42Smrg	next = FcValueListNext(l);
1672c393a42Smrg	free(l);
1682c393a42Smrg    }
1692c393a42Smrg}
1702c393a42Smrg
171ca08ab68SmrgFcValueListPtr
172ca08ab68SmrgFcValueListPrepend (FcValueListPtr vallist,
173ca08ab68Smrg		    FcValue        value,
174ca08ab68Smrg		    FcValueBinding binding)
175ca08ab68Smrg{
176ca08ab68Smrg    FcValueListPtr new;
177ca08ab68Smrg
178ca08ab68Smrg    if (value.type == FcTypeVoid)
179ca08ab68Smrg	return vallist;
180ca08ab68Smrg    new = FcValueListCreate ();
181ca08ab68Smrg    if (!new)
182ca08ab68Smrg	return vallist;
183ca08ab68Smrg
184ca08ab68Smrg    new->value = FcValueSave (value);
185ca08ab68Smrg    new->binding = binding;
186ca08ab68Smrg    new->next = vallist;
187ca08ab68Smrg
188ca08ab68Smrg    return new;
189ca08ab68Smrg}
190ca08ab68Smrg
191ca08ab68SmrgFcValueListPtr
192ca08ab68SmrgFcValueListAppend (FcValueListPtr vallist,
193ca08ab68Smrg		   FcValue        value,
194ca08ab68Smrg		   FcValueBinding binding)
195ca08ab68Smrg{
196ca08ab68Smrg    FcValueListPtr new, last;
197ca08ab68Smrg
198ca08ab68Smrg    if (value.type == FcTypeVoid)
199ca08ab68Smrg	return vallist;
200ca08ab68Smrg    new = FcValueListCreate ();
201ca08ab68Smrg    if (!new)
202ca08ab68Smrg	return vallist;
203ca08ab68Smrg
204ca08ab68Smrg    new->value = FcValueSave (value);
205ca08ab68Smrg    new->binding = binding;
206ca08ab68Smrg    new->next = NULL;
207ca08ab68Smrg
208ca08ab68Smrg    if (vallist)
209ca08ab68Smrg    {
210ca08ab68Smrg	for (last = vallist; FcValueListNext (last); last = FcValueListNext (last));
211ca08ab68Smrg
212ca08ab68Smrg	last->next = new;
213ca08ab68Smrg    }
214ca08ab68Smrg    else
215ca08ab68Smrg	vallist = new;
216ca08ab68Smrg
217ca08ab68Smrg    return vallist;
218ca08ab68Smrg}
219ca08ab68Smrg
220ca08ab68SmrgFcValueListPtr
221ca08ab68SmrgFcValueListDuplicate(FcValueListPtr orig)
222ca08ab68Smrg{
223ca08ab68Smrg    FcValueListPtr new = NULL, l, t = NULL;
224ca08ab68Smrg    FcValue v;
225ca08ab68Smrg
226ca08ab68Smrg    for (l = orig; l != NULL; l = FcValueListNext (l))
227ca08ab68Smrg    {
228ca08ab68Smrg	if (!new)
229ca08ab68Smrg	{
230ca08ab68Smrg	    t = new = FcValueListCreate();
231ca08ab68Smrg	}
232ca08ab68Smrg	else
233ca08ab68Smrg	{
234ca08ab68Smrg	    t->next = FcValueListCreate();
235ca08ab68Smrg	    t = FcValueListNext (t);
236ca08ab68Smrg	}
237ca08ab68Smrg	v = FcValueCanonicalize (&l->value);
238ca08ab68Smrg	t->value = FcValueSave (v);
239ca08ab68Smrg	t->binding = l->binding;
240ca08ab68Smrg	t->next = NULL;
241ca08ab68Smrg    }
242ca08ab68Smrg
243ca08ab68Smrg    return new;
244ca08ab68Smrg}
245ca08ab68Smrg
2462c393a42SmrgFcBool
2472c393a42SmrgFcValueEqual (FcValue va, FcValue vb)
2482c393a42Smrg{
2492c393a42Smrg    if (va.type != vb.type)
2502c393a42Smrg    {
2512c393a42Smrg	if (va.type == FcTypeInteger)
2522c393a42Smrg	{
2532c393a42Smrg	    va.type = FcTypeDouble;
2542c393a42Smrg	    va.u.d = va.u.i;
2552c393a42Smrg	}
2562c393a42Smrg	if (vb.type == FcTypeInteger)
2572c393a42Smrg	{
2582c393a42Smrg	    vb.type = FcTypeDouble;
2592c393a42Smrg	    vb.u.d = vb.u.i;
2602c393a42Smrg	}
2612c393a42Smrg	if (va.type != vb.type)
2622c393a42Smrg	    return FcFalse;
2632c393a42Smrg    }
2642c393a42Smrg    switch (va.type) {
2656fc018e4Smrg    case FcTypeUnknown:
2666fc018e4Smrg	return FcFalse;	/* don't know how to compare this object */
2672c393a42Smrg    case FcTypeVoid:
2682c393a42Smrg	return FcTrue;
2692c393a42Smrg    case FcTypeInteger:
2702c393a42Smrg	return va.u.i == vb.u.i;
2712c393a42Smrg    case FcTypeDouble:
2722c393a42Smrg	return va.u.d == vb.u.d;
2732c393a42Smrg    case FcTypeString:
2742c393a42Smrg	return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
2752c393a42Smrg    case FcTypeBool:
2762c393a42Smrg	return va.u.b == vb.u.b;
2772c393a42Smrg    case FcTypeMatrix:
2782c393a42Smrg	return FcMatrixEqual (va.u.m, vb.u.m);
2792c393a42Smrg    case FcTypeCharSet:
2802c393a42Smrg	return FcCharSetEqual (va.u.c, vb.u.c);
2812c393a42Smrg    case FcTypeFTFace:
2822c393a42Smrg	return va.u.f == vb.u.f;
2832c393a42Smrg    case FcTypeLangSet:
2842c393a42Smrg	return FcLangSetEqual (va.u.l, vb.u.l);
285953daebaSmrg    case FcTypeRange:
286953daebaSmrg	return FcRangeIsInRange (va.u.r, vb.u.r);
2872c393a42Smrg    }
2882c393a42Smrg    return FcFalse;
2892c393a42Smrg}
2902c393a42Smrg
2912c393a42Smrgstatic FcChar32
2922c393a42SmrgFcDoubleHash (double d)
2932c393a42Smrg{
2942c393a42Smrg    if (d < 0)
2952c393a42Smrg	d = -d;
2962c393a42Smrg    if (d > 0xffffffff)
2972c393a42Smrg	d = 0xffffffff;
2982c393a42Smrg    return (FcChar32) d;
2992c393a42Smrg}
3002c393a42Smrg
3012c393a42SmrgFcChar32
3022c393a42SmrgFcStringHash (const FcChar8 *s)
3032c393a42Smrg{
3042c393a42Smrg    FcChar8	c;
3052c393a42Smrg    FcChar32	h = 0;
306ca08ab68Smrg
3072c393a42Smrg    if (s)
3082c393a42Smrg	while ((c = *s++))
3092c393a42Smrg	    h = ((h << 1) | (h >> 31)) ^ c;
3102c393a42Smrg    return h;
3112c393a42Smrg}
3122c393a42Smrg
3132c393a42Smrgstatic FcChar32
3142c393a42SmrgFcValueHash (const FcValue *v)
3152c393a42Smrg{
316a6844aabSmrg    switch (v->type) {
3176fc018e4Smrg    case FcTypeUnknown:
3182c393a42Smrg    case FcTypeVoid:
3192c393a42Smrg	return 0;
3202c393a42Smrg    case FcTypeInteger:
3212c393a42Smrg	return (FcChar32) v->u.i;
3222c393a42Smrg    case FcTypeDouble:
3232c393a42Smrg	return FcDoubleHash (v->u.d);
3242c393a42Smrg    case FcTypeString:
325a6844aabSmrg	return FcStringHash (FcValueString(v));
3262c393a42Smrg    case FcTypeBool:
3272c393a42Smrg	return (FcChar32) v->u.b;
3282c393a42Smrg    case FcTypeMatrix:
329ca08ab68Smrg	return (FcDoubleHash (v->u.m->xx) ^
330ca08ab68Smrg		FcDoubleHash (v->u.m->xy) ^
331ca08ab68Smrg		FcDoubleHash (v->u.m->yx) ^
3322c393a42Smrg		FcDoubleHash (v->u.m->yy));
3332c393a42Smrg    case FcTypeCharSet:
334a6844aabSmrg	return (FcChar32) FcValueCharSet(v)->num;
3352c393a42Smrg    case FcTypeFTFace:
3362c393a42Smrg	return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
3372c393a42Smrg	       FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
3382c393a42Smrg    case FcTypeLangSet:
339a6844aabSmrg	return FcLangSetHash (FcValueLangSet(v));
340953daebaSmrg    case FcTypeRange:
341953daebaSmrg	return FcRangeHash (v->u.r);
3422c393a42Smrg    }
3436fc018e4Smrg    return 0;
3442c393a42Smrg}
3452c393a42Smrg
3462c393a42Smrgstatic FcBool
3472c393a42SmrgFcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
3482c393a42Smrg{
3492c393a42Smrg    if (la == lb)
3502c393a42Smrg	return FcTrue;
3512c393a42Smrg
3522c393a42Smrg    while (la && lb)
3532c393a42Smrg    {
3542c393a42Smrg	if (!FcValueEqual (la->value, lb->value))
3552c393a42Smrg	    return FcFalse;
3562c393a42Smrg	la = FcValueListNext(la);
3572c393a42Smrg	lb = FcValueListNext(lb);
3582c393a42Smrg    }
3592c393a42Smrg    if (la || lb)
3602c393a42Smrg	return FcFalse;
3612c393a42Smrg    return FcTrue;
3622c393a42Smrg}
3632c393a42Smrg
3642c393a42Smrgstatic FcChar32
3652c393a42SmrgFcValueListHash (FcValueListPtr l)
3662c393a42Smrg{
3672c393a42Smrg    FcChar32	hash = 0;
368ca08ab68Smrg
3692c393a42Smrg    for (; l; l = FcValueListNext(l))
3702c393a42Smrg    {
3712c393a42Smrg	hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
3722c393a42Smrg    }
3732c393a42Smrg    return hash;
3742c393a42Smrg}
3752c393a42Smrg
3762c393a42Smrgvoid
3772c393a42SmrgFcPatternDestroy (FcPattern *p)
3782c393a42Smrg{
3792c393a42Smrg    int		    i;
3802c393a42Smrg    FcPatternElt    *elts;
381ca08ab68Smrg
382c9710b42Smrg    if (!p)
383c9710b42Smrg	return;
384c9710b42Smrg
385c9710b42Smrg    if (FcRefIsConst (&p->ref))
3862c393a42Smrg    {
3872c393a42Smrg	FcCacheObjectDereference (p);
3882c393a42Smrg	return;
3892c393a42Smrg    }
3902c393a42Smrg
391c9710b42Smrg    if (FcRefDec (&p->ref) != 1)
3922c393a42Smrg	return;
3932c393a42Smrg
3942c393a42Smrg    elts = FcPatternElts (p);
3952c393a42Smrg    for (i = 0; i < p->num; i++)
3962c393a42Smrg	FcValueListDestroy (FcPatternEltValues(&elts[i]));
3972c393a42Smrg
3982c393a42Smrg    free (elts);
3992c393a42Smrg    free (p);
4002c393a42Smrg}
4012c393a42Smrg
4022c393a42Smrgstatic int
4032c393a42SmrgFcPatternObjectPosition (const FcPattern *p, FcObject object)
4042c393a42Smrg{
4052c393a42Smrg    int	    low, high, mid, c;
4062c393a42Smrg    FcPatternElt    *elts = FcPatternElts(p);
4072c393a42Smrg
4082c393a42Smrg    low = 0;
4092c393a42Smrg    high = p->num - 1;
4102c393a42Smrg    c = 1;
4112c393a42Smrg    mid = 0;
4122c393a42Smrg    while (low <= high)
4132c393a42Smrg    {
4142c393a42Smrg	mid = (low + high) >> 1;
4152c393a42Smrg	c = elts[mid].object - object;
4162c393a42Smrg	if (c == 0)
4172c393a42Smrg	    return mid;
4182c393a42Smrg	if (c < 0)
4192c393a42Smrg	    low = mid + 1;
4202c393a42Smrg	else
4212c393a42Smrg	    high = mid - 1;
4222c393a42Smrg    }
4232c393a42Smrg    if (c < 0)
4242c393a42Smrg	mid++;
4252c393a42Smrg    return -(mid + 1);
4262c393a42Smrg}
4272c393a42Smrg
428953daebaSmrgint
429953daebaSmrgFcPatternPosition (const FcPattern *p, const char *object)
430953daebaSmrg{
431953daebaSmrg    return FcPatternObjectPosition (p, FcObjectFromName (object));
432953daebaSmrg}
433953daebaSmrg
4342c393a42SmrgFcPatternElt *
4352c393a42SmrgFcPatternObjectFindElt (const FcPattern *p, FcObject object)
4362c393a42Smrg{
4372c393a42Smrg    int	    i = FcPatternObjectPosition (p, object);
4382c393a42Smrg    if (i < 0)
4392c393a42Smrg	return 0;
4402c393a42Smrg    return &FcPatternElts(p)[i];
4412c393a42Smrg}
4422c393a42Smrg
4432c393a42SmrgFcPatternElt *
4442c393a42SmrgFcPatternObjectInsertElt (FcPattern *p, FcObject object)
4452c393a42Smrg{
4462c393a42Smrg    int		    i;
4472c393a42Smrg    FcPatternElt   *e;
448ca08ab68Smrg
4492c393a42Smrg    i = FcPatternObjectPosition (p, object);
4502c393a42Smrg    if (i < 0)
4512c393a42Smrg    {
4522c393a42Smrg	i = -i - 1;
453ca08ab68Smrg
4542c393a42Smrg	/* reallocate array */
4552c393a42Smrg	if (p->num + 1 >= p->size)
4562c393a42Smrg	{
4572c393a42Smrg	    int s = p->size + 16;
4582c393a42Smrg	    if (p->size)
4592c393a42Smrg	    {
4602c393a42Smrg		FcPatternElt *e0 = FcPatternElts(p);
4612c393a42Smrg		e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
4622c393a42Smrg		if (!e) /* maybe it was mmapped */
4632c393a42Smrg		{
4642c393a42Smrg		    e = malloc(s * sizeof (FcPatternElt));
4652c393a42Smrg		    if (e)
4662c393a42Smrg			memcpy(e, e0, p->num * sizeof (FcPatternElt));
4672c393a42Smrg		}
4682c393a42Smrg	    }
4692c393a42Smrg	    else
4702c393a42Smrg		e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
4712c393a42Smrg	    if (!e)
4722c393a42Smrg		return FcFalse;
4732c393a42Smrg	    p->elts_offset = FcPtrToOffset (p, e);
4742c393a42Smrg	    while (p->size < s)
4752c393a42Smrg	    {
4762c393a42Smrg		e[p->size].object = 0;
4772c393a42Smrg		e[p->size].values = NULL;
4782c393a42Smrg		p->size++;
4792c393a42Smrg	    }
4802c393a42Smrg	}
4812c393a42Smrg
4822c393a42Smrg	e = FcPatternElts(p);
4832c393a42Smrg	/* move elts up */
4842c393a42Smrg	memmove (e + i + 1,
4852c393a42Smrg		 e + i,
4862c393a42Smrg		 sizeof (FcPatternElt) *
4872c393a42Smrg		 (p->num - i));
488ca08ab68Smrg
4892c393a42Smrg	/* bump count */
4902c393a42Smrg	p->num++;
4912c393a42Smrg
4922c393a42Smrg	e[i].object = object;
4932c393a42Smrg	e[i].values = NULL;
4942c393a42Smrg    }
495ca08ab68Smrg
4962c393a42Smrg    return FcPatternElts(p) + i;
4972c393a42Smrg}
4982c393a42Smrg
4992c393a42SmrgFcBool
5002c393a42SmrgFcPatternEqual (const FcPattern *pa, const FcPattern *pb)
5012c393a42Smrg{
5022c393a42Smrg    int	i;
5032c393a42Smrg    FcPatternElt   *pae, *pbe;
5042c393a42Smrg
5052c393a42Smrg    if (pa == pb)
5062c393a42Smrg	return FcTrue;
5072c393a42Smrg
5082c393a42Smrg    if (pa->num != pb->num)
5092c393a42Smrg	return FcFalse;
5102c393a42Smrg    pae = FcPatternElts(pa);
5112c393a42Smrg    pbe = FcPatternElts(pb);
5122c393a42Smrg    for (i = 0; i < pa->num; i++)
5132c393a42Smrg    {
5142c393a42Smrg	if (pae[i].object != pbe[i].object)
5152c393a42Smrg	    return FcFalse;
5162c393a42Smrg	if (!FcValueListEqual (FcPatternEltValues(&pae[i]),
5172c393a42Smrg			       FcPatternEltValues(&pbe[i])))
5182c393a42Smrg	    return FcFalse;
5192c393a42Smrg    }
5202c393a42Smrg    return FcTrue;
5212c393a42Smrg}
5222c393a42Smrg
5232c393a42SmrgFcChar32
5242c393a42SmrgFcPatternHash (const FcPattern *p)
5252c393a42Smrg{
5262c393a42Smrg    int		i;
5272c393a42Smrg    FcChar32	h = 0;
5282c393a42Smrg    FcPatternElt    *pe = FcPatternElts(p);
5292c393a42Smrg
5302c393a42Smrg    for (i = 0; i < p->num; i++)
5312c393a42Smrg    {
532ca08ab68Smrg	h = (((h << 1) | (h >> 31)) ^
5332c393a42Smrg	     pe[i].object ^
5342c393a42Smrg	     FcValueListHash (FcPatternEltValues(&pe[i])));
5352c393a42Smrg    }
5362c393a42Smrg    return h;
5372c393a42Smrg}
5382c393a42Smrg
5392c393a42SmrgFcBool
5402c393a42SmrgFcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
5412c393a42Smrg{
5422c393a42Smrg    FcPatternElt    *ea, *eb;
5432c393a42Smrg    int		    i;
544ca08ab68Smrg
5452c393a42Smrg    for (i = 0; i < os->nobject; i++)
5462c393a42Smrg    {
5472c393a42Smrg	FcObject    object = FcObjectFromName (os->objects[i]);
5482c393a42Smrg	ea = FcPatternObjectFindElt (pai, object);
5492c393a42Smrg	eb = FcPatternObjectFindElt (pbi, object);
5502c393a42Smrg	if (ea)
5512c393a42Smrg	{
5522c393a42Smrg	    if (!eb)
5532c393a42Smrg		return FcFalse;
5542c393a42Smrg	    if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
5552c393a42Smrg		return FcFalse;
5562c393a42Smrg	}
5572c393a42Smrg	else
5582c393a42Smrg	{
5592c393a42Smrg	    if (eb)
5602c393a42Smrg		return FcFalse;
5612c393a42Smrg	}
5622c393a42Smrg    }
5632c393a42Smrg    return FcTrue;
5642c393a42Smrg}
5652c393a42Smrg
566ca08ab68SmrgFcBool
567ca08ab68SmrgFcPatternObjectListAdd (FcPattern	*p,
568ca08ab68Smrg			FcObject	object,
569ca08ab68Smrg			FcValueListPtr	list,
570ca08ab68Smrg			FcBool		append)
571ca08ab68Smrg{
572ca08ab68Smrg    FcPatternElt   *e;
573ca08ab68Smrg    FcValueListPtr l, *prev;
574ca08ab68Smrg
575c9710b42Smrg    if (FcRefIsConst (&p->ref))
576ca08ab68Smrg	goto bail0;
577ca08ab68Smrg
578ca08ab68Smrg    /*
579ca08ab68Smrg     * Make sure the stored type is valid for built-in objects
580ca08ab68Smrg     */
581ca08ab68Smrg    for (l = list; l != NULL; l = FcValueListNext (l))
582ca08ab68Smrg    {
583ca08ab68Smrg	if (!FcObjectValidType (object, l->value.type))
584ca08ab68Smrg	{
585c9710b42Smrg	    fprintf (stderr,
586c9710b42Smrg		     "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
587c9710b42Smrg	    FcValuePrintFile (stderr, l->value);
588c9710b42Smrg	    fprintf (stderr, "\n");
589ca08ab68Smrg	    goto bail0;
590ca08ab68Smrg	}
591ca08ab68Smrg    }
592ca08ab68Smrg
593ca08ab68Smrg    e = FcPatternObjectInsertElt (p, object);
594ca08ab68Smrg    if (!e)
595ca08ab68Smrg	goto bail0;
596ca08ab68Smrg
597ca08ab68Smrg    if (append)
598ca08ab68Smrg    {
599ca08ab68Smrg	for (prev = &e->values; *prev; prev = &(*prev)->next)
600ca08ab68Smrg	    ;
601ca08ab68Smrg	*prev = list;
602ca08ab68Smrg    }
603ca08ab68Smrg    else
604ca08ab68Smrg    {
605ca08ab68Smrg	for (prev = &list; *prev; prev = &(*prev)->next)
606ca08ab68Smrg	    ;
607ca08ab68Smrg	*prev = e->values;
608ca08ab68Smrg	e->values = list;
609ca08ab68Smrg    }
610ca08ab68Smrg
611ca08ab68Smrg    return FcTrue;
612ca08ab68Smrg
613ca08ab68Smrgbail0:
614ca08ab68Smrg    return FcFalse;
615ca08ab68Smrg}
616ca08ab68Smrg
6172c393a42SmrgFcBool
6182c393a42SmrgFcPatternObjectAddWithBinding  (FcPattern	*p,
6192c393a42Smrg				FcObject	object,
6202c393a42Smrg				FcValue		value,
6212c393a42Smrg				FcValueBinding  binding,
6222c393a42Smrg				FcBool		append)
6232c393a42Smrg{
6242c393a42Smrg    FcPatternElt   *e;
6252c393a42Smrg    FcValueListPtr new, *prev;
6262c393a42Smrg
627c9710b42Smrg    if (FcRefIsConst (&p->ref))
6282c393a42Smrg	goto bail0;
6292c393a42Smrg
630ca08ab68Smrg    new = FcValueListCreate ();
6312c393a42Smrg    if (!new)
6322c393a42Smrg	goto bail0;
6332c393a42Smrg
634a6844aabSmrg    value = FcValueSave (value);
6352c393a42Smrg    if (value.type == FcTypeVoid)
6362c393a42Smrg	goto bail1;
6372c393a42Smrg
6382c393a42Smrg    /*
6392c393a42Smrg     * Make sure the stored type is valid for built-in objects
6402c393a42Smrg     */
6412c393a42Smrg    if (!FcObjectValidType (object, value.type))
6422c393a42Smrg    {
643c9710b42Smrg	fprintf (stderr,
644c9710b42Smrg		 "Fontconfig warning: FcPattern object %s does not accept value",
645c9710b42Smrg		 FcObjectName (object));
646c9710b42Smrg	FcValuePrintFile (stderr, value);
647c9710b42Smrg	fprintf (stderr, "\n");
6482c393a42Smrg	goto bail1;
6492c393a42Smrg    }
6502c393a42Smrg
6512c393a42Smrg    new->value = value;
6522c393a42Smrg    new->binding = binding;
6532c393a42Smrg    new->next = NULL;
654ca08ab68Smrg
6552c393a42Smrg    e = FcPatternObjectInsertElt (p, object);
6562c393a42Smrg    if (!e)
6572c393a42Smrg	goto bail2;
658ca08ab68Smrg
6592c393a42Smrg    if (append)
6602c393a42Smrg    {
6612c393a42Smrg	for (prev = &e->values; *prev; prev = &(*prev)->next)
6622c393a42Smrg	    ;
6632c393a42Smrg	*prev = new;
6642c393a42Smrg    }
6652c393a42Smrg    else
6662c393a42Smrg    {
6672c393a42Smrg	new->next = e->values;
6682c393a42Smrg	e->values = new;
6692c393a42Smrg    }
670ca08ab68Smrg
6712c393a42Smrg    return FcTrue;
6722c393a42Smrg
673ca08ab68Smrgbail2:
6742c393a42Smrg    FcValueDestroy (value);
6752c393a42Smrgbail1:
6762c393a42Smrg    free (new);
6772c393a42Smrgbail0:
6782c393a42Smrg    return FcFalse;
6792c393a42Smrg}
6802c393a42Smrg
6812c393a42SmrgFcBool
6822c393a42SmrgFcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
6832c393a42Smrg{
6842c393a42Smrg    return FcPatternObjectAddWithBinding (p, object,
6852c393a42Smrg					  value, FcValueBindingStrong, append);
6862c393a42Smrg}
6872c393a42Smrg
6882c393a42SmrgFcBool
6892c393a42SmrgFcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
6902c393a42Smrg{
6912c393a42Smrg    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
6922c393a42Smrg					  value, FcValueBindingStrong, append);
6932c393a42Smrg}
6942c393a42Smrg
6952c393a42SmrgFcBool
6962c393a42SmrgFcPatternAddWeak  (FcPattern *p, const char *object, FcValue value, FcBool append)
6972c393a42Smrg{
6982c393a42Smrg    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
6992c393a42Smrg					  value, FcValueBindingWeak, append);
7002c393a42Smrg}
7012c393a42Smrg
7022c393a42SmrgFcBool
7032c393a42SmrgFcPatternObjectDel (FcPattern *p, FcObject object)
7042c393a42Smrg{
7052c393a42Smrg    FcPatternElt   *e;
7062c393a42Smrg
7072c393a42Smrg    e = FcPatternObjectFindElt (p, object);
7082c393a42Smrg    if (!e)
7092c393a42Smrg	return FcFalse;
7102c393a42Smrg
7112c393a42Smrg    /* destroy value */
7122c393a42Smrg    FcValueListDestroy (e->values);
713ca08ab68Smrg
7142c393a42Smrg    /* shuffle existing ones down */
715ca08ab68Smrg    memmove (e, e+1,
716ca08ab68Smrg	     (FcPatternElts(p) + p->num - (e + 1)) *
7172c393a42Smrg	     sizeof (FcPatternElt));
7182c393a42Smrg    p->num--;
7192c393a42Smrg    e = FcPatternElts(p) + p->num;
7202c393a42Smrg    e->object = 0;
7212c393a42Smrg    e->values = NULL;
7222c393a42Smrg    return FcTrue;
7232c393a42Smrg}
7242c393a42Smrg
7252c393a42SmrgFcBool
7262c393a42SmrgFcPatternDel (FcPattern *p, const char *object)
7272c393a42Smrg{
7282c393a42Smrg    return FcPatternObjectDel (p, FcObjectFromName (object));
7292c393a42Smrg}
730ca08ab68Smrg
7312c393a42SmrgFcBool
7322c393a42SmrgFcPatternRemove (FcPattern *p, const char *object, int id)
7332c393a42Smrg{
7342c393a42Smrg    FcPatternElt    *e;
7352c393a42Smrg    FcValueListPtr  *prev, l;
7362c393a42Smrg
7372c393a42Smrg    e = FcPatternObjectFindElt (p, FcObjectFromName (object));
7382c393a42Smrg    if (!e)
7392c393a42Smrg	return FcFalse;
7402c393a42Smrg    for (prev = &e->values; (l = *prev); prev = &l->next)
7412c393a42Smrg    {
7422c393a42Smrg	if (!id)
7432c393a42Smrg	{
7442c393a42Smrg	    *prev = l->next;
7452c393a42Smrg	    l->next = NULL;
7462c393a42Smrg	    FcValueListDestroy (l);
7472c393a42Smrg	    if (!e->values)
7482c393a42Smrg		FcPatternDel (p, object);
7492c393a42Smrg	    return FcTrue;
7502c393a42Smrg	}
7512c393a42Smrg	id--;
7522c393a42Smrg    }
7532c393a42Smrg    return FcFalse;
7542c393a42Smrg}
7552c393a42Smrg
7562c393a42SmrgFcBool
7572c393a42SmrgFcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
7582c393a42Smrg{
7592c393a42Smrg    FcValue	v;
7602c393a42Smrg
7612c393a42Smrg    v.type = FcTypeInteger;
7622c393a42Smrg    v.u.i = i;
7632c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
7642c393a42Smrg}
7652c393a42Smrg
7662c393a42SmrgFcBool
7672c393a42SmrgFcPatternAddInteger (FcPattern *p, const char *object, int i)
7682c393a42Smrg{
7692c393a42Smrg    return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
7702c393a42Smrg}
7712c393a42Smrg
7722c393a42SmrgFcBool
7732c393a42SmrgFcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
7742c393a42Smrg{
7752c393a42Smrg    FcValue	v;
7762c393a42Smrg
7772c393a42Smrg    v.type = FcTypeDouble;
7782c393a42Smrg    v.u.d = d;
7792c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
7802c393a42Smrg}
7812c393a42Smrg
7822c393a42Smrg
7832c393a42SmrgFcBool
7842c393a42SmrgFcPatternAddDouble (FcPattern *p, const char *object, double d)
7852c393a42Smrg{
7862c393a42Smrg    return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
7872c393a42Smrg}
7882c393a42Smrg
7892c393a42SmrgFcBool
7902c393a42SmrgFcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
7912c393a42Smrg{
7922c393a42Smrg    FcValue	v;
7932c393a42Smrg
7942c393a42Smrg    if (!s)
7952c393a42Smrg    {
7962c393a42Smrg	v.type = FcTypeVoid;
7972c393a42Smrg	v.u.s = 0;
7982c393a42Smrg	return FcPatternObjectAdd (p, object, v, FcTrue);
7992c393a42Smrg    }
8002c393a42Smrg
8012c393a42Smrg    v.type = FcTypeString;
802ca08ab68Smrg    v.u.s = s;
8032c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
8042c393a42Smrg}
8052c393a42Smrg
8062c393a42SmrgFcBool
8072c393a42SmrgFcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
8082c393a42Smrg{
8092c393a42Smrg    return FcPatternObjectAddString (p, FcObjectFromName (object), s);
8102c393a42Smrg}
8112c393a42Smrg
8122c393a42SmrgFcBool
8132c393a42SmrgFcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
8142c393a42Smrg{
8152c393a42Smrg    FcValue	v;
8162c393a42Smrg
8172c393a42Smrg    v.type = FcTypeMatrix;
8182c393a42Smrg    v.u.m = s;
8192c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8202c393a42Smrg}
8212c393a42Smrg
8222c393a42Smrg
8232c393a42SmrgFcBool
8242c393a42SmrgFcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
8252c393a42Smrg{
8262c393a42Smrg    FcValue	v;
8272c393a42Smrg
8282c393a42Smrg    v.type = FcTypeBool;
8292c393a42Smrg    v.u.b = b;
8302c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
8312c393a42Smrg}
8322c393a42Smrg
8332c393a42SmrgFcBool
8342c393a42SmrgFcPatternAddBool (FcPattern *p, const char *object, FcBool b)
8352c393a42Smrg{
8362c393a42Smrg    return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
8372c393a42Smrg}
8382c393a42Smrg
8392c393a42SmrgFcBool
8402c393a42SmrgFcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
8412c393a42Smrg{
8422c393a42Smrg    FcValue	v;
8432c393a42Smrg
8442c393a42Smrg    v.type = FcTypeCharSet;
8452c393a42Smrg    v.u.c = (FcCharSet *)c;
8462c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8472c393a42Smrg}
8482c393a42Smrg
8492c393a42SmrgFcBool
8502c393a42SmrgFcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
8512c393a42Smrg{
8522c393a42Smrg    FcValue	v;
8532c393a42Smrg
8542c393a42Smrg    v.type = FcTypeFTFace;
8552c393a42Smrg    v.u.f = (void *) f;
8562c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8572c393a42Smrg}
8582c393a42Smrg
8592c393a42SmrgFcBool
8602c393a42SmrgFcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
8612c393a42Smrg{
8622c393a42Smrg    FcValue	v;
8632c393a42Smrg
8642c393a42Smrg    v.type = FcTypeLangSet;
8652c393a42Smrg    v.u.l = (FcLangSet *)ls;
8662c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8672c393a42Smrg}
8682c393a42Smrg
869953daebaSmrgFcBool
870953daebaSmrgFcPatternObjectAddRange (FcPattern *p, FcObject object, const FcRange *r)
871953daebaSmrg{
872953daebaSmrg    FcValue v;
873953daebaSmrg
874953daebaSmrg    v.type = FcTypeRange;
875953daebaSmrg    v.u.r = (FcRange *)r;
876953daebaSmrg    return FcPatternObjectAdd (p, object, v, FcTrue);
877953daebaSmrg}
878953daebaSmrg
879953daebaSmrgFcBool
880953daebaSmrgFcPatternAddRange (FcPattern *p, const char *object, const FcRange *r)
881953daebaSmrg{
882953daebaSmrg    return FcPatternObjectAddRange (p, FcObjectFromName (object), r);
883953daebaSmrg}
884953daebaSmrg
8852c393a42SmrgFcResult
8862c393a42SmrgFcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
8872c393a42Smrg{
8882c393a42Smrg    FcPatternElt   *e;
8892c393a42Smrg    FcValueListPtr l;
8902c393a42Smrg
891c9710b42Smrg    if (!p)
892c9710b42Smrg	return FcResultNoMatch;
8932c393a42Smrg    e = FcPatternObjectFindElt (p, object);
8942c393a42Smrg    if (!e)
8952c393a42Smrg	return FcResultNoMatch;
8962c393a42Smrg    for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
8972c393a42Smrg    {
8982c393a42Smrg	if (!id)
8992c393a42Smrg	{
9002c393a42Smrg	    *v = FcValueCanonicalize(&l->value);
9012c393a42Smrg	    return FcResultMatch;
9022c393a42Smrg	}
9032c393a42Smrg	id--;
9042c393a42Smrg    }
9052c393a42Smrg    return FcResultNoId;
9062c393a42Smrg}
9072c393a42Smrg
9082c393a42SmrgFcResult
9092c393a42SmrgFcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
9102c393a42Smrg{
9112c393a42Smrg    return FcPatternObjectGet (p, FcObjectFromName (object), id, v);
9122c393a42Smrg}
9132c393a42Smrg
9142c393a42SmrgFcResult
9152c393a42SmrgFcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
9162c393a42Smrg{
9172c393a42Smrg    FcValue	v;
9182c393a42Smrg    FcResult	r;
9192c393a42Smrg
9202c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
9212c393a42Smrg    if (r != FcResultMatch)
9222c393a42Smrg	return r;
923c9710b42Smrg    switch ((int) v.type) {
9242c393a42Smrg    case FcTypeDouble:
9252c393a42Smrg	*i = (int) v.u.d;
9262c393a42Smrg	break;
9272c393a42Smrg    case FcTypeInteger:
9282c393a42Smrg	*i = v.u.i;
9292c393a42Smrg	break;
9302c393a42Smrg    default:
9312c393a42Smrg        return FcResultTypeMismatch;
9322c393a42Smrg    }
9332c393a42Smrg    return FcResultMatch;
9342c393a42Smrg}
9352c393a42Smrg
9362c393a42SmrgFcResult
9372c393a42SmrgFcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
9382c393a42Smrg{
9392c393a42Smrg    return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
9402c393a42Smrg}
941ca08ab68Smrg
942ca08ab68Smrg
9432c393a42SmrgFcResult
9442c393a42SmrgFcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
9452c393a42Smrg{
9462c393a42Smrg    FcValue	v;
9472c393a42Smrg    FcResult	r;
9482c393a42Smrg
9492c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
9502c393a42Smrg    if (r != FcResultMatch)
9512c393a42Smrg	return r;
952c9710b42Smrg    switch ((int) v.type) {
9532c393a42Smrg    case FcTypeDouble:
9542c393a42Smrg	*d = v.u.d;
9552c393a42Smrg	break;
9562c393a42Smrg    case FcTypeInteger:
9572c393a42Smrg	*d = (double) v.u.i;
9582c393a42Smrg	break;
9592c393a42Smrg    default:
9602c393a42Smrg        return FcResultTypeMismatch;
9612c393a42Smrg    }
9622c393a42Smrg    return FcResultMatch;
9632c393a42Smrg}
9642c393a42Smrg
9652c393a42SmrgFcResult
9662c393a42SmrgFcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
9672c393a42Smrg{
9682c393a42Smrg    return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
9692c393a42Smrg}
9702c393a42Smrg
9712c393a42SmrgFcResult
9722c393a42SmrgFcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
9732c393a42Smrg{
9742c393a42Smrg    FcValue	v;
9752c393a42Smrg    FcResult	r;
9762c393a42Smrg
9772c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
9782c393a42Smrg    if (r != FcResultMatch)
9792c393a42Smrg	return r;
9802c393a42Smrg    if (v.type != FcTypeString)
9812c393a42Smrg        return FcResultTypeMismatch;
9822c393a42Smrg
9832c393a42Smrg    *s = (FcChar8 *) v.u.s;
9842c393a42Smrg    return FcResultMatch;
9852c393a42Smrg}
9862c393a42Smrg
9872c393a42SmrgFcResult
9882c393a42SmrgFcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
9892c393a42Smrg{
9902c393a42Smrg    return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
9912c393a42Smrg}
992ca08ab68Smrg
9932c393a42SmrgFcResult
9942c393a42SmrgFcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
9952c393a42Smrg{
9962c393a42Smrg    FcValue	v;
9972c393a42Smrg    FcResult	r;
9982c393a42Smrg
9992c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10002c393a42Smrg    if (r != FcResultMatch)
10012c393a42Smrg	return r;
10022c393a42Smrg    if (v.type != FcTypeMatrix)
10032c393a42Smrg        return FcResultTypeMismatch;
10042c393a42Smrg    *m = (FcMatrix *)v.u.m;
10052c393a42Smrg    return FcResultMatch;
10062c393a42Smrg}
10072c393a42Smrg
10082c393a42Smrg
10092c393a42SmrgFcResult
10102c393a42SmrgFcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
10112c393a42Smrg{
10122c393a42Smrg    FcValue	v;
10132c393a42Smrg    FcResult	r;
10142c393a42Smrg
10152c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10162c393a42Smrg    if (r != FcResultMatch)
10172c393a42Smrg	return r;
10182c393a42Smrg    if (v.type != FcTypeBool)
10192c393a42Smrg        return FcResultTypeMismatch;
10202c393a42Smrg    *b = v.u.b;
10212c393a42Smrg    return FcResultMatch;
10222c393a42Smrg}
10232c393a42Smrg
10242c393a42SmrgFcResult
10252c393a42SmrgFcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
10262c393a42Smrg{
10272c393a42Smrg    FcValue	v;
10282c393a42Smrg    FcResult	r;
10292c393a42Smrg
10302c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10312c393a42Smrg    if (r != FcResultMatch)
10322c393a42Smrg	return r;
10332c393a42Smrg    if (v.type != FcTypeCharSet)
10342c393a42Smrg        return FcResultTypeMismatch;
10352c393a42Smrg    *c = (FcCharSet *)v.u.c;
10362c393a42Smrg    return FcResultMatch;
10372c393a42Smrg}
10382c393a42Smrg
10392c393a42SmrgFcResult
10402c393a42SmrgFcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
10412c393a42Smrg{
10422c393a42Smrg    FcValue	v;
10432c393a42Smrg    FcResult	r;
10442c393a42Smrg
10452c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10462c393a42Smrg    if (r != FcResultMatch)
10472c393a42Smrg	return r;
10482c393a42Smrg    if (v.type != FcTypeFTFace)
10492c393a42Smrg	return FcResultTypeMismatch;
10502c393a42Smrg    *f = (FT_Face) v.u.f;
10512c393a42Smrg    return FcResultMatch;
10522c393a42Smrg}
10532c393a42Smrg
10542c393a42SmrgFcResult
10552c393a42SmrgFcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
10562c393a42Smrg{
10572c393a42Smrg    FcValue	v;
10582c393a42Smrg    FcResult	r;
10592c393a42Smrg
10602c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10612c393a42Smrg    if (r != FcResultMatch)
10622c393a42Smrg	return r;
10632c393a42Smrg    if (v.type != FcTypeLangSet)
10642c393a42Smrg        return FcResultTypeMismatch;
10652c393a42Smrg    *ls = (FcLangSet *)v.u.l;
10662c393a42Smrg    return FcResultMatch;
10672c393a42Smrg}
10682c393a42Smrg
1069953daebaSmrgFcResult
1070953daebaSmrgFcPatternObjectGetRange (const FcPattern *p, FcObject object, int id, FcRange **r)
1071953daebaSmrg{
1072953daebaSmrg    FcValue	v;
1073953daebaSmrg    FcResult	res;
1074953daebaSmrg
1075953daebaSmrg    res = FcPatternObjectGet (p, object, id, &v);
1076953daebaSmrg    if (res != FcResultMatch)
1077953daebaSmrg	return res;
1078953daebaSmrg    switch ((int)v.type) {
1079953daebaSmrg    case FcTypeRange:
1080953daebaSmrg	*r = (FcRange *)v.u.r;
1081953daebaSmrg	break;
1082953daebaSmrg    default:
1083953daebaSmrg	return FcResultTypeMismatch;
1084953daebaSmrg    }
1085953daebaSmrg    return FcResultMatch;
1086953daebaSmrg}
1087953daebaSmrg
1088953daebaSmrgFcResult
1089953daebaSmrgFcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r)
1090953daebaSmrg{
1091953daebaSmrg    return FcPatternObjectGetRange (p, FcObjectFromName (object), id, r);
1092953daebaSmrg}
1093953daebaSmrg
10942c393a42SmrgFcPattern *
10952c393a42SmrgFcPatternDuplicate (const FcPattern *orig)
10962c393a42Smrg{
10972c393a42Smrg    FcPattern	    *new;
10982c393a42Smrg    FcPatternElt    *e;
10992c393a42Smrg    int		    i;
11002c393a42Smrg    FcValueListPtr  l;
11012c393a42Smrg
11022c393a42Smrg    new = FcPatternCreate ();
11032c393a42Smrg    if (!new)
11042c393a42Smrg	goto bail0;
11052c393a42Smrg
11062c393a42Smrg    e = FcPatternElts(orig);
11072c393a42Smrg
11082c393a42Smrg    for (i = 0; i < orig->num; i++)
11092c393a42Smrg    {
11102c393a42Smrg	for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l))
11112c393a42Smrg	{
11122c393a42Smrg	    if (!FcPatternObjectAddWithBinding (new, e[i].object,
11132c393a42Smrg						FcValueCanonicalize(&l->value),
11142c393a42Smrg						l->binding,
11152c393a42Smrg						FcTrue))
11162c393a42Smrg		goto bail1;
1117ca08ab68Smrg
11182c393a42Smrg	}
11192c393a42Smrg    }
11202c393a42Smrg
11212c393a42Smrg    return new;
11222c393a42Smrg
11232c393a42Smrgbail1:
11242c393a42Smrg    FcPatternDestroy (new);
11252c393a42Smrgbail0:
11262c393a42Smrg    return 0;
11272c393a42Smrg}
11282c393a42Smrg
11292c393a42Smrgvoid
11302c393a42SmrgFcPatternReference (FcPattern *p)
11312c393a42Smrg{
1132c9710b42Smrg    if (!FcRefIsConst (&p->ref))
1133c9710b42Smrg	FcRefInc (&p->ref);
11342c393a42Smrg    else
11352c393a42Smrg	FcCacheObjectReference (p);
11362c393a42Smrg}
11372c393a42Smrg
11382c393a42SmrgFcPattern *
1139a6844aabSmrgFcPatternVaBuild (FcPattern *p, va_list va)
11402c393a42Smrg{
11412c393a42Smrg    FcPattern	*ret;
1142ca08ab68Smrg
1143a6844aabSmrg    FcPatternVapBuild (ret, p, va);
11442c393a42Smrg    return ret;
11452c393a42Smrg}
11462c393a42Smrg
11472c393a42SmrgFcPattern *
1148a6844aabSmrgFcPatternBuild (FcPattern *p, ...)
11492c393a42Smrg{
11502c393a42Smrg    va_list	va;
1151ca08ab68Smrg
1152a6844aabSmrg    va_start (va, p);
1153a6844aabSmrg    FcPatternVapBuild (p, p, va);
11542c393a42Smrg    va_end (va);
1155a6844aabSmrg    return p;
11562c393a42Smrg}
11572c393a42Smrg
11582c393a42Smrg/*
11592c393a42Smrg * Add all of the elements in 's' to 'p'
11602c393a42Smrg */
11612c393a42SmrgFcBool
11622c393a42SmrgFcPatternAppend (FcPattern *p, FcPattern *s)
11632c393a42Smrg{
11642c393a42Smrg    int		    i;
11652c393a42Smrg    FcPatternElt    *e;
11662c393a42Smrg    FcValueListPtr  v;
1167ca08ab68Smrg
11682c393a42Smrg    for (i = 0; i < s->num; i++)
11692c393a42Smrg    {
11702c393a42Smrg	e = FcPatternElts(s)+i;
11712c393a42Smrg	for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
11722c393a42Smrg	{
11732c393a42Smrg	    if (!FcPatternObjectAddWithBinding (p, e->object,
1174ca08ab68Smrg						FcValueCanonicalize(&v->value),
11752c393a42Smrg						v->binding, FcTrue))
11762c393a42Smrg		return FcFalse;
11772c393a42Smrg	}
11782c393a42Smrg    }
11792c393a42Smrg    return FcTrue;
11802c393a42Smrg}
11812c393a42Smrg
1182a6844aabSmrgFcPattern *
1183a6844aabSmrgFcPatternFilter (FcPattern *p, const FcObjectSet *os)
1184a6844aabSmrg{
1185a6844aabSmrg    int		    i;
1186a6844aabSmrg    FcPattern	    *ret;
1187a6844aabSmrg    FcPatternElt    *e;
1188a6844aabSmrg    FcValueListPtr  v;
1189a6844aabSmrg
1190a6844aabSmrg    if (!os)
1191a6844aabSmrg	return FcPatternDuplicate (p);
1192a6844aabSmrg
1193a6844aabSmrg    ret = FcPatternCreate ();
1194a6844aabSmrg    if (!ret)
1195a6844aabSmrg	return NULL;
1196a6844aabSmrg
1197a6844aabSmrg    for (i = 0; i < os->nobject; i++)
1198a6844aabSmrg    {
1199a6844aabSmrg	FcObject object = FcObjectFromName (os->objects[i]);
1200a6844aabSmrg	e = FcPatternObjectFindElt (p, object);
1201a6844aabSmrg	if (e)
1202a6844aabSmrg	{
1203a6844aabSmrg	    for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1204a6844aabSmrg	    {
1205a6844aabSmrg		if (!FcPatternObjectAddWithBinding (ret, e->object,
1206a6844aabSmrg						    FcValueCanonicalize(&v->value),
1207a6844aabSmrg						    v->binding, FcTrue))
1208a6844aabSmrg		    goto bail0;
1209a6844aabSmrg	    }
1210a6844aabSmrg	}
1211a6844aabSmrg    }
1212a6844aabSmrg    return ret;
1213a6844aabSmrg
1214a6844aabSmrgbail0:
1215a6844aabSmrg    FcPatternDestroy (ret);
1216a6844aabSmrg    return NULL;
1217a6844aabSmrg}
1218a6844aabSmrg
12192c393a42Smrg
12202c393a42SmrgFcBool
12212c393a42SmrgFcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
12222c393a42Smrg{
12232c393a42Smrg    int	i;
12242c393a42Smrg    FcPatternElt    *elts = FcPatternElts(pat);
1225ca08ab68Smrg
12262c393a42Smrg    if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
12272c393a42Smrg	return FcFalse;
12282c393a42Smrg    if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt)))
12292c393a42Smrg	return FcFalse;
12302c393a42Smrg    for (i = 0; i < pat->num; i++)
12312c393a42Smrg	if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
12322c393a42Smrg	    return FcFalse;
12332c393a42Smrg    return FcTrue;
12342c393a42Smrg}
12352c393a42Smrg
12362c393a42SmrgFcPattern *
12372c393a42SmrgFcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
12382c393a42Smrg{
12392c393a42Smrg    FcPattern	    *pat_serialized;
12402c393a42Smrg    FcPatternElt    *elts = FcPatternElts (pat);
12412c393a42Smrg    FcPatternElt    *elts_serialized;
12422c393a42Smrg    FcValueList	    *values_serialized;
12432c393a42Smrg    int		    i;
12442c393a42Smrg
12452c393a42Smrg    pat_serialized = FcSerializePtr (serialize, pat);
12462c393a42Smrg    if (!pat_serialized)
12472c393a42Smrg	return NULL;
12482c393a42Smrg    *pat_serialized = *pat;
12492c393a42Smrg    pat_serialized->size = pat->num;
1250c9710b42Smrg    FcRefSetConst (&pat_serialized->ref);
1251ca08ab68Smrg
12522c393a42Smrg    elts_serialized = FcSerializePtr (serialize, elts);
12532c393a42Smrg    if (!elts_serialized)
12542c393a42Smrg	return NULL;
1255ca08ab68Smrg
12562c393a42Smrg    pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
12572c393a42Smrg						 elts_serialized);
12582c393a42Smrg
12592c393a42Smrg    for (i = 0; i < pat->num; i++)
12602c393a42Smrg    {
12612c393a42Smrg	values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
12622c393a42Smrg	if (!values_serialized)
12632c393a42Smrg	    return NULL;
12642c393a42Smrg	elts_serialized[i].object = elts[i].object;
1265ca08ab68Smrg	elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
12662c393a42Smrg							  values_serialized,
12672c393a42Smrg							  FcValueList);
12682c393a42Smrg    }
12692c393a42Smrg    if (FcDebug() & FC_DBG_CACHEV) {
12702c393a42Smrg	printf ("Raw pattern:\n");
12712c393a42Smrg	FcPatternPrint (pat);
12722c393a42Smrg	printf ("Serialized pattern:\n");
12732c393a42Smrg	FcPatternPrint (pat_serialized);
12742c393a42Smrg	printf ("\n");
12752c393a42Smrg    }
12762c393a42Smrg    return pat_serialized;
12772c393a42Smrg}
12782c393a42Smrg
12792c393a42SmrgFcBool
12802c393a42SmrgFcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
12812c393a42Smrg{
12822c393a42Smrg    while (vl)
12832c393a42Smrg    {
12842c393a42Smrg	if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
12852c393a42Smrg	    return FcFalse;
1286c9710b42Smrg	switch ((int) vl->value.type) {
12872c393a42Smrg	case FcTypeString:
12882c393a42Smrg	    if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
12892c393a42Smrg		return FcFalse;
12902c393a42Smrg	    break;
12912c393a42Smrg	case FcTypeCharSet:
12922c393a42Smrg	    if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
12932c393a42Smrg		return FcFalse;
12942c393a42Smrg	    break;
12952c393a42Smrg	case FcTypeLangSet:
12962c393a42Smrg	    if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
12972c393a42Smrg		return FcFalse;
12982c393a42Smrg	    break;
1299953daebaSmrg	case FcTypeRange:
1300953daebaSmrg	    if (!FcRangeSerializeAlloc (serialize, vl->value.u.r))
1301953daebaSmrg		return FcFalse;
1302953daebaSmrg	    break;
13032c393a42Smrg	default:
13042c393a42Smrg	    break;
13052c393a42Smrg	}
13062c393a42Smrg	vl = vl->next;
13072c393a42Smrg    }
13082c393a42Smrg    return FcTrue;
13092c393a42Smrg}
13102c393a42Smrg
13112c393a42SmrgFcValueList *
13122c393a42SmrgFcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
13132c393a42Smrg{
13142c393a42Smrg    FcValueList	*vl_serialized;
13152c393a42Smrg    FcChar8	*s_serialized;
13162c393a42Smrg    FcCharSet	*c_serialized;
13172c393a42Smrg    FcLangSet	*l_serialized;
1318953daebaSmrg    FcRange	*r_serialized;
13192c393a42Smrg    FcValueList	*head_serialized = NULL;
13202c393a42Smrg    FcValueList	*prev_serialized = NULL;
13212c393a42Smrg
13222c393a42Smrg    while (vl)
13232c393a42Smrg    {
13242c393a42Smrg	vl_serialized = FcSerializePtr (serialize, vl);
13252c393a42Smrg	if (!vl_serialized)
13262c393a42Smrg	    return NULL;
1327ca08ab68Smrg
13282c393a42Smrg	if (prev_serialized)
13292c393a42Smrg	    prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
13302c393a42Smrg							  vl_serialized,
13312c393a42Smrg							  FcValueList);
13322c393a42Smrg	else
13332c393a42Smrg	    head_serialized = vl_serialized;
13342c393a42Smrg
13352c393a42Smrg	vl_serialized->next = NULL;
13362c393a42Smrg	vl_serialized->value.type = vl->value.type;
1337c9710b42Smrg	switch ((int) vl->value.type) {
13382c393a42Smrg	case FcTypeInteger:
13392c393a42Smrg	    vl_serialized->value.u.i = vl->value.u.i;
13402c393a42Smrg	    break;
13412c393a42Smrg	case FcTypeDouble:
13422c393a42Smrg	    vl_serialized->value.u.d = vl->value.u.d;
13432c393a42Smrg	    break;
13442c393a42Smrg	case FcTypeString:
13452c393a42Smrg	    s_serialized = FcStrSerialize (serialize, vl->value.u.s);
13462c393a42Smrg	    if (!s_serialized)
13472c393a42Smrg		return NULL;
13482c393a42Smrg	    vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
13492c393a42Smrg							     s_serialized,
13502c393a42Smrg							     FcChar8);
13512c393a42Smrg	    break;
13522c393a42Smrg	case FcTypeBool:
13532c393a42Smrg	    vl_serialized->value.u.b = vl->value.u.b;
13542c393a42Smrg	    break;
13552c393a42Smrg	case FcTypeMatrix:
13562c393a42Smrg	    /* can't happen */
13572c393a42Smrg	    break;
13582c393a42Smrg	case FcTypeCharSet:
13592c393a42Smrg	    c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
13602c393a42Smrg	    if (!c_serialized)
13612c393a42Smrg		return NULL;
13622c393a42Smrg	    vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
13632c393a42Smrg							     c_serialized,
13642c393a42Smrg							     FcCharSet);
13652c393a42Smrg	    break;
13662c393a42Smrg	case FcTypeFTFace:
13672c393a42Smrg	    /* can't happen */
13682c393a42Smrg	    break;
13692c393a42Smrg	case FcTypeLangSet:
13702c393a42Smrg	    l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
13712c393a42Smrg	    if (!l_serialized)
13722c393a42Smrg		return NULL;
13732c393a42Smrg	    vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
13742c393a42Smrg							     l_serialized,
13752c393a42Smrg							     FcLangSet);
13762c393a42Smrg	    break;
1377953daebaSmrg	case FcTypeRange:
1378953daebaSmrg	    r_serialized = FcRangeSerialize (serialize, vl->value.u.r);
1379953daebaSmrg	    if (!r_serialized)
1380953daebaSmrg		return NULL;
1381953daebaSmrg	    vl_serialized->value.u.r = FcPtrToEncodedOffset (&vl_serialized->value,
1382953daebaSmrg							     r_serialized,
1383953daebaSmrg							     FcRange);
1384953daebaSmrg	    break;
13852c393a42Smrg	default:
13862c393a42Smrg	    break;
13872c393a42Smrg	}
13882c393a42Smrg	prev_serialized = vl_serialized;
13892c393a42Smrg	vl = vl->next;
13902c393a42Smrg    }
13912c393a42Smrg    return head_serialized;
13922c393a42Smrg}
1393b09479dcSmrg
13942c393a42Smrg#define __fcpat__
13952c393a42Smrg#include "fcaliastail.h"
13962c393a42Smrg#include "fcftaliastail.h"
13972c393a42Smrg#undef __fcpat__
1398