aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp
diff options
context:
space:
mode:
authorAndy Nichols <andy.nichols@qt.io>2016-11-29 15:29:39 +0100
committerAndy Nichols <andy.nichols@qt.io>2016-12-13 15:43:24 +0000
commit0119439c9d25dfd892bbee47068e9d726f4bff97 (patch)
tree71df5718b21cd1471eb6cb4c4eac4c19a691f869 /src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp
parent3f57f2b7cc3899af154257a3c858bd23d9f03a62 (diff)
OpenVG: Support rendering paths with non-affine transforms
The current approach to rendering paths (used by Rectangles and Glyph nodes) does not support rendering with non-affine transformations. That is because OpenVG does not support passing a non-affine transformation matrix when rendering paths. So instead when using a non-affine transform we will fallback to rendering to an offscreen VGImage, then rendering that as an image which can have a perspective transform. Change-Id: I01508bcb67b339323cb6400c7ff6d885b62c5e02 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp')
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp60
1 files changed, 26 insertions, 34 deletions
diff --git a/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp b/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp
index fc9f5eb57c..8aa179f705 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp
+++ b/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp
@@ -93,12 +93,11 @@ bool QSGOpenVGNodeVisitor::visit(QSGClipNode *node)
// Render clip node geometry to mask
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
- vgLoadMatrix(m_transformStack.top().constData());
+ vgLoadIdentity();
VGPath clipPath = generateClipPath(node->clipRect());
vgRenderToMask(clipPath, VG_FILL_PATH, maskOperation);
- auto clipState = new ClipState(clipPath, m_transformStack.top());
- m_clipStack.push(clipState);
+ m_clipStack.push(clipPath);
return true;
}
@@ -107,29 +106,23 @@ void QSGOpenVGNodeVisitor::endVisit(QSGClipNode *)
{
// Remove clip node geometry from mask
auto clipState = m_clipStack.pop();
- vgDestroyPath(clipState->path);
+ vgDestroyPath(clipState);
if (m_clipStack.count() == 0) {
vgSeti(VG_MASKING, VG_FALSE);
} else {
// Recreate the mask
vgMask(0,VG_FILL_MASK, 0, 0, VG_MAXINT, VG_MAXINT);
- for (auto state : m_clipStack) {
- vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
- vgLoadMatrix(state->transform.constData());
- vgRenderToMask(state->path, VG_FILL_PATH, VG_INTERSECT_MASK);
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+ vgLoadIdentity();
+ for (auto path : qAsConst(m_clipStack)) {
+ vgRenderToMask(path, VG_FILL_PATH, VG_INTERSECT_MASK);
}
}
-
- delete clipState;
}
bool QSGOpenVGNodeVisitor::visit(QSGGeometryNode *node)
{
- vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
- vgLoadMatrix(m_transformStack.top().constData());
- vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
- vgLoadMatrix(m_transformStack.top().constData());
if (QSGSimpleRectNode *rectNode = dynamic_cast<QSGSimpleRectNode *>(node)) {
// TODO: Try and render the QSGSimpleRectNode
Q_UNUSED(rectNode)
@@ -169,8 +162,6 @@ void QSGOpenVGNodeVisitor::endVisit(QSGOpacityNode *)
bool QSGOpenVGNodeVisitor::visit(QSGInternalImageNode *node)
{
- vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
- vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGInternalImageNode*>(node));
return true;
}
@@ -181,8 +172,6 @@ void QSGOpenVGNodeVisitor::endVisit(QSGInternalImageNode *)
bool QSGOpenVGNodeVisitor::visit(QSGPainterNode *node)
{
- vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
- vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGPainterNode*>(node));
return true;
}
@@ -193,8 +182,6 @@ void QSGOpenVGNodeVisitor::endVisit(QSGPainterNode *)
bool QSGOpenVGNodeVisitor::visit(QSGInternalRectangleNode *node)
{
- vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
- vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGInternalRectangleNode*>(node));
return true;
}
@@ -205,8 +192,6 @@ void QSGOpenVGNodeVisitor::endVisit(QSGInternalRectangleNode *)
bool QSGOpenVGNodeVisitor::visit(QSGGlyphNode *node)
{
- vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
- vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGGlyphNode*>(node));
return true;
}
@@ -226,8 +211,6 @@ void QSGOpenVGNodeVisitor::endVisit(QSGRootNode *)
bool QSGOpenVGNodeVisitor::visit(QSGSpriteNode *node)
{
- vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
- vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGSpriteNode*>(node));
return true;
}
@@ -253,19 +236,28 @@ VGPath QSGOpenVGNodeVisitor::generateClipPath(const QRectF &rect) const
// Create command list
static const VGubyte rectCommands[] = {
VG_MOVE_TO_ABS,
- VG_HLINE_TO_REL,
- VG_VLINE_TO_REL,
- VG_HLINE_TO_REL,
+ VG_LINE_TO_ABS,
+ VG_LINE_TO_ABS,
+ VG_LINE_TO_ABS,
VG_CLOSE_PATH
};
+ const QOpenVGMatrix &transform = m_transformStack.top();
+
// Create command data
- QVector<VGfloat> coordinates(5);
- coordinates[0] = rect.x();
- coordinates[1] = rect.y();
- coordinates[2] = rect.width();
- coordinates[3] = rect.height();
- coordinates[4] = -rect.width();
+ QVector<VGfloat> coordinates(8);
+ const QPointF topLeft = transform.map(rect.topLeft());
+ const QPointF topRight = transform.map(rect.topRight());
+ const QPointF bottomLeft = transform.map(rect.bottomLeft());
+ const QPointF bottomRight = transform.map(rect.bottomRight());
+ coordinates[0] = bottomLeft.x();
+ coordinates[1] = bottomLeft.y();
+ coordinates[2] = bottomRight.x();
+ coordinates[3] = bottomRight.y();
+ coordinates[4] = topRight.x();
+ coordinates[5] = topRight.y();
+ coordinates[6] = topLeft.x();
+ coordinates[7] = topLeft.y();
vgAppendPathData(clipPath, 5, rectCommands, coordinates.constData());
return clipPath;
@@ -275,7 +267,7 @@ void QSGOpenVGNodeVisitor::renderRenderableNode(QSGOpenVGRenderable *node)
{
if (!node)
return;
-
+ node->setTransform(m_transformStack.top());
node->setOpacity(m_opacityState.top());
node->render();
}