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


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