From f54f8de67c87dc9ff7b0bb1f4a92687844d2d065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Wed, 12 Nov 2025 09:55:24 -0300 Subject: [PATCH] Some optimizations for the TextLayouter. --- src/eepp/graphics/textlayouter.cpp | 62 +++++++++++++++++++----------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/src/eepp/graphics/textlayouter.cpp b/src/eepp/graphics/textlayouter.cpp index a0b0874df..dcb54e330 100644 --- a/src/eepp/graphics/textlayouter.cpp +++ b/src/eepp/graphics/textlayouter.cpp @@ -6,6 +6,7 @@ #ifdef EE_TEXT_SHAPER_ENABLED #include +#include #include #include #endif @@ -23,12 +24,44 @@ struct TextSegment { hb_direction_t direction{}; }; +static inline bool isSimpleScript( hb_script_t script ) { + return script == HB_SCRIPT_LATIN || script == HB_SCRIPT_GREEK || script == HB_SCRIPT_CYRILLIC || + script == HB_SCRIPT_INVALID || script == HB_SCRIPT_COMMON; +} + +// Helper function to get a thread-local, reusable HarfBuzz buffer. +static hb_buffer_t* getThreadLocalHbBuffer() { + struct HbBufferDeleter { + void operator()( hb_buffer_t* buf ) const { + if ( buf ) + hb_buffer_destroy( buf ); + } + }; + thread_local static std::unique_ptr sHbBuffer( + hb_buffer_create() ); + return sHbBuffer.get(); +} + +// Helper function to get a thread-local, reusable SheenBidi script locator. +static SBScriptLocator* getThreadLocalSbScriptLocator() { + // Custom deleter for SBScriptLocator + struct SbScriptLocatorDeleter { + void operator()( SBScriptLocator* loc ) const { + if ( loc ) + SBScriptLocatorRelease( loc ); + } + }; + + thread_local static std::unique_ptr sSbScriptLocator( + SBScriptLocatorCreate() ); + return sSbScriptLocator.get(); +} + // Split string into segments with uniform text properties -static void segmentString( String::View input, - std::function cb ) { +template static void segmentString( String::View input, Callable cb ) { const SBCodepointSequence codepointSequence{ SBStringEncodingUTF32, static_cast( input.data() ), input.size() }; - auto* const scriptLocator = SBScriptLocatorCreate(); + auto* const scriptLocator = getThreadLocalSbScriptLocator(); auto* const algorithm = SBAlgorithmCreate( &codepointSequence ); SBUInteger paragraphOffset = 0; @@ -83,22 +116,13 @@ static void segmentString( String::View input, } SBAlgorithmRelease( algorithm ); - SBScriptLocatorRelease( scriptLocator ); } -static inline bool isSimpleScript( hb_script_t script ) { - return script == HB_SCRIPT_LATIN || script == HB_SCRIPT_GREEK || script == HB_SCRIPT_CYRILLIC || - script == HB_SCRIPT_INVALID || script == HB_SCRIPT_COMMON; -} - -static bool shapeAndRun( const String& string, FontTrueType* font, Uint32 characterSize, - Uint32 style, Float outlineThickness, - const std::function& cb ) { +template +static void shapeAndRun( const String& string, FontTrueType* font, Uint32 characterSize, + Uint32 style, Float outlineThickness, Callable cb ) { String::View input = string.view(); - hb_buffer_t* hbBuffer = hb_buffer_create(); - bool completeRun = true; + hb_buffer_t* hbBuffer = getThreadLocalHbBuffer(); segmentString( input, [&]( const TextSegment& segment ) { TextShapeRun run( input.substr( segment.offset, segment.length ), font, characterSize, @@ -141,7 +165,6 @@ static bool shapeAndRun( const String& string, FontTrueType* font, Uint32 charac if ( !font || !font->hb() ) { eeASSERT( font && font->hb() ); - completeRun = false; break; } @@ -156,17 +179,12 @@ static bool shapeAndRun( const String& string, FontTrueType* font, Uint32 charac if ( cb( glyphInfo, glyphPos, glyphCount, props, segment, run ) ) run.next(); else { - completeRun = false; return false; - break; } } return true; } ); - - hb_buffer_destroy( hbBuffer ); - return completeRun; } #endif