X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d0ee33f5c6908b4ac5e1364381f0ef00942e3936..ac3688c0d8a39d200f0556ad4b401d89b45ff04a:/src/msw/bitmap.cpp diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index e41a8cf197..725d5fd0cb 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,20 @@ #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" +#include "wx/msw/dc.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 +206,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:: + // CloneGDIRefData() wxASSERT_MSG( !data.m_isDIB, _T("can't copy bitmap locked for raw access!") ); @@ -245,24 +246,22 @@ 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; } -wxObjectRefData *wxBitmap::CloneRefData(const wxObjectRefData *dataOrig) const +wxGDIRefData *wxBitmap::CloneGDIRefData(const wxGDIRefData *dataOrig) const { const wxBitmapRefData * data = wx_static_cast(const wxBitmapRefData *, dataOrig); 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,16 +274,25 @@ 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); } - return m_refData; -} + wxBitmapRefData * const + selfdata = wx_static_cast(wxBitmapRefData *, m_refData); -#ifdef __WIN32__ + // copy also the mask + wxMask * const maskSrc = data->GetMask(); + if ( maskSrc ) + { + selfdata->SetMask(new wxMask(*maskSrc)); + } + + return selfdata; +} -bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) +bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon, + wxBitmapTransparency transp) { #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // it may be either HICON or HCURSOR @@ -310,31 +318,51 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor; + switch ( transp ) + { + default: + wxFAIL_MSG( _T("unknown wxBitmapTransparency value") ); + + case wxBitmapTransparency_None: + // nothing to do, refData->m_hasAlpha is false by default + break; + + case wxBitmapTransparency_Auto: #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; + wxDIB dib(iconInfo.hbmColor); + if (dib.IsOk()) + { + const unsigned char* pixels = dib.GetData(); + for (int idx = 0; idx < w*h*4; idx+=4) + { + if (pixels[idx+3] != 0) + { + // If there is an alpha byte that is non-zero + // then set the alpha flag and stop checking + refData->m_hasAlpha = true; + break; + } + } + } } } - } + break; +#endif // wxUSE_WXDIB + + case wxBitmapTransparency_Always: + refData->m_hasAlpha = true; + break; } -#endif + if ( !refData->m_hasAlpha ) { // the mask returned by GetIconInfo() is inverted compared to the usual @@ -346,32 +374,32 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) ::DeleteObject(iconInfo.hbmMask); return true; -#else +#else // __WXMICROWIN__ || __WXWINCE__ wxUnusedVar(icon); + wxUnusedVar(transp); + return false; -#endif +#endif // !__WXWINCE__/__WXWINCE__ } -#endif // Win32 - -bool wxBitmap::CopyFromCursor(const wxCursor& cursor) +bool wxBitmap::CopyFromCursor(const wxCursor& cursor, wxBitmapTransparency transp) { UnRef(); if ( !cursor.Ok() ) return false; - return CopyFromIconOrCursor(cursor); + return CopyFromIconOrCursor(cursor, transp); } -bool wxBitmap::CopyFromIcon(const wxIcon& icon) +bool wxBitmap::CopyFromIcon(const wxIcon& icon, wxBitmapTransparency transp) { UnRef(); if ( !icon.Ok() ) return false; - return CopyFromIconOrCursor(icon); + return CopyFromIconOrCursor(icon, transp); } #ifndef NEVER_USE_DIB @@ -420,8 +448,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 +482,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 +510,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); } @@ -539,9 +537,14 @@ bool wxBitmap::Create(int width, int height, int depth) bool wxBitmap::Create(int width, int height, const wxDC& dc) { - wxCHECK_MSG( dc.Ok(), false, _T("invalid HDC in wxBitmap::Create()") ); + wxCHECK_MSG( dc.IsOk(), false, _T("invalid HDC in wxBitmap::Create()") ); - return DoCreate(width, height, -1, dc.GetHDC()); + const wxMSWDCImpl *impl = wxDynamicCast( dc.GetImpl(), wxMSWDCImpl ); + + if (impl) + return DoCreate(width, height, -1, impl->GetHDC()); + else + return false; } bool wxBitmap::DoCreate(int w, int h, int d, WXHDC hdc) @@ -802,8 +805,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); @@ -811,12 +812,19 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth) bool wxBitmap::CreateFromImage(const wxImage& image, const wxDC& dc) { - wxCHECK_MSG( dc.Ok(), false, + wxCHECK_MSG( dc.IsOk(), false, _T("invalid HDC in wxBitmap::CreateFromImage()") ); - return CreateFromImage(image, -1, dc.GetHDC()); + const wxMSWDCImpl *impl = wxDynamicCast( dc.GetImpl(), wxMSWDCImpl ); + + if (impl) + return CreateFromImage(image, -1, impl->GetHDC()); + else + return false; } +#if wxUSE_WXDIB + bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) { wxCHECK_MSG( image.Ok(), false, wxT("invalid image") ); @@ -831,6 +839,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 +863,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 @@ -994,7 +1004,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 +1039,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 +1055,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 +1083,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? @@ -1076,8 +1101,14 @@ bool wxBitmap::SaveFile(const wxString& filename, // ---------------------------------------------------------------------------- // sub bitmap extraction // ---------------------------------------------------------------------------- +wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect ) const +{ + MemoryHDC dcSrc; + SelectInHDC selectSrc(dcSrc, GetHbitmap()); + return GetSubBitmapOfHDC( rect, (WXHDC)dcSrc ); +} -wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const +wxBitmap wxBitmap::GetSubBitmapOfHDC( const wxRect& rect, WXHDC hdc ) const { wxCHECK_MSG( Ok() && (rect.x >= 0) && (rect.y >= 0) && @@ -1091,23 +1122,22 @@ 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, dcDst; { - SelectInHDC selectSrc(dcSrc, GetHbitmap()), - selectDst(dcDst, GetHbitmapOf(ret)); - - if ( !selectSrc || !selectDst ) + SelectInHDC selectDst(dcDst, GetHbitmapOf(ret)); + + if ( !selectDst ) { - wxLogLastError(_T("SelectObjct(hBitmap)")); + wxLogLastError(_T("SelectObject(destBitmap)")); } if ( !::BitBlt(dcDst, 0, 0, rect.width, rect.height, - dcSrc, rect.x, rect.y, SRCCOPY) ) + (HDC)hdc, rect.x, rect.y, SRCCOPY) ) { wxLogLastError(_T("BitBlt")); } @@ -1170,15 +1200,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 +1243,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 // ---------------------------------------------------------------------------- @@ -1351,6 +1364,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 +1562,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 +1578,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 +1587,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), @@ -1571,57 +1617,6 @@ bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap), return false; } -// ---------------------------------------------------------------------------- -// DIB functions -// ---------------------------------------------------------------------------- - -#ifndef __WXMICROWIN__ -bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel, - HPALETTE hPal, LPBITMAPINFO* lpDIBHeader) -{ - unsigned long i, headerSize; - - // Allocate space for a DIB header - headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY))); - LPBITMAPINFO lpDIBheader = (BITMAPINFO *) malloc(headerSize); - LPPALETTEENTRY lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER)); - - GetPaletteEntries(hPal, 0, 256, lpPe); - - memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER)); - - // Fill in the static parts of the DIB header - lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - lpDIBheader->bmiHeader.biWidth = xSize; - lpDIBheader->bmiHeader.biHeight = ySize; - lpDIBheader->bmiHeader.biPlanes = 1; - - // 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.biClrUsed = 256; - - - // Initialize the DIB palette - for (i = 0; i < 256; i++) { - lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags; - lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed; - lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen; - lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue; - } - - *lpDIBHeader = lpDIBheader; - - return true; -} - -void wxFreeDIB(LPBITMAPINFO lpDIBHeader) -{ - free(lpDIBHeader); -} -#endif - // ---------------------------------------------------------------------------- // global helper functions implemented here // ---------------------------------------------------------------------------- @@ -1639,23 +1634,33 @@ HICON wxBitmapToIconOrCursor(const wxBitmap& bmp, return 0; } - wxMask* mask; - wxBitmap newbmp; if ( bmp.HasAlpha() ) { - // Convert alpha to a mask. NOTE: It would be better to actually put - // the alpha into the icon instead of making a mask, but I don't have - // time to figure that out today. - wxImage img = bmp.ConvertToImage(); - img.ConvertAlphaToMask(); - newbmp = wxBitmap(img); - mask = newbmp.GetMask(); - } - else - { - mask = bmp.GetMask(); + // 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,