1 /* 2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory 3 * PROJECT: ReactOS Win32k subsystem 4 * PURPOSE: Clip region functions 5 * FILE: win32ss/gdi/ntgdi/cliprgn.c 6 * PROGRAMER: Unknown 7 */ 8 9 #include <win32k.h> 10 11 #define NDEBUG 12 #include <debug.h> 13 14 DBG_DEFAULT_CHANNEL(GdiClipRgn); 15 16 VOID 17 FASTCALL 18 IntGdiReleaseRaoRgn(PDC pDC) 19 { 20 INT Index = GDI_HANDLE_GET_INDEX(pDC->BaseObject.hHmgr); 21 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index]; 22 pDC->fs |= DC_DIRTY_RAO; 23 Entry->Flags |= GDI_ENTRY_VALIDATE_VIS; // Need to validate Vis. 24 } 25 26 VOID 27 FASTCALL 28 IntGdiReleaseVisRgn(PDC pDC) 29 { 30 IntGdiReleaseRaoRgn(pDC); 31 REGION_Delete(pDC->prgnVis); 32 pDC->prgnVis = prgnDefault; // Vis can not be NULL!!! 33 } 34 35 // 36 // Updating Vis Region Attribute for DC Attributes. 37 // BTW: This system region has an user attribute for it. 38 // 39 VOID 40 FASTCALL 41 UpdateVisRgn( 42 PDC pdc) 43 { 44 INT Index = GDI_HANDLE_GET_INDEX(pdc->BaseObject.hHmgr); 45 PGDI_TABLE_ENTRY pEntry = &GdiHandleTable->Entries[Index]; 46 47 /* Setup Vis Region Attribute information to User side */ 48 pEntry->Flags |= GDI_ENTRY_VALIDATE_VIS; 49 pdc->pdcattr->VisRectRegion.iComplexity = REGION_GetRgnBox(pdc->prgnVis, &pdc->pdcattr->VisRectRegion.Rect); 50 pdc->pdcattr->VisRectRegion.AttrFlags = ATTR_RGN_VALID; 51 pEntry->Flags &= ~GDI_ENTRY_VALIDATE_VIS; 52 } 53 54 // 55 // Selecting Vis Region. 56 // 57 VOID 58 FASTCALL 59 GdiSelectVisRgn( 60 HDC hdc, 61 PREGION prgn) 62 { 63 DC *dc; 64 65 if (!(dc = DC_LockDc(hdc))) 66 { 67 EngSetLastError(ERROR_INVALID_HANDLE); 68 return; 69 } 70 71 if (!prgn) 72 { 73 DPRINT1("SVR: Setting NULL Region\n"); 74 IntGdiReleaseVisRgn(dc); 75 IntSetDefaultRegion(dc); 76 DC_UnlockDc(dc); 77 return; 78 } 79 80 dc->fs |= DC_DIRTY_RAO; 81 82 ASSERT(dc->prgnVis != NULL); 83 ASSERT(prgn != NULL); 84 85 REGION_bCopy(dc->prgnVis, prgn); 86 REGION_bOffsetRgn(dc->prgnVis, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y); 87 88 DC_UnlockDc(dc); 89 } 90 91 _Success_(return!=ERROR) 92 int 93 FASTCALL 94 IntSelectClipRgn( 95 _In_ PDC dc, 96 _In_ PREGION prgn, 97 _In_ int fnMode) 98 { 99 int Ret = ERROR; 100 PREGION prgnNClip, prgnOrigClip = dc->dclevel.prgnClip; 101 102 // 103 // No Coping Regions and no intersecting Regions or an User calling w NULL Region or have the Original Clip Region. 104 // 105 if (fnMode != RGN_COPY && (fnMode != RGN_AND || !prgn || prgnOrigClip)) 106 { 107 prgnNClip = IntSysCreateRectpRgn(0, 0, 0, 0); 108 109 // Have Original Clip Region. 110 if (prgnOrigClip) 111 { 112 // This will fail on NULL prgn. 113 Ret = IntGdiCombineRgn(prgnNClip, prgnOrigClip, prgn, fnMode); 114 115 if (Ret) 116 { 117 REGION_Delete(prgnOrigClip); 118 dc->dclevel.prgnClip = prgnNClip; 119 IntGdiReleaseRaoRgn(dc); 120 } 121 else 122 REGION_Delete(prgnNClip); 123 } 124 else // NULL Original Clip Region, setup a new one and process mode. 125 { 126 PREGION prgnClip; 127 RECTL rcl; 128 #if 0 129 PSURFACE pSurface; 130 131 // See IntSetDefaultRegion. 132 133 rcl.left = 0; 134 rcl.top = 0; 135 rcl.right = dc->dclevel.sizl.cx; 136 rcl.bottom = dc->dclevel.sizl.cy; 137 138 //EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock); 139 if (dc->ppdev->flFlags & PDEV_META_DEVICE) 140 { 141 pSurface = dc->dclevel.pSurface; 142 if (pSurface && pSurface->flags & PDEV_SURFACE) 143 { 144 rcl.left += dc->ppdev->ptlOrigion.x; 145 rcl.top += dc->ppdev->ptlOrigion.y; 146 rcl.right += dc->ppdev->ptlOrigion.x; 147 rcl.bottom += dc->ppdev->ptlOrigion.y; 148 } 149 } 150 //EngReleaseSemaphore(pdc->ppdev->hsemDevLock); 151 //#if 0 152 rcl.left += dc->ptlDCOrig.x; 153 rcl.top += dc->ptlDCOrig.y; 154 rcl.right += dc->ptlDCOrig.x; 155 rcl.bottom += dc->ptlDCOrig.y; 156 #endif 157 REGION_GetRgnBox(dc->prgnVis, &rcl); 158 159 prgnClip = IntSysCreateRectpRgnIndirect(&rcl); 160 161 Ret = IntGdiCombineRgn(prgnNClip, prgnClip, prgn, fnMode); 162 163 if (Ret) 164 { 165 dc->dclevel.prgnClip = prgnNClip; 166 IntGdiReleaseRaoRgn(dc); 167 } 168 else 169 REGION_Delete(prgnNClip); 170 171 REGION_Delete(prgnClip); 172 } 173 return Ret; 174 } 175 176 // Fall through to normal RectOS mode. 177 178 // 179 // Handle NULL Region and Original Clip Region. 180 // 181 if (!prgn) 182 { 183 if (prgnOrigClip) 184 { 185 REGION_Delete(dc->dclevel.prgnClip); 186 dc->dclevel.prgnClip = NULL; 187 IntGdiReleaseRaoRgn(dc); 188 } 189 return SIMPLEREGION; 190 } 191 192 // 193 // Combine the new Clip region with original Clip and caller Region. 194 // 195 if ( prgnOrigClip && 196 (Ret = IntGdiCombineRgn(prgnOrigClip, prgn, NULL, RGN_COPY)) ) // Clip could fail. 197 { 198 IntGdiReleaseRaoRgn(dc); 199 } 200 else // NULL original Clip, just copy caller region to new. 201 { 202 prgnNClip = IntSysCreateRectpRgn(0, 0, 0, 0); 203 REGION_bCopy(prgnNClip, prgn); 204 Ret = REGION_Complexity(prgnNClip); 205 dc->dclevel.prgnClip = prgnNClip; 206 IntGdiReleaseRaoRgn(dc); 207 } 208 return Ret; 209 } 210 211 // 212 // Call from Gdi Batch Subsystem. 213 // 214 // Was setup to just handle RGN_COPY only and return VOID, since this was called from Gdi32. 215 // Tested in place of the other, complexity aside. 216 // 217 218 _Success_(return!=ERROR) 219 int 220 FASTCALL 221 IntGdiExtSelectClipRect( 222 _In_ PDC dc, 223 _In_ PRECTL prcl, 224 _In_ int fnMode) 225 { 226 int Ret = ERROR; 227 PREGION prgn; 228 RECTL rect; 229 BOOL NoRegion = fnMode & GDIBS_NORECT; 230 231 fnMode &= ~GDIBS_NORECT; 232 233 if (NoRegion) // NULL Region. 234 { 235 if (fnMode == RGN_COPY) 236 { 237 Ret = IntSelectClipRgn( dc, NULL, RGN_COPY); 238 239 if (dc->fs & DC_DIRTY_RAO) 240 CLIPPING_UpdateGCRegion(dc); 241 242 if (Ret) // Copy? Return Vis complexity. 243 Ret = REGION_Complexity(dc->prgnVis); 244 } 245 } 246 else // Have a box to build a region with. 247 { // See CORE-16246 : Needs to be a one box Clip Region. 248 if ( dc->dclevel.prgnClip && (REGION_Complexity(dc->dclevel.prgnClip) == SIMPLEREGION) ) 249 { 250 REGION_GetRgnBox(dc->dclevel.prgnClip, &rect); 251 252 if (prcl->left == rect.left && 253 prcl->top == rect.top && 254 prcl->right == rect.right && 255 prcl->bottom == rect.bottom) 256 { 257 return REGION_Complexity( dc->prgnRao ? dc->prgnRao : dc->prgnVis ); 258 } 259 } 260 261 prgn = IntSysCreateRectpRgnIndirect(prcl); 262 263 Ret = IntSelectClipRgn( dc, prgn, fnMode); 264 265 if (dc->fs & DC_DIRTY_RAO) 266 CLIPPING_UpdateGCRegion(dc); 267 268 if (Ret) // In this case NtGdiExtSelectClipRgn tests pass. 269 Ret = REGION_Complexity( dc->prgnRao ? dc->prgnRao : dc->prgnVis ); 270 271 REGION_Delete(prgn); 272 } 273 return Ret; 274 } 275 276 _Success_(return!=ERROR) 277 int 278 FASTCALL 279 IntGdiExtSelectClipRgn( 280 _In_ PDC dc, 281 _In_ PREGION prgn, 282 _In_ int fnMode) 283 { 284 int Ret = ERROR; 285 286 if (!prgn) 287 { 288 if (fnMode == RGN_COPY) 289 { 290 if ((Ret = IntSelectClipRgn( dc, NULL, RGN_COPY))) 291 Ret = REGION_Complexity(dc->prgnVis); 292 } 293 } 294 else 295 { 296 if ((Ret = IntSelectClipRgn( dc, prgn, fnMode))) 297 { 298 DPRINT("IntGdiExtSelectClipRgn A %d\n",Ret); 299 // Update the Rao, it must be this way for now. 300 if (dc->fs & DC_DIRTY_RAO) 301 CLIPPING_UpdateGCRegion(dc); 302 303 Ret = REGION_Complexity( dc->prgnRao ? dc->prgnRao : dc->prgnVis ); 304 DPRINT("IntGdiExtSelectClipRgn B %d\n",Ret); 305 } 306 } 307 return Ret; 308 } 309 310 int 311 APIENTRY 312 NtGdiExtSelectClipRgn( 313 HDC hDC, 314 HRGN hrgn, 315 int fnMode) 316 { 317 int retval; 318 DC *dc; 319 PREGION prgn; 320 321 if ( fnMode < RGN_AND || fnMode > RGN_COPY ) 322 { 323 EngSetLastError(ERROR_INVALID_PARAMETER); 324 return ERROR; 325 } 326 327 if (!(dc = DC_LockDc(hDC))) 328 { 329 EngSetLastError(ERROR_INVALID_HANDLE); 330 return ERROR; 331 } 332 333 prgn = REGION_LockRgn(hrgn); 334 335 if ((prgn == NULL) && (fnMode != RGN_COPY)) 336 { 337 //EngSetLastError(ERROR_INVALID_HANDLE); doesn't set this. 338 retval = ERROR; 339 } 340 else 341 { 342 #if 0 // Testing GDI Batch. 343 { 344 RECTL rcl; 345 if (prgn) 346 REGION_GetRgnBox(prgn, &rcl); 347 else 348 fnMode |= GDIBS_NORECT; 349 retval = IntGdiExtSelectClipRect(dc, &rcl, fnMode); 350 } 351 #else 352 retval = IntGdiExtSelectClipRgn(dc, prgn, fnMode); 353 #endif 354 } 355 356 if (prgn) 357 REGION_UnlockRgn(prgn); 358 359 DC_UnlockDc(dc); 360 return retval; 361 } 362 363 _Success_(return!=ERROR) 364 INT 365 FASTCALL 366 GdiGetClipBox( 367 _In_ HDC hdc, 368 _Out_ LPRECT prc) 369 { 370 PDC pdc; 371 INT iComplexity; 372 373 /* Lock the DC */ 374 pdc = DC_LockDc(hdc); 375 if (!pdc) 376 { 377 return ERROR; 378 } 379 380 /* Update RAO region if necessary */ 381 if (pdc->fs & DC_DIRTY_RAO) 382 CLIPPING_UpdateGCRegion(pdc); 383 384 /* Check if we have a RAO region (intersection of API and VIS region) */ 385 if (pdc->prgnRao) 386 { 387 /* We have a RAO region, use it */ 388 iComplexity = REGION_GetRgnBox(pdc->prgnRao, prc); 389 } 390 else 391 { 392 /* No RAO region means no API region, so use the VIS region */ 393 ASSERT(pdc->prgnVis); 394 iComplexity = REGION_GetRgnBox(pdc->prgnVis, prc); 395 } 396 397 /* Unlock the DC */ 398 DC_UnlockDc(pdc); 399 400 /* Convert the rect to logical coordinates */ 401 IntDPtoLP(pdc, (LPPOINT)prc, 2); 402 403 /* Return the complexity */ 404 return iComplexity; 405 } 406 407 _Success_(return!=ERROR) 408 INT 409 APIENTRY 410 NtGdiGetAppClipBox( 411 _In_ HDC hdc, 412 _Out_ LPRECT prc) 413 { 414 RECT rect; 415 INT iComplexity; 416 417 /* Call the internal function */ 418 iComplexity = GdiGetClipBox(hdc, &rect); 419 420 if (iComplexity != ERROR) 421 { 422 _SEH2_TRY 423 { 424 ProbeForWrite(prc, sizeof(RECT), 1); 425 *prc = rect; 426 } 427 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 428 { 429 iComplexity = ERROR; 430 } 431 _SEH2_END 432 } 433 434 /* Return the complexity */ 435 return iComplexity; 436 } 437 438 INT 439 APIENTRY 440 NtGdiExcludeClipRect( 441 _In_ HDC hdc, 442 _In_ INT xLeft, 443 _In_ INT yTop, 444 _In_ INT xRight, 445 _In_ INT yBottom) 446 { 447 INT iComplexity = ERROR; 448 RECTL rect; 449 PDC pdc; 450 PREGION prgn; 451 452 /* Lock the DC */ 453 pdc = DC_LockDc(hdc); 454 if (pdc == NULL) 455 { 456 EngSetLastError(ERROR_INVALID_HANDLE); 457 return ERROR; 458 } 459 460 /* Convert coordinates to device space */ 461 rect.left = xLeft; 462 rect.top = yTop; 463 rect.right = xRight; 464 rect.bottom = yBottom; 465 RECTL_vMakeWellOrdered(&rect); 466 IntLPtoDP(pdc, (LPPOINT)&rect, 2); 467 468 prgn = IntSysCreateRectpRgnIndirect(&rect); 469 if ( prgn ) 470 { 471 iComplexity = IntSelectClipRgn( pdc, prgn, RGN_DIFF ); 472 473 REGION_Delete(prgn); 474 } 475 476 /* Emulate Windows behavior */ 477 if (iComplexity == SIMPLEREGION) 478 iComplexity = COMPLEXREGION; 479 480 /* Unlock the DC */ 481 DC_UnlockDc(pdc); 482 483 return iComplexity; 484 } 485 486 INT 487 APIENTRY 488 NtGdiIntersectClipRect( 489 _In_ HDC hdc, 490 _In_ INT xLeft, 491 _In_ INT yTop, 492 _In_ INT xRight, 493 _In_ INT yBottom) 494 { 495 INT iComplexity = ERROR; 496 RECTL rect; 497 PDC pdc; 498 PREGION prgn; 499 500 DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n", 501 hdc, xLeft, yTop, xRight, yBottom); 502 503 /* Lock the DC */ 504 pdc = DC_LockDc(hdc); 505 if (!pdc) 506 { 507 EngSetLastError(ERROR_INVALID_HANDLE); 508 return ERROR; 509 } 510 511 /* Convert coordinates to device space */ 512 rect.left = xLeft; 513 rect.top = yTop; 514 rect.right = xRight; 515 rect.bottom = yBottom; 516 RECTL_vMakeWellOrdered(&rect); 517 IntLPtoDP(pdc, (LPPOINT)&rect, 2); 518 519 prgn = IntSysCreateRectpRgnIndirect(&rect); 520 if ( prgn ) 521 { 522 iComplexity = IntSelectClipRgn( pdc, prgn, RGN_AND ); 523 524 REGION_Delete(prgn); 525 } 526 527 /* Emulate Windows behavior */ 528 if ( iComplexity == SIMPLEREGION ) 529 iComplexity = COMPLEXREGION; 530 531 /* Unlock the DC */ 532 DC_UnlockDc(pdc); 533 534 return iComplexity; 535 } 536 537 INT 538 APIENTRY 539 NtGdiOffsetClipRgn( 540 _In_ HDC hdc, 541 _In_ INT xOffset, 542 _In_ INT yOffset) 543 { 544 INT iComplexity; 545 PDC pdc; 546 POINTL apt[2]; 547 548 /* Lock the DC */ 549 pdc = DC_LockDc(hdc); 550 if (pdc == NULL) 551 { 552 if (!hdc) EngSetLastError(ERROR_INVALID_HANDLE); 553 return ERROR; 554 } 555 556 /* Check if we have a clip region */ 557 if (pdc->dclevel.prgnClip != NULL) 558 { 559 /* Convert coordinates into device space. Note that we need to convert 560 2 coordinates to account for rotation / shear / offset */ 561 apt[0].x = 0; 562 apt[0].y = 0; 563 apt[1].x = xOffset; 564 apt[1].y = yOffset; 565 IntLPtoDP(pdc, apt, 2); 566 567 /* Offset the clip region */ 568 if (!REGION_bOffsetRgn(pdc->dclevel.prgnClip, 569 apt[1].x - apt[0].x, 570 apt[1].y - apt[0].y)) 571 { 572 iComplexity = ERROR; 573 } 574 else 575 { 576 IntGdiReleaseRaoRgn(pdc); 577 UpdateVisRgn(pdc); 578 iComplexity = REGION_Complexity(pdc->dclevel.prgnClip); 579 } 580 581 /* Mark the RAO region as dirty */ 582 pdc->fs |= DC_DIRTY_RAO; 583 } 584 else 585 { 586 /* NULL means no clipping, i.e. the "whole" region */ 587 iComplexity = SIMPLEREGION; 588 } 589 590 /* Unlock the DC and return the complexity */ 591 DC_UnlockDc(pdc); 592 return iComplexity; 593 } 594 595 BOOL APIENTRY NtGdiPtVisible(HDC hDC, 596 int X, 597 int Y) 598 { 599 BOOL ret = FALSE; 600 PDC dc; 601 PREGION prgn; 602 603 if(!(dc = DC_LockDc(hDC))) 604 { 605 EngSetLastError(ERROR_INVALID_HANDLE); 606 return FALSE; 607 } 608 609 prgn = dc->prgnRao ? dc->prgnRao : dc->prgnVis; 610 611 if (prgn) 612 { 613 POINT pt = {X, Y}; 614 IntLPtoDP(dc, &pt, 1); 615 ret = REGION_PtInRegion(prgn, pt.x, pt.y); 616 } 617 618 DC_UnlockDc(dc); 619 620 return ret; 621 } 622 623 BOOL 624 APIENTRY 625 NtGdiRectVisible( 626 HDC hDC, 627 LPRECT UnsafeRect) 628 { 629 NTSTATUS Status = STATUS_SUCCESS; 630 PDC dc = DC_LockDc(hDC); 631 BOOL Result = FALSE; 632 RECTL Rect; 633 PREGION prgn; 634 635 if (!dc) 636 { 637 EngSetLastError(ERROR_INVALID_HANDLE); 638 return FALSE; 639 } 640 641 _SEH2_TRY 642 { 643 ProbeForRead(UnsafeRect, 644 sizeof(RECT), 645 1); 646 Rect = *UnsafeRect; 647 } 648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 649 { 650 Status = _SEH2_GetExceptionCode(); 651 } 652 _SEH2_END; 653 654 if(!NT_SUCCESS(Status)) 655 { 656 DC_UnlockDc(dc); 657 SetLastNtError(Status); 658 return FALSE; 659 } 660 661 if (dc->fs & DC_DIRTY_RAO) 662 CLIPPING_UpdateGCRegion(dc); 663 664 prgn = dc->prgnRao ? dc->prgnRao : dc->prgnVis; 665 if (prgn) 666 { 667 IntLPtoDP(dc, (LPPOINT)&Rect, 2); 668 Result = REGION_RectInRegion(prgn, &Rect); 669 } 670 DC_UnlockDc(dc); 671 672 return Result; 673 } 674 675 int 676 FASTCALL 677 IntGdiSetMetaRgn(PDC pDC) 678 { 679 INT Ret = ERROR; 680 681 if ( pDC->dclevel.prgnMeta ) 682 { 683 if ( pDC->dclevel.prgnClip ) 684 { 685 PREGION prgn = IntSysCreateRectpRgn(0,0,0,0); 686 if ( prgn ) 687 { 688 if (REGION_bIntersectRegion(prgn, pDC->dclevel.prgnMeta, pDC->dclevel.prgnClip)) 689 { 690 // See Restore/SaveDC 691 REGION_Delete(pDC->dclevel.prgnMeta); 692 pDC->dclevel.prgnMeta = prgn; 693 694 REGION_Delete(pDC->dclevel.prgnClip); 695 pDC->dclevel.prgnClip = NULL; 696 IntGdiReleaseRaoRgn(pDC); 697 698 Ret = REGION_Complexity(pDC->dclevel.prgnMeta); 699 } 700 else 701 REGION_Delete(prgn); 702 } 703 } 704 else 705 Ret = REGION_Complexity(pDC->dclevel.prgnMeta); 706 } 707 else 708 { 709 if ( pDC->dclevel.prgnClip ) 710 { 711 Ret = REGION_Complexity(pDC->dclevel.prgnClip); 712 pDC->dclevel.prgnMeta = pDC->dclevel.prgnClip; 713 pDC->dclevel.prgnClip = NULL; 714 } 715 else 716 Ret = SIMPLEREGION; 717 } 718 719 return Ret; 720 } 721 722 723 int APIENTRY NtGdiSetMetaRgn(HDC hDC) 724 { 725 INT Ret; 726 PDC pDC = DC_LockDc(hDC); 727 728 if (!pDC) 729 { 730 EngSetLastError(ERROR_INVALID_PARAMETER); 731 return ERROR; 732 } 733 Ret = IntGdiSetMetaRgn(pDC); 734 735 DC_UnlockDc(pDC); 736 return Ret; 737 } 738 739 VOID 740 FASTCALL 741 CLIPPING_UpdateGCRegion(PDC pDC) 742 { 743 // Moved from Release Rao. Though it still gets over written. 744 RECTL_vSetEmptyRect(&pDC->erclClip); 745 746 /* Must have VisRgn set to a valid state! */ 747 ASSERT (pDC->prgnVis); 748 #if 0 // (w2k3) This works with limitations. (w7u) ReactOS relies on Rao. 749 if ( !pDC->dclevel.prgnClip && 750 !pDC->dclevel.prgnMeta && 751 !pDC->prgnAPI) 752 { 753 if (pDC->prgnRao) 754 REGION_Delete(pDC->prgnRao); 755 pDC->prgnRao = NULL; 756 757 REGION_bOffsetRgn(pDC->prgnVis, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y); 758 759 RtlCopyMemory(&pDC->erclClip, 760 &pDC->prgnVis->rdh.rcBound, 761 sizeof(RECTL)); 762 763 IntEngUpdateClipRegion(&pDC->co, 764 pDC->prgnVis->rdh.nCount, 765 pDC->prgnVis->Buffer, 766 &pDC->erclClip); 767 768 REGION_bOffsetRgn(pDC->prgnVis, -pDC->ptlDCOrig.x, -pDC->ptlDCOrig.y); 769 770 pDC->fs &= ~DC_DIRTY_RAO; 771 UpdateVisRgn(pDC); 772 return; 773 } 774 #endif 775 if (pDC->prgnAPI) 776 { 777 REGION_Delete(pDC->prgnAPI); 778 pDC->prgnAPI = NULL; 779 } 780 781 if (pDC->dclevel.prgnMeta || pDC->dclevel.prgnClip) 782 { 783 pDC->prgnAPI = IntSysCreateRectpRgn(0,0,0,0); 784 if (!pDC->prgnAPI) 785 { 786 /* Best we can do here. Better than crashing. */ 787 ERR("Failed to allocate prgnAPI! Expect drawing issues!\n"); 788 return; 789 } 790 791 if (!pDC->dclevel.prgnMeta) 792 { 793 REGION_bCopy(pDC->prgnAPI, 794 pDC->dclevel.prgnClip); 795 } 796 else if (!pDC->dclevel.prgnClip) 797 { 798 REGION_bCopy(pDC->prgnAPI, 799 pDC->dclevel.prgnMeta); 800 } 801 else 802 { 803 REGION_bIntersectRegion(pDC->prgnAPI, 804 pDC->dclevel.prgnClip, 805 pDC->dclevel.prgnMeta); 806 } 807 } 808 809 if (pDC->prgnRao) 810 REGION_Delete(pDC->prgnRao); 811 812 pDC->prgnRao = IntSysCreateRectpRgn(0,0,0,0); 813 if (!pDC->prgnRao) 814 { 815 /* Best we can do here. Better than crashing. */ 816 ERR("Failed to allocate prgnRao! Expect drawing issues!\n"); 817 return; 818 } 819 820 if (pDC->prgnAPI) 821 { 822 REGION_bIntersectRegion(pDC->prgnRao, 823 pDC->prgnVis, 824 pDC->prgnAPI); 825 } 826 else 827 { 828 REGION_bCopy(pDC->prgnRao, 829 pDC->prgnVis); 830 } 831 832 833 REGION_bOffsetRgn(pDC->prgnRao, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y); 834 835 RtlCopyMemory(&pDC->erclClip, 836 &pDC->prgnRao->rdh.rcBound, 837 sizeof(RECTL)); 838 839 pDC->fs &= ~DC_DIRTY_RAO; 840 UpdateVisRgn(pDC); 841 842 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build 843 // the rects from region objects rects in pClipRgn->Buffer. 844 // With pDC->co.pClipRgn->Buffer, 845 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis; 846 847 IntEngUpdateClipRegion(&pDC->co, 848 pDC->prgnRao->rdh.nCount, 849 pDC->prgnRao->Buffer, 850 &pDC->erclClip); 851 852 REGION_bOffsetRgn(pDC->prgnRao, -pDC->ptlDCOrig.x, -pDC->ptlDCOrig.y); 853 } 854 855 /* EOF */ 856