2 * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $
4 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
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.
31 FcPatternCreate (void)
35 p = (FcPattern *) malloc (sizeof (FcPattern));
38 FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern));
47 FcValueDestroy (FcValue v)
51 FcStrFree ((FcChar8 *) v.u.s);
54 FcMatrixFree ((FcMatrix *) v.u.m);
57 FcCharSetDestroy ((FcCharSet *) v.u.c);
60 FcLangSetDestroy ((FcLangSet *) v.u.l);
68 FcValueSave (FcValue v)
72 v.u.s = FcStrCopy (v.u.s);
77 v.u.m = FcMatrixCopy (v.u.m);
82 v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
87 v.u.l = FcLangSetCopy (v.u.l);
98 FcValueListDestroy (FcValueList *l)
103 switch (l->value.type) {
105 FcStrFree ((FcChar8 *) l->value.u.s);
108 FcMatrixFree ((FcMatrix *) l->value.u.m);
111 FcCharSetDestroy ((FcCharSet *) l->value.u.c);
114 FcLangSetDestroy ((FcLangSet *) l->value.u.l);
120 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
126 FcValueEqual (FcValue va, FcValue vb)
128 if (va.type != vb.type)
130 if (va.type == FcTypeInteger)
132 va.type = FcTypeDouble;
135 if (vb.type == FcTypeInteger)
137 vb.type = FcTypeDouble;
140 if (va.type != vb.type)
147 return va.u.i == vb.u.i;
149 return va.u.d == vb.u.d;
151 return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
153 return va.u.b == vb.u.b;
155 return FcMatrixEqual (va.u.m, vb.u.m);
157 return FcCharSetEqual (va.u.c, vb.u.c);
159 return va.u.f == vb.u.f;
161 return FcLangSetEqual (va.u.l, vb.u.l);
167 FcDoubleHash (double d)
177 FcStringHash (const FcChar8 *s)
184 h = ((h << 1) | (h >> 31)) ^ c;
189 FcValueHash (FcValue v)
195 return (FcChar32) v.u.i;
197 return FcDoubleHash (v.u.d);
199 return FcStringHash (v.u.s);
201 return (FcChar32) v.u.b;
203 return (FcDoubleHash (v.u.m->xx) ^
204 FcDoubleHash (v.u.m->xy) ^
205 FcDoubleHash (v.u.m->yx) ^
206 FcDoubleHash (v.u.m->yy));
208 return (FcChar32) v.u.c->num;
210 return FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->family_name) ^
211 FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->style_name);
213 return FcLangSetHash (v.u.l);
219 FcValueListEqual (FcValueList *la, FcValueList *lb)
226 if (!FcValueEqual (la->value, lb->value))
237 FcValueListHash (FcValueList *l)
243 hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (l->value);
250 FcPatternDestroy (FcPattern *p)
254 if (p->ref == FC_REF_CONSTANT || --p->ref > 0)
257 for (i = 0; i < p->num; i++)
258 FcValueListDestroy (p->elts[i].values);
263 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
268 FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern));
272 #define FC_VALUE_LIST_HASH_SIZE 257
273 #define FC_PATTERN_HASH_SIZE 67
275 typedef struct _FcValueListEnt FcValueListEnt;
277 struct _FcValueListEnt {
278 FcValueListEnt *next;
283 typedef union _FcValueListAlign {
288 static int FcValueListFrozenCount[FcTypeLangSet + 1];
289 static int FcValueListFrozenBytes[FcTypeLangSet + 1];
290 static char *FcValueListFrozenName[] = {
303 FcValueListReport (void);
306 FcValueListReport (void)
310 printf ("Fc Frozen Values:\n");
311 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
312 for (t = FcTypeVoid; t <= FcTypeLangSet; t++)
313 printf ("\t%8s %9d %9d\n", FcValueListFrozenName[t],
314 FcValueListFrozenCount[t], FcValueListFrozenBytes[t]);
317 static FcValueListEnt *
318 FcValueListEntCreate (FcValueList *h)
320 FcValueListAlign *ea;
322 FcValueList *l, *new;
329 for (l = h; l; l = l->next)
331 if (l->value.type == FcTypeString)
332 string_size += strlen ((char *) l->value.u.s) + 1;
335 size = sizeof (FcValueListAlign) + n * sizeof (FcValueList) + string_size;
336 FcValueListFrozenCount[h->value.type]++;
337 FcValueListFrozenBytes[h->value.type] += size;
341 FcMemAlloc (FC_MEM_VALLIST, size);
343 e->list = (FcValueList *) (ea + 1);
344 strs = (FcChar8 *) (e->list + n);
346 for (l = h; l; l = l->next, new++)
348 if (l->value.type == FcTypeString)
350 new->value.type = FcTypeString;
351 new->value.u.s = strs;
352 strcpy ((char *) strs, (char *) l->value.u.s);
353 strs += strlen ((char *) strs) + 1;
357 new->value = l->value;
358 new->value = FcValueSave (new->value);
360 new->binding = l->binding;
369 static int FcValueListTotal;
370 static int FcValueListUsed;
373 FcValueListFreeze (FcValueList *l)
375 static FcValueListEnt *hashTable[FC_VALUE_LIST_HASH_SIZE];
376 FcChar32 hash = FcValueListHash (l);
377 FcValueListEnt **bucket = &hashTable[hash % FC_VALUE_LIST_HASH_SIZE];
381 for (ent = *bucket; ent; ent = ent->next)
383 if (ent->hash == hash && FcValueListEqual (ent->list, l))
387 ent = FcValueListEntCreate (l);
399 FcPatternBaseHash (FcPattern *b)
401 FcChar32 hash = b->num;
404 for (i = 0; i < b->num; i++)
405 hash = ((hash << 1) | (hash >> 31)) ^ ((long) b->elts[i].values);
409 typedef struct _FcPatternEnt FcPatternEnt;
411 struct _FcPatternEnt {
417 static int FcPatternTotal;
418 static int FcPatternUsed;
421 FcPatternBaseFreeze (FcPattern *b)
423 static FcPatternEnt *hashTable[FC_VALUE_LIST_HASH_SIZE];
424 FcChar32 hash = FcPatternBaseHash (b);
425 FcPatternEnt **bucket = &hashTable[hash % FC_VALUE_LIST_HASH_SIZE];
433 for (ent = *bucket; ent; ent = ent->next)
435 if (ent->hash == hash && b->num == ent->pattern.num)
437 for (i = 0; i < b->num; i++)
439 if (strcmp (b->elts[i].object, ent->pattern.elts[i].object))
441 if (b->elts[i].values != ent->pattern.elts[i].values)
445 return &ent->pattern;
450 * Compute size of pattern + elts + object names
453 for (i = 0; i < b->num; i++)
454 size_objects += strlen (b->elts[i].object) + 1;
456 size = sizeof (FcPatternEnt) + b->num*sizeof (FcPatternElt) + size_objects;
461 FcMemAlloc (FC_MEM_PATTERN, size);
464 ent->pattern.elts = (FcPatternElt *) (ent + 1);
465 ent->pattern.num = b->num;
466 ent->pattern.size = b->num;
467 ent->pattern.ref = FC_REF_CONSTANT;
469 objects = (char *) (ent->pattern.elts + b->num);
470 for (i = 0; i < b->num; i++)
472 ent->pattern.elts[i].values = b->elts[i].values;
473 strcpy (objects, b->elts[i].object);
474 ent->pattern.elts[i].object = objects;
475 objects += strlen (objects) + 1;
481 return &ent->pattern;
485 FcPatternFreeze (FcPattern *p)
487 FcPattern *b, *n = 0;
491 size = sizeof (FcPattern) + p->num * sizeof (FcPatternElt);
492 b = (FcPattern *) malloc (size);
495 FcMemAlloc (FC_MEM_PATTERN, size);
499 b->elts = (FcPatternElt *) (b + 1);
501 * Freeze object lists
503 for (i = 0; i < p->num; i++)
505 b->elts[i].object = p->elts[i].object;
506 b->elts[i].values = FcValueListFreeze (p->elts[i].values);
507 if (!b->elts[i].values)
513 n = FcPatternBaseFreeze (b);
515 if (FcDebug() & FC_DBG_MEMORY)
517 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal, FcValueListUsed);
518 printf ("Patterns: total %9d used %9d\n", FcPatternTotal, FcPatternUsed);
524 assert (FcPatternEqual (n, p));
530 FcPatternPosition (const FcPattern *p, const char *object)
532 int low, high, mid, c;
540 mid = (low + high) >> 1;
541 c = strcmp (p->elts[mid].object, object);
555 FcPatternFindElt (const FcPattern *p, const char *object)
557 int i = FcPatternPosition (p, object);
564 FcPatternInsertElt (FcPattern *p, const char *object)
569 i = FcPatternPosition (p, object);
575 if (p->num + 1 >= p->size)
577 int s = p->size + 16;
579 e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
581 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
586 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
587 FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
590 p->elts[p->size].object = 0;
591 p->elts[p->size].values = 0;
597 memmove (p->elts + i + 1,
599 sizeof (FcPatternElt) *
605 p->elts[i].object = object;
606 p->elts[i].values = 0;
613 FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
620 if (pa->num != pb->num)
622 for (i = 0; i < pa->num; i++)
624 if (strcmp (pa->elts[i].object, pb->elts[i].object) != 0)
626 if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values))
633 FcPatternHash (const FcPattern *p)
638 for (i = 0; i < p->num; i++)
640 h = (((h << 1) | (h >> 31)) ^
641 FcStringHash ((const FcChar8 *) p->elts[i].object) ^
642 FcValueListHash (p->elts[i].values));
648 FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os)
650 FcPatternElt *ea, *eb;
653 for (i = 0; i < os->nobject; i++)
655 ea = FcPatternFindElt (pa, os->objects[i]);
656 eb = FcPatternFindElt (pb, os->objects[i]);
661 if (!FcValueListEqual (ea->values, eb->values))
674 FcPatternAddWithBinding (FcPattern *p,
677 FcValueBinding binding,
681 FcValueList *new, **prev;
683 if (p->ref == FC_REF_CONSTANT)
686 new = (FcValueList *) malloc (sizeof (FcValueList));
690 FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
692 value = FcValueSave (value);
693 if (value.type == FcTypeVoid)
697 new->binding = binding;
700 e = FcPatternInsertElt (p, object);
706 for (prev = &e->values; *prev; prev = &(*prev)->next);
711 new->next = e->values;
718 switch (value.type) {
720 FcStrFree ((FcChar8 *) value.u.s);
723 FcMatrixFree ((FcMatrix *) value.u.m);
726 FcCharSetDestroy ((FcCharSet *) value.u.c);
729 FcLangSetDestroy ((FcLangSet *) value.u.l);
735 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
742 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
744 return FcPatternAddWithBinding (p, object, value, FcValueBindingStrong, append);
748 FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
750 return FcPatternAddWithBinding (p, object, value, FcValueBindingWeak, append);
754 FcPatternDel (FcPattern *p, const char *object)
759 e = FcPatternFindElt (p, object);
766 FcValueListDestroy (e->values);
768 /* shuffle existing ones down */
769 memmove (e, e+1, (p->elts + p->num - (e + 1)) * sizeof (FcPatternElt));
771 p->elts[p->num].object = 0;
772 p->elts[p->num].values = 0;
777 FcPatternAddInteger (FcPattern *p, const char *object, int i)
781 v.type = FcTypeInteger;
783 return FcPatternAdd (p, object, v, FcTrue);
787 FcPatternAddDouble (FcPattern *p, const char *object, double d)
791 v.type = FcTypeDouble;
793 return FcPatternAdd (p, object, v, FcTrue);
798 FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
802 v.type = FcTypeString;
804 return FcPatternAdd (p, object, v, FcTrue);
808 FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
812 v.type = FcTypeMatrix;
813 v.u.m = (FcMatrix *) s;
814 return FcPatternAdd (p, object, v, FcTrue);
819 FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
825 return FcPatternAdd (p, object, v, FcTrue);
829 FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
833 v.type = FcTypeCharSet;
834 v.u.c = (FcCharSet *) c;
835 return FcPatternAdd (p, object, v, FcTrue);
839 FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
843 v.type = FcTypeFTFace;
845 return FcPatternAdd (p, object, v, FcTrue);
849 FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
853 v.type = FcTypeLangSet;
854 v.u.l = (FcLangSet *) ls;
855 return FcPatternAdd (p, object, v, FcTrue);
859 FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
864 e = FcPatternFindElt (p, object);
866 return FcResultNoMatch;
867 for (l = e->values; l; l = l->next)
872 return FcResultMatch;
880 FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
885 r = FcPatternGet (p, object, id, &v);
886 if (r != FcResultMatch)
896 return FcResultTypeMismatch;
898 return FcResultMatch;
902 FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
907 r = FcPatternGet (p, object, id, &v);
908 if (r != FcResultMatch)
918 return FcResultTypeMismatch;
920 return FcResultMatch;
924 FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
929 r = FcPatternGet (p, object, id, &v);
930 if (r != FcResultMatch)
932 if (v.type != FcTypeString)
933 return FcResultTypeMismatch;
934 *s = (FcChar8 *) v.u.s;
935 return FcResultMatch;
939 FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
944 r = FcPatternGet (p, object, id, &v);
945 if (r != FcResultMatch)
947 if (v.type != FcTypeMatrix)
948 return FcResultTypeMismatch;
949 *m = (FcMatrix *) v.u.m;
950 return FcResultMatch;
955 FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
960 r = FcPatternGet (p, object, id, &v);
961 if (r != FcResultMatch)
963 if (v.type != FcTypeBool)
964 return FcResultTypeMismatch;
966 return FcResultMatch;
970 FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
975 r = FcPatternGet (p, object, id, &v);
976 if (r != FcResultMatch)
978 if (v.type != FcTypeCharSet)
979 return FcResultTypeMismatch;
980 *c = (FcCharSet *) v.u.c;
981 return FcResultMatch;
985 FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
990 r = FcPatternGet (p, object, id, &v);
991 if (r != FcResultMatch)
993 if (v.type != FcTypeFTFace)
994 return FcResultTypeMismatch;
995 *f = (FT_Face) v.u.f;
996 return FcResultMatch;
1000 FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
1005 r = FcPatternGet (p, object, id, &v);
1006 if (r != FcResultMatch)
1008 if (v.type != FcTypeLangSet)
1009 return FcResultTypeMismatch;
1010 *ls = (FcLangSet *) v.u.l;
1011 return FcResultMatch;
1015 FcPatternDuplicate (const FcPattern *orig)
1021 new = FcPatternCreate ();
1025 for (i = 0; i < orig->num; i++)
1027 for (l = orig->elts[i].values; l; l = l->next)
1028 if (!FcPatternAdd (new, orig->elts[i].object, l->value, FcTrue))
1035 FcPatternDestroy (new);
1041 FcPatternReference (FcPattern *p)
1043 if (p->ref != FC_REF_CONSTANT)
1048 FcPatternVaBuild (FcPattern *orig, va_list va)
1052 FcPatternVapBuild (ret, orig, va);
1057 FcPatternBuild (FcPattern *orig, ...)
1061 va_start (va, orig);
1062 FcPatternVapBuild (orig, orig, va);