]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/dib.cpp
Fixed bug [ 1195479 ] RedrawWindow() incompatible with eVC3
[wxWidgets.git] / src / msw / dib.cpp
index 8da2f37757c6f6934244972b3d857f63b8e7d902..1a57decc31716919a0a84471a63faaa121c1a3a9 100644 (file)
     #include <memory.h>
 #endif
 
-#ifdef __GNUWIN32_OLD__
-    #include "wx/msw/gnuwin32/extra.h"
-#endif
-
 #include "wx/image.h"
 #include "wx/msw/dib.h"
 
@@ -69,7 +65,7 @@ static inline WORD GetNumberOfColours(WORD bitsPerPixel)
 {
     // only 1, 4 and 8bpp bitmaps use palettes (well, they could be used with
     // 24bpp ones too but we don't support this as I think it's quite uncommon)
-    return bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0;
+    return (WORD)(bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0);
 }
 
 // wrapper around ::GetObject() for DIB sections
@@ -118,7 +114,7 @@ bool wxDIB::Create(int width, int height, int depth)
     info->bmiHeader.biHeight = height;
 
     info->bmiHeader.biPlanes = 1;
-    info->bmiHeader.biBitCount = depth;
+    info->bmiHeader.biBitCount = (WORD)depth;
     info->bmiHeader.biSizeImage = GetLineSize(width, depth)*height;
 
     m_handle = ::CreateDIBSection
@@ -151,10 +147,18 @@ bool wxDIB::Create(const wxBitmap& bmp)
 {
     wxCHECK_MSG( bmp.Ok(), false, _T("wxDIB::Create(): invalid bitmap") );
 
+    if ( !Create(GetHbitmapOf(bmp)) )
+        return false;
+
+    m_hasAlpha = bmp.HasAlpha();
+
+    return true;
+}
+
+bool wxDIB::Create(HBITMAP hbmp)
+{
     // this bitmap could already be a DIB section in which case we don't need
     // to convert it to DIB
-    HBITMAP hbmp = GetHbitmapOf(bmp);
-
     DIBSECTION ds;
     if ( GetDIBSection(hbmp, &ds) )
     {
@@ -172,13 +176,20 @@ bool wxDIB::Create(const wxBitmap& bmp)
     }
     else // no, it's a DDB -- convert it to DIB
     {
-        const int w = bmp.GetWidth();
-        const int h = bmp.GetHeight();
-        int d = bmp.GetDepth();
+        // prepare all the info we need
+        BITMAP bm;
+        if ( !::GetObject(hbmp, sizeof(bm), &bm) )
+        {
+            wxLogLastError(wxT("GetObject(bitmap)"));
+
+            return false;
+        }
+
+        int d = bm.bmBitsPixel;
         if ( d <= 0 )
             d = wxDisplayDepth();
 
-        if ( !Create(w, h, d) || !CopyFromDDB(hbmp) )
+        if ( !Create(bm.bmWidth, bm.bmHeight, d) || !CopyFromDDB(hbmp) )
             return false;
     }
 
@@ -588,7 +599,7 @@ wxPalette *wxDIB::CreatePalette() const
 
     // initialize the palette header
     pPalette->palVersion = 0x300;  // magic number, not in docs but works
-    pPalette->palNumEntries = biClrUsed;
+    pPalette->palNumEntries = (WORD)biClrUsed;
 
     // and the colour table (it starts right after the end of the header)
     const RGBQUAD *pRGB = (RGBQUAD *)((char *)&ds.dsBmih + ds.dsBmih.biSize);
@@ -634,8 +645,8 @@ bool wxDIB::Create(const wxImage& image)
 
     // if we have alpha channel, we need to create a 32bpp RGBA DIB, otherwise
     // a 24bpp RGB is sufficient
-    const bool hasAlpha = image.HasAlpha();
-    const int bpp = hasAlpha ? 32 : 24;
+    m_hasAlpha = image.HasAlpha();
+    const int bpp = m_hasAlpha ? 32 : 24;
 
     if ( !Create(w, h, bpp) )
         return false;
@@ -645,23 +656,37 @@ bool wxDIB::Create(const wxImage& image)
     const int srcBytesPerLine = w * 3;
     const int dstBytesPerLine = GetLineSize(w, bpp);
     const unsigned char *src = image.GetData() + ((h - 1) * srcBytesPerLine);
-    const unsigned char *alpha = hasAlpha ? image.GetAlpha() + (h - 1)*w : NULL;
+    const unsigned char *alpha = m_hasAlpha ? image.GetAlpha() + (h - 1)*w
+                                            : NULL;
     unsigned char *dstLineStart = (unsigned char *)m_data;
     for ( int y = 0; y < h; y++ )
     {
         // copy one DIB line
         unsigned char *dst = dstLineStart;
-        for ( int x = 0; x < w; x++ )
+        if ( alpha )
         {
-            // also, the order of RGB is inversed for DIBs
-            *dst++ = src[2];
-            *dst++ = src[1];
-            *dst++ = src[0];
-
-            src += 3;
-
-            if ( alpha )
-                *dst++ = *alpha++;
+            for ( int x = 0; x < w; x++ )
+            {
+                // RGB order is reversed, and we need to premultiply
+                // all channels by alpha value for use with ::AlphaBlend.
+                const unsigned char a = *alpha++;
+                *dst++ = (unsigned char)((src[2] * a + 127) / 255);
+                *dst++ = (unsigned char)((src[1] * a + 127) / 255);
+                *dst++ = (unsigned char)((src[0] * a + 127) / 255);
+                *dst++ = a;
+                src += 3;
+            }
+        }
+        else // no alpha channel
+        {
+            for ( int x = 0; x < w; x++ )
+            {
+                // RGB order is reversed.
+                *dst++ = src[2];
+                *dst++ = src[1];
+                *dst++ = src[0];
+                src += 3;
+            }
         }
 
         // pass to the previous line in the image
@@ -691,19 +716,20 @@ wxImage wxDIB::ConvertToImage() const
         return wxNullImage;
     }
 
-    const int bpp = GetDepth();
-    if ( bpp == 32 )
+    if ( m_hasAlpha )
     {
         image.SetAlpha();
     }
 
     // this is the same loop as in Create() just above but with copy direction
     // reversed
+    const int bpp = GetDepth();
     const int dstBytesPerLine = w * 3;
     const int srcBytesPerLine = GetLineSize(w, bpp);
     unsigned char *dst = image.GetData() + ((h - 1) * dstBytesPerLine);
     unsigned char *alpha = image.HasAlpha() ? image.GetAlpha() + (h - 1)*w
                                             : NULL;
+    const bool is32bit = bpp == 32;
     const unsigned char *srcLineStart = (unsigned char *)GetData();
     for ( int y = 0; y < h; y++ )
     {
@@ -717,8 +743,12 @@ wxImage wxDIB::ConvertToImage() const
 
             dst += 3;
 
-            if ( alpha )
-                *alpha++ = *src++;
+            if ( is32bit )
+            {
+                if ( alpha )
+                    *alpha++ = *src;
+                src++;
+            }
         }
 
         // pass to the previous line in the image