Cached sf::Text attributes

Two optimizations:
- If a value remains the same, nothing happens
- Recompute geometry only before drawing and bound access, not after each set

Closes #413
This commit is contained in:
Jan Haller 2014-03-29 16:46:15 +01:00
parent 59e920cf10
commit 666da801a1
2 changed files with 58 additions and 32 deletions

View File

@ -275,10 +275,13 @@ private :
virtual void draw(RenderTarget& target, RenderStates states) const; virtual void draw(RenderTarget& target, RenderStates states) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Update the text's geometry /// \brief Make sure the text's geometry is updated
///
/// All the attributes related to rendering are cached, such
/// that the geometry is only updated when necessary.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void updateGeometry(); void ensureGeometryUpdate() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
@ -288,8 +291,9 @@ private :
unsigned int m_characterSize; ///< Base size of characters, in pixels unsigned int m_characterSize; ///< Base size of characters, in pixels
Uint32 m_style; ///< Text style (see Style enum) Uint32 m_style; ///< Text style (see Style enum)
Color m_color; ///< Text color Color m_color; ///< Text color
VertexArray m_vertices; ///< Vertex array containing the text's geometry mutable VertexArray m_vertices; ///< Vertex array containing the text's geometry
FloatRect m_bounds; ///< Bounding rectangle of the text (in local coordinates) mutable FloatRect m_bounds; ///< Bounding rectangle of the text (in local coordinates)
mutable bool m_geometryNeedUpdate; ///< Does the geometry need to be recomputed?
}; };
} // namespace sf } // namespace sf

View File

@ -41,7 +41,8 @@ m_characterSize(30),
m_style (Regular), m_style (Regular),
m_color (255, 255, 255), m_color (255, 255, 255),
m_vertices (Quads), m_vertices (Quads),
m_bounds () m_bounds (),
m_geometryNeedUpdate(false)
{ {
} }
@ -55,17 +56,21 @@ m_characterSize(characterSize),
m_style (Regular), m_style (Regular),
m_color (255, 255, 255), m_color (255, 255, 255),
m_vertices (Quads), m_vertices (Quads),
m_bounds () m_bounds (),
m_geometryNeedUpdate(true)
{ {
updateGeometry();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Text::setString(const String& string) void Text::setString(const String& string)
{
if (m_string != string)
{ {
m_string = string; m_string = string;
updateGeometry(); m_geometryNeedUpdate = true;
}
} }
@ -75,7 +80,7 @@ void Text::setFont(const Font& font)
if (m_font != &font) if (m_font != &font)
{ {
m_font = &font; m_font = &font;
updateGeometry(); m_geometryNeedUpdate = true;
} }
} }
@ -86,7 +91,7 @@ void Text::setCharacterSize(unsigned int size)
if (m_characterSize != size) if (m_characterSize != size)
{ {
m_characterSize = size; m_characterSize = size;
updateGeometry(); m_geometryNeedUpdate = true;
} }
} }
@ -97,7 +102,7 @@ void Text::setStyle(Uint32 style)
if (m_style != style) if (m_style != style)
{ {
m_style = style; m_style = style;
updateGeometry(); m_geometryNeedUpdate = true;
} }
} }
@ -108,10 +113,16 @@ void Text::setColor(const Color& color)
if (color != m_color) if (color != m_color)
{ {
m_color = color; m_color = color;
// Change vertex colors directly, no need to update whole geometry
// (if geometry is updated anyway, we can skip this step)
if (!m_geometryNeedUpdate)
{
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i) for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
m_vertices[i].color = m_color; m_vertices[i].color = m_color;
} }
} }
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -199,6 +210,8 @@ Vector2f Text::findCharacterPos(std::size_t index) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
FloatRect Text::getLocalBounds() const FloatRect Text::getLocalBounds() const
{ {
ensureGeometryUpdate();
return m_bounds; return m_bounds;
} }
@ -215,6 +228,8 @@ void Text::draw(RenderTarget& target, RenderStates states) const
{ {
if (m_font) if (m_font)
{ {
ensureGeometryUpdate();
states.transform *= getTransform(); states.transform *= getTransform();
states.texture = &m_font->getTexture(m_characterSize); states.texture = &m_font->getTexture(m_characterSize);
target.draw(m_vertices, states); target.draw(m_vertices, states);
@ -223,8 +238,15 @@ void Text::draw(RenderTarget& target, RenderStates states) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Text::updateGeometry() void Text::ensureGeometryUpdate() const
{ {
// Do nothing, if geometry has not changed
if (!m_geometryNeedUpdate)
return;
// Mark geometry as updated
m_geometryNeedUpdate = false;
// Clear the previous geometry // Clear the previous geometry
m_vertices.clear(); m_vertices.clear();
m_bounds = FloatRect(); m_bounds = FloatRect();