2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 CLIPPING_UpdateGCRegion(DC
* Dc
)
28 PROSRGNDATA CombinedRegion
;
31 // would prefer this, but the rest of the code sucks
32 // ASSERT(Dc->rosdc.hGCClipRgn);
33 // ASSERT(Dc->rosdc.hClipRgn);
36 DPRINT1("Warning, prgnVis is NULL!\n");
40 hRgnVis
= Dc
->prgnVis
->BaseObject
.hHmgr
;
44 if (Dc
->rosdc
.hGCClipRgn
== NULL
)
45 Dc
->rosdc
.hGCClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
47 if (Dc
->rosdc
.hClipRgn
== NULL
)
48 NtGdiCombineRgn(Dc
->rosdc
.hGCClipRgn
, ((PROSRGNDATA
)Dc
->prgnVis
)->BaseObject
.hHmgr
, 0, RGN_COPY
);
50 NtGdiCombineRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->rosdc
.hClipRgn
, hRgnVis
, RGN_AND
);
52 NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->ptlDCOrig
.x
, Dc
->ptlDCOrig
.y
);
54 if((CombinedRegion
= RGNOBJAPI_Lock(Dc
->rosdc
.hGCClipRgn
, NULL
)))
56 CLIPOBJ
*CombinedClip
;
58 CombinedClip
= IntEngCreateClipRegion(CombinedRegion
->rdh
.nCount
,
59 CombinedRegion
->Buffer
,
60 &CombinedRegion
->rdh
.rcBound
);
62 RGNOBJAPI_Unlock(CombinedRegion
);
66 DPRINT1("IntEngCreateClipRegion() failed\n");
70 if(Dc
->rosdc
.CombinedClip
!= NULL
)
71 IntEngDeleteClipRegion(Dc
->rosdc
.CombinedClip
);
73 Dc
->rosdc
.CombinedClip
= CombinedClip
;
76 return NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, -Dc
->ptlDCOrig
.x
, -Dc
->ptlDCOrig
.y
);
80 GdiSelectVisRgn(HDC hdc
, HRGN hrgn
)
87 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
90 if (!(dc
= DC_LockDc(hdc
)))
92 SetLastWin32Error(ERROR_INVALID_HANDLE
);
96 dc
->fs
&= ~DC_FLAG_DIRTY_RAO
;
98 if (dc
->prgnVis
== NULL
)
100 dc
->prgnVis
= IntSysCreateRectpRgn(0, 0, 0, 0);
101 GDIOBJ_CopyOwnership(hdc
, ((PROSRGNDATA
)dc
->prgnVis
)->BaseObject
.hHmgr
);
104 retval
= NtGdiCombineRgn(((PROSRGNDATA
)dc
->prgnVis
)->BaseObject
.hHmgr
, hrgn
, 0, RGN_COPY
);
105 if ( retval
!= ERROR
)
107 NtGdiOffsetRgn(((PROSRGNDATA
)dc
->prgnVis
)->BaseObject
.hHmgr
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
108 CLIPPING_UpdateGCRegion(dc
);
116 int FASTCALL
GdiExtSelectClipRgn(PDC dc
,
120 // dc->fs &= ~DC_FLAG_DIRTY_RAO;
124 if (fnMode
== RGN_COPY
)
126 if (dc
->rosdc
.hClipRgn
!= NULL
)
128 REGION_FreeRgnByHandle(dc
->rosdc
.hClipRgn
);
129 dc
->rosdc
.hClipRgn
= NULL
;
134 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
140 if (!dc
->rosdc
.hClipRgn
)
145 REGION_GetRgnBox(dc
->prgnVis
, &rect
);
146 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgnIndirect(&rect
);
150 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
153 if(fnMode
== RGN_COPY
)
155 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, hrgn
, 0, fnMode
);
158 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, hrgn
, fnMode
);
161 return CLIPPING_UpdateGCRegion(dc
);
165 int APIENTRY
NtGdiExtSelectClipRgn(HDC hDC
,
172 if (!(dc
= DC_LockDc(hDC
)))
174 SetLastWin32Error(ERROR_INVALID_HANDLE
);
178 retval
= GdiExtSelectClipRgn ( dc
, hrgn
, fnMode
);
185 GdiGetClipBox(HDC hDC
, PRECTL rc
)
189 PROSRGNDATA pRgnNew
, pRgn
= NULL
;
190 BOOL Unlock
= FALSE
; //Small hack
192 if (!(dc
= DC_LockDc(hDC
)))
197 /* FIXME! Rao and Vis only! */
198 if (dc
->prgnAPI
) // APIRGN
202 else if (dc
->dclevel
.prgnMeta
) // METARGN
204 pRgn
= dc
->dclevel
.prgnMeta
;
209 pRgn
= REGION_LockRgn(dc
->rosdc
.hClipRgn
); // CLIPRGN
214 pRgnNew
= IntSysCreateRectpRgn( 0, 0, 0, 0 );
219 if(Unlock
) REGION_UnlockRgn(pRgn
);
223 IntGdiCombineRgn(pRgnNew
, dc
->prgnVis
, pRgn
, RGN_AND
);
225 retval
= REGION_GetRgnBox(pRgnNew
, rc
);
227 REGION_FreeRgnByHandle(pRgnNew
->BaseObject
.hHmgr
);
230 if(Unlock
) REGION_UnlockRgn(pRgn
);
234 retval
= REGION_GetRgnBox(dc
->prgnVis
, rc
);
235 IntDPtoLP(dc
, (LPPOINT
)rc
, 2);
242 NtGdiGetAppClipBox(HDC hDC
, PRECTL rc
)
245 NTSTATUS Status
= STATUS_SUCCESS
;
248 Ret
= GdiGetClipBox(hDC
, &Saferect
);
257 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
259 Status
= _SEH2_GetExceptionCode();
263 if(!NT_SUCCESS(Status
))
265 SetLastNtError(Status
);
272 int APIENTRY
NtGdiExcludeClipRect(HDC hDC
,
281 PDC dc
= DC_LockDc(hDC
);
285 SetLastWin32Error(ERROR_INVALID_HANDLE
);
289 Rect
.left
= LeftRect
;
291 Rect
.right
= RightRect
;
292 Rect
.bottom
= BottomRect
;
294 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
296 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
303 if (!dc
->rosdc
.hClipRgn
)
305 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
306 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, ((PROSRGNDATA
)dc
->prgnVis
)->BaseObject
.hHmgr
, NewRgn
, RGN_DIFF
);
307 Result
= SIMPLEREGION
;
311 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_DIFF
);
313 REGION_FreeRgnByHandle(NewRgn
);
316 CLIPPING_UpdateGCRegion(dc
);
323 int APIENTRY
NtGdiIntersectClipRect(HDC hDC
,
332 PDC dc
= DC_LockDc(hDC
);
334 DPRINT("NtGdiIntersectClipRect(%x, %d,%d-%d,%d)\n",
335 hDC
, LeftRect
, TopRect
, RightRect
, BottomRect
);
339 SetLastWin32Error(ERROR_INVALID_HANDLE
);
343 Rect
.left
= LeftRect
;
345 Rect
.right
= RightRect
;
346 Rect
.bottom
= BottomRect
;
348 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
350 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
355 else if (!dc
->rosdc
.hClipRgn
)
357 dc
->rosdc
.hClipRgn
= NewRgn
;
358 Result
= SIMPLEREGION
;
362 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_AND
);
363 REGION_FreeRgnByHandle(NewRgn
);
366 CLIPPING_UpdateGCRegion(dc
);
373 int APIENTRY
NtGdiOffsetClipRgn(HDC hDC
,
380 if(!(dc
= DC_LockDc(hDC
)))
382 SetLastWin32Error(ERROR_INVALID_HANDLE
);
386 if(dc
->rosdc
.hClipRgn
!= NULL
)
388 Result
= NtGdiOffsetRgn(dc
->rosdc
.hClipRgn
,
391 CLIPPING_UpdateGCRegion(dc
);
402 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
409 if(!(dc
= DC_LockDc(hDC
)))
411 SetLastWin32Error(ERROR_INVALID_HANDLE
);
415 rgn
= dc
->rosdc
.hGCClipRgn
;
418 return (rgn
? NtGdiPtInRegion(rgn
, X
, Y
) : FALSE
);
421 BOOL APIENTRY
NtGdiRectVisible(HDC hDC
,
424 NTSTATUS Status
= STATUS_SUCCESS
;
426 PDC dc
= DC_LockDc(hDC
);
432 SetLastWin32Error(ERROR_INVALID_HANDLE
);
438 ProbeForRead(UnsafeRect
,
443 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
445 Status
= _SEH2_GetExceptionCode();
449 if(!NT_SUCCESS(Status
))
452 SetLastNtError(Status
);
456 if (dc
->rosdc
.hGCClipRgn
)
458 if((Rgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(dc
->rosdc
.hGCClipRgn
, NULL
)))
460 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
461 Result
= REGION_RectInRegion(Rgn
, &Rect
);
462 RGNOBJAPI_Unlock(Rgn
);
472 IntGdiSetMetaRgn(PDC pDC
)
477 if ( pDC
->dclevel
.prgnMeta
)
479 if ( pDC
->dclevel
.prgnClip
)
481 TempRgn
= IntSysCreateRectpRgn(0,0,0,0);
484 Ret
= IntGdiCombineRgn( TempRgn
,
485 pDC
->dclevel
.prgnMeta
,
486 pDC
->dclevel
.prgnClip
,
490 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnMeta
);
491 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnMeta
)->BaseObject
.ulShareCount
)
492 REGION_Delete(pDC
->dclevel
.prgnMeta
);
494 pDC
->dclevel
.prgnMeta
= TempRgn
;
496 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnClip
);
497 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnClip
)->BaseObject
.ulShareCount
)
498 REGION_Delete(pDC
->dclevel
.prgnClip
);
500 pDC
->dclevel
.prgnClip
= NULL
;
502 IntGdiReleaseRaoRgn(pDC
);
505 REGION_Delete(TempRgn
);
509 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
513 if ( pDC
->dclevel
.prgnClip
)
515 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
516 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
517 pDC
->dclevel
.prgnClip
= NULL
;
526 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
529 PDC pDC
= DC_LockDc(hDC
);
533 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
536 Ret
= IntGdiSetMetaRgn(pDC
);
543 NEW_CLIPPING_UpdateGCRegion(PDC pDC
)
547 /* Must have VisRgn set to a valid state! */
548 if (!pDC
->prgnVis
) return ERROR
;
552 REGION_Delete(pDC
->prgnAPI
);
553 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
558 REGION_Delete(pDC
->prgnRao
);
559 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
562 if (pDC
->dclevel
.prgnMeta
&& pDC
->dclevel
.prgnClip
)
564 IntGdiCombineRgn( pDC
->prgnAPI
,
565 pDC
->dclevel
.prgnClip
,
566 pDC
->dclevel
.prgnMeta
,
571 if (pDC
->dclevel
.prgnClip
)
573 IntGdiCombineRgn( pDC
->prgnAPI
,
574 pDC
->dclevel
.prgnClip
,
578 else if (pDC
->dclevel
.prgnMeta
)
580 IntGdiCombineRgn( pDC
->prgnAPI
,
581 pDC
->dclevel
.prgnMeta
,
587 IntGdiCombineRgn( pDC
->prgnRao
,
592 RtlCopyMemory(&pDC
->erclClip
,
593 &((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.rcBound
,
596 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
598 IntGdiOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
600 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
601 // the rects from region objects rects in pClipRgn->Buffer.
602 // With pDC->co.pClipRgn->Buffer,
603 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
605 co
= IntEngCreateClipRegion( ((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.nCount
,
606 ((PROSRGNDATA
)pDC
->prgnRao
)->Buffer
,
610 if (pDC
->rosdc
.CombinedClip
!= NULL
)
611 IntEngDeleteClipRegion(pDC
->rosdc
.CombinedClip
);
613 pDC
->rosdc
.CombinedClip
= co
;
616 return IntGdiOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);