Enable transformations for Qt Quick in FT engine

In Qt Quick (or in Qt Widgets when setting QT_NO_FT_CACHE to 1 or
when using OpenGL engine), the alphaRGBMapForGlyph() will be used
to get glyphs, because we need to keep our own cache. Transforms
was not supported in this code path, instead it was turned off
in supportsTransformations().

This patch enables transformations in the alphaRGBMapForGlyph()
and alphaMapForGlyph() code paths as well, since this is needed
for proper rendering with QT_DEVICE_PIXEL_RATIO.

Change-Id: I7d6b79918f7c0bcc051a8343b16b315bfbba59cf
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2014-11-19 14:01:47 +01:00
parent bec1854cc0
commit 41db4b8cdc
2 changed files with 67 additions and 11 deletions

View File

@ -1459,10 +1459,7 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me
bool QFontEngineFT::supportsTransformation(const QTransform &transform) const
{
// The freetype engine falls back to QFontEngine for tranformed glyphs,
// which uses fast-tranform and produces very ugly results, so we claim
// to support just translations.
return transform.type() <= QTransform::TxTranslate;
return transform.type() <= QTransform::TxRotate;
}
void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
@ -1943,17 +1940,75 @@ void QFontEngineFT::unlockAlphaMapForGlyph()
currentlyLockedAlphaMap = QImage();
}
QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format)
QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
QFixed subPixelPosition,
GlyphFormat format,
const QTransform &t)
{
return defaultGlyphSet.outline_drawing ? 0 :
loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, g, subPixelPosition, format);
FT_Face face = 0;
QGlyphSet *glyphSet = 0;
FT_Matrix ftMatrix = QTransformToFTMatrix(t);
if (cacheEnabled) {
if (t.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) {
for (int i = 0; i < transformedGlyphSets.count(); ++i) {
const QGlyphSet &g = transformedGlyphSets.at(i);
if (g.transformationMatrix.xx == ftMatrix.xx
&& g.transformationMatrix.xy == ftMatrix.xy
&& g.transformationMatrix.yx == ftMatrix.yx
&& g.transformationMatrix.yy == ftMatrix.yy) {
// found a match, move it to the front
transformedGlyphSets.move(i, 0);
glyphSet = &transformedGlyphSets[0];
break;
}
}
if (!glyphSet) {
// don't cache more than 10 transformations
if (transformedGlyphSets.count() >= 10) {
transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
} else {
transformedGlyphSets.prepend(QGlyphSet());
}
glyphSet = &transformedGlyphSets[0];
glyphSet->clear();
glyphSet->transformationMatrix = ftMatrix;
}
} else {
glyphSet = &defaultGlyphSet;
}
Q_ASSERT(glyphSet != 0);
}
if (glyphSet != 0 && glyphSet->outline_drawing)
return 0;
Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0;
if (!glyph || glyph->format != format) {
face = lockFace();
FT_Matrix m = this->matrix;
FT_Matrix_Multiply(&ftMatrix, &m);
freetype->matrix = m;
glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false);
}
if (face)
unlockFace();
return glyph;
}
QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
{
return alphaMapForGlyph(g, subPixelPosition, QTransform());
}
QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
{
lockFace();
QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono));
QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g);
@ -1987,12 +2042,12 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
{
if (t.type() > QTransform::TxTranslate)
if (t.type() > QTransform::TxRotate)
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
lockFace();
QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32));
QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);

View File

@ -233,6 +233,7 @@ private:
virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const;
virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); }
virtual QImage alphaMapForGlyph(glyph_t, QFixed);
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
QFixed subPixelPosition,
@ -265,7 +266,7 @@ private:
inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
{ return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly); }
Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format);
Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t);
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,