diff options
Diffstat (limited to 'components/layout_2020/flow/float.rs')
-rw-r--r-- | components/layout_2020/flow/float.rs | 247 |
1 files changed, 128 insertions, 119 deletions
diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs index 1de87a59eb2..d43fd0d1f81 100644 --- a/components/layout_2020/flow/float.rs +++ b/components/layout_2020/flow/float.rs @@ -8,15 +8,16 @@ use std::collections::VecDeque; use std::fmt::{Debug, Formatter, Result as FmtResult}; +use std::mem; use std::ops::Range; -use std::{f32, mem}; +use app_units::{Au, MAX_AU, MIN_AU}; use euclid::num::Zero; use serde::Serialize; use servo_arc::Arc; use style::computed_values::float::T as FloatProperty; use style::properties::ComputedValues; -use style::values::computed::{CSSPixelLength, Clear, Length}; +use style::values::computed::{Clear, Length}; use style::values::specified::text::TextDecorationLine; use crate::context::LayoutContext; @@ -24,7 +25,7 @@ use crate::dom::NodeExt; use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::formatting_contexts::IndependentFormattingContext; use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, CollapsedMargin, FloatFragment}; -use crate::geom::{LogicalRect, LogicalVec2}; +use crate::geom::{LogicalRect, LogicalSides, LogicalVec2}; use crate::positioned::PositioningContext; use crate::style_ext::{ComputedValuesExt, DisplayInside, PaddingBorderMargin}; use crate::ContainingBlock; @@ -47,7 +48,7 @@ pub struct ContainingBlockPositionInfo { /// containing block, excluding uncollapsed block start margins. Note that /// this does not include uncollapsed block start margins because we don't /// know the value of collapsed margins until we lay out children. - pub(crate) block_start: Length, + pub(crate) block_start: Au, /// Any uncollapsed block start margins that we have collected between the /// block start of the float containing independent block formatting context /// and this containing block, including for this containing block. @@ -55,17 +56,17 @@ pub struct ContainingBlockPositionInfo { /// The distance from the inline start position of the float containing /// independent formatting context and the inline start of this containing /// block. - pub inline_start: Length, + pub inline_start: Au, /// The offset from the inline start position of the float containing /// independent formatting context to the inline end of this containing /// block. - pub inline_end: Length, + pub inline_end: Au, } impl ContainingBlockPositionInfo { - pub fn new_with_inline_offsets(inline_start: Length, inline_end: Length) -> Self { + pub fn new_with_inline_offsets(inline_start: Au, inline_end: Au) -> Self { Self { - block_start: Length::zero(), + block_start: Au::zero(), block_start_margins_not_collapsed: CollapsedMargin::zero(), inline_start, inline_end, @@ -84,33 +85,37 @@ pub(crate) struct PlacementAmongFloats<'a> { /// The next band, needed to know the height of the last band in current_bands. next_band: FloatBand, /// The size of the object to place. - object_size: LogicalVec2<Length>, + object_size: LogicalVec2<Au>, /// The minimum position in the block direction for the placement. Objects should not /// be placed before this point. - ceiling: Length, + ceiling: Au, /// The inline position where the object would be if there were no floats. The object /// can be placed after it due to floats, but not before it. - min_inline_start: Length, + min_inline_start: Au, /// The maximum inline position that the object can attain when avoiding floats. - max_inline_end: Length, + max_inline_end: Au, } impl<'a> PlacementAmongFloats<'a> { pub(crate) fn new( float_context: &'a FloatContext, - ceiling: Length, - object_size: LogicalVec2<Length>, + ceiling: Au, + object_size: LogicalVec2<Au>, pbm: &PaddingBorderMargin, ) -> Self { - assert!(!ceiling.px().is_infinite()); - let mut current_band = float_context.bands.find(ceiling).unwrap(); - current_band.top = ceiling; - let current_bands = VecDeque::from([current_band]); - let next_band = float_context.bands.find_next(ceiling).unwrap(); + let mut ceiling_band = float_context.bands.find(ceiling).unwrap(); + let (current_bands, next_band) = if ceiling == MAX_AU { + (VecDeque::new(), ceiling_band) + } else { + ceiling_band.top = ceiling; + let current_bands = VecDeque::from([ceiling_band]); + let next_band = float_context.bands.find_next(ceiling).unwrap(); + (current_bands, next_band) + }; let min_inline_start = float_context.containing_block_info.inline_start + - pbm.margin.inline_start.auto_is(Length::zero); + pbm.margin.inline_start.auto_is(Length::zero).into(); let max_inline_end = (float_context.containing_block_info.inline_end - - pbm.margin.inline_end.auto_is(Length::zero)) + pbm.margin.inline_end.auto_is(Length::zero).into()) .max(min_inline_start + object_size.inline); PlacementAmongFloats { float_context, @@ -126,24 +131,27 @@ impl<'a> PlacementAmongFloats<'a> { /// The top of the bands under consideration. This is initially the ceiling provided /// during creation of this [`PlacementAmongFloats`], but may be larger if the top /// band is discarded. - fn top_of_bands(&self) -> Option<Length> { + fn top_of_bands(&self) -> Option<Au> { self.current_bands.front().map(|band| band.top) } /// The height of the bands under consideration. - fn current_bands_height(&self) -> Length { - if let Some(top) = self.top_of_bands() { - self.next_band.top - top + fn current_bands_height(&self) -> Au { + if self.next_band.top == MAX_AU { + // Treat MAX_AU as infinity. + MAX_AU } else { - assert!(self.next_band.top.px().is_infinite()); - self.next_band.top + let top = self + .top_of_bands() + .expect("Should have bands before reaching the end"); + self.next_band.top - top } } /// Add a single band to the bands under consideration and calculate the new /// [`PlacementAmongFloats::next_band`]. fn add_one_band(&mut self) { - assert!(!self.next_band.top.px().is_infinite()); + assert!(self.next_band.top != MAX_AU); self.current_bands.push_back(self.next_band); self.next_band = self .float_context @@ -162,7 +170,7 @@ impl<'a> PlacementAmongFloats<'a> { /// Find the start and end of the inline space provided by the current set of bands /// under consideration. - fn calculate_inline_start_and_end(&self) -> (Length, Length) { + fn calculate_inline_start_and_end(&self) -> (Au, Au) { let mut max_inline_start = self.min_inline_start; let mut min_inline_end = self.max_inline_end; for band in self.current_bands.iter() { @@ -177,12 +185,12 @@ impl<'a> PlacementAmongFloats<'a> { } /// Find the total inline size provided by the current set of bands under consideration. - fn calculate_viable_inline_size(&self) -> Length { + fn calculate_viable_inline_size(&self) -> Au { let (inline_start, inline_end) = self.calculate_inline_start_and_end(); inline_end - inline_start } - fn try_place_once(&mut self) -> Option<LogicalRect<Length>> { + fn try_place_once(&mut self) -> Option<LogicalRect<Au>> { assert!(!self.current_bands.is_empty()); self.accumulate_enough_bands_for_block_size(); let (inline_start, inline_end) = self.calculate_inline_start_and_end(); @@ -190,15 +198,14 @@ impl<'a> PlacementAmongFloats<'a> { if available_inline_size < self.object_size.inline { return None; } - let top = self.top_of_bands().unwrap(); Some(LogicalRect { start_corner: LogicalVec2 { inline: inline_start, - block: top, + block: self.top_of_bands().unwrap(), }, size: LogicalVec2 { inline: available_inline_size, - block: self.next_band.top - top, + block: self.current_bands_height(), }, }) } @@ -206,7 +213,7 @@ impl<'a> PlacementAmongFloats<'a> { /// Checks if we either have bands or we have gone past all of them. /// This is an invariant that should hold, otherwise we are in a broken state. fn has_bands_or_at_end(&self) -> bool { - !self.current_bands.is_empty() || self.next_band.top.px().is_infinite() + !self.current_bands.is_empty() || self.next_band.top == MAX_AU } fn pop_front_band_ensuring_has_bands_or_at_end(&mut self) { @@ -217,7 +224,7 @@ impl<'a> PlacementAmongFloats<'a> { } /// Run the placement algorithm for this [PlacementAmongFloats]. - pub(crate) fn place(&mut self) -> LogicalRect<Length> { + pub(crate) fn place(&mut self) -> LogicalRect<Au> { debug_assert!(self.has_bands_or_at_end()); while !self.current_bands.is_empty() { if let Some(result) = self.try_place_once() { @@ -239,7 +246,7 @@ impl<'a> PlacementAmongFloats<'a> { }, size: LogicalVec2 { inline: self.max_inline_end - self.min_inline_start, - block: Length::new(f32::INFINITY), + block: MAX_AU, }, } } @@ -252,8 +259,8 @@ impl<'a> PlacementAmongFloats<'a> { /// (with this [PlacementAmongFloats]). pub(crate) fn try_to_expand_for_auto_block_size( &mut self, - block_size_after_layout: Length, - size_from_placement: &LogicalVec2<Length>, + block_size_after_layout: Au, + size_from_placement: &LogicalVec2<Au>, ) -> bool { debug_assert!(self.has_bands_or_at_end()); debug_assert_eq!(size_from_placement.block, self.current_bands_height()); @@ -309,59 +316,59 @@ pub struct FloatContext { pub bands: FloatBandTree, /// The block-direction "ceiling" defined by the placement of other floated content of /// this FloatContext. No new floats can be placed at a lower block start than this value. - pub ceiling_from_floats: Length, + pub ceiling_from_floats: Au, /// The block-direction "ceiling" defined by the placement of non-floated content that /// precedes floated content in the document. Note that this may actually decrease as /// content is laid out in the case that content overflows its container. - pub ceiling_from_non_floats: Length, + pub ceiling_from_non_floats: Au, /// Details about the position of the containing block relative to the /// independent block formatting context that contains all of the floats /// this `FloatContext` positions. pub containing_block_info: ContainingBlockPositionInfo, /// The (logically) lowest margin edge of the last left float. - pub clear_left_position: Length, + pub clear_left_position: Au, /// The (logically) lowest margin edge of the last right float. - pub clear_right_position: Length, + pub clear_right_position: Au, } impl FloatContext { /// Returns a new float context representing a containing block with the given content /// inline-size. - pub fn new(max_inline_size: Length) -> Self { + pub fn new(max_inline_size: Au) -> Self { let mut bands = FloatBandTree::new(); bands = bands.insert(FloatBand { - top: Length::new(-f32::INFINITY), + top: MIN_AU, left: None, right: None, }); bands = bands.insert(FloatBand { - top: Length::new(f32::INFINITY), + top: MAX_AU, left: None, right: None, }); FloatContext { bands, - ceiling_from_floats: Length::zero(), - ceiling_from_non_floats: Length::zero(), + ceiling_from_floats: Au::zero(), + ceiling_from_non_floats: Au::zero(), containing_block_info: ContainingBlockPositionInfo::new_with_inline_offsets( - Length::zero(), + Au::zero(), max_inline_size, ), - clear_left_position: Length::zero(), - clear_right_position: Length::zero(), + clear_left_position: Au::zero(), + clear_right_position: Au::zero(), } } /// (Logically) lowers the ceiling to at least `new_ceiling` units. /// /// If the ceiling is already logically lower (i.e. larger) than this, does nothing. - pub fn set_ceiling_from_non_floats(&mut self, new_ceiling: Length) { + pub fn set_ceiling_from_non_floats(&mut self, new_ceiling: Au) { self.ceiling_from_non_floats = new_ceiling; } /// The "ceiling" used for float placement. This is the minimum block position value /// that should be used for placing any new float. - fn ceiling(&mut self) -> Length { + fn ceiling(&mut self) -> Au { self.ceiling_from_floats.max(self.ceiling_from_non_floats) } @@ -370,11 +377,7 @@ impl FloatContext { /// /// This should be used for placing inline elements and block formatting contexts so that they /// don't collide with floats. - pub(crate) fn place_object( - &self, - object: &PlacementInfo, - ceiling: Length, - ) -> LogicalVec2<Length> { + pub(crate) fn place_object(&self, object: &PlacementInfo, ceiling: Au) -> LogicalVec2<Au> { let ceiling = match object.clear { Clear::None => ceiling, Clear::Left => ceiling.max(self.clear_left_position), @@ -388,7 +391,7 @@ impl FloatContext { let mut first_band = self.bands.find(ceiling).unwrap(); while !first_band.object_fits(&object, &self.containing_block_info) { let next_band = self.bands.find_next(first_band.top).unwrap(); - if next_band.top.px().is_infinite() { + if next_band.top == MAX_AU { break; } first_band = next_band; @@ -420,7 +423,7 @@ impl FloatContext { } /// Places a new float and adds it to the list. Returns the start corner of its margin box. - pub fn add_float(&mut self, new_float: &PlacementInfo) -> LogicalVec2<Length> { + pub fn add_float(&mut self, new_float: &PlacementInfo) -> LogicalVec2<Au> { // Place the float. let ceiling = self.ceiling(); let new_float_origin = self.place_object(&new_float, ceiling); @@ -436,8 +439,8 @@ impl FloatContext { // so negative that it's placed completely above the current float ceiling, then // we should position it as if it had zero block size. size: LogicalVec2 { - inline: new_float.size.inline.max(CSSPixelLength::zero()), - block: new_float.size.block.max(CSSPixelLength::zero()), + inline: new_float.size.inline.max(Au::zero()), + block: new_float.size.block.max(Au::zero()), }, }; @@ -476,17 +479,25 @@ impl FloatContext { // CSS 2.1 § 9.5.1 rule 6: The outer top of a floating box may not be higher than the outer // top of any block or floated box generated by an element earlier in the source document. - self.ceiling_from_floats - .max_assign(new_float_rect.start_corner.block); + max_assign_au( + &mut self.ceiling_from_floats, + new_float_rect.start_corner.block, + ); + new_float_rect.start_corner } } +fn max_assign_au(current: &mut Au, other: Au) { + let max_value = std::cmp::max(current.0, other.0); + *current = Au(max_value); +} + /// Information needed to place an object so that it doesn't collide with existing floats. #[derive(Clone, Debug)] pub struct PlacementInfo { /// The *margin* box size of the object. - pub size: LogicalVec2<Length>, + pub size: LogicalVec2<Au>, /// Whether the object is (logically) aligned to the left or right. pub side: FloatSide, /// Which side or sides to clear floats on. @@ -507,17 +518,17 @@ pub enum FloatSide { #[derive(Clone, Copy, Debug, PartialEq)] pub struct FloatBand { /// The logical vertical position of the top of this band. - pub top: Length, + pub top: Au, /// The distance from the left edge of the block formatting context to the first legal /// (logically) horizontal position where floats may be placed. If `None`, there are no floats /// to the left; distinguishing between the cases of "a zero-width float is present" and "no /// floats at all are present" is necessary to, for example, clear past zero-width floats. - pub left: Option<Length>, + pub left: Option<Au>, /// The distance from the *left* edge of the block formatting context to the first legal /// (logically) horizontal position where floats may be placed. If `None`, there are no floats /// to the right; distinguishing between the cases of "a zero-width float is present" and "no /// floats at all are present" is necessary to, for example, clear past zero-width floats. - pub right: Option<Length>, + pub right: Option<Au>, } impl FloatSide { @@ -624,24 +635,19 @@ impl FloatBandTree { } /// Returns the first band whose top is less than or equal to the given `block_position`. - pub fn find(&self, block_position: Length) -> Option<FloatBand> { + pub fn find(&self, block_position: Au) -> Option<FloatBand> { self.root.find(block_position) } /// Returns the first band whose top is strictly greater than to the given `block_position`. - pub fn find_next(&self, block_position: Length) -> Option<FloatBand> { + pub fn find_next(&self, block_position: Au) -> Option<FloatBand> { self.root.find_next(block_position) } /// Sets the side values of all bands within the given half-open range to be at least /// `new_value`. #[must_use] - pub fn set_range( - &self, - range: &Range<Length>, - side: FloatSide, - new_value: Length, - ) -> FloatBandTree { + pub fn set_range(&self, range: &Range<Au>, side: FloatSide, new_value: Au) -> FloatBandTree { FloatBandTree { root: FloatBandLink( self.root @@ -674,22 +680,21 @@ impl FloatBandNode { /// Sets the side values of all bands within the given half-open range to be at least /// `new_value`. - fn set_range( - &self, - range: &Range<Length>, - side: FloatSide, - new_value: Length, - ) -> Arc<FloatBandNode> { + fn set_range(&self, range: &Range<Au>, side: FloatSide, new_value: Au) -> Arc<FloatBandNode> { let mut new_band = self.band.clone(); if self.band.top >= range.start && self.band.top < range.end { match side { - FloatSide::Left => match new_band.left { - None => new_band.left = Some(new_value), - Some(ref mut old_value) => *old_value = old_value.max(new_value), + FloatSide::Left => { + new_band.left = match new_band.left { + Some(old_value) => Some(std::cmp::max(old_value, new_value)), + None => Some(new_value), + }; }, - FloatSide::Right => match new_band.right { - None => new_band.right = Some(new_value), - Some(ref mut old_value) => *old_value = old_value.min(new_value), + FloatSide::Right => { + new_band.right = match new_band.right { + Some(old_value) => Some(std::cmp::min(old_value, new_value)), + None => Some(new_value), + }; }, } } @@ -721,7 +726,7 @@ impl FloatBandNode { impl FloatBandLink { /// Returns the first band whose top is less than or equal to the given `block_position`. - fn find(&self, block_position: Length) -> Option<FloatBand> { + fn find(&self, block_position: Au) -> Option<FloatBand> { let this = match self.0 { None => return None, Some(ref node) => node, @@ -741,7 +746,7 @@ impl FloatBandLink { } /// Returns the first band whose top is strictly greater than the given `block_position`. - fn find_next(&self, block_position: Length) -> Option<FloatBand> { + fn find_next(&self, block_position: Au) -> Option<FloatBand> { let this = match self.0 { None => return None, Some(ref node) => node, @@ -886,7 +891,7 @@ impl FloatBox { // Margin is computed this way regardless of whether the element is replaced // or non-replaced. let pbm = style.padding_border_margin(containing_block); - let margin = pbm.margin.auto_is(|| Length::zero()); + let margin = pbm.margin.auto_is(Length::zero); let pbm_sums = &(&pbm.padding + &pbm.border) + &margin; let (content_size, children); @@ -993,18 +998,18 @@ pub(crate) struct SequentialLayoutState { /// This is often, but not always, the same as the float ceiling. The float ceiling can be lower /// than this value because this value is calculated based on in-flow boxes only, while /// out-of-flow floats can affect the ceiling as well (see CSS 2.1 § 9.5.1 rule 6). - pub(crate) bfc_relative_block_position: Length, + pub(crate) bfc_relative_block_position: Au, /// Any collapsible margins that we've encountered after `bfc_relative_block_position`. pub(crate) current_margin: CollapsedMargin, } impl SequentialLayoutState { /// Creates a new empty `SequentialLayoutState`. - pub(crate) fn new(max_inline_size: Length) -> SequentialLayoutState { + pub(crate) fn new(max_inline_size: Au) -> SequentialLayoutState { SequentialLayoutState { floats: FloatContext::new(max_inline_size), current_margin: CollapsedMargin::zero(), - bfc_relative_block_position: Length::zero(), + bfc_relative_block_position: Au::zero(), } } @@ -1014,7 +1019,7 @@ impl SequentialLayoutState { /// [`SequentialLayoutState`] after processing its overflowing content. /// /// Floats may not be placed higher than the current block position. - pub(crate) fn advance_block_position(&mut self, block_distance: Length) { + pub(crate) fn advance_block_position(&mut self, block_distance: Au) { self.bfc_relative_block_position += block_distance; self.floats .set_ceiling_from_non_floats(self.bfc_relative_block_position); @@ -1032,8 +1037,8 @@ impl SequentialLayoutState { /// Return the current block position in the float containing block formatting /// context and any uncollapsed block margins. - pub(crate) fn current_block_position_including_margins(&self) -> Length { - self.bfc_relative_block_position + self.current_margin.solve() + pub(crate) fn current_block_position_including_margins(&self) -> Au { + self.bfc_relative_block_position + self.current_margin.solve().into() } /// Collapses margins, moving the block position down by the collapsed value of `current_margin` @@ -1042,29 +1047,29 @@ impl SequentialLayoutState { /// Call this method before laying out children when it is known that the start margin of the /// current fragment can't collapse with the margins of any of its children. pub(crate) fn collapse_margins(&mut self) { - self.advance_block_position(self.current_margin.solve()); + self.advance_block_position(self.current_margin.solve().into()); self.current_margin = CollapsedMargin::zero(); } /// Computes the position of the block-start border edge of an element /// with the provided `block_start_margin`, assuming no clearance. - pub(crate) fn position_without_clearance( - &self, - block_start_margin: &CollapsedMargin, - ) -> Length { + pub(crate) fn position_without_clearance(&self, block_start_margin: &CollapsedMargin) -> Au { // Adjoin `current_margin` and `block_start_margin` since there is no clearance. - self.bfc_relative_block_position + self.current_margin.adjoin(&block_start_margin).solve() + self.bfc_relative_block_position + + self.current_margin + .adjoin(&block_start_margin) + .solve() + .into() } /// Computes the position of the block-start border edge of an element /// with the provided `block_start_margin`, assuming a clearance of 0px. - pub(crate) fn position_with_zero_clearance( - &self, - block_start_margin: &CollapsedMargin, - ) -> Length { + pub(crate) fn position_with_zero_clearance(&self, block_start_margin: &CollapsedMargin) -> Au { // Clearance prevents `current_margin` and `block_start_margin` from being // adjoining, so we need to solve them separately and then sum. - self.bfc_relative_block_position + self.current_margin.solve() + block_start_margin.solve() + self.bfc_relative_block_position + + self.current_margin.solve().into() + + block_start_margin.solve().into() } /// Returns the block-end outer edge of the lowest float that is to be cleared (if any) @@ -1073,7 +1078,7 @@ impl SequentialLayoutState { &self, clear: Clear, block_start_margin: &CollapsedMargin, - ) -> Option<Length> { + ) -> Option<Au> { if clear == Clear::None { return None; } @@ -1112,7 +1117,7 @@ impl SequentialLayoutState { &self, clear: Clear, block_start_margin: &CollapsedMargin, - ) -> Option<Length> { + ) -> Option<Au> { return self .calculate_clear_position(clear, &block_start_margin) .map(|offset| offset - self.position_with_zero_clearance(&block_start_margin)); @@ -1131,8 +1136,8 @@ impl SequentialLayoutState { clear: Clear, block_start_margin: &CollapsedMargin, pbm: &PaddingBorderMargin, - object_size: LogicalVec2<Length>, - ) -> (Option<Length>, LogicalRect<Length>) { + object_size: LogicalVec2<Au>, + ) -> (Option<Au>, LogicalRect<Au>) { // First compute the clear position required by the 'clear' property. // The code below may then add extra clearance when the element can't fit // next to floats not covered by 'clear'. @@ -1157,12 +1162,13 @@ impl SequentialLayoutState { } /// Get the offset of the current containing block and any uncollapsed margins. - pub(crate) fn current_containing_block_offset(&self) -> CSSPixelLength { + pub(crate) fn current_containing_block_offset(&self) -> Au { self.floats.containing_block_info.block_start + self.floats .containing_block_info .block_start_margins_not_collapsed .solve() + .into() } /// This function places a Fragment that has been created for a FloatBox. @@ -1170,30 +1176,33 @@ impl SequentialLayoutState { &mut self, box_fragment: &mut BoxFragment, margins_collapsing_with_parent_containing_block: CollapsedMargin, - block_offset_from_containing_block_top: Length, + block_offset_from_containing_block_top: Au, ) { let block_start_of_containing_block_in_bfc = self.floats.containing_block_info.block_start + self.floats .containing_block_info .block_start_margins_not_collapsed .adjoin(&margins_collapsing_with_parent_containing_block) - .solve(); + .solve() + .into(); self.floats.set_ceiling_from_non_floats( block_start_of_containing_block_in_bfc + block_offset_from_containing_block_top, ); let pbm_sums = &(&box_fragment.padding + &box_fragment.border) + &box_fragment.margin; + let content_rect: LogicalRect<Au> = box_fragment.content_rect.clone().into(); + let pbm_sums_all: LogicalSides<Au> = pbm_sums.map(|length| (*length).into()); let margin_box_start_corner = self.floats.add_float(&PlacementInfo { - size: &box_fragment.content_rect.size + &pbm_sums.sum(), + size: &content_rect.size + &pbm_sums_all.sum(), side: FloatSide::from_style(&box_fragment.style).expect("Float box wasn't floated!"), clear: box_fragment.style.get_box().clear, }); // This is the position of the float in the float-containing block formatting context. We add the // existing start corner here because we may have already gotten some relative positioning offset. - let new_position_in_bfc = &(&margin_box_start_corner + &pbm_sums.start_offset()) + - &box_fragment.content_rect.start_corner; + let new_position_in_bfc = + &(&margin_box_start_corner + &pbm_sums_all.start_offset()) + &content_rect.start_corner; // This is the position of the float relative to the containing block start. let new_position_in_containing_block = LogicalVec2 { @@ -1201,6 +1210,6 @@ impl SequentialLayoutState { block: new_position_in_bfc.block - block_start_of_containing_block_in_bfc, }; - box_fragment.content_rect.start_corner = new_position_in_containing_block; + box_fragment.content_rect.start_corner = new_position_in_containing_block.into(); } } |