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 static FcPattern
* fcpatterns
= NULL
;
32 static int fcpattern_ptr
, fcpattern_count
;
33 static FcPatternElt
* fcpatternelts
= NULL
;
34 static int fcpatternelt_ptr
, fcpatternelt_count
;
35 static FcValueList
* fcvaluelists
= NULL
;
36 static int fcvaluelist_ptr
, fcvaluelist_count
;
38 static char * object_content
;
39 static int object_content_count
;
40 static int object_content_ptr
;
43 FcPatternEltIsDynamic (FcPatternEltPtr pei
);
45 static FcPatternEltPtr
46 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
);
49 FcPatternCreate (void)
53 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
56 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
59 p
->elts
= FcPatternEltPtrCreateDynamic(0);
65 FcValueDestroy (FcValue v
)
69 FcObjectPtrDestroy (v
.u
.si
);
72 FcMatrixPtrDestroy (v
.u
.mi
);
75 FcCharSetPtrDestroy (v
.u
.ci
);
78 FcLangSetPtrDestroy (v
.u
.li
);
86 FcValueSave (FcValue v
)
90 v
.u
.si
= FcObjectPtrCreateDynamic(FcStrCopy (FcObjectPtrU(v
.u
.si
)));
91 if (!FcObjectPtrU(v
.u
.si
))
95 v
.u
.mi
= FcMatrixPtrCreateDynamic
96 (FcMatrixCopy (FcMatrixPtrU(v
.u
.mi
)));
97 if (!FcMatrixPtrU(v
.u
.mi
))
101 v
.u
.ci
= FcCharSetPtrCreateDynamic
102 (FcCharSetCopy (FcCharSetPtrU(v
.u
.ci
)));
103 if (!FcCharSetPtrU(v
.u
.ci
))
107 v
.u
.li
= FcLangSetPtrCreateDynamic
108 (FcLangSetCopy (FcLangSetPtrU(v
.u
.li
)));
109 if (!FcLangSetPtrU(v
.u
.li
))
119 FcValueListDestroy (FcValueListPtr l
)
122 for (; FcValueListPtrU(l
); l
= next
)
124 switch (FcValueListPtrU(l
)->value
.type
) {
126 FcObjectPtrDestroy (FcValueListPtrU(l
)->value
.u
.si
);
129 FcMatrixPtrDestroy (FcValueListPtrU(l
)->value
.u
.mi
);
133 (FcCharSetPtrU (FcValueListPtrU(l
)->value
.u
.ci
));
137 (FcLangSetPtrU (FcValueListPtrU(l
)->value
.u
.li
));
142 next
= FcValueListPtrU(l
)->next
;
144 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
145 if (l
.storage
== FcStorageDynamic
)
151 FcValueEqual (FcValue va
, FcValue vb
)
153 if (va
.type
!= vb
.type
)
155 if (va
.type
== FcTypeInteger
)
157 va
.type
= FcTypeDouble
;
160 if (vb
.type
== FcTypeInteger
)
162 vb
.type
= FcTypeDouble
;
165 if (va
.type
!= vb
.type
)
172 return va
.u
.i
== vb
.u
.i
;
174 return va
.u
.d
== vb
.u
.d
;
176 return FcStrCmpIgnoreCase (FcObjectPtrU(va
.u
.si
),
177 FcObjectPtrU(vb
.u
.si
)) == 0;
179 return va
.u
.b
== vb
.u
.b
;
181 return FcMatrixEqual (FcMatrixPtrU(va
.u
.mi
),
182 FcMatrixPtrU(vb
.u
.mi
));
184 return FcCharSetEqual (FcCharSetPtrU(va
.u
.ci
),
185 FcCharSetPtrU(vb
.u
.ci
));
187 return va
.u
.f
== vb
.u
.f
;
189 return FcLangSetEqual (FcLangSetPtrU(va
.u
.li
),
190 FcLangSetPtrU(vb
.u
.li
));
196 FcDoubleHash (double d
)
206 FcStringHash (const FcChar8
*s
)
213 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
218 FcValueHash (FcValue v
)
224 return (FcChar32
) v
.u
.i
;
226 return FcDoubleHash (v
.u
.d
);
228 return FcStringHash (FcObjectPtrU(v
.u
.si
));
230 return (FcChar32
) v
.u
.b
;
233 FcMatrix
* m
= FcMatrixPtrU(v
.u
.mi
);
234 return (FcDoubleHash (m
->xx
) ^
235 FcDoubleHash (m
->xy
) ^
236 FcDoubleHash (m
->yx
) ^
237 FcDoubleHash (m
->yy
));
240 return (FcChar32
) (FcCharSetPtrU(v
.u
.ci
))->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 (FcLangSetPtrU(v
.u
.li
));
251 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
253 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
256 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
258 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
259 FcValueListPtrU(lb
)->value
))
261 la
= FcValueListPtrU(la
)->next
;
262 lb
= FcValueListPtrU(lb
)->next
;
264 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
270 FcValueListHash (FcValueListPtr l
)
274 while (FcValueListPtrU(l
))
276 hash
= ((hash
<< 1) | (hash
>> 31)) ^
277 FcValueHash (FcValueListPtrU(l
)->value
);
278 l
= FcValueListPtrU(l
)->next
;
284 FcPatternDestroy (FcPattern
*p
)
288 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
291 for (i
= 0; i
< p
->num
; i
++)
292 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
295 if (FcPatternEltU(p
->elts
) && FcPatternEltIsDynamic(p
->elts
))
297 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
298 free (FcPatternEltU(p
->elts
));
299 p
->elts
= FcPatternEltPtrCreateDynamic(0);
302 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
306 #define FC_VALUE_LIST_HASH_SIZE 257
307 #define FC_PATTERN_HASH_SIZE 67
309 typedef struct _FcValueListEnt FcValueListEnt
;
311 struct _FcValueListEnt
{
312 FcValueListEnt
*next
;
317 typedef union _FcValueListAlign
{
322 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
323 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
324 static char *FcValueListFrozenName
[] = {
337 FcValueListReport (void);
340 FcValueListReport (void)
344 printf ("Fc Frozen Values:\n");
345 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
346 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
347 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
348 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
351 static FcValueListEnt
*
352 FcValueListEntCreate (FcValueListPtr h
)
354 FcValueListAlign
*ea
;
362 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
364 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
365 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
366 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
367 // this leaks for some reason
368 ea
= malloc (sizeof (FcValueListAlign
));
371 new = malloc (n
* sizeof (FcValueList
));
374 memset(new, 0, n
* sizeof (FcValueList
));
375 FcMemAlloc (FC_MEM_VALLIST
, size
);
377 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
378 for (l
= h
; FcValueListPtrU(l
);
379 l
= FcValueListPtrU(l
)->next
, new++)
381 if (FcValueListPtrU(l
)->value
.type
== FcTypeString
)
383 new->value
.type
= FcTypeString
;
384 new->value
.u
.si
= FcObjectStaticName
385 (FcObjectPtrU(FcValueListPtrU(l
)->value
.u
.si
));
389 new->value
= FcValueSave (FcValueListPtrU(l
)->value
);
391 new->binding
= FcValueListPtrU(l
)->binding
;
392 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
394 new->next
= FcValueListPtrCreateDynamic(new + 1);
398 new->next
= FcValueListPtrCreateDynamic(0);
405 FcValueListEntDestroy (FcValueListEnt
*e
)
409 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
411 /* XXX: We should perform these two operations with "size" as
412 computed in FcValueListEntCreate, but we don't have access to
413 that value here. Without this, the FcValueListFrozenBytes
414 values will be wrong as will the FcMemFree counts.
416 FcValueListFrozenBytes[e->list->value.type] -= size;
417 FcMemFree (FC_MEM_VALLIST, size);
420 for (l
= e
->list
; FcValueListPtrU(l
);
421 l
= FcValueListPtrU(l
)->next
)
423 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
424 FcValueDestroy (FcValueListPtrU(l
)->value
);
426 /* XXX: Are we being too chummy with the implementation here to
427 free(e) when it was actually the enclosing FcValueListAlign
428 that was allocated? */
432 static int FcValueListTotal
;
433 static int FcValueListUsed
;
435 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
437 static FcValueListPtr
438 FcValueListFreeze (FcValueListPtr l
)
440 FcChar32 hash
= FcValueListHash (l
);
441 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
445 for (ent
= *bucket
; ent
; ent
= ent
->next
)
447 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
451 ent
= FcValueListEntCreate (l
);
453 return FcValueListPtrCreateDynamic(0);
463 FcValueListThawAll (void)
466 FcValueListEnt
*ent
, *next
;
468 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
470 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
473 FcValueListEntDestroy (ent
);
475 FcValueListHashTable
[i
] = 0;
478 FcValueListTotal
= 0;
483 FcPatternBaseHash (FcPattern
*b
)
485 FcChar32 hash
= b
->num
;
488 for (i
= 0; i
< b
->num
; i
++)
489 hash
= ((hash
<< 1) | (hash
>> 31)) ^
490 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
494 typedef struct _FcPatternEnt FcPatternEnt
;
496 struct _FcPatternEnt
{
502 static int FcPatternTotal
;
503 static int FcPatternUsed
;
505 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
508 FcPatternBaseFreeze (FcPattern
*b
)
512 FcChar32 hash
= FcPatternBaseHash (b
);
513 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
518 for (ent
= *bucket
; ent
; ent
= ent
->next
)
520 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
522 for (i
= 0; i
< b
->num
; i
++)
524 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
525 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
527 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
528 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
537 * Compute size of pattern + elts
539 ent
= malloc (sizeof (FcPatternEnt
));
543 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
546 ep
= FcPatternCreate();
550 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
553 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
555 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
559 ep
->ref
= FC_REF_CONSTANT
;
561 for (i
= 0; i
< b
->num
; i
++)
563 (FcPatternEltU(ep
->elts
)+i
)->values
=
564 (FcPatternEltU(b
->elts
)+i
)->values
;
565 (FcPatternEltU(ep
->elts
)+i
)->object
=
566 (FcPatternEltU(b
->elts
)+i
)->object
;
575 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
581 FcPatternBaseThawAll (void)
584 FcPatternEnt
*ent
, *next
;
586 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
588 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
593 FcPatternHashTable
[i
] = 0;
601 FcPatternFreeze (FcPattern
*p
)
603 FcPattern
*b
, *n
= 0;
607 if (p
->ref
== FC_REF_CONSTANT
)
610 b
= FcPatternCreate();
618 e
= malloc(b
->num
* sizeof (FcPatternElt
));
621 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
622 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
625 * Freeze object lists
627 for (i
= 0; i
< p
->num
; i
++)
629 (FcPatternEltU(b
->elts
)+i
)->object
=
630 (FcPatternEltU(p
->elts
)+i
)->object
;
631 (FcPatternEltU(b
->elts
)+i
)->values
=
632 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
633 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
639 n
= FcPatternBaseFreeze (b
);
641 if (FcDebug() & FC_DBG_MEMORY
)
643 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
644 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
648 free(FcPatternEltU(b
->elts
));
649 b
->elts
= FcPatternEltPtrCreateDynamic(0);
650 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
653 assert (FcPatternEqual (n
, p
));
659 FcPatternThawAll (void)
661 FcPatternBaseThawAll ();
662 FcValueListThawAll ();
666 FcPatternPosition (const FcPattern
*p
, const char *object
)
668 int low
, high
, mid
, c
;
671 obj
= FcObjectStaticName(object
);
678 mid
= (low
+ high
) >> 1;
679 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
693 FcPatternFindElt (const FcPattern
*p
, const char *object
)
695 int i
= FcPatternPosition (p
, object
);
698 return FcPatternEltU(p
->elts
)+i
;
702 FcPatternInsertElt (FcPattern
*p
, const char *object
)
707 i
= FcPatternPosition (p
, object
);
712 /* reallocate array */
713 if (p
->num
+ 1 >= p
->size
)
715 int s
= p
->size
+ 16;
716 if (FcPatternEltU(p
->elts
))
718 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
719 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
720 if (!e
) /* maybe it was mmapped */
722 e
= malloc(s
* sizeof (FcPatternElt
));
724 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
728 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
731 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
733 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
734 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
737 (FcPatternEltU(p
->elts
)+p
->size
)->object
= FcObjectPtrCreateDynamic(0);
738 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
739 FcValueListPtrCreateDynamic(0);
745 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
746 FcPatternEltU(p
->elts
) + i
,
747 sizeof (FcPatternElt
) *
753 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectStaticName (object
);
754 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
757 return FcPatternEltU(p
->elts
)+i
;
761 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
768 if (pa
->num
!= pb
->num
)
770 for (i
= 0; i
< pa
->num
; i
++)
772 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
773 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
775 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
776 (FcPatternEltU(pb
->elts
)+i
)->values
))
783 FcPatternHash (const FcPattern
*p
)
788 for (i
= 0; i
< p
->num
; i
++)
790 h
= (((h
<< 1) | (h
>> 31)) ^
791 FcStringHash ((const FcChar8
*) FcObjectPtrU(((FcPatternEltU(p
->elts
)+i
)->object
))) ^
792 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
798 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
800 FcPatternElt
*ea
, *eb
;
803 for (i
= 0; i
< os
->nobject
; i
++)
805 ea
= FcPatternFindElt (pai
, FcObjectPtrU(os
->objects
[i
]));
806 eb
= FcPatternFindElt (pbi
, FcObjectPtrU(os
->objects
[i
]));
811 if (!FcValueListEqual (ea
->values
, eb
->values
))
824 FcPatternAddWithBinding (FcPattern
*p
,
827 FcValueBinding binding
,
831 FcValueListPtr
new, *prev
;
834 if (p
->ref
== FC_REF_CONSTANT
)
837 newp
= malloc (sizeof (FcValueList
));
841 memset(newp
, 0, sizeof (FcValueList
));
842 new = FcValueListPtrCreateDynamic(newp
);
843 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
845 value
= FcValueSave (value
);
846 if (value
.type
== FcTypeVoid
)
849 FcValueListPtrU(new)->value
= value
;
850 FcValueListPtrU(new)->binding
= binding
;
851 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
853 e
= FcPatternInsertElt (p
, object
);
859 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
865 FcValueListPtrU(new)->next
= e
->values
;
872 switch (value
.type
) {
874 FcStrFree ((FcChar8
*) FcObjectPtrU(value
.u
.si
));
877 FcMatrixFree (FcMatrixPtrU(value
.u
.mi
));
880 FcCharSetDestroy (FcCharSetPtrU(value
.u
.ci
));
883 FcLangSetDestroy (FcLangSetPtrU(value
.u
.li
));
889 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
890 free (FcValueListPtrU(new));
896 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
898 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
902 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
904 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
908 FcPatternDel (FcPattern
*p
, const char *object
)
912 e
= FcPatternFindElt (p
, object
);
917 FcValueListDestroy (e
->values
);
919 /* shuffle existing ones down */
921 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
922 sizeof (FcPatternElt
));
924 (FcPatternEltU(p
->elts
)+p
->num
)->object
= FcObjectPtrCreateDynamic(0);
925 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
930 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
933 FcValueListPtr
*prev
, l
;
935 e
= FcPatternFindElt (p
, object
);
938 for (prev
= &e
->values
;
939 FcValueListPtrU(l
= *prev
);
940 prev
= &FcValueListPtrU(l
)->next
)
944 *prev
= FcValueListPtrU(l
)->next
;
945 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
946 FcValueListDestroy (l
);
947 if (!FcValueListPtrU(e
->values
))
948 FcPatternDel (p
, object
);
957 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
961 v
.type
= FcTypeInteger
;
963 return FcPatternAdd (p
, object
, v
, FcTrue
);
967 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
971 v
.type
= FcTypeDouble
;
973 return FcPatternAdd (p
, object
, v
, FcTrue
);
978 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
982 v
.type
= FcTypeString
;
983 v
.u
.si
= FcObjectPtrCreateDynamic(s
);
984 return FcPatternAdd (p
, object
, v
, FcTrue
);
988 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
992 v
.type
= FcTypeMatrix
;
993 v
.u
.mi
= FcMatrixPtrCreateDynamic((FcMatrix
*) s
);
994 return FcPatternAdd (p
, object
, v
, FcTrue
);
999 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1003 v
.type
= FcTypeBool
;
1005 return FcPatternAdd (p
, object
, v
, FcTrue
);
1009 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1013 v
.type
= FcTypeCharSet
;
1014 v
.u
.ci
= FcCharSetPtrCreateDynamic((FcCharSet
*)c
);
1015 return FcPatternAdd (p
, object
, v
, FcTrue
);
1019 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1023 v
.type
= FcTypeFTFace
;
1025 return FcPatternAdd (p
, object
, v
, FcTrue
);
1029 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1033 v
.type
= FcTypeLangSet
;
1034 v
.u
.li
= FcLangSetPtrCreateDynamic((FcLangSet
*)ls
);
1035 return FcPatternAdd (p
, object
, v
, FcTrue
);
1039 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1044 e
= FcPatternFindElt (p
, object
);
1046 return FcResultNoMatch
;
1047 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1051 *v
= FcValueListPtrU(l
)->value
;
1052 return FcResultMatch
;
1056 return FcResultNoId
;
1060 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1065 r
= FcPatternGet (p
, object
, id
, &v
);
1066 if (r
!= FcResultMatch
)
1076 return FcResultTypeMismatch
;
1078 return FcResultMatch
;
1082 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1087 r
= FcPatternGet (p
, object
, id
, &v
);
1088 if (r
!= FcResultMatch
)
1095 *d
= (double) v
.u
.i
;
1098 return FcResultTypeMismatch
;
1100 return FcResultMatch
;
1104 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1109 r
= FcPatternGet (p
, object
, id
, &v
);
1110 if (r
!= FcResultMatch
)
1112 if (v
.type
!= FcTypeString
)
1113 return FcResultTypeMismatch
;
1114 *s
= (FcChar8
*) FcObjectPtrU(v
.u
.si
);
1115 return FcResultMatch
;
1119 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1124 r
= FcPatternGet (p
, object
, id
, &v
);
1125 if (r
!= FcResultMatch
)
1127 if (v
.type
!= FcTypeMatrix
)
1128 return FcResultTypeMismatch
;
1129 *m
= FcMatrixPtrU(v
.u
.mi
);
1130 return FcResultMatch
;
1135 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1140 r
= FcPatternGet (p
, object
, id
, &v
);
1141 if (r
!= FcResultMatch
)
1143 if (v
.type
!= FcTypeBool
)
1144 return FcResultTypeMismatch
;
1146 return FcResultMatch
;
1150 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1155 r
= FcPatternGet (p
, object
, id
, &v
);
1156 if (r
!= FcResultMatch
)
1158 if (v
.type
!= FcTypeCharSet
)
1159 return FcResultTypeMismatch
;
1160 *c
= FcCharSetPtrU(v
.u
.ci
);
1161 return FcResultMatch
;
1165 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1170 r
= FcPatternGet (p
, object
, id
, &v
);
1171 if (r
!= FcResultMatch
)
1173 if (v
.type
!= FcTypeFTFace
)
1174 return FcResultTypeMismatch
;
1175 *f
= (FT_Face
) v
.u
.f
;
1176 return FcResultMatch
;
1180 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1185 r
= FcPatternGet (p
, object
, id
, &v
);
1186 if (r
!= FcResultMatch
)
1188 if (v
.type
!= FcTypeLangSet
)
1189 return FcResultTypeMismatch
;
1190 *ls
= FcLangSetPtrU(v
.u
.li
);
1191 return FcResultMatch
;
1195 FcPatternDuplicate (const FcPattern
*orig
)
1202 new = FcPatternCreate ();
1206 e
= FcPatternEltU(orig
->elts
);
1208 for (i
= 0; i
< orig
->num
; i
++)
1210 for (l
= (e
+ i
)->values
;
1212 l
= FcValueListPtrU(l
)->next
)
1213 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1214 FcValueListPtrU(l
)->value
, FcTrue
))
1221 FcPatternDestroy (new);
1227 FcPatternReference (FcPattern
*p
)
1229 if (p
->ref
!= FC_REF_CONSTANT
)
1234 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1238 FcPatternVapBuild (ret
, orig
, va
);
1243 FcPatternBuild (FcPattern
*orig
, ...)
1247 va_start (va
, orig
);
1248 FcPatternVapBuild (orig
, orig
, va
);
1254 * Add all of the elements in 's' to 'p'
1257 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1263 for (i
= 0; i
< s
->num
; i
++)
1265 e
= FcPatternEltU(s
->elts
)+i
;
1266 for (v
= e
->values
; FcValueListPtrU(v
);
1267 v
= FcValueListPtrU(v
)->next
)
1269 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1270 FcValueListPtrU(v
)->value
,
1271 FcValueListPtrU(v
)->binding
, FcTrue
))
1278 #define OBJECT_HASH_SIZE 31
1279 struct objectBucket
{
1280 struct objectBucket
*next
;
1283 static struct objectBucket
**buckets
= 0;
1286 FcObjectStaticName (const char *name
)
1288 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1289 struct objectBucket
**p
;
1290 struct objectBucket
*b
;
1297 buckets
= malloc(sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1298 memset (buckets
, 0, sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1301 for (p
= &buckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1302 if (b
->hash
== hash
&& !strcmp (name
, FcObjectPtrU(*((FcObjectPtr
*) (b
+ 1)))))
1303 return *((FcObjectPtr
*) (b
+ 1));
1304 size
= sizeof (struct objectBucket
) + sizeof (FcObjectPtr
) + 1;
1306 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1308 return FcObjectPtrCreateDynamic(0);
1311 nn
= malloc(strlen(name
)+1);
1314 strcpy ((char *)nn
, name
);
1315 new = FcObjectPtrCreateDynamic ((char *) nn
);
1316 *((FcObjectPtr
*)(b
+1)) = new;
1322 return FcObjectPtrCreateDynamic(0);
1326 FcPatternEltU (FcPatternEltPtr pei
)
1328 switch (pei
.storage
)
1330 case FcStorageStatic
:
1331 if (pei
.u
.stat
== 0) return 0;
1332 return &fcpatternelts
[pei
.u
.stat
];
1333 case FcStorageDynamic
:
1340 static FcPatternEltPtr
1341 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1343 FcPatternEltPtr
new;
1344 new.storage
= FcStorageDynamic
;
1349 static FcPatternEltPtr
1350 FcPatternEltPtrCreateStatic (int i
)
1352 FcPatternEltPtr
new;
1353 new.storage
= FcStorageStatic
;
1359 FcPatternEltIsDynamic (FcPatternEltPtr pei
)
1361 return pei
.storage
== FcStorageDynamic
;
1365 struct objectTree
* left
, * right
;
1370 FcObjectPtrCreateDynamic (const char * s
)
1373 new.storage
= FcStorageDynamic
;
1376 new.hash
= FcStringHash(s
);
1383 FcObjectPtrDestroy (FcObjectPtr p
)
1385 if (p
.storage
== FcStorageDynamic
)
1386 FcStrFree ((char *)p
.u
.dyn
);
1390 FcObjectPtrU (FcObjectPtr si
)
1394 case FcStorageStatic
:
1395 if (si
.u
.stat
== 0) return 0;
1396 return &object_content
[si
.u
.stat
];
1397 case FcStorageDynamic
:
1405 FcObjectPtrCompare (const FcObjectPtr a
, const FcObjectPtr b
)
1407 int r
= a
.hash
- b
.hash
;
1410 return strcmp (FcObjectPtrU(a
), FcObjectPtrU(b
));
1415 FcObjectClearStatic(void)
1418 object_content_count
= 0;
1419 object_content_ptr
= 0;
1423 FcObjectSerialize (FcObjectPtr si
)
1425 struct objectBucket
**p
;
1426 struct objectBucket
*b
;
1428 if (!object_content
)
1430 object_content
= malloc(object_content_count
* sizeof(char));
1431 if (!object_content
)
1432 return FcObjectPtrCreateDynamic(0);
1436 return FcObjectPtrCreateDynamic(0);
1438 for (p
= &buckets
[si
.hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1439 if (b
->hash
== si
.hash
&& !strcmp (FcObjectPtrU(si
), FcObjectPtrU(*((FcObjectPtr
*) (b
+ 1)))))
1441 FcObjectPtr
*op
= (FcObjectPtr
*) (b
+ 1);
1442 if (op
->storage
== FcStorageStatic
)
1445 if (object_content_ptr
>= object_content_count
)
1446 return FcObjectPtrCreateDynamic(0);
1448 strcpy (object_content
+object_content_ptr
,
1451 op
->storage
= FcStorageStatic
;
1452 op
->u
.stat
= object_content_ptr
;
1454 object_content_ptr
+= strlen(FcObjectPtrU(si
))+1;
1459 return FcObjectPtrCreateDynamic(0);
1463 FcObjectPrepareSerialize (FcObjectPtr si
)
1465 object_content_count
+= strlen(FcObjectPtrU(si
)) + 1;
1470 FcPatternClearStatic (void)
1474 fcpattern_count
= 0;
1477 fcpatternelt_ptr
= 0;
1478 fcpatternelt_count
= 0;
1482 FcValueListClearStatic (void)
1485 fcvaluelist_ptr
= 0;
1486 fcvaluelist_count
= 0;
1490 FcPatternPrepareSerialize (FcPattern
* p
)
1495 fcpatternelt_count
+= p
->num
;
1497 for (i
= 0; i
< p
->num
; i
++)
1499 FcObjectPrepareSerialize
1500 ((FcPatternEltU(p
->elts
)+i
)->object
);
1501 if (!FcValueListPrepareSerialize
1502 (FcValueListPtrU(((FcPatternEltU(p
->elts
)+i
)->values
))))
1510 FcValueListPrepareSerialize (FcValueList
*p
)
1516 vl
= FcValueListPtrU(vl
->next
))
1518 FcValue v
= vl
->value
;
1523 FcMatrixPrepareSerialize(FcMatrixPtrU(v
.u
.mi
));
1526 FcCharSetPrepareSerialize(FcCharSetPtrU(v
.u
.ci
));
1529 FcLangSetPrepareSerialize(FcLangSetPtrU(v
.u
.li
));
1532 FcObjectPrepareSerialize(v
.u
.si
);
1536 fcvaluelist_count
++;
1543 FcPatternSerialize (FcPattern
*old
)
1546 FcPatternElt
*e
, *nep
;
1548 FcValueListPtr v
, nv_head
, nvp
;
1553 p
= malloc (sizeof (FcPattern
) * fcpattern_count
);
1557 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1561 e
= malloc (sizeof (FcPatternElt
) * fcpatternelt_count
);
1565 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1567 fcpatternelt_ptr
= 0;
1570 p
= FcPatternCreate();
1571 elts
= fcpatternelt_ptr
;
1572 nep
= &fcpatternelts
[elts
];
1575 fcpatternelt_ptr
+= old
->num
;
1577 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1580 nvp
= nv_head
= FcValueListSerialize(FcValueListPtrU(v
));
1581 if (!FcValueListPtrU(nv_head
))
1583 nv
= FcValueListPtrU(nvp
);
1587 v
= FcValueListPtrU(v
)->next
,
1588 nv
= FcValueListPtrU(nv
->next
))
1591 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1593 nvp
= FcValueListSerialize
1594 (FcValueListPtrU(FcValueListPtrU(v
)->next
));
1599 nep
[i
].values
= nv_head
;
1600 nep
[i
].object
= FcObjectSerialize
1601 (FcObjectStaticName(FcObjectPtrU(e
->object
)));
1604 p
->elts
= FcPatternEltPtrCreateStatic(elts
);
1606 p
->ref
= FC_REF_CONSTANT
;
1610 free (fcpatternelts
);
1618 FcValueListSerialize(FcValueList
*pi
)
1626 vl
= malloc (sizeof (FcValueList
) * fcvaluelist_count
);
1628 return FcValueListPtrCreateDynamic(0);
1630 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1632 fcvaluelist_ptr
= 0;
1635 fcvaluelists
[fcvaluelist_ptr
] = *pi
;
1636 new.storage
= FcStorageStatic
;
1637 new.u
.stat
= fcvaluelist_ptr
++;
1638 v
= &fcvaluelists
[new.u
.stat
].value
;
1642 if (FcObjectPtrU(v
->u
.si
))
1645 FcObjectSerialize(FcObjectStaticName(FcObjectPtrU(v
->u
.si
)));
1646 if (!FcObjectPtrU(v
->u
.si
))
1647 return FcValueListPtrCreateDynamic(pi
);
1652 if (FcMatrixPtrU(v
->u
.mi
))
1654 FcMatrixPtr mi
= FcMatrixSerialize(FcMatrixPtrU(v
->u
.mi
));
1656 if (!FcMatrixPtrU(mi
))
1657 return FcValueListPtrCreateDynamic(pi
);
1662 if (FcCharSetPtrU(v
->u
.ci
))
1664 FcCharSetPtr ci
= FcCharSetSerialize(FcCharSetPtrU(v
->u
.ci
));
1665 if (!FcCharSetPtrU(v
->u
.ci
))
1666 return FcValueListPtrCreateDynamic(pi
);
1671 if (FcLangSetPtrU(v
->u
.li
))
1673 FcLangSetPtr li
= FcLangSetSerialize(FcLangSetPtrU(v
->u
.li
));
1674 if (!FcLangSetPtrU(v
->u
.li
))
1675 return FcValueListPtrCreateDynamic(pi
);
1686 FcValueListPtrU (FcValueListPtr pi
)
1690 case FcStorageStatic
:
1691 if (pi
.u
.stat
== 0) return 0;
1692 return &fcvaluelists
[pi
.u
.stat
];
1693 case FcStorageDynamic
:
1701 FcValueListPtrCreateDynamic(FcValueList
* p
)
1705 r
.storage
= FcStorageDynamic
;