2 * $RCSId: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $
4 * Copyright © 2000 Keith Packard
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
30 static FcPattern ** fcpatterns = 0;
31 static int fcpattern_bank_count = 0, fcpattern_ptr, fcpattern_count;
32 static FcPatternElt ** fcpatternelts = 0;
33 static int fcpatternelt_ptr, fcpatternelt_count;
34 static FcValueList ** fcvaluelists = 0;
35 static int fcvaluelist_bank_count = 0, fcvaluelist_ptr, fcvaluelist_count;
38 FcPatternFindFullFname (const FcPattern *p);
39 static FcPatternEltPtr
40 FcPatternEltPtrCreateDynamic (FcPatternElt * e);
42 /* If you are trying to duplicate an FcPattern which will be used for
43 * rendering, be aware that (internally) you also have to use
44 * FcPatternTransferFullFname to transfer the associated filename. If
45 * you are copying the font (externally) using FcPatternGetString,
46 * then everything's fine; this caveat only applies if you're copying
47 * the bits individually. */
50 FcPatternCreate (void)
54 p = (FcPattern *) malloc (sizeof (FcPattern));
57 FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern));
60 p->elts = FcPatternEltPtrCreateDynamic(0);
61 p->bank = FC_BANK_DYNAMIC;
67 FcValueDestroy (FcValue v)
71 FcStrFree ((FcChar8 *) v.u.s);
74 FcMatrixFree ((FcMatrix *) v.u.m);
77 FcCharSetDestroy ((FcCharSet *) v.u.c);
80 FcLangSetDestroy ((FcLangSet *) v.u.l);
88 FcValueCanonicalize (const FcValue *v)
90 if (v->type & FC_STORAGE_STATIC)
94 switch (v->type & ~FC_STORAGE_STATIC)
97 new.u.s = fc_value_string(v);
98 new.type = FcTypeString;
101 new.u.c = fc_value_charset(v);
102 new.type = FcTypeCharSet;
105 new.u.l = fc_value_langset(v);
106 new.type = FcTypeLangSet;
115 FcValueSave (FcValue v)
119 v.u.s = FcStrCopy (v.u.s);
124 v.u.m = FcMatrixCopy (v.u.m);
129 v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
134 v.u.l = FcLangSetCopy (v.u.l);
145 FcValueListDestroy (FcValueListPtr l)
148 for (; FcValueListPtrU(l); l = next)
150 switch (FcValueListPtrU(l)->value.type) {
152 FcStrFree ((FcChar8 *)FcValueListPtrU(l)->value.u.s);
155 FcMatrixFree ((FcMatrix *)FcValueListPtrU(l)->value.u.m);
159 ((FcCharSet *) (FcValueListPtrU(l)->value.u.c));
163 ((FcLangSet *) (FcValueListPtrU(l)->value.u.l));
168 next = FcValueListPtrU(l)->next;
169 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
170 if (l.bank == FC_BANK_DYNAMIC)
176 FcValueEqual (FcValue va, FcValue vb)
178 if (va.type != vb.type)
180 if (va.type == FcTypeInteger)
182 va.type = FcTypeDouble;
185 if (vb.type == FcTypeInteger)
187 vb.type = FcTypeDouble;
190 if (va.type != vb.type)
197 return va.u.i == vb.u.i;
199 return va.u.d == vb.u.d;
201 return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
203 return va.u.b == vb.u.b;
205 return FcMatrixEqual (va.u.m, vb.u.m);
207 return FcCharSetEqual (va.u.c, vb.u.c);
209 return va.u.f == vb.u.f;
211 return FcLangSetEqual (va.u.l, vb.u.l);
217 FcDoubleHash (double d)
227 FcStringHash (const FcChar8 *s)
234 h = ((h << 1) | (h >> 31)) ^ c;
239 FcValueHash (const FcValue *v0)
241 FcValue v = FcValueCanonicalize(v0);
246 return (FcChar32) v.u.i;
248 return FcDoubleHash (v.u.d);
250 return FcStringHash (v.u.s);
252 return (FcChar32) v.u.b;
254 return (FcDoubleHash (v.u.m->xx) ^
255 FcDoubleHash (v.u.m->xy) ^
256 FcDoubleHash (v.u.m->yx) ^
257 FcDoubleHash (v.u.m->yy));
259 return (FcChar32) v.u.c->num;
261 return FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->family_name) ^
262 FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->style_name);
264 return FcLangSetHash (v.u.l);
270 FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
272 if (FcValueListPtrU(la) == FcValueListPtrU(lb))
275 while (FcValueListPtrU(la) && FcValueListPtrU(lb))
277 if (!FcValueEqual (FcValueListPtrU(la)->value,
278 FcValueListPtrU(lb)->value))
280 la = FcValueListPtrU(la)->next;
281 lb = FcValueListPtrU(lb)->next;
283 if (FcValueListPtrU(la) || FcValueListPtrU(lb))
289 FcValueListHash (FcValueListPtr l)
293 while (FcValueListPtrU(l))
295 hash = ((hash << 1) | (hash >> 31)) ^
296 FcValueHash (&FcValueListPtrU(l)->value);
297 l = FcValueListPtrU(l)->next;
303 FcPatternDestroy (FcPattern *p)
307 if (p->ref == FC_REF_CONSTANT || --p->ref > 0)
310 if (FcPatternFindFullFname (p))
312 FcStrFree ((FcChar8 *)FcPatternFindFullFname (p));
313 FcPatternAddFullFname (p, 0);
316 for (i = 0; i < p->num; i++)
317 FcValueListDestroy ((FcPatternEltU(p->elts)+i)->values);
320 if (FcPatternEltU(p->elts) && p->elts.bank == FC_BANK_DYNAMIC)
322 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
323 free (FcPatternEltU(p->elts));
324 p->elts = FcPatternEltPtrCreateDynamic(0);
327 FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern));
331 #define FC_VALUE_LIST_HASH_SIZE 257
332 #define FC_PATTERN_HASH_SIZE 67
334 typedef struct _FcValueListEnt FcValueListEnt;
336 struct _FcValueListEnt {
337 FcValueListEnt *next;
342 typedef union _FcValueListAlign {
347 static int FcValueListFrozenCount[FcTypeLangSet + 1];
348 static int FcValueListFrozenBytes[FcTypeLangSet + 1];
349 static char FcValueListFrozenName[][8] = {
362 FcValueListReport (void);
365 FcValueListReport (void)
369 printf ("Fc Frozen Values:\n");
370 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
371 for (t = FcTypeVoid; t <= FcTypeLangSet; t++)
372 printf ("\t%8s %9d %9d\n", FcValueListFrozenName[t],
373 FcValueListFrozenCount[t], FcValueListFrozenBytes[t]);
376 static FcValueListEnt *
377 FcValueListEntCreate (FcValueListPtr h)
379 FcValueListAlign *ea;
387 for (l = h; FcValueListPtrU(l); l = FcValueListPtrU(l)->next)
389 size = sizeof (FcValueListAlign) + n * sizeof (FcValueList);
390 FcValueListFrozenCount[FcValueListPtrU(h)->value.type]++;
391 FcValueListFrozenBytes[FcValueListPtrU(h)->value.type] += size;
392 // this leaks for some reason
393 ea = malloc (sizeof (FcValueListAlign));
396 new = malloc (n * sizeof (FcValueList));
399 memset(new, 0, n * sizeof (FcValueList));
400 FcMemAlloc (FC_MEM_VALLIST, size);
402 e->list = (FcValueListPtr) FcValueListPtrCreateDynamic(new);
403 for (l = h; FcValueListPtrU(l);
404 l = FcValueListPtrU(l)->next, new++)
406 if ((FcValueListPtrU(l)->value.type & ~FC_STORAGE_STATIC) == FcTypeString)
408 new->value.type = FcTypeString;
409 new->value.u.s = FcStrStaticName
410 (fc_value_string(&FcValueListPtrU(l)->value));
414 new->value = FcValueSave (FcValueCanonicalize
415 (&FcValueListPtrU(l)->value));
417 new->binding = FcValueListPtrU(l)->binding;
418 if (FcValueListPtrU(FcValueListPtrU(l)->next))
420 new->next = FcValueListPtrCreateDynamic(new + 1);
424 new->next = FcValueListPtrCreateDynamic(0);
431 FcValueListEntDestroy (FcValueListEnt *e)
435 FcValueListFrozenCount[FcValueListPtrU(e->list)->value.type]--;
437 /* XXX: We should perform these two operations with "size" as
438 computed in FcValueListEntCreate, but we don't have access to
439 that value here. Without this, the FcValueListFrozenBytes
440 values will be wrong as will the FcMemFree counts.
442 FcValueListFrozenBytes[e->list->value.type] -= size;
443 FcMemFree (FC_MEM_VALLIST, size);
446 for (l = e->list; FcValueListPtrU(l);
447 l = FcValueListPtrU(l)->next)
449 if (FcValueListPtrU(l)->value.type != FcTypeString)
450 FcValueDestroy (FcValueListPtrU(l)->value);
452 /* XXX: Are we being too chummy with the implementation here to
453 free(e) when it was actually the enclosing FcValueListAlign
454 that was allocated? */
458 static int FcValueListTotal;
459 static int FcValueListUsed;
461 static FcValueListEnt *FcValueListHashTable[FC_VALUE_LIST_HASH_SIZE];
463 static FcValueListPtr
464 FcValueListFreeze (FcValueListPtr l)
466 FcChar32 hash = FcValueListHash (l);
467 FcValueListEnt **bucket = &FcValueListHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
471 for (ent = *bucket; ent; ent = ent->next)
473 if (ent->hash == hash && FcValueListEqual (ent->list, l))
477 ent = FcValueListEntCreate (l);
479 return FcValueListPtrCreateDynamic(0);
489 FcValueListThawAll (void)
492 FcValueListEnt *ent, *next;
494 for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
496 for (ent = FcValueListHashTable[i]; ent; ent = next)
499 FcValueListEntDestroy (ent);
501 FcValueListHashTable[i] = 0;
504 FcValueListTotal = 0;
509 FcPatternBaseHash (FcPattern *b)
511 FcChar32 hash = b->num;
514 for (i = 0; i < b->num; i++)
515 hash = ((hash << 1) | (hash >> 31)) ^
516 (long) (FcValueListPtrU((FcPatternEltU(b->elts)+i)->values));
520 typedef struct _FcPatternEnt FcPatternEnt;
522 struct _FcPatternEnt {
528 static int FcPatternTotal;
529 static int FcPatternUsed;
531 static FcPatternEnt *FcPatternHashTable[FC_VALUE_LIST_HASH_SIZE];
534 FcPatternBaseFreeze (FcPattern *b)
538 FcChar32 hash = FcPatternBaseHash (b);
539 FcPatternEnt **bucket = &FcPatternHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
544 for (ent = *bucket; ent; ent = ent->next)
546 if (ent->hash == hash && b->num == ent->pattern->num)
548 for (i = 0; i < b->num; i++)
550 if (FcObjectPtrCompare((FcPatternEltU(b->elts)+i)->object,
551 (FcPatternEltU(ent->pattern->elts)+i)->object) != 0)
553 if (FcValueListPtrU((FcPatternEltU(b->elts)+i)->values) !=
554 FcValueListPtrU((FcPatternEltU(ent->pattern->elts)+i)->values))
563 * Compute size of pattern + elts
565 ent = malloc (sizeof (FcPatternEnt));
569 FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPatternEnt));
572 ep = FcPatternCreate();
576 epp = malloc(b->num * sizeof (FcPatternElt));
579 ep->elts = FcPatternEltPtrCreateDynamic(epp);
581 FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num));
585 ep->ref = FC_REF_CONSTANT;
587 for (i = 0; i < b->num; i++)
589 (FcPatternEltU(ep->elts)+i)->values =
590 (FcPatternEltU(b->elts)+i)->values;
591 (FcPatternEltU(ep->elts)+i)->object =
592 (FcPatternEltU(b->elts)+i)->object;
595 if (FcPatternFindElt (b, FC_FILE))
596 FcPatternTransferFullFname (ep, b);
604 FcMemFree (FC_MEM_PATTERN, sizeof (FcPatternEnt));
610 FcPatternBaseThawAll (void)
613 FcPatternEnt *ent, *next;
615 for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
617 for (ent = FcPatternHashTable[i]; ent; ent = next)
622 FcPatternHashTable[i] = 0;
630 FcPatternFreeze (FcPattern *p)
632 FcPattern *b, *n = 0;
636 if (p->ref == FC_REF_CONSTANT)
639 b = FcPatternCreate();
647 e = malloc(b->num * sizeof (FcPatternElt));
650 b->elts = FcPatternEltPtrCreateDynamic(e);
651 FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num));
654 * Freeze object lists
656 for (i = 0; i < p->num; i++)
658 (FcPatternEltU(b->elts)+i)->object =
659 (FcPatternEltU(p->elts)+i)->object;
660 (FcPatternEltU(b->elts)+i)->values =
661 FcValueListFreeze((FcPatternEltU(p->elts)+i)->values);
662 if (!FcValueListPtrU((FcPatternEltU(p->elts)+i)->values))
666 if (FcPatternFindElt (p, FC_FILE))
667 FcPatternTransferFullFname (b, p);
672 n = FcPatternBaseFreeze (b);
674 if (FcDebug() & FC_DBG_MEMORY)
676 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal, FcValueListUsed);
677 printf ("Patterns: total %9d used %9d\n", FcPatternTotal, FcPatternUsed);
681 free(FcPatternEltU(b->elts));
682 b->elts = FcPatternEltPtrCreateDynamic(0);
683 FcMemFree (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num));
686 assert (FcPatternEqual (n, p));
692 FcPatternPosition (const FcPattern *p, const char *object)
694 int low, high, mid, c;
697 obj = FcObjectToPtr(object);
704 mid = (low + high) >> 1;
705 c = FcObjectPtrCompare((FcPatternEltU(p->elts)+mid)->object, obj);
719 FcPatternFindElt (const FcPattern *p, const char *object)
721 int i = FcPatternPosition (p, object);
724 return FcPatternEltU(p->elts)+i;
728 FcPatternInsertElt (FcPattern *p, const char *object)
733 i = FcPatternPosition (p, object);
738 /* reallocate array */
739 if (p->num + 1 >= p->size)
741 int s = p->size + 16;
742 if (FcPatternEltU(p->elts))
744 FcPatternElt *e0 = FcPatternEltU(p->elts);
745 e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
746 if (!e) /* maybe it was mmapped */
748 e = malloc(s * sizeof (FcPatternElt));
750 memcpy(e, e0, p->num * sizeof (FcPatternElt));
754 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
757 p->elts = FcPatternEltPtrCreateDynamic(e);
759 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
760 FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
763 (FcPatternEltU(p->elts)+p->size)->object = 0;
764 (FcPatternEltU(p->elts)+p->size)->values =
765 FcValueListPtrCreateDynamic(0);
771 memmove (FcPatternEltU(p->elts) + i + 1,
772 FcPatternEltU(p->elts) + i,
773 sizeof (FcPatternElt) *
779 (FcPatternEltU(p->elts)+i)->object = FcObjectToPtr (object);
780 (FcPatternEltU(p->elts)+i)->values = FcValueListPtrCreateDynamic(0);
783 return FcPatternEltU(p->elts)+i;
787 FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
794 if (pa->num != pb->num)
796 for (i = 0; i < pa->num; i++)
798 if (FcObjectPtrCompare((FcPatternEltU(pa->elts)+i)->object,
799 (FcPatternEltU(pb->elts)+i)->object) != 0)
801 if (!FcValueListEqual ((FcPatternEltU(pa->elts)+i)->values,
802 (FcPatternEltU(pb->elts)+i)->values))
809 FcPatternHash (const FcPattern *p)
814 for (i = 0; i < p->num; i++)
816 h = (((h << 1) | (h >> 31)) ^
817 FcStringHash ((FcChar8 *)FcObjectPtrU ((FcPatternEltU(p->elts)+i)->object)) ^
818 FcValueListHash ((FcPatternEltU(p->elts)+i)->values));
824 FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
826 FcPatternElt *ea, *eb;
829 for (i = 0; i < os->nobject; i++)
831 ea = FcPatternFindElt (pai, os->objects[i]);
832 eb = FcPatternFindElt (pbi, os->objects[i]);
837 if (!FcValueListEqual (ea->values, eb->values))
850 FcPatternAddWithBinding (FcPattern *p,
853 FcValueBinding binding,
857 FcValueListPtr new, *prev;
860 if (p->ref == FC_REF_CONSTANT)
863 newp = malloc (sizeof (FcValueList));
867 memset(newp, 0, sizeof (FcValueList));
868 new = FcValueListPtrCreateDynamic(newp);
869 FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
871 value = FcValueSave (value);
872 if (value.type == FcTypeVoid)
875 /* quick and dirty hack to enable FcCompareFamily speedup:
876 * only allow strings to be added under the FC_FAMILY key.
877 * a better hack would use FcBaseObjectTypes to check all objects. */
878 if (FcObjectToPtr(object) == FcObjectToPtr(FC_FAMILY) &&
879 value.type != FcTypeString)
882 FcValueListPtrU(new)->value = value;
883 FcValueListPtrU(new)->binding = binding;
884 FcValueListPtrU(new)->next = FcValueListPtrCreateDynamic(0);
886 e = FcPatternInsertElt (p, object);
892 for (prev = &e->values; FcValueListPtrU(*prev); prev = &FcValueListPtrU(*prev)->next)
898 FcValueListPtrU(new)->next = e->values;
905 switch (value.type) {
907 FcStrFree ((FcChar8 *) value.u.s);
910 FcMatrixFree ((FcMatrix *) value.u.m);
913 FcCharSetDestroy ((FcCharSet *) value.u.c);
916 FcLangSetDestroy ((FcLangSet *) value.u.l);
922 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
923 free (FcValueListPtrU(new));
929 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
931 return FcPatternAddWithBinding (p, object, value, FcValueBindingStrong, append);
935 FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
937 return FcPatternAddWithBinding (p, object, value, FcValueBindingWeak, append);
941 FcPatternDel (FcPattern *p, const char *object)
945 e = FcPatternFindElt (p, object);
950 FcValueListDestroy (e->values);
952 /* shuffle existing ones down */
954 (FcPatternEltU(p->elts) + p->num - (e + 1)) *
955 sizeof (FcPatternElt));
957 (FcPatternEltU(p->elts)+p->num)->object = 0;
958 (FcPatternEltU(p->elts)+p->num)->values = FcValueListPtrCreateDynamic(0);
963 FcPatternRemove (FcPattern *p, const char *object, int id)
966 FcValueListPtr *prev, l;
968 e = FcPatternFindElt (p, object);
971 for (prev = &e->values;
972 FcValueListPtrU(l = *prev);
973 prev = &FcValueListPtrU(l)->next)
977 *prev = FcValueListPtrU(l)->next;
978 FcValueListPtrU(l)->next = FcValueListPtrCreateDynamic(0);
979 FcValueListDestroy (l);
980 if (!FcValueListPtrU(e->values))
981 FcPatternDel (p, object);
990 FcPatternAddInteger (FcPattern *p, const char *object, int i)
994 v.type = FcTypeInteger;
996 return FcPatternAdd (p, object, v, FcTrue);
1000 FcPatternAddDouble (FcPattern *p, const char *object, double d)
1004 v.type = FcTypeDouble;
1006 return FcPatternAdd (p, object, v, FcTrue);
1011 FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
1015 v.type = FcTypeString;
1016 v.u.s = FcStrStaticName(s);
1017 return FcPatternAdd (p, object, v, FcTrue);
1021 FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
1025 v.type = FcTypeMatrix;
1027 return FcPatternAdd (p, object, v, FcTrue);
1032 FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
1036 v.type = FcTypeBool;
1038 return FcPatternAdd (p, object, v, FcTrue);
1042 FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
1046 v.type = FcTypeCharSet;
1047 v.u.c = (FcCharSet *)c;
1048 return FcPatternAdd (p, object, v, FcTrue);
1052 FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
1056 v.type = FcTypeFTFace;
1058 return FcPatternAdd (p, object, v, FcTrue);
1062 FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
1066 v.type = FcTypeLangSet;
1067 v.u.l = (FcLangSet *)ls;
1068 return FcPatternAdd (p, object, v, FcTrue);
1072 FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
1077 e = FcPatternFindElt (p, object);
1079 return FcResultNoMatch;
1080 for (l = e->values; FcValueListPtrU(l); l = FcValueListPtrU(l)->next)
1084 *v = FcValueCanonicalize(&FcValueListPtrU(l)->value);
1085 return FcResultMatch;
1089 return FcResultNoId;
1093 FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
1098 r = FcPatternGet (p, object, id, &v);
1099 if (r != FcResultMatch)
1109 return FcResultTypeMismatch;
1111 return FcResultMatch;
1115 FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
1120 r = FcPatternGet (p, object, id, &v);
1121 if (r != FcResultMatch)
1128 *d = (double) v.u.i;
1131 return FcResultTypeMismatch;
1133 return FcResultMatch;
1137 FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
1142 r = FcPatternGet (p, object, id, &v);
1143 if (r != FcResultMatch)
1145 if (v.type != FcTypeString)
1146 return FcResultTypeMismatch;
1148 if (FcObjectToPtr(object) == FcObjectToPtr(FC_FILE))
1150 const char *fn, *fpath;
1154 fn = FcPatternFindFullFname(p);
1157 *s = (FcChar8 *) fn;
1158 return FcResultMatch;
1163 *s = (FcChar8 *) v.u.s;
1164 return FcResultMatch;
1167 fpath = FcCacheFindBankDir (p->bank);
1168 size = strlen((char*)fpath) + 1 + strlen ((char *)v.u.s) + 1;
1169 fname = malloc (size);
1171 return FcResultOutOfMemory;
1173 FcMemAlloc (FC_MEM_STRING, size);
1174 strcpy ((char *)fname, (char *)fpath);
1175 strcat ((char *)fname, "/");
1176 strcat ((char *)fname, (char *)v.u.s);
1178 FcPatternAddFullFname (p, (const char *)fname);
1179 *s = (FcChar8 *)fname;
1180 return FcResultMatch;
1183 *s = (FcChar8 *) v.u.s;
1184 return FcResultMatch;
1188 FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
1193 r = FcPatternGet (p, object, id, &v);
1194 if (r != FcResultMatch)
1196 if (v.type != FcTypeMatrix)
1197 return FcResultTypeMismatch;
1198 *m = (FcMatrix *)v.u.m;
1199 return FcResultMatch;
1204 FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
1209 r = FcPatternGet (p, object, id, &v);
1210 if (r != FcResultMatch)
1212 if (v.type != FcTypeBool)
1213 return FcResultTypeMismatch;
1215 return FcResultMatch;
1219 FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
1224 r = FcPatternGet (p, object, id, &v);
1225 if (r != FcResultMatch)
1227 if (v.type != FcTypeCharSet)
1228 return FcResultTypeMismatch;
1229 *c = (FcCharSet *)v.u.c;
1230 return FcResultMatch;
1234 FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
1239 r = FcPatternGet (p, object, id, &v);
1240 if (r != FcResultMatch)
1242 if (v.type != FcTypeFTFace)
1243 return FcResultTypeMismatch;
1244 *f = (FT_Face) v.u.f;
1245 return FcResultMatch;
1249 FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
1254 r = FcPatternGet (p, object, id, &v);
1255 if (r != FcResultMatch)
1257 if (v.type != FcTypeLangSet)
1258 return FcResultTypeMismatch;
1259 *ls = (FcLangSet *)v.u.l;
1260 return FcResultMatch;
1264 FcPatternDuplicate (const FcPattern *orig)
1271 new = FcPatternCreate ();
1275 e = FcPatternEltU(orig->elts);
1277 for (i = 0; i < orig->num; i++)
1279 for (l = (e + i)->values;
1281 l = FcValueListPtrU(l)->next)
1282 if (!FcPatternAdd (new, FcObjectPtrU((e + i)->object),
1283 FcValueCanonicalize(&FcValueListPtrU(l)->value),
1287 FcPatternTransferFullFname (new, orig);
1292 FcPatternDestroy (new);
1298 FcPatternReference (FcPattern *p)
1300 if (p->ref != FC_REF_CONSTANT)
1305 FcPatternVaBuild (FcPattern *orig, va_list va)
1309 FcPatternVapBuild (ret, orig, va);
1314 FcPatternBuild (FcPattern *orig, ...)
1318 va_start (va, orig);
1319 FcPatternVapBuild (orig, orig, va);
1325 * Add all of the elements in 's' to 'p'
1328 FcPatternAppend (FcPattern *p, FcPattern *s)
1334 for (i = 0; i < s->num; i++)
1336 e = FcPatternEltU(s->elts)+i;
1337 for (v = e->values; FcValueListPtrU(v);
1338 v = FcValueListPtrU(v)->next)
1340 if (!FcPatternAddWithBinding (p, FcObjectPtrU(e->object),
1341 FcValueCanonicalize(&FcValueListPtrU(v)->value),
1342 FcValueListPtrU(v)->binding, FcTrue))
1349 #define OBJECT_HASH_SIZE 31
1350 static struct objectBucket {
1351 struct objectBucket *next;
1353 } *FcObjectBuckets[OBJECT_HASH_SIZE];
1356 FcStrStaticName (const FcChar8 *name)
1358 FcChar32 hash = FcStringHash (name);
1359 struct objectBucket **p;
1360 struct objectBucket *b;
1363 for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
1364 if (b->hash == hash && !strcmp ((char *)name, (char *) (b + 1)))
1365 return (FcChar8 *) (b + 1);
1366 size = sizeof (struct objectBucket) + strlen ((char *)name) + 1;
1367 b = malloc (size + sizeof (int));
1368 /* workaround glibc bug which reads strlen in groups of 4 */
1369 FcMemAlloc (FC_MEM_STATICSTR, size + sizeof (int));
1374 strcpy ((char *) (b + 1), (char *)name);
1376 return (FcChar8 *) (b + 1);
1380 FcStrStaticNameFini (void)
1383 struct objectBucket *b, *next;
1386 for (i = 0; i < OBJECT_HASH_SIZE; i++)
1388 for (b = FcObjectBuckets[i]; b; b = next)
1391 name = (char *) (b + 1);
1392 size = sizeof (struct objectBucket) + strlen (name) + 1;
1393 FcMemFree (FC_MEM_STATICSTR, size);
1396 FcObjectBuckets[i] = 0;
1401 FcPatternFini (void)
1403 FcPatternBaseThawAll ();
1404 FcValueListThawAll ();
1405 FcStrStaticNameFini ();
1406 FcObjectStaticNameFini ();
1410 FcPatternEltU (FcPatternEltPtr pei)
1412 if (pei.bank == FC_BANK_DYNAMIC)
1415 return &fcpatternelts[FcCacheBankToIndex(pei.bank)][pei.u.stat];
1418 static FcPatternEltPtr
1419 FcPatternEltPtrCreateDynamic (FcPatternElt * e)
1421 FcPatternEltPtr new;
1422 new.bank = FC_BANK_DYNAMIC;
1427 static FcPatternEltPtr
1428 FcPatternEltPtrCreateStatic (int bank, int i)
1430 FcPatternEltPtr new;
1437 FcStrNewBank (void);
1439 FcStrNeededBytes (const FcChar8 * s);
1441 FcStrNeededBytesAlign (void);
1443 FcStrDistributeBytes (FcCache * metadata, void * block_ptr);
1444 static const FcChar8 *
1445 FcStrSerialize (int bank, const FcChar8 * s);
1447 FcStrUnserialize (FcCache metadata, void *block_ptr);
1450 FcValueListNewBank (void);
1452 FcValueListNeededBytes (FcValueList * vl);
1454 FcValueListNeededBytesAlign (void);
1456 FcValueListDistributeBytes (FcCache * metadata, void *block_ptr);
1457 static FcValueListPtr
1458 FcValueListSerialize(int bank, FcValueList *pi);
1460 FcValueListUnserialize (FcCache metadata, void *block_ptr);
1464 FcPatternNewBank (void)
1466 fcpattern_count = 0;
1467 fcpatternelt_count = 0;
1470 FcValueListNewBank();
1474 FcPatternNeededBytes (FcPattern * p)
1479 fcpatternelt_count += p->num;
1481 for (i = 0; i < p->num; i++)
1483 c = FcValueListNeededBytes (FcValueListPtrU
1484 (((FcPatternEltU(p->elts)+i)->values)));
1490 return cum + sizeof (FcPattern) + sizeof(FcPatternElt)*p->num;
1494 FcPatternNeededBytesAlign (void)
1496 return __alignof__ (FcPattern) + __alignof__ (FcPatternElt) +
1497 FcValueListNeededBytesAlign ();
1501 FcPatternEnsureBank (int bi)
1507 if (!fcpatterns || fcpattern_bank_count <= bi)
1509 int new_count = bi + 4;
1510 pp = realloc (fcpatterns, sizeof (FcPattern *) * new_count);
1514 FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern *) * new_count);
1517 ep = realloc (fcpatternelts, sizeof (FcPatternElt *) * new_count);
1521 FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt *) * new_count);
1524 for (i = fcpattern_bank_count; i < new_count; i++)
1527 fcpatternelts[i] = 0;
1530 fcpattern_bank_count = new_count;
1533 FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern) * fcpattern_count);
1538 FcPatternDistributeBytes (FcCache * metadata, void * block_ptr)
1540 int bi = FcCacheBankToIndex(metadata->bank);
1542 if (!FcPatternEnsureBank(bi))
1546 block_ptr = ALIGN(block_ptr, FcPattern);
1547 fcpatterns[bi] = (FcPattern *)block_ptr;
1548 block_ptr = (void *)((char *)block_ptr +
1549 (sizeof (FcPattern) * fcpattern_count));
1551 FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt) * fcpatternelt_count);
1552 fcpatternelt_ptr = 0;
1553 block_ptr = ALIGN(block_ptr, FcPatternElt);
1554 fcpatternelts[bi] = (FcPatternElt *)block_ptr;
1555 block_ptr = (void *)((char *)block_ptr +
1556 (sizeof (FcPatternElt) * fcpatternelt_count));
1558 metadata->pattern_count = fcpattern_count;
1559 metadata->patternelt_count = fcpatternelt_count;
1561 block_ptr = FcStrDistributeBytes (metadata, block_ptr);
1562 block_ptr = FcValueListDistributeBytes (metadata, block_ptr);
1567 FcPatternSerialize (int bank, FcPattern *old)
1570 FcPatternElt *e, *nep;
1572 FcValueListPtr v, nv_head, nvp;
1573 int i, elts, bi = FcCacheBankToIndex(bank);
1575 p = &fcpatterns[bi][fcpattern_ptr++];
1577 elts = fcpatternelt_ptr;
1578 nep = &fcpatternelts[bi][elts];
1582 fcpatternelt_ptr += old->num;
1584 for (e = FcPatternEltU(old->elts), i=0; i < old->num; i++, e++)
1587 nvp = nv_head = FcValueListSerialize(bank, FcValueListPtrU(v));
1588 if (!FcValueListPtrU(nv_head))
1590 nv = FcValueListPtrU(nvp);
1594 v = FcValueListPtrU(v)->next,
1595 nv = FcValueListPtrU(nv->next))
1598 if (FcValueListPtrU(FcValueListPtrU(v)->next))
1600 nvp = FcValueListSerialize
1601 (bank, FcValueListPtrU(FcValueListPtrU(v)->next));
1606 nep[i].values = nv_head;
1607 nep[i].object = e->object;
1610 p->elts = old->elts;
1611 p->elts = FcPatternEltPtrCreateStatic(bank, elts);
1614 p->ref = FC_REF_CONSTANT;
1619 FcPatternUnserialize (FcCache metadata, void *block_ptr)
1621 int bi = FcCacheBankToIndex(metadata.bank);
1622 if (!FcPatternEnsureBank(bi))
1625 FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern) * metadata.pattern_count);
1626 block_ptr = ALIGN(block_ptr, FcPattern);
1627 fcpatterns[bi] = (FcPattern *)block_ptr;
1628 block_ptr = (void *)((char *)block_ptr +
1629 (sizeof (FcPattern) * metadata.pattern_count));
1631 FcMemAlloc (FC_MEM_PATELT,
1632 sizeof (FcPatternElt) * metadata.patternelt_count);
1633 block_ptr = ALIGN(block_ptr, FcPatternElt);
1634 fcpatternelts[bi] = (FcPatternElt *)block_ptr;
1635 block_ptr = (void *)((char *)block_ptr +
1636 (sizeof (FcPatternElt) * metadata.patternelt_count));
1638 block_ptr = FcStrUnserialize (metadata, block_ptr);
1639 block_ptr = FcValueListUnserialize (metadata, block_ptr);
1645 FcValueListNewBank (void)
1647 fcvaluelist_count = 0;
1654 FcValueListNeededBytes (FcValueList *p)
1661 vl = FcValueListPtrU(vl->next))
1663 FcValue v = FcValueCanonicalize(&vl->value); // unserialize just in case
1668 cum += FcCharSetNeededBytes(v.u.c);
1671 cum += FcLangSetNeededBytes(v.u.l);
1674 cum += FcStrNeededBytes(v.u.s);
1678 fcvaluelist_count++;
1679 cum += sizeof (FcValueList);
1686 FcValueListNeededBytesAlign (void)
1688 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1689 FcStrNeededBytesAlign() + __alignof__ (FcValueList);
1693 FcValueListEnsureBank (int bi)
1697 if (!fcvaluelists || fcvaluelist_bank_count <= bi)
1699 int new_count = bi + 2, i;
1701 pvl = realloc (fcvaluelists, sizeof (FcValueList *) * new_count);
1705 FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList *) * new_count);
1708 for (i = fcvaluelist_bank_count; i < new_count; i++)
1709 fcvaluelists[i] = 0;
1711 fcvaluelist_bank_count = new_count;
1717 FcValueListDistributeBytes (FcCache * metadata, void *block_ptr)
1719 int bi = FcCacheBankToIndex(metadata->bank);
1721 if (!FcValueListEnsureBank(bi))
1724 FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList) * fcvaluelist_count);
1725 fcvaluelist_ptr = 0;
1726 block_ptr = ALIGN(block_ptr, FcValueList);
1727 fcvaluelists[bi] = (FcValueList *)block_ptr;
1728 block_ptr = (void *)((char *)block_ptr +
1729 (sizeof (FcValueList) * fcvaluelist_count));
1730 metadata->valuelist_count = fcvaluelist_count;
1732 block_ptr = FcCharSetDistributeBytes(metadata, block_ptr);
1733 block_ptr = FcLangSetDistributeBytes(metadata, block_ptr);
1738 static FcValueListPtr
1739 FcValueListSerialize(int bank, FcValueList *pi)
1743 int bi = FcCacheBankToIndex(bank);
1747 new.bank = FC_BANK_DYNAMIC;
1752 fcvaluelists[bi][fcvaluelist_ptr] = *pi;
1754 new.u.stat = fcvaluelist_ptr++;
1755 fcvaluelists[bi][new.u.stat].value = FcValueCanonicalize (&pi->value);
1756 v = &fcvaluelists[bi][new.u.stat].value;
1762 const FcChar8 * s = FcStrSerialize(bank, v->u.s);
1764 return FcValueListPtrCreateDynamic(pi);
1765 v->u.s_off = s - (const FcChar8 *)v;
1766 v->type |= FC_STORAGE_STATIC;
1774 FcCharSet * c = FcCharSetSerialize(bank, (FcCharSet *)v->u.c);
1776 return FcValueListPtrCreateDynamic(pi);
1777 v->u.c_off = (char *)c - (char *)v;
1778 v->type |= FC_STORAGE_STATIC;
1784 FcLangSet * l = FcLangSetSerialize(bank, (FcLangSet *)v->u.l);
1786 return FcValueListPtrCreateDynamic(pi);
1787 v->u.l_off = (char *)l - (char *)v;
1788 v->type |= FC_STORAGE_STATIC;
1798 FcValueListUnserialize (FcCache metadata, void *block_ptr)
1800 int bi = FcCacheBankToIndex(metadata.bank);
1802 if (!FcValueListEnsureBank(bi))
1805 FcMemAlloc (FC_MEM_VALLIST,
1806 sizeof (FcValueList) * metadata.valuelist_count);
1807 block_ptr = ALIGN(block_ptr, FcValueList);
1808 fcvaluelists[bi] = (FcValueList *)block_ptr;
1809 block_ptr = (void *)((char *)block_ptr +
1810 (sizeof (FcValueList) * metadata.valuelist_count));
1812 block_ptr = FcCharSetUnserialize(metadata, block_ptr);
1813 block_ptr = FcLangSetUnserialize(metadata, block_ptr);
1819 FcValueListPtrU (FcValueListPtr pi)
1821 if (pi.bank == FC_BANK_DYNAMIC)
1824 return &fcvaluelists[FcCacheBankToIndex(pi.bank)][pi.u.stat];
1828 FcValueListPtrCreateDynamic(FcValueList * p)
1832 r.bank = FC_BANK_DYNAMIC;
1837 static FcChar8 ** static_strs;
1838 static int static_str_bank_count = 0, fcstr_ptr, fcstr_count;
1840 static struct objectBucket *FcStrBuckets[OBJECT_HASH_SIZE];
1846 struct objectBucket *b, *next;
1849 for (i = 0; i < OBJECT_HASH_SIZE; i++)
1851 for (b = FcStrBuckets[i]; b; b = next)
1854 name = (char *) (b + 1);
1855 size = sizeof (struct objectBucket) + strlen (name) + 1;
1856 FcMemFree (FC_MEM_STATICSTR, size);
1859 FcStrBuckets[i] = 0;
1866 FcStrNeededBytes (const FcChar8 * s)
1868 FcChar32 hash = FcStringHash ((const FcChar8 *) s);
1869 struct objectBucket **p;
1870 struct objectBucket *b;
1873 for (p = &FcStrBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
1874 if (b->hash == hash && !strcmp ((char *)s, (char *) (b + 1)))
1876 size = sizeof (struct objectBucket) + strlen ((char *)s) + 1 + sizeof(char *);
1878 FcMemAlloc (FC_MEM_STATICSTR, size);
1883 strcpy ((char *) (b + 1), (char *)s);
1885 /* Yes, the following line is convoluted. However, it is
1886 * incorrect to replace the with a memset, because the C
1887 * specification doesn't guarantee that the null pointer is
1888 * the same as the zero bit pattern. */
1889 *(char **)((char *) (b + 1) + strlen((char *)s) + 1) = 0;
1892 fcstr_count += strlen((char *)s) + 1;
1893 return strlen((char *)s) + 1;
1897 FcStrNeededBytesAlign (void)
1899 return __alignof__ (char);
1903 FcStrEnsureBank (int bi)
1907 if (!static_strs || static_str_bank_count <= bi)
1909 int new_count = bi + 4, i;
1910 ss = realloc (static_strs, sizeof (const char *) * new_count);
1914 FcMemAlloc (FC_MEM_STRING, sizeof (const char *) * (new_count-static_str_bank_count));
1917 for (i = static_str_bank_count; i < new_count; i++)
1919 static_str_bank_count = new_count;
1925 FcStrDistributeBytes (FcCache * metadata, void * block_ptr)
1927 int bi = FcCacheBankToIndex(metadata->bank);
1928 if (!FcStrEnsureBank(bi))
1931 FcMemAlloc (FC_MEM_STRING, sizeof (char) * fcstr_count);
1932 block_ptr = ALIGN (block_ptr, FcChar8);
1933 static_strs[bi] = (FcChar8 *)block_ptr;
1934 block_ptr = (void *)((char *)block_ptr + (sizeof (char) * fcstr_count));
1935 metadata->str_count = fcstr_count;
1941 static const FcChar8 *
1942 FcStrSerialize (int bank, const FcChar8 * s)
1944 FcChar32 hash = FcStringHash ((const FcChar8 *) s);
1945 struct objectBucket **p;
1946 struct objectBucket *b;
1947 int bi = FcCacheBankToIndex(bank);
1949 for (p = &FcStrBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
1950 if (b->hash == hash && !strcmp ((char *)s, (char *) (b + 1)))
1952 FcChar8 * t = *(FcChar8 **)(((FcChar8 *)(b + 1)) + strlen ((char *)s) + 1);
1955 strcpy((char *)(static_strs[bi] + fcstr_ptr), (char *)s);
1956 *(FcChar8 **)((FcChar8 *) (b + 1) + strlen((char *)s) + 1) = (static_strs[bi] + fcstr_ptr);
1957 fcstr_ptr += strlen((char *)s) + 1;
1958 t = *(FcChar8 **)(((FcChar8 *)(b + 1)) + strlen ((char *)s) + 1);
1966 FcStrUnserialize (FcCache metadata, void *block_ptr)
1968 int bi = FcCacheBankToIndex(metadata.bank);
1969 if (!FcStrEnsureBank(bi))
1972 FcMemAlloc (FC_MEM_STRING, sizeof (char) * metadata.str_count);
1973 block_ptr = ALIGN (block_ptr, FcChar8);
1974 static_strs[bi] = (FcChar8 *)block_ptr;
1975 block_ptr = (void *)((char *)block_ptr +
1976 (sizeof (char) * metadata.str_count));
1981 /* we don't store these in the FcPattern itself because
1982 * we don't want to serialize the directory names */
1984 /* I suppose this should be cleaned, too... */
1985 typedef struct _FcPatternDirMapping {
1988 } FcPatternDirMapping;
1990 #define PATTERNDIR_HASH_SIZE 31
1991 static struct patternDirBucket {
1992 struct patternDirBucket *next;
1993 FcPatternDirMapping m;
1994 } FcPatternDirBuckets[PATTERNDIR_HASH_SIZE];
1997 FcPatternAddFullFname (const FcPattern *p, const char *fname)
1999 struct patternDirBucket *pb;
2001 /* N.B. FcPatternHash fails, since it's contents-based, not
2002 * address-based, and we're in the process of mutating the FcPattern. */
2003 for (pb = &FcPatternDirBuckets
2004 [((int)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE];
2005 pb->m.p != p && pb->next;
2011 pb->m.fname = fname;
2015 pb->next = malloc (sizeof (struct patternDirBucket));
2018 FcMemAlloc (FC_MEM_CACHE, sizeof (struct patternDirBucket));
2022 pb->next->m.fname = fname;
2026 FcPatternFindFullFname (const FcPattern *p)
2028 struct patternDirBucket *pb;
2030 for (pb = &FcPatternDirBuckets
2031 [((int)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE];
2040 FcPatternTransferFullFname (const FcPattern *new, const FcPattern *orig)
2043 FcPatternGetString (orig, FC_FILE, 0, &s);
2044 FcPatternAddFullFname (new,
2046 ((FcChar8 *)FcPatternFindFullFname(orig)));