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
);
41 FcPatternFindFullFname (const FcPattern
*p
);
43 /* If you are trying to duplicate an FcPattern which will be used for
44 * rendering, be aware that (internally) you also have to use
45 * FcPatternTransferFullFname to transfer the associated filename. If
46 * you are copying the font (externally) using FcPatternGetString,
47 * then everything's fine; this caveat only applies if you're copying
48 * the bits individually. */
51 FcPatternCreate (void)
55 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
58 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
61 p
->elts
= FcPatternEltPtrCreateDynamic(0);
62 p
->bank
= FC_BANK_DYNAMIC
;
68 FcValueDestroy (FcValue v
)
72 FcStrFree ((FcChar8
*) v
.u
.s
);
75 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
78 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
81 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
89 FcValueCanonicalize (const FcValue
*v
)
91 if (v
->type
& FC_STORAGE_STATIC
)
95 switch (v
->type
& ~FC_STORAGE_STATIC
)
98 new.u
.s
= fc_value_string(v
);
99 new.type
= FcTypeString
;
102 new.u
.c
= fc_value_charset(v
);
103 new.type
= FcTypeCharSet
;
106 new.u
.l
= fc_value_langset(v
);
107 new.type
= FcTypeLangSet
;
116 FcValueSave (FcValue v
)
120 v
.u
.s
= FcStrCopy (v
.u
.s
);
125 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
130 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
135 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
146 FcValueListDestroy (FcValueListPtr l
)
149 for (; FcValueListPtrU(l
); l
= next
)
151 switch (FcValueListPtrU(l
)->value
.type
) {
153 FcStrFree ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
);
156 FcMatrixFree ((FcMatrix
*)FcValueListPtrU(l
)->value
.u
.m
);
160 ((FcCharSet
*) (FcValueListPtrU(l
)->value
.u
.c
));
164 ((FcLangSet
*) (FcValueListPtrU(l
)->value
.u
.l
));
169 next
= FcValueListPtrU(l
)->next
;
170 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
171 if (l
.bank
== FC_BANK_DYNAMIC
)
177 FcValueEqual (FcValue va
, FcValue vb
)
179 if (va
.type
!= vb
.type
)
181 if (va
.type
== FcTypeInteger
)
183 va
.type
= FcTypeDouble
;
186 if (vb
.type
== FcTypeInteger
)
188 vb
.type
= FcTypeDouble
;
191 if (va
.type
!= vb
.type
)
198 return va
.u
.i
== vb
.u
.i
;
200 return va
.u
.d
== vb
.u
.d
;
202 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
204 return va
.u
.b
== vb
.u
.b
;
206 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
208 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
210 return va
.u
.f
== vb
.u
.f
;
212 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
218 FcDoubleHash (double d
)
228 FcStringHash (const FcChar8
*s
)
235 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
240 FcValueHash (const FcValue
*v0
)
242 FcValue v
= FcValueCanonicalize(v0
);
247 return (FcChar32
) v
.u
.i
;
249 return FcDoubleHash (v
.u
.d
);
251 return FcStringHash (v
.u
.s
);
253 return (FcChar32
) v
.u
.b
;
255 return (FcDoubleHash (v
.u
.m
->xx
) ^
256 FcDoubleHash (v
.u
.m
->xy
) ^
257 FcDoubleHash (v
.u
.m
->yx
) ^
258 FcDoubleHash (v
.u
.m
->yy
));
260 return (FcChar32
) v
.u
.c
->num
;
262 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
263 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
265 return FcLangSetHash (v
.u
.l
);
271 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
273 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
276 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
278 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
279 FcValueListPtrU(lb
)->value
))
281 la
= FcValueListPtrU(la
)->next
;
282 lb
= FcValueListPtrU(lb
)->next
;
284 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
290 FcValueListHash (FcValueListPtr l
)
294 while (FcValueListPtrU(l
))
296 hash
= ((hash
<< 1) | (hash
>> 31)) ^
297 FcValueHash (&FcValueListPtrU(l
)->value
);
298 l
= FcValueListPtrU(l
)->next
;
304 FcPatternDestroy (FcPattern
*p
)
308 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
311 if (FcPatternFindFullFname (p
))
313 FcStrFree ((FcChar8
*)FcPatternFindFullFname (p
));
314 FcPatternAddFullFname (p
, 0);
317 for (i
= 0; i
< p
->num
; i
++)
318 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
321 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
323 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
324 free (FcPatternEltU(p
->elts
));
325 p
->elts
= FcPatternEltPtrCreateDynamic(0);
328 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
332 #define FC_VALUE_LIST_HASH_SIZE 257
333 #define FC_PATTERN_HASH_SIZE 67
335 typedef struct _FcValueListEnt FcValueListEnt
;
337 struct _FcValueListEnt
{
338 FcValueListEnt
*next
;
343 typedef union _FcValueListAlign
{
348 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
349 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
350 static char FcValueListFrozenName
[][8] = {
363 FcValueListReport (void);
366 FcValueListReport (void)
370 printf ("Fc Frozen Values:\n");
371 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
372 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
373 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
374 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
377 static FcValueListEnt
*
378 FcValueListEntCreate (FcValueListPtr h
)
380 FcValueListAlign
*ea
;
388 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
390 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
391 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
392 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
393 // this leaks for some reason
394 ea
= malloc (sizeof (FcValueListAlign
));
397 new = malloc (n
* sizeof (FcValueList
));
400 memset(new, 0, n
* sizeof (FcValueList
));
401 FcMemAlloc (FC_MEM_VALLIST
, size
);
403 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
404 for (l
= h
; FcValueListPtrU(l
);
405 l
= FcValueListPtrU(l
)->next
, new++)
407 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
409 new->value
.type
= FcTypeString
;
410 new->value
.u
.s
= FcStrStaticName
411 (fc_value_string(&FcValueListPtrU(l
)->value
));
415 new->value
= FcValueSave (FcValueCanonicalize
416 (&FcValueListPtrU(l
)->value
));
418 new->binding
= FcValueListPtrU(l
)->binding
;
419 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
421 new->next
= FcValueListPtrCreateDynamic(new + 1);
425 new->next
= FcValueListPtrCreateDynamic(0);
432 FcValueListEntDestroy (FcValueListEnt
*e
)
436 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
438 /* XXX: We should perform these two operations with "size" as
439 computed in FcValueListEntCreate, but we don't have access to
440 that value here. Without this, the FcValueListFrozenBytes
441 values will be wrong as will the FcMemFree counts.
443 FcValueListFrozenBytes[e->list->value.type] -= size;
444 FcMemFree (FC_MEM_VALLIST, size);
447 for (l
= e
->list
; FcValueListPtrU(l
);
448 l
= FcValueListPtrU(l
)->next
)
450 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
451 FcValueDestroy (FcValueListPtrU(l
)->value
);
453 /* XXX: Are we being too chummy with the implementation here to
454 free(e) when it was actually the enclosing FcValueListAlign
455 that was allocated? */
459 static int FcValueListTotal
;
460 static int FcValueListUsed
;
462 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
464 static FcValueListPtr
465 FcValueListFreeze (FcValueListPtr l
)
467 FcChar32 hash
= FcValueListHash (l
);
468 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
472 for (ent
= *bucket
; ent
; ent
= ent
->next
)
474 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
478 ent
= FcValueListEntCreate (l
);
480 return FcValueListPtrCreateDynamic(0);
490 FcValueListThawAll (void)
493 FcValueListEnt
*ent
, *next
;
495 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
497 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
500 FcValueListEntDestroy (ent
);
502 FcValueListHashTable
[i
] = 0;
505 FcValueListTotal
= 0;
510 FcPatternBaseHash (FcPattern
*b
)
512 FcChar32 hash
= b
->num
;
515 for (i
= 0; i
< b
->num
; i
++)
516 hash
= ((hash
<< 1) | (hash
>> 31)) ^
517 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
521 typedef struct _FcPatternEnt FcPatternEnt
;
523 struct _FcPatternEnt
{
529 static int FcPatternTotal
;
530 static int FcPatternUsed
;
532 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
535 FcPatternBaseFreeze (FcPattern
*b
)
539 FcChar32 hash
= FcPatternBaseHash (b
);
540 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
545 for (ent
= *bucket
; ent
; ent
= ent
->next
)
547 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
549 for (i
= 0; i
< b
->num
; i
++)
551 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
552 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
554 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
555 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
564 * Compute size of pattern + elts
566 ent
= malloc (sizeof (FcPatternEnt
));
570 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
573 ep
= FcPatternCreate();
577 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
580 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
582 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
586 ep
->ref
= FC_REF_CONSTANT
;
588 for (i
= 0; i
< b
->num
; i
++)
590 (FcPatternEltU(ep
->elts
)+i
)->values
=
591 (FcPatternEltU(b
->elts
)+i
)->values
;
592 (FcPatternEltU(ep
->elts
)+i
)->object
=
593 (FcPatternEltU(b
->elts
)+i
)->object
;
596 if (FcPatternFindElt (b
, FC_FILE
))
597 FcPatternTransferFullFname (ep
, b
);
605 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
611 FcPatternBaseThawAll (void)
614 FcPatternEnt
*ent
, *next
;
616 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
618 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
623 FcPatternHashTable
[i
] = 0;
631 FcPatternFreeze (FcPattern
*p
)
633 FcPattern
*b
, *n
= 0;
637 if (p
->ref
== FC_REF_CONSTANT
)
640 b
= FcPatternCreate();
648 e
= malloc(b
->num
* sizeof (FcPatternElt
));
651 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
652 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
655 * Freeze object lists
657 for (i
= 0; i
< p
->num
; i
++)
659 (FcPatternEltU(b
->elts
)+i
)->object
=
660 (FcPatternEltU(p
->elts
)+i
)->object
;
661 (FcPatternEltU(b
->elts
)+i
)->values
=
662 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
663 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
667 if (FcPatternFindElt (p
, FC_FILE
))
668 FcPatternTransferFullFname (b
, p
);
673 n
= FcPatternBaseFreeze (b
);
675 if (FcDebug() & FC_DBG_MEMORY
)
677 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
678 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
682 free(FcPatternEltU(b
->elts
));
683 b
->elts
= FcPatternEltPtrCreateDynamic(0);
684 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
687 assert (FcPatternEqual (n
, p
));
693 FcPatternPosition (const FcPattern
*p
, const char *object
)
695 int low
, high
, mid
, c
;
698 obj
= FcObjectToPtr(object
);
705 mid
= (low
+ high
) >> 1;
706 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
720 FcPatternFindElt (const FcPattern
*p
, const char *object
)
722 int i
= FcPatternPosition (p
, object
);
725 return FcPatternEltU(p
->elts
)+i
;
729 FcPatternInsertElt (FcPattern
*p
, const char *object
)
734 i
= FcPatternPosition (p
, object
);
739 /* reallocate array */
740 if (p
->num
+ 1 >= p
->size
)
742 int s
= p
->size
+ 16;
743 if (FcPatternEltU(p
->elts
))
745 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
746 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
747 if (!e
) /* maybe it was mmapped */
749 e
= malloc(s
* sizeof (FcPatternElt
));
751 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
755 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
758 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
760 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
761 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
764 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
765 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
766 FcValueListPtrCreateDynamic(0);
772 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
773 FcPatternEltU(p
->elts
) + i
,
774 sizeof (FcPatternElt
) *
780 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
781 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
784 return FcPatternEltU(p
->elts
)+i
;
788 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
795 if (pa
->num
!= pb
->num
)
797 for (i
= 0; i
< pa
->num
; i
++)
799 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
800 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
802 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
803 (FcPatternEltU(pb
->elts
)+i
)->values
))
810 FcPatternHash (const FcPattern
*p
)
815 for (i
= 0; i
< p
->num
; i
++)
817 h
= (((h
<< 1) | (h
>> 31)) ^
818 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
819 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
825 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
827 FcPatternElt
*ea
, *eb
;
830 for (i
= 0; i
< os
->nobject
; i
++)
832 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
833 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
838 if (!FcValueListEqual (ea
->values
, eb
->values
))
851 FcPatternAddWithBinding (FcPattern
*p
,
854 FcValueBinding binding
,
858 FcValueListPtr
new, *prev
;
860 FcObjectPtr objectPtr
;
862 if (p
->ref
== FC_REF_CONSTANT
)
865 newp
= malloc (sizeof (FcValueList
));
869 memset(newp
, 0, sizeof (FcValueList
));
870 new = FcValueListPtrCreateDynamic(newp
);
871 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
873 value
= FcValueSave (value
);
874 if (value
.type
== FcTypeVoid
)
877 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
878 * speedup: only allow strings to be added under the FC_FAMILY,
879 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
880 * and charsets under FC_CHARSET key.
881 * This is slightly semantically different from the old behaviour,
882 * but fonts shouldn't be getting non-strings here anyway.
883 * a better hack would use FcBaseObjectTypes to check all objects. */
884 objectPtr
= FcObjectToPtr(object
);
885 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
886 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
887 || objectPtr
== FcObjectToPtr(FC_STYLE
)
888 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
889 && value
.type
!= FcTypeString
)
891 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
892 && value
.type
!= FcTypeCharSet
)
895 FcValueListPtrU(new)->value
= value
;
896 FcValueListPtrU(new)->binding
= binding
;
897 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
899 e
= FcPatternInsertElt (p
, object
);
905 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
911 FcValueListPtrU(new)->next
= e
->values
;
918 switch (value
.type
) {
920 FcStrFree ((FcChar8
*) value
.u
.s
);
923 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
926 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
929 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
935 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
936 free (FcValueListPtrU(new));
942 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
944 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
948 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
950 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
954 FcPatternDel (FcPattern
*p
, const char *object
)
958 e
= FcPatternFindElt (p
, object
);
963 FcValueListDestroy (e
->values
);
965 /* shuffle existing ones down */
967 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
968 sizeof (FcPatternElt
));
970 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
971 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
976 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
979 FcValueListPtr
*prev
, l
;
981 e
= FcPatternFindElt (p
, object
);
984 for (prev
= &e
->values
;
985 FcValueListPtrU(l
= *prev
);
986 prev
= &FcValueListPtrU(l
)->next
)
990 *prev
= FcValueListPtrU(l
)->next
;
991 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
992 FcValueListDestroy (l
);
993 if (!FcValueListPtrU(e
->values
))
994 FcPatternDel (p
, object
);
1003 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1007 v
.type
= FcTypeInteger
;
1009 return FcPatternAdd (p
, object
, v
, FcTrue
);
1013 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1017 v
.type
= FcTypeDouble
;
1019 return FcPatternAdd (p
, object
, v
, FcTrue
);
1024 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1028 v
.type
= FcTypeString
;
1029 v
.u
.s
= FcStrStaticName(s
);
1030 return FcPatternAdd (p
, object
, v
, FcTrue
);
1034 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1038 v
.type
= FcTypeMatrix
;
1040 return FcPatternAdd (p
, object
, v
, FcTrue
);
1045 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1049 v
.type
= FcTypeBool
;
1051 return FcPatternAdd (p
, object
, v
, FcTrue
);
1055 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1059 v
.type
= FcTypeCharSet
;
1060 v
.u
.c
= (FcCharSet
*)c
;
1061 return FcPatternAdd (p
, object
, v
, FcTrue
);
1065 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1069 v
.type
= FcTypeFTFace
;
1071 return FcPatternAdd (p
, object
, v
, FcTrue
);
1075 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1079 v
.type
= FcTypeLangSet
;
1080 v
.u
.l
= (FcLangSet
*)ls
;
1081 return FcPatternAdd (p
, object
, v
, FcTrue
);
1085 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1090 e
= FcPatternFindElt (p
, object
);
1092 return FcResultNoMatch
;
1093 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1097 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1098 return FcResultMatch
;
1102 return FcResultNoId
;
1106 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1111 r
= FcPatternGet (p
, object
, id
, &v
);
1112 if (r
!= FcResultMatch
)
1122 return FcResultTypeMismatch
;
1124 return FcResultMatch
;
1128 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1133 r
= FcPatternGet (p
, object
, id
, &v
);
1134 if (r
!= FcResultMatch
)
1141 *d
= (double) v
.u
.i
;
1144 return FcResultTypeMismatch
;
1146 return FcResultMatch
;
1150 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1155 r
= FcPatternGet (p
, object
, id
, &v
);
1156 if (r
!= FcResultMatch
)
1158 if (v
.type
!= FcTypeString
)
1159 return FcResultTypeMismatch
;
1161 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1163 const char *fn
, *fpath
;
1167 fn
= FcPatternFindFullFname(p
);
1170 *s
= (FcChar8
*) fn
;
1171 return FcResultMatch
;
1176 *s
= (FcChar8
*) v
.u
.s
;
1177 return FcResultMatch
;
1180 fpath
= FcCacheFindBankDir (p
->bank
);
1181 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1182 fname
= malloc (size
);
1184 return FcResultOutOfMemory
;
1186 FcMemAlloc (FC_MEM_STRING
, size
);
1187 strcpy ((char *)fname
, (char *)fpath
);
1188 strcat ((char *)fname
, "/");
1189 strcat ((char *)fname
, (char *)v
.u
.s
);
1191 FcPatternAddFullFname (p
, (const char *)fname
);
1192 *s
= (FcChar8
*)fname
;
1193 return FcResultMatch
;
1196 *s
= (FcChar8
*) v
.u
.s
;
1197 return FcResultMatch
;
1201 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1206 r
= FcPatternGet (p
, object
, id
, &v
);
1207 if (r
!= FcResultMatch
)
1209 if (v
.type
!= FcTypeMatrix
)
1210 return FcResultTypeMismatch
;
1211 *m
= (FcMatrix
*)v
.u
.m
;
1212 return FcResultMatch
;
1217 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1222 r
= FcPatternGet (p
, object
, id
, &v
);
1223 if (r
!= FcResultMatch
)
1225 if (v
.type
!= FcTypeBool
)
1226 return FcResultTypeMismatch
;
1228 return FcResultMatch
;
1232 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1237 r
= FcPatternGet (p
, object
, id
, &v
);
1238 if (r
!= FcResultMatch
)
1240 if (v
.type
!= FcTypeCharSet
)
1241 return FcResultTypeMismatch
;
1242 *c
= (FcCharSet
*)v
.u
.c
;
1243 return FcResultMatch
;
1247 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1252 r
= FcPatternGet (p
, object
, id
, &v
);
1253 if (r
!= FcResultMatch
)
1255 if (v
.type
!= FcTypeFTFace
)
1256 return FcResultTypeMismatch
;
1257 *f
= (FT_Face
) v
.u
.f
;
1258 return FcResultMatch
;
1262 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1267 r
= FcPatternGet (p
, object
, id
, &v
);
1268 if (r
!= FcResultMatch
)
1270 if (v
.type
!= FcTypeLangSet
)
1271 return FcResultTypeMismatch
;
1272 *ls
= (FcLangSet
*)v
.u
.l
;
1273 return FcResultMatch
;
1277 FcPatternDuplicate (const FcPattern
*orig
)
1284 new = FcPatternCreate ();
1288 e
= FcPatternEltU(orig
->elts
);
1290 for (i
= 0; i
< orig
->num
; i
++)
1292 for (l
= (e
+ i
)->values
;
1294 l
= FcValueListPtrU(l
)->next
)
1295 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1296 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1300 FcPatternTransferFullFname (new, orig
);
1305 FcPatternDestroy (new);
1311 FcPatternReference (FcPattern
*p
)
1313 if (p
->ref
!= FC_REF_CONSTANT
)
1318 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1322 FcPatternVapBuild (ret
, orig
, va
);
1327 FcPatternBuild (FcPattern
*orig
, ...)
1331 va_start (va
, orig
);
1332 FcPatternVapBuild (orig
, orig
, va
);
1338 * Add all of the elements in 's' to 'p'
1341 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1347 for (i
= 0; i
< s
->num
; i
++)
1349 e
= FcPatternEltU(s
->elts
)+i
;
1350 for (v
= e
->values
; FcValueListPtrU(v
);
1351 v
= FcValueListPtrU(v
)->next
)
1353 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1354 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1355 FcValueListPtrU(v
)->binding
, FcTrue
))
1362 #define OBJECT_HASH_SIZE 31
1363 static struct objectBucket
{
1364 struct objectBucket
*next
;
1366 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1369 FcStrStaticName (const FcChar8
*name
)
1371 FcChar32 hash
= FcStringHash (name
);
1372 struct objectBucket
**p
;
1373 struct objectBucket
*b
;
1376 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1377 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1378 return (FcChar8
*) (b
+ 1);
1379 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1380 b
= malloc (size
+ sizeof (int));
1381 /* workaround glibc bug which reads strlen in groups of 4 */
1382 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1387 strcpy ((char *) (b
+ 1), (char *)name
);
1389 return (FcChar8
*) (b
+ 1);
1393 FcStrStaticNameFini (void)
1396 struct objectBucket
*b
, *next
;
1399 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1401 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1404 name
= (char *) (b
+ 1);
1405 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1406 FcMemFree (FC_MEM_STATICSTR
, size
);
1409 FcObjectBuckets
[i
] = 0;
1414 FcPatternFini (void)
1416 FcPatternBaseThawAll ();
1417 FcValueListThawAll ();
1418 FcStrStaticNameFini ();
1419 FcObjectStaticNameFini ();
1422 static FcPatternEltPtr
1423 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1425 FcPatternEltPtr
new;
1426 new.bank
= FC_BANK_DYNAMIC
;
1431 static FcPatternEltPtr
1432 FcPatternEltPtrCreateStatic (int bank
, int i
)
1434 FcPatternEltPtr
new;
1441 FcStrNewBank (void);
1443 FcStrNeededBytes (const FcChar8
* s
);
1445 FcStrNeededBytesAlign (void);
1447 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1448 static const FcChar8
*
1449 FcStrSerialize (int bank
, const FcChar8
* s
);
1451 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1454 FcValueListNewBank (void);
1456 FcValueListNeededBytes (FcValueList
* vl
);
1458 FcValueListNeededBytesAlign (void);
1460 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1461 static FcValueListPtr
1462 FcValueListSerialize(int bank
, FcValueList
*pi
);
1464 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1468 FcPatternNewBank (void)
1470 fcpattern_count
= 0;
1471 fcpatternelt_count
= 0;
1474 FcValueListNewBank();
1478 FcPatternNeededBytes (FcPattern
* p
)
1483 fcpatternelt_count
+= p
->num
;
1485 for (i
= 0; i
< p
->num
; i
++)
1487 c
= FcValueListNeededBytes (FcValueListPtrU
1488 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1494 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1498 FcPatternNeededBytesAlign (void)
1500 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1501 FcValueListNeededBytesAlign ();
1505 FcPatternEnsureBank (int bi
)
1511 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1513 int new_count
= bi
+ 4;
1514 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1518 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1521 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1525 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1526 _fcPatternElts
= ep
;
1528 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1531 _fcPatternElts
[i
] = 0;
1534 fcpattern_bank_count
= new_count
;
1537 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1542 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1544 int bi
= FcCacheBankToIndex(metadata
->bank
);
1546 if (!FcPatternEnsureBank(bi
))
1550 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1551 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1552 block_ptr
= (void *)((char *)block_ptr
+
1553 (sizeof (FcPattern
) * fcpattern_count
));
1555 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1556 fcpatternelt_ptr
= 0;
1557 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1558 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1559 block_ptr
= (void *)((char *)block_ptr
+
1560 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1562 metadata
->pattern_count
= fcpattern_count
;
1563 metadata
->patternelt_count
= fcpatternelt_count
;
1565 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1566 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1571 FcPatternSerialize (int bank
, FcPattern
*old
)
1574 FcPatternElt
*e
, *nep
;
1576 FcValueListPtr v
, nv_head
, nvp
;
1577 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1579 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1581 elts
= fcpatternelt_ptr
;
1582 nep
= &_fcPatternElts
[bi
][elts
];
1586 fcpatternelt_ptr
+= old
->num
;
1588 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1591 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1592 if (!FcValueListPtrU(nv_head
))
1594 nv
= FcValueListPtrU(nvp
);
1598 v
= FcValueListPtrU(v
)->next
,
1599 nv
= FcValueListPtrU(nv
->next
))
1602 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1604 nvp
= FcValueListSerialize
1605 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1610 nep
[i
].values
= nv_head
;
1611 nep
[i
].object
= e
->object
;
1614 p
->elts
= old
->elts
;
1615 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1618 p
->ref
= FC_REF_CONSTANT
;
1623 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1625 int bi
= FcCacheBankToIndex(metadata
->bank
);
1626 if (!FcPatternEnsureBank(bi
))
1629 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1630 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1631 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1632 block_ptr
= (void *)((char *)block_ptr
+
1633 (sizeof (FcPattern
) * metadata
->pattern_count
));
1635 FcMemAlloc (FC_MEM_PATELT
,
1636 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1637 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1638 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1639 block_ptr
= (void *)((char *)block_ptr
+
1640 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1642 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1643 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1649 FcValueListNewBank (void)
1651 fcvaluelist_count
= 0;
1658 FcValueListNeededBytes (FcValueList
*p
)
1665 vl
= FcValueListPtrU(vl
->next
))
1667 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1672 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1675 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1678 cum
+= FcStrNeededBytes(v
.u
.s
);
1682 fcvaluelist_count
++;
1683 cum
+= sizeof (FcValueList
);
1690 FcValueListNeededBytesAlign (void)
1692 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1693 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1697 FcValueListEnsureBank (int bi
)
1701 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1703 int new_count
= bi
+ 2, i
;
1705 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1709 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1711 _fcValueLists
= pvl
;
1712 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1713 _fcValueLists
[i
] = 0;
1715 fcvaluelist_bank_count
= new_count
;
1721 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1723 int bi
= FcCacheBankToIndex(metadata
->bank
);
1725 if (!FcValueListEnsureBank(bi
))
1728 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1729 fcvaluelist_ptr
= 0;
1730 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1731 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1732 block_ptr
= (void *)((char *)block_ptr
+
1733 (sizeof (FcValueList
) * fcvaluelist_count
));
1734 metadata
->valuelist_count
= fcvaluelist_count
;
1736 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1737 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1742 static FcValueListPtr
1743 FcValueListSerialize(int bank
, FcValueList
*pi
)
1747 int bi
= FcCacheBankToIndex(bank
);
1751 new.bank
= FC_BANK_DYNAMIC
;
1756 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1758 new.u
.stat
= fcvaluelist_ptr
++;
1759 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1760 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1766 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1768 return FcValueListPtrCreateDynamic(pi
);
1769 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1770 v
->type
|= FC_STORAGE_STATIC
;
1778 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1780 return FcValueListPtrCreateDynamic(pi
);
1781 v
->u
.c_off
= (char *)c
- (char *)v
;
1782 v
->type
|= FC_STORAGE_STATIC
;
1788 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1790 return FcValueListPtrCreateDynamic(pi
);
1791 v
->u
.l_off
= (char *)l
- (char *)v
;
1792 v
->type
|= FC_STORAGE_STATIC
;
1802 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1804 int bi
= FcCacheBankToIndex(metadata
->bank
);
1806 if (!FcValueListEnsureBank(bi
))
1809 FcMemAlloc (FC_MEM_VALLIST
,
1810 sizeof (FcValueList
) * metadata
->valuelist_count
);
1811 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1812 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1813 block_ptr
= (void *)((char *)block_ptr
+
1814 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1816 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1817 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1823 FcValueListPtrCreateDynamic(FcValueList
* p
)
1827 r
.bank
= FC_BANK_DYNAMIC
;
1832 static FcChar8
** static_strs
;
1833 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1835 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1841 struct objectBucket
*b
, *next
;
1844 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1846 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1849 name
= (char *) (b
+ 1);
1850 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1851 FcMemFree (FC_MEM_STATICSTR
, size
);
1854 FcStrBuckets
[i
] = 0;
1861 FcStrNeededBytes (const FcChar8
* s
)
1863 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1864 struct objectBucket
**p
;
1865 struct objectBucket
*b
;
1868 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1869 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1871 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1873 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1878 strcpy ((char *) (b
+ 1), (char *)s
);
1880 /* Yes, the following line is convoluted. However, it is
1881 * incorrect to replace the with a memset, because the C
1882 * specification doesn't guarantee that the null pointer is
1883 * the same as the zero bit pattern. */
1884 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1887 fcstr_count
+= strlen((char *)s
) + 1;
1888 return strlen((char *)s
) + 1;
1892 FcStrNeededBytesAlign (void)
1894 return __alignof__ (char);
1898 FcStrEnsureBank (int bi
)
1902 if (!static_strs
|| static_str_bank_count
<= bi
)
1904 int new_count
= bi
+ 4, i
;
1905 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1909 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1912 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1914 static_str_bank_count
= new_count
;
1920 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1922 int bi
= FcCacheBankToIndex(metadata
->bank
);
1923 if (!FcStrEnsureBank(bi
))
1926 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1927 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1928 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1929 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1930 metadata
->str_count
= fcstr_count
;
1936 static const FcChar8
*
1937 FcStrSerialize (int bank
, const FcChar8
* s
)
1939 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1940 struct objectBucket
**p
;
1941 struct objectBucket
*b
;
1942 int bi
= FcCacheBankToIndex(bank
);
1944 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1945 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1947 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1950 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1951 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1952 fcstr_ptr
+= strlen((char *)s
) + 1;
1953 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1961 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
1963 int bi
= FcCacheBankToIndex(metadata
->bank
);
1964 if (!FcStrEnsureBank(bi
))
1967 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
1968 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1969 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1970 block_ptr
= (void *)((char *)block_ptr
+
1971 (sizeof (char) * metadata
->str_count
));
1976 /* we don't store these in the FcPattern itself because
1977 * we don't want to serialize the directory names */
1979 /* I suppose this should be cleaned, too... */
1980 typedef struct _FcPatternDirMapping
{
1983 } FcPatternDirMapping
;
1985 #define PATTERNDIR_HASH_SIZE 31
1986 static struct patternDirBucket
{
1987 struct patternDirBucket
*next
;
1988 FcPatternDirMapping m
;
1989 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
1992 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
1994 struct patternDirBucket
*pb
;
1996 /* N.B. FcPatternHash fails, since it's contents-based, not
1997 * address-based, and we're in the process of mutating the FcPattern. */
1998 for (pb
= &FcPatternDirBuckets
1999 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2000 pb
->m
.p
!= p
&& pb
->next
;
2006 pb
->m
.fname
= fname
;
2010 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2013 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2017 pb
->next
->m
.fname
= fname
;
2021 FcPatternFindFullFname (const FcPattern
*p
)
2023 struct patternDirBucket
*pb
;
2025 for (pb
= &FcPatternDirBuckets
2026 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2035 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2038 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2039 FcPatternAddFullFname (new,
2041 ((FcChar8
*)FcPatternFindFullFname(orig
)));