Skip to content
Permalink
Browse files

Split FlowChildren in IndependentLayout and FlowLayout

The result of doing the layout of an independent formatting context
should be unconcerned with margin collapsing.
  • Loading branch information
nox authored and SimonSapin committed Nov 26, 2019
1 parent 24b7ead commit 858bc5aca681fae70ce640d70d5fa80f7edd3dc9
@@ -4,7 +4,7 @@

use crate::context::LayoutContext;
use crate::flow::float::FloatBox;
use crate::flow::FlowChildren;
use crate::flow::FlowLayout;
use crate::fragments::{
AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment, TextFragment,
};
@@ -88,7 +88,7 @@ impl InlineFormattingContext {
containing_block: &ContainingBlock,
tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
) -> FlowChildren {
) -> FlowLayout {
let mut ifc = InlineFormattingContextState {
containing_block,
partial_inline_boxes_stack: Vec::new(),
@@ -156,9 +156,9 @@ impl InlineFormattingContext {
} else {
ifc.line_boxes
.finish_line(&mut ifc.current_nesting_level, containing_block);
return FlowChildren {
return FlowLayout {
fragments: ifc.line_boxes.boxes,
block_size: ifc.line_boxes.next_line_block_position,
content_block_size: ifc.line_boxes.next_line_block_position,
collapsible_margins_in_children: CollapsedBlockMargins::zero(),
};
}
@@ -7,11 +7,11 @@
use crate::context::LayoutContext;
use crate::flow::float::{FloatBox, FloatContext};
use crate::flow::inline::InlineFormattingContext;
use crate::formatting_contexts::IndependentFormattingContext;
use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout};
use crate::fragments::{
AnonymousFragment, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment,
};
use crate::geom::flow_relative::{Rect, Vec2};
use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::positioned::{
adjust_static_positions, AbsolutelyPositionedBox, AbsolutelyPositionedFragment,
};
@@ -54,9 +54,9 @@ pub(crate) enum BlockLevelBox {
Independent(IndependentFormattingContext),
}

pub(super) struct FlowChildren {
struct FlowLayout {
pub fragments: Vec<Fragment>,
pub block_size: Length,
pub content_block_size: Length,
pub collapsible_margins_in_children: CollapsedBlockMargins,
}

@@ -70,28 +70,32 @@ impl BlockFormattingContext {
containing_block: &ContainingBlock,
tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
) -> FlowChildren {
) -> IndependentLayout {
let mut float_context;
let float_context = if self.contains_floats {
float_context = FloatContext::new();
Some(&mut float_context)
} else {
None
};
let mut flow_children = self.contents.layout(
let flow_layout = self.contents.layout(
layout_context,
containing_block,
tree_rank,
absolutely_positioned_fragments,
float_context,
CollapsibleWithParentStartMargin(false),
);
flow_children.block_size += flow_children.collapsible_margins_in_children.end.solve();
flow_children
.collapsible_margins_in_children
.collapsed_through = false;
flow_children.collapsible_margins_in_children.end = CollapsedMargin::zero();
flow_children
assert!(
!flow_layout
.collapsible_margins_in_children
.collapsed_through
);
IndependentLayout {
fragments: flow_layout.fragments,
content_block_size: flow_layout.content_block_size +
flow_layout.collapsible_margins_in_children.end.solve(),
}
}
}

@@ -104,7 +108,7 @@ impl BlockContainer {
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
float_context: Option<&mut FloatContext>,
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
) -> FlowChildren {
) -> FlowLayout {
match self {
BlockContainer::BlockLevelBoxes(child_boxes) => layout_block_level_children(
layout_context,
@@ -133,7 +137,7 @@ fn layout_block_level_children<'a>(
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
float_context: Option<&mut FloatContext>,
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
) -> FlowChildren {
) -> FlowLayout {
fn place_block_level_fragment(fragment: &mut Fragment, placement_state: &mut PlacementState) {
match fragment {
Fragment::Box(fragment) => {
@@ -249,9 +253,9 @@ fn layout_block_level_children<'a>(
tree_rank,
);

FlowChildren {
FlowLayout {
fragments,
block_size: placement_state.current_block_direction_position,
content_block_size: placement_state.current_block_direction_position,
collapsible_margins_in_children: CollapsedBlockMargins {
collapsed_through: placement_state
.next_in_flow_margin_collapses_with_parent_start_margin,
@@ -302,12 +306,17 @@ impl BlockLevelBox {
&contents.style,
BlockLevelKind::EstablishesAnIndependentFormattingContext,
|containing_block, nested_abspos, _| {
non_replaced.layout(
let independent_layout = non_replaced.layout(
layout_context,
containing_block,
tree_rank,
nested_abspos,
)
);
FlowLayout {
fragments: independent_layout.fragments,
content_block_size: independent_layout.content_block_size,
collapsible_margins_in_children: CollapsedBlockMargins::zero(),
}
},
)),
},
@@ -341,7 +350,7 @@ fn layout_in_flow_non_replaced_block_level<'a>(
&ContainingBlock,
&mut Vec<AbsolutelyPositionedFragment<'a>>,
CollapsibleWithParentStartMargin,
) -> FlowChildren,
) -> FlowLayout,
) -> BoxFragment {
let cbis = containing_block.inline_size;
let padding = style.padding().percentages_relative_to(cbis);
@@ -400,7 +409,7 @@ fn layout_in_flow_non_replaced_block_level<'a>(
LengthOrAuto::Auto,
);
let mut nested_abspos = vec![];
let mut flow_children = layout_contents(
let mut flow_layout = layout_contents(
&containing_block_for_children,
if style.get_box().position == Position::Relative {
&mut nested_abspos
@@ -412,34 +421,34 @@ fn layout_in_flow_non_replaced_block_level<'a>(
if this_start_margin_can_collapse_with_children.0 {
block_margins_collapsed_with_children
.start
.adjoin_assign(&flow_children.collapsible_margins_in_children.start);
if flow_children
.adjoin_assign(&flow_layout.collapsible_margins_in_children.start);
if flow_layout
.collapsible_margins_in_children
.collapsed_through
{
block_margins_collapsed_with_children
.start
.adjoin_assign(&std::mem::replace(
&mut flow_children.collapsible_margins_in_children.end,
&mut flow_layout.collapsible_margins_in_children.end,
CollapsedMargin::zero(),
));
}
}
if this_end_margin_can_collapse_with_children {
block_margins_collapsed_with_children
.end
.adjoin_assign(&flow_children.collapsible_margins_in_children.end);
.adjoin_assign(&flow_layout.collapsible_margins_in_children.end);
} else {
flow_children.block_size += flow_children.collapsible_margins_in_children.end.solve();
flow_layout.content_block_size += flow_layout.collapsible_margins_in_children.end.solve();
}
block_margins_collapsed_with_children.collapsed_through =
this_start_margin_can_collapse_with_children.0 &&
this_end_margin_can_collapse_with_children &&
flow_children
flow_layout
.collapsible_margins_in_children
.collapsed_through;
let relative_adjustement = relative_adjustement(style, inline_size, block_size);
let block_size = block_size.auto_is(|| flow_children.block_size);
let block_size = block_size.auto_is(|| flow_layout.content_block_size);
let content_rect = Rect {
start_corner: Vec2 {
block: pb.block_start + relative_adjustement.block,
@@ -454,15 +463,15 @@ fn layout_in_flow_non_replaced_block_level<'a>(
AbsolutelyPositionedFragment::in_positioned_containing_block(
layout_context,
&nested_abspos,
&mut flow_children.fragments,
&mut flow_layout.fragments,
&content_rect.size,
&padding,
containing_block_for_children.mode,
)
}
BoxFragment {
style: style.clone(),
children: flow_children.fragments,
children: flow_layout.fragments,
content_rect,
padding,
border,
@@ -31,10 +31,7 @@ pub struct BoxTreeRoot(BlockFormattingContext);
pub struct FragmentTreeRoot(Vec<Fragment>);

impl BoxTreeRoot {
pub fn construct<'dom, Node>(
context: &SharedStyleContext<'_>,
root_element: Node,
) -> Self
pub fn construct<'dom, Node>(context: &SharedStyleContext<'_>, root_element: Node) -> Self
where
Node: 'dom + Copy + LayoutNode + Send + Sync,
{
@@ -124,7 +121,7 @@ impl BoxTreeRoot {
};
let dummy_tree_rank = 0;
let mut absolutely_positioned_fragments = vec![];
let mut flow_children = self.0.layout(
let mut independent_layout = self.0.layout(
layout_context,
&initial_containing_block,
dummy_tree_rank,
@@ -135,12 +132,12 @@ impl BoxTreeRoot {
size: initial_containing_block_size,
mode: initial_containing_block.mode,
};
flow_children.fragments.par_extend(
independent_layout.fragments.par_extend(
absolutely_positioned_fragments
.par_iter()
.map(|a| a.layout(layout_context, &initial_containing_block)),
);
FragmentTreeRoot(flow_children.fragments)
FragmentTreeRoot(independent_layout.fragments)
}
}

@@ -4,7 +4,8 @@

use crate::context::LayoutContext;
use crate::dom_traversal::{Contents, NodeExt};
use crate::flow::{BlockFormattingContext, FlowChildren};
use crate::flow::BlockFormattingContext;
use crate::fragments::Fragment;
use crate::geom::flow_relative::Vec2;
use crate::positioned::AbsolutelyPositionedFragment;
use crate::replaced::ReplacedContent;
@@ -14,6 +15,7 @@ use servo_arc::Arc;
use std::convert::TryInto;
use style::context::SharedStyleContext;
use style::properties::ComputedValues;
use style::values::computed::Length;

/// https://drafts.csswg.org/css-display/#independent-formatting-context
#[derive(Debug)]
@@ -22,6 +24,11 @@ pub(crate) struct IndependentFormattingContext {
contents: IndependentFormattingContextContents,
}

pub(crate) struct IndependentLayout {
pub fragments: Vec<Fragment>,
pub content_block_size: Length,
}

// Private so that code outside of this module cannot match variants.
// It should got through methods instead.
#[derive(Debug)]
@@ -74,7 +81,7 @@ impl IndependentFormattingContext {
containing_block: &ContainingBlock,
tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
) -> FlowChildren {
) -> IndependentLayout {
match self.as_replaced() {
Ok(replaced) => match *replaced {},
Err(ifc) => ifc.layout(
@@ -94,7 +101,7 @@ impl<'a> NonReplacedIFC<'a> {
containing_block: &ContainingBlock,
tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
) -> FlowChildren {
) -> IndependentLayout {
match &self.0 {
NonReplacedIFCKind::Flow(bfc) => bfc.layout(
layout_context,
@@ -33,7 +33,7 @@ pub use flow::{BoxTreeRoot, FragmentTreeRoot};

use crate::context::LayoutContext;
use crate::dom_traversal::{Contents, NodeExt};
use crate::flow::{BlockFormattingContext, FlowChildren};
use crate::flow::BlockFormattingContext;
use crate::geom::flow_relative::Vec2;
use crate::positioned::AbsolutelyPositionedFragment;
use crate::replaced::ReplacedContent;
@@ -274,7 +274,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
);
let dummy_tree_rank = 0;
let mut absolutely_positioned_fragments = vec![];
let mut flow_children = self.absolutely_positioned_box.contents.layout(
let mut independent_layout = self.absolutely_positioned_box.contents.layout(
layout_context,
&containing_block_for_children,
dummy_tree_rank,
@@ -286,7 +286,7 @@ 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_size = block_size.auto_is(|| independent_layout.content_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,
@@ -306,15 +306,15 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
AbsolutelyPositionedFragment::in_positioned_containing_block(
layout_context,
&absolutely_positioned_fragments,
&mut flow_children.fragments,
&mut independent_layout.fragments,
&content_rect.size,
&padding,
containing_block_for_children.mode,
);

Fragment::Box(BoxFragment {
style: style.clone(),
children: flow_children.fragments,
children: independent_layout.fragments,
content_rect,
padding,
border,

0 comments on commit 858bc5a

Please sign in to comment.
You can’t perform that action at this time.