fcname.c revision 5e61939b
12c393a42Smrg/*
2a6844aabSmrg * fontconfig/src/fcname.c
32c393a42Smrg *
42c393a42Smrg * Copyright © 2000 Keith Packard
52c393a42Smrg *
62c393a42Smrg * Permission to use, copy, modify, distribute, and sell this software and its
72c393a42Smrg * documentation for any purpose is hereby granted without fee, provided that
82c393a42Smrg * the above copyright notice appear in all copies and that both that
92c393a42Smrg * copyright notice and this permission notice appear in supporting
10898dab68Smrg * documentation, and that the name of the author(s) not be used in
112c393a42Smrg * advertising or publicity pertaining to distribution of the software without
12898dab68Smrg * specific, written prior permission.  The authors make no
132c393a42Smrg * representations about the suitability of this software for any purpose.  It
142c393a42Smrg * is provided "as is" without express or implied warranty.
152c393a42Smrg *
16a6844aabSmrg * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
172c393a42Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18a6844aabSmrg * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
192c393a42Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
202c393a42Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
212c393a42Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
222c393a42Smrg * PERFORMANCE OF THIS SOFTWARE.
232c393a42Smrg */
242c393a42Smrg
252c393a42Smrg#include "fcint.h"
262c393a42Smrg#include <ctype.h>
272c393a42Smrg#include <stdlib.h>
282c393a42Smrg#include <string.h>
292c393a42Smrg#include <stdio.h>
302c393a42Smrg
315e61939bSmrgstatic const FcObjectType FcObjects[] = {
325e61939bSmrg#define FC_OBJECT(NAME, Type, Cmp) { FC_##NAME, Type },
335e61939bSmrg#include "fcobjs.h"
345e61939bSmrg#undef FC_OBJECT
352c393a42Smrg};
362c393a42Smrg
375e61939bSmrg#define NUM_OBJECT_TYPES ((int) (sizeof FcObjects / sizeof FcObjects[0]))
382c393a42Smrg
395e61939bSmrgstatic const FcObjectType *
402c393a42SmrgFcObjectFindById (FcObject object)
412c393a42Smrg{
425e61939bSmrg    if (1 <= object && object <= NUM_OBJECT_TYPES)
435e61939bSmrg	return &FcObjects[object - 1];
445e61939bSmrg    return FcObjectLookupOtherTypeById (object);
452c393a42Smrg}
462c393a42Smrg
472c393a42SmrgFcBool
482c393a42SmrgFcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
492c393a42Smrg{
505e61939bSmrg    /* Deprecated. */
515e61939bSmrg    return FcFalse;
522c393a42Smrg}
532c393a42Smrg
542c393a42SmrgFcBool
552c393a42SmrgFcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
562c393a42Smrg{
575e61939bSmrg    /* Deprecated. */
585e61939bSmrg    return FcFalse;
592c393a42Smrg}
602c393a42Smrg
612c393a42Smrgconst FcObjectType *
622c393a42SmrgFcNameGetObjectType (const char *object)
632c393a42Smrg{
645e61939bSmrg    int id = FcObjectLookupBuiltinIdByName (object);
655e61939bSmrg
665e61939bSmrg    if (!id)
675e61939bSmrg	return FcObjectLookupOtherTypeByName (object);
685e61939bSmrg
695e61939bSmrg    return &FcObjects[id - 1];
702c393a42Smrg}
712c393a42Smrg
722c393a42SmrgFcBool
732c393a42SmrgFcObjectValidType (FcObject object, FcType type)
742c393a42Smrg{
755e61939bSmrg    const FcObjectType    *t = FcObjectFindById (object);
762c393a42Smrg
772c393a42Smrg    if (t) {
785e61939bSmrg	switch ((int) t->type) {
792c393a42Smrg	case FcTypeDouble:
802c393a42Smrg	case FcTypeInteger:
812c393a42Smrg	    if (type == FcTypeDouble || type == FcTypeInteger)
822c393a42Smrg		return FcTrue;
832c393a42Smrg	    break;
842c393a42Smrg	case FcTypeLangSet:
852c393a42Smrg	    if (type == FcTypeLangSet || type == FcTypeString)
862c393a42Smrg		return FcTrue;
872c393a42Smrg	    break;
882c393a42Smrg	default:
895e61939bSmrg	    if (t->type == (unsigned int) -1 || type == t->type)
902c393a42Smrg		return FcTrue;
912c393a42Smrg	    break;
922c393a42Smrg	}
932c393a42Smrg	return FcFalse;
942c393a42Smrg    }
952c393a42Smrg    return FcTrue;
962c393a42Smrg}
972c393a42Smrg
982c393a42SmrgFcObject
992c393a42SmrgFcObjectFromName (const char * name)
1002c393a42Smrg{
1015e61939bSmrg    return FcObjectLookupIdByName (name);
1022c393a42Smrg}
1032c393a42Smrg
104a6844aabSmrgFcObjectSet *
105a6844aabSmrgFcObjectGetSet (void)
106a6844aabSmrg{
107a6844aabSmrg    int		i;
108a6844aabSmrg    FcObjectSet	*os = NULL;
109a6844aabSmrg
110a6844aabSmrg
111a6844aabSmrg    os = FcObjectSetCreate ();
1125e61939bSmrg    for (i = 0; i < NUM_OBJECT_TYPES; i++)
113a6844aabSmrg	FcObjectSetAdd (os, FcObjects[i].object);
114a6844aabSmrg
115a6844aabSmrg    return os;
116a6844aabSmrg}
117a6844aabSmrg
1182c393a42Smrgconst char *
1192c393a42SmrgFcObjectName (FcObject object)
1202c393a42Smrg{
1215e61939bSmrg    const FcObjectType   *o = FcObjectFindById (object);
1222c393a42Smrg
1232c393a42Smrg    if (o)
1242c393a42Smrg	return o->object;
1255e61939bSmrg
1265e61939bSmrg    return FcObjectLookupOtherNameById (object);
1272c393a42Smrg}
1282c393a42Smrg
1292c393a42Smrgstatic const FcConstant _FcBaseConstants[] = {
1302c393a42Smrg    { (FcChar8 *) "thin",	    "weight",   FC_WEIGHT_THIN, },
1312c393a42Smrg    { (FcChar8 *) "extralight",	    "weight",   FC_WEIGHT_EXTRALIGHT, },
1322c393a42Smrg    { (FcChar8 *) "ultralight",	    "weight",   FC_WEIGHT_EXTRALIGHT, },
1332c393a42Smrg    { (FcChar8 *) "light",	    "weight",   FC_WEIGHT_LIGHT, },
1342c393a42Smrg    { (FcChar8 *) "book",	    "weight",	FC_WEIGHT_BOOK, },
1352c393a42Smrg    { (FcChar8 *) "regular",	    "weight",   FC_WEIGHT_REGULAR, },
1362c393a42Smrg    { (FcChar8 *) "medium",	    "weight",   FC_WEIGHT_MEDIUM, },
1372c393a42Smrg    { (FcChar8 *) "demibold",	    "weight",   FC_WEIGHT_DEMIBOLD, },
1382c393a42Smrg    { (FcChar8 *) "semibold",	    "weight",   FC_WEIGHT_DEMIBOLD, },
1392c393a42Smrg    { (FcChar8 *) "bold",	    "weight",   FC_WEIGHT_BOLD, },
1402c393a42Smrg    { (FcChar8 *) "extrabold",	    "weight",   FC_WEIGHT_EXTRABOLD, },
1412c393a42Smrg    { (FcChar8 *) "ultrabold",	    "weight",   FC_WEIGHT_EXTRABOLD, },
1422c393a42Smrg    { (FcChar8 *) "black",	    "weight",   FC_WEIGHT_BLACK, },
1432c393a42Smrg    { (FcChar8 *) "heavy",	    "weight",	FC_WEIGHT_HEAVY, },
1442c393a42Smrg
1452c393a42Smrg    { (FcChar8 *) "roman",	    "slant",    FC_SLANT_ROMAN, },
1462c393a42Smrg    { (FcChar8 *) "italic",	    "slant",    FC_SLANT_ITALIC, },
1472c393a42Smrg    { (FcChar8 *) "oblique",	    "slant",    FC_SLANT_OBLIQUE, },
1482c393a42Smrg
1492c393a42Smrg    { (FcChar8 *) "ultracondensed", "width",	FC_WIDTH_ULTRACONDENSED },
1502c393a42Smrg    { (FcChar8 *) "extracondensed", "width",	FC_WIDTH_EXTRACONDENSED },
1512c393a42Smrg    { (FcChar8 *) "condensed",	    "width",	FC_WIDTH_CONDENSED },
1525e61939bSmrg    { (FcChar8 *) "semicondensed",  "width",	FC_WIDTH_SEMICONDENSED },
1532c393a42Smrg    { (FcChar8 *) "normal",	    "width",	FC_WIDTH_NORMAL },
1542c393a42Smrg    { (FcChar8 *) "semiexpanded",   "width",	FC_WIDTH_SEMIEXPANDED },
1552c393a42Smrg    { (FcChar8 *) "expanded",	    "width",	FC_WIDTH_EXPANDED },
1562c393a42Smrg    { (FcChar8 *) "extraexpanded",  "width",	FC_WIDTH_EXTRAEXPANDED },
1572c393a42Smrg    { (FcChar8 *) "ultraexpanded",  "width",	FC_WIDTH_ULTRAEXPANDED },
158898dab68Smrg
1592c393a42Smrg    { (FcChar8 *) "proportional",   "spacing",  FC_PROPORTIONAL, },
1602c393a42Smrg    { (FcChar8 *) "dual",	    "spacing",  FC_DUAL, },
1612c393a42Smrg    { (FcChar8 *) "mono",	    "spacing",  FC_MONO, },
1622c393a42Smrg    { (FcChar8 *) "charcell",	    "spacing",  FC_CHARCELL, },
1632c393a42Smrg
1642c393a42Smrg    { (FcChar8 *) "unknown",	    "rgba",	    FC_RGBA_UNKNOWN },
1652c393a42Smrg    { (FcChar8 *) "rgb",	    "rgba",	    FC_RGBA_RGB, },
1662c393a42Smrg    { (FcChar8 *) "bgr",	    "rgba",	    FC_RGBA_BGR, },
1672c393a42Smrg    { (FcChar8 *) "vrgb",	    "rgba",	    FC_RGBA_VRGB },
1682c393a42Smrg    { (FcChar8 *) "vbgr",	    "rgba",	    FC_RGBA_VBGR },
1692c393a42Smrg    { (FcChar8 *) "none",	    "rgba",	    FC_RGBA_NONE },
1702c393a42Smrg
1712c393a42Smrg    { (FcChar8 *) "hintnone",	    "hintstyle",   FC_HINT_NONE },
1722c393a42Smrg    { (FcChar8 *) "hintslight",	    "hintstyle",   FC_HINT_SLIGHT },
1732c393a42Smrg    { (FcChar8 *) "hintmedium",	    "hintstyle",   FC_HINT_MEDIUM },
1742c393a42Smrg    { (FcChar8 *) "hintfull",	    "hintstyle",   FC_HINT_FULL },
1752c393a42Smrg
1762c393a42Smrg    { (FcChar8 *) "antialias",	    "antialias",    FcTrue },
1772c393a42Smrg    { (FcChar8 *) "hinting",	    "hinting",	    FcTrue },
1782c393a42Smrg    { (FcChar8 *) "verticallayout", "verticallayout",	FcTrue },
1792c393a42Smrg    { (FcChar8 *) "autohint",	    "autohint",	    FcTrue },
180898dab68Smrg    { (FcChar8 *) "globaladvance",  "globaladvance",	FcTrue }, /* deprecated */
1812c393a42Smrg    { (FcChar8 *) "outline",	    "outline",	    FcTrue },
1822c393a42Smrg    { (FcChar8 *) "scalable",	    "scalable",	    FcTrue },
1832c393a42Smrg    { (FcChar8 *) "minspace",	    "minspace",	    FcTrue },
1842c393a42Smrg    { (FcChar8 *) "embolden",	    "embolden",	    FcTrue },
1852c393a42Smrg    { (FcChar8 *) "embeddedbitmap", "embeddedbitmap",	FcTrue },
1862c393a42Smrg    { (FcChar8 *) "decorative",	    "decorative",   FcTrue },
1872c393a42Smrg    { (FcChar8 *) "lcdnone",	    "lcdfilter",    FC_LCD_NONE },
1882c393a42Smrg    { (FcChar8 *) "lcddefault",	    "lcdfilter",    FC_LCD_DEFAULT },
1892c393a42Smrg    { (FcChar8 *) "lcdlight",	    "lcdfilter",    FC_LCD_LIGHT },
1902c393a42Smrg    { (FcChar8 *) "lcdlegacy",	    "lcdfilter",    FC_LCD_LEGACY },
1912c393a42Smrg};
1922c393a42Smrg
1932c393a42Smrg#define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
1942c393a42Smrg
1952c393a42SmrgFcBool
1962c393a42SmrgFcNameRegisterConstants (const FcConstant *consts, int nconsts)
1972c393a42Smrg{
1985e61939bSmrg    /* Deprecated. */
1995e61939bSmrg    return FcFalse;
2002c393a42Smrg}
2012c393a42Smrg
2022c393a42SmrgFcBool
2032c393a42SmrgFcNameUnregisterConstants (const FcConstant *consts, int nconsts)
2042c393a42Smrg{
2055e61939bSmrg    /* Deprecated. */
2062c393a42Smrg    return FcFalse;
2072c393a42Smrg}
2082c393a42Smrg
2092c393a42Smrgconst FcConstant *
210898dab68SmrgFcNameGetConstant (const FcChar8 *string)
2112c393a42Smrg{
2125e61939bSmrg    unsigned int	    i;
2135e61939bSmrg
2145e61939bSmrg    for (i = 0; i < NUM_FC_CONSTANTS; i++)
2155e61939bSmrg	if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name))
2165e61939bSmrg	    return &_FcBaseConstants[i];
2172c393a42Smrg
2182c393a42Smrg    return 0;
2192c393a42Smrg}
2202c393a42Smrg
2212c393a42SmrgFcBool
222898dab68SmrgFcNameConstant (const FcChar8 *string, int *result)
2232c393a42Smrg{
2242c393a42Smrg    const FcConstant	*c;
2252c393a42Smrg
2262c393a42Smrg    if ((c = FcNameGetConstant(string)))
2272c393a42Smrg    {
2282c393a42Smrg	*result = c->value;
2292c393a42Smrg	return FcTrue;
2302c393a42Smrg    }
2312c393a42Smrg    return FcFalse;
2322c393a42Smrg}
2332c393a42Smrg
2342c393a42SmrgFcBool
2352c393a42SmrgFcNameBool (const FcChar8 *v, FcBool *result)
2362c393a42Smrg{
2372c393a42Smrg    char    c0, c1;
2382c393a42Smrg
2392c393a42Smrg    c0 = *v;
2402c393a42Smrg    c0 = FcToLower (c0);
2412c393a42Smrg    if (c0 == 't' || c0 == 'y' || c0 == '1')
2422c393a42Smrg    {
2432c393a42Smrg	*result = FcTrue;
2442c393a42Smrg	return FcTrue;
2452c393a42Smrg    }
2462c393a42Smrg    if (c0 == 'f' || c0 == 'n' || c0 == '0')
2472c393a42Smrg    {
2482c393a42Smrg	*result = FcFalse;
2492c393a42Smrg	return FcTrue;
2502c393a42Smrg    }
2512c393a42Smrg    if (c0 == 'o')
2522c393a42Smrg    {
2532c393a42Smrg	c1 = v[1];
2542c393a42Smrg	c1 = FcToLower (c1);
2552c393a42Smrg	if (c1 == 'n')
2562c393a42Smrg	{
2572c393a42Smrg	    *result = FcTrue;
2582c393a42Smrg	    return FcTrue;
2592c393a42Smrg	}
2602c393a42Smrg	if (c1 == 'f')
2612c393a42Smrg	{
2622c393a42Smrg	    *result = FcFalse;
2632c393a42Smrg	    return FcTrue;
2642c393a42Smrg	}
2652c393a42Smrg    }
2662c393a42Smrg    return FcFalse;
2672c393a42Smrg}
2682c393a42Smrg
2692c393a42Smrgstatic FcValue
270898dab68SmrgFcNameConvert (FcType type, FcChar8 *string)
2712c393a42Smrg{
2722c393a42Smrg    FcValue	v;
273898dab68Smrg    FcMatrix	m;
2742c393a42Smrg
2752c393a42Smrg    v.type = type;
2765e61939bSmrg    switch ((int) v.type) {
2772c393a42Smrg    case FcTypeInteger:
2782c393a42Smrg	if (!FcNameConstant (string, &v.u.i))
2792c393a42Smrg	    v.u.i = atoi ((char *) string);
2802c393a42Smrg	break;
2812c393a42Smrg    case FcTypeString:
2825e61939bSmrg	v.u.s = FcStrdup (string);
2832c393a42Smrg	if (!v.u.s)
2842c393a42Smrg	    v.type = FcTypeVoid;
2852c393a42Smrg	break;
2862c393a42Smrg    case FcTypeBool:
2872c393a42Smrg	if (!FcNameBool (string, &v.u.b))
2882c393a42Smrg	    v.u.b = FcFalse;
2892c393a42Smrg	break;
2902c393a42Smrg    case FcTypeDouble:
2912c393a42Smrg	v.u.d = strtod ((char *) string, 0);
2922c393a42Smrg	break;
2932c393a42Smrg    case FcTypeMatrix:
2945e61939bSmrg	FcMatrixInit (&m);
295898dab68Smrg	sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy);
296898dab68Smrg	v.u.m = FcMatrixCopy (&m);
2972c393a42Smrg	break;
2982c393a42Smrg    case FcTypeCharSet:
2992c393a42Smrg	v.u.c = FcNameParseCharSet (string);
3002c393a42Smrg	if (!v.u.c)
3012c393a42Smrg	    v.type = FcTypeVoid;
3022c393a42Smrg	break;
3032c393a42Smrg    case FcTypeLangSet:
3042c393a42Smrg	v.u.l = FcNameParseLangSet (string);
3052c393a42Smrg	if (!v.u.l)
3062c393a42Smrg	    v.type = FcTypeVoid;
3072c393a42Smrg	break;
3082c393a42Smrg    default:
3092c393a42Smrg	break;
3102c393a42Smrg    }
3112c393a42Smrg    return v;
3122c393a42Smrg}
3132c393a42Smrg
3142c393a42Smrgstatic const FcChar8 *
3152c393a42SmrgFcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
3162c393a42Smrg{
3172c393a42Smrg    FcChar8    c;
318898dab68Smrg
3192c393a42Smrg    while ((c = *cur))
3202c393a42Smrg    {
3212c393a42Smrg	if (c == '\\')
3222c393a42Smrg	{
3232c393a42Smrg	    ++cur;
3242c393a42Smrg	    if (!(c = *cur))
3252c393a42Smrg		break;
3262c393a42Smrg	}
3272c393a42Smrg	else if (strchr (delim, c))
3282c393a42Smrg	    break;
3292c393a42Smrg	++cur;
3302c393a42Smrg	*save++ = c;
3312c393a42Smrg    }
3322c393a42Smrg    *save = 0;
3332c393a42Smrg    *last = *cur;
3342c393a42Smrg    if (*cur)
3352c393a42Smrg	cur++;
3362c393a42Smrg    return cur;
3372c393a42Smrg}
3382c393a42Smrg
3392c393a42SmrgFcPattern *
3402c393a42SmrgFcNameParse (const FcChar8 *name)
3412c393a42Smrg{
3422c393a42Smrg    FcChar8		*save;
3432c393a42Smrg    FcPattern		*pat;
3442c393a42Smrg    double		d;
3452c393a42Smrg    FcChar8		*e;
3462c393a42Smrg    FcChar8		delim;
3472c393a42Smrg    FcValue		v;
3482c393a42Smrg    const FcObjectType	*t;
3492c393a42Smrg    const FcConstant	*c;
3502c393a42Smrg
3512c393a42Smrg    /* freed below */
3522c393a42Smrg    save = malloc (strlen ((char *) name) + 1);
3532c393a42Smrg    if (!save)
3542c393a42Smrg	goto bail0;
3552c393a42Smrg    pat = FcPatternCreate ();
3562c393a42Smrg    if (!pat)
3572c393a42Smrg	goto bail1;
3582c393a42Smrg
3592c393a42Smrg    for (;;)
3602c393a42Smrg    {
3612c393a42Smrg	name = FcNameFindNext (name, "-,:", save, &delim);
3622c393a42Smrg	if (save[0])
3632c393a42Smrg	{
3642c393a42Smrg	    if (!FcPatternAddString (pat, FC_FAMILY, save))
3652c393a42Smrg		goto bail2;
3662c393a42Smrg	}
3672c393a42Smrg	if (delim != ',')
3682c393a42Smrg	    break;
3692c393a42Smrg    }
3702c393a42Smrg    if (delim == '-')
3712c393a42Smrg    {
3722c393a42Smrg	for (;;)
3732c393a42Smrg	{
3742c393a42Smrg	    name = FcNameFindNext (name, "-,:", save, &delim);
3752c393a42Smrg	    d = strtod ((char *) save, (char **) &e);
3762c393a42Smrg	    if (e != save)
3772c393a42Smrg	    {
3782c393a42Smrg		if (!FcPatternAddDouble (pat, FC_SIZE, d))
3792c393a42Smrg		    goto bail2;
3802c393a42Smrg	    }
3812c393a42Smrg	    if (delim != ',')
3822c393a42Smrg		break;
3832c393a42Smrg	}
3842c393a42Smrg    }
3852c393a42Smrg    while (delim == ':')
3862c393a42Smrg    {
3872c393a42Smrg	name = FcNameFindNext (name, "=_:", save, &delim);
3882c393a42Smrg	if (save[0])
3892c393a42Smrg	{
3902c393a42Smrg	    if (delim == '=' || delim == '_')
3912c393a42Smrg	    {
3922c393a42Smrg		t = FcNameGetObjectType ((char *) save);
3932c393a42Smrg		for (;;)
3942c393a42Smrg		{
3952c393a42Smrg		    name = FcNameFindNext (name, ":,", save, &delim);
3962c393a42Smrg		    if (t)
3972c393a42Smrg		    {
398898dab68Smrg			v = FcNameConvert (t->type, save);
3992c393a42Smrg			if (!FcPatternAdd (pat, t->object, v, FcTrue))
4002c393a42Smrg			{
401898dab68Smrg			    FcValueDestroy (v);
4022c393a42Smrg			    goto bail2;
4032c393a42Smrg			}
404898dab68Smrg			FcValueDestroy (v);
4052c393a42Smrg		    }
4062c393a42Smrg		    if (delim != ',')
4072c393a42Smrg			break;
4082c393a42Smrg		}
4092c393a42Smrg	    }
4102c393a42Smrg	    else
4112c393a42Smrg	    {
4122c393a42Smrg		if ((c = FcNameGetConstant (save)))
4132c393a42Smrg		{
4142c393a42Smrg		    t = FcNameGetObjectType ((char *) c->object);
4155e61939bSmrg		    switch ((int) t->type) {
4162c393a42Smrg		    case FcTypeInteger:
4172c393a42Smrg		    case FcTypeDouble:
4182c393a42Smrg			if (!FcPatternAddInteger (pat, c->object, c->value))
4192c393a42Smrg			    goto bail2;
4202c393a42Smrg			break;
4212c393a42Smrg		    case FcTypeBool:
4222c393a42Smrg			if (!FcPatternAddBool (pat, c->object, c->value))
4232c393a42Smrg			    goto bail2;
4242c393a42Smrg			break;
4252c393a42Smrg		    default:
4262c393a42Smrg			break;
4272c393a42Smrg		    }
4282c393a42Smrg		}
4292c393a42Smrg	    }
4302c393a42Smrg	}
4312c393a42Smrg    }
4322c393a42Smrg
4332c393a42Smrg    free (save);
4342c393a42Smrg    return pat;
4352c393a42Smrg
4362c393a42Smrgbail2:
4372c393a42Smrg    FcPatternDestroy (pat);
4382c393a42Smrgbail1:
4392c393a42Smrg    free (save);
4402c393a42Smrgbail0:
4412c393a42Smrg    return 0;
4422c393a42Smrg}
4432c393a42Smrgstatic FcBool
444898dab68SmrgFcNameUnparseString (FcStrBuf	    *buf,
4452c393a42Smrg		     const FcChar8  *string,
4462c393a42Smrg		     const FcChar8  *escape)
4472c393a42Smrg{
4482c393a42Smrg    FcChar8 c;
4492c393a42Smrg    while ((c = *string++))
4502c393a42Smrg    {
4512c393a42Smrg	if (escape && strchr ((char *) escape, (char) c))
4522c393a42Smrg	{
4532c393a42Smrg	    if (!FcStrBufChar (buf, escape[0]))
4542c393a42Smrg		return FcFalse;
4552c393a42Smrg	}
4562c393a42Smrg	if (!FcStrBufChar (buf, c))
4572c393a42Smrg	    return FcFalse;
4582c393a42Smrg    }
4592c393a42Smrg    return FcTrue;
4602c393a42Smrg}
4612c393a42Smrg
462a6844aabSmrgFcBool
4632c393a42SmrgFcNameUnparseValue (FcStrBuf	*buf,
4642c393a42Smrg		    FcValue	*v0,
4652c393a42Smrg		    FcChar8	*escape)
4662c393a42Smrg{
4672c393a42Smrg    FcChar8	temp[1024];
4682c393a42Smrg    FcValue v = FcValueCanonicalize(v0);
469898dab68Smrg
4702c393a42Smrg    switch (v.type) {
4712c393a42Smrg    case FcTypeVoid:
4722c393a42Smrg	return FcTrue;
4732c393a42Smrg    case FcTypeInteger:
4742c393a42Smrg	sprintf ((char *) temp, "%d", v.u.i);
4752c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
4762c393a42Smrg    case FcTypeDouble:
4772c393a42Smrg	sprintf ((char *) temp, "%g", v.u.d);
4782c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
4792c393a42Smrg    case FcTypeString:
4802c393a42Smrg	return FcNameUnparseString (buf, v.u.s, escape);
4812c393a42Smrg    case FcTypeBool:
4822c393a42Smrg	return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
4832c393a42Smrg    case FcTypeMatrix:
484898dab68Smrg	sprintf ((char *) temp, "%g %g %g %g",
4852c393a42Smrg		 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
4862c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
4872c393a42Smrg    case FcTypeCharSet:
4882c393a42Smrg	return FcNameUnparseCharSet (buf, v.u.c);
4892c393a42Smrg    case FcTypeLangSet:
4902c393a42Smrg	return FcNameUnparseLangSet (buf, v.u.l);
4912c393a42Smrg    case FcTypeFTFace:
4922c393a42Smrg	return FcTrue;
4932c393a42Smrg    }
4942c393a42Smrg    return FcFalse;
4952c393a42Smrg}
4962c393a42Smrg
497a6844aabSmrgFcBool
4982c393a42SmrgFcNameUnparseValueList (FcStrBuf	*buf,
4992c393a42Smrg			FcValueListPtr	v,
5002c393a42Smrg			FcChar8		*escape)
5012c393a42Smrg{
5022c393a42Smrg    while (v)
5032c393a42Smrg    {
5042c393a42Smrg	if (!FcNameUnparseValue (buf, &v->value, escape))
5052c393a42Smrg	    return FcFalse;
5062c393a42Smrg	if ((v = FcValueListNext(v)) != NULL)
5072c393a42Smrg	    if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
5082c393a42Smrg		return FcFalse;
5092c393a42Smrg    }
5102c393a42Smrg    return FcTrue;
5112c393a42Smrg}
5122c393a42Smrg
5132c393a42Smrg#define FC_ESCAPE_FIXED    "\\-:,"
5142c393a42Smrg#define FC_ESCAPE_VARIABLE "\\=_:,"
5152c393a42Smrg
5162c393a42SmrgFcChar8 *
5172c393a42SmrgFcNameUnparse (FcPattern *pat)
5182c393a42Smrg{
5192c393a42Smrg    return FcNameUnparseEscaped (pat, FcTrue);
5202c393a42Smrg}
5212c393a42Smrg
5222c393a42SmrgFcChar8 *
5232c393a42SmrgFcNameUnparseEscaped (FcPattern *pat, FcBool escape)
5242c393a42Smrg{
5252c393a42Smrg    FcStrBuf		    buf;
5262c393a42Smrg    FcChar8		    buf_static[8192];
5272c393a42Smrg    int			    i;
5282c393a42Smrg    FcPatternElt	    *e;
5292c393a42Smrg
5302c393a42Smrg    FcStrBufInit (&buf, buf_static, sizeof (buf_static));
5312c393a42Smrg    e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
5322c393a42Smrg    if (e)
5332c393a42Smrg    {
5342c393a42Smrg        if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
5352c393a42Smrg	    goto bail0;
5362c393a42Smrg    }
5372c393a42Smrg    e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
5382c393a42Smrg    if (e)
5392c393a42Smrg    {
5402c393a42Smrg	if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
5412c393a42Smrg	    goto bail0;
5422c393a42Smrg	if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
5432c393a42Smrg	    goto bail0;
5442c393a42Smrg    }
5455e61939bSmrg    for (i = 0; i < NUM_OBJECT_TYPES; i++)
5462c393a42Smrg    {
5475e61939bSmrg	FcObject id = i + 1;
5485e61939bSmrg	const FcObjectType	    *o;
5495e61939bSmrg	o = &FcObjects[i];
5505e61939bSmrg	if (!strcmp (o->object, FC_FAMILY) ||
5515e61939bSmrg	    !strcmp (o->object, FC_SIZE))
5525e61939bSmrg	    continue;
5535e61939bSmrg
5545e61939bSmrg	e = FcPatternObjectFindElt (pat, id);
5555e61939bSmrg	if (e)
5562c393a42Smrg	{
5575e61939bSmrg	    if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
5585e61939bSmrg		goto bail0;
5595e61939bSmrg	    if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
5605e61939bSmrg		goto bail0;
5615e61939bSmrg	    if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
5625e61939bSmrg		goto bail0;
5635e61939bSmrg	    if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
5645e61939bSmrg					 (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
5655e61939bSmrg		goto bail0;
5662c393a42Smrg	}
5672c393a42Smrg    }
5682c393a42Smrg    return FcStrBufDone (&buf);
5692c393a42Smrgbail0:
5702c393a42Smrg    FcStrBufDestroy (&buf);
5712c393a42Smrg    return 0;
5722c393a42Smrg}
5732c393a42Smrg#define __fcname__
5742c393a42Smrg#include "fcaliastail.h"
5752c393a42Smrg#undef __fcname__
576