mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
Compare commits
1 Commits
f9cfd05af8
...
layout-202
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be64f47642 |
@@ -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(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_) => {
|
||||
|
||||
@@ -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),
|
||||
)),
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user