2 * Copyright © 2000 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the author(s) not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The authors make no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
26 /* Objects MT-safe for readonly access. */
29 FcPatternCreate (void)
33 p = (FcPattern *) malloc (sizeof (FcPattern));
36 memset (p, 0, sizeof (FcPattern));
39 p->elts_offset = FcPtrToOffset (p, NULL);
40 FcRefInit (&p->ref, 1);
45 FcValueDestroy (FcValue v)
47 switch ((int) v.type) {
52 FcMatrixFree ((FcMatrix *) v.u.m);
55 FcCharSetDestroy ((FcCharSet *) v.u.c);
58 FcLangSetDestroy ((FcLangSet *) v.u.l);
66 FcValueCanonicalize (const FcValue *v)
70 switch ((int) v->type)
73 new.u.s = FcValueString(v);
74 new.type = FcTypeString;
77 new.u.c = FcValueCharSet(v);
78 new.type = FcTypeCharSet;
81 new.u.l = FcValueLangSet(v);
82 new.type = FcTypeLangSet;
92 FcValueSave (FcValue v)
94 switch ((int) v.type) {
96 v.u.s = FcStrdup (v.u.s);
101 v.u.m = FcMatrixCopy (v.u.m);
106 v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
111 v.u.l = FcLangSetCopy (v.u.l);
122 FcValueListCreate (void)
124 return calloc (1, sizeof (FcValueList));
128 FcValueListDestroy (FcValueListPtr l)
133 switch ((int) l->value.type) {
135 FcFree (l->value.u.s);
138 FcMatrixFree ((FcMatrix *)l->value.u.m);
142 ((FcCharSet *) (l->value.u.c));
146 ((FcLangSet *) (l->value.u.l));
151 next = FcValueListNext(l);
157 FcValueListPrepend (FcValueListPtr vallist,
159 FcValueBinding binding)
163 if (value.type == FcTypeVoid)
165 new = FcValueListCreate ();
169 new->value = FcValueSave (value);
170 new->binding = binding;
177 FcValueListAppend (FcValueListPtr vallist,
179 FcValueBinding binding)
181 FcValueListPtr new, last;
183 if (value.type == FcTypeVoid)
185 new = FcValueListCreate ();
189 new->value = FcValueSave (value);
190 new->binding = binding;
195 for (last = vallist; FcValueListNext (last); last = FcValueListNext (last));
206 FcValueListDuplicate(FcValueListPtr orig)
208 FcValueListPtr new = NULL, l, t = NULL;
211 for (l = orig; l != NULL; l = FcValueListNext (l))
215 t = new = FcValueListCreate();
219 t->next = FcValueListCreate();
220 t = FcValueListNext (t);
222 v = FcValueCanonicalize (&l->value);
223 t->value = FcValueSave (v);
224 t->binding = l->binding;
232 FcValueEqual (FcValue va, FcValue vb)
234 if (va.type != vb.type)
236 if (va.type == FcTypeInteger)
238 va.type = FcTypeDouble;
241 if (vb.type == FcTypeInteger)
243 vb.type = FcTypeDouble;
246 if (va.type != vb.type)
251 return FcFalse; /* don't know how to compare this object */
255 return va.u.i == vb.u.i;
257 return va.u.d == vb.u.d;
259 return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
261 return va.u.b == vb.u.b;
263 return FcMatrixEqual (va.u.m, vb.u.m);
265 return FcCharSetEqual (va.u.c, vb.u.c);
267 return va.u.f == vb.u.f;
269 return FcLangSetEqual (va.u.l, vb.u.l);
275 FcDoubleHash (double d)
285 FcStringHash (const FcChar8 *s)
292 h = ((h << 1) | (h >> 31)) ^ c;
297 FcValueHash (const FcValue *v)
304 return (FcChar32) v->u.i;
306 return FcDoubleHash (v->u.d);
308 return FcStringHash (FcValueString(v));
310 return (FcChar32) v->u.b;
312 return (FcDoubleHash (v->u.m->xx) ^
313 FcDoubleHash (v->u.m->xy) ^
314 FcDoubleHash (v->u.m->yx) ^
315 FcDoubleHash (v->u.m->yy));
317 return (FcChar32) FcValueCharSet(v)->num;
319 return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
320 FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
322 return FcLangSetHash (FcValueLangSet(v));
328 FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
335 if (!FcValueEqual (la->value, lb->value))
337 la = FcValueListNext(la);
338 lb = FcValueListNext(lb);
346 FcValueListHash (FcValueListPtr l)
350 for (; l; l = FcValueListNext(l))
352 hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
358 FcPatternDestroy (FcPattern *p)
366 if (FcRefIsConst (&p->ref))
368 FcCacheObjectDereference (p);
372 if (FcRefDec (&p->ref) != 1)
375 elts = FcPatternElts (p);
376 for (i = 0; i < p->num; i++)
377 FcValueListDestroy (FcPatternEltValues(&elts[i]));
384 FcPatternObjectPosition (const FcPattern *p, FcObject object)
386 int low, high, mid, c;
387 FcPatternElt *elts = FcPatternElts(p);
395 mid = (low + high) >> 1;
396 c = elts[mid].object - object;
410 FcPatternObjectFindElt (const FcPattern *p, FcObject object)
412 int i = FcPatternObjectPosition (p, object);
415 return &FcPatternElts(p)[i];
419 FcPatternObjectInsertElt (FcPattern *p, FcObject object)
424 i = FcPatternObjectPosition (p, object);
429 /* reallocate array */
430 if (p->num + 1 >= p->size)
432 int s = p->size + 16;
435 FcPatternElt *e0 = FcPatternElts(p);
436 e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
437 if (!e) /* maybe it was mmapped */
439 e = malloc(s * sizeof (FcPatternElt));
441 memcpy(e, e0, p->num * sizeof (FcPatternElt));
445 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
448 p->elts_offset = FcPtrToOffset (p, e);
451 e[p->size].object = 0;
452 e[p->size].values = NULL;
457 e = FcPatternElts(p);
461 sizeof (FcPatternElt) *
467 e[i].object = object;
471 return FcPatternElts(p) + i;
475 FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
478 FcPatternElt *pae, *pbe;
483 if (pa->num != pb->num)
485 pae = FcPatternElts(pa);
486 pbe = FcPatternElts(pb);
487 for (i = 0; i < pa->num; i++)
489 if (pae[i].object != pbe[i].object)
491 if (!FcValueListEqual (FcPatternEltValues(&pae[i]),
492 FcPatternEltValues(&pbe[i])))
499 FcPatternHash (const FcPattern *p)
503 FcPatternElt *pe = FcPatternElts(p);
505 for (i = 0; i < p->num; i++)
507 h = (((h << 1) | (h >> 31)) ^
509 FcValueListHash (FcPatternEltValues(&pe[i])));
515 FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
517 FcPatternElt *ea, *eb;
520 for (i = 0; i < os->nobject; i++)
522 FcObject object = FcObjectFromName (os->objects[i]);
523 ea = FcPatternObjectFindElt (pai, object);
524 eb = FcPatternObjectFindElt (pbi, object);
529 if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
542 FcPatternObjectListAdd (FcPattern *p,
548 FcValueListPtr l, *prev;
550 if (FcRefIsConst (&p->ref))
554 * Make sure the stored type is valid for built-in objects
556 for (l = list; l != NULL; l = FcValueListNext (l))
558 if (!FcObjectValidType (object, l->value.type))
561 "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
562 FcValuePrintFile (stderr, l->value);
563 fprintf (stderr, "\n");
568 e = FcPatternObjectInsertElt (p, object);
574 for (prev = &e->values; *prev; prev = &(*prev)->next)
580 for (prev = &list; *prev; prev = &(*prev)->next)
593 FcPatternObjectAddWithBinding (FcPattern *p,
596 FcValueBinding binding,
600 FcValueListPtr new, *prev;
602 if (FcRefIsConst (&p->ref))
605 new = FcValueListCreate ();
609 value = FcValueSave (value);
610 if (value.type == FcTypeVoid)
614 * Make sure the stored type is valid for built-in objects
616 if (!FcObjectValidType (object, value.type))
619 "Fontconfig warning: FcPattern object %s does not accept value",
620 FcObjectName (object));
621 FcValuePrintFile (stderr, value);
622 fprintf (stderr, "\n");
627 new->binding = binding;
630 e = FcPatternObjectInsertElt (p, object);
636 for (prev = &e->values; *prev; prev = &(*prev)->next)
642 new->next = e->values;
649 FcValueDestroy (value);
657 FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
659 return FcPatternObjectAddWithBinding (p, object,
660 value, FcValueBindingStrong, append);
664 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
666 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
667 value, FcValueBindingStrong, append);
671 FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
673 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
674 value, FcValueBindingWeak, append);
678 FcPatternObjectDel (FcPattern *p, FcObject object)
682 e = FcPatternObjectFindElt (p, object);
687 FcValueListDestroy (e->values);
689 /* shuffle existing ones down */
691 (FcPatternElts(p) + p->num - (e + 1)) *
692 sizeof (FcPatternElt));
694 e = FcPatternElts(p) + p->num;
701 FcPatternDel (FcPattern *p, const char *object)
703 return FcPatternObjectDel (p, FcObjectFromName (object));
707 FcPatternRemove (FcPattern *p, const char *object, int id)
710 FcValueListPtr *prev, l;
712 e = FcPatternObjectFindElt (p, FcObjectFromName (object));
715 for (prev = &e->values; (l = *prev); prev = &l->next)
721 FcValueListDestroy (l);
723 FcPatternDel (p, object);
732 FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
736 v.type = FcTypeInteger;
738 return FcPatternObjectAdd (p, object, v, FcTrue);
742 FcPatternAddInteger (FcPattern *p, const char *object, int i)
744 return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
748 FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
752 v.type = FcTypeDouble;
754 return FcPatternObjectAdd (p, object, v, FcTrue);
759 FcPatternAddDouble (FcPattern *p, const char *object, double d)
761 return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
765 FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
773 return FcPatternObjectAdd (p, object, v, FcTrue);
776 v.type = FcTypeString;
778 return FcPatternObjectAdd (p, object, v, FcTrue);
782 FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
784 return FcPatternObjectAddString (p, FcObjectFromName (object), s);
788 FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
792 v.type = FcTypeMatrix;
794 return FcPatternAdd (p, object, v, FcTrue);
799 FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
805 return FcPatternObjectAdd (p, object, v, FcTrue);
809 FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
811 return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
815 FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
819 v.type = FcTypeCharSet;
820 v.u.c = (FcCharSet *)c;
821 return FcPatternAdd (p, object, v, FcTrue);
825 FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
829 v.type = FcTypeFTFace;
831 return FcPatternAdd (p, object, v, FcTrue);
835 FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
839 v.type = FcTypeLangSet;
840 v.u.l = (FcLangSet *)ls;
841 return FcPatternAdd (p, object, v, FcTrue);
845 FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
851 return FcResultNoMatch;
852 e = FcPatternObjectFindElt (p, object);
854 return FcResultNoMatch;
855 for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
859 *v = FcValueCanonicalize(&l->value);
860 return FcResultMatch;
868 FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
870 return FcPatternObjectGet (p, FcObjectFromName (object), id, v);
874 FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
879 r = FcPatternObjectGet (p, object, id, &v);
880 if (r != FcResultMatch)
882 switch ((int) v.type) {
890 return FcResultTypeMismatch;
892 return FcResultMatch;
896 FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
898 return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
903 FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
908 r = FcPatternObjectGet (p, object, id, &v);
909 if (r != FcResultMatch)
911 switch ((int) v.type) {
919 return FcResultTypeMismatch;
921 return FcResultMatch;
925 FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
927 return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
931 FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
936 r = FcPatternObjectGet (p, object, id, &v);
937 if (r != FcResultMatch)
939 if (v.type != FcTypeString)
940 return FcResultTypeMismatch;
942 *s = (FcChar8 *) v.u.s;
943 return FcResultMatch;
947 FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
949 return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
953 FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
958 r = FcPatternGet (p, object, id, &v);
959 if (r != FcResultMatch)
961 if (v.type != FcTypeMatrix)
962 return FcResultTypeMismatch;
963 *m = (FcMatrix *)v.u.m;
964 return FcResultMatch;
969 FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
974 r = FcPatternGet (p, object, id, &v);
975 if (r != FcResultMatch)
977 if (v.type != FcTypeBool)
978 return FcResultTypeMismatch;
980 return FcResultMatch;
984 FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
989 r = FcPatternGet (p, object, id, &v);
990 if (r != FcResultMatch)
992 if (v.type != FcTypeCharSet)
993 return FcResultTypeMismatch;
994 *c = (FcCharSet *)v.u.c;
995 return FcResultMatch;
999 FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
1004 r = FcPatternGet (p, object, id, &v);
1005 if (r != FcResultMatch)
1007 if (v.type != FcTypeFTFace)
1008 return FcResultTypeMismatch;
1009 *f = (FT_Face) v.u.f;
1010 return FcResultMatch;
1014 FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
1019 r = FcPatternGet (p, object, id, &v);
1020 if (r != FcResultMatch)
1022 if (v.type != FcTypeLangSet)
1023 return FcResultTypeMismatch;
1024 *ls = (FcLangSet *)v.u.l;
1025 return FcResultMatch;
1029 FcPatternDuplicate (const FcPattern *orig)
1036 new = FcPatternCreate ();
1040 e = FcPatternElts(orig);
1042 for (i = 0; i < orig->num; i++)
1044 for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l))
1046 if (!FcPatternObjectAddWithBinding (new, e[i].object,
1047 FcValueCanonicalize(&l->value),
1058 FcPatternDestroy (new);
1064 FcPatternReference (FcPattern *p)
1066 if (!FcRefIsConst (&p->ref))
1069 FcCacheObjectReference (p);
1073 FcPatternVaBuild (FcPattern *p, va_list va)
1077 FcPatternVapBuild (ret, p, va);
1082 FcPatternBuild (FcPattern *p, ...)
1087 FcPatternVapBuild (p, p, va);
1093 * Add all of the elements in 's' to 'p'
1096 FcPatternAppend (FcPattern *p, FcPattern *s)
1102 for (i = 0; i < s->num; i++)
1104 e = FcPatternElts(s)+i;
1105 for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1107 if (!FcPatternObjectAddWithBinding (p, e->object,
1108 FcValueCanonicalize(&v->value),
1109 v->binding, FcTrue))
1117 FcPatternFilter (FcPattern *p, const FcObjectSet *os)
1125 return FcPatternDuplicate (p);
1127 ret = FcPatternCreate ();
1131 for (i = 0; i < os->nobject; i++)
1133 FcObject object = FcObjectFromName (os->objects[i]);
1134 e = FcPatternObjectFindElt (p, object);
1137 for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1139 if (!FcPatternObjectAddWithBinding (ret, e->object,
1140 FcValueCanonicalize(&v->value),
1141 v->binding, FcTrue))
1149 FcPatternDestroy (ret);
1155 FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
1158 FcPatternElt *elts = FcPatternElts(pat);
1160 if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
1162 if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt)))
1164 for (i = 0; i < pat->num; i++)
1165 if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
1171 FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
1173 FcPattern *pat_serialized;
1174 FcPatternElt *elts = FcPatternElts (pat);
1175 FcPatternElt *elts_serialized;
1176 FcValueList *values_serialized;
1179 pat_serialized = FcSerializePtr (serialize, pat);
1180 if (!pat_serialized)
1182 *pat_serialized = *pat;
1183 pat_serialized->size = pat->num;
1184 FcRefSetConst (&pat_serialized->ref);
1186 elts_serialized = FcSerializePtr (serialize, elts);
1187 if (!elts_serialized)
1190 pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
1193 for (i = 0; i < pat->num; i++)
1195 values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
1196 if (!values_serialized)
1198 elts_serialized[i].object = elts[i].object;
1199 elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
1203 if (FcDebug() & FC_DBG_CACHEV) {
1204 printf ("Raw pattern:\n");
1205 FcPatternPrint (pat);
1206 printf ("Serialized pattern:\n");
1207 FcPatternPrint (pat_serialized);
1210 return pat_serialized;
1214 FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
1218 if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
1220 switch ((int) vl->value.type) {
1222 if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
1226 if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
1230 if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
1242 FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
1244 FcValueList *vl_serialized;
1245 FcChar8 *s_serialized;
1246 FcCharSet *c_serialized;
1247 FcLangSet *l_serialized;
1248 FcValueList *head_serialized = NULL;
1249 FcValueList *prev_serialized = NULL;
1253 vl_serialized = FcSerializePtr (serialize, vl);
1257 if (prev_serialized)
1258 prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
1262 head_serialized = vl_serialized;
1264 vl_serialized->next = NULL;
1265 vl_serialized->value.type = vl->value.type;
1266 switch ((int) vl->value.type) {
1268 vl_serialized->value.u.i = vl->value.u.i;
1271 vl_serialized->value.u.d = vl->value.u.d;
1274 s_serialized = FcStrSerialize (serialize, vl->value.u.s);
1277 vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
1282 vl_serialized->value.u.b = vl->value.u.b;
1288 c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
1291 vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
1299 l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
1302 vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
1309 prev_serialized = vl_serialized;
1312 return head_serialized;
1316 #include "fcaliastail.h"
1317 #include "fcftaliastail.h"