https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ce7836c6d3cb755d82c0a…
commit ce7836c6d3cb755d82c0a5de7e6fad225b949c3f
Author: Doug Lyons <douglyons(a)douglyons.com>
AuthorDate: Sat Feb 20 17:28:36 2021 -0600
Commit: GitHub <noreply(a)github.com>
CommitDate: Sun Feb 21 08:28:36 2021 +0900
[WIN32K] Add StretchBlt function ability to flip images (#3458)
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
---
win32ss/gdi/dib/dib16bpp.c | 309 +++++++++++++++++++++++--
win32ss/gdi/dib/dib1bpp.c | 210 +++++++++++++++--
win32ss/gdi/dib/dib24bpp.c | 289 +++++++++++++++++++++--
win32ss/gdi/dib/dib32bpp.c | 532 ++++++++++++++++++++++++++++++++++++++-----
win32ss/gdi/dib/dib32bppc.c | 3 +
win32ss/gdi/dib/dib4bpp.c | 201 ++++++++++++++--
win32ss/gdi/dib/dib8bpp.c | 313 +++++++++++++++++++++++--
win32ss/gdi/dib/stretchblt.c | 63 ++++-
win32ss/gdi/eng/bitblt.c | 77 ++++++-
win32ss/gdi/eng/copybits.c | 55 ++++-
win32ss/gdi/eng/stretchblt.c | 344 +++++++++++++++++++++++++++-
win32ss/gdi/ntgdi/bitblt.c | 61 +++++
win32ss/gdi/ntgdi/dibobj.c | 12 +-
13 files changed, 2304 insertions(+), 165 deletions(-)
diff --git a/win32ss/gdi/dib/dib16bpp.c b/win32ss/gdi/dib/dib16bpp.c
index 6ce4568293b..52789cfb3e4 100644
--- a/win32ss/gdi/dib/dib16bpp.c
+++ b/win32ss/gdi/dib/dib16bpp.c
@@ -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;
diff --git a/win32ss/gdi/dib/dib1bpp.c b/win32ss/gdi/dib/dib1bpp.c
index e5dc0fda639..034570e9cad 100644
--- a/win32ss/gdi/dib/dib1bpp.c
+++ b/win32ss/gdi/dib/dib1bpp.c
@@ -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);
diff --git a/win32ss/gdi/dib/dib24bpp.c b/win32ss/gdi/dib/dib24bpp.c
index 0974842b503..bc12095843e 100644
--- a/win32ss/gdi/dib/dib24bpp.c
+++ b/win32ss/gdi/dib/dib24bpp.c
@@ -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;
diff --git a/win32ss/gdi/dib/dib32bpp.c b/win32ss/gdi/dib/dib32bpp.c
index 78124b8d49a..1b2d920e96e 100644
--- a/win32ss/gdi/dib/dib32bpp.c
+++ b/win32ss/gdi/dib/dib32bpp.c
@@ -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);
diff --git a/win32ss/gdi/dib/dib32bppc.c b/win32ss/gdi/dib/dib32bppc.c
index fb1c0dc38d6..af2039545fc 100644
--- a/win32ss/gdi/dib/dib32bppc.c
+++ b/win32ss/gdi/dib/dib32bppc.c
@@ -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);
diff --git a/win32ss/gdi/dib/dib4bpp.c b/win32ss/gdi/dib/dib4bpp.c
index 56c03e50658..69daf319f6e 100644
--- a/win32ss/gdi/dib/dib4bpp.c
+++ b/win32ss/gdi/dib/dib4bpp.c
@@ -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);
diff --git a/win32ss/gdi/dib/dib8bpp.c b/win32ss/gdi/dib/dib8bpp.c
index c30d738b67b..520037bf709 100644
--- a/win32ss/gdi/dib/dib8bpp.c
+++ b/win32ss/gdi/dib/dib8bpp.c
@@ -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);
diff --git a/win32ss/gdi/dib/stretchblt.c b/win32ss/gdi/dib/stretchblt.c
index c768cf8e34c..718d8183f7a 100644
--- a/win32ss/gdi/dib/stretchblt.c
+++ b/win32ss/gdi/dib/stretchblt.c
@@ -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)
{
diff --git a/win32ss/gdi/eng/bitblt.c b/win32ss/gdi/eng/bitblt.c
index 8eea77535bb..59641cd6235 100644
--- a/win32ss/gdi/eng/bitblt.c
+++ b/win32ss/gdi/eng/bitblt.c
@@ -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,
diff --git a/win32ss/gdi/eng/copybits.c b/win32ss/gdi/eng/copybits.c
index 0b8824392db..92539da148e 100644
--- a/win32ss/gdi/eng/copybits.c
+++ b/win32ss/gdi/eng/copybits.c
@@ -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;
diff --git a/win32ss/gdi/eng/stretchblt.c b/win32ss/gdi/eng/stretchblt.c
index 2fb1a9afd2b..3b290e29a8a 100644
--- a/win32ss/gdi/eng/stretchblt.c
+++ b/win32ss/gdi/eng/stretchblt.c
@@ -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>
@@ -11,6 +12,21 @@
#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,
diff --git a/win32ss/gdi/ntgdi/bitblt.c b/win32ss/gdi/ntgdi/bitblt.c
index b60ef9047f8..6d113035d90 100644
--- a/win32ss/gdi/ntgdi/bitblt.c
+++ b/win32ss/gdi/ntgdi/bitblt.c
@@ -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,
diff --git a/win32ss/gdi/ntgdi/dibobj.c b/win32ss/gdi/ntgdi/dibobj.c
index 7b8cc330c73..3d88101c8ab 100644
--- a/win32ss/gdi/ntgdi/dibobj.c
+++ b/win32ss/gdi/ntgdi/dibobj.c
@@ -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;