[WIN32K] Add StretchBlt function ability to flip images (#3458)
authorDoug Lyons <douglyons@douglyons.com>
Sat, 20 Feb 2021 23:28:36 +0000 (17:28 -0600)
committerGitHub <noreply@github.com>
Sat, 20 Feb 2021 23:28:36 +0000 (08:28 +0900)
Modify dib\dibxxbpp.c programs to understand flipped images. See Videos at CORE-16642

1. Mirroring Horizontally works.
2. Mirroring Vertically works.
3. Rotation 180° works.

CORE-16642, CORE-14408, CORE-16634

13 files changed:
win32ss/gdi/dib/dib16bpp.c
win32ss/gdi/dib/dib1bpp.c
win32ss/gdi/dib/dib24bpp.c
win32ss/gdi/dib/dib32bpp.c
win32ss/gdi/dib/dib32bppc.c
win32ss/gdi/dib/dib4bpp.c
win32ss/gdi/dib/dib8bpp.c
win32ss/gdi/dib/stretchblt.c
win32ss/gdi/eng/bitblt.c
win32ss/gdi/eng/copybits.c
win32ss/gdi/eng/stretchblt.c
win32ss/gdi/ntgdi/bitblt.c
win32ss/gdi/ntgdi/dibobj.c

index 6ce4568..52789cf 100644 (file)
@@ -6,6 +6,7 @@
  * PROGRAMMERS:     Jason Filby
  *                  Thomas Bluemel
  *                  Gregor Anich
+ *                  Doug Lyons
  */
 
 #include <win32k.h>
@@ -13,6 +14,9 @@
 #define NDEBUG
 #include <debug.h>
 
+#define DEC_OR_INC(var, decTrue, amount) \
+    ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
+
 VOID
 DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
 {
@@ -142,17 +146,66 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
   LONG     i, j, sx, sy, xColor, f1;
   PBYTE    SourceBits, DestBits, SourceLine, DestLine;
   PBYTE    SourceBits_4BPP, SourceLine_4BPP;
+  PWORD    Source32, Dest32;
+  DWORD    Index, StartLeft, EndRight;
+  BOOLEAN  bTopToBottom, bLeftToRight;
+
+  DPRINT("DIB_16BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
+         BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
+         BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
+         BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
+
+  /* Get back left to right flip here */
+  bLeftToRight = BltInfo->DestRect.left > BltInfo->DestRect.right;
+
+  /* Check for top to bottom flip needed. */
+  bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
+
+  DPRINT("BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
+         BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
+
+  /* Make WellOrdered with top < bottom and left < right */
+  RECTL_vMakeWellOrdered(&BltInfo->DestRect);
+
+  DPRINT("BPP is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
+         BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
+
   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
 
   switch(BltInfo->SourceSurface->iBitmapFormat)
   {
   case BMF_1BPP:
+    DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
     sx = BltInfo->SourcePoint.x;
+
+    /* This sets sy to the top line */
     sy = BltInfo->SourcePoint.y;
+
+    if (bTopToBottom)
+    {
+      /* This sets sy to the bottom line */
+      sy += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+    }
+
     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
     {
       sx = BltInfo->SourcePoint.x;
-      for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
+
+      if (bLeftToRight)
+      {
+        /* This sets the sx to the rightmost pixel */
+        sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        StartLeft = BltInfo->DestRect.left + 1;
+        EndRight = BltInfo->DestRect.right + 1;
+      }
+      else
+      {
+        StartLeft = BltInfo->DestRect.left;
+        EndRight = BltInfo->DestRect.right;
+      }
+
+      for (i = StartLeft; i < EndRight; i++)
       {
         if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
         {
@@ -164,21 +217,37 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
             XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
         }
-        sx++;
+        DEC_OR_INC(sx, bLeftToRight, 1);
       }
-      sy++;
+      DEC_OR_INC(sy, bTopToBottom, 1);
     }
     break;
 
   case BMF_4BPP:
+    DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+    /* This sets SourceBits_4BPP to the top line */
     SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
       (BltInfo->SourcePoint.x >> 1);
 
+    if (bTopToBottom)
+    {
+      /* This sets SourceBits_4BPP to the bottom line */
+      SourceBits_4BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
+    }
+
     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
     {
       SourceLine_4BPP = SourceBits_4BPP;
       sx = BltInfo->SourcePoint.x;
+      if (bLeftToRight)
+      {
+        /* This sets sx to the rightmost pixel */
+        sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+      }
+
       f1 = sx & 1;
 
       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
@@ -188,49 +257,76 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
         DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
         if(f1 == 1)
         {
-          SourceLine_4BPP++;
+          DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
           f1 = 0;
         }
         else
         {
           f1 = 1;
         }
-        sx++;
+        DEC_OR_INC(sx, bLeftToRight, 1);
       }
-      SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
+      DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
     }
     break;
 
   case BMF_8BPP:
+    DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+    /* This sets SourceLine to the top line */
     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
       BltInfo->SourcePoint.x;
     DestLine = DestBits;
 
+    if (bTopToBottom)
+    {
+      /* This sets SourceLine to the bottom line */
+      SourceLine += BltInfo->SourceSurface->lDelta 
+        * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+    }
+
     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
     {
       SourceBits = SourceLine;
       DestBits = DestLine;
 
+      if (bLeftToRight)
+      {
+        /* This sets SourceBits to the rightmost pixel */
+        SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+      }
+
       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
       {
         *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
           BltInfo->XlateSourceToDest, *SourceBits);
-        SourceBits += 1;
+        DEC_OR_INC(SourceBits, bLeftToRight, 1);
         DestBits += 2;
       }
-
-      SourceLine += BltInfo->SourceSurface->lDelta;
+      DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
       DestLine += BltInfo->DestSurface->lDelta;
     }
     break;
 
   case BMF_16BPP:
-    if (NULL == BltInfo->XlateSourceToDest || 0 !=
-      (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
+    DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+    DPRINT("BMF_16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+           BltInfo->DestRect.left, BltInfo->DestRect.top,
+           BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+    if ((BltInfo->XlateSourceToDest == NULL ||
+      (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
+      (!bTopToBottom && !bLeftToRight))
     {
+      DPRINT("XO_TRIVIAL is TRUE.\n");
       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
       {
+        /* This sets SourceBits to the top line */
         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
           (BltInfo->SourcePoint.y *
           BltInfo->SourceSurface->lDelta) + 2 *
@@ -248,6 +344,7 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
       }
       else
       {
+        /* This sets SourceBits to the bottom line */
         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
           ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom -
           BltInfo->DestRect.top - 1) *
@@ -273,6 +370,11 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
     }
     else
     {
+      DPRINT("XO_TRIVIAL is NOT TRUE.\n");
+      if (!bTopToBottom && !bLeftToRight)
+      /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
+    {
+      DPRINT("Flip is None.\n");
       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
       {
         SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
@@ -330,14 +432,165 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           DestLine -= BltInfo->DestSurface->lDelta;
         }
       }
+    }
+      else
+      {
+        /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
+        BOOL TopToBottomDone = FALSE;
+
+        if (bLeftToRight)
+        {
+          DPRINT("Flip is bLeftToRight.\n");
+
+          /* Allocate enough pixels for a row in WORD's */
+          WORD *store = ExAllocatePoolWithTag(NonPagedPool,
+            (BltInfo->DestRect.right - BltInfo->DestRect.left + 1) * 2, TAG_DIB);
+          if (store == NULL)
+          {
+            DPRINT1("Storage Allocation Failed.\n");
+            return FALSE;
+          }
+          WORD  Index;
+
+          /* This sets SourceBits to the bottom line */
+          SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+            + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
+            * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
+
+          /* Sets DestBits to the bottom line */
+          DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+           + (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
+           + 2 * BltInfo->DestRect.left + 2;
+
+          for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
+          {
+            /* Set Dest32 to right pixel */
+            Dest32 = (WORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+            Source32 = (WORD *) SourceBits;
+
+            Index = 0;
+
+            /* Store pixels from left to right */
+            for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
+            {
+              store[Index] = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *(WORD *)Source32++);
+              Index++;
+            }
+
+            Index = 0;
+
+            /* Copy stored data to pixels from right to left */
+            for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
+            {
+              *(WORD *)Dest32-- = store[Index];
+              Index++;
+            }
+
+            SourceBits -= BltInfo->SourceSurface->lDelta;
+            DestBits -= BltInfo->DestSurface->lDelta;
+          }
+          ExFreePoolWithTag(store, TAG_DIB);
+          TopToBottomDone = TRUE;
+        }
+
+        if (bTopToBottom)
+        {
+          DPRINT("Flip is bTopToBottom.\n");
+
+          /* Allocate enough pixels for a column in WORD's */
+          WORD *store = ExAllocatePoolWithTag(NonPagedPool,
+            (BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1) * 2, TAG_DIB);
+          if (store == NULL)
+          {
+            DPRINT1("Storage Allocation Failed.\n");
+            return FALSE;
+          }
+
+          /* This set SourceBits to the top line */
+          SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+            + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+            + 2 * BltInfo->SourcePoint.x;
+
+          /* This sets DestBits to the top line */
+          DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+           + ((BltInfo->DestRect.top) * BltInfo->DestSurface->lDelta)
+           + 2 * BltInfo->DestRect.left;
+
+          if ((BltInfo->SourceSurface->fjBitmap & BMF_TOPDOWN) == 0)
+          {
+            DestBits += BltInfo->DestSurface->lDelta;
+          }
+
+          if (bLeftToRight)
+          {
+            DPRINT("Adjusting DestBits for bLeftToRight.\n");
+            DestBits += 2;
+          }
+
+          /* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
+           * and have already completed the bLeftToRight. So we will lose our first flip output
+           * unless we work with its output which is at the destination site. So in this case
+           * our new Source becomes the previous outputs Destination. */
+
+          if (TopToBottomDone)
+          {
+            /* This sets SourceBits to the top line */
+            SourceBits = DestBits;
+          }
+
+          for (j = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= j ; j--)
+          {
+            /* Set Dest32 to bottom pixel */
+            Dest32 = (WORD *) DestBits  + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
+              * BltInfo->DestSurface->lDelta / 2;
+            Source32 = (WORD *) SourceBits;
+
+            Index = 0;
+
+            /* Store pixels from top to bottom */
+            for (i = BltInfo->DestRect.top; i <= BltInfo->DestRect.bottom - 1; i++)
+            {
+              store[Index] = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32);
+              Source32 += BltInfo->SourceSurface->lDelta / 2;
+              Index++;
+            }
+
+            Index = 0;
+
+            /* Copy stored data to pixels from bottom to top */
+            for (i = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= i; i--)
+            {
+              *Dest32 = store[Index];
+              Dest32 -= BltInfo->DestSurface->lDelta / 2;
+              Index++;
+            }
+            SourceBits += 2;
+            DestBits += 2;
+          }
+          ExFreePoolWithTag(store, TAG_DIB);
+        }
+
+      }
     }
     break;
 
   case BMF_24BPP:
+
+    DPRINT("BMF_24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+           BltInfo->DestRect.left, BltInfo->DestRect.top,
+           BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+    /* This sets SourceLine to the top line */
     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
       3 * BltInfo->SourcePoint.x;
 
+    if (bTopToBottom)
+    {
+      /* This sets SourceLine to the bottom line */
+      SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+    }
     DestLine = DestBits;
 
     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@@ -345,6 +598,11 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
       SourceBits = SourceLine;
       DestBits = DestLine;
 
+      if (bLeftToRight)
+      {
+        /* This sets the SourceBits to the rightmost pixel */
+        SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3;
+      }
       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
       {
         xColor = (*(SourceBits + 2) << 0x10) +
@@ -353,19 +611,27 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
         *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
           BltInfo->XlateSourceToDest, xColor);
 
-        SourceBits += 3;
+        DEC_OR_INC(SourceBits, bLeftToRight, 3);
         DestBits += 2;
       }
-      SourceLine += BltInfo->SourceSurface->lDelta;
+      DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
       DestLine += BltInfo->DestSurface->lDelta;
     }
     break;
 
   case BMF_32BPP:
+    DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
       4 * BltInfo->SourcePoint.x;
 
+    if (bTopToBottom)
+    {
+      /* This sets SourceLine to the bottom line */
+      SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
+    }
     DestLine = DestBits;
 
     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@@ -373,23 +639,29 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
       SourceBits = SourceLine;
       DestBits = DestLine;
 
+      if (bLeftToRight)
+      {
+        /* This sets SourceBits to the rightmost pixel */
+        SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
+      }
+
       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
       {
         *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
           BltInfo->XlateSourceToDest,
           *((PDWORD) SourceBits));
-        SourceBits += 4;
+        DEC_OR_INC(SourceBits, bLeftToRight, 4);
         DestBits += 2;
       }
 
-      SourceLine += BltInfo->SourceSurface->lDelta;
+      DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
       DestLine += BltInfo->DestSurface->lDelta;
     }
     break;
 
   default:
-    DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n",
-      BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
+    DPRINT1("DIB_16BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n",
+            BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
     return FALSE;
   }
 
@@ -402,6 +674,9 @@ DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
 {
   LONG DestY;
 
+  /* Make WellOrdered with top < bottom and left < right */
+  RECTL_vMakeWellOrdered(DestRect);
+
 #if defined(_M_IX86) && !defined(_MSC_VER)
   /* This is about 10% faster than the generic C code below */
   ULONG delta = DestSurface->lDelta;
index e5dc0fd..034570e 100644 (file)
@@ -4,6 +4,7 @@
  * FILE:            win32ss/gdi/dib/dib1bpp.c
  * PURPOSE:         Device Independant Bitmap functions, 1bpp
  * PROGRAMMERS:     Jason Filby
+ *                  Doug Lyons
  */
 
 #include <win32k.h>
@@ -11,6 +12,9 @@
 #define NDEBUG
 #include <debug.h>
 
+#define DEC_OR_INC(var, decTrue, amount) \
+    ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
+
 VOID
 DIB_1BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
 {
@@ -57,13 +61,18 @@ DIB_1BPP_BitBltSrcCopy_From1BPP (
                                  SURFOBJ* SourceSurf,
                                  XLATEOBJ* pxlo,
                                  PRECTL DestRect,
-                                 POINTL *SourcePoint )
+                                 POINTL *SourcePoint,
+                                 BOOLEAN bTopToBottom,
+                                 BOOLEAN bLeftToRight )
 {
+
+  DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
+
   // The 'window' in this sense is the x-position that corresponds
   // to the left-edge of the 8-pixel byte we are currently working with.
   // dwx is current x-window, dwx2 is the 'last' window we need to process.
   int dwx, dwx2;  // Destination window x-position
-  int swx;        // Source window y-position
+  int swx;        // Source window x-position
 
   // Left and right edges of source and dest rectangles
   int dl = DestRect->left; // dest left
@@ -96,39 +105,75 @@ DIB_1BPP_BitBltSrcCopy_From1BPP (
 
   if ( DestRect->top <= SourcePoint->y )
   {
+    DPRINT("Moving up (scan top -> bottom).\n");
     // Moving up (scan top -> bottom)
     dy1 = DestRect->top;
     dy2 = DestRect->bottom - 1;
-    sy1 = SourcePoint->y;
+    if (bTopToBottom)
+    {
+      sy1 = SourcePoint->y + dy2 - dy1;
+      ySrcDelta = -SourceSurf->lDelta;
+    }
+    else
+    {
+      sy1 = SourcePoint->y;
+      ySrcDelta = SourceSurf->lDelta;
+    }
     yinc = 1;
-    ySrcDelta = SourceSurf->lDelta;
     yDstDelta = DestSurf->lDelta;
   }
   else
   {
+    DPRINT("Moving down (scan bottom -> top).\n");
     // Moving down (scan bottom -> top)
     dy1 = DestRect->bottom - 1;
     dy2 = DestRect->top;
-    sy1 = SourcePoint->y + dy1 - dy2;
+    if (bTopToBottom)
+    {
+      sy1 = SourcePoint->y;
+      ySrcDelta = SourceSurf->lDelta;
+    }
+    else
+    {
+      sy1 = SourcePoint->y + dy1 - dy2;
+      ySrcDelta = -SourceSurf->lDelta;
+    }
     yinc = -1;
-    ySrcDelta = -SourceSurf->lDelta;
     yDstDelta = -DestSurf->lDelta;
   }
   if ( DestRect->left <= SourcePoint->x )
   {
+    DPRINT("Moving left (scan left->right).\n");
     // Moving left (scan left->right)
     dwx = dl&~7;
-    swx = (sl-(dl&7))&~7;
     dwx2 = dr&~7;
-    xinc = 1;
+    if (bLeftToRight)
+    {
+      swx = (sr - (dr & 7)) & ~7;
+      xinc = -1;
+    }
+    else
+    {
+      swx = (sl-(dl&7))&~7;
+      xinc = 1;
+    }
   }
   else
   {
+    DPRINT("Moving right (scan right->left).\n");
     // Moving right (scan right->left)
     dwx = dr & ~7;
-    swx = (sr - (dr & 7)) & ~7; // (sr - 7) & ~7; // We need the left edge of this block. Thus the -7
     dwx2 = dl & ~7;
-    xinc = -1;
+    if (bLeftToRight)
+    {
+      swx = (sl-(dl&7))&~7;
+      xinc = 1;
+    }
+    else
+    {
+      swx = (sr - (dr & 7)) & ~7; // (sr - 7) & ~7; // We need the left edge of this block. Thus the -7
+      xinc = -1;
+    }
   }
   d = &(((PBYTE)DestSurf->pvScan0)[dy1*DestSurf->lDelta + (dwx>>3)]);
   s = &(((PBYTE)SourceSurf->pvScan0)[sy1*SourceSurf->lDelta + (swx>>3)]);
@@ -227,81 +272,199 @@ BOOLEAN
 DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)
 {
   ULONG Color;
-  LONG i, j, sx, sy = BltInfo->SourcePoint.y;
+  LONG i, j, sx, sy;
+  BOOLEAN bTopToBottom, bLeftToRight;
+
+  // This sets sy to the top line
+  sy = BltInfo->SourcePoint.y;
+
+  DPRINT("DIB_1BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
+         BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
+         BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
+         BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
+
+  /* Get back left to right flip here */
+  bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
+
+  /* Check for top to bottom flip needed. */
+  bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
+
+  // Make WellOrdered with top < bottom and left < right
+  RECTL_vMakeWellOrdered(&BltInfo->DestRect);
+
+  DPRINT("BPP is '%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
+         BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
 
   switch ( BltInfo->SourceSurface->iBitmapFormat )
   {
   case BMF_1BPP:
-    DIB_1BPP_BitBltSrcCopy_From1BPP ( BltInfo->DestSurface, BltInfo->SourceSurface, BltInfo->XlateSourceToDest, &BltInfo->DestRect, &BltInfo->SourcePoint );
+    DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+    DIB_1BPP_BitBltSrcCopy_From1BPP ( BltInfo->DestSurface, BltInfo->SourceSurface,
+      BltInfo->XlateSourceToDest, &BltInfo->DestRect, &BltInfo->SourcePoint,
+      bTopToBottom, bLeftToRight );
     break;
 
   case BMF_4BPP:
+    DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+    if (bTopToBottom)
+    {
+      // This sets sy to the bottom line
+      sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
+    }
+
     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
     {
       sx = BltInfo->SourcePoint.x;
+
+      if (bLeftToRight)
+      {
+       // This sets the sx to the rightmost pixel
+       sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+      }
+
       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
       {
         Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
         DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
-        sx++;
+
+        DEC_OR_INC(sx, bLeftToRight, 1);
       }
-      sy++;
+      DEC_OR_INC(sy, bTopToBottom, 1);
     }
     break;
 
   case BMF_8BPP:
+    DPRINT("8BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+           BltInfo->DestRect.left, BltInfo->DestRect.top,
+           BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+    if (bTopToBottom)
+    {
+      // This sets sy to the bottom line
+      sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
+    }
+
     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
     {
       sx = BltInfo->SourcePoint.x;
+
+      if (bLeftToRight)
+      {
+        // This sets sx to the rightmost pixel
+        sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+      }
+
       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
       {
         Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_8BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
         DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
-        sx++;
+
+        DEC_OR_INC(sx, bLeftToRight, 1);
       }
-      sy++;
+      DEC_OR_INC(sy, bTopToBottom, 1);
     }
     break;
 
   case BMF_16BPP:
+    DPRINT("16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+           BltInfo->DestRect.left, BltInfo->DestRect.top,
+           BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+    if (bTopToBottom)
+    {
+      // This sets sy to the bottom line
+      sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;;
+    }
+
     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
     {
       sx = BltInfo->SourcePoint.x;
+
+      if (bLeftToRight)
+      {
+        // This sets the sx to the rightmost pixel
+        sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+      }
+
       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
       {
         Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_16BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
         DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
-        sx++;
+        DEC_OR_INC(sx, bLeftToRight, 1);
       }
-      sy++;
+      DEC_OR_INC(sy, bTopToBottom, 1);
     }
     break;
 
   case BMF_24BPP:
+
+    DPRINT("24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+           BltInfo->DestRect.left, BltInfo->DestRect.top,
+           BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      if (bTopToBottom)
+      {
+        // This sets sy to the bottom line
+        sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
+      }
+
     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
     {
       sx = BltInfo->SourcePoint.x;
+
+      if (bLeftToRight)
+      {
+        // This sets the sx to the rightmost pixel
+        sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+      }
+
       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
       {
         Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
         DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
-        sx++;
+        DEC_OR_INC(sx, bLeftToRight, 1);
       }
-      sy++;
+      DEC_OR_INC(sy, bTopToBottom, 1);
     }
     break;
 
   case BMF_32BPP:
+
+    DPRINT("32BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+           BltInfo->DestRect.left, BltInfo->DestRect.top,
+           BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+           BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+    if (bTopToBottom)
+    {
+      // This sets sy to the bottom line
+      sy += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
+    }
+
     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
     {
       sx = BltInfo->SourcePoint.x;
+
+      if (bLeftToRight)
+      {
+        // This sets the sx to the rightmost pixel
+        sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+      }
+
       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
       {
         Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_32BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
         DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
-        sx++;
+        DEC_OR_INC(sx, bLeftToRight, 1);
       }
-      sy++;
+      DEC_OR_INC(sy, bTopToBottom, 1);
     }
     break;
 
@@ -460,6 +623,9 @@ DIB_1BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
 {
   LONG DestY;
 
+  /* Make WellOrdered with top < bottom and left < right */
+  RECTL_vMakeWellOrdered(DestRect);
+
   for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
   {
     DIB_1BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
index 0974842..bc12095 100644 (file)
@@ -6,6 +6,7 @@
  * PROGRAMMERS:     Jason Filby
  *                  Thomas Bluemel
  *                  Gregor Anich
+ *                  Doug Lyons
  */
 
 #include <win32k.h>
@@ -13,6 +14,9 @@
 #define NDEBUG
 #include <debug.h>
 
+#define DEC_OR_INC(var, decTrue, amount) \
+    ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
+
 VOID
 DIB_24BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
 {
@@ -53,6 +57,24 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
   PBYTE    SourceBits, DestBits, SourceLine, DestLine;
   PBYTE    SourceBits_4BPP, SourceLine_4BPP;
   PWORD    SourceBits_16BPP, SourceLine_16BPP;
+  BOOLEAN  bTopToBottom, bLeftToRight;
+
+  DPRINT("DIB_24BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
+         BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
+         BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
+         BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
+
+  /* Get back left to right flip here */
+  bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
+
+  /* Check for top to bottom flip needed. */
+  bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
+
+  DPRINT("BltInfo->SourcePoint.x is '%d' and BltInfo->SourcePoint.y is '%d'.\n",
+         BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
+
+  /* Make WellOrdered by making top < bottom and left < right */
+  RECTL_vMakeWellOrdered(&BltInfo->DestRect);
 
   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left * 3;
 
@@ -60,11 +82,26 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
   {
     case BMF_1BPP:
       sx = BltInfo->SourcePoint.x;
+
+      /* This sets sy to the top line */
       sy = BltInfo->SourcePoint.y;
 
+      if (bTopToBottom)
+      {
+        /* This sets sy to the bottom line */
+        sy += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+      }
+
       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
       {
         sx = BltInfo->SourcePoint.x;
+
+        if (bLeftToRight)
+        {
+          /* This sets sx to the rightmost pixel */
+          sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        }
+
         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
         {
           if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
@@ -73,20 +110,37 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           } else {
             DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
           }
-          sx++;
+          DEC_OR_INC(sx, bLeftToRight, 1);
         }
-        sy++;
+        DEC_OR_INC(sy, bTopToBottom, 1);
       }
       break;
 
     case BMF_4BPP:
+      DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      /* This sets SourceBits_4BPP to the top line */
       SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
 
+      if (bTopToBottom)
+      {
+        /* This sets SourceBits_4BPP to the bottom line */
+        SourceBits_4BPP += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+      }
+
       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
       {
         SourceLine_4BPP = SourceBits_4BPP;
         DestLine = DestBits;
         sx = BltInfo->SourcePoint.x;
+
+        if (bLeftToRight)
+        {
+          /* This sets sx to the rightmost pixel */
+          sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        }
+
         f1 = sx & 1;
 
         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
@@ -96,17 +150,33 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           *DestLine++ = xColor & 0xff;
           *(PWORD)DestLine = (WORD)(xColor >> 8);
           DestLine += 2;
-          if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
-          sx++;
+          if(f1 == 1) {
+            DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
+            f1 = 0;
+          } 
+          else
+          { 
+            f1 = 1;
+          }
+          DEC_OR_INC(sx, bLeftToRight, 1);
         }
-
-        SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestBits += BltInfo->DestSurface->lDelta;
       }
       break;
 
     case BMF_8BPP:
+      DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      /* This sets SourceLine to the top line */
       SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
+
+      if (bTopToBottom)
+      {
+        /* This sets SourceLine to the bottom line */
+        SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+      }
       DestLine = DestBits;
 
       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@@ -114,47 +184,83 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
         SourceBits = SourceLine;
         DestBits = DestLine;
 
+        if (bLeftToRight)
+        {
+          /* This sets the SourceBits to the rightmost pixel */
+          SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        }
+
         for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
         {
           xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
           *DestBits = xColor & 0xff;
           *(PWORD)(DestBits + 1) = (WORD)(xColor >> 8);
-          SourceBits += 1;
+          DEC_OR_INC(SourceBits, bLeftToRight, 1);
           DestBits += 3;
         }
 
-        SourceLine += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestLine += BltInfo->DestSurface->lDelta;
       }
       break;
 
     case BMF_16BPP:
+      DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      /* This sets SourceBits_16BPP to the top line */
       SourceBits_16BPP = (PWORD)((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x);
 
+      if (bTopToBottom)
+      {
+        /* This sets SourceBits_16BPP to the bottom line */
+        SourceBits_16BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
+      }
+
       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
       {
         SourceLine_16BPP = SourceBits_16BPP;
         DestLine = DestBits;
 
+        if (bLeftToRight)
+        {
+          /* This sets the SourceLine_16BPP to the rightmost pixel */
+          SourceLine_16BPP += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        }
+
         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
         {
           xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceLine_16BPP);
           *DestLine++ = xColor & 0xff;
           *(PWORD)DestLine = (WORD)(xColor >> 8);
           DestLine += 2;
-          SourceLine_16BPP++;
+          DEC_OR_INC(SourceLine_16BPP, bLeftToRight, 1);
+        }
+        if (bTopToBottom)
+        {
+          SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP - BltInfo->SourceSurface->lDelta);
+        }
+        else
+        {
+          SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP + BltInfo->SourceSurface->lDelta);
         }
-
-        SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP + BltInfo->SourceSurface->lDelta);
         DestBits += BltInfo->DestSurface->lDelta;
       }
       break;
 
     case BMF_24BPP:
-      if (NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
+      DPRINT("24BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      /* Check for no flips here because we are about to use RtlMoveMemory and it can only do increasing src & dst */
+      if ((BltInfo->XlateSourceToDest == NULL ||
+        (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
+        (!bTopToBottom && !bLeftToRight))
       {
+        DPRINT("XO_TRIVIAL is TRUE.\n");
         if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
         {
+          /* This sets SourceBits to the top line */
           SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
           for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
           {
@@ -176,6 +282,11 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
         }
       }
       else
+      {
+        DPRINT("XO_TRIVIAL is NOT TRUE.\n");
+
+        if (!bTopToBottom && !bLeftToRight)
+      /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
       {
         sx = BltInfo->SourcePoint.x;
         sy = BltInfo->SourcePoint.y;
@@ -191,11 +302,151 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           }
           sy++;
         }
+      }
+        else
+        {
+          /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
+          BOOL TopToBottomDone = FALSE;
+
+          if (bLeftToRight)
+          {
+            DPRINT("Flip is bLeftToRight.\n");
+            DWORD  Index;
+
+            /* Allocate enough pixels for a row in DWORD's */
+            DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
+              (BltInfo->DestRect.right - BltInfo->DestRect.left + 1) * 4, TAG_DIB);
+            if (store == NULL)
+            {
+              DPRINT1("Storage Allocation Failed.\n");
+              return FALSE;
+            }
+
+            sx = BltInfo->SourcePoint.x;
+            /* This sets sy to the top line */
+            sy = BltInfo->SourcePoint.y;
+
+            /* This sets sx to the rightmost pixel */
+            sx = BltInfo->SourcePoint.x + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+
+            for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
+            {
+
+              /* This sets sx to the rightmost pixel */
+              sx = BltInfo->SourcePoint.x + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+
+              Index = 0;
+
+              // Read right to left and store
+              for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
+              {
+                store[Index] = DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy);
+                Index++;
+                sx--;
+              }
+
+              Index = 0;
+
+              // Write left to right to pixel
+              for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
+              {
+                DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, store[Index]));
+                Index++;
+              }
+              sy++;
+            }
+            ExFreePoolWithTag(store, TAG_DIB);
+            TopToBottomDone = TRUE;
+          }
+
+          if (bTopToBottom)
+          {
+            DPRINT("Flip is bTopToBottom.\n");
+            DWORD  Index;
+
+            /* Allocate enough pixels for a column in DWORD's */
+            DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
+              (BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1) * 4, TAG_DIB);
+            if (store == NULL)
+            {
+              DPRINT1("Storage Allocation Failed.\n");
+              return FALSE;
+            }
+
+            /* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
+             * and have already completed the bLeftToRight. So we will lose our first flip output
+             * unless we work with its output which is at the destination site. So in this case
+             * our new Source becomes the previous outputs Destination.
+             */
+
+            if (TopToBottomDone)
+            {
+             sx = BltInfo->DestRect.left;
+              sy = BltInfo->DestRect.top;
+
+              /* This sets sy to the bottom line */
+              sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+            }
+            else
+            {
+              sx = BltInfo->SourcePoint.x;
+
+              /* This sets sy to the top line */
+              sy = BltInfo->SourcePoint.y;
+
+              /* This sets sy to the bottom line */
+              sy = BltInfo->SourcePoint.y + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+            }
+
+            for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
+            {
+
+              /* This sets sy to the bottom line */
+              sy = BltInfo->SourcePoint.y + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+              Index = 0;
+
+              /* Read bottom to top and store */
+              for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
+              {
+                if (TopToBottomDone)
+                {
+                  store[Index] = DIB_24BPP_GetPixel(BltInfo->DestSurface, sx, sy);
+                }
+                else
+                {
+                  store[Index] = DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy);
+                }
+                Index++;
+                sy--;
+              }
+
+              Index = 0;
+
+              for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
+              {
+                DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, store[Index]));
+                Index++;
+              }
+              sx++;
+            }
+            ExFreePoolWithTag(store, TAG_DIB);
+          }
+
+        }
       }
       break;
 
     case BMF_32BPP:
+      DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
       SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
+
+      if (bTopToBottom)
+      {
+        /* This sets SourceLine to the bottom line */
+        SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
+      }
       DestLine = DestBits;
 
       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@@ -203,16 +454,21 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
         SourceBits = SourceLine;
         DestBits = DestLine;
 
+        if (bLeftToRight)
+        {
+          /* This sets SourceBits to the rightmost pixel */
+          SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
+        }
         for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
         {
           xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((PDWORD) SourceBits));
           *DestBits = xColor & 0xff;
           *(PWORD)(DestBits + 1) = (WORD)(xColor >> 8);
-          SourceBits += 4;
+          DEC_OR_INC(SourceBits, bLeftToRight, 4);
           DestBits += 3;
         }
 
-        SourceLine += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestLine += BltInfo->DestSurface->lDelta;
       }
       break;
@@ -255,7 +511,9 @@ DIB_24BPP_BitBlt(PBLTINFO BltInfo)
       else
       {
          if (BltInfo->Brush)
+         {
             Pattern = BltInfo->Brush->iSolidColor;
+         }
       }
    }
 
@@ -301,6 +559,9 @@ DIB_24BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
 {
   LONG DestY;
 
+  /* Make WellOrdered by making top < bottom and left < right */
+  RECTL_vMakeWellOrdered(DestRect);
+
 #if defined(_M_IX86) && !defined(_MSC_VER)
   PBYTE xaddr = (PBYTE)DestSurface->pvScan0 + DestRect->top * DestSurface->lDelta + (DestRect->left << 1) + DestRect->left;
   PBYTE addr;
index 78124b8..1b2d920 100644 (file)
@@ -6,6 +6,7 @@
  * PROGRAMMERS:     Jason Filby
  *                  Thomas Bluemel
  *                  Gregor Anich
+ *                  Doug Lyons
  */
 
 #include <win32k.h>
@@ -13,6 +14,9 @@
 #define NDEBUG
 #include <debug.h>
 
+#define DEC_OR_INC(var, decTrue, amount) \
+    ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
+
 VOID
 DIB_32BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
 {
@@ -51,46 +55,137 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
 {
   LONG     i, j, sx, sy, xColor, f1;
   PBYTE    SourceBits, DestBits, SourceLine, DestLine;
+  PBYTE    SourceBitsT, SourceBitsB, DestBitsT, DestBitsB;
   PBYTE    SourceBits_4BPP, SourceLine_4BPP;
   PDWORD   Source32, Dest32;
+  DWORD    Index, DestWidth, DestHeight;
+  BOOLEAN  bTopToBottom, bLeftToRight;
+  BOOLEAN  blDeltaSrcNeg, blDeltaDestNeg;
+  BOOLEAN  blDeltaAdjustDone = FALSE;
+
+  DPRINT("DIB_32BPP_BitBltSrcCopy: SourcePoint (%d, %d), SourceSurface cx/cy (%d/%d), "
+         "DestSurface cx/cy (%d/%d) DestRect: (%d,%d)-(%d,%d)\n",
+         BltInfo->SourcePoint.x, BltInfo->SourcePoint.y,
+         BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
+         BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
+         BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
+
+  DPRINT("BltInfo->DestSurface->lDelta is '%d' and BltInfo->SourceSurface->lDelta is '%d'.\n",
+           BltInfo->DestSurface->lDelta,  BltInfo->SourceSurface->lDelta);
+
+  DPRINT("iBitmapFormat is %d and width,height is (%d,%d).\n", BltInfo->SourceSurface->iBitmapFormat,
+         BltInfo->DestRect.right - BltInfo->DestRect.left, BltInfo->DestRect.bottom - BltInfo->DestRect.top);
+
+  DPRINT("BltInfo->SourcePoint.x is '%d' and BltInfo->SourcePoint.y is '%d'.\n",
+         BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
+
+  /* Do not deal with negative numbers for these values */
+  if ((BltInfo->DestRect.left < 0) || (BltInfo->DestRect.top < 0) || 
+      (BltInfo->DestRect.right < 0) || (BltInfo->DestRect.bottom < 0))
+    return FALSE;
+
+  /* Detect negative lDelta's meaning Bottom-Up bitmaps */
+  blDeltaSrcNeg = BltInfo->SourceSurface->lDelta < 0;
+  blDeltaDestNeg = BltInfo->DestSurface->lDelta < 0;
+
+  /* Get back left to right flip here */
+  bLeftToRight = BltInfo->DestRect.left > BltInfo->DestRect.right;
+
+  /* Check for top to bottom flip needed. */
+  bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
+
+  DPRINT("bTopToBottom is '%d' and DestSurface->lDelta < 0 is '%d' and SourceSurface->lDelta < 0 is '%d'.\n",
+           bTopToBottom, BltInfo->DestSurface->lDelta < 0 ? 1 : 0,  BltInfo->SourceSurface->lDelta < 0 ? 1 : 0);
+
+  /* Make WellOrdered with top < bottom and left < right */
+  RECTL_vMakeWellOrdered(&BltInfo->DestRect);
+
+  DestWidth = BltInfo->DestRect.right - BltInfo->DestRect.left;
+  DestHeight = BltInfo->DestRect.bottom - BltInfo->DestRect.top;
 
   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
     + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta)
     + 4 * BltInfo->DestRect.left;
 
+  DPRINT("iBitmapFormat is %d and width,height is (%d,%d).\n", BltInfo->SourceSurface->iBitmapFormat,
+         DestWidth, DestHeight);
+
   switch (BltInfo->SourceSurface->iBitmapFormat)
   {
   case BMF_1BPP:
+    DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
+           DestWidth);
+
+    if (bLeftToRight || bTopToBottom)
+    DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
 
     sx = BltInfo->SourcePoint.x;
+
+    /* This sets sy to the top line */
     sy = BltInfo->SourcePoint.y;
 
+    if (bTopToBottom)
+    {
+      /* This sets sy to the bottom line */
+      sy += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
+    }
+
     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
     {
       sx = BltInfo->SourcePoint.x;
-      for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
+
+      if (bLeftToRight)
+      {
+        /* This sets the sx to the rightmost pixel */
+        sx += (DestWidth - 1);
+      }
+
+      for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
       {
         if (DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
         {
           DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
-        } else {
+        }
+        else
+        {
           DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
         }
-        sx++;
+
+        DEC_OR_INC(sx, bLeftToRight, 1);
       }
-      sy++;
+      DEC_OR_INC(sy, bTopToBottom, 1);
     }
     break;
 
   case BMF_4BPP:
+    DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
+           DestWidth);
+
+    if (bLeftToRight || bTopToBottom)
+    DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
+
+    /* This sets SourceBits_4BPP to the top line */
     SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0
       + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
       + (BltInfo->SourcePoint.x >> 1);
 
+    if (bTopToBottom)
+    {
+      /* This sets SourceBits_4BPP to the bottom line */
+      SourceBits_4BPP += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
+    }
+
     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
     {
       SourceLine_4BPP = SourceBits_4BPP;
       sx = BltInfo->SourcePoint.x;
+
+      if (bLeftToRight)
+      {
+        /* This sets sx to the rightmost pixel */
+        sx += (DestWidth - 1);
+      }
+
       f1 = sx & 1;
 
       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
@@ -99,66 +194,120 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
         DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
         if (f1 == 1) {
-          SourceLine_4BPP++;
+          DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
           f1 = 0;
         } else {
           f1 = 1;
         }
-        sx++;
+        DEC_OR_INC(sx, bLeftToRight, 1);
       }
-
-      SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
+      DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
     }
     break;
 
   case BMF_8BPP:
-    SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
+    DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
+           DestWidth);
+
+    if (bLeftToRight || bTopToBottom)
+    DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
+
+    /* This sets SourceLine to the top line */
+    SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
+      + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+      + BltInfo->SourcePoint.x;
     DestLine = DestBits;
 
+    if (bTopToBottom)
+    {
+      /* This sets SourceLine to the bottom line */
+      SourceLine += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
+    }
+
     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
     {
       SourceBits = SourceLine;
       DestBits = DestLine;
 
+      if (bLeftToRight)
+      {
+        /* This sets the SourceBits to the rightmost pixel */
+        SourceBits += (DestWidth - 1);
+      }
+
       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
       {
         xColor = *SourceBits;
         *((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
-        SourceBits += 1;
+        DEC_OR_INC(SourceBits, bLeftToRight, 1);
         DestBits += 4;
       }
-
-      SourceLine += BltInfo->SourceSurface->lDelta;
+      DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
       DestLine += BltInfo->DestSurface->lDelta;
     }
     break;
 
   case BMF_16BPP:
-    SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
+    DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
+            DestWidth);
+
+    if (bLeftToRight || bTopToBottom)
+    DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
+
+    /* This sets SourceLine to the top line */
+    SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
+      + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+      + 2 * BltInfo->SourcePoint.x;
     DestLine = DestBits;
 
+    if (bTopToBottom)
+    {
+      /* This sets SourceLine to the bottom line */
+      SourceLine += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
+    }
+
     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
     {
       SourceBits = SourceLine;
       DestBits = DestLine;
 
+      if (bLeftToRight)
+      {
+        /* This sets the SourceBits to the rightmost pixel */
+        SourceBits += (DestWidth - 1) * 2;
+      }
+
       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
       {
         xColor = *((PWORD) SourceBits);
         *((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
-        SourceBits += 2;
+        DEC_OR_INC(SourceBits, bLeftToRight, 2);
         DestBits += 4;
       }
 
-      SourceLine += BltInfo->SourceSurface->lDelta;
+      DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
       DestLine += BltInfo->DestSurface->lDelta;
     }
     break;
 
   case BMF_24BPP:
+    DPRINT("24BPP Case Selected with DestRect Width of '%d'.\n",
+      DestWidth);
+
+    if (bLeftToRight || bTopToBottom)
+    DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
+
+    /* This sets SourceLine to the top line */
     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
       + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
       + 3 * BltInfo->SourcePoint.x;
+
+    if (bTopToBottom)
+    {
+      /* This sets SourceLine to the bottom line */
+      SourceLine += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
+    }
+
     DestLine = DestBits;
 
     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@@ -166,113 +315,382 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
       SourceBits = SourceLine;
       DestBits = DestLine;
 
+      if (bLeftToRight)
+      {
+        /* This sets the SourceBits to the rightmost pixel */
+        SourceBits += (DestWidth - 1) * 3;
+      }
+
       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
       {
         xColor = (*(SourceBits + 2) << 0x10) +
           (*(SourceBits + 1) << 0x08) +
           (*(SourceBits));
         *((PDWORD)DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
-        SourceBits += 3;
+        DEC_OR_INC(SourceBits, bLeftToRight, 3);
         DestBits += 4;
       }
 
-      SourceLine += BltInfo->SourceSurface->lDelta;
+      DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
       DestLine += BltInfo->DestSurface->lDelta;
     }
     break;
 
   case BMF_32BPP:
-    if (NULL == BltInfo->XlateSourceToDest ||
-      0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
+    DPRINT("32BPP Case Selected with SourcePoint (%d,%d) and DestRect Width/height of '%d/%d' DestRect: (%d,%d)-(%d,%d).\n",
+           BltInfo->SourcePoint.x, BltInfo->SourcePoint.y, DestWidth, DestHeight,
+           BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
+
+    if (bLeftToRight || bTopToBottom)
+    DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
+
+    /* This handles the negative lDelta's which represent Top-to-Bottom bitmaps */
+    if (((blDeltaSrcNeg || blDeltaDestNeg) && !(blDeltaSrcNeg && blDeltaDestNeg)) && bTopToBottom)
     {
+      DPRINT("Adjusting for lDelta's here.\n");
       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
       {
-        SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
+        /* SourceBits points to top-left pixel for lDelta < 0 and bottom-left for lDelta > 0 */
+        SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+          + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+          + 4 * BltInfo->SourcePoint.x;
         for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
         {
-          RtlMoveMemory(DestBits, SourceBits, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
+          RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
           SourceBits += BltInfo->SourceSurface->lDelta;
           DestBits += BltInfo->DestSurface->lDelta;
         }
       }
       else
       {
+        /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
           + ((BltInfo->SourcePoint.y
-          + BltInfo->DestRect.bottom
-          - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta)
+          + DestHeight - 1) * BltInfo->SourceSurface->lDelta)
           + 4 * BltInfo->SourcePoint.x;
-        DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
+        /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
+        DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+          + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
+          + 4 * BltInfo->DestRect.left;
         for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
         {
-          RtlMoveMemory(DestBits, SourceBits, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
+          RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
           SourceBits -= BltInfo->SourceSurface->lDelta;
           DestBits -= BltInfo->DestSurface->lDelta;
         }
       }
+      blDeltaAdjustDone = TRUE;
     }
-    else
+
+    /* This tests for whether we can use simplified/quicker code below.
+     * It works for increasing source and destination areas only and there is no overlap and no flip.
+     */
+    if ((BltInfo->XlateSourceToDest == NULL ||
+      (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
+      (!bTopToBottom && !bLeftToRight))
     {
+      DPRINT("XO_TRIVIAL is TRUE.\n");
+
       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
       {
-        SourceBits = ((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x);
+        /* SourceBits points to top-left pixel for lDelta < 0 and bottom-left for lDelta > 0 */
+        SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+          + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+          + 4 * BltInfo->SourcePoint.x;
         for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
         {
-          if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
+          RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
+          SourceBits += BltInfo->SourceSurface->lDelta;
+          DestBits += BltInfo->DestSurface->lDelta;
+        }
+      }
+      else
+      {
+        /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
+        SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+          + ((BltInfo->SourcePoint.y
+          + DestHeight - 1) * BltInfo->SourceSurface->lDelta)
+          + 4 * BltInfo->SourcePoint.x;
+        /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
+        DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+          + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
+          + 4 * BltInfo->DestRect.left;
+        for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
+        {
+          RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
+          SourceBits -= BltInfo->SourceSurface->lDelta;
+          DestBits -= BltInfo->DestSurface->lDelta;
+        }
+      }
+    }
+    else
+    {
+      DPRINT("XO_TRIVIAL is NOT TRUE.\n");
+
+      if (!bTopToBottom && !bLeftToRight)
+      {
+        if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
+        {
+          SourceBits = ((PBYTE)BltInfo->SourceSurface->pvScan0
+            + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+            + 4 * BltInfo->SourcePoint.x);
+          for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
           {
-            Dest32 = (DWORD *) DestBits;
-            Source32 = (DWORD *) SourceBits;
-            for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
+            if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
             {
-              *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
+              Dest32 = (DWORD *) DestBits;
+              Source32 = (DWORD *) SourceBits;
+              for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
+              {
+                *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
+              }
             }
+            else
+            {
+              Dest32 = (DWORD *) DestBits + (DestWidth - 1);
+              Source32 = (DWORD *) SourceBits + (DestWidth - 1);
+              for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
+              {
+                *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
+              }
+            }
+            SourceBits += BltInfo->SourceSurface->lDelta;
+            DestBits += BltInfo->DestSurface->lDelta;
           }
-          else
+        }
+        else
+        {
+          SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+            + ((BltInfo->SourcePoint.y
+            + DestHeight - 1) * BltInfo->SourceSurface->lDelta)
+            + 4 * BltInfo->SourcePoint.x;
+          DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+            + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
+            + 4 * BltInfo->DestRect.left;
+          for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
           {
-            Dest32 = (DWORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
-            Source32 = (DWORD *) SourceBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
-            for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
+            if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
             {
-              *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
+              Dest32 = (DWORD *) DestBits;
+              Source32 = (DWORD *) SourceBits;
+              for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
+              {
+                *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
+              }
             }
+            else
+            {
+              Dest32 = (DWORD *) DestBits + (DestWidth - 1);
+              Source32 = (DWORD *) SourceBits + (DestWidth - 1);
+              for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
+              {
+                *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
+              }
+            }
+            SourceBits -= BltInfo->SourceSurface->lDelta;
+            DestBits -= BltInfo->DestSurface->lDelta;
           }
-          SourceBits += BltInfo->SourceSurface->lDelta;
-          DestBits += BltInfo->DestSurface->lDelta;
         }
       }
       else
       {
-        SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
-        DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
-        for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
+        /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
+        BOOL TopToBottomDone = FALSE;
+
+        /* No need to flip a LeftToRight bitmap only one pixel wide */
+        if ((bLeftToRight) && (DestWidth > 1))
         {
-          if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
+          DPRINT("Flip is bLeftToRight.\n");
+
+          /* Allocate enough pixels for a row in DWORD's */
+          DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
+            (DestWidth + 1) * 4, TAG_DIB);
+          if (store == NULL)
           {
-            Dest32 = (DWORD *) DestBits;
-            Source32 = (DWORD *) SourceBits;
-            for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
-            {
-              *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
-            }
+            DPRINT1("Storage Allocation Failed.\n");
+            return FALSE;
+          }
+
+          /* This sets SourceBits to the bottom line */
+          SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+            + ((BltInfo->SourcePoint.y + DestHeight - 1)
+            * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
+
+          /* This sets DestBits to the bottom line */
+          DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+           + (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
+           + 4 * BltInfo->DestRect.left;
+
+          for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
+          {
+
+              /* Set Dest32 to right pixel */
+              Dest32 = (DWORD *) DestBits + (DestWidth - 1);
+              Source32 = (DWORD *) SourceBits;
+
+              Index = 0;
+
+              /* Store pixels from left to right */
+              for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
+              {
+                store[Index] = *Source32++;
+                Index++;
+              }
+
+              Index = 0;
+
+              /* Copy stored dat to pixels from right to left */
+              for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
+              {
+                *Dest32-- = store[Index];
+                Index++;
+              }
+            SourceBits -= BltInfo->SourceSurface->lDelta;
+            DestBits -= BltInfo->DestSurface->lDelta;
+          }
+          ExFreePoolWithTag(store, TAG_DIB);
+          TopToBottomDone = TRUE;
+        }
+
+        /* Top to Botoom Handling if bitmap more than one pixel high */
+        if ((bTopToBottom) && (DestHeight > 1))
+         {
+          /* Note: It is very important that this code remain optimized for time used.
+           *   Otherwise you will have random crashes in ReactOS that are undesirable.
+           *   For an example of this just try executing the code here two times.
+           */
+
+          DPRINT("Flip is bTopToBottom.\n");
+
+          /* Allocate enough pixels for a row in DWORD's */
+          DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
+            (DestWidth + 1) * 4, TAG_DIB);
+          if (store == NULL)
+          {
+            DPRINT1("Storage Allocation Failed.\n");
+            return FALSE;
+          }
+
+          /* This set DestBitsT to the top line */
+          DestBitsT = (PBYTE)BltInfo->DestSurface->pvScan0
+            + ((BltInfo->DestRect.top) * BltInfo->DestSurface->lDelta)
+            + 4 * BltInfo->DestRect.left;
+
+          /* This sets DestBitsB to the bottom line */
+          DestBitsB = (PBYTE)BltInfo->DestSurface->pvScan0
+           + (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
+           + 4 * BltInfo->DestRect.left;
+
+          /* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
+           * and have already completed the bLeftToRight. So we will lose our first flip output
+           * unless we work with its output which is at the destination site. So in this case
+           * our new Source becomes the previous outputs Destination.
+           * Also in we use the same logic when we have corrected for negative lDelta's above
+           * and already completed a flip from Source to Destination for the first step 
+           */
+
+          if (TopToBottomDone || blDeltaAdjustDone)
+          {
+            /* This sets SourceBitsB to the bottom line */
+            SourceBitsB = DestBitsB;
+
+            /* This sets SourceBitsT to the top line */
+            SourceBitsT = DestBitsT;
           }
           else
           {
-            Dest32 = (DWORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
-            Source32 = (DWORD *) SourceBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
-            for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
+            /* This sets SourceBitsB to the bottom line */
+            SourceBitsB = (PBYTE)BltInfo->SourceSurface->pvScan0
+              + ((BltInfo->SourcePoint.y + DestHeight - 1)
+              * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
+
+            /* This sets SourceBitsT to the top line */
+            SourceBitsT = (PBYTE)BltInfo->SourceSurface->pvScan0
+              + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
+          }
+
+          /* Overlaps and Vertical flips do not mix well. So we test for this and handle it
+           * by using two operations. First we just do a copy of the source to the destination.
+           * Then we do a flip in place at the destination location and we are done.
+           */
+          if ((BltInfo->SourcePoint.y != BltInfo->DestRect.top) &&                        // The values are not equal and
+             (abs(BltInfo->SourcePoint.y - BltInfo->DestRect.top) < (DestHeight + 2)) &&  // they are NOT seperated by > DestHeight 
+             (BltInfo->SourceSurface->pvScan0 == BltInfo->DestSurface->pvScan0))          // and same surface (probably screen)
+          {
+            DPRINT("Flips Need Adjustments, so do move here.\n");
+
+            if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
             {
-              *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
+              /* SourceBits points to top-left pixel for lDelta < 0 and bottom-left for lDelta > 0 */
+              SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+                + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+                + 4 * BltInfo->SourcePoint.x;
+              for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
+              {
+                RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
+                SourceBits += BltInfo->SourceSurface->lDelta;
+                DestBits += BltInfo->DestSurface->lDelta;
+              }
             }
+            else
+            {
+              /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
+              SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+                + ((BltInfo->SourcePoint.y
+                + DestHeight - 1) * BltInfo->SourceSurface->lDelta)
+                + 4 * BltInfo->SourcePoint.x;
+              /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
+              DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+                + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
+                + 4 * BltInfo->DestRect.left;
+              for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
+              {
+                RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
+                SourceBits -= BltInfo->SourceSurface->lDelta;
+                DestBits -= BltInfo->DestSurface->lDelta;
+              }
+            }
+
+            /* This sets SourceBitsB to the bottom line */
+            SourceBitsB = DestBitsB;
+
+            /* This sets SourceBitsT to the top line */
+            SourceBitsT = DestBitsT;
           }
-          SourceBits -= BltInfo->SourceSurface->lDelta;
-          DestBits -= BltInfo->DestSurface->lDelta;
+
+          /* Vertical Flip code starts here */
+          for (j = 0; j < DestHeight / 2 ; j++)
+          {
+            /* Store bottom row of Source pixels */
+            RtlMoveMemory(store, SourceBitsB, 4 * DestWidth);
+
+            /* Copy top Source row to bottom Destination row overwriting it */
+            RtlMoveMemory(DestBitsB, SourceBitsT, 4 * DestWidth);
+
+            /* Copy stored bottom row of Source pixels to Destination top row of pixels */
+            RtlMoveMemory(DestBitsT, store, 4 * DestWidth);
+
+            /* Index top rows down and bottom rows up */
+            SourceBitsT += BltInfo->SourceSurface->lDelta;
+            SourceBitsB -= BltInfo->SourceSurface->lDelta;
+
+            DestBitsT += BltInfo->DestSurface->lDelta;
+            DestBitsB -= BltInfo->DestSurface->lDelta;
+          }
+          if (DestHeight % 2)
+          {
+            /* If we had an odd number of lines we handle the center one here */
+            DPRINT("Handling Top To Bottom with Odd Number of lines.\n");
+            RtlMoveMemory(DestBitsB, SourceBitsT, 4 * DestWidth);
+          }
+          ExFreePoolWithTag(store, TAG_DIB);
         }
       }
     }
     break;
 
   default:
-    DPRINT1("DIB_32BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
+    DPRINT1("DIB_32BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
     return FALSE;
   }
 
@@ -352,7 +770,7 @@ DIB_32BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
   register NICEPIXEL32 DstPixel, SrcPixel;
   UCHAR Alpha, SrcBpp;
 
-  DPRINT("DIB_32BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
+  DPRINT("DIB_32BPP_AlphaBlend: SourceRect: (%d,%d)-(%d,%d), DestRect: (%d,%d)-(%d,%d)\n",
     SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
     DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
 
index fb1c0dc..af20395 100644 (file)
@@ -32,6 +32,9 @@ DIB_32BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
 {
   ULONG DestY;
 
+  /* Make WellOrdered by making top < bottom and left < right */
+  RECTL_vMakeWellOrdered(DestRect);
+
   for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
   {
     DIB_32BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);
index 56c03e5..69daf31 100644 (file)
@@ -4,14 +4,17 @@
  * FILE:            win32ss/gdi/dib/dib4bpp.c
  * PURPOSE:         Device Independant Bitmap functions, 4bpp
  * PROGRAMMERS:     Jason Filby
+ *                  Doug Lyons
  */
 
-
 #include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 
+#define DEC_OR_INC(var, decTrue, amount) \
+    ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
+
 VOID
 DIB_4BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
 {
@@ -63,6 +66,24 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
   PBYTE    SourceBits_24BPP, SourceLine_24BPP;
   PBYTE    DestBits, DestLine, SourceBits_8BPP, SourceLine_8BPP;
   PBYTE    SourceBits, SourceLine;
+  BOOLEAN  bTopToBottom, bLeftToRight;
+
+  DPRINT("DIB_4BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
+         BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
+         BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
+         BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
+
+  /* Get back left to right flip here */
+  bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
+
+  /* Check for top to bottom flip needed. */
+  bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
+
+  /* Make WellOrdered with top < bottom and left < right */
+  RECTL_vMakeWellOrdered(&BltInfo->DestRect);
+
+  DPRINT("BPP is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
+         BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
 
   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 +
              (BltInfo->DestRect.left >> 1) +
@@ -71,12 +92,30 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
   switch (BltInfo->SourceSurface->iBitmapFormat)
   {
     case BMF_1BPP:
+      DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
       sx = BltInfo->SourcePoint.x;
+
+      /* This sets sy to the top line */
       sy = BltInfo->SourcePoint.y;
 
+      if (bTopToBottom)
+      {
+        /* This sets sy to the bottom line */
+        sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
+      }
+
       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
       {
         sx = BltInfo->SourcePoint.x;
+
+        if (bLeftToRight)
+        {
+          /* This sets the sx to the rightmost pixel */
+          sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        }
+
         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
         {
           if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
@@ -87,64 +126,129 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           {
             DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
           }
-          sx++;
+          DEC_OR_INC(sx, bLeftToRight, 1);
         }
-        sy++;
+        DEC_OR_INC(sy, bTopToBottom, 1);
       }
       break;
 
     case BMF_4BPP:
+      DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      /* This sets sy to the top line */
       sy = BltInfo->SourcePoint.y;
 
+      if (bTopToBottom)
+      {
+        /* This sets sy to the bottom line */
+        sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
+              * BltInfo->SourceSurface->lDelta;
+      }
+
       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
       {
         sx = BltInfo->SourcePoint.x;
 
+        if (bLeftToRight)
+        {
+          /* This sets the sx to the rightmost pixel */
+          sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        }
+
         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
         {
           if (NULL != BltInfo->XlateSourceToDest)
           {
-            DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy)));
+            DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j,
+              XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
+              DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy)));
           }
           else
           {
-            DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
+            DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j,
+              DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
           }
-          sx++;
+          DEC_OR_INC(sx, bLeftToRight, 1);
         }
-        sy++;
+        DEC_OR_INC(sy, bTopToBottom, 1);
       }
       break;
 
     case BMF_8BPP:
-      SourceBits_8BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
+      DPRINT("8BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+              BltInfo->DestRect.left, BltInfo->DestRect.top,
+              BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+              BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      SourceBits_8BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + 
+        (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
+
+      if (bTopToBottom)
+      {
+        /* This sets SourceBits to the bottom line */
+        SourceBits_8BPP = (PBYTE)((LONG_PTR)SourceBits_8BPP +
+          ((BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) *
+          BltInfo->SourceSurface->lDelta));
+      }
 
       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
       {
         SourceLine_8BPP = SourceBits_8BPP;
         DestLine = DestBits;
+
+        if (bLeftToRight)
+        {
+          /* This sets SourceBits_8BPP to the rightmost pixel */
+          SourceBits_8BPP += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        }
+
         f2 = BltInfo->DestRect.left & 1;
 
         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
         {
           *DestLine = (*DestLine & notmask[f2]) |
             (BYTE)((XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceLine_8BPP)) << ((4 * (1 - f2))));
-          if(f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; }
-          SourceLine_8BPP++;
+          if (f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; }
+          DEC_OR_INC(SourceLine_8BPP, bLeftToRight, 1);
         }
-
-        SourceBits_8BPP += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceBits_8BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestBits += BltInfo->DestSurface->lDelta;
       }
       break;
 
     case BMF_16BPP:
-      SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
+      DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      DPRINT("BMF_16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+             BltInfo->DestRect.left, BltInfo->DestRect.top,
+             BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
+        (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
+        2 * BltInfo->SourcePoint.x;
+
+      if (bTopToBottom)
+      {
+        /* This sets SourceLine to the bottom line */
+        SourceLine += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) *
+          BltInfo->SourceSurface->lDelta;;
+      }
+
       DestLine = DestBits;
 
       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
       {
         SourceBits = SourceLine;
+
+        if (bLeftToRight)
+        {
+          /* This sets SourceBits to the rightmost pixel */
+          SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 2;
+        }
+
         DestBits = DestLine;
         f2 = BltInfo->DestRect.left & 1;
 
@@ -154,16 +258,32 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           *DestBits = (*DestBits & notmask[f2]) |
             (BYTE)((XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor)) << ((4 * (1 - f2))));
           if(f2 == 1) { DestBits++; f2 = 0; } else { f2 = 1; }
-          SourceBits += 2;
+
+          DEC_OR_INC(SourceBits, bLeftToRight, 2);
         }
 
-        SourceLine += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestLine += BltInfo->DestSurface->lDelta;
       }
       break;
 
     case BMF_24BPP:
-      SourceBits_24BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x * 3;
+
+      DPRINT("24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+             BltInfo->DestRect.left, BltInfo->DestRect.top,
+             BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      SourceBits_24BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
+        (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
+        BltInfo->SourcePoint.x * 3;
+
+      if (bTopToBottom)
+      {
+        /* This sets SourceLine to the bottom line */
+        SourceBits_24BPP += BltInfo->SourceSurface->lDelta *
+          (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+      }
 
       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
       {
@@ -171,6 +291,12 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
         DestLine = DestBits;
         f2 = BltInfo->DestRect.left & 1;
 
+        if (bLeftToRight)
+        {
+          /* This sets the SourceBits_24BPP to the rightmost pixel */
+          SourceLine_24BPP += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3;
+        }
+
         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
         {
           xColor = (*(SourceLine_24BPP + 2) << 0x10) +
@@ -179,22 +305,40 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           *DestLine = (*DestLine & notmask[f2]) |
             (BYTE)((XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor)) << ((4 * (1 - f2))));
           if(f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; }
-          SourceLine_24BPP+=3;
+          DEC_OR_INC(SourceLine_24BPP, bLeftToRight, 3);
         }
-
-        SourceBits_24BPP += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceBits_24BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestBits += BltInfo->DestSurface->lDelta;
       }
       break;
 
     case BMF_32BPP:
-      SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
+      DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
+        (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
+        4 * BltInfo->SourcePoint.x;
+
+      if (bTopToBottom)
+      {
+        /* This sets SourceLine to the bottom line */
+        SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
+      }
+
       DestLine = DestBits;
 
       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
       {
         SourceBits = SourceLine;
         DestBits = DestLine;
+
+        if (bLeftToRight)
+        {
+          /* This sets SourceBits to the rightmost pixel */
+          SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
+        }
+
         f2 = BltInfo->DestRect.left & 1;
 
         for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
@@ -203,16 +347,18 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           *DestBits = (*DestBits & notmask[f2]) |
             (BYTE)((XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor)) << ((4 * (1 - f2))));
           if(f2 == 1) { DestBits++; f2 = 0; } else { f2 = 1; }
-          SourceBits += 4;
+
+          DEC_OR_INC(SourceBits, bLeftToRight, 4);
         }
 
-        SourceLine += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestLine += BltInfo->DestSurface->lDelta;
       }
       break;
 
     default:
-      DbgPrint("DIB_4BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
+      DbgPrint("DIB_4BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n",
+        BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
       return FALSE;
   }
   return(TRUE);
@@ -290,7 +436,8 @@ DIB_4BPP_BitBlt(PBLTINFO BltInfo)
 
       if (BltInfo->PatternSurface)
       {
-        Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
+        Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface,
+         (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
       }
 
       DIB_4BPP_PutPixel(BltInfo->DestSurface, DestX, DestY, DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xF);
@@ -339,7 +486,8 @@ DIB_4BPP_BitBlt(PBLTINFO BltInfo)
       }
       if (BltInfo->PatternSurface)
       {
-        Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
+        Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface,
+          (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
       }
       DIB_4BPP_PutPixel(BltInfo->DestSurface, DestX, DestY, DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xF);
     }
@@ -361,6 +509,9 @@ DIB_4BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
 {
   LONG DestY;
 
+  /* Make WellOrdered by making top < bottom and left < right */
+  RECTL_vMakeWellOrdered(DestRect);
+
   for (DestY = DestRect->top; DestY < DestRect->bottom; DestY++)
   {
     DIB_4BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
index c30d738..520037b 100644 (file)
@@ -6,6 +6,7 @@
  * PROGRAMMERS:     Jason Filby
  *                  Thomas Bluemel
  *                  Gregor Anich
+ *                  Doug Lyons
  */
 
 #include <win32k.h>
@@ -13,6 +14,9 @@
 #define NDEBUG
 #include <debug.h>
 
+#define DEC_OR_INC(var, decTrue, amount) \
+    ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
+
 VOID
 DIB_8BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
 {
@@ -57,18 +61,56 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
   LONG     i, j, sx, sy, xColor, f1;
   PBYTE    SourceBits, DestBits, SourceLine, DestLine;
   PBYTE    SourceBits_4BPP, SourceLine_4BPP;
+  BOOLEAN  bTopToBottom, bLeftToRight;
+
+  DPRINT("DIB_8BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
+         BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
+         BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
+         BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
+
+  /* Get back left to right flip here */
+  bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
+
+  /* Check for top to bottom flip needed. */
+  bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
+
+  DPRINT("bTopToBottom is '%d' and bLeftToRight is '%d'.\n", bTopToBottom, bLeftToRight);
+
+  /* Make WellOrdered by making top < bottom and left < right */
+  RECTL_vMakeWellOrdered(&BltInfo->DestRect);
+
+  DPRINT("BPP is '%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
+         BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
 
   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
 
   switch(BltInfo->SourceSurface->iBitmapFormat)
   {
     case BMF_1BPP:
+      DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
       sx = BltInfo->SourcePoint.x;
+
+      /* This sets sy to the top line */
       sy = BltInfo->SourcePoint.y;
 
+      if (bTopToBottom)
+      {
+        /* This sets sy to the bottom line */
+        sy += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
+      }
+
       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
       {
         sx = BltInfo->SourcePoint.x;
+
+        if (bLeftToRight)
+        {
+          /* This sets the sx to the rightmost pixel */
+          sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        }
+
         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
         {
           if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
@@ -79,19 +121,36 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           {
             DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
           }
-          sx++;
+          DEC_OR_INC(sx, bLeftToRight, 1);
         }
-        sy++;
+        DEC_OR_INC(sy, bTopToBottom, 1);
       }
       break;
 
     case BMF_4BPP:
+      DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      /* This sets SourceBits_4BPP to the top line */
       SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
 
+      if (bTopToBottom)
+      {
+        /* This sets SourceBits_4BPP to the bottom line */
+        SourceBits_4BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
+      }
+
       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
       {
         SourceLine_4BPP = SourceBits_4BPP;
         sx = BltInfo->SourcePoint.x;
+
+        if (bLeftToRight)
+        {
+          /* This sets sx to the rightmost pixel */
+          sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+        }
+
         f1 = sx & 1;
 
         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
@@ -99,19 +158,35 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
               (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
           DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
-          if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
-          sx++;
-        }
+          if(f1 == 1)
+          {
+            DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
+            f1 = 0;
+          }
+          else
+          {
+            f1 = 1;
+          }
 
-        SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
+          DEC_OR_INC(sx, bLeftToRight, 1);
+        }
+        DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
       }
       break;
 
     case BMF_8BPP:
-      if (NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
+      DPRINT("8BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+              BltInfo->DestRect.left, BltInfo->DestRect.top,
+              BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+              BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      if ((BltInfo->XlateSourceToDest == NULL ||
+        (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
+        (!bTopToBottom && !bLeftToRight))
       {
         if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
         {
+          DPRINT("BltInfo->DestRect.top < BltInfo->SourcePoint.y.\n");
           SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
           for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
           {
@@ -122,6 +197,7 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
         }
         else
         {
+          DPRINT("BltInfo->DestRect.top >= BltInfo->SourcePoint.y.\n");
           SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
           DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
           for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
@@ -134,8 +210,14 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
       }
       else
       {
+        DPRINT("XO_TRIVIAL is NOT TRUE or we have flips.\n");
+
+        if (!bTopToBottom && !bLeftToRight)
+      /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
+        {
         if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
         {
+          DPRINT("Dest.top < SourcePoint.y.\n");
           SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
           DestLine = DestBits;
           for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@@ -152,6 +234,7 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
         }
         else
         {
+          DPRINT("Dest.top >= SourcePoint.y.\n");
           SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
           DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
           for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
@@ -167,56 +250,244 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
           }
         }
       }
+      else
+      {
+          /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
+          BOOL OneDone = FALSE;
+
+          if (bLeftToRight)
+          {
+            DPRINT("Flip is bLeftToRight.\n");
+
+            /* Allocate enough pixels for a row in BYTE's */
+            BYTE *store = ExAllocatePoolWithTag(NonPagedPool,
+              BltInfo->DestRect.right - BltInfo->DestRect.left + 1, TAG_DIB);
+            if (store == NULL)
+            {
+              DPRINT1("Storage Allocation Failed.\n");
+              return FALSE;
+            }
+            WORD  Index;
+
+            /* This sets SourceLine to the top line */
+            SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
+              (BltInfo->SourcePoint.y *
+              BltInfo->SourceSurface->lDelta) +
+              BltInfo->SourcePoint.x;
+
+            /* This set the DestLine to the top line */
+            DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
+              (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) +
+              BltInfo->DestRect.left;
+
+            for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
+            {
+              SourceBits = SourceLine;
+              DestBits = DestLine;
+
+              /* This sets SourceBits to the rightmost pixel */
+              SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
+
+              Index = 0;
+
+              for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
+              {
+                store[Index] = (BYTE)XLATEOBJ_iXlate(
+                  BltInfo->XlateSourceToDest,
+                  *SourceBits);
+                SourceBits--;
+                Index++;
+              }
+
+              Index = 0;
+
+              for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
+              {
+                *DestBits = store[Index];
+                DestBits++;
+                Index++;
+              }
+
+              SourceLine += BltInfo->SourceSurface->lDelta;
+              DestLine += BltInfo->DestSurface->lDelta;
+            }
+            ExFreePoolWithTag(store, TAG_DIB);
+            OneDone = TRUE;
+          }
+
+          if (bTopToBottom)
+          {
+            DPRINT("Flip is bTopToBottom.\n");
+    
+            DWORD  Index;
+
+            /* Allocate enough pixels for a column in BYTE's */
+            BYTE *store = ExAllocatePoolWithTag(NonPagedPool,
+              BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1, TAG_DIB);
+            if (store == NULL)
+            {
+              DPRINT1("Storage Allocation Failed.\n");
+              return FALSE;
+            }
+
+            /* The OneDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
+             * and have already completed the bLeftToRight. So we will lose our first flip output
+             * unless we work with its output which is at the destination site. So in this case
+             * our new Source becomes the previous outputs Destination. */
+
+            if (OneDone)
+            {
+              /* This sets SourceLine to the bottom line of our previous destination */
+              SourceLine = (PBYTE)BltInfo->DestSurface->pvScan0 + 
+                (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left  +
+                (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->DestSurface->lDelta;
+            }
+            else
+            {
+              /* This sets SourceLine to the bottom line */
+              SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
+                ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
+                * BltInfo->SourceSurface->lDelta) +
+                BltInfo->SourcePoint.x;
+            }
+
+            /* This set the DestLine to the top line */
+            DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
+              (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) +
+              BltInfo->DestRect.left;
+
+            /* Read columns */
+            for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
+            {
+
+              DestBits = DestLine;
+              SourceBits = SourceLine;
+
+              Index = 0;
+
+              /* Read up the column and store the pixels */
+              for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
+              {
+                store[Index] = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
+                /* Go up a line */
+                SourceBits -= BltInfo->SourceSurface->lDelta;
+                Index++;
+              }
+              Index = 0;
+
+              /* Get the stored pixel and copy then down the column */
+              for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
+              {
+                *DestBits = store[Index];
+                /* Go down a line */
+                DestBits += BltInfo->SourceSurface->lDelta;
+                Index++;
+              }
+              /* Index to next column */
+              SourceLine += 1;
+              DestLine += 1;
+            }
+            ExFreePoolWithTag(store, TAG_DIB);
+          }
+
+        }
+      }
       break;
 
     case BMF_16BPP:
+      DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
+      DPRINT("BMF_16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+             BltInfo->DestRect.left, BltInfo->DestRect.top,
+             BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
       SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
+
+      if (bTopToBottom)
+      {
+        /* This sets SourceLine to the bottom line */
+        SourceLine += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;;
+      }
       DestLine = DestBits;
 
       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
       {
         SourceBits = SourceLine;
+
+        if (bLeftToRight)
+        {
+          /* This sets SourceBits to the rightmost pixel */
+          SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 2;
+        }
         DestBits = DestLine;
 
         for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
         {
           xColor = *((PWORD) SourceBits);
           *DestBits = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
-          SourceBits += 2;
+
+          DEC_OR_INC(SourceBits, bLeftToRight, 2);
           DestBits += 1;
         }
-
-        SourceLine += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestLine += BltInfo->DestSurface->lDelta;
       }
       break;
 
     case BMF_24BPP:
+      DPRINT("24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 
+             BltInfo->DestRect.left, BltInfo->DestRect.top,
+             BltInfo->DestRect.right, BltInfo->DestRect.bottom,
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
       SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
       DestLine = DestBits;
 
+      if (bTopToBottom)
+      {
+        /* This sets SourceLine to the bottom line */
+        SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
+      }
+
       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
       {
         SourceBits = SourceLine;
         DestBits = DestLine;
 
+        if (bLeftToRight)
+        {
+          /* This sets the SourceBits to the rightmost pixel */
+          SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3;
+        }
+
         for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
         {
           xColor = (*(SourceBits + 2) << 0x10) +
              (*(SourceBits + 1) << 0x08) +
              (*(SourceBits));
           *DestBits = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
-          SourceBits += 3;
+          DEC_OR_INC(SourceBits, bLeftToRight, 3);
           DestBits += 1;
         }
-
-        SourceLine += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestLine += BltInfo->DestSurface->lDelta;
       }
       break;
 
     case BMF_32BPP:
+      DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
+             BltInfo->DestRect.right - BltInfo->DestRect.left);
+
       SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
+
+      if (bTopToBottom)
+      {
+        /* This sets SourceLine to the bottom line */
+        SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
+      }
       DestLine = DestBits;
 
       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@@ -224,15 +495,21 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
         SourceBits = SourceLine;
         DestBits = DestLine;
 
+        if (bLeftToRight)
+        {
+          /* This sets SourceBits to the rightmost pixel */
+          SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
+        }
+
         for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
         {
           xColor = *((PDWORD) SourceBits);
           *DestBits = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
-          SourceBits += 4;
+
+          DEC_OR_INC(SourceBits, bLeftToRight, 4);
           DestBits += 1;
         }
-
-        SourceLine += BltInfo->SourceSurface->lDelta;
+        DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
         DestLine += BltInfo->DestSurface->lDelta;
       }
       break;
@@ -250,6 +527,10 @@ BOOLEAN
 DIB_8BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
 {
   LONG DestY;
+
+  /* Make WellOrdered by making top < bottom and left < right */
+  RECTL_vMakeWellOrdered(DestRect);
+
   for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
   {
     DIB_8BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
index c768cf8..718d818 100644 (file)
@@ -6,6 +6,7 @@
  * PROGRAMMERS:     Magnus Olsen
  *                  Evgeniy Boltik
  *                  Gregor Schneider
+ *                  Doug Lyons
  */
 
 #include <win32k.h>
@@ -47,25 +48,46 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
 
   BOOL UsesSource = ROP4_USES_SOURCE(ROP);
   BOOL UsesPattern = ROP4_USES_PATTERN(ROP);
+  BOOLEAN bTopToBottom, bLeftToRight;
 
   ASSERT(IS_VALID_ROP4(ROP));
 
   fnDest_GetPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_GetPixel;
   fnDest_PutPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_PutPixel;
 
-  DPRINT("Dest BPP: %u, dstRect: (%d,%d)-(%d,%d)\n",
+  DPRINT("Dest BPP: %u, DestRect: (%d,%d)-(%d,%d)\n",
     BitsPerFormat(DestSurf->iBitmapFormat), DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
 
+  DstHeight = DestRect->bottom - DestRect->top;
+  DstWidth = DestRect->right - DestRect->left;
+  SrcHeight = SourceRect->bottom - SourceRect->top;
+  SrcWidth = SourceRect->right - SourceRect->left;
+
+  /* Here we do the tests and set our conditions */
+  if (((SrcWidth < 0) && (DstWidth < 0)) || ((SrcWidth >= 0) && (DstWidth >= 0)))
+    bLeftToRight = FALSE;
+  else
+    bLeftToRight = TRUE;
+
+  if (((SrcHeight < 0) && (DstHeight < 0)) || ((SrcHeight >= 0) && (DstHeight >= 0)))
+    bTopToBottom = FALSE;
+  else
+    bTopToBottom = TRUE;
+
+  /* Make Well Ordered to start */
+  RECTL_vMakeWellOrdered(DestRect);
+
   if (UsesSource)
   {
     SourceCy = SourceSurf->sizlBitmap.cy;
     fnSource_GetPixel = DibFunctionsForBitmapFormat[SourceSurf->iBitmapFormat].DIB_GetPixel;
-    DPRINT("Source BPP: %u, srcRect: (%d,%d)-(%d,%d)\n",
+    DPRINT("Source BPP: %u, SourceRect: (%d,%d)-(%d,%d)\n",
       BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom);
   }
 
   if (MaskSurf)
   {
+    DPRINT("MaskSurf is not NULL.\n");
     fnMask_GetPixel = DibFunctionsForBitmapFormat[MaskSurf->iBitmapFormat].DIB_GetPixel;
     MaskCy = MaskSurf->sizlBitmap.cy;
   }
@@ -87,9 +109,11 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
   default:
     xxBPPMask = 0xFFFFFFFF;
   }
+  DPRINT("xxBPPMask is 0x%x.\n", xxBPPMask);
 
   if (UsesPattern)
   {
+    DPRINT("UsesPattern is not NULL.\n");
     if (PatternSurface)
     {
       PatternY = (DestRect->top - BrushOrigin->y) % PatternSurface->sizlBitmap.cy;
@@ -106,6 +130,12 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
     }
   }
 
+  if (PatternSurface)
+  {
+    DPRINT("PatternSurface is not NULL.\n");
+  }
+
+  DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
 
   for (DesY = DestRect->top; DesY < DestRect->bottom; DesY++)
   {
@@ -118,7 +148,16 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
       }
     }
     if (UsesSource)
-      sy = SourceRect->top+(DesY - DestRect->top) * SrcHeight / DstHeight;
+    {
+      if (bTopToBottom)
+      {
+        sy = SourceRect->bottom-(DesY - DestRect->top) * SrcHeight / DstHeight;  // flips about the x-axis
+      }
+      else
+      {
+        sy = SourceRect->top+(DesY - DestRect->top) * SrcHeight / DstHeight;
+      }
+    }
 
     for (DesX = DestRect->left; DesX < DestRect->right; DesX++)
     {
@@ -126,7 +165,14 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
 
       if (fnMask_GetPixel)
       {
-        sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
+        if (bLeftToRight)
+        {
+          sx = SourceRect->right - (DesX - DestRect->left) * SrcWidth / DstWidth;  // flips about the y-axis
+        }
+        else
+        {
+          sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
+        }
         if (sx < 0 || sy < 0 ||
           MaskSurf->sizlBitmap.cx < sx || MaskCy < sy ||
           fnMask_GetPixel(MaskSurf, sx, sy) != 0)
@@ -137,7 +183,14 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
 
       if (UsesSource && CanDraw)
       {
-        sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
+        if (bLeftToRight)
+        {
+          sx = SourceRect->right-(DesX - DestRect->left) * SrcWidth / DstWidth;  // flips about the y-axis
+        }
+        else
+        {
+          sx = SourceRect->left + (DesX - DestRect->left) * SrcWidth / DstWidth;
+        }
         if (sx >= 0 && sy >= 0 &&
           SourceSurf->sizlBitmap.cx > sx && SourceCy > sy)
         {
index 8eea775..59641cd 100644 (file)
@@ -3,8 +3,13 @@
  * PROJECT:          ReactOS Win32k subsystem
  * PURPOSE:          GDI BitBlt Functions
  * FILE:             win32ss/gdi/eng/bitblt.c
- * PROGRAMER       Jason Filby
+ * PROGRAMERS:       Jason Filby
  *                   Timo Kreuzer
+ *                   Doug Lyons
+ *
+ * WARNING: Modify this file with extreme caution. It is very sensitive to timing changes.
+ *   Adding code can cause the system to show a Fatal Exception Error and fail to boot!.
+ *   This is especially true in CallDibBitBlt, IntEngBitBlt and EngBitBlt (even DPRINT's).
  */
 
 #include <win32k.h>
@@ -255,6 +260,12 @@ CallDibBitBlt(SURFOBJ* OutputObj,
         psoPattern = NULL;
     }
 
+    /* Make WellOrdered with top < bottom and left < right */
+    RECTL_vMakeWellOrdered(&BltInfo.DestRect);
+
+    DPRINT("CallDibBitBlt: BltInfo.DestRect: (%d,%d)-(%d,%d)\n",
+           BltInfo.DestRect.left, BltInfo.DestRect.top, BltInfo.DestRect.right, BltInfo.DestRect.bottom);
+
     Result = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBlt(&BltInfo);
 
     return Result;
@@ -344,10 +355,30 @@ EngBitBlt(
     ULONG              Direction;
     BOOL               UsesSource, UsesMask;
     POINTL             AdjustedBrushOrigin;
+    LONG               lTmp;
+    BOOLEAN            bTopToBottom, bLeftToRight;
 
     UsesSource = ROP4_USES_SOURCE(rop4);
     UsesMask = ROP4_USES_MASK(rop4);
 
+    if (prclTrg->left > prclTrg->right)
+    {
+      bLeftToRight = TRUE;
+    }
+    else
+    {
+      bLeftToRight = FALSE;
+    }
+
+    if (prclTrg->top > prclTrg->bottom)
+    {
+      bTopToBottom = TRUE;
+    }
+    else
+    {
+      bTopToBottom = FALSE;
+    }
+
     if (rop4 == ROP4_NOOP)
     {
         /* Copy destination onto itself: nop */
@@ -359,6 +390,12 @@ EngBitBlt(
     OutputRect = *prclTrg;
     RECTL_vMakeWellOrdered(&OutputRect);
 
+    DPRINT("EngBitBlt: prclTrg: (%d,%d)-(%d,%d)\n",
+           prclTrg->left, prclTrg->top, prclTrg->right, prclTrg->bottom);
+
+    DPRINT("EngBitBlt: OutputRect: (%d,%d)-(%d,%d)\n",
+           OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
+
     if (UsesSource)
     {
         if (!psoSrc || !pptlSrc)
@@ -498,6 +535,21 @@ EngBitBlt(
     switch (clippingType)
     {
         case DC_TRIVIAL:
+            /* Fix up OutputRect here */
+            if (bLeftToRight)
+            {
+                lTmp = OutputRect.left;
+                OutputRect.left = OutputRect.right;
+                OutputRect.right = lTmp;
+            }
+
+            if (bTopToBottom)
+            {
+                lTmp = OutputRect.top;
+                OutputRect.top = OutputRect.bottom;
+                OutputRect.bottom = lTmp;
+            }
+
             Ret = (*BltRectFunc)(OutputObj,
                                  InputObj,
                                  psoMask,
@@ -622,6 +674,8 @@ IntEngBitBlt(
     RECTL rclSrcClipped;
     POINTL ptlBrush;
     PFN_DrvBitBlt pfnBitBlt;
+    LONG lTmp;
+    BOOLEAN bTopToBottom, bLeftToRight;
 
     /* Sanity checks */
     ASSERT(IS_VALID_ROP4(Rop4));
@@ -629,6 +683,9 @@ IntEngBitBlt(
 
     psurfTrg = CONTAINING_RECORD(psoTrg, SURFACE, SurfObj);
 
+    bLeftToRight = prclTrg->left > prclTrg->right;
+    bTopToBottom = prclTrg->top > prclTrg->bottom;
+
     /* Get the target rect and make it well ordered */
     rclClipped = *prclTrg;
     RECTL_vMakeWellOrdered(&rclClipped);
@@ -721,6 +778,24 @@ IntEngBitBlt(
         pfnBitBlt = EngBitBlt;
     }
 
+    /* rclClipped needs to be modified in accordance with flips here */
+    if (bLeftToRight)
+    {
+        lTmp = rclClipped.left;
+        rclClipped.left = rclClipped.right;
+        rclClipped.right = lTmp;
+    }
+
+    if (bTopToBottom)
+    {
+        lTmp = rclClipped.top;
+        rclClipped.top = rclClipped.bottom;
+        rclClipped.bottom = lTmp;
+    }
+
+    DPRINT("About to call EngBitBlt: rclClipped: (%d,%d)-(%d,%d)\n",
+           rclClipped.left, rclClipped.top, rclClipped.right, rclClipped.bottom);
+
     bResult = pfnBitBlt(psoTrg,
                         psoSrc,
                         psoMask,
index 0b88243..92539da 100644 (file)
@@ -3,7 +3,8 @@
  * PROJECT:          ReactOS kernel
  * PURPOSE:          GDI EngCopyBits Function
  * FILE:             win32ss/gdi/eng/copybits.c
- * PROGRAMER:        Jason Filby
+ * PROGRAMERS:       Jason Filby
+ *                   Doug Lyons
  */
 
 #include <win32k.h>
@@ -32,6 +33,30 @@ EngCopyBits(
     SURFACE *psurfSource;
     RECTL rclDest = *DestRect;
     POINTL ptlSrc = *SourcePoint;
+    LONG      lTmp;
+    BOOL      bTopToBottom;
+
+    DPRINT("Entering EngCopyBits with SourcePoint (%d,%d) and DestRect (%d,%d)-(%d,%d).\n",
+           SourcePoint->x, SourcePoint->y, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
+
+    DPRINT("psoSource cx/cy is %d/%d and psoDest cx/cy is %d/%d.\n",
+           psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy, psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy);
+
+    /* Retrieve Top Down/flip here and then make Well-Ordered again */
+    if (DestRect->top > DestRect->bottom)
+    {
+        bTopToBottom = TRUE;
+        lTmp = DestRect->top;
+        DestRect->top = DestRect->bottom;
+        DestRect->bottom = lTmp;
+        rclDest = *DestRect;
+    }
+    else
+    {
+        bTopToBottom = FALSE;
+    }
+
+    DPRINT("bTopToBottom is '%d'.\n", bTopToBottom);
 
     ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL);
 
@@ -113,24 +138,42 @@ EngCopyBits(
     switch (clippingType)
     {
         case DC_TRIVIAL:
+            DPRINT("DC_TRIVIAL.\n");
             BltInfo.DestRect = *DestRect;
             BltInfo.SourcePoint = *SourcePoint;
 
+            /* Now we set the Dest Rect top and bottom based on Top Down/flip */
+            if (bTopToBottom)
+            {
+                lTmp = BltInfo.DestRect.top;
+                BltInfo.DestRect.top = BltInfo.DestRect.bottom;
+                BltInfo.DestRect.bottom = lTmp;
+            }
+
             ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
             break;
 
         case DC_RECT:
+            DPRINT("DC_RECT.\n");
             // Clip the blt to the clip rectangle
             RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds);
 
             BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
             BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top  - DestRect->top;
 
+            /* Now we set the Dest Rect top and bottom based on Top Down/flip */
+            if (bTopToBottom)
+            {
+                lTmp = BltInfo.DestRect.top;
+                BltInfo.DestRect.top = BltInfo.DestRect.bottom;
+                BltInfo.DestRect.bottom = lTmp;
+            }
+
             ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
             break;
 
         case DC_COMPLEX:
-
+            DPRINT("DC_COMPLEX.\n");
             CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, 0);
 
             do
@@ -149,6 +192,14 @@ EngCopyBits(
                         BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
                         BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;
 
+                        /* Now we set the Dest Rect top and bottom based on Top Down/flip */
+                        if (bTopToBottom)
+                        {
+                            lTmp = BltInfo.DestRect.top;
+                            BltInfo.DestRect.top = BltInfo.DestRect.bottom;
+                            BltInfo.DestRect.bottom = lTmp;
+                        }
+
                         if (!DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo))
                         {
                             ret = FALSE;
index 2fb1a9a..3b290e2 100644 (file)
@@ -3,7 +3,8 @@
  * PROJECT:          ReactOS Win32k subsystem
  * PURPOSE:          GDI stretch blt functions
  * FILE:             win32ss/gdi/eng/stretchblt.c
- * PROGRAMER:        Jason Filby
+ * PROGRAMERS:       Jason Filby
+ *                   Doug Lyons
  */
 
 #include <win32k.h>
 #define NDEBUG
 #include <debug.h>
 
+/***************************************************************************************************************************
+  We want to receive and send the flip state along to existing functions without changing their parameter lists.
+  So a way that we can do this is to use the DestRect to carry this information along with it.
+  Since there are four values, we can use their relative positions (coordinates) to indicate the four flip conditions.
+  if delta-x == 0 then there can be no Left-to-Right flip. If delta-y == 0 there can be no Top-to-Bottom flip.
+  So we can set the four flip conditions based on BOOLEAN flags as follows:
+
+  We will use internal bits bTopToBottom and bLeftToRight as follows:
+
+  !bTopToBottom && !bLeftToRight means no flips      therefore left < right and top < bottom (normal well-formed rectangle)
+  bTopToBottom means there is a Top-To-Bottom flip   therefore left < right and top > bottom
+  bLeftToRight means there is a Left-To-Right flip   therefore left > right and top < bottom
+  bLeftToRight && bTopToBottom means both flips      therefore left > right and top > bottom
+****************************************************************************************************************************/
+
 typedef BOOLEAN (APIENTRY *PSTRETCHRECTFUNC)(SURFOBJ* OutputObj,
                                             SURFOBJ* InputObj,
                                             SURFOBJ* Mask,
@@ -38,6 +54,11 @@ CallDibStretchBlt(SURFOBJ* psoDest,
     SURFOBJ* psoPattern;
     BOOL bResult;
 
+    DPRINT("Entering CallDibStretchBlt: psoSource cx/cy (%d/%d), psoDest cx/cy (%d/%d) OutputRect: (%d,%d)-(%d,%d)\n",
+           psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy,
+           psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy,
+           OutputRect->left, OutputRect->top, OutputRect->right, OutputRect->bottom);
+
     if (BrushOrigin == NULL)
     {
         RealBrushOrigin.x = RealBrushOrigin.y = 0;
@@ -115,6 +136,35 @@ EngStretchBltROP(
     LONG SrcHeight;
     LONG SrcWidth;
 
+    LONG cxSrc, cySrc, cxDest, cyDest;
+    BOOLEAN bLeftToRight, bTopToBottom;
+    LONG lTmp;
+
+    DPRINT("Entering EngStretchBltROP: prclSrc: (%d/%d)-(%d/%d) prclDest: (%d,%d)-(%d,%d)\n",
+           prclSrc->left, prclSrc->top, prclSrc->right, prclSrc->bottom,
+           prclDest->left, prclDest->top, prclDest->right, prclDest->bottom);
+
+    cxSrc = prclSrc->right - prclSrc->left;
+    cySrc = prclSrc->bottom - prclSrc->top;
+    cxDest = prclDest->right - prclDest->left;
+    cyDest = prclDest->bottom - prclDest->top;
+
+    /* Here we do the tests and set our conditions */
+    if (((cxSrc < 0) && (cxDest < 0)) || ((cxSrc >= 0) && (cxDest >= 0)))
+        bLeftToRight = FALSE;
+    else
+        bLeftToRight = TRUE;
+
+    if (((cySrc < 0) && (cyDest < 0)) || ((cySrc >= 0) && (cyDest >= 0)))
+        bTopToBottom = FALSE;
+    else
+        bTopToBottom = TRUE;
+
+    /* Make Well Ordered to start */
+    OutputRect = *prclDest;
+    RECTL_vMakeWellOrdered(&OutputRect);
+    *prclDest = OutputRect;
+
     if (Rop4 == ROP4_NOOP)
     {
         /* Copy destination onto itself: nop */
@@ -237,9 +287,29 @@ EngStretchBltROP(
     DstWidth = OutputRect.right - OutputRect.left;
     SrcHeight = InputRect.bottom - InputRect.top;
     SrcWidth = InputRect.right - InputRect.left;
+
+    DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
+
     switch (clippingType)
     {
         case DC_TRIVIAL:
+            if (bLeftToRight)
+            {
+               lTmp = OutputRect.left;
+                OutputRect.left = OutputRect.right;
+                OutputRect.right = lTmp;
+            }
+
+            if (bTopToBottom)
+            {
+                lTmp = OutputRect.top;
+                OutputRect.top = OutputRect.bottom;
+                OutputRect.bottom = lTmp;
+            }
+
+            DPRINT("About to call CallDibStretchBlt: OutputRect: (%d,%d)-(%d,%d)\n",
+                   OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
+
             Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
                          ColorTranslation, &OutputRect, &InputRect, MaskOrigin,
                          pbo, &AdjustedBrushOrigin, Rop4);
@@ -256,6 +326,24 @@ EngStretchBltROP(
                 InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
                 InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
                 InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
+
+                if (bLeftToRight)
+                {
+                   lTmp = CombinedRect.left;
+                    CombinedRect.left = CombinedRect.right;
+                    CombinedRect.right = lTmp;
+                }
+
+                if (bTopToBottom)
+                {
+                    lTmp = CombinedRect.top;
+                    CombinedRect.top = CombinedRect.bottom;
+                    CombinedRect.bottom = lTmp;
+                }
+
+                DPRINT("About to call CallDibStretchBlt: CombinedRect: (%d,%d)-(%d,%d)\n",
+                       CombinedRect.left, CombinedRect.top, CombinedRect.right, CombinedRect.bottom);
+
                 Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
                            ColorTranslation,
                            &CombinedRect,
@@ -301,6 +389,24 @@ EngStretchBltROP(
                         InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
                         InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
                         InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
+
+                        if (bLeftToRight)
+                        {
+                            lTmp = CombinedRect.left;
+                            CombinedRect.left = CombinedRect.right;
+                            CombinedRect.right = lTmp;
+                        }
+
+                        if (bTopToBottom)
+                        {
+                            lTmp = CombinedRect.top;
+                            CombinedRect.top = CombinedRect.bottom;
+                            CombinedRect.bottom = lTmp;
+                        }
+
+                        DPRINT("About to call CallDibStretchBlt: CombinedRect: (%d,%d)-(%d,%d)\n",
+                               CombinedRect.left, CombinedRect.top, CombinedRect.right, CombinedRect.bottom);
+
                         Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
                            ColorTranslation,
                            &CombinedRect,
@@ -382,6 +488,18 @@ IntEngStretchBlt(SURFOBJ *psoDest,
     RECTL OutputRect;
     BOOL UsesSource = ROP4_USES_SOURCE(Rop4);
     LONG InputClWidth, InputClHeight, InputWidth, InputHeight;
+    LONG lTmp, cxSrc, cySrc, cxDest, cyDest;
+    BOOLEAN bTopToBottom, bLeftToRight;
+    INT Case0000, Case0001, Case0010, Case0011;
+    INT Case0100, Case0101, Case0110, Case0111;
+    INT Case1000, Case1001, Case1010, Case1011;
+    INT Case1100, Case1101, Case1110;
+
+    DPRINT("Source cx/cy (%d/%d) and Destination cx/cy (%d/%d).\n",
+            psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy, psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy);
+
+    DPRINT("Source lDelta is '%d' and Destination lDelta is '%d'.\n",
+            psoSource->lDelta, psoDest->lDelta);
 
     ASSERT(psoDest);
     //ASSERT(psoSource); // FIXME!
@@ -390,17 +508,113 @@ IntEngStretchBlt(SURFOBJ *psoDest,
     //ASSERT(!RECTL_bIsEmptyRect(SourceRect)); // FIXME!
 
     /* If no clip object is given, use trivial one */
-    if (!ClipRegion) ClipRegion = (CLIPOBJ *)&gxcoTrivial;
+    if (!ClipRegion)
+    {
+        DPRINT("Using trivial clip region.\n");
+        ClipRegion = (CLIPOBJ *)&gxcoTrivial;
+    }
+    else
+    {
+        DPRINT("ClipRegion->rclBounds is (%d,%d)-(%d,%d).\n",
+           ClipRegion->rclBounds.left, ClipRegion->rclBounds.top, 
+           ClipRegion->rclBounds.right, ClipRegion->rclBounds.bottom);
+    }
 
     psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
 
     /* Sanity check */
     ASSERT(IS_VALID_ROP4(Rop4));
 
+    cxSrc = SourceRect->right - SourceRect->left;
+    cySrc = SourceRect->bottom - SourceRect->top;
+    cxDest = DestRect->right - DestRect->left;
+    cyDest = DestRect->bottom - DestRect->top;
+
+    Case1110 = ((cxDest > 0) && (cyDest > 0) && (cxSrc > 0) && (cySrc < 0));
+    Case1101 = ((cxDest > 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc > 0));
+    Case1100 = ((cxDest > 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc < 0));
+    Case1011 = ((cxDest > 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc > 0));
+    Case1010 = ((cxDest > 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc < 0));
+    Case1001 = ((cxDest > 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc > 0));
+    Case1000 = ((cxDest > 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc < 0));
+    Case0111 = ((cxDest < 0) && (cyDest > 0) && (cxSrc > 0) && (cySrc > 0));
+    Case0110 = ((cxDest < 0) && (cyDest > 0) && (cxSrc > 0) && (cySrc < 0));
+    Case0101 = ((cxDest < 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc > 0));
+    Case0100 = ((cxDest < 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc < 0));
+    Case0011 = ((cxDest < 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc > 0));
+    Case0010 = ((cxDest < 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc < 0));
+    Case0001 = ((cxDest < 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc > 0));
+    Case0000 = ((cxDest < 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc < 0));
+
+    /* Make DestRect & OutputRect Well Ordered to start */
+    RECTL_vMakeWellOrdered(DestRect);
+    OutputRect = *DestRect;
+
+    /* Here we do the tests and set our conditions */
+    if (((cxSrc < 0) && (cxDest < 0)) || ((cxSrc >= 0) && (cxDest >= 0)))
+        bLeftToRight = FALSE;
+    else
+        bLeftToRight = TRUE;
+
+    if (((cySrc < 0) && (cyDest < 0)) || ((cySrc >= 0) && (cyDest >= 0)))
+        bTopToBottom = FALSE;
+    else
+        bTopToBottom = TRUE;
+
+    DPRINT("bTopToBottom is '%d' and bLeftToRight is '%d'.\n", bTopToBottom, bLeftToRight);
+
     /* Check if source and dest size are equal */
-    if (((DestRect->right - DestRect->left) == (SourceRect->right - SourceRect->left)) &&
-        ((DestRect->bottom - DestRect->top) == (SourceRect->bottom - SourceRect->top)))
+    if ((abs(DestRect->right - DestRect->left) == abs(SourceRect->right - SourceRect->left)) &&
+        (abs(DestRect->bottom - DestRect->top) == abs(SourceRect->bottom - SourceRect->top)))
     {
+        DPRINT("source and dest size are equal.\n");
+
+        DPRINT("IntEngStretchBlt: dstRect: (%d,%d)-(%d,%d)\n",
+                DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
+
+        if (Case0000 || Case0001 || Case0010 || Case0011) // Destinations X & Y are both negative
+        {
+            lTmp = SourceRect->left;
+            SourceRect->left = SourceRect->right;
+            SourceRect->right = lTmp;
+
+            lTmp = SourceRect->top;
+            SourceRect->top = SourceRect->bottom;
+            SourceRect->bottom = lTmp;
+        }
+
+        if (Case0100 || Case0101 || Case0110 || Case0111)  // Destination X is negative and Y is positive
+        {
+            lTmp = SourceRect->left;
+            SourceRect->left = SourceRect->right;
+            SourceRect->right = lTmp;
+        }
+
+        if (Case1000 || Case1001 || Case1010 || Case1011)  // Destination X is positive and Y is negative
+        {
+            lTmp = SourceRect->top;
+            SourceRect->top = SourceRect->bottom;
+            SourceRect->bottom = lTmp;
+        }
+
+        if (bLeftToRight)
+        {
+            lTmp = DestRect->left;
+            DestRect->left = DestRect->right;
+            DestRect->right = lTmp;
+        }
+
+        if (bTopToBottom)
+        {
+            lTmp = DestRect->top;
+            DestRect->top = DestRect->bottom;
+            DestRect->bottom = lTmp;
+        }
+
+        DPRINT("Calling IntEngBitBlt: SourceRect (%d,%d)-(%d,%d) DestRect: (%d,%d)-(%d,%d)\n",
+           SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
+           DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
+
         /* Pass the request to IntEngBitBlt */
         return IntEngBitBlt(psoDest,
                             psoSource,
@@ -415,6 +629,90 @@ IntEngStretchBlt(SURFOBJ *psoDest,
                             Rop4);
     }
 
+    DPRINT("source and dest size are NOT equal.\n");
+
+    DPRINT("SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d)\n",
+           SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
+           DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
+
+    /* if cxSrc < 0 then we change the signs for both cxSrc and cxDest and
+     * we reverse their coordinates, because these outcomes are the same.
+     */
+    if (cxSrc < 0)
+    {
+        lTmp = SourceRect->left;
+        SourceRect->left = SourceRect->right;
+        SourceRect->right = lTmp;
+        lTmp = DestRect->left;
+        DestRect->left = DestRect->right;
+        DestRect->right = lTmp;
+        cxSrc = -cxSrc;
+        cxDest = -cxDest;
+    }
+    /* if cySrc < 0 then we change the signs for both cySrc and cyDest and
+     * we reverse their coordinates, because these outcomes are the same.
+      */
+    if (cySrc < 0)
+    {
+        lTmp = DestRect->top;
+        DestRect->top = DestRect->bottom;
+        DestRect->bottom = lTmp;
+        lTmp = SourceRect->top;
+        SourceRect->top = SourceRect->bottom;
+        SourceRect->bottom = lTmp;
+        cySrc = -cySrc;
+        cyDest = -cyDest;
+    }
+
+    if (Case0010 || Case0111)  // Horizontal Flips
+    {
+        DestRect->left--;
+    }
+
+    if (Case0010 || Case0111 || Case1000 || Case1101)  // Horizontal Flips
+    {
+        SourceRect->left--;
+        SourceRect->right--;
+    }
+
+    if (Case0001 || Case0100 || Case1011 || Case1110)  // Vertical Flips
+    {
+        SourceRect->top--;
+        SourceRect->bottom--;
+    }
+
+    if (Case0011 || Case0110 || Case1001 || Case1100)  // Horizontal and Vertical Flips
+    {
+        SourceRect->left--;
+        SourceRect->right--;
+
+        SourceRect->top--;
+        SourceRect->bottom--;
+    }
+
+    if (Case0000 || Case1010)  // No Flip - Just Copy
+    {
+        SourceRect->top++;
+        SourceRect->bottom++;
+
+        DestRect->top++;
+        DestRect->bottom++;
+    }
+
+    if (Case0000 || Case0101)  // No Flip - Just Copy
+    {
+        SourceRect->left++;
+        SourceRect->right++;
+
+        DestRect->left++;
+        DestRect->right++;
+
+    }
+
+    DPRINT("SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d)\n",
+                SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
+                DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
+
     InputClippedRect = *DestRect;
     if (InputClippedRect.right < InputClippedRect.left)
     {
@@ -429,6 +727,7 @@ IntEngStretchBlt(SURFOBJ *psoDest,
 
     if (NULL == psoSource)
     {
+        DPRINT("Returning FALSE.\n");
         return FALSE;
     }
     InputRect = *SourceRect;
@@ -436,17 +735,28 @@ IntEngStretchBlt(SURFOBJ *psoDest,
     if (InputRect.right < InputRect.left ||
             InputRect.bottom < InputRect.top)
     {
+        DPRINT("Returning TRUE.\n");
         /* Everything clipped away, nothing to do */
         return TRUE;
     }
 
+    DPRINT("InputRect: (%d,%d)-(%d,%d) and InputClippedRect: (%d,%d)-(%d,%d)\n",
+        InputRect.left, InputRect.top, InputRect.right, InputRect.bottom,
+        InputClippedRect.left, InputClippedRect.top, InputClippedRect.right, InputClippedRect.bottom);
+
     if (ClipRegion->iDComplexity != DC_TRIVIAL)
     {
         if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect,
                                &ClipRegion->rclBounds))
         {
+            DPRINT("Returning TRUE.\n");
             return TRUE;
         }
+
+        DPRINT("InputClippedRect: (%d,%d)-(%d,%d) and OutputRect: (%d,%d)-(%d,%d)\n",
+               InputClippedRect.left, InputClippedRect.top, InputClippedRect.right, InputClippedRect.bottom,
+               OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
+
         /* Update source rect */
         InputClWidth = InputClippedRect.right - InputClippedRect.left;
         InputClHeight = InputClippedRect.bottom - InputClippedRect.top;
@@ -460,9 +770,15 @@ IntEngStretchBlt(SURFOBJ *psoDest,
     }
     else
     {
+        DPRINT("Complexity = DC_TRIVIAL.\n");
         OutputRect = InputClippedRect;
     }
 
+
+    DPRINT("InputRect: (%d,%d)-(%d,%d) and OutputRect: (%d,%d)-(%d,%d)\n",
+           InputRect.left, InputRect.top, InputRect.right, InputRect.bottom,
+           OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
+
     if (pMaskOrigin != NULL)
     {
         MaskOrigin.x = pMaskOrigin->x;
@@ -480,6 +796,7 @@ IntEngStretchBlt(SURFOBJ *psoDest,
     /* Call the driver's DrvStretchBlt if available */
     if (psurfDest->flags & HOOK_STRETCHBLTROP)
     {
+        DPRINT("About to call GDIDEVFUNCS(psoDest).StretchBltROP.\n");
         /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */
         ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest,
                                                  psoSource,
@@ -498,6 +815,25 @@ IntEngStretchBlt(SURFOBJ *psoDest,
 
     if (! ret)
     {
+        /* set OutputRect to follow flip */
+        if (bLeftToRight)
+        {
+            lTmp = OutputRect.left;
+            OutputRect.left = OutputRect.right;
+            OutputRect.right = lTmp;
+        }
+
+        if (bTopToBottom)
+        {
+            lTmp = OutputRect.top;
+            OutputRect.top = OutputRect.bottom;
+            OutputRect.bottom = lTmp;
+        }
+        DPRINT("Calling EngStretchBltROP: InputRect: (%d,%d)-(%d,%d) and OutputRect: (%d,%d)-(%d,%d)\n",
+               InputRect.left, InputRect.top, InputRect.right, InputRect.bottom,
+               OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
+
         ret = EngStretchBltROP(psoDest,
                                psoSource,
                                MaskSurf,
index b60ef90..6d11303 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 #include <win32k.h>
+#define NDEBUG
+#include <debug.h>
 DBG_DEFAULT_CHANNEL(GdiBlt);
 
 BOOL APIENTRY
@@ -480,6 +482,29 @@ NtGdiMaskBlt(
         XlateObj = &exlo.xlo;
     }
 
+    DPRINT("DestRect: (%d,%d)-(%d,%d) and SourcePoint is (%d,%d)\n",
+        DestRect.left, DestRect.top, DestRect.right, DestRect.bottom,
+        SourcePoint.x, SourcePoint.y);
+
+    DPRINT("nWidth is '%d' and nHeight is '%d'.\n", nWidth, nHeight);
+
+    /* Fix BitBlt so that it will not flip left to right */
+    if ((DestRect.left > DestRect.right) && (nWidth < 0))
+    {
+        SourcePoint.x += nWidth;
+        nWidth = -nWidth;
+    }
+
+    /* Fix BitBlt so that it will not flip top to bottom */
+    if ((DestRect.top > DestRect.bottom) && (nHeight < 0))
+    {
+        SourcePoint.y += nHeight;
+        nHeight = -nHeight;
+    }
+
+    /* Make Well Ordered so that we don't flip either way */
+    RECTL_vMakeWellOrdered(&DestRect);
+
     /* Perform the bitblt operation */
     Status = IntEngBitBlt(&BitmapDest->SurfObj,
                           BitmapSrc ? &BitmapSrc->SurfObj : NULL,
@@ -563,6 +588,7 @@ GreStretchBltMask(
     BOOL UsesSource;
     BOOL UsesMask;
     ROP4 rop4;
+    BOOL Case0000, Case0101, Case1010, CaseExcept;
 
     rop4 = WIN32_ROP4_TO_ENG_ROP4(dwRop4);
 
@@ -615,12 +641,31 @@ GreStretchBltMask(
         }
     }
 
+
+    Case0000 = ((WidthDest < 0) && (HeightDest < 0) && (WidthSrc < 0) && (HeightSrc < 0));
+    Case0101 = ((WidthDest < 0) && (HeightDest > 0) && (WidthSrc < 0) && (HeightSrc > 0));
+    Case1010 = ((WidthDest > 0) && (HeightDest < 0) && (WidthSrc > 0) && (HeightSrc < 0));
+    CaseExcept = (Case0000 || Case0101 || Case1010);
+
     pdcattr = DCDest->pdcattr;
 
     DestRect.left   = XOriginDest;
     DestRect.top    = YOriginDest;
     DestRect.right  = XOriginDest+WidthDest;
     DestRect.bottom = YOriginDest+HeightDest;
+
+    /* Account for possible negative span values */
+    if ((WidthDest < 0) && !CaseExcept)
+    {
+        DestRect.left++;
+        DestRect.right++;
+    }
+    if ((HeightDest < 0) && !CaseExcept)
+    {
+        DestRect.top++;
+        DestRect.bottom++;
+    }
+
     IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
 
     DestRect.left   += DCDest->ptlDCOrig.x;
@@ -638,6 +683,18 @@ GreStretchBltMask(
     SourceRect.right  = XOriginSrc+WidthSrc;
     SourceRect.bottom = YOriginSrc+HeightSrc;
 
+    /* Account for possible negative span values */
+    if ((WidthSrc < 0) && !CaseExcept)
+    {
+        SourceRect.left++;
+        SourceRect.right++;
+    }
+    if ((HeightSrc < 0) && !CaseExcept)
+    {
+        SourceRect.top++;
+        SourceRect.bottom++;
+    }
+
     if (UsesSource)
     {
         IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
@@ -698,6 +755,10 @@ GreStretchBltMask(
         MaskPoint.y += DCMask->ptlDCOrig.y;
     }
 
+    DPRINT("Calling IntEngStrethBlt SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d).\n",
+           SourceRect.left, SourceRect.top, SourceRect.right, SourceRect.bottom,
+           DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
+
     /* Perform the bitblt operation */
     Status = IntEngStretchBlt(&BitmapDest->SurfObj,
                               BitmapSrc ? &BitmapSrc->SurfObj : NULL,
index 7b8cc33..3d88101 100644 (file)
@@ -628,9 +628,17 @@ NtGdiSetDIBitsToDeviceInternal(
     pDestSurf = &pSurf->SurfObj;
 
     /* Copy the bits */
-    DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
+    DPRINT("BitsToDev with rcDest=(%d|%d) (%d|%d), ptSource=(%d|%d) w=%d h=%d\n",
            rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
            ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
+
+    /* This fixes the large Google text on Google.com from being upside down */
+    if (rcDest.top > rcDest.bottom)
+    {
+        RECTL_vMakeWellOrdered(&rcDest);
+        ptSource.y -= SourceSize.cy;
+    }
+
     bResult = IntEngBitBlt(pDestSurf,
                           pSourceSurf,
                           pMaskSurf,
@@ -722,7 +730,7 @@ GreGetDIBitsInternal(
                                     &size);
     if(bitmap_type == -1)
     {
-        DPRINT("Wrong bitmap format\n");
+        DPRINT1("Wrong bitmap format\n");
         EngSetLastError(ERROR_INVALID_PARAMETER);
         ScanLines = 0;
         goto done;