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