X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/907173e51df6d2a91d65463ddf6ce810d3fd921a..c0badb709a86b91a203416784b649e3d00c699c7:/src/msw/bitmap.cpp?ds=sidebyside diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index 16e23a409d..789fc53acf 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" @@ -38,10 +34,10 @@ #include "wx/dcmemory.h" #include "wx/bitmap.h" #include "wx/icon.h" + #include "wx/log.h" #endif #include "wx/msw/private.h" -#include "wx/log.h" #if wxUSE_WXDIB #include "wx/msw/dib.h" @@ -245,12 +241,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; @@ -310,10 +300,37 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor; - // the mask returned by GetIconInfo() is inversed compared to the usual - // wxWin convention - refData->SetMask(wxInvertMask(iconInfo.hbmMask, w, h)); - +#if wxUSE_WXDIB + // If the icon is 32 bits per pixel then it may have alpha channel data, + // although there are some icons that are 32 bpp but have no alpha... So + // convert to a DIB and manually check the 4th byte for each pixel. + BITMAP bm; + if ( ::GetObject(iconInfo.hbmColor, sizeof(BITMAP), (LPVOID)&bm) + && bm.bmBitsPixel == 32) + { + wxDIB dib(iconInfo.hbmColor); + if (dib.IsOk()) + { + unsigned char* pixels = dib.GetData(); + for (int idx=0; idxm_hasAlpha = true; + break; + } + } + } + } +#endif + if ( !refData->m_hasAlpha ) + { + // the mask returned by GetIconInfo() is inverted compared to the usual + // wxWin convention + refData->SetMask(wxInvertMask(iconInfo.hbmMask, w, h)); + } // delete the old one now as we don't need it any more ::DeleteObject(iconInfo.hbmMask); @@ -393,8 +410,6 @@ wxBitmap::~wxBitmap() wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) { - Init(); - #ifndef __WXMICROWIN__ wxBitmapRefData *refData = new wxBitmapRefData; m_refData = refData; @@ -408,7 +423,7 @@ wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) { // we assume that it is in XBM format which is not quite the same as // the format CreateBitmap() wants because the order of bytes in the - // line is inversed! + // line is reversed! const size_t bytesPerLine = (width + 7) / 8; const size_t padding = bytesPerLine % 2; const size_t len = height * ( padding + bytesPerLine ); @@ -460,14 +475,12 @@ wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) // 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") ) +#if wxUSE_IMAGE && wxUSE_XPM && wxUSE_WXDIB + 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") ) + wxCHECK_MSG( img.Ok(), false, wxT("invalid bitmap data") ); *this = wxBitmap(img); return true; @@ -479,29 +492,21 @@ bool wxBitmap::CreateFromXpm(const char **data) 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) { - Init(); - (void)Create(data, type, width, height, depth); } wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type) { - Init(); - LoadFile(filename, (int)type); } @@ -775,8 +780,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); @@ -790,6 +793,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") ); @@ -804,6 +809,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; @@ -826,14 +833,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 @@ -843,9 +850,42 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) // finally also set the mask if we have one if ( image.HasMask() ) { - SetMask(new wxMask(*this, wxColour(image.GetMaskRed(), - image.GetMaskGreen(), - image.GetMaskBlue()))); + const size_t len = 2*((w+15)/16); + BYTE *src = image.GetData(); + BYTE *data = new BYTE[h*len]; + memset(data, 0, h*len); + BYTE r = image.GetMaskRed(), + g = image.GetMaskGreen(), + b = image.GetMaskBlue(); + BYTE *dst = data; + for ( int y = 0; y < h; y++, dst += len ) + { + BYTE *dstLine = dst; + BYTE mask = 0x80; + for ( int x = 0; x < w; x++, src += 3 ) + { + if (src[0] != r || src[1] != g || src[2] != b) + *dstLine |= mask; + + if ( (mask >>= 1) == 0 ) + { + dstLine++; + mask = 0x80; + } + } + } + + hbitmap = ::CreateBitmap(w, h, 1, 1, data); + if ( !hbitmap ) + { + wxLogLastError(_T("CreateBitmap(mask)")); + } + else + { + SetMask(new wxMask((WXHBITMAP)hbitmap)); + } + + delete[] data; } return true; @@ -934,7 +974,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 @@ -954,7 +1009,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; @@ -998,7 +1053,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? @@ -1031,7 +1086,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, @@ -1092,6 +1147,15 @@ wxMask *wxBitmap::GetMask() const return GetBitmapData() ? GetBitmapData()->GetMask() : (wxMask *) NULL; } +wxBitmap wxBitmap::GetMaskBitmap() const +{ + wxBitmap bmp; + wxMask *mask = GetMask(); + if ( mask ) + bmp.SetHBITMAP(mask->GetMaskBitmap()); + return bmp; +} + #ifdef __WXDEBUG__ wxDC *wxBitmap::GetSelectedInto() const @@ -1181,7 +1245,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); @@ -1530,7 +1594,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; @@ -1570,7 +1634,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, @@ -1607,7 +1697,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;