diff --git a/src/compute/block.rs b/src/compute/block.rs index 0e5991113..74e81ecc5 100644 --- a/src/compute/block.rs +++ b/src/compute/block.rs @@ -172,6 +172,19 @@ impl BlockContext<'_> { pos } + /// Snapshot the current float placement state. The snapshot can be passed to + /// [`restore_float_snapshot`](Self::restore_float_snapshot) to undo the placement of any + /// floats placed after the snapshot was taken (e.g. to speculatively place floats). + pub fn float_snapshot(&self) -> FloatContext { + self.bfc.float_context.clone() + } + + /// Restore a float placement state snapshot taken with + /// [`float_snapshot`](Self::float_snapshot) + pub fn restore_float_snapshot(&mut self, snapshot: FloatContext) { + self.bfc.float_context = snapshot; + } + /// Search a space suitable for laying out non-floated content into pub fn find_content_slot(&self, min_y: f32, height: f32, clear: Clear, after: Option) -> ContentSlot { let mut slot = self.bfc.float_context.find_content_slot( diff --git a/tests/hand_written/floats.rs b/tests/hand_written/floats.rs index e0354173e..a86deb907 100644 --- a/tests/hand_written/floats.rs +++ b/tests/hand_written/floats.rs @@ -150,6 +150,37 @@ fn float_beside_existing_float_moves_down_instead_of_overflowing() { assert_eq!(taffy.layout(left2).unwrap().location, Point { x: 0.0, y: 100.0 }); } +/// Regression test for +/// +/// A zero-height float takes up no space, but still affects the placement of content +/// whose vertical extent crosses its position. +#[test] +fn zero_height_float_affects_crossing_content() { + let mut taffy = new_test_tree(); + + let f1 = taffy.new_leaf(float_block(10.0, 30.0, Float::Left)).unwrap(); + let zero = + taffy.new_leaf(Style { clear: taffy::style::Clear::Left, ..float_block(100.0, 0.0, Float::Left) }).unwrap(); + // A BFC box whose vertical extent would cross the zero-height float: it doesn't fit + // beside the float's 100px inset, so it must be placed below it + let bfc = taffy + .new_leaf(Style { + display: Display::Block, + overflow: Point { x: Overflow::Hidden, y: Overflow::Hidden }, + size: Size { width: length(450.0), height: length(40.0) }, + ..Default::default() + }) + .unwrap(); + + let root = taffy.new_with_children(root_style(500.0), &[f1, zero, bfc]).unwrap(); + + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + + assert_eq!(taffy.layout(f1).unwrap().location, Point { x: 0.0, y: 0.0 }); + assert_eq!(taffy.layout(zero).unwrap().location, Point { x: 0.0, y: 30.0 }); + assert_eq!(taffy.layout(bfc).unwrap().location, Point { x: 0.0, y: 30.0 }); +} + /// Regression test for /// /// A box establishing a new block formatting context must not overlap floats over its full @@ -190,34 +221,3 @@ fn bfc_avoids_floats_over_full_height() { // The BFC box starts below the float (y = 30 + 30 = 60), not beside the spacer assert_eq!(taffy.layout(bfc).unwrap().location, Point { x: 0.0, y: 60.0 }); } - -/// Regression test for -/// -/// A zero-height float takes up no space, but still affects the placement of content -/// whose vertical extent crosses its position. -#[test] -fn zero_height_float_affects_crossing_content() { - let mut taffy = new_test_tree(); - - let f1 = taffy.new_leaf(float_block(10.0, 30.0, Float::Left)).unwrap(); - let zero = - taffy.new_leaf(Style { clear: taffy::style::Clear::Left, ..float_block(100.0, 0.0, Float::Left) }).unwrap(); - // A BFC box whose vertical extent would cross the zero-height float: it doesn't fit - // beside the float's 100px inset, so it must be placed below it - let bfc = taffy - .new_leaf(Style { - display: Display::Block, - overflow: Point { x: Overflow::Hidden, y: Overflow::Hidden }, - size: Size { width: length(450.0), height: length(40.0) }, - ..Default::default() - }) - .unwrap(); - - let root = taffy.new_with_children(root_style(500.0), &[f1, zero, bfc]).unwrap(); - - taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); - - assert_eq!(taffy.layout(f1).unwrap().location, Point { x: 0.0, y: 0.0 }); - assert_eq!(taffy.layout(zero).unwrap().location, Point { x: 0.0, y: 30.0 }); - assert_eq!(taffy.layout(bfc).unwrap().location, Point { x: 0.0, y: 30.0 }); -}