fcpat.c revision 6fc018e4
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;
362c393a42Smrg    p->num = 0;
372c393a42Smrg    p->size = 0;
382c393a42Smrg    p->elts_offset = FcPtrToOffset (p, NULL);
39c9710b42Smrg    FcRefInit (&p->ref, 1);
402c393a42Smrg    return p;
412c393a42Smrg}
422c393a42Smrg
432c393a42Smrgvoid
442c393a42SmrgFcValueDestroy (FcValue v)
452c393a42Smrg{
46c9710b42Smrg    switch ((int) v.type) {
472c393a42Smrg    case FcTypeString:
48c9710b42Smrg	FcFree (v.u.s);
492c393a42Smrg	break;
502c393a42Smrg    case FcTypeMatrix:
512c393a42Smrg	FcMatrixFree ((FcMatrix *) v.u.m);
522c393a42Smrg	break;
532c393a42Smrg    case FcTypeCharSet:
542c393a42Smrg	FcCharSetDestroy ((FcCharSet *) v.u.c);
552c393a42Smrg	break;
562c393a42Smrg    case FcTypeLangSet:
572c393a42Smrg	FcLangSetDestroy ((FcLangSet *) v.u.l);
582c393a42Smrg	break;
592c393a42Smrg    default:
602c393a42Smrg	break;
612c393a42Smrg    }
622c393a42Smrg}
632c393a42Smrg
642c393a42SmrgFcValue
652c393a42SmrgFcValueCanonicalize (const FcValue *v)
662c393a42Smrg{
672c393a42Smrg    FcValue new;
682c393a42Smrg
69c9710b42Smrg    switch ((int) v->type)
702c393a42Smrg    {
712c393a42Smrg    case FcTypeString:
72a6844aabSmrg	new.u.s = FcValueString(v);
732c393a42Smrg	new.type = FcTypeString;
742c393a42Smrg	break;
752c393a42Smrg    case FcTypeCharSet:
76a6844aabSmrg	new.u.c = FcValueCharSet(v);
772c393a42Smrg	new.type = FcTypeCharSet;
782c393a42Smrg	break;
792c393a42Smrg    case FcTypeLangSet:
80a6844aabSmrg	new.u.l = FcValueLangSet(v);
812c393a42Smrg	new.type = FcTypeLangSet;
822c393a42Smrg	break;
832c393a42Smrg    default:
842c393a42Smrg	new = *v;
852c393a42Smrg	break;
862c393a42Smrg    }
872c393a42Smrg    return new;
882c393a42Smrg}
892c393a42Smrg
902c393a42SmrgFcValue
912c393a42SmrgFcValueSave (FcValue v)
922c393a42Smrg{
93c9710b42Smrg    switch ((int) v.type) {
942c393a42Smrg    case FcTypeString:
95c9710b42Smrg	v.u.s = FcStrdup (v.u.s);
962c393a42Smrg	if (!v.u.s)
972c393a42Smrg	    v.type = FcTypeVoid;
982c393a42Smrg	break;
992c393a42Smrg    case FcTypeMatrix:
1002c393a42Smrg	v.u.m = FcMatrixCopy (v.u.m);
1012c393a42Smrg	if (!v.u.m)
1022c393a42Smrg	    v.type = FcTypeVoid;
1032c393a42Smrg	break;
1042c393a42Smrg    case FcTypeCharSet:
1052c393a42Smrg	v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
1062c393a42Smrg	if (!v.u.c)
1072c393a42Smrg	    v.type = FcTypeVoid;
1082c393a42Smrg	break;
1092c393a42Smrg    case FcTypeLangSet:
1102c393a42Smrg	v.u.l = FcLangSetCopy (v.u.l);
1112c393a42Smrg	if (!v.u.l)
1122c393a42Smrg	    v.type = FcTypeVoid;
1132c393a42Smrg	break;
1142c393a42Smrg    default:
1152c393a42Smrg	break;
1162c393a42Smrg    }
1172c393a42Smrg    return v;
1182c393a42Smrg}
1192c393a42Smrg
120ca08ab68SmrgFcValueListPtr
121ca08ab68SmrgFcValueListCreate (void)
122ca08ab68Smrg{
123c9710b42Smrg    return calloc (1, sizeof (FcValueList));
124ca08ab68Smrg}
125ca08ab68Smrg
1262c393a42Smrgvoid
1272c393a42SmrgFcValueListDestroy (FcValueListPtr l)
1282c393a42Smrg{
1292c393a42Smrg    FcValueListPtr next;
1302c393a42Smrg    for (; l; l = next)
1312c393a42Smrg    {
132c9710b42Smrg	switch ((int) l->value.type) {
1332c393a42Smrg	case FcTypeString:
134c9710b42Smrg	    FcFree (l->value.u.s);
1352c393a42Smrg	    break;
1362c393a42Smrg	case FcTypeMatrix:
1372c393a42Smrg	    FcMatrixFree ((FcMatrix *)l->value.u.m);
1382c393a42Smrg	    break;
1392c393a42Smrg	case FcTypeCharSet:
140ca08ab68Smrg	    FcCharSetDestroy
1412c393a42Smrg		((FcCharSet *) (l->value.u.c));
1422c393a42Smrg	    break;
1432c393a42Smrg	case FcTypeLangSet:
144ca08ab68Smrg	    FcLangSetDestroy
1452c393a42Smrg		((FcLangSet *) (l->value.u.l));
1462c393a42Smrg	    break;
1472c393a42Smrg	default:
1482c393a42Smrg	    break;
1492c393a42Smrg	}
1502c393a42Smrg	next = FcValueListNext(l);
1512c393a42Smrg	free(l);
1522c393a42Smrg    }
1532c393a42Smrg}
1542c393a42Smrg
155ca08ab68SmrgFcValueListPtr
156ca08ab68SmrgFcValueListPrepend (FcValueListPtr vallist,
157ca08ab68Smrg		    FcValue        value,
158ca08ab68Smrg		    FcValueBinding binding)
159ca08ab68Smrg{
160ca08ab68Smrg    FcValueListPtr new;
161ca08ab68Smrg
162ca08ab68Smrg    if (value.type == FcTypeVoid)
163ca08ab68Smrg	return vallist;
164ca08ab68Smrg    new = FcValueListCreate ();
165ca08ab68Smrg    if (!new)
166ca08ab68Smrg	return vallist;
167ca08ab68Smrg
168ca08ab68Smrg    new->value = FcValueSave (value);
169ca08ab68Smrg    new->binding = binding;
170ca08ab68Smrg    new->next = vallist;
171ca08ab68Smrg
172ca08ab68Smrg    return new;
173ca08ab68Smrg}
174ca08ab68Smrg
175ca08ab68SmrgFcValueListPtr
176ca08ab68SmrgFcValueListAppend (FcValueListPtr vallist,
177ca08ab68Smrg		   FcValue        value,
178ca08ab68Smrg		   FcValueBinding binding)
179ca08ab68Smrg{
180ca08ab68Smrg    FcValueListPtr new, last;
181ca08ab68Smrg
182ca08ab68Smrg    if (value.type == FcTypeVoid)
183ca08ab68Smrg	return vallist;
184ca08ab68Smrg    new = FcValueListCreate ();
185ca08ab68Smrg    if (!new)
186ca08ab68Smrg	return vallist;
187ca08ab68Smrg
188ca08ab68Smrg    new->value = FcValueSave (value);
189ca08ab68Smrg    new->binding = binding;
190ca08ab68Smrg    new->next = NULL;
191ca08ab68Smrg
192ca08ab68Smrg    if (vallist)
193ca08ab68Smrg    {
194ca08ab68Smrg	for (last = vallist; FcValueListNext (last); last = FcValueListNext (last));
195ca08ab68Smrg
196ca08ab68Smrg	last->next = new;
197ca08ab68Smrg    }
198ca08ab68Smrg    else
199ca08ab68Smrg	vallist = new;
200ca08ab68Smrg
201ca08ab68Smrg    return vallist;
202ca08ab68Smrg}
203ca08ab68Smrg
204ca08ab68SmrgFcValueListPtr
205ca08ab68SmrgFcValueListDuplicate(FcValueListPtr orig)
206ca08ab68Smrg{
207ca08ab68Smrg    FcValueListPtr new = NULL, l, t = NULL;
208ca08ab68Smrg    FcValue v;
209ca08ab68Smrg
210ca08ab68Smrg    for (l = orig; l != NULL; l = FcValueListNext (l))
211ca08ab68Smrg    {
212ca08ab68Smrg	if (!new)
213ca08ab68Smrg	{
214ca08ab68Smrg	    t = new = FcValueListCreate();
215ca08ab68Smrg	}
216ca08ab68Smrg	else
217ca08ab68Smrg	{
218ca08ab68Smrg	    t->next = FcValueListCreate();
219ca08ab68Smrg	    t = FcValueListNext (t);
220ca08ab68Smrg	}
221ca08ab68Smrg	v = FcValueCanonicalize (&l->value);
222ca08ab68Smrg	t->value = FcValueSave (v);
223ca08ab68Smrg	t->binding = l->binding;
224ca08ab68Smrg	t->next = NULL;
225ca08ab68Smrg    }
226ca08ab68Smrg
227ca08ab68Smrg    return new;
228ca08ab68Smrg}
229ca08ab68Smrg
2302c393a42SmrgFcBool
2312c393a42SmrgFcValueEqual (FcValue va, FcValue vb)
2322c393a42Smrg{
2332c393a42Smrg    if (va.type != vb.type)
2342c393a42Smrg    {
2352c393a42Smrg	if (va.type == FcTypeInteger)
2362c393a42Smrg	{
2372c393a42Smrg	    va.type = FcTypeDouble;
2382c393a42Smrg	    va.u.d = va.u.i;
2392c393a42Smrg	}
2402c393a42Smrg	if (vb.type == FcTypeInteger)
2412c393a42Smrg	{
2422c393a42Smrg	    vb.type = FcTypeDouble;
2432c393a42Smrg	    vb.u.d = vb.u.i;
2442c393a42Smrg	}
2452c393a42Smrg	if (va.type != vb.type)
2462c393a42Smrg	    return FcFalse;
2472c393a42Smrg    }
2482c393a42Smrg    switch (va.type) {
2496fc018e4Smrg    case FcTypeUnknown:
2506fc018e4Smrg	return FcFalse;	/* don't know how to compare this object */
2512c393a42Smrg    case FcTypeVoid:
2522c393a42Smrg	return FcTrue;
2532c393a42Smrg    case FcTypeInteger:
2542c393a42Smrg	return va.u.i == vb.u.i;
2552c393a42Smrg    case FcTypeDouble:
2562c393a42Smrg	return va.u.d == vb.u.d;
2572c393a42Smrg    case FcTypeString:
2582c393a42Smrg	return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
2592c393a42Smrg    case FcTypeBool:
2602c393a42Smrg	return va.u.b == vb.u.b;
2612c393a42Smrg    case FcTypeMatrix:
2622c393a42Smrg	return FcMatrixEqual (va.u.m, vb.u.m);
2632c393a42Smrg    case FcTypeCharSet:
2642c393a42Smrg	return FcCharSetEqual (va.u.c, vb.u.c);
2652c393a42Smrg    case FcTypeFTFace:
2662c393a42Smrg	return va.u.f == vb.u.f;
2672c393a42Smrg    case FcTypeLangSet:
2682c393a42Smrg	return FcLangSetEqual (va.u.l, vb.u.l);
2692c393a42Smrg    }
2702c393a42Smrg    return FcFalse;
2712c393a42Smrg}
2722c393a42Smrg
2732c393a42Smrgstatic FcChar32
2742c393a42SmrgFcDoubleHash (double d)
2752c393a42Smrg{
2762c393a42Smrg    if (d < 0)
2772c393a42Smrg	d = -d;
2782c393a42Smrg    if (d > 0xffffffff)
2792c393a42Smrg	d = 0xffffffff;
2802c393a42Smrg    return (FcChar32) d;
2812c393a42Smrg}
2822c393a42Smrg
2832c393a42SmrgFcChar32
2842c393a42SmrgFcStringHash (const FcChar8 *s)
2852c393a42Smrg{
2862c393a42Smrg    FcChar8	c;
2872c393a42Smrg    FcChar32	h = 0;
288ca08ab68Smrg
2892c393a42Smrg    if (s)
2902c393a42Smrg	while ((c = *s++))
2912c393a42Smrg	    h = ((h << 1) | (h >> 31)) ^ c;
2922c393a42Smrg    return h;
2932c393a42Smrg}
2942c393a42Smrg
2952c393a42Smrgstatic FcChar32
2962c393a42SmrgFcValueHash (const FcValue *v)
2972c393a42Smrg{
298a6844aabSmrg    switch (v->type) {
2996fc018e4Smrg    case FcTypeUnknown:
3002c393a42Smrg    case FcTypeVoid:
3012c393a42Smrg	return 0;
3022c393a42Smrg    case FcTypeInteger:
3032c393a42Smrg	return (FcChar32) v->u.i;
3042c393a42Smrg    case FcTypeDouble:
3052c393a42Smrg	return FcDoubleHash (v->u.d);
3062c393a42Smrg    case FcTypeString:
307a6844aabSmrg	return FcStringHash (FcValueString(v));
3082c393a42Smrg    case FcTypeBool:
3092c393a42Smrg	return (FcChar32) v->u.b;
3102c393a42Smrg    case FcTypeMatrix:
311ca08ab68Smrg	return (FcDoubleHash (v->u.m->xx) ^
312ca08ab68Smrg		FcDoubleHash (v->u.m->xy) ^
313ca08ab68Smrg		FcDoubleHash (v->u.m->yx) ^
3142c393a42Smrg		FcDoubleHash (v->u.m->yy));
3152c393a42Smrg    case FcTypeCharSet:
316a6844aabSmrg	return (FcChar32) FcValueCharSet(v)->num;
3172c393a42Smrg    case FcTypeFTFace:
3182c393a42Smrg	return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
3192c393a42Smrg	       FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
3202c393a42Smrg    case FcTypeLangSet:
321a6844aabSmrg	return FcLangSetHash (FcValueLangSet(v));
3222c393a42Smrg    }
3236fc018e4Smrg    return 0;
3242c393a42Smrg}
3252c393a42Smrg
3262c393a42Smrgstatic FcBool
3272c393a42SmrgFcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
3282c393a42Smrg{
3292c393a42Smrg    if (la == lb)
3302c393a42Smrg	return FcTrue;
3312c393a42Smrg
3322c393a42Smrg    while (la && lb)
3332c393a42Smrg    {
3342c393a42Smrg	if (!FcValueEqual (la->value, lb->value))
3352c393a42Smrg	    return FcFalse;
3362c393a42Smrg	la = FcValueListNext(la);
3372c393a42Smrg	lb = FcValueListNext(lb);
3382c393a42Smrg    }
3392c393a42Smrg    if (la || lb)
3402c393a42Smrg	return FcFalse;
3412c393a42Smrg    return FcTrue;
3422c393a42Smrg}
3432c393a42Smrg
3442c393a42Smrgstatic FcChar32
3452c393a42SmrgFcValueListHash (FcValueListPtr l)
3462c393a42Smrg{
3472c393a42Smrg    FcChar32	hash = 0;
348ca08ab68Smrg
3492c393a42Smrg    for (; l; l = FcValueListNext(l))
3502c393a42Smrg    {
3512c393a42Smrg	hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
3522c393a42Smrg    }
3532c393a42Smrg    return hash;
3542c393a42Smrg}
3552c393a42Smrg
3562c393a42Smrgvoid
3572c393a42SmrgFcPatternDestroy (FcPattern *p)
3582c393a42Smrg{
3592c393a42Smrg    int		    i;
3602c393a42Smrg    FcPatternElt    *elts;
361ca08ab68Smrg
362c9710b42Smrg    if (!p)
363c9710b42Smrg	return;
364c9710b42Smrg
365c9710b42Smrg    if (FcRefIsConst (&p->ref))
3662c393a42Smrg    {
3672c393a42Smrg	FcCacheObjectDereference (p);
3682c393a42Smrg	return;
3692c393a42Smrg    }
3702c393a42Smrg
371c9710b42Smrg    if (FcRefDec (&p->ref) != 1)
3722c393a42Smrg	return;
3732c393a42Smrg
3742c393a42Smrg    elts = FcPatternElts (p);
3752c393a42Smrg    for (i = 0; i < p->num; i++)
3762c393a42Smrg	FcValueListDestroy (FcPatternEltValues(&elts[i]));
3772c393a42Smrg
3782c393a42Smrg    free (elts);
3792c393a42Smrg    free (p);
3802c393a42Smrg}
3812c393a42Smrg
3822c393a42Smrgstatic int
3832c393a42SmrgFcPatternObjectPosition (const FcPattern *p, FcObject object)
3842c393a42Smrg{
3852c393a42Smrg    int	    low, high, mid, c;
3862c393a42Smrg    FcPatternElt    *elts = FcPatternElts(p);
3872c393a42Smrg
3882c393a42Smrg    low = 0;
3892c393a42Smrg    high = p->num - 1;
3902c393a42Smrg    c = 1;
3912c393a42Smrg    mid = 0;
3922c393a42Smrg    while (low <= high)
3932c393a42Smrg    {
3942c393a42Smrg	mid = (low + high) >> 1;
3952c393a42Smrg	c = elts[mid].object - object;
3962c393a42Smrg	if (c == 0)
3972c393a42Smrg	    return mid;
3982c393a42Smrg	if (c < 0)
3992c393a42Smrg	    low = mid + 1;
4002c393a42Smrg	else
4012c393a42Smrg	    high = mid - 1;
4022c393a42Smrg    }
4032c393a42Smrg    if (c < 0)
4042c393a42Smrg	mid++;
4052c393a42Smrg    return -(mid + 1);
4062c393a42Smrg}
4072c393a42Smrg
4082c393a42SmrgFcPatternElt *
4092c393a42SmrgFcPatternObjectFindElt (const FcPattern *p, FcObject object)
4102c393a42Smrg{
4112c393a42Smrg    int	    i = FcPatternObjectPosition (p, object);
4122c393a42Smrg    if (i < 0)
4132c393a42Smrg	return 0;
4142c393a42Smrg    return &FcPatternElts(p)[i];
4152c393a42Smrg}
4162c393a42Smrg
4172c393a42SmrgFcPatternElt *
4182c393a42SmrgFcPatternObjectInsertElt (FcPattern *p, FcObject object)
4192c393a42Smrg{
4202c393a42Smrg    int		    i;
4212c393a42Smrg    FcPatternElt   *e;
422ca08ab68Smrg
4232c393a42Smrg    i = FcPatternObjectPosition (p, object);
4242c393a42Smrg    if (i < 0)
4252c393a42Smrg    {
4262c393a42Smrg	i = -i - 1;
427ca08ab68Smrg
4282c393a42Smrg	/* reallocate array */
4292c393a42Smrg	if (p->num + 1 >= p->size)
4302c393a42Smrg	{
4312c393a42Smrg	    int s = p->size + 16;
4322c393a42Smrg	    if (p->size)
4332c393a42Smrg	    {
4342c393a42Smrg		FcPatternElt *e0 = FcPatternElts(p);
4352c393a42Smrg		e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
4362c393a42Smrg		if (!e) /* maybe it was mmapped */
4372c393a42Smrg		{
4382c393a42Smrg		    e = malloc(s * sizeof (FcPatternElt));
4392c393a42Smrg		    if (e)
4402c393a42Smrg			memcpy(e, e0, p->num * sizeof (FcPatternElt));
4412c393a42Smrg		}
4422c393a42Smrg	    }
4432c393a42Smrg	    else
4442c393a42Smrg		e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
4452c393a42Smrg	    if (!e)
4462c393a42Smrg		return FcFalse;
4472c393a42Smrg	    p->elts_offset = FcPtrToOffset (p, e);
4482c393a42Smrg	    while (p->size < s)
4492c393a42Smrg	    {
4502c393a42Smrg		e[p->size].object = 0;
4512c393a42Smrg		e[p->size].values = NULL;
4522c393a42Smrg		p->size++;
4532c393a42Smrg	    }
4542c393a42Smrg	}
4552c393a42Smrg
4562c393a42Smrg	e = FcPatternElts(p);
4572c393a42Smrg	/* move elts up */
4582c393a42Smrg	memmove (e + i + 1,
4592c393a42Smrg		 e + i,
4602c393a42Smrg		 sizeof (FcPatternElt) *
4612c393a42Smrg		 (p->num - i));
462ca08ab68Smrg
4632c393a42Smrg	/* bump count */
4642c393a42Smrg	p->num++;
4652c393a42Smrg
4662c393a42Smrg	e[i].object = object;
4672c393a42Smrg	e[i].values = NULL;
4682c393a42Smrg    }
469ca08ab68Smrg
4702c393a42Smrg    return FcPatternElts(p) + i;
4712c393a42Smrg}
4722c393a42Smrg
4732c393a42SmrgFcBool
4742c393a42SmrgFcPatternEqual (const FcPattern *pa, const FcPattern *pb)
4752c393a42Smrg{
4762c393a42Smrg    int	i;
4772c393a42Smrg    FcPatternElt   *pae, *pbe;
4782c393a42Smrg
4792c393a42Smrg    if (pa == pb)
4802c393a42Smrg	return FcTrue;
4812c393a42Smrg
4822c393a42Smrg    if (pa->num != pb->num)
4832c393a42Smrg	return FcFalse;
4842c393a42Smrg    pae = FcPatternElts(pa);
4852c393a42Smrg    pbe = FcPatternElts(pb);
4862c393a42Smrg    for (i = 0; i < pa->num; i++)
4872c393a42Smrg    {
4882c393a42Smrg	if (pae[i].object != pbe[i].object)
4892c393a42Smrg	    return FcFalse;
4902c393a42Smrg	if (!FcValueListEqual (FcPatternEltValues(&pae[i]),
4912c393a42Smrg			       FcPatternEltValues(&pbe[i])))
4922c393a42Smrg	    return FcFalse;
4932c393a42Smrg    }
4942c393a42Smrg    return FcTrue;
4952c393a42Smrg}
4962c393a42Smrg
4972c393a42SmrgFcChar32
4982c393a42SmrgFcPatternHash (const FcPattern *p)
4992c393a42Smrg{
5002c393a42Smrg    int		i;
5012c393a42Smrg    FcChar32	h = 0;
5022c393a42Smrg    FcPatternElt    *pe = FcPatternElts(p);
5032c393a42Smrg
5042c393a42Smrg    for (i = 0; i < p->num; i++)
5052c393a42Smrg    {
506ca08ab68Smrg	h = (((h << 1) | (h >> 31)) ^
5072c393a42Smrg	     pe[i].object ^
5082c393a42Smrg	     FcValueListHash (FcPatternEltValues(&pe[i])));
5092c393a42Smrg    }
5102c393a42Smrg    return h;
5112c393a42Smrg}
5122c393a42Smrg
5132c393a42SmrgFcBool
5142c393a42SmrgFcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
5152c393a42Smrg{
5162c393a42Smrg    FcPatternElt    *ea, *eb;
5172c393a42Smrg    int		    i;
518ca08ab68Smrg
5192c393a42Smrg    for (i = 0; i < os->nobject; i++)
5202c393a42Smrg    {
5212c393a42Smrg	FcObject    object = FcObjectFromName (os->objects[i]);
5222c393a42Smrg	ea = FcPatternObjectFindElt (pai, object);
5232c393a42Smrg	eb = FcPatternObjectFindElt (pbi, object);
5242c393a42Smrg	if (ea)
5252c393a42Smrg	{
5262c393a42Smrg	    if (!eb)
5272c393a42Smrg		return FcFalse;
5282c393a42Smrg	    if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
5292c393a42Smrg		return FcFalse;
5302c393a42Smrg	}
5312c393a42Smrg	else
5322c393a42Smrg	{
5332c393a42Smrg	    if (eb)
5342c393a42Smrg		return FcFalse;
5352c393a42Smrg	}
5362c393a42Smrg    }
5372c393a42Smrg    return FcTrue;
5382c393a42Smrg}
5392c393a42Smrg
540ca08ab68SmrgFcBool
541ca08ab68SmrgFcPatternObjectListAdd (FcPattern	*p,
542ca08ab68Smrg			FcObject	object,
543ca08ab68Smrg			FcValueListPtr	list,
544ca08ab68Smrg			FcBool		append)
545ca08ab68Smrg{
546ca08ab68Smrg    FcPatternElt   *e;
547ca08ab68Smrg    FcValueListPtr l, *prev;
548ca08ab68Smrg
549c9710b42Smrg    if (FcRefIsConst (&p->ref))
550ca08ab68Smrg	goto bail0;
551ca08ab68Smrg
552ca08ab68Smrg    /*
553ca08ab68Smrg     * Make sure the stored type is valid for built-in objects
554ca08ab68Smrg     */
555ca08ab68Smrg    for (l = list; l != NULL; l = FcValueListNext (l))
556ca08ab68Smrg    {
557ca08ab68Smrg	if (!FcObjectValidType (object, l->value.type))
558ca08ab68Smrg	{
559c9710b42Smrg	    fprintf (stderr,
560c9710b42Smrg		     "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
561c9710b42Smrg	    FcValuePrintFile (stderr, l->value);
562c9710b42Smrg	    fprintf (stderr, "\n");
563ca08ab68Smrg	    goto bail0;
564ca08ab68Smrg	}
565ca08ab68Smrg    }
566ca08ab68Smrg
567ca08ab68Smrg    e = FcPatternObjectInsertElt (p, object);
568ca08ab68Smrg    if (!e)
569ca08ab68Smrg	goto bail0;
570ca08ab68Smrg
571ca08ab68Smrg    if (append)
572ca08ab68Smrg    {
573ca08ab68Smrg	for (prev = &e->values; *prev; prev = &(*prev)->next)
574ca08ab68Smrg	    ;
575ca08ab68Smrg	*prev = list;
576ca08ab68Smrg    }
577ca08ab68Smrg    else
578ca08ab68Smrg    {
579ca08ab68Smrg	for (prev = &list; *prev; prev = &(*prev)->next)
580ca08ab68Smrg	    ;
581ca08ab68Smrg	*prev = e->values;
582ca08ab68Smrg	e->values = list;
583ca08ab68Smrg    }
584ca08ab68Smrg
585ca08ab68Smrg    return FcTrue;
586ca08ab68Smrg
587ca08ab68Smrgbail0:
588ca08ab68Smrg    return FcFalse;
589ca08ab68Smrg}
590ca08ab68Smrg
5912c393a42SmrgFcBool
5922c393a42SmrgFcPatternObjectAddWithBinding  (FcPattern	*p,
5932c393a42Smrg				FcObject	object,
5942c393a42Smrg				FcValue		value,
5952c393a42Smrg				FcValueBinding  binding,
5962c393a42Smrg				FcBool		append)
5972c393a42Smrg{
5982c393a42Smrg    FcPatternElt   *e;
5992c393a42Smrg    FcValueListPtr new, *prev;
6002c393a42Smrg
601c9710b42Smrg    if (FcRefIsConst (&p->ref))
6022c393a42Smrg	goto bail0;
6032c393a42Smrg
604ca08ab68Smrg    new = FcValueListCreate ();
6052c393a42Smrg    if (!new)
6062c393a42Smrg	goto bail0;
6072c393a42Smrg
608a6844aabSmrg    value = FcValueSave (value);
6092c393a42Smrg    if (value.type == FcTypeVoid)
6102c393a42Smrg	goto bail1;
6112c393a42Smrg
6122c393a42Smrg    /*
6132c393a42Smrg     * Make sure the stored type is valid for built-in objects
6142c393a42Smrg     */
6152c393a42Smrg    if (!FcObjectValidType (object, value.type))
6162c393a42Smrg    {
617c9710b42Smrg	fprintf (stderr,
618c9710b42Smrg		 "Fontconfig warning: FcPattern object %s does not accept value",
619c9710b42Smrg		 FcObjectName (object));
620c9710b42Smrg	FcValuePrintFile (stderr, value);
621c9710b42Smrg	fprintf (stderr, "\n");
6222c393a42Smrg	goto bail1;
6232c393a42Smrg    }
6242c393a42Smrg
6252c393a42Smrg    new->value = value;
6262c393a42Smrg    new->binding = binding;
6272c393a42Smrg    new->next = NULL;
628ca08ab68Smrg
6292c393a42Smrg    e = FcPatternObjectInsertElt (p, object);
6302c393a42Smrg    if (!e)
6312c393a42Smrg	goto bail2;
632ca08ab68Smrg
6332c393a42Smrg    if (append)
6342c393a42Smrg    {
6352c393a42Smrg	for (prev = &e->values; *prev; prev = &(*prev)->next)
6362c393a42Smrg	    ;
6372c393a42Smrg	*prev = new;
6382c393a42Smrg    }
6392c393a42Smrg    else
6402c393a42Smrg    {
6412c393a42Smrg	new->next = e->values;
6422c393a42Smrg	e->values = new;
6432c393a42Smrg    }
644ca08ab68Smrg
6452c393a42Smrg    return FcTrue;
6462c393a42Smrg
647ca08ab68Smrgbail2:
6482c393a42Smrg    FcValueDestroy (value);
6492c393a42Smrgbail1:
6502c393a42Smrg    free (new);
6512c393a42Smrgbail0:
6522c393a42Smrg    return FcFalse;
6532c393a42Smrg}
6542c393a42Smrg
6552c393a42SmrgFcBool
6562c393a42SmrgFcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
6572c393a42Smrg{
6582c393a42Smrg    return FcPatternObjectAddWithBinding (p, object,
6592c393a42Smrg					  value, FcValueBindingStrong, append);
6602c393a42Smrg}
6612c393a42Smrg
6622c393a42SmrgFcBool
6632c393a42SmrgFcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
6642c393a42Smrg{
6652c393a42Smrg    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
6662c393a42Smrg					  value, FcValueBindingStrong, append);
6672c393a42Smrg}
6682c393a42Smrg
6692c393a42SmrgFcBool
6702c393a42SmrgFcPatternAddWeak  (FcPattern *p, const char *object, FcValue value, FcBool append)
6712c393a42Smrg{
6722c393a42Smrg    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
6732c393a42Smrg					  value, FcValueBindingWeak, append);
6742c393a42Smrg}
6752c393a42Smrg
6762c393a42SmrgFcBool
6772c393a42SmrgFcPatternObjectDel (FcPattern *p, FcObject object)
6782c393a42Smrg{
6792c393a42Smrg    FcPatternElt   *e;
6802c393a42Smrg
6812c393a42Smrg    e = FcPatternObjectFindElt (p, object);
6822c393a42Smrg    if (!e)
6832c393a42Smrg	return FcFalse;
6842c393a42Smrg
6852c393a42Smrg    /* destroy value */
6862c393a42Smrg    FcValueListDestroy (e->values);
687ca08ab68Smrg
6882c393a42Smrg    /* shuffle existing ones down */
689ca08ab68Smrg    memmove (e, e+1,
690ca08ab68Smrg	     (FcPatternElts(p) + p->num - (e + 1)) *
6912c393a42Smrg	     sizeof (FcPatternElt));
6922c393a42Smrg    p->num--;
6932c393a42Smrg    e = FcPatternElts(p) + p->num;
6942c393a42Smrg    e->object = 0;
6952c393a42Smrg    e->values = NULL;
6962c393a42Smrg    return FcTrue;
6972c393a42Smrg}
6982c393a42Smrg
6992c393a42SmrgFcBool
7002c393a42SmrgFcPatternDel (FcPattern *p, const char *object)
7012c393a42Smrg{
7022c393a42Smrg    return FcPatternObjectDel (p, FcObjectFromName (object));
7032c393a42Smrg}
704ca08ab68Smrg
7052c393a42SmrgFcBool
7062c393a42SmrgFcPatternRemove (FcPattern *p, const char *object, int id)
7072c393a42Smrg{
7082c393a42Smrg    FcPatternElt    *e;
7092c393a42Smrg    FcValueListPtr  *prev, l;
7102c393a42Smrg
7112c393a42Smrg    e = FcPatternObjectFindElt (p, FcObjectFromName (object));
7122c393a42Smrg    if (!e)
7132c393a42Smrg	return FcFalse;
7142c393a42Smrg    for (prev = &e->values; (l = *prev); prev = &l->next)
7152c393a42Smrg    {
7162c393a42Smrg	if (!id)
7172c393a42Smrg	{
7182c393a42Smrg	    *prev = l->next;
7192c393a42Smrg	    l->next = NULL;
7202c393a42Smrg	    FcValueListDestroy (l);
7212c393a42Smrg	    if (!e->values)
7222c393a42Smrg		FcPatternDel (p, object);
7232c393a42Smrg	    return FcTrue;
7242c393a42Smrg	}
7252c393a42Smrg	id--;
7262c393a42Smrg    }
7272c393a42Smrg    return FcFalse;
7282c393a42Smrg}
7292c393a42Smrg
7302c393a42SmrgFcBool
7312c393a42SmrgFcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
7322c393a42Smrg{
7332c393a42Smrg    FcValue	v;
7342c393a42Smrg
7352c393a42Smrg    v.type = FcTypeInteger;
7362c393a42Smrg    v.u.i = i;
7372c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
7382c393a42Smrg}
7392c393a42Smrg
7402c393a42SmrgFcBool
7412c393a42SmrgFcPatternAddInteger (FcPattern *p, const char *object, int i)
7422c393a42Smrg{
7432c393a42Smrg    return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
7442c393a42Smrg}
7452c393a42Smrg
7462c393a42SmrgFcBool
7472c393a42SmrgFcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
7482c393a42Smrg{
7492c393a42Smrg    FcValue	v;
7502c393a42Smrg
7512c393a42Smrg    v.type = FcTypeDouble;
7522c393a42Smrg    v.u.d = d;
7532c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
7542c393a42Smrg}
7552c393a42Smrg
7562c393a42Smrg
7572c393a42SmrgFcBool
7582c393a42SmrgFcPatternAddDouble (FcPattern *p, const char *object, double d)
7592c393a42Smrg{
7602c393a42Smrg    return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
7612c393a42Smrg}
7622c393a42Smrg
7632c393a42SmrgFcBool
7642c393a42SmrgFcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
7652c393a42Smrg{
7662c393a42Smrg    FcValue	v;
7672c393a42Smrg
7682c393a42Smrg    if (!s)
7692c393a42Smrg    {
7702c393a42Smrg	v.type = FcTypeVoid;
7712c393a42Smrg	v.u.s = 0;
7722c393a42Smrg	return FcPatternObjectAdd (p, object, v, FcTrue);
7732c393a42Smrg    }
7742c393a42Smrg
7752c393a42Smrg    v.type = FcTypeString;
776ca08ab68Smrg    v.u.s = s;
7772c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
7782c393a42Smrg}
7792c393a42Smrg
7802c393a42SmrgFcBool
7812c393a42SmrgFcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
7822c393a42Smrg{
7832c393a42Smrg    return FcPatternObjectAddString (p, FcObjectFromName (object), s);
7842c393a42Smrg}
7852c393a42Smrg
7862c393a42SmrgFcBool
7872c393a42SmrgFcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
7882c393a42Smrg{
7892c393a42Smrg    FcValue	v;
7902c393a42Smrg
7912c393a42Smrg    v.type = FcTypeMatrix;
7922c393a42Smrg    v.u.m = s;
7932c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
7942c393a42Smrg}
7952c393a42Smrg
7962c393a42Smrg
7972c393a42SmrgFcBool
7982c393a42SmrgFcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
7992c393a42Smrg{
8002c393a42Smrg    FcValue	v;
8012c393a42Smrg
8022c393a42Smrg    v.type = FcTypeBool;
8032c393a42Smrg    v.u.b = b;
8042c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
8052c393a42Smrg}
8062c393a42Smrg
8072c393a42SmrgFcBool
8082c393a42SmrgFcPatternAddBool (FcPattern *p, const char *object, FcBool b)
8092c393a42Smrg{
8102c393a42Smrg    return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
8112c393a42Smrg}
8122c393a42Smrg
8132c393a42SmrgFcBool
8142c393a42SmrgFcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
8152c393a42Smrg{
8162c393a42Smrg    FcValue	v;
8172c393a42Smrg
8182c393a42Smrg    v.type = FcTypeCharSet;
8192c393a42Smrg    v.u.c = (FcCharSet *)c;
8202c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8212c393a42Smrg}
8222c393a42Smrg
8232c393a42SmrgFcBool
8242c393a42SmrgFcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
8252c393a42Smrg{
8262c393a42Smrg    FcValue	v;
8272c393a42Smrg
8282c393a42Smrg    v.type = FcTypeFTFace;
8292c393a42Smrg    v.u.f = (void *) f;
8302c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8312c393a42Smrg}
8322c393a42Smrg
8332c393a42SmrgFcBool
8342c393a42SmrgFcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
8352c393a42Smrg{
8362c393a42Smrg    FcValue	v;
8372c393a42Smrg
8382c393a42Smrg    v.type = FcTypeLangSet;
8392c393a42Smrg    v.u.l = (FcLangSet *)ls;
8402c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8412c393a42Smrg}
8422c393a42Smrg
8432c393a42SmrgFcResult
8442c393a42SmrgFcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
8452c393a42Smrg{
8462c393a42Smrg    FcPatternElt   *e;
8472c393a42Smrg    FcValueListPtr l;
8482c393a42Smrg
849c9710b42Smrg    if (!p)
850c9710b42Smrg	return FcResultNoMatch;
8512c393a42Smrg    e = FcPatternObjectFindElt (p, object);
8522c393a42Smrg    if (!e)
8532c393a42Smrg	return FcResultNoMatch;
8542c393a42Smrg    for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
8552c393a42Smrg    {
8562c393a42Smrg	if (!id)
8572c393a42Smrg	{
8582c393a42Smrg	    *v = FcValueCanonicalize(&l->value);
8592c393a42Smrg	    return FcResultMatch;
8602c393a42Smrg	}
8612c393a42Smrg	id--;
8622c393a42Smrg    }
8632c393a42Smrg    return FcResultNoId;
8642c393a42Smrg}
8652c393a42Smrg
8662c393a42SmrgFcResult
8672c393a42SmrgFcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
8682c393a42Smrg{
8692c393a42Smrg    return FcPatternObjectGet (p, FcObjectFromName (object), id, v);
8702c393a42Smrg}
8712c393a42Smrg
8722c393a42SmrgFcResult
8732c393a42SmrgFcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
8742c393a42Smrg{
8752c393a42Smrg    FcValue	v;
8762c393a42Smrg    FcResult	r;
8772c393a42Smrg
8782c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
8792c393a42Smrg    if (r != FcResultMatch)
8802c393a42Smrg	return r;
881c9710b42Smrg    switch ((int) v.type) {
8822c393a42Smrg    case FcTypeDouble:
8832c393a42Smrg	*i = (int) v.u.d;
8842c393a42Smrg	break;
8852c393a42Smrg    case FcTypeInteger:
8862c393a42Smrg	*i = v.u.i;
8872c393a42Smrg	break;
8882c393a42Smrg    default:
8892c393a42Smrg        return FcResultTypeMismatch;
8902c393a42Smrg    }
8912c393a42Smrg    return FcResultMatch;
8922c393a42Smrg}
8932c393a42Smrg
8942c393a42SmrgFcResult
8952c393a42SmrgFcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
8962c393a42Smrg{
8972c393a42Smrg    return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
8982c393a42Smrg}
899ca08ab68Smrg
900ca08ab68Smrg
9012c393a42SmrgFcResult
9022c393a42SmrgFcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
9032c393a42Smrg{
9042c393a42Smrg    FcValue	v;
9052c393a42Smrg    FcResult	r;
9062c393a42Smrg
9072c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
9082c393a42Smrg    if (r != FcResultMatch)
9092c393a42Smrg	return r;
910c9710b42Smrg    switch ((int) v.type) {
9112c393a42Smrg    case FcTypeDouble:
9122c393a42Smrg	*d = v.u.d;
9132c393a42Smrg	break;
9142c393a42Smrg    case FcTypeInteger:
9152c393a42Smrg	*d = (double) v.u.i;
9162c393a42Smrg	break;
9172c393a42Smrg    default:
9182c393a42Smrg        return FcResultTypeMismatch;
9192c393a42Smrg    }
9202c393a42Smrg    return FcResultMatch;
9212c393a42Smrg}
9222c393a42Smrg
9232c393a42SmrgFcResult
9242c393a42SmrgFcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
9252c393a42Smrg{
9262c393a42Smrg    return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
9272c393a42Smrg}
9282c393a42Smrg
9292c393a42SmrgFcResult
9302c393a42SmrgFcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
9312c393a42Smrg{
9322c393a42Smrg    FcValue	v;
9332c393a42Smrg    FcResult	r;
9342c393a42Smrg
9352c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
9362c393a42Smrg    if (r != FcResultMatch)
9372c393a42Smrg	return r;
9382c393a42Smrg    if (v.type != FcTypeString)
9392c393a42Smrg        return FcResultTypeMismatch;
9402c393a42Smrg
9412c393a42Smrg    *s = (FcChar8 *) v.u.s;
9422c393a42Smrg    return FcResultMatch;
9432c393a42Smrg}
9442c393a42Smrg
9452c393a42SmrgFcResult
9462c393a42SmrgFcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
9472c393a42Smrg{
9482c393a42Smrg    return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
9492c393a42Smrg}
950ca08ab68Smrg
9512c393a42SmrgFcResult
9522c393a42SmrgFcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
9532c393a42Smrg{
9542c393a42Smrg    FcValue	v;
9552c393a42Smrg    FcResult	r;
9562c393a42Smrg
9572c393a42Smrg    r = FcPatternGet (p, object, id, &v);
9582c393a42Smrg    if (r != FcResultMatch)
9592c393a42Smrg	return r;
9602c393a42Smrg    if (v.type != FcTypeMatrix)
9612c393a42Smrg        return FcResultTypeMismatch;
9622c393a42Smrg    *m = (FcMatrix *)v.u.m;
9632c393a42Smrg    return FcResultMatch;
9642c393a42Smrg}
9652c393a42Smrg
9662c393a42Smrg
9672c393a42SmrgFcResult
9682c393a42SmrgFcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
9692c393a42Smrg{
9702c393a42Smrg    FcValue	v;
9712c393a42Smrg    FcResult	r;
9722c393a42Smrg
9732c393a42Smrg    r = FcPatternGet (p, object, id, &v);
9742c393a42Smrg    if (r != FcResultMatch)
9752c393a42Smrg	return r;
9762c393a42Smrg    if (v.type != FcTypeBool)
9772c393a42Smrg        return FcResultTypeMismatch;
9782c393a42Smrg    *b = v.u.b;
9792c393a42Smrg    return FcResultMatch;
9802c393a42Smrg}
9812c393a42Smrg
9822c393a42SmrgFcResult
9832c393a42SmrgFcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
9842c393a42Smrg{
9852c393a42Smrg    FcValue	v;
9862c393a42Smrg    FcResult	r;
9872c393a42Smrg
9882c393a42Smrg    r = FcPatternGet (p, object, id, &v);
9892c393a42Smrg    if (r != FcResultMatch)
9902c393a42Smrg	return r;
9912c393a42Smrg    if (v.type != FcTypeCharSet)
9922c393a42Smrg        return FcResultTypeMismatch;
9932c393a42Smrg    *c = (FcCharSet *)v.u.c;
9942c393a42Smrg    return FcResultMatch;
9952c393a42Smrg}
9962c393a42Smrg
9972c393a42SmrgFcResult
9982c393a42SmrgFcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
9992c393a42Smrg{
10002c393a42Smrg    FcValue	v;
10012c393a42Smrg    FcResult	r;
10022c393a42Smrg
10032c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10042c393a42Smrg    if (r != FcResultMatch)
10052c393a42Smrg	return r;
10062c393a42Smrg    if (v.type != FcTypeFTFace)
10072c393a42Smrg	return FcResultTypeMismatch;
10082c393a42Smrg    *f = (FT_Face) v.u.f;
10092c393a42Smrg    return FcResultMatch;
10102c393a42Smrg}
10112c393a42Smrg
10122c393a42SmrgFcResult
10132c393a42SmrgFcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
10142c393a42Smrg{
10152c393a42Smrg    FcValue	v;
10162c393a42Smrg    FcResult	r;
10172c393a42Smrg
10182c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10192c393a42Smrg    if (r != FcResultMatch)
10202c393a42Smrg	return r;
10212c393a42Smrg    if (v.type != FcTypeLangSet)
10222c393a42Smrg        return FcResultTypeMismatch;
10232c393a42Smrg    *ls = (FcLangSet *)v.u.l;
10242c393a42Smrg    return FcResultMatch;
10252c393a42Smrg}
10262c393a42Smrg
10272c393a42SmrgFcPattern *
10282c393a42SmrgFcPatternDuplicate (const FcPattern *orig)
10292c393a42Smrg{
10302c393a42Smrg    FcPattern	    *new;
10312c393a42Smrg    FcPatternElt    *e;
10322c393a42Smrg    int		    i;
10332c393a42Smrg    FcValueListPtr  l;
10342c393a42Smrg
10352c393a42Smrg    new = FcPatternCreate ();
10362c393a42Smrg    if (!new)
10372c393a42Smrg	goto bail0;
10382c393a42Smrg
10392c393a42Smrg    e = FcPatternElts(orig);
10402c393a42Smrg
10412c393a42Smrg    for (i = 0; i < orig->num; i++)
10422c393a42Smrg    {
10432c393a42Smrg	for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l))
10442c393a42Smrg	{
10452c393a42Smrg	    if (!FcPatternObjectAddWithBinding (new, e[i].object,
10462c393a42Smrg						FcValueCanonicalize(&l->value),
10472c393a42Smrg						l->binding,
10482c393a42Smrg						FcTrue))
10492c393a42Smrg		goto bail1;
1050ca08ab68Smrg
10512c393a42Smrg	}
10522c393a42Smrg    }
10532c393a42Smrg
10542c393a42Smrg    return new;
10552c393a42Smrg
10562c393a42Smrgbail1:
10572c393a42Smrg    FcPatternDestroy (new);
10582c393a42Smrgbail0:
10592c393a42Smrg    return 0;
10602c393a42Smrg}
10612c393a42Smrg
10622c393a42Smrgvoid
10632c393a42SmrgFcPatternReference (FcPattern *p)
10642c393a42Smrg{
1065c9710b42Smrg    if (!FcRefIsConst (&p->ref))
1066c9710b42Smrg	FcRefInc (&p->ref);
10672c393a42Smrg    else
10682c393a42Smrg	FcCacheObjectReference (p);
10692c393a42Smrg}
10702c393a42Smrg
10712c393a42SmrgFcPattern *
1072a6844aabSmrgFcPatternVaBuild (FcPattern *p, va_list va)
10732c393a42Smrg{
10742c393a42Smrg    FcPattern	*ret;
1075ca08ab68Smrg
1076a6844aabSmrg    FcPatternVapBuild (ret, p, va);
10772c393a42Smrg    return ret;
10782c393a42Smrg}
10792c393a42Smrg
10802c393a42SmrgFcPattern *
1081a6844aabSmrgFcPatternBuild (FcPattern *p, ...)
10822c393a42Smrg{
10832c393a42Smrg    va_list	va;
1084ca08ab68Smrg
1085a6844aabSmrg    va_start (va, p);
1086a6844aabSmrg    FcPatternVapBuild (p, p, va);
10872c393a42Smrg    va_end (va);
1088a6844aabSmrg    return p;
10892c393a42Smrg}
10902c393a42Smrg
10912c393a42Smrg/*
10922c393a42Smrg * Add all of the elements in 's' to 'p'
10932c393a42Smrg */
10942c393a42SmrgFcBool
10952c393a42SmrgFcPatternAppend (FcPattern *p, FcPattern *s)
10962c393a42Smrg{
10972c393a42Smrg    int		    i;
10982c393a42Smrg    FcPatternElt    *e;
10992c393a42Smrg    FcValueListPtr  v;
1100ca08ab68Smrg
11012c393a42Smrg    for (i = 0; i < s->num; i++)
11022c393a42Smrg    {
11032c393a42Smrg	e = FcPatternElts(s)+i;
11042c393a42Smrg	for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
11052c393a42Smrg	{
11062c393a42Smrg	    if (!FcPatternObjectAddWithBinding (p, e->object,
1107ca08ab68Smrg						FcValueCanonicalize(&v->value),
11082c393a42Smrg						v->binding, FcTrue))
11092c393a42Smrg		return FcFalse;
11102c393a42Smrg	}
11112c393a42Smrg    }
11122c393a42Smrg    return FcTrue;
11132c393a42Smrg}
11142c393a42Smrg
1115a6844aabSmrgFcPattern *
1116a6844aabSmrgFcPatternFilter (FcPattern *p, const FcObjectSet *os)
1117a6844aabSmrg{
1118a6844aabSmrg    int		    i;
1119a6844aabSmrg    FcPattern	    *ret;
1120a6844aabSmrg    FcPatternElt    *e;
1121a6844aabSmrg    FcValueListPtr  v;
1122a6844aabSmrg
1123a6844aabSmrg    if (!os)
1124a6844aabSmrg	return FcPatternDuplicate (p);
1125a6844aabSmrg
1126a6844aabSmrg    ret = FcPatternCreate ();
1127a6844aabSmrg    if (!ret)
1128a6844aabSmrg	return NULL;
1129a6844aabSmrg
1130a6844aabSmrg    for (i = 0; i < os->nobject; i++)
1131a6844aabSmrg    {
1132a6844aabSmrg	FcObject object = FcObjectFromName (os->objects[i]);
1133a6844aabSmrg	e = FcPatternObjectFindElt (p, object);
1134a6844aabSmrg	if (e)
1135a6844aabSmrg	{
1136a6844aabSmrg	    for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1137a6844aabSmrg	    {
1138a6844aabSmrg		if (!FcPatternObjectAddWithBinding (ret, e->object,
1139a6844aabSmrg						    FcValueCanonicalize(&v->value),
1140a6844aabSmrg						    v->binding, FcTrue))
1141a6844aabSmrg		    goto bail0;
1142a6844aabSmrg	    }
1143a6844aabSmrg	}
1144a6844aabSmrg    }
1145a6844aabSmrg    return ret;
1146a6844aabSmrg
1147a6844aabSmrgbail0:
1148a6844aabSmrg    FcPatternDestroy (ret);
1149a6844aabSmrg    return NULL;
1150a6844aabSmrg}
1151a6844aabSmrg
11522c393a42Smrg
11532c393a42SmrgFcBool
11542c393a42SmrgFcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
11552c393a42Smrg{
11562c393a42Smrg    int	i;
11572c393a42Smrg    FcPatternElt    *elts = FcPatternElts(pat);
1158ca08ab68Smrg
11592c393a42Smrg    if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
11602c393a42Smrg	return FcFalse;
11612c393a42Smrg    if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt)))
11622c393a42Smrg	return FcFalse;
11632c393a42Smrg    for (i = 0; i < pat->num; i++)
11642c393a42Smrg	if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
11652c393a42Smrg	    return FcFalse;
11662c393a42Smrg    return FcTrue;
11672c393a42Smrg}
11682c393a42Smrg
11692c393a42SmrgFcPattern *
11702c393a42SmrgFcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
11712c393a42Smrg{
11722c393a42Smrg    FcPattern	    *pat_serialized;
11732c393a42Smrg    FcPatternElt    *elts = FcPatternElts (pat);
11742c393a42Smrg    FcPatternElt    *elts_serialized;
11752c393a42Smrg    FcValueList	    *values_serialized;
11762c393a42Smrg    int		    i;
11772c393a42Smrg
11782c393a42Smrg    pat_serialized = FcSerializePtr (serialize, pat);
11792c393a42Smrg    if (!pat_serialized)
11802c393a42Smrg	return NULL;
11812c393a42Smrg    *pat_serialized = *pat;
11822c393a42Smrg    pat_serialized->size = pat->num;
1183c9710b42Smrg    FcRefSetConst (&pat_serialized->ref);
1184ca08ab68Smrg
11852c393a42Smrg    elts_serialized = FcSerializePtr (serialize, elts);
11862c393a42Smrg    if (!elts_serialized)
11872c393a42Smrg	return NULL;
1188ca08ab68Smrg
11892c393a42Smrg    pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
11902c393a42Smrg						 elts_serialized);
11912c393a42Smrg
11922c393a42Smrg    for (i = 0; i < pat->num; i++)
11932c393a42Smrg    {
11942c393a42Smrg	values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
11952c393a42Smrg	if (!values_serialized)
11962c393a42Smrg	    return NULL;
11972c393a42Smrg	elts_serialized[i].object = elts[i].object;
1198ca08ab68Smrg	elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
11992c393a42Smrg							  values_serialized,
12002c393a42Smrg							  FcValueList);
12012c393a42Smrg    }
12022c393a42Smrg    if (FcDebug() & FC_DBG_CACHEV) {
12032c393a42Smrg	printf ("Raw pattern:\n");
12042c393a42Smrg	FcPatternPrint (pat);
12052c393a42Smrg	printf ("Serialized pattern:\n");
12062c393a42Smrg	FcPatternPrint (pat_serialized);
12072c393a42Smrg	printf ("\n");
12082c393a42Smrg    }
12092c393a42Smrg    return pat_serialized;
12102c393a42Smrg}
12112c393a42Smrg
12122c393a42SmrgFcBool
12132c393a42SmrgFcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
12142c393a42Smrg{
12152c393a42Smrg    while (vl)
12162c393a42Smrg    {
12172c393a42Smrg	if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
12182c393a42Smrg	    return FcFalse;
1219c9710b42Smrg	switch ((int) vl->value.type) {
12202c393a42Smrg	case FcTypeString:
12212c393a42Smrg	    if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
12222c393a42Smrg		return FcFalse;
12232c393a42Smrg	    break;
12242c393a42Smrg	case FcTypeCharSet:
12252c393a42Smrg	    if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
12262c393a42Smrg		return FcFalse;
12272c393a42Smrg	    break;
12282c393a42Smrg	case FcTypeLangSet:
12292c393a42Smrg	    if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
12302c393a42Smrg		return FcFalse;
12312c393a42Smrg	    break;
12322c393a42Smrg	default:
12332c393a42Smrg	    break;
12342c393a42Smrg	}
12352c393a42Smrg	vl = vl->next;
12362c393a42Smrg    }
12372c393a42Smrg    return FcTrue;
12382c393a42Smrg}
12392c393a42Smrg
12402c393a42SmrgFcValueList *
12412c393a42SmrgFcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
12422c393a42Smrg{
12432c393a42Smrg    FcValueList	*vl_serialized;
12442c393a42Smrg    FcChar8	*s_serialized;
12452c393a42Smrg    FcCharSet	*c_serialized;
12462c393a42Smrg    FcLangSet	*l_serialized;
12472c393a42Smrg    FcValueList	*head_serialized = NULL;
12482c393a42Smrg    FcValueList	*prev_serialized = NULL;
12492c393a42Smrg
12502c393a42Smrg    while (vl)
12512c393a42Smrg    {
12522c393a42Smrg	vl_serialized = FcSerializePtr (serialize, vl);
12532c393a42Smrg	if (!vl_serialized)
12542c393a42Smrg	    return NULL;
1255ca08ab68Smrg
12562c393a42Smrg	if (prev_serialized)
12572c393a42Smrg	    prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
12582c393a42Smrg							  vl_serialized,
12592c393a42Smrg							  FcValueList);
12602c393a42Smrg	else
12612c393a42Smrg	    head_serialized = vl_serialized;
12622c393a42Smrg
12632c393a42Smrg	vl_serialized->next = NULL;
12642c393a42Smrg	vl_serialized->value.type = vl->value.type;
1265c9710b42Smrg	switch ((int) vl->value.type) {
12662c393a42Smrg	case FcTypeInteger:
12672c393a42Smrg	    vl_serialized->value.u.i = vl->value.u.i;
12682c393a42Smrg	    break;
12692c393a42Smrg	case FcTypeDouble:
12702c393a42Smrg	    vl_serialized->value.u.d = vl->value.u.d;
12712c393a42Smrg	    break;
12722c393a42Smrg	case FcTypeString:
12732c393a42Smrg	    s_serialized = FcStrSerialize (serialize, vl->value.u.s);
12742c393a42Smrg	    if (!s_serialized)
12752c393a42Smrg		return NULL;
12762c393a42Smrg	    vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
12772c393a42Smrg							     s_serialized,
12782c393a42Smrg							     FcChar8);
12792c393a42Smrg	    break;
12802c393a42Smrg	case FcTypeBool:
12812c393a42Smrg	    vl_serialized->value.u.b = vl->value.u.b;
12822c393a42Smrg	    break;
12832c393a42Smrg	case FcTypeMatrix:
12842c393a42Smrg	    /* can't happen */
12852c393a42Smrg	    break;
12862c393a42Smrg	case FcTypeCharSet:
12872c393a42Smrg	    c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
12882c393a42Smrg	    if (!c_serialized)
12892c393a42Smrg		return NULL;
12902c393a42Smrg	    vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
12912c393a42Smrg							     c_serialized,
12922c393a42Smrg							     FcCharSet);
12932c393a42Smrg	    break;
12942c393a42Smrg	case FcTypeFTFace:
12952c393a42Smrg	    /* can't happen */
12962c393a42Smrg	    break;
12972c393a42Smrg	case FcTypeLangSet:
12982c393a42Smrg	    l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
12992c393a42Smrg	    if (!l_serialized)
13002c393a42Smrg		return NULL;
13012c393a42Smrg	    vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
13022c393a42Smrg							     l_serialized,
13032c393a42Smrg							     FcLangSet);
13042c393a42Smrg	    break;
13052c393a42Smrg	default:
13062c393a42Smrg	    break;
13072c393a42Smrg	}
13082c393a42Smrg	prev_serialized = vl_serialized;
13092c393a42Smrg	vl = vl->next;
13102c393a42Smrg    }
13112c393a42Smrg    return head_serialized;
13122c393a42Smrg}
13132c393a42Smrg#define __fcpat__
13142c393a42Smrg#include "fcaliastail.h"
13152c393a42Smrg#include "fcftaliastail.h"
13162c393a42Smrg#undef __fcpat__
1317