From 36304f384dc676ac6bc4c94b699181168df5bb18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Wed, 29 Oct 2025 01:40:16 -0300 Subject: [PATCH] Fixes --- src/eepp/graphics/text.cpp | 44 +++- src/tests/ui_perf_test/ui_perf_test.cpp | 308 +++++++++++++----------- 2 files changed, 197 insertions(+), 155 deletions(-) diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index 2dcf17e40..a53156755 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -293,26 +293,46 @@ FontTrueType* TextShapeRun::font() { } void TextShapeRun::findNextEnd() { - Font* lFont = mStartFont; + Font* lFont = mStartFont ? mStartFont : mFont; std::size_t len = mString.size(); - std::size_t idx; std::size_t pos = 0; - for ( idx = mIndex; idx < len; idx++, pos++ ) { - Font* font = mFont - ->getGlyph( mString[idx], mCharacterSize, mStyle & Text::Bold, - mStyle & Text::Italic, mOutlineThickness ) - .font; - mIsNewLine = mString[idx] == '\n'; - if ( mIsNewLine || ( lFont != nullptr && font != lFont ) ) { - mCurFont = lFont; + Uint32 curScript = 0; + + for ( std::size_t idx = mIndex; idx < len; ++idx, ++pos ) { + auto ch = mString[idx]; + hb_script_t script = hb_unicode_script( hb_unicode_funcs_get_default(), ch ); + auto font = mFont + ->getGlyph( ch, mCharacterSize, mStyle & Text::Bold, mStyle & Text::Italic, + mOutlineThickness ) + .font; + mIsNewLine = ( ch == '\n' ); + + if ( idx == mIndex ) { + curScript = script; mStartFont = font; + lFont = font; + mCurFont = font; + } + + // Break run if: + // - Newline + // - Font changed + // - Script changed + hb_script_t effectiveScript = + ( script == HB_SCRIPT_COMMON ) ? (hb_script_t)curScript : script; + if ( mIsNewLine || ( lFont != nullptr && font != lFont ) || + effectiveScript != curScript ) { mLen = mIsNewLine ? pos + 1 : pos; + mCurFont = lFont; return; } + lFont = font; mCurFont = font; + curScript = script; } - mLen = idx; + + mLen = len - mIndex; } Float Text::tabAdvance( Float hspace, Uint32 tabWidth, std::optional tabOffset ) { @@ -1550,7 +1570,7 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos, bool returnNearest, Font* width = 0; lHeight = height; height += vspace; - if ( pos.x > width && pos.y <= lHeight ) { + if ( pos.x > width && pos.y <= lHeight && glyphCount > 0 ) { nearest = run.pos() + glyphInfo[glyphCount - 1].cluster + 1; return false; } diff --git a/src/tests/ui_perf_test/ui_perf_test.cpp b/src/tests/ui_perf_test/ui_perf_test.cpp index 2e18e6027..36d395e52 100644 --- a/src/tests/ui_perf_test/ui_perf_test.cpp +++ b/src/tests/ui_perf_test/ui_perf_test.cpp @@ -152,6 +152,25 @@ void mainLoop() { } EE_MAIN_FUNC int main( int, char*[] ) { + { + Text::TextShaperEnabled = true; + UIApplication app( WindowSettings( 1024, 650, "eepp - TextEdit", WindowStyle::Default, + WindowBackend::Default, 32, {}, 1, false, true ), + UIApplication::Settings( {}, 1.5f ) ); + FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); + auto ll = UILinearLayout::NewVertical(); + ll->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + auto editor = UICodeEditor::New(); + editor->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + editor->setParent( ll ); + editor->setLineWrapMode( LineWrapMode::Word ); + editor->setFont( FontManager::instance()->getByName( "monospace" ) ); + editor->loadFromFile( "unit_tests/assets/textfiles/test-arabic.uext" ); + // editor->loadFromFile( "unit_tests/assets/textfiles/test-flags.uext" ); + // editor->loadFromFile( "unit_tests/assets/textformat/english.utf8.lf.nobom.txt" ); + return app.run(); + } + win = Engine::instance()->createWindow( WindowSettings( 1366, 768, "eepp - UI Perf Test" ), ContextSettings( false ) ); @@ -199,50 +218,50 @@ EE_MAIN_FUNC int main( int, char*[] ) { ->setDefaultFont( font ) ->add( theme ); -/* - auto* vlay = UILinearLayout::NewVertical(); - vlay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + /* + auto* vlay = UILinearLayout::NewVertical(); + vlay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); - Clock clock; - auto model = FileSystemModel::New( "." ); // std::make_shared(); - // UITreeView* view = UITreeView::New(); - UITableView* view = UITableView::New(); - // view->setExpanderIconSize( PixelDensity::dpToPx( 20 ) ); - view->setId( "treeview" ); - view->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); - view->setParent( vlay ); - view->setModel( SortingProxyModel::New( model ) ); - Log::notice( "Total time: %.2fms", clock.getElapsedTime().asMilliseconds() ); - */ + Clock clock; + auto model = FileSystemModel::New( "." ); // std::make_shared(); + // UITreeView* view = UITreeView::New(); + UITableView* view = UITableView::New(); + // view->setExpanderIconSize( PixelDensity::dpToPx( 20 ) ); + view->setId( "treeview" ); + view->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + view->setParent( vlay ); + view->setModel( SortingProxyModel::New( model ) ); + Log::notice( "Total time: %.2fms", clock.getElapsedTime().asMilliseconds() ); + */ /* ListBox test */ -/* - std::vector strings; - for ( size_t i = 0; i < 10000; i++ ) - strings.emplace_back( String::format( - "This is a very long string number %ld. Cover the full width of the listbox.", - i ) ); - auto* lbox = UIListBox::New(); - std::cout << "Time New: " << clock.getElapsedTime().asMilliseconds() << " ms" << std::endl; - lbox->setParent( vlay ); - std::cout << "Time setParent: " << clock.getElapsedTime().asMilliseconds() << " ms" - << std::endl; - lbox->setLayoutMargin( Rectf( 4, 4, 4, 4 ) ); - std::cout << "Time setLayoutMargin: " << clock.getElapsedTime().asMilliseconds() << " ms" - << std::endl; - lbox->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); - std::cout << "Time setLayoutSizePolicy: " << clock.getElapsedTime().asMilliseconds() - << " ms" << std::endl; - for ( size_t i = 0; i < 10; i++ ) - lbox->addListBoxItem( String::format( - "This is a very long string number %ld. Cover the full width of the listbox.", - i ) ); - std::cout << "Time addListBoxItem: " << clock.getElapsedTime().asMilliseconds() << " ms" - << std::endl; - lbox->addListBoxItems( strings ); - std::cout << "Time addListBoxItems: " << clock.getElapsedTime().asMilliseconds() << " ms" - << std::endl; - */ + /* + std::vector strings; + for ( size_t i = 0; i < 10000; i++ ) + strings.emplace_back( String::format( + "This is a very long string number %ld. Cover the full width of the + listbox.", i ) ); auto* lbox = UIListBox::New(); std::cout << "Time New: " << + clock.getElapsedTime().asMilliseconds() << " ms" << std::endl; lbox->setParent( vlay ); + std::cout << "Time setParent: " << clock.getElapsedTime().asMilliseconds() << " ms" + << std::endl; + lbox->setLayoutMargin( Rectf( 4, 4, 4, 4 ) ); + std::cout << "Time setLayoutMargin: " << clock.getElapsedTime().asMilliseconds() << + " ms" + << std::endl; + lbox->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + std::cout << "Time setLayoutSizePolicy: " << clock.getElapsedTime().asMilliseconds() + << " ms" << std::endl; + for ( size_t i = 0; i < 10; i++ ) + lbox->addListBoxItem( String::format( + "This is a very long string number %ld. Cover the full width of the + listbox.", i ) ); std::cout << "Time addListBoxItem: " << + clock.getElapsedTime().asMilliseconds() << " ms" + << std::endl; + lbox->addListBoxItems( strings ); + std::cout << "Time addListBoxItems: " << clock.getElapsedTime().asMilliseconds() << + " ms" + << std::endl; + */ Clock total; /* Create Widget test */ @@ -277,7 +296,8 @@ EE_MAIN_FUNC int main( int, char*[] ) { but->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); but->setParent( parent )->clipEnable(); } - std::cout << "Time 10k UIPushButton total: " << total.getElapsedTime().toString() << std::endl; + std::cout << "Time 10k UIPushButton total: " << total.getElapsedTime().toString() + << std::endl; // uiSceneNode->getRoot()->closeAllChildren(); total.restart(); @@ -285,115 +305,117 @@ EE_MAIN_FUNC int main( int, char*[] ) { std::cout << "SceneManager::instance()->update(): " << total.getElapsedTime().toString() << std::endl; -/* - auto* main = UIRelativeLayout::New(); - main->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); - auto* sv = UIScrollView::New(); - sv->setParent( main ); - sv->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); - sv->setPixelsSize( win->getSize().asFloat() ); - auto* vlay = UILinearLayout::NewVertical(); - vlay->setParent( sv ); - vlay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); + /* + auto* main = UIRelativeLayout::New(); + main->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + auto* sv = UIScrollView::New(); + sv->setParent( main ); + sv->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + sv->setPixelsSize( win->getSize().asFloat() ); + auto* vlay = UILinearLayout::NewVertical(); + vlay->setParent( sv ); + vlay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); - total.restart(); - for ( size_t i = 0; i < 100000; i++ ) { - auto* widget = UIWidget::New(); - widget->setParent( vlay ); - widget->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed ); - widget->setSize( Sizef( 0, 4 ) ); - Colorf col; - col.hsv.h = Math::randf( 0, 360 ); - col.hsv.s = 1; - col.hsv.v = 1; - col.hsv.a = 1; - widget->setBackgroundColor( Color::fromHsv( col ) ); - } - std::cout << "Time UIWidget total: " << total.getElapsedTime().asMilliseconds() << " ms" - << std::endl; - */ -/* - UIWindow* wind = UIWindow::New(); - wind->setSize( 500, 500 ); - wind->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_RESIZEABLE | UI_WIN_MAXIMIZE_BUTTON ); + total.restart(); + for ( size_t i = 0; i < 100000; i++ ) { + auto* widget = UIWidget::New(); + widget->setParent( vlay ); + widget->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed ); + widget->setSize( Sizef( 0, 4 ) ); + Colorf col; + col.hsv.h = Math::randf( 0, 360 ); + col.hsv.s = 1; + col.hsv.v = 1; + col.hsv.a = 1; + widget->setBackgroundColor( Color::fromHsv( col ) ); + } + std::cout << "Time UIWidget total: " << total.getElapsedTime().asMilliseconds() << " + ms" + << std::endl; + */ + /* + UIWindow* wind = UIWindow::New(); + wind->setSize( 500, 500 ); + wind->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_RESIZEABLE | + UI_WIN_MAXIMIZE_BUTTON ); - UILinearLayout* layWin = UILinearLayout::NewVertical(); - layWin->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); - layWin->setParent( wind ); + UILinearLayout* layWin = UILinearLayout::NewVertical(); + layWin->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + layWin->setParent( wind ); - UILinearLayout* layPar = UILinearLayout::NewHorizontal(); - layPar->setParent( layWin ); - layPar->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ); - layPar->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); - layPar->setLayoutGravity( UI_VALIGN_CENTER | UI_HALIGN_CENTER ); - layPar->setBackgroundColor( 0x999999FF ); + UILinearLayout* layPar = UILinearLayout::NewHorizontal(); + layPar->setParent( layWin ); + layPar->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ); + layPar->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); + layPar->setLayoutGravity( UI_VALIGN_CENTER | UI_HALIGN_CENTER ); + layPar->setBackgroundColor( 0x999999FF ); - UILinearLayout* lay = UILinearLayout::NewVertical(); - lay->setLayoutGravity( UI_HALIGN_CENTER | UI_VALIGN_CENTER ); - lay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); - lay->setBackgroundColor( 0x333333FF ); - lay->setLayoutWeight( 0.7f ); + UILinearLayout* lay = UILinearLayout::NewVertical(); + lay->setLayoutGravity( UI_HALIGN_CENTER | UI_VALIGN_CENTER ); + lay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); + lay->setBackgroundColor( 0x333333FF ); + lay->setLayoutWeight( 0.7f ); - UITextView::New() - ->setText( "Text on test 1" ) - ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) - ->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::WrapContent ) - ->setParent( lay ); - UITextView::New() - ->setText( "Text on test 2" ) - ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) - ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) - ->setParent( lay ); - UICheckBox::New() - ->setText( "Checkbox" ) - ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) - ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) - ->setParent( lay ); - UITextView::New() - ->setText( "Text on test 3" ) - ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) - ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) - ->setParent( lay ); - UITextView::New() - ->setText( "Text on test 4" ) - ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) - ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) - ->setParent( lay ); - UITextInput::New() - ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) - ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) - ->setParent( lay ); + UITextView::New() + ->setText( "Text on test 1" ) + ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) + ->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::WrapContent ) + ->setParent( lay ); + UITextView::New() + ->setText( "Text on test 2" ) + ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) + ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) + ->setParent( lay ); + UICheckBox::New() + ->setText( "Checkbox" ) + ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) + ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) + ->setParent( lay ); + UITextView::New() + ->setText( "Text on test 3" ) + ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) + ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) + ->setParent( lay ); + UITextView::New() + ->setText( "Text on test 4" ) + ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) + ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) + ->setParent( lay ); + UITextInput::New() + ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) + ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) + ->setParent( lay ); - UILinearLayout* lay2 = UILinearLayout::NewVertical(); - lay2->setId( "hardlay" ); - lay2->setLayoutGravity( UI_HALIGN_CENTER | UI_VALIGN_CENTER ); - lay2->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::WrapContent ); - lay2->setBackgroundColor( Color::Black ); - lay2->setLayoutWeight( 0.3f ); + UILinearLayout* lay2 = UILinearLayout::NewVertical(); + lay2->setId( "hardlay" ); + lay2->setLayoutGravity( UI_HALIGN_CENTER | UI_VALIGN_CENTER ); + lay2->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::WrapContent ); + lay2->setBackgroundColor( Color::Black ); + lay2->setLayoutWeight( 0.3f ); - UIPushButton::New() - ->setText( "PushButton" ) - ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) - ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) - ->setLayoutGravity( UI_VALIGN_CENTER ) - ->setParent( lay2 ); - UIListBox* lbox = UIListBox::New(); - lbox->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) - ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed ) - ->setSize( 0, 105 ) - ->setParent( lay2 ); - lbox->addListBoxItems( { "This", "is", "a", "ListBox" } ); - lay2->setParent( layPar ); - lay->setParent( layPar ); + UIPushButton::New() + ->setText( "PushButton" ) + ->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) + ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) + ->setLayoutGravity( UI_VALIGN_CENTER ) + ->setParent( lay2 ); + UIListBox* lbox = UIListBox::New(); + lbox->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) + ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed ) + ->setSize( 0, 105 ) + ->setParent( lay2 ); + lbox->addListBoxItems( { "This", "is", "a", "ListBox" } ); + lay2->setParent( layPar ); + lay->setParent( layPar ); - UIDropDownList* drop = UIDropDownList::New(); - drop->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) - ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) - ->setParent( layWin ); - drop->getListBox()->addListBoxItems( { "Car", "Bus", "Plane", "Submarine" } ); - drop->getListBox()->setSelected( 0 ); - wind->show(); - */ + UIDropDownList* drop = UIDropDownList::New(); + drop->setLayoutMargin( Rectf( 10, 10, 10, 10 ) ) + ->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ) + ->setParent( layWin ); + drop->getListBox()->addListBoxItems( { "Car", "Bus", "Plane", "Submarine" } ); + drop->getListBox()->setSelected( 0 ); + wind->show(); + */ win->runMainLoop( &mainLoop ); }