2 * $RCSId: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $
4 * Copyright © 2000 Keith Packard
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
30 static FcPattern
** _fcPatterns
= 0;
31 static int fcpattern_bank_count
= 0, fcpattern_ptr
, fcpattern_count
;
32 FcPatternElt
** _fcPatternElts
= 0;
33 static int fcpatternelt_ptr
, fcpatternelt_count
;
34 FcValueList
** _fcValueLists
= 0;
35 static int fcvaluelist_bank_count
= 0, fcvaluelist_ptr
, fcvaluelist_count
;
37 static FcPatternEltPtr
38 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
);
40 FcStrHashed (const FcChar8
*name
);
43 FcPatternFindFullFname (const FcPattern
*p
);
45 /* If you are trying to duplicate an FcPattern which will be used for
46 * rendering, be aware that (internally) you also have to use
47 * FcPatternTransferFullFname to transfer the associated filename. If
48 * you are copying the font (externally) using FcPatternGetString,
49 * then everything's fine; this caveat only applies if you're copying
50 * the bits individually. */
53 FcPatternCreate (void)
57 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
60 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
63 p
->elts
= FcPatternEltPtrCreateDynamic(0);
64 p
->bank
= FC_BANK_DYNAMIC
;
70 FcValueDestroy (FcValue v
)
74 if (!FcStrHashed (v
.u
.s
))
75 FcStrFree ((FcChar8
*) v
.u
.s
);
78 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
81 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
84 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
92 FcValueCanonicalize (const FcValue
*v
)
94 if (v
->type
& FC_STORAGE_STATIC
)
98 switch (v
->type
& ~FC_STORAGE_STATIC
)
101 new.u
.s
= fc_value_string(v
);
102 new.type
= FcTypeString
;
105 new.u
.c
= fc_value_charset(v
);
106 new.type
= FcTypeCharSet
;
109 new.u
.l
= fc_value_langset(v
);
110 new.type
= FcTypeLangSet
;
119 FcValueSave (FcValue v
)
123 v
.u
.s
= FcStrCopy (v
.u
.s
);
128 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
133 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
138 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
149 FcValueListDestroy (FcValueListPtr l
)
152 for (; FcValueListPtrU(l
); l
= next
)
154 switch (FcValueListPtrU(l
)->value
.type
) {
156 if (!FcStrHashed ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
))
157 FcStrFree ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
);
160 FcMatrixFree ((FcMatrix
*)FcValueListPtrU(l
)->value
.u
.m
);
164 ((FcCharSet
*) (FcValueListPtrU(l
)->value
.u
.c
));
168 ((FcLangSet
*) (FcValueListPtrU(l
)->value
.u
.l
));
173 next
= FcValueListPtrU(l
)->next
;
174 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
175 if (l
.bank
== FC_BANK_DYNAMIC
)
181 FcValueEqual (FcValue va
, FcValue vb
)
183 if (va
.type
!= vb
.type
)
185 if (va
.type
== FcTypeInteger
)
187 va
.type
= FcTypeDouble
;
190 if (vb
.type
== FcTypeInteger
)
192 vb
.type
= FcTypeDouble
;
195 if (va
.type
!= vb
.type
)
202 return va
.u
.i
== vb
.u
.i
;
204 return va
.u
.d
== vb
.u
.d
;
206 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
208 return va
.u
.b
== vb
.u
.b
;
210 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
212 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
214 return va
.u
.f
== vb
.u
.f
;
216 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
222 FcDoubleHash (double d
)
232 FcStringHash (const FcChar8
*s
)
239 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
244 FcValueHash (const FcValue
*v
)
246 switch (fc_storage_type(v
)) {
250 return (FcChar32
) v
->u
.i
;
252 return FcDoubleHash (v
->u
.d
);
254 return FcStringHash (fc_value_string(v
));
256 return (FcChar32
) v
->u
.b
;
258 return (FcDoubleHash (v
->u
.m
->xx
) ^
259 FcDoubleHash (v
->u
.m
->xy
) ^
260 FcDoubleHash (v
->u
.m
->yx
) ^
261 FcDoubleHash (v
->u
.m
->yy
));
263 return (FcChar32
) fc_value_charset(v
)->num
;
265 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
->u
.f
)->family_name
) ^
266 FcStringHash ((const FcChar8
*) ((FT_Face
) v
->u
.f
)->style_name
);
268 return FcLangSetHash (fc_value_langset(v
));
274 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
276 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
279 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
281 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
282 FcValueListPtrU(lb
)->value
))
284 la
= FcValueListPtrU(la
)->next
;
285 lb
= FcValueListPtrU(lb
)->next
;
287 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
293 FcValueListHash (FcValueListPtr l
)
298 for (l_ptrU
= FcValueListPtrU(l
); l_ptrU
;
299 l_ptrU
= FcValueListPtrU(l_ptrU
->next
))
301 hash
= ((hash
<< 1) | (hash
>> 31)) ^ FcValueHash (&l_ptrU
->value
);
307 FcPatternDestroy (FcPattern
*p
)
311 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
314 if (FcPatternFindFullFname (p
))
316 FcStrFree ((FcChar8
*)FcPatternFindFullFname (p
));
317 FcPatternAddFullFname (p
, 0);
320 for (i
= 0; i
< p
->num
; i
++)
321 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
324 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
326 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
327 free (FcPatternEltU(p
->elts
));
328 p
->elts
= FcPatternEltPtrCreateDynamic(0);
331 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
335 #define FC_VALUE_LIST_HASH_SIZE 257
336 #define FC_PATTERN_HASH_SIZE 67
338 typedef struct _FcValueListEnt FcValueListEnt
;
340 struct _FcValueListEnt
{
341 FcValueListEnt
*next
;
346 typedef union _FcValueListAlign
{
351 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
352 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
353 static char FcValueListFrozenName
[][8] = {
366 FcValueListReport (void);
369 FcValueListReport (void)
373 printf ("Fc Frozen Values:\n");
374 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
375 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
376 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
377 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
380 static FcValueListEnt
*
381 FcValueListEntCreate (FcValueListPtr h
)
383 FcValueListAlign
*ea
;
391 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
393 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
394 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
395 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
396 /* this leaks for some reason */
397 ea
= malloc (sizeof (FcValueListAlign
));
400 new = malloc (n
* sizeof (FcValueList
));
403 memset(new, 0, n
* sizeof (FcValueList
));
404 FcMemAlloc (FC_MEM_VALLIST
, size
);
406 e
->list
= FcValueListPtrCreateDynamic(new);
407 for (l
= h
; FcValueListPtrU(l
);
408 l
= FcValueListPtrU(l
)->next
, new++)
410 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
412 new->value
.type
= FcTypeString
;
413 new->value
.u
.s
= FcStrStaticName
414 (fc_value_string(&FcValueListPtrU(l
)->value
));
418 new->value
= FcValueSave (FcValueCanonicalize
419 (&FcValueListPtrU(l
)->value
));
421 new->binding
= FcValueListPtrU(l
)->binding
;
422 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
424 new->next
= FcValueListPtrCreateDynamic(new + 1);
428 new->next
= FcValueListPtrCreateDynamic(0);
435 FcValueListEntDestroy (FcValueListEnt
*e
)
439 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
441 /* XXX: We should perform these two operations with "size" as
442 computed in FcValueListEntCreate, but we don't have access to
443 that value here. Without this, the FcValueListFrozenBytes
444 values will be wrong as will the FcMemFree counts.
446 FcValueListFrozenBytes[e->list->value.type] -= size;
447 FcMemFree (FC_MEM_VALLIST, size);
450 for (l
= e
->list
; FcValueListPtrU(l
);
451 l
= FcValueListPtrU(l
)->next
)
453 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
454 FcValueDestroy (FcValueListPtrU(l
)->value
);
456 /* XXX: Are we being too chummy with the implementation here to
457 free(e) when it was actually the enclosing FcValueListAlign
458 that was allocated? */
462 static int FcValueListTotal
;
463 static int FcValueListUsed
;
465 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
467 static FcValueListPtr
468 FcValueListFreeze (FcValueListPtr l
)
470 FcChar32 hash
= FcValueListHash (l
);
471 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
475 for (ent
= *bucket
; ent
; ent
= ent
->next
)
477 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
481 ent
= FcValueListEntCreate (l
);
483 return FcValueListPtrCreateDynamic(0);
493 FcValueListThawAll (void)
496 FcValueListEnt
*ent
, *next
;
498 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
500 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
503 FcValueListEntDestroy (ent
);
505 FcValueListHashTable
[i
] = 0;
508 FcValueListTotal
= 0;
513 FcPatternBaseHash (FcPattern
*b
)
515 FcChar32 hash
= b
->num
;
518 for (i
= 0; i
< b
->num
; i
++)
519 hash
= ((hash
<< 1) | (hash
>> 31)) ^
520 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
524 typedef struct _FcPatternEnt FcPatternEnt
;
526 struct _FcPatternEnt
{
532 static int FcPatternTotal
;
533 static int FcPatternUsed
;
535 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
538 FcPatternBaseFreeze (FcPattern
*b
)
542 FcChar32 hash
= FcPatternBaseHash (b
);
543 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
548 for (ent
= *bucket
; ent
; ent
= ent
->next
)
550 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
552 for (i
= 0; i
< b
->num
; i
++)
554 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
555 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
557 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
558 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
567 * Compute size of pattern + elts
569 ent
= malloc (sizeof (FcPatternEnt
));
573 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
576 ep
= FcPatternCreate();
580 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
583 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
585 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
589 ep
->ref
= FC_REF_CONSTANT
;
591 for (i
= 0; i
< b
->num
; i
++)
593 (FcPatternEltU(ep
->elts
)+i
)->values
=
594 (FcPatternEltU(b
->elts
)+i
)->values
;
595 (FcPatternEltU(ep
->elts
)+i
)->object
=
596 (FcPatternEltU(b
->elts
)+i
)->object
;
599 if (FcPatternFindElt (b
, FC_FILE
))
600 FcPatternTransferFullFname (ep
, b
);
608 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
614 FcPatternBaseThawAll (void)
617 FcPatternEnt
*ent
, *next
;
619 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
621 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
626 FcPatternHashTable
[i
] = 0;
634 FcPatternFreeze (FcPattern
*p
)
636 FcPattern
*b
, *n
= 0;
640 if (p
->ref
== FC_REF_CONSTANT
)
643 b
= FcPatternCreate();
651 e
= malloc(b
->num
* sizeof (FcPatternElt
));
654 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
655 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
658 * Freeze object lists
660 for (i
= 0; i
< p
->num
; i
++)
662 (FcPatternEltU(b
->elts
)+i
)->object
=
663 (FcPatternEltU(p
->elts
)+i
)->object
;
664 (FcPatternEltU(b
->elts
)+i
)->values
=
665 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
666 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
670 if (FcPatternFindElt (p
, FC_FILE
))
671 FcPatternTransferFullFname (b
, p
);
676 n
= FcPatternBaseFreeze (b
);
678 if (FcDebug() & FC_DBG_MEMORY
)
680 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
681 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
685 free(FcPatternEltU(b
->elts
));
686 b
->elts
= FcPatternEltPtrCreateDynamic(0);
687 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
690 assert (FcPatternEqual (n
, p
));
696 FcPatternPosition (const FcPattern
*p
, const char *object
)
698 int low
, high
, mid
, c
;
701 obj
= FcObjectToPtr(object
);
708 mid
= (low
+ high
) >> 1;
709 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
723 FcPatternFindElt (const FcPattern
*p
, const char *object
)
725 int i
= FcPatternPosition (p
, object
);
728 return FcPatternEltU(p
->elts
)+i
;
732 FcPatternInsertElt (FcPattern
*p
, const char *object
)
737 i
= FcPatternPosition (p
, object
);
742 /* reallocate array */
743 if (p
->num
+ 1 >= p
->size
)
745 int s
= p
->size
+ 16;
746 if (FcPatternEltU(p
->elts
))
748 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
749 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
750 if (!e
) /* maybe it was mmapped */
752 e
= malloc(s
* sizeof (FcPatternElt
));
754 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
758 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
761 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
763 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
764 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
767 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
768 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
769 FcValueListPtrCreateDynamic(0);
775 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
776 FcPatternEltU(p
->elts
) + i
,
777 sizeof (FcPatternElt
) *
783 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
784 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
787 return FcPatternEltU(p
->elts
)+i
;
791 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
798 if (pa
->num
!= pb
->num
)
800 for (i
= 0; i
< pa
->num
; i
++)
802 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
803 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
805 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
806 (FcPatternEltU(pb
->elts
)+i
)->values
))
813 FcPatternHash (const FcPattern
*p
)
818 for (i
= 0; i
< p
->num
; i
++)
820 h
= (((h
<< 1) | (h
>> 31)) ^
821 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
822 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
828 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
830 FcPatternElt
*ea
, *eb
;
833 for (i
= 0; i
< os
->nobject
; i
++)
835 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
836 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
841 if (!FcValueListEqual (ea
->values
, eb
->values
))
854 FcPatternAddWithBinding (FcPattern
*p
,
857 FcValueBinding binding
,
861 FcValueListPtr
new, *prev
;
863 FcObjectPtr objectPtr
;
865 if (p
->ref
== FC_REF_CONSTANT
)
868 newp
= malloc (sizeof (FcValueList
));
872 memset(newp
, 0, sizeof (FcValueList
));
873 new = FcValueListPtrCreateDynamic(newp
);
874 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
876 if (value
.type
== FcTypeString
)
878 value
.u
.s
= FcStrStaticName (value
.u
.s
);
880 value
.type
= FcTypeVoid
;
883 value
= FcValueSave (value
);
884 if (value
.type
== FcTypeVoid
)
887 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
888 * speedup: only allow strings to be added under the FC_FAMILY,
889 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
890 * and charsets under FC_CHARSET key.
891 * This is slightly semantically different from the old behaviour,
892 * but fonts shouldn't be getting non-strings here anyway.
893 * a better hack would use FcBaseObjectTypes to check all objects. */
894 objectPtr
= FcObjectToPtr(object
);
895 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
896 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
897 || objectPtr
== FcObjectToPtr(FC_STYLE
)
898 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
899 && value
.type
!= FcTypeString
)
901 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
902 && value
.type
!= FcTypeCharSet
)
905 FcValueListPtrU(new)->value
= value
;
906 FcValueListPtrU(new)->binding
= binding
;
907 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
909 e
= FcPatternInsertElt (p
, object
);
915 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
921 FcValueListPtrU(new)->next
= e
->values
;
928 switch (value
.type
) {
930 FcStrFree ((FcChar8
*) value
.u
.s
);
933 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
936 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
939 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
945 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
946 free (FcValueListPtrU(new));
952 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
954 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
958 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
960 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
964 FcPatternDel (FcPattern
*p
, const char *object
)
968 e
= FcPatternFindElt (p
, object
);
973 FcValueListDestroy (e
->values
);
975 /* shuffle existing ones down */
977 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
978 sizeof (FcPatternElt
));
980 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
981 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
986 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
989 FcValueListPtr
*prev
, l
;
991 e
= FcPatternFindElt (p
, object
);
994 for (prev
= &e
->values
;
995 FcValueListPtrU(l
= *prev
);
996 prev
= &FcValueListPtrU(l
)->next
)
1000 *prev
= FcValueListPtrU(l
)->next
;
1001 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
1002 FcValueListDestroy (l
);
1003 if (!FcValueListPtrU(e
->values
))
1004 FcPatternDel (p
, object
);
1013 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1017 v
.type
= FcTypeInteger
;
1019 return FcPatternAdd (p
, object
, v
, FcTrue
);
1023 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1027 v
.type
= FcTypeDouble
;
1029 return FcPatternAdd (p
, object
, v
, FcTrue
);
1034 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1040 v
.type
= FcTypeVoid
;
1042 return FcPatternAdd (p
, object
, v
, FcTrue
);
1045 v
.type
= FcTypeString
;
1046 v
.u
.s
= FcStrStaticName(s
);
1047 return FcPatternAdd (p
, object
, v
, FcTrue
);
1051 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1055 v
.type
= FcTypeMatrix
;
1057 return FcPatternAdd (p
, object
, v
, FcTrue
);
1062 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1066 v
.type
= FcTypeBool
;
1068 return FcPatternAdd (p
, object
, v
, FcTrue
);
1072 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1076 v
.type
= FcTypeCharSet
;
1077 v
.u
.c
= (FcCharSet
*)c
;
1078 return FcPatternAdd (p
, object
, v
, FcTrue
);
1082 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1086 v
.type
= FcTypeFTFace
;
1088 return FcPatternAdd (p
, object
, v
, FcTrue
);
1092 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1096 v
.type
= FcTypeLangSet
;
1097 v
.u
.l
= (FcLangSet
*)ls
;
1098 return FcPatternAdd (p
, object
, v
, FcTrue
);
1102 FcPatternGetFile (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1104 const char *fn
, *fpath
;
1108 fn
= FcPatternFindFullFname(p
);
1111 *s
= (FcChar8
*) fn
;
1112 return FcResultMatch
;
1116 return FcResultMatch
;
1118 fpath
= FcCacheFindBankDir (p
->bank
);
1119 size
= strlen((char *)fpath
) + 1 + strlen ((char *)*s
) + 1;
1120 fname
= malloc (size
);
1122 return FcResultOutOfMemory
;
1124 FcMemAlloc (FC_MEM_STRING
, size
);
1125 strcpy ((char *)fname
, (char *)fpath
);
1126 strcat ((char *)fname
, "/");
1127 strcat ((char *)fname
, (char *)*s
);
1129 FcPatternAddFullFname (p
, (const char *)fname
);
1130 *s
= (FcChar8
*)fname
;
1131 return FcResultMatch
;
1135 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1140 e
= FcPatternFindElt (p
, object
);
1142 return FcResultNoMatch
;
1143 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1147 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1149 /* Pull the FC_FILE trick here too. */
1150 if (v
->type
== FcTypeString
&&
1151 FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1152 return FcPatternGetFile (p
, object
, id
, (FcChar8
**)&(v
->u
.s
));
1154 return FcResultMatch
;
1158 return FcResultNoId
;
1162 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1167 r
= FcPatternGet (p
, object
, id
, &v
);
1168 if (r
!= FcResultMatch
)
1178 return FcResultTypeMismatch
;
1180 return FcResultMatch
;
1184 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1189 r
= FcPatternGet (p
, object
, id
, &v
);
1190 if (r
!= FcResultMatch
)
1197 *d
= (double) v
.u
.i
;
1200 return FcResultTypeMismatch
;
1202 return FcResultMatch
;
1206 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1211 r
= FcPatternGet (p
, object
, id
, &v
);
1212 if (r
!= FcResultMatch
)
1214 if (v
.type
!= FcTypeString
)
1215 return FcResultTypeMismatch
;
1217 *s
= (FcChar8
*) v
.u
.s
;
1218 return FcResultMatch
;
1222 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1227 r
= FcPatternGet (p
, object
, id
, &v
);
1228 if (r
!= FcResultMatch
)
1230 if (v
.type
!= FcTypeMatrix
)
1231 return FcResultTypeMismatch
;
1232 *m
= (FcMatrix
*)v
.u
.m
;
1233 return FcResultMatch
;
1238 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1243 r
= FcPatternGet (p
, object
, id
, &v
);
1244 if (r
!= FcResultMatch
)
1246 if (v
.type
!= FcTypeBool
)
1247 return FcResultTypeMismatch
;
1249 return FcResultMatch
;
1253 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1258 r
= FcPatternGet (p
, object
, id
, &v
);
1259 if (r
!= FcResultMatch
)
1261 if (v
.type
!= FcTypeCharSet
)
1262 return FcResultTypeMismatch
;
1263 *c
= (FcCharSet
*)v
.u
.c
;
1264 return FcResultMatch
;
1268 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1273 r
= FcPatternGet (p
, object
, id
, &v
);
1274 if (r
!= FcResultMatch
)
1276 if (v
.type
!= FcTypeFTFace
)
1277 return FcResultTypeMismatch
;
1278 *f
= (FT_Face
) v
.u
.f
;
1279 return FcResultMatch
;
1283 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1288 r
= FcPatternGet (p
, object
, id
, &v
);
1289 if (r
!= FcResultMatch
)
1291 if (v
.type
!= FcTypeLangSet
)
1292 return FcResultTypeMismatch
;
1293 *ls
= (FcLangSet
*)v
.u
.l
;
1294 return FcResultMatch
;
1298 FcPatternDuplicate (const FcPattern
*orig
)
1305 new = FcPatternCreate ();
1309 e
= FcPatternEltU(orig
->elts
);
1311 for (i
= 0; i
< orig
->num
; i
++)
1313 for (l
= (e
+ i
)->values
;
1315 l
= FcValueListPtrU(l
)->next
)
1316 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1317 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1321 FcPatternTransferFullFname (new, orig
);
1326 FcPatternDestroy (new);
1332 FcPatternReference (FcPattern
*p
)
1334 if (p
->ref
!= FC_REF_CONSTANT
)
1339 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1343 FcPatternVapBuild (ret
, orig
, va
);
1348 FcPatternBuild (FcPattern
*orig
, ...)
1352 va_start (va
, orig
);
1353 FcPatternVapBuild (orig
, orig
, va
);
1359 * Add all of the elements in 's' to 'p'
1362 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1368 for (i
= 0; i
< s
->num
; i
++)
1370 e
= FcPatternEltU(s
->elts
)+i
;
1371 for (v
= e
->values
; FcValueListPtrU(v
);
1372 v
= FcValueListPtrU(v
)->next
)
1374 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1375 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1376 FcValueListPtrU(v
)->binding
, FcTrue
))
1383 #define OBJECT_HASH_SIZE 31
1384 static struct objectBucket
{
1385 struct objectBucket
*next
;
1387 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1390 FcStrHashed (const FcChar8
*name
)
1392 FcChar32 hash
= FcStringHash (name
);
1393 struct objectBucket
**p
;
1394 struct objectBucket
*b
;
1396 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1397 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1403 FcStrStaticName (const FcChar8
*name
)
1405 FcChar32 hash
= FcStringHash (name
);
1406 struct objectBucket
**p
;
1407 struct objectBucket
*b
;
1410 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1411 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1412 return (FcChar8
*) (b
+ 1);
1413 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1414 b
= malloc (size
+ sizeof (int));
1415 /* workaround glibc bug which reads strlen in groups of 4 */
1416 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1421 strcpy ((char *) (b
+ 1), (char *)name
);
1423 return (FcChar8
*) (b
+ 1);
1427 FcStrStaticNameFini (void)
1430 struct objectBucket
*b
, *next
;
1433 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1435 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1438 name
= (char *) (b
+ 1);
1439 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1440 FcMemFree (FC_MEM_STATICSTR
, size
);
1443 FcObjectBuckets
[i
] = 0;
1448 FcPatternFini (void)
1450 FcPatternBaseThawAll ();
1451 FcValueListThawAll ();
1452 FcStrStaticNameFini ();
1453 FcObjectStaticNameFini ();
1456 static FcPatternEltPtr
1457 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1459 FcPatternEltPtr
new;
1460 new.bank
= FC_BANK_DYNAMIC
;
1465 static FcPatternEltPtr
1466 FcPatternEltPtrCreateStatic (int bank
, int i
)
1468 FcPatternEltPtr
new;
1475 FcStrNewBank (void);
1477 FcStrNeededBytes (const FcChar8
* s
);
1479 FcStrNeededBytesAlign (void);
1481 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1482 static const FcChar8
*
1483 FcStrSerialize (int bank
, const FcChar8
* s
);
1485 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1488 FcValueListNewBank (void);
1490 FcValueListNeededBytes (FcValueList
* vl
);
1492 FcValueListNeededBytesAlign (void);
1494 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1495 static FcValueListPtr
1496 FcValueListSerialize(int bank
, FcValueList
*pi
);
1498 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1502 FcPatternNewBank (void)
1504 fcpattern_count
= 0;
1505 fcpatternelt_count
= 0;
1508 FcValueListNewBank();
1512 FcPatternNeededBytes (FcPattern
* p
)
1517 fcpatternelt_count
+= p
->num
;
1519 for (i
= 0; i
< p
->num
; i
++)
1521 c
= FcValueListNeededBytes (FcValueListPtrU
1522 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1528 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1532 FcPatternNeededBytesAlign (void)
1534 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1535 FcValueListNeededBytesAlign ();
1539 FcPatternEnsureBank (int bi
)
1545 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1547 int new_count
= bi
+ 4;
1548 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1552 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1555 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1559 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1560 _fcPatternElts
= ep
;
1562 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1565 _fcPatternElts
[i
] = 0;
1568 fcpattern_bank_count
= new_count
;
1571 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1576 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1578 int bi
= FcCacheBankToIndex(metadata
->bank
);
1580 if (!FcPatternEnsureBank(bi
))
1584 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1585 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1586 block_ptr
= (void *)((char *)block_ptr
+
1587 (sizeof (FcPattern
) * fcpattern_count
));
1589 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1590 fcpatternelt_ptr
= 0;
1591 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1592 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1593 block_ptr
= (void *)((char *)block_ptr
+
1594 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1596 metadata
->pattern_count
= fcpattern_count
;
1597 metadata
->patternelt_count
= fcpatternelt_count
;
1599 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1600 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1605 FcPatternSerialize (int bank
, FcPattern
*old
)
1608 FcPatternElt
*e
, *nep
;
1610 FcValueListPtr v
, nv_head
, nvp
;
1611 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1613 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1615 elts
= fcpatternelt_ptr
;
1616 nep
= &_fcPatternElts
[bi
][elts
];
1620 fcpatternelt_ptr
+= old
->num
;
1622 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1625 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1626 if (!FcValueListPtrU(nv_head
))
1628 nv
= FcValueListPtrU(nvp
);
1632 v
= FcValueListPtrU(v
)->next
,
1633 nv
= FcValueListPtrU(nv
->next
))
1636 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1638 nvp
= FcValueListSerialize
1639 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1644 nep
[i
].values
= nv_head
;
1645 nep
[i
].object
= e
->object
;
1648 p
->elts
= old
->elts
;
1649 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1652 p
->ref
= FC_REF_CONSTANT
;
1657 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1659 int bi
= FcCacheBankToIndex(metadata
->bank
);
1660 if (!FcPatternEnsureBank(bi
))
1663 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1664 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1665 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1666 block_ptr
= (void *)((char *)block_ptr
+
1667 (sizeof (FcPattern
) * metadata
->pattern_count
));
1669 FcMemAlloc (FC_MEM_PATELT
,
1670 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1671 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1672 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1673 block_ptr
= (void *)((char *)block_ptr
+
1674 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1676 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1677 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1683 FcValueListNewBank (void)
1685 fcvaluelist_count
= 0;
1692 FcValueListNeededBytes (FcValueList
*p
)
1699 vl
= FcValueListPtrU(vl
->next
))
1701 /* unserialize just in case */
1702 FcValue v
= FcValueCanonicalize(&vl
->value
);
1707 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1710 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1713 cum
+= FcStrNeededBytes(v
.u
.s
);
1717 fcvaluelist_count
++;
1718 cum
+= sizeof (FcValueList
);
1725 FcValueListNeededBytesAlign (void)
1727 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1728 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1732 FcValueListEnsureBank (int bi
)
1736 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1738 int new_count
= bi
+ 2, i
;
1740 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1744 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1746 _fcValueLists
= pvl
;
1747 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1748 _fcValueLists
[i
] = 0;
1750 fcvaluelist_bank_count
= new_count
;
1756 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1758 int bi
= FcCacheBankToIndex(metadata
->bank
);
1760 if (!FcValueListEnsureBank(bi
))
1763 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1764 fcvaluelist_ptr
= 0;
1765 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1766 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1767 block_ptr
= (void *)((char *)block_ptr
+
1768 (sizeof (FcValueList
) * fcvaluelist_count
));
1769 metadata
->valuelist_count
= fcvaluelist_count
;
1771 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1772 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1777 static FcValueListPtr
1778 FcValueListSerialize(int bank
, FcValueList
*pi
)
1782 int bi
= FcCacheBankToIndex(bank
);
1786 new.bank
= FC_BANK_DYNAMIC
;
1791 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1793 new.u
.stat
= fcvaluelist_ptr
++;
1794 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1795 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1801 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1803 return FcValueListPtrCreateDynamic(pi
);
1804 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1805 v
->type
|= FC_STORAGE_STATIC
;
1813 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1815 return FcValueListPtrCreateDynamic(pi
);
1816 v
->u
.c_off
= (char *)c
- (char *)v
;
1817 v
->type
|= FC_STORAGE_STATIC
;
1823 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1825 return FcValueListPtrCreateDynamic(pi
);
1826 v
->u
.l_off
= (char *)l
- (char *)v
;
1827 v
->type
|= FC_STORAGE_STATIC
;
1837 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1839 int bi
= FcCacheBankToIndex(metadata
->bank
);
1841 if (!FcValueListEnsureBank(bi
))
1844 FcMemAlloc (FC_MEM_VALLIST
,
1845 sizeof (FcValueList
) * metadata
->valuelist_count
);
1846 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1847 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1848 block_ptr
= (void *)((char *)block_ptr
+
1849 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1851 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1852 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1858 FcValueListPtrCreateDynamic(FcValueList
* p
)
1862 r
.bank
= FC_BANK_DYNAMIC
;
1867 static FcChar8
** static_strs
;
1868 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1870 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1876 struct objectBucket
*b
, *next
;
1879 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1881 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1884 name
= (char *) (b
+ 1);
1885 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1886 FcMemFree (FC_MEM_STATICSTR
, size
);
1889 FcStrBuckets
[i
] = 0;
1896 FcStrNeededBytes (const FcChar8
* s
)
1898 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1899 struct objectBucket
**p
;
1900 struct objectBucket
*b
;
1902 FcChar8
*const null
= 0;
1904 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1905 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1907 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1909 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1914 strcpy ((char *) (b
+ 1), (char *)s
);
1916 /* Yes, the following line is convoluted. However, it is
1917 * incorrect to replace the with a memset, because the C
1918 * specification doesn't guarantee that the null pointer is
1919 * the same as the zero bit pattern. */
1920 /* Misaligned pointers are not guaranteed to work, either! */
1921 memcpy (((char *) (b
+ 1) + strlen((char *)s
) + 1), &null
, sizeof (null
));
1924 fcstr_count
+= strlen((char *)s
) + 1;
1925 return strlen((char *)s
) + 1;
1929 FcStrNeededBytesAlign (void)
1931 return __alignof__ (char);
1935 FcStrEnsureBank (int bi
)
1939 if (!static_strs
|| static_str_bank_count
<= bi
)
1941 int new_count
= bi
+ 4, i
;
1942 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1946 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1949 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1951 static_str_bank_count
= new_count
;
1957 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1959 int bi
= FcCacheBankToIndex(metadata
->bank
);
1960 if (!FcStrEnsureBank(bi
))
1963 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1964 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1965 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1966 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1967 metadata
->str_count
= fcstr_count
;
1973 static const FcChar8
*
1974 FcStrSerialize (int bank
, const FcChar8
* s
)
1976 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1977 struct objectBucket
**p
;
1978 struct objectBucket
*b
;
1979 int bi
= FcCacheBankToIndex(bank
);
1981 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1982 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1985 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
1988 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1989 t
= static_strs
[bi
] + fcstr_ptr
;
1990 memcpy ((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1, &t
, sizeof (FcChar8
*));
1991 fcstr_ptr
+= strlen((char *)s
) + 1;
1992 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
2000 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
2002 int bi
= FcCacheBankToIndex(metadata
->bank
);
2003 if (!FcStrEnsureBank(bi
))
2006 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
2007 block_ptr
= ALIGN (block_ptr
, FcChar8
);
2008 static_strs
[bi
] = (FcChar8
*)block_ptr
;
2009 block_ptr
= (void *)((char *)block_ptr
+
2010 (sizeof (char) * metadata
->str_count
));
2015 /* we don't store these in the FcPattern itself because
2016 * we don't want to serialize the directory names */
2018 /* I suppose this should be cleaned upon termination, too... */
2019 typedef struct _FcPatternDirMapping
{
2022 } FcPatternDirMapping
;
2024 #define PATTERNDIR_HASH_SIZE 31
2025 static struct patternDirBucket
{
2026 struct patternDirBucket
*next
;
2027 FcPatternDirMapping m
;
2028 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
2031 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
2033 struct patternDirBucket
*pb
;
2035 /* N.B. FcPatternHash fails, since it's contents-based, not
2036 * address-based, and we're in the process of mutating the FcPattern. */
2037 for (pb
= &FcPatternDirBuckets
2038 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2039 pb
->m
.p
!= p
&& pb
->next
;
2045 pb
->m
.fname
= fname
;
2049 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2052 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2056 pb
->next
->m
.fname
= fname
;
2060 FcPatternFindFullFname (const FcPattern
*p
)
2062 struct patternDirBucket
*pb
;
2064 for (pb
= &FcPatternDirBuckets
2065 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2074 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2077 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2078 FcPatternAddFullFname (new,
2080 ((FcChar8
*)FcPatternFindFullFname(orig
)));