tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

Fix flex line cross-size determination (#690)

b746ac4f346dde8a2b6f85d3a428c02a2342f099 · por Nico Burns · (hace 2 años) · padre e6255f79a · ver el árbol en este commit

Delta semántico · 13

src/compute/flexbox.rs

tests/generated/flex/align_content_space_around_wrapped_single.rs

tests/generated/flex/align_content_space_between_wrapped_single.rs

tests/generated/flex/align_content_space_evenly_wrapped_single.rs

tests/generated/flex/align_content_stretch_row_wrap.rs

10 archivos · +827 −38

diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index b9cf9d044..371e05afd 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -1412,34 +1412,11 @@ fn calculate_children_base_lines(
 /// # [9.4. Cross Size Determination](https://www.w3.org/TR/css-flexbox-1/#cross-sizing)
 ///
 /// - [**Calculate the cross size of each flex line**](https://www.w3.org/TR/css-flexbox-1/#algo-cross-line).
-///
-///     If the flex container is single-line and has a definite cross size, the cross size of the flex line is the flex container’s inner cross size.
-///
-///     Otherwise, for each flex line:
-///
-///     1. Collect all the flex items whose inline-axis is parallel to the main-axis, whose align-self is baseline, and whose cross-axis margins are both non-auto.
-///         Find the largest of the distances between each item’s baseline and its hypothetical outer cross-start edge,
-///         and the largest of the distances between each item’s baseline and its hypothetical outer cross-end edge, and sum these two values.
-///
-///     2. Among all the items not collected by the previous step, find the largest outer hypothetical cross size.
-///
-///     3. The used cross-size of the flex line is the largest of the numbers found in the previous two steps and zero.
-///
-///         If the flex container is single-line, then clamp the line’s cross-size to be within the container’s computed min and max cross sizes.
-///         **Note that if CSS 2.1’s definition of min/max-width/height applied more generally, this behavior would fall out automatically**.
 #[inline]
 fn calculate_cross_size(flex_lines: &mut [FlexLine], node_size: Size<Option<f32>>, constants: &AlgoConstants) {
-    // Note: AlignContent::SpaceEvenly and AlignContent::SpaceAround behave like AlignContent::Stretch when there is only
-    // a single flex line in the container. See: https://www.w3.org/TR/css-flexbox-1/#align-content-property
-    // Also: align_content is ignored entirely (and thus behaves like Stretch) when `flex_wrap` is set to `nowrap`.
-    if flex_lines.len() == 1
-        && node_size.cross(constants.dir).is_some()
-        && (!constants.is_wrap
-            || matches!(
-                constants.align_content,
-                AlignContent::Stretch | AlignContent::SpaceEvenly | AlignContent::SpaceAround
-            ))
-    {
+    // If the flex container is single-line and has a definite cross size,
+    // the cross size of the flex line is the flex container’s inner cross size.
+    if !constants.is_wrap && node_size.cross(constants.dir).is_some() {
         let cross_axis_padding_border = constants.content_box_inset.cross_axis_sum(constants.dir);
         let cross_min_size = constants.min_size.cross(constants.dir);
         let cross_max_size = constants.max_size.cross(constants.dir);
@@ -1450,19 +1427,20 @@ fn calculate_cross_size(flex_lines: &mut [FlexLine], node_size: Size<Option<f32>
             .maybe_max(0.0)
             .unwrap_or(0.0);
     } else {
-        for line in flex_lines.iter_mut() {
-            //    1. Collect all the flex items whose inline-axis is parallel to the main-axis, whose
-            //       align-self is baseline, and whose cross-axis margins are both non-auto. Find the
-            //       largest of the distances between each item’s baseline and its hypothetical outer
-            //       cross-start edge, and the largest of the distances between each item’s baseline
-            //       and its hypothetical outer cross-end edge, and sum these two values.
-
-            //    2. Among all the items not collected by the previous step, find the largest
-            //       outer hypothetical cross size.
+        // Otherwise, for each flex line:
+        //
+        //    1. Collect all the flex items whose inline-axis is parallel to the main-axis, whose
+        //       align-self is baseline, and whose cross-axis margins are both non-auto. Find the
+        //       largest of the distances between each item’s baseline and its hypothetical outer
+        //       cross-start edge, and the largest of the distances between each item’s baseline
+        //       and its hypothetical outer cross-end edge, and sum these two values.
 
-            //    3. The used cross-size of the flex line is the largest of the numbers found in the
-            //       previous two steps and zero.
+        //    2. Among all the items not collected by the previous step, find the largest
+        //       outer hypothetical cross size.
 
+        //    3. The used cross-size of the flex line is the largest of the numbers found in the
+        //       previous two steps and zero.
+        for line in flex_lines.iter_mut() {
             let max_baseline: f32 = line.items.iter().map(|child| child.baseline).fold(0.0, |acc, x| acc.max(x));
             line.cross_size = line
                 .items
@@ -1479,7 +1457,9 @@ fn calculate_cross_size(flex_lines: &mut [FlexLine], node_size: Size<Option<f32>
                 })
                 .fold(0.0, |acc, x| acc.max(x));
         }
-        //  If the flex container is single-line, then clamp the line’s cross-size to be within the container’s computed min and max cross sizes.
+
+        // If the flex container is single-line, then clamp the line’s cross-size to be within the container’s computed min and max cross sizes.
+        // Note that if CSS 2.1’s definition of min/max-width/height applied more generally, this behavior would fall out automatically.
         if !constants.is_wrap {
             let cross_axis_padding_border = constants.content_box_inset.cross_axis_sum(constants.dir);
             let cross_min_size = constants.min_size.cross(constants.dir);
diff --git a/test_fixtures/flex/align_content_space_around_wrapped_single.html b/test_fixtures/flex/align_content_space_around_wrapped_single.html
new file mode 100644
index 000000000..19c936fa2
--- /dev/null
+++ b/test_fixtures/flex/align_content_space_around_wrapped_single.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="width: 100px; height: 100px; flex-direction: row; flex-wrap: wrap; align-content: space-around;">
+  <div style="height: 10px; width: 50px;"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/flex/align_content_space_between_wrapped_single.html b/test_fixtures/flex/align_content_space_between_wrapped_single.html
new file mode 100644
index 000000000..874df4ac9
--- /dev/null
+++ b/test_fixtures/flex/align_content_space_between_wrapped_single.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="width: 100px; height: 100px; flex-direction: row; flex-wrap: wrap; align-content: space-between;">
+  <div style="height: 10px; width: 50px;"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/flex/align_content_space_evenly_wrapped_single.html b/test_fixtures/flex/align_content_space_evenly_wrapped_single.html
new file mode 100644
index 000000000..874df4ac9
--- /dev/null
+++ b/test_fixtures/flex/align_content_space_evenly_wrapped_single.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="width: 100px; height: 100px; flex-direction: row; flex-wrap: wrap; align-content: space-between;">
+  <div style="height: 10px; width: 50px;"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/flex/align_content_stretch_row_wrap.html b/test_fixtures/flex/align_content_stretch_row_wrap.html
new file mode 100644
index 000000000..cbeb1417d
--- /dev/null
+++ b/test_fixtures/flex/align_content_stretch_row_wrap.html
@@ -0,0 +1,19 @@
+<!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="width: 150px; height: 100px; flex-wrap: wrap; flex-direction: row; align-content: stretch;">
+  <div style="width: 100px;">
+    <div style="width: 50px; height: 150px;"></div>
+  </div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/tests/generated/flex/align_content_space_around_wrapped_single.rs b/tests/generated/flex/align_content_space_around_wrapped_single.rs
new file mode 100644
index 000000000..dde07e0dd
--- /dev/null
+++ b/tests/generated/flex/align_content_space_around_wrapped_single.rs
@@ -0,0 +1,167 @@
+#[test]
+#[allow(non_snake_case)]
+fn align_content_space_around_wrapped_single__border_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size {
+                width: taffy::style::Dimension::Length(50f32),
+                height: taffy::style::Dimension::Length(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                flex_wrap: taffy::style::FlexWrap::Wrap,
+                align_content: Some(taffy::style::AlignContent::SpaceAround),
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(100f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout_with_measure(node, taffy::geometry::Size::MAX_CONTENT, crate::test_measure_function).unwrap();
+    println!("\nComputed tree:");
+    taffy.print_tree(node);
+    println!();
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node, 100f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node, 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node0, 50f32, size.width);
+    assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node0, 10f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0, 0f32, location.x);
+    assert_eq!(location.y, 45f32, "y of node {:?}. Expected {}. Actual {}", node0, 45f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_height()
+    );
+}
+
+#[test]
+#[allow(non_snake_case)]
+fn align_content_space_around_wrapped_single__content_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            box_sizing: taffy::style::BoxSizing::ContentBox,
+            size: taffy::geometry::Size {
+                width: taffy::style::Dimension::Length(50f32),
+                height: taffy::style::Dimension::Length(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                flex_wrap: taffy::style::FlexWrap::Wrap,
+                align_content: Some(taffy::style::AlignContent::SpaceAround),
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(100f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout_with_measure(node, taffy::geometry::Size::MAX_CONTENT, crate::test_measure_function).unwrap();
+    println!("\nComputed tree:");
+    taffy.print_tree(node);
+    println!();
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node, 100f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node, 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node0, 50f32, size.width);
+    assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node0, 10f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0, 0f32, location.x);
+    assert_eq!(location.y, 45f32, "y of node {:?}. Expected {}. Actual {}", node0, 45f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_height()
+    );
+}
diff --git a/tests/generated/flex/align_content_space_between_wrapped_single.rs b/tests/generated/flex/align_content_space_between_wrapped_single.rs
new file mode 100644
index 000000000..5b3dbd35a
--- /dev/null
+++ b/tests/generated/flex/align_content_space_between_wrapped_single.rs
@@ -0,0 +1,167 @@
+#[test]
+#[allow(non_snake_case)]
+fn align_content_space_between_wrapped_single__border_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size {
+                width: taffy::style::Dimension::Length(50f32),
+                height: taffy::style::Dimension::Length(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                flex_wrap: taffy::style::FlexWrap::Wrap,
+                align_content: Some(taffy::style::AlignContent::SpaceBetween),
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(100f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout_with_measure(node, taffy::geometry::Size::MAX_CONTENT, crate::test_measure_function).unwrap();
+    println!("\nComputed tree:");
+    taffy.print_tree(node);
+    println!();
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node, 100f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node, 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node0, 50f32, size.width);
+    assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node0, 10f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_height()
+    );
+}
+
+#[test]
+#[allow(non_snake_case)]
+fn align_content_space_between_wrapped_single__content_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            box_sizing: taffy::style::BoxSizing::ContentBox,
+            size: taffy::geometry::Size {
+                width: taffy::style::Dimension::Length(50f32),
+                height: taffy::style::Dimension::Length(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                flex_wrap: taffy::style::FlexWrap::Wrap,
+                align_content: Some(taffy::style::AlignContent::SpaceBetween),
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(100f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout_with_measure(node, taffy::geometry::Size::MAX_CONTENT, crate::test_measure_function).unwrap();
+    println!("\nComputed tree:");
+    taffy.print_tree(node);
+    println!();
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node, 100f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node, 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node0, 50f32, size.width);
+    assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node0, 10f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_height()
+    );
+}
diff --git a/tests/generated/flex/align_content_space_evenly_wrapped_single.rs b/tests/generated/flex/align_content_space_evenly_wrapped_single.rs
new file mode 100644
index 000000000..ede01adb4
--- /dev/null
+++ b/tests/generated/flex/align_content_space_evenly_wrapped_single.rs
@@ -0,0 +1,167 @@
+#[test]
+#[allow(non_snake_case)]
+fn align_content_space_evenly_wrapped_single__border_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size {
+                width: taffy::style::Dimension::Length(50f32),
+                height: taffy::style::Dimension::Length(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                flex_wrap: taffy::style::FlexWrap::Wrap,
+                align_content: Some(taffy::style::AlignContent::SpaceBetween),
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(100f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout_with_measure(node, taffy::geometry::Size::MAX_CONTENT, crate::test_measure_function).unwrap();
+    println!("\nComputed tree:");
+    taffy.print_tree(node);
+    println!();
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node, 100f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node, 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node0, 50f32, size.width);
+    assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node0, 10f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_height()
+    );
+}
+
+#[test]
+#[allow(non_snake_case)]
+fn align_content_space_evenly_wrapped_single__content_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node0 = taffy
+        .new_leaf(taffy::style::Style {
+            box_sizing: taffy::style::BoxSizing::ContentBox,
+            size: taffy::geometry::Size {
+                width: taffy::style::Dimension::Length(50f32),
+                height: taffy::style::Dimension::Length(10f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                flex_wrap: taffy::style::FlexWrap::Wrap,
+                align_content: Some(taffy::style::AlignContent::SpaceBetween),
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(100f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout_with_measure(node, taffy::geometry::Size::MAX_CONTENT, crate::test_measure_function).unwrap();
+    println!("\nComputed tree:");
+    taffy.print_tree(node);
+    println!();
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node, 100f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node, 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node0, 50f32, size.width);
+    assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node0, 10f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_height()
+    );
+}
diff --git a/tests/generated/flex/align_content_stretch_row_wrap.rs b/tests/generated/flex/align_content_stretch_row_wrap.rs
new file mode 100644
index 000000000..a728457f3
--- /dev/null
+++ b/tests/generated/flex/align_content_stretch_row_wrap.rs
@@ -0,0 +1,234 @@
+#[test]
+#[allow(non_snake_case)]
+fn align_content_stretch_row_wrap__border_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node00 = taffy
+        .new_leaf(taffy::style::Style {
+            size: taffy::geometry::Size {
+                width: taffy::style::Dimension::Length(50f32),
+                height: taffy::style::Dimension::Length(150f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node0 = taffy
+        .new_with_children(
+            taffy::style::Style {
+                size: taffy::geometry::Size { width: taffy::style::Dimension::Length(100f32), height: auto() },
+                ..Default::default()
+            },
+            &[node00],
+        )
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                flex_wrap: taffy::style::FlexWrap::Wrap,
+                align_content: Some(taffy::style::AlignContent::Stretch),
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(150f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout_with_measure(node, taffy::geometry::Size::MAX_CONTENT, crate::test_measure_function).unwrap();
+    println!("\nComputed tree:");
+    taffy.print_tree(node);
+    println!();
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 150f32, "width of node {:?}. Expected {}. Actual {}", node, 150f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node, 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        50f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node,
+        50f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node0, 100f32, size.width);
+    assert_eq!(size.height, 150f32, "height of node {:?}. Expected {}. Actual {}", node0, 150f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node00).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node00, 50f32, size.width);
+    assert_eq!(size.height, 150f32, "height of node {:?}. Expected {}. Actual {}", node00, 150f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node00, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node00, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node00,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node00,
+        0f32,
+        layout.scroll_height()
+    );
+}
+
+#[test]
+#[allow(non_snake_case)]
+fn align_content_stretch_row_wrap__content_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node00 = taffy
+        .new_leaf(taffy::style::Style {
+            box_sizing: taffy::style::BoxSizing::ContentBox,
+            size: taffy::geometry::Size {
+                width: taffy::style::Dimension::Length(50f32),
+                height: taffy::style::Dimension::Length(150f32),
+            },
+            ..Default::default()
+        })
+        .unwrap();
+    let node0 = taffy
+        .new_with_children(
+            taffy::style::Style {
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                size: taffy::geometry::Size { width: taffy::style::Dimension::Length(100f32), height: auto() },
+                ..Default::default()
+            },
+            &[node00],
+        )
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                flex_wrap: taffy::style::FlexWrap::Wrap,
+                align_content: Some(taffy::style::AlignContent::Stretch),
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(150f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                ..Default::default()
+            },
+            &[node0],
+        )
+        .unwrap();
+    taffy.compute_layout_with_measure(node, taffy::geometry::Size::MAX_CONTENT, crate::test_measure_function).unwrap();
+    println!("\nComputed tree:");
+    taffy.print_tree(node);
+    println!();
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node).unwrap();
+    assert_eq!(size.width, 150f32, "width of node {:?}. Expected {}. Actual {}", node, 150f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node, 100f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        50f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node,
+        50f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node0).unwrap();
+    assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node0, 100f32, size.width);
+    assert_eq!(size.height, 150f32, "height of node {:?}. Expected {}. Actual {}", node0, 150f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node0,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node00).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node00, 50f32, size.width);
+    assert_eq!(size.height, 150f32, "height of node {:?}. Expected {}. Actual {}", node00, 150f32, size.height);
+    assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node00, 0f32, location.x);
+    assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node00, 0f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node00,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node00,
+        0f32,
+        layout.scroll_height()
+    );
+}
diff --git a/tests/generated/flex/mod.rs b/tests/generated/flex/mod.rs
index bd24c32ef..b20d6fcd5 100644
--- a/tests/generated/flex/mod.rs
+++ b/tests/generated/flex/mod.rs
@@ -86,18 +86,21 @@ mod align_content_space_around_single_line_negative_space_gap;
 mod align_content_space_around_wrapped;
 mod align_content_space_around_wrapped_negative_space;
 mod align_content_space_around_wrapped_negative_space_gap;
+mod align_content_space_around_wrapped_single;
 mod align_content_space_between_single_line;
 mod align_content_space_between_single_line_negative_space;
 mod align_content_space_between_single_line_negative_space_gap;
 mod align_content_space_between_wrapped;
 mod align_content_space_between_wrapped_negative_space;
 mod align_content_space_between_wrapped_negative_space_gap;
+mod align_content_space_between_wrapped_single;
 mod align_content_space_evenly_single_line;
 mod align_content_space_evenly_single_line_negative_space;
 mod align_content_space_evenly_single_line_negative_space_gap;
 mod align_content_space_evenly_wrapped;
 mod align_content_space_evenly_wrapped_negative_space;
 mod align_content_space_evenly_wrapped_negative_space_gap;
+mod align_content_space_evenly_wrapped_single;
 mod align_content_spacearound;
 mod align_content_spacebetween;
 mod align_content_start;
@@ -117,6 +120,7 @@ mod align_content_stretch_row_with_max_height;
 mod align_content_stretch_row_with_min_height;
 mod align_content_stretch_row_with_padding;
 mod align_content_stretch_row_with_single_row;
+mod align_content_stretch_row_wrap;
 mod align_flex_start_with_shrinking_children;
 mod align_flex_start_with_shrinking_children_with_stretch;
 mod align_flex_start_with_stretching_children;