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
;
30 /* Experiment with API region based on wine.. */
31 if (Dc
->rosdc
.hClipRgn
&& Dc
->dclevel
.prgnMeta
)
35 if ((pClipRgn
= RGNOBJAPI_Lock(Dc
->rosdc
.hClipRgn
, NULL
)))
37 if (!Dc
->prgnAPI
) Dc
->prgnAPI
= IntSysCreateRectpRgn( 0, 0, 0, 0 );
39 IntGdiCombineRgn( Dc
->prgnAPI
,
43 RGNOBJAPI_Unlock(pClipRgn
);
49 GreDeleteObject(((PROSRGNDATA
)Dc
->prgnAPI
)->BaseObject
.hHmgr
);
53 if (Dc
->rosdc
.hGCClipRgn
== NULL
)
54 Dc
->rosdc
.hGCClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
56 if (Dc
->rosdc
.hClipRgn
== NULL
)
57 NtGdiCombineRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->rosdc
.hVisRgn
, 0, RGN_COPY
);
59 NtGdiCombineRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->rosdc
.hClipRgn
, Dc
->rosdc
.hVisRgn
, RGN_AND
);
61 NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, Dc
->ptlDCOrig
.x
, Dc
->ptlDCOrig
.y
);
63 if((CombinedRegion
= RGNOBJAPI_Lock(Dc
->rosdc
.hGCClipRgn
, NULL
)))
65 CLIPOBJ
*CombinedClip
;
67 CombinedClip
= IntEngCreateClipRegion(CombinedRegion
->rdh
.nCount
,
68 CombinedRegion
->Buffer
,
69 &CombinedRegion
->rdh
.rcBound
);
71 RGNOBJAPI_Unlock(CombinedRegion
);
75 DPRINT1("IntEngCreateClipRegion() failed\n");
79 if (Dc
->rosdc
.CombinedClip
!= NULL
)
80 IntEngDeleteClipRegion(Dc
->rosdc
.CombinedClip
);
82 Dc
->rosdc
.CombinedClip
= CombinedClip
;
86 return NtGdiOffsetRgn(Dc
->rosdc
.hGCClipRgn
, -Dc
->ptlDCOrig
.x
, -Dc
->ptlDCOrig
.y
);
90 GdiSelectVisRgn(HDC hdc
, HRGN hrgn
)
97 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
100 if (!(dc
= DC_LockDc(hdc
)))
102 SetLastWin32Error(ERROR_INVALID_HANDLE
);
106 dc
->fs
&= ~DC_FLAG_DIRTY_RAO
;
108 if (dc
->rosdc
.hVisRgn
== NULL
)
110 dc
->rosdc
.hVisRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
111 GDIOBJ_CopyOwnership(hdc
, dc
->rosdc
.hVisRgn
);
114 retval
= NtGdiCombineRgn(dc
->rosdc
.hVisRgn
, hrgn
, 0, RGN_COPY
);
115 if ( retval
!= ERROR
)
117 NtGdiOffsetRgn(dc
->rosdc
.hVisRgn
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
118 CLIPPING_UpdateGCRegion(dc
);
127 int FASTCALL
GdiExtSelectClipRgn(PDC dc
,
131 // dc->fs &= ~DC_FLAG_DIRTY_RAO;
135 if (fnMode
== RGN_COPY
)
137 if (dc
->rosdc
.hClipRgn
!= NULL
)
139 REGION_FreeRgnByHandle(dc
->rosdc
.hClipRgn
);
140 dc
->rosdc
.hClipRgn
= NULL
;
145 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
151 if (!dc
->rosdc
.hClipRgn
)
155 if((Rgn
= RGNOBJAPI_Lock(dc
->rosdc
.hVisRgn
, NULL
)))
157 REGION_GetRgnBox(Rgn
, &rect
);
158 RGNOBJAPI_Unlock(Rgn
);
159 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgnIndirect(&rect
);
163 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
166 if(fnMode
== RGN_COPY
)
168 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, hrgn
, 0, fnMode
);
171 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, hrgn
, fnMode
);
173 return CLIPPING_UpdateGCRegion(dc
);
177 int APIENTRY
NtGdiExtSelectClipRgn(HDC hDC
,
184 if (!(dc
= DC_LockDc(hDC
)))
186 SetLastWin32Error(ERROR_INVALID_HANDLE
);
190 retval
= GdiExtSelectClipRgn ( dc
, hrgn
, fnMode
);
197 GdiGetClipBox(HDC hDC
, PRECTL rc
)
202 HRGN hRgnNew
, hRgn
= NULL
;
204 if (!(dc
= DC_LockDc(hDC
)))
209 /* FIXME! Rao and Vis only! */
210 if (dc
->prgnAPI
) // APIRGN
212 hRgn
= ((PROSRGNDATA
)dc
->prgnAPI
)->BaseObject
.hHmgr
;
214 else if (dc
->dclevel
.prgnMeta
) // METARGN
216 hRgn
= ((PROSRGNDATA
)dc
->dclevel
.prgnMeta
)->BaseObject
.hHmgr
;
220 hRgn
= dc
->rosdc
.hClipRgn
; // CLIPRGN
225 hRgnNew
= IntSysCreateRectRgn( 0, 0, 0, 0 );
227 NtGdiCombineRgn(hRgnNew
, dc
->rosdc
.hVisRgn
, hRgn
, RGN_AND
);
229 if (!(Rgn
= RGNOBJAPI_Lock(hRgnNew
, NULL
)))
235 retval
= REGION_GetRgnBox(Rgn
, rc
);
237 REGION_FreeRgnByHandle(hRgnNew
);
238 RGNOBJAPI_Unlock(Rgn
);
243 if (!(Rgn
= RGNOBJAPI_Lock(dc
->rosdc
.hVisRgn
, NULL
)))
248 retval
= REGION_GetRgnBox(Rgn
, rc
);
249 RGNOBJAPI_Unlock(Rgn
);
250 IntDPtoLP(dc
, (LPPOINT
)rc
, 2);
257 NtGdiGetAppClipBox(HDC hDC
, PRECTL rc
)
260 NTSTATUS Status
= STATUS_SUCCESS
;
263 Ret
= GdiGetClipBox(hDC
, &Saferect
);
272 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
274 Status
= _SEH2_GetExceptionCode();
278 if(!NT_SUCCESS(Status
))
280 SetLastNtError(Status
);
287 int APIENTRY
NtGdiExcludeClipRect(HDC hDC
,
296 PDC dc
= DC_LockDc(hDC
);
300 SetLastWin32Error(ERROR_INVALID_HANDLE
);
304 Rect
.left
= LeftRect
;
306 Rect
.right
= RightRect
;
307 Rect
.bottom
= BottomRect
;
309 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
311 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
318 if (!dc
->rosdc
.hClipRgn
)
320 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
321 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hVisRgn
, NewRgn
, RGN_DIFF
);
322 Result
= SIMPLEREGION
;
326 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_DIFF
);
328 REGION_FreeRgnByHandle(NewRgn
);
331 CLIPPING_UpdateGCRegion(dc
);
338 int APIENTRY
NtGdiIntersectClipRect(HDC hDC
,
347 PDC dc
= DC_LockDc(hDC
);
349 DPRINT("NtGdiIntersectClipRect(%x, %d,%d-%d,%d)\n",
350 hDC
, LeftRect
, TopRect
, RightRect
, BottomRect
);
354 SetLastWin32Error(ERROR_INVALID_HANDLE
);
358 Rect
.left
= LeftRect
;
360 Rect
.right
= RightRect
;
361 Rect
.bottom
= BottomRect
;
363 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
365 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
370 else if (!dc
->rosdc
.hClipRgn
)
372 dc
->rosdc
.hClipRgn
= NewRgn
;
373 Result
= SIMPLEREGION
;
377 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_AND
);
378 REGION_FreeRgnByHandle(NewRgn
);
381 CLIPPING_UpdateGCRegion(dc
);
388 int APIENTRY
NtGdiOffsetClipRgn(HDC hDC
,
395 if(!(dc
= DC_LockDc(hDC
)))
397 SetLastWin32Error(ERROR_INVALID_HANDLE
);
401 if(dc
->rosdc
.hClipRgn
!= NULL
)
403 Result
= NtGdiOffsetRgn(dc
->rosdc
.hClipRgn
,
406 CLIPPING_UpdateGCRegion(dc
);
417 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
424 if(!(dc
= DC_LockDc(hDC
)))
426 SetLastWin32Error(ERROR_INVALID_HANDLE
);
430 rgn
= dc
->rosdc
.hGCClipRgn
;
433 return (rgn
? NtGdiPtInRegion(rgn
, X
, Y
) : FALSE
);
436 BOOL APIENTRY
NtGdiRectVisible(HDC hDC
,
439 NTSTATUS Status
= STATUS_SUCCESS
;
441 PDC dc
= DC_LockDc(hDC
);
447 SetLastWin32Error(ERROR_INVALID_HANDLE
);
453 ProbeForRead(UnsafeRect
,
458 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
460 Status
= _SEH2_GetExceptionCode();
464 if(!NT_SUCCESS(Status
))
467 SetLastNtError(Status
);
471 if (dc
->rosdc
.hGCClipRgn
)
473 if((Rgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(dc
->rosdc
.hGCClipRgn
, NULL
)))
475 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
476 Result
= REGION_RectInRegion(Rgn
, &Rect
);
477 RGNOBJAPI_Unlock(Rgn
);
487 IntGdiSetMetaRgn(PDC pDC
)
492 if ( pDC
->dclevel
.prgnMeta
)
494 if ( pDC
->dclevel
.prgnClip
)
496 TempRgn
= IntSysCreateRectpRgn(0,0,0,0);
499 Ret
= IntGdiCombineRgn( TempRgn
,
500 pDC
->dclevel
.prgnMeta
,
501 pDC
->dclevel
.prgnClip
,
505 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnMeta
);
506 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnMeta
)->BaseObject
.ulShareCount
)
507 REGION_Delete(pDC
->dclevel
.prgnMeta
);
509 pDC
->dclevel
.prgnMeta
= TempRgn
;
511 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnClip
);
512 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnClip
)->BaseObject
.ulShareCount
)
513 REGION_Delete(pDC
->dclevel
.prgnClip
);
515 pDC
->dclevel
.prgnClip
= NULL
;
517 IntGdiReleaseRaoRgn(pDC
);
520 REGION_Delete(TempRgn
);
524 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
528 if ( pDC
->dclevel
.prgnClip
)
530 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
531 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
532 pDC
->dclevel
.prgnClip
= NULL
;
540 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
543 PDC pDC
= DC_LockDc(hDC
);
547 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
550 Ret
= IntGdiSetMetaRgn(pDC
);
557 NEW_CLIPPING_UpdateGCRegion(PDC pDC
)
561 /* Must have VisRgn set to a valid state! */
562 if (!pDC
->prgnVis
) return ERROR
;
566 REGION_Delete(pDC
->prgnAPI
);
567 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
572 REGION_Delete(pDC
->prgnRao
);
573 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
576 if (pDC
->dclevel
.prgnMeta
&& pDC
->dclevel
.prgnClip
)
578 IntGdiCombineRgn( pDC
->prgnAPI
,
579 pDC
->dclevel
.prgnClip
,
580 pDC
->dclevel
.prgnMeta
,
585 if (pDC
->dclevel
.prgnClip
)
587 IntGdiCombineRgn( pDC
->prgnAPI
,
588 pDC
->dclevel
.prgnClip
,
592 else if (pDC
->dclevel
.prgnMeta
)
594 IntGdiCombineRgn( pDC
->prgnAPI
,
595 pDC
->dclevel
.prgnMeta
,
601 IntGdiCombineRgn( pDC
->prgnRao
,
606 RtlCopyMemory( &pDC
->erclClip
,
607 &((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.rcBound
,
610 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
612 IntGdiOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
614 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
615 // the rects from region objects rects in pClipRgn->Buffer.
616 // With pDC->co.pClipRgn->Buffer,
617 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
619 co
= IntEngCreateClipRegion( ((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.nCount
,
620 ((PROSRGNDATA
)pDC
->prgnRao
)->Buffer
,
625 if (pDC
->rosdc
.CombinedClip
!= NULL
)
626 IntEngDeleteClipRegion(pDC
->rosdc
.CombinedClip
);
628 pDC
->rosdc
.CombinedClip
= co
;
631 return IntGdiOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);