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