|
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__
|