Always use DIBs in wxMSW wxGCDC.

Ensure that 32bpp bitmaps selected in wxMemoryDC use DIB for their internal
representation as GDI+ functions don't seem to work correctly with DDBs.

Note: Code responsible for converting and fixing the bitmap has been moved
from wxGCDCImpl::wxGCDCImpl to wxGDIPlusRenderer::CreateContext because this
is the common entry point for creating context for GDI+.

Closes #17324.
This commit is contained in:
Artur Wieczorek
2016-01-15 19:22:11 +01:00
committed by Vadim Zeitlin
parent 46953a1426
commit 976e3115b7
2 changed files with 56 additions and 56 deletions

View File

@@ -18,7 +18,6 @@
#if wxUSE_GRAPHICS_CONTEXT
#include "wx/dcgraph.h"
#include "wx/rawbmp.h"
#ifndef WX_PRECOMP
#include "wx/icon.h"
@@ -169,61 +168,6 @@ wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxWindowDC& dc ) :
wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxMemoryDC& dc ) :
wxDCImpl( owner )
{
#if defined(__WXMSW__) && wxUSE_WXDIB
// 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 // wxUSE_WXDIB
Init(wxGraphicsContext::Create(dc));
}