#endif
#include "wx/msw/private.h"
+#include "wx/msw/dc.h"
#if wxUSE_WXDIB
#include "wx/msw/dib.h"
#endif
-#ifdef wxHAVE_RAW_BITMAP
+#ifdef wxHAS_RAW_BITMAP
#include "wx/rawbmp.h"
#endif
#endif // no CLR_INVALID
// ----------------------------------------------------------------------------
-// Bitmap data
+// wxBitmapRefData
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxBitmapRefData : public wxGDIImageRefData
// MSW-specific
// ------------
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL
// this field is solely for error checking: we detect selecting a bitmap
// into more than one DC at once or deleting a bitmap still selected into a
// DC (both are serious programming errors under Windows)
wxDC *m_selectedInto;
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL
#if wxUSE_WXDIB
// when GetRawData() is called for a DDB we need to convert it to a DIB
wxBitmapRefData::wxBitmapRefData()
{
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL
m_selectedInto = NULL;
#endif
m_bitmapMask = NULL;
wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData& data)
: wxGDIImageRefData(data)
{
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL
m_selectedInto = NULL;
#endif
m_bitmapMask = new wxMask(*data.m_bitmapMask);
// FIXME: we don't copy m_hBitmap currently but we should, see wxBitmap::
- // CloneRefData()
+ // CloneGDIRefData()
wxASSERT_MSG( !data.m_isDIB,
- _T("can't copy bitmap locked for raw access!") );
+ wxT("can't copy bitmap locked for raw access!") );
m_isDIB = false;
m_hasAlpha = data.m_hasAlpha;
wxT("deleting bitmap still selected into wxMemoryDC") );
#if wxUSE_WXDIB
- wxASSERT_MSG( !m_dib, _T("forgot to call wxBitmap::UngetRawData()!") );
+ wxASSERT_MSG( !m_dib, wxT("forgot to call wxBitmap::UngetRawData()!") );
#endif
if ( m_hBitmap)
}
}
- delete m_bitmapMask;
- m_bitmapMask = NULL;
+ wxDELETE(m_bitmapMask);
}
// ----------------------------------------------------------------------------
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);
+ data = static_cast<const wxBitmapRefData *>(dataOrig);
if ( !data )
return NULL;
// 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);
+ wxBitmap *self = const_cast<wxBitmap *>(this);
+ wxBitmapRefData *selfdata;
#if wxUSE_WXDIB
// copy the other bitmap
if ( data->m_hBitmap )
{
wxDIB dib((HBITMAP)(data->m_hBitmap));
self->CopyFromDIB(dib);
+
+ selfdata = static_cast<wxBitmapRefData *>(m_refData);
+ selfdata->m_hasAlpha = data->m_hasAlpha;
}
else
#endif // wxUSE_WXDIB
{
// copy the bitmap data
- self->m_refData = new wxBitmapRefData(*data);
+ selfdata = new wxBitmapRefData(*data);
+ self->m_refData = selfdata;
}
// 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;
+ return selfdata;
}
-#ifdef __WIN32__
-
-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
refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor;
+ switch ( transp )
+ {
+ default:
+ wxFAIL_MSG( wxT("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; idx<w*h*4; idx+=4)
+ // 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.
{
- if (pixels[idx+3] != 0)
+ BITMAP bm;
+ if ( ::GetObject(iconInfo.hbmColor, sizeof(bm), &bm) &&
+ (bm.bmBitsPixel == 32) )
{
- // If there is an alpha byte that is non-zero then set the
- // alpha flag and bail out of the loop.
- refData->m_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
::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
bool wxBitmap::CopyFromDIB(const wxDIB& dib)
{
- wxCHECK_MSG( dib.IsOk(), false, _T("invalid DIB in CopyFromDIB") );
+ wxCHECK_MSG( dib.IsOk(), false, wxT("invalid DIB in CopyFromDIB") );
#ifdef SOMETIMES_USE_DIB
HBITMAP hbitmap = dib.CreateDDB();
if ( !hbitmap )
return false;
#else // ALWAYS_USE_DIB
- HBITMAP hbitmap = ((wxDIB &)dib).Detach(); // const_cast
+ HBITMAP hbitmap = const_cast<wxDIB &>(dib).Detach();
#endif // SOMETIMES_USE_DIB/ALWAYS_USE_DIB
UnRef();
else
{
// bits should already be in Windows standard format
- data = (char *)bits; // const_cast is harmless
+ data = const_cast<char *>(bits);
}
HBITMAP hbmp = ::CreateBitmap(width, height, 1, depth, data);
#endif
}
-wxBitmap::wxBitmap(int w, int h, int d)
-{
- (void)Create(w, h, d);
-}
-
wxBitmap::wxBitmap(int w, int h, const wxDC& dc)
{
(void)Create(w, h, dc);
}
-wxBitmap::wxBitmap(const void* data, long type, int width, int height, int depth)
+wxBitmap::wxBitmap(const void* data, wxBitmapType type, int width, int height, int depth)
{
(void)Create(data, type, width, height, depth);
}
wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
{
- LoadFile(filename, (int)type);
+ LoadFile(filename, type);
}
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, wxT("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)
bool wxBitmap::CreateFromImage(const wxImage& image, const wxDC& dc)
{
- wxCHECK_MSG( dc.Ok(), false,
- _T("invalid HDC in wxBitmap::CreateFromImage()") );
+ wxCHECK_MSG( dc.IsOk(), false,
+ wxT("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
if ( !dib.IsOk() )
return false;
- if ( depth == -1 )
- depth = dib.GetDepth(); // Get depth from image if none specified
+ const bool hasAlpha = image.HasAlpha();
+
+ if (depth == -1)
+ depth = dib.GetDepth();
// store the bitmap parameters
- wxBitmapRefData *refData = new wxBitmapRefData;
+ wxBitmapRefData * const refData = new wxBitmapRefData;
refData->m_width = w;
refData->m_height = h;
- refData->m_hasAlpha = image.HasAlpha();
+ refData->m_hasAlpha = hasAlpha;
+ refData->m_depth = depth;
m_refData = refData;
// are we going to use DIB?
//
// NB: DDBs don't support alpha so if we have alpha channel we must use DIB
- if ( image.HasAlpha() || wxShouldCreateDIB(w, h, depth, hdc) )
+ if ( hasAlpha || wxShouldCreateDIB(w, h, depth, hdc) )
{
// don't delete the DIB section in dib object dtor
hbitmap = dib.Detach();
refData->m_isDIB = true;
- 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;
}
#endif // !ALWAYS_USE_DIB
hbitmap = ::CreateBitmap(w, h, 1, 1, data);
if ( !hbitmap )
{
- wxLogLastError(_T("CreateBitmap(mask)"));
+ wxLogLastError(wxT("CreateBitmap(mask)"));
}
else
{
// loading and saving bitmaps
// ----------------------------------------------------------------------------
-bool wxBitmap::LoadFile(const wxString& filename, long type)
+bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
{
UnRef();
return false;
}
-bool wxBitmap::Create(const void* data, long type, int width, int height, int depth)
+bool wxBitmap::Create(const void* data, wxBitmapType type, int width, int height, int depth)
{
UnRef();
}
bool wxBitmap::SaveFile(const wxString& filename,
- int type,
- const wxPalette *palette)
+ wxBitmapType type,
+ const wxPalette *palette) const
{
wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
// ----------------------------------------------------------------------------
// 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) &&
dcDst;
{
- SelectInHDC selectSrc(dcSrc, GetHbitmap()),
- selectDst(dcDst, GetHbitmapOf(ret));
+ SelectInHDC selectDst(dcDst, GetHbitmapOf(ret));
- if ( !selectSrc || !selectDst )
+ if ( !selectDst )
{
- wxLogLastError(_T("SelectObjct(hBitmap)"));
+ wxLogLastError(wxT("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"));
+ wxLogLastError(wxT("BitBlt"));
}
}
if ( !::BitBlt(dcDst, 0, 0, rect.width, rect.height,
dcSrc, rect.x, rect.y, SRCCOPY) )
{
- wxLogLastError(_T("BitBlt"));
+ wxLogLastError(wxT("BitBlt"));
}
wxMask *mask = new wxMask((WXHBITMAP) hbmpMask);
wxPalette* wxBitmap::GetPalette() const
{
return GetBitmapData() ? &GetBitmapData()->m_bitmapPalette
- : (wxPalette *) NULL;
+ : NULL;
}
#endif
wxMask *wxBitmap::GetMask() const
{
- return GetBitmapData() ? GetBitmapData()->GetMask() : (wxMask *) NULL;
+ return GetBitmapData() ? GetBitmapData()->GetMask() : NULL;
}
wxBitmap wxBitmap::GetMaskBitmap() const
return bmp;
}
-#ifdef __WXDEBUG__
-
wxDC *wxBitmap::GetSelectedInto() const
{
- return GetBitmapData() ? GetBitmapData()->m_selectedInto : (wxDC *) NULL;
-}
-
+#if wxDEBUG_LEVEL
+ return GetBitmapData() ? GetBitmapData()->m_selectedInto : NULL;
+#else
+ return NULL;
#endif
+}
void wxBitmap::UseAlpha()
{
// wxBitmap setters
// ----------------------------------------------------------------------------
-#ifdef __WXDEBUG__
-
void wxBitmap::SetSelectedInto(wxDC *dc)
{
+#if wxDEBUG_LEVEL
if ( GetBitmapData() )
GetBitmapData()->m_selectedInto = dc;
-}
-
+#else
+ wxUnusedVar(dc);
#endif
+}
#if wxUSE_PALETTE
// raw bitmap access support
// ----------------------------------------------------------------------------
-#ifdef wxHAVE_RAW_BITMAP
+#ifdef wxHAS_RAW_BITMAP
+
void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp)
{
#if wxUSE_WXDIB
if ( !GetBitmapData()->m_isDIB )
{
wxCHECK_MSG( !GetBitmapData()->m_dib, NULL,
- _T("GetRawData() may be called only once") );
+ wxT("GetRawData() may be called only once") );
wxDIB *dib = new wxDIB(*this);
if ( !dib->IsOk() )
DIBSECTION ds;
if ( ::GetObject(hDIB, sizeof(ds), &ds) != sizeof(DIBSECTION) )
{
- wxFAIL_MSG( _T("failed to get DIBSECTION from a DIB?") );
+ wxFAIL_MSG( wxT("failed to get DIBSECTION from a DIB?") );
return NULL;
}
// check that the bitmap is in correct format
if ( ds.dsBm.bmBitsPixel != bpp )
{
- wxFAIL_MSG( _T("incorrect bitmap type in wxBitmap::GetRawData()") );
+ wxFAIL_MSG( wxT("incorrect bitmap type in wxBitmap::GetRawData()") );
return NULL;
}
}
#endif // wxUSE_WXDIB
}
-#endif // #ifdef wxHAVE_RAW_BITMAP
+#endif // wxHAS_RAW_BITMAP
// ----------------------------------------------------------------------------
// wxMask
{
#ifndef __WXMICROWIN__
wxCHECK_MSG( bitmap.Ok() && bitmap.GetDepth() == 1, false,
- _T("can't create mask from invalid or not monochrome bitmap") );
+ wxT("can't create mask from invalid or not monochrome bitmap") );
if ( m_maskBitmap )
{
bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
{
#ifndef __WXMICROWIN__
- wxCHECK_MSG( bitmap.Ok(), false, _T("invalid bitmap in wxMask::Create") );
+ wxCHECK_MSG( bitmap.Ok(), false, wxT("invalid bitmap in wxMask::Create") );
if ( m_maskBitmap )
{
// SelectObject() will fail
wxASSERT_MSG( !bitmap.GetSelectedInto(),
- _T("bitmap can't be selected in another DC") );
+ wxT("bitmap can't be selected in another DC") );
HGDIOBJ hbmpSrcOld = ::SelectObject(srcDC, GetHbitmapOf(bitmap));
if ( !hbmpSrcOld )
bool wxBitmapHandler::Create(wxGDIImage *image,
const void* data,
- long flags,
+ wxBitmapType type,
int width, int height, int depth)
{
wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
- return bitmap && Create(bitmap, data, flags, width, height, depth);
+ return bitmap && Create(bitmap, data, type, width, height, depth);
}
bool wxBitmapHandler::Load(wxGDIImage *image,
const wxString& name,
- long flags,
+ wxBitmapType type,
int width, int height)
{
wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
- return bitmap && LoadFile(bitmap, name, flags, width, height);
+ return bitmap && LoadFile(bitmap, name, type, width, height);
}
-bool wxBitmapHandler::Save(wxGDIImage *image,
+bool wxBitmapHandler::Save(const wxGDIImage *image,
const wxString& name,
- int type)
+ wxBitmapType type) const
{
wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap),
const void* WXUNUSED(data),
- long WXUNUSED(type),
+ wxBitmapType WXUNUSED(type),
int WXUNUSED(width),
int WXUNUSED(height),
int WXUNUSED(depth))
bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap),
const wxString& WXUNUSED(name),
- long WXUNUSED(type),
+ wxBitmapType WXUNUSED(type),
int WXUNUSED(desiredWidth),
int WXUNUSED(desiredHeight))
{
return false;
}
-bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap),
+bool wxBitmapHandler::SaveFile(const wxBitmap *WXUNUSED(bitmap),
const wxString& WXUNUSED(name),
- int WXUNUSED(type),
- const wxPalette *WXUNUSED(palette))
+ wxBitmapType WXUNUSED(type),
+ const wxPalette *WXUNUSED(palette)) const
{
return false;
}
if ( bmp.HasAlpha() )
{
+ HBITMAP hbmp;
+
+#if wxUSE_WXDIB && wxUSE_IMAGE
+ // CreateIconIndirect() requires non-pre-multiplied pixel data on input
+ // as it does pre-multiplication internally itself so we need to create
+ // a special DIB in such format to pass to it. This is inefficient but
+ // better than creating an icon with wrong colours.
+ AutoHBITMAP hbmpRelease;
+ hbmp = wxDIB(bmp.ConvertToImage(),
+ wxDIB::PixelFormat_NotPreMultiplied).Detach();
+ hbmpRelease.Init(hbmp);
+#else // !(wxUSE_WXDIB && wxUSE_IMAGE)
+ hbmp = GetHbitmapOf(bmp);
+#endif // wxUSE_WXDIB && wxUSE_IMAGE
+
// 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);
+ AutoHBITMAP
+ hMonoBitmap(CreateBitmap(bmp.GetWidth(),bmp.GetHeight(),1,1,NULL));
ICONINFO iconInfo;
wxZeroMemory(iconInfo);
}
iconInfo.hbmMask = hMonoBitmap;
- iconInfo.hbmColor = GetHbitmapOf(bmp);
-
- HICON hicon = ::CreateIconIndirect(&iconInfo);
+ iconInfo.hbmColor = hbmp;
- ::DeleteObject(hMonoBitmap);
-
- return hicon;
+ return ::CreateIconIndirect(&iconInfo);
}
wxMask* mask = bmp.GetMask();
iconInfo.yHotspot = hotSpotY;
}
- iconInfo.hbmMask = wxInvertMask((HBITMAP)mask->GetMaskBitmap());
+ AutoHBITMAP hbmpMask(wxInvertMask((HBITMAP)mask->GetMaskBitmap()));
+ iconInfo.hbmMask = hbmpMask;
iconInfo.hbmColor = GetHbitmapOf(bmp);
// black out the transparent area to preserve background colour, because
if ( !::BitBlt(dcDst, 0, 0, bmp.GetWidth(), bmp.GetHeight(),
dcSrc, 0, 0, SRCAND) )
{
- wxLogLastError(_T("BitBlt"));
+ wxLogLastError(wxT("BitBlt"));
}
}
delete mask;
}
- // delete the inverted mask bitmap we created as well
- ::DeleteObject(iconInfo.hbmMask);
-
return hicon;
}
HBITMAP wxInvertMask(HBITMAP hbmpMask, int w, int h)
{
#ifndef __WXMICROWIN__
- wxCHECK_MSG( hbmpMask, 0, _T("invalid bitmap in wxInvertMask") );
+ wxCHECK_MSG( hbmpMask, 0, wxT("invalid bitmap in wxInvertMask") );
// get width/height from the bitmap if not given
if ( !w || !h )