Blame src/fclist.c

Packit 352660
/*
Packit 352660
 * fontconfig/src/fclist.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 <stdlib.h>
Packit 352660
Packit 352660
FcObjectSet *
Packit 352660
FcObjectSetCreate (void)
Packit 352660
{
Packit 352660
    FcObjectSet    *os;
Packit 352660
Packit 352660
    os = (FcObjectSet *) malloc (sizeof (FcObjectSet));
Packit 352660
    if (!os)
Packit 352660
	return 0;
Packit 352660
    os->nobject = 0;
Packit 352660
    os->sobject = 0;
Packit 352660
    os->objects = 0;
Packit 352660
    return os;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcObjectSetAdd (FcObjectSet *os, const char *object)
Packit 352660
{
Packit 352660
    int		s;
Packit 352660
    const char	**objects;
Packit 352660
    int		high, low, mid, c;
Packit 352660
Packit 352660
    if (os->nobject == os->sobject)
Packit 352660
    {
Packit 352660
	s = os->sobject + 4;
Packit 352660
	if (os->objects)
Packit 352660
	    objects = (const char **) realloc ((void *) os->objects,
Packit 352660
					       s * sizeof (const char *));
Packit 352660
	else
Packit 352660
	    objects = (const char **) malloc (s * sizeof (const char *));
Packit 352660
	if (!objects)
Packit 352660
	    return FcFalse;
Packit 352660
	os->objects = objects;
Packit 352660
	os->sobject = s;
Packit 352660
    }
Packit 352660
    high = os->nobject - 1;
Packit 352660
    low = 0;
Packit 352660
    mid = 0;
Packit 352660
    c = 1;
Packit 352660
    object = strdup (object);
Packit 352660
    while (low <= high)
Packit 352660
    {
Packit 352660
	mid = (low + high) >> 1;
Packit 352660
	c = os->objects[mid] - object;
Packit 352660
	if (c == 0)
Packit 352660
	{
Packit 352660
	    FcFree (object);
Packit 352660
	    return FcTrue;
Packit 352660
	}
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
    memmove (os->objects + mid + 1, os->objects + mid,
Packit 352660
	     (os->nobject - mid) * sizeof (const char *));
Packit 352660
    os->objects[mid] = object;
Packit 352660
    os->nobject++;
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcObjectSetDestroy (FcObjectSet *os)
Packit 352660
{
Packit 352660
    int i;
Packit 352660
Packit 352660
    if (os->objects)
Packit 352660
    {
Packit 352660
	for (i = 0; i < os->nobject; i++)
Packit 352660
	    FcFree (os->objects[i]);
Packit 352660
Packit 352660
	free ((void *) os->objects);
Packit 352660
    }
Packit 352660
    free (os);
Packit 352660
}
Packit 352660
Packit 352660
FcObjectSet *
Packit 352660
FcObjectSetVaBuild (const char *first, va_list va)
Packit 352660
{
Packit 352660
    FcObjectSet    *ret;
Packit 352660
Packit 352660
    FcObjectSetVapBuild (ret, first, va);
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
FcObjectSet *
Packit 352660
FcObjectSetBuild (const char *first, ...)
Packit 352660
{
Packit 352660
    va_list	    va;
Packit 352660
    FcObjectSet    *os;
Packit 352660
Packit 352660
    va_start (va, first);
Packit 352660
    FcObjectSetVapBuild (os, first, va);
Packit 352660
    va_end (va);
Packit 352660
    return os;
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Font must have a containing value for every value in the pattern
Packit 352660
 */
Packit 352660
static FcBool
Packit 352660
FcListValueListMatchAny (FcValueListPtr patOrig,	    /* pattern */
Packit 352660
			 FcValueListPtr fntOrig)	    /* font */
Packit 352660
{
Packit 352660
    FcValueListPtr	 pat, fnt;
Packit 352660
Packit 352660
    for (pat = patOrig; pat != NULL; pat = FcValueListNext(pat))
Packit 352660
    {
Packit 352660
	for (fnt = fntOrig; fnt != NULL; fnt = FcValueListNext(fnt))
Packit 352660
	{
Packit 352660
	    /*
Packit 352660
	     * make sure the font 'contains' the pattern.
Packit 352660
	     * (OpListing is OpContains except for strings
Packit 352660
	     *  where it requires an exact match)
Packit 352660
	     */
Packit 352660
	    if (FcConfigCompareValue (&fnt->value,
Packit 352660
				      FC_OP (FcOpListing, FcOpFlagIgnoreBlanks),
Packit 352660
				      &pat->value))
Packit 352660
		break;
Packit 352660
	}
Packit 352660
	if (fnt == NULL)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcListValueListEqual (FcValueListPtr v1orig,
Packit 352660
		      FcValueListPtr v2orig)
Packit 352660
{
Packit 352660
    FcValueListPtr	    v1, v2;
Packit 352660
Packit 352660
    for (v1 = v1orig; v1 != NULL; v1 = FcValueListNext(v1))
Packit 352660
    {
Packit 352660
	for (v2 = v2orig; v2 != NULL; v2 = FcValueListNext(v2))
Packit 352660
	    if (FcValueEqual (FcValueCanonicalize(&(v1)->value),
Packit 352660
			      FcValueCanonicalize(&(v2)->value)))
Packit 352660
		break;
Packit 352660
	if (v2 == NULL)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    for (v2 = v2orig; v2 != NULL; v2 = FcValueListNext(v2))
Packit 352660
    {
Packit 352660
	for (v1 = v1orig; v1 != NULL; v1 = FcValueListNext(v1))
Packit 352660
	    if (FcValueEqual (FcValueCanonicalize(&v1->value),
Packit 352660
			      FcValueCanonicalize(&v2->value)))
Packit 352660
		break;
Packit 352660
	if (v1 == NULL)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcListPatternEqual (FcPattern	*p1,
Packit 352660
		    FcPattern	*p2,
Packit 352660
		    FcObjectSet	*os)
Packit 352660
{
Packit 352660
    int		    i;
Packit 352660
    FcPatternElt    *e1, *e2;
Packit 352660
Packit 352660
    for (i = 0; i < os->nobject; i++)
Packit 352660
    {
Packit 352660
	e1 = FcPatternObjectFindElt (p1, FcObjectFromName (os->objects[i]));
Packit 352660
	e2 = FcPatternObjectFindElt (p2, FcObjectFromName (os->objects[i]));
Packit 352660
	if (!e1 && !e2)
Packit 352660
	    continue;
Packit 352660
	if (!e1 || !e2)
Packit 352660
	    return FcFalse;
Packit 352660
	if (!FcListValueListEqual (FcPatternEltValues(e1),
Packit 352660
				   FcPatternEltValues(e2)))
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * FcTrue iff all objects in "p" match "font"
Packit 352660
 */
Packit 352660
Packit 352660
FcBool
Packit 352660
FcListPatternMatchAny (const FcPattern *p,
Packit 352660
		       const FcPattern *font)
Packit 352660
{
Packit 352660
    int		    i;
Packit 352660
Packit 352660
    if (!p)
Packit 352660
	return FcFalse;
Packit 352660
    for (i = 0; i < p->num; i++)
Packit 352660
    {
Packit 352660
	FcPatternElt	*pe = &FcPatternElts(p)[i];
Packit 352660
	FcPatternElt	*fe;
Packit 352660
Packit 352660
	if (pe->object == FC_NAMELANG_OBJECT)
Packit 352660
	{
Packit 352660
	    /* "namelang" object is the alias object to change "familylang",
Packit 352660
	     * "stylelang" and "fullnamelang" object alltogether. it won't be
Packit 352660
	     * available on the font pattern. so checking its availability
Packit 352660
	     * causes no results. we should ignore it here.
Packit 352660
	     */
Packit 352660
	    continue;
Packit 352660
	}
Packit 352660
	fe = FcPatternObjectFindElt (font, pe->object);
Packit 352660
	if (!fe)
Packit 352660
	    return FcFalse;
Packit 352660
	if (!FcListValueListMatchAny (FcPatternEltValues(pe),    /* pat elts */
Packit 352660
				      FcPatternEltValues(fe)))   /* font elts */
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
static FcChar32
Packit 352660
FcListMatrixHash (const FcMatrix *m)
Packit 352660
{
Packit 352660
    int	    xx = (int) (m->xx * 100),
Packit 352660
	    xy = (int) (m->xy * 100),
Packit 352660
	    yx = (int) (m->yx * 100),
Packit 352660
	    yy = (int) (m->yy * 100);
Packit 352660
Packit 352660
    return ((FcChar32) xx) ^ ((FcChar32) xy) ^ ((FcChar32) yx) ^ ((FcChar32) yy);
Packit 352660
}
Packit 352660
Packit 352660
static FcChar32
Packit 352660
FcListValueHash (FcValue    *value)
Packit 352660
{
Packit 352660
    FcValue v = FcValueCanonicalize(value);
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 (FcChar32) (int) v.u.d;
Packit 352660
    case FcTypeString:
Packit 352660
	return FcStrHashIgnoreCase (v.u.s);
Packit 352660
    case FcTypeBool:
Packit 352660
	return (FcChar32) v.u.b;
Packit 352660
    case FcTypeMatrix:
Packit 352660
	return FcListMatrixHash (v.u.m);
Packit 352660
    case FcTypeCharSet:
Packit 352660
	return FcCharSetCount (v.u.c);
Packit 352660
    case FcTypeFTFace:
Packit 352660
	return (intptr_t) v.u.f;
Packit 352660
    case FcTypeLangSet:
Packit 352660
	return FcLangSetHash (v.u.l);
Packit 352660
    case FcTypeRange:
Packit 352660
	return FcRangeHash (v.u.r);
Packit 352660
    }
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
static FcChar32
Packit 352660
FcListValueListHash (FcValueListPtr list)
Packit 352660
{
Packit 352660
    FcChar32	h = 0;
Packit 352660
Packit 352660
    while (list != NULL)
Packit 352660
    {
Packit 352660
	h = h ^ FcListValueHash (&list->value);
Packit 352660
	list = FcValueListNext(list);
Packit 352660
    }
Packit 352660
    return h;
Packit 352660
}
Packit 352660
Packit 352660
static FcChar32
Packit 352660
FcListPatternHash (FcPattern	*font,
Packit 352660
		   FcObjectSet	*os)
Packit 352660
{
Packit 352660
    int		    n;
Packit 352660
    FcPatternElt    *e;
Packit 352660
    FcChar32	    h = 0;
Packit 352660
Packit 352660
    for (n = 0; n < os->nobject; n++)
Packit 352660
    {
Packit 352660
	e = FcPatternObjectFindElt (font, FcObjectFromName (os->objects[n]));
Packit 352660
	if (e)
Packit 352660
	    h = h ^ FcListValueListHash (FcPatternEltValues(e));
Packit 352660
    }
Packit 352660
    return h;
Packit 352660
}
Packit 352660
Packit 352660
typedef struct _FcListBucket {
Packit 352660
    struct _FcListBucket    *next;
Packit 352660
    FcChar32		    hash;
Packit 352660
    FcPattern		    *pattern;
Packit 352660
} FcListBucket;
Packit 352660
Packit 352660
#define FC_LIST_HASH_SIZE   4099
Packit 352660
Packit 352660
typedef struct _FcListHashTable {
Packit 352660
    int		    entries;
Packit 352660
    FcListBucket    *buckets[FC_LIST_HASH_SIZE];
Packit 352660
} FcListHashTable;
Packit 352660
Packit 352660
static void
Packit 352660
FcListHashTableInit (FcListHashTable *table)
Packit 352660
{
Packit 352660
    table->entries = 0;
Packit 352660
    memset (table->buckets, '\0', sizeof (table->buckets));
Packit 352660
}
Packit 352660
Packit 352660
static void
Packit 352660
FcListHashTableCleanup (FcListHashTable *table)
Packit 352660
{
Packit 352660
    int	i;
Packit 352660
    FcListBucket    *bucket, *next;
Packit 352660
Packit 352660
    for (i = 0; i < FC_LIST_HASH_SIZE; i++)
Packit 352660
    {
Packit 352660
	for (bucket = table->buckets[i]; bucket; bucket = next)
Packit 352660
	{
Packit 352660
	    next = bucket->next;
Packit 352660
	    FcPatternDestroy (bucket->pattern);
Packit 352660
	    free (bucket);
Packit 352660
	}
Packit 352660
	table->buckets[i] = 0;
Packit 352660
    }
Packit 352660
    table->entries = 0;
Packit 352660
}
Packit 352660
Packit 352660
static int
Packit 352660
FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object, const FcChar8 *lang)
Packit 352660
{
Packit 352660
    FcPatternElt   *e = FcPatternObjectFindElt (font, object);
Packit 352660
    FcValueListPtr  v;
Packit 352660
    FcValue         value;
Packit 352660
    int             idx = -1;
Packit 352660
    int             defidx = -1;
Packit 352660
    int             i;
Packit 352660
Packit 352660
    if (e)
Packit 352660
    {
Packit 352660
	for (v = FcPatternEltValues(e), i = 0; v; v = FcValueListNext(v), ++i)
Packit 352660
	{
Packit 352660
	    value = FcValueCanonicalize (&v->value);
Packit 352660
Packit 352660
	    if (value.type == FcTypeString)
Packit 352660
	    {
Packit 352660
		FcLangResult res = FcLangCompare (value.u.s, lang);
Packit 352660
		if (res == FcLangEqual)
Packit 352660
		    return i;
Packit 352660
Packit 352660
		if (res == FcLangDifferentCountry && idx < 0)
Packit 352660
		    idx = i;
Packit 352660
		if (defidx < 0)
Packit 352660
		{
Packit 352660
		    /* workaround for fonts that has non-English value
Packit 352660
		     * at the head of values.
Packit 352660
		     */
Packit 352660
		    res = FcLangCompare (value.u.s, (FcChar8 *)"en");
Packit 352660
		    if (res == FcLangEqual)
Packit 352660
			defidx = i;
Packit 352660
		}
Packit 352660
	    }
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    return (idx > 0) ? idx : (defidx > 0) ? defidx : 0;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcListAppend (FcListHashTable	*table,
Packit 352660
	      FcPattern		*font,
Packit 352660
	      FcObjectSet	*os,
Packit 352660
	      const FcChar8	*lang)
Packit 352660
{
Packit 352660
    int		    o;
Packit 352660
    FcPatternElt    *e;
Packit 352660
    FcValueListPtr  v;
Packit 352660
    FcChar32	    hash;
Packit 352660
    FcListBucket    **prev, *bucket;
Packit 352660
    int             familyidx = -1;
Packit 352660
    int             fullnameidx = -1;
Packit 352660
    int             styleidx = -1;
Packit 352660
    int             defidx = 0;
Packit 352660
    int             idx;
Packit 352660
Packit 352660
    hash = FcListPatternHash (font, os);
Packit 352660
    for (prev = &table->buckets[hash % FC_LIST_HASH_SIZE];
Packit 352660
	 (bucket = *prev); prev = &(bucket->next))
Packit 352660
    {
Packit 352660
	if (bucket->hash == hash &&
Packit 352660
	    FcListPatternEqual (bucket->pattern, font, os))
Packit 352660
	    return FcTrue;
Packit 352660
    }
Packit 352660
    bucket = (FcListBucket *) malloc (sizeof (FcListBucket));
Packit 352660
    if (!bucket)
Packit 352660
	goto bail0;
Packit 352660
    bucket->next = 0;
Packit 352660
    bucket->hash = hash;
Packit 352660
    bucket->pattern = FcPatternCreate ();
Packit 352660
    if (!bucket->pattern)
Packit 352660
	goto bail1;
Packit 352660
Packit 352660
    for (o = 0; o < os->nobject; o++)
Packit 352660
    {
Packit 352660
	if (!strcmp (os->objects[o], FC_FAMILY) || !strcmp (os->objects[o], FC_FAMILYLANG))
Packit 352660
	{
Packit 352660
	    if (familyidx < 0)
Packit 352660
		familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT, lang);
Packit 352660
	    defidx = familyidx;
Packit 352660
	}
Packit 352660
	else if (!strcmp (os->objects[o], FC_FULLNAME) || !strcmp (os->objects[o], FC_FULLNAMELANG))
Packit 352660
	{
Packit 352660
	    if (fullnameidx < 0)
Packit 352660
		fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT, lang);
Packit 352660
	    defidx = fullnameidx;
Packit 352660
	}
Packit 352660
	else if (!strcmp (os->objects[o], FC_STYLE) || !strcmp (os->objects[o], FC_STYLELANG))
Packit 352660
	{
Packit 352660
	    if (styleidx < 0)
Packit 352660
		styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT, lang);
Packit 352660
	    defidx = styleidx;
Packit 352660
	}
Packit 352660
	else
Packit 352660
	    defidx = 0;
Packit 352660
Packit 352660
	e = FcPatternObjectFindElt (font, FcObjectFromName (os->objects[o]));
Packit 352660
	if (e)
Packit 352660
	{
Packit 352660
	    for (v = FcPatternEltValues(e), idx = 0; v;
Packit 352660
		 v = FcValueListNext(v), ++idx)
Packit 352660
	    {
Packit 352660
		if (!FcPatternAdd (bucket->pattern,
Packit 352660
				   os->objects[o],
Packit 352660
				   FcValueCanonicalize(&v->value), defidx != idx))
Packit 352660
		    goto bail2;
Packit 352660
	    }
Packit 352660
	}
Packit 352660
    }
Packit 352660
    *prev = bucket;
Packit 352660
    ++table->entries;
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
Packit 352660
bail2:
Packit 352660
    FcPatternDestroy (bucket->pattern);
Packit 352660
bail1:
Packit 352660
    free (bucket);
Packit 352660
bail0:
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
FcFontSet *
Packit 352660
FcFontSetList (FcConfig	    *config,
Packit 352660
	       FcFontSet    **sets,
Packit 352660
	       int	    nsets,
Packit 352660
	       FcPattern    *p,
Packit 352660
	       FcObjectSet  *os)
Packit 352660
{
Packit 352660
    FcFontSet	    *ret;
Packit 352660
    FcFontSet	    *s;
Packit 352660
    int		    f;
Packit 352660
    int		    set;
Packit 352660
    FcListHashTable table;
Packit 352660
    int		    i;
Packit 352660
    FcListBucket    *bucket;
Packit 352660
    int             destroy_os = 0;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	if (!FcInitBringUptoDate ())
Packit 352660
	    goto bail0;
Packit 352660
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    goto bail0;
Packit 352660
    }
Packit 352660
    FcListHashTableInit (&table);
Packit 352660
Packit 352660
    if (!os)
Packit 352660
    {
Packit 352660
	os = FcObjectGetSet ();
Packit 352660
	destroy_os = 1;
Packit 352660
    }
Packit 352660
Packit 352660
    /*
Packit 352660
     * Walk all available fonts adding those that
Packit 352660
     * match to the hash table
Packit 352660
     */
Packit 352660
    for (set = 0; set < nsets; set++)
Packit 352660
    {
Packit 352660
	s = sets[set];
Packit 352660
	if (!s)
Packit 352660
	    continue;
Packit 352660
	for (f = 0; f < s->nfont; f++)
Packit 352660
	    if (FcListPatternMatchAny (p,		/* pattern */
Packit 352660
				       s->fonts[f]))	/* font */
Packit 352660
	    {
Packit 352660
		FcChar8 *lang;
Packit 352660
Packit 352660
		if (FcPatternObjectGetString (p, FC_NAMELANG_OBJECT, 0, &lang) != FcResultMatch)
Packit 352660
		{
Packit 352660
			lang = FcGetDefaultLang ();
Packit 352660
		}
Packit 352660
		if (!FcListAppend (&table, s->fonts[f], os, lang))
Packit 352660
		    goto bail1;
Packit 352660
	    }
Packit 352660
    }
Packit 352660
#if 0
Packit 352660
    {
Packit 352660
	int	max = 0;
Packit 352660
	int	full = 0;
Packit 352660
	int	ents = 0;
Packit 352660
	int	len;
Packit 352660
	for (i = 0; i < FC_LIST_HASH_SIZE; i++)
Packit 352660
	{
Packit 352660
	    if ((bucket = table.buckets[i]))
Packit 352660
	    {
Packit 352660
		len = 0;
Packit 352660
		for (; bucket; bucket = bucket->next)
Packit 352660
		{
Packit 352660
		    ents++;
Packit 352660
		    len++;
Packit 352660
		}
Packit 352660
		if (len > max)
Packit 352660
		    max = len;
Packit 352660
		full++;
Packit 352660
	    }
Packit 352660
	}
Packit 352660
	printf ("used: %d max: %d avg: %g\n", full, max,
Packit 352660
		(double) ents / FC_LIST_HASH_SIZE);
Packit 352660
    }
Packit 352660
#endif
Packit 352660
    /*
Packit 352660
     * Walk the hash table and build
Packit 352660
     * a font set
Packit 352660
     */
Packit 352660
    ret = FcFontSetCreate ();
Packit 352660
    if (!ret)
Packit 352660
	goto bail0;
Packit 352660
    for (i = 0; i < FC_LIST_HASH_SIZE; i++)
Packit 352660
	while ((bucket = table.buckets[i]))
Packit 352660
	{
Packit 352660
	    if (!FcFontSetAdd (ret, bucket->pattern))
Packit 352660
		goto bail2;
Packit 352660
	    table.buckets[i] = bucket->next;
Packit 352660
	    free (bucket);
Packit 352660
	}
Packit 352660
Packit 352660
    if (destroy_os)
Packit 352660
        FcObjectSetDestroy (os);
Packit 352660
Packit 352660
    return ret;
Packit 352660
Packit 352660
bail2:
Packit 352660
    FcFontSetDestroy (ret);
Packit 352660
bail1:
Packit 352660
    FcListHashTableCleanup (&table);
Packit 352660
bail0:
Packit 352660
    if (destroy_os)
Packit 352660
	FcObjectSetDestroy (os);
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
FcFontSet *
Packit 352660
FcFontList (FcConfig	*config,
Packit 352660
	    FcPattern	*p,
Packit 352660
	    FcObjectSet *os)
Packit 352660
{
Packit 352660
    FcFontSet	*sets[2];
Packit 352660
    int		nsets;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	if (!FcInitBringUptoDate ())
Packit 352660
	    return 0;
Packit 352660
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return 0;
Packit 352660
    }
Packit 352660
    nsets = 0;
Packit 352660
    if (config->fonts[FcSetSystem])
Packit 352660
	sets[nsets++] = config->fonts[FcSetSystem];
Packit 352660
    if (config->fonts[FcSetApplication])
Packit 352660
	sets[nsets++] = config->fonts[FcSetApplication];
Packit 352660
    return FcFontSetList (config, sets, nsets, p, os);
Packit 352660
}
Packit 352660
#define __fclist__
Packit 352660
#include "fcaliastail.h"
Packit 352660
#undef __fclist__