diff --git a/win32ss/gdi/dib/dib16bpp.c b/win32ss/gdi/dib/dib16bpp.c index 6ce4568293..5ba404bfbf 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 @@ -139,19 +140,79 @@ DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c) BOOLEAN DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) { - LONG i, j, sx, sy, xColor, f1; + LONG i, j, sx, sy, xColor, f1, flip, lTmp; PBYTE SourceBits, DestBits, SourceLine, DestLine; PBYTE SourceBits_4BPP, SourceLine_4BPP; + + 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); + + /* Retrieve flip here and then make Well-Ordered again */ + if ((BltInfo->DestRect.left > BltInfo->DestRect.right) && (BltInfo->DestRect.top > BltInfo->DestRect.bottom)) + { + flip = 3; + } + else if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + flip = 1; + } + else if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + flip = 2; + } + else + { + flip = 0; + } + + /* Make WellOrdered with top < bottom and left < right */ + if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + lTmp = BltInfo->DestRect.left; + BltInfo->DestRect.left = BltInfo->DestRect.right; + BltInfo->DestRect.right = lTmp; + } + + if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + lTmp = BltInfo->DestRect.top; + BltInfo->DestRect.top = BltInfo->DestRect.bottom; + BltInfo->DestRect.bottom = lTmp; + } + + DPRINT("flip/bpp is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n", + flip, 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' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); sx = BltInfo->SourcePoint.x; + + /* This sets sy to the top line */ sy = BltInfo->SourcePoint.y; + + if ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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) @@ -164,21 +225,51 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1)); } - sx++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } break; case BMF_4BPP: + DPRINT("4BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* 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 ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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 +279,109 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor); if(f1 == 1) { - SourceLine_4BPP++; + if ((flip == 1) || (flip == 3)) + { + SourceLine_4BPP--; + } + else + { + SourceLine_4BPP++; + } f1 = 0; } else { f1 = 1; } - sx++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + SourceBits_4BPP -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceBits_4BPP += BltInfo->SourceSurface->lDelta; } - SourceBits_4BPP += BltInfo->SourceSurface->lDelta; } break; case BMF_8BPP: + DPRINT("8BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* This sets SourceLine to the top line */ SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x; DestLine = DestBits; + if ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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; + if ((flip == 1) || (flip == 3)) + { + SourceBits -= 1; + } + else + { + SourceBits += 1; + } DestBits += 2; } - - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip == 3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += 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' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + 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 ((NULL == BltInfo->XlateSourceToDest || 0 != + (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL)) && (flip == 0)) { + 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 +399,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 +425,11 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) } else { + DPRINT("XO_TRIVIAL is NOT TRUE.\n"); + if (flip == 0) + /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */ + { + DPRINT("Flip == 0.\n"); if (BltInfo->DestRect.top < BltInfo->SourcePoint.y) { SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + @@ -330,14 +487,153 @@ 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 ((flip == 1) || (flip == 3)) + { + DPRINT("Flip == 1 or 3.\n"); + + /* Allocate enough pixels for a row in DWORD's */ + DWORD store[BltInfo->DestRect.right - BltInfo->DestRect.left + 1]; + WORD Index; + + /* This sets SourceLine to the top line */ + SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + + (BltInfo->SourcePoint.y * + BltInfo->SourceSurface->lDelta) + 2 * + BltInfo->SourcePoint.x; + + /* This set the DestLine to the top line */ + DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + + 2 * 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) * 2; + + Index = 0; + + for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++) + { + store[Index] = (WORD)XLATEOBJ_iXlate( + BltInfo->XlateSourceToDest, + *((WORD *)SourceBits)); + SourceBits -= 2; + Index++; + } + + Index = 0; + + for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++) + { + *((WORD *)DestBits) = store[Index]; + DestBits += 2; + Index++; + } + + SourceLine += BltInfo->SourceSurface->lDelta; + DestLine += BltInfo->DestSurface->lDelta; + } + OneDone = TRUE; + } + + if ((flip == 2) || (flip == 3)) + { + DPRINT("Flip == 2 or 3.\n"); + DWORD Index; + + /* Allocate enough pixels for a column in DWORD's */ + WORD store[BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1]; + + /* This set the DestLine to the top line */ + DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + + 2 * BltInfo->DestRect.left; + + /* The OneDone flag indicates that we are doing a flip == 3 and have already */ + /* completed the flip == 1. 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) + 2 * 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->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x + + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta; + } + + /* 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] = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((WORD *)SourceBits)); + /* Go up a line */ + SourceBits -= BltInfo->SourceSurface->lDelta; + Index++; + } + + Index = 0; + + /* Get the stored pixels and copy them down the column */ + for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) + { + *((WORD *)DestBits) = store[Index]; + /* Go down a line */ + DestBits += BltInfo->SourceSurface->lDelta; + Index++; + } + /* Index to next column */ + SourceLine += 2; + DestLine += 2; + } + } + + } } 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 ((flip == 2) || (flip ==3)) + { + /* 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 +641,11 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) SourceBits = SourceLine; DestBits = DestLine; + if ((flip == 1) || (flip == 3)) + { + /* 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 +654,41 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( BltInfo->XlateSourceToDest, xColor); - SourceBits += 3; + if ((flip == 1) || (flip == 3)) + { + SourceBits -= 3; + } + else + { + SourceBits += 3; + } DestBits += 2; } - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip ==3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += BltInfo->SourceSurface->lDelta; + } DestLine += BltInfo->DestSurface->lDelta; } break; case BMF_32BPP: + DPRINT("32BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x; + if ((flip == 2) || (flip ==3)) + { + /* 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,22 +696,42 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) SourceBits = SourceLine; DestBits = DestLine; + if ((flip == 1) || (flip == 3)) + { + /* 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; + if ((flip == 1) || (flip ==3)) + { + SourceBits -= 4; + } + else + { + SourceBits += 4; + } DestBits += 2; } - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip ==3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += BltInfo->SourceSurface->lDelta; + } DestLine += BltInfo->DestSurface->lDelta; } break; default: - DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", + DPRINT1("DIB_16BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat)); return FALSE; } @@ -400,7 +743,21 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) BOOLEAN DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color) { - LONG DestY; + LONG DestY, lTmp; + + /* Make WellOrdered with top < bottom and left < right */ + if (DestRect->left > DestRect->right) + { + lTmp = DestRect->left; + DestRect->left = DestRect->right; + DestRect->right = lTmp; + } + if (DestRect->top > DestRect->bottom) + { + lTmp = DestRect->top; + DestRect->top = DestRect->bottom; + DestRect->bottom = lTmp; + } #if defined(_M_IX86) && !defined(_MSC_VER) /* This is about 10% faster than the generic C code below */ diff --git a/win32ss/gdi/dib/dib1bpp.c b/win32ss/gdi/dib/dib1bpp.c index e5dc0fda63..556879d9ed 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 @@ -57,13 +58,14 @@ DIB_1BPP_BitBltSrcCopy_From1BPP ( SURFOBJ* SourceSurf, XLATEOBJ* pxlo, PRECTL DestRect, - POINTL *SourcePoint ) + POINTL *SourcePoint, + LONG flip ) { // 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 @@ -99,36 +101,85 @@ DIB_1BPP_BitBltSrcCopy_From1BPP ( // Moving up (scan top -> bottom) dy1 = DestRect->top; dy2 = DestRect->bottom - 1; - sy1 = SourcePoint->y; + if ((flip == 2) || (flip ==3)) + { + sy1 = SourcePoint->y + dy1 - dy2; + } + else + { + sy1 = SourcePoint->y; + } yinc = 1; - ySrcDelta = SourceSurf->lDelta; - yDstDelta = DestSurf->lDelta; + + if ((flip == 2) || (flip ==3)) + { + ySrcDelta = DestSurf->lDelta; + yDstDelta = SourceSurf->lDelta; + } + else + { + ySrcDelta = SourceSurf->lDelta; + yDstDelta = DestSurf->lDelta; + } + } else { // Moving down (scan bottom -> top) dy1 = DestRect->bottom - 1; dy2 = DestRect->top; - sy1 = SourcePoint->y + dy1 - dy2; + if ((flip == 2) || (flip ==3)) + { + sy1 = SourcePoint->y; + } + else + { + sy1 = SourcePoint->y + dy1 - dy2; + } yinc = -1; - ySrcDelta = -SourceSurf->lDelta; - yDstDelta = -DestSurf->lDelta; + + if ((flip == 2) || (flip ==3)) + { + ySrcDelta = -DestSurf->lDelta; + yDstDelta = -SourceSurf->lDelta; + } + else + { + ySrcDelta = -SourceSurf->lDelta; + yDstDelta = -DestSurf->lDelta; + } } if ( DestRect->left <= SourcePoint->x ) { // Moving left (scan left->right) dwx = dl&~7; - swx = (sl-(dl&7))&~7; dwx2 = dr&~7; - xinc = 1; + if ((flip == 1) || (flip == 3)) + { + swx = (sr - (dr & 7)) & ~7; + xinc = -1; + } + else + { + swx = (sl-(dl&7))&~7; + xinc = 1; + } } else { // 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 ((flip == 1) || (flip == 3)) + { + 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 +278,293 @@ BOOLEAN DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo) { ULONG Color; - LONG i, j, sx, sy = BltInfo->SourcePoint.y; + LONG i, j, sx, sy; + LONG flip, lTmp; + + // 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); + + // Retrieve flip here and then make Well-Ordered again + // Get back flip here + + if ((BltInfo->DestRect.left > BltInfo->DestRect.right) && (BltInfo->DestRect.top > BltInfo->DestRect.bottom)) + { + flip = 3; + } + else if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + flip = 1; + } + else if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + flip = 2; + } + else + { + flip = 0; + } + + // Make WellOrdered with top < bottom and left < right + if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + lTmp = BltInfo->DestRect.left; + BltInfo->DestRect.left = BltInfo->DestRect.right; + BltInfo->DestRect.right = lTmp; + } + if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + lTmp = BltInfo->DestRect.top; + BltInfo->DestRect.top = BltInfo->DestRect.bottom; + BltInfo->DestRect.bottom = lTmp; + } + + DPRINT("flip/bpp is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n", + flip, 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' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + DIB_1BPP_BitBltSrcCopy_From1BPP ( BltInfo->DestSurface, BltInfo->SourceSurface, + BltInfo->XlateSourceToDest, &BltInfo->DestRect, &BltInfo->SourcePoint, flip ); break; case BMF_4BPP: + DPRINT("4BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + if ((flip == 2) || (flip ==3)) + { + // 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 ((flip == 1) || (flip == 3)) + { + // 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++; + + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } 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 ((flip == 2) || (flip == 3)) + { + // 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 ((flip == 1) || (flip == 3)) + { + // 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++; + + if ((flip == 2) || (flip ==3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } 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 ((flip == 2) || (flip ==3)) + { + // 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 ((flip == 1) || (flip == 3)) + { + // 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++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } 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 ((flip == 2) || (flip ==3)) + { + // 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 ((flip == 1) || (flip == 3)) + { + // 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++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } 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 ((flip == 2) || (flip ==3)) + { + // 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 ((flip == 1) || (flip == 3)) + { + // 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++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } break; @@ -458,7 +721,21 @@ DIB_1BPP_BitBlt(PBLTINFO BltInfo) BOOLEAN DIB_1BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color) { - LONG DestY; + LONG DestY, lTmp; + + /* Make WellOrdered with top < bottom and left < right */ + if (DestRect->left > DestRect->right) + { + lTmp = DestRect->left; + DestRect->left = DestRect->right; + DestRect->right = lTmp; + } + if (DestRect->top > DestRect->bottom) + { + lTmp = DestRect->top; + DestRect->top = DestRect->bottom; + DestRect->bottom = lTmp; + } for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++) { diff --git a/win32ss/gdi/dib/dib24bpp.c b/win32ss/gdi/dib/dib24bpp.c index 0974842b50..efa69e9db1 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 @@ -49,22 +50,78 @@ DIB_24BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c) BOOLEAN DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo) { - LONG i, j, sx, sy, xColor, f1; + LONG i, j, sx, sy, xColor, f1, flip, lTmp; PBYTE SourceBits, DestBits, SourceLine, DestLine; PBYTE SourceBits_4BPP, SourceLine_4BPP; PWORD SourceBits_16BPP, SourceLine_16BPP; + 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 flip here */ + if ((BltInfo->DestRect.left > BltInfo->DestRect.right) && (BltInfo->DestRect.top > BltInfo->DestRect.bottom)) + { + flip = 3; + } + else if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + flip = 2; + } + else if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + flip = 1; + } + else + { + flip = 0; + } + + DPRINT("flip is '%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n", + flip, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y); + + /* Make WellOrdered by making top < bottom and left < right */ + if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + lTmp = BltInfo->DestRect.left; + BltInfo->DestRect.left = BltInfo->DestRect.right; + BltInfo->DestRect.right = lTmp; + } + + if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + lTmp = BltInfo->DestRect.top; + BltInfo->DestRect.top = BltInfo->DestRect.bottom; + BltInfo->DestRect.bottom = lTmp; + } + DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left * 3; switch(BltInfo->SourceSurface->iBitmapFormat) { case BMF_1BPP: sx = BltInfo->SourcePoint.x; + + /* This sets sy to the top line */ sy = BltInfo->SourcePoint.y; + if ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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 +130,51 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo) } else { DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1)); } - sx++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } break; case BMF_4BPP: + DPRINT("4BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* 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 ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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 +184,54 @@ 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) { + if ((flip == 1) || (flip == 3)) + { + SourceLine_4BPP--; + } + else + { + SourceLine_4BPP++; + } + f1 = 0; + } + else + { + f1 = 1; + } + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + SourceBits_4BPP -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceBits_4BPP += BltInfo->SourceSurface->lDelta; } - - SourceBits_4BPP += BltInfo->SourceSurface->lDelta; DestBits += BltInfo->DestSurface->lDelta; } break; case BMF_8BPP: + DPRINT("8BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* This sets SourceLine to the top line */ SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x; + + if ((flip == 2) || (flip ==3)) + { + /* 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 +239,102 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo) SourceBits = SourceLine; DestBits = DestLine; + if ((flip == 1) || (flip == 3)) + { + /* 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; + if ((flip == 1) || (flip == 3)) + { + SourceBits -= 1; + } + else + { + SourceBits += 1; + } DestBits += 3; } - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip == 3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += BltInfo->SourceSurface->lDelta; + } DestLine += BltInfo->DestSurface->lDelta; } break; case BMF_16BPP: + DPRINT("16BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* 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 ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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++; + if ((flip == 1) || (flip == 3)) + { + SourceLine_16BPP--; + } + else + { + SourceLine_16BPP++; + } + } + if ((flip == 2) || (flip == 3)) + { + 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' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* Check for flip == 0 here because we are about to use RtlMoveMemory and it can only do increasing src & dst */ + if ((NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL)) && flip == 0) { + 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 +356,11 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo) } } else + { + DPRINT("XO_TRIVIAL is NOT TRUE.\n"); + + if (flip == 0) + /* **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 +376,138 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo) } sy++; } + } + else + { + /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */ + BOOL OneDone = FALSE; + + if ((flip == 1) || (flip == 3)) + { + DPRINT("Flip == 1 or 3.\n"); + // Buffering for when source and destination overlap. KHMZ MirrorTest CORE-16642 fix + + DWORD Index; + + /* Allocate enough pixels for a row in DWORD's */ + DWORD store[BltInfo->DestRect.right - BltInfo->DestRect.left + 1]; + + 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++; + } + OneDone = TRUE; + } + + if ((flip == 2) || (flip == 3)) + { + DPRINT("Flip == 2 or 3.\n"); + DWORD Index; + + /* Allocate enough pixels for a column in DWORD's */ + DWORD store[BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1]; + + /* The OneDone flag indicates that we are doing a flip == 3 and have already */ + /* completed the flip == 1. 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++; + } + } + + } } break; case BMF_32BPP: + DPRINT("32BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x; + + if ((flip == 2) || (flip ==3)) + { + /* 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 +515,35 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo) SourceBits = SourceLine; DestBits = DestLine; + if ((flip == 1) || (flip == 3)) + { + /* 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; + if ((flip == 1) || (flip ==3)) + { + SourceBits -= 4; + } + else + { + SourceBits += 4; + } DestBits += 3; } - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip ==3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += BltInfo->SourceSurface->lDelta; + } DestLine += BltInfo->DestSurface->lDelta; } break; @@ -255,7 +586,9 @@ DIB_24BPP_BitBlt(PBLTINFO BltInfo) else { if (BltInfo->Brush) + { Pattern = BltInfo->Brush->iSolidColor; + } } } @@ -299,7 +632,21 @@ DIB_24BPP_BitBlt(PBLTINFO BltInfo) BOOLEAN DIB_24BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color) { - LONG DestY; + LONG DestY, lTmp; + + /* Make WellOrdered by making top < bottom and left < right */ + if (DestRect->left > DestRect->right) + { + lTmp = DestRect->left; + DestRect->left = DestRect->right; + DestRect->right = lTmp; + } + if (DestRect->top > DestRect->bottom) + { + lTmp = DestRect->top; + DestRect->top = DestRect->bottom; + DestRect->bottom = lTmp; + } #if defined(_M_IX86) && !defined(_MSC_VER) PBYTE xaddr = (PBYTE)DestSurface->pvScan0 + DestRect->top * DestSurface->lDelta + (DestRect->left << 1) + DestRect->left; diff --git a/win32ss/gdi/dib/dib32bpp.c b/win32ss/gdi/dib/dib32bpp.c index 78124b8d49..4398d2fbb2 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 @@ -49,25 +50,91 @@ DIB_32BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c) BOOLEAN DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo) { - LONG i, j, sx, sy, xColor, f1; + LONG i, j, sx, sy, xColor, f1, flip, lTmp; PBYTE SourceBits, DestBits, SourceLine, DestLine; + PBYTE SourceBitsT, SourceBitsB, DestBitsT, DestBitsB; PBYTE SourceBits_4BPP, SourceLine_4BPP; PDWORD Source32, Dest32; + DWORD Index; + + DPRINT("DIB_32BPP_BitBltSrcCopy: SrcPt (%d, %d), SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%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); + + /* Get back flip here */ + if ((BltInfo->DestRect.left > BltInfo->DestRect.right) && (BltInfo->DestRect.top > BltInfo->DestRect.bottom)) + { + flip = 3; + } + else if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + flip = 2; + } + else if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + flip = 1; + } + else + { + flip = 0; + } + + DPRINT("flip is '%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n", + flip, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y); + + /* Make WellOrdered with top < bottom and left < right */ + if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + lTmp = BltInfo->DestRect.left; + BltInfo->DestRect.left = BltInfo->DestRect.right; + BltInfo->DestRect.right = lTmp; + } + if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + lTmp = BltInfo->DestRect.top; + BltInfo->DestRect.top = BltInfo->DestRect.bottom; + BltInfo->DestRect.bottom = lTmp; + } 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); + + DPRINT("Being Drawn at point '(%d,%d)-(%d,%d)'.\n", + BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom); + switch (BltInfo->SourceSurface->iBitmapFormat) { case BMF_1BPP: + DPRINT("1BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); sx = BltInfo->SourcePoint.x; + + /* This sets sy to the top line */ sy = BltInfo->SourcePoint.y; + if ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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) @@ -76,21 +143,53 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo) } else { DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1)); } - sx++; + + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } break; case BMF_4BPP: + DPRINT("4BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* 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 ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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 +198,156 @@ 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++; + if ((flip == 1) || (flip == 3)) + { + SourceLine_4BPP--; + } + else + { + SourceLine_4BPP++; + } f1 = 0; } else { f1 = 1; } - sx++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + SourceBits_4BPP -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceBits_4BPP += BltInfo->SourceSurface->lDelta; } - - SourceBits_4BPP += BltInfo->SourceSurface->lDelta; } break; case BMF_8BPP: + DPRINT("8BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* This sets SourceLine to the top line */ SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x; DestLine = DestBits; + if ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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; + if ((flip == 1) || (flip == 3)) + { + SourceBits--; + } + else + { + SourceBits++; + } DestBits += 4; } - - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip == 3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += BltInfo->SourceSurface->lDelta; + } DestLine += BltInfo->DestSurface->lDelta; } break; case BMF_16BPP: + DPRINT("16BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* 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 ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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; + if ((flip == 1) || (flip == 3)) + { + SourceBits -= 2; + } + else + { + SourceBits += 2; + } DestBits += 4; } - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip == 3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += BltInfo->SourceSurface->lDelta; + } DestLine += BltInfo->DestSurface->lDelta; } break; case BMF_24BPP: + DPRINT("24BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* This sets SourceLine to the top line */ SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x; + + if ((flip == 2) || (flip ==3)) + { + /* 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,25 +355,54 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo) SourceBits = SourceLine; DestBits = DestLine; + if ((flip == 1) || (flip == 3)) + { + /* 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; + if ((flip == 1) || (flip == 3)) + { + SourceBits -= 3; + } + else + { + SourceBits += 3; + } DestBits += 4; } - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip ==3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += 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 SrcPt (%d,%d) and DestRect Width/height of '%d/%d' and flip of '%d'.\n", + BltInfo->SourcePoint.x, BltInfo->SourcePoint.y, + BltInfo->DestRect.right - BltInfo->DestRect.left, + BltInfo->DestRect.bottom - BltInfo->DestRect.top, flip); + + /* This tests for whether we can use simplified/quicker code below which uses RtlMoveMemory. + * It works for increasing source and destination areas only where there is no full overlap and no flip. + */ + if ((NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL)) + && (flip == 0)) { + 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; @@ -213,6 +431,10 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo) } else { + DPRINT("XO_TRIVIAL is NOT TRUE.\n"); + if (flip == 0) + /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */ + { if (BltInfo->DestRect.top < BltInfo->SourcePoint.y) { SourceBits = ((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x); @@ -269,10 +491,135 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo) } } } + else + { + /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */ + BOOL OneDone = FALSE; + + if ((flip == 1) || (flip == 3)) + { + DPRINT("Flip == 1 or 3.\n"); + + /* Allocate enough pixels for a row in DWORD's */ + DWORD store[BltInfo->DestRect.right - BltInfo->DestRect.left + 1]; + + /* 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; + + /* Set DestBits to 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] = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *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-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, store[Index]); + Index++; + } + SourceBits -= BltInfo->SourceSurface->lDelta; + DestBits -= BltInfo->DestSurface->lDelta; + } + OneDone = TRUE; + } + + if ((flip == 2) || (flip == 3)) + { + + /* 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 == 2 or 3.\n"); + + /* Allocate enough pixels for a row in DWORD's */ + DWORD store[BltInfo->DestRect.right - BltInfo->DestRect.left + 1]; + + /* 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 doing a flip == 3 and have already */ + /* completed the flip == 1. 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 SourceBitsB to the bottom line */ + SourceBitsB = DestBitsB; + + /* This sets SourceBitsT to the top line */ + SourceBitsT = DestBitsT; + } + else + { + /* 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; + } + + for (j = 0; j < (BltInfo->DestRect.bottom - BltInfo->DestRect.top) / 2 ; j++) + { + /* Store bottom row */ + RtlMoveMemory(&store[0], SourceBitsB, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left)); + + /* Copy top row to bottom row overwriting it */ + RtlMoveMemory(DestBitsB, SourceBitsT, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left)); + + /* Copy stored bottom row to top row */ + 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 */ + RtlMoveMemory(DestBitsB, SourceBitsT, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left)); + } + } + } + } 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; } diff --git a/win32ss/gdi/dib/dib4bpp.c b/win32ss/gdi/dib/dib4bpp.c index 56c03e5065..b942ce58cf 100644 --- a/win32ss/gdi/dib/dib4bpp.c +++ b/win32ss/gdi/dib/dib4bpp.c @@ -4,6 +4,7 @@ * FILE: win32ss/gdi/dib/dib4bpp.c * PURPOSE: Device Independant Bitmap functions, 4bpp * PROGRAMMERS: Jason Filby + * Doug Lyons */ @@ -59,11 +60,54 @@ DIB_4BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c) BOOLEAN DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo) { - LONG i, j, sx, sy, f2, xColor; + LONG i, j, sx, sy, f2, xColor, flip, lTmp;; PBYTE SourceBits_24BPP, SourceLine_24BPP; PBYTE DestBits, DestLine, SourceBits_8BPP, SourceLine_8BPP; PBYTE SourceBits, SourceLine; + 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); + + /* Retrieve flip here and then make Well-Ordered again */ + /* Get back flip here */ + + if ((BltInfo->DestRect.left > BltInfo->DestRect.right) && (BltInfo->DestRect.top > BltInfo->DestRect.bottom)) + { + flip = 3; + } + else if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + flip = 1; + } + else if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + flip = 2; + } + else + { + flip = 0; + } + + /* Then we make top < bottom and left < right */ + if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + lTmp = BltInfo->DestRect.left; + BltInfo->DestRect.left = BltInfo->DestRect.right; + BltInfo->DestRect.right = lTmp; + } + + if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + lTmp = BltInfo->DestRect.top; + BltInfo->DestRect.top = BltInfo->DestRect.bottom; + BltInfo->DestRect.bottom = lTmp; + } + + DPRINT("flip/bpp is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n", + flip, BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y); + DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.left >> 1) + BltInfo->DestRect.top * BltInfo->DestSurface->lDelta; @@ -71,12 +115,30 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo) switch (BltInfo->SourceSurface->iBitmapFormat) { case BMF_1BPP: + DPRINT("1BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + sx = BltInfo->SourcePoint.x; + + /* This sets sy to the top line */ sy = BltInfo->SourcePoint.y; + if ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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,19 +149,49 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo) { DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1)); } - sx++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } break; case BMF_4BPP: + DPRINT("4BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* This sets sy to the top line */ sy = BltInfo->SourcePoint.y; + if ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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) @@ -110,41 +202,111 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo) { DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy)); } - sx++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } 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 ((flip == 2) || (flip == 3)) + { + /* This sets SourceBits to the bottom line */ + SourceBits = (PBYTE)((LONG)SourceBits + + ((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 ((flip == 1) || (flip == 3)) + { + /* 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; } + if ((flip == 2) || (flip ==3)) + { + SourceLine_8BPP--; + } + else + { + SourceLine_8BPP++; + } + } + if ((flip == 2) || (flip == 3)) + { + SourceBits_8BPP -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceBits_8BPP += BltInfo->SourceSurface->lDelta; } - - SourceBits_8BPP += BltInfo->SourceSurface->lDelta; DestBits += BltInfo->DestSurface->lDelta; } break; case BMF_16BPP: + DPRINT("16BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + 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 ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* This sets SourceBits to the rightmost pixel */ + SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 2; + } + DestBits = DestLine; f2 = BltInfo->DestRect.left & 1; @@ -154,23 +316,56 @@ 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; + + if ((flip == 1) || (flip ==3)) + { + SourceBits -= 2; + } + else + { + SourceBits += 2; + } } - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip ==3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += 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); + SourceBits_24BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x * 3; + if ((flip == 2) || (flip ==3)) + { + /* This sets SourceLine to the bottom line */ + SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1); + } + for (j=BltInfo->DestRect.top; jDestRect.bottom; j++) { SourceLine_24BPP = SourceBits_24BPP; DestLine = DestBits; f2 = BltInfo->DestRect.left & 1; + if ((flip == 1) || (flip == 3)) + { + /* 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 +374,52 @@ 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; + if ((flip == 1) || (flip ==3)) + { + SourceLine_24BPP-=3; + } + else + { + SourceLine_24BPP+=3; + } + } + if ((flip == 2) || (flip ==3)) + { + SourceBits_24BPP -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceBits_24BPP += BltInfo->SourceSurface->lDelta; } - - SourceBits_24BPP += BltInfo->SourceSurface->lDelta; DestBits += BltInfo->DestSurface->lDelta; } break; case BMF_32BPP: + DPRINT("32BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x; + + if ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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 +428,31 @@ 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; + + if ((flip == 1) || (flip ==3)) + { + SourceBits -= 4; + } + else + { + SourceBits += 4; + } } - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip ==3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += 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); @@ -359,7 +599,21 @@ DIB_4BPP_BitBlt(PBLTINFO BltInfo) BOOLEAN DIB_4BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color) { - LONG DestY; + LONG DestY, lTmp; + +/* Make WellOrdered by making top < bottom and left < right */ + if (DestRect->left > DestRect->right) + { + lTmp = DestRect->left; + DestRect->left = DestRect->right; + DestRect->right = lTmp; + } + if (DestRect->top > DestRect->bottom) + { + lTmp = DestRect->top; + DestRect->top = DestRect->bottom; + DestRect->bottom = lTmp; + } for (DestY = DestRect->top; DestY < DestRect->bottom; DestY++) { diff --git a/win32ss/gdi/dib/dib8bpp.c b/win32ss/gdi/dib/dib8bpp.c index c30d738b67..af58ea94a4 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 @@ -54,21 +55,82 @@ DIB_8BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c) BOOLEAN DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo) { - LONG i, j, sx, sy, xColor, f1; + LONG i, j, sx, sy, xColor, f1, flip, lTmp; PBYTE SourceBits, DestBits, SourceLine, DestLine; PBYTE SourceBits_4BPP, SourceLine_4BPP; + 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); + + /* Retrieve flip here and then make Well-Ordered again */ + /* Get back flip here */ + + if ((BltInfo->DestRect.left > BltInfo->DestRect.right) && (BltInfo->DestRect.top > BltInfo->DestRect.bottom)) + { + flip = 3; + } + else if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + flip = 1; + } + else if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + flip = 2; + } + else + { + flip = 0; + } + + /* Make WellOrdered by making top < bottom and left < right */ + if (BltInfo->DestRect.left > BltInfo->DestRect.right) + { + lTmp = BltInfo->DestRect.left; + BltInfo->DestRect.left = BltInfo->DestRect.right; + BltInfo->DestRect.right = lTmp; + } + + if (BltInfo->DestRect.top > BltInfo->DestRect.bottom) + { + lTmp = BltInfo->DestRect.top; + BltInfo->DestRect.top = BltInfo->DestRect.bottom; + BltInfo->DestRect.bottom = lTmp; + } + + DPRINT("flip/bpp is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n", + flip, 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' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + sx = BltInfo->SourcePoint.x; + + /* This sets sy to the top line */ sy = BltInfo->SourcePoint.y; + if ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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 +141,50 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo) { DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1)); } - sx++; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + sy--; + } + else + { + sy++; } - sy++; } break; case BMF_4BPP: + DPRINT("4BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + /* 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 ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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 +192,54 @@ 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) + { + if ((flip == 1) || (flip == 3)) + { + SourceLine_4BPP--; + } + else + { + SourceLine_4BPP++; + } + f1 = 0; + } + else + { + f1 = 1; + } - SourceBits_4BPP += BltInfo->SourceSurface->lDelta; + if ((flip == 1) || (flip == 3)) + { + sx--; + } + else + { + sx++; + } + } + if ((flip == 2) || (flip == 3)) + { + SourceBits_4BPP -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceBits_4BPP += 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 ((NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL)) && (flip == 0)) { 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 +250,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 +263,14 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo) } else { + DPRINT("XO_TRIVIAL is NOT TRUE or (flip != 0).\n"); + + if (flip == 0) + /* **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 +287,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 +303,259 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo) } } } + else + { + /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */ + BOOL OneDone = FALSE; + + if ((flip == 1) || (flip == 3)) + { + DPRINT("Flip == 1 or 3.\n"); + + /* Allocate enough pixels for a row in DWORD's */ + BYTE store[BltInfo->DestRect.right - BltInfo->DestRect.left + 1]; + 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; + } + OneDone = TRUE; + } + + if ((flip == 2) || (flip == 3)) + { + DPRINT("Flip == 2 or 3.\n"); + + DWORD Index; + + /* Allocate enough pixels for a column in DWORD's */ + BYTE store[BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1]; + + /* The OneDone flag indicates that we are doing a flip == 3 and have already */ + /* completed the flip == 1. 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->SourceSurface->lDelta) + BltInfo->SourcePoint.x + + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta; + } + + /* 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; + } + } + + } + } break; case BMF_16BPP: + DPRINT("16BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + + 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 ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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; + + if ((flip == 1) || (flip ==3)) + { + SourceBits -= 2; + } + else + { + SourceBits += 2; + } DestBits += 1; } - - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip ==3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += 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 ((flip == 2) || (flip ==3)) + { + /* 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 ((flip == 1) || (flip == 3)) + { + /* 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; + if ((flip == 1) || (flip == 3)) + { + SourceBits -= 3; + } + else + { + SourceBits += 3; + } DestBits += 1; } - - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip ==3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += BltInfo->SourceSurface->lDelta; + } DestLine += BltInfo->DestSurface->lDelta; } break; case BMF_32BPP: + + DPRINT("32BPP Case Selected with DestRect Width of '%d' and flip is '%d'.\n", + BltInfo->DestRect.right - BltInfo->DestRect.left, flip); + SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x; + + if ((flip == 2) || (flip ==3)) + { + /* 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 +563,35 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo) SourceBits = SourceLine; DestBits = DestLine; + if ((flip == 1) || (flip == 3)) + { + /* 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; + + if ((flip == 1) || (flip ==3)) + { + SourceBits -= 4; + } + else + { + SourceBits += 4; + } DestBits += 1; } - - SourceLine += BltInfo->SourceSurface->lDelta; + if ((flip == 2) || (flip ==3)) + { + SourceLine -= BltInfo->SourceSurface->lDelta; + } + else + { + SourceLine += BltInfo->SourceSurface->lDelta; + } DestLine += BltInfo->DestSurface->lDelta; } break; @@ -249,7 +608,22 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo) BOOLEAN DIB_8BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color) { - LONG DestY; + LONG DestY, lTmp; + + /* Make WellOrdered by making top < bottom and left < right */ + if (DestRect->left > DestRect->right) + { + lTmp = DestRect->left; + DestRect->left = DestRect->right; + DestRect->right = lTmp; + } + if (DestRect->top > DestRect->bottom) + { + lTmp = DestRect->top; + DestRect->top = DestRect->bottom; + DestRect->bottom = lTmp; + } + 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..675b0e307b 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,6 +48,9 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma BOOL UsesSource = ROP4_USES_SOURCE(ROP); BOOL UsesPattern = ROP4_USES_PATTERN(ROP); + LONG flip; + BOOL flipx, flipy; + RECTL OutputRect; ASSERT(IS_VALID_ROP4(ROP)); @@ -56,6 +60,56 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma DPRINT("Dest BPP: %u, dstRect: (%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 flip tests and set our conditions */ + if (((SrcWidth < 0) && (DstWidth < 0)) || ((SrcWidth >= 0) && (DstWidth >= 0))) + { + flipy = FALSE; + } + else + { + flipy = TRUE; + } + + if (((SrcHeight < 0) && (DstHeight < 0)) || ((SrcHeight >= 0) && (DstHeight >= 0))) + { + flipx = FALSE; + } + else + { + flipx = TRUE; + } + + DPRINT("flip about x-axis is '%d' and flip and y-axis is '%d'.\n", flipx, flipy); + + if (!flipx && !flipy) + { + flip = 0; + } + else if (!flipx && flipy) + { + flip = 1; + } + else if (flipx && !flipy) + { + flip = 2; + } + else + { + flip = 3; + } + + DPRINT("flip is '%d'.\n", flip); + + /* Make Well Ordered to start */ + OutputRect = *DestRect; + RECTL_vMakeWellOrdered(&OutputRect); + *DestRect = OutputRect; + if (UsesSource) { SourceCy = SourceSurf->sizlBitmap.cy; @@ -66,6 +120,7 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma if (MaskSurf) { + DPRINT("MaskSurf is not NULL.\n"); fnMask_GetPixel = DibFunctionsForBitmapFormat[MaskSurf->iBitmapFormat].DIB_GetPixel; MaskCy = MaskSurf->sizlBitmap.cy; } @@ -87,9 +142,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 +163,10 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma } } + if (PatternSurface) + { + DPRINT("PatternSurface is not NULL.\n"); + } for (DesY = DestRect->top; DesY < DestRect->bottom; DesY++) { @@ -118,7 +179,16 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma } } if (UsesSource) - sy = SourceRect->top+(DesY - DestRect->top) * SrcHeight / DstHeight; + { + if ((flip == 2) || (flip == 3)) + { + 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 +196,14 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma if (fnMask_GetPixel) { - sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth; + if ((flip == 1) || (flip == 3)) + { + 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 +214,14 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma if (UsesSource && CanDraw) { - sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth; + if ((flip == 1) || (flip == 3)) + { + 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..3266b197c2 100644 --- a/win32ss/gdi/eng/bitblt.c +++ b/win32ss/gdi/eng/bitblt.c @@ -3,8 +3,9 @@ * PROJECT: ReactOS Win32k subsystem * PURPOSE: GDI BitBlt Functions * FILE: win32ss/gdi/eng/bitblt.c - * PROGRAMER: Jason Filby + * PROGRAMERS: Jason Filby * Timo Kreuzer + * Doug Lyons */ #include @@ -222,6 +223,7 @@ CallDibBitBlt(SURFOBJ* OutputObj, BLTINFO BltInfo; SURFOBJ *psoPattern; BOOLEAN Result; + LONG lTmp; BltInfo.DestSurface = OutputObj; BltInfo.SourceSurface = InputObj; @@ -255,6 +257,23 @@ CallDibBitBlt(SURFOBJ* OutputObj, psoPattern = NULL; } + /* Make the top < bottom and left < right if needed */ + if (BltInfo.DestRect.left > BltInfo.DestRect.right) + { + lTmp = BltInfo.DestRect.left; + BltInfo.DestRect.left = BltInfo.DestRect.right; + BltInfo.DestRect.right = lTmp; + } + if (BltInfo.DestRect.top > BltInfo.DestRect.bottom) + { + lTmp = BltInfo.DestRect.top; + BltInfo.DestRect.top = BltInfo.DestRect.bottom; + BltInfo.DestRect.bottom = lTmp; + } + + DPRINT("CallDibBitBlt: dstRect: (%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 +363,30 @@ EngBitBlt( ULONG Direction; BOOL UsesSource, UsesMask; POINTL AdjustedBrushOrigin; + INT flip; + LONG lTmp; UsesSource = ROP4_USES_SOURCE(rop4); UsesMask = ROP4_USES_MASK(rop4); + /* Get back the incoming flip here */ + if ((prclTrg->left > prclTrg->right) && (prclTrg->top > prclTrg->bottom)) + { + flip = 3; + } + else if (prclTrg->left > prclTrg->right) + { + flip = 1; + } + else if (prclTrg->top > prclTrg-> bottom) + { + flip = 2; + } + else + { + flip = 0; + } + if (rop4 == ROP4_NOOP) { /* Copy destination onto itself: nop */ @@ -359,6 +398,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 +543,29 @@ EngBitBlt( switch (clippingType) { case DC_TRIVIAL: + /* Fix up OutputRect here */ + if (flip == 1) + { + lTmp = OutputRect.left; + OutputRect.left = OutputRect.right; + OutputRect.right = lTmp; + } + else if (flip == 2) + { + lTmp = OutputRect.top; + OutputRect.top = OutputRect.bottom; + OutputRect.bottom = lTmp; + } + else if (flip == 3) + { + lTmp = OutputRect.top; + OutputRect.top = OutputRect.bottom; + OutputRect.bottom = lTmp; + lTmp = OutputRect.left; + OutputRect.left = OutputRect.right; + OutputRect.right = lTmp; + } + Ret = (*BltRectFunc)(OutputObj, InputObj, psoMask, @@ -622,13 +690,36 @@ IntEngBitBlt( RECTL rclSrcClipped; POINTL ptlBrush; PFN_DrvBitBlt pfnBitBlt; + INT flip; + LONG lTmp; /* Sanity checks */ ASSERT(IS_VALID_ROP4(Rop4)); ASSERT(psoTrg); + DPRINT("IntEngBitBlt: prclTrg: (%d,%d)-(%d,%d)\n", + prclTrg->left, prclTrg->top, prclTrg->right, prclTrg->bottom); + psurfTrg = CONTAINING_RECORD(psoTrg, SURFACE, SurfObj); + /* Before making it well ordered we save the flip value */ + if ((prclTrg->left > prclTrg->right) && (prclTrg->top > prclTrg->bottom)) + { + flip = 3; + } + else if (prclTrg->top > prclTrg-> bottom) + { + flip = 2; + } + else if (prclTrg->left > prclTrg->right) + { + flip = 1; + } + else + { + flip = 0; + } + /* Get the target rect and make it well ordered */ rclClipped = *prclTrg; RECTL_vMakeWellOrdered(&rclClipped); @@ -721,6 +812,29 @@ IntEngBitBlt( pfnBitBlt = EngBitBlt; } + /* rclClipped needs to be modified in accordance with flip here */ + if (flip == 1) + { + lTmp = rclClipped.left; + rclClipped.left = rclClipped.right; + rclClipped.right = lTmp; + } + else if (flip == 2) + { + lTmp = rclClipped.top; + rclClipped.top = rclClipped.bottom; + rclClipped.bottom = lTmp; + } + else if (flip == 3) + { + lTmp = rclClipped.top; + rclClipped.top = rclClipped.bottom; + rclClipped.bottom = lTmp; + lTmp = rclClipped.left; + rclClipped.left = rclClipped.right; + rclClipped.right = lTmp; + } + bResult = pfnBitBlt(psoTrg, psoSrc, psoMask, diff --git a/win32ss/gdi/eng/copybits.c b/win32ss/gdi/eng/copybits.c index 0b8824392d..991618862c 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,28 @@ EngCopyBits( SURFACE *psurfSource; RECTL rclDest = *DestRect; POINTL ptlSrc = *SourcePoint; + LONG lTmp; + BOOL flip; + + 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("Source cx/cy is %d/%d and Dest 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) + { + flip = TRUE; + lTmp = DestRect->top; + DestRect->top = DestRect->bottom; + DestRect->bottom = lTmp; + rclDest = *DestRect; + } + else + flip = FALSE; + DPRINT("flip is '%d'.\n", flip); ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL); @@ -116,6 +139,14 @@ EngCopyBits( BltInfo.DestRect = *DestRect; BltInfo.SourcePoint = *SourcePoint; + /* Now we set the Dest Rect top and bottom based on Top Down/flip */ + if (flip) + { + lTmp = BltInfo.DestRect.top; + BltInfo.DestRect.top = BltInfo.DestRect.bottom; + BltInfo.DestRect.bottom = lTmp; + } + ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo); break; diff --git a/win32ss/gdi/eng/stretchblt.c b/win32ss/gdi/eng/stretchblt.c index 2fb1a9afd2..6c50d3a9fa 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 @@ -38,6 +39,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 +121,58 @@ EngStretchBltROP( LONG SrcHeight; LONG SrcWidth; + LONG cxSrc, cySrc, cxDest, cyDest, flip; + BOOL flipx, flipy; + LONG lTmp; + + DPRINT("Entering EngStretchBltROP: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n", + psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy, //SourceRect->right, SourceRect->bottom, + psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy, + 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))) + flipy = FALSE; + else + flipy = TRUE; + + if (((cySrc < 0) && (cyDest < 0)) || ((cySrc >= 0) && (cyDest >= 0))) + flipx = FALSE; + else + flipx = TRUE; + + DPRINT("flip about x-axis is '%d' and flip and y-axis is '%d'.\n", flipx, flipy); + + if (!flipx && !flipy) + { + flip = 0; + } + else if (!flipx && flipy) + { + flip = 1; + } + else if (flipx && !flipy) + { + flip = 2; + } + else + { + flip = 3; + } + + DPRINT("flip is '%d'.\n", flip); + + + /* Make Well Ordered to start */ + OutputRect = *prclDest; + RECTL_vMakeWellOrdered(&OutputRect); + *prclDest = OutputRect; + if (Rop4 == ROP4_NOOP) { /* Copy destination onto itself: nop */ @@ -240,6 +298,31 @@ EngStretchBltROP( switch (clippingType) { case DC_TRIVIAL: + if (flip == 1) + { + lTmp = OutputRect.left; + OutputRect.left = OutputRect.right; + OutputRect.right = lTmp; + } + else if (flip == 2) + { + lTmp = OutputRect.top; + OutputRect.top = OutputRect.bottom; + OutputRect.bottom = lTmp; + } + else if (flip == 3) + { + lTmp = OutputRect.top; + OutputRect.top = OutputRect.bottom; + OutputRect.bottom = lTmp; + lTmp = OutputRect.left; + OutputRect.left = OutputRect.right; + OutputRect.right = 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 +339,32 @@ 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 (flip == 1) + { + lTmp = CombinedRect.left; + CombinedRect.left = CombinedRect.right; + CombinedRect.right = lTmp; + } + else if (flip == 2) + { + lTmp = CombinedRect.top; + CombinedRect.top = CombinedRect.bottom; + CombinedRect.bottom = lTmp; + } + else if (flip == 3) + { + lTmp = CombinedRect.top; + CombinedRect.top = CombinedRect.bottom; + CombinedRect.bottom = lTmp; + lTmp = CombinedRect.left; + CombinedRect.left = CombinedRect.right; + CombinedRect.right = 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 +410,32 @@ 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 (flip == 1) + { + lTmp = CombinedRect.left; + CombinedRect.left = CombinedRect.right; + CombinedRect.right = lTmp; + } + else if (flip == 2) + { + lTmp = CombinedRect.top; + CombinedRect.top = CombinedRect.bottom; + CombinedRect.bottom = lTmp; + } + else if (flip == 3) + { + lTmp = CombinedRect.top; + CombinedRect.top = CombinedRect.bottom; + CombinedRect.bottom = lTmp; + lTmp = CombinedRect.left; + CombinedRect.left = CombinedRect.right; + CombinedRect.right = 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 +517,8 @@ IntEngStretchBlt(SURFOBJ *psoDest, RECTL OutputRect; BOOL UsesSource = ROP4_USES_SOURCE(Rop4); LONG InputClWidth, InputClHeight, InputWidth, InputHeight; + LONG lTmp, cxSrc, cySrc, cxDest, cyDest, flip; + BOOL flipx, flipy; // flipx is flip about the x-axis and flipy is flip about the y-axis ASSERT(psoDest); //ASSERT(psoSource); // FIXME! @@ -397,10 +534,169 @@ IntEngStretchBlt(SURFOBJ *psoDest, /* 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; + + DPRINT("xDest(%d) yDest(%d) cxDest(%d) cyDest(%d) xSrc(%d) ySrc(%d) cxSrc(%d) cySrc(%d)\n", + DestRect->left, DestRect->top, cxDest, cyDest, + SourceRect->left, SourceRect->top, cxSrc, cySrc); + + /* Check if source and dest size are equal */ + if ((abs(cxDest) == abs(cxSrc)) && (abs(cyDest) == abs(cySrc))) + { + /* if cxSrc < 0 and cxDest <0 (both negative, we change both their signs */ + /* because the outcome is the same as if they were both positive and we */ + /* reverse both their top and bottom values */ + if ((cxSrc < 0) && (cxDest < 0)) + { + lTmp = DestRect->left; + DestRect->left = DestRect->right; + DestRect->right = lTmp; + lTmp = SourceRect->left; + SourceRect->left = SourceRect->right; + SourceRect->right = lTmp; + cxSrc = abs(cxSrc); + cxDest = abs(cxDest); + } + + /* if cySrc < 0 and cyDest <0 (both negative, we change both their signs */ + /* because the outcome is the same as if they were both positive and we */ + /* reverse both their top and bottom values */ + if ((cySrc < 0) && (cyDest < 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 the cxDest >= 0 and cxSrc < 0 then we reverse */ + /* the signs of both cxDest and cxSrc */ + if ((cxDest >= 0) && (cxSrc < 0)) + { + cxDest = -cxDest; + cxSrc = -cxSrc; + } + + /* if the cxDest < 0 and cxSrc >= 0 then we reverse */ + /* the left and right values */ + else if ((cxDest < 0) && (cxSrc >= 0)) + { + lTmp = SourceRect->left; + SourceRect->left = SourceRect->right; + SourceRect->right = lTmp; + } + + /* if the cyDest >= 0 and cySrc < 0 then we reverse */ + /* the signs of both cxDest and cxSrc */ + if ((cyDest >= 0) && (cySrc < 0)) + { + cyDest = -cyDest; + cySrc = -cySrc; + } + + /* if the cyDest < 0 and cySrc >= 0 then we reverse */ + /* the top and bottom values */ + else if ((cyDest <= 0) && (cySrc > 0)) + { + lTmp = SourceRect->top; + SourceRect->top = SourceRect->bottom; + SourceRect->bottom = lTmp; + } + } + + /***************************************************************************************************************************** + We want to send the flip state to IntEngBitBlt without changing its parameter list. + 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 the cx = 0 then there can be no x-flip and if cy = 0 there can be no y-flip. We have no concerns about these conditions. + So we can set the four flip conditions as follows: + + flip = 0 means no flips therefore left < right and top < bottom (normal well-formed rect) + flip = 1 means that we are flipped about the y-axis therefore left < right and top > bottom + flip = 2 means that we are flipped about the x-axis therefore left > right and top < bottom + flip = 3 means that we are flipped about both axes therefore left > right and top > bottom + *****************************************************************************************************************************/ + + /* Make Well Ordered to start */ + OutputRect = *DestRect; + RECTL_vMakeWellOrdered(&OutputRect); + *DestRect = OutputRect; + + /* Here we do the tests and set our flip based on input conditions */ + if (((cxSrc < 0) && (cxDest < 0)) || ((cxSrc >= 0) && (cxDest >= 0))) + { + flipy = FALSE; + } + else + { + flipy = TRUE; + } + + if (((cySrc < 0) && (cyDest < 0)) || ((cySrc >= 0) && (cyDest >= 0))) + { + flipx = FALSE; + } + else + { + flipx = TRUE; + } + + DPRINT("flip about x-axis is '%d' and flip and y-axis is '%d'.\n", flipx, flipy); + + if (!flipx && !flipy) + { + flip = 0; + } + else if (!flipx && flipy) + { + flip = 1; + } + else if (flipx && !flipy) + { + flip = 2; + } + else + { + flip = 3; + } + + DPRINT("flip is '%d'.\n", flip); + /* 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"); + + if (flip == 1) + { + lTmp = DestRect->left; + DestRect->left = DestRect->right; + DestRect->right = lTmp; + } + else if (flip == 2) + { + lTmp = DestRect->top; + DestRect->top = DestRect->bottom; + DestRect->bottom = lTmp; + } + else if (flip == 3) + { + lTmp = DestRect->top; + DestRect->top = DestRect->bottom; + DestRect->bottom = lTmp; + lTmp = DestRect->left; + DestRect->left = DestRect->right; + DestRect->right = lTmp; + } + /* Pass the request to IntEngBitBlt */ return IntEngBitBlt(psoDest, psoSource, @@ -414,6 +710,36 @@ IntEngStretchBlt(SURFOBJ *psoDest, BrushOrigin, Rop4); } + else + DPRINT("source and dest size are NOT equal.\n"); + + /* 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; + } InputClippedRect = *DestRect; if (InputClippedRect.right < InputClippedRect.left) @@ -498,6 +824,34 @@ IntEngStretchBlt(SURFOBJ *psoDest, if (! ret) { + /* set OutputRect to follow flip */ + if (flip == 1) + { + lTmp = OutputRect.left; + OutputRect.left = OutputRect.right; + OutputRect.right = lTmp; + } + else if (flip == 2) + { + lTmp = OutputRect.top; + OutputRect.top = OutputRect.bottom; + OutputRect.bottom = lTmp; + } + else if (flip == 3) + { + lTmp = OutputRect.top; + OutputRect.top = OutputRect.bottom; + OutputRect.bottom = lTmp; + lTmp = OutputRect.left; + OutputRect.left = OutputRect.right; + OutputRect.right = lTmp; + } + + DPRINT("About to call EngStretchBltROP: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n", + psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy, //SourceRect->right, SourceRect->bottom, + psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy, + OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom); + ret = EngStretchBltROP(psoDest, psoSource, MaskSurf, diff --git a/win32ss/gdi/ntgdi/dibobj.c b/win32ss/gdi/ntgdi/dibobj.c index 93208665b3..418190f290 100644 --- a/win32ss/gdi/ntgdi/dibobj.c +++ b/win32ss/gdi/ntgdi/dibobj.c @@ -320,6 +320,14 @@ IntSetDIBits( ptSrc.x = 0; ptSrc.y = 0; + /* Here we adjust for Top Down to flip bmp for Lazarus */ + if (psurfSrc->SurfObj.fjBitmap & BMF_TOPDOWN) // Source surface TopDown bit + { + LONG lTmp = rcDst.top; + rcDst.top = rcDst.bottom; + rcDst.bottom = lTmp; + } + result = IntEngCopyBits(&psurfDst->SurfObj, &psurfSrc->SurfObj, NULL, @@ -690,7 +698,7 @@ GreGetDIBitsInternal( RGBQUAD* rgbQuads; VOID* colorPtr; - DPRINT("Entered GreGetDIBitsInternal()\n"); + DPRINT("Entered GreGetDIBitsInternal() and height is '%d'.\n", Info->bmiHeader.biHeight); if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap) return 0; @@ -1007,6 +1015,16 @@ GreGetDIBitsInternal( EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0); + /* Here we adjust for Top Down to flip bmp for PeaZip */ + /* This fixes Double Commander menubar icons, but not */ + /* its Configure - Options icons. */ + if (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) // Source surface TopDown bit + { + LONG lTmp = rcDest.top; + rcDest.top = rcDest.bottom; + rcDest.bottom = lTmp; + } + ret = IntEngCopyBits(&psurfDest->SurfObj, &psurf->SurfObj, NULL, @@ -1190,6 +1208,9 @@ NtGdiStretchDIBitsInternal( EXLATEOBJ exlo; PVOID pvBits; +DPRINT("NtGdiStretchDIBitsInternal Src(%d,%d) Dst(%d,%d) cxSrc/cySrc(%d/%d) cxDst/cyDst(%d/%d).\n", + xSrc, ySrc, xDst, yDst, cxSrc, cySrc, cxDst, cyDst); + if (!(pdc = DC_LockDc(hdc))) { EngSetLastError(ERROR_INVALID_HANDLE);