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
)
1034 v
.type
= FcTypeVoid
;
1036 return FcPatternAdd (p
, object
, v
, FcTrue
);
1039 v
.type
= FcTypeString
;
1040 v
.u
.s
= FcStrStaticName(s
);
1041 return FcPatternAdd (p
, object
, v
, FcTrue
);
1045 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1049 v
.type
= FcTypeMatrix
;
1051 return FcPatternAdd (p
, object
, v
, FcTrue
);
1056 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1060 v
.type
= FcTypeBool
;
1062 return FcPatternAdd (p
, object
, v
, FcTrue
);
1066 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1070 v
.type
= FcTypeCharSet
;
1071 v
.u
.c
= (FcCharSet
*)c
;
1072 return FcPatternAdd (p
, object
, v
, FcTrue
);
1076 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1080 v
.type
= FcTypeFTFace
;
1082 return FcPatternAdd (p
, object
, v
, FcTrue
);
1086 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1090 v
.type
= FcTypeLangSet
;
1091 v
.u
.l
= (FcLangSet
*)ls
;
1092 return FcPatternAdd (p
, object
, v
, FcTrue
);
1096 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1101 e
= FcPatternFindElt (p
, object
);
1103 return FcResultNoMatch
;
1104 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1108 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1109 return FcResultMatch
;
1113 return FcResultNoId
;
1117 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1122 r
= FcPatternGet (p
, object
, id
, &v
);
1123 if (r
!= FcResultMatch
)
1133 return FcResultTypeMismatch
;
1135 return FcResultMatch
;
1139 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1144 r
= FcPatternGet (p
, object
, id
, &v
);
1145 if (r
!= FcResultMatch
)
1152 *d
= (double) v
.u
.i
;
1155 return FcResultTypeMismatch
;
1157 return FcResultMatch
;
1161 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1166 r
= FcPatternGet (p
, object
, id
, &v
);
1167 if (r
!= FcResultMatch
)
1169 if (v
.type
!= FcTypeString
)
1170 return FcResultTypeMismatch
;
1172 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1174 const char *fn
, *fpath
;
1178 fn
= FcPatternFindFullFname(p
);
1181 *s
= (FcChar8
*) fn
;
1182 return FcResultMatch
;
1187 *s
= (FcChar8
*) v
.u
.s
;
1188 return FcResultMatch
;
1191 fpath
= FcCacheFindBankDir (p
->bank
);
1192 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1193 fname
= malloc (size
);
1195 return FcResultOutOfMemory
;
1197 FcMemAlloc (FC_MEM_STRING
, size
);
1198 strcpy ((char *)fname
, (char *)fpath
);
1199 strcat ((char *)fname
, "/");
1200 strcat ((char *)fname
, (char *)v
.u
.s
);
1202 FcPatternAddFullFname (p
, (const char *)fname
);
1203 *s
= (FcChar8
*)fname
;
1204 return FcResultMatch
;
1207 *s
= (FcChar8
*) v
.u
.s
;
1208 return FcResultMatch
;
1212 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1217 r
= FcPatternGet (p
, object
, id
, &v
);
1218 if (r
!= FcResultMatch
)
1220 if (v
.type
!= FcTypeMatrix
)
1221 return FcResultTypeMismatch
;
1222 *m
= (FcMatrix
*)v
.u
.m
;
1223 return FcResultMatch
;
1228 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1233 r
= FcPatternGet (p
, object
, id
, &v
);
1234 if (r
!= FcResultMatch
)
1236 if (v
.type
!= FcTypeBool
)
1237 return FcResultTypeMismatch
;
1239 return FcResultMatch
;
1243 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1248 r
= FcPatternGet (p
, object
, id
, &v
);
1249 if (r
!= FcResultMatch
)
1251 if (v
.type
!= FcTypeCharSet
)
1252 return FcResultTypeMismatch
;
1253 *c
= (FcCharSet
*)v
.u
.c
;
1254 return FcResultMatch
;
1258 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1263 r
= FcPatternGet (p
, object
, id
, &v
);
1264 if (r
!= FcResultMatch
)
1266 if (v
.type
!= FcTypeFTFace
)
1267 return FcResultTypeMismatch
;
1268 *f
= (FT_Face
) v
.u
.f
;
1269 return FcResultMatch
;
1273 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1278 r
= FcPatternGet (p
, object
, id
, &v
);
1279 if (r
!= FcResultMatch
)
1281 if (v
.type
!= FcTypeLangSet
)
1282 return FcResultTypeMismatch
;
1283 *ls
= (FcLangSet
*)v
.u
.l
;
1284 return FcResultMatch
;
1288 FcPatternDuplicate (const FcPattern
*orig
)
1295 new = FcPatternCreate ();
1299 e
= FcPatternEltU(orig
->elts
);
1301 for (i
= 0; i
< orig
->num
; i
++)
1303 for (l
= (e
+ i
)->values
;
1305 l
= FcValueListPtrU(l
)->next
)
1306 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1307 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1311 FcPatternTransferFullFname (new, orig
);
1316 FcPatternDestroy (new);
1322 FcPatternReference (FcPattern
*p
)
1324 if (p
->ref
!= FC_REF_CONSTANT
)
1329 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1333 FcPatternVapBuild (ret
, orig
, va
);
1338 FcPatternBuild (FcPattern
*orig
, ...)
1342 va_start (va
, orig
);
1343 FcPatternVapBuild (orig
, orig
, va
);
1349 * Add all of the elements in 's' to 'p'
1352 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1358 for (i
= 0; i
< s
->num
; i
++)
1360 e
= FcPatternEltU(s
->elts
)+i
;
1361 for (v
= e
->values
; FcValueListPtrU(v
);
1362 v
= FcValueListPtrU(v
)->next
)
1364 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1365 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1366 FcValueListPtrU(v
)->binding
, FcTrue
))
1373 #define OBJECT_HASH_SIZE 31
1374 static struct objectBucket
{
1375 struct objectBucket
*next
;
1377 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1380 FcStrHashed (const FcChar8
*name
)
1382 FcChar32 hash
= FcStringHash (name
);
1383 struct objectBucket
**p
;
1384 struct objectBucket
*b
;
1386 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1387 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1393 FcStrStaticName (const FcChar8
*name
)
1395 FcChar32 hash
= FcStringHash (name
);
1396 struct objectBucket
**p
;
1397 struct objectBucket
*b
;
1400 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1401 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1402 return (FcChar8
*) (b
+ 1);
1403 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1404 b
= malloc (size
+ sizeof (int));
1405 /* workaround glibc bug which reads strlen in groups of 4 */
1406 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1411 strcpy ((char *) (b
+ 1), (char *)name
);
1413 return (FcChar8
*) (b
+ 1);
1417 FcStrStaticNameFini (void)
1420 struct objectBucket
*b
, *next
;
1423 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1425 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1428 name
= (char *) (b
+ 1);
1429 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1430 FcMemFree (FC_MEM_STATICSTR
, size
);
1433 FcObjectBuckets
[i
] = 0;
1438 FcPatternFini (void)
1440 FcPatternBaseThawAll ();
1441 FcValueListThawAll ();
1442 FcStrStaticNameFini ();
1443 FcObjectStaticNameFini ();
1446 static FcPatternEltPtr
1447 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1449 FcPatternEltPtr
new;
1450 new.bank
= FC_BANK_DYNAMIC
;
1455 static FcPatternEltPtr
1456 FcPatternEltPtrCreateStatic (int bank
, int i
)
1458 FcPatternEltPtr
new;
1465 FcStrNewBank (void);
1467 FcStrNeededBytes (const FcChar8
* s
);
1469 FcStrNeededBytesAlign (void);
1471 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1472 static const FcChar8
*
1473 FcStrSerialize (int bank
, const FcChar8
* s
);
1475 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1478 FcValueListNewBank (void);
1480 FcValueListNeededBytes (FcValueList
* vl
);
1482 FcValueListNeededBytesAlign (void);
1484 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1485 static FcValueListPtr
1486 FcValueListSerialize(int bank
, FcValueList
*pi
);
1488 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1492 FcPatternNewBank (void)
1494 fcpattern_count
= 0;
1495 fcpatternelt_count
= 0;
1498 FcValueListNewBank();
1502 FcPatternNeededBytes (FcPattern
* p
)
1507 fcpatternelt_count
+= p
->num
;
1509 for (i
= 0; i
< p
->num
; i
++)
1511 c
= FcValueListNeededBytes (FcValueListPtrU
1512 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1518 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1522 FcPatternNeededBytesAlign (void)
1524 return __alignof__ (FcPattern
) + __alignof__ (FcPatternElt
) +
1525 FcValueListNeededBytesAlign ();
1529 FcPatternEnsureBank (int bi
)
1535 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1537 int new_count
= bi
+ 4;
1538 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1542 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1545 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1549 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1550 _fcPatternElts
= ep
;
1552 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1555 _fcPatternElts
[i
] = 0;
1558 fcpattern_bank_count
= new_count
;
1561 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1566 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1568 int bi
= FcCacheBankToIndex(metadata
->bank
);
1570 if (!FcPatternEnsureBank(bi
))
1574 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1575 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1576 block_ptr
= (void *)((char *)block_ptr
+
1577 (sizeof (FcPattern
) * fcpattern_count
));
1579 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1580 fcpatternelt_ptr
= 0;
1581 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1582 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1583 block_ptr
= (void *)((char *)block_ptr
+
1584 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1586 metadata
->pattern_count
= fcpattern_count
;
1587 metadata
->patternelt_count
= fcpatternelt_count
;
1589 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1590 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1595 FcPatternSerialize (int bank
, FcPattern
*old
)
1598 FcPatternElt
*e
, *nep
;
1600 FcValueListPtr v
, nv_head
, nvp
;
1601 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1603 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1605 elts
= fcpatternelt_ptr
;
1606 nep
= &_fcPatternElts
[bi
][elts
];
1610 fcpatternelt_ptr
+= old
->num
;
1612 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1615 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1616 if (!FcValueListPtrU(nv_head
))
1618 nv
= FcValueListPtrU(nvp
);
1622 v
= FcValueListPtrU(v
)->next
,
1623 nv
= FcValueListPtrU(nv
->next
))
1626 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1628 nvp
= FcValueListSerialize
1629 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1634 nep
[i
].values
= nv_head
;
1635 nep
[i
].object
= e
->object
;
1638 p
->elts
= old
->elts
;
1639 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1642 p
->ref
= FC_REF_CONSTANT
;
1647 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1649 int bi
= FcCacheBankToIndex(metadata
->bank
);
1650 if (!FcPatternEnsureBank(bi
))
1653 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1654 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1655 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1656 block_ptr
= (void *)((char *)block_ptr
+
1657 (sizeof (FcPattern
) * metadata
->pattern_count
));
1659 FcMemAlloc (FC_MEM_PATELT
,
1660 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1661 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1662 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1663 block_ptr
= (void *)((char *)block_ptr
+
1664 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1666 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1667 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1673 FcValueListNewBank (void)
1675 fcvaluelist_count
= 0;
1682 FcValueListNeededBytes (FcValueList
*p
)
1689 vl
= FcValueListPtrU(vl
->next
))
1691 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1696 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1699 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1702 cum
+= FcStrNeededBytes(v
.u
.s
);
1706 fcvaluelist_count
++;
1707 cum
+= sizeof (FcValueList
);
1714 FcValueListNeededBytesAlign (void)
1716 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1717 FcStrNeededBytesAlign() + __alignof__ (FcValueList
);
1721 FcValueListEnsureBank (int bi
)
1725 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1727 int new_count
= bi
+ 2, i
;
1729 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1733 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1735 _fcValueLists
= pvl
;
1736 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1737 _fcValueLists
[i
] = 0;
1739 fcvaluelist_bank_count
= new_count
;
1745 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1747 int bi
= FcCacheBankToIndex(metadata
->bank
);
1749 if (!FcValueListEnsureBank(bi
))
1752 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1753 fcvaluelist_ptr
= 0;
1754 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1755 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1756 block_ptr
= (void *)((char *)block_ptr
+
1757 (sizeof (FcValueList
) * fcvaluelist_count
));
1758 metadata
->valuelist_count
= fcvaluelist_count
;
1760 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1761 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1766 static FcValueListPtr
1767 FcValueListSerialize(int bank
, FcValueList
*pi
)
1771 int bi
= FcCacheBankToIndex(bank
);
1775 new.bank
= FC_BANK_DYNAMIC
;
1780 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1782 new.u
.stat
= fcvaluelist_ptr
++;
1783 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1784 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1790 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1792 return FcValueListPtrCreateDynamic(pi
);
1793 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1794 v
->type
|= FC_STORAGE_STATIC
;
1802 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1804 return FcValueListPtrCreateDynamic(pi
);
1805 v
->u
.c_off
= (char *)c
- (char *)v
;
1806 v
->type
|= FC_STORAGE_STATIC
;
1812 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1814 return FcValueListPtrCreateDynamic(pi
);
1815 v
->u
.l_off
= (char *)l
- (char *)v
;
1816 v
->type
|= FC_STORAGE_STATIC
;
1826 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1828 int bi
= FcCacheBankToIndex(metadata
->bank
);
1830 if (!FcValueListEnsureBank(bi
))
1833 FcMemAlloc (FC_MEM_VALLIST
,
1834 sizeof (FcValueList
) * metadata
->valuelist_count
);
1835 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1836 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1837 block_ptr
= (void *)((char *)block_ptr
+
1838 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1840 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1841 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1847 FcValueListPtrCreateDynamic(FcValueList
* p
)
1851 r
.bank
= FC_BANK_DYNAMIC
;
1856 static FcChar8
** static_strs
;
1857 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1859 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1865 struct objectBucket
*b
, *next
;
1868 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1870 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1873 name
= (char *) (b
+ 1);
1874 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1875 FcMemFree (FC_MEM_STATICSTR
, size
);
1878 FcStrBuckets
[i
] = 0;
1885 FcStrNeededBytes (const FcChar8
* s
)
1887 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1888 struct objectBucket
**p
;
1889 struct objectBucket
*b
;
1892 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1893 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1895 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1897 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1902 strcpy ((char *) (b
+ 1), (char *)s
);
1904 /* Yes, the following line is convoluted. However, it is
1905 * incorrect to replace the with a memset, because the C
1906 * specification doesn't guarantee that the null pointer is
1907 * the same as the zero bit pattern. */
1908 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1911 fcstr_count
+= strlen((char *)s
) + 1;
1912 return strlen((char *)s
) + 1;
1916 FcStrNeededBytesAlign (void)
1918 return __alignof__ (char);
1922 FcStrEnsureBank (int bi
)
1926 if (!static_strs
|| static_str_bank_count
<= bi
)
1928 int new_count
= bi
+ 4, i
;
1929 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1933 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1936 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1938 static_str_bank_count
= new_count
;
1944 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1946 int bi
= FcCacheBankToIndex(metadata
->bank
);
1947 if (!FcStrEnsureBank(bi
))
1950 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1951 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1952 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1953 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1954 metadata
->str_count
= fcstr_count
;
1960 static const FcChar8
*
1961 FcStrSerialize (int bank
, const FcChar8
* s
)
1963 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1964 struct objectBucket
**p
;
1965 struct objectBucket
*b
;
1966 int bi
= FcCacheBankToIndex(bank
);
1968 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1969 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1971 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1974 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1975 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1976 fcstr_ptr
+= strlen((char *)s
) + 1;
1977 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1985 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
1987 int bi
= FcCacheBankToIndex(metadata
->bank
);
1988 if (!FcStrEnsureBank(bi
))
1991 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
1992 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1993 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1994 block_ptr
= (void *)((char *)block_ptr
+
1995 (sizeof (char) * metadata
->str_count
));
2000 /* we don't store these in the FcPattern itself because
2001 * we don't want to serialize the directory names */
2003 /* I suppose this should be cleaned, too... */
2004 typedef struct _FcPatternDirMapping
{
2007 } FcPatternDirMapping
;
2009 #define PATTERNDIR_HASH_SIZE 31
2010 static struct patternDirBucket
{
2011 struct patternDirBucket
*next
;
2012 FcPatternDirMapping m
;
2013 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
2016 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
2018 struct patternDirBucket
*pb
;
2020 /* N.B. FcPatternHash fails, since it's contents-based, not
2021 * address-based, and we're in the process of mutating the FcPattern. */
2022 for (pb
= &FcPatternDirBuckets
2023 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2024 pb
->m
.p
!= p
&& pb
->next
;
2030 pb
->m
.fname
= fname
;
2034 pb
->next
= malloc (sizeof (struct patternDirBucket
));
2037 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
2041 pb
->next
->m
.fname
= fname
;
2045 FcPatternFindFullFname (const FcPattern
*p
)
2047 struct patternDirBucket
*pb
;
2049 for (pb
= &FcPatternDirBuckets
2050 [((unsigned long)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
2059 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
2062 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
2063 FcPatternAddFullFname (new,
2065 ((FcChar8
*)FcPatternFindFullFname(orig
)));