Fix wxMemoryDC::Blit() with itself as source in wxMSW

Don't use StretchDIBits() native function as it doesn't seem to handle the
case when its source and destination are the same correctly.

Closes #17666.
This commit is contained in:
Tim Roberts
2016-09-21 22:56:16 +02:00
committed by Vadim Zeitlin
parent 6bd6c94511
commit 607b800444
3 changed files with 44 additions and 1 deletions

View File

@@ -134,6 +134,7 @@ wxMSW:
- Fix wxGraphicsMatrix::TransformDistance for Direct2D renderer.
- Fix wxDC::Clear() for rotated DC.
- Fix wxDC::GetClippingBox() for transformed wxDC.
- Fix wxMemoryDC::Blit() with itself as source (Tim Roberts).
wxOSX:

View File

@@ -2294,8 +2294,10 @@ bool wxMSWDCImpl::DoStretchBlit(wxCoord xdest, wxCoord ydest,
// if we already have a DIB, draw it using StretchDIBits(), otherwise
// use StretchBlt() if available and finally fall back to BitBlt()
// Notice that we can't use StretchDIBits() when source and destination
// are the same as it can't, apparently, handle overlapping surfaces.
const int caps = ::GetDeviceCaps(GetHdc(), RASTERCAPS);
if ( bmpSrc.IsOk() && (caps & RC_STRETCHDIB) )
if ( bmpSrc.IsOk() && (GetHdc() != hdcSrc) && (caps & RC_STRETCHDIB) )
{
DIBSECTION ds;
wxZeroMemory(ds);

View File

@@ -17,8 +17,14 @@
#endif
#include "wx/bitmap.h"
#include "wx/rawbmp.h"
#include "wx/dcmemory.h"
#define ASSERT_EQUAL_RGB(c, r, g, b) \
CPPUNIT_ASSERT_EQUAL( r, (int)c.Red() ); \
CPPUNIT_ASSERT_EQUAL( g, (int)c.Green() ); \
CPPUNIT_ASSERT_EQUAL( b, (int)c.Blue() )
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
@@ -34,9 +40,11 @@ public:
private:
CPPUNIT_TEST_SUITE( BitmapTestCase );
CPPUNIT_TEST( Mask );
CPPUNIT_TEST( OverlappingBlit );
CPPUNIT_TEST_SUITE_END();
void Mask();
void OverlappingBlit();
wxBitmap m_bmp;
@@ -80,3 +88,35 @@ void BitmapTestCase::Mask()
m_bmp.SetMask(mask2);
}
void BitmapTestCase::OverlappingBlit()
{
m_bmp.SetMask( NULL );
// Clear to white.
wxMemoryDC dc(m_bmp);
dc.SetBackground( *wxWHITE );
dc.Clear();
// Draw red line across the top.
dc.SetPen(*wxRED_PEN);
dc.DrawLine(0, 0, 10, 0);
// Scroll down one line.
dc.Blit( 0, 1, 10, 9, &dc, 0, 0 );
// Now, lines 0 and 1 should be red, lines 2++ should still be white.
wxNativePixelData npd( m_bmp );
wxNativePixelData::Iterator it( npd );
ASSERT_EQUAL_RGB( it, 255, 0, 0 );
it.OffsetY( npd, 1 );
ASSERT_EQUAL_RGB( it, 255, 0, 0 );
it.OffsetY( npd, 1 );
ASSERT_EQUAL_RGB( it, 255, 255, 255 );
it.OffsetY( npd, 1 );
ASSERT_EQUAL_RGB( it, 255, 255, 255 );
}