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 /* If you are trying to duplicate an FcPattern which will be used for
41 * rendering, be aware that (internally) you also have to use
42 * FcPatternTransferFullFname to transfer the associated filename. If
43 * you are copying the font (externally) using FcPatternGetString,
44 * then everything's fine; this caveat only applies if you're copying
45 * the bits individually. */
48 FcPatternCreate (void)
52 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
55 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
58 p
->elts
= FcPatternEltPtrCreateDynamic(0);
59 p
->bank
= FC_BANK_DYNAMIC
;
65 FcValueDestroy (FcValue v
)
69 FcStrFree ((FcChar8
*) v
.u
.s
);
72 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
75 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
78 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
86 FcValueCanonicalize (const FcValue
*v
)
88 if (v
->type
& FC_STORAGE_STATIC
)
92 switch (v
->type
& ~FC_STORAGE_STATIC
)
95 new.u
.s
= fc_value_string(v
);
96 new.type
= FcTypeString
;
99 new.u
.c
= fc_value_charset(v
);
100 new.type
= FcTypeCharSet
;
103 new.u
.l
= fc_value_langset(v
);
104 new.type
= FcTypeLangSet
;
113 FcValueSave (FcValue v
)
117 v
.u
.s
= FcStrCopy (v
.u
.s
);
122 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
127 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
132 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
143 FcValueListDestroy (FcValueListPtr l
)
146 for (; FcValueListPtrU(l
); l
= next
)
148 switch (FcValueListPtrU(l
)->value
.type
) {
150 FcStrFree ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
);
153 FcMatrixFree ((FcMatrix
*)FcValueListPtrU(l
)->value
.u
.m
);
157 ((FcCharSet
*) (FcValueListPtrU(l
)->value
.u
.c
));
161 ((FcLangSet
*) (FcValueListPtrU(l
)->value
.u
.l
));
166 next
= FcValueListPtrU(l
)->next
;
167 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
168 if (l
.bank
== FC_BANK_DYNAMIC
)
174 FcValueEqual (FcValue va
, FcValue vb
)
176 if (va
.type
!= vb
.type
)
178 if (va
.type
== FcTypeInteger
)
180 va
.type
= FcTypeDouble
;
183 if (vb
.type
== FcTypeInteger
)
185 vb
.type
= FcTypeDouble
;
188 if (va
.type
!= vb
.type
)
195 return va
.u
.i
== vb
.u
.i
;
197 return va
.u
.d
== vb
.u
.d
;
199 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
201 return va
.u
.b
== vb
.u
.b
;
203 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
205 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
207 return va
.u
.f
== vb
.u
.f
;
209 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
215 FcDoubleHash (double d
)
225 FcStringHash (const FcChar8
*s
)
232 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
237 FcValueHash (const FcValue
*v0
)
239 FcValue v
= FcValueCanonicalize(v0
);
244 return (FcChar32
) v
.u
.i
;
246 return FcDoubleHash (v
.u
.d
);
248 return FcStringHash (v
.u
.s
);
250 return (FcChar32
) v
.u
.b
;
252 return (FcDoubleHash (v
.u
.m
->xx
) ^
253 FcDoubleHash (v
.u
.m
->xy
) ^
254 FcDoubleHash (v
.u
.m
->yx
) ^
255 FcDoubleHash (v
.u
.m
->yy
));
257 return (FcChar32
) v
.u
.c
->num
;
259 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
260 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
262 return FcLangSetHash (v
.u
.l
);
268 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
270 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
273 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
275 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
276 FcValueListPtrU(lb
)->value
))
278 la
= FcValueListPtrU(la
)->next
;
279 lb
= FcValueListPtrU(lb
)->next
;
281 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
287 FcValueListHash (FcValueListPtr l
)
291 while (FcValueListPtrU(l
))
293 hash
= ((hash
<< 1) | (hash
>> 31)) ^
294 FcValueHash (&FcValueListPtrU(l
)->value
);
295 l
= FcValueListPtrU(l
)->next
;
301 FcPatternDestroy (FcPattern
*p
)
305 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
308 if (FcPatternFindFullFname (p
))
310 FcStrFree ((FcChar8
*)FcPatternFindFullFname (p
));
311 FcPatternAddFullFname (p
, 0);
314 for (i
= 0; i
< p
->num
; i
++)
315 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
318 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
320 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
321 free (FcPatternEltU(p
->elts
));
322 p
->elts
= FcPatternEltPtrCreateDynamic(0);
325 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
329 #define FC_VALUE_LIST_HASH_SIZE 257
330 #define FC_PATTERN_HASH_SIZE 67
332 typedef struct _FcValueListEnt FcValueListEnt
;
334 struct _FcValueListEnt
{
335 FcValueListEnt
*next
;
340 typedef union _FcValueListAlign
{
345 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
346 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
347 static char FcValueListFrozenName
[][8] = {
360 FcValueListReport (void);
363 FcValueListReport (void)
367 printf ("Fc Frozen Values:\n");
368 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
369 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
370 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
371 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
374 static FcValueListEnt
*
375 FcValueListEntCreate (FcValueListPtr h
)
377 FcValueListAlign
*ea
;
385 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
387 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
388 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
389 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
390 // this leaks for some reason
391 ea
= malloc (sizeof (FcValueListAlign
));
394 new = malloc (n
* sizeof (FcValueList
));
397 memset(new, 0, n
* sizeof (FcValueList
));
398 FcMemAlloc (FC_MEM_VALLIST
, size
);
400 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
401 for (l
= h
; FcValueListPtrU(l
);
402 l
= FcValueListPtrU(l
)->next
, new++)
404 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
406 new->value
.type
= FcTypeString
;
407 new->value
.u
.s
= FcStrStaticName
408 (fc_value_string(&FcValueListPtrU(l
)->value
));
412 new->value
= FcValueSave (FcValueCanonicalize
413 (&FcValueListPtrU(l
)->value
));
415 new->binding
= FcValueListPtrU(l
)->binding
;
416 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
418 new->next
= FcValueListPtrCreateDynamic(new + 1);
422 new->next
= FcValueListPtrCreateDynamic(0);
429 FcValueListEntDestroy (FcValueListEnt
*e
)
433 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
435 /* XXX: We should perform these two operations with "size" as
436 computed in FcValueListEntCreate, but we don't have access to
437 that value here. Without this, the FcValueListFrozenBytes
438 values will be wrong as will the FcMemFree counts.
440 FcValueListFrozenBytes[e->list->value.type] -= size;
441 FcMemFree (FC_MEM_VALLIST, size);
444 for (l
= e
->list
; FcValueListPtrU(l
);
445 l
= FcValueListPtrU(l
)->next
)
447 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
448 FcValueDestroy (FcValueListPtrU(l
)->value
);
450 /* XXX: Are we being too chummy with the implementation here to
451 free(e) when it was actually the enclosing FcValueListAlign
452 that was allocated? */
456 static int FcValueListTotal
;
457 static int FcValueListUsed
;
459 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
461 static FcValueListPtr
462 FcValueListFreeze (FcValueListPtr l
)
464 FcChar32 hash
= FcValueListHash (l
);
465 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
469 for (ent
= *bucket
; ent
; ent
= ent
->next
)
471 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
475 ent
= FcValueListEntCreate (l
);
477 return FcValueListPtrCreateDynamic(0);
487 FcValueListThawAll (void)
490 FcValueListEnt
*ent
, *next
;
492 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
494 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
497 FcValueListEntDestroy (ent
);
499 FcValueListHashTable
[i
] = 0;
502 FcValueListTotal
= 0;
507 FcPatternBaseHash (FcPattern
*b
)
509 FcChar32 hash
= b
->num
;
512 for (i
= 0; i
< b
->num
; i
++)
513 hash
= ((hash
<< 1) | (hash
>> 31)) ^
514 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
518 typedef struct _FcPatternEnt FcPatternEnt
;
520 struct _FcPatternEnt
{
526 static int FcPatternTotal
;
527 static int FcPatternUsed
;
529 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
532 FcPatternBaseFreeze (FcPattern
*b
)
536 FcChar32 hash
= FcPatternBaseHash (b
);
537 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
542 for (ent
= *bucket
; ent
; ent
= ent
->next
)
544 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
546 for (i
= 0; i
< b
->num
; i
++)
548 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
549 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
551 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
552 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
561 * Compute size of pattern + elts
563 ent
= malloc (sizeof (FcPatternEnt
));
567 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
570 ep
= FcPatternCreate();
574 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
577 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
579 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
583 ep
->ref
= FC_REF_CONSTANT
;
585 for (i
= 0; i
< b
->num
; i
++)
587 (FcPatternEltU(ep
->elts
)+i
)->values
=
588 (FcPatternEltU(b
->elts
)+i
)->values
;
589 (FcPatternEltU(ep
->elts
)+i
)->object
=
590 (FcPatternEltU(b
->elts
)+i
)->object
;
593 if (FcPatternFindElt (b
, FC_FILE
))
594 FcPatternTransferFullFname (ep
, b
);
602 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
608 FcPatternBaseThawAll (void)
611 FcPatternEnt
*ent
, *next
;
613 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
615 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
620 FcPatternHashTable
[i
] = 0;
628 FcPatternFreeze (FcPattern
*p
)
630 FcPattern
*b
, *n
= 0;
634 if (p
->ref
== FC_REF_CONSTANT
)
637 b
= FcPatternCreate();
645 e
= malloc(b
->num
* sizeof (FcPatternElt
));
648 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
649 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
652 * Freeze object lists
654 for (i
= 0; i
< p
->num
; i
++)
656 (FcPatternEltU(b
->elts
)+i
)->object
=
657 (FcPatternEltU(p
->elts
)+i
)->object
;
658 (FcPatternEltU(b
->elts
)+i
)->values
=
659 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
660 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
664 if (FcPatternFindElt (p
, FC_FILE
))
665 FcPatternTransferFullFname (b
, p
);
670 n
= FcPatternBaseFreeze (b
);
672 if (FcDebug() & FC_DBG_MEMORY
)
674 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
675 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
679 free(FcPatternEltU(b
->elts
));
680 b
->elts
= FcPatternEltPtrCreateDynamic(0);
681 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
684 assert (FcPatternEqual (n
, p
));
690 FcPatternPosition (const FcPattern
*p
, const char *object
)
692 int low
, high
, mid
, c
;
695 obj
= FcObjectToPtr(object
);
702 mid
= (low
+ high
) >> 1;
703 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
717 FcPatternFindElt (const FcPattern
*p
, const char *object
)
719 int i
= FcPatternPosition (p
, object
);
722 return FcPatternEltU(p
->elts
)+i
;
726 FcPatternInsertElt (FcPattern
*p
, const char *object
)
731 i
= FcPatternPosition (p
, object
);
736 /* reallocate array */
737 if (p
->num
+ 1 >= p
->size
)
739 int s
= p
->size
+ 16;
740 if (FcPatternEltU(p
->elts
))
742 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
743 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
744 if (!e
) /* maybe it was mmapped */
746 e
= malloc(s
* sizeof (FcPatternElt
));
748 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
752 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
755 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
757 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
758 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
761 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
762 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
763 FcValueListPtrCreateDynamic(0);
769 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
770 FcPatternEltU(p
->elts
) + i
,
771 sizeof (FcPatternElt
) *
777 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
778 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
781 return FcPatternEltU(p
->elts
)+i
;
785 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
792 if (pa
->num
!= pb
->num
)
794 for (i
= 0; i
< pa
->num
; i
++)
796 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
797 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
799 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
800 (FcPatternEltU(pb
->elts
)+i
)->values
))
807 FcPatternHash (const FcPattern
*p
)
812 for (i
= 0; i
< p
->num
; i
++)
814 h
= (((h
<< 1) | (h
>> 31)) ^
815 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
816 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
822 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
824 FcPatternElt
*ea
, *eb
;
827 for (i
= 0; i
< os
->nobject
; i
++)
829 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
830 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
835 if (!FcValueListEqual (ea
->values
, eb
->values
))
848 FcPatternAddWithBinding (FcPattern
*p
,
851 FcValueBinding binding
,
855 FcValueListPtr
new, *prev
;
857 FcObjectPtr objectPtr
;
859 if (p
->ref
== FC_REF_CONSTANT
)
862 newp
= malloc (sizeof (FcValueList
));
866 memset(newp
, 0, sizeof (FcValueList
));
867 new = FcValueListPtrCreateDynamic(newp
);
868 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
870 value
= FcValueSave (value
);
871 if (value
.type
== FcTypeVoid
)
874 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
875 * speedup: only allow strings to be added under the FC_FAMILY,
876 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
877 * and charsets under FC_CHARSET key.
878 * This is slightly semantically different from the old behaviour,
879 * but fonts shouldn't be getting non-strings here anyway.
880 * a better hack would use FcBaseObjectTypes to check all objects. */
881 objectPtr
= FcObjectToPtr(object
);
882 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
883 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
884 || objectPtr
== FcObjectToPtr(FC_STYLE
)
885 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
886 && value
.type
!= FcTypeString
)
888 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
889 && value
.type
!= FcTypeCharSet
)
892 FcValueListPtrU(new)->value
= value
;
893 FcValueListPtrU(new)->binding
= binding
;
894 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
896 e
= FcPatternInsertElt (p
, object
);
902 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
908 FcValueListPtrU(new)->next
= e
->values
;
915 switch (value
.type
) {
917 FcStrFree ((FcChar8
*) value
.u
.s
);
920 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
923 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
926 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
932 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
933 free (FcValueListPtrU(new));
939 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
941 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
945 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
947 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
951 FcPatternDel (FcPattern
*p
, const char *object
)
955 e
= FcPatternFindElt (p
, object
);
960 FcValueListDestroy (e
->values
);
962 /* shuffle existing ones down */
964 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
965 sizeof (FcPatternElt
));
967 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
968 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
973 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
976 FcValueListPtr
*prev
, l
;
978 e
= FcPatternFindElt (p
, object
);
981 for (prev
= &e
->values
;
982 FcValueListPtrU(l
= *prev
);
983 prev
= &FcValueListPtrU(l
)->next
)
987 *prev
= FcValueListPtrU(l
)->next
;
988 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
989 FcValueListDestroy (l
);
990 if (!FcValueListPtrU(e
->values
))
991 FcPatternDel (p
, object
);
1000 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1004 v
.type
= FcTypeInteger
;
1006 return FcPatternAdd (p
, object
, v
, FcTrue
);
1010 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1014 v
.type
= FcTypeDouble
;
1016 return FcPatternAdd (p
, object
, v
, FcTrue
);
1021 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1025 v
.type
= FcTypeString
;
1026 v
.u
.s
= FcStrStaticName(s
);
1027 return FcPatternAdd (p
, object
, v
, FcTrue
);
1031 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1035 v
.type
= FcTypeMatrix
;
1037 return FcPatternAdd (p
, object
, v
, FcTrue
);
1042 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1046 v
.type
= FcTypeBool
;
1048 return FcPatternAdd (p
, object
, v
, FcTrue
);
1052 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1056 v
.type
= FcTypeCharSet
;
1057 v
.u
.c
= (FcCharSet
*)c
;
1058 return FcPatternAdd (p
, object
, v
, FcTrue
);
1062 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1066 v
.type
= FcTypeFTFace
;
1068 return FcPatternAdd (p
, object
, v
, FcTrue
);
1072 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1076 v
.type
= FcTypeLangSet
;
1077 v
.u
.l
= (FcLangSet
*)ls
;
1078 return FcPatternAdd (p
, object
, v
, FcTrue
);
1082 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1087 e
= FcPatternFindElt (p
, object
);
1089 return FcResultNoMatch
;
1090 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1094 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1095 return FcResultMatch
;
1099 return FcResultNoId
;
1103 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1108 r
= FcPatternGet (p
, object
, id
, &v
);
1109 if (r
!= FcResultMatch
)
1119 return FcResultTypeMismatch
;
1121 return FcResultMatch
;
1125 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1130 r
= FcPatternGet (p
, object
, id
, &v
);
1131 if (r
!= FcResultMatch
)
1138 *d
= (double) v
.u
.i
;
1141 return FcResultTypeMismatch
;
1143 return FcResultMatch
;
1147 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1152 r
= FcPatternGet (p
, object
, id
, &v
);
1153 if (r
!= FcResultMatch
)
1155 if (v
.type
!= FcTypeString
)
1156 return FcResultTypeMismatch
;
1158 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1160 const char *fn
, *fpath
;
1164 fn
= FcPatternFindFullFname(p
);
1167 *s
= (FcChar8
*) fn
;
1168 return FcResultMatch
;
1173 *s
= (FcChar8
*) v
.u
.s
;
1174 return FcResultMatch
;
1177 fpath
= FcCacheFindBankDir (p
->bank
);
1178 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1179 fname
= malloc (size
);
1181 return FcResultOutOfMemory
;
1183 FcMemAlloc (FC_MEM_STRING
, size
);
1184 strcpy ((char *)fname
, (char *)fpath
);
1185 strcat ((char *)fname
, "/");
1186 strcat ((char *)fname
, (char *)v
.u
.s
);
1188 FcPatternAddFullFname (p
, (const char *)fname
);
1189 *s
= (FcChar8
*)fname
;
1190 return FcResultMatch
;
1193 *s
= (FcChar8
*) v
.u
.s
;
1194 return FcResultMatch
;
1198 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1203 r
= FcPatternGet (p
, object
, id
, &v
);
1204 if (r
!= FcResultMatch
)
1206 if (v
.type
!= FcTypeMatrix
)
1207 return FcResultTypeMismatch
;
1208 *m
= (FcMatrix
*)v
.u
.m
;
1209 return FcResultMatch
;
1214 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1219 r
= FcPatternGet (p
, object
, id
, &v
);
1220 if (r
!= FcResultMatch
)
1222 if (v
.type
!= FcTypeBool
)
1223 return FcResultTypeMismatch
;
1225 return FcResultMatch
;
1229 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1234 r
= FcPatternGet (p
, object
, id
, &v
);
1235 if (r
!= FcResultMatch
)
1237 if (v
.type
!= FcTypeCharSet
)
1238 return FcResultTypeMismatch
;
1239 *c
= (FcCharSet
*)v
.u
.c
;
1240 return FcResultMatch
;
1244 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1249 r
= FcPatternGet (p
, object
, id
, &v
);
1250 if (r
!= FcResultMatch
)
1252 if (v
.type
!= FcTypeFTFace
)
1253 return FcResultTypeMismatch
;
1254 *f
= (FT_Face
) v
.u
.f
;
1255 return FcResultMatch
;
1259 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1264 r
= FcPatternGet (p
, object
, id
, &v
);
1265 if (r
!= FcResultMatch
)
1267 if (v
.type
!= FcTypeLangSet
)
1268 return FcResultTypeMismatch
;
1269 *ls
= (FcLangSet
*)v
.u
.l
;
1270 return FcResultMatch
;
1274 FcPatternDuplicate (const FcPattern
*orig
)
1281 new = FcPatternCreate ();
1285 e
= FcPatternEltU(orig
->elts
);
1287 for (i
= 0; i
< orig
->num
; i
++)
1289 for (l
= (e
+ i
)->values
;
1291 l
= FcValueListPtrU(l
)->next
)
1292 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1293 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1297 FcPatternTransferFullFname (new, orig
);
1302 FcPatternDestroy (new);
1308 FcPatternReference (FcPattern
*p
)
1310 if (p
->ref
!= FC_REF_CONSTANT
)
1315 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1319 FcPatternVapBuild (ret
, orig
, va
);
1324 FcPatternBuild (FcPattern
*orig
, ...)
1328 va_start (va
, orig
);
1329 FcPatternVapBuild (orig
, orig
, va
);
1335 * Add all of the elements in 's' to 'p'
1338 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1344 for (i
= 0; i
< s
->num
; i
++)
1346 e
= FcPatternEltU(s
->elts
)+i
;
1347 for (v
= e
->values
; FcValueListPtrU(v
);
1348 v
= FcValueListPtrU(v
)->next
)
1350 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1351 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1352 FcValueListPtrU(v
)->binding
, FcTrue
))
1359 #define OBJECT_HASH_SIZE 31
1360 static struct objectBucket
{
1361 struct objectBucket
*next
;
1363 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1366 FcStrStaticName (const FcChar8
*name
)
1368 FcChar32 hash
= FcStringHash (name
);
1369 struct objectBucket
**p
;
1370 struct objectBucket
*b
;
1373 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1374 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1375 return (FcChar8
*) (b
+ 1);
1376 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1377 b
= malloc (size
+ sizeof (int));
1378 /* workaround glibc bug which reads strlen in groups of 4 */
1379 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1384 strcpy ((char *) (b
+ 1), (char *)name
);
1386 return (FcChar8
*) (b
+ 1);
1390 FcStrStaticNameFini (void)
1393 struct objectBucket
*b
, *next
;
1396 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1398 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1401 name
= (char *) (b
+ 1);
1402 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1403 FcMemFree (FC_MEM_STATICSTR
, size
);
1406 FcObjectBuckets
[i
] = 0;
1411 FcPatternFini (void)
1413 FcPatternBaseThawAll ();
1414 FcValueListThawAll ();
1415 FcStrStaticNameFini ();
1416 FcObjectStaticNameFini ();
1419 static FcPatternEltPtr
1420 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1422 FcPatternEltPtr
new;
1423 new.bank
= FC_BANK_DYNAMIC
;
1428 static FcPatternEltPtr
1429 FcPatternEltPtrCreateStatic (int bank
, int i
)
1431 FcPatternEltPtr
new;
1438 FcStrNewBank (void);
1440 FcStrNeededBytes (const FcChar8
* s
);
1442 FcStrNeededBytesAlign (void);
1444 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1445 static const FcChar8
*
1446 FcStrSerialize (int bank
, const FcChar8
* s
);
1448 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1451 FcValueListNewBank (void);
1453 FcValueListNeededBytes (FcValueList
* vl
);
1455 FcValueListNeededBytesAlign (void);
1457 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1458 static FcValueListPtr
1459 FcValueListSerialize(int bank
, FcValueList
*pi
);
1461 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1465 FcPatternNewBank (void)
1467 fcpattern_count
= 0;
1468 fcpatternelt_count
= 0;
1471 FcValueListNewBank();
1475 FcPatternNeededBytes (FcPattern
* p
)
1480 fcpatternelt_count
+= p
->num
;
1482 for (i
= 0; i
< p
->num
; i
++)
1484 c
= FcValueListNeededBytes (FcValueListPtrU
1485 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1491 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1495 FcPatternNeededBytesAlign (void)
1497 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1498 FcValueListNeededBytesAlign ();
1502 FcPatternEnsureBank (int bi
)
1508 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1510 int new_count
= bi
+ 4;
1511 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1515 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1518 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1522 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1523 _fcPatternElts
= ep
;
1525 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1528 _fcPatternElts
[i
] = 0;
1531 fcpattern_bank_count
= new_count
;
1534 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1539 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1541 int bi
= FcCacheBankToIndex(metadata
->bank
);
1543 if (!FcPatternEnsureBank(bi
))
1547 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1548 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1549 block_ptr
= (void *)((char *)block_ptr
+
1550 (sizeof (FcPattern
) * fcpattern_count
));
1552 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1553 fcpatternelt_ptr
= 0;
1554 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1555 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1556 block_ptr
= (void *)((char *)block_ptr
+
1557 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1559 metadata
->pattern_count
= fcpattern_count
;
1560 metadata
->patternelt_count
= fcpatternelt_count
;
1562 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1563 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1568 FcPatternSerialize (int bank
, FcPattern
*old
)
1571 FcPatternElt
*e
, *nep
;
1573 FcValueListPtr v
, nv_head
, nvp
;
1574 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1576 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1578 elts
= fcpatternelt_ptr
;
1579 nep
= &_fcPatternElts
[bi
][elts
];
1583 fcpatternelt_ptr
+= old
->num
;
1585 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1588 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1589 if (!FcValueListPtrU(nv_head
))
1591 nv
= FcValueListPtrU(nvp
);
1595 v
= FcValueListPtrU(v
)->next
,
1596 nv
= FcValueListPtrU(nv
->next
))
1599 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1601 nvp
= FcValueListSerialize
1602 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1607 nep
[i
].values
= nv_head
;
1608 nep
[i
].object
= e
->object
;
1611 p
->elts
= old
->elts
;
1612 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1615 p
->ref
= FC_REF_CONSTANT
;
1620 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1622 int bi
= FcCacheBankToIndex(metadata
->bank
);
1623 if (!FcPatternEnsureBank(bi
))
1626 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1627 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1628 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1629 block_ptr
= (void *)((char *)block_ptr
+
1630 (sizeof (FcPattern
) * metadata
->pattern_count
));
1632 FcMemAlloc (FC_MEM_PATELT
,
1633 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1634 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1635 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1636 block_ptr
= (void *)((char *)block_ptr
+
1637 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1639 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1640 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1646 FcValueListNewBank (void)
1648 fcvaluelist_count
= 0;
1655 FcValueListNeededBytes (FcValueList
*p
)
1662 vl
= FcValueListPtrU(vl
->next
))
1664 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1669 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1672 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1675 cum
+= FcStrNeededBytes(v
.u
.s
);
1679 fcvaluelist_count
++;
1680 cum
+= sizeof (FcValueList
);
1687 FcValueListNeededBytesAlign (void)
1689 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1690 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1694 FcValueListEnsureBank (int bi
)
1698 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1700 int new_count
= bi
+ 2, i
;
1702 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1706 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1708 _fcValueLists
= pvl
;
1709 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1710 _fcValueLists
[i
] = 0;
1712 fcvaluelist_bank_count
= new_count
;
1718 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1720 int bi
= FcCacheBankToIndex(metadata
->bank
);
1722 if (!FcValueListEnsureBank(bi
))
1725 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1726 fcvaluelist_ptr
= 0;
1727 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1728 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1729 block_ptr
= (void *)((char *)block_ptr
+
1730 (sizeof (FcValueList
) * fcvaluelist_count
));
1731 metadata
->valuelist_count
= fcvaluelist_count
;
1733 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1734 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1739 static FcValueListPtr
1740 FcValueListSerialize(int bank
, FcValueList
*pi
)
1744 int bi
= FcCacheBankToIndex(bank
);
1748 new.bank
= FC_BANK_DYNAMIC
;
1753 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1755 new.u
.stat
= fcvaluelist_ptr
++;
1756 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1757 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1763 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1765 return FcValueListPtrCreateDynamic(pi
);
1766 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1767 v
->type
|= FC_STORAGE_STATIC
;
1775 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1777 return FcValueListPtrCreateDynamic(pi
);
1778 v
->u
.c_off
= (char *)c
- (char *)v
;
1779 v
->type
|= FC_STORAGE_STATIC
;
1785 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1787 return FcValueListPtrCreateDynamic(pi
);
1788 v
->u
.l_off
= (char *)l
- (char *)v
;
1789 v
->type
|= FC_STORAGE_STATIC
;
1799 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1801 int bi
= FcCacheBankToIndex(metadata
->bank
);
1803 if (!FcValueListEnsureBank(bi
))
1806 FcMemAlloc (FC_MEM_VALLIST
,
1807 sizeof (FcValueList
) * metadata
->valuelist_count
);
1808 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1809 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1810 block_ptr
= (void *)((char *)block_ptr
+
1811 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1813 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1814 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1820 FcValueListPtrCreateDynamic(FcValueList
* p
)
1824 r
.bank
= FC_BANK_DYNAMIC
;
1829 static FcChar8
** static_strs
;
1830 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1832 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1838 struct objectBucket
*b
, *next
;
1841 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1843 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1846 name
= (char *) (b
+ 1);
1847 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1848 FcMemFree (FC_MEM_STATICSTR
, size
);
1851 FcStrBuckets
[i
] = 0;
1858 FcStrNeededBytes (const FcChar8
* s
)
1860 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1861 struct objectBucket
**p
;
1862 struct objectBucket
*b
;
1865 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1866 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1868 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1870 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1875 strcpy ((char *) (b
+ 1), (char *)s
);
1877 /* Yes, the following line is convoluted. However, it is
1878 * incorrect to replace the with a memset, because the C
1879 * specification doesn't guarantee that the null pointer is
1880 * the same as the zero bit pattern. */
1881 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1884 fcstr_count
+= strlen((char *)s
) + 1;
1885 return strlen((char *)s
) + 1;
1889 FcStrNeededBytesAlign (void)
1891 return __alignof__ (char);
1895 FcStrEnsureBank (int bi
)
1899 if (!static_strs
|| static_str_bank_count
<= bi
)
1901 int new_count
= bi
+ 4, i
;
1902 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1906 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1909 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1911 static_str_bank_count
= new_count
;
1917 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1919 int bi
= FcCacheBankToIndex(metadata
->bank
);
1920 if (!FcStrEnsureBank(bi
))
1923 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1924 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1925 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1926 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1927 metadata
->str_count
= fcstr_count
;
1933 static const FcChar8
*
1934 FcStrSerialize (int bank
, const FcChar8
* s
)
1936 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1937 struct objectBucket
**p
;
1938 struct objectBucket
*b
;
1939 int bi
= FcCacheBankToIndex(bank
);
1941 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1942 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1944 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1947 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1948 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1949 fcstr_ptr
+= strlen((char *)s
) + 1;
1950 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1958 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
1960 int bi
= FcCacheBankToIndex(metadata
->bank
);
1961 if (!FcStrEnsureBank(bi
))
1964 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
1965 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1966 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1967 block_ptr
= (void *)((char *)block_ptr
+
1968 (sizeof (char) * metadata
->str_count
));
1973 /* we don't store these in the FcPattern itself because
1974 * we don't want to serialize the directory names */
1976 /* I suppose this should be cleaned, too... */
1977 typedef struct _FcPatternDirMapping
{
1980 } FcPatternDirMapping
;
1982 #define PATTERNDIR_HASH_SIZE 31
1983 static struct patternDirBucket
{
1984 struct patternDirBucket
*next
;
1985 FcPatternDirMapping m
;
1986 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
1989 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
1991 struct patternDirBucket
*pb
;
1993 /* N.B. FcPatternHash fails, since it's contents-based, not
1994 * address-based, and we're in the process of mutating the FcPattern. */
1995 for (pb
= &FcPatternDirBuckets
1996 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
1997 pb
->m
.p
!= p
&& pb
->next
;
2003 pb
->m
.fname
= fname
;
2007 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2010 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2014 pb
->next
->m
.fname
= fname
;
2018 FcPatternFindFullFname (const FcPattern
*p
)
2020 struct patternDirBucket
*pb
;
2022 for (pb
= &FcPatternDirBuckets
2023 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2032 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2035 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2036 FcPatternAddFullFname (new,
2038 ((FcChar8
*)FcPatternFindFullFname(orig
)));