fcname.c revision a6844aab
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
102c393a42Smrg * documentation, and that the name of Keith Packard not be used in
112c393a42Smrg * advertising or publicity pertaining to distribution of the software without
122c393a42Smrg * specific, written prior permission.  Keith Packard makes 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
312c393a42Smrg/*
322c393a42Smrg * Please do not change this list, it is used to initialize the object
332c393a42Smrg * list in this order to match the FC_foo_OBJECT constants. Those
342c393a42Smrg * constants are written into cache files.
352c393a42Smrg */
362c393a42Smrg
372c393a42Smrgstatic const FcObjectType _FcBaseObjectTypes[] = {
382c393a42Smrg    { FC_FAMILY,	FcTypeString, },    /* 1 */
392c393a42Smrg    { FC_FAMILYLANG,	FcTypeString, },
402c393a42Smrg    { FC_STYLE,		FcTypeString, },
412c393a42Smrg    { FC_STYLELANG,	FcTypeString, },
422c393a42Smrg    { FC_FULLNAME,	FcTypeString, },
432c393a42Smrg    { FC_FULLNAMELANG,	FcTypeString, },
442c393a42Smrg    { FC_SLANT,		FcTypeInteger, },
452c393a42Smrg    { FC_WEIGHT,	FcTypeInteger, },
462c393a42Smrg    { FC_WIDTH,		FcTypeInteger, },
472c393a42Smrg    { FC_SIZE,		FcTypeDouble, },
482c393a42Smrg    { FC_ASPECT,	FcTypeDouble, },
492c393a42Smrg    { FC_PIXEL_SIZE,	FcTypeDouble, },
502c393a42Smrg    { FC_SPACING,	FcTypeInteger, },
512c393a42Smrg    { FC_FOUNDRY,	FcTypeString, },
522c393a42Smrg    { FC_ANTIALIAS,	FcTypeBool, },
532c393a42Smrg    { FC_HINT_STYLE,    FcTypeInteger, },
542c393a42Smrg    { FC_HINTING,	FcTypeBool, },
552c393a42Smrg    { FC_VERTICAL_LAYOUT,   FcTypeBool, },
562c393a42Smrg    { FC_AUTOHINT,	FcTypeBool, },
572c393a42Smrg    { FC_GLOBAL_ADVANCE,    FcTypeBool, },
582c393a42Smrg    { FC_FILE,		FcTypeString, },
592c393a42Smrg    { FC_INDEX,		FcTypeInteger, },
602c393a42Smrg    { FC_RASTERIZER,	FcTypeString, },
612c393a42Smrg    { FC_OUTLINE,	FcTypeBool, },
622c393a42Smrg    { FC_SCALABLE,	FcTypeBool, },
632c393a42Smrg    { FC_DPI,		FcTypeDouble },
642c393a42Smrg    { FC_RGBA,		FcTypeInteger, },
652c393a42Smrg    { FC_SCALE,		FcTypeDouble, },
662c393a42Smrg    { FC_MINSPACE,	FcTypeBool, },
672c393a42Smrg    { FC_CHAR_WIDTH,	FcTypeInteger },
682c393a42Smrg    { FC_CHAR_HEIGHT,	FcTypeInteger },
692c393a42Smrg    { FC_MATRIX,	FcTypeMatrix },
702c393a42Smrg    { FC_CHARSET,	FcTypeCharSet },
712c393a42Smrg    { FC_LANG,		FcTypeLangSet },
722c393a42Smrg    { FC_FONTVERSION,	FcTypeInteger },
732c393a42Smrg    { FC_CAPABILITY,	FcTypeString },
742c393a42Smrg    { FC_FONTFORMAT,	FcTypeString },
752c393a42Smrg    { FC_EMBOLDEN,	FcTypeBool },
762c393a42Smrg    { FC_EMBEDDED_BITMAP,   FcTypeBool },
772c393a42Smrg    { FC_DECORATIVE,	FcTypeBool },
782c393a42Smrg    { FC_LCD_FILTER,	FcTypeInteger }, /* 41 */
792c393a42Smrg};
802c393a42Smrg
812c393a42Smrg#define NUM_OBJECT_TYPES    (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
822c393a42Smrg
832c393a42Smrgtypedef struct _FcObjectTypeList    FcObjectTypeList;
842c393a42Smrg
852c393a42Smrgstruct _FcObjectTypeList {
862c393a42Smrg    const FcObjectTypeList  *next;
872c393a42Smrg    const FcObjectType	    *types;
882c393a42Smrg    int			    ntypes;
892c393a42Smrg};
902c393a42Smrg
912c393a42Smrgstatic const FcObjectTypeList _FcBaseObjectTypesList = {
922c393a42Smrg    0,
932c393a42Smrg    _FcBaseObjectTypes,
942c393a42Smrg    NUM_OBJECT_TYPES,
952c393a42Smrg};
962c393a42Smrg
972c393a42Smrgstatic const FcObjectTypeList	*_FcObjectTypes = &_FcBaseObjectTypesList;
982c393a42Smrg
992c393a42Smrg#define OBJECT_HASH_SIZE    31
1002c393a42Smrg
1012c393a42Smrgtypedef struct _FcObjectBucket {
1022c393a42Smrg    struct _FcObjectBucket  *next;
1032c393a42Smrg    FcChar32		    hash;
1042c393a42Smrg    FcObject		    id;
1052c393a42Smrg} FcObjectBucket;
1062c393a42Smrg
1072c393a42Smrgstatic FcObjectBucket	*FcObjectBuckets[OBJECT_HASH_SIZE];
1082c393a42Smrg
1092c393a42Smrgstatic FcObjectType	*FcObjects = (FcObjectType *) _FcBaseObjectTypes;
1102c393a42Smrgstatic int		FcObjectsNumber = NUM_OBJECT_TYPES;
1112c393a42Smrgstatic int		FcObjectsSize = 0;
1122c393a42Smrgstatic FcBool		FcObjectsInited;
1132c393a42Smrg
1142c393a42Smrgstatic FcObjectType *
1152c393a42SmrgFcObjectInsert (const char *name, FcType type)
1162c393a42Smrg{
1172c393a42Smrg    FcObjectType    *o;
1182c393a42Smrg    if (FcObjectsNumber >= FcObjectsSize)
1192c393a42Smrg    {
1202c393a42Smrg	int		newsize = FcObjectsNumber * 2;
1212c393a42Smrg	FcObjectType	*newobjects;
1222c393a42Smrg
1232c393a42Smrg	if (FcObjectsSize)
1242c393a42Smrg	    newobjects = realloc (FcObjects, newsize * sizeof (FcObjectType));
1252c393a42Smrg	else
1262c393a42Smrg	{
1272c393a42Smrg	    newobjects = malloc (newsize * sizeof (FcObjectType));
1282c393a42Smrg	    if (newobjects)
1292c393a42Smrg		memcpy (newobjects, FcObjects,
1302c393a42Smrg			FcObjectsNumber * sizeof (FcObjectType));
1312c393a42Smrg	}
1322c393a42Smrg	if (!newobjects)
1332c393a42Smrg	    return NULL;
1342c393a42Smrg	FcObjects = newobjects;
1352c393a42Smrg	FcObjectsSize = newsize;
1362c393a42Smrg    }
1372c393a42Smrg    o = &FcObjects[FcObjectsNumber];
1382c393a42Smrg    o->object = name;
1392c393a42Smrg    o->type = type;
1402c393a42Smrg    ++FcObjectsNumber;
1412c393a42Smrg    return o;
1422c393a42Smrg}
1432c393a42Smrg
1442c393a42Smrgstatic FcObject
1452c393a42SmrgFcObjectId (FcObjectType *o)
1462c393a42Smrg{
1472c393a42Smrg    return o - FcObjects + 1;
1482c393a42Smrg}
1492c393a42Smrg
1502c393a42Smrgstatic FcObjectType *
1512c393a42SmrgFcObjectFindByName (const char *object, FcBool insert)
1522c393a42Smrg{
1532c393a42Smrg    FcChar32	    hash = FcStringHash ((const FcChar8 *) object);
1542c393a42Smrg    FcObjectBucket  **p;
1552c393a42Smrg    FcObjectBucket  *b;
1562c393a42Smrg    FcObjectType    *o;
1572c393a42Smrg
1582c393a42Smrg    if (!FcObjectsInited)
1592c393a42Smrg	FcObjectInit ();
1602c393a42Smrg    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
1612c393a42Smrg    {
1622c393a42Smrg	o = FcObjects + b->id - 1;
1632c393a42Smrg        if (b->hash == hash && !strcmp (object, (o->object)))
1642c393a42Smrg            return o;
1652c393a42Smrg    }
1662c393a42Smrg    if (!insert)
1672c393a42Smrg	return NULL;
1682c393a42Smrg    /*
1692c393a42Smrg     * Hook it into the hash chain
1702c393a42Smrg     */
1712c393a42Smrg    b = malloc (sizeof(FcObjectBucket));
1722c393a42Smrg    if (!b)
1732c393a42Smrg	return NULL;
1742c393a42Smrg    object = (const char *) FcStrCopy ((FcChar8 *) object);
1752c393a42Smrg    if (!object) {
1762c393a42Smrg	free (b);
1772c393a42Smrg	return NULL;
1782c393a42Smrg    }
1792c393a42Smrg    o = FcObjectInsert (object, -1);
1802c393a42Smrg    b->next = NULL;
1812c393a42Smrg    b->hash = hash;
1822c393a42Smrg    b->id = FcObjectId (o);
1832c393a42Smrg    *p = b;
1842c393a42Smrg    return o;
1852c393a42Smrg}
1862c393a42Smrg
1872c393a42Smrgstatic FcObjectType *
1882c393a42SmrgFcObjectFindById (FcObject object)
1892c393a42Smrg{
1902c393a42Smrg    if (1 <= object && object <= FcObjectsNumber)
1912c393a42Smrg	return FcObjects + object - 1;
1922c393a42Smrg    return NULL;
1932c393a42Smrg}
1942c393a42Smrg
1952c393a42Smrgstatic FcBool
1962c393a42SmrgFcObjectHashInsert (const FcObjectType *object, FcBool copy)
1972c393a42Smrg{
1982c393a42Smrg    FcChar32	    hash = FcStringHash ((const FcChar8 *) object->object);
1992c393a42Smrg    FcObjectBucket  **p;
2002c393a42Smrg    FcObjectBucket  *b;
2012c393a42Smrg    FcObjectType    *o;
2022c393a42Smrg
2032c393a42Smrg    if (!FcObjectsInited)
2042c393a42Smrg	FcObjectInit ();
2052c393a42Smrg    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
2062c393a42Smrg    {
2072c393a42Smrg	o = FcObjects + b->id - 1;
2082c393a42Smrg        if (b->hash == hash && !strcmp (object->object, o->object))
2092c393a42Smrg            return FcFalse;
2102c393a42Smrg    }
2112c393a42Smrg    /*
2122c393a42Smrg     * Hook it into the hash chain
2132c393a42Smrg     */
2142c393a42Smrg    b = malloc (sizeof(FcObjectBucket));
2152c393a42Smrg    if (!b)
2162c393a42Smrg	return FcFalse;
2172c393a42Smrg    if (copy)
2182c393a42Smrg    {
2192c393a42Smrg	o = FcObjectInsert (object->object, object->type);
2202c393a42Smrg	if (!o)
2212c393a42Smrg	{
2222c393a42Smrg	    free (b);
2232c393a42Smrg	    return FcFalse;
2242c393a42Smrg	}
2252c393a42Smrg    }
2262c393a42Smrg    else
2272c393a42Smrg	o = (FcObjectType *) object;
2282c393a42Smrg    b->next = NULL;
2292c393a42Smrg    b->hash = hash;
2302c393a42Smrg    b->id = FcObjectId (o);
2312c393a42Smrg    *p = b;
2322c393a42Smrg    return FcTrue;
2332c393a42Smrg}
2342c393a42Smrg
2352c393a42Smrgstatic void
2362c393a42SmrgFcObjectHashRemove (const FcObjectType *object, FcBool cleanobj)
2372c393a42Smrg{
2382c393a42Smrg    FcChar32	    hash = FcStringHash ((const FcChar8 *) object->object);
2392c393a42Smrg    FcObjectBucket  **p;
2402c393a42Smrg    FcObjectBucket  *b;
2412c393a42Smrg    FcObjectType    *o;
2422c393a42Smrg
2432c393a42Smrg    if (!FcObjectsInited)
2442c393a42Smrg	FcObjectInit ();
2452c393a42Smrg    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
2462c393a42Smrg    {
2472c393a42Smrg	o = FcObjects + b->id - 1;
2482c393a42Smrg        if (b->hash == hash && !strcmp (object->object, o->object))
2492c393a42Smrg	{
2502c393a42Smrg	    *p = b->next;
2512c393a42Smrg	    free (b);
2522c393a42Smrg	    if (cleanobj)
2532c393a42Smrg	    {
2542c393a42Smrg		/* Clean up object array */
2552c393a42Smrg		o->object = NULL;
2562c393a42Smrg		o->type = -1;
2572c393a42Smrg		while (FcObjects[FcObjectsNumber-1].object == NULL)
2582c393a42Smrg		    --FcObjectsNumber;
2592c393a42Smrg	    }
2602c393a42Smrg            break;
2612c393a42Smrg	}
2622c393a42Smrg    }
2632c393a42Smrg}
2642c393a42Smrg
2652c393a42SmrgFcBool
2662c393a42SmrgFcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
2672c393a42Smrg{
2682c393a42Smrg    int	i;
2692c393a42Smrg
2702c393a42Smrg    for (i = 0; i < ntypes; i++)
2712c393a42Smrg	if (!FcObjectHashInsert (&types[i], FcTrue))
2722c393a42Smrg	    return FcFalse;
2732c393a42Smrg    return FcTrue;
2742c393a42Smrg}
2752c393a42Smrg
2762c393a42SmrgFcBool
2772c393a42SmrgFcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
2782c393a42Smrg{
2792c393a42Smrg    int	i;
2802c393a42Smrg
2812c393a42Smrg    for (i = 0; i < ntypes; i++)
2822c393a42Smrg	FcObjectHashRemove (&types[i], FcTrue);
2832c393a42Smrg    return FcTrue;
2842c393a42Smrg}
2852c393a42Smrg
2862c393a42Smrgconst FcObjectType *
2872c393a42SmrgFcNameGetObjectType (const char *object)
2882c393a42Smrg{
2892c393a42Smrg    return FcObjectFindByName (object, FcFalse);
2902c393a42Smrg}
2912c393a42Smrg
2922c393a42SmrgFcBool
2932c393a42SmrgFcObjectValidType (FcObject object, FcType type)
2942c393a42Smrg{
2952c393a42Smrg    FcObjectType    *t = FcObjectFindById (object);
2962c393a42Smrg
2972c393a42Smrg    if (t) {
2982c393a42Smrg	switch (t->type) {
2992c393a42Smrg	case -1:
3002c393a42Smrg	    return FcTrue;
3012c393a42Smrg	case FcTypeDouble:
3022c393a42Smrg	case FcTypeInteger:
3032c393a42Smrg	    if (type == FcTypeDouble || type == FcTypeInteger)
3042c393a42Smrg		return FcTrue;
3052c393a42Smrg	    break;
3062c393a42Smrg	case FcTypeLangSet:
3072c393a42Smrg	    if (type == FcTypeLangSet || type == FcTypeString)
3082c393a42Smrg		return FcTrue;
3092c393a42Smrg	    break;
3102c393a42Smrg	default:
3112c393a42Smrg	    if (type == t->type)
3122c393a42Smrg		return FcTrue;
3132c393a42Smrg	    break;
3142c393a42Smrg	}
3152c393a42Smrg	return FcFalse;
3162c393a42Smrg    }
3172c393a42Smrg    return FcTrue;
3182c393a42Smrg}
3192c393a42Smrg
3202c393a42SmrgFcObject
3212c393a42SmrgFcObjectFromName (const char * name)
3222c393a42Smrg{
3232c393a42Smrg    FcObjectType    *o = FcObjectFindByName (name, FcTrue);
3242c393a42Smrg
3252c393a42Smrg    if (o)
3262c393a42Smrg	return FcObjectId (o);
3272c393a42Smrg    return 0;
3282c393a42Smrg}
3292c393a42Smrg
330a6844aabSmrgFcObjectSet *
331a6844aabSmrgFcObjectGetSet (void)
332a6844aabSmrg{
333a6844aabSmrg    int		i;
334a6844aabSmrg    FcObjectSet	*os = NULL;
335a6844aabSmrg
336a6844aabSmrg
337a6844aabSmrg    os = FcObjectSetCreate ();
338a6844aabSmrg    for (i = 0; i < FcObjectsNumber; i++)
339a6844aabSmrg	FcObjectSetAdd (os, FcObjects[i].object);
340a6844aabSmrg
341a6844aabSmrg    return os;
342a6844aabSmrg}
343a6844aabSmrg
3442c393a42SmrgFcBool
3452c393a42SmrgFcObjectInit (void)
3462c393a42Smrg{
3472c393a42Smrg    int	i;
3482c393a42Smrg
3492c393a42Smrg    if (FcObjectsInited)
3502c393a42Smrg	return FcTrue;
3512c393a42Smrg
3522c393a42Smrg    FcObjectsInited = FcTrue;
3532c393a42Smrg    for (i = 0; i < NUM_OBJECT_TYPES; i++)
3542c393a42Smrg	if (!FcObjectHashInsert (&_FcBaseObjectTypes[i], FcFalse))
3552c393a42Smrg	    return FcFalse;
3562c393a42Smrg    return FcTrue;
3572c393a42Smrg}
3582c393a42Smrg
3592c393a42Smrgvoid
3602c393a42SmrgFcObjectFini (void)
3612c393a42Smrg{
3622c393a42Smrg    int		    i;
3632c393a42Smrg    FcObjectBucket  *b, *next;
3642c393a42Smrg
3652c393a42Smrg    for (i = 0; i < OBJECT_HASH_SIZE; i++)
3662c393a42Smrg    {
3672c393a42Smrg	for (b = FcObjectBuckets[i]; b; b = next)
3682c393a42Smrg	{
3692c393a42Smrg	    next = b->next;
3702c393a42Smrg	    free (b);
3712c393a42Smrg	}
3722c393a42Smrg	FcObjectBuckets[i] = 0;
3732c393a42Smrg    }
3742c393a42Smrg    for (i = 0; i < FcObjectsNumber; i++)
3752c393a42Smrg	if (FcObjects[i].type == -1)
3762c393a42Smrg	    free ((void*) FcObjects[i].object);
3772c393a42Smrg    if (FcObjects != _FcBaseObjectTypes)
3782c393a42Smrg	free (FcObjects);
3792c393a42Smrg    FcObjects = (FcObjectType *) _FcBaseObjectTypes;
3802c393a42Smrg    FcObjectsNumber = NUM_OBJECT_TYPES;
3812c393a42Smrg    FcObjectsSize = 0;
3822c393a42Smrg    FcObjectsInited = FcFalse;
3832c393a42Smrg}
3842c393a42Smrg
3852c393a42Smrgconst char *
3862c393a42SmrgFcObjectName (FcObject object)
3872c393a42Smrg{
3882c393a42Smrg    FcObjectType    *o = FcObjectFindById (object);
3892c393a42Smrg
3902c393a42Smrg    if (o)
3912c393a42Smrg	return o->object;
3922c393a42Smrg    return NULL;
3932c393a42Smrg}
3942c393a42Smrg
3952c393a42Smrgstatic const FcConstant _FcBaseConstants[] = {
3962c393a42Smrg    { (FcChar8 *) "thin",	    "weight",   FC_WEIGHT_THIN, },
3972c393a42Smrg    { (FcChar8 *) "extralight",	    "weight",   FC_WEIGHT_EXTRALIGHT, },
3982c393a42Smrg    { (FcChar8 *) "ultralight",	    "weight",   FC_WEIGHT_EXTRALIGHT, },
3992c393a42Smrg    { (FcChar8 *) "light",	    "weight",   FC_WEIGHT_LIGHT, },
4002c393a42Smrg    { (FcChar8 *) "book",	    "weight",	FC_WEIGHT_BOOK, },
4012c393a42Smrg    { (FcChar8 *) "regular",	    "weight",   FC_WEIGHT_REGULAR, },
4022c393a42Smrg    { (FcChar8 *) "medium",	    "weight",   FC_WEIGHT_MEDIUM, },
4032c393a42Smrg    { (FcChar8 *) "demibold",	    "weight",   FC_WEIGHT_DEMIBOLD, },
4042c393a42Smrg    { (FcChar8 *) "semibold",	    "weight",   FC_WEIGHT_DEMIBOLD, },
4052c393a42Smrg    { (FcChar8 *) "bold",	    "weight",   FC_WEIGHT_BOLD, },
4062c393a42Smrg    { (FcChar8 *) "extrabold",	    "weight",   FC_WEIGHT_EXTRABOLD, },
4072c393a42Smrg    { (FcChar8 *) "ultrabold",	    "weight",   FC_WEIGHT_EXTRABOLD, },
4082c393a42Smrg    { (FcChar8 *) "black",	    "weight",   FC_WEIGHT_BLACK, },
4092c393a42Smrg    { (FcChar8 *) "heavy",	    "weight",	FC_WEIGHT_HEAVY, },
4102c393a42Smrg
4112c393a42Smrg    { (FcChar8 *) "roman",	    "slant",    FC_SLANT_ROMAN, },
4122c393a42Smrg    { (FcChar8 *) "italic",	    "slant",    FC_SLANT_ITALIC, },
4132c393a42Smrg    { (FcChar8 *) "oblique",	    "slant",    FC_SLANT_OBLIQUE, },
4142c393a42Smrg
4152c393a42Smrg    { (FcChar8 *) "ultracondensed", "width",	FC_WIDTH_ULTRACONDENSED },
4162c393a42Smrg    { (FcChar8 *) "extracondensed", "width",	FC_WIDTH_EXTRACONDENSED },
4172c393a42Smrg    { (FcChar8 *) "condensed",	    "width",	FC_WIDTH_CONDENSED },
4182c393a42Smrg    { (FcChar8 *) "semicondensed", "width",	FC_WIDTH_SEMICONDENSED },
4192c393a42Smrg    { (FcChar8 *) "normal",	    "width",	FC_WIDTH_NORMAL },
4202c393a42Smrg    { (FcChar8 *) "semiexpanded",   "width",	FC_WIDTH_SEMIEXPANDED },
4212c393a42Smrg    { (FcChar8 *) "expanded",	    "width",	FC_WIDTH_EXPANDED },
4222c393a42Smrg    { (FcChar8 *) "extraexpanded",  "width",	FC_WIDTH_EXTRAEXPANDED },
4232c393a42Smrg    { (FcChar8 *) "ultraexpanded",  "width",	FC_WIDTH_ULTRAEXPANDED },
4242c393a42Smrg
4252c393a42Smrg    { (FcChar8 *) "proportional",   "spacing",  FC_PROPORTIONAL, },
4262c393a42Smrg    { (FcChar8 *) "dual",	    "spacing",  FC_DUAL, },
4272c393a42Smrg    { (FcChar8 *) "mono",	    "spacing",  FC_MONO, },
4282c393a42Smrg    { (FcChar8 *) "charcell",	    "spacing",  FC_CHARCELL, },
4292c393a42Smrg
4302c393a42Smrg    { (FcChar8 *) "unknown",	    "rgba",	    FC_RGBA_UNKNOWN },
4312c393a42Smrg    { (FcChar8 *) "rgb",	    "rgba",	    FC_RGBA_RGB, },
4322c393a42Smrg    { (FcChar8 *) "bgr",	    "rgba",	    FC_RGBA_BGR, },
4332c393a42Smrg    { (FcChar8 *) "vrgb",	    "rgba",	    FC_RGBA_VRGB },
4342c393a42Smrg    { (FcChar8 *) "vbgr",	    "rgba",	    FC_RGBA_VBGR },
4352c393a42Smrg    { (FcChar8 *) "none",	    "rgba",	    FC_RGBA_NONE },
4362c393a42Smrg
4372c393a42Smrg    { (FcChar8 *) "hintnone",	    "hintstyle",   FC_HINT_NONE },
4382c393a42Smrg    { (FcChar8 *) "hintslight",	    "hintstyle",   FC_HINT_SLIGHT },
4392c393a42Smrg    { (FcChar8 *) "hintmedium",	    "hintstyle",   FC_HINT_MEDIUM },
4402c393a42Smrg    { (FcChar8 *) "hintfull",	    "hintstyle",   FC_HINT_FULL },
4412c393a42Smrg
4422c393a42Smrg    { (FcChar8 *) "antialias",	    "antialias",    FcTrue },
4432c393a42Smrg    { (FcChar8 *) "hinting",	    "hinting",	    FcTrue },
4442c393a42Smrg    { (FcChar8 *) "verticallayout", "verticallayout",	FcTrue },
4452c393a42Smrg    { (FcChar8 *) "autohint",	    "autohint",	    FcTrue },
4462c393a42Smrg    { (FcChar8 *) "globaladvance",  "globaladvance",	FcTrue },
4472c393a42Smrg    { (FcChar8 *) "outline",	    "outline",	    FcTrue },
4482c393a42Smrg    { (FcChar8 *) "scalable",	    "scalable",	    FcTrue },
4492c393a42Smrg    { (FcChar8 *) "minspace",	    "minspace",	    FcTrue },
4502c393a42Smrg    { (FcChar8 *) "embolden",	    "embolden",	    FcTrue },
4512c393a42Smrg    { (FcChar8 *) "embeddedbitmap", "embeddedbitmap",	FcTrue },
4522c393a42Smrg    { (FcChar8 *) "decorative",	    "decorative",   FcTrue },
4532c393a42Smrg    { (FcChar8 *) "lcdnone",	    "lcdfilter",    FC_LCD_NONE },
4542c393a42Smrg    { (FcChar8 *) "lcddefault",	    "lcdfilter",    FC_LCD_DEFAULT },
4552c393a42Smrg    { (FcChar8 *) "lcdlight",	    "lcdfilter",    FC_LCD_LIGHT },
4562c393a42Smrg    { (FcChar8 *) "lcdlegacy",	    "lcdfilter",    FC_LCD_LEGACY },
4572c393a42Smrg};
4582c393a42Smrg
4592c393a42Smrg#define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
4602c393a42Smrg
4612c393a42Smrgtypedef struct _FcConstantList FcConstantList;
4622c393a42Smrg
4632c393a42Smrgstruct _FcConstantList {
4642c393a42Smrg    const FcConstantList    *next;
4652c393a42Smrg    const FcConstant	    *consts;
4662c393a42Smrg    int			    nconsts;
4672c393a42Smrg};
4682c393a42Smrg
4692c393a42Smrgstatic const FcConstantList _FcBaseConstantList = {
4702c393a42Smrg    0,
4712c393a42Smrg    _FcBaseConstants,
4722c393a42Smrg    NUM_FC_CONSTANTS
4732c393a42Smrg};
4742c393a42Smrg
4752c393a42Smrgstatic const FcConstantList	*_FcConstants = &_FcBaseConstantList;
4762c393a42Smrg
4772c393a42SmrgFcBool
4782c393a42SmrgFcNameRegisterConstants (const FcConstant *consts, int nconsts)
4792c393a42Smrg{
4802c393a42Smrg    FcConstantList	*l;
4812c393a42Smrg
4822c393a42Smrg    l = (FcConstantList *) malloc (sizeof (FcConstantList));
4832c393a42Smrg    if (!l)
4842c393a42Smrg	return FcFalse;
4852c393a42Smrg    FcMemAlloc (FC_MEM_CONSTANT, sizeof (FcConstantList));
4862c393a42Smrg    l->consts = consts;
4872c393a42Smrg    l->nconsts = nconsts;
4882c393a42Smrg    l->next = _FcConstants;
4892c393a42Smrg    _FcConstants = l;
4902c393a42Smrg    return FcTrue;
4912c393a42Smrg}
4922c393a42Smrg
4932c393a42SmrgFcBool
4942c393a42SmrgFcNameUnregisterConstants (const FcConstant *consts, int nconsts)
4952c393a42Smrg{
4962c393a42Smrg    const FcConstantList	*l, **prev;
4972c393a42Smrg
4982c393a42Smrg    for (prev = &_FcConstants;
4992c393a42Smrg	 (l = *prev);
5002c393a42Smrg	 prev = (const FcConstantList **) &(l->next))
5012c393a42Smrg    {
5022c393a42Smrg	if (l->consts == consts && l->nconsts == nconsts)
5032c393a42Smrg	{
5042c393a42Smrg	    *prev = l->next;
5052c393a42Smrg	    FcMemFree (FC_MEM_CONSTANT, sizeof (FcConstantList));
5062c393a42Smrg	    free ((void *) l);
5072c393a42Smrg	    return FcTrue;
5082c393a42Smrg	}
5092c393a42Smrg    }
5102c393a42Smrg    return FcFalse;
5112c393a42Smrg}
5122c393a42Smrg
5132c393a42Smrgconst FcConstant *
5142c393a42SmrgFcNameGetConstant (FcChar8 *string)
5152c393a42Smrg{
5162c393a42Smrg    const FcConstantList    *l;
5172c393a42Smrg    int			    i;
5182c393a42Smrg
5192c393a42Smrg    for (l = _FcConstants; l; l = l->next)
5202c393a42Smrg    {
5212c393a42Smrg	for (i = 0; i < l->nconsts; i++)
5222c393a42Smrg	    if (!FcStrCmpIgnoreCase (string, l->consts[i].name))
5232c393a42Smrg		return &l->consts[i];
5242c393a42Smrg    }
5252c393a42Smrg    return 0;
5262c393a42Smrg}
5272c393a42Smrg
5282c393a42SmrgFcBool
5292c393a42SmrgFcNameConstant (FcChar8 *string, int *result)
5302c393a42Smrg{
5312c393a42Smrg    const FcConstant	*c;
5322c393a42Smrg
5332c393a42Smrg    if ((c = FcNameGetConstant(string)))
5342c393a42Smrg    {
5352c393a42Smrg	*result = c->value;
5362c393a42Smrg	return FcTrue;
5372c393a42Smrg    }
5382c393a42Smrg    return FcFalse;
5392c393a42Smrg}
5402c393a42Smrg
5412c393a42SmrgFcBool
5422c393a42SmrgFcNameBool (const FcChar8 *v, FcBool *result)
5432c393a42Smrg{
5442c393a42Smrg    char    c0, c1;
5452c393a42Smrg
5462c393a42Smrg    c0 = *v;
5472c393a42Smrg    c0 = FcToLower (c0);
5482c393a42Smrg    if (c0 == 't' || c0 == 'y' || c0 == '1')
5492c393a42Smrg    {
5502c393a42Smrg	*result = FcTrue;
5512c393a42Smrg	return FcTrue;
5522c393a42Smrg    }
5532c393a42Smrg    if (c0 == 'f' || c0 == 'n' || c0 == '0')
5542c393a42Smrg    {
5552c393a42Smrg	*result = FcFalse;
5562c393a42Smrg	return FcTrue;
5572c393a42Smrg    }
5582c393a42Smrg    if (c0 == 'o')
5592c393a42Smrg    {
5602c393a42Smrg	c1 = v[1];
5612c393a42Smrg	c1 = FcToLower (c1);
5622c393a42Smrg	if (c1 == 'n')
5632c393a42Smrg	{
5642c393a42Smrg	    *result = FcTrue;
5652c393a42Smrg	    return FcTrue;
5662c393a42Smrg	}
5672c393a42Smrg	if (c1 == 'f')
5682c393a42Smrg	{
5692c393a42Smrg	    *result = FcFalse;
5702c393a42Smrg	    return FcTrue;
5712c393a42Smrg	}
5722c393a42Smrg    }
5732c393a42Smrg    return FcFalse;
5742c393a42Smrg}
5752c393a42Smrg
5762c393a42Smrgstatic FcValue
5772c393a42SmrgFcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
5782c393a42Smrg{
5792c393a42Smrg    FcValue	v;
5802c393a42Smrg
5812c393a42Smrg    v.type = type;
5822c393a42Smrg    switch (v.type) {
5832c393a42Smrg    case FcTypeInteger:
5842c393a42Smrg	if (!FcNameConstant (string, &v.u.i))
5852c393a42Smrg	    v.u.i = atoi ((char *) string);
5862c393a42Smrg	break;
5872c393a42Smrg    case FcTypeString:
5882c393a42Smrg	v.u.s = FcStrStaticName(string);
5892c393a42Smrg	if (!v.u.s)
5902c393a42Smrg	    v.type = FcTypeVoid;
5912c393a42Smrg	break;
5922c393a42Smrg    case FcTypeBool:
5932c393a42Smrg	if (!FcNameBool (string, &v.u.b))
5942c393a42Smrg	    v.u.b = FcFalse;
5952c393a42Smrg	break;
5962c393a42Smrg    case FcTypeDouble:
5972c393a42Smrg	v.u.d = strtod ((char *) string, 0);
5982c393a42Smrg	break;
5992c393a42Smrg    case FcTypeMatrix:
6002c393a42Smrg	v.u.m = m;
6012c393a42Smrg	sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
6022c393a42Smrg	break;
6032c393a42Smrg    case FcTypeCharSet:
6042c393a42Smrg	v.u.c = FcNameParseCharSet (string);
6052c393a42Smrg	if (!v.u.c)
6062c393a42Smrg	    v.type = FcTypeVoid;
6072c393a42Smrg	break;
6082c393a42Smrg    case FcTypeLangSet:
6092c393a42Smrg	v.u.l = FcNameParseLangSet (string);
6102c393a42Smrg	if (!v.u.l)
6112c393a42Smrg	    v.type = FcTypeVoid;
6122c393a42Smrg	break;
6132c393a42Smrg    default:
6142c393a42Smrg	break;
6152c393a42Smrg    }
6162c393a42Smrg    return v;
6172c393a42Smrg}
6182c393a42Smrg
6192c393a42Smrgstatic const FcChar8 *
6202c393a42SmrgFcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
6212c393a42Smrg{
6222c393a42Smrg    FcChar8    c;
6232c393a42Smrg
6242c393a42Smrg    while ((c = *cur))
6252c393a42Smrg    {
6262c393a42Smrg	if (c == '\\')
6272c393a42Smrg	{
6282c393a42Smrg	    ++cur;
6292c393a42Smrg	    if (!(c = *cur))
6302c393a42Smrg		break;
6312c393a42Smrg	}
6322c393a42Smrg	else if (strchr (delim, c))
6332c393a42Smrg	    break;
6342c393a42Smrg	++cur;
6352c393a42Smrg	*save++ = c;
6362c393a42Smrg    }
6372c393a42Smrg    *save = 0;
6382c393a42Smrg    *last = *cur;
6392c393a42Smrg    if (*cur)
6402c393a42Smrg	cur++;
6412c393a42Smrg    return cur;
6422c393a42Smrg}
6432c393a42Smrg
6442c393a42SmrgFcPattern *
6452c393a42SmrgFcNameParse (const FcChar8 *name)
6462c393a42Smrg{
6472c393a42Smrg    FcChar8		*save;
6482c393a42Smrg    FcPattern		*pat;
6492c393a42Smrg    double		d;
6502c393a42Smrg    FcChar8		*e;
6512c393a42Smrg    FcChar8		delim;
6522c393a42Smrg    FcValue		v;
6532c393a42Smrg    FcMatrix		m;
6542c393a42Smrg    const FcObjectType	*t;
6552c393a42Smrg    const FcConstant	*c;
6562c393a42Smrg
6572c393a42Smrg    /* freed below */
6582c393a42Smrg    save = malloc (strlen ((char *) name) + 1);
6592c393a42Smrg    if (!save)
6602c393a42Smrg	goto bail0;
6612c393a42Smrg    pat = FcPatternCreate ();
6622c393a42Smrg    if (!pat)
6632c393a42Smrg	goto bail1;
6642c393a42Smrg
6652c393a42Smrg    for (;;)
6662c393a42Smrg    {
6672c393a42Smrg	name = FcNameFindNext (name, "-,:", save, &delim);
6682c393a42Smrg	if (save[0])
6692c393a42Smrg	{
6702c393a42Smrg	    if (!FcPatternAddString (pat, FC_FAMILY, save))
6712c393a42Smrg		goto bail2;
6722c393a42Smrg	}
6732c393a42Smrg	if (delim != ',')
6742c393a42Smrg	    break;
6752c393a42Smrg    }
6762c393a42Smrg    if (delim == '-')
6772c393a42Smrg    {
6782c393a42Smrg	for (;;)
6792c393a42Smrg	{
6802c393a42Smrg	    name = FcNameFindNext (name, "-,:", save, &delim);
6812c393a42Smrg	    d = strtod ((char *) save, (char **) &e);
6822c393a42Smrg	    if (e != save)
6832c393a42Smrg	    {
6842c393a42Smrg		if (!FcPatternAddDouble (pat, FC_SIZE, d))
6852c393a42Smrg		    goto bail2;
6862c393a42Smrg	    }
6872c393a42Smrg	    if (delim != ',')
6882c393a42Smrg		break;
6892c393a42Smrg	}
6902c393a42Smrg    }
6912c393a42Smrg    while (delim == ':')
6922c393a42Smrg    {
6932c393a42Smrg	name = FcNameFindNext (name, "=_:", save, &delim);
6942c393a42Smrg	if (save[0])
6952c393a42Smrg	{
6962c393a42Smrg	    if (delim == '=' || delim == '_')
6972c393a42Smrg	    {
6982c393a42Smrg		t = FcNameGetObjectType ((char *) save);
6992c393a42Smrg		for (;;)
7002c393a42Smrg		{
7012c393a42Smrg		    name = FcNameFindNext (name, ":,", save, &delim);
7022c393a42Smrg		    if (t)
7032c393a42Smrg		    {
7042c393a42Smrg			v = FcNameConvert (t->type, save, &m);
7052c393a42Smrg			if (!FcPatternAdd (pat, t->object, v, FcTrue))
7062c393a42Smrg			{
7072c393a42Smrg			    switch (v.type) {
7082c393a42Smrg			    case FcTypeCharSet:
7092c393a42Smrg				FcCharSetDestroy ((FcCharSet *) v.u.c);
7102c393a42Smrg				break;
7112c393a42Smrg			    case FcTypeLangSet:
7122c393a42Smrg				FcLangSetDestroy ((FcLangSet *) v.u.l);
7132c393a42Smrg				break;
7142c393a42Smrg			    default:
7152c393a42Smrg				break;
7162c393a42Smrg			    }
7172c393a42Smrg			    goto bail2;
7182c393a42Smrg			}
7192c393a42Smrg			switch (v.type) {
7202c393a42Smrg			case FcTypeCharSet:
7212c393a42Smrg			    FcCharSetDestroy ((FcCharSet *) v.u.c);
7222c393a42Smrg			    break;
7232c393a42Smrg			case FcTypeLangSet:
7242c393a42Smrg			    FcLangSetDestroy ((FcLangSet *) v.u.l);
7252c393a42Smrg			    break;
7262c393a42Smrg			default:
7272c393a42Smrg			    break;
7282c393a42Smrg			}
7292c393a42Smrg		    }
7302c393a42Smrg		    if (delim != ',')
7312c393a42Smrg			break;
7322c393a42Smrg		}
7332c393a42Smrg	    }
7342c393a42Smrg	    else
7352c393a42Smrg	    {
7362c393a42Smrg		if ((c = FcNameGetConstant (save)))
7372c393a42Smrg		{
7382c393a42Smrg		    t = FcNameGetObjectType ((char *) c->object);
7392c393a42Smrg		    switch (t->type) {
7402c393a42Smrg		    case FcTypeInteger:
7412c393a42Smrg		    case FcTypeDouble:
7422c393a42Smrg			if (!FcPatternAddInteger (pat, c->object, c->value))
7432c393a42Smrg			    goto bail2;
7442c393a42Smrg			break;
7452c393a42Smrg		    case FcTypeBool:
7462c393a42Smrg			if (!FcPatternAddBool (pat, c->object, c->value))
7472c393a42Smrg			    goto bail2;
7482c393a42Smrg			break;
7492c393a42Smrg		    default:
7502c393a42Smrg			break;
7512c393a42Smrg		    }
7522c393a42Smrg		}
7532c393a42Smrg	    }
7542c393a42Smrg	}
7552c393a42Smrg    }
7562c393a42Smrg
7572c393a42Smrg    free (save);
7582c393a42Smrg    return pat;
7592c393a42Smrg
7602c393a42Smrgbail2:
7612c393a42Smrg    FcPatternDestroy (pat);
7622c393a42Smrgbail1:
7632c393a42Smrg    free (save);
7642c393a42Smrgbail0:
7652c393a42Smrg    return 0;
7662c393a42Smrg}
7672c393a42Smrgstatic FcBool
7682c393a42SmrgFcNameUnparseString (FcStrBuf	    *buf,
7692c393a42Smrg		     const FcChar8  *string,
7702c393a42Smrg		     const FcChar8  *escape)
7712c393a42Smrg{
7722c393a42Smrg    FcChar8 c;
7732c393a42Smrg    while ((c = *string++))
7742c393a42Smrg    {
7752c393a42Smrg	if (escape && strchr ((char *) escape, (char) c))
7762c393a42Smrg	{
7772c393a42Smrg	    if (!FcStrBufChar (buf, escape[0]))
7782c393a42Smrg		return FcFalse;
7792c393a42Smrg	}
7802c393a42Smrg	if (!FcStrBufChar (buf, c))
7812c393a42Smrg	    return FcFalse;
7822c393a42Smrg    }
7832c393a42Smrg    return FcTrue;
7842c393a42Smrg}
7852c393a42Smrg
786a6844aabSmrgFcBool
7872c393a42SmrgFcNameUnparseValue (FcStrBuf	*buf,
7882c393a42Smrg		    FcValue	*v0,
7892c393a42Smrg		    FcChar8	*escape)
7902c393a42Smrg{
7912c393a42Smrg    FcChar8	temp[1024];
7922c393a42Smrg    FcValue v = FcValueCanonicalize(v0);
7932c393a42Smrg
7942c393a42Smrg    switch (v.type) {
7952c393a42Smrg    case FcTypeVoid:
7962c393a42Smrg	return FcTrue;
7972c393a42Smrg    case FcTypeInteger:
7982c393a42Smrg	sprintf ((char *) temp, "%d", v.u.i);
7992c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
8002c393a42Smrg    case FcTypeDouble:
8012c393a42Smrg	sprintf ((char *) temp, "%g", v.u.d);
8022c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
8032c393a42Smrg    case FcTypeString:
8042c393a42Smrg	return FcNameUnparseString (buf, v.u.s, escape);
8052c393a42Smrg    case FcTypeBool:
8062c393a42Smrg	return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
8072c393a42Smrg    case FcTypeMatrix:
8082c393a42Smrg	sprintf ((char *) temp, "%g %g %g %g",
8092c393a42Smrg		 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
8102c393a42Smrg	return FcNameUnparseString (buf, temp, 0);
8112c393a42Smrg    case FcTypeCharSet:
8122c393a42Smrg	return FcNameUnparseCharSet (buf, v.u.c);
8132c393a42Smrg    case FcTypeLangSet:
8142c393a42Smrg	return FcNameUnparseLangSet (buf, v.u.l);
8152c393a42Smrg    case FcTypeFTFace:
8162c393a42Smrg	return FcTrue;
8172c393a42Smrg    }
8182c393a42Smrg    return FcFalse;
8192c393a42Smrg}
8202c393a42Smrg
821a6844aabSmrgFcBool
8222c393a42SmrgFcNameUnparseValueList (FcStrBuf	*buf,
8232c393a42Smrg			FcValueListPtr	v,
8242c393a42Smrg			FcChar8		*escape)
8252c393a42Smrg{
8262c393a42Smrg    while (v)
8272c393a42Smrg    {
8282c393a42Smrg	if (!FcNameUnparseValue (buf, &v->value, escape))
8292c393a42Smrg	    return FcFalse;
8302c393a42Smrg	if ((v = FcValueListNext(v)) != NULL)
8312c393a42Smrg	    if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
8322c393a42Smrg		return FcFalse;
8332c393a42Smrg    }
8342c393a42Smrg    return FcTrue;
8352c393a42Smrg}
8362c393a42Smrg
8372c393a42Smrg#define FC_ESCAPE_FIXED    "\\-:,"
8382c393a42Smrg#define FC_ESCAPE_VARIABLE "\\=_:,"
8392c393a42Smrg
8402c393a42SmrgFcChar8 *
8412c393a42SmrgFcNameUnparse (FcPattern *pat)
8422c393a42Smrg{
8432c393a42Smrg    return FcNameUnparseEscaped (pat, FcTrue);
8442c393a42Smrg}
8452c393a42Smrg
8462c393a42SmrgFcChar8 *
8472c393a42SmrgFcNameUnparseEscaped (FcPattern *pat, FcBool escape)
8482c393a42Smrg{
8492c393a42Smrg    FcStrBuf		    buf;
8502c393a42Smrg    FcChar8		    buf_static[8192];
8512c393a42Smrg    int			    i;
8522c393a42Smrg    FcPatternElt	    *e;
8532c393a42Smrg    const FcObjectTypeList  *l;
8542c393a42Smrg    const FcObjectType	    *o;
8552c393a42Smrg
8562c393a42Smrg    FcStrBufInit (&buf, buf_static, sizeof (buf_static));
8572c393a42Smrg    e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
8582c393a42Smrg    if (e)
8592c393a42Smrg    {
8602c393a42Smrg        if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
8612c393a42Smrg	    goto bail0;
8622c393a42Smrg    }
8632c393a42Smrg    e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
8642c393a42Smrg    if (e)
8652c393a42Smrg    {
8662c393a42Smrg	if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
8672c393a42Smrg	    goto bail0;
8682c393a42Smrg	if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
8692c393a42Smrg	    goto bail0;
8702c393a42Smrg    }
8712c393a42Smrg    for (l = _FcObjectTypes; l; l = l->next)
8722c393a42Smrg    {
8732c393a42Smrg	for (i = 0; i < l->ntypes; i++)
8742c393a42Smrg	{
8752c393a42Smrg	    o = &l->types[i];
8762c393a42Smrg	    if (!strcmp (o->object, FC_FAMILY) ||
8772c393a42Smrg		!strcmp (o->object, FC_SIZE) ||
8782c393a42Smrg		!strcmp (o->object, FC_FILE))
8792c393a42Smrg		continue;
8802c393a42Smrg
8812c393a42Smrg	    e = FcPatternObjectFindElt (pat, FcObjectFromName (o->object));
8822c393a42Smrg	    if (e)
8832c393a42Smrg	    {
8842c393a42Smrg		if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
8852c393a42Smrg		    goto bail0;
8862c393a42Smrg		if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
8872c393a42Smrg		    goto bail0;
8882c393a42Smrg		if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
8892c393a42Smrg		    goto bail0;
8902c393a42Smrg		if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
8912c393a42Smrg					     (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
8922c393a42Smrg		    goto bail0;
8932c393a42Smrg	    }
8942c393a42Smrg	}
8952c393a42Smrg    }
8962c393a42Smrg    return FcStrBufDone (&buf);
8972c393a42Smrgbail0:
8982c393a42Smrg    FcStrBufDestroy (&buf);
8992c393a42Smrg    return 0;
9002c393a42Smrg}
9012c393a42Smrg#define __fcname__
9022c393a42Smrg#include "fcaliastail.h"
9032c393a42Smrg#undef __fcname__
904