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
16 IntGdiReleaseRaoRgn(PDC pDC
)
18 INT Index
= GDI_HANDLE_GET_INDEX(pDC
->BaseObject
.hHmgr
);
19 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
20 pDC
->fs
|= DC_DIRTY_RAO
;
21 Entry
->Flags
|= GDI_ENTRY_VALIDATE_VIS
; // Need to validate Vis.
26 IntGdiReleaseVisRgn(PDC pDC
)
28 IntGdiReleaseRaoRgn(pDC
);
29 REGION_Delete(pDC
->prgnVis
);
30 pDC
->prgnVis
= prgnDefault
; // Vis can not be NULL!!!
34 // Updating Vis Region Attribute for DC Attributes.
35 // BTW: This system region has an user attribute for it.
42 INT Index
= GDI_HANDLE_GET_INDEX(pdc
->BaseObject
.hHmgr
);
43 PGDI_TABLE_ENTRY pEntry
= &GdiHandleTable
->Entries
[Index
];
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
;
53 // Selecting Vis Region.
63 if (!(dc
= DC_LockDc(hdc
)))
65 EngSetLastError(ERROR_INVALID_HANDLE
);
71 DPRINT1("SVR: Setting NULL Region\n");
72 IntGdiReleaseVisRgn(dc
);
73 IntSetDefaultRegion(dc
);
78 dc
->fs
|= DC_DIRTY_RAO
;
80 ASSERT(dc
->prgnVis
!= NULL
);
83 REGION_bCopy(dc
->prgnVis
, prgn
);
84 REGION_bOffsetRgn(dc
->prgnVis
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
89 _Success_(return!=ERROR
)
98 PREGION prgnNClip
, prgnOrigClip
= dc
->dclevel
.prgnClip
;
101 // No Coping Regions and no intersecting Regions or an User calling w NULL Region or have the Original Clip Region.
103 if (fnMode
!= RGN_COPY
&& (fnMode
!= RGN_AND
|| !prgn
|| prgnOrigClip
))
105 prgnNClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
107 // Have Original Clip Region.
110 // This will fail on NULL prgn.
111 Ret
= IntGdiCombineRgn(prgnNClip
, prgnOrigClip
, prgn
, fnMode
);
115 REGION_Delete(prgnOrigClip
);
116 dc
->dclevel
.prgnClip
= prgnNClip
;
117 IntGdiReleaseRaoRgn(dc
);
120 REGION_Delete(prgnNClip
);
122 else // NULL Original Clip Region, setup a new one and process mode.
129 // See IntSetDefaultRegion.
133 rcl
.right
= dc
->dclevel
.sizl
.cx
;
134 rcl
.bottom
= dc
->dclevel
.sizl
.cy
;
136 //EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock);
137 if (dc
->ppdev
->flFlags
& PDEV_META_DEVICE
)
139 pSurface
= dc
->dclevel
.pSurface
;
140 if (pSurface
&& pSurface
->flags
& PDEV_SURFACE
)
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
;
148 //EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
150 rcl
.left
+= dc
->ptlDCOrig
.x
;
151 rcl
.top
+= dc
->ptlDCOrig
.y
;
152 rcl
.right
+= dc
->ptlDCOrig
.x
;
153 rcl
.bottom
+= dc
->ptlDCOrig
.y
;
155 REGION_GetRgnBox(dc
->prgnVis
, &rcl
);
157 prgnClip
= IntSysCreateRectpRgnIndirect(&rcl
);
159 Ret
= IntGdiCombineRgn(prgnNClip
, prgnClip
, prgn
, fnMode
);
163 dc
->dclevel
.prgnClip
= prgnNClip
;
164 IntGdiReleaseRaoRgn(dc
);
167 REGION_Delete(prgnNClip
);
169 REGION_Delete(prgnClip
);
174 // Fall through to normal RectOS mode.
177 // Handle NULL Region and Original Clip Region.
183 REGION_Delete(dc
->dclevel
.prgnClip
);
184 dc
->dclevel
.prgnClip
= NULL
;
185 IntGdiReleaseRaoRgn(dc
);
191 // Combine the new Clip region with original Clip and caller Region.
194 (Ret
= IntGdiCombineRgn(prgnOrigClip
, prgn
, NULL
, RGN_COPY
)) ) // Clip could fail.
196 IntGdiReleaseRaoRgn(dc
);
198 else // NULL original Clip, just copy caller region to new.
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
);
210 // Call from Gdi Batch Subsystem.
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.
216 _Success_(return!=ERROR
)
219 IntGdiExtSelectClipRect(
227 BOOL NoRegion
= fnMode
& GDIBS_NORECT
;
229 fnMode
&= ~GDIBS_NORECT
;
231 if (NoRegion
) // NULL Region.
233 if (fnMode
== RGN_COPY
)
235 Ret
= IntSelectClipRgn( dc
, NULL
, RGN_COPY
);
237 if (dc
->fs
& DC_DIRTY_RAO
)
238 CLIPPING_UpdateGCRegion(dc
);
240 if (Ret
) // Copy? Return Vis complexity.
241 Ret
= REGION_Complexity(dc
->prgnVis
);
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
) )
248 REGION_GetRgnBox(dc
->dclevel
.prgnClip
, &rect
);
250 if (prcl
->left
== rect
.left
&&
251 prcl
->top
== rect
.top
&&
252 prcl
->right
== rect
.right
&&
253 prcl
->bottom
== rect
.bottom
)
255 return REGION_Complexity( dc
->prgnRao
? dc
->prgnRao
: dc
->prgnVis
);
259 prgn
= IntSysCreateRectpRgnIndirect(prcl
);
261 Ret
= IntSelectClipRgn( dc
, prgn
, fnMode
);
263 if (dc
->fs
& DC_DIRTY_RAO
)
264 CLIPPING_UpdateGCRegion(dc
);
266 if (Ret
) // In this case NtGdiExtSelectClipRgn tests pass.
267 Ret
= REGION_Complexity( dc
->prgnRao
? dc
->prgnRao
: dc
->prgnVis
);
274 _Success_(return!=ERROR
)
277 IntGdiExtSelectClipRgn(
286 if (fnMode
== RGN_COPY
)
288 if ((Ret
= IntSelectClipRgn( dc
, NULL
, RGN_COPY
)))
289 Ret
= REGION_Complexity(dc
->prgnVis
);
294 if ((Ret
= IntSelectClipRgn( dc
, prgn
, fnMode
)))
296 DPRINT("IntGdiExtSelectClipRgn A %d\n",Ret
);
297 // Update the Rao, it must be this way for now.
298 if (dc
->fs
& DC_DIRTY_RAO
)
299 CLIPPING_UpdateGCRegion(dc
);
301 Ret
= REGION_Complexity( dc
->prgnRao
? dc
->prgnRao
: dc
->prgnVis
);
302 DPRINT("IntGdiExtSelectClipRgn B %d\n",Ret
);
310 NtGdiExtSelectClipRgn(
319 if ( fnMode
< RGN_AND
|| fnMode
> RGN_COPY
)
321 EngSetLastError(ERROR_INVALID_PARAMETER
);
325 if (!(dc
= DC_LockDc(hDC
)))
327 EngSetLastError(ERROR_INVALID_HANDLE
);
331 prgn
= REGION_LockRgn(hrgn
);
333 if ((prgn
== NULL
) && (fnMode
!= RGN_COPY
))
335 //EngSetLastError(ERROR_INVALID_HANDLE); doesn't set this.
340 #if 0 // Testing GDI Batch.
344 REGION_GetRgnBox(prgn
, &rcl
);
346 fnMode
|= GDIBS_NORECT
;
347 retval
= IntGdiExtSelectClipRect(dc
, &rcl
, fnMode
);
350 retval
= IntGdiExtSelectClipRgn(dc
, prgn
, fnMode
);
355 REGION_UnlockRgn(prgn
);
361 _Success_(return!=ERROR
)
372 pdc
= DC_LockDc(hdc
);
378 /* Update RAO region if necessary */
379 if (pdc
->fs
& DC_DIRTY_RAO
)
380 CLIPPING_UpdateGCRegion(pdc
);
382 /* Check if we have a RAO region (intersection of API and VIS region) */
385 /* We have a RAO region, use it */
386 iComplexity
= REGION_GetRgnBox(pdc
->prgnRao
, prc
);
390 /* No RAO region means no API region, so use the VIS region */
391 ASSERT(pdc
->prgnVis
);
392 iComplexity
= REGION_GetRgnBox(pdc
->prgnVis
, prc
);
398 /* Convert the rect to logical coordinates */
399 IntDPtoLP(pdc
, (LPPOINT
)prc
, 2);
401 /* Return the complexity */
405 _Success_(return!=ERROR
)
415 /* Call the internal function */
416 iComplexity
= GdiGetClipBox(hdc
, &rect
);
418 if (iComplexity
!= ERROR
)
422 ProbeForWrite(prc
, sizeof(RECT
), 1);
425 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
432 /* Return the complexity */
438 NtGdiExcludeClipRect(
445 INT iComplexity
= ERROR
;
451 pdc
= DC_LockDc(hdc
);
454 EngSetLastError(ERROR_INVALID_HANDLE
);
458 /* Convert coordinates to device space */
462 rect
.bottom
= yBottom
;
463 RECTL_vMakeWellOrdered(&rect
);
464 IntLPtoDP(pdc
, (LPPOINT
)&rect
, 2);
466 prgn
= IntSysCreateRectpRgnIndirect(&rect
);
469 iComplexity
= IntSelectClipRgn( pdc
, prgn
, RGN_DIFF
);
474 /* Emulate Windows behavior */
475 if (iComplexity
== SIMPLEREGION
)
476 iComplexity
= COMPLEXREGION
;
486 NtGdiIntersectClipRect(
493 INT iComplexity
= ERROR
;
498 DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
499 hdc
, xLeft
, yTop
, xRight
, yBottom
);
502 pdc
= DC_LockDc(hdc
);
505 EngSetLastError(ERROR_INVALID_HANDLE
);
509 /* Convert coordinates to device space */
513 rect
.bottom
= yBottom
;
514 RECTL_vMakeWellOrdered(&rect
);
515 IntLPtoDP(pdc
, (LPPOINT
)&rect
, 2);
517 prgn
= IntSysCreateRectpRgnIndirect(&rect
);
520 iComplexity
= IntSelectClipRgn( pdc
, prgn
, RGN_AND
);
525 /* Emulate Windows behavior */
526 if ( iComplexity
== SIMPLEREGION
)
527 iComplexity
= COMPLEXREGION
;
547 pdc
= DC_LockDc(hdc
);
550 if (!hdc
) EngSetLastError(ERROR_INVALID_HANDLE
);
554 /* Check if we have a clip region */
555 if (pdc
->dclevel
.prgnClip
!= NULL
)
557 /* Convert coordinates into device space. Note that we need to convert
558 2 coordinates to account for rotation / shear / offset */
563 IntLPtoDP(pdc
, apt
, 2);
565 /* Offset the clip region */
566 if (!REGION_bOffsetRgn(pdc
->dclevel
.prgnClip
,
568 apt
[1].y
- apt
[0].y
))
574 IntGdiReleaseRaoRgn(pdc
);
576 iComplexity
= REGION_Complexity(pdc
->dclevel
.prgnClip
);
579 /* Mark the RAO region as dirty */
580 pdc
->fs
|= DC_DIRTY_RAO
;
584 /* NULL means no clipping, i.e. the "whole" region */
585 iComplexity
= SIMPLEREGION
;
588 /* Unlock the DC and return the complexity */
593 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
601 if(!(dc
= DC_LockDc(hDC
)))
603 EngSetLastError(ERROR_INVALID_HANDLE
);
607 prgn
= dc
->prgnRao
? dc
->prgnRao
: dc
->prgnVis
;
612 IntLPtoDP(dc
, &pt
, 1);
613 ret
= REGION_PtInRegion(prgn
, pt
.x
, pt
.y
);
627 NTSTATUS Status
= STATUS_SUCCESS
;
628 PDC dc
= DC_LockDc(hDC
);
635 EngSetLastError(ERROR_INVALID_HANDLE
);
641 ProbeForRead(UnsafeRect
,
646 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
648 Status
= _SEH2_GetExceptionCode();
652 if(!NT_SUCCESS(Status
))
655 SetLastNtError(Status
);
659 if (dc
->fs
& DC_DIRTY_RAO
)
660 CLIPPING_UpdateGCRegion(dc
);
662 prgn
= dc
->prgnRao
? dc
->prgnRao
: dc
->prgnVis
;
665 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
666 Result
= REGION_RectInRegion(prgn
, &Rect
);
675 IntGdiSetMetaRgn(PDC pDC
)
679 if ( pDC
->dclevel
.prgnMeta
)
681 if ( pDC
->dclevel
.prgnClip
)
683 PREGION prgn
= IntSysCreateRectpRgn(0,0,0,0);
686 if (REGION_bIntersectRegion(prgn
, pDC
->dclevel
.prgnMeta
, pDC
->dclevel
.prgnClip
))
688 // See Restore/SaveDC
689 REGION_Delete(pDC
->dclevel
.prgnMeta
);
690 pDC
->dclevel
.prgnMeta
= prgn
;
692 REGION_Delete(pDC
->dclevel
.prgnClip
);
693 pDC
->dclevel
.prgnClip
= NULL
;
694 IntGdiReleaseRaoRgn(pDC
);
696 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
703 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
707 if ( pDC
->dclevel
.prgnClip
)
709 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
710 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
711 pDC
->dclevel
.prgnClip
= NULL
;
721 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
724 PDC pDC
= DC_LockDc(hDC
);
728 EngSetLastError(ERROR_INVALID_PARAMETER
);
731 Ret
= IntGdiSetMetaRgn(pDC
);
739 CLIPPING_UpdateGCRegion(PDC pDC
)
741 // Moved from Release Rao. Though it still gets over written.
742 RECTL_vSetEmptyRect(&pDC
->erclClip
);
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
&&
752 REGION_Delete(pDC
->prgnRao
);
755 REGION_bOffsetRgn(pDC
->prgnVis
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
757 RtlCopyMemory(&pDC
->erclClip
,
758 &pDC
->prgnVis
->rdh
.rcBound
,
761 IntEngUpdateClipRegion(&pDC
->co
,
762 pDC
->prgnVis
->rdh
.nCount
,
763 pDC
->prgnVis
->Buffer
,
766 REGION_bOffsetRgn(pDC
->prgnVis
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);
768 pDC
->fs
&= ~DC_DIRTY_RAO
;
775 REGION_Delete(pDC
->prgnAPI
);
780 REGION_Delete(pDC
->prgnRao
);
782 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
784 ASSERT(pDC
->prgnRao
);
786 if (pDC
->dclevel
.prgnMeta
|| pDC
->dclevel
.prgnClip
)
788 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
789 if (!pDC
->dclevel
.prgnMeta
)
791 REGION_bCopy(pDC
->prgnAPI
,
792 pDC
->dclevel
.prgnClip
);
794 else if (!pDC
->dclevel
.prgnClip
)
796 REGION_bCopy(pDC
->prgnAPI
,
797 pDC
->dclevel
.prgnMeta
);
801 REGION_bIntersectRegion(pDC
->prgnAPI
,
802 pDC
->dclevel
.prgnClip
,
803 pDC
->dclevel
.prgnMeta
);
809 REGION_bIntersectRegion(pDC
->prgnRao
,
815 REGION_bCopy(pDC
->prgnRao
,
820 REGION_bOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
822 RtlCopyMemory(&pDC
->erclClip
,
823 &pDC
->prgnRao
->rdh
.rcBound
,
826 pDC
->fs
&= ~DC_DIRTY_RAO
;
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;
834 IntEngUpdateClipRegion(&pDC
->co
,
835 pDC
->prgnRao
->rdh
.nCount
,
836 pDC
->prgnRao
->Buffer
,
839 REGION_bOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);