Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 51 additions & 19 deletions Libraries/LibWeb/Rust/src/layout/block_formatting_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ pub(crate) struct BlockFormattingContext<'pass> {
lowest_right_margin_edge: Cell<CssPixels>,
lowest_floating_descendant_bottom_margin_edge: Cell<Option<CssPixels>>,
derived_baselines_of_root_box: Cell<DerivedBaselines>,
trailing_collapsed_margin: Cell<Option<(Node, CssPixels)>>,
}

impl<'pass> BlockFormattingContext<'pass> {
Expand All @@ -213,6 +214,7 @@ impl<'pass> BlockFormattingContext<'pass> {
lowest_right_margin_edge: Cell::new(CssPixels::default()),
lowest_floating_descendant_bottom_margin_edge: Cell::new(None),
derived_baselines_of_root_box: Cell::new(DerivedBaselines::default()),
trailing_collapsed_margin: Cell::new(None),
}
}

Expand Down Expand Up @@ -1518,6 +1520,7 @@ impl<'pass> BlockFormattingContext<'pass> {
block_container: Node,
bottom_of_lowest_margin_box: &mut CssPixels,
input: LayoutInput,
containing_line_box_fragment: Option<LineBoxFragmentCoordinate>,
) {
let available_space = input.available_space;
let facts = self.facts(node);
Expand Down Expand Up @@ -1864,7 +1867,22 @@ impl<'pass> BlockFormattingContext<'pass> {
);
}

let block_container_used = self.used(block_container);
self.compute_inset(
run,
node,
LogicalSize {
inline_size: block_container_used.content_inline_size.get(),
block_size: block_container_used.content_block_size.get(),
},
);

if let Some(position) = pending_position {
if let Some(coordinate) = containing_line_box_fragment {
let used = self.used_mut(node);
used.has_containing_line_box_fragment.set(true);
used.containing_line_box_fragment.set(coordinate);
}
self.place_child(node, position);
}

Expand All @@ -1887,15 +1905,6 @@ impl<'pass> BlockFormattingContext<'pass> {
.add_margin(self.used(node).margin_bottom.get());
self.margin_state.borrow_mut().update_open_top_margin_group();

let block_container_used = self.used(block_container);
self.compute_inset(
run,
node,
LogicalSize {
inline_size: block_container_used.content_inline_size.get(),
block_size: block_container_used.content_block_size.get(),
},
);
let used = self.used(node);
*bottom_of_lowest_margin_box = (*bottom_of_lowest_margin_box)
.max(used.content_offset.get().y + used.content_block_size.get() + used.margin_box_bottom(false));
Expand Down Expand Up @@ -1926,6 +1935,7 @@ impl<'pass> BlockFormattingContext<'pass> {
block_container,
&mut bottom_of_lowest_margin_box,
child_input,
None,
);
}
self.block_offset_of_current_block_container.set(saved);
Expand Down Expand Up @@ -1962,7 +1972,7 @@ impl<'pass> BlockFormattingContext<'pass> {
} else {
caption_input
};
self.layout_block_level_box(run, child, wrapper, &mut bottom_of_lowest_margin_box, child_input);
self.layout_block_level_box(run, child, wrapper, &mut bottom_of_lowest_margin_box, child_input, None);
}
self.block_offset_of_current_block_container.set(saved);
self.finish_block_level_children_layout(wrapper, input, available_space_for_children, bottom_of_lowest_margin_box);
Expand Down Expand Up @@ -2026,7 +2036,7 @@ impl<'pass> BlockFormattingContext<'pass> {
.block_offset_of_current_block_container
.replace(Some(CssPixels::default()));
let mut dummy_bottom = CssPixels::default();
self.layout_block_level_box(run, legend, fieldset, &mut dummy_bottom, child_input);
self.layout_block_level_box(run, legend, fieldset, &mut dummy_bottom, child_input, None);
self.block_offset_of_current_block_container.set(saved);
}

Expand Down Expand Up @@ -2058,7 +2068,7 @@ impl<'pass> BlockFormattingContext<'pass> {
let saved = self.block_offset_of_current_block_container.replace(Some(extra_top));
for child in self.children(fieldset) {
if child != legend {
self.layout_block_level_box(run, child, fieldset, &mut bottom_of_lowest_margin_box, child_input);
self.layout_block_level_box(run, child, fieldset, &mut bottom_of_lowest_margin_box, child_input, None);
}
}
self.block_offset_of_current_block_container.set(saved);
Expand Down Expand Up @@ -2196,7 +2206,10 @@ impl<'pass> BlockFormattingContext<'pass> {
return;
}

// Assign collapsed margin left after children layout of formatting context to the last child box
// The run's trailing collapsed margin hangs below the last real in-flow child, but it
// aggregates margins of trailing collapse-through siblings laid out after that child was
// placed. It is run output, not a property of that child: the child keeps its own placed
// margin_bottom, and only the root's automatic block size consumes the aggregate.
let collapsed_margin = self.margin_state.borrow().current_collapsed_margin();
if collapsed_margin != CssPixels::default() {
let flow_children_bottom_up = if root_facts.is_table_wrapper() {
Expand All @@ -2212,12 +2225,9 @@ impl<'pass> BlockFormattingContext<'pass> {
if self.margins_collapse_through(child) {
continue;
}
self.used_mut(child).margin_bottom.set(collapsed_margin);
self.trailing_collapsed_margin.set(Some((child, collapsed_margin)));
break;
}
// The margin reassignment above changed a child's margin box, which the root's baselines may
// have been derived from (a scroll container child exports its bottom margin edge), so re-derive them.
self.compute_and_store_baselines(self.root);
}

if root_facts.is_list_item_box() {
Expand Down Expand Up @@ -2268,12 +2278,23 @@ impl<'pass> BlockFormattingContext<'pass> {
input: LayoutInput,
line_builder: &mut LineBuilder<'_, '_, '_>,
) {
let line_index = line_builder.line_index_for_block_level_box();
let current_block_offset = line_builder.current_block_offset();
let saved = self
.block_offset_of_current_block_container
.replace(Some(current_block_offset));
let mut dummy_bottom = CssPixels::default();
self.layout_block_level_box(run, node, containing_block, &mut dummy_bottom, input);
self.layout_block_level_box(
run,
node,
containing_block,
&mut dummy_bottom,
input,
Some(LineBoxFragmentCoordinate {
line_box_index: line_index,
fragment_index: 0,
}),
);
// SAFETY: The builder remains live and no reference escaped.
let block_bottom = self
.block_offset_of_current_block_container
Expand All @@ -2282,6 +2303,7 @@ impl<'pass> BlockFormattingContext<'pass> {
self.block_offset_of_current_block_container.set(saved);
line_builder.append_block_level_box(
node,
line_index,
block_bottom,
self.margin_state.borrow().current_collapsed_margin(),
);
Expand Down Expand Up @@ -2822,6 +2844,7 @@ impl<'pass> BlockFormattingContext<'pass> {
self.callbacks,
self.root,
self.lowest_floating_descendant_bottom_margin_edge.get(),
self.trailing_collapsed_margin.get(),
)
}
}
Expand Down Expand Up @@ -2870,6 +2893,7 @@ pub(crate) fn automatic_block_size_for_bfc_root(
callbacks: FfiLayoutFcCallbacks,
root: Node,
lowest_floating_descendant_bottom_margin_edge: Option<CssPixels>,
trailing_collapsed_margin: Option<(Node, CssPixels)>,
) -> CssPixels {
let facts = state.node_facts(&callbacks, root);
// https://drafts.csswg.org/css-contain-2/#containment-size
Expand Down Expand Up @@ -2918,9 +2942,17 @@ pub(crate) fn automatic_block_size_for_bfc_root(
let child_used = state.try_used_values(&callbacks, child);
// Children that have not been laid out yet contribute nothing to the automatic block size.
if let Some(child_used) = child_used {
// Margins cannot collapse out of a BFC root: below the last real in-flow
// child, the run's trailing collapsed margin (which folds in any trailing
// collapse-through siblings) replaces that child's own bottom margin.
let margin_bottom = match trailing_collapsed_margin {
Some((last_real_child, aggregate)) if last_real_child == child => aggregate,
_ => child_used.margin_bottom.get(),
};
let child_bottom = child_used.content_offset.get().y
+ child_used.content_block_size.get()
+ child_used.margin_box_bottom(false);
+ child_used.border_box_bottom(false)
+ margin_bottom;
bottom = Some(bottom.map_or(child_bottom, |value: CssPixels| value.max(child_bottom)));
}
}
Expand Down
1 change: 1 addition & 0 deletions Libraries/LibWeb/Rust/src/layout/formatting_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ pub(crate) fn place_child(
assert!(!used.has_content_offset.get());
used.has_content_offset.set(true);
used.content_offset.set(offset);
used.seal_committed_box_metrics();
}

pub(crate) fn register_contained_abspos_child(
Expand Down
4 changes: 3 additions & 1 deletion Libraries/LibWeb/Rust/src/layout/grid_formatting_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3448,7 +3448,8 @@ impl<'pass> GridFormattingContext<'pass> {
x: area.offset.inline_offset + self.item_margin_box_start(item, Axis::Column),
y: area.offset.block_offset + self.item_margin_box_start(item, Axis::Row),
};
crate::layout::place_child(self.state, &self.callbacks, item.box_, offset);
// Resolve relative-position insets before placement seals the
// item's committed metrics.
crate::layout::compute_inset_native(
self.state,
self.callbacks,
Expand All @@ -3458,6 +3459,7 @@ impl<'pass> GridFormattingContext<'pass> {
self.grid_container,
run.treat_block_axis_percentage_insets_as_auto_beyond_root,
);
crate::layout::place_child(self.state, &self.callbacks, item.box_, offset);
}
self.derived_baselines_of_root_box =
crate::layout::derive_baselines(self.state, &self.callbacks, self.grid_container, false);
Expand Down
6 changes: 5 additions & 1 deletion Libraries/LibWeb/Rust/src/layout/layout_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,6 @@ impl LayoutState {
used.set_content_block_size(geometry.content_block_size);
used.has_definite_inline_size.set(true);
used.has_definite_block_size.set(true);
used.has_content_offset.set(true);
used.content_offset.set(geometry.content_offset);
used.margin_left.set(geometry.margin_left);
used.margin_right.set(geometry.margin_right);
Expand All @@ -1101,6 +1100,11 @@ impl LayoutState {
self.used_values_rare_data_mut(slot_index).svg_viewport_size = Some(geometry.svg_viewport_size);
}

// Materialization is this box's placement: the previous paintable's
// committed geometry is final from the moment it is adopted.
used.has_content_offset.set(true);
used.seal_committed_box_metrics();

let used = self.used_values.allocate(slot_index, used);
self.register_anchor_candidate_if_carries_anchor_names(callbacks, node);
Some(used)
Expand Down
23 changes: 15 additions & 8 deletions Libraries/LibWeb/Rust/src/layout/line_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,19 @@ impl<'builder, 'context, 'pass> LineBuilder<'builder, 'context, 'pass> {
self.begin_new_line(true, true, ForcedBreak::No);
}

pub(crate) fn append_block_level_box(&mut self, node: Node, block_end: CssPixels, block_end_margin: CssPixels) {
pub(crate) fn line_index_for_block_level_box(&mut self) -> usize {
let line_index = self.ensure_last_line_index();
assert!(self.line(line_index).fragments.is_empty());
line_index
}

pub(crate) fn append_block_level_box(
&mut self,
node: Node,
line_index: usize,
block_end: CssPixels,
block_end_margin: CssPixels,
) {
let used = self.context().used(node);
assert!(used.has_content_offset.get());
let (inline_offset, block_offset) = to_logical(
Expand All @@ -359,7 +371,8 @@ impl<'builder, 'context, 'pass> LineBuilder<'builder, 'context, 'pass> {
used.margin_box_block_size(false),
)
.0;
let line_index = self.ensure_last_line_index();
let ensured_line_index = self.ensure_last_line_index();
assert_eq!(line_index, ensured_line_index);
assert!(self.line(line_index).fragments.is_empty());
let fragment = LineBoxFragmentData::new(
node,
Expand Down Expand Up @@ -391,12 +404,6 @@ impl<'builder, 'context, 'pass> LineBuilder<'builder, 'context, 'pass> {
marker.block_offset += current_block_offset;
}
}
let used = self.context().used_mut(node);
used.has_containing_line_box_fragment.set(true);
used.containing_line_box_fragment.set(LineBoxFragmentCoordinate {
line_box_index: line_index,
fragment_index: 0,
});
self.pending_margin_follows_block_level_box = true;
self.current_block_offset = block_end;
self.max_block_size_on_current_line = CssPixels::default();
Expand Down
Loading
Loading