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 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1226 FcPatternDestroy (new);
1232 FcPatternReference (FcPattern
*p
)
1234 if (p
->ref
!= FC_REF_CONSTANT
)
1239 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1243 FcPatternVapBuild (ret
, orig
, va
);
1248 FcPatternBuild (FcPattern
*orig
, ...)
1252 va_start (va
, orig
);
1253 FcPatternVapBuild (orig
, orig
, va
);
1259 * Add all of the elements in 's' to 'p'
1262 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1268 for (i
= 0; i
< s
->num
; i
++)
1270 e
= FcPatternEltU(s
->elts
)+i
;
1271 for (v
= e
->values
; FcValueListPtrU(v
);
1272 v
= FcValueListPtrU(v
)->next
)
1274 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1275 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1276 FcValueListPtrU(v
)->binding
, FcTrue
))
1283 #define OBJECT_HASH_SIZE 31
1284 static struct objectBucket
{
1285 struct objectBucket
*next
;
1287 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1290 FcStrStaticName (const FcChar8
*name
)
1292 FcChar32 hash
= FcStringHash (name
);
1293 struct objectBucket
**p
;
1294 struct objectBucket
*b
;
1297 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1298 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1299 return (FcChar8
*) (b
+ 1);
1300 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1302 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1307 strcpy ((char *) (b
+ 1), (char *)name
);
1309 return (FcChar8
*) (b
+ 1);
1313 FcStrStaticNameFini (void)
1316 struct objectBucket
*b
, *next
;
1319 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1321 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1324 name
= (char *) (b
+ 1);
1325 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1326 FcMemFree (FC_MEM_STATICSTR
, size
);
1329 FcObjectBuckets
[i
] = 0;
1334 FcPatternFini (void)
1336 FcPatternBaseThawAll ();
1337 FcValueListThawAll ();
1338 FcStrStaticNameFini ();
1339 FcObjectStaticNameFini ();
1343 FcPatternEltU (FcPatternEltPtr pei
)
1345 if (pei
.bank
== FC_BANK_DYNAMIC
)
1348 return &fcpatternelts
[FcCacheBankToIndex(pei
.bank
)][pei
.u
.stat
];
1351 static FcPatternEltPtr
1352 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1354 FcPatternEltPtr
new;
1355 new.bank
= FC_BANK_DYNAMIC
;
1360 static FcPatternEltPtr
1361 FcPatternEltPtrCreateStatic (int bank
, int i
)
1363 FcPatternEltPtr
new;
1370 FcStrNewBank (void);
1372 FcStrNeededBytes (const FcChar8
* s
);
1374 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1375 static const FcChar8
*
1376 FcStrSerialize (int bank
, const FcChar8
* s
);
1378 FcStrUnserialize (FcCache metadata
, void *block_ptr
);
1381 FcValueListNewBank (void);
1383 FcValueListNeededBytes (FcValueList
* vl
);
1385 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1386 static FcValueListPtr
1387 FcValueListSerialize(int bank
, FcValueList
*pi
);
1389 FcValueListUnserialize (FcCache metadata
, void *block_ptr
);
1393 FcPatternNewBank (void)
1395 fcpattern_count
= 0;
1396 fcpatternelt_count
= 0;
1399 FcValueListNewBank();
1403 FcPatternNeededBytes (FcPattern
* p
)
1408 fcpatternelt_count
+= p
->num
;
1410 for (i
= 0; i
< p
->num
; i
++)
1412 c
= FcValueListNeededBytes (FcValueListPtrU
1413 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1419 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1423 FcPatternEnsureBank (int bi
)
1429 if (!fcpatterns
|| fcpattern_bank_count
<= bi
)
1431 int new_count
= bi
+ 4;
1432 pp
= realloc (fcpatterns
, sizeof (FcPattern
*) * new_count
);
1436 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1439 ep
= realloc (fcpatternelts
, sizeof (FcPatternElt
*) * new_count
);
1443 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1446 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1449 fcpatternelts
[i
] = 0;
1452 fcpattern_bank_count
= new_count
;
1455 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1460 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1462 int bi
= FcCacheBankToIndex(metadata
->bank
);
1464 if (!FcPatternEnsureBank(bi
))
1468 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1469 block_ptr
= (void *)((char *)block_ptr
+
1470 (sizeof (FcPattern
) * fcpattern_count
));
1472 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1473 fcpatternelt_ptr
= 0;
1474 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1475 block_ptr
= (void *)((char *)block_ptr
+
1476 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1478 metadata
->pattern_count
= fcpattern_count
;
1479 metadata
->patternelt_count
= fcpatternelt_count
;
1481 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1482 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1487 FcPatternSerialize (int bank
, FcPattern
*old
)
1490 FcPatternElt
*e
, *nep
;
1492 FcValueListPtr v
, nv_head
, nvp
;
1493 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1495 p
= &fcpatterns
[bi
][fcpattern_ptr
++];
1497 elts
= fcpatternelt_ptr
;
1498 nep
= &fcpatternelts
[bi
][elts
];
1502 fcpatternelt_ptr
+= old
->num
;
1504 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1507 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1508 if (!FcValueListPtrU(nv_head
))
1510 nv
= FcValueListPtrU(nvp
);
1514 v
= FcValueListPtrU(v
)->next
,
1515 nv
= FcValueListPtrU(nv
->next
))
1518 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1520 nvp
= FcValueListSerialize
1521 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1526 nep
[i
].values
= nv_head
;
1527 nep
[i
].object
= e
->object
;
1530 p
->elts
= old
->elts
;
1531 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1534 p
->ref
= FC_REF_CONSTANT
;
1539 FcPatternUnserialize (FcCache metadata
, void *block_ptr
)
1541 int bi
= FcCacheBankToIndex(metadata
.bank
);
1542 if (!FcPatternEnsureBank(bi
))
1545 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
.pattern_count
);
1546 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1547 block_ptr
= (void *)((char *)block_ptr
+
1548 (sizeof (FcPattern
) * metadata
.pattern_count
));
1550 FcMemAlloc (FC_MEM_PATELT
,
1551 sizeof (FcPatternElt
) * metadata
.patternelt_count
);
1552 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1553 block_ptr
= (void *)((char *)block_ptr
+
1554 (sizeof (FcPatternElt
) * metadata
.patternelt_count
));
1556 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1557 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1563 FcValueListNewBank (void)
1565 fcvaluelist_count
= 0;
1572 FcValueListNeededBytes (FcValueList
*p
)
1579 vl
= FcValueListPtrU(vl
->next
))
1581 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1586 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1589 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1592 cum
+= FcStrNeededBytes(v
.u
.s
);
1596 fcvaluelist_count
++;
1597 cum
+= sizeof (FcValueList
);
1604 FcValueListEnsureBank (int bi
)
1608 if (!fcvaluelists
|| fcvaluelist_bank_count
<= bi
)
1610 int new_count
= bi
+ 2, i
;
1612 pvl
= realloc (fcvaluelists
, sizeof (FcValueList
*) * new_count
);
1616 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1619 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1620 fcvaluelists
[i
] = 0;
1622 fcvaluelist_bank_count
= new_count
;
1628 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1630 int bi
= FcCacheBankToIndex(metadata
->bank
);
1632 if (!FcValueListEnsureBank(bi
))
1635 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1636 fcvaluelist_ptr
= 0;
1637 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1638 block_ptr
= (void *)((char *)block_ptr
+
1639 (sizeof (FcValueList
) * fcvaluelist_count
));
1640 metadata
->valuelist_count
= fcvaluelist_count
;
1642 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1643 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1648 static FcValueListPtr
1649 FcValueListSerialize(int bank
, FcValueList
*pi
)
1653 int bi
= FcCacheBankToIndex(bank
);
1657 new.bank
= FC_BANK_DYNAMIC
;
1662 fcvaluelists
[bi
][fcvaluelist_ptr
] = *pi
;
1664 new.u
.stat
= fcvaluelist_ptr
++;
1665 v
= &fcvaluelists
[bi
][new.u
.stat
].value
;
1671 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1673 return FcValueListPtrCreateDynamic(pi
);
1674 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1675 v
->type
|= FC_STORAGE_STATIC
;
1683 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1685 return FcValueListPtrCreateDynamic(pi
);
1686 v
->u
.c_off
= (char *)c
- (char *)v
;
1687 v
->type
|= FC_STORAGE_STATIC
;
1693 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1695 return FcValueListPtrCreateDynamic(pi
);
1696 v
->u
.l_off
= (char *)l
- (char *)v
;
1697 v
->type
|= FC_STORAGE_STATIC
;
1707 FcValueListUnserialize (FcCache metadata
, void *block_ptr
)
1709 int bi
= FcCacheBankToIndex(metadata
.bank
);
1711 if (!FcValueListEnsureBank(bi
))
1714 FcMemAlloc (FC_MEM_VALLIST
,
1715 sizeof (FcValueList
) * metadata
.valuelist_count
);
1716 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1717 block_ptr
= (void *)((char *)block_ptr
+
1718 (sizeof (FcValueList
) * metadata
.valuelist_count
));
1720 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1721 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1727 FcValueListPtrU (FcValueListPtr pi
)
1729 if (pi
.bank
== FC_BANK_DYNAMIC
)
1732 return &fcvaluelists
[FcCacheBankToIndex(pi
.bank
)][pi
.u
.stat
];
1736 FcValueListPtrCreateDynamic(FcValueList
* p
)
1740 r
.bank
= FC_BANK_DYNAMIC
;
1745 static FcChar8
** static_strs
;
1746 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1748 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1754 struct objectBucket
*b
, *next
;
1757 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1759 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1762 name
= (char *) (b
+ 1);
1763 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1764 FcMemFree (FC_MEM_STATICSTR
, size
);
1767 FcStrBuckets
[i
] = 0;
1774 FcStrNeededBytes (const FcChar8
* s
)
1776 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1777 struct objectBucket
**p
;
1778 struct objectBucket
*b
;
1781 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1782 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1784 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1786 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1791 strcpy ((char *) (b
+ 1), (char *)s
);
1792 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1795 fcstr_count
+= strlen((char *)s
) + 1;
1796 return strlen((char *)s
) + 1;
1800 FcStrEnsureBank (int bi
)
1804 if (!static_strs
|| static_str_bank_count
<= bi
)
1806 int new_count
= bi
+ 4, i
;
1807 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1811 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1814 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1816 static_str_bank_count
= new_count
;
1822 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1824 int bi
= FcCacheBankToIndex(metadata
->bank
);
1825 if (!FcStrEnsureBank(bi
))
1828 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1829 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1830 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1831 metadata
->str_count
= fcstr_count
;
1837 static const FcChar8
*
1838 FcStrSerialize (int bank
, const FcChar8
* s
)
1840 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1841 struct objectBucket
**p
;
1842 struct objectBucket
*b
;
1843 int bi
= FcCacheBankToIndex(bank
);
1845 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1846 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1848 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1851 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1852 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1853 fcstr_ptr
+= strlen((char *)s
) + 1;
1854 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1862 FcStrUnserialize (FcCache metadata
, void *block_ptr
)
1864 int bi
= FcCacheBankToIndex(metadata
.bank
);
1865 if (!FcStrEnsureBank(bi
))
1868 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
.str_count
);
1869 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1870 block_ptr
= (void *)((char *)block_ptr
+
1871 (sizeof (char) * metadata
.str_count
));