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 FcPatternElt
** _fcPatternElts
= 0;
33 static int fcpatternelt_ptr
, fcpatternelt_count
;
34 FcValueList
** _fcValueLists
= 0;
35 static int fcvaluelist_bank_count
= 0, fcvaluelist_ptr
, fcvaluelist_count
;
37 static FcPatternEltPtr
38 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
);
40 FcStrHashed (const FcChar8
*name
);
43 FcPatternFindFullFname (const FcPattern
*p
);
45 /* If you are trying to duplicate an FcPattern which will be used for
46 * rendering, be aware that (internally) you also have to use
47 * FcPatternTransferFullFname to transfer the associated filename. If
48 * you are copying the font (externally) using FcPatternGetString,
49 * then everything's fine; this caveat only applies if you're copying
50 * the bits individually. */
53 FcPatternCreate (void)
57 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
60 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
63 p
->elts
= FcPatternEltPtrCreateDynamic(0);
64 p
->bank
= FC_BANK_DYNAMIC
;
70 FcValueDestroy (FcValue v
)
74 if (!FcStrHashed (v
.u
.s
))
75 FcStrFree ((FcChar8
*) v
.u
.s
);
78 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
81 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
84 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
92 FcValueCanonicalize (const FcValue
*v
)
94 if (v
->type
& FC_STORAGE_STATIC
)
98 switch (v
->type
& ~FC_STORAGE_STATIC
)
101 new.u
.s
= fc_value_string(v
);
102 new.type
= FcTypeString
;
105 new.u
.c
= fc_value_charset(v
);
106 new.type
= FcTypeCharSet
;
109 new.u
.l
= fc_value_langset(v
);
110 new.type
= FcTypeLangSet
;
119 FcValueSave (FcValue v
)
123 v
.u
.s
= FcStrCopy (v
.u
.s
);
128 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
133 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
138 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
149 FcValueListDestroy (FcValueListPtr l
)
152 for (; FcValueListPtrU(l
); l
= next
)
154 switch (FcValueListPtrU(l
)->value
.type
) {
156 if (!FcStrHashed ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
))
157 FcStrFree ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
);
160 FcMatrixFree ((FcMatrix
*)FcValueListPtrU(l
)->value
.u
.m
);
164 ((FcCharSet
*) (FcValueListPtrU(l
)->value
.u
.c
));
168 ((FcLangSet
*) (FcValueListPtrU(l
)->value
.u
.l
));
173 next
= FcValueListPtrU(l
)->next
;
174 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
175 if (l
.bank
== FC_BANK_DYNAMIC
)
181 FcValueEqual (FcValue va
, FcValue vb
)
183 if (va
.type
!= vb
.type
)
185 if (va
.type
== FcTypeInteger
)
187 va
.type
= FcTypeDouble
;
190 if (vb
.type
== FcTypeInteger
)
192 vb
.type
= FcTypeDouble
;
195 if (va
.type
!= vb
.type
)
202 return va
.u
.i
== vb
.u
.i
;
204 return va
.u
.d
== vb
.u
.d
;
206 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
208 return va
.u
.b
== vb
.u
.b
;
210 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
212 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
214 return va
.u
.f
== vb
.u
.f
;
216 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
222 FcDoubleHash (double d
)
232 FcStringHash (const FcChar8
*s
)
239 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
244 FcValueHash (const FcValue
*v
)
246 switch (fc_storage_type(v
)) {
250 return (FcChar32
) v
->u
.i
;
252 return FcDoubleHash (v
->u
.d
);
254 return FcStringHash (fc_value_string(v
));
256 return (FcChar32
) v
->u
.b
;
258 return (FcDoubleHash (v
->u
.m
->xx
) ^
259 FcDoubleHash (v
->u
.m
->xy
) ^
260 FcDoubleHash (v
->u
.m
->yx
) ^
261 FcDoubleHash (v
->u
.m
->yy
));
263 return (FcChar32
) fc_value_charset(v
)->num
;
265 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
->u
.f
)->family_name
) ^
266 FcStringHash ((const FcChar8
*) ((FT_Face
) v
->u
.f
)->style_name
);
268 return FcLangSetHash (fc_value_langset(v
));
274 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
276 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
279 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
281 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
282 FcValueListPtrU(lb
)->value
))
284 la
= FcValueListPtrU(la
)->next
;
285 lb
= FcValueListPtrU(lb
)->next
;
287 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
293 FcValueListHash (FcValueListPtr l
)
298 for (l_ptrU
= FcValueListPtrU(l
); l_ptrU
;
299 l_ptrU
= FcValueListPtrU(l_ptrU
->next
))
301 hash
= ((hash
<< 1) | (hash
>> 31)) ^ FcValueHash (&l_ptrU
->value
);
307 FcPatternDestroy (FcPattern
*p
)
311 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
314 if (FcPatternFindFullFname (p
))
316 FcStrFree ((FcChar8
*)FcPatternFindFullFname (p
));
317 FcPatternAddFullFname (p
, 0);
320 for (i
= 0; i
< p
->num
; i
++)
321 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
324 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
326 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
327 free (FcPatternEltU(p
->elts
));
328 p
->elts
= FcPatternEltPtrCreateDynamic(0);
331 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
335 #define FC_VALUE_LIST_HASH_SIZE 257
336 #define FC_PATTERN_HASH_SIZE 67
338 typedef struct _FcValueListEnt FcValueListEnt
;
340 struct _FcValueListEnt
{
341 FcValueListEnt
*next
;
346 typedef union _FcValueListAlign
{
351 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
352 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
353 static char FcValueListFrozenName
[][8] = {
366 FcValueListReport (void);
369 FcValueListReport (void)
373 printf ("Fc Frozen Values:\n");
374 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
375 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
376 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
377 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
380 static FcValueListEnt
*
381 FcValueListEntCreate (FcValueListPtr h
)
383 FcValueListAlign
*ea
;
391 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
393 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
394 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
395 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
396 /* this leaks for some reason */
397 ea
= malloc (sizeof (FcValueListAlign
));
400 new = malloc (n
* sizeof (FcValueList
));
403 memset(new, 0, n
* sizeof (FcValueList
));
404 FcMemAlloc (FC_MEM_VALLIST
, size
);
406 e
->list
= FcValueListPtrCreateDynamic(new);
407 for (l
= h
; FcValueListPtrU(l
);
408 l
= FcValueListPtrU(l
)->next
, new++)
410 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
412 new->value
.type
= FcTypeString
;
413 new->value
.u
.s
= FcStrStaticName
414 (fc_value_string(&FcValueListPtrU(l
)->value
));
418 new->value
= FcValueSave (FcValueCanonicalize
419 (&FcValueListPtrU(l
)->value
));
421 new->binding
= FcValueListPtrU(l
)->binding
;
422 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
424 new->next
= FcValueListPtrCreateDynamic(new + 1);
428 new->next
= FcValueListPtrCreateDynamic(0);
435 FcValueListEntDestroy (FcValueListEnt
*e
)
439 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
441 /* XXX: We should perform these two operations with "size" as
442 computed in FcValueListEntCreate, but we don't have access to
443 that value here. Without this, the FcValueListFrozenBytes
444 values will be wrong as will the FcMemFree counts.
446 FcValueListFrozenBytes[e->list->value.type] -= size;
447 FcMemFree (FC_MEM_VALLIST, size);
450 for (l
= e
->list
; FcValueListPtrU(l
);
451 l
= FcValueListPtrU(l
)->next
)
453 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
454 FcValueDestroy (FcValueListPtrU(l
)->value
);
456 /* XXX: Are we being too chummy with the implementation here to
457 free(e) when it was actually the enclosing FcValueListAlign
458 that was allocated? */
462 static int FcValueListTotal
;
463 static int FcValueListUsed
;
465 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
467 static FcValueListPtr
468 FcValueListFreeze (FcValueListPtr l
)
470 FcChar32 hash
= FcValueListHash (l
);
471 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
475 for (ent
= *bucket
; ent
; ent
= ent
->next
)
477 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
481 ent
= FcValueListEntCreate (l
);
483 return FcValueListPtrCreateDynamic(0);
493 FcValueListThawAll (void)
496 FcValueListEnt
*ent
, *next
;
498 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
500 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
503 FcValueListEntDestroy (ent
);
505 FcValueListHashTable
[i
] = 0;
508 FcValueListTotal
= 0;
513 FcPatternBaseHash (FcPattern
*b
)
515 FcChar32 hash
= b
->num
;
518 for (i
= 0; i
< b
->num
; i
++)
519 hash
= ((hash
<< 1) | (hash
>> 31)) ^
520 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
524 typedef struct _FcPatternEnt FcPatternEnt
;
526 struct _FcPatternEnt
{
532 static int FcPatternTotal
;
533 static int FcPatternUsed
;
535 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
538 FcPatternBaseFreeze (FcPattern
*b
)
542 FcChar32 hash
= FcPatternBaseHash (b
);
543 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
548 for (ent
= *bucket
; ent
; ent
= ent
->next
)
550 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
552 for (i
= 0; i
< b
->num
; i
++)
554 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
555 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
557 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
558 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
567 * Compute size of pattern + elts
569 ent
= malloc (sizeof (FcPatternEnt
));
573 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
576 ep
= FcPatternCreate();
580 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
583 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
585 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
589 ep
->ref
= FC_REF_CONSTANT
;
591 for (i
= 0; i
< b
->num
; i
++)
593 (FcPatternEltU(ep
->elts
)+i
)->values
=
594 (FcPatternEltU(b
->elts
)+i
)->values
;
595 (FcPatternEltU(ep
->elts
)+i
)->object
=
596 (FcPatternEltU(b
->elts
)+i
)->object
;
599 if (FcPatternFindElt (b
, FC_FILE
))
600 FcPatternTransferFullFname (ep
, b
);
608 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
614 FcPatternBaseThawAll (void)
617 FcPatternEnt
*ent
, *next
;
619 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
621 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
626 FcPatternHashTable
[i
] = 0;
634 FcPatternFreeze (FcPattern
*p
)
636 FcPattern
*b
, *n
= 0;
640 if (p
->ref
== FC_REF_CONSTANT
)
643 b
= FcPatternCreate();
651 e
= malloc(b
->num
* sizeof (FcPatternElt
));
654 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
655 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
658 * Freeze object lists
660 for (i
= 0; i
< p
->num
; i
++)
662 (FcPatternEltU(b
->elts
)+i
)->object
=
663 (FcPatternEltU(p
->elts
)+i
)->object
;
664 (FcPatternEltU(b
->elts
)+i
)->values
=
665 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
666 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
670 if (FcPatternFindElt (p
, FC_FILE
))
671 FcPatternTransferFullFname (b
, p
);
676 n
= FcPatternBaseFreeze (b
);
678 if (FcDebug() & FC_DBG_MEMORY
)
680 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
681 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
685 free(FcPatternEltU(b
->elts
));
686 b
->elts
= FcPatternEltPtrCreateDynamic(0);
687 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
690 assert (FcPatternEqual (n
, p
));
696 FcPatternPosition (const FcPattern
*p
, const char *object
)
698 int low
, high
, mid
, c
;
701 obj
= FcObjectToPtr(object
);
708 mid
= (low
+ high
) >> 1;
709 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
723 FcPatternFindElt (const FcPattern
*p
, const char *object
)
725 int i
= FcPatternPosition (p
, object
);
728 return FcPatternEltU(p
->elts
)+i
;
732 FcPatternInsertElt (FcPattern
*p
, const char *object
)
737 i
= FcPatternPosition (p
, object
);
742 /* reallocate array */
743 if (p
->num
+ 1 >= p
->size
)
745 int s
= p
->size
+ 16;
746 if (FcPatternEltU(p
->elts
))
748 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
749 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
750 if (!e
) /* maybe it was mmapped */
752 e
= malloc(s
* sizeof (FcPatternElt
));
754 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
758 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
761 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
763 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
764 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
767 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
768 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
769 FcValueListPtrCreateDynamic(0);
775 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
776 FcPatternEltU(p
->elts
) + i
,
777 sizeof (FcPatternElt
) *
783 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
784 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
787 return FcPatternEltU(p
->elts
)+i
;
791 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
798 if (pa
->num
!= pb
->num
)
800 for (i
= 0; i
< pa
->num
; i
++)
802 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
803 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
805 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
806 (FcPatternEltU(pb
->elts
)+i
)->values
))
813 FcPatternHash (const FcPattern
*p
)
818 for (i
= 0; i
< p
->num
; i
++)
820 h
= (((h
<< 1) | (h
>> 31)) ^
821 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
822 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
828 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
830 FcPatternElt
*ea
, *eb
;
833 for (i
= 0; i
< os
->nobject
; i
++)
835 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
836 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
841 if (!FcValueListEqual (ea
->values
, eb
->values
))
854 FcPatternAddWithBinding (FcPattern
*p
,
857 FcValueBinding binding
,
861 FcValueListPtr
new, *prev
;
863 FcObjectPtr objectPtr
;
865 if (p
->ref
== FC_REF_CONSTANT
)
868 newp
= malloc (sizeof (FcValueList
));
872 memset(newp
, 0, sizeof (FcValueList
));
873 new = FcValueListPtrCreateDynamic(newp
);
874 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
876 if (value
.type
== FcTypeString
)
878 value
.u
.s
= FcStrStaticName (value
.u
.s
);
880 value
.type
= FcTypeVoid
;
883 value
= FcValueSave (value
);
884 if (value
.type
== FcTypeVoid
)
887 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
888 * speedup: only allow strings to be added under the FC_FAMILY,
889 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
890 * and charsets under FC_CHARSET key.
891 * This is slightly semantically different from the old behaviour,
892 * but fonts shouldn't be getting non-strings here anyway.
893 * a better hack would use FcBaseObjectTypes to check all objects. */
894 objectPtr
= FcObjectToPtr(object
);
895 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
896 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
897 || objectPtr
== FcObjectToPtr(FC_STYLE
)
898 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
899 && value
.type
!= FcTypeString
)
901 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
902 && value
.type
!= FcTypeCharSet
)
905 FcValueListPtrU(new)->value
= value
;
906 FcValueListPtrU(new)->binding
= binding
;
907 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
909 e
= FcPatternInsertElt (p
, object
);
915 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
921 FcValueListPtrU(new)->next
= e
->values
;
928 switch (value
.type
) {
930 FcStrFree ((FcChar8
*) value
.u
.s
);
933 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
936 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
939 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
945 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
946 free (FcValueListPtrU(new));
952 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
954 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
958 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
960 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
964 FcPatternDel (FcPattern
*p
, const char *object
)
968 e
= FcPatternFindElt (p
, object
);
973 FcValueListDestroy (e
->values
);
975 /* shuffle existing ones down */
977 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
978 sizeof (FcPatternElt
));
980 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
981 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
986 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
989 FcValueListPtr
*prev
, l
;
991 e
= FcPatternFindElt (p
, object
);
994 for (prev
= &e
->values
;
995 FcValueListPtrU(l
= *prev
);
996 prev
= &FcValueListPtrU(l
)->next
)
1000 *prev
= FcValueListPtrU(l
)->next
;
1001 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
1002 FcValueListDestroy (l
);
1003 if (!FcValueListPtrU(e
->values
))
1004 FcPatternDel (p
, object
);
1013 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1017 v
.type
= FcTypeInteger
;
1019 return FcPatternAdd (p
, object
, v
, FcTrue
);
1023 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1027 v
.type
= FcTypeDouble
;
1029 return FcPatternAdd (p
, object
, v
, FcTrue
);
1034 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1040 v
.type
= FcTypeVoid
;
1042 return FcPatternAdd (p
, object
, v
, FcTrue
);
1045 v
.type
= FcTypeString
;
1046 v
.u
.s
= FcStrStaticName(s
);
1047 return FcPatternAdd (p
, object
, v
, FcTrue
);
1051 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1055 v
.type
= FcTypeMatrix
;
1057 return FcPatternAdd (p
, object
, v
, FcTrue
);
1062 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1066 v
.type
= FcTypeBool
;
1068 return FcPatternAdd (p
, object
, v
, FcTrue
);
1072 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1076 v
.type
= FcTypeCharSet
;
1077 v
.u
.c
= (FcCharSet
*)c
;
1078 return FcPatternAdd (p
, object
, v
, FcTrue
);
1082 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1086 v
.type
= FcTypeFTFace
;
1088 return FcPatternAdd (p
, object
, v
, FcTrue
);
1092 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1096 v
.type
= FcTypeLangSet
;
1097 v
.u
.l
= (FcLangSet
*)ls
;
1098 return FcPatternAdd (p
, object
, v
, FcTrue
);
1102 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1107 e
= FcPatternFindElt (p
, object
);
1109 return FcResultNoMatch
;
1110 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1114 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1115 return FcResultMatch
;
1119 return FcResultNoId
;
1123 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1128 r
= FcPatternGet (p
, object
, id
, &v
);
1129 if (r
!= FcResultMatch
)
1139 return FcResultTypeMismatch
;
1141 return FcResultMatch
;
1145 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1150 r
= FcPatternGet (p
, object
, id
, &v
);
1151 if (r
!= FcResultMatch
)
1158 *d
= (double) v
.u
.i
;
1161 return FcResultTypeMismatch
;
1163 return FcResultMatch
;
1167 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1172 r
= FcPatternGet (p
, object
, id
, &v
);
1173 if (r
!= FcResultMatch
)
1175 if (v
.type
!= FcTypeString
)
1176 return FcResultTypeMismatch
;
1178 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1180 const char *fn
, *fpath
;
1184 fn
= FcPatternFindFullFname(p
);
1187 *s
= (FcChar8
*) fn
;
1188 return FcResultMatch
;
1193 *s
= (FcChar8
*) v
.u
.s
;
1194 return FcResultMatch
;
1197 fpath
= FcCacheFindBankDir (p
->bank
);
1198 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1199 fname
= malloc (size
);
1201 return FcResultOutOfMemory
;
1203 FcMemAlloc (FC_MEM_STRING
, size
);
1204 strcpy ((char *)fname
, (char *)fpath
);
1205 strcat ((char *)fname
, "/");
1206 strcat ((char *)fname
, (char *)v
.u
.s
);
1208 FcPatternAddFullFname (p
, (const char *)fname
);
1209 *s
= (FcChar8
*)fname
;
1210 return FcResultMatch
;
1213 *s
= (FcChar8
*) v
.u
.s
;
1214 return FcResultMatch
;
1218 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1223 r
= FcPatternGet (p
, object
, id
, &v
);
1224 if (r
!= FcResultMatch
)
1226 if (v
.type
!= FcTypeMatrix
)
1227 return FcResultTypeMismatch
;
1228 *m
= (FcMatrix
*)v
.u
.m
;
1229 return FcResultMatch
;
1234 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1239 r
= FcPatternGet (p
, object
, id
, &v
);
1240 if (r
!= FcResultMatch
)
1242 if (v
.type
!= FcTypeBool
)
1243 return FcResultTypeMismatch
;
1245 return FcResultMatch
;
1249 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1254 r
= FcPatternGet (p
, object
, id
, &v
);
1255 if (r
!= FcResultMatch
)
1257 if (v
.type
!= FcTypeCharSet
)
1258 return FcResultTypeMismatch
;
1259 *c
= (FcCharSet
*)v
.u
.c
;
1260 return FcResultMatch
;
1264 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1269 r
= FcPatternGet (p
, object
, id
, &v
);
1270 if (r
!= FcResultMatch
)
1272 if (v
.type
!= FcTypeFTFace
)
1273 return FcResultTypeMismatch
;
1274 *f
= (FT_Face
) v
.u
.f
;
1275 return FcResultMatch
;
1279 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1284 r
= FcPatternGet (p
, object
, id
, &v
);
1285 if (r
!= FcResultMatch
)
1287 if (v
.type
!= FcTypeLangSet
)
1288 return FcResultTypeMismatch
;
1289 *ls
= (FcLangSet
*)v
.u
.l
;
1290 return FcResultMatch
;
1294 FcPatternDuplicate (const FcPattern
*orig
)
1301 new = FcPatternCreate ();
1305 e
= FcPatternEltU(orig
->elts
);
1307 for (i
= 0; i
< orig
->num
; i
++)
1309 for (l
= (e
+ i
)->values
;
1311 l
= FcValueListPtrU(l
)->next
)
1312 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1313 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1317 FcPatternTransferFullFname (new, orig
);
1322 FcPatternDestroy (new);
1328 FcPatternReference (FcPattern
*p
)
1330 if (p
->ref
!= FC_REF_CONSTANT
)
1335 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1339 FcPatternVapBuild (ret
, orig
, va
);
1344 FcPatternBuild (FcPattern
*orig
, ...)
1348 va_start (va
, orig
);
1349 FcPatternVapBuild (orig
, orig
, va
);
1355 * Add all of the elements in 's' to 'p'
1358 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1364 for (i
= 0; i
< s
->num
; i
++)
1366 e
= FcPatternEltU(s
->elts
)+i
;
1367 for (v
= e
->values
; FcValueListPtrU(v
);
1368 v
= FcValueListPtrU(v
)->next
)
1370 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1371 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1372 FcValueListPtrU(v
)->binding
, FcTrue
))
1379 #define OBJECT_HASH_SIZE 31
1380 static struct objectBucket
{
1381 struct objectBucket
*next
;
1383 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1386 FcStrHashed (const FcChar8
*name
)
1388 FcChar32 hash
= FcStringHash (name
);
1389 struct objectBucket
**p
;
1390 struct objectBucket
*b
;
1392 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1393 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1399 FcStrStaticName (const FcChar8
*name
)
1401 FcChar32 hash
= FcStringHash (name
);
1402 struct objectBucket
**p
;
1403 struct objectBucket
*b
;
1406 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1407 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1408 return (FcChar8
*) (b
+ 1);
1409 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1410 b
= malloc (size
+ sizeof (int));
1411 /* workaround glibc bug which reads strlen in groups of 4 */
1412 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1417 strcpy ((char *) (b
+ 1), (char *)name
);
1419 return (FcChar8
*) (b
+ 1);
1423 FcStrStaticNameFini (void)
1426 struct objectBucket
*b
, *next
;
1429 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1431 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1434 name
= (char *) (b
+ 1);
1435 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1436 FcMemFree (FC_MEM_STATICSTR
, size
);
1439 FcObjectBuckets
[i
] = 0;
1444 FcPatternFini (void)
1446 FcPatternBaseThawAll ();
1447 FcValueListThawAll ();
1448 FcStrStaticNameFini ();
1449 FcObjectStaticNameFini ();
1452 static FcPatternEltPtr
1453 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1455 FcPatternEltPtr
new;
1456 new.bank
= FC_BANK_DYNAMIC
;
1461 static FcPatternEltPtr
1462 FcPatternEltPtrCreateStatic (int bank
, int i
)
1464 FcPatternEltPtr
new;
1471 FcStrNewBank (void);
1473 FcStrNeededBytes (const FcChar8
* s
);
1475 FcStrNeededBytesAlign (void);
1477 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1478 static const FcChar8
*
1479 FcStrSerialize (int bank
, const FcChar8
* s
);
1481 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1484 FcValueListNewBank (void);
1486 FcValueListNeededBytes (FcValueList
* vl
);
1488 FcValueListNeededBytesAlign (void);
1490 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1491 static FcValueListPtr
1492 FcValueListSerialize(int bank
, FcValueList
*pi
);
1494 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1498 FcPatternNewBank (void)
1500 fcpattern_count
= 0;
1501 fcpatternelt_count
= 0;
1504 FcValueListNewBank();
1508 FcPatternNeededBytes (FcPattern
* p
)
1513 fcpatternelt_count
+= p
->num
;
1515 for (i
= 0; i
< p
->num
; i
++)
1517 c
= FcValueListNeededBytes (FcValueListPtrU
1518 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1524 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1528 FcPatternNeededBytesAlign (void)
1530 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1531 FcValueListNeededBytesAlign ();
1535 FcPatternEnsureBank (int bi
)
1541 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1543 int new_count
= bi
+ 4;
1544 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1548 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1551 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1555 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1556 _fcPatternElts
= ep
;
1558 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1561 _fcPatternElts
[i
] = 0;
1564 fcpattern_bank_count
= new_count
;
1567 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1572 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1574 int bi
= FcCacheBankToIndex(metadata
->bank
);
1576 if (!FcPatternEnsureBank(bi
))
1580 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1581 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1582 block_ptr
= (void *)((char *)block_ptr
+
1583 (sizeof (FcPattern
) * fcpattern_count
));
1585 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1586 fcpatternelt_ptr
= 0;
1587 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1588 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1589 block_ptr
= (void *)((char *)block_ptr
+
1590 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1592 metadata
->pattern_count
= fcpattern_count
;
1593 metadata
->patternelt_count
= fcpatternelt_count
;
1595 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1596 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1601 FcPatternSerialize (int bank
, FcPattern
*old
)
1604 FcPatternElt
*e
, *nep
;
1606 FcValueListPtr v
, nv_head
, nvp
;
1607 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1609 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1611 elts
= fcpatternelt_ptr
;
1612 nep
= &_fcPatternElts
[bi
][elts
];
1616 fcpatternelt_ptr
+= old
->num
;
1618 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1621 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1622 if (!FcValueListPtrU(nv_head
))
1624 nv
= FcValueListPtrU(nvp
);
1628 v
= FcValueListPtrU(v
)->next
,
1629 nv
= FcValueListPtrU(nv
->next
))
1632 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1634 nvp
= FcValueListSerialize
1635 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1640 nep
[i
].values
= nv_head
;
1641 nep
[i
].object
= e
->object
;
1644 p
->elts
= old
->elts
;
1645 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1648 p
->ref
= FC_REF_CONSTANT
;
1653 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1655 int bi
= FcCacheBankToIndex(metadata
->bank
);
1656 if (!FcPatternEnsureBank(bi
))
1659 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1660 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1661 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1662 block_ptr
= (void *)((char *)block_ptr
+
1663 (sizeof (FcPattern
) * metadata
->pattern_count
));
1665 FcMemAlloc (FC_MEM_PATELT
,
1666 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1667 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1668 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1669 block_ptr
= (void *)((char *)block_ptr
+
1670 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1672 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1673 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1679 FcValueListNewBank (void)
1681 fcvaluelist_count
= 0;
1688 FcValueListNeededBytes (FcValueList
*p
)
1695 vl
= FcValueListPtrU(vl
->next
))
1697 /* unserialize just in case */
1698 FcValue v
= FcValueCanonicalize(&vl
->value
);
1703 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1706 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1709 cum
+= FcStrNeededBytes(v
.u
.s
);
1713 fcvaluelist_count
++;
1714 cum
+= sizeof (FcValueList
);
1721 FcValueListNeededBytesAlign (void)
1723 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1724 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1728 FcValueListEnsureBank (int bi
)
1732 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1734 int new_count
= bi
+ 2, i
;
1736 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1740 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1742 _fcValueLists
= pvl
;
1743 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1744 _fcValueLists
[i
] = 0;
1746 fcvaluelist_bank_count
= new_count
;
1752 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1754 int bi
= FcCacheBankToIndex(metadata
->bank
);
1756 if (!FcValueListEnsureBank(bi
))
1759 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1760 fcvaluelist_ptr
= 0;
1761 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1762 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1763 block_ptr
= (void *)((char *)block_ptr
+
1764 (sizeof (FcValueList
) * fcvaluelist_count
));
1765 metadata
->valuelist_count
= fcvaluelist_count
;
1767 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1768 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1773 static FcValueListPtr
1774 FcValueListSerialize(int bank
, FcValueList
*pi
)
1778 int bi
= FcCacheBankToIndex(bank
);
1782 new.bank
= FC_BANK_DYNAMIC
;
1787 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1789 new.u
.stat
= fcvaluelist_ptr
++;
1790 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1791 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1797 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1799 return FcValueListPtrCreateDynamic(pi
);
1800 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1801 v
->type
|= FC_STORAGE_STATIC
;
1809 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1811 return FcValueListPtrCreateDynamic(pi
);
1812 v
->u
.c_off
= (char *)c
- (char *)v
;
1813 v
->type
|= FC_STORAGE_STATIC
;
1819 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1821 return FcValueListPtrCreateDynamic(pi
);
1822 v
->u
.l_off
= (char *)l
- (char *)v
;
1823 v
->type
|= FC_STORAGE_STATIC
;
1833 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1835 int bi
= FcCacheBankToIndex(metadata
->bank
);
1837 if (!FcValueListEnsureBank(bi
))
1840 FcMemAlloc (FC_MEM_VALLIST
,
1841 sizeof (FcValueList
) * metadata
->valuelist_count
);
1842 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1843 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1844 block_ptr
= (void *)((char *)block_ptr
+
1845 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1847 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1848 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1854 FcValueListPtrCreateDynamic(FcValueList
* p
)
1858 r
.bank
= FC_BANK_DYNAMIC
;
1863 static FcChar8
** static_strs
;
1864 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1866 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1872 struct objectBucket
*b
, *next
;
1875 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1877 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1880 name
= (char *) (b
+ 1);
1881 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1882 FcMemFree (FC_MEM_STATICSTR
, size
);
1885 FcStrBuckets
[i
] = 0;
1892 FcStrNeededBytes (const FcChar8
* s
)
1894 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1895 struct objectBucket
**p
;
1896 struct objectBucket
*b
;
1898 FcChar8
*const null
= 0;
1900 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1901 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1903 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1905 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1910 strcpy ((char *) (b
+ 1), (char *)s
);
1912 /* Yes, the following line is convoluted. However, it is
1913 * incorrect to replace the with a memset, because the C
1914 * specification doesn't guarantee that the null pointer is
1915 * the same as the zero bit pattern. */
1916 /* Misaligned pointers are not guaranteed to work, either! */
1917 memcpy (((char *) (b
+ 1) + strlen((char *)s
) + 1), &null
, sizeof (null
));
1920 fcstr_count
+= strlen((char *)s
) + 1;
1921 return strlen((char *)s
) + 1;
1925 FcStrNeededBytesAlign (void)
1927 return __alignof__ (char);
1931 FcStrEnsureBank (int bi
)
1935 if (!static_strs
|| static_str_bank_count
<= bi
)
1937 int new_count
= bi
+ 4, i
;
1938 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1942 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1945 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1947 static_str_bank_count
= new_count
;
1953 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1955 int bi
= FcCacheBankToIndex(metadata
->bank
);
1956 if (!FcStrEnsureBank(bi
))
1959 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1960 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1961 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1962 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1963 metadata
->str_count
= fcstr_count
;
1969 static const FcChar8
*
1970 FcStrSerialize (int bank
, const FcChar8
* s
)
1972 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1973 struct objectBucket
**p
;
1974 struct objectBucket
*b
;
1975 int bi
= FcCacheBankToIndex(bank
);
1977 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1978 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1981 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
1984 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1985 t
= static_strs
[bi
] + fcstr_ptr
;
1986 memcpy ((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1, &t
, sizeof (FcChar8
*));
1987 fcstr_ptr
+= strlen((char *)s
) + 1;
1988 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
1996 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
1998 int bi
= FcCacheBankToIndex(metadata
->bank
);
1999 if (!FcStrEnsureBank(bi
))
2002 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
2003 block_ptr
= ALIGN (block_ptr
, FcChar8
);
2004 static_strs
[bi
] = (FcChar8
*)block_ptr
;
2005 block_ptr
= (void *)((char *)block_ptr
+
2006 (sizeof (char) * metadata
->str_count
));
2011 /* we don't store these in the FcPattern itself because
2012 * we don't want to serialize the directory names */
2014 /* I suppose this should be cleaned upon termination, too... */
2015 typedef struct _FcPatternDirMapping
{
2018 } FcPatternDirMapping
;
2020 #define PATTERNDIR_HASH_SIZE 31
2021 static struct patternDirBucket
{
2022 struct patternDirBucket
*next
;
2023 FcPatternDirMapping m
;
2024 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
2027 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
2029 struct patternDirBucket
*pb
;
2031 /* N.B. FcPatternHash fails, since it's contents-based, not
2032 * address-based, and we're in the process of mutating the FcPattern. */
2033 for (pb
= &FcPatternDirBuckets
2034 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2035 pb
->m
.p
!= p
&& pb
->next
;
2041 pb
->m
.fname
= fname
;
2045 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2048 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2052 pb
->next
->m
.fname
= fname
;
2056 FcPatternFindFullFname (const FcPattern
*p
)
2058 struct patternDirBucket
*pb
;
2060 for (pb
= &FcPatternDirBuckets
2061 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2070 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2073 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2074 FcPatternAddFullFname (new,
2076 ((FcChar8
*)FcPatternFindFullFname(orig
)));