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
;
38 FcPatternFindFullFname (const FcPattern
*p
);
39 static FcPatternEltPtr
40 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
);
42 /* If you are trying to duplicate an FcPattern which will be used for
43 * rendering, be aware that (internally) you also have to use
44 * FcPatternTransferFullFname to transfer the associated filename. If
45 * you are copying the font (externally) using FcPatternGetString,
46 * then everything's fine; this caveat only applies if you're copying
47 * the bits individually. */
50 FcPatternCreate (void)
54 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
57 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
60 p
->elts
= FcPatternEltPtrCreateDynamic(0);
61 p
->bank
= FC_BANK_DYNAMIC
;
67 FcValueDestroy (FcValue v
)
71 FcStrFree ((FcChar8
*) v
.u
.s
);
74 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
77 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
80 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
88 FcValueCanonicalize (const FcValue
*v
)
90 if (v
->type
& FC_STORAGE_STATIC
)
94 switch (v
->type
& ~FC_STORAGE_STATIC
)
97 new.u
.s
= fc_value_string(v
);
98 new.type
= FcTypeString
;
101 new.u
.c
= fc_value_charset(v
);
102 new.type
= FcTypeCharSet
;
105 new.u
.l
= fc_value_langset(v
);
106 new.type
= FcTypeLangSet
;
115 FcValueSave (FcValue v
)
119 v
.u
.s
= FcStrCopy (v
.u
.s
);
124 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
129 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
134 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
145 FcValueListDestroy (FcValueListPtr l
)
148 for (; FcValueListPtrU(l
); l
= next
)
150 switch (FcValueListPtrU(l
)->value
.type
) {
152 FcStrFree ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
);
155 FcMatrixFree ((FcMatrix
*)FcValueListPtrU(l
)->value
.u
.m
);
159 ((FcCharSet
*) (FcValueListPtrU(l
)->value
.u
.c
));
163 ((FcLangSet
*) (FcValueListPtrU(l
)->value
.u
.l
));
168 next
= FcValueListPtrU(l
)->next
;
169 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
170 if (l
.bank
== FC_BANK_DYNAMIC
)
176 FcValueEqual (FcValue va
, FcValue vb
)
178 if (va
.type
!= vb
.type
)
180 if (va
.type
== FcTypeInteger
)
182 va
.type
= FcTypeDouble
;
185 if (vb
.type
== FcTypeInteger
)
187 vb
.type
= FcTypeDouble
;
190 if (va
.type
!= vb
.type
)
197 return va
.u
.i
== vb
.u
.i
;
199 return va
.u
.d
== vb
.u
.d
;
201 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
203 return va
.u
.b
== vb
.u
.b
;
205 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
207 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
209 return va
.u
.f
== vb
.u
.f
;
211 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
217 FcDoubleHash (double d
)
227 FcStringHash (const FcChar8
*s
)
234 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
239 FcValueHash (const FcValue
*v0
)
241 FcValue v
= FcValueCanonicalize(v0
);
246 return (FcChar32
) v
.u
.i
;
248 return FcDoubleHash (v
.u
.d
);
250 return FcStringHash (v
.u
.s
);
252 return (FcChar32
) v
.u
.b
;
254 return (FcDoubleHash (v
.u
.m
->xx
) ^
255 FcDoubleHash (v
.u
.m
->xy
) ^
256 FcDoubleHash (v
.u
.m
->yx
) ^
257 FcDoubleHash (v
.u
.m
->yy
));
259 return (FcChar32
) v
.u
.c
->num
;
261 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
262 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
264 return FcLangSetHash (v
.u
.l
);
270 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
272 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
275 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
277 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
278 FcValueListPtrU(lb
)->value
))
280 la
= FcValueListPtrU(la
)->next
;
281 lb
= FcValueListPtrU(lb
)->next
;
283 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
289 FcValueListHash (FcValueListPtr l
)
293 while (FcValueListPtrU(l
))
295 hash
= ((hash
<< 1) | (hash
>> 31)) ^
296 FcValueHash (&FcValueListPtrU(l
)->value
);
297 l
= FcValueListPtrU(l
)->next
;
303 FcPatternDestroy (FcPattern
*p
)
307 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
310 if (FcPatternFindFullFname (p
))
312 FcStrFree ((FcChar8
*)FcPatternFindFullFname (p
));
313 FcPatternAddFullFname (p
, 0);
316 for (i
= 0; i
< p
->num
; i
++)
317 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
320 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
322 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
323 free (FcPatternEltU(p
->elts
));
324 p
->elts
= FcPatternEltPtrCreateDynamic(0);
327 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
331 #define FC_VALUE_LIST_HASH_SIZE 257
332 #define FC_PATTERN_HASH_SIZE 67
334 typedef struct _FcValueListEnt FcValueListEnt
;
336 struct _FcValueListEnt
{
337 FcValueListEnt
*next
;
342 typedef union _FcValueListAlign
{
347 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
348 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
349 static char FcValueListFrozenName
[][8] = {
362 FcValueListReport (void);
365 FcValueListReport (void)
369 printf ("Fc Frozen Values:\n");
370 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
371 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
372 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
373 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
376 static FcValueListEnt
*
377 FcValueListEntCreate (FcValueListPtr h
)
379 FcValueListAlign
*ea
;
387 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
389 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
390 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
391 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
392 // this leaks for some reason
393 ea
= malloc (sizeof (FcValueListAlign
));
396 new = malloc (n
* sizeof (FcValueList
));
399 memset(new, 0, n
* sizeof (FcValueList
));
400 FcMemAlloc (FC_MEM_VALLIST
, size
);
402 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
403 for (l
= h
; FcValueListPtrU(l
);
404 l
= FcValueListPtrU(l
)->next
, new++)
406 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
408 new->value
.type
= FcTypeString
;
409 new->value
.u
.s
= FcStrStaticName
410 (fc_value_string(&FcValueListPtrU(l
)->value
));
414 new->value
= FcValueSave (FcValueCanonicalize
415 (&FcValueListPtrU(l
)->value
));
417 new->binding
= FcValueListPtrU(l
)->binding
;
418 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
420 new->next
= FcValueListPtrCreateDynamic(new + 1);
424 new->next
= FcValueListPtrCreateDynamic(0);
431 FcValueListEntDestroy (FcValueListEnt
*e
)
435 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
437 /* XXX: We should perform these two operations with "size" as
438 computed in FcValueListEntCreate, but we don't have access to
439 that value here. Without this, the FcValueListFrozenBytes
440 values will be wrong as will the FcMemFree counts.
442 FcValueListFrozenBytes[e->list->value.type] -= size;
443 FcMemFree (FC_MEM_VALLIST, size);
446 for (l
= e
->list
; FcValueListPtrU(l
);
447 l
= FcValueListPtrU(l
)->next
)
449 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
450 FcValueDestroy (FcValueListPtrU(l
)->value
);
452 /* XXX: Are we being too chummy with the implementation here to
453 free(e) when it was actually the enclosing FcValueListAlign
454 that was allocated? */
458 static int FcValueListTotal
;
459 static int FcValueListUsed
;
461 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
463 static FcValueListPtr
464 FcValueListFreeze (FcValueListPtr l
)
466 FcChar32 hash
= FcValueListHash (l
);
467 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
471 for (ent
= *bucket
; ent
; ent
= ent
->next
)
473 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
477 ent
= FcValueListEntCreate (l
);
479 return FcValueListPtrCreateDynamic(0);
489 FcValueListThawAll (void)
492 FcValueListEnt
*ent
, *next
;
494 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
496 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
499 FcValueListEntDestroy (ent
);
501 FcValueListHashTable
[i
] = 0;
504 FcValueListTotal
= 0;
509 FcPatternBaseHash (FcPattern
*b
)
511 FcChar32 hash
= b
->num
;
514 for (i
= 0; i
< b
->num
; i
++)
515 hash
= ((hash
<< 1) | (hash
>> 31)) ^
516 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
520 typedef struct _FcPatternEnt FcPatternEnt
;
522 struct _FcPatternEnt
{
528 static int FcPatternTotal
;
529 static int FcPatternUsed
;
531 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
534 FcPatternBaseFreeze (FcPattern
*b
)
538 FcChar32 hash
= FcPatternBaseHash (b
);
539 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
544 for (ent
= *bucket
; ent
; ent
= ent
->next
)
546 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
548 for (i
= 0; i
< b
->num
; i
++)
550 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
551 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
553 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
554 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
563 * Compute size of pattern + elts
565 ent
= malloc (sizeof (FcPatternEnt
));
569 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
572 ep
= FcPatternCreate();
576 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
579 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
581 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
585 ep
->ref
= FC_REF_CONSTANT
;
587 for (i
= 0; i
< b
->num
; i
++)
589 (FcPatternEltU(ep
->elts
)+i
)->values
=
590 (FcPatternEltU(b
->elts
)+i
)->values
;
591 (FcPatternEltU(ep
->elts
)+i
)->object
=
592 (FcPatternEltU(b
->elts
)+i
)->object
;
595 if (FcPatternFindElt (b
, FC_FILE
))
596 FcPatternTransferFullFname (ep
, b
);
604 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
610 FcPatternBaseThawAll (void)
613 FcPatternEnt
*ent
, *next
;
615 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
617 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
622 FcPatternHashTable
[i
] = 0;
630 FcPatternFreeze (FcPattern
*p
)
632 FcPattern
*b
, *n
= 0;
636 if (p
->ref
== FC_REF_CONSTANT
)
639 b
= FcPatternCreate();
647 e
= malloc(b
->num
* sizeof (FcPatternElt
));
650 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
651 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
654 * Freeze object lists
656 for (i
= 0; i
< p
->num
; i
++)
658 (FcPatternEltU(b
->elts
)+i
)->object
=
659 (FcPatternEltU(p
->elts
)+i
)->object
;
660 (FcPatternEltU(b
->elts
)+i
)->values
=
661 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
662 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
666 if (FcPatternFindElt (p
, FC_FILE
))
667 FcPatternTransferFullFname (b
, p
);
672 n
= FcPatternBaseFreeze (b
);
674 if (FcDebug() & FC_DBG_MEMORY
)
676 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
677 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
681 free(FcPatternEltU(b
->elts
));
682 b
->elts
= FcPatternEltPtrCreateDynamic(0);
683 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
686 assert (FcPatternEqual (n
, p
));
692 FcPatternPosition (const FcPattern
*p
, const char *object
)
694 int low
, high
, mid
, c
;
697 obj
= FcObjectToPtr(object
);
704 mid
= (low
+ high
) >> 1;
705 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
719 FcPatternFindElt (const FcPattern
*p
, const char *object
)
721 int i
= FcPatternPosition (p
, object
);
724 return FcPatternEltU(p
->elts
)+i
;
728 FcPatternInsertElt (FcPattern
*p
, const char *object
)
733 i
= FcPatternPosition (p
, object
);
738 /* reallocate array */
739 if (p
->num
+ 1 >= p
->size
)
741 int s
= p
->size
+ 16;
742 if (FcPatternEltU(p
->elts
))
744 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
745 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
746 if (!e
) /* maybe it was mmapped */
748 e
= malloc(s
* sizeof (FcPatternElt
));
750 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
754 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
757 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
759 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
760 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
763 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
764 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
765 FcValueListPtrCreateDynamic(0);
771 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
772 FcPatternEltU(p
->elts
) + i
,
773 sizeof (FcPatternElt
) *
779 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
780 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
783 return FcPatternEltU(p
->elts
)+i
;
787 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
794 if (pa
->num
!= pb
->num
)
796 for (i
= 0; i
< pa
->num
; i
++)
798 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
799 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
801 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
802 (FcPatternEltU(pb
->elts
)+i
)->values
))
809 FcPatternHash (const FcPattern
*p
)
814 for (i
= 0; i
< p
->num
; i
++)
816 h
= (((h
<< 1) | (h
>> 31)) ^
817 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
818 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
824 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
826 FcPatternElt
*ea
, *eb
;
829 for (i
= 0; i
< os
->nobject
; i
++)
831 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
832 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
837 if (!FcValueListEqual (ea
->values
, eb
->values
))
850 FcPatternAddWithBinding (FcPattern
*p
,
853 FcValueBinding binding
,
857 FcValueListPtr
new, *prev
;
859 FcObjectPtr objectPtr
;
861 if (p
->ref
== FC_REF_CONSTANT
)
864 newp
= malloc (sizeof (FcValueList
));
868 memset(newp
, 0, sizeof (FcValueList
));
869 new = FcValueListPtrCreateDynamic(newp
);
870 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
872 value
= FcValueSave (value
);
873 if (value
.type
== FcTypeVoid
)
876 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
877 * speedup: only allow strings to be added under the FC_FAMILY,
878 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
879 * and charsets under FC_CHARSET key.
880 * This is slightly semantically different from the old behaviour,
881 * but fonts shouldn't be getting non-strings here anyway.
882 * a better hack would use FcBaseObjectTypes to check all objects. */
883 objectPtr
= FcObjectToPtr(object
);
884 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
885 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
886 || objectPtr
== FcObjectToPtr(FC_STYLE
)
887 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
888 && value
.type
!= FcTypeString
)
890 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
891 && value
.type
!= FcTypeCharSet
)
894 FcValueListPtrU(new)->value
= value
;
895 FcValueListPtrU(new)->binding
= binding
;
896 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
898 e
= FcPatternInsertElt (p
, object
);
904 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
910 FcValueListPtrU(new)->next
= e
->values
;
917 switch (value
.type
) {
919 FcStrFree ((FcChar8
*) value
.u
.s
);
922 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
925 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
928 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
934 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
935 free (FcValueListPtrU(new));
941 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
943 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
947 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
949 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
953 FcPatternDel (FcPattern
*p
, const char *object
)
957 e
= FcPatternFindElt (p
, object
);
962 FcValueListDestroy (e
->values
);
964 /* shuffle existing ones down */
966 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
967 sizeof (FcPatternElt
));
969 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
970 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
975 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
978 FcValueListPtr
*prev
, l
;
980 e
= FcPatternFindElt (p
, object
);
983 for (prev
= &e
->values
;
984 FcValueListPtrU(l
= *prev
);
985 prev
= &FcValueListPtrU(l
)->next
)
989 *prev
= FcValueListPtrU(l
)->next
;
990 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
991 FcValueListDestroy (l
);
992 if (!FcValueListPtrU(e
->values
))
993 FcPatternDel (p
, object
);
1002 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1006 v
.type
= FcTypeInteger
;
1008 return FcPatternAdd (p
, object
, v
, FcTrue
);
1012 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1016 v
.type
= FcTypeDouble
;
1018 return FcPatternAdd (p
, object
, v
, FcTrue
);
1023 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1027 v
.type
= FcTypeString
;
1028 v
.u
.s
= FcStrStaticName(s
);
1029 return FcPatternAdd (p
, object
, v
, FcTrue
);
1033 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1037 v
.type
= FcTypeMatrix
;
1039 return FcPatternAdd (p
, object
, v
, FcTrue
);
1044 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1048 v
.type
= FcTypeBool
;
1050 return FcPatternAdd (p
, object
, v
, FcTrue
);
1054 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1058 v
.type
= FcTypeCharSet
;
1059 v
.u
.c
= (FcCharSet
*)c
;
1060 return FcPatternAdd (p
, object
, v
, FcTrue
);
1064 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1068 v
.type
= FcTypeFTFace
;
1070 return FcPatternAdd (p
, object
, v
, FcTrue
);
1074 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1078 v
.type
= FcTypeLangSet
;
1079 v
.u
.l
= (FcLangSet
*)ls
;
1080 return FcPatternAdd (p
, object
, v
, FcTrue
);
1084 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1089 e
= FcPatternFindElt (p
, object
);
1091 return FcResultNoMatch
;
1092 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1096 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1097 return FcResultMatch
;
1101 return FcResultNoId
;
1105 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1110 r
= FcPatternGet (p
, object
, id
, &v
);
1111 if (r
!= FcResultMatch
)
1121 return FcResultTypeMismatch
;
1123 return FcResultMatch
;
1127 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1132 r
= FcPatternGet (p
, object
, id
, &v
);
1133 if (r
!= FcResultMatch
)
1140 *d
= (double) v
.u
.i
;
1143 return FcResultTypeMismatch
;
1145 return FcResultMatch
;
1149 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1154 r
= FcPatternGet (p
, object
, id
, &v
);
1155 if (r
!= FcResultMatch
)
1157 if (v
.type
!= FcTypeString
)
1158 return FcResultTypeMismatch
;
1160 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1162 const char *fn
, *fpath
;
1166 fn
= FcPatternFindFullFname(p
);
1169 *s
= (FcChar8
*) fn
;
1170 return FcResultMatch
;
1175 *s
= (FcChar8
*) v
.u
.s
;
1176 return FcResultMatch
;
1179 fpath
= FcCacheFindBankDir (p
->bank
);
1180 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1181 fname
= malloc (size
);
1183 return FcResultOutOfMemory
;
1185 FcMemAlloc (FC_MEM_STRING
, size
);
1186 strcpy ((char *)fname
, (char *)fpath
);
1187 strcat ((char *)fname
, "/");
1188 strcat ((char *)fname
, (char *)v
.u
.s
);
1190 FcPatternAddFullFname (p
, (const char *)fname
);
1191 *s
= (FcChar8
*)fname
;
1192 return FcResultMatch
;
1195 *s
= (FcChar8
*) v
.u
.s
;
1196 return FcResultMatch
;
1200 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1205 r
= FcPatternGet (p
, object
, id
, &v
);
1206 if (r
!= FcResultMatch
)
1208 if (v
.type
!= FcTypeMatrix
)
1209 return FcResultTypeMismatch
;
1210 *m
= (FcMatrix
*)v
.u
.m
;
1211 return FcResultMatch
;
1216 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1221 r
= FcPatternGet (p
, object
, id
, &v
);
1222 if (r
!= FcResultMatch
)
1224 if (v
.type
!= FcTypeBool
)
1225 return FcResultTypeMismatch
;
1227 return FcResultMatch
;
1231 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1236 r
= FcPatternGet (p
, object
, id
, &v
);
1237 if (r
!= FcResultMatch
)
1239 if (v
.type
!= FcTypeCharSet
)
1240 return FcResultTypeMismatch
;
1241 *c
= (FcCharSet
*)v
.u
.c
;
1242 return FcResultMatch
;
1246 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1251 r
= FcPatternGet (p
, object
, id
, &v
);
1252 if (r
!= FcResultMatch
)
1254 if (v
.type
!= FcTypeFTFace
)
1255 return FcResultTypeMismatch
;
1256 *f
= (FT_Face
) v
.u
.f
;
1257 return FcResultMatch
;
1261 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1266 r
= FcPatternGet (p
, object
, id
, &v
);
1267 if (r
!= FcResultMatch
)
1269 if (v
.type
!= FcTypeLangSet
)
1270 return FcResultTypeMismatch
;
1271 *ls
= (FcLangSet
*)v
.u
.l
;
1272 return FcResultMatch
;
1276 FcPatternDuplicate (const FcPattern
*orig
)
1283 new = FcPatternCreate ();
1287 e
= FcPatternEltU(orig
->elts
);
1289 for (i
= 0; i
< orig
->num
; i
++)
1291 for (l
= (e
+ i
)->values
;
1293 l
= FcValueListPtrU(l
)->next
)
1294 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1295 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1299 FcPatternTransferFullFname (new, orig
);
1304 FcPatternDestroy (new);
1310 FcPatternReference (FcPattern
*p
)
1312 if (p
->ref
!= FC_REF_CONSTANT
)
1317 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1321 FcPatternVapBuild (ret
, orig
, va
);
1326 FcPatternBuild (FcPattern
*orig
, ...)
1330 va_start (va
, orig
);
1331 FcPatternVapBuild (orig
, orig
, va
);
1337 * Add all of the elements in 's' to 'p'
1340 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1346 for (i
= 0; i
< s
->num
; i
++)
1348 e
= FcPatternEltU(s
->elts
)+i
;
1349 for (v
= e
->values
; FcValueListPtrU(v
);
1350 v
= FcValueListPtrU(v
)->next
)
1352 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1353 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1354 FcValueListPtrU(v
)->binding
, FcTrue
))
1361 #define OBJECT_HASH_SIZE 31
1362 static struct objectBucket
{
1363 struct objectBucket
*next
;
1365 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1368 FcStrStaticName (const FcChar8
*name
)
1370 FcChar32 hash
= FcStringHash (name
);
1371 struct objectBucket
**p
;
1372 struct objectBucket
*b
;
1375 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1376 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1377 return (FcChar8
*) (b
+ 1);
1378 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1379 b
= malloc (size
+ sizeof (int));
1380 /* workaround glibc bug which reads strlen in groups of 4 */
1381 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1386 strcpy ((char *) (b
+ 1), (char *)name
);
1388 return (FcChar8
*) (b
+ 1);
1392 FcStrStaticNameFini (void)
1395 struct objectBucket
*b
, *next
;
1398 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1400 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1403 name
= (char *) (b
+ 1);
1404 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1405 FcMemFree (FC_MEM_STATICSTR
, size
);
1408 FcObjectBuckets
[i
] = 0;
1413 FcPatternFini (void)
1415 FcPatternBaseThawAll ();
1416 FcValueListThawAll ();
1417 FcStrStaticNameFini ();
1418 FcObjectStaticNameFini ();
1422 FcPatternEltU (FcPatternEltPtr pei
)
1424 if (pei
.bank
== FC_BANK_DYNAMIC
)
1427 return &fcpatternelts
[FcCacheBankToIndex(pei
.bank
)][pei
.u
.stat
];
1430 static FcPatternEltPtr
1431 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1433 FcPatternEltPtr
new;
1434 new.bank
= FC_BANK_DYNAMIC
;
1439 static FcPatternEltPtr
1440 FcPatternEltPtrCreateStatic (int bank
, int i
)
1442 FcPatternEltPtr
new;
1449 FcStrNewBank (void);
1451 FcStrNeededBytes (const FcChar8
* s
);
1453 FcStrNeededBytesAlign (void);
1455 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1456 static const FcChar8
*
1457 FcStrSerialize (int bank
, const FcChar8
* s
);
1459 FcStrUnserialize (FcCache metadata
, void *block_ptr
);
1462 FcValueListNewBank (void);
1464 FcValueListNeededBytes (FcValueList
* vl
);
1466 FcValueListNeededBytesAlign (void);
1468 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1469 static FcValueListPtr
1470 FcValueListSerialize(int bank
, FcValueList
*pi
);
1472 FcValueListUnserialize (FcCache metadata
, void *block_ptr
);
1476 FcPatternNewBank (void)
1478 fcpattern_count
= 0;
1479 fcpatternelt_count
= 0;
1482 FcValueListNewBank();
1486 FcPatternNeededBytes (FcPattern
* p
)
1491 fcpatternelt_count
+= p
->num
;
1493 for (i
= 0; i
< p
->num
; i
++)
1495 c
= FcValueListNeededBytes (FcValueListPtrU
1496 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1502 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1506 FcPatternNeededBytesAlign (void)
1508 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1509 FcValueListNeededBytesAlign ();
1513 FcPatternEnsureBank (int bi
)
1519 if (!fcpatterns
|| fcpattern_bank_count
<= bi
)
1521 int new_count
= bi
+ 4;
1522 pp
= realloc (fcpatterns
, sizeof (FcPattern
*) * new_count
);
1526 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1529 ep
= realloc (fcpatternelts
, sizeof (FcPatternElt
*) * new_count
);
1533 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1536 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1539 fcpatternelts
[i
] = 0;
1542 fcpattern_bank_count
= new_count
;
1545 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1550 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1552 int bi
= FcCacheBankToIndex(metadata
->bank
);
1554 if (!FcPatternEnsureBank(bi
))
1558 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1559 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1560 block_ptr
= (void *)((char *)block_ptr
+
1561 (sizeof (FcPattern
) * fcpattern_count
));
1563 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1564 fcpatternelt_ptr
= 0;
1565 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1566 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1567 block_ptr
= (void *)((char *)block_ptr
+
1568 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1570 metadata
->pattern_count
= fcpattern_count
;
1571 metadata
->patternelt_count
= fcpatternelt_count
;
1573 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1574 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1579 FcPatternSerialize (int bank
, FcPattern
*old
)
1582 FcPatternElt
*e
, *nep
;
1584 FcValueListPtr v
, nv_head
, nvp
;
1585 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1587 p
= &fcpatterns
[bi
][fcpattern_ptr
++];
1589 elts
= fcpatternelt_ptr
;
1590 nep
= &fcpatternelts
[bi
][elts
];
1594 fcpatternelt_ptr
+= old
->num
;
1596 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1599 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1600 if (!FcValueListPtrU(nv_head
))
1602 nv
= FcValueListPtrU(nvp
);
1606 v
= FcValueListPtrU(v
)->next
,
1607 nv
= FcValueListPtrU(nv
->next
))
1610 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1612 nvp
= FcValueListSerialize
1613 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1618 nep
[i
].values
= nv_head
;
1619 nep
[i
].object
= e
->object
;
1622 p
->elts
= old
->elts
;
1623 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1626 p
->ref
= FC_REF_CONSTANT
;
1631 FcPatternUnserialize (FcCache metadata
, void *block_ptr
)
1633 int bi
= FcCacheBankToIndex(metadata
.bank
);
1634 if (!FcPatternEnsureBank(bi
))
1637 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
.pattern_count
);
1638 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1639 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1640 block_ptr
= (void *)((char *)block_ptr
+
1641 (sizeof (FcPattern
) * metadata
.pattern_count
));
1643 FcMemAlloc (FC_MEM_PATELT
,
1644 sizeof (FcPatternElt
) * metadata
.patternelt_count
);
1645 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1646 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1647 block_ptr
= (void *)((char *)block_ptr
+
1648 (sizeof (FcPatternElt
) * metadata
.patternelt_count
));
1650 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1651 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1657 FcValueListNewBank (void)
1659 fcvaluelist_count
= 0;
1666 FcValueListNeededBytes (FcValueList
*p
)
1673 vl
= FcValueListPtrU(vl
->next
))
1675 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1680 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1683 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1686 cum
+= FcStrNeededBytes(v
.u
.s
);
1690 fcvaluelist_count
++;
1691 cum
+= sizeof (FcValueList
);
1698 FcValueListNeededBytesAlign (void)
1700 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1701 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1705 FcValueListEnsureBank (int bi
)
1709 if (!fcvaluelists
|| fcvaluelist_bank_count
<= bi
)
1711 int new_count
= bi
+ 2, i
;
1713 pvl
= realloc (fcvaluelists
, sizeof (FcValueList
*) * new_count
);
1717 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1720 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1721 fcvaluelists
[i
] = 0;
1723 fcvaluelist_bank_count
= new_count
;
1729 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1731 int bi
= FcCacheBankToIndex(metadata
->bank
);
1733 if (!FcValueListEnsureBank(bi
))
1736 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1737 fcvaluelist_ptr
= 0;
1738 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1739 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1740 block_ptr
= (void *)((char *)block_ptr
+
1741 (sizeof (FcValueList
) * fcvaluelist_count
));
1742 metadata
->valuelist_count
= fcvaluelist_count
;
1744 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1745 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1750 static FcValueListPtr
1751 FcValueListSerialize(int bank
, FcValueList
*pi
)
1755 int bi
= FcCacheBankToIndex(bank
);
1759 new.bank
= FC_BANK_DYNAMIC
;
1764 fcvaluelists
[bi
][fcvaluelist_ptr
] = *pi
;
1766 new.u
.stat
= fcvaluelist_ptr
++;
1767 fcvaluelists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1768 v
= &fcvaluelists
[bi
][new.u
.stat
].value
;
1774 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1776 return FcValueListPtrCreateDynamic(pi
);
1777 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1778 v
->type
|= FC_STORAGE_STATIC
;
1786 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1788 return FcValueListPtrCreateDynamic(pi
);
1789 v
->u
.c_off
= (char *)c
- (char *)v
;
1790 v
->type
|= FC_STORAGE_STATIC
;
1796 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1798 return FcValueListPtrCreateDynamic(pi
);
1799 v
->u
.l_off
= (char *)l
- (char *)v
;
1800 v
->type
|= FC_STORAGE_STATIC
;
1810 FcValueListUnserialize (FcCache metadata
, void *block_ptr
)
1812 int bi
= FcCacheBankToIndex(metadata
.bank
);
1814 if (!FcValueListEnsureBank(bi
))
1817 FcMemAlloc (FC_MEM_VALLIST
,
1818 sizeof (FcValueList
) * metadata
.valuelist_count
);
1819 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1820 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1821 block_ptr
= (void *)((char *)block_ptr
+
1822 (sizeof (FcValueList
) * metadata
.valuelist_count
));
1824 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1825 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1831 FcValueListPtrU (FcValueListPtr pi
)
1833 if (pi
.bank
== FC_BANK_DYNAMIC
)
1836 return &fcvaluelists
[FcCacheBankToIndex(pi
.bank
)][pi
.u
.stat
];
1840 FcValueListPtrCreateDynamic(FcValueList
* p
)
1844 r
.bank
= FC_BANK_DYNAMIC
;
1849 static FcChar8
** static_strs
;
1850 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1852 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1858 struct objectBucket
*b
, *next
;
1861 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1863 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1866 name
= (char *) (b
+ 1);
1867 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1868 FcMemFree (FC_MEM_STATICSTR
, size
);
1871 FcStrBuckets
[i
] = 0;
1878 FcStrNeededBytes (const FcChar8
* s
)
1880 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1881 struct objectBucket
**p
;
1882 struct objectBucket
*b
;
1885 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1886 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1888 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1890 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1895 strcpy ((char *) (b
+ 1), (char *)s
);
1897 /* Yes, the following line is convoluted. However, it is
1898 * incorrect to replace the with a memset, because the C
1899 * specification doesn't guarantee that the null pointer is
1900 * the same as the zero bit pattern. */
1901 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1904 fcstr_count
+= strlen((char *)s
) + 1;
1905 return strlen((char *)s
) + 1;
1909 FcStrNeededBytesAlign (void)
1911 return __alignof__ (char);
1915 FcStrEnsureBank (int bi
)
1919 if (!static_strs
|| static_str_bank_count
<= bi
)
1921 int new_count
= bi
+ 4, i
;
1922 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1926 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1929 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1931 static_str_bank_count
= new_count
;
1937 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1939 int bi
= FcCacheBankToIndex(metadata
->bank
);
1940 if (!FcStrEnsureBank(bi
))
1943 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1944 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1945 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1946 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1947 metadata
->str_count
= fcstr_count
;
1953 static const FcChar8
*
1954 FcStrSerialize (int bank
, const FcChar8
* s
)
1956 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1957 struct objectBucket
**p
;
1958 struct objectBucket
*b
;
1959 int bi
= FcCacheBankToIndex(bank
);
1961 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1962 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1964 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1967 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1968 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1969 fcstr_ptr
+= strlen((char *)s
) + 1;
1970 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1978 FcStrUnserialize (FcCache metadata
, void *block_ptr
)
1980 int bi
= FcCacheBankToIndex(metadata
.bank
);
1981 if (!FcStrEnsureBank(bi
))
1984 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
.str_count
);
1985 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1986 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1987 block_ptr
= (void *)((char *)block_ptr
+
1988 (sizeof (char) * metadata
.str_count
));
1993 /* we don't store these in the FcPattern itself because
1994 * we don't want to serialize the directory names */
1996 /* I suppose this should be cleaned, too... */
1997 typedef struct _FcPatternDirMapping
{
2000 } FcPatternDirMapping
;
2002 #define PATTERNDIR_HASH_SIZE 31
2003 static struct patternDirBucket
{
2004 struct patternDirBucket
*next
;
2005 FcPatternDirMapping m
;
2006 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
2009 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
2011 struct patternDirBucket
*pb
;
2013 /* N.B. FcPatternHash fails, since it's contents-based, not
2014 * address-based, and we're in the process of mutating the FcPattern. */
2015 for (pb
= &FcPatternDirBuckets
2016 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2017 pb
->m
.p
!= p
&& pb
->next
;
2023 pb
->m
.fname
= fname
;
2027 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2030 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2034 pb
->next
->m
.fname
= fname
;
2038 FcPatternFindFullFname (const FcPattern
*p
)
2040 struct patternDirBucket
*pb
;
2042 for (pb
= &FcPatternDirBuckets
2043 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2052 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2055 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2056 FcPatternAddFullFname (new,
2058 ((FcChar8
*)FcPatternFindFullFname(orig
)));