mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Split FlowChildren in IndependentLayout and FlowLayout
The result of doing the layout of an independent formatting context should be unconcerned with margin collapsing.
This commit is contained in:
parent
24b7eadfff
commit
858bc5aca6
6 changed files with 61 additions and 48 deletions
|
@ -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,7 +70,7 @@ 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();
|
||||
|
@ -78,7 +78,7 @@ impl BlockFormattingContext {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let mut flow_children = self.contents.layout(
|
||||
let flow_layout = self.contents.layout(
|
||||
layout_context,
|
||||
containing_block,
|
||||
tree_rank,
|
||||
|
@ -86,12 +86,16 @@ impl BlockFormattingContext {
|
|||
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,15 +421,15 @@ 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(),
|
||||
));
|
||||
}
|
||||
|
@ -428,18 +437,18 @@ fn layout_in_flow_non_replaced_block_level<'a>(
|
|||
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,7 +463,7 @@ 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,
|
||||
|
@ -462,7 +471,7 @@ fn layout_in_flow_non_replaced_block_level<'a>(
|
|||
}
|
||||
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,7 +306,7 @@ 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,
|
||||
|
@ -314,7 +314,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
|
|||
|
||||
Fragment::Box(BoxFragment {
|
||||
style: style.clone(),
|
||||
children: flow_children.fragments,
|
||||
children: independent_layout.fragments,
|
||||
content_rect,
|
||||
padding,
|
||||
border,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue