Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_plot_canvas.h"
00011 #include "qwt_painter.h"
00012 #include "qwt_math.h"
00013 #include "qwt_plot.h"
00014
00015 #ifndef QWT_NO_OPENGL
00016
00017 #if QT_VERSION < 0x050000
00018 #define FBO_OPENGL 0
00019 #else
00020 #define FBO_OPENGL 1
00021 #endif
00022
00023 #if FBO_OPENGL
00024 #include <qopenglcontext.h>
00025 #include <qopenglframebufferobject.h>
00026 #include <qopenglpaintdevice.h>
00027
00028 #if QT_VERSION >= 0x050100
00029 #include <qoffscreensurface.h>
00030 typedef QOffscreenSurface QwtPlotCanvasSurfaceGL;
00031
00032 #else
00033 #include <qwindow.h>
00034 class QwtPlotCanvasSurfaceGL: public QWindow
00035 {
00036 public:
00037 QwtPlotCanvasSurfaceGL() { setSurfaceType( QWindow::OpenGLSurface ); }
00038 };
00039 #endif
00040
00041 #else
00042 #include <qglframebufferobject.h>
00043 typedef QGLWidget QwtPlotCanvasSurfaceGL;
00044 #endif
00045
00046 #endif // !QWT_NO_OPENGL
00047
00048 #include <qpainter.h>
00049 #include <qstyle.h>
00050 #include <qstyleoption.h>
00051 #include <qpaintengine.h>
00052 #include <qevent.h>
00053
00054 class QwtPlotCanvas::PrivateData
00055 {
00056 public:
00057 PrivateData():
00058 paintAttributes( 0 ),
00059 #ifndef QWT_NO_OPENGL
00060 surfaceGL( NULL ),
00061 #endif
00062 backingStore( NULL )
00063 {
00064 }
00065
00066 ~PrivateData()
00067 {
00068 delete backingStore;
00069
00070 #ifndef QWT_NO_OPENGL
00071 delete surfaceGL;
00072 #endif
00073 }
00074
00075 QwtPlotCanvas::PaintAttributes paintAttributes;
00076
00077 #ifndef QWT_NO_OPENGL
00078 QwtPlotCanvasSurfaceGL *surfaceGL;
00079 #endif
00080
00081 QPixmap *backingStore;
00082 };
00083
00090 QwtPlotCanvas::QwtPlotCanvas( QwtPlot *plot ):
00091 QFrame( plot ),
00092 QwtPlotAbstractCanvas( this )
00093 {
00094 d_data = new PrivateData;
00095
00096 setPaintAttribute( QwtPlotCanvas::BackingStore, true );
00097 setPaintAttribute( QwtPlotCanvas::Opaque, true );
00098 setPaintAttribute( QwtPlotCanvas::HackStyledBackground, true );
00099 }
00100
00102 QwtPlotCanvas::~QwtPlotCanvas()
00103 {
00104 delete d_data;
00105 }
00106
00115 void QwtPlotCanvas::setPaintAttribute( PaintAttribute attribute, bool on )
00116 {
00117 if ( bool( d_data->paintAttributes & attribute ) == on )
00118 return;
00119
00120 if ( on )
00121 d_data->paintAttributes |= attribute;
00122 else
00123 d_data->paintAttributes &= ~attribute;
00124
00125 switch ( attribute )
00126 {
00127 case BackingStore:
00128 {
00129 if ( on )
00130 {
00131 if ( d_data->backingStore == NULL )
00132 d_data->backingStore = new QPixmap();
00133
00134 if ( isVisible() )
00135 {
00136 #if QT_VERSION >= 0x050000
00137 *d_data->backingStore = grab( rect() );
00138 #else
00139 *d_data->backingStore =
00140 QPixmap::grabWidget( this, rect() );
00141 #endif
00142 }
00143 }
00144 else
00145 {
00146 delete d_data->backingStore;
00147 d_data->backingStore = NULL;
00148 }
00149 break;
00150 }
00151 case Opaque:
00152 {
00153 if ( on )
00154 setAttribute( Qt::WA_OpaquePaintEvent, true );
00155
00156 break;
00157 }
00158 default:
00159 {
00160 break;
00161 }
00162 }
00163 }
00164
00172 bool QwtPlotCanvas::testPaintAttribute( PaintAttribute attribute ) const
00173 {
00174 return d_data->paintAttributes & attribute;
00175 }
00176
00178 const QPixmap *QwtPlotCanvas::backingStore() const
00179 {
00180 return d_data->backingStore;
00181 }
00182
00184 void QwtPlotCanvas::invalidateBackingStore()
00185 {
00186 if ( d_data->backingStore )
00187 *d_data->backingStore = QPixmap();
00188 }
00189
00196 bool QwtPlotCanvas::event( QEvent *event )
00197 {
00198 if ( event->type() == QEvent::PolishRequest )
00199 {
00200 if ( testPaintAttribute( QwtPlotCanvas::Opaque ) )
00201 {
00202
00203
00204
00205
00206 setAttribute( Qt::WA_OpaquePaintEvent, true );
00207 }
00208 }
00209
00210 if ( event->type() == QEvent::PolishRequest ||
00211 event->type() == QEvent::StyleChange )
00212 {
00213 updateStyleSheetInfo();
00214 }
00215
00216 return QFrame::event( event );
00217 }
00218
00223 void QwtPlotCanvas::paintEvent( QPaintEvent *event )
00224 {
00225 QPainter painter( this );
00226 painter.setClipRegion( event->region() );
00227
00228 if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) &&
00229 d_data->backingStore != NULL )
00230 {
00231 QPixmap &bs = *d_data->backingStore;
00232 if ( bs.size() != size() )
00233 {
00234 bs = QwtPainter::backingStore( this, size() );
00235
00236 #ifndef QWT_NO_OPENGL
00237 if ( testPaintAttribute( OpenGLBuffer ) )
00238 {
00239 QPainter p( &bs );
00240 p.drawImage( 0, 0, toImageFBO( size() ) );
00241 p.end();
00242 }
00243 else
00244 #endif
00245 if ( testAttribute(Qt::WA_StyledBackground) )
00246 {
00247 QPainter p( &bs );
00248 drawStyled( &p, testPaintAttribute( HackStyledBackground ) );
00249 }
00250 else
00251 {
00252 QPainter p;
00253 if ( borderRadius() <= 0.0 )
00254 {
00255 QwtPainter::fillPixmap( this, bs );
00256 p.begin( &bs );
00257 drawCanvas( &p );
00258 }
00259 else
00260 {
00261 p.begin( &bs );
00262 drawUnstyled( &p );
00263 }
00264
00265 if ( frameWidth() > 0 )
00266 drawBorder( &p );
00267 }
00268 }
00269
00270 painter.drawPixmap( 0, 0, *d_data->backingStore );
00271 }
00272 else
00273 {
00274 #ifndef QWT_NO_OPENGL
00275 if ( testPaintAttribute( OpenGLBuffer ) )
00276 {
00277 painter.drawImage( 0, 0, toImageFBO( size() ) );
00278 }
00279 else
00280 #endif
00281 if ( testAttribute(Qt::WA_StyledBackground ) )
00282 {
00283 if ( testAttribute( Qt::WA_OpaquePaintEvent ) )
00284 {
00285 drawStyled( &painter, testPaintAttribute( HackStyledBackground ) );
00286 }
00287 else
00288 {
00289 drawCanvas( &painter );
00290 }
00291 }
00292 else
00293 {
00294 if ( testAttribute( Qt::WA_OpaquePaintEvent ) )
00295 {
00296 if ( autoFillBackground() )
00297 {
00298 fillBackground( &painter );
00299 drawBackground( &painter );
00300 }
00301 }
00302 else
00303 {
00304 if ( borderRadius() > 0.0 )
00305 {
00306 QPainterPath clipPath;
00307 clipPath.addRect( rect() );
00308 clipPath = clipPath.subtracted( borderPath( rect() ) );
00309
00310 painter.save();
00311
00312 painter.setClipPath( clipPath, Qt::IntersectClip );
00313 fillBackground( &painter );
00314 drawBackground( &painter );
00315
00316 painter.restore();
00317 }
00318 }
00319
00320 drawCanvas( &painter );
00321
00322 if ( frameWidth() > 0 )
00323 drawBorder( &painter );
00324 }
00325 }
00326
00327 if ( hasFocus() && focusIndicator() == CanvasFocusIndicator )
00328 drawFocusIndicator( &painter );
00329 }
00330
00337 void QwtPlotCanvas::drawBorder( QPainter *painter )
00338 {
00339 #if QT_VERSION >= 0x040500
00340 if ( borderRadius() <= 0 )
00341 {
00342 drawFrame( painter );
00343 return;
00344 }
00345 #endif
00346
00347 QwtPlotAbstractCanvas::drawBorder( painter );
00348 }
00349
00354 void QwtPlotCanvas::resizeEvent( QResizeEvent *event )
00355 {
00356 QFrame::resizeEvent( event );
00357 updateStyleSheetInfo();
00358 }
00359
00364 void QwtPlotCanvas::replot()
00365 {
00366 invalidateBackingStore();
00367
00368 if ( testPaintAttribute( QwtPlotCanvas::ImmediatePaint ) )
00369 repaint( contentsRect() );
00370 else
00371 update( contentsRect() );
00372 }
00373
00383 QPainterPath QwtPlotCanvas::borderPath( const QRect &rect ) const
00384 {
00385 return borderPath2( rect );
00386 }
00387
00388 #ifndef QWT_NO_OPENGL
00389
00390 #define FIX_GL_TRANSLATION 0
00391
00392 QImage QwtPlotCanvas::toImageFBO( const QSize &size )
00393 {
00394 const int numSamples = 4;
00395
00396 #if FBO_OPENGL
00397
00398 if ( d_data->surfaceGL == NULL )
00399 {
00400 d_data->surfaceGL = new QwtPlotCanvasSurfaceGL();
00401 d_data->surfaceGL->create();
00402 }
00403
00404 QOpenGLContext context;
00405 context.create();
00406
00407 context.makeCurrent( d_data->surfaceGL );
00408
00409
00410 QOpenGLFramebufferObjectFormat fboFormat;
00411 fboFormat.setSamples(numSamples);
00412 QOpenGLFramebufferObject fbo( size, fboFormat );
00413
00414 QOpenGLPaintDevice pd( size );
00415
00416 #else
00417
00418 if ( d_data->surfaceGL == NULL )
00419 {
00420 QGLFormat format = QGLFormat::defaultFormat();
00421 format.setSampleBuffers( true );
00422 format.setSamples( numSamples );
00423
00424 d_data->surfaceGL = new QwtPlotCanvasSurfaceGL( format );
00425 }
00426
00427 d_data->surfaceGL->makeCurrent();
00428
00429 #if QT_VERSION >= 0x040600
00430 QGLFramebufferObjectFormat fboFormat;
00431 fboFormat.setSamples(numSamples);
00432
00433 QGLFramebufferObject fbo( size, fboFormat );
00434 #else
00435 QGLFramebufferObject fbo( size );
00436 #endif
00437 QGLFramebufferObject &pd = fbo;
00438
00439 #endif
00440
00441 QPainter painter( &pd );
00442
00443 if ( testAttribute( Qt::WA_StyledBackground ) )
00444 drawStyled( &painter, testPaintAttribute( HackStyledBackground ) );
00445 else
00446 drawUnstyled( &painter );
00447
00448 if ( frameWidth() > 0 )
00449 drawBorder( &painter );
00450
00451 painter.end();
00452
00453 QImage image = fbo.toImage();
00454
00455 #if QT_VERSION >= 0x050000
00456 image.setDevicePixelRatio( QwtPainter::devicePixelRatio( this ) );
00457 #endif
00458 return image;
00459 }
00460
00461 #else
00462
00463 QImage QwtPlotCanvas::toImageFBO( const QSize &)
00464 {
00465
00466 return QImage();
00467 }
00468
00469 #endif