[WIN32K] Implement RECTL_bClipRectBySize() and use it in IntEngBitBlt() to clip the...
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 11 Mar 2018 22:03:38 +0000 (23:03 +0100)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 30 Jun 2018 14:40:04 +0000 (16:40 +0200)
win32ss/gdi/eng/bitblt.c
win32ss/gdi/eng/bitblt_new.c
win32ss/gdi/ntgdi/rect.h

index 9c3e1d1..8eea775 100644 (file)
@@ -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
     {
index 56bfade..d978866 100644 (file)
@@ -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;
index 6e975c5..a268311 100644 (file)
@@ -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(