fcname.c revision 7872e0a1
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, },
1462c393a42Smrg    { (FcChar8 *) "medium",	    "weight",   FC_WEIGHT_MEDIUM, },
1472c393a42Smrg    { (FcChar8 *) "demibold",	    "weight",   FC_WEIGHT_DEMIBOLD, },
1482c393a42Smrg    { (FcChar8 *) "semibold",	    "weight",   FC_WEIGHT_DEMIBOLD, },
1492c393a42Smrg    { (FcChar8 *) "bold",	    "weight",   FC_WEIGHT_BOLD, },
1502c393a42Smrg    { (FcChar8 *) "extrabold",	    "weight",   FC_WEIGHT_EXTRABOLD, },
1512c393a42Smrg    { (FcChar8 *) "ultrabold",	    "weight",   FC_WEIGHT_EXTRABOLD, },
1522c393a42Smrg    { (FcChar8 *) "black",	    "weight",   FC_WEIGHT_BLACK, },
1532c393a42Smrg    { (FcChar8 *) "heavy",	    "weight",	FC_WEIGHT_HEAVY, },
1542c393a42Smrg
1552c393a42Smrg    { (FcChar8 *) "roman",	    "slant",    FC_SLANT_ROMAN, },
1562c393a42Smrg    { (FcChar8 *) "italic",	    "slant",    FC_SLANT_ITALIC, },
1572c393a42Smrg    { (FcChar8 *) "oblique",	    "slant",    FC_SLANT_OBLIQUE, },
1582c393a42Smrg
1592c393a42Smrg    { (FcChar8 *) "ultracondensed", "width",	FC_WIDTH_ULTRACONDENSED },
1602c393a42Smrg    { (FcChar8 *) "extracondensed", "width",	FC_WIDTH_EXTRACONDENSED },
1612c393a42Smrg    { (FcChar8 *) "condensed",	    "width",	FC_WIDTH_CONDENSED },
1625e61939bSmrg    { (FcChar8 *) "semicondensed",  "width",	FC_WIDTH_SEMICONDENSED },
1632c393a42Smrg    { (FcChar8 *) "normal",	    "width",	FC_WIDTH_NORMAL },
1642c393a42Smrg    { (FcChar8 *) "semiexpanded",   "width",	FC_WIDTH_SEMIEXPANDED },
1652c393a42Smrg    { (FcChar8 *) "expanded",	    "width",	FC_WIDTH_EXPANDED },
1662c393a42Smrg    { (FcChar8 *) "extraexpanded",  "width",	FC_WIDTH_EXTRAEXPANDED },
1672c393a42Smrg    { (FcChar8 *) "ultraexpanded",  "width",	FC_WIDTH_ULTRAEXPANDED },
168898dab68Smrg
1692c393a42Smrg    { (FcChar8 *) "proportional",   "spacing",  FC_PROPORTIONAL, },
1702c393a42Smrg    { (FcChar8 *) "dual",	    "spacing",  FC_DUAL, },
1712c393a42Smrg    { (FcChar8 *) "mono",	    "spacing",  FC_MONO, },
1722c393a42Smrg    { (FcChar8 *) "charcell",	    "spacing",  FC_CHARCELL, },
1732c393a42Smrg
1742c393a42Smrg    { (FcChar8 *) "unknown",	    "rgba",	    FC_RGBA_UNKNOWN },
1752c393a42Smrg    { (FcChar8 *) "rgb",	    "rgba",	    FC_RGBA_RGB, },
1762c393a42Smrg    { (FcChar8 *) "bgr",	    "rgba",	    FC_RGBA_BGR, },
1772c393a42Smrg    { (FcChar8 *) "vrgb",	    "rgba",	    FC_RGBA_VRGB },
1782c393a42Smrg    { (FcChar8 *) "vbgr",	    "rgba",	    FC_RGBA_VBGR },
1792c393a42Smrg    { (FcChar8 *) "none",	    "rgba",	    FC_RGBA_NONE },
1802c393a42Smrg
1812c393a42Smrg    { (FcChar8 *) "hintnone",	    "hintstyle",   FC_HINT_NONE },
1822c393a42Smrg    { (FcChar8 *) "hintslight",	    "hintstyle",   FC_HINT_SLIGHT },
1832c393a42Smrg    { (FcChar8 *) "hintmedium",	    "hintstyle",   FC_HINT_MEDIUM },
1842c393a42Smrg    { (FcChar8 *) "hintfull",	    "hintstyle",   FC_HINT_FULL },
1852c393a42Smrg
1862c393a42Smrg    { (FcChar8 *) "antialias",	    "antialias",    FcTrue },
1872c393a42Smrg    { (FcChar8 *) "hinting",	    "hinting",	    FcTrue },
1882c393a42Smrg    { (FcChar8 *) "verticallayout", "verticallayout",	FcTrue },
1892c393a42Smrg    { (FcChar8 *) "autohint",	    "autohint",	    FcTrue },
190898dab68Smrg    { (FcChar8 *) "globaladvance",  "globaladvance",	FcTrue }, /* deprecated */
1912c393a42Smrg    { (FcChar8 *) "outline",	    "outline",	    FcTrue },
1922c393a42Smrg    { (FcChar8 *) "scalable",	    "scalable",	    FcTrue },
1932c393a42Smrg    { (FcChar8 *) "minspace",	    "minspace",	    FcTrue },
1942c393a42Smrg    { (FcChar8 *) "embolden",	    "embolden",	    FcTrue },
1952c393a42Smrg    { (FcChar8 *) "embeddedbitmap", "embeddedbitmap",	FcTrue },
1962c393a42Smrg    { (FcChar8 *) "decorative",	    "decorative",   FcTrue },
1972c393a42Smrg    { (FcChar8 *) "lcdnone",	    "lcdfilter",    FC_LCD_NONE },
1982c393a42Smrg    { (FcChar8 *) "lcddefault",	    "lcdfilter",    FC_LCD_DEFAULT },
1992c393a42Smrg    { (FcChar8 *) "lcdlight",	    "lcdfilter",    FC_LCD_LIGHT },
2002c393a42Smrg    { (FcChar8 *) "lcdlegacy",	    "lcdfilter",    FC_LCD_LEGACY },
2012c393a42Smrg};
2022c393a42Smrg
2032c393a42Smrg#define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
2042c393a42Smrg
2052c393a42SmrgFcBool
2062c393a42SmrgFcNameRegisterConstants (const FcConstant *consts, int nconsts)
2072c393a42Smrg{
2085e61939bSmrg    /* Deprecated. */
2095e61939bSmrg    return FcFalse;
2102c393a42Smrg}
2112c393a42Smrg
2122c393a42SmrgFcBool
2132c393a42SmrgFcNameUnregisterConstants (const FcConstant *consts, int nconsts)
2142c393a42Smrg{
2155e61939bSmrg    /* Deprecated. */
2162c393a42Smrg    return FcFalse;
2172c393a42Smrg}
2182c393a42Smrg
2192c393a42Smrgconst FcConstant *
220898dab68SmrgFcNameGetConstant (const FcChar8 *string)
2212c393a42Smrg{
2225e61939bSmrg    unsigned int	    i;
2235e61939bSmrg
2245e61939bSmrg    for (i = 0; i < NUM_FC_CONSTANTS; i++)
2255e61939bSmrg	if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name))
2265e61939bSmrg	    return &_FcBaseConstants[i];
2272c393a42Smrg
2282c393a42Smrg    return 0;
2292c393a42Smrg}
2302c393a42Smrg
2312c393a42SmrgFcBool
232898dab68SmrgFcNameConstant (const FcChar8 *string, int *result)
2332c393a42Smrg{
2342c393a42Smrg    const FcConstant	*c;
2352c393a42Smrg
2362c393a42Smrg    if ((c = FcNameGetConstant(string)))
2372c393a42Smrg    {
2382c393a42Smrg	*result = c->value;
2392c393a42Smrg	return FcTrue;
2402c393a42Smrg    }
2412c393a42Smrg    return FcFalse;
2422c393a42Smrg}
2432c393a42Smrg
2447872e0a1SmrgFcBool
2457872e0a1SmrgFcNameConstantWithObjectCheck (const FcChar8 *string, const char *object, int *result)
2467872e0a1Smrg{
2477872e0a1Smrg    const FcConstant	*c;
2487872e0a1Smrg
2497872e0a1Smrg    if ((c = FcNameGetConstant(string)))
2507872e0a1Smrg    {
2517872e0a1Smrg	if (strcmp (c->object, object) != 0)
2527872e0a1Smrg	{
2537872e0a1Smrg	    fprintf (stderr, "Fontconfig error: Unexpected constant name `%s' used for object `%s': should be `%s'\n", string, object, c->object);
2547872e0a1Smrg	    return FcFalse;
2557872e0a1Smrg	}
2567872e0a1Smrg	*result = c->value;
2577872e0a1Smrg	return FcTrue;
2587872e0a1Smrg    }
2597872e0a1Smrg    return FcFalse;
2607872e0a1Smrg}
2617872e0a1Smrg
2622c393a42SmrgFcBool
2632c393a42SmrgFcNameBool (const FcChar8 *v, FcBool *result)
2642c393a42Smrg{
2652c393a42Smrg    char    c0, c1;
2662c393a42Smrg
2672c393a42Smrg    c0 = *v;
2682c393a42Smrg    c0 = FcToLower (c0);
2692c393a42Smrg    if (c0 == 't' || c0 == 'y' || c0 == '1')
2702c393a42Smrg    {
2712c393a42Smrg	*result = FcTrue;
2722c393a42Smrg	return FcTrue;
2732c393a42Smrg    }
2742c393a42Smrg    if (c0 == 'f' || c0 == 'n' || c0 == '0')
2752c393a42Smrg    {
2762c393a42Smrg	*result = FcFalse;
2772c393a42Smrg	return FcTrue;
2782c393a42Smrg    }
2791887081fSmrg    if (c0 == 'd' || c0 == 'x' || c0 == '2')
2801887081fSmrg    {
2811887081fSmrg	*result = FcDontCare;
2821887081fSmrg	return FcTrue;
2831887081fSmrg    }
2842c393a42Smrg    if (c0 == 'o')
2852c393a42Smrg    {
2862c393a42Smrg	c1 = v[1];
2872c393a42Smrg	c1 = FcToLower (c1);
2882c393a42Smrg	if (c1 == 'n')
2892c393a42Smrg	{
2902c393a42Smrg	    *result = FcTrue;
2912c393a42Smrg	    return FcTrue;
2922c393a42Smrg	}
2932c393a42Smrg	if (c1 == 'f')
2942c393a42Smrg	{
2952c393a42Smrg	    *result = FcFalse;
2962c393a42Smrg	    return FcTrue;
2972c393a42Smrg	}
2981887081fSmrg	if (c1 == 'r')
2991887081fSmrg	{
3001887081fSmrg	    *result = FcDontCare;
3011887081fSmrg	    return FcTrue;
3021887081fSmrg	}
3032c393a42Smrg    }
3042c393a42Smrg    return FcFalse;
3052c393a42Smrg}
3062c393a42Smrg
3072c393a42Smrgstatic FcValue
3087872e0a1SmrgFcNameConvert (FcType type, const char *object, FcChar8 *string)
3092c393a42Smrg{
3102c393a42Smrg    FcValue	v;
311898dab68Smrg    FcMatrix	m;
31218bd4a06Smrg    double	b, e;
31318bd4a06Smrg    char	*p;
3142c393a42Smrg
3152c393a42Smrg    v.type = type;
3165e61939bSmrg    switch ((int) v.type) {
3172c393a42Smrg    case FcTypeInteger:
3187872e0a1Smrg	if (!FcNameConstantWithObjectCheck (string, object, &v.u.i))
3192c393a42Smrg	    v.u.i = atoi ((char *) string);
3202c393a42Smrg	break;
3212c393a42Smrg    case FcTypeString:
3225e61939bSmrg	v.u.s = FcStrdup (string);
3232c393a42Smrg	if (!v.u.s)
3242c393a42Smrg	    v.type = FcTypeVoid;
3252c393a42Smrg	break;
3262c393a42Smrg    case FcTypeBool:
3272c393a42Smrg	if (!FcNameBool (string, &v.u.b))
3282c393a42Smrg	    v.u.b = FcFalse;
3292c393a42Smrg	break;
3302c393a42Smrg    case FcTypeDouble:
3312c393a42Smrg	v.u.d = strtod ((char *) string, 0);
3322c393a42Smrg	break;
3332c393a42Smrg    case FcTypeMatrix:
3345e61939bSmrg	FcMatrixInit (&m);
335898dab68Smrg	sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy);
336898dab68Smrg	v.u.m = FcMatrixCopy (&m);
3372c393a42Smrg	break;
3382c393a42Smrg    case FcTypeCharSet:
3392c393a42Smrg	v.u.c = FcNameParseCharSet (string);
3402c393a42Smrg	if (!v.u.c)
3412c393a42Smrg	    v.type = FcTypeVoid;
3422c393a42Smrg	break;
3432c393a42Smrg    case FcTypeLangSet:
3442c393a42Smrg	v.u.l = FcNameParseLangSet (string);
3452c393a42Smrg	if (!v.u.l)
3462c393a42Smrg	    v.type = FcTypeVoid;
3472c393a42Smrg	break;
34818bd4a06Smrg    case FcTypeRange:
3491887081fSmrg	if (sscanf ((char *) string, "[%lg %lg]", &b, &e) != 2)
35018bd4a06Smrg	{
3511887081fSmrg	    char *sc, *ec;
3521887081fSmrg	    size_t len = strlen ((const char *) string);
3531887081fSmrg	    int si, ei;
3541887081fSmrg
3551887081fSmrg	    sc = malloc (len + 1);
3561887081fSmrg	    ec = malloc (len + 1);
3571887081fSmrg	    if (sc && ec && sscanf ((char *) string, "[%s %[^]]]", sc, ec) == 2)
35818bd4a06Smrg	    {
3597872e0a1Smrg		if (FcNameConstantWithObjectCheck ((const FcChar8 *) sc, object, &si) &&
3607872e0a1Smrg		    FcNameConstantWithObjectCheck ((const FcChar8 *) ec, object, &ei))
3611887081fSmrg		    v.u.r =  FcRangeCreateDouble (si, ei);
3621887081fSmrg		else
3631887081fSmrg		    goto bail1;
36418bd4a06Smrg	    }
3651887081fSmrg	    else
3661887081fSmrg	    {
3671887081fSmrg	    bail1:
3681887081fSmrg		v.type = FcTypeDouble;
3697872e0a1Smrg		if (FcNameConstantWithObjectCheck (string, object, &si))
3701887081fSmrg		{
3711887081fSmrg		    v.u.d = (double) si;
3721887081fSmrg		} else {
3731887081fSmrg		    v.u.d = strtod ((char *) string, &p);
3741887081fSmrg		    if (p != NULL && p[0] != 0)
3751887081fSmrg			v.type = FcTypeVoid;
3761887081fSmrg		}
3771887081fSmrg	    }
3781887081fSmrg	    if (sc)
3791887081fSmrg		free (sc);
3801887081fSmrg	    if (ec)
3811887081fSmrg		free (ec);
38218bd4a06Smrg	}
38318bd4a06Smrg	else
38418bd4a06Smrg	    v.u.r = FcRangeCreateDouble (b, e);
38518bd4a06Smrg	break;
3862c393a42Smrg    default:
3872c393a42Smrg	break;
3882c393a42Smrg    }
3892c393a42Smrg    return v;
3902c393a42Smrg}
3912c393a42Smrg
3922c393a42Smrgstatic const FcChar8 *
3932c393a42SmrgFcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
3942c393a42Smrg{
3952c393a42Smrg    FcChar8    c;
396898dab68Smrg
397d91dd368Smrg    while ((c = *cur))
398d91dd368Smrg    {
399d91dd368Smrg	if (!isspace (c))
400d91dd368Smrg	    break;
401d91dd368Smrg	++cur;
402d91dd368Smrg    }
4032c393a42Smrg    while ((c = *cur))
4042c393a42Smrg    {
4052c393a42Smrg	if (c == '\\')
4062c393a42Smrg	{
4072c393a42Smrg	    ++cur;
4082c393a42Smrg	    if (!(c = *cur))
4092c393a42Smrg		break;
4102c393a42Smrg	}
4112c393a42Smrg	else if (strchr (delim, c))
4122c393a42Smrg	    break;
4132c393a42Smrg	++cur;
4142c393a42Smrg	*save++ = c;
4152c393a42Smrg    }
4162c393a42Smrg    *save = 0;
4172c393a42Smrg    *last = *cur;
4182c393a42Smrg    if (*cur)
4192c393a42Smrg	cur++;
4202c393a42Smrg    return cur;
4212c393a42Smrg}
4222c393a42Smrg
4232c393a42SmrgFcPattern *
4242c393a42SmrgFcNameParse (const FcChar8 *name)
4252c393a42Smrg{
4262c393a42Smrg    FcChar8		*save;
4272c393a42Smrg    FcPattern		*pat;
4282c393a42Smrg    double		d;
4292c393a42Smrg    FcChar8		*e;
4302c393a42Smrg    FcChar8		delim;
4312c393a42Smrg    FcValue		v;
4322c393a42Smrg    const FcObjectType	*t;
4332c393a42Smrg    const FcConstant	*c;
4342c393a42Smrg
4352c393a42Smrg    /* freed below */
4362c393a42Smrg    save = malloc (strlen ((char *) name) + 1);
4372c393a42Smrg    if (!save)
4382c393a42Smrg	goto bail0;
4392c393a42Smrg    pat = FcPatternCreate ();
4402c393a42Smrg    if (!pat)
4412c393a42Smrg	goto bail1;
4422c393a42Smrg
4432c393a42Smrg    for (;;)
4442c393a42Smrg    {
4452c393a42Smrg	name = FcNameFindNext (name, "-,:", save, &delim);
4462c393a42Smrg	if (save[0])
4472c393a42Smrg	{
4487872e0a1Smrg	    if (!FcPatternObjectAddString (pat, FC_FAMILY_OBJECT, save))
4492c393a42Smrg		goto bail2;
4502c393a42Smrg	}
4512c393a42Smrg	if (delim != ',')
4522c393a42Smrg	    break;
4532c393a42Smrg    }
4542c393a42Smrg    if (delim == '-')
4552c393a42Smrg    {
4562c393a42Smrg	for (;;)
4572c393a42Smrg	{
4582c393a42Smrg	    name = FcNameFindNext (name, "-,:", save, &delim);
4592c393a42Smrg	    d = strtod ((char *) save, (char **) &e);
4602c393a42Smrg	    if (e != save)
4612c393a42Smrg	    {
4627872e0a1Smrg		if (!FcPatternObjectAddDouble (pat, FC_SIZE_OBJECT, d))
4632c393a42Smrg		    goto bail2;
4642c393a42Smrg	    }
4652c393a42Smrg	    if (delim != ',')
4662c393a42Smrg		break;
4672c393a42Smrg	}
4682c393a42Smrg    }
4692c393a42Smrg    while (delim == ':')
4702c393a42Smrg    {
4712c393a42Smrg	name = FcNameFindNext (name, "=_:", save, &delim);
4722c393a42Smrg	if (save[0])
4732c393a42Smrg	{
4742c393a42Smrg	    if (delim == '=' || delim == '_')
4752c393a42Smrg	    {
4762c393a42Smrg		t = FcNameGetObjectType ((char *) save);
4772c393a42Smrg		for (;;)
4782c393a42Smrg		{
4792c393a42Smrg		    name = FcNameFindNext (name, ":,", save, &delim);
4802c393a42Smrg		    if (t)
4812c393a42Smrg		    {
4827872e0a1Smrg			v = FcNameConvert (t->type, t->object, save);
4832c393a42Smrg			if (!FcPatternAdd (pat, t->object, v, FcTrue))
4842c393a42Smrg			{
485898dab68Smrg			    FcValueDestroy (v);
4862c393a42Smrg			    goto bail2;
4872c393a42Smrg			}
488898dab68Smrg			FcValueDestroy (v);
4892c393a42Smrg		    }
4902c393a42Smrg		    if (delim != ',')
4912c393a42Smrg			break;
4922c393a42Smrg		}
4932c393a42Smrg	    }
4942c393a42Smrg	    else
4952c393a42Smrg	    {
4962c393a42Smrg		if ((c = FcNameGetConstant (save)))
4972c393a42Smrg		{
4982c393a42Smrg		    t = FcNameGetObjectType ((char *) c->object);
499b2a52337Smrg		    if (t == NULL)
500b2a52337Smrg			goto bail2;
5015e61939bSmrg		    switch ((int) t->type) {
5022c393a42Smrg		    case FcTypeInteger:
5032c393a42Smrg		    case FcTypeDouble:
5042c393a42Smrg			if (!FcPatternAddInteger (pat, c->object, c->value))
5052c393a42Smrg			    goto bail2;
5062c393a42Smrg			break;
5072c393a42Smrg		    case FcTypeBool:
5082c393a42Smrg			if (!FcPatternAddBool (pat, c->object, c->value))
5092c393a42Smrg			    goto bail2;
5102c393a42Smrg			break;
5111887081fSmrg		    case FcTypeRange:
5121887081fSmrg			if (!FcPatternAddInteger (pat, c->object, c->value))
5131887081fSmrg			    goto bail2;
5141887081fSmrg			break;
5152c393a42Smrg		    default:
5162c393a42Smrg			break;
5172c393a42Smrg		    }
5182c393a42Smrg		}
5192c393a42Smrg	    }
5202c393a42Smrg	}
5212c393a42Smrg    }
5222c393a42Smrg
5232c393a42Smrg    free (save);
5242c393a42Smrg    return pat;
5252c393a42Smrg
5262c393a42Smrgbail2:
5272c393a42Smrg    FcPatternDestroy (pat);
5282c393a42Smrgbail1:
5292c393a42Smrg    free (save);
5302c393a42Smrgbail0:
5312c393a42Smrg    return 0;
5322c393a42Smrg}
5332c393a42Smrgstatic FcBool
534898dab68SmrgFcNameUnparseString (FcStrBuf	    *buf,
5352c393a42Smrg		     const FcChar8  *string,
5362c393a42Smrg		     const FcChar8  *escape)
5372c393a42Smrg{
5382c393a42Smrg    FcChar8 c;
5392c393a42Smrg    while ((c = *string++))
5402c393a42Smrg    {
5412c393a42Smrg	if (escape && strchr ((char *) escape, (char) c))
5422c393a42Smrg	{
5432c393a42Smrg	    if (!FcStrBufChar (buf, escape[0]))
5442c393a42Smrg		return FcFalse;
5452c393a42Smrg	}
5462c393a42Smrg	if (!FcStrBufChar (buf, c))
5472c393a42Smrg	    return FcFalse;
5482c393a42Smrg    }
5492c393a42Smrg    return FcTrue;
5502c393a42Smrg}
5512c393a42Smrg
552a6844aabSmrgFcBool
5532c393a42SmrgFcNameUnparseValue (FcStrBuf	*buf,
5542c393a42Smrg		    FcValue	*v0,
5552c393a42Smrg		    FcChar8	*escape)
5562c393a42Smrg{
5572c393a42Smrg    FcChar8	temp[1024];
5582c393a42Smrg    FcValue v = FcValueCanonicalize(v0);
559898dab68Smrg
5602c393a42Smrg    switch (v.type) {
561d91dd368Smrg    case FcTypeUnknown:
5622c393a42Smrg    case FcTypeVoid:
5632c393a42Smrg	return FcTrue;
5642c393a42Smrg    case FcTypeInteger:
5652c393a42Smrg	sprintf ((char *) temp, "%d", v.u.i);
5662c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
5672c393a42Smrg    case FcTypeDouble:
5682c393a42Smrg	sprintf ((char *) temp, "%g", v.u.d);
5692c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
5702c393a42Smrg    case FcTypeString:
5712c393a42Smrg	return FcNameUnparseString (buf, v.u.s, escape);
5722c393a42Smrg    case FcTypeBool:
5731887081fSmrg	return FcNameUnparseString (buf,
5741887081fSmrg				    v.u.b == FcTrue  ? (FcChar8 *) "True" :
5751887081fSmrg				    v.u.b == FcFalse ? (FcChar8 *) "False" :
5761887081fSmrg				                       (FcChar8 *) "DontCare", 0);
5772c393a42Smrg    case FcTypeMatrix:
578898dab68Smrg	sprintf ((char *) temp, "%g %g %g %g",
5792c393a42Smrg		 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
5802c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
5812c393a42Smrg    case FcTypeCharSet:
5822c393a42Smrg	return FcNameUnparseCharSet (buf, v.u.c);
5832c393a42Smrg    case FcTypeLangSet:
5842c393a42Smrg	return FcNameUnparseLangSet (buf, v.u.l);
5852c393a42Smrg    case FcTypeFTFace:
5862c393a42Smrg	return FcTrue;
58718bd4a06Smrg    case FcTypeRange:
5881887081fSmrg	sprintf ((char *) temp, "[%g %g]", v.u.r->begin, v.u.r->end);
58918bd4a06Smrg	return FcNameUnparseString (buf, temp, 0);
5902c393a42Smrg    }
5912c393a42Smrg    return FcFalse;
5922c393a42Smrg}
5932c393a42Smrg
594a6844aabSmrgFcBool
5952c393a42SmrgFcNameUnparseValueList (FcStrBuf	*buf,
5962c393a42Smrg			FcValueListPtr	v,
5972c393a42Smrg			FcChar8		*escape)
5982c393a42Smrg{
5992c393a42Smrg    while (v)
6002c393a42Smrg    {
6012c393a42Smrg	if (!FcNameUnparseValue (buf, &v->value, escape))
6022c393a42Smrg	    return FcFalse;
6032c393a42Smrg	if ((v = FcValueListNext(v)) != NULL)
6042c393a42Smrg	    if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
6052c393a42Smrg		return FcFalse;
6062c393a42Smrg    }
6072c393a42Smrg    return FcTrue;
6082c393a42Smrg}
6092c393a42Smrg
6102c393a42Smrg#define FC_ESCAPE_FIXED    "\\-:,"
6112c393a42Smrg#define FC_ESCAPE_VARIABLE "\\=_:,"
6122c393a42Smrg
6132c393a42SmrgFcChar8 *
6142c393a42SmrgFcNameUnparse (FcPattern *pat)
6152c393a42Smrg{
6162c393a42Smrg    return FcNameUnparseEscaped (pat, FcTrue);
6172c393a42Smrg}
6182c393a42Smrg
6192c393a42SmrgFcChar8 *
6202c393a42SmrgFcNameUnparseEscaped (FcPattern *pat, FcBool escape)
6212c393a42Smrg{
62218bd4a06Smrg    FcStrBuf		    buf, buf2;
62318bd4a06Smrg    FcChar8		    buf_static[8192], buf2_static[256];
6242c393a42Smrg    int			    i;
6252c393a42Smrg    FcPatternElt	    *e;
6262c393a42Smrg
6272c393a42Smrg    FcStrBufInit (&buf, buf_static, sizeof (buf_static));
62818bd4a06Smrg    FcStrBufInit (&buf2, buf2_static, sizeof (buf2_static));
6292c393a42Smrg    e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
6302c393a42Smrg    if (e)
6312c393a42Smrg    {
6322c393a42Smrg        if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
6332c393a42Smrg	    goto bail0;
6342c393a42Smrg    }
6352c393a42Smrg    e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
6362c393a42Smrg    if (e)
6372c393a42Smrg    {
63818bd4a06Smrg	FcChar8 *p;
63918bd4a06Smrg
64018bd4a06Smrg	if (!FcNameUnparseString (&buf2, (FcChar8 *) "-", 0))
6412c393a42Smrg	    goto bail0;
64218bd4a06Smrg	if (!FcNameUnparseValueList (&buf2, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
6432c393a42Smrg	    goto bail0;
64418bd4a06Smrg	p = FcStrBufDoneStatic (&buf2);
64518bd4a06Smrg	FcStrBufDestroy (&buf2);
64618bd4a06Smrg	if (strlen ((const char *)p) > 1)
64718bd4a06Smrg	    if (!FcStrBufString (&buf, p))
64818bd4a06Smrg		goto bail0;
6492c393a42Smrg    }
6505e61939bSmrg    for (i = 0; i < NUM_OBJECT_TYPES; i++)
6512c393a42Smrg    {
6525e61939bSmrg	FcObject id = i + 1;
6535e61939bSmrg	const FcObjectType	    *o;
6545e61939bSmrg	o = &FcObjects[i];
6555e61939bSmrg	if (!strcmp (o->object, FC_FAMILY) ||
6565e61939bSmrg	    !strcmp (o->object, FC_SIZE))
6575e61939bSmrg	    continue;
6585e61939bSmrg
6595e61939bSmrg	e = FcPatternObjectFindElt (pat, id);
6605e61939bSmrg	if (e)
6612c393a42Smrg	{
6625e61939bSmrg	    if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
6635e61939bSmrg		goto bail0;
6645e61939bSmrg	    if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
6655e61939bSmrg		goto bail0;
6665e61939bSmrg	    if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
6675e61939bSmrg		goto bail0;
6685e61939bSmrg	    if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
6695e61939bSmrg					 (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
6705e61939bSmrg		goto bail0;
6712c393a42Smrg	}
6722c393a42Smrg    }
6732c393a42Smrg    return FcStrBufDone (&buf);
6742c393a42Smrgbail0:
6752c393a42Smrg    FcStrBufDestroy (&buf);
6762c393a42Smrg    return 0;
6772c393a42Smrg}
6782c393a42Smrg#define __fcname__
6792c393a42Smrg#include "fcaliastail.h"
6802c393a42Smrg#undef __fcname__
681