]>
git.wh0rd.org - fontconfig.git/blob - src/fcpat.c
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 FcPatternCreate (void)
47 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
50 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
53 p
->elts
= FcPatternEltPtrCreateDynamic(0);
54 p
->bank
= FC_BANK_DYNAMIC
;
60 FcValueDestroy (FcValue v
)
64 if (!FcStrHashed (v
.u
.s
))
65 FcStrFree ((FcChar8
*) v
.u
.s
);
68 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
71 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
74 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
82 FcValueCanonicalize (const FcValue
*v
)
84 if (v
->type
& FC_STORAGE_STATIC
)
88 switch (v
->type
& ~FC_STORAGE_STATIC
)
91 new.u
.s
= fc_value_string(v
);
92 new.type
= FcTypeString
;
95 new.u
.c
= fc_value_charset(v
);
96 new.type
= FcTypeCharSet
;
99 new.u
.l
= fc_value_langset(v
);
100 new.type
= FcTypeLangSet
;
109 FcValueSave (FcValue v
)
113 v
.u
.s
= FcStrCopy (v
.u
.s
);
118 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
123 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
128 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
139 FcValueListDestroy (FcValueListPtr l
)
142 for (; FcValueListPtrU(l
); l
= next
)
144 switch (FcValueListPtrU(l
)->value
.type
) {
146 if (!FcStrHashed ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
))
147 FcStrFree ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
);
150 FcMatrixFree ((FcMatrix
*)FcValueListPtrU(l
)->value
.u
.m
);
154 ((FcCharSet
*) (FcValueListPtrU(l
)->value
.u
.c
));
158 ((FcLangSet
*) (FcValueListPtrU(l
)->value
.u
.l
));
163 next
= FcValueListPtrU(l
)->next
;
164 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
165 if (l
.bank
== FC_BANK_DYNAMIC
)
171 FcValueEqual (FcValue va
, FcValue vb
)
173 if (va
.type
!= vb
.type
)
175 if (va
.type
== FcTypeInteger
)
177 va
.type
= FcTypeDouble
;
180 if (vb
.type
== FcTypeInteger
)
182 vb
.type
= FcTypeDouble
;
185 if (va
.type
!= vb
.type
)
192 return va
.u
.i
== vb
.u
.i
;
194 return va
.u
.d
== vb
.u
.d
;
196 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
198 return va
.u
.b
== vb
.u
.b
;
200 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
202 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
204 return va
.u
.f
== vb
.u
.f
;
206 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
212 FcDoubleHash (double d
)
222 FcStringHash (const FcChar8
*s
)
229 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
234 FcValueHash (const FcValue
*v
)
236 switch (fc_storage_type(v
)) {
240 return (FcChar32
) v
->u
.i
;
242 return FcDoubleHash (v
->u
.d
);
244 return FcStringHash (fc_value_string(v
));
246 return (FcChar32
) v
->u
.b
;
248 return (FcDoubleHash (v
->u
.m
->xx
) ^
249 FcDoubleHash (v
->u
.m
->xy
) ^
250 FcDoubleHash (v
->u
.m
->yx
) ^
251 FcDoubleHash (v
->u
.m
->yy
));
253 return (FcChar32
) fc_value_charset(v
)->num
;
255 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
->u
.f
)->family_name
) ^
256 FcStringHash ((const FcChar8
*) ((FT_Face
) v
->u
.f
)->style_name
);
258 return FcLangSetHash (fc_value_langset(v
));
264 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
266 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
269 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
271 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
272 FcValueListPtrU(lb
)->value
))
274 la
= FcValueListPtrU(la
)->next
;
275 lb
= FcValueListPtrU(lb
)->next
;
277 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
283 FcValueListHash (FcValueListPtr l
)
288 for (l_ptrU
= FcValueListPtrU(l
); l_ptrU
;
289 l_ptrU
= FcValueListPtrU(l_ptrU
->next
))
291 hash
= ((hash
<< 1) | (hash
>> 31)) ^ FcValueHash (&l_ptrU
->value
);
297 FcPatternDestroy (FcPattern
*p
)
301 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
304 for (i
= 0; i
< p
->num
; i
++)
305 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
308 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
310 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
311 free (FcPatternEltU(p
->elts
));
312 p
->elts
= FcPatternEltPtrCreateDynamic(0);
315 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
320 FcPatternPosition (const FcPattern
*p
, const char *object
)
322 int low
, high
, mid
, c
;
325 obj
= FcObjectToPtr(object
);
332 mid
= (low
+ high
) >> 1;
333 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
347 FcPatternFindElt (const FcPattern
*p
, const char *object
)
349 int i
= FcPatternPosition (p
, object
);
352 return FcPatternEltU(p
->elts
)+i
;
356 FcPatternInsertElt (FcPattern
*p
, const char *object
)
361 i
= FcPatternPosition (p
, object
);
366 /* reallocate array */
367 if (p
->num
+ 1 >= p
->size
)
369 int s
= p
->size
+ 16;
370 if (FcPatternEltU(p
->elts
))
372 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
373 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
374 if (!e
) /* maybe it was mmapped */
376 e
= malloc(s
* sizeof (FcPatternElt
));
378 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
382 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
385 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
387 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
388 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
391 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
392 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
393 FcValueListPtrCreateDynamic(0);
399 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
400 FcPatternEltU(p
->elts
) + i
,
401 sizeof (FcPatternElt
) *
407 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
408 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
411 return FcPatternEltU(p
->elts
)+i
;
415 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
422 if (pa
->num
!= pb
->num
)
424 for (i
= 0; i
< pa
->num
; i
++)
426 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
427 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
429 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
430 (FcPatternEltU(pb
->elts
)+i
)->values
))
437 FcPatternHash (const FcPattern
*p
)
442 for (i
= 0; i
< p
->num
; i
++)
444 h
= (((h
<< 1) | (h
>> 31)) ^
445 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
446 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
452 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
454 FcPatternElt
*ea
, *eb
;
457 for (i
= 0; i
< os
->nobject
; i
++)
459 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
460 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
465 if (!FcValueListEqual (ea
->values
, eb
->values
))
478 FcPatternAddWithBinding (FcPattern
*p
,
481 FcValueBinding binding
,
485 FcValueListPtr
new, *prev
;
487 FcObjectPtr objectPtr
;
489 if (p
->ref
== FC_REF_CONSTANT
)
492 newp
= malloc (sizeof (FcValueList
));
496 memset(newp
, 0, sizeof (FcValueList
));
497 new = FcValueListPtrCreateDynamic(newp
);
498 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
500 if (value
.type
== FcTypeString
)
502 value
.u
.s
= FcStrStaticName (value
.u
.s
);
504 value
.type
= FcTypeVoid
;
507 value
= FcValueSave (value
);
508 if (value
.type
== FcTypeVoid
)
511 /* quick and dirty hack to enable FcCompareFamily/FcCompareString
512 * speedup: only allow strings to be added under the FC_FAMILY,
513 * FC_FOUNDRY, FC_STYLE, FC_RASTERIZER keys.
514 * and charsets under FC_CHARSET key.
515 * This is slightly semantically different from the old behaviour,
516 * but fonts shouldn't be getting non-strings here anyway.
517 * a better hack would use FcBaseObjectTypes to check all objects. */
518 objectPtr
= FcObjectToPtr(object
);
519 if ((objectPtr
== FcObjectToPtr(FC_FAMILY
)
520 || objectPtr
== FcObjectToPtr(FC_FOUNDRY
)
521 || objectPtr
== FcObjectToPtr(FC_STYLE
)
522 || objectPtr
== FcObjectToPtr(FC_RASTERIZER
))
523 && value
.type
!= FcTypeString
)
525 if (objectPtr
== FcObjectToPtr(FC_CHARSET
)
526 && value
.type
!= FcTypeCharSet
)
529 FcValueListPtrU(new)->value
= value
;
530 FcValueListPtrU(new)->binding
= binding
;
531 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
533 e
= FcPatternInsertElt (p
, object
);
539 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
545 FcValueListPtrU(new)->next
= e
->values
;
552 switch (value
.type
) {
554 FcStrFree ((FcChar8
*) value
.u
.s
);
557 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
560 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
563 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
569 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
570 free (FcValueListPtrU(new));
576 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
578 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
582 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
584 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
588 FcPatternDel (FcPattern
*p
, const char *object
)
592 e
= FcPatternFindElt (p
, object
);
597 FcValueListDestroy (e
->values
);
599 /* shuffle existing ones down */
601 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
602 sizeof (FcPatternElt
));
604 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
605 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
610 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
613 FcValueListPtr
*prev
, l
;
615 e
= FcPatternFindElt (p
, object
);
618 for (prev
= &e
->values
;
619 FcValueListPtrU(l
= *prev
);
620 prev
= &FcValueListPtrU(l
)->next
)
624 *prev
= FcValueListPtrU(l
)->next
;
625 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
626 FcValueListDestroy (l
);
627 if (!FcValueListPtrU(e
->values
))
628 FcPatternDel (p
, object
);
637 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
641 v
.type
= FcTypeInteger
;
643 return FcPatternAdd (p
, object
, v
, FcTrue
);
647 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
651 v
.type
= FcTypeDouble
;
653 return FcPatternAdd (p
, object
, v
, FcTrue
);
658 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
666 return FcPatternAdd (p
, object
, v
, FcTrue
);
669 v
.type
= FcTypeString
;
670 v
.u
.s
= FcStrStaticName(s
);
671 return FcPatternAdd (p
, object
, v
, FcTrue
);
675 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
679 v
.type
= FcTypeMatrix
;
681 return FcPatternAdd (p
, object
, v
, FcTrue
);
686 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
692 return FcPatternAdd (p
, object
, v
, FcTrue
);
696 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
700 v
.type
= FcTypeCharSet
;
701 v
.u
.c
= (FcCharSet
*)c
;
702 return FcPatternAdd (p
, object
, v
, FcTrue
);
706 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
710 v
.type
= FcTypeFTFace
;
712 return FcPatternAdd (p
, object
, v
, FcTrue
);
716 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
720 v
.type
= FcTypeLangSet
;
721 v
.u
.l
= (FcLangSet
*)ls
;
722 return FcPatternAdd (p
, object
, v
, FcTrue
);
726 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
731 e
= FcPatternFindElt (p
, object
);
733 return FcResultNoMatch
;
734 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
738 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
739 return FcResultMatch
;
747 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
752 r
= FcPatternGet (p
, object
, id
, &v
);
753 if (r
!= FcResultMatch
)
763 return FcResultTypeMismatch
;
765 return FcResultMatch
;
769 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
774 r
= FcPatternGet (p
, object
, id
, &v
);
775 if (r
!= FcResultMatch
)
785 return FcResultTypeMismatch
;
787 return FcResultMatch
;
791 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
796 r
= FcPatternGet (p
, object
, id
, &v
);
797 if (r
!= FcResultMatch
)
799 if (v
.type
!= FcTypeString
)
800 return FcResultTypeMismatch
;
802 *s
= (FcChar8
*) v
.u
.s
;
803 return FcResultMatch
;
807 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
812 r
= FcPatternGet (p
, object
, id
, &v
);
813 if (r
!= FcResultMatch
)
815 if (v
.type
!= FcTypeMatrix
)
816 return FcResultTypeMismatch
;
817 *m
= (FcMatrix
*)v
.u
.m
;
818 return FcResultMatch
;
823 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
828 r
= FcPatternGet (p
, object
, id
, &v
);
829 if (r
!= FcResultMatch
)
831 if (v
.type
!= FcTypeBool
)
832 return FcResultTypeMismatch
;
834 return FcResultMatch
;
838 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
843 r
= FcPatternGet (p
, object
, id
, &v
);
844 if (r
!= FcResultMatch
)
846 if (v
.type
!= FcTypeCharSet
)
847 return FcResultTypeMismatch
;
848 *c
= (FcCharSet
*)v
.u
.c
;
849 return FcResultMatch
;
853 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
858 r
= FcPatternGet (p
, object
, id
, &v
);
859 if (r
!= FcResultMatch
)
861 if (v
.type
!= FcTypeFTFace
)
862 return FcResultTypeMismatch
;
863 *f
= (FT_Face
) v
.u
.f
;
864 return FcResultMatch
;
868 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
873 r
= FcPatternGet (p
, object
, id
, &v
);
874 if (r
!= FcResultMatch
)
876 if (v
.type
!= FcTypeLangSet
)
877 return FcResultTypeMismatch
;
878 *ls
= (FcLangSet
*)v
.u
.l
;
879 return FcResultMatch
;
883 FcPatternDuplicate (const FcPattern
*orig
)
890 new = FcPatternCreate ();
894 e
= FcPatternEltU(orig
->elts
);
896 for (i
= 0; i
< orig
->num
; i
++)
898 for (l
= (e
+ i
)->values
;
900 l
= FcValueListPtrU(l
)->next
)
901 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
902 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
910 FcPatternDestroy (new);
916 FcPatternReference (FcPattern
*p
)
918 if (p
->ref
!= FC_REF_CONSTANT
)
923 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
927 FcPatternVapBuild (ret
, orig
, va
);
932 FcPatternBuild (FcPattern
*orig
, ...)
937 FcPatternVapBuild (orig
, orig
, va
);
943 * Add all of the elements in 's' to 'p'
946 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
952 for (i
= 0; i
< s
->num
; i
++)
954 e
= FcPatternEltU(s
->elts
)+i
;
955 for (v
= e
->values
; FcValueListPtrU(v
);
956 v
= FcValueListPtrU(v
)->next
)
958 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
959 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
960 FcValueListPtrU(v
)->binding
, FcTrue
))
967 #define OBJECT_HASH_SIZE 31
968 static struct objectBucket
{
969 struct objectBucket
*next
;
971 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
974 FcStrHashed (const FcChar8
*name
)
976 FcChar32 hash
= FcStringHash (name
);
977 struct objectBucket
**p
;
978 struct objectBucket
*b
;
980 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
981 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
987 FcStrStaticName (const FcChar8
*name
)
989 FcChar32 hash
= FcStringHash (name
);
990 struct objectBucket
**p
;
991 struct objectBucket
*b
;
994 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
995 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
996 return (FcChar8
*) (b
+ 1);
997 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
998 b
= malloc (size
+ sizeof (int));
999 /* workaround glibc bug which reads strlen in groups of 4 */
1000 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1005 strcpy ((char *) (b
+ 1), (char *)name
);
1007 return (FcChar8
*) (b
+ 1);
1011 FcStrStaticNameFini (void)
1014 struct objectBucket
*b
, *next
;
1017 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1019 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1022 name
= (char *) (b
+ 1);
1023 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1024 FcMemFree (FC_MEM_STATICSTR
, size
);
1027 FcObjectBuckets
[i
] = 0;
1032 FcPatternFini (void)
1034 FcStrStaticNameFini ();
1035 FcObjectStaticNameFini ();
1038 static FcPatternEltPtr
1039 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1041 FcPatternEltPtr
new;
1042 new.bank
= FC_BANK_DYNAMIC
;
1047 static FcPatternEltPtr
1048 FcPatternEltPtrCreateStatic (int bank
, int i
)
1050 FcPatternEltPtr
new;
1057 FcStrNewBank (void);
1059 FcStrNeededBytes (const FcChar8
* s
);
1061 FcStrNeededBytesAlign (void);
1063 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1064 static const FcChar8
*
1065 FcStrSerialize (int bank
, const FcChar8
* s
);
1067 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
);
1070 FcValueListNewBank (void);
1072 FcValueListNeededBytes (FcValueList
* vl
);
1074 FcValueListNeededBytesAlign (void);
1076 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1077 static FcValueListPtr
1078 FcValueListSerialize(int bank
, FcValueList
*pi
);
1080 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
);
1084 FcPatternNewBank (void)
1086 fcpattern_count
= 0;
1087 fcpatternelt_count
= 0;
1090 FcValueListNewBank();
1094 FcPatternNeededBytes (FcPattern
* p
)
1099 fcpatternelt_count
+= p
->num
;
1101 for (i
= 0; i
< p
->num
; i
++)
1103 c
= FcValueListNeededBytes (FcValueListPtrU
1104 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1110 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1114 FcPatternNeededBytesAlign (void)
1116 return fc_alignof (FcPattern
) + fc_alignof (FcPatternElt
) +
1117 FcValueListNeededBytesAlign ();
1121 FcPatternEnsureBank (int bi
)
1127 if (!_fcPatterns
|| fcpattern_bank_count
<= bi
)
1129 int new_count
= bi
+ 4;
1130 pp
= realloc (_fcPatterns
, sizeof (FcPattern
*) * new_count
);
1134 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1137 ep
= realloc (_fcPatternElts
, sizeof (FcPatternElt
*) * new_count
);
1141 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1142 _fcPatternElts
= ep
;
1144 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1147 _fcPatternElts
[i
] = 0;
1150 fcpattern_bank_count
= new_count
;
1153 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1158 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1160 int bi
= FcCacheBankToIndex(metadata
->bank
);
1162 if (!FcPatternEnsureBank(bi
))
1166 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1167 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1168 block_ptr
= (void *)((char *)block_ptr
+
1169 (sizeof (FcPattern
) * fcpattern_count
));
1171 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1172 fcpatternelt_ptr
= 0;
1173 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1174 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1175 block_ptr
= (void *)((char *)block_ptr
+
1176 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1178 metadata
->pattern_count
= fcpattern_count
;
1179 metadata
->patternelt_count
= fcpatternelt_count
;
1181 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1182 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1187 FcPatternSerialize (int bank
, FcPattern
*old
)
1190 FcPatternElt
*e
, *nep
;
1192 FcValueListPtr v
, nv_head
, nvp
;
1193 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1195 p
= &_fcPatterns
[bi
][fcpattern_ptr
++];
1197 elts
= fcpatternelt_ptr
;
1198 nep
= &_fcPatternElts
[bi
][elts
];
1202 fcpatternelt_ptr
+= old
->num
;
1204 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1207 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1208 if (!FcValueListPtrU(nv_head
))
1210 nv
= FcValueListPtrU(nvp
);
1214 v
= FcValueListPtrU(v
)->next
,
1215 nv
= FcValueListPtrU(nv
->next
))
1218 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1220 nvp
= FcValueListSerialize
1221 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1226 nep
[i
].values
= nv_head
;
1227 nep
[i
].object
= e
->object
;
1230 p
->elts
= old
->elts
;
1231 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1234 p
->ref
= FC_REF_CONSTANT
;
1239 FcPatternUnserialize (FcCache
* metadata
, void *block_ptr
)
1241 int bi
= FcCacheBankToIndex(metadata
->bank
);
1242 if (!FcPatternEnsureBank(bi
))
1245 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
->pattern_count
);
1246 block_ptr
= ALIGN(block_ptr
, FcPattern
);
1247 _fcPatterns
[bi
] = (FcPattern
*)block_ptr
;
1248 block_ptr
= (void *)((char *)block_ptr
+
1249 (sizeof (FcPattern
) * metadata
->pattern_count
));
1251 FcMemAlloc (FC_MEM_PATELT
,
1252 sizeof (FcPatternElt
) * metadata
->patternelt_count
);
1253 block_ptr
= ALIGN(block_ptr
, FcPatternElt
);
1254 _fcPatternElts
[bi
] = (FcPatternElt
*)block_ptr
;
1255 block_ptr
= (void *)((char *)block_ptr
+
1256 (sizeof (FcPatternElt
) * metadata
->patternelt_count
));
1258 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1259 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1265 FcValueListNewBank (void)
1267 fcvaluelist_count
= 0;
1274 FcValueListNeededBytes (FcValueList
*p
)
1281 vl
= FcValueListPtrU(vl
->next
))
1283 /* unserialize just in case */
1284 FcValue v
= FcValueCanonicalize(&vl
->value
);
1289 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1292 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1295 cum
+= FcStrNeededBytes(v
.u
.s
);
1299 fcvaluelist_count
++;
1300 cum
+= sizeof (FcValueList
);
1307 FcValueListNeededBytesAlign (void)
1309 return FcCharSetNeededBytesAlign() + FcLangSetNeededBytesAlign() +
1310 FcStrNeededBytesAlign() + fc_alignof (FcValueList
);
1314 FcValueListEnsureBank (int bi
)
1318 if (!_fcValueLists
|| fcvaluelist_bank_count
<= bi
)
1320 int new_count
= bi
+ 2, i
;
1322 pvl
= realloc (_fcValueLists
, sizeof (FcValueList
*) * new_count
);
1326 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1328 _fcValueLists
= pvl
;
1329 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1330 _fcValueLists
[i
] = 0;
1332 fcvaluelist_bank_count
= new_count
;
1338 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1340 int bi
= FcCacheBankToIndex(metadata
->bank
);
1342 if (!FcValueListEnsureBank(bi
))
1345 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1346 fcvaluelist_ptr
= 0;
1347 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1348 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1349 block_ptr
= (void *)((char *)block_ptr
+
1350 (sizeof (FcValueList
) * fcvaluelist_count
));
1351 metadata
->valuelist_count
= fcvaluelist_count
;
1353 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1354 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1359 static FcValueListPtr
1360 FcValueListSerialize(int bank
, FcValueList
*pi
)
1364 int bi
= FcCacheBankToIndex(bank
);
1368 new.bank
= FC_BANK_DYNAMIC
;
1373 _fcValueLists
[bi
][fcvaluelist_ptr
] = *pi
;
1375 new.u
.stat
= fcvaluelist_ptr
++;
1376 _fcValueLists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1377 v
= &_fcValueLists
[bi
][new.u
.stat
].value
;
1383 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1385 return FcValueListPtrCreateDynamic(pi
);
1386 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1387 v
->type
|= FC_STORAGE_STATIC
;
1395 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1397 return FcValueListPtrCreateDynamic(pi
);
1398 v
->u
.c_off
= (char *)c
- (char *)v
;
1399 v
->type
|= FC_STORAGE_STATIC
;
1405 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1407 return FcValueListPtrCreateDynamic(pi
);
1408 v
->u
.l_off
= (char *)l
- (char *)v
;
1409 v
->type
|= FC_STORAGE_STATIC
;
1419 FcValueListUnserialize (FcCache
* metadata
, void *block_ptr
)
1421 int bi
= FcCacheBankToIndex(metadata
->bank
);
1423 if (!FcValueListEnsureBank(bi
))
1426 FcMemAlloc (FC_MEM_VALLIST
,
1427 sizeof (FcValueList
) * metadata
->valuelist_count
);
1428 block_ptr
= ALIGN(block_ptr
, FcValueList
);
1429 _fcValueLists
[bi
] = (FcValueList
*)block_ptr
;
1430 block_ptr
= (void *)((char *)block_ptr
+
1431 (sizeof (FcValueList
) * metadata
->valuelist_count
));
1433 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1434 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1440 FcValueListPtrCreateDynamic(FcValueList
* p
)
1444 r
.bank
= FC_BANK_DYNAMIC
;
1449 static FcChar8
** static_strs
;
1450 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1452 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1458 struct objectBucket
*b
, *next
;
1461 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1463 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1466 name
= (char *) (b
+ 1);
1467 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1468 FcMemFree (FC_MEM_STATICSTR
, size
);
1471 FcStrBuckets
[i
] = 0;
1478 FcStrNeededBytes (const FcChar8
* s
)
1480 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1481 struct objectBucket
**p
;
1482 struct objectBucket
*b
;
1484 FcChar8
*const null
= 0;
1486 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1487 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1489 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1491 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1496 strcpy ((char *) (b
+ 1), (char *)s
);
1498 /* Yes, the following line is convoluted. However, it is
1499 * incorrect to replace the with a memset, because the C
1500 * specification doesn't guarantee that the null pointer is
1501 * the same as the zero bit pattern. */
1502 /* Misaligned pointers are not guaranteed to work, either! */
1503 memcpy (((char *) (b
+ 1) + strlen((char *)s
) + 1), &null
, sizeof (null
));
1506 fcstr_count
+= strlen((char *)s
) + 1;
1507 return strlen((char *)s
) + 1;
1511 FcStrNeededBytesAlign (void)
1513 return fc_alignof (char);
1517 FcStrEnsureBank (int bi
)
1521 if (!static_strs
|| static_str_bank_count
<= bi
)
1523 int new_count
= bi
+ 4, i
;
1524 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1528 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1531 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1533 static_str_bank_count
= new_count
;
1539 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1541 int bi
= FcCacheBankToIndex(metadata
->bank
);
1542 if (!FcStrEnsureBank(bi
))
1545 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1546 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1547 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1548 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1549 metadata
->str_count
= fcstr_count
;
1555 static const FcChar8
*
1556 FcStrSerialize (int bank
, const FcChar8
* s
)
1558 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1559 struct objectBucket
**p
;
1560 struct objectBucket
*b
;
1561 int bi
= FcCacheBankToIndex(bank
);
1563 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1564 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1567 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
1570 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1571 t
= static_strs
[bi
] + fcstr_ptr
;
1572 memcpy ((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1, &t
, sizeof (FcChar8
*));
1573 fcstr_ptr
+= strlen((char *)s
) + 1;
1574 memcpy (&t
, ((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1, sizeof (FcChar8
*));
1582 FcStrUnserialize (FcCache
* metadata
, void *block_ptr
)
1584 int bi
= FcCacheBankToIndex(metadata
->bank
);
1585 if (!FcStrEnsureBank(bi
))
1588 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
->str_count
);
1589 block_ptr
= ALIGN (block_ptr
, FcChar8
);
1590 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1591 block_ptr
= (void *)((char *)block_ptr
+
1592 (sizeof (char) * metadata
->str_count
));