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
;
29 HRGN hRgnVis
= Dc
->prgnVis
->BaseObject
.hHmgr
;
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
, hRgnVis
, 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 ASSERT (dc
->prgnVis
!= NULL
);
100 retval
= NtGdiCombineRgn(dc
->prgnVis
->BaseObject
.hHmgr
, hrgn
, 0, RGN_COPY
);
101 if ( retval
!= ERROR
)
103 NtGdiOffsetRgn(dc
->prgnVis
->BaseObject
.hHmgr
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
104 CLIPPING_UpdateGCRegion(dc
);
112 int FASTCALL
GdiExtSelectClipRgn(PDC dc
,
116 // dc->fs &= ~DC_FLAG_DIRTY_RAO;
120 if (fnMode
== RGN_COPY
)
122 if (dc
->rosdc
.hClipRgn
!= NULL
)
124 REGION_FreeRgnByHandle(dc
->rosdc
.hClipRgn
);
125 dc
->rosdc
.hClipRgn
= NULL
;
130 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
136 if (!dc
->rosdc
.hClipRgn
)
141 REGION_GetRgnBox(dc
->prgnVis
, &rect
);
142 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgnIndirect(&rect
);
146 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
149 if(fnMode
== RGN_COPY
)
151 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, hrgn
, 0, fnMode
);
154 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, hrgn
, fnMode
);
157 return CLIPPING_UpdateGCRegion(dc
);
161 int APIENTRY
NtGdiExtSelectClipRgn(HDC hDC
,
168 if (!(dc
= DC_LockDc(hDC
)))
170 SetLastWin32Error(ERROR_INVALID_HANDLE
);
174 retval
= GdiExtSelectClipRgn ( dc
, hrgn
, fnMode
);
181 GdiGetClipBox(HDC hDC
, PRECTL rc
)
185 PROSRGNDATA pRgnNew
, pRgn
= NULL
;
186 BOOL Unlock
= FALSE
; //Small hack
188 if (!(dc
= DC_LockDc(hDC
)))
193 /* FIXME! Rao and Vis only! */
194 if (dc
->prgnAPI
) // APIRGN
198 else if (dc
->dclevel
.prgnMeta
) // METARGN
200 pRgn
= dc
->dclevel
.prgnMeta
;
205 pRgn
= REGION_LockRgn(dc
->rosdc
.hClipRgn
); // CLIPRGN
210 pRgnNew
= IntSysCreateRectpRgn( 0, 0, 0, 0 );
215 if(Unlock
) REGION_UnlockRgn(pRgn
);
219 IntGdiCombineRgn(pRgnNew
, dc
->prgnVis
, pRgn
, RGN_AND
);
221 retval
= REGION_GetRgnBox(pRgnNew
, rc
);
223 REGION_FreeRgnByHandle(pRgnNew
->BaseObject
.hHmgr
);
226 if(Unlock
) REGION_UnlockRgn(pRgn
);
230 retval
= REGION_GetRgnBox(dc
->prgnVis
, rc
);
231 IntDPtoLP(dc
, (LPPOINT
)rc
, 2);
238 NtGdiGetAppClipBox(HDC hDC
, PRECTL rc
)
241 NTSTATUS Status
= STATUS_SUCCESS
;
244 Ret
= GdiGetClipBox(hDC
, &Saferect
);
253 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
255 Status
= _SEH2_GetExceptionCode();
259 if(!NT_SUCCESS(Status
))
261 SetLastNtError(Status
);
268 int APIENTRY
NtGdiExcludeClipRect(HDC hDC
,
277 PDC dc
= DC_LockDc(hDC
);
281 SetLastWin32Error(ERROR_INVALID_HANDLE
);
285 Rect
.left
= LeftRect
;
287 Rect
.right
= RightRect
;
288 Rect
.bottom
= BottomRect
;
290 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
292 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
299 if (!dc
->rosdc
.hClipRgn
)
301 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
302 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->prgnVis
->BaseObject
.hHmgr
, NewRgn
, RGN_DIFF
);
303 Result
= SIMPLEREGION
;
307 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_DIFF
);
309 REGION_FreeRgnByHandle(NewRgn
);
312 CLIPPING_UpdateGCRegion(dc
);
319 int APIENTRY
NtGdiIntersectClipRect(HDC hDC
,
328 PDC dc
= DC_LockDc(hDC
);
330 DPRINT("NtGdiIntersectClipRect(%x, %d,%d-%d,%d)\n",
331 hDC
, LeftRect
, TopRect
, RightRect
, BottomRect
);
335 SetLastWin32Error(ERROR_INVALID_HANDLE
);
339 Rect
.left
= LeftRect
;
341 Rect
.right
= RightRect
;
342 Rect
.bottom
= BottomRect
;
344 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
346 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
351 else if (!dc
->rosdc
.hClipRgn
)
353 dc
->rosdc
.hClipRgn
= NewRgn
;
354 Result
= SIMPLEREGION
;
358 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_AND
);
359 REGION_FreeRgnByHandle(NewRgn
);
362 CLIPPING_UpdateGCRegion(dc
);
369 int APIENTRY
NtGdiOffsetClipRgn(HDC hDC
,
376 if(!(dc
= DC_LockDc(hDC
)))
378 SetLastWin32Error(ERROR_INVALID_HANDLE
);
382 if(dc
->rosdc
.hClipRgn
!= NULL
)
384 Result
= NtGdiOffsetRgn(dc
->rosdc
.hClipRgn
,
387 CLIPPING_UpdateGCRegion(dc
);
398 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
405 if(!(dc
= DC_LockDc(hDC
)))
407 SetLastWin32Error(ERROR_INVALID_HANDLE
);
411 rgn
= dc
->rosdc
.hGCClipRgn
;
414 return (rgn
? NtGdiPtInRegion(rgn
, X
, Y
) : FALSE
);
417 BOOL APIENTRY
NtGdiRectVisible(HDC hDC
,
420 NTSTATUS Status
= STATUS_SUCCESS
;
422 PDC dc
= DC_LockDc(hDC
);
428 SetLastWin32Error(ERROR_INVALID_HANDLE
);
434 ProbeForRead(UnsafeRect
,
439 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
441 Status
= _SEH2_GetExceptionCode();
445 if(!NT_SUCCESS(Status
))
448 SetLastNtError(Status
);
452 if (dc
->rosdc
.hGCClipRgn
)
454 if((Rgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(dc
->rosdc
.hGCClipRgn
, NULL
)))
456 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
457 Result
= REGION_RectInRegion(Rgn
, &Rect
);
458 RGNOBJAPI_Unlock(Rgn
);
468 IntGdiSetMetaRgn(PDC pDC
)
473 if ( pDC
->dclevel
.prgnMeta
)
475 if ( pDC
->dclevel
.prgnClip
)
477 TempRgn
= IntSysCreateRectpRgn(0,0,0,0);
480 Ret
= IntGdiCombineRgn( TempRgn
,
481 pDC
->dclevel
.prgnMeta
,
482 pDC
->dclevel
.prgnClip
,
486 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnMeta
);
487 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnMeta
)->BaseObject
.ulShareCount
)
488 REGION_Delete(pDC
->dclevel
.prgnMeta
);
490 pDC
->dclevel
.prgnMeta
= TempRgn
;
492 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnClip
);
493 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnClip
)->BaseObject
.ulShareCount
)
494 REGION_Delete(pDC
->dclevel
.prgnClip
);
496 pDC
->dclevel
.prgnClip
= NULL
;
498 IntGdiReleaseRaoRgn(pDC
);
501 REGION_Delete(TempRgn
);
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
;
522 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
525 PDC pDC
= DC_LockDc(hDC
);
529 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
532 Ret
= IntGdiSetMetaRgn(pDC
);
539 NEW_CLIPPING_UpdateGCRegion(PDC pDC
)
543 /* Must have VisRgn set to a valid state! */
544 ASSERT (pDC
->prgnVis
);
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);
558 if (pDC
->dclevel
.prgnMeta
&& pDC
->dclevel
.prgnClip
)
560 IntGdiCombineRgn( pDC
->prgnAPI
,
561 pDC
->dclevel
.prgnClip
,
562 pDC
->dclevel
.prgnMeta
,
567 if (pDC
->dclevel
.prgnClip
)
569 IntGdiCombineRgn( pDC
->prgnAPI
,
570 pDC
->dclevel
.prgnClip
,
574 else if (pDC
->dclevel
.prgnMeta
)
576 IntGdiCombineRgn( pDC
->prgnAPI
,
577 pDC
->dclevel
.prgnMeta
,
583 IntGdiCombineRgn( pDC
->prgnRao
,
588 RtlCopyMemory(&pDC
->erclClip
,
589 &((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.rcBound
,
592 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
594 IntGdiOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
596 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
597 // the rects from region objects rects in pClipRgn->Buffer.
598 // With pDC->co.pClipRgn->Buffer,
599 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
601 co
= IntEngCreateClipRegion( ((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.nCount
,
602 ((PROSRGNDATA
)pDC
->prgnRao
)->Buffer
,
606 if (pDC
->rosdc
.CombinedClip
!= NULL
)
607 IntEngDeleteClipRegion(pDC
->rosdc
.CombinedClip
);
609 pDC
->rosdc
.CombinedClip
= co
;
612 return IntGdiOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);