730 lines
18 KiB
C
730 lines
18 KiB
C
|
/*
|
||
|
*
|
||
|
* Copyright © 2000 SuSE, Inc.
|
||
|
*
|
||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||
|
* the above copyright notice appear in all copies and that both that
|
||
|
* copyright notice and this permission notice appear in supporting
|
||
|
* documentation, and that the name of SuSE not be used in advertising or
|
||
|
* publicity pertaining to distribution of the software without specific,
|
||
|
* written prior permission. SuSE makes no representations about the
|
||
|
* suitability of this software for any purpose. It is provided "as is"
|
||
|
* without express or implied warranty.
|
||
|
*
|
||
|
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||
|
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||
|
*
|
||
|
* Author: Keith Packard, SuSE, Inc.
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_DIX_CONFIG_H
|
||
|
#include <dix-config.h>
|
||
|
#endif
|
||
|
|
||
|
#include "misc.h"
|
||
|
#include "scrnintstr.h"
|
||
|
#include "os.h"
|
||
|
#include "regionstr.h"
|
||
|
#include "validate.h"
|
||
|
#include "windowstr.h"
|
||
|
#include "input.h"
|
||
|
#include "resource.h"
|
||
|
#include "colormapst.h"
|
||
|
#include "cursorstr.h"
|
||
|
#include "dixstruct.h"
|
||
|
#include "gcstruct.h"
|
||
|
#include "servermd.h"
|
||
|
#include "picturestr.h"
|
||
|
#include "glyphstr.h"
|
||
|
|
||
|
/*
|
||
|
* From Knuth -- a good choice for hash/rehash values is p, p-2 where
|
||
|
* p and p-2 are both prime. These tables are sized to have an extra 10%
|
||
|
* free to avoid exponential performance degradation as the hash table fills
|
||
|
*/
|
||
|
static GlyphHashSetRec glyphHashSets[] = {
|
||
|
{32, 43, 41},
|
||
|
{64, 73, 71},
|
||
|
{128, 151, 149},
|
||
|
{256, 283, 281},
|
||
|
{512, 571, 569},
|
||
|
{1024, 1153, 1151},
|
||
|
{2048, 2269, 2267},
|
||
|
{4096, 4519, 4517},
|
||
|
{8192, 9013, 9011},
|
||
|
{16384, 18043, 18041},
|
||
|
{32768, 36109, 36107},
|
||
|
{65536, 72091, 72089},
|
||
|
{131072, 144409, 144407},
|
||
|
{262144, 288361, 288359},
|
||
|
{524288, 576883, 576881},
|
||
|
{1048576, 1153459, 1153457},
|
||
|
{2097152, 2307163, 2307161},
|
||
|
{4194304, 4613893, 4613891},
|
||
|
{8388608, 9227641, 9227639},
|
||
|
{16777216, 18455029, 18455027},
|
||
|
{33554432, 36911011, 36911009},
|
||
|
{67108864, 73819861, 73819859},
|
||
|
{134217728, 147639589, 147639587},
|
||
|
{268435456, 295279081, 295279079},
|
||
|
{536870912, 590559793, 590559791}
|
||
|
};
|
||
|
|
||
|
#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0]))
|
||
|
|
||
|
const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 };
|
||
|
|
||
|
GlyphHashRec globalGlyphs[GlyphFormatNum];
|
||
|
|
||
|
int globalTotalGlyphPrivateSize = 0;
|
||
|
|
||
|
static void
|
||
|
SetGlyphScreenPrivateOffsets(void)
|
||
|
{
|
||
|
PictureScreenPtr ps;
|
||
|
|
||
|
int offset = 0;
|
||
|
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < screenInfo.numScreens; i++) {
|
||
|
ps = GetPictureScreenIfSet(screenInfo.screens[i]);
|
||
|
if (ps && ps->totalGlyphPrivateSize) {
|
||
|
ps->glyphPrivateOffset = offset;
|
||
|
offset += ps->totalGlyphPrivateSize / sizeof(DevUnion);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
SetGlyphPrivatePointers(GlyphPtr glyph)
|
||
|
{
|
||
|
PictureScreenPtr ps;
|
||
|
|
||
|
int i;
|
||
|
|
||
|
char *ptr;
|
||
|
|
||
|
DevUnion *ppriv;
|
||
|
|
||
|
unsigned *sizes;
|
||
|
|
||
|
unsigned size;
|
||
|
|
||
|
int len;
|
||
|
|
||
|
for (i = 0; i < screenInfo.numScreens; i++) {
|
||
|
ps = GetPictureScreenIfSet(screenInfo.screens[i]);
|
||
|
if (ps && ps->totalGlyphPrivateSize) {
|
||
|
ppriv = glyph->devPrivates + ps->glyphPrivateOffset;
|
||
|
sizes = ps->glyphPrivateSizes;
|
||
|
ptr = (char *) (ppriv + ps->glyphPrivateLen);
|
||
|
for (len = ps->glyphPrivateLen; --len >= 0; ppriv++, sizes++) {
|
||
|
if ((size = *sizes) != 0) {
|
||
|
ppriv->ptr = (pointer) ptr;
|
||
|
ptr += size;
|
||
|
}
|
||
|
else
|
||
|
ppriv->ptr = (pointer) 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
ReallocGlobalGlyphPrivate(GlyphPtr glyph)
|
||
|
{
|
||
|
PictureScreenPtr ps;
|
||
|
|
||
|
DevUnion *devPrivates;
|
||
|
|
||
|
char *ptr;
|
||
|
|
||
|
int i;
|
||
|
|
||
|
devPrivates = malloc(globalTotalGlyphPrivateSize);
|
||
|
if (!devPrivates)
|
||
|
return FALSE;
|
||
|
|
||
|
ptr = (char *) devPrivates;
|
||
|
for (i = 0; i < screenInfo.numScreens; i++) {
|
||
|
ps = GetPictureScreenIfSet(screenInfo.screens[i]);
|
||
|
if (ps && ps->totalGlyphPrivateSize) {
|
||
|
if (ps->glyphPrivateOffset != -1) {
|
||
|
memcpy(ptr, glyph->devPrivates + ps->glyphPrivateOffset,
|
||
|
ps->totalGlyphPrivateSize);
|
||
|
}
|
||
|
else if (ps->totalGlyphPrivateSize) {
|
||
|
memset(ptr, 0, ps->totalGlyphPrivateSize);
|
||
|
}
|
||
|
|
||
|
ptr += ps->totalGlyphPrivateSize;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (glyph->devPrivates)
|
||
|
free(glyph->devPrivates);
|
||
|
|
||
|
glyph->devPrivates = devPrivates;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
GlyphInit(ScreenPtr pScreen)
|
||
|
{
|
||
|
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
||
|
|
||
|
ps->totalGlyphPrivateSize = 0;
|
||
|
ps->glyphPrivateSizes = 0;
|
||
|
ps->glyphPrivateLen = 0;
|
||
|
ps->glyphPrivateOffset = -1;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
GlyphFinishInit(ScreenPtr pScreen)
|
||
|
{
|
||
|
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
||
|
|
||
|
if (ps->totalGlyphPrivateSize) {
|
||
|
GlyphPtr glyph;
|
||
|
|
||
|
int fdepth, i;
|
||
|
|
||
|
globalTotalGlyphPrivateSize += ps->totalGlyphPrivateSize;
|
||
|
|
||
|
for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) {
|
||
|
if (!globalGlyphs[fdepth].hashSet)
|
||
|
continue;
|
||
|
|
||
|
for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) {
|
||
|
glyph = globalGlyphs[fdepth].table[i].glyph;
|
||
|
if (glyph && glyph != DeletedGlyph) {
|
||
|
if (!ReallocGlobalGlyphPrivate(glyph))
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetGlyphScreenPrivateOffsets();
|
||
|
|
||
|
for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) {
|
||
|
if (!globalGlyphs[fdepth].hashSet)
|
||
|
continue;
|
||
|
|
||
|
for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) {
|
||
|
glyph = globalGlyphs[fdepth].table[i].glyph;
|
||
|
if (glyph && glyph != DeletedGlyph) {
|
||
|
SetGlyphPrivatePointers(glyph);
|
||
|
|
||
|
if (!(*ps->RealizeGlyph) (pScreen, glyph))
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
ps->glyphPrivateOffset = 0;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
GlyphUninit(ScreenPtr pScreen)
|
||
|
{
|
||
|
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
||
|
|
||
|
GlyphPtr glyph;
|
||
|
|
||
|
int fdepth, i;
|
||
|
|
||
|
globalTotalGlyphPrivateSize -= ps->totalGlyphPrivateSize;
|
||
|
|
||
|
for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) {
|
||
|
if (!globalGlyphs[fdepth].hashSet)
|
||
|
continue;
|
||
|
|
||
|
for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) {
|
||
|
glyph = globalGlyphs[fdepth].table[i].glyph;
|
||
|
if (glyph && glyph != DeletedGlyph) {
|
||
|
(*ps->UnrealizeGlyph) (pScreen, glyph);
|
||
|
|
||
|
if (globalTotalGlyphPrivateSize) {
|
||
|
if (!ReallocGlobalGlyphPrivate(glyph))
|
||
|
return;
|
||
|
}
|
||
|
else {
|
||
|
if (glyph->devPrivates)
|
||
|
free(glyph->devPrivates);
|
||
|
glyph->devPrivates = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (globalTotalGlyphPrivateSize)
|
||
|
SetGlyphScreenPrivateOffsets();
|
||
|
|
||
|
for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) {
|
||
|
if (!globalGlyphs[fdepth].hashSet)
|
||
|
continue;
|
||
|
|
||
|
for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) {
|
||
|
glyph = globalGlyphs[fdepth].table[i].glyph;
|
||
|
if (glyph && glyph != DeletedGlyph) {
|
||
|
if (globalTotalGlyphPrivateSize)
|
||
|
SetGlyphPrivatePointers(glyph);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ps->glyphPrivateSizes)
|
||
|
free(ps->glyphPrivateSizes);
|
||
|
}
|
||
|
|
||
|
GlyphHashSetPtr
|
||
|
FindGlyphHashSet(CARD32 filled)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < NGLYPHHASHSETS; i++)
|
||
|
if (glyphHashSets[i].entries >= filled)
|
||
|
return &glyphHashSets[i];
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int _GlyphSetPrivateAllocateIndex = 0;
|
||
|
|
||
|
void
|
||
|
ResetGlyphSetPrivateIndex(void)
|
||
|
{
|
||
|
_GlyphSetPrivateAllocateIndex = 0;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
_GlyphSetSetNewPrivate(GlyphSetPtr glyphSet, int n, pointer ptr)
|
||
|
{
|
||
|
pointer *new;
|
||
|
|
||
|
if (n > glyphSet->maxPrivate) {
|
||
|
if (glyphSet->devPrivates &&
|
||
|
glyphSet->devPrivates != (pointer) (&glyphSet[1])) {
|
||
|
new = (pointer *) realloc(glyphSet->devPrivates,
|
||
|
(n + 1) * sizeof(pointer));
|
||
|
if (!new)
|
||
|
return FALSE;
|
||
|
}
|
||
|
else {
|
||
|
new = malloc((n + 1) * sizeof(pointer));
|
||
|
if (!new)
|
||
|
return FALSE;
|
||
|
if (glyphSet->devPrivates)
|
||
|
memcpy(new,
|
||
|
glyphSet->devPrivates,
|
||
|
(glyphSet->maxPrivate + 1) * sizeof(pointer));
|
||
|
}
|
||
|
glyphSet->devPrivates = new;
|
||
|
/* Zero out new, uninitialize privates */
|
||
|
while (++glyphSet->maxPrivate < n)
|
||
|
glyphSet->devPrivates[glyphSet->maxPrivate] = (pointer) 0;
|
||
|
}
|
||
|
glyphSet->devPrivates[n] = ptr;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
GlyphRefPtr
|
||
|
FindGlyphRef(GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare)
|
||
|
{
|
||
|
CARD32 elt, step, s;
|
||
|
|
||
|
GlyphPtr glyph;
|
||
|
|
||
|
GlyphRefPtr table, gr, del;
|
||
|
|
||
|
CARD32 tableSize = hash->hashSet->size;
|
||
|
|
||
|
table = hash->table;
|
||
|
elt = signature % tableSize;
|
||
|
step = 0;
|
||
|
del = 0;
|
||
|
for (;;) {
|
||
|
gr = &table[elt];
|
||
|
s = gr->signature;
|
||
|
glyph = gr->glyph;
|
||
|
if (!glyph) {
|
||
|
if (del)
|
||
|
gr = del;
|
||
|
break;
|
||
|
}
|
||
|
if (glyph == DeletedGlyph) {
|
||
|
if (!del)
|
||
|
del = gr;
|
||
|
else if (gr == del)
|
||
|
break;
|
||
|
}
|
||
|
else if (s == signature &&
|
||
|
(!match ||
|
||
|
memcmp(&compare->info, &glyph->info, compare->size) == 0)) {
|
||
|
break;
|
||
|
}
|
||
|
if (!step) {
|
||
|
step = signature % hash->hashSet->rehash;
|
||
|
if (!step)
|
||
|
step = 1;
|
||
|
}
|
||
|
elt += step;
|
||
|
if (elt >= tableSize)
|
||
|
elt -= tableSize;
|
||
|
}
|
||
|
return gr;
|
||
|
}
|
||
|
|
||
|
CARD32
|
||
|
HashGlyph(GlyphPtr glyph)
|
||
|
{
|
||
|
CARD32 *bits = (CARD32 *) &(glyph->info);
|
||
|
|
||
|
CARD32 hash;
|
||
|
|
||
|
int n = glyph->size / sizeof(CARD32);
|
||
|
|
||
|
hash = 0;
|
||
|
while (n--)
|
||
|
hash ^= *bits++;
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
#ifdef CHECK_DUPLICATES
|
||
|
void
|
||
|
DuplicateRef(GlyphPtr glyph, char *where)
|
||
|
{
|
||
|
ErrorF("Duplicate Glyph 0x%x from %s\n", glyph, where);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CheckDuplicates(GlyphHashPtr hash, char *where)
|
||
|
{
|
||
|
GlyphPtr g;
|
||
|
|
||
|
int i, j;
|
||
|
|
||
|
for (i = 0; i < hash->hashSet->size; i++) {
|
||
|
g = hash->table[i].glyph;
|
||
|
if (!g || g == DeletedGlyph)
|
||
|
continue;
|
||
|
for (j = i + 1; j < hash->hashSet->size; j++)
|
||
|
if (hash->table[j].glyph == g)
|
||
|
DuplicateRef(g, where);
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
#define CheckDuplicates(a,b)
|
||
|
#define DuplicateRef(a,b)
|
||
|
#endif
|
||
|
|
||
|
void
|
||
|
FreeGlyph(GlyphPtr glyph, int format)
|
||
|
{
|
||
|
CheckDuplicates(&globalGlyphs[format], "FreeGlyph");
|
||
|
if (--glyph->refcnt == 0) {
|
||
|
PictureScreenPtr ps;
|
||
|
|
||
|
GlyphRefPtr gr;
|
||
|
|
||
|
int i;
|
||
|
|
||
|
int first;
|
||
|
|
||
|
first = -1;
|
||
|
for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
|
||
|
if (globalGlyphs[format].table[i].glyph == glyph) {
|
||
|
if (first != -1)
|
||
|
DuplicateRef(glyph, "FreeGlyph check");
|
||
|
first = i;
|
||
|
}
|
||
|
|
||
|
gr = FindGlyphRef(&globalGlyphs[format], HashGlyph(glyph), TRUE, glyph);
|
||
|
if (gr - globalGlyphs[format].table != first)
|
||
|
DuplicateRef(glyph, "Found wrong one");
|
||
|
if (gr->glyph && gr->glyph != DeletedGlyph) {
|
||
|
gr->glyph = DeletedGlyph;
|
||
|
gr->signature = 0;
|
||
|
globalGlyphs[format].tableEntries--;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < screenInfo.numScreens; i++) {
|
||
|
ps = GetPictureScreenIfSet(screenInfo.screens[i]);
|
||
|
if (ps)
|
||
|
(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
|
||
|
}
|
||
|
|
||
|
if (glyph->devPrivates)
|
||
|
free(glyph->devPrivates);
|
||
|
free(glyph);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
AddGlyph(GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
|
||
|
{
|
||
|
GlyphRefPtr gr;
|
||
|
|
||
|
CARD32 hash;
|
||
|
|
||
|
CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
|
||
|
/* Locate existing matching glyph */
|
||
|
hash = HashGlyph(glyph);
|
||
|
gr = FindGlyphRef(&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph);
|
||
|
if (gr->glyph && gr->glyph != DeletedGlyph) {
|
||
|
PictureScreenPtr ps;
|
||
|
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < screenInfo.numScreens; i++) {
|
||
|
ps = GetPictureScreenIfSet(screenInfo.screens[i]);
|
||
|
if (ps)
|
||
|
(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
|
||
|
}
|
||
|
if (glyph->devPrivates)
|
||
|
free(glyph->devPrivates);
|
||
|
free(glyph);
|
||
|
glyph = gr->glyph;
|
||
|
}
|
||
|
else {
|
||
|
gr->glyph = glyph;
|
||
|
gr->signature = hash;
|
||
|
globalGlyphs[glyphSet->fdepth].tableEntries++;
|
||
|
}
|
||
|
|
||
|
/* Insert/replace glyphset value */
|
||
|
gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0);
|
||
|
++glyph->refcnt;
|
||
|
if (gr->glyph && gr->glyph != DeletedGlyph)
|
||
|
FreeGlyph(gr->glyph, glyphSet->fdepth);
|
||
|
else
|
||
|
glyphSet->hash.tableEntries++;
|
||
|
gr->glyph = glyph;
|
||
|
gr->signature = id;
|
||
|
CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
DeleteGlyph(GlyphSetPtr glyphSet, Glyph id)
|
||
|
{
|
||
|
GlyphRefPtr gr;
|
||
|
|
||
|
GlyphPtr glyph;
|
||
|
|
||
|
gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0);
|
||
|
glyph = gr->glyph;
|
||
|
if (glyph && glyph != DeletedGlyph) {
|
||
|
gr->glyph = DeletedGlyph;
|
||
|
glyphSet->hash.tableEntries--;
|
||
|
FreeGlyph(glyph, glyphSet->fdepth);
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
GlyphPtr
|
||
|
FindGlyph(GlyphSetPtr glyphSet, Glyph id)
|
||
|
{
|
||
|
GlyphPtr glyph;
|
||
|
|
||
|
glyph = FindGlyphRef(&glyphSet->hash, id, FALSE, 0)->glyph;
|
||
|
if (glyph == DeletedGlyph)
|
||
|
glyph = 0;
|
||
|
return glyph;
|
||
|
}
|
||
|
|
||
|
GlyphPtr
|
||
|
AllocateGlyph(xGlyphInfo * gi, int fdepth)
|
||
|
{
|
||
|
PictureScreenPtr ps;
|
||
|
|
||
|
int size;
|
||
|
|
||
|
GlyphPtr glyph;
|
||
|
|
||
|
int i;
|
||
|
|
||
|
size = gi->height * PixmapBytePad(gi->width, glyphDepths[fdepth]);
|
||
|
glyph = malloc(size + sizeof(GlyphRec));
|
||
|
if (!glyph)
|
||
|
return 0;
|
||
|
glyph->refcnt = 0;
|
||
|
glyph->size = size + sizeof(xGlyphInfo);
|
||
|
glyph->info = *gi;
|
||
|
|
||
|
if (globalTotalGlyphPrivateSize) {
|
||
|
glyph->devPrivates = malloc(globalTotalGlyphPrivateSize);
|
||
|
if (!glyph->devPrivates)
|
||
|
return 0;
|
||
|
|
||
|
SetGlyphPrivatePointers(glyph);
|
||
|
}
|
||
|
else
|
||
|
glyph->devPrivates = NULL;
|
||
|
|
||
|
for (i = 0; i < screenInfo.numScreens; i++) {
|
||
|
ps = GetPictureScreenIfSet(screenInfo.screens[i]);
|
||
|
if (ps) {
|
||
|
if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph)) {
|
||
|
while (i--) {
|
||
|
ps = GetPictureScreenIfSet(screenInfo.screens[i]);
|
||
|
if (ps)
|
||
|
(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
|
||
|
}
|
||
|
|
||
|
if (glyph->devPrivates)
|
||
|
free(glyph->devPrivates);
|
||
|
free(glyph);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return glyph;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
AllocateGlyphHash(GlyphHashPtr hash, GlyphHashSetPtr hashSet)
|
||
|
{
|
||
|
hash->table = malloc(hashSet->size * sizeof(GlyphRefRec));
|
||
|
if (!hash->table)
|
||
|
return FALSE;
|
||
|
memset(hash->table, 0, hashSet->size * sizeof(GlyphRefRec));
|
||
|
hash->hashSet = hashSet;
|
||
|
hash->tableEntries = 0;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
ResizeGlyphHash(GlyphHashPtr hash, CARD32 change, Bool global)
|
||
|
{
|
||
|
CARD32 tableEntries;
|
||
|
|
||
|
GlyphHashSetPtr hashSet;
|
||
|
|
||
|
GlyphHashRec newHash;
|
||
|
|
||
|
GlyphRefPtr gr;
|
||
|
|
||
|
GlyphPtr glyph;
|
||
|
|
||
|
int i;
|
||
|
|
||
|
int oldSize;
|
||
|
|
||
|
CARD32 s;
|
||
|
|
||
|
tableEntries = hash->tableEntries + change;
|
||
|
hashSet = FindGlyphHashSet(tableEntries);
|
||
|
if (hashSet == hash->hashSet)
|
||
|
return TRUE;
|
||
|
if (global)
|
||
|
CheckDuplicates(hash, "ResizeGlyphHash top");
|
||
|
if (!AllocateGlyphHash(&newHash, hashSet))
|
||
|
return FALSE;
|
||
|
if (hash->table) {
|
||
|
oldSize = hash->hashSet->size;
|
||
|
for (i = 0; i < oldSize; i++) {
|
||
|
glyph = hash->table[i].glyph;
|
||
|
if (glyph && glyph != DeletedGlyph) {
|
||
|
s = hash->table[i].signature;
|
||
|
gr = FindGlyphRef(&newHash, s, global, glyph);
|
||
|
|
||
|
gr->signature = s;
|
||
|
gr->glyph = glyph;
|
||
|
++newHash.tableEntries;
|
||
|
}
|
||
|
}
|
||
|
free(hash->table);
|
||
|
}
|
||
|
*hash = newHash;
|
||
|
if (global)
|
||
|
CheckDuplicates(hash, "ResizeGlyphHash bottom");
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
Bool
|
||
|
ResizeGlyphSet(GlyphSetPtr glyphSet, CARD32 change)
|
||
|
{
|
||
|
return (ResizeGlyphHash(&glyphSet->hash, change, FALSE) &&
|
||
|
ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], change, TRUE));
|
||
|
}
|
||
|
|
||
|
GlyphSetPtr
|
||
|
AllocateGlyphSet(int fdepth, PictFormatPtr format)
|
||
|
{
|
||
|
GlyphSetPtr glyphSet;
|
||
|
|
||
|
int size;
|
||
|
|
||
|
if (!globalGlyphs[fdepth].hashSet) {
|
||
|
if (!AllocateGlyphHash(&globalGlyphs[fdepth], &glyphHashSets[0]))
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
size = (sizeof(GlyphSetRec) +
|
||
|
(sizeof(pointer) * _GlyphSetPrivateAllocateIndex));
|
||
|
glyphSet = malloc(size);
|
||
|
if (!glyphSet)
|
||
|
return FALSE;
|
||
|
bzero((char *) glyphSet, size);
|
||
|
glyphSet->maxPrivate = _GlyphSetPrivateAllocateIndex - 1;
|
||
|
if (_GlyphSetPrivateAllocateIndex)
|
||
|
glyphSet->devPrivates = (pointer) (&glyphSet[1]);
|
||
|
|
||
|
if (!AllocateGlyphHash(&glyphSet->hash, &glyphHashSets[0])) {
|
||
|
free(glyphSet);
|
||
|
return FALSE;
|
||
|
}
|
||
|
glyphSet->refcnt = 1;
|
||
|
glyphSet->fdepth = fdepth;
|
||
|
glyphSet->format = format;
|
||
|
return glyphSet;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
FreeGlyphSet(pointer value, XID gid)
|
||
|
{
|
||
|
GlyphSetPtr glyphSet = (GlyphSetPtr) value;
|
||
|
|
||
|
if (--glyphSet->refcnt == 0) {
|
||
|
CARD32 i, tableSize = glyphSet->hash.hashSet->size;
|
||
|
|
||
|
GlyphRefPtr table = glyphSet->hash.table;
|
||
|
|
||
|
GlyphPtr glyph;
|
||
|
|
||
|
for (i = 0; i < tableSize; i++) {
|
||
|
glyph = table[i].glyph;
|
||
|
if (glyph && glyph != DeletedGlyph)
|
||
|
FreeGlyph(glyph, glyphSet->fdepth);
|
||
|
}
|
||
|
if (!globalGlyphs[glyphSet->fdepth].tableEntries) {
|
||
|
free(globalGlyphs[glyphSet->fdepth].table);
|
||
|
globalGlyphs[glyphSet->fdepth].table = 0;
|
||
|
globalGlyphs[glyphSet->fdepth].hashSet = 0;
|
||
|
}
|
||
|
else
|
||
|
ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], 0, TRUE);
|
||
|
free(table);
|
||
|
|
||
|
if (glyphSet->devPrivates &&
|
||
|
glyphSet->devPrivates != (pointer) (&glyphSet[1]))
|
||
|
free(glyphSet->devPrivates);
|
||
|
|
||
|
free(glyphSet);
|
||
|
}
|
||
|
return Success;
|
||
|
}
|