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
19f7df2e56Smrg * 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
294202a189Smrg#include "xsha1.h"
304642e01fSmrg
3105b261ecSmrg#include "misc.h"
3205b261ecSmrg#include "scrnintstr.h"
3305b261ecSmrg#include "os.h"
3405b261ecSmrg#include "regionstr.h"
3505b261ecSmrg#include "validate.h"
3605b261ecSmrg#include "windowstr.h"
3705b261ecSmrg#include "input.h"
3805b261ecSmrg#include "resource.h"
3905b261ecSmrg#include "colormapst.h"
4005b261ecSmrg#include "cursorstr.h"
4105b261ecSmrg#include "dixstruct.h"
4205b261ecSmrg#include "gcstruct.h"
4305b261ecSmrg#include "servermd.h"
4405b261ecSmrg#include "picturestr.h"
4505b261ecSmrg#include "glyphstr.h"
464642e01fSmrg#include "mipict.h"
4705b261ecSmrg
4805b261ecSmrg/*
4905b261ecSmrg * From Knuth -- a good choice for hash/rehash values is p, p-2 where
5005b261ecSmrg * p and p-2 are both prime.  These tables are sized to have an extra 10%
5105b261ecSmrg * free to avoid exponential performance degradation as the hash table fills
5205b261ecSmrg */
5305b261ecSmrgstatic GlyphHashSetRec glyphHashSets[] = {
54f7df2e56Smrg    {32, 43, 41},
55f7df2e56Smrg    {64, 73, 71},
56f7df2e56Smrg    {128, 151, 149},
57f7df2e56Smrg    {256, 283, 281},
58f7df2e56Smrg    {512, 571, 569},
59f7df2e56Smrg    {1024, 1153, 1151},
60f7df2e56Smrg    {2048, 2269, 2267},
61f7df2e56Smrg    {4096, 4519, 4517},
62f7df2e56Smrg    {8192, 9013, 9011},
63f7df2e56Smrg    {16384, 18043, 18041},
64f7df2e56Smrg    {32768, 36109, 36107},
65f7df2e56Smrg    {65536, 72091, 72089},
66f7df2e56Smrg    {131072, 144409, 144407},
67f7df2e56Smrg    {262144, 288361, 288359},
68f7df2e56Smrg    {524288, 576883, 576881},
69f7df2e56Smrg    {1048576, 1153459, 1153457},
70f7df2e56Smrg    {2097152, 2307163, 2307161},
71f7df2e56Smrg    {4194304, 4613893, 4613891},
72f7df2e56Smrg    {8388608, 9227641, 9227639},
73f7df2e56Smrg    {16777216, 18455029, 18455027},
74f7df2e56Smrg    {33554432, 36911011, 36911009},
75f7df2e56Smrg    {67108864, 73819861, 73819859},
76f7df2e56Smrg    {134217728, 147639589, 147639587},
77f7df2e56Smrg    {268435456, 295279081, 295279079},
78f7df2e56Smrg    {536870912, 590559793, 590559791}
7905b261ecSmrg};
8005b261ecSmrg
817e31ba66Smrg#define NGLYPHHASHSETS	ARRAY_SIZE(glyphHashSets)
8205b261ecSmrg
83f7df2e56Smrgstatic GlyphHashRec globalGlyphs[GlyphFormatNum];
8405b261ecSmrg
8505b261ecSmrgvoid
86f7df2e56SmrgGlyphUninit(ScreenPtr pScreen)
8705b261ecSmrg{
88f7df2e56Smrg    PictureScreenPtr ps = GetPictureScreen(pScreen);
89f7df2e56Smrg    GlyphPtr glyph;
90f7df2e56Smrg    int fdepth, i;
91f7df2e56Smrg
92f7df2e56Smrg    for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) {
93f7df2e56Smrg        if (!globalGlyphs[fdepth].hashSet)
94f7df2e56Smrg            continue;
95f7df2e56Smrg
96f7df2e56Smrg        for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) {
97f7df2e56Smrg            glyph = globalGlyphs[fdepth].table[i].glyph;
98f7df2e56Smrg            if (glyph && glyph != DeletedGlyph) {
99f7df2e56Smrg                if (GetGlyphPicture(glyph, pScreen)) {
100f7df2e56Smrg                    FreePicture((void *) GetGlyphPicture(glyph, pScreen), 0);
101f7df2e56Smrg                    SetGlyphPicture(glyph, pScreen, NULL);
102f7df2e56Smrg                }
103f7df2e56Smrg                (*ps->UnrealizeGlyph) (pScreen, glyph);
104f7df2e56Smrg            }
105f7df2e56Smrg        }
10605b261ecSmrg    }
10705b261ecSmrg}
10805b261ecSmrg
109f7df2e56Smrgstatic GlyphHashSetPtr
110f7df2e56SmrgFindGlyphHashSet(CARD32 filled)
11105b261ecSmrg{
112f7df2e56Smrg    int i;
11305b261ecSmrg
11405b261ecSmrg    for (i = 0; i < NGLYPHHASHSETS; i++)
115f7df2e56Smrg        if (glyphHashSets[i].entries >= filled)
116f7df2e56Smrg            return &glyphHashSets[i];
11705b261ecSmrg    return 0;
11805b261ecSmrg}
11905b261ecSmrg
120f7df2e56Smrgstatic GlyphRefPtr
121f7df2e56SmrgFindGlyphRef(GlyphHashPtr hash,
122f7df2e56Smrg             CARD32 signature, Bool match, unsigned char sha1[20])
12305b261ecSmrg{
124f7df2e56Smrg    CARD32 elt, step, s;
125f7df2e56Smrg    GlyphPtr glyph;
126f7df2e56Smrg    GlyphRefPtr table, gr, del;
127f7df2e56Smrg    CARD32 tableSize = hash->hashSet->size;
12805b261ecSmrg
12905b261ecSmrg    table = hash->table;
13005b261ecSmrg    elt = signature % tableSize;
13105b261ecSmrg    step = 0;
13205b261ecSmrg    del = 0;
133f7df2e56Smrg    for (;;) {
134f7df2e56Smrg        gr = &table[elt];
135f7df2e56Smrg        s = gr->signature;
136f7df2e56Smrg        glyph = gr->glyph;
137f7df2e56Smrg        if (!glyph) {
138f7df2e56Smrg            if (del)
139f7df2e56Smrg                gr = del;
140f7df2e56Smrg            break;
141f7df2e56Smrg        }
142f7df2e56Smrg        if (glyph == DeletedGlyph) {
143f7df2e56Smrg            if (!del)
144f7df2e56Smrg                del = gr;
145f7df2e56Smrg            else if (gr == del)
146f7df2e56Smrg                break;
147f7df2e56Smrg        }
148f7df2e56Smrg        else if (s == signature &&
149f7df2e56Smrg                 (!match || memcmp(glyph->sha1, sha1, 20) == 0)) {
150f7df2e56Smrg            break;
151f7df2e56Smrg        }
152f7df2e56Smrg        if (!step) {
153f7df2e56Smrg            step = signature % hash->hashSet->rehash;
154f7df2e56Smrg            if (!step)
155f7df2e56Smrg                step = 1;
156f7df2e56Smrg        }
157f7df2e56Smrg        elt += step;
158f7df2e56Smrg        if (elt >= tableSize)
159f7df2e56Smrg            elt -= tableSize;
16005b261ecSmrg    }
16105b261ecSmrg    return gr;
16205b261ecSmrg}
16305b261ecSmrg
1644642e01fSmrgint
165f7df2e56SmrgHashGlyph(xGlyphInfo * gi,
166f7df2e56Smrg          CARD8 *bits, unsigned long size, unsigned char sha1[20])
16705b261ecSmrg{
1684202a189Smrg    void *ctx = x_sha1_init();
1694642e01fSmrg    int success;
1704642e01fSmrg
1714202a189Smrg    if (!ctx)
172f7df2e56Smrg        return BadAlloc;
1734642e01fSmrg
1744202a189Smrg    success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo));
1754202a189Smrg    if (!success)
176f7df2e56Smrg        return BadAlloc;
1774202a189Smrg    success = x_sha1_update(ctx, bits, size);
1784202a189Smrg    if (!success)
179f7df2e56Smrg        return BadAlloc;
1804202a189Smrg    success = x_sha1_final(ctx, sha1);
1814202a189Smrg    if (!success)
182f7df2e56Smrg        return BadAlloc;
1834642e01fSmrg    return Success;
1844642e01fSmrg}
1854642e01fSmrg
1864642e01fSmrgGlyphPtr
187f7df2e56SmrgFindGlyphByHash(unsigned char sha1[20], int format)
1884642e01fSmrg{
1894642e01fSmrg    GlyphRefPtr gr;
1904642e01fSmrg    CARD32 signature = *(CARD32 *) sha1;
1914642e01fSmrg
192ad5464f4Smrg    if (!globalGlyphs[format].hashSet)
193f7df2e56Smrg        return NULL;
194ad5464f4Smrg
195f7df2e56Smrg    gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, sha1);
1964642e01fSmrg
1974642e01fSmrg    if (gr->glyph && gr->glyph != DeletedGlyph)
198f7df2e56Smrg        return gr->glyph;
1994642e01fSmrg    else
200f7df2e56Smrg        return NULL;
20105b261ecSmrg}
20205b261ecSmrg
20305b261ecSmrg#ifdef CHECK_DUPLICATES
20405b261ecSmrgvoid
205f7df2e56SmrgDuplicateRef(GlyphPtr glyph, char *where)
20605b261ecSmrg{
207f7df2e56Smrg    ErrorF("Duplicate Glyph 0x%x from %s\n", glyph, where);
20805b261ecSmrg}
20905b261ecSmrg
21005b261ecSmrgvoid
211f7df2e56SmrgCheckDuplicates(GlyphHashPtr hash, char *where)
21205b261ecSmrg{
213f7df2e56Smrg    GlyphPtr g;
214f7df2e56Smrg    int i, j;
215f7df2e56Smrg
216f7df2e56Smrg    for (i = 0; i < hash->hashSet->size; i++) {
217f7df2e56Smrg        g = hash->table[i].glyph;
218f7df2e56Smrg        if (!g || g == DeletedGlyph)
219f7df2e56Smrg            continue;
220f7df2e56Smrg        for (j = i + 1; j < hash->hashSet->size; j++)
221f7df2e56Smrg            if (hash->table[j].glyph == g)
222f7df2e56Smrg                DuplicateRef(g, where);
22305b261ecSmrg    }
22405b261ecSmrg}
22505b261ecSmrg#else
22605b261ecSmrg#define CheckDuplicates(a,b)
22705b261ecSmrg#define DuplicateRef(a,b)
22805b261ecSmrg#endif
22905b261ecSmrg
2304202a189Smrgstatic void
2314202a189SmrgFreeGlyphPicture(GlyphPtr glyph)
2324202a189Smrg{
2334202a189Smrg    PictureScreenPtr ps;
2344202a189Smrg    int i;
2354202a189Smrg
236f7df2e56Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
2374202a189Smrg        ScreenPtr pScreen = screenInfo.screens[i];
2384202a189Smrg
239f7df2e56Smrg        if (GetGlyphPicture(glyph, pScreen))
240f7df2e56Smrg            FreePicture((void *) GetGlyphPicture(glyph, pScreen), 0);
2414202a189Smrg
242f7df2e56Smrg        ps = GetPictureScreenIfSet(pScreen);
2434202a189Smrg        if (ps)
2444202a189Smrg            (*ps->UnrealizeGlyph) (pScreen, glyph);
2454202a189Smrg    }
2464202a189Smrg}
2474202a189Smrg
248875c6e4fSmrgvoid
249f7df2e56SmrgFreeGlyph(GlyphPtr glyph, int format)
25005b261ecSmrg{
251f7df2e56Smrg    CheckDuplicates(&globalGlyphs[format], "FreeGlyph");
252875c6e4fSmrg    BUG_RETURN(glyph->refcnt == 0);
253f7df2e56Smrg    if (--glyph->refcnt == 0) {
254f7df2e56Smrg        GlyphRefPtr gr;
255f7df2e56Smrg        int i;
256f7df2e56Smrg        int first;
257f7df2e56Smrg        CARD32 signature;
258f7df2e56Smrg
259f7df2e56Smrg        first = -1;
260f7df2e56Smrg        for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
261f7df2e56Smrg            if (globalGlyphs[format].table[i].glyph == glyph) {
262f7df2e56Smrg                if (first != -1)
263f7df2e56Smrg                    DuplicateRef(glyph, "FreeGlyph check");
264f7df2e56Smrg                first = i;
265f7df2e56Smrg            }
266f7df2e56Smrg
267f7df2e56Smrg        signature = *(CARD32 *) glyph->sha1;
268f7df2e56Smrg        gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, glyph->sha1);
269f7df2e56Smrg        if (gr - globalGlyphs[format].table != first)
270f7df2e56Smrg            DuplicateRef(glyph, "Found wrong one");
271f7df2e56Smrg        if (gr->glyph && gr->glyph != DeletedGlyph) {
272f7df2e56Smrg            gr->glyph = DeletedGlyph;
273f7df2e56Smrg            gr->signature = 0;
274f7df2e56Smrg            globalGlyphs[format].tableEntries--;
275f7df2e56Smrg        }
276f7df2e56Smrg
277f7df2e56Smrg        FreeGlyphPicture(glyph);
278f7df2e56Smrg        dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
27905b261ecSmrg    }
28005b261ecSmrg}
28105b261ecSmrg
28205b261ecSmrgvoid
283f7df2e56SmrgAddGlyph(GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
28405b261ecSmrg{
285f7df2e56Smrg    GlyphRefPtr gr;
286f7df2e56Smrg    CARD32 signature;
28705b261ecSmrg
288f7df2e56Smrg    CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
28905b261ecSmrg    /* Locate existing matching glyph */
2904642e01fSmrg    signature = *(CARD32 *) glyph->sha1;
291f7df2e56Smrg    gr = FindGlyphRef(&globalGlyphs[glyphSet->fdepth], signature,
292f7df2e56Smrg                      TRUE, glyph->sha1);
293f7df2e56Smrg    if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) {
294f7df2e56Smrg        glyph = gr->glyph;
29505b261ecSmrg    }
296f7df2e56Smrg    else if (gr->glyph != glyph) {
297f7df2e56Smrg        gr->glyph = glyph;
298f7df2e56Smrg        gr->signature = signature;
299f7df2e56Smrg        globalGlyphs[glyphSet->fdepth].tableEntries++;
30005b261ecSmrg    }
301f7df2e56Smrg
30205b261ecSmrg    /* Insert/replace glyphset value */
303f7df2e56Smrg    gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0);
30405b261ecSmrg    ++glyph->refcnt;
30505b261ecSmrg    if (gr->glyph && gr->glyph != DeletedGlyph)
306f7df2e56Smrg        FreeGlyph(gr->glyph, glyphSet->fdepth);
30705b261ecSmrg    else
308f7df2e56Smrg        glyphSet->hash.tableEntries++;
30905b261ecSmrg    gr->glyph = glyph;
31005b261ecSmrg    gr->signature = id;
311f7df2e56Smrg    CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
31205b261ecSmrg}
31305b261ecSmrg
31405b261ecSmrgBool
315f7df2e56SmrgDeleteGlyph(GlyphSetPtr glyphSet, Glyph id)
31605b261ecSmrg{
317f7df2e56Smrg    GlyphRefPtr gr;
318f7df2e56Smrg    GlyphPtr glyph;
31905b261ecSmrg
320f7df2e56Smrg    gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0);
32105b261ecSmrg    glyph = gr->glyph;
322f7df2e56Smrg    if (glyph && glyph != DeletedGlyph) {
323f7df2e56Smrg        gr->glyph = DeletedGlyph;
324f7df2e56Smrg        glyphSet->hash.tableEntries--;
325f7df2e56Smrg        FreeGlyph(glyph, glyphSet->fdepth);
326f7df2e56Smrg        return TRUE;
32705b261ecSmrg    }
32805b261ecSmrg    return FALSE;
32905b261ecSmrg}
33005b261ecSmrg
33105b261ecSmrgGlyphPtr
332f7df2e56SmrgFindGlyph(GlyphSetPtr glyphSet, Glyph id)
33305b261ecSmrg{
334f7df2e56Smrg    GlyphPtr glyph;
33505b261ecSmrg
336f7df2e56Smrg    glyph = FindGlyphRef(&glyphSet->hash, id, FALSE, 0)->glyph;
33705b261ecSmrg    if (glyph == DeletedGlyph)
338f7df2e56Smrg        glyph = 0;
33905b261ecSmrg    return glyph;
34005b261ecSmrg}
34105b261ecSmrg
34205b261ecSmrgGlyphPtr
343f7df2e56SmrgAllocateGlyph(xGlyphInfo * gi, int fdepth)
34405b261ecSmrg{
34505b261ecSmrg    PictureScreenPtr ps;
346f7df2e56Smrg    int size;
347f7df2e56Smrg    GlyphPtr glyph;
348f7df2e56Smrg    int i;
349f7df2e56Smrg    int head_size;
3504642e01fSmrg
351f7df2e56Smrg    head_size = sizeof(GlyphRec) + screenInfo.numScreens * sizeof(PicturePtr);
3524202a189Smrg    size = (head_size + dixPrivatesSize(PRIVATE_GLYPH));
353f7df2e56Smrg    glyph = (GlyphPtr) malloc(size);
35405b261ecSmrg    if (!glyph)
355f7df2e56Smrg        return 0;
356875c6e4fSmrg    glyph->refcnt = 1;
357f7df2e56Smrg    glyph->size = size + sizeof(xGlyphInfo);
35805b261ecSmrg    glyph->info = *gi;
3594202a189Smrg    dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH);
36005b261ecSmrg
361f7df2e56Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
362f7df2e56Smrg        ScreenPtr pScreen = screenInfo.screens[i];
363f7df2e56Smrg        SetGlyphPicture(glyph, pScreen, NULL);
364f7df2e56Smrg        ps = GetPictureScreenIfSet(pScreen);
3654642e01fSmrg
366f7df2e56Smrg        if (ps) {
367f7df2e56Smrg            if (!(*ps->RealizeGlyph) (pScreen, glyph))
368f7df2e56Smrg                goto bail;
369f7df2e56Smrg        }
37005b261ecSmrg    }
371f7df2e56Smrg
37205b261ecSmrg    return glyph;
3734642e01fSmrg
374f7df2e56Smrg bail:
375f7df2e56Smrg    while (i--) {
376f7df2e56Smrg        ps = GetPictureScreenIfSet(screenInfo.screens[i]);
377f7df2e56Smrg        if (ps)
378f7df2e56Smrg            (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
3794642e01fSmrg    }
3804642e01fSmrg
3814202a189Smrg    dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
3824642e01fSmrg    return 0;
38305b261ecSmrg}
384f7df2e56Smrg
385f7df2e56Smrgstatic Bool
386f7df2e56SmrgAllocateGlyphHash(GlyphHashPtr hash, GlyphHashSetPtr hashSet)
38705b261ecSmrg{
388f7df2e56Smrg    hash->table = calloc(hashSet->size, sizeof(GlyphRefRec));
38905b261ecSmrg    if (!hash->table)
390f7df2e56Smrg        return FALSE;
39105b261ecSmrg    hash->hashSet = hashSet;
39205b261ecSmrg    hash->tableEntries = 0;
39305b261ecSmrg    return TRUE;
39405b261ecSmrg}
39505b261ecSmrg
396f7df2e56Smrgstatic Bool
397f7df2e56SmrgResizeGlyphHash(GlyphHashPtr hash, CARD32 change, Bool global)
39805b261ecSmrg{
399f7df2e56Smrg    CARD32 tableEntries;
40005b261ecSmrg    GlyphHashSetPtr hashSet;
401f7df2e56Smrg    GlyphHashRec newHash;
402f7df2e56Smrg    GlyphRefPtr gr;
403f7df2e56Smrg    GlyphPtr glyph;
404f7df2e56Smrg    int i;
405f7df2e56Smrg    int oldSize;
406f7df2e56Smrg    CARD32 s;
40705b261ecSmrg
40805b261ecSmrg    tableEntries = hash->tableEntries + change;
409f7df2e56Smrg    hashSet = FindGlyphHashSet(tableEntries);
41005b261ecSmrg    if (hashSet == hash->hashSet)
411f7df2e56Smrg        return TRUE;
41205b261ecSmrg    if (global)
413f7df2e56Smrg        CheckDuplicates(hash, "ResizeGlyphHash top");
414f7df2e56Smrg    if (!AllocateGlyphHash(&newHash, hashSet))
415f7df2e56Smrg        return FALSE;
416f7df2e56Smrg    if (hash->table) {
417f7df2e56Smrg        oldSize = hash->hashSet->size;
418f7df2e56Smrg        for (i = 0; i < oldSize; i++) {
419f7df2e56Smrg            glyph = hash->table[i].glyph;
420f7df2e56Smrg            if (glyph && glyph != DeletedGlyph) {
421f7df2e56Smrg                s = hash->table[i].signature;
422f7df2e56Smrg                gr = FindGlyphRef(&newHash, s, global, glyph->sha1);
423f7df2e56Smrg
424f7df2e56Smrg                gr->signature = s;
425f7df2e56Smrg                gr->glyph = glyph;
426f7df2e56Smrg                ++newHash.tableEntries;
427f7df2e56Smrg            }
428f7df2e56Smrg        }
429f7df2e56Smrg        free(hash->table);
43005b261ecSmrg    }
43105b261ecSmrg    *hash = newHash;
43205b261ecSmrg    if (global)
433f7df2e56Smrg        CheckDuplicates(hash, "ResizeGlyphHash bottom");
43405b261ecSmrg    return TRUE;
43505b261ecSmrg}
43605b261ecSmrg
43705b261ecSmrgBool
438f7df2e56SmrgResizeGlyphSet(GlyphSetPtr glyphSet, CARD32 change)
43905b261ecSmrg{
440f7df2e56Smrg    return (ResizeGlyphHash(&glyphSet->hash, change, FALSE) &&
441f7df2e56Smrg            ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], change, TRUE));
44205b261ecSmrg}
443f7df2e56Smrg
44405b261ecSmrgGlyphSetPtr
445f7df2e56SmrgAllocateGlyphSet(int fdepth, PictFormatPtr format)
44605b261ecSmrg{
447f7df2e56Smrg    GlyphSetPtr glyphSet;
448f7df2e56Smrg
449f7df2e56Smrg    if (!globalGlyphs[fdepth].hashSet) {
450f7df2e56Smrg        if (!AllocateGlyphHash(&globalGlyphs[fdepth], &glyphHashSets[0]))
451f7df2e56Smrg            return FALSE;
45205b261ecSmrg    }
45305b261ecSmrg
4544202a189Smrg    glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET);
45505b261ecSmrg    if (!glyphSet)
456f7df2e56Smrg        return FALSE;
45705b261ecSmrg
458f7df2e56Smrg    if (!AllocateGlyphHash(&glyphSet->hash, &glyphHashSets[0])) {
459f7df2e56Smrg        free(glyphSet);
460f7df2e56Smrg        return FALSE;
46105b261ecSmrg    }
46205b261ecSmrg    glyphSet->refcnt = 1;
46305b261ecSmrg    glyphSet->fdepth = fdepth;
46405b261ecSmrg    glyphSet->format = format;
465f7df2e56Smrg    return glyphSet;
46605b261ecSmrg}
46705b261ecSmrg
46805b261ecSmrgint
469f7df2e56SmrgFreeGlyphSet(void *value, XID gid)
47005b261ecSmrg{
471f7df2e56Smrg    GlyphSetPtr glyphSet = (GlyphSetPtr) value;
472f7df2e56Smrg
473f7df2e56Smrg    if (--glyphSet->refcnt == 0) {
474f7df2e56Smrg        CARD32 i, tableSize = glyphSet->hash.hashSet->size;
475f7df2e56Smrg        GlyphRefPtr table = glyphSet->hash.table;
476f7df2e56Smrg        GlyphPtr glyph;
477f7df2e56Smrg
478f7df2e56Smrg        for (i = 0; i < tableSize; i++) {
479f7df2e56Smrg            glyph = table[i].glyph;
480f7df2e56Smrg            if (glyph && glyph != DeletedGlyph)
481f7df2e56Smrg                FreeGlyph(glyph, glyphSet->fdepth);
482f7df2e56Smrg        }
483f7df2e56Smrg        if (!globalGlyphs[glyphSet->fdepth].tableEntries) {
484f7df2e56Smrg            free(globalGlyphs[glyphSet->fdepth].table);
485f7df2e56Smrg            globalGlyphs[glyphSet->fdepth].table = 0;
486f7df2e56Smrg            globalGlyphs[glyphSet->fdepth].hashSet = 0;
487f7df2e56Smrg        }
488f7df2e56Smrg        else
489f7df2e56Smrg            ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], 0, TRUE);
490f7df2e56Smrg        free(table);
491f7df2e56Smrg        dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET);
49205b261ecSmrg    }
49305b261ecSmrg    return Success;
49405b261ecSmrg}
4954642e01fSmrg
4964642e01fSmrgstatic void
497f7df2e56SmrgGlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents)
4984642e01fSmrg{
499f7df2e56Smrg    int x1, x2, y1, y2;
500f7df2e56Smrg    int n;
501f7df2e56Smrg    GlyphPtr glyph;
502f7df2e56Smrg    int x, y;
503f7df2e56Smrg
5044642e01fSmrg    x = 0;
5054642e01fSmrg    y = 0;
5064642e01fSmrg    extents->x1 = MAXSHORT;
5074642e01fSmrg    extents->x2 = MINSHORT;
5084642e01fSmrg    extents->y1 = MAXSHORT;
5094642e01fSmrg    extents->y2 = MINSHORT;
510f7df2e56Smrg    while (nlist--) {
511f7df2e56Smrg        x += list->xOff;
512f7df2e56Smrg        y += list->yOff;
513f7df2e56Smrg        n = list->len;
514f7df2e56Smrg        list++;
515f7df2e56Smrg        while (n--) {
516f7df2e56Smrg            glyph = *glyphs++;
517f7df2e56Smrg            x1 = x - glyph->info.x;
518f7df2e56Smrg            if (x1 < MINSHORT)
519f7df2e56Smrg                x1 = MINSHORT;
520f7df2e56Smrg            y1 = y - glyph->info.y;
521f7df2e56Smrg            if (y1 < MINSHORT)
522f7df2e56Smrg                y1 = MINSHORT;
523f7df2e56Smrg            x2 = x1 + glyph->info.width;
524f7df2e56Smrg            if (x2 > MAXSHORT)
525f7df2e56Smrg                x2 = MAXSHORT;
526f7df2e56Smrg            y2 = y1 + glyph->info.height;
527f7df2e56Smrg            if (y2 > MAXSHORT)
528f7df2e56Smrg                y2 = MAXSHORT;
529f7df2e56Smrg            if (x1 < extents->x1)
530f7df2e56Smrg                extents->x1 = x1;
531f7df2e56Smrg            if (x2 > extents->x2)
532f7df2e56Smrg                extents->x2 = x2;
533f7df2e56Smrg            if (y1 < extents->y1)
534f7df2e56Smrg                extents->y1 = y1;
535f7df2e56Smrg            if (y2 > extents->y2)
536f7df2e56Smrg                extents->y2 = y2;
537f7df2e56Smrg            x += glyph->info.xOff;
538f7df2e56Smrg            y += glyph->info.yOff;
539f7df2e56Smrg        }
5404642e01fSmrg    }
5414642e01fSmrg}
5424642e01fSmrg
5434642e01fSmrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
5444642e01fSmrg
5454202a189Smrgvoid
546f7df2e56SmrgCompositeGlyphs(CARD8 op,
547f7df2e56Smrg                PicturePtr pSrc,
548f7df2e56Smrg                PicturePtr pDst,
549f7df2e56Smrg                PictFormatPtr maskFormat,
550f7df2e56Smrg                INT16 xSrc,
551f7df2e56Smrg                INT16 ySrc, int nlist, GlyphListPtr lists, GlyphPtr * glyphs)
5524642e01fSmrg{
553f7df2e56Smrg    PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
5544642e01fSmrg
555f7df2e56Smrg    ValidatePicture(pSrc);
556f7df2e56Smrg    ValidatePicture(pDst);
557f7df2e56Smrg    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists,
558f7df2e56Smrg                   glyphs);
5594642e01fSmrg}
5604642e01fSmrg
5614642e01fSmrgBool
562f7df2e56SmrgmiRealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph)
5634642e01fSmrg{
5644642e01fSmrg    return TRUE;
5654642e01fSmrg}
5664642e01fSmrg
5674642e01fSmrgvoid
568f7df2e56SmrgmiUnrealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph)
5694642e01fSmrg{
5704642e01fSmrg}
5714642e01fSmrg
5724202a189Smrgvoid
573f7df2e56SmrgmiGlyphs(CARD8 op,
574f7df2e56Smrg         PicturePtr pSrc,
575f7df2e56Smrg         PicturePtr pDst,
576f7df2e56Smrg         PictFormatPtr maskFormat,
577f7df2e56Smrg         INT16 xSrc,
578f7df2e56Smrg         INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
5794642e01fSmrg{
580f7df2e56Smrg    PicturePtr pPicture;
581f7df2e56Smrg    PixmapPtr pMaskPixmap = 0;
582f7df2e56Smrg    PicturePtr pMask;
583f7df2e56Smrg    ScreenPtr pScreen = pDst->pDrawable->pScreen;
584f7df2e56Smrg    int width = 0, height = 0;
585f7df2e56Smrg    int x, y;
586f7df2e56Smrg    int xDst = list->xOff, yDst = list->yOff;
587f7df2e56Smrg    int n;
588f7df2e56Smrg    GlyphPtr glyph;
589f7df2e56Smrg    int error;
590f7df2e56Smrg    BoxRec extents = { 0, 0, 0, 0 };
591f7df2e56Smrg    CARD32 component_alpha;
592f7df2e56Smrg
593f7df2e56Smrg    if (maskFormat) {
594f7df2e56Smrg        GCPtr pGC;
595f7df2e56Smrg        xRectangle rect;
596f7df2e56Smrg
597f7df2e56Smrg        GlyphExtents(nlist, list, glyphs, &extents);
598f7df2e56Smrg
599f7df2e56Smrg        if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
600f7df2e56Smrg            return;
601f7df2e56Smrg        width = extents.x2 - extents.x1;
602f7df2e56Smrg        height = extents.y2 - extents.y1;
603f7df2e56Smrg        pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
604f7df2e56Smrg                                                maskFormat->depth,
605f7df2e56Smrg                                                CREATE_PIXMAP_USAGE_SCRATCH);
606f7df2e56Smrg        if (!pMaskPixmap)
607f7df2e56Smrg            return;
608f7df2e56Smrg        component_alpha = NeedsComponent(maskFormat->format);
609f7df2e56Smrg        pMask = CreatePicture(0, &pMaskPixmap->drawable,
610f7df2e56Smrg                              maskFormat, CPComponentAlpha, &component_alpha,
611f7df2e56Smrg                              serverClient, &error);
612f7df2e56Smrg        if (!pMask) {
613f7df2e56Smrg            (*pScreen->DestroyPixmap) (pMaskPixmap);
614f7df2e56Smrg            return;
615f7df2e56Smrg        }
616f7df2e56Smrg        pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen);
617f7df2e56Smrg        ValidateGC(&pMaskPixmap->drawable, pGC);
618f7df2e56Smrg        rect.x = 0;
619f7df2e56Smrg        rect.y = 0;
620f7df2e56Smrg        rect.width = width;
621f7df2e56Smrg        rect.height = height;
622f7df2e56Smrg        (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
623f7df2e56Smrg        FreeScratchGC(pGC);
624f7df2e56Smrg        x = -extents.x1;
625f7df2e56Smrg        y = -extents.y1;
6264642e01fSmrg    }
627f7df2e56Smrg    else {
628f7df2e56Smrg        pMask = pDst;
629f7df2e56Smrg        x = 0;
630f7df2e56Smrg        y = 0;
6314642e01fSmrg    }
632f7df2e56Smrg    while (nlist--) {
633f7df2e56Smrg        x += list->xOff;
634f7df2e56Smrg        y += list->yOff;
635f7df2e56Smrg        n = list->len;
636f7df2e56Smrg        while (n--) {
637f7df2e56Smrg            glyph = *glyphs++;
638f7df2e56Smrg            pPicture = GetGlyphPicture(glyph, pScreen);
639f7df2e56Smrg
640f7df2e56Smrg            if (pPicture) {
641f7df2e56Smrg                if (maskFormat) {
642f7df2e56Smrg                    CompositePicture(PictOpAdd,
643f7df2e56Smrg                                     pPicture,
644f7df2e56Smrg                                     None,
645f7df2e56Smrg                                     pMask,
646f7df2e56Smrg                                     0, 0,
647f7df2e56Smrg                                     0, 0,
648f7df2e56Smrg                                     x - glyph->info.x,
649f7df2e56Smrg                                     y - glyph->info.y,
650f7df2e56Smrg                                     glyph->info.width, glyph->info.height);
651f7df2e56Smrg                }
652f7df2e56Smrg                else {
653f7df2e56Smrg                    CompositePicture(op,
654f7df2e56Smrg                                     pSrc,
655f7df2e56Smrg                                     pPicture,
656f7df2e56Smrg                                     pDst,
657f7df2e56Smrg                                     xSrc + (x - glyph->info.x) - xDst,
658f7df2e56Smrg                                     ySrc + (y - glyph->info.y) - yDst,
659f7df2e56Smrg                                     0, 0,
660f7df2e56Smrg                                     x - glyph->info.x,
661f7df2e56Smrg                                     y - glyph->info.y,
662f7df2e56Smrg                                     glyph->info.width, glyph->info.height);
663f7df2e56Smrg                }
664f7df2e56Smrg            }
665f7df2e56Smrg
666f7df2e56Smrg            x += glyph->info.xOff;
667f7df2e56Smrg            y += glyph->info.yOff;
668f7df2e56Smrg        }
669f7df2e56Smrg        list++;
6704642e01fSmrg    }
671f7df2e56Smrg    if (maskFormat) {
672f7df2e56Smrg        x = extents.x1;
673f7df2e56Smrg        y = extents.y1;
674f7df2e56Smrg        CompositePicture(op,
675f7df2e56Smrg                         pSrc,
676f7df2e56Smrg                         pMask,
677f7df2e56Smrg                         pDst,
678f7df2e56Smrg                         xSrc + x - xDst,
679f7df2e56Smrg                         ySrc + y - yDst, 0, 0, x, y, width, height);
680f7df2e56Smrg        FreePicture((void *) pMask, (XID) 0);
681f7df2e56Smrg        (*pScreen->DestroyPixmap) (pMaskPixmap);
6824642e01fSmrg    }
6834642e01fSmrg}
684f7df2e56Smrg
685f7df2e56SmrgPicturePtr GetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen)
686f7df2e56Smrg{
687f7df2e56Smrg    if (pScreen->isGPU)
688f7df2e56Smrg        return NULL;
689f7df2e56Smrg    return GlyphPicture(glyph)[pScreen->myNum];
690f7df2e56Smrg}
691f7df2e56Smrg
692f7df2e56Smrgvoid SetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen, PicturePtr picture)
693f7df2e56Smrg{
694f7df2e56Smrg    GlyphPicture(glyph)[pScreen->myNum] = picture;
695f7df2e56Smrg}
696