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    {
145a4e54154Smrg	FcValueDestroy (l->value);
1462c393a42Smrg	next = FcValueListNext(l);
1472c393a42Smrg	free(l);
1482c393a42Smrg    }
1492c393a42Smrg}
1502c393a42Smrg
151ca08ab68SmrgFcValueListPtr
152ca08ab68SmrgFcValueListPrepend (FcValueListPtr vallist,
153ca08ab68Smrg		    FcValue        value,
154ca08ab68Smrg		    FcValueBinding binding)
155ca08ab68Smrg{
156ca08ab68Smrg    FcValueListPtr new;
157ca08ab68Smrg
158ca08ab68Smrg    if (value.type == FcTypeVoid)
159ca08ab68Smrg	return vallist;
160ca08ab68Smrg    new = FcValueListCreate ();
161ca08ab68Smrg    if (!new)
162ca08ab68Smrg	return vallist;
163ca08ab68Smrg
164ca08ab68Smrg    new->value = FcValueSave (value);
165ca08ab68Smrg    new->binding = binding;
166ca08ab68Smrg    new->next = vallist;
167ca08ab68Smrg
168ca08ab68Smrg    return new;
169ca08ab68Smrg}
170ca08ab68Smrg
171ca08ab68SmrgFcValueListPtr
172ca08ab68SmrgFcValueListAppend (FcValueListPtr vallist,
173ca08ab68Smrg		   FcValue        value,
174ca08ab68Smrg		   FcValueBinding binding)
175ca08ab68Smrg{
176ca08ab68Smrg    FcValueListPtr new, last;
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 = NULL;
187ca08ab68Smrg
188ca08ab68Smrg    if (vallist)
189ca08ab68Smrg    {
190ca08ab68Smrg	for (last = vallist; FcValueListNext (last); last = FcValueListNext (last));
191ca08ab68Smrg
192ca08ab68Smrg	last->next = new;
193ca08ab68Smrg    }
194ca08ab68Smrg    else
195ca08ab68Smrg	vallist = new;
196ca08ab68Smrg
197ca08ab68Smrg    return vallist;
198ca08ab68Smrg}
199ca08ab68Smrg
200ca08ab68SmrgFcValueListPtr
201ca08ab68SmrgFcValueListDuplicate(FcValueListPtr orig)
202ca08ab68Smrg{
203ca08ab68Smrg    FcValueListPtr new = NULL, l, t = NULL;
204ca08ab68Smrg    FcValue v;
205ca08ab68Smrg
206ca08ab68Smrg    for (l = orig; l != NULL; l = FcValueListNext (l))
207ca08ab68Smrg    {
208ca08ab68Smrg	if (!new)
209ca08ab68Smrg	{
210ca08ab68Smrg	    t = new = FcValueListCreate();
211ca08ab68Smrg	}
212ca08ab68Smrg	else
213ca08ab68Smrg	{
214ca08ab68Smrg	    t->next = FcValueListCreate();
215ca08ab68Smrg	    t = FcValueListNext (t);
216ca08ab68Smrg	}
217ca08ab68Smrg	v = FcValueCanonicalize (&l->value);
218ca08ab68Smrg	t->value = FcValueSave (v);
219ca08ab68Smrg	t->binding = l->binding;
220ca08ab68Smrg	t->next = NULL;
221ca08ab68Smrg    }
222ca08ab68Smrg
223ca08ab68Smrg    return new;
224ca08ab68Smrg}
225ca08ab68Smrg
2262c393a42SmrgFcBool
2272c393a42SmrgFcValueEqual (FcValue va, FcValue vb)
2282c393a42Smrg{
2292c393a42Smrg    if (va.type != vb.type)
2302c393a42Smrg    {
2312c393a42Smrg	if (va.type == FcTypeInteger)
2322c393a42Smrg	{
2332c393a42Smrg	    va.type = FcTypeDouble;
2342c393a42Smrg	    va.u.d = va.u.i;
2352c393a42Smrg	}
2362c393a42Smrg	if (vb.type == FcTypeInteger)
2372c393a42Smrg	{
2382c393a42Smrg	    vb.type = FcTypeDouble;
2392c393a42Smrg	    vb.u.d = vb.u.i;
2402c393a42Smrg	}
2412c393a42Smrg	if (va.type != vb.type)
2422c393a42Smrg	    return FcFalse;
2432c393a42Smrg    }
2442c393a42Smrg    switch (va.type) {
2456fc018e4Smrg    case FcTypeUnknown:
2466fc018e4Smrg	return FcFalse;	/* don't know how to compare this object */
2472c393a42Smrg    case FcTypeVoid:
2482c393a42Smrg	return FcTrue;
2492c393a42Smrg    case FcTypeInteger:
2502c393a42Smrg	return va.u.i == vb.u.i;
2512c393a42Smrg    case FcTypeDouble:
2522c393a42Smrg	return va.u.d == vb.u.d;
2532c393a42Smrg    case FcTypeString:
2542c393a42Smrg	return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
2552c393a42Smrg    case FcTypeBool:
2562c393a42Smrg	return va.u.b == vb.u.b;
2572c393a42Smrg    case FcTypeMatrix:
2582c393a42Smrg	return FcMatrixEqual (va.u.m, vb.u.m);
2592c393a42Smrg    case FcTypeCharSet:
2602c393a42Smrg	return FcCharSetEqual (va.u.c, vb.u.c);
2612c393a42Smrg    case FcTypeFTFace:
2622c393a42Smrg	return va.u.f == vb.u.f;
2632c393a42Smrg    case FcTypeLangSet:
2642c393a42Smrg	return FcLangSetEqual (va.u.l, vb.u.l);
265953daebaSmrg    case FcTypeRange:
266953daebaSmrg	return FcRangeIsInRange (va.u.r, vb.u.r);
2672c393a42Smrg    }
2682c393a42Smrg    return FcFalse;
2692c393a42Smrg}
2702c393a42Smrg
2712c393a42Smrgstatic FcChar32
2722c393a42SmrgFcDoubleHash (double d)
2732c393a42Smrg{
2742c393a42Smrg    if (d < 0)
2752c393a42Smrg	d = -d;
2762c393a42Smrg    if (d > 0xffffffff)
2772c393a42Smrg	d = 0xffffffff;
2782c393a42Smrg    return (FcChar32) d;
2792c393a42Smrg}
2802c393a42Smrg
2812c393a42SmrgFcChar32
2822c393a42SmrgFcStringHash (const FcChar8 *s)
2832c393a42Smrg{
2842c393a42Smrg    FcChar8	c;
2852c393a42Smrg    FcChar32	h = 0;
286ca08ab68Smrg
2872c393a42Smrg    if (s)
2882c393a42Smrg	while ((c = *s++))
2892c393a42Smrg	    h = ((h << 1) | (h >> 31)) ^ c;
2902c393a42Smrg    return h;
2912c393a42Smrg}
2922c393a42Smrg
2932c393a42Smrgstatic FcChar32
2942c393a42SmrgFcValueHash (const FcValue *v)
2952c393a42Smrg{
296a6844aabSmrg    switch (v->type) {
2976fc018e4Smrg    case FcTypeUnknown:
2982c393a42Smrg    case FcTypeVoid:
2992c393a42Smrg	return 0;
3002c393a42Smrg    case FcTypeInteger:
3012c393a42Smrg	return (FcChar32) v->u.i;
3022c393a42Smrg    case FcTypeDouble:
3032c393a42Smrg	return FcDoubleHash (v->u.d);
3042c393a42Smrg    case FcTypeString:
305a6844aabSmrg	return FcStringHash (FcValueString(v));
3062c393a42Smrg    case FcTypeBool:
3072c393a42Smrg	return (FcChar32) v->u.b;
3082c393a42Smrg    case FcTypeMatrix:
309ca08ab68Smrg	return (FcDoubleHash (v->u.m->xx) ^
310ca08ab68Smrg		FcDoubleHash (v->u.m->xy) ^
311ca08ab68Smrg		FcDoubleHash (v->u.m->yx) ^
3122c393a42Smrg		FcDoubleHash (v->u.m->yy));
3132c393a42Smrg    case FcTypeCharSet:
314a6844aabSmrg	return (FcChar32) FcValueCharSet(v)->num;
3152c393a42Smrg    case FcTypeFTFace:
3162c393a42Smrg	return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
3172c393a42Smrg	       FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
3182c393a42Smrg    case FcTypeLangSet:
319a6844aabSmrg	return FcLangSetHash (FcValueLangSet(v));
320953daebaSmrg    case FcTypeRange:
321a4e54154Smrg	return FcRangeHash (FcValueRange (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
356a32e9e42Smrgstatic void *
357a32e9e42SmrgFcPatternGetCacheObject (FcPattern *p)
358a32e9e42Smrg{
359a32e9e42Smrg  /* We use a value to find the cache, instead of the FcPattern object
360a32e9e42Smrg   * because the pattern itself may be a cache allocation if we rewrote the path,
361a32e9e42Smrg   * so the p may not be in the cached region. */
362a32e9e42Smrg  return FcPatternEltValues(&FcPatternElts (p)[0]);
363a32e9e42Smrg}
364a32e9e42Smrg
365a32e9e42SmrgFcPattern *
366a32e9e42SmrgFcPatternCacheRewriteFile (const FcPattern *p,
367a32e9e42Smrg                           FcCache *cache,
368a32e9e42Smrg                           const FcChar8 *relocated_font_file)
369a32e9e42Smrg{
370a32e9e42Smrg    FcPatternElt *elts = FcPatternElts (p);
371a32e9e42Smrg    size_t i,j;
372a32e9e42Smrg    FcChar8 *data;
373a32e9e42Smrg    FcPattern *new_p;
374a32e9e42Smrg    FcPatternElt *new_elts;
375a32e9e42Smrg    FcValueList *new_value_list;
376a32e9e42Smrg    size_t new_path_len = strlen ((char *)relocated_font_file);
377a32e9e42Smrg    FcChar8 *new_path;
378a32e9e42Smrg
379a32e9e42Smrg    /* Allocate space for the patter, the PatternElt headers and
380a32e9e42Smrg     * the FC_FILE FcValueList and path that will be freed with the
381a32e9e42Smrg     * cache */
382a32e9e42Smrg    data = FcCacheAllocate (cache,
383a32e9e42Smrg			    sizeof (FcPattern) +
384a32e9e42Smrg			    p->num * sizeof (FcPatternElt) +
385a32e9e42Smrg			    sizeof (FcValueList) +
386a32e9e42Smrg			    new_path_len + 1);
387a32e9e42Smrg
388a32e9e42Smrg    new_p = (FcPattern *)data;
389a32e9e42Smrg    data += sizeof (FcPattern);
390a32e9e42Smrg    new_elts = (FcPatternElt *)(data);
391a32e9e42Smrg    data += p->num * sizeof (FcPatternElt);
392a32e9e42Smrg    new_value_list = (FcValueList *)data;
393a32e9e42Smrg    data += sizeof (FcValueList);
394a32e9e42Smrg    new_path = data;
395a32e9e42Smrg
396a32e9e42Smrg    *new_p = *p;
397a32e9e42Smrg    new_p->elts_offset = FcPtrToOffset (new_p, new_elts);
398a32e9e42Smrg
399a32e9e42Smrg    /* Copy all but the FILE values from the cache */
400a32e9e42Smrg    for (i = 0, j = 0; i < p->num; i++)
401a32e9e42Smrg    {
402a32e9e42Smrg	FcPatternElt *elt = &elts[i];
403a32e9e42Smrg	new_elts[j].object = elt->object;
404a32e9e42Smrg	if (elt->object != FC_FILE_OBJECT)
405a32e9e42Smrg	    new_elts[j++].values = FcPatternEltValues(elt);
406a32e9e42Smrg	else
407a32e9e42Smrg	    new_elts[j++].values = new_value_list;
408a32e9e42Smrg    }
409a32e9e42Smrg
410a32e9e42Smrg    new_value_list->next = NULL;
411a32e9e42Smrg    new_value_list->value.type = FcTypeString;
412a32e9e42Smrg    new_value_list->value.u.s = new_path;
413a32e9e42Smrg    new_value_list->binding = FcValueBindingWeak;
414a32e9e42Smrg
415a32e9e42Smrg    /* Add rewritten path at the end */
416a32e9e42Smrg    strcpy ((char *)new_path, (char *)relocated_font_file);
417a32e9e42Smrg
418a32e9e42Smrg    return new_p;
419a32e9e42Smrg}
420a32e9e42Smrg
4212c393a42Smrgvoid
4222c393a42SmrgFcPatternDestroy (FcPattern *p)
4232c393a42Smrg{
4242c393a42Smrg    int		    i;
4252c393a42Smrg    FcPatternElt    *elts;
426ca08ab68Smrg
427c9710b42Smrg    if (!p)
428c9710b42Smrg	return;
429c9710b42Smrg
430c9710b42Smrg    if (FcRefIsConst (&p->ref))
4312c393a42Smrg    {
432a32e9e42Smrg	FcCacheObjectDereference (FcPatternGetCacheObject(p));
4332c393a42Smrg	return;
4342c393a42Smrg    }
435a32e9e42Smrg
436c9710b42Smrg    if (FcRefDec (&p->ref) != 1)
4372c393a42Smrg	return;
4382c393a42Smrg
4392c393a42Smrg    elts = FcPatternElts (p);
440a32e9e42Smrg    for (i = 0; i < FcPatternObjectCount (p); i++)
4412c393a42Smrg	FcValueListDestroy (FcPatternEltValues(&elts[i]));
4422c393a42Smrg
4432c393a42Smrg    free (elts);
4442c393a42Smrg    free (p);
4452c393a42Smrg}
4462c393a42Smrg
447a32e9e42Smrgint
448a32e9e42SmrgFcPatternObjectCount (const FcPattern *pat)
449a32e9e42Smrg{
450a32e9e42Smrg    if (pat)
451a32e9e42Smrg	return pat->num;
452a32e9e42Smrg
453a32e9e42Smrg    return 0;
454a32e9e42Smrg}
455a32e9e42Smrg
456a32e9e42Smrg
4572c393a42Smrgstatic int
4582c393a42SmrgFcPatternObjectPosition (const FcPattern *p, FcObject object)
4592c393a42Smrg{
4602c393a42Smrg    int	    low, high, mid, c;
4612c393a42Smrg    FcPatternElt    *elts = FcPatternElts(p);
4622c393a42Smrg
4632c393a42Smrg    low = 0;
464a32e9e42Smrg    high = FcPatternObjectCount (p) - 1;
4652c393a42Smrg    c = 1;
4662c393a42Smrg    mid = 0;
4672c393a42Smrg    while (low <= high)
4682c393a42Smrg    {
4692c393a42Smrg	mid = (low + high) >> 1;
4702c393a42Smrg	c = elts[mid].object - object;
4712c393a42Smrg	if (c == 0)
4722c393a42Smrg	    return mid;
4732c393a42Smrg	if (c < 0)
4742c393a42Smrg	    low = mid + 1;
4752c393a42Smrg	else
4762c393a42Smrg	    high = mid - 1;
4772c393a42Smrg    }
4782c393a42Smrg    if (c < 0)
4792c393a42Smrg	mid++;
4802c393a42Smrg    return -(mid + 1);
4812c393a42Smrg}
4822c393a42Smrg
483953daebaSmrgint
484953daebaSmrgFcPatternPosition (const FcPattern *p, const char *object)
485953daebaSmrg{
486953daebaSmrg    return FcPatternObjectPosition (p, FcObjectFromName (object));
487953daebaSmrg}
488953daebaSmrg
4892c393a42SmrgFcPatternElt *
4902c393a42SmrgFcPatternObjectFindElt (const FcPattern *p, FcObject object)
4912c393a42Smrg{
4922c393a42Smrg    int	    i = FcPatternObjectPosition (p, object);
4932c393a42Smrg    if (i < 0)
4942c393a42Smrg	return 0;
4952c393a42Smrg    return &FcPatternElts(p)[i];
4962c393a42Smrg}
4972c393a42Smrg
4982c393a42SmrgFcPatternElt *
4992c393a42SmrgFcPatternObjectInsertElt (FcPattern *p, FcObject object)
5002c393a42Smrg{
5012c393a42Smrg    int		    i;
5022c393a42Smrg    FcPatternElt   *e;
503ca08ab68Smrg
5042c393a42Smrg    i = FcPatternObjectPosition (p, object);
5052c393a42Smrg    if (i < 0)
5062c393a42Smrg    {
5072c393a42Smrg	i = -i - 1;
508ca08ab68Smrg
5092c393a42Smrg	/* reallocate array */
510a32e9e42Smrg	if (FcPatternObjectCount (p) + 1 >= p->size)
5112c393a42Smrg	{
5122c393a42Smrg	    int s = p->size + 16;
5132c393a42Smrg	    if (p->size)
5142c393a42Smrg	    {
5152c393a42Smrg		FcPatternElt *e0 = FcPatternElts(p);
5162c393a42Smrg		e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
5172c393a42Smrg		if (!e) /* maybe it was mmapped */
5182c393a42Smrg		{
5192c393a42Smrg		    e = malloc(s * sizeof (FcPatternElt));
5202c393a42Smrg		    if (e)
521a32e9e42Smrg			memcpy(e, e0, FcPatternObjectCount (p) * sizeof (FcPatternElt));
5222c393a42Smrg		}
5232c393a42Smrg	    }
5242c393a42Smrg	    else
5252c393a42Smrg		e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
5262c393a42Smrg	    if (!e)
5272c393a42Smrg		return FcFalse;
5282c393a42Smrg	    p->elts_offset = FcPtrToOffset (p, e);
5292c393a42Smrg	    while (p->size < s)
5302c393a42Smrg	    {
5312c393a42Smrg		e[p->size].object = 0;
5322c393a42Smrg		e[p->size].values = NULL;
5332c393a42Smrg		p->size++;
5342c393a42Smrg	    }
5352c393a42Smrg	}
5361cc69409Smrg
5372c393a42Smrg	e = FcPatternElts(p);
5382c393a42Smrg	/* move elts up */
5392c393a42Smrg	memmove (e + i + 1,
5402c393a42Smrg		 e + i,
5412c393a42Smrg		 sizeof (FcPatternElt) *
542a32e9e42Smrg		 (FcPatternObjectCount (p) - i));
5431cc69409Smrg
5442c393a42Smrg	/* bump count */
5452c393a42Smrg	p->num++;
5461cc69409Smrg
5472c393a42Smrg	e[i].object = object;
5482c393a42Smrg	e[i].values = NULL;
5492c393a42Smrg    }
550ca08ab68Smrg
5512c393a42Smrg    return FcPatternElts(p) + i;
5522c393a42Smrg}
5532c393a42Smrg
5542c393a42SmrgFcBool
5552c393a42SmrgFcPatternEqual (const FcPattern *pa, const FcPattern *pb)
5562c393a42Smrg{
557a32e9e42Smrg    FcPatternIter ia, ib;
5582c393a42Smrg
5592c393a42Smrg    if (pa == pb)
5602c393a42Smrg	return FcTrue;
5612c393a42Smrg
562a32e9e42Smrg    if (FcPatternObjectCount (pa) != FcPatternObjectCount (pb))
5632c393a42Smrg	return FcFalse;
564a32e9e42Smrg    FcPatternIterStart (pa, &ia);
565a32e9e42Smrg    FcPatternIterStart (pb, &ib);
566a32e9e42Smrg    do {
567a32e9e42Smrg	FcBool ra, rb;
568a32e9e42Smrg
569a32e9e42Smrg	if (!FcPatternIterEqual (pa, &ia, pb, &ib))
5702c393a42Smrg	    return FcFalse;
571a32e9e42Smrg	ra = FcPatternIterNext (pa, &ia);
572a32e9e42Smrg	rb = FcPatternIterNext (pb, &ib);
573a32e9e42Smrg	if (!ra && !rb)
574a32e9e42Smrg	    break;
575a32e9e42Smrg    } while (1);
576a32e9e42Smrg
5772c393a42Smrg    return FcTrue;
5782c393a42Smrg}
5792c393a42Smrg
5802c393a42SmrgFcChar32
5812c393a42SmrgFcPatternHash (const FcPattern *p)
5822c393a42Smrg{
5832c393a42Smrg    int		i;
5842c393a42Smrg    FcChar32	h = 0;
5852c393a42Smrg    FcPatternElt    *pe = FcPatternElts(p);
5862c393a42Smrg
587a32e9e42Smrg    for (i = 0; i < FcPatternObjectCount (p); i++)
5882c393a42Smrg    {
589ca08ab68Smrg	h = (((h << 1) | (h >> 31)) ^
5902c393a42Smrg	     pe[i].object ^
5912c393a42Smrg	     FcValueListHash (FcPatternEltValues(&pe[i])));
5922c393a42Smrg    }
5932c393a42Smrg    return h;
5942c393a42Smrg}
5952c393a42Smrg
5962c393a42SmrgFcBool
5972c393a42SmrgFcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
5982c393a42Smrg{
5992c393a42Smrg    FcPatternElt    *ea, *eb;
6002c393a42Smrg    int		    i;
601ca08ab68Smrg
6022c393a42Smrg    for (i = 0; i < os->nobject; i++)
6032c393a42Smrg    {
6042c393a42Smrg	FcObject    object = FcObjectFromName (os->objects[i]);
6052c393a42Smrg	ea = FcPatternObjectFindElt (pai, object);
6062c393a42Smrg	eb = FcPatternObjectFindElt (pbi, object);
6072c393a42Smrg	if (ea)
6082c393a42Smrg	{
6092c393a42Smrg	    if (!eb)
6102c393a42Smrg		return FcFalse;
6112c393a42Smrg	    if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
6122c393a42Smrg		return FcFalse;
6132c393a42Smrg	}
6142c393a42Smrg	else
6152c393a42Smrg	{
6162c393a42Smrg	    if (eb)
6172c393a42Smrg		return FcFalse;
6182c393a42Smrg	}
6192c393a42Smrg    }
6202c393a42Smrg    return FcTrue;
6212c393a42Smrg}
6222c393a42Smrg
623ca08ab68SmrgFcBool
624ca08ab68SmrgFcPatternObjectListAdd (FcPattern	*p,
625ca08ab68Smrg			FcObject	object,
626ca08ab68Smrg			FcValueListPtr	list,
627ca08ab68Smrg			FcBool		append)
628ca08ab68Smrg{
629ca08ab68Smrg    FcPatternElt   *e;
630ca08ab68Smrg    FcValueListPtr l, *prev;
631ca08ab68Smrg
632c9710b42Smrg    if (FcRefIsConst (&p->ref))
633ca08ab68Smrg	goto bail0;
634ca08ab68Smrg
635ca08ab68Smrg    /*
636ca08ab68Smrg     * Make sure the stored type is valid for built-in objects
637ca08ab68Smrg     */
638ca08ab68Smrg    for (l = list; l != NULL; l = FcValueListNext (l))
639ca08ab68Smrg    {
640ca08ab68Smrg	if (!FcObjectValidType (object, l->value.type))
641ca08ab68Smrg	{
642c9710b42Smrg	    fprintf (stderr,
643c9710b42Smrg		     "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
644c9710b42Smrg	    FcValuePrintFile (stderr, l->value);
645c9710b42Smrg	    fprintf (stderr, "\n");
646ca08ab68Smrg	    goto bail0;
647ca08ab68Smrg	}
648ca08ab68Smrg    }
649ca08ab68Smrg
650ca08ab68Smrg    e = FcPatternObjectInsertElt (p, object);
651ca08ab68Smrg    if (!e)
652ca08ab68Smrg	goto bail0;
653ca08ab68Smrg
654ca08ab68Smrg    if (append)
655ca08ab68Smrg    {
656ca08ab68Smrg	for (prev = &e->values; *prev; prev = &(*prev)->next)
657ca08ab68Smrg	    ;
658ca08ab68Smrg	*prev = list;
659ca08ab68Smrg    }
660ca08ab68Smrg    else
661ca08ab68Smrg    {
662ca08ab68Smrg	for (prev = &list; *prev; prev = &(*prev)->next)
663ca08ab68Smrg	    ;
664ca08ab68Smrg	*prev = e->values;
665ca08ab68Smrg	e->values = list;
666ca08ab68Smrg    }
667ca08ab68Smrg
668ca08ab68Smrg    return FcTrue;
669ca08ab68Smrg
670ca08ab68Smrgbail0:
671ca08ab68Smrg    return FcFalse;
672ca08ab68Smrg}
673ca08ab68Smrg
6742c393a42SmrgFcBool
6752c393a42SmrgFcPatternObjectAddWithBinding  (FcPattern	*p,
6762c393a42Smrg				FcObject	object,
6772c393a42Smrg				FcValue		value,
6782c393a42Smrg				FcValueBinding  binding,
6792c393a42Smrg				FcBool		append)
6802c393a42Smrg{
6812c393a42Smrg    FcPatternElt   *e;
6822c393a42Smrg    FcValueListPtr new, *prev;
6832c393a42Smrg
684c9710b42Smrg    if (FcRefIsConst (&p->ref))
6852c393a42Smrg	goto bail0;
6862c393a42Smrg
687ca08ab68Smrg    new = FcValueListCreate ();
6882c393a42Smrg    if (!new)
6892c393a42Smrg	goto bail0;
6902c393a42Smrg
691a4e54154Smrg    new->value = FcValueSave (value);
692a4e54154Smrg    new->binding = binding;
693a4e54154Smrg    new->next = NULL;
694a4e54154Smrg
695a4e54154Smrg    if (new->value.type == FcTypeVoid)
6962c393a42Smrg	goto bail1;
6972c393a42Smrg
6982c393a42Smrg    /*
6992c393a42Smrg     * Make sure the stored type is valid for built-in objects
7002c393a42Smrg     */
701a4e54154Smrg    if (!FcObjectValidType (object, new->value.type))
7022c393a42Smrg    {
703c9710b42Smrg	fprintf (stderr,
704c9710b42Smrg		 "Fontconfig warning: FcPattern object %s does not accept value",
705c9710b42Smrg		 FcObjectName (object));
706a4e54154Smrg	FcValuePrintFile (stderr, new->value);
707c9710b42Smrg	fprintf (stderr, "\n");
7082c393a42Smrg	goto bail1;
7092c393a42Smrg    }
7102c393a42Smrg
7112c393a42Smrg    e = FcPatternObjectInsertElt (p, object);
7122c393a42Smrg    if (!e)
713a4e54154Smrg	goto bail1;
714ca08ab68Smrg
7152c393a42Smrg    if (append)
7162c393a42Smrg    {
7172c393a42Smrg	for (prev = &e->values; *prev; prev = &(*prev)->next)
7182c393a42Smrg	    ;
7192c393a42Smrg	*prev = new;
7202c393a42Smrg    }
7212c393a42Smrg    else
7222c393a42Smrg    {
7232c393a42Smrg	new->next = e->values;
7242c393a42Smrg	e->values = new;
7252c393a42Smrg    }
726ca08ab68Smrg
7272c393a42Smrg    return FcTrue;
7282c393a42Smrg
7292c393a42Smrgbail1:
730a4e54154Smrg    FcValueListDestroy (new);
7312c393a42Smrgbail0:
7322c393a42Smrg    return FcFalse;
7332c393a42Smrg}
7342c393a42Smrg
7352c393a42SmrgFcBool
7362c393a42SmrgFcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
7372c393a42Smrg{
7382c393a42Smrg    return FcPatternObjectAddWithBinding (p, object,
7392c393a42Smrg					  value, FcValueBindingStrong, append);
7402c393a42Smrg}
7412c393a42Smrg
7422c393a42SmrgFcBool
7432c393a42SmrgFcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
7442c393a42Smrg{
7452c393a42Smrg    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
7462c393a42Smrg					  value, FcValueBindingStrong, append);
7472c393a42Smrg}
7482c393a42Smrg
7492c393a42SmrgFcBool
7502c393a42SmrgFcPatternAddWeak  (FcPattern *p, const char *object, FcValue value, FcBool append)
7512c393a42Smrg{
7522c393a42Smrg    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
7532c393a42Smrg					  value, FcValueBindingWeak, append);
7542c393a42Smrg}
7552c393a42Smrg
7562c393a42SmrgFcBool
7572c393a42SmrgFcPatternObjectDel (FcPattern *p, FcObject object)
7582c393a42Smrg{
7592c393a42Smrg    FcPatternElt   *e;
7602c393a42Smrg
7612c393a42Smrg    e = FcPatternObjectFindElt (p, object);
7622c393a42Smrg    if (!e)
7632c393a42Smrg	return FcFalse;
7642c393a42Smrg
7652c393a42Smrg    /* destroy value */
7662c393a42Smrg    FcValueListDestroy (e->values);
767ca08ab68Smrg
7682c393a42Smrg    /* shuffle existing ones down */
769ca08ab68Smrg    memmove (e, e+1,
770a32e9e42Smrg	     (FcPatternElts(p) + FcPatternObjectCount (p) - (e + 1)) *
7712c393a42Smrg	     sizeof (FcPatternElt));
7722c393a42Smrg    p->num--;
773a32e9e42Smrg    e = FcPatternElts(p) + FcPatternObjectCount (p);
7742c393a42Smrg    e->object = 0;
7752c393a42Smrg    e->values = NULL;
7762c393a42Smrg    return FcTrue;
7772c393a42Smrg}
7782c393a42Smrg
7792c393a42SmrgFcBool
7802c393a42SmrgFcPatternDel (FcPattern *p, const char *object)
7812c393a42Smrg{
7822c393a42Smrg    return FcPatternObjectDel (p, FcObjectFromName (object));
7832c393a42Smrg}
784ca08ab68Smrg
7852c393a42SmrgFcBool
7862c393a42SmrgFcPatternRemove (FcPattern *p, const char *object, int id)
7872c393a42Smrg{
7882c393a42Smrg    FcPatternElt    *e;
7892c393a42Smrg    FcValueListPtr  *prev, l;
7902c393a42Smrg
7912c393a42Smrg    e = FcPatternObjectFindElt (p, FcObjectFromName (object));
7922c393a42Smrg    if (!e)
7932c393a42Smrg	return FcFalse;
7942c393a42Smrg    for (prev = &e->values; (l = *prev); prev = &l->next)
7952c393a42Smrg    {
7962c393a42Smrg	if (!id)
7972c393a42Smrg	{
7982c393a42Smrg	    *prev = l->next;
7992c393a42Smrg	    l->next = NULL;
8002c393a42Smrg	    FcValueListDestroy (l);
8012c393a42Smrg	    if (!e->values)
8022c393a42Smrg		FcPatternDel (p, object);
8032c393a42Smrg	    return FcTrue;
8042c393a42Smrg	}
8052c393a42Smrg	id--;
8062c393a42Smrg    }
8072c393a42Smrg    return FcFalse;
8082c393a42Smrg}
8092c393a42Smrg
8102c393a42SmrgFcBool
8112c393a42SmrgFcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
8122c393a42Smrg{
8132c393a42Smrg    FcValue	v;
8142c393a42Smrg
8152c393a42Smrg    v.type = FcTypeInteger;
8162c393a42Smrg    v.u.i = i;
8172c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
8182c393a42Smrg}
8192c393a42Smrg
8202c393a42SmrgFcBool
8212c393a42SmrgFcPatternAddInteger (FcPattern *p, const char *object, int i)
8222c393a42Smrg{
8232c393a42Smrg    return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
8242c393a42Smrg}
8252c393a42Smrg
8262c393a42SmrgFcBool
8272c393a42SmrgFcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
8282c393a42Smrg{
8292c393a42Smrg    FcValue	v;
8302c393a42Smrg
8312c393a42Smrg    v.type = FcTypeDouble;
8322c393a42Smrg    v.u.d = d;
8332c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
8342c393a42Smrg}
8352c393a42Smrg
8362c393a42Smrg
8372c393a42SmrgFcBool
8382c393a42SmrgFcPatternAddDouble (FcPattern *p, const char *object, double d)
8392c393a42Smrg{
8402c393a42Smrg    return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
8412c393a42Smrg}
8422c393a42Smrg
8432c393a42SmrgFcBool
8442c393a42SmrgFcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
8452c393a42Smrg{
8462c393a42Smrg    FcValue	v;
8472c393a42Smrg
8482c393a42Smrg    if (!s)
8492c393a42Smrg    {
8502c393a42Smrg	v.type = FcTypeVoid;
8512c393a42Smrg	v.u.s = 0;
8522c393a42Smrg	return FcPatternObjectAdd (p, object, v, FcTrue);
8532c393a42Smrg    }
8542c393a42Smrg
8552c393a42Smrg    v.type = FcTypeString;
856ca08ab68Smrg    v.u.s = s;
8572c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
8582c393a42Smrg}
8592c393a42Smrg
8602c393a42SmrgFcBool
8612c393a42SmrgFcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
8622c393a42Smrg{
8632c393a42Smrg    return FcPatternObjectAddString (p, FcObjectFromName (object), s);
8642c393a42Smrg}
8652c393a42Smrg
8662c393a42SmrgFcBool
8672c393a42SmrgFcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
8682c393a42Smrg{
8692c393a42Smrg    FcValue	v;
8702c393a42Smrg
8712c393a42Smrg    v.type = FcTypeMatrix;
8722c393a42Smrg    v.u.m = s;
8732c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
8742c393a42Smrg}
8752c393a42Smrg
8762c393a42Smrg
8772c393a42SmrgFcBool
8782c393a42SmrgFcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
8792c393a42Smrg{
8802c393a42Smrg    FcValue	v;
8812c393a42Smrg
8822c393a42Smrg    v.type = FcTypeBool;
8832c393a42Smrg    v.u.b = b;
8842c393a42Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
8852c393a42Smrg}
8862c393a42Smrg
8872c393a42SmrgFcBool
8882c393a42SmrgFcPatternAddBool (FcPattern *p, const char *object, FcBool b)
8892c393a42Smrg{
8902c393a42Smrg    return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
8912c393a42Smrg}
8922c393a42Smrg
8932c393a42SmrgFcBool
894a4e54154SmrgFcPatternObjectAddCharSet (FcPattern *p, FcObject object, const FcCharSet *c)
8952c393a42Smrg{
8962c393a42Smrg    FcValue	v;
8972c393a42Smrg
8982c393a42Smrg    v.type = FcTypeCharSet;
8992c393a42Smrg    v.u.c = (FcCharSet *)c;
900a4e54154Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
901a4e54154Smrg}
902a4e54154Smrg
903a4e54154SmrgFcBool
904a4e54154SmrgFcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
905a4e54154Smrg{
906a4e54154Smrg    return FcPatternObjectAddCharSet (p, FcObjectFromName (object), c);
9072c393a42Smrg}
9082c393a42Smrg
9092c393a42SmrgFcBool
9102c393a42SmrgFcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
9112c393a42Smrg{
9122c393a42Smrg    FcValue	v;
9132c393a42Smrg
9142c393a42Smrg    v.type = FcTypeFTFace;
9152c393a42Smrg    v.u.f = (void *) f;
9162c393a42Smrg    return FcPatternAdd (p, object, v, FcTrue);
9172c393a42Smrg}
9182c393a42Smrg
9192c393a42SmrgFcBool
920a4e54154SmrgFcPatternObjectAddLangSet (FcPattern *p, FcObject object, const FcLangSet *ls)
9212c393a42Smrg{
9222c393a42Smrg    FcValue	v;
9232c393a42Smrg
9242c393a42Smrg    v.type = FcTypeLangSet;
9252c393a42Smrg    v.u.l = (FcLangSet *)ls;
926a4e54154Smrg    return FcPatternObjectAdd (p, object, v, FcTrue);
927a4e54154Smrg}
928a4e54154Smrg
929a4e54154SmrgFcBool
930a4e54154SmrgFcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
931a4e54154Smrg{
932a4e54154Smrg    return FcPatternObjectAddLangSet (p, FcObjectFromName (object), ls);
9332c393a42Smrg}
9342c393a42Smrg
935953daebaSmrgFcBool
936953daebaSmrgFcPatternObjectAddRange (FcPattern *p, FcObject object, const FcRange *r)
937953daebaSmrg{
938953daebaSmrg    FcValue v;
939953daebaSmrg
940953daebaSmrg    v.type = FcTypeRange;
941953daebaSmrg    v.u.r = (FcRange *)r;
942953daebaSmrg    return FcPatternObjectAdd (p, object, v, FcTrue);
943953daebaSmrg}
944953daebaSmrg
945953daebaSmrgFcBool
946953daebaSmrgFcPatternAddRange (FcPattern *p, const char *object, const FcRange *r)
947953daebaSmrg{
948953daebaSmrg    return FcPatternObjectAddRange (p, FcObjectFromName (object), r);
949953daebaSmrg}
950953daebaSmrg
9512c393a42SmrgFcResult
952a32e9e42SmrgFcPatternObjectGetWithBinding (const FcPattern *p, FcObject object, int id, FcValue *v, FcValueBinding *b)
9532c393a42Smrg{
9542c393a42Smrg    FcPatternElt   *e;
9552c393a42Smrg    FcValueListPtr l;
9562c393a42Smrg
957c9710b42Smrg    if (!p)
958c9710b42Smrg	return FcResultNoMatch;
9592c393a42Smrg    e = FcPatternObjectFindElt (p, object);
9602c393a42Smrg    if (!e)
9612c393a42Smrg	return FcResultNoMatch;
9622c393a42Smrg    for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
9632c393a42Smrg    {
9642c393a42Smrg	if (!id)
9652c393a42Smrg	{
9662c393a42Smrg	    *v = FcValueCanonicalize(&l->value);
967a32e9e42Smrg	    if (b)
968a32e9e42Smrg		*b = l->binding;
9692c393a42Smrg	    return FcResultMatch;
9702c393a42Smrg	}
9712c393a42Smrg	id--;
9722c393a42Smrg    }
9732c393a42Smrg    return FcResultNoId;
9742c393a42Smrg}
9752c393a42Smrg
976a32e9e42SmrgFcResult
977a32e9e42SmrgFcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
978a32e9e42Smrg{
979a32e9e42Smrg    return FcPatternObjectGetWithBinding (p, object, id, v, NULL);
980a32e9e42Smrg}
981a32e9e42Smrg
982a32e9e42SmrgFcResult
983a32e9e42SmrgFcPatternGetWithBinding (const FcPattern *p, const char *object, int id, FcValue *v, FcValueBinding *b)
984a32e9e42Smrg{
985a32e9e42Smrg    return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, b);
986a32e9e42Smrg}
987a32e9e42Smrg
9882c393a42SmrgFcResult
9892c393a42SmrgFcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
9902c393a42Smrg{
991a32e9e42Smrg    return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, NULL);
9922c393a42Smrg}
9932c393a42Smrg
9942c393a42SmrgFcResult
9952c393a42SmrgFcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
9962c393a42Smrg{
9972c393a42Smrg    FcValue	v;
9982c393a42Smrg    FcResult	r;
9992c393a42Smrg
10002c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
10012c393a42Smrg    if (r != FcResultMatch)
10022c393a42Smrg	return r;
1003c9710b42Smrg    switch ((int) v.type) {
10042c393a42Smrg    case FcTypeDouble:
10052c393a42Smrg	*i = (int) v.u.d;
10062c393a42Smrg	break;
10072c393a42Smrg    case FcTypeInteger:
10082c393a42Smrg	*i = v.u.i;
10092c393a42Smrg	break;
10102c393a42Smrg    default:
10112c393a42Smrg        return FcResultTypeMismatch;
10122c393a42Smrg    }
10132c393a42Smrg    return FcResultMatch;
10142c393a42Smrg}
10152c393a42Smrg
10162c393a42SmrgFcResult
10172c393a42SmrgFcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
10182c393a42Smrg{
10192c393a42Smrg    return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
10202c393a42Smrg}
1021ca08ab68Smrg
1022ca08ab68Smrg
10232c393a42SmrgFcResult
10242c393a42SmrgFcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
10252c393a42Smrg{
10262c393a42Smrg    FcValue	v;
10272c393a42Smrg    FcResult	r;
10282c393a42Smrg
10292c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
10302c393a42Smrg    if (r != FcResultMatch)
10312c393a42Smrg	return r;
1032c9710b42Smrg    switch ((int) v.type) {
10332c393a42Smrg    case FcTypeDouble:
10342c393a42Smrg	*d = v.u.d;
10352c393a42Smrg	break;
10362c393a42Smrg    case FcTypeInteger:
10372c393a42Smrg	*d = (double) v.u.i;
10382c393a42Smrg	break;
10392c393a42Smrg    default:
10402c393a42Smrg        return FcResultTypeMismatch;
10412c393a42Smrg    }
10422c393a42Smrg    return FcResultMatch;
10432c393a42Smrg}
10442c393a42Smrg
10452c393a42SmrgFcResult
10462c393a42SmrgFcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
10472c393a42Smrg{
10482c393a42Smrg    return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
10492c393a42Smrg}
10502c393a42Smrg
10512c393a42SmrgFcResult
10522c393a42SmrgFcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
10532c393a42Smrg{
10542c393a42Smrg    FcValue	v;
10552c393a42Smrg    FcResult	r;
10562c393a42Smrg
10572c393a42Smrg    r = FcPatternObjectGet (p, object, id, &v);
10582c393a42Smrg    if (r != FcResultMatch)
10592c393a42Smrg	return r;
10602c393a42Smrg    if (v.type != FcTypeString)
10612c393a42Smrg        return FcResultTypeMismatch;
10622c393a42Smrg
10632c393a42Smrg    *s = (FcChar8 *) v.u.s;
10642c393a42Smrg    return FcResultMatch;
10652c393a42Smrg}
10662c393a42Smrg
10672c393a42SmrgFcResult
10682c393a42SmrgFcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
10692c393a42Smrg{
10702c393a42Smrg    return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
10712c393a42Smrg}
1072ca08ab68Smrg
10732c393a42SmrgFcResult
10742c393a42SmrgFcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
10752c393a42Smrg{
10762c393a42Smrg    FcValue	v;
10772c393a42Smrg    FcResult	r;
10782c393a42Smrg
10792c393a42Smrg    r = FcPatternGet (p, object, id, &v);
10802c393a42Smrg    if (r != FcResultMatch)
10812c393a42Smrg	return r;
10822c393a42Smrg    if (v.type != FcTypeMatrix)
10832c393a42Smrg        return FcResultTypeMismatch;
10842c393a42Smrg    *m = (FcMatrix *)v.u.m;
10852c393a42Smrg    return FcResultMatch;
10862c393a42Smrg}
10872c393a42Smrg
10882c393a42Smrg
10892c393a42SmrgFcResult
1090a32e9e42SmrgFcPatternObjectGetBool (const FcPattern *p, FcObject object, int id, FcBool *b)
10912c393a42Smrg{
10922c393a42Smrg    FcValue	v;
10932c393a42Smrg    FcResult	r;
10942c393a42Smrg
1095a32e9e42Smrg    r = FcPatternObjectGet (p, object, id, &v);
10962c393a42Smrg    if (r != FcResultMatch)
10972c393a42Smrg	return r;
10982c393a42Smrg    if (v.type != FcTypeBool)
10992c393a42Smrg        return FcResultTypeMismatch;
11002c393a42Smrg    *b = v.u.b;
11012c393a42Smrg    return FcResultMatch;
11022c393a42Smrg}
11032c393a42Smrg
1104a32e9e42SmrgFcResult
1105a32e9e42SmrgFcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
1106a32e9e42Smrg{
1107a32e9e42Smrg    return FcPatternObjectGetBool (p, FcObjectFromName (object), id, b);
1108a32e9e42Smrg}
1109a32e9e42Smrg
11102c393a42SmrgFcResult
11112c393a42SmrgFcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
11122c393a42Smrg{
11132c393a42Smrg    FcValue	v;
11142c393a42Smrg    FcResult	r;
11152c393a42Smrg
11162c393a42Smrg    r = FcPatternGet (p, object, id, &v);
11172c393a42Smrg    if (r != FcResultMatch)
11182c393a42Smrg	return r;
11192c393a42Smrg    if (v.type != FcTypeCharSet)
11202c393a42Smrg        return FcResultTypeMismatch;
11212c393a42Smrg    *c = (FcCharSet *)v.u.c;
11222c393a42Smrg    return FcResultMatch;
11232c393a42Smrg}
11242c393a42Smrg
11252c393a42SmrgFcResult
11262c393a42SmrgFcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
11272c393a42Smrg{
11282c393a42Smrg    FcValue	v;
11292c393a42Smrg    FcResult	r;
11302c393a42Smrg
11312c393a42Smrg    r = FcPatternGet (p, object, id, &v);
11322c393a42Smrg    if (r != FcResultMatch)
11332c393a42Smrg	return r;
11342c393a42Smrg    if (v.type != FcTypeFTFace)
11352c393a42Smrg	return FcResultTypeMismatch;
11362c393a42Smrg    *f = (FT_Face) v.u.f;
11372c393a42Smrg    return FcResultMatch;
11382c393a42Smrg}
11392c393a42Smrg
11402c393a42SmrgFcResult
11412c393a42SmrgFcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
11422c393a42Smrg{
11432c393a42Smrg    FcValue	v;
11442c393a42Smrg    FcResult	r;
11452c393a42Smrg
11462c393a42Smrg    r = FcPatternGet (p, object, id, &v);
11472c393a42Smrg    if (r != FcResultMatch)
11482c393a42Smrg	return r;
11492c393a42Smrg    if (v.type != FcTypeLangSet)
11502c393a42Smrg        return FcResultTypeMismatch;
11512c393a42Smrg    *ls = (FcLangSet *)v.u.l;
11522c393a42Smrg    return FcResultMatch;
11532c393a42Smrg}
11542c393a42Smrg
1155953daebaSmrgFcResult
1156953daebaSmrgFcPatternObjectGetRange (const FcPattern *p, FcObject object, int id, FcRange **r)
1157953daebaSmrg{
1158953daebaSmrg    FcValue	v;
1159953daebaSmrg    FcResult	res;
1160953daebaSmrg
1161953daebaSmrg    res = FcPatternObjectGet (p, object, id, &v);
1162953daebaSmrg    if (res != FcResultMatch)
1163953daebaSmrg	return res;
1164953daebaSmrg    switch ((int)v.type) {
1165953daebaSmrg    case FcTypeRange:
1166953daebaSmrg	*r = (FcRange *)v.u.r;
1167953daebaSmrg	break;
1168953daebaSmrg    default:
1169953daebaSmrg	return FcResultTypeMismatch;
1170953daebaSmrg    }
1171953daebaSmrg    return FcResultMatch;
1172953daebaSmrg}
1173953daebaSmrg
1174953daebaSmrgFcResult
1175953daebaSmrgFcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r)
1176953daebaSmrg{
1177953daebaSmrg    return FcPatternObjectGetRange (p, FcObjectFromName (object), id, r);
1178953daebaSmrg}
1179953daebaSmrg
11802c393a42SmrgFcPattern *
11812c393a42SmrgFcPatternDuplicate (const FcPattern *orig)
11822c393a42Smrg{
11832c393a42Smrg    FcPattern	    *new;
1184a32e9e42Smrg    FcPatternIter   iter;
11852c393a42Smrg    FcValueListPtr  l;
11862c393a42Smrg
1187a32e9e42Smrg    if (!orig)
1188a32e9e42Smrg	return NULL;
1189a32e9e42Smrg
11902c393a42Smrg    new = FcPatternCreate ();
11912c393a42Smrg    if (!new)
11922c393a42Smrg	goto bail0;
11932c393a42Smrg
1194a32e9e42Smrg    FcPatternIterStart (orig, &iter);
1195a32e9e42Smrg    do
11962c393a42Smrg    {
1197a32e9e42Smrg	for (l = FcPatternIterGetValues (orig, &iter); l; l = FcValueListNext (l))
11982c393a42Smrg	{
1199a32e9e42Smrg	    if (!FcPatternObjectAddWithBinding (new, FcPatternIterGetObjectId (orig, &iter),
12002c393a42Smrg						FcValueCanonicalize(&l->value),
12012c393a42Smrg						l->binding,
12022c393a42Smrg						FcTrue))
12032c393a42Smrg		goto bail1;
12042c393a42Smrg	}
1205a32e9e42Smrg    } while (FcPatternIterNext (orig, &iter));
12062c393a42Smrg
12072c393a42Smrg    return new;
12082c393a42Smrg
12092c393a42Smrgbail1:
12102c393a42Smrg    FcPatternDestroy (new);
12112c393a42Smrgbail0:
12122c393a42Smrg    return 0;
12132c393a42Smrg}
12142c393a42Smrg
12152c393a42Smrgvoid
12162c393a42SmrgFcPatternReference (FcPattern *p)
12172c393a42Smrg{
1218c9710b42Smrg    if (!FcRefIsConst (&p->ref))
1219c9710b42Smrg	FcRefInc (&p->ref);
12202c393a42Smrg    else
1221a32e9e42Smrg	FcCacheObjectReference (FcPatternGetCacheObject(p));
12222c393a42Smrg}
12232c393a42Smrg
12242c393a42SmrgFcPattern *
1225a6844aabSmrgFcPatternVaBuild (FcPattern *p, va_list va)
12262c393a42Smrg{
12272c393a42Smrg    FcPattern	*ret;
1228ca08ab68Smrg
1229a6844aabSmrg    FcPatternVapBuild (ret, p, va);
12302c393a42Smrg    return ret;
12312c393a42Smrg}
12322c393a42Smrg
12332c393a42SmrgFcPattern *
1234a6844aabSmrgFcPatternBuild (FcPattern *p, ...)
12352c393a42Smrg{
12362c393a42Smrg    va_list	va;
1237ca08ab68Smrg
1238a6844aabSmrg    va_start (va, p);
1239a6844aabSmrg    FcPatternVapBuild (p, p, va);
12402c393a42Smrg    va_end (va);
1241a6844aabSmrg    return p;
12422c393a42Smrg}
12432c393a42Smrg
12442c393a42Smrg/*
12452c393a42Smrg * Add all of the elements in 's' to 'p'
12462c393a42Smrg */
12472c393a42SmrgFcBool
12482c393a42SmrgFcPatternAppend (FcPattern *p, FcPattern *s)
12492c393a42Smrg{
1250a32e9e42Smrg    FcPatternIter  iter;
1251a32e9e42Smrg    FcValueListPtr v;
1252ca08ab68Smrg
1253a32e9e42Smrg    FcPatternIterStart (s, &iter);
1254a32e9e42Smrg    do
12552c393a42Smrg    {
1256a32e9e42Smrg	for (v = FcPatternIterGetValues (s, &iter); v; v = FcValueListNext (v))
12572c393a42Smrg	{
1258a32e9e42Smrg	    if (!FcPatternObjectAddWithBinding (p, FcPatternIterGetObjectId (s, &iter),
1259ca08ab68Smrg						FcValueCanonicalize(&v->value),
12602c393a42Smrg						v->binding, FcTrue))
12612c393a42Smrg		return FcFalse;
12622c393a42Smrg	}
1263a32e9e42Smrg    } while (FcPatternIterNext (s, &iter));
1264a32e9e42Smrg
12652c393a42Smrg    return FcTrue;
12662c393a42Smrg}
12672c393a42Smrg
1268a6844aabSmrgFcPattern *
1269a6844aabSmrgFcPatternFilter (FcPattern *p, const FcObjectSet *os)
1270a6844aabSmrg{
1271a6844aabSmrg    int		    i;
1272a6844aabSmrg    FcPattern	    *ret;
1273a6844aabSmrg    FcPatternElt    *e;
1274a6844aabSmrg    FcValueListPtr  v;
1275a6844aabSmrg
1276a6844aabSmrg    if (!os)
1277a6844aabSmrg	return FcPatternDuplicate (p);
1278a6844aabSmrg
1279a6844aabSmrg    ret = FcPatternCreate ();
1280a6844aabSmrg    if (!ret)
1281a6844aabSmrg	return NULL;
1282a6844aabSmrg
1283a6844aabSmrg    for (i = 0; i < os->nobject; i++)
1284a6844aabSmrg    {
1285a6844aabSmrg	FcObject object = FcObjectFromName (os->objects[i]);
1286a6844aabSmrg	e = FcPatternObjectFindElt (p, object);
1287a6844aabSmrg	if (e)
1288a6844aabSmrg	{
1289a6844aabSmrg	    for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1290a6844aabSmrg	    {
1291a6844aabSmrg		if (!FcPatternObjectAddWithBinding (ret, e->object,
1292a6844aabSmrg						    FcValueCanonicalize(&v->value),
1293a6844aabSmrg						    v->binding, FcTrue))
1294a6844aabSmrg		    goto bail0;
1295a6844aabSmrg	    }
1296a6844aabSmrg	}
1297a6844aabSmrg    }
1298a6844aabSmrg    return ret;
1299a6844aabSmrg
1300a6844aabSmrgbail0:
1301a6844aabSmrg    FcPatternDestroy (ret);
1302a6844aabSmrg    return NULL;
1303a6844aabSmrg}
1304a6844aabSmrg
1305a32e9e42Smrgtypedef struct _FcPatternPrivateIter {
1306a32e9e42Smrg    FcPatternElt *elt;
1307a32e9e42Smrg    int           pos;
1308a32e9e42Smrg} FcPatternPrivateIter;
1309a32e9e42Smrg
1310a32e9e42Smrgstatic void
1311a32e9e42SmrgFcPatternIterSet (const FcPattern *pat, FcPatternPrivateIter *iter)
1312a32e9e42Smrg{
1313a32e9e42Smrg    iter->elt = FcPatternObjectCount (pat) > 0 && iter->pos < FcPatternObjectCount (pat) ? &FcPatternElts (pat)[iter->pos] : NULL;
1314a32e9e42Smrg}
1315a32e9e42Smrg
1316a32e9e42Smrgvoid
1317a32e9e42SmrgFcPatternIterStart (const FcPattern *pat, FcPatternIter *iter)
1318a32e9e42Smrg{
1319a32e9e42Smrg    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1320a32e9e42Smrg
1321a32e9e42Smrg    priv->pos = 0;
1322a32e9e42Smrg    FcPatternIterSet (pat, priv);
1323a32e9e42Smrg}
1324a32e9e42Smrg
1325a32e9e42SmrgFcBool
1326a32e9e42SmrgFcPatternIterNext (const FcPattern *pat, FcPatternIter *iter)
1327a32e9e42Smrg{
1328a32e9e42Smrg    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1329a32e9e42Smrg
1330a32e9e42Smrg    priv->pos++;
1331a32e9e42Smrg    if (priv->pos >= FcPatternObjectCount (pat))
1332a32e9e42Smrg	return FcFalse;
1333a32e9e42Smrg    FcPatternIterSet (pat, priv);
1334a32e9e42Smrg
1335a32e9e42Smrg    return FcTrue;
1336a32e9e42Smrg}
1337a32e9e42Smrg
1338a32e9e42SmrgFcBool
1339a32e9e42SmrgFcPatternIterEqual (const FcPattern *p1, FcPatternIter *i1,
1340a32e9e42Smrg		    const FcPattern *p2, FcPatternIter *i2)
1341a32e9e42Smrg{
1342a32e9e42Smrg    FcBool b1 = FcPatternIterIsValid (p1, i1);
1343a32e9e42Smrg    FcBool b2 = FcPatternIterIsValid (p2, i2);
1344a32e9e42Smrg
1345a32e9e42Smrg    if (!i1 && !i2)
1346a32e9e42Smrg	return FcTrue;
1347a32e9e42Smrg    if (!b1 || !b2)
1348a32e9e42Smrg	return FcFalse;
1349a32e9e42Smrg    if (FcPatternIterGetObjectId (p1, i1) != FcPatternIterGetObjectId (p2, i2))
1350a32e9e42Smrg	return FcFalse;
1351a32e9e42Smrg
1352a32e9e42Smrg    return FcValueListEqual (FcPatternIterGetValues (p1, i1),
1353a32e9e42Smrg			     FcPatternIterGetValues (p2, i2));
1354a32e9e42Smrg}
1355a32e9e42Smrg
1356a32e9e42SmrgFcBool
1357a32e9e42SmrgFcPatternFindObjectIter (const FcPattern *pat, FcPatternIter *iter, FcObject object)
1358a32e9e42Smrg{
1359a32e9e42Smrg    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1360a32e9e42Smrg    int i = FcPatternObjectPosition (pat, object);
1361a32e9e42Smrg
1362a32e9e42Smrg    priv->elt = NULL;
1363a32e9e42Smrg    if (i < 0)
1364a32e9e42Smrg	return FcFalse;
1365a32e9e42Smrg
1366a32e9e42Smrg    priv->pos = i;
1367a32e9e42Smrg    FcPatternIterSet (pat, priv);
1368a32e9e42Smrg
1369a32e9e42Smrg    return FcTrue;
1370a32e9e42Smrg}
1371a32e9e42Smrg
1372a32e9e42SmrgFcBool
1373a32e9e42SmrgFcPatternFindIter (const FcPattern *pat, FcPatternIter *iter, const char *object)
1374a32e9e42Smrg{
1375a32e9e42Smrg    return FcPatternFindObjectIter (pat, iter, FcObjectFromName (object));
1376a32e9e42Smrg}
1377a32e9e42Smrg
1378a32e9e42SmrgFcBool
1379a32e9e42SmrgFcPatternIterIsValid (const FcPattern *pat, FcPatternIter *iter)
1380a32e9e42Smrg{
1381a32e9e42Smrg    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1382a32e9e42Smrg
1383a32e9e42Smrg    if (priv && priv->elt)
1384a32e9e42Smrg	return FcTrue;
1385a32e9e42Smrg
1386a32e9e42Smrg    return FcFalse;
1387a32e9e42Smrg}
1388a32e9e42Smrg
1389a32e9e42SmrgFcObject
1390a32e9e42SmrgFcPatternIterGetObjectId (const FcPattern *pat, FcPatternIter *iter)
1391a32e9e42Smrg{
1392a32e9e42Smrg    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1393a32e9e42Smrg
1394a32e9e42Smrg    if (priv && priv->elt)
1395a32e9e42Smrg	return priv->elt->object;
1396a32e9e42Smrg
1397a32e9e42Smrg    return 0;
1398a32e9e42Smrg}
1399a32e9e42Smrg
1400a32e9e42Smrgconst char *
1401a32e9e42SmrgFcPatternIterGetObject (const FcPattern *pat, FcPatternIter *iter)
1402a32e9e42Smrg{
1403a32e9e42Smrg    return FcObjectName (FcPatternIterGetObjectId (pat, iter));
1404a32e9e42Smrg}
1405a32e9e42Smrg
1406a32e9e42SmrgFcValueListPtr
1407a32e9e42SmrgFcPatternIterGetValues (const FcPattern *pat, FcPatternIter *iter)
1408a32e9e42Smrg{
1409a32e9e42Smrg    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1410a32e9e42Smrg
1411a32e9e42Smrg    if (priv && priv->elt)
1412a32e9e42Smrg	return FcPatternEltValues (priv->elt);
1413a32e9e42Smrg
1414a32e9e42Smrg    return NULL;
1415a32e9e42Smrg}
1416a32e9e42Smrg
1417a32e9e42Smrgint
1418a32e9e42SmrgFcPatternIterValueCount (const FcPattern *pat, FcPatternIter *iter)
1419a32e9e42Smrg{
1420a32e9e42Smrg    int count = 0;
1421a32e9e42Smrg    FcValueListPtr l;
1422a32e9e42Smrg
1423a32e9e42Smrg    for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l))
1424a32e9e42Smrg	count++;
1425a32e9e42Smrg
1426a32e9e42Smrg    return count;
1427a32e9e42Smrg}
1428a32e9e42Smrg
1429a32e9e42SmrgFcResult
1430a32e9e42SmrgFcPatternIterGetValue (const FcPattern *pat, FcPatternIter *iter, int id, FcValue *v, FcValueBinding *b)
1431a32e9e42Smrg{
1432a32e9e42Smrg    FcValueListPtr l;
1433a32e9e42Smrg
1434a32e9e42Smrg    for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l))
1435a32e9e42Smrg    {
1436a32e9e42Smrg	if (id == 0)
1437a32e9e42Smrg	{
1438a32e9e42Smrg	    *v = FcValueCanonicalize (&l->value);
1439a32e9e42Smrg	    if (b)
1440a32e9e42Smrg		*b = l->binding;
1441a32e9e42Smrg	    return FcResultMatch;
1442a32e9e42Smrg	}
1443a32e9e42Smrg	id--;
1444a32e9e42Smrg    }
1445a32e9e42Smrg    return FcResultNoId;
1446a32e9e42Smrg}
14472c393a42Smrg
14482c393a42SmrgFcBool
14492c393a42SmrgFcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
14502c393a42Smrg{
14512c393a42Smrg    int	i;
14522c393a42Smrg    FcPatternElt    *elts = FcPatternElts(pat);
1453ca08ab68Smrg
14542c393a42Smrg    if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
14552c393a42Smrg	return FcFalse;
1456a32e9e42Smrg    if (!FcSerializeAlloc (serialize, elts, FcPatternObjectCount (pat) * sizeof (FcPatternElt)))
14572c393a42Smrg	return FcFalse;
1458a32e9e42Smrg    for (i = 0; i < FcPatternObjectCount (pat); i++)
14592c393a42Smrg	if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
14602c393a42Smrg	    return FcFalse;
14612c393a42Smrg    return FcTrue;
14622c393a42Smrg}
14632c393a42Smrg
14642c393a42SmrgFcPattern *
14652c393a42SmrgFcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
14662c393a42Smrg{
14672c393a42Smrg    FcPattern	    *pat_serialized;
14682c393a42Smrg    FcPatternElt    *elts = FcPatternElts (pat);
14692c393a42Smrg    FcPatternElt    *elts_serialized;
14702c393a42Smrg    FcValueList	    *values_serialized;
14712c393a42Smrg    int		    i;
14722c393a42Smrg
14732c393a42Smrg    pat_serialized = FcSerializePtr (serialize, pat);
14742c393a42Smrg    if (!pat_serialized)
14752c393a42Smrg	return NULL;
14762c393a42Smrg    *pat_serialized = *pat;
1477a32e9e42Smrg    pat_serialized->size = FcPatternObjectCount (pat);
1478c9710b42Smrg    FcRefSetConst (&pat_serialized->ref);
1479ca08ab68Smrg
14802c393a42Smrg    elts_serialized = FcSerializePtr (serialize, elts);
14812c393a42Smrg    if (!elts_serialized)
14822c393a42Smrg	return NULL;
1483ca08ab68Smrg
14842c393a42Smrg    pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
14852c393a42Smrg						 elts_serialized);
14862c393a42Smrg
1487a32e9e42Smrg    for (i = 0; i < FcPatternObjectCount (pat); i++)
14882c393a42Smrg    {
14892c393a42Smrg	values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
14902c393a42Smrg	if (!values_serialized)
14912c393a42Smrg	    return NULL;
14922c393a42Smrg	elts_serialized[i].object = elts[i].object;
1493ca08ab68Smrg	elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
14942c393a42Smrg							  values_serialized,
14952c393a42Smrg							  FcValueList);
14962c393a42Smrg    }
14972c393a42Smrg    if (FcDebug() & FC_DBG_CACHEV) {
14982c393a42Smrg	printf ("Raw pattern:\n");
14992c393a42Smrg	FcPatternPrint (pat);
15002c393a42Smrg	printf ("Serialized pattern:\n");
15012c393a42Smrg	FcPatternPrint (pat_serialized);
15022c393a42Smrg	printf ("\n");
15032c393a42Smrg    }
15042c393a42Smrg    return pat_serialized;
15052c393a42Smrg}
15062c393a42Smrg
15072c393a42SmrgFcBool
15082c393a42SmrgFcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
15092c393a42Smrg{
15102c393a42Smrg    while (vl)
15112c393a42Smrg    {
15122c393a42Smrg	if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
15132c393a42Smrg	    return FcFalse;
1514c9710b42Smrg	switch ((int) vl->value.type) {
15152c393a42Smrg	case FcTypeString:
15162c393a42Smrg	    if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
15172c393a42Smrg		return FcFalse;
15182c393a42Smrg	    break;
15192c393a42Smrg	case FcTypeCharSet:
15202c393a42Smrg	    if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
15212c393a42Smrg		return FcFalse;
15222c393a42Smrg	    break;
15232c393a42Smrg	case FcTypeLangSet:
15242c393a42Smrg	    if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
15252c393a42Smrg		return FcFalse;
15262c393a42Smrg	    break;
1527953daebaSmrg	case FcTypeRange:
1528953daebaSmrg	    if (!FcRangeSerializeAlloc (serialize, vl->value.u.r))
1529953daebaSmrg		return FcFalse;
1530953daebaSmrg	    break;
15312c393a42Smrg	default:
15322c393a42Smrg	    break;
15332c393a42Smrg	}
15342c393a42Smrg	vl = vl->next;
15352c393a42Smrg    }
15362c393a42Smrg    return FcTrue;
15372c393a42Smrg}
15382c393a42Smrg
15392c393a42SmrgFcValueList *
15402c393a42SmrgFcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
15412c393a42Smrg{
15422c393a42Smrg    FcValueList	*vl_serialized;
15432c393a42Smrg    FcChar8	*s_serialized;
15442c393a42Smrg    FcCharSet	*c_serialized;
15452c393a42Smrg    FcLangSet	*l_serialized;
1546953daebaSmrg    FcRange	*r_serialized;
15472c393a42Smrg    FcValueList	*head_serialized = NULL;
15482c393a42Smrg    FcValueList	*prev_serialized = NULL;
15492c393a42Smrg
15502c393a42Smrg    while (vl)
15512c393a42Smrg    {
15522c393a42Smrg	vl_serialized = FcSerializePtr (serialize, vl);
15532c393a42Smrg	if (!vl_serialized)
15542c393a42Smrg	    return NULL;
1555ca08ab68Smrg
15562c393a42Smrg	if (prev_serialized)
15572c393a42Smrg	    prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
15582c393a42Smrg							  vl_serialized,
15592c393a42Smrg							  FcValueList);
15602c393a42Smrg	else
15612c393a42Smrg	    head_serialized = vl_serialized;
15621cc69409Smrg
15632c393a42Smrg	vl_serialized->next = NULL;
15642c393a42Smrg	vl_serialized->value.type = vl->value.type;
1565c9710b42Smrg	switch ((int) vl->value.type) {
15662c393a42Smrg	case FcTypeInteger:
15672c393a42Smrg	    vl_serialized->value.u.i = vl->value.u.i;
15682c393a42Smrg	    break;
15692c393a42Smrg	case FcTypeDouble:
15702c393a42Smrg	    vl_serialized->value.u.d = vl->value.u.d;
15712c393a42Smrg	    break;
15722c393a42Smrg	case FcTypeString:
15732c393a42Smrg	    s_serialized = FcStrSerialize (serialize, vl->value.u.s);
15742c393a42Smrg	    if (!s_serialized)
15752c393a42Smrg		return NULL;
15762c393a42Smrg	    vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
15772c393a42Smrg							     s_serialized,
15782c393a42Smrg							     FcChar8);
15792c393a42Smrg	    break;
15802c393a42Smrg	case FcTypeBool:
15812c393a42Smrg	    vl_serialized->value.u.b = vl->value.u.b;
15822c393a42Smrg	    break;
15832c393a42Smrg	case FcTypeMatrix:
15842c393a42Smrg	    /* can't happen */
15852c393a42Smrg	    break;
15862c393a42Smrg	case FcTypeCharSet:
15872c393a42Smrg	    c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
15882c393a42Smrg	    if (!c_serialized)
15892c393a42Smrg		return NULL;
15902c393a42Smrg	    vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
15912c393a42Smrg							     c_serialized,
15922c393a42Smrg							     FcCharSet);
15932c393a42Smrg	    break;
15942c393a42Smrg	case FcTypeFTFace:
15952c393a42Smrg	    /* can't happen */
15962c393a42Smrg	    break;
15972c393a42Smrg	case FcTypeLangSet:
15982c393a42Smrg	    l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
15992c393a42Smrg	    if (!l_serialized)
16002c393a42Smrg		return NULL;
16012c393a42Smrg	    vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
16022c393a42Smrg							     l_serialized,
16032c393a42Smrg							     FcLangSet);
16042c393a42Smrg	    break;
1605953daebaSmrg	case FcTypeRange:
1606953daebaSmrg	    r_serialized = FcRangeSerialize (serialize, vl->value.u.r);
1607953daebaSmrg	    if (!r_serialized)
1608953daebaSmrg		return NULL;
1609953daebaSmrg	    vl_serialized->value.u.r = FcPtrToEncodedOffset (&vl_serialized->value,
1610953daebaSmrg							     r_serialized,
1611953daebaSmrg							     FcRange);
1612953daebaSmrg	    break;
16132c393a42Smrg	default:
16142c393a42Smrg	    break;
16152c393a42Smrg	}
16162c393a42Smrg	prev_serialized = vl_serialized;
16172c393a42Smrg	vl = vl->next;
16182c393a42Smrg    }
16192c393a42Smrg    return head_serialized;
16202c393a42Smrg}
1621b09479dcSmrg
16222c393a42Smrg#define __fcpat__
16232c393a42Smrg#include "fcaliastail.h"
16242c393a42Smrg#include "fcftaliastail.h"
16252c393a42Smrg#undef __fcpat__
1626