From a9cf934b5f86c49b86647a7ae7be8dc317165dc9 Mon Sep 17 00:00:00 2001 From: Michael Ragazzon Date: Sat, 6 Jul 2024 22:01:50 +0200 Subject: [PATCH] Font optimization: Store whether font size has been set during kerning queries Helps speed-up layout with non-ascii text especially. --- .../FontFaceHandleDefault.cpp | 22 ++++++++++++------- .../FontEngineDefault/FontFaceHandleDefault.h | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp b/Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp index 4e08723f0..b9867e67e 100644 --- a/Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp +++ b/Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp @@ -87,6 +87,7 @@ int FontFaceHandleDefault::GetStringWidth(const String& string, float letter_spa { RMLUI_ZoneScoped; + bool has_set_size = false; int width = 0; for (auto it_string = StringIteratorU8(string); it_string; ++it_string) { @@ -97,7 +98,7 @@ int FontFaceHandleDefault::GetStringWidth(const String& string, float letter_spa continue; // Adjust the cursor for the kerning between this character and the previous one. - width += GetKerning(prior_character, character); + width += GetKerning(prior_character, character, has_set_size); // Adjust the cursor for this character's advance. width += glyph->advance; @@ -195,12 +196,13 @@ bool FontFaceHandleDefault::GenerateLayerTexture(Vector& texture_data, Vec int FontFaceHandleDefault::GenerateString(RenderManager& render_manager, TexturedMeshList& mesh_list, const String& string, const Vector2f position, const ColourbPremultiplied colour, const float opacity, const float letter_spacing, const int layer_configuration_index) { - int geometry_index = 0; - int line_width = 0; - RMLUI_ASSERT(layer_configuration_index >= 0); RMLUI_ASSERT(layer_configuration_index < (int)layer_configurations.size()); + int geometry_index = 0; + int line_width = 0; + bool has_set_size = false; + UpdateLayersOnDirty(); // Fetch the requested configuration and generate the geometry for each one. @@ -247,7 +249,7 @@ int FontFaceHandleDefault::GenerateString(RenderManager& render_manager, Texture continue; // Adjust the cursor for the kerning between this character and the previous one. - line_width += GetKerning(prior_character, character); + line_width += GetKerning(prior_character, character, has_set_size); ColourbPremultiplied glyph_color = layer_colour; // Use white vertex colors on RGB glyphs. @@ -323,11 +325,11 @@ void FontFaceHandleDefault::FillKerningPairCache() } } -int FontFaceHandleDefault::GetKerning(Character lhs, Character rhs) const +int FontFaceHandleDefault::GetKerning(Character lhs, Character rhs, bool& has_set_size) const { static_assert(' ' == 32, "Only ASCII/UTF8 character set supported."); - // Check if we have no kerning, or if we are have a control character. + // Check if we have no kerning, or if we have a control character. if (!has_kerning || char32_t(lhs) < ' ' || char32_t(rhs) < ' ') return 0; @@ -348,7 +350,11 @@ int FontFaceHandleDefault::GetKerning(Character lhs, Character rhs) const } // Fetch it from the font face instead. - const int result = FreeType::GetKerning(ft_face, metrics.size, lhs, rhs); + const int result = FreeType::GetKerning(ft_face, has_set_size ? 0 : metrics.size, lhs, rhs); + + // This is purely an optimization to avoid repeatedly setting the font size in FreeType, which can be a measurable performance hit. + has_set_size = true; + return result; } diff --git a/Source/Core/FontEngineDefault/FontFaceHandleDefault.h b/Source/Core/FontEngineDefault/FontFaceHandleDefault.h index 33b797e42..a5972fc54 100644 --- a/Source/Core/FontEngineDefault/FontFaceHandleDefault.h +++ b/Source/Core/FontEngineDefault/FontFaceHandleDefault.h @@ -100,7 +100,7 @@ class FontFaceHandleDefault final : public NonCopyMoveable { void FillKerningPairCache(); // Return the kerning for a character pair. - int GetKerning(Character lhs, Character rhs) const; + int GetKerning(Character lhs, Character rhs, bool& has_set_size) const; /// Retrieve a glyph from the given code point, building and appending a new glyph if not already built. /// @param[in-out] character The character, can be changed e.g. to the replacement character if no glyph is found.