⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qstroker.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "private/qstroker_p.h"#include "private/qbezier_p.h"#include "private/qmath_p.h"#include "qline.h"#include "qtransform.h"// #define QPP_STROKE_DEBUGclass QSubpathForwardIterator{public:    QSubpathForwardIterator(const QDataBuffer<QStrokerOps::Element> *path)        : m_path(path), m_pos(0) { }    inline int position() const { return m_pos; }    inline bool hasNext() const { return m_pos < m_path->size(); }    inline QStrokerOps::Element next() { Q_ASSERT(hasNext()); return m_path->at(m_pos++); }private:    const QDataBuffer<QStrokerOps::Element> *m_path;    int m_pos;};class QSubpathBackwardIterator{public:    QSubpathBackwardIterator(const QDataBuffer<QStrokerOps::Element> *path)        : m_path(path), m_pos(path->size() - 1) { }    inline int position() const { return m_pos; }    inline bool hasNext() const { return m_pos >= 0; }    inline QStrokerOps::Element next()    {        Q_ASSERT(hasNext());        QStrokerOps::Element ce = m_path->at(m_pos);   // current element        if (m_pos == m_path->size() - 1) {            --m_pos;            ce.type = QPainterPath::MoveToElement;            return ce;        }        const QStrokerOps::Element &pe = m_path->at(m_pos + 1); // previous element        switch (pe.type) {        case QPainterPath::LineToElement:            ce.type = QPainterPath::LineToElement;            break;        case QPainterPath::CurveToDataElement:            // First control point?            if (ce.type == QPainterPath::CurveToElement) {                ce.type = QPainterPath::CurveToDataElement;            } else { // Second control point then                ce.type = QPainterPath::CurveToElement;            }            break;        case QPainterPath::CurveToElement:            ce.type = QPainterPath::CurveToDataElement;            break;        default:            qWarning("QSubpathReverseIterator::next: Case %d unhandled", ce.type);            break;        }        --m_pos;        return ce;    }private:    const QDataBuffer<QStrokerOps::Element> *m_path;    int m_pos;};class QSubpathFlatIterator{public:    QSubpathFlatIterator(const QDataBuffer<QStrokerOps::Element> *path)        : m_path(path), m_pos(0), m_curve_index(-1) { }    inline bool hasNext() const { return m_curve_index >= 0 || m_pos < m_path->size(); }    QStrokerOps::Element next()    {        Q_ASSERT(hasNext());        if (m_curve_index >= 0) {            QStrokerOps::Element e = { QPainterPath::LineToElement,                                       qt_real_to_fixed(m_curve.at(m_curve_index).x()),                                       qt_real_to_fixed(m_curve.at(m_curve_index).y())                                       };            ++m_curve_index;            if (m_curve_index >= m_curve.size())                m_curve_index = -1;            return e;        }        QStrokerOps::Element e = m_path->at(m_pos);        if (e.isCurveTo()) {            Q_ASSERT(m_pos > 0);            Q_ASSERT(m_pos < m_path->size());            m_curve = QBezier::fromPoints(QPointF(qt_fixed_to_real(m_path->at(m_pos-1).x),                                                  qt_fixed_to_real(m_path->at(m_pos-1).y)),                                          QPointF(qt_fixed_to_real(e.x),                                                  qt_fixed_to_real(e.y)),                                          QPointF(qt_fixed_to_real(m_path->at(m_pos+1).x),                                                  qt_fixed_to_real(m_path->at(m_pos+1).y)),                                          QPointF(qt_fixed_to_real(m_path->at(m_pos+2).x),                                                  qt_fixed_to_real(m_path->at(m_pos+2).y))).toPolygon();            m_curve_index = 1;            e.type = QPainterPath::LineToElement;            e.x = m_curve.at(0).x();            e.y = m_curve.at(0).y();            m_pos += 2;        }        Q_ASSERT(e.isLineTo() || e.isMoveTo());        ++m_pos;        return e;    }private:    const QDataBuffer<QStrokerOps::Element> *m_path;    int m_pos;    QPolygonF m_curve;    int m_curve_index;};template <class Iterator> bool qt_stroke_side(Iterator *it, QStroker *stroker,                                              bool capFirst, QLineF *startTangent);/******************************************************************************* * QLineF::angle gives us the smalles angle between two lines. Here we * want to identify the line's angle direction on the unit circle. */static inline qreal adapted_angle_on_x(const QLineF &line){    qreal angle = line.angle(QLineF(0, 0, 1, 0));    if (line.dy() > 0)        angle = 360 - angle;    return angle;}QStrokerOps::QStrokerOps()    : m_customData(0), m_moveTo(0), m_lineTo(0), m_cubicTo(0){}QStrokerOps::~QStrokerOps(){}/*!    Prepares the stroker. Call this function once before starting a    stroke by calling moveTo, lineTo or cubicTo.    The \a customData is passed back through that callback functions    and can be used by the user to for instance maintain state    information.*/void QStrokerOps::begin(void *customData){    m_customData = customData;    m_elements.reset();}/*!    Finishes the stroke. Call this function once when an entire    primitive has been stroked.*/void QStrokerOps::end(){    if (m_elements.size() > 1)        processCurrentSubpath();    m_customData = 0;}/*!    Convenience function that decomposes \a path into begin(),    moveTo(), lineTo(), curevTo() and end() calls.    The \a customData parameter is used in the callback functions    The \a matrix is used to transform the points before input to the    stroker.    \sa begin()*/void QStrokerOps::strokePath(const QPainterPath &path, void *customData, const QTransform &matrix){    if (path.isEmpty())        return;    begin(customData);    int count = path.elementCount();    if (matrix.isIdentity()) {        for (int i=0; i<count; ++i) {            const QPainterPath::Element &e = path.elementAt(i);            switch (e.type) {            case QPainterPath::MoveToElement:                moveTo(qt_real_to_fixed(e.x), qt_real_to_fixed(e.y));                break;            case QPainterPath::LineToElement:                lineTo(qt_real_to_fixed(e.x), qt_real_to_fixed(e.y));                break;            case QPainterPath::CurveToElement:                {                    const QPainterPath::Element &cp2 = path.elementAt(++i);                    const QPainterPath::Element &ep = path.elementAt(++i);                    cubicTo(qt_real_to_fixed(e.x), qt_real_to_fixed(e.y),                            qt_real_to_fixed(cp2.x), qt_real_to_fixed(cp2.y),                            qt_real_to_fixed(ep.x), qt_real_to_fixed(ep.y));                }                break;            default:                break;            }        }    } else {        for (int i=0; i<count; ++i) {            const QPainterPath::Element &e = path.elementAt(i);            QPointF pt = QPointF(e.x, e.y) * matrix;            switch (e.type) {            case QPainterPath::MoveToElement:                moveTo(qt_real_to_fixed(pt.x()), qt_real_to_fixed(pt.y()));                break;            case QPainterPath::LineToElement:                lineTo(qt_real_to_fixed(pt.x()), qt_real_to_fixed(pt.y()));                break;            case QPainterPath::CurveToElement:                {                    QPointF cp2 = ((QPointF) path.elementAt(++i)) * matrix;                    QPointF ep = ((QPointF) path.elementAt(++i)) * matrix;                    cubicTo(qt_real_to_fixed(pt.x()), qt_real_to_fixed(pt.y()),                            qt_real_to_fixed(cp2.x()), qt_real_to_fixed(cp2.y()),                            qt_real_to_fixed(ep.x()), qt_real_to_fixed(ep.y()));                }                break;            default:                break;            }        }    }    end();}/*!    Convenience function for stroking a polygon of the \a pointCount    first points in \a points. If \a implicit_close is set to true a    line is implictly drawn between the first and last point in the    polygon. Typically true for polygons and false for polylines.    The \a matrix is used to transform the points before they enter the    stroker.    \sa begin()*/void QStrokerOps::strokePolygon(const QPointF *points, int pointCount, bool implicit_close,                                void *data, const QTransform &matrix){    if (!pointCount)        return;    begin(data);    if (matrix.isIdentity()) {        moveTo(qt_real_to_fixed(points[0].x()), qt_real_to_fixed(points[0].y()));        for (int i=1; i<pointCount; ++i)            lineTo(qt_real_to_fixed(points[i].x()),                   qt_real_to_fixed(points[i].y()));        if (implicit_close)            lineTo(qt_real_to_fixed(points[0].x()), qt_real_to_fixed(points[0].y()));    } else {        QPointF start = points[0] * matrix;        moveTo(qt_real_to_fixed(start.x()), qt_real_to_fixed(start.y()));        for (int i=1; i<pointCount; ++i) {            QPointF pt = points[i] * matrix;            lineTo(qt_real_to_fixed(pt.x()), qt_real_to_fixed(pt.y()));        }        if (implicit_close)            lineTo(qt_real_to_fixed(start.x()), qt_real_to_fixed(start.y()));    }    end();}/*!    Convenience function for stroking an ellipse with bounding rect \a    rect. The \a matrix is used to transform the coordinates before    they enter the stroker.*/void QStrokerOps::strokeEllipse(const QRectF &rect, void *data, const QTransform &matrix){    int count = 0;    QPointF pts[12];    QPointF start = qt_curves_for_arc(rect, 0, 360, pts, &count);    Q_ASSERT(count == 12); // a perfect circle..    if (!matrix.isIdentity()) {        start = start * matrix;        for (int i=0; i<12; ++i) {            pts[i] = pts[i] * matrix;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -