qwt_widget_overlay.cpp
Go to the documentation of this file.
1 /******************************************************************************
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_widget_overlay.h"
11 #include "qwt_painter.h"
12 
13 #include <qpainter.h>
14 #include <qpaintengine.h>
15 #include <qpainterpath.h>
16 #include <qimage.h>
17 #include <qevent.h>
18 
19 #include <cstdlib>
20 
21 static QImage::Format qwtMaskImageFormat()
22 {
24  return QImage::Format_ARGB32;
25 
26  return QImage::Format_ARGB32_Premultiplied;
27 }
28 
29 static QRegion qwtAlphaMask( const QImage& image, const QRegion& region )
30 {
31  const int w = image.width();
32  const int h = image.height();
33 
34  QRegion mask;
35  QRect rect;
36 
37 #if QT_VERSION >= 0x050800
38  for ( QRegion::const_iterator it = region.cbegin();
39  it != region.cend(); ++it )
40  {
41  const QRect& r = *it;
42 #else
43  const QVector< QRect > rects = region.rects();
44  for ( int i = 0; i < rects.size(); i++ )
45  {
46  const QRect& r = rects[i];
47 #endif
48  int x1, x2, y1, y2;
49  r.getCoords( &x1, &y1, &x2, &y2 );
50 
51  x1 = qMax( x1, 0 );
52  x2 = qMin( x2, w - 1 );
53  y1 = qMax( y1, 0 );
54  y2 = qMin( y2, h - 1 );
55 
56  for ( int y = y1; y <= y2; ++y )
57  {
58  bool inRect = false;
59  int rx0 = -1;
60 
61  const uint* line =
62  reinterpret_cast< const uint* > ( image.scanLine( y ) ) + x1;
63  for ( int x = x1; x <= x2; x++ )
64  {
65  const bool on = ( ( *line++ >> 24 ) != 0 );
66  if ( on != inRect )
67  {
68  if ( inRect )
69  {
70  rect.setCoords( rx0, y, x - 1, y );
71  mask += rect;
72  }
73  else
74  {
75  rx0 = x;
76  }
77 
78  inRect = on;
79  }
80  }
81 
82  if ( inRect )
83  {
84  rect.setCoords( rx0, y, x2, y );
85  mask = mask.united( rect );
86  }
87  }
88  }
89 
90  return mask;
91 }
92 
94 {
95  public:
99  , rgbaBuffer( NULL )
100  {
101  }
102 
104  {
105  resetRgbaBuffer();
106  }
107 
109  {
110  if ( rgbaBuffer )
111  {
112  std::free( rgbaBuffer );
113  rgbaBuffer = NULL;
114  }
115  }
116 
120 };
121 
127  : QWidget( widget )
128 {
129  m_data = new PrivateData;
130 
131  setAttribute( Qt::WA_TransparentForMouseEvents );
132  setAttribute( Qt::WA_NoSystemBackground );
133  setFocusPolicy( Qt::NoFocus );
134 
135  if ( widget )
136  {
137  resize( widget->size() );
138  widget->installEventFilter( this );
139  }
140 }
141 
144 {
145  delete m_data;
146 }
147 
155 {
156  if ( mode != m_data->maskMode )
157  {
158  m_data->maskMode = mode;
160  }
161 }
162 
168 {
169  return m_data->maskMode;
170 }
171 
179 {
180  m_data->renderMode = mode;
181 }
182 
188 {
189  return m_data->renderMode;
190 }
191 
196 {
197  updateMask();
198  update();
199 }
200 
202 {
204 
205  QRegion mask;
206 
208  {
209  mask = maskHint();
210  }
212  {
213  // TODO: the image doesn't need to be larger than
214  // the bounding rectangle of the hint !!
215 
216  QRegion hint = maskHint();
217  if ( hint.isEmpty() )
218  hint += QRect( 0, 0, width(), height() );
219 
220  // A fresh buffer from calloc() is usually faster
221  // than reinitializing an existing one with
222  // QImage::fill( 0 ) or memset()
223 
224  m_data->rgbaBuffer = ( uchar* )::calloc( width() * height(), 4 );
225 
226  QImage image( m_data->rgbaBuffer,
227  width(), height(), qwtMaskImageFormat() );
228 
229  QPainter painter( &image );
230  draw( &painter );
231  painter.end();
232 
233  mask = qwtAlphaMask( image, hint );
234 
236  {
237  // we don't need the buffer later
239  }
240  }
241 
242  // A bug in Qt initiates a full repaint of the widget
243  // when we change the mask, while we are visible !
244 
245  setVisible( false );
246 
247  if ( mask.isEmpty() )
248  clearMask();
249  else
250  setMask( mask );
251 
252  setVisible( true );
253 }
254 
261 void QwtWidgetOverlay::paintEvent( QPaintEvent* event )
262 {
263  const QRegion& clipRegion = event->region();
264 
265  QPainter painter( this );
266 
267  bool useRgbaBuffer = false;
269  {
270  useRgbaBuffer = true;
271  }
273  {
274  if ( painter.paintEngine()->type() == QPaintEngine::Raster )
275  useRgbaBuffer = true;
276  }
277 
278  if ( m_data->rgbaBuffer && useRgbaBuffer )
279  {
280  const QImage image( m_data->rgbaBuffer,
281  width(), height(), qwtMaskImageFormat() );
282 
283  const int rectCount = clipRegion.rectCount();
284 
285  if ( rectCount > 2000 )
286  {
287  // the region is to complex
288  painter.setClipRegion( clipRegion );
289 
290  const QRect r = clipRegion.boundingRect();
291  painter.drawImage( r.topLeft(), image, r );
292  }
293  else
294  {
295 #if QT_VERSION >= 0x050800
296  for ( QRegion::const_iterator it = clipRegion.cbegin();
297  it != clipRegion.cend(); ++it )
298  {
299  const QRect& r = *it;
300  painter.drawImage( r.topLeft(), image, r );
301  }
302 #else
303  const QVector< QRect > rects = clipRegion.rects();
304  for ( int i = 0; i < rects.size(); i++ )
305  {
306  const QRect& r = rects[i];
307  painter.drawImage( r.topLeft(), image, r );
308  }
309 #endif
310  }
311  }
312  else
313  {
314  painter.setClipRegion( clipRegion );
315  draw( &painter );
316  }
317 }
318 
323 void QwtWidgetOverlay::resizeEvent( QResizeEvent* event )
324 {
325  Q_UNUSED( event );
326 
328 }
329 
330 void QwtWidgetOverlay::draw( QPainter* painter ) const
331 {
332  if ( QWidget* widget = parentWidget() )
333  {
334  painter->setClipRect( widget->contentsRect() );
335 
336  // something special for the plot canvas
337 
338  const int idx = widget->metaObject()->indexOfMethod( "borderPath(QRect)" );
339  if ( idx >= 0 )
340  {
341  QPainterPath clipPath;
342 
343  ( void )QMetaObject::invokeMethod(
344  widget, "borderPath", Qt::DirectConnection,
345  Q_RETURN_ARG( QPainterPath, clipPath ), Q_ARG( QRect, rect() ) );
346 
347  if (!clipPath.isEmpty() )
348  painter->setClipPath( clipPath, Qt::IntersectClip );
349  }
350  }
351 
352  drawOverlay( painter );
353 }
354 
374 {
375  return QRegion();
376 }
377 
389 bool QwtWidgetOverlay::eventFilter( QObject* object, QEvent* event )
390 {
391  if ( object == parent() && event->type() == QEvent::Resize )
392  {
393  QResizeEvent* resizeEvent = static_cast< QResizeEvent* >( event );
394  resize( resizeEvent->size() );
395  }
396 
397  return QObject::eventFilter( object, event );
398 }
399 
400 #if QWT_MOC_INCLUDE
401 #include "moc_qwt_widget_overlay.cpp"
402 #endif
QwtWidgetOverlay::drawOverlay
virtual void drawOverlay(QPainter *painter) const =0
QwtWidgetOverlay
An overlay for a widget.
Definition: qwt_widget_overlay.h:40
QwtWidgetOverlay::m_data
PrivateData * m_data
Definition: qwt_widget_overlay.h:147
QwtWidgetOverlay::draw
void draw(QPainter *) const
Definition: qwt_widget_overlay.cpp:330
QwtWidgetOverlay::PrivateData::~PrivateData
~PrivateData()
Definition: qwt_widget_overlay.cpp:103
QwtWidgetOverlay::PrivateData::rgbaBuffer
uchar * rgbaBuffer
Definition: qwt_widget_overlay.cpp:119
QwtWidgetOverlay::paintEvent
virtual void paintEvent(QPaintEvent *) QWT_OVERRIDE
Definition: qwt_widget_overlay.cpp:261
QVector
Definition: qwt_clipper.h:23
QwtWidgetOverlay::PrivateData::maskMode
MaskMode maskMode
Definition: qwt_widget_overlay.cpp:117
mqtt_test_proto.x
x
Definition: mqtt_test_proto.py:34
QwtWidgetOverlay::PrivateData::resetRgbaBuffer
void resetRgbaBuffer()
Definition: qwt_widget_overlay.cpp:108
QwtWidgetOverlay::AutoRenderMode
@ AutoRenderMode
Copy the buffer, when using the raster paint engine.
Definition: qwt_widget_overlay.h:107
QwtWidgetOverlay::MaskHint
@ MaskHint
Use maskHint() as mask.
Definition: qwt_widget_overlay.h:74
mqtt_test_proto.y
y
Definition: mqtt_test_proto.py:35
QwtWidgetOverlay::PrivateData
Definition: qwt_widget_overlay.cpp:93
qwt_widget_overlay.h
QwtWidgetOverlay::DrawOverlay
@ DrawOverlay
Never copy the buffer.
Definition: qwt_widget_overlay.h:113
QwtWidgetOverlay::setRenderMode
void setRenderMode(RenderMode)
Definition: qwt_widget_overlay.cpp:178
QwtWidgetOverlay::CopyAlphaMask
@ CopyAlphaMask
Always copy the buffer.
Definition: qwt_widget_overlay.h:110
QwtWidgetOverlay::updateMask
void updateMask()
Definition: qwt_widget_overlay.cpp:201
update
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
QwtWidgetOverlay::resizeEvent
virtual void resizeEvent(QResizeEvent *) QWT_OVERRIDE
Definition: qwt_widget_overlay.cpp:323
QwtWidgetOverlay::~QwtWidgetOverlay
virtual ~QwtWidgetOverlay()
Destructor.
Definition: qwt_widget_overlay.cpp:143
QwtWidgetOverlay::RenderMode
RenderMode
Render mode.
Definition: qwt_widget_overlay.h:104
nlohmann::detail::void
j template void())
Definition: json.hpp:4061
QwtWidgetOverlay::eventFilter
virtual bool eventFilter(QObject *, QEvent *) QWT_OVERRIDE
Event filter.
Definition: qwt_widget_overlay.cpp:389
QwtPainter::isX11GraphicsSystem
static bool isX11GraphicsSystem()
Definition: qwt_painter.cpp:233
QwtWidgetOverlay::MaskMode
MaskMode
Mask mode.
Definition: qwt_widget_overlay.h:62
qwt_painter.h
QwtWidgetOverlay::PrivateData::renderMode
RenderMode renderMode
Definition: qwt_widget_overlay.cpp:118
QwtWidgetOverlay::updateOverlay
void updateOverlay()
Definition: qwt_widget_overlay.cpp:195
QwtWidgetOverlay::AlphaMask
@ AlphaMask
Calculate a mask by checking the alpha values.
Definition: qwt_widget_overlay.h:86
qwtAlphaMask
static QRegion qwtAlphaMask(const QImage &image, const QRegion &region)
Definition: qwt_widget_overlay.cpp:29
QwtWidgetOverlay::maskMode
MaskMode maskMode() const
Definition: qwt_widget_overlay.cpp:167
uchar
#define uchar(c)
Definition: lstrlib.c:40
QwtWidgetOverlay::QwtWidgetOverlay
QwtWidgetOverlay(QWidget *)
Constructor.
Definition: qwt_widget_overlay.cpp:126
QwtWidgetOverlay::PrivateData::PrivateData
PrivateData()
Definition: qwt_widget_overlay.cpp:96
qwtMaskImageFormat
static QImage::Format qwtMaskImageFormat()
Definition: qwt_widget_overlay.cpp:21
QwtWidgetOverlay::setMaskMode
void setMaskMode(MaskMode)
Specify how to find the mask for the overlay.
Definition: qwt_widget_overlay.cpp:154
QwtWidgetOverlay::maskHint
virtual QRegion maskHint() const
Calculate an approximation for the mask.
Definition: qwt_widget_overlay.cpp:373
QwtWidgetOverlay::renderMode
RenderMode renderMode() const
Definition: qwt_widget_overlay.cpp:187


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Aug 11 2024 02:24:25