aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2019-05-06 20:37:42 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2019-06-04 20:52:01 +0200
commit3961cf124af9d811da4bbe72bb28508aef71c7df (patch)
tree221298e19225250c3b53c80d05693c4398ee7854
parent00b317a19eed629d041d27596e40c1cf24fdf1a6 (diff)
Add scale property to QQuickPath
With this property, Paths and ShapePaths become scalable. [ChangeLog][QQuick][Path] Added scale property to scale a path before sending it in to PathView/Shape. Change-Id: Id9ce7d1247d55e2cdb0d27a19c86fe0970e66268 Fixes: QTBUG-74456 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r--src/imports/shapes/plugin.cpp3
-rw-r--r--src/quick/items/qquickitemsmodule.cpp1
-rw-r--r--src/quick/util/qquickpath.cpp45
-rw-r--r--src/quick/util/qquickpath_p.h5
-rw-r--r--src/quick/util/qquickpath_p_p.h1
-rw-r--r--src/quickshapes/qquickshape_p.h1
-rw-r--r--tests/auto/quick/qquickpath/qquickpath.pro1
-rw-r--r--tests/auto/quick/qquickpath/tst_qquickpath.cpp156
-rw-r--r--tests/auto/quick/qquickshape/qquickshape.pro1
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp2
-rw-r--r--tests/manual/scalablepath/ShapeTestScale.qml287
-rw-r--r--tests/manual/scalablepath/main.cpp42
-rw-r--r--tests/manual/scalablepath/main.qml42
-rw-r--r--tests/manual/scalablepath/qml.qrc6
-rw-r--r--tests/manual/scalablepath/scalablepath.pro5
15 files changed, 559 insertions, 39 deletions
diff --git a/src/imports/shapes/plugin.cpp b/src/imports/shapes/plugin.cpp
index e3a9017681..0679a70630 100644
--- a/src/imports/shapes/plugin.cpp
+++ b/src/imports/shapes/plugin.cpp
@@ -69,6 +69,9 @@ public:
// revision in Qt 5.11: added containsMode property
qmlRegisterType<QQuickShape, 11>(uri, 1, 11, "Shape");
+
+ // revision in Qt 5.14: added scale property
+ qmlRegisterType<QQuickShapePath, 14>(uri, 1, 14, "ShapePath"); // QTBUG-61942
}
};
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index eaad06e0c4..4649e33070 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -226,6 +226,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickPathCatmullRomCurve>("QtQuick",2,0,"PathCurve");
qmlRegisterType<QQuickPathArc>("QtQuick",2,0,"PathArc");
qmlRegisterType<QQuickPathSvg>("QtQuick",2,0,"PathSvg");
+ qmlRegisterType<QQuickPath, 14>(uri, 2, 14, "Path");
#endif
#if QT_CONFIG(quick_pathview)
qmlRegisterType<QQuickPathView>(uri,major,minor,"PathView");
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp
index 16723b997e..a0f3749552 100644
--- a/src/quick/util/qquickpath.cpp
+++ b/src/quick/util/qquickpath.cpp
@@ -407,6 +407,19 @@ void QQuickPath::processPath()
emit changed();
}
+inline static void scalePath(QPainterPath &path, const QSizeF &scale)
+{
+ const qreal xscale = scale.width();
+ const qreal yscale = scale.height();
+ if (xscale == 1 && yscale == 1)
+ return;
+
+ for (int i = 0; i < path.elementCount(); ++i) {
+ const QPainterPath::Element &element = path.elementAt(i);
+ path.setElementPositionAt(i, element.x * xscale, element.y * yscale);
+ }
+}
+
QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList<AttributePoint> &attributePoints, bool *closed)
{
Q_D(QQuickPath);
@@ -465,7 +478,7 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
d->_attributePoints.last().values[percentString] = 1;
interpolate(d->_attributePoints.count() - 1, percentString, 1);
}
-
+ scalePath(path, d->scale);
// Adjust percent
qreal length = path.length();
@@ -491,7 +504,7 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
if (closed) {
QPointF end = path.currentPosition();
- *closed = length > 0 && startX == end.x() && startY == end.y();
+ *closed = length > 0 && startX * d->scale.width() == end.x() && startY * d->scale.height() == end.y();
}
pathLength = length;
@@ -525,6 +538,7 @@ QPainterPath QQuickPath::createShapePath(const QPointF &startPoint, const QPoint
QPointF end = path.currentPosition();
*closed = startX == end.x() && startY == end.y();
}
+ scalePath(path, d->scale);
// Note: Length of paths inside ShapePath is not used, so currently
// length is always 0. This avoids potentially heavy path.length()
@@ -723,6 +737,33 @@ void QQuickPath::invalidateSequentialHistory() const
d->prevBez.isValid = false;
}
+/*!
+ \qmlproperty size QtQuick::Path::scale
+
+ This property holds the scale factor for the path.
+ The width and height of \a scale can be different, to
+ achieve anisotropic scaling.
+
+ \note Setting this property will not affect the border width.
+
+ \since QtQuick 2.14
+*/
+QSizeF QQuickPath::scale() const
+{
+ Q_D(const QQuickPath);
+ return d->scale;
+}
+
+void QQuickPath::setScale(const QSizeF &scale)
+{
+ Q_D(QQuickPath);
+ if (scale == d->scale)
+ return;
+ d->scale = scale;
+ emit scaleChanged();
+ processPath();
+}
+
QPointF QQuickPath::sequentialPointAt(qreal p, qreal *angle) const
{
Q_D(const QQuickPath);
diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h
index 6b9a40fe6d..01f60c34d2 100644
--- a/src/quick/util/qquickpath_p.h
+++ b/src/quick/util/qquickpath_p.h
@@ -445,6 +445,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPath : public QObject, public QQmlParserStatu
Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged)
Q_PROPERTY(qreal startY READ startY WRITE setStartY NOTIFY startYChanged)
Q_PROPERTY(bool closed READ isClosed NOTIFY changed)
+ Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION 14)
Q_CLASSINFO("DefaultProperty", "pathElements")
Q_INTERFACES(QQmlParserStatus)
public:
@@ -470,10 +471,14 @@ public:
QPointF sequentialPointAt(qreal p, qreal *angle = nullptr) const;
void invalidateSequentialHistory() const;
+ QSizeF scale() const;
+ void setScale(const QSizeF &scale);
+
Q_SIGNALS:
void changed();
void startXChanged();
void startYChanged();
+ Q_REVISION(14) void scaleChanged();
protected:
QQuickPath(QQuickPathPrivate &dd, QObject *parent = nullptr);
diff --git a/src/quick/util/qquickpath_p_p.h b/src/quick/util/qquickpath_p_p.h
index 9735d51264..e26001ec77 100644
--- a/src/quick/util/qquickpath_p_p.h
+++ b/src/quick/util/qquickpath_p_p.h
@@ -84,6 +84,7 @@ public:
QQmlNullableValue<qreal> startX;
QQmlNullableValue<qreal> startY;
qreal pathLength = 0;
+ QSizeF scale = QSizeF(1, 1);
bool closed = false;
bool componentComplete = true;
bool isShapePath = false;
diff --git a/src/quickshapes/qquickshape_p.h b/src/quickshapes/qquickshape_p.h
index cd242cafc3..7066ea0709 100644
--- a/src/quickshapes/qquickshape_p.h
+++ b/src/quickshapes/qquickshape_p.h
@@ -213,6 +213,7 @@ class Q_QUICKSHAPES_PRIVATE_EXPORT QQuickShapePath : public QQuickPath
Q_PROPERTY(qreal dashOffset READ dashOffset WRITE setDashOffset NOTIFY dashOffsetChanged)
Q_PROPERTY(QVector<qreal> dashPattern READ dashPattern WRITE setDashPattern NOTIFY dashPatternChanged)
Q_PROPERTY(QQuickShapeGradient *fillGradient READ fillGradient WRITE setFillGradient RESET resetFillGradient)
+ Q_PROPERTY(QSizeF scale READ scale WRITE setScale NOTIFY scaleChanged REVISION 14)
public:
enum FillRule {
diff --git a/tests/auto/quick/qquickpath/qquickpath.pro b/tests/auto/quick/qquickpath/qquickpath.pro
index 492f82f53d..ef110a8331 100644
--- a/tests/auto/quick/qquickpath/qquickpath.pro
+++ b/tests/auto/quick/qquickpath/qquickpath.pro
@@ -7,5 +7,6 @@ SOURCES += tst_qquickpath.cpp
include (../../shared/util.pri)
TESTDATA = data/*
+DISTFILES = data/*
QT += core-private gui-private qml-private quick-private testlib
diff --git a/tests/auto/quick/qquickpath/tst_qquickpath.cpp b/tests/auto/quick/qquickpath/tst_qquickpath.cpp
index 12a8c673b0..bac1fc5861 100644
--- a/tests/auto/quick/qquickpath/tst_qquickpath.cpp
+++ b/tests/auto/quick/qquickpath/tst_qquickpath.cpp
@@ -42,18 +42,44 @@ public:
private slots:
void arc();
void angleArc();
- void catmullromCurve();
- void closedCatmullromCurve();
+ void catmullRomCurve();
+ void closedCatmullRomCurve();
void svg();
void line();
+
+private:
+ void arc(QSizeF scale);
+ void angleArc(QSizeF scale);
+ void catmullRomCurve(QSizeF scale, const QVector<QPointF> &points);
+ void closedCatmullRomCurve(QSizeF scale, const QVector<QPointF> &points);
+ void svg(QSizeF scale);
+ void line(QSizeF scale);
};
-void tst_QuickPath::arc()
+static void compare(const QPointF &point, const QSizeF &scale, int line, double x, double y)
+{
+ QVERIFY2(qFuzzyCompare(float(point.x()), float(x * scale.width())),
+ (QStringLiteral("Actual: ") + QString::number(point.x(),'g',14)
+ + QStringLiteral(" Expected: ") + QString::number(x * scale.width(),'g',14)
+ + QStringLiteral(" At: ") + QString::number(line)).toLatin1().data());
+ QVERIFY2(qFuzzyCompare(float(point.y()), float(y * scale.height())),
+ (QStringLiteral("Actual: ") + QString::number(point.y(),'g',14)
+ + QStringLiteral(" Expected: ") + QString::number(y * scale.height(),'g',14)
+ + QStringLiteral(" At: ") + QString::number(line)).toLatin1().data());
+}
+static void compare(const QPointF &point, int line, const QPointF &pt)
+{
+ return compare(point, QSizeF(1,1), line, pt.x(), pt.y());
+}
+
+void tst_QuickPath::arc(QSizeF scale)
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("arc.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
QVERIFY(obj != nullptr);
+ if (scale != QSizeF(1,1))
+ obj->setProperty("scale", scale);
QCOMPARE(obj->startX(), 0.);
QCOMPARE(obj->startY(), 0.);
@@ -76,19 +102,27 @@ void tst_QuickPath::arc()
QPointF pos = obj->pointAt(0);
QCOMPARE(pos, QPointF(0,0));
pos = obj->pointAt(.25);
- QCOMPARE(pos.toPoint(), QPoint(39,8)); //fuzzy compare
+ compare(pos, scale, __LINE__, 38.9244897744, 7.85853964341);
pos = obj->pointAt(.75);
- QCOMPARE(pos.toPoint(), QPoint(92,61)); //fuzzy compare
+ compare(pos, scale, __LINE__, 92.141460356592, 61.07551022559);
pos = obj->pointAt(1);
- QCOMPARE(pos, QPointF(100,100));
+ QCOMPARE(pos, QPointF(100 * scale.width(), 100 * scale.height()));
}
-void tst_QuickPath::angleArc()
+void tst_QuickPath::arc()
+{
+ arc(QSizeF(1,1));
+ arc(QSizeF(2.2,3.4));
+}
+
+void tst_QuickPath::angleArc(QSizeF scale)
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("anglearc.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
QVERIFY(obj != nullptr);
+ if (scale != QSizeF(1,1))
+ obj->setProperty("scale", scale);
QQmlListReference list(obj, "pathElements");
QCOMPARE(list.count(), 1);
@@ -106,15 +140,14 @@ void tst_QuickPath::angleArc()
QPainterPath path = obj->path();
QVERIFY(path != QPainterPath());
- // using QPoint to do fuzzy compare
QPointF pos = obj->pointAt(0);
- QCOMPARE(pos.toPoint(), QPoint(135,135));
+ compare(pos, scale, __LINE__, 135.35533905867, 135.35533905867);
pos = obj->pointAt(.25);
- QCOMPARE(pos.toPoint(), QPoint(119,146));
+ compare(pos, scale, __LINE__, 119.46222180396, 146.07068621369);
pos = obj->pointAt(.75);
- QCOMPARE(pos.toPoint(), QPoint(81,146));
+ compare(pos, scale, __LINE__, 80.537778196007, 146.07068621366);
pos = obj->pointAt(1);
- QCOMPARE(pos.toPoint(), QPoint(65,135));
+ compare(pos, scale, __LINE__, 64.644660941173, 135.35533905867);
// if moveToStart is false, we should have a line starting from startX/Y
arc->setMoveToStart(false);
@@ -122,12 +155,20 @@ void tst_QuickPath::angleArc()
QCOMPARE(pos, QPointF(0,0));
}
-void tst_QuickPath::catmullromCurve()
+void tst_QuickPath::angleArc()
+{
+ angleArc(QSizeF(1,1));
+ angleArc(QSizeF(2.7,0.92));
+}
+
+void tst_QuickPath::catmullRomCurve(QSizeF scale, const QVector<QPointF> &points)
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("curve.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
QVERIFY(obj != nullptr);
+ if (scale != QSizeF(1,1))
+ obj->setProperty("scale", scale);
QCOMPARE(obj->startX(), 0.);
QCOMPARE(obj->startY(), 0.);
@@ -148,22 +189,36 @@ void tst_QuickPath::catmullromCurve()
QPainterPath path = obj->path();
QVERIFY(path != QPainterPath());
- QPointF pos = obj->pointAt(0);
- QCOMPARE(pos, QPointF(0,0));
- pos = obj->pointAt(.25);
- QCOMPARE(pos.toPoint(), QPoint(63,26)); //fuzzy compare
- pos = obj->pointAt(.75);
- QCOMPARE(pos.toPoint(), QPoint(51,105)); //fuzzy compare
- pos = obj->pointAt(1);
- QCOMPARE(pos.toPoint(), QPoint(100,150));
+ QPointF pos = path.pointAtPercent(0);
+ QCOMPARE(pos, points.at(0));
+ pos = path.pointAtPercent(.25);
+ compare(pos, __LINE__, points.at(1));
+ pos = path.pointAtPercent(.75);
+ compare(pos, __LINE__, points.at(2));
+ pos = path.pointAtPercent(1);
+ compare(pos, __LINE__, points.at(3));
}
-void tst_QuickPath::closedCatmullromCurve()
+void tst_QuickPath::catmullRomCurve()
+{
+ catmullRomCurve(QSizeF(1,1), { QPointF(0,0),
+ QPointF(62.917022919131, 26.175485291549),
+ QPointF(51.194527196674 , 105.27985623074),
+ QPointF(100, 150) });
+ catmullRomCurve(QSizeF(2,5.3), { QPointF(0,0),
+ QPointF(150.80562419914, 170.34065984615),
+ QPointF(109.08400252853 , 588.35165918579),
+ QPointF(200, 795) });
+}
+
+void tst_QuickPath::closedCatmullRomCurve(QSizeF scale, const QVector<QPointF> &points)
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("closedcurve.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
QVERIFY(obj != nullptr);
+ if (scale != QSizeF(1,1))
+ obj->setProperty("scale", scale);
QCOMPARE(obj->startX(), 50.);
QCOMPARE(obj->startY(), 50.);
@@ -181,22 +236,36 @@ void tst_QuickPath::closedCatmullromCurve()
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));
+ QPointF pos = path.pointAtPercent(0);
+ QCOMPARE(pos, points.at(0));
+ pos = path.pointAtPercent(.1);
+ compare(pos, __LINE__, points.at(1));
+ pos = path.pointAtPercent(.75);
+ compare(pos, __LINE__, points.at(2));
+ pos = path.pointAtPercent(1);
+ compare(pos, __LINE__, points.at(3));
}
-void tst_QuickPath::svg()
+void tst_QuickPath::closedCatmullRomCurve()
+{
+ closedCatmullRomCurve(QSizeF(1,1), { QPointF(50,50),
+ QPointF(66.776225481812, 55.617435304145),
+ QPointF(44.10269379731 , 116.33512508175),
+ QPointF(50, 50) });
+ closedCatmullRomCurve(QSizeF(2,3), { QPointF(100,150),
+ QPointF(136.49725836178, 170.25466686363),
+ QPointF(87.713232151943 , 328.29232737977),
+ QPointF(100, 150) });
+}
+
+void tst_QuickPath::svg(QSizeF scale)
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("svg.qml"));
QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
QVERIFY(obj != nullptr);
+ if (scale != QSizeF(1,1))
+ obj->setProperty("scale", scale);
QCOMPARE(obj->startX(), 0.);
QCOMPARE(obj->startY(), 0.);
@@ -212,16 +281,22 @@ void tst_QuickPath::svg()
QVERIFY(path != QPainterPath());
QPointF pos = obj->pointAt(0);
- QCOMPARE(pos, QPointF(200,300));
+ QCOMPARE(pos, QPointF(200 * scale.width(),300 * scale.height()));
pos = obj->pointAt(.25);
- QCOMPARE(pos.toPoint(), QPoint(400,175)); //fuzzy compare
+ QCOMPARE(pos.toPoint(), QPoint(400 * scale.width(),175 * scale.height())); //fuzzy compare
pos = obj->pointAt(.75);
- QCOMPARE(pos.toPoint(), QPoint(800,425)); //fuzzy compare
+ QCOMPARE(pos.toPoint(), QPoint(800 * scale.width(),425 * scale.height())); //fuzzy compare
pos = obj->pointAt(1);
- QCOMPARE(pos, QPointF(1000,300));
+ QCOMPARE(pos, QPointF(1000 * scale.width(),300 * scale.height()));
}
-void tst_QuickPath::line()
+void tst_QuickPath::svg()
+{
+ svg(QSizeF(1,1));
+ svg(QSizeF(5,3));
+}
+
+void tst_QuickPath::line(QSizeF scale)
{
QQmlEngine engine;
QQmlComponent c1(&engine);
@@ -234,6 +309,8 @@ void tst_QuickPath::line()
QScopedPointer<QObject> o1(c1.create());
QQuickPath *path1 = qobject_cast<QQuickPath *>(o1.data());
QVERIFY(path1);
+ if (scale != QSizeF(1,1))
+ path1->setProperty("scale", scale);
QQmlComponent c2(&engine);
c2.setData(
@@ -246,6 +323,8 @@ void tst_QuickPath::line()
QScopedPointer<QObject> o2(c2.create());
QQuickPath *path2 = qobject_cast<QQuickPath *>(o2.data());
QVERIFY(path2);
+ if (scale != QSizeF(1,1))
+ path2->setProperty("scale", scale);
for (int i = 0; i < 167; ++i) {
qreal t = i / 167.0;
@@ -258,6 +337,11 @@ void tst_QuickPath::line()
}
}
+void tst_QuickPath::line()
+{
+ line(QSizeF(1,1));
+ line(QSizeF(7.23,7.23));
+}
QTEST_MAIN(tst_QuickPath)
diff --git a/tests/auto/quick/qquickshape/qquickshape.pro b/tests/auto/quick/qquickshape/qquickshape.pro
index a0e5c002e0..3cf79426c5 100644
--- a/tests/auto/quick/qquickshape/qquickshape.pro
+++ b/tests/auto/quick/qquickshape/qquickshape.pro
@@ -8,6 +8,7 @@ include (../../shared/util.pri)
include (../shared/util.pri)
TESTDATA = data/*
+DISTFILES = data/*
QT += core-private gui-private qml-private quick-private testlib quickshapes-private
qtHaveModule(widgets): QT += widgets
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
index 61fb260612..eb98f849f8 100644
--- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -66,7 +66,7 @@ tst_QQuickShape::tst_QQuickShape()
const char *uri = "tst_qquickpathitem";
qmlRegisterType<QQuickShape>(uri, 1, 0, "Shape");
- qmlRegisterType<QQuickShapePath>(uri, 1, 0, "ShapePath");
+ qmlRegisterType<QQuickShapePath, 14>(uri, 1, 0, "ShapePath");
qmlRegisterUncreatableType<QQuickShapeGradient>(uri, 1, 0, "ShapeGradient", QQuickShapeGradient::tr("ShapeGradient is an abstract base class"));
qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "LinearGradient");
qmlRegisterType<QQuickShapeRadialGradient>(uri, 1, 0, "RadialGradient");
diff --git a/tests/manual/scalablepath/ShapeTestScale.qml b/tests/manual/scalablepath/ShapeTestScale.qml
new file mode 100644
index 0000000000..097ecf3a93
--- /dev/null
+++ b/tests/manual/scalablepath/ShapeTestScale.qml
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import QtQuick.Shapes 1.14
+
+Rectangle {
+ id: i
+ width: parent.width * 0.5
+ height: parent.height * 0.5
+ anchors.centerIn: parent
+ color: "transparent"
+ border.color: "red"
+
+ Shape {
+ id: pathLineMove
+ vendorExtensionsEnabled: false
+ anchors {
+ left: parent.left
+ top: parent.top
+ bottom: parent.verticalCenter
+ right: parent.horizontalCenter
+ }
+
+ visible: true
+
+ ShapePath {
+ id: c_sp1
+ strokeWidth: -1
+ fillColor: Qt.rgba(1,0,1,1.0)
+ scale: Qt.size(pathLineMove.width - 1, pathLineMove.height - 1)
+
+ startX: 0.5;
+ startY: 1
+
+ PathLine {
+ x: 0
+ y: 1
+ }
+ PathLine {
+ x: 0.5
+ y: 0
+ }
+ PathLine {
+ x: 1
+ y: 1
+ }
+ PathLine {
+ x: c_sp1.startX
+ y: c_sp1.startY
+ }
+
+ // Inner shape
+ PathMove {
+ x: 0.5
+ y: 0.25
+ }
+ PathLine {
+ x: 0.8
+ y: 0.8
+ }
+ PathLine {
+ x: 0.2
+ y: 0.8
+ }
+ PathLine {
+ x: 0.5
+ y: 0.25
+ }
+ }
+ }
+ Shape {
+ id: pathCurveArcQuad
+ vendorExtensionsEnabled: false
+ anchors {
+ left: parent.horizontalCenter
+ top: parent.top
+ bottom: parent.verticalCenter
+ right: parent.right
+ }
+
+ visible: true
+
+ ShapePath {
+ strokeWidth: 1
+ fillColor: "transparent"
+ strokeColor: "goldenrod"
+ scale: Qt.size(pathCurveArcQuad.width - 1, pathCurveArcQuad.height - 1)
+
+ startX: 0/400; startY: 100/400
+
+ PathCurve { x: 75/400; y: 75/400 }
+ PathCurve { x: 200/400; y: 150/400 }
+ PathCurve { x: 325/400; y: 25/400 }
+ PathCurve { x: 400/400; y: 100/400 }
+ PathMove { x: 0.5; y: 0 }
+ PathArc {
+ x: 0; y: 100 / 200
+ radiusX: 100 / 200; radiusY: 100 / 200
+ useLargeArc: true
+ }
+ PathMove { x: 0; y: 0.5 }
+ PathQuad { x: 1; y: 0.5; controlX: 0.5; controlY: 1 }
+ }
+ }
+
+
+ Shape {
+ id: pathCubicAngleArc
+ vendorExtensionsEnabled: false
+ anchors {
+ left: parent.left
+ top: parent.verticalCenter
+ bottom: parent.bottom
+ right: parent.horizontalCenter
+ }
+
+ visible: true
+
+ ShapePath {
+ strokeWidth: 1
+ fillColor: "transparent"
+ strokeColor: "deepskyblue"
+ scale: Qt.size(pathCubicAngleArc.width - 1, pathCubicAngleArc.height - 1)
+
+ startX: 20/200; startY: 0
+
+ PathCubic {
+ x: 180/200; y: 0
+ control1X: -10/200; control1Y: 90/200
+ control2X: 210/200; control2Y: 90/200
+ }
+
+ PathAngleArc {
+ centerX: 0.5; centerY: 0.5
+ radiusX: 0.45; radiusY: 0.45
+ startAngle: -180
+ sweepAngle: 234
+ moveToStart: true
+ }
+ }
+ }
+ Shape {
+ id: pathSvg
+ vendorExtensionsEnabled: false
+ anchors {
+ left: parent.horizontalCenter
+ top: parent.verticalCenter
+ bottom: parent.bottom
+ right: parent.right
+ }
+
+ visible: true
+
+ ShapePath {
+ strokeWidth: 5
+ fillColor: "transparent"
+ strokeColor: "coral"
+ scale: Qt.size((pathSvg.width - 1), (pathSvg.height - 1))
+ startX: .25; startY: .25
+ PathSvg { path: "L .75 .25 L .5 .75 z" }
+ }
+
+ ShapePath {
+ strokeWidth: 1
+ fillColor: "transparent"
+ strokeColor: "black"
+ scale: Qt.size((pathSvg.width - 1) / 200, (pathSvg.height - 1) / 200)
+ startX: 50; startY: 50
+ PathSvg { path: "L 150 50 L 100 150 z" }
+ }
+
+ ShapePath {
+ strokeColor: "red"
+ strokeWidth: 4
+ fillColor: "transparent"
+ scale: Qt.size((pathSvg.width - 1) / 500, (pathSvg.height - 1) / 500)
+ PathSvg {
+ path: "m 325.03711,0.5
+ c -26.61408,6.4494547 -49.95197,2.1018066 -76.21132,1.0771669
+ -22.26577,7.6817151 -47.96405,9.3627181 -65.67832,25.8497861
+ -15.74718,12.80008 -41.1564,19.605644 -45.74903,40.600391
+ -12.46933,17.76181 -25.36105,35.720146 -29.20117,57.999996
+ -18.709864,3.10961 -16.347355,30.83801 -22.385143,46.675
+ -6.848711,11.2677 11.07278,24.69174 -8.514666,27.97383
+ -10.266901,5.61543 -12.859313,28.96588 -13.732346,5.78143
+ 0.940083,-11.53398 -13.486195,-38.30626 -16.81701,-34.20231
+ 14.608079,7.8234 21.299281,50.52979 11.380052,48.14418
+ -3.406456,-15.12428 -26.181106,-38.29457 -31.849471,-35.62945
+ 16.851912,6.41472 35.569884,31.75215 28.172486,47.93115
+ -7.906485,-15.42757 -37.758959,-35.53783 -44.275447,-31.28685
+ 18.975831,1.7428 37.986009,20.68109 42.87115,37.14427 C
+ 42.279655,225.774 9.879724,213.57795 4.7080253,219.04989
+ 20.780803,212.57418 55.055919,239.88547 49.602579,241.25683
+ 38.186641,230.40078 6.6930104,222.77983 2.5752529,228.41774 c
+ 13.6045481,-8.33065 49.4437901,14.89041 43.5525671,14.2358
+ -9.759981,-7.96123 -43.5842921,7.36937 -17.554974,-1.20248
+ 9.464499,-3.73452 40.555672,12.80659 16.398749,5.14121
+ -9.1987,-7.28225 -39.0013156,3.37352 -14.121965,-2.12828
+ 13.244874,-0.0206 35.758428,14.62706 10.562447,6.42228
+ -10.780465,-8.4873 -47.8282254,11.10651 -21.027329,-0.003
+ 11.640859,-4.82877 52.615601,10.74471 24.234828,8.2659
+ -10.695834,-7.03902 -42.9384162,8.93905 -34.227854,5.58373
+ 9.077539,-8.56443 49.068801,-5.28097 43.06838,0.45546
+ -10.900893,-0.7118 -27.449619,17.27258 -10.00187,3.46526
+ 15.705191,-9.18198 18.344231,9.31645 1.10807,8.73907
+ -9.908444,1.77856 -21.108189,20.66671 -7.974821,4.92019
+ 15.750746,-14.10374 34.01348,2.07267 9.796961,8.69337
+ -8.17128,5.49929 -12.642664,19.13654 -3.994573,4.19708
+ 9.044753,-8.7077 23.850399,-13.64552 21.404959,4.02329
+ 12.509737,17.12562 51.158782,11.0442 45.106112,43.34009
+ -0.65006,10.05318 -3.79228,13.95389 1.62128,14.30064
+ -4.30913,8.82737 -14.652714,37.9591 2.92144,17.46024
+ 7.37972,-3.68333 -7.62399,16.24161 -7.98007,23.83761
+ -9.336865,18.77418 19.74873,-18.55943 6.62229,5.46195
+ 5.46464,-3.7389 36.23886,-19.41901 14.78167,0.58987
+ -8.59505,4.55644 29.29441,-2.99423 8.95489,6.47134 -9.22562,5.54437
+ -24.09765,26.79976 -11.73274,22.20385 -0.81685,5.4936
+ -1.58629,21.47626 2.34158,9.14886 1.61237,14.67029
+ -2.38384,25.22225 12.26908,15.1741 -4.40761,8.01039
+ -8.23679,36.91214 5.12235,17.92578 1.53454,2.99551 9.37569,3.1726
+ 7.15304,14.93579 3.51234,-11.31873 18.4607,-29.83809
+ 12.36869,-6.48005 -0.22629,16.26174 5.44303,-7.24791
+ 6.56926,10.49819 12.45412,28.9931 3.40908,-41.89883
+ 17.52051,-9.19238 3.23093,11.1924 6.53006,29.46941 7.55984,5.1249
+ 15.37236,-19.52583 4.09776,20.07416 12.64063,1.48215
+ 18.11247,-24.55068 -8.92586,38.39355 6.73828,6.62225
+ 4.55353,-6.91007 15.35028,-38.88977 12.55806,-13.78666
+ 1.05309,27.02664 11.54743,-24.40259 12.40657,6.86306
+ -1.72561,13.28253 11.85393,-24.15909 13.85568,-1.38002
+ 3.12455,8.33539 8.76536,26.46432 8.73882,5.09231 3.57025,-10.37352
+ -16.025,-37.75672 0.20707,-22.5788 -1.2458,-14.17213
+ -2.38918,-16.90145 10.85489,-6.71468 -16.57629,-17.22152
+ 0.19706,-26.08949 5.7751,-19.14889 -14.91681,-16.1674
+ 19.74174,7.19334 2.31875,-9.86869 -4.32508,-15.23278
+ 27.25228,29.12341 20.27514,18.81172 -11.97527,-18.92603
+ -17.96305,-45.80333 11.70099,-51.52566 17.19069,-9.57351
+ 31.17452,21.93154 38.50541,1.56304 16.26048,-4.6633
+ 22.3749,38.26516 24.86349,9.11316 5.94153,-9.9731 30.14313,6.97379
+ 36.34294,4.75012 7.07435,18.27732 8.06778,14.78971 11.04264,3.86016
+ 2.73754,-15.85945 28.7269,10.06391 28.09146,25.96561 3.00672,2.4754
+ 6.55025,-22.10264 11.23552,-14.43872 2.84155,-11.4823
+ -3.28976,-27.88574 4.24895,-25.5189 -0.61494,-11.53957
+ 22.83611,0.11011 10.64648,-15.28756 -6.5587,-21.38598
+ 9.32959,-3.0159 13.5107,-4.69375 -1.38592,-16.74533
+ -8.66673,-31.83316 -1.90087,-41.0875 2.39623,-15.14303
+ -12.50533,-44.45478 -4.70573,-48.49375 15.08472,3.42779
+ -20.39159,-42.17451 -1.69776,-40.85728 24.07272,21.63552
+ -3.65989,-30.10299 2.27233,-33.17152 16.90643,17.53071
+ -12.7383,-38.42821 6.79531,-21.57013 -4.50946,-21.08135
+ -2.53357,-37.43561 -15.5535,-55.59527 -11.0035,-12.40086
+ -1.87775,-7.12745 1.34831,-8.11755 C 468.27562,118.9774
+ 451.40746,102.656 430.98897,92.119168 439.06192,78.203836
+ 455.88012,60.123881 457.38638,40.337815 463.2373,23.183067
+ 450.82861,4.7342783 435.04883,22.626367 409.5188,28.206712
+ 386.3569,24.131269 365.63904,8.0954152 352.788,2.8857182
+ 338.88892,0.40735091 325.03711,0.5 Z m -219.0625,357.04297
+ -0.97656,0.88476 z"
+ }
+ }
+ }
+}
diff --git a/tests/manual/scalablepath/main.cpp b/tests/manual/scalablepath/main.cpp
new file mode 100644
index 0000000000..d35c590020
--- /dev/null
+++ b/tests/manual/scalablepath/main.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+ if (engine.rootObjects().isEmpty())
+ return -1;
+
+ return app.exec();
+}
diff --git a/tests/manual/scalablepath/main.qml b/tests/manual/scalablepath/main.qml
new file mode 100644
index 0000000000..e549a753d7
--- /dev/null
+++ b/tests/manual/scalablepath/main.qml
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import QtQuick.Window 2.14
+
+Window {
+ visible: true
+ width: 512
+ height: 512
+ color: "black"
+
+ ShapeTestScale {
+ anchors.centerIn: parent
+
+ }
+}
diff --git a/tests/manual/scalablepath/qml.qrc b/tests/manual/scalablepath/qml.qrc
new file mode 100644
index 0000000000..a7a14beed4
--- /dev/null
+++ b/tests/manual/scalablepath/qml.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>ShapeTestScale.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/scalablepath/scalablepath.pro b/tests/manual/scalablepath/scalablepath.pro
new file mode 100644
index 0000000000..b95ce1de44
--- /dev/null
+++ b/tests/manual/scalablepath/scalablepath.pro
@@ -0,0 +1,5 @@
+TEMPLATE = app
+QT += quick qml
+SOURCES += main.cpp
+RESOURCES += qml.qrc
+CONFIG += c++11