diff options
author | Andy Nichols <andy.nichols@qt.io> | 2016-11-29 15:29:39 +0100 |
---|---|---|
committer | Andy Nichols <andy.nichols@qt.io> | 2016-12-13 15:43:24 +0000 |
commit | 0119439c9d25dfd892bbee47068e9d726f4bff97 (patch) | |
tree | 71df5718b21cd1471eb6cb4c4eac4c19a691f869 /src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp | |
parent | 3f57f2b7cc3899af154257a3c858bd23d9f03a62 (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/qsgopenvgpublicnodes.cpp')
-rw-r--r-- | src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp index f5890210a9..1afc5ea7ca 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp +++ b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp @@ -73,10 +73,33 @@ void QSGOpenVGRectangleNode::setColor(const QColor &color) markDirty(DirtyMaterial); } +void QSGOpenVGRectangleNode::setTransform(const QOpenVGMatrix &transform) +{ + // if there transform matrix is not affine, regenerate the path + if (transform.isAffine()) + m_pathDirty = true; + markDirty(DirtyGeometry); + + QSGOpenVGRenderable::setTransform(transform); +} + void QSGOpenVGRectangleNode::render() { + // Set Transform + if (transform().isAffine()) { + // Use current transform matrix + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadMatrix(transform().constData()); + } else { + // map the path's to handle the perspective matrix + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadIdentity(); + } + if (m_pathDirty) { vgClearPath(m_rectPath, VG_PATH_CAPABILITY_APPEND_TO); + + if (transform().isAffine()) { // Create command list static const VGubyte rectCommands[] = { VG_MOVE_TO_ABS, @@ -95,6 +118,34 @@ void QSGOpenVGRectangleNode::render() coordinates[4] = -m_rect.width(); vgAppendPathData(m_rectPath, 5, rectCommands, coordinates.constData()); + + } else { + // Pre-transform path + static const VGubyte rectCommands[] = { + VG_MOVE_TO_ABS, + VG_LINE_TO_ABS, + VG_LINE_TO_ABS, + VG_LINE_TO_ABS, + VG_CLOSE_PATH + }; + + QVector<VGfloat> coordinates(8); + const QPointF topLeft = transform().map(m_rect.topLeft()); + const QPointF topRight = transform().map(m_rect.topRight()); + const QPointF bottomLeft = transform().map(m_rect.bottomLeft()); + const QPointF bottomRight = transform().map(m_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(m_rectPath, 5, rectCommands, coordinates.constData()); + } + m_pathDirty = false; } @@ -155,6 +206,10 @@ void QSGOpenVGImageNode::render() vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL); } + // Set Transform + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + vgLoadMatrix(transform().constData()); + VGImage image = static_cast<VGImage>(m_texture->textureId()); //Apply the TextureCoordinateTransform Flag @@ -251,6 +306,10 @@ void QSGOpenVGNinePatchNode::render() vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL); } + // Set Transform + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + vgLoadMatrix(transform().constData()); + VGImage image = static_cast<VGImage>(m_texture->textureId()); //Draw borderImage |