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

Last change on this file since 4720 was 4271, checked in by mervart, 13 years ago
File size: 8.1 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 renderItem(
21 QPainter *painter, const QRect &canvasRect,
22 QwtPlotAbstractSeriesItem *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
36class QwtPlotDirectPainter::PrivateData
37{
38public:
39 PrivateData():
40 attributes( 0 ),
41 hasClipping(false),
42 seriesItem( NULL )
43 {
44 }
45
46 QwtPlotDirectPainter::Attributes attributes;
47
48 bool hasClipping;
49 QRegion clipRegion;
50
51 QPainter painter;
52
53 QwtPlotAbstractSeriesItem *seriesItem;
54 int from;
55 int to;
56};
57
58//! Constructor
59QwtPlotDirectPainter::QwtPlotDirectPainter( QObject *parent ):
60 QObject( parent )
61{
62 d_data = new PrivateData;
63}
64
65//! Destructor
66QwtPlotDirectPainter::~QwtPlotDirectPainter()
67{
68 delete d_data;
69}
70
71/*!
72 Change an attribute
73
74 \param attribute Attribute to change
75 \param on On/Off
76
77 \sa Attribute, testAttribute()
78*/
79void QwtPlotDirectPainter::setAttribute( Attribute attribute, bool on )
80{
81 if ( bool( d_data->attributes & attribute ) != on )
82 {
83 if ( on )
84 d_data->attributes |= attribute;
85 else
86 d_data->attributes &= ~attribute;
87
88 if ( ( attribute == AtomicPainter ) && on )
89 reset();
90 }
91}
92
93/*!
94 Check if a attribute is set.
95
96 \param attribute Attribute to be tested
97 \sa Attribute, setAttribute()
98*/
99bool QwtPlotDirectPainter::testAttribute( Attribute attribute ) const
100{
101 return d_data->attributes & attribute;
102}
103
104/*!
105 En/Disables clipping
106
107 \param enable Enables clipping is true, disable it otherwise
108 \sa hasClipping(), clipRegion(), setClipRegion()
109*/
110void QwtPlotDirectPainter::setClipping( bool enable )
111{
112 d_data->hasClipping = enable;
113}
114
115/*!
116 \return true, when clipping is enabled
117 \sa setClipping(), clipRegion(), setClipRegion()
118*/
119bool QwtPlotDirectPainter::hasClipping() const
120{
121 return d_data->hasClipping;
122}
123
124/*!
125 \brief Assign a clip region and enable clipping
126
127 Depending on the environment setting a proper clip region might improve
128 the performance heavily. F.e. on Qt embedded only the clipped part of
129 the backing store will be copied to a ( maybe unaccelerated ) frame buffer
130 device.
131
132 \param region Clip region
133 \sa clipRegion(), hasClipping(), setClipping()
134*/
135void QwtPlotDirectPainter::setClipRegion( const QRegion &region )
136{
137 d_data->clipRegion = region;
138 d_data->hasClipping = true;
139}
140
141/*!
142 \return Currently set clip region.
143 \sa setClipRegion(), setClipping(), hasClipping()
144*/
145QRegion QwtPlotDirectPainter::clipRegion() const
146{
147 return d_data->clipRegion;
148}
149
150/*!
151 \brief Draw a set of points of a seriesItem.
152
153 When observing an measurement while it is running, new points have to be
154 added to an existing seriesItem. drawSeries can be used to display them avoiding
155 a complete redraw of the canvas.
156
157 Setting plot()->canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true);
158 will result in faster painting, if the paint engine of the canvas widget
159 supports this feature.
160
161 \param seriesItem Item to be painted
162 \param from Index of the first point to be painted
163 \param to Index of the last point to be painted. If to < 0 the
164 series will be painted to its last point.
165*/
166void QwtPlotDirectPainter::drawSeries(
167 QwtPlotAbstractSeriesItem *seriesItem, int from, int to )
168{
169 if ( seriesItem == NULL || seriesItem->plot() == NULL )
170 return;
171
172 QwtPlotCanvas *canvas = seriesItem->plot()->canvas();
173 const QRect canvasRect = canvas->contentsRect();
174
175 const bool hasBackingStore =
176 canvas->testPaintAttribute( QwtPlotCanvas::BackingStore )
177 && canvas->backingStore() && !canvas->backingStore()->isNull();
178
179 if ( hasBackingStore )
180 {
181 QPainter painter( const_cast<QPixmap *>( canvas->backingStore() ) );
182 painter.translate( -canvasRect.x(), -canvasRect.y() );
183
184 if ( d_data->hasClipping )
185 painter.setClipRegion( d_data->clipRegion );
186
187 renderItem( &painter, canvasRect, seriesItem, from, to );
188
189 if ( testAttribute( QwtPlotDirectPainter::FullRepaint ) )
190 {
191 canvas->repaint();
192 return;
193 }
194 }
195
196 bool immediatePaint = true;
197 if ( !canvas->testAttribute( Qt::WA_WState_InPaintEvent ) &&
198 !canvas->testAttribute( Qt::WA_PaintOutsidePaintEvent ) )
199 {
200 immediatePaint = false;
201 }
202
203 if ( immediatePaint )
204 {
205 QwtPlotCanvas *canvas = seriesItem->plot()->canvas();
206 if ( !d_data->painter.isActive() )
207 {
208 reset();
209
210 d_data->painter.begin( canvas );
211 canvas->installEventFilter( this );
212 }
213
214 if ( d_data->hasClipping )
215 {
216 d_data->painter.setClipRegion(
217 QRegion( canvasRect ) & d_data->clipRegion );
218 }
219 else
220 {
221 if ( !d_data->painter.hasClipping() )
222 d_data->painter.setClipRect( canvasRect );
223 }
224
225 renderItem( &d_data->painter, canvasRect, seriesItem, from, to );
226
227 if ( d_data->attributes & QwtPlotDirectPainter::AtomicPainter )
228 {
229 reset();
230 }
231 else
232 {
233 if ( d_data->hasClipping )
234 d_data->painter.setClipping( false );
235 }
236 }
237 else
238 {
239 reset();
240
241 d_data->seriesItem = seriesItem;
242 d_data->from = from;
243 d_data->to = to;
244
245 QRegion clipRegion = canvasRect;
246 if ( d_data->hasClipping )
247 clipRegion &= d_data->clipRegion;
248
249 canvas->installEventFilter( this );
250 canvas->repaint(clipRegion);
251 canvas->removeEventFilter( this );
252
253 d_data->seriesItem = NULL;
254 }
255}
256
257//! Close the internal QPainter
258void QwtPlotDirectPainter::reset()
259{
260 if ( d_data->painter.isActive() )
261 {
262 QWidget *w = ( QWidget * )d_data->painter.device();
263 if ( w )
264 w->removeEventFilter( this );
265
266 d_data->painter.end();
267 }
268}
269
270//! Event filter
271bool QwtPlotDirectPainter::eventFilter( QObject *, QEvent *event )
272{
273 if ( event->type() == QEvent::Paint )
274 {
275 reset();
276
277 if ( d_data->seriesItem )
278 {
279 const QPaintEvent *pe = static_cast< QPaintEvent *>( event );
280
281 QwtPlotCanvas *canvas = d_data->seriesItem->plot()->canvas();
282
283 QPainter painter( canvas );
284 painter.setClipRegion( pe->region() );
285
286 bool copyCache = testAttribute( CopyBackingStore )
287 && canvas->testPaintAttribute( QwtPlotCanvas::BackingStore );
288
289 if ( copyCache )
290 {
291 // is something valid in the cache ?
292 copyCache = ( canvas->backingStore() != NULL )
293 && !canvas->backingStore()->isNull();
294 }
295
296 if ( copyCache )
297 {
298 painter.drawPixmap(
299 canvas->contentsRect().topLeft(),
300 *canvas->backingStore() );
301 }
302 else
303 {
304 renderItem( &painter, canvas->contentsRect(),
305 d_data->seriesItem, d_data->from, d_data->to );
306 }
307
308 return true; // don't call QwtPlotCanvas::paintEvent()
309 }
310 }
311
312 return false;
313}
Note: See TracBrowser for help on using the repository browser.