From 6ef03d49b568a49376b406ab9ccc9f554ba0e4e0 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 5 Jun 2019 17:54:30 +0200 Subject: [PATCH 01/18] Make in_flow_non_replaced return a BoxFragment --- victor/src/layout/flow/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index 844ca41..a58f1fe 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -164,24 +164,24 @@ impl BlockLevelBox { ) -> Fragment { match self { BlockLevelBox::SameFormattingContextBlock { style, contents } => { - layout_in_flow_non_replaced_block_level( + Fragment::Box(layout_in_flow_non_replaced_block_level( containing_block, absolutely_positioned_fragments, style, |containing_block| contents.layout(containing_block, float_context, tree_rank), - ) + )) } BlockLevelBox::Independent { style, contents } => match contents.as_replaced() { Ok(replaced) => { // FIXME match *replaced {} } - Err(contents) => layout_in_flow_non_replaced_block_level( + Err(contents) => Fragment::Box(layout_in_flow_non_replaced_block_level( containing_block, absolutely_positioned_fragments, style, |containing_block| contents.layout(containing_block, tree_rank), - ), + )), }, BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => { absolutely_positioned_fragments.push(box_.layout(Vec2::zero(), tree_rank)); @@ -204,7 +204,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( layout_contents: impl FnOnce( &ContainingBlock, ) -> (Vec, Vec>, Length), -) -> Fragment { +) -> BoxFragment { let cbis = containing_block.inline_size; let padding = style.padding().percentages_relative_to(cbis); let border = style.border_width().percentages_relative_to(cbis); @@ -276,12 +276,12 @@ fn layout_in_flow_non_replaced_block_level<'a>( } else { absolutely_positioned_fragments.extend(nested_abspos); }; - Fragment::Box(BoxFragment { + BoxFragment { style: style.clone(), children, content_rect, padding, border, margin, - }) + } } From 365292ac15582ae707077172c30fb7c0f5f1d8be Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 6 Jun 2019 11:10:38 +0200 Subject: [PATCH 02/18] Implement margin collapsing between siblings --- tests/reftests/blocks.html | 6 +-- victor/src/layout/flow/inline.rs | 1 + victor/src/layout/flow/mod.rs | 69 ++++++++++++++++++++++++------- victor/src/layout/fragments.rs | 2 + victor/src/layout/positioned.rs | 1 + victor/src/style/values/length.rs | 12 ++++++ 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/tests/reftests/blocks.html b/tests/reftests/blocks.html index c71d5a4..4ca1d72 100644 --- a/tests/reftests/blocks.html +++ b/tests/reftests/blocks.html @@ -1,9 +1,9 @@ -
+

\ No newline at end of file +p { background-color: blue; width: 200px; height: 100px; margin: 10px 5px 5px } + diff --git a/victor/src/layout/flow/inline.rs b/victor/src/layout/flow/inline.rs index 3072fd9..fbc56bd 100644 --- a/victor/src/layout/flow/inline.rs +++ b/victor/src/layout/flow/inline.rs @@ -242,6 +242,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> { padding: self.padding.clone(), border: self.border.clone(), margin: self.margin.clone(), + collapsible_margins: false, }; let last_fragment = self.last_box_tree_fragment && !at_line_break; if last_fragment { diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index a58f1fe..08a15e3 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -39,6 +39,9 @@ pub(super) enum BlockLevelBox { }, } +#[derive(Clone, Copy)] +struct CollapsibleMargins(bool); + impl BlockFormattingContext { pub(super) fn layout( &self, @@ -81,6 +84,7 @@ fn layout_block_level_children<'a>( ) -> (Vec, Vec>, Length) { let mut absolutely_positioned_fragments = vec![]; let mut current_block_direction_position = Length::zero(); + let mut ongoing_collapsed_margin = Length::zero(); let mut child_fragments: Vec; if let Some(float_context) = float_context { // Because floats are involved, we do layout for this block formatting context @@ -96,7 +100,11 @@ fn layout_block_level_children<'a>( tree_rank, &mut absolutely_positioned_fragments, ); - place_block_level_fragment(&mut fragment, &mut current_block_direction_position); + place_block_level_fragment( + &mut fragment, + &mut current_block_direction_position, + &mut ongoing_collapsed_margin, + ); fragment }) .collect() @@ -120,10 +128,14 @@ fn layout_block_level_children<'a>( ) .collect(); for fragment in &mut child_fragments { - place_block_level_fragment(fragment, &mut current_block_direction_position) + place_block_level_fragment( + fragment, + &mut current_block_direction_position, + &mut ongoing_collapsed_margin, + ) } } - let content_block_size = current_block_direction_position; + let content_block_size = current_block_direction_position + ongoing_collapsed_margin; let block_size = containing_block.block_size.auto_is(|| content_block_size); adjust_static_positions( @@ -135,23 +147,48 @@ fn layout_block_level_children<'a>( (child_fragments, absolutely_positioned_fragments, block_size) } +fn collapse_adjoining_margins(first: Length, second: Length) -> Length { + match (first >= Length::zero(), second >= Length::zero()) { + (true, true) => first.max(second), + (false, false) => first.min(second), + _ => first + second, + } +} + fn place_block_level_fragment( fragment: &mut Fragment, current_block_direction_position: &mut Length, + ongoing_collapsed_margin: &mut Length, ) { - let (bpm, rect) = match fragment { - Fragment::Box(fragment) => ( - fragment.padding.block_sum() + match fragment { + Fragment::Box(fragment) => { + if fragment.collapsible_margins { + fragment.content_rect.start_corner.block -= fragment.margin.block_start; + *current_block_direction_position += collapse_adjoining_margins( + fragment.margin.block_start, + *ongoing_collapsed_margin, + ); + } + fragment.content_rect.start_corner.block += *current_block_direction_position; + *current_block_direction_position += fragment.padding.block_sum() + fragment.border.block_sum() - + fragment.margin.block_sum(), - &mut fragment.content_rect, - ), - Fragment::Anonymous(fragment) => (Length::zero(), &mut fragment.rect), + + fragment.content_rect.size.block; + if fragment.collapsible_margins { + *ongoing_collapsed_margin = fragment.margin.block_end; + } else { + *current_block_direction_position += fragment.margin.block_end; + *ongoing_collapsed_margin = Length::zero(); + } + } + Fragment::Anonymous(fragment) => { + // FIXME(nox): Margin collapsing for hypothetical boxes of + // abspos elements is probably wrong. + assert!(fragment.children.is_empty()); + assert_eq!(fragment.rect.size.block, Length::zero()); + fragment.rect.start_corner.block += *current_block_direction_position; + } _ => unreachable!(), - }; - // FIXME: margin collapsing - rect.start_corner.block += *current_block_direction_position; - *current_block_direction_position += bpm + rect.size.block; + } } impl BlockLevelBox { @@ -168,6 +205,7 @@ impl BlockLevelBox { containing_block, absolutely_positioned_fragments, style, + CollapsibleMargins(true), |containing_block| contents.layout(containing_block, float_context, tree_rank), )) } @@ -180,6 +218,7 @@ impl BlockLevelBox { containing_block, absolutely_positioned_fragments, style, + CollapsibleMargins(false), |containing_block| contents.layout(containing_block, tree_rank), )), }, @@ -201,6 +240,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( containing_block: &ContainingBlock, absolutely_positioned_fragments: &mut Vec>, style: &Arc, + collapsible_margins: CollapsibleMargins, layout_contents: impl FnOnce( &ContainingBlock, ) -> (Vec, Vec>, Length), @@ -283,5 +323,6 @@ fn layout_in_flow_non_replaced_block_level<'a>( padding, border, margin, + collapsible_margins: collapsible_margins.0, } } diff --git a/victor/src/layout/fragments.rs b/victor/src/layout/fragments.rs index 29d831e..711ccc5 100644 --- a/victor/src/layout/fragments.rs +++ b/victor/src/layout/fragments.rs @@ -19,6 +19,8 @@ pub(crate) struct BoxFragment { pub padding: Sides, pub border: Sides, pub margin: Sides, + + pub collapsible_margins: bool, } /// Can contain child fragments with relative coordinates, but does not contribute to painting itself. diff --git a/victor/src/layout/positioned.rs b/victor/src/layout/positioned.rs index f1b8388..3c238ba 100644 --- a/victor/src/layout/positioned.rs +++ b/victor/src/layout/positioned.rs @@ -295,6 +295,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { padding, border, margin, + collapsible_margins: false, }) } } diff --git a/victor/src/style/values/length.rs b/victor/src/style/values/length.rs index 37881bd..adbebfd 100644 --- a/victor/src/style/values/length.rs +++ b/victor/src/style/values/length.rs @@ -110,6 +110,12 @@ impl Length { } } + pub fn min(self, other: Self) -> Self { + Length { + px: self.px.min(other.px), + } + } + pub fn max_assign(&mut self, other: Self) { *self = self.max(other) } @@ -146,6 +152,12 @@ impl ops::AddAssign for Length { } } +impl ops::SubAssign for Length { + fn sub_assign(&mut self, other: Self) { + self.px -= other.px + } +} + impl ops::Mul for Length { type Output = Self; From 13220bfd3ce3220bc676630fc3aed1c752499550 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 7 Jun 2019 20:26:44 +0200 Subject: [PATCH 03/18] Introduce CollapsingContext --- victor/src/layout/flow/inline.rs | 2 +- victor/src/layout/flow/mod.rs | 37 +++++++++++------------- victor/src/layout/fragments.rs | 49 +++++++++++++++++++++++++++++++- victor/src/layout/positioned.rs | 2 +- 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/victor/src/layout/flow/inline.rs b/victor/src/layout/flow/inline.rs index fbc56bd..4643035 100644 --- a/victor/src/layout/flow/inline.rs +++ b/victor/src/layout/flow/inline.rs @@ -242,7 +242,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> { padding: self.padding.clone(), border: self.border.clone(), margin: self.margin.clone(), - collapsible_margins: false, + collapsing_context: None, }; let last_fragment = self.last_box_tree_fragment && !at_line_break; if last_fragment { diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index 08a15e3..fb57c9a 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -84,7 +84,7 @@ fn layout_block_level_children<'a>( ) -> (Vec, Vec>, Length) { let mut absolutely_positioned_fragments = vec![]; let mut current_block_direction_position = Length::zero(); - let mut ongoing_collapsed_margin = Length::zero(); + let mut ongoing_collapsed_margin = CollapsedMargin::zero(); let mut child_fragments: Vec; if let Some(float_context) = float_context { // Because floats are involved, we do layout for this block formatting context @@ -135,7 +135,7 @@ fn layout_block_level_children<'a>( ) } } - let content_block_size = current_block_direction_position + ongoing_collapsed_margin; + let content_block_size = current_block_direction_position + ongoing_collapsed_margin.solve(); let block_size = containing_block.block_size.auto_is(|| content_block_size); adjust_static_positions( @@ -147,37 +147,29 @@ fn layout_block_level_children<'a>( (child_fragments, absolutely_positioned_fragments, block_size) } -fn collapse_adjoining_margins(first: Length, second: Length) -> Length { - match (first >= Length::zero(), second >= Length::zero()) { - (true, true) => first.max(second), - (false, false) => first.min(second), - _ => first + second, - } -} - fn place_block_level_fragment( fragment: &mut Fragment, current_block_direction_position: &mut Length, - ongoing_collapsed_margin: &mut Length, + ongoing_collapsed_margin: &mut CollapsedMargin, ) { match fragment { Fragment::Box(fragment) => { - if fragment.collapsible_margins { + if let Some(collapsing_context) = &fragment.collapsing_context { fragment.content_rect.start_corner.block -= fragment.margin.block_start; - *current_block_direction_position += collapse_adjoining_margins( - fragment.margin.block_start, - *ongoing_collapsed_margin, - ); + *current_block_direction_position += collapsing_context + .start + .adjoin(ongoing_collapsed_margin) + .solve(); } fragment.content_rect.start_corner.block += *current_block_direction_position; *current_block_direction_position += fragment.padding.block_sum() + fragment.border.block_sum() + fragment.content_rect.size.block; - if fragment.collapsible_margins { - *ongoing_collapsed_margin = fragment.margin.block_end; + if let Some(collapsing_context) = &fragment.collapsing_context { + *ongoing_collapsed_margin = collapsing_context.end; } else { *current_block_direction_position += fragment.margin.block_end; - *ongoing_collapsed_margin = Length::zero(); + *ongoing_collapsed_margin = CollapsedMargin::zero(); } } Fragment::Anonymous(fragment) => { @@ -294,6 +286,11 @@ fn layout_in_flow_non_replaced_block_level<'a>( containing_block.mode, containing_block_for_children.mode, "Mixed writing modes are not supported yet" ); + let collapsing_context = if collapsible_margins.0 { + Some(CollapsingContext::from_margin(&margin)) + } else { + None + }; let (mut children, nested_abspos, content_block_size) = layout_contents(&containing_block_for_children); let relative_adjustement = relative_adjustement(style, inline_size, block_size); @@ -323,6 +320,6 @@ fn layout_in_flow_non_replaced_block_level<'a>( padding, border, margin, - collapsible_margins: collapsible_margins.0, + collapsing_context, } } diff --git a/victor/src/layout/fragments.rs b/victor/src/layout/fragments.rs index 711ccc5..180ab0c 100644 --- a/victor/src/layout/fragments.rs +++ b/victor/src/layout/fragments.rs @@ -20,7 +20,18 @@ pub(crate) struct BoxFragment { pub border: Sides, pub margin: Sides, - pub collapsible_margins: bool, + pub collapsing_context: Option, +} + +pub(crate) struct CollapsingContext { + pub start: CollapsedMargin, + pub end: CollapsedMargin, +} + +#[derive(Clone, Copy)] +pub(crate) struct CollapsedMargin { + max_positive: Length, + min_negative: Length, } /// Can contain child fragments with relative coordinates, but does not contribute to painting itself. @@ -53,3 +64,39 @@ impl BoxFragment { .inflate(&self.border) } } + +impl CollapsingContext { + pub fn from_margin(margin: &Sides) -> Self { + Self { + start: CollapsedMargin::new(margin.block_start), + end: CollapsedMargin::new(margin.block_end), + } + } +} + +impl CollapsedMargin { + pub fn zero() -> Self { + Self { + max_positive: Length::zero(), + min_negative: Length::zero(), + } + } + + pub fn new(margin: Length) -> Self { + Self { + max_positive: margin.max(Length::zero()), + min_negative: margin.min(Length::zero()), + } + } + + pub fn adjoin(&self, other: &Self) -> Self { + Self { + max_positive: self.max_positive.max(other.max_positive), + min_negative: self.min_negative.min(other.min_negative), + } + } + + pub fn solve(&self) -> Length { + self.max_positive + self.min_negative + } +} diff --git a/victor/src/layout/positioned.rs b/victor/src/layout/positioned.rs index 3c238ba..336a6a5 100644 --- a/victor/src/layout/positioned.rs +++ b/victor/src/layout/positioned.rs @@ -295,7 +295,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { padding, border, margin, - collapsible_margins: false, + collapsing_context: None, }) } } From 3f259e59fa69c34a4bb8038cf47ee9ab84b4b805 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 9 Jun 2019 15:18:12 +0200 Subject: [PATCH 04/18] Change the start corner returned from layout_in_flow_non_replaced_block_level It now doesn't account for margins of fragments whose margins can collapse with other fragments. --- victor/src/layout/flow/mod.rs | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index fb57c9a..a2154a4 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -154,23 +154,21 @@ fn place_block_level_fragment( ) { match fragment { Fragment::Box(fragment) => { + let mut fragment_block_size = fragment.padding.block_sum() + + fragment.border.block_sum() + + fragment.content_rect.size.block; if let Some(collapsing_context) = &fragment.collapsing_context { - fragment.content_rect.start_corner.block -= fragment.margin.block_start; *current_block_direction_position += collapsing_context .start .adjoin(ongoing_collapsed_margin) .solve(); - } - fragment.content_rect.start_corner.block += *current_block_direction_position; - *current_block_direction_position += fragment.padding.block_sum() - + fragment.border.block_sum() - + fragment.content_rect.size.block; - if let Some(collapsing_context) = &fragment.collapsing_context { *ongoing_collapsed_margin = collapsing_context.end; } else { - *current_block_direction_position += fragment.margin.block_end; + fragment_block_size += fragment.margin.block_sum(); *ongoing_collapsed_margin = CollapsedMargin::zero(); } + fragment.content_rect.start_corner.block += *current_block_direction_position; + *current_block_direction_position += fragment_block_size; } Fragment::Anonymous(fragment) => { // FIXME(nox): Margin collapsing for hypothetical boxes of @@ -269,8 +267,15 @@ fn layout_in_flow_non_replaced_block_level<'a>( } } let margin = computed_margin.auto_is(Length::zero); - let pbm = &pb + &margin; - let inline_size = inline_size.auto_is(|| cbis - pbm.inline_sum()); + let (collapsing_context, initial_margin_block_start) = if collapsible_margins.0 { + ( + Some(CollapsingContext::from_margin(&margin)), + Length::zero(), + ) + } else { + (None, margin.block_start) + }; + let inline_size = inline_size.auto_is(|| cbis - pb.inline_sum() - margin.inline_sum()); let block_size = match box_size.block { LengthOrPercentageOrAuto::Length(l) => LengthOrAuto::Length(l), LengthOrPercentageOrAuto::Percentage(p) => containing_block.block_size.map(|cbbs| cbbs * p), @@ -286,17 +291,15 @@ fn layout_in_flow_non_replaced_block_level<'a>( containing_block.mode, containing_block_for_children.mode, "Mixed writing modes are not supported yet" ); - let collapsing_context = if collapsible_margins.0 { - Some(CollapsingContext::from_margin(&margin)) - } else { - None - }; let (mut children, nested_abspos, content_block_size) = layout_contents(&containing_block_for_children); let relative_adjustement = relative_adjustement(style, inline_size, block_size); let block_size = block_size.auto_is(|| content_block_size); let content_rect = Rect { - start_corner: &pbm.start_corner() + &relative_adjustement, + start_corner: Vec2 { + block: pb.block_start + relative_adjustement.block + initial_margin_block_start, + inline: pb.inline_start + relative_adjustement.inline + margin.inline_start, + }, size: Vec2 { block: block_size, inline: inline_size, From 77665f8576a4384345dd7f9a260b3f7f3df44cd1 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 10 Jun 2019 10:23:13 +0200 Subject: [PATCH 05/18] Introduce FlowChildren --- victor/src/layout/flow/inline.rs | 12 ++++----- victor/src/layout/flow/mod.rs | 45 ++++++++++++++++++-------------- victor/src/layout/flow/root.rs | 10 +++---- victor/src/layout/mod.rs | 12 ++------- victor/src/layout/positioned.rs | 14 +++++----- 5 files changed, 47 insertions(+), 46 deletions(-) diff --git a/victor/src/layout/flow/inline.rs b/victor/src/layout/flow/inline.rs index 4643035..9ab02c7 100644 --- a/victor/src/layout/flow/inline.rs +++ b/victor/src/layout/flow/inline.rs @@ -71,7 +71,7 @@ impl InlineFormattingContext { &self, containing_block: &ContainingBlock, tree_rank: usize, - ) -> (Vec, Vec, Length) { + ) -> FlowChildren { let mut ifc = InlineFormattingContextState { containing_block, absolutely_positioned_fragments: Vec::new(), @@ -137,11 +137,11 @@ impl InlineFormattingContext { } else { ifc.line_boxes .finish_line(&mut ifc.current_nesting_level, containing_block); - return ( - ifc.line_boxes.boxes, - ifc.absolutely_positioned_fragments, - ifc.line_boxes.next_line_block_position, - ); + return FlowChildren { + fragments: ifc.line_boxes.boxes, + absolutely_positioned_fragments: ifc.absolutely_positioned_fragments, + block_size: ifc.line_boxes.next_line_block_position, + }; } } } diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index a2154a4..e96f5b8 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -39,6 +39,12 @@ pub(super) enum BlockLevelBox { }, } +pub(super) struct FlowChildren<'a> { + pub fragments: Vec, + pub absolutely_positioned_fragments: Vec>, + pub block_size: Length, +} + #[derive(Clone, Copy)] struct CollapsibleMargins(bool); @@ -47,7 +53,7 @@ impl BlockFormattingContext { &self, containing_block: &ContainingBlock, tree_rank: usize, - ) -> (Vec, Vec, Length) { + ) -> FlowChildren { let mut float_context; let float_context = if self.contains_floats { float_context = FloatContext::new(); @@ -66,7 +72,7 @@ impl BlockContainer { containing_block: &ContainingBlock, float_context: Option<&mut FloatContext>, tree_rank: usize, - ) -> (Vec, Vec, Length) { + ) -> FlowChildren { match self { BlockContainer::BlockLevelBoxes(child_boxes) => { layout_block_level_children(containing_block, float_context, tree_rank, child_boxes) @@ -81,16 +87,16 @@ fn layout_block_level_children<'a>( float_context: Option<&mut FloatContext>, tree_rank: usize, child_boxes: &'a [BlockLevelBox], -) -> (Vec, Vec>, Length) { +) -> FlowChildren<'a> { let mut absolutely_positioned_fragments = vec![]; let mut current_block_direction_position = Length::zero(); let mut ongoing_collapsed_margin = CollapsedMargin::zero(); - let mut child_fragments: Vec; + let mut fragments: Vec<_>; if let Some(float_context) = float_context { // Because floats are involved, we do layout for this block formatting context // in tree order without parallelism. This enables mutable access // to a `FloatContext` that tracks every float encountered so far (again in tree order). - child_fragments = child_boxes + fragments = child_boxes .iter() .enumerate() .map(|(tree_rank, box_)| { @@ -109,7 +115,7 @@ fn layout_block_level_children<'a>( }) .collect() } else { - child_fragments = child_boxes + fragments = child_boxes .par_iter() .enumerate() .mapfold_reduce_into( @@ -127,7 +133,7 @@ fn layout_block_level_children<'a>( }, ) .collect(); - for fragment in &mut child_fragments { + for fragment in &mut fragments { place_block_level_fragment( fragment, &mut current_block_direction_position, @@ -140,11 +146,15 @@ fn layout_block_level_children<'a>( adjust_static_positions( &mut absolutely_positioned_fragments, - &mut child_fragments, + &mut fragments, tree_rank, ); - (child_fragments, absolutely_positioned_fragments, block_size) + FlowChildren { + fragments, + absolutely_positioned_fragments, + block_size, + } } fn place_block_level_fragment( @@ -231,9 +241,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( absolutely_positioned_fragments: &mut Vec>, style: &Arc, collapsible_margins: CollapsibleMargins, - layout_contents: impl FnOnce( - &ContainingBlock, - ) -> (Vec, Vec>, Length), + layout_contents: impl FnOnce(&ContainingBlock) -> FlowChildren<'a>, ) -> BoxFragment { let cbis = containing_block.inline_size; let padding = style.padding().percentages_relative_to(cbis); @@ -291,10 +299,9 @@ fn layout_in_flow_non_replaced_block_level<'a>( containing_block.mode, containing_block_for_children.mode, "Mixed writing modes are not supported yet" ); - let (mut children, nested_abspos, content_block_size) = - layout_contents(&containing_block_for_children); + let mut flow_children = layout_contents(&containing_block_for_children); let relative_adjustement = relative_adjustement(style, inline_size, block_size); - let block_size = block_size.auto_is(|| content_block_size); + let block_size = block_size.auto_is(|| flow_children.block_size); let content_rect = Rect { start_corner: Vec2 { block: pb.block_start + relative_adjustement.block + initial_margin_block_start, @@ -307,18 +314,18 @@ fn layout_in_flow_non_replaced_block_level<'a>( }; if style.box_.position.is_relatively_positioned() { AbsolutelyPositionedFragment::in_positioned_containing_block( - &nested_abspos, - &mut children, + &flow_children.absolutely_positioned_fragments, + &mut flow_children.fragments, &content_rect.size, &padding, containing_block_for_children.mode, ) } else { - absolutely_positioned_fragments.extend(nested_abspos); + absolutely_positioned_fragments.extend(flow_children.absolutely_positioned_fragments); }; BoxFragment { style: style.clone(), - children, + children: flow_children.fragments, content_rect, padding, border, diff --git a/victor/src/layout/flow/root.rs b/victor/src/layout/flow/root.rs index bf044a3..489f4a0 100644 --- a/victor/src/layout/flow/root.rs +++ b/victor/src/layout/flow/root.rs @@ -101,18 +101,18 @@ impl BoxTreeRoot { mode: (WritingMode::HorizontalTb, Direction::Ltr), }; let dummy_tree_rank = 0; - let (mut fragments, abspos, _) = self.0.layout(&initial_containing_block, dummy_tree_rank); + let mut flow_children = self.0.layout(&initial_containing_block, dummy_tree_rank); let initial_containing_block = DefiniteContainingBlock { size: initial_containing_block_size, mode: initial_containing_block.mode, }; - fragments.par_extend( - abspos + flow_children.fragments.par_extend( + flow_children + .absolutely_positioned_fragments .par_iter() .map(|a| a.layout(&initial_containing_block)), ); - - fragments + flow_children.fragments } } diff --git a/victor/src/layout/mod.rs b/victor/src/layout/mod.rs index bfa637e..1d7beb8 100644 --- a/victor/src/layout/mod.rs +++ b/victor/src/layout/mod.rs @@ -59,11 +59,7 @@ impl IndependentFormattingContext { } } - fn layout( - &self, - containing_block: &ContainingBlock, - tree_rank: usize, - ) -> (Vec, Vec, Length) { + fn layout(&self, containing_block: &ContainingBlock, tree_rank: usize) -> FlowChildren { match self.as_replaced() { Ok(replaced) => match *replaced {}, Err(ifc) => ifc.layout(containing_block, tree_rank), @@ -72,11 +68,7 @@ impl IndependentFormattingContext { } impl<'a> NonReplacedIFC<'a> { - fn layout( - &self, - containing_block: &ContainingBlock, - tree_rank: usize, - ) -> (Vec, Vec>, Length) { + fn layout(&self, containing_block: &ContainingBlock, tree_rank: usize) -> FlowChildren<'a> { match self { NonReplacedIFC::Flow(bfc) => bfc.layout(containing_block, tree_rank), } diff --git a/victor/src/layout/positioned.rs b/victor/src/layout/positioned.rs index 336a6a5..01eb410 100644 --- a/victor/src/layout/positioned.rs +++ b/victor/src/layout/positioned.rs @@ -254,7 +254,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { "Mixed writing modes are not supported yet" ); let dummy_tree_rank = 0; - let (mut children, nested_abspos, block_size) = self + let mut flow_children = self .absolutely_positioned_box .contents .layout(&containing_block_for_children, dummy_tree_rank); @@ -266,7 +266,9 @@ impl<'a> AbsolutelyPositionedFragment<'a> { let block_start = match block_anchor { Anchor::Start(start) => start + pb.block_start + margin.block_start, - Anchor::End(end) => cbbs - end - pb.block_end - margin.block_end - block_size, + Anchor::End(end) => { + cbbs - end - pb.block_end - margin.block_end - flow_children.block_size + } }; let content_rect = Rect { @@ -276,13 +278,13 @@ impl<'a> AbsolutelyPositionedFragment<'a> { }, size: Vec2 { inline: inline_size, - block: block_size, + block: flow_children.block_size, }, }; AbsolutelyPositionedFragment::in_positioned_containing_block( - &nested_abspos, - &mut children, + &flow_children.absolutely_positioned_fragments, + &mut flow_children.fragments, &content_rect.size, &padding, containing_block_for_children.mode, @@ -290,7 +292,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { Fragment::Box(BoxFragment { style: style.clone(), - children, + children: flow_children.fragments, content_rect, padding, border, From 52a05494585fdb5e06c7c790f0df4aec861582e8 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 10 Jun 2019 10:33:30 +0200 Subject: [PATCH 06/18] Move place_block_level_fragment in layout_block_level_children --- victor/src/layout/flow/mod.rs | 68 +++++++++++++++++------------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index e96f5b8..8037675 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -88,6 +88,40 @@ fn layout_block_level_children<'a>( tree_rank: usize, child_boxes: &'a [BlockLevelBox], ) -> FlowChildren<'a> { + fn place_block_level_fragment( + fragment: &mut Fragment, + current_block_direction_position: &mut Length, + ongoing_collapsed_margin: &mut CollapsedMargin, + ) { + match fragment { + Fragment::Box(fragment) => { + let mut fragment_block_size = fragment.padding.block_sum() + + fragment.border.block_sum() + + fragment.content_rect.size.block; + if let Some(collapsing_context) = &fragment.collapsing_context { + *current_block_direction_position += collapsing_context + .start + .adjoin(ongoing_collapsed_margin) + .solve(); + *ongoing_collapsed_margin = collapsing_context.end; + } else { + fragment_block_size += fragment.margin.block_sum(); + *ongoing_collapsed_margin = CollapsedMargin::zero(); + } + fragment.content_rect.start_corner.block += *current_block_direction_position; + *current_block_direction_position += fragment_block_size; + } + Fragment::Anonymous(fragment) => { + // FIXME(nox): Margin collapsing for hypothetical boxes of + // abspos elements is probably wrong. + assert!(fragment.children.is_empty()); + assert_eq!(fragment.rect.size.block, Length::zero()); + fragment.rect.start_corner.block += *current_block_direction_position; + } + _ => unreachable!(), + } + } + let mut absolutely_positioned_fragments = vec![]; let mut current_block_direction_position = Length::zero(); let mut ongoing_collapsed_margin = CollapsedMargin::zero(); @@ -157,40 +191,6 @@ fn layout_block_level_children<'a>( } } -fn place_block_level_fragment( - fragment: &mut Fragment, - current_block_direction_position: &mut Length, - ongoing_collapsed_margin: &mut CollapsedMargin, -) { - match fragment { - Fragment::Box(fragment) => { - let mut fragment_block_size = fragment.padding.block_sum() - + fragment.border.block_sum() - + fragment.content_rect.size.block; - if let Some(collapsing_context) = &fragment.collapsing_context { - *current_block_direction_position += collapsing_context - .start - .adjoin(ongoing_collapsed_margin) - .solve(); - *ongoing_collapsed_margin = collapsing_context.end; - } else { - fragment_block_size += fragment.margin.block_sum(); - *ongoing_collapsed_margin = CollapsedMargin::zero(); - } - fragment.content_rect.start_corner.block += *current_block_direction_position; - *current_block_direction_position += fragment_block_size; - } - Fragment::Anonymous(fragment) => { - // FIXME(nox): Margin collapsing for hypothetical boxes of - // abspos elements is probably wrong. - assert!(fragment.children.is_empty()); - assert_eq!(fragment.rect.size.block, Length::zero()); - fragment.rect.start_corner.block += *current_block_direction_position; - } - _ => unreachable!(), - } -} - impl BlockLevelBox { fn layout<'a>( &'a self, From 3859d00a9eb9d79e988ebc6c8c164d10c764d74f Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 10 Jun 2019 10:45:41 +0200 Subject: [PATCH 07/18] Introduce OngoingCollapsedMargin --- victor/src/layout/flow/mod.rs | 34 +++++++++++++++++++++++++--------- victor/src/layout/fragments.rs | 9 +++++++++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index 8037675..8d8cbcc 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -91,7 +91,7 @@ fn layout_block_level_children<'a>( fn place_block_level_fragment( fragment: &mut Fragment, current_block_direction_position: &mut Length, - ongoing_collapsed_margin: &mut CollapsedMargin, + ongoing_collapsed_margin: &mut OngoingCollapsedMargin, ) { match fragment { Fragment::Box(fragment) => { @@ -99,14 +99,11 @@ fn layout_block_level_children<'a>( + fragment.border.block_sum() + fragment.content_rect.size.block; if let Some(collapsing_context) = &fragment.collapsing_context { - *current_block_direction_position += collapsing_context - .start - .adjoin(ongoing_collapsed_margin) - .solve(); - *ongoing_collapsed_margin = collapsing_context.end; + *current_block_direction_position += + ongoing_collapsed_margin.adjoin(collapsing_context); } else { fragment_block_size += fragment.margin.block_sum(); - *ongoing_collapsed_margin = CollapsedMargin::zero(); + ongoing_collapsed_margin.reset_end(); } fragment.content_rect.start_corner.block += *current_block_direction_position; *current_block_direction_position += fragment_block_size; @@ -122,9 +119,27 @@ fn layout_block_level_children<'a>( } } + struct OngoingCollapsedMargin { + context: CollapsingContext, + } + + impl OngoingCollapsedMargin { + fn adjoin(&mut self, other: &CollapsingContext) -> Length { + let margin = self.context.end.adjoin(&other.start).solve(); + self.context.end = other.end; + margin + } + + fn reset_end(&mut self) { + self.context.end = CollapsedMargin::zero(); + } + } + let mut absolutely_positioned_fragments = vec![]; let mut current_block_direction_position = Length::zero(); - let mut ongoing_collapsed_margin = CollapsedMargin::zero(); + let mut ongoing_collapsed_margin = OngoingCollapsedMargin { + context: CollapsingContext::zero(), + }; let mut fragments: Vec<_>; if let Some(float_context) = float_context { // Because floats are involved, we do layout for this block formatting context @@ -175,7 +190,8 @@ fn layout_block_level_children<'a>( ) } } - let content_block_size = current_block_direction_position + ongoing_collapsed_margin.solve(); + let content_block_size = + current_block_direction_position + ongoing_collapsed_margin.context.end.solve(); let block_size = containing_block.block_size.auto_is(|| content_block_size); adjust_static_positions( diff --git a/victor/src/layout/fragments.rs b/victor/src/layout/fragments.rs index 180ab0c..45f7e83 100644 --- a/victor/src/layout/fragments.rs +++ b/victor/src/layout/fragments.rs @@ -74,6 +74,15 @@ impl CollapsingContext { } } +impl CollapsingContext { + pub fn zero() -> Self { + Self { + start: CollapsedMargin::zero(), + end: CollapsedMargin::zero(), + } + } +} + impl CollapsedMargin { pub fn zero() -> Self { Self { From 86c8fd9f183989dd2b38d5fa8ebb3fc7d797163e Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 10 Jun 2019 11:35:41 +0200 Subject: [PATCH 08/18] Implement margin collapsing with parent margins --- tests/reftests/blocks.png | Bin 2586 -> 2586 bytes victor/src/layout/flow/inline.rs | 1 + victor/src/layout/flow/mod.rs | 83 ++++++++++++++++++++++++------ victor/src/layout/fragments.rs | 4 ++ victor/src/layout/positioned.rs | 5 +- victor/src/style/values/length.rs | 2 +- 6 files changed, 77 insertions(+), 18 deletions(-) diff --git a/tests/reftests/blocks.png b/tests/reftests/blocks.png index 9eb0c8fd5bc47dcfc1fe3641e0c86ca5c601d82f..60023f2842453a877024b4f1325071eac5eb9432 100644 GIT binary patch delta 257 zcmbOwGD~EF4>Qy6#EJe^;`gkVv+vo`S6#)#uwm!c^wWQQ`5720q$VpeS_$r6#@-Y4 z{R`8L>sHIf8ESOJCmXVAPyWD?gM@u~Zcyt$#+H6yMNW|3{ls UX!7pf^$bAZ>FVdQ&MBb@0ATQ9#{d8T literal 2586 zcmeAS@N?(olHy`uVBq!ia0y~yV2WU1U{>H@1B(1lkU0XR*pj^6T^Rm@;DWu&Co?c` zp7(Td45^s&_U^&n!v+E@jxQG+n7LDr@prPxhAlCo2W_N(EA%r1by5Tp?4N&W*nX|h z-=BfOZ2PyInfqTdGBEfnZ(v|ZV&Y~{P$QXf{YyjO>v?euzoVXiVQN_aw275LKp5y< z!^Tm@kPC#}%h-EB@yPI?F^1TbVE=E@Z`-{L-<~dKZs^~cz{qffMU270XOuDY0%6@t z#>Lkx_cAb4D2VGYG|V`_#L&SxxEK_bexsU4Ltr!nMni!1A@E>n{e;t;LhCBk#X**N My85}Sb4q9e05-84ga7~l diff --git a/victor/src/layout/flow/inline.rs b/victor/src/layout/flow/inline.rs index 9ab02c7..5776c99 100644 --- a/victor/src/layout/flow/inline.rs +++ b/victor/src/layout/flow/inline.rs @@ -141,6 +141,7 @@ impl InlineFormattingContext { fragments: ifc.line_boxes.boxes, absolutely_positioned_fragments: ifc.absolutely_positioned_fragments, block_size: ifc.line_boxes.next_line_block_position, + collapsing_context: CollapsingContext::zero(), }; } } diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index 8d8cbcc..addbd5b 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -43,11 +43,15 @@ pub(super) struct FlowChildren<'a> { pub fragments: Vec, pub absolutely_positioned_fragments: Vec>, pub block_size: Length, + pub collapsing_context: CollapsingContext, } #[derive(Clone, Copy)] struct CollapsibleMargins(bool); +#[derive(Clone, Copy)] +struct CollapsibleWithParentStartMargin(bool); + impl BlockFormattingContext { pub(super) fn layout( &self, @@ -61,22 +65,34 @@ impl BlockFormattingContext { } else { None }; - self.contents - .layout(containing_block, float_context, tree_rank) + let mut flow_children = self.contents.layout( + containing_block, + float_context, + tree_rank, + CollapsibleWithParentStartMargin(false), + ); + flow_children.block_size += flow_children.collapsing_context.end.solve(); + flow_children.collapsing_context.end = CollapsedMargin::zero(); + flow_children } } impl BlockContainer { - pub fn layout( + fn layout( &self, containing_block: &ContainingBlock, float_context: Option<&mut FloatContext>, tree_rank: usize, + collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, ) -> FlowChildren { match self { - BlockContainer::BlockLevelBoxes(child_boxes) => { - layout_block_level_children(containing_block, float_context, tree_rank, child_boxes) - } + BlockContainer::BlockLevelBoxes(child_boxes) => layout_block_level_children( + containing_block, + float_context, + tree_rank, + collapsible_with_parent_start_margin, + child_boxes, + ), BlockContainer::InlineFormattingContext(ifc) => ifc.layout(containing_block, tree_rank), } } @@ -86,6 +102,7 @@ fn layout_block_level_children<'a>( containing_block: &ContainingBlock, float_context: Option<&mut FloatContext>, tree_rank: usize, + collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, child_boxes: &'a [BlockLevelBox], ) -> FlowChildren<'a> { fn place_block_level_fragment( @@ -120,11 +137,18 @@ fn layout_block_level_children<'a>( } struct OngoingCollapsedMargin { + collapsed_with_parent_start_margin: bool, context: CollapsingContext, } impl OngoingCollapsedMargin { fn adjoin(&mut self, other: &CollapsingContext) -> Length { + if self.collapsed_with_parent_start_margin.take() { + assert_eq!(self.context.end.solve(), Length::zero()); + self.context.start.adjoin_assign(&other.start); + self.context.end = other.end; + return Length::zero(); + } let margin = self.context.end.adjoin(&other.start).solve(); self.context.end = other.end; margin @@ -138,6 +162,7 @@ fn layout_block_level_children<'a>( let mut absolutely_positioned_fragments = vec![]; let mut current_block_direction_position = Length::zero(); let mut ongoing_collapsed_margin = OngoingCollapsedMargin { + collapsed_with_parent_start_margin: collapsible_with_parent_start_margin.0, context: CollapsingContext::zero(), }; let mut fragments: Vec<_>; @@ -190,9 +215,6 @@ fn layout_block_level_children<'a>( ) } } - let content_block_size = - current_block_direction_position + ongoing_collapsed_margin.context.end.solve(); - let block_size = containing_block.block_size.auto_is(|| content_block_size); adjust_static_positions( &mut absolutely_positioned_fragments, @@ -203,7 +225,8 @@ fn layout_block_level_children<'a>( FlowChildren { fragments, absolutely_positioned_fragments, - block_size, + block_size: current_block_direction_position, + collapsing_context: ongoing_collapsed_margin.context, } } @@ -222,7 +245,14 @@ impl BlockLevelBox { absolutely_positioned_fragments, style, CollapsibleMargins(true), - |containing_block| contents.layout(containing_block, float_context, tree_rank), + |containing_block, collapsible_with_parent_start_margin| { + contents.layout( + containing_block, + float_context, + tree_rank, + collapsible_with_parent_start_margin, + ) + }, )) } BlockLevelBox::Independent { style, contents } => match contents.as_replaced() { @@ -235,7 +265,7 @@ impl BlockLevelBox { absolutely_positioned_fragments, style, CollapsibleMargins(false), - |containing_block| contents.layout(containing_block, tree_rank), + |containing_block, _| contents.layout(containing_block, tree_rank), )), }, BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => { @@ -257,7 +287,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( absolutely_positioned_fragments: &mut Vec>, style: &Arc, collapsible_margins: CollapsibleMargins, - layout_contents: impl FnOnce(&ContainingBlock) -> FlowChildren<'a>, + layout_contents: impl FnOnce(&ContainingBlock, CollapsibleWithParentStartMargin) -> FlowChildren<'a>, ) -> BoxFragment { let cbis = containing_block.inline_size; let padding = style.padding().percentages_relative_to(cbis); @@ -291,7 +321,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( } } let margin = computed_margin.auto_is(Length::zero); - let (collapsing_context, initial_margin_block_start) = if collapsible_margins.0 { + let (mut collapsing_context, initial_margin_block_start) = if collapsible_margins.0 { ( Some(CollapsingContext::from_margin(&margin)), Length::zero(), @@ -315,7 +345,30 @@ fn layout_in_flow_non_replaced_block_level<'a>( containing_block.mode, containing_block_for_children.mode, "Mixed writing modes are not supported yet" ); - let mut flow_children = layout_contents(&containing_block_for_children); + let collapsible_with_parent_start_margin = + CollapsibleWithParentStartMargin(collapsible_margins.0 && pb.block_start == Length::zero()); + let mut flow_children = layout_contents( + &containing_block_for_children, + collapsible_with_parent_start_margin, + ); + if let Some(collapsing_context) = &mut collapsing_context { + if collapsible_with_parent_start_margin.0 { + collapsing_context + .start + .adjoin_assign(&flow_children.collapsing_context.start); + } + } + let collapsible_with_parent_end_margin = + collapsible_margins.0 && pb.block_end == Length::zero() && block_size == LengthOrAuto::Auto; + let collapsed_end_margin = collapsing_context + .as_mut() + .map(|context| &mut context.end) + .filter(|_| collapsible_with_parent_end_margin); + if let Some(collapsed_end_margin) = collapsed_end_margin { + collapsed_end_margin.adjoin_assign(&flow_children.collapsing_context.end); + } else { + flow_children.block_size += flow_children.collapsing_context.end.solve(); + } let relative_adjustement = relative_adjustement(style, inline_size, block_size); let block_size = block_size.auto_is(|| flow_children.block_size); let content_rect = Rect { diff --git a/victor/src/layout/fragments.rs b/victor/src/layout/fragments.rs index 45f7e83..238dd5b 100644 --- a/victor/src/layout/fragments.rs +++ b/victor/src/layout/fragments.rs @@ -105,6 +105,10 @@ impl CollapsedMargin { } } + pub fn adjoin_assign(&mut self, other: &Self) { + *self = self.adjoin(other); + } + pub fn solve(&self) -> Length { self.max_positive + self.min_negative } diff --git a/victor/src/layout/positioned.rs b/victor/src/layout/positioned.rs index 01eb410..fd92a39 100644 --- a/victor/src/layout/positioned.rs +++ b/victor/src/layout/positioned.rs @@ -264,10 +264,11 @@ impl<'a> AbsolutelyPositionedFragment<'a> { Anchor::End(end) => cbbs - end - pb.inline_end - margin.inline_end - inline_size, }; + let block_size = block_size.auto_is(|| flow_children.block_size); let block_start = match block_anchor { Anchor::Start(start) => start + pb.block_start + margin.block_start, Anchor::End(end) => { - cbbs - end - pb.block_end - margin.block_end - flow_children.block_size + cbbs - end - pb.block_end - margin.block_end - block_size } }; @@ -278,7 +279,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { }, size: Vec2 { inline: inline_size, - block: flow_children.block_size, + block: block_size, }, }; diff --git a/victor/src/style/values/length.rs b/victor/src/style/values/length.rs index adbebfd..531e7b9 100644 --- a/victor/src/style/values/length.rs +++ b/victor/src/style/values/length.rs @@ -50,7 +50,7 @@ pub(crate) enum LengthOrPercentageOrAuto { Auto, } -#[derive(Debug, Copy, Clone, FromVariants)] +#[derive(Copy, Clone, Debug, FromVariants, PartialEq)] pub(crate) enum LengthOrAuto { Length(Length), Auto, From 6ecbcdea1b13c1bd1d412550af6eac6463064a74 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 11 Jun 2019 10:40:09 +0200 Subject: [PATCH 09/18] fmt --- victor/src/layout/positioned.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/victor/src/layout/positioned.rs b/victor/src/layout/positioned.rs index fd92a39..a99aae4 100644 --- a/victor/src/layout/positioned.rs +++ b/victor/src/layout/positioned.rs @@ -267,9 +267,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { let block_size = block_size.auto_is(|| flow_children.block_size); let block_start = match block_anchor { Anchor::Start(start) => start + pb.block_start + margin.block_start, - Anchor::End(end) => { - cbbs - end - pb.block_end - margin.block_end - block_size - } + Anchor::End(end) => cbbs - end - pb.block_end - margin.block_end - block_size, }; let content_rect = Rect { From 5aca8ad11eddd747e77fd4a75e328bf0319061f7 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 11 Jun 2019 10:44:30 +0200 Subject: [PATCH 10/18] Replace CollapsibleMargins bool wrapper with BlockLevelKind enum --- victor/src/layout/flow/mod.rs | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index addbd5b..91c392c 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -46,9 +46,6 @@ pub(super) struct FlowChildren<'a> { pub collapsing_context: CollapsingContext, } -#[derive(Clone, Copy)] -struct CollapsibleMargins(bool); - #[derive(Clone, Copy)] struct CollapsibleWithParentStartMargin(bool); @@ -244,7 +241,7 @@ impl BlockLevelBox { containing_block, absolutely_positioned_fragments, style, - CollapsibleMargins(true), + BlockLevelKind::SameFormattingContextBlock, |containing_block, collapsible_with_parent_start_margin| { contents.layout( containing_block, @@ -264,7 +261,7 @@ impl BlockLevelBox { containing_block, absolutely_positioned_fragments, style, - CollapsibleMargins(false), + BlockLevelKind::EstablishesAnIndependentFormattingContext, |containing_block, _| contents.layout(containing_block, tree_rank), )), }, @@ -280,13 +277,18 @@ impl BlockLevelBox { } } +enum BlockLevelKind { + SameFormattingContextBlock, + EstablishesAnIndependentFormattingContext, +} + /// https://drafts.csswg.org/css2/visudet.html#blockwidth /// https://drafts.csswg.org/css2/visudet.html#normal-block fn layout_in_flow_non_replaced_block_level<'a>( containing_block: &ContainingBlock, absolutely_positioned_fragments: &mut Vec>, style: &Arc, - collapsible_margins: CollapsibleMargins, + block_level_kind: BlockLevelKind, layout_contents: impl FnOnce(&ContainingBlock, CollapsibleWithParentStartMargin) -> FlowChildren<'a>, ) -> BoxFragment { let cbis = containing_block.inline_size; @@ -321,13 +323,12 @@ fn layout_in_flow_non_replaced_block_level<'a>( } } let margin = computed_margin.auto_is(Length::zero); - let (mut collapsing_context, initial_margin_block_start) = if collapsible_margins.0 { - ( + let (mut collapsing_context, initial_margin_block_start) = match block_level_kind { + BlockLevelKind::SameFormattingContextBlock => ( Some(CollapsingContext::from_margin(&margin)), Length::zero(), - ) - } else { - (None, margin.block_start) + ), + BlockLevelKind::EstablishesAnIndependentFormattingContext => (None, margin.block_start), }; let inline_size = inline_size.auto_is(|| cbis - pb.inline_sum() - margin.inline_sum()); let block_size = match box_size.block { @@ -345,8 +346,10 @@ fn layout_in_flow_non_replaced_block_level<'a>( containing_block.mode, containing_block_for_children.mode, "Mixed writing modes are not supported yet" ); - let collapsible_with_parent_start_margin = - CollapsibleWithParentStartMargin(collapsible_margins.0 && pb.block_start == Length::zero()); + let collapsible_with_parent_start_margin = CollapsibleWithParentStartMargin( + matches!(block_level_kind, BlockLevelKind::SameFormattingContextBlock) + && pb.block_start == Length::zero(), + ); let mut flow_children = layout_contents( &containing_block_for_children, collapsible_with_parent_start_margin, @@ -359,7 +362,9 @@ fn layout_in_flow_non_replaced_block_level<'a>( } } let collapsible_with_parent_end_margin = - collapsible_margins.0 && pb.block_end == Length::zero() && block_size == LengthOrAuto::Auto; + matches!(block_level_kind, BlockLevelKind::SameFormattingContextBlock) + && pb.block_end == Length::zero() + && block_size == LengthOrAuto::Auto; let collapsed_end_margin = collapsing_context .as_mut() .map(|context| &mut context.end) From 3b4750f60f2698550bf20791d9da3066ad27ecc5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 11 Jun 2019 11:31:27 +0200 Subject: [PATCH 11/18] More margin collapsings related renames --- victor/src/layout/flow/inline.rs | 4 ++-- victor/src/layout/flow/mod.rs | 40 ++++++++++++++++---------------- victor/src/layout/fragments.rs | 8 +++---- victor/src/layout/positioned.rs | 2 +- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/victor/src/layout/flow/inline.rs b/victor/src/layout/flow/inline.rs index 5776c99..26e5dc7 100644 --- a/victor/src/layout/flow/inline.rs +++ b/victor/src/layout/flow/inline.rs @@ -141,7 +141,7 @@ impl InlineFormattingContext { fragments: ifc.line_boxes.boxes, absolutely_positioned_fragments: ifc.absolutely_positioned_fragments, block_size: ifc.line_boxes.next_line_block_position, - collapsing_context: CollapsingContext::zero(), + collapsible_margins_in_children: CollapsedBlockMargins::zero(), }; } } @@ -243,7 +243,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> { padding: self.padding.clone(), border: self.border.clone(), margin: self.margin.clone(), - collapsing_context: None, + collapsible_margins_in_children: None, }; let last_fragment = self.last_box_tree_fragment && !at_line_break; if last_fragment { diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index 91c392c..c73eb21 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -43,7 +43,7 @@ pub(super) struct FlowChildren<'a> { pub fragments: Vec, pub absolutely_positioned_fragments: Vec>, pub block_size: Length, - pub collapsing_context: CollapsingContext, + pub collapsible_margins_in_children: CollapsedBlockMargins, } #[derive(Clone, Copy)] @@ -68,8 +68,8 @@ impl BlockFormattingContext { tree_rank, CollapsibleWithParentStartMargin(false), ); - flow_children.block_size += flow_children.collapsing_context.end.solve(); - flow_children.collapsing_context.end = CollapsedMargin::zero(); + flow_children.block_size += flow_children.collapsible_margins_in_children.end.solve(); + flow_children.collapsible_margins_in_children.end = CollapsedMargin::zero(); flow_children } } @@ -112,7 +112,7 @@ fn layout_block_level_children<'a>( let mut fragment_block_size = fragment.padding.block_sum() + fragment.border.block_sum() + fragment.content_rect.size.block; - if let Some(collapsing_context) = &fragment.collapsing_context { + if let Some(collapsing_context) = &fragment.collapsible_margins_in_children { *current_block_direction_position += ongoing_collapsed_margin.adjoin(collapsing_context); } else { @@ -135,11 +135,11 @@ fn layout_block_level_children<'a>( struct OngoingCollapsedMargin { collapsed_with_parent_start_margin: bool, - context: CollapsingContext, + context: CollapsedBlockMargins, } impl OngoingCollapsedMargin { - fn adjoin(&mut self, other: &CollapsingContext) -> Length { + fn adjoin(&mut self, other: &CollapsedBlockMargins) -> Length { if self.collapsed_with_parent_start_margin.take() { assert_eq!(self.context.end.solve(), Length::zero()); self.context.start.adjoin_assign(&other.start); @@ -160,7 +160,7 @@ fn layout_block_level_children<'a>( let mut current_block_direction_position = Length::zero(); let mut ongoing_collapsed_margin = OngoingCollapsedMargin { collapsed_with_parent_start_margin: collapsible_with_parent_start_margin.0, - context: CollapsingContext::zero(), + context: CollapsedBlockMargins::zero(), }; let mut fragments: Vec<_>; if let Some(float_context) = float_context { @@ -223,7 +223,7 @@ fn layout_block_level_children<'a>( fragments, absolutely_positioned_fragments, block_size: current_block_direction_position, - collapsing_context: ongoing_collapsed_margin.context, + collapsible_margins_in_children: ongoing_collapsed_margin.context, } } @@ -323,9 +323,9 @@ fn layout_in_flow_non_replaced_block_level<'a>( } } let margin = computed_margin.auto_is(Length::zero); - let (mut collapsing_context, initial_margin_block_start) = match block_level_kind { + let (mut collapsible_margins_in_children, initial_margin_block_start) = match block_level_kind { BlockLevelKind::SameFormattingContextBlock => ( - Some(CollapsingContext::from_margin(&margin)), + Some(CollapsedBlockMargins::from_margin(&margin)), Length::zero(), ), BlockLevelKind::EstablishesAnIndependentFormattingContext => (None, margin.block_start), @@ -346,33 +346,33 @@ fn layout_in_flow_non_replaced_block_level<'a>( containing_block.mode, containing_block_for_children.mode, "Mixed writing modes are not supported yet" ); - let collapsible_with_parent_start_margin = CollapsibleWithParentStartMargin( + let this_start_margin_can_collapse_with_children = CollapsibleWithParentStartMargin( matches!(block_level_kind, BlockLevelKind::SameFormattingContextBlock) && pb.block_start == Length::zero(), ); let mut flow_children = layout_contents( &containing_block_for_children, - collapsible_with_parent_start_margin, + this_start_margin_can_collapse_with_children, ); - if let Some(collapsing_context) = &mut collapsing_context { - if collapsible_with_parent_start_margin.0 { - collapsing_context + if let Some(collapsible_margins_in_children) = &mut collapsible_margins_in_children { + if this_start_margin_can_collapse_with_children.0 { + collapsible_margins_in_children .start - .adjoin_assign(&flow_children.collapsing_context.start); + .adjoin_assign(&flow_children.collapsible_margins_in_children.start); } } let collapsible_with_parent_end_margin = matches!(block_level_kind, BlockLevelKind::SameFormattingContextBlock) && pb.block_end == Length::zero() && block_size == LengthOrAuto::Auto; - let collapsed_end_margin = collapsing_context + let collapsed_end_margin = collapsible_margins_in_children .as_mut() .map(|context| &mut context.end) .filter(|_| collapsible_with_parent_end_margin); if let Some(collapsed_end_margin) = collapsed_end_margin { - collapsed_end_margin.adjoin_assign(&flow_children.collapsing_context.end); + collapsed_end_margin.adjoin_assign(&flow_children.collapsible_margins_in_children.end); } else { - flow_children.block_size += flow_children.collapsing_context.end.solve(); + flow_children.block_size += flow_children.collapsible_margins_in_children.end.solve(); } let relative_adjustement = relative_adjustement(style, inline_size, block_size); let block_size = block_size.auto_is(|| flow_children.block_size); @@ -404,6 +404,6 @@ fn layout_in_flow_non_replaced_block_level<'a>( padding, border, margin, - collapsing_context, + collapsible_margins_in_children, } } diff --git a/victor/src/layout/fragments.rs b/victor/src/layout/fragments.rs index 238dd5b..680b3c3 100644 --- a/victor/src/layout/fragments.rs +++ b/victor/src/layout/fragments.rs @@ -20,10 +20,10 @@ pub(crate) struct BoxFragment { pub border: Sides, pub margin: Sides, - pub collapsing_context: Option, + pub collapsible_margins_in_children: Option, } -pub(crate) struct CollapsingContext { +pub(crate) struct CollapsedBlockMargins { pub start: CollapsedMargin, pub end: CollapsedMargin, } @@ -65,16 +65,14 @@ impl BoxFragment { } } -impl CollapsingContext { +impl CollapsedBlockMargins { pub fn from_margin(margin: &Sides) -> Self { Self { start: CollapsedMargin::new(margin.block_start), end: CollapsedMargin::new(margin.block_end), } } -} -impl CollapsingContext { pub fn zero() -> Self { Self { start: CollapsedMargin::zero(), diff --git a/victor/src/layout/positioned.rs b/victor/src/layout/positioned.rs index a99aae4..6b7fecd 100644 --- a/victor/src/layout/positioned.rs +++ b/victor/src/layout/positioned.rs @@ -296,7 +296,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { padding, border, margin, - collapsing_context: None, + collapsible_margins_in_children: None, }) } } From c0748c6a64193efa8bb44d4364a10ca061b0699f Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 11 Jun 2019 11:46:17 +0200 Subject: [PATCH 12/18] PartialEq --- victor/src/layout/flow/mod.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index c73eb21..4c4b4b6 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -277,6 +277,7 @@ impl BlockLevelBox { } } +#[derive(PartialEq)] enum BlockLevelKind { SameFormattingContextBlock, EstablishesAnIndependentFormattingContext, @@ -347,7 +348,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( "Mixed writing modes are not supported yet" ); let this_start_margin_can_collapse_with_children = CollapsibleWithParentStartMargin( - matches!(block_level_kind, BlockLevelKind::SameFormattingContextBlock) + block_level_kind == BlockLevelKind::SameFormattingContextBlock && pb.block_start == Length::zero(), ); let mut flow_children = layout_contents( @@ -361,10 +362,12 @@ fn layout_in_flow_non_replaced_block_level<'a>( .adjoin_assign(&flow_children.collapsible_margins_in_children.start); } } - let collapsible_with_parent_end_margin = - matches!(block_level_kind, BlockLevelKind::SameFormattingContextBlock) - && pb.block_end == Length::zero() - && block_size == LengthOrAuto::Auto; + let collapsible_with_parent_end_margin = (block_level_kind, pb.block_end, block_size) + == ( + BlockLevelKind::SameFormattingContextBlock, + Length::zero(), + LengthOrAuto::Auto, + ); let collapsed_end_margin = collapsible_margins_in_children .as_mut() .map(|context| &mut context.end) From a669851b9c12088df9382cf685a0f96d361e45b5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 12 Jun 2019 16:54:49 +0200 Subject: [PATCH 13/18] Collapse margins of independent formatting contexts with their siblings --- victor/src/layout/flow/inline.rs | 2 +- victor/src/layout/flow/mod.rs | 39 ++++++++++---------------------- victor/src/layout/fragments.rs | 2 +- victor/src/layout/positioned.rs | 2 +- 4 files changed, 15 insertions(+), 30 deletions(-) diff --git a/victor/src/layout/flow/inline.rs b/victor/src/layout/flow/inline.rs index 26e5dc7..4a86402 100644 --- a/victor/src/layout/flow/inline.rs +++ b/victor/src/layout/flow/inline.rs @@ -243,7 +243,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> { padding: self.padding.clone(), border: self.border.clone(), margin: self.margin.clone(), - collapsible_margins_in_children: None, + collapsible_margins_in_children: CollapsedBlockMargins::zero(), }; let last_fragment = self.last_box_tree_fragment && !at_line_break; if last_fragment { diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index 4c4b4b6..e539192 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -112,13 +112,8 @@ fn layout_block_level_children<'a>( let mut fragment_block_size = fragment.padding.block_sum() + fragment.border.block_sum() + fragment.content_rect.size.block; - if let Some(collapsing_context) = &fragment.collapsible_margins_in_children { - *current_block_direction_position += - ongoing_collapsed_margin.adjoin(collapsing_context); - } else { - fragment_block_size += fragment.margin.block_sum(); - ongoing_collapsed_margin.reset_end(); - } + *current_block_direction_position += + ongoing_collapsed_margin.adjoin(&fragment.collapsible_margins_in_children); fragment.content_rect.start_corner.block += *current_block_direction_position; *current_block_direction_position += fragment_block_size; } @@ -324,13 +319,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( } } let margin = computed_margin.auto_is(Length::zero); - let (mut collapsible_margins_in_children, initial_margin_block_start) = match block_level_kind { - BlockLevelKind::SameFormattingContextBlock => ( - Some(CollapsedBlockMargins::from_margin(&margin)), - Length::zero(), - ), - BlockLevelKind::EstablishesAnIndependentFormattingContext => (None, margin.block_start), - }; + let mut collapsible_margins_in_children = CollapsedBlockMargins::from_margin(&margin); let inline_size = inline_size.auto_is(|| cbis - pb.inline_sum() - margin.inline_sum()); let block_size = match box_size.block { LengthOrPercentageOrAuto::Length(l) => LengthOrAuto::Length(l), @@ -355,12 +344,10 @@ fn layout_in_flow_non_replaced_block_level<'a>( &containing_block_for_children, this_start_margin_can_collapse_with_children, ); - if let Some(collapsible_margins_in_children) = &mut collapsible_margins_in_children { - if this_start_margin_can_collapse_with_children.0 { - collapsible_margins_in_children - .start - .adjoin_assign(&flow_children.collapsible_margins_in_children.start); - } + if this_start_margin_can_collapse_with_children.0 { + collapsible_margins_in_children + .start + .adjoin_assign(&flow_children.collapsible_margins_in_children.start); } let collapsible_with_parent_end_margin = (block_level_kind, pb.block_end, block_size) == ( @@ -368,12 +355,10 @@ fn layout_in_flow_non_replaced_block_level<'a>( Length::zero(), LengthOrAuto::Auto, ); - let collapsed_end_margin = collapsible_margins_in_children - .as_mut() - .map(|context| &mut context.end) - .filter(|_| collapsible_with_parent_end_margin); - if let Some(collapsed_end_margin) = collapsed_end_margin { - collapsed_end_margin.adjoin_assign(&flow_children.collapsible_margins_in_children.end); + if collapsible_with_parent_end_margin { + collapsible_margins_in_children + .end + .adjoin_assign(&flow_children.collapsible_margins_in_children.end); } else { flow_children.block_size += flow_children.collapsible_margins_in_children.end.solve(); } @@ -381,7 +366,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( let block_size = block_size.auto_is(|| flow_children.block_size); let content_rect = Rect { start_corner: Vec2 { - block: pb.block_start + relative_adjustement.block + initial_margin_block_start, + block: pb.block_start + relative_adjustement.block, inline: pb.inline_start + relative_adjustement.inline + margin.inline_start, }, size: Vec2 { diff --git a/victor/src/layout/fragments.rs b/victor/src/layout/fragments.rs index 680b3c3..fbcd305 100644 --- a/victor/src/layout/fragments.rs +++ b/victor/src/layout/fragments.rs @@ -20,7 +20,7 @@ pub(crate) struct BoxFragment { pub border: Sides, pub margin: Sides, - pub collapsible_margins_in_children: Option, + pub collapsible_margins_in_children: CollapsedBlockMargins, } pub(crate) struct CollapsedBlockMargins { diff --git a/victor/src/layout/positioned.rs b/victor/src/layout/positioned.rs index 6b7fecd..06076b8 100644 --- a/victor/src/layout/positioned.rs +++ b/victor/src/layout/positioned.rs @@ -296,7 +296,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { padding, border, margin, - collapsible_margins_in_children: None, + collapsible_margins_in_children: CollapsedBlockMargins::zero(), }) } } From deb5b4ec988ffd52ac8aa101b4def459b8849930 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 12 Jun 2019 22:40:28 +0200 Subject: [PATCH 14/18] Warnings --- victor/src/layout/flow/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index e539192..ce3dce1 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -109,7 +109,7 @@ fn layout_block_level_children<'a>( ) { match fragment { Fragment::Box(fragment) => { - let mut fragment_block_size = fragment.padding.block_sum() + let fragment_block_size = fragment.padding.block_sum() + fragment.border.block_sum() + fragment.content_rect.size.block; *current_block_direction_position += @@ -145,10 +145,6 @@ fn layout_block_level_children<'a>( self.context.end = other.end; margin } - - fn reset_end(&mut self) { - self.context.end = CollapsedMargin::zero(); - } } let mut absolutely_positioned_fragments = vec![]; From 8dc4440cb40033f771bf6e8e1effd7a4b71b815e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 12 Jun 2019 22:41:14 +0200 Subject: [PATCH 15/18] Another rename --- victor/src/layout/flow/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index ce3dce1..861b209 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -345,13 +345,13 @@ fn layout_in_flow_non_replaced_block_level<'a>( .start .adjoin_assign(&flow_children.collapsible_margins_in_children.start); } - let collapsible_with_parent_end_margin = (block_level_kind, pb.block_end, block_size) + let this_end_margin_can_collapse_with_children = (block_level_kind, pb.block_end, block_size) == ( BlockLevelKind::SameFormattingContextBlock, Length::zero(), LengthOrAuto::Auto, ); - if collapsible_with_parent_end_margin { + if this_end_margin_can_collapse_with_children { collapsible_margins_in_children .end .adjoin_assign(&flow_children.collapsible_margins_in_children.end); From 6768a5b98ea96e06cc95fc46cc171a26e7e01206 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 12 Jun 2019 23:05:01 +0200 Subject: [PATCH 16/18] Inline OngoingCollapsedMargin::adjoin --- victor/src/layout/flow/mod.rs | 36 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index 861b209..4d70f61 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -112,8 +112,26 @@ fn layout_block_level_children<'a>( let fragment_block_size = fragment.padding.block_sum() + fragment.border.block_sum() + fragment.content_rect.size.block; - *current_block_direction_position += - ongoing_collapsed_margin.adjoin(&fragment.collapsible_margins_in_children); + + let end = std::mem::replace( + &mut ongoing_collapsed_margin.context.end, + fragment.collapsible_margins_in_children.end, + ); + if ongoing_collapsed_margin + .collapsed_with_parent_start_margin + .take() + { + assert_eq!(end.solve(), Length::zero()); + ongoing_collapsed_margin + .context + .start + .adjoin_assign(&fragment.collapsible_margins_in_children.start); + } else { + *current_block_direction_position += end + .adjoin(&fragment.collapsible_margins_in_children.start) + .solve() + } + fragment.content_rect.start_corner.block += *current_block_direction_position; *current_block_direction_position += fragment_block_size; } @@ -133,20 +151,6 @@ fn layout_block_level_children<'a>( context: CollapsedBlockMargins, } - impl OngoingCollapsedMargin { - fn adjoin(&mut self, other: &CollapsedBlockMargins) -> Length { - if self.collapsed_with_parent_start_margin.take() { - assert_eq!(self.context.end.solve(), Length::zero()); - self.context.start.adjoin_assign(&other.start); - self.context.end = other.end; - return Length::zero(); - } - let margin = self.context.end.adjoin(&other.start).solve(); - self.context.end = other.end; - margin - } - } - let mut absolutely_positioned_fragments = vec![]; let mut current_block_direction_position = Length::zero(); let mut ongoing_collapsed_margin = OngoingCollapsedMargin { From 04251afa7ea065c6f40ff9b6c50086a8344480b0 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 12 Jun 2019 23:17:30 +0200 Subject: [PATCH 17/18] BoxFragment::collapsible_margins_in_children is actually block_margins_collapsed_with_children But FlowChildren::collapsible_margins_in_children is correctly named. --- victor/src/layout/flow/inline.rs | 2 +- victor/src/layout/flow/mod.rs | 14 +++++++------- victor/src/layout/fragments.rs | 2 +- victor/src/layout/positioned.rs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/victor/src/layout/flow/inline.rs b/victor/src/layout/flow/inline.rs index 4a86402..8086332 100644 --- a/victor/src/layout/flow/inline.rs +++ b/victor/src/layout/flow/inline.rs @@ -243,7 +243,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> { padding: self.padding.clone(), border: self.border.clone(), margin: self.margin.clone(), - collapsible_margins_in_children: CollapsedBlockMargins::zero(), + block_margins_collapsed_with_children: CollapsedBlockMargins::zero(), }; let last_fragment = self.last_box_tree_fragment && !at_line_break; if last_fragment { diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index 4d70f61..bf8c916 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -115,7 +115,7 @@ fn layout_block_level_children<'a>( let end = std::mem::replace( &mut ongoing_collapsed_margin.context.end, - fragment.collapsible_margins_in_children.end, + fragment.block_margins_collapsed_with_children.end, ); if ongoing_collapsed_margin .collapsed_with_parent_start_margin @@ -125,10 +125,10 @@ fn layout_block_level_children<'a>( ongoing_collapsed_margin .context .start - .adjoin_assign(&fragment.collapsible_margins_in_children.start); + .adjoin_assign(&fragment.block_margins_collapsed_with_children.start); } else { *current_block_direction_position += end - .adjoin(&fragment.collapsible_margins_in_children.start) + .adjoin(&fragment.block_margins_collapsed_with_children.start) .solve() } @@ -319,7 +319,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( } } let margin = computed_margin.auto_is(Length::zero); - let mut collapsible_margins_in_children = CollapsedBlockMargins::from_margin(&margin); + let mut block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin); let inline_size = inline_size.auto_is(|| cbis - pb.inline_sum() - margin.inline_sum()); let block_size = match box_size.block { LengthOrPercentageOrAuto::Length(l) => LengthOrAuto::Length(l), @@ -345,7 +345,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( this_start_margin_can_collapse_with_children, ); if this_start_margin_can_collapse_with_children.0 { - collapsible_margins_in_children + block_margins_collapsed_with_children .start .adjoin_assign(&flow_children.collapsible_margins_in_children.start); } @@ -356,7 +356,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( LengthOrAuto::Auto, ); if this_end_margin_can_collapse_with_children { - collapsible_margins_in_children + block_margins_collapsed_with_children .end .adjoin_assign(&flow_children.collapsible_margins_in_children.end); } else { @@ -392,6 +392,6 @@ fn layout_in_flow_non_replaced_block_level<'a>( padding, border, margin, - collapsible_margins_in_children, + block_margins_collapsed_with_children, } } diff --git a/victor/src/layout/fragments.rs b/victor/src/layout/fragments.rs index fbcd305..1d6034a 100644 --- a/victor/src/layout/fragments.rs +++ b/victor/src/layout/fragments.rs @@ -20,7 +20,7 @@ pub(crate) struct BoxFragment { pub border: Sides, pub margin: Sides, - pub collapsible_margins_in_children: CollapsedBlockMargins, + pub block_margins_collapsed_with_children: CollapsedBlockMargins, } pub(crate) struct CollapsedBlockMargins { diff --git a/victor/src/layout/positioned.rs b/victor/src/layout/positioned.rs index 06076b8..3702f0f 100644 --- a/victor/src/layout/positioned.rs +++ b/victor/src/layout/positioned.rs @@ -296,7 +296,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { padding, border, margin, - collapsible_margins_in_children: CollapsedBlockMargins::zero(), + block_margins_collapsed_with_children: CollapsedBlockMargins::zero(), }) } } From 242984c99f7c224ab638853a35795144a21b5ae3 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 12 Jun 2019 23:35:25 +0200 Subject: [PATCH 18/18] Refactor/rename OngoingCollapsedMargin into PlacementState --- victor/src/layout/flow/mod.rs | 70 +++++++++++++++++------------------ 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/victor/src/layout/flow/mod.rs b/victor/src/layout/flow/mod.rs index bf8c916..1f47fb0 100644 --- a/victor/src/layout/flow/mod.rs +++ b/victor/src/layout/flow/mod.rs @@ -102,60 +102,61 @@ fn layout_block_level_children<'a>( collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, child_boxes: &'a [BlockLevelBox], ) -> FlowChildren<'a> { - fn place_block_level_fragment( - fragment: &mut Fragment, - current_block_direction_position: &mut Length, - ongoing_collapsed_margin: &mut OngoingCollapsedMargin, - ) { + fn place_block_level_fragment(fragment: &mut Fragment, placement_state: &mut PlacementState) { match fragment { Fragment::Box(fragment) => { let fragment_block_size = fragment.padding.block_sum() + fragment.border.block_sum() + fragment.content_rect.size.block; - let end = std::mem::replace( - &mut ongoing_collapsed_margin.context.end, + let current_margin = std::mem::replace( + &mut placement_state.current_margin, fragment.block_margins_collapsed_with_children.end, ); - if ongoing_collapsed_margin - .collapsed_with_parent_start_margin + if placement_state + .next_in_flow_margin_collapses_with_parent_start_margin .take() { - assert_eq!(end.solve(), Length::zero()); - ongoing_collapsed_margin - .context - .start - .adjoin_assign(&fragment.block_margins_collapsed_with_children.start); + debug_assert_eq!(current_margin.solve(), Length::zero()); + debug_assert_eq!(placement_state.start_margin.solve(), Length::zero()); + placement_state.start_margin = + fragment.block_margins_collapsed_with_children.start; } else { - *current_block_direction_position += end + placement_state.current_block_direction_position += current_margin .adjoin(&fragment.block_margins_collapsed_with_children.start) .solve() } - fragment.content_rect.start_corner.block += *current_block_direction_position; - *current_block_direction_position += fragment_block_size; + fragment.content_rect.start_corner.block += + placement_state.current_block_direction_position; + placement_state.current_block_direction_position += fragment_block_size; } Fragment::Anonymous(fragment) => { // FIXME(nox): Margin collapsing for hypothetical boxes of // abspos elements is probably wrong. assert!(fragment.children.is_empty()); assert_eq!(fragment.rect.size.block, Length::zero()); - fragment.rect.start_corner.block += *current_block_direction_position; + fragment.rect.start_corner.block += + placement_state.current_block_direction_position; } _ => unreachable!(), } } - struct OngoingCollapsedMargin { - collapsed_with_parent_start_margin: bool, - context: CollapsedBlockMargins, + struct PlacementState { + next_in_flow_margin_collapses_with_parent_start_margin: bool, + start_margin: CollapsedMargin, + current_margin: CollapsedMargin, + current_block_direction_position: Length, } let mut absolutely_positioned_fragments = vec![]; - let mut current_block_direction_position = Length::zero(); - let mut ongoing_collapsed_margin = OngoingCollapsedMargin { - collapsed_with_parent_start_margin: collapsible_with_parent_start_margin.0, - context: CollapsedBlockMargins::zero(), + let mut placement_state = PlacementState { + next_in_flow_margin_collapses_with_parent_start_margin: + collapsible_with_parent_start_margin.0, + start_margin: CollapsedMargin::zero(), + current_margin: CollapsedMargin::zero(), + current_block_direction_position: Length::zero(), }; let mut fragments: Vec<_>; if let Some(float_context) = float_context { @@ -172,11 +173,7 @@ fn layout_block_level_children<'a>( tree_rank, &mut absolutely_positioned_fragments, ); - place_block_level_fragment( - &mut fragment, - &mut current_block_direction_position, - &mut ongoing_collapsed_margin, - ); + place_block_level_fragment(&mut fragment, &mut placement_state); fragment }) .collect() @@ -200,11 +197,7 @@ fn layout_block_level_children<'a>( ) .collect(); for fragment in &mut fragments { - place_block_level_fragment( - fragment, - &mut current_block_direction_position, - &mut ongoing_collapsed_margin, - ) + place_block_level_fragment(fragment, &mut placement_state) } } @@ -217,8 +210,11 @@ fn layout_block_level_children<'a>( FlowChildren { fragments, absolutely_positioned_fragments, - block_size: current_block_direction_position, - collapsible_margins_in_children: ongoing_collapsed_margin.context, + block_size: placement_state.current_block_direction_position, + collapsible_margins_in_children: CollapsedBlockMargins { + start: placement_state.start_margin, + end: placement_state.current_margin, + }, } }