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