X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3103e8a97e834e9793f0eb149aa82a99fd64ef9a..633566f6ef1729066b478918d963762f90dbae37:/src/msw/bitmap.cpp?ds=inline diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index bfcddabf48..8ef2b8b3f3 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////////// -// Name: bitmap.cpp +// Name: src/msw/bitmap.cpp // Purpose: wxBitmap // Author: Julian Smart // Modified by: @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "bitmap.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -28,6 +24,8 @@ #pragma hdrstop #endif +#include "wx/bitmap.h" + #ifndef WX_PRECOMP #include @@ -36,22 +34,19 @@ #include "wx/app.h" #include "wx/palette.h" #include "wx/dcmemory.h" - #include "wx/bitmap.h" #include "wx/icon.h" + #include "wx/log.h" + #include "wx/image.h" #endif #include "wx/msw/private.h" -#include "wx/log.h" #if wxUSE_WXDIB -#include "wx/msw/dib.h" + #include "wx/msw/dib.h" #endif -#include "wx/image.h" -#include "wx/xpmdecod.h" - #ifdef wxHAVE_RAW_BITMAP -#include "wx/rawbmp.h" + #include "wx/rawbmp.h" #endif // missing from mingw32 header @@ -210,8 +205,13 @@ wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData& data) m_selectedInto = NULL; #endif - // can't copy the mask as the other bitmap destroys it + // (deep) copy the mask if present m_bitmapMask = NULL; + if (data.m_bitmapMask) + m_bitmapMask = new wxMask(*data.m_bitmapMask); + + // FIXME: we don't copy m_hBitmap currently but we should, see wxBitmap:: + // CloneRefData() wxASSERT_MSG( !data.m_isDIB, _T("can't copy bitmap locked for raw access!") ); @@ -245,12 +245,6 @@ void wxBitmapRefData::Free() // wxBitmap creation // ---------------------------------------------------------------------------- -// this function should be called from all wxBitmap ctors -void wxBitmap::Init() -{ - // m_refData = NULL; done in the base class ctor -} - wxGDIImageRefData *wxBitmap::CreateData() const { return new wxBitmapRefData; @@ -263,6 +257,10 @@ wxObjectRefData *wxBitmap::CloneRefData(const wxObjectRefData *dataOrig) const if ( !data ) return NULL; + // FIXME: this method is backwards, it should just create a new + // wxBitmapRefData using its copy ctor but instead it modifies this + // bitmap itself and then returns its m_refData -- which works, of + // course (except in !wxUSE_WXDIB), but is completely illogical wxBitmap *self = wx_const_cast(wxBitmap *, this); #if wxUSE_WXDIB @@ -275,10 +273,19 @@ wxObjectRefData *wxBitmap::CloneRefData(const wxObjectRefData *dataOrig) const else #endif // wxUSE_WXDIB { - // don't copy the bitmap data, but do copy the size, depth, ... + // copy the bitmap data self->m_refData = new wxBitmapRefData(*data); } + // copy also the mask + wxMask * const maskSrc = data->GetMask(); + if ( maskSrc ) + { + wxBitmapRefData *selfdata = wx_static_cast(wxBitmapRefData *, m_refData); + + selfdata->SetMask(new wxMask(*maskSrc)); + } + return m_refData; } @@ -324,7 +331,7 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) unsigned char* pixels = dib.GetData(); for (int idx=0; idxSetMask(wxInvertMask(iconInfo.hbmMask, w, h)); } - + // delete the old one now as we don't need it any more ::DeleteObject(iconInfo.hbmMask); @@ -420,8 +427,6 @@ wxBitmap::~wxBitmap() wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) { - Init(); - #ifndef __WXMICROWIN__ wxBitmapRefData *refData = new wxBitmapRefData; m_refData = refData; @@ -456,7 +461,7 @@ wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) reversed |= (unsigned char)(val & 0x01); val >>= 1; } - *dst++ = reversed; + *dst++ = ~reversed; } if ( padding ) @@ -484,51 +489,23 @@ wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) #endif } -// Create from XPM data -bool wxBitmap::CreateFromXpm(const char **data) -{ -#if wxUSE_IMAGE && wxUSE_XPM - Init(); - - wxCHECK_MSG( data != NULL, false, wxT("invalid bitmap data") ) - - wxXPMDecoder decoder; - wxImage img = decoder.ReadData(data); - wxCHECK_MSG( img.Ok(), false, wxT("invalid bitmap data") ) - - *this = wxBitmap(img); - return true; -#else - wxUnusedVar(data); - return false; -#endif -} - wxBitmap::wxBitmap(int w, int h, int d) { - Init(); - (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) +wxBitmap::wxBitmap(const void* data, long type, int width, int height, int depth) { - Init(); - (void)Create(data, type, width, height, depth); } wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type) { - Init(); - LoadFile(filename, (int)type); } @@ -802,8 +779,6 @@ wxImage wxBitmap::ConvertToImage() const // wxImage to/from conversions // ---------------------------------------------------------------------------- -#if wxUSE_WXDIB - bool wxBitmap::CreateFromImage(const wxImage& image, int depth) { return CreateFromImage(image, depth, 0); @@ -817,6 +792,8 @@ bool wxBitmap::CreateFromImage(const wxImage& image, const wxDC& dc) return CreateFromImage(image, -1, dc.GetHDC()); } +#if wxUSE_WXDIB + bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) { wxCHECK_MSG( image.Ok(), false, wxT("invalid image") ); @@ -831,6 +808,8 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) if ( !dib.IsOk() ) return false; + if ( depth == -1 ) + depth = dib.GetDepth(); // Get depth from image if none specified // store the bitmap parameters wxBitmapRefData *refData = new wxBitmapRefData; @@ -853,14 +832,14 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) hbitmap = dib.Detach(); refData->m_isDIB = true; - refData->m_depth = dib.GetDepth(); + refData->m_depth = depth; } #ifndef ALWAYS_USE_DIB else // we need to convert DIB to DDB { hbitmap = dib.CreateDDB((HDC)hdc); - refData->m_depth = depth == -1 ? dib.GetDepth() : depth; + refData->m_depth = depth; } #endif // !ALWAYS_USE_DIB @@ -905,7 +884,7 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) SetMask(new wxMask((WXHBITMAP)hbitmap)); } - delete data; + delete[] data; } return true; @@ -994,7 +973,22 @@ wxImage wxBitmap::ConvertToImage() const return image; } -#endif // wxUSE_WXDIB +#else // !wxUSE_WXDIB + +bool +wxBitmap::CreateFromImage(const wxImage& WXUNUSED(image), + int WXUNUSED(depth), + WXHDC WXUNUSED(hdc)) +{ + return false; +} + +wxImage wxBitmap::ConvertToImage() const +{ + return wxImage(); +} + +#endif // wxUSE_WXDIB/!wxUSE_WXDIB #endif // wxUSE_IMAGE @@ -1014,7 +1008,7 @@ bool wxBitmap::LoadFile(const wxString& filename, long type) return handler->LoadFile(this, filename, type, -1, -1); } -#if wxUSE_IMAGE +#if wxUSE_IMAGE && wxUSE_WXDIB else // no bitmap handler found { wxImage image; @@ -1030,7 +1024,7 @@ bool wxBitmap::LoadFile(const wxString& filename, long type) return false; } -bool wxBitmap::Create(void *data, long type, int width, int height, int depth) +bool wxBitmap::Create(const void* data, long type, int width, int height, int depth) { UnRef(); @@ -1058,7 +1052,7 @@ bool wxBitmap::SaveFile(const wxString& filename, { return handler->SaveFile(this, filename, type, palette); } -#if wxUSE_IMAGE +#if wxUSE_IMAGE && wxUSE_WXDIB else // no bitmap handler found { // FIXME what about palette? shouldn't we use it? @@ -1091,7 +1085,7 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const #ifndef __WXMICROWIN__ // handle alpha channel, if any if (HasAlpha()) - ret.UseAlpha(); + ret.UseAlpha(); // copy bitmap data MemoryHDC dcSrc, @@ -1170,15 +1164,6 @@ wxDC *wxBitmap::GetSelectedInto() const #endif -#if WXWIN_COMPATIBILITY_2_4 - -int wxBitmap::GetQuality() const -{ - return 0; -} - -#endif // WXWIN_COMPATIBILITY_2_4 - void wxBitmap::UseAlpha() { if ( GetBitmapData() ) @@ -1222,14 +1207,6 @@ void wxBitmap::SetMask(wxMask *mask) GetBitmapData()->SetMask(mask); } -#if WXWIN_COMPATIBILITY_2_4 - -void wxBitmap::SetQuality(int WXUNUSED(quality)) -{ -} - -#endif // WXWIN_COMPATIBILITY_2_4 - // ---------------------------------------------------------------------------- // raw bitmap access support // ---------------------------------------------------------------------------- @@ -1250,7 +1227,7 @@ void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp) HBITMAP hDIB; if ( !GetBitmapData()->m_isDIB ) { - wxCHECK_MSG( !GetBitmapData()->m_dib, FALSE, + wxCHECK_MSG( !GetBitmapData()->m_dib, NULL, _T("GetRawData() may be called only once") ); wxDIB *dib = new wxDIB(*this); @@ -1351,6 +1328,39 @@ wxMask::wxMask() m_maskBitmap = 0; } +// Copy constructor +wxMask::wxMask(const wxMask &mask) + : wxObject() +{ + BITMAP bmp; + + HDC srcDC = CreateCompatibleDC(0); + HDC destDC = CreateCompatibleDC(0); + + // GetBitmapDimensionEx won't work if SetBitmapDimensionEx wasn't used + // so we'll use GetObject() API here: + if (::GetObject((HGDIOBJ)mask.m_maskBitmap, sizeof(bmp), &bmp) == 0) + { + wxFAIL_MSG(wxT("Cannot retrieve the dimensions of the wxMask to copy")); + return; + } + + // create our HBITMAP + int w = bmp.bmWidth, h = bmp.bmHeight; + m_maskBitmap = (WXHBITMAP)CreateCompatibleBitmap(srcDC, w, h); + + // copy the mask's HBITMAP into our HBITMAP + SelectObject(srcDC, (HBITMAP) mask.m_maskBitmap); + SelectObject(destDC, (HBITMAP) m_maskBitmap); + + BitBlt(destDC, 0, 0, w, h, srcDC, 0, 0, SRCCOPY); + + SelectObject(srcDC, 0); + DeleteDC(srcDC); + SelectObject(destDC, 0); + DeleteDC(destDC); +} + // Construct a mask from a bitmap and a colour indicating // the transparent area wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour) @@ -1516,13 +1526,13 @@ bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour) // ---------------------------------------------------------------------------- bool wxBitmapHandler::Create(wxGDIImage *image, - void *data, + const void* data, long flags, int width, int height, int depth) { wxBitmap *bitmap = wxDynamicCast(image, wxBitmap); - return bitmap ? Create(bitmap, data, flags, width, height, depth) : false; + return bitmap && Create(bitmap, data, flags, width, height, depth); } bool wxBitmapHandler::Load(wxGDIImage *image, @@ -1532,7 +1542,7 @@ bool wxBitmapHandler::Load(wxGDIImage *image, { wxBitmap *bitmap = wxDynamicCast(image, wxBitmap); - return bitmap ? LoadFile(bitmap, name, flags, width, height) : false; + return bitmap && LoadFile(bitmap, name, flags, width, height); } bool wxBitmapHandler::Save(wxGDIImage *image, @@ -1541,11 +1551,11 @@ bool wxBitmapHandler::Save(wxGDIImage *image, { wxBitmap *bitmap = wxDynamicCast(image, wxBitmap); - return bitmap ? SaveFile(bitmap, name, type) : false; + return bitmap && SaveFile(bitmap, name, type); } bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), - void *WXUNUSED(data), + const void* WXUNUSED(data), long WXUNUSED(type), int WXUNUSED(width), int WXUNUSED(height), @@ -1599,7 +1609,7 @@ bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel, // this value must be 1, 4, 8 or 24 so PixelDepth can only be lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel); lpDIBheader->bmiHeader.biCompression = BI_RGB; - lpDIBheader->bmiHeader.biSizeImage = xSize * abs(ySize) * bitsPerPixel >> 3; + lpDIBheader->bmiHeader.biSizeImage = (xSize * abs(ySize) * bitsPerPixel) >> 3; lpDIBheader->bmiHeader.biClrUsed = 256; @@ -1639,7 +1649,33 @@ HICON wxBitmapToIconOrCursor(const wxBitmap& bmp, return 0; } - wxMask *mask = bmp.GetMask(); + if ( bmp.HasAlpha() ) + { + // Create an empty mask bitmap. + // it doesn't seem to work if we mess with the mask at all. + HBITMAP hMonoBitmap = CreateBitmap(bmp.GetWidth(),bmp.GetHeight(),1,1,NULL); + + ICONINFO iconInfo; + wxZeroMemory(iconInfo); + iconInfo.fIcon = iconWanted; // do we want an icon or a cursor? + if ( !iconWanted ) + { + iconInfo.xHotspot = hotSpotX; + iconInfo.yHotspot = hotSpotY; + } + + iconInfo.hbmMask = hMonoBitmap; + iconInfo.hbmColor = GetHbitmapOf(bmp); + + HICON hicon = ::CreateIconIndirect(&iconInfo); + + ::DeleteObject(hMonoBitmap); + + return hicon; + } + + wxMask* mask = bmp.GetMask(); + if ( !mask ) { // we must have a mask for an icon, so even if it's probably incorrect, @@ -1676,7 +1712,7 @@ HICON wxBitmapToIconOrCursor(const wxBitmap& bmp, HICON hicon = ::CreateIconIndirect(&iconInfo); - if ( !bmp.GetMask() ) + if ( !bmp.GetMask() && !bmp.HasAlpha() ) { // we created the mask, now delete it delete mask;