Joel Holdsworth : user32: Fixed CURSORICON_CreateIconFromBMI to preserve the alpha channel.

Alexandre Julliard julliard at winehq.org
Mon Oct 5 09:54:30 CDT 2009


Module: wine
Branch: master
Commit: c2202929ab4b6d1ce379865dfd8904186814f265
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c2202929ab4b6d1ce379865dfd8904186814f265

Author: Joel Holdsworth <joel at airwebreathe.org.uk>
Date:   Mon Jun 29 19:10:36 2009 +0100

user32: Fixed CURSORICON_CreateIconFromBMI to preserve the alpha channel.

---

 dlls/user32/cursoricon.c |  147 +++++++++++++++++++++++++++-------------------
 1 files changed, 87 insertions(+), 60 deletions(-)

diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c
index 23de6a5..a74b79d 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,12 +699,11 @@ 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;
-    BOOL DoStretch;
     INT size;
+    BITMAPINFO *pSrcInfo, *pDestInfo;
 
     if (dwVersion == 0x00020000)
     {
@@ -693,11 +725,10 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi,
 
     if (!width) width = bmi->bmiHeader.biWidth;
     if (!height) height = bmi->bmiHeader.biHeight/2;
-    DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
-      (bmi->bmiHeader.biWidth != width);
 
     /* Scale the hotspot */
-    if (DoStretch && hotspot.x != ICON_HOTSPOT && hotspot.y != ICON_HOTSPOT)
+    if (((bmi->bmiHeader.biHeight/2 != height) || (bmi->bmiHeader.biWidth != width)) &&
+        hotspot.x != ICON_HOTSPOT && hotspot.y != ICON_HOTSPOT)
     {
         hotspot.x = (hotspot.x * width) / bmi->bmiHeader.biWidth;
         hotspot.y = (hotspot.y * height) / (bmi->bmiHeader.biHeight / 2);
@@ -706,8 +737,6 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi,
     if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL );
     if (screen_dc)
     {
-        BITMAPINFO* pInfo;
-
         /* Make sure we have room for the monochrome bitmap later on.
          * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
          * up to and including the biBitCount. In-memory icon resource
@@ -719,40 +748,47 @@ 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)
+            {
+                void *pDIBBuffer = NULL;
+                hXorBits = CreateDIBSection(screen_dc, pDestInfo, DIB_RGB_COLORS, &pDIBBuffer, NULL, 0);
 
-            if (DoStretch) {
+                if(hXorBits)
+                {
+                    if (!stretch_blt_icon(hXorBits, pDestInfo, pSrcInfo, (char*)bmi + size))
+                    {
+                        DeleteObject(hXorBits);
+                        hXorBits = 0;
+                    }
+                }
+            }
+            else
+            {
                 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(!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); 
             }
 
             if( hXorBits )
@@ -761,51 +797,42 @@ 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;
                 }
 
                 /* Create the AND bitmap */
+                hAndBits = CreateBitmap(width, height, 1, 1, NULL);
 
-            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);
 
+                if( !hAndBits )
+                {
+                    DeleteObject( hXorBits );
+                    hXorBits = 0;
+                }
             }
-                if( !hAndBits ) DeleteObject( hXorBits );
-            }
-            HeapFree( GetProcessHeap(), 0, pInfo );
+
+            HeapFree( GetProcessHeap(), 0, pSrcInfo );
+            HeapFree( GetProcessHeap(), 0, pDestInfo );
         }
     }
 




More information about the wine-cvs mailing list