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_FLAG_DIRTY_RAO
;
21 Entry
->Flags
|= GDI_ENTRY_VALIDATE_VIS
;
22 RECTL_vSetEmptyRect(&pDC
->erclClip
);
23 REGION_Delete(pDC
->prgnRao
);
29 IntGdiReleaseVisRgn(PDC pDC
)
31 INT Index
= GDI_HANDLE_GET_INDEX(pDC
->BaseObject
.hHmgr
);
32 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
33 pDC
->fs
|= DC_FLAG_DIRTY_RAO
;
34 Entry
->Flags
|= GDI_ENTRY_VALIDATE_VIS
;
35 RECTL_vSetEmptyRect(&pDC
->erclClip
);
36 REGION_Delete(pDC
->prgnVis
);
37 pDC
->prgnVis
= prgnDefault
;
48 if (!(dc
= DC_LockDc(hdc
)))
50 EngSetLastError(ERROR_INVALID_HANDLE
);
54 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
56 ASSERT(dc
->prgnVis
!= NULL
);
59 IntGdiCombineRgn(dc
->prgnVis
, prgn
, NULL
, RGN_COPY
);
60 REGION_bOffsetRgn(dc
->prgnVis
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
68 IntGdiExtSelectClipRgn(
73 if (fnMode
== RGN_COPY
)
77 if (dc
->dclevel
.prgnClip
!= NULL
)
79 REGION_Delete(dc
->dclevel
.prgnClip
);
80 dc
->dclevel
.prgnClip
= NULL
;
81 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
86 if (!dc
->dclevel
.prgnClip
)
87 dc
->dclevel
.prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
89 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
91 return IntGdiCombineRgn(dc
->dclevel
.prgnClip
, prgn
, NULL
, RGN_COPY
);
96 if (!dc
->dclevel
.prgnClip
)
100 REGION_GetRgnBox(dc
->prgnVis
, &rect
);
101 dc
->dclevel
.prgnClip
= IntSysCreateRectpRgnIndirect(&rect
);
104 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
106 return IntGdiCombineRgn(dc
->dclevel
.prgnClip
, dc
->dclevel
.prgnClip
, prgn
, fnMode
);
112 NtGdiExtSelectClipRgn(
121 if (!(dc
= DC_LockDc(hDC
)))
123 EngSetLastError(ERROR_INVALID_HANDLE
);
127 prgn
= REGION_LockRgn(hrgn
);
129 if ((prgn
== NULL
) && (fnMode
!= RGN_COPY
))
131 EngSetLastError(ERROR_INVALID_HANDLE
);
136 retval
= IntGdiExtSelectClipRgn(dc
, prgn
, fnMode
);
140 REGION_UnlockRgn(prgn
);
146 _Success_(return!=ERROR
)
157 pdc
= DC_LockDc(hdc
);
163 /* Update RAO region if necessary */
164 if (pdc
->fs
& DC_FLAG_DIRTY_RAO
)
165 CLIPPING_UpdateGCRegion(pdc
);
167 /* Check if we have a RAO region (intersection of API and VIS region) */
170 /* We have a RAO region, use it */
171 iComplexity
= REGION_GetRgnBox(pdc
->prgnRao
, prc
);
175 /* No RAO region means no API region, so use the VIS region */
176 ASSERT(pdc
->prgnVis
);
177 iComplexity
= REGION_GetRgnBox(pdc
->prgnVis
, prc
);
183 /* Convert the rect to logical coordinates */
184 IntDPtoLP(pdc
, (LPPOINT
)prc
, 2);
186 /* Return the complexity */
190 _Success_(return!=ERROR
)
200 /* Call the internal function */
201 iComplexity
= GdiGetClipBox(hdc
, &rect
);
203 if (iComplexity
!= ERROR
)
207 ProbeForWrite(prc
, sizeof(RECT
), 1);
210 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
217 /* Return the complexity */
223 NtGdiExcludeClipRect(
235 pdc
= DC_LockDc(hdc
);
238 EngSetLastError(ERROR_INVALID_HANDLE
);
242 /* Convert coordinates to device space */
246 rect
.bottom
= yBottom
;
247 RECTL_vMakeWellOrdered(&rect
);
248 IntLPtoDP(pdc
, (LPPOINT
)&rect
, 2);
250 /* Check if we already have a clip region */
251 if (pdc
->dclevel
.prgnClip
!= NULL
)
253 /* We have a region, subtract the rect */
254 iComplexity
= REGION_SubtractRectFromRgn(pdc
->dclevel
.prgnClip
,
255 pdc
->dclevel
.prgnClip
,
260 /* We don't have a clip region yet, create an empty region */
261 pdc
->dclevel
.prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
262 if (pdc
->dclevel
.prgnClip
== NULL
)
268 /* Subtract the rect from the VIS region */
269 iComplexity
= REGION_SubtractRectFromRgn(pdc
->dclevel
.prgnClip
,
275 /* Emulate Windows behavior */
276 if (iComplexity
== SIMPLEREGION
)
277 iComplexity
= COMPLEXREGION
;
279 /* If we succeeded, mark the RAO region as dirty */
280 if (iComplexity
!= ERROR
)
281 pdc
->fs
|= DC_FLAG_DIRTY_RAO
;
291 NtGdiIntersectClipRect(
303 DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
304 hdc
, xLeft
, yTop
, xRight
, yBottom
);
307 pdc
= DC_LockDc(hdc
);
310 EngSetLastError(ERROR_INVALID_HANDLE
);
314 /* Convert coordinates to device space */
318 rect
.bottom
= yBottom
;
319 IntLPtoDP(pdc
, (LPPOINT
)&rect
, 2);
321 /* Check if we already have a clip region */
322 if (pdc
->dclevel
.prgnClip
!= NULL
)
324 /* We have a region, crop it */
325 iComplexity
= REGION_CropRegion(pdc
->dclevel
.prgnClip
,
326 pdc
->dclevel
.prgnClip
,
331 /* We don't have a region yet, allocate a new one */
332 prgnNew
= IntSysCreateRectpRgnIndirect(&rect
);
339 /* Set the new region */
340 pdc
->dclevel
.prgnClip
= prgnNew
;
341 iComplexity
= SIMPLEREGION
;
345 /* If we succeeded, mark the RAO region as dirty */
346 if (iComplexity
!= ERROR
)
347 pdc
->fs
|= DC_FLAG_DIRTY_RAO
;
367 pdc
= DC_LockDc(hdc
);
373 /* Check if we have a clip region */
374 if (pdc
->dclevel
.prgnClip
!= NULL
)
376 /* Convert coordinates into device space. Note that we need to convert
377 2 coordinates to account for rotation / shear / offset */
382 IntLPtoDP(pdc
, &apt
, 2);
384 /* Offset the clip region */
385 if (!REGION_bOffsetRgn(pdc
->dclevel
.prgnClip
,
387 apt
[1].y
- apt
[0].y
))
393 iComplexity
= REGION_Complexity(pdc
->dclevel
.prgnClip
);
396 /* Mark the RAO region as dirty */
397 pdc
->fs
|= DC_FLAG_DIRTY_RAO
;
401 /* NULL means no clipping, i.e. the "whole" region */
402 iComplexity
= SIMPLEREGION
;
405 /* Unlock the DC and return the complexity */
410 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
417 if(!(dc
= DC_LockDc(hDC
)))
419 EngSetLastError(ERROR_INVALID_HANDLE
);
426 IntLPtoDP(dc
, &pt
, 1);
427 ret
= REGION_PtInRegion(dc
->prgnRao
, pt
.x
, pt
.y
);
441 NTSTATUS Status
= STATUS_SUCCESS
;
442 PDC dc
= DC_LockDc(hDC
);
448 EngSetLastError(ERROR_INVALID_HANDLE
);
454 ProbeForRead(UnsafeRect
,
459 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
461 Status
= _SEH2_GetExceptionCode();
465 if(!NT_SUCCESS(Status
))
468 SetLastNtError(Status
);
472 if (dc
->fs
& DC_FLAG_DIRTY_RAO
)
473 CLIPPING_UpdateGCRegion(dc
);
477 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
478 Result
= REGION_RectInRegion(dc
->prgnRao
, &Rect
);
487 IntGdiSetMetaRgn(PDC pDC
)
491 if ( pDC
->dclevel
.prgnMeta
)
493 if ( pDC
->dclevel
.prgnClip
)
495 // preferably REGION_IntersectRegion
496 Ret
= IntGdiCombineRgn(pDC
->dclevel
.prgnMeta
, pDC
->dclevel
.prgnMeta
, pDC
->dclevel
.prgnClip
, RGN_AND
);
499 REGION_Delete(pDC
->dclevel
.prgnClip
);
500 pDC
->dclevel
.prgnClip
= NULL
;
501 IntGdiReleaseRaoRgn(pDC
);
505 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
509 if ( pDC
->dclevel
.prgnClip
)
511 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
512 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
513 pDC
->dclevel
.prgnClip
= NULL
;
520 pDC
->fs
|= DC_FLAG_DIRTY_RAO
;
526 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
529 PDC pDC
= DC_LockDc(hDC
);
533 EngSetLastError(ERROR_INVALID_PARAMETER
);
536 Ret
= IntGdiSetMetaRgn(pDC
);
544 CLIPPING_UpdateGCRegion(PDC pDC
)
546 /* Must have VisRgn set to a valid state! */
547 ASSERT (pDC
->prgnVis
);
551 REGION_Delete(pDC
->prgnAPI
);
556 REGION_Delete(pDC
->prgnRao
);
558 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
560 ASSERT(pDC
->prgnRao
);
562 if (pDC
->dclevel
.prgnMeta
|| pDC
->dclevel
.prgnClip
)
564 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
565 if (!pDC
->dclevel
.prgnMeta
)
567 IntGdiCombineRgn(pDC
->prgnAPI
,
568 pDC
->dclevel
.prgnClip
,
572 else if (!pDC
->dclevel
.prgnClip
)
574 IntGdiCombineRgn(pDC
->prgnAPI
,
575 pDC
->dclevel
.prgnMeta
,
581 IntGdiCombineRgn(pDC
->prgnAPI
,
582 pDC
->dclevel
.prgnClip
,
583 pDC
->dclevel
.prgnMeta
,
590 IntGdiCombineRgn(pDC
->prgnRao
,
597 IntGdiCombineRgn(pDC
->prgnRao
,
604 REGION_bOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
606 RtlCopyMemory(&pDC
->erclClip
,
607 &pDC
->prgnRao
->rdh
.rcBound
,
610 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
612 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
613 // the rects from region objects rects in pClipRgn->Buffer.
614 // With pDC->co.pClipRgn->Buffer,
615 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
617 IntEngUpdateClipRegion(&pDC
->co
,
618 pDC
->prgnRao
->rdh
.nCount
,
619 pDC
->prgnRao
->Buffer
,
622 REGION_bOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);