tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

Fix inset being incorrectly applied to `position:relative` flex items when both insets were set in a given axis (#348)

* Fix application of inset of relatively position flex nodes when both top and bottom or both left and right are specified

* Tests for relative inset conflicts

* Update changelog

ec371711989b7f4d870d91bea4b66bdd94b45c9e · por Nico Burns · (hace 3 años) · padre ab747b81e · ver el árbol en este commit

Delta semántico · 14

benches/generated/flex_column_relative_all_sides.rs

benches/generated/flex_row_relative_all_sides.rs

benches/generated/grid_relative_all_sides.rs

benches/generated/mod.rs

src/compute/flexbox.rs

tests/generated/flex_column_relative_all_sides.rs

tests/generated/flex_row_relative_all_sides.rs

tests/generated/grid_relative_all_sides.rs

tests/generated/mod.rs

13 archivos · +295 −2

diff --git a/RELEASES.md b/RELEASES.md
index 419cb094c..8861aaab4 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -16,6 +16,7 @@
 - Aspect ratio is now applied correctly in many circumstances
 - Absolutely positioned items now apply margins correctly
 - Min/max size are now applied correctly
+- Inset applied incorrectly to relatively positioned flexbox children when both `top` and `bottom` or `left` and `right` were specified (#348)
 
 ### Removed
 
diff --git a/benches/generated/flex_column_relative_all_sides.rs b/benches/generated/flex_column_relative_all_sides.rs
new file mode 100644
index 000000000..35a57b7cb
--- /dev/null
+++ b/benches/generated/flex_column_relative_all_sides.rs
@@ -0,0 +1,31 @@
+pub fn compute() {
+    #[allow(unused_imports)]
+    use taffy::prelude::*;
+    let mut taffy = taffy::Taffy::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+            inset: taffy::geometry::Rect {
+                left: taffy::style::LengthPercentageAuto::Points(10f32),
+                right: taffy::style::LengthPercentageAuto::Points(10f32),
+                top: taffy::style::LengthPercentageAuto::Points(10f32),
+                bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                flex_direction: taffy::style::FlexDirection::Column,
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Points(100f32),
+                    height: taffy::style::Dimension::Points(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/flex_row_relative_all_sides.rs b/benches/generated/flex_row_relative_all_sides.rs
new file mode 100644
index 000000000..b95cbfeb0
--- /dev/null
+++ b/benches/generated/flex_row_relative_all_sides.rs
@@ -0,0 +1,30 @@
+pub fn compute() {
+    #[allow(unused_imports)]
+    use taffy::prelude::*;
+    let mut taffy = taffy::Taffy::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+            inset: taffy::geometry::Rect {
+                left: taffy::style::LengthPercentageAuto::Points(10f32),
+                right: taffy::style::LengthPercentageAuto::Points(10f32),
+                top: taffy::style::LengthPercentageAuto::Points(10f32),
+                bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Points(100f32),
+                    height: taffy::style::Dimension::Points(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/grid_relative_all_sides.rs b/benches/generated/grid_relative_all_sides.rs
new file mode 100644
index 000000000..81a26bc18
--- /dev/null
+++ b/benches/generated/grid_relative_all_sides.rs
@@ -0,0 +1,31 @@
+pub fn compute() {
+    #[allow(unused_imports)]
+    use taffy::prelude::*;
+    let mut taffy = taffy::Taffy::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+            inset: taffy::geometry::Rect {
+                left: taffy::style::LengthPercentageAuto::Points(10f32),
+                right: taffy::style::LengthPercentageAuto::Points(10f32),
+                top: taffy::style::LengthPercentageAuto::Points(10f32),
+                bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                display: taffy::style::Display::Grid,
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Points(100f32),
+                    height: taffy::style::Dimension::Points(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/mod.rs b/benches/generated/mod.rs
index 6dc849d6c..3f469d704 100644
--- a/benches/generated/mod.rs
+++ b/benches/generated/mod.rs
@@ -233,6 +233,7 @@ mod flex_basis_smaller_then_content_with_flex_grow_very_large_size;
 mod flex_basis_unconstraint_column;
 mod flex_basis_unconstraint_row;
 mod flex_basis_zero_undefined_main_size;
+mod flex_column_relative_all_sides;
 mod flex_direction_column;
 mod flex_direction_column_no_height;
 mod flex_direction_column_reverse;
@@ -256,6 +257,7 @@ mod flex_grow_within_constrained_min_max_column;
 mod flex_grow_within_constrained_min_row;
 mod flex_grow_within_max_width;
 mod flex_root_ignored;
+mod flex_row_relative_all_sides;
 mod flex_shrink_by_outer_margin_with_max_size;
 mod flex_shrink_flex_grow_child_flex_shrink_other_child;
 mod flex_shrink_flex_grow_row;
@@ -607,6 +609,8 @@ mod grid_placement_auto_negative;
 #[cfg(feature = "grid")]
 mod grid_placement_definite_in_secondary_axis_with_fully_definite_negative;
 #[cfg(feature = "grid")]
+mod grid_relative_all_sides;
+#[cfg(feature = "grid")]
 mod grid_relayout_vertical_text;
 #[cfg(feature = "grid")]
 mod grid_repeat_integer;
@@ -960,6 +964,7 @@ fn benchmark(c: &mut Criterion) {
             flex_basis_unconstraint_column::compute();
             flex_basis_unconstraint_row::compute();
             flex_basis_zero_undefined_main_size::compute();
+            flex_column_relative_all_sides::compute();
             flex_direction_column::compute();
             flex_direction_column_no_height::compute();
             flex_direction_column_reverse::compute();
@@ -983,6 +988,7 @@ fn benchmark(c: &mut Criterion) {
             flex_grow_within_constrained_min_row::compute();
             flex_grow_within_max_width::compute();
             flex_root_ignored::compute();
+            flex_row_relative_all_sides::compute();
             flex_shrink_by_outer_margin_with_max_size::compute();
             flex_shrink_flex_grow_child_flex_shrink_other_child::compute();
             flex_shrink_flex_grow_row::compute();
@@ -1334,6 +1340,8 @@ fn benchmark(c: &mut Criterion) {
             #[cfg(feature = "grid")]
             grid_placement_definite_in_secondary_axis_with_fully_definite_negative::compute();
             #[cfg(feature = "grid")]
+            grid_relative_all_sides::compute();
+            #[cfg(feature = "grid")]
             grid_relayout_vertical_text::compute();
             #[cfg(feature = "grid")]
             grid_repeat_integer::compute();
diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index f4cee05f2..b0379c935 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -1523,13 +1523,13 @@ fn calculate_flex_item(
     let offset_main = *total_offset_main
         + item.offset_main
         + item.margin.main_start(direction)
-        + (item.inset.main_start(direction).unwrap_or(0.0) - item.inset.main_end(direction).unwrap_or(0.0));
+        + (item.inset.main_start(direction).or(item.inset.main_end(direction).map(|pos| -pos)).unwrap_or(0.0));
 
     let offset_cross = total_offset_cross
         + item.offset_cross
         + line_offset_cross
         + item.margin.cross_start(direction)
-        + (item.inset.cross_start(direction).unwrap_or(0.0) - item.inset.cross_end(direction).unwrap_or(0.0));
+        + (item.inset.cross_start(direction).or(item.inset.cross_end(direction).map(|pos| -pos)).unwrap_or(0.0));
 
     if direction.is_row() {
         let baseline_offset_cross = total_offset_cross + item.offset_cross + item.margin.cross_start(direction);
diff --git a/test_fixtures/flex_column_relative_all_sides.html b/test_fixtures/flex_column_relative_all_sides.html
new file mode 100644
index 000000000..aa5a6b2a9
--- /dev/null
+++ b/test_fixtures/flex_column_relative_all_sides.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <script src="../scripts/gentest/test_helper.js"></script>
+  <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+  <title>
+    Test description
+  </title>
+<head/>
+<body>
+
+<div id="test-root" style="height: 100px; width: 100px;flex-direction: column;">
+  <div style="width: 40px;top: 10px;bottom:10px;left: 10px;right: 10px"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/flex_row_relative_all_sides.html b/test_fixtures/flex_row_relative_all_sides.html
new file mode 100644
index 000000000..ea8f8b9fd
--- /dev/null
+++ b/test_fixtures/flex_row_relative_all_sides.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <script src="../scripts/gentest/test_helper.js"></script>
+  <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+  <title>
+    Test description
+  </title>
+<head/>
+<body>
+
+<div id="test-root" style="height: 100px; width: 100px;">
+  <div style="width: 40px;top: 10px;bottom:10px;left: 10px;right: 10px"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/grid_relative_all_sides.html b/test_fixtures/grid_relative_all_sides.html
new file mode 100644
index 000000000..31388558c
--- /dev/null
+++ b/test_fixtures/grid_relative_all_sides.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <script src="../scripts/gentest/test_helper.js"></script>
+  <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+  <title>
+    Test description
+  </title>
+<head/>
+<body>
+
+<div id="test-root" style="display: grid;height: 100px; width: 100px;">
+  <div style="width: 40px;top: 10px;bottom:10px;left: 10px;right: 10px"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/tests/generated/flex_column_relative_all_sides.rs b/tests/generated/flex_column_relative_all_sides.rs
new file mode 100644
index 000000000..5a2891e6d
--- /dev/null
+++ b/tests/generated/flex_column_relative_all_sides.rs
@@ -0,0 +1,46 @@
+#[test]
+fn flex_column_relative_all_sides() {
+    use slotmap::Key;
+    #[allow(unused_imports)]
+    use taffy::{layout::Layout, prelude::*};
+    let mut taffy = taffy::Taffy::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+            inset: taffy::geometry::Rect {
+                left: taffy::style::LengthPercentageAuto::Points(10f32),
+                right: taffy::style::LengthPercentageAuto::Points(10f32),
+                top: taffy::style::LengthPercentageAuto::Points(10f32),
+                bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                flex_direction: taffy::style::FlexDirection::Column,
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Points(100f32),
+                    height: taffy::style::Dimension::Points(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+    println!("\nComputed tree:");
+    taffy::debug::print_tree(&taffy, node);
+    println!();
+    let Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.y);
+    let Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, size.width);
+    assert_eq!(size.height, 0f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, size.height);
+    assert_eq!(location.x, 10f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.x);
+    assert_eq!(location.y, 10f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.y);
+}
diff --git a/tests/generated/flex_row_relative_all_sides.rs b/tests/generated/flex_row_relative_all_sides.rs
new file mode 100644
index 000000000..69bcb920e
--- /dev/null
+++ b/tests/generated/flex_row_relative_all_sides.rs
@@ -0,0 +1,45 @@
+#[test]
+fn flex_row_relative_all_sides() {
+    use slotmap::Key;
+    #[allow(unused_imports)]
+    use taffy::{layout::Layout, prelude::*};
+    let mut taffy = taffy::Taffy::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+            inset: taffy::geometry::Rect {
+                left: taffy::style::LengthPercentageAuto::Points(10f32),
+                right: taffy::style::LengthPercentageAuto::Points(10f32),
+                top: taffy::style::LengthPercentageAuto::Points(10f32),
+                bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Points(100f32),
+                    height: taffy::style::Dimension::Points(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+    println!("\nComputed tree:");
+    taffy::debug::print_tree(&taffy, node);
+    println!();
+    let Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.y);
+    let Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 100f32, size.height);
+    assert_eq!(location.x, 10f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.x);
+    assert_eq!(location.y, 10f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.y);
+}
diff --git a/tests/generated/grid_relative_all_sides.rs b/tests/generated/grid_relative_all_sides.rs
new file mode 100644
index 000000000..a956627f3
--- /dev/null
+++ b/tests/generated/grid_relative_all_sides.rs
@@ -0,0 +1,46 @@
+#[test]
+fn grid_relative_all_sides() {
+    use slotmap::Key;
+    #[allow(unused_imports)]
+    use taffy::{layout::Layout, prelude::*};
+    let mut taffy = taffy::Taffy::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size { width: taffy::style::Dimension::Points(40f32), height: auto() },
+            inset: taffy::geometry::Rect {
+                left: taffy::style::LengthPercentageAuto::Points(10f32),
+                right: taffy::style::LengthPercentageAuto::Points(10f32),
+                top: taffy::style::LengthPercentageAuto::Points(10f32),
+                bottom: taffy::style::LengthPercentageAuto::Points(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                display: taffy::style::Display::Grid,
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Points(100f32),
+                    height: taffy::style::Dimension::Points(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+    println!("\nComputed tree:");
+    taffy::debug::print_tree(&taffy, node);
+    println!();
+    let Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node.data(), 0f32, location.y);
+    let Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 100f32, size.height);
+    assert_eq!(location.x, 10f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.x);
+    assert_eq!(location.y, 10f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, location.y);
+}
diff --git a/tests/generated/mod.rs b/tests/generated/mod.rs
index 8ad7c04e8..d347ce174 100644
--- a/tests/generated/mod.rs
+++ b/tests/generated/mod.rs
@@ -232,6 +232,7 @@ mod flex_basis_smaller_then_content_with_flex_grow_very_large_size;
 mod flex_basis_unconstraint_column;
 mod flex_basis_unconstraint_row;
 mod flex_basis_zero_undefined_main_size;
+mod flex_column_relative_all_sides;
 mod flex_direction_column;
 mod flex_direction_column_no_height;
 mod flex_direction_column_reverse;
@@ -255,6 +256,7 @@ mod flex_grow_within_constrained_min_max_column;
 mod flex_grow_within_constrained_min_row;
 mod flex_grow_within_max_width;
 mod flex_root_ignored;
+mod flex_row_relative_all_sides;
 mod flex_shrink_by_outer_margin_with_max_size;
 mod flex_shrink_flex_grow_child_flex_shrink_other_child;
 mod flex_shrink_flex_grow_row;
@@ -606,6 +608,8 @@ mod grid_placement_auto_negative;
 #[cfg(feature = "grid")]
 mod grid_placement_definite_in_secondary_axis_with_fully_definite_negative;
 #[cfg(feature = "grid")]
+mod grid_relative_all_sides;
+#[cfg(feature = "grid")]
 mod grid_relayout_vertical_text;
 #[cfg(feature = "grid")]
 mod grid_repeat_integer;