From e956b53827e6c4ad6d3c2b0d9281dfc0e37b89d9 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 22 Aug 2024 05:05:15 -0700 Subject: [PATCH] layout: Clean up inline layout data structures (#33149) - Rename `InlineFormattingContextState` to `InlineFormattingContextLayout`. - Have `InlineFormattingContextLayout` hold a reference to the `InlineFormattingContext`, so that it does not need to be passed around as an argument - Have `LineItemLayout` hold a reference to `InlineFormattingContextLayout` to avoid duplicating so much data. - Rename some members of `LineItemLayout` to make it clearer what they do. - Give beter names to many lifetimes and combine some that are effectively the same. Signed-off-by: Martin Robinson Co-authored-by: Rakhi Sharma --- components/layout_2020/flow/inline/line.rs | 178 ++++++++---------- components/layout_2020/flow/inline/mod.rs | 164 +++++++--------- .../layout_2020/flow/inline/text_run.rs | 6 +- 3 files changed, 154 insertions(+), 194 deletions(-) diff --git a/components/layout_2020/flow/inline/line.rs b/components/layout_2020/flow/inline/line.rs index 68095c0f8c3..93032b9b102 100644 --- a/components/layout_2020/flow/inline/line.rs +++ b/components/layout_2020/flow/inline/line.rs @@ -2,8 +2,6 @@ * 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 std::rc::Rc; - use app_units::Au; use bitflags::bitflags; use fonts::{FontMetrics, GlyphStore}; @@ -20,12 +18,9 @@ use style::Zero; use unicode_bidi::{BidiInfo, Level}; use webrender_api::FontInstanceKey; -use super::inline_box::{ - InlineBoxContainerState, InlineBoxIdentifier, InlineBoxTreePathToken, InlineBoxes, -}; -use super::{InlineFormattingContextState, LineBlockSizes}; +use super::inline_box::{InlineBoxContainerState, InlineBoxIdentifier, InlineBoxTreePathToken}; +use super::{InlineFormattingContextLayout, LineBlockSizes}; use crate::cell::ArcRefCell; -use crate::context::LayoutContext; use crate::fragment_tree::{ BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, Fragment, TextFragment, }; @@ -33,7 +28,6 @@ use crate::geom::{LogicalRect, LogicalVec2, ToLogical}; use crate::positioned::{ relative_adjustement, AbsolutelyPositionedBox, PositioningContext, PositioningContextLength, }; -use crate::ContainingBlock; pub(super) struct LineMetrics { /// The block offset of the line start in the containing @@ -132,31 +126,16 @@ impl LineItemLayoutInlineContainerState { /// The second phase of [`super::InlineFormattingContext`] layout: once items are gathered /// for a line, we must lay them out and create fragments for them, properly positioning them /// according to their baselines and also handling absolutely positioned children. -pub(super) struct LineItemLayout<'a> { - /// The set of [`super::InlineBox`]es for the [`super::InlineFormattingContext`]. This - /// does *not* include any state from during phase one of layout. - pub inline_boxes: &'a InlineBoxes, - - /// The set of [`super::InlineBoxContainerState`] from phase one of IFC layout. There is - /// one of these for every inline box, *not* for the root inline container. - pub inline_box_states: &'a [Rc], +pub(super) struct LineItemLayout<'layout_data, 'layout> { + /// The state of the overall [`super::InlineFormattingContext`] layout. + layout: &'layout mut InlineFormattingContextLayout<'layout_data>, /// The set of [`super::LineItemLayoutInlineContainerState`] created while laying out items /// on this line. This does not include the current level of recursion. pub state_stack: Vec, /// The current [`super::LineItemLayoutInlineContainerState`]. - pub state: LineItemLayoutInlineContainerState, - - /// The [`LayoutContext`] to use for laying out absolutely positioned line items. - pub layout_context: &'a LayoutContext<'a>, - - /// The root positioning context for this layout. - pub root_positioning_context: &'a mut PositioningContext, - - /// The [`ContainingBlock`] of the parent [`super::InlineFormattingContext`] of the line being - /// laid out. - pub ifc_containing_block: &'a ContainingBlock<'a>, + pub current_state: LineItemLayoutInlineContainerState, /// The metrics of this line, which should remain constant throughout the /// layout process. @@ -167,9 +146,9 @@ pub(super) struct LineItemLayout<'a> { pub justification_adjustment: Au, } -impl<'a> LineItemLayout<'a> { +impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> { pub(super) fn layout_line_items( - state: &mut InlineFormattingContextState, + layout: &mut InlineFormattingContextLayout, line_items: Vec, start_position: LogicalVec2, effective_block_advance: &LineBlockSizes, @@ -177,13 +156,12 @@ impl<'a> LineItemLayout<'a> { ) -> Vec { let baseline_offset = effective_block_advance.find_baseline_offset(); LineItemLayout { - inline_boxes: state.inline_boxes, - inline_box_states: &state.inline_box_states, + layout, state_stack: Vec::new(), - root_positioning_context: state.positioning_context, - layout_context: state.layout_context, - state: LineItemLayoutInlineContainerState::root(start_position.inline, baseline_offset), - ifc_containing_block: state.containing_block, + current_state: LineItemLayoutInlineContainerState::root( + start_position.inline, + baseline_offset, + ), line_metrics: LineMetrics { block_offset: start_position.block, block_size: effective_block_advance.resolve(), @@ -191,7 +169,7 @@ impl<'a> LineItemLayout<'a> { }, justification_adjustment, } - .layout(line_items, state.has_right_to_left_content) + .layout(line_items) } /// Start and end inline boxes in tree order, so that it reflects the given inline box. @@ -207,8 +185,10 @@ impl<'a> LineItemLayout<'a> { // Otherwise, follow the path given to us by our collection of inline boxes, so we know which // inline boxes to start and end. let path = self + .layout + .ifc .inline_boxes - .get_path(self.state.identifier, new_inline_box); + .get_path(self.current_state.identifier, new_inline_box); for token in path { match token { InlineBoxTreePathToken::Start(ref identifier) => self.start_inline_box(identifier), @@ -217,12 +197,8 @@ impl<'a> LineItemLayout<'a> { } } - pub(super) fn layout( - &mut self, - mut line_items: Vec, - has_right_to_left_content: bool, - ) -> Vec { - let mut last_level: Level = Level::ltr(); + pub(super) fn layout(&mut self, mut line_items: Vec) -> Vec { + let mut last_level = Level::ltr(); let levels: Vec<_> = line_items .iter() .map(|item| { @@ -246,7 +222,7 @@ impl<'a> LineItemLayout<'a> { }) .collect(); - if has_right_to_left_content { + if self.layout.ifc.has_right_to_left_content { sort_by_indices_in_place(&mut line_items, BidiInfo::reorder_visual(&levels)); } @@ -257,17 +233,17 @@ impl<'a> LineItemLayout<'a> { // any in the inline formatting context. self.prepare_layout_for_inline_box(item.inline_box_identifier()); - self.state + self.current_state .flags .insert(LineLayoutInlineContainerFlags::HAD_ANY_LINE_ITEMS); match item { LineItem::StartInlineBoxPaddingBorderMargin(_) => { - self.state + self.current_state .flags .insert(LineLayoutInlineContainerFlags::HAD_START_PBM); }, LineItem::EndInlineBoxPaddingBorderMargin(_) => { - self.state + self.current_state .flags .insert(LineLayoutInlineContainerFlags::HAD_END_PBM); }, @@ -280,12 +256,13 @@ impl<'a> LineItemLayout<'a> { // Move back to the root of the inline box tree, so that all boxes are ended. self.prepare_layout_for_inline_box(None); - std::mem::take(&mut self.state.fragments) + std::mem::take(&mut self.current_state.fragments) } fn current_positioning_context_mut(&mut self) -> &mut PositioningContext { - if let Either::First(ref mut positioning_context) = - self.state.positioning_context_or_start_offset_in_parent + if let Either::First(ref mut positioning_context) = self + .current_state + .positioning_context_or_start_offset_in_parent { return positioning_context; } @@ -298,12 +275,13 @@ impl<'a> LineItemLayout<'a> { Either::Second(_) => None, }, ) - .unwrap_or(self.root_positioning_context) + .unwrap_or(self.layout.positioning_context) } fn start_inline_box(&mut self, identifier: &InlineBoxIdentifier) { - let inline_box_state = &*self.inline_box_states[identifier.index_in_inline_boxes as usize]; - let inline_box = self.inline_boxes.get(identifier); + let inline_box_state = + &*self.layout.inline_box_states[identifier.index_in_inline_boxes as usize]; + let inline_box = self.layout.ifc.inline_boxes.get(identifier); let inline_box = &*(inline_box.borrow()); let style = &inline_box.style; @@ -318,12 +296,12 @@ impl<'a> LineItemLayout<'a> { }; let parent_offset = LogicalVec2 { - inline: self.state.inline_advance + self.state.parent_offset.inline, + inline: self.current_state.inline_advance + self.current_state.parent_offset.inline, block: block_start_offset, }; let outer_state = std::mem::replace( - &mut self.state, + &mut self.current_state, LineItemLayoutInlineContainerState::new( Some(*identifier), parent_offset, @@ -337,11 +315,12 @@ impl<'a> LineItemLayout<'a> { fn end_inline_box(&mut self) { let outer_state = self.state_stack.pop().expect("Ended unknown inline box"); - let mut inner_state = std::mem::replace(&mut self.state, outer_state); + let mut inner_state = std::mem::replace(&mut self.current_state, outer_state); let identifier = inner_state.identifier.expect("Ended unknown inline box"); - let inline_box_state = &*self.inline_box_states[identifier.index_in_inline_boxes as usize]; - let inline_box = self.inline_boxes.get(&identifier); + let inline_box_state = + &*self.layout.inline_box_states[identifier.index_in_inline_boxes as usize]; + let inline_box = self.layout.ifc.inline_boxes.get(&identifier); let inline_box = &*(inline_box.borrow()); let mut padding = inline_box_state.pbm.padding; @@ -379,8 +358,8 @@ impl<'a> LineItemLayout<'a> { // Make `content_rect` relative to the parent Fragment. let mut content_rect = LogicalRect { start_corner: LogicalVec2 { - inline: self.state.inline_advance + pbm_sums.inline_start, - block: inner_state.parent_offset.block - self.state.parent_offset.block, + inline: self.current_state.inline_advance + pbm_sums.inline_start, + block: inner_state.parent_offset.block - self.current_state.parent_offset.block, }, size: LogicalVec2 { inline: inner_state.inline_advance, @@ -388,7 +367,7 @@ impl<'a> LineItemLayout<'a> { }, }; - let ifc_writing_mode = self.ifc_containing_block.effective_writing_mode(); + let ifc_writing_mode = self.layout.containing_block.effective_writing_mode(); if inner_state .flags .contains(LineLayoutInlineContainerFlags::HAD_ANY_FLOATS) @@ -405,7 +384,7 @@ impl<'a> LineItemLayout<'a> { // do it right before creating the Fragment. let style = &inline_box.style; if style.clone_position().is_relative() { - content_rect.start_corner += relative_adjustement(style, self.ifc_containing_block); + content_rect.start_corner += relative_adjustement(style, self.layout.containing_block); } let mut fragment = BoxFragment::new( @@ -422,7 +401,8 @@ impl<'a> LineItemLayout<'a> { match inner_state.positioning_context_or_start_offset_in_parent { Either::First(mut positioning_context) => { - positioning_context.layout_collected_children(self.layout_context, &mut fragment); + positioning_context + .layout_collected_children(self.layout.layout_context, &mut fragment); positioning_context.adjust_static_position_of_hoisted_fragments_with_offset( &fragment.content_rect.origin.to_logical(ifc_writing_mode), PositioningContextLength::zero(), @@ -439,8 +419,8 @@ impl<'a> LineItemLayout<'a> { }, } - self.state.inline_advance += inner_state.inline_advance + pbm_sums.inline_sum(); - self.state.fragments.push(Fragment::Box(fragment)); + self.current_state.inline_advance += inner_state.inline_advance + pbm_sums.inline_sum(); + self.current_state.fragments.push(Fragment::Box(fragment)); } fn calculate_inline_box_block_start( @@ -496,10 +476,10 @@ impl<'a> LineItemLayout<'a> { // inline box's strut), but for children of the inline formatting context root or for // fallback fonts that use baseline relative alignment, it might be different. let start_corner = LogicalVec2 { - inline: self.state.inline_advance, - block: self.state.baseline_offset - + inline: self.current_state.inline_advance, + block: self.current_state.baseline_offset - text_item.font_metrics.ascent - - self.state.parent_offset.block, + self.current_state.parent_offset.block, }; let rect = LogicalRect { @@ -510,17 +490,19 @@ impl<'a> LineItemLayout<'a> { }, }; - self.state.inline_advance += inline_advance; - self.state.fragments.push(Fragment::Text(TextFragment { - base: text_item.base_fragment_info.into(), - parent_style: text_item.parent_style, - rect: rect.to_physical(self.ifc_containing_block.effective_writing_mode()), - font_metrics: text_item.font_metrics, - font_key: text_item.font_key, - glyphs: text_item.text, - text_decoration_line: text_item.text_decoration_line, - justification_adjustment: self.justification_adjustment, - })); + self.current_state.inline_advance += inline_advance; + self.current_state + .fragments + .push(Fragment::Text(TextFragment { + base: text_item.base_fragment_info.into(), + parent_style: text_item.parent_style, + rect: rect.to_physical(self.layout.containing_block.effective_writing_mode()), + font_metrics: text_item.font_metrics, + font_key: text_item.font_key, + glyphs: text_item.text, + text_decoration_line: text_item.text_decoration_line, + justification_adjustment: self.justification_adjustment, + })); } fn layout_atomic(&mut self, mut atomic: AtomicLineItem) { @@ -529,17 +511,17 @@ impl<'a> LineItemLayout<'a> { // This needs to be added to the calculated block and inline positions. // Make the final result relative to the parent box. let mut atomic_offset = LogicalVec2 { - inline: self.state.inline_advance, + inline: self.current_state.inline_advance, block: atomic.calculate_block_start(&self.line_metrics) - - self.state.parent_offset.block, + self.current_state.parent_offset.block, }; if atomic.fragment.style.clone_position().is_relative() { atomic_offset += - relative_adjustement(&atomic.fragment.style, self.ifc_containing_block); + relative_adjustement(&atomic.fragment.style, self.layout.containing_block); } - let ifc_writing_mode = self.ifc_containing_block.effective_writing_mode(); + let ifc_writing_mode = self.layout.containing_block.effective_writing_mode(); atomic.fragment.content_rect.origin += atomic_offset.to_physical_size(ifc_writing_mode); if let Some(mut positioning_context) = atomic.positioning_context { @@ -555,8 +537,10 @@ impl<'a> LineItemLayout<'a> { .append(positioning_context); } - self.state.inline_advance += atomic.size.inline; - self.state.fragments.push(Fragment::Box(atomic.fragment)); + self.current_state.inline_advance += atomic.size.inline; + self.current_state + .fragments + .push(Fragment::Box(atomic.fragment)); } fn layout_absolute(&mut self, absolute: AbsolutelyPositionedLineItem) { @@ -579,31 +563,31 @@ impl<'a> LineItemLayout<'a> { if style.get_box().original_display.outside() == DisplayOutside::Inline { // Top of the line at the current inline position. LogicalVec2 { - inline: self.state.inline_advance, - block: -self.state.parent_offset.block, + inline: self.current_state.inline_advance, + block: -self.current_state.parent_offset.block, } } else { // After the bottom of the line at the start of the inline formatting context. LogicalVec2 { - inline: -self.state.parent_offset.inline, - block: self.line_metrics.block_size - self.state.parent_offset.block, + inline: -self.current_state.parent_offset.inline, + block: self.line_metrics.block_size - self.current_state.parent_offset.block, } }; let hoisted_box = AbsolutelyPositionedBox::to_hoisted( absolute.absolutely_positioned_box.clone(), initial_start_corner.into(), - self.ifc_containing_block, + self.layout.containing_block, ); let hoisted_fragment = hoisted_box.fragment.clone(); self.current_positioning_context_mut().push(hoisted_box); - self.state + self.current_state .fragments .push(Fragment::AbsoluteOrFixedPositioned(hoisted_fragment)); } fn layout_float(&mut self, mut float: FloatLineItem) { - self.state + self.current_state .flags .insert(LineLayoutInlineContainerFlags::HAD_ANY_FLOATS); @@ -613,12 +597,14 @@ impl<'a> LineItemLayout<'a> { // formatting context, so that they are parented properly for StackingContext // properties such as opacity & filters. let distance_from_parent_to_ifc = LogicalVec2 { - inline: self.state.parent_offset.inline, - block: self.line_metrics.block_offset + self.state.parent_offset.block, + inline: self.current_state.parent_offset.inline, + block: self.line_metrics.block_offset + self.current_state.parent_offset.block, }; float.fragment.content_rect.origin -= distance_from_parent_to_ifc - .to_physical_size(self.ifc_containing_block.effective_writing_mode()); - self.state.fragments.push(Fragment::Float(float.fragment)); + .to_physical_size(self.layout.containing_block.effective_writing_mode()); + self.current_state + .fragments + .push(Fragment::Float(float.fragment)); } } diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs index 22632cee22f..34cb5ff4c39 100644 --- a/components/layout_2020/flow/inline/mod.rs +++ b/components/layout_2020/flow/inline/mod.rs @@ -196,11 +196,11 @@ pub(crate) enum InlineItem { } /// Information about the current line under construction for a particular -/// [`InlineFormattingContextState`]. This tracks position and size information while +/// [`InlineFormattingContextLayout`]. This tracks position and size information while /// [`LineItem`]s are collected and is used as input when those [`LineItem`]s are /// converted into [`Fragment`]s during the final phase of line layout. Note that this /// does not store the [`LineItem`]s themselves, as they are stored as part of the -/// nesting state in the [`InlineFormattingContextState`]. +/// nesting state in the [`InlineFormattingContextLayout`]. struct LineUnderConstruction { /// The position where this line will start once it is laid out. This includes any /// offset from `text-indent`. @@ -552,19 +552,14 @@ pub(super) struct InlineContainerState { font_metrics: FontMetrics, } -pub(super) struct InlineFormattingContextState<'a, 'b> { - positioning_context: &'a mut PositioningContext, - containing_block: &'b ContainingBlock<'b>, - sequential_layout_state: Option<&'a mut SequentialLayoutState>, - layout_context: &'b LayoutContext<'b>, +pub(super) struct InlineFormattingContextLayout<'layout_data> { + positioning_context: &'layout_data mut PositioningContext, + containing_block: &'layout_data ContainingBlock<'layout_data>, + sequential_layout_state: Option<&'layout_data mut SequentialLayoutState>, + layout_context: &'layout_data LayoutContext<'layout_data>, - /// The inline boxes collection of the [`InlineFormattingContext`] that this - /// state is laying out. - inline_boxes: &'a InlineBoxes, - - /// The list of [`FontMetrics`] used by the [`InlineFormattingContext`] that - /// we are laying out. - fonts: &'a Vec, + /// The [`InlineFormattingContext`] that we are laying out. + ifc: &'layout_data InlineFormattingContext, /// The [`InlineContainerState`] for the container formed by the root of the /// [`InlineFormattingContext`]. This is effectively the "root inline box" described @@ -616,7 +611,7 @@ pub(super) struct InlineFormattingContextState<'a, 'b> { /// In this case, the `` should not extend to the second line. If we linebreak /// as soon as we encounter the `
` the ``'s ending inline borders would be /// placed on the second line, because we add those borders in - /// [`InlineFormattingContextState::finish_inline_box()`]. + /// [`InlineFormattingContextLayout::finish_inline_box()`]. linebreak_before_new_content: bool, /// When a `
` element has `clear`, this needs to be applied after the linebreak, @@ -633,13 +628,13 @@ pub(super) struct InlineFormattingContextState<'a, 'b> { had_inflow_content: bool, /// The currently white-space-collapse setting of this line. This is stored on the - /// [`InlineFormattingContextState`] because when a soft wrap opportunity is defined + /// [`InlineFormattingContextLayout`] because when a soft wrap opportunity is defined /// by the boundary between two characters, the white-space-collapse property of their /// nearest common ancestor is used. white_space_collapse: WhiteSpaceCollapse, /// The currently text-wrap-mode setting of this line. This is stored on the - /// [`InlineFormattingContextState`] because when a soft wrap opportunity is defined + /// [`InlineFormattingContextLayout`] because when a soft wrap opportunity is defined /// by the boundary between two characters, the text-wrap-mode property of their nearest /// common ancestor is used. text_wrap_mode: TextWrapMode, @@ -648,12 +643,9 @@ pub(super) struct InlineFormattingContextState<'a, 'b> { /// are laying out. This is used to propagate baselines to the ancestors of /// `display: inline-block` elements and table content. baselines: Baselines, - - /// Whether or not the [`InlineFormattingContext`] being laid out has right-to-left content. - has_right_to_left_content: bool, } -impl<'a, 'b> InlineFormattingContextState<'a, 'b> { +impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> { fn current_inline_container_state(&self) -> &InlineContainerState { match self.inline_box_state_stack.last() { Some(inline_box_state) => &inline_box_state.base, @@ -706,7 +698,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { inline_box.is_last_fragment, inline_box .default_font_index - .map(|index| &self.fonts[index].metrics), + .map(|index| &self.ifc.font_metrics[index].metrics), ); // If we are starting a `
` element prepare to clear after its deferred linebreak has been @@ -799,7 +791,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { /// Finish layout of all inline boxes for the current line. This will gather all /// [`LineItem`]s and turn them into [`Fragment`]s, then reset the - /// [`InlineFormattingContextState`] preparing it for laying out a new line. + /// [`InlineFormattingContextLayout`] preparing it for laying out a new line. fn finish_current_line_and_reset(&mut self, last_line_or_forced_line_break: bool) { let whitespace_trimmed = self.current_line.trim_trailing_whitespace(); let (inline_start_position, justification_adjustment) = self @@ -1265,7 +1257,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { // If the metrics of this font don't match the default font, we are likely using a fallback // font and need to adjust the line size to account for a potentially different font. // If somehow the metrics match, the line size won't change. - let ifc_font_info = &self.fonts[font_index]; + let ifc_font_info = &self.ifc.font_metrics[font_index]; let font_metrics = ifc_font_info.metrics.clone(); let using_fallback_font = self.current_inline_container_state().font_metrics != font_metrics; @@ -1609,13 +1601,12 @@ impl InlineFormattingContext { .insert(InlineContainerStateFlags::IS_SINGLE_LINE_TEXT_INPUT); } - let mut ifc = InlineFormattingContextState { + let mut layout = InlineFormattingContextLayout { positioning_context, containing_block, sequential_layout_state, layout_context, - inline_boxes: &self.inline_boxes, - fonts: &self.font_metrics, + ifc: self, fragments: Vec::new(), current_line: LineUnderConstruction::new(LogicalVec2 { inline: first_line_inline_start, @@ -1638,13 +1629,12 @@ impl InlineFormattingContext { white_space_collapse: style_text.white_space_collapse, text_wrap_mode: style_text.text_wrap_mode, baselines: Baselines::default(), - has_right_to_left_content: self.has_right_to_left_content, }; // FIXME(pcwalton): This assumes that margins never collapse through inline formatting // contexts (i.e. that inline formatting contexts are never empty). Is that right? // FIXME(mrobinson): This should not happen if the IFC collapses through. - if let Some(ref mut sequential_layout_state) = ifc.sequential_layout_state { + if let Some(ref mut sequential_layout_state) = layout.sequential_layout_state { sequential_layout_state.collapse_margins(); // FIXME(mrobinson): Collapse margins in the containing block offsets as well?? } @@ -1654,51 +1644,49 @@ impl InlineFormattingContext { // Any new box should flush a pending hard line break. if !matches!(item, InlineItem::EndInlineBox) { - ifc.possibly_flush_deferred_forced_line_break(); + layout.possibly_flush_deferred_forced_line_break(); } match item { InlineItem::StartInlineBox(identifier) => { - ifc.start_inline_box(&self.inline_boxes.get(identifier).borrow()); + layout.start_inline_box(&self.inline_boxes.get(identifier).borrow()); }, - InlineItem::EndInlineBox => ifc.finish_inline_box(), - InlineItem::TextRun(run) => run.layout_into_line_items(&mut ifc), + InlineItem::EndInlineBox => layout.finish_inline_box(), + InlineItem::TextRun(run) => run.layout_into_line_items(&mut layout), InlineItem::Atomic(atomic_formatting_context, offset_in_text, bidi_level) => { atomic_formatting_context.layout_into_line_items( - layout_context, - self, - &mut ifc, + &mut layout, *offset_in_text, *bidi_level, ); }, InlineItem::OutOfFlowAbsolutelyPositionedBox(positioned_box, _) => { - ifc.push_line_item_to_unbreakable_segment(LineItem::AbsolutelyPositioned( - ifc.current_inline_box_identifier(), + layout.push_line_item_to_unbreakable_segment(LineItem::AbsolutelyPositioned( + layout.current_inline_box_identifier(), AbsolutelyPositionedLineItem { absolutely_positioned_box: positioned_box.clone(), }, )); }, InlineItem::OutOfFlowFloatBox(ref mut float_box) => { - float_box.layout_into_line_items(layout_context, &mut ifc); + float_box.layout_into_line_items(&mut layout); }, } } - ifc.finish_last_line(); + layout.finish_last_line(); let mut collapsible_margins_in_children = CollapsedBlockMargins::zero(); - let content_block_size = ifc.current_line.start_position.block; - collapsible_margins_in_children.collapsed_through = !ifc.had_inflow_content && + let content_block_size = layout.current_line.start_position.block; + collapsible_margins_in_children.collapsed_through = !layout.had_inflow_content && content_block_size == Au::zero() && collapsible_with_parent_start_margin.0; FlowLayout { - fragments: ifc.fragments, + fragments: layout.fragments, content_block_size: content_block_size.into(), collapsible_margins_in_children, - baselines: ifc.baselines, + baselines: layout.baselines, } } @@ -1913,18 +1901,13 @@ impl InlineContainerState { impl IndependentFormattingContext { fn layout_into_line_items( &mut self, - layout_context: &LayoutContext, - inline_formatting_context: &InlineFormattingContext, - inline_formatting_context_state: &mut InlineFormattingContextState, + layout: &mut InlineFormattingContextLayout, offset_in_text: usize, bidi_level: Level, ) { let style = self.style(); - let container_writing_mode = inline_formatting_context_state - .containing_block - .style - .effective_writing_mode(); - let pbm = style.padding_border_margin(inline_formatting_context_state.containing_block); + let container_writing_mode = layout.containing_block.style.effective_writing_mode(); + let pbm = style.padding_border_margin(layout.containing_block); let margin = pbm.margin.auto_is(Au::zero); let pbm_sums = pbm.padding + pbm.border + margin; let pbm_physical_origin = pbm_sums @@ -1938,7 +1921,7 @@ impl IndependentFormattingContext { let size = replaced .contents .used_size_as_if_inline_element( - inline_formatting_context_state.containing_block, + layout.containing_block, &replaced.style, None, &pbm, @@ -1962,22 +1945,21 @@ impl IndependentFormattingContext { IndependentFormattingContext::NonReplaced(non_replaced) => { let box_size = non_replaced .style - .content_box_size(inline_formatting_context_state.containing_block, &pbm); + .content_box_size(layout.containing_block, &pbm); let max_box_size = non_replaced .style - .content_max_box_size(inline_formatting_context_state.containing_block, &pbm); + .content_max_box_size(layout.containing_block, &pbm); let min_box_size = non_replaced .style - .content_min_box_size(inline_formatting_context_state.containing_block, &pbm) + .content_min_box_size(layout.containing_block, &pbm) .auto_is(Length::zero); // https://drafts.csswg.org/css2/visudet.html#inlineblock-width let tentative_inline_size = box_size.inline.auto_is(|| { let available_size = - inline_formatting_context_state.containing_block.inline_size - - pbm_sums.inline_sum(); + layout.containing_block.inline_size - pbm_sums.inline_sum(); non_replaced - .inline_content_sizes(layout_context) + .inline_content_sizes(layout.layout_context) .shrink_to_fit(available_size) .into() }); @@ -1994,11 +1976,7 @@ impl IndependentFormattingContext { style: &non_replaced.style, }; assert_eq!( - inline_formatting_context_state - .containing_block - .style - .writing_mode - .is_horizontal(), + layout.containing_block.style.writing_mode.is_horizontal(), containing_block_for_children .style .writing_mode @@ -2013,10 +1991,10 @@ impl IndependentFormattingContext { true, /* collects_for_nearest_positioned_ancestor */ )); let independent_layout = non_replaced.layout( - layout_context, + layout.layout_context, child_positioning_context.as_mut().unwrap(), &containing_block_for_children, - inline_formatting_context_state.containing_block, + layout.containing_block, ); let (inline_size, block_size) = match independent_layout.content_inline_size_for_table { @@ -2061,11 +2039,12 @@ impl IndependentFormattingContext { }, }; - if inline_formatting_context_state.text_wrap_mode == TextWrapMode::Wrap && - !inline_formatting_context + if layout.text_wrap_mode == TextWrapMode::Wrap && + !layout + .ifc .previous_character_prevents_soft_wrap_opportunity(offset_in_text) { - inline_formatting_context_state.process_soft_wrap_opportunity(); + layout.process_soft_wrap_opportunity(); } let size = pbm_sums.sum() + @@ -2078,18 +2057,15 @@ impl IndependentFormattingContext { .map(|baseline| pbm_sums.block_start + baseline) .unwrap_or(size.block); - let (block_sizes, baseline_offset_in_parent) = self.get_block_sizes_and_baseline_offset( - inline_formatting_context_state, - size.block, - baseline_offset, - ); - inline_formatting_context_state.update_unbreakable_segment_for_new_content( + let (block_sizes, baseline_offset_in_parent) = + self.get_block_sizes_and_baseline_offset(layout, size.block, baseline_offset); + layout.update_unbreakable_segment_for_new_content( &block_sizes, size.inline, SegmentContentFlags::empty(), ); - inline_formatting_context_state.push_line_item_to_unbreakable_segment(LineItem::Atomic( - inline_formatting_context_state.current_inline_box_identifier(), + layout.push_line_item_to_unbreakable_segment(LineItem::Atomic( + layout.current_inline_box_identifier(), AtomicLineItem { fragment, size, @@ -2102,9 +2078,11 @@ impl IndependentFormattingContext { // If there's a soft wrap opportunity following this atomic, defer a soft wrap opportunity // for when we next process text content. - if !inline_formatting_context.next_character_prevents_soft_wrap_opportunity(offset_in_text) + if !layout + .ifc + .next_character_prevents_soft_wrap_opportunity(offset_in_text) { - inline_formatting_context_state.have_deferred_soft_wrap_opportunity = true; + layout.have_deferred_soft_wrap_opportunity = true; } } @@ -2128,7 +2106,7 @@ impl IndependentFormattingContext { fn get_block_sizes_and_baseline_offset( &self, - ifc: &InlineFormattingContextState, + ifc: &InlineFormattingContextLayout, block_size: Au, baseline_offset_in_content_area: Au, ) -> (LineBlockSizes, Au) { @@ -2163,18 +2141,14 @@ impl IndependentFormattingContext { } impl FloatBox { - fn layout_into_line_items( - &mut self, - layout_context: &LayoutContext, - ifc: &mut InlineFormattingContextState, - ) { + fn layout_into_line_items(&mut self, layout: &mut InlineFormattingContextLayout) { let fragment = self.layout( - layout_context, - ifc.positioning_context, - ifc.containing_block, + layout.layout_context, + layout.positioning_context, + layout.containing_block, ); - ifc.push_line_item_to_unbreakable_segment(LineItem::Float( - ifc.current_inline_box_identifier(), + layout.push_line_item_to_unbreakable_segment(LineItem::Float( + layout.current_inline_box_identifier(), FloatLineItem { fragment, needs_placement: true, @@ -2183,7 +2157,7 @@ impl FloatBox { } } -fn place_pending_floats(ifc: &mut InlineFormattingContextState, line_items: &mut [LineItem]) { +fn place_pending_floats(ifc: &mut InlineFormattingContextLayout, line_items: &mut [LineItem]) { for item in line_items.iter_mut() { if let LineItem::Float(_, float_line_item) = item { if float_line_item.needs_placement { @@ -2282,8 +2256,8 @@ fn inline_container_needs_strut( } /// A struct which takes care of computing [`ContentSizes`] for an [`InlineFormattingContext`]. -struct ContentSizesComputation<'a> { - layout_context: &'a LayoutContext<'a>, +struct ContentSizesComputation<'layout_data> { + layout_context: &'layout_data LayoutContext<'layout_data>, containing_block_writing_mode: WritingMode, paragraph: ContentSizes, current_line: ContentSizes, @@ -2297,7 +2271,7 @@ struct ContentSizesComputation<'a> { ending_inline_pbm_stack: Vec, } -impl<'a> ContentSizesComputation<'a> { +impl<'layout_data> ContentSizesComputation<'layout_data> { fn traverse(mut self, inline_formatting_context: &InlineFormattingContext) -> ContentSizes { for inline_item in inline_formatting_context.inline_items.iter() { self.process_item(&mut inline_item.borrow_mut(), inline_formatting_context); @@ -2452,7 +2426,7 @@ impl<'a> ContentSizesComputation<'a> { /// Compute the [`ContentSizes`] of the given [`InlineFormattingContext`]. fn compute( inline_formatting_context: &InlineFormattingContext, - layout_context: &'a LayoutContext, + layout_context: &'layout_data LayoutContext, containing_block_writing_mode: WritingMode, ) -> ContentSizes { Self { diff --git a/components/layout_2020/flow/inline/text_run.rs b/components/layout_2020/flow/inline/text_run.rs index 796d07793b7..0c50e9c76ce 100644 --- a/components/layout_2020/flow/inline/text_run.rs +++ b/components/layout_2020/flow/inline/text_run.rs @@ -27,7 +27,7 @@ use unicode_script::Script; use xi_unicode::linebreak_property; use super::line_breaker::LineBreaker; -use super::{FontKeyAndMetrics, InlineFormattingContextState}; +use super::{FontKeyAndMetrics, InlineFormattingContextLayout}; use crate::fragment_tree::BaseFragmentInfo; // These constants are the xi-unicode line breaking classes that are defined in @@ -136,7 +136,7 @@ impl TextRunSegment { &self, text_run: &TextRun, mut soft_wrap_policy: SegmentStartSoftWrapPolicy, - ifc: &mut InlineFormattingContextState, + ifc: &mut InlineFormattingContextLayout, ) { if self.break_at_start && soft_wrap_policy == SegmentStartSoftWrapPolicy::FollowLinebreaker { @@ -492,7 +492,7 @@ impl TextRun { results } - pub(super) fn layout_into_line_items(&self, ifc: &mut InlineFormattingContextState) { + pub(super) fn layout_into_line_items(&self, ifc: &mut InlineFormattingContextLayout) { if self.text_range.is_empty() { return; }