[PATCH] user32: Do not use SetDIBits() in create_masked_bitmap().

Zebediah Figura zfigura at codeweavers.com
Wed Dec 15 16:49:16 CST 2021


The given bitmap is in DDB format, not DIB format.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51296
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/user32/cursoricon.c       | 31 ++++++++++++----------
 dlls/user32/tests/cursoricon.c | 47 ++++++++++++++++++++++------------
 2 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c
index 827db302a30..828c88de92f 100644
--- a/dlls/user32/cursoricon.c
+++ b/dlls/user32/cursoricon.c
@@ -1753,22 +1753,25 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
 
 static HBITMAP create_masked_bitmap( int width, int height, const void *and, const void *xor )
 {
-    HDC dc = CreateCompatibleDC( 0 );
-    HBITMAP bitmap;
-
-    const BITMAPINFO bitmap_info =
-    {
-        .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
-        .bmiHeader.biWidth = width,
-        .bmiHeader.biHeight = height * 2,
-        .bmiHeader.biPlanes = 1,
-        .bmiHeader.biBitCount = 1,
-    };
+    HBITMAP and_bitmap, xor_bitmap, bitmap;
+    HDC src_dc, dst_dc;
 
+    and_bitmap = CreateBitmap( width, height, 1, 1, and );
+    xor_bitmap = CreateBitmap( width, height, 1, 1, xor );
     bitmap = CreateBitmap( width, height * 2, 1, 1, NULL );
-    SetDIBits( dc, bitmap, 0, height, and, &bitmap_info, FALSE );
-    SetDIBits( dc, bitmap, height, height, xor, &bitmap_info, FALSE );
-    DeleteDC( dc );
+    src_dc = CreateCompatibleDC( 0 );
+    dst_dc = CreateCompatibleDC( 0 );
+
+    SelectObject( dst_dc, bitmap );
+    SelectObject( src_dc, and_bitmap );
+    BitBlt( dst_dc, 0, 0, width, height, src_dc, 0, 0, SRCCOPY );
+    SelectObject( src_dc, xor_bitmap );
+    BitBlt( dst_dc, 0, height, width, height, src_dc, 0, 0, SRCCOPY );
+
+    DeleteObject( and_bitmap );
+    DeleteObject( xor_bitmap );
+    DeleteDC( src_dc );
+    DeleteDC( dst_dc );
     return bitmap;
 }
 
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c
index 1bbe2591d59..3e8d7c1707f 100644
--- a/dlls/user32/tests/cursoricon.c
+++ b/dlls/user32/tests/cursoricon.c
@@ -769,8 +769,9 @@ static void test_initial_cursor(void)
 }
 
 static void test_icon_info_(HICON hIcon, UINT exp_cx, UINT exp_cy,
-        UINT exp_mask_cy, UINT exp_bpp, UINT has_color, int line)
+        UINT exp_mask_cy, UINT exp_bpp, const BYTE *mask_bits, UINT has_color, int line)
 {
+    BYTE ret_bits[1024];
     ICONINFO info;
     DWORD ret;
     BITMAP bmMask, bmColor;
@@ -783,6 +784,15 @@ static void test_icon_info_(HICON hIcon, UINT exp_cx, UINT exp_cy,
     ok_(__FILE__, line)(info.yHotspot == exp_cy/2, "info.yHotspot = %u\n", info.yHotspot);
     ok_(__FILE__, line)(info.hbmMask != 0, "info.hbmMask is NULL\n");
 
+    if (mask_bits)
+    {
+        unsigned int exp_stride = (exp_cx + 7) / 8;
+        exp_stride = (exp_stride + 1) & ~1;
+        ret = GetBitmapBits(info.hbmMask, sizeof(ret_bits), ret_bits);
+        ok_(__FILE__, line)(ret == exp_stride * exp_mask_cy, "GetBitmapBits returned %u\n", ret);
+        ok_(__FILE__, line)(!memcmp(ret_bits, mask_bits, ret), "mask bitmap didn't match\n");
+    }
+
     ret = GetObjectA(info.hbmMask, sizeof(bmMask), &bmMask);
     ok_(__FILE__, line)(ret == sizeof(bmMask), "GetObject(info.hbmMask) failed, ret %u\n", ret);
 
@@ -849,11 +859,11 @@ static void test_icon_info_(HICON hIcon, UINT exp_cx, UINT exp_cy,
     }
 }
 
-#define test_icon_info(a,b,c,d,e,f) test_icon_info_(a,b,c,d,e,f,__LINE__)
+#define test_icon_info(a,b,c,d,e,f,g) test_icon_info_(a,b,c,d,e,f,g,__LINE__)
 
 static void test_CreateIcon(void)
 {
-    static const BYTE bmp_bits[1024];
+    BYTE bmp_bits[1024];
     HICON hIcon;
     HBITMAP hbmMask, hbmColor;
     BITMAPINFO *bmpinfo;
@@ -863,6 +873,9 @@ static void test_CreateIcon(void)
     UINT display_bpp;
     int i;
 
+    for (i = 0; i < sizeof(bmp_bits); ++i)
+        bmp_bits[i] = 111 * i;
+
     hdc = GetDC(0);
     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
 
@@ -871,19 +884,19 @@ static void test_CreateIcon(void)
     hIcon = CreateIcon(0, 16, 16, 1, 1, NULL, bmp_bits);
     */
 
-    hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits);
+    hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, &bmp_bits[16 * 16 / 8]);
     ok(hIcon != 0, "CreateIcon failed\n");
-    test_icon_info(hIcon, 16, 16, 32, 1, FALSE);
+    test_icon_info(hIcon, 16, 16, 32, 1, bmp_bits, FALSE);
     DestroyIcon(hIcon);
 
-    hIcon = CreateCursor(0, 8, 8, 16, 16, bmp_bits, bmp_bits);
+    hIcon = CreateCursor(0, 8, 8, 16, 16, bmp_bits, &bmp_bits[16 * 16 / 8]);
     ok(hIcon != 0, "CreateCursor failed\n");
-    test_icon_info(hIcon, 16, 16, 32, 1, FALSE);
+    test_icon_info(hIcon, 16, 16, 32, 1, bmp_bits, FALSE);
     DestroyCursor(hIcon);
 
     hIcon = CreateIcon(0, 16, 16, 1, display_bpp, bmp_bits, bmp_bits);
     ok(hIcon != 0, "CreateIcon failed\n");
-    test_icon_info(hIcon, 16, 16, 16, display_bpp, TRUE);
+    test_icon_info(hIcon, 16, 16, 16, display_bpp, bmp_bits, TRUE);
     DestroyIcon(hIcon);
 
     hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
@@ -918,7 +931,7 @@ static void test_CreateIcon(void)
     info.hbmColor = hbmColor;
     hIcon = CreateIconIndirect(&info);
     ok(hIcon != 0, "CreateIconIndirect failed\n");
-    test_icon_info(hIcon, 16, 16, 16, display_bpp, TRUE);
+    test_icon_info(hIcon, 16, 16, 16, display_bpp, bmp_bits, TRUE);
     DestroyIcon(hIcon);
 
     DeleteObject(hbmMask);
@@ -935,7 +948,7 @@ static void test_CreateIcon(void)
     SetLastError(0xdeadbeaf);
     hIcon = CreateIconIndirect(&info);
     ok(hIcon != 0, "CreateIconIndirect failed\n");
-    test_icon_info(hIcon, 16, 16, 32, 1, FALSE);
+    test_icon_info(hIcon, 16, 16, 32, 1, bmp_bits, FALSE);
     DestroyIcon(hIcon);
 
     info.hbmMask = hbmMask;
@@ -943,7 +956,7 @@ static void test_CreateIcon(void)
     SetLastError(0xdeadbeaf);
     hIcon = CreateIconIndirect(&info);
     ok(hIcon != 0, "CreateIconIndirect failed\n");
-    test_icon_info(hIcon, 16, 32, 32, 1, TRUE);
+    test_icon_info(hIcon, 16, 32, 32, 1, bmp_bits, TRUE);
     DestroyIcon(hIcon);
 
     DeleteObject(hbmMask);
@@ -961,7 +974,7 @@ static void test_CreateIcon(void)
         SetLastError(0xdeadbeaf);
         hIcon = CreateIconIndirect(&info);
         ok(hIcon != 0, "CreateIconIndirect failed\n");
-        test_icon_info(hIcon, 1, i / 2, max(i,1), 1, FALSE);
+        test_icon_info(hIcon, 1, i / 2, max(i,1), 1, NULL, FALSE);
         DestroyIcon(hIcon);
         DeleteObject(hbmMask);
     }
@@ -974,7 +987,7 @@ static void test_CreateIcon(void)
     SetLastError(0xdeadbeaf);
     hIcon = CreateIconIndirect(&info);
     ok(hIcon != 0, "CreateIconIndirect failed\n");
-    test_icon_info(hIcon, 16, 16, 32, 1, FALSE);
+    test_icon_info(hIcon, 16, 16, 32, 1, NULL, FALSE);
     DestroyIcon(hIcon);
 
     DeleteObject(hbmMask);
@@ -1006,7 +1019,7 @@ static void test_CreateIcon(void)
     SetLastError(0xdeadbeaf);
     hIcon = CreateIconIndirect(&info);
     ok(hIcon != 0, "CreateIconIndirect failed\n");
-    test_icon_info(hIcon, 32, 32, 32, 8, TRUE);
+    test_icon_info(hIcon, 32, 32, 32, 8, NULL, TRUE);
     DestroyIcon(hIcon);
     DeleteObject(hbmColor);
 
@@ -1024,7 +1037,7 @@ static void test_CreateIcon(void)
     SetLastError(0xdeadbeaf);
     hIcon = CreateIconIndirect(&info);
     ok(hIcon != 0, "CreateIconIndirect failed\n");
-    test_icon_info(hIcon, 32, 32, 32, 8, TRUE);
+    test_icon_info(hIcon, 32, 32, 32, 8, NULL, TRUE);
     DestroyIcon(hIcon);
     DeleteObject(hbmColor);
 
@@ -1042,7 +1055,7 @@ static void test_CreateIcon(void)
     SetLastError(0xdeadbeaf);
     hIcon = CreateIconIndirect(&info);
     ok(hIcon != 0, "CreateIconIndirect failed\n");
-    test_icon_info(hIcon, 32, 32, 32, 8, TRUE);
+    test_icon_info(hIcon, 32, 32, 32, 8, NULL, TRUE);
     DestroyIcon(hIcon);
 
     DeleteObject(hbmMask);
@@ -2812,7 +2825,7 @@ static void test_PrivateExtractIcons(void)
     ok(ret == 1, "PrivateExtractIconsA returned %u\n", ret);
     ok(icon != NULL, "icon == NULL\n");
 
-    test_icon_info(icon, 32, 32, 32, 32, TRUE);
+    test_icon_info(icon, 32, 32, 32, 32, NULL, TRUE);
     DestroyIcon(icon);
 
     DeleteFileA("extract.ico");
-- 
2.34.1




More information about the wine-devel mailing list