gdi32: Fixed initialization of bit masks in GetDIBits for 16-bit bitmaps.
authorAlexandre Julliard <julliard@winehq.org>
Fri, 18 Apr 2008 10:08:12 +0000 (12:08 +0200)
committerAlexandre Julliard <julliard@winehq.org>
Fri, 18 Apr 2008 11:57:15 +0000 (13:57 +0200)
Fix and improve the test cases.

dlls/gdi32/dib.c
dlls/gdi32/tests/bitmap.c

index 2b5ae374d44f4d068c441fa06dbc4927156c438b..caf3e6ca9abb91bb752396bbd949458dc492d442 100644 (file)
@@ -620,8 +620,55 @@ INT WINAPI GetDIBits(
 
     /* Transfer color info */
 
-    if (bpp <= 8 && bpp > 0)
+    switch (bpp)
     {
+    case 0:  /* query bitmap info only */
+        if (core_header)
+        {
+            BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
+            coreheader->bcWidth = bmp->bitmap.bmWidth;
+            coreheader->bcHeight = bmp->bitmap.bmHeight;
+            coreheader->bcPlanes = 1;
+            coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
+        }
+        else
+        {
+            info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
+            info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
+            info->bmiHeader.biPlanes = 1;
+            info->bmiHeader.biSizeImage =
+                DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
+                                      bmp->bitmap.bmHeight,
+                                      bmp->bitmap.bmBitsPixel );
+            switch(bmp->bitmap.bmBitsPixel)
+            {
+            case 15:
+                info->bmiHeader.biBitCount = 16;
+                info->bmiHeader.biCompression = BI_RGB;
+                break;
+            case 16:
+                info->bmiHeader.biBitCount = 16;
+                info->bmiHeader.biCompression = BI_BITFIELDS;
+                break;
+            default:
+                info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
+                info->bmiHeader.biCompression = BI_RGB;
+                break;
+            }
+            info->bmiHeader.biXPelsPerMeter = 0;
+            info->bmiHeader.biYPelsPerMeter = 0;
+            info->bmiHeader.biClrUsed = 0;
+            info->bmiHeader.biClrImportant = 0;
+
+            /* Windows 2000 doesn't touch the additional struct members if
+               it's a BITMAPV4HEADER or a BITMAPV5HEADER */
+        }
+        lines = abs(bmp->bitmap.bmHeight);
+        goto done;
+
+    case 1:
+    case 4:
+    case 8:
         if (!core_header) info->bmiHeader.biClrUsed = 0;
 
        /* If the bitmap object already has a dib section at the
@@ -758,6 +805,25 @@ INT WINAPI GetDIBits(
                 }
             }
         }
+        break;
+
+    case 15:
+        if (info->bmiHeader.biCompression == BI_BITFIELDS)
+        {
+            ((PDWORD)info->bmiColors)[0] = 0x7c00;
+            ((PDWORD)info->bmiColors)[1] = 0x03e0;
+            ((PDWORD)info->bmiColors)[2] = 0x001f;
+        }
+        break;
+
+    case 16:
+        if (info->bmiHeader.biCompression == BI_BITFIELDS)
+        {
+            ((PDWORD)info->bmiColors)[0] = 0xf800;
+            ((PDWORD)info->bmiColors)[1] = 0x07e0;
+            ((PDWORD)info->bmiColors)[2] = 0x001f;
+        }
+        break;
     }
 
     if (bits && lines)
@@ -981,84 +1047,21 @@ INT WINAPI GetDIBits(
             }
         }
     }
-    else
-    {
-       /* fill in struct members */
-
-        if (bpp == 0)
-        {
-            if (core_header)
-            {
-                BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
-                coreheader->bcWidth = bmp->bitmap.bmWidth;
-                coreheader->bcHeight = bmp->bitmap.bmHeight;
-                coreheader->bcPlanes = 1;
-                coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
-            }
-            else
-            {
-                info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
-                info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
-                info->bmiHeader.biPlanes = 1;
-                info->bmiHeader.biSizeImage =
-                                 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
-                                                       bmp->bitmap.bmHeight,
-                                                       bmp->bitmap.bmBitsPixel );
-                switch(bmp->bitmap.bmBitsPixel)
-                {
-                case 15:
-                    info->bmiHeader.biBitCount = 16;
-                    info->bmiHeader.biCompression = BI_RGB;
-                    break;
-                    
-                case 16:
-                    if (bits)
-                    {
-                        /* Add color only when bits is given, as per MSDN */
-                        ((PDWORD)info->bmiColors)[0] = 0xf800;
-                        ((PDWORD)info->bmiColors)[1] = 0x07e0;
-                        ((PDWORD)info->bmiColors)[2] = 0x001f;
-                    }
-                    info->bmiHeader.biBitCount = 16;
-                    info->bmiHeader.biCompression = BI_BITFIELDS;
-                    break;
-    
-                default:
-                    info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
-                    info->bmiHeader.biCompression = BI_RGB;
-                    break;
-                }
-                info->bmiHeader.biXPelsPerMeter = 0;
-                info->bmiHeader.biYPelsPerMeter = 0;
-                info->bmiHeader.biClrUsed = 0;
-                info->bmiHeader.biClrImportant = 0;
-                
-                /* Windows 2000 doesn't touch the additional struct members if
-                   it's a BITMAPV4HEADER or a BITMAPV5HEADER */
-            }
-            lines = abs(bmp->bitmap.bmHeight);
-        }
-        else
-        {
-            /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
-               if bits == NULL and bpp != 0, only biSizeImage and the color table are
-               filled in. */
-            if (!core_header)
-            {
-                /* FIXME: biSizeImage should be calculated according to the selected
-                          compression algorithm if biCompression != BI_RGB */
-                info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
-            }
-            lines = abs(height);
-        }
-    }
+    else lines = abs(height);
 
+    /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
+       if bits == NULL and bpp != 0, only biSizeImage and the color table are
+       filled in. */
     if (!core_header)
     {
+        /* FIXME: biSizeImage should be calculated according to the selected
+           compression algorithm if biCompression != BI_RGB */
+        info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
         TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
     }
     TRACE("biWidth = %d, biHeight = %d\n", width, height);
 
+done:
     release_dc_ptr( dc );
     GDI_ReleaseObj( hbitmap );
     return lines;
index 67bb27fc82e99edd5db017d83dc3e114b4bcc05f..15a463b01759e63b23cae185bc2dbd65a1dc8ffb 100644 (file)
@@ -1606,6 +1606,7 @@ static void test_GetDIBits_BI_BITFIELDS(void)
      * for the three primary colors in non-paletted 16 bit mode.
      */
     char dibinfo_buf[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
+    DWORD bits[32];
     LPBITMAPINFO dibinfo = (LPBITMAPINFO) dibinfo_buf;
     HDC hdc;
     HBITMAP hbm;
@@ -1622,30 +1623,61 @@ static void test_GetDIBits_BI_BITFIELDS(void)
     /* Call GetDIBits to fill in bmiHeader.  */
     ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
     ok(ret == 1, "GetDIBits failed\n");
-    if (dibinfo->bmiHeader.biBitCount == 16
-    &&  dibinfo->bmiHeader.biCompression == BI_BITFIELDS) {
-         /* In the BITMAPINFOHEADER doc, this little struct is implicit.
-          * Making explicit for clarity.
-          */
-         struct bi_bitfields_s {
-             DWORD red;
-             DWORD blue;
-             DWORD green;
-         } *bitmasks;
-
-         /* Retrieve the BI_BITFIELDS info (requires second call, honest). */
-         ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
-         ok(ret == 1, "GetDIBits failed\n");
-
-         bitmasks = (struct bi_bitfields_s *) dibinfo->bmiColors;
-         todo_wine {
-             ok(bitmasks->red != 0, "expected space for red pixels\n");
-             ok(bitmasks->blue != 0, "expected space for blue pixels\n");
-             ok(bitmasks->green != 0, "expected space for green pixels\n");
-         }
-    } else {
-         skip("not in 16 bpp BI_BITFIELDS mode, skipping that test\n");
+    if (dibinfo->bmiHeader.biBitCount == 16 &&
+        dibinfo->bmiHeader.biCompression == BI_BITFIELDS)
+    {
+        DWORD *bitmasks = (DWORD *)dibinfo->bmiColors;
+
+        ok( !bitmasks[0], "red mask is set\n" );
+        ok( !bitmasks[1], "green mask is set\n" );
+        ok( !bitmasks[2], "blue mask is set\n" );
+
+        /* test with NULL bits pointer and correct bpp */
+        dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
+        ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
+        ok(ret == 1, "GetDIBits failed\n");
+
+        ok( bitmasks[0] != 0, "red mask is not set\n" );
+        ok( bitmasks[1] != 0, "green mask is not set\n" );
+        ok( bitmasks[2] != 0, "blue mask is not set\n" );
+        ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
+
+        /* test with valid bits pointer */
+        memset(dibinfo, 0, sizeof(dibinfo_buf));
+        dibinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+        ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
+        ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
+        dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
+        ret = GetDIBits(hdc, hbm, 0, 1, bits, dibinfo, DIB_RGB_COLORS);
+        ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
+
+        ok( bitmasks[0] != 0, "red mask is not set\n" );
+        ok( bitmasks[1] != 0, "green mask is not set\n" );
+        ok( bitmasks[2] != 0, "blue mask is not set\n" );
+        ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
+
+        /* now with bits and 0 lines */
+        memset(dibinfo, 0, sizeof(dibinfo_buf));
+        dibinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+        dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
+        ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS);
+
+        ok( !bitmasks[0], "red mask is set\n" );
+        ok( !bitmasks[1], "green mask is set\n" );
+        ok( !bitmasks[2], "blue mask is set\n" );
+        ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
+
+        memset(bitmasks, 0, 3*sizeof(DWORD));
+        dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
+        ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS);
+        ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
+
+        ok( bitmasks[0] != 0, "red mask is not set\n" );
+        ok( bitmasks[1] != 0, "green mask is not set\n" );
+        ok( bitmasks[2] != 0, "blue mask is not set\n" );
+        ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
     }
+    else skip("not in 16 bpp BI_BITFIELDS mode, skipping that test\n");
 
     DeleteObject(hbm);
     ReleaseDC(NULL, hdc);