3 * Copyright © 2000 SuSE, Inc.
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of SuSE not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission. SuSE makes no representations about the
12 * suitability of this software for any purpose. It is provided "as is"
13 * without express or implied warranty.
15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Author: Keith Packard, SuSE, Inc.
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
32 #include "scrnintstr.h"
34 #include "regionstr.h"
36 #include "windowstr.h"
39 #include "colormapst.h"
40 #include "cursorstr.h"
41 #include "dixstruct.h"
44 #include "picturestr.h"
49 * From Knuth -- a good choice for hash/rehash values is p, p-2 where
50 * p and p-2 are both prime. These tables are sized to have an extra 10%
51 * free to avoid exponential performance degradation as the hash table fills
53 static GlyphHashSetRec glyphHashSets
[] = {
63 {16384, 18043, 18041},
64 {32768, 36109, 36107},
65 {65536, 72091, 72089},
66 {131072, 144409, 144407},
67 {262144, 288361, 288359},
68 {524288, 576883, 576881},
69 {1048576, 1153459, 1153457},
70 {2097152, 2307163, 2307161},
71 {4194304, 4613893, 4613891},
72 {8388608, 9227641, 9227639},
73 {16777216, 18455029, 18455027},
74 {33554432, 36911011, 36911009},
75 {67108864, 73819861, 73819859},
76 {134217728, 147639589, 147639587},
77 {268435456, 295279081, 295279079},
78 {536870912, 590559793, 590559791}
81 #define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0]))
83 static GlyphHashRec globalGlyphs
[GlyphFormatNum
];
86 GlyphUninit(ScreenPtr pScreen
)
88 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
92 for (fdepth
= 0; fdepth
< GlyphFormatNum
; fdepth
++) {
93 if (!globalGlyphs
[fdepth
].hashSet
)
96 for (i
= 0; i
< globalGlyphs
[fdepth
].hashSet
->size
; i
++) {
97 glyph
= globalGlyphs
[fdepth
].table
[i
].glyph
;
98 if (glyph
&& glyph
!= DeletedGlyph
) {
99 if (GetGlyphPicture(glyph
, pScreen
)) {
100 FreePicture((pointer
) GetGlyphPicture(glyph
, pScreen
), 0);
101 SetGlyphPicture(glyph
, pScreen
, NULL
);
103 (*ps
->UnrealizeGlyph
) (pScreen
, glyph
);
110 FindGlyphHashSet(CARD32 filled
)
114 for (i
= 0; i
< NGLYPHHASHSETS
; i
++)
115 if (glyphHashSets
[i
].entries
>= filled
)
116 return &glyphHashSets
[i
];
121 FindGlyphRef(GlyphHashPtr hash
,
122 CARD32 signature
, Bool match
, unsigned char sha1
[20])
126 GlyphRefPtr table
, gr
, del
;
127 CARD32 tableSize
= hash
->hashSet
->size
;
130 elt
= signature
% tableSize
;
142 if (glyph
== DeletedGlyph
) {
148 else if (s
== signature
&&
149 (!match
|| memcmp(glyph
->sha1
, sha1
, 20) == 0)) {
153 step
= signature
% hash
->hashSet
->rehash
;
158 if (elt
>= tableSize
)
165 HashGlyph(xGlyphInfo
* gi
,
166 CARD8
*bits
, unsigned long size
, unsigned char sha1
[20])
168 void *ctx
= x_sha1_init();
174 success
= x_sha1_update(ctx
, gi
, sizeof(xGlyphInfo
));
177 success
= x_sha1_update(ctx
, bits
, size
);
180 success
= x_sha1_final(ctx
, sha1
);
187 FindGlyphByHash(unsigned char sha1
[20], int format
)
190 CARD32 signature
= *(CARD32
*) sha1
;
192 if (!globalGlyphs
[format
].hashSet
)
195 gr
= FindGlyphRef(&globalGlyphs
[format
], signature
, TRUE
, sha1
);
197 if (gr
->glyph
&& gr
->glyph
!= DeletedGlyph
)
203 #ifdef CHECK_DUPLICATES
205 DuplicateRef(GlyphPtr glyph
, char *where
)
207 ErrorF("Duplicate Glyph 0x%x from %s\n", glyph
, where
);
211 CheckDuplicates(GlyphHashPtr hash
, char *where
)
216 for (i
= 0; i
< hash
->hashSet
->size
; i
++) {
217 g
= hash
->table
[i
].glyph
;
218 if (!g
|| g
== DeletedGlyph
)
220 for (j
= i
+ 1; j
< hash
->hashSet
->size
; j
++)
221 if (hash
->table
[j
].glyph
== g
)
222 DuplicateRef(g
, where
);
226 #define CheckDuplicates(a,b)
227 #define DuplicateRef(a,b)
231 FreeGlyphPicture(GlyphPtr glyph
)
236 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
237 ScreenPtr pScreen
= screenInfo
.screens
[i
];
239 if (GetGlyphPicture(glyph
, pScreen
))
240 FreePicture((pointer
) GetGlyphPicture(glyph
, pScreen
), 0);
242 ps
= GetPictureScreenIfSet(pScreen
);
244 (*ps
->UnrealizeGlyph
) (pScreen
, glyph
);
249 FreeGlyph(GlyphPtr glyph
, int format
)
251 CheckDuplicates(&globalGlyphs
[format
], "FreeGlyph");
252 if (--glyph
->refcnt
== 0) {
259 for (i
= 0; i
< globalGlyphs
[format
].hashSet
->size
; i
++)
260 if (globalGlyphs
[format
].table
[i
].glyph
== glyph
) {
262 DuplicateRef(glyph
, "FreeGlyph check");
266 signature
= *(CARD32
*) glyph
->sha1
;
267 gr
= FindGlyphRef(&globalGlyphs
[format
], signature
, TRUE
, glyph
->sha1
);
268 if (gr
- globalGlyphs
[format
].table
!= first
)
269 DuplicateRef(glyph
, "Found wrong one");
270 if (gr
->glyph
&& gr
->glyph
!= DeletedGlyph
) {
271 gr
->glyph
= DeletedGlyph
;
273 globalGlyphs
[format
].tableEntries
--;
276 FreeGlyphPicture(glyph
);
277 dixFreeObjectWithPrivates(glyph
, PRIVATE_GLYPH
);
282 AddGlyph(GlyphSetPtr glyphSet
, GlyphPtr glyph
, Glyph id
)
287 CheckDuplicates(&globalGlyphs
[glyphSet
->fdepth
], "AddGlyph top global");
288 /* Locate existing matching glyph */
289 signature
= *(CARD32
*) glyph
->sha1
;
290 gr
= FindGlyphRef(&globalGlyphs
[glyphSet
->fdepth
], signature
,
292 if (gr
->glyph
&& gr
->glyph
!= DeletedGlyph
&& gr
->glyph
!= glyph
) {
293 FreeGlyphPicture(glyph
);
294 dixFreeObjectWithPrivates(glyph
, PRIVATE_GLYPH
);
297 else if (gr
->glyph
!= glyph
) {
299 gr
->signature
= signature
;
300 globalGlyphs
[glyphSet
->fdepth
].tableEntries
++;
303 /* Insert/replace glyphset value */
304 gr
= FindGlyphRef(&glyphSet
->hash
, id
, FALSE
, 0);
306 if (gr
->glyph
&& gr
->glyph
!= DeletedGlyph
)
307 FreeGlyph(gr
->glyph
, glyphSet
->fdepth
);
309 glyphSet
->hash
.tableEntries
++;
312 CheckDuplicates(&globalGlyphs
[glyphSet
->fdepth
], "AddGlyph bottom");
316 DeleteGlyph(GlyphSetPtr glyphSet
, Glyph id
)
321 gr
= FindGlyphRef(&glyphSet
->hash
, id
, FALSE
, 0);
323 if (glyph
&& glyph
!= DeletedGlyph
) {
324 gr
->glyph
= DeletedGlyph
;
325 glyphSet
->hash
.tableEntries
--;
326 FreeGlyph(glyph
, glyphSet
->fdepth
);
333 FindGlyph(GlyphSetPtr glyphSet
, Glyph id
)
337 glyph
= FindGlyphRef(&glyphSet
->hash
, id
, FALSE
, 0)->glyph
;
338 if (glyph
== DeletedGlyph
)
344 AllocateGlyph(xGlyphInfo
* gi
, int fdepth
)
352 head_size
= sizeof(GlyphRec
) + screenInfo
.numScreens
* sizeof(PicturePtr
);
353 size
= (head_size
+ dixPrivatesSize(PRIVATE_GLYPH
));
354 glyph
= (GlyphPtr
) malloc(size
);
358 glyph
->size
= size
+ sizeof(xGlyphInfo
);
360 dixInitPrivates(glyph
, (char *) glyph
+ head_size
, PRIVATE_GLYPH
);
362 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
363 ScreenPtr pScreen
= screenInfo
.screens
[i
];
364 SetGlyphPicture(glyph
, pScreen
, NULL
);
365 ps
= GetPictureScreenIfSet(pScreen
);
368 if (!(*ps
->RealizeGlyph
) (pScreen
, glyph
))
377 ps
= GetPictureScreenIfSet(screenInfo
.screens
[i
]);
379 (*ps
->UnrealizeGlyph
) (screenInfo
.screens
[i
], glyph
);
382 dixFreeObjectWithPrivates(glyph
, PRIVATE_GLYPH
);
387 AllocateGlyphHash(GlyphHashPtr hash
, GlyphHashSetPtr hashSet
)
389 hash
->table
= calloc(hashSet
->size
, sizeof(GlyphRefRec
));
392 hash
->hashSet
= hashSet
;
393 hash
->tableEntries
= 0;
398 ResizeGlyphHash(GlyphHashPtr hash
, CARD32 change
, Bool global
)
401 GlyphHashSetPtr hashSet
;
402 GlyphHashRec newHash
;
409 tableEntries
= hash
->tableEntries
+ change
;
410 hashSet
= FindGlyphHashSet(tableEntries
);
411 if (hashSet
== hash
->hashSet
)
414 CheckDuplicates(hash
, "ResizeGlyphHash top");
415 if (!AllocateGlyphHash(&newHash
, hashSet
))
418 oldSize
= hash
->hashSet
->size
;
419 for (i
= 0; i
< oldSize
; i
++) {
420 glyph
= hash
->table
[i
].glyph
;
421 if (glyph
&& glyph
!= DeletedGlyph
) {
422 s
= hash
->table
[i
].signature
;
423 gr
= FindGlyphRef(&newHash
, s
, global
, glyph
->sha1
);
427 ++newHash
.tableEntries
;
434 CheckDuplicates(hash
, "ResizeGlyphHash bottom");
439 ResizeGlyphSet(GlyphSetPtr glyphSet
, CARD32 change
)
441 return (ResizeGlyphHash(&glyphSet
->hash
, change
, FALSE
) &&
442 ResizeGlyphHash(&globalGlyphs
[glyphSet
->fdepth
], change
, TRUE
));
446 AllocateGlyphSet(int fdepth
, PictFormatPtr format
)
448 GlyphSetPtr glyphSet
;
450 if (!globalGlyphs
[fdepth
].hashSet
) {
451 if (!AllocateGlyphHash(&globalGlyphs
[fdepth
], &glyphHashSets
[0]))
455 glyphSet
= dixAllocateObjectWithPrivates(GlyphSetRec
, PRIVATE_GLYPHSET
);
459 if (!AllocateGlyphHash(&glyphSet
->hash
, &glyphHashSets
[0])) {
463 glyphSet
->refcnt
= 1;
464 glyphSet
->fdepth
= fdepth
;
465 glyphSet
->format
= format
;
470 FreeGlyphSet(pointer value
, XID gid
)
472 GlyphSetPtr glyphSet
= (GlyphSetPtr
) value
;
474 if (--glyphSet
->refcnt
== 0) {
475 CARD32 i
, tableSize
= glyphSet
->hash
.hashSet
->size
;
476 GlyphRefPtr table
= glyphSet
->hash
.table
;
479 for (i
= 0; i
< tableSize
; i
++) {
480 glyph
= table
[i
].glyph
;
481 if (glyph
&& glyph
!= DeletedGlyph
)
482 FreeGlyph(glyph
, glyphSet
->fdepth
);
484 if (!globalGlyphs
[glyphSet
->fdepth
].tableEntries
) {
485 free(globalGlyphs
[glyphSet
->fdepth
].table
);
486 globalGlyphs
[glyphSet
->fdepth
].table
= 0;
487 globalGlyphs
[glyphSet
->fdepth
].hashSet
= 0;
490 ResizeGlyphHash(&globalGlyphs
[glyphSet
->fdepth
], 0, TRUE
);
492 dixFreeObjectWithPrivates(glyphSet
, PRIVATE_GLYPHSET
);
498 GlyphExtents(int nlist
, GlyphListPtr list
, GlyphPtr
* glyphs
, BoxPtr extents
)
507 extents
->x1
= MAXSHORT
;
508 extents
->x2
= MINSHORT
;
509 extents
->y1
= MAXSHORT
;
510 extents
->y2
= MINSHORT
;
518 x1
= x
- glyph
->info
.x
;
521 y1
= y
- glyph
->info
.y
;
524 x2
= x1
+ glyph
->info
.width
;
527 y2
= y1
+ glyph
->info
.height
;
530 if (x1
< extents
->x1
)
532 if (x2
> extents
->x2
)
534 if (y1
< extents
->y1
)
536 if (y2
> extents
->y2
)
538 x
+= glyph
->info
.xOff
;
539 y
+= glyph
->info
.yOff
;
544 #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
547 CompositeGlyphs(CARD8 op
,
550 PictFormatPtr maskFormat
,
552 INT16 ySrc
, int nlist
, GlyphListPtr lists
, GlyphPtr
* glyphs
)
554 PictureScreenPtr ps
= GetPictureScreen(pDst
->pDrawable
->pScreen
);
556 ValidatePicture(pSrc
);
557 ValidatePicture(pDst
);
558 (*ps
->Glyphs
) (op
, pSrc
, pDst
, maskFormat
, xSrc
, ySrc
, nlist
, lists
,
563 miRealizeGlyph(ScreenPtr pScreen
, GlyphPtr glyph
)
569 miUnrealizeGlyph(ScreenPtr pScreen
, GlyphPtr glyph
)
577 PictFormatPtr maskFormat
,
579 INT16 ySrc
, int nlist
, GlyphListPtr list
, GlyphPtr
* glyphs
)
582 PixmapPtr pMaskPixmap
= 0;
584 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
585 int width
= 0, height
= 0;
587 int xDst
= list
->xOff
, yDst
= list
->yOff
;
591 BoxRec extents
= { 0, 0, 0, 0 };
592 CARD32 component_alpha
;
598 GlyphExtents(nlist
, list
, glyphs
, &extents
);
600 if (extents
.x2
<= extents
.x1
|| extents
.y2
<= extents
.y1
)
602 width
= extents
.x2
- extents
.x1
;
603 height
= extents
.y2
- extents
.y1
;
604 pMaskPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
,
606 CREATE_PIXMAP_USAGE_SCRATCH
);
609 component_alpha
= NeedsComponent(maskFormat
->format
);
610 pMask
= CreatePicture(0, &pMaskPixmap
->drawable
,
611 maskFormat
, CPComponentAlpha
, &component_alpha
,
612 serverClient
, &error
);
614 (*pScreen
->DestroyPixmap
) (pMaskPixmap
);
617 pGC
= GetScratchGC(pMaskPixmap
->drawable
.depth
, pScreen
);
618 ValidateGC(&pMaskPixmap
->drawable
, pGC
);
622 rect
.height
= height
;
623 (*pGC
->ops
->PolyFillRect
) (&pMaskPixmap
->drawable
, pGC
, 1, &rect
);
639 pPicture
= GetGlyphPicture(glyph
, pScreen
);
643 CompositePicture(PictOpAdd
,
651 glyph
->info
.width
, glyph
->info
.height
);
658 xSrc
+ (x
- glyph
->info
.x
) - xDst
,
659 ySrc
+ (y
- glyph
->info
.y
) - yDst
,
663 glyph
->info
.width
, glyph
->info
.height
);
667 x
+= glyph
->info
.xOff
;
668 y
+= glyph
->info
.yOff
;
680 ySrc
+ y
- yDst
, 0, 0, x
, y
, width
, height
);
681 FreePicture((pointer
) pMask
, (XID
) 0);
682 (*pScreen
->DestroyPixmap
) (pMaskPixmap
);
686 PicturePtr
GetGlyphPicture(GlyphPtr glyph
, ScreenPtr pScreen
)
690 return GlyphPicture(glyph
)[pScreen
->myNum
];
693 void SetGlyphPicture(GlyphPtr glyph
, ScreenPtr pScreen
, PicturePtr picture
)
695 GlyphPicture(glyph
)[pScreen
->myNum
] = picture
;