glyph.c revision ad5464f4
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
238ad5464f4Smrg    if (!globalGlyphs[format].hashSet)
239ad5464f4Smrg        return NULL;
240ad5464f4Smrg
2414642e01fSmrg    gr = FindGlyphRef (&globalGlyphs[format],
2424642e01fSmrg		       signature, TRUE, sha1);
2434642e01fSmrg
2444642e01fSmrg    if (gr->glyph && gr->glyph != DeletedGlyph)
2454642e01fSmrg	return gr->glyph;
2464642e01fSmrg    else
2474642e01fSmrg	return NULL;
24805b261ecSmrg}
24905b261ecSmrg
25005b261ecSmrg#ifdef CHECK_DUPLICATES
25105b261ecSmrgvoid
25205b261ecSmrgDuplicateRef (GlyphPtr glyph, char *where)
25305b261ecSmrg{
25405b261ecSmrg    ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where);
25505b261ecSmrg}
25605b261ecSmrg
25705b261ecSmrgvoid
25805b261ecSmrgCheckDuplicates (GlyphHashPtr hash, char *where)
25905b261ecSmrg{
26005b261ecSmrg    GlyphPtr	g;
26105b261ecSmrg    int		i, j;
26205b261ecSmrg
26305b261ecSmrg    for (i = 0; i < hash->hashSet->size; i++)
26405b261ecSmrg    {
26505b261ecSmrg	g = hash->table[i].glyph;
26605b261ecSmrg	if (!g || g == DeletedGlyph)
26705b261ecSmrg	    continue;
26805b261ecSmrg	for (j = i + 1; j < hash->hashSet->size; j++)
26905b261ecSmrg	    if (hash->table[j].glyph == g)
27005b261ecSmrg		DuplicateRef (g, where);
27105b261ecSmrg    }
27205b261ecSmrg}
27305b261ecSmrg#else
27405b261ecSmrg#define CheckDuplicates(a,b)
27505b261ecSmrg#define DuplicateRef(a,b)
27605b261ecSmrg#endif
27705b261ecSmrg
27805b261ecSmrgvoid
27905b261ecSmrgFreeGlyph (GlyphPtr glyph, int format)
28005b261ecSmrg{
28105b261ecSmrg    CheckDuplicates (&globalGlyphs[format], "FreeGlyph");
28205b261ecSmrg    if (--glyph->refcnt == 0)
28305b261ecSmrg    {
28405b261ecSmrg	PictureScreenPtr ps;
28505b261ecSmrg	GlyphRefPtr      gr;
28605b261ecSmrg	int	         i;
28705b261ecSmrg	int	         first;
2884642e01fSmrg	CARD32		 signature;
28905b261ecSmrg
29005b261ecSmrg	first = -1;
29105b261ecSmrg	for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
29205b261ecSmrg	    if (globalGlyphs[format].table[i].glyph == glyph)
29305b261ecSmrg	    {
29405b261ecSmrg		if (first != -1)
29505b261ecSmrg		    DuplicateRef (glyph, "FreeGlyph check");
29605b261ecSmrg		first = i;
29705b261ecSmrg	    }
29805b261ecSmrg
2994642e01fSmrg	signature = *(CARD32 *) glyph->sha1;
3004642e01fSmrg	gr = FindGlyphRef (&globalGlyphs[format], signature,
3014642e01fSmrg			   TRUE, glyph->sha1);
30205b261ecSmrg	if (gr - globalGlyphs[format].table != first)
30305b261ecSmrg	    DuplicateRef (glyph, "Found wrong one");
30405b261ecSmrg	if (gr->glyph && gr->glyph != DeletedGlyph)
30505b261ecSmrg	{
30605b261ecSmrg	    gr->glyph = DeletedGlyph;
30705b261ecSmrg	    gr->signature = 0;
30805b261ecSmrg	    globalGlyphs[format].tableEntries--;
30905b261ecSmrg	}
31005b261ecSmrg
31105b261ecSmrg	for (i = 0; i < screenInfo.numScreens; i++)
31205b261ecSmrg	{
3134642e01fSmrg	    ScreenPtr pScreen = screenInfo.screens[i];
3144642e01fSmrg
3154642e01fSmrg	    FreePicture ((pointer) GlyphPicture (glyph)[i], 0);
3164642e01fSmrg
3174642e01fSmrg	    ps = GetPictureScreenIfSet (pScreen);
31805b261ecSmrg	    if (ps)
3194642e01fSmrg		(*ps->UnrealizeGlyph) (pScreen, glyph);
32005b261ecSmrg	}
32105b261ecSmrg
3224642e01fSmrg	FreeGlyphPrivates(glyph);
32305b261ecSmrg	xfree (glyph);
32405b261ecSmrg    }
32505b261ecSmrg}
32605b261ecSmrg
32705b261ecSmrgvoid
32805b261ecSmrgAddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
32905b261ecSmrg{
33005b261ecSmrg    GlyphRefPtr	    gr;
3314642e01fSmrg    CARD32	    signature;
33205b261ecSmrg
33305b261ecSmrg    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
33405b261ecSmrg    /* Locate existing matching glyph */
3354642e01fSmrg    signature = *(CARD32 *) glyph->sha1;
3364642e01fSmrg    gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], signature,
3374642e01fSmrg		       TRUE, glyph->sha1);
3384642e01fSmrg    if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph)
33905b261ecSmrg    {
34005b261ecSmrg	PictureScreenPtr ps;
34105b261ecSmrg	int              i;
34205b261ecSmrg
34305b261ecSmrg	for (i = 0; i < screenInfo.numScreens; i++)
34405b261ecSmrg	{
34505b261ecSmrg	    ps = GetPictureScreenIfSet (screenInfo.screens[i]);
34605b261ecSmrg	    if (ps)
34705b261ecSmrg		(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
34805b261ecSmrg	}
3494642e01fSmrg	FreeGlyphPrivates(glyph);
35005b261ecSmrg	xfree (glyph);
35105b261ecSmrg	glyph = gr->glyph;
35205b261ecSmrg    }
3534642e01fSmrg    else if (gr->glyph != glyph)
35405b261ecSmrg    {
35505b261ecSmrg	gr->glyph = glyph;
3564642e01fSmrg	gr->signature = signature;
35705b261ecSmrg	globalGlyphs[glyphSet->fdepth].tableEntries++;
35805b261ecSmrg    }
35905b261ecSmrg
36005b261ecSmrg    /* Insert/replace glyphset value */
36105b261ecSmrg    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
36205b261ecSmrg    ++glyph->refcnt;
36305b261ecSmrg    if (gr->glyph && gr->glyph != DeletedGlyph)
36405b261ecSmrg	FreeGlyph (gr->glyph, glyphSet->fdepth);
36505b261ecSmrg    else
36605b261ecSmrg	glyphSet->hash.tableEntries++;
36705b261ecSmrg    gr->glyph = glyph;
36805b261ecSmrg    gr->signature = id;
36905b261ecSmrg    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
37005b261ecSmrg}
37105b261ecSmrg
37205b261ecSmrgBool
37305b261ecSmrgDeleteGlyph (GlyphSetPtr glyphSet, Glyph id)
37405b261ecSmrg{
37505b261ecSmrg    GlyphRefPtr     gr;
37605b261ecSmrg    GlyphPtr	    glyph;
37705b261ecSmrg
37805b261ecSmrg    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
37905b261ecSmrg    glyph = gr->glyph;
38005b261ecSmrg    if (glyph && glyph != DeletedGlyph)
38105b261ecSmrg    {
38205b261ecSmrg	gr->glyph = DeletedGlyph;
38305b261ecSmrg	glyphSet->hash.tableEntries--;
38405b261ecSmrg	FreeGlyph (glyph, glyphSet->fdepth);
38505b261ecSmrg	return TRUE;
38605b261ecSmrg    }
38705b261ecSmrg    return FALSE;
38805b261ecSmrg}
38905b261ecSmrg
39005b261ecSmrgGlyphPtr
39105b261ecSmrgFindGlyph (GlyphSetPtr glyphSet, Glyph id)
39205b261ecSmrg{
39305b261ecSmrg    GlyphPtr        glyph;
39405b261ecSmrg
39505b261ecSmrg    glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph;
39605b261ecSmrg    if (glyph == DeletedGlyph)
39705b261ecSmrg	glyph = 0;
39805b261ecSmrg    return glyph;
39905b261ecSmrg}
40005b261ecSmrg
40105b261ecSmrgGlyphPtr
40205b261ecSmrgAllocateGlyph (xGlyphInfo *gi, int fdepth)
40305b261ecSmrg{
40405b261ecSmrg    PictureScreenPtr ps;
40505b261ecSmrg    int		     size;
40605b261ecSmrg    GlyphPtr	     glyph;
40705b261ecSmrg    int		     i;
4084642e01fSmrg
4094642e01fSmrg    size = screenInfo.numScreens * sizeof (PicturePtr);
41005b261ecSmrg    glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec));
41105b261ecSmrg    if (!glyph)
41205b261ecSmrg	return 0;
41305b261ecSmrg    glyph->refcnt = 0;
41405b261ecSmrg    glyph->size = size + sizeof (xGlyphInfo);
41505b261ecSmrg    glyph->info = *gi;
4164642e01fSmrg    glyph->devPrivates = NULL;
41705b261ecSmrg
41805b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++)
41905b261ecSmrg    {
42005b261ecSmrg	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
4214642e01fSmrg
42205b261ecSmrg	if (ps)
42305b261ecSmrg	{
42405b261ecSmrg	    if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph))
4254642e01fSmrg		goto bail;
42605b261ecSmrg	}
42705b261ecSmrg    }
42805b261ecSmrg
42905b261ecSmrg    return glyph;
4304642e01fSmrg
4314642e01fSmrgbail:
4324642e01fSmrg    while (i--)
4334642e01fSmrg    {
4344642e01fSmrg	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
4354642e01fSmrg	if (ps)
4364642e01fSmrg	    (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
4374642e01fSmrg    }
4384642e01fSmrg
4394642e01fSmrg    FreeGlyphPrivates(glyph);
4404642e01fSmrg    xfree (glyph);
4414642e01fSmrg    return 0;
44205b261ecSmrg}
44305b261ecSmrg
44405b261ecSmrgBool
44505b261ecSmrgAllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet)
44605b261ecSmrg{
4474642e01fSmrg    hash->table = xcalloc (hashSet->size, sizeof (GlyphRefRec));
44805b261ecSmrg    if (!hash->table)
44905b261ecSmrg	return FALSE;
45005b261ecSmrg    hash->hashSet = hashSet;
45105b261ecSmrg    hash->tableEntries = 0;
45205b261ecSmrg    return TRUE;
45305b261ecSmrg}
45405b261ecSmrg
45505b261ecSmrgBool
45605b261ecSmrgResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global)
45705b261ecSmrg{
45805b261ecSmrg    CARD32	    tableEntries;
45905b261ecSmrg    GlyphHashSetPtr hashSet;
46005b261ecSmrg    GlyphHashRec    newHash;
46105b261ecSmrg    GlyphRefPtr	    gr;
46205b261ecSmrg    GlyphPtr	    glyph;
46305b261ecSmrg    int		    i;
46405b261ecSmrg    int		    oldSize;
46505b261ecSmrg    CARD32	    s;
46605b261ecSmrg
46705b261ecSmrg    tableEntries = hash->tableEntries + change;
46805b261ecSmrg    hashSet = FindGlyphHashSet (tableEntries);
46905b261ecSmrg    if (hashSet == hash->hashSet)
47005b261ecSmrg	return TRUE;
47105b261ecSmrg    if (global)
47205b261ecSmrg	CheckDuplicates (hash, "ResizeGlyphHash top");
47305b261ecSmrg    if (!AllocateGlyphHash (&newHash, hashSet))
47405b261ecSmrg	return FALSE;
47505b261ecSmrg    if (hash->table)
47605b261ecSmrg    {
47705b261ecSmrg	oldSize = hash->hashSet->size;
47805b261ecSmrg	for (i = 0; i < oldSize; i++)
47905b261ecSmrg	{
48005b261ecSmrg	    glyph = hash->table[i].glyph;
48105b261ecSmrg	    if (glyph && glyph != DeletedGlyph)
48205b261ecSmrg	    {
48305b261ecSmrg		s = hash->table[i].signature;
4844642e01fSmrg		gr = FindGlyphRef (&newHash, s, global, glyph->sha1);
48505b261ecSmrg		gr->signature = s;
48605b261ecSmrg		gr->glyph = glyph;
48705b261ecSmrg		++newHash.tableEntries;
48805b261ecSmrg	    }
48905b261ecSmrg	}
49005b261ecSmrg	xfree (hash->table);
49105b261ecSmrg    }
49205b261ecSmrg    *hash = newHash;
49305b261ecSmrg    if (global)
49405b261ecSmrg	CheckDuplicates (hash, "ResizeGlyphHash bottom");
49505b261ecSmrg    return TRUE;
49605b261ecSmrg}
49705b261ecSmrg
49805b261ecSmrgBool
49905b261ecSmrgResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change)
50005b261ecSmrg{
50105b261ecSmrg    return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) &&
50205b261ecSmrg	    ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE));
50305b261ecSmrg}
50405b261ecSmrg
50505b261ecSmrgGlyphSetPtr
50605b261ecSmrgAllocateGlyphSet (int fdepth, PictFormatPtr format)
50705b261ecSmrg{
50805b261ecSmrg    GlyphSetPtr	glyphSet;
50905b261ecSmrg    int size;
51005b261ecSmrg
51105b261ecSmrg    if (!globalGlyphs[fdepth].hashSet)
51205b261ecSmrg    {
51305b261ecSmrg	if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0]))
51405b261ecSmrg	    return FALSE;
51505b261ecSmrg    }
51605b261ecSmrg
5174642e01fSmrg    size = sizeof (GlyphSetRec);
5184642e01fSmrg    glyphSet = xcalloc (1, size);
51905b261ecSmrg    if (!glyphSet)
52005b261ecSmrg	return FALSE;
52105b261ecSmrg
52205b261ecSmrg    if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0]))
52305b261ecSmrg    {
52405b261ecSmrg	xfree (glyphSet);
52505b261ecSmrg	return FALSE;
52605b261ecSmrg    }
52705b261ecSmrg    glyphSet->refcnt = 1;
52805b261ecSmrg    glyphSet->fdepth = fdepth;
52905b261ecSmrg    glyphSet->format = format;
53005b261ecSmrg    return glyphSet;
53105b261ecSmrg}
53205b261ecSmrg
53305b261ecSmrgint
53405b261ecSmrgFreeGlyphSet (pointer	value,
53505b261ecSmrg	      XID       gid)
53605b261ecSmrg{
53705b261ecSmrg    GlyphSetPtr	glyphSet = (GlyphSetPtr) value;
53805b261ecSmrg
53905b261ecSmrg    if (--glyphSet->refcnt == 0)
54005b261ecSmrg    {
54105b261ecSmrg	CARD32	    i, tableSize = glyphSet->hash.hashSet->size;
54205b261ecSmrg	GlyphRefPtr table = glyphSet->hash.table;
54305b261ecSmrg	GlyphPtr    glyph;
54405b261ecSmrg
54505b261ecSmrg	for (i = 0; i < tableSize; i++)
54605b261ecSmrg	{
54705b261ecSmrg	    glyph = table[i].glyph;
54805b261ecSmrg	    if (glyph && glyph != DeletedGlyph)
54905b261ecSmrg		FreeGlyph (glyph, glyphSet->fdepth);
55005b261ecSmrg	}
55105b261ecSmrg	if (!globalGlyphs[glyphSet->fdepth].tableEntries)
55205b261ecSmrg	{
55305b261ecSmrg	    xfree (globalGlyphs[glyphSet->fdepth].table);
55405b261ecSmrg	    globalGlyphs[glyphSet->fdepth].table = 0;
55505b261ecSmrg	    globalGlyphs[glyphSet->fdepth].hashSet = 0;
55605b261ecSmrg	}
55705b261ecSmrg	else
55805b261ecSmrg	    ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE);
55905b261ecSmrg	xfree (table);
5604642e01fSmrg	dixFreePrivates(glyphSet->devPrivates);
56105b261ecSmrg	xfree (glyphSet);
56205b261ecSmrg    }
56305b261ecSmrg    return Success;
56405b261ecSmrg}
5654642e01fSmrg
5664642e01fSmrgstatic void
5674642e01fSmrgGlyphExtents (int		nlist,
5684642e01fSmrg		GlyphListPtr	list,
5694642e01fSmrg		GlyphPtr	*glyphs,
5704642e01fSmrg		BoxPtr		extents)
5714642e01fSmrg{
5724642e01fSmrg    int		x1, x2, y1, y2;
5734642e01fSmrg    int		n;
5744642e01fSmrg    GlyphPtr	glyph;
5754642e01fSmrg    int		x, y;
5764642e01fSmrg
5774642e01fSmrg    x = 0;
5784642e01fSmrg    y = 0;
5794642e01fSmrg    extents->x1 = MAXSHORT;
5804642e01fSmrg    extents->x2 = MINSHORT;
5814642e01fSmrg    extents->y1 = MAXSHORT;
5824642e01fSmrg    extents->y2 = MINSHORT;
5834642e01fSmrg    while (nlist--)
5844642e01fSmrg    {
5854642e01fSmrg	x += list->xOff;
5864642e01fSmrg	y += list->yOff;
5874642e01fSmrg	n = list->len;
5884642e01fSmrg	list++;
5894642e01fSmrg	while (n--)
5904642e01fSmrg	{
5914642e01fSmrg	    glyph = *glyphs++;
5924642e01fSmrg	    x1 = x - glyph->info.x;
5934642e01fSmrg	    if (x1 < MINSHORT)
5944642e01fSmrg		x1 = MINSHORT;
5954642e01fSmrg	    y1 = y - glyph->info.y;
5964642e01fSmrg	    if (y1 < MINSHORT)
5974642e01fSmrg		y1 = MINSHORT;
5984642e01fSmrg	    x2 = x1 + glyph->info.width;
5994642e01fSmrg	    if (x2 > MAXSHORT)
6004642e01fSmrg		x2 = MAXSHORT;
6014642e01fSmrg	    y2 = y1 + glyph->info.height;
6024642e01fSmrg	    if (y2 > MAXSHORT)
6034642e01fSmrg		y2 = MAXSHORT;
6044642e01fSmrg	    if (x1 < extents->x1)
6054642e01fSmrg		extents->x1 = x1;
6064642e01fSmrg	    if (x2 > extents->x2)
6074642e01fSmrg		extents->x2 = x2;
6084642e01fSmrg	    if (y1 < extents->y1)
6094642e01fSmrg		extents->y1 = y1;
6104642e01fSmrg	    if (y2 > extents->y2)
6114642e01fSmrg		extents->y2 = y2;
6124642e01fSmrg	    x += glyph->info.xOff;
6134642e01fSmrg	    y += glyph->info.yOff;
6144642e01fSmrg	}
6154642e01fSmrg    }
6164642e01fSmrg}
6174642e01fSmrg
6184642e01fSmrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
6194642e01fSmrg
6204642e01fSmrg_X_EXPORT void
6214642e01fSmrgCompositeGlyphs (CARD8		op,
6224642e01fSmrg		 PicturePtr	pSrc,
6234642e01fSmrg		 PicturePtr	pDst,
6244642e01fSmrg		 PictFormatPtr	maskFormat,
6254642e01fSmrg		 INT16		xSrc,
6264642e01fSmrg		 INT16		ySrc,
6274642e01fSmrg		 int		nlist,
6284642e01fSmrg		 GlyphListPtr	lists,
6294642e01fSmrg		 GlyphPtr	*glyphs)
6304642e01fSmrg{
6314642e01fSmrg    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
6324642e01fSmrg
6334642e01fSmrg    ValidatePicture (pSrc);
6344642e01fSmrg    ValidatePicture (pDst);
6354642e01fSmrg    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs);
6364642e01fSmrg}
6374642e01fSmrg
6384642e01fSmrgBool
6394642e01fSmrgmiRealizeGlyph (ScreenPtr pScreen,
6404642e01fSmrg		GlyphPtr  glyph)
6414642e01fSmrg{
6424642e01fSmrg    return TRUE;
6434642e01fSmrg}
6444642e01fSmrg
6454642e01fSmrgvoid
6464642e01fSmrgmiUnrealizeGlyph (ScreenPtr pScreen,
6474642e01fSmrg		  GlyphPtr  glyph)
6484642e01fSmrg{
6494642e01fSmrg}
6504642e01fSmrg
6514642e01fSmrg_X_EXPORT void
6524642e01fSmrgmiGlyphs (CARD8		op,
6534642e01fSmrg	  PicturePtr	pSrc,
6544642e01fSmrg	  PicturePtr	pDst,
6554642e01fSmrg	  PictFormatPtr	maskFormat,
6564642e01fSmrg	  INT16		xSrc,
6574642e01fSmrg	  INT16		ySrc,
6584642e01fSmrg	  int		nlist,
6594642e01fSmrg	  GlyphListPtr	list,
6604642e01fSmrg	  GlyphPtr	*glyphs)
6614642e01fSmrg{
6624642e01fSmrg    PicturePtr	pPicture;
6634642e01fSmrg    PixmapPtr   pMaskPixmap = 0;
6644642e01fSmrg    PicturePtr  pMask;
6654642e01fSmrg    ScreenPtr   pScreen = pDst->pDrawable->pScreen;
6664642e01fSmrg    int		width = 0, height = 0;
6674642e01fSmrg    int		x, y;
6684642e01fSmrg    int		xDst = list->xOff, yDst = list->yOff;
6694642e01fSmrg    int		n;
6704642e01fSmrg    GlyphPtr	glyph;
6714642e01fSmrg    int		error;
6724642e01fSmrg    BoxRec	extents = {0, 0, 0, 0};
6734642e01fSmrg    CARD32	component_alpha;
6744642e01fSmrg
6754642e01fSmrg    if (maskFormat)
6764642e01fSmrg    {
6774642e01fSmrg	GCPtr	    pGC;
6784642e01fSmrg	xRectangle  rect;
6794642e01fSmrg
6804642e01fSmrg	GlyphExtents (nlist, list, glyphs, &extents);
6814642e01fSmrg
6824642e01fSmrg	if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
6834642e01fSmrg	    return;
6844642e01fSmrg	width = extents.x2 - extents.x1;
6854642e01fSmrg	height = extents.y2 - extents.y1;
6864642e01fSmrg	pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
6874642e01fSmrg						maskFormat->depth,
6884642e01fSmrg						CREATE_PIXMAP_USAGE_SCRATCH);
6894642e01fSmrg	if (!pMaskPixmap)
6904642e01fSmrg	    return;
6914642e01fSmrg	component_alpha = NeedsComponent(maskFormat->format);
6924642e01fSmrg	pMask = CreatePicture (0, &pMaskPixmap->drawable,
6934642e01fSmrg			       maskFormat, CPComponentAlpha, &component_alpha,
6944642e01fSmrg			       serverClient, &error);
6954642e01fSmrg	if (!pMask)
6964642e01fSmrg	{
6974642e01fSmrg	    (*pScreen->DestroyPixmap) (pMaskPixmap);
6984642e01fSmrg	    return;
6994642e01fSmrg	}
7004642e01fSmrg	pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
7014642e01fSmrg	ValidateGC (&pMaskPixmap->drawable, pGC);
7024642e01fSmrg	rect.x = 0;
7034642e01fSmrg	rect.y = 0;
7044642e01fSmrg	rect.width = width;
7054642e01fSmrg	rect.height = height;
7064642e01fSmrg	(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
7074642e01fSmrg	FreeScratchGC (pGC);
7084642e01fSmrg	x = -extents.x1;
7094642e01fSmrg	y = -extents.y1;
7104642e01fSmrg    }
7114642e01fSmrg    else
7124642e01fSmrg    {
7134642e01fSmrg	pMask = pDst;
7144642e01fSmrg	x = 0;
7154642e01fSmrg	y = 0;
7164642e01fSmrg    }
7174642e01fSmrg    while (nlist--)
7184642e01fSmrg    {
7194642e01fSmrg	x += list->xOff;
7204642e01fSmrg	y += list->yOff;
7214642e01fSmrg	n = list->len;
7224642e01fSmrg	while (n--)
7234642e01fSmrg	{
7244642e01fSmrg	    glyph = *glyphs++;
7254642e01fSmrg	    pPicture = GlyphPicture (glyph)[pScreen->myNum];
7264642e01fSmrg
7274642e01fSmrg	    if (maskFormat)
7284642e01fSmrg	    {
7294642e01fSmrg		CompositePicture (PictOpAdd,
7304642e01fSmrg				  pPicture,
7314642e01fSmrg				  None,
7324642e01fSmrg				  pMask,
7334642e01fSmrg				  0, 0,
7344642e01fSmrg				  0, 0,
7354642e01fSmrg				  x - glyph->info.x,
7364642e01fSmrg				  y - glyph->info.y,
7374642e01fSmrg				  glyph->info.width,
7384642e01fSmrg				  glyph->info.height);
7394642e01fSmrg	    }
7404642e01fSmrg	    else
7414642e01fSmrg	    {
7424642e01fSmrg		CompositePicture (op,
7434642e01fSmrg				  pSrc,
7444642e01fSmrg				  pPicture,
7454642e01fSmrg				  pDst,
7464642e01fSmrg				  xSrc + (x - glyph->info.x) - xDst,
7474642e01fSmrg				  ySrc + (y - glyph->info.y) - yDst,
7484642e01fSmrg				  0, 0,
7494642e01fSmrg				  x - glyph->info.x,
7504642e01fSmrg				  y - glyph->info.y,
7514642e01fSmrg				  glyph->info.width,
7524642e01fSmrg				  glyph->info.height);
7534642e01fSmrg	    }
7544642e01fSmrg
7554642e01fSmrg	    x += glyph->info.xOff;
7564642e01fSmrg	    y += glyph->info.yOff;
7574642e01fSmrg	}
7584642e01fSmrg	list++;
7594642e01fSmrg    }
7604642e01fSmrg    if (maskFormat)
7614642e01fSmrg    {
7624642e01fSmrg	x = extents.x1;
7634642e01fSmrg	y = extents.y1;
7644642e01fSmrg	CompositePicture (op,
7654642e01fSmrg			  pSrc,
7664642e01fSmrg			  pMask,
7674642e01fSmrg			  pDst,
7684642e01fSmrg			  xSrc + x - xDst,
7694642e01fSmrg			  ySrc + y - yDst,
7704642e01fSmrg			  0, 0,
7714642e01fSmrg			  x, y,
7724642e01fSmrg			  width, height);
7734642e01fSmrg	FreePicture ((pointer) pMask, (XID) 0);
7744642e01fSmrg	(*pScreen->DestroyPixmap) (pMaskPixmap);
7754642e01fSmrg    }
7764642e01fSmrg}
777