LibWeb: Use actual line height to calculate float y in IFC

Before, we were using the line height from NodeWithStyle::line_height()
 to calculate the y offset for floats inside the IFC. However, this
value doesn't always correspond to the actual height of a line box. For
instance, adding a fragment for an inline-block might change the height
of the line box. With this change, we recalculate the height of the
line box after adding a new fragment and use this recalculated height
value to determine the y position for floats.

Fixes https://github.com/SerenityOS/serenity/issues/20982
This commit is contained in:
Aliaksandr Kalenik 2023-09-09 15:39:22 +02:00 committed by Andreas Kling
parent 6ab11e5f44
commit df2bc8187c
4 changed files with 50 additions and 3 deletions

View file

@ -0,0 +1,28 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (1,1) content-size 798x250.03125 [BFC] children: not-inline
BlockContainer <body> at (10,10) content-size 780x21.46875 children: not-inline
BlockContainer <div.Layout-sidebar> at (11,11) content-size 220x19.46875 children: inline
line 0 width: 102, height: 19.46875, bottom: 19.46875, baseline: 14.53125
frag 0 from BlockContainer start: 0, length: 0, rect: [12,12 100x17.46875]
BlockContainer <div.d-inline-block> at (12,12) content-size 100x17.46875 inline-block [BFC] children: inline
line 0 width: 69.734375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
frag 0 from TextNode start: 0, length: 12, rect: [12,12 69.734375x17.46875]
"floats!!!!!!"
TextNode <#text>
BlockContainer <div.float-left> at (12,31.46875) content-size 232.71875x218.5625 floating [BFC] children: inline
line 0 width: 232.71875, height: 109.1875, bottom: 109.1875, baseline: 84.578125
frag 0 from TextNode start: 0, length: 5, rect: [12,31.46875 232.71875x109.1875]
"float"
line 1 width: 164.0625, height: 109.375, bottom: 218.5625, baseline: 84.578125
frag 0 from TextNode start: 6, length: 4, rect: [12,140.46875 164.0625x109.1875]
"left"
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x252.03125]
PaintableWithLines (BlockContainer<BODY>) [9,9 782x23.46875]
PaintableWithLines (BlockContainer<DIV>.Layout-sidebar) [10,10 222x21.46875]
PaintableWithLines (BlockContainer<DIV>.d-inline-block) [11,11 102x19.46875]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.float-left) [11,30.46875 234.71875x220.5625]
TextPaintable (TextNode<#text>)

View file

@ -0,0 +1,18 @@
<!DOCTYPE html><style type="text/css">
* {
border: 1px solid black;
}
.float-left {
float: left;
font-size: 100px;
}
.d-inline-block {
display: inline-block;
width: 100px;
background-color: sandybrown;
}
.Layout-sidebar {
width: 220px;
background-color: beige;
}
</style><div class="Layout-sidebar"><div class="d-inline-block">floats!!!!!!</div><div class="float-left">float left</div></div>

View file

@ -29,6 +29,7 @@ void LineBox::add_fragment(Node const& layout_node, int start, int length, CSSPi
m_fragments.append(LineBoxFragment { layout_node, start, length, CSSPixelPoint(x_offset, y_offset), CSSPixelSize(content_width, content_height), border_box_top, border_box_bottom });
}
m_width += leading_margin + leading_size + content_width + trailing_size + trailing_margin;
m_height = max(m_height, content_height + border_box_top + border_box_bottom);
}
void LineBox::trim_trailing_whitespace()

View file

@ -111,11 +111,11 @@ CSSPixels LineBuilder::y_for_float_to_be_inserted_here(Box const& box)
CSSPixels candidate_y = m_current_y;
CSSPixels current_line_width = ensure_last_line_box().width();
auto const& current_line = ensure_last_line_box();
// If there's already inline content on the current line, check if the new float can fit
// alongside the content. If not, place it on the next line.
if (current_line_width > 0 && (current_line_width + width) > m_available_width_for_current_line)
candidate_y += m_context.containing_block().line_height();
if (current_line.width() > 0 && (current_line.width() + width) > m_available_width_for_current_line)
candidate_y += current_line.height();
// Then, look for the next Y position where we can fit the new float.
// FIXME: This is super dumb, we move 1px downwards per iteration and stop