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

« back to all changes in this revision

Viewing changes to hw/xfree86/shadowfb/shadow.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
   Copyright (C) 1999.  The XFree86 Project Inc.
 
3
 
 
4
   Written by Mark Vojkovich (mvojkovi@ucsd.edu)
 
5
 
 
6
   Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan@vmware.com)
 
7
*/
 
8
 
 
9
/* $XFree86: xc/programs/Xserver/hw/xfree86/shadowfb/shadow.c,v 1.20tsi Exp $ */
 
10
 
 
11
#ifdef HAVE_XORG_CONFIG_H
 
12
#include <xorg-config.h>
 
13
#endif
 
14
 
 
15
#include <X11/X.h>
 
16
#include <X11/Xproto.h>
 
17
#include "misc.h"
 
18
#include "pixmapstr.h"
 
19
#include "input.h"
 
20
#include <X11/fonts/font.h>
 
21
#include "mi.h"
 
22
#include "scrnintstr.h"
 
23
#include "windowstr.h"
 
24
#include "gcstruct.h"
 
25
#include "dixfontstr.h"
 
26
#include <X11/fonts/fontstruct.h>
 
27
#include "xf86.h"
 
28
#include "xf86str.h"
 
29
#include "shadowfb.h"
 
30
 
 
31
#ifdef RENDER
 
32
# include "picturestr.h"
 
33
#endif
 
34
 
 
35
#define MIN(a,b) (((a)<(b))?(a):(b))
 
36
#define MAX(a,b) (((a)>(b))?(a):(b))
 
37
 
 
38
static Bool ShadowCloseScreen (int i, ScreenPtr pScreen);
 
39
static void ShadowRestoreAreas (    
 
40
    PixmapPtr pPixmap,
 
41
    RegionPtr prgn,
 
42
    int       xorg,
 
43
    int       yorg,
 
44
    WindowPtr pWin 
 
45
);
 
46
static void ShadowPaintWindow (
 
47
    WindowPtr pWin,
 
48
    RegionPtr prgn,
 
49
    int what 
 
50
);
 
51
static void ShadowCopyWindow(
 
52
    WindowPtr pWin,
 
53
    DDXPointRec ptOldOrg,
 
54
    RegionPtr prgn 
 
55
);
 
56
static Bool ShadowCreateGC(GCPtr pGC);
 
57
static Bool ShadowModifyPixmapHeader(
 
58
    PixmapPtr pPixmap,
 
59
    int width,
 
60
    int height,
 
61
    int depth,
 
62
    int bitsPerPixel,
 
63
    int devKind,
 
64
    pointer pPixData
 
65
);
 
66
 
 
67
static Bool ShadowEnterVT(int index, int flags);
 
68
static void ShadowLeaveVT(int index, int flags);
 
69
 
 
70
#ifdef RENDER
 
71
static void ShadowComposite(
 
72
    CARD8 op,
 
73
    PicturePtr pSrc,
 
74
    PicturePtr pMask,
 
75
    PicturePtr pDst,
 
76
    INT16 xSrc,
 
77
    INT16 ySrc,
 
78
    INT16 xMask,
 
79
    INT16 yMask,
 
80
    INT16 xDst,
 
81
    INT16 yDst,
 
82
    CARD16 width,
 
83
    CARD16 height
 
84
);
 
85
#endif /* RENDER */
 
86
 
 
87
 
 
88
typedef struct {
 
89
  ScrnInfoPtr                           pScrn;
 
90
  RefreshAreaFuncPtr                    preRefresh;
 
91
  RefreshAreaFuncPtr                    postRefresh;
 
92
  CloseScreenProcPtr                    CloseScreen;
 
93
  PaintWindowBackgroundProcPtr          PaintWindowBackground;
 
94
  PaintWindowBorderProcPtr              PaintWindowBorder;
 
95
  CopyWindowProcPtr                     CopyWindow;
 
96
  CreateGCProcPtr                       CreateGC;
 
97
  BackingStoreRestoreAreasProcPtr       RestoreAreas;  
 
98
  ModifyPixmapHeaderProcPtr             ModifyPixmapHeader;
 
99
#ifdef RENDER
 
100
  CompositeProcPtr Composite;
 
101
#endif /* RENDER */
 
102
  Bool                          (*EnterVT)(int, int);
 
103
  void                          (*LeaveVT)(int, int);
 
104
  Bool                          vtSema;
 
105
} ShadowScreenRec, *ShadowScreenPtr;
 
106
 
 
107
typedef struct {
 
108
   GCOps   *ops;
 
109
   GCFuncs *funcs;
 
110
} ShadowGCRec, *ShadowGCPtr;
 
111
 
 
112
 
 
113
static int ShadowScreenIndex = -1;
 
114
static int ShadowGCIndex = -1;
 
115
static unsigned long ShadowGeneration = 0;
 
116
 
 
117
#define GET_SCREEN_PRIVATE(pScreen) \
 
118
        (ShadowScreenPtr)((pScreen)->devPrivates[ShadowScreenIndex].ptr)
 
119
#define GET_GC_PRIVATE(pGC) \
 
120
        (ShadowGCPtr)((pGC)->devPrivates[ShadowGCIndex].ptr)
 
121
 
 
122
#define SHADOW_GC_FUNC_PROLOGUE(pGC)\
 
123
    ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\
 
124
    (pGC)->funcs = pGCPriv->funcs;\
 
125
    if(pGCPriv->ops)\
 
126
        (pGC)->ops = pGCPriv->ops
 
127
 
 
128
#define SHADOW_GC_FUNC_EPILOGUE(pGC)\
 
129
    pGCPriv->funcs = (pGC)->funcs;\
 
130
    (pGC)->funcs = &ShadowGCFuncs;\
 
131
    if(pGCPriv->ops) {\
 
132
        pGCPriv->ops = (pGC)->ops;\
 
133
        (pGC)->ops = &ShadowGCOps;\
 
134
    }
 
135
 
 
136
#define SHADOW_GC_OP_PROLOGUE(pGC)\
 
137
    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pGC->pScreen); \
 
138
    ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\
 
139
    GCFuncs *oldFuncs = pGC->funcs;\
 
140
    pGC->funcs = pGCPriv->funcs;\
 
141
    pGC->ops = pGCPriv->ops
 
142
 
 
143
    
 
144
#define SHADOW_GC_OP_EPILOGUE(pGC)\
 
145
    pGCPriv->ops = pGC->ops;\
 
146
    pGC->funcs = oldFuncs;\
 
147
    pGC->ops   = &ShadowGCOps
 
148
 
 
149
#define IS_VISIBLE(pWin) (pPriv->vtSema && \
 
150
    (((WindowPtr)pWin)->visibility != VisibilityFullyObscured))
 
151
 
 
152
#define TRIM_BOX(box, pGC) { \
 
153
    BoxPtr extents = &pGC->pCompositeClip->extents;\
 
154
    if(box.x1 < extents->x1) box.x1 = extents->x1; \
 
155
    if(box.x2 > extents->x2) box.x2 = extents->x2; \
 
156
    if(box.y1 < extents->y1) box.y1 = extents->y1; \
 
157
    if(box.y2 > extents->y2) box.y2 = extents->y2; \
 
158
    }
 
159
 
 
160
#define TRANSLATE_BOX(box, pDraw) { \
 
161
    box.x1 += pDraw->x; \
 
162
    box.x2 += pDraw->x; \
 
163
    box.y1 += pDraw->y; \
 
164
    box.y2 += pDraw->y; \
 
165
    }
 
166
 
 
167
#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
 
168
    TRANSLATE_BOX(box, pDraw); \
 
169
    TRIM_BOX(box, pGC); \
 
170
    }
 
171
 
 
172
#define BOX_NOT_EMPTY(box) \
 
173
    (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
 
174
 
 
175
 
 
176
 
 
177
Bool
 
178
ShadowFBInit2 (
 
179
    ScreenPtr           pScreen,
 
180
    RefreshAreaFuncPtr  preRefreshArea,
 
181
    RefreshAreaFuncPtr  postRefreshArea
 
182
){
 
183
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 
184
    ShadowScreenPtr pPriv;
 
185
#ifdef RENDER
 
186
    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
 
187
#endif /* RENDER */
 
188
 
 
189
    if(!preRefreshArea && !postRefreshArea) return FALSE;
 
190
    
 
191
    if (ShadowGeneration != serverGeneration) {
 
192
        if(((ShadowScreenIndex = AllocateScreenPrivateIndex ()) < 0) ||
 
193
           ((ShadowGCIndex = AllocateGCPrivateIndex()) < 0))
 
194
            return FALSE;
 
195
        ShadowGeneration = serverGeneration;
 
196
    }
 
197
 
 
198
    if(!AllocateGCPrivate(pScreen, ShadowGCIndex, sizeof(ShadowGCRec)))
 
199
        return FALSE;
 
200
 
 
201
    if(!(pPriv = (ShadowScreenPtr)xalloc(sizeof(ShadowScreenRec))))
 
202
        return FALSE;
 
203
 
 
204
    pScreen->devPrivates[ShadowScreenIndex].ptr = (pointer)pPriv;  
 
205
 
 
206
    pPriv->pScrn = pScrn;
 
207
    pPriv->preRefresh = preRefreshArea;
 
208
    pPriv->postRefresh = postRefreshArea;
 
209
    pPriv->vtSema = TRUE;
 
210
 
 
211
    pPriv->CloseScreen = pScreen->CloseScreen;
 
212
    pPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
 
213
    pPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
 
214
    pPriv->CopyWindow = pScreen->CopyWindow;
 
215
    pPriv->CreateGC = pScreen->CreateGC;
 
216
    pPriv->RestoreAreas = pScreen->BackingStoreFuncs.RestoreAreas;
 
217
    pPriv->ModifyPixmapHeader = pScreen->ModifyPixmapHeader;
 
218
 
 
219
    pPriv->EnterVT = pScrn->EnterVT;
 
220
    pPriv->LeaveVT = pScrn->LeaveVT;
 
221
 
 
222
    pScreen->CloseScreen = ShadowCloseScreen;
 
223
    pScreen->PaintWindowBackground = ShadowPaintWindow;
 
224
    pScreen->PaintWindowBorder = ShadowPaintWindow;
 
225
    pScreen->CopyWindow = ShadowCopyWindow;
 
226
    pScreen->CreateGC = ShadowCreateGC;
 
227
    pScreen->BackingStoreFuncs.RestoreAreas = ShadowRestoreAreas;
 
228
    pScreen->ModifyPixmapHeader = ShadowModifyPixmapHeader;
 
229
 
 
230
    pScrn->EnterVT = ShadowEnterVT;
 
231
    pScrn->LeaveVT = ShadowLeaveVT;
 
232
 
 
233
#ifdef RENDER
 
234
    if(ps) {
 
235
      pPriv->Composite = ps->Composite;
 
236
      ps->Composite = ShadowComposite;
 
237
    }
 
238
#endif /* RENDER */
 
239
 
 
240
    return TRUE;
 
241
}
 
242
 
 
243
Bool
 
244
ShadowFBInit (
 
245
    ScreenPtr           pScreen,
 
246
    RefreshAreaFuncPtr  refreshArea
 
247
){
 
248
    return ShadowFBInit2(pScreen, NULL, refreshArea);
 
249
}
 
250
 
 
251
/**********************************************************/
 
252
 
 
253
static Bool
 
254
ShadowEnterVT(int index, int flags)
 
255
{
 
256
    ScrnInfoPtr pScrn = xf86Screens[index];
 
257
    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScrn->pScreen);
 
258
 
 
259
    if((*pPriv->EnterVT)(index, flags)) {
 
260
        pPriv->vtSema = TRUE;
 
261
        return TRUE;
 
262
    }
 
263
 
 
264
    return FALSE;
 
265
}
 
266
 
 
267
static void
 
268
ShadowLeaveVT(int index, int flags)
 
269
{
 
270
    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(xf86Screens[index]->pScreen);
 
271
 
 
272
    pPriv->vtSema = FALSE;
 
273
 
 
274
    (*pPriv->LeaveVT)(index, flags);
 
275
}
 
276
 
 
277
/**********************************************************/
 
278
 
 
279
 
 
280
static Bool
 
281
ShadowCloseScreen (int i, ScreenPtr pScreen)
 
282
{
 
283
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 
284
    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
 
285
#ifdef RENDER
 
286
    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
 
287
#endif /* RENDER */
 
288
 
 
289
    pScreen->CloseScreen = pPriv->CloseScreen;
 
290
    pScreen->PaintWindowBackground = pPriv->PaintWindowBackground;
 
291
    pScreen->PaintWindowBorder = pPriv->PaintWindowBorder;
 
292
    pScreen->CopyWindow = pPriv->CopyWindow;
 
293
    pScreen->CreateGC = pPriv->CreateGC;
 
294
    pScreen->BackingStoreFuncs.RestoreAreas = pPriv->RestoreAreas;
 
295
    pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader;
 
296
 
 
297
    pScrn->EnterVT = pPriv->EnterVT;
 
298
    pScrn->LeaveVT = pPriv->LeaveVT;
 
299
 
 
300
#ifdef RENDER
 
301
    if(ps) {
 
302
        ps->Composite = pPriv->Composite;
 
303
    }
 
304
#endif /* RENDER */
 
305
 
 
306
    xfree((pointer)pPriv);
 
307
 
 
308
    return (*pScreen->CloseScreen) (i, pScreen);
 
309
}
 
310
 
 
311
 
 
312
static void
 
313
ShadowRestoreAreas (    
 
314
    PixmapPtr pPixmap,
 
315
    RegionPtr prgn,
 
316
    int       xorg,
 
317
    int       yorg,
 
318
    WindowPtr pWin 
 
319
){
 
320
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
321
    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
 
322
    int num = 0;
 
323
 
 
324
    if(pPriv->vtSema && (num = REGION_NUM_RECTS(prgn)))
 
325
        if(pPriv->preRefresh)
 
326
            (*pPriv->preRefresh)(pPriv->pScrn, num, REGION_RECTS(prgn));
 
327
 
 
328
    pScreen->BackingStoreFuncs.RestoreAreas = pPriv->RestoreAreas;
 
329
    (*pScreen->BackingStoreFuncs.RestoreAreas) (
 
330
                pPixmap, prgn, xorg, yorg, pWin);
 
331
    pScreen->BackingStoreFuncs.RestoreAreas = ShadowRestoreAreas;
 
332
 
 
333
    if(num && pPriv->postRefresh)
 
334
        (*pPriv->postRefresh)(pPriv->pScrn, num, REGION_RECTS(prgn));
 
335
}
 
336
 
 
337
 
 
338
static void
 
339
ShadowPaintWindow(
 
340
  WindowPtr pWin,
 
341
  RegionPtr prgn,
 
342
  int what 
 
343
){
 
344
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
345
    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
 
346
    int num = 0;
 
347
 
 
348
    if(pPriv->vtSema && (num = REGION_NUM_RECTS(prgn)))
 
349
        if(pPriv->preRefresh)
 
350
            (*pPriv->preRefresh)(pPriv->pScrn, num, REGION_RECTS(prgn));
 
351
 
 
352
    if(what == PW_BACKGROUND) {
 
353
        pScreen->PaintWindowBackground = pPriv->PaintWindowBackground;
 
354
        (*pScreen->PaintWindowBackground) (pWin, prgn, what);
 
355
        pScreen->PaintWindowBackground = ShadowPaintWindow;
 
356
    } else {
 
357
        pScreen->PaintWindowBorder = pPriv->PaintWindowBorder;
 
358
        (*pScreen->PaintWindowBorder) (pWin, prgn, what);
 
359
        pScreen->PaintWindowBorder = ShadowPaintWindow;
 
360
    }
 
361
 
 
362
    if(num && pPriv->postRefresh)
 
363
        (*pPriv->postRefresh)(pPriv->pScrn, num, REGION_RECTS(prgn));    
 
364
}
 
365
 
 
366
 
 
367
static void 
 
368
ShadowCopyWindow(
 
369
   WindowPtr pWin,
 
370
   DDXPointRec ptOldOrg,
 
371
   RegionPtr prgn 
 
372
){
 
373
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
374
    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
 
375
    int num = 0;
 
376
    RegionRec rgnDst;
 
377
 
 
378
    if (pPriv->vtSema) {
 
379
        REGION_NULL(pWin->drawable.pScreen, &rgnDst);
 
380
        REGION_COPY(pWin->drawable.pScreen, &rgnDst, prgn);
 
381
        
 
382
        REGION_TRANSLATE(pWin->drawable.pScreen, &rgnDst,
 
383
                         pWin->drawable.x - ptOldOrg.x,
 
384
                         pWin->drawable.y - ptOldOrg.y);
 
385
        REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, &rgnDst);
 
386
        if ((num = REGION_NUM_RECTS(&rgnDst))) {
 
387
            if(pPriv->preRefresh)
 
388
                (*pPriv->preRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst));
 
389
        } else {
 
390
            REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
 
391
        }
 
392
    }
 
393
    
 
394
    pScreen->CopyWindow = pPriv->CopyWindow;
 
395
    (*pScreen->CopyWindow) (pWin, ptOldOrg, prgn);
 
396
    pScreen->CopyWindow = ShadowCopyWindow;
 
397
    
 
398
    if (num) {
 
399
        if (pPriv->postRefresh)
 
400
            (*pPriv->postRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst));
 
401
        REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
 
402
    }
 
403
}
 
404
 
 
405
static Bool
 
406
ShadowModifyPixmapHeader(
 
407
    PixmapPtr pPixmap,
 
408
    int width,
 
409
    int height,
 
410
    int depth,
 
411
    int bitsPerPixel,
 
412
    int devKind,
 
413
    pointer pPixData
 
414
)
 
415
{
 
416
    ScreenPtr pScreen;
 
417
    ScrnInfoPtr pScrn;
 
418
    ShadowScreenPtr pPriv;
 
419
    Bool retval;
 
420
    PixmapPtr pScreenPix;
 
421
 
 
422
    if (!pPixmap)
 
423
        return FALSE;
 
424
 
 
425
    pScreen = pPixmap->drawable.pScreen;
 
426
    pScrn = xf86Screens[pScreen->myNum];
 
427
 
 
428
    pScreenPix = (*pScreen->GetScreenPixmap)(pScreen);
 
429
    
 
430
    if (pPixmap == pScreenPix && !pScrn->vtSema)
 
431
        pScreenPix->devPrivate = pScrn->pixmapPrivate;
 
432
    
 
433
    pPriv = GET_SCREEN_PRIVATE(pScreen);
 
434
 
 
435
    pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader;
 
436
    retval = (*pScreen->ModifyPixmapHeader)(pPixmap,
 
437
        width, height, depth, bitsPerPixel, devKind, pPixData);
 
438
    pScreen->ModifyPixmapHeader = ShadowModifyPixmapHeader;
 
439
 
 
440
    if (pPixmap == pScreenPix && !pScrn->vtSema)
 
441
    {
 
442
        pScrn->pixmapPrivate = pScreenPix->devPrivate;
 
443
        pScreenPix->devPrivate.ptr = 0;
 
444
    }
 
445
    return retval;
 
446
}
 
447
 
 
448
#ifdef RENDER
 
449
static void
 
450
ShadowComposite(
 
451
    CARD8 op,
 
452
    PicturePtr pSrc,
 
453
    PicturePtr pMask,
 
454
    PicturePtr pDst,
 
455
    INT16 xSrc,
 
456
    INT16 ySrc,
 
457
    INT16 xMask,
 
458
    INT16 yMask,
 
459
    INT16 xDst,
 
460
    INT16 yDst,
 
461
    CARD16 width,
 
462
    CARD16 height
 
463
){
 
464
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
 
465
    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
 
466
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 
467
    BoxRec box;
 
468
    BoxPtr extents;
 
469
    Bool boxNotEmpty = FALSE;
 
470
 
 
471
    if (pPriv->vtSema
 
472
        && pDst->pDrawable->type == DRAWABLE_WINDOW) {
 
473
 
 
474
        box.x1 = pDst->pDrawable->x + xDst;
 
475
        box.y1 = pDst->pDrawable->y + yDst;
 
476
        box.x2 = box.x1 + width;
 
477
        box.y2 = box.y1 + height;
 
478
 
 
479
        extents = &pDst->pCompositeClip->extents;
 
480
        if(box.x1 < extents->x1) box.x1 = extents->x1;
 
481
        if(box.x2 > extents->x2) box.x2 = extents->x2;
 
482
        if(box.y1 < extents->y1) box.y1 = extents->y1;
 
483
        if(box.y2 > extents->y2) box.y2 = extents->y2;
 
484
        
 
485
        if (BOX_NOT_EMPTY(box)) {
 
486
            if (pPriv->preRefresh)
 
487
                (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
488
            boxNotEmpty = TRUE;
 
489
        }
 
490
    }
 
491
    
 
492
    ps->Composite = pPriv->Composite;
 
493
    (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
 
494
                     xMask, yMask, xDst, yDst, width, height);
 
495
    ps->Composite = ShadowComposite;
 
496
 
 
497
    if (pPriv->postRefresh && boxNotEmpty) {
 
498
        (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
499
    }
 
500
}
 
501
#endif /* RENDER */
 
502
 
 
503
/**********************************************************/
 
504
 
 
505
static void ShadowValidateGC(GCPtr, unsigned long, DrawablePtr);
 
506
static void ShadowChangeGC(GCPtr, unsigned long);
 
507
static void ShadowCopyGC(GCPtr, unsigned long, GCPtr);
 
508
static void ShadowDestroyGC(GCPtr);
 
509
static void ShadowChangeClip(GCPtr, int, pointer, int);
 
510
static void ShadowDestroyClip(GCPtr);
 
511
static void ShadowCopyClip(GCPtr, GCPtr);
 
512
 
 
513
GCFuncs ShadowGCFuncs = {
 
514
    ShadowValidateGC, ShadowChangeGC, ShadowCopyGC, ShadowDestroyGC,
 
515
    ShadowChangeClip, ShadowDestroyClip, ShadowCopyClip
 
516
};
 
517
 
 
518
 
 
519
extern GCOps ShadowGCOps;
 
520
 
 
521
static Bool
 
522
ShadowCreateGC(GCPtr pGC)
 
523
{
 
524
    ScreenPtr pScreen = pGC->pScreen;
 
525
    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
 
526
    ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);
 
527
    Bool ret;
 
528
   
 
529
    pScreen->CreateGC = pPriv->CreateGC;
 
530
    if((ret = (*pScreen->CreateGC) (pGC))) {
 
531
        pGCPriv->ops = NULL;
 
532
        pGCPriv->funcs = pGC->funcs;
 
533
        pGC->funcs = &ShadowGCFuncs;
 
534
    }
 
535
    pScreen->CreateGC = ShadowCreateGC;
 
536
 
 
537
    return ret;
 
538
}
 
539
 
 
540
 
 
541
static void
 
542
ShadowValidateGC(
 
543
   GCPtr         pGC,
 
544
   unsigned long changes,
 
545
   DrawablePtr   pDraw 
 
546
){
 
547
    SHADOW_GC_FUNC_PROLOGUE (pGC);
 
548
    (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
 
549
    if(pDraw->type == DRAWABLE_WINDOW)
 
550
        pGCPriv->ops = pGC->ops;  /* just so it's not NULL */
 
551
    else 
 
552
        pGCPriv->ops = NULL;
 
553
    SHADOW_GC_FUNC_EPILOGUE (pGC);
 
554
}
 
555
 
 
556
 
 
557
static void
 
558
ShadowDestroyGC(GCPtr pGC)
 
559
{
 
560
    SHADOW_GC_FUNC_PROLOGUE (pGC);
 
561
    (*pGC->funcs->DestroyGC)(pGC);
 
562
    SHADOW_GC_FUNC_EPILOGUE (pGC);
 
563
}
 
564
 
 
565
static void
 
566
ShadowChangeGC (
 
567
    GCPtr           pGC,
 
568
    unsigned long   mask
 
569
){
 
570
    SHADOW_GC_FUNC_PROLOGUE (pGC);
 
571
    (*pGC->funcs->ChangeGC) (pGC, mask);
 
572
    SHADOW_GC_FUNC_EPILOGUE (pGC);
 
573
}
 
574
 
 
575
static void
 
576
ShadowCopyGC (
 
577
    GCPtr           pGCSrc, 
 
578
    unsigned long   mask,
 
579
    GCPtr           pGCDst
 
580
){
 
581
    SHADOW_GC_FUNC_PROLOGUE (pGCDst);
 
582
    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
 
583
    SHADOW_GC_FUNC_EPILOGUE (pGCDst);
 
584
}
 
585
 
 
586
static void
 
587
ShadowChangeClip (
 
588
    GCPtr   pGC,
 
589
    int         type,
 
590
    pointer     pvalue,
 
591
    int         nrects 
 
592
){
 
593
    SHADOW_GC_FUNC_PROLOGUE (pGC);
 
594
    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
 
595
    SHADOW_GC_FUNC_EPILOGUE (pGC);
 
596
}
 
597
 
 
598
static void
 
599
ShadowCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
 
600
{
 
601
    SHADOW_GC_FUNC_PROLOGUE (pgcDst);
 
602
    (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
 
603
    SHADOW_GC_FUNC_EPILOGUE (pgcDst);
 
604
}
 
605
 
 
606
static void
 
607
ShadowDestroyClip(GCPtr pGC)
 
608
{
 
609
    SHADOW_GC_FUNC_PROLOGUE (pGC);
 
610
    (* pGC->funcs->DestroyClip)(pGC);
 
611
    SHADOW_GC_FUNC_EPILOGUE (pGC);
 
612
}
 
613
 
 
614
 
 
615
 
 
616
 
 
617
/**********************************************************/
 
618
 
 
619
 
 
620
static void
 
621
ShadowFillSpans(
 
622
    DrawablePtr pDraw,
 
623
    GC          *pGC,
 
624
    int         nInit,  
 
625
    DDXPointPtr pptInit,        
 
626
    int         *pwidthInit,            
 
627
    int         fSorted 
 
628
){
 
629
    SHADOW_GC_OP_PROLOGUE(pGC);    
 
630
 
 
631
    if(IS_VISIBLE(pDraw) && nInit) {
 
632
        DDXPointPtr ppt = pptInit;
 
633
        int *pwidth = pwidthInit;
 
634
        int i = nInit;
 
635
        BoxRec box;
 
636
        Bool boxNotEmpty = FALSE;
 
637
 
 
638
        box.x1 = ppt->x;
 
639
        box.x2 = box.x1 + *pwidth;
 
640
        box.y2 = box.y1 = ppt->y;
 
641
 
 
642
        while(--i) {
 
643
           ppt++;
 
644
           pwidth++;
 
645
           if(box.x1 > ppt->x) box.x1 = ppt->x;
 
646
           if(box.x2 < (ppt->x + *pwidth)) 
 
647
                box.x2 = ppt->x + *pwidth;
 
648
           if(box.y1 > ppt->y) box.y1 = ppt->y;
 
649
           else if(box.y2 < ppt->y) box.y2 = ppt->y;
 
650
        }
 
651
 
 
652
        box.y2++;
 
653
 
 
654
        if(!pGC->miTranslate) {
 
655
           TRANSLATE_BOX(box, pDraw);
 
656
        }
 
657
        TRIM_BOX(box, pGC); 
 
658
 
 
659
        if(BOX_NOT_EMPTY(box)) {
 
660
            if(pPriv->preRefresh)
 
661
                (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
662
            boxNotEmpty = TRUE;
 
663
        }
 
664
 
 
665
        (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
 
666
 
 
667
        if(boxNotEmpty && pPriv->postRefresh)
 
668
           (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
669
    } else
 
670
        (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
 
671
 
 
672
    SHADOW_GC_OP_EPILOGUE(pGC);
 
673
}
 
674
 
 
675
static void
 
676
ShadowSetSpans(
 
677
    DrawablePtr         pDraw,
 
678
    GCPtr               pGC,
 
679
    char                *pcharsrc,
 
680
    DDXPointPtr         pptInit,
 
681
    int                 *pwidthInit,
 
682
    int                 nspans,
 
683
    int                 fSorted 
 
684
){
 
685
    SHADOW_GC_OP_PROLOGUE(pGC);
 
686
 
 
687
    if(IS_VISIBLE(pDraw) && nspans) {
 
688
        DDXPointPtr ppt = pptInit;
 
689
        int *pwidth = pwidthInit;
 
690
        int i = nspans;
 
691
        BoxRec box;
 
692
        Bool boxNotEmpty = FALSE;
 
693
 
 
694
        box.x1 = ppt->x;
 
695
        box.x2 = box.x1 + *pwidth;
 
696
        box.y2 = box.y1 = ppt->y;
 
697
 
 
698
        while(--i) {
 
699
           ppt++;
 
700
           pwidth++;
 
701
           if(box.x1 > ppt->x) box.x1 = ppt->x;
 
702
           if(box.x2 < (ppt->x + *pwidth)) 
 
703
                box.x2 = ppt->x + *pwidth;
 
704
           if(box.y1 > ppt->y) box.y1 = ppt->y;
 
705
           else if(box.y2 < ppt->y) box.y2 = ppt->y;
 
706
        }
 
707
 
 
708
        box.y2++;
 
709
 
 
710
        if(!pGC->miTranslate) {
 
711
           TRANSLATE_BOX(box, pDraw);
 
712
        }
 
713
        TRIM_BOX(box, pGC);
 
714
 
 
715
        if(BOX_NOT_EMPTY(box)) {
 
716
           if(pPriv->preRefresh)
 
717
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
718
           boxNotEmpty = TRUE;
 
719
        }
 
720
 
 
721
        (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, 
 
722
                                pwidthInit, nspans, fSorted);
 
723
 
 
724
        if(boxNotEmpty && pPriv->postRefresh)
 
725
           (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
726
    } else
 
727
        (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, 
 
728
                                pwidthInit, nspans, fSorted);
 
729
 
 
730
    SHADOW_GC_OP_EPILOGUE(pGC);
 
731
}
 
732
 
 
733
static void
 
734
ShadowPutImage(
 
735
    DrawablePtr pDraw,
 
736
    GCPtr       pGC,
 
737
    int         depth, 
 
738
    int x, int y, int w, int h,
 
739
    int         leftPad,
 
740
    int         format,
 
741
    char        *pImage 
 
742
){
 
743
    BoxRec box;
 
744
    Bool boxNotEmpty = FALSE;
 
745
    
 
746
    SHADOW_GC_OP_PROLOGUE(pGC);
 
747
 
 
748
    if(IS_VISIBLE(pDraw)) {
 
749
        box.x1 = x + pDraw->x;
 
750
        box.x2 = box.x1 + w;
 
751
        box.y1 = y + pDraw->y;
 
752
        box.y2 = box.y1 + h;
 
753
 
 
754
        TRIM_BOX(box, pGC);
 
755
        if(BOX_NOT_EMPTY(box)) {
 
756
           if(pPriv->preRefresh)
 
757
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
758
           boxNotEmpty = TRUE;
 
759
        }
 
760
    }
 
761
 
 
762
    (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, 
 
763
                leftPad, format, pImage);
 
764
                
 
765
    if(boxNotEmpty && pPriv->postRefresh)
 
766
        (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
767
    
 
768
    SHADOW_GC_OP_EPILOGUE(pGC);
 
769
 
 
770
}
 
771
 
 
772
static RegionPtr
 
773
ShadowCopyArea(
 
774
    DrawablePtr pSrc,
 
775
    DrawablePtr pDst,
 
776
    GC *pGC,
 
777
    int srcx, int srcy,
 
778
    int width, int height,
 
779
    int dstx, int dsty 
 
780
){
 
781
    RegionPtr ret;
 
782
    BoxRec box;
 
783
    Bool boxNotEmpty = FALSE;
 
784
    
 
785
    SHADOW_GC_OP_PROLOGUE(pGC);
 
786
 
 
787
    if(IS_VISIBLE(pDst)) {
 
788
        box.x1 = dstx + pDst->x;
 
789
        box.x2 = box.x1 + width;
 
790
        box.y1 = dsty + pDst->y;
 
791
        box.y2 = box.y1 + height;
 
792
 
 
793
        TRIM_BOX(box, pGC);
 
794
        if(BOX_NOT_EMPTY(box)) {
 
795
           if(pPriv->preRefresh)
 
796
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
797
           boxNotEmpty = TRUE;
 
798
        }
 
799
    }
 
800
    
 
801
    ret = (*pGC->ops->CopyArea)(pSrc, pDst,
 
802
            pGC, srcx, srcy, width, height, dstx, dsty);
 
803
 
 
804
    if(boxNotEmpty && pPriv->postRefresh)
 
805
        (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
806
    
 
807
    SHADOW_GC_OP_EPILOGUE(pGC);
 
808
 
 
809
    return ret;
 
810
}
 
811
 
 
812
static RegionPtr
 
813
ShadowCopyPlane(
 
814
    DrawablePtr pSrc,
 
815
    DrawablePtr pDst,
 
816
    GCPtr pGC,
 
817
    int srcx, int srcy,
 
818
    int width, int height,
 
819
    int dstx, int dsty,
 
820
    unsigned long bitPlane 
 
821
){
 
822
    RegionPtr ret;
 
823
    BoxRec box;
 
824
    Bool boxNotEmpty = FALSE;
 
825
    
 
826
    SHADOW_GC_OP_PROLOGUE(pGC);
 
827
 
 
828
    if(IS_VISIBLE(pDst)) {
 
829
        box.x1 = dstx + pDst->x;
 
830
        box.x2 = box.x1 + width;
 
831
        box.y1 = dsty + pDst->y;
 
832
        box.y2 = box.y1 + height;
 
833
 
 
834
        TRIM_BOX(box, pGC);
 
835
        if(BOX_NOT_EMPTY(box)) {
 
836
           if(pPriv->preRefresh)
 
837
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
838
           boxNotEmpty = TRUE;
 
839
        }
 
840
    }
 
841
    
 
842
    ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
 
843
               pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
 
844
    
 
845
    if(boxNotEmpty && pPriv->postRefresh)
 
846
        (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
847
    
 
848
    SHADOW_GC_OP_EPILOGUE(pGC);
 
849
 
 
850
    return ret;
 
851
}
 
852
 
 
853
static void
 
854
ShadowPolyPoint(
 
855
    DrawablePtr pDraw,
 
856
    GCPtr pGC,
 
857
    int mode,
 
858
    int nptInit,
 
859
    xPoint *pptInit 
 
860
){
 
861
    BoxRec box;
 
862
    Bool boxNotEmpty = FALSE;
 
863
    
 
864
    SHADOW_GC_OP_PROLOGUE(pGC);
 
865
 
 
866
    if(IS_VISIBLE(pDraw) && nptInit) {
 
867
        xPoint *ppt = pptInit;
 
868
        int npt = nptInit;
 
869
 
 
870
        box.x2 = box.x1 = pptInit->x;
 
871
        box.y2 = box.y1 = pptInit->y;
 
872
 
 
873
        /* this could be slow if the points were spread out */
 
874
 
 
875
        while(--npt) {
 
876
           ppt++;
 
877
           if(box.x1 > ppt->x) box.x1 = ppt->x;
 
878
           else if(box.x2 < ppt->x) box.x2 = ppt->x;
 
879
           if(box.y1 > ppt->y) box.y1 = ppt->y;
 
880
           else if(box.y2 < ppt->y) box.y2 = ppt->y;
 
881
        }
 
882
 
 
883
        box.x2++;
 
884
        box.y2++;
 
885
 
 
886
        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 
887
        if(BOX_NOT_EMPTY(box)) {
 
888
           if(pPriv->preRefresh)
 
889
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
890
           boxNotEmpty = TRUE;
 
891
        }
 
892
    }
 
893
    
 
894
    (*pGC->ops->PolyPoint)(pDraw, pGC, mode, nptInit, pptInit);
 
895
    
 
896
    if(boxNotEmpty && pPriv->postRefresh)
 
897
        (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
898
 
 
899
    SHADOW_GC_OP_EPILOGUE(pGC);
 
900
}
 
901
 
 
902
static void
 
903
ShadowPolylines(
 
904
    DrawablePtr pDraw,
 
905
    GCPtr       pGC,
 
906
    int         mode,           
 
907
    int         nptInit,                
 
908
    DDXPointPtr pptInit 
 
909
){
 
910
    BoxRec box;
 
911
    Bool boxNotEmpty = FALSE;
 
912
    
 
913
    SHADOW_GC_OP_PROLOGUE(pGC);
 
914
 
 
915
    if(IS_VISIBLE(pDraw) && nptInit) {
 
916
        DDXPointPtr ppt = pptInit;
 
917
        int npt = nptInit;
 
918
        int extra = pGC->lineWidth >> 1;
 
919
 
 
920
        box.x2 = box.x1 = pptInit->x;
 
921
        box.y2 = box.y1 = pptInit->y;
 
922
 
 
923
        if(npt > 1) {
 
924
           if(pGC->joinStyle == JoinMiter)
 
925
                extra = 6 * pGC->lineWidth;
 
926
           else if(pGC->capStyle == CapProjecting)
 
927
                extra = pGC->lineWidth;
 
928
        }
 
929
 
 
930
        if(mode == CoordModePrevious) {
 
931
           int x = box.x1;
 
932
           int y = box.y1;
 
933
           while(--npt) {
 
934
                ppt++;
 
935
                x += ppt->x;
 
936
                y += ppt->y;
 
937
                if(box.x1 > x) box.x1 = x;
 
938
                else if(box.x2 < x) box.x2 = x;
 
939
                if(box.y1 > y) box.y1 = y;
 
940
                else if(box.y2 < y) box.y2 = y;
 
941
            }
 
942
        } else {
 
943
           while(--npt) {
 
944
                ppt++;
 
945
                if(box.x1 > ppt->x) box.x1 = ppt->x;
 
946
                else if(box.x2 < ppt->x) box.x2 = ppt->x;
 
947
                if(box.y1 > ppt->y) box.y1 = ppt->y;
 
948
                else if(box.y2 < ppt->y) box.y2 = ppt->y;
 
949
            }
 
950
        }
 
951
 
 
952
        box.x2++;
 
953
        box.y2++;
 
954
 
 
955
        if(extra) {
 
956
           box.x1 -= extra;
 
957
           box.x2 += extra;
 
958
           box.y1 -= extra;
 
959
           box.y2 += extra;
 
960
        }
 
961
 
 
962
        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 
963
        if(BOX_NOT_EMPTY(box)) {
 
964
           if(pPriv->preRefresh)
 
965
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
966
           boxNotEmpty = TRUE;
 
967
        }
 
968
    }
 
969
    
 
970
    (*pGC->ops->Polylines)(pDraw, pGC, mode, nptInit, pptInit);
 
971
 
 
972
    if(boxNotEmpty && pPriv->postRefresh)
 
973
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
974
 
 
975
    SHADOW_GC_OP_EPILOGUE(pGC);
 
976
}
 
977
 
 
978
static void 
 
979
ShadowPolySegment(
 
980
    DrawablePtr pDraw,
 
981
    GCPtr       pGC,
 
982
    int         nsegInit,
 
983
    xSegment    *pSegInit 
 
984
){
 
985
    BoxRec box;
 
986
    Bool boxNotEmpty = FALSE;
 
987
   
 
988
    SHADOW_GC_OP_PROLOGUE(pGC);
 
989
 
 
990
    if(IS_VISIBLE(pDraw) && nsegInit) {
 
991
        int extra = pGC->lineWidth;
 
992
        xSegment *pSeg = pSegInit;
 
993
        int nseg = nsegInit;
 
994
 
 
995
        if(pGC->capStyle != CapProjecting)      
 
996
           extra >>= 1;
 
997
 
 
998
        if(pSeg->x2 > pSeg->x1) {
 
999
            box.x1 = pSeg->x1;
 
1000
            box.x2 = pSeg->x2;
 
1001
        } else {
 
1002
            box.x2 = pSeg->x1;
 
1003
            box.x1 = pSeg->x2;
 
1004
        }
 
1005
 
 
1006
        if(pSeg->y2 > pSeg->y1) {
 
1007
            box.y1 = pSeg->y1;
 
1008
            box.y2 = pSeg->y2;
 
1009
        } else {
 
1010
            box.y2 = pSeg->y1;
 
1011
            box.y1 = pSeg->y2;
 
1012
        }
 
1013
 
 
1014
        while(--nseg) {
 
1015
            pSeg++;
 
1016
            if(pSeg->x2 > pSeg->x1) {
 
1017
                if(pSeg->x1 < box.x1) box.x1 = pSeg->x1;
 
1018
                if(pSeg->x2 > box.x2) box.x2 = pSeg->x2;
 
1019
            } else {
 
1020
                if(pSeg->x2 < box.x1) box.x1 = pSeg->x2;
 
1021
                if(pSeg->x1 > box.x2) box.x2 = pSeg->x1;
 
1022
            }
 
1023
            if(pSeg->y2 > pSeg->y1) {
 
1024
                if(pSeg->y1 < box.y1) box.y1 = pSeg->y1;
 
1025
                if(pSeg->y2 > box.y2) box.y2 = pSeg->y2;
 
1026
            } else {
 
1027
                if(pSeg->y2 < box.y1) box.y1 = pSeg->y2;
 
1028
                if(pSeg->y1 > box.y2) box.y2 = pSeg->y1;
 
1029
            }
 
1030
        }
 
1031
 
 
1032
        box.x2++;
 
1033
        box.y2++;
 
1034
 
 
1035
        if(extra) {
 
1036
           box.x1 -= extra;
 
1037
           box.x2 += extra;
 
1038
           box.y1 -= extra;
 
1039
           box.y2 += extra;
 
1040
        }
 
1041
 
 
1042
        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 
1043
        if(BOX_NOT_EMPTY(box)) {
 
1044
           if(pPriv->preRefresh)
 
1045
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1046
           boxNotEmpty = TRUE;
 
1047
        }
 
1048
    }
 
1049
    
 
1050
    (*pGC->ops->PolySegment)(pDraw, pGC, nsegInit, pSegInit);
 
1051
 
 
1052
    if(boxNotEmpty && pPriv->postRefresh)
 
1053
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1054
 
 
1055
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1056
}
 
1057
 
 
1058
static void
 
1059
ShadowPolyRectangle(
 
1060
    DrawablePtr  pDraw,
 
1061
    GCPtr        pGC,
 
1062
    int          nRectsInit,
 
1063
    xRectangle  *pRectsInit 
 
1064
){
 
1065
    BoxRec box;
 
1066
    BoxPtr pBoxInit = NULL;
 
1067
    Bool boxNotEmpty = FALSE;
 
1068
    int num = 0;
 
1069
    
 
1070
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1071
 
 
1072
    if(IS_VISIBLE(pDraw) && nRectsInit) {
 
1073
        xRectangle *pRects = pRectsInit;
 
1074
        int nRects = nRectsInit;
 
1075
 
 
1076
        if(nRects >= 32) {
 
1077
            int extra = pGC->lineWidth >> 1;
 
1078
 
 
1079
            box.x1 = pRects->x;
 
1080
            box.x2 = box.x1 + pRects->width;
 
1081
            box.y1 = pRects->y;
 
1082
            box.y2 = box.y1 + pRects->height;
 
1083
 
 
1084
            while(--nRects) {
 
1085
                pRects++;
 
1086
                if(box.x1 > pRects->x) box.x1 = pRects->x;
 
1087
                if(box.x2 < (pRects->x + pRects->width))
 
1088
                        box.x2 = pRects->x + pRects->width;
 
1089
                if(box.y1 > pRects->y) box.y1 = pRects->y;
 
1090
                if(box.y2 < (pRects->y + pRects->height))
 
1091
                        box.y2 = pRects->y + pRects->height;
 
1092
            }
 
1093
 
 
1094
            if(extra) {
 
1095
                box.x1 -= extra;
 
1096
                box.x2 += extra;
 
1097
                box.y1 -= extra;
 
1098
                box.y2 += extra;
 
1099
            }
 
1100
 
 
1101
            box.x2++;
 
1102
            box.y2++;
 
1103
 
 
1104
            TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 
1105
            if(BOX_NOT_EMPTY(box)) {
 
1106
                if(pPriv->preRefresh)
 
1107
                   (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1108
                boxNotEmpty = TRUE;
 
1109
            }
 
1110
        } else {
 
1111
            BoxPtr pbox;
 
1112
            int offset1, offset2, offset3;
 
1113
 
 
1114
            offset2 = pGC->lineWidth;
 
1115
            if(!offset2) offset2 = 1;
 
1116
            offset1 = offset2 >> 1;
 
1117
            offset3 = offset2 - offset1;
 
1118
 
 
1119
            pBoxInit = (BoxPtr)ALLOCATE_LOCAL(nRects * 4 * sizeof(BoxRec));
 
1120
            pbox = pBoxInit;
 
1121
 
 
1122
            while(nRects--) {
 
1123
                pbox->x1 = pRects->x - offset1;
 
1124
                pbox->y1 = pRects->y - offset1;
 
1125
                pbox->x2 = pbox->x1 + pRects->width + offset2;
 
1126
                pbox->y2 = pbox->y1 + offset2;          
 
1127
                TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
 
1128
                if(BOX_NOT_EMPTY((*pbox))) {
 
1129
                   num++;
 
1130
                   pbox++;
 
1131
                }
 
1132
 
 
1133
                pbox->x1 = pRects->x - offset1;
 
1134
                pbox->y1 = pRects->y + offset3;
 
1135
                pbox->x2 = pbox->x1 + offset2;
 
1136
                pbox->y2 = pbox->y1 + pRects->height - offset2;         
 
1137
                TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
 
1138
                if(BOX_NOT_EMPTY((*pbox))) {
 
1139
                   num++;
 
1140
                   pbox++;
 
1141
                }
 
1142
 
 
1143
                pbox->x1 = pRects->x + pRects->width - offset1;
 
1144
                pbox->y1 = pRects->y + offset3;
 
1145
                pbox->x2 = pbox->x1 + offset2;
 
1146
                pbox->y2 = pbox->y1 + pRects->height - offset2;         
 
1147
                TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
 
1148
                if(BOX_NOT_EMPTY((*pbox))) {
 
1149
                   num++;
 
1150
                   pbox++;
 
1151
                }
 
1152
 
 
1153
                pbox->x1 = pRects->x - offset1;
 
1154
                pbox->y1 = pRects->y + pRects->height - offset1;
 
1155
                pbox->x2 = pbox->x1 + pRects->width + offset2;
 
1156
                pbox->y2 = pbox->y1 + offset2;          
 
1157
                TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
 
1158
                if(BOX_NOT_EMPTY((*pbox))) {
 
1159
                   num++;
 
1160
                   pbox++;
 
1161
                }
 
1162
 
 
1163
                pRects++;
 
1164
            }
 
1165
            
 
1166
            if(num) {
 
1167
                if(pPriv->preRefresh)
 
1168
                    (*pPriv->preRefresh)(pPriv->pScrn, num, pBoxInit);
 
1169
            } else {
 
1170
                DEALLOCATE_LOCAL(pBoxInit);
 
1171
            }                
 
1172
        }
 
1173
    }
 
1174
 
 
1175
    (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit);
 
1176
 
 
1177
    if(boxNotEmpty && pPriv->postRefresh) {
 
1178
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1179
    } else if(num) {
 
1180
       if(pPriv->postRefresh)
 
1181
          (*pPriv->postRefresh)(pPriv->pScrn, num, pBoxInit);
 
1182
       DEALLOCATE_LOCAL(pBoxInit);
 
1183
    }
 
1184
    
 
1185
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1186
 
 
1187
}
 
1188
 
 
1189
static void
 
1190
ShadowPolyArc(
 
1191
    DrawablePtr pDraw,
 
1192
    GCPtr       pGC,
 
1193
    int         narcsInit,
 
1194
    xArc        *parcsInit 
 
1195
){
 
1196
    BoxRec box;
 
1197
    Bool boxNotEmpty = FALSE;
 
1198
   
 
1199
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1200
 
 
1201
    if(IS_VISIBLE(pDraw) && narcsInit) {
 
1202
        int narcs = narcsInit;
 
1203
        xArc *parcs = parcsInit;
 
1204
        int extra = pGC->lineWidth >> 1;
 
1205
 
 
1206
        box.x1 = parcs->x;
 
1207
        box.x2 = box.x1 + parcs->width;
 
1208
        box.y1 = parcs->y;
 
1209
        box.y2 = box.y1 + parcs->height;
 
1210
 
 
1211
        /* should I break these up instead ? */
 
1212
 
 
1213
        while(--narcs) {
 
1214
           parcs++;
 
1215
           if(box.x1 > parcs->x) box.x1 = parcs->x;
 
1216
           if(box.x2 < (parcs->x + parcs->width))
 
1217
                box.x2 = parcs->x + parcs->width;
 
1218
           if(box.y1 > parcs->y) box.y1 = parcs->y;
 
1219
           if(box.y2 < (parcs->y + parcs->height))
 
1220
                box.y2 = parcs->y + parcs->height;
 
1221
        }
 
1222
 
 
1223
        if(extra) {
 
1224
           box.x1 -= extra;
 
1225
           box.x2 += extra;
 
1226
           box.y1 -= extra;
 
1227
           box.y2 += extra;
 
1228
        }
 
1229
 
 
1230
        box.x2++;
 
1231
        box.y2++;
 
1232
 
 
1233
        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 
1234
        if(BOX_NOT_EMPTY(box)) {
 
1235
           if(pPriv->preRefresh)
 
1236
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1237
           boxNotEmpty = TRUE;
 
1238
        }
 
1239
    }
 
1240
    
 
1241
    (*pGC->ops->PolyArc)(pDraw, pGC, narcsInit, parcsInit);
 
1242
 
 
1243
    if(boxNotEmpty && pPriv->postRefresh)
 
1244
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1245
    
 
1246
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1247
 
 
1248
}
 
1249
 
 
1250
static void
 
1251
ShadowFillPolygon(
 
1252
    DrawablePtr pDraw,
 
1253
    GCPtr       pGC,
 
1254
    int         shape,
 
1255
    int         mode,
 
1256
    int         count,
 
1257
    DDXPointPtr pptInit 
 
1258
){
 
1259
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1260
 
 
1261
    if(IS_VISIBLE(pDraw) && (count > 2)) {
 
1262
        DDXPointPtr ppt = pptInit;
 
1263
        int i = count;
 
1264
        BoxRec box;
 
1265
        Bool boxNotEmpty = FALSE;
 
1266
 
 
1267
        box.x2 = box.x1 = ppt->x;
 
1268
        box.y2 = box.y1 = ppt->y;
 
1269
 
 
1270
        if(mode != CoordModeOrigin) {
 
1271
           int x = box.x1;
 
1272
           int y = box.y1;
 
1273
           while(--i) {
 
1274
                ppt++;
 
1275
                x += ppt->x;
 
1276
                y += ppt->y;
 
1277
                if(box.x1 > x) box.x1 = x;
 
1278
                else if(box.x2 < x) box.x2 = x;
 
1279
                if(box.y1 > y) box.y1 = y;
 
1280
                else if(box.y2 < y) box.y2 = y;
 
1281
            }
 
1282
        } else {
 
1283
           while(--i) {
 
1284
                ppt++;
 
1285
                if(box.x1 > ppt->x) box.x1 = ppt->x;
 
1286
                else if(box.x2 < ppt->x) box.x2 = ppt->x;
 
1287
                if(box.y1 > ppt->y) box.y1 = ppt->y;
 
1288
                else if(box.y2 < ppt->y) box.y2 = ppt->y;
 
1289
            }
 
1290
        }
 
1291
 
 
1292
        box.x2++;
 
1293
        box.y2++;
 
1294
 
 
1295
        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 
1296
        if(BOX_NOT_EMPTY(box)) {
 
1297
           if(pPriv->preRefresh)
 
1298
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1299
           boxNotEmpty = TRUE;
 
1300
        }
 
1301
 
 
1302
        (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
 
1303
 
 
1304
        if(boxNotEmpty && pPriv->postRefresh)
 
1305
           (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);        
 
1306
    } else
 
1307
        (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
 
1308
 
 
1309
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1310
}
 
1311
 
 
1312
 
 
1313
static void 
 
1314
ShadowPolyFillRect(
 
1315
    DrawablePtr pDraw,
 
1316
    GCPtr       pGC,
 
1317
    int         nRectsInit, 
 
1318
    xRectangle  *pRectsInit 
 
1319
){
 
1320
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1321
 
 
1322
    if(IS_VISIBLE(pDraw) && nRectsInit) {
 
1323
        BoxRec box;
 
1324
        Bool boxNotEmpty = FALSE;
 
1325
        xRectangle *pRects = pRectsInit;
 
1326
        int nRects = nRectsInit;
 
1327
 
 
1328
        box.x1 = pRects->x;
 
1329
        box.x2 = box.x1 + pRects->width;
 
1330
        box.y1 = pRects->y;
 
1331
        box.y2 = box.y1 + pRects->height;
 
1332
 
 
1333
        while(--nRects) {
 
1334
            pRects++;
 
1335
            if(box.x1 > pRects->x) box.x1 = pRects->x;
 
1336
            if(box.x2 < (pRects->x + pRects->width))
 
1337
                box.x2 = pRects->x + pRects->width;
 
1338
            if(box.y1 > pRects->y) box.y1 = pRects->y;
 
1339
            if(box.y2 < (pRects->y + pRects->height))
 
1340
                box.y2 = pRects->y + pRects->height;
 
1341
        }
 
1342
 
 
1343
        /* cfb messes with the pRectsInit so we have to do our
 
1344
           calculations first */
 
1345
 
 
1346
        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 
1347
        if(BOX_NOT_EMPTY(box)) {
 
1348
            if(pPriv->preRefresh)
 
1349
                (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1350
            boxNotEmpty = TRUE;
 
1351
        }
 
1352
 
 
1353
        (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
 
1354
 
 
1355
        if(boxNotEmpty && pPriv->postRefresh)
 
1356
            (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1357
    } else
 
1358
        (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
 
1359
 
 
1360
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1361
}
 
1362
 
 
1363
 
 
1364
static void
 
1365
ShadowPolyFillArc(
 
1366
    DrawablePtr pDraw,
 
1367
    GCPtr       pGC,
 
1368
    int         narcsInit,
 
1369
    xArc        *parcsInit 
 
1370
){
 
1371
    BoxRec box;
 
1372
    Bool boxNotEmpty = FALSE;
 
1373
   
 
1374
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1375
 
 
1376
    if(IS_VISIBLE(pDraw) && narcsInit) {
 
1377
        xArc *parcs = parcsInit;
 
1378
        int narcs = narcsInit;
 
1379
 
 
1380
        box.x1 = parcs->x;
 
1381
        box.x2 = box.x1 + parcs->width;
 
1382
        box.y1 = parcs->y;
 
1383
        box.y2 = box.y1 + parcs->height;
 
1384
 
 
1385
        /* should I break these up instead ? */
 
1386
 
 
1387
        while(--narcs) {
 
1388
           parcs++;
 
1389
           if(box.x1 > parcs->x) box.x1 = parcs->x;
 
1390
           if(box.x2 < (parcs->x + parcs->width))
 
1391
                box.x2 = parcs->x + parcs->width;
 
1392
           if(box.y1 > parcs->y) box.y1 = parcs->y;
 
1393
           if(box.y2 < (parcs->y + parcs->height))
 
1394
                box.y2 = parcs->y + parcs->height;
 
1395
        }
 
1396
 
 
1397
        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
 
1398
        if(BOX_NOT_EMPTY(box)) {
 
1399
           if(pPriv->preRefresh)
 
1400
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1401
           boxNotEmpty = TRUE;
 
1402
        }
 
1403
    }
 
1404
 
 
1405
    (*pGC->ops->PolyFillArc)(pDraw, pGC, narcsInit, parcsInit);
 
1406
 
 
1407
    if(boxNotEmpty && pPriv->postRefresh)
 
1408
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);       
 
1409
    
 
1410
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1411
}
 
1412
 
 
1413
static void
 
1414
ShadowTextExtent(FontPtr pFont, int count, char* chars,
 
1415
                 FontEncoding fontEncoding, BoxPtr box)
 
1416
{
 
1417
    unsigned long n, i;
 
1418
    int w;
 
1419
    CharInfoPtr charinfo[255];  /* encoding only has 1 byte for count */
 
1420
 
 
1421
    GetGlyphs(pFont, (unsigned long)count, (unsigned char *)chars,
 
1422
              fontEncoding, &n, charinfo);
 
1423
    w = 0;
 
1424
    for (i=0; i < n; i++) {
 
1425
        w += charinfo[i]->metrics.characterWidth;
 
1426
    }
 
1427
    if (i) {
 
1428
        w += charinfo[i - 1]->metrics.rightSideBearing;
 
1429
    }
 
1430
    
 
1431
    box->x1 = 0;
 
1432
    if (n) {
 
1433
        if (charinfo[0]->metrics.leftSideBearing < 0) {
 
1434
            box->x1 = charinfo[0]->metrics.leftSideBearing;
 
1435
        }
 
1436
    }
 
1437
    box->x2 = w;
 
1438
    box->y1 = -FONTMAXBOUNDS(pFont,ascent);
 
1439
    box->y2 = FONTMAXBOUNDS(pFont,descent);
 
1440
}
 
1441
 
 
1442
 
 
1443
 
 
1444
static void
 
1445
ShadowFontToBox(BoxPtr BB, DrawablePtr pDrawable, GCPtr pGC, int x, int y,
 
1446
                int count, char *chars, int wide)
 
1447
{
 
1448
    FontPtr pFont;
 
1449
 
 
1450
    pFont = pGC->font;
 
1451
    if (pFont->info.constantWidth) {
 
1452
        int ascent, descent, left, right = 0;
 
1453
 
 
1454
        ascent = MAX(pFont->info.fontAscent, pFont->info.maxbounds.ascent);
 
1455
        descent = MAX(pFont->info.fontDescent, pFont->info.maxbounds.descent);
 
1456
        left = pFont->info.maxbounds.leftSideBearing;
 
1457
        if (count > 0) {
 
1458
            right = (count - 1) * pFont->info.maxbounds.characterWidth;
 
1459
        }
 
1460
        right += pFont->info.maxbounds.rightSideBearing;
 
1461
        BB->x1 =
 
1462
            MAX(pDrawable->x + x - left, (REGION_EXTENTS(pGC->pScreen,
 
1463
                &((WindowPtr) pDrawable)->winSize))->x1);
 
1464
        BB->y1 =
 
1465
            MAX(pDrawable->y + y - ascent,
 
1466
            (REGION_EXTENTS(pGC->pScreen,
 
1467
             &((WindowPtr) pDrawable)->winSize))->y1);
 
1468
        BB->x2 =
 
1469
            MIN(pDrawable->x + x + right,
 
1470
            (REGION_EXTENTS(pGC->pScreen,
 
1471
             &((WindowPtr) pDrawable)->winSize))->x2);
 
1472
        BB->y2 =
 
1473
            MIN(pDrawable->y + y + descent,
 
1474
            (REGION_EXTENTS(pGC->pScreen,
 
1475
             &((WindowPtr) pDrawable)->winSize))->y2);
 
1476
    } else {
 
1477
        ShadowTextExtent(pFont, count, chars, wide ? (FONTLASTROW(pFont) == 0)
 
1478
                         ? Linear16Bit : TwoD16Bit : Linear8Bit, BB);
 
1479
        BB->x1 =
 
1480
            MAX(pDrawable->x + x + BB->x1, (REGION_EXTENTS(pGC->pScreen,
 
1481
                &((WindowPtr) pDrawable)->winSize))->x1);
 
1482
        BB->y1 =
 
1483
            MAX(pDrawable->y + y + BB->y1,
 
1484
            (REGION_EXTENTS(pGC->pScreen,
 
1485
             &((WindowPtr) pDrawable)->winSize))->y1);
 
1486
        BB->x2 =
 
1487
            MIN(pDrawable->x + x + BB->x2,
 
1488
            (REGION_EXTENTS(pGC->pScreen,
 
1489
             &((WindowPtr) pDrawable)->winSize))->x2);
 
1490
        BB->y2 =
 
1491
            MIN(pDrawable->y + y + BB->y2,
 
1492
            (REGION_EXTENTS(pGC->pScreen, 
 
1493
             &((WindowPtr) pDrawable)->winSize))->y2);
 
1494
    }
 
1495
}
 
1496
 
 
1497
static int
 
1498
ShadowPolyText8(
 
1499
    DrawablePtr pDraw,
 
1500
    GCPtr       pGC,
 
1501
    int         x, 
 
1502
    int         y,
 
1503
    int         count,
 
1504
    char        *chars 
 
1505
){
 
1506
    int width;
 
1507
    BoxRec box;
 
1508
    Bool boxNotEmpty = FALSE;
 
1509
    
 
1510
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1511
 
 
1512
    if(IS_VISIBLE(pDraw)) {
 
1513
        ShadowFontToBox(&box, pDraw, pGC, x, y, count, chars, 0);
 
1514
       
 
1515
        TRIM_BOX(box, pGC);
 
1516
        if(BOX_NOT_EMPTY(box)) {
 
1517
           if(pPriv->preRefresh)
 
1518
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1519
           boxNotEmpty = TRUE;
 
1520
        }
 
1521
    }
 
1522
    
 
1523
    width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
 
1524
 
 
1525
    if(boxNotEmpty && pPriv->postRefresh)
 
1526
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1527
    
 
1528
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1529
 
 
1530
    return width;
 
1531
}
 
1532
 
 
1533
static int
 
1534
ShadowPolyText16(
 
1535
    DrawablePtr pDraw,
 
1536
    GCPtr       pGC,
 
1537
    int         x,
 
1538
    int         y,
 
1539
    int         count,
 
1540
    unsigned short *chars 
 
1541
){
 
1542
    int width;
 
1543
    BoxRec box;
 
1544
    Bool boxNotEmpty = FALSE;
 
1545
 
 
1546
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1547
 
 
1548
    if(IS_VISIBLE(pDraw)) {
 
1549
        ShadowFontToBox(&box, pDraw, pGC, x, y, count, (char*)chars, 1);
 
1550
       
 
1551
        TRIM_BOX(box, pGC);
 
1552
        if(BOX_NOT_EMPTY(box)) {
 
1553
           if(pPriv->preRefresh)
 
1554
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1555
           boxNotEmpty = TRUE;
 
1556
        }
 
1557
    }
 
1558
 
 
1559
    width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
 
1560
 
 
1561
    if(boxNotEmpty && pPriv->postRefresh)
 
1562
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1563
 
 
1564
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1565
 
 
1566
    return width;
 
1567
}
 
1568
 
 
1569
static void
 
1570
ShadowImageText8(
 
1571
    DrawablePtr pDraw,
 
1572
    GCPtr       pGC,
 
1573
    int         x, 
 
1574
    int         y,
 
1575
    int         count,
 
1576
    char        *chars 
 
1577
){
 
1578
    BoxRec box;
 
1579
    Bool boxNotEmpty = FALSE;
 
1580
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1581
 
 
1582
    if(IS_VISIBLE(pDraw) && count) {
 
1583
        int top, bot, Min, Max;
 
1584
 
 
1585
        top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
 
1586
        bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
 
1587
 
 
1588
        Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
 
1589
        if(Min > 0) Min = 0;
 
1590
        Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); 
 
1591
        if(Max < 0) Max = 0;
 
1592
 
 
1593
        /* ugh */
 
1594
        box.x1 = pDraw->x + x + Min +
 
1595
                FONTMINBOUNDS(pGC->font, leftSideBearing);
 
1596
        box.x2 = pDraw->x + x + Max + 
 
1597
                FONTMAXBOUNDS(pGC->font, rightSideBearing);
 
1598
 
 
1599
        box.y1 = pDraw->y + y - top;
 
1600
        box.y2 = pDraw->y + y + bot;
 
1601
 
 
1602
        TRIM_BOX(box, pGC);
 
1603
        if(BOX_NOT_EMPTY(box)) {
 
1604
            if(pPriv->preRefresh) 
 
1605
               (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1606
            boxNotEmpty = TRUE;
 
1607
        }
 
1608
    }
 
1609
    
 
1610
    (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
 
1611
 
 
1612
    if(boxNotEmpty && pPriv->postRefresh)
 
1613
        (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1614
    
 
1615
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1616
}
 
1617
static void
 
1618
ShadowImageText16(
 
1619
    DrawablePtr pDraw,
 
1620
    GCPtr       pGC,
 
1621
    int         x,
 
1622
    int         y,
 
1623
    int         count,
 
1624
    unsigned short *chars 
 
1625
){
 
1626
    BoxRec box;
 
1627
    Bool boxNotEmpty = FALSE;
 
1628
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1629
 
 
1630
    if(IS_VISIBLE(pDraw) && count) {
 
1631
        int top, bot, Min, Max;
 
1632
 
 
1633
        top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
 
1634
        bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
 
1635
 
 
1636
        Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
 
1637
        if(Min > 0) Min = 0;
 
1638
        Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); 
 
1639
        if(Max < 0) Max = 0;
 
1640
 
 
1641
        /* ugh */
 
1642
        box.x1 = pDraw->x + x + Min +
 
1643
                FONTMINBOUNDS(pGC->font, leftSideBearing);
 
1644
        box.x2 = pDraw->x + x + Max + 
 
1645
                FONTMAXBOUNDS(pGC->font, rightSideBearing);
 
1646
 
 
1647
        box.y1 = pDraw->y + y - top;
 
1648
        box.y2 = pDraw->y + y + bot;
 
1649
 
 
1650
        TRIM_BOX(box, pGC);
 
1651
        if(BOX_NOT_EMPTY(box)) {
 
1652
           if(pPriv->preRefresh)
 
1653
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1654
           boxNotEmpty = TRUE;
 
1655
        }
 
1656
    }
 
1657
    
 
1658
    (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
 
1659
 
 
1660
    if(boxNotEmpty && pPriv->postRefresh)
 
1661
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);   
 
1662
    
 
1663
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1664
}
 
1665
 
 
1666
 
 
1667
static void
 
1668
ShadowImageGlyphBlt(
 
1669
    DrawablePtr pDraw,
 
1670
    GCPtr pGC,
 
1671
    int x, int y,
 
1672
    unsigned int nglyphInit,
 
1673
    CharInfoPtr *ppciInit,
 
1674
    pointer pglyphBase 
 
1675
){
 
1676
    BoxRec box;
 
1677
    Bool boxNotEmpty = FALSE;
 
1678
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1679
 
 
1680
    if(IS_VISIBLE(pDraw) && nglyphInit) {
 
1681
        CharInfoPtr *ppci = ppciInit;
 
1682
        unsigned int nglyph = nglyphInit;
 
1683
        int top, bot, width = 0;
 
1684
 
 
1685
        top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
 
1686
        bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
 
1687
 
 
1688
        box.x1 = ppci[0]->metrics.leftSideBearing;
 
1689
        if(box.x1 > 0) box.x1 = 0;
 
1690
        box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - 
 
1691
                ppci[nglyph - 1]->metrics.characterWidth;
 
1692
        if(box.x2 < 0) box.x2 = 0;
 
1693
 
 
1694
        box.x2 += pDraw->x + x;
 
1695
        box.x1 += pDraw->x + x;
 
1696
           
 
1697
        while(nglyph--) {
 
1698
            width += (*ppci)->metrics.characterWidth;
 
1699
            ppci++;
 
1700
        }
 
1701
 
 
1702
        if(width > 0) 
 
1703
           box.x2 += width;
 
1704
        else 
 
1705
           box.x1 += width;
 
1706
 
 
1707
        box.y1 = pDraw->y + y - top;
 
1708
        box.y2 = pDraw->y + y + bot;
 
1709
 
 
1710
        TRIM_BOX(box, pGC);
 
1711
        if(BOX_NOT_EMPTY(box)) {
 
1712
           if(pPriv->preRefresh)
 
1713
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1714
           boxNotEmpty = TRUE;
 
1715
        }
 
1716
    }
 
1717
 
 
1718
    (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyphInit, 
 
1719
                                        ppciInit, pglyphBase);
 
1720
 
 
1721
    if(boxNotEmpty && pPriv->postRefresh)
 
1722
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1723
 
 
1724
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1725
}
 
1726
 
 
1727
static void
 
1728
ShadowPolyGlyphBlt(
 
1729
    DrawablePtr pDraw,
 
1730
    GCPtr pGC,
 
1731
    int x, int y,
 
1732
    unsigned int nglyphInit,
 
1733
    CharInfoPtr *ppciInit,
 
1734
    pointer pglyphBase 
 
1735
){
 
1736
    BoxRec box;
 
1737
    Bool boxNotEmpty = FALSE;
 
1738
 
 
1739
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1740
 
 
1741
    if(IS_VISIBLE(pDraw) && nglyphInit) {
 
1742
        CharInfoPtr *ppci = ppciInit;
 
1743
        unsigned int nglyph = nglyphInit;
 
1744
 
 
1745
        /* ugh */
 
1746
        box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing;
 
1747
        box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
 
1748
 
 
1749
        if(nglyph > 1) {
 
1750
            int width = 0;
 
1751
 
 
1752
            while(--nglyph) { 
 
1753
                width += (*ppci)->metrics.characterWidth;
 
1754
                ppci++;
 
1755
            }
 
1756
        
 
1757
            if(width > 0) box.x2 += width;
 
1758
            else box.x1 += width;
 
1759
        }
 
1760
 
 
1761
        box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
 
1762
        box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
 
1763
 
 
1764
        TRIM_BOX(box, pGC);
 
1765
        if(BOX_NOT_EMPTY(box)) {
 
1766
           if(pPriv->preRefresh)
 
1767
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1768
           boxNotEmpty = TRUE;
 
1769
        }
 
1770
    }
 
1771
    
 
1772
    (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyphInit, 
 
1773
                                ppciInit, pglyphBase);
 
1774
 
 
1775
    if(boxNotEmpty && pPriv->postRefresh)
 
1776
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1777
 
 
1778
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1779
}
 
1780
 
 
1781
static void
 
1782
ShadowPushPixels(
 
1783
    GCPtr       pGC,
 
1784
    PixmapPtr   pBitMap,
 
1785
    DrawablePtr pDraw,
 
1786
    int dx, int dy, int xOrg, int yOrg 
 
1787
){
 
1788
    BoxRec box;
 
1789
    Bool boxNotEmpty = FALSE;
 
1790
    
 
1791
    SHADOW_GC_OP_PROLOGUE(pGC);
 
1792
 
 
1793
    if(IS_VISIBLE(pDraw)) {
 
1794
        box.x1 = xOrg;
 
1795
        box.y1 = yOrg;
 
1796
 
 
1797
        if(!pGC->miTranslate) {
 
1798
           box.x1 += pDraw->x;          
 
1799
           box.y1 += pDraw->y;          
 
1800
        }
 
1801
 
 
1802
        box.x2 = box.x1 + dx;
 
1803
        box.y2 = box.y1 + dy;
 
1804
 
 
1805
        TRIM_BOX(box, pGC);
 
1806
        if(BOX_NOT_EMPTY(box)) {
 
1807
           if(pPriv->preRefresh)
 
1808
              (*pPriv->preRefresh)(pPriv->pScrn, 1, &box);
 
1809
           boxNotEmpty = TRUE;
 
1810
        }
 
1811
    }
 
1812
 
 
1813
    (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
 
1814
 
 
1815
    if(boxNotEmpty && pPriv->postRefresh)
 
1816
       (*pPriv->postRefresh)(pPriv->pScrn, 1, &box);
 
1817
 
 
1818
    SHADOW_GC_OP_EPILOGUE(pGC);
 
1819
}
 
1820
 
 
1821
 
 
1822
GCOps ShadowGCOps = {
 
1823
    ShadowFillSpans, ShadowSetSpans, 
 
1824
    ShadowPutImage, ShadowCopyArea, 
 
1825
    ShadowCopyPlane, ShadowPolyPoint, 
 
1826
    ShadowPolylines, ShadowPolySegment, 
 
1827
    ShadowPolyRectangle, ShadowPolyArc, 
 
1828
    ShadowFillPolygon, ShadowPolyFillRect, 
 
1829
    ShadowPolyFillArc, ShadowPolyText8, 
 
1830
    ShadowPolyText16, ShadowImageText8, 
 
1831
    ShadowImageText16, ShadowImageGlyphBlt, 
 
1832
    ShadowPolyGlyphBlt, ShadowPushPixels,
 
1833
#ifdef NEED_LINEHELPER
 
1834
    NULL,
 
1835
#endif
 
1836
    {NULL}              /* devPrivate */
 
1837
};
 
1838