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, *freeme
= 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
))
682 if (FcPatternFindElt (p
, FC_FILE
))
683 FcPatternTransferFullFname (b
, p
);
688 n
= FcPatternBaseFreeze (b
);
690 if (FcDebug() & FC_DBG_MEMORY
)
692 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
693 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
697 free(FcPatternEltU(b
->elts
));
698 b
->elts
= FcPatternEltPtrCreateDynamic(0);
699 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
702 FcPatternDestroy (freeme
);
704 assert (FcPatternEqual (n
, p
));
710 FcPatternPosition (const FcPattern
*p
, const char *object
)
712 int low
, high
, mid
, c
;
715 obj
= FcObjectToPtr(object
);
722 mid
= (low
+ high
) >> 1;
723 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
737 FcPatternFindElt (const FcPattern
*p
, const char *object
)
739 int i
= FcPatternPosition (p
, object
);
742 return FcPatternEltU(p
->elts
)+i
;
746 FcPatternInsertElt (FcPattern
*p
, const char *object
)
751 i
= FcPatternPosition (p
, object
);
756 /* reallocate array */
757 if (p
->num
+ 1 >= p
->size
)
759 int s
= p
->size
+ 16;
760 if (FcPatternEltU(p
->elts
))
762 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
763 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
764 if (!e
) /* maybe it was mmapped */
766 e
= malloc(s
* sizeof (FcPatternElt
));
768 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
772 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
775 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
777 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
778 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
781 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
782 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
783 FcValueListPtrCreateDynamic(0);
789 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
790 FcPatternEltU(p
->elts
) + i
,
791 sizeof (FcPatternElt
) *
797 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
798 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
801 return FcPatternEltU(p
->elts
)+i
;
805 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
812 if (pa
->num
!= pb
->num
)
814 for (i
= 0; i
< pa
->num
; i
++)
816 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
817 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
819 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
820 (FcPatternEltU(pb
->elts
)+i
)->values
))
827 FcPatternHash (const FcPattern
*p
)
832 for (i
= 0; i
< p
->num
; i
++)
834 h
= (((h
<< 1) | (h
>> 31)) ^
835 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
836 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
842 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
844 FcPatternElt
*ea
, *eb
;
847 for (i
= 0; i
< os
->nobject
; i
++)
849 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
850 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
855 if (!FcValueListEqual (ea
->values
, eb
->values
))
868 FcPatternAddWithBinding (FcPattern
*p
,
871 FcValueBinding binding
,
875 FcValueListPtr
new, *prev
;
877 FcObjectPtr objectPtr
;
879 if (p
->ref
== FC_REF_CONSTANT
)
882 newp
= malloc (sizeof (FcValueList
));
886 memset(newp
, 0, sizeof (FcValueList
));
887 new = FcValueListPtrCreateDynamic(newp
);
888 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
890 if (value
.type
== FcTypeString
)
892 value
.u
.s
= FcStrStaticName (value
.u
.s
);
894 value
.type
= FcTypeVoid
;
897 value
= FcValueSave (value
);
898 if (value
.type
== FcTypeVoid
)
901 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
902 * speedup: only allow strings to be added under the FC_FAMILY,
903 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
904 * and charsets under FC_CHARSET key.
905 * This is slightly semantically different from the old behaviour,
906 * but fonts shouldn't be getting non-strings here anyway.
907 * a better hack would use FcBaseObjectTypes to check all objects. */
908 objectPtr
= FcObjectToPtr(object
);
909 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
910 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
911 || objectPtr
== FcObjectToPtr(FC_STYLE
)
912 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
913 && value
.type
!= FcTypeString
)
915 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
916 && value
.type
!= FcTypeCharSet
)
919 FcValueListPtrU(new)->value
= value
;
920 FcValueListPtrU(new)->binding
= binding
;
921 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
923 e
= FcPatternInsertElt (p
, object
);
929 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
935 FcValueListPtrU(new)->next
= e
->values
;
942 switch (value
.type
) {
944 FcStrFree ((FcChar8
*) value
.u
.s
);
947 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
950 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
953 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
959 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
960 free (FcValueListPtrU(new));
966 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
968 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
972 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
974 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
978 FcPatternDel (FcPattern
*p
, const char *object
)
982 e
= FcPatternFindElt (p
, object
);
987 FcValueListDestroy (e
->values
);
989 /* shuffle existing ones down */
991 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
992 sizeof (FcPatternElt
));
994 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
995 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
1000 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
1003 FcValueListPtr
*prev
, l
;
1005 e
= FcPatternFindElt (p
, object
);
1008 for (prev
= &e
->values
;
1009 FcValueListPtrU(l
= *prev
);
1010 prev
= &FcValueListPtrU(l
)->next
)
1014 *prev
= FcValueListPtrU(l
)->next
;
1015 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
1016 FcValueListDestroy (l
);
1017 if (!FcValueListPtrU(e
->values
))
1018 FcPatternDel (p
, object
);
1027 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1031 v
.type
= FcTypeInteger
;
1033 return FcPatternAdd (p
, object
, v
, FcTrue
);
1037 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1041 v
.type
= FcTypeDouble
;
1043 return FcPatternAdd (p
, object
, v
, FcTrue
);
1048 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1054 v
.type
= FcTypeVoid
;
1056 return FcPatternAdd (p
, object
, v
, FcTrue
);
1059 v
.type
= FcTypeString
;
1060 v
.u
.s
= FcStrStaticName(s
);
1061 return FcPatternAdd (p
, object
, v
, FcTrue
);
1065 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1069 v
.type
= FcTypeMatrix
;
1071 return FcPatternAdd (p
, object
, v
, FcTrue
);
1076 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1080 v
.type
= FcTypeBool
;
1082 return FcPatternAdd (p
, object
, v
, FcTrue
);
1086 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1090 v
.type
= FcTypeCharSet
;
1091 v
.u
.c
= (FcCharSet
*)c
;
1092 return FcPatternAdd (p
, object
, v
, FcTrue
);
1096 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1100 v
.type
= FcTypeFTFace
;
1102 return FcPatternAdd (p
, object
, v
, FcTrue
);
1106 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1110 v
.type
= FcTypeLangSet
;
1111 v
.u
.l
= (FcLangSet
*)ls
;
1112 return FcPatternAdd (p
, object
, v
, FcTrue
);
1116 FcPatternGetFile (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1118 const char *fn
, *fpath
;
1122 fn
= FcPatternFindFullFname(p
);
1125 *s
= (FcChar8
*) fn
;
1126 return FcResultMatch
;
1130 return FcResultMatch
;
1132 fpath
= FcCacheFindBankDir (p
->bank
);
1133 size
= strlen((char *)fpath
) + 1 + strlen ((char *)*s
) + 1;
1134 fname
= malloc (size
);
1136 return FcResultOutOfMemory
;
1138 FcMemAlloc (FC_MEM_STRING
, size
);
1139 strcpy ((char *)fname
, (char *)fpath
);
1140 strcat ((char *)fname
, "/");
1141 strcat ((char *)fname
, (char *)*s
);
1143 FcPatternAddFullFname (p
, (const char *)fname
);
1144 *s
= (FcChar8
*)fname
;
1145 return FcResultMatch
;
1149 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1154 e
= FcPatternFindElt (p
, object
);
1156 return FcResultNoMatch
;
1157 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1161 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1163 /* Pull the FC_FILE trick here too. */
1164 if (v
->type
== FcTypeString
&&
1165 FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1166 return FcPatternGetFile (p
, object
, id
, (FcChar8
**)&(v
->u
.s
));
1168 return FcResultMatch
;
1172 return FcResultNoId
;
1176 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1181 r
= FcPatternGet (p
, object
, id
, &v
);
1182 if (r
!= FcResultMatch
)
1192 return FcResultTypeMismatch
;
1194 return FcResultMatch
;
1198 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1203 r
= FcPatternGet (p
, object
, id
, &v
);
1204 if (r
!= FcResultMatch
)
1211 *d
= (double) v
.u
.i
;
1214 return FcResultTypeMismatch
;
1216 return FcResultMatch
;
1220 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1225 r
= FcPatternGet (p
, object
, id
, &v
);
1226 if (r
!= FcResultMatch
)
1228 if (v
.type
!= FcTypeString
)
1229 return FcResultTypeMismatch
;
1231 *s
= (FcChar8
*) v
.u
.s
;
1232 return FcResultMatch
;
1236 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1241 r
= FcPatternGet (p
, object
, id
, &v
);
1242 if (r
!= FcResultMatch
)
1244 if (v
.type
!= FcTypeMatrix
)
1245 return FcResultTypeMismatch
;
1246 *m
= (FcMatrix
*)v
.u
.m
;
1247 return FcResultMatch
;
1252 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1257 r
= FcPatternGet (p
, object
, id
, &v
);
1258 if (r
!= FcResultMatch
)
1260 if (v
.type
!= FcTypeBool
)
1261 return FcResultTypeMismatch
;
1263 return FcResultMatch
;
1267 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1272 r
= FcPatternGet (p
, object
, id
, &v
);
1273 if (r
!= FcResultMatch
)
1275 if (v
.type
!= FcTypeCharSet
)
1276 return FcResultTypeMismatch
;
1277 *c
= (FcCharSet
*)v
.u
.c
;
1278 return FcResultMatch
;
1282 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1287 r
= FcPatternGet (p
, object
, id
, &v
);
1288 if (r
!= FcResultMatch
)
1290 if (v
.type
!= FcTypeFTFace
)
1291 return FcResultTypeMismatch
;
1292 *f
= (FT_Face
) v
.u
.f
;
1293 return FcResultMatch
;
1297 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1302 r
= FcPatternGet (p
, object
, id
, &v
);
1303 if (r
!= FcResultMatch
)
1305 if (v
.type
!= FcTypeLangSet
)
1306 return FcResultTypeMismatch
;
1307 *ls
= (FcLangSet
*)v
.u
.l
;
1308 return FcResultMatch
;
1312 FcPatternDuplicate (const FcPattern
*orig
)
1319 new = FcPatternCreate ();
1323 e
= FcPatternEltU(orig
->elts
);
1325 for (i
= 0; i
< orig
->num
; i
++)
1327 for (l
= (e
+ i
)->values
;
1329 l
= FcValueListPtrU(l
)->next
)
1330 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1331 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1335 FcPatternTransferFullFname (new, orig
);
1340 FcPatternDestroy (new);
1346 FcPatternReference (FcPattern
*p
)
1348 if (p
->ref
!= FC_REF_CONSTANT
)
1353 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1357 FcPatternVapBuild (ret
, orig
, va
);
1362 FcPatternBuild (FcPattern
*orig
, ...)
1366 va_start (va
, orig
);
1367 FcPatternVapBuild (orig
, orig
, va
);
1373 * Add all of the elements in 's' to 'p'
1376 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1382 for (i
= 0; i
< s
->num
; i
++)
1384 e
= FcPatternEltU(s
->elts
)+i
;
1385 for (v
= e
->values
; FcValueListPtrU(v
);
1386 v
= FcValueListPtrU(v
)->next
)
1388 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1389 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1390 FcValueListPtrU(v
)->binding
, FcTrue
))
1397 #define OBJECT_HASH_SIZE 31
1398 static struct objectBucket
{
1399 struct objectBucket
*next
;
1401 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1404 FcStrHashed (const FcChar8
*name
)
1406 FcChar32 hash
= FcStringHash (name
);
1407 struct objectBucket
**p
;
1408 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)))
1417 FcStrStaticName (const FcChar8
*name
)
1419 FcChar32 hash
= FcStringHash (name
);
1420 struct objectBucket
**p
;
1421 struct objectBucket
*b
;
1424 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1425 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1426 return (FcChar8
*) (b
+ 1);
1427 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1428 b
= malloc (size
+ sizeof (int));
1429 /* workaround glibc bug which reads strlen in groups of 4 */
1430 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1435 strcpy ((char *) (b
+ 1), (char *)name
);
1437 return (FcChar8
*) (b
+ 1);
1441 FcStrStaticNameFini (void)
1444 struct objectBucket
*b
, *next
;
1447 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1449 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1452 name
= (char *) (b
+ 1);
1453 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1454 FcMemFree (FC_MEM_STATICSTR
, size
);
1457 FcObjectBuckets
[i
] = 0;
1462 FcPatternFini (void)
1464 FcPatternBaseThawAll ();
1465 FcValueListThawAll ();
1466 FcStrStaticNameFini ();
1467 FcObjectStaticNameFini ();
1470 static FcPatternEltPtr
1471 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1473 FcPatternEltPtr
new;
1474 new.bank
= FC_BANK_DYNAMIC
;
1479 static FcPatternEltPtr
1480 FcPatternEltPtrCreateStatic (int bank
, int i
)
1482 FcPatternEltPtr
new;
1489 FcStrNewBank (void);
1491 FcStrNeededBytes (const FcChar8
* s
);
1493 FcStrNeededBytesAlign (void);
1495 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1496 static const FcChar8
*
1497 FcStrSerialize (int bank
, const FcChar8
* s
);
1499 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1502 FcValueListNewBank (void);
1504 FcValueListNeededBytes (FcValueList
* vl
);
1506 FcValueListNeededBytesAlign (void);
1508 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1509 static FcValueListPtr
1510 FcValueListSerialize(int bank
, FcValueList
*pi
);
1512 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1516 FcPatternNewBank (void)
1518 fcpattern_count
= 0;
1519 fcpatternelt_count
= 0;
1522 FcValueListNewBank();
1526 FcPatternNeededBytes (FcPattern
* p
)
1531 fcpatternelt_count
+= p
->num
;
1533 for (i
= 0; i
< p
->num
; i
++)
1535 c
= FcValueListNeededBytes (FcValueListPtrU
1536 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1542 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1546 FcPatternNeededBytesAlign (void)
1548 return fc_alignof (FcPattern
) + fc_alignof (FcPatternElt
) +
1549 FcValueListNeededBytesAlign ();
1553 FcPatternEnsureBank (int bi
)
1559 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1561 int new_count
= bi
+ 4;
1562 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1566 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1569 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1573 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1574 _fcPatternElts
= ep
;
1576 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1579 _fcPatternElts
[i
] = 0;
1582 fcpattern_bank_count
= new_count
;
1585 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1590 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1592 int bi
= FcCacheBankToIndex(metadata
->bank
);
1594 if (!FcPatternEnsureBank(bi
))
1598 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1599 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1600 block_ptr
= (void *)((char *)block_ptr
+
1601 (sizeof (FcPattern
) * fcpattern_count
));
1603 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1604 fcpatternelt_ptr
= 0;
1605 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1606 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1607 block_ptr
= (void *)((char *)block_ptr
+
1608 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1610 metadata
->pattern_count
= fcpattern_count
;
1611 metadata
->patternelt_count
= fcpatternelt_count
;
1613 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1614 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1619 FcPatternSerialize (int bank
, FcPattern
*old
)
1622 FcPatternElt
*e
, *nep
;
1624 FcValueListPtr v
, nv_head
, nvp
;
1625 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1627 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1629 elts
= fcpatternelt_ptr
;
1630 nep
= &_fcPatternElts
[bi
][elts
];
1634 fcpatternelt_ptr
+= old
->num
;
1636 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1639 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1640 if (!FcValueListPtrU(nv_head
))
1642 nv
= FcValueListPtrU(nvp
);
1646 v
= FcValueListPtrU(v
)->next
,
1647 nv
= FcValueListPtrU(nv
->next
))
1650 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1652 nvp
= FcValueListSerialize
1653 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1658 nep
[i
].values
= nv_head
;
1659 nep
[i
].object
= e
->object
;
1662 p
->elts
= old
->elts
;
1663 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1666 p
->ref
= FC_REF_CONSTANT
;
1671 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1673 int bi
= FcCacheBankToIndex(metadata
->bank
);
1674 if (!FcPatternEnsureBank(bi
))
1677 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1678 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1679 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1680 block_ptr
= (void *)((char *)block_ptr
+
1681 (sizeof (FcPattern
) * metadata
->pattern_count
));
1683 FcMemAlloc (FC_MEM_PATELT
,
1684 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1685 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1686 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1687 block_ptr
= (void *)((char *)block_ptr
+
1688 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1690 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1691 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1697 FcValueListNewBank (void)
1699 fcvaluelist_count
= 0;
1706 FcValueListNeededBytes (FcValueList
*p
)
1713 vl
= FcValueListPtrU(vl
->next
))
1715 /* unserialize just in case */
1716 FcValue v
= FcValueCanonicalize(&vl
->value
);
1721 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1724 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1727 cum
+= FcStrNeededBytes(v
.u
.s
);
1731 fcvaluelist_count
++;
1732 cum
+= sizeof (FcValueList
);
1739 FcValueListNeededBytesAlign (void)
1741 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1742 FcStrNeededBytesAlign() + fc_alignof (FcValueList
);
1746 FcValueListEnsureBank (int bi
)
1750 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1752 int new_count
= bi
+ 2, i
;
1754 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1758 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1760 _fcValueLists
= pvl
;
1761 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1762 _fcValueLists
[i
] = 0;
1764 fcvaluelist_bank_count
= new_count
;
1770 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1772 int bi
= FcCacheBankToIndex(metadata
->bank
);
1774 if (!FcValueListEnsureBank(bi
))
1777 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1778 fcvaluelist_ptr
= 0;
1779 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1780 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1781 block_ptr
= (void *)((char *)block_ptr
+
1782 (sizeof (FcValueList
) * fcvaluelist_count
));
1783 metadata
->valuelist_count
= fcvaluelist_count
;
1785 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1786 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1791 static FcValueListPtr
1792 FcValueListSerialize(int bank
, FcValueList
*pi
)
1796 int bi
= FcCacheBankToIndex(bank
);
1800 new.bank
= FC_BANK_DYNAMIC
;
1805 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1807 new.u
.stat
= fcvaluelist_ptr
++;
1808 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1809 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1815 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1817 return FcValueListPtrCreateDynamic(pi
);
1818 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1819 v
->type
|= FC_STORAGE_STATIC
;
1827 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1829 return FcValueListPtrCreateDynamic(pi
);
1830 v
->u
.c_off
= (char *)c
- (char *)v
;
1831 v
->type
|= FC_STORAGE_STATIC
;
1837 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1839 return FcValueListPtrCreateDynamic(pi
);
1840 v
->u
.l_off
= (char *)l
- (char *)v
;
1841 v
->type
|= FC_STORAGE_STATIC
;
1851 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1853 int bi
= FcCacheBankToIndex(metadata
->bank
);
1855 if (!FcValueListEnsureBank(bi
))
1858 FcMemAlloc (FC_MEM_VALLIST
,
1859 sizeof (FcValueList
) * metadata
->valuelist_count
);
1860 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1861 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1862 block_ptr
= (void *)((char *)block_ptr
+
1863 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1865 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1866 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1872 FcValueListPtrCreateDynamic(FcValueList
* p
)
1876 r
.bank
= FC_BANK_DYNAMIC
;
1881 static FcChar8
** static_strs
;
1882 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1884 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1890 struct objectBucket
*b
, *next
;
1893 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1895 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1898 name
= (char *) (b
+ 1);
1899 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1900 FcMemFree (FC_MEM_STATICSTR
, size
);
1903 FcStrBuckets
[i
] = 0;
1910 FcStrNeededBytes (const FcChar8
* s
)
1912 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1913 struct objectBucket
**p
;
1914 struct objectBucket
*b
;
1916 FcChar8
*const null
= 0;
1918 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1919 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1921 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1923 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1928 strcpy ((char *) (b
+ 1), (char *)s
);
1930 /* Yes, the following line is convoluted. However, it is
1931 * incorrect to replace the with a memset, because the C
1932 * specification doesn't guarantee that the null pointer is
1933 * the same as the zero bit pattern. */
1934 /* Misaligned pointers are not guaranteed to work, either! */
1935 memcpy (((char *) (b
+ 1) + strlen((char *)s
) + 1), &null
, sizeof (null
));
1938 fcstr_count
+= strlen((char *)s
) + 1;
1939 return strlen((char *)s
) + 1;
1943 FcStrNeededBytesAlign (void)
1945 return fc_alignof (char);
1949 FcStrEnsureBank (int bi
)
1953 if (!static_strs
|| static_str_bank_count
<= bi
)
1955 int new_count
= bi
+ 4, i
;
1956 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1960 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1963 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1965 static_str_bank_count
= new_count
;
1971 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1973 int bi
= FcCacheBankToIndex(metadata
->bank
);
1974 if (!FcStrEnsureBank(bi
))
1977 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1978 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1979 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1980 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1981 metadata
->str_count
= fcstr_count
;
1987 static const FcChar8
*
1988 FcStrSerialize (int bank
, const FcChar8
* s
)
1990 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1991 struct objectBucket
**p
;
1992 struct objectBucket
*b
;
1993 int bi
= FcCacheBankToIndex(bank
);
1995 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1996 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1999 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
2002 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
2003 t
= static_strs
[bi
] + fcstr_ptr
;
2004 memcpy ((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1, &t
, sizeof (FcChar8
*));
2005 fcstr_ptr
+= strlen((char *)s
) + 1;
2006 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
2014 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
2016 int bi
= FcCacheBankToIndex(metadata
->bank
);
2017 if (!FcStrEnsureBank(bi
))
2020 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
2021 block_ptr
= ALIGN (block_ptr
, FcChar8
);
2022 static_strs
[bi
] = (FcChar8
*)block_ptr
;
2023 block_ptr
= (void *)((char *)block_ptr
+
2024 (sizeof (char) * metadata
->str_count
));
2029 /* we don't store these in the FcPattern itself because
2030 * we don't want to serialize the directory names */
2032 /* I suppose this should be cleaned upon termination, too... */
2033 typedef struct _FcPatternDirMapping
{
2036 } FcPatternDirMapping
;
2038 #define PATTERNDIR_HASH_SIZE 31
2039 static struct patternDirBucket
{
2040 struct patternDirBucket
*next
;
2041 FcPatternDirMapping m
;
2042 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
2045 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
2047 struct patternDirBucket
*pb
;
2049 /* N.B. FcPatternHash fails, since it's contents-based, not
2050 * address-based, and we're in the process of mutating the FcPattern. */
2051 for (pb
= &FcPatternDirBuckets
2052 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2053 pb
->m
.p
!= p
&& pb
->next
;
2059 pb
->m
.fname
= fname
;
2063 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2066 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2070 pb
->next
->m
.fname
= fname
;
2074 FcPatternFindFullFname (const FcPattern
*p
)
2076 struct patternDirBucket
*pb
;
2078 for (pb
= &FcPatternDirBuckets
2079 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2088 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2091 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2092 FcPatternAddFullFname (new,
2094 ((FcChar8
*)FcPatternFindFullFname(orig
)));