Signed-off-by: Zebediah Figura z.figura12@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");