Flexbox: pass correct cross-axis available space when computing an item's intrinsic main size (+misc fixes) (#522)
* Add tests for bevyengine/bevy#9350
* Pass accurate cross-axis available space when computing a flexbox item's intrinsic main size
* Subtract child margin not parent margin when computing stretch-alignment known size
* Add extra debug logs to flexbox algorithm
* Apply margins to leaf nodes when computing available space for measure functions
(cherry picked from commit dab541d6104d58e2e10ce90c4a1dad0b703160cd)
df4873ec33473556892439341dbc5f9a88ed8808 · ruwaq Nico Burns · 2023-08-07T22:01:02Z (3 wata ñawpaq) · tayta b2a38dafc · kay commitpi sach'ata qhaway
Semántico sayk'uy · 19
tests/generated/bevy_issue_9530.rs
tests/generated/bevy_issue_9530_reduced.rs
tests/generated/bevy_issue_9530_reduced2.rs
tests/generated/bevy_issue_9530_reduced3.rs
tests/generated/bevy_issue_9530_reduced4.rs
diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index 5fa20ccc1..55eb0b927 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -265,6 +265,8 @@ fn compute_preliminary(
// If container size is undefined, determine the container's main size
// and then re-resolve gaps based on newly determined size
+ #[cfg(feature = "debug")]
+ NODE_LOGGER.log("determine_container_main_size");
let original_gap = constants.gap;
if let Some(inner_main_size) = constants.node_inner_size.main(constants.dir) {
let outer_main_size = inner_main_size + constants.padding_border.main_axis_sum(constants.dir);
@@ -272,10 +274,15 @@ fn compute_preliminary(
constants.container_size.set_main(constants.dir, outer_main_size);
} else {
// Sets constants.container_size and constants.outer_container_size
- determine_container_main_size(tree, available_space.main(constants.dir), &mut flex_lines, &mut constants);
+ determine_container_main_size(tree, available_space, &mut flex_lines, &mut constants);
constants.node_inner_size.set_main(constants.dir, Some(constants.inner_container_size.main(constants.dir)));
constants.node_outer_size.set_main(constants.dir, Some(constants.container_size.main(constants.dir)));
+ #[cfg(feature = "debug")]
+ NODE_LOGGER.labelled_debug_log("constants.node_outer_size", constants.node_outer_size);
+ #[cfg(feature = "debug")]
+ NODE_LOGGER.labelled_debug_log("constants.node_inner_size", constants.node_inner_size);
+
// Re-resolve percentage gaps
let style = tree.style(node);
let inner_container_size = constants.inner_container_size.main(constants.dir);
@@ -655,7 +662,7 @@ fn determine_flex_base_size(
.cross(dir)
.into_option()
.maybe_clamp(child_min_cross, child_max_cross)
- .maybe_sub(constants.margin.cross_axis_sum(dir)),
+ .maybe_sub(child.margin.cross_axis_sum(dir)),
);
}
ckd
@@ -809,14 +816,15 @@ fn collect_flex_lines<'a>(
/// Determine the container's main size (if not already known)
fn determine_container_main_size(
tree: &mut impl LayoutTree,
- main_axis_available_space: AvailableSpace,
+ available_space: Size<AvailableSpace>,
lines: &mut Vec<FlexLine<'_>>,
constants: &mut AlgoConstants,
) {
+ let dir = constants.dir;
let main_padding_border = constants.padding_border.main_axis_sum(constants.dir);
let outer_main_size: f32 = constants.node_outer_size.main(constants.dir).unwrap_or_else(|| {
- match main_axis_available_space {
+ match available_space.main(dir) {
AvailableSpace::Definite(main_axis_available_space) => {
let longest_line_length: f32 = lines
.iter()
@@ -902,6 +910,20 @@ fn determine_container_main_size(
// Else compute the min- or -max content size and apply the full formula for computing the
// min- or max- content contributuon
_ => {
+ // Parent size for child sizing
+ let cross_axis_parent_size = constants.node_inner_size.cross(dir);
+
+ // Available space for child sizing
+ let cross_axis_margin_sum = constants.margin.cross_axis_sum(dir);
+ let child_min_cross = item.min_size.cross(dir).maybe_add(cross_axis_margin_sum);
+ let child_max_cross = item.max_size.cross(dir).maybe_add(cross_axis_margin_sum);
+ let cross_axis_available_space: AvailableSpace = available_space
+ .cross(dir)
+ .map_definite_value(|val| cross_axis_parent_size.unwrap_or(val))
+ .maybe_clamp(child_min_cross, child_max_cross);
+
+ let child_available_space = available_space.with_cross(dir, cross_axis_available_space);
+
// Either the min- or max- content size depending on which constraint we are sizing under.
// TODO: Optimise by using already computed values where available
let content_main_size = GenericAlgorithm::measure_size(
@@ -909,7 +931,7 @@ fn determine_container_main_size(
item.node,
Size::NONE,
constants.node_inner_size,
- Size { width: main_axis_available_space, height: main_axis_available_space },
+ child_available_space,
SizingMode::InherentSize,
)
.main(constants.dir)
diff --git a/src/compute/leaf.rs b/src/compute/leaf.rs
index a884bc16f..cd913efcd 100644
--- a/src/compute/leaf.rs
+++ b/src/compute/leaf.rs
@@ -74,6 +74,7 @@ pub(crate) fn compute(
// Note: both horizontal and vertical percentage padding/borders are resolved against the container's inline size (i.e. width).
// This is not a bug, but is how CSS is specified (see: https://developer.mozilla.org/en-US/docs/Web/CSS/padding#values)
+ let margin = style.margin.resolve_or_zero(parent_size.width);
let padding = style.padding.resolve_or_zero(parent_size.width);
let border = style.border.resolve_or_zero(parent_size.width);
let padding_border = padding + border;
@@ -100,11 +101,13 @@ pub(crate) fn compute(
let available_space = Size {
width: available_space
.width
+ .maybe_sub(margin.horizontal_axis_sum())
.maybe_set(node_size.width)
.maybe_set(node_max_size.width)
.map_definite_value(|size| size.maybe_clamp(node_min_size.width, node_max_size.width)),
height: available_space
.height
+ .maybe_sub(margin.vertical_axis_sum())
.maybe_set(node_size.height)
.maybe_set(node_max_size.height)
.map_definite_value(|size| size.maybe_clamp(node_min_size.height, node_max_size.height)),
diff --git a/test_fixtures/bevy_issue_9530.html b/test_fixtures/bevy_issue_9530.html
new file mode 100644
index 000000000..4b346eb59
--- /dev/null
+++ b/test_fixtures/bevy_issue_9530.html
@@ -0,0 +1,23 @@
+<!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="background: white; width: 300px; height: 300px; margin: auto; align-content: center; align-items: center; flex-direction: column;">
+ <div style="width: 100%; height: 20px; flex-direction: column; background: red;"></div>
+ <div style="width: 100%; flex-grow: 1; padding: 20px; margin: 20px; flex-direction: column; background: red;">
+ <div style="width: 100%; height: 50px;"></div>
+ <div style="/*width: 100%; */flex-grow: 1; align-content: center; align-items: center; justify-content: center; margin: 20px; background: blue;">HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH​HHHH</div>
+ <div style="width: 100%; height: 50px;"></div>
+
+ </div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/bevy_issue_9530_reduced.html b/test_fixtures/bevy_issue_9530_reduced.html
new file mode 100644
index 000000000..4d6f223f8
--- /dev/null
+++ b/test_fixtures/bevy_issue_9530_reduced.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="flex-direction: column; width: 40px;">
+ <div style="flex-direction: column; flex-grow: 1;">
+ <div style="flex-grow: 1;">HH​HH​HH​HH</div>
+ </div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/bevy_issue_9530_reduced2.html b/test_fixtures/bevy_issue_9530_reduced2.html
new file mode 100644
index 000000000..f488740ae
--- /dev/null
+++ b/test_fixtures/bevy_issue_9530_reduced2.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="flex-direction: column;">
+ <div style="flex-direction: column; flex-grow: 1; width: 80px; margin: 0 20px;">
+ <div style="flex-grow: 1;">HH​HH​HH​HH​HH​HH​HH​HH</div>
+ </div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/bevy_issue_9530_reduced3.html b/test_fixtures/bevy_issue_9530_reduced3.html
new file mode 100644
index 000000000..44488c9c0
--- /dev/null
+++ b/test_fixtures/bevy_issue_9530_reduced3.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="flex-direction: column; width: 80px;">
+ <div style="flex-grow: 1; margin: 0 20px;">HH​HH​HH​HH​HH​HH​HH​HH</div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/test_fixtures/bevy_issue_9530_reduced4.html b/test_fixtures/bevy_issue_9530_reduced4.html
new file mode 100644
index 000000000..42f84c156
--- /dev/null
+++ b/test_fixtures/bevy_issue_9530_reduced4.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="flex-direction: column; width: 80px;">
+ <div style="margin: 20px;">HH​HH​HH​HH​HH​HH​HH​HH</div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/tests/generated/bevy_issue_9530.rs b/tests/generated/bevy_issue_9530.rs
new file mode 100644
index 000000000..4641f9fa5
--- /dev/null
+++ b/tests/generated/bevy_issue_9530.rs
@@ -0,0 +1,114 @@
+#[test]
+fn bevy_issue_9530() {
+ 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 {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Percent(1f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Percent(1f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node11 = taffy . new_leaf_with_measure (taffy :: style :: Style { align_items : Some (taffy :: style :: AlignItems :: Center) , align_content : Some (taffy :: style :: AlignContent :: Center) , justify_content : Some (taffy :: style :: JustifyContent :: Center) , flex_grow : 1f32 , margin : taffy :: geometry :: Rect { left : taffy :: style :: LengthPercentageAuto :: Points (20f32) , right : taffy :: style :: LengthPercentageAuto :: Points (20f32) , top : taffy :: style :: LengthPercentageAuto :: Points (20f32) , bottom : taffy :: style :: LengthPercentageAuto :: Points (20f32) , } , .. Default :: default () } , taffy :: node :: MeasureFunc :: Raw (| known_dimensions , available_space | { const TEXT : & str = "HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH\u{200b}HHHH" ; super :: measure_standard_text (known_dimensions , available_space , TEXT , super :: WritingMode :: Horizontal , None) }) ,) . unwrap () ;
+ let node12 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Percent(1f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ flex_grow: 1f32,
+ size: taffy::geometry::Size { width: taffy::style::Dimension::Percent(1f32), height: auto() },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(20f32),
+ right: taffy::style::LengthPercentageAuto::Points(20f32),
+ top: taffy::style::LengthPercentageAuto::Points(20f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(20f32),
+ },
+ padding: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentage::Points(20f32),
+ right: taffy::style::LengthPercentage::Points(20f32),
+ top: taffy::style::LengthPercentage::Points(20f32),
+ bottom: taffy::style::LengthPercentage::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node10, node11, node12],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ align_items: Some(taffy::style::AlignItems::Center),
+ align_content: Some(taffy::style::AlignContent::Center),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(300f32),
+ height: taffy::style::Dimension::Points(300f32),
+ },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Auto,
+ right: taffy::style::LengthPercentageAuto::Auto,
+ top: taffy::style::LengthPercentageAuto::Auto,
+ bottom: taffy::style::LengthPercentageAuto::Auto,
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .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, 300f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 300f32, size.width);
+ assert_eq!(size.height, 300f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 300f32, 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, 300f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 300f32, size.width);
+ assert_eq!(size.height, 0f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node1).unwrap();
+ assert_eq!(size.width, 300f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 300f32, size.width);
+ assert_eq!(size.height, 420f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 420f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, location.x);
+ assert_eq!(location.y, 20f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 20f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node10).unwrap();
+ assert_eq!(size.width, 260f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 260f32, size.width);
+ assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 50f32, size.height);
+ assert_eq!(location.x, 20f32, "x of node {:?}. Expected {}. Actual {}", node10.data(), 20f32, location.x);
+ assert_eq!(location.y, 20f32, "y of node {:?}. Expected {}. Actual {}", node10.data(), 20f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node11).unwrap();
+ assert_eq!(size.width, 220f32, "width of node {:?}. Expected {}. Actual {}", node11.data(), 220f32, size.width);
+ assert_eq!(size.height, 240f32, "height of node {:?}. Expected {}. Actual {}", node11.data(), 240f32, size.height);
+ assert_eq!(location.x, 40f32, "x of node {:?}. Expected {}. Actual {}", node11.data(), 40f32, location.x);
+ assert_eq!(location.y, 90f32, "y of node {:?}. Expected {}. Actual {}", node11.data(), 90f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node12).unwrap();
+ assert_eq!(size.width, 260f32, "width of node {:?}. Expected {}. Actual {}", node12.data(), 260f32, size.width);
+ assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node12.data(), 50f32, size.height);
+ assert_eq!(location.x, 20f32, "x of node {:?}. Expected {}. Actual {}", node12.data(), 20f32, location.x);
+ assert_eq!(location.y, 350f32, "y of node {:?}. Expected {}. Actual {}", node12.data(), 350f32, location.y);
+}
diff --git a/tests/generated/bevy_issue_9530_reduced.rs b/tests/generated/bevy_issue_9530_reduced.rs
new file mode 100644
index 000000000..449546295
--- /dev/null
+++ b/tests/generated/bevy_issue_9530_reduced.rs
@@ -0,0 +1,61 @@
+#[test]
+fn bevy_issue_9530_reduced() {
+ use slotmap::Key;
+ #[allow(unused_imports)]
+ use taffy::{layout::Layout, prelude::*};
+ let mut taffy = taffy::Taffy::new();
+ let node00 = taffy
+ .new_leaf_with_measure(
+ taffy::style::Style { flex_grow: 1f32, ..Default::default() },
+ taffy::node::MeasureFunc::Raw(|known_dimensions, available_space| {
+ const TEXT: &str = "HH\u{200b}HH\u{200b}HH\u{200b}HH";
+ super::measure_standard_text(
+ known_dimensions,
+ available_space,
+ TEXT,
+ super::WritingMode::Horizontal,
+ None,
+ )
+ }),
+ )
+ .unwrap();
+ let node0 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ flex_grow: 1f32,
+ ..Default::default()
+ },
+ &[node00],
+ )
+ .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(40f32), height: auto() },
+ ..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, 40f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 40f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 20f32, 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, 20f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 20f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node00).unwrap();
+ assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node00.data(), 40f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node00.data(), 20f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.y);
+}
diff --git a/tests/generated/bevy_issue_9530_reduced2.rs b/tests/generated/bevy_issue_9530_reduced2.rs
new file mode 100644
index 000000000..41eca5abc
--- /dev/null
+++ b/tests/generated/bevy_issue_9530_reduced2.rs
@@ -0,0 +1,64 @@
+#[test]
+fn bevy_issue_9530_reduced2() {
+ use slotmap::Key;
+ #[allow(unused_imports)]
+ use taffy::{layout::Layout, prelude::*};
+ let mut taffy = taffy::Taffy::new();
+ let node00 = taffy
+ .new_leaf_with_measure(
+ taffy::style::Style { flex_grow: 1f32, ..Default::default() },
+ taffy::node::MeasureFunc::Raw(|known_dimensions, available_space| {
+ const TEXT: &str = "HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH";
+ super::measure_standard_text(
+ known_dimensions,
+ available_space,
+ TEXT,
+ super::WritingMode::Horizontal,
+ None,
+ )
+ }),
+ )
+ .unwrap();
+ let node0 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ flex_grow: 1f32,
+ size: taffy::geometry::Size { width: taffy::style::Dimension::Points(80f32), height: auto() },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(20f32),
+ right: taffy::style::LengthPercentageAuto::Points(20f32),
+ top: taffy::style::LengthPercentageAuto::Points(0f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(0f32),
+ },
+ ..Default::default()
+ },
+ &[node00],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style { flex_direction: taffy::style::FlexDirection::Column, ..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, 120f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 120f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 20f32, 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, 80f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 80f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 20f32, size.height);
+ assert_eq!(location.x, 20f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 20f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node00).unwrap();
+ assert_eq!(size.width, 80f32, "width of node {:?}. Expected {}. Actual {}", node00.data(), 80f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node00.data(), 20f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.y);
+}
diff --git a/tests/generated/bevy_issue_9530_reduced3.rs b/tests/generated/bevy_issue_9530_reduced3.rs
new file mode 100644
index 000000000..f29fb6d40
--- /dev/null
+++ b/tests/generated/bevy_issue_9530_reduced3.rs
@@ -0,0 +1,55 @@
+#[test]
+fn bevy_issue_9530_reduced3() {
+ use slotmap::Key;
+ #[allow(unused_imports)]
+ use taffy::{layout::Layout, prelude::*};
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf_with_measure(
+ taffy::style::Style {
+ flex_grow: 1f32,
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(20f32),
+ right: taffy::style::LengthPercentageAuto::Points(20f32),
+ top: taffy::style::LengthPercentageAuto::Points(0f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(0f32),
+ },
+ ..Default::default()
+ },
+ taffy::node::MeasureFunc::Raw(|known_dimensions, available_space| {
+ const TEXT: &str = "HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH";
+ super::measure_standard_text(
+ known_dimensions,
+ available_space,
+ TEXT,
+ super::WritingMode::Horizontal,
+ None,
+ )
+ }),
+ )
+ .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(80f32), height: auto() },
+ ..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, 80f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 80f32, size.width);
+ assert_eq!(size.height, 40f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 40f32, 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, 40f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, size.height);
+ assert_eq!(location.x, 20f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 20f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, location.y);
+}
diff --git a/tests/generated/bevy_issue_9530_reduced4.rs b/tests/generated/bevy_issue_9530_reduced4.rs
new file mode 100644
index 000000000..fac6668f2
--- /dev/null
+++ b/tests/generated/bevy_issue_9530_reduced4.rs
@@ -0,0 +1,54 @@
+#[test]
+fn bevy_issue_9530_reduced4() {
+ use slotmap::Key;
+ #[allow(unused_imports)]
+ use taffy::{layout::Layout, prelude::*};
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf_with_measure(
+ taffy::style::Style {
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(20f32),
+ right: taffy::style::LengthPercentageAuto::Points(20f32),
+ top: taffy::style::LengthPercentageAuto::Points(20f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(20f32),
+ },
+ ..Default::default()
+ },
+ taffy::node::MeasureFunc::Raw(|known_dimensions, available_space| {
+ const TEXT: &str = "HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH\u{200b}HH";
+ super::measure_standard_text(
+ known_dimensions,
+ available_space,
+ TEXT,
+ super::WritingMode::Horizontal,
+ None,
+ )
+ }),
+ )
+ .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(80f32), height: auto() },
+ ..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, 80f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 80f32, size.width);
+ assert_eq!(size.height, 80f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 80f32, 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, 40f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, size.height);
+ assert_eq!(location.x, 20f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 20f32, location.x);
+ assert_eq!(location.y, 20f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 20f32, location.y);
+}
diff --git a/tests/generated/mod.rs b/tests/generated/mod.rs
index 4be363806..05c7f1243 100644
--- a/tests/generated/mod.rs
+++ b/tests/generated/mod.rs
@@ -205,6 +205,11 @@ mod bevy_issue_8017;
mod bevy_issue_8017_reduced;
mod bevy_issue_8082;
mod bevy_issue_8082_percent;
+mod bevy_issue_9530;
+mod bevy_issue_9530_reduced;
+mod bevy_issue_9530_reduced2;
+mod bevy_issue_9530_reduced3;
+mod bevy_issue_9530_reduced4;
mod border_center_child;
mod border_container_match_child;
mod border_flex_child;