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