LibWeb: Fix handling of max-content containing block for floating box
Fixes layout of page toolbar on Wikipedia.
This commit is contained in:
parent
97ba1ff1f7
commit
b6f9f4c28c
Notes:
sideshowbarker
2024-07-17 01:11:48 +09:00
Author: https://github.com/axgallo Commit: https://github.com/SerenityOS/serenity/commit/b6f9f4c28c Pull-request: https://github.com/SerenityOS/serenity/pull/20540 Reviewed-by: https://github.com/kalenikaliaksandr ✅
5 changed files with 94 additions and 16 deletions
|
@ -0,0 +1,27 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x0 children: not-inline
|
||||||
|
Box <div.display_flex> at (8,8) content-size 23.609375x17.46875 floating flex-container(row) [FFC] children: not-inline
|
||||||
|
BlockContainer <div> at (8,8) content-size 23.609375x17.46875 flex-item [BFC] children: not-inline
|
||||||
|
BlockContainer <div> at (8,8) content-size 23.609375x17.46875 floating [BFC] children: not-inline
|
||||||
|
BlockContainer <span> at (8,8) content-size 14.265625x17.46875 floating [BFC] children: inline
|
||||||
|
line 0 width: 14.265625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [8,8 14.265625x17.46875]
|
||||||
|
"A"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <span> at (22.265625,8) content-size 9.34375x17.46875 floating [BFC] children: inline
|
||||||
|
line 0 width: 9.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [22.265625,8 9.34375x17.46875]
|
||||||
|
"B"
|
||||||
|
TextNode <#text>
|
||||||
|
|
||||||
|
PaintableWithLines (Viewport<#document>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [8,8 784x0] overflow: [8,8 23.609375x17.46875]
|
||||||
|
PaintableBox (Box<DIV>.display_flex) [8,8 23.609375x17.46875]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>) [8,8 23.609375x17.46875]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>) [8,8 23.609375x17.46875]
|
||||||
|
PaintableWithLines (BlockContainer<SPAN>) [8,8 14.265625x17.46875]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<SPAN>) [22.265625,8 9.34375x17.46875]
|
||||||
|
TextPaintable (TextNode<#text>)
|
|
@ -0,0 +1,23 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x0 children: not-inline
|
||||||
|
BlockContainer <div> at (8,8) content-size 23.609375x17.46875 floating [BFC] children: not-inline
|
||||||
|
BlockContainer <span> at (8,8) content-size 14.265625x17.46875 floating [BFC] children: inline
|
||||||
|
line 0 width: 14.265625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [8,8 14.265625x17.46875]
|
||||||
|
"A"
|
||||||
|
TextNode <#text>
|
||||||
|
BlockContainer <span> at (22.265625,8) content-size 9.34375x17.46875 floating [BFC] children: inline
|
||||||
|
line 0 width: 9.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||||
|
frag 0 from TextNode start: 0, length: 1, rect: [22.265625,8 9.34375x17.46875]
|
||||||
|
"B"
|
||||||
|
TextNode <#text>
|
||||||
|
|
||||||
|
PaintableWithLines (Viewport<#document>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [8,8 784x0] overflow: [8,8 23.609375x17.46875]
|
||||||
|
PaintableWithLines (BlockContainer<DIV>) [8,8 23.609375x17.46875]
|
||||||
|
PaintableWithLines (BlockContainer<SPAN>) [8,8 14.265625x17.46875]
|
||||||
|
TextPaintable (TextNode<#text>)
|
||||||
|
PaintableWithLines (BlockContainer<SPAN>) [22.265625,8 9.34375x17.46875]
|
||||||
|
TextPaintable (TextNode<#text>)
|
|
@ -0,0 +1,13 @@
|
||||||
|
<style>
|
||||||
|
.display_flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
</style><div class="display_flex"><div><div><span>A</span><span>B</span></div></div></div>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
</style><div><span>A</span><span>B</span></div>
|
|
@ -290,10 +290,7 @@ void BlockFormattingContext::compute_width_for_floating_box(Box const& box, Avai
|
||||||
auto& computed_values = box.computed_values();
|
auto& computed_values = box.computed_values();
|
||||||
|
|
||||||
auto zero_value = CSS::Length::make_px(0);
|
auto zero_value = CSS::Length::make_px(0);
|
||||||
auto width_of_containing_block = available_space.width.to_px_or_zero();
|
auto width_of_containing_block_as_length_for_resolve = CSS::Length::make_px(available_space.width.to_px_or_zero());
|
||||||
auto width_of_containing_block_as_length_for_resolve = CSS::Length::make_px(width_of_containing_block);
|
|
||||||
if (!available_space.width.is_definite())
|
|
||||||
width_of_containing_block_as_length_for_resolve = CSS::Length::make_px(0);
|
|
||||||
|
|
||||||
auto margin_left = computed_values.margin().left().resolved(box, width_of_containing_block_as_length_for_resolve);
|
auto margin_left = computed_values.margin().left().resolved(box, width_of_containing_block_as_length_for_resolve);
|
||||||
auto margin_right = computed_values.margin().right().resolved(box, width_of_containing_block_as_length_for_resolve);
|
auto margin_right = computed_values.margin().right().resolved(box, width_of_containing_block_as_length_for_resolve);
|
||||||
|
@ -309,18 +306,24 @@ void BlockFormattingContext::compute_width_for_floating_box(Box const& box, Avai
|
||||||
auto compute_width = [&](auto width) {
|
auto compute_width = [&](auto width) {
|
||||||
// If 'width' is computed as 'auto', the used value is the "shrink-to-fit" width.
|
// If 'width' is computed as 'auto', the used value is the "shrink-to-fit" width.
|
||||||
if (width.is_auto()) {
|
if (width.is_auto()) {
|
||||||
|
|
||||||
// Find the available width: in this case, this is the width of the containing
|
|
||||||
// block minus the used values of 'margin-left', 'border-left-width', 'padding-left',
|
|
||||||
// 'padding-right', 'border-right-width', 'margin-right', and the widths of any relevant scroll bars.
|
|
||||||
auto available_width = width_of_containing_block
|
|
||||||
- margin_left.to_px(box) - computed_values.border_left().width - padding_left
|
|
||||||
- padding_right - computed_values.border_right().width - margin_right.to_px(box);
|
|
||||||
|
|
||||||
auto result = calculate_shrink_to_fit_widths(box);
|
auto result = calculate_shrink_to_fit_widths(box);
|
||||||
|
|
||||||
// Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).
|
if (available_space.width.is_definite()) {
|
||||||
width = CSS::Length::make_px(min(max(result.preferred_minimum_width, available_width), result.preferred_width));
|
// Find the available width: in this case, this is the width of the containing
|
||||||
|
// block minus the used values of 'margin-left', 'border-left-width', 'padding-left',
|
||||||
|
// 'padding-right', 'border-right-width', 'margin-right', and the widths of any relevant scroll bars.
|
||||||
|
auto available_width = available_space.width.to_px_or_zero()
|
||||||
|
- margin_left.to_px(box) - computed_values.border_left().width - padding_left
|
||||||
|
- padding_right - computed_values.border_right().width - margin_right.to_px(box);
|
||||||
|
// Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).
|
||||||
|
width = CSS::Length::make_px(min(max(result.preferred_minimum_width, available_width), result.preferred_width));
|
||||||
|
} else if (available_space.width.is_indefinite() || available_space.width.is_max_content()) {
|
||||||
|
// Fold the formula for shrink-to-fit width for indefinite and max-content available width.
|
||||||
|
width = CSS::Length::make_px(result.preferred_width);
|
||||||
|
} else {
|
||||||
|
// Fold the formula for shrink-to-fit width for min-content available width.
|
||||||
|
width = CSS::Length::make_px(min(result.preferred_minimum_width, result.preferred_width));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
|
@ -898,7 +901,6 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer
|
||||||
VERIFY(box.is_floating());
|
VERIFY(box.is_floating());
|
||||||
|
|
||||||
auto& box_state = m_state.get_mutable(box);
|
auto& box_state = m_state.get_mutable(box);
|
||||||
CSSPixels width_of_containing_block = available_space.width.to_px_or_zero();
|
|
||||||
|
|
||||||
resolve_vertical_box_model_metrics(box);
|
resolve_vertical_box_model_metrics(box);
|
||||||
|
|
||||||
|
@ -957,7 +959,11 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer
|
||||||
bool fits_next_to_preceding_float = false;
|
bool fits_next_to_preceding_float = false;
|
||||||
if (side == FloatSide::Left) {
|
if (side == FloatSide::Left) {
|
||||||
tentative_offset_from_edge = preceding_float.offset_from_edge + preceding_float_state.content_width() + preceding_float_state.margin_box_right() + box_state.margin_box_left();
|
tentative_offset_from_edge = preceding_float.offset_from_edge + preceding_float_state.content_width() + preceding_float_state.margin_box_right() + box_state.margin_box_left();
|
||||||
fits_next_to_preceding_float = (tentative_offset_from_edge + box_state.content_width() + box_state.margin_box_right()) <= width_of_containing_block;
|
if (available_space.width.is_definite()) {
|
||||||
|
fits_next_to_preceding_float = (tentative_offset_from_edge + box_state.content_width() + box_state.margin_box_right()) <= available_space.width.to_px_or_zero();
|
||||||
|
} else if (available_space.width.is_max_content() || available_space.width.is_indefinite()) {
|
||||||
|
fits_next_to_preceding_float = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tentative_offset_from_edge = preceding_float.offset_from_edge + preceding_float_state.margin_box_left() + box_state.margin_box_right() + box_state.content_width();
|
tentative_offset_from_edge = preceding_float.offset_from_edge + preceding_float_state.margin_box_left() + box_state.margin_box_right() + box_state.content_width();
|
||||||
fits_next_to_preceding_float = tentative_offset_from_edge >= 0;
|
fits_next_to_preceding_float = tentative_offset_from_edge >= 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue