Alexandre Julliard : user32: Support creating cursors and icons from DIB section bitmaps.
Alexandre Julliard
julliard at winehq.org
Wed May 21 05:22:45 CDT 2008
Module: wine
Branch: master
Commit: 0528a2b660f3aa01d274ecae5f2de02d5fb52ae8
URL: http://source.winehq.org/git/wine.git/?a=commit;h=0528a2b660f3aa01d274ecae5f2de02d5fb52ae8
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed May 21 11:39:38 2008 +0200
user32: Support creating cursors and icons from DIB section bitmaps.
---
dlls/user32/cursoricon.c | 76 +++++++++++++++++++++++++++++++++------
dlls/user32/tests/cursoricon.c | 66 ++++++++++++++++++++++++++++++++++-
2 files changed, 129 insertions(+), 13 deletions(-)
diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c
index c5d192d..a1ba570 100644
--- a/dlls/user32/cursoricon.c
+++ b/dlls/user32/cursoricon.c
@@ -1790,9 +1790,10 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo)
*/
HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
{
- BITMAP bmpXor,bmpAnd;
+ DIBSECTION bmpXor;
+ BITMAP bmpAnd;
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",
iconinfo->hbmColor, iconinfo->hbmMask,
@@ -1800,19 +1801,24 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
if (!iconinfo->hbmMask) return 0;
+ planes = GetDeviceCaps( screen_dc, PLANES );
+ bpp = GetDeviceCaps( screen_dc, BITSPIXEL );
+
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",
- bmpXor.bmWidth, bmpXor.bmHeight, bmpXor.bmWidthBytes,
- bmpXor.bmPlanes, bmpXor.bmBitsPixel);
+ bmpXor.dsBm.bmWidth, bmpXor.dsBm.bmHeight, bmpXor.dsBm.bmWidthBytes,
+ 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 );
TRACE("mask: width %d, height %d, width bytes %d, planes %u, bpp %u\n",
bmpAnd.bmWidth, bmpAnd.bmHeight, bmpAnd.bmWidthBytes,
bmpAnd.bmPlanes, bmpAnd.bmBitsPixel);
- sizeXor = iconinfo->hbmColor ? (bmpXor.bmHeight * bmpXor.bmWidthBytes) : 0;
sizeAnd = bmpAnd.bmHeight * get_bitmap_width_bytes(bmpAnd.bmWidth, 1);
hObj = GlobalAlloc16( GMEM_MOVEABLE,
@@ -1837,11 +1843,11 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
if (iconinfo->hbmColor)
{
- info->nWidth = bmpXor.bmWidth;
- info->nHeight = bmpXor.bmHeight;
- info->nWidthBytes = bmpXor.bmWidthBytes;
- info->bPlanes = bmpXor.bmPlanes;
- info->bBitsPerPixel = bmpXor.bmBitsPixel;
+ info->nWidth = bmpXor.dsBm.bmWidth;
+ info->nHeight = bmpXor.dsBm.bmHeight;
+ info->nWidthBytes = bmpXor.dsBm.bmWidthBytes;
+ info->bPlanes = planes;
+ info->bBitsPerPixel = bpp;
}
else
{
@@ -1883,7 +1889,53 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
GetBitmapBits( hbmp_mono, sizeAnd, (char*)(info + 1) );
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 );
}
return HICON_32(hObj);
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c
index 40f3a14..dcac002 100644
--- a/dlls/user32/tests/cursoricon.c
+++ b/dlls/user32/tests/cursoricon.c
@@ -504,13 +504,14 @@ static void test_CreateIcon(void)
static const BYTE bmp_bits[1024];
HICON hIcon;
HBITMAP hbmMask, hbmColor;
+ BITMAPINFO bmpinfo;
ICONINFO info;
HDC hdc;
+ void *bits;
UINT display_bpp;
hdc = GetDC(0);
display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
- ReleaseDC(0, hdc);
/* these crash under XP
hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, NULL);
@@ -581,6 +582,69 @@ static void test_CreateIcon(void)
DeleteObject(hbmMask);
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 */
More information about the wine-cvs
mailing list