Browse Source

Use StringView in FontEngineInterface to avoid a lot of string copies

Michael Ragazzon 1 year ago
parent
commit
4df92161f4

+ 1 - 1
Include/RmlUi/Core/ElementUtilities.h

@@ -85,7 +85,7 @@ public:
 	/// @param[in] string The string to measure.
 	/// @param[in] prior_character The character placed just before this string, used for kerning.
 	/// @return The string width, in pixels.
-	static int GetStringWidth(Element* element, const String& string, Character prior_character = Character::Null);
+	static int GetStringWidth(Element* element, StringView string, Character prior_character = Character::Null);
 
 	/// Generates the clipping region for an element.
 	/// @param[in] element The element to generate the clipping region for.

+ 3 - 4
Include/RmlUi/Core/FontEngineInterface.h

@@ -99,7 +99,7 @@ public:
 	/// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string
 	/// width due to kerning.
 	/// @return The width, in pixels, this string will occupy if rendered with this handle.
-	virtual int GetStringWidth(FontFaceHandle handle, const String& string, const TextShapingContext& text_shaping_context,
+	virtual int GetStringWidth(FontFaceHandle handle, StringView string, const TextShapingContext& text_shaping_context,
 		Character prior_character = Character::Null);
 
 	/// Called by RmlUi when it wants to retrieve the meshes required to render a single line of text.
@@ -113,9 +113,8 @@ public:
 	/// @param[in] text_shaping_context Additional parameters that provide context for text shaping.
 	/// @param[out] mesh_list A list to place the meshes and textures representing the string to be rendered.
 	/// @return The width, in pixels, of the string mesh.
-	virtual int GenerateString(RenderManager& render_manager, FontFaceHandle face_handle, FontEffectsHandle font_effects_handle, const String& string,
-		const Vector2f& position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
-		TexturedMeshList& mesh_list);
+	virtual int GenerateString(RenderManager& render_manager, FontFaceHandle face_handle, FontEffectsHandle font_effects_handle, StringView string,
+		Vector2f position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context, TexturedMeshList& mesh_list);
 
 	/// Called by RmlUi to determine if the text geometry is required to be re-generated. Whenever the returned version
 	/// is changed, all geometry belonging to the given face handle will be re-generated.

+ 1 - 0
Include/RmlUi/Core/Types.h

@@ -89,6 +89,7 @@ class Transform;
 class PropertyIdSet;
 class Decorator;
 class FontEffect;
+class StringView;
 struct Animation;
 struct Transition;
 struct TransitionList;

+ 4 - 5
Samples/basic/bitmap_font/src/FontEngineBitmap.cpp

@@ -124,12 +124,11 @@ FontFaceBitmap* GetFontFaceHandle(const String& family, FontStyle style, FontWei
 
 FontFaceBitmap::FontFaceBitmap(String family, FontStyle style, FontWeight weight, FontMetrics metrics, String texture_name, String texture_path,
 	Vector2f texture_dimensions, FontGlyphs&& glyphs, FontKerning&& kerning) :
-	family(family),
-	style(style), weight(weight), metrics(metrics), texture_source(texture_name, texture_path), texture_dimensions(texture_dimensions),
-	glyphs(std::move(glyphs)), kerning(std::move(kerning))
+	family(family), style(style), weight(weight), metrics(metrics), texture_source(texture_name, texture_path),
+	texture_dimensions(texture_dimensions), glyphs(std::move(glyphs)), kerning(std::move(kerning))
 {}
 
-int FontFaceBitmap::GetStringWidth(const String& string, Character previous_character)
+int FontFaceBitmap::GetStringWidth(StringView string, Character previous_character)
 {
 	int width = 0;
 
@@ -152,7 +151,7 @@ int FontFaceBitmap::GetStringWidth(const String& string, Character previous_char
 	return width;
 }
 
-int FontFaceBitmap::GenerateString(RenderManager& render_manager, const String& string, const Vector2f& string_position, ColourbPremultiplied colour,
+int FontFaceBitmap::GenerateString(RenderManager& render_manager, StringView string, Vector2f string_position, ColourbPremultiplied colour,
 	TexturedMeshList& mesh_list)
 {
 	int width = 0;

+ 2 - 2
Samples/basic/bitmap_font/src/FontEngineBitmap.h

@@ -63,10 +63,10 @@ public:
 		Vector2f texture_dimensions, FontGlyphs&& glyphs, FontKerning&& kerning);
 
 	// Get width of string.
-	int GetStringWidth(const String& string, Character prior_character);
+	int GetStringWidth(StringView string, Character prior_character);
 
 	// Generate the string geometry, returning its width.
-	int GenerateString(RenderManager& render_manager, const String& string, const Vector2f& position, ColourbPremultiplied colour, TexturedMeshList& mesh_list);
+	int GenerateString(RenderManager& render_manager, StringView string, Vector2f position, ColourbPremultiplied colour, TexturedMeshList& mesh_list);
 
 	const FontMetrics& GetMetrics() const { return metrics; }
 

+ 3 - 3
Samples/basic/bitmap_font/src/FontEngineInterfaceBitmap.cpp

@@ -74,7 +74,7 @@ const FontMetrics& FontEngineInterfaceBitmap::GetFontMetrics(FontFaceHandle hand
 	return handle_bitmap->GetMetrics();
 }
 
-int FontEngineInterfaceBitmap::GetStringWidth(FontFaceHandle handle, const String& string, const TextShapingContext& /*text_shaping_context*/,
+int FontEngineInterfaceBitmap::GetStringWidth(FontFaceHandle handle, StringView string, const TextShapingContext& /*text_shaping_context*/,
 	Character prior_character)
 {
 	auto handle_bitmap = reinterpret_cast<FontFaceBitmap*>(handle);
@@ -82,8 +82,8 @@ int FontEngineInterfaceBitmap::GetStringWidth(FontFaceHandle handle, const Strin
 }
 
 int FontEngineInterfaceBitmap::GenerateString(RenderManager& render_manager, FontFaceHandle handle, FontEffectsHandle /*font_effects_handle*/,
-	const String& string, const Vector2f& position, ColourbPremultiplied colour, float /*opacity*/,
-	const TextShapingContext& /*text_shaping_context*/, TexturedMeshList& mesh_list)
+	StringView string, Vector2f position, ColourbPremultiplied colour, float /*opacity*/, const TextShapingContext& /*text_shaping_context*/,
+	TexturedMeshList& mesh_list)
 {
 	auto handle_bitmap = reinterpret_cast<FontFaceBitmap*>(handle);
 	return handle_bitmap->GenerateString(render_manager, string, position, colour, mesh_list);

+ 4 - 3
Samples/basic/bitmap_font/src/FontEngineInterfaceBitmap.h

@@ -41,6 +41,7 @@ using Rml::Character;
 using Rml::ColourbPremultiplied;
 using Rml::Span;
 using Rml::String;
+using Rml::StringView;
 using Rml::Texture;
 using Rml::Vector2f;
 using Rml::Vector2i;
@@ -79,12 +80,12 @@ public:
 	const FontMetrics& GetFontMetrics(FontFaceHandle handle) override;
 
 	/// Called by RmlUi when it wants to retrieve the width of a string when rendered with this handle.
-	int GetStringWidth(FontFaceHandle handle, const String& string, const TextShapingContext& text_shaping_context,
+	int GetStringWidth(FontFaceHandle handle, StringView string, const TextShapingContext& text_shaping_context,
 		Character prior_character = Character::Null) override;
 
 	/// Called by RmlUi when it wants to retrieve the geometry required to render a single line of text.
-	int GenerateString(RenderManager& render_manager, FontFaceHandle face_handle, FontEffectsHandle font_effects_handle, const String& string,
-		const Vector2f& position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
+	int GenerateString(RenderManager& render_manager, FontFaceHandle face_handle, FontEffectsHandle font_effects_handle, StringView string,
+		Vector2f position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
 		TexturedMeshList& mesh_list) override;
 
 	/// Called by RmlUi to determine if the text geometry is required to be re-generated.eometry.

+ 2 - 2
Samples/basic/harfbuzz/src/FontEngineInterfaceHarfBuzz.cpp

@@ -69,7 +69,7 @@ const FontMetrics& FontEngineInterfaceHarfBuzz::GetFontMetrics(FontFaceHandle ha
 	return handle_harfbuzz->GetFontMetrics();
 }
 
-int FontEngineInterfaceHarfBuzz::GetStringWidth(FontFaceHandle handle, const String& string, const TextShapingContext& text_shaping_context,
+int FontEngineInterfaceHarfBuzz::GetStringWidth(FontFaceHandle handle, StringView string, const TextShapingContext& text_shaping_context,
 	Character prior_character)
 {
 	auto handle_harfbuzz = reinterpret_cast<FontFaceHandleHarfBuzz*>(handle);
@@ -77,7 +77,7 @@ int FontEngineInterfaceHarfBuzz::GetStringWidth(FontFaceHandle handle, const Str
 }
 
 int FontEngineInterfaceHarfBuzz::GenerateString(RenderManager& render_manager, FontFaceHandle handle, FontEffectsHandle font_effects_handle,
-	const String& string, const Vector2f& position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
+	StringView string, Vector2f position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
 	TexturedMeshList& mesh_list)
 {
 	auto handle_harfbuzz = reinterpret_cast<FontFaceHandleHarfBuzz*>(handle);

+ 4 - 4
Samples/basic/harfbuzz/src/FontEngineInterfaceHarfBuzz.h

@@ -42,6 +42,7 @@ using Rml::FontMetrics;
 using Rml::RenderManager;
 using Rml::Span;
 using Rml::String;
+using Rml::StringView;
 using Rml::TextShapingContext;
 using Rml::TexturedMeshList;
 using Rml::Vector2f;
@@ -71,12 +72,11 @@ public:
 	const FontMetrics& GetFontMetrics(FontFaceHandle handle) override;
 
 	/// Returns the width a string will take up if rendered with this handle.
-	int GetStringWidth(FontFaceHandle handle, const String& string, const TextShapingContext& text_shaping_context,
-		Character prior_character) override;
+	int GetStringWidth(FontFaceHandle handle, StringView string, const TextShapingContext& text_shaping_context, Character prior_character) override;
 
 	/// Generates the geometry required to render a single line of text.
-	int GenerateString(RenderManager& render_manager, FontFaceHandle face_handle, FontEffectsHandle effects_handle, const String& string,
-		const Vector2f& position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
+	int GenerateString(RenderManager& render_manager, FontFaceHandle face_handle, FontEffectsHandle effects_handle, StringView string,
+		Vector2f position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
 		TexturedMeshList& mesh_list) override;
 
 	/// Returns the current version of the font face.

+ 8 - 8
Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.cpp

@@ -92,7 +92,7 @@ const FontGlyphMap& FontFaceHandleHarfBuzz::GetGlyphs() const
 	return glyphs;
 }
 
-int FontFaceHandleHarfBuzz::GetStringWidth(const String& string, const TextShapingContext& text_shaping_context,
+int FontFaceHandleHarfBuzz::GetStringWidth(StringView string, const TextShapingContext& text_shaping_context,
 	const LanguageDataMap& registered_languages, Character prior_character)
 {
 	int width = 0;
@@ -101,7 +101,7 @@ int FontFaceHandleHarfBuzz::GetStringWidth(const String& string, const TextShapi
 	hb_buffer_t* shaping_buffer = hb_buffer_create();
 	RMLUI_ASSERT(shaping_buffer != nullptr);
 	ConfigureTextShapingBuffer(shaping_buffer, string, text_shaping_context, registered_languages);
-	hb_buffer_add_utf8(shaping_buffer, string.c_str(), -1, 0, -1);
+	hb_buffer_add_utf8(shaping_buffer, string.begin(), (int)string.size(), 0, (int)string.size());
 	hb_shape(hb_font, shaping_buffer, nullptr, 0);
 
 	FontGlyphIndex prior_glyph_codepoint = FreeType::GetGlyphIndexFromCharacter(ft_face, prior_character);
@@ -112,7 +112,7 @@ int FontFaceHandleHarfBuzz::GetStringWidth(const String& string, const TextShapi
 	for (int g = 0; g < (int)glyph_count; ++g)
 	{
 		// Don't render control characters.
-		Character character = *Rml::StringIteratorU8(&string[glyph_info[g].cluster]);
+		Character character = Rml::StringUtilities::ToCharacter(string.begin() + glyph_info[g].cluster, string.end());
 		if (IsASCIIControlCharacter(character))
 			continue;
 
@@ -219,7 +219,7 @@ bool FontFaceHandleHarfBuzz::GenerateLayerTexture(Vector<byte>& texture_data, Ve
 	return it->layer->GenerateTexture(texture_data, texture_dimensions, texture_id, glyphs);
 }
 
-int FontFaceHandleHarfBuzz::GenerateString(RenderManager& render_manager, TexturedMeshList& mesh_list, const String& string, const Vector2f position,
+int FontFaceHandleHarfBuzz::GenerateString(RenderManager& render_manager, TexturedMeshList& mesh_list, StringView string, const Vector2f position,
 	const ColourbPremultiplied colour, const float opacity, const TextShapingContext& text_shaping_context,
 	const LanguageDataMap& registered_languages, const int layer_configuration_index)
 {
@@ -269,7 +269,7 @@ int FontFaceHandleHarfBuzz::GenerateString(RenderManager& render_manager, Textur
 		// Set up and apply text shaping.
 		hb_buffer_clear_contents(shaping_buffer);
 		ConfigureTextShapingBuffer(shaping_buffer, string, text_shaping_context, registered_languages);
-		hb_buffer_add_utf8(shaping_buffer, string.c_str(), -1, 0, -1);
+		hb_buffer_add_utf8(shaping_buffer, string.begin(), (int)string.size(), 0, (int)string.size());
 		hb_shape(hb_font, shaping_buffer, nullptr, 0);
 
 		unsigned int glyph_count = 0;
@@ -281,7 +281,7 @@ int FontFaceHandleHarfBuzz::GenerateString(RenderManager& render_manager, Textur
 		for (int g = 0; g < (int)glyph_count; ++g)
 		{
 			// Don't render control characters.
-			Character character = *Rml::StringIteratorU8(&string[glyph_info[g].cluster]);
+			Character character = Rml::StringUtilities::ToCharacter(string.begin() + glyph_info[g].cluster, string.end());
 			if (IsASCIIControlCharacter(character))
 				continue;
 
@@ -480,7 +480,7 @@ bool FontFaceHandleHarfBuzz::GenerateLayer(FontFaceLayer* layer)
 	return result;
 }
 
-void FontFaceHandleHarfBuzz::ConfigureTextShapingBuffer(hb_buffer_t* shaping_buffer, const String& string,
+void FontFaceHandleHarfBuzz::ConfigureTextShapingBuffer(hb_buffer_t* shaping_buffer, StringView string,
 	const TextShapingContext& text_shaping_context, const LanguageDataMap& registered_languages)
 {
 	// Set the buffer's language based on the value of the element's 'lang' attribute.
@@ -498,7 +498,7 @@ void FontFaceHandleHarfBuzz::ConfigureTextShapingBuffer(hb_buffer_t* shaping_buf
 		hb_unicode_funcs_t* unicode_functions = hb_unicode_funcs_get_default();
 		if (unicode_functions != nullptr && !string.empty())
 		{
-			Character first_character = *Rml::StringIteratorU8(string);
+			Character first_character = Rml::StringUtilities::ToCharacter(string.begin(), string.end());
 			script = hb_unicode_script(unicode_functions, (hb_codepoint_t)first_character);
 		}
 	}

+ 5 - 5
Samples/basic/harfbuzz/src/FontFaceHandleHarfBuzz.h

@@ -47,6 +47,7 @@ using Rml::RenderManager;
 using Rml::SharedPtr;
 using Rml::SmallUnorderedMap;
 using Rml::String;
+using Rml::StringView;
 using Rml::TextShapingContext;
 using Rml::TexturedMeshList;
 using Rml::UniquePtr;
@@ -77,7 +78,7 @@ public:
 	/// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string
 	/// width due to kerning.
 	/// @return The width, in pixels, this string will occupy if rendered with this handle.
-	int GetStringWidth(const String& string, const TextShapingContext& text_shaping_context, const LanguageDataMap& registered_languages,
+	int GetStringWidth(StringView string, const TextShapingContext& text_shaping_context, const LanguageDataMap& registered_languages,
 		Character prior_character = Character::Null);
 
 	/// Generates, if required, the layer configuration for a given list of font effects.
@@ -104,9 +105,8 @@ public:
 	/// @param[in] registered_languages A list of languages registered in the font engine interface.
 	/// @param[in] layer_configuration Face configuration index to use for generating string.
 	/// @return The width, in pixels, of the string geometry.
-	int GenerateString(RenderManager& render_manager, TexturedMeshList& mesh_list, const String& string, Vector2f position,
-		ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context, const LanguageDataMap& registered_languages,
-		int layer_configuration = 0);
+	int GenerateString(RenderManager& render_manager, TexturedMeshList& mesh_list, StringView, Vector2f position, ColourbPremultiplied colour,
+		float opacity, const TextShapingContext& text_shaping_context, const LanguageDataMap& registered_languages, int layer_configuration = 0);
 
 	/// Version is changed whenever the layers are dirtied, requiring regeneration of string geometry.
 	int GetVersion() const;
@@ -136,7 +136,7 @@ private:
 	bool GenerateLayer(FontFaceLayer* layer);
 
 	// Configure internal text shaping buffer values with context.
-	void ConfigureTextShapingBuffer(struct hb_buffer_t* shaping_buffer, const String& string, const TextShapingContext& text_shaping_context,
+	void ConfigureTextShapingBuffer(struct hb_buffer_t* shaping_buffer, StringView string, const TextShapingContext& text_shaping_context,
 		const LanguageDataMap& registered_languages);
 
 	FontGlyphMap glyphs;

+ 1 - 1
Source/Core/ElementUtilities.cpp

@@ -157,7 +157,7 @@ float ElementUtilities::GetDensityIndependentPixelRatio(Element* element)
 	return context->GetDensityIndependentPixelRatio();
 }
 
-int ElementUtilities::GetStringWidth(Element* element, const String& string, Character prior_character)
+int ElementUtilities::GetStringWidth(Element* element, StringView string, Character prior_character)
 {
 	const auto& computed = element->GetComputedValues();
 	const TextShapingContext text_shaping_context{computed.language(), computed.direction(), computed.letter_spacing()};

+ 14 - 15
Source/Core/Elements/WidgetTextInput.cpp

@@ -1050,8 +1050,8 @@ void WidgetTextInput::SetCursorFromRelativeIndices(int cursor_line_index, int cu
 	for (int i = 0; i < cursor_line_index; i++)
 		absolute_cursor_index += lines[i].size;
 
-	// Don't wrap down if we're located at the end of the line.
-	cursor_wrap_down = !(cursor_character_index >= lines[cursor_line_index].editable_length);
+	// Only wrap down if we're not located at the end of the line.
+	cursor_wrap_down = (cursor_character_index < lines[cursor_line_index].editable_length);
 }
 
 int WidgetTextInput::CalculateLineIndex(float position) const
@@ -1063,18 +1063,16 @@ int WidgetTextInput::CalculateLineIndex(float position) const
 
 float WidgetTextInput::GetAlignmentSpecificTextOffset(const Line& line) const
 {
-	const String& value = GetValue();
-	StringView editable_line_string(value, line.value_offset, line.editable_length);
-
-	const Style::TextAlign text_align = parent->GetComputedValues().text_align();
-
 	// Callback to avoid expensive calculation in the cases where it is not needed.
-	auto RemainingWidth = [&] {
-		const float total_width = (float)ElementUtilities::GetStringWidth(text_element, String(editable_line_string));
+	auto RemainingWidth = [this](StringView editable_line_string) {
+		const float total_width = (float)ElementUtilities::GetStringWidth(text_element, editable_line_string);
 		return GetAvailableWidth() - total_width;
 	};
 
-	switch (text_align)
+	const String& value = GetValue();
+	StringView editable_line_string(value, line.value_offset, line.editable_length);
+
+	switch (parent->GetComputedValues().text_align())
 	{
 	case Style::TextAlign::Left: return 0;
 	case Style::TextAlign::Right:
@@ -1086,9 +1084,9 @@ float WidgetTextInput::GetAlignmentSpecificTextOffset(const Line& line) const
 		{
 			editable_line_string = StringView(editable_line_string.begin(), editable_line_string.end() - 1);
 		}
-		return Math::Max(0.0f, RemainingWidth());
+		return Math::Max(0.0f, RemainingWidth(editable_line_string));
 	}
-	case Style::TextAlign::Center: return Math::Max(0.0f, 0.5f * RemainingWidth());
+	case Style::TextAlign::Center: return Math::Max(0.0f, 0.5f * RemainingWidth(editable_line_string));
 	case Style::TextAlign::Justify: return 0;
 	}
 	return 0;
@@ -1103,15 +1101,16 @@ int WidgetTextInput::CalculateCharacterIndex(int line_index, float position)
 
 	const Line& line = lines[line_index];
 	const char* p_begin = GetValue().data() + line.value_offset;
+	const char* p_end = p_begin + line.editable_length;
 
 	position -= GetAlignmentSpecificTextOffset(line);
 
-	for (auto it = StringIteratorU8(p_begin, p_begin, p_begin + line.editable_length); it;)
+	for (auto it = StringIteratorU8(p_begin, p_begin, p_end); it;)
 	{
 		++it;
 		const int offset = (int)it.offset();
 
-		const float line_width = (float)ElementUtilities::GetStringWidth(text_element, String(p_begin, (size_t)offset));
+		const float line_width = (float)ElementUtilities::GetStringWidth(text_element, StringView(p_begin, p_begin + offset));
 		if (line_width > position)
 		{
 			if (position - prev_line_width < line_width - position)
@@ -1448,7 +1447,7 @@ void WidgetTextInput::UpdateCursorPosition(bool update_ideal_cursor_position)
 
 	const auto& line = lines[cursor_line_index];
 	const int string_width_pre_cursor =
-		ElementUtilities::GetStringWidth(text_element, String(StringView(GetValue(), line.value_offset, cursor_character_index)));
+		ElementUtilities::GetStringWidth(text_element, StringView(GetValue(), line.value_offset, cursor_character_index));
 	const float alignment_offset = GetAlignmentSpecificTextOffset(line);
 
 	cursor_position = {

+ 3 - 2
Source/Core/FontEngineDefault/FontEngineInterfaceDefault.cpp

@@ -27,6 +27,7 @@
  */
 
 #include "FontEngineInterfaceDefault.h"
+#include "../../../Include/RmlUi/Core/StringUtilities.h"
 #include "FontFaceHandleDefault.h"
 #include "FontProvider.h"
 
@@ -71,7 +72,7 @@ const FontMetrics& FontEngineInterfaceDefault::GetFontMetrics(FontFaceHandle han
 	return handle_default->GetFontMetrics();
 }
 
-int FontEngineInterfaceDefault::GetStringWidth(FontFaceHandle handle, const String& string, const TextShapingContext& text_shaping_context,
+int FontEngineInterfaceDefault::GetStringWidth(FontFaceHandle handle, StringView string, const TextShapingContext& text_shaping_context,
 	Character prior_character)
 {
 	auto handle_default = reinterpret_cast<FontFaceHandleDefault*>(handle);
@@ -79,7 +80,7 @@ int FontEngineInterfaceDefault::GetStringWidth(FontFaceHandle handle, const Stri
 }
 
 int FontEngineInterfaceDefault::GenerateString(RenderManager& render_manager, FontFaceHandle handle, FontEffectsHandle font_effects_handle,
-	const String& string, const Vector2f& position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
+	StringView string, Vector2f position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
 	TexturedMeshList& mesh_list)
 {
 	auto handle_default = reinterpret_cast<FontFaceHandleDefault*>(handle);

+ 3 - 4
Source/Core/FontEngineDefault/FontEngineInterfaceDefault.h

@@ -59,12 +59,11 @@ public:
 	const FontMetrics& GetFontMetrics(FontFaceHandle handle) override;
 
 	/// Returns the width a string will take up if rendered with this handle.
-	int GetStringWidth(FontFaceHandle handle, const String& string, const TextShapingContext& text_shaping_context,
-		Character prior_character) override;
+	int GetStringWidth(FontFaceHandle handle, StringView string, const TextShapingContext& text_shaping_context, Character prior_character) override;
 
 	/// Generates the geometry required to render a single line of text.
-	int GenerateString(RenderManager& render_manager, FontFaceHandle face_handle, FontEffectsHandle effects_handle, const String& string,
-		const Vector2f& position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
+	int GenerateString(RenderManager& render_manager, FontFaceHandle face_handle, FontEffectsHandle effects_handle, StringView string,
+		Vector2f position, ColourbPremultiplied colour, float opacity, const TextShapingContext& text_shaping_context,
 		TexturedMeshList& mesh_list) override;
 
 	/// Returns the current version of the font face.

+ 2 - 2
Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp

@@ -83,7 +83,7 @@ const FontGlyphMap& FontFaceHandleDefault::GetGlyphs() const
 	return glyphs;
 }
 
-int FontFaceHandleDefault::GetStringWidth(const String& string, float letter_spacing, Character prior_character)
+int FontFaceHandleDefault::GetStringWidth(StringView string, float letter_spacing, Character prior_character)
 {
 	RMLUI_ZoneScoped;
 
@@ -193,7 +193,7 @@ bool FontFaceHandleDefault::GenerateLayerTexture(Vector<byte>& texture_data, Vec
 	return it->layer->GenerateTexture(texture_data, texture_dimensions, texture_id, glyphs);
 }
 
-int FontFaceHandleDefault::GenerateString(RenderManager& render_manager, TexturedMeshList& mesh_list, const String& string, const Vector2f position,
+int FontFaceHandleDefault::GenerateString(RenderManager& render_manager, TexturedMeshList& mesh_list, StringView string, const Vector2f position,
 	const ColourbPremultiplied colour, const float opacity, const float letter_spacing, const int layer_configuration_index)
 {
 	RMLUI_ASSERT(layer_configuration_index >= 0);

+ 3 - 3
Source/Core/FontEngineDefault/FontFaceHandleDefault.h

@@ -61,7 +61,7 @@ public:
 	/// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string
 	/// width due to kerning.
 	/// @return The width, in pixels, this string will occupy if rendered with this handle.
-	int GetStringWidth(const String& string, float letter_spacing, Character prior_character = Character::Null);
+	int GetStringWidth(StringView string, float letter_spacing, Character prior_character = Character::Null);
 
 	/// Generates, if required, the layer configuration for a given list of font effects.
 	/// @param[in] font_effects The list of font effects to generate the configuration for.
@@ -86,8 +86,8 @@ public:
 	/// @param[in] letter_spacing The letter spacing size in pixels.
 	/// @param[in] layer_configuration Face configuration index to use for generating string.
 	/// @return The width, in pixels, of the string geometry.
-	int GenerateString(RenderManager& render_manager, TexturedMeshList& mesh_list, const String& string, Vector2f position,
-		ColourbPremultiplied colour, float opacity, float letter_spacing, int layer_configuration);
+	int GenerateString(RenderManager& render_manager, TexturedMeshList& mesh_list, StringView string, Vector2f position, ColourbPremultiplied colour,
+		float opacity, float letter_spacing, int layer_configuration);
 
 	/// Version is changed whenever the layers are dirtied, requiring regeneration of string geometry.
 	int GetVersion() const;

+ 3 - 2
Source/Core/FontEngineInterface.cpp

@@ -27,6 +27,7 @@
  */
 
 #include "../../Include/RmlUi/Core/FontEngineInterface.h"
+#include "../../Include/RmlUi/Core/StringUtilities.h"
 
 namespace Rml {
 
@@ -66,14 +67,14 @@ const FontMetrics& FontEngineInterface::GetFontMetrics(FontFaceHandle /*handle*/
 	return metrics;
 }
 
-int FontEngineInterface::GetStringWidth(FontFaceHandle /*handle*/, const String& /*string*/, const TextShapingContext& /*text_shaping_context*/,
+int FontEngineInterface::GetStringWidth(FontFaceHandle /*handle*/, StringView /*string*/, const TextShapingContext& /*text_shaping_context*/,
 	Character /*prior_character*/)
 {
 	return 0;
 }
 
 int FontEngineInterface::GenerateString(RenderManager& /*render_manager*/, FontFaceHandle /*face_handle*/, FontEffectsHandle /*font_effects_handle*/,
-	const String& /*string*/, const Vector2f& /*position*/, ColourbPremultiplied /*colour*/, float /*opacity*/,
+	StringView /*string*/, Vector2f /*position*/, ColourbPremultiplied /*colour*/, float /*opacity*/,
 	const TextShapingContext& /*text_shaping_context*/, TexturedMeshList& /*mesh_list*/)
 {
 	return 0;