From c13098fa6e0dcaca1022f1c50ced6cba4d5f7168 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 6 Jan 2012 09:37:03 +1000 Subject: [PATCH] Smooth join point for closed Paths starting and ending with PathCurve. Change-Id: I6d416e7d794271c10c9eb19de9678b0fe45b083d Reviewed-by: Bea Lam --- src/quick/util/qdeclarativepath.cpp | 38 ++++++++++++++-- .../qtquick2/qdeclarativepath/data/closedcurve.qml | 9 ++++ .../qdeclarativepath/tst_qdeclarativepath.cpp | 51 ++++++++++++++++++---- 3 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 tests/auto/qtquick2/qdeclarativepath/data/closedcurve.qml diff --git a/src/quick/util/qdeclarativepath.cpp b/src/quick/util/qdeclarativepath.cpp index 4f048ba..f1a2a1d 100644 --- a/src/quick/util/qdeclarativepath.cpp +++ b/src/quick/util/qdeclarativepath.cpp @@ -1377,8 +1377,32 @@ void QDeclarativePathCatmullRomCurve::addToPath(QPainterPath &path, const QDecla if (qobject_cast(curve)) { prev = path.currentPosition(); prevFar = previousPathPosition(path); - } else - prevFar = prev = path.currentPosition(); + } else { + prev = path.currentPosition(); + bool prevFarSet = false; + if (index == -1 && data.curves.count() > 1) { + if (qobject_cast(data.curves.at(data.curves.count()-1))) { + //TODO: profile and optimize + QPointF pos = prev; + QDeclarativePathData loopData; + loopData.endPoint = data.endPoint; + loopData.curves = data.curves; + for (int i = data.index; i < data.curves.count(); ++i) { + loopData.index = i; + pos = positionForCurve(loopData, pos); + if (i == data.curves.count()-2) + prevFar = pos; + } + if (pos == QPointF(path.elementAt(0))) { + //this is a closed path starting and ending with catmull-rom segments. + //we try to smooth the join point + prevFarSet = true; + } + } + } + if (!prevFarSet) + prevFar = prev; + } //get current point point = positionForCurve(data, path.currentPosition()); @@ -1391,8 +1415,14 @@ void QDeclarativePathCatmullRomCurve::addToPath(QPainterPath &path, const QDecla nextData.endPoint = data.endPoint; nextData.curves = data.curves; next = positionForCurve(nextData, point); - } else - next = point; + } else { + if (point == QPointF(path.elementAt(0)) && qobject_cast(data.curves.at(0))) { + //this is a closed path starting and ending with catmull-rom segments. + //we try to smooth the join point + next = QPointF(path.elementAt(3)); //the first catmull-rom point + } else + next = point; + } /* full conversion matrix (inverse bezier * catmull-rom): diff --git a/tests/auto/qtquick2/qdeclarativepath/data/closedcurve.qml b/tests/auto/qtquick2/qdeclarativepath/data/closedcurve.qml new file mode 100644 index 0000000..bb4a715 --- /dev/null +++ b/tests/auto/qtquick2/qdeclarativepath/data/closedcurve.qml @@ -0,0 +1,9 @@ +import QtQuick 2.0 + +Path { + startX: 50; startY: 50 + + PathCurve { x: 100; y: 100 } + PathCurve { x: 50; y: 150 } + PathCurve { x: 50; y: 50 } +} diff --git a/tests/auto/qtquick2/qdeclarativepath/tst_qdeclarativepath.cpp b/tests/auto/qtquick2/qdeclarativepath/tst_qdeclarativepath.cpp index 0b0000d..c268235 100644 --- a/tests/auto/qtquick2/qdeclarativepath/tst_qdeclarativepath.cpp +++ b/tests/auto/qtquick2/qdeclarativepath/tst_qdeclarativepath.cpp @@ -55,6 +55,7 @@ public: private slots: void arc(); void catmullromCurve(); + void closedCatmullromCurve(); void svg(); }; @@ -106,14 +107,15 @@ void tst_QDeclarativePath::catmullromCurve() QDeclarativeListReference list(obj, "pathElements"); QCOMPARE(list.count(), 3); - QDeclarativePathCatmullRomCurve* arc = qobject_cast(list.at(0)); -// QVERIFY(arc != 0); -// QCOMPARE(arc->x(), 100.); -// QCOMPARE(arc->y(), 100.); -// QCOMPARE(arc->radiusX(), 100.); -// QCOMPARE(arc->radiusY(), 100.); -// QCOMPARE(arc->useLargeArc(), false); -// QCOMPARE(arc->direction(), QDeclarativePathArc::Clockwise); + QDeclarativePathCatmullRomCurve* curve = qobject_cast(list.at(0)); + QVERIFY(curve != 0); + QCOMPARE(curve->x(), 100.); + QCOMPARE(curve->y(), 50.); + + curve = qobject_cast(list.at(2)); + QVERIFY(curve != 0); + QCOMPARE(curve->x(), 100.); + QCOMPARE(curve->y(), 150.); QPainterPath path = obj->path(); QVERIFY(path != QPainterPath()); @@ -128,6 +130,39 @@ void tst_QDeclarativePath::catmullromCurve() QCOMPARE(pos, QPointF(100,150)); } +void tst_QDeclarativePath::closedCatmullromCurve() +{ + QDeclarativeEngine engine; + QDeclarativeComponent c(&engine, testFileUrl("closedcurve.qml")); + QDeclarativePath *obj = qobject_cast(c.create()); + QVERIFY(obj != 0); + + QCOMPARE(obj->startX(), 50.); + QCOMPARE(obj->startY(), 50.); + + QDeclarativeListReference list(obj, "pathElements"); + QCOMPARE(list.count(), 3); + + QDeclarativePathCatmullRomCurve* curve = qobject_cast(list.at(2)); + QVERIFY(curve != 0); + QCOMPARE(curve->x(), 50.); + QCOMPARE(curve->y(), 50.); + + QVERIFY(obj->isClosed()); + + QPainterPath path = obj->path(); + QVERIFY(path != QPainterPath()); + + QPointF pos = obj->pointAt(0); + QCOMPARE(pos, QPointF(50,50)); + pos = obj->pointAt(.1); + QCOMPARE(pos.toPoint(), QPoint(67,56)); //fuzzy compare + pos = obj->pointAt(.75); + QCOMPARE(pos.toPoint(), QPoint(44,116)); //fuzzy compare + pos = obj->pointAt(1); + QCOMPARE(pos, QPointF(50,50)); +} + void tst_QDeclarativePath::svg() { QDeclarativeEngine engine; -- 2.7.4