From db15e9988474840e9518c7d2a8f70648add5f370 Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Wed, 12 Dec 2018 09:03:10 +0000 Subject: [PATCH] Fix wxBitmap::GetRawData() in wxQt This method used to return a dangling pointer to a temporary buffer, which resulted in a crash when using it, e.g. in the unit test. Fix this by keeping a QImage as a member in wxBitmapRefData, so that the pointer to its data remain valid until UngetRawData() is called. Also check that GetRawData() returns a non-null pointer in the test. Closes https://github.com/wxWidgets/wxWidgets/pull/1067 --- src/qt/bitmap.cpp | 25 +++++++++++++++---------- tests/graphics/bitmap.cpp | 1 + 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/qt/bitmap.cpp b/src/qt/bitmap.cpp index 6f632a1931..31f1380c06 100644 --- a/src/qt/bitmap.cpp +++ b/src/qt/bitmap.cpp @@ -144,6 +144,7 @@ class wxBitmapRefData: public wxGDIRefData virtual ~wxBitmapRefData() { delete m_mask; } QPixmap m_qtPixmap; + QImage m_rawPixelSource; wxMask *m_mask; private: @@ -409,17 +410,19 @@ void wxBitmap::SetDepth(int depth) void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp) { void* bits = NULL; - // allow access if bpp is valid and matches existence of alpha - if ( !M_PIXDATA.isNull() ) + + wxBitmapRefData *refData = static_cast(m_refData); + + // allow access if bpp is valid + if ( !refData->m_qtPixmap.isNull() ) { - QImage qimage = M_PIXDATA.toImage(); - bool hasAlpha = M_PIXDATA.hasAlphaChannel(); - if ((bpp == 24 && !hasAlpha) || (bpp == 32 && hasAlpha)) + if ( bpp == 32 ) { - data.m_height = qimage.height(); - data.m_width = qimage.width(); - data.m_stride = qimage.bytesPerLine(); - bits = (void*) qimage.bits(); + refData->m_rawPixelSource = refData->m_qtPixmap.toImage().convertToFormat(QImage::Format_RGBA8888); + data.m_height = refData->m_rawPixelSource.height(); + data.m_width = refData->m_rawPixelSource.width(); + data.m_stride = refData->m_rawPixelSource.bytesPerLine(); + bits = refData->m_rawPixelSource.bits(); } } return bits; @@ -427,7 +430,9 @@ void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp) void wxBitmap::UngetRawData(wxPixelDataBase& WXUNUSED(data)) { - wxMISSING_IMPLEMENTATION( __FUNCTION__ ); + wxBitmapRefData *refData = static_cast(m_refData); + refData->m_qtPixmap = QPixmap::fromImage(refData->m_rawPixelSource); + refData->m_rawPixelSource = QImage(); } QPixmap *wxBitmap::GetHandle() const diff --git a/tests/graphics/bitmap.cpp b/tests/graphics/bitmap.cpp index a93062e157..b07f348b08 100644 --- a/tests/graphics/bitmap.cpp +++ b/tests/graphics/bitmap.cpp @@ -126,6 +126,7 @@ void BitmapTestCase::OverlappingBlit() if ( m_bmp.GetDepth() == 32 ) { wxAlphaPixelData npd( m_bmp ); + CPPUNIT_ASSERT_MESSAGE( "Expected raw pixels to not be NULL", npd ); wxAlphaPixelData::Iterator it( npd ); ASSERT_EQUAL_RGB( it, 255, 0, 0 );