1 /*
2 * fontconfig/src/fcname.c
3 *
4 * Copyright © 2000 Keith Packard
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of the author(s) not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. The authors make no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25 #include "fcint.h"
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30
31 static const FcObjectType FcObjects[] = {
32 #define FC_OBJECT(NAME, Type, Cmp) { FC_##NAME, Type },
33 #include "fcobjs.h"
34 #undef FC_OBJECT
35 };
36
37 #define NUM_OBJECT_TYPES ((int) (sizeof FcObjects / sizeof FcObjects[0]))
38
39 static const FcObjectType *
FcObjectFindById(FcObject object)40 FcObjectFindById (FcObject object)
41 {
42 if (1 <= object && object <= NUM_OBJECT_TYPES)
43 return &FcObjects[object - 1];
44 return FcObjectLookupOtherTypeById (object);
45 }
46
47 FcBool
FcNameRegisterObjectTypes(const FcObjectType * types,int ntypes)48 FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
49 {
50 /* Deprecated. */
51 return FcFalse;
52 }
53
54 FcBool
FcNameUnregisterObjectTypes(const FcObjectType * types,int ntypes)55 FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
56 {
57 /* Deprecated. */
58 return FcFalse;
59 }
60
61 const FcObjectType *
FcNameGetObjectType(const char * object)62 FcNameGetObjectType (const char *object)
63 {
64 int id = FcObjectLookupBuiltinIdByName (object);
65
66 if (!id)
67 return FcObjectLookupOtherTypeByName (object);
68
69 return &FcObjects[id - 1];
70 }
71
72 FcBool
FcObjectValidType(FcObject object,FcType type)73 FcObjectValidType (FcObject object, FcType type)
74 {
75 const FcObjectType *t = FcObjectFindById (object);
76
77 if (t) {
78 switch ((int) t->type) {
79 case FcTypeUnknown:
80 return FcTrue;
81 case FcTypeDouble:
82 case FcTypeInteger:
83 if (type == FcTypeDouble || type == FcTypeInteger)
84 return FcTrue;
85 break;
86 case FcTypeLangSet:
87 if (type == FcTypeLangSet || type == FcTypeString)
88 return FcTrue;
89 break;
90 case FcTypeRange:
91 if (type == FcTypeRange ||
92 type == FcTypeDouble ||
93 type == FcTypeInteger)
94 return FcTrue;
95 break;
96 default:
97 if (type == t->type)
98 return FcTrue;
99 break;
100 }
101 return FcFalse;
102 }
103 return FcTrue;
104 }
105
106 FcObject
FcObjectFromName(const char * name)107 FcObjectFromName (const char * name)
108 {
109 return FcObjectLookupIdByName (name);
110 }
111
112 FcObjectSet *
FcObjectGetSet(void)113 FcObjectGetSet (void)
114 {
115 int i;
116 FcObjectSet *os = NULL;
117
118
119 os = FcObjectSetCreate ();
120 for (i = 0; i < NUM_OBJECT_TYPES; i++)
121 FcObjectSetAdd (os, FcObjects[i].object);
122
123 return os;
124 }
125
126 const char *
FcObjectName(FcObject object)127 FcObjectName (FcObject object)
128 {
129 const FcObjectType *o = FcObjectFindById (object);
130
131 if (o)
132 return o->object;
133
134 return FcObjectLookupOtherNameById (object);
135 }
136
137 static const FcConstant _FcBaseConstants[] = {
138 { (FcChar8 *) "thin", "weight", FC_WEIGHT_THIN, },
139 { (FcChar8 *) "extralight", "weight", FC_WEIGHT_EXTRALIGHT, },
140 { (FcChar8 *) "ultralight", "weight", FC_WEIGHT_EXTRALIGHT, },
141 { (FcChar8 *) "demilight", "weight", FC_WEIGHT_DEMILIGHT, },
142 { (FcChar8 *) "semilight", "weight", FC_WEIGHT_DEMILIGHT, },
143 { (FcChar8 *) "light", "weight", FC_WEIGHT_LIGHT, },
144 { (FcChar8 *) "book", "weight", FC_WEIGHT_BOOK, },
145 { (FcChar8 *) "regular", "weight", FC_WEIGHT_REGULAR, },
146 { (FcChar8 *) "medium", "weight", FC_WEIGHT_MEDIUM, },
147 { (FcChar8 *) "demibold", "weight", FC_WEIGHT_DEMIBOLD, },
148 { (FcChar8 *) "semibold", "weight", FC_WEIGHT_DEMIBOLD, },
149 { (FcChar8 *) "bold", "weight", FC_WEIGHT_BOLD, },
150 { (FcChar8 *) "extrabold", "weight", FC_WEIGHT_EXTRABOLD, },
151 { (FcChar8 *) "ultrabold", "weight", FC_WEIGHT_EXTRABOLD, },
152 { (FcChar8 *) "black", "weight", FC_WEIGHT_BLACK, },
153 { (FcChar8 *) "heavy", "weight", FC_WEIGHT_HEAVY, },
154
155 { (FcChar8 *) "roman", "slant", FC_SLANT_ROMAN, },
156 { (FcChar8 *) "italic", "slant", FC_SLANT_ITALIC, },
157 { (FcChar8 *) "oblique", "slant", FC_SLANT_OBLIQUE, },
158
159 { (FcChar8 *) "ultracondensed", "width", FC_WIDTH_ULTRACONDENSED },
160 { (FcChar8 *) "extracondensed", "width", FC_WIDTH_EXTRACONDENSED },
161 { (FcChar8 *) "condensed", "width", FC_WIDTH_CONDENSED },
162 { (FcChar8 *) "semicondensed", "width", FC_WIDTH_SEMICONDENSED },
163 { (FcChar8 *) "normal", "width", FC_WIDTH_NORMAL },
164 { (FcChar8 *) "semiexpanded", "width", FC_WIDTH_SEMIEXPANDED },
165 { (FcChar8 *) "expanded", "width", FC_WIDTH_EXPANDED },
166 { (FcChar8 *) "extraexpanded", "width", FC_WIDTH_EXTRAEXPANDED },
167 { (FcChar8 *) "ultraexpanded", "width", FC_WIDTH_ULTRAEXPANDED },
168
169 { (FcChar8 *) "proportional", "spacing", FC_PROPORTIONAL, },
170 { (FcChar8 *) "dual", "spacing", FC_DUAL, },
171 { (FcChar8 *) "mono", "spacing", FC_MONO, },
172 { (FcChar8 *) "charcell", "spacing", FC_CHARCELL, },
173
174 { (FcChar8 *) "unknown", "rgba", FC_RGBA_UNKNOWN },
175 { (FcChar8 *) "rgb", "rgba", FC_RGBA_RGB, },
176 { (FcChar8 *) "bgr", "rgba", FC_RGBA_BGR, },
177 { (FcChar8 *) "vrgb", "rgba", FC_RGBA_VRGB },
178 { (FcChar8 *) "vbgr", "rgba", FC_RGBA_VBGR },
179 { (FcChar8 *) "none", "rgba", FC_RGBA_NONE },
180
181 { (FcChar8 *) "hintnone", "hintstyle", FC_HINT_NONE },
182 { (FcChar8 *) "hintslight", "hintstyle", FC_HINT_SLIGHT },
183 { (FcChar8 *) "hintmedium", "hintstyle", FC_HINT_MEDIUM },
184 { (FcChar8 *) "hintfull", "hintstyle", FC_HINT_FULL },
185
186 { (FcChar8 *) "antialias", "antialias", FcTrue },
187 { (FcChar8 *) "hinting", "hinting", FcTrue },
188 { (FcChar8 *) "verticallayout", "verticallayout", FcTrue },
189 { (FcChar8 *) "autohint", "autohint", FcTrue },
190 { (FcChar8 *) "globaladvance", "globaladvance", FcTrue }, /* deprecated */
191 { (FcChar8 *) "outline", "outline", FcTrue },
192 { (FcChar8 *) "scalable", "scalable", FcTrue },
193 { (FcChar8 *) "minspace", "minspace", FcTrue },
194 { (FcChar8 *) "embolden", "embolden", FcTrue },
195 { (FcChar8 *) "embeddedbitmap", "embeddedbitmap", FcTrue },
196 { (FcChar8 *) "decorative", "decorative", FcTrue },
197 { (FcChar8 *) "lcdnone", "lcdfilter", FC_LCD_NONE },
198 { (FcChar8 *) "lcddefault", "lcdfilter", FC_LCD_DEFAULT },
199 { (FcChar8 *) "lcdlight", "lcdfilter", FC_LCD_LIGHT },
200 { (FcChar8 *) "lcdlegacy", "lcdfilter", FC_LCD_LEGACY },
201 };
202
203 #define NUM_FC_CONSTANTS (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
204
205 FcBool
FcNameRegisterConstants(const FcConstant * consts,int nconsts)206 FcNameRegisterConstants (const FcConstant *consts, int nconsts)
207 {
208 /* Deprecated. */
209 return FcFalse;
210 }
211
212 FcBool
FcNameUnregisterConstants(const FcConstant * consts,int nconsts)213 FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
214 {
215 /* Deprecated. */
216 return FcFalse;
217 }
218
219 const FcConstant *
FcNameGetConstant(const FcChar8 * string)220 FcNameGetConstant (const FcChar8 *string)
221 {
222 unsigned int i;
223
224 for (i = 0; i < NUM_FC_CONSTANTS; i++)
225 if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name))
226 return &_FcBaseConstants[i];
227
228 return 0;
229 }
230
231 FcBool
FcNameConstant(const FcChar8 * string,int * result)232 FcNameConstant (const FcChar8 *string, int *result)
233 {
234 const FcConstant *c;
235
236 if ((c = FcNameGetConstant(string)))
237 {
238 *result = c->value;
239 return FcTrue;
240 }
241 return FcFalse;
242 }
243
244 FcBool
FcNameConstantWithObjectCheck(const FcChar8 * string,const char * object,int * result)245 FcNameConstantWithObjectCheck (const FcChar8 *string, const char *object, int *result)
246 {
247 const FcConstant *c;
248
249 if ((c = FcNameGetConstant(string)))
250 {
251 if (strcmp (c->object, object) != 0)
252 {
253 fprintf (stderr, "Fontconfig error: Unexpected constant name `%s' used for object `%s': should be `%s'\n", string, object, c->object);
254 return FcFalse;
255 }
256 *result = c->value;
257 return FcTrue;
258 }
259 return FcFalse;
260 }
261
262 FcBool
FcNameBool(const FcChar8 * v,FcBool * result)263 FcNameBool (const FcChar8 *v, FcBool *result)
264 {
265 char c0, c1;
266
267 c0 = *v;
268 c0 = FcToLower (c0);
269 if (c0 == 't' || c0 == 'y' || c0 == '1')
270 {
271 *result = FcTrue;
272 return FcTrue;
273 }
274 if (c0 == 'f' || c0 == 'n' || c0 == '0')
275 {
276 *result = FcFalse;
277 return FcTrue;
278 }
279 if (c0 == 'd' || c0 == 'x' || c0 == '2')
280 {
281 *result = FcDontCare;
282 return FcTrue;
283 }
284 if (c0 == 'o')
285 {
286 c1 = v[1];
287 c1 = FcToLower (c1);
288 if (c1 == 'n')
289 {
290 *result = FcTrue;
291 return FcTrue;
292 }
293 if (c1 == 'f')
294 {
295 *result = FcFalse;
296 return FcTrue;
297 }
298 if (c1 == 'r')
299 {
300 *result = FcDontCare;
301 return FcTrue;
302 }
303 }
304 return FcFalse;
305 }
306
307 static FcValue
FcNameConvert(FcType type,const char * object,FcChar8 * string)308 FcNameConvert (FcType type, const char *object, FcChar8 *string)
309 {
310 FcValue v;
311 FcMatrix m;
312 double b, e;
313 char *p;
314
315 v.type = type;
316 switch ((int) v.type) {
317 case FcTypeInteger:
318 if (!FcNameConstantWithObjectCheck (string, object, &v.u.i))
319 v.u.i = atoi ((char *) string);
320 break;
321 case FcTypeString:
322 v.u.s = FcStrdup (string);
323 if (!v.u.s)
324 v.type = FcTypeVoid;
325 break;
326 case FcTypeBool:
327 if (!FcNameBool (string, &v.u.b))
328 v.u.b = FcFalse;
329 break;
330 case FcTypeDouble:
331 v.u.d = strtod ((char *) string, 0);
332 break;
333 case FcTypeMatrix:
334 FcMatrixInit (&m);
335 sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy);
336 v.u.m = FcMatrixCopy (&m);
337 break;
338 case FcTypeCharSet:
339 v.u.c = FcNameParseCharSet (string);
340 if (!v.u.c)
341 v.type = FcTypeVoid;
342 break;
343 case FcTypeLangSet:
344 v.u.l = FcNameParseLangSet (string);
345 if (!v.u.l)
346 v.type = FcTypeVoid;
347 break;
348 case FcTypeRange:
349 if (sscanf ((char *) string, "[%lg %lg]", &b, &e) != 2)
350 {
351 char *sc, *ec;
352 size_t len = strlen ((const char *) string);
353 int si, ei;
354
355 sc = malloc (len + 1);
356 ec = malloc (len + 1);
357 if (sc && ec && sscanf ((char *) string, "[%s %[^]]]", sc, ec) == 2)
358 {
359 if (FcNameConstantWithObjectCheck ((const FcChar8 *) sc, object, &si) &&
360 FcNameConstantWithObjectCheck ((const FcChar8 *) ec, object, &ei))
361 v.u.r = FcRangeCreateDouble (si, ei);
362 else
363 goto bail1;
364 }
365 else
366 {
367 bail1:
368 v.type = FcTypeDouble;
369 if (FcNameConstantWithObjectCheck (string, object, &si))
370 {
371 v.u.d = (double) si;
372 } else {
373 v.u.d = strtod ((char *) string, &p);
374 if (p != NULL && p[0] != 0)
375 v.type = FcTypeVoid;
376 }
377 }
378 if (sc)
379 free (sc);
380 if (ec)
381 free (ec);
382 }
383 else
384 v.u.r = FcRangeCreateDouble (b, e);
385 break;
386 default:
387 break;
388 }
389 return v;
390 }
391
392 static const FcChar8 *
FcNameFindNext(const FcChar8 * cur,const char * delim,FcChar8 * save,FcChar8 * last)393 FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
394 {
395 FcChar8 c;
396
397 while ((c = *cur))
398 {
399 if (!isspace (c))
400 break;
401 ++cur;
402 }
403 while ((c = *cur))
404 {
405 if (c == '\\')
406 {
407 ++cur;
408 if (!(c = *cur))
409 break;
410 }
411 else if (strchr (delim, c))
412 break;
413 ++cur;
414 *save++ = c;
415 }
416 *save = 0;
417 *last = *cur;
418 if (*cur)
419 cur++;
420 return cur;
421 }
422
423 FcPattern *
FcNameParse(const FcChar8 * name)424 FcNameParse (const FcChar8 *name)
425 {
426 FcChar8 *save;
427 FcPattern *pat;
428 double d;
429 FcChar8 *e;
430 FcChar8 delim;
431 FcValue v;
432 const FcObjectType *t;
433 const FcConstant *c;
434
435 /* freed below */
436 save = malloc (strlen ((char *) name) + 1);
437 if (!save)
438 goto bail0;
439 pat = FcPatternCreate ();
440 if (!pat)
441 goto bail1;
442
443 for (;;)
444 {
445 name = FcNameFindNext (name, "-,:", save, &delim);
446 if (save[0])
447 {
448 if (!FcPatternObjectAddString (pat, FC_FAMILY_OBJECT, save))
449 goto bail2;
450 }
451 if (delim != ',')
452 break;
453 }
454 if (delim == '-')
455 {
456 for (;;)
457 {
458 name = FcNameFindNext (name, "-,:", save, &delim);
459 d = strtod ((char *) save, (char **) &e);
460 if (e != save)
461 {
462 if (!FcPatternObjectAddDouble (pat, FC_SIZE_OBJECT, d))
463 goto bail2;
464 }
465 if (delim != ',')
466 break;
467 }
468 }
469 while (delim == ':')
470 {
471 name = FcNameFindNext (name, "=_:", save, &delim);
472 if (save[0])
473 {
474 if (delim == '=' || delim == '_')
475 {
476 t = FcNameGetObjectType ((char *) save);
477 for (;;)
478 {
479 name = FcNameFindNext (name, ":,", save, &delim);
480 if (t)
481 {
482 v = FcNameConvert (t->type, t->object, save);
483 if (!FcPatternAdd (pat, t->object, v, FcTrue))
484 {
485 FcValueDestroy (v);
486 goto bail2;
487 }
488 FcValueDestroy (v);
489 }
490 if (delim != ',')
491 break;
492 }
493 }
494 else
495 {
496 if ((c = FcNameGetConstant (save)))
497 {
498 t = FcNameGetObjectType ((char *) c->object);
499 if (t == NULL)
500 goto bail2;
501 switch ((int) t->type) {
502 case FcTypeInteger:
503 case FcTypeDouble:
504 if (!FcPatternAddInteger (pat, c->object, c->value))
505 goto bail2;
506 break;
507 case FcTypeBool:
508 if (!FcPatternAddBool (pat, c->object, c->value))
509 goto bail2;
510 break;
511 case FcTypeRange:
512 if (!FcPatternAddInteger (pat, c->object, c->value))
513 goto bail2;
514 break;
515 default:
516 break;
517 }
518 }
519 }
520 }
521 }
522
523 free (save);
524 return pat;
525
526 bail2:
527 FcPatternDestroy (pat);
528 bail1:
529 free (save);
530 bail0:
531 return 0;
532 }
533 static FcBool
FcNameUnparseString(FcStrBuf * buf,const FcChar8 * string,const FcChar8 * escape)534 FcNameUnparseString (FcStrBuf *buf,
535 const FcChar8 *string,
536 const FcChar8 *escape)
537 {
538 FcChar8 c;
539 while ((c = *string++))
540 {
541 if (escape && strchr ((char *) escape, (char) c))
542 {
543 if (!FcStrBufChar (buf, escape[0]))
544 return FcFalse;
545 }
546 if (!FcStrBufChar (buf, c))
547 return FcFalse;
548 }
549 return FcTrue;
550 }
551
552 FcBool
FcNameUnparseValue(FcStrBuf * buf,FcValue * v0,FcChar8 * escape)553 FcNameUnparseValue (FcStrBuf *buf,
554 FcValue *v0,
555 FcChar8 *escape)
556 {
557 FcChar8 temp[1024];
558 FcValue v = FcValueCanonicalize(v0);
559
560 switch (v.type) {
561 case FcTypeUnknown:
562 case FcTypeVoid:
563 return FcTrue;
564 case FcTypeInteger:
565 sprintf ((char *) temp, "%d", v.u.i);
566 return FcNameUnparseString (buf, temp, 0);
567 case FcTypeDouble:
568 sprintf ((char *) temp, "%g", v.u.d);
569 return FcNameUnparseString (buf, temp, 0);
570 case FcTypeString:
571 return FcNameUnparseString (buf, v.u.s, escape);
572 case FcTypeBool:
573 return FcNameUnparseString (buf,
574 v.u.b == FcTrue ? (FcChar8 *) "True" :
575 v.u.b == FcFalse ? (FcChar8 *) "False" :
576 (FcChar8 *) "DontCare", 0);
577 case FcTypeMatrix:
578 sprintf ((char *) temp, "%g %g %g %g",
579 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
580 return FcNameUnparseString (buf, temp, 0);
581 case FcTypeCharSet:
582 return FcNameUnparseCharSet (buf, v.u.c);
583 case FcTypeLangSet:
584 return FcNameUnparseLangSet (buf, v.u.l);
585 case FcTypeFTFace:
586 return FcTrue;
587 case FcTypeRange:
588 sprintf ((char *) temp, "[%g %g]", v.u.r->begin, v.u.r->end);
589 return FcNameUnparseString (buf, temp, 0);
590 }
591 return FcFalse;
592 }
593
594 FcBool
FcNameUnparseValueList(FcStrBuf * buf,FcValueListPtr v,FcChar8 * escape)595 FcNameUnparseValueList (FcStrBuf *buf,
596 FcValueListPtr v,
597 FcChar8 *escape)
598 {
599 while (v)
600 {
601 if (!FcNameUnparseValue (buf, &v->value, escape))
602 return FcFalse;
603 if ((v = FcValueListNext(v)) != NULL)
604 if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
605 return FcFalse;
606 }
607 return FcTrue;
608 }
609
610 #define FC_ESCAPE_FIXED "\\-:,"
611 #define FC_ESCAPE_VARIABLE "\\=_:,"
612
613 FcChar8 *
FcNameUnparse(FcPattern * pat)614 FcNameUnparse (FcPattern *pat)
615 {
616 return FcNameUnparseEscaped (pat, FcTrue);
617 }
618
619 FcChar8 *
FcNameUnparseEscaped(FcPattern * pat,FcBool escape)620 FcNameUnparseEscaped (FcPattern *pat, FcBool escape)
621 {
622 FcStrBuf buf, buf2;
623 FcChar8 buf_static[8192], buf2_static[256];
624 int i;
625 FcPatternElt *e;
626
627 FcStrBufInit (&buf, buf_static, sizeof (buf_static));
628 FcStrBufInit (&buf2, buf2_static, sizeof (buf2_static));
629 e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
630 if (e)
631 {
632 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
633 goto bail0;
634 }
635 e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
636 if (e)
637 {
638 FcChar8 *p;
639
640 if (!FcNameUnparseString (&buf2, (FcChar8 *) "-", 0))
641 goto bail0;
642 if (!FcNameUnparseValueList (&buf2, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
643 goto bail0;
644 p = FcStrBufDoneStatic (&buf2);
645 FcStrBufDestroy (&buf2);
646 if (strlen ((const char *)p) > 1)
647 if (!FcStrBufString (&buf, p))
648 goto bail0;
649 }
650 for (i = 0; i < NUM_OBJECT_TYPES; i++)
651 {
652 FcObject id = i + 1;
653 const FcObjectType *o;
654 o = &FcObjects[i];
655 if (!strcmp (o->object, FC_FAMILY) ||
656 !strcmp (o->object, FC_SIZE))
657 continue;
658
659 e = FcPatternObjectFindElt (pat, id);
660 if (e)
661 {
662 if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
663 goto bail0;
664 if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
665 goto bail0;
666 if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
667 goto bail0;
668 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
669 (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
670 goto bail0;
671 }
672 }
673 return FcStrBufDone (&buf);
674 bail0:
675 FcStrBufDestroy (&buf);
676 return 0;
677 }
678 #define __fcname__
679 #include "fcaliastail.h"
680 #undef __fcname__
681