mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 18:50:16 +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;
|
result.lines.back().y = curY;
|
||||||
}
|
}
|
||||||
Float placedY = curY;
|
Float placedY = curY;
|
||||||
bool moved;
|
while ( true ) {
|
||||||
do {
|
Float nextPlacedY = placedY;
|
||||||
moved = false;
|
|
||||||
for ( const auto& propagated : *payload.propagatedFloats ) {
|
for ( const auto& propagated : *payload.propagatedFloats ) {
|
||||||
Rectf rect = propagated.rect;
|
Rectf rect = propagated.rect;
|
||||||
rect.move( { curX, placedY } );
|
rect.move( { curX, placedY } );
|
||||||
auto avoidActiveFloat = [&]( const Rectf& active ) {
|
auto avoidActiveFloat = [&]( const Rectf& active ) {
|
||||||
if ( rect.intersect( active ) && active.Bottom > placedY ) {
|
if ( rect.intersect( active ) )
|
||||||
placedY += active.Bottom - rect.Top;
|
nextPlacedY = std::max(
|
||||||
moved = true;
|
nextPlacedY, placedY + active.Bottom - rect.Top );
|
||||||
}
|
|
||||||
};
|
};
|
||||||
for ( const auto& active : leftFloats )
|
for ( const auto& active : leftFloats )
|
||||||
avoidActiveFloat( active );
|
avoidActiveFloat( active );
|
||||||
for ( const auto& active : rightFloats )
|
for ( const auto& active : rightFloats )
|
||||||
avoidActiveFloat( active );
|
avoidActiveFloat( active );
|
||||||
}
|
}
|
||||||
} while ( moved );
|
if ( nextPlacedY <= placedY + 0.01f )
|
||||||
|
break;
|
||||||
|
placedY = nextPlacedY;
|
||||||
|
}
|
||||||
if ( placedY > curY ) {
|
if ( placedY > curY ) {
|
||||||
curY = placedY;
|
curY = placedY;
|
||||||
result.lines.back().y = curY;
|
result.lines.back().y = curY;
|
||||||
|
|||||||
@@ -61,6 +61,24 @@ UTEST( UIHTMLFloat, structure_FloatAndClearEnums ) {
|
|||||||
EXPECT_EQ( (int)CSSClear::None, (int)CSSClearHelper::fromString( "garbage" ) );
|
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 ) {
|
UTEST( UIHTMLFloat, property_DefaultsAreNone ) {
|
||||||
UIHTMLWidget* w = UIHTMLWidget::New();
|
UIHTMLWidget* w = UIHTMLWidget::New();
|
||||||
EXPECT_EQ( CSSFloat::None, w->getCSSFloat() );
|
EXPECT_EQ( CSSFloat::None, w->getCSSFloat() );
|
||||||
|
|||||||
Reference in New Issue
Block a user