Optimize distance field construction.
authorMichael Brasser <michael.brasser@live.com>
Fri, 20 Feb 2015 13:50:45 +0000 (07:50 -0600)
committerMichael Brasser <michael.brasser@live.com>
Wed, 25 Feb 2015 21:55:49 +0000 (21:55 +0000)
Reduce the number of times we construct a painter path from a glyph.

Change-Id: Ic1f32c78ab5dfd3b75d5442da163cda1dedab3ee
Task-number: QTBUG-42853
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
src/quick/scenegraph/qsgadaptationlayer.cpp
src/quick/scenegraph/qsgadaptationlayer_p.h

index 4232bf1..4f5c4ef 100644 (file)
@@ -62,7 +62,9 @@ QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCach
     m_doubleGlyphResolution = qt_fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT;
 
     m_referenceFont = font;
-    m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_doubleGlyphResolution));
+    // we set the same pixel size as used by the distance field internally.
+    // this allows us to call pathForGlyph once and reuse the result.
+    m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_doubleGlyphResolution) * QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution));
     Q_ASSERT(m_referenceFont.isValid());
 
     m_coreProfile = (c->format().profile() == QSurfaceFormat::CoreProfile);
@@ -78,8 +80,12 @@ QSGDistanceFieldGlyphCache::GlyphData &QSGDistanceFieldGlyphCache::glyphData(gly
     if (data == m_glyphsData.end()) {
         GlyphData gd;
         gd.texture = &s_emptyTexture;
-        QPainterPath path = m_referenceFont.pathForGlyph(glyph);
-        gd.boundingRect = path.boundingRect();
+        gd.path = m_referenceFont.pathForGlyph(glyph);
+        // need bounding rect in base font size scale
+        qreal scaleFactor = qreal(1) / QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution);
+        QTransform scaleDown;
+        scaleDown.scale(scaleFactor, scaleFactor);
+        gd.boundingRect = scaleDown.mapRect(gd.path.boundingRect());
         data = m_glyphsData.insert(glyph, gd);
     }
     return data.value();
@@ -160,9 +166,11 @@ void QSGDistanceFieldGlyphCache::update()
 
     QList<QDistanceField> distanceFields;
     for (int i = 0; i < m_pendingGlyphs.size(); ++i) {
-        distanceFields.append(QDistanceField(m_referenceFont,
+        GlyphData &gd = glyphData(m_pendingGlyphs.at(i));
+        distanceFields.append(QDistanceField(gd.path,
                                              m_pendingGlyphs.at(i),
                                              m_doubleGlyphResolution));
+        gd.path = QPainterPath(); // no longer needed, so release memory used by the painter path
     }
 
     qint64 renderTime = 0;
index e5923fc..1253711 100644 (file)
@@ -323,6 +323,7 @@ protected:
         Texture *texture;
         TexCoord texCoord;
         QRectF boundingRect;
+        QPainterPath path;
         quint32 ref;
 
         GlyphData() : texture(0), ref(0) { }