diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com> | 2014-08-26 10:52:22 +0200 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com> | 2014-09-10 13:52:07 +0200 |
commit | a9238292145e05d36be7c35bdd50829c6400a3de (patch) | |
tree | d5bca3fa163215f7b4bb1cba63018da7492d91c9 /src/quick/scenegraph/qsgdefaultimagenode.cpp | |
parent | f9ee33f9683a4cd4d1a2e41efa6e8d124e9d731d (diff) |
Fix pixel bleed in BorderImage
Keeping all patches of the border image in the same texture
with different sample points can cause parts of the border
to bleed over to the center patch. To rectify this, we
create a separate texture for each of the nine patches we
need, and separate image nodes.
To avoid applying antialiasing on the interior edges of the
border image, we introduce new antialiasing flags which can
be used to specify precisely which edges of the image should
be antialiased.
[ChangeLog][BorderImage] Fixed possible pixel bleed between
border patches and center patch in BorderImage.
Change-Id: Icc292b3969217320eecca99e79675316c42eab08
Task-number: QTBUG-35838
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
Diffstat (limited to 'src/quick/scenegraph/qsgdefaultimagenode.cpp')
-rw-r--r-- | src/quick/scenegraph/qsgdefaultimagenode.cpp | 57 |
1 files changed, 48 insertions, 9 deletions
diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp index 7f85c31ccb..69df506d2a 100644 --- a/src/quick/scenegraph/qsgdefaultimagenode.cpp +++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp @@ -140,10 +140,11 @@ void SmoothTextureMaterialShader::initialize() QSGDefaultImageNode::QSGDefaultImageNode() : m_innerSourceRect(0, 0, 1, 1) , m_subSourceRect(0, 0, 1, 1) - , m_antialiasing(false) , m_mirror(false) , m_dirtyGeometry(false) , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) + , m_antialiasing(AntialiasingNone) + { setMaterial(&m_materialO); setOpaqueMaterial(&m_material); @@ -249,10 +250,20 @@ void QSGDefaultImageNode::setTexture(QSGTexture *texture) void QSGDefaultImageNode::setAntialiasing(bool antialiasing) { - if (antialiasing == m_antialiasing) + AntialiasingFlags antialiasingFlags = antialiasing + ? AntialiasingAll + : AntialiasingNone; + + setAntialiasing(antialiasingFlags); +} + +void QSGDefaultImageNode::setAntialiasing(AntialiasingFlags antialiasingFlags) +{ + if (antialiasingFlags == m_antialiasing) return; - m_antialiasing = antialiasing; - if (m_antialiasing) { + + m_antialiasing = antialiasingFlags; + if (m_antialiasing != AntialiasingNone) { setMaterial(&m_smoothMaterial); setOpaqueMaterial(0); setGeometry(new QSGGeometry(smoothAttributeSet(), 0)); @@ -364,11 +375,14 @@ void QSGDefaultImageNode::updateGeometry() } // An image can be rendered as a single quad if: + // - There is antialiasing on all or no edges // - There are no margins, and either: // - the image isn't repeated // - the source rectangle fills the entire texture so that texture wrapping can be used, // and NPOT is supported - if (!hasMargins && (!hasTiles || (fullTexture && wrapSupported))) { + if (!hasMargins + && (m_antialiasing == AntialiasingAll || m_antialiasing == AntialiasingNone) + && (!hasTiles || (fullTexture && wrapSupported))) { QRectF sr; if (!fullTexture) { sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(), @@ -547,10 +561,35 @@ void QSGDefaultImageNode::updateGeometry() topDv = bottomDv *= 0.5f; } + if (!m_antialiasing.testFlag(AntialiasingTop)) { + topDy = 0.0f; + topDv = 0.0f; + } + + if (!m_antialiasing.testFlag(AntialiasingBottom)) { + bottomDy = 0.0f; + bottomDv = 0.0f; + } + + if (!m_antialiasing.testFlag(AntialiasingLeft)) { + leftDx = 0.0f; + leftDu = 0.0f; + } + + if (!m_antialiasing.testFlag(AntialiasingRight)) { + rightDx = 0.0f; + rightDu = 0.0f; + } + // This delta is how much the fuzziness can reach out from the image. float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height()) ? m_targetRect.width() : m_targetRect.height()) * 0.5f; + float deltaTop = m_antialiasing.testFlag(AntialiasingTop) ? delta : 0.0f; + float deltaBottom = m_antialiasing.testFlag(AntialiasingBottom) ? delta : 0.0f; + float deltaLeft = m_antialiasing.testFlag(AntialiasingLeft) ? delta : 0.0f; + float deltaRight = m_antialiasing.testFlag(AntialiasingRight) ? delta : 0.0f; + quint16 index = 0; ys = yData.data(); for (int j = 0; j < vCells; ++j, ys += 2) { @@ -600,28 +639,28 @@ void QSGDefaultImageNode::updateGeometry() if (isTop) { vertices[topLeft].dy = vertices[topRight].dy = topDy; vertices[topLeft].dv = vertices[topRight].dv = topDv; - vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta; + vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -deltaTop; appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight); } if (isBottom) { vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy; vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv; - vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta; + vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = deltaBottom; appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1); } if (isLeft) { vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx; vertices[topLeft].du = vertices[bottomLeft].du = leftDu; - vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta; + vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -deltaLeft; appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft); } if (isRight) { vertices[topRight].dx = vertices[bottomRight].dx = -rightDx; vertices[topRight].du = vertices[bottomRight].du = -rightDu; - vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta; + vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = deltaRight; appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1); } } |