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 FcPatternGetFile (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1104 const char *fn
, *fpath
;
1108 fn
= FcPatternFindFullFname(p
);
1111 *s
= (FcChar8
*) fn
;
1112 return FcResultMatch
;
1116 return FcResultMatch
;
1118 fpath
= FcCacheFindBankDir (p
->bank
);
1119 size
= strlen((char *)fpath
) + 1 + strlen ((char *)*s
) + 1;
1120 fname
= malloc (size
);
1122 return FcResultOutOfMemory
;
1124 FcMemAlloc (FC_MEM_STRING
, size
);
1125 strcpy ((char *)fname
, (char *)fpath
);
1126 strcat ((char *)fname
, "/");
1127 strcat ((char *)fname
, (char *)*s
);
1129 FcPatternAddFullFname (p
, (const char *)fname
);
1130 *s
= (FcChar8
*)fname
;
1131 return FcResultMatch
;
1135 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1140 e
= FcPatternFindElt (p
, object
);
1142 return FcResultNoMatch
;
1143 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1147 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1149 /* Pull the FC_FILE trick here too. */
1150 if (v
->type
== FcTypeString
&&
1151 FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1152 return FcPatternGetFile (p
, object
, id
, (FcChar8
**)&(v
->u
.s
));
1154 return FcResultMatch
;
1158 return FcResultNoId
;
1162 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1167 r
= FcPatternGet (p
, object
, id
, &v
);
1168 if (r
!= FcResultMatch
)
1178 return FcResultTypeMismatch
;
1180 return FcResultMatch
;
1184 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1189 r
= FcPatternGet (p
, object
, id
, &v
);
1190 if (r
!= FcResultMatch
)
1197 *d
= (double) v
.u
.i
;
1200 return FcResultTypeMismatch
;
1202 return FcResultMatch
;
1206 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1211 r
= FcPatternGet (p
, object
, id
, &v
);
1212 if (r
!= FcResultMatch
)
1214 if (v
.type
!= FcTypeString
)
1215 return FcResultTypeMismatch
;
1217 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1218 return FcPatternGetFile (p
, object
, id
, s
);
1220 *s
= (FcChar8
*) v
.u
.s
;
1221 return FcResultMatch
;
1225 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1230 r
= FcPatternGet (p
, object
, id
, &v
);
1231 if (r
!= FcResultMatch
)
1233 if (v
.type
!= FcTypeMatrix
)
1234 return FcResultTypeMismatch
;
1235 *m
= (FcMatrix
*)v
.u
.m
;
1236 return FcResultMatch
;
1241 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1246 r
= FcPatternGet (p
, object
, id
, &v
);
1247 if (r
!= FcResultMatch
)
1249 if (v
.type
!= FcTypeBool
)
1250 return FcResultTypeMismatch
;
1252 return FcResultMatch
;
1256 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1261 r
= FcPatternGet (p
, object
, id
, &v
);
1262 if (r
!= FcResultMatch
)
1264 if (v
.type
!= FcTypeCharSet
)
1265 return FcResultTypeMismatch
;
1266 *c
= (FcCharSet
*)v
.u
.c
;
1267 return FcResultMatch
;
1271 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1276 r
= FcPatternGet (p
, object
, id
, &v
);
1277 if (r
!= FcResultMatch
)
1279 if (v
.type
!= FcTypeFTFace
)
1280 return FcResultTypeMismatch
;
1281 *f
= (FT_Face
) v
.u
.f
;
1282 return FcResultMatch
;
1286 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1291 r
= FcPatternGet (p
, object
, id
, &v
);
1292 if (r
!= FcResultMatch
)
1294 if (v
.type
!= FcTypeLangSet
)
1295 return FcResultTypeMismatch
;
1296 *ls
= (FcLangSet
*)v
.u
.l
;
1297 return FcResultMatch
;
1301 FcPatternDuplicate (const FcPattern
*orig
)
1308 new = FcPatternCreate ();
1312 e
= FcPatternEltU(orig
->elts
);
1314 for (i
= 0; i
< orig
->num
; i
++)
1316 for (l
= (e
+ i
)->values
;
1318 l
= FcValueListPtrU(l
)->next
)
1319 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1320 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1324 FcPatternTransferFullFname (new, orig
);
1329 FcPatternDestroy (new);
1335 FcPatternReference (FcPattern
*p
)
1337 if (p
->ref
!= FC_REF_CONSTANT
)
1342 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1346 FcPatternVapBuild (ret
, orig
, va
);
1351 FcPatternBuild (FcPattern
*orig
, ...)
1355 va_start (va
, orig
);
1356 FcPatternVapBuild (orig
, orig
, va
);
1362 * Add all of the elements in 's' to 'p'
1365 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1371 for (i
= 0; i
< s
->num
; i
++)
1373 e
= FcPatternEltU(s
->elts
)+i
;
1374 for (v
= e
->values
; FcValueListPtrU(v
);
1375 v
= FcValueListPtrU(v
)->next
)
1377 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1378 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1379 FcValueListPtrU(v
)->binding
, FcTrue
))
1386 #define OBJECT_HASH_SIZE 31
1387 static struct objectBucket
{
1388 struct objectBucket
*next
;
1390 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1393 FcStrHashed (const FcChar8
*name
)
1395 FcChar32 hash
= FcStringHash (name
);
1396 struct objectBucket
**p
;
1397 struct objectBucket
*b
;
1399 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1400 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1406 FcStrStaticName (const FcChar8
*name
)
1408 FcChar32 hash
= FcStringHash (name
);
1409 struct objectBucket
**p
;
1410 struct objectBucket
*b
;
1413 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1414 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1415 return (FcChar8
*) (b
+ 1);
1416 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1417 b
= malloc (size
+ sizeof (int));
1418 /* workaround glibc bug which reads strlen in groups of 4 */
1419 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1424 strcpy ((char *) (b
+ 1), (char *)name
);
1426 return (FcChar8
*) (b
+ 1);
1430 FcStrStaticNameFini (void)
1433 struct objectBucket
*b
, *next
;
1436 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1438 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1441 name
= (char *) (b
+ 1);
1442 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1443 FcMemFree (FC_MEM_STATICSTR
, size
);
1446 FcObjectBuckets
[i
] = 0;
1451 FcPatternFini (void)
1453 FcPatternBaseThawAll ();
1454 FcValueListThawAll ();
1455 FcStrStaticNameFini ();
1456 FcObjectStaticNameFini ();
1459 static FcPatternEltPtr
1460 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1462 FcPatternEltPtr
new;
1463 new.bank
= FC_BANK_DYNAMIC
;
1468 static FcPatternEltPtr
1469 FcPatternEltPtrCreateStatic (int bank
, int i
)
1471 FcPatternEltPtr
new;
1478 FcStrNewBank (void);
1480 FcStrNeededBytes (const FcChar8
* s
);
1482 FcStrNeededBytesAlign (void);
1484 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1485 static const FcChar8
*
1486 FcStrSerialize (int bank
, const FcChar8
* s
);
1488 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1491 FcValueListNewBank (void);
1493 FcValueListNeededBytes (FcValueList
* vl
);
1495 FcValueListNeededBytesAlign (void);
1497 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1498 static FcValueListPtr
1499 FcValueListSerialize(int bank
, FcValueList
*pi
);
1501 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1505 FcPatternNewBank (void)
1507 fcpattern_count
= 0;
1508 fcpatternelt_count
= 0;
1511 FcValueListNewBank();
1515 FcPatternNeededBytes (FcPattern
* p
)
1520 fcpatternelt_count
+= p
->num
;
1522 for (i
= 0; i
< p
->num
; i
++)
1524 c
= FcValueListNeededBytes (FcValueListPtrU
1525 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1531 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1535 FcPatternNeededBytesAlign (void)
1537 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1538 FcValueListNeededBytesAlign ();
1542 FcPatternEnsureBank (int bi
)
1548 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1550 int new_count
= bi
+ 4;
1551 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1555 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1558 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1562 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1563 _fcPatternElts
= ep
;
1565 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1568 _fcPatternElts
[i
] = 0;
1571 fcpattern_bank_count
= new_count
;
1574 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1579 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1581 int bi
= FcCacheBankToIndex(metadata
->bank
);
1583 if (!FcPatternEnsureBank(bi
))
1587 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1588 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1589 block_ptr
= (void *)((char *)block_ptr
+
1590 (sizeof (FcPattern
) * fcpattern_count
));
1592 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1593 fcpatternelt_ptr
= 0;
1594 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1595 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1596 block_ptr
= (void *)((char *)block_ptr
+
1597 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1599 metadata
->pattern_count
= fcpattern_count
;
1600 metadata
->patternelt_count
= fcpatternelt_count
;
1602 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1603 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1608 FcPatternSerialize (int bank
, FcPattern
*old
)
1611 FcPatternElt
*e
, *nep
;
1613 FcValueListPtr v
, nv_head
, nvp
;
1614 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1616 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1618 elts
= fcpatternelt_ptr
;
1619 nep
= &_fcPatternElts
[bi
][elts
];
1623 fcpatternelt_ptr
+= old
->num
;
1625 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1628 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1629 if (!FcValueListPtrU(nv_head
))
1631 nv
= FcValueListPtrU(nvp
);
1635 v
= FcValueListPtrU(v
)->next
,
1636 nv
= FcValueListPtrU(nv
->next
))
1639 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1641 nvp
= FcValueListSerialize
1642 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1647 nep
[i
].values
= nv_head
;
1648 nep
[i
].object
= e
->object
;
1651 p
->elts
= old
->elts
;
1652 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1655 p
->ref
= FC_REF_CONSTANT
;
1660 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1662 int bi
= FcCacheBankToIndex(metadata
->bank
);
1663 if (!FcPatternEnsureBank(bi
))
1666 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1667 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1668 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1669 block_ptr
= (void *)((char *)block_ptr
+
1670 (sizeof (FcPattern
) * metadata
->pattern_count
));
1672 FcMemAlloc (FC_MEM_PATELT
,
1673 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1674 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1675 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1676 block_ptr
= (void *)((char *)block_ptr
+
1677 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1679 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1680 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1686 FcValueListNewBank (void)
1688 fcvaluelist_count
= 0;
1695 FcValueListNeededBytes (FcValueList
*p
)
1702 vl
= FcValueListPtrU(vl
->next
))
1704 /* unserialize just in case */
1705 FcValue v
= FcValueCanonicalize(&vl
->value
);
1710 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1713 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1716 cum
+= FcStrNeededBytes(v
.u
.s
);
1720 fcvaluelist_count
++;
1721 cum
+= sizeof (FcValueList
);
1728 FcValueListNeededBytesAlign (void)
1730 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1731 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1735 FcValueListEnsureBank (int bi
)
1739 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1741 int new_count
= bi
+ 2, i
;
1743 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1747 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1749 _fcValueLists
= pvl
;
1750 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1751 _fcValueLists
[i
] = 0;
1753 fcvaluelist_bank_count
= new_count
;
1759 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1761 int bi
= FcCacheBankToIndex(metadata
->bank
);
1763 if (!FcValueListEnsureBank(bi
))
1766 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1767 fcvaluelist_ptr
= 0;
1768 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1769 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1770 block_ptr
= (void *)((char *)block_ptr
+
1771 (sizeof (FcValueList
) * fcvaluelist_count
));
1772 metadata
->valuelist_count
= fcvaluelist_count
;
1774 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1775 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1780 static FcValueListPtr
1781 FcValueListSerialize(int bank
, FcValueList
*pi
)
1785 int bi
= FcCacheBankToIndex(bank
);
1789 new.bank
= FC_BANK_DYNAMIC
;
1794 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1796 new.u
.stat
= fcvaluelist_ptr
++;
1797 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1798 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1804 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1806 return FcValueListPtrCreateDynamic(pi
);
1807 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1808 v
->type
|= FC_STORAGE_STATIC
;
1816 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1818 return FcValueListPtrCreateDynamic(pi
);
1819 v
->u
.c_off
= (char *)c
- (char *)v
;
1820 v
->type
|= FC_STORAGE_STATIC
;
1826 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1828 return FcValueListPtrCreateDynamic(pi
);
1829 v
->u
.l_off
= (char *)l
- (char *)v
;
1830 v
->type
|= FC_STORAGE_STATIC
;
1840 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1842 int bi
= FcCacheBankToIndex(metadata
->bank
);
1844 if (!FcValueListEnsureBank(bi
))
1847 FcMemAlloc (FC_MEM_VALLIST
,
1848 sizeof (FcValueList
) * metadata
->valuelist_count
);
1849 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1850 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1851 block_ptr
= (void *)((char *)block_ptr
+
1852 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1854 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1855 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1861 FcValueListPtrCreateDynamic(FcValueList
* p
)
1865 r
.bank
= FC_BANK_DYNAMIC
;
1870 static FcChar8
** static_strs
;
1871 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1873 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1879 struct objectBucket
*b
, *next
;
1882 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1884 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1887 name
= (char *) (b
+ 1);
1888 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1889 FcMemFree (FC_MEM_STATICSTR
, size
);
1892 FcStrBuckets
[i
] = 0;
1899 FcStrNeededBytes (const FcChar8
* s
)
1901 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1902 struct objectBucket
**p
;
1903 struct objectBucket
*b
;
1905 FcChar8
*const null
= 0;
1907 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1908 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1910 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1912 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1917 strcpy ((char *) (b
+ 1), (char *)s
);
1919 /* Yes, the following line is convoluted. However, it is
1920 * incorrect to replace the with a memset, because the C
1921 * specification doesn't guarantee that the null pointer is
1922 * the same as the zero bit pattern. */
1923 /* Misaligned pointers are not guaranteed to work, either! */
1924 memcpy (((char *) (b
+ 1) + strlen((char *)s
) + 1), &null
, sizeof (null
));
1927 fcstr_count
+= strlen((char *)s
) + 1;
1928 return strlen((char *)s
) + 1;
1932 FcStrNeededBytesAlign (void)
1934 return __alignof__ (char);
1938 FcStrEnsureBank (int bi
)
1942 if (!static_strs
|| static_str_bank_count
<= bi
)
1944 int new_count
= bi
+ 4, i
;
1945 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1949 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1952 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1954 static_str_bank_count
= new_count
;
1960 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1962 int bi
= FcCacheBankToIndex(metadata
->bank
);
1963 if (!FcStrEnsureBank(bi
))
1966 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1967 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1968 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1969 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1970 metadata
->str_count
= fcstr_count
;
1976 static const FcChar8
*
1977 FcStrSerialize (int bank
, const FcChar8
* s
)
1979 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1980 struct objectBucket
**p
;
1981 struct objectBucket
*b
;
1982 int bi
= FcCacheBankToIndex(bank
);
1984 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1985 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1988 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
1991 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1992 t
= static_strs
[bi
] + fcstr_ptr
;
1993 memcpy ((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1, &t
, sizeof (FcChar8
*));
1994 fcstr_ptr
+= strlen((char *)s
) + 1;
1995 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
2003 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
2005 int bi
= FcCacheBankToIndex(metadata
->bank
);
2006 if (!FcStrEnsureBank(bi
))
2009 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
2010 block_ptr
= ALIGN (block_ptr
, FcChar8
);
2011 static_strs
[bi
] = (FcChar8
*)block_ptr
;
2012 block_ptr
= (void *)((char *)block_ptr
+
2013 (sizeof (char) * metadata
->str_count
));
2018 /* we don't store these in the FcPattern itself because
2019 * we don't want to serialize the directory names */
2021 /* I suppose this should be cleaned upon termination, too... */
2022 typedef struct _FcPatternDirMapping
{
2025 } FcPatternDirMapping
;
2027 #define PATTERNDIR_HASH_SIZE 31
2028 static struct patternDirBucket
{
2029 struct patternDirBucket
*next
;
2030 FcPatternDirMapping m
;
2031 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
2034 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
2036 struct patternDirBucket
*pb
;
2038 /* N.B. FcPatternHash fails, since it's contents-based, not
2039 * address-based, and we're in the process of mutating the FcPattern. */
2040 for (pb
= &FcPatternDirBuckets
2041 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2042 pb
->m
.p
!= p
&& pb
->next
;
2048 pb
->m
.fname
= fname
;
2052 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2055 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2059 pb
->next
->m
.fname
= fname
;
2063 FcPatternFindFullFname (const FcPattern
*p
)
2065 struct patternDirBucket
*pb
;
2067 for (pb
= &FcPatternDirBuckets
2068 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2077 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2080 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2081 FcPatternAddFullFname (new,
2083 ((FcChar8
*)FcPatternFindFullFname(orig
)));