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 /* Experiment with API region based on wine.. */
32 if (Dc
->rosdc
.hClipRgn
&& Dc
->dclevel
.prgnMeta
)
36 if ((pClipRgn
= RGNOBJAPI_Lock(Dc
->rosdc
.hClipRgn
, NULL
)))
38 if (!Dc
->prgnAPI
) Dc
->prgnAPI
= IntSysCreateRectpRgn( 0, 0, 0, 0 );
40 IntGdiCombineRgn( Dc
->prgnAPI
,
44 RGNOBJAPI_Unlock(pClipRgn
);
50 GreDeleteObject(((PROSRGNDATA
)Dc
->prgnAPI
)->BaseObject
.hHmgr
);
55 if (Dc
->rosdc
.hGCClipRgn
== NULL
)
56 Dc
->rosdc
.hGCClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
58 if (Dc
->rosdc
.hClipRgn
== NULL
)
59 NtGdiCombineRgn(Dc
->rosdc
.hGCClipRgn
, hRgnVis
, 0, RGN_COPY
);
61 NtGdiCombineRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->rosdc
.hClipRgn
, hRgnVis
, RGN_AND
);
63 NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->ptlDCOrig
.x
, Dc
->ptlDCOrig
.y
);
65 if((CombinedRegion
= RGNOBJAPI_Lock(Dc
->rosdc
.hGCClipRgn
, NULL
)))
67 CLIPOBJ
*CombinedClip
;
69 CombinedClip
= IntEngCreateClipRegion(CombinedRegion
->rdh
.nCount
,
70 CombinedRegion
->Buffer
,
71 &CombinedRegion
->rdh
.rcBound
);
73 RGNOBJAPI_Unlock(CombinedRegion
);
77 DPRINT1("IntEngCreateClipRegion() failed\n");
81 if (Dc
->rosdc
.CombinedClip
!= NULL
)
82 IntEngDeleteClipRegion(Dc
->rosdc
.CombinedClip
);
84 Dc
->rosdc
.CombinedClip
= CombinedClip
;
88 return NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, -Dc
->ptlDCOrig
.x
, -Dc
->ptlDCOrig
.y
);
92 GdiSelectVisRgn(HDC hdc
, HRGN hrgn
)
99 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
102 if (!(dc
= DC_LockDc(hdc
)))
104 SetLastWin32Error(ERROR_INVALID_HANDLE
);
108 dc
->fs
&= ~DC_FLAG_DIRTY_RAO
;
110 ASSERT (dc
->prgnVis
!= NULL
);
112 retval
= NtGdiCombineRgn(dc
->prgnVis
->BaseObject
.hHmgr
, hrgn
, 0, RGN_COPY
);
113 if ( retval
!= ERROR
)
115 NtGdiOffsetRgn(dc
->prgnVis
->BaseObject
.hHmgr
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
116 CLIPPING_UpdateGCRegion(dc
);
125 int FASTCALL
GdiExtSelectClipRgn(PDC dc
,
129 // dc->fs &= ~DC_FLAG_DIRTY_RAO;
133 if (fnMode
== RGN_COPY
)
135 if (dc
->rosdc
.hClipRgn
!= NULL
)
137 REGION_FreeRgnByHandle(dc
->rosdc
.hClipRgn
);
138 dc
->rosdc
.hClipRgn
= NULL
;
143 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
149 if (!dc
->rosdc
.hClipRgn
)
154 REGION_GetRgnBox(dc
->prgnVis
, &rect
);
155 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgnIndirect(&rect
);
159 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
162 if(fnMode
== RGN_COPY
)
164 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, hrgn
, 0, fnMode
);
167 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, hrgn
, fnMode
);
169 return CLIPPING_UpdateGCRegion(dc
);
173 int APIENTRY
NtGdiExtSelectClipRgn(HDC hDC
,
180 if (!(dc
= DC_LockDc(hDC
)))
182 SetLastWin32Error(ERROR_INVALID_HANDLE
);
186 retval
= GdiExtSelectClipRgn ( dc
, hrgn
, fnMode
);
193 GdiGetClipBox(HDC hDC
, PRECTL rc
)
197 PROSRGNDATA pRgnNew
, pRgn
= NULL
;
198 BOOL Unlock
= FALSE
; //Small hack
200 if (!(dc
= DC_LockDc(hDC
)))
205 /* FIXME! Rao and Vis only! */
206 if (dc
->prgnAPI
) // APIRGN
210 else if (dc
->dclevel
.prgnMeta
) // METARGN
212 pRgn
= dc
->dclevel
.prgnMeta
;
217 pRgn
= REGION_LockRgn(dc
->rosdc
.hClipRgn
); // CLIPRGN
222 pRgnNew
= IntSysCreateRectpRgn( 0, 0, 0, 0 );
227 if(Unlock
) REGION_UnlockRgn(pRgn
);
231 IntGdiCombineRgn(pRgnNew
, dc
->prgnVis
, pRgn
, RGN_AND
);
233 retval
= REGION_GetRgnBox(pRgnNew
, rc
);
235 REGION_FreeRgnByHandle(pRgnNew
->BaseObject
.hHmgr
);
237 if(Unlock
) REGION_UnlockRgn(pRgn
);
241 retval
= REGION_GetRgnBox(dc
->prgnVis
, rc
);
242 IntDPtoLP(dc
, (LPPOINT
)rc
, 2);
249 NtGdiGetAppClipBox(HDC hDC
, PRECTL rc
)
252 NTSTATUS Status
= STATUS_SUCCESS
;
255 Ret
= GdiGetClipBox(hDC
, &Saferect
);
264 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
266 Status
= _SEH2_GetExceptionCode();
270 if(!NT_SUCCESS(Status
))
272 SetLastNtError(Status
);
279 int APIENTRY
NtGdiExcludeClipRect(HDC hDC
,
288 PDC dc
= DC_LockDc(hDC
);
292 SetLastWin32Error(ERROR_INVALID_HANDLE
);
296 Rect
.left
= LeftRect
;
298 Rect
.right
= RightRect
;
299 Rect
.bottom
= BottomRect
;
301 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
303 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
310 if (!dc
->rosdc
.hClipRgn
)
312 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
313 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->prgnVis
->BaseObject
.hHmgr
, NewRgn
, RGN_DIFF
);
314 Result
= SIMPLEREGION
;
318 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_DIFF
);
320 REGION_FreeRgnByHandle(NewRgn
);
323 CLIPPING_UpdateGCRegion(dc
);
330 int APIENTRY
NtGdiIntersectClipRect(HDC hDC
,
339 PDC dc
= DC_LockDc(hDC
);
341 DPRINT("NtGdiIntersectClipRect(%x, %d,%d-%d,%d)\n",
342 hDC
, LeftRect
, TopRect
, RightRect
, BottomRect
);
346 SetLastWin32Error(ERROR_INVALID_HANDLE
);
350 Rect
.left
= LeftRect
;
352 Rect
.right
= RightRect
;
353 Rect
.bottom
= BottomRect
;
355 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
357 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
362 else if (!dc
->rosdc
.hClipRgn
)
364 dc
->rosdc
.hClipRgn
= NewRgn
;
365 Result
= SIMPLEREGION
;
369 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_AND
);
370 REGION_FreeRgnByHandle(NewRgn
);
373 CLIPPING_UpdateGCRegion(dc
);
380 int APIENTRY
NtGdiOffsetClipRgn(HDC hDC
,
387 if(!(dc
= DC_LockDc(hDC
)))
389 SetLastWin32Error(ERROR_INVALID_HANDLE
);
393 if(dc
->rosdc
.hClipRgn
!= NULL
)
395 Result
= NtGdiOffsetRgn(dc
->rosdc
.hClipRgn
,
398 CLIPPING_UpdateGCRegion(dc
);
409 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
416 if(!(dc
= DC_LockDc(hDC
)))
418 SetLastWin32Error(ERROR_INVALID_HANDLE
);
422 rgn
= dc
->rosdc
.hGCClipRgn
;
425 return (rgn
? NtGdiPtInRegion(rgn
, X
, Y
) : FALSE
);
428 BOOL APIENTRY
NtGdiRectVisible(HDC hDC
,
431 NTSTATUS Status
= STATUS_SUCCESS
;
433 PDC dc
= DC_LockDc(hDC
);
439 SetLastWin32Error(ERROR_INVALID_HANDLE
);
445 ProbeForRead(UnsafeRect
,
450 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
452 Status
= _SEH2_GetExceptionCode();
456 if(!NT_SUCCESS(Status
))
459 SetLastNtError(Status
);
463 if (dc
->rosdc
.hGCClipRgn
)
465 if((Rgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(dc
->rosdc
.hGCClipRgn
, NULL
)))
467 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
468 Result
= REGION_RectInRegion(Rgn
, &Rect
);
469 RGNOBJAPI_Unlock(Rgn
);
479 IntGdiSetMetaRgn(PDC pDC
)
484 if ( pDC
->dclevel
.prgnMeta
)
486 if ( pDC
->dclevel
.prgnClip
)
488 TempRgn
= IntSysCreateRectpRgn(0,0,0,0);
491 Ret
= IntGdiCombineRgn( TempRgn
,
492 pDC
->dclevel
.prgnMeta
,
493 pDC
->dclevel
.prgnClip
,
497 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnMeta
);
498 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnMeta
)->BaseObject
.ulShareCount
)
499 REGION_Delete(pDC
->dclevel
.prgnMeta
);
501 pDC
->dclevel
.prgnMeta
= TempRgn
;
503 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnClip
);
504 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnClip
)->BaseObject
.ulShareCount
)
505 REGION_Delete(pDC
->dclevel
.prgnClip
);
507 pDC
->dclevel
.prgnClip
= NULL
;
509 IntGdiReleaseRaoRgn(pDC
);
512 REGION_Delete(TempRgn
);
516 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
520 if ( pDC
->dclevel
.prgnClip
)
522 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
523 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
524 pDC
->dclevel
.prgnClip
= NULL
;
532 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
535 PDC pDC
= DC_LockDc(hDC
);
539 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
542 Ret
= IntGdiSetMetaRgn(pDC
);
549 NEW_CLIPPING_UpdateGCRegion(PDC pDC
)
553 /* Must have VisRgn set to a valid state! */
554 ASSERT (pDC
->prgnVis
);
558 REGION_Delete(pDC
->prgnAPI
);
559 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
564 REGION_Delete(pDC
->prgnRao
);
565 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
568 if (pDC
->dclevel
.prgnMeta
&& pDC
->dclevel
.prgnClip
)
570 IntGdiCombineRgn( pDC
->prgnAPI
,
571 pDC
->dclevel
.prgnClip
,
572 pDC
->dclevel
.prgnMeta
,
577 if (pDC
->dclevel
.prgnClip
)
579 IntGdiCombineRgn( pDC
->prgnAPI
,
580 pDC
->dclevel
.prgnClip
,
584 else if (pDC
->dclevel
.prgnMeta
)
586 IntGdiCombineRgn( pDC
->prgnAPI
,
587 pDC
->dclevel
.prgnMeta
,
593 IntGdiCombineRgn( pDC
->prgnRao
,
598 RtlCopyMemory( &pDC
->erclClip
,
599 &((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.rcBound
,
602 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
604 IntGdiOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
606 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
607 // the rects from region objects rects in pClipRgn->Buffer.
608 // With pDC->co.pClipRgn->Buffer,
609 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
611 co
= IntEngCreateClipRegion( ((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.nCount
,
612 ((PROSRGNDATA
)pDC
->prgnRao
)->Buffer
,
617 if (pDC
->rosdc
.CombinedClip
!= NULL
)
618 IntEngDeleteClipRegion(pDC
->rosdc
.CombinedClip
);
620 pDC
->rosdc
.CombinedClip
= co
;
623 return IntGdiOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);