INT FASTCALL GdiGetClipBox(HDC hDC, PRECTL rc) { INT retval; PDC dc; PROSRGNDATA pRgnNew, pRgn = NULL; BOOL Unlock = FALSE; //Small hack if (!(dc = DC_LockDc(hDC))) { return ERROR; } /* FIXME! Rao and Vis only! */ if (dc->prgnAPI) // APIRGN { pRgn = dc->prgnAPI; } else if (dc->dclevel.prgnMeta) // METARGN { pRgn = dc->dclevel.prgnMeta; } else if (dc->rosdc.hClipRgn) { Unlock = TRUE ; pRgn = REGION_LockRgn(dc->rosdc.hClipRgn); // CLIPRGN } if (pRgn) { pRgnNew = IntSysCreateRectpRgn( 0, 0, 0, 0 ); if (!pRgnNew) { DC_UnlockDc(dc); if(Unlock) REGION_UnlockRgn(pRgn); return ERROR; } IntGdiCombineRgn(pRgnNew, dc->prgnVis, pRgn, RGN_AND); retval = REGION_GetRgnBox(pRgnNew, rc); REGION_Delete(pRgnNew); DC_UnlockDc(dc); if(Unlock) REGION_UnlockRgn(pRgn); return retval; } retval = REGION_GetRgnBox(dc->prgnVis, rc); IntDPtoLP(dc, (LPPOINT)rc, 2); DC_UnlockDc(dc); return retval; }
int FASTCALL CLIPPING_UpdateGCRegion(DC* Dc) { PROSRGNDATA CombinedRegion; HRGN hRgnVis; PREGION prgnClip, prgnGCClip; // would prefer this, but the rest of the code sucks // ASSERT(Dc->rosdc.hGCClipRgn); // ASSERT(Dc->rosdc.hClipRgn); ASSERT(Dc->prgnVis); hRgnVis = Dc->prgnVis->BaseObject.hHmgr; if (Dc->rosdc.hGCClipRgn == NULL) Dc->rosdc.hGCClipRgn = IntSysCreateRectRgn(0, 0, 0, 0); prgnGCClip = REGION_LockRgn(Dc->rosdc.hGCClipRgn); ASSERT(prgnGCClip); if (Dc->rosdc.hClipRgn == NULL) IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, NULL, RGN_COPY); else { prgnClip = REGION_LockRgn(Dc->rosdc.hClipRgn); // FIXME: locking order, ugh IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, prgnClip, RGN_AND); REGION_UnlockRgn(prgnClip); } REGION_UnlockRgn(prgnGCClip); NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, Dc->ptlDCOrig.x, Dc->ptlDCOrig.y); if((CombinedRegion = RGNOBJAPI_Lock(Dc->rosdc.hGCClipRgn, NULL))) { CLIPOBJ *CombinedClip; CombinedClip = IntEngCreateClipRegion(CombinedRegion->rdh.nCount, CombinedRegion->Buffer, &CombinedRegion->rdh.rcBound); RGNOBJAPI_Unlock(CombinedRegion); if ( !CombinedClip ) { DPRINT1("IntEngCreateClipRegion() failed\n"); return ERROR; } if(Dc->rosdc.CombinedClip != NULL) IntEngDeleteClipRegion(Dc->rosdc.CombinedClip); Dc->rosdc.CombinedClip = CombinedClip ; } return NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, -Dc->ptlDCOrig.x, -Dc->ptlDCOrig.y); }
int APIENTRY NtGdiExcludeClipRect(HDC hDC, int LeftRect, int TopRect, int RightRect, int BottomRect) { INT Result; RECTL Rect; PREGION prgnNew, prgnClip; PDC dc = DC_LockDc(hDC); if (!dc) { EngSetLastError(ERROR_INVALID_HANDLE); return ERROR; } Rect.left = LeftRect; Rect.top = TopRect; Rect.right = RightRect; Rect.bottom = BottomRect; IntLPtoDP(dc, (LPPOINT)&Rect, 2); prgnNew = IntSysCreateRectpRgnIndirect(&Rect); if (!prgnNew) { Result = ERROR; } else { if (!dc->rosdc.hClipRgn) { dc->rosdc.hClipRgn = IntSysCreateRectRgn(0, 0, 0, 0); prgnClip = REGION_LockRgn(dc->rosdc.hClipRgn); IntGdiCombineRgn(prgnClip, dc->prgnVis, prgnNew, RGN_DIFF); REGION_UnlockRgn(prgnClip); Result = SIMPLEREGION; } else { prgnClip = REGION_LockRgn(dc->rosdc.hClipRgn); Result = IntGdiCombineRgn(prgnClip, prgnClip, prgnNew, RGN_DIFF); REGION_UnlockRgn(prgnClip); } REGION_Delete(prgnNew); } if (Result != ERROR) CLIPPING_UpdateGCRegion(dc); DC_UnlockDc(dc); return Result; }
int APIENTRY NtGdiExtSelectClipRgn( HDC hDC, HRGN hrgn, int fnMode) { int retval; DC *dc; PREGION prgn; if (!(dc = DC_LockDc(hDC))) { EngSetLastError(ERROR_INVALID_HANDLE); return ERROR; } prgn = REGION_LockRgn(hrgn); if ((prgn == NULL) && (fnMode != RGN_COPY)) { EngSetLastError(ERROR_INVALID_HANDLE); retval = ERROR; } else { retval = IntGdiExtSelectClipRgn(dc, prgn, fnMode); } if (prgn) REGION_UnlockRgn(prgn); DC_UnlockDc(dc); return retval; }
DWORD APIENTRY NtUserCallHwndParamLock( HWND hWnd, DWORD Param, DWORD Routine) { DWORD Ret = 0; PWND Window; USER_REFERENCE_ENTRY Ref; DECLARE_RETURN(DWORD); TRACE("Enter NtUserCallHwndParamLock\n"); UserEnterExclusive(); if (!(Window = UserGetWindowObject(hWnd))) { RETURN( FALSE); } UserRefObjectCo(Window, &Ref); switch (Routine) { case TWOPARAM_ROUTINE_VALIDATERGN: { PREGION Rgn = REGION_LockRgn((HRGN)Param); if (Rgn) { Ret = (DWORD)co_UserRedrawWindow( Window, NULL, Rgn, RDW_VALIDATE); REGION_UnlockRgn(Rgn); } break; } } UserDerefObjectCo(Window); RETURN( Ret); CLEANUP: TRACE("Leave NtUserCallHwndParamLock, ret=%lu\n",_ret_); UserLeave(); END_CLEANUP; }
/* See wine, msdn, osr and Feng Yuan - Windows Graphics Programming Win32 Gdi And Directdraw 1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong! The intersection of the clip with the meta region is not Rao it's API! Go back and read 7.2 Clipping pages 418-19: Rao = API & Vis: 1) The Rao region is the intersection of the API region and the system region, named after the Microsoft engineer who initially proposed it. 2) The Rao region can be calculated from the API region and the system region. API: API region is the intersection of the meta region and the clipping region, clearly named after the fact that it is controlled by GDI API calls. */ INT APIENTRY NtGdiGetRandomRgn( HDC hdc, HRGN hrgnDest, INT iCode) { INT ret = 0; PDC pdc; HRGN hrgnSrc = NULL; POINTL ptlOrg; pdc = DC_LockDc(hdc); if (!pdc) { EngSetLastError(ERROR_INVALID_PARAMETER); return -1; } switch (iCode) { case CLIPRGN: hrgnSrc = pdc->rosdc.hClipRgn; // if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr; break; case METARGN: if (pdc->dclevel.prgnMeta) hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr; break; case APIRGN: if (pdc->prgnAPI) hrgnSrc = pdc->prgnAPI->BaseObject.hHmgr; // else if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr; else if (pdc->rosdc.hClipRgn) hrgnSrc = pdc->rosdc.hClipRgn; else if (pdc->dclevel.prgnMeta) hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr; break; case SYSRGN: if (pdc->prgnVis) { PREGION prgnDest = REGION_LockRgn(hrgnDest); ret = IntGdiCombineRgn(prgnDest, pdc->prgnVis, 0, RGN_COPY) == ERROR ? -1 : 1; REGION_UnlockRgn(prgnDest); } break; default: hrgnSrc = NULL; } if (hrgnSrc) { ret = NtGdiCombineRgn(hrgnDest, hrgnSrc, 0, RGN_COPY) == ERROR ? -1 : 1; } if (iCode == SYSRGN) { ptlOrg = pdc->ptlDCOrig; NtGdiOffsetRgn(hrgnDest, ptlOrg.x, ptlOrg.y ); } DC_UnlockDc(pdc); return ret; }
PREGION FASTCALL VIS_ComputeVisibleRegion( PWND Wnd, BOOLEAN ClientArea, BOOLEAN ClipChildren, BOOLEAN ClipSiblings) { PREGION VisRgn, ClipRgn; PWND PreviousWindow, CurrentWindow, CurrentSibling; if (!Wnd || !(Wnd->style & WS_VISIBLE)) { return NULL; } VisRgn = NULL; if (ClientArea) { VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcClient); } else { VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow); } /* * Walk through all parent windows and for each clip the visble region * to the parent's client area and exclude all siblings that are over * our window. */ PreviousWindow = Wnd; CurrentWindow = Wnd->spwndParent; while (CurrentWindow) { if (!VerifyWnd(CurrentWindow)) { ERR("ATM the Current Window or Parent is dead! %p\n",CurrentWindow); if (VisRgn) REGION_Delete(VisRgn); return NULL; } if (!(CurrentWindow->style & WS_VISIBLE)) { if (VisRgn) REGION_Delete(VisRgn); return NULL; } ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcClient); IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND); REGION_Delete(ClipRgn); if ((PreviousWindow->style & WS_CLIPSIBLINGS) || (PreviousWindow == Wnd && ClipSiblings)) { CurrentSibling = CurrentWindow->spwndChild; while ( CurrentSibling != NULL && CurrentSibling != PreviousWindow ) { if ((CurrentSibling->style & WS_VISIBLE) && !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT)) { ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentSibling->rcWindow); /* Combine it with the window region if available */ if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE)) { PREGION SiblingClipRgn = REGION_LockRgn(CurrentSibling->hrgnClip); if (SiblingClipRgn) { REGION_bOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top); IntGdiCombineRgn(ClipRgn, ClipRgn, SiblingClipRgn, RGN_AND); REGION_bOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top); REGION_UnlockRgn(SiblingClipRgn); } } IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); REGION_Delete(ClipRgn); } CurrentSibling = CurrentSibling->spwndNext; } } PreviousWindow = CurrentWindow; CurrentWindow = CurrentWindow->spwndParent; } if (ClipChildren) { CurrentWindow = Wnd->spwndChild; while (CurrentWindow) { if ((CurrentWindow->style & WS_VISIBLE) && !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT)) { ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcWindow); /* Combine it with the window region if available */ if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE)) { PREGION CurrentRgnClip = REGION_LockRgn(CurrentWindow->hrgnClip); if (CurrentRgnClip) { REGION_bOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top); IntGdiCombineRgn(ClipRgn, ClipRgn, CurrentRgnClip, RGN_AND); REGION_bOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top); REGION_UnlockRgn(CurrentRgnClip); } } IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); REGION_Delete(ClipRgn); } CurrentWindow = CurrentWindow->spwndNext; } } if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE)) { PREGION WndRgnClip = REGION_LockRgn(Wnd->hrgnClip); if (WndRgnClip) { REGION_bOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top); IntGdiCombineRgn(VisRgn, VisRgn, WndRgnClip, RGN_AND); REGION_bOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top); REGION_UnlockRgn(WndRgnClip); } } return VisRgn; }
VOID FASTCALL DceUpdateVisRgn(DCE *Dce, PWND Window, ULONG Flags) { PREGION RgnVisible = NULL; ULONG DcxFlags; PWND DesktopWindow; if (Flags & DCX_PARENTCLIP) { PWND Parent; Parent = Window->spwndParent; if (!Parent) { RgnVisible = NULL; goto noparent; } if (Parent->style & WS_CLIPSIBLINGS) { DcxFlags = DCX_CLIPSIBLINGS | (Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW)); } else { DcxFlags = Flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW); } RgnVisible = DceGetVisRgn(Parent, DcxFlags, Window->head.h, Flags); } else if (Window == NULL) { DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); if (NULL != DesktopWindow) { RgnVisible = IntSysCreateRectpRgnIndirect(&DesktopWindow->rcWindow); } else { RgnVisible = NULL; } } else { RgnVisible = DceGetVisRgn(Window, Flags, 0, 0); } noparent: if (Flags & DCX_INTERSECTRGN) { PREGION RgnClip = NULL; if (Dce->hrgnClip != NULL) RgnClip = REGION_LockRgn(Dce->hrgnClip); if (RgnClip) { IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_AND); REGION_UnlockRgn(RgnClip); } else { if (RgnVisible != NULL) { REGION_Delete(RgnVisible); } RgnVisible = IntSysCreateRectpRgn(0, 0, 0, 0); } } else if ((Flags & DCX_EXCLUDERGN) && Dce->hrgnClip != NULL) { PREGION RgnClip = REGION_LockRgn(Dce->hrgnClip); IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_DIFF); REGION_UnlockRgn(RgnClip); } Dce->DCXFlags &= ~DCX_DCEDIRTY; GdiSelectVisRgn(Dce->hDC, RgnVisible); /* Tell GDI driver */ if (Window) IntEngWindowChanged(Window, WOC_RGN_CLIENT); if (RgnVisible != NULL) { REGION_Delete(RgnVisible); } }