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
*v0
)
246 FcValue v
= FcValueCanonicalize(v0
);
251 return (FcChar32
) v
.u
.i
;
253 return FcDoubleHash (v
.u
.d
);
255 return FcStringHash (v
.u
.s
);
257 return (FcChar32
) v
.u
.b
;
259 return (FcDoubleHash (v
.u
.m
->xx
) ^
260 FcDoubleHash (v
.u
.m
->xy
) ^
261 FcDoubleHash (v
.u
.m
->yx
) ^
262 FcDoubleHash (v
.u
.m
->yy
));
264 return (FcChar32
) v
.u
.c
->num
;
266 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
267 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
269 return FcLangSetHash (v
.u
.l
);
275 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
277 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
280 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
282 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
283 FcValueListPtrU(lb
)->value
))
285 la
= FcValueListPtrU(la
)->next
;
286 lb
= FcValueListPtrU(lb
)->next
;
288 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
294 FcValueListHash (FcValueListPtr l
)
298 while (FcValueListPtrU(l
))
300 hash
= ((hash
<< 1) | (hash
>> 31)) ^
301 FcValueHash (&FcValueListPtrU(l
)->value
);
302 l
= FcValueListPtrU(l
)->next
;
308 FcPatternDestroy (FcPattern
*p
)
312 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
315 if (FcPatternFindFullFname (p
))
317 FcStrFree ((FcChar8
*)FcPatternFindFullFname (p
));
318 FcPatternAddFullFname (p
, 0);
321 for (i
= 0; i
< p
->num
; i
++)
322 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
325 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
327 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
328 free (FcPatternEltU(p
->elts
));
329 p
->elts
= FcPatternEltPtrCreateDynamic(0);
332 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
336 #define FC_VALUE_LIST_HASH_SIZE 257
337 #define FC_PATTERN_HASH_SIZE 67
339 typedef struct _FcValueListEnt FcValueListEnt
;
341 struct _FcValueListEnt
{
342 FcValueListEnt
*next
;
347 typedef union _FcValueListAlign
{
352 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
353 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
354 static char FcValueListFrozenName
[][8] = {
367 FcValueListReport (void);
370 FcValueListReport (void)
374 printf ("Fc Frozen Values:\n");
375 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
376 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
377 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
378 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
381 static FcValueListEnt
*
382 FcValueListEntCreate (FcValueListPtr h
)
384 FcValueListAlign
*ea
;
392 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
394 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
395 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
396 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
397 // this leaks for some reason
398 ea
= malloc (sizeof (FcValueListAlign
));
401 new = malloc (n
* sizeof (FcValueList
));
404 memset(new, 0, n
* sizeof (FcValueList
));
405 FcMemAlloc (FC_MEM_VALLIST
, size
);
407 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
408 for (l
= h
; FcValueListPtrU(l
);
409 l
= FcValueListPtrU(l
)->next
, new++)
411 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
413 new->value
.type
= FcTypeString
;
414 new->value
.u
.s
= FcStrStaticName
415 (fc_value_string(&FcValueListPtrU(l
)->value
));
419 new->value
= FcValueSave (FcValueCanonicalize
420 (&FcValueListPtrU(l
)->value
));
422 new->binding
= FcValueListPtrU(l
)->binding
;
423 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
425 new->next
= FcValueListPtrCreateDynamic(new + 1);
429 new->next
= FcValueListPtrCreateDynamic(0);
436 FcValueListEntDestroy (FcValueListEnt
*e
)
440 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
442 /* XXX: We should perform these two operations with "size" as
443 computed in FcValueListEntCreate, but we don't have access to
444 that value here. Without this, the FcValueListFrozenBytes
445 values will be wrong as will the FcMemFree counts.
447 FcValueListFrozenBytes[e->list->value.type] -= size;
448 FcMemFree (FC_MEM_VALLIST, size);
451 for (l
= e
->list
; FcValueListPtrU(l
);
452 l
= FcValueListPtrU(l
)->next
)
454 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
455 FcValueDestroy (FcValueListPtrU(l
)->value
);
457 /* XXX: Are we being too chummy with the implementation here to
458 free(e) when it was actually the enclosing FcValueListAlign
459 that was allocated? */
463 static int FcValueListTotal
;
464 static int FcValueListUsed
;
466 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
468 static FcValueListPtr
469 FcValueListFreeze (FcValueListPtr l
)
471 FcChar32 hash
= FcValueListHash (l
);
472 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
476 for (ent
= *bucket
; ent
; ent
= ent
->next
)
478 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
482 ent
= FcValueListEntCreate (l
);
484 return FcValueListPtrCreateDynamic(0);
494 FcValueListThawAll (void)
497 FcValueListEnt
*ent
, *next
;
499 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
501 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
504 FcValueListEntDestroy (ent
);
506 FcValueListHashTable
[i
] = 0;
509 FcValueListTotal
= 0;
514 FcPatternBaseHash (FcPattern
*b
)
516 FcChar32 hash
= b
->num
;
519 for (i
= 0; i
< b
->num
; i
++)
520 hash
= ((hash
<< 1) | (hash
>> 31)) ^
521 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
525 typedef struct _FcPatternEnt FcPatternEnt
;
527 struct _FcPatternEnt
{
533 static int FcPatternTotal
;
534 static int FcPatternUsed
;
536 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
539 FcPatternBaseFreeze (FcPattern
*b
)
543 FcChar32 hash
= FcPatternBaseHash (b
);
544 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
549 for (ent
= *bucket
; ent
; ent
= ent
->next
)
551 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
553 for (i
= 0; i
< b
->num
; i
++)
555 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
556 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
558 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
559 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
568 * Compute size of pattern + elts
570 ent
= malloc (sizeof (FcPatternEnt
));
574 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
577 ep
= FcPatternCreate();
581 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
584 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
586 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
590 ep
->ref
= FC_REF_CONSTANT
;
592 for (i
= 0; i
< b
->num
; i
++)
594 (FcPatternEltU(ep
->elts
)+i
)->values
=
595 (FcPatternEltU(b
->elts
)+i
)->values
;
596 (FcPatternEltU(ep
->elts
)+i
)->object
=
597 (FcPatternEltU(b
->elts
)+i
)->object
;
600 if (FcPatternFindElt (b
, FC_FILE
))
601 FcPatternTransferFullFname (ep
, b
);
609 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
615 FcPatternBaseThawAll (void)
618 FcPatternEnt
*ent
, *next
;
620 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
622 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
627 FcPatternHashTable
[i
] = 0;
635 FcPatternFreeze (FcPattern
*p
)
637 FcPattern
*b
, *n
= 0;
641 if (p
->ref
== FC_REF_CONSTANT
)
644 b
= FcPatternCreate();
652 e
= malloc(b
->num
* sizeof (FcPatternElt
));
655 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
656 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
659 * Freeze object lists
661 for (i
= 0; i
< p
->num
; i
++)
663 (FcPatternEltU(b
->elts
)+i
)->object
=
664 (FcPatternEltU(p
->elts
)+i
)->object
;
665 (FcPatternEltU(b
->elts
)+i
)->values
=
666 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
667 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
671 if (FcPatternFindElt (p
, FC_FILE
))
672 FcPatternTransferFullFname (b
, p
);
677 n
= FcPatternBaseFreeze (b
);
679 if (FcDebug() & FC_DBG_MEMORY
)
681 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
682 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
686 free(FcPatternEltU(b
->elts
));
687 b
->elts
= FcPatternEltPtrCreateDynamic(0);
688 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
691 assert (FcPatternEqual (n
, p
));
697 FcPatternPosition (const FcPattern
*p
, const char *object
)
699 int low
, high
, mid
, c
;
702 obj
= FcObjectToPtr(object
);
709 mid
= (low
+ high
) >> 1;
710 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
724 FcPatternFindElt (const FcPattern
*p
, const char *object
)
726 int i
= FcPatternPosition (p
, object
);
729 return FcPatternEltU(p
->elts
)+i
;
733 FcPatternInsertElt (FcPattern
*p
, const char *object
)
738 i
= FcPatternPosition (p
, object
);
743 /* reallocate array */
744 if (p
->num
+ 1 >= p
->size
)
746 int s
= p
->size
+ 16;
747 if (FcPatternEltU(p
->elts
))
749 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
750 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
751 if (!e
) /* maybe it was mmapped */
753 e
= malloc(s
* sizeof (FcPatternElt
));
755 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
759 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
762 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
764 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
765 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
768 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
769 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
770 FcValueListPtrCreateDynamic(0);
776 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
777 FcPatternEltU(p
->elts
) + i
,
778 sizeof (FcPatternElt
) *
784 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
785 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
788 return FcPatternEltU(p
->elts
)+i
;
792 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
799 if (pa
->num
!= pb
->num
)
801 for (i
= 0; i
< pa
->num
; i
++)
803 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
804 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
806 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
807 (FcPatternEltU(pb
->elts
)+i
)->values
))
814 FcPatternHash (const FcPattern
*p
)
819 for (i
= 0; i
< p
->num
; i
++)
821 h
= (((h
<< 1) | (h
>> 31)) ^
822 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
823 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
829 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
831 FcPatternElt
*ea
, *eb
;
834 for (i
= 0; i
< os
->nobject
; i
++)
836 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
837 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
842 if (!FcValueListEqual (ea
->values
, eb
->values
))
855 FcPatternAddWithBinding (FcPattern
*p
,
858 FcValueBinding binding
,
862 FcValueListPtr
new, *prev
;
864 FcObjectPtr objectPtr
;
866 if (p
->ref
== FC_REF_CONSTANT
)
869 newp
= malloc (sizeof (FcValueList
));
873 memset(newp
, 0, sizeof (FcValueList
));
874 new = FcValueListPtrCreateDynamic(newp
);
875 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
877 if (value
.type
== FcTypeString
)
879 value
.u
.s
= FcStrStaticName (value
.u
.s
);
881 value
.type
= FcTypeVoid
;
884 value
= FcValueSave (value
);
885 if (value
.type
== FcTypeVoid
)
888 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
889 * speedup: only allow strings to be added under the FC_FAMILY,
890 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
891 * and charsets under FC_CHARSET key.
892 * This is slightly semantically different from the old behaviour,
893 * but fonts shouldn't be getting non-strings here anyway.
894 * a better hack would use FcBaseObjectTypes to check all objects. */
895 objectPtr
= FcObjectToPtr(object
);
896 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
897 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
898 || objectPtr
== FcObjectToPtr(FC_STYLE
)
899 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
900 && value
.type
!= FcTypeString
)
902 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
903 && value
.type
!= FcTypeCharSet
)
906 FcValueListPtrU(new)->value
= value
;
907 FcValueListPtrU(new)->binding
= binding
;
908 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
910 e
= FcPatternInsertElt (p
, object
);
916 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
922 FcValueListPtrU(new)->next
= e
->values
;
929 switch (value
.type
) {
931 FcStrFree ((FcChar8
*) value
.u
.s
);
934 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
937 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
940 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
946 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
947 free (FcValueListPtrU(new));
953 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
955 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
959 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
961 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
965 FcPatternDel (FcPattern
*p
, const char *object
)
969 e
= FcPatternFindElt (p
, object
);
974 FcValueListDestroy (e
->values
);
976 /* shuffle existing ones down */
978 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
979 sizeof (FcPatternElt
));
981 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
982 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
987 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
990 FcValueListPtr
*prev
, l
;
992 e
= FcPatternFindElt (p
, object
);
995 for (prev
= &e
->values
;
996 FcValueListPtrU(l
= *prev
);
997 prev
= &FcValueListPtrU(l
)->next
)
1001 *prev
= FcValueListPtrU(l
)->next
;
1002 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
1003 FcValueListDestroy (l
);
1004 if (!FcValueListPtrU(e
->values
))
1005 FcPatternDel (p
, object
);
1014 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1018 v
.type
= FcTypeInteger
;
1020 return FcPatternAdd (p
, object
, v
, FcTrue
);
1024 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1028 v
.type
= FcTypeDouble
;
1030 return FcPatternAdd (p
, object
, v
, FcTrue
);
1035 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1041 v
.type
= FcTypeVoid
;
1043 return FcPatternAdd (p
, object
, v
, FcTrue
);
1046 v
.type
= FcTypeString
;
1047 v
.u
.s
= FcStrStaticName(s
);
1048 return FcPatternAdd (p
, object
, v
, FcTrue
);
1052 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1056 v
.type
= FcTypeMatrix
;
1058 return FcPatternAdd (p
, object
, v
, FcTrue
);
1063 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1067 v
.type
= FcTypeBool
;
1069 return FcPatternAdd (p
, object
, v
, FcTrue
);
1073 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1077 v
.type
= FcTypeCharSet
;
1078 v
.u
.c
= (FcCharSet
*)c
;
1079 return FcPatternAdd (p
, object
, v
, FcTrue
);
1083 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1087 v
.type
= FcTypeFTFace
;
1089 return FcPatternAdd (p
, object
, v
, FcTrue
);
1093 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1097 v
.type
= FcTypeLangSet
;
1098 v
.u
.l
= (FcLangSet
*)ls
;
1099 return FcPatternAdd (p
, object
, v
, FcTrue
);
1103 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1108 e
= FcPatternFindElt (p
, object
);
1110 return FcResultNoMatch
;
1111 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1115 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1116 return FcResultMatch
;
1120 return FcResultNoId
;
1124 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1129 r
= FcPatternGet (p
, object
, id
, &v
);
1130 if (r
!= FcResultMatch
)
1140 return FcResultTypeMismatch
;
1142 return FcResultMatch
;
1146 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1151 r
= FcPatternGet (p
, object
, id
, &v
);
1152 if (r
!= FcResultMatch
)
1159 *d
= (double) v
.u
.i
;
1162 return FcResultTypeMismatch
;
1164 return FcResultMatch
;
1168 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1173 r
= FcPatternGet (p
, object
, id
, &v
);
1174 if (r
!= FcResultMatch
)
1176 if (v
.type
!= FcTypeString
)
1177 return FcResultTypeMismatch
;
1179 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1181 const char *fn
, *fpath
;
1185 fn
= FcPatternFindFullFname(p
);
1188 *s
= (FcChar8
*) fn
;
1189 return FcResultMatch
;
1194 *s
= (FcChar8
*) v
.u
.s
;
1195 return FcResultMatch
;
1198 fpath
= FcCacheFindBankDir (p
->bank
);
1199 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1200 fname
= malloc (size
);
1202 return FcResultOutOfMemory
;
1204 FcMemAlloc (FC_MEM_STRING
, size
);
1205 strcpy ((char *)fname
, (char *)fpath
);
1206 strcat ((char *)fname
, "/");
1207 strcat ((char *)fname
, (char *)v
.u
.s
);
1209 FcPatternAddFullFname (p
, (const char *)fname
);
1210 *s
= (FcChar8
*)fname
;
1211 return FcResultMatch
;
1214 *s
= (FcChar8
*) v
.u
.s
;
1215 return FcResultMatch
;
1219 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1224 r
= FcPatternGet (p
, object
, id
, &v
);
1225 if (r
!= FcResultMatch
)
1227 if (v
.type
!= FcTypeMatrix
)
1228 return FcResultTypeMismatch
;
1229 *m
= (FcMatrix
*)v
.u
.m
;
1230 return FcResultMatch
;
1235 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1240 r
= FcPatternGet (p
, object
, id
, &v
);
1241 if (r
!= FcResultMatch
)
1243 if (v
.type
!= FcTypeBool
)
1244 return FcResultTypeMismatch
;
1246 return FcResultMatch
;
1250 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1255 r
= FcPatternGet (p
, object
, id
, &v
);
1256 if (r
!= FcResultMatch
)
1258 if (v
.type
!= FcTypeCharSet
)
1259 return FcResultTypeMismatch
;
1260 *c
= (FcCharSet
*)v
.u
.c
;
1261 return FcResultMatch
;
1265 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1270 r
= FcPatternGet (p
, object
, id
, &v
);
1271 if (r
!= FcResultMatch
)
1273 if (v
.type
!= FcTypeFTFace
)
1274 return FcResultTypeMismatch
;
1275 *f
= (FT_Face
) v
.u
.f
;
1276 return FcResultMatch
;
1280 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1285 r
= FcPatternGet (p
, object
, id
, &v
);
1286 if (r
!= FcResultMatch
)
1288 if (v
.type
!= FcTypeLangSet
)
1289 return FcResultTypeMismatch
;
1290 *ls
= (FcLangSet
*)v
.u
.l
;
1291 return FcResultMatch
;
1295 FcPatternDuplicate (const FcPattern
*orig
)
1302 new = FcPatternCreate ();
1306 e
= FcPatternEltU(orig
->elts
);
1308 for (i
= 0; i
< orig
->num
; i
++)
1310 for (l
= (e
+ i
)->values
;
1312 l
= FcValueListPtrU(l
)->next
)
1313 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1314 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1318 FcPatternTransferFullFname (new, orig
);
1323 FcPatternDestroy (new);
1329 FcPatternReference (FcPattern
*p
)
1331 if (p
->ref
!= FC_REF_CONSTANT
)
1336 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1340 FcPatternVapBuild (ret
, orig
, va
);
1345 FcPatternBuild (FcPattern
*orig
, ...)
1349 va_start (va
, orig
);
1350 FcPatternVapBuild (orig
, orig
, va
);
1356 * Add all of the elements in 's' to 'p'
1359 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1365 for (i
= 0; i
< s
->num
; i
++)
1367 e
= FcPatternEltU(s
->elts
)+i
;
1368 for (v
= e
->values
; FcValueListPtrU(v
);
1369 v
= FcValueListPtrU(v
)->next
)
1371 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1372 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1373 FcValueListPtrU(v
)->binding
, FcTrue
))
1380 #define OBJECT_HASH_SIZE 31
1381 static struct objectBucket
{
1382 struct objectBucket
*next
;
1384 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1387 FcStrHashed (const FcChar8
*name
)
1389 FcChar32 hash
= FcStringHash (name
);
1390 struct objectBucket
**p
;
1391 struct objectBucket
*b
;
1393 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1394 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1400 FcStrStaticName (const FcChar8
*name
)
1402 FcChar32 hash
= FcStringHash (name
);
1403 struct objectBucket
**p
;
1404 struct objectBucket
*b
;
1407 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1408 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1409 return (FcChar8
*) (b
+ 1);
1410 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1411 b
= malloc (size
+ sizeof (int));
1412 /* workaround glibc bug which reads strlen in groups of 4 */
1413 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1418 strcpy ((char *) (b
+ 1), (char *)name
);
1420 return (FcChar8
*) (b
+ 1);
1424 FcStrStaticNameFini (void)
1427 struct objectBucket
*b
, *next
;
1430 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1432 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1435 name
= (char *) (b
+ 1);
1436 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1437 FcMemFree (FC_MEM_STATICSTR
, size
);
1440 FcObjectBuckets
[i
] = 0;
1445 FcPatternFini (void)
1447 FcPatternBaseThawAll ();
1448 FcValueListThawAll ();
1449 FcStrStaticNameFini ();
1450 FcObjectStaticNameFini ();
1453 static FcPatternEltPtr
1454 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1456 FcPatternEltPtr
new;
1457 new.bank
= FC_BANK_DYNAMIC
;
1462 static FcPatternEltPtr
1463 FcPatternEltPtrCreateStatic (int bank
, int i
)
1465 FcPatternEltPtr
new;
1472 FcStrNewBank (void);
1474 FcStrNeededBytes (const FcChar8
* s
);
1476 FcStrNeededBytesAlign (void);
1478 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1479 static const FcChar8
*
1480 FcStrSerialize (int bank
, const FcChar8
* s
);
1482 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1485 FcValueListNewBank (void);
1487 FcValueListNeededBytes (FcValueList
* vl
);
1489 FcValueListNeededBytesAlign (void);
1491 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1492 static FcValueListPtr
1493 FcValueListSerialize(int bank
, FcValueList
*pi
);
1495 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1499 FcPatternNewBank (void)
1501 fcpattern_count
= 0;
1502 fcpatternelt_count
= 0;
1505 FcValueListNewBank();
1509 FcPatternNeededBytes (FcPattern
* p
)
1514 fcpatternelt_count
+= p
->num
;
1516 for (i
= 0; i
< p
->num
; i
++)
1518 c
= FcValueListNeededBytes (FcValueListPtrU
1519 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1525 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1529 FcPatternNeededBytesAlign (void)
1531 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1532 FcValueListNeededBytesAlign ();
1536 FcPatternEnsureBank (int bi
)
1542 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1544 int new_count
= bi
+ 4;
1545 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1549 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1552 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1556 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1557 _fcPatternElts
= ep
;
1559 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1562 _fcPatternElts
[i
] = 0;
1565 fcpattern_bank_count
= new_count
;
1568 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1573 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1575 int bi
= FcCacheBankToIndex(metadata
->bank
);
1577 if (!FcPatternEnsureBank(bi
))
1581 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1582 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1583 block_ptr
= (void *)((char *)block_ptr
+
1584 (sizeof (FcPattern
) * fcpattern_count
));
1586 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1587 fcpatternelt_ptr
= 0;
1588 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1589 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1590 block_ptr
= (void *)((char *)block_ptr
+
1591 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1593 metadata
->pattern_count
= fcpattern_count
;
1594 metadata
->patternelt_count
= fcpatternelt_count
;
1596 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1597 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1602 FcPatternSerialize (int bank
, FcPattern
*old
)
1605 FcPatternElt
*e
, *nep
;
1607 FcValueListPtr v
, nv_head
, nvp
;
1608 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1610 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1612 elts
= fcpatternelt_ptr
;
1613 nep
= &_fcPatternElts
[bi
][elts
];
1617 fcpatternelt_ptr
+= old
->num
;
1619 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1622 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1623 if (!FcValueListPtrU(nv_head
))
1625 nv
= FcValueListPtrU(nvp
);
1629 v
= FcValueListPtrU(v
)->next
,
1630 nv
= FcValueListPtrU(nv
->next
))
1633 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1635 nvp
= FcValueListSerialize
1636 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1641 nep
[i
].values
= nv_head
;
1642 nep
[i
].object
= e
->object
;
1645 p
->elts
= old
->elts
;
1646 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1649 p
->ref
= FC_REF_CONSTANT
;
1654 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1656 int bi
= FcCacheBankToIndex(metadata
->bank
);
1657 if (!FcPatternEnsureBank(bi
))
1660 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1661 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1662 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1663 block_ptr
= (void *)((char *)block_ptr
+
1664 (sizeof (FcPattern
) * metadata
->pattern_count
));
1666 FcMemAlloc (FC_MEM_PATELT
,
1667 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1668 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1669 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1670 block_ptr
= (void *)((char *)block_ptr
+
1671 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1673 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1674 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1680 FcValueListNewBank (void)
1682 fcvaluelist_count
= 0;
1689 FcValueListNeededBytes (FcValueList
*p
)
1696 vl
= FcValueListPtrU(vl
->next
))
1698 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1703 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1706 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1709 cum
+= FcStrNeededBytes(v
.u
.s
);
1713 fcvaluelist_count
++;
1714 cum
+= sizeof (FcValueList
);
1721 FcValueListNeededBytesAlign (void)
1723 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1724 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1728 FcValueListEnsureBank (int bi
)
1732 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1734 int new_count
= bi
+ 2, i
;
1736 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1740 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1742 _fcValueLists
= pvl
;
1743 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1744 _fcValueLists
[i
] = 0;
1746 fcvaluelist_bank_count
= new_count
;
1752 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1754 int bi
= FcCacheBankToIndex(metadata
->bank
);
1756 if (!FcValueListEnsureBank(bi
))
1759 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1760 fcvaluelist_ptr
= 0;
1761 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1762 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1763 block_ptr
= (void *)((char *)block_ptr
+
1764 (sizeof (FcValueList
) * fcvaluelist_count
));
1765 metadata
->valuelist_count
= fcvaluelist_count
;
1767 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1768 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1773 static FcValueListPtr
1774 FcValueListSerialize(int bank
, FcValueList
*pi
)
1778 int bi
= FcCacheBankToIndex(bank
);
1782 new.bank
= FC_BANK_DYNAMIC
;
1787 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1789 new.u
.stat
= fcvaluelist_ptr
++;
1790 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1791 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1797 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1799 return FcValueListPtrCreateDynamic(pi
);
1800 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1801 v
->type
|= FC_STORAGE_STATIC
;
1809 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1811 return FcValueListPtrCreateDynamic(pi
);
1812 v
->u
.c_off
= (char *)c
- (char *)v
;
1813 v
->type
|= FC_STORAGE_STATIC
;
1819 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1821 return FcValueListPtrCreateDynamic(pi
);
1822 v
->u
.l_off
= (char *)l
- (char *)v
;
1823 v
->type
|= FC_STORAGE_STATIC
;
1833 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1835 int bi
= FcCacheBankToIndex(metadata
->bank
);
1837 if (!FcValueListEnsureBank(bi
))
1840 FcMemAlloc (FC_MEM_VALLIST
,
1841 sizeof (FcValueList
) * metadata
->valuelist_count
);
1842 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1843 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1844 block_ptr
= (void *)((char *)block_ptr
+
1845 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1847 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1848 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1854 FcValueListPtrCreateDynamic(FcValueList
* p
)
1858 r
.bank
= FC_BANK_DYNAMIC
;
1863 static FcChar8
** static_strs
;
1864 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1866 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1872 struct objectBucket
*b
, *next
;
1875 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1877 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1880 name
= (char *) (b
+ 1);
1881 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1882 FcMemFree (FC_MEM_STATICSTR
, size
);
1885 FcStrBuckets
[i
] = 0;
1892 FcStrNeededBytes (const FcChar8
* s
)
1894 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1895 struct objectBucket
**p
;
1896 struct objectBucket
*b
;
1898 FcChar8
*const null
= 0;
1900 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1901 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1903 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1905 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1910 strcpy ((char *) (b
+ 1), (char *)s
);
1912 /* Yes, the following line is convoluted. However, it is
1913 * incorrect to replace the with a memset, because the C
1914 * specification doesn't guarantee that the null pointer is
1915 * the same as the zero bit pattern. */
1916 /* Misaligned pointers are not guaranteed to work, either! */
1917 memcpy (((char *) (b
+ 1) + strlen((char *)s
) + 1), &null
, sizeof (null
));
1920 fcstr_count
+= strlen((char *)s
) + 1;
1921 return strlen((char *)s
) + 1;
1925 FcStrNeededBytesAlign (void)
1927 return __alignof__ (char);
1931 FcStrEnsureBank (int bi
)
1935 if (!static_strs
|| static_str_bank_count
<= bi
)
1937 int new_count
= bi
+ 4, i
;
1938 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1942 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1945 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1947 static_str_bank_count
= new_count
;
1953 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1955 int bi
= FcCacheBankToIndex(metadata
->bank
);
1956 if (!FcStrEnsureBank(bi
))
1959 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1960 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1961 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1962 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1963 metadata
->str_count
= fcstr_count
;
1969 static const FcChar8
*
1970 FcStrSerialize (int bank
, const FcChar8
* s
)
1972 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1973 struct objectBucket
**p
;
1974 struct objectBucket
*b
;
1975 int bi
= FcCacheBankToIndex(bank
);
1977 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1978 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1981 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
1984 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1985 t
= static_strs
[bi
] + fcstr_ptr
;
1986 memcpy ((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1, &t
, sizeof (FcChar8
*));
1987 fcstr_ptr
+= strlen((char *)s
) + 1;
1988 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
1996 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
1998 int bi
= FcCacheBankToIndex(metadata
->bank
);
1999 if (!FcStrEnsureBank(bi
))
2002 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
2003 block_ptr
= ALIGN (block_ptr
, FcChar8
);
2004 static_strs
[bi
] = (FcChar8
*)block_ptr
;
2005 block_ptr
= (void *)((char *)block_ptr
+
2006 (sizeof (char) * metadata
->str_count
));
2011 /* we don't store these in the FcPattern itself because
2012 * we don't want to serialize the directory names */
2014 /* I suppose this should be cleaned upon termination, too... */
2015 typedef struct _FcPatternDirMapping
{
2018 } FcPatternDirMapping
;
2020 #define PATTERNDIR_HASH_SIZE 31
2021 static struct patternDirBucket
{
2022 struct patternDirBucket
*next
;
2023 FcPatternDirMapping m
;
2024 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
2027 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
2029 struct patternDirBucket
*pb
;
2031 /* N.B. FcPatternHash fails, since it's contents-based, not
2032 * address-based, and we're in the process of mutating the FcPattern. */
2033 for (pb
= &FcPatternDirBuckets
2034 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2035 pb
->m
.p
!= p
&& pb
->next
;
2041 pb
->m
.fname
= fname
;
2045 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2048 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2052 pb
->next
->m
.fname
= fname
;
2056 FcPatternFindFullFname (const FcPattern
*p
)
2058 struct patternDirBucket
*pb
;
2060 for (pb
= &FcPatternDirBuckets
2061 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2070 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2073 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2074 FcPatternAddFullFname (new,
2076 ((FcChar8
*)FcPatternFindFullFname(orig
)));