tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 497HTML 254C 19JavaScript 81329 Definiciones

Flexbox: Fix flooring hypothetical_main_size by computed min size (#689)

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

Delta semántico · 4

src/compute/flexbox.rs

tests/generated/flex/flex_grow_0_min_size.rs

tests/generated/flex/mod.rs

4 archivos · +457 −8

diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index 358c76bf7..b9cf9d044 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -744,14 +744,6 @@ fn determine_flex_base_size(
             child.flex_basis - child.padding.main_axis_sum(constants.dir) - child.border.main_axis_sum(constants.dir);
 
         let padding_border_axes_sums = (child.padding + child.border).sum_axes().map(Some);
-        let hypothetical_inner_min_main =
-            child.min_size.main(constants.dir).maybe_max(padding_border_axes_sums.main(constants.dir));
-        let hypothetical_inner_size =
-            child.flex_basis.maybe_clamp(hypothetical_inner_min_main, child.max_size.main(constants.dir));
-        let hypothetical_outer_size = hypothetical_inner_size + child.margin.main_axis_sum(constants.dir);
-
-        child.hypothetical_inner_size.set_main(constants.dir, hypothetical_inner_size);
-        child.hypothetical_outer_size.set_main(constants.dir, hypothetical_outer_size);
 
         // Note that it is important that the `parent_size` parameter in the main axis is not set for this
         // function call as it used for resolving percentages, and percentage size in an axis should not contribute
@@ -784,6 +776,15 @@ fn determine_flex_base_size(
                 min_content_main_size.maybe_min(child.size.main(dir)).maybe_min(child.max_size.main(dir));
             clamped_min_content_size.maybe_max(padding_border_axes_sums.main(dir))
         });
+
+        let hypothetical_inner_min_main =
+            child.resolved_minimum_main_size.maybe_max(padding_border_axes_sums.main(constants.dir));
+        let hypothetical_inner_size =
+            child.flex_basis.maybe_clamp(Some(hypothetical_inner_min_main), child.max_size.main(constants.dir));
+        let hypothetical_outer_size = hypothetical_inner_size + child.margin.main_axis_sum(constants.dir);
+
+        child.hypothetical_inner_size.set_main(constants.dir, hypothetical_inner_size);
+        child.hypothetical_outer_size.set_main(constants.dir, hypothetical_outer_size);
     }
 }
 
diff --git a/test_fixtures/flex/flex_grow_0_min_size.html b/test_fixtures/flex/flex_grow_0_min_size.html
new file mode 100644
index 000000000..cdaaa808b
--- /dev/null
+++ b/test_fixtures/flex/flex_grow_0_min_size.html
@@ -0,0 +1,21 @@
+<!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">
+  <meta name="wpt-test-port" value="css/css-flexbox/flexbox_flex-0-0-0.html" />
+  <title>
+    Test description
+  </title>
+</head>
+<body>
+
+<div id="test-root" style="display: flex; flex-direction: row; height: 100px; width: 400px; background: blue; border: 1px solid black;">
+  <div style="flex-shrink: 0; flex-grow: 0; flex-basis: 0%;">one</div>
+  <div style="flex-shrink: 0; flex-grow: 0; flex-basis: 0%;">two</div>
+  <div style="flex-shrink: 0; flex-grow: 0; flex-basis: 0%;">three</div>
+  <div style="flex-shrink: 0; flex-grow: 0; flex-basis: 0%;">four</div>
+</div>
+
+</body>
+</html>
diff --git a/tests/generated/flex/flex_grow_0_min_size.rs b/tests/generated/flex/flex_grow_0_min_size.rs
new file mode 100644
index 000000000..adcc46b55
--- /dev/null
+++ b/tests/generated/flex/flex_grow_0_min_size.rs
@@ -0,0 +1,426 @@
+#[test]
+#[allow(non_snake_case)]
+fn flex_grow_0_min_size__border_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node0 = taffy
+        .new_leaf_with_context(
+            taffy::style::Style {
+                flex_grow: 0f32,
+                flex_shrink: 0f32,
+                flex_basis: taffy::style::Dimension::Percent(0f32),
+                ..Default::default()
+            },
+            crate::TextMeasure {
+                text_content: "one",
+                writing_mode: crate::WritingMode::Horizontal,
+                _aspect_ratio: None,
+            },
+        )
+        .unwrap();
+    let node1 = taffy
+        .new_leaf_with_context(
+            taffy::style::Style {
+                flex_grow: 0f32,
+                flex_shrink: 0f32,
+                flex_basis: taffy::style::Dimension::Percent(0f32),
+                ..Default::default()
+            },
+            crate::TextMeasure {
+                text_content: "two",
+                writing_mode: crate::WritingMode::Horizontal,
+                _aspect_ratio: None,
+            },
+        )
+        .unwrap();
+    let node2 = taffy
+        .new_leaf_with_context(
+            taffy::style::Style {
+                flex_grow: 0f32,
+                flex_shrink: 0f32,
+                flex_basis: taffy::style::Dimension::Percent(0f32),
+                ..Default::default()
+            },
+            crate::TextMeasure {
+                text_content: "three",
+                writing_mode: crate::WritingMode::Horizontal,
+                _aspect_ratio: None,
+            },
+        )
+        .unwrap();
+    let node3 = taffy
+        .new_leaf_with_context(
+            taffy::style::Style {
+                flex_grow: 0f32,
+                flex_shrink: 0f32,
+                flex_basis: taffy::style::Dimension::Percent(0f32),
+                ..Default::default()
+            },
+            crate::TextMeasure {
+                text_content: "four",
+                writing_mode: crate::WritingMode::Horizontal,
+                _aspect_ratio: None,
+            },
+        )
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                display: taffy::style::Display::Flex,
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(400f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                border: taffy::geometry::Rect {
+                    left: taffy::style::LengthPercentage::Length(1f32),
+                    right: taffy::style::LengthPercentage::Length(1f32),
+                    top: taffy::style::LengthPercentage::Length(1f32),
+                    bottom: taffy::style::LengthPercentage::Length(1f32),
+                },
+                ..Default::default()
+            },
+            &[node0, node1, node2, node3],
+        )
+        .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, 400f32, "width of node {:?}. Expected {}. Actual {}", node, 400f32, 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, 30f32, "width of node {:?}. Expected {}. Actual {}", node0, 30f32, size.width);
+    assert_eq!(size.height, 98f32, "height of node {:?}. Expected {}. Actual {}", node0, 98f32, size.height);
+    assert_eq!(location.x, 1f32, "x of node {:?}. Expected {}. Actual {}", node0, 1f32, location.x);
+    assert_eq!(location.y, 1f32, "y of node {:?}. Expected {}. Actual {}", node0, 1f32, 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(node1).unwrap();
+    assert_eq!(size.width, 30f32, "width of node {:?}. Expected {}. Actual {}", node1, 30f32, size.width);
+    assert_eq!(size.height, 98f32, "height of node {:?}. Expected {}. Actual {}", node1, 98f32, size.height);
+    assert_eq!(location.x, 31f32, "x of node {:?}. Expected {}. Actual {}", node1, 31f32, location.x);
+    assert_eq!(location.y, 1f32, "y of node {:?}. Expected {}. Actual {}", node1, 1f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node1,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node1,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node2).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node2, 50f32, size.width);
+    assert_eq!(size.height, 98f32, "height of node {:?}. Expected {}. Actual {}", node2, 98f32, size.height);
+    assert_eq!(location.x, 61f32, "x of node {:?}. Expected {}. Actual {}", node2, 61f32, location.x);
+    assert_eq!(location.y, 1f32, "y of node {:?}. Expected {}. Actual {}", node2, 1f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node2,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node2,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node3).unwrap();
+    assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node3, 40f32, size.width);
+    assert_eq!(size.height, 98f32, "height of node {:?}. Expected {}. Actual {}", node3, 98f32, size.height);
+    assert_eq!(location.x, 111f32, "x of node {:?}. Expected {}. Actual {}", node3, 111f32, location.x);
+    assert_eq!(location.y, 1f32, "y of node {:?}. Expected {}. Actual {}", node3, 1f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node3,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node3,
+        0f32,
+        layout.scroll_height()
+    );
+}
+
+#[test]
+#[allow(non_snake_case)]
+fn flex_grow_0_min_size__content_box() {
+    #[allow(unused_imports)]
+    use taffy::{prelude::*, tree::Layout, TaffyTree};
+    let mut taffy: TaffyTree<crate::TextMeasure> = TaffyTree::new();
+    let node0 = taffy
+        .new_leaf_with_context(
+            taffy::style::Style {
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                flex_grow: 0f32,
+                flex_shrink: 0f32,
+                flex_basis: taffy::style::Dimension::Percent(0f32),
+                ..Default::default()
+            },
+            crate::TextMeasure {
+                text_content: "one",
+                writing_mode: crate::WritingMode::Horizontal,
+                _aspect_ratio: None,
+            },
+        )
+        .unwrap();
+    let node1 = taffy
+        .new_leaf_with_context(
+            taffy::style::Style {
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                flex_grow: 0f32,
+                flex_shrink: 0f32,
+                flex_basis: taffy::style::Dimension::Percent(0f32),
+                ..Default::default()
+            },
+            crate::TextMeasure {
+                text_content: "two",
+                writing_mode: crate::WritingMode::Horizontal,
+                _aspect_ratio: None,
+            },
+        )
+        .unwrap();
+    let node2 = taffy
+        .new_leaf_with_context(
+            taffy::style::Style {
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                flex_grow: 0f32,
+                flex_shrink: 0f32,
+                flex_basis: taffy::style::Dimension::Percent(0f32),
+                ..Default::default()
+            },
+            crate::TextMeasure {
+                text_content: "three",
+                writing_mode: crate::WritingMode::Horizontal,
+                _aspect_ratio: None,
+            },
+        )
+        .unwrap();
+    let node3 = taffy
+        .new_leaf_with_context(
+            taffy::style::Style {
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                flex_grow: 0f32,
+                flex_shrink: 0f32,
+                flex_basis: taffy::style::Dimension::Percent(0f32),
+                ..Default::default()
+            },
+            crate::TextMeasure {
+                text_content: "four",
+                writing_mode: crate::WritingMode::Horizontal,
+                _aspect_ratio: None,
+            },
+        )
+        .unwrap();
+    let node = taffy
+        .new_with_children(
+            taffy::style::Style {
+                display: taffy::style::Display::Flex,
+                box_sizing: taffy::style::BoxSizing::ContentBox,
+                size: taffy::geometry::Size {
+                    width: taffy::style::Dimension::Length(400f32),
+                    height: taffy::style::Dimension::Length(100f32),
+                },
+                border: taffy::geometry::Rect {
+                    left: taffy::style::LengthPercentage::Length(1f32),
+                    right: taffy::style::LengthPercentage::Length(1f32),
+                    top: taffy::style::LengthPercentage::Length(1f32),
+                    bottom: taffy::style::LengthPercentage::Length(1f32),
+                },
+                ..Default::default()
+            },
+            &[node0, node1, node2, node3],
+        )
+        .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, 402f32, "width of node {:?}. Expected {}. Actual {}", node, 402f32, size.width);
+    assert_eq!(size.height, 102f32, "height of node {:?}. Expected {}. Actual {}", node, 102f32, 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, 30f32, "width of node {:?}. Expected {}. Actual {}", node0, 30f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node0, 100f32, size.height);
+    assert_eq!(location.x, 1f32, "x of node {:?}. Expected {}. Actual {}", node0, 1f32, location.x);
+    assert_eq!(location.y, 1f32, "y of node {:?}. Expected {}. Actual {}", node0, 1f32, 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(node1).unwrap();
+    assert_eq!(size.width, 30f32, "width of node {:?}. Expected {}. Actual {}", node1, 30f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node1, 100f32, size.height);
+    assert_eq!(location.x, 31f32, "x of node {:?}. Expected {}. Actual {}", node1, 31f32, location.x);
+    assert_eq!(location.y, 1f32, "y of node {:?}. Expected {}. Actual {}", node1, 1f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node1,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node1,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node2).unwrap();
+    assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node2, 50f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node2, 100f32, size.height);
+    assert_eq!(location.x, 61f32, "x of node {:?}. Expected {}. Actual {}", node2, 61f32, location.x);
+    assert_eq!(location.y, 1f32, "y of node {:?}. Expected {}. Actual {}", node2, 1f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node2,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node2,
+        0f32,
+        layout.scroll_height()
+    );
+    #[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
+    let layout @ Layout { size, location, .. } = taffy.layout(node3).unwrap();
+    assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node3, 40f32, size.width);
+    assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node3, 100f32, size.height);
+    assert_eq!(location.x, 111f32, "x of node {:?}. Expected {}. Actual {}", node3, 111f32, location.x);
+    assert_eq!(location.y, 1f32, "y of node {:?}. Expected {}. Actual {}", node3, 1f32, location.y);
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_width(),
+        0f32,
+        "scroll_width of node {:?}. Expected {}. Actual {}",
+        node3,
+        0f32,
+        layout.scroll_width()
+    );
+    #[cfg(feature = "content_size")]
+    assert_eq!(
+        layout.scroll_height(),
+        0f32,
+        "scroll_height of node {:?}. Expected {}. Actual {}",
+        node3,
+        0f32,
+        layout.scroll_height()
+    );
+}
diff --git a/tests/generated/flex/mod.rs b/tests/generated/flex/mod.rs
index bc2806cdd..bd24c32ef 100644
--- a/tests/generated/flex/mod.rs
+++ b/tests/generated/flex/mod.rs
@@ -235,6 +235,7 @@ mod flex_direction_column_reverse_no_height;
 mod flex_direction_row;
 mod flex_direction_row_no_width;
 mod flex_direction_row_reverse;
+mod flex_grow_0_min_size;
 mod flex_grow_child;
 mod flex_grow_flex_basis_percent_min_max;
 mod flex_grow_height_maximized;