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