Don't register sub distance field glyph nodes with the glyph cache.
authorYoann Lopes <yoann.lopes@nokia.com>
Tue, 20 Mar 2012 13:09:13 +0000 (14:09 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 20 Mar 2012 15:44:18 +0000 (16:44 +0100)
The original distance field glyph node takes care of the glyphs
reference counting. The potential sub glyph nodes created when the
glyphs are in another texture are note registered anymore with the cache
and don't reference count their glyphs.
Also got rid of unnecessary data members.

Change-Id: I1544792d5d896c6de26e0838e4f80397759ea012
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
src/quick/scenegraph/qsgdistancefieldglyphnode_p.h

index 16a8ce2..d6fe6f9 100644 (file)
@@ -47,7 +47,8 @@
 QT_BEGIN_NAMESPACE
 
 QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGContext *context)
-    : m_context(context)
+    : m_glyphNodeType(RootGlyphNode)
+    , m_context(context)
     , m_material(0)
     , m_glyph_cache(0)
     , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0)
@@ -69,15 +70,17 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode()
 {
     delete m_material;
 
+    if (m_glyphNodeType == SubGlyphNode)
+        return;
+
     if (m_glyph_cache) {
         m_glyph_cache->release(m_glyphs.glyphIndexes());
         m_glyph_cache->unregisterGlyphNode(this);
         m_glyph_cache->unregisterOwnerElement(ownerElement());
     }
 
-    for (int i = 0; i < m_nodesToDelete.count(); ++i)
-        delete m_nodesToDelete.at(i);
-    m_nodesToDelete.clear();
+    while (m_nodesToDelete.count())
+        delete m_nodesToDelete.takeLast();
 }
 
 void QSGDistanceFieldGlyphNode::setColor(const QColor &color)
@@ -106,8 +109,15 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR
     m_position = QPointF(position.x(), position.y() - font.ascent());
     m_glyphs = glyphs;
 
+    m_dirtyGeometry = true;
+    m_dirtyMaterial = true;
+
     QSGDistanceFieldGlyphCache *oldCache = m_glyph_cache;
     m_glyph_cache = m_context->distanceFieldGlyphCache(m_glyphs.rawFont());
+
+    if (m_glyphNodeType == SubGlyphNode)
+        return;
+
     if (m_glyph_cache != oldCache) {
         Q_ASSERT(ownerElement() != 0);
         if (oldCache) {
@@ -122,9 +132,6 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR
     const QVector<quint32> glyphIndexes = m_glyphs.glyphIndexes();
     for (int i = 0; i < glyphIndexes.count(); ++i)
         m_allGlyphIndexesLookup.insert(glyphIndexes.at(i));
-
-    m_dirtyGeometry = true;
-    m_dirtyMaterial = true;
 }
 
 void QSGDistanceFieldGlyphNode::setStyle(QQuickText::TextStyle style)
@@ -153,9 +160,8 @@ void QSGDistanceFieldGlyphNode::preprocess()
 {
     Q_ASSERT(m_glyph_cache);
 
-    for (int i = 0; i < m_nodesToDelete.count(); ++i)
-        delete m_nodesToDelete.at(i);
-    m_nodesToDelete.clear();
+    while (m_nodesToDelete.count())
+        delete m_nodesToDelete.takeLast();
 
     m_glyph_cache->processPendingGlyphs();
     m_glyph_cache->update();
@@ -182,14 +188,15 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
     Q_ASSERT(m_glyph_cache);
 
     // Remove previously created sub glyph nodes
-    QHash<const QSGDistanceFieldGlyphCache::Texture *, QSGDistanceFieldGlyphNode *>::iterator it = m_subNodes.begin();
-    while (it != m_subNodes.end()) {
-        removeChildNode(it.value());
+    // We assume all the children are sub glyph nodes
+    QSGNode *subnode = firstChild();
+    while (subnode) {
         // We can't delete the node now as it might be in the preprocess list
         // It will be deleted in the next preprocess
-        m_nodesToDelete.append(it.value());
-        it = m_subNodes.erase(it);
+        m_nodesToDelete.append(subnode);
+        subnode = subnode->nextSibling();
     }
+    removeAllChildNodes();
 
     QSGGeometry *g = geometry();
 
@@ -287,25 +294,19 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
 
     QHash<const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo>::const_iterator ite = glyphsInOtherTextures.constBegin();
     while (ite != glyphsInOtherTextures.constEnd()) {
-        QHash<const QSGDistanceFieldGlyphCache::Texture *, QSGDistanceFieldGlyphNode *>::iterator subIt = m_subNodes.find(ite.key());
-        if (subIt == m_subNodes.end()) {
-            QSGDistanceFieldGlyphNode *subNode = new QSGDistanceFieldGlyphNode(m_context);
-            subNode->setOwnerElement(m_ownerElement);
-            subNode->setColor(m_color);
-            subNode->setStyle(m_style);
-            subNode->setStyleColor(m_styleColor);
-            subNode->update();
-            appendChildNode(subNode);
-            subIt = m_subNodes.insert(ite.key(), subNode);
-        }
-
         QGlyphRun subNodeGlyphRun(m_glyphs);
         subNodeGlyphRun.setGlyphIndexes(ite->indexes);
         subNodeGlyphRun.setPositions(ite->positions);
 
-        subIt.value()->setGlyphs(m_originalPosition, subNodeGlyphRun);
-        subIt.value()->update();
-        subIt.value()->updateGeometry(); // we have to explicity call this now as preprocess won't be called before it's rendered
+        QSGDistanceFieldGlyphNode *subNode = new QSGDistanceFieldGlyphNode(m_context);
+        subNode->setGlyphNodeType(SubGlyphNode);
+        subNode->setColor(m_color);
+        subNode->setStyle(m_style);
+        subNode->setStyleColor(m_styleColor);
+        subNode->setGlyphs(m_originalPosition, subNodeGlyphRun);
+        subNode->update();
+        subNode->updateGeometry(); // we have to explicity call this now as preprocess won't be called before it's rendered
+        appendChildNode(subNode);
 
         ++ite;
     }
index f8c8267..146267c 100644 (file)
@@ -77,8 +77,15 @@ public:
     void updateGeometry();
 
 private:
+    enum DistanceFieldGlyphNodeType {
+        RootGlyphNode,
+        SubGlyphNode
+    };
+
+    void setGlyphNodeType(DistanceFieldGlyphNodeType type) { m_glyphNodeType = type; }
     void updateMaterial();
 
+    DistanceFieldGlyphNodeType m_glyphNodeType;
     QColor m_color;
     QPointF m_baseLine;
     QSGContext *m_context;
@@ -93,8 +100,7 @@ private:
     AntialiasingMode m_antialiasingMode;
     QRectF m_boundingRect;
     const QSGDistanceFieldGlyphCache::Texture *m_texture;
-    QHash<const QSGDistanceFieldGlyphCache::Texture *, QSGDistanceFieldGlyphNode *> m_subNodes;
-    QList<QSGDistanceFieldGlyphNode *> m_nodesToDelete;
+    QLinkedList<QSGNode *> m_nodesToDelete;
 
     struct GlyphInfo {
         QVector<quint32> indexes;