diff options
-rw-r--r-- | src/quick/util/qquickpath.cpp | 35 | ||||
-rw-r--r-- | tests/auto/quick/qquickpath/tst_qquickpath.cpp | 38 |
2 files changed, 62 insertions, 11 deletions
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp index 8dadab620a..8cb6e47028 100644 --- a/src/quick/util/qquickpath.cpp +++ b/src/quick/util/qquickpath.cpp @@ -455,6 +455,20 @@ static inline QBezier nextBezier(const QPainterPath &path, int *current, qreal * return QBezier(); } +static inline int segmentCount(const QPainterPath &path, qreal pathLength) +{ + // In the really simple case of a single straight line we can interpolate without jitter + // between just two points. + if (path.elementCount() == 2 + && path.elementAt(0).type == QPainterPath::MoveToElement + && path.elementAt(1).type == QPainterPath::LineToElement) { + return 1; + } + // more points means less jitter between items as they move along the + // path, but takes longer to generate + return qCeil(pathLength*5); +} + //derivative of the equation static inline qreal slopeAt(qreal t, qreal a, qreal b, qreal c, qreal d) { @@ -467,11 +481,10 @@ void QQuickPath::createPointCache() const qreal pathLength = d->pathLength; if (pathLength <= 0 || qIsNaN(pathLength)) return; - // more points means less jitter between items as they move along the - // path, but takes longer to generate - const int points = qCeil(pathLength*5); + + const int segments = segmentCount(d->_path, pathLength); const int lastElement = d->_path.elementCount() - 1; - d->_pointCache.resize(points+1); + d->_pointCache.resize(segments+1); int currElement = -1; qreal bezLength = 0; @@ -484,7 +497,7 @@ void QQuickPath::createPointCache() const qreal prevPercent = 0; qreal prevOrigPercent = 0; for (int ii = 0; ii < d->_attributePoints.count(); ++ii) { - qreal percent = qreal(i)/points; + qreal percent = qreal(i)/segments; const AttributePoint &point = d->_attributePoints.at(ii); if (percent < point.percent || ii == d->_attributePoints.count() - 1) { //### || is special case for very last item qreal elementPercent = (percent - prevPercent); @@ -657,12 +670,12 @@ QPointF QQuickPath::pointAt(qreal p) const return QPointF(); } - const int pointCacheSize = d->_pointCache.size(); - qreal idxf = p*pointCacheSize; + const int segmentCount = d->_pointCache.size() - 1; + qreal idxf = p*segmentCount; int idx1 = qFloor(idxf); qreal delta = idxf - idx1; - if (idx1 >= pointCacheSize) - idx1 = pointCacheSize - 1; + if (idx1 > segmentCount) + idx1 = segmentCount; else if (idx1 < 0) idx1 = 0; @@ -671,8 +684,8 @@ QPointF QQuickPath::pointAt(qreal p) const // interpolate between the two points. int idx2 = qCeil(idxf); - if (idx2 >= pointCacheSize) - idx2 = pointCacheSize - 1; + if (idx2 > segmentCount) + idx2 = segmentCount; else if (idx2 < 0) idx2 = 0; diff --git a/tests/auto/quick/qquickpath/tst_qquickpath.cpp b/tests/auto/quick/qquickpath/tst_qquickpath.cpp index 73e7e6ea38..af5b194bd9 100644 --- a/tests/auto/quick/qquickpath/tst_qquickpath.cpp +++ b/tests/auto/quick/qquickpath/tst_qquickpath.cpp @@ -57,6 +57,7 @@ private slots: void catmullromCurve(); void closedCatmullromCurve(); void svg(); + void line(); }; void tst_QuickPath::arc() @@ -193,6 +194,43 @@ void tst_QuickPath::svg() QCOMPARE(pos, QPointF(1000,300)); } +void tst_QuickPath::line() +{ + QQmlEngine engine; + QQmlComponent c1(&engine); + c1.setData( + "import QtQuick 2.0\n" + "Path {\n" + "startX: 0; startY: 0\n" + "PathLine { x: 100; y: 100 }\n" + "}", QUrl()); + QScopedPointer<QObject> o1(c1.create()); + QQuickPath *path1 = qobject_cast<QQuickPath *>(o1.data()); + QVERIFY(path1); + + QQmlComponent c2(&engine); + c2.setData( + "import QtQuick 2.0\n" + "Path {\n" + "startX: 0; startY: 0\n" + "PathLine { x: 50; y: 50 }\n" + "PathLine { x: 100; y: 100 }\n" + "}", QUrl()); + QScopedPointer<QObject> o2(c2.create()); + QQuickPath *path2 = qobject_cast<QQuickPath *>(o2.data()); + QVERIFY(path2); + + for (int i = 0; i < 167; ++i) { + qreal t = i / 167.0; + + QPointF p1 = path1->pointAt(t); + QCOMPARE(p1.x(), p1.y()); + + QPointF p2 = path2->pointAt(t); + QCOMPARE(p1, p2); + } +} + QTEST_MAIN(tst_QuickPath) |