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 value
= FcValueSave (value
);
878 if (value
.type
== FcTypeVoid
)
881 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
882 * speedup: only allow strings to be added under the FC_FAMILY,
883 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
884 * and charsets under FC_CHARSET key.
885 * This is slightly semantically different from the old behaviour,
886 * but fonts shouldn't be getting non-strings here anyway.
887 * a better hack would use FcBaseObjectTypes to check all objects. */
888 objectPtr
= FcObjectToPtr(object
);
889 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
890 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
891 || objectPtr
== FcObjectToPtr(FC_STYLE
)
892 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
893 && value
.type
!= FcTypeString
)
895 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
896 && value
.type
!= FcTypeCharSet
)
899 FcValueListPtrU(new)->value
= value
;
900 FcValueListPtrU(new)->binding
= binding
;
901 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
903 e
= FcPatternInsertElt (p
, object
);
909 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
915 FcValueListPtrU(new)->next
= e
->values
;
922 switch (value
.type
) {
924 FcStrFree ((FcChar8
*) value
.u
.s
);
927 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
930 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
933 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
939 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
940 free (FcValueListPtrU(new));
946 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
948 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
952 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
954 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
958 FcPatternDel (FcPattern
*p
, const char *object
)
962 e
= FcPatternFindElt (p
, object
);
967 FcValueListDestroy (e
->values
);
969 /* shuffle existing ones down */
971 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
972 sizeof (FcPatternElt
));
974 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
975 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
980 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
983 FcValueListPtr
*prev
, l
;
985 e
= FcPatternFindElt (p
, object
);
988 for (prev
= &e
->values
;
989 FcValueListPtrU(l
= *prev
);
990 prev
= &FcValueListPtrU(l
)->next
)
994 *prev
= FcValueListPtrU(l
)->next
;
995 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
996 FcValueListDestroy (l
);
997 if (!FcValueListPtrU(e
->values
))
998 FcPatternDel (p
, object
);
1007 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
1011 v
.type
= FcTypeInteger
;
1013 return FcPatternAdd (p
, object
, v
, FcTrue
);
1017 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
1021 v
.type
= FcTypeDouble
;
1023 return FcPatternAdd (p
, object
, v
, FcTrue
);
1028 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
1032 v
.type
= FcTypeString
;
1033 v
.u
.s
= FcStrStaticName(s
);
1034 return FcPatternAdd (p
, object
, v
, FcTrue
);
1038 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1042 v
.type
= FcTypeMatrix
;
1044 return FcPatternAdd (p
, object
, v
, FcTrue
);
1049 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1053 v
.type
= FcTypeBool
;
1055 return FcPatternAdd (p
, object
, v
, FcTrue
);
1059 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1063 v
.type
= FcTypeCharSet
;
1064 v
.u
.c
= (FcCharSet
*)c
;
1065 return FcPatternAdd (p
, object
, v
, FcTrue
);
1069 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1073 v
.type
= FcTypeFTFace
;
1075 return FcPatternAdd (p
, object
, v
, FcTrue
);
1079 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1083 v
.type
= FcTypeLangSet
;
1084 v
.u
.l
= (FcLangSet
*)ls
;
1085 return FcPatternAdd (p
, object
, v
, FcTrue
);
1089 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1094 e
= FcPatternFindElt (p
, object
);
1096 return FcResultNoMatch
;
1097 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1101 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1102 return FcResultMatch
;
1106 return FcResultNoId
;
1110 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1115 r
= FcPatternGet (p
, object
, id
, &v
);
1116 if (r
!= FcResultMatch
)
1126 return FcResultTypeMismatch
;
1128 return FcResultMatch
;
1132 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1137 r
= FcPatternGet (p
, object
, id
, &v
);
1138 if (r
!= FcResultMatch
)
1145 *d
= (double) v
.u
.i
;
1148 return FcResultTypeMismatch
;
1150 return FcResultMatch
;
1154 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1159 r
= FcPatternGet (p
, object
, id
, &v
);
1160 if (r
!= FcResultMatch
)
1162 if (v
.type
!= FcTypeString
)
1163 return FcResultTypeMismatch
;
1165 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1167 const char *fn
, *fpath
;
1171 fn
= FcPatternFindFullFname(p
);
1174 *s
= (FcChar8
*) fn
;
1175 return FcResultMatch
;
1180 *s
= (FcChar8
*) v
.u
.s
;
1181 return FcResultMatch
;
1184 fpath
= FcCacheFindBankDir (p
->bank
);
1185 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1186 fname
= malloc (size
);
1188 return FcResultOutOfMemory
;
1190 FcMemAlloc (FC_MEM_STRING
, size
);
1191 strcpy ((char *)fname
, (char *)fpath
);
1192 strcat ((char *)fname
, "/");
1193 strcat ((char *)fname
, (char *)v
.u
.s
);
1195 FcPatternAddFullFname (p
, (const char *)fname
);
1196 *s
= (FcChar8
*)fname
;
1197 return FcResultMatch
;
1200 *s
= (FcChar8
*) v
.u
.s
;
1201 return FcResultMatch
;
1205 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1210 r
= FcPatternGet (p
, object
, id
, &v
);
1211 if (r
!= FcResultMatch
)
1213 if (v
.type
!= FcTypeMatrix
)
1214 return FcResultTypeMismatch
;
1215 *m
= (FcMatrix
*)v
.u
.m
;
1216 return FcResultMatch
;
1221 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1226 r
= FcPatternGet (p
, object
, id
, &v
);
1227 if (r
!= FcResultMatch
)
1229 if (v
.type
!= FcTypeBool
)
1230 return FcResultTypeMismatch
;
1232 return FcResultMatch
;
1236 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1241 r
= FcPatternGet (p
, object
, id
, &v
);
1242 if (r
!= FcResultMatch
)
1244 if (v
.type
!= FcTypeCharSet
)
1245 return FcResultTypeMismatch
;
1246 *c
= (FcCharSet
*)v
.u
.c
;
1247 return FcResultMatch
;
1251 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1256 r
= FcPatternGet (p
, object
, id
, &v
);
1257 if (r
!= FcResultMatch
)
1259 if (v
.type
!= FcTypeFTFace
)
1260 return FcResultTypeMismatch
;
1261 *f
= (FT_Face
) v
.u
.f
;
1262 return FcResultMatch
;
1266 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1271 r
= FcPatternGet (p
, object
, id
, &v
);
1272 if (r
!= FcResultMatch
)
1274 if (v
.type
!= FcTypeLangSet
)
1275 return FcResultTypeMismatch
;
1276 *ls
= (FcLangSet
*)v
.u
.l
;
1277 return FcResultMatch
;
1281 FcPatternDuplicate (const FcPattern
*orig
)
1288 new = FcPatternCreate ();
1292 e
= FcPatternEltU(orig
->elts
);
1294 for (i
= 0; i
< orig
->num
; i
++)
1296 for (l
= (e
+ i
)->values
;
1298 l
= FcValueListPtrU(l
)->next
)
1299 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1300 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1304 FcPatternTransferFullFname (new, orig
);
1309 FcPatternDestroy (new);
1315 FcPatternReference (FcPattern
*p
)
1317 if (p
->ref
!= FC_REF_CONSTANT
)
1322 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1326 FcPatternVapBuild (ret
, orig
, va
);
1331 FcPatternBuild (FcPattern
*orig
, ...)
1335 va_start (va
, orig
);
1336 FcPatternVapBuild (orig
, orig
, va
);
1342 * Add all of the elements in 's' to 'p'
1345 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1351 for (i
= 0; i
< s
->num
; i
++)
1353 e
= FcPatternEltU(s
->elts
)+i
;
1354 for (v
= e
->values
; FcValueListPtrU(v
);
1355 v
= FcValueListPtrU(v
)->next
)
1357 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1358 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1359 FcValueListPtrU(v
)->binding
, FcTrue
))
1366 #define OBJECT_HASH_SIZE 31
1367 static struct objectBucket
{
1368 struct objectBucket
*next
;
1370 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1373 FcStrHashed (const FcChar8
*name
)
1375 FcChar32 hash
= FcStringHash (name
);
1376 struct objectBucket
**p
;
1377 struct objectBucket
*b
;
1379 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1380 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1386 FcStrStaticName (const FcChar8
*name
)
1388 FcChar32 hash
= FcStringHash (name
);
1389 struct objectBucket
**p
;
1390 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)))
1395 return (FcChar8
*) (b
+ 1);
1396 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1397 b
= malloc (size
+ sizeof (int));
1398 /* workaround glibc bug which reads strlen in groups of 4 */
1399 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1404 strcpy ((char *) (b
+ 1), (char *)name
);
1406 return (FcChar8
*) (b
+ 1);
1410 FcStrStaticNameFini (void)
1413 struct objectBucket
*b
, *next
;
1416 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1418 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1421 name
= (char *) (b
+ 1);
1422 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1423 FcMemFree (FC_MEM_STATICSTR
, size
);
1426 FcObjectBuckets
[i
] = 0;
1431 FcPatternFini (void)
1433 FcPatternBaseThawAll ();
1434 FcValueListThawAll ();
1435 FcStrStaticNameFini ();
1436 FcObjectStaticNameFini ();
1439 static FcPatternEltPtr
1440 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1442 FcPatternEltPtr
new;
1443 new.bank
= FC_BANK_DYNAMIC
;
1448 static FcPatternEltPtr
1449 FcPatternEltPtrCreateStatic (int bank
, int i
)
1451 FcPatternEltPtr
new;
1458 FcStrNewBank (void);
1460 FcStrNeededBytes (const FcChar8
* s
);
1462 FcStrNeededBytesAlign (void);
1464 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1465 static const FcChar8
*
1466 FcStrSerialize (int bank
, const FcChar8
* s
);
1468 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1471 FcValueListNewBank (void);
1473 FcValueListNeededBytes (FcValueList
* vl
);
1475 FcValueListNeededBytesAlign (void);
1477 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1478 static FcValueListPtr
1479 FcValueListSerialize(int bank
, FcValueList
*pi
);
1481 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1485 FcPatternNewBank (void)
1487 fcpattern_count
= 0;
1488 fcpatternelt_count
= 0;
1491 FcValueListNewBank();
1495 FcPatternNeededBytes (FcPattern
* p
)
1500 fcpatternelt_count
+= p
->num
;
1502 for (i
= 0; i
< p
->num
; i
++)
1504 c
= FcValueListNeededBytes (FcValueListPtrU
1505 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1511 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1515 FcPatternNeededBytesAlign (void)
1517 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1518 FcValueListNeededBytesAlign ();
1522 FcPatternEnsureBank (int bi
)
1528 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1530 int new_count
= bi
+ 4;
1531 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1535 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1538 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1542 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1543 _fcPatternElts
= ep
;
1545 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1548 _fcPatternElts
[i
] = 0;
1551 fcpattern_bank_count
= new_count
;
1554 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1559 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1561 int bi
= FcCacheBankToIndex(metadata
->bank
);
1563 if (!FcPatternEnsureBank(bi
))
1567 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1568 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1569 block_ptr
= (void *)((char *)block_ptr
+
1570 (sizeof (FcPattern
) * fcpattern_count
));
1572 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1573 fcpatternelt_ptr
= 0;
1574 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1575 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1576 block_ptr
= (void *)((char *)block_ptr
+
1577 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1579 metadata
->pattern_count
= fcpattern_count
;
1580 metadata
->patternelt_count
= fcpatternelt_count
;
1582 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1583 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1588 FcPatternSerialize (int bank
, FcPattern
*old
)
1591 FcPatternElt
*e
, *nep
;
1593 FcValueListPtr v
, nv_head
, nvp
;
1594 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1596 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1598 elts
= fcpatternelt_ptr
;
1599 nep
= &_fcPatternElts
[bi
][elts
];
1603 fcpatternelt_ptr
+= old
->num
;
1605 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1608 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1609 if (!FcValueListPtrU(nv_head
))
1611 nv
= FcValueListPtrU(nvp
);
1615 v
= FcValueListPtrU(v
)->next
,
1616 nv
= FcValueListPtrU(nv
->next
))
1619 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1621 nvp
= FcValueListSerialize
1622 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1627 nep
[i
].values
= nv_head
;
1628 nep
[i
].object
= e
->object
;
1631 p
->elts
= old
->elts
;
1632 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1635 p
->ref
= FC_REF_CONSTANT
;
1640 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1642 int bi
= FcCacheBankToIndex(metadata
->bank
);
1643 if (!FcPatternEnsureBank(bi
))
1646 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1647 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1648 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1649 block_ptr
= (void *)((char *)block_ptr
+
1650 (sizeof (FcPattern
) * metadata
->pattern_count
));
1652 FcMemAlloc (FC_MEM_PATELT
,
1653 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1654 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1655 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1656 block_ptr
= (void *)((char *)block_ptr
+
1657 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1659 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1660 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1666 FcValueListNewBank (void)
1668 fcvaluelist_count
= 0;
1675 FcValueListNeededBytes (FcValueList
*p
)
1682 vl
= FcValueListPtrU(vl
->next
))
1684 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1689 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1692 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1695 cum
+= FcStrNeededBytes(v
.u
.s
);
1699 fcvaluelist_count
++;
1700 cum
+= sizeof (FcValueList
);
1707 FcValueListNeededBytesAlign (void)
1709 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1710 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1714 FcValueListEnsureBank (int bi
)
1718 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1720 int new_count
= bi
+ 2, i
;
1722 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1726 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1728 _fcValueLists
= pvl
;
1729 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1730 _fcValueLists
[i
] = 0;
1732 fcvaluelist_bank_count
= new_count
;
1738 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1740 int bi
= FcCacheBankToIndex(metadata
->bank
);
1742 if (!FcValueListEnsureBank(bi
))
1745 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1746 fcvaluelist_ptr
= 0;
1747 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1748 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1749 block_ptr
= (void *)((char *)block_ptr
+
1750 (sizeof (FcValueList
) * fcvaluelist_count
));
1751 metadata
->valuelist_count
= fcvaluelist_count
;
1753 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1754 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1759 static FcValueListPtr
1760 FcValueListSerialize(int bank
, FcValueList
*pi
)
1764 int bi
= FcCacheBankToIndex(bank
);
1768 new.bank
= FC_BANK_DYNAMIC
;
1773 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1775 new.u
.stat
= fcvaluelist_ptr
++;
1776 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1777 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1783 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1785 return FcValueListPtrCreateDynamic(pi
);
1786 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1787 v
->type
|= FC_STORAGE_STATIC
;
1795 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1797 return FcValueListPtrCreateDynamic(pi
);
1798 v
->u
.c_off
= (char *)c
- (char *)v
;
1799 v
->type
|= FC_STORAGE_STATIC
;
1805 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1807 return FcValueListPtrCreateDynamic(pi
);
1808 v
->u
.l_off
= (char *)l
- (char *)v
;
1809 v
->type
|= FC_STORAGE_STATIC
;
1819 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1821 int bi
= FcCacheBankToIndex(metadata
->bank
);
1823 if (!FcValueListEnsureBank(bi
))
1826 FcMemAlloc (FC_MEM_VALLIST
,
1827 sizeof (FcValueList
) * metadata
->valuelist_count
);
1828 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1829 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1830 block_ptr
= (void *)((char *)block_ptr
+
1831 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1833 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1834 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1840 FcValueListPtrCreateDynamic(FcValueList
* p
)
1844 r
.bank
= FC_BANK_DYNAMIC
;
1849 static FcChar8
** static_strs
;
1850 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1852 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1858 struct objectBucket
*b
, *next
;
1861 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1863 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1866 name
= (char *) (b
+ 1);
1867 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1868 FcMemFree (FC_MEM_STATICSTR
, size
);
1871 FcStrBuckets
[i
] = 0;
1878 FcStrNeededBytes (const FcChar8
* s
)
1880 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1881 struct objectBucket
**p
;
1882 struct objectBucket
*b
;
1885 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1886 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1888 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1890 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1895 strcpy ((char *) (b
+ 1), (char *)s
);
1897 /* Yes, the following line is convoluted. However, it is
1898 * incorrect to replace the with a memset, because the C
1899 * specification doesn't guarantee that the null pointer is
1900 * the same as the zero bit pattern. */
1901 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1904 fcstr_count
+= strlen((char *)s
) + 1;
1905 return strlen((char *)s
) + 1;
1909 FcStrNeededBytesAlign (void)
1911 return __alignof__ (char);
1915 FcStrEnsureBank (int bi
)
1919 if (!static_strs
|| static_str_bank_count
<= bi
)
1921 int new_count
= bi
+ 4, i
;
1922 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1926 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1929 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1931 static_str_bank_count
= new_count
;
1937 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1939 int bi
= FcCacheBankToIndex(metadata
->bank
);
1940 if (!FcStrEnsureBank(bi
))
1943 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1944 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1945 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1946 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1947 metadata
->str_count
= fcstr_count
;
1953 static const FcChar8
*
1954 FcStrSerialize (int bank
, const FcChar8
* s
)
1956 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1957 struct objectBucket
**p
;
1958 struct objectBucket
*b
;
1959 int bi
= FcCacheBankToIndex(bank
);
1961 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1962 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1964 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1967 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1968 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1969 fcstr_ptr
+= strlen((char *)s
) + 1;
1970 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1978 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
1980 int bi
= FcCacheBankToIndex(metadata
->bank
);
1981 if (!FcStrEnsureBank(bi
))
1984 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
1985 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1986 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1987 block_ptr
= (void *)((char *)block_ptr
+
1988 (sizeof (char) * metadata
->str_count
));
1993 /* we don't store these in the FcPattern itself because
1994 * we don't want to serialize the directory names */
1996 /* I suppose this should be cleaned, too... */
1997 typedef struct _FcPatternDirMapping
{
2000 } FcPatternDirMapping
;
2002 #define PATTERNDIR_HASH_SIZE 31
2003 static struct patternDirBucket
{
2004 struct patternDirBucket
*next
;
2005 FcPatternDirMapping m
;
2006 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
2009 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
2011 struct patternDirBucket
*pb
;
2013 /* N.B. FcPatternHash fails, since it's contents-based, not
2014 * address-based, and we're in the process of mutating the FcPattern. */
2015 for (pb
= &FcPatternDirBuckets
2016 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2017 pb
->m
.p
!= p
&& pb
->next
;
2023 pb
->m
.fname
= fname
;
2027 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2030 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2034 pb
->next
->m
.fname
= fname
;
2038 FcPatternFindFullFname (const FcPattern
*p
)
2040 struct patternDirBucket
*pb
;
2042 for (pb
= &FcPatternDirBuckets
2043 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2052 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2055 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2056 FcPatternAddFullFname (new,
2058 ((FcChar8
*)FcPatternFindFullFname(orig
)));