INT FASTCALL GdiSelectVisRgn(HDC hdc, HRGN hrgn) { int retval; DC *dc; PREGION prgn; if (!hrgn) { EngSetLastError(ERROR_INVALID_PARAMETER); return ERROR; } if (!(dc = DC_LockDc(hdc))) { EngSetLastError(ERROR_INVALID_HANDLE); return ERROR; } dc->fs &= ~DC_FLAG_DIRTY_RAO; ASSERT (dc->prgnVis != NULL); prgn = RGNOBJAPI_Lock(hrgn, NULL); retval = prgn ? IntGdiCombineRgn(dc->prgnVis, prgn, NULL, RGN_COPY) : ERROR; RGNOBJAPI_Unlock(prgn); if ( retval != ERROR ) { IntGdiOffsetRgn(dc->prgnVis, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y); CLIPPING_UpdateGCRegion(dc); } 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); }
BOOL APIENTRY NtGdiRectVisible(HDC hDC, LPRECT UnsafeRect) { NTSTATUS Status = STATUS_SUCCESS; PROSRGNDATA Rgn; PDC dc = DC_LockDc(hDC); BOOL Result = FALSE; RECTL Rect; if (!dc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } _SEH2_TRY { ProbeForRead(UnsafeRect, sizeof(RECT), 1); Rect = *UnsafeRect; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if(!NT_SUCCESS(Status)) { DC_UnlockDc(dc); SetLastNtError(Status); return FALSE; } if (dc->rosdc.hGCClipRgn) { if((Rgn = (PROSRGNDATA)RGNOBJAPI_Lock(dc->rosdc.hGCClipRgn, NULL))) { IntLPtoDP(dc, (LPPOINT)&Rect, 2); Result = REGION_RectInRegion(Rgn, &Rect); RGNOBJAPI_Unlock(Rgn); } } DC_UnlockDc(dc); return Result; }
/* * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WND */ BOOLEAN FASTCALL IntEngWndUpdateClipObj( WNDGDI *WndObjInt, PWND Window) { HRGN hVisRgn; PROSRGNDATA visRgn; CLIPOBJ *ClipObj = NULL; CLIPOBJ *OldClipObj; DPRINT("IntEngWndUpdateClipObj\n"); hVisRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE); if (hVisRgn != NULL) { NtGdiOffsetRgn(hVisRgn, Window->rcClient.left, Window->rcClient.top); visRgn = RGNOBJAPI_Lock(hVisRgn, NULL); if (visRgn != NULL) { if (visRgn->rdh.nCount > 0) { ClipObj = IntEngCreateClipRegion(visRgn->rdh.nCount, visRgn->Buffer, &visRgn->rdh.rcBound); DPRINT("Created visible region with %lu rects\n", visRgn->rdh.nCount); DPRINT(" BoundingRect: %d, %d %d, %d\n", visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top, visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom); { ULONG i; for (i = 0; i < visRgn->rdh.nCount; i++) { DPRINT(" Rect #%lu: %ld,%ld %ld,%ld\n", i+1, visRgn->Buffer[i].left, visRgn->Buffer[i].top, visRgn->Buffer[i].right, visRgn->Buffer[i].bottom); } } } RGNOBJAPI_Unlock(visRgn); } else { DPRINT1("Warning: Couldn't lock visible region of window DC\n"); } GreDeleteObject(hVisRgn); } else { DPRINT1("Warning: VIS_ComputeVisibleRegion failed!\n"); } if (ClipObj == NULL) { /* Fall back to client rect */ ClipObj = IntEngCreateClipRegion(1, &Window->rcClient, &Window->rcClient); } if (ClipObj == NULL) { DPRINT1("Warning: IntEngCreateClipRegion() failed!\n"); return FALSE; } RtlCopyMemory(&WndObjInt->WndObj.coClient, ClipObj, sizeof (CLIPOBJ)); RtlCopyMemory(&WndObjInt->WndObj.rclClient, &Window->rcClient, sizeof (RECT)); OldClipObj = InterlockedExchangePointer((PVOID*)&WndObjInt->ClientClipObj, ClipObj); if (OldClipObj != NULL) IntEngDeleteClipRegion(OldClipObj); return TRUE; }