Hi All, I've been working on alpha support in HICONs and HIMAGELISTs. This patch set includes my earlier test patch (plus modifications as per the comments), and fixes up DrawIcon, DrawIconEx and CURSORICON_CreateIconFromBMI.
I've tested the test patch on 2k, XP, and Vista - but any other test platforms would be welcome, and any comments on the other 4 patches before I submit them. Best Regards Joel Holdsworth
>From d22ba983b85028f667a7754858f35c7e219847e9 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth <j...@airwebreathe.org.uk> Date: Tue, 2 Jun 2009 21:13:47 +0100 Subject: [PATCH] Added tests for DrawIcon and DrawIconEx --- dlls/user32/tests/cursoricon.c | 355 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 355 insertions(+), 0 deletions(-) diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 9475534..4caf442 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -956,6 +956,359 @@ static void test_CreateIconFromResource(void) HeapFree(GetProcessHeap(), 0, hotspot); } +static HICON create_test_icon(HDC hdc, int width, int height, int bpp, + BOOL maskvalue, UINT32 *color, int colorSize) +{ + ICONINFO iconInfo; + BITMAPINFO bitmapInfo; + UINT32 *buffer = NULL; + UINT32 mask = maskvalue ? 0xFFFFFFFF : 0x00000000; + + memset(&bitmapInfo, 0, sizeof(bitmapInfo)); + bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapInfo.bmiHeader.biWidth = width; + bitmapInfo.bmiHeader.biHeight = height; + bitmapInfo.bmiHeader.biPlanes = 1; + bitmapInfo.bmiHeader.biBitCount = bpp; + bitmapInfo.bmiHeader.biCompression = BI_RGB; + bitmapInfo.bmiHeader.biSizeImage = colorSize; + + iconInfo.fIcon = TRUE; + iconInfo.xHotspot = 0; + iconInfo.yHotspot = 0; + + iconInfo.hbmMask = CreateBitmap( width, height, 1, 1, &mask ); + if(!iconInfo.hbmMask) return NULL; + + iconInfo.hbmColor = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0); + if(!iconInfo.hbmColor || !buffer) + { + DeleteObject(iconInfo.hbmMask); + return NULL; + } + + memcpy(buffer, color, colorSize); + + return CreateIconIndirect(&iconInfo); +} + +static void flood_background(HDC hdc, int width, int height, COLORREF color) +{ + RECT rect = {0, 0, 1, 1}; + HBRUSH backgroundBrush = CreateSolidBrush(color); + FillRect(hdc, &rect, backgroundBrush); + DeleteObject(backgroundBrush); +} + +static void check_DrawIcon(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, + COLORREF background, COLORREF expected, int line) +{ + COLORREF result; + HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color)); + if (!hicon) return; + flood_background(hdc, 1, 1, background); + DrawIcon(hdc, 0, 0, hicon); + result = GetPixel(hdc, 0, 0); + + ok (result == expected, + "Overlaying Mask %d on Color %08X with DrawIcon. Expected %08X. Got %08X from line %d\n", + maskvalue, (unsigned int)color, (unsigned int)expected, (unsigned int)result, line); +} + +static void check_DrawIconEx(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, UINT flags, + COLORREF background, COLORREF expected, int line) +{ + COLORREF result; + HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color)); + if (!hicon) return; + flood_background(hdc, 1, 1, background); + DrawIconEx(hdc, 0, 0, hicon, 1, 1, 0, NULL, flags); + result = GetPixel(hdc, 0, 0); + + ok (result == expected, + "Overlaying Mask %d on Color %08X with DrawIconEx flags %08X. Expected %08X. Got %08X from line %d\n", + maskvalue, (unsigned int)color, flags, (unsigned int)expected, (unsigned int)result, line); +} + +static void check_alpha_draw(HDC hdc, BOOL drawiconex, BOOL alpha, int bpp, int line) +{ + HICON hicon; + UINT32 mask; + UINT32 color[2]; + COLORREF expected, result; + + mask = 0x00000000; + color[0] = 0x00A0B0C0; + color[1] = alpha ? 0xFF000000 : 0x00000000; + expected = alpha ? 0x00FFFFFF : 0x00C0B0A0; + + hicon = create_test_icon(hdc, 2, 1, bpp, 0, (UINT32*)&color, sizeof(color)); + if (!hicon) return; + + flood_background(hdc, 1, 1, 0x00FFFFFF); + + if(drawiconex) + DrawIconEx(hdc, 0, 0, hicon, 2, 1, 0, NULL, DI_NORMAL); + else + DrawIcon(hdc, 0, 0, hicon); + + result = GetPixel(hdc, 0, 0); + ok (result == expected, + "%s. Expected %08X with %s. Got %08X from line %d\n", + alpha ? "Alpha blending" : "Not alpha blending", + (unsigned int)expected, drawiconex ? "DrawIconEx" : "DrawIcon", + (unsigned int)result, line); +} + +static void test_DrawIcon_true_color(HDC hdcDst) +{ + DWORD dwVersion = GetVersion(); + DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); + DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); + + /* Mask is only heeded if alpha channel is always zero */ + check_DrawIcon(hdcDst, FALSE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x003F4F5F, __LINE__); + + /* Test alpha blending */ + /* Applicable to XP and up */ + if(dwMajorVersion > 5 || dwMinorVersion >= 1) + { + check_DrawIcon(hdcDst, FALSE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + + todo_wine + { + check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + + check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, __LINE__); + check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, __LINE__); + + check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, __LINE__); + check_DrawIcon(hdcDst, FALSE, 0xFEFFFFFF, 32, 0x00000000, 0x00FEFEFE, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0xFEFFFFFF, 32, 0x00000000, 0x00FEFEFE, __LINE__); + } + + /* Test detecting of alpha channel */ + /* If a single pixel's alpha channel is non-zero, the icon + will be alpha blended, otherwise it will be draw with + and + xor blts. */ + check_alpha_draw(hdcDst, FALSE, FALSE, 32, __LINE__); + todo_wine check_alpha_draw(hdcDst, FALSE, TRUE, 32, __LINE__); + } +} + +static void test_DrawIcon() +{ + BITMAPINFO bitmapInfo; + HDC hdcDst = NULL; + HBITMAP bmpDst = NULL; + HBITMAP bmpOld = NULL; + UINT32 *bits = 0; + + hdcDst = CreateCompatibleDC(0); + if (!hdcDst) + return; + + memset(&bitmapInfo, 0, sizeof(bitmapInfo)); + bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapInfo.bmiHeader.biWidth = 1; + bitmapInfo.bmiHeader.biHeight = 1; + bitmapInfo.bmiHeader.biPlanes = 1; + bitmapInfo.bmiHeader.biCompression = BI_RGB; + bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32); + + /* 16-bit Tests */ + bitmapInfo.bmiHeader.biBitCount = 16; + bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + if (!bmpDst || !bits) + goto cleanup; + bmpOld = SelectObject(hdcDst, bmpDst); + + check_DrawIcon(hdcDst, FALSE, 0x00A0B0C0, 16, 0x00FFFFFF, 0x00003163, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0x00A0B0C0, 16, 0x00FFFFFF, 0x00FFCE9C, __LINE__); + + check_DrawIcon(hdcDst, FALSE, 0xFFA0B0C0, 16, 0x00FFFFFF, 0x00003163, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 16, 0x00FFFFFF, 0x00FFCE9C, __LINE__); + check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 16, 0x00FFFFFF, 0x00003163, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 16, 0x00FFFFFF, 0x00FFCE9C, __LINE__); + + SelectObject(hdcDst, bmpOld); + DeleteObject(bmpDst); + bmpOld = NULL; + bmpDst = NULL; + + /* 24-bit Tests */ + bitmapInfo.bmiHeader.biBitCount = 24; + bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + if (!bmpDst || !bits) + goto cleanup; + bmpOld = SelectObject(hdcDst, bmpDst); + + test_DrawIcon_true_color(hdcDst); + + SelectObject(hdcDst, bmpOld); + DeleteObject(bmpDst); + bmpOld = NULL; + bmpDst = NULL; + + /* 32-bit Tests */ + bitmapInfo.bmiHeader.biBitCount = 32; + bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + if (!bmpDst || !bits) + goto cleanup; + bmpOld = SelectObject(hdcDst, bmpDst); + + test_DrawIcon_true_color(hdcDst); + + SelectObject(hdcDst, bmpOld); + DeleteObject(bmpDst); + bmpOld = NULL; + bmpDst = NULL; + +cleanup: + if(bmpOld) + SelectObject(hdcDst, bmpOld); + if(bmpDst) + DeleteObject(bmpDst); + if(hdcDst) + DeleteDC(hdcDst); +} + +static void test_DrawIconEx_true_color(HDC hdcDst) +{ + DWORD dwVersion = GetVersion(); + DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); + DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); + + /* Test null, image only, and mask only drawing */ + todo_wine + { + check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, __LINE__); + } + + check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00000000, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00FFFFFF, __LINE__); + + todo_wine + { + check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + } + + /* Test normal drawing */ + check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + todo_wine check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x003F4F5F, __LINE__); + check_DrawIconEx(hdcDst, FALSE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + + /* Test alpha blending */ + /* Applicable to XP and up */ + if(dwMajorVersion > 5 || dwMinorVersion >= 1) + { + todo_wine + { + check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + + check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, __LINE__); + check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, __LINE__); + + check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, __LINE__); + check_DrawIconEx(hdcDst, FALSE, 0xFEFFFFFF, 32, DI_NORMAL, 0x00000000, 0x00FEFEFE, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0xFEFFFFFF, 32, DI_NORMAL, 0x00000000, 0x00FEFEFE, __LINE__); + } + + /* Test detecting of alpha channel */ + /* If a single pixel's alpha channel is non-zero, the icon + will be alpha blended, otherwise it will be draw with + and + xor blts. */ + check_alpha_draw(hdcDst, TRUE, FALSE, 32, __LINE__); + todo_wine check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__); + } +} + +static void test_DrawIconEx() +{ + BITMAPINFO bitmapInfo; + HDC hdcDst = NULL; + HBITMAP bmpDst = NULL; + HBITMAP bmpOld = NULL; + UINT32 bits = 0; + + hdcDst = CreateCompatibleDC(0); + if (!hdcDst) + return; + + memset(&bitmapInfo, 0, sizeof(bitmapInfo)); + bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapInfo.bmiHeader.biWidth = 1; + bitmapInfo.bmiHeader.biHeight = 1; + bitmapInfo.bmiHeader.biPlanes = 1; + bitmapInfo.bmiHeader.biCompression = BI_RGB; + bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32); + + /* 16-bit Tests */ + bitmapInfo.bmiHeader.biBitCount = 16; + bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + if (!bmpDst || !bits) + goto cleanup; + bmpOld = SelectObject(hdcDst, bmpDst); + + check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 16, DI_NORMAL, 0x00FFFFFF, 0x00003163, __LINE__); + todo_wine check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 16, DI_NORMAL, 0x00FFFFFF, 0x00FFCE9C, __LINE__); + + check_DrawIconEx(hdcDst, FALSE, 0xFFA0B0C0, 16, DI_NORMAL, 0x00FFFFFF, 0x00003163, __LINE__); + todo_wine check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 16, DI_NORMAL, 0x00FFFFFF, 0x00FFCE9C, __LINE__); + check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 16, DI_NORMAL, 0x00FFFFFF, 0x00003163, __LINE__); + todo_wine check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 16, DI_NORMAL, 0x00FFFFFF, 0x00FFCE9C, __LINE__); + + SelectObject(hdcDst, bmpOld); + DeleteObject(bmpDst); + bmpOld = NULL; + bmpDst = NULL; + + /* 24-bit Tests */ + bitmapInfo.bmiHeader.biBitCount = 24; + bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + if (!bmpDst || !bits) + goto cleanup; + bmpOld = SelectObject(hdcDst, bmpDst); + + test_DrawIconEx_true_color(hdcDst); + + SelectObject(hdcDst, bmpOld); + DeleteObject(bmpDst); + bmpOld = NULL; + bmpDst = NULL; + + /* 32-bit Tests */ + bitmapInfo.bmiHeader.biBitCount = 32; + bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + if (!bmpDst || !bits) + goto cleanup; + bmpOld = SelectObject(hdcDst, bmpDst); + + test_DrawIconEx_true_color(hdcDst); + + SelectObject(hdcDst, bmpOld); + DeleteObject(bmpDst); + bmpOld = NULL; + bmpDst = NULL; + +cleanup: + if(bmpOld) + SelectObject(hdcDst, bmpOld); + if(bmpDst) + DeleteObject(bmpDst); + if(hdcDst) + DeleteDC(hdcDst); +} + static void test_DestroyCursor(void) { static const BYTE bmp_bits[4096]; @@ -1063,6 +1416,8 @@ START_TEST(cursoricon) test_CreateIcon(); test_LoadImage(); test_CreateIconFromResource(); + test_DrawIcon(); + test_DrawIconEx(); test_DestroyCursor(); do_parent(); test_child_process(); -- 1.6.0.4
>From f4fb02ea0039539c04ad1757ac57ce59fe08bc91 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth <j...@airwebreathe.org.uk> Date: Sun, 31 May 2009 17:00:17 +0100 Subject: [PATCH] Added icon alpha blend support functions --- dlls/user32/cursoricon.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 68 insertions(+), 0 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 707d2bb..3cdd623 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -1598,6 +1598,74 @@ BOOL WINAPI DestroyCursor( HCURSOR hCursor ) return DestroyIcon32(HCURSOR_16(hCursor), CID_WIN32); } +/*********************************************************************** + * bitmap_has_alpha_channel + * + * Analyses bits bitmap to determine if alpha data is present. + * + * PARAMS + * bpp [I] The bits-per-pixel of the bitmap + * bitmapBits [I] A pointer to the bitmap data + * bitmapLength [I] The length of the bitmap in bytes + * + * RETURNS + * TRUE if an alpha channel is discovered, FALSE + * + * NOTE + * Windows' behaviour is that if the icon bitmap is 32-bit and at + * least one pixel has a non-zero alpha, then the bitmap is a + * treated as having an alpha channel transparentcy. Otherwise, + * it's treated as being completely opaque. + * + */ +static BOOL bitmap_has_alpha_channel( int bpp, unsigned char *bitmapBits, + unsigned int bitmapLength ) +{ + /* Detect an alpha channel by looking for non-zero alpha pixels */ + if(bpp == 32) + { + unsigned int offset; + for(offset = 3; offset < bitmapLength; offset += 4) + { + if(bitmapBits[offset] != 0) + { + return TRUE; + break; + } + } + } + return FALSE; +} + +/*********************************************************************** + * premultiply_alpha_channel + * + * Premultiplies the color channels of a 32-bit bitmap by the alpha + * channel. This is a necessary step that must be carried out on + * the image before it is passed to GdiAlphaBlend + * + * PARAMS + * destBitmap [I] The destination bitmap buffer + * srcBitmap [I] The source bitmap buffer + * bitmapLength [I] The length of the bitmap in bytes + * + */ +static void premultiply_alpha_channel( unsigned char *destBitmap, + unsigned char *srcBitmap, + unsigned int bitmapLength ) +{ + unsigned char *destPixel = destBitmap; + unsigned char *srcPixel = srcBitmap; + + while(destPixel < destBitmap + bitmapLength) + { + unsigned char alpha = srcPixel[3]; + *(destPixel++) = *(srcPixel++) * alpha / 255; + *(destPixel++) = *(srcPixel++) * alpha / 255; + *(destPixel++) = *(srcPixel++) * alpha / 255; + *(destPixel++) = *(srcPixel++); + } +} /*********************************************************************** * DrawIcon (USER32.@) -- 1.6.0.4
>From 1141b32bd30537159feed223f6ca0265add58bed Mon Sep 17 00:00:00 2001 From: Joel Holdsworth <j...@airwebreathe.org.uk> Date: Sun, 31 May 2009 16:55:39 +0100 Subject: [PATCH] Added DrawIcon alpha blending support --- dlls/user32/cursoricon.c | 63 +++++++++++++++++++++++++++++++++------- dlls/user32/tests/cursoricon.c | 23 ++++++-------- 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 3cdd623..7f56648 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -1674,28 +1674,69 @@ BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon ) { CURSORICONINFO *ptr; HDC hMemDC; - HBITMAP hXorBits, hAndBits; + HBITMAP hXorBits = NULL, hAndBits = NULL, hBitTemp = NULL; COLORREF oldFg, oldBg; + unsigned char *xorBitmapBits; + unsigned int dibLength; TRACE("%p, (%d,%d), %p\n", hdc, x, y, hIcon); if (!(ptr = GlobalLock16(HICON_16(hIcon)))) return FALSE; if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE; - hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1, ptr + 1 ); - hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes, - ptr->bBitsPerPixel, (char *)(ptr + 1) - + ptr->nHeight * get_bitmap_width_bytes(ptr->nWidth,1) ); + + dibLength = ptr->nHeight * get_bitmap_width_bytes( + ptr->nWidth, ptr->bBitsPerPixel); + + xorBitmapBits = (unsigned char *)(ptr + 1) + ptr->nHeight * + get_bitmap_width_bytes(ptr->nWidth, 1); + oldFg = SetTextColor( hdc, RGB(0,0,0) ); oldBg = SetBkColor( hdc, RGB(255,255,255) ); - if (hXorBits && hAndBits) + if(bitmap_has_alpha_channel(ptr->bBitsPerPixel, xorBitmapBits, dibLength)) + { + BITMAPINFOHEADER bmih; + unsigned char *dibBits; + + memset(&bmih, 0, sizeof(BITMAPINFOHEADER)); + bmih.biSize = sizeof(BITMAPINFOHEADER); + bmih.biWidth = ptr->nWidth; + bmih.biHeight = -ptr->nHeight; + bmih.biPlanes = ptr->bPlanes; + bmih.biBitCount = 32; + bmih.biCompression = BI_RGB; + + hXorBits = CreateDIBSection(hdc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, + (void*)&dibBits, NULL, 0); + + if (hXorBits && dibBits) + { + BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + + /* Do the alpha blending render */ + premultiply_alpha_channel(dibBits, xorBitmapBits, dibLength); + hBitTemp = SelectObject( hMemDC, hXorBits ); + GdiAlphaBlend(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, + 0, 0, ptr->nWidth, ptr->nHeight, pixelblend); + SelectObject( hMemDC, hBitTemp ); + } + } + else { - HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits ); - BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND ); - SelectObject( hMemDC, hXorBits ); - BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT); - SelectObject( hMemDC, hBitTemp ); + hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1, ptr + 1 ); + hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes, + ptr->bBitsPerPixel, xorBitmapBits); + + if (hXorBits && hAndBits) + { + hBitTemp = SelectObject( hMemDC, hAndBits ); + BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND ); + SelectObject( hMemDC, hXorBits ); + BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT); + SelectObject( hMemDC, hBitTemp ); + } } + DeleteDC( hMemDC ); if (hXorBits) DeleteObject( hXorBits ); if (hAndBits) DeleteObject( hAndBits ); diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 4caf442..23c1d3b 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -1076,27 +1076,24 @@ static void test_DrawIcon_true_color(HDC hdcDst) { check_DrawIcon(hdcDst, FALSE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, __LINE__); - todo_wine - { - check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, __LINE__); - check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, __LINE__); - check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, __LINE__); - check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, __LINE__); - check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, __LINE__); + check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, __LINE__); + check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, __LINE__); - check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, __LINE__); - check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, __LINE__); - check_DrawIcon(hdcDst, FALSE, 0xFEFFFFFF, 32, 0x00000000, 0x00FEFEFE, __LINE__); - check_DrawIcon(hdcDst, TRUE, 0xFEFFFFFF, 32, 0x00000000, 0x00FEFEFE, __LINE__); - } + check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, __LINE__); + check_DrawIcon(hdcDst, FALSE, 0xFEFFFFFF, 32, 0x00000000, 0x00FEFEFE, __LINE__); + check_DrawIcon(hdcDst, TRUE, 0xFEFFFFFF, 32, 0x00000000, 0x00FEFEFE, __LINE__); /* Test detecting of alpha channel */ /* If a single pixel's alpha channel is non-zero, the icon will be alpha blended, otherwise it will be draw with and + xor blts. */ check_alpha_draw(hdcDst, FALSE, FALSE, 32, __LINE__); - todo_wine check_alpha_draw(hdcDst, FALSE, TRUE, 32, __LINE__); + check_alpha_draw(hdcDst, FALSE, TRUE, 32, __LINE__); } } -- 1.6.0.4
>From 936d4340692fa9ffe31d3f8bbf054ab29ac56295 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth <j...@airwebreathe.org.uk> Date: Sun, 31 May 2009 16:52:48 +0100 Subject: [PATCH] Added DrawIconEx alpha blending support --- dlls/user32/cursoricon.c | 102 +++++++++++++++++++++++++++++----------- dlls/user32/tests/cursoricon.c | 30 +++++------- 2 files changed, 87 insertions(+), 45 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 7f56648..92446e1 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -2273,25 +2273,33 @@ BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon, INT cxWidth, INT cyWidth, UINT istep, HBRUSH hbr, UINT flags ) { - CURSORICONINFO *ptr = GlobalLock16(HICON_16(hIcon)); + CURSORICONINFO *ptr; HDC hDC_off = 0, hMemDC; BOOL result = FALSE, DoOffscreen; HBITMAP hB_off = 0, hOld = 0; + unsigned char *xorBitmapBits; + unsigned int xorLength; + BOOL has_alpha = FALSE; - if (!ptr) return FALSE; TRACE_(icon)("(hdc=%p,pos=%d.%d,hicon=%p,extend=%d.%d,istep=%d,br=%p,flags=0x%08x)\n", hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags ); - hMemDC = CreateCompatibleDC (hdc); + if (!(ptr = GlobalLock16(HICON_16(hIcon)))) return FALSE; + if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE; + if (istep) FIXME_(icon)("Ignoring istep=%d\n", istep); if (flags & DI_NOMIRROR) FIXME_(icon)("Ignoring flag DI_NOMIRROR\n"); - if (!flags) { - FIXME_(icon)("no flags set? setting to DI_NORMAL\n"); - flags = DI_NORMAL; - } + xorLength = ptr->nHeight * get_bitmap_width_bytes( + ptr->nWidth, ptr->bBitsPerPixel); + xorBitmapBits = (unsigned char *)(ptr + 1) + ptr->nHeight * + get_bitmap_width_bytes(ptr->nWidth, 1); + + if (flags & DI_IMAGE) + has_alpha = bitmap_has_alpha_channel( + ptr->bBitsPerPixel, xorBitmapBits, xorLength); /* Calculate the size of the destination image. */ if (cxWidth == 0) @@ -2329,50 +2337,90 @@ BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon, if (hMemDC && (!DoOffscreen || (hDC_off && hB_off))) { - HBITMAP hXorBits, hAndBits; + HBITMAP hBitTemp; + HBITMAP hXorBits = NULL, hAndBits = NULL; COLORREF oldFg, oldBg; INT nStretchMode; nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS); - hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight, - ptr->bPlanes, ptr->bBitsPerPixel, - (char *)(ptr + 1) - + ptr->nHeight * - get_bitmap_width_bytes(ptr->nWidth,1) ); - hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight, 1, 1, ptr + 1 ); oldFg = SetTextColor( hdc, RGB(0,0,0) ); oldBg = SetBkColor( hdc, RGB(255,255,255) ); - if (hXorBits && hAndBits) + if (((flags & DI_MASK) && !(flags & DI_IMAGE)) || + ((flags & DI_MASK) && !has_alpha)) { - HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits ); - if (flags & DI_MASK) + hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight, 1, 1, ptr + 1 ); + if (hAndBits) { + hBitTemp = SelectObject( hMemDC, hAndBits ); if (DoOffscreen) StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth, hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND); else StretchBlt (hdc, x0, y0, cxWidth, cyWidth, hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND); + SelectObject( hMemDC, hBitTemp ); } - SelectObject( hMemDC, hXorBits ); - if (flags & DI_IMAGE) + } + + if (flags & DI_IMAGE) + { + BITMAPINFOHEADER bmih; + unsigned char *dibBits; + + memset(&bmih, 0, sizeof(BITMAPINFOHEADER)); + bmih.biSize = sizeof(BITMAPINFOHEADER); + bmih.biWidth = ptr->nWidth; + bmih.biHeight = -ptr->nHeight; + bmih.biPlanes = ptr->bPlanes; + bmih.biBitCount = ptr->bBitsPerPixel; + bmih.biCompression = BI_RGB; + + hXorBits = CreateDIBSection(hdc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, + (void*)&dibBits, NULL, 0); + + if (hXorBits && dibBits) { - if (DoOffscreen) - StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth, - hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT); + if(has_alpha) + { + BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; + + /* Do the alpha blending render */ + premultiply_alpha_channel(dibBits, xorBitmapBits, xorLength); + hBitTemp = SelectObject( hMemDC, hXorBits ); + + if (DoOffscreen) + GdiAlphaBlend(hDC_off, 0, 0, cxWidth, cyWidth, hMemDC, + 0, 0, ptr->nWidth, ptr->nHeight, pixelblend); + else + GdiAlphaBlend(hdc, x0, y0, cxWidth, cyWidth, hMemDC, + 0, 0, ptr->nWidth, ptr->nHeight, pixelblend); + + SelectObject( hMemDC, hBitTemp ); + } else - StretchBlt (hdc, x0, y0, cxWidth, cyWidth, - hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT); + { + memcpy(dibBits, xorBitmapBits, xorLength); + hBitTemp = SelectObject( hMemDC, hXorBits ); + if (DoOffscreen) + StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth, + hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT); + else + StretchBlt (hdc, x0, y0, cxWidth, cyWidth, + hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT); + SelectObject( hMemDC, hBitTemp ); + } + + DeleteObject( hXorBits ); } - SelectObject( hMemDC, hBitTemp ); - result = TRUE; } + result = TRUE; + SetTextColor( hdc, oldFg ); SetBkColor( hdc, oldBg ); - if (hXorBits) DeleteObject( hXorBits ); + if (hAndBits) DeleteObject( hAndBits ); SetStretchBltMode (hdc, nStretchMode); if (DoOffscreen) { diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 23c1d3b..a2313a6 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -1181,11 +1181,8 @@ static void test_DrawIconEx_true_color(HDC hdcDst) DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); /* Test null, image only, and mask only drawing */ - todo_wine - { - check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, __LINE__); - check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, __LINE__); - } + check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, __LINE__); check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00000000, __LINE__); check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00FFFFFF, __LINE__); @@ -1205,27 +1202,24 @@ static void test_DrawIconEx_true_color(HDC hdcDst) /* Applicable to XP and up */ if(dwMajorVersion > 5 || dwMinorVersion >= 1) { - todo_wine - { - check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, __LINE__); - check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, __LINE__); - check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, __LINE__); - check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, __LINE__); - check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, __LINE__); + check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, __LINE__); + check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, __LINE__); - check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, __LINE__); - check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, __LINE__); - check_DrawIconEx(hdcDst, FALSE, 0xFEFFFFFF, 32, DI_NORMAL, 0x00000000, 0x00FEFEFE, __LINE__); - check_DrawIconEx(hdcDst, TRUE, 0xFEFFFFFF, 32, DI_NORMAL, 0x00000000, 0x00FEFEFE, __LINE__); - } + check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, __LINE__); + check_DrawIconEx(hdcDst, FALSE, 0xFEFFFFFF, 32, DI_NORMAL, 0x00000000, 0x00FEFEFE, __LINE__); + check_DrawIconEx(hdcDst, TRUE, 0xFEFFFFFF, 32, DI_NORMAL, 0x00000000, 0x00FEFEFE, __LINE__); /* Test detecting of alpha channel */ /* If a single pixel's alpha channel is non-zero, the icon will be alpha blended, otherwise it will be draw with and + xor blts. */ check_alpha_draw(hdcDst, TRUE, FALSE, 32, __LINE__); - todo_wine check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__); + check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__); } } -- 1.6.0.4
>From ec8d43d4b705150e4a7b29aaec9e4d39d87dc0a6 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth <j...@airwebreathe.org.uk> Date: Tue, 2 Jun 2009 22:05:14 +0100 Subject: [PATCH] Fixed CURSORICON_CreateIconFromBMI to preserve the alpha channel --- dlls/user32/cursoricon.c | 159 ++++++++++++++++++++++++++++++++-------------- 1 files changed, 112 insertions(+), 47 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 92446e1..e13bb0c 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -659,6 +659,39 @@ static CURSORICONFILEDIRENTRY *CURSORICON_FindBestIconFile( CURSORICONFILEDIR *d return &dir->idEntries[n]; } +/*********************************************************************** + * stretch_blt_icon + * + * A helper function that stretches a bitmap buffer into an HBITMAP. + * + * PARAMS + * hDest [I] The handle of the destination bitmap. + * pDestInfo [I] The BITMAPINFO of the destination bitmap. + * pSrcInfo [I] The BITMAPINFO of the source bitmap. + * pSrcBits [I] A pointer to the source bitmap buffer. + **/ +static BOOL stretch_blt_icon(HBITMAP hDest, BITMAPINFO *pDestInfo, BITMAPINFO *pSrcInfo, char *pSrcBits) +{ + HBITMAP hOld; + BOOL res = FALSE; + static HDC hdcMem = NULL; + + if (!hdcMem) + hdcMem = CreateCompatibleDC(screen_dc); + + if (hdcMem) + { + hOld = SelectObject(hdcMem, hDest); + res = StretchDIBits(hdcMem, + 0, 0, pDestInfo->bmiHeader.biWidth, pDestInfo->bmiHeader.biHeight, + 0, 0, pSrcInfo->bmiHeader.biWidth, pSrcInfo->bmiHeader.biHeight, + pSrcBits, pSrcInfo, DIB_RGB_COLORS, SRCCOPY); + SelectObject(hdcMem, hOld); + } + + return res; +} + static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, POINT16 hotspot, BOOL bIcon, DWORD dwVersion, @@ -666,7 +699,6 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, UINT cFlag ) { HGLOBAL16 hObj; - static HDC hdcMem; int sizeAnd, sizeXor; HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */ BITMAP bmpXor, bmpAnd; @@ -706,7 +738,7 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL ); if (screen_dc) { - BITMAPINFO* pInfo; + BITMAPINFO *pSrcInfo, *pDestInfo; /* Make sure we have room for the monochrome bitmap later on. * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same @@ -719,40 +751,78 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, * BYTE icAND[] // DIB bits for AND mask */ - if ((pInfo = HeapAlloc( GetProcessHeap(), 0, - max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD))))) + pSrcInfo = HeapAlloc( GetProcessHeap(), 0, + max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD))); + pDestInfo = HeapAlloc( GetProcessHeap(), 0, + max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD))); + if (pSrcInfo && pDestInfo) { - memcpy( pInfo, bmi, size ); - pInfo->bmiHeader.biHeight /= 2; + memcpy( pSrcInfo, bmi, size ); + pSrcInfo->bmiHeader.biHeight /= 2; + memcpy( pDestInfo, bmi, size ); + + pDestInfo->bmiHeader.biWidth = width; + pDestInfo->bmiHeader.biHeight = height; + pDestInfo->bmiHeader.biSizeImage = 0; /* Create the XOR bitmap */ + if(pSrcInfo->bmiHeader.biBitCount == 32) + { + UINT32 *dibBuffer = NULL; + + pDestInfo->bmiHeader.biSizeImage = get_dib_width_bytes( pDestInfo->bmiHeader.biWidth, + pDestInfo->bmiHeader.biBitCount ) * abs( pDestInfo->bmiHeader.biHeight ); + + /* If this is a 32-bpp bitmap, we need to use a dib section + so that the alpha channel is preserved */ + hXorBits = CreateDIBSection(screen_dc, pDestInfo, DIB_RGB_COLORS, (void**)&dibBuffer, NULL, 0); - if (DoStretch) { - hXorBits = CreateCompatibleBitmap(screen_dc, width, height); if(hXorBits) { - HBITMAP hOld; - BOOL res = FALSE; - - if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc); - if (hdcMem) { - hOld = SelectObject(hdcMem, hXorBits); - res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0, - bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2, - (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY); - SelectObject(hdcMem, hOld); + if(DoStretch) + { + if(pSrcInfo->bmiHeader.biBitCount == 32) + { + /* FIXME: StretchDIBits currently draws via X11, which does + * not preserve the alpha channel. + */ + FIXME("StretchDIBits will not preserve the alpha channel.\n"); + } + + if (!stretch_blt_icon(hXorBits, pDestInfo, pSrcInfo, (char*)bmi + size)) + { + DeleteObject(hXorBits); + hXorBits = 0; + } + } + else + { + if(dibBuffer) + memcpy(dibBuffer, (char*)bmi + size, pDestInfo->bmiHeader.biSizeImage); + else + { + DeleteObject(hXorBits); + hXorBits = 0; + ERR("dibBuffer should not have been NULL"); + } + } + } + } + else + { + if(DoStretch) + { + hXorBits = CreateCompatibleBitmap(screen_dc, width, height); + + if (!stretch_blt_icon(hXorBits, pDestInfo, pSrcInfo, (char*)bmi + size)) + { + DeleteObject(hXorBits); + hXorBits = 0; + } } - if (!res) { DeleteObject(hXorBits); hXorBits = 0; } - } - } else { - if (is_dib_monochrome(bmi)) { - hXorBits = CreateBitmap(width, height, 1, 1, NULL); - SetDIBits(screen_dc, hXorBits, 0, height, - (char*)bmi + size, pInfo, DIB_RGB_COLORS); - } - else - hXorBits = CreateDIBitmap(screen_dc, &pInfo->bmiHeader, - CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS); + else + hXorBits = CreateDIBitmap(screen_dc, &pSrcInfo->bmiHeader, + CBM_INIT, (char*)bmi + size, pSrcInfo, DIB_RGB_COLORS); } if( hXorBits ) @@ -761,19 +831,19 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, get_dib_width_bytes( bmi->bmiHeader.biWidth, bmi->bmiHeader.biBitCount ) * abs( bmi->bmiHeader.biHeight ) / 2; - pInfo->bmiHeader.biBitCount = 1; - if (pInfo->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) + pSrcInfo->bmiHeader.biBitCount = 1; + if (pSrcInfo->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) { - RGBQUAD *rgb = pInfo->bmiColors; + RGBQUAD *rgb = pSrcInfo->bmiColors; - pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2; + pSrcInfo->bmiHeader.biClrUsed = pSrcInfo->bmiHeader.biClrImportant = 2; rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00; rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff; rgb[0].rgbReserved = rgb[1].rgbReserved = 0; } else { - RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1); + RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pSrcInfo) + 1); rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00; rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff; @@ -783,29 +853,24 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, if (DoStretch) { if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) { - HBITMAP hOld; - BOOL res = FALSE; - - if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc); - if (hdcMem) { - hOld = SelectObject(hdcMem, hAndBits); - res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0, - pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight, - xbits, pInfo, DIB_RGB_COLORS, SRCCOPY); - SelectObject(hdcMem, hOld); + if (!stretch_blt_icon(hAndBits, pDestInfo, pSrcInfo, xbits)) + { + DeleteObject(hAndBits); + hAndBits = 0; } - if (!res) { DeleteObject(hAndBits); hAndBits = 0; } } } else { hAndBits = CreateBitmap(width, height, 1, 1, NULL); if (hAndBits) SetDIBits(screen_dc, hAndBits, 0, height, - xbits, pInfo, DIB_RGB_COLORS); + xbits, pSrcInfo, DIB_RGB_COLORS); } if( !hAndBits ) DeleteObject( hXorBits ); } - HeapFree( GetProcessHeap(), 0, pInfo ); + + HeapFree( GetProcessHeap(), 0, pSrcInfo ); + HeapFree( GetProcessHeap(), 0, pDestInfo ); } } -- 1.6.0.4