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.
31 static FcPattern
* fcpatterns
= NULL
;
32 static int fcpattern_ptr
, fcpattern_count
;
33 static FcPatternElt
* fcpatternelts
= NULL
;
34 static int fcpatternelt_ptr
, fcpatternelt_count
;
35 static FcValueList
* fcvaluelists
= NULL
;
36 static int fcvaluelist_ptr
, fcvaluelist_count
;
39 FcPatternEltIsDynamic (FcPatternEltPtr pei
);
41 static FcPatternEltPtr
42 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
);
45 FcPatternCreate (void)
49 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
52 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
55 p
->elts
= FcPatternEltPtrCreateDynamic(0);
61 FcValueDestroy (FcValue v
)
65 FcObjectPtrDestroy (v
.u
.si
);
68 FcMatrixPtrDestroy (v
.u
.mi
);
71 FcCharSetPtrDestroy (v
.u
.ci
);
74 FcLangSetPtrDestroy (v
.u
.li
);
82 FcValueSave (FcValue v
)
86 v
.u
.si
= FcObjectStaticName(FcObjectPtrU(v
.u
.si
));
87 if (!FcObjectPtrU(v
.u
.si
))
91 v
.u
.mi
= FcMatrixPtrCreateDynamic
92 (FcMatrixCopy (FcMatrixPtrU(v
.u
.mi
)));
93 if (!FcMatrixPtrU(v
.u
.mi
))
97 v
.u
.ci
= FcCharSetPtrCreateDynamic
98 (FcCharSetCopy (FcCharSetPtrU(v
.u
.ci
)));
99 if (!FcCharSetPtrU(v
.u
.ci
))
103 v
.u
.li
= FcLangSetPtrCreateDynamic
104 (FcLangSetCopy (FcLangSetPtrU(v
.u
.li
)));
105 if (!FcLangSetPtrU(v
.u
.li
))
115 FcValueListDestroy (FcValueListPtr l
)
118 for (; FcValueListPtrU(l
); l
= next
)
120 switch (FcValueListPtrU(l
)->value
.type
) {
122 FcObjectPtrDestroy (FcValueListPtrU(l
)->value
.u
.si
);
125 FcMatrixPtrDestroy (FcValueListPtrU(l
)->value
.u
.mi
);
129 (FcCharSetPtrU (FcValueListPtrU(l
)->value
.u
.ci
));
133 (FcLangSetPtrU (FcValueListPtrU(l
)->value
.u
.li
));
138 next
= FcValueListPtrU(l
)->next
;
140 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
141 if (l
.storage
== FcStorageDynamic
)
147 FcValueEqual (FcValue va
, FcValue vb
)
149 if (va
.type
!= vb
.type
)
151 if (va
.type
== FcTypeInteger
)
153 va
.type
= FcTypeDouble
;
156 if (vb
.type
== FcTypeInteger
)
158 vb
.type
= FcTypeDouble
;
161 if (va
.type
!= vb
.type
)
168 return va
.u
.i
== vb
.u
.i
;
170 return va
.u
.d
== vb
.u
.d
;
172 return FcStrCmpIgnoreCase (FcObjectPtrU(va
.u
.si
),
173 FcObjectPtrU(vb
.u
.si
)) == 0;
175 return va
.u
.b
== vb
.u
.b
;
177 return FcMatrixEqual (FcMatrixPtrU(va
.u
.mi
),
178 FcMatrixPtrU(vb
.u
.mi
));
180 return FcCharSetEqual (FcCharSetPtrU(va
.u
.ci
),
181 FcCharSetPtrU(vb
.u
.ci
));
183 return va
.u
.f
== vb
.u
.f
;
185 return FcLangSetEqual (FcLangSetPtrU(va
.u
.li
),
186 FcLangSetPtrU(vb
.u
.li
));
192 FcDoubleHash (double d
)
202 FcStringHash (const FcChar8
*s
)
209 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
214 FcValueHash (FcValue v
)
220 return (FcChar32
) v
.u
.i
;
222 return FcDoubleHash (v
.u
.d
);
224 return FcStringHash (FcObjectPtrU(v
.u
.si
));
226 return (FcChar32
) v
.u
.b
;
229 FcMatrix
* m
= FcMatrixPtrU(v
.u
.mi
);
230 return (FcDoubleHash (m
->xx
) ^
231 FcDoubleHash (m
->xy
) ^
232 FcDoubleHash (m
->yx
) ^
233 FcDoubleHash (m
->yy
));
236 return (FcChar32
) (FcCharSetPtrU(v
.u
.ci
))->num
;
238 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
239 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
241 return FcLangSetHash (FcLangSetPtrU(v
.u
.li
));
247 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
249 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
252 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
254 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
255 FcValueListPtrU(lb
)->value
))
257 la
= FcValueListPtrU(la
)->next
;
258 lb
= FcValueListPtrU(lb
)->next
;
260 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
266 FcValueListHash (FcValueListPtr l
)
270 while (FcValueListPtrU(l
))
272 hash
= ((hash
<< 1) | (hash
>> 31)) ^
273 FcValueHash (FcValueListPtrU(l
)->value
);
274 l
= FcValueListPtrU(l
)->next
;
280 FcPatternDestroy (FcPattern
*p
)
284 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
287 for (i
= 0; i
< p
->num
; i
++)
288 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
291 if (FcPatternEltU(p
->elts
) && FcPatternEltIsDynamic(p
->elts
))
293 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
294 free (FcPatternEltU(p
->elts
));
295 p
->elts
= FcPatternEltPtrCreateDynamic(0);
298 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
302 #define FC_VALUE_LIST_HASH_SIZE 257
303 #define FC_PATTERN_HASH_SIZE 67
305 typedef struct _FcValueListEnt FcValueListEnt
;
307 struct _FcValueListEnt
{
308 FcValueListEnt
*next
;
313 typedef union _FcValueListAlign
{
318 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
319 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
320 static char *FcValueListFrozenName
[] = {
333 FcValueListReport (void);
336 FcValueListReport (void)
340 printf ("Fc Frozen Values:\n");
341 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
342 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
343 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
344 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
347 static FcValueListEnt
*
348 FcValueListEntCreate (FcValueListPtr h
)
350 FcValueListAlign
*ea
;
358 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
360 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
361 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
362 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
363 // this leaks for some reason
364 ea
= malloc (sizeof (FcValueListAlign
));
367 new = malloc (n
* sizeof (FcValueList
));
370 memset(new, 0, n
* sizeof (FcValueList
));
371 FcMemAlloc (FC_MEM_VALLIST
, size
);
373 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
374 for (l
= h
; FcValueListPtrU(l
);
375 l
= FcValueListPtrU(l
)->next
, new++)
377 if (FcValueListPtrU(l
)->value
.type
== FcTypeString
)
379 new->value
.type
= FcTypeString
;
380 new->value
.u
.si
= FcObjectStaticName
381 (FcObjectPtrU(FcValueListPtrU(l
)->value
.u
.si
));
385 new->value
= FcValueSave (FcValueListPtrU(l
)->value
);
387 new->binding
= FcValueListPtrU(l
)->binding
;
388 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
390 new->next
= FcValueListPtrCreateDynamic(new + 1);
394 new->next
= FcValueListPtrCreateDynamic(0);
401 FcValueListEntDestroy (FcValueListEnt
*e
)
405 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
407 /* XXX: We should perform these two operations with "size" as
408 computed in FcValueListEntCreate, but we don't have access to
409 that value here. Without this, the FcValueListFrozenBytes
410 values will be wrong as will the FcMemFree counts.
412 FcValueListFrozenBytes[e->list->value.type] -= size;
413 FcMemFree (FC_MEM_VALLIST, size);
416 for (l
= e
->list
; FcValueListPtrU(l
);
417 l
= FcValueListPtrU(l
)->next
)
419 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
420 FcValueDestroy (FcValueListPtrU(l
)->value
);
422 /* XXX: Are we being too chummy with the implementation here to
423 free(e) when it was actually the enclosing FcValueListAlign
424 that was allocated? */
428 static int FcValueListTotal
;
429 static int FcValueListUsed
;
431 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
433 static FcValueListPtr
434 FcValueListFreeze (FcValueListPtr l
)
436 FcChar32 hash
= FcValueListHash (l
);
437 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
441 for (ent
= *bucket
; ent
; ent
= ent
->next
)
443 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
447 ent
= FcValueListEntCreate (l
);
449 return FcValueListPtrCreateDynamic(0);
459 FcValueListThawAll (void)
462 FcValueListEnt
*ent
, *next
;
464 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
466 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
469 FcValueListEntDestroy (ent
);
471 FcValueListHashTable
[i
] = 0;
474 FcValueListTotal
= 0;
479 FcPatternBaseHash (FcPattern
*b
)
481 FcChar32 hash
= b
->num
;
484 for (i
= 0; i
< b
->num
; i
++)
485 hash
= ((hash
<< 1) | (hash
>> 31)) ^
486 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
490 typedef struct _FcPatternEnt FcPatternEnt
;
492 struct _FcPatternEnt
{
498 static int FcPatternTotal
;
499 static int FcPatternUsed
;
501 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
504 FcPatternBaseFreeze (FcPattern
*b
)
508 FcChar32 hash
= FcPatternBaseHash (b
);
509 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
514 for (ent
= *bucket
; ent
; ent
= ent
->next
)
516 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
518 for (i
= 0; i
< b
->num
; i
++)
520 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
521 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
523 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
524 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
533 * Compute size of pattern + elts
535 ent
= malloc (sizeof (FcPatternEnt
));
539 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
542 ep
= FcPatternCreate();
546 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
549 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
551 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
555 ep
->ref
= FC_REF_CONSTANT
;
557 for (i
= 0; i
< b
->num
; i
++)
559 (FcPatternEltU(ep
->elts
)+i
)->values
=
560 (FcPatternEltU(b
->elts
)+i
)->values
;
561 (FcPatternEltU(ep
->elts
)+i
)->object
=
562 (FcPatternEltU(b
->elts
)+i
)->object
;
571 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
577 FcPatternBaseThawAll (void)
580 FcPatternEnt
*ent
, *next
;
582 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
584 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
589 FcPatternHashTable
[i
] = 0;
597 FcPatternFreeze (FcPattern
*p
)
599 FcPattern
*b
, *n
= 0;
603 if (p
->ref
== FC_REF_CONSTANT
)
606 b
= FcPatternCreate();
614 e
= malloc(b
->num
* sizeof (FcPatternElt
));
617 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
618 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
621 * Freeze object lists
623 for (i
= 0; i
< p
->num
; i
++)
625 (FcPatternEltU(b
->elts
)+i
)->object
=
626 (FcPatternEltU(p
->elts
)+i
)->object
;
627 (FcPatternEltU(b
->elts
)+i
)->values
=
628 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
629 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
635 n
= FcPatternBaseFreeze (b
);
637 if (FcDebug() & FC_DBG_MEMORY
)
639 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
640 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
644 free(FcPatternEltU(b
->elts
));
645 b
->elts
= FcPatternEltPtrCreateDynamic(0);
646 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
649 assert (FcPatternEqual (n
, p
));
655 FcPatternPosition (const FcPattern
*p
, const char *object
)
657 int low
, high
, mid
, c
;
660 obj
= FcObjectStaticName(object
);
667 mid
= (low
+ high
) >> 1;
668 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
682 FcPatternFindElt (const FcPattern
*p
, const char *object
)
684 int i
= FcPatternPosition (p
, object
);
687 return FcPatternEltU(p
->elts
)+i
;
691 FcPatternInsertElt (FcPattern
*p
, const char *object
)
696 i
= FcPatternPosition (p
, object
);
701 /* reallocate array */
702 if (p
->num
+ 1 >= p
->size
)
704 int s
= p
->size
+ 16;
705 if (FcPatternEltU(p
->elts
))
707 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
708 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
709 if (!e
) /* maybe it was mmapped */
711 e
= malloc(s
* sizeof (FcPatternElt
));
713 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
717 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
720 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
722 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
723 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
726 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
727 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
728 FcValueListPtrCreateDynamic(0);
734 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
735 FcPatternEltU(p
->elts
) + i
,
736 sizeof (FcPatternElt
) *
742 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectStaticName (object
);
743 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
746 return FcPatternEltU(p
->elts
)+i
;
750 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
757 if (pa
->num
!= pb
->num
)
759 for (i
= 0; i
< pa
->num
; i
++)
761 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
762 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
764 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
765 (FcPatternEltU(pb
->elts
)+i
)->values
))
772 FcPatternHash (const FcPattern
*p
)
777 for (i
= 0; i
< p
->num
; i
++)
779 h
= (((h
<< 1) | (h
>> 31)) ^
780 FcStringHash ((const FcChar8
*) FcObjectPtrU(((FcPatternEltU(p
->elts
)+i
)->object
))) ^
781 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
787 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
789 FcPatternElt
*ea
, *eb
;
792 for (i
= 0; i
< os
->nobject
; i
++)
794 ea
= FcPatternFindElt (pai
, FcObjectPtrU(os
->objects
[i
]));
795 eb
= FcPatternFindElt (pbi
, FcObjectPtrU(os
->objects
[i
]));
800 if (!FcValueListEqual (ea
->values
, eb
->values
))
813 FcPatternAddWithBinding (FcPattern
*p
,
816 FcValueBinding binding
,
820 FcValueListPtr
new, *prev
;
823 if (p
->ref
== FC_REF_CONSTANT
)
826 newp
= malloc (sizeof (FcValueList
));
830 memset(newp
, 0, sizeof (FcValueList
));
831 new = FcValueListPtrCreateDynamic(newp
);
832 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
834 value
= FcValueSave (value
);
835 if (value
.type
== FcTypeVoid
)
838 FcValueListPtrU(new)->value
= value
;
839 FcValueListPtrU(new)->binding
= binding
;
840 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
842 e
= FcPatternInsertElt (p
, object
);
848 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
854 FcValueListPtrU(new)->next
= e
->values
;
861 switch (value
.type
) {
863 FcStrFree ((FcChar8
*) FcObjectPtrU(value
.u
.si
));
866 FcMatrixFree (FcMatrixPtrU(value
.u
.mi
));
869 FcCharSetDestroy (FcCharSetPtrU(value
.u
.ci
));
872 FcLangSetDestroy (FcLangSetPtrU(value
.u
.li
));
878 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
879 free (FcValueListPtrU(new));
885 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
887 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
891 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
893 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
897 FcPatternDel (FcPattern
*p
, const char *object
)
901 e
= FcPatternFindElt (p
, object
);
906 FcValueListDestroy (e
->values
);
908 /* shuffle existing ones down */
910 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
911 sizeof (FcPatternElt
));
913 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
914 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
919 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
922 FcValueListPtr
*prev
, l
;
924 e
= FcPatternFindElt (p
, object
);
927 for (prev
= &e
->values
;
928 FcValueListPtrU(l
= *prev
);
929 prev
= &FcValueListPtrU(l
)->next
)
933 *prev
= FcValueListPtrU(l
)->next
;
934 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
935 FcValueListDestroy (l
);
936 if (!FcValueListPtrU(e
->values
))
937 FcPatternDel (p
, object
);
946 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
950 v
.type
= FcTypeInteger
;
952 return FcPatternAdd (p
, object
, v
, FcTrue
);
956 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
960 v
.type
= FcTypeDouble
;
962 return FcPatternAdd (p
, object
, v
, FcTrue
);
967 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
971 v
.type
= FcTypeString
;
972 v
.u
.si
= FcObjectStaticName(s
);
973 return FcPatternAdd (p
, object
, v
, FcTrue
);
977 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
981 v
.type
= FcTypeMatrix
;
982 v
.u
.mi
= FcMatrixPtrCreateDynamic((FcMatrix
*) s
);
983 return FcPatternAdd (p
, object
, v
, FcTrue
);
988 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
994 return FcPatternAdd (p
, object
, v
, FcTrue
);
998 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1002 v
.type
= FcTypeCharSet
;
1003 v
.u
.ci
= FcCharSetPtrCreateDynamic((FcCharSet
*)c
);
1004 return FcPatternAdd (p
, object
, v
, FcTrue
);
1008 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1012 v
.type
= FcTypeFTFace
;
1014 return FcPatternAdd (p
, object
, v
, FcTrue
);
1018 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1022 v
.type
= FcTypeLangSet
;
1023 v
.u
.li
= FcLangSetPtrCreateDynamic((FcLangSet
*)ls
);
1024 return FcPatternAdd (p
, object
, v
, FcTrue
);
1028 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1033 e
= FcPatternFindElt (p
, object
);
1035 return FcResultNoMatch
;
1036 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1040 *v
= FcValueListPtrU(l
)->value
;
1041 return FcResultMatch
;
1045 return FcResultNoId
;
1049 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1054 r
= FcPatternGet (p
, object
, id
, &v
);
1055 if (r
!= FcResultMatch
)
1065 return FcResultTypeMismatch
;
1067 return FcResultMatch
;
1071 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1076 r
= FcPatternGet (p
, object
, id
, &v
);
1077 if (r
!= FcResultMatch
)
1084 *d
= (double) v
.u
.i
;
1087 return FcResultTypeMismatch
;
1089 return FcResultMatch
;
1093 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1098 r
= FcPatternGet (p
, object
, id
, &v
);
1099 if (r
!= FcResultMatch
)
1101 if (v
.type
!= FcTypeString
)
1102 return FcResultTypeMismatch
;
1103 *s
= (FcChar8
*) FcObjectPtrU(v
.u
.si
);
1104 return FcResultMatch
;
1108 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1113 r
= FcPatternGet (p
, object
, id
, &v
);
1114 if (r
!= FcResultMatch
)
1116 if (v
.type
!= FcTypeMatrix
)
1117 return FcResultTypeMismatch
;
1118 *m
= FcMatrixPtrU(v
.u
.mi
);
1119 return FcResultMatch
;
1124 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1129 r
= FcPatternGet (p
, object
, id
, &v
);
1130 if (r
!= FcResultMatch
)
1132 if (v
.type
!= FcTypeBool
)
1133 return FcResultTypeMismatch
;
1135 return FcResultMatch
;
1139 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1144 r
= FcPatternGet (p
, object
, id
, &v
);
1145 if (r
!= FcResultMatch
)
1147 if (v
.type
!= FcTypeCharSet
)
1148 return FcResultTypeMismatch
;
1149 *c
= FcCharSetPtrU(v
.u
.ci
);
1150 return FcResultMatch
;
1154 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1159 r
= FcPatternGet (p
, object
, id
, &v
);
1160 if (r
!= FcResultMatch
)
1162 if (v
.type
!= FcTypeFTFace
)
1163 return FcResultTypeMismatch
;
1164 *f
= (FT_Face
) v
.u
.f
;
1165 return FcResultMatch
;
1169 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1174 r
= FcPatternGet (p
, object
, id
, &v
);
1175 if (r
!= FcResultMatch
)
1177 if (v
.type
!= FcTypeLangSet
)
1178 return FcResultTypeMismatch
;
1179 *ls
= FcLangSetPtrU(v
.u
.li
);
1180 return FcResultMatch
;
1184 FcPatternDuplicate (const FcPattern
*orig
)
1191 new = FcPatternCreate ();
1195 e
= FcPatternEltU(orig
->elts
);
1197 for (i
= 0; i
< orig
->num
; i
++)
1199 for (l
= (e
+ i
)->values
;
1201 l
= FcValueListPtrU(l
)->next
)
1202 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1203 FcValueListPtrU(l
)->value
, FcTrue
))
1210 FcPatternDestroy (new);
1216 FcPatternReference (FcPattern
*p
)
1218 if (p
->ref
!= FC_REF_CONSTANT
)
1223 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1227 FcPatternVapBuild (ret
, orig
, va
);
1232 FcPatternBuild (FcPattern
*orig
, ...)
1236 va_start (va
, orig
);
1237 FcPatternVapBuild (orig
, orig
, va
);
1243 * Add all of the elements in 's' to 'p'
1246 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1252 for (i
= 0; i
< s
->num
; i
++)
1254 e
= FcPatternEltU(s
->elts
)+i
;
1255 for (v
= e
->values
; FcValueListPtrU(v
);
1256 v
= FcValueListPtrU(v
)->next
)
1258 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1259 FcValueListPtrU(v
)->value
,
1260 FcValueListPtrU(v
)->binding
, FcTrue
))
1268 FcPatternEltU (FcPatternEltPtr pei
)
1270 switch (pei
.storage
)
1272 case FcStorageStatic
:
1273 if (pei
.u
.stat
== 0) return 0;
1274 return &fcpatternelts
[pei
.u
.stat
];
1275 case FcStorageDynamic
:
1282 static FcPatternEltPtr
1283 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1285 FcPatternEltPtr
new;
1286 new.storage
= FcStorageDynamic
;
1291 static FcPatternEltPtr
1292 FcPatternEltPtrCreateStatic (int i
)
1294 FcPatternEltPtr
new;
1295 new.storage
= FcStorageStatic
;
1301 FcPatternEltIsDynamic (FcPatternEltPtr pei
)
1303 return pei
.storage
== FcStorageDynamic
;
1308 FcPatternClearStatic (void)
1312 fcpattern_count
= 0;
1315 fcpatternelt_ptr
= 0;
1316 fcpatternelt_count
= 0;
1320 FcValueListClearStatic (void)
1323 fcvaluelist_ptr
= 0;
1324 fcvaluelist_count
= 0;
1328 FcObjectSerialize (FcObjectPtr si
);
1331 FcPatternPrepareSerialize (FcPattern
* p
)
1336 fcpatternelt_count
+= p
->num
;
1338 for (i
= 0; i
< p
->num
; i
++)
1340 FcObjectPrepareSerialize
1341 ((FcPatternEltU(p
->elts
)+i
)->object
);
1342 if (!FcValueListPrepareSerialize
1343 (FcValueListPtrU(((FcPatternEltU(p
->elts
)+i
)->values
))))
1351 FcValueListPrepareSerialize (FcValueList
*p
)
1357 vl
= FcValueListPtrU(vl
->next
))
1359 FcValue v
= vl
->value
;
1364 FcMatrixPrepareSerialize(FcMatrixPtrU(v
.u
.mi
));
1367 FcCharSetPrepareSerialize(FcCharSetPtrU(v
.u
.ci
));
1370 FcLangSetPrepareSerialize(FcLangSetPtrU(v
.u
.li
));
1373 FcObjectPrepareSerialize(v
.u
.si
);
1377 fcvaluelist_count
++;
1384 FcPatternSerialize (FcPattern
*old
)
1387 FcPatternElt
*e
, *nep
;
1389 FcValueListPtr v
, nv_head
, nvp
;
1394 p
= malloc (sizeof (FcPattern
) * fcpattern_count
);
1398 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1402 e
= malloc (sizeof (FcPatternElt
) * fcpatternelt_count
);
1406 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1408 fcpatternelt_ptr
= 0;
1411 p
= FcPatternCreate();
1412 elts
= fcpatternelt_ptr
;
1413 nep
= &fcpatternelts
[elts
];
1416 fcpatternelt_ptr
+= old
->num
;
1418 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1421 nvp
= nv_head
= FcValueListSerialize(FcValueListPtrU(v
));
1422 if (!FcValueListPtrU(nv_head
))
1424 nv
= FcValueListPtrU(nvp
);
1428 v
= FcValueListPtrU(v
)->next
,
1429 nv
= FcValueListPtrU(nv
->next
))
1432 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1434 nvp
= FcValueListSerialize
1435 (FcValueListPtrU(FcValueListPtrU(v
)->next
));
1440 nep
[i
].values
= nv_head
;
1441 nep
[i
].object
= FcObjectSerialize
1442 (FcObjectStaticName(FcObjectPtrU(e
->object
)));
1445 p
->elts
= FcPatternEltPtrCreateStatic(elts
);
1447 p
->ref
= FC_REF_CONSTANT
;
1451 free (fcpatternelts
);
1459 FcValueListSerialize(FcValueList
*pi
)
1467 vl
= malloc (sizeof (FcValueList
) * fcvaluelist_count
);
1469 return FcValueListPtrCreateDynamic(0);
1471 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1473 fcvaluelist_ptr
= 0;
1476 fcvaluelists
[fcvaluelist_ptr
] = *pi
;
1477 new.storage
= FcStorageStatic
;
1478 new.u
.stat
= fcvaluelist_ptr
++;
1479 v
= &fcvaluelists
[new.u
.stat
].value
;
1483 if (FcObjectPtrU(v
->u
.si
))
1486 FcObjectSerialize(FcObjectStaticName(FcObjectPtrU(v
->u
.si
)));
1487 if (!FcObjectPtrU(v
->u
.si
))
1488 return FcValueListPtrCreateDynamic(pi
);
1493 if (FcMatrixPtrU(v
->u
.mi
))
1495 FcMatrixPtr mi
= FcMatrixSerialize(FcMatrixPtrU(v
->u
.mi
));
1497 if (!FcMatrixPtrU(mi
))
1498 return FcValueListPtrCreateDynamic(pi
);
1503 if (FcCharSetPtrU(v
->u
.ci
))
1505 FcCharSetPtr ci
= FcCharSetSerialize(FcCharSetPtrU(v
->u
.ci
));
1506 if (!FcCharSetPtrU(v
->u
.ci
))
1507 return FcValueListPtrCreateDynamic(pi
);
1512 if (FcLangSetPtrU(v
->u
.li
))
1514 FcLangSetPtr li
= FcLangSetSerialize(FcLangSetPtrU(v
->u
.li
));
1515 if (!FcLangSetPtrU(v
->u
.li
))
1516 return FcValueListPtrCreateDynamic(pi
);
1527 FcValueListPtrU (FcValueListPtr pi
)
1531 case FcStorageStatic
:
1532 if (pi
.u
.stat
== 0) return 0;
1533 return &fcvaluelists
[pi
.u
.stat
];
1534 case FcStorageDynamic
:
1542 FcValueListPtrCreateDynamic(FcValueList
* p
)
1546 r
.storage
= FcStorageDynamic
;
1551 /* Indices allow us to convert dynamic strings into static
1552 * strings without having to reassign IDs. We do reassign IDs
1553 * when serializing, which effectively performs mark-and-sweep
1554 * garbage collection. */
1556 /* objectptr_count maps FcObjectPtr to:
1557 + offsets in objectcontent_static_buf (if positive)
1558 - entries in objectcontent_dynamic (if negative)
1560 static int objectptr_count
= 1;
1561 static int objectptr_alloc
= 0;
1562 static int * objectptr_indices
= 0;
1564 /* invariant: objectcontent_static_buf must be sorted. */
1565 /* e.g. objectptr_static_buf = "name\0style\0weight\0" */
1566 static int objectcontent_static_bytes
= 0;
1567 static char * objectcontent_static_buf
;
1569 /* just a bunch of strings. */
1570 static int objectcontent_dynamic_count
= 1;
1571 static int objectcontent_dynamic_alloc
= 0;
1572 static const char ** objectcontent_dynamic
= 0;
1573 static int * objectcontent_dynamic_refcount
= 0;
1575 #define OBJECT_HASH_SIZE 31
1576 struct objectBucket
{
1577 struct objectBucket
*next
;
1580 static struct objectBucket
**FcObjectBuckets
= 0;
1583 FcObjectStaticName (const char *name
)
1585 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1586 struct objectBucket
**p
;
1587 struct objectBucket
*b
;
1592 if (!FcObjectBuckets
)
1594 FcObjectBuckets
= malloc(sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1595 memset (FcObjectBuckets
, 0, sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1598 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1600 FcObjectPtr bp
= *((FcObjectPtr
*) (b
+ 1));
1601 if (b
->hash
== hash
&& FcObjectPtrU(bp
) && !strcmp (name
, FcObjectPtrU(bp
)))
1603 if (objectptr_indices
[bp
] < 0)
1604 objectcontent_dynamic_refcount
[-objectptr_indices
[bp
]]++;
1609 /* didn't find it, so add a new dynamic string */
1610 if (objectcontent_dynamic_count
>= objectcontent_dynamic_alloc
)
1612 int s
= objectcontent_dynamic_alloc
+ 4;
1614 const char ** d
= realloc (objectcontent_dynamic
,
1618 FcMemFree(FC_MEM_STATICSTR
,
1619 objectcontent_dynamic_alloc
* sizeof(char *));
1620 FcMemAlloc(FC_MEM_STATICSTR
, s
*sizeof(char *));
1621 objectcontent_dynamic
= d
;
1622 objectcontent_dynamic_alloc
= s
;
1624 int * rc
= realloc (objectcontent_dynamic_refcount
, s
*sizeof(int));
1627 FcMemFree(FC_MEM_STATICSTR
,
1628 objectcontent_dynamic_alloc
* sizeof(int));
1629 FcMemAlloc(FC_MEM_STATICSTR
, s
* sizeof(int));
1630 objectcontent_dynamic_refcount
= rc
;
1632 if (objectptr_count
>= objectptr_alloc
)
1634 int s
= objectptr_alloc
+ 4;
1635 int * d
= realloc (objectptr_indices
, s
*sizeof(int));
1638 FcMemFree(FC_MEM_STATICSTR
, objectptr_alloc
* sizeof(int));
1639 FcMemAlloc(FC_MEM_STATICSTR
, s
);
1640 objectptr_indices
= d
;
1641 objectptr_indices
[0] = 0;
1642 objectptr_alloc
= s
;
1645 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1649 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1652 nn
= malloc(strlen(name
)+1);
1655 strcpy ((char *)nn
, name
);
1656 objectptr_indices
[objectptr_count
] = -objectcontent_dynamic_count
;
1657 objectcontent_dynamic_refcount
[objectcontent_dynamic_count
] = 1;
1658 objectcontent_dynamic
[objectcontent_dynamic_count
++] = nn
;
1659 new = objectptr_count
++;
1660 *((FcObjectPtr
*)(b
+1)) = new;
1670 FcObjectPtrDestroy (FcObjectPtr p
)
1672 if (objectptr_indices
[p
] < 0)
1674 objectcontent_dynamic_refcount
[-objectptr_indices
[p
]]--;
1675 if (objectcontent_dynamic_refcount
[-objectptr_indices
[p
]] == 0)
1677 /* this code doesn't seem to be reached terribly often. */
1678 /* (note that objectcontent_dynamic overapproximates
1679 * the use count, because not every result from
1680 * StaticName is stored. */
1681 FcStrFree((char *)objectcontent_dynamic
[-objectptr_indices
[p
]]);
1682 objectcontent_dynamic
[-objectptr_indices
[p
]] = 0;
1688 FcObjectPtrU (FcObjectPtr si
)
1690 if (objectptr_indices
[si
] > 0)
1691 return &objectcontent_static_buf
[objectptr_indices
[si
]];
1693 return objectcontent_dynamic
[-objectptr_indices
[si
]];
1696 static FcBool objectptr_first_serialization
= FcFalse
;
1697 static int * object_old_id_to_new
= 0;
1700 FcObjectRebuildStaticNameHashtable (void)
1703 struct objectBucket
*b
, *bn
;
1705 if (FcObjectBuckets
)
1707 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1709 b
= FcObjectBuckets
[i
];
1714 FcMemFree (FC_MEM_STATICSTR
,
1715 sizeof (struct objectBucket
)+sizeof (FcObjectPtr
));
1719 free (FcObjectBuckets
);
1722 FcObjectBuckets
= malloc(sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1723 memset (FcObjectBuckets
, 0, sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1725 for (i
= 1; i
< objectptr_count
; i
++)
1727 if (FcObjectPtrU(i
))
1729 const char * name
= FcObjectPtrU(i
);
1730 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1731 struct objectBucket
**p
;
1734 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
);
1737 size
= sizeof (struct objectBucket
) + sizeof (FcObjectPtr
);
1741 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1744 *((FcObjectPtr
*)(b
+1)) = i
;
1750 /* Hmm. This will have a terrible effect on the memory size,
1751 * because the mmapped strings now get reallocated on the heap.
1752 * Is it all worth it? (Of course, the Serialization codepath is
1753 * not problematic.) */
1755 FcObjectPtrConvertToStatic(FcBool renumber
)
1757 int active_count
, i
, j
, longest_string
= 0,
1758 new_static_bytes
= 1;
1759 char * fixed_length_buf
, * new_static_buf
, * p
;
1763 objectptr_first_serialization
= FcFalse
;
1765 /* collect statistics */
1766 for (i
= 1, active_count
= 1; i
< objectptr_count
; i
++)
1767 if (!renumber
|| object_old_id_to_new
[i
] == -1)
1769 int sl
= strlen(FcObjectPtrU(i
));
1771 if (sl
> longest_string
)
1772 longest_string
= sl
;
1773 new_static_bytes
+= sl
+ 1;
1776 /* allocate storage */
1777 fixed_length_buf
= malloc
1778 ((longest_string
+1) * active_count
* sizeof(char));
1779 if (!fixed_length_buf
)
1781 new_static_buf
= malloc (new_static_bytes
* sizeof(char));
1782 if (!new_static_buf
)
1784 new_indices
= malloc (active_count
* sizeof(int));
1788 FcMemAlloc (FC_MEM_STATICSTR
, new_static_bytes
);
1789 FcMemFree (FC_MEM_STATICSTR
, objectptr_count
* sizeof (int));
1790 FcMemAlloc (FC_MEM_STATICSTR
, active_count
* sizeof (int));
1792 /* copy strings to temporary buffers */
1793 for (j
= 0, i
= 1; i
< objectptr_count
; i
++)
1794 if (!renumber
|| object_old_id_to_new
[i
] == -1)
1796 strcpy (fixed_length_buf
+(j
*(longest_string
+1)), FcObjectPtrU(i
));
1800 /* sort the new statics */
1801 qsort (fixed_length_buf
, active_count
-1, longest_string
+1,
1802 (int (*)(const void *, const void *)) FcStrCmp
);
1804 /* now we create the new static buffer in sorted order. */
1805 p
= new_static_buf
+1;
1806 for (i
= 0; i
< active_count
-1; i
++)
1808 strcpy(p
, fixed_length_buf
+ i
* (longest_string
+1));
1812 /* create translation table by iterating over sorted strings
1813 * and getting their old values */
1814 p
= new_static_buf
+1;
1815 for (i
= 0; i
< active_count
-1; i
++)
1817 int n
= FcObjectStaticName(fixed_length_buf
+i
*(longest_string
+1));
1820 object_old_id_to_new
[n
] = i
;
1821 new_indices
[i
] = p
-new_static_buf
;
1824 new_indices
[n
] = p
-new_static_buf
;
1828 free (objectptr_indices
);
1829 objectptr_indices
= new_indices
;
1830 objectptr_count
= active_count
;
1831 objectptr_alloc
= active_count
;
1833 /* free old storage */
1834 for (i
= 1; i
< objectcontent_dynamic_count
; i
++)
1836 if (objectcontent_dynamic
[i
])
1838 FcMemFree (FC_MEM_STATICSTR
, strlen(objectcontent_dynamic
[i
])+1);
1839 free ((char *)objectcontent_dynamic
[i
]);
1842 free (objectcontent_dynamic
);
1843 free (objectcontent_dynamic_refcount
);
1844 FcMemFree (FC_MEM_STATICSTR
, objectcontent_dynamic_count
*sizeof (int));
1845 objectcontent_dynamic
= 0;
1846 objectcontent_dynamic_refcount
= 0;
1847 objectcontent_dynamic_count
= 1;
1848 objectcontent_dynamic_alloc
= 0;
1849 free (objectcontent_static_buf
);
1850 FcMemFree (FC_MEM_STATICSTR
, objectcontent_static_bytes
);
1851 objectcontent_static_buf
= new_static_buf
;
1852 objectcontent_static_bytes
= new_static_bytes
;
1854 /* fix up hash table */
1855 FcObjectRebuildStaticNameHashtable();
1857 free (fixed_length_buf
);
1861 free (new_static_buf
);
1863 free (fixed_length_buf
);
1868 #define OBJECT_PTR_CONVERSION_TRIGGER 100000
1871 FcObjectPtrCompare (const FcObjectPtr a
, const FcObjectPtr b
)
1873 /* This is the dynamic count. We could also use a static
1874 * count, i.e. the number of slow strings being created.
1875 * I think dyncount gives us a better estimate of inefficiency. -PL */
1876 static int compare_count
= OBJECT_PTR_CONVERSION_TRIGGER
;
1878 /* count on sortedness for fast objectptrs. */
1879 if ((a
== b
) || (objectptr_indices
[a
] > 0 && objectptr_indices
[b
] > 0))
1880 return objectptr_indices
[a
] - objectptr_indices
[b
];
1885 FcObjectPtrConvertToStatic(FcFalse
);
1886 compare_count
= OBJECT_PTR_CONVERSION_TRIGGER
;
1889 return strcmp (FcObjectPtrU(a
), FcObjectPtrU(b
));
1893 FcObjectClearStatic(void)
1895 objectptr_count
= 1;
1896 objectptr_alloc
= 0;
1897 objectptr_indices
= 0;
1899 objectcontent_static_bytes
= 0;
1900 objectcontent_static_buf
= 0;
1902 objectcontent_dynamic_count
= 1;
1903 objectcontent_dynamic_alloc
= 0;
1904 objectcontent_dynamic
= 0;
1905 objectcontent_dynamic_refcount
= 0;
1907 object_old_id_to_new
= 0;
1911 FcObjectSerialize (FcObjectPtr si
)
1913 if (objectptr_first_serialization
)
1914 if (!FcObjectPtrConvertToStatic(FcTrue
))
1917 return object_old_id_to_new
[si
];
1920 /* In the pre-serialization phase, mark the used strings with
1921 * -1 in the mapping array. */
1922 /* The first call to the serialization phase assigns actual
1923 * static indices to the strings (sweep). */
1925 FcObjectPrepareSerialize (FcObjectPtr si
)
1927 if (object_old_id_to_new
== 0)
1929 object_old_id_to_new
= malloc(objectptr_count
* sizeof(int));
1930 if (!object_old_id_to_new
)
1932 memset (object_old_id_to_new
, 0,
1933 objectptr_count
* sizeof(int));
1936 object_old_id_to_new
[si
] = -1;
1937 objectptr_first_serialization
= FcTrue
;
1946 FcObjectStaticNameFini (void)
1949 struct objectBucket
*b
, *next
;
1952 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1954 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1957 name
= (char *) (b
+ 1);
1958 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1959 FcMemFree (FC_MEM_STATICSTR
, size
);
1962 FcObjectBuckets
[i
] = 0;
1967 FcPatternFini (void)
1969 FcPatternBaseThawAll ();
1970 FcValueListThawAll ();
1971 FcObjectStaticNameFini ();