[PATCH] Added DrawIconEx alpha blending support

Joel Holdsworth joel at airwebreathe.org.uk
Sun May 31 10:52:48 CDT 2009


---
 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


--=-ah4Y+4JJYEJgspfhD/dk--





More information about the wine-patches mailing list