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.
29 FcStrHashed (const FcChar8 *name);
32 FcPatternCreate (void)
36 p = (FcPattern *) malloc (sizeof (FcPattern));
39 FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern));
42 p->elts_offset = FcPtrToOffset (p, NULL);
48 FcValueDestroy (FcValue v)
52 if (!FcStrHashed (v.u.s))
53 FcStrFree ((FcChar8 *) v.u.s);
56 FcMatrixFree ((FcMatrix *) v.u.m);
59 FcCharSetDestroy ((FcCharSet *) v.u.c);
62 FcLangSetDestroy ((FcLangSet *) v.u.l);
70 FcValueCanonicalize (const FcValue *v)
77 new.u.s = fc_value_string(v);
78 new.type = FcTypeString;
81 new.u.c = fc_value_charset(v);
82 new.type = FcTypeCharSet;
85 new.u.l = fc_value_langset(v);
86 new.type = FcTypeLangSet;
96 FcValueSave (FcValue v)
100 v.u.s = FcStrCopy (v.u.s);
105 v.u.m = FcMatrixCopy (v.u.m);
110 v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
115 v.u.l = FcLangSetCopy (v.u.l);
126 FcValueListDestroy (FcValueListPtr l)
131 switch (l->value.type) {
133 if (!FcStrHashed ((FcChar8 *)l->value.u.s))
134 FcStrFree ((FcChar8 *)l->value.u.s);
137 FcMatrixFree ((FcMatrix *)l->value.u.m);
141 ((FcCharSet *) (l->value.u.c));
145 ((FcLangSet *) (l->value.u.l));
150 next = FcValueListNext(l);
151 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
157 FcValueEqual (FcValue va, FcValue vb)
159 if (va.type != vb.type)
161 if (va.type == FcTypeInteger)
163 va.type = FcTypeDouble;
166 if (vb.type == FcTypeInteger)
168 vb.type = FcTypeDouble;
171 if (va.type != vb.type)
178 return va.u.i == vb.u.i;
180 return va.u.d == vb.u.d;
182 return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
184 return va.u.b == vb.u.b;
186 return FcMatrixEqual (va.u.m, vb.u.m);
188 return FcCharSetEqual (va.u.c, vb.u.c);
190 return va.u.f == vb.u.f;
192 return FcLangSetEqual (va.u.l, vb.u.l);
198 FcDoubleHash (double d)
208 FcStringHash (const FcChar8 *s)
215 h = ((h << 1) | (h >> 31)) ^ c;
220 FcValueHash (const FcValue *v)
222 switch (fc_storage_type(v)) {
226 return (FcChar32) v->u.i;
228 return FcDoubleHash (v->u.d);
230 return FcStringHash (fc_value_string(v));
232 return (FcChar32) v->u.b;
234 return (FcDoubleHash (v->u.m->xx) ^
235 FcDoubleHash (v->u.m->xy) ^
236 FcDoubleHash (v->u.m->yx) ^
237 FcDoubleHash (v->u.m->yy));
239 return (FcChar32) fc_value_charset(v)->num;
241 return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
242 FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
244 return FcLangSetHash (fc_value_langset(v));
250 FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
257 if (!FcValueEqual (la->value, lb->value))
259 la = FcValueListNext(la);
260 lb = FcValueListNext(lb);
268 FcValueListHash (FcValueListPtr l)
272 for (; l; l = FcValueListNext(l))
274 hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
280 FcPatternDestroy (FcPattern *p)
285 if (p->ref == FC_REF_CONSTANT)
287 FcCacheObjectDereference (p);
294 elts = FcPatternElts (p);
295 for (i = 0; i < p->num; i++)
296 FcValueListDestroy (FcPatternEltValues(&elts[i]));
298 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
300 FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern));
305 FcPatternObjectPosition (const FcPattern *p, FcObject object)
307 int low, high, mid, c;
308 FcPatternElt *elts = FcPatternElts(p);
316 mid = (low + high) >> 1;
317 c = elts[mid].object - object;
331 FcPatternObjectFindElt (const FcPattern *p, FcObject object)
333 int i = FcPatternObjectPosition (p, object);
336 return &FcPatternElts(p)[i];
340 FcPatternObjectInsertElt (FcPattern *p, FcObject object)
345 i = FcPatternObjectPosition (p, object);
350 /* reallocate array */
351 if (p->num + 1 >= p->size)
353 int s = p->size + 16;
356 FcPatternElt *e0 = FcPatternElts(p);
357 e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
358 if (!e) /* maybe it was mmapped */
360 e = malloc(s * sizeof (FcPatternElt));
362 memcpy(e, e0, p->num * sizeof (FcPatternElt));
366 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
369 p->elts_offset = FcPtrToOffset (p, e);
371 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
372 FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
375 e[p->size].object = 0;
376 e[p->size].values = NULL;
381 e = FcPatternElts(p);
385 sizeof (FcPatternElt) *
391 e[i].object = object;
395 return FcPatternElts(p) + i;
399 FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
402 FcPatternElt *pae, *pbe;
407 if (pa->num != pb->num)
409 pae = FcPatternElts(pa);
410 pbe = FcPatternElts(pb);
411 for (i = 0; i < pa->num; i++)
413 if (pae[i].object != pbe[i].object)
415 if (!FcValueListEqual (FcPatternEltValues(&pae[i]),
416 FcPatternEltValues(&pbe[i])))
423 FcPatternHash (const FcPattern *p)
427 FcPatternElt *pe = FcPatternElts(p);
429 for (i = 0; i < p->num; i++)
431 h = (((h << 1) | (h >> 31)) ^
433 FcValueListHash (FcPatternEltValues(&pe[i])));
439 FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
441 FcPatternElt *ea, *eb;
444 for (i = 0; i < os->nobject; i++)
446 FcObject object = FcObjectFromName (os->objects[i]);
447 ea = FcPatternObjectFindElt (pai, object);
448 eb = FcPatternObjectFindElt (pbi, object);
453 if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
466 FcPatternObjectAddWithBinding (FcPattern *p,
469 FcValueBinding binding,
473 FcValueListPtr new, *prev;
475 if (p->ref == FC_REF_CONSTANT)
478 new = malloc (sizeof (FcValueList));
482 memset(new, 0, sizeof (FcValueList));
483 FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
485 if (value.type == FcTypeString)
487 value.u.s = FcStrStaticName (value.u.s);
489 value.type = FcTypeVoid;
492 value = FcValueSave (value);
493 if (value.type == FcTypeVoid)
497 * Make sure the stored type is valid for built-in objects
499 if (!FcObjectValidType (object, value.type))
501 if (FcDebug() & FC_DBG_OBJTYPES)
503 printf ("FcPattern object %s does not accept value ",
504 FcObjectName (object));
505 FcValuePrint (value);
511 new->binding = binding;
514 e = FcPatternObjectInsertElt (p, object);
520 for (prev = &e->values; *prev; prev = &(*prev)->next)
526 new->next = e->values;
533 FcValueDestroy (value);
535 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
542 FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
544 return FcPatternObjectAddWithBinding (p, object,
545 value, FcValueBindingStrong, append);
549 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
551 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
552 value, FcValueBindingStrong, append);
556 FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
558 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
559 value, FcValueBindingWeak, append);
563 FcPatternObjectDel (FcPattern *p, FcObject object)
567 e = FcPatternObjectFindElt (p, object);
572 FcValueListDestroy (e->values);
574 /* shuffle existing ones down */
576 (FcPatternElts(p) + p->num - (e + 1)) *
577 sizeof (FcPatternElt));
579 e = FcPatternElts(p) + p->num;
586 FcPatternDel (FcPattern *p, const char *object)
588 return FcPatternObjectDel (p, FcObjectFromName (object));
592 FcPatternRemove (FcPattern *p, const char *object, int id)
595 FcValueListPtr *prev, l;
597 e = FcPatternObjectFindElt (p, FcObjectFromName (object));
600 for (prev = &e->values; (l = *prev); prev = &l->next)
606 FcValueListDestroy (l);
608 FcPatternDel (p, object);
617 FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
621 v.type = FcTypeInteger;
623 return FcPatternObjectAdd (p, object, v, FcTrue);
627 FcPatternAddInteger (FcPattern *p, const char *object, int i)
629 return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
633 FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
637 v.type = FcTypeDouble;
639 return FcPatternObjectAdd (p, object, v, FcTrue);
644 FcPatternAddDouble (FcPattern *p, const char *object, double d)
646 return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
650 FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
658 return FcPatternObjectAdd (p, object, v, FcTrue);
661 v.type = FcTypeString;
662 v.u.s = FcStrStaticName(s);
663 return FcPatternObjectAdd (p, object, v, FcTrue);
667 FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
669 return FcPatternObjectAddString (p, FcObjectFromName (object), s);
673 FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
677 v.type = FcTypeMatrix;
679 return FcPatternAdd (p, object, v, FcTrue);
684 FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
690 return FcPatternObjectAdd (p, object, v, FcTrue);
694 FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
696 return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
700 FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
704 v.type = FcTypeCharSet;
705 v.u.c = (FcCharSet *)c;
706 return FcPatternAdd (p, object, v, FcTrue);
710 FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
714 v.type = FcTypeFTFace;
716 return FcPatternAdd (p, object, v, FcTrue);
720 FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
724 v.type = FcTypeLangSet;
725 v.u.l = (FcLangSet *)ls;
726 return FcPatternAdd (p, object, v, FcTrue);
730 FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
735 e = FcPatternObjectFindElt (p, object);
737 return FcResultNoMatch;
738 for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
742 *v = FcValueCanonicalize(&l->value);
743 return FcResultMatch;
751 FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
753 return FcPatternObjectGet (p, FcObjectFromName (object), id, v);
757 FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
762 r = FcPatternObjectGet (p, object, id, &v);
763 if (r != FcResultMatch)
773 return FcResultTypeMismatch;
775 return FcResultMatch;
779 FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
781 return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
786 FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
791 r = FcPatternObjectGet (p, object, id, &v);
792 if (r != FcResultMatch)
802 return FcResultTypeMismatch;
804 return FcResultMatch;
808 FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
810 return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
814 FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
819 r = FcPatternObjectGet (p, object, id, &v);
820 if (r != FcResultMatch)
822 if (v.type != FcTypeString)
823 return FcResultTypeMismatch;
825 *s = (FcChar8 *) v.u.s;
826 return FcResultMatch;
830 FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
832 return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
836 FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
841 r = FcPatternGet (p, object, id, &v);
842 if (r != FcResultMatch)
844 if (v.type != FcTypeMatrix)
845 return FcResultTypeMismatch;
846 *m = (FcMatrix *)v.u.m;
847 return FcResultMatch;
852 FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
857 r = FcPatternGet (p, object, id, &v);
858 if (r != FcResultMatch)
860 if (v.type != FcTypeBool)
861 return FcResultTypeMismatch;
863 return FcResultMatch;
867 FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
872 r = FcPatternGet (p, object, id, &v);
873 if (r != FcResultMatch)
875 if (v.type != FcTypeCharSet)
876 return FcResultTypeMismatch;
877 *c = (FcCharSet *)v.u.c;
878 return FcResultMatch;
882 FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
887 r = FcPatternGet (p, object, id, &v);
888 if (r != FcResultMatch)
890 if (v.type != FcTypeFTFace)
891 return FcResultTypeMismatch;
892 *f = (FT_Face) v.u.f;
893 return FcResultMatch;
897 FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
902 r = FcPatternGet (p, object, id, &v);
903 if (r != FcResultMatch)
905 if (v.type != FcTypeLangSet)
906 return FcResultTypeMismatch;
907 *ls = (FcLangSet *)v.u.l;
908 return FcResultMatch;
912 FcPatternDuplicate (const FcPattern *orig)
919 new = FcPatternCreate ();
923 e = FcPatternElts(orig);
925 for (i = 0; i < orig->num; i++)
927 for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l))
928 if (!FcPatternObjectAdd (new, e[i].object,
929 FcValueCanonicalize(&l->value),
937 FcPatternDestroy (new);
943 FcPatternReference (FcPattern *p)
945 if (p->ref != FC_REF_CONSTANT)
948 FcCacheObjectReference (p);
952 FcPatternVaBuild (FcPattern *orig, va_list va)
956 FcPatternVapBuild (ret, orig, va);
961 FcPatternBuild (FcPattern *orig, ...)
966 FcPatternVapBuild (orig, orig, va);
972 * Add all of the elements in 's' to 'p'
975 FcPatternAppend (FcPattern *p, FcPattern *s)
981 for (i = 0; i < s->num; i++)
983 e = FcPatternElts(s)+i;
984 for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
986 if (!FcPatternObjectAddWithBinding (p, e->object,
987 FcValueCanonicalize(&v->value),
995 #define OBJECT_HASH_SIZE 31
996 static struct objectBucket {
997 struct objectBucket *next;
999 } *FcObjectBuckets[OBJECT_HASH_SIZE];
1002 FcStrHashed (const FcChar8 *name)
1004 FcChar32 hash = FcStringHash (name);
1005 struct objectBucket **p;
1006 struct objectBucket *b;
1008 for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
1009 if (b->hash == hash && !strcmp ((char *)name, (char *) (b + 1)))
1015 FcStrStaticName (const FcChar8 *name)
1017 FcChar32 hash = FcStringHash (name);
1018 struct objectBucket **p;
1019 struct objectBucket *b;
1022 for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
1023 if (b->hash == hash && !strcmp ((char *)name, (char *) (b + 1)))
1024 return (FcChar8 *) (b + 1);
1025 size = sizeof (struct objectBucket) + strlen ((char *)name) + 1;
1026 b = malloc (size + sizeof (int));
1027 /* workaround glibc bug which reads strlen in groups of 4 */
1028 FcMemAlloc (FC_MEM_STATICSTR, size + sizeof (int));
1033 strcpy ((char *) (b + 1), (char *)name);
1035 return (FcChar8 *) (b + 1);
1039 FcStrStaticNameFini (void)
1042 struct objectBucket *b, *next;
1045 for (i = 0; i < OBJECT_HASH_SIZE; i++)
1047 for (b = FcObjectBuckets[i]; b; b = next)
1050 name = (char *) (b + 1);
1051 size = sizeof (struct objectBucket) + strlen (name) + 1;
1052 FcMemFree (FC_MEM_STATICSTR, size);
1055 FcObjectBuckets[i] = 0;
1060 FcPatternFini (void)
1062 FcStrStaticNameFini ();
1067 FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
1070 FcPatternElt *elts = FcPatternElts(pat);
1072 if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
1074 if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt)))
1076 for (i = 0; i < pat->num; i++)
1077 if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
1083 FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
1085 FcPattern *pat_serialized;
1086 FcPatternElt *elts = FcPatternElts (pat);
1087 FcPatternElt *elts_serialized;
1088 FcValueList *values_serialized;
1091 pat_serialized = FcSerializePtr (serialize, pat);
1092 if (!pat_serialized)
1094 *pat_serialized = *pat;
1095 pat_serialized->size = pat->num;
1096 pat_serialized->ref = FC_REF_CONSTANT;
1098 elts_serialized = FcSerializePtr (serialize, elts);
1099 if (!elts_serialized)
1102 pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
1105 for (i = 0; i < pat->num; i++)
1107 values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
1108 if (!values_serialized)
1110 elts_serialized[i].object = elts[i].object;
1111 elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
1115 if (FcDebug() & FC_DBG_CACHEV) {
1116 printf ("Raw pattern:\n");
1117 FcPatternPrint (pat);
1118 printf ("Serialized pattern:\n");
1119 FcPatternPrint (pat_serialized);
1122 return pat_serialized;
1126 FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
1130 if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
1132 switch (vl->value.type) {
1134 if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
1138 if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
1142 if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
1154 FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
1156 FcValueList *vl_serialized;
1157 FcChar8 *s_serialized;
1158 FcCharSet *c_serialized;
1159 FcLangSet *l_serialized;
1160 FcValueList *head_serialized = NULL;
1161 FcValueList *prev_serialized = NULL;
1165 vl_serialized = FcSerializePtr (serialize, vl);
1169 if (prev_serialized)
1170 prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
1174 head_serialized = vl_serialized;
1176 vl_serialized->next = NULL;
1177 vl_serialized->value = vl->value;
1178 switch (vl->value.type) {
1180 s_serialized = FcStrSerialize (serialize, vl->value.u.s);
1183 vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
1188 c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
1191 vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
1196 l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
1199 vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
1206 prev_serialized = vl_serialized;
1209 return head_serialized;
1212 #include "fcaliastail.h"