10#include "qwt_plot_renderer.h"
12#include "qwt_painter.h"
13#include "qwt_plot_layout.h"
14#include "qwt_abstract_legend.h"
15#include "qwt_scale_widget.h"
16#include "qwt_scale_engine.h"
17#include "qwt_scale_map.h"
19#include "qwt_text_label.h"
23#include <qpainterpath.h>
24#include <qtransform.h>
26#include <qfiledialog.h>
28#include <qimagewriter.h>
34#define QWT_FORMAT_SVG 1
39#define QWT_FORMAT_PDF 1
48#if QT_VERSION >= 0x050300
51#define QWT_FORMAT_PDF 1
54#define QWT_PDF_WRITER 1
61#if QT_VERSION < 0x050000
62#define QWT_FORMAT_POSTSCRIPT 1
67#include <qsvggenerator.h>
71#include <qpdfwriter.h>
74static qreal qwtScalePenWidth(
const QwtPlot* plot )
78 for (
int axisId = 0; axisId < QwtAxis::AxisPositions; axisId++ )
87static QColor qwtScalePenColor(
const QwtPlot* plot )
90 return pal.color( QPalette::WindowText );
93static QPainterPath qwtCanvasClip(
94 const QWidget* canvas,
const QRectF& canvasRect )
100 int x1 = qwtCeil( canvasRect.left() );
101 int x2 = qwtFloor( canvasRect.right() );
102 int y1 = qwtCeil( canvasRect.top() );
103 int y2 = qwtFloor( canvasRect.bottom() );
105 const QRect r( x1, y1, x2 - x1 - 1, y2 - y1 - 1 );
107 QPainterPath clipPath;
109 ( void ) QMetaObject::invokeMethod(
110 const_cast< QWidget*
>( canvas ),
"borderPath",
111 Qt::DirectConnection,
112 Q_RETURN_ARG( QPainterPath, clipPath ), Q_ARG( QRect, r ) );
117static inline QFont qwtResolvedFont(
const QWidget* widget )
119 QFont font = widget->font();
120#if QT_VERSION >= 0x060000
121 font.setResolveMask( QFont::AllPropertiesResolved );
123 font.resolve( QFont::AllPropertiesResolved );
129class QwtPlotRenderer::PrivateData
149 m_data =
new PrivateData;
169 m_data->discardFlags |= flag;
171 m_data->discardFlags &= ~flag;
181 return m_data->discardFlags & flag;
192 m_data->discardFlags = flags;
201 return m_data->discardFlags;
215 m_data->layoutFlags |= flag;
217 m_data->layoutFlags &= ~flag;
227 return m_data->layoutFlags & flag;
238 m_data->layoutFlags = flags;
247 return m_data->layoutFlags;
262 const QString& fileName,
const QSizeF& sizeMM,
int resolution )
265 QFileInfo( fileName ).suffix(), sizeMM, resolution );
294 const QString& fileName,
const QString& format,
295 const QSizeF& sizeMM,
int resolution )
297 if ( plot == NULL || sizeMM.isEmpty() || resolution <= 0 )
301 if ( title.isEmpty() )
302 title =
"Plot Document";
304 const double mmToInch = 1.0 / 25.4;
305 const QSizeF size = sizeMM * mmToInch * resolution;
307 const QRectF documentRect( 0.0, 0.0, size.width(), size.height() );
309 const QString fmt = format.toLower();
310 if ( fmt == QLatin1String(
"pdf" ) )
315 QPdfWriter pdfWriter( fileName );
316 pdfWriter.setPageSize( QPageSize( sizeMM, QPageSize::Millimeter ) );
317 pdfWriter.setTitle( title );
318 pdfWriter.setPageMargins( QMarginsF() );
319 pdfWriter.setResolution( resolution );
321 QPainter painter( &pdfWriter );
322 render( plot, &painter, documentRect );
325 printer.setOutputFormat( QPrinter::PdfFormat );
326 printer.setColorMode( QPrinter::Color );
327 printer.setFullPage(
true );
328 printer.setPaperSize( sizeMM, QPrinter::Millimeter );
329 printer.setDocName( title );
330 printer.setOutputFileName( fileName );
331 printer.setResolution( resolution );
333 QPainter painter( &printer );
334 render( plot, &painter, documentRect );
338 else if ( fmt == QLatin1String(
"ps" ) )
340#if QWT_FORMAT_POSTSCRIPT
342 printer.setOutputFormat( QPrinter::PostScriptFormat );
343 printer.setColorMode( QPrinter::Color );
344 printer.setFullPage(
true );
345 printer.setPaperSize( sizeMM, QPrinter::Millimeter );
346 printer.setDocName( title );
347 printer.setOutputFileName( fileName );
348 printer.setResolution( resolution );
350 QPainter painter( &printer );
351 render( plot, &painter, documentRect );
354 else if ( fmt == QLatin1String(
"svg" ) )
357 QSvgGenerator generator;
358 generator.setTitle( title );
359 generator.setFileName( fileName );
360 generator.setResolution( resolution );
361 generator.setViewBox( documentRect );
363 QPainter painter( &generator );
364 render( plot, &painter, documentRect );
369 if ( QImageWriter::supportedImageFormats().indexOf(
370 format.toLatin1() ) >= 0 )
372 const QRect imageRect = documentRect.toRect();
373 const int dotsPerMeter = qRound( resolution * mmToInch * 1000.0 );
375 QImage image( imageRect.size(), QImage::Format_ARGB32 );
376 image.setDotsPerMeterX( dotsPerMeter );
377 image.setDotsPerMeterY( dotsPerMeter );
378 image.fill( QColor( Qt::white ).rgb() );
380 QPainter painter( &image );
381 render( plot, &painter, imageRect );
384 image.save( fileName, format.toLatin1() );
403 QwtPlot* plot, QPaintDevice& paintDevice )
const
405 int w = paintDevice.width();
406 int h = paintDevice.height();
408 QPainter p( &paintDevice );
409 render( plot, &p, QRectF( 0, 0, w, h ) );
428 QwtPlot* plot, QPrinter& printer )
const
430 int w = printer.width();
431 int h = printer.height();
433 QRectF rect( 0, 0, w, h );
434 double aspect = rect.width() / rect.height();
435 if ( ( aspect < 1.0 ) )
436 rect.setHeight( aspect * rect.width() );
438 QPainter p( &printer );
458 QwtPlot* plot, QSvgGenerator& generator )
const
460 QRectF rect = generator.viewBoxF();
461 if ( rect.isEmpty() )
462 rect.setRect( 0, 0, generator.width(), generator.height() );
464 if ( rect.isEmpty() )
465 rect.setRect( 0, 0, 800, 600 );
467 QPainter p( &generator );
483 QPainter* painter,
const QRectF& plotRect )
const
485 if ( painter == 0 || !painter->isActive() ||
486 !plotRect.isValid() || plot->size().isNull() )
499 QTransform transform;
501 double( painter->device()->logicalDpiX() ) / plot->logicalDpiX(),
502 double( painter->device()->logicalDpiY() ) / plot->logicalDpiY() );
504 QRectF layoutRect = transform.inverted().mapRect( plotRect );
510 const QMargins m = plot->contentsMargins();
511 layoutRect.adjust( m.left(), m.top(), -m.right(), -m.bottom() );
516 int baseLineDists[QwtAxis::AxisPositions];
517 int canvasMargins[QwtAxis::AxisPositions];
519 for (
int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
521 canvasMargins[axisPos] = layout->
canvasMargin( axisPos );
525 const QwtAxisId axisId( axisPos );
530 baseLineDists[axisPos] = scaleWidget->
margin();
540 const qreal fw = qwtScalePenWidth( plot );
545 layoutRect.adjust( fw, 0, 0, 0 );
549 layoutRect.adjust( 0, 0, -fw, 0 );
553 layoutRect.adjust( 0, fw, 0, 0 );
557 layoutRect.adjust( 0, 0, 0, -fw );
586 layout->
activate( plot, layoutRect, layoutOptions );
591 buildCanvasMaps( plot, layout->
canvasRect(), maps );
592 if ( updateCanvasMargins( plot, layout->
canvasRect(), maps ) )
597 layout->
activate( plot, layoutRect, layoutOptions );
598 buildCanvasMaps( plot, layout->
canvasRect(), maps );
604 painter->setWorldTransform( transform,
true );
626 for (
int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
629 const QwtAxisId axisId( axisPos );
634 int baseDist = scaleWidget->
margin();
636 int startDist, endDist;
639 renderScale( plot, painter, axisId, startDist, endDist,
648 for (
int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
652 const QwtAxisId axisId( axisPos );
656 scaleWidget->
setMargin( baseLineDists[axisPos] );
674 QPainter* painter,
const QRectF& titleRect )
const
676 painter->setFont( qwtResolvedFont( plot->
titleLabel() ) );
678 const QColor color = plot->
titleLabel()->palette().color(
679 QPalette::Active, QPalette::Text );
681 painter->setPen( color );
693 QPainter* painter,
const QRectF& footerRect )
const
695 painter->setFont( qwtResolvedFont( plot->
footerLabel() ) );
697 const QColor color = plot->
footerLabel()->palette().color(
698 QPalette::Active, QPalette::Text );
700 painter->setPen( color );
712 QPainter* painter,
const QRectF& legendRect )
const
734 QwtAxisId axisId,
int startDist,
int endDist,
int baseDist,
735 const QRectF& scaleRect )
const
755 off = qwtScalePenWidth( plot );
761 x = scaleRect.right() - 1.0 - baseDist - off;
762 y = scaleRect.y() + startDist;
763 w = scaleRect.height() - startDist - endDist;
769 x = scaleRect.left() + baseDist + off;
770 y = scaleRect.y() + startDist;
771 w = scaleRect.height() - startDist - endDist;
777 x = scaleRect.left() + startDist;
778 y = scaleRect.bottom() - 1.0 - baseDist - off;
779 w = scaleRect.width() - startDist - endDist;
785 x = scaleRect.left() + startDist;
786 y = scaleRect.top() + baseDist + off;
787 w = scaleRect.width() - startDist - endDist;
795 scaleWidget->
drawTitle( painter, align, scaleRect );
797 painter->setFont( qwtResolvedFont( scaleWidget ) );
800 const QPointF sdPos = sd->
pos();
801 const double sdLength = sd->
length();
811 QPalette palette = scaleWidget->palette();
812 palette.setCurrentColorGroup( QPalette::Active );
813 sd->
draw( painter, palette );
832 QPainter* painter,
const QRectF& canvasRect,
835 const QWidget* canvas = plot->
canvas();
837 QRectF r = canvasRect.adjusted( 0.0, 0.0, -1.0, -1.0 );
844 pen.setColor( qwtScalePenColor( plot ) );
845 pen.setWidth( qwtScalePenWidth( plot ) );
846 pen.setJoinStyle( Qt::MiterJoin );
848 painter->setPen( pen );
850 const qreal pw2 = 0.5 * pen.widthF();
851 r.adjust( -pw2, -pw2, pw2, pw2 );
855 const QBrush bgBrush =
856 canvas->palette().brush( plot->backgroundRole() );
857 painter->setBrush( bgBrush );
865 painter->setClipRect( canvasRect );
866 plot->
drawItems( painter, canvasRect, maps );
870 else if ( canvas->testAttribute( Qt::WA_StyledBackground ) )
872 QPainterPath clipPath;
879 clipPath = qwtCanvasClip( canvas, canvasRect );
885 if ( clipPath.isEmpty() )
886 painter->setClipRect( canvasRect );
888 painter->setClipPath( clipPath );
890 plot->
drawItems( painter, canvasRect, maps );
896 QPainterPath clipPath;
898 double frameWidth = 0.0;
902 const QVariant fw = canvas->property(
"frameWidth" );
903 if ( fw.canConvert<
double >() )
904 frameWidth = fw.value<
double >();
906 clipPath = qwtCanvasClip( canvas, canvasRect );
909 QRectF innerRect = canvasRect.adjusted(
910 frameWidth, frameWidth, -frameWidth, -frameWidth );
914 if ( clipPath.isEmpty() )
916 painter->setClipRect( innerRect );
920 painter->setClipPath( clipPath );
928 plot->
drawItems( painter, innerRect, maps );
932 if ( frameWidth > 0 )
936 const int frameStyle =
937 canvas->property(
"frameShadow" ).toInt() |
938 canvas->property(
"frameShape" ).toInt();
940 const QVariant borderRadius = canvas->property(
"borderRadius" );
941 if ( borderRadius.canConvert<
double >()
942 && borderRadius.value<
double >() > 0.0 )
944 const double radius = borderRadius.value<
double >();
947 radius, radius, canvas->palette(), frameWidth, frameStyle );
951 const int midLineWidth = canvas->property(
"midLineWidth" ).toInt();
954 canvas->palette(), canvas->foregroundRole(),
955 frameWidth, midLineWidth, frameStyle );
969void QwtPlotRenderer::buildCanvasMaps(
const QwtPlot* plot,
970 const QRectF& canvasRect,
QwtScaleMap maps[] )
const
972 for (
int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
975 const QwtAxisId axisId( axisPos );
995 from = scaleRect.left() + sDist;
996 to = scaleRect.right() - eDist;
1000 from = scaleRect.bottom() - eDist;
1001 to = scaleRect.top() + sDist;
1012 from = canvasRect.bottom() - margin;
1013 to = canvasRect.top() + margin;
1017 from = canvasRect.left() + margin;
1018 to = canvasRect.right() - margin;
1026bool QwtPlotRenderer::updateCanvasMargins(
QwtPlot* plot,
1027 const QRectF& canvasRect,
const QwtScaleMap maps[] )
const
1031 double margins[AxisPositions];
1033 margins[YLeft], margins[XTop], margins[YRight], margins[XBottom] );
1035 bool marginsChanged =
false;
1036 for (
int axisId = 0; axisId < AxisPositions; axisId++ )
1038 if ( margins[axisId] >= 0.0 )
1040 const int m = qwtCeil( margins[axisId] );
1042 marginsChanged =
true;
1046 return marginsChanged;
1061 const QSizeF& sizeMM,
int resolution )
1066 QString fileName = documentName;
1070#ifndef QT_NO_FILEDIALOG
1072 QImageWriter::supportedImageFormats();
1076 filter += QString(
"PDF " ) + tr(
"Documents" ) +
" (*.pdf)";
1079 filter += QString(
"SVG " ) + tr(
"Documents" ) +
" (*.svg)";
1081#if QWT_FORMAT_POSTSCRIPT
1082 filter += QString(
"Postscript " ) + tr(
"Documents" ) +
" (*.ps)";
1085 if ( imageFormats.size() > 0 )
1087 QString imageFilter( tr(
"Images" ) );
1088 imageFilter +=
" (";
1089 for (
int i = 0; i < imageFormats.size(); i++ )
1093 imageFilter +=
"*.";
1094 imageFilter += imageFormats[i];
1098 filter += imageFilter;
1101 fileName = QFileDialog::getSaveFileName(
1102 NULL, tr(
"Export File Name" ), fileName,
1103 filter.join(
";;" ), NULL, QFileDialog::DontConfirmOverwrite );
1105 if ( fileName.isEmpty() )
1113#include "moc_qwt_plot_renderer.cpp"
virtual void renderLegend(QPainter *painter, const QRectF &rect, bool fillBackground) const =0
virtual bool isEmpty() const =0
@ Backbone
Backbone = the line where the ticks are located.
bool hasComponent(ScaleComponent) const
virtual void draw(QPainter *, const QPalette &) const
Draw the scale.
void enableComponent(ScaleComponent, bool enable=true)
static void drawRoundedFrame(QPainter *, const QRectF &, qreal xRadius, qreal yRadius, const QPalette &, int lineWidth, int frameStyle)
static void drawBackgound(QPainter *, const QRectF &, const QWidget *)
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
static void drawFrame(QPainter *, const QRectF &rect, const QPalette &palette, QPalette::ColorRole foregroundRole, int lineWidth, int midLineWidth, int frameStyle)
virtual void getCanvasMarginsHint(const QwtScaleMap maps[], const QRectF &canvasRect, double &left, double &top, double &right, double &bottom) const
Calculate the canvas margins.
QwtScaleEngine * axisScaleEngine(QwtAxisId)
virtual void drawItems(QPainter *, const QRectF &, const QwtScaleMap maps[QwtAxis::AxisPositions]) const
QwtTextLabel * footerLabel()
bool isAxisVisible(QwtAxisId) const
QwtPlotLayout * plotLayout()
QwtAbstractLegend * legend()
const QwtScaleWidget * axisWidget(QwtAxisId) const
QwtTextLabel * titleLabel()
const QwtScaleDiv & axisScaleDiv(QwtAxisId) const
Return the scale division of a specified axis.
const QwtScaleDraw * axisScaleDraw(QwtAxisId) const
Return the scale draw of a specified axis.
Layout engine for QwtPlot.
void setCanvasMargin(int margin, int axis=-1)
QRectF footerRect() const
int canvasMargin(int axisId) const
QRectF legendRect() const
virtual void invalidate()
bool alignCanvasToScale(int axisId) const
QRectF scaleRect(QwtAxisId) const
QRectF canvasRect() const
@ IgnoreTitle
Ignore the title.
@ IgnoreFooter
Ignore the footer.
@ IgnoreFrames
Ignore all frames.
@ IgnoreLegend
Ignore the legend.
virtual void activate(const QwtPlot *, const QRectF &plotRect, Options options=Options())
Recalculate the geometry of all components.
Renderer for exporting a plot to a document, a printer or anything else, that is supported by QPainte...
void renderTo(QwtPlot *, QPrinter &) const
Render the plot to a QPrinter.
@ DefaultLayout
Use the default layout as on screen.
virtual void renderCanvas(const QwtPlot *, QPainter *, const QRectF &canvasRect, const QwtScaleMap *maps) const
virtual void renderFooter(const QwtPlot *, QPainter *, const QRectF &footerRect) const
void setDiscardFlag(DiscardFlag flag, bool on=true)
DiscardFlag
Discard flags.
@ DiscardFooter
Don't render the footer of the plot.
@ DiscardTitle
Don't render the title of the plot.
@ DiscardBackground
Don't render the background of the plot.
@ DiscardCanvasBackground
Don't render the background of the canvas.
@ DiscardLegend
Don't render the legend of the plot.
@ DiscardNone
Render all components of the plot.
virtual void renderLegend(const QwtPlot *, QPainter *, const QRectF &legendRect) const
void setLayoutFlags(LayoutFlags flags)
virtual ~QwtPlotRenderer()
Destructor.
virtual void renderScale(const QwtPlot *, QPainter *, QwtAxisId, int startDist, int endDist, int baseDist, const QRectF &scaleRect) const
Paint a scale into a given rectangle. Paint the scale into a given rectangle.
virtual void renderTitle(const QwtPlot *, QPainter *, const QRectF &titleRect) const
bool testLayoutFlag(LayoutFlag flag) const
void renderDocument(QwtPlot *, const QString &fileName, const QSizeF &sizeMM, int resolution=85)
QwtPlotRenderer(QObject *=NULL)
QFlags< LayoutFlag > LayoutFlags
void setLayoutFlag(LayoutFlag flag, bool on=true)
QFlags< DiscardFlag > DiscardFlags
DiscardFlags discardFlags() const
bool exportTo(QwtPlot *, const QString &documentName, const QSizeF &sizeMM=QSizeF(300, 200), int resolution=85)
Execute a file dialog and render the plot to the selected file.
void setDiscardFlags(DiscardFlags flags)
bool testDiscardFlag(DiscardFlag flag) const
virtual void render(QwtPlot *, QPainter *, const QRectF &plotRect) const
LayoutFlags layoutFlags() const
A class representing a scale division.
double lowerBound() const
double upperBound() const
A class for drawing scales.
void setLength(double length)
void move(double x, double y)
@ BottomScale
The scale is below.
@ TopScale
The scale is above.
@ RightScale
The scale is right.
@ LeftScale
The scale is left.
QwtTransform * transformation() const
void setPaintInterval(double p1, double p2)
Specify the borders of the paint device interval.
void setScaleInterval(double s1, double s2)
Specify the borders of the scale interval.
void setTransformation(QwtTransform *)
void draw(QPainter *painter, const QRectF &rect) const
const QwtText & text() const
Return the text.
bool isYAxis(int axisPos)
@ YRight
Y axis right of the canvas.
@ XTop
X axis above the canvas.
@ XBottom
X axis below the canvas.
@ YLeft
Y axis left of the canvas.
bool isXAxis(int axisPos)