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:
committed by
Vadim Zeitlin
parent
6bd6c94511
commit
607b800444
@@ -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:
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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 );
|
||||
}
|
||||
|
Reference in New Issue
Block a user