[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