From ae20edb5397f6aa9c5bb6800119d0ebf70750984 Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Mon, 17 Dec 2018 11:48:59 +0000 Subject: [PATCH] Fix several problem with wxMemoryDC in wxQt Under wxQT, wxMemoryDC was previously rendering to a temporary image which was only being blitted back to the original wxBitmap when either the DC wx destroyed or a new bitmap was selected (via SelectObject). With these change wxMemoryDCImpl now draws directly to the bitmap managed by wxBitmap, this makes the behaviour more consistent with the MSW and GTK implementations. Closes https://github.com/wxWidgets/wxWidgets/pull/1083 --- include/wx/qt/dc.h | 4 ++-- include/wx/qt/dcscreen.h | 4 +--- src/qt/dc.cpp | 35 +++++++++++++++++++++++------------ src/qt/dcclient.cpp | 2 -- src/qt/dcmemory.cpp | 34 +++++++++------------------------- src/qt/dcscreen.cpp | 20 +++++--------------- 6 files changed, 40 insertions(+), 59 deletions(-) diff --git a/include/wx/qt/dc.h b/include/wx/qt/dc.h index 94623e4201..56849a2124 100644 --- a/include/wx/qt/dc.h +++ b/include/wx/qt/dc.h @@ -111,10 +111,10 @@ public: virtual void* GetHandle() const { return (void*) m_qtPainter; } protected: - virtual QImage *GetQImage() { return m_qtImage; } + virtual QPixmap *GetQPixmap() { return m_qtPixmap; } QPainter *m_qtPainter; - QImage *m_qtImage; + QPixmap *m_qtPixmap; wxRegion *m_clippingRegion; private: diff --git a/include/wx/qt/dcscreen.h b/include/wx/qt/dcscreen.h index c6c19b4848..f2fba75bca 100644 --- a/include/wx/qt/dcscreen.h +++ b/include/wx/qt/dcscreen.h @@ -19,9 +19,7 @@ public: protected: virtual void DoGetSize(int *width, int *height) const wxOVERRIDE; - virtual bool DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const; - - virtual QImage *GetQImage(); + virtual QPixmap *GetQPixmap() wxOVERRIDE; wxDECLARE_ABSTRACT_CLASS(wxScreenDCImpl); }; diff --git a/src/qt/dc.cpp b/src/qt/dc.cpp index 8098a03dcf..737d1554d1 100644 --- a/src/qt/dc.cpp +++ b/src/qt/dc.cpp @@ -47,7 +47,7 @@ wxQtDCImpl::wxQtDCImpl( wxDC *owner ) : wxDCImpl( owner ) { m_clippingRegion = new wxRegion; - m_qtImage = NULL; + m_qtPixmap = NULL; m_rasterColourOp = wxQtNONE; m_qtPenColor = new QColor; m_qtBrushColor = new QColor; @@ -474,15 +474,18 @@ bool wxQtDCImpl::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const if ( col ) { - wxCHECK_MSG( m_qtImage != NULL, false, "This DC doesn't support GetPixel()" ); - - QColor pixel = m_qtImage->pixel( x, y ); + wxCHECK_MSG( m_qtPixmap != NULL, false, "This DC doesn't support GetPixel()" ); + QPixmap pixmap1px = m_qtPixmap->copy( x, y, 1, 1 ); + QImage image = pixmap1px.toImage(); + QColor pixel = image.pixel( 0, 0 ); col->Set( pixel.red(), pixel.green(), pixel.blue(), pixel.alpha() ); return true; } else + { return false; + } } void wxQtDCImpl::DoDrawPoint(wxCoord x, wxCoord y) @@ -739,23 +742,31 @@ bool wxQtDCImpl::DoBlit(wxCoord xdest, wxCoord ydest, { wxQtDCImpl *implSource = (wxQtDCImpl*)source->GetImpl(); - QImage *qtSource = implSource->GetQImage(); + QPixmap *qtSource = implSource->GetQPixmap(); // Not a CHECK on purpose if ( !qtSource ) return false; - QImage qtSourceConverted = *qtSource; - if ( !useMask ) - qtSourceConverted = qtSourceConverted.convertToFormat( QImage::Format_RGB32 ); - // Change logical function wxRasterOperationMode savedMode = GetLogicalFunction(); SetLogicalFunction( rop ); - m_qtPainter->drawImage( QRect( xdest, ydest, width, height ), - qtSourceConverted, - QRect( xsrc, ysrc, width, height ) ); + if ( useMask ) + { + m_qtPainter->drawPixmap( QRect( xdest, ydest, width, height ), + *qtSource, + QRect( xsrc, ysrc, width, height ) ); + } + else + { + QImage qtSourceConverted = qtSource->toImage(); + qtSourceConverted = qtSourceConverted.convertToFormat(QImage::Format_RGB32); + + m_qtPainter->drawImage( QRect( xdest, ydest, width, height ), + qtSourceConverted, + QRect( xsrc, ysrc, width, height ) ); + } SetLogicalFunction( savedMode ); diff --git a/src/qt/dcclient.cpp b/src/qt/dcclient.cpp index 696b69e2d4..eea8088a42 100644 --- a/src/qt/dcclient.cpp +++ b/src/qt/dcclient.cpp @@ -31,7 +31,6 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner ) : wxQtDCImpl( owner ) { m_window = NULL; - m_qtImage = NULL; m_ok = false; m_qtPainter = new QPainter(); } @@ -40,7 +39,6 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *win ) : wxQtDCImpl( owner ) { m_window = win; - m_qtImage = NULL; m_qtPainter = m_window->QtGetPainter(); // if we're not inside a Paint event, painter will invalid m_ok = m_qtPainter != NULL; diff --git a/src/qt/dcmemory.cpp b/src/qt/dcmemory.cpp index 3f85c3e3db..563d1cff1f 100644 --- a/src/qt/dcmemory.cpp +++ b/src/qt/dcmemory.cpp @@ -16,7 +16,6 @@ wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner ) : wxQtDCImpl( owner ) { - m_qtImage = NULL; m_ok = false; m_qtPainter = new QPainter(); } @@ -24,7 +23,6 @@ wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner ) wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxBitmap& bitmap ) : wxQtDCImpl( owner ) { - m_qtImage = NULL; m_ok = false; m_qtPainter = new QPainter(); DoSelect( bitmap ); @@ -33,7 +31,6 @@ wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxBitmap& bitmap ) wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxDC *WXUNUSED(dc) ) : wxQtDCImpl( owner ) { - m_qtImage = NULL; m_ok = false; m_qtPainter = new QPainter(); } @@ -50,34 +47,21 @@ void wxMemoryDCImpl::DoSelect( const wxBitmap& bitmap ) { // Finish the painting in the intermediate image device: m_qtPainter->end(); - - if (m_selected.IsOk() && !m_selected.GetHandle()->isNull()) - { - // Copy intermediate image to the bitmap - m_qtPainter->begin( m_selected.GetHandle() ); - m_qtPainter->drawImage( QPoint( 0, 0 ), *m_qtImage ); - m_qtPainter->end(); - } m_ok = false; } // clean up the intermediate image device: - if ( m_qtImage ) - { - delete m_qtImage; - m_qtImage = NULL; - } - m_selected = bitmap; - if ( bitmap.IsOk() && !bitmap.GetHandle()->isNull() ) { - QPixmap pixmap(*bitmap.GetHandle()); - // apply mask before converting to image - if ( bitmap.GetMask() && bitmap.GetMask()->GetHandle() ) - pixmap.setMask(*bitmap.GetMask()->GetHandle()); - // create the intermediate image for the pixmap: - m_qtImage = new QImage( pixmap.toImage() ); + m_qtPixmap = bitmap.GetHandle(); + if ( bitmap.IsOk() && !m_qtPixmap->isNull() ) + { + // apply mask before drawing + wxMask *mask = bitmap.GetMask(); + if ( mask && mask->GetHandle() ) + m_qtPixmap->setMask(*mask->GetHandle()); + // start drawing on the intermediary device: - m_ok = m_qtPainter->begin( m_qtImage ); + m_ok = m_qtPainter->begin( m_qtPixmap ); SetPen(m_pen); SetBrush(m_brush); diff --git a/src/qt/dcscreen.cpp b/src/qt/dcscreen.cpp index b42445ea3a..12b02f6715 100644 --- a/src/qt/dcscreen.cpp +++ b/src/qt/dcscreen.cpp @@ -21,12 +21,11 @@ wxIMPLEMENT_ABSTRACT_CLASS(wxScreenDCImpl, wxWindowDCImpl); wxScreenDCImpl::wxScreenDCImpl( wxScreenDC *owner ) : wxWindowDCImpl( owner ) { - m_qtImage = NULL; } wxScreenDCImpl::~wxScreenDCImpl( ) { - delete m_qtImage; + delete m_qtPixmap; } void wxScreenDCImpl::DoGetSize(int *width, int *height) const @@ -34,19 +33,10 @@ void wxScreenDCImpl::DoGetSize(int *width, int *height) const wxDisplaySize(width, height); } -bool wxScreenDCImpl::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const -{ -// const_cast(this)->GetQImage(); -// return wxQtDCImpl::DoGetPixel(x, y, col); - x = y = 0; - col = 0; - return false; -} - // defered allocation for blit -QImage *wxScreenDCImpl::GetQImage() +QPixmap *wxScreenDCImpl::GetQPixmap() { - if ( !m_qtImage ) - m_qtImage = new QImage(QApplication::primaryScreen()->grabWindow(QApplication::desktop()->winId()).toImage()); - return m_qtImage; + if ( !m_qtPixmap ) + m_qtPixmap = new QPixmap(QApplication::primaryScreen()->grabWindow(QApplication::desktop()->winId())); + return m_qtPixmap; }