Fix alpha channel values when using wxGCDC with wxMemoryDC in wxMSW.
Ensure that 32bpp bitmaps selected in wxMemoryDC use DIB for their internal representation as GDI+ functions don't seem to work correctly with DDBs with alpha channel. Closes #13328. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75648 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#if wxUSE_GRAPHICS_CONTEXT
|
||||
|
||||
#include "wx/dcgraph.h"
|
||||
#include "wx/rawbmp.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/icon.h"
|
||||
@@ -171,6 +172,61 @@ wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxWindowDC& dc ) :
|
||||
wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxMemoryDC& dc ) :
|
||||
wxDCImpl( owner )
|
||||
{
|
||||
#ifndef NEVER_USE_DIB
|
||||
// It seems that GDI+ sets invalid values for alpha channel when used with
|
||||
// a compatible bitmap (DDB). So we need to convert the currently selected
|
||||
// bitmap to a DIB before using it with any GDI+ functions to ensure that
|
||||
// we get the correct alpha channel values in it at the end.
|
||||
|
||||
wxBitmap bmp = dc.GetSelectedBitmap();
|
||||
wxASSERT_MSG( bmp.IsOk(), "Should select a bitmap before creating wxGCDC" );
|
||||
|
||||
// We don't need to convert it if it can't have alpha at all (any depth but
|
||||
// 32) or is already a DIB with alpha.
|
||||
if ( bmp.GetDepth() == 32 && (!bmp.IsDIB() || !bmp.HasAlpha()) )
|
||||
{
|
||||
// We need to temporarily deselect this bitmap from the memory DC
|
||||
// before modifying it.
|
||||
const_cast<wxMemoryDC&>(dc).SelectObject(wxNullBitmap);
|
||||
|
||||
bmp.ConvertToDIB(); // Does nothing if already a DIB.
|
||||
|
||||
if( !bmp.HasAlpha() )
|
||||
{
|
||||
// Initialize alpha channel, even if we don't have any alpha yet,
|
||||
// we should have correct (opaque) alpha values in it for GDI+
|
||||
// functions to work correctly.
|
||||
{
|
||||
wxAlphaPixelData data(bmp);
|
||||
if ( data )
|
||||
{
|
||||
wxAlphaPixelData::Iterator p(data);
|
||||
for ( int y = 0; y < data.GetHeight(); y++ )
|
||||
{
|
||||
wxAlphaPixelData::Iterator rowStart = p;
|
||||
|
||||
for ( int x = 0; x < data.GetWidth(); x++ )
|
||||
{
|
||||
p.Alpha() = wxALPHA_OPAQUE;
|
||||
++p;
|
||||
}
|
||||
|
||||
p = rowStart;
|
||||
p.OffsetY(data, 1);
|
||||
}
|
||||
}
|
||||
} // End of block modifying the bitmap.
|
||||
|
||||
// Using wxAlphaPixelData sets the internal "has alpha" flag but we
|
||||
// don't really have any alpha yet, so reset it back for now.
|
||||
bmp.ResetAlpha();
|
||||
}
|
||||
|
||||
// Undo SelectObject() at the beginning of this block.
|
||||
const_cast<wxMemoryDC&>(dc).SelectObjectAsSource(bmp);
|
||||
}
|
||||
#endif // !NEVER_USE_DIB
|
||||
|
||||
Init(wxGraphicsContext::Create(dc));
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user