Пример #1
0
static QPoint cutPoint(QPoint p11, QPoint p12, QPoint p21, QPoint p22)
{
    double dx1 = p12.x() - p11.x();
    double dy1 = p12.y() - p11.y();
    double dx2 = p22.x() - p21.x();
    double dy2 = p22.y() - p21.y();

    if ( dx1 == 0.0 && dx2 == 0.0 )
        return QPoint();

    if ( dx1 == 0.0 )
    {
        const double m = dy2 / dx2;
        const double t = p21.y() - m * p21.x();
        return QPoint(p11.x(), qwtInt(m * p11.x() + t));
    }

    if ( dx2 == 0 )
    {
        const double m = dy1 / dx1;
        const double t = p11.y() - m * p11.x();
        return QPoint(p21.x(), qwtInt(m * p21.x() + t));
    }

    const double m1 = dy1 / dx1;
    const double t1 = p11.y() - m1 * p11.x();

    const double m2 = dy2 / dx2;
    const double t2 = p21.y() - m2 * p21.x();

    if ( m1 == m2 )
        return QPoint();

    const double x = ( t2 - t1 ) / ( m1 - m2 );
    const double y = t1 + m1 * x;

    return QPoint(qwtInt(x), qwtInt(y));
}
/*!
  \brief Paint the plot into a given rectangle.
  Paint the contents of a QwtPlot instance into a given rectangle.

  \param painter Painter
  \param plotRect Bounding rectangle
  \param pfilter Print filter
  \sa QwtPlotPrintFilter
*/
void QwtPlot::print(QPainter *painter, const QRect &plotRect,
        const QwtPlotPrintFilter &pfilter) const
{
    int axis;

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

    painter->save();

    // All paint operations need to be scaled according to
    // the paint device metrics. 

    QwtPainter::setMetricsMap(this, painter->device());

#if QT_VERSION < 300 
    if ( painter->device()->isExtDev() )
    {
        QPaintDeviceMetrics metrics(painter->device());
        if ( metrics.logicalDpiX() == 72 && metrics.logicalDpiY() == 72 )
        {
            // In Qt 2.x QPrinter returns hardcoded wrong metrics.
            // So scaling won´t work: we reset to screen resolution

            QwtPainter::setMetricsMap(this, this);
        }
    }
#endif

    const QwtMetricsMap &metricsMap = QwtPainter::metricsMap();

    // It is almost impossible to integrate into the Qt layout
    // framework, when using different fonts for printing
    // and screen. To avoid writing different and Qt unconform
    // layout engines we change the widget attributes, print and 
    // reset the widget attributes again. This way we produce a lot of
    // useless layout events ...

    pfilter.apply((QwtPlot *)this);

    int baseLineDists[QwtPlot::axisCnt];
    if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) )
    {
        // In case of no background we set the backbone of
        // the scale on the frame of the canvas.

        for (axis = 0; axis < QwtPlot::axisCnt; axis++ )
        {
            if ( d_scale[axis] )
            {
                baseLineDists[axis] = d_scale[axis]->baseLineDist();
                d_scale[axis]->setBaselineDist(0);
            }
        }
    }
    // Calculate the layout for the print.

    int layoutOptions = QwtPlotLayout::IgnoreScrollbars 
        | QwtPlotLayout::IgnoreFrames;
    if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) )
        layoutOptions |= QwtPlotLayout::IgnoreMargin;
    if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) )
        layoutOptions |= QwtPlotLayout::IgnoreLegend;

    d_layout->activate(this, QwtPainter::metricsMap().deviceToLayout(plotRect), 
        layoutOptions);

    if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle)
        && (!d_lblTitle->text().isEmpty()))
    {
        printTitle(painter, d_layout->titleRect());
    }

    if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend)
        && !d_legend->isEmpty() )
    {
        printLegend(painter, d_layout->legendRect());
    }

    for ( axis = 0; axis < QwtPlot::axisCnt; axis++ )
    {
        if (d_scale[axis])
        {
            int baseDist = d_scale[axis]->baseLineDist();

            int startDist, endDist;
            d_scale[axis]->minBorderDist(startDist, endDist);

            printScale(painter, axis, startDist, endDist,
                baseDist, d_layout->scaleRect(axis));
        }
    }

    const QRect canvasRect = metricsMap.layoutToDevice(d_layout->canvasRect());

    // When using QwtPainter all sizes where computed in pixel
    // coordinates and scaled by QwtPainter later. This limits
    // the precision to screen resolution. A much better solution
    // is to scale the maps and print in unlimited resolution.

    QwtArray<QwtDiMap> map(axisCnt);
    for (axis = 0; axis < axisCnt; axis++)
    {
        const QwtScaleDiv &scaleDiv = d_as[axis].scaleDiv();
        map[axis].setDblRange(scaleDiv.lBound(),
            scaleDiv.hBound(), scaleDiv.logScale());

        double from, to;
        if ( axisEnabled(axis) )
        {
            const int sDist = d_scale[axis]->startBorderDist();
            const int eDist = d_scale[axis]->endBorderDist();
            const QRect &scaleRect = d_layout->scaleRect(axis);

            if ( axis == xTop || axis == xBottom )
            {
                from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist);
                to = metricsMap.layoutToDeviceX(scaleRect.right() - eDist);
            }
            else
            {
                from = metricsMap.layoutToDeviceY(scaleRect.bottom() - sDist);
                to = metricsMap.layoutToDeviceY(scaleRect.top() + eDist);
            }
        }
        else
        {
            const int margin = plotLayout()->canvasMargin(axis);

            const QRect &canvasRect = plotLayout()->canvasRect();
            if ( axis == yLeft || axis == yRight )
            {
                from = metricsMap.layoutToDeviceX(canvasRect.bottom() - margin);
                to = metricsMap.layoutToDeviceX(canvasRect.top() + margin);
            }
            else
            {
                from = metricsMap.layoutToDeviceY(canvasRect.left() + margin);
                to = metricsMap.layoutToDeviceY(canvasRect.right() - margin);
            }
        }
        map[axis].setIntRange( qwtInt(from), qwtInt(to));
    }


    // The maps are already scaled. 
    QwtPainter::setMetricsMap(painter->device(), painter->device());

    printCanvas(painter, canvasRect, map, pfilter);

    QwtPainter::resetMetricsMap();

    d_layout->invalidate();

    // reset all widgets with their original attributes.
    if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) )
    {
        // restore the previous base line dists

        for (axis = 0; axis < QwtPlot::axisCnt; axis++ )
        {
            if ( d_scale[axis] )
                d_scale[axis]->setBaselineDist(baseLineDists[axis]);
        }
    }

    pfilter.reset((QwtPlot *)this);

    painter->restore();
}