diff options
author | Yoann Lopes <yoann.lopes@nokia.com> | 2011-12-13 11:18:33 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-14 09:06:21 +0100 |
commit | 17bffaa4d447959f08e16ca9a45885f631a16cc0 (patch) | |
tree | d5a014dd626e2fc07179938eedde661357cb5663 /src/quick/scenegraph/qsgdistancefieldglyphnode.cpp | |
parent | 22a8387aeab93fd086b297443945487677aef280 (diff) |
More distance-field cache refactoring.
The distance field glyph node now uses preprocess().
The glyph cache is updated at that time, then when all the glyphs are
ready the node's geometry is updated.
addGlyphPositions and addGlyphTextures in QSGDistanceFieldGlyphCache
have been renamed to setGlyphsPosition and setGlyphsTexture to reflect the
fact that they can be used to update existing glyphs. For example when
a glyph has moved to a different texture.
When an existing glyph is updated, all nodes containing that glyph are
invalidated and their geometries are reconstructed with the new values.
Change-Id: I7758313155f48811e6027434e6c9a1c3df5dfab7
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Diffstat (limited to 'src/quick/scenegraph/qsgdistancefieldglyphnode.cpp')
-rw-r--r-- | src/quick/scenegraph/qsgdistancefieldglyphnode.cpp | 148 |
1 files changed, 57 insertions, 91 deletions
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp index d3b90bed60..def4d9486b 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp @@ -56,6 +56,7 @@ QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheM , m_dirtyGeometry(false) , m_dirtyMaterial(false) { + setFlag(UsePreprocess); m_geometry.setDrawingMode(GL_TRIANGLES); setGeometry(&m_geometry); setPreferredAntialiasingMode(cacheManager->defaultAntialiasingMode()); @@ -106,13 +107,10 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR m_glyph_cache->populate(glyphs.glyphIndexes()); const QVector<quint32> &glyphIndexes = m_glyphs.glyphIndexes(); - const QVector<QPointF> &glyphPositions = m_glyphs.positions(); - for (int i = 0; i < glyphIndexes.size(); ++i) { - GlyphInfo g; - g.glyphIndex = glyphIndexes.at(i); - g.position = glyphPositions.at(i); - m_glyphsToAdd.append(g); - } + m_allGlyphIndexes += glyphIndexes; + m_allGlyphPositions += m_glyphs.positions(); + for (int i = 0; i < glyphIndexes.count(); ++i) + m_allGlyphIndexesLookup.insert(glyphIndexes.at(i)); m_dirtyGeometry = true; m_dirtyMaterial = true; @@ -138,68 +136,70 @@ void QSGDistanceFieldGlyphNode::update() { if (m_dirtyMaterial) updateMaterial(); +} + +void QSGDistanceFieldGlyphNode::preprocess() +{ + Q_ASSERT(m_glyph_cache); + + m_glyph_cache->update(); + if (m_dirtyGeometry) updateGeometry(); } +void QSGDistanceFieldGlyphNode::invalidateGlyphs(const QVector<quint32> &glyphs) +{ + if (m_dirtyGeometry) + return; + + for (int i = 0; i < glyphs.count(); ++i) { + if (m_allGlyphIndexesLookup.contains(glyphs.at(i))) { + m_dirtyGeometry = true; + return; + } + } +} + void QSGDistanceFieldGlyphNode::updateGeometry() { Q_ASSERT(m_glyph_cache); - if (m_glyphsToAdd.isEmpty()) - return; - QSGGeometry *g = geometry(); Q_ASSERT(g->indexType() == GL_UNSIGNED_SHORT); - int oldVertexCount = g->vertexCount(); - int oldIndexCount = g->indexCount(); + g->allocate(m_allGlyphIndexes.size() * 4, m_allGlyphIndexes.size() * 6); - QVector<QSGGeometry::TexturedPoint2D> vp; - vp.reserve(m_glyphsToAdd.size() * 4); - QVector<ushort> ip; - ip.reserve(m_glyphsToAdd.size() * 6); + QSGGeometry::TexturedPoint2D *vp = g->vertexDataAsTexturedPoint2D(); + ushort *ip = g->indexDataAsUShort(); QPointF margins(2, 2); QPointF texMargins = margins / m_glyph_cache->fontScale(); const QSGDistanceFieldGlyphCache::Texture *textureToUse = 0; - QLinkedList<GlyphInfo>::iterator it = m_glyphsToAdd.begin(); - while (it != m_glyphsToAdd.end()) { - quint32 glyphIndex = it->glyphIndex; + for (int i = 0; i < m_allGlyphIndexes.size(); ++i) { + quint32 glyphIndex = m_allGlyphIndexes.at(i); + QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex); QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphIndex); - if (c.isNull()) { - if (!c.isValid()) - ++it; - else - it = m_glyphsToAdd.erase(it); - continue; - } - const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphIndex); - if (!texture->textureId) { - ++it; - continue; - } - - QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex); - - if (!textureToUse) + if (texture->textureId && !textureToUse) textureToUse = texture; - metrics.width += margins.x() * 2; - metrics.height += margins.y() * 2; - metrics.baselineX -= margins.x(); - metrics.baselineY += margins.y(); - c.xMargin -= texMargins.x(); - c.yMargin -= texMargins.y(); - c.width += texMargins.x() * 2; - c.height += texMargins.y() * 2; + if (!metrics.isNull() && !c.isNull()) { + metrics.width += margins.x() * 2; + metrics.height += margins.y() * 2; + metrics.baselineX -= margins.x(); + metrics.baselineY += margins.y(); + c.xMargin -= texMargins.x(); + c.yMargin -= texMargins.y(); + c.width += texMargins.x() * 2; + c.height += texMargins.y() * 2; + } - const QPointF &glyphPosition = it->position; + const QPointF &glyphPosition = m_allGlyphPositions.at(i); qreal x = glyphPosition.x() + metrics.baselineX + m_position.x(); qreal y = glyphPosition.y() - metrics.baselineY + m_position.y(); @@ -218,55 +218,21 @@ void QSGDistanceFieldGlyphNode::updateGeometry() if (m_baseLine.isNull()) m_baseLine = glyphPosition; - int i = vp.size(); - - QSGGeometry::TexturedPoint2D v1; - v1.set(cx1, cy1, tx1, ty1); - QSGGeometry::TexturedPoint2D v2; - v2.set(cx2, cy1, tx2, ty1); - QSGGeometry::TexturedPoint2D v3; - v3.set(cx1, cy2, tx1, ty2); - QSGGeometry::TexturedPoint2D v4; - v4.set(cx2, cy2, tx2, ty2); - vp.append(v1); - vp.append(v2); - vp.append(v3); - vp.append(v4); - - int o = i + oldVertexCount; - ip.append(o + 0); - ip.append(o + 2); - ip.append(o + 3); - ip.append(o + 3); - ip.append(o + 1); - ip.append(o + 0); - - it = m_glyphsToAdd.erase(it); + int vi = i & 1 ? (m_allGlyphIndexes.size() + 1) / 2 + i / 2 : i / 2; + vp[4 * vi + 0].set(cx1, cy1, tx1, ty1); + vp[4 * vi + 1].set(cx2, cy1, tx2, ty1); + vp[4 * vi + 2].set(cx1, cy2, tx1, ty2); + vp[4 * vi + 3].set(cx2, cy2, tx2, ty2); + + int o = i * 4; + ip[6 * i + 0] = o + 0; + ip[6 * i + 1] = o + 2; + ip[6 * i + 2] = o + 3; + ip[6 * i + 3] = o + 3; + ip[6 * i + 4] = o + 1; + ip[6 * i + 5] = o + 0; } - if (vp.isEmpty()) - return; - - void *data = 0; - if (oldVertexCount && oldIndexCount) { - int byteSize = oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D) - + oldIndexCount * sizeof(quint16); - data = qMalloc(byteSize); - memcpy(data, g->vertexData(), byteSize); - } - - g->allocate(oldVertexCount + vp.size(), oldIndexCount + ip.size()); - - if (data) { - memcpy(g->vertexData(), data, oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D)); - memcpy(g->indexData(), ((char *) data) + oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D), - oldIndexCount * sizeof(quint16)); - qFree(data); - } - - memcpy(g->vertexDataAsTexturedPoint2D() + oldVertexCount, vp.constData(), vp.size() * sizeof(QSGGeometry::TexturedPoint2D)); - memcpy(g->indexDataAsUShort() + oldIndexCount, ip.constData(), ip.size() * sizeof(quint16)); - setBoundingRect(m_boundingRect); markDirty(DirtyGeometry); m_dirtyGeometry = false; |