Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layout `position: fixed` in the initial containing block #25273

Merged
merged 13 commits into from Dec 13, 2019
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Give `PositioningContext` more responsibilities

Iits details are now private to the module.

It has a couple methods that take closures to make sure that "before" and "after" steps are done together:

* In an absolutely positioned box, take care of nested abspos (establish a new containing block, etc.)
* For a box that *might* be `position: relative`, optionally take care of the same.
  • Loading branch information
SimonSapin committed Dec 12, 2019
commit c44ee516a10fca4d4d715337cc5c61c10bca1a44
@@ -245,7 +245,6 @@ impl InlineFormattingContext {
},
};
ifc.positioning_context
.abspos
.push(box_.layout(initial_start_corner, tree_rank));
},
InlineLevelBox::OutOfFlowFloatBox(_box_) => {
@@ -18,7 +18,6 @@ use crate::{relative_adjustement, ContainingBlock};
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use rayon_croissant::ParallelIteratorExt;
use servo_arc::Arc;
use style::computed_values::position::T as Position;
use style::properties::ComputedValues;
use style::values::computed::{Length, LengthOrAuto};
use style::Zero;
@@ -235,8 +234,8 @@ fn layout_block_level_children<'a>(
/* float_context = */ None,
)
},
Default::default,
|left, right| left.append(right),
PositioningContext::new,
PositioningContext::append,
)
.collect();
for fragment in &mut fragments {
@@ -317,9 +316,7 @@ impl BlockLevelBox {
)),
},
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
positioning_context
.abspos
.push(box_.layout(Vec2::zero(), tree_rank));
positioning_context.push(box_.layout(Vec2::zero(), tree_rank));
Fragment::Anonymous(AnonymousFragment::no_op(
containing_block.style.writing_mode,
))
@@ -433,80 +430,70 @@ fn layout_in_flow_non_replaced_block_level<'a>(
min_box_size.block == Length::zero() &&
pb.block_end == Length::zero() &&
block_level_kind == BlockLevelKind::SameFormattingContextBlock;
let mut nested_positioning_context = PositioningContext { abspos: Vec::new() };
let mut flow_layout = layout_contents(
if style.get_box().position == Position::Relative {
&mut nested_positioning_context
} else {
positioning_context
},
&containing_block_for_children,
this_start_margin_can_collapse_with_children,
);
let mut block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
if this_start_margin_can_collapse_with_children.0 {
block_margins_collapsed_with_children
.start
.adjoin_assign(&flow_layout.collapsible_margins_in_children.start);
if flow_layout
.collapsible_margins_in_children
.collapsed_through
{

positioning_context.for_maybe_position_relative(layout_context, style, |positioning_context| {
This conversation was marked as resolved by nox

This comment has been minimized.

Copy link
@nox

nox Dec 13, 2019

Member

I understand the logic but I'm not sure I like how big this closure is and how it drifts everything even more to the right. Do you think it could be its own function, living in the module next to this one?

let mut flow_layout = layout_contents(
positioning_context,
&containing_block_for_children,
this_start_margin_can_collapse_with_children,
);
let mut block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
if this_start_margin_can_collapse_with_children.0 {
block_margins_collapsed_with_children
.start
.adjoin_assign(&std::mem::replace(
&mut flow_layout.collapsible_margins_in_children.end,
CollapsedMargin::zero(),
));
.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_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_layout.collapsible_margins_in_children.end);
} else {
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 &&
if this_end_margin_can_collapse_with_children {
block_margins_collapsed_with_children
.end
.adjoin_assign(&flow_layout.collapsible_margins_in_children.end);
} else {
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_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_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_layout
.content_block_size
.clamp_between_extremums(min_box_size.block, max_box_size.block)
});
let content_rect = Rect {
start_corner: Vec2 {
block: pb.block_start + relative_adjustement.block,
inline: pb.inline_start + relative_adjustement.inline + margin.inline_start,
},
size: Vec2 {
block: block_size,
inline: inline_size,
},
};
if style.get_box().position == Position::Relative {
nested_positioning_context.layout_abspos(
layout_context,
&mut flow_layout.fragments,
&content_rect.size,
&padding,
style,
)
}
BoxFragment {
style: style.clone(),
children: flow_layout.fragments,
content_rect,
padding,
border,
margin,
block_margins_collapsed_with_children,
}
.content_block_size
.clamp_between_extremums(min_box_size.block, max_box_size.block)
});
let content_rect = Rect {
start_corner: Vec2 {
block: pb.block_start + relative_adjustement.block,
inline: pb.inline_start + relative_adjustement.inline + margin.inline_start,
},
size: Vec2 {
block: block_size,
inline: inline_size,
},
};
BoxFragment {
style: style.clone(),
children: flow_layout.fragments,
content_rect,
padding,
border,
margin,
block_margins_collapsed_with_children,
}
})
}

/// https://drafts.csswg.org/css2/visudet.html#block-replaced-width
@@ -12,13 +12,12 @@ use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragments::Fragment;
use crate::geom;
use crate::geom::flow_relative::Vec2;
use crate::positioned::AbsolutelyPositionedBox;
use crate::positioned::PositioningContext;
use crate::positioned::{AbsolutelyPositionedBox, CollectedAbsolutelyPositionedBox};
use crate::replaced::ReplacedContent;
use crate::sizing::ContentSizesRequest;
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
use crate::DefiniteContainingBlock;
use rayon::iter::{IntoParallelRefIterator, ParallelExtend, ParallelIterator};
use script_layout_interface::wrapper_traits::LayoutNode;
use servo_arc::Arc;
use style::properties::ComputedValues;
@@ -111,26 +110,19 @@ impl BoxTreeRoot {
};

let dummy_tree_rank = 0;
let mut positioning_context = PositioningContext { abspos: Vec::new() };
let mut positioning_context = PositioningContext::new();
let mut independent_layout = self.0.layout(
layout_context,
&mut positioning_context,
&(&initial_containing_block).into(),
dummy_tree_rank,
);

let map = |a: &CollectedAbsolutelyPositionedBox| {
a.layout(layout_context, &initial_containing_block)
};
if layout_context.use_rayon {
independent_layout
.fragments
.par_extend(positioning_context.abspos.par_iter().map(map))
} else {
independent_layout
.fragments
.extend(positioning_context.abspos.iter().map(map))
}
positioning_context.layout_in_initial_containing_block(
layout_context,
&initial_containing_block,
&mut independent_layout.fragments,
);

FragmentTreeRoot(independent_layout.fragments)
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.