diff --git a/src/eepp/graphics/richtext.cpp b/src/eepp/graphics/richtext.cpp index 1344d9f53..505972027 100644 --- a/src/eepp/graphics/richtext.cpp +++ b/src/eepp/graphics/richtext.cpp @@ -1379,24 +1379,25 @@ class RichTextInlineLayouter { result.lines.back().y = curY; } Float placedY = curY; - bool moved; - do { - moved = false; + while ( true ) { + Float nextPlacedY = placedY; for ( const auto& propagated : *payload.propagatedFloats ) { Rectf rect = propagated.rect; rect.move( { curX, placedY } ); auto avoidActiveFloat = [&]( const Rectf& active ) { - if ( rect.intersect( active ) && active.Bottom > placedY ) { - placedY += active.Bottom - rect.Top; - moved = true; - } + if ( rect.intersect( active ) ) + nextPlacedY = std::max( + nextPlacedY, placedY + active.Bottom - rect.Top ); }; for ( const auto& active : leftFloats ) avoidActiveFloat( active ); for ( const auto& active : rightFloats ) avoidActiveFloat( active ); } - } while ( moved ); + if ( nextPlacedY <= placedY + 0.01f ) + break; + placedY = nextPlacedY; + } if ( placedY > curY ) { curY = placedY; result.lines.back().y = curY; diff --git a/src/tests/unit_tests/uihtml_float_tests.cpp b/src/tests/unit_tests/uihtml_float_tests.cpp index 304a1a044..194447d71 100644 --- a/src/tests/unit_tests/uihtml_float_tests.cpp +++ b/src/tests/unit_tests/uihtml_float_tests.cpp @@ -61,6 +61,24 @@ UTEST( UIHTMLFloat, structure_FloatAndClearEnums ) { EXPECT_EQ( (int)CSSClear::None, (int)CSSClearHelper::fromString( "garbage" ) ); } +UTEST( UIHTMLFloat, propagatedFloatTouchingActiveFloatMakesForwardProgress ) { + RichText richText; + richText.setMaxWidth( 200.f ); + richText.setExternalFloatExclusions( + { { Rectf( 0.f, 0.f, 100.f, 20.f ), RichText::InlineFloat::Left } } ); + + auto propagated = std::make_shared>(); + propagated->push_back( { Rectf( -100.f, 20.f, 10.f, 30.f ), RichText::InlineFloat::Left } ); + richText.addCustomSize( { 20.f, 10.f }, RichText::InlineFloat::None, + RichText::InlineClear::None, -1.f, {}, {}, false, false, propagated ); + + const Sizef size = richText.getSize(); + EXPECT_TRUE( std::isfinite( size.getWidth() ) ); + EXPECT_TRUE( std::isfinite( size.getHeight() ) ); + EXPECT_GT( size.getWidth(), 0.f ); + EXPECT_GT( size.getHeight(), 0.f ); +} + UTEST( UIHTMLFloat, property_DefaultsAreNone ) { UIHTMLWidget* w = UIHTMLWidget::New(); EXPECT_EQ( CSSFloat::None, w->getCSSFloat() );