/*!
  Render the legend into a given rectangle.

  \param plot Plot widget
  \param painter Painter
  \param rect Bounding rectangle
*/
void QwtPlotRenderer::renderLegend( const QwtPlot *plot,
    QPainter *painter, const QRectF &rect ) const
{
    if ( !plot->legend() || plot->legend()->isEmpty() )
        return;

    if ( !( d_data->discardFlags & DiscardBackground ) )
    {
        if ( plot->legend()->autoFillBackground() ||
            plot->legend()->testAttribute( Qt::WA_StyledBackground ) )
        {
            qwtRenderBackground( painter, rect, plot->legend() );
        }
    }

    const QwtDynGridLayout *legendLayout = qobject_cast<QwtDynGridLayout *>( 
        plot->legend()->contentsWidget()->layout() );
    if ( legendLayout == NULL )
        return;

    int left, right, top, bottom;
    plot->legend()->getContentsMargins( &left, &top, &right, &bottom );

    QRect layoutRect;
    layoutRect.setLeft( qCeil( rect.left() ) + left );
    layoutRect.setTop( qCeil( rect.top() ) + top );
    layoutRect.setRight( qFloor( rect.right() ) - right );
    layoutRect.setBottom( qFloor( rect.bottom() ) - bottom );

    uint numCols = legendLayout->columnsForWidth( layoutRect.width() );
    QList<QRect> itemRects =
        legendLayout->layoutItems( layoutRect, numCols );

    int index = 0;

    for ( int i = 0; i < legendLayout->count(); i++ )
    {
        QLayoutItem *item = legendLayout->itemAt( i );
        QWidget *w = item->widget();
        if ( w )
        {
            painter->save();

            painter->setClipRect( itemRects[index] );
            renderLegendItem( plot, painter, w, itemRects[index] );

            index++;
            painter->restore();
        }
    }
}
/*!
  Render the legend into a given rectangle.

  \param plot Plot widget
  \param painter Painter
  \param rect Bounding rectangle
*/
void QwtPlotRenderer::renderLegend( const QwtPlot *plot,
    QPainter *painter, const QRectF &rect ) const
{
    if ( !plot->legend() || plot->legend()->isEmpty() )
        return;

    if ( !( d_data->discardFlags & DiscardBackground ) )
    {
        if ( plot->legend()->autoFillBackground() ||
            plot->legend()->testAttribute( Qt::WA_StyledBackground ) )
        {
            qwtRenderBackground( painter, rect, plot->legend() );
        }
    }

    const QwtDynGridLayout *legendLayout = qobject_cast<QwtDynGridLayout *>( 
        plot->legend()->contentsWidget()->layout() );
    if ( legendLayout == NULL )
        return;

    uint numCols = legendLayout->columnsForWidth( rect.width() );
    QList<QRect> itemRects =
        legendLayout->layoutItems( rect.toRect(), numCols );

    int index = 0;

    for ( int i = 0; i < legendLayout->count(); i++ )
    {
        QLayoutItem *item = legendLayout->itemAt( i );
        QWidget *w = item->widget();
        if ( w )
        {
            painter->save();

            painter->setClipRect( itemRects[index] );
            renderLegendItem( plot, painter, w, itemRects[index] );

            index++;
            painter->restore();
        }
    }
}
/*!
  Render the legend item into a given rectangle.

  \param plot Plot widget
  \param painter Painter
  \param widget Widget representing a legend item
  \param rect Bounding rectangle

  \note When widget is not derived from QwtLegendItem renderLegendItem
        does nothing and needs to be overloaded
*/
void QwtPlotRenderer::renderLegendItem( const QwtPlot *plot,
    QPainter *painter, const QWidget *widget, const QRectF &rect ) const
{
    if ( !( d_data->discardFlags & DiscardBackground ) )
    {
        if ( widget->autoFillBackground() ||
            widget->testAttribute( Qt::WA_StyledBackground ) )
        {
            qwtRenderBackground( painter, rect, widget );
        }
    }

    const QwtLegendItem *item = qobject_cast<const QwtLegendItem *>( widget );
    if ( item )
    {
        const QSize sz = item->identifierSize();

        const QRectF identifierRect( rect.x() + item->margin(), 
            rect.center().y() - 0.5 * sz.height(), sz.width(), sz.height() );

        QwtLegendItemManager *itemManger = plot->legend()->find( item );
        if ( itemManger )
        {
            painter->save();
            painter->setClipRect( identifierRect, Qt::IntersectClip );
            itemManger->drawLegendIdentifier( painter, identifierRect );
            painter->restore();
        }

        // Label

        QRectF titleRect = rect;
        titleRect.setX( identifierRect.right() + 2 * item->spacing() );

        painter->setFont( item->font() );
        item->text().draw( painter, titleRect );
    }
}
/*!
  Render the canvas into a given rectangle.

  \param plot Plot widget
  \param painter Painter
  \param map Maps mapping between plot and paint device coordinates
  \param canvasRect Canvas rectangle
*/
void QwtPlotRenderer::renderCanvas( const QwtPlot *plot,
    QPainter *painter, const QRectF &canvasRect, 
    const QwtScaleMap *map ) const
{
    painter->save();

    QPainterPath clipPath;

    QRectF r = canvasRect.adjusted( 0.0, 0.0, -1.0, -1.0 );

    if ( d_data->layoutFlags & FrameWithScales )
    {
        r.adjust( -1.0, -1.0, 1.0, 1.0 );
        painter->setPen( QPen( Qt::black ) );

        if ( !( d_data->discardFlags & DiscardCanvasBackground ) )
        {
            const QBrush bgBrush =
                plot->canvas()->palette().brush( plot->backgroundRole() );
            painter->setBrush( bgBrush );
        }

        QwtPainter::drawRect( painter, r );
    }
    else
    {
        if ( !( d_data->discardFlags & DiscardCanvasBackground ) )
        {
            qwtRenderBackground( painter, r, plot->canvas() );

            if ( plot->canvas()->testAttribute( Qt::WA_StyledBackground ) )
            {
                // The clip region is calculated in integers
                // To avoid too much rounding errors better
                // calculate it in target device resolution
                // TODO ...

                int x1 = qCeil( canvasRect.left() );
                int x2 = qFloor( canvasRect.right() );
                int y1 = qCeil( canvasRect.top() );
                int y2 = qFloor( canvasRect.bottom() );

                clipPath = plot->canvas()->borderPath( 
                    QRect( x1, y1, x2 - x1 - 1, y2 - y1 - 1 ) );
            }
        }
    }

    painter->restore();

    painter->save();

    if ( clipPath.isEmpty() )
        painter->setClipRect( canvasRect );
    else
        painter->setClipPath( clipPath );

    plot->drawItems( painter, canvasRect, map );

    painter->restore();
}
/*!
  Paint the contents of a QwtPlot instance into a given rectangle.

  \param plot Plot to be rendered
  \param painter Painter
  \param plotRect Bounding rectangle

  \sa renderDocument(), renderTo(), QwtPainter::setRoundingAlignment()
*/
void QwtPlotRenderer::render( QwtPlot *plot,
    QPainter *painter, const QRectF &plotRect ) const
{
    int axisId;

    if ( painter == 0 || !painter->isActive() ||
            !plotRect.isValid() || plot->size().isNull() )
        return;

    if ( !( d_data->discardFlags & DiscardBackground ) )
        qwtRenderBackground( painter, plotRect, plot );

    /*
      The layout engine uses the same methods as they are used
      by the Qt layout system. Therefore we need to calculate the
      layout in screen coordinates and paint with a scaled painter.
     */
    QTransform transform;
    transform.scale(
        double( painter->device()->logicalDpiX() ) / plot->logicalDpiX(),
        double( painter->device()->logicalDpiY() ) / plot->logicalDpiY() );


    QRectF layoutRect = transform.inverted().mapRect( plotRect );

    if ( !( d_data->discardFlags & DiscardBackground ) )
    {
        // subtract the contents margins

        int left, top, right, bottom;
        plot->getContentsMargins( &left, &top, &right, &bottom );
        layoutRect.adjust( left, top, -right, -bottom );
    }

    int baseLineDists[QwtPlot::axisCnt];
    if ( d_data->layoutFlags & FrameWithScales )
    {
        for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
        {
            QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
            if ( scaleWidget )
            {
                baseLineDists[axisId] = scaleWidget->margin();
                scaleWidget->setMargin( 0 );
            }

            if ( !plot->axisEnabled( axisId ) )
            {
                int left = 0;
                int right = 0;
                int top = 0;
                int bottom = 0;

                // When we have a scale the frame is painted on
                // the position of the backbone - otherwise we
                // need to introduce a margin around the canvas

                switch( axisId )
                {
                    case QwtPlot::yLeft:
                        layoutRect.adjust( 1, 0, 0, 0 );
                        break;
                    case QwtPlot::yRight:
                        layoutRect.adjust( 0, 0, -1, 0 );
                        break;
                    case QwtPlot::xTop:
                        layoutRect.adjust( 0, 1, 0, 0 );
                        break;
                    case QwtPlot::xBottom:
                        layoutRect.adjust( 0, 0, 0, -1 );
                        break;
                    default:
                        break;
                }
                layoutRect.adjust( left, top, right, bottom );
            }
        }
    }

    // Calculate the layout for the document.

    QwtPlotLayout::Options layoutOptions = 
        QwtPlotLayout::IgnoreScrollbars | QwtPlotLayout::IgnoreFrames;

    if ( d_data->discardFlags & DiscardLegend )
        layoutOptions |= QwtPlotLayout::IgnoreLegend;

    plot->plotLayout()->activate( plot, layoutRect, layoutOptions );

    // now start painting

    painter->save();
    painter->setWorldTransform( transform, true );

    // canvas

    QwtScaleMap maps[QwtPlot::axisCnt];
    buildCanvasMaps( plot, plot->plotLayout()->canvasRect(), maps );
    renderCanvas( plot, painter, plot->plotLayout()->canvasRect(), maps );

    if ( !( d_data->discardFlags & DiscardTitle )
        && ( !plot->titleLabel()->text().isEmpty() ) )
    {
        renderTitle( plot, painter, plot->plotLayout()->titleRect() );
    }

    if ( !( d_data->discardFlags & DiscardLegend )
        && plot->legend() && !plot->legend()->isEmpty() )
    {
        renderLegend( plot, painter, plot->plotLayout()->legendRect() );
    }

    for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
    {
        QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
        if ( scaleWidget )
        {
            int baseDist = scaleWidget->margin();

            int startDist, endDist;
            scaleWidget->getBorderDistHint( startDist, endDist );

            renderScale( plot, painter, axisId, startDist, endDist,
                baseDist, plot->plotLayout()->scaleRect( axisId ) );
        }
    }


    plot->plotLayout()->invalidate();

    // reset all widgets with their original attributes.
    if ( d_data->layoutFlags & FrameWithScales )
    {
        // restore the previous base line dists

        for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
        {
            QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
            if ( scaleWidget  )
                scaleWidget->setMargin( baseLineDists[axisId] );
        }
    }

    painter->restore();
}
/*!
  Paint the contents of a QwtPlot instance into a given rectangle.

  \param plot Plot to be rendered
  \param painter Painter
  \param plotRect Bounding rectangle

  \sa renderDocument(), renderTo(), QwtPainter::setRoundingAlignment()
*/
void QwtPlotRenderer::render( QwtPlot *plot,
    QPainter *painter, const QRectF &plotRect ) const
{
    int axisId;

    if ( painter == 0 || !painter->isActive() ||
            !plotRect.isValid() || plot->size().isNull() )
        return;

    if ( !( d_data->discardFlags & DiscardBackground ) )
        qwtRenderBackground( painter, plotRect, plot );

    /*
      The layout engine uses the same methods as they are used
      by the Qt layout system. Therefore we need to calculate the
      layout in screen coordinates and paint with a scaled painter.
     */
    QTransform transform;
    transform.scale(
        double( painter->device()->logicalDpiX() ) / plot->logicalDpiX(),
        double( painter->device()->logicalDpiY() ) / plot->logicalDpiY() );

    painter->save();

    int baseLineDists[QwtPlot::axisCnt];
    if ( d_data->layoutFlags & FrameWithScales )
    {
        for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
        {
            QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
            if ( scaleWidget )
            {
                baseLineDists[axisId] = scaleWidget->margin();
                scaleWidget->setMargin( 0 );
            }
        }
    }
    // Calculate the layout for the print.

    QwtPlotLayout::Options layoutOptions = 
        QwtPlotLayout::IgnoreScrollbars | QwtPlotLayout::IgnoreFrames;
    if ( d_data->discardFlags & DiscardLegend )
        layoutOptions |= QwtPlotLayout::IgnoreLegend;

    const QRectF layoutRect = transform.inverted().mapRect( plotRect );
    plot->plotLayout()->activate( plot, layoutRect, layoutOptions );

    painter->setWorldTransform( transform, true );

    // canvas

    QwtScaleMap maps[QwtPlot::axisCnt];
    buildCanvasMaps( plot, plot->plotLayout()->canvasRect(), maps );
    renderCanvas( plot, painter, plot->plotLayout()->canvasRect(), maps );

    if ( !( d_data->discardFlags & DiscardTitle )
        && ( !plot->titleLabel()->text().isEmpty() ) )
    {
        renderTitle( plot, painter, plot->plotLayout()->titleRect() );
    }

    if ( !( d_data->discardFlags & DiscardLegend )
        && plot->legend() && !plot->legend()->isEmpty() )
    {
        renderLegend( plot, painter, plot->plotLayout()->legendRect() );
    }

    for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
    {
        QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
        if ( scaleWidget )
        {
            int baseDist = scaleWidget->margin();

            int startDist, endDist;
            scaleWidget->getBorderDistHint( startDist, endDist );

            renderScale( plot, painter, axisId, startDist, endDist,
                baseDist, plot->plotLayout()->scaleRect( axisId ) );
        }
    }


    plot->plotLayout()->invalidate();

    // reset all widgets with their original attributes.
    if ( d_data->layoutFlags & FrameWithScales )
    {
        // restore the previous base line dists

        for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
        {
            QwtScaleWidget *scaleWidget = plot->axisWidget( axisId );
            if ( scaleWidget  )
                scaleWidget->setMargin( baseLineDists[axisId] );
        }
    }

    painter->restore();
}