1062 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1062 lines
		
	
	
		
			23 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 <stddef.h>  /* buggy openssl/sha.h wants size_t */
 | |
| #include <openssl/sha.h>
 | |
| 
 | |
| #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"
 | |
| #include "mipict.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]))
 | |
| 
 | |
| static const CARD8	glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 };
 | |
| 
 | |
| static GlyphHashRec	globalGlyphs[GlyphFormatNum];
 | |
| 
 | |
| static int	globalTotalGlyphPrivateSize = 0;
 | |
| 
 | |
| static int	glyphPrivateCount = 0;
 | |
| 
 | |
| void
 | |
| ResetGlyphPrivates (void)
 | |
| {
 | |
|     glyphPrivateCount = 0;
 | |
| }
 | |
| 
 | |
| int
 | |
| AllocateGlyphPrivateIndex (void)
 | |
| {
 | |
|     return glyphPrivateCount++;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| AllocateGlyphPrivate (ScreenPtr pScreen,
 | |
| 		      int	index2,
 | |
| 		      unsigned	amount)
 | |
| {
 | |
|     PictureScreenPtr ps;
 | |
|     unsigned	     oldamount;
 | |
| 
 | |
|     ps = GetPictureScreenIfSet (pScreen);
 | |
|     if (!ps)
 | |
| 	return FALSE;
 | |
| 
 | |
|     /* Round up sizes for proper alignment */
 | |
|     amount = ((amount + (sizeof (DevUnion) - 1)) / sizeof (DevUnion)) *
 | |
| 	sizeof (DevUnion);
 | |
| 
 | |
|     if (index2 >= ps->glyphPrivateLen)
 | |
|     {
 | |
| 	unsigned *nsizes;
 | |
| 	nsizes = (unsigned *) xrealloc (ps->glyphPrivateSizes,
 | |
| 					(index2 + 1) * sizeof (unsigned));
 | |
| 	if (!nsizes)
 | |
| 	    return FALSE;
 | |
| 	
 | |
| 	while (ps->glyphPrivateLen <= index2)
 | |
| 	{
 | |
| 	    nsizes[ps->glyphPrivateLen++] = 0;
 | |
| 	    ps->totalGlyphPrivateSize += sizeof (DevUnion);
 | |
| 	}
 | |
| 	ps->glyphPrivateSizes = nsizes;
 | |
|     }
 | |
|     oldamount = ps->glyphPrivateSizes[index2];
 | |
|     if (amount > oldamount)
 | |
|     {
 | |
| 	ps->glyphPrivateSizes[index2] = amount;
 | |
| 	ps->totalGlyphPrivateSize += (amount - oldamount);
 | |
|     }
 | |
|     ps->totalGlyphPrivateSize = BitmapBytePad (ps->totalGlyphPrivateSize * 8);
 | |
|     
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| 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 = xalloc (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)
 | |
| 	xfree (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)
 | |
| 			xfree (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)
 | |
| 	xfree (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;
 | |
| 
 | |
| int
 | |
| AllocateGlyphSetPrivateIndex (void)
 | |
| {
 | |
|     return _GlyphSetPrivateAllocateIndex++;
 | |
| }
 | |
| 
 | |
| 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 *) xrealloc (glyphSet->devPrivates,
 | |
| 					(n + 1) * sizeof (pointer));
 | |
| 	    if (!new)
 | |
| 		return FALSE;
 | |
| 	} else {
 | |
| 	    new = (pointer *) xalloc ((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,
 | |
| 	      unsigned char	sha1[20])
 | |
| {
 | |
|     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 (glyph->sha1, sha1, 20) == 0))
 | |
| 	{
 | |
| 	    break;
 | |
| 	}
 | |
| 	if (!step)
 | |
| 	{
 | |
| 	    step = signature % hash->hashSet->rehash;
 | |
| 	    if (!step)
 | |
| 		step = 1;
 | |
| 	}
 | |
| 	elt += step;
 | |
| 	if (elt >= tableSize)
 | |
| 	    elt -= tableSize;
 | |
|     }
 | |
|     return gr;
 | |
| }
 | |
| 
 | |
| int
 | |
| HashGlyph (xGlyphInfo    *gi,
 | |
| 	   CARD8	 *bits,
 | |
| 	   unsigned long size,
 | |
| 	   unsigned char sha1[20])
 | |
| {
 | |
|     SHA_CTX ctx;
 | |
|     int success;
 | |
| 
 | |
|     success = SHA1_Init (&ctx);
 | |
|     if (! success)
 | |
| 	return BadAlloc;
 | |
| 
 | |
|     success = SHA1_Update (&ctx, gi, sizeof (xGlyphInfo));
 | |
|     if (! success)
 | |
| 	return BadAlloc;
 | |
| 
 | |
|     success = SHA1_Update (&ctx, bits, size);
 | |
|     if (! success)
 | |
| 	return BadAlloc;
 | |
| 
 | |
|     success = SHA1_Final (sha1, &ctx);
 | |
|     if (! success)
 | |
| 	return BadAlloc;
 | |
| 
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| GlyphPtr
 | |
| FindGlyphByHash (unsigned char sha1[20], int format)
 | |
| {
 | |
|     GlyphRefPtr gr;
 | |
|     CARD32 signature = *(CARD32 *) sha1;
 | |
| 
 | |
|     gr = FindGlyphRef (&globalGlyphs[format],
 | |
| 		       signature, TRUE, sha1);
 | |
| 
 | |
|     if (gr->glyph && gr->glyph != DeletedGlyph)
 | |
| 	return gr->glyph;
 | |
|     else
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| #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;
 | |
| 	CARD32		 signature;
 | |
| 
 | |
| 	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;
 | |
| 	    }
 | |
| 
 | |
| 	signature = *(CARD32 *) glyph->sha1;
 | |
| 	gr = FindGlyphRef (&globalGlyphs[format], signature,
 | |
| 			   TRUE, glyph->sha1);
 | |
| 	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++)
 | |
| 	{
 | |
| 	    ScreenPtr pScreen = screenInfo.screens[i];
 | |
| 
 | |
| 	    FreePicture ((pointer) GlyphPicture (glyph)[i], 0);
 | |
| 
 | |
| 	    ps = GetPictureScreenIfSet (pScreen);
 | |
| 	    if (ps)
 | |
| 		(*ps->UnrealizeGlyph) (pScreen, glyph);
 | |
| 	}
 | |
| 	
 | |
| 	if (glyph->devPrivates)
 | |
| 	    xfree (glyph->devPrivates);
 | |
| 	xfree (glyph);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
 | |
| {
 | |
|     GlyphRefPtr	    gr;
 | |
|     CARD32	    signature;
 | |
| 
 | |
|     CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
 | |
|     /* Locate existing matching glyph */
 | |
|     signature = *(CARD32 *) glyph->sha1;
 | |
|     gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], signature,
 | |
| 		       TRUE, glyph->sha1);
 | |
|     if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph)
 | |
|     {
 | |
| 	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)
 | |
| 	    xfree (glyph->devPrivates);
 | |
| 	xfree (glyph);
 | |
| 	glyph = gr->glyph;
 | |
|     }
 | |
|     else if (gr->glyph != glyph)
 | |
|     {
 | |
| 	gr->glyph = glyph;
 | |
| 	gr->signature = signature;
 | |
| 	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 = screenInfo.numScreens * sizeof (PicturePtr);
 | |
|     glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec));
 | |
|     if (!glyph)
 | |
| 	return 0;
 | |
|     glyph->refcnt = 0;
 | |
|     glyph->size = size + sizeof (xGlyphInfo);
 | |
|     glyph->info = *gi;
 | |
| 
 | |
|     if (globalTotalGlyphPrivateSize)
 | |
|     {
 | |
| 	glyph->devPrivates = xalloc (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))
 | |
| 		goto bail;
 | |
| 	}
 | |
|     }
 | |
|     
 | |
|     return glyph;
 | |
| 
 | |
| bail:
 | |
|     while (i--)
 | |
|     {
 | |
| 	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
 | |
| 	if (ps)
 | |
| 	    (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
 | |
|     }
 | |
| 		
 | |
|     if (glyph->devPrivates)
 | |
| 	xfree (glyph->devPrivates);
 | |
|     xfree (glyph);
 | |
|     return 0;
 | |
| }
 | |
|     
 | |
| Bool
 | |
| AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet)
 | |
| {
 | |
|     hash->table = (GlyphRefPtr) xalloc (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->sha1);
 | |
| 		gr->signature = s;
 | |
| 		gr->glyph = glyph;
 | |
| 		++newHash.tableEntries;
 | |
| 	    }
 | |
| 	}
 | |
| 	xfree (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 = xalloc (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]))
 | |
|     {
 | |
| 	xfree (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)
 | |
| 	{
 | |
| 	    xfree (globalGlyphs[glyphSet->fdepth].table);
 | |
| 	    globalGlyphs[glyphSet->fdepth].table = 0;
 | |
| 	    globalGlyphs[glyphSet->fdepth].hashSet = 0;
 | |
| 	}
 | |
| 	else
 | |
| 	    ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE);
 | |
| 	xfree (table);
 | |
| 
 | |
| 	if (glyphSet->devPrivates &&
 | |
| 	    glyphSet->devPrivates != (pointer)(&glyphSet[1]))
 | |
| 	    xfree(glyphSet->devPrivates);
 | |
| 
 | |
| 	xfree (glyphSet);
 | |
|     }
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static void
 | |
| GlyphExtents (int		nlist,
 | |
| 		GlyphListPtr	list,
 | |
| 		GlyphPtr	*glyphs,
 | |
| 		BoxPtr		extents)
 | |
| {
 | |
|     int		x1, x2, y1, y2;
 | |
|     int		n;
 | |
|     GlyphPtr	glyph;
 | |
|     int		x, y;
 | |
|     
 | |
|     x = 0;
 | |
|     y = 0;
 | |
|     extents->x1 = MAXSHORT;
 | |
|     extents->x2 = MINSHORT;
 | |
|     extents->y1 = MAXSHORT;
 | |
|     extents->y2 = MINSHORT;
 | |
|     while (nlist--)
 | |
|     {
 | |
| 	x += list->xOff;
 | |
| 	y += list->yOff;
 | |
| 	n = list->len;
 | |
| 	list++;
 | |
| 	while (n--)
 | |
| 	{
 | |
| 	    glyph = *glyphs++;
 | |
| 	    x1 = x - glyph->info.x;
 | |
| 	    if (x1 < MINSHORT)
 | |
| 		x1 = MINSHORT;
 | |
| 	    y1 = y - glyph->info.y;
 | |
| 	    if (y1 < MINSHORT)
 | |
| 		y1 = MINSHORT;
 | |
| 	    x2 = x1 + glyph->info.width;
 | |
| 	    if (x2 > MAXSHORT)
 | |
| 		x2 = MAXSHORT;
 | |
| 	    y2 = y1 + glyph->info.height;
 | |
| 	    if (y2 > MAXSHORT)
 | |
| 		y2 = MAXSHORT;
 | |
| 	    if (x1 < extents->x1)
 | |
| 		extents->x1 = x1;
 | |
| 	    if (x2 > extents->x2)
 | |
| 		extents->x2 = x2;
 | |
| 	    if (y1 < extents->y1)
 | |
| 		extents->y1 = y1;
 | |
| 	    if (y2 > extents->y2)
 | |
| 		extents->y2 = y2;
 | |
| 	    x += glyph->info.xOff;
 | |
| 	    y += glyph->info.yOff;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
 | |
| 
 | |
| _X_EXPORT void
 | |
| CompositeGlyphs (CARD8		op,
 | |
| 		 PicturePtr	pSrc,
 | |
| 		 PicturePtr	pDst,
 | |
| 		 PictFormatPtr	maskFormat,
 | |
| 		 INT16		xSrc,
 | |
| 		 INT16		ySrc,
 | |
| 		 int		nlist,
 | |
| 		 GlyphListPtr	lists,
 | |
| 		 GlyphPtr	*glyphs)
 | |
| {
 | |
|     PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
 | |
| 
 | |
|     ValidatePicture (pSrc);
 | |
|     ValidatePicture (pDst);
 | |
|     (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| miRealizeGlyph (ScreenPtr pScreen,
 | |
| 		GlyphPtr  glyph)
 | |
| {
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| void
 | |
| miUnrealizeGlyph (ScreenPtr pScreen,
 | |
| 		  GlyphPtr  glyph)
 | |
| {
 | |
| }
 | |
| 
 | |
| _X_EXPORT void
 | |
| miGlyphs (CARD8		op,
 | |
| 	  PicturePtr	pSrc,
 | |
| 	  PicturePtr	pDst,
 | |
| 	  PictFormatPtr	maskFormat,
 | |
| 	  INT16		xSrc,
 | |
| 	  INT16		ySrc,
 | |
| 	  int		nlist,
 | |
| 	  GlyphListPtr	list,
 | |
| 	  GlyphPtr	*glyphs)
 | |
| {
 | |
|     PicturePtr	pPicture;
 | |
|     PixmapPtr   pMaskPixmap = 0;
 | |
|     PicturePtr  pMask;
 | |
|     ScreenPtr   pScreen = pDst->pDrawable->pScreen;
 | |
|     int		width = 0, height = 0;
 | |
|     int		x, y;
 | |
|     int		xDst = list->xOff, yDst = list->yOff;
 | |
|     int		n;
 | |
|     GlyphPtr	glyph;
 | |
|     int		error;
 | |
|     BoxRec	extents = {0, 0, 0, 0};
 | |
|     CARD32	component_alpha;
 | |
| 
 | |
|     if (maskFormat)
 | |
|     {
 | |
| 	GCPtr	    pGC;
 | |
| 	xRectangle  rect;
 | |
| 
 | |
| 	GlyphExtents (nlist, list, glyphs, &extents);
 | |
| 
 | |
| 	if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
 | |
| 	    return;
 | |
| 	width = extents.x2 - extents.x1;
 | |
| 	height = extents.y2 - extents.y1;
 | |
| 	pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
 | |
| 						maskFormat->depth,
 | |
| 						CREATE_PIXMAP_USAGE_SCRATCH);
 | |
| 	if (!pMaskPixmap)
 | |
| 	    return;
 | |
| 	component_alpha = NeedsComponent(maskFormat->format);
 | |
| 	pMask = CreatePicture (0, &pMaskPixmap->drawable,
 | |
| 			       maskFormat, CPComponentAlpha, &component_alpha,
 | |
| 			       serverClient, &error);
 | |
| 	if (!pMask)
 | |
| 	{
 | |
| 	    (*pScreen->DestroyPixmap) (pMaskPixmap);
 | |
| 	    return;
 | |
| 	}
 | |
| 	pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
 | |
| 	ValidateGC (&pMaskPixmap->drawable, pGC);
 | |
| 	rect.x = 0;
 | |
| 	rect.y = 0;
 | |
| 	rect.width = width;
 | |
| 	rect.height = height;
 | |
| 	(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
 | |
| 	FreeScratchGC (pGC);
 | |
| 	x = -extents.x1;
 | |
| 	y = -extents.y1;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	pMask = pDst;
 | |
| 	x = 0;
 | |
| 	y = 0;
 | |
|     }
 | |
|     while (nlist--)
 | |
|     {
 | |
| 	x += list->xOff;
 | |
| 	y += list->yOff;
 | |
| 	n = list->len;
 | |
| 	while (n--)
 | |
| 	{
 | |
| 	    glyph = *glyphs++;
 | |
| 	    pPicture = GlyphPicture (glyph)[pScreen->myNum];
 | |
| 
 | |
| 	    if (maskFormat)
 | |
| 	    {
 | |
| 		CompositePicture (PictOpAdd,
 | |
| 				  pPicture,
 | |
| 				  None,
 | |
| 				  pMask,
 | |
| 				  0, 0,
 | |
| 				  0, 0,
 | |
| 				  x - glyph->info.x,
 | |
| 				  y - glyph->info.y,
 | |
| 				  glyph->info.width,
 | |
| 				  glyph->info.height);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		CompositePicture (op,
 | |
| 				  pSrc,
 | |
| 				  pPicture,
 | |
| 				  pDst,
 | |
| 				  xSrc + (x - glyph->info.x) - xDst,
 | |
| 				  ySrc + (y - glyph->info.y) - yDst,
 | |
| 				  0, 0,
 | |
| 				  x - glyph->info.x,
 | |
| 				  y - glyph->info.y,
 | |
| 				  glyph->info.width,
 | |
| 				  glyph->info.height);
 | |
| 	    }
 | |
| 
 | |
| 	    x += glyph->info.xOff;
 | |
| 	    y += glyph->info.yOff;
 | |
| 	}
 | |
| 	list++;
 | |
|     }
 | |
|     if (maskFormat)
 | |
|     {
 | |
| 	x = extents.x1;
 | |
| 	y = extents.y1;
 | |
| 	CompositePicture (op,
 | |
| 			  pSrc,
 | |
| 			  pMask,
 | |
| 			  pDst,
 | |
| 			  xSrc + x - xDst,
 | |
| 			  ySrc + y - yDst,
 | |
| 			  0, 0,
 | |
| 			  x, y,
 | |
| 			  width, height);
 | |
| 	FreePicture ((pointer) pMask, (XID) 0);
 | |
| 	(*pScreen->DestroyPixmap) (pMaskPixmap);
 | |
|     }
 | |
| }
 |