From e70f21152aa8b2459c903db0cf4ca30bde5bd178 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 Mar 2013 14:21:04 +0100 Subject: [PATCH] Fix rendering of subpixel positioned native text To get accurate sampling of the native text rendering, we use nearest filtering. This, however, does not work well when we're sampling in the middle of pixels and the result is that with text which is positioned at 0.5 offsets, we will sample the wrong pixels and get artifacts from this. The main use case for native rendered text is unrotated and unscaled text, so we fix this use case by pixel-aligning the translation factor. Done-with: Samuel Task-number: QTBUG-30022 Change-Id: I6911196d6ff491dca3b329c42da1c6dd7263cff0 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/coreapi/qsgmaterial.cpp | 10 +++++++++ src/quick/scenegraph/coreapi/qsgmaterial.h | 1 + src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 26 +++++++++++++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp index f678504..11ce987 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp @@ -442,6 +442,16 @@ QMatrix4x4 QSGMaterialShader::RenderState::modelViewMatrix() const return static_cast(m_data)->currentModelViewMatrix(); } +/*! + Returns the projection matrix. + */ + +QMatrix4x4 QSGMaterialShader::RenderState::projectionMatrix() const +{ + Q_ASSERT(m_data); + return static_cast(m_data)->currentProjectionMatrix(); +} + /*! diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.h b/src/quick/scenegraph/coreapi/qsgmaterial.h index 50e9c77..238bf83 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.h +++ b/src/quick/scenegraph/coreapi/qsgmaterial.h @@ -69,6 +69,7 @@ public: float opacity() const; QMatrix4x4 combinedMatrix() const; QMatrix4x4 modelViewMatrix() const; + QMatrix4x4 projectionMatrix() const; QRect viewportRect() const; QRect deviceRect() const; float determinant() const; diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index 6b8f992..b65686e6 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -178,7 +178,7 @@ void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial 1.0 / material->cacheTextureHeight())); glBindTexture(GL_TEXTURE_2D, material->texture()->textureId()); - // Set the mag/min filters to be linear. We only need to do this when the texture + // Set the mag/min filters to be nearest. We only need to do this when the texture // has been recreated. if (updated) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -186,8 +186,28 @@ void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial } } - if (state.isMatrixDirty()) - program()->setUniformValue(m_matrix_id, state.combinedMatrix()); + if (state.isMatrixDirty()) { + QMatrix4x4 transform = state.modelViewMatrix(); + qreal xTranslation = transform(0, 3); + qreal yTranslation = transform(1, 3); + + // Remove translation and check identity to see if matrix is only translating. + // If it is, we can round the translation to make sure the text is pixel aligned, + // which is the only thing that works with GL_NEAREST filtering. Adding rotations + // and scales to native rendered text is not a prioritized use case, since the + // default rendering type is designed for that. + transform(0, 3) = 0.0; + transform(1, 3) = 0.0; + if (transform.isIdentity()) { + transform(0, 3) = qRound(xTranslation); + transform(1, 3) = qRound(yTranslation); + + transform = state.projectionMatrix() * transform; + program()->setUniformValue(m_matrix_id, transform); + } else { + program()->setUniformValue(m_matrix_id, state.combinedMatrix()); + } + } } QSGTextMaskMaterial::QSGTextMaskMaterial(const QRawFont &font) -- 1.7.2.5