mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Introduce PositioningContext
This commit is contained in:
parent
06e3d13795
commit
b43a3de51d
5 changed files with 90 additions and 69 deletions
|
@ -9,7 +9,7 @@ use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::fragments::CollapsedBlockMargins;
|
use crate::fragments::CollapsedBlockMargins;
|
||||||
use crate::fragments::{AnonymousFragment, BoxFragment, Fragment, TextFragment};
|
use crate::fragments::{AnonymousFragment, BoxFragment, Fragment, TextFragment};
|
||||||
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment};
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
||||||
use crate::sizing::ContentSizes;
|
use crate::sizing::ContentSizes;
|
||||||
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside};
|
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside};
|
||||||
use crate::{relative_adjustement, ContainingBlock};
|
use crate::{relative_adjustement, ContainingBlock};
|
||||||
|
@ -68,9 +68,9 @@ struct PartialInlineBoxFragment<'box_tree> {
|
||||||
parent_nesting_level: InlineNestingLevelState<'box_tree>,
|
parent_nesting_level: InlineNestingLevelState<'box_tree>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InlineFormattingContextState<'box_tree, 'a> {
|
struct InlineFormattingContextState<'box_tree, 'a, 'b> {
|
||||||
absolutely_positioned_fragments: &'a mut Vec<AbsolutelyPositionedFragment<'box_tree>>,
|
positioning_context: &'a mut PositioningContext<'box_tree>,
|
||||||
containing_block: &'a ContainingBlock<'a>,
|
containing_block: &'b ContainingBlock<'b>,
|
||||||
lines: Lines,
|
lines: Lines,
|
||||||
inline_position: Length,
|
inline_position: Length,
|
||||||
partial_inline_boxes_stack: Vec<PartialInlineBoxFragment<'box_tree>>,
|
partial_inline_boxes_stack: Vec<PartialInlineBoxFragment<'box_tree>>,
|
||||||
|
@ -195,12 +195,12 @@ impl InlineFormattingContext {
|
||||||
pub(super) fn layout<'a>(
|
pub(super) fn layout<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
positioning_context: &mut PositioningContext<'a>,
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
tree_rank: usize,
|
tree_rank: usize,
|
||||||
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
|
|
||||||
) -> FlowLayout {
|
) -> FlowLayout {
|
||||||
let mut ifc = InlineFormattingContextState {
|
let mut ifc = InlineFormattingContextState {
|
||||||
absolutely_positioned_fragments,
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
partial_inline_boxes_stack: Vec::new(),
|
partial_inline_boxes_stack: Vec::new(),
|
||||||
lines: Lines {
|
lines: Lines {
|
||||||
|
@ -244,7 +244,8 @@ impl InlineFormattingContext {
|
||||||
panic!("display:none does not generate an abspos box")
|
panic!("display:none does not generate an abspos box")
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
ifc.absolutely_positioned_fragments
|
ifc.positioning_context
|
||||||
|
.abspos
|
||||||
.push(box_.layout(initial_start_corner, tree_rank));
|
.push(box_.layout(initial_start_corner, tree_rank));
|
||||||
},
|
},
|
||||||
InlineLevelBox::OutOfFlowFloatBox(_box_) => {
|
InlineLevelBox::OutOfFlowFloatBox(_box_) => {
|
||||||
|
@ -346,7 +347,7 @@ impl Lines {
|
||||||
impl InlineBox {
|
impl InlineBox {
|
||||||
fn start_layout<'box_tree>(
|
fn start_layout<'box_tree>(
|
||||||
&'box_tree self,
|
&'box_tree self,
|
||||||
ifc: &mut InlineFormattingContextState<'box_tree, '_>,
|
ifc: &mut InlineFormattingContextState<'box_tree, '_, '_>,
|
||||||
) -> PartialInlineBoxFragment<'box_tree> {
|
) -> PartialInlineBoxFragment<'box_tree> {
|
||||||
let style = self.style.clone();
|
let style = self.style.clone();
|
||||||
let cbis = ifc.containing_block.inline_size;
|
let cbis = ifc.containing_block.inline_size;
|
||||||
|
@ -440,7 +441,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> {
|
||||||
|
|
||||||
fn layout_atomic<'box_tree>(
|
fn layout_atomic<'box_tree>(
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
ifc: &mut InlineFormattingContextState<'box_tree, '_>,
|
ifc: &mut InlineFormattingContextState<'box_tree, '_, '_>,
|
||||||
atomic: &'box_tree IndependentFormattingContext,
|
atomic: &'box_tree IndependentFormattingContext,
|
||||||
) {
|
) {
|
||||||
let cbis = ifc.containing_block.inline_size;
|
let cbis = ifc.containing_block.inline_size;
|
||||||
|
@ -521,9 +522,9 @@ fn layout_atomic<'box_tree>(
|
||||||
// FIXME: Do we need to call `adjust_static_positions` somewhere near here?
|
// FIXME: Do we need to call `adjust_static_positions` somewhere near here?
|
||||||
let independent_layout = non_replaced.layout(
|
let independent_layout = non_replaced.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
ifc.positioning_context,
|
||||||
&containing_block_for_children,
|
&containing_block_for_children,
|
||||||
dummy_tree_rank,
|
dummy_tree_rank,
|
||||||
ifc.absolutely_positioned_fragments,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
|
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::fragments::{AnonymousFragment, BoxFragment, Fragment};
|
||||||
use crate::fragments::{CollapsedBlockMargins, CollapsedMargin};
|
use crate::fragments::{CollapsedBlockMargins, CollapsedMargin};
|
||||||
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
||||||
use crate::positioned::adjust_static_positions;
|
use crate::positioned::adjust_static_positions;
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment};
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::style_ext::ComputedValuesExt;
|
use crate::style_ext::ComputedValuesExt;
|
||||||
use crate::{relative_adjustement, ContainingBlock};
|
use crate::{relative_adjustement, ContainingBlock};
|
||||||
|
@ -67,9 +67,9 @@ impl BlockFormattingContext {
|
||||||
pub(super) fn layout<'a>(
|
pub(super) fn layout<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
positioning_context: &mut PositioningContext<'a>,
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
tree_rank: usize,
|
tree_rank: usize,
|
||||||
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
|
|
||||||
) -> IndependentLayout {
|
) -> IndependentLayout {
|
||||||
let mut float_context;
|
let mut float_context;
|
||||||
let float_context = if self.contains_floats {
|
let float_context = if self.contains_floats {
|
||||||
|
@ -80,9 +80,9 @@ impl BlockFormattingContext {
|
||||||
};
|
};
|
||||||
let flow_layout = self.contents.layout(
|
let flow_layout = self.contents.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
absolutely_positioned_fragments,
|
|
||||||
float_context,
|
float_context,
|
||||||
CollapsibleWithParentStartMargin(false),
|
CollapsibleWithParentStartMargin(false),
|
||||||
);
|
);
|
||||||
|
@ -103,27 +103,27 @@ impl BlockContainer {
|
||||||
fn layout<'a>(
|
fn layout<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
positioning_context: &mut PositioningContext<'a>,
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
tree_rank: usize,
|
tree_rank: usize,
|
||||||
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
|
|
||||||
float_context: Option<&mut FloatContext>,
|
float_context: Option<&mut FloatContext>,
|
||||||
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
|
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
|
||||||
) -> FlowLayout {
|
) -> FlowLayout {
|
||||||
match self {
|
match self {
|
||||||
BlockContainer::BlockLevelBoxes(child_boxes) => layout_block_level_children(
|
BlockContainer::BlockLevelBoxes(child_boxes) => layout_block_level_children(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
child_boxes,
|
child_boxes,
|
||||||
containing_block,
|
containing_block,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
absolutely_positioned_fragments,
|
|
||||||
float_context,
|
float_context,
|
||||||
collapsible_with_parent_start_margin,
|
collapsible_with_parent_start_margin,
|
||||||
),
|
),
|
||||||
BlockContainer::InlineFormattingContext(ifc) => ifc.layout(
|
BlockContainer::InlineFormattingContext(ifc) => ifc.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
absolutely_positioned_fragments,
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,10 +131,10 @@ impl BlockContainer {
|
||||||
|
|
||||||
fn layout_block_level_children<'a>(
|
fn layout_block_level_children<'a>(
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
positioning_context: &mut PositioningContext<'a>,
|
||||||
child_boxes: &'a [Arc<BlockLevelBox>],
|
child_boxes: &'a [Arc<BlockLevelBox>],
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
tree_rank: usize,
|
tree_rank: usize,
|
||||||
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
|
|
||||||
mut float_context: Option<&mut FloatContext>,
|
mut float_context: Option<&mut FloatContext>,
|
||||||
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
|
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
|
||||||
) -> FlowLayout {
|
) -> FlowLayout {
|
||||||
|
@ -194,7 +194,7 @@ fn layout_block_level_children<'a>(
|
||||||
current_block_direction_position: Length,
|
current_block_direction_position: Length,
|
||||||
}
|
}
|
||||||
|
|
||||||
let abspos_so_far = absolutely_positioned_fragments.len();
|
let abspos_so_far = positioning_context.abspos.len();
|
||||||
let mut placement_state = PlacementState {
|
let mut placement_state = PlacementState {
|
||||||
next_in_flow_margin_collapses_with_parent_start_margin:
|
next_in_flow_margin_collapses_with_parent_start_margin:
|
||||||
collapsible_with_parent_start_margin.0,
|
collapsible_with_parent_start_margin.0,
|
||||||
|
@ -213,9 +213,9 @@ fn layout_block_level_children<'a>(
|
||||||
.map(|(tree_rank, box_)| {
|
.map(|(tree_rank, box_)| {
|
||||||
let mut fragment = box_.layout(
|
let mut fragment = box_.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
absolutely_positioned_fragments,
|
|
||||||
float_context.as_mut().map(|c| &mut **c),
|
float_context.as_mut().map(|c| &mut **c),
|
||||||
);
|
);
|
||||||
place_block_level_fragment(&mut fragment, &mut placement_state);
|
place_block_level_fragment(&mut fragment, &mut placement_state);
|
||||||
|
@ -227,19 +227,17 @@ fn layout_block_level_children<'a>(
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.mapfold_reduce_into(
|
.mapfold_reduce_into(
|
||||||
absolutely_positioned_fragments,
|
positioning_context,
|
||||||
|abspos_fragments, (tree_rank, box_)| {
|
|positioning_context, (tree_rank, box_)| {
|
||||||
box_.layout(
|
box_.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
abspos_fragments,
|
|
||||||
/* float_context = */ None,
|
/* float_context = */ None,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|left_abspos_fragments, mut right_abspos_fragments| {
|
|left, right| left.append(right),
|
||||||
left_abspos_fragments.append(&mut right_abspos_fragments);
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.collect();
|
.collect();
|
||||||
for fragment in &mut fragments {
|
for fragment in &mut fragments {
|
||||||
|
@ -248,7 +246,7 @@ fn layout_block_level_children<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
adjust_static_positions(
|
adjust_static_positions(
|
||||||
&mut absolutely_positioned_fragments[abspos_so_far..],
|
&mut positioning_context.abspos[abspos_so_far..],
|
||||||
&mut fragments,
|
&mut fragments,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
);
|
);
|
||||||
|
@ -269,25 +267,27 @@ impl BlockLevelBox {
|
||||||
fn layout<'a>(
|
fn layout<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
positioning_context: &mut PositioningContext<'a>,
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
tree_rank: usize,
|
tree_rank: usize,
|
||||||
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
|
|
||||||
float_context: Option<&mut FloatContext>,
|
float_context: Option<&mut FloatContext>,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
match self {
|
match self {
|
||||||
BlockLevelBox::SameFormattingContextBlock { style, contents } => {
|
BlockLevelBox::SameFormattingContextBlock { style, contents } => {
|
||||||
Fragment::Box(layout_in_flow_non_replaced_block_level(
|
Fragment::Box(layout_in_flow_non_replaced_block_level(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
absolutely_positioned_fragments,
|
|
||||||
style,
|
style,
|
||||||
BlockLevelKind::SameFormattingContextBlock,
|
BlockLevelKind::SameFormattingContextBlock,
|
||||||
|containing_block, nested_abspos, collapsible_with_parent_start_margin| {
|
|positioning_context,
|
||||||
|
containing_block,
|
||||||
|
collapsible_with_parent_start_margin| {
|
||||||
contents.layout(
|
contents.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
nested_abspos,
|
|
||||||
float_context,
|
float_context,
|
||||||
collapsible_with_parent_start_margin,
|
collapsible_with_parent_start_margin,
|
||||||
)
|
)
|
||||||
|
@ -302,16 +302,16 @@ impl BlockLevelBox {
|
||||||
)),
|
)),
|
||||||
Err(non_replaced) => Fragment::Box(layout_in_flow_non_replaced_block_level(
|
Err(non_replaced) => Fragment::Box(layout_in_flow_non_replaced_block_level(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
absolutely_positioned_fragments,
|
|
||||||
&contents.style,
|
&contents.style,
|
||||||
BlockLevelKind::EstablishesAnIndependentFormattingContext,
|
BlockLevelKind::EstablishesAnIndependentFormattingContext,
|
||||||
|containing_block, nested_abspos, _| {
|
|positioning_context, containing_block, _| {
|
||||||
let independent_layout = non_replaced.layout(
|
let independent_layout = non_replaced.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
nested_abspos,
|
|
||||||
);
|
);
|
||||||
FlowLayout {
|
FlowLayout {
|
||||||
fragments: independent_layout.fragments,
|
fragments: independent_layout.fragments,
|
||||||
|
@ -322,7 +322,9 @@ impl BlockLevelBox {
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
|
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
|
||||||
absolutely_positioned_fragments.push(box_.layout(Vec2::zero(), tree_rank));
|
positioning_context
|
||||||
|
.abspos
|
||||||
|
.push(box_.layout(Vec2::zero(), tree_rank));
|
||||||
Fragment::Anonymous(AnonymousFragment::no_op(
|
Fragment::Anonymous(AnonymousFragment::no_op(
|
||||||
containing_block.style.writing_mode,
|
containing_block.style.writing_mode,
|
||||||
))
|
))
|
||||||
|
@ -347,13 +349,13 @@ enum BlockLevelKind {
|
||||||
/// https://drafts.csswg.org/css2/visudet.html#normal-block
|
/// https://drafts.csswg.org/css2/visudet.html#normal-block
|
||||||
fn layout_in_flow_non_replaced_block_level<'a>(
|
fn layout_in_flow_non_replaced_block_level<'a>(
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
positioning_context: &mut PositioningContext<'a>,
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
|
|
||||||
style: &Arc<ComputedValues>,
|
style: &Arc<ComputedValues>,
|
||||||
block_level_kind: BlockLevelKind,
|
block_level_kind: BlockLevelKind,
|
||||||
layout_contents: impl FnOnce(
|
layout_contents: impl FnOnce(
|
||||||
|
&mut PositioningContext<'a>,
|
||||||
&ContainingBlock,
|
&ContainingBlock,
|
||||||
&mut Vec<AbsolutelyPositionedFragment<'a>>,
|
|
||||||
CollapsibleWithParentStartMargin,
|
CollapsibleWithParentStartMargin,
|
||||||
) -> FlowLayout,
|
) -> FlowLayout,
|
||||||
) -> BoxFragment {
|
) -> BoxFragment {
|
||||||
|
@ -436,14 +438,14 @@ fn layout_in_flow_non_replaced_block_level<'a>(
|
||||||
min_box_size.block == Length::zero() &&
|
min_box_size.block == Length::zero() &&
|
||||||
pb.block_end == Length::zero() &&
|
pb.block_end == Length::zero() &&
|
||||||
block_level_kind == BlockLevelKind::SameFormattingContextBlock;
|
block_level_kind == BlockLevelKind::SameFormattingContextBlock;
|
||||||
let mut nested_abspos = vec![];
|
let mut nested_positioning_context = PositioningContext { abspos: Vec::new() };
|
||||||
let mut flow_layout = layout_contents(
|
let mut flow_layout = layout_contents(
|
||||||
&containing_block_for_children,
|
|
||||||
if style.get_box().position == Position::Relative {
|
if style.get_box().position == Position::Relative {
|
||||||
&mut nested_abspos
|
&mut nested_positioning_context
|
||||||
} else {
|
} else {
|
||||||
absolutely_positioned_fragments
|
positioning_context
|
||||||
},
|
},
|
||||||
|
&containing_block_for_children,
|
||||||
this_start_margin_can_collapse_with_children,
|
this_start_margin_can_collapse_with_children,
|
||||||
);
|
);
|
||||||
let mut block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
|
let mut block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
|
||||||
|
@ -493,9 +495,8 @@ fn layout_in_flow_non_replaced_block_level<'a>(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if style.get_box().position == Position::Relative {
|
if style.get_box().position == Position::Relative {
|
||||||
AbsolutelyPositionedFragment::in_positioned_containing_block(
|
nested_positioning_context.layout_abspos(
|
||||||
layout_context,
|
layout_context,
|
||||||
&nested_abspos,
|
|
||||||
&mut flow_layout.fragments,
|
&mut flow_layout.fragments,
|
||||||
&content_rect.size,
|
&content_rect.size,
|
||||||
&padding,
|
&padding,
|
||||||
|
|
|
@ -12,7 +12,8 @@ use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::fragments::Fragment;
|
use crate::fragments::Fragment;
|
||||||
use crate::geom;
|
use crate::geom;
|
||||||
use crate::geom::flow_relative::Vec2;
|
use crate::geom::flow_relative::Vec2;
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment};
|
use crate::positioned::PositioningContext;
|
||||||
|
use crate::positioned::{AbsolutelyPositionedBox, CollectedAbsolutelyPositionedBox};
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::sizing::ContentSizesRequest;
|
use crate::sizing::ContentSizesRequest;
|
||||||
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
|
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
|
||||||
|
@ -110,24 +111,25 @@ impl BoxTreeRoot {
|
||||||
};
|
};
|
||||||
|
|
||||||
let dummy_tree_rank = 0;
|
let dummy_tree_rank = 0;
|
||||||
let mut absolutely_positioned_fragments = vec![];
|
let mut positioning_context = PositioningContext { abspos: Vec::new() };
|
||||||
let mut independent_layout = self.0.layout(
|
let mut independent_layout = self.0.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
&mut positioning_context,
|
||||||
&(&initial_containing_block).into(),
|
&(&initial_containing_block).into(),
|
||||||
dummy_tree_rank,
|
dummy_tree_rank,
|
||||||
&mut absolutely_positioned_fragments,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let map =
|
let map = |a: &CollectedAbsolutelyPositionedBox| {
|
||||||
|a: &AbsolutelyPositionedFragment| a.layout(layout_context, &initial_containing_block);
|
a.layout(layout_context, &initial_containing_block)
|
||||||
|
};
|
||||||
if layout_context.use_rayon {
|
if layout_context.use_rayon {
|
||||||
independent_layout
|
independent_layout
|
||||||
.fragments
|
.fragments
|
||||||
.par_extend(absolutely_positioned_fragments.par_iter().map(map))
|
.par_extend(positioning_context.abspos.par_iter().map(map))
|
||||||
} else {
|
} else {
|
||||||
independent_layout
|
independent_layout
|
||||||
.fragments
|
.fragments
|
||||||
.extend(absolutely_positioned_fragments.iter().map(map))
|
.extend(positioning_context.abspos.iter().map(map))
|
||||||
}
|
}
|
||||||
|
|
||||||
FragmentTreeRoot(independent_layout.fragments)
|
FragmentTreeRoot(independent_layout.fragments)
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::{Contents, NodeExt};
|
use crate::dom_traversal::{Contents, NodeExt};
|
||||||
use crate::flow::BlockFormattingContext;
|
use crate::flow::BlockFormattingContext;
|
||||||
use crate::fragments::Fragment;
|
use crate::fragments::Fragment;
|
||||||
use crate::positioned::AbsolutelyPositionedFragment;
|
use crate::positioned::PositioningContext;
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::sizing::{BoxContentSizes, ContentSizesRequest};
|
use crate::sizing::{BoxContentSizes, ContentSizesRequest};
|
||||||
use crate::style_ext::DisplayInside;
|
use crate::style_ext::DisplayInside;
|
||||||
|
@ -101,16 +101,16 @@ impl<'a> NonReplacedIFC<'a> {
|
||||||
pub fn layout(
|
pub fn layout(
|
||||||
&self,
|
&self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
positioning_context: &mut PositioningContext<'a>,
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
tree_rank: usize,
|
tree_rank: usize,
|
||||||
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
|
|
||||||
) -> IndependentLayout {
|
) -> IndependentLayout {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
NonReplacedIFCKind::Flow(bfc) => bfc.layout(
|
NonReplacedIFCKind::Flow(bfc) => bfc.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
absolutely_positioned_fragments,
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,15 @@ pub(crate) struct AbsolutelyPositionedBox {
|
||||||
pub contents: IndependentFormattingContext,
|
pub contents: IndependentFormattingContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub(crate) struct PositioningContext<'box_tree> {
|
||||||
|
/// With `position: absolute`
|
||||||
|
pub abspos: Vec<CollectedAbsolutelyPositionedBox<'box_tree>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct AbsolutelyPositionedFragment<'box_> {
|
pub(crate) struct CollectedAbsolutelyPositionedBox<'box_tree> {
|
||||||
absolutely_positioned_box: &'box_ AbsolutelyPositionedBox,
|
absolutely_positioned_box: &'box_tree AbsolutelyPositionedBox,
|
||||||
|
|
||||||
/// The rank of the child from which this absolutely positioned fragment
|
/// The rank of the child from which this absolutely positioned fragment
|
||||||
/// came from, when doing the layout of a block container. Used to compute
|
/// came from, when doing the layout of a block container. Used to compute
|
||||||
|
@ -81,7 +87,7 @@ impl AbsolutelyPositionedBox {
|
||||||
&'a self,
|
&'a self,
|
||||||
initial_start_corner: Vec2<Length>,
|
initial_start_corner: Vec2<Length>,
|
||||||
tree_rank: usize,
|
tree_rank: usize,
|
||||||
) -> AbsolutelyPositionedFragment {
|
) -> CollectedAbsolutelyPositionedBox {
|
||||||
fn absolute_box_offsets(
|
fn absolute_box_offsets(
|
||||||
initial_static_start: Length,
|
initial_static_start: Length,
|
||||||
start: LengthPercentageOrAuto,
|
start: LengthPercentageOrAuto,
|
||||||
|
@ -98,7 +104,7 @@ impl AbsolutelyPositionedBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
let box_offsets = self.contents.style.box_offsets();
|
let box_offsets = self.contents.style.box_offsets();
|
||||||
AbsolutelyPositionedFragment {
|
CollectedAbsolutelyPositionedBox {
|
||||||
absolutely_positioned_box: self,
|
absolutely_positioned_box: self,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
box_offsets: Vec2 {
|
box_offsets: Vec2 {
|
||||||
|
@ -117,16 +123,25 @@ impl AbsolutelyPositionedBox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AbsolutelyPositionedFragment<'a> {
|
impl PositioningContext<'_> {
|
||||||
pub(crate) fn in_positioned_containing_block(
|
/// Unlike `Vec::append`, this takes ownership of the other value.
|
||||||
|
pub(crate) fn append(&mut self, mut other: Self) {
|
||||||
|
if self.abspos.is_empty() {
|
||||||
|
self.abspos = other.abspos
|
||||||
|
} else {
|
||||||
|
self.abspos.append(&mut other.abspos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn layout_abspos(
|
||||||
|
self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
absolute: &[Self],
|
|
||||||
fragments: &mut Vec<Fragment>,
|
fragments: &mut Vec<Fragment>,
|
||||||
content_rect_size: &Vec2<Length>,
|
content_rect_size: &Vec2<Length>,
|
||||||
padding: &Sides<Length>,
|
padding: &Sides<Length>,
|
||||||
style: &ComputedValues,
|
style: &ComputedValues,
|
||||||
) {
|
) {
|
||||||
if absolute.is_empty() {
|
if self.abspos.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let padding_rect = Rect {
|
let padding_rect = Rect {
|
||||||
|
@ -139,11 +154,12 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
|
||||||
size: padding_rect.size.clone(),
|
size: padding_rect.size.clone(),
|
||||||
style,
|
style,
|
||||||
};
|
};
|
||||||
let map = |a: &AbsolutelyPositionedFragment| a.layout(layout_context, &containing_block);
|
let map =
|
||||||
|
|a: &CollectedAbsolutelyPositionedBox| a.layout(layout_context, &containing_block);
|
||||||
let children = if layout_context.use_rayon {
|
let children = if layout_context.use_rayon {
|
||||||
absolute.par_iter().map(map).collect()
|
self.abspos.par_iter().map(map).collect()
|
||||||
} else {
|
} else {
|
||||||
absolute.iter().map(map).collect()
|
self.abspos.iter().map(map).collect()
|
||||||
};
|
};
|
||||||
fragments.push(Fragment::Anonymous(AnonymousFragment {
|
fragments.push(Fragment::Anonymous(AnonymousFragment {
|
||||||
children,
|
children,
|
||||||
|
@ -151,7 +167,9 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
|
||||||
mode: style.writing_mode,
|
mode: style.writing_mode,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CollectedAbsolutelyPositionedBox<'_> {
|
||||||
pub(crate) fn layout(
|
pub(crate) fn layout(
|
||||||
&self,
|
&self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
@ -216,7 +234,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
|
||||||
block_end: block_axis.margin_end,
|
block_end: block_axis.margin_end,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut absolutely_positioned_fragments = Vec::new();
|
let mut positioning_context = PositioningContext { abspos: Vec::new() };
|
||||||
let (size, mut fragments) = match self.absolutely_positioned_box.contents.as_replaced() {
|
let (size, mut fragments) = match self.absolutely_positioned_box.contents.as_replaced() {
|
||||||
Ok(replaced) => {
|
Ok(replaced) => {
|
||||||
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
|
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
|
||||||
|
@ -256,9 +274,9 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
|
||||||
let dummy_tree_rank = 0;
|
let dummy_tree_rank = 0;
|
||||||
let independent_layout = non_replaced.layout(
|
let independent_layout = non_replaced.layout(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
&mut positioning_context,
|
||||||
&containing_block_for_children,
|
&containing_block_for_children,
|
||||||
dummy_tree_rank,
|
dummy_tree_rank,
|
||||||
&mut absolutely_positioned_fragments,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let size = Vec2 {
|
let size = Vec2 {
|
||||||
|
@ -288,9 +306,8 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
|
||||||
size,
|
size,
|
||||||
};
|
};
|
||||||
|
|
||||||
AbsolutelyPositionedFragment::in_positioned_containing_block(
|
positioning_context.layout_abspos(
|
||||||
layout_context,
|
layout_context,
|
||||||
&absolutely_positioned_fragments,
|
|
||||||
&mut fragments,
|
&mut fragments,
|
||||||
&content_rect.size,
|
&content_rect.size,
|
||||||
&padding,
|
&padding,
|
||||||
|
@ -414,8 +431,8 @@ fn solve_axis(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn adjust_static_positions(
|
pub(crate) fn adjust_static_positions(
|
||||||
absolutely_positioned_fragments: &mut [AbsolutelyPositionedFragment],
|
absolutely_positioned_fragments: &mut [CollectedAbsolutelyPositionedBox],
|
||||||
child_fragments: &mut [Fragment],
|
child_fragments: &[Fragment],
|
||||||
tree_rank_in_parent: usize,
|
tree_rank_in_parent: usize,
|
||||||
) {
|
) {
|
||||||
for abspos_fragment in absolutely_positioned_fragments {
|
for abspos_fragment in absolutely_positioned_fragments {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue