diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-01-24 18:27:27 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-01-27 09:12:28 +0000 |
commit | a48244d5aa1d14c286b7cd39afebcfff9c9dcb60 (patch) | |
tree | 7acd17b061bf6f5afccc4f737e11704ebf035acd /src/quick/items/qquickpathitemnvprrenderer.cpp | |
parent | 00d3f3e9da071efce92d320884b331ea559fb292 (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/qquickpathitemnvprrenderer.cpp')
-rw-r--r-- | src/quick/items/qquickpathitemnvprrenderer.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
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; |