summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@digia.com>2013-05-26 20:31:40 +0200
committerGunnar Sletta <gunnar.sletta@digia.com>2013-05-28 09:29:08 +0200
commit1837bafc23d252fc7a7e9b86618d6e688063b17f (patch)
treef7c03c3e1cb5062b6dad1668770e0aeaaa45c4c6
parentbaaa6d691a1820c80670ee7cfd727fb1c2c7b832 (diff)
Say hello to Qt.labs.shapes 0.1
The shapes plugin provies three element types. 1. TriangleSet - which encapsulates a set of triangles including read/save logic to a very basic textual format. Binary can of course be added later... It also contains a set of path commands and uses Qt's triangulator internally to convert a path into triangles. 2. Polygon - Renders a flat shaded triangle set. 3. MaskedImage - Reads two triangle sets in addition to an image and splits the image into a opaque and blended part, making it possible to greatly reduce the blending needed for drawing large bitmaps which are largely opaque. There is also a maskmaker tool in the tools subdirectory which provides a simple means of generating masks for the MaskedImage Change-Id: Ia00f059fb81872e6ca1dca78baf3073c9581acab Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
-rw-r--r--shapes/shapes.pro2
-rw-r--r--shapes/shapesplugin/qmldir2
-rw-r--r--shapes/shapesplugin/qsgmaskedimage.cpp266
-rw-r--r--shapes/shapesplugin/qsgmaskedimage.h82
-rw-r--r--shapes/shapesplugin/qsgpolygon.cpp140
-rw-r--r--shapes/shapesplugin/qsgpolygon.h82
-rw-r--r--shapes/shapesplugin/qsgtriangleset.cpp302
-rw-r--r--shapes/shapesplugin/qsgtriangleset.h107
-rw-r--r--shapes/shapesplugin/shapesplugin.cpp62
-rw-r--r--shapes/shapesplugin/shapesplugin.pro29
-rw-r--r--shapes/tests/TestMaskedImage.qml77
-rw-r--r--shapes/tests/TestPolygon.qml96
-rw-r--r--shapes/tests/TestVectorPath.qml71
-rw-r--r--shapes/tests/qtlogo.pngbin0 -> 35860 bytes
-rw-r--r--shapes/tests/qtlogo.png.alphamask75
-rw-r--r--shapes/tests/qtlogo.png.opaquemask41
-rw-r--r--shapes/tools/maskmaker/Checkers.qml68
-rw-r--r--shapes/tools/maskmaker/Main.qml330
-rw-r--r--shapes/tools/maskmaker/maskmaker.cpp97
-rw-r--r--shapes/tools/maskmaker/maskmaker.pro9
-rw-r--r--shapes/tools/maskmaker/maskmaker.qrc6
21 files changed, 1944 insertions, 0 deletions
diff --git a/shapes/shapes.pro b/shapes/shapes.pro
new file mode 100644
index 0000000..5da5d4c
--- /dev/null
+++ b/shapes/shapes.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += shapesplugin tools/maskmaker
diff --git a/shapes/shapesplugin/qmldir b/shapes/shapesplugin/qmldir
new file mode 100644
index 0000000..7ee1dd5
--- /dev/null
+++ b/shapes/shapesplugin/qmldir
@@ -0,0 +1,2 @@
+module Qt.labs.shapes
+plugin shapes
diff --git a/shapes/shapesplugin/qsgmaskedimage.cpp b/shapes/shapesplugin/qsgmaskedimage.cpp
new file mode 100644
index 0000000..6309aa3
--- /dev/null
+++ b/shapes/shapesplugin/qsgmaskedimage.cpp
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgmaskedimage.h"
+#include <QtQml/QQmlFile>
+
+#include <QtQuick/QSGGeometryNode>
+#include <QtQuick/QSGTexture>
+#include <QtQuick/QSGTextureMaterial>
+#include <QtQuick/QQuickWindow>
+
+#include <private/qquickpixmapcache_p.h>
+#include <private/qquickimagebase_p_p.h>
+
+namespace QSGMaskedImageNS
+{
+
+class Mesh : public QSGGeometryNode
+{
+public:
+
+ Mesh()
+ : geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0, 0)
+ {
+ setGeometry(&geometry);
+ setMaterial(&material);
+ setOpaqueMaterial(&opaqueMaterial);
+ setFlags(OwnedByParent | OwnsOpaqueMaterial | OwnsMaterial | OwnsGeometry, false);
+ geometry.setDrawingMode(GL_TRIANGLE_STRIP);
+ }
+
+ void setTexture(QSGTexture *texture) {
+ opaqueMaterial.setTexture(texture);
+ material.setTexture(texture);
+ }
+
+ void setTriangles(QSGTriangleSet *t) {
+ Q_ASSERT_X(t->vertexType() == QSGTriangleSet::IndexedPoint2D, "QSGMaskedImage", "only IndexedPoint2D is supported by masked image");
+
+ QVector<QSGGeometry::Point2D> vertices = t->vertices2D();
+ QVector<quint16> indices = t->indices();
+ geometry.allocate(vertices.size(), indices.size());
+ geometry.setDrawingMode(t->drawingMode());
+
+ QSGGeometry::TexturedPoint2D *v = geometry.vertexDataAsTexturedPoint2D();
+ for (int i=0; i<vertices.size(); ++i) {
+ const QSGGeometry::Point2D &pt = vertices.at(i);
+ v[i].set(pt.x, pt.y, pt.x, pt.y);
+ }
+
+ quint16 *in = geometry.indexDataAsUShort();
+ memcpy(in, indices.constData(), indices.size() * sizeof(quint16));
+ }
+
+ QSGOpaqueTextureMaterial opaqueMaterial;
+ QSGTextureMaterial material;
+ QSGGeometry geometry;
+};
+
+class Root : public QSGTransformNode
+{
+public:
+ Root()
+ {
+#ifdef QML_RUNTIME_TESTING
+ description = "MaskedImage";
+ opaque.description = QStringLiteral("MaskedImage.opaque");
+ alpha.description = QStringLiteral("MaskedImage.alpha");
+#endif
+ }
+
+ void setTexture(QSGTexture *t) {
+ alpha.setTexture(t);
+ opaque.setTexture(t);
+ // Disable blending on this node as setTexture will set it to true.
+ opaque.opaqueMaterial.setFlag(QSGMaterial::Blending, false);
+ opaque.material.setFlag(QSGMaterial::Blending, false);
+ }
+
+ Mesh opaque;
+ Mesh alpha;
+};
+
+
+
+class MaskStore : public QObject
+{
+ Q_OBJECT
+
+public:
+ static QSGTriangleSet *lookup(QQuickTextureFactory *factory, const QString &url, bool opaque);
+
+public slots:
+ void factoryDestroyed(QObject *o);
+
+private:
+ QHash<qintptr, QSGTriangleSet *> store;
+
+ static MaskStore instance;
+};
+
+MaskStore MaskStore::instance;
+
+QSGTriangleSet *MaskStore::lookup(QQuickTextureFactory *factory, const QString &url, bool opaque)
+{
+ qintptr key = (qintptr) factory;
+ if (opaque)
+ key += 1;
+
+ if (instance.store.contains(key))
+ return instance.store.value(key);
+
+ QSGTriangleSet *set = new QSGTriangleSet();
+ QString res = set->readFile(url);
+ if (res.length() > 0) {
+ qDebug() << "Failed to read" << url << "," << res;
+ delete set;
+ set = 0;
+ }
+
+ // Only connect to opaque to avoid connecting twice...
+ if (opaque)
+ connect(factory, SIGNAL(destroyed(QObject *)), &instance, SLOT(factoryDestroyed(QObject *)));
+
+ instance.store[key] = set;
+ return set;
+}
+
+void MaskStore::factoryDestroyed(QObject *o)
+{
+ QQuickTextureFactory *f = static_cast<QQuickTextureFactory *>(o);
+ store.remove(qintptr(f));
+ store.remove(qintptr(f) + 1);
+}
+
+}
+
+using namespace QSGMaskedImageNS;
+
+
+QSGMaskedImage::QSGMaskedImage(QQuickItem *parent)
+ : QQuickImageBase(parent)
+ , m_opaqueTriangles(0)
+ , m_alphaTriangles(0)
+ , m_sourceChanged(false)
+{
+ setFlag(ItemHasContents, true);
+
+ connect(this, SIGNAL(widthChanged()), this, SLOT(sizeWasChanged()));
+ connect(this, SIGNAL(heightChanged()), this, SLOT(sizeWasChanged()));
+}
+
+QSGMaskedImage::~QSGMaskedImage()
+{
+
+}
+
+void QSGMaskedImage::pixmapChange()
+{
+ m_sourceChanged = true;
+ polish();
+ QQuickImageBase::pixmapChange();
+}
+
+void QSGMaskedImage::updatePolish()
+{
+ if (m_sourceChanged) {
+ QString baseName = QQmlFile::urlToLocalFileOrQrc(source());
+ m_opaqueTriangles = MaskStore::lookup(static_cast<QQuickImageBasePrivate *>(d_ptr.data())->pix.textureFactory(),
+ baseName + QStringLiteral(".opaquemask"),
+ true);
+ m_alphaTriangles = MaskStore::lookup(static_cast<QQuickImageBasePrivate *>(d_ptr.data())->pix.textureFactory(),
+ baseName + QStringLiteral(".alphamask"),
+ false);
+ }
+
+ update();
+}
+
+void QSGMaskedImage::sizeWasChanged()
+{
+ update();
+}
+
+QSGNode *QSGMaskedImage::updatePaintNode(QSGNode *old, UpdatePaintNodeData *)
+{
+ Root *node = static_cast<Root *>(old);
+
+ if (m_sourceChanged) {
+ QQuickPixmap *pix = &static_cast<QQuickImageBasePrivate *>(d_ptr.data())->pix;
+ delete node;
+ if (pix->isNull())
+ return 0;
+
+ node = new Root();
+
+ QSGTexture *t = pix->textureFactory()->createTexture(window());
+ node->setTexture(t);
+ m_sourceChanged = false;
+
+ if (m_alphaTriangles && m_alphaTriangles->isValid()) {
+ node->alpha.setTriangles(m_alphaTriangles);
+ node->appendChildNode(&node->alpha);
+ }
+
+ if (m_opaqueTriangles && m_opaqueTriangles->isValid()) {
+ node->opaque.setTriangles(m_opaqueTriangles);
+ node->appendChildNode(&node->opaque);
+ }
+ }
+
+ if (!node)
+ return 0;
+
+ QSGTexture::Filtering filter = smooth() ? QSGTexture::Linear : QSGTexture::Nearest;
+ node->opaque.material.setFiltering(filter);
+ node->opaque.opaqueMaterial.setFiltering(filter);
+ node->alpha.material.setFiltering(filter);
+ node->alpha.opaqueMaterial.setFiltering(filter);
+
+ QMatrix4x4 m;
+ m.scale(width(), height());
+ node->setMatrix(m);
+
+ return node;
+}
+
+#include "qsgmaskedimage.moc"
diff --git a/shapes/shapesplugin/qsgmaskedimage.h b/shapes/shapesplugin/qsgmaskedimage.h
new file mode 100644
index 0000000..299794b
--- /dev/null
+++ b/shapes/shapesplugin/qsgmaskedimage.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGMASKEDIMAGE_H
+#define QSGMASKEDIMAGE_H
+
+#include <private/qquickimagebase_p.h>
+
+#include <QtGui/QImage>
+
+#include "qsgtriangleset.h"
+
+class QSGMaskedImage : public QQuickImageBase
+{
+ Q_OBJECT
+
+public:
+ QSGMaskedImage(QQuickItem *parent = 0);
+ ~QSGMaskedImage();
+
+protected:
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ void updatePolish();
+
+ void pixmapChange();
+
+public slots:
+ void sizeWasChanged();
+
+signals:
+ void sourceChanged(QUrl source);
+
+private:
+ QSGTriangleSet *m_opaqueTriangles;
+ QSGTriangleSet *m_alphaTriangles;
+
+ uint m_sourceChanged : 1;
+ uint m_explicitSize : 1;
+};
+
+QML_DECLARE_TYPE(QSGMaskedImage)
+
+#endif // QSGMASKEDIMAGE_H
+
diff --git a/shapes/shapesplugin/qsgpolygon.cpp b/shapes/shapesplugin/qsgpolygon.cpp
new file mode 100644
index 0000000..7741126
--- /dev/null
+++ b/shapes/shapesplugin/qsgpolygon.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgpolygon.h"
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsgflatcolormaterial.h>
+
+// #define QSGPOLYGON_DEBUG
+
+class QSGPolygonNode : public QSGGeometryNode
+{
+public:
+ QSGPolygonNode()
+ : g(QSGGeometry::defaultAttributes_Point2D(), 0, 0)
+ {
+ setGeometry(&g);
+ setMaterial(&m);
+ setFlags(OwnsGeometry | OwnsMaterial, false);
+ }
+
+ QSGGeometry g;
+ QSGFlatColorMaterial m;
+};
+
+QSGPolygon::QSGPolygon()
+ : m_triangleSet(0)
+ , m_color(Qt::white)
+ , m_colorWasChanged(false)
+ , m_triangleSetWasChanged(false)
+{
+ setFlag(ItemHasContents, true);
+}
+
+void QSGPolygon::setTriangleSet(QSGTriangleSet *set)
+{
+ if (set == m_triangleSet)
+ return;
+
+ if (m_triangleSet)
+ disconnect(m_triangleSet, SIGNAL(changed()), this, SLOT(update()));
+ m_triangleSet = set;
+ connect(m_triangleSet, SIGNAL(changed()), this, SLOT(update()));
+
+ m_triangleSetWasChanged = true;
+
+ emit triangleSetChanged(m_triangleSet);
+ update();
+}
+
+void QSGPolygon::setColor(const QColor &color)
+{
+ if (color == m_color)
+ return;
+
+ m_color = color;
+
+ m_colorWasChanged = true;
+ emit colorChanged(m_color);
+ update();
+}
+
+QSGNode *QSGPolygon::updatePaintNode(QSGNode *old, UpdatePaintNodeData *)
+{
+ QSGPolygonNode *n = static_cast<QSGPolygonNode *>(old);
+
+ if (m_triangleSet == 0 || !m_triangleSet->isValid() || !m_color.isValid() || m_color.alpha() == 0) {
+ delete n;
+ return 0;
+ }
+
+ if (!n)
+ n = new QSGPolygonNode();
+
+ if (m_triangleSetWasChanged) {
+ QSGGeometry *g = &n->g;
+ g->allocate(m_triangleSet->vertices2D().size(), m_triangleSet->indices().size());
+ g->setDrawingMode(m_triangleSet->drawingMode());
+
+ memcpy(g->vertexData(), m_triangleSet->vertices2D().constData(), g->sizeOfVertex() * g->vertexCount());
+ memcpy(g->indexData(), m_triangleSet->indices().constData(), g->sizeOfIndex() * g->indexCount());
+
+#ifdef QSGPOLYGON_DEBUG
+ for (int i=0; i<g->vertexCount(); ++i)
+ qDebug() << "Polygon Vertex:" << g->vertexDataAsPoint2D()[i].x << g->vertexDataAsPoint2D()[i].y;
+ for (int i=0; i<g->indexCount(); ++i)
+ qDebug() << "Polygon Index:" << g->indexDataAsUShort()[i];
+#endif
+
+ n->markDirty(QSGNode::DirtyGeometry);
+ m_triangleSetWasChanged = false;
+ }
+
+ if (m_colorWasChanged) {
+ n->m.setColor(m_color);
+ m_colorWasChanged = false;
+ n->markDirty(QSGNode::DirtyMaterial);
+ }
+
+ return n;
+}
+
diff --git a/shapes/shapesplugin/qsgpolygon.h b/shapes/shapesplugin/qsgpolygon.h
new file mode 100644
index 0000000..b5c1f8c
--- /dev/null
+++ b/shapes/shapesplugin/qsgpolygon.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGPOLYGON_H
+#define QSGPOLYGON_H
+
+#include <QtQuick/QQuickItem>
+
+#include "qsgtriangleset.h"
+
+class QSGPolygon : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QSGTriangleSet *triangleSet READ triangleSet WRITE setTriangleSet NOTIFY triangleSetChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+public:
+ QSGPolygon();
+
+ QSGTriangleSet *triangleSet() const { return m_triangleSet; }
+ QColor color() const { return m_color; }
+
+protected:
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+
+signals:
+ void triangleSetChanged(QSGTriangleSet *set);
+ void colorChanged(const QColor &color);
+
+public slots:
+ void setTriangleSet(QSGTriangleSet *set);
+ void setColor(const QColor &color);
+
+private:
+ QSGTriangleSet *m_triangleSet;
+ QColor m_color;
+
+ uint m_colorWasChanged : 1;
+ uint m_triangleSetWasChanged : 1;
+};
+
+QML_DECLARE_TYPE(QSGPolygon)
+
+#endif
diff --git a/shapes/shapesplugin/qsgtriangleset.cpp b/shapes/shapesplugin/qsgtriangleset.cpp
new file mode 100644
index 0000000..64d876f
--- /dev/null
+++ b/shapes/shapesplugin/qsgtriangleset.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgtriangleset.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextStream>
+#include <QtCore/QDebug>
+
+#include <QtGui/QTransform>
+
+#include <private/qpolygonclipper_p.h>
+
+#include <private/qtriangulator_p.h>
+
+// #define QSGTRIANGLESET_DEBUG
+
+QSGTriangleSet::QSGTriangleSet()
+ : QObject()
+ , m_mode(GL_TRIANGLES)
+ , m_vertexType(IndexedPoint2D)
+{
+}
+
+
+void QSGTriangleSet::setDrawingMode(int drawingMode)
+{
+ if (m_mode == drawingMode)
+ return;
+
+ switch (drawingMode) {
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_STRIP:
+ case GL_TRIANGLE_FAN:
+ case GL_LINES:
+ m_mode = drawingMode;
+ break;
+ default:
+ qWarning("QSGTriangleSet::setDrawingMode: mode is unsupported: %d", drawingMode);
+ return;
+ }
+
+ emit changed();
+}
+
+void QSGTriangleSet::setVertexType(VertexType type)
+{
+ m_vertexType = type;
+ emit changed();
+}
+
+/*
+ * Reads the file and returns an empty string if it fails.
+ */
+
+QString QSGTriangleSet::readFile(const QUrl &name)
+{
+ QFile file(name.isRelative() ? name.toString() : name.toLocalFile());
+ if (!file.open(QFile::ReadOnly))
+ return file.errorString() + QStringLiteral(", ") + QFileInfo(file).absoluteFilePath();
+
+ QTextStream stream(&file);
+
+ QByteArray tag, version;
+
+ stream >> tag;
+ stream >> version;
+ if (tag != "qsgtriangleset")
+ return "not a triangleset file";
+ if (version != "0.1")
+ return "invalid version, only 0.1 currently supported";
+
+ stream >> tag;
+ QByteArray value;
+
+ int drawingMode = -1;
+ int vertexType = -1;
+
+ // Parse the rest of the header...
+ while (tag != "v" && tag != "V") {
+ if (tag == "drawing-mode") {
+ stream >> value;
+ if (value == "triangle-strip") drawingMode = GL_TRIANGLE_STRIP;
+ else if (value == "triangle-fan") drawingMode = GL_TRIANGLE_FAN;
+ else if (value == "triangles") drawingMode = GL_TRIANGLES;
+ else if (value == "lines") drawingMode = GL_LINES;
+ else return "bad drawing-mode: " + value;
+ } else if (tag == "data-type") {
+ stream >> value;
+ if (value == "indexed-point-2d") vertexType = IndexedPoint2D;
+ else return "bad data-type: " + value;
+ }
+
+ stream >> tag;
+
+ if (stream.atEnd())
+ return "premature end of file while parsing headers...";
+ }
+
+ if (drawingMode == -1)
+ return QStringLiteral("missing drawing-mode tag...");
+ if (vertexType == -1)
+ return QStringLiteral("missing vertex-type tag...");
+
+ QVector<QSGGeometry::Point2D> vertices;
+
+ // Parse vertices...
+ while (tag == "V" || tag == "v") {
+ QSGGeometry::Point2D p;
+ stream >> p.x >> p.y;
+ vertices << p;
+ stream >> tag;
+ }
+ if (vertices.size() == 0)
+ return "no vertices";
+
+ QVector<quint16> indices;
+ while (tag == "I" || tag == "i") {
+ quint16 i;
+ stream >> i;
+ indices << i;
+ stream >> tag;
+ }
+
+ if (indices.size() == 0)
+ return "no indices...";
+
+ m_indices = indices;
+ m_vertices = vertices;
+ m_mode = drawingMode;
+ m_vertexType = (VertexType) vertexType;
+
+ emit changed();
+
+ return QString();
+}
+
+QString QSGTriangleSet::saveFile(const QUrl &name)
+{
+ QFile file(name.isRelative() ? name.toString() : name.toLocalFile());
+ if (!file.open(QFile::WriteOnly))
+ return QStringLiteral("failed to open file, ") + QFileInfo(file).absoluteFilePath();
+
+ QTextStream stream(&file);
+
+ stream << "qsgtriangleset 0.1" << endl
+ << "drawing-mode ";
+ if (m_mode == GL_TRIANGLES)
+ stream << "triangles";
+ else if (m_mode == GL_TRIANGLE_STRIP)
+ stream << "triangle-strip";
+ else if (m_mode == GL_TRIANGLE_FAN)
+ stream << "triangle-fan";
+ else if (m_mode == GL_LINES)
+ stream << "lines";
+ stream << endl << "data-type indexed-point-2d" << endl;
+
+ for (int i=0; i<m_vertices.size(); ++i)
+ stream << "V " << m_vertices.at(i).x << " " << m_vertices.at(i).y << endl;
+ for (int i=0; i<m_indices.size(); ++i)
+ stream << "I " << m_indices.at(i) << endl;
+
+ return QString();
+}
+
+void QSGTriangleSet::beginPathConstruction()
+{
+ m_path = QPainterPath();
+}
+
+void QSGTriangleSet::moveTo(qreal x, qreal y)
+{
+ m_path.moveTo(x, y);
+}
+
+void QSGTriangleSet::lineTo(qreal x, qreal y)
+{
+ m_path.lineTo(x, y);
+}
+
+void QSGTriangleSet::quadTo(qreal cx, qreal cy, qreal ex, qreal ey)
+{
+ m_path.quadTo(cx, cy, ex, ey);
+}
+
+void QSGTriangleSet::cubicTo(qreal cx1, qreal cy1, qreal cx2, qreal cy2, qreal ex, qreal ey)
+{
+ m_path.cubicTo(cx1, cy1, cx2, cy2, ex, ey);
+}
+
+void QSGTriangleSet::addEllipse(qreal x, qreal y, qreal width, qreal height)
+{
+ m_path.addEllipse(x, y, width, height);
+}
+
+void QSGTriangleSet::addRect(qreal x, qreal y, qreal width, qreal height)
+{
+ m_path.addRect(x, y, width, height);
+}
+
+void QSGTriangleSet::addRoundedRect(qreal x, qreal y, qreal width, qreal height, qreal xrad, qreal yrad)
+{
+ m_path.addRoundedRect(x, y, width, height, xrad, yrad);
+}
+
+void QSGTriangleSet::closeSubpath()
+{
+ m_path.closeSubpath();
+}
+
+void QSGTriangleSet::setWindingMode(bool winding)
+{
+ m_path.setFillRule(winding ? Qt::WindingFill : Qt::OddEvenFill);
+}
+
+void QSGTriangleSet::clipToRect(qreal x, qreal y, qreal width, qreal height)
+{
+ QPainterPath bounds;
+ bounds.addRect(x, y, width, height);
+ m_path = m_path.intersected(bounds);
+}
+
+void QSGTriangleSet::finishPathConstruction()
+{
+ qreal scale = 100;
+
+ QTriangleSet ts = qTriangulate(m_path, QTransform::fromScale(scale, scale));
+
+ m_mode = GL_TRIANGLES;
+
+ m_vertices.resize(ts.vertices.size() / 2);
+ QSGGeometry::Point2D *vdst = m_vertices.data();
+ const qreal *vdata = ts.vertices.constData();
+ for (int i=0; i<ts.vertices.size() / 2; ++i) {
+ vdst[i].set(vdata[i*2] / scale, vdata[i*2+1] / scale);
+#ifdef QSGTRIANGLESET_DEBUG
+ qDebug() << "vertex: " << vdst[i].x << vdst[i].y;
+#endif
+ }
+
+ m_indices.resize(ts.indices.size());
+ quint16 *idst = m_indices.data();
+ if (ts.indices.type() == QVertexIndexVector::UnsignedShort) {
+ memcpy(idst, ts.indices.data(), m_indices.size() * sizeof(quint16));
+#ifdef QSGTRIANGLESET_DEBUG
+ for (int i=0; i<m_indices.size(); ++i) {
+ qDebug() << "index(16): " << idst[i];
+ }
+#endif
+ } else {
+ const quint32 *isrc = (const quint32 *) ts.indices.data();
+ for (int i=0; i<m_indices.size(); ++i) {
+ idst[i] = isrc[i];
+#ifdef QSGTRIANGLESET_DEBUG
+ qDebug() << "index: " << idst[i];
+#endif
+ }
+ }
+
+ emit changed();
+
+}
+
diff --git a/shapes/shapesplugin/qsgtriangleset.h b/shapes/shapesplugin/qsgtriangleset.h
new file mode 100644
index 0000000..4ca84a6
--- /dev/null
+++ b/shapes/shapesplugin/qsgtriangleset.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGTRIANGLESET_H
+#define QSGTRIANGLESET_H
+
+#include <QObject>
+
+#include <QtGui/QPainterPath>
+
+#include <QtQuick/qsggeometry.h>
+#include <QtQuick/QQuickItem>
+
+class QSGTriangleSet : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int drawingMode READ drawingMode WRITE setDrawingMode NOTIFY changed)
+
+public:
+ enum VertexType {
+ IndexedPoint2D
+ };
+
+ QSGTriangleSet();
+
+ QVector<quint16> indices() const { return m_indices; }
+ QVector<QSGGeometry::Point2D> vertices2D() const { return m_vertices; }
+
+ int drawingMode() const { return m_mode; }
+ void setDrawingMode(int drawingMode);
+
+ VertexType vertexType() const { return m_vertexType; }
+ void setVertexType(VertexType type);
+
+ bool isValid() const { return m_indices.size() > 0 && m_vertices.size() > 0; }
+
+public slots:
+ QString readFile(const QUrl &name);
+ QString saveFile(const QUrl &name);
+
+ void beginPathConstruction();
+ void moveTo(qreal x, qreal y);
+ void lineTo(qreal x, qreal y);
+ void quadTo(qreal cx, qreal cy, qreal ex, qreal ey);
+ void cubicTo(qreal cx1, qreal cy1, qreal cx2, qreal cy2, qreal ex, qreal ey);
+ void addEllipse(qreal x, qreal y, qreal width, qreal height);
+ void addRect(qreal x, qreal y, qreal width, qreal height);
+ void addRoundedRect(qreal x, qreal y, qreal width, qreal height, qreal xrad, qreal yrad);
+ void setWindingMode(bool winding);
+ void closeSubpath();
+ void clipToRect(qreal x, qreal y, qreal width, qreal height);
+ void finishPathConstruction();
+
+signals:
+ void changed();
+
+private:
+ int m_mode;
+ VertexType m_vertexType;
+ QVector<quint16> m_indices;
+ QVector<QSGGeometry::Point2D> m_vertices;
+
+ QPainterPath m_path;
+};
+
+QML_DECLARE_TYPE(QSGTriangleSet)
+
+#endif // QSGTRIANGLESET_H
diff --git a/shapes/shapesplugin/shapesplugin.cpp b/shapes/shapesplugin/shapesplugin.cpp
new file mode 100644
index 0000000..248ad85
--- /dev/null
+++ b/shapes/shapesplugin/shapesplugin.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QQmlExtensionPlugin>
+
+#include "qsgmaskedimage.h"
+#include "qsgpolygon.h"
+#include "qsgtriangleset.h"
+
+class MaskedimagepluginPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+
+public:
+ void registerTypes(const char *uri)
+ {
+ qmlRegisterType<QSGMaskedImage>(uri, 1, 0, "MaskedImage");
+ qmlRegisterType<QSGPolygon>(uri, 1, 0, "Polygon");
+ qmlRegisterType<QSGTriangleSet>(uri, 1, 0, "TriangleSet");
+ }
+};
+
+#include "shapesplugin.moc"
diff --git a/shapes/shapesplugin/shapesplugin.pro b/shapes/shapesplugin/shapesplugin.pro
new file mode 100644
index 0000000..e0150ab
--- /dev/null
+++ b/shapes/shapesplugin/shapesplugin.pro
@@ -0,0 +1,29 @@
+TEMPLATE = lib
+TARGET = shapes
+
+QT += quick
+QT += v8-private qml-private quick-private gui-private core-private # to get access to QPainter's triangulator
+
+CONFIG += qt plugin
+
+SOURCES += \
+ shapesplugin.cpp \
+ qsgmaskedimage.cpp \
+ qsgtriangleset.cpp \
+ qsgpolygon.cpp
+
+HEADERS += \
+ qsgmaskedimage.h \
+ qsgtriangleset.h \
+ qsgpolygon.h
+
+TARGETPATH=Qt/labs/shapes
+
+OTHER_FILES = qmldir
+
+target.path = $$[QT_INSTALL_QML]/$$TARGETPATH
+
+qmldir.files = qmldir
+qmldir.path = $$[QT_INSTALL_QML]/$$TARGETPATH
+
+INSTALLS = target qmldir
diff --git a/shapes/tests/TestMaskedImage.qml b/shapes/tests/TestMaskedImage.qml
new file mode 100644
index 0000000..28dd7a9
--- /dev/null
+++ b/shapes/tests/TestMaskedImage.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import Qt.labs.shapes 1.0
+
+Rectangle {
+ width: 800
+ height: 800
+
+ gradient: Gradient {
+ GradientStop { position: 0; color: "steelblue" }
+ GradientStop { position: 1; color: "black" }
+ }
+
+ MaskedImage {
+ anchors.centerIn: parent
+ source: "qtlogo.png"
+
+ asynchronous: true
+
+ opacity: status == Image.Ready ? 1 : 0
+ Behavior on opacity { NumberAnimation { duration: 500 } }
+ }
+
+ MaskedImage {
+ anchors.centerIn: parent
+ source: "qtlogo.png"
+
+ asynchronous: true
+
+ scale: 0.2
+
+ opacity: status == Image.Ready ? 1 : 0
+ Behavior on opacity { NumberAnimation { duration: 500 } }
+ }
+
+}
diff --git a/shapes/tests/TestPolygon.qml b/shapes/tests/TestPolygon.qml
new file mode 100644
index 0000000..48ca069
--- /dev/null
+++ b/shapes/tests/TestPolygon.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import Qt.labs.shapes 1.0
+
+Rectangle {
+ width: 1280
+ height: 720
+
+ gradient: Gradient {
+ GradientStop { position: 0; color: "steelblue" }
+ GradientStop { position: 1; color: "black" }
+ }
+
+ Polygon {
+ x: 150
+ y: 50
+
+ color: "white"
+ triangleSet: TriangleSet {
+ Component.onCompleted: {
+ var result = readFile(Qt.resolvedUrl("qtlogo.png.alphamask"))
+ if (result == "")
+ print("loaded file ok.." + Qt.resolvedUrl("qtlogo.png.alphamask"));
+ else
+ print("failed to load: " + result);
+ print("loaded file ok.." + Qt.resolvedUrl("qtlogo.png.alphamask"));
+ }
+ }
+
+ scale: 600
+ opacity: 0.5
+ }
+
+ Polygon {
+
+ x: 150
+ y: 50
+
+ color: "lightgray"
+ triangleSet: TriangleSet {
+ Component.onCompleted: {
+ var result = readFile(Qt.resolvedUrl("qtlogo.png.opaquemask"))
+ if (result == "")
+ print("loaded file ok..");
+ else
+ print("failed to load: " + result);
+ }
+ }
+
+ scale: 600
+
+ opacity: 0.5
+ }
+
+}
diff --git a/shapes/tests/TestVectorPath.qml b/shapes/tests/TestVectorPath.qml
new file mode 100644
index 0000000..9f7a7a1
--- /dev/null
+++ b/shapes/tests/TestVectorPath.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt.labs.shapes 1.0
+
+Rectangle {
+ width: 600
+ height: 600
+
+ gradient: Gradient {
+ GradientStop { position: 0; color: "steelblue" }
+ GradientStop { position: 1; color: "black" }
+ }
+
+ Polygon {
+ x: 50
+ y: 50
+
+ color: "white"
+ triangleSet: TriangleSet {
+ Component.onCompleted: {
+ beginPathConstruction();
+ addEllipse(100, 100, 200, 200);
+ addEllipse(200, 200, 200, 200);
+ moveTo(0, 0);
+ cubicTo(500, 0, 250, 250, 500, 500);
+ cubicTo(0, 500, 250, 250, 0, 0);
+ finishPathConstruction();
+ }
+ }
+ }
+}
diff --git a/shapes/tests/qtlogo.png b/shapes/tests/qtlogo.png
new file mode 100644
index 0000000..9073a38
--- /dev/null
+++ b/shapes/tests/qtlogo.png
Binary files differ
diff --git a/shapes/tests/qtlogo.png.alphamask b/shapes/tests/qtlogo.png.alphamask
new file mode 100644
index 0000000..c35d96a
--- /dev/null
+++ b/shapes/tests/qtlogo.png.alphamask
@@ -0,0 +1,75 @@
+qsgtriangleset 0.1
+drawing-mode triangles
+data-type indexed-point-2d
+V 0 0.14
+V 0.0065625 0.139687
+V 0.0509375 0.049375
+V 0.22875 0.008125
+V 1 0.116563
+V 1 0.753125
+V 0.986875 0.759375
+V 0.960625 0.831875
+V 0.917813 0.871562
+V 0.080625 0.98625
+V 0 0.92625
+V 0 0.0690625
+V 0.0165625 0.036875
+V 0.0984375 0
+V 0.336563 0
+V 1 0.0884375
+V 1 0.8325
+V 0.9475 0.886563
+V 0.143438 1
+V 0.0621875 1
+V 0 0.955938
+I 13
+I 3
+I 14
+I 13
+I 12
+I 3
+I 12
+I 2
+I 3
+I 12
+I 11
+I 2
+I 11
+I 1
+I 2
+I 11
+I 0
+I 1
+I 3
+I 15
+I 14
+I 3
+I 4
+I 15
+I 6
+I 7
+I 5
+I 7
+I 16
+I 5
+I 7
+I 8
+I 16
+I 8
+I 17
+I 16
+I 8
+I 9
+I 17
+I 9
+I 19
+I 17
+I 19
+I 18
+I 17
+I 20
+I 9
+I 10
+I 20
+I 19
+I 9
diff --git a/shapes/tests/qtlogo.png.opaquemask b/shapes/tests/qtlogo.png.opaquemask
new file mode 100644
index 0000000..702dae4
--- /dev/null
+++ b/shapes/tests/qtlogo.png.opaquemask
@@ -0,0 +1,41 @@
+qsgtriangleset 0.1
+drawing-mode triangles
+data-type indexed-point-2d
+V 0 0.14
+V 0.0065625 0.139687
+V 0.0509375 0.049375
+V 0.22875 0.008125
+V 1 0.116563
+V 1 0.753125
+V 0.986875 0.759375
+V 0.960625 0.831875
+V 0.917813 0.871562
+V 0.080625 0.98625
+V 0 0.92625
+I 2
+I 4
+I 3
+I 2
+I 1
+I 4
+I 1
+I 0
+I 4
+I 0
+I 5
+I 4
+I 0
+I 6
+I 5
+I 0
+I 7
+I 6
+I 0
+I 8
+I 7
+I 0
+I 10
+I 8
+I 10
+I 9
+I 8
diff --git a/shapes/tools/maskmaker/Checkers.qml b/shapes/tools/maskmaker/Checkers.qml
new file mode 100644
index 0000000..a0a78d7
--- /dev/null
+++ b/shapes/tools/maskmaker/Checkers.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+import QtQuick 2.0
+
+ShaderEffect {
+ id: tileBackground
+
+ property real tileSize: 16
+ property color color1: Qt.rgba(0.9, 0.9, 0.9, 1);
+ property color color2: Qt.rgba(0.85, 0.85, 0.85, 1);
+
+ property size pixelSize: Qt.size(width / tileSize, height / tileSize);
+
+ fragmentShader:
+ "
+ uniform lowp vec4 color1;
+ uniform lowp vec4 color2;
+ uniform highp vec2 pixelSize;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ highp vec2 tc = sign(sin(3.14152 * qt_TexCoord0 * pixelSize));
+ if (tc.x != tc.y)
+ gl_FragColor = color1;
+ else
+ gl_FragColor = color2;
+ }
+ "
+}
diff --git a/shapes/tools/maskmaker/Main.qml b/shapes/tools/maskmaker/Main.qml
new file mode 100644
index 0000000..f95b67e
--- /dev/null
+++ b/shapes/tools/maskmaker/Main.qml
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Scene Graph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt.labs.shapes 1.0
+
+Item {
+
+ id: root;
+
+ width: Math.max(600, imageRoot.width + 200);
+ height: Math.max(600, imageRoot.height + 200);
+
+ property bool viewFiltered: true
+ property real aspectRatio: width / height
+ property string writeMode: "interior" // interior, exterior, none
+
+ property var exterior: []
+ property var interior: []
+
+ property int boxSize: 4
+
+ Checkers
+ {
+ anchors.fill: parent
+ }
+
+ Item {
+ id: imageRoot
+
+ visible: image.status == Image.Ready
+
+ anchors.centerIn: parent
+ width: image.width
+ height: image.height
+
+ Image {
+ id: image
+ property real aspectRatio: width / height
+ source: "file:" + engine.source;
+ }
+
+ ShaderEffect {
+ anchors.fill: parent;
+
+ visible: root.viewFiltered
+
+ blending: false
+ property variant source: image
+ fragmentShader:
+ "
+ uniform lowp sampler2D source;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ lowp float a = texture2D(source, qt_TexCoord0).a;
+ if (a == 0.0)
+ gl_FragColor = vec4(0, 0, 0, 1);
+ else if (a == 1.0)
+ gl_FragColor = vec4(0.4, 0.4, 0.4, 1);
+ else
+ gl_FragColor = vec4(1, 1, 1, 1);
+ }
+ "
+ }
+ }
+
+ Canvas {
+ id: overlay
+
+ anchors.fill: parent;
+
+ function drawDots(ctx, list, color) {
+ ctx.beginPath();
+ for (var si=0; si<list.length; ++si) {
+ var subpath = list[si];
+ for (var i=0; i<subpath.length; ++i) {
+ var p = subpath[i];
+ ctx.ellipse(p.x - 6, p.y - 6, 13, 13);
+ }
+ }
+ ctx.fillStyle = color
+ ctx.fill();
+ ctx.strokeStyle = "white"
+ ctx.stroke();
+ }
+
+ function xform(pt) {
+ return { x: pt.x * imageRoot.width + imageRoot.x,
+ y: pt.y * imageRoot.height + imageRoot.y };
+ }
+
+ function drawShapes(ctx, list, color) {
+ for (var si=0; si<list.length; ++si) {
+ var subpath = list[si];
+ if (subpath.length >= 3) {
+ for (var i=0; i<subpath.length; ++i) {
+ var p = subpath[i];
+ if (i == 0)
+ ctx.moveTo(p.x, p.y);
+ else
+ ctx.lineTo(p.x, p.y);
+ }
+ }
+ ctx.closePath();
+ }
+ ctx.fillStyle = color;
+ ctx.fill();
+ ctx.stroke()
+ }
+
+ onPaint: {
+ var ctx = overlay.getContext("2d");
+
+ ctx.clearRect(0, 0, overlay.width, overlay.height);
+ ctx.reset();
+
+ ctx.translate(imageRoot.x, imageRoot.y);
+
+ ctx.lineCap = "butt"
+ ctx.beginPath();
+ ctx.globalAlpha = 0.7
+ ctx.strokeStyle = "white";
+ ctx.fillRule = Qt.OddEvenFill
+ ctx.lineWidth = 1;
+ drawShapes(ctx, root.interior, "#aaaaff");
+ if (root.exterior.length > 0 && root.exterior[0].length > 2)
+ drawShapes(ctx, root.exterior, "#ffaaaa");
+
+ ctx.lineWidth = 2
+ ctx.globalAlpha = 1.0;
+ drawDots(ctx, root.interior, "blue");
+ drawDots(ctx, root.exterior, "red");
+
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onClicked: {
+ helpOverlay.hidden = true;
+ var list = root.writeMode == "interior" ? root.interior : root.exterior;
+ var pt = { x: mouse.x - imageRoot.x, y: mouse.y - imageRoot.y };
+
+ if (list.length == 0) {
+ list.push( [ pt ]);
+ } else {
+ var subpath = list[list.length - 1];
+ if (subpath.length == 0) {
+ subpath.push(pt)
+ } else {
+ var s = subpath[0];
+ if (Math.abs(s.x - mouse.x + imageRoot.x) < 20 && Math.abs(s.y - mouse.y + imageRoot.x) < 20 && subpath.length >= 2) {
+ subpath.push(s);
+ list.push([]);
+ } else {
+ subpath.push(pt);
+ }
+ }
+ }
+ overlay.requestPaint()
+ }
+ }
+
+ TriangleSet {
+ id: triangleSet
+
+ function add(list) {
+ for (var si=0; si<list.length; ++si) {
+ var subpath = list[si];
+ if (subpath.length > 0)
+ moveTo(subpath[0].x / imageRoot.width, subpath[0].y / imageRoot.height);
+ for (var i=1; i<subpath.length; ++i)
+ lineTo(subpath[i].x / imageRoot.width, subpath[i].y / imageRoot.height);
+ closeSubpath()
+ }
+ }
+
+ function save() {
+ if (root.interior.length == 0 || root.interior[0].length < 3
+ || root.exterior.length == 0 || root.exterior[0].length < 3) {
+ helpOverlay.hidden = false;
+ return;
+ }
+
+ beginPathConstruction();
+ add(root.interior);
+ clipToRect(0, 0, 1, 1)
+ finishPathConstruction();
+ var or = saveFile(engine.source + ".opaquemask");
+
+ if (or == "") {
+ print("saved " + engine.source + ".opaquemask ok...");
+ } else {
+ print("saving " + engine.source + ".opaquemask failed: " + or);
+ return;
+ }
+
+ beginPathConstruction();
+ add(root.interior);
+ add(root.exterior);
+ clipToRect(0, 0, 1, 1);
+ finishPathConstruction();
+ var ar = saveFile(engine.source + ".alphamask");
+ if (ar == "") {
+ print("saved " + engine.source + ".alphamask ok...");
+ } else {
+ print("saving " + engine.source + ".alphamask failed: " + ar);
+ return;
+ }
+
+ print("My work here is done...\nGood bye!")
+ Qt.quit();
+ }
+ }
+
+ Keys.onSpacePressed: root.viewFiltered = !root.viewFiltered;
+ Keys.onPressed: {
+ if (event.key == Qt.Key_I) {
+ root.writeMode = "interior"
+ } else if (event.key == Qt.Key_E) {
+ root.writeMode = "exterior"
+ } else if (event.key == Qt.Key_F1) {
+ helpOverlay.hidden = !helpOverlay.hidden;
+ } else if (event.key == Qt.Key_Escape) {
+ Qt.quit();
+ } else if (event.key == Qt.Key_Backspace) {
+ root.interior = []
+ root.exterior = []
+ overlay.requestPaint();
+ } else if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return) {
+ triangleSet.save()
+ }
+ }
+
+ Rectangle {
+
+ id: helpOverlay
+
+ x: parent.width / 2 - width / 2;
+ y: parent.height / 2- height / 2;
+
+ width: label.width + 40
+ height: label.height + 40
+
+ gradient: Gradient {
+ GradientStop { position: 0; color: "white" }
+ GradientStop { position: 1; color: "gray" }
+ }
+ property bool hidden: false
+ opacity: hidden ? 0.0 : 1.0
+ Behavior on opacity { NumberAnimation { duration: 100 } }
+ border.color: "black"
+ radius: 10
+
+ enabled: !hidden
+
+ Text {
+ id: label
+ font.family: "courier"
+ text: image.status != Image.Ready ?
+ "Missing source image. Did you forget to specify it?" :
+"
+Usage:
+
+Click to add points to the polygon for interior and exterior.
+The interior polygon should mark that which is fully opaque,
+visible as gray when the filter is active. The exterior should
+be outside all partially translucent pixels, visible as white
+when the filter is active. You need at least three nodes in both
+interior and exterior before writing the triangles set to disk.
+
+Shortcuts:
+
+E: Add to exterior " + (root.writeMode == "exterior" ? "*" : "") + "
+I: Add to interior " + (root.writeMode == "interior" ? "*" : "") + "
+Backspace: Clear polygons and start over...
+F1: Toggle this help
+Enter: Save polygons as MaskedImage metadata
+Space: Toggle image filter " + (root.viewFiltered ? "*" : "") + "
+Escape: Exit...
+"
+ anchors.centerIn: parent;
+
+ }
+ }
+
+
+ focus: true
+
+
+}
diff --git a/shapes/tools/maskmaker/maskmaker.cpp b/shapes/tools/maskmaker/maskmaker.cpp
new file mode 100644
index 0000000..3f092cb
--- /dev/null
+++ b/shapes/tools/maskmaker/maskmaker.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the Scenegraph Playground module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Digia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDebug>
+#include <QtGui/QGuiApplication>
+#include <QtQml/QQmlContext>
+#include <QtQuick/QQuickView>
+
+class Engine : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString source READ source CONSTANT)
+public:
+
+ QString source() const { return m_source; }
+ void setSource(const QString &src) { m_source = src; }
+
+private:
+ QString m_source;
+};
+
+void printHelp() {
+ qDebug("Usage:\n"
+ " > maskmaker [options] filename\n"
+ "\n"
+ "Options:\n"
+ " -h --help This help..");
+}
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ Engine engine;
+
+ QStringList args = app.arguments();
+
+ for (int i=0; i<args.size(); ++i) {
+ if (args.at(i) == QStringLiteral("--help") || args.at(i) == QStringLiteral("-h")) {
+ printHelp();
+ return 0;
+ } else if (i == args.size() - 1 && i > 0) {
+ engine.setSource(args.at(i));
+ }
+ }
+
+ QQuickView view;
+ view.rootContext()->setContextProperty("engine", &engine);
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:/Main.qml"));
+ view.show();
+
+ QObject::connect((QObject *) view.engine(), SIGNAL(quit()), &app, SLOT(quit()));
+
+ app.exec();
+}
+
+#include "maskmaker.moc"
diff --git a/shapes/tools/maskmaker/maskmaker.pro b/shapes/tools/maskmaker/maskmaker.pro
new file mode 100644
index 0000000..f3a98c0
--- /dev/null
+++ b/shapes/tools/maskmaker/maskmaker.pro
@@ -0,0 +1,9 @@
+TARGET = maskmaker
+QT += quick
+CONFIG -= app_bundle
+SOURCES += maskmaker.cpp
+RESOURCES += maskmaker.qrc
+
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS = target
+
diff --git a/shapes/tools/maskmaker/maskmaker.qrc b/shapes/tools/maskmaker/maskmaker.qrc
new file mode 100644
index 0000000..730d5b5
--- /dev/null
+++ b/shapes/tools/maskmaker/maskmaker.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>Main.qml</file>
+ <file>Checkers.qml</file>
+ </qresource>
+</RCC>