~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to render/glyph.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $XFree86: xc/programs/Xserver/render/glyph.c,v 1.5 2001/01/30 07:01:22 keithp Exp $
 
3
 *
 
4
 * Copyright Ā© 2000 SuSE, Inc.
 
5
 *
 
6
 * Permission to use, copy, modify, distribute, and sell this software and its
 
7
 * documentation for any purpose is hereby granted without fee, provided that
 
8
 * the above copyright notice appear in all copies and that both that
 
9
 * copyright notice and this permission notice appear in supporting
 
10
 * documentation, and that the name of SuSE not be used in advertising or
 
11
 * publicity pertaining to distribution of the software without specific,
 
12
 * written prior permission.  SuSE makes no representations about the
 
13
 * suitability of this software for any purpose.  It is provided "as is"
 
14
 * without express or implied warranty.
 
15
 *
 
16
 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
 
18
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
19
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 
20
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
 
21
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
22
 *
 
23
 * Author:  Keith Packard, SuSE, Inc.
 
24
 */
 
25
 
 
26
#ifdef HAVE_DIX_CONFIG_H
 
27
#include <dix-config.h>
 
28
#endif
 
29
 
 
30
#include "misc.h"
 
31
#include "scrnintstr.h"
 
32
#include "os.h"
 
33
#include "regionstr.h"
 
34
#include "validate.h"
 
35
#include "windowstr.h"
 
36
#include "input.h"
 
37
#include "resource.h"
 
38
#include "colormapst.h"
 
39
#include "cursorstr.h"
 
40
#include "dixstruct.h"
 
41
#include "gcstruct.h"
 
42
#include "servermd.h"
 
43
#include "picturestr.h"
 
44
#include "glyphstr.h"
 
45
 
 
46
/*
 
47
 * From Knuth -- a good choice for hash/rehash values is p, p-2 where
 
48
 * p and p-2 are both prime.  These tables are sized to have an extra 10%
 
49
 * free to avoid exponential performance degradation as the hash table fills
 
50
 */
 
51
static GlyphHashSetRec glyphHashSets[] = {
 
52
    { 32,               43,             41        },
 
53
    { 64,               73,             71        },
 
54
    { 128,              151,            149       },
 
55
    { 256,              283,            281       },
 
56
    { 512,              571,            569       },
 
57
    { 1024,             1153,           1151      },
 
58
    { 2048,             2269,           2267      },
 
59
    { 4096,             4519,           4517      },
 
60
    { 8192,             9013,           9011      },
 
61
    { 16384,            18043,          18041     },
 
62
    { 32768,            36109,          36107     },
 
63
    { 65536,            72091,          72089     },
 
64
    { 131072,           144409,         144407    },
 
65
    { 262144,           288361,         288359    },
 
66
    { 524288,           576883,         576881    },
 
67
    { 1048576,          1153459,        1153457   },
 
68
    { 2097152,          2307163,        2307161   },
 
69
    { 4194304,          4613893,        4613891   },
 
70
    { 8388608,          9227641,        9227639   },
 
71
    { 16777216,         18455029,       18455027  },
 
72
    { 33554432,         36911011,       36911009  },
 
73
    { 67108864,         73819861,       73819859  },
 
74
    { 134217728,        147639589,      147639587 },
 
75
    { 268435456,        295279081,      295279079 },
 
76
    { 536870912,        590559793,      590559791 }
 
77
};
 
78
 
 
79
#define NGLYPHHASHSETS  (sizeof(glyphHashSets)/sizeof(glyphHashSets[0]))
 
80
 
 
81
const CARD8     glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 };
 
82
 
 
83
GlyphHashRec    globalGlyphs[GlyphFormatNum];
 
84
 
 
85
int             globalTotalGlyphPrivateSize = 0;
 
86
 
 
87
static int      glyphPrivateCount = 0;
 
88
 
 
89
void
 
90
ResetGlyphPrivates ()
 
91
{
 
92
    glyphPrivateCount = 0;
 
93
}
 
94
 
 
95
int
 
96
AllocateGlyphPrivateIndex ()
 
97
{
 
98
    return glyphPrivateCount++;
 
99
}
 
100
 
 
101
Bool
 
102
AllocateGlyphPrivate (ScreenPtr pScreen,
 
103
                      int       index2,
 
104
                      unsigned  amount)
 
105
{
 
106
    PictureScreenPtr ps;
 
107
    unsigned         oldamount;
 
108
 
 
109
    ps = GetPictureScreenIfSet (pScreen);
 
110
    if (!ps)
 
111
        return FALSE;
 
112
 
 
113
    /* Round up sizes for proper alignment */
 
114
    amount = ((amount + (sizeof (DevUnion) - 1)) / sizeof (DevUnion)) *
 
115
        sizeof (DevUnion);
 
116
 
 
117
    if (index2 >= ps->glyphPrivateLen)
 
118
    {
 
119
        unsigned *nsizes;
 
120
        nsizes = (unsigned *) xrealloc (ps->glyphPrivateSizes,
 
121
                                        (index2 + 1) * sizeof (unsigned));
 
122
        if (!nsizes)
 
123
            return FALSE;
 
124
        
 
125
        while (ps->glyphPrivateLen <= index2)
 
126
        {
 
127
            nsizes[ps->glyphPrivateLen++] = 0;
 
128
            ps->totalGlyphPrivateSize += sizeof (DevUnion);
 
129
        }
 
130
        ps->glyphPrivateSizes = nsizes;
 
131
    }
 
132
    oldamount = ps->glyphPrivateSizes[index2];
 
133
    if (amount > oldamount)
 
134
    {
 
135
        ps->glyphPrivateSizes[index2] = amount;
 
136
        ps->totalGlyphPrivateSize += (amount - oldamount);
 
137
    }
 
138
    ps->totalGlyphPrivateSize = BitmapBytePad (ps->totalGlyphPrivateSize * 8);
 
139
    
 
140
    return TRUE;
 
141
}
 
142
 
 
143
static void
 
144
SetGlyphScreenPrivateOffsets (void)
 
145
{
 
146
    PictureScreenPtr ps;
 
147
    int              offset = 0;
 
148
    int              i;
 
149
 
 
150
    for (i = 0; i < screenInfo.numScreens; i++)
 
151
    {
 
152
        ps = GetPictureScreenIfSet (screenInfo.screens[i]);
 
153
        if (ps && ps->totalGlyphPrivateSize)
 
154
        {
 
155
            ps->glyphPrivateOffset = offset;
 
156
            offset += ps->totalGlyphPrivateSize / sizeof (DevUnion);
 
157
        }
 
158
    }
 
159
}
 
160
 
 
161
static void
 
162
SetGlyphPrivatePointers (GlyphPtr glyph)
 
163
{
 
164
    PictureScreenPtr ps;
 
165
    int              i;
 
166
    char             *ptr;
 
167
    DevUnion         *ppriv;
 
168
    unsigned         *sizes;
 
169
    unsigned         size;
 
170
    int              len;
 
171
 
 
172
    for (i = 0; i < screenInfo.numScreens; i++)
 
173
    {
 
174
        ps = GetPictureScreenIfSet (screenInfo.screens[i]);
 
175
        if (ps && ps->totalGlyphPrivateSize)
 
176
        {
 
177
            ppriv = glyph->devPrivates + ps->glyphPrivateOffset;
 
178
            sizes = ps->glyphPrivateSizes;
 
179
            ptr = (char *) (ppriv + ps->glyphPrivateLen);
 
180
            for (len = ps->glyphPrivateLen; --len >= 0; ppriv++, sizes++)
 
181
            {
 
182
                if ((size = *sizes) != 0)
 
183
                {
 
184
                    ppriv->ptr = (pointer) ptr;
 
185
                    ptr += size;
 
186
                }
 
187
                else
 
188
                    ppriv->ptr = (pointer) 0;
 
189
            }
 
190
        }
 
191
    }
 
192
}
 
193
 
 
194
static Bool
 
195
ReallocGlobalGlyphPrivate (GlyphPtr glyph)
 
196
{
 
197
    PictureScreenPtr ps;
 
198
    DevUnion         *devPrivates;
 
199
    char             *ptr;
 
200
    int              i;
 
201
 
 
202
    devPrivates = xalloc (globalTotalGlyphPrivateSize);
 
203
    if (!devPrivates)
 
204
        return FALSE;
 
205
 
 
206
    ptr = (char *) devPrivates;
 
207
    for (i = 0; i < screenInfo.numScreens; i++)
 
208
    {
 
209
        ps = GetPictureScreenIfSet (screenInfo.screens[i]);
 
210
        if (ps && ps->totalGlyphPrivateSize)
 
211
        {
 
212
            if (ps->glyphPrivateOffset != -1)
 
213
            {
 
214
                memcpy (ptr, glyph->devPrivates + ps->glyphPrivateOffset,
 
215
                        ps->totalGlyphPrivateSize);
 
216
            }
 
217
            else if (ps->totalGlyphPrivateSize)
 
218
            {
 
219
                memset (ptr, 0, ps->totalGlyphPrivateSize);
 
220
            }
 
221
            
 
222
            ptr += ps->totalGlyphPrivateSize;
 
223
        }
 
224
    }
 
225
 
 
226
    if (glyph->devPrivates)
 
227
        xfree (glyph->devPrivates);
 
228
    
 
229
    glyph->devPrivates = devPrivates;
 
230
 
 
231
    return TRUE;
 
232
}
 
233
 
 
234
Bool
 
235
GlyphInit (ScreenPtr pScreen)
 
236
{
 
237
    PictureScreenPtr ps = GetPictureScreen (pScreen);
 
238
    
 
239
    ps->totalGlyphPrivateSize = 0;
 
240
    ps->glyphPrivateSizes = 0;
 
241
    ps->glyphPrivateLen = 0;
 
242
    ps->glyphPrivateOffset = -1;
 
243
    
 
244
    return TRUE;
 
245
}
 
246
 
 
247
Bool
 
248
GlyphFinishInit (ScreenPtr pScreen)
 
249
{
 
250
    PictureScreenPtr ps = GetPictureScreen (pScreen);
 
251
 
 
252
    if (ps->totalGlyphPrivateSize)
 
253
    {
 
254
        GlyphPtr glyph;
 
255
        int      fdepth, i;
 
256
        
 
257
        globalTotalGlyphPrivateSize += ps->totalGlyphPrivateSize;
 
258
        
 
259
        for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
 
260
        {
 
261
            if (!globalGlyphs[fdepth].hashSet)
 
262
                continue;
 
263
                
 
264
            for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
 
265
            {
 
266
                glyph = globalGlyphs[fdepth].table[i].glyph;
 
267
                if (glyph && glyph != DeletedGlyph)
 
268
                {
 
269
                    if (!ReallocGlobalGlyphPrivate (glyph))
 
270
                        return FALSE;
 
271
                }
 
272
            }
 
273
        }
 
274
 
 
275
        SetGlyphScreenPrivateOffsets ();
 
276
 
 
277
        for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
 
278
        {
 
279
            if (!globalGlyphs[fdepth].hashSet)
 
280
                continue;
 
281
                
 
282
            for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
 
283
            {
 
284
                glyph = globalGlyphs[fdepth].table[i].glyph;
 
285
                if (glyph && glyph != DeletedGlyph)
 
286
                {
 
287
                    SetGlyphPrivatePointers (glyph);
 
288
                        
 
289
                    if (!(*ps->RealizeGlyph) (pScreen, glyph))
 
290
                        return FALSE;
 
291
                }
 
292
            }
 
293
        }
 
294
    }
 
295
    else
 
296
        ps->glyphPrivateOffset = 0;
 
297
    
 
298
    return TRUE;
 
299
}
 
300
 
 
301
void
 
302
GlyphUninit (ScreenPtr pScreen)
 
303
{
 
304
    PictureScreenPtr ps = GetPictureScreen (pScreen);
 
305
    GlyphPtr         glyph;
 
306
    int              fdepth, i;
 
307
 
 
308
    globalTotalGlyphPrivateSize -= ps->totalGlyphPrivateSize;
 
309
 
 
310
    for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
 
311
    {
 
312
        if (!globalGlyphs[fdepth].hashSet)
 
313
            continue;
 
314
        
 
315
        for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
 
316
        {
 
317
            glyph = globalGlyphs[fdepth].table[i].glyph;
 
318
            if (glyph && glyph != DeletedGlyph)
 
319
            {
 
320
                (*ps->UnrealizeGlyph) (pScreen, glyph);
 
321
                
 
322
                if (globalTotalGlyphPrivateSize)
 
323
                {
 
324
                    if (!ReallocGlobalGlyphPrivate (glyph))
 
325
                        return;
 
326
                }
 
327
                else
 
328
                {
 
329
                    if (glyph->devPrivates)
 
330
                        xfree (glyph->devPrivates);
 
331
                    glyph->devPrivates = NULL;
 
332
                }
 
333
            }
 
334
        }
 
335
    }
 
336
 
 
337
    if (globalTotalGlyphPrivateSize)
 
338
        SetGlyphScreenPrivateOffsets ();
 
339
 
 
340
    for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++)
 
341
    {
 
342
        if (!globalGlyphs[fdepth].hashSet)
 
343
            continue;
 
344
        
 
345
        for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++)
 
346
        {
 
347
            glyph = globalGlyphs[fdepth].table[i].glyph;    
 
348
            if (glyph && glyph != DeletedGlyph)
 
349
            {
 
350
                if (globalTotalGlyphPrivateSize)
 
351
                    SetGlyphPrivatePointers (glyph);
 
352
            }
 
353
        }
 
354
    }
 
355
 
 
356
    if (ps->glyphPrivateSizes)
 
357
        xfree (ps->glyphPrivateSizes);
 
358
}
 
359
 
 
360
GlyphHashSetPtr
 
361
FindGlyphHashSet (CARD32 filled)
 
362
{
 
363
    int i;
 
364
 
 
365
    for (i = 0; i < NGLYPHHASHSETS; i++)
 
366
        if (glyphHashSets[i].entries >= filled)
 
367
            return &glyphHashSets[i];
 
368
    return 0;
 
369
}
 
370
 
 
371
static int _GlyphSetPrivateAllocateIndex = 0;
 
372
 
 
373
int
 
374
AllocateGlyphSetPrivateIndex (void)
 
375
{
 
376
    return _GlyphSetPrivateAllocateIndex++;
 
377
}
 
378
 
 
379
void
 
380
ResetGlyphSetPrivateIndex (void)
 
381
{
 
382
    _GlyphSetPrivateAllocateIndex = 0;
 
383
}
 
384
 
 
385
Bool
 
386
_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr)
 
387
{
 
388
    pointer *new;
 
389
 
 
390
    if (n > glyphSet->maxPrivate) {
 
391
        if (glyphSet->devPrivates &&
 
392
            glyphSet->devPrivates != (pointer)(&glyphSet[1])) {
 
393
            new = (pointer *) xrealloc (glyphSet->devPrivates,
 
394
                                        (n + 1) * sizeof (pointer));
 
395
            if (!new)
 
396
                return FALSE;
 
397
        } else {
 
398
            new = (pointer *) xalloc ((n + 1) * sizeof (pointer));
 
399
            if (!new)
 
400
                return FALSE;
 
401
            if (glyphSet->devPrivates)
 
402
                memcpy (new,
 
403
                        glyphSet->devPrivates,
 
404
                        (glyphSet->maxPrivate + 1) * sizeof (pointer));
 
405
        }
 
406
        glyphSet->devPrivates = new;
 
407
        /* Zero out new, uninitialize privates */
 
408
        while (++glyphSet->maxPrivate < n)
 
409
            glyphSet->devPrivates[glyphSet->maxPrivate] = (pointer)0;
 
410
    }
 
411
    glyphSet->devPrivates[n] = ptr;
 
412
    return TRUE;
 
413
}
 
414
 
 
415
GlyphRefPtr
 
416
FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare)
 
417
{
 
418
    CARD32      elt, step, s;
 
419
    GlyphPtr    glyph;
 
420
    GlyphRefPtr table, gr, del;
 
421
    CARD32      tableSize = hash->hashSet->size;
 
422
 
 
423
    table = hash->table;
 
424
    elt = signature % tableSize;
 
425
    step = 0;
 
426
    del = 0;
 
427
    for (;;)
 
428
    {
 
429
        gr = &table[elt];
 
430
        s = gr->signature;
 
431
        glyph = gr->glyph;
 
432
        if (!glyph)
 
433
        {
 
434
            if (del)
 
435
                gr = del;
 
436
            break;
 
437
        }
 
438
        if (glyph == DeletedGlyph)
 
439
        {
 
440
            if (!del)
 
441
                del = gr;
 
442
            else if (gr == del)
 
443
                break;
 
444
        }
 
445
        else if (s == signature &&
 
446
                 (!match || 
 
447
                  memcmp (&compare->info, &glyph->info, compare->size) == 0))
 
448
        {
 
449
            break;
 
450
        }
 
451
        if (!step)
 
452
        {
 
453
            step = signature % hash->hashSet->rehash;
 
454
            if (!step)
 
455
                step = 1;
 
456
        }
 
457
        elt += step;
 
458
        if (elt >= tableSize)
 
459
            elt -= tableSize;
 
460
    }
 
461
    return gr;
 
462
}
 
463
 
 
464
CARD32
 
465
HashGlyph (GlyphPtr glyph)
 
466
{
 
467
    CARD32  *bits = (CARD32 *) &(glyph->info);
 
468
    CARD32  hash;
 
469
    int     n = glyph->size / sizeof (CARD32);
 
470
 
 
471
    hash = 0;
 
472
    while (n--)
 
473
        hash ^= *bits++;
 
474
    return hash;
 
475
}
 
476
 
 
477
#ifdef CHECK_DUPLICATES
 
478
void
 
479
DuplicateRef (GlyphPtr glyph, char *where)
 
480
{
 
481
    ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where);
 
482
}
 
483
 
 
484
void
 
485
CheckDuplicates (GlyphHashPtr hash, char *where)
 
486
{
 
487
    GlyphPtr    g;
 
488
    int         i, j;
 
489
 
 
490
    for (i = 0; i < hash->hashSet->size; i++)
 
491
    {
 
492
        g = hash->table[i].glyph;
 
493
        if (!g || g == DeletedGlyph)
 
494
            continue;
 
495
        for (j = i + 1; j < hash->hashSet->size; j++)
 
496
            if (hash->table[j].glyph == g)
 
497
                DuplicateRef (g, where);
 
498
    }
 
499
}
 
500
#else
 
501
#define CheckDuplicates(a,b)
 
502
#define DuplicateRef(a,b)
 
503
#endif
 
504
 
 
505
void
 
506
FreeGlyph (GlyphPtr glyph, int format)
 
507
{
 
508
    CheckDuplicates (&globalGlyphs[format], "FreeGlyph");
 
509
    if (--glyph->refcnt == 0)
 
510
    {
 
511
        PictureScreenPtr ps;
 
512
        GlyphRefPtr      gr;
 
513
        int              i;
 
514
        int              first;
 
515
 
 
516
        first = -1;
 
517
        for (i = 0; i < globalGlyphs[format].hashSet->size; i++)
 
518
            if (globalGlyphs[format].table[i].glyph == glyph)
 
519
            {
 
520
                if (first != -1)
 
521
                    DuplicateRef (glyph, "FreeGlyph check");
 
522
                first = i;
 
523
            }
 
524
 
 
525
        gr = FindGlyphRef (&globalGlyphs[format],
 
526
                           HashGlyph (glyph), TRUE, glyph);
 
527
        if (gr - globalGlyphs[format].table != first)
 
528
            DuplicateRef (glyph, "Found wrong one");
 
529
        if (gr->glyph && gr->glyph != DeletedGlyph)
 
530
        {
 
531
            gr->glyph = DeletedGlyph;
 
532
            gr->signature = 0;
 
533
            globalGlyphs[format].tableEntries--;
 
534
        }
 
535
 
 
536
        for (i = 0; i < screenInfo.numScreens; i++)
 
537
        {
 
538
            ps = GetPictureScreenIfSet (screenInfo.screens[i]);
 
539
            if (ps)
 
540
                (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
 
541
        }
 
542
        
 
543
        if (glyph->devPrivates)
 
544
            xfree (glyph->devPrivates);
 
545
        xfree (glyph);
 
546
    }
 
547
}
 
548
 
 
549
void
 
550
AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
 
551
{
 
552
    GlyphRefPtr     gr;
 
553
    CARD32          hash;
 
554
 
 
555
    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
 
556
    /* Locate existing matching glyph */
 
557
    hash = HashGlyph (glyph);
 
558
    gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph);
 
559
    if (gr->glyph && gr->glyph != DeletedGlyph)
 
560
    {
 
561
        PictureScreenPtr ps;
 
562
        int              i;
 
563
        
 
564
        for (i = 0; i < screenInfo.numScreens; i++)
 
565
        {
 
566
            ps = GetPictureScreenIfSet (screenInfo.screens[i]);
 
567
            if (ps)
 
568
                (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
 
569
        }
 
570
        if (glyph->devPrivates)
 
571
            xfree (glyph->devPrivates);
 
572
        xfree (glyph);
 
573
        glyph = gr->glyph;
 
574
    }
 
575
    else
 
576
    {
 
577
        gr->glyph = glyph;
 
578
        gr->signature = hash;
 
579
        globalGlyphs[glyphSet->fdepth].tableEntries++;
 
580
    }
 
581
    
 
582
    /* Insert/replace glyphset value */
 
583
    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
 
584
    ++glyph->refcnt;
 
585
    if (gr->glyph && gr->glyph != DeletedGlyph)
 
586
        FreeGlyph (gr->glyph, glyphSet->fdepth);
 
587
    else
 
588
        glyphSet->hash.tableEntries++;
 
589
    gr->glyph = glyph;
 
590
    gr->signature = id;
 
591
    CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
 
592
}
 
593
 
 
594
Bool
 
595
DeleteGlyph (GlyphSetPtr glyphSet, Glyph id)
 
596
{
 
597
    GlyphRefPtr     gr;
 
598
    GlyphPtr        glyph;
 
599
 
 
600
    gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
 
601
    glyph = gr->glyph;
 
602
    if (glyph && glyph != DeletedGlyph)
 
603
    {
 
604
        gr->glyph = DeletedGlyph;
 
605
        glyphSet->hash.tableEntries--;
 
606
        FreeGlyph (glyph, glyphSet->fdepth);
 
607
        return TRUE;
 
608
    }
 
609
    return FALSE;
 
610
}
 
611
 
 
612
GlyphPtr
 
613
FindGlyph (GlyphSetPtr glyphSet, Glyph id)
 
614
{
 
615
    GlyphPtr        glyph;
 
616
 
 
617
    glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph;
 
618
    if (glyph == DeletedGlyph)
 
619
        glyph = 0;
 
620
    return glyph;
 
621
}
 
622
 
 
623
GlyphPtr
 
624
AllocateGlyph (xGlyphInfo *gi, int fdepth)
 
625
{
 
626
    PictureScreenPtr ps;
 
627
    int              size;
 
628
    GlyphPtr         glyph;
 
629
    int              i;
 
630
 
 
631
    size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]);
 
632
    glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec));
 
633
    if (!glyph)
 
634
        return 0;
 
635
    glyph->refcnt = 0;
 
636
    glyph->size = size + sizeof (xGlyphInfo);
 
637
    glyph->info = *gi;
 
638
 
 
639
    if (globalTotalGlyphPrivateSize)
 
640
    {
 
641
        glyph->devPrivates = xalloc (globalTotalGlyphPrivateSize);
 
642
        if (!glyph->devPrivates)
 
643
            return 0;
 
644
 
 
645
        SetGlyphPrivatePointers (glyph);
 
646
    } else
 
647
        glyph->devPrivates = NULL;
 
648
 
 
649
    for (i = 0; i < screenInfo.numScreens; i++)
 
650
    {
 
651
        ps = GetPictureScreenIfSet (screenInfo.screens[i]);
 
652
        if (ps)
 
653
        {
 
654
            if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph))
 
655
            {
 
656
                while (i--)
 
657
                {
 
658
                    ps = GetPictureScreenIfSet (screenInfo.screens[i]);
 
659
                    if (ps)
 
660
                        (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
 
661
                }
 
662
                
 
663
                if (glyph->devPrivates)
 
664
                    xfree (glyph->devPrivates);
 
665
                xfree (glyph);
 
666
                return 0;
 
667
            }
 
668
        }
 
669
    }
 
670
    
 
671
    return glyph;
 
672
}
 
673
    
 
674
Bool
 
675
AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet)
 
676
{
 
677
    hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec));
 
678
    if (!hash->table)
 
679
        return FALSE;
 
680
    memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec));
 
681
    hash->hashSet = hashSet;
 
682
    hash->tableEntries = 0;
 
683
    return TRUE;
 
684
}
 
685
 
 
686
Bool
 
687
ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global)
 
688
{
 
689
    CARD32          tableEntries;
 
690
    GlyphHashSetPtr hashSet;
 
691
    GlyphHashRec    newHash;
 
692
    GlyphRefPtr     gr;
 
693
    GlyphPtr        glyph;
 
694
    int             i;
 
695
    int             oldSize;
 
696
    CARD32          s;
 
697
 
 
698
    tableEntries = hash->tableEntries + change;
 
699
    hashSet = FindGlyphHashSet (tableEntries);
 
700
    if (hashSet == hash->hashSet)
 
701
        return TRUE;
 
702
    if (global)
 
703
        CheckDuplicates (hash, "ResizeGlyphHash top");
 
704
    if (!AllocateGlyphHash (&newHash, hashSet))
 
705
        return FALSE;
 
706
    if (hash->table)
 
707
    {
 
708
        oldSize = hash->hashSet->size;
 
709
        for (i = 0; i < oldSize; i++)
 
710
        {
 
711
            glyph = hash->table[i].glyph;
 
712
            if (glyph && glyph != DeletedGlyph)
 
713
            {
 
714
                s = hash->table[i].signature;
 
715
                gr = FindGlyphRef (&newHash, s, global, glyph);
 
716
                gr->signature = s;
 
717
                gr->glyph = glyph;
 
718
                ++newHash.tableEntries;
 
719
            }
 
720
        }
 
721
        xfree (hash->table);
 
722
    }
 
723
    *hash = newHash;
 
724
    if (global)
 
725
        CheckDuplicates (hash, "ResizeGlyphHash bottom");
 
726
    return TRUE;
 
727
}
 
728
 
 
729
Bool
 
730
ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change)
 
731
{
 
732
    return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) &&
 
733
            ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE));
 
734
}
 
735
                            
 
736
GlyphSetPtr
 
737
AllocateGlyphSet (int fdepth, PictFormatPtr format)
 
738
{
 
739
    GlyphSetPtr glyphSet;
 
740
    int size;
 
741
    
 
742
    if (!globalGlyphs[fdepth].hashSet)
 
743
    {
 
744
        if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0]))
 
745
            return FALSE;
 
746
    }
 
747
 
 
748
    size = (sizeof (GlyphSetRec) +
 
749
            (sizeof (pointer) * _GlyphSetPrivateAllocateIndex));
 
750
    glyphSet = xalloc (size);
 
751
    if (!glyphSet)
 
752
        return FALSE;
 
753
    bzero((char *)glyphSet, size);
 
754
    glyphSet->maxPrivate = _GlyphSetPrivateAllocateIndex - 1;
 
755
    if (_GlyphSetPrivateAllocateIndex)
 
756
        glyphSet->devPrivates = (pointer)(&glyphSet[1]);
 
757
 
 
758
    if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0]))
 
759
    {
 
760
        xfree (glyphSet);
 
761
        return FALSE;
 
762
    }
 
763
    glyphSet->refcnt = 1;
 
764
    glyphSet->fdepth = fdepth;
 
765
    glyphSet->format = format;
 
766
    return glyphSet;    
 
767
}
 
768
 
 
769
int
 
770
FreeGlyphSet (pointer   value,
 
771
              XID       gid)
 
772
{
 
773
    GlyphSetPtr glyphSet = (GlyphSetPtr) value;
 
774
    
 
775
    if (--glyphSet->refcnt == 0)
 
776
    {
 
777
        CARD32      i, tableSize = glyphSet->hash.hashSet->size;
 
778
        GlyphRefPtr table = glyphSet->hash.table;
 
779
        GlyphPtr    glyph;
 
780
    
 
781
        for (i = 0; i < tableSize; i++)
 
782
        {
 
783
            glyph = table[i].glyph;
 
784
            if (glyph && glyph != DeletedGlyph)
 
785
                FreeGlyph (glyph, glyphSet->fdepth);
 
786
        }
 
787
        if (!globalGlyphs[glyphSet->fdepth].tableEntries)
 
788
        {
 
789
            xfree (globalGlyphs[glyphSet->fdepth].table);
 
790
            globalGlyphs[glyphSet->fdepth].table = 0;
 
791
            globalGlyphs[glyphSet->fdepth].hashSet = 0;
 
792
        }
 
793
        else
 
794
            ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE);
 
795
        xfree (table);
 
796
 
 
797
        if (glyphSet->devPrivates &&
 
798
            glyphSet->devPrivates != (pointer)(&glyphSet[1]))
 
799
            xfree(glyphSet->devPrivates);
 
800
 
 
801
        xfree (glyphSet);
 
802
    }
 
803
    return Success;
 
804
}