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 FcPatternThawAll (void)
657 FcPatternBaseThawAll ();
658 FcValueListThawAll ();
662 FcPatternPosition (const FcPattern
*p
, const char *object
)
664 int low
, high
, mid
, c
;
667 obj
= FcObjectStaticName(object
);
674 mid
= (low
+ high
) >> 1;
675 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
689 FcPatternFindElt (const FcPattern
*p
, const char *object
)
691 int i
= FcPatternPosition (p
, object
);
694 return FcPatternEltU(p
->elts
)+i
;
698 FcPatternInsertElt (FcPattern
*p
, const char *object
)
703 i
= FcPatternPosition (p
, object
);
708 /* reallocate array */
709 if (p
->num
+ 1 >= p
->size
)
711 int s
= p
->size
+ 16;
712 if (FcPatternEltU(p
->elts
))
714 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
715 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
716 if (!e
) /* maybe it was mmapped */
718 e
= malloc(s
* sizeof (FcPatternElt
));
720 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
724 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
727 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
729 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
730 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
733 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
734 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
735 FcValueListPtrCreateDynamic(0);
741 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
742 FcPatternEltU(p
->elts
) + i
,
743 sizeof (FcPatternElt
) *
749 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectStaticName (object
);
750 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
753 return FcPatternEltU(p
->elts
)+i
;
757 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
764 if (pa
->num
!= pb
->num
)
766 for (i
= 0; i
< pa
->num
; i
++)
768 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
769 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
771 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
772 (FcPatternEltU(pb
->elts
)+i
)->values
))
779 FcPatternHash (const FcPattern
*p
)
784 for (i
= 0; i
< p
->num
; i
++)
786 h
= (((h
<< 1) | (h
>> 31)) ^
787 FcStringHash ((const FcChar8
*) FcObjectPtrU(((FcPatternEltU(p
->elts
)+i
)->object
))) ^
788 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
794 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
796 FcPatternElt
*ea
, *eb
;
799 for (i
= 0; i
< os
->nobject
; i
++)
801 ea
= FcPatternFindElt (pai
, FcObjectPtrU(os
->objects
[i
]));
802 eb
= FcPatternFindElt (pbi
, FcObjectPtrU(os
->objects
[i
]));
807 if (!FcValueListEqual (ea
->values
, eb
->values
))
820 FcPatternAddWithBinding (FcPattern
*p
,
823 FcValueBinding binding
,
827 FcValueListPtr
new, *prev
;
830 if (p
->ref
== FC_REF_CONSTANT
)
833 newp
= malloc (sizeof (FcValueList
));
837 memset(newp
, 0, sizeof (FcValueList
));
838 new = FcValueListPtrCreateDynamic(newp
);
839 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
841 value
= FcValueSave (value
);
842 if (value
.type
== FcTypeVoid
)
845 FcValueListPtrU(new)->value
= value
;
846 FcValueListPtrU(new)->binding
= binding
;
847 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
849 e
= FcPatternInsertElt (p
, object
);
855 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
861 FcValueListPtrU(new)->next
= e
->values
;
868 switch (value
.type
) {
870 FcStrFree ((FcChar8
*) FcObjectPtrU(value
.u
.si
));
873 FcMatrixFree (FcMatrixPtrU(value
.u
.mi
));
876 FcCharSetDestroy (FcCharSetPtrU(value
.u
.ci
));
879 FcLangSetDestroy (FcLangSetPtrU(value
.u
.li
));
885 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
886 free (FcValueListPtrU(new));
892 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
894 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
898 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
900 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
904 FcPatternDel (FcPattern
*p
, const char *object
)
908 e
= FcPatternFindElt (p
, object
);
913 FcValueListDestroy (e
->values
);
915 /* shuffle existing ones down */
917 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
918 sizeof (FcPatternElt
));
920 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
921 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
926 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
929 FcValueListPtr
*prev
, l
;
931 e
= FcPatternFindElt (p
, object
);
934 for (prev
= &e
->values
;
935 FcValueListPtrU(l
= *prev
);
936 prev
= &FcValueListPtrU(l
)->next
)
940 *prev
= FcValueListPtrU(l
)->next
;
941 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
942 FcValueListDestroy (l
);
943 if (!FcValueListPtrU(e
->values
))
944 FcPatternDel (p
, object
);
953 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
957 v
.type
= FcTypeInteger
;
959 return FcPatternAdd (p
, object
, v
, FcTrue
);
963 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
967 v
.type
= FcTypeDouble
;
969 return FcPatternAdd (p
, object
, v
, FcTrue
);
974 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
978 v
.type
= FcTypeString
;
979 v
.u
.si
= FcObjectStaticName(s
);
980 return FcPatternAdd (p
, object
, v
, FcTrue
);
984 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
988 v
.type
= FcTypeMatrix
;
989 v
.u
.mi
= FcMatrixPtrCreateDynamic((FcMatrix
*) s
);
990 return FcPatternAdd (p
, object
, v
, FcTrue
);
995 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1001 return FcPatternAdd (p
, object
, v
, FcTrue
);
1005 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1009 v
.type
= FcTypeCharSet
;
1010 v
.u
.ci
= FcCharSetPtrCreateDynamic((FcCharSet
*)c
);
1011 return FcPatternAdd (p
, object
, v
, FcTrue
);
1015 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1019 v
.type
= FcTypeFTFace
;
1021 return FcPatternAdd (p
, object
, v
, FcTrue
);
1025 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1029 v
.type
= FcTypeLangSet
;
1030 v
.u
.li
= FcLangSetPtrCreateDynamic((FcLangSet
*)ls
);
1031 return FcPatternAdd (p
, object
, v
, FcTrue
);
1035 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1040 e
= FcPatternFindElt (p
, object
);
1042 return FcResultNoMatch
;
1043 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1047 *v
= FcValueListPtrU(l
)->value
;
1048 return FcResultMatch
;
1052 return FcResultNoId
;
1056 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1061 r
= FcPatternGet (p
, object
, id
, &v
);
1062 if (r
!= FcResultMatch
)
1072 return FcResultTypeMismatch
;
1074 return FcResultMatch
;
1078 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1083 r
= FcPatternGet (p
, object
, id
, &v
);
1084 if (r
!= FcResultMatch
)
1091 *d
= (double) v
.u
.i
;
1094 return FcResultTypeMismatch
;
1096 return FcResultMatch
;
1100 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1105 r
= FcPatternGet (p
, object
, id
, &v
);
1106 if (r
!= FcResultMatch
)
1108 if (v
.type
!= FcTypeString
)
1109 return FcResultTypeMismatch
;
1110 *s
= (FcChar8
*) FcObjectPtrU(v
.u
.si
);
1111 return FcResultMatch
;
1115 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1120 r
= FcPatternGet (p
, object
, id
, &v
);
1121 if (r
!= FcResultMatch
)
1123 if (v
.type
!= FcTypeMatrix
)
1124 return FcResultTypeMismatch
;
1125 *m
= FcMatrixPtrU(v
.u
.mi
);
1126 return FcResultMatch
;
1131 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1136 r
= FcPatternGet (p
, object
, id
, &v
);
1137 if (r
!= FcResultMatch
)
1139 if (v
.type
!= FcTypeBool
)
1140 return FcResultTypeMismatch
;
1142 return FcResultMatch
;
1146 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1151 r
= FcPatternGet (p
, object
, id
, &v
);
1152 if (r
!= FcResultMatch
)
1154 if (v
.type
!= FcTypeCharSet
)
1155 return FcResultTypeMismatch
;
1156 *c
= FcCharSetPtrU(v
.u
.ci
);
1157 return FcResultMatch
;
1161 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1166 r
= FcPatternGet (p
, object
, id
, &v
);
1167 if (r
!= FcResultMatch
)
1169 if (v
.type
!= FcTypeFTFace
)
1170 return FcResultTypeMismatch
;
1171 *f
= (FT_Face
) v
.u
.f
;
1172 return FcResultMatch
;
1176 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1181 r
= FcPatternGet (p
, object
, id
, &v
);
1182 if (r
!= FcResultMatch
)
1184 if (v
.type
!= FcTypeLangSet
)
1185 return FcResultTypeMismatch
;
1186 *ls
= FcLangSetPtrU(v
.u
.li
);
1187 return FcResultMatch
;
1191 FcPatternDuplicate (const FcPattern
*orig
)
1198 new = FcPatternCreate ();
1202 e
= FcPatternEltU(orig
->elts
);
1204 for (i
= 0; i
< orig
->num
; i
++)
1206 for (l
= (e
+ i
)->values
;
1208 l
= FcValueListPtrU(l
)->next
)
1209 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1210 FcValueListPtrU(l
)->value
, FcTrue
))
1217 FcPatternDestroy (new);
1223 FcPatternReference (FcPattern
*p
)
1225 if (p
->ref
!= FC_REF_CONSTANT
)
1230 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1234 FcPatternVapBuild (ret
, orig
, va
);
1239 FcPatternBuild (FcPattern
*orig
, ...)
1243 va_start (va
, orig
);
1244 FcPatternVapBuild (orig
, orig
, va
);
1250 * Add all of the elements in 's' to 'p'
1253 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1259 for (i
= 0; i
< s
->num
; i
++)
1261 e
= FcPatternEltU(s
->elts
)+i
;
1262 for (v
= e
->values
; FcValueListPtrU(v
);
1263 v
= FcValueListPtrU(v
)->next
)
1265 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1266 FcValueListPtrU(v
)->value
,
1267 FcValueListPtrU(v
)->binding
, FcTrue
))
1275 FcPatternEltU (FcPatternEltPtr pei
)
1277 switch (pei
.storage
)
1279 case FcStorageStatic
:
1280 if (pei
.u
.stat
== 0) return 0;
1281 return &fcpatternelts
[pei
.u
.stat
];
1282 case FcStorageDynamic
:
1289 static FcPatternEltPtr
1290 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1292 FcPatternEltPtr
new;
1293 new.storage
= FcStorageDynamic
;
1298 static FcPatternEltPtr
1299 FcPatternEltPtrCreateStatic (int i
)
1301 FcPatternEltPtr
new;
1302 new.storage
= FcStorageStatic
;
1308 FcPatternEltIsDynamic (FcPatternEltPtr pei
)
1310 return pei
.storage
== FcStorageDynamic
;
1315 FcPatternClearStatic (void)
1319 fcpattern_count
= 0;
1322 fcpatternelt_ptr
= 0;
1323 fcpatternelt_count
= 0;
1327 FcValueListClearStatic (void)
1330 fcvaluelist_ptr
= 0;
1331 fcvaluelist_count
= 0;
1335 FcObjectSerialize (FcObjectPtr si
);
1338 FcPatternPrepareSerialize (FcPattern
* p
)
1343 fcpatternelt_count
+= p
->num
;
1345 for (i
= 0; i
< p
->num
; i
++)
1347 FcObjectPrepareSerialize
1348 ((FcPatternEltU(p
->elts
)+i
)->object
);
1349 if (!FcValueListPrepareSerialize
1350 (FcValueListPtrU(((FcPatternEltU(p
->elts
)+i
)->values
))))
1358 FcValueListPrepareSerialize (FcValueList
*p
)
1364 vl
= FcValueListPtrU(vl
->next
))
1366 FcValue v
= vl
->value
;
1371 FcMatrixPrepareSerialize(FcMatrixPtrU(v
.u
.mi
));
1374 FcCharSetPrepareSerialize(FcCharSetPtrU(v
.u
.ci
));
1377 FcLangSetPrepareSerialize(FcLangSetPtrU(v
.u
.li
));
1380 FcObjectPrepareSerialize(v
.u
.si
);
1384 fcvaluelist_count
++;
1391 FcPatternSerialize (FcPattern
*old
)
1394 FcPatternElt
*e
, *nep
;
1396 FcValueListPtr v
, nv_head
, nvp
;
1401 p
= malloc (sizeof (FcPattern
) * fcpattern_count
);
1405 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1409 e
= malloc (sizeof (FcPatternElt
) * fcpatternelt_count
);
1413 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1415 fcpatternelt_ptr
= 0;
1418 p
= FcPatternCreate();
1419 elts
= fcpatternelt_ptr
;
1420 nep
= &fcpatternelts
[elts
];
1423 fcpatternelt_ptr
+= old
->num
;
1425 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1428 nvp
= nv_head
= FcValueListSerialize(FcValueListPtrU(v
));
1429 if (!FcValueListPtrU(nv_head
))
1431 nv
= FcValueListPtrU(nvp
);
1435 v
= FcValueListPtrU(v
)->next
,
1436 nv
= FcValueListPtrU(nv
->next
))
1439 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1441 nvp
= FcValueListSerialize
1442 (FcValueListPtrU(FcValueListPtrU(v
)->next
));
1447 nep
[i
].values
= nv_head
;
1448 nep
[i
].object
= FcObjectSerialize
1449 (FcObjectStaticName(FcObjectPtrU(e
->object
)));
1452 p
->elts
= FcPatternEltPtrCreateStatic(elts
);
1454 p
->ref
= FC_REF_CONSTANT
;
1458 free (fcpatternelts
);
1466 FcValueListSerialize(FcValueList
*pi
)
1474 vl
= malloc (sizeof (FcValueList
) * fcvaluelist_count
);
1476 return FcValueListPtrCreateDynamic(0);
1478 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1480 fcvaluelist_ptr
= 0;
1483 fcvaluelists
[fcvaluelist_ptr
] = *pi
;
1484 new.storage
= FcStorageStatic
;
1485 new.u
.stat
= fcvaluelist_ptr
++;
1486 v
= &fcvaluelists
[new.u
.stat
].value
;
1490 if (FcObjectPtrU(v
->u
.si
))
1493 FcObjectSerialize(FcObjectStaticName(FcObjectPtrU(v
->u
.si
)));
1494 if (!FcObjectPtrU(v
->u
.si
))
1495 return FcValueListPtrCreateDynamic(pi
);
1500 if (FcMatrixPtrU(v
->u
.mi
))
1502 FcMatrixPtr mi
= FcMatrixSerialize(FcMatrixPtrU(v
->u
.mi
));
1504 if (!FcMatrixPtrU(mi
))
1505 return FcValueListPtrCreateDynamic(pi
);
1510 if (FcCharSetPtrU(v
->u
.ci
))
1512 FcCharSetPtr ci
= FcCharSetSerialize(FcCharSetPtrU(v
->u
.ci
));
1513 if (!FcCharSetPtrU(v
->u
.ci
))
1514 return FcValueListPtrCreateDynamic(pi
);
1519 if (FcLangSetPtrU(v
->u
.li
))
1521 FcLangSetPtr li
= FcLangSetSerialize(FcLangSetPtrU(v
->u
.li
));
1522 if (!FcLangSetPtrU(v
->u
.li
))
1523 return FcValueListPtrCreateDynamic(pi
);
1534 FcValueListPtrU (FcValueListPtr pi
)
1538 case FcStorageStatic
:
1539 if (pi
.u
.stat
== 0) return 0;
1540 return &fcvaluelists
[pi
.u
.stat
];
1541 case FcStorageDynamic
:
1549 FcValueListPtrCreateDynamic(FcValueList
* p
)
1553 r
.storage
= FcStorageDynamic
;
1558 /* Indices allow us to convert dynamic strings into static
1559 * strings without having to reassign IDs. We do reassign IDs
1560 * when serializing, which effectively performs mark-and-sweep
1561 * garbage collection. */
1563 /* objectptr_count maps FcObjectPtr to:
1564 + offsets in objectcontent_static_buf (if positive)
1565 - entries in objectcontent_dynamic (if negative)
1567 static int objectptr_count
= 1;
1568 static int objectptr_alloc
= 0;
1569 static int * objectptr_indices
= 0;
1571 /* invariant: objectcontent_static_buf must be sorted. */
1572 /* e.g. objectptr_static_buf = "name\0style\0weight\0" */
1573 static int objectcontent_static_bytes
= 0;
1574 static char * objectcontent_static_buf
;
1576 /* just a bunch of strings. */
1577 static int objectcontent_dynamic_count
= 1;
1578 static int objectcontent_dynamic_alloc
= 0;
1579 static const char ** objectcontent_dynamic
= 0;
1580 static int * objectcontent_dynamic_refcount
= 0;
1582 #define OBJECT_HASH_SIZE 31
1583 struct objectBucket
{
1584 struct objectBucket
*next
;
1587 static struct objectBucket
**buckets
= 0;
1590 FcObjectStaticName (const char *name
)
1592 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1593 struct objectBucket
**p
;
1594 struct objectBucket
*b
;
1601 buckets
= malloc(sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1602 memset (buckets
, 0, sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1605 for (p
= &buckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1607 FcObjectPtr bp
= *((FcObjectPtr
*) (b
+ 1));
1608 if (b
->hash
== hash
&& FcObjectPtrU(bp
) && !strcmp (name
, FcObjectPtrU(bp
)))
1610 if (objectptr_indices
[bp
] < 0)
1611 objectcontent_dynamic_refcount
[-objectptr_indices
[bp
]]++;
1616 /* didn't find it, so add a new dynamic string */
1617 if (objectcontent_dynamic_count
>= objectcontent_dynamic_alloc
)
1619 int s
= objectcontent_dynamic_alloc
+ 4;
1621 const char ** d
= realloc (objectcontent_dynamic
,
1625 FcMemFree(FC_MEM_STATICSTR
,
1626 objectcontent_dynamic_alloc
* sizeof(char *));
1627 FcMemAlloc(FC_MEM_STATICSTR
, s
*sizeof(char *));
1628 objectcontent_dynamic
= d
;
1629 objectcontent_dynamic_alloc
= s
;
1631 int * rc
= realloc (objectcontent_dynamic_refcount
, s
*sizeof(int));
1634 FcMemFree(FC_MEM_STATICSTR
,
1635 objectcontent_dynamic_alloc
* sizeof(int));
1636 FcMemAlloc(FC_MEM_STATICSTR
, s
* sizeof(int));
1637 objectcontent_dynamic_refcount
= rc
;
1639 if (objectptr_count
>= objectptr_alloc
)
1641 int s
= objectptr_alloc
+ 4;
1642 int * d
= realloc (objectptr_indices
, s
*sizeof(int));
1645 FcMemFree(FC_MEM_STATICSTR
, objectptr_alloc
* sizeof(int));
1646 FcMemAlloc(FC_MEM_STATICSTR
, s
);
1647 objectptr_indices
= d
;
1648 objectptr_indices
[0] = 0;
1649 objectptr_alloc
= s
;
1652 size
= sizeof (struct objectBucket
) + sizeof (FcObjectPtr
);
1656 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1659 nn
= malloc(strlen(name
)+1);
1662 strcpy ((char *)nn
, name
);
1663 objectptr_indices
[objectptr_count
] = -objectcontent_dynamic_count
;
1664 objectcontent_dynamic_refcount
[objectcontent_dynamic_count
] = 1;
1665 objectcontent_dynamic
[objectcontent_dynamic_count
++] = nn
;
1666 new = objectptr_count
++;
1667 *((FcObjectPtr
*)(b
+1)) = new;
1677 FcObjectPtrDestroy (FcObjectPtr p
)
1679 if (objectptr_indices
[p
] < 0)
1681 objectcontent_dynamic_refcount
[-objectptr_indices
[p
]]--;
1682 if (objectcontent_dynamic_refcount
[-objectptr_indices
[p
]] == 0)
1684 /* this code doesn't seem to be reached terribly often. */
1685 /* (note that objectcontent_dynamic overapproximates
1686 * the use count, because not every result from
1687 * StaticName is stored. */
1688 FcStrFree((char *)objectcontent_dynamic
[-objectptr_indices
[p
]]);
1689 objectcontent_dynamic
[-objectptr_indices
[p
]] = 0;
1695 FcObjectPtrU (FcObjectPtr si
)
1697 if (objectptr_indices
[si
] > 0)
1698 return &objectcontent_static_buf
[objectptr_indices
[si
]];
1700 return objectcontent_dynamic
[-objectptr_indices
[si
]];
1703 static FcBool objectptr_first_serialization
= FcFalse
;
1704 static int * object_old_id_to_new
= 0;
1707 FcObjectRebuildStaticNameHashtable (void)
1710 struct objectBucket
*b
, *bn
;
1714 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1721 FcMemFree (FC_MEM_STATICSTR
,
1722 sizeof (struct objectBucket
)+sizeof (FcObjectPtr
));
1729 buckets
= malloc(sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1730 memset (buckets
, 0, sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1732 for (i
= 1; i
< objectptr_count
; i
++)
1734 if (FcObjectPtrU(i
))
1736 const char * name
= FcObjectPtrU(i
);
1737 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1738 struct objectBucket
**p
;
1741 for (p
= &buckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
);
1744 size
= sizeof (struct objectBucket
) + sizeof (FcObjectPtr
);
1748 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1751 *((FcObjectPtr
*)(b
+1)) = i
;
1757 /* Hmm. This will have a terrible effect on the memory size,
1758 * because the mmapped strings now get reallocated on the heap.
1759 * Is it all worth it? (Of course, the Serialization codepath is
1760 * not problematic.) */
1762 FcObjectPtrConvertToStatic(FcBool renumber
)
1764 int active_count
, i
, j
, longest_string
= 0,
1765 new_static_bytes
= 1;
1766 char * fixed_length_buf
, * new_static_buf
, * p
;
1770 objectptr_first_serialization
= FcFalse
;
1772 /* collect statistics */
1773 for (i
= 1, active_count
= 1; i
< objectptr_count
; i
++)
1774 if (!renumber
|| object_old_id_to_new
[i
] == -1)
1776 int sl
= strlen(FcObjectPtrU(i
));
1778 if (sl
> longest_string
)
1779 longest_string
= sl
;
1780 new_static_bytes
+= sl
+ 1;
1783 /* allocate storage */
1784 fixed_length_buf
= malloc
1785 ((longest_string
+1) * active_count
* sizeof(char));
1786 if (!fixed_length_buf
)
1788 new_static_buf
= malloc (new_static_bytes
* sizeof(char));
1789 if (!new_static_buf
)
1791 new_indices
= malloc (active_count
* sizeof(int));
1795 FcMemAlloc (FC_MEM_STATICSTR
, new_static_bytes
);
1796 FcMemFree (FC_MEM_STATICSTR
, objectptr_count
* sizeof (int));
1797 FcMemAlloc (FC_MEM_STATICSTR
, active_count
* sizeof (int));
1799 /* copy strings to temporary buffers */
1800 for (j
= 0, i
= 1; i
< objectptr_count
; i
++)
1801 if (!renumber
|| object_old_id_to_new
[i
] == -1)
1803 strcpy (fixed_length_buf
+(j
*(longest_string
+1)), FcObjectPtrU(i
));
1807 /* sort the new statics */
1808 qsort (fixed_length_buf
, active_count
-1, longest_string
+1,
1809 (int (*)(const void *, const void *)) FcStrCmp
);
1811 /* now we create the new static buffer in sorted order. */
1812 p
= new_static_buf
+1;
1813 for (i
= 0; i
< active_count
-1; i
++)
1815 strcpy(p
, fixed_length_buf
+ i
* (longest_string
+1));
1819 /* create translation table by iterating over sorted strings
1820 * and getting their old values */
1821 p
= new_static_buf
+1;
1822 for (i
= 0; i
< active_count
-1; i
++)
1824 int n
= FcObjectStaticName(fixed_length_buf
+i
*(longest_string
+1));
1827 object_old_id_to_new
[n
] = i
;
1828 new_indices
[i
] = p
-new_static_buf
;
1831 new_indices
[n
] = p
-new_static_buf
;
1835 free (objectptr_indices
);
1836 objectptr_indices
= new_indices
;
1837 objectptr_count
= active_count
;
1838 objectptr_alloc
= active_count
;
1840 /* free old storage */
1841 for (i
= 1; i
< objectcontent_dynamic_count
; i
++)
1843 if (objectcontent_dynamic
[i
])
1845 FcMemFree (FC_MEM_STATICSTR
, strlen(objectcontent_dynamic
[i
])+1);
1846 free ((char *)objectcontent_dynamic
[i
]);
1849 free (objectcontent_dynamic
);
1850 free (objectcontent_dynamic_refcount
);
1851 FcMemFree (FC_MEM_STATICSTR
, objectcontent_dynamic_count
*sizeof (int));
1852 objectcontent_dynamic
= 0;
1853 objectcontent_dynamic_refcount
= 0;
1854 objectcontent_dynamic_count
= 1;
1855 objectcontent_dynamic_alloc
= 0;
1856 free (objectcontent_static_buf
);
1857 FcMemFree (FC_MEM_STATICSTR
, objectcontent_static_bytes
);
1858 objectcontent_static_buf
= new_static_buf
;
1859 objectcontent_static_bytes
= new_static_bytes
;
1861 /* fix up hash table */
1862 FcObjectRebuildStaticNameHashtable();
1864 free (fixed_length_buf
);
1868 free (new_static_buf
);
1870 free (fixed_length_buf
);
1875 #define OBJECT_PTR_CONVERSION_TRIGGER 100000
1878 FcObjectPtrCompare (const FcObjectPtr a
, const FcObjectPtr b
)
1880 /* This is the dynamic count. We could also use a static
1881 * count, i.e. the number of slow strings being created.
1882 * I think dyncount gives us a better estimate of inefficiency. -PL */
1883 static int compare_count
= OBJECT_PTR_CONVERSION_TRIGGER
;
1885 /* count on sortedness for fast objectptrs. */
1886 if ((a
== b
) || (objectptr_indices
[a
] > 0 && objectptr_indices
[b
] > 0))
1887 return objectptr_indices
[a
] - objectptr_indices
[b
];
1892 FcObjectPtrConvertToStatic(FcFalse
);
1893 compare_count
= OBJECT_PTR_CONVERSION_TRIGGER
;
1896 return strcmp (FcObjectPtrU(a
), FcObjectPtrU(b
));
1900 FcObjectClearStatic(void)
1902 objectptr_count
= 1;
1903 objectptr_alloc
= 0;
1904 objectptr_indices
= 0;
1906 objectcontent_static_bytes
= 0;
1907 objectcontent_static_buf
= 0;
1909 objectcontent_dynamic_count
= 1;
1910 objectcontent_dynamic_alloc
= 0;
1911 objectcontent_dynamic
= 0;
1912 objectcontent_dynamic_refcount
= 0;
1914 object_old_id_to_new
= 0;
1918 FcObjectSerialize (FcObjectPtr si
)
1920 if (objectptr_first_serialization
)
1921 if (!FcObjectPtrConvertToStatic(FcTrue
))
1924 return object_old_id_to_new
[si
];
1927 /* In the pre-serialization phase, mark the used strings with
1928 * -1 in the mapping array. */
1929 /* The first call to the serialization phase assigns actual
1930 * static indices to the strings (sweep). */
1932 FcObjectPrepareSerialize (FcObjectPtr si
)
1934 if (object_old_id_to_new
== 0)
1936 object_old_id_to_new
= malloc(objectptr_count
* sizeof(int));
1937 if (!object_old_id_to_new
)
1939 memset (object_old_id_to_new
, 0,
1940 objectptr_count
* sizeof(int));
1943 object_old_id_to_new
[si
] = -1;
1944 objectptr_first_serialization
= FcTrue
;