diff --git a/docs/changes.txt b/docs/changes.txt index bdddc2fa86..cd9d7bb5b4 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -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: diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 5d19524668..a5e19a95d6 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -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); diff --git a/tests/graphics/bitmap.cpp b/tests/graphics/bitmap.cpp index a3f2b8c58f..80f10170bd 100644 --- a/tests/graphics/bitmap.cpp +++ b/tests/graphics/bitmap.cpp @@ -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 ); +}