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; }
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:

View File

@ -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);
};

View File

@ -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 );

View File

@ -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;

View File

@ -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);

View File

@ -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<wxScreenDCImpl*>(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;
}