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
15 CLIPPING_UpdateGCRegion(DC
* Dc
)
17 PROSRGNDATA CombinedRegion
;
19 PREGION prgnClip
, prgnGCClip
;
21 /* Would prefer this, but the rest of the code sucks... */
22 //ASSERT(Dc->rosdc.hGCClipRgn);
23 //ASSERT(Dc->rosdc.hClipRgn);
25 //hRgnVis = Dc->prgnVis->BaseObject.hHmgr;
27 if (Dc
->rosdc
.hGCClipRgn
== NULL
)
28 Dc
->rosdc
.hGCClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
30 prgnGCClip
= REGION_LockRgn(Dc
->rosdc
.hGCClipRgn
);
33 if (Dc
->rosdc
.hClipRgn
== NULL
)
34 IntGdiCombineRgn(prgnGCClip
, Dc
->prgnVis
, NULL
, RGN_COPY
);
37 prgnClip
= REGION_LockRgn(Dc
->rosdc
.hClipRgn
); // FIXME: Locking order, ugh!
38 IntGdiCombineRgn(prgnGCClip
, Dc
->prgnVis
, prgnClip
, RGN_AND
);
39 REGION_UnlockRgn(prgnClip
);
41 REGION_UnlockRgn(prgnGCClip
);
43 NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->ptlDCOrig
.x
, Dc
->ptlDCOrig
.y
);
45 if((CombinedRegion
= RGNOBJAPI_Lock(Dc
->rosdc
.hGCClipRgn
, NULL
)))
47 CLIPOBJ
*CombinedClip
;
49 CombinedClip
= IntEngCreateClipRegion(CombinedRegion
->rdh
.nCount
,
50 CombinedRegion
->Buffer
,
51 &CombinedRegion
->rdh
.rcBound
);
53 RGNOBJAPI_Unlock(CombinedRegion
);
57 DPRINT1("IntEngCreateClipRegion() failed\n");
61 if(Dc
->rosdc
.CombinedClip
!= NULL
)
62 IntEngDeleteClipRegion(Dc
->rosdc
.CombinedClip
);
64 Dc
->rosdc
.CombinedClip
= CombinedClip
;
67 return NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, -Dc
->ptlDCOrig
.x
, -Dc
->ptlDCOrig
.y
);
71 GdiSelectVisRgn(HDC hdc
, HRGN hrgn
)
79 EngSetLastError(ERROR_INVALID_PARAMETER
);
82 if (!(dc
= DC_LockDc(hdc
)))
84 EngSetLastError(ERROR_INVALID_HANDLE
);
88 dc
->fs
&= ~DC_FLAG_DIRTY_RAO
;
90 ASSERT (dc
->prgnVis
!= NULL
);
92 prgn
= RGNOBJAPI_Lock(hrgn
, NULL
);
93 retval
= prgn
? IntGdiCombineRgn(dc
->prgnVis
, prgn
, NULL
, RGN_COPY
) : ERROR
;
94 RGNOBJAPI_Unlock(prgn
);
95 if ( retval
!= ERROR
)
97 IntGdiOffsetRgn(dc
->prgnVis
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
98 CLIPPING_UpdateGCRegion(dc
);
106 int FASTCALL
GdiExtSelectClipRgn(PDC dc
,
110 // dc->fs &= ~DC_FLAG_DIRTY_RAO;
114 if (fnMode
== RGN_COPY
)
116 if (dc
->rosdc
.hClipRgn
!= NULL
)
118 GreDeleteObject(dc
->rosdc
.hClipRgn
);
119 dc
->rosdc
.hClipRgn
= NULL
;
124 EngSetLastError(ERROR_INVALID_PARAMETER
);
130 if (!dc
->rosdc
.hClipRgn
)
135 REGION_GetRgnBox(dc
->prgnVis
, &rect
);
136 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgnIndirect(&rect
);
140 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
143 if(fnMode
== RGN_COPY
)
145 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, hrgn
, 0, fnMode
);
148 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, hrgn
, fnMode
);
151 return CLIPPING_UpdateGCRegion(dc
);
155 int APIENTRY
NtGdiExtSelectClipRgn(HDC hDC
,
162 if (!(dc
= DC_LockDc(hDC
)))
164 EngSetLastError(ERROR_INVALID_HANDLE
);
168 retval
= GdiExtSelectClipRgn ( dc
, hrgn
, fnMode
);
175 GdiGetClipBox(HDC hDC
, PRECTL rc
)
179 PROSRGNDATA pRgnNew
, pRgn
= NULL
;
180 BOOL Unlock
= FALSE
; // Small HACK
182 if (!(dc
= DC_LockDc(hDC
)))
187 /* FIXME: Rao and Vis only! */
188 if (dc
->prgnAPI
) // APIRGN
192 else if (dc
->dclevel
.prgnMeta
) // METARGN
194 pRgn
= dc
->dclevel
.prgnMeta
;
196 else if (dc
->rosdc
.hClipRgn
)
199 pRgn
= REGION_LockRgn(dc
->rosdc
.hClipRgn
); // CLIPRGN
204 pRgnNew
= IntSysCreateRectpRgn( 0, 0, 0, 0 );
209 if(Unlock
) REGION_UnlockRgn(pRgn
);
213 IntGdiCombineRgn(pRgnNew
, dc
->prgnVis
, pRgn
, RGN_AND
);
215 retval
= REGION_GetRgnBox(pRgnNew
, rc
);
217 REGION_Delete(pRgnNew
);
220 if(Unlock
) REGION_UnlockRgn(pRgn
);
224 retval
= REGION_GetRgnBox(dc
->prgnVis
, rc
);
225 IntDPtoLP(dc
, (LPPOINT
)rc
, 2);
232 NtGdiGetAppClipBox(HDC hDC
, PRECTL rc
)
235 NTSTATUS Status
= STATUS_SUCCESS
;
238 Ret
= GdiGetClipBox(hDC
, &Saferect
);
247 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
249 Status
= _SEH2_GetExceptionCode();
253 if(!NT_SUCCESS(Status
))
255 SetLastNtError(Status
);
262 int APIENTRY
NtGdiExcludeClipRect(HDC hDC
,
270 PREGION prgnNew
, prgnClip
;
271 PDC dc
= DC_LockDc(hDC
);
275 EngSetLastError(ERROR_INVALID_HANDLE
);
279 Rect
.left
= LeftRect
;
281 Rect
.right
= RightRect
;
282 Rect
.bottom
= BottomRect
;
284 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
286 prgnNew
= IntSysCreateRectpRgnIndirect(&Rect
);
293 if (!dc
->rosdc
.hClipRgn
)
295 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
296 prgnClip
= REGION_LockRgn(dc
->rosdc
.hClipRgn
);
297 IntGdiCombineRgn(prgnClip
, dc
->prgnVis
, prgnNew
, RGN_DIFF
);
298 REGION_UnlockRgn(prgnClip
);
299 Result
= SIMPLEREGION
;
303 prgnClip
= REGION_LockRgn(dc
->rosdc
.hClipRgn
);
304 Result
= IntGdiCombineRgn(prgnClip
, prgnClip
, prgnNew
, RGN_DIFF
);
305 REGION_UnlockRgn(prgnClip
);
307 REGION_Delete(prgnNew
);
310 CLIPPING_UpdateGCRegion(dc
);
317 int APIENTRY
NtGdiIntersectClipRect(HDC hDC
,
326 PDC dc
= DC_LockDc(hDC
);
328 DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
329 hDC
, LeftRect
, TopRect
, RightRect
, BottomRect
);
333 EngSetLastError(ERROR_INVALID_HANDLE
);
337 Rect
.left
= LeftRect
;
339 Rect
.right
= RightRect
;
340 Rect
.bottom
= BottomRect
;
342 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
344 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
349 else if (!dc
->rosdc
.hClipRgn
)
351 dc
->rosdc
.hClipRgn
= NewRgn
;
352 Result
= SIMPLEREGION
;
356 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_AND
);
357 GreDeleteObject(NewRgn
);
360 CLIPPING_UpdateGCRegion(dc
);
367 int APIENTRY
NtGdiOffsetClipRgn(HDC hDC
,
374 if(!(dc
= DC_LockDc(hDC
)))
376 EngSetLastError(ERROR_INVALID_HANDLE
);
380 if(dc
->rosdc
.hClipRgn
!= NULL
)
382 Result
= NtGdiOffsetRgn(dc
->rosdc
.hClipRgn
,
385 CLIPPING_UpdateGCRegion(dc
);
396 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
403 if(!(dc
= DC_LockDc(hDC
)))
405 EngSetLastError(ERROR_INVALID_HANDLE
);
409 rgn
= dc
->rosdc
.hGCClipRgn
;
412 return (rgn
? NtGdiPtInRegion(rgn
, X
, Y
) : FALSE
);
415 BOOL APIENTRY
NtGdiRectVisible(HDC hDC
,
418 NTSTATUS Status
= STATUS_SUCCESS
;
420 PDC dc
= DC_LockDc(hDC
);
426 EngSetLastError(ERROR_INVALID_HANDLE
);
432 ProbeForRead(UnsafeRect
,
437 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
439 Status
= _SEH2_GetExceptionCode();
443 if(!NT_SUCCESS(Status
))
446 SetLastNtError(Status
);
450 if (dc
->rosdc
.hGCClipRgn
)
452 if((Rgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(dc
->rosdc
.hGCClipRgn
, NULL
)))
454 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
455 Result
= REGION_RectInRegion(Rgn
, &Rect
);
456 RGNOBJAPI_Unlock(Rgn
);
466 IntGdiSetMetaRgn(PDC pDC
)
471 if ( pDC
->dclevel
.prgnMeta
)
473 if ( pDC
->dclevel
.prgnClip
)
475 TempRgn
= IntSysCreateRectpRgn(0,0,0,0);
478 Ret
= IntGdiCombineRgn( TempRgn
,
479 pDC
->dclevel
.prgnMeta
,
480 pDC
->dclevel
.prgnClip
,
484 GDIOBJ_vDereferenceObject(&pDC
->dclevel
.prgnMeta
->BaseObject
);
485 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnMeta
)->BaseObject
.ulShareCount
)
486 REGION_Delete(pDC
->dclevel
.prgnMeta
);
488 pDC
->dclevel
.prgnMeta
= TempRgn
;
490 GDIOBJ_vDereferenceObject(&pDC
->dclevel
.prgnClip
->BaseObject
);
491 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnClip
)->BaseObject
.ulShareCount
)
492 REGION_Delete(pDC
->dclevel
.prgnClip
);
494 pDC
->dclevel
.prgnClip
= NULL
;
496 IntGdiReleaseRaoRgn(pDC
);
499 REGION_Delete(TempRgn
);
503 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
507 if ( pDC
->dclevel
.prgnClip
)
509 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
510 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
511 pDC
->dclevel
.prgnClip
= NULL
;
520 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
523 PDC pDC
= DC_LockDc(hDC
);
527 EngSetLastError(ERROR_INVALID_PARAMETER
);
530 Ret
= IntGdiSetMetaRgn(pDC
);
537 NEW_CLIPPING_UpdateGCRegion(PDC pDC
)
541 /* Must have VisRgn set to a valid state! */
542 ASSERT (pDC
->prgnVis
);
544 // FIXME: this seems to be broken!
548 REGION_Delete(pDC
->prgnAPI
);
549 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
554 REGION_Delete(pDC
->prgnRao
);
555 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
563 if (pDC
->dclevel
.prgnMeta
&& pDC
->dclevel
.prgnClip
)
565 IntGdiCombineRgn( pDC
->prgnAPI
,
566 pDC
->dclevel
.prgnClip
,
567 pDC
->dclevel
.prgnMeta
,
572 if (pDC
->dclevel
.prgnClip
)
574 IntGdiCombineRgn( pDC
->prgnAPI
,
575 pDC
->dclevel
.prgnClip
,
579 else if (pDC
->dclevel
.prgnMeta
)
581 IntGdiCombineRgn( pDC
->prgnAPI
,
582 pDC
->dclevel
.prgnMeta
,
588 IntGdiCombineRgn( pDC
->prgnRao
,
593 RtlCopyMemory(&pDC
->erclClip
,
594 &pDC
->prgnRao
->rdh
.rcBound
,
597 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
599 IntGdiOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
601 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
602 // the rects from region objects rects in pClipRgn->Buffer.
603 // With pDC->co.pClipRgn->Buffer,
604 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
606 co
= IntEngCreateClipRegion(pDC
->prgnRao
->rdh
.nCount
,
607 pDC
->prgnRao
->Buffer
,
611 if (pDC
->rosdc
.CombinedClip
!= NULL
)
612 IntEngDeleteClipRegion(pDC
->rosdc
.CombinedClip
);
614 pDC
->rosdc
.CombinedClip
= co
;
617 return IntGdiOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);