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 Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD 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.
30 FcHashOwnsName(const FcChar8 *name);
33 FcPatternCreate (void)
37 p = (FcPattern *) malloc (sizeof (FcPattern));
40 FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern));
43 p->elts_offset = FcPtrToOffset (p, NULL);
49 FcValueDestroy (FcValue v)
53 if (!FcHashOwnsName(v.u.s))
54 FcStrFree ((FcChar8 *) v.u.s);
57 FcMatrixFree ((FcMatrix *) v.u.m);
60 FcCharSetDestroy ((FcCharSet *) v.u.c);
63 FcLangSetDestroy ((FcLangSet *) v.u.l);
71 FcValueCanonicalize (const FcValue *v)
78 new.u.s = fc_value_string(v);
79 new.type = FcTypeString;
82 new.u.c = fc_value_charset(v);
83 new.type = FcTypeCharSet;
86 new.u.l = fc_value_langset(v);
87 new.type = FcTypeLangSet;
97 FcValueSave (FcValue v)
101 v.u.s = FcStrCopy (v.u.s);
106 v.u.m = FcMatrixCopy (v.u.m);
111 v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
116 v.u.l = FcLangSetCopy (v.u.l);
127 FcValueListDestroy (FcValueListPtr l)
132 switch (l->value.type) {
134 if (!FcHashOwnsName((FcChar8 *)l->value.u.s))
135 FcStrFree ((FcChar8 *)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);
152 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
158 FcValueEqual (FcValue va, FcValue vb)
160 if (va.type != vb.type)
162 if (va.type == FcTypeInteger)
164 va.type = FcTypeDouble;
167 if (vb.type == FcTypeInteger)
169 vb.type = FcTypeDouble;
172 if (va.type != vb.type)
179 return va.u.i == vb.u.i;
181 return va.u.d == vb.u.d;
183 return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
185 return va.u.b == vb.u.b;
187 return FcMatrixEqual (va.u.m, vb.u.m);
189 return FcCharSetEqual (va.u.c, vb.u.c);
191 return va.u.f == vb.u.f;
193 return FcLangSetEqual (va.u.l, vb.u.l);
199 FcDoubleHash (double d)
209 FcStringHash (const FcChar8 *s)
216 h = ((h << 1) | (h >> 31)) ^ c;
221 FcValueHash (const FcValue *v)
223 switch (fc_storage_type(v)) {
227 return (FcChar32) v->u.i;
229 return FcDoubleHash (v->u.d);
231 return FcStringHash (fc_value_string(v));
233 return (FcChar32) v->u.b;
235 return (FcDoubleHash (v->u.m->xx) ^
236 FcDoubleHash (v->u.m->xy) ^
237 FcDoubleHash (v->u.m->yx) ^
238 FcDoubleHash (v->u.m->yy));
240 return (FcChar32) fc_value_charset(v)->num;
242 return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
243 FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
245 return FcLangSetHash (fc_value_langset(v));
251 FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
258 if (!FcValueEqual (la->value, lb->value))
260 la = FcValueListNext(la);
261 lb = FcValueListNext(lb);
269 FcValueListHash (FcValueListPtr l)
273 for (; l; l = FcValueListNext(l))
275 hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
281 FcPatternDestroy (FcPattern *p)
286 if (p->ref == FC_REF_CONSTANT)
288 FcCacheObjectDereference (p);
295 elts = FcPatternElts (p);
296 for (i = 0; i < p->num; i++)
297 FcValueListDestroy (FcPatternEltValues(&elts[i]));
299 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
301 FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern));
306 FcPatternObjectPosition (const FcPattern *p, FcObject object)
308 int low, high, mid, c;
309 FcPatternElt *elts = FcPatternElts(p);
317 mid = (low + high) >> 1;
318 c = elts[mid].object - object;
332 FcPatternObjectFindElt (const FcPattern *p, FcObject object)
334 int i = FcPatternObjectPosition (p, object);
337 return &FcPatternElts(p)[i];
341 FcPatternObjectInsertElt (FcPattern *p, FcObject object)
346 i = FcPatternObjectPosition (p, object);
351 /* reallocate array */
352 if (p->num + 1 >= p->size)
354 int s = p->size + 16;
357 FcPatternElt *e0 = FcPatternElts(p);
358 e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
359 if (!e) /* maybe it was mmapped */
361 e = malloc(s * sizeof (FcPatternElt));
363 memcpy(e, e0, p->num * sizeof (FcPatternElt));
367 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
370 p->elts_offset = FcPtrToOffset (p, e);
372 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
373 FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
376 e[p->size].object = 0;
377 e[p->size].values = NULL;
382 e = FcPatternElts(p);
386 sizeof (FcPatternElt) *
392 e[i].object = object;
396 return FcPatternElts(p) + i;
400 FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
403 FcPatternElt *pae, *pbe;
408 if (pa->num != pb->num)
410 pae = FcPatternElts(pa);
411 pbe = FcPatternElts(pb);
412 for (i = 0; i < pa->num; i++)
414 if (pae[i].object != pbe[i].object)
416 if (!FcValueListEqual (FcPatternEltValues(&pae[i]),
417 FcPatternEltValues(&pbe[i])))
424 FcPatternHash (const FcPattern *p)
428 FcPatternElt *pe = FcPatternElts(p);
430 for (i = 0; i < p->num; i++)
432 h = (((h << 1) | (h >> 31)) ^
434 FcValueListHash (FcPatternEltValues(&pe[i])));
440 FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
442 FcPatternElt *ea, *eb;
445 for (i = 0; i < os->nobject; i++)
447 FcObject object = FcObjectFromName (os->objects[i]);
448 ea = FcPatternObjectFindElt (pai, object);
449 eb = FcPatternObjectFindElt (pbi, object);
454 if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
467 FcPatternObjectAddWithBinding (FcPattern *p,
470 FcValueBinding binding,
474 FcValueListPtr new, *prev;
476 if (p->ref == FC_REF_CONSTANT)
479 new = malloc (sizeof (FcValueList));
483 memset(new, 0, sizeof (FcValueList));
484 FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
486 if (value.type == FcTypeString)
488 value.u.s = FcStrStaticName (value.u.s);
490 value.type = FcTypeVoid;
493 value = FcValueSave (value);
494 if (value.type == FcTypeVoid)
498 * Make sure the stored type is valid for built-in objects
500 if (!FcObjectValidType (object, value.type))
502 if (FcDebug() & FC_DBG_OBJTYPES)
504 printf ("FcPattern object %s does not accept value ",
505 FcObjectName (object));
506 FcValuePrint (value);
512 new->binding = binding;
515 e = FcPatternObjectInsertElt (p, object);
521 for (prev = &e->values; *prev; prev = &(*prev)->next)
527 new->next = e->values;
534 FcValueDestroy (value);
536 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
543 FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
545 return FcPatternObjectAddWithBinding (p, object,
546 value, FcValueBindingStrong, append);
550 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
552 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
553 value, FcValueBindingStrong, append);
557 FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
559 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
560 value, FcValueBindingWeak, append);
564 FcPatternObjectDel (FcPattern *p, FcObject object)
568 e = FcPatternObjectFindElt (p, object);
573 FcValueListDestroy (e->values);
575 /* shuffle existing ones down */
577 (FcPatternElts(p) + p->num - (e + 1)) *
578 sizeof (FcPatternElt));
580 e = FcPatternElts(p) + p->num;
587 FcPatternDel (FcPattern *p, const char *object)
589 return FcPatternObjectDel (p, FcObjectFromName (object));
593 FcPatternRemove (FcPattern *p, const char *object, int id)
596 FcValueListPtr *prev, l;
598 e = FcPatternObjectFindElt (p, FcObjectFromName (object));
601 for (prev = &e->values; (l = *prev); prev = &l->next)
607 FcValueListDestroy (l);
609 FcPatternDel (p, object);
618 FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
622 v.type = FcTypeInteger;
624 return FcPatternObjectAdd (p, object, v, FcTrue);
628 FcPatternAddInteger (FcPattern *p, const char *object, int i)
630 return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
634 FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
638 v.type = FcTypeDouble;
640 return FcPatternObjectAdd (p, object, v, FcTrue);
645 FcPatternAddDouble (FcPattern *p, const char *object, double d)
647 return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
651 FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
659 return FcPatternObjectAdd (p, object, v, FcTrue);
662 v.type = FcTypeString;
663 v.u.s = FcStrStaticName(s);
664 return FcPatternObjectAdd (p, object, v, FcTrue);
668 FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
670 return FcPatternObjectAddString (p, FcObjectFromName (object), s);
674 FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
678 v.type = FcTypeMatrix;
680 return FcPatternAdd (p, object, v, FcTrue);
685 FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
691 return FcPatternObjectAdd (p, object, v, FcTrue);
695 FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
697 return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
701 FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
705 v.type = FcTypeCharSet;
706 v.u.c = (FcCharSet *)c;
707 return FcPatternAdd (p, object, v, FcTrue);
711 FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
715 v.type = FcTypeFTFace;
717 return FcPatternAdd (p, object, v, FcTrue);
721 FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
725 v.type = FcTypeLangSet;
726 v.u.l = (FcLangSet *)ls;
727 return FcPatternAdd (p, object, v, FcTrue);
731 FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
736 e = FcPatternObjectFindElt (p, object);
738 return FcResultNoMatch;
739 for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
743 *v = FcValueCanonicalize(&l->value);
744 return FcResultMatch;
752 FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
754 return FcPatternObjectGet (p, FcObjectFromName (object), id, v);
758 FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
763 r = FcPatternObjectGet (p, object, id, &v);
764 if (r != FcResultMatch)
774 return FcResultTypeMismatch;
776 return FcResultMatch;
780 FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
782 return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
787 FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
792 r = FcPatternObjectGet (p, object, id, &v);
793 if (r != FcResultMatch)
803 return FcResultTypeMismatch;
805 return FcResultMatch;
809 FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
811 return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
815 FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
820 r = FcPatternObjectGet (p, object, id, &v);
821 if (r != FcResultMatch)
823 if (v.type != FcTypeString)
824 return FcResultTypeMismatch;
826 *s = (FcChar8 *) v.u.s;
827 return FcResultMatch;
831 FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
833 return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
837 FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
842 r = FcPatternGet (p, object, id, &v);
843 if (r != FcResultMatch)
845 if (v.type != FcTypeMatrix)
846 return FcResultTypeMismatch;
847 *m = (FcMatrix *)v.u.m;
848 return FcResultMatch;
853 FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
858 r = FcPatternGet (p, object, id, &v);
859 if (r != FcResultMatch)
861 if (v.type != FcTypeBool)
862 return FcResultTypeMismatch;
864 return FcResultMatch;
868 FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
873 r = FcPatternGet (p, object, id, &v);
874 if (r != FcResultMatch)
876 if (v.type != FcTypeCharSet)
877 return FcResultTypeMismatch;
878 *c = (FcCharSet *)v.u.c;
879 return FcResultMatch;
883 FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
888 r = FcPatternGet (p, object, id, &v);
889 if (r != FcResultMatch)
891 if (v.type != FcTypeFTFace)
892 return FcResultTypeMismatch;
893 *f = (FT_Face) v.u.f;
894 return FcResultMatch;
898 FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
903 r = FcPatternGet (p, object, id, &v);
904 if (r != FcResultMatch)
906 if (v.type != FcTypeLangSet)
907 return FcResultTypeMismatch;
908 *ls = (FcLangSet *)v.u.l;
909 return FcResultMatch;
913 FcPatternDuplicate (const FcPattern *orig)
920 new = FcPatternCreate ();
924 e = FcPatternElts(orig);
926 for (i = 0; i < orig->num; i++)
928 for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l))
930 if (!FcPatternObjectAddWithBinding (new, e[i].object,
931 FcValueCanonicalize(&l->value),
942 FcPatternDestroy (new);
948 FcPatternReference (FcPattern *p)
950 if (p->ref != FC_REF_CONSTANT)
953 FcCacheObjectReference (p);
957 FcPatternVaBuild (FcPattern *p, va_list va)
961 FcPatternVapBuild (ret, p, va);
966 FcPatternBuild (FcPattern *p, ...)
971 FcPatternVapBuild (p, p, va);
977 * Add all of the elements in 's' to 'p'
980 FcPatternAppend (FcPattern *p, FcPattern *s)
986 for (i = 0; i < s->num; i++)
988 e = FcPatternElts(s)+i;
989 for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
991 if (!FcPatternObjectAddWithBinding (p, e->object,
992 FcValueCanonicalize(&v->value),
1001 FcPatternFilter (FcPattern *p, const FcObjectSet *os)
1009 return FcPatternDuplicate (p);
1011 ret = FcPatternCreate ();
1015 for (i = 0; i < os->nobject; i++)
1017 FcObject object = FcObjectFromName (os->objects[i]);
1018 e = FcPatternObjectFindElt (p, object);
1021 for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1023 if (!FcPatternObjectAddWithBinding (ret, e->object,
1024 FcValueCanonicalize(&v->value),
1025 v->binding, FcTrue))
1033 FcPatternDestroy (ret);
1037 #define OBJECT_HASH_SIZE 31
1038 static struct objectBucket {
1039 struct objectBucket *next;
1041 } *FcObjectBuckets[OBJECT_HASH_SIZE];
1044 FcHashOwnsName (const FcChar8 *name)
1046 FcChar32 hash = FcStringHash (name);
1047 struct objectBucket **p;
1048 struct objectBucket *b;
1050 for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
1051 if (b->hash == hash && ((char *)name == (char *) (b + 1)))
1057 FcStrStaticName (const FcChar8 *name)
1059 FcChar32 hash = FcStringHash (name);
1060 struct objectBucket **p;
1061 struct objectBucket *b;
1064 for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
1065 if (b->hash == hash && !strcmp ((char *)name, (char *) (b + 1)))
1066 return (FcChar8 *) (b + 1);
1067 size = sizeof (struct objectBucket) + strlen ((char *)name) + 1;
1068 b = malloc (size + sizeof (int));
1069 /* workaround glibc bug which reads strlen in groups of 4 */
1070 FcMemAlloc (FC_MEM_STATICSTR, size + sizeof (int));
1075 strcpy ((char *) (b + 1), (char *)name);
1077 return (FcChar8 *) (b + 1);
1081 FcStrStaticNameFini (void)
1084 struct objectBucket *b, *next;
1087 for (i = 0; i < OBJECT_HASH_SIZE; i++)
1089 for (b = FcObjectBuckets[i]; b; b = next)
1092 name = (char *) (b + 1);
1093 size = sizeof (struct objectBucket) + strlen (name) + 1;
1094 FcMemFree (FC_MEM_STATICSTR, size + sizeof (int));
1097 FcObjectBuckets[i] = 0;
1102 FcPatternFini (void)
1104 FcStrStaticNameFini ();
1109 FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
1112 FcPatternElt *elts = FcPatternElts(pat);
1114 if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
1116 if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt)))
1118 for (i = 0; i < pat->num; i++)
1119 if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
1125 FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
1127 FcPattern *pat_serialized;
1128 FcPatternElt *elts = FcPatternElts (pat);
1129 FcPatternElt *elts_serialized;
1130 FcValueList *values_serialized;
1133 pat_serialized = FcSerializePtr (serialize, pat);
1134 if (!pat_serialized)
1136 *pat_serialized = *pat;
1137 pat_serialized->size = pat->num;
1138 pat_serialized->ref = FC_REF_CONSTANT;
1140 elts_serialized = FcSerializePtr (serialize, elts);
1141 if (!elts_serialized)
1144 pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
1147 for (i = 0; i < pat->num; i++)
1149 values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
1150 if (!values_serialized)
1152 elts_serialized[i].object = elts[i].object;
1153 elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
1157 if (FcDebug() & FC_DBG_CACHEV) {
1158 printf ("Raw pattern:\n");
1159 FcPatternPrint (pat);
1160 printf ("Serialized pattern:\n");
1161 FcPatternPrint (pat_serialized);
1164 return pat_serialized;
1168 FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
1172 if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
1174 switch (vl->value.type) {
1176 if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
1180 if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
1184 if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
1196 FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
1198 FcValueList *vl_serialized;
1199 FcChar8 *s_serialized;
1200 FcCharSet *c_serialized;
1201 FcLangSet *l_serialized;
1202 FcValueList *head_serialized = NULL;
1203 FcValueList *prev_serialized = NULL;
1207 vl_serialized = FcSerializePtr (serialize, vl);
1211 if (prev_serialized)
1212 prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
1216 head_serialized = vl_serialized;
1218 vl_serialized->next = NULL;
1219 vl_serialized->value.type = vl->value.type;
1220 switch (vl->value.type) {
1222 vl_serialized->value.u.i = vl->value.u.i;
1225 vl_serialized->value.u.d = vl->value.u.d;
1228 s_serialized = FcStrSerialize (serialize, vl->value.u.s);
1231 vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
1236 vl_serialized->value.u.b = vl->value.u.b;
1242 c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
1245 vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
1253 l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
1256 vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
1263 prev_serialized = vl_serialized;
1266 return head_serialized;
1269 #include "fcaliastail.h"
1270 #include "fcftaliastail.h"