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