[PATCH] Added DrawIcon alpha blending support

Joel Holdsworth joel at airwebreathe.org.uk
Sun May 31 10:55:39 CDT 2009


---
 dlls/user32/cursoricon.c       |   63 +++++++++++++++++++++++++++++++++-------
 dlls/user32/tests/cursoricon.c |   20 +++++-------
 2 files changed, 60 insertions(+), 23 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 26c533b..1e6d87e 100644
--- a/dlls/user32/tests/cursoricon.c
+++ b/dlls/user32/tests/cursoricon.c
@@ -1090,26 +1090,22 @@ static void test_DrawIcon(void)
     /* Test alpha blending */
     /* Windows 2000 and up will alpha blend, earlier Windows versions will not */
     check_DrawIcon(hdcDst, FALSE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
+    check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
 
-    todo_wine
-    {
-        check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
+    check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
+    check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
+    check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
+    check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
 
-        check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
-        check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
-        check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
-        check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
-
-        check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
-        check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
-    }
+    check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
+    check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __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__);
 
     SelectObject(hdcDst, bmpOld);
     DeleteObject(bmpDst);
-- 
1.6.0.4


--=-wHfc5bh04b1Uhs1Id98H--





More information about the wine-patches mailing list