Commit 0528a2b6 authored by Alexandre Julliard's avatar Alexandre Julliard

user32: Support creating cursors and icons from DIB section bitmaps.

parent 1db3aa0b
...@@ -1790,9 +1790,10 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo) ...@@ -1790,9 +1790,10 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo)
*/ */
HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
{ {
BITMAP bmpXor,bmpAnd; DIBSECTION bmpXor;
BITMAP bmpAnd;
HICON16 hObj; HICON16 hObj;
int sizeXor,sizeAnd; int xor_objsize = 0, sizeXor = 0, sizeAnd, planes, bpp;
TRACE("color %p, mask %p, hotspot %ux%u, fIcon %d\n", TRACE("color %p, mask %p, hotspot %ux%u, fIcon %d\n",
iconinfo->hbmColor, iconinfo->hbmMask, iconinfo->hbmColor, iconinfo->hbmMask,
...@@ -1800,19 +1801,24 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) ...@@ -1800,19 +1801,24 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
if (!iconinfo->hbmMask) return 0; if (!iconinfo->hbmMask) return 0;
planes = GetDeviceCaps( screen_dc, PLANES );
bpp = GetDeviceCaps( screen_dc, BITSPIXEL );
if (iconinfo->hbmColor) if (iconinfo->hbmColor)
{ {
GetObjectW( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor ); xor_objsize = GetObjectW( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
TRACE("color: width %d, height %d, width bytes %d, planes %u, bpp %u\n", TRACE("color: width %d, height %d, width bytes %d, planes %u, bpp %u\n",
bmpXor.bmWidth, bmpXor.bmHeight, bmpXor.bmWidthBytes, bmpXor.dsBm.bmWidth, bmpXor.dsBm.bmHeight, bmpXor.dsBm.bmWidthBytes,
bmpXor.bmPlanes, bmpXor.bmBitsPixel); bmpXor.dsBm.bmPlanes, bmpXor.dsBm.bmBitsPixel);
/* we can use either depth 1 or screen depth for xor bitmap */
if (bmpXor.dsBm.bmPlanes == 1 && bmpXor.dsBm.bmBitsPixel == 1) planes = bpp = 1;
sizeXor = bmpXor.dsBm.bmHeight * planes * get_bitmap_width_bytes( bmpXor.dsBm.bmWidth, bpp );
} }
GetObjectW( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd ); GetObjectW( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
TRACE("mask: width %d, height %d, width bytes %d, planes %u, bpp %u\n", TRACE("mask: width %d, height %d, width bytes %d, planes %u, bpp %u\n",
bmpAnd.bmWidth, bmpAnd.bmHeight, bmpAnd.bmWidthBytes, bmpAnd.bmWidth, bmpAnd.bmHeight, bmpAnd.bmWidthBytes,
bmpAnd.bmPlanes, bmpAnd.bmBitsPixel); bmpAnd.bmPlanes, bmpAnd.bmBitsPixel);
sizeXor = iconinfo->hbmColor ? (bmpXor.bmHeight * bmpXor.bmWidthBytes) : 0;
sizeAnd = bmpAnd.bmHeight * get_bitmap_width_bytes(bmpAnd.bmWidth, 1); sizeAnd = bmpAnd.bmHeight * get_bitmap_width_bytes(bmpAnd.bmWidth, 1);
hObj = GlobalAlloc16( GMEM_MOVEABLE, hObj = GlobalAlloc16( GMEM_MOVEABLE,
...@@ -1837,11 +1843,11 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) ...@@ -1837,11 +1843,11 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
if (iconinfo->hbmColor) if (iconinfo->hbmColor)
{ {
info->nWidth = bmpXor.bmWidth; info->nWidth = bmpXor.dsBm.bmWidth;
info->nHeight = bmpXor.bmHeight; info->nHeight = bmpXor.dsBm.bmHeight;
info->nWidthBytes = bmpXor.bmWidthBytes; info->nWidthBytes = bmpXor.dsBm.bmWidthBytes;
info->bPlanes = bmpXor.bmPlanes; info->bPlanes = planes;
info->bBitsPerPixel = bmpXor.bmBitsPixel; info->bBitsPerPixel = bpp;
} }
else else
{ {
...@@ -1883,7 +1889,53 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) ...@@ -1883,7 +1889,53 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
GetBitmapBits( hbmp_mono, sizeAnd, (char*)(info + 1) ); GetBitmapBits( hbmp_mono, sizeAnd, (char*)(info + 1) );
DeleteObject( hbmp_mono ); DeleteObject( hbmp_mono );
} }
if (iconinfo->hbmColor) GetBitmapBits( iconinfo->hbmColor, sizeXor, (char*)(info + 1) + sizeAnd );
if (iconinfo->hbmColor)
{
char *dst_bits = (char*)(info + 1) + sizeAnd;
if (bmpXor.dsBm.bmPlanes == planes && bmpXor.dsBm.bmBitsPixel == bpp)
GetBitmapBits( iconinfo->hbmColor, sizeXor, dst_bits );
else
{
BITMAPINFO bminfo;
int dib_width = get_dib_width_bytes( info->nWidth, info->bBitsPerPixel );
int bitmap_width = get_bitmap_width_bytes( info->nWidth, info->bBitsPerPixel );
bminfo.bmiHeader.biSize = sizeof(bminfo);
bminfo.bmiHeader.biWidth = info->nWidth;
bminfo.bmiHeader.biHeight = info->nHeight;
bminfo.bmiHeader.biPlanes = info->bPlanes;
bminfo.bmiHeader.biBitCount = info->bBitsPerPixel;
bminfo.bmiHeader.biCompression = BI_RGB;
bminfo.bmiHeader.biSizeImage = info->nHeight * dib_width;
bminfo.bmiHeader.biXPelsPerMeter = 0;
bminfo.bmiHeader.biYPelsPerMeter = 0;
bminfo.bmiHeader.biClrUsed = 0;
bminfo.bmiHeader.biClrImportant = 0;
/* swap lines for dib sections */
if (xor_objsize == sizeof(DIBSECTION))
bminfo.bmiHeader.biHeight = -bminfo.bmiHeader.biHeight;
if (dib_width != bitmap_width) /* need to fixup alignment */
{
char *src_bits = HeapAlloc( GetProcessHeap(), 0, bminfo.bmiHeader.biSizeImage );
if (src_bits && GetDIBits( screen_dc, iconinfo->hbmColor, 0, info->nHeight,
src_bits, &bminfo, DIB_RGB_COLORS ))
{
int y;
for (y = 0; y < info->nHeight; y++)
memcpy( dst_bits + y * bitmap_width, src_bits + y * dib_width, bitmap_width );
}
HeapFree( GetProcessHeap(), 0, src_bits );
}
else
GetDIBits( screen_dc, iconinfo->hbmColor, 0, info->nHeight,
dst_bits, &bminfo, DIB_RGB_COLORS );
}
}
GlobalUnlock16( hObj ); GlobalUnlock16( hObj );
} }
return HICON_32(hObj); return HICON_32(hObj);
......
...@@ -504,13 +504,14 @@ static void test_CreateIcon(void) ...@@ -504,13 +504,14 @@ static void test_CreateIcon(void)
static const BYTE bmp_bits[1024]; static const BYTE bmp_bits[1024];
HICON hIcon; HICON hIcon;
HBITMAP hbmMask, hbmColor; HBITMAP hbmMask, hbmColor;
BITMAPINFO bmpinfo;
ICONINFO info; ICONINFO info;
HDC hdc; HDC hdc;
void *bits;
UINT display_bpp; UINT display_bpp;
hdc = GetDC(0); hdc = GetDC(0);
display_bpp = GetDeviceCaps(hdc, BITSPIXEL); display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(0, hdc);
/* these crash under XP /* these crash under XP
hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, NULL); hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, NULL);
...@@ -581,6 +582,69 @@ static void test_CreateIcon(void) ...@@ -581,6 +582,69 @@ static void test_CreateIcon(void)
DeleteObject(hbmMask); DeleteObject(hbmMask);
DeleteObject(hbmColor); DeleteObject(hbmColor);
/* test creating an icon from a DIB section */
memset( &bmpinfo, 0, sizeof(bmpinfo) );
bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpinfo.bmiHeader.biWidth = 32;
bmpinfo.bmiHeader.biHeight = 32;
bmpinfo.bmiHeader.biPlanes = 1;
bmpinfo.bmiHeader.biBitCount = 8;
bmpinfo.bmiHeader.biCompression = BI_RGB;
hbmColor = CreateDIBSection( hdc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
memset( bits, 0x55, 32 * 32 * bmpinfo.bmiHeader.biBitCount / 8 );
bmpinfo.bmiHeader.biBitCount = 1;
hbmMask = CreateDIBSection( hdc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
memset( bits, 0x55, 32 * 32 * bmpinfo.bmiHeader.biBitCount / 8 );
info.fIcon = TRUE;
info.xHotspot = 8;
info.yHotspot = 8;
info.hbmMask = hbmColor;
info.hbmColor = hbmMask;
SetLastError(0xdeadbeaf);
hIcon = CreateIconIndirect(&info);
ok(hIcon != 0, "CreateIconIndirect failed\n");
test_icon_info(hIcon, 32, 32, 8);
DestroyIcon(hIcon);
DeleteObject(hbmColor);
bmpinfo.bmiHeader.biBitCount = 16;
hbmColor = CreateDIBSection( hdc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
memset( bits, 0x55, 32 * 32 * bmpinfo.bmiHeader.biBitCount / 8 );
info.fIcon = TRUE;
info.xHotspot = 8;
info.yHotspot = 8;
info.hbmMask = hbmColor;
info.hbmColor = hbmMask;
SetLastError(0xdeadbeaf);
hIcon = CreateIconIndirect(&info);
ok(hIcon != 0, "CreateIconIndirect failed\n");
test_icon_info(hIcon, 32, 32, 8);
DestroyIcon(hIcon);
DeleteObject(hbmColor);
bmpinfo.bmiHeader.biBitCount = 32;
hbmColor = CreateDIBSection( hdc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
memset( bits, 0x55, 32 * 32 * bmpinfo.bmiHeader.biBitCount / 8 );
info.fIcon = TRUE;
info.xHotspot = 8;
info.yHotspot = 8;
info.hbmMask = hbmColor;
info.hbmColor = hbmMask;
SetLastError(0xdeadbeaf);
hIcon = CreateIconIndirect(&info);
ok(hIcon != 0, "CreateIconIndirect failed\n");
test_icon_info(hIcon, 32, 32, 8);
DestroyIcon(hIcon);
DeleteObject(hbmMask);
DeleteObject(hbmColor);
ReleaseDC(0, hdc);
} }
/* Shamelessly ripped from dlls/oleaut32/tests/olepicture.c */ /* Shamelessly ripped from dlls/oleaut32/tests/olepicture.c */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment