Merge branch 'imaglist-mask'
Fixes for using mask and alpha in wxMSW wxImageList. See #22101.
This commit is contained in:
commit
bd058106a3
@ -24,7 +24,7 @@ public:
|
|||||||
* Public interface
|
* Public interface
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wxImageList();
|
wxImageList() { Init(); }
|
||||||
|
|
||||||
// Creates an image list.
|
// Creates an image list.
|
||||||
// Specify the width and height of the images in the list,
|
// Specify the width and height of the images in the list,
|
||||||
@ -32,7 +32,7 @@ public:
|
|||||||
// from icons), and the initial size of the list.
|
// from icons), and the initial size of the list.
|
||||||
wxImageList(int width, int height, bool mask = true, int initialCount = 1)
|
wxImageList(int width, int height, bool mask = true, int initialCount = 1)
|
||||||
{
|
{
|
||||||
m_hImageList = NULL;
|
Init();
|
||||||
Create(width, height, mask, initialCount);
|
Create(width, height, mask, initialCount);
|
||||||
}
|
}
|
||||||
virtual ~wxImageList();
|
virtual ~wxImageList();
|
||||||
@ -198,8 +198,16 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
WXHIMAGELIST m_hImageList;
|
WXHIMAGELIST m_hImageList;
|
||||||
wxSize m_size;
|
wxSize m_size;
|
||||||
|
|
||||||
|
private:
|
||||||
bool m_useMask;
|
bool m_useMask;
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
m_hImageList = NULL;
|
||||||
|
m_useMask = false;
|
||||||
|
}
|
||||||
|
|
||||||
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxImageList);
|
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxImageList);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include "wx/imaglist.h"
|
#include "wx/imaglist.h"
|
||||||
#include "wx/dc.h"
|
#include "wx/dc.h"
|
||||||
|
#include "wx/scopedptr.h"
|
||||||
#include "wx/msw/dc.h"
|
#include "wx/msw/dc.h"
|
||||||
#include "wx/msw/dib.h"
|
#include "wx/msw/dib.h"
|
||||||
#include "wx/msw/private.h"
|
#include "wx/msw/private.h"
|
||||||
@ -64,12 +65,6 @@ static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask);
|
|||||||
// wxImageList creation/destruction
|
// wxImageList creation/destruction
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxImageList::wxImageList()
|
|
||||||
: m_hImageList(NULL)
|
|
||||||
, m_useMask(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates an image list
|
// Creates an image list
|
||||||
bool wxImageList::Create(int width, int height, bool mask, int initial)
|
bool wxImageList::Create(int width, int height, bool mask, int initial)
|
||||||
{
|
{
|
||||||
@ -88,7 +83,10 @@ bool wxImageList::Create(int width, int height, bool mask, int initial)
|
|||||||
|
|
||||||
// For comctl32.dll < 6 always use masks as it doesn't support alpha.
|
// For comctl32.dll < 6 always use masks as it doesn't support alpha.
|
||||||
if ( mask || wxApp::GetComCtl32Version() < 600 )
|
if ( mask || wxApp::GetComCtl32Version() < 600 )
|
||||||
|
{
|
||||||
|
m_useMask = true;
|
||||||
flags |= ILC_MASK;
|
flags |= ILC_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
// Grow by 1, I guess this is reasonable behaviour most of the time
|
// Grow by 1, I guess this is reasonable behaviour most of the time
|
||||||
m_hImageList = (WXHIMAGELIST) ImageList_Create(width, height, flags,
|
m_hImageList = (WXHIMAGELIST) ImageList_Create(width, height, flags,
|
||||||
@ -98,7 +96,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,74 +143,48 @@ void GetImageListBitmaps(const wxBitmap& bitmap, const wxBitmap& mask, bool useM
|
|||||||
AutoHBITMAP& hbmpRelease, AutoHBITMAP& hbmpMask, HBITMAP& hbmp)
|
AutoHBITMAP& hbmpRelease, AutoHBITMAP& hbmpMask, HBITMAP& hbmp)
|
||||||
{
|
{
|
||||||
#if wxUSE_WXDIB && wxUSE_IMAGE
|
#if wxUSE_WXDIB && wxUSE_IMAGE
|
||||||
// wxBitmap normally stores alpha in pre-multiplied format but
|
// We can only use directly bitmaps without alpha and without mask unless
|
||||||
// ImageList_Draw() does pre-multiplication internally so we need to undo
|
// the image list uses masks and need to modify bitmap in all the other
|
||||||
// the pre-multiplication here. Converting back and forth like this is, of
|
// cases, so check if this is necessary.
|
||||||
// course, very inefficient but it's better than wrong appearance so we do
|
if ( bitmap.HasAlpha() || (!useMask && (mask.IsOk() || bitmap.GetMask())) )
|
||||||
// this for now until a better way can be found.
|
|
||||||
if ( useMask )
|
|
||||||
{
|
{
|
||||||
if ( bitmap.HasAlpha() )
|
wxBitmap bmp(bitmap);
|
||||||
|
|
||||||
|
if ( mask.IsOk() || bmp.GetMask() )
|
||||||
{
|
{
|
||||||
// Remove alpha channel from image to prevent
|
// Explicitly specified mask overrides the mask associated with the
|
||||||
// possible interferences with the mask.
|
// bitmap, if any.
|
||||||
// The bitmap isn't drawn correctly if we use both.
|
if ( mask.IsOk() )
|
||||||
wxImage img = bitmap.ConvertToImage();
|
bmp.SetMask(new wxMask(mask));
|
||||||
img.ClearAlpha();
|
|
||||||
hbmp = wxDIB(img, wxDIB::PixelFormat_NotPreMultiplied).Detach();
|
// Get rid of the mask by converting it to alpha.
|
||||||
hbmpRelease.Init(hbmp);
|
if ( bmp.HasAlpha() )
|
||||||
}
|
bmp.MSWBlendMaskWithAlpha();
|
||||||
else
|
|
||||||
{
|
|
||||||
hbmp = GetHbitmapOf(bitmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hbmpMask.Init(GetMaskForImage(bitmap, mask));
|
// wxBitmap normally stores alpha in pre-multiplied format but
|
||||||
|
// ImageList_Draw() does pre-multiplication internally so we need to undo
|
||||||
|
// the pre-multiplication here. Converting back and forth like this is, of
|
||||||
|
// course, very inefficient but it's better than wrong appearance so we do
|
||||||
|
// this for now until a better way can be found.
|
||||||
|
wxImage img = bmp.ConvertToImage();
|
||||||
|
if ( !img.HasAlpha() )
|
||||||
|
img.InitAlpha();
|
||||||
|
hbmp = wxDIB(img, wxDIB::PixelFormat_NotPreMultiplied).Detach();
|
||||||
|
hbmpRelease.Init(hbmp);
|
||||||
|
|
||||||
|
// In any case we'll never use mask at the native image list level as
|
||||||
|
// it's incompatible with alpha and we need to use alpha.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if ( bitmap.HasAlpha() )
|
|
||||||
{
|
|
||||||
wxBitmap bmp(bitmap);
|
|
||||||
if ( mask.IsOk() || bmp.GetMask() )
|
|
||||||
{
|
|
||||||
// Blend mask with alpha channel.
|
|
||||||
if ( mask.IsOk() )
|
|
||||||
{
|
|
||||||
bmp.SetMask(new wxMask(mask));
|
|
||||||
}
|
|
||||||
bmp.MSWBlendMaskWithAlpha();
|
|
||||||
}
|
|
||||||
wxImage img = bmp.ConvertToImage();
|
|
||||||
hbmp = wxDIB(img, wxDIB::PixelFormat_NotPreMultiplied).Detach();
|
|
||||||
hbmpRelease.Init(hbmp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( mask.IsOk() || bitmap.GetMask() )
|
|
||||||
{
|
|
||||||
// Convert mask to alpha channel.
|
|
||||||
wxBitmap bmp(bitmap);
|
|
||||||
if ( mask.IsOk() )
|
|
||||||
{
|
|
||||||
bmp.SetMask(new wxMask(mask));
|
|
||||||
}
|
|
||||||
wxImage img = bmp.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
|
#endif // wxUSE_WXDIB && wxUSE_IMAGE
|
||||||
|
{
|
||||||
|
hbmp = GetHbitmapOf(bitmap);
|
||||||
|
if ( useMask )
|
||||||
|
hbmpMask.Init(GetMaskForImage(bitmap, mask));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
} // anonymous namespace
|
||||||
|
|
||||||
// Adds a bitmap, and optionally a mask bitmap.
|
// Adds a bitmap, and optionally a mask bitmap.
|
||||||
// Note that wxImageList creates new bitmaps, so you may delete
|
// Note that wxImageList creates new bitmaps, so you may delete
|
||||||
@ -488,39 +459,16 @@ wxIcon wxImageList::GetIcon(int index) const
|
|||||||
|
|
||||||
static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask)
|
static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask)
|
||||||
{
|
{
|
||||||
#if wxUSE_IMAGE
|
|
||||||
wxBitmap bitmapWithMask;
|
|
||||||
#endif // wxUSE_IMAGE
|
|
||||||
|
|
||||||
HBITMAP hbmpMask;
|
HBITMAP hbmpMask;
|
||||||
wxMask *pMask;
|
wxScopedPtr<wxMask> maskDeleter;
|
||||||
bool deleteMask = false;
|
|
||||||
|
|
||||||
if ( mask.IsOk() )
|
if ( mask.IsOk() )
|
||||||
{
|
{
|
||||||
hbmpMask = GetHbitmapOf(mask);
|
hbmpMask = GetHbitmapOf(mask);
|
||||||
pMask = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pMask = bitmap.GetMask();
|
wxMask* pMask = bitmap.GetMask();
|
||||||
|
|
||||||
#if wxUSE_IMAGE
|
|
||||||
// check if we don't have alpha in this bitmap -- we can create a mask
|
|
||||||
// from it (and we need to do it for the older systems which don't
|
|
||||||
// support 32bpp bitmaps natively)
|
|
||||||
if ( !pMask )
|
|
||||||
{
|
|
||||||
wxImage img(bitmap.ConvertToImage());
|
|
||||||
if ( img.HasAlpha() )
|
|
||||||
{
|
|
||||||
img.ConvertAlphaToMask();
|
|
||||||
bitmapWithMask = wxBitmap(img);
|
|
||||||
pMask = bitmapWithMask.GetMask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // wxUSE_IMAGE
|
|
||||||
|
|
||||||
if ( !pMask )
|
if ( !pMask )
|
||||||
{
|
{
|
||||||
// use the light grey count as transparent: the trouble here is
|
// use the light grey count as transparent: the trouble here is
|
||||||
@ -532,19 +480,12 @@ static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask)
|
|||||||
|
|
||||||
pMask = new wxMask(bitmap, col);
|
pMask = new wxMask(bitmap, col);
|
||||||
|
|
||||||
deleteMask = true;
|
maskDeleter.reset(pMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
hbmpMask = (HBITMAP)pMask->GetMaskBitmap();
|
hbmpMask = (HBITMAP)pMask->GetMaskBitmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// windows mask convention is opposite to the wxWidgets one
|
// windows mask convention is opposite to the wxWidgets one
|
||||||
HBITMAP hbmpMaskInv = wxInvertMask(hbmpMask);
|
return wxInvertMask(hbmpMask);
|
||||||
|
|
||||||
if ( deleteMask )
|
|
||||||
{
|
|
||||||
delete pMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hbmpMaskInv;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user