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