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
, hRgnVis
, 0, RGN_COPY
);
49 else // FYI: Vis == NULL! source of "IntGdiCombineRgn requires hSrc2 != NULL for combine mode 1!"
50 NtGdiCombineRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->rosdc
.hClipRgn
, hRgnVis
, RGN_AND
);
51 NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->ptlDCOrig
.x
, Dc
->ptlDCOrig
.y
);
53 if((CombinedRegion
= RGNOBJAPI_Lock(Dc
->rosdc
.hGCClipRgn
, NULL
)))
55 CLIPOBJ
*CombinedClip
;
57 CombinedClip
= IntEngCreateClipRegion(CombinedRegion
->rdh
.nCount
,
58 CombinedRegion
->Buffer
,
59 &CombinedRegion
->rdh
.rcBound
);
61 RGNOBJAPI_Unlock(CombinedRegion
);
65 DPRINT1("IntEngCreateClipRegion() failed\n");
69 if(Dc
->rosdc
.CombinedClip
!= NULL
)
70 IntEngDeleteClipRegion(Dc
->rosdc
.CombinedClip
);
72 Dc
->rosdc
.CombinedClip
= CombinedClip
;
75 return NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, -Dc
->ptlDCOrig
.x
, -Dc
->ptlDCOrig
.y
);
79 GdiSelectVisRgn(HDC hdc
, HRGN hrgn
)
86 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
89 if (!(dc
= DC_LockDc(hdc
)))
91 SetLastWin32Error(ERROR_INVALID_HANDLE
);
95 dc
->fs
&= ~DC_FLAG_DIRTY_RAO
;
97 if (dc
->prgnVis
== NULL
)
99 dc
->prgnVis
= IntSysCreateRectpRgn(0, 0, 0, 0);
100 GDIOBJ_CopyOwnership(hdc
, dc
->prgnVis
->BaseObject
.hHmgr
);
103 retval
= NtGdiCombineRgn(dc
->prgnVis
->BaseObject
.hHmgr
, hrgn
, 0, RGN_COPY
);
104 if ( retval
!= ERROR
)
106 IntGdiOffsetRgn(dc
->prgnVis
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
107 CLIPPING_UpdateGCRegion(dc
);
115 int FASTCALL
GdiExtSelectClipRgn(PDC dc
,
119 // dc->fs &= ~DC_FLAG_DIRTY_RAO;
123 if (fnMode
== RGN_COPY
)
125 if (dc
->rosdc
.hClipRgn
!= NULL
)
127 REGION_FreeRgnByHandle(dc
->rosdc
.hClipRgn
);
128 dc
->rosdc
.hClipRgn
= NULL
;
133 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
139 if (!dc
->rosdc
.hClipRgn
)
143 if((Rgn
= RGNOBJAPI_Lock(dc
->prgnVis
->BaseObject
.hHmgr
, NULL
)))
145 REGION_GetRgnBox(Rgn
, &rect
);
146 RGNOBJAPI_Unlock(Rgn
);
147 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgnIndirect(&rect
);
151 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
154 if(fnMode
== RGN_COPY
)
156 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, hrgn
, 0, fnMode
);
159 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, hrgn
, fnMode
);
162 return CLIPPING_UpdateGCRegion(dc
);
166 int APIENTRY
NtGdiExtSelectClipRgn(HDC hDC
,
173 if (!(dc
= DC_LockDc(hDC
)))
175 SetLastWin32Error(ERROR_INVALID_HANDLE
);
179 retval
= GdiExtSelectClipRgn ( dc
, hrgn
, fnMode
);
186 GdiGetClipBox(HDC hDC
, PRECTL rc
)
191 HRGN hRgnNew
, hRgn
= NULL
;
193 if (!(dc
= DC_LockDc(hDC
)))
198 /* FIXME! Rao and Vis only! */
199 if (dc
->prgnAPI
) // APIRGN
201 hRgn
= ((PROSRGNDATA
)dc
->prgnAPI
)->BaseObject
.hHmgr
;
203 else if (dc
->dclevel
.prgnMeta
) // METARGN
205 hRgn
= ((PROSRGNDATA
)dc
->dclevel
.prgnMeta
)->BaseObject
.hHmgr
;
209 hRgn
= dc
->rosdc
.hClipRgn
; // CLIPRGN
214 hRgnNew
= IntSysCreateRectRgn( 0, 0, 0, 0 );
216 NtGdiCombineRgn(hRgnNew
, dc
->prgnVis
->BaseObject
.hHmgr
, hRgn
, RGN_AND
);
218 if (!(Rgn
= RGNOBJAPI_Lock(hRgnNew
, NULL
)))
224 retval
= REGION_GetRgnBox(Rgn
, rc
);
226 REGION_FreeRgnByHandle(hRgnNew
);
227 RGNOBJAPI_Unlock(Rgn
);
233 if (!(Rgn
= RGNOBJAPI_Lock(dc
->prgnVis
->BaseObject
.hHmgr
, NULL
)))
238 retval
= REGION_GetRgnBox(Rgn
, rc
);
239 RGNOBJAPI_Unlock(Rgn
);
240 IntDPtoLP(dc
, (LPPOINT
)rc
, 2);
247 NtGdiGetAppClipBox(HDC hDC
, PRECTL rc
)
250 NTSTATUS Status
= STATUS_SUCCESS
;
253 Ret
= GdiGetClipBox(hDC
, &Saferect
);
262 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
264 Status
= _SEH2_GetExceptionCode();
268 if(!NT_SUCCESS(Status
))
270 SetLastNtError(Status
);
277 int APIENTRY
NtGdiExcludeClipRect(HDC hDC
,
286 PDC dc
= DC_LockDc(hDC
);
290 SetLastWin32Error(ERROR_INVALID_HANDLE
);
294 Rect
.left
= LeftRect
;
296 Rect
.right
= RightRect
;
297 Rect
.bottom
= BottomRect
;
299 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
301 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
308 if (!dc
->rosdc
.hClipRgn
)
310 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
311 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->prgnVis
->BaseObject
.hHmgr
, NewRgn
, RGN_DIFF
);
312 Result
= SIMPLEREGION
;
316 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_DIFF
);
318 REGION_FreeRgnByHandle(NewRgn
);
321 CLIPPING_UpdateGCRegion(dc
);
328 int APIENTRY
NtGdiIntersectClipRect(HDC hDC
,
337 PDC dc
= DC_LockDc(hDC
);
339 DPRINT("NtGdiIntersectClipRect(%x, %d,%d-%d,%d)\n",
340 hDC
, LeftRect
, TopRect
, RightRect
, BottomRect
);
344 SetLastWin32Error(ERROR_INVALID_HANDLE
);
348 Rect
.left
= LeftRect
;
350 Rect
.right
= RightRect
;
351 Rect
.bottom
= BottomRect
;
353 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
355 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
360 else if (!dc
->rosdc
.hClipRgn
)
362 dc
->rosdc
.hClipRgn
= NewRgn
;
363 Result
= SIMPLEREGION
;
367 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_AND
);
368 REGION_FreeRgnByHandle(NewRgn
);
371 CLIPPING_UpdateGCRegion(dc
);
378 int APIENTRY
NtGdiOffsetClipRgn(HDC hDC
,
385 if(!(dc
= DC_LockDc(hDC
)))
387 SetLastWin32Error(ERROR_INVALID_HANDLE
);
391 if(dc
->rosdc
.hClipRgn
!= NULL
)
393 Result
= NtGdiOffsetRgn(dc
->rosdc
.hClipRgn
,
396 CLIPPING_UpdateGCRegion(dc
);
407 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
414 if(!(dc
= DC_LockDc(hDC
)))
416 SetLastWin32Error(ERROR_INVALID_HANDLE
);
420 rgn
= dc
->rosdc
.hGCClipRgn
;
423 return (rgn
? NtGdiPtInRegion(rgn
, X
, Y
) : FALSE
);
426 BOOL APIENTRY
NtGdiRectVisible(HDC hDC
,
429 NTSTATUS Status
= STATUS_SUCCESS
;
431 PDC dc
= DC_LockDc(hDC
);
437 SetLastWin32Error(ERROR_INVALID_HANDLE
);
443 ProbeForRead(UnsafeRect
,
448 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
450 Status
= _SEH2_GetExceptionCode();
454 if(!NT_SUCCESS(Status
))
457 SetLastNtError(Status
);
461 if (dc
->rosdc
.hGCClipRgn
)
463 if((Rgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(dc
->rosdc
.hGCClipRgn
, NULL
)))
465 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
466 Result
= REGION_RectInRegion(Rgn
, &Rect
);
467 RGNOBJAPI_Unlock(Rgn
);
477 IntGdiSetMetaRgn(PDC pDC
)
482 if ( pDC
->dclevel
.prgnMeta
)
484 if ( pDC
->dclevel
.prgnClip
)
486 TempRgn
= IntSysCreateRectpRgn(0,0,0,0);
489 Ret
= IntGdiCombineRgn( TempRgn
,
490 pDC
->dclevel
.prgnMeta
,
491 pDC
->dclevel
.prgnClip
,
495 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnMeta
);
496 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnMeta
)->BaseObject
.ulShareCount
)
497 REGION_Delete(pDC
->dclevel
.prgnMeta
);
499 pDC
->dclevel
.prgnMeta
= TempRgn
;
501 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnClip
);
502 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnClip
)->BaseObject
.ulShareCount
)
503 REGION_Delete(pDC
->dclevel
.prgnClip
);
505 pDC
->dclevel
.prgnClip
= NULL
;
507 IntGdiReleaseRaoRgn(pDC
);
510 REGION_Delete(TempRgn
);
514 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
518 if ( pDC
->dclevel
.prgnClip
)
520 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
521 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
522 pDC
->dclevel
.prgnClip
= NULL
;
531 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
534 PDC pDC
= DC_LockDc(hDC
);
538 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
541 Ret
= IntGdiSetMetaRgn(pDC
);
548 NEW_CLIPPING_UpdateGCRegion(PDC pDC
)
552 /* Must have VisRgn set to a valid state! */
553 if (!pDC
->prgnVis
) return ERROR
;
557 REGION_Delete(pDC
->prgnAPI
);
558 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
563 REGION_Delete(pDC
->prgnRao
);
564 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
567 if (pDC
->dclevel
.prgnMeta
&& pDC
->dclevel
.prgnClip
)
569 IntGdiCombineRgn( pDC
->prgnAPI
,
570 pDC
->dclevel
.prgnClip
,
571 pDC
->dclevel
.prgnMeta
,
576 if (pDC
->dclevel
.prgnClip
)
578 IntGdiCombineRgn( pDC
->prgnAPI
,
579 pDC
->dclevel
.prgnClip
,
583 else if (pDC
->dclevel
.prgnMeta
)
585 IntGdiCombineRgn( pDC
->prgnAPI
,
586 pDC
->dclevel
.prgnMeta
,
592 IntGdiCombineRgn( pDC
->prgnRao
,
597 RtlCopyMemory(&pDC
->erclClip
,
598 &((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.rcBound
,
601 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
603 IntGdiOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
605 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
606 // the rects from region objects rects in pClipRgn->Buffer.
607 // With pDC->co.pClipRgn->Buffer,
608 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
610 co
= IntEngCreateClipRegion( ((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.nCount
,
611 ((PROSRGNDATA
)pDC
->prgnRao
)->Buffer
,
615 if (pDC
->rosdc
.CombinedClip
!= NULL
)
616 IntEngDeleteClipRegion(pDC
->rosdc
.CombinedClip
);
618 pDC
->rosdc
.CombinedClip
= co
;
621 return IntGdiOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);