Imported Upstream version 2.13.1
[platform/upstream/fontconfig.git] / src / fcpat.c
1 /*
2  * Copyright © 2000 Keith Packard
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the author(s) not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  The authors make no
11  * representations about the suitability of this software for any purpose.  It
12  * is provided "as is" without express or implied warranty.
13  *
14  * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include "fcint.h"
24 #include "fcftint.h"
25
26 /* Objects MT-safe for readonly access. */
27
28 FcPattern *
29 FcPatternCreate (void)
30 {
31     FcPattern   *p;
32
33     p = (FcPattern *) malloc (sizeof (FcPattern));
34     if (!p)
35         return 0;
36     memset (p, 0, sizeof (FcPattern));
37     p->num = 0;
38     p->size = 0;
39     p->elts_offset = FcPtrToOffset (p, NULL);
40     FcRefInit (&p->ref, 1);
41     return p;
42 }
43
44 void
45 FcValueDestroy (FcValue v)
46 {
47     switch ((int) v.type) {
48     case FcTypeString:
49         FcFree (v.u.s);
50         break;
51     case FcTypeMatrix:
52         FcMatrixFree ((FcMatrix *) v.u.m);
53         break;
54     case FcTypeCharSet:
55         FcCharSetDestroy ((FcCharSet *) v.u.c);
56         break;
57     case FcTypeLangSet:
58         FcLangSetDestroy ((FcLangSet *) v.u.l);
59         break;
60     case FcTypeRange:
61         FcRangeDestroy ((FcRange *) v.u.r);
62         break;
63     default:
64         break;
65     }
66 }
67
68 FcValue
69 FcValueCanonicalize (const FcValue *v)
70 {
71     FcValue new;
72
73     switch ((int) v->type)
74     {
75     case FcTypeString:
76         new.u.s = FcValueString(v);
77         new.type = FcTypeString;
78         break;
79     case FcTypeCharSet:
80         new.u.c = FcValueCharSet(v);
81         new.type = FcTypeCharSet;
82         break;
83     case FcTypeLangSet:
84         new.u.l = FcValueLangSet(v);
85         new.type = FcTypeLangSet;
86         break;
87     case FcTypeRange:
88         new.u.r = FcValueRange(v);
89         new.type = FcTypeRange;
90         break;
91     default:
92         new = *v;
93         break;
94     }
95     return new;
96 }
97
98 FcValue
99 FcValueSave (FcValue v)
100 {
101     switch ((int) v.type) {
102     case FcTypeString:
103         v.u.s = FcStrdup (v.u.s);
104         if (!v.u.s)
105             v.type = FcTypeVoid;
106         break;
107     case FcTypeMatrix:
108         v.u.m = FcMatrixCopy (v.u.m);
109         if (!v.u.m)
110             v.type = FcTypeVoid;
111         break;
112     case FcTypeCharSet:
113         v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
114         if (!v.u.c)
115             v.type = FcTypeVoid;
116         break;
117     case FcTypeLangSet:
118         v.u.l = FcLangSetCopy (v.u.l);
119         if (!v.u.l)
120             v.type = FcTypeVoid;
121         break;
122     case FcTypeRange:
123         v.u.r = FcRangeCopy (v.u.r);
124         if (!v.u.r)
125             v.type = FcTypeVoid;
126         break;
127     default:
128         break;
129     }
130     return v;
131 }
132
133 FcValueListPtr
134 FcValueListCreate (void)
135 {
136     return calloc (1, sizeof (FcValueList));
137 }
138
139 void
140 FcValueListDestroy (FcValueListPtr l)
141 {
142     FcValueListPtr next;
143     for (; l; l = next)
144     {
145         switch ((int) l->value.type) {
146         case FcTypeString:
147             FcFree (l->value.u.s);
148             break;
149         case FcTypeMatrix:
150             FcMatrixFree ((FcMatrix *)l->value.u.m);
151             break;
152         case FcTypeCharSet:
153             FcCharSetDestroy
154                 ((FcCharSet *) (l->value.u.c));
155             break;
156         case FcTypeLangSet:
157             FcLangSetDestroy
158                 ((FcLangSet *) (l->value.u.l));
159             break;
160         case FcTypeRange:
161             FcRangeDestroy ((FcRange *) (l->value.u.r));
162             break;
163         default:
164             break;
165         }
166         next = FcValueListNext(l);
167         free(l);
168     }
169 }
170
171 FcValueListPtr
172 FcValueListPrepend (FcValueListPtr vallist,
173                     FcValue        value,
174                     FcValueBinding binding)
175 {
176     FcValueListPtr new;
177
178     if (value.type == FcTypeVoid)
179         return vallist;
180     new = FcValueListCreate ();
181     if (!new)
182         return vallist;
183
184     new->value = FcValueSave (value);
185     new->binding = binding;
186     new->next = vallist;
187
188     return new;
189 }
190
191 FcValueListPtr
192 FcValueListAppend (FcValueListPtr vallist,
193                    FcValue        value,
194                    FcValueBinding binding)
195 {
196     FcValueListPtr new, last;
197
198     if (value.type == FcTypeVoid)
199         return vallist;
200     new = FcValueListCreate ();
201     if (!new)
202         return vallist;
203
204     new->value = FcValueSave (value);
205     new->binding = binding;
206     new->next = NULL;
207
208     if (vallist)
209     {
210         for (last = vallist; FcValueListNext (last); last = FcValueListNext (last));
211
212         last->next = new;
213     }
214     else
215         vallist = new;
216
217     return vallist;
218 }
219
220 FcValueListPtr
221 FcValueListDuplicate(FcValueListPtr orig)
222 {
223     FcValueListPtr new = NULL, l, t = NULL;
224     FcValue v;
225
226     for (l = orig; l != NULL; l = FcValueListNext (l))
227     {
228         if (!new)
229         {
230             t = new = FcValueListCreate();
231         }
232         else
233         {
234             t->next = FcValueListCreate();
235             t = FcValueListNext (t);
236         }
237         v = FcValueCanonicalize (&l->value);
238         t->value = FcValueSave (v);
239         t->binding = l->binding;
240         t->next = NULL;
241     }
242
243     return new;
244 }
245
246 FcBool
247 FcValueEqual (FcValue va, FcValue vb)
248 {
249     if (va.type != vb.type)
250     {
251         if (va.type == FcTypeInteger)
252         {
253             va.type = FcTypeDouble;
254             va.u.d = va.u.i;
255         }
256         if (vb.type == FcTypeInteger)
257         {
258             vb.type = FcTypeDouble;
259             vb.u.d = vb.u.i;
260         }
261         if (va.type != vb.type)
262             return FcFalse;
263     }
264     switch (va.type) {
265     case FcTypeUnknown:
266         return FcFalse; /* don't know how to compare this object */
267     case FcTypeVoid:
268         return FcTrue;
269     case FcTypeInteger:
270         return va.u.i == vb.u.i;
271     case FcTypeDouble:
272         return va.u.d == vb.u.d;
273     case FcTypeString:
274         return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
275     case FcTypeBool:
276         return va.u.b == vb.u.b;
277     case FcTypeMatrix:
278         return FcMatrixEqual (va.u.m, vb.u.m);
279     case FcTypeCharSet:
280         return FcCharSetEqual (va.u.c, vb.u.c);
281     case FcTypeFTFace:
282         return va.u.f == vb.u.f;
283     case FcTypeLangSet:
284         return FcLangSetEqual (va.u.l, vb.u.l);
285     case FcTypeRange:
286         return FcRangeIsInRange (va.u.r, vb.u.r);
287     }
288     return FcFalse;
289 }
290
291 static FcChar32
292 FcDoubleHash (double d)
293 {
294     if (d < 0)
295         d = -d;
296     if (d > 0xffffffff)
297         d = 0xffffffff;
298     return (FcChar32) d;
299 }
300
301 FcChar32
302 FcStringHash (const FcChar8 *s)
303 {
304     FcChar8     c;
305     FcChar32    h = 0;
306
307     if (s)
308         while ((c = *s++))
309             h = ((h << 1) | (h >> 31)) ^ c;
310     return h;
311 }
312
313 static FcChar32
314 FcValueHash (const FcValue *v)
315 {
316     switch (v->type) {
317     case FcTypeUnknown:
318     case FcTypeVoid:
319         return 0;
320     case FcTypeInteger:
321         return (FcChar32) v->u.i;
322     case FcTypeDouble:
323         return FcDoubleHash (v->u.d);
324     case FcTypeString:
325         return FcStringHash (FcValueString(v));
326     case FcTypeBool:
327         return (FcChar32) v->u.b;
328     case FcTypeMatrix:
329         return (FcDoubleHash (v->u.m->xx) ^
330                 FcDoubleHash (v->u.m->xy) ^
331                 FcDoubleHash (v->u.m->yx) ^
332                 FcDoubleHash (v->u.m->yy));
333     case FcTypeCharSet:
334         return (FcChar32) FcValueCharSet(v)->num;
335     case FcTypeFTFace:
336         return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
337                FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
338     case FcTypeLangSet:
339         return FcLangSetHash (FcValueLangSet(v));
340     case FcTypeRange:
341         return FcRangeHash (v->u.r);
342     }
343     return 0;
344 }
345
346 static FcBool
347 FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
348 {
349     if (la == lb)
350         return FcTrue;
351
352     while (la && lb)
353     {
354         if (!FcValueEqual (la->value, lb->value))
355             return FcFalse;
356         la = FcValueListNext(la);
357         lb = FcValueListNext(lb);
358     }
359     if (la || lb)
360         return FcFalse;
361     return FcTrue;
362 }
363
364 static FcChar32
365 FcValueListHash (FcValueListPtr l)
366 {
367     FcChar32    hash = 0;
368
369     for (; l; l = FcValueListNext(l))
370     {
371         hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
372     }
373     return hash;
374 }
375
376 static void *
377 FcPatternGetCacheObject (FcPattern *p)
378 {
379   /* We use a value to find the cache, instead of the FcPattern object
380    * because the pattern itself may be a cache allocation if we rewrote the path,
381    * so the p may not be in the cached region. */
382   return FcPatternEltValues(&FcPatternElts (p)[0]);
383 }
384
385 FcPattern *
386 FcPatternCacheRewriteFile (const FcPattern *p,
387                            FcCache *cache,
388                            const FcChar8 *relocated_font_file)
389 {
390     FcPatternElt *elts = FcPatternElts (p);
391     size_t i,j;
392     FcChar8 *data;
393     FcPattern *new_p;
394     FcPatternElt *new_elts;
395     FcValueList *new_value_list;
396     size_t new_path_len = strlen ((char *)relocated_font_file);
397     FcChar8 *new_path;
398
399     /* Allocate space for the patter, the PatternElt headers and
400      * the FC_FILE FcValueList and path that will be freed with the
401      * cache */
402     data = FcCacheAllocate (cache,
403                             sizeof (FcPattern) +
404                             p->num * sizeof (FcPatternElt) +
405                             sizeof (FcValueList) +
406                             new_path_len + 1);
407
408     new_p = (FcPattern *)data;
409     data += sizeof (FcPattern);
410     new_elts = (FcPatternElt *)(data);
411     data += p->num * sizeof (FcPatternElt);
412     new_value_list = (FcValueList *)data;
413     data += sizeof (FcValueList);
414     new_path = data;
415
416     *new_p = *p;
417     new_p->elts_offset = FcPtrToOffset (new_p, new_elts);
418
419     /* Copy all but the FILE values from the cache */
420     for (i = 0, j = 0; i < p->num; i++)
421     {
422         FcPatternElt *elt = &elts[i];
423         new_elts[j].object = elt->object;
424         if (elt->object != FC_FILE_OBJECT)
425             new_elts[j++].values = FcPatternEltValues(elt);
426         else
427             new_elts[j++].values = new_value_list;
428     }
429
430     new_value_list->next = NULL;
431     new_value_list->value.type = FcTypeString;
432     new_value_list->value.u.s = new_path;
433     new_value_list->binding = FcValueBindingWeak;
434
435     /* Add rewritten path at the end */
436     strcpy ((char *)new_path, (char *)relocated_font_file);
437
438     return new_p;
439 }
440
441 void
442 FcPatternDestroy (FcPattern *p)
443 {
444     int             i;
445     FcPatternElt    *elts;
446
447     if (!p)
448         return;
449
450     if (FcRefIsConst (&p->ref))
451     {
452         FcCacheObjectDereference (FcPatternGetCacheObject(p));
453         return;
454     }
455
456     if (FcRefDec (&p->ref) != 1)
457         return;
458
459     elts = FcPatternElts (p);
460     for (i = 0; i < FcPatternObjectCount (p); i++)
461         FcValueListDestroy (FcPatternEltValues(&elts[i]));
462
463     free (elts);
464     free (p);
465 }
466
467 int
468 FcPatternObjectCount (const FcPattern *pat)
469 {
470     if (pat)
471         return pat->num;
472
473     return 0;
474 }
475
476
477 static int
478 FcPatternObjectPosition (const FcPattern *p, FcObject object)
479 {
480     int     low, high, mid, c;
481     FcPatternElt    *elts = FcPatternElts(p);
482
483     low = 0;
484     high = FcPatternObjectCount (p) - 1;
485     c = 1;
486     mid = 0;
487     while (low <= high)
488     {
489         mid = (low + high) >> 1;
490         c = elts[mid].object - object;
491         if (c == 0)
492             return mid;
493         if (c < 0)
494             low = mid + 1;
495         else
496             high = mid - 1;
497     }
498     if (c < 0)
499         mid++;
500     return -(mid + 1);
501 }
502
503 int
504 FcPatternPosition (const FcPattern *p, const char *object)
505 {
506     return FcPatternObjectPosition (p, FcObjectFromName (object));
507 }
508
509 FcPatternElt *
510 FcPatternObjectFindElt (const FcPattern *p, FcObject object)
511 {
512     int     i = FcPatternObjectPosition (p, object);
513     if (i < 0)
514         return 0;
515     return &FcPatternElts(p)[i];
516 }
517
518 FcPatternElt *
519 FcPatternObjectInsertElt (FcPattern *p, FcObject object)
520 {
521     int             i;
522     FcPatternElt   *e;
523
524     i = FcPatternObjectPosition (p, object);
525     if (i < 0)
526     {
527         i = -i - 1;
528
529         /* reallocate array */
530         if (FcPatternObjectCount (p) + 1 >= p->size)
531         {
532             int s = p->size + 16;
533             if (p->size)
534             {
535                 FcPatternElt *e0 = FcPatternElts(p);
536                 e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
537                 if (!e) /* maybe it was mmapped */
538                 {
539                     e = malloc(s * sizeof (FcPatternElt));
540                     if (e)
541                         memcpy(e, e0, FcPatternObjectCount (p) * sizeof (FcPatternElt));
542                 }
543             }
544             else
545                 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
546             if (!e)
547                 return FcFalse;
548             p->elts_offset = FcPtrToOffset (p, e);
549             while (p->size < s)
550             {
551                 e[p->size].object = 0;
552                 e[p->size].values = NULL;
553                 p->size++;
554             }
555         }
556         
557         e = FcPatternElts(p);
558         /* move elts up */
559         memmove (e + i + 1,
560                  e + i,
561                  sizeof (FcPatternElt) *
562                  (FcPatternObjectCount (p) - i));
563                 
564         /* bump count */
565         p->num++;
566         
567         e[i].object = object;
568         e[i].values = NULL;
569     }
570
571     return FcPatternElts(p) + i;
572 }
573
574 FcBool
575 FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
576 {
577     FcPatternIter ia, ib;
578
579     if (pa == pb)
580         return FcTrue;
581
582     if (FcPatternObjectCount (pa) != FcPatternObjectCount (pb))
583         return FcFalse;
584     FcPatternIterStart (pa, &ia);
585     FcPatternIterStart (pb, &ib);
586     do {
587         FcBool ra, rb;
588
589         if (!FcPatternIterEqual (pa, &ia, pb, &ib))
590             return FcFalse;
591         ra = FcPatternIterNext (pa, &ia);
592         rb = FcPatternIterNext (pb, &ib);
593         if (!ra && !rb)
594             break;
595     } while (1);
596
597     return FcTrue;
598 }
599
600 FcChar32
601 FcPatternHash (const FcPattern *p)
602 {
603     int         i;
604     FcChar32    h = 0;
605     FcPatternElt    *pe = FcPatternElts(p);
606
607     for (i = 0; i < FcPatternObjectCount (p); i++)
608     {
609         h = (((h << 1) | (h >> 31)) ^
610              pe[i].object ^
611              FcValueListHash (FcPatternEltValues(&pe[i])));
612     }
613     return h;
614 }
615
616 FcBool
617 FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
618 {
619     FcPatternElt    *ea, *eb;
620     int             i;
621
622     for (i = 0; i < os->nobject; i++)
623     {
624         FcObject    object = FcObjectFromName (os->objects[i]);
625         ea = FcPatternObjectFindElt (pai, object);
626         eb = FcPatternObjectFindElt (pbi, object);
627         if (ea)
628         {
629             if (!eb)
630                 return FcFalse;
631             if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
632                 return FcFalse;
633         }
634         else
635         {
636             if (eb)
637                 return FcFalse;
638         }
639     }
640     return FcTrue;
641 }
642
643 FcBool
644 FcPatternObjectListAdd (FcPattern       *p,
645                         FcObject        object,
646                         FcValueListPtr  list,
647                         FcBool          append)
648 {
649     FcPatternElt   *e;
650     FcValueListPtr l, *prev;
651
652     if (FcRefIsConst (&p->ref))
653         goto bail0;
654
655     /*
656      * Make sure the stored type is valid for built-in objects
657      */
658     for (l = list; l != NULL; l = FcValueListNext (l))
659     {
660         if (!FcObjectValidType (object, l->value.type))
661         {
662             fprintf (stderr,
663                      "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
664             FcValuePrintFile (stderr, l->value);
665             fprintf (stderr, "\n");
666             goto bail0;
667         }
668     }
669
670     e = FcPatternObjectInsertElt (p, object);
671     if (!e)
672         goto bail0;
673
674     if (append)
675     {
676         for (prev = &e->values; *prev; prev = &(*prev)->next)
677             ;
678         *prev = list;
679     }
680     else
681     {
682         for (prev = &list; *prev; prev = &(*prev)->next)
683             ;
684         *prev = e->values;
685         e->values = list;
686     }
687
688     return FcTrue;
689
690 bail0:
691     return FcFalse;
692 }
693
694 FcBool
695 FcPatternObjectAddWithBinding  (FcPattern       *p,
696                                 FcObject        object,
697                                 FcValue         value,
698                                 FcValueBinding  binding,
699                                 FcBool          append)
700 {
701     FcPatternElt   *e;
702     FcValueListPtr new, *prev;
703
704     if (FcRefIsConst (&p->ref))
705         goto bail0;
706
707     new = FcValueListCreate ();
708     if (!new)
709         goto bail0;
710
711     value = FcValueSave (value);
712     if (value.type == FcTypeVoid)
713         goto bail1;
714
715     /*
716      * Make sure the stored type is valid for built-in objects
717      */
718     if (!FcObjectValidType (object, value.type))
719     {
720         fprintf (stderr,
721                  "Fontconfig warning: FcPattern object %s does not accept value",
722                  FcObjectName (object));
723         FcValuePrintFile (stderr, value);
724         fprintf (stderr, "\n");
725         goto bail1;
726     }
727
728     new->value = value;
729     new->binding = binding;
730     new->next = NULL;
731
732     e = FcPatternObjectInsertElt (p, object);
733     if (!e)
734         goto bail2;
735
736     if (append)
737     {
738         for (prev = &e->values; *prev; prev = &(*prev)->next)
739             ;
740         *prev = new;
741     }
742     else
743     {
744         new->next = e->values;
745         e->values = new;
746     }
747
748     return FcTrue;
749
750 bail2:
751     FcValueDestroy (value);
752 bail1:
753     free (new);
754 bail0:
755     return FcFalse;
756 }
757
758 FcBool
759 FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
760 {
761     return FcPatternObjectAddWithBinding (p, object,
762                                           value, FcValueBindingStrong, append);
763 }
764
765 FcBool
766 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
767 {
768     return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
769                                           value, FcValueBindingStrong, append);
770 }
771
772 FcBool
773 FcPatternAddWeak  (FcPattern *p, const char *object, FcValue value, FcBool append)
774 {
775     return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
776                                           value, FcValueBindingWeak, append);
777 }
778
779 FcBool
780 FcPatternObjectDel (FcPattern *p, FcObject object)
781 {
782     FcPatternElt   *e;
783
784     e = FcPatternObjectFindElt (p, object);
785     if (!e)
786         return FcFalse;
787
788     /* destroy value */
789     FcValueListDestroy (e->values);
790
791     /* shuffle existing ones down */
792     memmove (e, e+1,
793              (FcPatternElts(p) + FcPatternObjectCount (p) - (e + 1)) *
794              sizeof (FcPatternElt));
795     p->num--;
796     e = FcPatternElts(p) + FcPatternObjectCount (p);
797     e->object = 0;
798     e->values = NULL;
799     return FcTrue;
800 }
801
802 FcBool
803 FcPatternDel (FcPattern *p, const char *object)
804 {
805     return FcPatternObjectDel (p, FcObjectFromName (object));
806 }
807
808 FcBool
809 FcPatternRemove (FcPattern *p, const char *object, int id)
810 {
811     FcPatternElt    *e;
812     FcValueListPtr  *prev, l;
813
814     e = FcPatternObjectFindElt (p, FcObjectFromName (object));
815     if (!e)
816         return FcFalse;
817     for (prev = &e->values; (l = *prev); prev = &l->next)
818     {
819         if (!id)
820         {
821             *prev = l->next;
822             l->next = NULL;
823             FcValueListDestroy (l);
824             if (!e->values)
825                 FcPatternDel (p, object);
826             return FcTrue;
827         }
828         id--;
829     }
830     return FcFalse;
831 }
832
833 FcBool
834 FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
835 {
836     FcValue     v;
837
838     v.type = FcTypeInteger;
839     v.u.i = i;
840     return FcPatternObjectAdd (p, object, v, FcTrue);
841 }
842
843 FcBool
844 FcPatternAddInteger (FcPattern *p, const char *object, int i)
845 {
846     return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
847 }
848
849 FcBool
850 FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
851 {
852     FcValue     v;
853
854     v.type = FcTypeDouble;
855     v.u.d = d;
856     return FcPatternObjectAdd (p, object, v, FcTrue);
857 }
858
859
860 FcBool
861 FcPatternAddDouble (FcPattern *p, const char *object, double d)
862 {
863     return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
864 }
865
866 FcBool
867 FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
868 {
869     FcValue     v;
870
871     if (!s)
872     {
873         v.type = FcTypeVoid;
874         v.u.s = 0;
875         return FcPatternObjectAdd (p, object, v, FcTrue);
876     }
877
878     v.type = FcTypeString;
879     v.u.s = s;
880     return FcPatternObjectAdd (p, object, v, FcTrue);
881 }
882
883 FcBool
884 FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
885 {
886     return FcPatternObjectAddString (p, FcObjectFromName (object), s);
887 }
888
889 FcBool
890 FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
891 {
892     FcValue     v;
893
894     v.type = FcTypeMatrix;
895     v.u.m = s;
896     return FcPatternAdd (p, object, v, FcTrue);
897 }
898
899
900 FcBool
901 FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
902 {
903     FcValue     v;
904
905     v.type = FcTypeBool;
906     v.u.b = b;
907     return FcPatternObjectAdd (p, object, v, FcTrue);
908 }
909
910 FcBool
911 FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
912 {
913     return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
914 }
915
916 FcBool
917 FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
918 {
919     FcValue     v;
920
921     v.type = FcTypeCharSet;
922     v.u.c = (FcCharSet *)c;
923     return FcPatternAdd (p, object, v, FcTrue);
924 }
925
926 FcBool
927 FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
928 {
929     FcValue     v;
930
931     v.type = FcTypeFTFace;
932     v.u.f = (void *) f;
933     return FcPatternAdd (p, object, v, FcTrue);
934 }
935
936 FcBool
937 FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
938 {
939     FcValue     v;
940
941     v.type = FcTypeLangSet;
942     v.u.l = (FcLangSet *)ls;
943     return FcPatternAdd (p, object, v, FcTrue);
944 }
945
946 FcBool
947 FcPatternObjectAddRange (FcPattern *p, FcObject object, const FcRange *r)
948 {
949     FcValue v;
950
951     v.type = FcTypeRange;
952     v.u.r = (FcRange *)r;
953     return FcPatternObjectAdd (p, object, v, FcTrue);
954 }
955
956 FcBool
957 FcPatternAddRange (FcPattern *p, const char *object, const FcRange *r)
958 {
959     return FcPatternObjectAddRange (p, FcObjectFromName (object), r);
960 }
961
962 FcResult
963 FcPatternObjectGetWithBinding (const FcPattern *p, FcObject object, int id, FcValue *v, FcValueBinding *b)
964 {
965     FcPatternElt   *e;
966     FcValueListPtr l;
967
968     if (!p)
969         return FcResultNoMatch;
970     e = FcPatternObjectFindElt (p, object);
971     if (!e)
972         return FcResultNoMatch;
973     for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
974     {
975         if (!id)
976         {
977             *v = FcValueCanonicalize(&l->value);
978             if (b)
979                 *b = l->binding;
980             return FcResultMatch;
981         }
982         id--;
983     }
984     return FcResultNoId;
985 }
986
987 FcResult
988 FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
989 {
990     return FcPatternObjectGetWithBinding (p, object, id, v, NULL);
991 }
992
993 FcResult
994 FcPatternGetWithBinding (const FcPattern *p, const char *object, int id, FcValue *v, FcValueBinding *b)
995 {
996     return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, b);
997 }
998
999 FcResult
1000 FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
1001 {
1002     return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, NULL);
1003 }
1004
1005 FcResult
1006 FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
1007 {
1008     FcValue     v;
1009     FcResult    r;
1010
1011     r = FcPatternObjectGet (p, object, id, &v);
1012     if (r != FcResultMatch)
1013         return r;
1014     switch ((int) v.type) {
1015     case FcTypeDouble:
1016         *i = (int) v.u.d;
1017         break;
1018     case FcTypeInteger:
1019         *i = v.u.i;
1020         break;
1021     default:
1022         return FcResultTypeMismatch;
1023     }
1024     return FcResultMatch;
1025 }
1026
1027 FcResult
1028 FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
1029 {
1030     return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
1031 }
1032
1033
1034 FcResult
1035 FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
1036 {
1037     FcValue     v;
1038     FcResult    r;
1039
1040     r = FcPatternObjectGet (p, object, id, &v);
1041     if (r != FcResultMatch)
1042         return r;
1043     switch ((int) v.type) {
1044     case FcTypeDouble:
1045         *d = v.u.d;
1046         break;
1047     case FcTypeInteger:
1048         *d = (double) v.u.i;
1049         break;
1050     default:
1051         return FcResultTypeMismatch;
1052     }
1053     return FcResultMatch;
1054 }
1055
1056 FcResult
1057 FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
1058 {
1059     return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
1060 }
1061
1062 FcResult
1063 FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
1064 {
1065     FcValue     v;
1066     FcResult    r;
1067
1068     r = FcPatternObjectGet (p, object, id, &v);
1069     if (r != FcResultMatch)
1070         return r;
1071     if (v.type != FcTypeString)
1072         return FcResultTypeMismatch;
1073
1074     *s = (FcChar8 *) v.u.s;
1075     return FcResultMatch;
1076 }
1077
1078 FcResult
1079 FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
1080 {
1081     return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
1082 }
1083
1084 FcResult
1085 FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
1086 {
1087     FcValue     v;
1088     FcResult    r;
1089
1090     r = FcPatternGet (p, object, id, &v);
1091     if (r != FcResultMatch)
1092         return r;
1093     if (v.type != FcTypeMatrix)
1094         return FcResultTypeMismatch;
1095     *m = (FcMatrix *)v.u.m;
1096     return FcResultMatch;
1097 }
1098
1099
1100 FcResult
1101 FcPatternObjectGetBool (const FcPattern *p, FcObject object, int id, FcBool *b)
1102 {
1103     FcValue     v;
1104     FcResult    r;
1105
1106     r = FcPatternObjectGet (p, object, id, &v);
1107     if (r != FcResultMatch)
1108         return r;
1109     if (v.type != FcTypeBool)
1110         return FcResultTypeMismatch;
1111     *b = v.u.b;
1112     return FcResultMatch;
1113 }
1114
1115 FcResult
1116 FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
1117 {
1118     return FcPatternObjectGetBool (p, FcObjectFromName (object), id, b);
1119 }
1120
1121 FcResult
1122 FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
1123 {
1124     FcValue     v;
1125     FcResult    r;
1126
1127     r = FcPatternGet (p, object, id, &v);
1128     if (r != FcResultMatch)
1129         return r;
1130     if (v.type != FcTypeCharSet)
1131         return FcResultTypeMismatch;
1132     *c = (FcCharSet *)v.u.c;
1133     return FcResultMatch;
1134 }
1135
1136 FcResult
1137 FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
1138 {
1139     FcValue     v;
1140     FcResult    r;
1141
1142     r = FcPatternGet (p, object, id, &v);
1143     if (r != FcResultMatch)
1144         return r;
1145     if (v.type != FcTypeFTFace)
1146         return FcResultTypeMismatch;
1147     *f = (FT_Face) v.u.f;
1148     return FcResultMatch;
1149 }
1150
1151 FcResult
1152 FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
1153 {
1154     FcValue     v;
1155     FcResult    r;
1156
1157     r = FcPatternGet (p, object, id, &v);
1158     if (r != FcResultMatch)
1159         return r;
1160     if (v.type != FcTypeLangSet)
1161         return FcResultTypeMismatch;
1162     *ls = (FcLangSet *)v.u.l;
1163     return FcResultMatch;
1164 }
1165
1166 FcResult
1167 FcPatternObjectGetRange (const FcPattern *p, FcObject object, int id, FcRange **r)
1168 {
1169     FcValue     v;
1170     FcResult    res;
1171
1172     res = FcPatternObjectGet (p, object, id, &v);
1173     if (res != FcResultMatch)
1174         return res;
1175     switch ((int)v.type) {
1176     case FcTypeRange:
1177         *r = (FcRange *)v.u.r;
1178         break;
1179     default:
1180         return FcResultTypeMismatch;
1181     }
1182     return FcResultMatch;
1183 }
1184
1185 FcResult
1186 FcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r)
1187 {
1188     return FcPatternObjectGetRange (p, FcObjectFromName (object), id, r);
1189 }
1190
1191 FcPattern *
1192 FcPatternDuplicate (const FcPattern *orig)
1193 {
1194     FcPattern       *new;
1195     FcPatternIter   iter;
1196     FcValueListPtr  l;
1197
1198     if (!orig)
1199         return NULL;
1200
1201     new = FcPatternCreate ();
1202     if (!new)
1203         goto bail0;
1204
1205     FcPatternIterStart (orig, &iter);
1206     do
1207     {
1208         for (l = FcPatternIterGetValues (orig, &iter); l; l = FcValueListNext (l))
1209         {
1210             if (!FcPatternObjectAddWithBinding (new, FcPatternIterGetObjectId (orig, &iter),
1211                                                 FcValueCanonicalize(&l->value),
1212                                                 l->binding,
1213                                                 FcTrue))
1214                 goto bail1;
1215         }
1216     } while (FcPatternIterNext (orig, &iter));
1217
1218     return new;
1219
1220 bail1:
1221     FcPatternDestroy (new);
1222 bail0:
1223     return 0;
1224 }
1225
1226 void
1227 FcPatternReference (FcPattern *p)
1228 {
1229     if (!FcRefIsConst (&p->ref))
1230         FcRefInc (&p->ref);
1231     else
1232         FcCacheObjectReference (FcPatternGetCacheObject(p));
1233 }
1234
1235 FcPattern *
1236 FcPatternVaBuild (FcPattern *p, va_list va)
1237 {
1238     FcPattern   *ret;
1239
1240     FcPatternVapBuild (ret, p, va);
1241     return ret;
1242 }
1243
1244 FcPattern *
1245 FcPatternBuild (FcPattern *p, ...)
1246 {
1247     va_list     va;
1248
1249     va_start (va, p);
1250     FcPatternVapBuild (p, p, va);
1251     va_end (va);
1252     return p;
1253 }
1254
1255 /*
1256  * Add all of the elements in 's' to 'p'
1257  */
1258 FcBool
1259 FcPatternAppend (FcPattern *p, FcPattern *s)
1260 {
1261     FcPatternIter  iter;
1262     FcValueListPtr v;
1263
1264     FcPatternIterStart (s, &iter);
1265     do
1266     {
1267         for (v = FcPatternIterGetValues (s, &iter); v; v = FcValueListNext (v))
1268         {
1269             if (!FcPatternObjectAddWithBinding (p, FcPatternIterGetObjectId (s, &iter),
1270                                                 FcValueCanonicalize(&v->value),
1271                                                 v->binding, FcTrue))
1272                 return FcFalse;
1273         }
1274     } while (FcPatternIterNext (s, &iter));
1275
1276     return FcTrue;
1277 }
1278
1279 FcPattern *
1280 FcPatternFilter (FcPattern *p, const FcObjectSet *os)
1281 {
1282     int             i;
1283     FcPattern       *ret;
1284     FcPatternElt    *e;
1285     FcValueListPtr  v;
1286
1287     if (!os)
1288         return FcPatternDuplicate (p);
1289
1290     ret = FcPatternCreate ();
1291     if (!ret)
1292         return NULL;
1293
1294     for (i = 0; i < os->nobject; i++)
1295     {
1296         FcObject object = FcObjectFromName (os->objects[i]);
1297         e = FcPatternObjectFindElt (p, object);
1298         if (e)
1299         {
1300             for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1301             {
1302                 if (!FcPatternObjectAddWithBinding (ret, e->object,
1303                                                     FcValueCanonicalize(&v->value),
1304                                                     v->binding, FcTrue))
1305                     goto bail0;
1306             }
1307         }
1308     }
1309     return ret;
1310
1311 bail0:
1312     FcPatternDestroy (ret);
1313     return NULL;
1314 }
1315
1316 typedef struct _FcPatternPrivateIter {
1317     FcPatternElt *elt;
1318     int           pos;
1319 } FcPatternPrivateIter;
1320
1321 static void
1322 FcPatternIterSet (const FcPattern *pat, FcPatternPrivateIter *iter)
1323 {
1324     iter->elt = FcPatternObjectCount (pat) > 0 && iter->pos < FcPatternObjectCount (pat) ? &FcPatternElts (pat)[iter->pos] : NULL;
1325 }
1326
1327 void
1328 FcPatternIterStart (const FcPattern *pat, FcPatternIter *iter)
1329 {
1330     FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1331
1332     priv->pos = 0;
1333     FcPatternIterSet (pat, priv);
1334 }
1335
1336 FcBool
1337 FcPatternIterNext (const FcPattern *pat, FcPatternIter *iter)
1338 {
1339     FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1340
1341     priv->pos++;
1342     if (priv->pos >= FcPatternObjectCount (pat))
1343         return FcFalse;
1344     FcPatternIterSet (pat, priv);
1345
1346     return FcTrue;
1347 }
1348
1349 FcBool
1350 FcPatternIterEqual (const FcPattern *p1, FcPatternIter *i1,
1351                     const FcPattern *p2, FcPatternIter *i2)
1352 {
1353     FcBool b1 = FcPatternIterIsValid (p1, i1);
1354     FcBool b2 = FcPatternIterIsValid (p2, i2);
1355
1356     if (!i1 && !i2)
1357         return FcTrue;
1358     if (!b1 || !b2)
1359         return FcFalse;
1360     if (FcPatternIterGetObjectId (p1, i1) != FcPatternIterGetObjectId (p2, i2))
1361         return FcFalse;
1362
1363     return FcValueListEqual (FcPatternIterGetValues (p1, i1),
1364                              FcPatternIterGetValues (p2, i2));
1365 }
1366
1367 FcBool
1368 FcPatternFindObjectIter (const FcPattern *pat, FcPatternIter *iter, FcObject object)
1369 {
1370     FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1371     int i = FcPatternObjectPosition (pat, object);
1372
1373     priv->elt = NULL;
1374     if (i < 0)
1375         return FcFalse;
1376
1377     priv->pos = i;
1378     FcPatternIterSet (pat, priv);
1379
1380     return FcTrue;
1381 }
1382
1383 FcBool
1384 FcPatternFindIter (const FcPattern *pat, FcPatternIter *iter, const char *object)
1385 {
1386     return FcPatternFindObjectIter (pat, iter, FcObjectFromName (object));
1387 }
1388
1389 FcBool
1390 FcPatternIterIsValid (const FcPattern *pat, FcPatternIter *iter)
1391 {
1392     FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1393
1394     if (priv && priv->elt)
1395         return FcTrue;
1396
1397     return FcFalse;
1398 }
1399
1400 FcObject
1401 FcPatternIterGetObjectId (const FcPattern *pat, FcPatternIter *iter)
1402 {
1403     FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1404
1405     if (priv && priv->elt)
1406         return priv->elt->object;
1407
1408     return 0;
1409 }
1410
1411 const char *
1412 FcPatternIterGetObject (const FcPattern *pat, FcPatternIter *iter)
1413 {
1414     return FcObjectName (FcPatternIterGetObjectId (pat, iter));
1415 }
1416
1417 FcValueListPtr
1418 FcPatternIterGetValues (const FcPattern *pat, FcPatternIter *iter)
1419 {
1420     FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
1421
1422     if (priv && priv->elt)
1423         return FcPatternEltValues (priv->elt);
1424
1425     return NULL;
1426 }
1427
1428 int
1429 FcPatternIterValueCount (const FcPattern *pat, FcPatternIter *iter)
1430 {
1431     int count = 0;
1432     FcValueListPtr l;
1433
1434     for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l))
1435         count++;
1436
1437     return count;
1438 }
1439
1440 FcResult
1441 FcPatternIterGetValue (const FcPattern *pat, FcPatternIter *iter, int id, FcValue *v, FcValueBinding *b)
1442 {
1443     FcValueListPtr l;
1444
1445     for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l))
1446     {
1447         if (id == 0)
1448         {
1449             *v = FcValueCanonicalize (&l->value);
1450             if (b)
1451                 *b = l->binding;
1452             return FcResultMatch;
1453         }
1454         id--;
1455     }
1456     return FcResultNoId;
1457 }
1458
1459 FcBool
1460 FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
1461 {
1462     int i;
1463     FcPatternElt    *elts = FcPatternElts(pat);
1464
1465     if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
1466         return FcFalse;
1467     if (!FcSerializeAlloc (serialize, elts, FcPatternObjectCount (pat) * sizeof (FcPatternElt)))
1468         return FcFalse;
1469     for (i = 0; i < FcPatternObjectCount (pat); i++)
1470         if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
1471             return FcFalse;
1472     return FcTrue;
1473 }
1474
1475 FcPattern *
1476 FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
1477 {
1478     FcPattern       *pat_serialized;
1479     FcPatternElt    *elts = FcPatternElts (pat);
1480     FcPatternElt    *elts_serialized;
1481     FcValueList     *values_serialized;
1482     int             i;
1483
1484     pat_serialized = FcSerializePtr (serialize, pat);
1485     if (!pat_serialized)
1486         return NULL;
1487     *pat_serialized = *pat;
1488     pat_serialized->size = FcPatternObjectCount (pat);
1489     FcRefSetConst (&pat_serialized->ref);
1490
1491     elts_serialized = FcSerializePtr (serialize, elts);
1492     if (!elts_serialized)
1493         return NULL;
1494
1495     pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
1496                                                  elts_serialized);
1497
1498     for (i = 0; i < FcPatternObjectCount (pat); i++)
1499     {
1500         values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
1501         if (!values_serialized)
1502             return NULL;
1503         elts_serialized[i].object = elts[i].object;
1504         elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
1505                                                           values_serialized,
1506                                                           FcValueList);
1507     }
1508     if (FcDebug() & FC_DBG_CACHEV) {
1509         printf ("Raw pattern:\n");
1510         FcPatternPrint (pat);
1511         printf ("Serialized pattern:\n");
1512         FcPatternPrint (pat_serialized);
1513         printf ("\n");
1514     }
1515     return pat_serialized;
1516 }
1517
1518 FcBool
1519 FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
1520 {
1521     while (vl)
1522     {
1523         if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
1524             return FcFalse;
1525         switch ((int) vl->value.type) {
1526         case FcTypeString:
1527             if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
1528                 return FcFalse;
1529             break;
1530         case FcTypeCharSet:
1531             if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
1532                 return FcFalse;
1533             break;
1534         case FcTypeLangSet:
1535             if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
1536                 return FcFalse;
1537             break;
1538         case FcTypeRange:
1539             if (!FcRangeSerializeAlloc (serialize, vl->value.u.r))
1540                 return FcFalse;
1541             break;
1542         default:
1543             break;
1544         }
1545         vl = vl->next;
1546     }
1547     return FcTrue;
1548 }
1549
1550 FcValueList *
1551 FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
1552 {
1553     FcValueList *vl_serialized;
1554     FcChar8     *s_serialized;
1555     FcCharSet   *c_serialized;
1556     FcLangSet   *l_serialized;
1557     FcRange     *r_serialized;
1558     FcValueList *head_serialized = NULL;
1559     FcValueList *prev_serialized = NULL;
1560
1561     while (vl)
1562     {
1563         vl_serialized = FcSerializePtr (serialize, vl);
1564         if (!vl_serialized)
1565             return NULL;
1566
1567         if (prev_serialized)
1568             prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
1569                                                           vl_serialized,
1570                                                           FcValueList);
1571         else
1572             head_serialized = vl_serialized;
1573         
1574         vl_serialized->next = NULL;
1575         vl_serialized->value.type = vl->value.type;
1576         switch ((int) vl->value.type) {
1577         case FcTypeInteger:
1578             vl_serialized->value.u.i = vl->value.u.i;
1579             break;
1580         case FcTypeDouble:
1581             vl_serialized->value.u.d = vl->value.u.d;
1582             break;
1583         case FcTypeString:
1584             s_serialized = FcStrSerialize (serialize, vl->value.u.s);
1585             if (!s_serialized)
1586                 return NULL;
1587             vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
1588                                                              s_serialized,
1589                                                              FcChar8);
1590             break;
1591         case FcTypeBool:
1592             vl_serialized->value.u.b = vl->value.u.b;
1593             break;
1594         case FcTypeMatrix:
1595             /* can't happen */
1596             break;
1597         case FcTypeCharSet:
1598             c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
1599             if (!c_serialized)
1600                 return NULL;
1601             vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
1602                                                              c_serialized,
1603                                                              FcCharSet);
1604             break;
1605         case FcTypeFTFace:
1606             /* can't happen */
1607             break;
1608         case FcTypeLangSet:
1609             l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
1610             if (!l_serialized)
1611                 return NULL;
1612             vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
1613                                                              l_serialized,
1614                                                              FcLangSet);
1615             break;
1616         case FcTypeRange:
1617             r_serialized = FcRangeSerialize (serialize, vl->value.u.r);
1618             if (!r_serialized)
1619                 return NULL;
1620             vl_serialized->value.u.r = FcPtrToEncodedOffset (&vl_serialized->value,
1621                                                              r_serialized,
1622                                                              FcRange);
1623             break;
1624         default:
1625             break;
1626         }
1627         prev_serialized = vl_serialized;
1628         vl = vl->next;
1629     }
1630     return head_serialized;
1631 }
1632
1633 #define __fcpat__
1634 #include "fcaliastail.h"
1635 #include "fcftaliastail.h"
1636 #undef __fcpat__