Add support for retina glyph-based text drawing in the GL paint-engine
Instead of always using a non-transformed glyph-cache we now allow a scaled glyph-cache so that retina-screens can take advantage of this. We take the cache's scale into account when positioning and drawing the glyphs so that the scale is not applied twice. Change-Id: Ia927656f0070df61e78da76e97d2c49de4d856d9 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
This commit is contained in:
parent
04773fe72e
commit
b5922c89ba
@ -1069,6 +1069,18 @@ void QOpenGL2PaintEngineExPrivate::resetClipIfNeeded()
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
}
|
||||
|
||||
bool QOpenGL2PaintEngineExPrivate::prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache)
|
||||
{
|
||||
Q_Q(QOpenGL2PaintEngineEx);
|
||||
|
||||
QTransform &transform = q->state()->matrix;
|
||||
transform.scale(1.0 / cache.transform().m11(), 1.0 / cache.transform().m22());
|
||||
bool ret = prepareForDraw(false);
|
||||
transform.scale(cache.transform().m11(), cache.transform().m22());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool QOpenGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
|
||||
{
|
||||
if (brushTextureDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
|
||||
@ -1543,10 +1555,14 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
|
||||
bool recreateVertexArrays = false;
|
||||
QFontEngine *fe = staticTextItem->fontEngine();
|
||||
|
||||
// We allow scaling, so that the glyph-cache will contain glyphs with the
|
||||
// appropriate resolution in the case of displays with a device-pixel-ratio != 1.
|
||||
QTransform transform = QTransform::fromScale(s->matrix.m11(), s->matrix.m22());
|
||||
|
||||
QOpenGLTextureGlyphCache *cache =
|
||||
(QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, QTransform());
|
||||
(QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, transform);
|
||||
if (!cache || cache->cacheType() != glyphType || cache->contextGroup() == 0) {
|
||||
cache = new QOpenGLTextureGlyphCache(glyphType, QTransform());
|
||||
cache = new QOpenGLTextureGlyphCache(glyphType, transform);
|
||||
fe->setGlyphCache(cacheKey, cache);
|
||||
recreateVertexArrays = true;
|
||||
}
|
||||
@ -1638,8 +1654,8 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
|
||||
if (c.isNull())
|
||||
continue;
|
||||
|
||||
int x = qFloor(staticTextItem->glyphPositions[i].x) + c.baseLineX - margin;
|
||||
int y = qRound(staticTextItem->glyphPositions[i].y) - c.baseLineY - margin;
|
||||
int x = qFloor(staticTextItem->glyphPositions[i].x.toReal() * cache->transform().m11()) + c.baseLineX - margin;
|
||||
int y = qRound(staticTextItem->glyphPositions[i].y.toReal() * cache->transform().m22()) - c.baseLineY - margin;
|
||||
|
||||
vertexCoordinates->addQuad(QRectF(x, y, c.w, c.h));
|
||||
textureCoordinates->addQuad(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy));
|
||||
@ -1712,9 +1728,9 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
|
||||
}
|
||||
|
||||
compositionModeDirty = false; // I can handle this myself, thank you very much
|
||||
prepareForDraw(false); // Text always causes src pixels to be transparent
|
||||
prepareForCachedGlyphDraw(*cache);
|
||||
|
||||
// prepareForDraw() have set the opacity on the current shader, so the opacity state can now be reset.
|
||||
// prepareForCachedGlyphDraw() have set the opacity on the current shader, so the opacity state can now be reset.
|
||||
if (compMode == QPainter::CompositionMode_Source) {
|
||||
q->state()->opacity = oldOpacity;
|
||||
opacityUniformDirty = true;
|
||||
@ -1735,7 +1751,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
|
||||
}
|
||||
|
||||
compositionModeDirty = false; // I can handle this myself, thank you very much
|
||||
prepareForDraw(false); // Text always causes src pixels to be transparent
|
||||
prepareForCachedGlyphDraw(*cache);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
@ -1759,7 +1775,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
|
||||
}
|
||||
|
||||
compositionModeDirty = false;
|
||||
prepareForDraw(false); // Text always causes src pixels to be transparent
|
||||
prepareForCachedGlyphDraw(*cache);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
}
|
||||
@ -1768,7 +1784,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
|
||||
// Greyscale/mono glyphs
|
||||
|
||||
shaderManager->setMaskType(QOpenGLEngineShaderManager::PixelMask);
|
||||
prepareForDraw(false); // Text always causes src pixels to be transparent
|
||||
prepareForCachedGlyphDraw(*cache);
|
||||
}
|
||||
|
||||
QOpenGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QOpenGLTextureGlyphCache::Linear:QOpenGLTextureGlyphCache::Nearest;
|
||||
|
@ -236,6 +236,7 @@ public:
|
||||
void setBrush(const QBrush& brush);
|
||||
void transferMode(EngineMode newMode);
|
||||
bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed
|
||||
bool prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache);
|
||||
inline void useSimpleShader();
|
||||
inline GLuint location(const QOpenGLEngineShaderManager::Uniform uniform) {
|
||||
return shaderManager->getUniformLocation(uniform);
|
||||
|
@ -78,6 +78,7 @@ public:
|
||||
virtual ~QFontEngineGlyphCache() { }
|
||||
|
||||
Type cacheType() const { return m_type; }
|
||||
const QTransform &transform() const { return m_transform; }
|
||||
|
||||
QTransform m_transform;
|
||||
QFontEngineGlyphCache::Type m_type;
|
||||
|
@ -1086,6 +1086,18 @@ void QGL2PaintEngineExPrivate::resetClipIfNeeded()
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
}
|
||||
|
||||
bool QGL2PaintEngineExPrivate::prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache)
|
||||
{
|
||||
Q_Q(QGL2PaintEngineEx);
|
||||
|
||||
QTransform &transform = q->state()->matrix;
|
||||
transform.scale(1.0 / cache.transform().m11(), 1.0 / cache.transform().m22());
|
||||
bool ret = prepareForDraw(false);
|
||||
transform.scale(cache.transform().m11(), cache.transform().m22());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
|
||||
{
|
||||
if (brushTextureDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
|
||||
@ -1580,11 +1592,15 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
|
||||
void *cacheKey = const_cast<QGLContext *>(QGLContextPrivate::contextGroup(ctx)->context());
|
||||
bool recreateVertexArrays = false;
|
||||
|
||||
// We allow scaling, so that the glyph-cache will contain glyphs with the
|
||||
// appropriate resolution in the case of displays with a device-pixel-ratio != 1.
|
||||
QTransform transform = QTransform::fromScale(s->matrix.m11(), s->matrix.m22());
|
||||
|
||||
QFontEngine *fe = staticTextItem->fontEngine();
|
||||
QGLTextureGlyphCache *cache =
|
||||
(QGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, QTransform());
|
||||
(QGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, transform);
|
||||
if (!cache || cache->cacheType() != glyphType || cache->contextGroup() == 0) {
|
||||
cache = new QGLTextureGlyphCache(glyphType, QTransform());
|
||||
cache = new QGLTextureGlyphCache(glyphType, transform);
|
||||
fe->setGlyphCache(cacheKey, cache);
|
||||
recreateVertexArrays = true;
|
||||
}
|
||||
@ -1676,8 +1692,8 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
|
||||
if (c.isNull())
|
||||
continue;
|
||||
|
||||
int x = qFloor(staticTextItem->glyphPositions[i].x) + c.baseLineX - margin;
|
||||
int y = qRound(staticTextItem->glyphPositions[i].y) - c.baseLineY - margin;
|
||||
int x = qFloor(staticTextItem->glyphPositions[i].x.toReal() * cache->transform().m11()) + c.baseLineX - margin;
|
||||
int y = qRound(staticTextItem->glyphPositions[i].y.toReal() * cache->transform().m22()) - c.baseLineY - margin;
|
||||
|
||||
vertexCoordinates->addQuad(QRectF(x, y, c.w, c.h));
|
||||
textureCoordinates->addQuad(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy));
|
||||
@ -1750,9 +1766,9 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
|
||||
}
|
||||
|
||||
compositionModeDirty = false; // I can handle this myself, thank you very much
|
||||
prepareForDraw(false); // Text always causes src pixels to be transparent
|
||||
prepareForCachedGlyphDraw(*cache);
|
||||
|
||||
// prepareForDraw() have set the opacity on the current shader, so the opacity state can now be reset.
|
||||
// prepareForCachedGlyphDraw() have set the opacity on the current shader, so the opacity state can now be reset.
|
||||
if (compMode == QPainter::CompositionMode_Source) {
|
||||
q->state()->opacity = oldOpacity;
|
||||
opacityUniformDirty = true;
|
||||
@ -1773,7 +1789,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
|
||||
}
|
||||
|
||||
compositionModeDirty = false; // I can handle this myself, thank you very much
|
||||
prepareForDraw(false); // Text always causes src pixels to be transparent
|
||||
prepareForCachedGlyphDraw(*cache);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
@ -1797,7 +1813,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
|
||||
}
|
||||
|
||||
compositionModeDirty = false;
|
||||
prepareForDraw(false); // Text always causes src pixels to be transparent
|
||||
prepareForCachedGlyphDraw(*cache);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
}
|
||||
@ -1806,7 +1822,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
|
||||
// Greyscale/mono glyphs
|
||||
|
||||
shaderManager->setMaskType(QGLEngineShaderManager::PixelMask);
|
||||
prepareForDraw(false); // Text always causes src pixels to be transparent
|
||||
prepareForCachedGlyphDraw(*cache);
|
||||
}
|
||||
|
||||
QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest;
|
||||
|
@ -227,6 +227,7 @@ public:
|
||||
void setBrush(const QBrush& brush);
|
||||
void transferMode(EngineMode newMode);
|
||||
bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed
|
||||
bool prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache);
|
||||
inline void useSimpleShader();
|
||||
inline GLuint location(const QGLEngineShaderManager::Uniform uniform) {
|
||||
return shaderManager->getUniformLocation(uniform);
|
||||
|
Loading…
Reference in New Issue
Block a user