mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-11 05:25:32 +03:00
LibWeb: Consider margins of atomic inlines in layout
According to CSS Inline Layout Module Level 3 § 2.2 Step 1. atomic inlines should be layed out in a line box based on their margin box. However, up until this patch we were unconditionally considering only the border box during line box height calculation. This made us essentially drop all vertical margins for atomic inlines.
This commit is contained in:
parent
0aa4466ce9
commit
b96920a9d6
Notes:
sideshowbarker
2024-07-19 01:59:31 +09:00
Author: https://github.com/fahrradflucht Commit: https://github.com/SerenityOS/serenity/commit/b96920a9d6 Pull-request: https://github.com/SerenityOS/serenity/pull/17848
@ -0,0 +1,12 @@
|
||||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (0,0) content-size 800x191 children: not-inline
|
||||
BlockContainer <body> at (8,8) content-size 784x175 children: inline
|
||||
line 0 width: 210.828125, height: 175, bottom: 175, baseline: 13.53125
|
||||
frag 0 from TextNode start: 0, length: 6, rect: [8,8 43.125x17.46875]
|
||||
"Well, "
|
||||
frag 1 from BlockContainer start: 0, length: 0, rect: [51,58 100x100]
|
||||
frag 2 from TextNode start: 0, length: 9, rect: [151,8 67.703125x17.46875]
|
||||
" friends."
|
||||
TextNode <#text>
|
||||
BlockContainer <div#inline-box> at (51,58) content-size 100x100 inline-block children: not-inline
|
||||
TextNode <#text>
|
@ -0,0 +1,12 @@
|
||||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (0,0) content-size 800x194.46875 children: not-inline
|
||||
BlockContainer <body> at (8,8) content-size 784x178.46875 children: inline
|
||||
line 0 width: 210.828125, height: 178.46875, bottom: 178.46875, baseline: 175
|
||||
frag 0 from TextNode start: 0, length: 6, rect: [8,169 43.125x17.46875]
|
||||
"Well, "
|
||||
frag 1 from BlockContainer start: 0, length: 0, rect: [51,58 100x100]
|
||||
frag 2 from TextNode start: 0, length: 9, rect: [151,169 67.703125x17.46875]
|
||||
" friends."
|
||||
TextNode <#text>
|
||||
BlockContainer <div#inline-box> at (51,58) content-size 100x100 inline-block children: not-inline
|
||||
TextNode <#text>
|
@ -0,0 +1,12 @@
|
||||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (0,0) content-size 800x232.46875 children: not-inline
|
||||
BlockContainer <body> at (8,8) content-size 784x216.46875 children: inline
|
||||
line 0 width: 174.828125, height: 216.46875, bottom: 216.46875, baseline: 213
|
||||
frag 0 from TextNode start: 0, length: 6, rect: [8,207 43.125x17.46875]
|
||||
"Well, "
|
||||
frag 1 from ImageBox start: 0, length: 0, rect: [51,33 64x138]
|
||||
frag 2 from TextNode start: 0, length: 9, rect: [115,207 67.703125x17.46875]
|
||||
" friends."
|
||||
TextNode <#text>
|
||||
ImageBox <img#image> at (51,33) content-size 64x138 children: not-inline
|
||||
TextNode <#text>
|
BIN
Tests/LibWeb/Layout/input/buggie.png
Normal file
BIN
Tests/LibWeb/Layout/input/buggie.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
@ -0,0 +1,16 @@
|
||||
<style>
|
||||
body {
|
||||
font-family: 'SerenitySans';
|
||||
}
|
||||
|
||||
#inline-box {
|
||||
background-color: red;
|
||||
margin-top: 50px;
|
||||
margin-bottom: 25px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>Well, <div id="inline-box"></div> friends.
|
@ -0,0 +1,15 @@
|
||||
<style>
|
||||
body {
|
||||
font-family: 'SerenitySans';
|
||||
}
|
||||
|
||||
#inline-box {
|
||||
background-color: red;
|
||||
margin-top: 50px;
|
||||
margin-bottom: 25px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
|
||||
display: inline-block;
|
||||
}
|
||||
</style>Well, <div id="inline-box"></div> friends.
|
@ -0,0 +1,10 @@
|
||||
<style>
|
||||
body {
|
||||
font-family: 'SerenitySans';
|
||||
}
|
||||
|
||||
#image {
|
||||
margin-top: 25px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
</style>Well, <img id="image" src="buggie.png" /> friends.
|
@ -110,7 +110,7 @@ CSSPixels box_baseline(LayoutState const& state, Box const& box)
|
||||
return box_state.border_box_top();
|
||||
case CSS::VerticalAlign::Bottom:
|
||||
// Bottom: Align the bottom of the aligned subtree with the bottom of the line box.
|
||||
return box_state.content_height() + box_state.border_box_bottom();
|
||||
return box_state.content_height() + box_state.margin_box_top();
|
||||
case CSS::VerticalAlign::TextTop:
|
||||
// TextTop: Align the top of the box with the top of the parent's content area (see 10.6.1).
|
||||
return box.computed_values().font_size();
|
||||
@ -123,13 +123,13 @@ CSSPixels box_baseline(LayoutState const& state, Box const& box)
|
||||
}
|
||||
|
||||
if (!box_state.line_boxes.is_empty())
|
||||
return box_state.border_box_top() + box_state.offset.y() + box_state.line_boxes.last().baseline();
|
||||
return box_state.margin_box_top() + box_state.offset.y() + box_state.line_boxes.last().baseline();
|
||||
if (box.has_children() && !box.children_are_inline()) {
|
||||
auto const* child_box = box.last_child_of_type<Box>();
|
||||
VERIFY(child_box);
|
||||
return box_baseline(state, *child_box);
|
||||
}
|
||||
return box_state.border_box_height();
|
||||
return box_state.margin_box_height();
|
||||
}
|
||||
|
||||
CSSPixelRect margin_box_rect(Box const& box, LayoutState const& state)
|
||||
|
@ -149,4 +149,9 @@ CSSPixelRect LineBoxFragment::selection_rect(Gfx::Font const& font) const
|
||||
return {};
|
||||
}
|
||||
|
||||
bool LineBoxFragment::is_atomic_inline() const
|
||||
{
|
||||
return layout_node().is_replaced_box() || (layout_node().display().is_inline_outside() && !layout_node().display().is_flow_inside());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -76,6 +76,8 @@ public:
|
||||
|
||||
CSSPixelRect selection_rect(Gfx::Font const&) const;
|
||||
|
||||
bool is_atomic_inline() const;
|
||||
|
||||
private:
|
||||
Node const& m_layout_node;
|
||||
int m_start { 0 };
|
||||
|
@ -78,7 +78,7 @@ void LineBuilder::append_box(Box const& box, CSSPixels leading_size, CSSPixels t
|
||||
auto& box_state = m_layout_state.get_mutable(box);
|
||||
auto& line_box = ensure_last_line_box();
|
||||
line_box.add_fragment(box, 0, 0, leading_size, trailing_size, leading_margin, trailing_margin, box_state.content_width(), box_state.content_height(), box_state.border_box_top(), box_state.border_box_bottom());
|
||||
m_max_height_on_current_line = max(m_max_height_on_current_line, box_state.border_box_height());
|
||||
m_max_height_on_current_line = max(m_max_height_on_current_line, box_state.margin_box_height());
|
||||
|
||||
box_state.containing_line_box_fragment = LineBoxFragmentCoordinate {
|
||||
.line_box_index = m_containing_block_state.line_boxes.size() - 1,
|
||||
@ -235,11 +235,17 @@ void LineBuilder::update_last_line()
|
||||
CSSPixels new_fragment_y = 0;
|
||||
|
||||
auto y_value_for_alignment = [&](CSS::VerticalAlign vertical_align) {
|
||||
CSSPixels effective_box_top = fragment.border_box_top();
|
||||
if (fragment.is_atomic_inline()) {
|
||||
auto const& fragment_box_state = m_layout_state.get(static_cast<Box const&>(fragment.layout_node()));
|
||||
effective_box_top = fragment_box_state.margin_box_top();
|
||||
}
|
||||
|
||||
switch (vertical_align) {
|
||||
case CSS::VerticalAlign::Baseline:
|
||||
return m_current_y + line_box_baseline - fragment.baseline() + fragment.border_box_top();
|
||||
return m_current_y + line_box_baseline - fragment.baseline() + effective_box_top;
|
||||
case CSS::VerticalAlign::Top:
|
||||
return m_current_y + fragment.border_box_top();
|
||||
return m_current_y + effective_box_top;
|
||||
case CSS::VerticalAlign::Middle:
|
||||
case CSS::VerticalAlign::Bottom:
|
||||
case CSS::VerticalAlign::Sub:
|
||||
@ -247,7 +253,7 @@ void LineBuilder::update_last_line()
|
||||
case CSS::VerticalAlign::TextBottom:
|
||||
case CSS::VerticalAlign::TextTop:
|
||||
// FIXME: These are all 'baseline'
|
||||
return m_current_y + line_box_baseline - fragment.baseline() + fragment.border_box_top();
|
||||
return m_current_y + line_box_baseline - fragment.baseline() + effective_box_top;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
};
|
||||
@ -268,7 +274,7 @@ void LineBuilder::update_last_line()
|
||||
CSSPixels bottom_of_inline_box = 0;
|
||||
{
|
||||
// FIXME: Support inline-table elements.
|
||||
if (fragment.layout_node().is_replaced_box() || (fragment.layout_node().display().is_inline_outside() && !fragment.layout_node().display().is_flow_inside())) {
|
||||
if (fragment.is_atomic_inline()) {
|
||||
auto const& fragment_box_state = m_layout_state.get(static_cast<Box const&>(fragment.layout_node()));
|
||||
top_of_inline_box = (fragment.offset().y() - fragment_box_state.margin_box_top());
|
||||
bottom_of_inline_box = (fragment.offset().y() + fragment_box_state.content_height() + fragment_box_state.margin_box_bottom());
|
||||
|
Loading…
Reference in New Issue
Block a user