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> 
   27 #include <qfileinfo.h> 
   28 #include <qimagewriter.h> 
   34 #define QWT_FORMAT_SVG 1 
   39 #define QWT_FORMAT_PDF 1 
   48 #if QT_VERSION >= 0x050300 
   50 #ifndef QWT_FORMAT_PDF 
   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> 
   74 static qreal qwtScalePenWidth( 
const QwtPlot* plot )
 
   78     for ( 
int axisId = 0; axisId < QwtAxis::AxisPositions; axisId++ )
 
   87 static QColor qwtScalePenColor( 
const QwtPlot* plot )
 
   90     return pal.color( QPalette::WindowText );
 
   93 static 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 ) );
 
  117 static 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 );
 
  129 class 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 ) );
 
  425 #ifndef QT_NO_PRINTER 
  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 );
 
  969 void 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;
 
 1026 bool 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() )
 
 1114 #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)