Module: wine Branch: master Commit: 0528a2b660f3aa01d274ecae5f2de02d5fb52ae8 URL: http://source.winehq.org/git/wine.git/?a=commit;h=0528a2b660f3aa01d274ecae5f...
Author: Alexandre Julliard julliard@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 */