source: ntrip/trunk/BNC/qwt/qwt_plot_directpainter.cpp@ 8486

Last change on this file since 8486 was 8127, checked in by stoecker, 8 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

File size: 8.3 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_plot_directpainter.h"
11#include "qwt_scale_map.h"
12#include "qwt_plot.h"
13#include "qwt_plot_canvas.h"
14#include "qwt_plot_seriesitem.h"
15#include <qpainter.h>
16#include <qevent.h>
17#include <qapplication.h>
18#include <qpixmap.h>
19
20static inline void qwtRenderItem(
21 QPainter *painter, const QRect &canvasRect,
22 QwtPlotSeriesItem *seriesItem, int from, int to )
23{
24 // A minor performance improvement is possible
25 // with caching the maps. TODO ...
26
27 QwtPlot *plot = seriesItem->plot();
28 const QwtScaleMap xMap = plot->canvasMap( seriesItem->xAxis() );
29 const QwtScaleMap yMap = plot->canvasMap( seriesItem->yAxis() );
30
31 painter->setRenderHint( QPainter::Antialiasing,
32 seriesItem->testRenderHint( QwtPlotItem::RenderAntialiased ) );
33 seriesItem->drawSeries( painter, xMap, yMap, canvasRect, from, to );
34}
35
36static inline bool qwtHasBackingStore( const QwtPlotCanvas *canvas )
37{
38 return canvas->testPaintAttribute( QwtPlotCanvas::BackingStore )
39 && canvas->backingStore() && !canvas->backingStore()->isNull();
40}
41
42class QwtPlotDirectPainter::PrivateData
43{
44public:
45 PrivateData():
46 attributes( 0 ),
47 hasClipping(false),
48 seriesItem( NULL ),
49 from( 0 ),
50 to( 0 )
51 {
52 }
53
54 QwtPlotDirectPainter::Attributes attributes;
55
56 bool hasClipping;
57 QRegion clipRegion;
58
59 QPainter painter;
60
61 QwtPlotSeriesItem *seriesItem;
62 int from;
63 int to;
64};
65
66//! Constructor
67QwtPlotDirectPainter::QwtPlotDirectPainter( QObject *parent ):
68 QObject( parent )
69{
70 d_data = new PrivateData;
71}
72
73//! Destructor
74QwtPlotDirectPainter::~QwtPlotDirectPainter()
75{
76 delete d_data;
77}
78
79/*!
80 Change an attribute
81
82 \param attribute Attribute to change
83 \param on On/Off
84
85 \sa Attribute, testAttribute()
86*/
87void QwtPlotDirectPainter::setAttribute( Attribute attribute, bool on )
88{
89 if ( bool( d_data->attributes & attribute ) != on )
90 {
91 if ( on )
92 d_data->attributes |= attribute;
93 else
94 d_data->attributes &= ~attribute;
95
96 if ( ( attribute == AtomicPainter ) && on )
97 reset();
98 }
99}
100
101/*!
102 \return True, when attribute is enabled
103 \param attribute Attribute to be tested
104 \sa Attribute, setAttribute()
105*/
106bool QwtPlotDirectPainter::testAttribute( Attribute attribute ) const
107{
108 return d_data->attributes & attribute;
109}
110
111/*!
112 En/Disables clipping
113
114 \param enable Enables clipping is true, disable it otherwise
115 \sa hasClipping(), clipRegion(), setClipRegion()
116*/
117void QwtPlotDirectPainter::setClipping( bool enable )
118{
119 d_data->hasClipping = enable;
120}
121
122/*!
123 \return true, when clipping is enabled
124 \sa setClipping(), clipRegion(), setClipRegion()
125*/
126bool QwtPlotDirectPainter::hasClipping() const
127{
128 return d_data->hasClipping;
129}
130
131/*!
132 \brief Assign a clip region and enable clipping
133
134 Depending on the environment setting a proper clip region might improve
135 the performance heavily. F.e. on Qt embedded only the clipped part of
136 the backing store will be copied to a ( maybe unaccelerated ) frame buffer
137 device.
138
139 \param region Clip region
140 \sa clipRegion(), hasClipping(), setClipping()
141*/
142void QwtPlotDirectPainter::setClipRegion( const QRegion &region )
143{
144 d_data->clipRegion = region;
145 d_data->hasClipping = true;
146}
147
148/*!
149 \return Currently set clip region.
150 \sa setClipRegion(), setClipping(), hasClipping()
151*/
152QRegion QwtPlotDirectPainter::clipRegion() const
153{
154 return d_data->clipRegion;
155}
156
157/*!
158 \brief Draw a set of points of a seriesItem.
159
160 When observing an measurement while it is running, new points have to be
161 added to an existing seriesItem. drawSeries() can be used to display them avoiding
162 a complete redraw of the canvas.
163
164 Setting plot()->canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true);
165 will result in faster painting, if the paint engine of the canvas widget
166 supports this feature.
167
168 \param seriesItem Item to be painted
169 \param from Index of the first point to be painted
170 \param to Index of the last point to be painted. If to < 0 the
171 series will be painted to its last point.
172*/
173void QwtPlotDirectPainter::drawSeries(
174 QwtPlotSeriesItem *seriesItem, int from, int to )
175{
176 if ( seriesItem == NULL || seriesItem->plot() == NULL )
177 return;
178
179 QWidget *canvas = seriesItem->plot()->canvas();
180 const QRect canvasRect = canvas->contentsRect();
181
182 QwtPlotCanvas *plotCanvas = qobject_cast<QwtPlotCanvas *>( canvas );
183
184 if ( plotCanvas && qwtHasBackingStore( plotCanvas ) )
185 {
186 QPainter painter( const_cast<QPixmap *>( plotCanvas->backingStore() ) );
187
188 if ( d_data->hasClipping )
189 painter.setClipRegion( d_data->clipRegion );
190
191 qwtRenderItem( &painter, canvasRect, seriesItem, from, to );
192
193 painter.end();
194
195 if ( testAttribute( QwtPlotDirectPainter::FullRepaint ) )
196 {
197 plotCanvas->repaint();
198 return;
199 }
200 }
201
202 bool immediatePaint = true;
203 if ( !canvas->testAttribute( Qt::WA_WState_InPaintEvent ) )
204 {
205#if QT_VERSION < 0x050000
206 if ( !canvas->testAttribute( Qt::WA_PaintOutsidePaintEvent ) )
207#endif
208 immediatePaint = false;
209 }
210
211 if ( immediatePaint )
212 {
213 if ( !d_data->painter.isActive() )
214 {
215 reset();
216
217 d_data->painter.begin( canvas );
218 canvas->installEventFilter( this );
219 }
220
221 if ( d_data->hasClipping )
222 {
223 d_data->painter.setClipRegion(
224 QRegion( canvasRect ) & d_data->clipRegion );
225 }
226 else
227 {
228 if ( !d_data->painter.hasClipping() )
229 d_data->painter.setClipRect( canvasRect );
230 }
231
232 qwtRenderItem( &d_data->painter, canvasRect, seriesItem, from, to );
233
234 if ( d_data->attributes & QwtPlotDirectPainter::AtomicPainter )
235 {
236 reset();
237 }
238 else
239 {
240 if ( d_data->hasClipping )
241 d_data->painter.setClipping( false );
242 }
243 }
244 else
245 {
246 reset();
247
248 d_data->seriesItem = seriesItem;
249 d_data->from = from;
250 d_data->to = to;
251
252 QRegion clipRegion = canvasRect;
253 if ( d_data->hasClipping )
254 clipRegion &= d_data->clipRegion;
255
256 canvas->installEventFilter( this );
257 canvas->repaint(clipRegion);
258 canvas->removeEventFilter( this );
259
260 d_data->seriesItem = NULL;
261 }
262}
263
264//! Close the internal QPainter
265void QwtPlotDirectPainter::reset()
266{
267 if ( d_data->painter.isActive() )
268 {
269 QWidget *w = static_cast<QWidget *>( d_data->painter.device() );
270 if ( w )
271 w->removeEventFilter( this );
272
273 d_data->painter.end();
274 }
275}
276
277//! Event filter
278bool QwtPlotDirectPainter::eventFilter( QObject *, QEvent *event )
279{
280 if ( event->type() == QEvent::Paint )
281 {
282 reset();
283
284 if ( d_data->seriesItem )
285 {
286 const QPaintEvent *pe = static_cast< QPaintEvent *>( event );
287
288 QWidget *canvas = d_data->seriesItem->plot()->canvas();
289
290 QPainter painter( canvas );
291 painter.setClipRegion( pe->region() );
292
293 bool doCopyCache = testAttribute( CopyBackingStore );
294
295 if ( doCopyCache )
296 {
297 QwtPlotCanvas *plotCanvas =
298 qobject_cast<QwtPlotCanvas *>( canvas );
299 if ( plotCanvas )
300 {
301 doCopyCache = qwtHasBackingStore( plotCanvas );
302 if ( doCopyCache )
303 {
304 painter.drawPixmap( plotCanvas->rect().topLeft(),
305 *plotCanvas->backingStore() );
306 }
307 }
308 }
309
310 if ( !doCopyCache )
311 {
312 qwtRenderItem( &painter, canvas->contentsRect(),
313 d_data->seriesItem, d_data->from, d_data->to );
314 }
315
316 return true; // don't call QwtPlotCanvas::paintEvent()
317 }
318 }
319
320 return false;
321}
Note: See TracBrowser for help on using the repository browser.