summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qbezier_p.h
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/gui/painting/qbezier_p.h
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/gui/painting/qbezier_p.h')
-rw-r--r--src/gui/painting/qbezier_p.h274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/gui/painting/qbezier_p.h b/src/gui/painting/qbezier_p.h
new file mode 100644
index 0000000000..8d37e9a653
--- /dev/null
+++ b/src/gui/painting/qbezier_p.h
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBEZIER_P_H
+#define QBEZIER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qpoint.h"
+#include "QtCore/qline.h"
+#include "QtCore/qrect.h"
+#include "QtCore/qvector.h"
+#include "QtCore/qlist.h"
+#include "QtCore/qpair.h"
+#include "QtGui/qtransform.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPolygonF;
+
+class Q_GUI_EXPORT QBezier
+{
+public:
+ static QBezier fromPoints(const QPointF &p1, const QPointF &p2,
+ const QPointF &p3, const QPointF &p4);
+
+ static void coefficients(qreal t, qreal &a, qreal &b, qreal &c, qreal &d);
+
+ inline QPointF pointAt(qreal t) const;
+ inline QPointF normalVector(qreal t) const;
+
+ inline QPointF derivedAt(qreal t) const;
+ inline QPointF secondDerivedAt(qreal t) const;
+
+ QPolygonF toPolygon(qreal bezier_flattening_threshold = 0.5) const;
+ void addToPolygon(QPolygonF *p, qreal bezier_flattening_threshold = 0.5) const;
+
+ QRectF bounds() const;
+ qreal length(qreal error = 0.01) const;
+ void addIfClose(qreal *length, qreal error) const;
+
+ qreal tAtLength(qreal len) const;
+
+ int stationaryYPoints(qreal &t0, qreal &t1) const;
+ qreal tForY(qreal t0, qreal t1, qreal y) const;
+
+ QPointF pt1() const { return QPointF(x1, y1); }
+ QPointF pt2() const { return QPointF(x2, y2); }
+ QPointF pt3() const { return QPointF(x3, y3); }
+ QPointF pt4() const { return QPointF(x4, y4); }
+
+ QBezier mapBy(const QTransform &transform) const;
+
+ inline QPointF midPoint() const;
+ inline QLineF midTangent() const;
+
+ inline QLineF startTangent() const;
+ inline QLineF endTangent() const;
+
+ inline void parameterSplitLeft(qreal t, QBezier *left);
+ inline void split(QBezier *firstHalf, QBezier *secondHalf) const;
+
+ int shifted(QBezier *curveSegments, int maxSegmets,
+ qreal offset, float threshold) const;
+
+ QBezier bezierOnInterval(qreal t0, qreal t1) const;
+ QBezier getSubRange(qreal t0, qreal t1) const;
+
+ qreal x1, y1, x2, y2, x3, y3, x4, y4;
+};
+
+inline QPointF QBezier::midPoint() const
+{
+ return QPointF((x1 + x4 + 3*(x2 + x3))/8., (y1 + y4 + 3*(y2 + y3))/8.);
+}
+
+inline QLineF QBezier::midTangent() const
+{
+ QPointF mid = midPoint();
+ QLineF dir(QLineF(x1, y1, x2, y2).pointAt(0.5), QLineF(x3, y3, x4, y4).pointAt(0.5));
+ return QLineF(mid.x() - dir.dx(), mid.y() - dir.dy(),
+ mid.x() + dir.dx(), mid.y() + dir.dy());
+}
+
+inline QLineF QBezier::startTangent() const
+{
+ QLineF tangent(pt1(), pt2());
+ if (tangent.isNull())
+ tangent = QLineF(pt1(), pt3());
+ if (tangent.isNull())
+ tangent = QLineF(pt1(), pt4());
+ return tangent;
+}
+
+inline QLineF QBezier::endTangent() const
+{
+ QLineF tangent(pt4(), pt3());
+ if (tangent.isNull())
+ tangent = QLineF(pt4(), pt2());
+ if (tangent.isNull())
+ tangent = QLineF(pt4(), pt1());
+ return tangent;
+}
+
+inline void QBezier::coefficients(qreal t, qreal &a, qreal &b, qreal &c, qreal &d)
+{
+ qreal m_t = 1. - t;
+ b = m_t * m_t;
+ c = t * t;
+ d = c * t;
+ a = b * m_t;
+ b *= 3. * t;
+ c *= 3. * m_t;
+}
+
+inline QPointF QBezier::pointAt(qreal t) const
+{
+#if 1
+ qreal a, b, c, d;
+ coefficients(t, a, b, c, d);
+ return QPointF(a*x1 + b*x2 + c*x3 + d*x4, a*y1 + b*y2 + c*y3 + d*y4);
+#else
+ // numerically more stable:
+ qreal m_t = 1. - t;
+ qreal a = x1*m_t + x2*t;
+ qreal b = x2*m_t + x3*t;
+ qreal c = x3*m_t + x4*t;
+ a = a*m_t + b*t;
+ b = b*m_t + c*t;
+ qreal x = a*m_t + b*t;
+ qreal a = y1*m_t + y2*t;
+ qreal b = y2*m_t + y3*t;
+ qreal c = y3*m_t + y4*t;
+ a = a*m_t + b*t;
+ b = b*m_t + c*t;
+ qreal y = a*m_t + b*t;
+ return QPointF(x, y);
+#endif
+}
+
+inline QPointF QBezier::normalVector(qreal t) const
+{
+ qreal m_t = 1. - t;
+ qreal a = m_t * m_t;
+ qreal b = t * m_t;
+ qreal c = t * t;
+
+ return QPointF((y2-y1) * a + (y3-y2) * b + (y4-y3) * c, -(x2-x1) * a - (x3-x2) * b - (x4-x3) * c);
+}
+
+inline QPointF QBezier::derivedAt(qreal t) const
+{
+ // p'(t) = 3 * (-(1-2t+t^2) * p0 + (1 - 4 * t + 3 * t^2) * p1 + (2 * t - 3 * t^2) * p2 + t^2 * p3)
+
+ qreal m_t = 1. - t;
+
+ qreal d = t * t;
+ qreal a = -m_t * m_t;
+ qreal b = 1 - 4 * t + 3 * d;
+ qreal c = 2 * t - 3 * d;
+
+ return 3 * QPointF(a * x1 + b * x2 + c * x3 + d * x4,
+ a * y1 + b * y2 + c * y3 + d * y4);
+}
+
+inline QPointF QBezier::secondDerivedAt(qreal t) const
+{
+ qreal a = 2. - 2. * t;
+ qreal b = -4 + 6 * t;
+ qreal c = 2 - 6 * t;
+ qreal d = 2 * t;
+
+ return 3 * QPointF(a * x1 + b * x2 + c * x3 + d * x4,
+ a * y1 + b * y2 + c * y3 + d * y4);
+}
+
+inline void QBezier::split(QBezier *firstHalf, QBezier *secondHalf) const
+{
+ Q_ASSERT(firstHalf);
+ Q_ASSERT(secondHalf);
+
+ qreal c = (x2 + x3)*.5;
+ firstHalf->x2 = (x1 + x2)*.5;
+ secondHalf->x3 = (x3 + x4)*.5;
+ firstHalf->x1 = x1;
+ secondHalf->x4 = x4;
+ firstHalf->x3 = (firstHalf->x2 + c)*.5;
+ secondHalf->x2 = (secondHalf->x3 + c)*.5;
+ firstHalf->x4 = secondHalf->x1 = (firstHalf->x3 + secondHalf->x2)*.5;
+
+ c = (y2 + y3)/2;
+ firstHalf->y2 = (y1 + y2)*.5;
+ secondHalf->y3 = (y3 + y4)*.5;
+ firstHalf->y1 = y1;
+ secondHalf->y4 = y4;
+ firstHalf->y3 = (firstHalf->y2 + c)*.5;
+ secondHalf->y2 = (secondHalf->y3 + c)*.5;
+ firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2)*.5;
+}
+
+inline void QBezier::parameterSplitLeft(qreal t, QBezier *left)
+{
+ left->x1 = x1;
+ left->y1 = y1;
+
+ left->x2 = x1 + t * ( x2 - x1 );
+ left->y2 = y1 + t * ( y2 - y1 );
+
+ left->x3 = x2 + t * ( x3 - x2 ); // temporary holding spot
+ left->y3 = y2 + t * ( y3 - y2 ); // temporary holding spot
+
+ x3 = x3 + t * ( x4 - x3 );
+ y3 = y3 + t * ( y4 - y3 );
+
+ x2 = left->x3 + t * ( x3 - left->x3);
+ y2 = left->y3 + t * ( y3 - left->y3);
+
+ left->x3 = left->x2 + t * ( left->x3 - left->x2 );
+ left->y3 = left->y2 + t * ( left->y3 - left->y2 );
+
+ left->x4 = x1 = left->x3 + t * (x2 - left->x3);
+ left->y4 = y1 = left->y3 + t * (y2 - left->y3);
+}
+
+QT_END_NAMESPACE
+
+#endif // QBEZIER_P_H