Fix adding wxBitmap with mask to wxImageList not supporting masks (wxMSW)
If wxBitmap with mask is added to wxImageList that doesn't support masks we need to convert a bitmap mask to alpha channel values prior to adding bitmap to the native list to preserve bitmap transparency. Closes #19036.
This commit is contained in:
@@ -194,6 +194,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
WXHIMAGELIST m_hImageList;
|
WXHIMAGELIST m_hImageList;
|
||||||
wxSize m_size;
|
wxSize m_size;
|
||||||
|
bool m_useMask;
|
||||||
|
|
||||||
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxImageList);
|
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxImageList);
|
||||||
};
|
};
|
||||||
|
@@ -65,8 +65,9 @@ static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask);
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxImageList::wxImageList()
|
wxImageList::wxImageList()
|
||||||
|
: m_hImageList(NULL)
|
||||||
|
, m_useMask(false)
|
||||||
{
|
{
|
||||||
m_hImageList = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an image list
|
// Creates an image list
|
||||||
@@ -94,6 +95,7 @@ bool wxImageList::Create(int width, int height, bool mask, int initial)
|
|||||||
wxLogLastError(wxT("ImageList_Create()"));
|
wxLogLastError(wxT("ImageList_Create()"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_useMask = (flags & ILC_MASK) != 0;
|
||||||
return m_hImageList != 0;
|
return m_hImageList != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,8 +137,7 @@ bool wxImageList::GetSize(int WXUNUSED(index), int &width, int &height) const
|
|||||||
// 'bitmap' and 'mask'.
|
// 'bitmap' and 'mask'.
|
||||||
int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask)
|
int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask)
|
||||||
{
|
{
|
||||||
HBITMAP hbmp;
|
HBITMAP hbmp = NULL;
|
||||||
bool useMask;
|
|
||||||
|
|
||||||
#if wxUSE_WXDIB && wxUSE_IMAGE
|
#if wxUSE_WXDIB && wxUSE_IMAGE
|
||||||
// wxBitmap normally stores alpha in pre-multiplied format but
|
// wxBitmap normally stores alpha in pre-multiplied format but
|
||||||
@@ -147,34 +148,73 @@ int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask)
|
|||||||
AutoHBITMAP hbmpRelease;
|
AutoHBITMAP hbmpRelease;
|
||||||
if ( bitmap.HasAlpha() )
|
if ( bitmap.HasAlpha() )
|
||||||
{
|
{
|
||||||
wxImage img = bitmap.ConvertToImage();
|
wxImage img;
|
||||||
|
if ( m_useMask )
|
||||||
// For comctl32.dll < 6 remove alpha channel from image
|
|
||||||
// to prevent possible interferences with the mask.
|
|
||||||
if ( wxApp::GetComCtl32Version() < 600 )
|
|
||||||
{
|
{
|
||||||
|
// Remove alpha channel from image to prevent
|
||||||
|
// possible interferences with the mask.
|
||||||
|
// The bitmap isn't drawn correctly if we use both.
|
||||||
|
img = bitmap.ConvertToImage();
|
||||||
img.ClearAlpha();
|
img.ClearAlpha();
|
||||||
useMask = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
useMask = false;
|
wxBitmap bmpWithoutMask = bitmap;
|
||||||
|
if ( mask.IsOk() || bmpWithoutMask.GetMask() )
|
||||||
|
{
|
||||||
|
// Blend mask with alpha channel.
|
||||||
|
if ( mask.IsOk() )
|
||||||
|
{
|
||||||
|
bmpWithoutMask.SetMask(new wxMask(mask));
|
||||||
|
}
|
||||||
|
bmpWithoutMask.MSWBlendMaskWithAlpha();
|
||||||
|
}
|
||||||
|
img = bmpWithoutMask.ConvertToImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
hbmp = wxDIB(img, wxDIB::PixelFormat_NotPreMultiplied).Detach();
|
hbmp = wxDIB(img, wxDIB::PixelFormat_NotPreMultiplied).Detach();
|
||||||
hbmpRelease.Init(hbmp);
|
hbmpRelease.Init(hbmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif // wxUSE_WXDIB && wxUSE_IMAGE
|
|
||||||
{
|
{
|
||||||
hbmp = GetHbitmapOf(bitmap);
|
if ( m_useMask )
|
||||||
useMask = true;
|
{
|
||||||
|
hbmp = GetHbitmapOf(bitmap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( mask.IsOk() || bitmap.GetMask() )
|
||||||
|
{
|
||||||
|
// Convert mask to alpha channel.
|
||||||
|
wxBitmap bmpWithMask;
|
||||||
|
if ( mask.IsOk() )
|
||||||
|
{
|
||||||
|
bmpWithMask = bitmap;
|
||||||
|
bmpWithMask.SetMask(new wxMask(mask));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bmpWithMask = bitmap;
|
||||||
|
}
|
||||||
|
wxImage img = bmpWithMask.ConvertToImage();
|
||||||
|
img.InitAlpha();
|
||||||
|
hbmp = wxDIB(img, wxDIB::PixelFormat_NotPreMultiplied).Detach();
|
||||||
|
hbmpRelease.Init(hbmp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hbmp = GetHbitmapOf(bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
hbmp = GetHbitmapOf(bitmap);
|
||||||
|
#endif // wxUSE_WXDIB && wxUSE_IMAGE
|
||||||
|
|
||||||
// Use mask only if we don't have alpha, the bitmap isn't drawn correctly
|
// Use mask only if we don't have alpha, the bitmap isn't drawn correctly
|
||||||
// if we use both.
|
// if we use both.
|
||||||
AutoHBITMAP hbmpMask;
|
AutoHBITMAP hbmpMask;
|
||||||
if ( useMask )
|
if ( m_useMask )
|
||||||
hbmpMask.Init(GetMaskForImage(bitmap, mask));
|
hbmpMask.Init(GetMaskForImage(bitmap, mask));
|
||||||
|
|
||||||
int index = ImageList_Add(GetHImageList(), hbmp, hbmpMask);
|
int index = ImageList_Add(GetHImageList(), hbmp, hbmpMask);
|
||||||
@@ -255,38 +295,78 @@ bool wxImageList::Replace(int index,
|
|||||||
const wxBitmap& bitmap,
|
const wxBitmap& bitmap,
|
||||||
const wxBitmap& mask)
|
const wxBitmap& mask)
|
||||||
{
|
{
|
||||||
HBITMAP hbmp;
|
HBITMAP hbmp = NULL;
|
||||||
bool useMask;
|
|
||||||
|
|
||||||
#if wxUSE_WXDIB && wxUSE_IMAGE
|
#if wxUSE_WXDIB && wxUSE_IMAGE
|
||||||
// See the comment in Add() above.
|
// See the comment in Add() above.
|
||||||
AutoHBITMAP hbmpRelease;
|
AutoHBITMAP hbmpRelease;
|
||||||
if ( bitmap.HasAlpha() )
|
if ( bitmap.HasAlpha() )
|
||||||
{
|
{
|
||||||
wxImage img = bitmap.ConvertToImage();
|
wxImage img;
|
||||||
|
if ( m_useMask )
|
||||||
if ( wxApp::GetComCtl32Version() < 600 )
|
|
||||||
{
|
{
|
||||||
|
// Remove alpha channel from image to prevent
|
||||||
|
// possible interferences with the mask.
|
||||||
|
// The bitmap isn't drawn correctly if we use both.
|
||||||
|
img = bitmap.ConvertToImage();
|
||||||
img.ClearAlpha();
|
img.ClearAlpha();
|
||||||
useMask = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
useMask = false;
|
wxBitmap bmpWithoutMask = bitmap;
|
||||||
|
if ( mask.IsOk() || bmpWithoutMask.GetMask() )
|
||||||
|
{
|
||||||
|
// Blend mask with alpha channel.
|
||||||
|
if ( mask.IsOk() )
|
||||||
|
{
|
||||||
|
bmpWithoutMask.SetMask(new wxMask(mask));
|
||||||
|
}
|
||||||
|
bmpWithoutMask.MSWBlendMaskWithAlpha();
|
||||||
|
}
|
||||||
|
img = bmpWithoutMask.ConvertToImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
hbmp = wxDIB(img, wxDIB::PixelFormat_NotPreMultiplied).Detach();
|
hbmp = wxDIB(img, wxDIB::PixelFormat_NotPreMultiplied).Detach();
|
||||||
hbmpRelease.Init(hbmp);
|
hbmpRelease.Init(hbmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif // wxUSE_WXDIB && wxUSE_IMAGE
|
|
||||||
{
|
{
|
||||||
hbmp = GetHbitmapOf(bitmap);
|
if ( m_useMask )
|
||||||
useMask = true;
|
{
|
||||||
|
hbmp = GetHbitmapOf(bitmap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( mask.IsOk() || bitmap.GetMask() )
|
||||||
|
{
|
||||||
|
// Convert mask to alpha channel.
|
||||||
|
wxBitmap bmpWithMask;
|
||||||
|
if ( mask.IsOk() )
|
||||||
|
{
|
||||||
|
bmpWithMask = bitmap;
|
||||||
|
bmpWithMask.SetMask(new wxMask(mask));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bmpWithMask = bitmap;
|
||||||
|
}
|
||||||
|
wxImage img = bmpWithMask.ConvertToImage();
|
||||||
|
img.InitAlpha();
|
||||||
|
hbmp = wxDIB(img, wxDIB::PixelFormat_NotPreMultiplied).Detach();
|
||||||
|
hbmpRelease.Init(hbmp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hbmp = GetHbitmapOf(bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
hbmp = GetHbitmapOf(bitmap);
|
||||||
|
#endif // wxUSE_WXDIB && wxUSE_IMAGE
|
||||||
|
|
||||||
AutoHBITMAP hbmpMask;
|
AutoHBITMAP hbmpMask;
|
||||||
if ( useMask )
|
if ( m_useMask )
|
||||||
hbmpMask.Init(GetMaskForImage(bitmap, mask));
|
hbmpMask.Init(GetMaskForImage(bitmap, mask));
|
||||||
|
|
||||||
if ( !ImageList_Replace(GetHImageList(), index, hbmp, hbmpMask) )
|
if ( !ImageList_Replace(GetHImageList(), index, hbmp, hbmpMask) )
|
||||||
|
Reference in New Issue
Block a user