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.
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);