aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/quick/examples/tst_examples.cpp2
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem1.qml5
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem2.qml7
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem3.pngbin0 -> 5214 bytes
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem3.qml33
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem4.pngbin0 -> 5713 bytes
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem4.qml56
-rw-r--r--tests/auto/quick/qquickshape/qquickshape.pro35
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp250
-rw-r--r--tests/auto/quick/quick.pro1
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_arc.qml112
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_arc_fill.qml112
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_cubic.qml35
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_linear_gradient.qml33
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_lines.qml92
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_quad.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_spread.qml35
-rw-r--r--tests/manual/shapestest/main.cpp69
-rw-r--r--tests/manual/shapestest/shapestest.pro6
-rw-r--r--tests/manual/shapestest/shapestest.qml396
-rw-r--r--tests/manual/shapestest/shapestest.qrc5
21 files changed, 1318 insertions, 0 deletions
diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp
index b6742b9efe..d35a2e971a 100644
--- a/tests/auto/quick/examples/tst_examples.cpp
+++ b/tests/auto/quick/examples/tst_examples.cpp
@@ -86,6 +86,8 @@ tst_examples::tst_examples()
excludedDirs << "snippets/qml/visualdatamodel_rootindex";
excludedDirs << "snippets/qml/qtbinding";
excludedDirs << "snippets/qml/imports";
+ excludedFiles << "examples/quick/shapes/content/pathitem.qml"; // relies on resources
+ excludedFiles << "examples/quick/shapes/content/pathiteminteract.qml"; // relies on resources
#ifdef QT_NO_XMLPATTERNS
excludedDirs << "demos/twitter";
diff --git a/tests/auto/quick/qquickshape/data/pathitem1.qml b/tests/auto/quick/qquickshape/data/pathitem1.qml
new file mode 100644
index 0000000000..29ca67b0bb
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem1.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Shape {
+}
diff --git a/tests/auto/quick/qquickshape/data/pathitem2.qml b/tests/auto/quick/qquickshape/data/pathitem2.qml
new file mode 100644
index 0000000000..a255a37af6
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem2.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Shape {
+ ShapePath { }
+ ShapePath { }
+}
diff --git a/tests/auto/quick/qquickshape/data/pathitem3.png b/tests/auto/quick/qquickshape/data/pathitem3.png
new file mode 100644
index 0000000000..a8b4483c96
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem3.png
Binary files differ
diff --git a/tests/auto/quick/qquickshape/data/pathitem3.qml b/tests/auto/quick/qquickshape/data/pathitem3.qml
new file mode 100644
index 0000000000..8328f2fc33
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem3.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Item {
+ width: 200
+ height: 150
+
+ Shape {
+ vendorExtensionsEnabled: false
+ objectName: "pathItem"
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: LinearGradient {
+ x1: 20; y1: 20
+ x2: 180; y2: 130
+ GradientStop { position: 0; color: "blue" }
+ GradientStop { position: 0.2; color: "green" }
+ GradientStop { position: 0.4; color: "red" }
+ GradientStop { position: 0.6; color: "yellow" }
+ GradientStop { position: 1; color: "cyan" }
+ }
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 20; startY: 20
+ PathLine { x: 180; y: 130 }
+ PathLine { x: 20; y: 130 }
+ PathLine { x: 20; y: 20 }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshape/data/pathitem4.png b/tests/auto/quick/qquickshape/data/pathitem4.png
new file mode 100644
index 0000000000..3a988ba249
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem4.png
Binary files differ
diff --git a/tests/auto/quick/qquickshape/data/pathitem4.qml b/tests/auto/quick/qquickshape/data/pathitem4.qml
new file mode 100644
index 0000000000..635113416f
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem4.qml
@@ -0,0 +1,56 @@
+import QtQuick 2.9
+import tst_qquickpathitem 1.0
+
+Item {
+ width: 200
+ height: 150
+
+ Shape {
+ vendorExtensionsEnabled: false
+ objectName: "pathItem"
+ anchors.fill: parent
+
+ ShapePath {
+ strokeColor: "red"
+ fillColor: "green"
+ startX: 40; startY: 30
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 160; y: 30; controlX: 200; controlY: 80 }
+ }
+
+ ShapePath {
+ strokeWidth: 10
+ fillColor: "transparent"
+ strokeColor: "blue"
+ startX: 40; startY: 30
+ PathCubic { x: 50; y: 80; control1X: 0; control1Y: 80; control2X: 100; control2Y: 100 }
+ }
+
+ ShapePath {
+ fillGradient: LinearGradient {
+ y2: 150
+ GradientStop { position: 0; color: "yellow" }
+ GradientStop { position: 1; color: "green" }
+ }
+
+ startX: 10; startY: 100
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 25; radiusY: 25
+ }
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 25; radiusY: 35
+ }
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 25; radiusY: 60
+ }
+ PathArc {
+ relativeX: 50; y: 100
+ radiusX: 50; radiusY: 120
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshape/qquickshape.pro b/tests/auto/quick/qquickshape/qquickshape.pro
new file mode 100644
index 0000000000..29c3502b86
--- /dev/null
+++ b/tests/auto/quick/qquickshape/qquickshape.pro
@@ -0,0 +1,35 @@
+CONFIG += testcase
+TARGET = tst_qquickshape
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qquickshape.cpp
+
+include (../../shared/util.pri)
+include (../shared/util.pri)
+
+TESTDATA = data/*
+
+HEADERS += \
+ ../../../../src/imports/shapes/qquickshape_p.h \
+ ../../../../src/imports/shapes/qquickshape_p_p.h \
+ ../../../../src/imports/shapes/qquickshapegenericrenderer_p.h \
+ ../../../../src/imports/shapes/qquickshapesoftwarerenderer_p.h
+
+SOURCES += \
+ ../../../../src/imports/shapes/qquickshape.cpp \
+ ../../../../src/imports/shapes/qquickshapegenericrenderer.cpp \
+ ../../../../src/imports/shapes/qquickshapesoftwarerenderer.cpp
+
+qtConfig(opengl) {
+ HEADERS += \
+ ../../../../src/imports/shapes/qquicknvprfunctions_p.h \
+ ../../../../src/imports/shapes/qquicknvprfunctions_p_p.h \
+ ../../../../src/imports/shapes/qquickshapenvprrenderer_p.h
+
+ SOURCES += \
+ ../../../../src/imports/shapes/qquicknvprfunctions.cpp \
+ ../../../../src/imports/shapes/qquickshapenvprrenderer.cpp
+}
+
+QT += core-private gui-private qml-private quick-private testlib
+qtHaveModule(widgets): QT += widgets
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
new file mode 100644
index 0000000000..dcc79e6599
--- /dev/null
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 <QtTest/QtTest>
+#include <QtQuick/qquickview.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlexpression.h>
+#include <QtQml/qqmlincubator.h>
+#include "../../../../src/imports/shapes/qquickshape_p.h"
+
+#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
+#include "../shared/visualtestutil.h"
+
+using namespace QQuickViewTestUtil;
+using namespace QQuickVisualTestUtil;
+
+class tst_QQuickShape : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_QQuickShape();
+
+private slots:
+ void initValues();
+ void vpInitValues();
+ void basicShape();
+ void changeSignals();
+ void render();
+ void renderWithMultipleSp();
+};
+
+tst_QQuickShape::tst_QQuickShape()
+{
+ // Force the software backend to get reliable rendering results regardless of the hw and drivers.
+ QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);
+
+ const char *uri = "tst_qquickpathitem";
+ qmlRegisterType<QQuickShape>(uri, 1, 0, "Shape");
+ qmlRegisterType<QQuickShapePath>(uri, 1, 0, "ShapePath");
+ qmlRegisterUncreatableType<QQuickShapeGradient>(uri, 1, 0, "ShapeGradient", QQuickShapeGradient::tr("ShapeGradient is an abstract base class"));
+ qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "LinearGradient");
+}
+
+void tst_QQuickShape::initValues()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("pathitem1.qml"));
+ QQuickShape *obj = qobject_cast<QQuickShape *>(c.create());
+
+ QVERIFY(obj != nullptr);
+ QVERIFY(obj->rendererType() == QQuickShape::UnknownRenderer);
+ QVERIFY(!obj->asynchronous());
+ QVERIFY(obj->vendorExtensionsEnabled());
+ QVERIFY(obj->status() == QQuickShape::Null);
+ auto vps = obj->data();
+ QVERIFY(vps.count(&vps) == 0);
+
+ delete obj;
+}
+
+void tst_QQuickShape::vpInitValues()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("pathitem2.qml"));
+ QQuickShape *obj = qobject_cast<QQuickShape *>(c.create());
+
+ QVERIFY(obj != nullptr);
+ QVERIFY(obj->rendererType() == QQuickShape::UnknownRenderer);
+ QVERIFY(!obj->asynchronous());
+ QVERIFY(obj->vendorExtensionsEnabled());
+ QVERIFY(obj->status() == QQuickShape::Null);
+ auto vps = obj->data();
+ QVERIFY(vps.count(&vps) == 2);
+
+ QQuickShapePath *vp = qobject_cast<QQuickShapePath *>(vps.at(&vps, 0));
+ QVERIFY(vp != nullptr);
+ QQmlListReference pathList(vp, "pathElements");
+ QCOMPARE(pathList.count(), 0);
+ QCOMPARE(vp->strokeColor(), QColor(Qt::white));
+ QCOMPARE(vp->strokeWidth(), 1.0f);
+ QCOMPARE(vp->fillColor(), QColor(Qt::white));
+ QCOMPARE(vp->fillRule(), QQuickShapePath::OddEvenFill);
+ QCOMPARE(vp->joinStyle(), QQuickShapePath::BevelJoin);
+ QCOMPARE(vp->miterLimit(), 2);
+ QCOMPARE(vp->capStyle(), QQuickShapePath::SquareCap);
+ QCOMPARE(vp->strokeStyle(), QQuickShapePath::SolidLine);
+ QCOMPARE(vp->dashOffset(), 0.0f);
+ QCOMPARE(vp->dashPattern(), QVector<qreal>() << 4 << 2);
+ QVERIFY(!vp->fillGradient());
+
+ delete obj;
+}
+
+void tst_QQuickShape::basicShape()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem3.qml"));
+ qApp->processEvents();
+
+ QQuickShape *obj = findItem<QQuickShape>(window->rootObject(), "pathItem");
+ QVERIFY(obj != nullptr);
+ QQmlListReference list(obj, "data");
+ QCOMPARE(list.count(), 1);
+ QQuickShapePath *vp = qobject_cast<QQuickShapePath *>(list.at(0));
+ QVERIFY(vp != nullptr);
+ QCOMPARE(vp->strokeWidth(), 4.0f);
+ QVERIFY(vp->fillGradient() != nullptr);
+ QCOMPARE(vp->strokeStyle(), QQuickShapePath::DashLine);
+
+ vp->setStrokeWidth(5.0f);
+ QCOMPARE(vp->strokeWidth(), 5.0f);
+
+ QQuickShapeLinearGradient *lgrad = qobject_cast<QQuickShapeLinearGradient *>(vp->fillGradient());
+ QVERIFY(lgrad != nullptr);
+ QCOMPARE(lgrad->spread(), QQuickShapeGradient::PadSpread);
+ QCOMPARE(lgrad->x1(), 20.0f);
+ QQmlListReference stopList(lgrad, "stops");
+ QCOMPARE(stopList.count(), 5);
+ QVERIFY(stopList.at(2) != nullptr);
+
+ QQuickPath *path = vp;
+ QCOMPARE(path->startX(), 20.0f);
+ QQmlListReference pathList(path, "pathElements");
+ QCOMPARE(pathList.count(), 3);
+}
+
+void tst_QQuickShape::changeSignals()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem3.qml"));
+ qApp->processEvents();
+
+ QQuickShape *obj = findItem<QQuickShape>(window->rootObject(), "pathItem");
+ QVERIFY(obj != nullptr);
+
+ QSignalSpy asyncPropSpy(obj, SIGNAL(asynchronousChanged()));
+ obj->setAsynchronous(true);
+ obj->setAsynchronous(false);
+ QCOMPARE(asyncPropSpy.count(), 2);
+
+ QQmlListReference list(obj, "data");
+ QQuickShapePath *vp = qobject_cast<QQuickShapePath *>(list.at(0));
+ QVERIFY(vp != nullptr);
+
+ // Verify that VisualPath property changes emit shapePathChanged().
+ QSignalSpy vpChangeSpy(vp, SIGNAL(shapePathChanged()));
+ QSignalSpy strokeColorPropSpy(vp, SIGNAL(strokeColorChanged()));
+ vp->setStrokeColor(Qt::blue);
+ vp->setStrokeWidth(1.0f);
+ QQuickShapeGradient *g = vp->fillGradient();
+ vp->setFillGradient(nullptr);
+ vp->setFillColor(Qt::yellow);
+ vp->setFillRule(QQuickShapePath::WindingFill);
+ vp->setJoinStyle(QQuickShapePath::MiterJoin);
+ vp->setMiterLimit(5);
+ vp->setCapStyle(QQuickShapePath::RoundCap);
+ vp->setDashOffset(10);
+ vp->setDashPattern(QVector<qreal>() << 1 << 2 << 3 << 4);
+ QCOMPARE(strokeColorPropSpy.count(), 1);
+ QCOMPARE(vpChangeSpy.count(), 10);
+
+ // Verify that property changes from Path and its elements bubble up and result in shapePathChanged().
+ QQuickPath *path = vp;
+ path->setStartX(30);
+ QCOMPARE(vpChangeSpy.count(), 11);
+ QQmlListReference pathList(path, "pathElements");
+ qobject_cast<QQuickPathLine *>(pathList.at(1))->setY(200);
+ QCOMPARE(vpChangeSpy.count(), 12);
+
+ // Verify that property changes from the gradient bubble up and result in shapePathChanged().
+ vp->setFillGradient(g);
+ QCOMPARE(vpChangeSpy.count(), 13);
+ QQuickShapeLinearGradient *lgrad = qobject_cast<QQuickShapeLinearGradient *>(g);
+ lgrad->setX2(200);
+ QCOMPARE(vpChangeSpy.count(), 14);
+ QQmlListReference stopList(lgrad, "stops");
+ QCOMPARE(stopList.count(), 5);
+ qobject_cast<QQuickGradientStop *>(stopList.at(1))->setPosition(0.3);
+ QCOMPARE(vpChangeSpy.count(), 15);
+ qobject_cast<QQuickGradientStop *>(stopList.at(1))->setColor(Qt::black);
+ QCOMPARE(vpChangeSpy.count(), 16);
+}
+
+void tst_QQuickShape::render()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem3.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("pathitem3.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QVERIFY(QQuickVisualTestUtil::compareImages(img.convertToFormat(refImg.format()), refImg));
+}
+
+void tst_QQuickShape::renderWithMultipleSp()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem4.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("pathitem4.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QVERIFY(QQuickVisualTestUtil::compareImages(img.convertToFormat(refImg.format()), refImg));
+}
+
+QTEST_MAIN(tst_QQuickShape)
+
+#include "tst_qquickshape.moc"
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 00be8240e5..2ff606488c 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -69,6 +69,7 @@ QUICKTESTS = \
qquickmousearea \
qquickmultipointtoucharea \
qquickpainteditem \
+ qquickshape \
qquickpathview \
qquickpincharea \
qquickpositioners \
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_arc.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_arc.qml
new file mode 100644
index 0000000000..0b2396012e
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_arc.qml
@@ -0,0 +1,112 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 4; startY: 4
+ PathArc {
+ id: arc
+ x: 96; y: 96
+ radiusX: 100; radiusY: 100
+ direction: model.index === 0 ? PathArc.Clockwise : PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 100
+ PathArc {
+ x: 100; y: 150
+ radiusX: 50; radiusY: 50
+ useLargeArc: model.index === 1
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 150
+ PathArc {
+ x: 150; y: 150
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ }
+ }
+ }
+ }
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: model.index === 0 ? "red" : "blue"
+
+ startX: 50; startY: 150
+ PathArc {
+ x: 150; y: 150
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ direction: PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_arc_fill.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_arc_fill.qml
new file mode 100644
index 0000000000..fefc2ec3eb
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_arc_fill.qml
@@ -0,0 +1,112 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "lightBlue"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 4; startY: 4
+ PathArc {
+ id: arc
+ x: 96; y: 96
+ radiusX: 100; radiusY: 100
+ direction: model.index === 0 ? PathArc.Clockwise : PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "green"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 100
+ PathArc {
+ x: 100; y: 150
+ radiusX: 50; radiusY: 50
+ useLargeArc: model.index === 1
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ width: 200
+ height: 100
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "gray"
+ strokeColor: model.index === 0 ? "red" : "blue"
+ strokeStyle: ShapePath.DashLine
+ strokeWidth: 4
+
+ startX: 50; startY: 150
+ PathArc {
+ x: 150; y: 150
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ }
+ }
+ }
+ }
+
+ Repeater {
+ model: 2
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ fillColor: "lightGray"
+ strokeColor: model.index === 0 ? "red" : "blue"
+
+ startX: 50; startY: 150
+ PathArc {
+ x: 150; y: 150
+ radiusX: 50; radiusY: 20
+ xAxisRotation: model.index === 0 ? 0 : 45
+ direction: PathArc.Counterclockwise
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_cubic.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_cubic.qml
new file mode 100644
index 0000000000..1d2f9fd40d
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_cubic.qml
@@ -0,0 +1,35 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Repeater {
+ model: 4
+ Item {
+ width: 200
+ height: 100
+
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ strokeWidth: (model.index + 2) * 2
+ strokeColor: "black"
+ fillColor: "lightBlue"
+
+ startX: 50; startY: 100
+ PathCubic {
+ x: 150; y: 100
+ control1X: model.index * 10; control1Y: model.index * 5
+ control2X: model.index * -10; control2Y: model.index * 10
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_linear_gradient.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_linear_gradient.qml
new file mode 100644
index 0000000000..1caaec7781
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_linear_gradient.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Shape {
+ vendorExtensionsEnabled: false
+
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: LinearGradient {
+ x1: 20; y1: 20
+ x2: 180; y2: 130
+ GradientStop { position: 0; color: "blue" }
+ GradientStop { position: 0.2; color: "green" }
+ GradientStop { position: 0.4; color: "red" }
+ GradientStop { position: 0.6; color: "yellow" }
+ GradientStop { position: 1; color: "cyan" }
+ }
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 20; startY: 20
+ PathLine { x: 180; y: 130 }
+ PathLine { x: 20; y: 130 }
+ PathLine { x: 20; y: 20 }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_lines.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_lines.qml
new file mode 100644
index 0000000000..56045cb5ae
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_lines.qml
@@ -0,0 +1,92 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Shape {
+ vendorExtensionsEnabled: false
+
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 1
+ strokeColor: "red"
+ fillColor: "transparent"
+ PathLine { x: 50; y: 50 }
+ }
+ ShapePath {
+ strokeWidth: 2
+ strokeColor: "blue"
+ fillColor: "transparent"
+ startX: 20
+ PathLine { x: 70; y: 50 }
+ }
+ ShapePath {
+ strokeWidth: 3
+ strokeColor: "green"
+ fillColor: "transparent"
+ startX: 40
+ PathLine { x: 90; y: 50 }
+ }
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "yellow"
+ fillColor: "transparent"
+ startX: 60
+ PathLine { x: 110; y: 50 }
+ }
+ ShapePath {
+ strokeWidth: 5
+ strokeColor: "black"
+ fillColor: "transparent"
+ strokeStyle: ShapePath.DashLine
+ startX: 80
+ PathLine { x: 130; y: 50 }
+ }
+
+ ShapePath {
+ strokeWidth: 20
+ strokeColor: "gray"
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ startX: 120; startY: 20
+ PathLine { x: 200; y: 100 }
+ }
+
+ ShapePath {
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ joinStyle: ShapePath.BevelJoin
+ startX: 20
+ startY: 100
+ PathLine { x: 120; y: 200 }
+ PathLine { x: 50; y: 200 }
+ }
+ ShapePath {
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ joinStyle: ShapePath.MiterJoin
+ startX: 150
+ startY: 100
+ PathLine { x: 250; y: 200 }
+ PathLine { x: 180; y: 200 }
+ }
+ ShapePath {
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ joinStyle: ShapePath.RoundJoin
+ startX: 270
+ startY: 100
+ PathLine { x: 310; y: 200 }
+ PathLine { x: 280; y: 200 }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_quad.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_quad.qml
new file mode 100644
index 0000000000..a4c95f7c15
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_quad.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Repeater {
+ model: 4
+ Item {
+ width: 200
+ height: 100
+
+ Shape {
+ anchors.fill: parent
+ vendorExtensionsEnabled: false
+
+ ShapePath {
+ strokeWidth: (model.index + 2) * 2
+ strokeColor: "black"
+ fillColor: "lightBlue"
+
+ startX: 50; startY: 100
+ PathQuad {
+ x: 150; y: 100
+ controlX: model.index * 10; controlY: model.index * 5
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_spread.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_spread.qml
new file mode 100644
index 0000000000..f310f08773
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_spread.qml
@@ -0,0 +1,35 @@
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Column {
+ Repeater {
+ model: 3
+ Shape {
+ vendorExtensionsEnabled: false
+ width: 200
+ height: 150
+ ShapePath {
+ strokeColor: "transparent"
+
+ fillGradient: LinearGradient {
+ id: grad
+ y1: 50; y2: 80
+ spread: model.index === 0 ? ShapeGradient.PadSpread : (model.index === 1 ? ShapeGradient.RepeatSpread : ShapeGradient.ReflectSpread)
+ GradientStop { position: 0; color: "black" }
+ GradientStop { position: 1; color: "red" }
+ }
+
+ startX: 10; startY: 10
+ PathLine { relativeX: 180; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: 100 }
+ PathLine { relativeX: -180; relativeY: 0 }
+ PathLine { relativeX: 0; relativeY: -100 }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/shapestest/main.cpp b/tests/manual/shapestest/main.cpp
new file mode 100644
index 0000000000..b9b93fbf9f
--- /dev/null
+++ b/tests/manual/shapestest/main.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QSurfaceFormat>
+#include <QQuickView>
+#include <QQmlEngine>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ QSurfaceFormat fmt;
+ fmt.setDepthBufferSize(24);
+ fmt.setStencilBufferSize(8);
+ if (app.arguments().contains(QStringLiteral("--multisample")))
+ fmt.setSamples(4);
+ if (app.arguments().contains(QStringLiteral("--coreprofile"))) {
+ fmt.setVersion(4, 3);
+ fmt.setProfile(QSurfaceFormat::CoreProfile);
+ }
+ view.setFormat(fmt);
+
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.resize(1024, 768);
+ view.setSource(QUrl("qrc:/shapestest/shapestest.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/shapestest/shapestest.pro b/tests/manual/shapestest/shapestest.pro
new file mode 100644
index 0000000000..1776175134
--- /dev/null
+++ b/tests/manual/shapestest/shapestest.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+
+QT += quick qml
+SOURCES += main.cpp
+RESOURCES += shapestest.qrc
+OTHER_FILES += shapestest.qml
diff --git a/tests/manual/shapestest/shapestest.qml b/tests/manual/shapestest/shapestest.qml
new file mode 100644
index 0000000000..df53f088ae
--- /dev/null
+++ b/tests/manual/shapestest/shapestest.qml
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Shapes 1.0
+
+Rectangle {
+ id: root
+ width: 1024
+ height: 768
+
+ property color col: "lightsteelblue"
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: Qt.tint(root.col, "#20FFFFFF") }
+ GradientStop { position: 0.1; color: Qt.tint(root.col, "#20AAAAAA") }
+ GradientStop { position: 0.9; color: Qt.tint(root.col, "#20666666") }
+ GradientStop { position: 1.0; color: Qt.tint(root.col, "#20000000") }
+ }
+
+ Row {
+ anchors.top: parent.top
+ anchors.centerIn: parent
+ spacing: 20
+
+ Column {
+ spacing: 20
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ id: triangle
+ anchors.fill: parent
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ fillGradient: LinearGradient {
+ x1: 0; y1: 0
+ x2: 200; y2: 100
+ GradientStop { position: 0; color: "blue" }
+ GradientStop { position: 0.2; color: "green" }
+ GradientStop { position: 0.4; color: "red" }
+ GradientStop { position: 0.6; color: "yellow" }
+ GradientStop { position: 1; color: "cyan" }
+ }
+ fillColor: "blue" // ignored with the gradient set
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ PathLine { x: 200; y: 100 }
+ PathLine { x: 0; y: 100 }
+ PathLine { x: 0; y: 0 }
+ }
+ transform: Rotation { origin.x: 100; origin.y: 50; axis { x: 0; y: 1; z: 0 }
+ SequentialAnimation on angle {
+ NumberAnimation { from: 0; to: 75; duration: 2000 }
+ NumberAnimation { from: 75; to: -75; duration: 4000 }
+ NumberAnimation { from: -75; to: 0; duration: 2000 }
+ loops: Animation.Infinite
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ id: someCurve
+ property color sc: "gray"
+ strokeColor: sc
+ property color fc: "yellow"
+ fillColor: fc
+ startX: 20; startY: 10
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 180; y: 10; controlX: 200; controlY: 80 }
+ PathLine { x: 20; y: 10 }
+ // Dynamic changes via property bindings etc. all work but can
+ // be computationally expense with the generic backend for properties
+ // that need retriangulating on every change. Should be cheap with NVPR.
+ NumberAnimation on strokeWidth {
+ from: 1; to: 20; duration: 10000
+ }
+ }
+ }
+ // Changing colors for a solid stroke or fill is simple and
+ // (relatively) cheap. However, changing to/from transparent
+ // stroke/fill color and stroke width 0 are special as these
+ // change the scenegraph node tree (with the generic backend).
+ Timer {
+ interval: 2000
+ running: true
+ repeat: true
+ onTriggered: someCurve.fillColor = (someCurve.fillColor === someCurve.fc ? "transparent" : someCurve.fc)
+ }
+ Timer {
+ interval: 1000
+ running: true
+ repeat: true
+ onTriggered: someCurve.strokeColor = (someCurve.strokeColor === someCurve.sc ? "transparent" : someCurve.sc)
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 300
+ height: 100
+ Shape {
+ id: linesAndMoves
+ anchors.fill: parent
+ ShapePath {
+ strokeColor: "black"
+ startX: 0; startY: 50
+ PathLine { relativeX: 100; y: 50 }
+ PathMove { relativeX: 100; y: 50 }
+ PathLine { relativeX: 100; y: 50 }
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 120
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ id: joinTest
+ strokeColor: "black"
+ strokeWidth: 16
+ fillColor: "transparent"
+ capStyle: ShapePath.RoundCap
+ startX: 30
+ startY: 30
+ PathLine { x: 100; y: 100 }
+ PathLine { x: 30; y: 100 }
+ }
+ }
+ Timer {
+ interval: 1000
+ repeat: true
+ running: true
+ property variant styles: [ ShapePath.BevelJoin, ShapePath.MiterJoin, ShapePath.RoundJoin ]
+ onTriggered: {
+ for (var i = 0; i < styles.length; ++i)
+ if (styles[i] === joinTest.joinStyle) {
+ joinTest.joinStyle = styles[(i + 1) % styles.length];
+ break;
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ id: star
+ strokeColor: "blue"
+ fillColor: "lightGray"
+ strokeWidth: 2
+ PathMove { x: 90; y: 50 }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 1 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 1 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 2 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 2 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 3 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 3 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 4 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 4 * Math.PI) }
+ PathLine { x: 90; y: 50 }
+ }
+ }
+ Timer {
+ interval: 1000
+ onTriggered: star.fillRule = (star.fillRule === ShapePath.OddEvenFill ? ShapePath.WindingFill : ShapePath.OddEvenFill)
+ repeat: true
+ running: true
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "black"
+ fillColor: "transparent"
+ startX: 20; startY: 10
+ PathCubic {
+ id: cb
+ x: 180; y: 10
+ control1X: -10; control1Y: 90; control2Y: 90
+ NumberAnimation on control2X { from: 400; to: 0; duration: 5000; loops: Animation.Infinite }
+ }
+ }
+ }
+ }
+ }
+
+ Column {
+ spacing: 20
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ fillColor: "transparent"
+ strokeColor: "red"
+ strokeWidth: 4
+ startX: 10; startY: 40
+ PathArc {
+ x: 10; y: 60
+ radiusX: 40; radiusY: 40
+ useLargeArc: true
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 200
+ height: 200
+ Rectangle {
+ anchors.centerIn: parent
+ // have a size smaller than 150x150
+ width: 100
+ height: 100
+ // and enable clipping. Normally this goes via scissoring, unless
+ // some transform triggers the stencil-based path. Ensure this via rotation.
+ clip: true
+ NumberAnimation on rotation {
+ from: 0; to: 360; duration: 5000; loops: Animation.Infinite
+ }
+
+ Shape {
+ width: 150
+ height: 150
+
+ ShapePath {
+ fillColor: "blue"
+ strokeColor: "red"
+ strokeWidth: 4
+ startX: 10; startY: 10
+ PathLine { x: 140; y: 140 }
+ PathLine { x: 10; y: 140 }
+ PathLine { x: 10; y: 10 }
+ }
+ }
+ }
+ }
+
+ // stencil clip test #2, something more complicated:
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 150
+ height: 150
+ Rectangle {
+ anchors.centerIn: parent
+ width: 60
+ height: 60
+ clip: true
+ NumberAnimation on rotation {
+ from: 0; to: 360; duration: 5000; loops: Animation.Infinite
+ }
+ Shape {
+ width: 100
+ height: 100
+ ShapePath {
+ id: clippedStar
+ strokeColor: "blue"
+ fillColor: "lightGray"
+ strokeWidth: 2
+ PathMove { x: 90; y: 50 }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 1 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 1 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 2 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 2 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 3 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 3 * Math.PI) }
+ PathLine { x: 50 + 40 * Math.cos(0.8 * 4 * Math.PI); y: 50 + 40 * Math.sin(0.8 * 4 * Math.PI) }
+ PathLine { x: 90; y: 50 }
+ }
+ }
+ Timer {
+ interval: 1000
+ onTriggered: clippedStar.fillRule = (clippedStar.fillRule === ShapePath.OddEvenFill ? ShapePath.WindingFill : ShapePath.OddEvenFill)
+ repeat: true
+ running: true
+ }
+ }
+ }
+
+ Rectangle {
+ border.color: "purple"
+ color: "transparent"
+ width: 100
+ height: 100
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ strokeColor: "red"
+ PathLine { x: 100; y: 100 }
+ }
+ ShapePath {
+ strokeColor: "blue"
+ startX: 100; startY: 0
+ PathLine { x: 0; y: 100 }
+ }
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: stackTestRect
+ SequentialAnimation on opacity {
+ NumberAnimation { from: 0; to: 1; duration: 5000 }
+ PauseAnimation { duration: 2000 }
+ NumberAnimation { from: 1; to: 0; duration: 5000 }
+ PauseAnimation { duration: 2000 }
+ loops: Animation.Infinite
+ id: opAnim
+ }
+ color: "blue"
+ anchors.margins: 10
+ anchors.fill: parent
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: stackTestRect.visible = !stackTestRect.visible
+ }
+}
diff --git a/tests/manual/shapestest/shapestest.qrc b/tests/manual/shapestest/shapestest.qrc
new file mode 100644
index 0000000000..6bfc953997
--- /dev/null
+++ b/tests/manual/shapestest/shapestest.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/shapestest">
+ <file>shapestest.qml</file>
+ </qresource>
+</RCC>