tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1077HTML 1008Markdown 12TOML 83209 Definiciones

Fix grid tracks growing past their limits during space distribution

Fixes #1000

1c87903caa54996981830a94af2174e7bf97a827 · por nico.burns · (hace 2 meses) · padre 0972b84ee · ver el árbol en este commit

Delta semántico · 4

src/compute/grid/track_sizing.rs

tests/hand_written/measure.rs

3 archivos · +55 −2

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3e99001bb..4c42650d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@
 
 ### Fixed
 
+- Grid: tracks no longer grow past their growth limits when distributing free space to multiple tracks with asymmetric limits (in the "maximise tracks" step and when distributing item contributions to base sizes). Previously a track could be assigned space beyond its limit in later distribution iterations, causing `auto` tracks to overflow a definite container (#1000)
+
 - Flexbox: min/max sizes transferred through the aspect ratio now clamp the flex base size, the automatic minimum size, and the hypothetical main/cross sizes of flex items, instead of being baked into the item's used min/max sizes. This matches browser behaviour for replaced elements and items with `aspect-ratio` combined with min/max constraints in the opposite axis ([w3c/csswg-drafts#10997](https://github.com/w3c/csswg-drafts/issues/10997))
 
 - Numeric style helpers (`length`, `percent`, `fr`, `flex`) now accept `Input: Into<f64>` instead of `Input: Into<f32>`. This allows bare float literals such as `length(800.0)` to be used without triggering the `float_literal_f32_fallback` future-compatibility lint, while widening the set of accepted numeric input types (#974)
diff --git a/src/compute/grid/track_sizing.rs b/src/compute/grid/track_sizing.rs
index 10e3ea20d..9d8ad0766 100644
--- a/src/compute/grid/track_sizing.rs
+++ b/src/compute/grid/track_sizing.rs
@@ -1399,7 +1399,10 @@ fn distribute_space_up_to_limits(
             .iter()
             .filter(|track| track_affected_property(track) + track.item_incurred_increase < track_limit(track))
             .filter(|track| track_is_affected(track))
-            .map(|track| (track_limit(track) - track_affected_property(track)) / track_distribution_proportion(track))
+            .map(|track| {
+                (track_limit(track) - track_affected_property(track) - track.item_incurred_increase)
+                    / track_distribution_proportion(track)
+            })
             .min_by(|a, b| a.total_cmp(b))
             .unwrap(); // We will never pass an empty track list to this function
         let iteration_item_incurred_increase =
@@ -1407,7 +1410,10 @@ fn distribute_space_up_to_limits(
 
         for track in tracks.iter_mut().filter(|track| track_is_affected(track)) {
             let increase = iteration_item_incurred_increase * track_distribution_proportion(track);
-            if increase > 0.0 && track_affected_property(track) + increase <= track_limit(track) + THRESHOLD {
+            if increase > 0.0
+                && track_affected_property(track) + track.item_incurred_increase + increase
+                    <= track_limit(track) + THRESHOLD
+            {
                 track.item_incurred_increase += increase;
                 space_to_distribute -= increase;
             }
diff --git a/tests/hand_written/measure.rs b/tests/hand_written/measure.rs
index 32ebcbc61..0cba021a6 100644
--- a/tests/hand_written/measure.rs
+++ b/tests/hand_written/measure.rs
@@ -368,4 +368,49 @@ mod measure {
         assert_eq!(taffy.layout(child).unwrap().size.width, 100.0);
         assert_eq!(taffy.layout(child).unwrap().size.height, 100.0);
     }
+
+    /// Test for https://github.com/DioxusLabs/taffy/issues/1000
+    /// Grid `auto` tracks must not grow past their growth limits (max-content contributions)
+    /// during the "maximise tracks" step, even when the tracks have asymmetric growth limits.
+    #[test]
+    fn grid_auto_tracks_no_grow_past_max_content() {
+        use taffy::{AvailableSpace, TaffyTree};
+
+        const MIN_CONTENT: f32 = 60.0;
+        const CONTAINER: f32 = 928.0;
+        let max_contents = [400.0f32, 674.0];
+
+        let mut tree: TaffyTree<f32> = TaffyTree::new();
+        let cells: Vec<NodeId> =
+            max_contents.iter().map(|mc| tree.new_leaf_with_context(Style::default(), *mc).unwrap()).collect();
+        let grid = tree
+            .new_with_children(
+                Style {
+                    display: Display::Grid,
+                    grid_template_columns: vec![auto(); max_contents.len()],
+                    size: Size { width: Dimension::from_length(CONTAINER), height: auto() },
+                    ..Default::default()
+                },
+                &cells,
+            )
+            .unwrap();
+        tree.compute_layout_with_measure(
+            grid,
+            Size { width: AvailableSpace::Definite(CONTAINER), height: AvailableSpace::MaxContent },
+            |known, available, _node, ctx, _style| {
+                let Some(&mut max_content) = ctx else { return Size::ZERO };
+                let width = known.width.unwrap_or(match available.width {
+                    AvailableSpace::Definite(w) => w.clamp(MIN_CONTENT, max_content),
+                    AvailableSpace::MaxContent => max_content,
+                    AvailableSpace::MinContent => MIN_CONTENT,
+                });
+                Size { width, height: 19.0 }
+            },
+        )
+        .unwrap();
+
+        // Track 0 freezes at its growth limit (400); the remainder goes to track 1.
+        assert_eq!(tree.layout(cells[0]).unwrap().size.width, 400.0);
+        assert_eq!(tree.layout(cells[1]).unwrap().size.width, 528.0);
+    }
 }