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
,
232 /* We don't have a clip region yet, create an empty region */
233 pdc
->dclevel
.prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
234 if (pdc
->dclevel
.prgnClip
== NULL
)
240 /* Subtract the rect from the VIS region */
241 iComplexity
= REGION_SubtractRectFromRgn(pdc
->dclevel
.prgnClip
,
247 /* Emulate Windows behavior */
248 if (iComplexity
== SIMPLEREGION
)
249 iComplexity
= COMPLEXREGION
;
251 /* If we succeeded, mark the RAO region as dirty */
252 if (iComplexity
!= ERROR
)
253 pdc
->fs
|= DC_FLAG_DIRTY_RAO
;
263 NtGdiIntersectClipRect(
275 DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
276 hdc
, xLeft
, yTop
, xRight
, yBottom
);
279 pdc
= DC_LockDc(hdc
);
282 EngSetLastError(ERROR_INVALID_HANDLE
);
286 /* Convert coordinates to device space */
290 rect
.bottom
= yBottom
;
291 IntLPtoDP(pdc
, (LPPOINT
)&rect
, 2);
293 /* Check if we already have a clip region */
294 if (pdc
->dclevel
.prgnClip
!= NULL
)
296 /* We have a region, crop it */
297 iComplexity
= REGION_CropAndOffsetRegion(pdc
->dclevel
.prgnClip
,
298 pdc
->dclevel
.prgnClip
,
304 /* We don't have a region yet, allocate a new one */
305 prgnNew
= IntSysCreateRectpRgnIndirect(&rect
);
312 /* Set the new region */
313 pdc
->dclevel
.prgnClip
= prgnNew
;
314 iComplexity
= SIMPLEREGION
;
318 /* If we succeeded, mark the RAO region as dirty */
319 if (iComplexity
!= ERROR
)
320 pdc
->fs
|= DC_FLAG_DIRTY_RAO
;
328 int APIENTRY
NtGdiOffsetClipRgn(HDC hDC
,
335 if(!(dc
= DC_LockDc(hDC
)))
337 EngSetLastError(ERROR_INVALID_HANDLE
);
341 if(dc
->dclevel
.prgnClip
!= NULL
)
343 Result
= IntGdiOffsetRgn(dc
->dclevel
.prgnClip
,
346 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
357 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
364 if(!(dc
= DC_LockDc(hDC
)))
366 EngSetLastError(ERROR_INVALID_HANDLE
);
373 IntLPtoDP(dc
, &pt
, 1);
374 ret
= REGION_PtInRegion(dc
->prgnRao
, pt
.x
, pt
.y
);
388 NTSTATUS Status
= STATUS_SUCCESS
;
389 PDC dc
= DC_LockDc(hDC
);
395 EngSetLastError(ERROR_INVALID_HANDLE
);
401 ProbeForRead(UnsafeRect
,
406 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
408 Status
= _SEH2_GetExceptionCode();
412 if(!NT_SUCCESS(Status
))
415 SetLastNtError(Status
);
419 if (dc
->fs
& DC_FLAG_DIRTY_RAO
)
420 CLIPPING_UpdateGCRegion(dc
);
424 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
425 Result
= REGION_RectInRegion(dc
->prgnRao
, &Rect
);
434 IntGdiSetMetaRgn(PDC pDC
)
438 if ( pDC
->dclevel
.prgnMeta
)
440 if ( pDC
->dclevel
.prgnClip
)
442 Ret
= IntGdiCombineRgn(pDC
->dclevel
.prgnMeta
, pDC
->dclevel
.prgnMeta
, pDC
->dclevel
.prgnClip
, RGN_AND
);
445 REGION_Delete(pDC
->dclevel
.prgnClip
);
446 pDC
->dclevel
.prgnClip
= NULL
;
447 IntGdiReleaseRaoRgn(pDC
);
451 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
455 if ( pDC
->dclevel
.prgnClip
)
457 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
458 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
459 pDC
->dclevel
.prgnClip
= NULL
;
466 pDC
->fs
|= DC_FLAG_DIRTY_RAO
;
472 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
475 PDC pDC
= DC_LockDc(hDC
);
479 EngSetLastError(ERROR_INVALID_PARAMETER
);
482 Ret
= IntGdiSetMetaRgn(pDC
);
490 CLIPPING_UpdateGCRegion(PDC pDC
)
492 /* Must have VisRgn set to a valid state! */
493 ASSERT (pDC
->prgnVis
);
497 REGION_Delete(pDC
->prgnAPI
);
502 REGION_Delete(pDC
->prgnRao
);
504 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
506 ASSERT(pDC
->prgnRao
);
508 if (pDC
->dclevel
.prgnMeta
|| pDC
->dclevel
.prgnClip
)
510 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
511 if (!pDC
->dclevel
.prgnMeta
)
513 IntGdiCombineRgn(pDC
->prgnAPI
,
514 pDC
->dclevel
.prgnClip
,
518 else if (!pDC
->dclevel
.prgnClip
)
520 IntGdiCombineRgn(pDC
->prgnAPI
,
521 pDC
->dclevel
.prgnMeta
,
527 IntGdiCombineRgn(pDC
->prgnAPI
,
528 pDC
->dclevel
.prgnClip
,
529 pDC
->dclevel
.prgnMeta
,
536 IntGdiCombineRgn(pDC
->prgnRao
,
543 IntGdiCombineRgn(pDC
->prgnRao
,
550 IntGdiOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
552 RtlCopyMemory(&pDC
->erclClip
,
553 &pDC
->prgnRao
->rdh
.rcBound
,
556 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
558 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
559 // the rects from region objects rects in pClipRgn->Buffer.
560 // With pDC->co.pClipRgn->Buffer,
561 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
563 IntEngUpdateClipRegion(&pDC
->co
,
564 pDC
->prgnRao
->rdh
.nCount
,
565 pDC
->prgnRao
->Buffer
,
568 IntGdiOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);