[PATCH 1/4] user32: Handle monochrome icons in CreateIcon() and CreateCursor() instead of CreateIconIndirect().

Zebediah Figura z.figura12 at gmail.com
Sun May 23 23:47:17 CDT 2021


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/user32/cursoricon.c       | 102 ++++++++++++++++++---------------
 dlls/user32/tests/cursoricon.c |  53 ++++++++++++-----
 2 files changed, 96 insertions(+), 59 deletions(-)

diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c
index e772d541235..ee6d27acf2e 100644
--- a/dlls/user32/cursoricon.c
+++ b/dlls/user32/cursoricon.c
@@ -1570,29 +1570,47 @@ 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,
+    };
+
+    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 );
+    return bitmap;
+}
+
+
 /***********************************************************************
  *		CreateCursor (USER32.@)
  */
-HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
-                                 INT xHotSpot, INT yHotSpot,
-                                 INT nWidth, INT nHeight,
-                                 LPCVOID lpANDbits, LPCVOID lpXORbits )
+HCURSOR WINAPI CreateCursor( HINSTANCE instance, int hotspot_x, int hotspot_y,
+                             int width, int height, const void *and, const void *xor )
 {
     ICONINFO info;
-    HCURSOR hCursor;
+    HCURSOR cursor;
 
-    TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
-                    nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
+    TRACE( "hotspot (%d,%d), size %dx%d\n", hotspot_x, hotspot_y, width, height );
 
     info.fIcon = FALSE;
-    info.xHotspot = xHotSpot;
-    info.yHotspot = yHotSpot;
-    info.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, lpANDbits );
-    info.hbmColor = CreateBitmap( nWidth, nHeight, 1, 1, lpXORbits );
-    hCursor = CreateIconIndirect( &info );
+    info.xHotspot = hotspot_x;
+    info.yHotspot = hotspot_y;
+    info.hbmColor = NULL;
+    info.hbmMask = create_masked_bitmap( width, height, and, xor );
+    cursor = CreateIconIndirect( &info );
     DeleteObject( info.hbmMask );
-    DeleteObject( info.hbmColor );
-    return hCursor;
+    return cursor;
 }
 
 
@@ -1615,33 +1633,34 @@ HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
  *
  * FIXME: Do we need to resize the bitmaps?
  */
-HICON WINAPI CreateIcon(
-    HINSTANCE hInstance,  /* [in] the application's hInstance */
-    INT       nWidth,     /* [in] the width of the provided bitmaps */
-    INT       nHeight,    /* [in] the height of the provided bitmaps */
-    BYTE      bPlanes,    /* [in] the number of planes in the provided bitmaps */
-    BYTE      bBitsPixel, /* [in] the number of bits per pixel of the lpXORbits bitmap */
-    LPCVOID   lpANDbits,  /* [in] a monochrome bitmap representing the icon's mask */
-    LPCVOID   lpXORbits)  /* [in] the icon's 'color' bitmap */
+HICON WINAPI CreateIcon( HINSTANCE instance, int width, int height, BYTE planes,
+                         BYTE depth, const void *and, const void *xor )
 {
-    ICONINFO iinfo;
-    HICON hIcon;
+    ICONINFO info;
+    HICON icon;
 
-    TRACE_(icon)("%dx%d, planes %d, bpp %d, xor %p, and %p\n",
-                 nWidth, nHeight, bPlanes, bBitsPixel, lpXORbits, lpANDbits);
+    TRACE_(icon)( "%dx%d, planes %d, depth %d\n", width, height, planes, depth );
 
-    iinfo.fIcon = TRUE;
-    iinfo.xHotspot = nWidth / 2;
-    iinfo.yHotspot = nHeight / 2;
-    iinfo.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, lpANDbits );
-    iinfo.hbmColor = CreateBitmap( nWidth, nHeight, bPlanes, bBitsPixel, lpXORbits );
+    info.fIcon = TRUE;
+    info.xHotspot = width / 2;
+    info.yHotspot = height / 2;
+    if (depth == 1)
+    {
+        info.hbmColor = NULL;
+        info.hbmMask = create_masked_bitmap( width, height, and, xor );
+    }
+    else
+    {
+        info.hbmColor = CreateBitmap( width, height, planes, depth, xor );
+        info.hbmMask = CreateBitmap( width, height, 1, 1, and );
+    }
 
-    hIcon = CreateIconIndirect( &iinfo );
+    icon = CreateIconIndirect( &info );
 
-    DeleteObject( iinfo.hbmMask );
-    DeleteObject( iinfo.hbmColor );
+    DeleteObject( info.hbmMask );
+    DeleteObject( info.hbmColor );
 
-    return hIcon;
+    return icon;
 }
 
 
@@ -2248,19 +2267,14 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
 
         width = bmpXor.bmWidth;
         height = bmpXor.bmHeight;
-        if (bmpXor.bmPlanes * bmpXor.bmBitsPixel != 1 || bmpAnd.bmPlanes * bmpAnd.bmBitsPixel != 1)
-        {
-            color = create_color_bitmap( width, height );
-            mask = CreateBitmap( width, height, 1, 1, NULL );
-        }
-        else mask = CreateBitmap( width, height * 2, 1, 1, NULL );
+        color = create_color_bitmap( width, height );
     }
     else
     {
         width = bmpAnd.bmWidth;
         height = bmpAnd.bmHeight;
-        mask = CreateBitmap( width, height, 1, 1, NULL );
     }
+    mask = CreateBitmap( width, height, 1, 1, NULL );
 
     hdc = CreateCompatibleDC( 0 );
     SelectObject( hdc, mask );
@@ -2271,10 +2285,6 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
         SelectObject( hdc, color );
         stretch_blt_icon( hdc, 0, 0, width, height, iconinfo->hbmColor, width, height );
     }
-    else if (iconinfo->hbmColor)
-    {
-        stretch_blt_icon( hdc, 0, height, width, height, iconinfo->hbmColor, width, height );
-    }
     else height /= 2;
 
     DeleteDC( hdc );
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c
index d2265be9b19..f60c845f8bc 100644
--- a/dlls/user32/tests/cursoricon.c
+++ b/dlls/user32/tests/cursoricon.c
@@ -709,7 +709,8 @@ static void test_initial_cursor(void)
     ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
 }
 
-static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_mask_cy, UINT exp_bpp, int line)
+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)
 {
     ICONINFO info;
     DWORD ret;
@@ -726,8 +727,7 @@ static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_m
     ret = GetObjectA(info.hbmMask, sizeof(bmMask), &bmMask);
     ok_(__FILE__, line)(ret == sizeof(bmMask), "GetObject(info.hbmMask) failed, ret %u\n", ret);
 
-    if (exp_bpp == 1)
-        ok_(__FILE__, line)(info.hbmColor == 0, "info.hbmColor should be NULL\n");
+    ok_(__FILE__, line)(!!info.hbmColor == has_color, "got hbmColor %p\n", info.hbmColor);
 
     if (info.hbmColor)
     {
@@ -790,7 +790,7 @@ static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_m
     }
 }
 
-#define test_icon_info(a,b,c,d,e) test_icon_info_dbg((a),(b),(c),(d),(e),__LINE__)
+#define test_icon_info(a,b,c,d,e,f) test_icon_info_(a,b,c,d,e,f,__LINE__)
 
 static void test_CreateIcon(void)
 {
@@ -814,12 +814,17 @@ static void test_CreateIcon(void)
 
     hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits);
     ok(hIcon != 0, "CreateIcon failed\n");
-    test_icon_info(hIcon, 16, 16, 32, 1);
+    test_icon_info(hIcon, 16, 16, 32, 1, FALSE);
     DestroyIcon(hIcon);
 
+    hIcon = CreateCursor(0, 8, 8, 16, 16, bmp_bits, bmp_bits);
+    ok(hIcon != 0, "CreateCursor failed\n");
+    test_icon_info(hIcon, 16, 16, 32, 1, 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);
+    test_icon_info(hIcon, 16, 16, 16, display_bpp, TRUE);
     DestroyIcon(hIcon);
 
     hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
@@ -854,7 +859,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);
+    test_icon_info(hIcon, 16, 16, 16, display_bpp, TRUE);
     DestroyIcon(hIcon);
 
     DeleteObject(hbmMask);
@@ -871,8 +876,17 @@ static void test_CreateIcon(void)
     SetLastError(0xdeadbeaf);
     hIcon = CreateIconIndirect(&info);
     ok(hIcon != 0, "CreateIconIndirect failed\n");
-    test_icon_info(hIcon, 16, 16, 32, 1);
+    test_icon_info(hIcon, 16, 16, 32, 1, FALSE);
     DestroyIcon(hIcon);
+
+    info.hbmMask = hbmMask;
+    info.hbmColor = hbmMask;
+    SetLastError(0xdeadbeaf);
+    hIcon = CreateIconIndirect(&info);
+    ok(hIcon != 0, "CreateIconIndirect failed\n");
+    test_icon_info(hIcon, 16, 32, 32, 1, TRUE);
+    DestroyIcon(hIcon);
+
     DeleteObject(hbmMask);
 
     for (i = 0; i <= 4; i++)
@@ -888,11 +902,24 @@ 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);
+        test_icon_info(hIcon, 1, i / 2, max(i,1), 1, FALSE);
         DestroyIcon(hIcon);
         DeleteObject(hbmMask);
     }
 
+    hbmMask = CreateBitmap(16, 32, 1, 16, bmp_bits);
+    ok(hbmMask != 0, "CreateBitmap failed\n");
+
+    info.hbmMask = hbmMask;
+    info.hbmColor = 0;
+    SetLastError(0xdeadbeaf);
+    hIcon = CreateIconIndirect(&info);
+    ok(hIcon != 0, "CreateIconIndirect failed\n");
+    test_icon_info(hIcon, 16, 16, 32, 1, FALSE);
+    DestroyIcon(hIcon);
+
+    DeleteObject(hbmMask);
+
     /* test creating an icon from a DIB section */
 
     bmpinfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(BITMAPINFO,bmiColors[256]));
@@ -920,7 +947,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);
+    test_icon_info(hIcon, 32, 32, 32, 8, TRUE);
     DestroyIcon(hIcon);
     DeleteObject(hbmColor);
 
@@ -938,7 +965,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);
+    test_icon_info(hIcon, 32, 32, 32, 8, TRUE);
     DestroyIcon(hIcon);
     DeleteObject(hbmColor);
 
@@ -956,7 +983,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);
+    test_icon_info(hIcon, 32, 32, 32, 8, TRUE);
     DestroyIcon(hIcon);
 
     DeleteObject(hbmMask);
@@ -2662,7 +2689,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);
+    test_icon_info(icon, 32, 32, 32, 32, TRUE);
     DestroyIcon(icon);
 
     DeleteFileA("extract.ico");
-- 
2.30.2




More information about the wine-devel mailing list