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
;
38 FcPatternFindFullFname (const FcPattern
*p
);
39 static FcPatternEltPtr
40 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
);
42 /* If you are trying to duplicate an FcPattern which will be used for
43 * rendering, be aware that (internally) you also have to use
44 * FcPatternTransferFullFname to transfer the associated filename. If
45 * you are copying the font (externally) using FcPatternGetString,
46 * then everything's fine; this caveat only applies if you're copying
47 * the bits individually. */
50 FcPatternCreate (void)
54 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
57 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
60 p
->elts
= FcPatternEltPtrCreateDynamic(0);
61 p
->bank
= FC_BANK_DYNAMIC
;
67 FcValueDestroy (FcValue v
)
71 FcStrFree ((FcChar8
*) v
.u
.s
);
74 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
77 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
80 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
88 FcValueCanonicalize (const FcValue
*v
)
90 if (v
->type
& FC_STORAGE_STATIC
)
94 switch (v
->type
& ~FC_STORAGE_STATIC
)
97 new.u
.s
= fc_value_string(v
);
98 new.type
= FcTypeString
;
101 new.u
.c
= fc_value_charset(v
);
102 new.type
= FcTypeCharSet
;
105 new.u
.l
= fc_value_langset(v
);
106 new.type
= FcTypeLangSet
;
115 FcValueSave (FcValue v
)
119 v
.u
.s
= FcStrCopy (v
.u
.s
);
124 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
129 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
134 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
145 FcValueListDestroy (FcValueListPtr l
)
148 for (; FcValueListPtrU(l
); l
= next
)
150 switch (FcValueListPtrU(l
)->value
.type
) {
152 FcStrFree ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
);
155 FcMatrixFree ((FcMatrix
*)FcValueListPtrU(l
)->value
.u
.m
);
159 ((FcCharSet
*) (FcValueListPtrU(l
)->value
.u
.c
));
163 ((FcLangSet
*) (FcValueListPtrU(l
)->value
.u
.l
));
168 next
= FcValueListPtrU(l
)->next
;
169 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
170 if (l
.bank
== FC_BANK_DYNAMIC
)
176 FcValueEqual (FcValue va
, FcValue vb
)
178 if (va
.type
!= vb
.type
)
180 if (va
.type
== FcTypeInteger
)
182 va
.type
= FcTypeDouble
;
185 if (vb
.type
== FcTypeInteger
)
187 vb
.type
= FcTypeDouble
;
190 if (va
.type
!= vb
.type
)
197 return va
.u
.i
== vb
.u
.i
;
199 return va
.u
.d
== vb
.u
.d
;
201 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
203 return va
.u
.b
== vb
.u
.b
;
205 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
207 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
209 return va
.u
.f
== vb
.u
.f
;
211 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
217 FcDoubleHash (double d
)
227 FcStringHash (const FcChar8
*s
)
234 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
239 FcValueHash (const FcValue
*v0
)
241 FcValue v
= FcValueCanonicalize(v0
);
246 return (FcChar32
) v
.u
.i
;
248 return FcDoubleHash (v
.u
.d
);
250 return FcStringHash (v
.u
.s
);
252 return (FcChar32
) v
.u
.b
;
254 return (FcDoubleHash (v
.u
.m
->xx
) ^
255 FcDoubleHash (v
.u
.m
->xy
) ^
256 FcDoubleHash (v
.u
.m
->yx
) ^
257 FcDoubleHash (v
.u
.m
->yy
));
259 return (FcChar32
) v
.u
.c
->num
;
261 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
262 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
264 return FcLangSetHash (v
.u
.l
);
270 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
272 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
275 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
277 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
278 FcValueListPtrU(lb
)->value
))
280 la
= FcValueListPtrU(la
)->next
;
281 lb
= FcValueListPtrU(lb
)->next
;
283 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
289 FcValueListHash (FcValueListPtr l
)
293 while (FcValueListPtrU(l
))
295 hash
= ((hash
<< 1) | (hash
>> 31)) ^
296 FcValueHash (&FcValueListPtrU(l
)->value
);
297 l
= FcValueListPtrU(l
)->next
;
303 FcPatternDestroy (FcPattern
*p
)
307 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
310 if (FcPatternFindFullFname (p
))
312 FcStrFree ((FcChar8
*)FcPatternFindFullFname (p
));
313 FcPatternAddFullFname (p
, 0);
316 for (i
= 0; i
< p
->num
; i
++)
317 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
320 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
322 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
323 free (FcPatternEltU(p
->elts
));
324 p
->elts
= FcPatternEltPtrCreateDynamic(0);
327 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
331 #define FC_VALUE_LIST_HASH_SIZE 257
332 #define FC_PATTERN_HASH_SIZE 67
334 typedef struct _FcValueListEnt FcValueListEnt
;
336 struct _FcValueListEnt
{
337 FcValueListEnt
*next
;
342 typedef union _FcValueListAlign
{
347 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
348 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
349 static char FcValueListFrozenName
[][8] = {
362 FcValueListReport (void);
365 FcValueListReport (void)
369 printf ("Fc Frozen Values:\n");
370 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
371 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
372 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
373 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
376 static FcValueListEnt
*
377 FcValueListEntCreate (FcValueListPtr h
)
379 FcValueListAlign
*ea
;
387 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
389 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
390 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
391 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
392 // this leaks for some reason
393 ea
= malloc (sizeof (FcValueListAlign
));
396 new = malloc (n
* sizeof (FcValueList
));
399 memset(new, 0, n
* sizeof (FcValueList
));
400 FcMemAlloc (FC_MEM_VALLIST
, size
);
402 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
403 for (l
= h
; FcValueListPtrU(l
);
404 l
= FcValueListPtrU(l
)->next
, new++)
406 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
408 new->value
.type
= FcTypeString
;
409 new->value
.u
.s
= FcStrStaticName
410 (fc_value_string(&FcValueListPtrU(l
)->value
));
414 new->value
= FcValueSave (FcValueCanonicalize
415 (&FcValueListPtrU(l
)->value
));
417 new->binding
= FcValueListPtrU(l
)->binding
;
418 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
420 new->next
= FcValueListPtrCreateDynamic(new + 1);
424 new->next
= FcValueListPtrCreateDynamic(0);
431 FcValueListEntDestroy (FcValueListEnt
*e
)
435 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
437 /* XXX: We should perform these two operations with "size" as
438 computed in FcValueListEntCreate, but we don't have access to
439 that value here. Without this, the FcValueListFrozenBytes
440 values will be wrong as will the FcMemFree counts.
442 FcValueListFrozenBytes[e->list->value.type] -= size;
443 FcMemFree (FC_MEM_VALLIST, size);
446 for (l
= e
->list
; FcValueListPtrU(l
);
447 l
= FcValueListPtrU(l
)->next
)
449 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
450 FcValueDestroy (FcValueListPtrU(l
)->value
);
452 /* XXX: Are we being too chummy with the implementation here to
453 free(e) when it was actually the enclosing FcValueListAlign
454 that was allocated? */
458 static int FcValueListTotal
;
459 static int FcValueListUsed
;
461 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
463 static FcValueListPtr
464 FcValueListFreeze (FcValueListPtr l
)
466 FcChar32 hash
= FcValueListHash (l
);
467 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
471 for (ent
= *bucket
; ent
; ent
= ent
->next
)
473 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
477 ent
= FcValueListEntCreate (l
);
479 return FcValueListPtrCreateDynamic(0);
489 FcValueListThawAll (void)
492 FcValueListEnt
*ent
, *next
;
494 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
496 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
499 FcValueListEntDestroy (ent
);
501 FcValueListHashTable
[i
] = 0;
504 FcValueListTotal
= 0;
509 FcPatternBaseHash (FcPattern
*b
)
511 FcChar32 hash
= b
->num
;
514 for (i
= 0; i
< b
->num
; i
++)
515 hash
= ((hash
<< 1) | (hash
>> 31)) ^
516 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
520 typedef struct _FcPatternEnt FcPatternEnt
;
522 struct _FcPatternEnt
{
528 static int FcPatternTotal
;
529 static int FcPatternUsed
;
531 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
534 FcPatternBaseFreeze (FcPattern
*b
)
538 FcChar32 hash
= FcPatternBaseHash (b
);
539 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
544 for (ent
= *bucket
; ent
; ent
= ent
->next
)
546 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
548 for (i
= 0; i
< b
->num
; i
++)
550 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
551 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
553 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
554 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
563 * Compute size of pattern + elts
565 ent
= malloc (sizeof (FcPatternEnt
));
569 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
572 ep
= FcPatternCreate();
576 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
579 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
581 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
585 ep
->ref
= FC_REF_CONSTANT
;
587 for (i
= 0; i
< b
->num
; i
++)
589 (FcPatternEltU(ep
->elts
)+i
)->values
=
590 (FcPatternEltU(b
->elts
)+i
)->values
;
591 (FcPatternEltU(ep
->elts
)+i
)->object
=
592 (FcPatternEltU(b
->elts
)+i
)->object
;
595 if (FcPatternFindElt (b
, FC_FILE
))
596 FcPatternTransferFullFname (ep
, b
);
604 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
610 FcPatternBaseThawAll (void)
613 FcPatternEnt
*ent
, *next
;
615 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
617 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
622 FcPatternHashTable
[i
] = 0;
630 FcPatternFreeze (FcPattern
*p
)
632 FcPattern
*b
, *n
= 0;
636 if (p
->ref
== FC_REF_CONSTANT
)
639 b
= FcPatternCreate();
647 e
= malloc(b
->num
* sizeof (FcPatternElt
));
650 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
651 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
654 * Freeze object lists
656 for (i
= 0; i
< p
->num
; i
++)
658 (FcPatternEltU(b
->elts
)+i
)->object
=
659 (FcPatternEltU(p
->elts
)+i
)->object
;
660 (FcPatternEltU(b
->elts
)+i
)->values
=
661 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
662 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
666 if (FcPatternFindElt (p
, FC_FILE
))
667 FcPatternTransferFullFname (b
, p
);
672 n
= FcPatternBaseFreeze (b
);
674 if (FcDebug() & FC_DBG_MEMORY
)
676 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
677 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
681 free(FcPatternEltU(b
->elts
));
682 b
->elts
= FcPatternEltPtrCreateDynamic(0);
683 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
686 assert (FcPatternEqual (n
, p
));
692 FcPatternPosition (const FcPattern
*p
, const char *object
)
694 int low
, high
, mid
, c
;
697 obj
= FcObjectToPtr(object
);
704 mid
= (low
+ high
) >> 1;
705 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
719 FcPatternFindElt (const FcPattern
*p
, const char *object
)
721 int i
= FcPatternPosition (p
, object
);
724 return FcPatternEltU(p
->elts
)+i
;
728 FcPatternInsertElt (FcPattern
*p
, const char *object
)
733 i
= FcPatternPosition (p
, object
);
738 /* reallocate array */
739 if (p
->num
+ 1 >= p
->size
)
741 int s
= p
->size
+ 16;
742 if (FcPatternEltU(p
->elts
))
744 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
745 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
746 if (!e
) /* maybe it was mmapped */
748 e
= malloc(s
* sizeof (FcPatternElt
));
750 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
754 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
757 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
759 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
760 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
763 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
764 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
765 FcValueListPtrCreateDynamic(0);
771 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
772 FcPatternEltU(p
->elts
) + i
,
773 sizeof (FcPatternElt
) *
779 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
780 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
783 return FcPatternEltU(p
->elts
)+i
;
787 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
794 if (pa
->num
!= pb
->num
)
796 for (i
= 0; i
< pa
->num
; i
++)
798 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
799 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
801 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
802 (FcPatternEltU(pb
->elts
)+i
)->values
))
809 FcPatternHash (const FcPattern
*p
)
814 for (i
= 0; i
< p
->num
; i
++)
816 h
= (((h
<< 1) | (h
>> 31)) ^
817 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
818 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
824 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
826 FcPatternElt
*ea
, *eb
;
829 for (i
= 0; i
< os
->nobject
; i
++)
831 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
832 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
837 if (!FcValueListEqual (ea
->values
, eb
->values
))
850 FcPatternAddWithBinding (FcPattern
*p
,
853 FcValueBinding binding
,
857 FcValueListPtr
new, *prev
;
859 FcObjectPtr objectPtr
;
861 if (p
->ref
== FC_REF_CONSTANT
)
864 newp
= malloc (sizeof (FcValueList
));
868 memset(newp
, 0, sizeof (FcValueList
));
869 new = FcValueListPtrCreateDynamic(newp
);
870 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
872 value
= FcValueSave (value
);
873 if (value
.type
== FcTypeVoid
)
876 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
877 * speedup: only allow strings to be added under the FC_FAMILY,
878 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
879 * and charsets under FC_CHARSET key.
880 * This is slightly semantically different from the old behaviour,
881 * but fonts shouldn't be getting non-strings here anyway.
882 * a better hack would use FcBaseObjectTypes to check all objects. */
883 objectPtr
= FcObjectToPtr(object
);
884 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
885 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
886 || objectPtr
== FcObjectToPtr(FC_STYLE
)
887 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
888 && value
.type
!= FcTypeString
)
890 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
891 && value
.type
!= FcTypeCharSet
)
894 FcValueListPtrU(new)->value
= value
;
895 FcValueListPtrU(new)->binding
= binding
;
896 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
898 e
= FcPatternInsertElt (p
, object
);
904 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
910 FcValueListPtrU(new)->next
= e
->values
;
917 switch (value
.type
) {
919 FcStrFree ((FcChar8
*) value
.u
.s
);
922 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
925 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
928 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
934 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
935 free (FcValueListPtrU(new));
941 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
943 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
947 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
949 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
953 FcPatternDel (FcPattern
*p
, const char *object
)
957 e
= FcPatternFindElt (p
, object
);
962 FcValueListDestroy (e
->values
);
964 /* shuffle existing ones down */
966 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
967 sizeof (FcPatternElt
));
969 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
970 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
975 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
978 FcValueListPtr
*prev
, l
;
980 e
= FcPatternFindElt (p
, object
);
983 for (prev
= &e
->values
;
984 FcValueListPtrU(l
= *prev
);
985 prev
= &FcValueListPtrU(l
)->next
)
989 *prev
= FcValueListPtrU(l
)->next
;
990 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
991 FcValueListDestroy (l
);
992 if (!FcValueListPtrU(e
->values
))
993 FcPatternDel (p
, object
);
1002 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1006 v
.type
= FcTypeInteger
;
1008 return FcPatternAdd (p
, object
, v
, FcTrue
);
1012 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1016 v
.type
= FcTypeDouble
;
1018 return FcPatternAdd (p
, object
, v
, FcTrue
);
1023 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1027 v
.type
= FcTypeString
;
1028 v
.u
.s
= FcStrStaticName(s
);
1029 return FcPatternAdd (p
, object
, v
, FcTrue
);
1033 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1037 v
.type
= FcTypeMatrix
;
1039 return FcPatternAdd (p
, object
, v
, FcTrue
);
1044 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1048 v
.type
= FcTypeBool
;
1050 return FcPatternAdd (p
, object
, v
, FcTrue
);
1054 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1058 v
.type
= FcTypeCharSet
;
1059 v
.u
.c
= (FcCharSet
*)c
;
1060 return FcPatternAdd (p
, object
, v
, FcTrue
);
1064 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1068 v
.type
= FcTypeFTFace
;
1070 return FcPatternAdd (p
, object
, v
, FcTrue
);
1074 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1078 v
.type
= FcTypeLangSet
;
1079 v
.u
.l
= (FcLangSet
*)ls
;
1080 return FcPatternAdd (p
, object
, v
, FcTrue
);
1084 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1089 e
= FcPatternFindElt (p
, object
);
1091 return FcResultNoMatch
;
1092 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1096 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1097 return FcResultMatch
;
1101 return FcResultNoId
;
1105 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1110 r
= FcPatternGet (p
, object
, id
, &v
);
1111 if (r
!= FcResultMatch
)
1121 return FcResultTypeMismatch
;
1123 return FcResultMatch
;
1127 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1132 r
= FcPatternGet (p
, object
, id
, &v
);
1133 if (r
!= FcResultMatch
)
1140 *d
= (double) v
.u
.i
;
1143 return FcResultTypeMismatch
;
1145 return FcResultMatch
;
1149 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1154 r
= FcPatternGet (p
, object
, id
, &v
);
1155 if (r
!= FcResultMatch
)
1157 if (v
.type
!= FcTypeString
)
1158 return FcResultTypeMismatch
;
1160 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1162 const char *fn
, *fpath
;
1166 fn
= FcPatternFindFullFname(p
);
1169 *s
= (FcChar8
*) fn
;
1170 return FcResultMatch
;
1175 *s
= (FcChar8
*) v
.u
.s
;
1176 return FcResultMatch
;
1179 fpath
= FcCacheFindBankDir (p
->bank
);
1180 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1181 fname
= malloc (size
);
1183 return FcResultOutOfMemory
;
1185 FcMemAlloc (FC_MEM_STRING
, size
);
1186 strcpy ((char *)fname
, (char *)fpath
);
1187 strcat ((char *)fname
, "/");
1188 strcat ((char *)fname
, (char *)v
.u
.s
);
1190 FcPatternAddFullFname (p
, (const char *)fname
);
1191 *s
= (FcChar8
*)fname
;
1192 return FcResultMatch
;
1195 *s
= (FcChar8
*) v
.u
.s
;
1196 return FcResultMatch
;
1200 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1205 r
= FcPatternGet (p
, object
, id
, &v
);
1206 if (r
!= FcResultMatch
)
1208 if (v
.type
!= FcTypeMatrix
)
1209 return FcResultTypeMismatch
;
1210 *m
= (FcMatrix
*)v
.u
.m
;
1211 return FcResultMatch
;
1216 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1221 r
= FcPatternGet (p
, object
, id
, &v
);
1222 if (r
!= FcResultMatch
)
1224 if (v
.type
!= FcTypeBool
)
1225 return FcResultTypeMismatch
;
1227 return FcResultMatch
;
1231 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1236 r
= FcPatternGet (p
, object
, id
, &v
);
1237 if (r
!= FcResultMatch
)
1239 if (v
.type
!= FcTypeCharSet
)
1240 return FcResultTypeMismatch
;
1241 *c
= (FcCharSet
*)v
.u
.c
;
1242 return FcResultMatch
;
1246 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1251 r
= FcPatternGet (p
, object
, id
, &v
);
1252 if (r
!= FcResultMatch
)
1254 if (v
.type
!= FcTypeFTFace
)
1255 return FcResultTypeMismatch
;
1256 *f
= (FT_Face
) v
.u
.f
;
1257 return FcResultMatch
;
1261 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1266 r
= FcPatternGet (p
, object
, id
, &v
);
1267 if (r
!= FcResultMatch
)
1269 if (v
.type
!= FcTypeLangSet
)
1270 return FcResultTypeMismatch
;
1271 *ls
= (FcLangSet
*)v
.u
.l
;
1272 return FcResultMatch
;
1276 FcPatternDuplicate (const FcPattern
*orig
)
1283 new = FcPatternCreate ();
1287 e
= FcPatternEltU(orig
->elts
);
1289 for (i
= 0; i
< orig
->num
; i
++)
1291 for (l
= (e
+ i
)->values
;
1293 l
= FcValueListPtrU(l
)->next
)
1294 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1295 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1299 FcPatternTransferFullFname (new, orig
);
1304 FcPatternDestroy (new);
1310 FcPatternReference (FcPattern
*p
)
1312 if (p
->ref
!= FC_REF_CONSTANT
)
1317 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1321 FcPatternVapBuild (ret
, orig
, va
);
1326 FcPatternBuild (FcPattern
*orig
, ...)
1330 va_start (va
, orig
);
1331 FcPatternVapBuild (orig
, orig
, va
);
1337 * Add all of the elements in 's' to 'p'
1340 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1346 for (i
= 0; i
< s
->num
; i
++)
1348 e
= FcPatternEltU(s
->elts
)+i
;
1349 for (v
= e
->values
; FcValueListPtrU(v
);
1350 v
= FcValueListPtrU(v
)->next
)
1352 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1353 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1354 FcValueListPtrU(v
)->binding
, FcTrue
))
1361 #define OBJECT_HASH_SIZE 31
1362 static struct objectBucket
{
1363 struct objectBucket
*next
;
1365 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1368 FcStrStaticName (const FcChar8
*name
)
1370 FcChar32 hash
= FcStringHash (name
);
1371 struct objectBucket
**p
;
1372 struct objectBucket
*b
;
1375 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1376 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1377 return (FcChar8
*) (b
+ 1);
1378 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1379 b
= malloc (size
+ sizeof (int));
1380 /* workaround glibc bug which reads strlen in groups of 4 */
1381 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1386 strcpy ((char *) (b
+ 1), (char *)name
);
1388 return (FcChar8
*) (b
+ 1);
1392 FcStrStaticNameFini (void)
1395 struct objectBucket
*b
, *next
;
1398 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1400 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1403 name
= (char *) (b
+ 1);
1404 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1405 FcMemFree (FC_MEM_STATICSTR
, size
);
1408 FcObjectBuckets
[i
] = 0;
1413 FcPatternFini (void)
1415 FcPatternBaseThawAll ();
1416 FcValueListThawAll ();
1417 FcStrStaticNameFini ();
1418 FcObjectStaticNameFini ();
1421 static FcPatternEltPtr
1422 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1424 FcPatternEltPtr
new;
1425 new.bank
= FC_BANK_DYNAMIC
;
1430 static FcPatternEltPtr
1431 FcPatternEltPtrCreateStatic (int bank
, int i
)
1433 FcPatternEltPtr
new;
1440 FcStrNewBank (void);
1442 FcStrNeededBytes (const FcChar8
* s
);
1444 FcStrNeededBytesAlign (void);
1446 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1447 static const FcChar8
*
1448 FcStrSerialize (int bank
, const FcChar8
* s
);
1450 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1453 FcValueListNewBank (void);
1455 FcValueListNeededBytes (FcValueList
* vl
);
1457 FcValueListNeededBytesAlign (void);
1459 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1460 static FcValueListPtr
1461 FcValueListSerialize(int bank
, FcValueList
*pi
);
1463 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1467 FcPatternNewBank (void)
1469 fcpattern_count
= 0;
1470 fcpatternelt_count
= 0;
1473 FcValueListNewBank();
1477 FcPatternNeededBytes (FcPattern
* p
)
1482 fcpatternelt_count
+= p
->num
;
1484 for (i
= 0; i
< p
->num
; i
++)
1486 c
= FcValueListNeededBytes (FcValueListPtrU
1487 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1493 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1497 FcPatternNeededBytesAlign (void)
1499 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1500 FcValueListNeededBytesAlign ();
1504 FcPatternEnsureBank (int bi
)
1510 if (!fcpatterns
|| fcpattern_bank_count
<= bi
)
1512 int new_count
= bi
+ 4;
1513 pp
= realloc (fcpatterns
, sizeof (FcPattern
*) * new_count
);
1517 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1520 ep
= realloc (fcpatternelts
, sizeof (FcPatternElt
*) * new_count
);
1524 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1527 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1530 fcpatternelts
[i
] = 0;
1533 fcpattern_bank_count
= new_count
;
1536 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1541 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1543 int bi
= FcCacheBankToIndex(metadata
->bank
);
1545 if (!FcPatternEnsureBank(bi
))
1549 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1550 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1551 block_ptr
= (void *)((char *)block_ptr
+
1552 (sizeof (FcPattern
) * fcpattern_count
));
1554 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1555 fcpatternelt_ptr
= 0;
1556 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1557 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1558 block_ptr
= (void *)((char *)block_ptr
+
1559 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1561 metadata
->pattern_count
= fcpattern_count
;
1562 metadata
->patternelt_count
= fcpatternelt_count
;
1564 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1565 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1570 FcPatternSerialize (int bank
, FcPattern
*old
)
1573 FcPatternElt
*e
, *nep
;
1575 FcValueListPtr v
, nv_head
, nvp
;
1576 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1578 p
= &fcpatterns
[bi
][fcpattern_ptr
++];
1580 elts
= fcpatternelt_ptr
;
1581 nep
= &fcpatternelts
[bi
][elts
];
1585 fcpatternelt_ptr
+= old
->num
;
1587 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1590 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1591 if (!FcValueListPtrU(nv_head
))
1593 nv
= FcValueListPtrU(nvp
);
1597 v
= FcValueListPtrU(v
)->next
,
1598 nv
= FcValueListPtrU(nv
->next
))
1601 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1603 nvp
= FcValueListSerialize
1604 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1609 nep
[i
].values
= nv_head
;
1610 nep
[i
].object
= e
->object
;
1613 p
->elts
= old
->elts
;
1614 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1617 p
->ref
= FC_REF_CONSTANT
;
1622 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1624 int bi
= FcCacheBankToIndex(metadata
->bank
);
1625 if (!FcPatternEnsureBank(bi
))
1628 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1629 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1630 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1631 block_ptr
= (void *)((char *)block_ptr
+
1632 (sizeof (FcPattern
) * metadata
->pattern_count
));
1634 FcMemAlloc (FC_MEM_PATELT
,
1635 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1636 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1637 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1638 block_ptr
= (void *)((char *)block_ptr
+
1639 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1641 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1642 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1648 FcValueListNewBank (void)
1650 fcvaluelist_count
= 0;
1657 FcValueListNeededBytes (FcValueList
*p
)
1664 vl
= FcValueListPtrU(vl
->next
))
1666 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1671 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1674 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1677 cum
+= FcStrNeededBytes(v
.u
.s
);
1681 fcvaluelist_count
++;
1682 cum
+= sizeof (FcValueList
);
1689 FcValueListNeededBytesAlign (void)
1691 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1692 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1696 FcValueListEnsureBank (int bi
)
1700 if (!fcvaluelists
|| fcvaluelist_bank_count
<= bi
)
1702 int new_count
= bi
+ 2, i
;
1704 pvl
= realloc (fcvaluelists
, sizeof (FcValueList
*) * new_count
);
1708 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1711 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1712 fcvaluelists
[i
] = 0;
1714 fcvaluelist_bank_count
= new_count
;
1720 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1722 int bi
= FcCacheBankToIndex(metadata
->bank
);
1724 if (!FcValueListEnsureBank(bi
))
1727 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1728 fcvaluelist_ptr
= 0;
1729 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1730 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1731 block_ptr
= (void *)((char *)block_ptr
+
1732 (sizeof (FcValueList
) * fcvaluelist_count
));
1733 metadata
->valuelist_count
= fcvaluelist_count
;
1735 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1736 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1741 static FcValueListPtr
1742 FcValueListSerialize(int bank
, FcValueList
*pi
)
1746 int bi
= FcCacheBankToIndex(bank
);
1750 new.bank
= FC_BANK_DYNAMIC
;
1755 fcvaluelists
[bi
][fcvaluelist_ptr
] = *pi
;
1757 new.u
.stat
= fcvaluelist_ptr
++;
1758 fcvaluelists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1759 v
= &fcvaluelists
[bi
][new.u
.stat
].value
;
1765 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1767 return FcValueListPtrCreateDynamic(pi
);
1768 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1769 v
->type
|= FC_STORAGE_STATIC
;
1777 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1779 return FcValueListPtrCreateDynamic(pi
);
1780 v
->u
.c_off
= (char *)c
- (char *)v
;
1781 v
->type
|= FC_STORAGE_STATIC
;
1787 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1789 return FcValueListPtrCreateDynamic(pi
);
1790 v
->u
.l_off
= (char *)l
- (char *)v
;
1791 v
->type
|= FC_STORAGE_STATIC
;
1801 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1803 int bi
= FcCacheBankToIndex(metadata
->bank
);
1805 if (!FcValueListEnsureBank(bi
))
1808 FcMemAlloc (FC_MEM_VALLIST
,
1809 sizeof (FcValueList
) * metadata
->valuelist_count
);
1810 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1811 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1812 block_ptr
= (void *)((char *)block_ptr
+
1813 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1815 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1816 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1822 FcValueListPtrCreateDynamic(FcValueList
* p
)
1826 r
.bank
= FC_BANK_DYNAMIC
;
1831 static FcChar8
** static_strs
;
1832 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1834 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1840 struct objectBucket
*b
, *next
;
1843 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1845 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1848 name
= (char *) (b
+ 1);
1849 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1850 FcMemFree (FC_MEM_STATICSTR
, size
);
1853 FcStrBuckets
[i
] = 0;
1860 FcStrNeededBytes (const FcChar8
* s
)
1862 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1863 struct objectBucket
**p
;
1864 struct objectBucket
*b
;
1867 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1868 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1870 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1872 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1877 strcpy ((char *) (b
+ 1), (char *)s
);
1879 /* Yes, the following line is convoluted. However, it is
1880 * incorrect to replace the with a memset, because the C
1881 * specification doesn't guarantee that the null pointer is
1882 * the same as the zero bit pattern. */
1883 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1886 fcstr_count
+= strlen((char *)s
) + 1;
1887 return strlen((char *)s
) + 1;
1891 FcStrNeededBytesAlign (void)
1893 return __alignof__ (char);
1897 FcStrEnsureBank (int bi
)
1901 if (!static_strs
|| static_str_bank_count
<= bi
)
1903 int new_count
= bi
+ 4, i
;
1904 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1908 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1911 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1913 static_str_bank_count
= new_count
;
1919 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1921 int bi
= FcCacheBankToIndex(metadata
->bank
);
1922 if (!FcStrEnsureBank(bi
))
1925 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1926 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1927 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1928 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1929 metadata
->str_count
= fcstr_count
;
1935 static const FcChar8
*
1936 FcStrSerialize (int bank
, const FcChar8
* s
)
1938 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1939 struct objectBucket
**p
;
1940 struct objectBucket
*b
;
1941 int bi
= FcCacheBankToIndex(bank
);
1943 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1944 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1946 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1949 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1950 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1951 fcstr_ptr
+= strlen((char *)s
) + 1;
1952 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1960 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
1962 int bi
= FcCacheBankToIndex(metadata
->bank
);
1963 if (!FcStrEnsureBank(bi
))
1966 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
1967 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1968 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1969 block_ptr
= (void *)((char *)block_ptr
+
1970 (sizeof (char) * metadata
->str_count
));
1975 /* we don't store these in the FcPattern itself because
1976 * we don't want to serialize the directory names */
1978 /* I suppose this should be cleaned, too... */
1979 typedef struct _FcPatternDirMapping
{
1982 } FcPatternDirMapping
;
1984 #define PATTERNDIR_HASH_SIZE 31
1985 static struct patternDirBucket
{
1986 struct patternDirBucket
*next
;
1987 FcPatternDirMapping m
;
1988 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
1991 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
1993 struct patternDirBucket
*pb
;
1995 /* N.B. FcPatternHash fails, since it's contents-based, not
1996 * address-based, and we're in the process of mutating the FcPattern. */
1997 for (pb
= &FcPatternDirBuckets
1998 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
1999 pb
->m
.p
!= p
&& pb
->next
;
2005 pb
->m
.fname
= fname
;
2009 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2012 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2016 pb
->next
->m
.fname
= fname
;
2020 FcPatternFindFullFname (const FcPattern
*p
)
2022 struct patternDirBucket
*pb
;
2024 for (pb
= &FcPatternDirBuckets
2025 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2034 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2037 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2038 FcPatternAddFullFname (new,
2040 ((FcChar8
*)FcPatternFindFullFname(orig
)));