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:
committed by
Vadim Zeitlin
parent
46953a1426
commit
976e3115b7
@@ -18,7 +18,6 @@
|
|||||||
#if wxUSE_GRAPHICS_CONTEXT
|
#if wxUSE_GRAPHICS_CONTEXT
|
||||||
|
|
||||||
#include "wx/dcgraph.h"
|
#include "wx/dcgraph.h"
|
||||||
#include "wx/rawbmp.h"
|
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include "wx/icon.h"
|
#include "wx/icon.h"
|
||||||
@@ -169,61 +168,6 @@ wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxWindowDC& dc ) :
|
|||||||
wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxMemoryDC& dc ) :
|
wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxMemoryDC& dc ) :
|
||||||
wxDCImpl( owner )
|
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));
|
Init(wxGraphicsContext::Create(dc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,6 +46,7 @@
|
|||||||
#include "wx/msw/enhmeta.h"
|
#include "wx/msw/enhmeta.h"
|
||||||
#endif
|
#endif
|
||||||
#include "wx/dcgraph.h"
|
#include "wx/dcgraph.h"
|
||||||
|
#include "wx/rawbmp.h"
|
||||||
|
|
||||||
#include "wx/msw/private.h" // needs to be before #include <commdlg.h>
|
#include "wx/msw/private.h" // needs to be before #include <commdlg.h>
|
||||||
|
|
||||||
@@ -2107,6 +2108,61 @@ wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxEnhMetaFileDC& dc)
|
|||||||
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc)
|
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc)
|
||||||
{
|
{
|
||||||
ENSURE_LOADED_OR_RETURN(NULL);
|
ENSURE_LOADED_OR_RETURN(NULL);
|
||||||
|
#if 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
|
||||||
|
|
||||||
wxGDIPlusContext* context = new wxGDIPlusContext(this, dc);
|
wxGDIPlusContext* context = new wxGDIPlusContext(this, dc);
|
||||||
context->EnableOffset(true);
|
context->EnableOffset(true);
|
||||||
return context;
|
return context;
|
||||||
|
Reference in New Issue
Block a user