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