From 3c239fa0cd00a80cdccde9f7a19e9bbf862bac4f Mon Sep 17 00:00:00 2001 From: John Edmonds Date: Sun, 20 Feb 2011 22:31:26 -0500 Subject: [PATCH] gdi32: Fixed GetDIBits for top-down bitmaps. --- dlls/gdi32/dib.c | 23 ++++++++++++++--------- dlls/gdi32/tests/bitmap.c | 10 +++++----- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index 5067e494371..0619304dca8 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -871,18 +871,23 @@ INT WINAPI GetDIBits( if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15) { /*FIXME: Only RGB dibs supported for now */ - unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes; + unsigned int srcwidth = bmp->dib->dsBm.bmWidth; + int srcwidthb = bmp->dib->dsBm.bmWidthBytes; unsigned int dstwidth = width; - int dstwidthb = DIB_GetDIBWidthBytes( width, bpp ); + unsigned int dstwidthb = DIB_GetDIBWidthBytes( width, bpp ); LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb); unsigned int x, y, width, widthb; - if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0)) + /* + * If copying from a top-down source bitmap, move the source + * pointer to the end of the source bitmap and negate the width + * so that we copy the bits upside-down. + */ + if (bmp->dib->dsBmih.biHeight < 0) { - dbits = (LPBYTE)bits + (dstwidthb * (lines-1)); - dstwidthb = -dstwidthb; + sbits += (srcwidthb * (abs(bmp->dib->dsBmih.biHeight) - 2 * startscan - 1)); + srcwidthb = -srcwidthb; } - switch( bpp ) { case 15: @@ -897,7 +902,7 @@ INT WINAPI GetDIBits( case 16: /* 16 bpp srcDIB -> 16 bpp dstDIB */ { - widthb = min(srcwidthb, abs(dstwidthb)); + widthb = min(abs(srcwidthb), dstwidthb); /* FIXME: BI_BITFIELDS not supported yet */ for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) memcpy(dbits, sbits, widthb); @@ -975,7 +980,7 @@ INT WINAPI GetDIBits( case 24: /* 24 bpp srcDIB -> 24 bpp dstDIB */ { - widthb = min(srcwidthb, abs(dstwidthb)); + widthb = min(abs(srcwidthb), dstwidthb); for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) memcpy(dbits, sbits, widthb); } @@ -1051,7 +1056,7 @@ INT WINAPI GetDIBits( case 32: /* 32 bpp srcDIB -> 32 bpp dstDIB */ { - widthb = min(srcwidthb, abs(dstwidthb)); + widthb = min(abs(srcwidthb), dstwidthb); /* FIXME: BI_BITFIELDS not supported yet */ for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb) { memcpy(dbits, sbits, widthb); diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c index 4b543026823..1a743c72745 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -3116,27 +3116,27 @@ static void test_GetDIBits_single_pixel_destination(int bpp) ok((char)pixelOut == 0, "Bottom-up -> bottom-up: first pixel should be 0 but was %d.\n", (char)pixelOut); statusCode = GetDIBits(hdc, bmptb, 0, 1, &pixelOut, &bi, DIB_RGB_COLORS); ok(statusCode, "Failed to call GetDIBits. Status code: %d.\n", statusCode); - todo_wine ok((char)pixelOut == 2, "Top-down -> bottom-up: first pixel should be 2 but was %d.\n", (char)pixelOut); + ok((char)pixelOut == 2, "Top-down -> bottom-up: first pixel should be 2 but was %d.\n", (char)pixelOut); /*Check second scanline.*/ statusCode = GetDIBits(hdc, bmptb, 1, 1, &pixelOut, &bi, DIB_RGB_COLORS); ok(statusCode, "Failed to call GetDIBits. Status code: %d.\n", statusCode); - todo_wine ok((char)pixelOut == 0, "Top-down -> bottom-up: first pixel should be 0 but was %d.\n", (char)pixelOut); + ok((char)pixelOut == 0, "Top-down -> bottom-up: first pixel should be 0 but was %d.\n", (char)pixelOut); statusCode = GetDIBits(hdc, bmpbt, 1, 1, &pixelOut, &bi, DIB_RGB_COLORS); ok(statusCode, "Failed to call GetDIBits. Status code: %d.\n", statusCode); ok((char)pixelOut == 2, "Top-down -> bottom-up: first pixel should be 2 but was %d.\n", (char)pixelOut); - /*Make destination bitmap top-down. Windows (and soon, Wine) will ignore this.*/ + /*Make destination bitmap top-down. This should be ignored by GetDIBits.*/ bi.bmiHeader.biHeight = -2; statusCode = GetDIBits(hdc, bmpbt, 0, 1, &pixelOut, &bi, DIB_RGB_COLORS); ok(statusCode, "Failed to call GetDIBits. Status code: %d.\n", statusCode); ok((char)pixelOut == 0, "Bottom-up -> top-down: first pixel should be 0 but was %d.\n", (char)pixelOut); statusCode = GetDIBits(hdc, bmptb, 0, 1, &pixelOut, &bi, DIB_RGB_COLORS); ok(statusCode, "Failed to call GetDIBits. Status code: %d.\n", statusCode); - todo_wine ok((char)pixelOut == 2, "Top-down -> top-down: first pixel should be 2 but was %d.\n", (char)pixelOut); + ok((char)pixelOut == 2, "Top-down -> top-down: first pixel should be 2 but was %d.\n", (char)pixelOut); /*Check second scanline.*/ statusCode = GetDIBits(hdc, bmptb, 1, 1, &pixelOut, &bi, DIB_RGB_COLORS); ok(statusCode, "Failed to call GetDIBits. Status code: %d.\n", statusCode); - todo_wine ok((char)pixelOut == 0, "Top-down -> bottom-up: first pixel should be 0 but was %d.\n", (char)pixelOut); + ok((char)pixelOut == 0, "Top-down -> bottom-up: first pixel should be 0 but was %d.\n", (char)pixelOut); statusCode = GetDIBits(hdc, bmpbt, 1, 1, &pixelOut, &bi, DIB_RGB_COLORS); ok(statusCode, "Failed to call GetDIBits. Status code: %d.\n", statusCode); ok((char)pixelOut == 2, "Top-down -> bottom-up: first pixel should be 2 but was %d.\n", (char)pixelOut);