Compare commits

...

1 Commits

Author SHA1 Message Date
Anthony Ramine
be64f47642 Mutably borrow to do layout of independent formatting contexts
We want to compute content sizes on demand rather than eagerly so we will
need to mutate the independent formatting contexts that own the content sizes.
2020-06-09 15:10:26 +02:00
7 changed files with 70 additions and 58 deletions

View File

@@ -15,7 +15,6 @@ use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest};
use crate::style_ext::DisplayGeneratingBox;
use crate::ContainingBlock;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use servo_arc::Arc;
use std::borrow::Cow;
use style::values::computed::Length;
use style::values::specified::text::TextDecorationLine;
@@ -31,7 +30,7 @@ pub(crate) struct FlexContainer {
#[derive(Debug, Serialize)]
pub(crate) enum FlexLevelBox {
FlexItem(IndependentFormattingContext),
OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>),
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
}
impl FlexContainer {
@@ -192,14 +191,14 @@ where
};
let box_ = if info.style.get_box().position.is_absolutely_positioned() {
// https://drafts.csswg.org/css-flexbox/#abspos-items
ArcRefCell::new(FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct(
ArcRefCell::new(FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(
ArcRefCell::new(AbsolutelyPositionedBox::construct(
self.context,
&info,
display_inside,
contents,
),
)))
)),
))
} else {
ArcRefCell::new(FlexLevelBox::FlexItem(
IndependentFormattingContext::construct(

View File

@@ -571,9 +571,14 @@ where
kind,
});
} else {
let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct(self.context, info, display_inside, contents),
)));
let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(
ArcRefCell::new(AbsolutelyPositionedBox::construct(
self.context,
info,
display_inside,
contents,
)),
));
self.current_inline_level_boxes().push(box_.clone());
box_slot.set(LayoutBox::InlineLevel(box_))
}
@@ -722,10 +727,11 @@ where
display_inside,
contents,
} => {
let block_level_box =
ArcRefCell::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
let block_level_box = ArcRefCell::new(
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, info, display_inside, contents),
)));
)),
);
(block_level_box, ContainsFloats::No)
},
BlockLevelCreator::OutOfFlowFloatBox {

View File

@@ -20,6 +20,7 @@ use crate::sizing::ContentSizes;
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside};
use crate::ContainingBlock;
use app_units::Au;
use atomic_refcell::AtomicRef;
use gfx::text::text_run::GlyphRun;
use servo_arc::Arc;
use style::properties::ComputedValues;
@@ -39,7 +40,7 @@ pub(crate) struct InlineFormattingContext {
pub(crate) enum InlineLevelBox {
InlineBox(InlineBox),
TextRun(TextRun),
OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>),
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
OutOfFlowFloatBox(FloatBox),
Atomic(IndependentFormattingContext),
}
@@ -275,7 +276,7 @@ impl InlineFormattingContext {
loop {
if let Some(child) = ifc.current_nesting_level.remaining_boxes.next() {
match &*child.borrow() {
match &mut *child.borrow_mut() {
InlineLevelBox::InlineBox(inline) => {
let partial = inline.start_layout(child.clone(), &mut ifc);
ifc.partial_inline_boxes_stack.push(partial)
@@ -283,8 +284,9 @@ impl InlineFormattingContext {
InlineLevelBox::TextRun(run) => run.layout(layout_context, &mut ifc),
InlineLevelBox::Atomic(a) => layout_atomic(layout_context, &mut ifc, a),
InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
let style = AtomicRef::map(box_.borrow(), |box_| &box_.contents.style);
let initial_start_corner =
match Display::from(box_.contents.style.get_box().original_display) {
match Display::from(style.get_box().original_display) {
Display::GeneratingBox(DisplayGeneratingBox::OutsideInside {
outside,
inside: _,
@@ -313,7 +315,7 @@ impl InlineFormattingContext {
Fragment::AbsoluteOrFixedPositioned(
AbsoluteOrFixedPositionedFragment {
hoisted_fragment,
position: box_.contents.style.clone_position(),
position: style.clone_position(),
},
),
);
@@ -529,7 +531,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> {
fn layout_atomic(
layout_context: &LayoutContext,
ifc: &mut InlineFormattingContextState,
atomic: &IndependentFormattingContext,
atomic: &mut IndependentFormattingContext,
) {
let pbm = atomic.style.padding_border_margin(&ifc.containing_block);
let margin = pbm.margin.auto_is(Length::zero);

View File

@@ -52,7 +52,7 @@ pub(crate) enum BlockLevelBox {
style: Arc<ComputedValues>,
contents: BlockContainer,
},
OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>),
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
OutOfFlowFloatBox(FloatBox),
Independent(IndependentFormattingContext),
}
@@ -206,7 +206,7 @@ fn layout_block_level_children(
.iter()
.enumerate()
.map(|(tree_rank, box_)| {
let mut fragment = box_.borrow().layout(
let mut fragment = box_.borrow_mut().layout(
layout_context,
positioning_context,
containing_block,
@@ -226,7 +226,7 @@ fn layout_block_level_children(
.mapfold_reduce_into(
positioning_context,
|positioning_context, (tree_rank, box_)| {
box_.borrow().layout(
box_.borrow_mut().layout(
layout_context,
positioning_context,
containing_block,
@@ -259,7 +259,7 @@ fn layout_block_level_children(
impl BlockLevelBox {
fn layout(
&self,
&mut self,
layout_context: &LayoutContext,
positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
@@ -322,7 +322,7 @@ impl BlockLevelBox {
positioning_context.push(hoisted_box);
Fragment::AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment {
hoisted_fragment,
position: box_.contents.style.clone_position(),
position: box_.borrow().contents.style.clone_position(),
})
},
BlockLevelBox::OutOfFlowFloatBox(_box_) => {

View File

@@ -207,7 +207,7 @@ impl BoxTree {
let contents = ReplacedContent::for_element(dirty_node)
.map_or(Contents::OfElement, Contents::Replaced);
let info = NodeAndStyleInfo::new(dirty_node, Arc::clone(&primary_style));
let out_of_flow_absolutely_positioned_box = Arc::new(
let out_of_flow_absolutely_positioned_box = ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, &info, display_inside, contents),
);
match update_point {
@@ -267,7 +267,7 @@ fn construct_for_root_element<'dom>(
let (contains_floats, root_box) = if box_style.position.is_absolutely_positioned() {
(
ContainsFloats::No,
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, &info, display_inside, contents),
)),
)

View File

@@ -12,9 +12,8 @@ use crate::geom::{LengthOrAuto, LengthPercentageOrAuto};
use crate::sizing::ContentSizesRequest;
use crate::style_ext::{ComputedValuesExt, DisplayInside};
use crate::{ContainingBlock, DefiniteContainingBlock};
use rayon::iter::{IntoParallelRefIterator, ParallelExtend};
use rayon::iter::{IntoParallelRefMutIterator, ParallelExtend};
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, LengthPercentage};
@@ -36,7 +35,7 @@ pub(crate) struct PositioningContext {
}
pub(crate) struct HoistedAbsolutelyPositionedBox {
absolutely_positioned_box: Arc<AbsolutelyPositionedBox>,
absolutely_positioned_box: ArcRefCell<AbsolutelyPositionedBox>,
/// The rank of the child from which this absolutely positioned fragment
/// came from, when doing the layout of a block container. Used to compute
@@ -98,14 +97,14 @@ impl AbsolutelyPositionedBox {
}
pub(crate) fn to_hoisted(
self_: Arc<Self>,
self_: ArcRefCell<Self>,
initial_start_corner: Vec2<Length>,
tree_rank: usize,
) -> HoistedAbsolutelyPositionedBox {
fn absolute_box_offsets(
initial_static_start: Length,
start: LengthPercentageOrAuto,
end: LengthPercentageOrAuto,
start: LengthPercentageOrAuto<'_>,
end: LengthPercentageOrAuto<'_>,
) -> AbsoluteBoxOffsets {
match (start.non_auto(), end.non_auto()) {
(None, None) => AbsoluteBoxOffsets::StaticStart {
@@ -122,10 +121,10 @@ impl AbsolutelyPositionedBox {
}
}
let box_offsets = self_.contents.style.box_offsets();
HoistedAbsolutelyPositionedBox {
tree_rank,
box_offsets: Vec2 {
let box_offsets = {
let box_ = self_.borrow();
let box_offsets = box_.contents.style.box_offsets();
Vec2 {
inline: absolute_box_offsets(
initial_start_corner.inline,
box_offsets.inline_start,
@@ -136,7 +135,11 @@ impl AbsolutelyPositionedBox {
box_offsets.block_start,
box_offsets.block_end,
),
},
}
};
HoistedAbsolutelyPositionedBox {
tree_rank,
box_offsets,
fragment: ArcRefCell::new(None),
absolutely_positioned_box: self_,
}
@@ -268,7 +271,7 @@ impl PositioningContext {
while !hoisted_boxes.is_empty() {
HoistedAbsolutelyPositionedBox::layout_many(
layout_context,
&hoisted_boxes,
&mut hoisted_boxes,
&mut laid_out_child_fragments,
&mut self.for_nearest_containing_block_for_all_descendants,
&containing_block,
@@ -281,12 +284,13 @@ impl PositioningContext {
pub(crate) fn push(&mut self, box_: HoistedAbsolutelyPositionedBox) {
if let Some(nearest) = &mut self.for_nearest_positioned_ancestor {
match box_
let position = box_
.absolutely_positioned_box
.borrow()
.contents
.style
.clone_position()
{
.clone_position();
match position {
Position::Fixed => {}, // fall through
Position::Absolute => return nearest.push(box_),
Position::Static | Position::Relative => unreachable!(),
@@ -357,7 +361,7 @@ impl PositioningContext {
{
HoistedAbsolutelyPositionedBox::layout_many(
layout_context,
&std::mem::take(&mut self.for_nearest_containing_block_for_all_descendants),
&mut std::mem::take(&mut self.for_nearest_containing_block_for_all_descendants),
fragments,
&mut self.for_nearest_containing_block_for_all_descendants,
initial_containing_block,
@@ -369,13 +373,13 @@ impl PositioningContext {
impl HoistedAbsolutelyPositionedBox {
pub(crate) fn layout_many(
layout_context: &LayoutContext,
boxes: &[Self],
boxes: &mut [Self],
fragments: &mut Vec<ArcRefCell<Fragment>>,
for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>,
containing_block: &DefiniteContainingBlock,
) {
if layout_context.use_rayon {
fragments.par_extend(boxes.par_iter().mapfold_reduce_into(
fragments.par_extend(boxes.par_iter_mut().mapfold_reduce_into(
for_nearest_containing_block_for_all_descendants,
|for_nearest_containing_block_for_all_descendants, box_| {
let new_fragment = ArcRefCell::new(Fragment::Box(box_.layout(
@@ -391,7 +395,7 @@ impl HoistedAbsolutelyPositionedBox {
vec_append_owned,
))
} else {
fragments.extend(boxes.iter().map(|box_| {
fragments.extend(boxes.iter_mut().map(|box_| {
let new_fragment = ArcRefCell::new(Fragment::Box(box_.layout(
layout_context,
for_nearest_containing_block_for_all_descendants,
@@ -404,19 +408,20 @@ impl HoistedAbsolutelyPositionedBox {
}
pub(crate) fn layout(
&self,
&mut self,
layout_context: &LayoutContext,
for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>,
containing_block: &DefiniteContainingBlock,
) -> BoxFragment {
let cbis = containing_block.size.inline;
let cbbs = containing_block.size.block;
let style = &self.absolutely_positioned_box.contents.style;
let absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut();
let style = &absolutely_positioned_box.contents.style;
let pbm = style.padding_border_margin(&containing_block.into());
let size;
let replaced_used_size;
match self.absolutely_positioned_box.contents.as_replaced() {
match absolutely_positioned_box.contents.as_replaced() {
Ok(replaced) => {
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
@@ -468,11 +473,11 @@ impl HoistedAbsolutelyPositionedBox {
|positioning_context| {
let size;
let fragments;
match self.absolutely_positioned_box.contents.as_replaced() {
match absolutely_positioned_box.contents.as_replaced() {
Ok(replaced) => {
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
let style = &self.absolutely_positioned_box.contents.style;
let style = &absolutely_positioned_box.contents.style;
size = replaced_used_size.unwrap();
fragments = replaced.make_fragments(style, size.clone());
},
@@ -488,7 +493,7 @@ impl HoistedAbsolutelyPositionedBox {
anchor -
pbm.padding_border_sums.inline -
margin.inline_sum();
self.absolutely_positioned_box
absolutely_positioned_box
.contents
.content_sizes
.shrink_to_fit(available_size)
@@ -544,7 +549,7 @@ impl HoistedAbsolutelyPositionedBox {
};
BoxFragment::new(
self.absolutely_positioned_box.contents.tag,
absolutely_positioned_box.contents.tag,
style.clone(),
fragments,
content_rect,

View File

@@ -64,9 +64,9 @@ pub(crate) struct PaddingBorderMargin {
pub(crate) trait ComputedValuesExt {
fn inline_size_is_length(&self) -> bool;
fn inline_box_offsets_are_both_non_auto(&self) -> bool;
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto>;
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>;
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>;
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>>;
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>>;
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>>;
fn max_box_size(&self) -> flow_relative::Vec2<Option<&LengthPercentage>>;
fn content_box_size(
&self,
@@ -86,7 +86,7 @@ pub(crate) trait ComputedValuesExt {
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin;
fn padding(&self) -> flow_relative::Sides<&LengthPercentage>;
fn border_width(&self) -> flow_relative::Sides<Length>;
fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto>;
fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>>;
fn has_transform_or_perspective(&self) -> bool;
fn effective_z_index(&self) -> i32;
fn establishes_stacking_context(&self) -> bool;
@@ -117,7 +117,7 @@ impl ComputedValuesExt for ComputedValues {
!a.is_auto() && !b.is_auto()
}
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto> {
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>> {
let position = self.get_position();
flow_relative::Sides::from_physical(
&PhysicalSides::new(
@@ -130,7 +130,7 @@ impl ComputedValuesExt for ComputedValues {
)
}
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> {
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>> {
let position = self.get_position();
flow_relative::Vec2::from_physical_size(
&PhysicalSize::new(
@@ -141,7 +141,7 @@ impl ComputedValuesExt for ComputedValues {
)
}
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> {
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>> {
let position = self.get_position();
flow_relative::Vec2::from_physical_size(
&PhysicalSize::new(
@@ -271,7 +271,7 @@ impl ComputedValuesExt for ComputedValues {
)
}
fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto> {
fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>> {
let margin = self.get_margin();
flow_relative::Sides::from_physical(
&PhysicalSides::new(