qwt_widget_overlay.cpp
Go to the documentation of this file.
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_widget_overlay.h"
11 #include "qwt_painter.h"
12 #include <qpainter.h>
13 #include <qpaintengine.h>
14 #include <qimage.h>
15 #include <qevent.h>
16 
17 static QImage::Format qwtMaskImageFormat()
18 {
20  return QImage::Format_ARGB32;
21 
22  return QImage::Format_ARGB32_Premultiplied;
23 }
24 
25 static QRegion qwtAlphaMask(
26  const QImage& image, const QVector<QRect> &rects )
27 {
28  const int w = image.width();
29  const int h = image.height();
30 
31  QRegion region;
32  QRect rect;
33 
34  for ( int i = 0; i < rects.size(); i++ )
35  {
36  int x1, x2, y1, y2;
37  rects[i].getCoords( &x1, &y1, &x2, &y2 );
38 
39  x1 = qMax( x1, 0 );
40  x2 = qMin( x2, w - 1 );
41  y1 = qMax( y1, 0 );
42  y2 = qMin( y2, h - 1 );
43 
44  for ( int y = y1; y <= y2; ++y )
45  {
46  bool inRect = false;
47  int rx0 = -1;
48 
49  const uint *line =
50  reinterpret_cast<const uint *> ( image.scanLine( y ) ) + x1;
51  for ( int x = x1; x <= x2; x++ )
52  {
53  const bool on = ( ( *line++ >> 24 ) != 0 );
54  if ( on != inRect )
55  {
56  if ( inRect )
57  {
58  rect.setCoords( rx0, y, x - 1, y );
59  region += rect;
60  }
61  else
62  {
63  rx0 = x;
64  }
65 
66  inRect = on;
67  }
68  }
69 
70  if ( inRect )
71  {
72  rect.setCoords( rx0, y, x2, y );
73  region = region.united( rect );
74  }
75  }
76  }
77 
78  return region;
79 }
80 
82 {
83 public:
87  rgbaBuffer( NULL )
88  {
89  }
90 
92  {
94  }
95 
97  {
98  if ( rgbaBuffer )
99  {
100  ::free( rgbaBuffer );
101  rgbaBuffer = NULL;
102  }
103  }
104 
107  uchar *rgbaBuffer;
108 };
109 
115  QWidget( widget )
116 {
117  d_data = new PrivateData;
118 
119  setAttribute( Qt::WA_TransparentForMouseEvents );
120  setAttribute( Qt::WA_NoSystemBackground );
121  setFocusPolicy( Qt::NoFocus );
122 
123  if ( widget )
124  {
125  resize( widget->size() );
126  widget->installEventFilter( this );
127  }
128 }
129 
132 {
133  delete d_data;
134 }
135 
143 {
144  if ( mode != d_data->maskMode )
145  {
146  d_data->maskMode = mode;
148  }
149 }
150 
156 {
157  return d_data->maskMode;
158 }
159 
167 {
168  d_data->renderMode = mode;
169 }
170 
176 {
177  return d_data->renderMode;
178 }
179 
184 {
185  updateMask();
186  update();
187 }
188 
190 {
192 
193  QRegion mask;
194 
196  {
197  mask = maskHint();
198  }
200  {
201  // TODO: the image doesn't need to be larger than
202  // the bounding rectangle of the hint !!
203 
204  QRegion hint = maskHint();
205  if ( hint.isEmpty() )
206  hint += QRect( 0, 0, width(), height() );
207 
208  // A fresh buffer from calloc() is usually faster
209  // than reinitializing an existing one with
210  // QImage::fill( 0 ) or memset()
211 
212  d_data->rgbaBuffer = ( uchar* )::calloc( width() * height(), 4 );
213 
214  QImage image( d_data->rgbaBuffer,
215  width(), height(), qwtMaskImageFormat() );
216 
217  QPainter painter( &image );
218  draw( &painter );
219  painter.end();
220 
221  mask = qwtAlphaMask( image, hint.rects() );
222 
224  {
225  // we don't need the buffer later
227  }
228  }
229 
230  // A bug in Qt initiates a full repaint of the widget
231  // when we change the mask, while we are visible !
232 
233  setVisible( false );
234 
235  if ( mask.isEmpty() )
236  clearMask();
237  else
238  setMask( mask );
239 
240  setVisible( true );
241 }
242 
249 void QwtWidgetOverlay::paintEvent( QPaintEvent* event )
250 {
251  const QRegion clipRegion = event->region();
252 
253  QPainter painter( this );
254 
255  bool useRgbaBuffer = false;
257  {
258  useRgbaBuffer = true;
259  }
261  {
262  if ( painter.paintEngine()->type() == QPaintEngine::Raster )
263  useRgbaBuffer = true;
264  }
265 
266  if ( d_data->rgbaBuffer && useRgbaBuffer )
267  {
268  const QImage image( d_data->rgbaBuffer,
269  width(), height(), qwtMaskImageFormat() );
270 
271  QVector<QRect> rects;
272  if ( clipRegion.rects().size() > 2000 )
273  {
274  // the region is to complex
275  painter.setClipRegion( clipRegion );
276  rects += clipRegion.boundingRect();
277  }
278  else
279  {
280  rects = clipRegion.rects();
281  }
282 
283  for ( int i = 0; i < rects.size(); i++ )
284  {
285  const QRect r = rects[i];
286  painter.drawImage( r.topLeft(), image, r );
287  }
288  }
289  else
290  {
291  painter.setClipRegion( clipRegion );
292  draw( &painter );
293  }
294 }
295 
300 void QwtWidgetOverlay::resizeEvent( QResizeEvent* event )
301 {
302  Q_UNUSED( event );
303 
305 }
306 
307 void QwtWidgetOverlay::draw( QPainter *painter ) const
308 {
309  QWidget *widget = const_cast< QWidget *>( parentWidget() );
310  if ( widget )
311  {
312  painter->setClipRect( parentWidget()->contentsRect() );
313 
314  // something special for the plot canvas
315 
316  const int idx = widget->metaObject()->indexOfMethod( "borderPath(QRect)" );
317  if ( idx >= 0 )
318  {
319  QPainterPath clipPath;
320 
321  ( void )QMetaObject::invokeMethod(
322  widget, "borderPath", Qt::DirectConnection,
323  Q_RETURN_ARG( QPainterPath, clipPath ), Q_ARG( QRect, rect() ) );
324 
325  if (!clipPath.isEmpty())
326  painter->setClipPath( clipPath, Qt::IntersectClip );
327  }
328  }
329 
330  drawOverlay( painter );
331 }
332 
352 {
353  return QRegion();
354 }
355 
367 bool QwtWidgetOverlay::eventFilter( QObject* object, QEvent* event )
368 {
369  if ( object == parent() && event->type() == QEvent::Resize )
370  {
371  QResizeEvent *resizeEvent = static_cast<QResizeEvent *>( event );
372  resize( resizeEvent->size() );
373  }
374 
375  return QObject::eventFilter( object, event );
376 }
void setRenderMode(RenderMode)
virtual void resizeEvent(QResizeEvent *event)
virtual ~QwtWidgetOverlay()
Destructor.
MaskMode maskMode() const
static bool isX11GraphicsSystem()
QwtWidgetOverlay(QWidget *)
Constructor.
RenderMode
Render mode.
void setMaskMode(MaskMode)
Specify how to find the mask for the overlay.
static QImage::Format qwtMaskImageFormat()
virtual void drawOverlay(QPainter *painter) const =0
TFSIMD_FORCE_INLINE const tfScalar & y() const
Copy the buffer, when using the raster paint engine.
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
RenderMode renderMode() const
virtual QRegion maskHint() const
Calculate an approximation for the mask.
TFSIMD_FORCE_INLINE const tfScalar & x() const
static QRegion qwtAlphaMask(const QImage &image, const QVector< QRect > &rects)
Use maskHint() as mask.
PrivateData * d_data
TFSIMD_FORCE_INLINE const tfScalar & w() const
Calculate a mask by checking the alpha values.
An overlay for a widget.
void draw(QPainter *) const
virtual bool eventFilter(QObject *, QEvent *)
Event filter.
int i
virtual void paintEvent(QPaintEvent *event)


plotjuggler
Author(s): Davide Faconti
autogenerated on Sat Jul 6 2019 03:44:18