Switch the standard slice iterator in inline layout to a custom one in order to

avoid lifetime problems
This commit is contained in:
Patrick Walton 2020-03-13 19:30:43 -07:00
parent 1d9f669cf0
commit 42058681a5
2 changed files with 65 additions and 10 deletions

View file

@ -60,7 +60,7 @@ pub(crate) struct TextRun {
} }
struct InlineNestingLevelState<'box_tree> { struct InlineNestingLevelState<'box_tree> {
remaining_boxes: std::slice::Iter<'box_tree, ArcRefCell<InlineLevelBox>>, remaining_boxes: InlineBoxChildIter<'box_tree>,
fragments_so_far: Vec<Fragment>, fragments_so_far: Vec<Fragment>,
inline_start: Length, inline_start: Length,
max_block_size_of_fragments_so_far: Length, max_block_size_of_fragments_so_far: Length,
@ -222,7 +222,7 @@ impl InlineFormattingContext {
}, },
inline_position: Length::zero(), inline_position: Length::zero(),
current_nesting_level: InlineNestingLevelState { 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()), fragments_so_far: Vec::with_capacity(self.inline_level_boxes.len()),
inline_start: Length::zero(), inline_start: Length::zero(),
max_block_size_of_fragments_so_far: Length::zero(), max_block_size_of_fragments_so_far: Length::zero(),
@ -232,7 +232,7 @@ impl InlineFormattingContext {
if let Some(child) = ifc.current_nesting_level.remaining_boxes.next() { if let Some(child) = ifc.current_nesting_level.remaining_boxes.next() {
match &*child.borrow() { match &*child.borrow() {
InlineLevelBox::InlineBox(inline) => { 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) ifc.partial_inline_boxes_stack.push(partial)
}, },
InlineLevelBox::TextRun(run) => run.layout(layout_context, &mut ifc), InlineLevelBox::TextRun(run) => run.layout(layout_context, &mut ifc),
@ -257,7 +257,8 @@ impl InlineFormattingContext {
panic!("display:none does not generate an abspos box") 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; let hoisted_fragment_id = hoisted_fragment.fragment_id;
ifc.positioning_context.push(hoisted_fragment); ifc.positioning_context.push(hoisted_fragment);
ifc.lines ifc.lines
@ -365,7 +366,8 @@ impl Lines {
impl InlineBox { impl InlineBox {
fn start_layout<'box_tree>( fn start_layout<'box_tree>(
&'box_tree self, &self,
this_inline_level_box: ArcRefCell<InlineLevelBox>,
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();
@ -401,7 +403,9 @@ impl InlineBox {
parent_nesting_level: std::mem::replace( parent_nesting_level: std::mem::replace(
&mut ifc.current_nesting_level, &mut ifc.current_nesting_level,
InlineNestingLevelState { 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()), fragments_so_far: Vec::with_capacity(self.children.len()),
inline_start: ifc.inline_position, inline_start: ifc.inline_position,
max_block_size_of_fragments_so_far: Length::zero(), max_block_size_of_fragments_so_far: Length::zero(),
@ -461,10 +465,10 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> {
} }
} }
fn layout_atomic<'box_tree>( fn layout_atomic(
layout_context: &LayoutContext, layout_context: &LayoutContext,
ifc: &mut InlineFormattingContextState<'box_tree, '_, '_>, ifc: &mut InlineFormattingContextState,
atomic: &'box_tree IndependentFormattingContext, atomic: &IndependentFormattingContext,
) { ) {
let cbis = ifc.containing_block.inline_size; let cbis = ifc.containing_block.inline_size;
let padding = atomic.style.padding().percentages_relative_to(cbis); let padding = atomic.style.padding().percentages_relative_to(cbis);
@ -759,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!(),
},
}
}
}

View file

@ -315,7 +315,7 @@ impl BlockLevelBox {
)) ))
}, },
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => { 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(); let hoisted_fragment_id = hoisted_fragment.fragment_id.clone();
positioning_context.push(hoisted_fragment); positioning_context.push(hoisted_fragment);
Fragment::AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment( Fragment::AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment(