Change FcCharSet datastructure, add FcFontSort API

This commit is contained in:
Keith Packard 2002-05-31 04:42:42 +00:00
parent bc9469baad
commit 20ac65ab00
4 changed files with 455 additions and 387 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $XFree86: xc/lib/fontconfig/fontconfig/fontconfig.h,v 1.11 2002/05/24 05:20:02 keithp Exp $ * $XFree86: xc/lib/fontconfig/fontconfig/fontconfig.h,v 1.12 2002/05/29 08:21:33 keithp Exp $
* *
* Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
* *
@ -516,6 +516,13 @@ FcFontSetSort (FcConfig *config,
FcCharSet **csp, FcCharSet **csp,
FcResult *result); FcResult *result);
FcFontSet *
FcFontSort (FcConfig *config,
FcPattern *p,
FcBool trim,
FcCharSet **csp,
FcResult *result);
void void
FcFontSetSortDestroy (FcFontSet *fs); FcFontSetSortDestroy (FcFontSet *fs);

View File

@ -1,5 +1,5 @@
/* /*
* $XFree86: xc/lib/fontconfig/src/fccharset.c,v 1.8 2002/05/29 08:21:33 keithp Exp $ * $XFree86: xc/lib/fontconfig/src/fccharset.c,v 1.9 2002/05/29 22:07:33 keithp Exp $
* *
* Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
* *
@ -27,53 +27,7 @@
/* #define CHECK */ /* #define CHECK */
static int /* #define CHATTY */
FcCharSetLevels (FcChar32 ucs4)
{
if (ucs4 <= 0xff)
return 1;
if (ucs4 <= 0xffff)
return 2;
if (ucs4 <= 0xffffff)
return 3;
return 4;
}
static FcBool
FcCharSetCheckLevel (FcCharSet *fcs, FcChar32 ucs4)
{
int level = FcCharSetLevels (ucs4);
if (level <= fcs->levels)
return FcTrue;
while (fcs->levels < level)
{
if (fcs->levels == 0)
{
FcCharLeaf *leaf;
leaf = (FcCharLeaf *) calloc (1, sizeof (FcCharLeaf));
if (!leaf)
return FcFalse;
FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharLeaf));
fcs->node.leaf = leaf;
}
else
{
FcCharBranch *branch;
branch = (FcCharBranch *) calloc (1, sizeof (FcCharBranch));
if (!branch)
return FcFalse;
FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharBranch));
branch->nodes[0] = fcs->node;
/* next pointers are all zero */
fcs->node.branch = branch;
}
++fcs->levels;
}
return FcTrue;
}
FcCharSet * FcCharSet *
FcCharSetCreate (void) FcCharSetCreate (void)
@ -85,8 +39,9 @@ FcCharSetCreate (void)
return 0; return 0;
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet)); FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
fcs->ref = 1; fcs->ref = 1;
fcs->levels = 0; fcs->num = 0;
fcs->node.leaf = 0; fcs->leaves = 0;
fcs->numbers = 0;
fcs->constant = FcFalse; fcs->constant = FcFalse;
return fcs; return fcs;
} }
@ -100,64 +55,111 @@ FcCharSetNew (void)
return FcCharSetCreate (); return FcCharSetCreate ();
} }
static void
FcCharNodeDestroy (FcCharNode node, int level)
{
int i;
switch (level) {
case 0:
break;
case 1:
FcMemFree (FC_MEM_CHARNODE, sizeof (FcCharLeaf));
free (node.leaf);
break;
default:
for (i = 0; i < 256; i++)
if (node.branch->nodes[i].branch)
FcCharNodeDestroy (node.branch->nodes[i], level - 1);
FcMemFree (FC_MEM_CHARNODE, sizeof (FcCharBranch));
free (node.branch);
}
}
void void
FcCharSetDestroy (FcCharSet *fcs) FcCharSetDestroy (FcCharSet *fcs)
{ {
if (fcs->constant) if (!fcs->constant && --fcs->ref <= 0)
return;
if (--fcs->ref <= 0)
{ {
FcCharNodeDestroy (fcs->node, fcs->levels); int i;
for (i = 0; i < fcs->num; i++)
{
FcMemFree (FC_MEM_CHARNODE, sizeof (FcCharLeaf));
free (fcs->leaves[i]);
}
if (fcs->leaves)
{
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
free (fcs->leaves);
}
if (fcs->numbers)
{
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
free (fcs->numbers);
}
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet)); FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (fcs); free (fcs);
} }
} }
/* /*
* Locate the leaf containing the specified char, returning * Locate the leaf containing the specified char, return
* null if it doesn't exist * its index if it exists, otherwise return negative of
* the (position + 1) where it should be inserted
*/ */
static int
FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
{
FcChar16 *numbers = fcs->numbers;
FcChar16 page;
int low = 0;
int high = fcs->num - 1;
if (!numbers)
return -1;
ucs4 >>= 8;
while (low <= high)
{
int mid = (low + high) >> 1;
page = numbers[mid];
if (page == ucs4)
return mid;
if (page < ucs4)
low = mid + 1;
else
high = mid - 1;
}
if (numbers[high] < ucs4)
high++;
return -(high + 1);
}
static FcCharLeaf * static FcCharLeaf *
FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4) FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4)
{ {
int l; int pos = FcCharSetFindLeafPos (fcs, ucs4);
const FcCharNode *prev; if (pos >= 0)
FcCharNode node; return fcs->leaves[pos];
FcChar32 i;
prev = &fcs->node;
l = fcs->levels;
while (--l > 0)
{
node = *prev;
if (!node.branch)
return 0; return 0;
i = (ucs4 >> (l << 3)) & 0xff;
prev = &node.branch->nodes[i];
} }
return prev->leaf;
static FcBool
FcCharSetPutLeaf (FcCharSet *fcs,
FcChar32 ucs4,
FcCharLeaf *leaf,
int pos)
{
FcCharLeaf **leaves;
FcChar16 *numbers;
ucs4 >>= 8;
if (ucs4 >= 0x10000)
return FcFalse;
if (!fcs->leaves)
leaves = malloc (sizeof (FcCharLeaf *));
else
leaves = realloc (fcs->leaves, (fcs->num + 1) * sizeof (FcCharLeaf *));
if (!leaves)
return FcFalse;
fcs->leaves = leaves;
if (!fcs->numbers)
numbers = malloc (sizeof (FcChar16));
else
numbers = realloc (fcs->numbers, (fcs->num + 1) * sizeof (FcChar16));
if (!numbers)
return FcFalse;
fcs->numbers = numbers;
memmove (fcs->leaves + pos + 1, fcs->leaves + pos,
(fcs->num - pos) * sizeof (FcCharLeaf *));
memmove (fcs->numbers + pos + 1, fcs->numbers + pos,
(fcs->num - pos) * sizeof (FcChar16));
fcs->numbers[pos] = (FcChar16) ucs4;
fcs->leaves[pos] = leaf;
fcs->num++;
return FcTrue;
} }
/* /*
@ -168,54 +170,41 @@ FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4)
static FcCharLeaf * static FcCharLeaf *
FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4) FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4)
{ {
int l; int pos;
FcCharNode *prev, node; FcCharLeaf *leaf;
FcChar32 i = 0;
int j;
FcChar8 *next = 0, old;
if (!FcCharSetCheckLevel (fcs, ucs4)) pos = FcCharSetFindLeafPos (fcs, ucs4);
return FcFalse; if (pos >= 0)
prev = &fcs->node; return fcs->leaves[pos];
l = fcs->levels;
while (--l > 0) leaf = calloc (1, sizeof (FcCharLeaf));
{ if (!leaf)
node = *prev;
if (!node.branch)
{
node.branch = calloc (1, sizeof (FcCharBranch));
if (!node.branch)
return 0; return 0;
FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharBranch));
*prev = node; pos = -pos - 1;
if (next) if (!FcCharSetPutLeaf (fcs, ucs4, leaf, pos))
{ {
old = next[i]; free (leaf);
for (j = (int) i - 1; j >= 0 && next[j] == old; j--)
next[j] = i;
}
}
i = (ucs4 >> (l << 3)) & 0xff;
prev = &node.branch->nodes[i];
next = &node.branch->next[0];
}
node = *prev;
if (!node.leaf)
{
node.leaf = calloc (1, sizeof (FcCharLeaf));
if (!node.leaf)
return 0; return 0;
}
return leaf;
}
static FcBool
FcCharSetInsertLeaf (FcCharSet *fcs, FcChar32 ucs4, FcCharLeaf *leaf)
{
int pos;
pos = FcCharSetFindLeafPos (fcs, ucs4);
if (pos >= 0)
{
FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharLeaf)); FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharLeaf));
*prev = node; free (fcs->leaves[pos]);
ucs4 = ucs4 & ~0xff; fcs->leaves[pos] = leaf;
if (next) return FcTrue;
{
old = next[i];
for (j = i - 1; j >= 0 && next[j] == old; j--)
next[j] = i;
} }
} pos = -pos - 1;
return node.leaf; return FcCharSetPutLeaf (fcs, ucs4, leaf, pos);
} }
FcBool FcBool
@ -241,188 +230,75 @@ FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4)
typedef struct _fcCharSetIter { typedef struct _fcCharSetIter {
FcCharLeaf *leaf; FcCharLeaf *leaf;
FcChar32 ucs4; FcChar32 ucs4;
FcCharBranch *branch_stack[5]; int pos;
int branch_stackp;
} FcCharSetIter; } FcCharSetIter;
/* /*
* Find the nearest leaf at or beyond *ucs4, return 0 if no leaf * Set iter->leaf to the leaf containing iter->ucs4 or higher
* exists
*/ */
static FcCharLeaf *
FcCharSetIterLeaf (FcCharNode node, int level, FcChar32 *ucs4)
{
if (level <= 1)
return node.leaf;
else if (!node.branch)
return 0;
else
{
int shift = ((level - 1) << 3);
FcChar32 inc = 1 << shift;
FcChar32 mask = ~(inc - 1);
FcChar32 byte = (*ucs4 >> shift) & 0xff;
FcCharLeaf *leaf;
for (;;)
{
leaf = FcCharSetIterLeaf (node.branch->nodes[byte],
level - 1,
ucs4);
if (leaf)
break;
/* step to next branch, resetting lower indices */
*ucs4 = (*ucs4 & mask) + inc;
byte = (byte + 1) & 0xff;
if (byte == 0)
break;
}
return leaf;
}
}
static void static void
FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter) FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter)
{ {
int level = fcs->levels; int pos = FcCharSetFindLeafPos (fcs, iter->ucs4);
FcChar32 ucs4 = iter->ucs4;
FcCharNode node = fcs->node;
iter->branch_stackp = 0; if (pos < 0)
if (ucs4 >= 1 << (level << 3)) {
pos = -pos - 1;
if (pos == fcs->num)
{ {
iter->leaf = 0;
iter->ucs4 = ~0; iter->ucs4 = ~0;
iter->leaf = 0;
return; return;
} }
if (level > 1) iter->ucs4 = (FcChar32) fcs->numbers[pos] << 8;
{
level--;
for (;;)
{
FcCharBranch *branch = node.branch;
FcChar32 byte;
byte = (ucs4 >> (level << 3)) & 0xff;
node = branch->nodes[byte];
if (!node.leaf)
{
while (!(byte = branch->next[byte]))
{
if (iter->branch_stackp == 0)
{
iter->leaf = 0;
iter->ucs4 = ~0;
return;
} }
branch = node.branch = iter->branch_stack[--iter->branch_stackp]; iter->leaf = fcs->leaves[pos];
level++; iter->pos = pos;
ucs4 += 1 << (level << 3); #ifdef CHATTY
byte = (ucs4 >> (level << 3)) & 0xff; printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf);
}
ucs4 = (ucs4 & ~ ((1 << ((level + 1) << 3)) - 1)) |
(byte << (level << 3));
node = branch->nodes[byte];
}
iter->branch_stack[iter->branch_stackp++] = branch;
if (--level == 0)
break;
}
}
if (!(iter->leaf = node.leaf))
ucs4 = ~0;
iter->ucs4 = ucs4;
#if 0
printf ("set %08x: %08x\n", ucs4, node.leaf);
#endif #endif
} }
static void static void
FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter) FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter)
{ {
FcCharNode node; int pos = iter->pos + 1;
FcCharBranch *branch; if (pos >= fcs->num)
FcChar32 ucs4;
int level;
if (!iter->branch_stackp)
{ {
iter->ucs4 = ~0; iter->ucs4 = ~0;
iter->leaf = 0; iter->leaf = 0;
return;
}
level = 1;
node.branch = iter->branch_stack[--iter->branch_stackp];
ucs4 = iter->ucs4;
for (;;)
{
FcChar32 byte;
branch = node.branch;
while (!(byte = branch->next[(ucs4 >> (level << 3)) & 0xff]))
{
if (iter->branch_stackp == 0)
{
iter->leaf = 0;
iter->ucs4 = ~0;
return;
}
branch = node.branch = iter->branch_stack[--iter->branch_stackp];
level++;
ucs4 += 1 << (level << 3);
}
ucs4 = (ucs4 & ~ ((1 << ((level + 1) << 3)) - 1)) |
(byte << (level << 3));
node = branch->nodes[byte];
iter->branch_stack[iter->branch_stackp++] = branch;
if (--level == 0)
break;
}
iter->ucs4 = ucs4;
iter->leaf = node.leaf;
}
#if 0
static void
FcCharSetDump (FcCharNode node, int level, FcChar32 ucs4, int indent)
{
if (level)
{
if (node.branch)
{
FcChar32 inc = (1 << (level << 3));
int i;
FcCharBranch *branch = node.branch;
for (i = 0; i < indent; i++)
printf (" ");
printf ("%08x: %08x\n", ucs4, branch);
for (i = 0; i < 256; i++)
{
FcCharSetDump (branch->nodes[i], level - 1, ucs4, indent+1);
ucs4 += inc;
}
}
} }
else else
{ {
if (node.leaf) iter->ucs4 = (FcChar32) fcs->numbers[pos] << 8;
{ iter->leaf = fcs->leaves[pos];
while (indent--) iter->pos = pos;
printf (" ");
printf ("%08x: %08x\n", ucs4, node.leaf);
} }
} }
#ifdef CHATTY
static void
FcCharSetDump (const FcCharSet *fcs)
{
int pos;
printf ("fcs %08x:\n", (FcChar32) fcs);
for (pos = 0; pos < fcs->num; pos++)
{
FcCharLeaf *leaf = fcs->leaves[pos];
FcChar32 ucs4 = (FcChar32) fcs->numbers[pos] << 8;
printf (" %08x: %08x\n", ucs4, (FcChar32) leaf);
}
} }
#endif #endif
static void static void
FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter) FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
{ {
#if 0 #ifdef CHATTY
FcCharSetDump (fcs->node, fcs->levels - 1, 0, 0); FcCharSetDump (fcs);
#endif #endif
iter->ucs4 = 0; iter->ucs4 = 0;
FcCharSetIterSet (fcs, iter); FcCharSetIterSet (fcs, iter);
@ -697,93 +573,61 @@ FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b)
return count; return count;
} }
typedef struct {
FcCharBranch *ab, *bb;
FcChar32 byte;
} FcCharSetPairStack;
/* /*
* return FcTrue iff a is a subset of b * return FcTrue iff a is a subset of b
*/ */
FcBool FcBool
FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b) FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
{ {
FcCharSetPairStack stack[5], *stackp; int ai, bi;
FcChar32 byte; FcChar16 an, bn;
FcCharBranch *ab, *bb;
int level;
FcCharNode an, bn;
if (a->levels > b->levels) if (a == b) return FcTrue;
return FcFalse; bi = 0;
ai = 0;
level = b->levels; while (ai < a->num && bi < b->num)
an = a->node;
bn = b->node;
while (level != a->levels)
{ {
bn = bn.branch->nodes[0]; an = a->numbers[ai];
level--; bn = b->numbers[bi];
} if (an == bn)
{
if (level == 0) FcChar32 *am = a->leaves[ai]->map;
; FcChar32 *bm = b->leaves[bi]->map;
if (level == 1)
if (am != bm)
{ {
FcChar32 *am = an.leaf->map;
FcChar32 *bm = bn.leaf->map;
int i = 256/32; int i = 256/32;
while (i--) while (i--)
if (*am++ & ~*bm++) if (*am++ & ~*bm++)
return FcFalse; return FcFalse;
} }
ai++;
bi++;
}
else if (an < bn)
return FcFalse;
else else
{ {
byte = 0; int low = bi + 1;
stackp = stack; int high = b->num - 1;
ab = an.branch;
bb = bn.branch;
for (;;)
{
an = ab->nodes[byte];
if (an.branch)
{
bn = bb->nodes[byte];
if (!bn.branch)
return FcFalse;
if (level == 2)
{
FcChar32 *am = an.leaf->map;
FcChar32 *bm = bn.leaf->map;
int i = 256/32;
while (i--) while (low <= high)
if (*am++ & ~*bm++)
return FcFalse;
}
else
{ {
level--; int mid = (low + high) >> 1;
stackp->ab = ab; bn = b->numbers[mid];
stackp->bb = bb; if (bn == an)
stackp->byte = byte;
stackp++;
byte = 0;
continue;
}
}
byte = ab->next[byte];
if (!byte)
{ {
if (stackp == stack) high = mid;
break; break;
level++;
--stackp;
ab = stackp->ab;
bb = stackp->bb;
byte = stackp->byte;
} }
if (bn < an)
low = mid + 1;
else
high = mid - 1;
}
bi = high;
while (bi < b->num && b->numbers[bi] < an)
bi++;
} }
} }
return FcTrue; return FcTrue;
@ -830,6 +674,33 @@ FcCharSetFirstPage (const FcCharSet *a,
return FcCharSetNextPage (a, map, next); return FcCharSetNextPage (a, map, next);
} }
/*
* old coverage API, rather hard to use correctly
*/
FcChar32
FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result);
FcChar32
FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result)
{
FcCharSetIter ai;
ai.ucs4 = page;
FcCharSetIterSet (a, &ai);
if (!ai.leaf)
{
memset (result, '\0', 256 / 8);
page = 0;
}
else
{
memcpy (result, ai.leaf->map, sizeof (ai.leaf->map));
FcCharSetIterNext (a, &ai);
page = ai.ucs4;
}
return page;
}
/* /*
* ASCII representation of charsets. * ASCII representation of charsets.
* *
@ -943,12 +814,159 @@ FcCharSetUnparseValue (FcStrBuf *buf, FcChar32 value)
return FcTrue; return FcTrue;
} }
typedef struct _FcCharLeafEnt FcCharLeafEnt;
struct _FcCharLeafEnt {
FcCharLeafEnt *next;
FcChar32 hash;
FcCharLeaf leaf;
};
#define FC_CHAR_LEAF_BLOCK (4096 / sizeof (FcCharLeafEnt))
static FcCharLeafEnt *
FcCharLeafEntCreate (void)
{
static FcCharLeafEnt *block;
static int remain;
if (!remain)
{
block = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
if (!block)
return 0;
remain = FC_CHAR_LEAF_BLOCK;
}
remain--;
return block++;
}
#define FC_CHAR_LEAF_HASH_SIZE 257
static FcChar32
FcCharLeafHash (FcCharLeaf *leaf)
{
FcChar32 hash = 0;
int i;
for (i = 0; i < 256/32; i++)
hash = ((hash << 1) | (hash >> 31)) ^ leaf->map[i];
return hash;
}
static int FcCharLeafTotal;
static int FcCharLeafUsed;
static FcCharLeaf *
FcNameParseBuildLeaf (FcCharLeaf *leaf)
{
static FcCharLeafEnt *hashTable[FC_CHAR_LEAF_HASH_SIZE];
FcChar32 hash = FcCharLeafHash (leaf);
FcCharLeafEnt **bucket = &hashTable[hash % FC_CHAR_LEAF_HASH_SIZE];
FcCharLeafEnt *ent;
FcCharLeafTotal++;
for (ent = *bucket; ent; ent = ent->next)
{
if (ent->hash == hash && !memcmp (&ent->leaf, leaf, sizeof (FcCharLeaf)))
return &ent->leaf;
}
ent = FcCharLeafEntCreate();
if (!ent)
return 0;
FcCharLeafUsed++;
ent->leaf = *leaf;
ent->hash = hash;
ent->next = *bucket;
*bucket = ent;
return &ent->leaf;
}
typedef struct _FcCharSetEnt FcCharSetEnt;
struct _FcCharSetEnt {
FcCharSetEnt *next;
FcChar32 hash;
FcCharSet set;
};
#define FC_CHAR_SET_HASH_SIZE 67
static FcChar32
FcCharSetHash (FcCharSet *fcs)
{
FcChar32 hash = 0;
FcChar32 *p;
int i;
/* hash in leaves */
p = (FcChar32 *) fcs->leaves;
for (i = 0; i < fcs->num * sizeof (FcCharLeaf *) / sizeof (FcChar32); i++)
hash = ((hash << 1) | (hash >> 31)) ^ *p++;
/* hash in numbers */
for (i = 0; i < fcs->num; i++)
hash = ((hash << 1) | (hash >> 31)) ^ fcs->numbers[i];
return hash;
}
static int FcCharSetTotal;
static int FcCharSetUsed;
static int FcCharSetTotalEnts, FcCharSetUsedEnts;
static FcCharSet *
FcNameParseBuildSet (FcCharSet *fcs)
{
static FcCharSetEnt *hashTable[FC_CHAR_SET_HASH_SIZE];
FcChar32 hash = FcCharSetHash (fcs);
FcCharSetEnt **bucket = &hashTable[hash % FC_CHAR_SET_HASH_SIZE];
FcCharSetEnt *ent;
FcCharSetTotal++;
FcCharSetTotalEnts += fcs->num;
for (ent = *bucket; ent; ent = ent->next)
{
if (ent->hash == hash &&
ent->set.num == fcs->num &&
!memcmp (ent->set.leaves, fcs->leaves,
fcs->num * sizeof (FcCharLeaf *)) &&
!memcmp (ent->set.numbers, fcs->numbers,
fcs->num * sizeof (FcChar16)))
{
return &ent->set;
}
}
ent = malloc (sizeof (FcCharSetEnt) +
fcs->num * sizeof (FcCharLeaf *) +
fcs->num * sizeof (FcChar16));
if (!ent)
return 0;
FcCharSetUsed++;
FcCharSetUsedEnts += fcs->num;
ent->set.ref = 0;
ent->set.constant = FcTrue;
ent->set.num = fcs->num;
ent->set.leaves = (FcCharLeaf **) (ent + 1);
ent->set.numbers = (FcChar16 *) (ent->set.leaves + fcs->num);
memcpy (ent->set.leaves, fcs->leaves, fcs->num * sizeof (FcCharLeaf *));
memcpy (ent->set.numbers, fcs->numbers, fcs->num * sizeof (FcChar16));
ent->hash = hash;
ent->next = *bucket;
*bucket = ent;
return &ent->set;
}
FcCharSet * FcCharSet *
FcNameParseCharSet (FcChar8 *string) FcNameParseCharSet (FcChar8 *string)
{ {
FcCharSet *c; FcCharSet *c, *n = 0;
FcChar32 ucs4; FcChar32 ucs4;
FcCharLeaf *leaf; FcCharLeaf *leaf;
FcCharLeaf temp;
FcChar32 bits;
int i; int i;
c = FcCharSetCreate (); c = FcCharSetCreate ();
@ -959,21 +977,53 @@ FcNameParseCharSet (FcChar8 *string)
string = FcCharSetParseValue (string, &ucs4); string = FcCharSetParseValue (string, &ucs4);
if (!string) if (!string)
goto bail1; goto bail1;
leaf = FcCharSetFindLeafCreate (c, ucs4); bits = 0;
if (!leaf)
goto bail1;
for (i = 0; i < 256/32; i++) for (i = 0; i < 256/32; i++)
{ {
string = FcCharSetParseValue (string, &leaf->map[i]); string = FcCharSetParseValue (string, &temp.map[i]);
if (!string) if (!string)
goto bail1; goto bail1;
bits |= temp.map[i];
}
if (bits)
{
leaf = FcNameParseBuildLeaf (&temp);
if (!leaf)
goto bail1;
if (!FcCharSetInsertLeaf (c, ucs4, leaf))
goto bail1;
} }
} }
return c; #ifdef CHATTY
printf (" %8s %8s %8s %8s\n", "total", "totalmem", "new", "newmem");
printf ("Leaves: %8d %8d %8d %8d\n",
FcCharLeafTotal, sizeof (FcCharLeaf) * FcCharLeafTotal,
FcCharLeafUsed, sizeof (FcCharLeaf) * FcCharLeafUsed);
printf ("Charsets: %8d %8d %8d %8d\n",
FcCharSetTotal, sizeof (FcCharSet) * FcCharSetTotal,
FcCharSetUsed, sizeof (FcCharSet) * FcCharSetUsed);
printf ("Tables: %8d %8d %8d %8d\n",
FcCharSetTotalEnts, FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
FcCharSetUsedEnts, FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
printf ("Total: %8s %8d %8s %8d\n",
"",
sizeof (FcCharLeaf) * FcCharLeafTotal +
sizeof (FcCharSet) * FcCharSetTotal +
FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
"",
sizeof (FcCharLeaf) * FcCharLeafUsed +
sizeof (FcCharSet) * FcCharSetUsed +
FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
#endif
n = FcNameParseBuildSet (c);
bail1: bail1:
FcCharSetDestroy (c); if (c->leaves)
free (c->leaves);
if (c->numbers)
free (c->numbers);
free (c);
bail0: bail0:
return 0; return n;
} }
FcBool FcBool

View File

@ -1,5 +1,5 @@
/* /*
* $XFree86: xc/lib/fontconfig/src/fcint.h,v 1.8 2002/05/21 17:06:22 keithp Exp $ * $XFree86: xc/lib/fontconfig/src/fcint.h,v 1.10 2002/05/29 22:07:33 keithp Exp $
* *
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
* *
@ -157,29 +157,16 @@ typedef struct _FcSubst {
FcEdit *edit; FcEdit *edit;
} FcSubst; } FcSubst;
typedef struct _FcCharLeaf FcCharLeaf; typedef struct _FcCharLeaf {
typedef struct _FcCharBranch FcCharBranch;
typedef union _FcCharNode FcCharNode;
struct _FcCharLeaf {
FcChar32 map[256/32]; FcChar32 map[256/32];
}; } FcCharLeaf;
union _FcCharNode {
FcCharBranch *branch;
FcCharLeaf *leaf;
};
struct _FcCharBranch {
FcCharNode nodes[256];
FcChar8 next[256];
};
struct _FcCharSet { struct _FcCharSet {
int levels;
int ref; /* reference count */ int ref; /* reference count */
FcBool constant; /* shared constant */ FcBool constant; /* in hash table constant */
FcCharNode node; int num; /* size of leaves and numbers arrays */
FcCharLeaf **leaves;
FcChar16 *numbers;
}; };
struct _FcStrSet { struct _FcStrSet {

View File

@ -1,5 +1,5 @@
/* /*
* $XFree86: xc/lib/fontconfig/src/fcmatch.c,v 1.6 2002/05/29 08:21:33 keithp Exp $ * $XFree86: xc/lib/fontconfig/src/fcmatch.c,v 1.7 2002/05/29 22:07:33 keithp Exp $
* *
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
* *
@ -613,3 +613,27 @@ bail1:
bail0: bail0:
return 0; return 0;
} }
FcFontSet *
FcFontSort (FcConfig *config,
FcPattern *p,
FcBool trim,
FcCharSet **csp,
FcResult *result)
{
FcFontSet *sets[2];
int nsets;
if (!config)
{
config = FcConfigGetCurrent ();
if (!config)
return 0;
}
nsets = 0;
if (config->fonts[FcSetSystem])
sets[nsets++] = config->fonts[FcSetSystem];
if (config->fonts[FcSetApplication])
sets[nsets++] = config->fonts[FcSetApplication];
return FcFontSetSort (config, sets, nsets, p, trim, csp, result);
}