1706f2543Smrg/*
2706f2543Smrg *
3706f2543Smrg * Copyright © 2000 SuSE, Inc.
4706f2543Smrg *
5706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
7706f2543Smrg * the above copyright notice appear in all copies and that both that
8706f2543Smrg * copyright notice and this permission notice appear in supporting
9706f2543Smrg * documentation, and that the name of SuSE not be used in advertising or
10706f2543Smrg * publicity pertaining to distribution of the software without specific,
11706f2543Smrg * written prior permission.  SuSE makes no representations about the
12706f2543Smrg * suitability of this software for any purpose.  It is provided "as is"
13706f2543Smrg * without express or implied warranty.
14706f2543Smrg *
15706f2543Smrg * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16706f2543Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17706f2543Smrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18706f2543Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19706f2543Smrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20706f2543Smrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg *
22706f2543Smrg * Author:  Keith Packard, SuSE, Inc.
23706f2543Smrg */
24706f2543Smrg
25706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
26706f2543Smrg#include <dix-config.h>
27706f2543Smrg#endif
28706f2543Smrg
29706f2543Smrg#include "xsha1.h"
30706f2543Smrg
31706f2543Smrg#include "misc.h"
32706f2543Smrg#include "scrnintstr.h"
33706f2543Smrg#include "os.h"
34706f2543Smrg#include "regionstr.h"
35706f2543Smrg#include "validate.h"
36706f2543Smrg#include "windowstr.h"
37706f2543Smrg#include "input.h"
38706f2543Smrg#include "resource.h"
39706f2543Smrg#include "colormapst.h"
40706f2543Smrg#include "cursorstr.h"
41706f2543Smrg#include "dixstruct.h"
42706f2543Smrg#include "gcstruct.h"
43706f2543Smrg#include "servermd.h"
44706f2543Smrg#include "picturestr.h"
45706f2543Smrg#include "glyphstr.h"
46706f2543Smrg#include "mipict.h"
47706f2543Smrg
48706f2543Smrg/*
49706f2543Smrg * From Knuth -- a good choice for hash/rehash values is p, p-2 where
50706f2543Smrg * p and p-2 are both prime.  These tables are sized to have an extra 10%
51706f2543Smrg * free to avoid exponential performance degradation as the hash table fills
52706f2543Smrg */
53706f2543Smrgstatic GlyphHashSetRec glyphHashSets[] = {
54706f2543Smrg    { 32,		43,		41        },
55706f2543Smrg    { 64,		73,		71        },
56706f2543Smrg    { 128,		151,		149       },
57706f2543Smrg    { 256,		283,		281       },
58706f2543Smrg    { 512,		571,		569       },
59706f2543Smrg    { 1024,		1153,		1151      },
60706f2543Smrg    { 2048,		2269,		2267      },
61706f2543Smrg    { 4096,		4519,		4517      },
62706f2543Smrg    { 8192,		9013,		9011      },
63706f2543Smrg    { 16384,		18043,		18041     },
64706f2543Smrg    { 32768,		36109,		36107     },
65706f2543Smrg    { 65536,		72091,		72089     },
66706f2543Smrg    { 131072,		144409,		144407    },
67706f2543Smrg    { 262144,		288361,		288359    },
68706f2543Smrg    { 524288,		576883,		576881    },
69706f2543Smrg    { 1048576,		1153459,	1153457   },
70706f2543Smrg    { 2097152,		2307163,	2307161   },
71706f2543Smrg    { 4194304,		4613893,	4613891   },
72706f2543Smrg    { 8388608,		9227641,	9227639   },
73706f2543Smrg    { 16777216,		18455029,	18455027  },
74706f2543Smrg    { 33554432,		36911011,	36911009  },
75706f2543Smrg    { 67108864,		73819861,	73819859  },
76706f2543Smrg    { 134217728,	147639589,	147639587 },
77706f2543Smrg    { 268435456,	295279081,	295279079 },
78706f2543Smrg    { 536870912,	590559793,	590559791 }
79706f2543Smrg};
80706f2543Smrg
81706f2543Smrg#define NGLYPHHASHSETS	(sizeof(glyphHashSets)/sizeof(glyphHashSets[0]))
82706f2543Smrg
83706f2543Smrgstatic const CARD8	glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 };
84706f2543Smrg
85706f2543Smrgstatic GlyphHashRec	globalGlyphs[GlyphFormatNum];
86706f2543Smrg
87706f2543Smrgvoid
88706f2543SmrgGlyphUninit (ScreenPtr pScreen)
89706f2543Smrg{
90706f2543Smrg    PictureScreenPtr ps = GetPictureScreen (pScreen);
91706f2543Smrg    GlyphPtr	     glyph;
92706f2543Smrg    int		     fdepth, i;
93706f2543Smrg    int		     scrno = pScreen->myNum;
94706f2543Smrg
95706f2543Smrg    for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
96706f2543Smrg    {
97706f2543Smrg	if (!globalGlyphs[fdepth].hashSet)
98706f2543Smrg	    continue;
99706f2543Smrg
100706f2543Smrg	for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
101706f2543Smrg	{
102706f2543Smrg	    glyph = globalGlyphs[fdepth].table[i].glyph;
103706f2543Smrg	    if (glyph && glyph != DeletedGlyph)
104706f2543Smrg	    {
105706f2543Smrg		if (GlyphPicture(glyph)[scrno])
106706f2543Smrg		{
107706f2543Smrg		    FreePicture ((pointer) GlyphPicture (glyph)[scrno], 0);
108706f2543Smrg		    GlyphPicture(glyph)[scrno] = NULL;
109706f2543Smrg		}
110706f2543Smrg		(*ps->UnrealizeGlyph) (pScreen, glyph);
111706f2543Smrg	    }
112706f2543Smrg	}
113706f2543Smrg    }
114706f2543Smrg}
115706f2543Smrg
116706f2543SmrgGlyphHashSetPtr
117706f2543SmrgFindGlyphHashSet (CARD32 filled)
118706f2543Smrg{
119706f2543Smrg    int	i;
120706f2543Smrg
121706f2543Smrg    for (i = 0; i < NGLYPHHASHSETS; i++)
122706f2543Smrg	if (glyphHashSets[i].entries >= filled)
123706f2543Smrg	    return &glyphHashSets[i];
124706f2543Smrg    return 0;
125706f2543Smrg}
126706f2543Smrg
127706f2543SmrgGlyphRefPtr
128706f2543SmrgFindGlyphRef (GlyphHashPtr	hash,
129706f2543Smrg	      CARD32		signature,
130706f2543Smrg	      Bool		match,
131706f2543Smrg	      unsigned char	sha1[20])
132706f2543Smrg{
133706f2543Smrg    CARD32	elt, step, s;
134706f2543Smrg    GlyphPtr	glyph;
135706f2543Smrg    GlyphRefPtr	table, gr, del;
136706f2543Smrg    CARD32	tableSize = hash->hashSet->size;
137706f2543Smrg
138706f2543Smrg    table = hash->table;
139706f2543Smrg    elt = signature % tableSize;
140706f2543Smrg    step = 0;
141706f2543Smrg    del = 0;
142706f2543Smrg    for (;;)
143706f2543Smrg    {
144706f2543Smrg	gr = &table[elt];
145706f2543Smrg	s = gr->signature;
146706f2543Smrg	glyph = gr->glyph;
147706f2543Smrg	if (!glyph)
148706f2543Smrg	{
149706f2543Smrg	    if (del)
150706f2543Smrg		gr = del;
151706f2543Smrg	    break;
152706f2543Smrg	}
153706f2543Smrg	if (glyph == DeletedGlyph)
154706f2543Smrg	{
155706f2543Smrg	    if (!del)
156706f2543Smrg		del = gr;
157706f2543Smrg	    else if (gr == del)
158706f2543Smrg		break;
159706f2543Smrg	}
160706f2543Smrg	else if (s == signature &&
161706f2543Smrg		 (!match ||
162706f2543Smrg		  memcmp (glyph->sha1, sha1, 20) == 0))
163706f2543Smrg	{
164706f2543Smrg	    break;
165706f2543Smrg	}
166706f2543Smrg	if (!step)
167706f2543Smrg	{
168706f2543Smrg	    step = signature % hash->hashSet->rehash;
169706f2543Smrg	    if (!step)
170706f2543Smrg		step = 1;
171706f2543Smrg	}
172706f2543Smrg	elt += step;
173706f2543Smrg	if (elt >= tableSize)
174706f2543Smrg	    elt -= tableSize;
175706f2543Smrg    }
176706f2543Smrg    return gr;
177706f2543Smrg}
178706f2543Smrg
179706f2543Smrgint
180706f2543SmrgHashGlyph (xGlyphInfo    *gi,
181706f2543Smrg	   CARD8	 *bits,
182706f2543Smrg	   unsigned long size,
183706f2543Smrg	   unsigned char sha1[20])
184706f2543Smrg{
185706f2543Smrg    void *ctx = x_sha1_init();
186706f2543Smrg    int success;
187706f2543Smrg
188706f2543Smrg    if (!ctx)
189706f2543Smrg	return BadAlloc;
190706f2543Smrg
191706f2543Smrg    success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo));
192706f2543Smrg    if (!success)
193706f2543Smrg	return BadAlloc;
194706f2543Smrg    success = x_sha1_update(ctx, bits, size);
195706f2543Smrg    if (!success)
196706f2543Smrg	return BadAlloc;
197706f2543Smrg    success = x_sha1_final(ctx, sha1);
198706f2543Smrg    if (!success)
199706f2543Smrg	return BadAlloc;
200706f2543Smrg    return Success;
201706f2543Smrg}
202706f2543Smrg
203706f2543SmrgGlyphPtr
204706f2543SmrgFindGlyphByHash (unsigned char sha1[20], int format)
205706f2543Smrg{
206706f2543Smrg    GlyphRefPtr gr;
207706f2543Smrg    CARD32 signature = *(CARD32 *) sha1;
208706f2543Smrg
209706f2543Smrg    if (!globalGlyphs[format].hashSet)
210706f2543Smrg	return NULL;
211706f2543Smrg
212706f2543Smrg    gr = FindGlyphRef (&globalGlyphs[format],
213706f2543Smrg		       signature, TRUE, sha1);
214706f2543Smrg
215706f2543Smrg    if (gr->glyph && gr->glyph != DeletedGlyph)
216706f2543Smrg	return gr->glyph;
217706f2543Smrg    else
218706f2543Smrg	return NULL;
219706f2543Smrg}
220706f2543Smrg
221706f2543Smrg#ifdef CHECK_DUPLICATES
222706f2543Smrgvoid
223706f2543SmrgDuplicateRef (GlyphPtr glyph, char *where)
224706f2543Smrg{
225706f2543Smrg    ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where);
226706f2543Smrg}
227706f2543Smrg
228706f2543Smrgvoid
229706f2543SmrgCheckDuplicates (GlyphHashPtr hash, char *where)
230706f2543Smrg{
231706f2543Smrg    GlyphPtr	g;
232706f2543Smrg    int		i, j;
233706f2543Smrg
234706f2543Smrg    for (i = 0; i < hash->hashSet->size; i++)
235706f2543Smrg    {
236706f2543Smrg	g = hash->table[i].glyph;
237706f2543Smrg	if (!g || g == DeletedGlyph)
238706f2543Smrg	    continue;
239706f2543Smrg	for (j = i + 1; j < hash->hashSet->size; j++)
240706f2543Smrg	    if (hash->table[j].glyph == g)
241706f2543Smrg		DuplicateRef (g, where);
242706f2543Smrg    }
243706f2543Smrg}
244706f2543Smrg#else
245706f2543Smrg#define CheckDuplicates(a,b)
246706f2543Smrg#define DuplicateRef(a,b)
247706f2543Smrg#endif
248706f2543Smrg
249706f2543Smrgstatic void
250706f2543SmrgFreeGlyphPicture(GlyphPtr glyph)
251706f2543Smrg{
252706f2543Smrg    PictureScreenPtr ps;
253706f2543Smrg    int i;
254706f2543Smrg
255706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++)
256706f2543Smrg    {
257706f2543Smrg        ScreenPtr pScreen = screenInfo.screens[i];
258706f2543Smrg
259706f2543Smrg        if (GlyphPicture(glyph)[i])
260706f2543Smrg            FreePicture ((pointer) GlyphPicture (glyph)[i], 0);
261706f2543Smrg
262706f2543Smrg        ps = GetPictureScreenIfSet (pScreen);
263706f2543Smrg        if (ps)
264706f2543Smrg            (*ps->UnrealizeGlyph) (pScreen, glyph);
265706f2543Smrg    }
266706f2543Smrg}
267706f2543Smrg
268706f2543Smrg
269706f2543Smrgvoid
270706f2543SmrgFreeGlyph (GlyphPtr glyph, int format)
271706f2543Smrg{
272706f2543Smrg    CheckDuplicates (&globalGlyphs[format], "FreeGlyph");
273706f2543Smrg    if (--glyph->refcnt == 0)
274706f2543Smrg    {
275706f2543Smrg	GlyphRefPtr      gr;
276706f2543Smrg	int	         i;
277706f2543Smrg	int	         first;
278706f2543Smrg	CARD32		 signature;
279706f2543Smrg
280706f2543Smrg	first = -1;
281706f2543Smrg	for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
282706f2543Smrg	    if (globalGlyphs[format].table[i].glyph == glyph)
283706f2543Smrg	    {
284706f2543Smrg		if (first != -1)
285706f2543Smrg		    DuplicateRef (glyph, "FreeGlyph check");
286706f2543Smrg		first = i;
287706f2543Smrg	    }
288706f2543Smrg
289706f2543Smrg	signature = *(CARD32 *) glyph->sha1;
290706f2543Smrg	gr = FindGlyphRef (&globalGlyphs[format], signature,
291706f2543Smrg			   TRUE, glyph->sha1);
292706f2543Smrg	if (gr - globalGlyphs[format].table != first)
293706f2543Smrg	    DuplicateRef (glyph, "Found wrong one");
294706f2543Smrg	if (gr->glyph && gr->glyph != DeletedGlyph)
295706f2543Smrg	{
296706f2543Smrg	    gr->glyph = DeletedGlyph;
297706f2543Smrg	    gr->signature = 0;
298706f2543Smrg	    globalGlyphs[format].tableEntries--;
299706f2543Smrg	}
300706f2543Smrg
301706f2543Smrg	FreeGlyphPicture(glyph);
302706f2543Smrg	dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
303706f2543Smrg    }
304706f2543Smrg}
305706f2543Smrg
306706f2543Smrgvoid
307706f2543SmrgAddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
308706f2543Smrg{
309706f2543Smrg    GlyphRefPtr	    gr;
310706f2543Smrg    CARD32	    signature;
311706f2543Smrg
312706f2543Smrg    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
313706f2543Smrg    /* Locate existing matching glyph */
314706f2543Smrg    signature = *(CARD32 *) glyph->sha1;
315706f2543Smrg    gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], signature,
316706f2543Smrg		       TRUE, glyph->sha1);
317706f2543Smrg    if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph)
318706f2543Smrg    {
319706f2543Smrg	FreeGlyphPicture(glyph);
320706f2543Smrg	dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
321706f2543Smrg	glyph = gr->glyph;
322706f2543Smrg    }
323706f2543Smrg    else if (gr->glyph != glyph)
324706f2543Smrg    {
325706f2543Smrg	gr->glyph = glyph;
326706f2543Smrg	gr->signature = signature;
327706f2543Smrg	globalGlyphs[glyphSet->fdepth].tableEntries++;
328706f2543Smrg    }
329706f2543Smrg
330706f2543Smrg    /* Insert/replace glyphset value */
331706f2543Smrg    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
332706f2543Smrg    ++glyph->refcnt;
333706f2543Smrg    if (gr->glyph && gr->glyph != DeletedGlyph)
334706f2543Smrg	FreeGlyph (gr->glyph, glyphSet->fdepth);
335706f2543Smrg    else
336706f2543Smrg	glyphSet->hash.tableEntries++;
337706f2543Smrg    gr->glyph = glyph;
338706f2543Smrg    gr->signature = id;
339706f2543Smrg    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
340706f2543Smrg}
341706f2543Smrg
342706f2543SmrgBool
343706f2543SmrgDeleteGlyph (GlyphSetPtr glyphSet, Glyph id)
344706f2543Smrg{
345706f2543Smrg    GlyphRefPtr     gr;
346706f2543Smrg    GlyphPtr	    glyph;
347706f2543Smrg
348706f2543Smrg    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
349706f2543Smrg    glyph = gr->glyph;
350706f2543Smrg    if (glyph && glyph != DeletedGlyph)
351706f2543Smrg    {
352706f2543Smrg	gr->glyph = DeletedGlyph;
353706f2543Smrg	glyphSet->hash.tableEntries--;
354706f2543Smrg	FreeGlyph (glyph, glyphSet->fdepth);
355706f2543Smrg	return TRUE;
356706f2543Smrg    }
357706f2543Smrg    return FALSE;
358706f2543Smrg}
359706f2543Smrg
360706f2543SmrgGlyphPtr
361706f2543SmrgFindGlyph (GlyphSetPtr glyphSet, Glyph id)
362706f2543Smrg{
363706f2543Smrg    GlyphPtr        glyph;
364706f2543Smrg
365706f2543Smrg    glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph;
366706f2543Smrg    if (glyph == DeletedGlyph)
367706f2543Smrg	glyph = 0;
368706f2543Smrg    return glyph;
369706f2543Smrg}
370706f2543Smrg
371706f2543SmrgGlyphPtr
372706f2543SmrgAllocateGlyph (xGlyphInfo *gi, int fdepth)
373706f2543Smrg{
374706f2543Smrg    PictureScreenPtr ps;
375706f2543Smrg    int		     size;
376706f2543Smrg    GlyphPtr	     glyph;
377706f2543Smrg    int		     i;
378706f2543Smrg    int		     head_size;
379706f2543Smrg
380706f2543Smrg    head_size = sizeof (GlyphRec) + screenInfo.numScreens * sizeof (PicturePtr);
381706f2543Smrg    size = (head_size + dixPrivatesSize(PRIVATE_GLYPH));
382706f2543Smrg    glyph = (GlyphPtr) malloc (size);
383706f2543Smrg    if (!glyph)
384706f2543Smrg	return 0;
385706f2543Smrg    glyph->refcnt = 0;
386706f2543Smrg    glyph->size = size + sizeof (xGlyphInfo);
387706f2543Smrg    glyph->info = *gi;
388706f2543Smrg    dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH);
389706f2543Smrg
390706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++)
391706f2543Smrg    {
392706f2543Smrg	GlyphPicture(glyph)[i] = NULL;
393706f2543Smrg	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
394706f2543Smrg
395706f2543Smrg	if (ps)
396706f2543Smrg	{
397706f2543Smrg	    if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph))
398706f2543Smrg		goto bail;
399706f2543Smrg	}
400706f2543Smrg    }
401706f2543Smrg
402706f2543Smrg    return glyph;
403706f2543Smrg
404706f2543Smrgbail:
405706f2543Smrg    while (i--)
406706f2543Smrg    {
407706f2543Smrg	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
408706f2543Smrg	if (ps)
409706f2543Smrg	    (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
410706f2543Smrg    }
411706f2543Smrg
412706f2543Smrg    dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
413706f2543Smrg    return 0;
414706f2543Smrg}
415706f2543Smrg
416706f2543SmrgBool
417706f2543SmrgAllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet)
418706f2543Smrg{
419706f2543Smrg    hash->table = calloc(hashSet->size, sizeof (GlyphRefRec));
420706f2543Smrg    if (!hash->table)
421706f2543Smrg	return FALSE;
422706f2543Smrg    hash->hashSet = hashSet;
423706f2543Smrg    hash->tableEntries = 0;
424706f2543Smrg    return TRUE;
425706f2543Smrg}
426706f2543Smrg
427706f2543SmrgBool
428706f2543SmrgResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global)
429706f2543Smrg{
430706f2543Smrg    CARD32	    tableEntries;
431706f2543Smrg    GlyphHashSetPtr hashSet;
432706f2543Smrg    GlyphHashRec    newHash;
433706f2543Smrg    GlyphRefPtr	    gr;
434706f2543Smrg    GlyphPtr	    glyph;
435706f2543Smrg    int		    i;
436706f2543Smrg    int		    oldSize;
437706f2543Smrg    CARD32	    s;
438706f2543Smrg
439706f2543Smrg    tableEntries = hash->tableEntries + change;
440706f2543Smrg    hashSet = FindGlyphHashSet (tableEntries);
441706f2543Smrg    if (hashSet == hash->hashSet)
442706f2543Smrg	return TRUE;
443706f2543Smrg    if (global)
444706f2543Smrg	CheckDuplicates (hash, "ResizeGlyphHash top");
445706f2543Smrg    if (!AllocateGlyphHash (&newHash, hashSet))
446706f2543Smrg	return FALSE;
447706f2543Smrg    if (hash->table)
448706f2543Smrg    {
449706f2543Smrg	oldSize = hash->hashSet->size;
450706f2543Smrg	for (i = 0; i < oldSize; i++)
451706f2543Smrg	{
452706f2543Smrg	    glyph = hash->table[i].glyph;
453706f2543Smrg	    if (glyph && glyph != DeletedGlyph)
454706f2543Smrg	    {
455706f2543Smrg		s = hash->table[i].signature;
456706f2543Smrg		gr = FindGlyphRef (&newHash, s, global, glyph->sha1);
457706f2543Smrg		gr->signature = s;
458706f2543Smrg		gr->glyph = glyph;
459706f2543Smrg		++newHash.tableEntries;
460706f2543Smrg	    }
461706f2543Smrg	}
462706f2543Smrg	free(hash->table);
463706f2543Smrg    }
464706f2543Smrg    *hash = newHash;
465706f2543Smrg    if (global)
466706f2543Smrg	CheckDuplicates (hash, "ResizeGlyphHash bottom");
467706f2543Smrg    return TRUE;
468706f2543Smrg}
469706f2543Smrg
470706f2543SmrgBool
471706f2543SmrgResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change)
472706f2543Smrg{
473706f2543Smrg    return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) &&
474706f2543Smrg	    ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE));
475706f2543Smrg}
476706f2543Smrg
477706f2543SmrgGlyphSetPtr
478706f2543SmrgAllocateGlyphSet (int fdepth, PictFormatPtr format)
479706f2543Smrg{
480706f2543Smrg    GlyphSetPtr	glyphSet;
481706f2543Smrg
482706f2543Smrg    if (!globalGlyphs[fdepth].hashSet)
483706f2543Smrg    {
484706f2543Smrg	if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0]))
485706f2543Smrg	    return FALSE;
486706f2543Smrg    }
487706f2543Smrg
488706f2543Smrg    glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET);
489706f2543Smrg    if (!glyphSet)
490706f2543Smrg	return FALSE;
491706f2543Smrg
492706f2543Smrg    if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0]))
493706f2543Smrg    {
494706f2543Smrg	free(glyphSet);
495706f2543Smrg	return FALSE;
496706f2543Smrg    }
497706f2543Smrg    glyphSet->refcnt = 1;
498706f2543Smrg    glyphSet->fdepth = fdepth;
499706f2543Smrg    glyphSet->format = format;
500706f2543Smrg    return glyphSet;
501706f2543Smrg}
502706f2543Smrg
503706f2543Smrgint
504706f2543SmrgFreeGlyphSet (pointer	value,
505706f2543Smrg	      XID       gid)
506706f2543Smrg{
507706f2543Smrg    GlyphSetPtr	glyphSet = (GlyphSetPtr) value;
508706f2543Smrg
509706f2543Smrg    if (--glyphSet->refcnt == 0)
510706f2543Smrg    {
511706f2543Smrg	CARD32	    i, tableSize = glyphSet->hash.hashSet->size;
512706f2543Smrg	GlyphRefPtr table = glyphSet->hash.table;
513706f2543Smrg	GlyphPtr    glyph;
514706f2543Smrg
515706f2543Smrg	for (i = 0; i < tableSize; i++)
516706f2543Smrg	{
517706f2543Smrg	    glyph = table[i].glyph;
518706f2543Smrg	    if (glyph && glyph != DeletedGlyph)
519706f2543Smrg		FreeGlyph (glyph, glyphSet->fdepth);
520706f2543Smrg	}
521706f2543Smrg	if (!globalGlyphs[glyphSet->fdepth].tableEntries)
522706f2543Smrg	{
523706f2543Smrg	    free(globalGlyphs[glyphSet->fdepth].table);
524706f2543Smrg	    globalGlyphs[glyphSet->fdepth].table = 0;
525706f2543Smrg	    globalGlyphs[glyphSet->fdepth].hashSet = 0;
526706f2543Smrg	}
527706f2543Smrg	else
528706f2543Smrg	    ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE);
529706f2543Smrg	free(table);
530706f2543Smrg	dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET);
531706f2543Smrg    }
532706f2543Smrg    return Success;
533706f2543Smrg}
534706f2543Smrg
535706f2543Smrgstatic void
536706f2543SmrgGlyphExtents (int		nlist,
537706f2543Smrg		GlyphListPtr	list,
538706f2543Smrg		GlyphPtr	*glyphs,
539706f2543Smrg		BoxPtr		extents)
540706f2543Smrg{
541706f2543Smrg    int		x1, x2, y1, y2;
542706f2543Smrg    int		n;
543706f2543Smrg    GlyphPtr	glyph;
544706f2543Smrg    int		x, y;
545706f2543Smrg
546706f2543Smrg    x = 0;
547706f2543Smrg    y = 0;
548706f2543Smrg    extents->x1 = MAXSHORT;
549706f2543Smrg    extents->x2 = MINSHORT;
550706f2543Smrg    extents->y1 = MAXSHORT;
551706f2543Smrg    extents->y2 = MINSHORT;
552706f2543Smrg    while (nlist--)
553706f2543Smrg    {
554706f2543Smrg	x += list->xOff;
555706f2543Smrg	y += list->yOff;
556706f2543Smrg	n = list->len;
557706f2543Smrg	list++;
558706f2543Smrg	while (n--)
559706f2543Smrg	{
560706f2543Smrg	    glyph = *glyphs++;
561706f2543Smrg	    x1 = x - glyph->info.x;
562706f2543Smrg	    if (x1 < MINSHORT)
563706f2543Smrg		x1 = MINSHORT;
564706f2543Smrg	    y1 = y - glyph->info.y;
565706f2543Smrg	    if (y1 < MINSHORT)
566706f2543Smrg		y1 = MINSHORT;
567706f2543Smrg	    x2 = x1 + glyph->info.width;
568706f2543Smrg	    if (x2 > MAXSHORT)
569706f2543Smrg		x2 = MAXSHORT;
570706f2543Smrg	    y2 = y1 + glyph->info.height;
571706f2543Smrg	    if (y2 > MAXSHORT)
572706f2543Smrg		y2 = MAXSHORT;
573706f2543Smrg	    if (x1 < extents->x1)
574706f2543Smrg		extents->x1 = x1;
575706f2543Smrg	    if (x2 > extents->x2)
576706f2543Smrg		extents->x2 = x2;
577706f2543Smrg	    if (y1 < extents->y1)
578706f2543Smrg		extents->y1 = y1;
579706f2543Smrg	    if (y2 > extents->y2)
580706f2543Smrg		extents->y2 = y2;
581706f2543Smrg	    x += glyph->info.xOff;
582706f2543Smrg	    y += glyph->info.yOff;
583706f2543Smrg	}
584706f2543Smrg    }
585706f2543Smrg}
586706f2543Smrg
587706f2543Smrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
588706f2543Smrg
589706f2543Smrgvoid
590706f2543SmrgCompositeGlyphs (CARD8		op,
591706f2543Smrg		 PicturePtr	pSrc,
592706f2543Smrg		 PicturePtr	pDst,
593706f2543Smrg		 PictFormatPtr	maskFormat,
594706f2543Smrg		 INT16		xSrc,
595706f2543Smrg		 INT16		ySrc,
596706f2543Smrg		 int		nlist,
597706f2543Smrg		 GlyphListPtr	lists,
598706f2543Smrg		 GlyphPtr	*glyphs)
599706f2543Smrg{
600706f2543Smrg    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
601706f2543Smrg
602706f2543Smrg    ValidatePicture (pSrc);
603706f2543Smrg    ValidatePicture (pDst);
604706f2543Smrg    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs);
605706f2543Smrg}
606706f2543Smrg
607706f2543SmrgBool
608706f2543SmrgmiRealizeGlyph (ScreenPtr pScreen,
609706f2543Smrg		GlyphPtr  glyph)
610706f2543Smrg{
611706f2543Smrg    return TRUE;
612706f2543Smrg}
613706f2543Smrg
614706f2543Smrgvoid
615706f2543SmrgmiUnrealizeGlyph (ScreenPtr pScreen,
616706f2543Smrg		  GlyphPtr  glyph)
617706f2543Smrg{
618706f2543Smrg}
619706f2543Smrg
620706f2543Smrgvoid
621706f2543SmrgmiGlyphs (CARD8		op,
622706f2543Smrg	  PicturePtr	pSrc,
623706f2543Smrg	  PicturePtr	pDst,
624706f2543Smrg	  PictFormatPtr	maskFormat,
625706f2543Smrg	  INT16		xSrc,
626706f2543Smrg	  INT16		ySrc,
627706f2543Smrg	  int		nlist,
628706f2543Smrg	  GlyphListPtr	list,
629706f2543Smrg	  GlyphPtr	*glyphs)
630706f2543Smrg{
631706f2543Smrg    PicturePtr	pPicture;
632706f2543Smrg    PixmapPtr   pMaskPixmap = 0;
633706f2543Smrg    PicturePtr  pMask;
634706f2543Smrg    ScreenPtr   pScreen = pDst->pDrawable->pScreen;
635706f2543Smrg    int		width = 0, height = 0;
636706f2543Smrg    int		x, y;
637706f2543Smrg    int		xDst = list->xOff, yDst = list->yOff;
638706f2543Smrg    int		n;
639706f2543Smrg    GlyphPtr	glyph;
640706f2543Smrg    int		error;
641706f2543Smrg    BoxRec	extents = {0, 0, 0, 0};
642706f2543Smrg    CARD32	component_alpha;
643706f2543Smrg
644706f2543Smrg    if (maskFormat)
645706f2543Smrg    {
646706f2543Smrg	GCPtr	    pGC;
647706f2543Smrg	xRectangle  rect;
648706f2543Smrg
649706f2543Smrg	GlyphExtents (nlist, list, glyphs, &extents);
650706f2543Smrg
651706f2543Smrg	if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
652706f2543Smrg	    return;
653706f2543Smrg	width = extents.x2 - extents.x1;
654706f2543Smrg	height = extents.y2 - extents.y1;
655706f2543Smrg	pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
656706f2543Smrg						maskFormat->depth,
657706f2543Smrg						CREATE_PIXMAP_USAGE_SCRATCH);
658706f2543Smrg	if (!pMaskPixmap)
659706f2543Smrg	    return;
660706f2543Smrg	component_alpha = NeedsComponent(maskFormat->format);
661706f2543Smrg	pMask = CreatePicture (0, &pMaskPixmap->drawable,
662706f2543Smrg			       maskFormat, CPComponentAlpha, &component_alpha,
663706f2543Smrg			       serverClient, &error);
664706f2543Smrg	if (!pMask)
665706f2543Smrg	{
666706f2543Smrg	    (*pScreen->DestroyPixmap) (pMaskPixmap);
667706f2543Smrg	    return;
668706f2543Smrg	}
669706f2543Smrg	pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
670706f2543Smrg	ValidateGC (&pMaskPixmap->drawable, pGC);
671706f2543Smrg	rect.x = 0;
672706f2543Smrg	rect.y = 0;
673706f2543Smrg	rect.width = width;
674706f2543Smrg	rect.height = height;
675706f2543Smrg	(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
676706f2543Smrg	FreeScratchGC (pGC);
677706f2543Smrg	x = -extents.x1;
678706f2543Smrg	y = -extents.y1;
679706f2543Smrg    }
680706f2543Smrg    else
681706f2543Smrg    {
682706f2543Smrg	pMask = pDst;
683706f2543Smrg	x = 0;
684706f2543Smrg	y = 0;
685706f2543Smrg    }
686706f2543Smrg    while (nlist--)
687706f2543Smrg    {
688706f2543Smrg	x += list->xOff;
689706f2543Smrg	y += list->yOff;
690706f2543Smrg	n = list->len;
691706f2543Smrg	while (n--)
692706f2543Smrg	{
693706f2543Smrg	    glyph = *glyphs++;
694706f2543Smrg	    pPicture = GlyphPicture (glyph)[pScreen->myNum];
695706f2543Smrg
696706f2543Smrg	    if (pPicture)
697706f2543Smrg	    {
698706f2543Smrg		if (maskFormat)
699706f2543Smrg		{
700706f2543Smrg			CompositePicture (PictOpAdd,
701706f2543Smrg					  pPicture,
702706f2543Smrg					  None,
703706f2543Smrg					  pMask,
704706f2543Smrg					  0, 0,
705706f2543Smrg					  0, 0,
706706f2543Smrg					  x - glyph->info.x,
707706f2543Smrg					  y - glyph->info.y,
708706f2543Smrg					  glyph->info.width,
709706f2543Smrg					  glyph->info.height);
710706f2543Smrg		}
711706f2543Smrg		else
712706f2543Smrg		{
713706f2543Smrg		    CompositePicture (op,
714706f2543Smrg				      pSrc,
715706f2543Smrg				      pPicture,
716706f2543Smrg				      pDst,
717706f2543Smrg				      xSrc + (x - glyph->info.x) - xDst,
718706f2543Smrg				      ySrc + (y - glyph->info.y) - yDst,
719706f2543Smrg				      0, 0,
720706f2543Smrg				      x - glyph->info.x,
721706f2543Smrg				      y - glyph->info.y,
722706f2543Smrg				      glyph->info.width,
723706f2543Smrg				      glyph->info.height);
724706f2543Smrg		}
725706f2543Smrg	    }
726706f2543Smrg
727706f2543Smrg	    x += glyph->info.xOff;
728706f2543Smrg	    y += glyph->info.yOff;
729706f2543Smrg	}
730706f2543Smrg	list++;
731706f2543Smrg    }
732706f2543Smrg    if (maskFormat)
733706f2543Smrg    {
734706f2543Smrg	x = extents.x1;
735706f2543Smrg	y = extents.y1;
736706f2543Smrg	CompositePicture (op,
737706f2543Smrg			  pSrc,
738706f2543Smrg			  pMask,
739706f2543Smrg			  pDst,
740706f2543Smrg			  xSrc + x - xDst,
741706f2543Smrg			  ySrc + y - yDst,
742706f2543Smrg			  0, 0,
743706f2543Smrg			  x, y,
744706f2543Smrg			  width, height);
745706f2543Smrg	FreePicture ((pointer) pMask, (XID) 0);
746706f2543Smrg	(*pScreen->DestroyPixmap) (pMaskPixmap);
747706f2543Smrg    }
748706f2543Smrg}
749