glyph.c revision f7df2e56
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
8105b261ecSmrg#define NGLYPHHASHSETS	(sizeof(glyphHashSets)/sizeof(glyphHashSets[0]))
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
248f7df2e56Smrgstatic void
249f7df2e56SmrgFreeGlyph(GlyphPtr glyph, int format)
25005b261ecSmrg{
251f7df2e56Smrg    CheckDuplicates(&globalGlyphs[format], "FreeGlyph");
252f7df2e56Smrg    if (--glyph->refcnt == 0) {
253f7df2e56Smrg        GlyphRefPtr gr;
254f7df2e56Smrg        int i;
255f7df2e56Smrg        int first;
256f7df2e56Smrg        CARD32 signature;
257f7df2e56Smrg
258f7df2e56Smrg        first = -1;
259f7df2e56Smrg        for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
260f7df2e56Smrg            if (globalGlyphs[format].table[i].glyph == glyph) {
261f7df2e56Smrg                if (first != -1)
262f7df2e56Smrg                    DuplicateRef(glyph, "FreeGlyph check");
263f7df2e56Smrg                first = i;
264f7df2e56Smrg            }
265f7df2e56Smrg
266f7df2e56Smrg        signature = *(CARD32 *) glyph->sha1;
267f7df2e56Smrg        gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, glyph->sha1);
268f7df2e56Smrg        if (gr - globalGlyphs[format].table != first)
269f7df2e56Smrg            DuplicateRef(glyph, "Found wrong one");
270f7df2e56Smrg        if (gr->glyph && gr->glyph != DeletedGlyph) {
271f7df2e56Smrg            gr->glyph = DeletedGlyph;
272f7df2e56Smrg            gr->signature = 0;
273f7df2e56Smrg            globalGlyphs[format].tableEntries--;
274f7df2e56Smrg        }
275f7df2e56Smrg
276f7df2e56Smrg        FreeGlyphPicture(glyph);
277f7df2e56Smrg        dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
27805b261ecSmrg    }
27905b261ecSmrg}
28005b261ecSmrg
28105b261ecSmrgvoid
282f7df2e56SmrgAddGlyph(GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
28305b261ecSmrg{
284f7df2e56Smrg    GlyphRefPtr gr;
285f7df2e56Smrg    CARD32 signature;
28605b261ecSmrg
287f7df2e56Smrg    CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
28805b261ecSmrg    /* Locate existing matching glyph */
2894642e01fSmrg    signature = *(CARD32 *) glyph->sha1;
290f7df2e56Smrg    gr = FindGlyphRef(&globalGlyphs[glyphSet->fdepth], signature,
291f7df2e56Smrg                      TRUE, glyph->sha1);
292f7df2e56Smrg    if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) {
293f7df2e56Smrg        FreeGlyphPicture(glyph);
294f7df2e56Smrg        dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
295f7df2e56Smrg        glyph = gr->glyph;
29605b261ecSmrg    }
297f7df2e56Smrg    else if (gr->glyph != glyph) {
298f7df2e56Smrg        gr->glyph = glyph;
299f7df2e56Smrg        gr->signature = signature;
300f7df2e56Smrg        globalGlyphs[glyphSet->fdepth].tableEntries++;
30105b261ecSmrg    }
302f7df2e56Smrg
30305b261ecSmrg    /* Insert/replace glyphset value */
304f7df2e56Smrg    gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0);
30505b261ecSmrg    ++glyph->refcnt;
30605b261ecSmrg    if (gr->glyph && gr->glyph != DeletedGlyph)
307f7df2e56Smrg        FreeGlyph(gr->glyph, glyphSet->fdepth);
30805b261ecSmrg    else
309f7df2e56Smrg        glyphSet->hash.tableEntries++;
31005b261ecSmrg    gr->glyph = glyph;
31105b261ecSmrg    gr->signature = id;
312f7df2e56Smrg    CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
31305b261ecSmrg}
31405b261ecSmrg
31505b261ecSmrgBool
316f7df2e56SmrgDeleteGlyph(GlyphSetPtr glyphSet, Glyph id)
31705b261ecSmrg{
318f7df2e56Smrg    GlyphRefPtr gr;
319f7df2e56Smrg    GlyphPtr glyph;
32005b261ecSmrg
321f7df2e56Smrg    gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0);
32205b261ecSmrg    glyph = gr->glyph;
323f7df2e56Smrg    if (glyph && glyph != DeletedGlyph) {
324f7df2e56Smrg        gr->glyph = DeletedGlyph;
325f7df2e56Smrg        glyphSet->hash.tableEntries--;
326f7df2e56Smrg        FreeGlyph(glyph, glyphSet->fdepth);
327f7df2e56Smrg        return TRUE;
32805b261ecSmrg    }
32905b261ecSmrg    return FALSE;
33005b261ecSmrg}
33105b261ecSmrg
33205b261ecSmrgGlyphPtr
333f7df2e56SmrgFindGlyph(GlyphSetPtr glyphSet, Glyph id)
33405b261ecSmrg{
335f7df2e56Smrg    GlyphPtr glyph;
33605b261ecSmrg
337f7df2e56Smrg    glyph = FindGlyphRef(&glyphSet->hash, id, FALSE, 0)->glyph;
33805b261ecSmrg    if (glyph == DeletedGlyph)
339f7df2e56Smrg        glyph = 0;
34005b261ecSmrg    return glyph;
34105b261ecSmrg}
34205b261ecSmrg
34305b261ecSmrgGlyphPtr
344f7df2e56SmrgAllocateGlyph(xGlyphInfo * gi, int fdepth)
34505b261ecSmrg{
34605b261ecSmrg    PictureScreenPtr ps;
347f7df2e56Smrg    int size;
348f7df2e56Smrg    GlyphPtr glyph;
349f7df2e56Smrg    int i;
350f7df2e56Smrg    int head_size;
3514642e01fSmrg
352f7df2e56Smrg    head_size = sizeof(GlyphRec) + screenInfo.numScreens * sizeof(PicturePtr);
3534202a189Smrg    size = (head_size + dixPrivatesSize(PRIVATE_GLYPH));
354f7df2e56Smrg    glyph = (GlyphPtr) malloc(size);
35505b261ecSmrg    if (!glyph)
356f7df2e56Smrg        return 0;
35705b261ecSmrg    glyph->refcnt = 0;
358f7df2e56Smrg    glyph->size = size + sizeof(xGlyphInfo);
35905b261ecSmrg    glyph->info = *gi;
3604202a189Smrg    dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH);
36105b261ecSmrg
362f7df2e56Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
363f7df2e56Smrg        ScreenPtr pScreen = screenInfo.screens[i];
364f7df2e56Smrg        SetGlyphPicture(glyph, pScreen, NULL);
365f7df2e56Smrg        ps = GetPictureScreenIfSet(pScreen);
3664642e01fSmrg
367f7df2e56Smrg        if (ps) {
368f7df2e56Smrg            if (!(*ps->RealizeGlyph) (pScreen, glyph))
369f7df2e56Smrg                goto bail;
370f7df2e56Smrg        }
37105b261ecSmrg    }
372f7df2e56Smrg
37305b261ecSmrg    return glyph;
3744642e01fSmrg
375f7df2e56Smrg bail:
376f7df2e56Smrg    while (i--) {
377f7df2e56Smrg        ps = GetPictureScreenIfSet(screenInfo.screens[i]);
378f7df2e56Smrg        if (ps)
379f7df2e56Smrg            (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
3804642e01fSmrg    }
3814642e01fSmrg
3824202a189Smrg    dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH);
3834642e01fSmrg    return 0;
38405b261ecSmrg}
385f7df2e56Smrg
386f7df2e56Smrgstatic Bool
387f7df2e56SmrgAllocateGlyphHash(GlyphHashPtr hash, GlyphHashSetPtr hashSet)
38805b261ecSmrg{
389f7df2e56Smrg    hash->table = calloc(hashSet->size, sizeof(GlyphRefRec));
39005b261ecSmrg    if (!hash->table)
391f7df2e56Smrg        return FALSE;
39205b261ecSmrg    hash->hashSet = hashSet;
39305b261ecSmrg    hash->tableEntries = 0;
39405b261ecSmrg    return TRUE;
39505b261ecSmrg}
39605b261ecSmrg
397f7df2e56Smrgstatic Bool
398f7df2e56SmrgResizeGlyphHash(GlyphHashPtr hash, CARD32 change, Bool global)
39905b261ecSmrg{
400f7df2e56Smrg    CARD32 tableEntries;
40105b261ecSmrg    GlyphHashSetPtr hashSet;
402f7df2e56Smrg    GlyphHashRec newHash;
403f7df2e56Smrg    GlyphRefPtr gr;
404f7df2e56Smrg    GlyphPtr glyph;
405f7df2e56Smrg    int i;
406f7df2e56Smrg    int oldSize;
407f7df2e56Smrg    CARD32 s;
40805b261ecSmrg
40905b261ecSmrg    tableEntries = hash->tableEntries + change;
410f7df2e56Smrg    hashSet = FindGlyphHashSet(tableEntries);
41105b261ecSmrg    if (hashSet == hash->hashSet)
412f7df2e56Smrg        return TRUE;
41305b261ecSmrg    if (global)
414f7df2e56Smrg        CheckDuplicates(hash, "ResizeGlyphHash top");
415f7df2e56Smrg    if (!AllocateGlyphHash(&newHash, hashSet))
416f7df2e56Smrg        return FALSE;
417f7df2e56Smrg    if (hash->table) {
418f7df2e56Smrg        oldSize = hash->hashSet->size;
419f7df2e56Smrg        for (i = 0; i < oldSize; i++) {
420f7df2e56Smrg            glyph = hash->table[i].glyph;
421f7df2e56Smrg            if (glyph && glyph != DeletedGlyph) {
422f7df2e56Smrg                s = hash->table[i].signature;
423f7df2e56Smrg                gr = FindGlyphRef(&newHash, s, global, glyph->sha1);
424f7df2e56Smrg
425f7df2e56Smrg                gr->signature = s;
426f7df2e56Smrg                gr->glyph = glyph;
427f7df2e56Smrg                ++newHash.tableEntries;
428f7df2e56Smrg            }
429f7df2e56Smrg        }
430f7df2e56Smrg        free(hash->table);
43105b261ecSmrg    }
43205b261ecSmrg    *hash = newHash;
43305b261ecSmrg    if (global)
434f7df2e56Smrg        CheckDuplicates(hash, "ResizeGlyphHash bottom");
43505b261ecSmrg    return TRUE;
43605b261ecSmrg}
43705b261ecSmrg
43805b261ecSmrgBool
439f7df2e56SmrgResizeGlyphSet(GlyphSetPtr glyphSet, CARD32 change)
44005b261ecSmrg{
441f7df2e56Smrg    return (ResizeGlyphHash(&glyphSet->hash, change, FALSE) &&
442f7df2e56Smrg            ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], change, TRUE));
44305b261ecSmrg}
444f7df2e56Smrg
44505b261ecSmrgGlyphSetPtr
446f7df2e56SmrgAllocateGlyphSet(int fdepth, PictFormatPtr format)
44705b261ecSmrg{
448f7df2e56Smrg    GlyphSetPtr glyphSet;
449f7df2e56Smrg
450f7df2e56Smrg    if (!globalGlyphs[fdepth].hashSet) {
451f7df2e56Smrg        if (!AllocateGlyphHash(&globalGlyphs[fdepth], &glyphHashSets[0]))
452f7df2e56Smrg            return FALSE;
45305b261ecSmrg    }
45405b261ecSmrg
4554202a189Smrg    glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET);
45605b261ecSmrg    if (!glyphSet)
457f7df2e56Smrg        return FALSE;
45805b261ecSmrg
459f7df2e56Smrg    if (!AllocateGlyphHash(&glyphSet->hash, &glyphHashSets[0])) {
460f7df2e56Smrg        free(glyphSet);
461f7df2e56Smrg        return FALSE;
46205b261ecSmrg    }
46305b261ecSmrg    glyphSet->refcnt = 1;
46405b261ecSmrg    glyphSet->fdepth = fdepth;
46505b261ecSmrg    glyphSet->format = format;
466f7df2e56Smrg    return glyphSet;
46705b261ecSmrg}
46805b261ecSmrg
46905b261ecSmrgint
470f7df2e56SmrgFreeGlyphSet(void *value, XID gid)
47105b261ecSmrg{
472f7df2e56Smrg    GlyphSetPtr glyphSet = (GlyphSetPtr) value;
473f7df2e56Smrg
474f7df2e56Smrg    if (--glyphSet->refcnt == 0) {
475f7df2e56Smrg        CARD32 i, tableSize = glyphSet->hash.hashSet->size;
476f7df2e56Smrg        GlyphRefPtr table = glyphSet->hash.table;
477f7df2e56Smrg        GlyphPtr glyph;
478f7df2e56Smrg
479f7df2e56Smrg        for (i = 0; i < tableSize; i++) {
480f7df2e56Smrg            glyph = table[i].glyph;
481f7df2e56Smrg            if (glyph && glyph != DeletedGlyph)
482f7df2e56Smrg                FreeGlyph(glyph, glyphSet->fdepth);
483f7df2e56Smrg        }
484f7df2e56Smrg        if (!globalGlyphs[glyphSet->fdepth].tableEntries) {
485f7df2e56Smrg            free(globalGlyphs[glyphSet->fdepth].table);
486f7df2e56Smrg            globalGlyphs[glyphSet->fdepth].table = 0;
487f7df2e56Smrg            globalGlyphs[glyphSet->fdepth].hashSet = 0;
488f7df2e56Smrg        }
489f7df2e56Smrg        else
490f7df2e56Smrg            ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], 0, TRUE);
491f7df2e56Smrg        free(table);
492f7df2e56Smrg        dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET);
49305b261ecSmrg    }
49405b261ecSmrg    return Success;
49505b261ecSmrg}
4964642e01fSmrg
4974642e01fSmrgstatic void
498f7df2e56SmrgGlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents)
4994642e01fSmrg{
500f7df2e56Smrg    int x1, x2, y1, y2;
501f7df2e56Smrg    int n;
502f7df2e56Smrg    GlyphPtr glyph;
503f7df2e56Smrg    int x, y;
504f7df2e56Smrg
5054642e01fSmrg    x = 0;
5064642e01fSmrg    y = 0;
5074642e01fSmrg    extents->x1 = MAXSHORT;
5084642e01fSmrg    extents->x2 = MINSHORT;
5094642e01fSmrg    extents->y1 = MAXSHORT;
5104642e01fSmrg    extents->y2 = MINSHORT;
511f7df2e56Smrg    while (nlist--) {
512f7df2e56Smrg        x += list->xOff;
513f7df2e56Smrg        y += list->yOff;
514f7df2e56Smrg        n = list->len;
515f7df2e56Smrg        list++;
516f7df2e56Smrg        while (n--) {
517f7df2e56Smrg            glyph = *glyphs++;
518f7df2e56Smrg            x1 = x - glyph->info.x;
519f7df2e56Smrg            if (x1 < MINSHORT)
520f7df2e56Smrg                x1 = MINSHORT;
521f7df2e56Smrg            y1 = y - glyph->info.y;
522f7df2e56Smrg            if (y1 < MINSHORT)
523f7df2e56Smrg                y1 = MINSHORT;
524f7df2e56Smrg            x2 = x1 + glyph->info.width;
525f7df2e56Smrg            if (x2 > MAXSHORT)
526f7df2e56Smrg                x2 = MAXSHORT;
527f7df2e56Smrg            y2 = y1 + glyph->info.height;
528f7df2e56Smrg            if (y2 > MAXSHORT)
529f7df2e56Smrg                y2 = MAXSHORT;
530f7df2e56Smrg            if (x1 < extents->x1)
531f7df2e56Smrg                extents->x1 = x1;
532f7df2e56Smrg            if (x2 > extents->x2)
533f7df2e56Smrg                extents->x2 = x2;
534f7df2e56Smrg            if (y1 < extents->y1)
535f7df2e56Smrg                extents->y1 = y1;
536f7df2e56Smrg            if (y2 > extents->y2)
537f7df2e56Smrg                extents->y2 = y2;
538f7df2e56Smrg            x += glyph->info.xOff;
539f7df2e56Smrg            y += glyph->info.yOff;
540f7df2e56Smrg        }
5414642e01fSmrg    }
5424642e01fSmrg}
5434642e01fSmrg
5444642e01fSmrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
5454642e01fSmrg
5464202a189Smrgvoid
547f7df2e56SmrgCompositeGlyphs(CARD8 op,
548f7df2e56Smrg                PicturePtr pSrc,
549f7df2e56Smrg                PicturePtr pDst,
550f7df2e56Smrg                PictFormatPtr maskFormat,
551f7df2e56Smrg                INT16 xSrc,
552f7df2e56Smrg                INT16 ySrc, int nlist, GlyphListPtr lists, GlyphPtr * glyphs)
5534642e01fSmrg{
554f7df2e56Smrg    PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
5554642e01fSmrg
556f7df2e56Smrg    ValidatePicture(pSrc);
557f7df2e56Smrg    ValidatePicture(pDst);
558f7df2e56Smrg    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists,
559f7df2e56Smrg                   glyphs);
5604642e01fSmrg}
5614642e01fSmrg
5624642e01fSmrgBool
563f7df2e56SmrgmiRealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph)
5644642e01fSmrg{
5654642e01fSmrg    return TRUE;
5664642e01fSmrg}
5674642e01fSmrg
5684642e01fSmrgvoid
569f7df2e56SmrgmiUnrealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph)
5704642e01fSmrg{
5714642e01fSmrg}
5724642e01fSmrg
5734202a189Smrgvoid
574f7df2e56SmrgmiGlyphs(CARD8 op,
575f7df2e56Smrg         PicturePtr pSrc,
576f7df2e56Smrg         PicturePtr pDst,
577f7df2e56Smrg         PictFormatPtr maskFormat,
578f7df2e56Smrg         INT16 xSrc,
579f7df2e56Smrg         INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
5804642e01fSmrg{
581f7df2e56Smrg    PicturePtr pPicture;
582f7df2e56Smrg    PixmapPtr pMaskPixmap = 0;
583f7df2e56Smrg    PicturePtr pMask;
584f7df2e56Smrg    ScreenPtr pScreen = pDst->pDrawable->pScreen;
585f7df2e56Smrg    int width = 0, height = 0;
586f7df2e56Smrg    int x, y;
587f7df2e56Smrg    int xDst = list->xOff, yDst = list->yOff;
588f7df2e56Smrg    int n;
589f7df2e56Smrg    GlyphPtr glyph;
590f7df2e56Smrg    int error;
591f7df2e56Smrg    BoxRec extents = { 0, 0, 0, 0 };
592f7df2e56Smrg    CARD32 component_alpha;
593f7df2e56Smrg
594f7df2e56Smrg    if (maskFormat) {
595f7df2e56Smrg        GCPtr pGC;
596f7df2e56Smrg        xRectangle rect;
597f7df2e56Smrg
598f7df2e56Smrg        GlyphExtents(nlist, list, glyphs, &extents);
599f7df2e56Smrg
600f7df2e56Smrg        if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
601f7df2e56Smrg            return;
602f7df2e56Smrg        width = extents.x2 - extents.x1;
603f7df2e56Smrg        height = extents.y2 - extents.y1;
604f7df2e56Smrg        pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
605f7df2e56Smrg                                                maskFormat->depth,
606f7df2e56Smrg                                                CREATE_PIXMAP_USAGE_SCRATCH);
607f7df2e56Smrg        if (!pMaskPixmap)
608f7df2e56Smrg            return;
609f7df2e56Smrg        component_alpha = NeedsComponent(maskFormat->format);
610f7df2e56Smrg        pMask = CreatePicture(0, &pMaskPixmap->drawable,
611f7df2e56Smrg                              maskFormat, CPComponentAlpha, &component_alpha,
612f7df2e56Smrg                              serverClient, &error);
613f7df2e56Smrg        if (!pMask) {
614f7df2e56Smrg            (*pScreen->DestroyPixmap) (pMaskPixmap);
615f7df2e56Smrg            return;
616f7df2e56Smrg        }
617f7df2e56Smrg        pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen);
618f7df2e56Smrg        ValidateGC(&pMaskPixmap->drawable, pGC);
619f7df2e56Smrg        rect.x = 0;
620f7df2e56Smrg        rect.y = 0;
621f7df2e56Smrg        rect.width = width;
622f7df2e56Smrg        rect.height = height;
623f7df2e56Smrg        (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
624f7df2e56Smrg        FreeScratchGC(pGC);
625f7df2e56Smrg        x = -extents.x1;
626f7df2e56Smrg        y = -extents.y1;
6274642e01fSmrg    }
628f7df2e56Smrg    else {
629f7df2e56Smrg        pMask = pDst;
630f7df2e56Smrg        x = 0;
631f7df2e56Smrg        y = 0;
6324642e01fSmrg    }
633f7df2e56Smrg    while (nlist--) {
634f7df2e56Smrg        x += list->xOff;
635f7df2e56Smrg        y += list->yOff;
636f7df2e56Smrg        n = list->len;
637f7df2e56Smrg        while (n--) {
638f7df2e56Smrg            glyph = *glyphs++;
639f7df2e56Smrg            pPicture = GetGlyphPicture(glyph, pScreen);
640f7df2e56Smrg
641f7df2e56Smrg            if (pPicture) {
642f7df2e56Smrg                if (maskFormat) {
643f7df2e56Smrg                    CompositePicture(PictOpAdd,
644f7df2e56Smrg                                     pPicture,
645f7df2e56Smrg                                     None,
646f7df2e56Smrg                                     pMask,
647f7df2e56Smrg                                     0, 0,
648f7df2e56Smrg                                     0, 0,
649f7df2e56Smrg                                     x - glyph->info.x,
650f7df2e56Smrg                                     y - glyph->info.y,
651f7df2e56Smrg                                     glyph->info.width, glyph->info.height);
652f7df2e56Smrg                }
653f7df2e56Smrg                else {
654f7df2e56Smrg                    CompositePicture(op,
655f7df2e56Smrg                                     pSrc,
656f7df2e56Smrg                                     pPicture,
657f7df2e56Smrg                                     pDst,
658f7df2e56Smrg                                     xSrc + (x - glyph->info.x) - xDst,
659f7df2e56Smrg                                     ySrc + (y - glyph->info.y) - yDst,
660f7df2e56Smrg                                     0, 0,
661f7df2e56Smrg                                     x - glyph->info.x,
662f7df2e56Smrg                                     y - glyph->info.y,
663f7df2e56Smrg                                     glyph->info.width, glyph->info.height);
664f7df2e56Smrg                }
665f7df2e56Smrg            }
666f7df2e56Smrg
667f7df2e56Smrg            x += glyph->info.xOff;
668f7df2e56Smrg            y += glyph->info.yOff;
669f7df2e56Smrg        }
670f7df2e56Smrg        list++;
6714642e01fSmrg    }
672f7df2e56Smrg    if (maskFormat) {
673f7df2e56Smrg        x = extents.x1;
674f7df2e56Smrg        y = extents.y1;
675f7df2e56Smrg        CompositePicture(op,
676f7df2e56Smrg                         pSrc,
677f7df2e56Smrg                         pMask,
678f7df2e56Smrg                         pDst,
679f7df2e56Smrg                         xSrc + x - xDst,
680f7df2e56Smrg                         ySrc + y - yDst, 0, 0, x, y, width, height);
681f7df2e56Smrg        FreePicture((void *) pMask, (XID) 0);
682f7df2e56Smrg        (*pScreen->DestroyPixmap) (pMaskPixmap);
6834642e01fSmrg    }
6844642e01fSmrg}
685f7df2e56Smrg
686f7df2e56SmrgPicturePtr GetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen)
687f7df2e56Smrg{
688f7df2e56Smrg    if (pScreen->isGPU)
689f7df2e56Smrg        return NULL;
690f7df2e56Smrg    return GlyphPicture(glyph)[pScreen->myNum];
691f7df2e56Smrg}
692f7df2e56Smrg
693f7df2e56Smrgvoid SetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen, PicturePtr picture)
694f7df2e56Smrg{
695f7df2e56Smrg    GlyphPicture(glyph)[pScreen->myNum] = picture;
696f7df2e56Smrg}
697