aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2020-03-18 06:14:20 -0400
committerGitHub <noreply@github.com>2020-03-18 06:14:20 -0400
commit5bf45b2622b7bfc194047ab602d27249f463d0da (patch)
treec3d15a51fadf5ae5ae89f21c1c346337f7e07273
parent9fb83d81438d425e06d061f8ba0c4128c61fc1ac (diff)
parent0d6c60f03ed6829dc02fc16fb3e43482f0ab1ae7 (diff)
downloadservo-5bf45b2622b7bfc194047ab602d27249f463d0da.tar.gz
servo-5bf45b2622b7bfc194047ab602d27249f463d0da.zip
Auto merge of #25957 - pcwalton:layout-2020-atomic-refcell, r=nox
Start using `AtomicRefCell` in layout 2020 as preparation for incremental layout This makes `BlockLevelBox` and `InlineLevelBox` use `AtomicRefCell` for incremental layout, per @nox's suggestion in https://github.com/servo/servo/issues/25168. As part of this, it reworks inline layout to use recursion, per https://github.com/servo/servo/issues/25950. LLVM should be able to optimize this into a loop (though I have not verified this). r? @nox
-rw-r--r--Cargo.lock4
-rw-r--r--components/layout_2020/Cargo.toml2
-rw-r--r--components/layout_2020/cell.rs69
-rw-r--r--components/layout_2020/dom_traversal.rs7
-rw-r--r--components/layout_2020/element_data.rs13
-rw-r--r--components/layout_2020/flow/construct.rs180
-rw-r--r--components/layout_2020/flow/inline.rs94
-rw-r--r--components/layout_2020/flow/mod.rs41
-rw-r--r--components/layout_2020/flow/root.rs27
-rw-r--r--components/layout_2020/formatting_contexts.rs4
-rw-r--r--components/layout_2020/lib.rs2
-rw-r--r--components/layout_2020/positioned.rs31
12 files changed, 309 insertions, 165 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3002d5a7ac6..edbc3c83993 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -166,9 +166,9 @@ checksum = "3c86699c3f02778ec07158376991c8f783dd1f2f95c579ffaf0738dc984b2fe2"
[[package]]
name = "atomic_refcell"
-version = "0.1.0"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
+checksum = "3bc31dce067eab974c815a9deb95f6217806de7b53685d7fc31f8ccf3fb2539f"
[[package]]
name = "atty"
diff --git a/components/layout_2020/Cargo.toml b/components/layout_2020/Cargo.toml
index a4cbe4c4ea1..0d3e30dba53 100644
--- a/components/layout_2020/Cargo.toml
+++ b/components/layout_2020/Cargo.toml
@@ -14,7 +14,7 @@ doctest = false
[dependencies]
app_units = "0.7"
-atomic_refcell = "0.1"
+atomic_refcell = "0.1.6"
canvas_traits = {path = "../canvas_traits"}
cssparser = "0.27"
embedder_traits = {path = "../embedder_traits"}
diff --git a/components/layout_2020/cell.rs b/components/layout_2020/cell.rs
new file mode 100644
index 00000000000..8aae377b24c
--- /dev/null
+++ b/components/layout_2020/cell.rs
@@ -0,0 +1,69 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use atomic_refcell::AtomicRefCell;
+use serde::{Serialize, Serializer};
+use servo_arc::Arc;
+use std::fmt;
+use std::ops::Deref;
+
+pub(crate) struct ArcRefCell<T> {
+ value: Arc<AtomicRefCell<T>>,
+}
+
+impl<T> ArcRefCell<T> {
+ pub fn new(value: T) -> Self {
+ Self {
+ value: Arc::new(AtomicRefCell::new(value)),
+ }
+ }
+}
+
+impl<T> Clone for ArcRefCell<T> {
+ fn clone(&self) -> Self {
+ Self {
+ value: self.value.clone(),
+ }
+ }
+}
+
+impl<T> Default for ArcRefCell<T>
+where
+ T: Default,
+{
+ fn default() -> Self {
+ Self {
+ value: Arc::new(AtomicRefCell::new(Default::default())),
+ }
+ }
+}
+
+impl<T> Deref for ArcRefCell<T> {
+ type Target = AtomicRefCell<T>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.value
+ }
+}
+
+impl<T> fmt::Debug for ArcRefCell<T>
+where
+ T: fmt::Debug,
+{
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.value.fmt(formatter)
+ }
+}
+
+impl<T> Serialize for ArcRefCell<T>
+where
+ T: Serialize,
+{
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ self.borrow().serialize(serializer)
+ }
+}
diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs
index 1a3a969919c..d60e779e665 100644
--- a/components/layout_2020/dom_traversal.rs
+++ b/components/layout_2020/dom_traversal.rs
@@ -2,13 +2,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::element_data::{LayoutBox, LayoutDataForElement};
use crate::geom::PhysicalSize;
use crate::replaced::{CanvasInfo, CanvasSource, ReplacedContent};
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside};
use crate::wrapper::GetRawData;
-use atomic_refcell::{AtomicRefCell, AtomicRefMut};
+use atomic_refcell::AtomicRefMut;
use html5ever::LocalName;
use net_traits::image::base::Image as NetImage;
use script_layout_interface::wrapper_traits::{
@@ -317,12 +318,12 @@ where
}
pub struct BoxSlot<'dom> {
- slot: Option<ServoArc<AtomicRefCell<Option<LayoutBox>>>>,
+ slot: Option<ArcRefCell<Option<LayoutBox>>>,
marker: marker<&'dom ()>,
}
impl BoxSlot<'_> {
- pub(crate) fn new(slot: ServoArc<AtomicRefCell<Option<LayoutBox>>>) -> Self {
+ pub(crate) fn new(slot: ArcRefCell<Option<LayoutBox>>) -> Self {
*slot.borrow_mut() = None;
let slot = Some(slot);
Self { slot, marker }
diff --git a/components/layout_2020/element_data.rs b/components/layout_2020/element_data.rs
index ccd48ac04e3..7385b7d84f0 100644
--- a/components/layout_2020/element_data.rs
+++ b/components/layout_2020/element_data.rs
@@ -2,25 +2,24 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::cell::ArcRefCell;
use crate::flow::inline::InlineLevelBox;
use crate::flow::BlockLevelBox;
-use atomic_refcell::AtomicRefCell;
-use servo_arc::Arc;
#[derive(Default)]
pub struct LayoutDataForElement {
- pub(super) self_box: Arc<AtomicRefCell<Option<LayoutBox>>>,
+ pub(super) self_box: ArcRefCell<Option<LayoutBox>>,
pub(super) pseudo_elements: Option<Box<PseudoElementBoxes>>,
}
#[derive(Default)]
pub(super) struct PseudoElementBoxes {
- pub before: Arc<AtomicRefCell<Option<LayoutBox>>>,
- pub after: Arc<AtomicRefCell<Option<LayoutBox>>>,
+ pub before: ArcRefCell<Option<LayoutBox>>,
+ pub after: ArcRefCell<Option<LayoutBox>>,
}
pub(super) enum LayoutBox {
DisplayContents,
- BlockLevel(Arc<BlockLevelBox>),
- InlineLevel(Arc<InlineLevelBox>),
+ BlockLevel(ArcRefCell<BlockLevelBox>),
+ InlineLevel(ArcRefCell<InlineLevelBox>),
}
diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs
index cff3fa281a6..0bf0b5c83ad 100644
--- a/components/layout_2020/flow/construct.rs
+++ b/components/layout_2020/flow/construct.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom_traversal::{BoxSlot, Contents, NodeExt, NonReplacedContents, TraversalHandler};
use crate::element_data::LayoutBox;
@@ -282,54 +283,48 @@ where
// context with the parent style of that builder.
let inlines = self.current_inline_level_boxes();
- fn last_text(inlines: &mut [Arc<InlineLevelBox>]) -> Option<&mut String> {
- let last = inlines.last_mut()?;
- if let InlineLevelBox::TextRun(_) = &**last {
- // We never clone text run boxes, so the refcount is 1 and unwrap succeeds:
- let last = Arc::get_mut(last).unwrap();
- if let InlineLevelBox::TextRun(TextRun { text, .. }) = last {
- Some(text)
- } else {
- unreachable!()
- }
- } else {
- None
- }
- }
-
let mut new_text_run_contents;
let output;
- if let Some(text) = last_text(inlines) {
- // Append to the existing text run
- new_text_run_contents = None;
- output = text;
- } else {
- new_text_run_contents = Some(String::new());
- output = new_text_run_contents.as_mut().unwrap();
- }
- if leading_whitespace {
- output.push(' ')
- }
- loop {
- if let Some(i) = input.bytes().position(|b| b.is_ascii_whitespace()) {
- let (non_whitespace, rest) = input.split_at(i);
- output.push_str(non_whitespace);
- output.push(' ');
- if let Some(i) = rest.bytes().position(|b| !b.is_ascii_whitespace()) {
- input = &rest[i..];
+ {
+ let mut last_box = inlines.last_mut().map(|last| last.borrow_mut());
+ let last_text = last_box.as_mut().and_then(|last| match &mut **last {
+ InlineLevelBox::TextRun(last) => Some(&mut last.text),
+ _ => None,
+ });
+
+ if let Some(text) = last_text {
+ // Append to the existing text run
+ new_text_run_contents = None;
+ output = text;
+ } else {
+ new_text_run_contents = Some(String::new());
+ output = new_text_run_contents.as_mut().unwrap();
+ }
+
+ if leading_whitespace {
+ output.push(' ')
+ }
+ loop {
+ if let Some(i) = input.bytes().position(|b| b.is_ascii_whitespace()) {
+ let (non_whitespace, rest) = input.split_at(i);
+ output.push_str(non_whitespace);
+ output.push(' ');
+ if let Some(i) = rest.bytes().position(|b| !b.is_ascii_whitespace()) {
+ input = &rest[i..];
+ } else {
+ break;
+ }
} else {
+ output.push_str(input);
break;
}
- } else {
- output.push_str(input);
- break;
}
}
if let Some(text) = new_text_run_contents {
let parent_style = parent_style.clone();
- inlines.push(Arc::new(InlineLevelBox::TextRun(TextRun {
+ inlines.push(ArcRefCell::new(InlineLevelBox::TextRun(TextRun {
tag: node.as_opaque(),
parent_style,
text,
@@ -353,29 +348,53 @@ where
if !text.starts_with(|c: char| c.is_ascii_whitespace()) {
return (false, text);
}
- let mut inline_level_boxes = self.current_inline_level_boxes().iter().rev();
- let mut stack = Vec::new();
- let preserved = loop {
- match inline_level_boxes.next().map(|b| &**b) {
- Some(InlineLevelBox::TextRun(r)) => break !r.text.ends_with(' '),
- Some(InlineLevelBox::Atomic { .. }) => break false,
- Some(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(_)) |
- Some(InlineLevelBox::OutOfFlowFloatBox(_)) => {},
- Some(InlineLevelBox::InlineBox(b)) => {
- stack.push(inline_level_boxes);
- inline_level_boxes = b.children.iter().rev()
- },
- None => {
- if let Some(iter) = stack.pop() {
- inline_level_boxes = iter
- } else {
- break false; // Paragraph start
- }
- },
- }
+
+ let preserved = match whitespace_is_preserved(self.current_inline_level_boxes()) {
+ WhitespacePreservedResult::Unknown => {
+ // Paragraph start.
+ false
+ },
+ WhitespacePreservedResult::NotPreserved => false,
+ WhitespacePreservedResult::Preserved => true,
};
+
let text = text.trim_start_matches(|c: char| c.is_ascii_whitespace());
- (preserved, text)
+ return (preserved, text);
+
+ fn whitespace_is_preserved(
+ inline_level_boxes: &[ArcRefCell<InlineLevelBox>],
+ ) -> WhitespacePreservedResult {
+ for inline_level_box in inline_level_boxes.iter().rev() {
+ match *inline_level_box.borrow() {
+ InlineLevelBox::TextRun(ref r) => {
+ if r.text.ends_with(' ') {
+ return WhitespacePreservedResult::NotPreserved;
+ }
+ return WhitespacePreservedResult::Preserved;
+ },
+ InlineLevelBox::Atomic { .. } => {
+ return WhitespacePreservedResult::NotPreserved;
+ },
+ InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(_) |
+ InlineLevelBox::OutOfFlowFloatBox(_) => {},
+ InlineLevelBox::InlineBox(ref b) => {
+ match whitespace_is_preserved(&b.children) {
+ WhitespacePreservedResult::Unknown => {},
+ result => return result,
+ }
+ },
+ }
+ }
+
+ WhitespacePreservedResult::Unknown
+ }
+
+ #[derive(Clone, Copy, PartialEq)]
+ enum WhitespacePreservedResult {
+ Preserved,
+ NotPreserved,
+ Unknown,
+ }
}
fn handle_inline_level_element(
@@ -384,7 +403,7 @@ where
style: &Arc<ComputedValues>,
display_inside: DisplayInside,
contents: Contents,
- ) -> Arc<InlineLevelBox> {
+ ) -> ArcRefCell<InlineLevelBox> {
let box_ = if display_inside == DisplayInside::Flow && !contents.is_replaced() {
// We found un inline box.
// Whatever happened before, all we need to do before recurring
@@ -410,9 +429,9 @@ where
.pop()
.expect("no ongoing inline level box found");
inline_box.last_fragment = true;
- Arc::new(InlineLevelBox::InlineBox(inline_box))
+ ArcRefCell::new(InlineLevelBox::InlineBox(inline_box))
} else {
- Arc::new(InlineLevelBox::Atomic(
+ ArcRefCell::new(InlineLevelBox::Atomic(
IndependentFormattingContext::construct(
self.context,
node,
@@ -466,13 +485,13 @@ where
for mut fragmented_parent_inline_box in fragmented_inline_boxes {
fragmented_parent_inline_box
.children
- .push(Arc::new(fragmented_inline));
+ .push(ArcRefCell::new(fragmented_inline));
fragmented_inline = InlineLevelBox::InlineBox(fragmented_parent_inline_box);
}
self.ongoing_inline_formatting_context
.inline_level_boxes
- .push(Arc::new(fragmented_inline));
+ .push(ArcRefCell::new(fragmented_inline));
}
// We found a block level element, so the ongoing inline formatting
@@ -525,7 +544,7 @@ where
kind,
});
} else {
- let box_ = Arc::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(
+ let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct(
self.context,
node,
@@ -533,7 +552,7 @@ where
display_inside,
contents,
),
- ));
+ )));
self.current_inline_level_boxes().push(box_.clone());
box_slot.set(LayoutBox::InlineLevel(box_))
}
@@ -561,7 +580,7 @@ where
kind,
});
} else {
- let box_ = Arc::new(InlineLevelBox::OutOfFlowFloatBox(FloatBox::construct(
+ let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowFloatBox(FloatBox::construct(
self.context,
node,
style,
@@ -610,7 +629,7 @@ where
});
}
- fn current_inline_level_boxes(&mut self) -> &mut Vec<Arc<InlineLevelBox>> {
+ fn current_inline_level_boxes(&mut self) -> &mut Vec<ArcRefCell<InlineLevelBox>> {
match self.ongoing_inline_boxes_stack.last_mut() {
Some(last) => &mut last.children,
None => &mut self.ongoing_inline_formatting_context.inline_level_boxes,
@@ -634,7 +653,7 @@ where
self,
context: &LayoutContext,
max_assign_in_flow_outer_content_sizes_to: Option<&mut ContentSizes>,
- ) -> (Arc<BlockLevelBox>, ContainsFloats) {
+ ) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) {
let node = self.node;
let style = self.style;
let (block_level_box, contains_floats) = match self.kind {
@@ -651,7 +670,7 @@ where
if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
to.max_assign(&box_content_sizes.outer_inline(&style))
}
- let block_level_box = Arc::new(BlockLevelBox::SameFormattingContextBlock {
+ let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock {
tag: node.as_opaque(),
contents,
style,
@@ -678,7 +697,7 @@ where
to.max_assign(&contents.content_sizes.outer_inline(&contents.style))
}
(
- Arc::new(BlockLevelBox::Independent(contents)),
+ ArcRefCell::new(BlockLevelBox::Independent(contents)),
ContainsFloats::No,
)
},
@@ -686,22 +705,23 @@ where
display_inside,
contents,
} => {
- let block_level_box = Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(
- AbsolutelyPositionedBox::construct(
- context,
- node,
- style,
- display_inside,
- contents,
- ),
- ));
+ let block_level_box =
+ ArcRefCell::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
+ AbsolutelyPositionedBox::construct(
+ context,
+ node,
+ style,
+ display_inside,
+ contents,
+ ),
+ )));
(block_level_box, ContainsFloats::No)
},
BlockLevelCreator::OutOfFlowFloatBox {
display_inside,
contents,
} => {
- let block_level_box = Arc::new(BlockLevelBox::OutOfFlowFloatBox(
+ let block_level_box = ArcRefCell::new(BlockLevelBox::OutOfFlowFloatBox(
FloatBox::construct(context, node, style, display_inside, contents),
));
(block_level_box, ContainsFloats::Yes)
diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs
index bd8f5bc784f..f71187e1118 100644
--- a/components/layout_2020/flow/inline.rs
+++ b/components/layout_2020/flow/inline.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::flow::float::FloatBox;
use crate::flow::FlowLayout;
@@ -27,14 +28,14 @@ use webrender_api::FontInstanceKey;
#[derive(Debug, Default, Serialize)]
pub(crate) struct InlineFormattingContext {
- pub(super) inline_level_boxes: Vec<Arc<InlineLevelBox>>,
+ pub(super) inline_level_boxes: Vec<ArcRefCell<InlineLevelBox>>,
}
#[derive(Debug, Serialize)]
pub(crate) enum InlineLevelBox {
InlineBox(InlineBox),
TextRun(TextRun),
- OutOfFlowAbsolutelyPositionedBox(AbsolutelyPositionedBox),
+ OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>),
OutOfFlowFloatBox(FloatBox),
Atomic(IndependentFormattingContext),
}
@@ -46,7 +47,7 @@ pub(crate) struct InlineBox {
pub style: Arc<ComputedValues>,
pub first_fragment: bool,
pub last_fragment: bool,
- pub children: Vec<Arc<InlineLevelBox>>,
+ pub children: Vec<ArcRefCell<InlineLevelBox>>,
}
/// https://www.w3.org/TR/css-display-3/#css-text-run
@@ -59,7 +60,7 @@ pub(crate) struct TextRun {
}
struct InlineNestingLevelState<'box_tree> {
- remaining_boxes: std::slice::Iter<'box_tree, Arc<InlineLevelBox>>,
+ remaining_boxes: InlineBoxChildIter<'box_tree>,
fragments_so_far: Vec<Fragment>,
inline_start: Length,
max_block_size_of_fragments_so_far: Length,
@@ -77,7 +78,7 @@ struct PartialInlineBoxFragment<'box_tree> {
}
struct InlineFormattingContextState<'box_tree, 'a, 'b> {
- positioning_context: &'a mut PositioningContext<'box_tree>,
+ positioning_context: &'a mut PositioningContext,
containing_block: &'b ContainingBlock<'b>,
lines: Lines,
inline_position: Length,
@@ -105,10 +106,10 @@ impl InlineFormattingContext {
fn traverse(
&mut self,
layout_context: &LayoutContext,
- inline_level_boxes: &[Arc<InlineLevelBox>],
+ inline_level_boxes: &[ArcRefCell<InlineLevelBox>],
) {
for inline_level_box in inline_level_boxes {
- match &**inline_level_box {
+ match &*inline_level_box.borrow() {
InlineLevelBox::InlineBox(inline_box) => {
let padding = inline_box.style.padding();
let border = inline_box.style.border_width();
@@ -204,10 +205,10 @@ impl InlineFormattingContext {
computation.paragraph
}
- pub(super) fn layout<'a>(
- &'a self,
+ pub(super) fn layout(
+ &self,
layout_context: &LayoutContext,
- positioning_context: &mut PositioningContext<'a>,
+ positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
tree_rank: usize,
) -> FlowLayout {
@@ -221,7 +222,7 @@ impl InlineFormattingContext {
},
inline_position: Length::zero(),
current_nesting_level: InlineNestingLevelState {
- remaining_boxes: self.inline_level_boxes.iter(),
+ remaining_boxes: InlineBoxChildIter::from_formatting_context(self),
fragments_so_far: Vec::with_capacity(self.inline_level_boxes.len()),
inline_start: Length::zero(),
max_block_size_of_fragments_so_far: Length::zero(),
@@ -229,9 +230,9 @@ impl InlineFormattingContext {
};
loop {
if let Some(child) = ifc.current_nesting_level.remaining_boxes.next() {
- match &**child {
+ match &*child.borrow() {
InlineLevelBox::InlineBox(inline) => {
- let partial = inline.start_layout(&mut ifc);
+ let partial = inline.start_layout(child.clone(), &mut ifc);
ifc.partial_inline_boxes_stack.push(partial)
},
InlineLevelBox::TextRun(run) => run.layout(layout_context, &mut ifc),
@@ -256,7 +257,8 @@ impl InlineFormattingContext {
panic!("display:none does not generate an abspos box")
},
};
- let hoisted_fragment = box_.to_hoisted(initial_start_corner, tree_rank);
+ let hoisted_fragment =
+ box_.clone().to_hoisted(initial_start_corner, tree_rank);
let hoisted_fragment_id = hoisted_fragment.fragment_id;
ifc.positioning_context.push(hoisted_fragment);
ifc.lines
@@ -364,7 +366,8 @@ impl Lines {
impl InlineBox {
fn start_layout<'box_tree>(
- &'box_tree self,
+ &self,
+ this_inline_level_box: ArcRefCell<InlineLevelBox>,
ifc: &mut InlineFormattingContextState<'box_tree, '_, '_>,
) -> PartialInlineBoxFragment<'box_tree> {
let style = self.style.clone();
@@ -400,7 +403,9 @@ impl InlineBox {
parent_nesting_level: std::mem::replace(
&mut ifc.current_nesting_level,
InlineNestingLevelState {
- remaining_boxes: self.children.iter(),
+ remaining_boxes: InlineBoxChildIter::from_inline_level_box(
+ this_inline_level_box,
+ ),
fragments_so_far: Vec::with_capacity(self.children.len()),
inline_start: ifc.inline_position,
max_block_size_of_fragments_so_far: Length::zero(),
@@ -460,10 +465,10 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> {
}
}
-fn layout_atomic<'box_tree>(
+fn layout_atomic(
layout_context: &LayoutContext,
- ifc: &mut InlineFormattingContextState<'box_tree, '_, '_>,
- atomic: &'box_tree IndependentFormattingContext,
+ ifc: &mut InlineFormattingContextState,
+ atomic: &IndependentFormattingContext,
) {
let cbis = ifc.containing_block.inline_size;
let padding = atomic.style.padding().percentages_relative_to(cbis);
@@ -758,3 +763,54 @@ impl TextRun {
}
}
}
+
+enum InlineBoxChildIter<'box_tree> {
+ InlineFormattingContext(std::slice::Iter<'box_tree, ArcRefCell<InlineLevelBox>>),
+ InlineBox {
+ inline_level_box: ArcRefCell<InlineLevelBox>,
+ child_index: usize,
+ },
+}
+
+impl<'box_tree> InlineBoxChildIter<'box_tree> {
+ fn from_formatting_context(
+ inline_formatting_context: &'box_tree InlineFormattingContext,
+ ) -> InlineBoxChildIter<'box_tree> {
+ InlineBoxChildIter::InlineFormattingContext(
+ inline_formatting_context.inline_level_boxes.iter(),
+ )
+ }
+
+ fn from_inline_level_box(
+ inline_level_box: ArcRefCell<InlineLevelBox>,
+ ) -> InlineBoxChildIter<'box_tree> {
+ InlineBoxChildIter::InlineBox {
+ inline_level_box,
+ child_index: 0,
+ }
+ }
+}
+
+impl<'box_tree> Iterator for InlineBoxChildIter<'box_tree> {
+ type Item = ArcRefCell<InlineLevelBox>;
+ fn next(&mut self) -> Option<ArcRefCell<InlineLevelBox>> {
+ match *self {
+ InlineBoxChildIter::InlineFormattingContext(ref mut iter) => iter.next().cloned(),
+ InlineBoxChildIter::InlineBox {
+ ref inline_level_box,
+ ref mut child_index,
+ } => match *inline_level_box.borrow() {
+ InlineLevelBox::InlineBox(ref inline_box) => {
+ if *child_index >= inline_box.children.len() {
+ return None;
+ }
+
+ let kid = inline_box.children[*child_index].clone();
+ *child_index += 1;
+ Some(kid)
+ },
+ _ => unreachable!(),
+ },
+ }
+ }
+}
diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs
index e15947f52b0..6aab3ba2be6 100644
--- a/components/layout_2020/flow/mod.rs
+++ b/components/layout_2020/flow/mod.rs
@@ -4,6 +4,7 @@
//! Flow layout, also known as block-and-inline layout.
+use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::flow::float::{FloatBox, FloatContext};
use crate::flow::inline::InlineFormattingContext;
@@ -38,7 +39,7 @@ pub(crate) struct BlockFormattingContext {
#[derive(Debug, Serialize)]
pub(crate) enum BlockContainer {
- BlockLevelBoxes(Vec<Arc<BlockLevelBox>>),
+ BlockLevelBoxes(Vec<ArcRefCell<BlockLevelBox>>),
InlineFormattingContext(InlineFormattingContext),
}
@@ -50,7 +51,7 @@ pub(crate) enum BlockLevelBox {
style: Arc<ComputedValues>,
contents: BlockContainer,
},
- OutOfFlowAbsolutelyPositionedBox(AbsolutelyPositionedBox),
+ OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>),
OutOfFlowFloatBox(FloatBox),
Independent(IndependentFormattingContext),
}
@@ -65,10 +66,10 @@ struct FlowLayout {
struct CollapsibleWithParentStartMargin(bool);
impl BlockFormattingContext {
- pub(super) fn layout<'a>(
- &'a self,
+ pub(super) fn layout(
+ &self,
layout_context: &LayoutContext,
- positioning_context: &mut PositioningContext<'a>,
+ positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
tree_rank: usize,
) -> IndependentLayout {
@@ -101,10 +102,10 @@ impl BlockFormattingContext {
}
impl BlockContainer {
- fn layout<'a>(
- &'a self,
+ fn layout(
+ &self,
layout_context: &LayoutContext,
- positioning_context: &mut PositioningContext<'a>,
+ positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
tree_rank: usize,
float_context: Option<&mut FloatContext>,
@@ -130,10 +131,10 @@ impl BlockContainer {
}
}
-fn layout_block_level_children<'a>(
+fn layout_block_level_children(
layout_context: &LayoutContext,
- positioning_context: &mut PositioningContext<'a>,
- child_boxes: &'a [Arc<BlockLevelBox>],
+ positioning_context: &mut PositioningContext,
+ child_boxes: &[ArcRefCell<BlockLevelBox>],
containing_block: &ContainingBlock,
tree_rank: usize,
mut float_context: Option<&mut FloatContext>,
@@ -204,7 +205,7 @@ fn layout_block_level_children<'a>(
.iter()
.enumerate()
.map(|(tree_rank, box_)| {
- let mut fragment = box_.layout(
+ let mut fragment = box_.borrow().layout(
layout_context,
positioning_context,
containing_block,
@@ -224,7 +225,7 @@ fn layout_block_level_children<'a>(
.mapfold_reduce_into(
positioning_context,
|positioning_context, (tree_rank, box_)| {
- box_.layout(
+ box_.borrow().layout(
layout_context,
positioning_context,
containing_block,
@@ -256,10 +257,10 @@ fn layout_block_level_children<'a>(
}
impl BlockLevelBox {
- fn layout<'a>(
- &'a self,
+ fn layout(
+ &self,
layout_context: &LayoutContext,
- positioning_context: &mut PositioningContext<'a>,
+ positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
tree_rank: usize,
float_context: Option<&mut FloatContext>,
@@ -314,7 +315,7 @@ impl BlockLevelBox {
))
},
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
- let hoisted_fragment = box_.to_hoisted(Vec2::zero(), tree_rank);
+ let hoisted_fragment = box_.clone().to_hoisted(Vec2::zero(), tree_rank);
let hoisted_fragment_id = hoisted_fragment.fragment_id.clone();
positioning_context.push(hoisted_fragment);
Fragment::AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment(
@@ -338,13 +339,13 @@ enum NonReplacedContents<'a> {
/// https://drafts.csswg.org/css2/visudet.html#blockwidth
/// 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(
layout_context: &LayoutContext,
- positioning_context: &mut PositioningContext<'a>,
+ positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
tag: OpaqueNode,
style: &Arc<ComputedValues>,
- block_level_kind: NonReplacedContents<'a>,
+ block_level_kind: NonReplacedContents,
tree_rank: usize,
float_context: Option<&mut FloatContext>,
) -> BoxFragment {
diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs
index 0b93701b01b..6a8be578630 100644
--- a/components/layout_2020/flow/root.rs
+++ b/components/layout_2020/flow/root.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::display_list::stacking_context::{
ContainingBlock, ContainingBlockInfo, StackingContext, StackingContextBuildMode,
@@ -62,7 +63,7 @@ impl BoxTreeRoot {
fn construct_for_root_element<'dom>(
context: &LayoutContext,
root_element: impl NodeExt<'dom>,
-) -> (ContainsFloats, Vec<Arc<BlockLevelBox>>) {
+) -> (ContainsFloats, Vec<ArcRefCell<BlockLevelBox>>) {
let style = root_element.style(context);
let replaced = ReplacedContent::for_element(root_element);
let box_style = style.get_box();
@@ -83,27 +84,29 @@ fn construct_for_root_element<'dom>(
if box_style.position.is_absolutely_positioned() {
(
ContainsFloats::No,
- vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(
- AbsolutelyPositionedBox::construct(
- context,
- root_element,
- style,
- display_inside,
- contents,
- ),
- ))],
+ vec![ArcRefCell::new(
+ BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
+ AbsolutelyPositionedBox::construct(
+ context,
+ root_element,
+ style,
+ display_inside,
+ contents,
+ ),
+ )),
+ )],
)
} else if box_style.float.is_floating() {
(
ContainsFloats::Yes,
- vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox(
+ vec![ArcRefCell::new(BlockLevelBox::OutOfFlowFloatBox(
FloatBox::construct(context, root_element, style, display_inside, contents),
))],
)
} else {
(
ContainsFloats::No,
- vec![Arc::new(BlockLevelBox::Independent(
+ vec![ArcRefCell::new(BlockLevelBox::Independent(
IndependentFormattingContext::construct(
context,
root_element,
diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs
index e4baf169476..100ef4a7c4b 100644
--- a/components/layout_2020/formatting_contexts.rs
+++ b/components/layout_2020/formatting_contexts.rs
@@ -104,11 +104,11 @@ impl IndependentFormattingContext {
}
}
-impl<'a> NonReplacedIFC<'a> {
+impl NonReplacedIFC<'_> {
pub fn layout(
&self,
layout_context: &LayoutContext,
- positioning_context: &mut PositioningContext<'a>,
+ positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
tree_rank: usize,
) -> IndependentLayout {
diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs
index 610c5306f53..3fc093399ee 100644
--- a/components/layout_2020/lib.rs
+++ b/components/layout_2020/lib.rs
@@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#![deny(unsafe_code)]
+#![feature(arbitrary_self_types)]
#![feature(exact_size_is_empty)]
#[macro_use]
@@ -10,6 +11,7 @@ extern crate log;
#[macro_use]
extern crate serde;
+mod cell;
pub mod context;
pub mod data;
pub mod display_list;
diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs
index b40a3b8b1ab..b909ae2d471 100644
--- a/components/layout_2020/positioned.rs
+++ b/components/layout_2020/positioned.rs
@@ -36,19 +36,18 @@ pub(crate) struct AbsolutelyPositionedBox {
pub contents: IndependentFormattingContext,
}
-pub(crate) struct PositioningContext<'box_tree> {
- for_nearest_positioned_ancestor: Option<Vec<HoistedAbsolutelyPositionedBox<'box_tree>>>,
+pub(crate) struct PositioningContext {
+ for_nearest_positioned_ancestor: Option<Vec<HoistedAbsolutelyPositionedBox>>,
// For nearest `containing block for all descendants` as defined by the CSS transforms
// spec.
// https://www.w3.org/TR/css-transforms-1/#containing-block-for-all-descendants
- for_nearest_containing_block_for_all_descendants:
- Vec<HoistedAbsolutelyPositionedBox<'box_tree>>,
+ for_nearest_containing_block_for_all_descendants: Vec<HoistedAbsolutelyPositionedBox>,
}
#[derive(Debug)]
-pub(crate) struct HoistedAbsolutelyPositionedBox<'box_tree> {
- absolutely_positioned_box: &'box_tree AbsolutelyPositionedBox,
+pub(crate) struct HoistedAbsolutelyPositionedBox {
+ absolutely_positioned_box: Arc<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
@@ -110,7 +109,7 @@ impl AbsolutelyPositionedBox {
}
pub(crate) fn to_hoisted(
- &self,
+ self: Arc<Self>,
initial_start_corner: Vec2<Length>,
tree_rank: usize,
) -> HoistedAbsolutelyPositionedBox {
@@ -150,7 +149,7 @@ impl AbsolutelyPositionedBox {
}
}
-impl<'box_tree> PositioningContext<'box_tree> {
+impl PositioningContext {
pub(crate) fn new_for_containing_block_for_all_descendants() -> Self {
Self {
for_nearest_positioned_ancestor: None,
@@ -220,9 +219,7 @@ impl<'box_tree> PositioningContext<'box_tree> {
fn create_and_layout_positioned(
layout_context: &LayoutContext,
style: &ComputedValues,
- for_nearest_containing_block_for_all_descendants: &mut Vec<
- HoistedAbsolutelyPositionedBox<'box_tree>,
- >,
+ for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>,
fragment_layout_fn: impl FnOnce(&mut Self) -> BoxFragment,
) -> BoxFragment {
if style.establishes_containing_block_for_all_descendants() {
@@ -296,7 +293,7 @@ impl<'box_tree> PositioningContext<'box_tree> {
new_fragment
}
- pub(crate) fn push(&mut self, box_: HoistedAbsolutelyPositionedBox<'box_tree>) {
+ pub(crate) fn push(&mut self, box_: HoistedAbsolutelyPositionedBox) {
if let Some(nearest) = &mut self.for_nearest_positioned_ancestor {
match box_
.absolutely_positioned_box
@@ -412,14 +409,12 @@ impl<'box_tree> PositioningContext<'box_tree> {
}
}
-impl<'box_tree> HoistedAbsolutelyPositionedBox<'box_tree> {
+impl HoistedAbsolutelyPositionedBox {
pub(crate) fn layout_many(
layout_context: &LayoutContext,
boxes: &[Self],
fragments: &mut Vec<Fragment>,
- for_nearest_containing_block_for_all_descendants: &mut Vec<
- HoistedAbsolutelyPositionedBox<'box_tree>,
- >,
+ for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>,
containing_block: &DefiniteContainingBlock,
) {
if layout_context.use_rayon {
@@ -449,9 +444,7 @@ impl<'box_tree> HoistedAbsolutelyPositionedBox<'box_tree> {
pub(crate) fn layout(
&self,
layout_context: &LayoutContext,
- for_nearest_containing_block_for_all_descendants: &mut Vec<
- HoistedAbsolutelyPositionedBox<'box_tree>,
- >,
+ for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>,
containing_block: &DefiniteContainingBlock,
) -> BoxFragment {
let style = &self.absolutely_positioned_box.contents.style;