qwt_painter.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_painter.h"
11 #include "qwt_math.h"
12 #include "qwt_clipper.h"
13 #include "qwt_color_map.h"
14 #include "qwt_scale_map.h"
15 
16 #include <qwidget.h>
17 #include <qframe.h>
18 #include <qrect.h>
19 #include <qpainter.h>
20 #include <qpalette.h>
21 #include <qpaintdevice.h>
22 #include <qpainterpath.h>
23 #include <qpixmap.h>
24 #include <qstyle.h>
25 #include <qtextdocument.h>
26 #include <qabstracttextdocumentlayout.h>
27 #include <qstyleoption.h>
28 #include <qpaintengine.h>
29 #include <qapplication.h>
30 #include <qdesktopwidget.h>
31 
32 #if QT_VERSION < 0x050000
33 
34 #ifdef Q_WS_X11
35 #include <qx11info_x11.h>
36 #endif
37 
38 #endif
39 
40 #include <cstring>
41 
44 
45 static inline bool qwtIsRasterPaintEngineBuggy()
46 {
47 #if 0
48  static int isBuggy = -1;
49  if ( isBuggy < 0 )
50  {
51  // auto detect bug of the raster paint engine,
52  // fixed with: https://codereview.qt-project.org/#/c/99456/
53 
54  QImage image( 2, 3, QImage::Format_ARGB32 );
55  image.fill( 0u );
56 
57  QPolygonF p;
58  p += QPointF(0, 1);
59  p += QPointF(0, 0);
60  p += QPointF(1, 0 );
61  p += QPointF(1, 2 );
62 
63  QPainter painter( &image );
64  painter.drawPolyline( p );
65  painter.end();
66 
67  isBuggy = ( image.pixel( 1, 1 ) == 0 ) ? 1 : 0;
68  }
69 
70  return isBuggy == 1;
71 #endif
72 
73 #if QT_VERSION < 0x050000
74  return true;
75 #elif QT_VERSION < 0x050100
76  return false;
77 #elif QT_VERSION < 0x050400
78  return true;
79 #else
80  return false;
81 #endif
82 }
83 
84 static inline bool qwtIsClippingNeeded(
85  const QPainter *painter, QRectF &clipRect )
86 {
87  bool doClipping = false;
88  const QPaintEngine *pe = painter->paintEngine();
89  if ( pe && pe->type() == QPaintEngine::SVG )
90  {
91  // The SVG paint engine ignores any clipping,
92 
93  if ( painter->hasClipping() )
94  {
95  doClipping = true;
96  clipRect = painter->clipRegion().boundingRect();
97  }
98  }
99 
100  return doClipping;
101 }
102 
103 template <class T>
104 static inline void qwtDrawPolyline( QPainter *painter,
105  const T *points, int pointCount, bool polylineSplitting )
106 {
107  bool doSplit = false;
108  if ( polylineSplitting && pointCount > 3 )
109  {
110  const QPaintEngine *pe = painter->paintEngine();
111  if ( pe && pe->type() == QPaintEngine::Raster )
112  {
113  if ( painter->pen().width() <= 1 )
114  {
115  // work around a bug with short lines below 2 pixels difference
116  // in height and width
117 
118  doSplit = qwtIsRasterPaintEngineBuggy();
119  }
120  else
121  {
122  /*
123  Raster paint engine is much faster when splitting
124  the polygon, but of course we might see some issues where
125  the pieces are joining
126  */
127  doSplit = true;
128  }
129  }
130  }
131 
132  if ( doSplit )
133  {
134  QPen pen = painter->pen();
135 
136  const int splitSize = 6;
137 
138  if ( pen.width() <= 1 && pen.isSolid() && qwtIsRasterPaintEngineBuggy()
139  && !( painter->renderHints() & QPainter::Antialiasing ) )
140  {
141  int k = 0;
142 
143  for ( int i = k + 1; i < pointCount; i++ )
144  {
145  const QPointF &p1 = points[i-1];
146  const QPointF &p2 = points[i];
147 
148  const bool isBad = ( qAbs( p2.y() - p1.y() ) <= 1 )
149  && qAbs( p2.x() - p1.x() ) <= 1;
150 
151  if ( isBad || ( i - k >= splitSize ) )
152  {
153  painter->drawPolyline( points + k, i - k + 1 );
154  k = i;
155  }
156  }
157 
158  painter->drawPolyline( points + k, pointCount - k );
159  }
160  else
161  {
162  for ( int i = 0; i < pointCount; i += splitSize )
163  {
164  const int n = qMin( splitSize + 1, pointCount - i );
165  painter->drawPolyline( points + i, n );
166  }
167  }
168  }
169  else
170  {
171  painter->drawPolyline( points, pointCount );
172  }
173 }
174 
175 static inline QSize qwtScreenResolution()
176 {
177  static QSize screenResolution;
178  if ( !screenResolution.isValid() )
179  {
180  QDesktopWidget *desktop = QApplication::desktop();
181  if ( desktop )
182  {
183  screenResolution.setWidth( desktop->logicalDpiX() );
184  screenResolution.setHeight( desktop->logicalDpiY() );
185  }
186  }
187 
188  return screenResolution;
189 }
190 
191 static inline void qwtUnscaleFont( QPainter *painter )
192 {
193  if ( painter->font().pixelSize() >= 0 )
194  return;
195 
196  const QSize screenResolution = qwtScreenResolution();
197 
198  const QPaintDevice *pd = painter->device();
199  if ( pd->logicalDpiX() != screenResolution.width() ||
200  pd->logicalDpiY() != screenResolution.height() )
201  {
202  QFont pixelFont( painter->font(), QApplication::desktop() );
203  pixelFont.setPixelSize( QFontInfo( pixelFont ).pixelSize() );
204 
205  painter->setFont( pixelFont );
206  }
207 }
208 
217 {
218  /*
219  The X11 paint engine has been removed with Qt 5.0, but
220  reintroduced with Qt 5.10. It can be enabled with
221  "export QT_XCB_NATIVE_PAINTING=1".
222  */
223 
224  static int onX11 = -1;
225  if ( onX11 < 0 )
226  {
227  QPixmap pm( 1, 1 );
228  QPainter painter( &pm );
229 
230  onX11 = ( painter.paintEngine()->type() == QPaintEngine::X11 ) ? 1 : 0;
231  }
232 
233  return onX11 == 1;
234 }
235 
250 bool QwtPainter::isAligning( const QPainter *painter )
251 {
252  if ( painter && painter->isActive() )
253  {
254  const QPaintEngine::Type type =
255  painter->paintEngine()->type();
256 
257  if ( type >= QPaintEngine::User )
258  {
259  // we have no idea - better don't align
260  return false;
261  }
262 
263  switch ( type )
264  {
265  case QPaintEngine::Pdf:
266  case QPaintEngine::SVG:
267 #if 0
268  case QPaintEngine::MacPrinter:
269 #endif
270  return false;
271 
272  default:
273  break;
274  }
275 
276  const QTransform &tr = painter->transform();
277  if ( tr.isRotating() || tr.isScaling() )
278  {
279  // we might have to check translations too
280  return false;
281  }
282  }
283 
284  return true;
285 }
286 
299 {
301 }
302 
319 {
321 }
322 
324 void QwtPainter::drawPath( QPainter *painter, const QPainterPath &path )
325 {
326  painter->drawPath( path );
327 }
328 
330 void QwtPainter::drawRect( QPainter *painter, qreal x, qreal y, qreal w, qreal h )
331 {
332  drawRect( painter, QRectF( x, y, w, h ) );
333 }
334 
336 void QwtPainter::drawRect( QPainter *painter, const QRectF &rect )
337 {
338  const QRectF r = rect;
339 
340  QRectF clipRect;
341  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
342 
343  if ( deviceClipping )
344  {
345  if ( !clipRect.intersects( r ) )
346  return;
347 
348  if ( !clipRect.contains( r ) )
349  {
350  fillRect( painter, r & clipRect, painter->brush() );
351 
352  painter->save();
353  painter->setBrush( Qt::NoBrush );
354  drawPolyline( painter, QPolygonF( r ) );
355  painter->restore();
356 
357  return;
358  }
359  }
360 
361  painter->drawRect( r );
362 }
363 
365 void QwtPainter::fillRect( QPainter *painter,
366  const QRectF &rect, const QBrush &brush )
367 {
368  if ( !rect.isValid() )
369  return;
370 
371  QRectF clipRect;
372  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
373 
374  /*
375  Performance of Qt4 is horrible for a non trivial brush. Without
376  clipping expect minutes or hours for repainting large rectangles
377  (might result from zooming)
378  */
379 
380  if ( deviceClipping )
381  clipRect &= painter->window();
382  else
383  clipRect = painter->window();
384 
385  if ( painter->hasClipping() )
386  clipRect &= painter->clipRegion().boundingRect();
387 
388  QRectF r = rect;
389  if ( deviceClipping )
390  r = r.intersected( clipRect );
391 
392  if ( r.isValid() )
393  painter->fillRect( r, brush );
394 }
395 
397 void QwtPainter::drawPie( QPainter *painter, const QRectF &rect,
398  int a, int alen )
399 {
400  QRectF clipRect;
401  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
402  if ( deviceClipping && !clipRect.contains( rect ) )
403  return;
404 
405  painter->drawPie( rect, a, alen );
406 }
407 
409 void QwtPainter::drawEllipse( QPainter *painter, const QRectF &rect )
410 {
411  QRectF clipRect;
412  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
413 
414  if ( deviceClipping && !clipRect.contains( rect ) )
415  return;
416 
417  painter->drawEllipse( rect );
418 }
419 
421 void QwtPainter::drawText( QPainter *painter,
422  qreal x, qreal y, const QString &text )
423 {
424  drawText( painter, QPointF( x, y ), text );
425 }
426 
428 void QwtPainter::drawText( QPainter *painter, const QPointF &pos,
429  const QString &text )
430 {
431  QRectF clipRect;
432  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
433 
434  if ( deviceClipping && !clipRect.contains( pos ) )
435  return;
436 
437 
438  painter->save();
439  qwtUnscaleFont( painter );
440  painter->drawText( pos, text );
441  painter->restore();
442 }
443 
445 void QwtPainter::drawText( QPainter *painter,
446  qreal x, qreal y, qreal w, qreal h,
447  int flags, const QString &text )
448 {
449  drawText( painter, QRectF( x, y, w, h ), flags, text );
450 }
451 
453 void QwtPainter::drawText( QPainter *painter, const QRectF &rect,
454  int flags, const QString &text )
455 {
456  painter->save();
457  qwtUnscaleFont( painter );
458  painter->drawText( rect, flags, text );
459  painter->restore();
460 }
461 
462 #ifndef QT_NO_RICHTEXT
463 
472 void QwtPainter::drawSimpleRichText( QPainter *painter, const QRectF &rect,
473  int flags, const QTextDocument &text )
474 {
475  QTextDocument *txt = text.clone();
476 
477  painter->save();
478 
479  QRectF unscaledRect = rect;
480 
481  if ( painter->font().pixelSize() < 0 )
482  {
483  const QSize res = qwtScreenResolution();
484 
485  const QPaintDevice *pd = painter->device();
486  if ( pd->logicalDpiX() != res.width() ||
487  pd->logicalDpiY() != res.height() )
488  {
489  QTransform transform;
490  transform.scale( res.width() / qreal( pd->logicalDpiX() ),
491  res.height() / qreal( pd->logicalDpiY() ));
492 
493  painter->setWorldTransform( transform, true );
494  unscaledRect = transform.inverted().mapRect(rect);
495  }
496  }
497 
498  txt->setDefaultFont( painter->font() );
499  txt->setPageSize( QSizeF( unscaledRect.width(), QWIDGETSIZE_MAX ) );
500 
501  QAbstractTextDocumentLayout* layout = txt->documentLayout();
502 
503  const qreal height = layout->documentSize().height();
504  qreal y = unscaledRect.y();
505  if ( flags & Qt::AlignBottom )
506  y += ( unscaledRect.height() - height );
507  else if ( flags & Qt::AlignVCenter )
508  y += ( unscaledRect.height() - height ) / 2;
509 
510  QAbstractTextDocumentLayout::PaintContext context;
511  context.palette.setColor( QPalette::Text, painter->pen().color() );
512 
513  painter->translate( unscaledRect.x(), y );
514  layout->draw( painter, context );
515 
516  painter->restore();
517  delete txt;
518 }
519 
520 #endif // !QT_NO_RICHTEXT
521 
522 
524 void QwtPainter::drawLine( QPainter *painter,
525  const QPointF &p1, const QPointF &p2 )
526 {
527  QRectF clipRect;
528  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
529 
530  if ( deviceClipping &&
531  !( clipRect.contains( p1 ) && clipRect.contains( p2 ) ) )
532  {
533  QPolygonF polygon;
534  polygon += p1;
535  polygon += p2;
536  drawPolyline( painter, polygon );
537  return;
538  }
539 
540  painter->drawLine( p1, p2 );
541 }
542 
544 void QwtPainter::drawPolygon( QPainter *painter, const QPolygonF &polygon )
545 {
546  QRectF clipRect;
547  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
548 
549  if ( deviceClipping )
550  {
551  painter->drawPolygon(
552  QwtClipper::clippedPolygonF( clipRect, polygon, true ) );
553  }
554  else
555  {
556  painter->drawPolygon( polygon );
557  }
558 }
559 
561 void QwtPainter::drawPolyline( QPainter *painter, const QPolygonF &polygon )
562 {
563  QRectF clipRect;
564  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
565 
566  if ( deviceClipping )
567  {
568  const QPolygonF cpa = QwtClipper::clippedPolygonF( clipRect, polygon );
569 
570  qwtDrawPolyline<QPointF>( painter,
571  cpa.constData(), cpa.size(), d_polylineSplitting );
572  }
573  else
574  {
575  qwtDrawPolyline<QPointF>( painter,
576  polygon.constData(), polygon.size(), d_polylineSplitting );
577  }
578 }
579 
581 void QwtPainter::drawPolyline( QPainter *painter,
582  const QPointF *points, int pointCount )
583 {
584  QRectF clipRect;
585  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
586 
587  if ( deviceClipping )
588  {
589  QPolygonF polygon( pointCount );
590  std::memcpy( polygon.data(), points, pointCount * sizeof( QPointF ) );
591 
592  QwtClipper::clipPolygonF( clipRect, polygon );
593  qwtDrawPolyline<QPointF>( painter,
594  polygon.constData(), polygon.size(), d_polylineSplitting );
595  }
596  else
597  {
598  qwtDrawPolyline<QPointF>( painter, points, pointCount, d_polylineSplitting );
599  }
600 }
601 
603 void QwtPainter::drawPolygon( QPainter *painter, const QPolygon &polygon )
604 {
605  QRectF clipRect;
606  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
607 
608  if ( deviceClipping )
609  {
610  painter->drawPolygon(
611  QwtClipper::clippedPolygon( clipRect, polygon, true ) );
612  }
613  else
614  {
615  painter->drawPolygon( polygon );
616  }
617 }
618 
620 void QwtPainter::drawPolyline( QPainter *painter, const QPolygon &polygon )
621 {
622  QRectF clipRect;
623  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
624 
625  if ( deviceClipping )
626  {
627  const QPolygon cpa = QwtClipper::clippedPolygon( clipRect, polygon );
628 
629  qwtDrawPolyline<QPoint>( painter,
630  cpa.constData(), cpa.size(), d_polylineSplitting );
631  }
632  else
633  {
634  qwtDrawPolyline<QPoint>( painter,
635  polygon.constData(), polygon.size(), d_polylineSplitting );
636  }
637 }
638 
640 void QwtPainter::drawPolyline( QPainter *painter,
641  const QPoint *points, int pointCount )
642 {
643  QRectF clipRect;
644  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
645 
646  if ( deviceClipping )
647  {
648  QPolygon polygon( pointCount );
649  std::memcpy( polygon.data(), points, pointCount * sizeof( QPoint ) );
650 
651  QwtClipper::clipPolygon( clipRect, polygon );
652  qwtDrawPolyline<QPoint>( painter,
653  polygon.constData(), polygon.size(), d_polylineSplitting );
654  }
655  else
656  {
657  qwtDrawPolyline<QPoint>( painter, points, pointCount, d_polylineSplitting );
658  }
659 }
660 
662 void QwtPainter::drawPoint( QPainter *painter, const QPointF &pos )
663 {
664  QRectF clipRect;
665  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
666 
667  if ( deviceClipping && !clipRect.contains( pos ) )
668  return;
669 
670  painter->drawPoint( pos );
671 }
672 
674 void QwtPainter::drawPoint( QPainter *painter, const QPoint &pos )
675 {
676  QRectF clipRect;
677  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
678 
679  if ( deviceClipping )
680  {
681  const int minX = qwtCeil( clipRect.left() );
682  const int maxX = qwtFloor( clipRect.right() );
683  const int minY = qwtCeil( clipRect.top() );
684  const int maxY = qwtFloor( clipRect.bottom() );
685 
686  if ( pos.x() < minX || pos.x() > maxX
687  || pos.y() < minY || pos.y() > maxY )
688  {
689  return;
690  }
691  }
692 
693  painter->drawPoint( pos );
694 }
695 
697 void QwtPainter::drawPoints( QPainter *painter,
698  const QPoint *points, int pointCount )
699 {
700  QRectF clipRect;
701  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
702 
703  if ( deviceClipping )
704  {
705  const int minX = qwtCeil( clipRect.left() );
706  const int maxX = qwtFloor( clipRect.right() );
707  const int minY = qwtCeil( clipRect.top() );
708  const int maxY = qwtFloor( clipRect.bottom() );
709 
710  const QRect r( minX, minY, maxX - minX, maxY - minY );
711 
712  QPolygon clippedPolygon( pointCount );
713  QPoint *clippedData = clippedPolygon.data();
714 
715  int numClippedPoints = 0;
716  for ( int i = 0; i < pointCount; i++ )
717  {
718  if ( r.contains( points[i] ) )
719  clippedData[ numClippedPoints++ ] = points[i];
720  }
721  painter->drawPoints( clippedData, numClippedPoints );
722  }
723  else
724  {
725  painter->drawPoints( points, pointCount );
726  }
727 }
728 
730 void QwtPainter::drawPoints( QPainter *painter,
731  const QPointF *points, int pointCount )
732 {
733  QRectF clipRect;
734  const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
735 
736  if ( deviceClipping )
737  {
738  QPolygonF clippedPolygon( pointCount );
739  QPointF *clippedData = clippedPolygon.data();
740 
741  int numClippedPoints = 0;
742  for ( int i = 0; i < pointCount; i++ )
743  {
744  if ( clipRect.contains( points[i] ) )
745  clippedData[ numClippedPoints++ ] = points[i];
746  }
747  painter->drawPoints( clippedData, numClippedPoints );
748  }
749  else
750  {
751  painter->drawPoints( points, pointCount );
752  }
753 }
754 
756 void QwtPainter::drawImage( QPainter *painter,
757  const QRectF &rect, const QImage &image )
758 {
759  const QRect alignedRect = rect.toAlignedRect();
760 
761  if ( alignedRect != rect )
762  {
763  const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
764 
765  painter->save();
766  painter->setClipRect( clipRect, Qt::IntersectClip );
767  painter->drawImage( alignedRect, image );
768  painter->restore();
769  }
770  else
771  {
772  painter->drawImage( alignedRect, image );
773  }
774 }
775 
777 void QwtPainter::drawPixmap( QPainter *painter,
778  const QRectF &rect, const QPixmap &pixmap )
779 {
780  const QRect alignedRect = rect.toAlignedRect();
781 
782  if ( alignedRect != rect )
783  {
784  const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
785 
786  painter->save();
787  painter->setClipRect( clipRect, Qt::IntersectClip );
788  painter->drawPixmap( alignedRect, pixmap );
789  painter->restore();
790  }
791  else
792  {
793  painter->drawPixmap( alignedRect, pixmap );
794  }
795 }
796 
798 void QwtPainter::drawFocusRect( QPainter *painter, const QWidget *widget )
799 {
800  drawFocusRect( painter, widget, widget->rect() );
801 }
802 
804 void QwtPainter::drawFocusRect( QPainter *painter, const QWidget *widget,
805  const QRect &rect )
806 {
807  QStyleOptionFocusRect opt;
808  opt.initFrom( widget );
809  opt.rect = rect;
810  opt.state |= QStyle::State_HasFocus;
811  opt.backgroundColor = widget->palette().color( widget->backgroundRole() );
812 
813  widget->style()->drawPrimitive(
814  QStyle::PE_FrameFocusRect, &opt, painter, widget );
815 }
816 
828 void QwtPainter::drawRoundFrame( QPainter *painter,
829  const QRectF &rect, const QPalette &palette,
830  int lineWidth, int frameStyle )
831 {
832  enum Style
833  {
834  Plain,
835  Sunken,
836  Raised
837  };
838 
839  Style style = Plain;
840  if ( (frameStyle & QFrame::Sunken) == QFrame::Sunken )
841  style = Sunken;
842  else if ( (frameStyle & QFrame::Raised) == QFrame::Raised )
843  style = Raised;
844 
845  const qreal lw2 = 0.5 * lineWidth;
846  QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 );
847 
848  QBrush brush;
849 
850  if ( style != Plain )
851  {
852  QColor c1 = palette.color( QPalette::Light );
853  QColor c2 = palette.color( QPalette::Dark );
854 
855  if ( style == Sunken )
856  qSwap( c1, c2 );
857 
858  QLinearGradient gradient( r.topLeft(), r.bottomRight() );
859  gradient.setColorAt( 0.0, c1 );
860 #if 0
861  gradient.setColorAt( 0.3, c1 );
862  gradient.setColorAt( 0.7, c2 );
863 #endif
864  gradient.setColorAt( 1.0, c2 );
865 
866  brush = QBrush( gradient );
867  }
868  else // Plain
869  {
870  brush = palette.brush( QPalette::WindowText );
871  }
872 
873  painter->save();
874 
875  painter->setPen( QPen( brush, lineWidth ) );
876  painter->setBrush( Qt::NoBrush );
877 
878  painter->drawEllipse( r );
879 
880  painter->restore();
881 }
882 
894 void QwtPainter::drawFrame( QPainter *painter, const QRectF &rect,
895  const QPalette &palette, QPalette::ColorRole foregroundRole,
896  int frameWidth, int midLineWidth, int frameStyle )
897 {
898  if ( frameWidth <= 0 || rect.isEmpty() )
899  return;
900 
901  const int shadow = frameStyle & QFrame::Shadow_Mask;
902 
903  painter->save();
904 
905  if ( shadow == QFrame::Plain )
906  {
907  const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
908  const QRectF innerRect = outerRect.adjusted(
909  frameWidth, frameWidth, -frameWidth, -frameWidth );
910 
911  QPainterPath path;
912  path.addRect( outerRect );
913  path.addRect( innerRect );
914 
915  painter->setPen( Qt::NoPen );
916  painter->setBrush( palette.color( foregroundRole ) );
917 
918  painter->drawPath( path );
919  }
920  else
921  {
922  const int shape = frameStyle & QFrame::Shape_Mask;
923 
924  if ( shape == QFrame::Box )
925  {
926  const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
927  const QRectF midRect1 = outerRect.adjusted(
928  frameWidth, frameWidth, -frameWidth, -frameWidth );
929  const QRectF midRect2 = midRect1.adjusted(
930  midLineWidth, midLineWidth, -midLineWidth, -midLineWidth );
931 
932  const QRectF innerRect = midRect2.adjusted(
933  frameWidth, frameWidth, -frameWidth, -frameWidth );
934 
935  QPainterPath path1;
936  path1.moveTo( outerRect.bottomLeft() );
937  path1.lineTo( outerRect.topLeft() );
938  path1.lineTo( outerRect.topRight() );
939  path1.lineTo( midRect1.topRight() );
940  path1.lineTo( midRect1.topLeft() );
941  path1.lineTo( midRect1.bottomLeft() );
942 
943  QPainterPath path2;
944  path2.moveTo( outerRect.bottomLeft() );
945  path2.lineTo( outerRect.bottomRight() );
946  path2.lineTo( outerRect.topRight() );
947  path2.lineTo( midRect1.topRight() );
948  path2.lineTo( midRect1.bottomRight() );
949  path2.lineTo( midRect1.bottomLeft() );
950 
951  QPainterPath path3;
952  path3.moveTo( midRect2.bottomLeft() );
953  path3.lineTo( midRect2.topLeft() );
954  path3.lineTo( midRect2.topRight() );
955  path3.lineTo( innerRect.topRight() );
956  path3.lineTo( innerRect.topLeft() );
957  path3.lineTo( innerRect.bottomLeft() );
958 
959  QPainterPath path4;
960  path4.moveTo( midRect2.bottomLeft() );
961  path4.lineTo( midRect2.bottomRight() );
962  path4.lineTo( midRect2.topRight() );
963  path4.lineTo( innerRect.topRight() );
964  path4.lineTo( innerRect.bottomRight() );
965  path4.lineTo( innerRect.bottomLeft() );
966 
967  QPainterPath path5;
968  path5.addRect( midRect1 );
969  path5.addRect( midRect2 );
970 
971  painter->setPen( Qt::NoPen );
972 
973  QBrush brush1 = palette.dark().color();
974  QBrush brush2 = palette.light().color();
975 
976  if ( shadow == QFrame::Raised )
977  qSwap( brush1, brush2 );
978 
979  painter->setBrush( brush1 );
980  painter->drawPath( path1 );
981  painter->drawPath( path4 );
982 
983  painter->setBrush( brush2 );
984  painter->drawPath( path2 );
985  painter->drawPath( path3 );
986 
987  painter->setBrush( palette.mid() );
988  painter->drawPath( path5 );
989  }
990  else
991  {
992  const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
993  const QRectF innerRect = outerRect.adjusted(
994  frameWidth - 1.0, frameWidth - 1.0,
995  -( frameWidth - 1.0 ), -( frameWidth - 1.0 ) );
996 
997  QPainterPath path1;
998  path1.moveTo( outerRect.bottomLeft() );
999  path1.lineTo( outerRect.topLeft() );
1000  path1.lineTo( outerRect.topRight() );
1001  path1.lineTo( innerRect.topRight() );
1002  path1.lineTo( innerRect.topLeft() );
1003  path1.lineTo( innerRect.bottomLeft() );
1004 
1005 
1006  QPainterPath path2;
1007  path2.moveTo( outerRect.bottomLeft() );
1008  path2.lineTo( outerRect.bottomRight() );
1009  path2.lineTo( outerRect.topRight() );
1010  path2.lineTo( innerRect.topRight() );
1011  path2.lineTo( innerRect.bottomRight() );
1012  path2.lineTo( innerRect.bottomLeft() );
1013 
1014  painter->setPen( Qt::NoPen );
1015 
1016  QBrush brush1 = palette.dark().color();
1017  QBrush brush2 = palette.light().color();
1018 
1019  if ( shadow == QFrame::Raised )
1020  qSwap( brush1, brush2 );
1021 
1022  painter->setBrush( brush1 );
1023  painter->drawPath( path1 );
1024 
1025  painter->setBrush( brush2 );
1026  painter->drawPath( path2 );
1027  }
1028 
1029  }
1030 
1031  painter->restore();
1032 }
1033 
1048 void QwtPainter::drawRoundedFrame( QPainter *painter,
1049  const QRectF &rect, qreal xRadius, qreal yRadius,
1050  const QPalette &palette, int lineWidth, int frameStyle )
1051 {
1052  painter->save();
1053  painter->setRenderHint( QPainter::Antialiasing, true );
1054  painter->setBrush( Qt::NoBrush );
1055 
1056  qreal lw2 = lineWidth * 0.5;
1057  QRectF innerRect = rect.adjusted( lw2, lw2, -lw2, -lw2 );
1058 
1059  QPainterPath path;
1060  path.addRoundedRect( innerRect, xRadius, yRadius );
1061 
1062  enum Style
1063  {
1064  Plain,
1065  Sunken,
1066  Raised
1067  };
1068 
1069  Style style = Plain;
1070  if ( (frameStyle & QFrame::Sunken) == QFrame::Sunken )
1071  style = Sunken;
1072  else if ( (frameStyle & QFrame::Raised) == QFrame::Raised )
1073  style = Raised;
1074 
1075  if ( style != Plain && path.elementCount() == 17 )
1076  {
1077  // move + 4 * ( cubicTo + lineTo )
1078  QPainterPath pathList[8];
1079 
1080  for ( int i = 0; i < 4; i++ )
1081  {
1082  const int j = i * 4 + 1;
1083 
1084  pathList[ 2 * i ].moveTo(
1085  path.elementAt(j - 1).x, path.elementAt( j - 1 ).y
1086  );
1087 
1088  pathList[ 2 * i ].cubicTo(
1089  path.elementAt(j + 0).x, path.elementAt(j + 0).y,
1090  path.elementAt(j + 1).x, path.elementAt(j + 1).y,
1091  path.elementAt(j + 2).x, path.elementAt(j + 2).y );
1092 
1093  pathList[ 2 * i + 1 ].moveTo(
1094  path.elementAt(j + 2).x, path.elementAt(j + 2).y
1095  );
1096  pathList[ 2 * i + 1 ].lineTo(
1097  path.elementAt(j + 3).x, path.elementAt(j + 3).y
1098  );
1099  }
1100 
1101  QColor c1( palette.color( QPalette::Dark ) );
1102  QColor c2( palette.color( QPalette::Light ) );
1103 
1104  if ( style == Raised )
1105  qSwap( c1, c2 );
1106 
1107  for ( int i = 0; i < 4; i++ )
1108  {
1109  const QRectF r = pathList[2 * i].controlPointRect();
1110 
1111  QPen arcPen;
1112  arcPen.setCapStyle( Qt::FlatCap );
1113  arcPen.setWidth( lineWidth );
1114 
1115  QPen linePen;
1116  linePen.setCapStyle( Qt::FlatCap );
1117  linePen.setWidth( lineWidth );
1118 
1119  switch( i )
1120  {
1121  case 0:
1122  {
1123  arcPen.setColor( c1 );
1124  linePen.setColor( c1 );
1125  break;
1126  }
1127  case 1:
1128  {
1129  QLinearGradient gradient;
1130  gradient.setStart( r.topLeft() );
1131  gradient.setFinalStop( r.bottomRight() );
1132  gradient.setColorAt( 0.0, c1 );
1133  gradient.setColorAt( 1.0, c2 );
1134 
1135  arcPen.setBrush( gradient );
1136  linePen.setColor( c2 );
1137  break;
1138  }
1139  case 2:
1140  {
1141  arcPen.setColor( c2 );
1142  linePen.setColor( c2 );
1143  break;
1144  }
1145  case 3:
1146  {
1147  QLinearGradient gradient;
1148 
1149  gradient.setStart( r.bottomRight() );
1150  gradient.setFinalStop( r.topLeft() );
1151  gradient.setColorAt( 0.0, c2 );
1152  gradient.setColorAt( 1.0, c1 );
1153 
1154  arcPen.setBrush( gradient );
1155  linePen.setColor( c1 );
1156  break;
1157  }
1158  }
1159 
1160 
1161  painter->setPen( arcPen );
1162  painter->drawPath( pathList[ 2 * i] );
1163 
1164  painter->setPen( linePen );
1165  painter->drawPath( pathList[ 2 * i + 1] );
1166  }
1167  }
1168  else
1169  {
1170  QPen pen( palette.color( QPalette::WindowText ), lineWidth );
1171  painter->setPen( pen );
1172  painter->drawPath( path );
1173  }
1174 
1175  painter->restore();
1176 }
1177 
1188 void QwtPainter::drawColorBar( QPainter *painter,
1189  const QwtColorMap &colorMap, const QwtInterval &interval,
1190  const QwtScaleMap &scaleMap, Qt::Orientation orientation,
1191  const QRectF &rect )
1192 {
1193  QVector<QRgb> colorTable;
1194  if ( colorMap.format() == QwtColorMap::Indexed )
1195  colorTable = colorMap.colorTable256();
1196 
1197  QColor c;
1198 
1199  const QRect devRect = rect.toAlignedRect();
1200 
1201  /*
1202  We paint to a pixmap first to have something scalable for printing
1203  ( f.e. in a Pdf document )
1204  */
1205 
1206  QPixmap pixmap( devRect.size() );
1207  pixmap.fill( Qt::transparent );
1208 
1209  QPainter pmPainter( &pixmap );
1210  pmPainter.translate( -devRect.x(), -devRect.y() );
1211 
1212  if ( orientation == Qt::Horizontal )
1213  {
1214  QwtScaleMap sMap = scaleMap;
1215  sMap.setPaintInterval( rect.left(), rect.right() );
1216 
1217  for ( int x = devRect.left(); x <= devRect.right(); x++ )
1218  {
1219  const double value = sMap.invTransform( x );
1220 
1221  if ( colorMap.format() == QwtColorMap::RGB )
1222  c.setRgba( colorMap.rgb( interval, value ) );
1223  else
1224  c = colorTable[colorMap.colorIndex( 256, interval, value )];
1225 
1226  pmPainter.setPen( c );
1227  pmPainter.drawLine( x, devRect.top(), x, devRect.bottom() );
1228  }
1229  }
1230  else // Vertical
1231  {
1232  QwtScaleMap sMap = scaleMap;
1233  sMap.setPaintInterval( rect.bottom(), rect.top() );
1234 
1235  for ( int y = devRect.top(); y <= devRect.bottom(); y++ )
1236  {
1237  const double value = sMap.invTransform( y );
1238 
1239  if ( colorMap.format() == QwtColorMap::RGB )
1240  c.setRgba( colorMap.rgb( interval, value ) );
1241  else
1242  c = colorTable[colorMap.colorIndex( 256, interval, value )];
1243 
1244  pmPainter.setPen( c );
1245  pmPainter.drawLine( devRect.left(), y, devRect.right(), y );
1246  }
1247  }
1248  pmPainter.end();
1249 
1250  drawPixmap( painter, rect, pixmap );
1251 }
1252 
1253 static inline void qwtFillRect( const QWidget *widget, QPainter *painter,
1254  const QRect &rect, const QBrush &brush)
1255 {
1256  if ( brush.style() == Qt::TexturePattern )
1257  {
1258  painter->save();
1259 
1260  painter->setClipRect( rect );
1261  painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
1262 
1263  painter->restore();
1264  }
1265  else if ( brush.gradient() )
1266  {
1267  painter->save();
1268 
1269  painter->setClipRect( rect );
1270  painter->fillRect(0, 0, widget->width(),
1271  widget->height(), brush);
1272 
1273  painter->restore();
1274  }
1275  else
1276  {
1277  painter->fillRect(rect, brush);
1278  }
1279 }
1280 
1294 void QwtPainter::fillPixmap( const QWidget *widget,
1295  QPixmap &pixmap, const QPoint &offset )
1296 {
1297  const QRect rect( offset, pixmap.size() );
1298 
1299  QPainter painter( &pixmap );
1300  painter.translate( -offset );
1301 
1302  const QBrush autoFillBrush =
1303  widget->palette().brush( widget->backgroundRole() );
1304 
1305  if ( !( widget->autoFillBackground() && autoFillBrush.isOpaque() ) )
1306  {
1307  const QBrush bg = widget->palette().brush( QPalette::Window );
1308  qwtFillRect( widget, &painter, rect, bg);
1309  }
1310 
1311  if ( widget->autoFillBackground() )
1312  qwtFillRect( widget, &painter, rect, autoFillBrush);
1313 
1314  if ( widget->testAttribute(Qt::WA_StyledBackground) )
1315  {
1316  painter.setClipRegion( rect );
1317 
1318  QStyleOption opt;
1319  opt.initFrom( widget );
1320  widget->style()->drawPrimitive( QStyle::PE_Widget,
1321  &opt, &painter, widget );
1322  }
1323 }
1324 
1334 void QwtPainter::drawBackgound( QPainter *painter,
1335  const QRectF &rect, const QWidget *widget )
1336 {
1337  if ( widget->testAttribute( Qt::WA_StyledBackground ) )
1338  {
1339  QStyleOption opt;
1340  opt.initFrom( widget );
1341  opt.rect = rect.toAlignedRect();
1342 
1343  widget->style()->drawPrimitive(
1344  QStyle::PE_Widget, &opt, painter, widget);
1345  }
1346  else
1347  {
1348  const QBrush brush =
1349  widget->palette().brush( widget->backgroundRole() );
1350 
1351  painter->fillRect( rect, brush );
1352  }
1353 }
1354 
1363  const QFontMetrics& fontMetrics, const QString& text )
1364 {
1365 #if QT_VERSION >= 0x050b00
1366  return fontMetrics.horizontalAdvance( text );
1367 #else
1368  return fontMetrics.width( text );
1369 #endif
1370 
1371 }
1372 
1381  const QFontMetricsF& fontMetrics, const QString& text )
1382 {
1383 #if QT_VERSION >= 0x050b00
1384  return fontMetrics.horizontalAdvance( text );
1385 #else
1386  return fontMetrics.width( text );
1387 #endif
1388 }
1389 
1398  const QFontMetrics& fontMetrics, QChar ch )
1399 {
1400 #if QT_VERSION >= 0x050b00
1401  return fontMetrics.horizontalAdvance( ch );
1402 #else
1403  return fontMetrics.width( ch );
1404 #endif
1405 }
1406 
1415  const QFontMetricsF& fontMetrics, QChar ch )
1416 {
1417 #if QT_VERSION >= 0x050b00
1418  return fontMetrics.horizontalAdvance( ch );
1419 #else
1420  return fontMetrics.width( ch );
1421 #endif
1422 }
1423 
1428 qreal QwtPainter::devicePixelRatio( const QPaintDevice *paintDevice )
1429 {
1430  qreal pixelRatio = 0.0;
1431 
1432 #if QT_VERSION >= 0x050100
1433  if ( paintDevice )
1434  {
1435 #if QT_VERSION >= 0x050600
1436  pixelRatio = paintDevice->devicePixelRatioF();
1437 #else
1438  pixelRatio = paintDevice->devicePixelRatio();
1439 #endif
1440  }
1441 #else
1442  Q_UNUSED( paintDevice )
1443 #endif
1444 
1445 #if QT_VERSION >= 0x050000
1446  if ( pixelRatio == 0.0 && qApp )
1447  pixelRatio = qApp->devicePixelRatio();
1448 #endif
1449 
1450  if ( pixelRatio == 0.0 )
1451  pixelRatio = 1.0;
1452 
1453  return pixelRatio;
1454 }
1455 
1462 QPixmap QwtPainter::backingStore( QWidget *widget, const QSize &size )
1463 {
1464  QPixmap pm;
1465 
1466 #if QT_VERSION >= 0x050000
1467  const qreal pixelRatio = QwtPainter::devicePixelRatio( widget );
1468 
1469  pm = QPixmap( size * pixelRatio );
1470  pm.setDevicePixelRatio( pixelRatio );
1471 #else
1472  pm = QPixmap( size );
1473 #endif
1474 
1475 #ifdef Q_WS_X11
1476  if ( widget && isX11GraphicsSystem() )
1477  {
1478  if ( pm.x11Info().screen() != widget->x11Info().screen() )
1479  pm.x11SetScreen( widget->x11Info().screen() );
1480  }
1481 #else
1482  Q_UNUSED( widget )
1483 #endif
1484 
1485  return pm;
1486 }
static void fillPixmap(const QWidget *, QPixmap &, const QPoint &offset=QPoint())
enum MQTTPropertyCodes value
static void drawImage(QPainter *, const QRectF &, const QImage &)
Wrapper for QPainter::drawImage()
static void fillRect(QPainter *, const QRectF &, const QBrush &)
Wrapper for QPainter::fillRect()
static void drawFocusRect(QPainter *, const QWidget *)
Draw a focus rectangle on a widget using its style.
virtual QVector< QRgb > colorTable256() const
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
Definition: qwt_painter.h:152
A class representing an interval.
Definition: qwt_interval.h:22
static void drawPoints(QPainter *, const QPolygon &)
Wrapper for QPainter::drawPoints()
Definition: qwt_painter.h:140
static void setRoundingAlignment(bool)
static void drawColorBar(QPainter *, const QwtColorMap &, const QwtInterval &, const QwtScaleMap &, Qt::Orientation, const QRectF &)
static void drawRoundFrame(QPainter *, const QRectF &, const QPalette &, int lineWidth, int frameStyle)
static void drawPixmap(QPainter *, const QRectF &, const QPixmap &)
Wrapper for QPainter::drawPixmap()
static bool isX11GraphicsSystem()
static void drawSimpleRichText(QPainter *, const QRectF &, int flags, const QTextDocument &)
static void drawPath(QPainter *, const QPainterPath &)
Wrapper for QPainter::drawPath()
static QPolygonF clippedPolygonF(const QRectF &, const QPolygonF &, bool closePolygon=false)
static void drawRoundedFrame(QPainter *, const QRectF &, qreal xRadius, qreal yRadius, const QPalette &, int lineWidth, int frameStyle)
int qwtFloor(qreal value)
Definition: qwt_math.h:271
static bool isAligning(const QPainter *)
static void setPolylineSplitting(bool)
En/Disable line splitting for the raster paint engine.
static QPolygon clippedPolygon(const QRect &, const QPolygon &, bool closePolygon=false)
virtual uint colorIndex(int numColors, const QwtInterval &interval, double value) const
Map a value of a given interval into a color index.
static void drawPolygon(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolygon()
static bool qwtIsClippingNeeded(const QPainter *painter, QRectF &clipRect)
Definition: qwt_painter.cpp:84
static void drawText(QPainter *, qreal x, qreal y, const QString &)
Wrapper for QPainter::drawText()
static int horizontalAdvance(const QFontMetrics &, const QString &)
static qreal devicePixelRatio(const QPaintDevice *)
static void clipPolygonF(const QRectF &, QPolygonF &, bool closePolygon=false)
void setPaintInterval(double p1, double p2)
Specify the borders of the paint device interval.
static QSize qwtScreenResolution()
static void drawFrame(QPainter *, const QRectF &rect, const QPalette &palette, QPalette::ColorRole foregroundRole, int lineWidth, int midLineWidth, int frameStyle)
QwtColorMap is used to map values into colors.
Definition: qwt_color_map.h:34
static void drawBackgound(QPainter *, const QRectF &, const QWidget *)
static bool qwtIsRasterPaintEngineBuggy()
Definition: qwt_painter.cpp:45
A scale map.
Definition: qwt_scale_map.h:26
double invTransform(double p) const
The map is intended to map into RGB values.
Definition: qwt_color_map.h:45
static void drawEllipse(QPainter *, const QRectF &)
Wrapper for QPainter::drawEllipse()
static void qwtFillRect(const QWidget *widget, QPainter *painter, const QRect &rect, const QBrush &brush)
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
static bool d_roundingAlignment
Definition: qwt_painter.h:130
MQTTClient c
Definition: test10.c:1656
static void drawPolyline(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolyline()
dictionary context
Definition: test2.py:57
static void qwtDrawPolyline(QPainter *painter, const T *points, int pointCount, bool polylineSplitting)
std::enable_if_t< all< Args... >::value, enable_t > enable
Definition: sol.hpp:1726
virtual QRgb rgb(const QwtInterval &interval, double value) const =0
static void qwtUnscaleFont(QPainter *painter)
static void drawPie(QPainter *, const QRectF &r, int a, int alen)
Wrapper for QPainter::drawPie()
Format format() const
static void drawPoint(QPainter *, const QPoint &)
Wrapper for QPainter::drawPoint()
int qwtCeil(qreal value)
Definition: qwt_math.h:262
static bool d_polylineSplitting
Definition: qwt_painter.h:129
static void clipPolygon(const QRect &, QPolygon &, bool closePolygon=false)
static QPixmap backingStore(QWidget *, const QSize &)


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10