aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@digia.com>2014-02-26 15:27:23 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-28 02:36:18 +0100
commit3f88a5b835198e39e899bc77d798f48f0fe593bb (patch)
tree72f7a88b6fa21ee7d80da599c113e75be3be4d16 /src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
parent78cee4eb22ee6b0b61f5d89c98f15e61e7c52078 (diff)
Fix renderType: Text.NativeRendering on retina screens
The QSGDefaultGlyphNode's QSGTextMaskMaterial failed to take the device pixel ratio of the surface into account, both when building the glyph cache in init() and when blitting the glyphs from the cache in populate(). We now handle both, resulting in equal rendering as the raster engine, which itself matches CoreText, except for some minor shaping differences. One snag with the QSGTextMaskMaterial compared to eg. the raster engine is that the incoming glyph positions (from shaping) are not pre-scaled, which means we have to be careful to apply the device pixel ratio before rounding the coordinates, to match the behavior of the raster engine. Change-Id: I51cf796bd437f68fad298f689ee3f2d9a2863b4d Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
Diffstat (limited to 'src/quick/scenegraph/qsgdefaultglyphnode_p.cpp')
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp51
1 files changed, 39 insertions, 12 deletions
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 3267eeed83..300741bc0a 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -366,19 +366,27 @@ void QSGTextMaskMaterial::init(QFontEngine::GlyphFormat glyphFormat)
// sequence. See also QSGRenderContext::invalidate
QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
- if (fontD->fontEngine != 0) {
+ if (QFontEngine *fontEngine = fontD->fontEngine) {
if (glyphFormat == QFontEngine::Format_None) {
- glyphFormat = fontD->fontEngine->glyphFormat != QFontEngine::Format_None
- ? fontD->fontEngine->glyphFormat
+ glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None
+ ? fontEngine->glyphFormat
: QFontEngine::Format_A32;
}
- m_glyphCache = fontD->fontEngine->glyphCache(ctx, glyphFormat, QTransform());
+
+ qreal devicePixelRatio = ctx->surface()->surfaceClass() == QSurface::Window ?
+ static_cast<QWindow *>(ctx->surface())->devicePixelRatio() : ctx->screen()->devicePixelRatio();
+
+ QTransform glyphCacheTransform = QTransform::fromScale(devicePixelRatio, devicePixelRatio);
+ if (!fontEngine->supportsTransformation(glyphCacheTransform))
+ glyphCacheTransform = QTransform();
+
+ m_glyphCache = fontEngine->glyphCache(ctx, glyphFormat, glyphCacheTransform);
if (!m_glyphCache || int(m_glyphCache->glyphFormat()) != glyphFormat) {
- m_glyphCache = new QOpenGLTextureGlyphCache(glyphFormat, QTransform());
- fontD->fontEngine->setGlyphCache(ctx, m_glyphCache.data());
+ m_glyphCache = new QOpenGLTextureGlyphCache(glyphFormat, glyphCacheTransform);
+ fontEngine->setGlyphCache(ctx, m_glyphCache.data());
QSGRenderContext *sg = QSGRenderContext::from(ctx);
Q_ASSERT(sg);
- sg->registerFontengineForCleanup(fontD->fontEngine);
+ sg->registerFontengineForCleanup(fontEngine);
}
}
}
@@ -405,6 +413,11 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
int margin = fontD->fontEngine->glyphMargin(cache->glyphFormat());
+ qreal glyphCacheScaleX = cache->transform().m11();
+ qreal glyphCacheScaleY = cache->transform().m22();
+ qreal glyphCacheInverseScaleX = 1.0 / glyphCacheScaleX;
+ qreal glyphCacheInverseScaleY = 1.0 / glyphCacheScaleY;
+
Q_ASSERT(geometry->indexType() == GL_UNSIGNED_SHORT);
geometry->allocate(glyphIndexes.size() * 4, glyphIndexes.size() * 6);
QVector4D *vp = (QVector4D *)geometry->vertexDataAsTexturedPoint2D();
@@ -420,17 +433,31 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i), subPixelPosition);
const QTextureGlyphCache::Coord &c = cache->coords.value(glyph);
+ if (c.isNull())
+ continue;
QPointF glyphPosition = glyphPositions.at(i) + position;
- int x = qFloor(glyphPosition.x()) + c.baseLineX - margin;
- int y = qFloor(glyphPosition.y()) - c.baseLineY - margin;
- *boundingRect |= QRectF(x + margin, y + margin, c.w, c.h);
+ // On a retina screen the glyph positions are not pre-scaled (as opposed to
+ // eg. the raster paint engine). To ensure that we get the same behavior as
+ // the raster engine (and CoreText itself) when it comes to rounding of the
+ // coordinates, we need to apply the scale factor before rounding, and then
+ // apply the inverse scale to get back to the coordinate system of the node.
+
+ qreal x = (qFloor(glyphPosition.x() * glyphCacheScaleX) * glyphCacheInverseScaleX) +
+ (c.baseLineX * glyphCacheInverseScaleX) - margin;
+ qreal y = (qRound(glyphPosition.y() * glyphCacheScaleY) * glyphCacheInverseScaleY) -
+ (c.baseLineY * glyphCacheInverseScaleY) - margin;
+
+ qreal w = c.w * glyphCacheInverseScaleX;
+ qreal h = c.h * glyphCacheInverseScaleY;
+
+ *boundingRect |= QRectF(x + margin, y + margin, w, h);
float cx1 = x - margins.left();
- float cx2 = x + c.w + margins.right();
+ float cx2 = x + w + margins.right();
float cy1 = y - margins.top();
- float cy2 = y + c.h + margins.bottom();
+ float cy2 = y + h + margins.bottom();
float tx1 = c.x - margins.left();
float tx2 = c.x + c.w + margins.right();