]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/bitmap.cpp
update to make digitalmars compile/link make clean
[wxWidgets.git] / src / msw / bitmap.cpp
index 0202599afb6719db718e4c7dc9a68324d3fb8412..b34424a5fe1410cace71e3aa86fa0c28755b0f26 100644 (file)
@@ -100,10 +100,18 @@ public:
     wxDC         *m_selectedInto;
 #endif // __WXDEBUG__
 
+    // when GetRawData() is called for a DDB we need to convert it to a DIB
+    // first to be able to provide direct access to it and we cache that DIB
+    // here and convert it back to DDB when UngetRawData() is called
+    wxDIB *m_dib;
+
     // true if we have alpha transparency info and can be drawn using
     // AlphaBlend()
     bool m_hasAlpha;
 
+    // true if our HBITMAP is a DIB section, false if it is a DDB
+    bool m_isDIB;
+
 private:
     // optional mask for transparent drawing
     wxMask       *m_bitmapMask;
@@ -162,7 +170,11 @@ wxBitmapRefData::wxBitmapRefData()
     m_selectedInto = NULL;
 #endif
     m_bitmapMask = NULL;
+
     m_hBitmap = (WXHBITMAP) NULL;
+    m_dib = NULL;
+
+    m_isDIB =
     m_hasAlpha = FALSE;
 }
 
@@ -171,6 +183,8 @@ void wxBitmapRefData::Free()
     wxASSERT_MSG( !m_selectedInto,
                   wxT("deleting bitmap still selected into wxMemoryDC") );
 
+    wxASSERT_MSG( !m_dib, _T("forgot to call wxBitmap::UngetRawData()!") );
+
     if ( m_hBitmap)
     {
         if ( !::DeleteObject((HBITMAP)m_hBitmap) )
@@ -434,6 +448,13 @@ wxBitmap::wxBitmap(int w, int h, int d)
     (void)Create(w, h, d);
 }
 
+wxBitmap::wxBitmap(int w, int h, const wxDC& dc)
+{
+    Init();
+
+    (void)Create(w, h, dc);
+}
+
 wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
 {
     Init();
@@ -486,6 +507,7 @@ bool wxBitmap::DoCreate(int w, int h, int d, WXHDC hdc)
         // don't delete the DIB section in dib object dtor
         hbmp = dib.Detach();
 
+        GetBitmapData()->m_isDIB = TRUE;
         GetBitmapData()->m_depth = d;
     }
     else // create a DDB
@@ -771,6 +793,7 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc )
         // don't delete the DIB section in dib object dtor
         hbitmap = dib.Detach();
 
+        refData->m_isDIB = TRUE;
         refData->m_depth = dib.GetDepth();
     }
     else // we need to convert DIB to DDB
@@ -1172,10 +1195,38 @@ bool wxBitmap::GetRawData(wxRawBitmapData *data)
         return FALSE;
     }
 
-    // we only support raw access to the DIBs, so check if we have one
+    // if we're already a DIB we can access our data directly, but if not we
+    // need to convert this DDB to a DIB section and use it for raw access and
+    // then convert it back
+    HBITMAP hDIB;
+    if ( !GetBitmapData()->m_isDIB )
+    {
+        wxCHECK_MSG( !GetBitmapData()->m_dib, FALSE,
+                        _T("GetRawData() may be called only once") );
+
+        wxDIB *dib = new wxDIB(*this);
+        if ( !dib->IsOk() )
+        {
+            delete dib;
+
+            return FALSE;
+        }
+
+        // we'll free it in UngetRawData()
+        GetBitmapData()->m_dib = dib;
+
+        hDIB = dib->GetHandle();
+    }
+    else // we're a DIB
+    {
+        hDIB = GetHbitmap();
+    }
+
     DIBSECTION ds;
-    if ( !::GetObject(GetHbitmap(), sizeof(ds), &ds) )
+    if ( ::GetObject(hDIB, sizeof(ds), &ds) != sizeof(DIBSECTION) )
     {
+        wxFAIL_MSG( _T("failed to get DIBSECTION from a DIB?") );
+
         return FALSE;
     }
 
@@ -1202,6 +1253,17 @@ void wxBitmap::UngetRawData(wxRawBitmapData *data)
 {
     wxCHECK_RET( data, _T("NULL pointer in wxBitmap::UngetRawData()") );
 
+    if ( !Ok() )
+        return;
+
+    if ( !*data )
+    {
+        // invalid data, don't crash -- but don't assert neither as we're
+        // called automatically from wxRawBitmapData dtor and so there is no
+        // way to prevent this from happening
+        return;
+    }
+
     // AlphaBlend() wants to have premultiplied source alpha but wxRawBitmap
     // API uses normal, not premultiplied, colours, so adjust them here now
     wxRawBitmapIterator p(*data);
@@ -1217,9 +1279,9 @@ void wxBitmap::UngetRawData(wxRawBitmapData *data)
         {
             const unsigned alpha = p.Alpha();
 
-            p.Red() = (p.Red() * alpha) / 255;
-            p.Blue() = (p.Blue() * alpha) / 255;
-            p.Green() = (p.Green() * alpha) / 255;
+            p.Red() = (p.Red() * alpha + 127) / 255;
+            p.Blue() = (p.Blue() * alpha + 127) / 255;
+            p.Green() = (p.Green() * alpha + 127) / 255;
 
             ++p;
         }
@@ -1227,6 +1289,18 @@ void wxBitmap::UngetRawData(wxRawBitmapData *data)
         p = rowStart;
         p.OffsetY(1);
     }
+
+    // if we're a DDB we need to convert DIB back to DDB now to make the
+    // changes made via wxRawBitmapData effective
+    if ( !GetBitmapData()->m_isDIB )
+    {
+        wxDIB *dib = GetBitmapData()->m_dib;
+        GetBitmapData()->m_dib = NULL;
+
+        // TODO: convert
+
+        delete dib;
+    }
 }
 
 // ----------------------------------------------------------------------------