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 ((const FcChar8
*) ((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 struct objectBucket
{
1284 struct objectBucket
*next
;
1287 static struct objectBucket
*FcObjectBuckets
[OBJECT_HASH_SIZE
];
1290 FcStrStaticName (const char *name
)
1292 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1293 struct objectBucket
**p
;
1294 struct objectBucket
*b
;
1297 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
)
1299 if (b
->hash
== hash
&& !strcmp (name
, (char *) (b
+ 1)))
1300 return (char *) (b
+ 1);
1301 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1303 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1308 strcpy ((char *) (b
+ 1), name
);
1310 return (char *) (b
+ 1);
1314 FcStrStaticNameFini (void)
1317 struct objectBucket
*b
, *next
;
1320 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1322 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1325 name
= (char *) (b
+ 1);
1326 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1327 FcMemFree (FC_MEM_STATICSTR
, size
);
1330 FcObjectBuckets
[i
] = 0;
1335 FcPatternFini (void)
1337 FcPatternBaseThawAll ();
1338 FcValueListThawAll ();
1339 FcStrStaticNameFini ();
1340 FcObjectStaticNameFini ();
1344 FcPatternEltU (FcPatternEltPtr pei
)
1346 if (pei
.bank
== FC_BANK_DYNAMIC
)
1349 return &fcpatternelts
[FcCacheBankToIndex(pei
.bank
)][pei
.u
.stat
];
1352 static FcPatternEltPtr
1353 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1355 FcPatternEltPtr
new;
1356 new.bank
= FC_BANK_DYNAMIC
;
1361 static FcPatternEltPtr
1362 FcPatternEltPtrCreateStatic (int bank
, int i
)
1364 FcPatternEltPtr
new;
1371 FcStrNewBank (void);
1373 FcStrNeededBytes (const char * s
);
1375 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1377 FcStrSerialize (int bank
, const char * s
);
1379 FcStrUnserialize (FcCache metadata
, void *block_ptr
);
1382 FcValueListNewBank (void);
1384 FcValueListNeededBytes (FcValueList
* vl
);
1386 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1387 static FcValueListPtr
1388 FcValueListSerialize(int bank
, FcValueList
*pi
);
1390 FcValueListUnserialize (FcCache metadata
, void *block_ptr
);
1394 FcPatternNewBank (void)
1396 fcpattern_count
= 0;
1397 fcpatternelt_count
= 0;
1400 FcValueListNewBank();
1404 FcPatternNeededBytes (FcPattern
* p
)
1409 fcpatternelt_count
+= p
->num
;
1411 for (i
= 0; i
< p
->num
; i
++)
1413 c
= FcValueListNeededBytes (FcValueListPtrU
1414 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1420 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1424 FcPatternEnsureBank (int bi
)
1430 if (!fcpatterns
|| fcpattern_bank_count
<= bi
)
1432 int new_count
= bi
+ 4;
1433 pp
= realloc (fcpatterns
, sizeof (FcPattern
*) * new_count
);
1437 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1440 ep
= realloc (fcpatternelts
, sizeof (FcPatternElt
*) * new_count
);
1444 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1447 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1450 fcpatternelts
[i
] = 0;
1453 fcpattern_bank_count
= new_count
;
1456 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1461 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1463 int bi
= FcCacheBankToIndex(metadata
->bank
);
1465 if (!FcPatternEnsureBank(bi
))
1469 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1470 block_ptr
= (void *)((char *)block_ptr
+
1471 (sizeof (FcPattern
) * fcpattern_count
));
1473 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1474 fcpatternelt_ptr
= 0;
1475 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1476 block_ptr
= (void *)((char *)block_ptr
+
1477 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1479 metadata
->pattern_count
= fcpattern_count
;
1480 metadata
->patternelt_count
= fcpatternelt_count
;
1482 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1483 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1488 FcPatternSerialize (int bank
, FcPattern
*old
)
1491 FcPatternElt
*e
, *nep
;
1493 FcValueListPtr v
, nv_head
, nvp
;
1494 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1496 p
= &fcpatterns
[bi
][fcpattern_ptr
++];
1498 elts
= fcpatternelt_ptr
;
1499 nep
= &fcpatternelts
[bi
][elts
];
1503 fcpatternelt_ptr
+= old
->num
;
1505 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1508 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1509 if (!FcValueListPtrU(nv_head
))
1511 nv
= FcValueListPtrU(nvp
);
1515 v
= FcValueListPtrU(v
)->next
,
1516 nv
= FcValueListPtrU(nv
->next
))
1519 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1521 nvp
= FcValueListSerialize
1522 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1527 nep
[i
].values
= nv_head
;
1528 nep
[i
].object
= e
->object
;
1531 p
->elts
= old
->elts
;
1532 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1535 p
->ref
= FC_REF_CONSTANT
;
1540 FcPatternUnserialize (FcCache metadata
, void *block_ptr
)
1542 int bi
= FcCacheBankToIndex(metadata
.bank
);
1543 if (!FcPatternEnsureBank(bi
))
1546 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
.pattern_count
);
1547 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1548 block_ptr
= (void *)((char *)block_ptr
+
1549 (sizeof (FcPattern
) * metadata
.pattern_count
));
1551 FcMemAlloc (FC_MEM_PATELT
,
1552 sizeof (FcPatternElt
) * metadata
.patternelt_count
);
1553 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1554 block_ptr
= (void *)((char *)block_ptr
+
1555 (sizeof (FcPatternElt
) * metadata
.patternelt_count
));
1557 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1558 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1564 FcValueListNewBank (void)
1566 fcvaluelist_count
= 0;
1573 FcValueListNeededBytes (FcValueList
*p
)
1580 vl
= FcValueListPtrU(vl
->next
))
1582 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1587 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1590 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1593 cum
+= FcStrNeededBytes(v
.u
.s
);
1597 fcvaluelist_count
++;
1598 cum
+= sizeof (FcValueList
);
1605 FcValueListEnsureBank (int bi
)
1609 if (!fcvaluelists
|| fcvaluelist_bank_count
<= bi
)
1611 int new_count
= bi
+ 2, i
;
1613 pvl
= realloc (fcvaluelists
, sizeof (FcValueList
*) * new_count
);
1617 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1620 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1621 fcvaluelists
[i
] = 0;
1623 fcvaluelist_bank_count
= new_count
;
1629 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1631 int bi
= FcCacheBankToIndex(metadata
->bank
);
1633 if (!FcValueListEnsureBank(bi
))
1636 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1637 fcvaluelist_ptr
= 0;
1638 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1639 block_ptr
= (void *)((char *)block_ptr
+
1640 (sizeof (FcValueList
) * fcvaluelist_count
));
1641 metadata
->valuelist_count
= fcvaluelist_count
;
1643 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1644 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1649 static FcValueListPtr
1650 FcValueListSerialize(int bank
, FcValueList
*pi
)
1654 int bi
= FcCacheBankToIndex(bank
);
1658 new.bank
= FC_BANK_DYNAMIC
;
1663 fcvaluelists
[bi
][fcvaluelist_ptr
] = *pi
;
1665 new.u
.stat
= fcvaluelist_ptr
++;
1666 v
= &fcvaluelists
[bi
][new.u
.stat
].value
;
1672 const char * s
= FcStrSerialize(bank
, v
->u
.s
);
1674 return FcValueListPtrCreateDynamic(pi
);
1675 v
->u
.s_off
= s
- (const char *)v
;
1676 v
->type
|= FC_STORAGE_STATIC
;
1684 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1686 return FcValueListPtrCreateDynamic(pi
);
1687 v
->u
.c_off
= (char *)c
- (char *)v
;
1688 v
->type
|= FC_STORAGE_STATIC
;
1694 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1696 return FcValueListPtrCreateDynamic(pi
);
1697 v
->u
.l_off
= (char *)l
- (char *)v
;
1698 v
->type
|= FC_STORAGE_STATIC
;
1708 FcValueListUnserialize (FcCache metadata
, void *block_ptr
)
1710 int bi
= FcCacheBankToIndex(metadata
.bank
);
1712 if (!FcValueListEnsureBank(bi
))
1715 FcMemAlloc (FC_MEM_VALLIST
,
1716 sizeof (FcValueList
) * metadata
.valuelist_count
);
1717 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1718 block_ptr
= (void *)((char *)block_ptr
+
1719 (sizeof (FcValueList
) * metadata
.valuelist_count
));
1721 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1722 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1728 FcValueListPtrU (FcValueListPtr pi
)
1730 if (pi
.bank
== FC_BANK_DYNAMIC
)
1733 return &fcvaluelists
[FcCacheBankToIndex(pi
.bank
)][pi
.u
.stat
];
1737 FcValueListPtrCreateDynamic(FcValueList
* p
)
1741 r
.bank
= FC_BANK_DYNAMIC
;
1746 static char ** static_strs
;
1747 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1749 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1755 struct objectBucket
*b
, *next
;
1758 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1760 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1763 name
= (char *) (b
+ 1);
1764 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1765 FcMemFree (FC_MEM_STATICSTR
, size
);
1768 FcStrBuckets
[i
] = 0;
1775 FcStrNeededBytes (const char * s
)
1777 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1778 struct objectBucket
**p
;
1779 struct objectBucket
*b
;
1782 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1783 if (b
->hash
== hash
&& !strcmp (s
, (char *) (b
+ 1)))
1785 size
= sizeof (struct objectBucket
) + strlen (s
) + 1 + sizeof(char *);
1787 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1792 strcpy ((char *) (b
+ 1), s
);
1793 *(char **)((char *) (b
+ 1) + strlen(s
) + 1) = 0;
1796 fcstr_count
+= strlen(s
) + 1;
1797 return strlen(s
) + 1;
1801 FcStrEnsureBank (int bi
)
1805 if (!static_strs
|| static_str_bank_count
<= bi
)
1807 int new_count
= bi
+ 4, i
;
1808 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1812 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1815 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1817 static_str_bank_count
= new_count
;
1823 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1825 int bi
= FcCacheBankToIndex(metadata
->bank
);
1826 if (!FcStrEnsureBank(bi
))
1829 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1830 static_strs
[bi
] = (char *)block_ptr
;
1831 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1832 metadata
->str_count
= fcstr_count
;
1839 FcStrSerialize (int bank
, const char * s
)
1841 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1842 struct objectBucket
**p
;
1843 struct objectBucket
*b
;
1844 int bi
= FcCacheBankToIndex(bank
);
1846 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1847 if (b
->hash
== hash
&& !strcmp (s
, (char *) (b
+ 1)))
1849 char * t
= *(char **)(((char *)(b
+ 1)) + strlen (s
) + 1);
1852 strcpy(static_strs
[bi
] + fcstr_ptr
, s
);
1853 *(char **)((char *) (b
+ 1) + strlen(s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1854 fcstr_ptr
+= strlen(s
) + 1;
1855 t
= *(char **)(((char *)(b
+ 1)) + strlen (s
) + 1);
1863 FcStrUnserialize (FcCache metadata
, void *block_ptr
)
1865 int bi
= FcCacheBankToIndex(metadata
.bank
);
1866 if (!FcStrEnsureBank(bi
))
1869 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
.str_count
);
1870 static_strs
[bi
] = (char *)block_ptr
;
1871 block_ptr
= (void *)((char *)block_ptr
+
1872 (sizeof (char) * metadata
.str_count
));