diff options
author | Kaj Grönholm <kgronholm@gmail.com> | 2017-12-16 12:00:07 +0200 |
---|---|---|
committer | Tony Sarajärvi <tony.sarajarvi@qt.io> | 2018-02-01 06:39:24 +0000 |
commit | f5abe488f1e7c9c31badd0622b7374648bea943a (patch) | |
tree | 4ba5c8c2fdc3af666917cced5937c767bdd5e6ef /src/quick/util | |
parent | 07f9ca1759e35f1eb497fe2f1ad4b7ba71b69b5c (diff) |
Add optimized path for QML ShapePath
Improve performance of QML ShapePath, especially with more complex
animating paths. Testing revealed that considerable amount of time
is used for calculating QPainterPath::length(). QML ShapePath
doesn't support QQuickPathAttribute or QQuickPathPercent, so it
can have a fast-path for creating the path without calculating
length or attributes.
This gave heavy bezier lines rendering test ~7x performance boost.
Task-number: QTBUG-64951
Change-Id: I5240ed3516b5eafb0391790ac96835e70f88e540
Reviewed-by: Robin Burchell <robin.burchell@crimson.no>
Reviewed-by: Michael Brasser <michael.brasser@live.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/quick/util')
-rw-r--r-- | src/quick/util/qquickpath.cpp | 43 | ||||
-rw-r--r-- | src/quick/util/qquickpath_p.h | 1 | ||||
-rw-r--r-- | src/quick/util/qquickpath_p_p.h | 3 |
3 files changed, 45 insertions, 2 deletions
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp index 0323dc9286..1ae9b78669 100644 --- a/src/quick/util/qquickpath.cpp +++ b/src/quick/util/qquickpath.cpp @@ -397,7 +397,12 @@ void QQuickPath::processPath() d->_pointCache.clear(); d->prevBez.isValid = false; - d->_path = createPath(QPointF(), QPointF(), d->_attributes, d->pathLength, d->_attributePoints, &d->closed); + if (d->isShapePath) { + // This path is a ShapePath, so avoid extra overhead + d->_path = createShapePath(QPointF(), QPointF(), d->pathLength, &d->closed); + } else { + d->_path = createPath(QPointF(), QPointF(), d->_attributes, d->pathLength, d->_attributePoints, &d->closed); + } emit changed(); } @@ -493,6 +498,42 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en return path; } +QPainterPath QQuickPath::createShapePath(const QPointF &startPoint, const QPointF &endPoint, qreal &pathLength, bool *closed) +{ + Q_D(QQuickPath); + + if (!d->componentComplete) + return QPainterPath(); + + QPainterPath path; + + qreal startX = d->startX.isValid() ? d->startX.value : startPoint.x(); + qreal startY = d->startY.isValid() ? d->startY.value : startPoint.y(); + path.moveTo(startX, startY); + + int index = 0; + for (QQuickCurve *curve : qAsConst(d->_pathCurves)) { + QQuickPathData data; + data.index = index; + data.endPoint = endPoint; + data.curves = d->_pathCurves; + curve->addToPath(path, data); + ++index; + } + + if (closed) { + QPointF end = path.currentPosition(); + *closed = startX == end.x() && startY == end.y(); + } + + // Note: Length of paths inside ShapePath is not used, so currently + // length is always 0. This avoids potentially heavy path.length() + //pathLength = path.length(); + pathLength = 0; + + return path; +} + void QQuickPath::classBegin() { Q_D(QQuickPath); diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h index d5474e2d30..a49403fd0e 100644 --- a/src/quick/util/qquickpath_p.h +++ b/src/quick/util/qquickpath_p.h @@ -522,6 +522,7 @@ private: public: QPainterPath createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList<AttributePoint> &attributePoints, bool *closed = 0); + QPainterPath createShapePath(const QPointF &startPoint, const QPointF &endPoint, qreal &pathLength, bool *closed = 0); static QPointF sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle = 0); }; diff --git a/src/quick/util/qquickpath_p_p.h b/src/quick/util/qquickpath_p_p.h index 8ce85dbf0f..f5c9664223 100644 --- a/src/quick/util/qquickpath_p_p.h +++ b/src/quick/util/qquickpath_p_p.h @@ -72,7 +72,7 @@ public: static QQuickPathPrivate* get(QQuickPath *path) { return path->d_func(); } static const QQuickPathPrivate* get(const QQuickPath *path) { return path->d_func(); } - QQuickPathPrivate() : pathLength(0), closed(false), componentComplete(true) { } + QQuickPathPrivate() : pathLength(0), closed(false), componentComplete(true), isShapePath(false) { } QPainterPath _path; QList<QQuickPathElement*> _pathElements; @@ -86,6 +86,7 @@ public: qreal pathLength; bool closed; bool componentComplete; + bool isShapePath; }; QT_END_NAMESPACE |