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 if (dc
->prgnVis
== NULL
)
112 dc
->prgnVis
= IntSysCreateRectpRgn(0, 0, 0, 0);
113 GDIOBJ_CopyOwnership(hdc
, ((PROSRGNDATA
)dc
->prgnVis
)->BaseObject
.hHmgr
);
116 retval
= NtGdiCombineRgn(((PROSRGNDATA
)dc
->prgnVis
)->BaseObject
.hHmgr
, hrgn
, 0, RGN_COPY
);
117 if ( retval
!= ERROR
)
119 NtGdiOffsetRgn(((PROSRGNDATA
)dc
->prgnVis
)->BaseObject
.hHmgr
, -dc
->ptlDCOrig
.x
, -dc
->ptlDCOrig
.y
);
120 CLIPPING_UpdateGCRegion(dc
);
129 int FASTCALL
GdiExtSelectClipRgn(PDC dc
,
133 // dc->fs &= ~DC_FLAG_DIRTY_RAO;
137 if (fnMode
== RGN_COPY
)
139 if (dc
->rosdc
.hClipRgn
!= NULL
)
141 REGION_FreeRgnByHandle(dc
->rosdc
.hClipRgn
);
142 dc
->rosdc
.hClipRgn
= NULL
;
147 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
153 if (!dc
->rosdc
.hClipRgn
)
158 REGION_GetRgnBox(dc
->prgnVis
, &rect
);
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
)
201 PROSRGNDATA pRgnNew
, pRgn
= NULL
;
202 BOOL Unlock
= FALSE
; //Small hack
204 if (!(dc
= DC_LockDc(hDC
)))
209 /* FIXME! Rao and Vis only! */
210 if (dc
->prgnAPI
) // APIRGN
214 else if (dc
->dclevel
.prgnMeta
) // METARGN
216 pRgn
= dc
->dclevel
.prgnMeta
;
221 pRgn
= REGION_LockRgn(dc
->rosdc
.hClipRgn
); // CLIPRGN
226 pRgnNew
= IntSysCreateRectpRgn( 0, 0, 0, 0 );
231 if(Unlock
) REGION_UnlockRgn(pRgn
);
235 IntGdiCombineRgn(pRgnNew
, dc
->prgnVis
, pRgn
, RGN_AND
);
237 retval
= REGION_GetRgnBox(pRgnNew
, rc
);
239 REGION_FreeRgnByHandle(pRgnNew
->BaseObject
.hHmgr
);
241 if(Unlock
) REGION_UnlockRgn(pRgn
);
245 retval
= REGION_GetRgnBox(dc
->prgnVis
, rc
);
246 IntDPtoLP(dc
, (LPPOINT
)rc
, 2);
253 NtGdiGetAppClipBox(HDC hDC
, PRECTL rc
)
256 NTSTATUS Status
= STATUS_SUCCESS
;
259 Ret
= GdiGetClipBox(hDC
, &Saferect
);
268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
270 Status
= _SEH2_GetExceptionCode();
274 if(!NT_SUCCESS(Status
))
276 SetLastNtError(Status
);
283 int APIENTRY
NtGdiExcludeClipRect(HDC hDC
,
292 PDC dc
= DC_LockDc(hDC
);
296 SetLastWin32Error(ERROR_INVALID_HANDLE
);
300 Rect
.left
= LeftRect
;
302 Rect
.right
= RightRect
;
303 Rect
.bottom
= BottomRect
;
305 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
307 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
314 if (!dc
->rosdc
.hClipRgn
)
316 dc
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
317 NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, ((PROSRGNDATA
)dc
->prgnVis
)->BaseObject
.hHmgr
, NewRgn
, RGN_DIFF
);
318 Result
= SIMPLEREGION
;
322 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_DIFF
);
324 REGION_FreeRgnByHandle(NewRgn
);
327 CLIPPING_UpdateGCRegion(dc
);
334 int APIENTRY
NtGdiIntersectClipRect(HDC hDC
,
343 PDC dc
= DC_LockDc(hDC
);
345 DPRINT("NtGdiIntersectClipRect(%x, %d,%d-%d,%d)\n",
346 hDC
, LeftRect
, TopRect
, RightRect
, BottomRect
);
350 SetLastWin32Error(ERROR_INVALID_HANDLE
);
354 Rect
.left
= LeftRect
;
356 Rect
.right
= RightRect
;
357 Rect
.bottom
= BottomRect
;
359 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
361 NewRgn
= IntSysCreateRectRgnIndirect(&Rect
);
366 else if (!dc
->rosdc
.hClipRgn
)
368 dc
->rosdc
.hClipRgn
= NewRgn
;
369 Result
= SIMPLEREGION
;
373 Result
= NtGdiCombineRgn(dc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, NewRgn
, RGN_AND
);
374 REGION_FreeRgnByHandle(NewRgn
);
377 CLIPPING_UpdateGCRegion(dc
);
384 int APIENTRY
NtGdiOffsetClipRgn(HDC hDC
,
391 if(!(dc
= DC_LockDc(hDC
)))
393 SetLastWin32Error(ERROR_INVALID_HANDLE
);
397 if(dc
->rosdc
.hClipRgn
!= NULL
)
399 Result
= NtGdiOffsetRgn(dc
->rosdc
.hClipRgn
,
402 CLIPPING_UpdateGCRegion(dc
);
413 BOOL APIENTRY
NtGdiPtVisible(HDC hDC
,
420 if(!(dc
= DC_LockDc(hDC
)))
422 SetLastWin32Error(ERROR_INVALID_HANDLE
);
426 rgn
= dc
->rosdc
.hGCClipRgn
;
429 return (rgn
? NtGdiPtInRegion(rgn
, X
, Y
) : FALSE
);
432 BOOL APIENTRY
NtGdiRectVisible(HDC hDC
,
435 NTSTATUS Status
= STATUS_SUCCESS
;
437 PDC dc
= DC_LockDc(hDC
);
443 SetLastWin32Error(ERROR_INVALID_HANDLE
);
449 ProbeForRead(UnsafeRect
,
454 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
456 Status
= _SEH2_GetExceptionCode();
460 if(!NT_SUCCESS(Status
))
463 SetLastNtError(Status
);
467 if (dc
->rosdc
.hGCClipRgn
)
469 if((Rgn
= (PROSRGNDATA
)RGNOBJAPI_Lock(dc
->rosdc
.hGCClipRgn
, NULL
)))
471 IntLPtoDP(dc
, (LPPOINT
)&Rect
, 2);
472 Result
= REGION_RectInRegion(Rgn
, &Rect
);
473 RGNOBJAPI_Unlock(Rgn
);
483 IntGdiSetMetaRgn(PDC pDC
)
488 if ( pDC
->dclevel
.prgnMeta
)
490 if ( pDC
->dclevel
.prgnClip
)
492 TempRgn
= IntSysCreateRectpRgn(0,0,0,0);
495 Ret
= IntGdiCombineRgn( TempRgn
,
496 pDC
->dclevel
.prgnMeta
,
497 pDC
->dclevel
.prgnClip
,
501 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnMeta
);
502 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnMeta
)->BaseObject
.ulShareCount
)
503 REGION_Delete(pDC
->dclevel
.prgnMeta
);
505 pDC
->dclevel
.prgnMeta
= TempRgn
;
507 GDIOBJ_ShareUnlockObjByPtr(pDC
->dclevel
.prgnClip
);
508 if (!((PROSRGNDATA
)pDC
->dclevel
.prgnClip
)->BaseObject
.ulShareCount
)
509 REGION_Delete(pDC
->dclevel
.prgnClip
);
511 pDC
->dclevel
.prgnClip
= NULL
;
513 IntGdiReleaseRaoRgn(pDC
);
516 REGION_Delete(TempRgn
);
520 Ret
= REGION_Complexity(pDC
->dclevel
.prgnMeta
);
524 if ( pDC
->dclevel
.prgnClip
)
526 Ret
= REGION_Complexity(pDC
->dclevel
.prgnClip
);
527 pDC
->dclevel
.prgnMeta
= pDC
->dclevel
.prgnClip
;
528 pDC
->dclevel
.prgnClip
= NULL
;
536 int APIENTRY
NtGdiSetMetaRgn(HDC hDC
)
539 PDC pDC
= DC_LockDc(hDC
);
543 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
546 Ret
= IntGdiSetMetaRgn(pDC
);
553 NEW_CLIPPING_UpdateGCRegion(PDC pDC
)
557 /* Must have VisRgn set to a valid state! */
558 if (!pDC
->prgnVis
) return ERROR
;
562 REGION_Delete(pDC
->prgnAPI
);
563 pDC
->prgnAPI
= IntSysCreateRectpRgn(0,0,0,0);
568 REGION_Delete(pDC
->prgnRao
);
569 pDC
->prgnRao
= IntSysCreateRectpRgn(0,0,0,0);
572 if (pDC
->dclevel
.prgnMeta
&& pDC
->dclevel
.prgnClip
)
574 IntGdiCombineRgn( pDC
->prgnAPI
,
575 pDC
->dclevel
.prgnClip
,
576 pDC
->dclevel
.prgnMeta
,
581 if (pDC
->dclevel
.prgnClip
)
583 IntGdiCombineRgn( pDC
->prgnAPI
,
584 pDC
->dclevel
.prgnClip
,
588 else if (pDC
->dclevel
.prgnMeta
)
590 IntGdiCombineRgn( pDC
->prgnAPI
,
591 pDC
->dclevel
.prgnMeta
,
597 IntGdiCombineRgn( pDC
->prgnRao
,
602 RtlCopyMemory( &pDC
->erclClip
,
603 &((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.rcBound
,
606 pDC
->fs
&= ~DC_FLAG_DIRTY_RAO
;
608 IntGdiOffsetRgn(pDC
->prgnRao
, pDC
->ptlDCOrig
.x
, pDC
->ptlDCOrig
.y
);
610 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
611 // the rects from region objects rects in pClipRgn->Buffer.
612 // With pDC->co.pClipRgn->Buffer,
613 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
615 co
= IntEngCreateClipRegion( ((PROSRGNDATA
)pDC
->prgnRao
)->rdh
.nCount
,
616 ((PROSRGNDATA
)pDC
->prgnRao
)->Buffer
,
621 if (pDC
->rosdc
.CombinedClip
!= NULL
)
622 IntEngDeleteClipRegion(pDC
->rosdc
.CombinedClip
);
624 pDC
->rosdc
.CombinedClip
= co
;
627 return IntGdiOffsetRgn(pDC
->prgnRao
, -pDC
->ptlDCOrig
.x
, -pDC
->ptlDCOrig
.y
);