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)