2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Clip region functions
5 * FILE: subsystems/win32/win32k/objects/cliprgn.c
22 if (!(dc
= DC_LockDc(hdc
)))
24 EngSetLastError(ERROR_INVALID_HANDLE
);
28 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
30 ASSERT(dc
->prgnVis
!= NULL
);
33 IntGdiCombineRgn(dc
->prgnVis
, prgn
, NULL
, RGN_COPY
);
34 IntGdiOffsetRgn(dc
->prgnVis
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
42 IntGdiExtSelectClipRgn(
47 if (fnMode
== RGN_COPY
)
51 if (dc
->dclevel
.prgnClip
!= NULL
)
53 REGION_Delete(dc
->dclevel
.prgnClip
);
54 dc
->dclevel
.prgnClip
= NULL
;
55 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
60 if (!dc
->dclevel
.prgnClip
)
61 dc
->dclevel
.prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
63 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
65 return IntGdiCombineRgn(dc
->dclevel
.prgnClip
, prgn
, NULL
, RGN_COPY
);
70 if (!dc
->dclevel
.prgnClip
)
74 REGION_GetRgnBox(dc
->prgnVis
, &rect
);
75 dc
->dclevel
.prgnClip
= IntSysCreateRectpRgnIndirect(&rect
);
78 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
80 return IntGdiCombineRgn(dc
->dclevel
.prgnClip
, dc
->dclevel
.prgnClip
, prgn
, fnMode
);
86 NtGdiExtSelectClipRgn(
95 if (!(dc
= DC_LockDc(hDC
)))
97 EngSetLastError(ERROR_INVALID_HANDLE
);
101 prgn
= REGION_LockRgn(hrgn
);
103 if ((prgn
== NULL
) && (fnMode
!= RGN_COPY
))
105 EngSetLastError(ERROR_INVALID_HANDLE
);
110 retval
= IntGdiExtSelectClipRgn(dc
, prgn
, fnMode
);
114 REGION_UnlockRgn(prgn
);
130 pdc
= DC_LockDc(hdc
);
136 /* Update RAO region if necessary */
137 if (pdc
->fs
& DC_FLAG_DIRTY_RAO
)
138 CLIPPING_UpdateGCRegion(pdc
);
140 /* Check if we have a RAO region (intersection of API and VIS region) */
143 /* We have a RAO region, use it */
144 iComplexity
= REGION_GetRgnBox(pdc
->prgnRao
, prc
);
148 /* No RAO region means no API region, so use the VIS region */
149 ASSERT(pdc
->prgnVis
);
150 iComplexity
= REGION_GetRgnBox(pdc
->prgnVis
, prc
);
156 /* Convert the rect to logical coordinates */
157 IntDPtoLP(pdc
, (LPPOINT
)prc
, 2);
159 /* Return the complexity */
172 /* Call the internal function */
173 iComplexity
= GdiGetClipBox(hdc
, &rect
);
175 if (iComplexity
!= ERROR
)
179 ProbeForWrite(prc
, sizeof(RECT
), 1);
182 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
189 /* Return the complexity */
195 NtGdiExcludeClipRect(
207 pdc
= DC_LockDc(hdc
);
210 EngSetLastError(ERROR_INVALID_HANDLE
);
214 /* Convert coordinates to device space */
218 rect
.bottom
= yBottom
;
219 RECTL_vMakeWellOrdered(&rect
);
220 IntLPtoDP(pdc
, (LPPOINT
)&rect
, 2);
222 /* Check if we already have a clip region */
223 if (pdc
->dclevel
.prgnClip
!= NULL
)
225 /* We have a region, subtract the rect */
226 iComplexity
= REGION_SubtractRectFromRgn(pdc
->dclevel
.prgnClip
,
227 pdc
->dclevel
.prgnClip
,
230 /* Emulate Windows behavior */
231 if (iComplexity
== SIMPLEREGION
)
232 iComplexity
= COMPLEXREGION
;
236 /* Check if the rect intersects with the window rect */
237 if (RECTL_bIntersectRect(&rect
, &rect
, &pdc
->erclWindow
))
239 /* It does. In this case create an empty region */
240 pdc
->dclevel
.prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
241 iComplexity
= NULLREGION
;
245 /* Otherwise, emulate strange Windows behavior... */
246 pdc
->dclevel
.prgnClip
= IntSysCreateRectpRgn(0, 0, 1, 1);
247 iComplexity
= COMPLEXREGION
;
250 /* Check if creating the region failed */
251 if (pdc
->dclevel
.prgnClip
== NULL
)
253 /* Return error code */
258 /* If we succeeded, mark the RAO region as dirty */
259 if (iComplexity
!= ERROR
)
260 pdc
->fs
|= DC_FLAG_DIRTY_RAO
;
270 NtGdiIntersectClipRect(
282 DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
283 hdc
, xLeft
, yTop
, xRight
, yBottom
);
286 pdc
= DC_LockDc(hdc
);
289 EngSetLastError(ERROR_INVALID_HANDLE
);
293 /* Convert coordinates to device space */
297 rect
.bottom
= yBottom
;
298 IntLPtoDP(pdc
, (LPPOINT
)&rect
, 2);
300 /* Check if we already have a clip region */
301 if (pdc
->dclevel
.prgnClip
!= NULL
)
303 /* We have a region, crop it */
304 iComplexity
= REGION_CropAndOffsetRegion(pdc
->dclevel
.prgnClip
,
305 pdc
->dclevel
.prgnClip
,
311 /* We don't have a region yet, allocate a new one */
312 prgnNew
= IntSysCreateRectpRgnIndirect(&rect
);
319 /* Set the new region */
320 pdc
->dclevel
.prgnClip
= prgnNew
;
321 iComplexity
= SIMPLEREGION
;
325 /* If we succeeded, mark the RAO region as dirty */
326 if (iComplexity
!= ERROR
)
327 pdc
->fs
|= DC_FLAG_DIRTY_RAO
;
335 int APIENTRY
NtGdiOffsetClipRgn(HDC hDC
,
342 if(!(dc
= DC_LockDc(hDC
)))
344 EngSetLastError(ERROR_INVALID_HANDLE
);
348 if(dc
->dclevel
.prgnClip
!= NULL
)
350 Result
= IntGdiOffsetRgn(dc
->dclevel
.prgnClip
,
353 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
364 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
371 if(!(dc
= DC_LockDc(hDC
)))
373 EngSetLastError(ERROR_INVALID_HANDLE
);
380 IntLPtoDP(dc
, &pt
, 1);
381 ret
= REGION_PtInRegion(dc
->prgnRao
, pt
.x
, pt
.y
);
395 NTSTATUS Status
= STATUS_SUCCESS
;
396 PDC dc
= DC_LockDc(hDC
);
402 EngSetLastError(ERROR_INVALID_HANDLE
);
408 ProbeForRead(UnsafeRect
,
413 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
415 Status
= _SEH2_GetExceptionCode();
419 if(!NT_SUCCESS(Status
))
422 SetLastNtError(Status
);
426 if (dc
->fs
& DC_FLAG_DIRTY_RAO
)
427 CLIPPING_UpdateGCRegion(dc
);
431 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
432 Result
= REGION_RectInRegion(dc
->prgnRao
, &Rect
);
441 IntGdiSetMetaRgn(PDC pDC
)
445 if ( pDC
->dclevel
.prgnMeta
)
447 if ( pDC
->dclevel
.prgnClip
)
449 Ret
= IntGdiCombineRgn(pDC
->dclevel
.prgnMeta
, pDC
->dclevel
.prgnMeta
, pDC
->dclevel
.prgnClip
, RGN_AND
);
452 REGION_Delete(pDC
->dclevel
.prgnClip
);
453 pDC
->dclevel
.prgnClip
= NULL
;
454 IntGdiReleaseRaoRgn(pDC
);
458 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
462 if ( pDC
->dclevel
.prgnClip
)
464 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
465 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
466 pDC
->dclevel
.prgnClip
= NULL
;
473 pDC
->fs
|= DC_FLAG_DIRTY_RAO
;
479 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
482 PDC pDC
= DC_LockDc(hDC
);
486 EngSetLastError(ERROR_INVALID_PARAMETER
);
489 Ret
= IntGdiSetMetaRgn(pDC
);
497 CLIPPING_UpdateGCRegion(PDC pDC
)
499 /* Must have VisRgn set to a valid state! */
500 ASSERT (pDC
->prgnVis
);
504 REGION_Delete(pDC
->prgnAPI
);
509 REGION_Delete(pDC
->prgnRao
);
511 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
513 ASSERT(pDC
->prgnRao
);
515 if (pDC
->dclevel
.prgnMeta
|| pDC
->dclevel
.prgnClip
)
517 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
518 if (!pDC
->dclevel
.prgnMeta
)
520 IntGdiCombineRgn(pDC
->prgnAPI
,
521 pDC
->dclevel
.prgnClip
,
525 else if (!pDC
->dclevel
.prgnClip
)
527 IntGdiCombineRgn(pDC
->prgnAPI
,
528 pDC
->dclevel
.prgnMeta
,
534 IntGdiCombineRgn(pDC
->prgnAPI
,
535 pDC
->dclevel
.prgnClip
,
536 pDC
->dclevel
.prgnMeta
,
543 IntGdiCombineRgn(pDC
->prgnRao
,
550 IntGdiCombineRgn(pDC
->prgnRao
,
557 IntGdiOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
559 RtlCopyMemory(&pDC
->erclClip
,
560 &pDC
->prgnRao
->rdh
.rcBound
,
563 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
565 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
566 // the rects from region objects rects in pClipRgn->Buffer.
567 // With pDC->co.pClipRgn->Buffer,
568 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
570 IntEngUpdateClipRegion(&pDC
->co
,
571 pDC
->prgnRao
->rdh
.nCount
,
572 pDC
->prgnRao
->Buffer
,
575 IntGdiOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);