diff --git a/win32ss/gdi/dib/dib16bpp.c b/win32ss/gdi/dib/dib16bpp.c index 6ce4568293..59bcd38484 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 @@ -13,6 +14,9 @@ #define NDEBUG #include +#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; jDestRect.bottom; j++) { sx = BltInfo->SourcePoint.x; - for (i=BltInfo->DestRect.left; iDestRect.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; jDestRect.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; iDestRect.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,166 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) DestLine -= BltInfo->DestSurface->lDelta; } } + } + 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 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); + OneDone = 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 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 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 +599,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 +612,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 +640,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 +675,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 e5dc0fda63..034570e9ca 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 @@ -11,6 +12,9 @@ #define NDEBUG #include +#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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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 0974842b50..4e09f993d2 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 @@ -13,6 +14,9 @@ #define NDEBUG #include +#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' & 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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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,150 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo) } sy++; } + } + else + { + /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */ + BOOL OneDone = 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; jDestRect.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; iDestRect.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; iDestRect.right; i++) + { + DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, store[Index])); + Index++; + } + sy++; + } + ExFreePoolWithTag(store, TAG_DIB); + OneDone = 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 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) + { + 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; iDestRect.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; jDestRect.bottom; j++) + { + if (OneDone) + { + 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; jDestRect.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 +453,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 +510,9 @@ DIB_24BPP_BitBlt(PBLTINFO BltInfo) else { if (BltInfo->Brush) + { Pattern = BltInfo->Brush->iSolidColor; + } } } @@ -301,6 +558,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 78124b8d49..31ae22bea4 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 @@ -13,6 +14,9 @@ #define NDEBUG #include +#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,135 @@ 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; + 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' & 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); + + /* Our default DestBits points to the top-left with lDelta > 0 and must be recalculated if lDelta < 0 */ 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, + BltInfo->DestRect.right - BltInfo->DestRect.left, BltInfo->DestRect.bottom - BltInfo->DestRect.top); + switch (BltInfo->SourceSurface->iBitmapFormat) { case BMF_1BPP: + DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left); + + 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 * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1); + } + for (j=BltInfo->DestRect.top; jDestRect.bottom; j++) { sx = BltInfo->SourcePoint.x; - for (i=BltInfo->DestRect.left; iDestRect.right; i++) + + 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) { 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", + BltInfo->DestRect.right - BltInfo->DestRect.left); + + 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 * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1); + } + for (j=BltInfo->DestRect.top; jDestRect.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; iDestRect.right; i++) @@ -99,66 +192,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", + BltInfo->DestRect.right - BltInfo->DestRect.left); + + 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 * (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); + } + 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", + BltInfo->DestRect.right - BltInfo->DestRect.left); + + 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 * (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) * 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", + BltInfo->DestRect.right - BltInfo->DestRect.left); + + 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 * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1); + } + DestLine = DestBits; for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) @@ -166,28 +313,48 @@ DIB_32BPP_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) + (*(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, + BltInfo->DestRect.right - BltInfo->DestRect.left, + BltInfo->DestRect.bottom - BltInfo->DestRect.top, + BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom); + + 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"); + + /* This does a Simple Top-to-Bottom flip in order to correct for negative lDelta values */ 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)); @@ -197,12 +364,15 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo) } 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) + + 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; + /* 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)); @@ -210,69 +380,268 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo) 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 * (BltInfo->DestRect.right - BltInfo->DestRect.left)); + 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) + + 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 * (BltInfo->DestRect.right - BltInfo->DestRect.left)); + 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 + (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--) + { + *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--); + } + } + SourceBits += BltInfo->SourceSurface->lDelta; + DestBits += BltInfo->DestSurface->lDelta; } - else + } + 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--) { - 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 + (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--) + { + *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 OneDone = FALSE; + + /* Left to Right Handling if bitmap more than one pixel wide */ + if ((bLeftToRight) && ((BltInfo->DestRect.right - BltInfo->DestRect.left) > 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, + (BltInfo->DestRect.right - BltInfo->DestRect.left + 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 + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 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 + (BltInfo->DestRect.right - BltInfo->DestRect.left - 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); + OneDone = TRUE; + } + + /* Top to Botoom Handling if bitmap more than one pixel high */ + if ((bTopToBottom) && ((BltInfo->DestRect.bottom - BltInfo->DestRect.top) > 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, + (BltInfo->DestRect.right - BltInfo->DestRect.left + 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 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. + * 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 (OneDone || 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--) - { - *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--); - } + /* This sets SourceBitsB to the bottom line */ + SourceBitsB = (PBYTE)BltInfo->SourceSurface->pvScan0 + + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 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; } - SourceBits -= BltInfo->SourceSurface->lDelta; - DestBits -= BltInfo->DestSurface->lDelta; + + for (j = 0; j < (BltInfo->DestRect.bottom - BltInfo->DestRect.top) / 2 ; j++) + { + /* Store bottom row of Source pixels */ + RtlMoveMemory(&store[0], SourceBitsB, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left)); + + /* Copy top Source row to bottom Destination row overwriting it */ + RtlMoveMemory(DestBitsB, SourceBitsT, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left)); + + /* Copy stored bottom row of Source pixels to Destination top row of pixels */ + RtlMoveMemory(DestBitsT, &store[0], 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left)); + + /* 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 ((BltInfo->DestRect.bottom - BltInfo->DestRect.top) % 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 * (BltInfo->DestRect.right - BltInfo->DestRect.left)); + } + 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 +721,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 fb1c0dc38d..af2039545f 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 56c03e5065..69daf319f6 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 #define NDEBUG #include +#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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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 c30d738b67..520037bf70 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 @@ -13,6 +14,9 @@ #define NDEBUG #include +#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; jDestRect.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; iDestRect.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; jDestRect.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; iDestRect.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 c768cf8e34..8739236069 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 @@ -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 8eea77535b..59641cd623 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 @@ -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 0b8824392d..92539da148 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 @@ -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 2fb1a9afd2..57409eb88d 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 @@ -11,6 +12,21 @@ #define NDEBUG #include +/*************************************************************************************************************************** + 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,88 @@ 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 +725,7 @@ IntEngStretchBlt(SURFOBJ *psoDest, if (NULL == psoSource) { + DPRINT("Returning FALSE.\n"); return FALSE; } InputRect = *SourceRect; @@ -436,17 +733,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 +768,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 +794,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 +813,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 b60ef9047f..6d113035d9 100644 --- a/win32ss/gdi/ntgdi/bitblt.c +++ b/win32ss/gdi/ntgdi/bitblt.c @@ -7,6 +7,8 @@ */ #include +#define NDEBUG +#include 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 7b8cc330c7..3d88101c8a 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;