[PATCH 2/2] gdi32: Fixed GetDIBits for top-down bitmaps.

John Edmonds pocketcookies2 at gmail.com
Sun Feb 20 21:31:26 CST 2011


Reversed source width (in bytes) so that when copying from the source bitmap, the bottom scanline would be copied first (previously, the top scanline would be copied first which would cause a problem for getting single pixels).
Removed the check for a top-down destination bitmap.
Updated copies between bitmaps with the same bits per pixel to cope with a negative source width (in bytes).
Removed todo_wine from the tests for this fix.
This addresses Bug #24278.
---
 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 5067e49..6ceb95c 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 4b54302..1a743c7 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);
-- 
1.7.1





More information about the wine-patches mailing list