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 static FcPatternElt
** fcpatternelts
= 0;
33 static int fcpatternelt_ptr
, fcpatternelt_count
;
34 static FcValueList
** fcvaluelists
= 0;
35 static int fcvaluelist_bank_count
= 0, fcvaluelist_ptr
, fcvaluelist_count
;
38 FcPatternFindFullFname (const FcPattern
*p
);
39 static FcPatternEltPtr
40 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
);
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 FcStrFree ((FcChar8
*) v
.u
.s
);
67 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
70 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
73 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
81 FcValueCanonicalize (const FcValue
*v
)
83 if (v
->type
& FC_STORAGE_STATIC
)
87 switch (v
->type
& ~FC_STORAGE_STATIC
)
90 new.u
.s
= fc_value_string(v
);
91 new.type
= FcTypeString
;
94 new.u
.c
= fc_value_charset(v
);
95 new.type
= FcTypeCharSet
;
98 new.u
.l
= fc_value_langset(v
);
99 new.type
= FcTypeLangSet
;
108 FcValueSave (FcValue v
)
112 v
.u
.s
= FcStrCopy (v
.u
.s
);
117 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
122 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
127 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
138 FcValueListDestroy (FcValueListPtr l
)
141 for (; FcValueListPtrU(l
); l
= next
)
143 switch (FcValueListPtrU(l
)->value
.type
) {
145 FcStrFree ((FcChar8
*)FcValueListPtrU(l
)->value
.u
.s
);
148 FcMatrixFree ((FcMatrix
*)FcValueListPtrU(l
)->value
.u
.m
);
152 ((FcCharSet
*) (FcValueListPtrU(l
)->value
.u
.c
));
156 ((FcLangSet
*) (FcValueListPtrU(l
)->value
.u
.l
));
161 next
= FcValueListPtrU(l
)->next
;
162 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
163 if (l
.bank
== FC_BANK_DYNAMIC
)
169 FcValueEqual (FcValue va
, FcValue vb
)
171 if (va
.type
!= vb
.type
)
173 if (va
.type
== FcTypeInteger
)
175 va
.type
= FcTypeDouble
;
178 if (vb
.type
== FcTypeInteger
)
180 vb
.type
= FcTypeDouble
;
183 if (va
.type
!= vb
.type
)
190 return va
.u
.i
== vb
.u
.i
;
192 return va
.u
.d
== vb
.u
.d
;
194 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
196 return va
.u
.b
== vb
.u
.b
;
198 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
200 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
202 return va
.u
.f
== vb
.u
.f
;
204 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
210 FcDoubleHash (double d
)
220 FcStringHash (const FcChar8
*s
)
227 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
232 FcValueHash (const FcValue
*v0
)
234 FcValue v
= FcValueCanonicalize(v0
);
239 return (FcChar32
) v
.u
.i
;
241 return FcDoubleHash (v
.u
.d
);
243 return FcStringHash (v
.u
.s
);
245 return (FcChar32
) v
.u
.b
;
247 return (FcDoubleHash (v
.u
.m
->xx
) ^
248 FcDoubleHash (v
.u
.m
->xy
) ^
249 FcDoubleHash (v
.u
.m
->yx
) ^
250 FcDoubleHash (v
.u
.m
->yy
));
252 return (FcChar32
) v
.u
.c
->num
;
254 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
255 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
257 return FcLangSetHash (v
.u
.l
);
263 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
265 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
268 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
270 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
271 FcValueListPtrU(lb
)->value
))
273 la
= FcValueListPtrU(la
)->next
;
274 lb
= FcValueListPtrU(lb
)->next
;
276 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
282 FcValueListHash (FcValueListPtr l
)
286 while (FcValueListPtrU(l
))
288 hash
= ((hash
<< 1) | (hash
>> 31)) ^
289 FcValueHash (&FcValueListPtrU(l
)->value
);
290 l
= FcValueListPtrU(l
)->next
;
296 FcPatternDestroy (FcPattern
*p
)
300 if (FcPatternFindFullFname (p
))
301 FcPatternAddFullFname (p
, 0);
303 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
306 for (i
= 0; i
< p
->num
; i
++)
307 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
310 if (FcPatternEltU(p
->elts
) && p
->elts
.bank
== FC_BANK_DYNAMIC
)
312 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
313 free (FcPatternEltU(p
->elts
));
314 p
->elts
= FcPatternEltPtrCreateDynamic(0);
317 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
321 #define FC_VALUE_LIST_HASH_SIZE 257
322 #define FC_PATTERN_HASH_SIZE 67
324 typedef struct _FcValueListEnt FcValueListEnt
;
326 struct _FcValueListEnt
{
327 FcValueListEnt
*next
;
332 typedef union _FcValueListAlign
{
337 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
338 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
339 static char FcValueListFrozenName
[][8] = {
352 FcValueListReport (void);
355 FcValueListReport (void)
359 printf ("Fc Frozen Values:\n");
360 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
361 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
362 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
363 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
366 static FcValueListEnt
*
367 FcValueListEntCreate (FcValueListPtr h
)
369 FcValueListAlign
*ea
;
377 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
379 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
380 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
381 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
382 // this leaks for some reason
383 ea
= malloc (sizeof (FcValueListAlign
));
386 new = malloc (n
* sizeof (FcValueList
));
389 memset(new, 0, n
* sizeof (FcValueList
));
390 FcMemAlloc (FC_MEM_VALLIST
, size
);
392 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
393 for (l
= h
; FcValueListPtrU(l
);
394 l
= FcValueListPtrU(l
)->next
, new++)
396 if ((FcValueListPtrU(l
)->value
.type
& ~FC_STORAGE_STATIC
) == FcTypeString
)
398 new->value
.type
= FcTypeString
;
399 new->value
.u
.s
= FcStrStaticName
400 (fc_value_string(&FcValueListPtrU(l
)->value
));
404 new->value
= FcValueSave (FcValueCanonicalize
405 (&FcValueListPtrU(l
)->value
));
407 new->binding
= FcValueListPtrU(l
)->binding
;
408 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
410 new->next
= FcValueListPtrCreateDynamic(new + 1);
414 new->next
= FcValueListPtrCreateDynamic(0);
421 FcValueListEntDestroy (FcValueListEnt
*e
)
425 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
427 /* XXX: We should perform these two operations with "size" as
428 computed in FcValueListEntCreate, but we don't have access to
429 that value here. Without this, the FcValueListFrozenBytes
430 values will be wrong as will the FcMemFree counts.
432 FcValueListFrozenBytes[e->list->value.type] -= size;
433 FcMemFree (FC_MEM_VALLIST, size);
436 for (l
= e
->list
; FcValueListPtrU(l
);
437 l
= FcValueListPtrU(l
)->next
)
439 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
440 FcValueDestroy (FcValueListPtrU(l
)->value
);
442 /* XXX: Are we being too chummy with the implementation here to
443 free(e) when it was actually the enclosing FcValueListAlign
444 that was allocated? */
448 static int FcValueListTotal
;
449 static int FcValueListUsed
;
451 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
453 static FcValueListPtr
454 FcValueListFreeze (FcValueListPtr l
)
456 FcChar32 hash
= FcValueListHash (l
);
457 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
461 for (ent
= *bucket
; ent
; ent
= ent
->next
)
463 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
467 ent
= FcValueListEntCreate (l
);
469 return FcValueListPtrCreateDynamic(0);
479 FcValueListThawAll (void)
482 FcValueListEnt
*ent
, *next
;
484 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
486 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
489 FcValueListEntDestroy (ent
);
491 FcValueListHashTable
[i
] = 0;
494 FcValueListTotal
= 0;
499 FcPatternBaseHash (FcPattern
*b
)
501 FcChar32 hash
= b
->num
;
504 for (i
= 0; i
< b
->num
; i
++)
505 hash
= ((hash
<< 1) | (hash
>> 31)) ^
506 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
510 typedef struct _FcPatternEnt FcPatternEnt
;
512 struct _FcPatternEnt
{
518 static int FcPatternTotal
;
519 static int FcPatternUsed
;
521 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
524 FcPatternBaseFreeze (FcPattern
*b
)
528 FcChar32 hash
= FcPatternBaseHash (b
);
529 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
534 for (ent
= *bucket
; ent
; ent
= ent
->next
)
536 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
538 for (i
= 0; i
< b
->num
; i
++)
540 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
541 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
543 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
544 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
553 * Compute size of pattern + elts
555 ent
= malloc (sizeof (FcPatternEnt
));
559 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
562 ep
= FcPatternCreate();
566 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
569 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
571 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
575 ep
->ref
= FC_REF_CONSTANT
;
577 for (i
= 0; i
< b
->num
; i
++)
579 (FcPatternEltU(ep
->elts
)+i
)->values
=
580 (FcPatternEltU(b
->elts
)+i
)->values
;
581 (FcPatternEltU(ep
->elts
)+i
)->object
=
582 (FcPatternEltU(b
->elts
)+i
)->object
;
585 if (FcPatternFindElt (b
, FC_FILE
))
586 FcPatternTransferFullFname (ep
, b
);
594 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
600 FcPatternBaseThawAll (void)
603 FcPatternEnt
*ent
, *next
;
605 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
607 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
612 FcPatternHashTable
[i
] = 0;
620 FcPatternFreeze (FcPattern
*p
)
622 FcPattern
*b
, *n
= 0;
626 if (p
->ref
== FC_REF_CONSTANT
)
629 b
= FcPatternCreate();
637 e
= malloc(b
->num
* sizeof (FcPatternElt
));
640 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
641 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
644 * Freeze object lists
646 for (i
= 0; i
< p
->num
; i
++)
648 (FcPatternEltU(b
->elts
)+i
)->object
=
649 (FcPatternEltU(p
->elts
)+i
)->object
;
650 (FcPatternEltU(b
->elts
)+i
)->values
=
651 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
652 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
656 if (FcPatternFindElt (p
, FC_FILE
))
657 FcPatternTransferFullFname (b
, p
);
662 n
= FcPatternBaseFreeze (b
);
664 if (FcDebug() & FC_DBG_MEMORY
)
666 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
667 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
671 free(FcPatternEltU(b
->elts
));
672 b
->elts
= FcPatternEltPtrCreateDynamic(0);
673 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
676 assert (FcPatternEqual (n
, p
));
682 FcPatternPosition (const FcPattern
*p
, const char *object
)
684 int low
, high
, mid
, c
;
687 obj
= FcObjectToPtr(object
);
694 mid
= (low
+ high
) >> 1;
695 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
709 FcPatternFindElt (const FcPattern
*p
, const char *object
)
711 int i
= FcPatternPosition (p
, object
);
714 return FcPatternEltU(p
->elts
)+i
;
718 FcPatternInsertElt (FcPattern
*p
, const char *object
)
723 i
= FcPatternPosition (p
, object
);
728 /* reallocate array */
729 if (p
->num
+ 1 >= p
->size
)
731 int s
= p
->size
+ 16;
732 if (FcPatternEltU(p
->elts
))
734 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
735 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
736 if (!e
) /* maybe it was mmapped */
738 e
= malloc(s
* sizeof (FcPatternElt
));
740 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
744 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
747 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
749 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
750 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
753 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
754 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
755 FcValueListPtrCreateDynamic(0);
761 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
762 FcPatternEltU(p
->elts
) + i
,
763 sizeof (FcPatternElt
) *
769 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectToPtr (object
);
770 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
773 return FcPatternEltU(p
->elts
)+i
;
777 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
784 if (pa
->num
!= pb
->num
)
786 for (i
= 0; i
< pa
->num
; i
++)
788 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
789 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
791 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
792 (FcPatternEltU(pb
->elts
)+i
)->values
))
799 FcPatternHash (const FcPattern
*p
)
804 for (i
= 0; i
< p
->num
; i
++)
806 h
= (((h
<< 1) | (h
>> 31)) ^
807 FcStringHash ((FcChar8
*)FcObjectPtrU ((FcPatternEltU(p
->elts
)+i
)->object
)) ^
808 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
814 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
816 FcPatternElt
*ea
, *eb
;
819 for (i
= 0; i
< os
->nobject
; i
++)
821 ea
= FcPatternFindElt (pai
, os
->objects
[i
]);
822 eb
= FcPatternFindElt (pbi
, os
->objects
[i
]);
827 if (!FcValueListEqual (ea
->values
, eb
->values
))
840 FcPatternAddWithBinding (FcPattern
*p
,
843 FcValueBinding binding
,
847 FcValueListPtr
new, *prev
;
850 if (p
->ref
== FC_REF_CONSTANT
)
853 newp
= malloc (sizeof (FcValueList
));
857 memset(newp
, 0, sizeof (FcValueList
));
858 new = FcValueListPtrCreateDynamic(newp
);
859 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
861 value
= FcValueSave (value
);
862 if (value
.type
== FcTypeVoid
)
865 FcValueListPtrU(new)->value
= value
;
866 FcValueListPtrU(new)->binding
= binding
;
867 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
869 e
= FcPatternInsertElt (p
, object
);
875 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
881 FcValueListPtrU(new)->next
= e
->values
;
888 switch (value
.type
) {
890 FcStrFree ((FcChar8
*) value
.u
.s
);
893 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
896 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
899 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
905 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
906 free (FcValueListPtrU(new));
912 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
914 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
918 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
920 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
924 FcPatternDel (FcPattern
*p
, const char *object
)
928 e
= FcPatternFindElt (p
, object
);
933 FcValueListDestroy (e
->values
);
935 /* shuffle existing ones down */
937 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
938 sizeof (FcPatternElt
));
940 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
941 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
946 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
949 FcValueListPtr
*prev
, l
;
951 e
= FcPatternFindElt (p
, object
);
954 for (prev
= &e
->values
;
955 FcValueListPtrU(l
= *prev
);
956 prev
= &FcValueListPtrU(l
)->next
)
960 *prev
= FcValueListPtrU(l
)->next
;
961 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
962 FcValueListDestroy (l
);
963 if (!FcValueListPtrU(e
->values
))
964 FcPatternDel (p
, object
);
973 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
977 v
.type
= FcTypeInteger
;
979 return FcPatternAdd (p
, object
, v
, FcTrue
);
983 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
987 v
.type
= FcTypeDouble
;
989 return FcPatternAdd (p
, object
, v
, FcTrue
);
994 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
998 v
.type
= FcTypeString
;
999 v
.u
.s
= FcStrStaticName(s
);
1000 return FcPatternAdd (p
, object
, v
, FcTrue
);
1004 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
1008 v
.type
= FcTypeMatrix
;
1010 return FcPatternAdd (p
, object
, v
, FcTrue
);
1015 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
1019 v
.type
= FcTypeBool
;
1021 return FcPatternAdd (p
, object
, v
, FcTrue
);
1025 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1029 v
.type
= FcTypeCharSet
;
1030 v
.u
.c
= (FcCharSet
*)c
;
1031 return FcPatternAdd (p
, object
, v
, FcTrue
);
1035 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1039 v
.type
= FcTypeFTFace
;
1041 return FcPatternAdd (p
, object
, v
, FcTrue
);
1045 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1049 v
.type
= FcTypeLangSet
;
1050 v
.u
.l
= (FcLangSet
*)ls
;
1051 return FcPatternAdd (p
, object
, v
, FcTrue
);
1055 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1060 e
= FcPatternFindElt (p
, object
);
1062 return FcResultNoMatch
;
1063 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1067 *v
= FcValueCanonicalize(&FcValueListPtrU(l
)->value
);
1068 return FcResultMatch
;
1072 return FcResultNoId
;
1076 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1081 r
= FcPatternGet (p
, object
, id
, &v
);
1082 if (r
!= FcResultMatch
)
1092 return FcResultTypeMismatch
;
1094 return FcResultMatch
;
1098 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1103 r
= FcPatternGet (p
, object
, id
, &v
);
1104 if (r
!= FcResultMatch
)
1111 *d
= (double) v
.u
.i
;
1114 return FcResultTypeMismatch
;
1116 return FcResultMatch
;
1120 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1125 r
= FcPatternGet (p
, object
, id
, &v
);
1126 if (r
!= FcResultMatch
)
1128 if (v
.type
!= FcTypeString
)
1129 return FcResultTypeMismatch
;
1131 if (FcObjectToPtr(object
) == FcObjectToPtr(FC_FILE
))
1133 const char *fn
, *fpath
;
1137 fn
= FcPatternFindFullFname(p
);
1140 *s
= (FcChar8
*) fn
;
1141 return FcResultMatch
;
1146 *s
= (FcChar8
*) v
.u
.s
;
1147 return FcResultMatch
;
1150 fpath
= FcCacheFindBankDir (p
->bank
);
1151 size
= strlen((char*)fpath
) + 1 + strlen ((char *)v
.u
.s
) + 1;
1152 fname
= malloc (size
);
1154 return FcResultOutOfMemory
;
1156 FcMemAlloc (FC_MEM_STRING
, size
);
1157 strcpy ((char *)fname
, (char *)fpath
);
1158 strcat ((char *)fname
, "/");
1159 strcat ((char *)fname
, (char *)v
.u
.s
);
1161 FcPatternAddFullFname (p
, (const char *)fname
);
1162 *s
= (FcChar8
*)fname
;
1163 return FcResultMatch
;
1166 *s
= (FcChar8
*) v
.u
.s
;
1167 return FcResultMatch
;
1171 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1176 r
= FcPatternGet (p
, object
, id
, &v
);
1177 if (r
!= FcResultMatch
)
1179 if (v
.type
!= FcTypeMatrix
)
1180 return FcResultTypeMismatch
;
1181 *m
= (FcMatrix
*)v
.u
.m
;
1182 return FcResultMatch
;
1187 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1192 r
= FcPatternGet (p
, object
, id
, &v
);
1193 if (r
!= FcResultMatch
)
1195 if (v
.type
!= FcTypeBool
)
1196 return FcResultTypeMismatch
;
1198 return FcResultMatch
;
1202 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1207 r
= FcPatternGet (p
, object
, id
, &v
);
1208 if (r
!= FcResultMatch
)
1210 if (v
.type
!= FcTypeCharSet
)
1211 return FcResultTypeMismatch
;
1212 *c
= (FcCharSet
*)v
.u
.c
;
1213 return FcResultMatch
;
1217 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1222 r
= FcPatternGet (p
, object
, id
, &v
);
1223 if (r
!= FcResultMatch
)
1225 if (v
.type
!= FcTypeFTFace
)
1226 return FcResultTypeMismatch
;
1227 *f
= (FT_Face
) v
.u
.f
;
1228 return FcResultMatch
;
1232 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1237 r
= FcPatternGet (p
, object
, id
, &v
);
1238 if (r
!= FcResultMatch
)
1240 if (v
.type
!= FcTypeLangSet
)
1241 return FcResultTypeMismatch
;
1242 *ls
= (FcLangSet
*)v
.u
.l
;
1243 return FcResultMatch
;
1247 FcPatternDuplicate (const FcPattern
*orig
)
1254 new = FcPatternCreate ();
1258 e
= FcPatternEltU(orig
->elts
);
1260 for (i
= 0; i
< orig
->num
; i
++)
1262 for (l
= (e
+ i
)->values
;
1264 l
= FcValueListPtrU(l
)->next
)
1265 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1266 FcValueCanonicalize(&FcValueListPtrU(l
)->value
),
1270 if (!strcmp ((char *)FcObjectPtrU((e
+ i
)->object
), FC_FILE
))
1273 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
1274 FcPatternAddFullFname (new, FcPatternFindFullFname(orig
));
1281 FcPatternDestroy (new);
1287 FcPatternReference (FcPattern
*p
)
1289 if (p
->ref
!= FC_REF_CONSTANT
)
1294 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1298 FcPatternVapBuild (ret
, orig
, va
);
1303 FcPatternBuild (FcPattern
*orig
, ...)
1307 va_start (va
, orig
);
1308 FcPatternVapBuild (orig
, orig
, va
);
1314 * Add all of the elements in 's' to 'p'
1317 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1323 for (i
= 0; i
< s
->num
; i
++)
1325 e
= FcPatternEltU(s
->elts
)+i
;
1326 for (v
= e
->values
; FcValueListPtrU(v
);
1327 v
= FcValueListPtrU(v
)->next
)
1329 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1330 FcValueCanonicalize(&FcValueListPtrU(v
)->value
),
1331 FcValueListPtrU(v
)->binding
, FcTrue
))
1338 #define OBJECT_HASH_SIZE 31
1339 static struct objectBucket
{
1340 struct objectBucket
*next
;
1342 } *FcObjectBuckets
[OBJECT_HASH_SIZE
];
1345 FcStrStaticName (const FcChar8
*name
)
1347 FcChar32 hash
= FcStringHash (name
);
1348 struct objectBucket
**p
;
1349 struct objectBucket
*b
;
1352 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1353 if (b
->hash
== hash
&& !strcmp ((char *)name
, (char *) (b
+ 1)))
1354 return (FcChar8
*) (b
+ 1);
1355 size
= sizeof (struct objectBucket
) + strlen ((char *)name
) + 1;
1356 b
= malloc (size
+ sizeof (int));
1357 /* workaround glibc bug which reads strlen in groups of 4 */
1358 FcMemAlloc (FC_MEM_STATICSTR
, size
+ sizeof (int));
1363 strcpy ((char *) (b
+ 1), (char *)name
);
1365 return (FcChar8
*) (b
+ 1);
1369 FcStrStaticNameFini (void)
1372 struct objectBucket
*b
, *next
;
1375 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1377 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
1380 name
= (char *) (b
+ 1);
1381 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1382 FcMemFree (FC_MEM_STATICSTR
, size
);
1385 FcObjectBuckets
[i
] = 0;
1390 FcPatternFini (void)
1392 FcPatternBaseThawAll ();
1393 FcValueListThawAll ();
1394 FcStrStaticNameFini ();
1395 FcObjectStaticNameFini ();
1399 FcPatternEltU (FcPatternEltPtr pei
)
1401 if (pei
.bank
== FC_BANK_DYNAMIC
)
1404 return &fcpatternelts
[FcCacheBankToIndex(pei
.bank
)][pei
.u
.stat
];
1407 static FcPatternEltPtr
1408 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1410 FcPatternEltPtr
new;
1411 new.bank
= FC_BANK_DYNAMIC
;
1416 static FcPatternEltPtr
1417 FcPatternEltPtrCreateStatic (int bank
, int i
)
1419 FcPatternEltPtr
new;
1426 FcStrNewBank (void);
1428 FcStrNeededBytes (const FcChar8
* s
);
1430 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
);
1431 static const FcChar8
*
1432 FcStrSerialize (int bank
, const FcChar8
* s
);
1434 FcStrUnserialize (FcCache metadata
, void *block_ptr
);
1437 FcValueListNewBank (void);
1439 FcValueListNeededBytes (FcValueList
* vl
);
1441 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
);
1442 static FcValueListPtr
1443 FcValueListSerialize(int bank
, FcValueList
*pi
);
1445 FcValueListUnserialize (FcCache metadata
, void *block_ptr
);
1449 FcPatternNewBank (void)
1451 fcpattern_count
= 0;
1452 fcpatternelt_count
= 0;
1455 FcValueListNewBank();
1459 FcPatternNeededBytes (FcPattern
* p
)
1464 fcpatternelt_count
+= p
->num
;
1466 for (i
= 0; i
< p
->num
; i
++)
1468 c
= FcValueListNeededBytes (FcValueListPtrU
1469 (((FcPatternEltU(p
->elts
)+i
)->values
)));
1475 return cum
+ sizeof (FcPattern
) + sizeof(FcPatternElt
)*p
->num
;
1479 FcPatternEnsureBank (int bi
)
1485 if (!fcpatterns
|| fcpattern_bank_count
<= bi
)
1487 int new_count
= bi
+ 4;
1488 pp
= realloc (fcpatterns
, sizeof (FcPattern
*) * new_count
);
1492 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
*) * new_count
);
1495 ep
= realloc (fcpatternelts
, sizeof (FcPatternElt
*) * new_count
);
1499 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
*) * new_count
);
1502 for (i
= fcpattern_bank_count
; i
< new_count
; i
++)
1505 fcpatternelts
[i
] = 0;
1508 fcpattern_bank_count
= new_count
;
1511 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1516 FcPatternDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1518 int bi
= FcCacheBankToIndex(metadata
->bank
);
1520 if (!FcPatternEnsureBank(bi
))
1524 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1525 block_ptr
= (void *)((char *)block_ptr
+
1526 (sizeof (FcPattern
) * fcpattern_count
));
1528 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1529 fcpatternelt_ptr
= 0;
1530 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1531 block_ptr
= (void *)((char *)block_ptr
+
1532 (sizeof (FcPatternElt
) * fcpatternelt_count
));
1534 metadata
->pattern_count
= fcpattern_count
;
1535 metadata
->patternelt_count
= fcpatternelt_count
;
1537 block_ptr
= FcStrDistributeBytes (metadata
, block_ptr
);
1538 block_ptr
= FcValueListDistributeBytes (metadata
, block_ptr
);
1543 FcPatternSerialize (int bank
, FcPattern
*old
)
1546 FcPatternElt
*e
, *nep
;
1548 FcValueListPtr v
, nv_head
, nvp
;
1549 int i
, elts
, bi
= FcCacheBankToIndex(bank
);
1551 p
= &fcpatterns
[bi
][fcpattern_ptr
++];
1553 elts
= fcpatternelt_ptr
;
1554 nep
= &fcpatternelts
[bi
][elts
];
1558 fcpatternelt_ptr
+= old
->num
;
1560 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1563 nvp
= nv_head
= FcValueListSerialize(bank
, FcValueListPtrU(v
));
1564 if (!FcValueListPtrU(nv_head
))
1566 nv
= FcValueListPtrU(nvp
);
1570 v
= FcValueListPtrU(v
)->next
,
1571 nv
= FcValueListPtrU(nv
->next
))
1574 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1576 nvp
= FcValueListSerialize
1577 (bank
, FcValueListPtrU(FcValueListPtrU(v
)->next
));
1582 nep
[i
].values
= nv_head
;
1583 nep
[i
].object
= e
->object
;
1586 p
->elts
= old
->elts
;
1587 p
->elts
= FcPatternEltPtrCreateStatic(bank
, elts
);
1590 p
->ref
= FC_REF_CONSTANT
;
1595 FcPatternUnserialize (FcCache metadata
, void *block_ptr
)
1597 int bi
= FcCacheBankToIndex(metadata
.bank
);
1598 if (!FcPatternEnsureBank(bi
))
1601 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * metadata
.pattern_count
);
1602 fcpatterns
[bi
] = (FcPattern
*)block_ptr
;
1603 block_ptr
= (void *)((char *)block_ptr
+
1604 (sizeof (FcPattern
) * metadata
.pattern_count
));
1606 FcMemAlloc (FC_MEM_PATELT
,
1607 sizeof (FcPatternElt
) * metadata
.patternelt_count
);
1608 fcpatternelts
[bi
] = (FcPatternElt
*)block_ptr
;
1609 block_ptr
= (void *)((char *)block_ptr
+
1610 (sizeof (FcPatternElt
) * metadata
.patternelt_count
));
1612 block_ptr
= FcStrUnserialize (metadata
, block_ptr
);
1613 block_ptr
= FcValueListUnserialize (metadata
, block_ptr
);
1619 FcValueListNewBank (void)
1621 fcvaluelist_count
= 0;
1628 FcValueListNeededBytes (FcValueList
*p
)
1635 vl
= FcValueListPtrU(vl
->next
))
1637 FcValue v
= FcValueCanonicalize(&vl
->value
); // unserialize just in case
1642 cum
+= FcCharSetNeededBytes(v
.u
.c
);
1645 cum
+= FcLangSetNeededBytes(v
.u
.l
);
1648 cum
+= FcStrNeededBytes(v
.u
.s
);
1652 fcvaluelist_count
++;
1653 cum
+= sizeof (FcValueList
);
1660 FcValueListEnsureBank (int bi
)
1664 if (!fcvaluelists
|| fcvaluelist_bank_count
<= bi
)
1666 int new_count
= bi
+ 2, i
;
1668 pvl
= realloc (fcvaluelists
, sizeof (FcValueList
*) * new_count
);
1672 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
*) * new_count
);
1675 for (i
= fcvaluelist_bank_count
; i
< new_count
; i
++)
1676 fcvaluelists
[i
] = 0;
1678 fcvaluelist_bank_count
= new_count
;
1684 FcValueListDistributeBytes (FcCache
* metadata
, void *block_ptr
)
1686 int bi
= FcCacheBankToIndex(metadata
->bank
);
1688 if (!FcValueListEnsureBank(bi
))
1691 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1692 fcvaluelist_ptr
= 0;
1693 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1694 block_ptr
= (void *)((char *)block_ptr
+
1695 (sizeof (FcValueList
) * fcvaluelist_count
));
1696 metadata
->valuelist_count
= fcvaluelist_count
;
1698 block_ptr
= FcCharSetDistributeBytes(metadata
, block_ptr
);
1699 block_ptr
= FcLangSetDistributeBytes(metadata
, block_ptr
);
1704 static FcValueListPtr
1705 FcValueListSerialize(int bank
, FcValueList
*pi
)
1709 int bi
= FcCacheBankToIndex(bank
);
1713 new.bank
= FC_BANK_DYNAMIC
;
1718 fcvaluelists
[bi
][fcvaluelist_ptr
] = *pi
;
1720 new.u
.stat
= fcvaluelist_ptr
++;
1721 fcvaluelists
[bi
][new.u
.stat
].value
= FcValueCanonicalize (&pi
->value
);
1722 v
= &fcvaluelists
[bi
][new.u
.stat
].value
;
1728 const FcChar8
* s
= FcStrSerialize(bank
, v
->u
.s
);
1730 return FcValueListPtrCreateDynamic(pi
);
1731 v
->u
.s_off
= s
- (const FcChar8
*)v
;
1732 v
->type
|= FC_STORAGE_STATIC
;
1740 FcCharSet
* c
= FcCharSetSerialize(bank
, (FcCharSet
*)v
->u
.c
);
1742 return FcValueListPtrCreateDynamic(pi
);
1743 v
->u
.c_off
= (char *)c
- (char *)v
;
1744 v
->type
|= FC_STORAGE_STATIC
;
1750 FcLangSet
* l
= FcLangSetSerialize(bank
, (FcLangSet
*)v
->u
.l
);
1752 return FcValueListPtrCreateDynamic(pi
);
1753 v
->u
.l_off
= (char *)l
- (char *)v
;
1754 v
->type
|= FC_STORAGE_STATIC
;
1764 FcValueListUnserialize (FcCache metadata
, void *block_ptr
)
1766 int bi
= FcCacheBankToIndex(metadata
.bank
);
1768 if (!FcValueListEnsureBank(bi
))
1771 FcMemAlloc (FC_MEM_VALLIST
,
1772 sizeof (FcValueList
) * metadata
.valuelist_count
);
1773 fcvaluelists
[bi
] = (FcValueList
*)block_ptr
;
1774 block_ptr
= (void *)((char *)block_ptr
+
1775 (sizeof (FcValueList
) * metadata
.valuelist_count
));
1777 block_ptr
= FcCharSetUnserialize(metadata
, block_ptr
);
1778 block_ptr
= FcLangSetUnserialize(metadata
, block_ptr
);
1784 FcValueListPtrU (FcValueListPtr pi
)
1786 if (pi
.bank
== FC_BANK_DYNAMIC
)
1789 return &fcvaluelists
[FcCacheBankToIndex(pi
.bank
)][pi
.u
.stat
];
1793 FcValueListPtrCreateDynamic(FcValueList
* p
)
1797 r
.bank
= FC_BANK_DYNAMIC
;
1802 static FcChar8
** static_strs
;
1803 static int static_str_bank_count
= 0, fcstr_ptr
, fcstr_count
;
1805 static struct objectBucket
*FcStrBuckets
[OBJECT_HASH_SIZE
];
1811 struct objectBucket
*b
, *next
;
1814 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1816 for (b
= FcStrBuckets
[i
]; b
; b
= next
)
1819 name
= (char *) (b
+ 1);
1820 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1821 FcMemFree (FC_MEM_STATICSTR
, size
);
1824 FcStrBuckets
[i
] = 0;
1831 FcStrNeededBytes (const FcChar8
* s
)
1833 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1834 struct objectBucket
**p
;
1835 struct objectBucket
*b
;
1838 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1839 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1841 size
= sizeof (struct objectBucket
) + strlen ((char *)s
) + 1 + sizeof(char *);
1843 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1848 strcpy ((char *) (b
+ 1), (char *)s
);
1849 *(char **)((char *) (b
+ 1) + strlen((char *)s
) + 1) = 0;
1852 fcstr_count
+= strlen((char *)s
) + 1;
1853 return strlen((char *)s
) + 1;
1857 FcStrEnsureBank (int bi
)
1861 if (!static_strs
|| static_str_bank_count
<= bi
)
1863 int new_count
= bi
+ 4, i
;
1864 ss
= realloc (static_strs
, sizeof (const char *) * new_count
);
1868 FcMemAlloc (FC_MEM_STRING
, sizeof (const char *) * (new_count
-static_str_bank_count
));
1871 for (i
= static_str_bank_count
; i
< new_count
; i
++)
1873 static_str_bank_count
= new_count
;
1879 FcStrDistributeBytes (FcCache
* metadata
, void * block_ptr
)
1881 int bi
= FcCacheBankToIndex(metadata
->bank
);
1882 if (!FcStrEnsureBank(bi
))
1885 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * fcstr_count
);
1886 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1887 block_ptr
= (void *)((char *)block_ptr
+ (sizeof (char) * fcstr_count
));
1888 metadata
->str_count
= fcstr_count
;
1894 static const FcChar8
*
1895 FcStrSerialize (int bank
, const FcChar8
* s
)
1897 FcChar32 hash
= FcStringHash ((const FcChar8
*) s
);
1898 struct objectBucket
**p
;
1899 struct objectBucket
*b
;
1900 int bi
= FcCacheBankToIndex(bank
);
1902 for (p
= &FcStrBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1903 if (b
->hash
== hash
&& !strcmp ((char *)s
, (char *) (b
+ 1)))
1905 FcChar8
* t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1908 strcpy((char *)(static_strs
[bi
] + fcstr_ptr
), (char *)s
);
1909 *(FcChar8
**)((FcChar8
*) (b
+ 1) + strlen((char *)s
) + 1) = (static_strs
[bi
] + fcstr_ptr
);
1910 fcstr_ptr
+= strlen((char *)s
) + 1;
1911 t
= *(FcChar8
**)(((FcChar8
*)(b
+ 1)) + strlen ((char *)s
) + 1);
1919 FcStrUnserialize (FcCache metadata
, void *block_ptr
)
1921 int bi
= FcCacheBankToIndex(metadata
.bank
);
1922 if (!FcStrEnsureBank(bi
))
1925 FcMemAlloc (FC_MEM_STRING
, sizeof (char) * metadata
.str_count
);
1926 static_strs
[bi
] = (FcChar8
*)block_ptr
;
1927 block_ptr
= (void *)((char *)block_ptr
+
1928 (sizeof (char) * metadata
.str_count
));
1933 /* we don't store these in the FcPattern itself because
1934 * we don't want to serialize the directory names */
1936 /* I suppose this should be cleaned, too... */
1937 typedef struct _FcPatternDirMapping
{
1940 } FcPatternDirMapping
;
1942 #define PATTERNDIR_HASH_SIZE 31
1943 static struct patternDirBucket
{
1944 struct patternDirBucket
*next
;
1945 FcPatternDirMapping m
;
1946 } FcPatternDirBuckets
[PATTERNDIR_HASH_SIZE
];
1949 FcPatternAddFullFname (const FcPattern
*p
, const char *fname
)
1951 struct patternDirBucket
*pb
;
1953 /* N.B. FcPatternHash fails, since it's contents-based, not
1954 * address-based, and we're in the process of mutating the FcPattern. */
1955 for (pb
= &FcPatternDirBuckets
1956 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
1957 pb
->m
.p
!= p
&& pb
->next
;
1963 pb
->m
.fname
= fname
;
1967 pb
->next
= malloc (sizeof (struct patternDirBucket
));
1970 FcMemAlloc (FC_MEM_CACHE
, sizeof (struct patternDirBucket
));
1974 pb
->next
->m
.fname
= fname
;
1978 FcPatternFindFullFname (const FcPattern
*p
)
1980 struct patternDirBucket
*pb
;
1982 for (pb
= &FcPatternDirBuckets
1983 [((int)p
/ sizeof (FcPattern
*)) % PATTERNDIR_HASH_SIZE
];
1992 FcPatternTransferFullFname (const FcPattern
*new, const FcPattern
*orig
)
1995 FcPatternGetString (orig
, FC_FILE
, 0, &s
);
1996 FcPatternAddFullFname (new, FcPatternFindFullFname(orig
));