Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_plot_directpainter.h"
00011 #include "qwt_scale_map.h"
00012 #include "qwt_plot.h"
00013 #include "qwt_plot_canvas.h"
00014 #include "qwt_plot_seriesitem.h"
00015 #include <qpainter.h>
00016 #include <qevent.h>
00017 #include <qapplication.h>
00018 #include <qpixmap.h>
00019
00020 static inline void qwtRenderItem(
00021 QPainter *painter, const QRect &canvasRect,
00022 QwtPlotSeriesItem *seriesItem, int from, int to )
00023 {
00024
00025
00026
00027 QwtPlot *plot = seriesItem->plot();
00028 const QwtScaleMap xMap = plot->canvasMap( seriesItem->xAxis() );
00029 const QwtScaleMap yMap = plot->canvasMap( seriesItem->yAxis() );
00030
00031 painter->setRenderHint( QPainter::Antialiasing,
00032 seriesItem->testRenderHint( QwtPlotItem::RenderAntialiased ) );
00033 seriesItem->drawSeries( painter, xMap, yMap, canvasRect, from, to );
00034 }
00035
00036 static inline bool qwtHasBackingStore( const QwtPlotCanvas *canvas )
00037 {
00038 return canvas->testPaintAttribute( QwtPlotCanvas::BackingStore )
00039 && canvas->backingStore() && !canvas->backingStore()->isNull();
00040 }
00041
00042 class QwtPlotDirectPainter::PrivateData
00043 {
00044 public:
00045 PrivateData():
00046 attributes( 0 ),
00047 hasClipping(false),
00048 seriesItem( NULL ),
00049 from( 0 ),
00050 to( 0 )
00051 {
00052 }
00053
00054 QwtPlotDirectPainter::Attributes attributes;
00055
00056 bool hasClipping;
00057 QRegion clipRegion;
00058
00059 QPainter painter;
00060
00061 QwtPlotSeriesItem *seriesItem;
00062 int from;
00063 int to;
00064 };
00065
00067 QwtPlotDirectPainter::QwtPlotDirectPainter( QObject *parent ):
00068 QObject( parent )
00069 {
00070 d_data = new PrivateData;
00071 }
00072
00074 QwtPlotDirectPainter::~QwtPlotDirectPainter()
00075 {
00076 delete d_data;
00077 }
00078
00087 void QwtPlotDirectPainter::setAttribute( Attribute attribute, bool on )
00088 {
00089 if ( bool( d_data->attributes & attribute ) != on )
00090 {
00091 if ( on )
00092 d_data->attributes |= attribute;
00093 else
00094 d_data->attributes &= ~attribute;
00095
00096 if ( ( attribute == AtomicPainter ) && on )
00097 reset();
00098 }
00099 }
00100
00106 bool QwtPlotDirectPainter::testAttribute( Attribute attribute ) const
00107 {
00108 return d_data->attributes & attribute;
00109 }
00110
00117 void QwtPlotDirectPainter::setClipping( bool enable )
00118 {
00119 d_data->hasClipping = enable;
00120 }
00121
00126 bool QwtPlotDirectPainter::hasClipping() const
00127 {
00128 return d_data->hasClipping;
00129 }
00130
00142 void QwtPlotDirectPainter::setClipRegion( const QRegion ®ion )
00143 {
00144 d_data->clipRegion = region;
00145 d_data->hasClipping = true;
00146 }
00147
00152 QRegion QwtPlotDirectPainter::clipRegion() const
00153 {
00154 return d_data->clipRegion;
00155 }
00156
00173 void QwtPlotDirectPainter::drawSeries(
00174 QwtPlotSeriesItem *seriesItem, int from, int to )
00175 {
00176 if ( seriesItem == NULL || seriesItem->plot() == NULL )
00177 return;
00178
00179 QWidget *canvas = seriesItem->plot()->canvas();
00180 const QRect canvasRect = canvas->contentsRect();
00181
00182 QwtPlotCanvas *plotCanvas = qobject_cast<QwtPlotCanvas *>( canvas );
00183
00184 if ( plotCanvas && qwtHasBackingStore( plotCanvas ) )
00185 {
00186 QPainter painter( const_cast<QPixmap *>( plotCanvas->backingStore() ) );
00187
00188 if ( d_data->hasClipping )
00189 painter.setClipRegion( d_data->clipRegion );
00190
00191 qwtRenderItem( &painter, canvasRect, seriesItem, from, to );
00192
00193 painter.end();
00194
00195 if ( testAttribute( QwtPlotDirectPainter::FullRepaint ) )
00196 {
00197 plotCanvas->repaint();
00198 return;
00199 }
00200 }
00201
00202 bool immediatePaint = true;
00203 if ( !canvas->testAttribute( Qt::WA_WState_InPaintEvent ) )
00204 {
00205 #if QT_VERSION < 0x050000
00206 if ( !canvas->testAttribute( Qt::WA_PaintOutsidePaintEvent ) )
00207 #endif
00208 immediatePaint = false;
00209 }
00210
00211 if ( immediatePaint )
00212 {
00213 if ( !d_data->painter.isActive() )
00214 {
00215 reset();
00216
00217 d_data->painter.begin( canvas );
00218 canvas->installEventFilter( this );
00219 }
00220
00221 if ( d_data->hasClipping )
00222 {
00223 d_data->painter.setClipRegion(
00224 QRegion( canvasRect ) & d_data->clipRegion );
00225 }
00226 else
00227 {
00228 if ( !d_data->painter.hasClipping() )
00229 d_data->painter.setClipRect( canvasRect );
00230 }
00231
00232 qwtRenderItem( &d_data->painter, canvasRect, seriesItem, from, to );
00233
00234 if ( d_data->attributes & QwtPlotDirectPainter::AtomicPainter )
00235 {
00236 reset();
00237 }
00238 else
00239 {
00240 if ( d_data->hasClipping )
00241 d_data->painter.setClipping( false );
00242 }
00243 }
00244 else
00245 {
00246 reset();
00247
00248 d_data->seriesItem = seriesItem;
00249 d_data->from = from;
00250 d_data->to = to;
00251
00252 QRegion clipRegion = canvasRect;
00253 if ( d_data->hasClipping )
00254 clipRegion &= d_data->clipRegion;
00255
00256 canvas->installEventFilter( this );
00257 canvas->repaint(clipRegion);
00258 canvas->removeEventFilter( this );
00259
00260 d_data->seriesItem = NULL;
00261 }
00262 }
00263
00265 void QwtPlotDirectPainter::reset()
00266 {
00267 if ( d_data->painter.isActive() )
00268 {
00269 QWidget *w = static_cast<QWidget *>( d_data->painter.device() );
00270 if ( w )
00271 w->removeEventFilter( this );
00272
00273 d_data->painter.end();
00274 }
00275 }
00276
00278 bool QwtPlotDirectPainter::eventFilter( QObject *, QEvent *event )
00279 {
00280 if ( event->type() == QEvent::Paint )
00281 {
00282 reset();
00283
00284 if ( d_data->seriesItem )
00285 {
00286 const QPaintEvent *pe = static_cast< QPaintEvent *>( event );
00287
00288 QWidget *canvas = d_data->seriesItem->plot()->canvas();
00289
00290 QPainter painter( canvas );
00291 painter.setClipRegion( pe->region() );
00292
00293 bool doCopyCache = testAttribute( CopyBackingStore );
00294
00295 if ( doCopyCache )
00296 {
00297 QwtPlotCanvas *plotCanvas =
00298 qobject_cast<QwtPlotCanvas *>( canvas );
00299 if ( plotCanvas )
00300 {
00301 doCopyCache = qwtHasBackingStore( plotCanvas );
00302 if ( doCopyCache )
00303 {
00304 painter.drawPixmap( plotCanvas->rect().topLeft(),
00305 *plotCanvas->backingStore() );
00306 }
00307 }
00308 }
00309
00310 if ( !doCopyCache )
00311 {
00312 qwtRenderItem( &painter, canvas->contentsRect(),
00313 d_data->seriesItem, d_data->from, d_data->to );
00314 }
00315
00316 return true;
00317 }
00318 }
00319
00320 return false;
00321 }