X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/106c33bb1d7a35d1fa7fb8ce338c186beb0b2930..249aad307f8396980986481ef17bebe966a91ab3:/src/msw/bitmap.cpp diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index 0202599afb..b34424a5fe 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -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; + } } // ----------------------------------------------------------------------------