aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2017-01-24 18:27:27 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2017-01-27 09:12:28 +0000
commita48244d5aa1d14c286b7cd39afebcfff9c9dcb60 (patch)
tree7acd17b061bf6f5afccc4f737e11704ebf035acd /src/quick/items
parent00d3f3e9da071efce92d320884b331ea559fb292 (diff)
JS API for defining static paths and draw params
In order to avoid the over head of one QObject for each VisualPath, Path and PathXxxx element, provide an optional JavaScript API. PathItem { VisualPath { strokeWidth: 4; fillColor: "blue"; dashPattern: [ 1, 2, 3, 4]; capStyle: RoundCap path: Path { PathMove { x: 100; y: 200 } PathLine { x: 300; y: 300 } } } can now also be written as, at least when the path and the stroke/fill params are static and do not need changing/animating later on: PathItem { Component.onCompleted: { var path = newPath(); var sfp = newStrokeFillParams(); path.moveTo(100, 200); path.lineTo(300, 300); sfp.strokeWidth = 4; sfp.fillColor = "blue"; sfp.dashPattern = [ 1, 2, 3, 4 ]; sfp.capStyle = VisualPath.RoundCap; appendVisualPath(path, sfp); commitVisualPaths(); } } In order to emphasize the difference from an imperative API (like context2d), keep the path and the path stroke/fill parameters separate. To preserve our sanity, extras like gradients are not mapped to JavaScript, instead, one still references an QML-defined object from properties like fillGradient. The objects from newPath() and newStrokeFillParams() are reusable by calling clear(). This avoids the need for multiple temp objects when there are multiple paths. Add a simple test and a hidden stress test with the tiger to the manual test. Change-Id: I3b1e275bacf8c8fc52f585fbed5d6f9354d5ae8e Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/quick/items')
-rw-r--r--src/quick/items/qquickpathitem.cpp814
-rw-r--r--src/quick/items/qquickpathitem_p.h7
-rw-r--r--src/quick/items/qquickpathitem_p_p.h103
-rw-r--r--src/quick/items/qquickpathitemgenericrenderer.cpp7
-rw-r--r--src/quick/items/qquickpathitemgenericrenderer_p.h1
-rw-r--r--src/quick/items/qquickpathitemnvprrenderer.cpp84
-rw-r--r--src/quick/items/qquickpathitemnvprrenderer_p.h2
-rw-r--r--src/quick/items/qquickpathitemsoftwarerenderer.cpp8
-rw-r--r--src/quick/items/qquickpathitemsoftwarerenderer_p.h1
9 files changed, 938 insertions, 89 deletions
diff --git a/src/quick/items/qquickpathitem.cpp b/src/quick/items/qquickpathitem.cpp
index c5ad73e960..61216be9b0 100644
--- a/src/quick/items/qquickpathitem.cpp
+++ b/src/quick/items/qquickpathitem.cpp
@@ -43,15 +43,20 @@
#include "qquickpathitemnvprrenderer_p.h"
#include "qquickpathitemsoftwarerenderer_p.h"
#include <private/qsgtexture_p.h>
+#include <private/qquicksvgparser_p.h>
#include <QtGui/private/qdrawhelper_p.h>
#include <QOpenGLFunctions>
+#include <private/qv4engine_p.h>
+#include <private/qv4object_p.h>
+#include <private/qv4qobjectwrapper_p.h>
+#include <private/qv4mm_p.h>
+#include <private/qqmlengine_p.h>
+
QT_BEGIN_NAMESPACE
-QQuickVisualPathPrivate::QQuickVisualPathPrivate()
- : path(nullptr),
- dirty(DirtyAll),
- strokeColor(Qt::white),
+QQuickPathItemStrokeFillParams::QQuickPathItemStrokeFillParams()
+ : strokeColor(Qt::white),
strokeWidth(1),
fillColor(Qt::white),
fillRule(QQuickVisualPath::OddEvenFill),
@@ -65,6 +70,56 @@ QQuickVisualPathPrivate::QQuickVisualPathPrivate()
dashPattern << 4 << 2; // 4 * strokeWidth dash followed by 2 * strokeWidth space
}
+QPainterPath QQuickPathItemPath::toPainterPath() const
+{
+ QPainterPath p;
+ int coordIdx = 0;
+ for (int i = 0; i < cmd.count(); ++i) {
+ switch (cmd[i]) {
+ case QQuickPathItemPath::MoveTo:
+ p.moveTo(coords[coordIdx], coords[coordIdx + 1]);
+ coordIdx += 2;
+ break;
+ case QQuickPathItemPath::LineTo:
+ p.lineTo(coords[coordIdx], coords[coordIdx + 1]);
+ coordIdx += 2;
+ break;
+ case QQuickPathItemPath::QuadTo:
+ p.quadTo(coords[coordIdx], coords[coordIdx + 1],
+ coords[coordIdx + 2], coords[coordIdx + 3]);
+ coordIdx += 4;
+ break;
+ case QQuickPathItemPath::CubicTo:
+ p.cubicTo(coords[coordIdx], coords[coordIdx + 1],
+ coords[coordIdx + 2], coords[coordIdx + 3],
+ coords[coordIdx + 4], coords[coordIdx + 5]);
+ coordIdx += 6;
+ break;
+ case QQuickPathItemPath::ArcTo:
+ // does not map to the QPainterPath API; reuse the helper code from QQuickSvgParser
+ QQuickSvgParser::pathArc(p,
+ coords[coordIdx], coords[coordIdx + 1], // radius
+ coords[coordIdx + 2], // xAxisRotation
+ !qFuzzyIsNull(coords[coordIdx + 6]), // useLargeArc
+ !qFuzzyIsNull(coords[coordIdx + 5]), // sweep flag
+ coords[coordIdx + 3], coords[coordIdx + 4], // end
+ p.currentPosition().x(), p.currentPosition().y());
+ coordIdx += 7;
+ break;
+ default:
+ qWarning("Unknown JS path command: %d", cmd[i]);
+ break;
+ }
+ }
+ return p;
+}
+
+QQuickVisualPathPrivate::QQuickVisualPathPrivate()
+ : path(nullptr),
+ dirty(DirtyAll)
+{
+}
+
QQuickVisualPath::QQuickVisualPath(QObject *parent)
: QObject(*(new QQuickVisualPathPrivate), parent)
{
@@ -108,14 +163,14 @@ void QQuickVisualPathPrivate::_q_pathChanged()
QColor QQuickVisualPath::strokeColor() const
{
Q_D(const QQuickVisualPath);
- return d->strokeColor;
+ return d->sfp.strokeColor;
}
void QQuickVisualPath::setStrokeColor(const QColor &color)
{
Q_D(QQuickVisualPath);
- if (d->strokeColor != color) {
- d->strokeColor = color;
+ if (d->sfp.strokeColor != color) {
+ d->sfp.strokeColor = color;
d->dirty |= QQuickVisualPathPrivate::DirtyStrokeColor;
emit strokeColorChanged();
emit changed();
@@ -125,14 +180,14 @@ void QQuickVisualPath::setStrokeColor(const QColor &color)
qreal QQuickVisualPath::strokeWidth() const
{
Q_D(const QQuickVisualPath);
- return d->strokeWidth;
+ return d->sfp.strokeWidth;
}
void QQuickVisualPath::setStrokeWidth(qreal w)
{
Q_D(QQuickVisualPath);
- if (d->strokeWidth != w) {
- d->strokeWidth = w;
+ if (d->sfp.strokeWidth != w) {
+ d->sfp.strokeWidth = w;
d->dirty |= QQuickVisualPathPrivate::DirtyStrokeWidth;
emit strokeWidthChanged();
emit changed();
@@ -142,14 +197,14 @@ void QQuickVisualPath::setStrokeWidth(qreal w)
QColor QQuickVisualPath::fillColor() const
{
Q_D(const QQuickVisualPath);
- return d->fillColor;
+ return d->sfp.fillColor;
}
void QQuickVisualPath::setFillColor(const QColor &color)
{
Q_D(QQuickVisualPath);
- if (d->fillColor != color) {
- d->fillColor = color;
+ if (d->sfp.fillColor != color) {
+ d->sfp.fillColor = color;
d->dirty |= QQuickVisualPathPrivate::DirtyFillColor;
emit fillColorChanged();
emit changed();
@@ -159,14 +214,14 @@ void QQuickVisualPath::setFillColor(const QColor &color)
QQuickVisualPath::FillRule QQuickVisualPath::fillRule() const
{
Q_D(const QQuickVisualPath);
- return d->fillRule;
+ return d->sfp.fillRule;
}
void QQuickVisualPath::setFillRule(FillRule fillRule)
{
Q_D(QQuickVisualPath);
- if (d->fillRule != fillRule) {
- d->fillRule = fillRule;
+ if (d->sfp.fillRule != fillRule) {
+ d->sfp.fillRule = fillRule;
d->dirty |= QQuickVisualPathPrivate::DirtyFillRule;
emit fillRuleChanged();
emit changed();
@@ -176,14 +231,14 @@ void QQuickVisualPath::setFillRule(FillRule fillRule)
QQuickVisualPath::JoinStyle QQuickVisualPath::joinStyle() const
{
Q_D(const QQuickVisualPath);
- return d->joinStyle;
+ return d->sfp.joinStyle;
}
void QQuickVisualPath::setJoinStyle(JoinStyle style)
{
Q_D(QQuickVisualPath);
- if (d->joinStyle != style) {
- d->joinStyle = style;
+ if (d->sfp.joinStyle != style) {
+ d->sfp.joinStyle = style;
d->dirty |= QQuickVisualPathPrivate::DirtyStyle;
emit joinStyleChanged();
emit changed();
@@ -193,14 +248,14 @@ void QQuickVisualPath::setJoinStyle(JoinStyle style)
int QQuickVisualPath::miterLimit() const
{
Q_D(const QQuickVisualPath);
- return d->miterLimit;
+ return d->sfp.miterLimit;
}
void QQuickVisualPath::setMiterLimit(int limit)
{
Q_D(QQuickVisualPath);
- if (d->miterLimit != limit) {
- d->miterLimit = limit;
+ if (d->sfp.miterLimit != limit) {
+ d->sfp.miterLimit = limit;
d->dirty |= QQuickVisualPathPrivate::DirtyStyle;
emit miterLimitChanged();
emit changed();
@@ -210,14 +265,14 @@ void QQuickVisualPath::setMiterLimit(int limit)
QQuickVisualPath::CapStyle QQuickVisualPath::capStyle() const
{
Q_D(const QQuickVisualPath);
- return d->capStyle;
+ return d->sfp.capStyle;
}
void QQuickVisualPath::setCapStyle(CapStyle style)
{
Q_D(QQuickVisualPath);
- if (d->capStyle != style) {
- d->capStyle = style;
+ if (d->sfp.capStyle != style) {
+ d->sfp.capStyle = style;
d->dirty |= QQuickVisualPathPrivate::DirtyStyle;
emit capStyleChanged();
emit changed();
@@ -227,14 +282,14 @@ void QQuickVisualPath::setCapStyle(CapStyle style)
QQuickVisualPath::StrokeStyle QQuickVisualPath::strokeStyle() const
{
Q_D(const QQuickVisualPath);
- return d->strokeStyle;
+ return d->sfp.strokeStyle;
}
void QQuickVisualPath::setStrokeStyle(StrokeStyle style)
{
Q_D(QQuickVisualPath);
- if (d->strokeStyle != style) {
- d->strokeStyle = style;
+ if (d->sfp.strokeStyle != style) {
+ d->sfp.strokeStyle = style;
d->dirty |= QQuickVisualPathPrivate::DirtyDash;
emit strokeStyleChanged();
emit changed();
@@ -244,14 +299,14 @@ void QQuickVisualPath::setStrokeStyle(StrokeStyle style)
qreal QQuickVisualPath::dashOffset() const
{
Q_D(const QQuickVisualPath);
- return d->dashOffset;
+ return d->sfp.dashOffset;
}
void QQuickVisualPath::setDashOffset(qreal offset)
{
Q_D(QQuickVisualPath);
- if (d->dashOffset != offset) {
- d->dashOffset = offset;
+ if (d->sfp.dashOffset != offset) {
+ d->sfp.dashOffset = offset;
d->dirty |= QQuickVisualPathPrivate::DirtyDash;
emit dashOffsetChanged();
emit changed();
@@ -261,14 +316,14 @@ void QQuickVisualPath::setDashOffset(qreal offset)
QVector<qreal> QQuickVisualPath::dashPattern() const
{
Q_D(const QQuickVisualPath);
- return d->dashPattern;
+ return d->sfp.dashPattern;
}
void QQuickVisualPath::setDashPattern(const QVector<qreal> &array)
{
Q_D(QQuickVisualPath);
- if (d->dashPattern != array) {
- d->dashPattern = array;
+ if (d->sfp.dashPattern != array) {
+ d->sfp.dashPattern = array;
d->dirty |= QQuickVisualPathPrivate::DirtyDash;
emit dashPatternChanged();
emit changed();
@@ -278,19 +333,19 @@ void QQuickVisualPath::setDashPattern(const QVector<qreal> &array)
QQuickPathGradient *QQuickVisualPath::fillGradient() const
{
Q_D(const QQuickVisualPath);
- return d->fillGradient;
+ return d->sfp.fillGradient;
}
void QQuickVisualPath::setFillGradient(QQuickPathGradient *gradient)
{
Q_D(QQuickVisualPath);
- if (d->fillGradient != gradient) {
- if (d->fillGradient)
- qmlobject_disconnect(d->fillGradient, QQuickPathGradient, SIGNAL(updated()),
+ if (d->sfp.fillGradient != gradient) {
+ if (d->sfp.fillGradient)
+ qmlobject_disconnect(d->sfp.fillGradient, QQuickPathGradient, SIGNAL(updated()),
this, QQuickVisualPath, SLOT(_q_fillGradientChanged()));
- d->fillGradient = gradient;
- if (d->fillGradient)
- qmlobject_connect(d->fillGradient, QQuickPathGradient, SIGNAL(updated()),
+ d->sfp.fillGradient = gradient;
+ if (d->sfp.fillGradient)
+ qmlobject_connect(d->sfp.fillGradient, QQuickPathGradient, SIGNAL(updated()),
this, QQuickVisualPath, SLOT(_q_fillGradientChanged()));
d->dirty |= QQuickVisualPathPrivate::DirtyFillGradient;
emit changed();
@@ -430,14 +485,14 @@ QQuickPathItem::Status QQuickPathItem::status() const
static QQuickVisualPath *vpe_at(QQmlListProperty<QQuickVisualPath> *property, int index)
{
QQuickPathItemPrivate *d = QQuickPathItemPrivate::get(static_cast<QQuickPathItem *>(property->object));
- return d->vp.at(index);
+ return d->qmlData.vp.at(index);
}
static void vpe_append(QQmlListProperty<QQuickVisualPath> *property, QQuickVisualPath *obj)
{
QQuickPathItem *item = static_cast<QQuickPathItem *>(property->object);
QQuickPathItemPrivate *d = QQuickPathItemPrivate::get(item);
- d->vp.append(obj);
+ d->qmlData.vp.append(obj);
if (d->componentComplete) {
QObject::connect(obj, SIGNAL(changed()), item, SLOT(_q_visualPathChanged()));
@@ -448,7 +503,7 @@ static void vpe_append(QQmlListProperty<QQuickVisualPath> *property, QQuickVisua
static int vpe_count(QQmlListProperty<QQuickVisualPath> *property)
{
QQuickPathItemPrivate *d = QQuickPathItemPrivate::get(static_cast<QQuickPathItem *>(property->object));
- return d->vp.count();
+ return d->qmlData.vp.count();
}
static void vpe_clear(QQmlListProperty<QQuickVisualPath> *property)
@@ -456,10 +511,10 @@ static void vpe_clear(QQmlListProperty<QQuickVisualPath> *property)
QQuickPathItem *item = static_cast<QQuickPathItem *>(property->object);
QQuickPathItemPrivate *d = QQuickPathItemPrivate::get(item);
- for (QQuickVisualPath *p : d->vp)
+ for (QQuickVisualPath *p : d->qmlData.vp)
QObject::disconnect(p, SIGNAL(changed()), item, SLOT(_q_visualPathChanged()));
- d->vp.clear();
+ d->qmlData.vp.clear();
if (d->componentComplete)
d->_q_visualPathChanged();
@@ -486,7 +541,7 @@ void QQuickPathItem::componentComplete()
Q_D(QQuickPathItem);
d->componentComplete = true;
- for (QQuickVisualPath *p : d->vp)
+ for (QQuickVisualPath *p : d->qmlData.vp)
connect(p, SIGNAL(changed()), this, SLOT(_q_visualPathChanged()));
d->_q_visualPathChanged();
@@ -624,36 +679,60 @@ void QQuickPathItemPrivate::sync()
renderer->setAsyncCallback(q_asyncPathItemReady, this);
}
- const int count = vp.count();
- renderer->beginSync(count);
-
- for (int i = 0; i < count; ++i) {
- QQuickVisualPath *p = vp[i];
- int &dirty(QQuickVisualPathPrivate::get(p)->dirty);
-
- if (dirty & QQuickVisualPathPrivate::DirtyPath)
- renderer->setPath(i, p->path());
- if (dirty & QQuickVisualPathPrivate::DirtyStrokeColor)
- renderer->setStrokeColor(i, p->strokeColor());
- if (dirty & QQuickVisualPathPrivate::DirtyStrokeWidth)
- renderer->setStrokeWidth(i, p->strokeWidth());
- if (dirty & QQuickVisualPathPrivate::DirtyFillColor)
- renderer->setFillColor(i, p->fillColor());
- if (dirty & QQuickVisualPathPrivate::DirtyFillRule)
- renderer->setFillRule(i, p->fillRule());
- if (dirty & QQuickVisualPathPrivate::DirtyStyle) {
- renderer->setJoinStyle(i, p->joinStyle(), p->miterLimit());
- renderer->setCapStyle(i, p->capStyle());
+ if (!jsData.isValid()) {
+ // Standard route: The path and stroke/fill parameters are provided via
+ // VisualPath and Path.
+ const int count = qmlData.vp.count();
+ renderer->beginSync(count);
+
+ for (int i = 0; i < count; ++i) {
+ QQuickVisualPath *p = qmlData.vp[i];
+ int &dirty(QQuickVisualPathPrivate::get(p)->dirty);
+
+ if (dirty & QQuickVisualPathPrivate::DirtyPath)
+ renderer->setPath(i, p->path());
+ if (dirty & QQuickVisualPathPrivate::DirtyStrokeColor)
+ renderer->setStrokeColor(i, p->strokeColor());
+ if (dirty & QQuickVisualPathPrivate::DirtyStrokeWidth)
+ renderer->setStrokeWidth(i, p->strokeWidth());
+ if (dirty & QQuickVisualPathPrivate::DirtyFillColor)
+ renderer->setFillColor(i, p->fillColor());
+ if (dirty & QQuickVisualPathPrivate::DirtyFillRule)
+ renderer->setFillRule(i, p->fillRule());
+ if (dirty & QQuickVisualPathPrivate::DirtyStyle) {
+ renderer->setJoinStyle(i, p->joinStyle(), p->miterLimit());
+ renderer->setCapStyle(i, p->capStyle());
+ }
+ if (dirty & QQuickVisualPathPrivate::DirtyDash)
+ renderer->setStrokeStyle(i, p->strokeStyle(), p->dashOffset(), p->dashPattern());
+ if (dirty & QQuickVisualPathPrivate::DirtyFillGradient)
+ renderer->setFillGradient(i, p->fillGradient());
+
+ dirty = 0;
}
- if (dirty & QQuickVisualPathPrivate::DirtyDash)
- renderer->setStrokeStyle(i, p->strokeStyle(), p->dashOffset(), p->dashPattern());
- if (dirty & QQuickVisualPathPrivate::DirtyFillGradient)
- renderer->setFillGradient(i, p->fillGradient());
- dirty = 0;
- }
+ renderer->endSync(useAsync);
+ } else {
+ // Path and stroke/fill params provided from JavaScript. This avoids
+ // QObjects at the expense of not supporting changes afterwards.
+ const int count = jsData.paths.count();
+ renderer->beginSync(count);
+
+ for (int i = 0; i < count; ++i) {
+ renderer->setJSPath(i, jsData.paths[i]);
+ const QQuickPathItemStrokeFillParams sfp(jsData.sfp[i]);
+ renderer->setStrokeColor(i, sfp.strokeColor);
+ renderer->setStrokeWidth(i, sfp.strokeWidth);
+ renderer->setFillColor(i, sfp.fillColor);
+ renderer->setFillRule(i, sfp.fillRule);
+ renderer->setJoinStyle(i, sfp.joinStyle, sfp.miterLimit);
+ renderer->setCapStyle(i, sfp.capStyle);
+ renderer->setStrokeStyle(i, sfp.strokeStyle, sfp.dashOffset, sfp.dashPattern);
+ renderer->setFillGradient(i, sfp.fillGradient);
+ }
- renderer->endSync(useAsync);
+ renderer->endSync(useAsync);
+ }
if (!useAsync)
setStatus(QQuickPathItem::Ready);
@@ -935,6 +1014,593 @@ QSGTexture *QQuickPathItemGradientCache::get(const GradientDesc &grad)
#endif // QT_NO_OPENGL
+// ***** JS-based alternative for creating static paths, (mostly) without QObjects *****
+
+class QQuickPathItemJSEngineData : public QV8Engine::Deletable
+{
+public:
+ QQuickPathItemJSEngineData(QV4::ExecutionEngine *engine);
+
+ QV4::PersistentValue pathProto;
+ QV4::PersistentValue strokeFillParamsProto;
+};
+
+V4_DEFINE_EXTENSION(QQuickPathItemJSEngineData, engineData)
+
+namespace QV4 {
+namespace Heap {
+
+struct QQuickPathItemJSPathPrototype : Object {
+ void init() { Object::init(); }
+};
+
+struct QQuickPathItemJSPath : Object {
+ void init() { Object::init(); }
+ QQuickPathItemPathObject *obj;
+};
+
+struct QQuickPathItemJSStrokeFillParamsPrototype : Object {
+ void init() { Object::init(); }
+};
+
+struct QQuickPathItemJSStrokeFillParams : Object {
+ void init() { Object::init(); }
+ QQuickPathItemStrokeFillParamsObject *obj;
+};
+
+} // namespace Heap
+} // namespace QV4
+
+struct QQuickPathItemJSPathPrototype : public QV4::Object
+{
+ V4_OBJECT2(QQuickPathItemJSPathPrototype, QV4::Object)
+public:
+ static QV4::Heap::QQuickPathItemJSPathPrototype *create(QV4::ExecutionEngine *engine)
+ {
+ QV4::Scope scope(engine);
+ auto obj = engine->memoryManager->allocObject<QQuickPathItemJSPathPrototype>();
+ QV4::Scoped<QQuickPathItemJSPathPrototype> o(scope, obj);
+
+ o->defineDefaultProperty(QStringLiteral("clear"), method_clear, 0);
+ o->defineDefaultProperty(QStringLiteral("moveTo"), method_moveTo, 0);
+ o->defineDefaultProperty(QStringLiteral("lineTo"), method_lineTo, 0);
+ o->defineDefaultProperty(QStringLiteral("quadTo"), method_quadTo, 0);
+ o->defineDefaultProperty(QStringLiteral("cubicTo"), method_cubicTo, 0);
+ o->defineDefaultProperty(QStringLiteral("arcTo"), method_arcTo, 0);
+
+ return o->d();
+ }
+
+ static void method_clear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_moveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_lineTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_quadTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_cubicTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_arcTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+};
+
+DEFINE_OBJECT_VTABLE(QQuickPathItemJSPathPrototype);
+
+struct QQuickPathItemJSStrokeFillParamsPrototype : public QV4::Object
+{
+ V4_OBJECT2(QQuickPathItemJSStrokeFillParamsPrototype, QV4::Object)
+public:
+ static QV4::Heap::QQuickPathItemJSStrokeFillParamsPrototype *create(QV4::ExecutionEngine *engine)
+ {
+ QV4::Scope scope(engine);
+ auto obj = engine->memoryManager->allocObject<QQuickPathItemJSStrokeFillParamsPrototype>();
+ QV4::Scoped<QQuickPathItemJSStrokeFillParamsPrototype> o(scope, obj);
+
+ o->defineDefaultProperty(QStringLiteral("clear"), method_clear, 0);
+
+ return o->d();
+ }
+
+ static void method_clear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+};
+
+DEFINE_OBJECT_VTABLE(QQuickPathItemJSStrokeFillParamsPrototype);
+
+struct QQuickPathItemJSPath : public QV4::Object
+{
+ V4_OBJECT2(QQuickPathItemJSPath, QV4::Object)
+};
+
+DEFINE_OBJECT_VTABLE(QQuickPathItemJSPath);
+
+struct QQuickPathItemJSStrokeFillParams : public QV4::Object
+{
+ V4_OBJECT2(QQuickPathItemJSStrokeFillParams, QV4::Object)
+
+ static void method_get_strokeColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_strokeColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_strokeWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_strokeWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_fillColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_fillColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_joinStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_joinStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_capStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_capStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_dashOffset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_dashOffset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_dashPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_dashPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_get_fillGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+ static void method_set_fillGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData);
+};
+
+DEFINE_OBJECT_VTABLE(QQuickPathItemJSStrokeFillParams);
+
+void QQuickPathItemJSPathPrototype::method_clear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>());
+
+ r->d()->obj->clear();
+
+ scope.result = callData->thisObject.asReturnedValue();
+}
+
+void QQuickPathItemJSPathPrototype::method_moveTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>());
+
+ if (callData->argc >= 2) {
+ QQuickPathItemPathObject *p = r->d()->obj;
+ p->path.cmd.append(QQuickPathItemPath::MoveTo);
+ p->path.coords.append(callData->args[0].toNumber());
+ p->path.coords.append(callData->args[1].toNumber());
+ }
+
+ scope.result = callData->thisObject.asReturnedValue();
+}
+
+void QQuickPathItemJSPathPrototype::method_lineTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>());
+
+ if (callData->argc >= 2) {
+ QQuickPathItemPathObject *p = r->d()->obj;
+ p->path.cmd.append(QQuickPathItemPath::LineTo);
+ p->path.coords.append(callData->args[0].toNumber());
+ p->path.coords.append(callData->args[1].toNumber());
+ }
+
+ scope.result = callData->thisObject.asReturnedValue();
+}
+
+void QQuickPathItemJSPathPrototype::method_quadTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>());
+
+ if (callData->argc >= 4) {
+ QQuickPathItemPathObject *p = r->d()->obj;
+ p->path.cmd.append(QQuickPathItemPath::QuadTo);
+ const QV4::Value *v = callData->args;
+ p->path.coords.append(v[0].toNumber()); // cx
+ p->path.coords.append(v[1].toNumber()); // cy
+ p->path.coords.append(v[2].toNumber()); // x
+ p->path.coords.append(v[3].toNumber()); // y
+ }
+
+ scope.result = callData->thisObject.asReturnedValue();
+}
+
+void QQuickPathItemJSPathPrototype::method_cubicTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>());
+
+ if (callData->argc >= 6) {
+ QQuickPathItemPathObject *p = r->d()->obj;
+ p->path.cmd.append(QQuickPathItemPath::CubicTo);
+ const QV4::Value *v = callData->args;
+ p->path.coords.append(v[0].toNumber()); // c1x
+ p->path.coords.append(v[1].toNumber()); // c1y
+ p->path.coords.append(v[2].toNumber()); // c2x
+ p->path.coords.append(v[3].toNumber()); // c2y
+ p->path.coords.append(v[4].toNumber()); // x
+ p->path.coords.append(v[5].toNumber()); // y
+ }
+
+ scope.result = callData->thisObject.asReturnedValue();
+}
+
+void QQuickPathItemJSPathPrototype::method_arcTo(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSPath> r(scope, callData->thisObject.as<QQuickPathItemJSPath>());
+
+ if (callData->argc >= 7) {
+ QQuickPathItemPathObject *p = r->d()->obj;
+ p->path.cmd.append(QQuickPathItemPath::ArcTo);
+ const QV4::Value *v = callData->args;
+ p->path.coords.append(v[0].toNumber()); // radiusX
+ p->path.coords.append(v[1].toNumber()); // radiusY
+ p->path.coords.append(v[2].toNumber()); // xAxisRotation
+ p->path.coords.append(v[3].toNumber()); // x
+ p->path.coords.append(v[4].toNumber()); // y
+ p->path.coords.append(v[5].toNumber()); // sweepFlag
+ p->path.coords.append(v[6].toNumber()); // largeArc
+ }
+
+ scope.result = callData->thisObject.asReturnedValue();
+}
+
+void QQuickPathItemJSStrokeFillParamsPrototype::method_clear(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ r->d()->obj->clear();
+
+ scope.result = callData->thisObject.asReturnedValue();
+}
+
+extern QColor qt_color_from_string(const QV4::Value &name); // qquickcontext2d.cpp
+
+static inline QString qt_color_string(const QColor &color)
+{
+ if (color.alpha() == 255)
+ return color.name();
+ QString alphaString = QString::number(color.alphaF(), 'f');
+ while (alphaString.endsWith(QLatin1Char('0')))
+ alphaString.chop(1);
+ if (alphaString.endsWith(QLatin1Char('.')))
+ alphaString += QLatin1Char('0');
+ return QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString);
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_strokeColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = QV4::Encode(scope.engine->newString(qt_color_string(r->d()->obj->sfp.strokeColor)));
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_strokeColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ if (value->isString())
+ r->d()->obj->sfp.strokeColor = qt_color_from_string(value);
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_strokeWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = scope.engine->fromVariant(r->d()->obj->sfp.strokeWidth);
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_strokeWidth(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ r->d()->obj->sfp.strokeWidth = value->toNumber();
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_fillColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = QV4::Encode(scope.engine->newString(qt_color_string(r->d()->obj->sfp.fillColor)));
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_fillColor(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ if (value->isString())
+ r->d()->obj->sfp.fillColor = qt_color_from_string(value);
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = scope.engine->fromVariant(r->d()->obj->sfp.fillRule);
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_fillRule(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ if (value->isInt32())
+ r->d()->obj->sfp.fillRule = QQuickVisualPath::FillRule(value->integerValue());
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_joinStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = scope.engine->fromVariant(r->d()->obj->sfp.joinStyle);
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_joinStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ if (value->isInt32())
+ r->d()->obj->sfp.joinStyle = QQuickVisualPath::JoinStyle(value->integerValue());
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = scope.engine->fromVariant(r->d()->obj->sfp.miterLimit);
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_miterLimit(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ r->d()->obj->sfp.miterLimit = value->toNumber();
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_capStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = scope.engine->fromVariant(r->d()->obj->sfp.capStyle);
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_capStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ if (value->isInt32())
+ r->d()->obj->sfp.capStyle = QQuickVisualPath::CapStyle(value->integerValue());
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = scope.engine->fromVariant(r->d()->obj->sfp.strokeStyle);
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_strokeStyle(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ if (value->isInt32())
+ r->d()->obj->sfp.strokeStyle = QQuickVisualPath::StrokeStyle(value->integerValue());
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_dashOffset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = scope.engine->fromVariant(r->d()->obj->sfp.dashOffset);
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_dashOffset(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ r->d()->obj->sfp.dashOffset = value->toNumber();
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_dashPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedArrayObject a(scope, scope.engine->newArrayObject());
+ QQuickPathItemStrokeFillParamsObject *p = r->d()->obj;
+ a->arrayReserve(p->sfp.dashPattern.count());
+ QV4::ScopedValue v(scope);
+ for (int i = 0; i < p->sfp.dashPattern.count(); ++i)
+ a->arrayPut(i, (v = scope.engine->fromVariant(p->sfp.dashPattern[i])));
+ a->setArrayLengthUnchecked(p->sfp.dashPattern.count());
+
+ scope.result = a.asReturnedValue();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_dashPattern(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ if (value->isObject()) {
+ QV4::Scoped<QV4::ArrayObject> ao(scope, value);
+ if (!!ao) {
+ QQuickPathItemStrokeFillParamsObject *p = r->d()->obj;
+ p->sfp.dashPattern.resize(ao->getLength());
+ QV4::ScopedValue val(scope);
+ for (int i = 0; i < p->sfp.dashPattern.count(); ++i) {
+ val = ao->getIndexed(i);
+ p->sfp.dashPattern[i] = val->toNumber();
+ }
+ }
+ }
+
+ scope.result = QV4::Encode::undefined();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_get_fillGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ scope.result = r->d()->obj->v4fillGradient.value();
+}
+
+void QQuickPathItemJSStrokeFillParams::method_set_fillGradient(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData)
+{
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> r(scope, callData->thisObject.as<QQuickPathItemJSStrokeFillParams>());
+
+ QV4::ScopedValue value(scope, callData->argument(0));
+ QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, value);
+ if (!!qobjectWrapper) {
+ if (QQuickPathGradient *grad = qobject_cast<QQuickPathGradient *>(qobjectWrapper->object())) {
+ r->d()->obj->v4fillGradient.set(scope.engine, value);
+ r->d()->obj->sfp.fillGradient = grad;
+ }
+ } else {
+ r->d()->obj->v4fillGradient.set(scope.engine, nullptr);
+ r->d()->obj->sfp.fillGradient = nullptr;
+ }
+
+ scope.result = QV4::Encode::undefined();
+}
+
+QQuickPathItemJSEngineData::QQuickPathItemJSEngineData(QV4::ExecutionEngine *v4)
+{
+ QV4::Scope scope(v4);
+
+ QV4::ScopedObject proto(scope, QQuickPathItemJSPathPrototype::create(v4));
+ pathProto = proto;
+
+ proto = QV4::ScopedObject(scope, QQuickPathItemJSStrokeFillParamsPrototype::create(v4));
+
+ proto->defineAccessorProperty(QStringLiteral("strokeColor"),
+ QQuickPathItemJSStrokeFillParams::method_get_strokeColor,
+ QQuickPathItemJSStrokeFillParams::method_set_strokeColor);
+ proto->defineAccessorProperty(QStringLiteral("strokeWidth"),
+ QQuickPathItemJSStrokeFillParams::method_get_strokeWidth,
+ QQuickPathItemJSStrokeFillParams::method_set_strokeWidth);
+ proto->defineAccessorProperty(QStringLiteral("fillColor"),
+ QQuickPathItemJSStrokeFillParams::method_get_fillColor,
+ QQuickPathItemJSStrokeFillParams::method_set_fillColor);
+ proto->defineAccessorProperty(QStringLiteral("fillRule"),
+ QQuickPathItemJSStrokeFillParams::method_get_fillRule,
+ QQuickPathItemJSStrokeFillParams::method_set_fillRule);
+ proto->defineAccessorProperty(QStringLiteral("joinStyle"),
+ QQuickPathItemJSStrokeFillParams::method_get_joinStyle,
+ QQuickPathItemJSStrokeFillParams::method_set_joinStyle);
+ proto->defineAccessorProperty(QStringLiteral("miterLimit"),
+ QQuickPathItemJSStrokeFillParams::method_get_miterLimit,
+ QQuickPathItemJSStrokeFillParams::method_set_miterLimit);
+ proto->defineAccessorProperty(QStringLiteral("capStyle"),
+ QQuickPathItemJSStrokeFillParams::method_get_capStyle,
+ QQuickPathItemJSStrokeFillParams::method_set_capStyle);
+ proto->defineAccessorProperty(QStringLiteral("strokeStyle"),
+ QQuickPathItemJSStrokeFillParams::method_get_strokeStyle,
+ QQuickPathItemJSStrokeFillParams::method_set_strokeStyle);
+ proto->defineAccessorProperty(QStringLiteral("dashOffset"),
+ QQuickPathItemJSStrokeFillParams::method_get_dashOffset,
+ QQuickPathItemJSStrokeFillParams::method_set_dashOffset);
+ proto->defineAccessorProperty(QStringLiteral("dashPattern"),
+ QQuickPathItemJSStrokeFillParams::method_get_dashPattern,
+ QQuickPathItemJSStrokeFillParams::method_set_dashPattern);
+ proto->defineAccessorProperty(QStringLiteral("fillGradient"),
+ QQuickPathItemJSStrokeFillParams::method_get_fillGradient,
+ QQuickPathItemJSStrokeFillParams::method_set_fillGradient);
+
+ strokeFillParamsProto = proto;
+}
+
+void QQuickPathItemPathObject::setV4Engine(QV4::ExecutionEngine *engine)
+{
+ QQuickPathItemJSEngineData *ed = engineData(engine);
+ QV4::Scope scope(engine);
+ QV4::Scoped<QQuickPathItemJSPath> wrapper(scope, engine->memoryManager->allocObject<QQuickPathItemJSPath>());
+ QV4::ScopedObject p(scope, ed->pathProto.value());
+ wrapper->setPrototype(p);
+ wrapper->d()->obj = this;
+ m_v4value = wrapper;
+}
+
+void QQuickPathItemPathObject::clear()
+{
+ path = QQuickPathItemPath();
+}
+
+void QQuickPathItemStrokeFillParamsObject::clear()
+{
+ sfp = QQuickPathItemStrokeFillParams();
+ if (!v4fillGradient.isNullOrUndefined())
+ v4fillGradient.set(v4fillGradient.engine(), nullptr);
+}
+
+void QQuickPathItemStrokeFillParamsObject::setV4Engine(QV4::ExecutionEngine *engine)
+{
+ QQuickPathItemJSEngineData *ed = engineData(engine);
+ QV4::Scope scope(engine);
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> wrapper(scope, engine->memoryManager->allocObject<QQuickPathItemJSStrokeFillParams>());
+ QV4::ScopedObject p(scope, ed->strokeFillParamsProto.value());
+ wrapper->setPrototype(p);
+ wrapper->d()->obj = this;
+ m_v4value = wrapper;
+}
+
+void QQuickPathItem::newPath(QQmlV4Function *args)
+{
+ QQuickPathItemPathObject *obj = new QQuickPathItemPathObject(this);
+ obj->setV4Engine(QQmlEnginePrivate::get(qmlEngine(this))->v4engine());
+ args->setReturnValue(obj->v4value());
+}
+
+void QQuickPathItem::newStrokeFillParams(QQmlV4Function *args)
+{
+ QQuickPathItemStrokeFillParamsObject *obj = new QQuickPathItemStrokeFillParamsObject(this);
+ obj->setV4Engine(QQmlEnginePrivate::get(qmlEngine(this))->v4engine());
+ args->setReturnValue(obj->v4value());
+}
+
+void QQuickPathItem::clearVisualPaths(QQmlV4Function *args)
+{
+ Q_UNUSED(args);
+ Q_D(QQuickPathItem);
+ d->jsData.paths.clear();
+ d->jsData.sfp.clear();
+}
+
+void QQuickPathItem::commitVisualPaths(QQmlV4Function *args)
+{
+ Q_UNUSED(args);
+ Q_D(QQuickPathItem);
+ d->_q_visualPathChanged();
+}
+
+void QQuickPathItem::appendVisualPath(QQmlV4Function *args)
+{
+ if (args->length() < 2)
+ return;
+
+ Q_D(QQuickPathItem);
+ QV4::Scope scope(args->v4engine());
+ QV4::Scoped<QQuickPathItemJSPath> jsp(scope, (*args)[0]);
+ QV4::Scoped<QQuickPathItemJSStrokeFillParams> jssfp(scope, (*args)[1]);
+
+ const QQuickPathItemPath &path(jsp->d()->obj->path);
+ const QQuickPathItemStrokeFillParams &sfp(jssfp->d()->obj->sfp);
+
+ d->jsData.paths.append(path);
+ d->jsData.sfp.append(sfp);
+}
+
QT_END_NAMESPACE
#include "moc_qquickpathitem_p.cpp"
diff --git a/src/quick/items/qquickpathitem_p.h b/src/quick/items/qquickpathitem_p.h
index 9ca1418d9e..991ab7a2bf 100644
--- a/src/quick/items/qquickpathitem_p.h
+++ b/src/quick/items/qquickpathitem_p.h
@@ -55,6 +55,7 @@
#include <private/qtquickglobal_p.h>
#include <private/qquickpath_p.h>
+#include <private/qv8engine_p.h>
#include <QGradientStops>
QT_REQUIRE_CONFIG(quick_path);
@@ -296,6 +297,12 @@ public:
QQmlListProperty<QQuickVisualPath> elements();
+ Q_INVOKABLE void newPath(QQmlV4Function *args);
+ Q_INVOKABLE void newStrokeFillParams(QQmlV4Function *args);
+ Q_INVOKABLE void clearVisualPaths(QQmlV4Function *args);
+ Q_INVOKABLE void commitVisualPaths(QQmlV4Function *args);
+ Q_INVOKABLE void appendVisualPath(QQmlV4Function *args);
+
protected:
QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *) override;
void updatePolish() override;
diff --git a/src/quick/items/qquickpathitem_p_p.h b/src/quick/items/qquickpathitem_p_p.h
index 3c63ec6dc2..091a453c0b 100644
--- a/src/quick/items/qquickpathitem_p_p.h
+++ b/src/quick/items/qquickpathitem_p_p.h
@@ -62,6 +62,39 @@ QT_BEGIN_NAMESPACE
class QSGPlainTexture;
+struct QQuickPathItemPath
+{
+ enum Command {
+ MoveTo,
+ LineTo,
+ QuadTo,
+ CubicTo,
+ ArcTo
+ };
+
+ QVector<Command> cmd;
+ QVector<float> coords;
+
+ QPainterPath toPainterPath() const;
+};
+
+struct QQuickPathItemStrokeFillParams
+{
+ QQuickPathItemStrokeFillParams();
+
+ QColor strokeColor;
+ qreal strokeWidth;
+ QColor fillColor;
+ QQuickVisualPath::FillRule fillRule;
+ QQuickVisualPath::JoinStyle joinStyle;
+ int miterLimit;
+ QQuickVisualPath::CapStyle capStyle;
+ QQuickVisualPath::StrokeStyle strokeStyle;
+ qreal dashOffset;
+ QVector<qreal> dashPattern;
+ QQuickPathGradient *fillGradient;
+};
+
class QQuickAbstractPathRenderer
{
public:
@@ -74,7 +107,14 @@ public:
// Gui thread
virtual void beginSync(int totalCount) = 0;
+ virtual void endSync(bool async) = 0;
+ virtual void setAsyncCallback(void (*)(void *), void *) { }
+ virtual Flags flags() const { return 0; }
+ // - QML API
virtual void setPath(int index, const QQuickPath *path) = 0;
+ // - JS API
+ virtual void setJSPath(int index, const QQuickPathItemPath &path) = 0;
+ // - stroke/fill parameters
virtual void setStrokeColor(int index, const QColor &color) = 0;
virtual void setStrokeWidth(int index, qreal w) = 0;
virtual void setFillColor(int index, const QColor &color) = 0;
@@ -84,9 +124,6 @@ public:
virtual void setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle,
qreal dashOffset, const QVector<qreal> &dashPattern) = 0;
virtual void setFillGradient(int index, QQuickPathGradient *gradient) = 0;
- virtual void endSync(bool async) = 0;
- virtual void setAsyncCallback(void (*)(void *), void *) { }
- virtual Flags flags() const { return 0; }
// Render thread, with gui blocked
virtual void updateNode() = 0;
@@ -121,17 +158,7 @@ public:
QQuickPath *path;
int dirty;
- QColor strokeColor;
- qreal strokeWidth;
- QColor fillColor;
- QQuickVisualPath::FillRule fillRule;
- QQuickVisualPath::JoinStyle joinStyle;
- int miterLimit;
- QQuickVisualPath::CapStyle capStyle;
- QQuickVisualPath::StrokeStyle strokeStyle;
- qreal dashOffset;
- QVector<qreal> dashPattern;
- QQuickPathGradient *fillGradient;
+ QQuickPathItemStrokeFillParams sfp;
};
class QQuickPathItemPrivate : public QQuickItemPrivate
@@ -157,7 +184,53 @@ public:
bool async;
QQuickPathItem::Status status;
QQuickAbstractPathRenderer *renderer;
- QVector<QQuickVisualPath *> vp;
+
+ struct {
+ QVector<QQuickVisualPath *> vp;
+ } qmlData;
+
+ struct {
+ bool isValid() const { Q_ASSERT(paths.count() == sfp.count()); return !paths.isEmpty(); }
+ QVector<QQuickPathItemPath> paths;
+ QVector<QQuickPathItemStrokeFillParams> sfp;
+ } jsData;
+};
+
+class QQuickPathItemPathObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ QQuickPathItemPathObject(QObject *parent = nullptr) : QObject(parent) { }
+
+ void setV4Engine(QV4::ExecutionEngine *engine);
+ QV4::ReturnedValue v4value() const { return m_v4value.value(); }
+
+ QQuickPathItemPath path;
+
+ void clear();
+
+private:
+ QV4::PersistentValue m_v4value;
+};
+
+class QQuickPathItemStrokeFillParamsObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ QQuickPathItemStrokeFillParamsObject(QObject *parent = nullptr) : QObject(parent) { }
+
+ void setV4Engine(QV4::ExecutionEngine *engine);
+ QV4::ReturnedValue v4value() const { return m_v4value.value(); }
+
+ QQuickPathItemStrokeFillParams sfp;
+ QV4::PersistentValue v4fillGradient;
+
+ void clear();
+
+private:
+ QV4::PersistentValue m_v4value;
};
#ifndef QT_NO_OPENGL
diff --git a/src/quick/items/qquickpathitemgenericrenderer.cpp b/src/quick/items/qquickpathitemgenericrenderer.cpp
index 3de01a5bc7..a76a5e2b43 100644
--- a/src/quick/items/qquickpathitemgenericrenderer.cpp
+++ b/src/quick/items/qquickpathitemgenericrenderer.cpp
@@ -178,6 +178,13 @@ void QQuickPathItemGenericRenderer::setPath(int index, const QQuickPath *path)
d.syncDirty |= DirtyFillGeom | DirtyStrokeGeom;
}
+void QQuickPathItemGenericRenderer::setJSPath(int index, const QQuickPathItemPath &path)
+{
+ VisualPathData &d(m_vp[index]);
+ d.path = path.toPainterPath();
+ d.syncDirty |= DirtyFillGeom | DirtyStrokeGeom;
+}
+
void QQuickPathItemGenericRenderer::setStrokeColor(int index, const QColor &color)
{
VisualPathData &d(m_vp[index]);
diff --git a/src/quick/items/qquickpathitemgenericrenderer_p.h b/src/quick/items/qquickpathitemgenericrenderer_p.h
index 045c52d610..70a9e88d2f 100644
--- a/src/quick/items/qquickpathitemgenericrenderer_p.h
+++ b/src/quick/items/qquickpathitemgenericrenderer_p.h
@@ -87,6 +87,7 @@ public:
void beginSync(int totalCount) override;
void setPath(int index, const QQuickPath *path) override;
+ void setJSPath(int index, const QQuickPathItemPath &path) override;
void setStrokeColor(int index, const QColor &color) override;
void setStrokeWidth(int index, qreal w) override;
void setFillColor(int index, const QColor &color) override;
diff --git a/src/quick/items/qquickpathitemnvprrenderer.cpp b/src/quick/items/qquickpathitemnvprrenderer.cpp
index 13fab2dc76..f8504f9985 100644
--- a/src/quick/items/qquickpathitemnvprrenderer.cpp
+++ b/src/quick/items/qquickpathitemnvprrenderer.cpp
@@ -62,6 +62,14 @@ void QQuickPathItemNvprRenderer::setPath(int index, const QQuickPath *path)
m_accDirty |= DirtyPath;
}
+void QQuickPathItemNvprRenderer::setJSPath(int index, const QQuickPathItemPath &path)
+{
+ VisualPathGuiData &d(m_vp[index]);
+ convertJSPath(path, &d);
+ d.dirty |= DirtyPath;
+ m_accDirty |= DirtyPath;
+}
+
void QQuickPathItemNvprRenderer::setStrokeColor(int index, const QColor &color)
{
VisualPathGuiData &d(m_vp[index]);
@@ -288,6 +296,82 @@ void QQuickPathItemNvprRenderer::convertPath(const QQuickPath *path, VisualPathG
d->path.cmd.append(GL_CLOSE_PATH_NV);
}
+void QQuickPathItemNvprRenderer::convertJSPath(const QQuickPathItemPath &path, VisualPathGuiData *d)
+{
+ d->path = NvprPath();
+ if (path.cmd.isEmpty())
+ return;
+
+ QPointF startPos(0, 0);
+ QPointF pos(startPos);
+ int coordIdx = 0;
+
+ for (QQuickPathItemPath::Command cmd : path.cmd) {
+ switch (cmd) {
+ case QQuickPathItemPath::MoveTo:
+ d->path.cmd.append(GL_MOVE_TO_NV);
+ pos = QPointF(path.coords[coordIdx], path.coords[coordIdx + 1]);
+ startPos = pos;
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 2;
+ break;
+ case QQuickPathItemPath::LineTo:
+ d->path.cmd.append(GL_LINE_TO_NV);
+ pos = QPointF(path.coords[coordIdx], path.coords[coordIdx + 1]);
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 2;
+ break;
+ case QQuickPathItemPath::QuadTo:
+ d->path.cmd.append(GL_QUADRATIC_CURVE_TO_NV);
+ d->path.coord.append(path.coords[coordIdx]);
+ d->path.coord.append(path.coords[coordIdx + 1]);
+ pos = QPointF(path.coords[coordIdx + 2], path.coords[coordIdx + 3]);
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 4;
+ break;
+ case QQuickPathItemPath::CubicTo:
+ d->path.cmd.append(GL_CUBIC_CURVE_TO_NV);
+ d->path.coord.append(path.coords[coordIdx]);
+ d->path.coord.append(path.coords[coordIdx + 1]);
+ d->path.coord.append(path.coords[coordIdx + 2]);
+ d->path.coord.append(path.coords[coordIdx + 3]);
+ pos = QPointF(path.coords[coordIdx + 4], path.coords[coordIdx + 5]);
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 6;
+ break;
+ case QQuickPathItemPath::ArcTo:
+ {
+ const bool sweepFlag = !qFuzzyIsNull(path.coords[coordIdx + 5]);
+ const bool useLargeArc = !qFuzzyIsNull(path.coords[coordIdx + 6]);
+ GLenum cmd;
+ if (useLargeArc)
+ cmd = sweepFlag ? GL_LARGE_CCW_ARC_TO_NV : GL_LARGE_CW_ARC_TO_NV;
+ else
+ cmd = sweepFlag ? GL_SMALL_CCW_ARC_TO_NV : GL_SMALL_CW_ARC_TO_NV;
+ d->path.cmd.append(cmd);
+ d->path.coord.append(path.coords[coordIdx]); // rx
+ d->path.coord.append(path.coords[coordIdx + 1]); // ry
+ d->path.coord.append(path.coords[coordIdx + 2]); // xrot
+ pos = QPointF(path.coords[coordIdx + 3], path.coords[coordIdx + 4]);
+ d->path.coord.append(pos.x());
+ d->path.coord.append(pos.y());
+ coordIdx += 7;
+ }
+ break;
+ default:
+ qWarning("Unknown JS path command: %d", cmd);
+ break;
+ }
+ }
+
+ if (pos == startPos)
+ d->path.cmd.append(GL_CLOSE_PATH_NV);
+}
+
static inline QVector4D qsg_premultiply(const QColor &c, float globalOpacity)
{
const float o = c.alphaF() * globalOpacity;
diff --git a/src/quick/items/qquickpathitemnvprrenderer_p.h b/src/quick/items/qquickpathitemnvprrenderer_p.h
index 61f8b5ebb9..deab9cf7f9 100644
--- a/src/quick/items/qquickpathitemnvprrenderer_p.h
+++ b/src/quick/items/qquickpathitemnvprrenderer_p.h
@@ -81,6 +81,7 @@ public:
void beginSync(int totalCount) override;
void setPath(int index, const QQuickPath *path) override;
+ void setJSPath(int index, const QQuickPathItemPath &path) override;
void setStrokeColor(int index, const QColor &color) override;
void setStrokeWidth(int index, qreal w) override;
void setFillColor(int index, const QColor &color) override;
@@ -121,6 +122,7 @@ private:
};
void convertPath(const QQuickPath *path, VisualPathGuiData *d);
+ void convertJSPath(const QQuickPathItemPath &path, VisualPathGuiData *d);
QQuickPathItemNvprRenderNode *m_node = nullptr;
int m_accDirty = 0;
diff --git a/src/quick/items/qquickpathitemsoftwarerenderer.cpp b/src/quick/items/qquickpathitemsoftwarerenderer.cpp
index 46ebcbfe6d..b7aa93bf65 100644
--- a/src/quick/items/qquickpathitemsoftwarerenderer.cpp
+++ b/src/quick/items/qquickpathitemsoftwarerenderer.cpp
@@ -58,6 +58,14 @@ void QQuickPathItemSoftwareRenderer::setPath(int index, const QQuickPath *path)
m_accDirty |= DirtyPath;
}
+void QQuickPathItemSoftwareRenderer::setJSPath(int index, const QQuickPathItemPath &path)
+{
+ VisualPathGuiData &d(m_vp[index]);
+ d.path = path.toPainterPath();
+ d.dirty |= DirtyPath;
+ m_accDirty |= DirtyPath;
+}
+
void QQuickPathItemSoftwareRenderer::setStrokeColor(int index, const QColor &color)
{
VisualPathGuiData &d(m_vp[index]);
diff --git a/src/quick/items/qquickpathitemsoftwarerenderer_p.h b/src/quick/items/qquickpathitemsoftwarerenderer_p.h
index 64280b436e..e76590bdfe 100644
--- a/src/quick/items/qquickpathitemsoftwarerenderer_p.h
+++ b/src/quick/items/qquickpathitemsoftwarerenderer_p.h
@@ -73,6 +73,7 @@ public:
void beginSync(int totalCount) override;
void setPath(int index, const QQuickPath *path) override;
+ void setJSPath(int index, const QQuickPathItemPath &path) override;
void setStrokeColor(int index, const QColor &color) override;
void setStrokeWidth(int index, qreal w) override;
void setFillColor(int index, const QColor &color) override;