Blame src/fcpat.c

Packit 352660
/*
Packit 352660
 * Copyright © 2000 Keith Packard
Packit 352660
 *
Packit 352660
 * Permission to use, copy, modify, distribute, and sell this software and its
Packit 352660
 * documentation for any purpose is hereby granted without fee, provided that
Packit 352660
 * the above copyright notice appear in all copies and that both that
Packit 352660
 * copyright notice and this permission notice appear in supporting
Packit 352660
 * documentation, and that the name of the author(s) not be used in
Packit 352660
 * advertising or publicity pertaining to distribution of the software without
Packit 352660
 * specific, written prior permission.  The authors make no
Packit 352660
 * representations about the suitability of this software for any purpose.  It
Packit 352660
 * is provided "as is" without express or implied warranty.
Packit 352660
 *
Packit 352660
 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Packit 352660
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
Packit 352660
 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Packit 352660
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
Packit 352660
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
Packit 352660
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
Packit 352660
 * PERFORMANCE OF THIS SOFTWARE.
Packit 352660
 */
Packit 352660
Packit 352660
#include "fcint.h"
Packit 352660
#include "fcftint.h"
Packit 352660
Packit 352660
/* Objects MT-safe for readonly access. */
Packit 352660
Packit 352660
FcPattern *
Packit 352660
FcPatternCreate (void)
Packit 352660
{
Packit 352660
    FcPattern	*p;
Packit 352660
Packit 352660
    p = (FcPattern *) malloc (sizeof (FcPattern));
Packit 352660
    if (!p)
Packit 352660
	return 0;
Packit 352660
    memset (p, 0, sizeof (FcPattern));
Packit 352660
    p->num = 0;
Packit 352660
    p->size = 0;
Packit 352660
    p->elts_offset = FcPtrToOffset (p, NULL);
Packit 352660
    FcRefInit (&p->ref, 1);
Packit 352660
    return p;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcValueDestroy (FcValue v)
Packit 352660
{
Packit 352660
    switch ((int) v.type) {
Packit 352660
    case FcTypeString:
Packit 352660
	FcFree (v.u.s);
Packit 352660
	break;
Packit 352660
    case FcTypeMatrix:
Packit 352660
	FcMatrixFree ((FcMatrix *) v.u.m);
Packit 352660
	break;
Packit 352660
    case FcTypeCharSet:
Packit 352660
	FcCharSetDestroy ((FcCharSet *) v.u.c);
Packit 352660
	break;
Packit 352660
    case FcTypeLangSet:
Packit 352660
	FcLangSetDestroy ((FcLangSet *) v.u.l);
Packit 352660
	break;
Packit 352660
    case FcTypeRange:
Packit 352660
	FcRangeDestroy ((FcRange *) v.u.r);
Packit 352660
	break;
Packit 352660
    default:
Packit 352660
	break;
Packit 352660
    }
Packit 352660
}
Packit 352660
Packit 352660
FcValue
Packit 352660
FcValueCanonicalize (const FcValue *v)
Packit 352660
{
Packit 352660
    FcValue new;
Packit 352660
Packit 352660
    switch ((int) v->type)
Packit 352660
    {
Packit 352660
    case FcTypeString:
Packit 352660
	new.u.s = FcValueString(v);
Packit 352660
	new.type = FcTypeString;
Packit 352660
	break;
Packit 352660
    case FcTypeCharSet:
Packit 352660
	new.u.c = FcValueCharSet(v);
Packit 352660
	new.type = FcTypeCharSet;
Packit 352660
	break;
Packit 352660
    case FcTypeLangSet:
Packit 352660
	new.u.l = FcValueLangSet(v);
Packit 352660
	new.type = FcTypeLangSet;
Packit 352660
	break;
Packit 352660
    case FcTypeRange:
Packit 352660
	new.u.r = FcValueRange(v);
Packit 352660
	new.type = FcTypeRange;
Packit 352660
	break;
Packit 352660
    default:
Packit 352660
	new = *v;
Packit 352660
	break;
Packit 352660
    }
Packit 352660
    return new;
Packit 352660
}
Packit 352660
Packit 352660
FcValue
Packit 352660
FcValueSave (FcValue v)
Packit 352660
{
Packit 352660
    switch ((int) v.type) {
Packit 352660
    case FcTypeString:
Packit 352660
	v.u.s = FcStrdup (v.u.s);
Packit 352660
	if (!v.u.s)
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	break;
Packit 352660
    case FcTypeMatrix:
Packit 352660
	v.u.m = FcMatrixCopy (v.u.m);
Packit 352660
	if (!v.u.m)
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	break;
Packit 352660
    case FcTypeCharSet:
Packit 352660
	v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
Packit 352660
	if (!v.u.c)
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	break;
Packit 352660
    case FcTypeLangSet:
Packit 352660
	v.u.l = FcLangSetCopy (v.u.l);
Packit 352660
	if (!v.u.l)
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	break;
Packit 352660
    case FcTypeRange:
Packit 352660
	v.u.r = FcRangeCopy (v.u.r);
Packit 352660
	if (!v.u.r)
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	break;
Packit 352660
    default:
Packit 352660
	break;
Packit 352660
    }
Packit 352660
    return v;
Packit 352660
}
Packit 352660
Packit 352660
FcValueListPtr
Packit 352660
FcValueListCreate (void)
Packit 352660
{
Packit 352660
    return calloc (1, sizeof (FcValueList));
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcValueListDestroy (FcValueListPtr l)
Packit 352660
{
Packit 352660
    FcValueListPtr next;
Packit 352660
    for (; l; l = next)
Packit 352660
    {
Packit 352660
	switch ((int) l->value.type) {
Packit 352660
	case FcTypeString:
Packit 352660
	    FcFree (l->value.u.s);
Packit 352660
	    break;
Packit 352660
	case FcTypeMatrix:
Packit 352660
	    FcMatrixFree ((FcMatrix *)l->value.u.m);
Packit 352660
	    break;
Packit 352660
	case FcTypeCharSet:
Packit 352660
	    FcCharSetDestroy
Packit 352660
		((FcCharSet *) (l->value.u.c));
Packit 352660
	    break;
Packit 352660
	case FcTypeLangSet:
Packit 352660
	    FcLangSetDestroy
Packit 352660
		((FcLangSet *) (l->value.u.l));
Packit 352660
	    break;
Packit 352660
	case FcTypeRange:
Packit 352660
	    FcRangeDestroy ((FcRange *) (l->value.u.r));
Packit 352660
	    break;
Packit 352660
	default:
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
	next = FcValueListNext(l);
Packit 352660
	free(l);
Packit 352660
    }
Packit 352660
}
Packit 352660
Packit 352660
FcValueListPtr
Packit 352660
FcValueListPrepend (FcValueListPtr vallist,
Packit 352660
		    FcValue        value,
Packit 352660
		    FcValueBinding binding)
Packit 352660
{
Packit 352660
    FcValueListPtr new;
Packit 352660
Packit 352660
    if (value.type == FcTypeVoid)
Packit 352660
	return vallist;
Packit 352660
    new = FcValueListCreate ();
Packit 352660
    if (!new)
Packit 352660
	return vallist;
Packit 352660
Packit 352660
    new->value = FcValueSave (value);
Packit 352660
    new->binding = binding;
Packit 352660
    new->next = vallist;
Packit 352660
Packit 352660
    return new;
Packit 352660
}
Packit 352660
Packit 352660
FcValueListPtr
Packit 352660
FcValueListAppend (FcValueListPtr vallist,
Packit 352660
		   FcValue        value,
Packit 352660
		   FcValueBinding binding)
Packit 352660
{
Packit 352660
    FcValueListPtr new, last;
Packit 352660
Packit 352660
    if (value.type == FcTypeVoid)
Packit 352660
	return vallist;
Packit 352660
    new = FcValueListCreate ();
Packit 352660
    if (!new)
Packit 352660
	return vallist;
Packit 352660
Packit 352660
    new->value = FcValueSave (value);
Packit 352660
    new->binding = binding;
Packit 352660
    new->next = NULL;
Packit 352660
Packit 352660
    if (vallist)
Packit 352660
    {
Packit 352660
	for (last = vallist; FcValueListNext (last); last = FcValueListNext (last));
Packit 352660
Packit 352660
	last->next = new;
Packit 352660
    }
Packit 352660
    else
Packit 352660
	vallist = new;
Packit 352660
Packit 352660
    return vallist;
Packit 352660
}
Packit 352660
Packit 352660
FcValueListPtr
Packit 352660
FcValueListDuplicate(FcValueListPtr orig)
Packit 352660
{
Packit 352660
    FcValueListPtr new = NULL, l, t = NULL;
Packit 352660
    FcValue v;
Packit 352660
Packit 352660
    for (l = orig; l != NULL; l = FcValueListNext (l))
Packit 352660
    {
Packit 352660
	if (!new)
Packit 352660
	{
Packit 352660
	    t = new = FcValueListCreate();
Packit 352660
	}
Packit 352660
	else
Packit 352660
	{
Packit 352660
	    t->next = FcValueListCreate();
Packit 352660
	    t = FcValueListNext (t);
Packit 352660
	}
Packit 352660
	v = FcValueCanonicalize (&l->value);
Packit 352660
	t->value = FcValueSave (v);
Packit 352660
	t->binding = l->binding;
Packit 352660
	t->next = NULL;
Packit 352660
    }
Packit 352660
Packit 352660
    return new;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcValueEqual (FcValue va, FcValue vb)
Packit 352660
{
Packit 352660
    if (va.type != vb.type)
Packit 352660
    {
Packit 352660
	if (va.type == FcTypeInteger)
Packit 352660
	{
Packit 352660
	    va.type = FcTypeDouble;
Packit 352660
	    va.u.d = va.u.i;
Packit 352660
	}
Packit 352660
	if (vb.type == FcTypeInteger)
Packit 352660
	{
Packit 352660
	    vb.type = FcTypeDouble;
Packit 352660
	    vb.u.d = vb.u.i;
Packit 352660
	}
Packit 352660
	if (va.type != vb.type)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    switch (va.type) {
Packit 352660
    case FcTypeUnknown:
Packit 352660
	return FcFalse;	/* don't know how to compare this object */
Packit 352660
    case FcTypeVoid:
Packit 352660
	return FcTrue;
Packit 352660
    case FcTypeInteger:
Packit 352660
	return va.u.i == vb.u.i;
Packit 352660
    case FcTypeDouble:
Packit 352660
	return va.u.d == vb.u.d;
Packit 352660
    case FcTypeString:
Packit 352660
	return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
Packit 352660
    case FcTypeBool:
Packit 352660
	return va.u.b == vb.u.b;
Packit 352660
    case FcTypeMatrix:
Packit 352660
	return FcMatrixEqual (va.u.m, vb.u.m);
Packit 352660
    case FcTypeCharSet:
Packit 352660
	return FcCharSetEqual (va.u.c, vb.u.c);
Packit 352660
    case FcTypeFTFace:
Packit 352660
	return va.u.f == vb.u.f;
Packit 352660
    case FcTypeLangSet:
Packit 352660
	return FcLangSetEqual (va.u.l, vb.u.l);
Packit 352660
    case FcTypeRange:
Packit 352660
	return FcRangeIsInRange (va.u.r, vb.u.r);
Packit 352660
    }
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
static FcChar32
Packit 352660
FcDoubleHash (double d)
Packit 352660
{
Packit 352660
    if (d < 0)
Packit 352660
	d = -d;
Packit 352660
    if (d > 0xffffffff)
Packit 352660
	d = 0xffffffff;
Packit 352660
    return (FcChar32) d;
Packit 352660
}
Packit 352660
Packit 352660
FcChar32
Packit 352660
FcStringHash (const FcChar8 *s)
Packit 352660
{
Packit 352660
    FcChar8	c;
Packit 352660
    FcChar32	h = 0;
Packit 352660
Packit 352660
    if (s)
Packit 352660
	while ((c = *s++))
Packit 352660
	    h = ((h << 1) | (h >> 31)) ^ c;
Packit 352660
    return h;
Packit 352660
}
Packit 352660
Packit 352660
static FcChar32
Packit 352660
FcValueHash (const FcValue *v)
Packit 352660
{
Packit 352660
    switch (v->type) {
Packit 352660
    case FcTypeUnknown:
Packit 352660
    case FcTypeVoid:
Packit 352660
	return 0;
Packit 352660
    case FcTypeInteger:
Packit 352660
	return (FcChar32) v->u.i;
Packit 352660
    case FcTypeDouble:
Packit 352660
	return FcDoubleHash (v->u.d);
Packit 352660
    case FcTypeString:
Packit 352660
	return FcStringHash (FcValueString(v));
Packit 352660
    case FcTypeBool:
Packit 352660
	return (FcChar32) v->u.b;
Packit 352660
    case FcTypeMatrix:
Packit 352660
	return (FcDoubleHash (v->u.m->xx) ^
Packit 352660
		FcDoubleHash (v->u.m->xy) ^
Packit 352660
		FcDoubleHash (v->u.m->yx) ^
Packit 352660
		FcDoubleHash (v->u.m->yy));
Packit 352660
    case FcTypeCharSet:
Packit 352660
	return (FcChar32) FcValueCharSet(v)->num;
Packit 352660
    case FcTypeFTFace:
Packit 352660
	return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
Packit 352660
	       FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
Packit 352660
    case FcTypeLangSet:
Packit 352660
	return FcLangSetHash (FcValueLangSet(v));
Packit 352660
    case FcTypeRange:
Packit 352660
	return FcRangeHash (v->u.r);
Packit 352660
    }
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
Packit 352660
{
Packit 352660
    if (la == lb)
Packit 352660
	return FcTrue;
Packit 352660
Packit 352660
    while (la && lb)
Packit 352660
    {
Packit 352660
	if (!FcValueEqual (la->value, lb->value))
Packit 352660
	    return FcFalse;
Packit 352660
	la = FcValueListNext(la);
Packit 352660
	lb = FcValueListNext(lb);
Packit 352660
    }
Packit 352660
    if (la || lb)
Packit 352660
	return FcFalse;
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
static FcChar32
Packit 352660
FcValueListHash (FcValueListPtr l)
Packit 352660
{
Packit 352660
    FcChar32	hash = 0;
Packit 352660
Packit 352660
    for (; l; l = FcValueListNext(l))
Packit 352660
    {
Packit 352660
	hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
Packit 352660
    }
Packit 352660
    return hash;
Packit 352660
}
Packit 352660
Packit 352660
static void *
Packit 352660
FcPatternGetCacheObject (FcPattern *p)
Packit 352660
{
Packit 352660
  /* We use a value to find the cache, instead of the FcPattern object
Packit 352660
   * because the pattern itself may be a cache allocation if we rewrote the path,
Packit 352660
   * so the p may not be in the cached region. */
Packit 352660
  return FcPatternEltValues(&FcPatternElts (p)[0]);
Packit 352660
}
Packit 352660
Packit 352660
FcPattern *
Packit 352660
FcPatternCacheRewriteFile (const FcPattern *p,
Packit 352660
                           FcCache *cache,
Packit 352660
                           const FcChar8 *relocated_font_file)
Packit 352660
{
Packit 352660
    FcPatternElt *elts = FcPatternElts (p);
Packit 352660
    size_t i,j;
Packit 352660
    FcChar8 *data;
Packit 352660
    FcPattern *new_p;
Packit 352660
    FcPatternElt *new_elts;
Packit 352660
    FcValueList *new_value_list;
Packit 352660
    size_t new_path_len = strlen ((char *)relocated_font_file);
Packit 352660
    FcChar8 *new_path;
Packit 352660
Packit 352660
    /* Allocate space for the patter, the PatternElt headers and
Packit 352660
     * the FC_FILE FcValueList and path that will be freed with the
Packit 352660
     * cache */
Packit 352660
    data = FcCacheAllocate (cache,
Packit 352660
			    sizeof (FcPattern) +
Packit 352660
			    p->num * sizeof (FcPatternElt) +
Packit 352660
			    sizeof (FcValueList) +
Packit 352660
			    new_path_len + 1);
Packit 352660
Packit 352660
    new_p = (FcPattern *)data;
Packit 352660
    data += sizeof (FcPattern);
Packit 352660
    new_elts = (FcPatternElt *)(data);
Packit 352660
    data += p->num * sizeof (FcPatternElt);
Packit 352660
    new_value_list = (FcValueList *)data;
Packit 352660
    data += sizeof (FcValueList);
Packit 352660
    new_path = data;
Packit 352660
Packit 352660
    *new_p = *p;
Packit 352660
    new_p->elts_offset = FcPtrToOffset (new_p, new_elts);
Packit 352660
Packit 352660
    /* Copy all but the FILE values from the cache */
Packit 352660
    for (i = 0, j = 0; i < p->num; i++)
Packit 352660
    {
Packit 352660
	FcPatternElt *elt = &elts[i];
Packit 352660
	new_elts[j].object = elt->object;
Packit 352660
	if (elt->object != FC_FILE_OBJECT)
Packit 352660
	    new_elts[j++].values = FcPatternEltValues(elt);
Packit 352660
	else
Packit 352660
	    new_elts[j++].values = new_value_list;
Packit 352660
    }
Packit 352660
Packit 352660
    new_value_list->next = NULL;
Packit 352660
    new_value_list->value.type = FcTypeString;
Packit 352660
    new_value_list->value.u.s = new_path;
Packit 352660
    new_value_list->binding = FcValueBindingWeak;
Packit 352660
Packit 352660
    /* Add rewritten path at the end */
Packit 352660
    strcpy ((char *)new_path, (char *)relocated_font_file);
Packit 352660
Packit 352660
    return new_p;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcPatternDestroy (FcPattern *p)
Packit 352660
{
Packit 352660
    int		    i;
Packit 352660
    FcPatternElt    *elts;
Packit 352660
Packit 352660
    if (!p)
Packit 352660
	return;
Packit 352660
Packit 352660
    if (FcRefIsConst (&p->ref))
Packit 352660
    {
Packit 352660
	FcCacheObjectDereference (FcPatternGetCacheObject(p));
Packit 352660
	return;
Packit 352660
    }
Packit 352660
Packit 352660
    if (FcRefDec (&p->ref) != 1)
Packit 352660
	return;
Packit 352660
Packit 352660
    elts = FcPatternElts (p);
Packit 352660
    for (i = 0; i < FcPatternObjectCount (p); i++)
Packit 352660
	FcValueListDestroy (FcPatternEltValues(&elts[i]));
Packit 352660
Packit 352660
    free (elts);
Packit 352660
    free (p);
Packit 352660
}
Packit 352660
Packit 352660
int
Packit 352660
FcPatternObjectCount (const FcPattern *pat)
Packit 352660
{
Packit 352660
    if (pat)
Packit 352660
	return pat->num;
Packit 352660
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
Packit 352660
static int
Packit 352660
FcPatternObjectPosition (const FcPattern *p, FcObject object)
Packit 352660
{
Packit 352660
    int	    low, high, mid, c;
Packit 352660
    FcPatternElt    *elts = FcPatternElts(p);
Packit 352660
Packit 352660
    low = 0;
Packit 352660
    high = FcPatternObjectCount (p) - 1;
Packit 352660
    c = 1;
Packit 352660
    mid = 0;
Packit 352660
    while (low <= high)
Packit 352660
    {
Packit 352660
	mid = (low + high) >> 1;
Packit 352660
	c = elts[mid].object - object;
Packit 352660
	if (c == 0)
Packit 352660
	    return mid;
Packit 352660
	if (c < 0)
Packit 352660
	    low = mid + 1;
Packit 352660
	else
Packit 352660
	    high = mid - 1;
Packit 352660
    }
Packit 352660
    if (c < 0)
Packit 352660
	mid++;
Packit 352660
    return -(mid + 1);
Packit 352660
}
Packit 352660
Packit 352660
int
Packit 352660
FcPatternPosition (const FcPattern *p, const char *object)
Packit 352660
{
Packit 352660
    return FcPatternObjectPosition (p, FcObjectFromName (object));
Packit 352660
}
Packit 352660
Packit 352660
FcPatternElt *
Packit 352660
FcPatternObjectFindElt (const FcPattern *p, FcObject object)
Packit 352660
{
Packit 352660
    int	    i = FcPatternObjectPosition (p, object);
Packit 352660
    if (i < 0)
Packit 352660
	return 0;
Packit 352660
    return &FcPatternElts(p)[i];
Packit 352660
}
Packit 352660
Packit 352660
FcPatternElt *
Packit 352660
FcPatternObjectInsertElt (FcPattern *p, FcObject object)
Packit 352660
{
Packit 352660
    int		    i;
Packit 352660
    FcPatternElt   *e;
Packit 352660
Packit 352660
    i = FcPatternObjectPosition (p, object);
Packit 352660
    if (i < 0)
Packit 352660
    {
Packit 352660
	i = -i - 1;
Packit 352660
Packit 352660
	/* reallocate array */
Packit 352660
	if (FcPatternObjectCount (p) + 1 >= p->size)
Packit 352660
	{
Packit 352660
	    int s = p->size + 16;
Packit 352660
	    if (p->size)
Packit 352660
	    {
Packit 352660
		FcPatternElt *e0 = FcPatternElts(p);
Packit 352660
		e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
Packit 352660
		if (!e) /* maybe it was mmapped */
Packit 352660
		{
Packit 352660
		    e = malloc(s * sizeof (FcPatternElt));
Packit 352660
		    if (e)
Packit 352660
			memcpy(e, e0, FcPatternObjectCount (p) * sizeof (FcPatternElt));
Packit 352660
		}
Packit 352660
	    }
Packit 352660
	    else
Packit 352660
		e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
Packit 352660
	    if (!e)
Packit 352660
		return FcFalse;
Packit 352660
	    p->elts_offset = FcPtrToOffset (p, e);
Packit 352660
	    while (p->size < s)
Packit 352660
	    {
Packit 352660
		e[p->size].object = 0;
Packit 352660
		e[p->size].values = NULL;
Packit 352660
		p->size++;
Packit 352660
	    }
Packit 352660
	}
Packit 352660
	
Packit 352660
	e = FcPatternElts(p);
Packit 352660
	/* move elts up */
Packit 352660
	memmove (e + i + 1,
Packit 352660
		 e + i,
Packit 352660
		 sizeof (FcPatternElt) *
Packit 352660
		 (FcPatternObjectCount (p) - i));
Packit 352660
		
Packit 352660
	/* bump count */
Packit 352660
	p->num++;
Packit 352660
	
Packit 352660
	e[i].object = object;
Packit 352660
	e[i].values = NULL;
Packit 352660
    }
Packit 352660
Packit 352660
    return FcPatternElts(p) + i;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
Packit 352660
{
Packit 352660
    FcPatternIter ia, ib;
Packit 352660
Packit 352660
    if (pa == pb)
Packit 352660
	return FcTrue;
Packit 352660
Packit 352660
    if (FcPatternObjectCount (pa) != FcPatternObjectCount (pb))
Packit 352660
	return FcFalse;
Packit 352660
    FcPatternIterStart (pa, &ia);
Packit 352660
    FcPatternIterStart (pb, &ib;;
Packit 352660
    do {
Packit 352660
	FcBool ra, rb;
Packit 352660
Packit 352660
	if (!FcPatternIterEqual (pa, &ia, pb, &ib))
Packit 352660
	    return FcFalse;
Packit 352660
	ra = FcPatternIterNext (pa, &ia);
Packit 352660
	rb = FcPatternIterNext (pb, &ib;;
Packit 352660
	if (!ra && !rb)
Packit 352660
	    break;
Packit 352660
    } while (1);
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcChar32
Packit 352660
FcPatternHash (const FcPattern *p)
Packit 352660
{
Packit 352660
    int		i;
Packit 352660
    FcChar32	h = 0;
Packit 352660
    FcPatternElt    *pe = FcPatternElts(p);
Packit 352660
Packit 352660
    for (i = 0; i < FcPatternObjectCount (p); i++)
Packit 352660
    {
Packit 352660
	h = (((h << 1) | (h >> 31)) ^
Packit 352660
	     pe[i].object ^
Packit 352660
	     FcValueListHash (FcPatternEltValues(&pe[i])));
Packit 352660
    }
Packit 352660
    return h;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
Packit 352660
{
Packit 352660
    FcPatternElt    *ea, *eb;
Packit 352660
    int		    i;
Packit 352660
Packit 352660
    for (i = 0; i < os->nobject; i++)
Packit 352660
    {
Packit 352660
	FcObject    object = FcObjectFromName (os->objects[i]);
Packit 352660
	ea = FcPatternObjectFindElt (pai, object);
Packit 352660
	eb = FcPatternObjectFindElt (pbi, object);
Packit 352660
	if (ea)
Packit 352660
	{
Packit 352660
	    if (!eb)
Packit 352660
		return FcFalse;
Packit 352660
	    if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
Packit 352660
		return FcFalse;
Packit 352660
	}
Packit 352660
	else
Packit 352660
	{
Packit 352660
	    if (eb)
Packit 352660
		return FcFalse;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternObjectListAdd (FcPattern	*p,
Packit 352660
			FcObject	object,
Packit 352660
			FcValueListPtr	list,
Packit 352660
			FcBool		append)
Packit 352660
{
Packit 352660
    FcPatternElt   *e;
Packit 352660
    FcValueListPtr l, *prev;
Packit 352660
Packit 352660
    if (FcRefIsConst (&p->ref))
Packit 352660
	goto bail0;
Packit 352660
Packit 352660
    /*
Packit 352660
     * Make sure the stored type is valid for built-in objects
Packit 352660
     */
Packit 352660
    for (l = list; l != NULL; l = FcValueListNext (l))
Packit 352660
    {
Packit 352660
	if (!FcObjectValidType (object, l->value.type))
Packit 352660
	{
Packit 352660
	    fprintf (stderr,
Packit 352660
		     "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
Packit 352660
	    FcValuePrintFile (stderr, l->value);
Packit 352660
	    fprintf (stderr, "\n");
Packit 352660
	    goto bail0;
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    e = FcPatternObjectInsertElt (p, object);
Packit 352660
    if (!e)
Packit 352660
	goto bail0;
Packit 352660
Packit 352660
    if (append)
Packit 352660
    {
Packit 352660
	for (prev = &e->values; *prev; prev = &(*prev)->next)
Packit 352660
	    ;
Packit 352660
	*prev = list;
Packit 352660
    }
Packit 352660
    else
Packit 352660
    {
Packit 352660
	for (prev = &list; *prev; prev = &(*prev)->next)
Packit 352660
	    ;
Packit 352660
	*prev = e->values;
Packit 352660
	e->values = list;
Packit 352660
    }
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
Packit 352660
bail0:
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternObjectAddWithBinding  (FcPattern	*p,
Packit 352660
				FcObject	object,
Packit 352660
				FcValue		value,
Packit 352660
				FcValueBinding  binding,
Packit 352660
				FcBool		append)
Packit 352660
{
Packit 352660
    FcPatternElt   *e;
Packit 352660
    FcValueListPtr new, *prev;
Packit 352660
Packit 352660
    if (FcRefIsConst (&p->ref))
Packit 352660
	goto bail0;
Packit 352660
Packit 352660
    new = FcValueListCreate ();
Packit 352660
    if (!new)
Packit 352660
	goto bail0;
Packit 352660
Packit 352660
    value = FcValueSave (value);
Packit 352660
    if (value.type == FcTypeVoid)
Packit 352660
	goto bail1;
Packit 352660
Packit 352660
    /*
Packit 352660
     * Make sure the stored type is valid for built-in objects
Packit 352660
     */
Packit 352660
    if (!FcObjectValidType (object, value.type))
Packit 352660
    {
Packit 352660
	fprintf (stderr,
Packit 352660
		 "Fontconfig warning: FcPattern object %s does not accept value",
Packit 352660
		 FcObjectName (object));
Packit 352660
	FcValuePrintFile (stderr, value);
Packit 352660
	fprintf (stderr, "\n");
Packit 352660
	goto bail1;
Packit 352660
    }
Packit 352660
Packit 352660
    new->value = value;
Packit 352660
    new->binding = binding;
Packit 352660
    new->next = NULL;
Packit 352660
Packit 352660
    e = FcPatternObjectInsertElt (p, object);
Packit 352660
    if (!e)
Packit 352660
	goto bail2;
Packit 352660
Packit 352660
    if (append)
Packit 352660
    {
Packit 352660
	for (prev = &e->values; *prev; prev = &(*prev)->next)
Packit 352660
	    ;
Packit 352660
	*prev = new;
Packit 352660
    }
Packit 352660
    else
Packit 352660
    {
Packit 352660
	new->next = e->values;
Packit 352660
	e->values = new;
Packit 352660
    }
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
Packit 352660
bail2:
Packit 352660
    FcValueDestroy (value);
Packit 352660
bail1:
Packit 352660
    free (new);
Packit 352660
bail0:
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
Packit 352660
{
Packit 352660
    return FcPatternObjectAddWithBinding (p, object,
Packit 352660
					  value, FcValueBindingStrong, append);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
Packit 352660
{
Packit 352660
    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
Packit 352660
					  value, FcValueBindingStrong, append);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddWeak  (FcPattern *p, const char *object, FcValue value, FcBool append)
Packit 352660
{
Packit 352660
    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
Packit 352660
					  value, FcValueBindingWeak, append);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternObjectDel (FcPattern *p, FcObject object)
Packit 352660
{
Packit 352660
    FcPatternElt   *e;
Packit 352660
Packit 352660
    e = FcPatternObjectFindElt (p, object);
Packit 352660
    if (!e)
Packit 352660
	return FcFalse;
Packit 352660
Packit 352660
    /* destroy value */
Packit 352660
    FcValueListDestroy (e->values);
Packit 352660
Packit 352660
    /* shuffle existing ones down */
Packit 352660
    memmove (e, e+1,
Packit 352660
	     (FcPatternElts(p) + FcPatternObjectCount (p) - (e + 1)) *
Packit 352660
	     sizeof (FcPatternElt));
Packit 352660
    p->num--;
Packit 352660
    e = FcPatternElts(p) + FcPatternObjectCount (p);
Packit 352660
    e->object = 0;
Packit 352660
    e->values = NULL;
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternDel (FcPattern *p, const char *object)
Packit 352660
{
Packit 352660
    return FcPatternObjectDel (p, FcObjectFromName (object));
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternRemove (FcPattern *p, const char *object, int id)
Packit 352660
{
Packit 352660
    FcPatternElt    *e;
Packit 352660
    FcValueListPtr  *prev, l;
Packit 352660
Packit 352660
    e = FcPatternObjectFindElt (p, FcObjectFromName (object));
Packit 352660
    if (!e)
Packit 352660
	return FcFalse;
Packit 352660
    for (prev = &e->values; (l = *prev); prev = &l->next)
Packit 352660
    {
Packit 352660
	if (!id)
Packit 352660
	{
Packit 352660
	    *prev = l->next;
Packit 352660
	    l->next = NULL;
Packit 352660
	    FcValueListDestroy (l);
Packit 352660
	    if (!e->values)
Packit 352660
		FcPatternDel (p, object);
Packit 352660
	    return FcTrue;
Packit 352660
	}
Packit 352660
	id--;
Packit 352660
    }
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
Packit 352660
    v.type = FcTypeInteger;
Packit 352660
    v.u.i = i;
Packit 352660
    return FcPatternObjectAdd (p, object, v, FcTrue);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddInteger (FcPattern *p, const char *object, int i)
Packit 352660
{
Packit 352660
    return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
Packit 352660
    v.type = FcTypeDouble;
Packit 352660
    v.u.d = d;
Packit 352660
    return FcPatternObjectAdd (p, object, v, FcTrue);
Packit 352660
}
Packit 352660
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddDouble (FcPattern *p, const char *object, double d)
Packit 352660
{
Packit 352660
    return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
Packit 352660
    if (!s)
Packit 352660
    {
Packit 352660
	v.type = FcTypeVoid;
Packit 352660
	v.u.s = 0;
Packit 352660
	return FcPatternObjectAdd (p, object, v, FcTrue);
Packit 352660
    }
Packit 352660
Packit 352660
    v.type = FcTypeString;
Packit 352660
    v.u.s = s;
Packit 352660
    return FcPatternObjectAdd (p, object, v, FcTrue);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
Packit 352660
{
Packit 352660
    return FcPatternObjectAddString (p, FcObjectFromName (object), s);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
Packit 352660
    v.type = FcTypeMatrix;
Packit 352660
    v.u.m = s;
Packit 352660
    return FcPatternAdd (p, object, v, FcTrue);
Packit 352660
}
Packit 352660
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
Packit 352660
    v.type = FcTypeBool;
Packit 352660
    v.u.b = b;
Packit 352660
    return FcPatternObjectAdd (p, object, v, FcTrue);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
Packit 352660
{
Packit 352660
    return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
Packit 352660
    v.type = FcTypeCharSet;
Packit 352660
    v.u.c = (FcCharSet *)c;
Packit 352660
    return FcPatternAdd (p, object, v, FcTrue);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
Packit 352660
    v.type = FcTypeFTFace;
Packit 352660
    v.u.f = (void *) f;
Packit 352660
    return FcPatternAdd (p, object, v, FcTrue);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
Packit 352660
    v.type = FcTypeLangSet;
Packit 352660
    v.u.l = (FcLangSet *)ls;
Packit 352660
    return FcPatternAdd (p, object, v, FcTrue);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternObjectAddRange (FcPattern *p, FcObject object, const FcRange *r)
Packit 352660
{
Packit 352660
    FcValue v;
Packit 352660
Packit 352660
    v.type = FcTypeRange;
Packit 352660
    v.u.r = (FcRange *)r;
Packit 352660
    return FcPatternObjectAdd (p, object, v, FcTrue);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternAddRange (FcPattern *p, const char *object, const FcRange *r)
Packit 352660
{
Packit 352660
    return FcPatternObjectAddRange (p, FcObjectFromName (object), r);
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternObjectGetWithBinding (const FcPattern *p, FcObject object, int id, FcValue *v, FcValueBinding *b)
Packit 352660
{
Packit 352660
    FcPatternElt   *e;
Packit 352660
    FcValueListPtr l;
Packit 352660
Packit 352660
    if (!p)
Packit 352660
	return FcResultNoMatch;
Packit 352660
    e = FcPatternObjectFindElt (p, object);
Packit 352660
    if (!e)
Packit 352660
	return FcResultNoMatch;
Packit 352660
    for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
Packit 352660
    {
Packit 352660
	if (!id)
Packit 352660
	{
Packit 352660
	    *v = FcValueCanonicalize(&l->value);
Packit 352660
	    if (b)
Packit 352660
		*b = l->binding;
Packit 352660
	    return FcResultMatch;
Packit 352660
	}
Packit 352660
	id--;
Packit 352660
    }
Packit 352660
    return FcResultNoId;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
Packit 352660
{
Packit 352660
    return FcPatternObjectGetWithBinding (p, object, id, v, NULL);
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetWithBinding (const FcPattern *p, const char *object, int id, FcValue *v, FcValueBinding *b)
Packit 352660
{
Packit 352660
    return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, b);
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
Packit 352660
{
Packit 352660
    return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, NULL);
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
    FcResult	r;
Packit 352660
Packit 352660
    r = FcPatternObjectGet (p, object, id, &v);
Packit 352660
    if (r != FcResultMatch)
Packit 352660
	return r;
Packit 352660
    switch ((int) v.type) {
Packit 352660
    case FcTypeDouble:
Packit 352660
	*i = (int) v.u.d;
Packit 352660
	break;
Packit 352660
    case FcTypeInteger:
Packit 352660
	*i = v.u.i;
Packit 352660
	break;
Packit 352660
    default:
Packit 352660
        return FcResultTypeMismatch;
Packit 352660
    }
Packit 352660
    return FcResultMatch;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
Packit 352660
{
Packit 352660
    return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
Packit 352660
}
Packit 352660
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
    FcResult	r;
Packit 352660
Packit 352660
    r = FcPatternObjectGet (p, object, id, &v);
Packit 352660
    if (r != FcResultMatch)
Packit 352660
	return r;
Packit 352660
    switch ((int) v.type) {
Packit 352660
    case FcTypeDouble:
Packit 352660
	*d = v.u.d;
Packit 352660
	break;
Packit 352660
    case FcTypeInteger:
Packit 352660
	*d = (double) v.u.i;
Packit 352660
	break;
Packit 352660
    default:
Packit 352660
        return FcResultTypeMismatch;
Packit 352660
    }
Packit 352660
    return FcResultMatch;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
Packit 352660
{
Packit 352660
    return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
    FcResult	r;
Packit 352660
Packit 352660
    r = FcPatternObjectGet (p, object, id, &v);
Packit 352660
    if (r != FcResultMatch)
Packit 352660
	return r;
Packit 352660
    if (v.type != FcTypeString)
Packit 352660
        return FcResultTypeMismatch;
Packit 352660
Packit 352660
    *s = (FcChar8 *) v.u.s;
Packit 352660
    return FcResultMatch;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
Packit 352660
{
Packit 352660
    return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
    FcResult	r;
Packit 352660
Packit 352660
    r = FcPatternGet (p, object, id, &v);
Packit 352660
    if (r != FcResultMatch)
Packit 352660
	return r;
Packit 352660
    if (v.type != FcTypeMatrix)
Packit 352660
        return FcResultTypeMismatch;
Packit 352660
    *m = (FcMatrix *)v.u.m;
Packit 352660
    return FcResultMatch;
Packit 352660
}
Packit 352660
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternObjectGetBool (const FcPattern *p, FcObject object, int id, FcBool *b)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
    FcResult	r;
Packit 352660
Packit 352660
    r = FcPatternObjectGet (p, object, id, &v);
Packit 352660
    if (r != FcResultMatch)
Packit 352660
	return r;
Packit 352660
    if (v.type != FcTypeBool)
Packit 352660
        return FcResultTypeMismatch;
Packit 352660
    *b = v.u.b;
Packit 352660
    return FcResultMatch;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
Packit 352660
{
Packit 352660
    return FcPatternObjectGetBool (p, FcObjectFromName (object), id, b);
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
    FcResult	r;
Packit 352660
Packit 352660
    r = FcPatternGet (p, object, id, &v);
Packit 352660
    if (r != FcResultMatch)
Packit 352660
	return r;
Packit 352660
    if (v.type != FcTypeCharSet)
Packit 352660
        return FcResultTypeMismatch;
Packit 352660
    *c = (FcCharSet *)v.u.c;
Packit 352660
    return FcResultMatch;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
    FcResult	r;
Packit 352660
Packit 352660
    r = FcPatternGet (p, object, id, &v);
Packit 352660
    if (r != FcResultMatch)
Packit 352660
	return r;
Packit 352660
    if (v.type != FcTypeFTFace)
Packit 352660
	return FcResultTypeMismatch;
Packit 352660
    *f = (FT_Face) v.u.f;
Packit 352660
    return FcResultMatch;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
    FcResult	r;
Packit 352660
Packit 352660
    r = FcPatternGet (p, object, id, &v);
Packit 352660
    if (r != FcResultMatch)
Packit 352660
	return r;
Packit 352660
    if (v.type != FcTypeLangSet)
Packit 352660
        return FcResultTypeMismatch;
Packit 352660
    *ls = (FcLangSet *)v.u.l;
Packit 352660
    return FcResultMatch;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternObjectGetRange (const FcPattern *p, FcObject object, int id, FcRange **r)
Packit 352660
{
Packit 352660
    FcValue	v;
Packit 352660
    FcResult	res;
Packit 352660
Packit 352660
    res = FcPatternObjectGet (p, object, id, &v);
Packit 352660
    if (res != FcResultMatch)
Packit 352660
	return res;
Packit 352660
    switch ((int)v.type) {
Packit 352660
    case FcTypeRange:
Packit 352660
	*r = (FcRange *)v.u.r;
Packit 352660
	break;
Packit 352660
    default:
Packit 352660
	return FcResultTypeMismatch;
Packit 352660
    }
Packit 352660
    return FcResultMatch;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r)
Packit 352660
{
Packit 352660
    return FcPatternObjectGetRange (p, FcObjectFromName (object), id, r);
Packit 352660
}
Packit 352660
Packit 352660
FcPattern *
Packit 352660
FcPatternDuplicate (const FcPattern *orig)
Packit 352660
{
Packit 352660
    FcPattern	    *new;
Packit 352660
    FcPatternIter   iter;
Packit 352660
    FcValueListPtr  l;
Packit 352660
Packit 352660
    if (!orig)
Packit 352660
	return NULL;
Packit 352660
Packit 352660
    new = FcPatternCreate ();
Packit 352660
    if (!new)
Packit 352660
	goto bail0;
Packit 352660
Packit 352660
    FcPatternIterStart (orig, &iter);
Packit 352660
    do
Packit 352660
    {
Packit 352660
	for (l = FcPatternIterGetValues (orig, &iter); l; l = FcValueListNext (l))
Packit 352660
	{
Packit 352660
	    if (!FcPatternObjectAddWithBinding (new, FcPatternIterGetObjectId (orig, &iter),
Packit 352660
						FcValueCanonicalize(&l->value),
Packit 352660
						l->binding,
Packit 352660
						FcTrue))
Packit 352660
		goto bail1;
Packit 352660
	}
Packit 352660
    } while (FcPatternIterNext (orig, &iter));
Packit 352660
Packit 352660
    return new;
Packit 352660
Packit 352660
bail1:
Packit 352660
    FcPatternDestroy (new);
Packit 352660
bail0:
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcPatternReference (FcPattern *p)
Packit 352660
{
Packit 352660
    if (!FcRefIsConst (&p->ref))
Packit 352660
	FcRefInc (&p->ref);
Packit 352660
    else
Packit 352660
	FcCacheObjectReference (FcPatternGetCacheObject(p));
Packit 352660
}
Packit 352660
Packit 352660
FcPattern *
Packit 352660
FcPatternVaBuild (FcPattern *p, va_list va)
Packit 352660
{
Packit 352660
    FcPattern	*ret;
Packit 352660
Packit 352660
    FcPatternVapBuild (ret, p, va);
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
FcPattern *
Packit 352660
FcPatternBuild (FcPattern *p, ...)
Packit 352660
{
Packit 352660
    va_list	va;
Packit 352660
Packit 352660
    va_start (va, p);
Packit 352660
    FcPatternVapBuild (p, p, va);
Packit 352660
    va_end (va);
Packit 352660
    return p;
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Add all of the elements in 's' to 'p'
Packit 352660
 */
Packit 352660
FcBool
Packit 352660
FcPatternAppend (FcPattern *p, FcPattern *s)
Packit 352660
{
Packit 352660
    FcPatternIter  iter;
Packit 352660
    FcValueListPtr v;
Packit 352660
Packit 352660
    FcPatternIterStart (s, &iter);
Packit 352660
    do
Packit 352660
    {
Packit 352660
	for (v = FcPatternIterGetValues (s, &iter); v; v = FcValueListNext (v))
Packit 352660
	{
Packit 352660
	    if (!FcPatternObjectAddWithBinding (p, FcPatternIterGetObjectId (s, &iter),
Packit 352660
						FcValueCanonicalize(&v->value),
Packit 352660
						v->binding, FcTrue))
Packit 352660
		return FcFalse;
Packit 352660
	}
Packit 352660
    } while (FcPatternIterNext (s, &iter));
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcPattern *
Packit 352660
FcPatternFilter (FcPattern *p, const FcObjectSet *os)
Packit 352660
{
Packit 352660
    int		    i;
Packit 352660
    FcPattern	    *ret;
Packit 352660
    FcPatternElt    *e;
Packit 352660
    FcValueListPtr  v;
Packit 352660
Packit 352660
    if (!os)
Packit 352660
	return FcPatternDuplicate (p);
Packit 352660
Packit 352660
    ret = FcPatternCreate ();
Packit 352660
    if (!ret)
Packit 352660
	return NULL;
Packit 352660
Packit 352660
    for (i = 0; i < os->nobject; i++)
Packit 352660
    {
Packit 352660
	FcObject object = FcObjectFromName (os->objects[i]);
Packit 352660
	e = FcPatternObjectFindElt (p, object);
Packit 352660
	if (e)
Packit 352660
	{
Packit 352660
	    for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
Packit 352660
	    {
Packit 352660
		if (!FcPatternObjectAddWithBinding (ret, e->object,
Packit 352660
						    FcValueCanonicalize(&v->value),
Packit 352660
						    v->binding, FcTrue))
Packit 352660
		    goto bail0;
Packit 352660
	    }
Packit 352660
	}
Packit 352660
    }
Packit 352660
    return ret;
Packit 352660
Packit 352660
bail0:
Packit 352660
    FcPatternDestroy (ret);
Packit 352660
    return NULL;
Packit 352660
}
Packit 352660
Packit 352660
typedef struct _FcPatternPrivateIter {
Packit 352660
    FcPatternElt *elt;
Packit 352660
    int           pos;
Packit 352660
} FcPatternPrivateIter;
Packit 352660
Packit 352660
static void
Packit 352660
FcPatternIterSet (const FcPattern *pat, FcPatternPrivateIter *iter)
Packit 352660
{
Packit 352660
    iter->elt = FcPatternObjectCount (pat) > 0 && iter->pos < FcPatternObjectCount (pat) ? &FcPatternElts (pat)[iter->pos] : NULL;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcPatternIterStart (const FcPattern *pat, FcPatternIter *iter)
Packit 352660
{
Packit 352660
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
Packit 352660
Packit 352660
    priv->pos = 0;
Packit 352660
    FcPatternIterSet (pat, priv);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternIterNext (const FcPattern *pat, FcPatternIter *iter)
Packit 352660
{
Packit 352660
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
Packit 352660
Packit 352660
    priv->pos++;
Packit 352660
    if (priv->pos >= FcPatternObjectCount (pat))
Packit 352660
	return FcFalse;
Packit 352660
    FcPatternIterSet (pat, priv);
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternIterEqual (const FcPattern *p1, FcPatternIter *i1,
Packit 352660
		    const FcPattern *p2, FcPatternIter *i2)
Packit 352660
{
Packit 352660
    FcBool b1 = FcPatternIterIsValid (p1, i1);
Packit 352660
    FcBool b2 = FcPatternIterIsValid (p2, i2);
Packit 352660
Packit 352660
    if (!i1 && !i2)
Packit 352660
	return FcTrue;
Packit 352660
    if (!b1 || !b2)
Packit 352660
	return FcFalse;
Packit 352660
    if (FcPatternIterGetObjectId (p1, i1) != FcPatternIterGetObjectId (p2, i2))
Packit 352660
	return FcFalse;
Packit 352660
Packit 352660
    return FcValueListEqual (FcPatternIterGetValues (p1, i1),
Packit 352660
			     FcPatternIterGetValues (p2, i2));
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternFindObjectIter (const FcPattern *pat, FcPatternIter *iter, FcObject object)
Packit 352660
{
Packit 352660
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
Packit 352660
    int i = FcPatternObjectPosition (pat, object);
Packit 352660
Packit 352660
    priv->elt = NULL;
Packit 352660
    if (i < 0)
Packit 352660
	return FcFalse;
Packit 352660
Packit 352660
    priv->pos = i;
Packit 352660
    FcPatternIterSet (pat, priv);
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternFindIter (const FcPattern *pat, FcPatternIter *iter, const char *object)
Packit 352660
{
Packit 352660
    return FcPatternFindObjectIter (pat, iter, FcObjectFromName (object));
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternIterIsValid (const FcPattern *pat, FcPatternIter *iter)
Packit 352660
{
Packit 352660
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
Packit 352660
Packit 352660
    if (priv && priv->elt)
Packit 352660
	return FcTrue;
Packit 352660
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
FcObject
Packit 352660
FcPatternIterGetObjectId (const FcPattern *pat, FcPatternIter *iter)
Packit 352660
{
Packit 352660
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
Packit 352660
Packit 352660
    if (priv && priv->elt)
Packit 352660
	return priv->elt->object;
Packit 352660
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
const char *
Packit 352660
FcPatternIterGetObject (const FcPattern *pat, FcPatternIter *iter)
Packit 352660
{
Packit 352660
    return FcObjectName (FcPatternIterGetObjectId (pat, iter));
Packit 352660
}
Packit 352660
Packit 352660
FcValueListPtr
Packit 352660
FcPatternIterGetValues (const FcPattern *pat, FcPatternIter *iter)
Packit 352660
{
Packit 352660
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter;
Packit 352660
Packit 352660
    if (priv && priv->elt)
Packit 352660
	return FcPatternEltValues (priv->elt);
Packit 352660
Packit 352660
    return NULL;
Packit 352660
}
Packit 352660
Packit 352660
int
Packit 352660
FcPatternIterValueCount (const FcPattern *pat, FcPatternIter *iter)
Packit 352660
{
Packit 352660
    int count = 0;
Packit 352660
    FcValueListPtr l;
Packit 352660
Packit 352660
    for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l))
Packit 352660
	count++;
Packit 352660
Packit 352660
    return count;
Packit 352660
}
Packit 352660
Packit 352660
FcResult
Packit 352660
FcPatternIterGetValue (const FcPattern *pat, FcPatternIter *iter, int id, FcValue *v, FcValueBinding *b)
Packit 352660
{
Packit 352660
    FcValueListPtr l;
Packit 352660
Packit 352660
    for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l))
Packit 352660
    {
Packit 352660
	if (id == 0)
Packit 352660
	{
Packit 352660
	    *v = FcValueCanonicalize (&l->value);
Packit 352660
	    if (b)
Packit 352660
		*b = l->binding;
Packit 352660
	    return FcResultMatch;
Packit 352660
	}
Packit 352660
	id--;
Packit 352660
    }
Packit 352660
    return FcResultNoId;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
Packit 352660
{
Packit 352660
    int	i;
Packit 352660
    FcPatternElt    *elts = FcPatternElts(pat);
Packit 352660
Packit 352660
    if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
Packit 352660
	return FcFalse;
Packit 352660
    if (!FcSerializeAlloc (serialize, elts, FcPatternObjectCount (pat) * sizeof (FcPatternElt)))
Packit 352660
	return FcFalse;
Packit 352660
    for (i = 0; i < FcPatternObjectCount (pat); i++)
Packit 352660
	if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
Packit 352660
	    return FcFalse;
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcPattern *
Packit 352660
FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
Packit 352660
{
Packit 352660
    FcPattern	    *pat_serialized;
Packit 352660
    FcPatternElt    *elts = FcPatternElts (pat);
Packit 352660
    FcPatternElt    *elts_serialized;
Packit 352660
    FcValueList	    *values_serialized;
Packit 352660
    int		    i;
Packit 352660
Packit 352660
    pat_serialized = FcSerializePtr (serialize, pat);
Packit 352660
    if (!pat_serialized)
Packit 352660
	return NULL;
Packit 352660
    *pat_serialized = *pat;
Packit 352660
    pat_serialized->size = FcPatternObjectCount (pat);
Packit 352660
    FcRefSetConst (&pat_serialized->ref);
Packit 352660
Packit 352660
    elts_serialized = FcSerializePtr (serialize, elts);
Packit 352660
    if (!elts_serialized)
Packit 352660
	return NULL;
Packit 352660
Packit 352660
    pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
Packit 352660
						 elts_serialized);
Packit 352660
Packit 352660
    for (i = 0; i < FcPatternObjectCount (pat); i++)
Packit 352660
    {
Packit 352660
	values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
Packit 352660
	if (!values_serialized)
Packit 352660
	    return NULL;
Packit 352660
	elts_serialized[i].object = elts[i].object;
Packit 352660
	elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
Packit 352660
							  values_serialized,
Packit 352660
							  FcValueList);
Packit 352660
    }
Packit 352660
    if (FcDebug() & FC_DBG_CACHEV) {
Packit 352660
	printf ("Raw pattern:\n");
Packit 352660
	FcPatternPrint (pat);
Packit 352660
	printf ("Serialized pattern:\n");
Packit 352660
	FcPatternPrint (pat_serialized);
Packit 352660
	printf ("\n");
Packit 352660
    }
Packit 352660
    return pat_serialized;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
Packit 352660
{
Packit 352660
    while (vl)
Packit 352660
    {
Packit 352660
	if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
Packit 352660
	    return FcFalse;
Packit 352660
	switch ((int) vl->value.type) {
Packit 352660
	case FcTypeString:
Packit 352660
	    if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
Packit 352660
		return FcFalse;
Packit 352660
	    break;
Packit 352660
	case FcTypeCharSet:
Packit 352660
	    if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
Packit 352660
		return FcFalse;
Packit 352660
	    break;
Packit 352660
	case FcTypeLangSet:
Packit 352660
	    if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
Packit 352660
		return FcFalse;
Packit 352660
	    break;
Packit 352660
	case FcTypeRange:
Packit 352660
	    if (!FcRangeSerializeAlloc (serialize, vl->value.u.r))
Packit 352660
		return FcFalse;
Packit 352660
	    break;
Packit 352660
	default:
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
	vl = vl->next;
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcValueList *
Packit 352660
FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
Packit 352660
{
Packit 352660
    FcValueList	*vl_serialized;
Packit 352660
    FcChar8	*s_serialized;
Packit 352660
    FcCharSet	*c_serialized;
Packit 352660
    FcLangSet	*l_serialized;
Packit 352660
    FcRange	*r_serialized;
Packit 352660
    FcValueList	*head_serialized = NULL;
Packit 352660
    FcValueList	*prev_serialized = NULL;
Packit 352660
Packit 352660
    while (vl)
Packit 352660
    {
Packit 352660
	vl_serialized = FcSerializePtr (serialize, vl);
Packit 352660
	if (!vl_serialized)
Packit 352660
	    return NULL;
Packit 352660
Packit 352660
	if (prev_serialized)
Packit 352660
	    prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
Packit 352660
							  vl_serialized,
Packit 352660
							  FcValueList);
Packit 352660
	else
Packit 352660
	    head_serialized = vl_serialized;
Packit 352660
	
Packit 352660
	vl_serialized->next = NULL;
Packit 352660
	vl_serialized->value.type = vl->value.type;
Packit 352660
	switch ((int) vl->value.type) {
Packit 352660
	case FcTypeInteger:
Packit 352660
	    vl_serialized->value.u.i = vl->value.u.i;
Packit 352660
	    break;
Packit 352660
	case FcTypeDouble:
Packit 352660
	    vl_serialized->value.u.d = vl->value.u.d;
Packit 352660
	    break;
Packit 352660
	case FcTypeString:
Packit 352660
	    s_serialized = FcStrSerialize (serialize, vl->value.u.s);
Packit 352660
	    if (!s_serialized)
Packit 352660
		return NULL;
Packit 352660
	    vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
Packit 352660
							     s_serialized,
Packit 352660
							     FcChar8);
Packit 352660
	    break;
Packit 352660
	case FcTypeBool:
Packit 352660
	    vl_serialized->value.u.b = vl->value.u.b;
Packit 352660
	    break;
Packit 352660
	case FcTypeMatrix:
Packit 352660
	    /* can't happen */
Packit 352660
	    break;
Packit 352660
	case FcTypeCharSet:
Packit 352660
	    c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
Packit 352660
	    if (!c_serialized)
Packit 352660
		return NULL;
Packit 352660
	    vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
Packit 352660
							     c_serialized,
Packit 352660
							     FcCharSet);
Packit 352660
	    break;
Packit 352660
	case FcTypeFTFace:
Packit 352660
	    /* can't happen */
Packit 352660
	    break;
Packit 352660
	case FcTypeLangSet:
Packit 352660
	    l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
Packit 352660
	    if (!l_serialized)
Packit 352660
		return NULL;
Packit 352660
	    vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
Packit 352660
							     l_serialized,
Packit 352660
							     FcLangSet);
Packit 352660
	    break;
Packit 352660
	case FcTypeRange:
Packit 352660
	    r_serialized = FcRangeSerialize (serialize, vl->value.u.r);
Packit 352660
	    if (!r_serialized)
Packit 352660
		return NULL;
Packit 352660
	    vl_serialized->value.u.r = FcPtrToEncodedOffset (&vl_serialized->value,
Packit 352660
							     r_serialized,
Packit 352660
							     FcRange);
Packit 352660
	    break;
Packit 352660
	default:
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
	prev_serialized = vl_serialized;
Packit 352660
	vl = vl->next;
Packit 352660
    }
Packit 352660
    return head_serialized;
Packit 352660
}
Packit 352660
Packit 352660
#define __fcpat__
Packit 352660
#include "fcaliastail.h"
Packit 352660
#include "fcftaliastail.h"
Packit 352660
#undef __fcpat__