1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * Copyright © 2000 SuSE, Inc.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun * documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun * the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun * copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun * documentation, and that the name of SuSE not be used in advertising or
10*4882a593Smuzhiyun * publicity pertaining to distribution of the software without specific,
11*4882a593Smuzhiyun * written prior permission. SuSE makes no representations about the
12*4882a593Smuzhiyun * suitability of this software for any purpose. It is provided "as is"
13*4882a593Smuzhiyun * without express or implied warranty.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16*4882a593Smuzhiyun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17*4882a593Smuzhiyun * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18*4882a593Smuzhiyun * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19*4882a593Smuzhiyun * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20*4882a593Smuzhiyun * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * Author: Keith Packard, SuSE, Inc.
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
26*4882a593Smuzhiyun #include <dix-config.h>
27*4882a593Smuzhiyun #endif
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include "xsha1.h"
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #include "misc.h"
32*4882a593Smuzhiyun #include "scrnintstr.h"
33*4882a593Smuzhiyun #include "os.h"
34*4882a593Smuzhiyun #include "regionstr.h"
35*4882a593Smuzhiyun #include "validate.h"
36*4882a593Smuzhiyun #include "windowstr.h"
37*4882a593Smuzhiyun #include "input.h"
38*4882a593Smuzhiyun #include "resource.h"
39*4882a593Smuzhiyun #include "colormapst.h"
40*4882a593Smuzhiyun #include "cursorstr.h"
41*4882a593Smuzhiyun #include "dixstruct.h"
42*4882a593Smuzhiyun #include "gcstruct.h"
43*4882a593Smuzhiyun #include "servermd.h"
44*4882a593Smuzhiyun #include "picturestr.h"
45*4882a593Smuzhiyun #include "glyphstr.h"
46*4882a593Smuzhiyun #include "mipict.h"
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /*
49*4882a593Smuzhiyun * From Knuth -- a good choice for hash/rehash values is p, p-2 where
50*4882a593Smuzhiyun * p and p-2 are both prime. These tables are sized to have an extra 10%
51*4882a593Smuzhiyun * free to avoid exponential performance degradation as the hash table fills
52*4882a593Smuzhiyun */
53*4882a593Smuzhiyun static GlyphHashSetRec glyphHashSets[] = {
54*4882a593Smuzhiyun {32, 43, 41},
55*4882a593Smuzhiyun {64, 73, 71},
56*4882a593Smuzhiyun {128, 151, 149},
57*4882a593Smuzhiyun {256, 283, 281},
58*4882a593Smuzhiyun {512, 571, 569},
59*4882a593Smuzhiyun {1024, 1153, 1151},
60*4882a593Smuzhiyun {2048, 2269, 2267},
61*4882a593Smuzhiyun {4096, 4519, 4517},
62*4882a593Smuzhiyun {8192, 9013, 9011},
63*4882a593Smuzhiyun {16384, 18043, 18041},
64*4882a593Smuzhiyun {32768, 36109, 36107},
65*4882a593Smuzhiyun {65536, 72091, 72089},
66*4882a593Smuzhiyun {131072, 144409, 144407},
67*4882a593Smuzhiyun {262144, 288361, 288359},
68*4882a593Smuzhiyun {524288, 576883, 576881},
69*4882a593Smuzhiyun {1048576, 1153459, 1153457},
70*4882a593Smuzhiyun {2097152, 2307163, 2307161},
71*4882a593Smuzhiyun {4194304, 4613893, 4613891},
72*4882a593Smuzhiyun {8388608, 9227641, 9227639},
73*4882a593Smuzhiyun {16777216, 18455029, 18455027},
74*4882a593Smuzhiyun {33554432, 36911011, 36911009},
75*4882a593Smuzhiyun {67108864, 73819861, 73819859},
76*4882a593Smuzhiyun {134217728, 147639589, 147639587},
77*4882a593Smuzhiyun {268435456, 295279081, 295279079},
78*4882a593Smuzhiyun {536870912, 590559793, 590559791}
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun #define NGLYPHHASHSETS ARRAY_SIZE(glyphHashSets)
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun static GlyphHashRec globalGlyphs[GlyphFormatNum];
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun void
GlyphUninit(ScreenPtr pScreen)86*4882a593Smuzhiyun GlyphUninit(ScreenPtr pScreen)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun PictureScreenPtr ps = GetPictureScreen(pScreen);
89*4882a593Smuzhiyun GlyphPtr glyph;
90*4882a593Smuzhiyun int fdepth, i;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) {
93*4882a593Smuzhiyun if (!globalGlyphs[fdepth].hashSet)
94*4882a593Smuzhiyun continue;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) {
97*4882a593Smuzhiyun glyph = globalGlyphs[fdepth].table[i].glyph;
98*4882a593Smuzhiyun if (glyph && glyph != DeletedGlyph) {
99*4882a593Smuzhiyun if (GetGlyphPicture(glyph, pScreen)) {
100*4882a593Smuzhiyun FreePicture((void *) GetGlyphPicture(glyph, pScreen), 0);
101*4882a593Smuzhiyun SetGlyphPicture(glyph, pScreen, NULL);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun (*ps->UnrealizeGlyph) (pScreen, glyph);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun static GlyphHashSetPtr
FindGlyphHashSet(CARD32 filled)110*4882a593Smuzhiyun FindGlyphHashSet(CARD32 filled)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun int i;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun for (i = 0; i < NGLYPHHASHSETS; i++)
115*4882a593Smuzhiyun if (glyphHashSets[i].entries >= filled)
116*4882a593Smuzhiyun return &glyphHashSets[i];
117*4882a593Smuzhiyun return 0;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun static GlyphRefPtr
FindGlyphRef(GlyphHashPtr hash,CARD32 signature,Bool match,unsigned char sha1[20])121*4882a593Smuzhiyun FindGlyphRef(GlyphHashPtr hash,
122*4882a593Smuzhiyun CARD32 signature, Bool match, unsigned char sha1[20])
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun CARD32 elt, step, s;
125*4882a593Smuzhiyun GlyphPtr glyph;
126*4882a593Smuzhiyun GlyphRefPtr table, gr, del;
127*4882a593Smuzhiyun CARD32 tableSize = hash->hashSet->size;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun table = hash->table;
130*4882a593Smuzhiyun elt = signature % tableSize;
131*4882a593Smuzhiyun step = 0;
132*4882a593Smuzhiyun del = 0;
133*4882a593Smuzhiyun for (;;) {
134*4882a593Smuzhiyun gr = &table[elt];
135*4882a593Smuzhiyun s = gr->signature;
136*4882a593Smuzhiyun glyph = gr->glyph;
137*4882a593Smuzhiyun if (!glyph) {
138*4882a593Smuzhiyun if (del)
139*4882a593Smuzhiyun gr = del;
140*4882a593Smuzhiyun break;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun if (glyph == DeletedGlyph) {
143*4882a593Smuzhiyun if (!del)
144*4882a593Smuzhiyun del = gr;
145*4882a593Smuzhiyun else if (gr == del)
146*4882a593Smuzhiyun break;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun else if (s == signature &&
149*4882a593Smuzhiyun (!match || memcmp(glyph->sha1, sha1, 20) == 0)) {
150*4882a593Smuzhiyun break;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun if (!step) {
153*4882a593Smuzhiyun step = signature % hash->hashSet->rehash;
154*4882a593Smuzhiyun if (!step)
155*4882a593Smuzhiyun step = 1;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun elt += step;
158*4882a593Smuzhiyun if (elt >= tableSize)
159*4882a593Smuzhiyun elt -= tableSize;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun return gr;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun int
HashGlyph(xGlyphInfo * gi,CARD8 * bits,unsigned long size,unsigned char sha1[20])165*4882a593Smuzhiyun HashGlyph(xGlyphInfo * gi,
166*4882a593Smuzhiyun CARD8 *bits, unsigned long size, unsigned char sha1[20])
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun void *ctx = x_sha1_init();
169*4882a593Smuzhiyun int success;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (!ctx)
172*4882a593Smuzhiyun return BadAlloc;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo));
175*4882a593Smuzhiyun if (!success)
176*4882a593Smuzhiyun return BadAlloc;
177*4882a593Smuzhiyun success = x_sha1_update(ctx, bits, size);
178*4882a593Smuzhiyun if (!success)
179*4882a593Smuzhiyun return BadAlloc;
180*4882a593Smuzhiyun success = x_sha1_final(ctx, sha1);
181*4882a593Smuzhiyun if (!success)
182*4882a593Smuzhiyun return BadAlloc;
183*4882a593Smuzhiyun return Success;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun GlyphPtr
FindGlyphByHash(unsigned char sha1[20],int format)187*4882a593Smuzhiyun FindGlyphByHash(unsigned char sha1[20], int format)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun GlyphRefPtr gr;
190*4882a593Smuzhiyun CARD32 signature = *(CARD32 *) sha1;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (!globalGlyphs[format].hashSet)
193*4882a593Smuzhiyun return NULL;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, sha1);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (gr->glyph && gr->glyph != DeletedGlyph)
198*4882a593Smuzhiyun return gr->glyph;
199*4882a593Smuzhiyun else
200*4882a593Smuzhiyun return NULL;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun #ifdef CHECK_DUPLICATES
204*4882a593Smuzhiyun void
DuplicateRef(GlyphPtr glyph,char * where)205*4882a593Smuzhiyun DuplicateRef(GlyphPtr glyph, char *where)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun ErrorF("Duplicate Glyph 0x%x from %s\n", glyph, where);
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun void
CheckDuplicates(GlyphHashPtr hash,char * where)211*4882a593Smuzhiyun CheckDuplicates(GlyphHashPtr hash, char *where)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun GlyphPtr g;
214*4882a593Smuzhiyun int i, j;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun for (i = 0; i < hash->hashSet->size; i++) {
217*4882a593Smuzhiyun g = hash->table[i].glyph;
218*4882a593Smuzhiyun if (!g || g == DeletedGlyph)
219*4882a593Smuzhiyun continue;
220*4882a593Smuzhiyun for (j = i + 1; j < hash->hashSet->size; j++)
221*4882a593Smuzhiyun if (hash->table[j].glyph == g)
222*4882a593Smuzhiyun DuplicateRef(g, where);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun #else
226*4882a593Smuzhiyun #define CheckDuplicates(a,b)
227*4882a593Smuzhiyun #define DuplicateRef(a,b)
228*4882a593Smuzhiyun #endif
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun static void
FreeGlyphPicture(GlyphPtr glyph)231*4882a593Smuzhiyun FreeGlyphPicture(GlyphPtr glyph)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun PictureScreenPtr ps;
234*4882a593Smuzhiyun int i;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun for (i = 0; i < screenInfo.numScreens; i++) {
237*4882a593Smuzhiyun ScreenPtr pScreen = screenInfo.screens[i];
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun if (GetGlyphPicture(glyph, pScreen))
240*4882a593Smuzhiyun FreePicture((void *) GetGlyphPicture(glyph, pScreen), 0);
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun ps = GetPictureScreenIfSet(pScreen);
243*4882a593Smuzhiyun if (ps)
244*4882a593Smuzhiyun (*ps->UnrealizeGlyph) (pScreen, glyph);
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun static void
FreeGlyph(GlyphPtr glyph,int format)249*4882a593Smuzhiyun FreeGlyph(GlyphPtr glyph, int format)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun CheckDuplicates(&globalGlyphs[format], "FreeGlyph");
252*4882a593Smuzhiyun if (--glyph->refcnt == 0) {
253*4882a593Smuzhiyun GlyphRefPtr gr;
254*4882a593Smuzhiyun int i;
255*4882a593Smuzhiyun int first;
256*4882a593Smuzhiyun CARD32 signature;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun first = -1;
259*4882a593Smuzhiyun for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
260*4882a593Smuzhiyun if (globalGlyphs[format].table[i].glyph == glyph) {
261*4882a593Smuzhiyun if (first != -1)
262*4882a593Smuzhiyun DuplicateRef(glyph, "FreeGlyph check");
263*4882a593Smuzhiyun first = i;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun signature = *(CARD32 *) glyph->sha1;
267*4882a593Smuzhiyun gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, glyph->sha1);
268*4882a593Smuzhiyun if (gr - globalGlyphs[format].table != first)
269*4882a593Smuzhiyun DuplicateRef(glyph, "Found wrong one");
270*4882a593Smuzhiyun if (gr->glyph && gr->glyph != DeletedGlyph) {
271*4882a593Smuzhiyun gr->glyph = DeletedGlyph;
272*4882a593Smuzhiyun gr->signature = 0;
273*4882a593Smuzhiyun globalGlyphs[format].tableEntries--;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun FreeGlyphPicture(glyph);
277*4882a593Smuzhiyun dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun void
AddGlyph(GlyphSetPtr glyphSet,GlyphPtr glyph,Glyph id)282*4882a593Smuzhiyun AddGlyph(GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun GlyphRefPtr gr;
285*4882a593Smuzhiyun CARD32 signature;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
288*4882a593Smuzhiyun /* Locate existing matching glyph */
289*4882a593Smuzhiyun signature = *(CARD32 *) glyph->sha1;
290*4882a593Smuzhiyun gr = FindGlyphRef(&globalGlyphs[glyphSet->fdepth], signature,
291*4882a593Smuzhiyun TRUE, glyph->sha1);
292*4882a593Smuzhiyun if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) {
293*4882a593Smuzhiyun FreeGlyphPicture(glyph);
294*4882a593Smuzhiyun dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
295*4882a593Smuzhiyun glyph = gr->glyph;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun else if (gr->glyph != glyph) {
298*4882a593Smuzhiyun gr->glyph = glyph;
299*4882a593Smuzhiyun gr->signature = signature;
300*4882a593Smuzhiyun globalGlyphs[glyphSet->fdepth].tableEntries++;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /* Insert/replace glyphset value */
304*4882a593Smuzhiyun gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0);
305*4882a593Smuzhiyun ++glyph->refcnt;
306*4882a593Smuzhiyun if (gr->glyph && gr->glyph != DeletedGlyph)
307*4882a593Smuzhiyun FreeGlyph(gr->glyph, glyphSet->fdepth);
308*4882a593Smuzhiyun else
309*4882a593Smuzhiyun glyphSet->hash.tableEntries++;
310*4882a593Smuzhiyun gr->glyph = glyph;
311*4882a593Smuzhiyun gr->signature = id;
312*4882a593Smuzhiyun CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun Bool
DeleteGlyph(GlyphSetPtr glyphSet,Glyph id)316*4882a593Smuzhiyun DeleteGlyph(GlyphSetPtr glyphSet, Glyph id)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun GlyphRefPtr gr;
319*4882a593Smuzhiyun GlyphPtr glyph;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0);
322*4882a593Smuzhiyun glyph = gr->glyph;
323*4882a593Smuzhiyun if (glyph && glyph != DeletedGlyph) {
324*4882a593Smuzhiyun gr->glyph = DeletedGlyph;
325*4882a593Smuzhiyun glyphSet->hash.tableEntries--;
326*4882a593Smuzhiyun FreeGlyph(glyph, glyphSet->fdepth);
327*4882a593Smuzhiyun return TRUE;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun return FALSE;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun GlyphPtr
FindGlyph(GlyphSetPtr glyphSet,Glyph id)333*4882a593Smuzhiyun FindGlyph(GlyphSetPtr glyphSet, Glyph id)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun GlyphPtr glyph;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun glyph = FindGlyphRef(&glyphSet->hash, id, FALSE, 0)->glyph;
338*4882a593Smuzhiyun if (glyph == DeletedGlyph)
339*4882a593Smuzhiyun glyph = 0;
340*4882a593Smuzhiyun return glyph;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun GlyphPtr
AllocateGlyph(xGlyphInfo * gi,int fdepth)344*4882a593Smuzhiyun AllocateGlyph(xGlyphInfo * gi, int fdepth)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun PictureScreenPtr ps;
347*4882a593Smuzhiyun int size;
348*4882a593Smuzhiyun GlyphPtr glyph;
349*4882a593Smuzhiyun int i;
350*4882a593Smuzhiyun int head_size;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun head_size = sizeof(GlyphRec) + screenInfo.numScreens * sizeof(PicturePtr);
353*4882a593Smuzhiyun size = (head_size + dixPrivatesSize(PRIVATE_GLYPH));
354*4882a593Smuzhiyun glyph = (GlyphPtr) malloc(size);
355*4882a593Smuzhiyun if (!glyph)
356*4882a593Smuzhiyun return 0;
357*4882a593Smuzhiyun glyph->refcnt = 0;
358*4882a593Smuzhiyun glyph->size = size + sizeof(xGlyphInfo);
359*4882a593Smuzhiyun glyph->info = *gi;
360*4882a593Smuzhiyun dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH);
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun for (i = 0; i < screenInfo.numScreens; i++) {
363*4882a593Smuzhiyun ScreenPtr pScreen = screenInfo.screens[i];
364*4882a593Smuzhiyun SetGlyphPicture(glyph, pScreen, NULL);
365*4882a593Smuzhiyun ps = GetPictureScreenIfSet(pScreen);
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun if (ps) {
368*4882a593Smuzhiyun if (!(*ps->RealizeGlyph) (pScreen, glyph))
369*4882a593Smuzhiyun goto bail;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun return glyph;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun bail:
376*4882a593Smuzhiyun while (i--) {
377*4882a593Smuzhiyun ps = GetPictureScreenIfSet(screenInfo.screens[i]);
378*4882a593Smuzhiyun if (ps)
379*4882a593Smuzhiyun (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
383*4882a593Smuzhiyun return 0;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun static Bool
AllocateGlyphHash(GlyphHashPtr hash,GlyphHashSetPtr hashSet)387*4882a593Smuzhiyun AllocateGlyphHash(GlyphHashPtr hash, GlyphHashSetPtr hashSet)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun hash->table = calloc(hashSet->size, sizeof(GlyphRefRec));
390*4882a593Smuzhiyun if (!hash->table)
391*4882a593Smuzhiyun return FALSE;
392*4882a593Smuzhiyun hash->hashSet = hashSet;
393*4882a593Smuzhiyun hash->tableEntries = 0;
394*4882a593Smuzhiyun return TRUE;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun static Bool
ResizeGlyphHash(GlyphHashPtr hash,CARD32 change,Bool global)398*4882a593Smuzhiyun ResizeGlyphHash(GlyphHashPtr hash, CARD32 change, Bool global)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun CARD32 tableEntries;
401*4882a593Smuzhiyun GlyphHashSetPtr hashSet;
402*4882a593Smuzhiyun GlyphHashRec newHash;
403*4882a593Smuzhiyun GlyphRefPtr gr;
404*4882a593Smuzhiyun GlyphPtr glyph;
405*4882a593Smuzhiyun int i;
406*4882a593Smuzhiyun int oldSize;
407*4882a593Smuzhiyun CARD32 s;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun tableEntries = hash->tableEntries + change;
410*4882a593Smuzhiyun hashSet = FindGlyphHashSet(tableEntries);
411*4882a593Smuzhiyun if (hashSet == hash->hashSet)
412*4882a593Smuzhiyun return TRUE;
413*4882a593Smuzhiyun if (global)
414*4882a593Smuzhiyun CheckDuplicates(hash, "ResizeGlyphHash top");
415*4882a593Smuzhiyun if (!AllocateGlyphHash(&newHash, hashSet))
416*4882a593Smuzhiyun return FALSE;
417*4882a593Smuzhiyun if (hash->table) {
418*4882a593Smuzhiyun oldSize = hash->hashSet->size;
419*4882a593Smuzhiyun for (i = 0; i < oldSize; i++) {
420*4882a593Smuzhiyun glyph = hash->table[i].glyph;
421*4882a593Smuzhiyun if (glyph && glyph != DeletedGlyph) {
422*4882a593Smuzhiyun s = hash->table[i].signature;
423*4882a593Smuzhiyun gr = FindGlyphRef(&newHash, s, global, glyph->sha1);
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun gr->signature = s;
426*4882a593Smuzhiyun gr->glyph = glyph;
427*4882a593Smuzhiyun ++newHash.tableEntries;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun free(hash->table);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun *hash = newHash;
433*4882a593Smuzhiyun if (global)
434*4882a593Smuzhiyun CheckDuplicates(hash, "ResizeGlyphHash bottom");
435*4882a593Smuzhiyun return TRUE;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun Bool
ResizeGlyphSet(GlyphSetPtr glyphSet,CARD32 change)439*4882a593Smuzhiyun ResizeGlyphSet(GlyphSetPtr glyphSet, CARD32 change)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun return (ResizeGlyphHash(&glyphSet->hash, change, FALSE) &&
442*4882a593Smuzhiyun ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], change, TRUE));
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun GlyphSetPtr
AllocateGlyphSet(int fdepth,PictFormatPtr format)446*4882a593Smuzhiyun AllocateGlyphSet(int fdepth, PictFormatPtr format)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun GlyphSetPtr glyphSet;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun if (!globalGlyphs[fdepth].hashSet) {
451*4882a593Smuzhiyun if (!AllocateGlyphHash(&globalGlyphs[fdepth], &glyphHashSets[0]))
452*4882a593Smuzhiyun return FALSE;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET);
456*4882a593Smuzhiyun if (!glyphSet)
457*4882a593Smuzhiyun return FALSE;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun if (!AllocateGlyphHash(&glyphSet->hash, &glyphHashSets[0])) {
460*4882a593Smuzhiyun free(glyphSet);
461*4882a593Smuzhiyun return FALSE;
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun glyphSet->refcnt = 1;
464*4882a593Smuzhiyun glyphSet->fdepth = fdepth;
465*4882a593Smuzhiyun glyphSet->format = format;
466*4882a593Smuzhiyun return glyphSet;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun int
FreeGlyphSet(void * value,XID gid)470*4882a593Smuzhiyun FreeGlyphSet(void *value, XID gid)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun GlyphSetPtr glyphSet = (GlyphSetPtr) value;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun if (--glyphSet->refcnt == 0) {
475*4882a593Smuzhiyun CARD32 i, tableSize = glyphSet->hash.hashSet->size;
476*4882a593Smuzhiyun GlyphRefPtr table = glyphSet->hash.table;
477*4882a593Smuzhiyun GlyphPtr glyph;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun for (i = 0; i < tableSize; i++) {
480*4882a593Smuzhiyun glyph = table[i].glyph;
481*4882a593Smuzhiyun if (glyph && glyph != DeletedGlyph)
482*4882a593Smuzhiyun FreeGlyph(glyph, glyphSet->fdepth);
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun if (!globalGlyphs[glyphSet->fdepth].tableEntries) {
485*4882a593Smuzhiyun free(globalGlyphs[glyphSet->fdepth].table);
486*4882a593Smuzhiyun globalGlyphs[glyphSet->fdepth].table = 0;
487*4882a593Smuzhiyun globalGlyphs[glyphSet->fdepth].hashSet = 0;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun else
490*4882a593Smuzhiyun ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], 0, TRUE);
491*4882a593Smuzhiyun free(table);
492*4882a593Smuzhiyun dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun return Success;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun static void
GlyphExtents(int nlist,GlyphListPtr list,GlyphPtr * glyphs,BoxPtr extents)498*4882a593Smuzhiyun GlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun int x1, x2, y1, y2;
501*4882a593Smuzhiyun int n;
502*4882a593Smuzhiyun GlyphPtr glyph;
503*4882a593Smuzhiyun int x, y;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun x = 0;
506*4882a593Smuzhiyun y = 0;
507*4882a593Smuzhiyun extents->x1 = MAXSHORT;
508*4882a593Smuzhiyun extents->x2 = MINSHORT;
509*4882a593Smuzhiyun extents->y1 = MAXSHORT;
510*4882a593Smuzhiyun extents->y2 = MINSHORT;
511*4882a593Smuzhiyun while (nlist--) {
512*4882a593Smuzhiyun x += list->xOff;
513*4882a593Smuzhiyun y += list->yOff;
514*4882a593Smuzhiyun n = list->len;
515*4882a593Smuzhiyun list++;
516*4882a593Smuzhiyun while (n--) {
517*4882a593Smuzhiyun glyph = *glyphs++;
518*4882a593Smuzhiyun x1 = x - glyph->info.x;
519*4882a593Smuzhiyun if (x1 < MINSHORT)
520*4882a593Smuzhiyun x1 = MINSHORT;
521*4882a593Smuzhiyun y1 = y - glyph->info.y;
522*4882a593Smuzhiyun if (y1 < MINSHORT)
523*4882a593Smuzhiyun y1 = MINSHORT;
524*4882a593Smuzhiyun x2 = x1 + glyph->info.width;
525*4882a593Smuzhiyun if (x2 > MAXSHORT)
526*4882a593Smuzhiyun x2 = MAXSHORT;
527*4882a593Smuzhiyun y2 = y1 + glyph->info.height;
528*4882a593Smuzhiyun if (y2 > MAXSHORT)
529*4882a593Smuzhiyun y2 = MAXSHORT;
530*4882a593Smuzhiyun if (x1 < extents->x1)
531*4882a593Smuzhiyun extents->x1 = x1;
532*4882a593Smuzhiyun if (x2 > extents->x2)
533*4882a593Smuzhiyun extents->x2 = x2;
534*4882a593Smuzhiyun if (y1 < extents->y1)
535*4882a593Smuzhiyun extents->y1 = y1;
536*4882a593Smuzhiyun if (y2 > extents->y2)
537*4882a593Smuzhiyun extents->y2 = y2;
538*4882a593Smuzhiyun x += glyph->info.xOff;
539*4882a593Smuzhiyun y += glyph->info.yOff;
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun void
CompositeGlyphs(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int nlist,GlyphListPtr lists,GlyphPtr * glyphs)547*4882a593Smuzhiyun CompositeGlyphs(CARD8 op,
548*4882a593Smuzhiyun PicturePtr pSrc,
549*4882a593Smuzhiyun PicturePtr pDst,
550*4882a593Smuzhiyun PictFormatPtr maskFormat,
551*4882a593Smuzhiyun INT16 xSrc,
552*4882a593Smuzhiyun INT16 ySrc, int nlist, GlyphListPtr lists, GlyphPtr * glyphs)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun ValidatePicture(pSrc);
557*4882a593Smuzhiyun ValidatePicture(pDst);
558*4882a593Smuzhiyun (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists,
559*4882a593Smuzhiyun glyphs);
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun Bool
miRealizeGlyph(ScreenPtr pScreen,GlyphPtr glyph)563*4882a593Smuzhiyun miRealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph)
564*4882a593Smuzhiyun {
565*4882a593Smuzhiyun return TRUE;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun void
miUnrealizeGlyph(ScreenPtr pScreen,GlyphPtr glyph)569*4882a593Smuzhiyun miUnrealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun void
miGlyphs(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int nlist,GlyphListPtr list,GlyphPtr * glyphs)574*4882a593Smuzhiyun miGlyphs(CARD8 op,
575*4882a593Smuzhiyun PicturePtr pSrc,
576*4882a593Smuzhiyun PicturePtr pDst,
577*4882a593Smuzhiyun PictFormatPtr maskFormat,
578*4882a593Smuzhiyun INT16 xSrc,
579*4882a593Smuzhiyun INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun PicturePtr pPicture;
582*4882a593Smuzhiyun PixmapPtr pMaskPixmap = 0;
583*4882a593Smuzhiyun PicturePtr pMask;
584*4882a593Smuzhiyun ScreenPtr pScreen = pDst->pDrawable->pScreen;
585*4882a593Smuzhiyun int width = 0, height = 0;
586*4882a593Smuzhiyun int x, y;
587*4882a593Smuzhiyun int xDst = list->xOff, yDst = list->yOff;
588*4882a593Smuzhiyun int n;
589*4882a593Smuzhiyun GlyphPtr glyph;
590*4882a593Smuzhiyun int error;
591*4882a593Smuzhiyun BoxRec extents = { 0, 0, 0, 0 };
592*4882a593Smuzhiyun CARD32 component_alpha;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun if (maskFormat) {
595*4882a593Smuzhiyun GCPtr pGC;
596*4882a593Smuzhiyun xRectangle rect;
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun GlyphExtents(nlist, list, glyphs, &extents);
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
601*4882a593Smuzhiyun return;
602*4882a593Smuzhiyun width = extents.x2 - extents.x1;
603*4882a593Smuzhiyun height = extents.y2 - extents.y1;
604*4882a593Smuzhiyun pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
605*4882a593Smuzhiyun maskFormat->depth,
606*4882a593Smuzhiyun CREATE_PIXMAP_USAGE_SCRATCH);
607*4882a593Smuzhiyun if (!pMaskPixmap)
608*4882a593Smuzhiyun return;
609*4882a593Smuzhiyun component_alpha = NeedsComponent(maskFormat->format);
610*4882a593Smuzhiyun pMask = CreatePicture(0, &pMaskPixmap->drawable,
611*4882a593Smuzhiyun maskFormat, CPComponentAlpha, &component_alpha,
612*4882a593Smuzhiyun serverClient, &error);
613*4882a593Smuzhiyun if (!pMask) {
614*4882a593Smuzhiyun (*pScreen->DestroyPixmap) (pMaskPixmap);
615*4882a593Smuzhiyun return;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen);
618*4882a593Smuzhiyun ValidateGC(&pMaskPixmap->drawable, pGC);
619*4882a593Smuzhiyun rect.x = 0;
620*4882a593Smuzhiyun rect.y = 0;
621*4882a593Smuzhiyun rect.width = width;
622*4882a593Smuzhiyun rect.height = height;
623*4882a593Smuzhiyun (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
624*4882a593Smuzhiyun FreeScratchGC(pGC);
625*4882a593Smuzhiyun x = -extents.x1;
626*4882a593Smuzhiyun y = -extents.y1;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun else {
629*4882a593Smuzhiyun pMask = pDst;
630*4882a593Smuzhiyun x = 0;
631*4882a593Smuzhiyun y = 0;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun while (nlist--) {
634*4882a593Smuzhiyun x += list->xOff;
635*4882a593Smuzhiyun y += list->yOff;
636*4882a593Smuzhiyun n = list->len;
637*4882a593Smuzhiyun while (n--) {
638*4882a593Smuzhiyun glyph = *glyphs++;
639*4882a593Smuzhiyun pPicture = GetGlyphPicture(glyph, pScreen);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun if (pPicture) {
642*4882a593Smuzhiyun if (maskFormat) {
643*4882a593Smuzhiyun CompositePicture(PictOpAdd,
644*4882a593Smuzhiyun pPicture,
645*4882a593Smuzhiyun None,
646*4882a593Smuzhiyun pMask,
647*4882a593Smuzhiyun 0, 0,
648*4882a593Smuzhiyun 0, 0,
649*4882a593Smuzhiyun x - glyph->info.x,
650*4882a593Smuzhiyun y - glyph->info.y,
651*4882a593Smuzhiyun glyph->info.width, glyph->info.height);
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun else {
654*4882a593Smuzhiyun CompositePicture(op,
655*4882a593Smuzhiyun pSrc,
656*4882a593Smuzhiyun pPicture,
657*4882a593Smuzhiyun pDst,
658*4882a593Smuzhiyun xSrc + (x - glyph->info.x) - xDst,
659*4882a593Smuzhiyun ySrc + (y - glyph->info.y) - yDst,
660*4882a593Smuzhiyun 0, 0,
661*4882a593Smuzhiyun x - glyph->info.x,
662*4882a593Smuzhiyun y - glyph->info.y,
663*4882a593Smuzhiyun glyph->info.width, glyph->info.height);
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun x += glyph->info.xOff;
668*4882a593Smuzhiyun y += glyph->info.yOff;
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun list++;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun if (maskFormat) {
673*4882a593Smuzhiyun x = extents.x1;
674*4882a593Smuzhiyun y = extents.y1;
675*4882a593Smuzhiyun CompositePicture(op,
676*4882a593Smuzhiyun pSrc,
677*4882a593Smuzhiyun pMask,
678*4882a593Smuzhiyun pDst,
679*4882a593Smuzhiyun xSrc + x - xDst,
680*4882a593Smuzhiyun ySrc + y - yDst, 0, 0, x, y, width, height);
681*4882a593Smuzhiyun FreePicture((void *) pMask, (XID) 0);
682*4882a593Smuzhiyun (*pScreen->DestroyPixmap) (pMaskPixmap);
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
GetGlyphPicture(GlyphPtr glyph,ScreenPtr pScreen)686*4882a593Smuzhiyun PicturePtr GetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun if (pScreen->isGPU)
689*4882a593Smuzhiyun return NULL;
690*4882a593Smuzhiyun return GlyphPicture(glyph)[pScreen->myNum];
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun
SetGlyphPicture(GlyphPtr glyph,ScreenPtr pScreen,PicturePtr picture)693*4882a593Smuzhiyun void SetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen, PicturePtr picture)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun GlyphPicture(glyph)[pScreen->myNum] = picture;
696*4882a593Smuzhiyun }
697