glyph.c revision 4642e01f
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
294642e01fSmrg#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */
304642e01fSmrg# include <sha1.h>
314642e01fSmrg#else /* Use OpenSSL's libcrypto */
324642e01fSmrg# include <stddef.h>  /* buggy openssl/sha.h wants size_t */
334642e01fSmrg# include <openssl/sha.h>
344642e01fSmrg#endif
354642e01fSmrg
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "scrnintstr.h"
3805b261ecSmrg#include "os.h"
3905b261ecSmrg#include "regionstr.h"
4005b261ecSmrg#include "validate.h"
4105b261ecSmrg#include "windowstr.h"
4205b261ecSmrg#include "input.h"
4305b261ecSmrg#include "resource.h"
4405b261ecSmrg#include "colormapst.h"
4505b261ecSmrg#include "cursorstr.h"
4605b261ecSmrg#include "dixstruct.h"
4705b261ecSmrg#include "gcstruct.h"
4805b261ecSmrg#include "servermd.h"
4905b261ecSmrg#include "picturestr.h"
5005b261ecSmrg#include "glyphstr.h"
514642e01fSmrg#include "mipict.h"
5205b261ecSmrg
5305b261ecSmrg/*
5405b261ecSmrg * From Knuth -- a good choice for hash/rehash values is p, p-2 where
5505b261ecSmrg * p and p-2 are both prime.  These tables are sized to have an extra 10%
5605b261ecSmrg * free to avoid exponential performance degradation as the hash table fills
5705b261ecSmrg */
5805b261ecSmrgstatic GlyphHashSetRec glyphHashSets[] = {
5905b261ecSmrg    { 32,		43,		41        },
6005b261ecSmrg    { 64,		73,		71        },
6105b261ecSmrg    { 128,		151,		149       },
6205b261ecSmrg    { 256,		283,		281       },
6305b261ecSmrg    { 512,		571,		569       },
6405b261ecSmrg    { 1024,		1153,		1151      },
6505b261ecSmrg    { 2048,		2269,		2267      },
6605b261ecSmrg    { 4096,		4519,		4517      },
6705b261ecSmrg    { 8192,		9013,		9011      },
6805b261ecSmrg    { 16384,		18043,		18041     },
6905b261ecSmrg    { 32768,		36109,		36107     },
7005b261ecSmrg    { 65536,		72091,		72089     },
7105b261ecSmrg    { 131072,		144409,		144407    },
7205b261ecSmrg    { 262144,		288361,		288359    },
7305b261ecSmrg    { 524288,		576883,		576881    },
7405b261ecSmrg    { 1048576,		1153459,	1153457   },
7505b261ecSmrg    { 2097152,		2307163,	2307161   },
7605b261ecSmrg    { 4194304,		4613893,	4613891   },
7705b261ecSmrg    { 8388608,		9227641,	9227639   },
7805b261ecSmrg    { 16777216,		18455029,	18455027  },
7905b261ecSmrg    { 33554432,		36911011,	36911009  },
8005b261ecSmrg    { 67108864,		73819861,	73819859  },
8105b261ecSmrg    { 134217728,	147639589,	147639587 },
8205b261ecSmrg    { 268435456,	295279081,	295279079 },
8305b261ecSmrg    { 536870912,	590559793,	590559791 }
8405b261ecSmrg};
8505b261ecSmrg
8605b261ecSmrg#define NGLYPHHASHSETS	(sizeof(glyphHashSets)/sizeof(glyphHashSets[0]))
8705b261ecSmrg
8805b261ecSmrgstatic const CARD8	glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 };
8905b261ecSmrg
9005b261ecSmrgstatic GlyphHashRec	globalGlyphs[GlyphFormatNum];
9105b261ecSmrg
9205b261ecSmrgstatic void
934642e01fSmrgFreeGlyphPrivates (GlyphPtr glyph)
9405b261ecSmrg{
954642e01fSmrg    dixFreePrivates(glyph->devPrivates);
964642e01fSmrg    glyph->devPrivates = NULL;
9705b261ecSmrg}
9805b261ecSmrg
9905b261ecSmrgvoid
10005b261ecSmrgGlyphUninit (ScreenPtr pScreen)
10105b261ecSmrg{
10205b261ecSmrg    PictureScreenPtr ps = GetPictureScreen (pScreen);
10305b261ecSmrg    GlyphPtr	     glyph;
10405b261ecSmrg    int		     fdepth, i;
10505b261ecSmrg
10605b261ecSmrg    for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
10705b261ecSmrg    {
10805b261ecSmrg	if (!globalGlyphs[fdepth].hashSet)
10905b261ecSmrg	    continue;
11005b261ecSmrg
11105b261ecSmrg	for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
11205b261ecSmrg	{
11305b261ecSmrg	    glyph = globalGlyphs[fdepth].table[i].glyph;
11405b261ecSmrg	    if (glyph && glyph != DeletedGlyph)
11505b261ecSmrg	    {
11605b261ecSmrg		(*ps->UnrealizeGlyph) (pScreen, glyph);
1174642e01fSmrg		FreeGlyphPrivates(glyph);
11805b261ecSmrg	    }
11905b261ecSmrg	}
12005b261ecSmrg    }
12105b261ecSmrg
12205b261ecSmrg    for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
12305b261ecSmrg    {
12405b261ecSmrg	if (!globalGlyphs[fdepth].hashSet)
12505b261ecSmrg	    continue;
12605b261ecSmrg
12705b261ecSmrg	for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
12805b261ecSmrg	    glyph = globalGlyphs[fdepth].table[i].glyph;
12905b261ecSmrg    }
13005b261ecSmrg}
13105b261ecSmrg
13205b261ecSmrgGlyphHashSetPtr
13305b261ecSmrgFindGlyphHashSet (CARD32 filled)
13405b261ecSmrg{
13505b261ecSmrg    int	i;
13605b261ecSmrg
13705b261ecSmrg    for (i = 0; i < NGLYPHHASHSETS; i++)
13805b261ecSmrg	if (glyphHashSets[i].entries >= filled)
13905b261ecSmrg	    return &glyphHashSets[i];
14005b261ecSmrg    return 0;
14105b261ecSmrg}
14205b261ecSmrg
14305b261ecSmrgGlyphRefPtr
1444642e01fSmrgFindGlyphRef (GlyphHashPtr	hash,
1454642e01fSmrg	      CARD32		signature,
1464642e01fSmrg	      Bool		match,
1474642e01fSmrg	      unsigned char	sha1[20])
14805b261ecSmrg{
14905b261ecSmrg    CARD32	elt, step, s;
15005b261ecSmrg    GlyphPtr	glyph;
15105b261ecSmrg    GlyphRefPtr	table, gr, del;
15205b261ecSmrg    CARD32	tableSize = hash->hashSet->size;
15305b261ecSmrg
15405b261ecSmrg    table = hash->table;
15505b261ecSmrg    elt = signature % tableSize;
15605b261ecSmrg    step = 0;
15705b261ecSmrg    del = 0;
15805b261ecSmrg    for (;;)
15905b261ecSmrg    {
16005b261ecSmrg	gr = &table[elt];
16105b261ecSmrg	s = gr->signature;
16205b261ecSmrg	glyph = gr->glyph;
16305b261ecSmrg	if (!glyph)
16405b261ecSmrg	{
16505b261ecSmrg	    if (del)
16605b261ecSmrg		gr = del;
16705b261ecSmrg	    break;
16805b261ecSmrg	}
16905b261ecSmrg	if (glyph == DeletedGlyph)
17005b261ecSmrg	{
17105b261ecSmrg	    if (!del)
17205b261ecSmrg		del = gr;
17305b261ecSmrg	    else if (gr == del)
17405b261ecSmrg		break;
17505b261ecSmrg	}
17605b261ecSmrg	else if (s == signature &&
17705b261ecSmrg		 (!match ||
1784642e01fSmrg		  memcmp (glyph->sha1, sha1, 20) == 0))
17905b261ecSmrg	{
18005b261ecSmrg	    break;
18105b261ecSmrg	}
18205b261ecSmrg	if (!step)
18305b261ecSmrg	{
18405b261ecSmrg	    step = signature % hash->hashSet->rehash;
18505b261ecSmrg	    if (!step)
18605b261ecSmrg		step = 1;
18705b261ecSmrg	}
18805b261ecSmrg	elt += step;
18905b261ecSmrg	if (elt >= tableSize)
19005b261ecSmrg	    elt -= tableSize;
19105b261ecSmrg    }
19205b261ecSmrg    return gr;
19305b261ecSmrg}
19405b261ecSmrg
1954642e01fSmrgint
1964642e01fSmrgHashGlyph (xGlyphInfo    *gi,
1974642e01fSmrg	   CARD8	 *bits,
1984642e01fSmrg	   unsigned long size,
1994642e01fSmrg	   unsigned char sha1[20])
20005b261ecSmrg{
2014642e01fSmrg#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */
2024642e01fSmrg    SHA1_CTX ctx;
2034642e01fSmrg
2044642e01fSmrg    SHA1Init (&ctx);
2054642e01fSmrg    SHA1Update (&ctx, gi, sizeof (xGlyphInfo));
2064642e01fSmrg    SHA1Update (&ctx, bits, size);
2074642e01fSmrg    SHA1Final (sha1, &ctx);
2084642e01fSmrg#else /* Use OpenSSL's libcrypto */
2094642e01fSmrg    SHA_CTX ctx;
2104642e01fSmrg    int success;
2114642e01fSmrg
2124642e01fSmrg    success = SHA1_Init (&ctx);
2134642e01fSmrg    if (! success)
2144642e01fSmrg	return BadAlloc;
2154642e01fSmrg
2164642e01fSmrg    success = SHA1_Update (&ctx, gi, sizeof (xGlyphInfo));
2174642e01fSmrg    if (! success)
2184642e01fSmrg	return BadAlloc;
2194642e01fSmrg
2204642e01fSmrg    success = SHA1_Update (&ctx, bits, size);
2214642e01fSmrg    if (! success)
2224642e01fSmrg	return BadAlloc;
2234642e01fSmrg
2244642e01fSmrg    success = SHA1_Final (sha1, &ctx);
2254642e01fSmrg    if (! success)
2264642e01fSmrg	return BadAlloc;
2274642e01fSmrg#endif
2284642e01fSmrg
2294642e01fSmrg    return Success;
2304642e01fSmrg}
2314642e01fSmrg
2324642e01fSmrgGlyphPtr
2334642e01fSmrgFindGlyphByHash (unsigned char sha1[20], int format)
2344642e01fSmrg{
2354642e01fSmrg    GlyphRefPtr gr;
2364642e01fSmrg    CARD32 signature = *(CARD32 *) sha1;
2374642e01fSmrg
2384642e01fSmrg    gr = FindGlyphRef (&globalGlyphs[format],
2394642e01fSmrg		       signature, TRUE, sha1);
2404642e01fSmrg
2414642e01fSmrg    if (gr->glyph && gr->glyph != DeletedGlyph)
2424642e01fSmrg	return gr->glyph;
2434642e01fSmrg    else
2444642e01fSmrg	return NULL;
24505b261ecSmrg}
24605b261ecSmrg
24705b261ecSmrg#ifdef CHECK_DUPLICATES
24805b261ecSmrgvoid
24905b261ecSmrgDuplicateRef (GlyphPtr glyph, char *where)
25005b261ecSmrg{
25105b261ecSmrg    ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where);
25205b261ecSmrg}
25305b261ecSmrg
25405b261ecSmrgvoid
25505b261ecSmrgCheckDuplicates (GlyphHashPtr hash, char *where)
25605b261ecSmrg{
25705b261ecSmrg    GlyphPtr	g;
25805b261ecSmrg    int		i, j;
25905b261ecSmrg
26005b261ecSmrg    for (i = 0; i < hash->hashSet->size; i++)
26105b261ecSmrg    {
26205b261ecSmrg	g = hash->table[i].glyph;
26305b261ecSmrg	if (!g || g == DeletedGlyph)
26405b261ecSmrg	    continue;
26505b261ecSmrg	for (j = i + 1; j < hash->hashSet->size; j++)
26605b261ecSmrg	    if (hash->table[j].glyph == g)
26705b261ecSmrg		DuplicateRef (g, where);
26805b261ecSmrg    }
26905b261ecSmrg}
27005b261ecSmrg#else
27105b261ecSmrg#define CheckDuplicates(a,b)
27205b261ecSmrg#define DuplicateRef(a,b)
27305b261ecSmrg#endif
27405b261ecSmrg
27505b261ecSmrgvoid
27605b261ecSmrgFreeGlyph (GlyphPtr glyph, int format)
27705b261ecSmrg{
27805b261ecSmrg    CheckDuplicates (&globalGlyphs[format], "FreeGlyph");
27905b261ecSmrg    if (--glyph->refcnt == 0)
28005b261ecSmrg    {
28105b261ecSmrg	PictureScreenPtr ps;
28205b261ecSmrg	GlyphRefPtr      gr;
28305b261ecSmrg	int	         i;
28405b261ecSmrg	int	         first;
2854642e01fSmrg	CARD32		 signature;
28605b261ecSmrg
28705b261ecSmrg	first = -1;
28805b261ecSmrg	for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
28905b261ecSmrg	    if (globalGlyphs[format].table[i].glyph == glyph)
29005b261ecSmrg	    {
29105b261ecSmrg		if (first != -1)
29205b261ecSmrg		    DuplicateRef (glyph, "FreeGlyph check");
29305b261ecSmrg		first = i;
29405b261ecSmrg	    }
29505b261ecSmrg
2964642e01fSmrg	signature = *(CARD32 *) glyph->sha1;
2974642e01fSmrg	gr = FindGlyphRef (&globalGlyphs[format], signature,
2984642e01fSmrg			   TRUE, glyph->sha1);
29905b261ecSmrg	if (gr - globalGlyphs[format].table != first)
30005b261ecSmrg	    DuplicateRef (glyph, "Found wrong one");
30105b261ecSmrg	if (gr->glyph && gr->glyph != DeletedGlyph)
30205b261ecSmrg	{
30305b261ecSmrg	    gr->glyph = DeletedGlyph;
30405b261ecSmrg	    gr->signature = 0;
30505b261ecSmrg	    globalGlyphs[format].tableEntries--;
30605b261ecSmrg	}
30705b261ecSmrg
30805b261ecSmrg	for (i = 0; i < screenInfo.numScreens; i++)
30905b261ecSmrg	{
3104642e01fSmrg	    ScreenPtr pScreen = screenInfo.screens[i];
3114642e01fSmrg
3124642e01fSmrg	    FreePicture ((pointer) GlyphPicture (glyph)[i], 0);
3134642e01fSmrg
3144642e01fSmrg	    ps = GetPictureScreenIfSet (pScreen);
31505b261ecSmrg	    if (ps)
3164642e01fSmrg		(*ps->UnrealizeGlyph) (pScreen, glyph);
31705b261ecSmrg	}
31805b261ecSmrg
3194642e01fSmrg	FreeGlyphPrivates(glyph);
32005b261ecSmrg	xfree (glyph);
32105b261ecSmrg    }
32205b261ecSmrg}
32305b261ecSmrg
32405b261ecSmrgvoid
32505b261ecSmrgAddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
32605b261ecSmrg{
32705b261ecSmrg    GlyphRefPtr	    gr;
3284642e01fSmrg    CARD32	    signature;
32905b261ecSmrg
33005b261ecSmrg    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
33105b261ecSmrg    /* Locate existing matching glyph */
3324642e01fSmrg    signature = *(CARD32 *) glyph->sha1;
3334642e01fSmrg    gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], signature,
3344642e01fSmrg		       TRUE, glyph->sha1);
3354642e01fSmrg    if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph)
33605b261ecSmrg    {
33705b261ecSmrg	PictureScreenPtr ps;
33805b261ecSmrg	int              i;
33905b261ecSmrg
34005b261ecSmrg	for (i = 0; i < screenInfo.numScreens; i++)
34105b261ecSmrg	{
34205b261ecSmrg	    ps = GetPictureScreenIfSet (screenInfo.screens[i]);
34305b261ecSmrg	    if (ps)
34405b261ecSmrg		(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
34505b261ecSmrg	}
3464642e01fSmrg	FreeGlyphPrivates(glyph);
34705b261ecSmrg	xfree (glyph);
34805b261ecSmrg	glyph = gr->glyph;
34905b261ecSmrg    }
3504642e01fSmrg    else if (gr->glyph != glyph)
35105b261ecSmrg    {
35205b261ecSmrg	gr->glyph = glyph;
3534642e01fSmrg	gr->signature = signature;
35405b261ecSmrg	globalGlyphs[glyphSet->fdepth].tableEntries++;
35505b261ecSmrg    }
35605b261ecSmrg
35705b261ecSmrg    /* Insert/replace glyphset value */
35805b261ecSmrg    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
35905b261ecSmrg    ++glyph->refcnt;
36005b261ecSmrg    if (gr->glyph && gr->glyph != DeletedGlyph)
36105b261ecSmrg	FreeGlyph (gr->glyph, glyphSet->fdepth);
36205b261ecSmrg    else
36305b261ecSmrg	glyphSet->hash.tableEntries++;
36405b261ecSmrg    gr->glyph = glyph;
36505b261ecSmrg    gr->signature = id;
36605b261ecSmrg    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
36705b261ecSmrg}
36805b261ecSmrg
36905b261ecSmrgBool
37005b261ecSmrgDeleteGlyph (GlyphSetPtr glyphSet, Glyph id)
37105b261ecSmrg{
37205b261ecSmrg    GlyphRefPtr     gr;
37305b261ecSmrg    GlyphPtr	    glyph;
37405b261ecSmrg
37505b261ecSmrg    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
37605b261ecSmrg    glyph = gr->glyph;
37705b261ecSmrg    if (glyph && glyph != DeletedGlyph)
37805b261ecSmrg    {
37905b261ecSmrg	gr->glyph = DeletedGlyph;
38005b261ecSmrg	glyphSet->hash.tableEntries--;
38105b261ecSmrg	FreeGlyph (glyph, glyphSet->fdepth);
38205b261ecSmrg	return TRUE;
38305b261ecSmrg    }
38405b261ecSmrg    return FALSE;
38505b261ecSmrg}
38605b261ecSmrg
38705b261ecSmrgGlyphPtr
38805b261ecSmrgFindGlyph (GlyphSetPtr glyphSet, Glyph id)
38905b261ecSmrg{
39005b261ecSmrg    GlyphPtr        glyph;
39105b261ecSmrg
39205b261ecSmrg    glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph;
39305b261ecSmrg    if (glyph == DeletedGlyph)
39405b261ecSmrg	glyph = 0;
39505b261ecSmrg    return glyph;
39605b261ecSmrg}
39705b261ecSmrg
39805b261ecSmrgGlyphPtr
39905b261ecSmrgAllocateGlyph (xGlyphInfo *gi, int fdepth)
40005b261ecSmrg{
40105b261ecSmrg    PictureScreenPtr ps;
40205b261ecSmrg    int		     size;
40305b261ecSmrg    GlyphPtr	     glyph;
40405b261ecSmrg    int		     i;
4054642e01fSmrg
4064642e01fSmrg    size = screenInfo.numScreens * sizeof (PicturePtr);
40705b261ecSmrg    glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec));
40805b261ecSmrg    if (!glyph)
40905b261ecSmrg	return 0;
41005b261ecSmrg    glyph->refcnt = 0;
41105b261ecSmrg    glyph->size = size + sizeof (xGlyphInfo);
41205b261ecSmrg    glyph->info = *gi;
4134642e01fSmrg    glyph->devPrivates = NULL;
41405b261ecSmrg
41505b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++)
41605b261ecSmrg    {
41705b261ecSmrg	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
4184642e01fSmrg
41905b261ecSmrg	if (ps)
42005b261ecSmrg	{
42105b261ecSmrg	    if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph))
4224642e01fSmrg		goto bail;
42305b261ecSmrg	}
42405b261ecSmrg    }
42505b261ecSmrg
42605b261ecSmrg    return glyph;
4274642e01fSmrg
4284642e01fSmrgbail:
4294642e01fSmrg    while (i--)
4304642e01fSmrg    {
4314642e01fSmrg	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
4324642e01fSmrg	if (ps)
4334642e01fSmrg	    (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
4344642e01fSmrg    }
4354642e01fSmrg
4364642e01fSmrg    FreeGlyphPrivates(glyph);
4374642e01fSmrg    xfree (glyph);
4384642e01fSmrg    return 0;
43905b261ecSmrg}
44005b261ecSmrg
44105b261ecSmrgBool
44205b261ecSmrgAllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet)
44305b261ecSmrg{
4444642e01fSmrg    hash->table = xcalloc (hashSet->size, sizeof (GlyphRefRec));
44505b261ecSmrg    if (!hash->table)
44605b261ecSmrg	return FALSE;
44705b261ecSmrg    hash->hashSet = hashSet;
44805b261ecSmrg    hash->tableEntries = 0;
44905b261ecSmrg    return TRUE;
45005b261ecSmrg}
45105b261ecSmrg
45205b261ecSmrgBool
45305b261ecSmrgResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global)
45405b261ecSmrg{
45505b261ecSmrg    CARD32	    tableEntries;
45605b261ecSmrg    GlyphHashSetPtr hashSet;
45705b261ecSmrg    GlyphHashRec    newHash;
45805b261ecSmrg    GlyphRefPtr	    gr;
45905b261ecSmrg    GlyphPtr	    glyph;
46005b261ecSmrg    int		    i;
46105b261ecSmrg    int		    oldSize;
46205b261ecSmrg    CARD32	    s;
46305b261ecSmrg
46405b261ecSmrg    tableEntries = hash->tableEntries + change;
46505b261ecSmrg    hashSet = FindGlyphHashSet (tableEntries);
46605b261ecSmrg    if (hashSet == hash->hashSet)
46705b261ecSmrg	return TRUE;
46805b261ecSmrg    if (global)
46905b261ecSmrg	CheckDuplicates (hash, "ResizeGlyphHash top");
47005b261ecSmrg    if (!AllocateGlyphHash (&newHash, hashSet))
47105b261ecSmrg	return FALSE;
47205b261ecSmrg    if (hash->table)
47305b261ecSmrg    {
47405b261ecSmrg	oldSize = hash->hashSet->size;
47505b261ecSmrg	for (i = 0; i < oldSize; i++)
47605b261ecSmrg	{
47705b261ecSmrg	    glyph = hash->table[i].glyph;
47805b261ecSmrg	    if (glyph && glyph != DeletedGlyph)
47905b261ecSmrg	    {
48005b261ecSmrg		s = hash->table[i].signature;
4814642e01fSmrg		gr = FindGlyphRef (&newHash, s, global, glyph->sha1);
48205b261ecSmrg		gr->signature = s;
48305b261ecSmrg		gr->glyph = glyph;
48405b261ecSmrg		++newHash.tableEntries;
48505b261ecSmrg	    }
48605b261ecSmrg	}
48705b261ecSmrg	xfree (hash->table);
48805b261ecSmrg    }
48905b261ecSmrg    *hash = newHash;
49005b261ecSmrg    if (global)
49105b261ecSmrg	CheckDuplicates (hash, "ResizeGlyphHash bottom");
49205b261ecSmrg    return TRUE;
49305b261ecSmrg}
49405b261ecSmrg
49505b261ecSmrgBool
49605b261ecSmrgResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change)
49705b261ecSmrg{
49805b261ecSmrg    return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) &&
49905b261ecSmrg	    ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE));
50005b261ecSmrg}
50105b261ecSmrg
50205b261ecSmrgGlyphSetPtr
50305b261ecSmrgAllocateGlyphSet (int fdepth, PictFormatPtr format)
50405b261ecSmrg{
50505b261ecSmrg    GlyphSetPtr	glyphSet;
50605b261ecSmrg    int size;
50705b261ecSmrg
50805b261ecSmrg    if (!globalGlyphs[fdepth].hashSet)
50905b261ecSmrg    {
51005b261ecSmrg	if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0]))
51105b261ecSmrg	    return FALSE;
51205b261ecSmrg    }
51305b261ecSmrg
5144642e01fSmrg    size = sizeof (GlyphSetRec);
5154642e01fSmrg    glyphSet = xcalloc (1, size);
51605b261ecSmrg    if (!glyphSet)
51705b261ecSmrg	return FALSE;
51805b261ecSmrg
51905b261ecSmrg    if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0]))
52005b261ecSmrg    {
52105b261ecSmrg	xfree (glyphSet);
52205b261ecSmrg	return FALSE;
52305b261ecSmrg    }
52405b261ecSmrg    glyphSet->refcnt = 1;
52505b261ecSmrg    glyphSet->fdepth = fdepth;
52605b261ecSmrg    glyphSet->format = format;
52705b261ecSmrg    return glyphSet;
52805b261ecSmrg}
52905b261ecSmrg
53005b261ecSmrgint
53105b261ecSmrgFreeGlyphSet (pointer	value,
53205b261ecSmrg	      XID       gid)
53305b261ecSmrg{
53405b261ecSmrg    GlyphSetPtr	glyphSet = (GlyphSetPtr) value;
53505b261ecSmrg
53605b261ecSmrg    if (--glyphSet->refcnt == 0)
53705b261ecSmrg    {
53805b261ecSmrg	CARD32	    i, tableSize = glyphSet->hash.hashSet->size;
53905b261ecSmrg	GlyphRefPtr table = glyphSet->hash.table;
54005b261ecSmrg	GlyphPtr    glyph;
54105b261ecSmrg
54205b261ecSmrg	for (i = 0; i < tableSize; i++)
54305b261ecSmrg	{
54405b261ecSmrg	    glyph = table[i].glyph;
54505b261ecSmrg	    if (glyph && glyph != DeletedGlyph)
54605b261ecSmrg		FreeGlyph (glyph, glyphSet->fdepth);
54705b261ecSmrg	}
54805b261ecSmrg	if (!globalGlyphs[glyphSet->fdepth].tableEntries)
54905b261ecSmrg	{
55005b261ecSmrg	    xfree (globalGlyphs[glyphSet->fdepth].table);
55105b261ecSmrg	    globalGlyphs[glyphSet->fdepth].table = 0;
55205b261ecSmrg	    globalGlyphs[glyphSet->fdepth].hashSet = 0;
55305b261ecSmrg	}
55405b261ecSmrg	else
55505b261ecSmrg	    ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE);
55605b261ecSmrg	xfree (table);
5574642e01fSmrg	dixFreePrivates(glyphSet->devPrivates);
55805b261ecSmrg	xfree (glyphSet);
55905b261ecSmrg    }
56005b261ecSmrg    return Success;
56105b261ecSmrg}
5624642e01fSmrg
5634642e01fSmrgstatic void
5644642e01fSmrgGlyphExtents (int		nlist,
5654642e01fSmrg		GlyphListPtr	list,
5664642e01fSmrg		GlyphPtr	*glyphs,
5674642e01fSmrg		BoxPtr		extents)
5684642e01fSmrg{
5694642e01fSmrg    int		x1, x2, y1, y2;
5704642e01fSmrg    int		n;
5714642e01fSmrg    GlyphPtr	glyph;
5724642e01fSmrg    int		x, y;
5734642e01fSmrg
5744642e01fSmrg    x = 0;
5754642e01fSmrg    y = 0;
5764642e01fSmrg    extents->x1 = MAXSHORT;
5774642e01fSmrg    extents->x2 = MINSHORT;
5784642e01fSmrg    extents->y1 = MAXSHORT;
5794642e01fSmrg    extents->y2 = MINSHORT;
5804642e01fSmrg    while (nlist--)
5814642e01fSmrg    {
5824642e01fSmrg	x += list->xOff;
5834642e01fSmrg	y += list->yOff;
5844642e01fSmrg	n = list->len;
5854642e01fSmrg	list++;
5864642e01fSmrg	while (n--)
5874642e01fSmrg	{
5884642e01fSmrg	    glyph = *glyphs++;
5894642e01fSmrg	    x1 = x - glyph->info.x;
5904642e01fSmrg	    if (x1 < MINSHORT)
5914642e01fSmrg		x1 = MINSHORT;
5924642e01fSmrg	    y1 = y - glyph->info.y;
5934642e01fSmrg	    if (y1 < MINSHORT)
5944642e01fSmrg		y1 = MINSHORT;
5954642e01fSmrg	    x2 = x1 + glyph->info.width;
5964642e01fSmrg	    if (x2 > MAXSHORT)
5974642e01fSmrg		x2 = MAXSHORT;
5984642e01fSmrg	    y2 = y1 + glyph->info.height;
5994642e01fSmrg	    if (y2 > MAXSHORT)
6004642e01fSmrg		y2 = MAXSHORT;
6014642e01fSmrg	    if (x1 < extents->x1)
6024642e01fSmrg		extents->x1 = x1;
6034642e01fSmrg	    if (x2 > extents->x2)
6044642e01fSmrg		extents->x2 = x2;
6054642e01fSmrg	    if (y1 < extents->y1)
6064642e01fSmrg		extents->y1 = y1;
6074642e01fSmrg	    if (y2 > extents->y2)
6084642e01fSmrg		extents->y2 = y2;
6094642e01fSmrg	    x += glyph->info.xOff;
6104642e01fSmrg	    y += glyph->info.yOff;
6114642e01fSmrg	}
6124642e01fSmrg    }
6134642e01fSmrg}
6144642e01fSmrg
6154642e01fSmrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
6164642e01fSmrg
6174642e01fSmrg_X_EXPORT void
6184642e01fSmrgCompositeGlyphs (CARD8		op,
6194642e01fSmrg		 PicturePtr	pSrc,
6204642e01fSmrg		 PicturePtr	pDst,
6214642e01fSmrg		 PictFormatPtr	maskFormat,
6224642e01fSmrg		 INT16		xSrc,
6234642e01fSmrg		 INT16		ySrc,
6244642e01fSmrg		 int		nlist,
6254642e01fSmrg		 GlyphListPtr	lists,
6264642e01fSmrg		 GlyphPtr	*glyphs)
6274642e01fSmrg{
6284642e01fSmrg    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
6294642e01fSmrg
6304642e01fSmrg    ValidatePicture (pSrc);
6314642e01fSmrg    ValidatePicture (pDst);
6324642e01fSmrg    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs);
6334642e01fSmrg}
6344642e01fSmrg
6354642e01fSmrgBool
6364642e01fSmrgmiRealizeGlyph (ScreenPtr pScreen,
6374642e01fSmrg		GlyphPtr  glyph)
6384642e01fSmrg{
6394642e01fSmrg    return TRUE;
6404642e01fSmrg}
6414642e01fSmrg
6424642e01fSmrgvoid
6434642e01fSmrgmiUnrealizeGlyph (ScreenPtr pScreen,
6444642e01fSmrg		  GlyphPtr  glyph)
6454642e01fSmrg{
6464642e01fSmrg}
6474642e01fSmrg
6484642e01fSmrg_X_EXPORT void
6494642e01fSmrgmiGlyphs (CARD8		op,
6504642e01fSmrg	  PicturePtr	pSrc,
6514642e01fSmrg	  PicturePtr	pDst,
6524642e01fSmrg	  PictFormatPtr	maskFormat,
6534642e01fSmrg	  INT16		xSrc,
6544642e01fSmrg	  INT16		ySrc,
6554642e01fSmrg	  int		nlist,
6564642e01fSmrg	  GlyphListPtr	list,
6574642e01fSmrg	  GlyphPtr	*glyphs)
6584642e01fSmrg{
6594642e01fSmrg    PicturePtr	pPicture;
6604642e01fSmrg    PixmapPtr   pMaskPixmap = 0;
6614642e01fSmrg    PicturePtr  pMask;
6624642e01fSmrg    ScreenPtr   pScreen = pDst->pDrawable->pScreen;
6634642e01fSmrg    int		width = 0, height = 0;
6644642e01fSmrg    int		x, y;
6654642e01fSmrg    int		xDst = list->xOff, yDst = list->yOff;
6664642e01fSmrg    int		n;
6674642e01fSmrg    GlyphPtr	glyph;
6684642e01fSmrg    int		error;
6694642e01fSmrg    BoxRec	extents = {0, 0, 0, 0};
6704642e01fSmrg    CARD32	component_alpha;
6714642e01fSmrg
6724642e01fSmrg    if (maskFormat)
6734642e01fSmrg    {
6744642e01fSmrg	GCPtr	    pGC;
6754642e01fSmrg	xRectangle  rect;
6764642e01fSmrg
6774642e01fSmrg	GlyphExtents (nlist, list, glyphs, &extents);
6784642e01fSmrg
6794642e01fSmrg	if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
6804642e01fSmrg	    return;
6814642e01fSmrg	width = extents.x2 - extents.x1;
6824642e01fSmrg	height = extents.y2 - extents.y1;
6834642e01fSmrg	pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
6844642e01fSmrg						maskFormat->depth,
6854642e01fSmrg						CREATE_PIXMAP_USAGE_SCRATCH);
6864642e01fSmrg	if (!pMaskPixmap)
6874642e01fSmrg	    return;
6884642e01fSmrg	component_alpha = NeedsComponent(maskFormat->format);
6894642e01fSmrg	pMask = CreatePicture (0, &pMaskPixmap->drawable,
6904642e01fSmrg			       maskFormat, CPComponentAlpha, &component_alpha,
6914642e01fSmrg			       serverClient, &error);
6924642e01fSmrg	if (!pMask)
6934642e01fSmrg	{
6944642e01fSmrg	    (*pScreen->DestroyPixmap) (pMaskPixmap);
6954642e01fSmrg	    return;
6964642e01fSmrg	}
6974642e01fSmrg	pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
6984642e01fSmrg	ValidateGC (&pMaskPixmap->drawable, pGC);
6994642e01fSmrg	rect.x = 0;
7004642e01fSmrg	rect.y = 0;
7014642e01fSmrg	rect.width = width;
7024642e01fSmrg	rect.height = height;
7034642e01fSmrg	(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
7044642e01fSmrg	FreeScratchGC (pGC);
7054642e01fSmrg	x = -extents.x1;
7064642e01fSmrg	y = -extents.y1;
7074642e01fSmrg    }
7084642e01fSmrg    else
7094642e01fSmrg    {
7104642e01fSmrg	pMask = pDst;
7114642e01fSmrg	x = 0;
7124642e01fSmrg	y = 0;
7134642e01fSmrg    }
7144642e01fSmrg    while (nlist--)
7154642e01fSmrg    {
7164642e01fSmrg	x += list->xOff;
7174642e01fSmrg	y += list->yOff;
7184642e01fSmrg	n = list->len;
7194642e01fSmrg	while (n--)
7204642e01fSmrg	{
7214642e01fSmrg	    glyph = *glyphs++;
7224642e01fSmrg	    pPicture = GlyphPicture (glyph)[pScreen->myNum];
7234642e01fSmrg
7244642e01fSmrg	    if (maskFormat)
7254642e01fSmrg	    {
7264642e01fSmrg		CompositePicture (PictOpAdd,
7274642e01fSmrg				  pPicture,
7284642e01fSmrg				  None,
7294642e01fSmrg				  pMask,
7304642e01fSmrg				  0, 0,
7314642e01fSmrg				  0, 0,
7324642e01fSmrg				  x - glyph->info.x,
7334642e01fSmrg				  y - glyph->info.y,
7344642e01fSmrg				  glyph->info.width,
7354642e01fSmrg				  glyph->info.height);
7364642e01fSmrg	    }
7374642e01fSmrg	    else
7384642e01fSmrg	    {
7394642e01fSmrg		CompositePicture (op,
7404642e01fSmrg				  pSrc,
7414642e01fSmrg				  pPicture,
7424642e01fSmrg				  pDst,
7434642e01fSmrg				  xSrc + (x - glyph->info.x) - xDst,
7444642e01fSmrg				  ySrc + (y - glyph->info.y) - yDst,
7454642e01fSmrg				  0, 0,
7464642e01fSmrg				  x - glyph->info.x,
7474642e01fSmrg				  y - glyph->info.y,
7484642e01fSmrg				  glyph->info.width,
7494642e01fSmrg				  glyph->info.height);
7504642e01fSmrg	    }
7514642e01fSmrg
7524642e01fSmrg	    x += glyph->info.xOff;
7534642e01fSmrg	    y += glyph->info.yOff;
7544642e01fSmrg	}
7554642e01fSmrg	list++;
7564642e01fSmrg    }
7574642e01fSmrg    if (maskFormat)
7584642e01fSmrg    {
7594642e01fSmrg	x = extents.x1;
7604642e01fSmrg	y = extents.y1;
7614642e01fSmrg	CompositePicture (op,
7624642e01fSmrg			  pSrc,
7634642e01fSmrg			  pMask,
7644642e01fSmrg			  pDst,
7654642e01fSmrg			  xSrc + x - xDst,
7664642e01fSmrg			  ySrc + y - yDst,
7674642e01fSmrg			  0, 0,
7684642e01fSmrg			  x, y,
7694642e01fSmrg			  width, height);
7704642e01fSmrg	FreePicture ((pointer) pMask, (XID) 0);
7714642e01fSmrg	(*pScreen->DestroyPixmap) (pMaskPixmap);
7724642e01fSmrg    }
7734642e01fSmrg}
774