[SHELL32]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 5 Aug 2010 14:42:56 +0000 (14:42 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 5 Aug 2010 14:42:56 +0000 (14:42 +0000)
When creating a shortcut icon and we have 32 bpp, use GdiAlphaBlend to create the final bitmap. This is neccessary, since we want to support alpha channels and those are destroyed when using SRCPAINT or any similar ROPs on the alpha bitmap (not a bug, Windows works like that, too). We could use MaskBlt, if it would work correctly, but on reactos it destroys the alpha channel as well (bug!), it's also most likely slower then the current solution.
Fixes broken overlay icons.
See issue #5455 for more details.

svn path=/trunk/; revision=48463

reactos/dll/win32/shell32/iconcache.c

index bc3ea24..41883ac 100644 (file)
@@ -171,25 +171,40 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
          goto fail;
        }
 
-       /* Copy the source xor bitmap to the target and clear out part of it by using
-          the shortcut mask */
+       /* Copy the source color bitmap to the target */
        if (! BitBlt(TargetDC, 0, 0, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmHeight,
-                    SourceDC, 0, 0, SRCCOPY) ||
-           ! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
-                    ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
-                    ShortcutDC, 0, 0, SRCAND))
+                    SourceDC, 0, 0, SRCCOPY)) goto fail;
+
+       /* Check if we can use alpha blending */
+       if (ShortcutBitmapInfo.bmBitsPixel == 32)
        {
-         goto fail;
+               /* Use alpha blending to make sure the target alpha channel stays valid */
+               if (NULL == SelectObject(ShortcutDC, ShortcutIconInfo.hbmColor)) goto fail;
+               if (!GdiAlphaBlend(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
+                               ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
+                               ShortcutDC, 0, 0, ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
+                               (BLENDFUNCTION){AC_SRC_OVER, 0, 255, AC_SRC_ALPHA})) goto fail;
        }
-
-       if (NULL == SelectObject(ShortcutDC, ShortcutIconInfo.hbmColor)) goto fail;
-
-       /* Now put in the shortcut xor mask */
-       if (! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
-                    ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
-                    ShortcutDC, 0, 0, SRCINVERT))
+       else
        {
-         goto fail;
+               /* Copy the source xor bitmap to the target and clear out part of it by using
+                  the shortcut mask */
+               if (! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
+                            ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
+                        ShortcutDC, 0, 0, SRCAND))
+               {
+                       goto fail;
+               }
+
+               if (NULL == SelectObject(ShortcutDC, ShortcutIconInfo.hbmColor)) goto fail;
+
+               /* Now put in the shortcut xor mask */
+               if (! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
+                            ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
+                        ShortcutDC, 0, 0, SRCINVERT))
+               {
+                       goto fail;
+               }
        }
 
        /* Clean up, we're not goto'ing to 'fail' after this so we can be lazy and not set
@@ -387,14 +402,14 @@ BOOL SIC_Initialize(void)
     if (sic_hdpa)
     {
         TRACE("Icon cache already initialized\n");
-        return TRUE;
+         return TRUE;
     }
 
-    sic_hdpa = DPA_Create(16);
-    if (!sic_hdpa)
-    {
+       sic_hdpa = DPA_Create(16);
+       if (!sic_hdpa)
+       {
         return FALSE;
-    }
+       }
 
     hDC = CreateICW(L"DISPLAY", NULL, NULL, NULL);
     if (!hDC)
@@ -439,7 +454,7 @@ BOOL SIC_Initialize(void)
                                         100);
     if (ShellSmallIconList)
     {
-         /* Load the document icon, which is used as the default if an icon isn't found. */
+        /* Load the document icon, which is used as the default if an icon isn't found. */
         hSm = (HICON)LoadImageW(shell32_hInstance,
                                 MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT),
                                 IMAGE_ICON,
@@ -459,7 +474,7 @@ BOOL SIC_Initialize(void)
     }
 
     if (ShellBigIconList)
-    {
+        {
         hLg = (HICON)LoadImageW(shell32_hInstance,
                                 MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT),
                                 IMAGE_ICON,
@@ -470,7 +485,7 @@ BOOL SIC_Initialize(void)
         {
             ERR("Failed to load IDI_SHELL_DOCUMENT icon2!\n");
             DestroyIcon(hSm);
-            return FALSE;
+          return FALSE;
         }
     }
     else
@@ -482,9 +497,9 @@ BOOL SIC_Initialize(void)
     SIC_IconAppend(swShell32Name, IDI_SHELL_DOCUMENT-1, hSm, hLg, 0);
     SIC_IconAppend(swShell32Name, -IDI_SHELL_DOCUMENT, hSm, hLg, 0);
 
-    TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList);
+       TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList);
 
-    return TRUE;
+       return TRUE;
 }
 /*************************************************************************
  * SIC_Destroy
@@ -550,7 +565,7 @@ static int SIC_LoadOverlayIcon(int icon_idx)
                LPWSTR p = wcschr(buffer, ',');
 
                if (p)
-                   *p++ = 0;
+               *p++ = 0;
 
                iconPath = buffer;
                iconIdx = _wtoi(p);