mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
Switch the standard slice iterator in inline layout to a custom one in order to
avoid lifetime problems
This commit is contained in:
parent
1d9f669cf0
commit
42058681a5
2 changed files with 65 additions and 10 deletions
|
@ -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!(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue