diff --git a/win32ss/gdi/eng/bitblt.c b/win32ss/gdi/eng/bitblt.c index 9c3e1d1183a..8eea77535bb 100644 --- a/win32ss/gdi/eng/bitblt.c +++ b/win32ss/gdi/eng/bitblt.c @@ -619,20 +619,26 @@ IntEngBitBlt( BOOL bResult; RECTL rclClipped; RECTL rclSrc; + RECTL rclSrcClipped; POINTL ptlBrush; PFN_DrvBitBlt pfnBitBlt; + /* Sanity checks */ + ASSERT(IS_VALID_ROP4(Rop4)); ASSERT(psoTrg); + psurfTrg = CONTAINING_RECORD(psoTrg, SURFACE, SurfObj); - /* FIXME: Should we really allow to pass non-well-ordered rects? */ + /* Get the target rect and make it well ordered */ rclClipped = *prclTrg; RECTL_vMakeWellOrdered(&rclClipped); - //DPRINT1("Rop4 : 0x%08x\n", Rop4); - - /* Sanity check */ - ASSERT(IS_VALID_ROP4(Rop4)); + /* Clip the target rect against the bounds of the target surface */ + if (!RECTL_bClipRectBySize(&rclClipped, &rclClipped, &psoTrg->sizlBitmap)) + { + /* Nothing left */ + return TRUE; + } if (pco) { @@ -660,7 +666,21 @@ IntEngBitBlt( rclSrc.top = pptlSrc->y + rclClipped.top - prclTrg->top; rclSrc.right = rclSrc.left + rclClipped.right - rclClipped.left; rclSrc.bottom = rclSrc.top + rclClipped.bottom - rclClipped.top; - pptlSrc = (PPOINTL)&rclSrc; + + /* Clip the source rect against the size of the source surface */ + if (!RECTL_bClipRectBySize(&rclSrcClipped, &rclSrc, &psoSrc->sizlBitmap)) + { + /* Nothing left */ + return TRUE; + } + + /* Fix up target rect */ + rclClipped.left += (rclSrcClipped.left - rclSrc.left); + rclClipped.top += (rclSrcClipped.top - rclSrc.top); + rclClipped.right -= (rclSrc.right - rclSrcClipped.right); + rclClipped.bottom -= (rclSrc.bottom - rclSrcClipped.bottom); + + pptlSrc = (PPOINTL)&rclSrcClipped; } else { diff --git a/win32ss/gdi/eng/bitblt_new.c b/win32ss/gdi/eng/bitblt_new.c index 56bfade89f4..d97886626ad 100644 --- a/win32ss/gdi/eng/bitblt_new.c +++ b/win32ss/gdi/eng/bitblt_new.c @@ -410,10 +410,11 @@ IntEngBitBlt( ASSERT(prclTrg); /* Clip the target rect to the extents of the target surface */ - rcClipped.left = max(prclTrg->left, 0); - rcClipped.top = max(prclTrg->top, 0); - rcClipped.right = min(prclTrg->right, psoTrg->sizlBitmap.cx); - rcClipped.bottom = min(prclTrg->bottom, psoTrg->sizlBitmap.cy); + if (!RECTL_bClipRectBySize(&rcClipped, prclTrg, &psoTrg->sizlBitmap)) + { + /* Nothing left */ + return TRUE; + } /* If no clip object is given, use trivial one */ if (!pco) pco = (CLIPOBJ*)&gxcoTrivial; diff --git a/win32ss/gdi/ntgdi/rect.h b/win32ss/gdi/ntgdi/rect.h index 6e975c5f945..a268311ad27 100644 --- a/win32ss/gdi/ntgdi/rect.h +++ b/win32ss/gdi/ntgdi/rect.h @@ -67,6 +67,20 @@ RECTL_bIsWellOrdered( (prcl->top <= prcl->bottom)); } +FORCEINLINE +BOOL +RECTL_bClipRectBySize( + _Out_ RECTL *prclDst, + _In_ const RECTL *prclSrc, + _In_ const SIZEL *pszl) +{ + prclDst->left = max(prclSrc->left, 0); + prclDst->top = max(prclSrc->top, 0); + prclDst->right = min(prclSrc->right, pszl->cx); + prclDst->bottom = min(prclSrc->bottom, pszl->cy); + return !RECTL_bIsEmptyRect(prclDst); +} + BOOL FASTCALL RECTL_bUnionRect(