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 static FcPatternElt
** fcpatternelts
= 0;
33 static int fcpatternelt_ptr
, fcpatternelt_count
;
34 static 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
;
860 if (p
->ref
== FC_REF_CONSTANT
)
863 newp
= malloc (sizeof (FcValueList
));
867 memset(newp
, 0, sizeof (FcValueList
));
868 new = FcValueListPtrCreateDynamic(newp
);
869 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
871 value
= FcValueSave (value
);
872 if (value
.type
== FcTypeVoid
)
875 FcValueListPtrU(new)->value
= value
;
876 FcValueListPtrU(new)->binding
= binding
;
877 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
879 e
= FcPatternInsertElt (p
, object
);
885 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
891 FcValueListPtrU(new)->next
= e
->values
;
898 switch (value
.type
) {
900 FcStrFree ((FcChar8
*) value
.u
.s
);
903 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
906 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
909 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
915 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
916 free (FcValueListPtrU(new));
922 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
924 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
928 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
930 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
934 FcPatternDel (FcPattern
*p
, const char *object
)
938 e
= FcPatternFindElt (p
, object
);
943 FcValueListDestroy (e
->values
);
945 /* shuffle existing ones down */
947 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
948 sizeof (FcPatternElt
));
950 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
951 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
956 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
959 FcValueListPtr
*prev
, l
;
961 e
= FcPatternFindElt (p
, object
);
964 for (prev
= &e
->values
;
965 FcValueListPtrU(l
= *prev
);
966 prev
= &FcValueListPtrU(l
)->next
)
970 *prev
= FcValueListPtrU(l
)->next
;
971 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
972 FcValueListDestroy (l
);
973 if (!FcValueListPtrU(e
->values
))
974 FcPatternDel (p
, object
);
983 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
987 v
.type
= FcTypeInteger
;
989 return FcPatternAdd (p
, object
, v
, FcTrue
);
993 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
997 v
.type
= FcTypeDouble
;
999 return FcPatternAdd (p
, object
, v
, FcTrue
);
1004 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1008 v
.type
= FcTypeString
;
1009 v
.u
.s
= FcStrStaticName(s
);
1010 return FcPatternAdd (p
, object
, v
, FcTrue
);
1014 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1018 v
.type
= FcTypeMatrix
;
1020 return FcPatternAdd (p
, object
, v
, FcTrue
);
1025 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1029 v
.type
= FcTypeBool
;
1031 return FcPatternAdd (p
, object
, v
, FcTrue
);
1035 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1039 v
.type
= FcTypeCharSet
;
1040 v
.u
.c
= (FcCharSet
*)c
;
1041 return FcPatternAdd (p
, object
, v
, FcTrue
);
1045 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1049 v
.type
= FcTypeFTFace
;
1051 return FcPatternAdd (p
, object
, v
, FcTrue
);
1055 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1059 v
.type
= FcTypeLangSet
;
1060 v
.u
.l
= (FcLangSet
*)ls
;
1061 return FcPatternAdd (p
, object
, v
, FcTrue
);
1065 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1070 e
= FcPatternFindElt (p
, object
);
1072 return FcResultNoMatch
;
1073 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1077 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1078 return FcResultMatch
;
1082 return FcResultNoId
;
1086 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1091 r
= FcPatternGet (p
, object
, id
, &v
);
1092 if (r
!= FcResultMatch
)
1102 return FcResultTypeMismatch
;
1104 return FcResultMatch
;
1108 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1113 r
= FcPatternGet (p
, object
, id
, &v
);
1114 if (r
!= FcResultMatch
)
1121 *d
= (double) v
.u
.i
;
1124 return FcResultTypeMismatch
;
1126 return FcResultMatch
;
1130 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1135 r
= FcPatternGet (p
, object
, id
, &v
);
1136 if (r
!= FcResultMatch
)
1138 if (v
.type
!= FcTypeString
)
1139 return FcResultTypeMismatch
;
1141 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1143 const char *fn
, *fpath
;
1147 fn
= FcPatternFindFullFname(p
);
1150 *s
= (FcChar8
*) fn
;
1151 return FcResultMatch
;
1156 *s
= (FcChar8
*) v
.u
.s
;
1157 return FcResultMatch
;
1160 fpath
= FcCacheFindBankDir (p
->bank
);
1161 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1162 fname
= malloc (size
);
1164 return FcResultOutOfMemory
;
1166 FcMemAlloc (FC_MEM_STRING
, size
);
1167 strcpy ((char *)fname
, (char *)fpath
);
1168 strcat ((char *)fname
, "/");
1169 strcat ((char *)fname
, (char *)v
.u
.s
);
1171 FcPatternAddFullFname (p
, (const char *)fname
);
1172 *s
= (FcChar8
*)fname
;
1173 return FcResultMatch
;
1176 *s
= (FcChar8
*) v
.u
.s
;
1177 return FcResultMatch
;
1181 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1186 r
= FcPatternGet (p
, object
, id
, &v
);
1187 if (r
!= FcResultMatch
)
1189 if (v
.type
!= FcTypeMatrix
)
1190 return FcResultTypeMismatch
;
1191 *m
= (FcMatrix
*)v
.u
.m
;
1192 return FcResultMatch
;
1197 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1202 r
= FcPatternGet (p
, object
, id
, &v
);
1203 if (r
!= FcResultMatch
)
1205 if (v
.type
!= FcTypeBool
)
1206 return FcResultTypeMismatch
;
1208 return FcResultMatch
;
1212 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1217 r
= FcPatternGet (p
, object
, id
, &v
);
1218 if (r
!= FcResultMatch
)
1220 if (v
.type
!= FcTypeCharSet
)
1221 return FcResultTypeMismatch
;
1222 *c
= (FcCharSet
*)v
.u
.c
;
1223 return FcResultMatch
;
1227 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1232 r
= FcPatternGet (p
, object
, id
, &v
);
1233 if (r
!= FcResultMatch
)
1235 if (v
.type
!= FcTypeFTFace
)
1236 return FcResultTypeMismatch
;
1237 *f
= (FT_Face
) v
.u
.f
;
1238 return FcResultMatch
;
1242 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1247 r
= FcPatternGet (p
, object
, id
, &v
);
1248 if (r
!= FcResultMatch
)
1250 if (v
.type
!= FcTypeLangSet
)
1251 return FcResultTypeMismatch
;
1252 *ls
= (FcLangSet
*)v
.u
.l
;
1253 return FcResultMatch
;
1257 FcPatternDuplicate (const FcPattern
*orig
)
1264 new = FcPatternCreate ();
1268 e
= FcPatternEltU(orig
->elts
);
1270 for (i
= 0; i
< orig
->num
; i
++)
1272 for (l
= (e
+ i
)->values
;
1274 l
= FcValueListPtrU(l
)->next
)
1275 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1276 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1280 FcPatternTransferFullFname (new, orig
);
1285 FcPatternDestroy (new);
1291 FcPatternReference (FcPattern
*p
)
1293 if (p
->ref
!= FC_REF_CONSTANT
)
1298 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1302 FcPatternVapBuild (ret
, orig
, va
);
1307 FcPatternBuild (FcPattern
*orig
, ...)
1311 va_start (va
, orig
);
1312 FcPatternVapBuild (orig
, orig
, va
);
1318 * Add all of the elements in 's' to 'p'
1321 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1327 for (i
= 0; i
< s
->num
; i
++)
1329 e
= FcPatternEltU(s
->elts
)+i
;
1330 for (v
= e
->values
; FcValueListPtrU(v
);
1331 v
= FcValueListPtrU(v
)->next
)
1333 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1334 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1335 FcValueListPtrU(v
)->binding
, FcTrue
))
1342 #define OBJECT_HASH_SIZE 31
1343 static struct objectBucket
{
1344 struct objectBucket
*next
;
1346 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1349 FcStrStaticName (const FcChar8
*name
)
1351 FcChar32 hash
= FcStringHash (name
);
1352 struct objectBucket
**p
;
1353 struct objectBucket
*b
;
1356 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1357 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1358 return (FcChar8
*) (b
+ 1);
1359 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1360 b
= malloc (size
+ sizeof (int));
1361 /* workaround glibc bug which reads strlen in groups of 4 */
1362 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1367 strcpy ((char *) (b
+ 1), (char *)name
);
1369 return (FcChar8
*) (b
+ 1);
1373 FcStrStaticNameFini (void)
1376 struct objectBucket
*b
, *next
;
1379 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1381 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1384 name
= (char *) (b
+ 1);
1385 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1386 FcMemFree (FC_MEM_STATICSTR
, size
);
1389 FcObjectBuckets
[i
] = 0;
1394 FcPatternFini (void)
1396 FcPatternBaseThawAll ();
1397 FcValueListThawAll ();
1398 FcStrStaticNameFini ();
1399 FcObjectStaticNameFini ();
1403 FcPatternEltU (FcPatternEltPtr pei
)
1405 if (pei
.bank
== FC_BANK_DYNAMIC
)
1408 return &fcpatternelts
[FcCacheBankToIndex(pei
.bank
)][pei
.u
.stat
];
1411 static FcPatternEltPtr
1412 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1414 FcPatternEltPtr
new;
1415 new.bank
= FC_BANK_DYNAMIC
;
1420 static FcPatternEltPtr
1421 FcPatternEltPtrCreateStatic (int bank
, int i
)
1423 FcPatternEltPtr
new;
1430 FcStrNewBank (void);
1432 FcStrNeededBytes (const FcChar8
* s
);
1434 FcStrNeededBytesAlign (void);
1436 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1437 static const FcChar8
*
1438 FcStrSerialize (int bank
, const FcChar8
* s
);
1440 FcStrUnserialize (FcCache metadata
, void *block_ptr
);
1443 FcValueListNewBank (void);
1445 FcValueListNeededBytes (FcValueList
* vl
);
1447 FcValueListNeededBytesAlign (void);
1449 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1450 static FcValueListPtr
1451 FcValueListSerialize(int bank
, FcValueList
*pi
);
1453 FcValueListUnserialize (FcCache metadata
, void *block_ptr
);
1457 FcPatternNewBank (void)
1459 fcpattern_count
= 0;
1460 fcpatternelt_count
= 0;
1463 FcValueListNewBank();
1467 FcPatternNeededBytes (FcPattern
* p
)
1472 fcpatternelt_count
+= p
->num
;
1474 for (i
= 0; i
< p
->num
; i
++)
1476 c
= FcValueListNeededBytes (FcValueListPtrU
1477 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1483 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1487 FcPatternNeededBytesAlign (void)
1489 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1490 FcValueListNeededBytesAlign ();
1494 FcPatternEnsureBank (int bi
)
1500 if (!fcpatterns
|| fcpattern_bank_count
<= bi
)
1502 int new_count
= bi
+ 4;
1503 pp
= realloc (fcpatterns
, sizeof (FcPattern
*) * new_count
);
1507 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1510 ep
= realloc (fcpatternelts
, sizeof (FcPatternElt
*) * new_count
);
1514 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1517 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1520 fcpatternelts
[i
] = 0;
1523 fcpattern_bank_count
= new_count
;
1526 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1531 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1533 int bi
= FcCacheBankToIndex(metadata
->bank
);
1535 if (!FcPatternEnsureBank(bi
))
1539 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1540 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1541 block_ptr
= (void *)((char *)block_ptr
+
1542 (sizeof (FcPattern
) * fcpattern_count
));
1544 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1545 fcpatternelt_ptr
= 0;
1546 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1547 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1548 block_ptr
= (void *)((char *)block_ptr
+
1549 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1551 metadata
->pattern_count
= fcpattern_count
;
1552 metadata
->patternelt_count
= fcpatternelt_count
;
1554 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1555 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1560 FcPatternSerialize (int bank
, FcPattern
*old
)
1563 FcPatternElt
*e
, *nep
;
1565 FcValueListPtr v
, nv_head
, nvp
;
1566 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1568 p
= &fcpatterns
[bi
][fcpattern_ptr
++];
1570 elts
= fcpatternelt_ptr
;
1571 nep
= &fcpatternelts
[bi
][elts
];
1575 fcpatternelt_ptr
+= old
->num
;
1577 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1580 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1581 if (!FcValueListPtrU(nv_head
))
1583 nv
= FcValueListPtrU(nvp
);
1587 v
= FcValueListPtrU(v
)->next
,
1588 nv
= FcValueListPtrU(nv
->next
))
1591 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1593 nvp
= FcValueListSerialize
1594 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1599 nep
[i
].values
= nv_head
;
1600 nep
[i
].object
= e
->object
;
1603 p
->elts
= old
->elts
;
1604 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1607 p
->ref
= FC_REF_CONSTANT
;
1612 FcPatternUnserialize (FcCache metadata
, void *block_ptr
)
1614 int bi
= FcCacheBankToIndex(metadata
.bank
);
1615 if (!FcPatternEnsureBank(bi
))
1618 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
.pattern_count
);
1619 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1620 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1621 block_ptr
= (void *)((char *)block_ptr
+
1622 (sizeof (FcPattern
) * metadata
.pattern_count
));
1624 FcMemAlloc (FC_MEM_PATELT
,
1625 sizeof (FcPatternElt
) * metadata
.patternelt_count
);
1626 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1627 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1628 block_ptr
= (void *)((char *)block_ptr
+
1629 (sizeof (FcPatternElt
) * metadata
.patternelt_count
));
1631 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1632 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1638 FcValueListNewBank (void)
1640 fcvaluelist_count
= 0;
1647 FcValueListNeededBytes (FcValueList
*p
)
1654 vl
= FcValueListPtrU(vl
->next
))
1656 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1661 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1664 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1667 cum
+= FcStrNeededBytes(v
.u
.s
);
1671 fcvaluelist_count
++;
1672 cum
+= sizeof (FcValueList
);
1679 FcValueListNeededBytesAlign (void)
1681 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1682 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1686 FcValueListEnsureBank (int bi
)
1690 if (!fcvaluelists
|| fcvaluelist_bank_count
<= bi
)
1692 int new_count
= bi
+ 2, i
;
1694 pvl
= realloc (fcvaluelists
, sizeof (FcValueList
*) * new_count
);
1698 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1701 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1702 fcvaluelists
[i
] = 0;
1704 fcvaluelist_bank_count
= new_count
;
1710 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1712 int bi
= FcCacheBankToIndex(metadata
->bank
);
1714 if (!FcValueListEnsureBank(bi
))
1717 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1718 fcvaluelist_ptr
= 0;
1719 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1720 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1721 block_ptr
= (void *)((char *)block_ptr
+
1722 (sizeof (FcValueList
) * fcvaluelist_count
));
1723 metadata
->valuelist_count
= fcvaluelist_count
;
1725 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1726 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1731 static FcValueListPtr
1732 FcValueListSerialize(int bank
, FcValueList
*pi
)
1736 int bi
= FcCacheBankToIndex(bank
);
1740 new.bank
= FC_BANK_DYNAMIC
;
1745 fcvaluelists
[bi
][fcvaluelist_ptr
] = *pi
;
1747 new.u
.stat
= fcvaluelist_ptr
++;
1748 fcvaluelists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1749 v
= &fcvaluelists
[bi
][new.u
.stat
].value
;
1755 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1757 return FcValueListPtrCreateDynamic(pi
);
1758 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1759 v
->type
|= FC_STORAGE_STATIC
;
1767 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1769 return FcValueListPtrCreateDynamic(pi
);
1770 v
->u
.c_off
= (char *)c
- (char *)v
;
1771 v
->type
|= FC_STORAGE_STATIC
;
1777 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1779 return FcValueListPtrCreateDynamic(pi
);
1780 v
->u
.l_off
= (char *)l
- (char *)v
;
1781 v
->type
|= FC_STORAGE_STATIC
;
1791 FcValueListUnserialize (FcCache metadata
, void *block_ptr
)
1793 int bi
= FcCacheBankToIndex(metadata
.bank
);
1795 if (!FcValueListEnsureBank(bi
))
1798 FcMemAlloc (FC_MEM_VALLIST
,
1799 sizeof (FcValueList
) * metadata
.valuelist_count
);
1800 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1801 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1802 block_ptr
= (void *)((char *)block_ptr
+
1803 (sizeof (FcValueList
) * metadata
.valuelist_count
));
1805 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1806 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1812 FcValueListPtrU (FcValueListPtr pi
)
1814 if (pi
.bank
== FC_BANK_DYNAMIC
)
1817 return &fcvaluelists
[FcCacheBankToIndex(pi
.bank
)][pi
.u
.stat
];
1821 FcValueListPtrCreateDynamic(FcValueList
* p
)
1825 r
.bank
= FC_BANK_DYNAMIC
;
1830 static FcChar8
** static_strs
;
1831 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1833 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1839 struct objectBucket
*b
, *next
;
1842 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1844 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1847 name
= (char *) (b
+ 1);
1848 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1849 FcMemFree (FC_MEM_STATICSTR
, size
);
1852 FcStrBuckets
[i
] = 0;
1859 FcStrNeededBytes (const FcChar8
* s
)
1861 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1862 struct objectBucket
**p
;
1863 struct objectBucket
*b
;
1866 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1867 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1869 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1871 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1876 strcpy ((char *) (b
+ 1), (char *)s
);
1878 /* Yes, the following line is convoluted. However, it is
1879 * incorrect to replace the with a memset, because the C
1880 * specification doesn't guarantee that the null pointer is
1881 * the same as the zero bit pattern. */
1882 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1885 fcstr_count
+= strlen((char *)s
) + 1;
1886 return strlen((char *)s
) + 1;
1890 FcStrNeededBytesAlign (void)
1892 return __alignof__ (char);
1896 FcStrEnsureBank (int bi
)
1900 if (!static_strs
|| static_str_bank_count
<= bi
)
1902 int new_count
= bi
+ 4, i
;
1903 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1907 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1910 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1912 static_str_bank_count
= new_count
;
1918 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1920 int bi
= FcCacheBankToIndex(metadata
->bank
);
1921 if (!FcStrEnsureBank(bi
))
1924 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1925 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1926 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1927 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1928 metadata
->str_count
= fcstr_count
;
1934 static const FcChar8
*
1935 FcStrSerialize (int bank
, const FcChar8
* s
)
1937 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1938 struct objectBucket
**p
;
1939 struct objectBucket
*b
;
1940 int bi
= FcCacheBankToIndex(bank
);
1942 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1943 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1945 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1948 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1949 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1950 fcstr_ptr
+= strlen((char *)s
) + 1;
1951 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1959 FcStrUnserialize (FcCache metadata
, void *block_ptr
)
1961 int bi
= FcCacheBankToIndex(metadata
.bank
);
1962 if (!FcStrEnsureBank(bi
))
1965 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
.str_count
);
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
)));