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 const 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
));
406 memset(new, 0, n
* sizeof (FcValueList
));
407 FcMemAlloc (FC_MEM_VALLIST
, size
);
409 e
->list
= FcValueListPtrCreateDynamic(new);
410 for (l
= h
; FcValueListPtrU(l
);
411 l
= FcValueListPtrU(l
)->next
, new++)
413 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
415 new->value
.type
= FcTypeString
;
416 new->value
.u
.s
= FcStrStaticName
417 (fc_value_string(&FcValueListPtrU(l
)->value
));
421 new->value
= FcValueSave (FcValueCanonicalize
422 (&FcValueListPtrU(l
)->value
));
424 new->binding
= FcValueListPtrU(l
)->binding
;
425 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
427 new->next
= FcValueListPtrCreateDynamic(new + 1);
431 new->next
= FcValueListPtrCreateDynamic(0);
438 FcValueListEntDestroy (FcValueListEnt
*e
)
442 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
444 /* XXX: We should perform these two operations with "size" as
445 computed in FcValueListEntCreate, but we don't have access to
446 that value here. Without this, the FcValueListFrozenBytes
447 values will be wrong as will the FcMemFree counts.
449 FcValueListFrozenBytes[e->list->value.type] -= size;
450 FcMemFree (FC_MEM_VALLIST, size);
453 for (l
= e
->list
; FcValueListPtrU(l
);
454 l
= FcValueListPtrU(l
)->next
)
456 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
457 FcValueDestroy (FcValueListPtrU(l
)->value
);
459 /* XXX: Are we being too chummy with the implementation here to
460 free(e) when it was actually the enclosing FcValueListAlign
461 that was allocated? */
465 static int FcValueListTotal
;
466 static int FcValueListUsed
;
468 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
470 static FcValueListPtr
471 FcValueListFreeze (FcValueListPtr l
)
473 FcChar32 hash
= FcValueListHash (l
);
474 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
478 for (ent
= *bucket
; ent
; ent
= ent
->next
)
480 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
484 ent
= FcValueListEntCreate (l
);
486 return FcValueListPtrCreateDynamic(0);
496 FcValueListThawAll (void)
499 FcValueListEnt
*ent
, *next
;
501 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
503 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
506 FcValueListEntDestroy (ent
);
508 FcValueListHashTable
[i
] = 0;
511 FcValueListTotal
= 0;
516 FcPatternBaseHash (FcPattern
*b
)
518 FcChar32 hash
= b
->num
;
521 for (i
= 0; i
< b
->num
; i
++)
522 hash
= ((hash
<< 1) | (hash
>> 31)) ^
523 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
527 typedef struct _FcPatternEnt FcPatternEnt
;
529 struct _FcPatternEnt
{
535 static int FcPatternTotal
;
536 static int FcPatternUsed
;
538 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
541 FcPatternBaseFreeze (FcPattern
*b
)
545 FcChar32 hash
= FcPatternBaseHash (b
);
546 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
551 for (ent
= *bucket
; ent
; ent
= ent
->next
)
553 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
555 for (i
= 0; i
< b
->num
; i
++)
557 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
558 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
560 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
561 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
570 * Compute size of pattern + elts
572 ent
= malloc (sizeof (FcPatternEnt
));
576 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
579 ep
= FcPatternCreate();
583 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
586 FcPatternDestroy (ep
);
589 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
591 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
595 ep
->ref
= FC_REF_CONSTANT
;
597 for (i
= 0; i
< b
->num
; i
++)
599 (FcPatternEltU(ep
->elts
)+i
)->values
=
600 (FcPatternEltU(b
->elts
)+i
)->values
;
601 (FcPatternEltU(ep
->elts
)+i
)->object
=
602 (FcPatternEltU(b
->elts
)+i
)->object
;
605 if (FcPatternFindElt (b
, FC_FILE
))
606 FcPatternTransferFullFname (ep
, b
);
614 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
620 FcPatternBaseThawAll (void)
623 FcPatternEnt
*ent
, *next
;
625 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
627 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
632 FcPatternHashTable
[i
] = 0;
640 FcPatternFreeze (FcPattern
*p
)
642 FcPattern
*b
, *n
= 0;
646 if (p
->ref
== FC_REF_CONSTANT
)
649 b
= FcPatternCreate();
657 e
= malloc(b
->num
* sizeof (FcPatternElt
));
660 FcPatternDestroy (b
);
663 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
664 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
667 * Freeze object lists
669 for (i
= 0; i
< p
->num
; i
++)
671 (FcPatternEltU(b
->elts
)+i
)->object
=
672 (FcPatternEltU(p
->elts
)+i
)->object
;
673 (FcPatternEltU(b
->elts
)+i
)->values
=
674 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
675 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
679 if (FcPatternFindElt (p
, FC_FILE
))
680 FcPatternTransferFullFname (b
, p
);
685 n
= FcPatternBaseFreeze (b
);
687 if (FcDebug() & FC_DBG_MEMORY
)
689 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
690 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
694 free(FcPatternEltU(b
->elts
));
695 b
->elts
= FcPatternEltPtrCreateDynamic(0);
696 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
699 assert (FcPatternEqual (n
, p
));
705 FcPatternPosition (const FcPattern
*p
, const char *object
)
707 int low
, high
, mid
, c
;
710 obj
= FcObjectToPtr(object
);
717 mid
= (low
+ high
) >> 1;
718 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
732 FcPatternFindElt (const FcPattern
*p
, const char *object
)
734 int i
= FcPatternPosition (p
, object
);
737 return FcPatternEltU(p
->elts
)+i
;
741 FcPatternInsertElt (FcPattern
*p
, const char *object
)
746 i
= FcPatternPosition (p
, object
);
751 /* reallocate array */
752 if (p
->num
+ 1 >= p
->size
)
754 int s
= p
->size
+ 16;
755 if (FcPatternEltU(p
->elts
))
757 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
758 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
759 if (!e
) /* maybe it was mmapped */
761 e
= malloc(s
* sizeof (FcPatternElt
));
763 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
767 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
770 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
772 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
773 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
776 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
777 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
778 FcValueListPtrCreateDynamic(0);
784 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
785 FcPatternEltU(p
->elts
) + i
,
786 sizeof (FcPatternElt
) *
792 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
793 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
796 return FcPatternEltU(p
->elts
)+i
;
800 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
807 if (pa
->num
!= pb
->num
)
809 for (i
= 0; i
< pa
->num
; i
++)
811 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
812 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
814 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
815 (FcPatternEltU(pb
->elts
)+i
)->values
))
822 FcPatternHash (const FcPattern
*p
)
827 for (i
= 0; i
< p
->num
; i
++)
829 h
= (((h
<< 1) | (h
>> 31)) ^
830 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
831 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
837 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
839 FcPatternElt
*ea
, *eb
;
842 for (i
= 0; i
< os
->nobject
; i
++)
844 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
845 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
850 if (!FcValueListEqual (ea
->values
, eb
->values
))
863 FcPatternAddWithBinding (FcPattern
*p
,
866 FcValueBinding binding
,
870 FcValueListPtr
new, *prev
;
872 FcObjectPtr objectPtr
;
874 if (p
->ref
== FC_REF_CONSTANT
)
877 newp
= malloc (sizeof (FcValueList
));
881 memset(newp
, 0, sizeof (FcValueList
));
882 new = FcValueListPtrCreateDynamic(newp
);
883 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
885 if (value
.type
== FcTypeString
)
887 value
.u
.s
= FcStrStaticName (value
.u
.s
);
889 value
.type
= FcTypeVoid
;
892 value
= FcValueSave (value
);
893 if (value
.type
== FcTypeVoid
)
896 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
897 * speedup: only allow strings to be added under the FC_FAMILY,
898 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
899 * and charsets under FC_CHARSET key.
900 * This is slightly semantically different from the old behaviour,
901 * but fonts shouldn't be getting non-strings here anyway.
902 * a better hack would use FcBaseObjectTypes to check all objects. */
903 objectPtr
= FcObjectToPtr(object
);
904 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
905 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
906 || objectPtr
== FcObjectToPtr(FC_STYLE
)
907 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
908 && value
.type
!= FcTypeString
)
910 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
911 && value
.type
!= FcTypeCharSet
)
914 FcValueListPtrU(new)->value
= value
;
915 FcValueListPtrU(new)->binding
= binding
;
916 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
918 e
= FcPatternInsertElt (p
, object
);
924 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
930 FcValueListPtrU(new)->next
= e
->values
;
937 switch (value
.type
) {
939 FcStrFree ((FcChar8
*) value
.u
.s
);
942 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
945 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
948 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
954 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
955 free (FcValueListPtrU(new));
961 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
963 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
967 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
969 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
973 FcPatternDel (FcPattern
*p
, const char *object
)
977 e
= FcPatternFindElt (p
, object
);
982 FcValueListDestroy (e
->values
);
984 /* shuffle existing ones down */
986 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
987 sizeof (FcPatternElt
));
989 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
990 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
995 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
998 FcValueListPtr
*prev
, l
;
1000 e
= FcPatternFindElt (p
, object
);
1003 for (prev
= &e
->values
;
1004 FcValueListPtrU(l
= *prev
);
1005 prev
= &FcValueListPtrU(l
)->next
)
1009 *prev
= FcValueListPtrU(l
)->next
;
1010 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
1011 FcValueListDestroy (l
);
1012 if (!FcValueListPtrU(e
->values
))
1013 FcPatternDel (p
, object
);
1022 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1026 v
.type
= FcTypeInteger
;
1028 return FcPatternAdd (p
, object
, v
, FcTrue
);
1032 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1036 v
.type
= FcTypeDouble
;
1038 return FcPatternAdd (p
, object
, v
, FcTrue
);
1043 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1049 v
.type
= FcTypeVoid
;
1051 return FcPatternAdd (p
, object
, v
, FcTrue
);
1054 v
.type
= FcTypeString
;
1055 v
.u
.s
= FcStrStaticName(s
);
1056 return FcPatternAdd (p
, object
, v
, FcTrue
);
1060 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1064 v
.type
= FcTypeMatrix
;
1066 return FcPatternAdd (p
, object
, v
, FcTrue
);
1071 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1075 v
.type
= FcTypeBool
;
1077 return FcPatternAdd (p
, object
, v
, FcTrue
);
1081 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1085 v
.type
= FcTypeCharSet
;
1086 v
.u
.c
= (FcCharSet
*)c
;
1087 return FcPatternAdd (p
, object
, v
, FcTrue
);
1091 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1095 v
.type
= FcTypeFTFace
;
1097 return FcPatternAdd (p
, object
, v
, FcTrue
);
1101 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1105 v
.type
= FcTypeLangSet
;
1106 v
.u
.l
= (FcLangSet
*)ls
;
1107 return FcPatternAdd (p
, object
, v
, FcTrue
);
1111 FcPatternGetFile (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1113 const char *fn
, *fpath
;
1117 fn
= FcPatternFindFullFname(p
);
1120 *s
= (FcChar8
*) fn
;
1121 return FcResultMatch
;
1125 return FcResultMatch
;
1127 fpath
= FcCacheFindBankDir (p
->bank
);
1128 size
= strlen((char *)fpath
) + 1 + strlen ((char *)*s
) + 1;
1129 fname
= malloc (size
);
1131 return FcResultOutOfMemory
;
1133 FcMemAlloc (FC_MEM_STRING
, size
);
1134 strcpy ((char *)fname
, (char *)fpath
);
1135 strcat ((char *)fname
, "/");
1136 strcat ((char *)fname
, (char *)*s
);
1138 FcPatternAddFullFname (p
, (const char *)fname
);
1139 *s
= (FcChar8
*)fname
;
1140 return FcResultMatch
;
1144 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1149 e
= FcPatternFindElt (p
, object
);
1151 return FcResultNoMatch
;
1152 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1156 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1158 /* Pull the FC_FILE trick here too. */
1159 if (v
->type
== FcTypeString
&&
1160 FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1161 return FcPatternGetFile (p
, object
, id
, (FcChar8
**)&(v
->u
.s
));
1163 return FcResultMatch
;
1167 return FcResultNoId
;
1171 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1176 r
= FcPatternGet (p
, object
, id
, &v
);
1177 if (r
!= FcResultMatch
)
1187 return FcResultTypeMismatch
;
1189 return FcResultMatch
;
1193 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1198 r
= FcPatternGet (p
, object
, id
, &v
);
1199 if (r
!= FcResultMatch
)
1206 *d
= (double) v
.u
.i
;
1209 return FcResultTypeMismatch
;
1211 return FcResultMatch
;
1215 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1220 r
= FcPatternGet (p
, object
, id
, &v
);
1221 if (r
!= FcResultMatch
)
1223 if (v
.type
!= FcTypeString
)
1224 return FcResultTypeMismatch
;
1226 *s
= (FcChar8
*) v
.u
.s
;
1227 return FcResultMatch
;
1231 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1236 r
= FcPatternGet (p
, object
, id
, &v
);
1237 if (r
!= FcResultMatch
)
1239 if (v
.type
!= FcTypeMatrix
)
1240 return FcResultTypeMismatch
;
1241 *m
= (FcMatrix
*)v
.u
.m
;
1242 return FcResultMatch
;
1247 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1252 r
= FcPatternGet (p
, object
, id
, &v
);
1253 if (r
!= FcResultMatch
)
1255 if (v
.type
!= FcTypeBool
)
1256 return FcResultTypeMismatch
;
1258 return FcResultMatch
;
1262 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1267 r
= FcPatternGet (p
, object
, id
, &v
);
1268 if (r
!= FcResultMatch
)
1270 if (v
.type
!= FcTypeCharSet
)
1271 return FcResultTypeMismatch
;
1272 *c
= (FcCharSet
*)v
.u
.c
;
1273 return FcResultMatch
;
1277 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1282 r
= FcPatternGet (p
, object
, id
, &v
);
1283 if (r
!= FcResultMatch
)
1285 if (v
.type
!= FcTypeFTFace
)
1286 return FcResultTypeMismatch
;
1287 *f
= (FT_Face
) v
.u
.f
;
1288 return FcResultMatch
;
1292 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1297 r
= FcPatternGet (p
, object
, id
, &v
);
1298 if (r
!= FcResultMatch
)
1300 if (v
.type
!= FcTypeLangSet
)
1301 return FcResultTypeMismatch
;
1302 *ls
= (FcLangSet
*)v
.u
.l
;
1303 return FcResultMatch
;
1307 FcPatternDuplicate (const FcPattern
*orig
)
1314 new = FcPatternCreate ();
1318 e
= FcPatternEltU(orig
->elts
);
1320 for (i
= 0; i
< orig
->num
; i
++)
1322 for (l
= (e
+ i
)->values
;
1324 l
= FcValueListPtrU(l
)->next
)
1325 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1326 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1330 FcPatternTransferFullFname (new, orig
);
1335 FcPatternDestroy (new);
1341 FcPatternReference (FcPattern
*p
)
1343 if (p
->ref
!= FC_REF_CONSTANT
)
1348 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1352 FcPatternVapBuild (ret
, orig
, va
);
1357 FcPatternBuild (FcPattern
*orig
, ...)
1361 va_start (va
, orig
);
1362 FcPatternVapBuild (orig
, orig
, va
);
1368 * Add all of the elements in 's' to 'p'
1371 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1377 for (i
= 0; i
< s
->num
; i
++)
1379 e
= FcPatternEltU(s
->elts
)+i
;
1380 for (v
= e
->values
; FcValueListPtrU(v
);
1381 v
= FcValueListPtrU(v
)->next
)
1383 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1384 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1385 FcValueListPtrU(v
)->binding
, FcTrue
))
1392 #define OBJECT_HASH_SIZE 31
1393 static struct objectBucket
{
1394 struct objectBucket
*next
;
1396 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1399 FcStrHashed (const FcChar8
*name
)
1401 FcChar32 hash
= FcStringHash (name
);
1402 struct objectBucket
**p
;
1403 struct objectBucket
*b
;
1405 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1406 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1412 FcStrStaticName (const FcChar8
*name
)
1414 FcChar32 hash
= FcStringHash (name
);
1415 struct objectBucket
**p
;
1416 struct objectBucket
*b
;
1419 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1420 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1421 return (FcChar8
*) (b
+ 1);
1422 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1423 b
= malloc (size
+ sizeof (int));
1424 /* workaround glibc bug which reads strlen in groups of 4 */
1425 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1430 strcpy ((char *) (b
+ 1), (char *)name
);
1432 return (FcChar8
*) (b
+ 1);
1436 FcStrStaticNameFini (void)
1439 struct objectBucket
*b
, *next
;
1442 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1444 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1447 name
= (char *) (b
+ 1);
1448 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1449 FcMemFree (FC_MEM_STATICSTR
, size
);
1452 FcObjectBuckets
[i
] = 0;
1457 FcPatternFini (void)
1459 FcPatternBaseThawAll ();
1460 FcValueListThawAll ();
1461 FcStrStaticNameFini ();
1462 FcObjectStaticNameFini ();
1465 static FcPatternEltPtr
1466 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1468 FcPatternEltPtr
new;
1469 new.bank
= FC_BANK_DYNAMIC
;
1474 static FcPatternEltPtr
1475 FcPatternEltPtrCreateStatic (int bank
, int i
)
1477 FcPatternEltPtr
new;
1484 FcStrNewBank (void);
1486 FcStrNeededBytes (const FcChar8
* s
);
1488 FcStrNeededBytesAlign (void);
1490 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1491 static const FcChar8
*
1492 FcStrSerialize (int bank
, const FcChar8
* s
);
1494 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1497 FcValueListNewBank (void);
1499 FcValueListNeededBytes (FcValueList
* vl
);
1501 FcValueListNeededBytesAlign (void);
1503 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1504 static FcValueListPtr
1505 FcValueListSerialize(int bank
, FcValueList
*pi
);
1507 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1511 FcPatternNewBank (void)
1513 fcpattern_count
= 0;
1514 fcpatternelt_count
= 0;
1517 FcValueListNewBank();
1521 FcPatternNeededBytes (FcPattern
* p
)
1526 fcpatternelt_count
+= p
->num
;
1528 for (i
= 0; i
< p
->num
; i
++)
1530 c
= FcValueListNeededBytes (FcValueListPtrU
1531 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1537 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1541 FcPatternNeededBytesAlign (void)
1543 return fc_alignof (FcPattern
) + fc_alignof (FcPatternElt
) +
1544 FcValueListNeededBytesAlign ();
1548 FcPatternEnsureBank (int bi
)
1554 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1556 int new_count
= bi
+ 4;
1557 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1561 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1564 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1568 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1569 _fcPatternElts
= ep
;
1571 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1574 _fcPatternElts
[i
] = 0;
1577 fcpattern_bank_count
= new_count
;
1580 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1585 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1587 int bi
= FcCacheBankToIndex(metadata
->bank
);
1589 if (!FcPatternEnsureBank(bi
))
1593 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1594 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1595 block_ptr
= (void *)((char *)block_ptr
+
1596 (sizeof (FcPattern
) * fcpattern_count
));
1598 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1599 fcpatternelt_ptr
= 0;
1600 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1601 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1602 block_ptr
= (void *)((char *)block_ptr
+
1603 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1605 metadata
->pattern_count
= fcpattern_count
;
1606 metadata
->patternelt_count
= fcpatternelt_count
;
1608 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1609 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1614 FcPatternSerialize (int bank
, FcPattern
*old
)
1617 FcPatternElt
*e
, *nep
;
1619 FcValueListPtr v
, nv_head
, nvp
;
1620 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1622 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1624 elts
= fcpatternelt_ptr
;
1625 nep
= &_fcPatternElts
[bi
][elts
];
1629 fcpatternelt_ptr
+= old
->num
;
1631 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1634 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1635 if (!FcValueListPtrU(nv_head
))
1637 nv
= FcValueListPtrU(nvp
);
1641 v
= FcValueListPtrU(v
)->next
,
1642 nv
= FcValueListPtrU(nv
->next
))
1645 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1647 nvp
= FcValueListSerialize
1648 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1653 nep
[i
].values
= nv_head
;
1654 nep
[i
].object
= e
->object
;
1657 p
->elts
= old
->elts
;
1658 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1661 p
->ref
= FC_REF_CONSTANT
;
1666 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1668 int bi
= FcCacheBankToIndex(metadata
->bank
);
1669 if (!FcPatternEnsureBank(bi
))
1672 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1673 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1674 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1675 block_ptr
= (void *)((char *)block_ptr
+
1676 (sizeof (FcPattern
) * metadata
->pattern_count
));
1678 FcMemAlloc (FC_MEM_PATELT
,
1679 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1680 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1681 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1682 block_ptr
= (void *)((char *)block_ptr
+
1683 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1685 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1686 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1692 FcValueListNewBank (void)
1694 fcvaluelist_count
= 0;
1701 FcValueListNeededBytes (FcValueList
*p
)
1708 vl
= FcValueListPtrU(vl
->next
))
1710 /* unserialize just in case */
1711 FcValue v
= FcValueCanonicalize(&vl
->value
);
1716 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1719 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1722 cum
+= FcStrNeededBytes(v
.u
.s
);
1726 fcvaluelist_count
++;
1727 cum
+= sizeof (FcValueList
);
1734 FcValueListNeededBytesAlign (void)
1736 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1737 FcStrNeededBytesAlign() + fc_alignof (FcValueList
);
1741 FcValueListEnsureBank (int bi
)
1745 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1747 int new_count
= bi
+ 2, i
;
1749 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1753 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1755 _fcValueLists
= pvl
;
1756 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1757 _fcValueLists
[i
] = 0;
1759 fcvaluelist_bank_count
= new_count
;
1765 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1767 int bi
= FcCacheBankToIndex(metadata
->bank
);
1769 if (!FcValueListEnsureBank(bi
))
1772 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1773 fcvaluelist_ptr
= 0;
1774 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1775 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1776 block_ptr
= (void *)((char *)block_ptr
+
1777 (sizeof (FcValueList
) * fcvaluelist_count
));
1778 metadata
->valuelist_count
= fcvaluelist_count
;
1780 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1781 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1786 static FcValueListPtr
1787 FcValueListSerialize(int bank
, FcValueList
*pi
)
1791 int bi
= FcCacheBankToIndex(bank
);
1795 new.bank
= FC_BANK_DYNAMIC
;
1800 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1802 new.u
.stat
= fcvaluelist_ptr
++;
1803 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1804 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1810 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1812 return FcValueListPtrCreateDynamic(pi
);
1813 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1814 v
->type
|= FC_STORAGE_STATIC
;
1822 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1824 return FcValueListPtrCreateDynamic(pi
);
1825 v
->u
.c_off
= (char *)c
- (char *)v
;
1826 v
->type
|= FC_STORAGE_STATIC
;
1832 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1834 return FcValueListPtrCreateDynamic(pi
);
1835 v
->u
.l_off
= (char *)l
- (char *)v
;
1836 v
->type
|= FC_STORAGE_STATIC
;
1846 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1848 int bi
= FcCacheBankToIndex(metadata
->bank
);
1850 if (!FcValueListEnsureBank(bi
))
1853 FcMemAlloc (FC_MEM_VALLIST
,
1854 sizeof (FcValueList
) * metadata
->valuelist_count
);
1855 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1856 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1857 block_ptr
= (void *)((char *)block_ptr
+
1858 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1860 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1861 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1867 FcValueListPtrCreateDynamic(FcValueList
* p
)
1871 r
.bank
= FC_BANK_DYNAMIC
;
1876 static FcChar8
** static_strs
;
1877 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1879 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1885 struct objectBucket
*b
, *next
;
1888 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1890 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1893 name
= (char *) (b
+ 1);
1894 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1895 FcMemFree (FC_MEM_STATICSTR
, size
);
1898 FcStrBuckets
[i
] = 0;
1905 FcStrNeededBytes (const FcChar8
* s
)
1907 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1908 struct objectBucket
**p
;
1909 struct objectBucket
*b
;
1911 FcChar8
*const null
= 0;
1913 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1914 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1916 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1918 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1923 strcpy ((char *) (b
+ 1), (char *)s
);
1925 /* Yes, the following line is convoluted. However, it is
1926 * incorrect to replace the with a memset, because the C
1927 * specification doesn't guarantee that the null pointer is
1928 * the same as the zero bit pattern. */
1929 /* Misaligned pointers are not guaranteed to work, either! */
1930 memcpy (((char *) (b
+ 1) + strlen((char *)s
) + 1), &null
, sizeof (null
));
1933 fcstr_count
+= strlen((char *)s
) + 1;
1934 return strlen((char *)s
) + 1;
1938 FcStrNeededBytesAlign (void)
1940 return fc_alignof (char);
1944 FcStrEnsureBank (int bi
)
1948 if (!static_strs
|| static_str_bank_count
<= bi
)
1950 int new_count
= bi
+ 4, i
;
1951 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1955 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1958 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1960 static_str_bank_count
= new_count
;
1966 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1968 int bi
= FcCacheBankToIndex(metadata
->bank
);
1969 if (!FcStrEnsureBank(bi
))
1972 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1973 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1974 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1975 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1976 metadata
->str_count
= fcstr_count
;
1982 static const FcChar8
*
1983 FcStrSerialize (int bank
, const FcChar8
* s
)
1985 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1986 struct objectBucket
**p
;
1987 struct objectBucket
*b
;
1988 int bi
= FcCacheBankToIndex(bank
);
1990 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1991 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1994 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
1997 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1998 t
= static_strs
[bi
] + fcstr_ptr
;
1999 memcpy ((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1, &t
, sizeof (FcChar8
*));
2000 fcstr_ptr
+= strlen((char *)s
) + 1;
2001 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
2009 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
2011 int bi
= FcCacheBankToIndex(metadata
->bank
);
2012 if (!FcStrEnsureBank(bi
))
2015 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
2016 block_ptr
= ALIGN (block_ptr
, FcChar8
);
2017 static_strs
[bi
] = (FcChar8
*)block_ptr
;
2018 block_ptr
= (void *)((char *)block_ptr
+
2019 (sizeof (char) * metadata
->str_count
));
2024 /* we don't store these in the FcPattern itself because
2025 * we don't want to serialize the directory names */
2027 /* I suppose this should be cleaned upon termination, too... */
2028 typedef struct _FcPatternDirMapping
{
2031 } FcPatternDirMapping
;
2033 #define PATTERNDIR_HASH_SIZE 31
2034 static struct patternDirBucket
{
2035 struct patternDirBucket
*next
;
2036 FcPatternDirMapping m
;
2037 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
2040 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
2042 struct patternDirBucket
*pb
;
2044 /* N.B. FcPatternHash fails, since it's contents-based, not
2045 * address-based, and we're in the process of mutating the FcPattern. */
2046 for (pb
= &FcPatternDirBuckets
2047 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2048 pb
->m
.p
!= p
&& pb
->next
;
2054 pb
->m
.fname
= fname
;
2058 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2061 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2065 pb
->next
->m
.fname
= fname
;
2069 FcPatternFindFullFname (const FcPattern
*p
)
2071 struct patternDirBucket
*pb
;
2073 for (pb
= &FcPatternDirBuckets
2074 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2083 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2086 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2087 FcPatternAddFullFname (new,
2089 ((FcChar8
*)FcPatternFindFullFname(orig
)));