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
;
37 static FcPatternEltPtr
38 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
);
41 FcPatternCreate (void)
45 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
48 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
51 p
->elts
= FcPatternEltPtrCreateDynamic(0);
52 p
->bank
= FC_BANK_DYNAMIC
;
58 FcValueDestroy (FcValue v
)
62 FcStrFree ((FcChar8
*) v
.u
.s
);
65 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
68 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
71 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
79 FcValueCanonicalize (const FcValue
*v
)
81 if (v
->type
& FC_STORAGE_STATIC
)
85 switch (v
->type
& ~FC_STORAGE_STATIC
)
88 new.u
.s
= fc_value_string(v
);
89 new.type
= FcTypeString
;
92 new.u
.c
= fc_value_charset(v
);
93 new.type
= FcTypeCharSet
;
96 new.u
.l
= fc_value_langset(v
);
97 new.type
= FcTypeLangSet
;
106 FcValueSave (FcValue v
)
110 v
.u
.s
= FcStrCopy (v
.u
.s
);
115 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
120 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
125 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
136 FcValueListDestroy (FcValueListPtr l
)
139 for (; FcValueListPtrU(l
); l
= next
)
141 switch (FcValueListPtrU(l
)->value
.type
) {
143 FcStrFree ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
);
146 FcMatrixFree ((FcMatrix
*)FcValueListPtrU(l
)->value
.u
.m
);
150 ((FcCharSet
*) (FcValueListPtrU(l
)->value
.u
.c
));
154 ((FcLangSet
*) (FcValueListPtrU(l
)->value
.u
.l
));
159 next
= FcValueListPtrU(l
)->next
;
160 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
161 if (l
.bank
== FC_BANK_DYNAMIC
)
167 FcValueEqual (FcValue va
, FcValue vb
)
169 if (va
.type
!= vb
.type
)
171 if (va
.type
== FcTypeInteger
)
173 va
.type
= FcTypeDouble
;
176 if (vb
.type
== FcTypeInteger
)
178 vb
.type
= FcTypeDouble
;
181 if (va
.type
!= vb
.type
)
188 return va
.u
.i
== vb
.u
.i
;
190 return va
.u
.d
== vb
.u
.d
;
192 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
194 return va
.u
.b
== vb
.u
.b
;
196 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
198 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
200 return va
.u
.f
== vb
.u
.f
;
202 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
208 FcDoubleHash (double d
)
218 FcStringHash (const FcChar8
*s
)
225 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
230 FcValueHash (const FcValue
*v0
)
232 FcValue v
= FcValueCanonicalize(v0
);
237 return (FcChar32
) v
.u
.i
;
239 return FcDoubleHash (v
.u
.d
);
241 return FcStringHash (v
.u
.s
);
243 return (FcChar32
) v
.u
.b
;
245 return (FcDoubleHash (v
.u
.m
->xx
) ^
246 FcDoubleHash (v
.u
.m
->xy
) ^
247 FcDoubleHash (v
.u
.m
->yx
) ^
248 FcDoubleHash (v
.u
.m
->yy
));
250 return (FcChar32
) v
.u
.c
->num
;
252 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
253 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
255 return FcLangSetHash (v
.u
.l
);
261 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
263 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
266 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
268 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
269 FcValueListPtrU(lb
)->value
))
271 la
= FcValueListPtrU(la
)->next
;
272 lb
= FcValueListPtrU(lb
)->next
;
274 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
280 FcValueListHash (FcValueListPtr l
)
284 while (FcValueListPtrU(l
))
286 hash
= ((hash
<< 1) | (hash
>> 31)) ^
287 FcValueHash (&FcValueListPtrU(l
)->value
);
288 l
= FcValueListPtrU(l
)->next
;
294 FcPatternDestroy (FcPattern
*p
)
298 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
301 for (i
= 0; i
< p
->num
; i
++)
302 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
305 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
307 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
308 free (FcPatternEltU(p
->elts
));
309 p
->elts
= FcPatternEltPtrCreateDynamic(0);
312 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
316 #define FC_VALUE_LIST_HASH_SIZE 257
317 #define FC_PATTERN_HASH_SIZE 67
319 typedef struct _FcValueListEnt FcValueListEnt
;
321 struct _FcValueListEnt
{
322 FcValueListEnt
*next
;
327 typedef union _FcValueListAlign
{
332 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
333 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
334 static char *FcValueListFrozenName
[] = {
347 FcValueListReport (void);
350 FcValueListReport (void)
354 printf ("Fc Frozen Values:\n");
355 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
356 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
357 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
358 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
361 static FcValueListEnt
*
362 FcValueListEntCreate (FcValueListPtr h
)
364 FcValueListAlign
*ea
;
372 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
374 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
375 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
376 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
377 // this leaks for some reason
378 ea
= malloc (sizeof (FcValueListAlign
));
381 new = malloc (n
* sizeof (FcValueList
));
384 memset(new, 0, n
* sizeof (FcValueList
));
385 FcMemAlloc (FC_MEM_VALLIST
, size
);
387 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
388 for (l
= h
; FcValueListPtrU(l
);
389 l
= FcValueListPtrU(l
)->next
, new++)
391 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
393 new->value
.type
= FcTypeString
;
394 new->value
.u
.s
= FcStrStaticName
395 (fc_value_string(&FcValueListPtrU(l
)->value
));
399 new->value
= FcValueSave (FcValueCanonicalize
400 (&FcValueListPtrU(l
)->value
));
402 new->binding
= FcValueListPtrU(l
)->binding
;
403 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
405 new->next
= FcValueListPtrCreateDynamic(new + 1);
409 new->next
= FcValueListPtrCreateDynamic(0);
416 FcValueListEntDestroy (FcValueListEnt
*e
)
420 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
422 /* XXX: We should perform these two operations with "size" as
423 computed in FcValueListEntCreate, but we don't have access to
424 that value here. Without this, the FcValueListFrozenBytes
425 values will be wrong as will the FcMemFree counts.
427 FcValueListFrozenBytes[e->list->value.type] -= size;
428 FcMemFree (FC_MEM_VALLIST, size);
431 for (l
= e
->list
; FcValueListPtrU(l
);
432 l
= FcValueListPtrU(l
)->next
)
434 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
435 FcValueDestroy (FcValueListPtrU(l
)->value
);
437 /* XXX: Are we being too chummy with the implementation here to
438 free(e) when it was actually the enclosing FcValueListAlign
439 that was allocated? */
443 static int FcValueListTotal
;
444 static int FcValueListUsed
;
446 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
448 static FcValueListPtr
449 FcValueListFreeze (FcValueListPtr l
)
451 FcChar32 hash
= FcValueListHash (l
);
452 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
456 for (ent
= *bucket
; ent
; ent
= ent
->next
)
458 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
462 ent
= FcValueListEntCreate (l
);
464 return FcValueListPtrCreateDynamic(0);
474 FcValueListThawAll (void)
477 FcValueListEnt
*ent
, *next
;
479 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
481 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
484 FcValueListEntDestroy (ent
);
486 FcValueListHashTable
[i
] = 0;
489 FcValueListTotal
= 0;
494 FcPatternBaseHash (FcPattern
*b
)
496 FcChar32 hash
= b
->num
;
499 for (i
= 0; i
< b
->num
; i
++)
500 hash
= ((hash
<< 1) | (hash
>> 31)) ^
501 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
505 typedef struct _FcPatternEnt FcPatternEnt
;
507 struct _FcPatternEnt
{
513 static int FcPatternTotal
;
514 static int FcPatternUsed
;
516 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
519 FcPatternBaseFreeze (FcPattern
*b
)
523 FcChar32 hash
= FcPatternBaseHash (b
);
524 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
529 for (ent
= *bucket
; ent
; ent
= ent
->next
)
531 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
533 for (i
= 0; i
< b
->num
; i
++)
535 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
536 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
538 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
539 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
548 * Compute size of pattern + elts
550 ent
= malloc (sizeof (FcPatternEnt
));
554 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
557 ep
= FcPatternCreate();
561 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
564 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
566 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
570 ep
->ref
= FC_REF_CONSTANT
;
572 for (i
= 0; i
< b
->num
; i
++)
574 (FcPatternEltU(ep
->elts
)+i
)->values
=
575 (FcPatternEltU(b
->elts
)+i
)->values
;
576 (FcPatternEltU(ep
->elts
)+i
)->object
=
577 (FcPatternEltU(b
->elts
)+i
)->object
;
586 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
592 FcPatternBaseThawAll (void)
595 FcPatternEnt
*ent
, *next
;
597 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
599 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
604 FcPatternHashTable
[i
] = 0;
612 FcPatternFreeze (FcPattern
*p
)
614 FcPattern
*b
, *n
= 0;
618 if (p
->ref
== FC_REF_CONSTANT
)
621 b
= FcPatternCreate();
629 e
= malloc(b
->num
* sizeof (FcPatternElt
));
632 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
633 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
636 * Freeze object lists
638 for (i
= 0; i
< p
->num
; i
++)
640 (FcPatternEltU(b
->elts
)+i
)->object
=
641 (FcPatternEltU(p
->elts
)+i
)->object
;
642 (FcPatternEltU(b
->elts
)+i
)->values
=
643 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
644 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
650 n
= FcPatternBaseFreeze (b
);
652 if (FcDebug() & FC_DBG_MEMORY
)
654 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
655 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
659 free(FcPatternEltU(b
->elts
));
660 b
->elts
= FcPatternEltPtrCreateDynamic(0);
661 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
664 assert (FcPatternEqual (n
, p
));
670 FcPatternPosition (const FcPattern
*p
, const char *object
)
672 int low
, high
, mid
, c
;
675 obj
= FcObjectToPtr(object
);
682 mid
= (low
+ high
) >> 1;
683 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
697 FcPatternFindElt (const FcPattern
*p
, const char *object
)
699 int i
= FcPatternPosition (p
, object
);
702 return FcPatternEltU(p
->elts
)+i
;
706 FcPatternInsertElt (FcPattern
*p
, const char *object
)
711 i
= FcPatternPosition (p
, object
);
716 /* reallocate array */
717 if (p
->num
+ 1 >= p
->size
)
719 int s
= p
->size
+ 16;
720 if (FcPatternEltU(p
->elts
))
722 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
723 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
724 if (!e
) /* maybe it was mmapped */
726 e
= malloc(s
* sizeof (FcPatternElt
));
728 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
732 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
735 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
737 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
738 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
741 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
742 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
743 FcValueListPtrCreateDynamic(0);
749 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
750 FcPatternEltU(p
->elts
) + i
,
751 sizeof (FcPatternElt
) *
757 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
758 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
761 return FcPatternEltU(p
->elts
)+i
;
765 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
772 if (pa
->num
!= pb
->num
)
774 for (i
= 0; i
< pa
->num
; i
++)
776 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
777 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
779 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
780 (FcPatternEltU(pb
->elts
)+i
)->values
))
787 FcPatternHash (const FcPattern
*p
)
792 for (i
= 0; i
< p
->num
; i
++)
794 h
= (((h
<< 1) | (h
>> 31)) ^
795 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
796 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
802 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
804 FcPatternElt
*ea
, *eb
;
807 for (i
= 0; i
< os
->nobject
; i
++)
809 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
810 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
815 if (!FcValueListEqual (ea
->values
, eb
->values
))
828 FcPatternAddWithBinding (FcPattern
*p
,
831 FcValueBinding binding
,
835 FcValueListPtr
new, *prev
;
838 if (p
->ref
== FC_REF_CONSTANT
)
841 newp
= malloc (sizeof (FcValueList
));
845 memset(newp
, 0, sizeof (FcValueList
));
846 new = FcValueListPtrCreateDynamic(newp
);
847 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
849 value
= FcValueSave (value
);
850 if (value
.type
== FcTypeVoid
)
853 FcValueListPtrU(new)->value
= value
;
854 FcValueListPtrU(new)->binding
= binding
;
855 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
857 e
= FcPatternInsertElt (p
, object
);
863 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
869 FcValueListPtrU(new)->next
= e
->values
;
876 switch (value
.type
) {
878 FcStrFree ((FcChar8
*) value
.u
.s
);
881 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
884 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
887 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
893 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
894 free (FcValueListPtrU(new));
900 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
902 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
906 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
908 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
912 FcPatternDel (FcPattern
*p
, const char *object
)
916 e
= FcPatternFindElt (p
, object
);
921 FcValueListDestroy (e
->values
);
923 /* shuffle existing ones down */
925 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
926 sizeof (FcPatternElt
));
928 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
929 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
934 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
937 FcValueListPtr
*prev
, l
;
939 e
= FcPatternFindElt (p
, object
);
942 for (prev
= &e
->values
;
943 FcValueListPtrU(l
= *prev
);
944 prev
= &FcValueListPtrU(l
)->next
)
948 *prev
= FcValueListPtrU(l
)->next
;
949 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
950 FcValueListDestroy (l
);
951 if (!FcValueListPtrU(e
->values
))
952 FcPatternDel (p
, object
);
961 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
965 v
.type
= FcTypeInteger
;
967 return FcPatternAdd (p
, object
, v
, FcTrue
);
971 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
975 v
.type
= FcTypeDouble
;
977 return FcPatternAdd (p
, object
, v
, FcTrue
);
982 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
986 v
.type
= FcTypeString
;
987 v
.u
.s
= FcStrStaticName(s
);
988 return FcPatternAdd (p
, object
, v
, FcTrue
);
992 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
996 v
.type
= FcTypeMatrix
;
998 return FcPatternAdd (p
, object
, v
, FcTrue
);
1003 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1007 v
.type
= FcTypeBool
;
1009 return FcPatternAdd (p
, object
, v
, FcTrue
);
1013 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1017 v
.type
= FcTypeCharSet
;
1018 v
.u
.c
= (FcCharSet
*)c
;
1019 return FcPatternAdd (p
, object
, v
, FcTrue
);
1023 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1027 v
.type
= FcTypeFTFace
;
1029 return FcPatternAdd (p
, object
, v
, FcTrue
);
1033 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1037 v
.type
= FcTypeLangSet
;
1038 v
.u
.l
= (FcLangSet
*)ls
;
1039 return FcPatternAdd (p
, object
, v
, FcTrue
);
1043 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1048 e
= FcPatternFindElt (p
, object
);
1050 return FcResultNoMatch
;
1051 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1055 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1056 return FcResultMatch
;
1060 return FcResultNoId
;
1064 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1069 r
= FcPatternGet (p
, object
, id
, &v
);
1070 if (r
!= FcResultMatch
)
1080 return FcResultTypeMismatch
;
1082 return FcResultMatch
;
1086 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1091 r
= FcPatternGet (p
, object
, id
, &v
);
1092 if (r
!= FcResultMatch
)
1099 *d
= (double) v
.u
.i
;
1102 return FcResultTypeMismatch
;
1104 return FcResultMatch
;
1108 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1113 r
= FcPatternGet (p
, object
, id
, &v
);
1114 if (r
!= FcResultMatch
)
1116 if (v
.type
!= FcTypeString
)
1117 return FcResultTypeMismatch
;
1118 *s
= (FcChar8
*) v
.u
.s
;
1119 return FcResultMatch
;
1123 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1128 r
= FcPatternGet (p
, object
, id
, &v
);
1129 if (r
!= FcResultMatch
)
1131 if (v
.type
!= FcTypeMatrix
)
1132 return FcResultTypeMismatch
;
1133 *m
= (FcMatrix
*)v
.u
.m
;
1134 return FcResultMatch
;
1139 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1144 r
= FcPatternGet (p
, object
, id
, &v
);
1145 if (r
!= FcResultMatch
)
1147 if (v
.type
!= FcTypeBool
)
1148 return FcResultTypeMismatch
;
1150 return FcResultMatch
;
1154 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1159 r
= FcPatternGet (p
, object
, id
, &v
);
1160 if (r
!= FcResultMatch
)
1162 if (v
.type
!= FcTypeCharSet
)
1163 return FcResultTypeMismatch
;
1164 *c
= (FcCharSet
*)v
.u
.c
;
1165 return FcResultMatch
;
1169 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1174 r
= FcPatternGet (p
, object
, id
, &v
);
1175 if (r
!= FcResultMatch
)
1177 if (v
.type
!= FcTypeFTFace
)
1178 return FcResultTypeMismatch
;
1179 *f
= (FT_Face
) v
.u
.f
;
1180 return FcResultMatch
;
1184 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1189 r
= FcPatternGet (p
, object
, id
, &v
);
1190 if (r
!= FcResultMatch
)
1192 if (v
.type
!= FcTypeLangSet
)
1193 return FcResultTypeMismatch
;
1194 *ls
= (FcLangSet
*)v
.u
.l
;
1195 return FcResultMatch
;
1199 FcPatternDuplicate (const FcPattern
*orig
)
1206 new = FcPatternCreate ();
1210 e
= FcPatternEltU(orig
->elts
);
1212 for (i
= 0; i
< orig
->num
; i
++)
1214 for (l
= (e
+ i
)->values
;
1216 l
= FcValueListPtrU(l
)->next
)
1217 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1218 FcValueListPtrU(l
)->value
, FcTrue
))
1225 FcPatternDestroy (new);
1231 FcPatternReference (FcPattern
*p
)
1233 if (p
->ref
!= FC_REF_CONSTANT
)
1238 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1242 FcPatternVapBuild (ret
, orig
, va
);
1247 FcPatternBuild (FcPattern
*orig
, ...)
1251 va_start (va
, orig
);
1252 FcPatternVapBuild (orig
, orig
, va
);
1258 * Add all of the elements in 's' to 'p'
1261 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1267 for (i
= 0; i
< s
->num
; i
++)
1269 e
= FcPatternEltU(s
->elts
)+i
;
1270 for (v
= e
->values
; FcValueListPtrU(v
);
1271 v
= FcValueListPtrU(v
)->next
)
1273 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1274 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1275 FcValueListPtrU(v
)->binding
, FcTrue
))
1282 #define OBJECT_HASH_SIZE 31
1283 static struct objectBucket
{
1284 struct objectBucket
*next
;
1286 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1289 FcStrStaticName (const FcChar8
*name
)
1291 FcChar32 hash
= FcStringHash (name
);
1292 struct objectBucket
**p
;
1293 struct objectBucket
*b
;
1296 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1297 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1298 return (FcChar8
*) (b
+ 1);
1299 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1301 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1306 strcpy ((char *) (b
+ 1), (char *)name
);
1308 return (FcChar8
*) (b
+ 1);
1312 FcStrStaticNameFini (void)
1315 struct objectBucket
*b
, *next
;
1318 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1320 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1323 name
= (char *) (b
+ 1);
1324 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1325 FcMemFree (FC_MEM_STATICSTR
, size
);
1328 FcObjectBuckets
[i
] = 0;
1333 FcPatternFini (void)
1335 FcPatternBaseThawAll ();
1336 FcValueListThawAll ();
1337 FcStrStaticNameFini ();
1338 FcObjectStaticNameFini ();
1342 FcPatternEltU (FcPatternEltPtr pei
)
1344 if (pei
.bank
== FC_BANK_DYNAMIC
)
1347 return &fcpatternelts
[FcCacheBankToIndex(pei
.bank
)][pei
.u
.stat
];
1350 static FcPatternEltPtr
1351 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1353 FcPatternEltPtr
new;
1354 new.bank
= FC_BANK_DYNAMIC
;
1359 static FcPatternEltPtr
1360 FcPatternEltPtrCreateStatic (int bank
, int i
)
1362 FcPatternEltPtr
new;
1369 FcStrNewBank (void);
1371 FcStrNeededBytes (const FcChar8
* s
);
1373 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1374 static const FcChar8
*
1375 FcStrSerialize (int bank
, const FcChar8
* s
);
1377 FcStrUnserialize (FcCache metadata
, void *block_ptr
);
1380 FcValueListNewBank (void);
1382 FcValueListNeededBytes (FcValueList
* vl
);
1384 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1385 static FcValueListPtr
1386 FcValueListSerialize(int bank
, FcValueList
*pi
);
1388 FcValueListUnserialize (FcCache metadata
, void *block_ptr
);
1392 FcPatternNewBank (void)
1394 fcpattern_count
= 0;
1395 fcpatternelt_count
= 0;
1398 FcValueListNewBank();
1402 FcPatternNeededBytes (FcPattern
* p
)
1407 fcpatternelt_count
+= p
->num
;
1409 for (i
= 0; i
< p
->num
; i
++)
1411 c
= FcValueListNeededBytes (FcValueListPtrU
1412 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1418 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1422 FcPatternEnsureBank (int bi
)
1428 if (!fcpatterns
|| fcpattern_bank_count
<= bi
)
1430 int new_count
= bi
+ 4;
1431 pp
= realloc (fcpatterns
, sizeof (FcPattern
*) * new_count
);
1435 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1438 ep
= realloc (fcpatternelts
, sizeof (FcPatternElt
*) * new_count
);
1442 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1445 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1448 fcpatternelts
[i
] = 0;
1451 fcpattern_bank_count
= new_count
;
1454 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1459 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1461 int bi
= FcCacheBankToIndex(metadata
->bank
);
1463 if (!FcPatternEnsureBank(bi
))
1467 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1468 block_ptr
= (void *)((char *)block_ptr
+
1469 (sizeof (FcPattern
) * fcpattern_count
));
1471 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1472 fcpatternelt_ptr
= 0;
1473 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1474 block_ptr
= (void *)((char *)block_ptr
+
1475 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1477 metadata
->pattern_count
= fcpattern_count
;
1478 metadata
->patternelt_count
= fcpatternelt_count
;
1480 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1481 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1486 FcPatternSerialize (int bank
, FcPattern
*old
)
1489 FcPatternElt
*e
, *nep
;
1491 FcValueListPtr v
, nv_head
, nvp
;
1492 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1494 p
= &fcpatterns
[bi
][fcpattern_ptr
++];
1496 elts
= fcpatternelt_ptr
;
1497 nep
= &fcpatternelts
[bi
][elts
];
1501 fcpatternelt_ptr
+= old
->num
;
1503 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1506 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1507 if (!FcValueListPtrU(nv_head
))
1509 nv
= FcValueListPtrU(nvp
);
1513 v
= FcValueListPtrU(v
)->next
,
1514 nv
= FcValueListPtrU(nv
->next
))
1517 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1519 nvp
= FcValueListSerialize
1520 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1525 nep
[i
].values
= nv_head
;
1526 nep
[i
].object
= e
->object
;
1529 p
->elts
= old
->elts
;
1530 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1533 p
->ref
= FC_REF_CONSTANT
;
1538 FcPatternUnserialize (FcCache metadata
, void *block_ptr
)
1540 int bi
= FcCacheBankToIndex(metadata
.bank
);
1541 if (!FcPatternEnsureBank(bi
))
1544 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
.pattern_count
);
1545 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1546 block_ptr
= (void *)((char *)block_ptr
+
1547 (sizeof (FcPattern
) * metadata
.pattern_count
));
1549 FcMemAlloc (FC_MEM_PATELT
,
1550 sizeof (FcPatternElt
) * metadata
.patternelt_count
);
1551 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1552 block_ptr
= (void *)((char *)block_ptr
+
1553 (sizeof (FcPatternElt
) * metadata
.patternelt_count
));
1555 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1556 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1562 FcValueListNewBank (void)
1564 fcvaluelist_count
= 0;
1571 FcValueListNeededBytes (FcValueList
*p
)
1578 vl
= FcValueListPtrU(vl
->next
))
1580 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1585 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1588 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1591 cum
+= FcStrNeededBytes(v
.u
.s
);
1595 fcvaluelist_count
++;
1596 cum
+= sizeof (FcValueList
);
1603 FcValueListEnsureBank (int bi
)
1607 if (!fcvaluelists
|| fcvaluelist_bank_count
<= bi
)
1609 int new_count
= bi
+ 2, i
;
1611 pvl
= realloc (fcvaluelists
, sizeof (FcValueList
*) * new_count
);
1615 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1618 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1619 fcvaluelists
[i
] = 0;
1621 fcvaluelist_bank_count
= new_count
;
1627 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1629 int bi
= FcCacheBankToIndex(metadata
->bank
);
1631 if (!FcValueListEnsureBank(bi
))
1634 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1635 fcvaluelist_ptr
= 0;
1636 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1637 block_ptr
= (void *)((char *)block_ptr
+
1638 (sizeof (FcValueList
) * fcvaluelist_count
));
1639 metadata
->valuelist_count
= fcvaluelist_count
;
1641 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1642 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1647 static FcValueListPtr
1648 FcValueListSerialize(int bank
, FcValueList
*pi
)
1652 int bi
= FcCacheBankToIndex(bank
);
1656 new.bank
= FC_BANK_DYNAMIC
;
1661 fcvaluelists
[bi
][fcvaluelist_ptr
] = *pi
;
1663 new.u
.stat
= fcvaluelist_ptr
++;
1664 v
= &fcvaluelists
[bi
][new.u
.stat
].value
;
1670 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1672 return FcValueListPtrCreateDynamic(pi
);
1673 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1674 v
->type
|= FC_STORAGE_STATIC
;
1682 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1684 return FcValueListPtrCreateDynamic(pi
);
1685 v
->u
.c_off
= (char *)c
- (char *)v
;
1686 v
->type
|= FC_STORAGE_STATIC
;
1692 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1694 return FcValueListPtrCreateDynamic(pi
);
1695 v
->u
.l_off
= (char *)l
- (char *)v
;
1696 v
->type
|= FC_STORAGE_STATIC
;
1706 FcValueListUnserialize (FcCache metadata
, void *block_ptr
)
1708 int bi
= FcCacheBankToIndex(metadata
.bank
);
1710 if (!FcValueListEnsureBank(bi
))
1713 FcMemAlloc (FC_MEM_VALLIST
,
1714 sizeof (FcValueList
) * metadata
.valuelist_count
);
1715 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1716 block_ptr
= (void *)((char *)block_ptr
+
1717 (sizeof (FcValueList
) * metadata
.valuelist_count
));
1719 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1720 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1726 FcValueListPtrU (FcValueListPtr pi
)
1728 if (pi
.bank
== FC_BANK_DYNAMIC
)
1731 return &fcvaluelists
[FcCacheBankToIndex(pi
.bank
)][pi
.u
.stat
];
1735 FcValueListPtrCreateDynamic(FcValueList
* p
)
1739 r
.bank
= FC_BANK_DYNAMIC
;
1744 static FcChar8
** static_strs
;
1745 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1747 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1753 struct objectBucket
*b
, *next
;
1756 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1758 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1761 name
= (char *) (b
+ 1);
1762 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1763 FcMemFree (FC_MEM_STATICSTR
, size
);
1766 FcStrBuckets
[i
] = 0;
1773 FcStrNeededBytes (const FcChar8
* s
)
1775 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1776 struct objectBucket
**p
;
1777 struct objectBucket
*b
;
1780 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1781 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1783 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1785 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1790 strcpy ((char *) (b
+ 1), (char *)s
);
1791 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1794 fcstr_count
+= strlen((char *)s
) + 1;
1795 return strlen((char *)s
) + 1;
1799 FcStrEnsureBank (int bi
)
1803 if (!static_strs
|| static_str_bank_count
<= bi
)
1805 int new_count
= bi
+ 4, i
;
1806 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1810 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1813 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1815 static_str_bank_count
= new_count
;
1821 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1823 int bi
= FcCacheBankToIndex(metadata
->bank
);
1824 if (!FcStrEnsureBank(bi
))
1827 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1828 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1829 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1830 metadata
->str_count
= fcstr_count
;
1836 static const FcChar8
*
1837 FcStrSerialize (int bank
, const FcChar8
* s
)
1839 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1840 struct objectBucket
**p
;
1841 struct objectBucket
*b
;
1842 int bi
= FcCacheBankToIndex(bank
);
1844 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1845 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1847 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1850 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1851 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1852 fcstr_ptr
+= strlen((char *)s
) + 1;
1853 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1861 FcStrUnserialize (FcCache metadata
, void *block_ptr
)
1863 int bi
= FcCacheBankToIndex(metadata
.bank
);
1864 if (!FcStrEnsureBank(bi
))
1867 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
.str_count
);
1868 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1869 block_ptr
= (void *)((char *)block_ptr
+
1870 (sizeof (char) * metadata
.str_count
));