mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-09-26 22:00:01 +03:00
fix rich text propagated float placement loop
- require propagated float placement to make forward progress - avoid zero-displacement loops when float edges touch - recompute collisions after each vertical adjustment - add regression coverage for touching propagated and active floats
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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<std::vector<RichText::FloatExclusion>>();
|
||||
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() );
|
||||
|
||||
Reference in New Issue
Block a user