glyph.c revision 4202a189
105b261ecSmrg/*
205b261ecSmrg *
305b261ecSmrg * Copyright © 2000 SuSE, Inc.
405b261ecSmrg *
505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
705b261ecSmrg * the above copyright notice appear in all copies and that both that
805b261ecSmrg * copyright notice and this permission notice appear in supporting
905b261ecSmrg * documentation, and that the name of SuSE not be used in advertising or
1005b261ecSmrg * publicity pertaining to distribution of the software without specific,
1105b261ecSmrg * written prior permission.  SuSE makes no representations about the
1205b261ecSmrg * suitability of this software for any purpose.  It is provided "as is"
1305b261ecSmrg * without express or implied warranty.
1405b261ecSmrg *
1505b261ecSmrg * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
1605b261ecSmrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
1705b261ecSmrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1805b261ecSmrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
1905b261ecSmrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
2005b261ecSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2105b261ecSmrg *
2205b261ecSmrg * Author:  Keith Packard, SuSE, Inc.
2305b261ecSmrg */
2405b261ecSmrg
2505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2605b261ecSmrg#include <dix-config.h>
2705b261ecSmrg#endif
2805b261ecSmrg
294202a189Smrg#include "xsha1.h"
304642e01fSmrg
3105b261ecSmrg#include "misc.h"
3205b261ecSmrg#include "scrnintstr.h"
3305b261ecSmrg#include "os.h"
3405b261ecSmrg#include "regionstr.h"
3505b261ecSmrg#include "validate.h"
3605b261ecSmrg#include "windowstr.h"
3705b261ecSmrg#include "input.h"
3805b261ecSmrg#include "resource.h"
3905b261ecSmrg#include "colormapst.h"
4005b261ecSmrg#include "cursorstr.h"
4105b261ecSmrg#include "dixstruct.h"
4205b261ecSmrg#include "gcstruct.h"
4305b261ecSmrg#include "servermd.h"
4405b261ecSmrg#include "picturestr.h"
4505b261ecSmrg#include "glyphstr.h"
464642e01fSmrg#include "mipict.h"
4705b261ecSmrg
4805b261ecSmrg/*
4905b261ecSmrg * From Knuth -- a good choice for hash/rehash values is p, p-2 where
5005b261ecSmrg * p and p-2 are both prime.  These tables are sized to have an extra 10%
5105b261ecSmrg * free to avoid exponential performance degradation as the hash table fills
5205b261ecSmrg */
5305b261ecSmrgstatic GlyphHashSetRec glyphHashSets[] = {
5405b261ecSmrg    { 32,		43,		41        },
5505b261ecSmrg    { 64,		73,		71        },
5605b261ecSmrg    { 128,		151,		149       },
5705b261ecSmrg    { 256,		283,		281       },
5805b261ecSmrg    { 512,		571,		569       },
5905b261ecSmrg    { 1024,		1153,		1151      },
6005b261ecSmrg    { 2048,		2269,		2267      },
6105b261ecSmrg    { 4096,		4519,		4517      },
6205b261ecSmrg    { 8192,		9013,		9011      },
6305b261ecSmrg    { 16384,		18043,		18041     },
6405b261ecSmrg    { 32768,		36109,		36107     },
6505b261ecSmrg    { 65536,		72091,		72089     },
6605b261ecSmrg    { 131072,		144409,		144407    },
6705b261ecSmrg    { 262144,		288361,		288359    },
6805b261ecSmrg    { 524288,		576883,		576881    },
6905b261ecSmrg    { 1048576,		1153459,	1153457   },
7005b261ecSmrg    { 2097152,		2307163,	2307161   },
7105b261ecSmrg    { 4194304,		4613893,	4613891   },
7205b261ecSmrg    { 8388608,		9227641,	9227639   },
7305b261ecSmrg    { 16777216,		18455029,	18455027  },
7405b261ecSmrg    { 33554432,		36911011,	36911009  },
7505b261ecSmrg    { 67108864,		73819861,	73819859  },
7605b261ecSmrg    { 134217728,	147639589,	147639587 },
7705b261ecSmrg    { 268435456,	295279081,	295279079 },
7805b261ecSmrg    { 536870912,	590559793,	590559791 }
7905b261ecSmrg};
8005b261ecSmrg
8105b261ecSmrg#define NGLYPHHASHSETS	(sizeof(glyphHashSets)/sizeof(glyphHashSets[0]))
8205b261ecSmrg
8305b261ecSmrgstatic const CARD8	glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 };
8405b261ecSmrg
8505b261ecSmrgstatic GlyphHashRec	globalGlyphs[GlyphFormatNum];
8605b261ecSmrg
8705b261ecSmrgvoid
8805b261ecSmrgGlyphUninit (ScreenPtr pScreen)
8905b261ecSmrg{
9005b261ecSmrg    PictureScreenPtr ps = GetPictureScreen (pScreen);
9105b261ecSmrg    GlyphPtr	     glyph;
9205b261ecSmrg    int		     fdepth, i;
934202a189Smrg    int		     scrno = pScreen->myNum;
9405b261ecSmrg
9505b261ecSmrg    for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
9605b261ecSmrg    {
9705b261ecSmrg	if (!globalGlyphs[fdepth].hashSet)
9805b261ecSmrg	    continue;
9905b261ecSmrg
10005b261ecSmrg	for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
10105b261ecSmrg	{
10205b261ecSmrg	    glyph = globalGlyphs[fdepth].table[i].glyph;
10305b261ecSmrg	    if (glyph && glyph != DeletedGlyph)
10405b261ecSmrg	    {
1054202a189Smrg		if (GlyphPicture(glyph)[scrno])
1064202a189Smrg		{
1074202a189Smrg		    FreePicture ((pointer) GlyphPicture (glyph)[scrno], 0);
1084202a189Smrg		    GlyphPicture(glyph)[scrno] = NULL;
1094202a189Smrg		}
11005b261ecSmrg		(*ps->UnrealizeGlyph) (pScreen, glyph);
11105b261ecSmrg	    }
11205b261ecSmrg	}
11305b261ecSmrg    }
11405b261ecSmrg}
11505b261ecSmrg
11605b261ecSmrgGlyphHashSetPtr
11705b261ecSmrgFindGlyphHashSet (CARD32 filled)
11805b261ecSmrg{
11905b261ecSmrg    int	i;
12005b261ecSmrg
12105b261ecSmrg    for (i = 0; i < NGLYPHHASHSETS; i++)
12205b261ecSmrg	if (glyphHashSets[i].entries >= filled)
12305b261ecSmrg	    return &glyphHashSets[i];
12405b261ecSmrg    return 0;
12505b261ecSmrg}
12605b261ecSmrg
12705b261ecSmrgGlyphRefPtr
1284642e01fSmrgFindGlyphRef (GlyphHashPtr	hash,
1294642e01fSmrg	      CARD32		signature,
1304642e01fSmrg	      Bool		match,
1314642e01fSmrg	      unsigned char	sha1[20])
13205b261ecSmrg{
13305b261ecSmrg    CARD32	elt, step, s;
13405b261ecSmrg    GlyphPtr	glyph;
13505b261ecSmrg    GlyphRefPtr	table, gr, del;
13605b261ecSmrg    CARD32	tableSize = hash->hashSet->size;
13705b261ecSmrg
13805b261ecSmrg    table = hash->table;
13905b261ecSmrg    elt = signature % tableSize;
14005b261ecSmrg    step = 0;
14105b261ecSmrg    del = 0;
14205b261ecSmrg    for (;;)
14305b261ecSmrg    {
14405b261ecSmrg	gr = &table[elt];
14505b261ecSmrg	s = gr->signature;
14605b261ecSmrg	glyph = gr->glyph;
14705b261ecSmrg	if (!glyph)
14805b261ecSmrg	{
14905b261ecSmrg	    if (del)
15005b261ecSmrg		gr = del;
15105b261ecSmrg	    break;
15205b261ecSmrg	}
15305b261ecSmrg	if (glyph == DeletedGlyph)
15405b261ecSmrg	{
15505b261ecSmrg	    if (!del)
15605b261ecSmrg		del = gr;
15705b261ecSmrg	    else if (gr == del)
15805b261ecSmrg		break;
15905b261ecSmrg	}
16005b261ecSmrg	else if (s == signature &&
16105b261ecSmrg		 (!match ||
1624642e01fSmrg		  memcmp (glyph->sha1, sha1, 20) == 0))
16305b261ecSmrg	{
16405b261ecSmrg	    break;
16505b261ecSmrg	}
16605b261ecSmrg	if (!step)
16705b261ecSmrg	{
16805b261ecSmrg	    step = signature % hash->hashSet->rehash;
16905b261ecSmrg	    if (!step)
17005b261ecSmrg		step = 1;
17105b261ecSmrg	}
17205b261ecSmrg	elt += step;
17305b261ecSmrg	if (elt >= tableSize)
17405b261ecSmrg	    elt -= tableSize;
17505b261ecSmrg    }
17605b261ecSmrg    return gr;
17705b261ecSmrg}
17805b261ecSmrg
1794642e01fSmrgint
1804642e01fSmrgHashGlyph (xGlyphInfo    *gi,
1814642e01fSmrg	   CARD8	 *bits,
1824642e01fSmrg	   unsigned long size,
1834642e01fSmrg	   unsigned char sha1[20])
18405b261ecSmrg{
1854202a189Smrg    void *ctx = x_sha1_init();
1864642e01fSmrg    int success;
1874642e01fSmrg
1884202a189Smrg    if (!ctx)
1894642e01fSmrg	return BadAlloc;
1904642e01fSmrg
1914202a189Smrg    success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo));
1924202a189Smrg    if (!success)
1934642e01fSmrg	return BadAlloc;
1944202a189Smrg    success = x_sha1_update(ctx, bits, size);
1954202a189Smrg    if (!success)
1964642e01fSmrg	return BadAlloc;
1974202a189Smrg    success = x_sha1_final(ctx, sha1);
1984202a189Smrg    if (!success)
1994642e01fSmrg	return BadAlloc;
2004642e01fSmrg    return Success;
2014642e01fSmrg}
2024642e01fSmrg
2034642e01fSmrgGlyphPtr
2044642e01fSmrgFindGlyphByHash (unsigned char sha1[20], int format)
2054642e01fSmrg{
2064642e01fSmrg    GlyphRefPtr gr;
2074642e01fSmrg    CARD32 signature = *(CARD32 *) sha1;
2084642e01fSmrg
209ad5464f4Smrg    if (!globalGlyphs[format].hashSet)
2104202a189Smrg	return NULL;
211ad5464f4Smrg
2124642e01fSmrg    gr = FindGlyphRef (&globalGlyphs[format],
2134642e01fSmrg		       signature, TRUE, sha1);
2144642e01fSmrg
2154642e01fSmrg    if (gr->glyph && gr->glyph != DeletedGlyph)
2164642e01fSmrg	return gr->glyph;
2174642e01fSmrg    else
2184642e01fSmrg	return NULL;
21905b261ecSmrg}
22005b261ecSmrg
22105b261ecSmrg#ifdef CHECK_DUPLICATES
22205b261ecSmrgvoid
22305b261ecSmrgDuplicateRef (GlyphPtr glyph, char *where)
22405b261ecSmrg{
22505b261ecSmrg    ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where);
22605b261ecSmrg}
22705b261ecSmrg
22805b261ecSmrgvoid
22905b261ecSmrgCheckDuplicates (GlyphHashPtr hash, char *where)
23005b261ecSmrg{
23105b261ecSmrg    GlyphPtr	g;
23205b261ecSmrg    int		i, j;
23305b261ecSmrg
23405b261ecSmrg    for (i = 0; i < hash->hashSet->size; i++)
23505b261ecSmrg    {
23605b261ecSmrg	g = hash->table[i].glyph;
23705b261ecSmrg	if (!g || g == DeletedGlyph)
23805b261ecSmrg	    continue;
23905b261ecSmrg	for (j = i + 1; j < hash->hashSet->size; j++)
24005b261ecSmrg	    if (hash->table[j].glyph == g)
24105b261ecSmrg		DuplicateRef (g, where);
24205b261ecSmrg    }
24305b261ecSmrg}
24405b261ecSmrg#else
24505b261ecSmrg#define CheckDuplicates(a,b)
24605b261ecSmrg#define DuplicateRef(a,b)
24705b261ecSmrg#endif
24805b261ecSmrg
2494202a189Smrgstatic void
2504202a189SmrgFreeGlyphPicture(GlyphPtr glyph)
2514202a189Smrg{
2524202a189Smrg    PictureScreenPtr ps;
2534202a189Smrg    int i;
2544202a189Smrg
2554202a189Smrg    for (i = 0; i < screenInfo.numScreens; i++)
2564202a189Smrg    {
2574202a189Smrg        ScreenPtr pScreen = screenInfo.screens[i];
2584202a189Smrg
2594202a189Smrg        if (GlyphPicture(glyph)[i])
2604202a189Smrg            FreePicture ((pointer) GlyphPicture (glyph)[i], 0);
2614202a189Smrg
2624202a189Smrg        ps = GetPictureScreenIfSet (pScreen);
2634202a189Smrg        if (ps)
2644202a189Smrg            (*ps->UnrealizeGlyph) (pScreen, glyph);
2654202a189Smrg    }
2664202a189Smrg}
2674202a189Smrg
2684202a189Smrg
26905b261ecSmrgvoid
27005b261ecSmrgFreeGlyph (GlyphPtr glyph, int format)
27105b261ecSmrg{
27205b261ecSmrg    CheckDuplicates (&globalGlyphs[format], "FreeGlyph");
27305b261ecSmrg    if (--glyph->refcnt == 0)
27405b261ecSmrg    {
27505b261ecSmrg	GlyphRefPtr      gr;
27605b261ecSmrg	int	         i;
27705b261ecSmrg	int	         first;
2784642e01fSmrg	CARD32		 signature;
27905b261ecSmrg
28005b261ecSmrg	first = -1;
28105b261ecSmrg	for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
28205b261ecSmrg	    if (globalGlyphs[format].table[i].glyph == glyph)
28305b261ecSmrg	    {
28405b261ecSmrg		if (first != -1)
28505b261ecSmrg		    DuplicateRef (glyph, "FreeGlyph check");
28605b261ecSmrg		first = i;
28705b261ecSmrg	    }
28805b261ecSmrg
2894642e01fSmrg	signature = *(CARD32 *) glyph->sha1;
2904642e01fSmrg	gr = FindGlyphRef (&globalGlyphs[format], signature,
2914642e01fSmrg			   TRUE, glyph->sha1);
29205b261ecSmrg	if (gr - globalGlyphs[format].table != first)
29305b261ecSmrg	    DuplicateRef (glyph, "Found wrong one");
29405b261ecSmrg	if (gr->glyph && gr->glyph != DeletedGlyph)
29505b261ecSmrg	{
29605b261ecSmrg	    gr->glyph = DeletedGlyph;
29705b261ecSmrg	    gr->signature = 0;
29805b261ecSmrg	    globalGlyphs[format].tableEntries--;
29905b261ecSmrg	}
30005b261ecSmrg
3014202a189Smrg	FreeGlyphPicture(glyph);
3024202a189Smrg	dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
30305b261ecSmrg    }
30405b261ecSmrg}
30505b261ecSmrg
30605b261ecSmrgvoid
30705b261ecSmrgAddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
30805b261ecSmrg{
30905b261ecSmrg    GlyphRefPtr	    gr;
3104642e01fSmrg    CARD32	    signature;
31105b261ecSmrg
31205b261ecSmrg    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
31305b261ecSmrg    /* Locate existing matching glyph */
3144642e01fSmrg    signature = *(CARD32 *) glyph->sha1;
3154642e01fSmrg    gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], signature,
3164642e01fSmrg		       TRUE, glyph->sha1);
3174642e01fSmrg    if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph)
31805b261ecSmrg    {
3194202a189Smrg	FreeGlyphPicture(glyph);
3204202a189Smrg	dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
32105b261ecSmrg	glyph = gr->glyph;
32205b261ecSmrg    }
3234642e01fSmrg    else if (gr->glyph != glyph)
32405b261ecSmrg    {
32505b261ecSmrg	gr->glyph = glyph;
3264642e01fSmrg	gr->signature = signature;
32705b261ecSmrg	globalGlyphs[glyphSet->fdepth].tableEntries++;
32805b261ecSmrg    }
32905b261ecSmrg
33005b261ecSmrg    /* Insert/replace glyphset value */
33105b261ecSmrg    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
33205b261ecSmrg    ++glyph->refcnt;
33305b261ecSmrg    if (gr->glyph && gr->glyph != DeletedGlyph)
33405b261ecSmrg	FreeGlyph (gr->glyph, glyphSet->fdepth);
33505b261ecSmrg    else
33605b261ecSmrg	glyphSet->hash.tableEntries++;
33705b261ecSmrg    gr->glyph = glyph;
33805b261ecSmrg    gr->signature = id;
33905b261ecSmrg    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
34005b261ecSmrg}
34105b261ecSmrg
34205b261ecSmrgBool
34305b261ecSmrgDeleteGlyph (GlyphSetPtr glyphSet, Glyph id)
34405b261ecSmrg{
34505b261ecSmrg    GlyphRefPtr     gr;
34605b261ecSmrg    GlyphPtr	    glyph;
34705b261ecSmrg
34805b261ecSmrg    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
34905b261ecSmrg    glyph = gr->glyph;
35005b261ecSmrg    if (glyph && glyph != DeletedGlyph)
35105b261ecSmrg    {
35205b261ecSmrg	gr->glyph = DeletedGlyph;
35305b261ecSmrg	glyphSet->hash.tableEntries--;
35405b261ecSmrg	FreeGlyph (glyph, glyphSet->fdepth);
35505b261ecSmrg	return TRUE;
35605b261ecSmrg    }
35705b261ecSmrg    return FALSE;
35805b261ecSmrg}
35905b261ecSmrg
36005b261ecSmrgGlyphPtr
36105b261ecSmrgFindGlyph (GlyphSetPtr glyphSet, Glyph id)
36205b261ecSmrg{
36305b261ecSmrg    GlyphPtr        glyph;
36405b261ecSmrg
36505b261ecSmrg    glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph;
36605b261ecSmrg    if (glyph == DeletedGlyph)
36705b261ecSmrg	glyph = 0;
36805b261ecSmrg    return glyph;
36905b261ecSmrg}
37005b261ecSmrg
37105b261ecSmrgGlyphPtr
37205b261ecSmrgAllocateGlyph (xGlyphInfo *gi, int fdepth)
37305b261ecSmrg{
37405b261ecSmrg    PictureScreenPtr ps;
37505b261ecSmrg    int		     size;
37605b261ecSmrg    GlyphPtr	     glyph;
37705b261ecSmrg    int		     i;
3784202a189Smrg    int		     head_size;
3794642e01fSmrg
3804202a189Smrg    head_size = sizeof (GlyphRec) + screenInfo.numScreens * sizeof (PicturePtr);
3814202a189Smrg    size = (head_size + dixPrivatesSize(PRIVATE_GLYPH));
3824202a189Smrg    glyph = (GlyphPtr) malloc (size);
38305b261ecSmrg    if (!glyph)
38405b261ecSmrg	return 0;
38505b261ecSmrg    glyph->refcnt = 0;
38605b261ecSmrg    glyph->size = size + sizeof (xGlyphInfo);
38705b261ecSmrg    glyph->info = *gi;
3884202a189Smrg    dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH);
38905b261ecSmrg
39005b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++)
39105b261ecSmrg    {
3924202a189Smrg	GlyphPicture(glyph)[i] = NULL;
39305b261ecSmrg	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
3944642e01fSmrg
39505b261ecSmrg	if (ps)
39605b261ecSmrg	{
39705b261ecSmrg	    if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph))
3984642e01fSmrg		goto bail;
39905b261ecSmrg	}
40005b261ecSmrg    }
40105b261ecSmrg
40205b261ecSmrg    return glyph;
4034642e01fSmrg
4044642e01fSmrgbail:
4054642e01fSmrg    while (i--)
4064642e01fSmrg    {
4074642e01fSmrg	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
4084642e01fSmrg	if (ps)
4094642e01fSmrg	    (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
4104642e01fSmrg    }
4114642e01fSmrg
4124202a189Smrg    dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
4134642e01fSmrg    return 0;
41405b261ecSmrg}
41505b261ecSmrg
41605b261ecSmrgBool
41705b261ecSmrgAllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet)
41805b261ecSmrg{
4194202a189Smrg    hash->table = calloc(hashSet->size, sizeof (GlyphRefRec));
42005b261ecSmrg    if (!hash->table)
42105b261ecSmrg	return FALSE;
42205b261ecSmrg    hash->hashSet = hashSet;
42305b261ecSmrg    hash->tableEntries = 0;
42405b261ecSmrg    return TRUE;
42505b261ecSmrg}
42605b261ecSmrg
42705b261ecSmrgBool
42805b261ecSmrgResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global)
42905b261ecSmrg{
43005b261ecSmrg    CARD32	    tableEntries;
43105b261ecSmrg    GlyphHashSetPtr hashSet;
43205b261ecSmrg    GlyphHashRec    newHash;
43305b261ecSmrg    GlyphRefPtr	    gr;
43405b261ecSmrg    GlyphPtr	    glyph;
43505b261ecSmrg    int		    i;
43605b261ecSmrg    int		    oldSize;
43705b261ecSmrg    CARD32	    s;
43805b261ecSmrg
43905b261ecSmrg    tableEntries = hash->tableEntries + change;
44005b261ecSmrg    hashSet = FindGlyphHashSet (tableEntries);
44105b261ecSmrg    if (hashSet == hash->hashSet)
44205b261ecSmrg	return TRUE;
44305b261ecSmrg    if (global)
44405b261ecSmrg	CheckDuplicates (hash, "ResizeGlyphHash top");
44505b261ecSmrg    if (!AllocateGlyphHash (&newHash, hashSet))
44605b261ecSmrg	return FALSE;
44705b261ecSmrg    if (hash->table)
44805b261ecSmrg    {
44905b261ecSmrg	oldSize = hash->hashSet->size;
45005b261ecSmrg	for (i = 0; i < oldSize; i++)
45105b261ecSmrg	{
45205b261ecSmrg	    glyph = hash->table[i].glyph;
45305b261ecSmrg	    if (glyph && glyph != DeletedGlyph)
45405b261ecSmrg	    {
45505b261ecSmrg		s = hash->table[i].signature;
4564642e01fSmrg		gr = FindGlyphRef (&newHash, s, global, glyph->sha1);
45705b261ecSmrg		gr->signature = s;
45805b261ecSmrg		gr->glyph = glyph;
45905b261ecSmrg		++newHash.tableEntries;
46005b261ecSmrg	    }
46105b261ecSmrg	}
4624202a189Smrg	free(hash->table);
46305b261ecSmrg    }
46405b261ecSmrg    *hash = newHash;
46505b261ecSmrg    if (global)
46605b261ecSmrg	CheckDuplicates (hash, "ResizeGlyphHash bottom");
46705b261ecSmrg    return TRUE;
46805b261ecSmrg}
46905b261ecSmrg
47005b261ecSmrgBool
47105b261ecSmrgResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change)
47205b261ecSmrg{
47305b261ecSmrg    return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) &&
47405b261ecSmrg	    ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE));
47505b261ecSmrg}
47605b261ecSmrg
47705b261ecSmrgGlyphSetPtr
47805b261ecSmrgAllocateGlyphSet (int fdepth, PictFormatPtr format)
47905b261ecSmrg{
48005b261ecSmrg    GlyphSetPtr	glyphSet;
48105b261ecSmrg
48205b261ecSmrg    if (!globalGlyphs[fdepth].hashSet)
48305b261ecSmrg    {
48405b261ecSmrg	if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0]))
48505b261ecSmrg	    return FALSE;
48605b261ecSmrg    }
48705b261ecSmrg
4884202a189Smrg    glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET);
48905b261ecSmrg    if (!glyphSet)
49005b261ecSmrg	return FALSE;
49105b261ecSmrg
49205b261ecSmrg    if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0]))
49305b261ecSmrg    {
4944202a189Smrg	free(glyphSet);
49505b261ecSmrg	return FALSE;
49605b261ecSmrg    }
49705b261ecSmrg    glyphSet->refcnt = 1;
49805b261ecSmrg    glyphSet->fdepth = fdepth;
49905b261ecSmrg    glyphSet->format = format;
50005b261ecSmrg    return glyphSet;
50105b261ecSmrg}
50205b261ecSmrg
50305b261ecSmrgint
50405b261ecSmrgFreeGlyphSet (pointer	value,
50505b261ecSmrg	      XID       gid)
50605b261ecSmrg{
50705b261ecSmrg    GlyphSetPtr	glyphSet = (GlyphSetPtr) value;
50805b261ecSmrg
50905b261ecSmrg    if (--glyphSet->refcnt == 0)
51005b261ecSmrg    {
51105b261ecSmrg	CARD32	    i, tableSize = glyphSet->hash.hashSet->size;
51205b261ecSmrg	GlyphRefPtr table = glyphSet->hash.table;
51305b261ecSmrg	GlyphPtr    glyph;
51405b261ecSmrg
51505b261ecSmrg	for (i = 0; i < tableSize; i++)
51605b261ecSmrg	{
51705b261ecSmrg	    glyph = table[i].glyph;
51805b261ecSmrg	    if (glyph && glyph != DeletedGlyph)
51905b261ecSmrg		FreeGlyph (glyph, glyphSet->fdepth);
52005b261ecSmrg	}
52105b261ecSmrg	if (!globalGlyphs[glyphSet->fdepth].tableEntries)
52205b261ecSmrg	{
5234202a189Smrg	    free(globalGlyphs[glyphSet->fdepth].table);
52405b261ecSmrg	    globalGlyphs[glyphSet->fdepth].table = 0;
52505b261ecSmrg	    globalGlyphs[glyphSet->fdepth].hashSet = 0;
52605b261ecSmrg	}
52705b261ecSmrg	else
52805b261ecSmrg	    ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE);
5294202a189Smrg	free(table);
5304202a189Smrg	dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET);
53105b261ecSmrg    }
53205b261ecSmrg    return Success;
53305b261ecSmrg}
5344642e01fSmrg
5354642e01fSmrgstatic void
5364642e01fSmrgGlyphExtents (int		nlist,
5374642e01fSmrg		GlyphListPtr	list,
5384642e01fSmrg		GlyphPtr	*glyphs,
5394642e01fSmrg		BoxPtr		extents)
5404642e01fSmrg{
5414642e01fSmrg    int		x1, x2, y1, y2;
5424642e01fSmrg    int		n;
5434642e01fSmrg    GlyphPtr	glyph;
5444642e01fSmrg    int		x, y;
5454642e01fSmrg
5464642e01fSmrg    x = 0;
5474642e01fSmrg    y = 0;
5484642e01fSmrg    extents->x1 = MAXSHORT;
5494642e01fSmrg    extents->x2 = MINSHORT;
5504642e01fSmrg    extents->y1 = MAXSHORT;
5514642e01fSmrg    extents->y2 = MINSHORT;
5524642e01fSmrg    while (nlist--)
5534642e01fSmrg    {
5544642e01fSmrg	x += list->xOff;
5554642e01fSmrg	y += list->yOff;
5564642e01fSmrg	n = list->len;
5574642e01fSmrg	list++;
5584642e01fSmrg	while (n--)
5594642e01fSmrg	{
5604642e01fSmrg	    glyph = *glyphs++;
5614642e01fSmrg	    x1 = x - glyph->info.x;
5624642e01fSmrg	    if (x1 < MINSHORT)
5634642e01fSmrg		x1 = MINSHORT;
5644642e01fSmrg	    y1 = y - glyph->info.y;
5654642e01fSmrg	    if (y1 < MINSHORT)
5664642e01fSmrg		y1 = MINSHORT;
5674642e01fSmrg	    x2 = x1 + glyph->info.width;
5684642e01fSmrg	    if (x2 > MAXSHORT)
5694642e01fSmrg		x2 = MAXSHORT;
5704642e01fSmrg	    y2 = y1 + glyph->info.height;
5714642e01fSmrg	    if (y2 > MAXSHORT)
5724642e01fSmrg		y2 = MAXSHORT;
5734642e01fSmrg	    if (x1 < extents->x1)
5744642e01fSmrg		extents->x1 = x1;
5754642e01fSmrg	    if (x2 > extents->x2)
5764642e01fSmrg		extents->x2 = x2;
5774642e01fSmrg	    if (y1 < extents->y1)
5784642e01fSmrg		extents->y1 = y1;
5794642e01fSmrg	    if (y2 > extents->y2)
5804642e01fSmrg		extents->y2 = y2;
5814642e01fSmrg	    x += glyph->info.xOff;
5824642e01fSmrg	    y += glyph->info.yOff;
5834642e01fSmrg	}
5844642e01fSmrg    }
5854642e01fSmrg}
5864642e01fSmrg
5874642e01fSmrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
5884642e01fSmrg
5894202a189Smrgvoid
5904642e01fSmrgCompositeGlyphs (CARD8		op,
5914642e01fSmrg		 PicturePtr	pSrc,
5924642e01fSmrg		 PicturePtr	pDst,
5934642e01fSmrg		 PictFormatPtr	maskFormat,
5944642e01fSmrg		 INT16		xSrc,
5954642e01fSmrg		 INT16		ySrc,
5964642e01fSmrg		 int		nlist,
5974642e01fSmrg		 GlyphListPtr	lists,
5984642e01fSmrg		 GlyphPtr	*glyphs)
5994642e01fSmrg{
6004642e01fSmrg    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
6014642e01fSmrg
6024642e01fSmrg    ValidatePicture (pSrc);
6034642e01fSmrg    ValidatePicture (pDst);
6044642e01fSmrg    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs);
6054642e01fSmrg}
6064642e01fSmrg
6074642e01fSmrgBool
6084642e01fSmrgmiRealizeGlyph (ScreenPtr pScreen,
6094642e01fSmrg		GlyphPtr  glyph)
6104642e01fSmrg{
6114642e01fSmrg    return TRUE;
6124642e01fSmrg}
6134642e01fSmrg
6144642e01fSmrgvoid
6154642e01fSmrgmiUnrealizeGlyph (ScreenPtr pScreen,
6164642e01fSmrg		  GlyphPtr  glyph)
6174642e01fSmrg{
6184642e01fSmrg}
6194642e01fSmrg
6204202a189Smrgvoid
6214642e01fSmrgmiGlyphs (CARD8		op,
6224642e01fSmrg	  PicturePtr	pSrc,
6234642e01fSmrg	  PicturePtr	pDst,
6244642e01fSmrg	  PictFormatPtr	maskFormat,
6254642e01fSmrg	  INT16		xSrc,
6264642e01fSmrg	  INT16		ySrc,
6274642e01fSmrg	  int		nlist,
6284642e01fSmrg	  GlyphListPtr	list,
6294642e01fSmrg	  GlyphPtr	*glyphs)
6304642e01fSmrg{
6314642e01fSmrg    PicturePtr	pPicture;
6324642e01fSmrg    PixmapPtr   pMaskPixmap = 0;
6334642e01fSmrg    PicturePtr  pMask;
6344642e01fSmrg    ScreenPtr   pScreen = pDst->pDrawable->pScreen;
6354642e01fSmrg    int		width = 0, height = 0;
6364642e01fSmrg    int		x, y;
6374642e01fSmrg    int		xDst = list->xOff, yDst = list->yOff;
6384642e01fSmrg    int		n;
6394642e01fSmrg    GlyphPtr	glyph;
6404642e01fSmrg    int		error;
6414642e01fSmrg    BoxRec	extents = {0, 0, 0, 0};
6424642e01fSmrg    CARD32	component_alpha;
6434642e01fSmrg
6444642e01fSmrg    if (maskFormat)
6454642e01fSmrg    {
6464642e01fSmrg	GCPtr	    pGC;
6474642e01fSmrg	xRectangle  rect;
6484642e01fSmrg
6494642e01fSmrg	GlyphExtents (nlist, list, glyphs, &extents);
6504642e01fSmrg
6514642e01fSmrg	if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
6524642e01fSmrg	    return;
6534642e01fSmrg	width = extents.x2 - extents.x1;
6544642e01fSmrg	height = extents.y2 - extents.y1;
6554642e01fSmrg	pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
6564642e01fSmrg						maskFormat->depth,
6574642e01fSmrg						CREATE_PIXMAP_USAGE_SCRATCH);
6584642e01fSmrg	if (!pMaskPixmap)
6594642e01fSmrg	    return;
6604642e01fSmrg	component_alpha = NeedsComponent(maskFormat->format);
6614642e01fSmrg	pMask = CreatePicture (0, &pMaskPixmap->drawable,
6624642e01fSmrg			       maskFormat, CPComponentAlpha, &component_alpha,
6634642e01fSmrg			       serverClient, &error);
6644642e01fSmrg	if (!pMask)
6654642e01fSmrg	{
6664642e01fSmrg	    (*pScreen->DestroyPixmap) (pMaskPixmap);
6674642e01fSmrg	    return;
6684642e01fSmrg	}
6694642e01fSmrg	pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
6704642e01fSmrg	ValidateGC (&pMaskPixmap->drawable, pGC);
6714642e01fSmrg	rect.x = 0;
6724642e01fSmrg	rect.y = 0;
6734642e01fSmrg	rect.width = width;
6744642e01fSmrg	rect.height = height;
6754642e01fSmrg	(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
6764642e01fSmrg	FreeScratchGC (pGC);
6774642e01fSmrg	x = -extents.x1;
6784642e01fSmrg	y = -extents.y1;
6794642e01fSmrg    }
6804642e01fSmrg    else
6814642e01fSmrg    {
6824642e01fSmrg	pMask = pDst;
6834642e01fSmrg	x = 0;
6844642e01fSmrg	y = 0;
6854642e01fSmrg    }
6864642e01fSmrg    while (nlist--)
6874642e01fSmrg    {
6884642e01fSmrg	x += list->xOff;
6894642e01fSmrg	y += list->yOff;
6904642e01fSmrg	n = list->len;
6914642e01fSmrg	while (n--)
6924642e01fSmrg	{
6934642e01fSmrg	    glyph = *glyphs++;
6944642e01fSmrg	    pPicture = GlyphPicture (glyph)[pScreen->myNum];
6954642e01fSmrg
6964202a189Smrg	    if (pPicture)
6974642e01fSmrg	    {
6984202a189Smrg		if (maskFormat)
6994202a189Smrg		{
7004202a189Smrg			CompositePicture (PictOpAdd,
7014202a189Smrg					  pPicture,
7024202a189Smrg					  None,
7034202a189Smrg					  pMask,
7044202a189Smrg					  0, 0,
7054202a189Smrg					  0, 0,
7064202a189Smrg					  x - glyph->info.x,
7074202a189Smrg					  y - glyph->info.y,
7084202a189Smrg					  glyph->info.width,
7094202a189Smrg					  glyph->info.height);
7104202a189Smrg		}
7114202a189Smrg		else
7124202a189Smrg		{
7134202a189Smrg		    CompositePicture (op,
7144202a189Smrg				      pSrc,
7154202a189Smrg				      pPicture,
7164202a189Smrg				      pDst,
7174202a189Smrg				      xSrc + (x - glyph->info.x) - xDst,
7184202a189Smrg				      ySrc + (y - glyph->info.y) - yDst,
7194202a189Smrg				      0, 0,
7204202a189Smrg				      x - glyph->info.x,
7214202a189Smrg				      y - glyph->info.y,
7224202a189Smrg				      glyph->info.width,
7234202a189Smrg				      glyph->info.height);
7244202a189Smrg		}
7254642e01fSmrg	    }
7264642e01fSmrg
7274642e01fSmrg	    x += glyph->info.xOff;
7284642e01fSmrg	    y += glyph->info.yOff;
7294642e01fSmrg	}
7304642e01fSmrg	list++;
7314642e01fSmrg    }
7324642e01fSmrg    if (maskFormat)
7334642e01fSmrg    {
7344642e01fSmrg	x = extents.x1;
7354642e01fSmrg	y = extents.y1;
7364642e01fSmrg	CompositePicture (op,
7374642e01fSmrg			  pSrc,
7384642e01fSmrg			  pMask,
7394642e01fSmrg			  pDst,
7404642e01fSmrg			  xSrc + x - xDst,
7414642e01fSmrg			  ySrc + y - yDst,
7424642e01fSmrg			  0, 0,
7434642e01fSmrg			  x, y,
7444642e01fSmrg			  width, height);
7454642e01fSmrg	FreePicture ((pointer) pMask, (XID) 0);
7464642e01fSmrg	(*pScreen->DestroyPixmap) (pMaskPixmap);
7474642e01fSmrg    }
7484642e01fSmrg}
749