tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 788HTML 740Markdown 12TOML 62536 Definiciones

solve divided by zero error

51012cd818d5f6d65bfb6b38cafbb1412bcd58a8 · por Emil Sjölander · (hace 7 años) · padre b83a1f717 · ver el árbol en este commit

Delta semántico · 2

src/algo.rs

tests/generated.rs

3 archivos · +85 −28

diff --git a/src/algo.rs b/src/algo.rs
index f6166c193..4845beae2 100644
--- a/src/algo.rs
+++ b/src/algo.rs
@@ -40,7 +40,7 @@ impl SafeMath for f32 {
             self.min(rhs)
         }
     }
-    
+
     fn safe_max(&self, rhs: f32) -> f32 {
         if self.is_nan() {
             f32::NAN
@@ -81,6 +81,7 @@ struct FlexItem<'a> {
     offset_cross: f32,
 }
 
+#[derive(Debug)]
 struct ComputeResult {
     size: FlexSize,
     children: Vec<layout::Node>,
@@ -231,7 +232,7 @@ fn compute_internal(
 
     let wrap_reverse = node.flex_wrap == style::FlexWrap::WrapReverse;
 
-    let percent_calc_base_child = node_width;
+    let percent_calc_base_child = if node.flex_direction.is_row() { node_inner_main } else { node_inner_cross };
 
     // 9.2. Line Length Determination
 
@@ -382,9 +383,10 @@ fn compute_internal(
             percent_calc_base_child,
         ).size;
 
-        child.flex_basis = size.main(node.flex_direction)
-                .max(child.node.min_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
-                .min(child.node.max_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN));
+        child.flex_basis = size
+            .main(node.flex_direction)
+            .max(child.node.min_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
+            .min(child.node.max_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN));
     }
 
     // The hypothetical main size is the item’s flex base size clamped according to its
@@ -412,15 +414,15 @@ fn compute_internal(
             ).size
             .width
             .min(child.node.width.resolve(percent_calc_base_child, f32::NAN))
-            .max(child.node.min_width.resolve(percent_calc_base_child, f32::MIN))
+            .max(child.node.min_width.resolve(percent_calc_base_child, f32::NAN))
         } else {
-            child.node.min_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::MIN)
+            child.node.min_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN)
         };
 
         child.hypothetical_inner_main_size = child
             .flex_basis
-            .max(min_main)
-            .min(child.node.max_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::MAX))
+            .safe_max(min_main)
+            .safe_min(child.node.max_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
             .max(0.0);
 
         child.hypothetical_outer_main_size = child.hypothetical_inner_main_size
@@ -626,10 +628,12 @@ fn compute_internal(
                     let sum_scaled_shrink_factor: f32 =
                         unfrozen.iter().map(|child| child.inner_flex_basis * child.node.flex_shrink).sum();
 
-                    for child in &mut unfrozen {
-                        let scaled_shrink_factor = child.inner_flex_basis * child.node.flex_shrink;
-                        child.target_main_size =
-                            child.flex_basis + free_space * (scaled_shrink_factor / sum_scaled_shrink_factor);
+                    if sum_scaled_shrink_factor > 0.0 {
+                        for child in &mut unfrozen {
+                            let scaled_shrink_factor = child.inner_flex_basis * child.node.flex_shrink;
+                            child.target_main_size =
+                                child.flex_basis + free_space * (scaled_shrink_factor / sum_scaled_shrink_factor);
+                        }
                     }
                 }
             }
@@ -656,14 +660,14 @@ fn compute_internal(
                     ).size
                     .width
                     .min(child.node.width.resolve(percent_calc_base_child, f32::NAN))
-                    .max(child.node.min_width.resolve(percent_calc_base_child, f32::MIN))
+                    .max(child.node.min_width.resolve(percent_calc_base_child, f32::NAN))
                 } else {
-                    child.node.min_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::MIN)
+                    child.node.min_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN)
                 };
 
-                let max_main = child.node.max_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::MAX);
+                let max_main = child.node.max_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN);
 
-                let clamped = child.target_main_size.min(max_main).max(min_main).max(0.0);
+                let clamped = child.target_main_size.safe_min(max_main).safe_max(min_main).max(0.0);
                 child.violation = clamped - child.target_main_size;
                 total_violation += child.violation;
                 child.target_main_size = clamped;
@@ -746,8 +750,8 @@ fn compute_internal(
 
             child.hypothetical_inner_cross_size = size
                 .cross(node.flex_direction)
-                .max(child.node.min_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::MIN))
-                .min(child.node.max_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::MAX))
+                .safe_max(child.node.min_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
+                .safe_min(child.node.max_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
                 .max(0.0);
 
             child.hypothetical_outer_cross_size = child.hypothetical_inner_cross_size
@@ -844,8 +848,8 @@ fn compute_internal(
                 (line.cross_size
                     - child.node.cross_margin_start(node.flex_direction).resolve(percent_calc_base_child, 0.0)
                     - child.node.cross_margin_end(node.flex_direction).resolve(percent_calc_base_child, 0.0))
-                    .max(child.node.min_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::MIN))
-                    .min(child.node.max_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::MAX))
+                    .safe_max(child.node.min_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
+                    .safe_min(child.node.max_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
             } else {
                 child.hypothetical_inner_cross_size
             };
@@ -1139,7 +1143,7 @@ fn compute_internal(
                 if node.flex_direction.is_reverse() {
                     children.reverse();
                 }
-                
+
                 lines.push(children);
             };
 
@@ -1201,12 +1205,16 @@ fn compute_internal(
             container_main_size,
         );
 
-        let free_main_space = container_main_size - result.size.main(node.flex_direction)
-                        .max(child.min_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
-                        .min(child.max_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN));
-        let free_cross_space = container_cross_size - result.size.cross(node.flex_direction)
-                        .max(child.min_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
-                        .min(child.max_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN));
+        let free_main_space = container_main_size - result
+            .size
+            .main(node.flex_direction)
+            .max(child.min_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
+            .min(child.max_main_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN));
+        let free_cross_space = container_cross_size - result
+            .size
+            .cross(node.flex_direction)
+            .max(child.min_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN))
+            .min(child.max_cross_size(node.flex_direction).resolve(percent_calc_base_child, f32::NAN));
 
         let offset_main = if start_main.is_finite() {
             start_main + border_main_start
diff --git a/test_fixtures/percentage_size_based_on_parent_inner_size.html b/test_fixtures/percentage_size_based_on_parent_inner_size.html
new file mode 100644
index 000000000..d501c8ac6
--- /dev/null
+++ b/test_fixtures/percentage_size_based_on_parent_inner_size.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: 200px; height: 200px; padding: 20px; flex-direction: column;">
+  <div style="width: 50%; height: 50%;"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/tests/generated.rs b/tests/generated.rs
index f2af0e004..9b2c11c8b 100644
--- a/tests/generated.rs
+++ b/tests/generated.rs
@@ -4363,6 +4363,38 @@ mod generated {
         assert_eq!(layout.children[2].y, 0.0000);
     }
 
+    #[test]
+    fn percentage_size_based_on_parent_inner_size() {
+        let layout = stretch::compute(&stretch::style::Node {
+            flex_direction: stretch::style::FlexDirection::Column,
+            width: stretch::style::Dimension::Points(200.0000),
+            height: stretch::style::Dimension::Points(200.0000),
+            padding: stretch::style::Edges {
+                start: stretch::style::Dimension::Points(20.0000),
+                end: stretch::style::Dimension::Points(20.0000),
+                top: stretch::style::Dimension::Points(20.0000),
+                bottom: stretch::style::Dimension::Points(20.0000),
+                ..Default::default()
+            },
+            children: vec![stretch::style::Node {
+                width: stretch::style::Dimension::Percent(0.5000),
+                height: stretch::style::Dimension::Percent(0.5000),
+                ..Default::default()
+            }],
+            ..Default::default()
+        });
+
+        assert_eq!(layout.width, 200.0000);
+        assert_eq!(layout.height, 200.0000);
+        assert_eq!(layout.x, 0.0000);
+        assert_eq!(layout.y, 0.0000);
+
+        assert_eq!(layout.children[0].width, 80.0000);
+        assert_eq!(layout.children[0].height, 80.0000);
+        assert_eq!(layout.children[0].x, 20.0000);
+        assert_eq!(layout.children[0].y, 20.0000);
+    }
+
     #[test]
     fn wrap_reverse_row_align_content_stretch() {
         let layout = stretch::compute(&stretch::style::Node {