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
This commit is contained in:
Graham Dawes
2018-12-17 11:48:59 +00:00
committed by Vadim Zeitlin
parent 80904d1bc7
commit ae20edb539
6 changed files with 40 additions and 59 deletions

View File

@@ -111,10 +111,10 @@ public:
virtual void* GetHandle() const { return (void*) m_qtPainter; } virtual void* GetHandle() const { return (void*) m_qtPainter; }
protected: protected:
virtual QImage *GetQImage() { return m_qtImage; } virtual QPixmap *GetQPixmap() { return m_qtPixmap; }
QPainter *m_qtPainter; QPainter *m_qtPainter;
QImage *m_qtImage; QPixmap *m_qtPixmap;
wxRegion *m_clippingRegion; wxRegion *m_clippingRegion;
private: private:

View File

@@ -19,9 +19,7 @@ public:
protected: protected:
virtual void DoGetSize(int *width, int *height) const wxOVERRIDE; virtual void DoGetSize(int *width, int *height) const wxOVERRIDE;
virtual bool DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const; virtual QPixmap *GetQPixmap() wxOVERRIDE;
virtual QImage *GetQImage();
wxDECLARE_ABSTRACT_CLASS(wxScreenDCImpl); wxDECLARE_ABSTRACT_CLASS(wxScreenDCImpl);
}; };

View File

@@ -47,7 +47,7 @@ wxQtDCImpl::wxQtDCImpl( wxDC *owner )
: wxDCImpl( owner ) : wxDCImpl( owner )
{ {
m_clippingRegion = new wxRegion; m_clippingRegion = new wxRegion;
m_qtImage = NULL; m_qtPixmap = NULL;
m_rasterColourOp = wxQtNONE; m_rasterColourOp = wxQtNONE;
m_qtPenColor = new QColor; m_qtPenColor = new QColor;
m_qtBrushColor = new QColor; m_qtBrushColor = new QColor;
@@ -474,15 +474,18 @@ bool wxQtDCImpl::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
if ( col ) if ( col )
{ {
wxCHECK_MSG( m_qtImage != NULL, false, "This DC doesn't support GetPixel()" ); wxCHECK_MSG( m_qtPixmap != NULL, false, "This DC doesn't support GetPixel()" );
QPixmap pixmap1px = m_qtPixmap->copy( x, y, 1, 1 );
QColor pixel = m_qtImage->pixel( x, y ); QImage image = pixmap1px.toImage();
QColor pixel = image.pixel( 0, 0 );
col->Set( pixel.red(), pixel.green(), pixel.blue(), pixel.alpha() ); col->Set( pixel.red(), pixel.green(), pixel.blue(), pixel.alpha() );
return true; return true;
} }
else else
{
return false; return false;
}
} }
void wxQtDCImpl::DoDrawPoint(wxCoord x, wxCoord y) void wxQtDCImpl::DoDrawPoint(wxCoord x, wxCoord y)
@@ -739,23 +742,31 @@ bool wxQtDCImpl::DoBlit(wxCoord xdest, wxCoord ydest,
{ {
wxQtDCImpl *implSource = (wxQtDCImpl*)source->GetImpl(); wxQtDCImpl *implSource = (wxQtDCImpl*)source->GetImpl();
QImage *qtSource = implSource->GetQImage(); QPixmap *qtSource = implSource->GetQPixmap();
// Not a CHECK on purpose // Not a CHECK on purpose
if ( !qtSource ) if ( !qtSource )
return false; return false;
QImage qtSourceConverted = *qtSource;
if ( !useMask )
qtSourceConverted = qtSourceConverted.convertToFormat( QImage::Format_RGB32 );
// Change logical function // Change logical function
wxRasterOperationMode savedMode = GetLogicalFunction(); wxRasterOperationMode savedMode = GetLogicalFunction();
SetLogicalFunction( rop ); SetLogicalFunction( rop );
m_qtPainter->drawImage( QRect( xdest, ydest, width, height ), if ( useMask )
qtSourceConverted, {
QRect( xsrc, ysrc, width, height ) ); 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 ); SetLogicalFunction( savedMode );

View File

@@ -31,7 +31,6 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner )
: wxQtDCImpl( owner ) : wxQtDCImpl( owner )
{ {
m_window = NULL; m_window = NULL;
m_qtImage = NULL;
m_ok = false; m_ok = false;
m_qtPainter = new QPainter(); m_qtPainter = new QPainter();
} }
@@ -40,7 +39,6 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *win )
: wxQtDCImpl( owner ) : wxQtDCImpl( owner )
{ {
m_window = win; m_window = win;
m_qtImage = NULL;
m_qtPainter = m_window->QtGetPainter(); m_qtPainter = m_window->QtGetPainter();
// if we're not inside a Paint event, painter will invalid // if we're not inside a Paint event, painter will invalid
m_ok = m_qtPainter != NULL; m_ok = m_qtPainter != NULL;

View File

@@ -16,7 +16,6 @@
wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner ) wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner )
: wxQtDCImpl( owner ) : wxQtDCImpl( owner )
{ {
m_qtImage = NULL;
m_ok = false; m_ok = false;
m_qtPainter = new QPainter(); m_qtPainter = new QPainter();
} }
@@ -24,7 +23,6 @@ wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner )
wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxBitmap& bitmap ) wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxBitmap& bitmap )
: wxQtDCImpl( owner ) : wxQtDCImpl( owner )
{ {
m_qtImage = NULL;
m_ok = false; m_ok = false;
m_qtPainter = new QPainter(); m_qtPainter = new QPainter();
DoSelect( bitmap ); DoSelect( bitmap );
@@ -33,7 +31,6 @@ wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxBitmap& bitmap )
wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxDC *WXUNUSED(dc) ) wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxDC *WXUNUSED(dc) )
: wxQtDCImpl( owner ) : wxQtDCImpl( owner )
{ {
m_qtImage = NULL;
m_ok = false; m_ok = false;
m_qtPainter = new QPainter(); m_qtPainter = new QPainter();
} }
@@ -50,34 +47,21 @@ void wxMemoryDCImpl::DoSelect( const wxBitmap& bitmap )
{ {
// Finish the painting in the intermediate image device: // Finish the painting in the intermediate image device:
m_qtPainter->end(); 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; m_ok = false;
} }
// clean up the intermediate image device: // clean up the intermediate image device:
if ( m_qtImage )
{
delete m_qtImage;
m_qtImage = NULL;
}
m_selected = bitmap; m_selected = bitmap;
if ( bitmap.IsOk() && !bitmap.GetHandle()->isNull() ) { m_qtPixmap = bitmap.GetHandle();
QPixmap pixmap(*bitmap.GetHandle()); if ( bitmap.IsOk() && !m_qtPixmap->isNull() )
// apply mask before converting to image {
if ( bitmap.GetMask() && bitmap.GetMask()->GetHandle() ) // apply mask before drawing
pixmap.setMask(*bitmap.GetMask()->GetHandle()); wxMask *mask = bitmap.GetMask();
// create the intermediate image for the pixmap: if ( mask && mask->GetHandle() )
m_qtImage = new QImage( pixmap.toImage() ); m_qtPixmap->setMask(*mask->GetHandle());
// start drawing on the intermediary device: // start drawing on the intermediary device:
m_ok = m_qtPainter->begin( m_qtImage ); m_ok = m_qtPainter->begin( m_qtPixmap );
SetPen(m_pen); SetPen(m_pen);
SetBrush(m_brush); SetBrush(m_brush);

View File

@@ -21,12 +21,11 @@ wxIMPLEMENT_ABSTRACT_CLASS(wxScreenDCImpl, wxWindowDCImpl);
wxScreenDCImpl::wxScreenDCImpl( wxScreenDC *owner ) wxScreenDCImpl::wxScreenDCImpl( wxScreenDC *owner )
: wxWindowDCImpl( owner ) : wxWindowDCImpl( owner )
{ {
m_qtImage = NULL;
} }
wxScreenDCImpl::~wxScreenDCImpl( ) wxScreenDCImpl::~wxScreenDCImpl( )
{ {
delete m_qtImage; delete m_qtPixmap;
} }
void wxScreenDCImpl::DoGetSize(int *width, int *height) const void wxScreenDCImpl::DoGetSize(int *width, int *height) const
@@ -34,19 +33,10 @@ void wxScreenDCImpl::DoGetSize(int *width, int *height) const
wxDisplaySize(width, height); wxDisplaySize(width, height);
} }
bool wxScreenDCImpl::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
{
// const_cast<wxScreenDCImpl*>(this)->GetQImage();
// return wxQtDCImpl::DoGetPixel(x, y, col);
x = y = 0;
col = 0;
return false;
}
// defered allocation for blit // defered allocation for blit
QImage *wxScreenDCImpl::GetQImage() QPixmap *wxScreenDCImpl::GetQPixmap()
{ {
if ( !m_qtImage ) if ( !m_qtPixmap )
m_qtImage = new QImage(QApplication::primaryScreen()->grabWindow(QApplication::desktop()->winId()).toImage()); m_qtPixmap = new QPixmap(QApplication::primaryScreen()->grabWindow(QApplication::desktop()->winId()));
return m_qtImage; return m_qtPixmap;
} }