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
= FcObjectStaticName
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
= FcObjectStaticName(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 FcObjectStaticName (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 FcObjectStaticNameFini (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 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 char * s
);
1374 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1376 FcStrSerialize (int bank
, const char * 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 cum
+= FcObjectNeededBytes
1413 ((FcPatternEltU(p
->elts
)+i
)->object
);
1414 c
= FcValueListNeededBytes (FcValueListPtrU
1415 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1421 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1425 FcPatternEnsureBank (int bi
)
1431 if (!fcpatterns
|| fcpattern_bank_count
<= bi
)
1433 int new_count
= bi
+ 4;
1434 pp
= realloc (fcpatterns
, sizeof (FcPattern
*) * new_count
);
1438 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1441 ep
= realloc (fcpatternelts
, sizeof (FcPatternElt
*) * new_count
);
1445 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1448 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1451 fcpatternelts
[i
] = 0;
1454 fcpattern_bank_count
= new_count
;
1457 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1462 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1464 int bi
= FcCacheBankToIndex(metadata
->bank
);
1466 if (!FcPatternEnsureBank(bi
))
1470 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1471 block_ptr
= (void *)((char *)block_ptr
+
1472 (sizeof (FcPattern
) * fcpattern_count
));
1474 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1475 fcpatternelt_ptr
= 0;
1476 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1477 block_ptr
= (void *)((char *)block_ptr
+
1478 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1480 metadata
->pattern_count
= fcpattern_count
;
1481 metadata
->patternelt_count
= fcpatternelt_count
;
1483 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1484 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1489 FcPatternSerialize (int bank
, FcPattern
*old
)
1492 FcPatternElt
*e
, *nep
;
1494 FcValueListPtr v
, nv_head
, nvp
;
1495 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1497 p
= &fcpatterns
[bi
][fcpattern_ptr
++];
1499 elts
= fcpatternelt_ptr
;
1500 nep
= &fcpatternelts
[bi
][elts
];
1504 fcpatternelt_ptr
+= old
->num
;
1506 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1509 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1510 if (!FcValueListPtrU(nv_head
))
1512 nv
= FcValueListPtrU(nvp
);
1516 v
= FcValueListPtrU(v
)->next
,
1517 nv
= FcValueListPtrU(nv
->next
))
1520 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1522 nvp
= FcValueListSerialize
1523 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1528 nep
[i
].values
= nv_head
;
1529 nep
[i
].object
= FcObjectSerialize (e
->object
);
1532 p
->elts
= old
->elts
;
1533 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1536 p
->ref
= FC_REF_CONSTANT
;
1541 FcPatternUnserialize (FcCache metadata
, void *block_ptr
)
1543 int bi
= FcCacheBankToIndex(metadata
.bank
);
1544 if (!FcPatternEnsureBank(bi
))
1547 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
.pattern_count
);
1548 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1549 block_ptr
= (void *)((char *)block_ptr
+
1550 (sizeof (FcPattern
) * metadata
.pattern_count
));
1552 FcMemAlloc (FC_MEM_PATELT
,
1553 sizeof (FcPatternElt
) * metadata
.patternelt_count
);
1554 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1555 block_ptr
= (void *)((char *)block_ptr
+
1556 (sizeof (FcPatternElt
) * metadata
.patternelt_count
));
1558 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1559 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1561 return fcpatterns
[bi
];
1565 FcValueListNewBank (void)
1567 fcvaluelist_count
= 0;
1574 FcValueListNeededBytes (FcValueList
*p
)
1581 vl
= FcValueListPtrU(vl
->next
))
1583 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1588 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1591 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1594 cum
+= FcStrNeededBytes(v
.u
.s
);
1598 fcvaluelist_count
++;
1599 cum
+= sizeof (FcValueList
);
1606 FcValueListEnsureBank (int bi
)
1610 if (!fcvaluelists
|| fcvaluelist_bank_count
<= bi
)
1612 int new_count
= bi
+ 2, i
;
1614 pvl
= realloc (fcvaluelists
, sizeof (FcValueList
*) * new_count
);
1618 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1621 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1622 fcvaluelists
[i
] = 0;
1624 fcvaluelist_bank_count
= new_count
;
1630 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1632 int bi
= FcCacheBankToIndex(metadata
->bank
);
1634 if (!FcValueListEnsureBank(bi
))
1637 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1638 fcvaluelist_ptr
= 0;
1639 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1640 block_ptr
= (void *)((char *)block_ptr
+
1641 (sizeof (FcValueList
) * fcvaluelist_count
));
1642 metadata
->valuelist_count
= fcvaluelist_count
;
1644 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1645 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1650 static FcValueListPtr
1651 FcValueListSerialize(int bank
, FcValueList
*pi
)
1655 int bi
= FcCacheBankToIndex(bank
);
1659 new.bank
= FC_BANK_DYNAMIC
;
1664 fcvaluelists
[bi
][fcvaluelist_ptr
] = *pi
;
1666 new.u
.stat
= fcvaluelist_ptr
++;
1667 v
= &fcvaluelists
[bi
][new.u
.stat
].value
;
1673 const char * s
= FcStrSerialize(bank
, v
->u
.s
);
1675 return FcValueListPtrCreateDynamic(pi
);
1676 v
->u
.s_off
= s
- (const char *)v
;
1677 v
->type
|= FC_STORAGE_STATIC
;
1685 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1687 return FcValueListPtrCreateDynamic(pi
);
1688 v
->u
.c_off
= (char *)c
- (char *)v
;
1689 v
->type
|= FC_STORAGE_STATIC
;
1695 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1697 return FcValueListPtrCreateDynamic(pi
);
1698 v
->u
.l_off
= (char *)l
- (char *)v
;
1699 v
->type
|= FC_STORAGE_STATIC
;
1709 FcValueListUnserialize (FcCache metadata
, void *block_ptr
)
1711 int bi
= FcCacheBankToIndex(metadata
.bank
);
1713 if (!FcValueListEnsureBank(bi
))
1716 FcMemAlloc (FC_MEM_VALLIST
,
1717 sizeof (FcValueList
) * metadata
.valuelist_count
);
1718 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1719 block_ptr
= (void *)((char *)block_ptr
+
1720 (sizeof (FcValueList
) * metadata
.valuelist_count
));
1722 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1723 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1729 FcValueListPtrU (FcValueListPtr pi
)
1731 if (pi
.bank
== FC_BANK_DYNAMIC
)
1734 return &fcvaluelists
[FcCacheBankToIndex(pi
.bank
)][pi
.u
.stat
];
1738 FcValueListPtrCreateDynamic(FcValueList
* p
)
1742 r
.bank
= FC_BANK_DYNAMIC
;
1747 static char ** static_strs
;
1748 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1750 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1756 struct objectBucket
*b
, *next
;
1759 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1761 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1764 name
= (char *) (b
+ 1);
1765 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1766 FcMemFree (FC_MEM_STATICSTR
, size
);
1769 FcStrBuckets
[i
] = 0;
1776 FcStrNeededBytes (const char * s
)
1778 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1779 struct objectBucket
**p
;
1780 struct objectBucket
*b
;
1783 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1784 if (b
->hash
== hash
&& !strcmp (s
, (char *) (b
+ 1)))
1786 size
= sizeof (struct objectBucket
) + strlen (s
) + 1 + sizeof(char *);
1788 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1793 strcpy ((char *) (b
+ 1), s
);
1794 *(char **)((char *) (b
+ 1) + strlen(s
) + 1) = 0;
1797 fcstr_count
+= strlen(s
) + 1;
1798 return strlen(s
) + 1;
1802 FcStrEnsureBank (int bi
)
1806 if (!static_strs
|| static_str_bank_count
<= bi
)
1808 int new_count
= bi
+ 4, i
;
1809 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1813 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1816 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1818 static_str_bank_count
= new_count
;
1824 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1826 int bi
= FcCacheBankToIndex(metadata
->bank
);
1827 if (!FcStrEnsureBank(bi
))
1830 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1831 static_strs
[bi
] = (char *)block_ptr
;
1832 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1833 metadata
->str_count
= fcstr_count
;
1840 FcStrSerialize (int bank
, const char * s
)
1842 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1843 struct objectBucket
**p
;
1844 struct objectBucket
*b
;
1845 int bi
= FcCacheBankToIndex(bank
);
1847 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1848 if (b
->hash
== hash
&& !strcmp (s
, (char *) (b
+ 1)))
1850 char * t
= *(char **)(((char *)(b
+ 1)) + strlen (s
) + 1);
1853 strcpy(static_strs
[bi
] + fcstr_ptr
, s
);
1854 *(char **)((char *) (b
+ 1) + strlen(s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1855 fcstr_ptr
+= strlen(s
) + 1;
1856 t
= *(char **)(((char *)(b
+ 1)) + strlen (s
) + 1);
1864 FcStrUnserialize (FcCache metadata
, void *block_ptr
)
1866 int bi
= FcCacheBankToIndex(metadata
.bank
);
1867 if (!FcStrEnsureBank(bi
))
1870 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
.str_count
);
1871 static_strs
[bi
] = (char *)block_ptr
;
1872 block_ptr
= (void *)((char *)block_ptr
+
1873 (sizeof (char) * metadata
.str_count
));