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) {
79d91dd368Smrg	case FcTypeUnknown:
80d91dd368Smrg	    return FcTrue;
812c393a42Smrg	case FcTypeDouble:
822c393a42Smrg	case FcTypeInteger:
832c393a42Smrg	    if (type == FcTypeDouble || type == FcTypeInteger)
842c393a42Smrg		return FcTrue;
852c393a42Smrg	    break;
862c393a42Smrg	case FcTypeLangSet:
872c393a42Smrg	    if (type == FcTypeLangSet || type == FcTypeString)
882c393a42Smrg		return FcTrue;
892c393a42Smrg	    break;
9018bd4a06Smrg	case FcTypeRange:
9118bd4a06Smrg	    if (type == FcTypeRange ||
9218bd4a06Smrg		type == FcTypeDouble ||
9318bd4a06Smrg		type == FcTypeInteger)
9418bd4a06Smrg		return FcTrue;
9518bd4a06Smrg	    break;
962c393a42Smrg	default:
97d91dd368Smrg	    if (type == t->type)
982c393a42Smrg		return FcTrue;
992c393a42Smrg	    break;
1002c393a42Smrg	}
1012c393a42Smrg	return FcFalse;
1022c393a42Smrg    }
1032c393a42Smrg    return FcTrue;
1042c393a42Smrg}
1052c393a42Smrg
1062c393a42SmrgFcObject
1072c393a42SmrgFcObjectFromName (const char * name)
1082c393a42Smrg{
1095e61939bSmrg    return FcObjectLookupIdByName (name);
1102c393a42Smrg}
1112c393a42Smrg
112a6844aabSmrgFcObjectSet *
113a6844aabSmrgFcObjectGetSet (void)
114a6844aabSmrg{
115a6844aabSmrg    int		i;
116a6844aabSmrg    FcObjectSet	*os = NULL;
117a6844aabSmrg
118a6844aabSmrg
119a6844aabSmrg    os = FcObjectSetCreate ();
1205e61939bSmrg    for (i = 0; i < NUM_OBJECT_TYPES; i++)
121a6844aabSmrg	FcObjectSetAdd (os, FcObjects[i].object);
122a6844aabSmrg
123a6844aabSmrg    return os;
124a6844aabSmrg}
125a6844aabSmrg
1262c393a42Smrgconst char *
1272c393a42SmrgFcObjectName (FcObject object)
1282c393a42Smrg{
1295e61939bSmrg    const FcObjectType   *o = FcObjectFindById (object);
1302c393a42Smrg
1312c393a42Smrg    if (o)
1322c393a42Smrg	return o->object;
1335e61939bSmrg
1345e61939bSmrg    return FcObjectLookupOtherNameById (object);
1352c393a42Smrg}
1362c393a42Smrg
1372c393a42Smrgstatic const FcConstant _FcBaseConstants[] = {
1382c393a42Smrg    { (FcChar8 *) "thin",	    "weight",   FC_WEIGHT_THIN, },
1392c393a42Smrg    { (FcChar8 *) "extralight",	    "weight",   FC_WEIGHT_EXTRALIGHT, },
1402c393a42Smrg    { (FcChar8 *) "ultralight",	    "weight",   FC_WEIGHT_EXTRALIGHT, },
14118bd4a06Smrg    { (FcChar8 *) "demilight",	    "weight",   FC_WEIGHT_DEMILIGHT, },
14218bd4a06Smrg    { (FcChar8 *) "semilight",	    "weight",   FC_WEIGHT_DEMILIGHT, },
1432c393a42Smrg    { (FcChar8 *) "light",	    "weight",   FC_WEIGHT_LIGHT, },
1442c393a42Smrg    { (FcChar8 *) "book",	    "weight",	FC_WEIGHT_BOOK, },
1452c393a42Smrg    { (FcChar8 *) "regular",	    "weight",   FC_WEIGHT_REGULAR, },
14646bb3e47Smrg    { (FcChar8 *) "normal",	    "weight",	FC_WEIGHT_NORMAL, },
1472c393a42Smrg    { (FcChar8 *) "medium",	    "weight",   FC_WEIGHT_MEDIUM, },
1482c393a42Smrg    { (FcChar8 *) "demibold",	    "weight",   FC_WEIGHT_DEMIBOLD, },
1492c393a42Smrg    { (FcChar8 *) "semibold",	    "weight",   FC_WEIGHT_DEMIBOLD, },
1502c393a42Smrg    { (FcChar8 *) "bold",	    "weight",   FC_WEIGHT_BOLD, },
1512c393a42Smrg    { (FcChar8 *) "extrabold",	    "weight",   FC_WEIGHT_EXTRABOLD, },
1522c393a42Smrg    { (FcChar8 *) "ultrabold",	    "weight",   FC_WEIGHT_EXTRABOLD, },
1532c393a42Smrg    { (FcChar8 *) "black",	    "weight",   FC_WEIGHT_BLACK, },
1542c393a42Smrg    { (FcChar8 *) "heavy",	    "weight",	FC_WEIGHT_HEAVY, },
15546bb3e47Smrg    { (FcChar8 *) "extrablack",     "weight",	FC_WEIGHT_EXTRABLACK, },
15646bb3e47Smrg    { (FcChar8 *) "ultrablack",     "weight",	FC_WEIGHT_ULTRABLACK, },
1572c393a42Smrg
1582c393a42Smrg    { (FcChar8 *) "roman",	    "slant",    FC_SLANT_ROMAN, },
1592c393a42Smrg    { (FcChar8 *) "italic",	    "slant",    FC_SLANT_ITALIC, },
1602c393a42Smrg    { (FcChar8 *) "oblique",	    "slant",    FC_SLANT_OBLIQUE, },
1612c393a42Smrg
1622c393a42Smrg    { (FcChar8 *) "ultracondensed", "width",	FC_WIDTH_ULTRACONDENSED },
1632c393a42Smrg    { (FcChar8 *) "extracondensed", "width",	FC_WIDTH_EXTRACONDENSED },
1642c393a42Smrg    { (FcChar8 *) "condensed",	    "width",	FC_WIDTH_CONDENSED },
1655e61939bSmrg    { (FcChar8 *) "semicondensed",  "width",	FC_WIDTH_SEMICONDENSED },
1662c393a42Smrg    { (FcChar8 *) "normal",	    "width",	FC_WIDTH_NORMAL },
1672c393a42Smrg    { (FcChar8 *) "semiexpanded",   "width",	FC_WIDTH_SEMIEXPANDED },
1682c393a42Smrg    { (FcChar8 *) "expanded",	    "width",	FC_WIDTH_EXPANDED },
1692c393a42Smrg    { (FcChar8 *) "extraexpanded",  "width",	FC_WIDTH_EXTRAEXPANDED },
1702c393a42Smrg    { (FcChar8 *) "ultraexpanded",  "width",	FC_WIDTH_ULTRAEXPANDED },
171898dab68Smrg
1722c393a42Smrg    { (FcChar8 *) "proportional",   "spacing",  FC_PROPORTIONAL, },
1732c393a42Smrg    { (FcChar8 *) "dual",	    "spacing",  FC_DUAL, },
1742c393a42Smrg    { (FcChar8 *) "mono",	    "spacing",  FC_MONO, },
1752c393a42Smrg    { (FcChar8 *) "charcell",	    "spacing",  FC_CHARCELL, },
1762c393a42Smrg
1772c393a42Smrg    { (FcChar8 *) "unknown",	    "rgba",	    FC_RGBA_UNKNOWN },
1782c393a42Smrg    { (FcChar8 *) "rgb",	    "rgba",	    FC_RGBA_RGB, },
1792c393a42Smrg    { (FcChar8 *) "bgr",	    "rgba",	    FC_RGBA_BGR, },
1802c393a42Smrg    { (FcChar8 *) "vrgb",	    "rgba",	    FC_RGBA_VRGB },
1812c393a42Smrg    { (FcChar8 *) "vbgr",	    "rgba",	    FC_RGBA_VBGR },
1822c393a42Smrg    { (FcChar8 *) "none",	    "rgba",	    FC_RGBA_NONE },
1832c393a42Smrg
1842c393a42Smrg    { (FcChar8 *) "hintnone",	    "hintstyle",   FC_HINT_NONE },
1852c393a42Smrg    { (FcChar8 *) "hintslight",	    "hintstyle",   FC_HINT_SLIGHT },
1862c393a42Smrg    { (FcChar8 *) "hintmedium",	    "hintstyle",   FC_HINT_MEDIUM },
1872c393a42Smrg    { (FcChar8 *) "hintfull",	    "hintstyle",   FC_HINT_FULL },
1882c393a42Smrg
1892c393a42Smrg    { (FcChar8 *) "antialias",	    "antialias",    FcTrue },
1902c393a42Smrg    { (FcChar8 *) "hinting",	    "hinting",	    FcTrue },
1912c393a42Smrg    { (FcChar8 *) "verticallayout", "verticallayout",	FcTrue },
1922c393a42Smrg    { (FcChar8 *) "autohint",	    "autohint",	    FcTrue },
193898dab68Smrg    { (FcChar8 *) "globaladvance",  "globaladvance",	FcTrue }, /* deprecated */
1942c393a42Smrg    { (FcChar8 *) "outline",	    "outline",	    FcTrue },
1952c393a42Smrg    { (FcChar8 *) "scalable",	    "scalable",	    FcTrue },
1962c393a42Smrg    { (FcChar8 *) "minspace",	    "minspace",	    FcTrue },
1972c393a42Smrg    { (FcChar8 *) "embolden",	    "embolden",	    FcTrue },
1982c393a42Smrg    { (FcChar8 *) "embeddedbitmap", "embeddedbitmap",	FcTrue },
1992c393a42Smrg    { (FcChar8 *) "decorative",	    "decorative",   FcTrue },
2002c393a42Smrg    { (FcChar8 *) "lcdnone",	    "lcdfilter",    FC_LCD_NONE },
2012c393a42Smrg    { (FcChar8 *) "lcddefault",	    "lcdfilter",    FC_LCD_DEFAULT },
2022c393a42Smrg    { (FcChar8 *) "lcdlight",	    "lcdfilter",    FC_LCD_LIGHT },
2032c393a42Smrg    { (FcChar8 *) "lcdlegacy",	    "lcdfilter",    FC_LCD_LEGACY },
2042c393a42Smrg};
2052c393a42Smrg
2062c393a42Smrg#define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
2072c393a42Smrg
2082c393a42SmrgFcBool
2092c393a42SmrgFcNameRegisterConstants (const FcConstant *consts, int nconsts)
2102c393a42Smrg{
2115e61939bSmrg    /* Deprecated. */
2125e61939bSmrg    return FcFalse;
2132c393a42Smrg}
2142c393a42Smrg
2152c393a42SmrgFcBool
2162c393a42SmrgFcNameUnregisterConstants (const FcConstant *consts, int nconsts)
2172c393a42Smrg{
2185e61939bSmrg    /* Deprecated. */
2192c393a42Smrg    return FcFalse;
2202c393a42Smrg}
2212c393a42Smrg
2222c393a42Smrgconst FcConstant *
223898dab68SmrgFcNameGetConstant (const FcChar8 *string)
2242c393a42Smrg{
2255e61939bSmrg    unsigned int	    i;
2265e61939bSmrg
2275e61939bSmrg    for (i = 0; i < NUM_FC_CONSTANTS; i++)
2285e61939bSmrg	if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name))
2295e61939bSmrg	    return &_FcBaseConstants[i];
2302c393a42Smrg
2312c393a42Smrg    return 0;
2322c393a42Smrg}
2332c393a42Smrg
23446bb3e47Smrgconst FcConstant *
23546bb3e47SmrgFcNameGetConstantFor (const FcChar8 *string, const char *object)
23646bb3e47Smrg{
23746bb3e47Smrg    unsigned int	    i;
23846bb3e47Smrg
23946bb3e47Smrg    for (i = 0; i < NUM_FC_CONSTANTS; i++)
24046bb3e47Smrg	if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name) &&
24146bb3e47Smrg	    !FcStrCmpIgnoreCase ((const FcChar8 *)object, (const FcChar8 *)_FcBaseConstants[i].object))
24246bb3e47Smrg	    return &_FcBaseConstants[i];
24346bb3e47Smrg
24446bb3e47Smrg    return 0;
24546bb3e47Smrg}
24646bb3e47Smrg
2472c393a42SmrgFcBool
248898dab68SmrgFcNameConstant (const FcChar8 *string, int *result)
2492c393a42Smrg{
2502c393a42Smrg    const FcConstant	*c;
2512c393a42Smrg
2522c393a42Smrg    if ((c = FcNameGetConstant(string)))
2532c393a42Smrg    {
2542c393a42Smrg	*result = c->value;
2552c393a42Smrg	return FcTrue;
2562c393a42Smrg    }
2572c393a42Smrg    return FcFalse;
2582c393a42Smrg}
2592c393a42Smrg
2607872e0a1SmrgFcBool
2617872e0a1SmrgFcNameConstantWithObjectCheck (const FcChar8 *string, const char *object, int *result)
2627872e0a1Smrg{
2637872e0a1Smrg    const FcConstant	*c;
2647872e0a1Smrg
26546bb3e47Smrg    if ((c = FcNameGetConstantFor(string, object)))
26646bb3e47Smrg    {
26746bb3e47Smrg	*result = c->value;
26846bb3e47Smrg	return FcTrue;
26946bb3e47Smrg    }
27046bb3e47Smrg    else if ((c = FcNameGetConstant(string)))
2717872e0a1Smrg    {
2727872e0a1Smrg	if (strcmp (c->object, object) != 0)
2737872e0a1Smrg	{
2747872e0a1Smrg	    fprintf (stderr, "Fontconfig error: Unexpected constant name `%s' used for object `%s': should be `%s'\n", string, object, c->object);
2757872e0a1Smrg	    return FcFalse;
2767872e0a1Smrg	}
27746bb3e47Smrg	/* Unlikely to reach out */
2787872e0a1Smrg	*result = c->value;
2797872e0a1Smrg	return FcTrue;
2807872e0a1Smrg    }
2817872e0a1Smrg    return FcFalse;
2827872e0a1Smrg}
2837872e0a1Smrg
2842c393a42SmrgFcBool
2852c393a42SmrgFcNameBool (const FcChar8 *v, FcBool *result)
2862c393a42Smrg{
2872c393a42Smrg    char    c0, c1;
2882c393a42Smrg
2892c393a42Smrg    c0 = *v;
2902c393a42Smrg    c0 = FcToLower (c0);
2912c393a42Smrg    if (c0 == 't' || c0 == 'y' || c0 == '1')
2922c393a42Smrg    {
2932c393a42Smrg	*result = FcTrue;
2942c393a42Smrg	return FcTrue;
2952c393a42Smrg    }
2962c393a42Smrg    if (c0 == 'f' || c0 == 'n' || c0 == '0')
2972c393a42Smrg    {
2982c393a42Smrg	*result = FcFalse;
2992c393a42Smrg	return FcTrue;
3002c393a42Smrg    }
3011887081fSmrg    if (c0 == 'd' || c0 == 'x' || c0 == '2')
3021887081fSmrg    {
3031887081fSmrg	*result = FcDontCare;
3041887081fSmrg	return FcTrue;
3051887081fSmrg    }
3062c393a42Smrg    if (c0 == 'o')
3072c393a42Smrg    {
3082c393a42Smrg	c1 = v[1];
3092c393a42Smrg	c1 = FcToLower (c1);
3102c393a42Smrg	if (c1 == 'n')
3112c393a42Smrg	{
3122c393a42Smrg	    *result = FcTrue;
3132c393a42Smrg	    return FcTrue;
3142c393a42Smrg	}
3152c393a42Smrg	if (c1 == 'f')
3162c393a42Smrg	{
3172c393a42Smrg	    *result = FcFalse;
3182c393a42Smrg	    return FcTrue;
3192c393a42Smrg	}
3201887081fSmrg	if (c1 == 'r')
3211887081fSmrg	{
3221887081fSmrg	    *result = FcDontCare;
3231887081fSmrg	    return FcTrue;
3241887081fSmrg	}
3252c393a42Smrg    }
3262c393a42Smrg    return FcFalse;
3272c393a42Smrg}
3282c393a42Smrg
3292c393a42Smrgstatic FcValue
3307872e0a1SmrgFcNameConvert (FcType type, const char *object, FcChar8 *string)
3312c393a42Smrg{
3322c393a42Smrg    FcValue	v;
333898dab68Smrg    FcMatrix	m;
33418bd4a06Smrg    double	b, e;
33518bd4a06Smrg    char	*p;
3362c393a42Smrg
3372c393a42Smrg    v.type = type;
3385e61939bSmrg    switch ((int) v.type) {
3392c393a42Smrg    case FcTypeInteger:
3407872e0a1Smrg	if (!FcNameConstantWithObjectCheck (string, object, &v.u.i))
3412c393a42Smrg	    v.u.i = atoi ((char *) string);
3422c393a42Smrg	break;
3432c393a42Smrg    case FcTypeString:
3445e61939bSmrg	v.u.s = FcStrdup (string);
3452c393a42Smrg	if (!v.u.s)
3462c393a42Smrg	    v.type = FcTypeVoid;
3472c393a42Smrg	break;
3482c393a42Smrg    case FcTypeBool:
3492c393a42Smrg	if (!FcNameBool (string, &v.u.b))
3502c393a42Smrg	    v.u.b = FcFalse;
3512c393a42Smrg	break;
3522c393a42Smrg    case FcTypeDouble:
3532c393a42Smrg	v.u.d = strtod ((char *) string, 0);
3542c393a42Smrg	break;
3552c393a42Smrg    case FcTypeMatrix:
3565e61939bSmrg	FcMatrixInit (&m);
357898dab68Smrg	sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy);
358898dab68Smrg	v.u.m = FcMatrixCopy (&m);
3592c393a42Smrg	break;
3602c393a42Smrg    case FcTypeCharSet:
3612c393a42Smrg	v.u.c = FcNameParseCharSet (string);
3622c393a42Smrg	if (!v.u.c)
3632c393a42Smrg	    v.type = FcTypeVoid;
3642c393a42Smrg	break;
3652c393a42Smrg    case FcTypeLangSet:
3662c393a42Smrg	v.u.l = FcNameParseLangSet (string);
3672c393a42Smrg	if (!v.u.l)
3682c393a42Smrg	    v.type = FcTypeVoid;
3692c393a42Smrg	break;
37018bd4a06Smrg    case FcTypeRange:
3711887081fSmrg	if (sscanf ((char *) string, "[%lg %lg]", &b, &e) != 2)
37218bd4a06Smrg	{
3731887081fSmrg	    char *sc, *ec;
3741887081fSmrg	    size_t len = strlen ((const char *) string);
3751887081fSmrg	    int si, ei;
3761887081fSmrg
3771887081fSmrg	    sc = malloc (len + 1);
3781887081fSmrg	    ec = malloc (len + 1);
3791887081fSmrg	    if (sc && ec && sscanf ((char *) string, "[%s %[^]]]", sc, ec) == 2)
38018bd4a06Smrg	    {
3817872e0a1Smrg		if (FcNameConstantWithObjectCheck ((const FcChar8 *) sc, object, &si) &&
3827872e0a1Smrg		    FcNameConstantWithObjectCheck ((const FcChar8 *) ec, object, &ei))
3831887081fSmrg		    v.u.r =  FcRangeCreateDouble (si, ei);
3841887081fSmrg		else
3851887081fSmrg		    goto bail1;
38618bd4a06Smrg	    }
3871887081fSmrg	    else
3881887081fSmrg	    {
3891887081fSmrg	    bail1:
3901887081fSmrg		v.type = FcTypeDouble;
3917872e0a1Smrg		if (FcNameConstantWithObjectCheck (string, object, &si))
3921887081fSmrg		{
3931887081fSmrg		    v.u.d = (double) si;
3941887081fSmrg		} else {
3951887081fSmrg		    v.u.d = strtod ((char *) string, &p);
3961887081fSmrg		    if (p != NULL && p[0] != 0)
3971887081fSmrg			v.type = FcTypeVoid;
3981887081fSmrg		}
3991887081fSmrg	    }
4001887081fSmrg	    if (sc)
4011887081fSmrg		free (sc);
4021887081fSmrg	    if (ec)
4031887081fSmrg		free (ec);
40418bd4a06Smrg	}
40518bd4a06Smrg	else
40618bd4a06Smrg	    v.u.r = FcRangeCreateDouble (b, e);
40718bd4a06Smrg	break;
4082c393a42Smrg    default:
4092c393a42Smrg	break;
4102c393a42Smrg    }
4112c393a42Smrg    return v;
4122c393a42Smrg}
4132c393a42Smrg
4142c393a42Smrgstatic const FcChar8 *
4152c393a42SmrgFcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
4162c393a42Smrg{
4172c393a42Smrg    FcChar8    c;
418898dab68Smrg
419d91dd368Smrg    while ((c = *cur))
420d91dd368Smrg    {
421d91dd368Smrg	if (!isspace (c))
422d91dd368Smrg	    break;
423d91dd368Smrg	++cur;
424d91dd368Smrg    }
4252c393a42Smrg    while ((c = *cur))
4262c393a42Smrg    {
4272c393a42Smrg	if (c == '\\')
4282c393a42Smrg	{
4292c393a42Smrg	    ++cur;
4302c393a42Smrg	    if (!(c = *cur))
4312c393a42Smrg		break;
4322c393a42Smrg	}
4332c393a42Smrg	else if (strchr (delim, c))
4342c393a42Smrg	    break;
4352c393a42Smrg	++cur;
4362c393a42Smrg	*save++ = c;
4372c393a42Smrg    }
4382c393a42Smrg    *save = 0;
4392c393a42Smrg    *last = *cur;
4402c393a42Smrg    if (*cur)
4412c393a42Smrg	cur++;
4422c393a42Smrg    return cur;
4432c393a42Smrg}
4442c393a42Smrg
4452c393a42SmrgFcPattern *
4462c393a42SmrgFcNameParse (const FcChar8 *name)
4472c393a42Smrg{
4482c393a42Smrg    FcChar8		*save;
4492c393a42Smrg    FcPattern		*pat;
4502c393a42Smrg    double		d;
4512c393a42Smrg    FcChar8		*e;
4522c393a42Smrg    FcChar8		delim;
4532c393a42Smrg    FcValue		v;
4542c393a42Smrg    const FcObjectType	*t;
4552c393a42Smrg    const FcConstant	*c;
4562c393a42Smrg
4572c393a42Smrg    /* freed below */
4582c393a42Smrg    save = malloc (strlen ((char *) name) + 1);
4592c393a42Smrg    if (!save)
4602c393a42Smrg	goto bail0;
4612c393a42Smrg    pat = FcPatternCreate ();
4622c393a42Smrg    if (!pat)
4632c393a42Smrg	goto bail1;
4642c393a42Smrg
4652c393a42Smrg    for (;;)
4662c393a42Smrg    {
4672c393a42Smrg	name = FcNameFindNext (name, "-,:", save, &delim);
4682c393a42Smrg	if (save[0])
4692c393a42Smrg	{
4707872e0a1Smrg	    if (!FcPatternObjectAddString (pat, FC_FAMILY_OBJECT, save))
4712c393a42Smrg		goto bail2;
4722c393a42Smrg	}
4732c393a42Smrg	if (delim != ',')
4742c393a42Smrg	    break;
4752c393a42Smrg    }
4762c393a42Smrg    if (delim == '-')
4772c393a42Smrg    {
4782c393a42Smrg	for (;;)
4792c393a42Smrg	{
4802c393a42Smrg	    name = FcNameFindNext (name, "-,:", save, &delim);
4812c393a42Smrg	    d = strtod ((char *) save, (char **) &e);
4822c393a42Smrg	    if (e != save)
4832c393a42Smrg	    {
4847872e0a1Smrg		if (!FcPatternObjectAddDouble (pat, FC_SIZE_OBJECT, d))
4852c393a42Smrg		    goto bail2;
4862c393a42Smrg	    }
4872c393a42Smrg	    if (delim != ',')
4882c393a42Smrg		break;
4892c393a42Smrg	}
4902c393a42Smrg    }
4912c393a42Smrg    while (delim == ':')
4922c393a42Smrg    {
4932c393a42Smrg	name = FcNameFindNext (name, "=_:", save, &delim);
4942c393a42Smrg	if (save[0])
4952c393a42Smrg	{
4962c393a42Smrg	    if (delim == '=' || delim == '_')
4972c393a42Smrg	    {
4982c393a42Smrg		t = FcNameGetObjectType ((char *) save);
4992c393a42Smrg		for (;;)
5002c393a42Smrg		{
5012c393a42Smrg		    name = FcNameFindNext (name, ":,", save, &delim);
5022c393a42Smrg		    if (t)
5032c393a42Smrg		    {
5047872e0a1Smrg			v = FcNameConvert (t->type, t->object, save);
5052c393a42Smrg			if (!FcPatternAdd (pat, t->object, v, FcTrue))
5062c393a42Smrg			{
507898dab68Smrg			    FcValueDestroy (v);
5082c393a42Smrg			    goto bail2;
5092c393a42Smrg			}
510898dab68Smrg			FcValueDestroy (v);
5112c393a42Smrg		    }
5122c393a42Smrg		    if (delim != ',')
5132c393a42Smrg			break;
5142c393a42Smrg		}
5152c393a42Smrg	    }
5162c393a42Smrg	    else
5172c393a42Smrg	    {
5182c393a42Smrg		if ((c = FcNameGetConstant (save)))
5192c393a42Smrg		{
5202c393a42Smrg		    t = FcNameGetObjectType ((char *) c->object);
521b2a52337Smrg		    if (t == NULL)
522b2a52337Smrg			goto bail2;
5235e61939bSmrg		    switch ((int) t->type) {
5242c393a42Smrg		    case FcTypeInteger:
5252c393a42Smrg		    case FcTypeDouble:
5262c393a42Smrg			if (!FcPatternAddInteger (pat, c->object, c->value))
5272c393a42Smrg			    goto bail2;
5282c393a42Smrg			break;
5292c393a42Smrg		    case FcTypeBool:
5302c393a42Smrg			if (!FcPatternAddBool (pat, c->object, c->value))
5312c393a42Smrg			    goto bail2;
5322c393a42Smrg			break;
5331887081fSmrg		    case FcTypeRange:
5341887081fSmrg			if (!FcPatternAddInteger (pat, c->object, c->value))
5351887081fSmrg			    goto bail2;
5361887081fSmrg			break;
5372c393a42Smrg		    default:
5382c393a42Smrg			break;
5392c393a42Smrg		    }
5402c393a42Smrg		}
5412c393a42Smrg	    }
5422c393a42Smrg	}
5432c393a42Smrg    }
5442c393a42Smrg
5452c393a42Smrg    free (save);
5462c393a42Smrg    return pat;
5472c393a42Smrg
5482c393a42Smrgbail2:
5492c393a42Smrg    FcPatternDestroy (pat);
5502c393a42Smrgbail1:
5512c393a42Smrg    free (save);
5522c393a42Smrgbail0:
5532c393a42Smrg    return 0;
5542c393a42Smrg}
5552c393a42Smrgstatic FcBool
556898dab68SmrgFcNameUnparseString (FcStrBuf	    *buf,
5572c393a42Smrg		     const FcChar8  *string,
5582c393a42Smrg		     const FcChar8  *escape)
5592c393a42Smrg{
5602c393a42Smrg    FcChar8 c;
5612c393a42Smrg    while ((c = *string++))
5622c393a42Smrg    {
5632c393a42Smrg	if (escape && strchr ((char *) escape, (char) c))
5642c393a42Smrg	{
5652c393a42Smrg	    if (!FcStrBufChar (buf, escape[0]))
5662c393a42Smrg		return FcFalse;
5672c393a42Smrg	}
5682c393a42Smrg	if (!FcStrBufChar (buf, c))
5692c393a42Smrg	    return FcFalse;
5702c393a42Smrg    }
5712c393a42Smrg    return FcTrue;
5722c393a42Smrg}
5732c393a42Smrg
574a6844aabSmrgFcBool
5752c393a42SmrgFcNameUnparseValue (FcStrBuf	*buf,
5762c393a42Smrg		    FcValue	*v0,
5772c393a42Smrg		    FcChar8	*escape)
5782c393a42Smrg{
5792c393a42Smrg    FcChar8	temp[1024];
5802c393a42Smrg    FcValue v = FcValueCanonicalize(v0);
581898dab68Smrg
5822c393a42Smrg    switch (v.type) {
583d91dd368Smrg    case FcTypeUnknown:
5842c393a42Smrg    case FcTypeVoid:
5852c393a42Smrg	return FcTrue;
5862c393a42Smrg    case FcTypeInteger:
5872c393a42Smrg	sprintf ((char *) temp, "%d", v.u.i);
5882c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
5892c393a42Smrg    case FcTypeDouble:
5902c393a42Smrg	sprintf ((char *) temp, "%g", v.u.d);
5912c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
5922c393a42Smrg    case FcTypeString:
5932c393a42Smrg	return FcNameUnparseString (buf, v.u.s, escape);
5942c393a42Smrg    case FcTypeBool:
5951887081fSmrg	return FcNameUnparseString (buf,
5961887081fSmrg				    v.u.b == FcTrue  ? (FcChar8 *) "True" :
5971887081fSmrg				    v.u.b == FcFalse ? (FcChar8 *) "False" :
5981887081fSmrg				                       (FcChar8 *) "DontCare", 0);
5992c393a42Smrg    case FcTypeMatrix:
600898dab68Smrg	sprintf ((char *) temp, "%g %g %g %g",
6012c393a42Smrg		 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
6022c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
6032c393a42Smrg    case FcTypeCharSet:
6042c393a42Smrg	return FcNameUnparseCharSet (buf, v.u.c);
6052c393a42Smrg    case FcTypeLangSet:
6062c393a42Smrg	return FcNameUnparseLangSet (buf, v.u.l);
6072c393a42Smrg    case FcTypeFTFace:
6082c393a42Smrg	return FcTrue;
60918bd4a06Smrg    case FcTypeRange:
6101887081fSmrg	sprintf ((char *) temp, "[%g %g]", v.u.r->begin, v.u.r->end);
61118bd4a06Smrg	return FcNameUnparseString (buf, temp, 0);
6122c393a42Smrg    }
6132c393a42Smrg    return FcFalse;
6142c393a42Smrg}
6152c393a42Smrg
616a6844aabSmrgFcBool
6172c393a42SmrgFcNameUnparseValueList (FcStrBuf	*buf,
6182c393a42Smrg			FcValueListPtr	v,
6192c393a42Smrg			FcChar8		*escape)
6202c393a42Smrg{
6212c393a42Smrg    while (v)
6222c393a42Smrg    {
6232c393a42Smrg	if (!FcNameUnparseValue (buf, &v->value, escape))
6242c393a42Smrg	    return FcFalse;
6252c393a42Smrg	if ((v = FcValueListNext(v)) != NULL)
6262c393a42Smrg	    if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
6272c393a42Smrg		return FcFalse;
6282c393a42Smrg    }
6292c393a42Smrg    return FcTrue;
6302c393a42Smrg}
6312c393a42Smrg
6322c393a42Smrg#define FC_ESCAPE_FIXED    "\\-:,"
6332c393a42Smrg#define FC_ESCAPE_VARIABLE "\\=_:,"
6342c393a42Smrg
6352c393a42SmrgFcChar8 *
6362c393a42SmrgFcNameUnparse (FcPattern *pat)
6372c393a42Smrg{
6382c393a42Smrg    return FcNameUnparseEscaped (pat, FcTrue);
6392c393a42Smrg}
6402c393a42Smrg
6412c393a42SmrgFcChar8 *
6422c393a42SmrgFcNameUnparseEscaped (FcPattern *pat, FcBool escape)
6432c393a42Smrg{
64418bd4a06Smrg    FcStrBuf		    buf, buf2;
64518bd4a06Smrg    FcChar8		    buf_static[8192], buf2_static[256];
6462c393a42Smrg    int			    i;
6472c393a42Smrg    FcPatternElt	    *e;
6482c393a42Smrg
6492c393a42Smrg    FcStrBufInit (&buf, buf_static, sizeof (buf_static));
65018bd4a06Smrg    FcStrBufInit (&buf2, buf2_static, sizeof (buf2_static));
6512c393a42Smrg    e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
6522c393a42Smrg    if (e)
6532c393a42Smrg    {
6542c393a42Smrg        if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
6552c393a42Smrg	    goto bail0;
6562c393a42Smrg    }
6572c393a42Smrg    e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
6582c393a42Smrg    if (e)
6592c393a42Smrg    {
66018bd4a06Smrg	FcChar8 *p;
66118bd4a06Smrg
66218bd4a06Smrg	if (!FcNameUnparseString (&buf2, (FcChar8 *) "-", 0))
6632c393a42Smrg	    goto bail0;
66418bd4a06Smrg	if (!FcNameUnparseValueList (&buf2, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
6652c393a42Smrg	    goto bail0;
66618bd4a06Smrg	p = FcStrBufDoneStatic (&buf2);
66718bd4a06Smrg	FcStrBufDestroy (&buf2);
66818bd4a06Smrg	if (strlen ((const char *)p) > 1)
66918bd4a06Smrg	    if (!FcStrBufString (&buf, p))
67018bd4a06Smrg		goto bail0;
6712c393a42Smrg    }
6725e61939bSmrg    for (i = 0; i < NUM_OBJECT_TYPES; i++)
6732c393a42Smrg    {
6745e61939bSmrg	FcObject id = i + 1;
6755e61939bSmrg	const FcObjectType	    *o;
6765e61939bSmrg	o = &FcObjects[i];
6775e61939bSmrg	if (!strcmp (o->object, FC_FAMILY) ||
6785e61939bSmrg	    !strcmp (o->object, FC_SIZE))
6795e61939bSmrg	    continue;
68046bb3e47Smrg
6815e61939bSmrg	e = FcPatternObjectFindElt (pat, id);
6825e61939bSmrg	if (e)
6832c393a42Smrg	{
6845e61939bSmrg	    if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
6855e61939bSmrg		goto bail0;
6865e61939bSmrg	    if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
6875e61939bSmrg		goto bail0;
6885e61939bSmrg	    if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
6895e61939bSmrg		goto bail0;
6905e61939bSmrg	    if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
6915e61939bSmrg					 (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
6925e61939bSmrg		goto bail0;
6932c393a42Smrg	}
6942c393a42Smrg    }
6952c393a42Smrg    return FcStrBufDone (&buf);
6962c393a42Smrgbail0:
6972c393a42Smrg    FcStrBufDestroy (&buf);
6982c393a42Smrg    return 0;
6992c393a42Smrg}
7002c393a42Smrg#define __fcname__
7012c393a42Smrg#include "fcaliastail.h"
7022c393a42Smrg#undef __fcname__
703