From 5fc12da21c8d347011eec5c83e62a3bb478fa6bd Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Wed, 28 Dec 2022 00:33:05 +0000 Subject: [PATCH 01/12] Use style helpers for creating GridPlacement::Line in gentests --- benches/generated/grid_absolute_column_end.rs | 5 +---- .../generated/grid_absolute_column_start.rs | 5 +---- benches/generated/grid_absolute_row_end.rs | 5 +---- benches/generated/grid_absolute_row_start.rs | 5 +---- .../grid_align_items_sized_center.rs | 20 ++++--------------- .../generated/grid_align_items_sized_end.rs | 20 ++++--------------- .../generated/grid_align_items_sized_start.rs | 20 ++++--------------- .../grid_align_items_sized_stretch.rs | 20 ++++--------------- .../grid_justify_items_sized_center.rs | 20 ++++--------------- .../generated/grid_justify_items_sized_end.rs | 20 ++++--------------- .../grid_justify_items_sized_start.rs | 20 ++++--------------- .../grid_justify_items_sized_stretch.rs | 20 ++++--------------- benches/generated/grid_out_of_order_items.rs | 20 ++++--------------- scripts/gentest/src/main.rs | 2 +- tests/generated/grid_absolute_column_end.rs | 5 +---- tests/generated/grid_absolute_column_start.rs | 5 +---- tests/generated/grid_absolute_row_end.rs | 5 +---- tests/generated/grid_absolute_row_start.rs | 5 +---- .../grid_align_items_sized_center.rs | 20 ++++--------------- tests/generated/grid_align_items_sized_end.rs | 20 ++++--------------- .../generated/grid_align_items_sized_start.rs | 20 ++++--------------- .../grid_align_items_sized_stretch.rs | 20 ++++--------------- .../grid_justify_items_sized_center.rs | 20 ++++--------------- .../generated/grid_justify_items_sized_end.rs | 20 ++++--------------- .../grid_justify_items_sized_start.rs | 20 ++++--------------- .../grid_justify_items_sized_stretch.rs | 20 ++++--------------- tests/generated/grid_out_of_order_items.rs | 20 ++++--------------- 27 files changed, 81 insertions(+), 321 deletions(-) diff --git a/benches/generated/grid_absolute_column_end.rs b/benches/generated/grid_absolute_column_end.rs index 06ef955eb..60cfa519e 100644 --- a/benches/generated/grid_absolute_column_end.rs +++ b/benches/generated/grid_absolute_column_end.rs @@ -5,10 +5,7 @@ pub fn compute() { let node0 = taffy .new_leaf(taffy::style::Style { position: taffy::style::Position::Absolute, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Auto, - end: taffy::style::GridPlacement::Line(1i16), - }, + grid_column: taffy::geometry::Line { start: taffy::style::GridPlacement::Auto, end: line(1i16) }, inset: taffy::geometry::Rect { left: taffy::style::LengthPercentageAuto::Points(4f32), right: taffy::style::LengthPercentageAuto::Points(3f32), diff --git a/benches/generated/grid_absolute_column_start.rs b/benches/generated/grid_absolute_column_start.rs index e81125301..11362c184 100644 --- a/benches/generated/grid_absolute_column_start.rs +++ b/benches/generated/grid_absolute_column_start.rs @@ -5,10 +5,7 @@ pub fn compute() { let node0 = taffy .new_leaf(taffy::style::Style { position: taffy::style::Position::Absolute, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, inset: taffy::geometry::Rect { left: taffy::style::LengthPercentageAuto::Points(4f32), right: taffy::style::LengthPercentageAuto::Points(3f32), diff --git a/benches/generated/grid_absolute_row_end.rs b/benches/generated/grid_absolute_row_end.rs index 571cebfb5..2526a81fa 100644 --- a/benches/generated/grid_absolute_row_end.rs +++ b/benches/generated/grid_absolute_row_end.rs @@ -5,10 +5,7 @@ pub fn compute() { let node0 = taffy .new_leaf(taffy::style::Style { position: taffy::style::Position::Absolute, - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Auto, - end: taffy::style::GridPlacement::Line(1i16), - }, + grid_row: taffy::geometry::Line { start: taffy::style::GridPlacement::Auto, end: line(1i16) }, inset: taffy::geometry::Rect { left: taffy::style::LengthPercentageAuto::Points(4f32), right: taffy::style::LengthPercentageAuto::Points(3f32), diff --git a/benches/generated/grid_absolute_row_start.rs b/benches/generated/grid_absolute_row_start.rs index c3940bbef..66975aef0 100644 --- a/benches/generated/grid_absolute_row_start.rs +++ b/benches/generated/grid_absolute_row_start.rs @@ -5,10 +5,7 @@ pub fn compute() { let node0 = taffy .new_leaf(taffy::style::Style { position: taffy::style::Position::Absolute, - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, inset: taffy::geometry::Rect { left: taffy::style::LengthPercentageAuto::Points(4f32), right: taffy::style::LengthPercentageAuto::Points(3f32), diff --git a/benches/generated/grid_align_items_sized_center.rs b/benches/generated/grid_align_items_sized_center.rs index 67f4c5d78..d7cb9e00f 100644 --- a/benches/generated/grid_align_items_sized_center.rs +++ b/benches/generated/grid_align_items_sized_center.rs @@ -4,14 +4,8 @@ pub fn compute() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -21,14 +15,8 @@ pub fn compute() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/benches/generated/grid_align_items_sized_end.rs b/benches/generated/grid_align_items_sized_end.rs index 6ec0a4abc..200df8105 100644 --- a/benches/generated/grid_align_items_sized_end.rs +++ b/benches/generated/grid_align_items_sized_end.rs @@ -4,14 +4,8 @@ pub fn compute() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -21,14 +15,8 @@ pub fn compute() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/benches/generated/grid_align_items_sized_start.rs b/benches/generated/grid_align_items_sized_start.rs index 16d9f0588..b1882f104 100644 --- a/benches/generated/grid_align_items_sized_start.rs +++ b/benches/generated/grid_align_items_sized_start.rs @@ -4,14 +4,8 @@ pub fn compute() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -21,14 +15,8 @@ pub fn compute() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/benches/generated/grid_align_items_sized_stretch.rs b/benches/generated/grid_align_items_sized_stretch.rs index 349562e6a..96512291c 100644 --- a/benches/generated/grid_align_items_sized_stretch.rs +++ b/benches/generated/grid_align_items_sized_stretch.rs @@ -4,14 +4,8 @@ pub fn compute() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -21,14 +15,8 @@ pub fn compute() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/benches/generated/grid_justify_items_sized_center.rs b/benches/generated/grid_justify_items_sized_center.rs index 1fa28e5f6..c02604a7b 100644 --- a/benches/generated/grid_justify_items_sized_center.rs +++ b/benches/generated/grid_justify_items_sized_center.rs @@ -4,14 +4,8 @@ pub fn compute() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -21,14 +15,8 @@ pub fn compute() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/benches/generated/grid_justify_items_sized_end.rs b/benches/generated/grid_justify_items_sized_end.rs index 836b4ca2b..47844d4e9 100644 --- a/benches/generated/grid_justify_items_sized_end.rs +++ b/benches/generated/grid_justify_items_sized_end.rs @@ -4,14 +4,8 @@ pub fn compute() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -21,14 +15,8 @@ pub fn compute() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/benches/generated/grid_justify_items_sized_start.rs b/benches/generated/grid_justify_items_sized_start.rs index 4b6ee18f5..5cd3ed913 100644 --- a/benches/generated/grid_justify_items_sized_start.rs +++ b/benches/generated/grid_justify_items_sized_start.rs @@ -4,14 +4,8 @@ pub fn compute() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -21,14 +15,8 @@ pub fn compute() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/benches/generated/grid_justify_items_sized_stretch.rs b/benches/generated/grid_justify_items_sized_stretch.rs index 6a8b3feaa..c936740f7 100644 --- a/benches/generated/grid_justify_items_sized_stretch.rs +++ b/benches/generated/grid_justify_items_sized_stretch.rs @@ -4,14 +4,8 @@ pub fn compute() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -21,14 +15,8 @@ pub fn compute() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/benches/generated/grid_out_of_order_items.rs b/benches/generated/grid_out_of_order_items.rs index cbb487bfc..b6bc62472 100644 --- a/benches/generated/grid_out_of_order_items.rs +++ b/benches/generated/grid_out_of_order_items.rs @@ -6,10 +6,7 @@ pub fn compute() { let node1 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); let node2 = taffy .new_leaf(taffy::style::Style { - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(35f32), height: taffy::style::Dimension::Points(35f32), @@ -21,14 +18,8 @@ pub fn compute() { let node4 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); let node5 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -39,10 +30,7 @@ pub fn compute() { let node6 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); let node7 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(10f32), height: taffy::style::Dimension::Points(10f32), diff --git a/scripts/gentest/src/main.rs b/scripts/gentest/src/main.rs index 83c847f1f..7d43e7b06 100644 --- a/scripts/gentest/src/main.rs +++ b/scripts/gentest/src/main.rs @@ -714,7 +714,7 @@ fn generate_grid_position(grid_position: &serde_json::Map) -> Tok } "line" => { let value = value() as i16; - quote!(taffy::style::GridPlacement::Line(#value)) + quote!(line(#value)) } _ => unreachable!(), }, diff --git a/tests/generated/grid_absolute_column_end.rs b/tests/generated/grid_absolute_column_end.rs index 68340985e..fcb7dac1b 100644 --- a/tests/generated/grid_absolute_column_end.rs +++ b/tests/generated/grid_absolute_column_end.rs @@ -7,10 +7,7 @@ fn grid_absolute_column_end() { let node0 = taffy .new_leaf(taffy::style::Style { position: taffy::style::Position::Absolute, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Auto, - end: taffy::style::GridPlacement::Line(1i16), - }, + grid_column: taffy::geometry::Line { start: taffy::style::GridPlacement::Auto, end: line(1i16) }, inset: taffy::geometry::Rect { left: taffy::style::LengthPercentageAuto::Points(4f32), right: taffy::style::LengthPercentageAuto::Points(3f32), diff --git a/tests/generated/grid_absolute_column_start.rs b/tests/generated/grid_absolute_column_start.rs index f6fd1c750..356c3838c 100644 --- a/tests/generated/grid_absolute_column_start.rs +++ b/tests/generated/grid_absolute_column_start.rs @@ -7,10 +7,7 @@ fn grid_absolute_column_start() { let node0 = taffy .new_leaf(taffy::style::Style { position: taffy::style::Position::Absolute, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, inset: taffy::geometry::Rect { left: taffy::style::LengthPercentageAuto::Points(4f32), right: taffy::style::LengthPercentageAuto::Points(3f32), diff --git a/tests/generated/grid_absolute_row_end.rs b/tests/generated/grid_absolute_row_end.rs index 542b310a3..c69c1a1d7 100644 --- a/tests/generated/grid_absolute_row_end.rs +++ b/tests/generated/grid_absolute_row_end.rs @@ -7,10 +7,7 @@ fn grid_absolute_row_end() { let node0 = taffy .new_leaf(taffy::style::Style { position: taffy::style::Position::Absolute, - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Auto, - end: taffy::style::GridPlacement::Line(1i16), - }, + grid_row: taffy::geometry::Line { start: taffy::style::GridPlacement::Auto, end: line(1i16) }, inset: taffy::geometry::Rect { left: taffy::style::LengthPercentageAuto::Points(4f32), right: taffy::style::LengthPercentageAuto::Points(3f32), diff --git a/tests/generated/grid_absolute_row_start.rs b/tests/generated/grid_absolute_row_start.rs index 6d407e9f7..96dbd90bd 100644 --- a/tests/generated/grid_absolute_row_start.rs +++ b/tests/generated/grid_absolute_row_start.rs @@ -7,10 +7,7 @@ fn grid_absolute_row_start() { let node0 = taffy .new_leaf(taffy::style::Style { position: taffy::style::Position::Absolute, - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, inset: taffy::geometry::Rect { left: taffy::style::LengthPercentageAuto::Points(4f32), right: taffy::style::LengthPercentageAuto::Points(3f32), diff --git a/tests/generated/grid_align_items_sized_center.rs b/tests/generated/grid_align_items_sized_center.rs index 6980f62d4..cef789834 100644 --- a/tests/generated/grid_align_items_sized_center.rs +++ b/tests/generated/grid_align_items_sized_center.rs @@ -6,14 +6,8 @@ fn grid_align_items_sized_center() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -23,14 +17,8 @@ fn grid_align_items_sized_center() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/tests/generated/grid_align_items_sized_end.rs b/tests/generated/grid_align_items_sized_end.rs index e2a4eb4d2..8c003bd90 100644 --- a/tests/generated/grid_align_items_sized_end.rs +++ b/tests/generated/grid_align_items_sized_end.rs @@ -6,14 +6,8 @@ fn grid_align_items_sized_end() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -23,14 +17,8 @@ fn grid_align_items_sized_end() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/tests/generated/grid_align_items_sized_start.rs b/tests/generated/grid_align_items_sized_start.rs index 780adb24f..8b98ea38a 100644 --- a/tests/generated/grid_align_items_sized_start.rs +++ b/tests/generated/grid_align_items_sized_start.rs @@ -6,14 +6,8 @@ fn grid_align_items_sized_start() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -23,14 +17,8 @@ fn grid_align_items_sized_start() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/tests/generated/grid_align_items_sized_stretch.rs b/tests/generated/grid_align_items_sized_stretch.rs index eaca1d8a7..be7989810 100644 --- a/tests/generated/grid_align_items_sized_stretch.rs +++ b/tests/generated/grid_align_items_sized_stretch.rs @@ -6,14 +6,8 @@ fn grid_align_items_sized_stretch() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -23,14 +17,8 @@ fn grid_align_items_sized_stretch() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/tests/generated/grid_justify_items_sized_center.rs b/tests/generated/grid_justify_items_sized_center.rs index 4347c5ba1..57c788e9a 100644 --- a/tests/generated/grid_justify_items_sized_center.rs +++ b/tests/generated/grid_justify_items_sized_center.rs @@ -6,14 +6,8 @@ fn grid_justify_items_sized_center() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -23,14 +17,8 @@ fn grid_justify_items_sized_center() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/tests/generated/grid_justify_items_sized_end.rs b/tests/generated/grid_justify_items_sized_end.rs index 34bae63c9..8e0b10969 100644 --- a/tests/generated/grid_justify_items_sized_end.rs +++ b/tests/generated/grid_justify_items_sized_end.rs @@ -6,14 +6,8 @@ fn grid_justify_items_sized_end() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -23,14 +17,8 @@ fn grid_justify_items_sized_end() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/tests/generated/grid_justify_items_sized_start.rs b/tests/generated/grid_justify_items_sized_start.rs index ba45d0999..d72826b3d 100644 --- a/tests/generated/grid_justify_items_sized_start.rs +++ b/tests/generated/grid_justify_items_sized_start.rs @@ -6,14 +6,8 @@ fn grid_justify_items_sized_start() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -23,14 +17,8 @@ fn grid_justify_items_sized_start() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/tests/generated/grid_justify_items_sized_stretch.rs b/tests/generated/grid_justify_items_sized_stretch.rs index 872d3b7b9..d254e90a9 100644 --- a/tests/generated/grid_justify_items_sized_stretch.rs +++ b/tests/generated/grid_justify_items_sized_stretch.rs @@ -6,14 +6,8 @@ fn grid_justify_items_sized_stretch() { let mut taffy = taffy::Taffy::new(); let node0 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -23,14 +17,8 @@ fn grid_justify_items_sized_stretch() { .unwrap(); let node1 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(3i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(3i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(60f32), height: taffy::style::Dimension::Points(60f32), diff --git a/tests/generated/grid_out_of_order_items.rs b/tests/generated/grid_out_of_order_items.rs index 166ab6e5a..257b0cb5f 100644 --- a/tests/generated/grid_out_of_order_items.rs +++ b/tests/generated/grid_out_of_order_items.rs @@ -8,10 +8,7 @@ fn grid_out_of_order_items() { let node1 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); let node2 = taffy .new_leaf(taffy::style::Style { - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(35f32), height: taffy::style::Dimension::Points(35f32), @@ -23,14 +20,8 @@ fn grid_out_of_order_items() { let node4 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); let node5 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, - grid_column: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(20f32), height: taffy::style::Dimension::Points(20f32), @@ -41,10 +32,7 @@ fn grid_out_of_order_items() { let node6 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); let node7 = taffy .new_leaf(taffy::style::Style { - grid_row: taffy::geometry::Line { - start: taffy::style::GridPlacement::Line(1i16), - end: taffy::style::GridPlacement::Auto, - }, + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, size: taffy::geometry::Size { width: taffy::style::Dimension::Points(10f32), height: taffy::style::Dimension::Points(10f32), From c819ee82b8b209abec1cde74cffaeea894de41ca Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Wed, 28 Dec 2022 00:48:46 +0000 Subject: [PATCH 02/12] Introduce newtype system for grid line coordinate handling --- src/compute/grid/implicit_grid.rs | 96 +++++++------- src/compute/grid/mod.rs | 31 ++--- src/compute/grid/placement.rs | 88 ++++++------- src/compute/grid/track_sizing.rs | 4 +- src/compute/grid/types/cell_occupancy.rs | 22 ++-- src/compute/grid/types/coordinates.rs | 113 ++++++++++++++++ src/compute/grid/types/grid_item.rs | 15 ++- src/compute/grid/types/grid_track_counts.rs | 30 +---- src/compute/grid/types/mod.rs | 2 + src/compute/grid/util/coordinates.rs | 36 ------ src/compute/grid/util/mod.rs | 7 +- src/compute/grid/util/test_helpers.rs | 10 ++ src/style/grid.rs | 135 ++++++++++++-------- src/style/mod.rs | 2 + 14 files changed, 345 insertions(+), 246 deletions(-) create mode 100644 src/compute/grid/types/coordinates.rs delete mode 100644 src/compute/grid/util/coordinates.rs diff --git a/src/compute/grid/implicit_grid.rs b/src/compute/grid/implicit_grid.rs index 2319b0caf..a0008b611 100644 --- a/src/compute/grid/implicit_grid.rs +++ b/src/compute/grid/implicit_grid.rs @@ -1,11 +1,11 @@ //! This module is not required for spec compliance, but is used as a performance optimisation //! to reduce the number of allocations required when creating a grid. use crate::geometry::Line; -use crate::style::{GridPlacement, Style}; +use crate::style::{GenericGridPlacement, GridPlacement, Style}; use core::cmp::{max, min}; use super::types::TrackCounts; -use super::util::css_grid_line_into_origin_zero_coords; +use super::OriginZeroLine; /// Estimate the number of rows and columns in the grid /// This is used as a performance optimisation to pre-size vectors and reduce allocations. It also forms a necessary step @@ -28,12 +28,12 @@ pub(crate) fn compute_grid_size_estimate<'a>( // Compute *track* count estimates for each axis from: // - The explicit track counts // - The origin-zero coordinate min and max grid line variables - let negative_implicit_inline_tracks = col_min.unsigned_abs(); + let negative_implicit_inline_tracks = col_min.0.unsigned_abs(); let explicit_inline_tracks = explicit_col_count; - let mut positive_implicit_inline_tracks = max(explicit_col_count, col_max.unsigned_abs()) - explicit_col_count; - let negative_implicit_block_tracks = row_min.unsigned_abs(); + let mut positive_implicit_inline_tracks = max(explicit_col_count, col_max.0.unsigned_abs()) - explicit_col_count; + let negative_implicit_block_tracks = row_min.0.unsigned_abs(); let explicit_block_tracks = explicit_row_count; - let mut positive_implicit_block_tracks = max(explicit_row_count, row_max.unsigned_abs()) - explicit_row_count; + let mut positive_implicit_block_tracks = max(explicit_row_count, row_max.0.unsigned_abs()) - explicit_row_count; // In each axis, adjust positive track estimate if any items have a span that does not fit within // the total number of tracks in the estimate @@ -64,8 +64,9 @@ fn get_known_child_positions<'a>( children_iter: impl Iterator, explicit_col_count: u16, explicit_row_count: u16, -) -> (i16, i16, u16, i16, i16, u16) { - let (mut col_min, mut col_max, mut col_max_span, mut row_min, mut row_max, mut row_max_span) = (0, 0, 0, 0, 0, 0); +) -> (OriginZeroLine, OriginZeroLine, u16, OriginZeroLine, OriginZeroLine, u16) { + let (mut col_min, mut col_max, mut col_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0); + let (mut row_min, mut row_max, mut row_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0); children_iter.for_each(|child_style: &Style| { // Note: that the children reference the lines in between (and around) the tracks not tracks themselves, // and thus we must subtract 1 to get an accurate estimate of the number of tracks @@ -89,8 +90,11 @@ fn get_known_child_positions<'a>( /// /// Values are returned in origin-zero coordinates #[inline] -fn child_min_line_max_line_span(line: Line, explicit_track_count: u16) -> (i16, i16, u16) { - use GridPlacement::*; +fn child_min_line_max_line_span( + line: Line, + explicit_track_count: u16, +) -> (OriginZeroLine, OriginZeroLine, u16) { + use GenericGridPlacement::*; // 8.3.1. Grid Placement Conflict Handling // A. If the placement for a grid item contains two lines, and the start line is further end-ward than the end line, swap the two lines. @@ -98,58 +102,55 @@ fn child_min_line_max_line_span(line: Line, explicit_track_count: // C. If the placement contains two spans, remove the one contributed by the end grid-placement property. // D. If the placement contains only a span for a named line, replace it with a span of 1. - let into_oz = |grid_line: i16| css_grid_line_into_origin_zero_coords(grid_line, explicit_track_count); + // Convert line into origin-zero coordinates before attempting to analyze + let oz_line = line.into_origin_zero(explicit_track_count); - let min = match (line.start, line.end) { + let min = match (oz_line.start, oz_line.end) { // Both tracks specified (Line(track1), Line(track2)) => { - let track1_oz = into_oz(track1); - let track2_oz = into_oz(track2); // See rules A and B above - if track1_oz == track2_oz { - track1_oz + if track1 == track2 { + track1 } else { - min(track1_oz, track2_oz) + min(track1, track2) } } // Start track specified - (Line(track), Auto) => into_oz(track), - (Line(track), Span(_)) => into_oz(track), + (Line(track), Auto) => track, + (Line(track), Span(_)) => track, // End track specified - (Auto, Line(track)) => into_oz(track), - (Span(span), Line(track)) => into_oz(track) - (span as i16), + (Auto, Line(track)) => track, + (Span(span), Line(track)) => track - span, // Only spans or autos - // We ignore spans here by returning 1 which never effect the estimate as these are accounted for separately - (Auto | Span(_), Auto | Span(_)) => 1, + // We ignore spans here by returning 0 which never effect the estimate as these are accounted for separately + (Auto | Span(_), Auto | Span(_)) => OriginZeroLine(0), }; - let max = match (line.start, line.end) { + let max = match (oz_line.start, oz_line.end) { // Both tracks specified (Line(track1), Line(track2)) => { - let track1_oz = into_oz(track1); - let track2_oz = into_oz(track2); // See rules A and B above - if track1_oz == track2_oz { - track1_oz + 1 + if track1 == track2 { + track1 + 1 } else { - max(track1_oz, track2_oz) + max(track1, track2) } } // Start track specified - (Line(track), Auto) => into_oz(track) + 1, - (Line(track), Span(span)) => into_oz(track) + (span as i16), + (Line(track), Auto) => track + 1, + (Line(track), Span(span)) => track + span, // End track specified - (Auto, Line(track)) => into_oz(track), - (Span(_), Line(track)) => into_oz(track), + (Auto, Line(track)) => track, + (Span(_), Line(track)) => track, // Only spans or autos - // We ignore spans here by returning 1 which never effect the estimate as these are accounted for separately - (Auto | Span(_), Auto | Span(_)) => 1, + // We ignore spans here by returning 0 which never effect the estimate as these are accounted for separately + (Auto | Span(_), Auto | Span(_)) => OriginZeroLine(0), }; // Calculate span only for indefinitely placed items as we don't need for other items (whose required space will @@ -167,22 +168,23 @@ fn child_min_line_max_line_span(line: Line, explicit_track_count: mod tests { mod test_child_min_max_line { use super::super::child_min_line_max_line_span; + use super::super::OriginZeroLine; use crate::geometry::Line; - use crate::style::GridPlacement::*; + use crate::style_helpers::*; #[test] fn child_min_max_line_auto() { - let (min_col, max_col, span) = child_min_line_max_line_span(Line { start: Line(5), end: Span(6) }, 6); - assert_eq!(min_col, 4); - assert_eq!(max_col, 10); + let (min_col, max_col, span) = child_min_line_max_line_span(Line { start: line(5), end: span(6) }, 6); + assert_eq!(min_col, OriginZeroLine(4)); + assert_eq!(max_col, OriginZeroLine(10)); assert_eq!(span, 1); } #[test] fn child_min_max_line_negative_track() { - let (min_col, max_col, span) = child_min_line_max_line_span(Line { start: Line(-5), end: Span(3) }, 6); - assert_eq!(min_col, 2); - assert_eq!(max_col, 5); + let (min_col, max_col, span) = child_min_line_max_line_span(Line { start: line(-5), end: span(3) }, 6); + assert_eq!(min_col, OriginZeroLine(2)); + assert_eq!(max_col, OriginZeroLine(5)); assert_eq!(span, 1); } } @@ -190,15 +192,15 @@ mod tests { mod test_intial_grid_sizing { use super::super::compute_grid_size_estimate; use crate::compute::grid::util::test_helpers::*; - use crate::style::GridPlacement::*; + use crate::style_helpers::*; #[test] fn explicit_grid_sizing_with_children() { let explicit_col_count = 6; let explicit_row_count = 8; let child_styles = vec![ - (Line(1), Span(2), Line(2), Auto).into_grid_child(), - (Line(-4), Auto, Line(-2), Auto).into_grid_child(), + (line(1), span(2), line(2), auto()).into_grid_child(), + (line(-4), auto(), line(-2), auto()).into_grid_child(), ]; let (inline, block) = compute_grid_size_estimate(explicit_col_count, explicit_row_count, child_styles.iter()); @@ -215,8 +217,8 @@ mod tests { let explicit_col_count = 4; let explicit_row_count = 4; let child_styles = vec![ - (Line(-6), Span(2), Line(-8), Auto).into_grid_child(), - (Line(4), Auto, Line(3), Auto).into_grid_child(), + (line(-6), span(2), line(-8), auto()).into_grid_child(), + (line(4), auto(), line(3), auto()).into_grid_child(), ]; let (inline, block) = compute_grid_size_estimate(explicit_col_count, explicit_row_count, child_styles.iter()); diff --git a/src/compute/grid/mod.rs b/src/compute/grid/mod.rs index 52c1aaa83..eee1dc31d 100644 --- a/src/compute/grid/mod.rs +++ b/src/compute/grid/mod.rs @@ -16,7 +16,8 @@ use implicit_grid::compute_grid_size_estimate; use placement::place_grid_items; use track_sizing::{determine_if_item_crosses_flexible_tracks, resolve_item_track_indexes, track_sizing_algorithm}; use types::{CellOccupancyMatrix, GridTrack}; -use util::coordinates::css_grid_line_into_origin_zero_coords; + +pub(crate) use types::{GridCoordinate, GridLine, OriginZeroLine}; #[cfg(feature = "debug")] use crate::debug::NODE_LOGGER; @@ -285,22 +286,22 @@ pub fn compute( if child_style.position == Position::Absolute { // Convert grid-col-{start/end} into Option's of indexes into the columns vector // The Option is None if the style property is Auto and an unresolvable Span - let maybe_grid_cols = child_style.grid_column.resolve_absolutely_positioned_grid_tracks(); - let maybe_col_indexes = maybe_grid_cols.map(|maybe_grid_line| { - maybe_grid_line.map(|grid_line| { - let oz_line = css_grid_line_into_origin_zero_coords(grid_line, final_col_counts.explicit); - final_col_counts.oz_line_to_grid_track_vec_index(oz_line) as usize - }) - }); + let maybe_col_indexes = child_style + .grid_column + .into_origin_zero(final_col_counts.explicit) + .resolve_absolutely_positioned_grid_tracks() + .map(|maybe_grid_line| { + maybe_grid_line.map(|line: OriginZeroLine| line.into_track_vec_index(final_col_counts)) + }); // Convert grid-row-{start/end} into Option's of indexes into the row vector // The Option is None if the style property is Auto and an unresolvable Span - let maybe_grid_rows = child_style.grid_row.resolve_absolutely_positioned_grid_tracks(); - let maybe_row_indexes = maybe_grid_rows.map(|maybe_grid_line| { - maybe_grid_line.map(|grid_line| { - let oz_line = css_grid_line_into_origin_zero_coords(grid_line, final_row_counts.explicit); - final_row_counts.oz_line_to_grid_track_vec_index(oz_line) as usize - }) - }); + let maybe_row_indexes = child_style + .grid_row + .into_origin_zero(final_col_counts.explicit) + .resolve_absolutely_positioned_grid_tracks() + .map(|maybe_grid_line| { + maybe_grid_line.map(|line: OriginZeroLine| line.into_track_vec_index(final_row_counts)) + }); let grid_area = Rect { top: maybe_row_indexes.start.map(|index| rows[index].offset).unwrap_or(0.0), diff --git a/src/compute/grid/placement.rs b/src/compute/grid/placement.rs index 0c8218848..7e56d9c9a 100644 --- a/src/compute/grid/placement.rs +++ b/src/compute/grid/placement.rs @@ -1,11 +1,11 @@ //! Implements placing items in the grid and resolving the implicit grid. //! https://www.w3.org/TR/css-grid-1/#placement use super::types::{CellOccupancyMatrix, CellOccupancyState, GridItem}; -use super::util::css_grid_line_into_origin_zero_coords; +use super::OriginZeroLine; use crate::axis::{AbsoluteAxis, InBothAbsAxis}; use crate::geometry::Line; use crate::node::Node; -use crate::style::{GridAutoFlow, GridPlacement, Style}; +use crate::style::{GridAutoFlow, OriginZeroGridPlacement, Style}; use crate::sys::Vec; /// 8.5. Grid Item Placement Algorithm @@ -28,12 +28,8 @@ pub(super) fn place_grid_items<'a, ChildIter>( let explicit_row_count = cell_occupancy_matrix.track_counts(AbsoluteAxis::Vertical).explicit; move |(index, node, style): (usize, Node, &'a Style)| -> (_, _, _, &'a Style) { let origin_zero_placement = InBothAbsAxis { - horizontal: style.grid_column.map(|placement| { - placement.map_track(|track| css_grid_line_into_origin_zero_coords(track, explicit_col_count)) - }), - vertical: style.grid_row.map(|placement| { - placement.map_track(|track| css_grid_line_into_origin_zero_coords(track, explicit_row_count)) - }), + horizontal: style.grid_column.map(|placement| placement.into_origin_zero_placement(explicit_col_count)), + vertical: style.grid_row.map(|placement| placement.into_origin_zero_placement(explicit_row_count)), }; (index, node, origin_zero_placement, style) } @@ -136,7 +132,7 @@ pub(super) fn place_grid_items<'a, ChildIter>( // Otherwise set it to the position of the current item so that the next item it placed after it. grid_position = match grid_auto_flow.is_dense() { true => (0, 0), - false => (primary_span.end as u16, secondary_span.start as u16), + false => (primary_span.end.0 as u16, secondary_span.start.0 as u16), } }); } @@ -144,12 +140,12 @@ pub(super) fn place_grid_items<'a, ChildIter>( /// 8.5. Grid Item Placement Algorithm /// Place a single definitely placed item into the grid fn place_definite_grid_item( - placement: InBothAbsAxis>, + placement: InBothAbsAxis>, primary_axis: AbsoluteAxis, -) -> (Line, Line) { +) -> (Line, Line) { // Resolve spans to tracks - let primary_span = placement.get(primary_axis).resolve_definite_grid_tracks(); - let secondary_span = placement.get(primary_axis.other_axis()).resolve_definite_grid_tracks(); + let primary_span = placement.get(primary_axis).resolve_definite_grid_lines(); + let secondary_span = placement.get(primary_axis.other_axis()).resolve_definite_grid_lines(); (primary_span, secondary_span) } @@ -158,21 +154,21 @@ fn place_definite_grid_item( /// Step 2. Place remaining children with definite secondary axis positions fn place_definite_secondary_axis_item( cell_occupancy_matrix: &CellOccupancyMatrix, - placement: InBothAbsAxis>, + placement: InBothAbsAxis>, auto_flow: GridAutoFlow, -) -> (Line, Line) { +) -> (Line, Line) { let primary_axis = auto_flow.primary_axis(); let secondary_axis = primary_axis.other_axis(); - let secondary_axis_placement = placement.get(secondary_axis).resolve_definite_grid_tracks(); + let secondary_axis_placement = placement.get(secondary_axis).resolve_definite_grid_lines(); let starting_position = match auto_flow.is_dense() { - true => 0, + true => OriginZeroLine(0), false => cell_occupancy_matrix .last_of_type(primary_axis, secondary_axis_placement.start, CellOccupancyState::AutoPlaced) - .unwrap_or(0), + .unwrap_or(OriginZeroLine(0)), }; - let mut position: i16 = starting_position; + let mut position: OriginZeroLine = starting_position; loop { let primary_axis_placement = placement.get(primary_axis).resolve_indefinite_grid_tracks(position); @@ -194,10 +190,10 @@ fn place_definite_secondary_axis_item( /// Step 4. Position the remaining grid items. fn place_indefinitely_positioned_item( cell_occupancy_matrix: &CellOccupancyMatrix, - placement: InBothAbsAxis>, + placement: InBothAbsAxis>, auto_flow: GridAutoFlow, grid_position: (u16, u16), -) -> (Line, Line) { +) -> (Line, Line) { let primary_axis = auto_flow.primary_axis(); let primary_placement_style = placement.get(primary_axis); @@ -216,7 +212,7 @@ fn place_indefinitely_positioned_item( let (mut primary_idx, mut secondary_idx) = grid_position; if has_definite_primary_axis_position { - let definite_primary_placement = primary_placement_style.resolve_definite_grid_tracks(); + let definite_primary_placement = primary_placement_style.resolve_definite_grid_lines(); let defined_primary_idx = cell_occupancy_matrix.lines_to_tracks(primary_axis.other_axis(), definite_primary_placement).start as u16; @@ -282,8 +278,8 @@ fn record_grid_placement( index: usize, style: &Style, primary_axis: AbsoluteAxis, - primary_span: Line, - secondary_span: Line, + primary_span: Line, + secondary_span: Line, placement_type: CellOccupancyState, ) { #[cfg(test)] @@ -321,7 +317,7 @@ mod tests { use crate::compute::grid::util::*; use crate::compute::grid::CellOccupancyMatrix; use crate::prelude::*; - use crate::style::{GridAutoFlow, GridPlacement::*}; + use crate::style::GridAutoFlow; use slotmap::SlotMap; use super::super::place_grid_items; @@ -355,7 +351,7 @@ mod tests { { assert_eq!(item.node, *node); let actual_placement = (item.column.start, item.column.end, item.row.start, item.row.end); - assert_eq!(actual_placement, *expected_placement, "Item {idx} (0-indexed)"); + assert_eq!(actual_placement, (*expected_placement).into_oz(), "Item {idx} (0-indexed)"); } // Assert that the correct number of implicit rows have been generated @@ -374,10 +370,10 @@ mod tests { let mut sm = SlotMap::new(); vec![ // node, style (grid coords), expected_placement (oz coords) - (1, sm.insert(()), (Line(1), Auto, Line(1), Auto).into_grid_child(), (0, 1, 0, 1)), - (2, sm.insert(()), (Line(-4), Auto, Line(-3), Auto).into_grid_child(), (-1, 0, 0, 1)), - (3, sm.insert(()), (Line(-3), Auto, Line(-4), Auto).into_grid_child(), (0, 1, -1, 0)), - (4, sm.insert(()), (Line(3), Span(2), Line(5), Auto).into_grid_child(), (2, 4, 4, 5)), + (1, sm.insert(()), (line(1), auto(), line(1), auto()).into_grid_child(), (0, 1, 0, 1)), + (2, sm.insert(()), (line(-4), auto(), line(-3), auto()).into_grid_child(), (-1, 0, 0, 1)), + (3, sm.insert(()), (line(-3), auto(), line(-4), auto()).into_grid_child(), (0, 1, -1, 0)), + (4, sm.insert(()), (line(3), span(2), line(5), auto()).into_grid_child(), (2, 4, 4, 5)), ] }; let expected_cols = TrackCounts { negative_implicit: 1, explicit: 2, positive_implicit: 2 }; @@ -392,7 +388,7 @@ mod tests { let explicit_row_count = 2; let children = { let mut sm = SlotMap::new(); - let auto_child = (Auto, Auto, Auto, Auto).into_grid_child(); + let auto_child = (auto(), auto(), auto(), auto()).into_grid_child(); vec![ // output order, node, style (grid coords), expected_placement (oz coords) (1, sm.insert(()), auto_child.clone(), (0, 1, 0, 1)), @@ -417,7 +413,7 @@ mod tests { let explicit_row_count = 2; let children = { let mut sm = SlotMap::new(); - let auto_child = (Auto, Auto, Auto, Auto).into_grid_child(); + let auto_child = (auto(), auto(), auto(), auto()).into_grid_child(); vec![ // output order, node, style (grid coords), expected_placement (oz coords) (1, sm.insert(()), auto_child.clone(), (0, 1, 0, 1)), @@ -444,7 +440,7 @@ mod tests { let mut sm = SlotMap::new(); vec![ // output order, node, style (grid coords), expected_placement (oz coords) - (1, sm.insert(()), (Span(5), Auto, Auto, Auto).into_grid_child(), (0, 5, 0, 1)), + (1, sm.insert(()), (span(5), auto(), auto(), auto()).into_grid_child(), (0, 5, 0, 1)), ] }; let expected_cols = TrackCounts { negative_implicit: 0, explicit: 2, positive_implicit: 3 }; @@ -461,10 +457,10 @@ mod tests { let mut sm = SlotMap::new(); vec![ // output order, node, style (grid coords), expected_placement (oz coords) - (1, sm.insert(()), (Span(2), Auto, Line(1), Auto).into_grid_child(), (0, 2, 0, 1)), - (2, sm.insert(()), (Auto, Auto, Line(2), Auto).into_grid_child(), (0, 1, 1, 2)), - (3, sm.insert(()), (Auto, Auto, Line(1), Auto).into_grid_child(), (2, 3, 0, 1)), - (4, sm.insert(()), (Auto, Auto, Line(4), Auto).into_grid_child(), (0, 1, 3, 4)), + (1, sm.insert(()), (span(2), auto(), line(1), auto()).into_grid_child(), (0, 2, 0, 1)), + (2, sm.insert(()), (auto(), auto(), line(2), auto()).into_grid_child(), (0, 1, 1, 2)), + (3, sm.insert(()), (auto(), auto(), line(1), auto()).into_grid_child(), (2, 3, 0, 1)), + (4, sm.insert(()), (auto(), auto(), line(4), auto()).into_grid_child(), (0, 1, 3, 4)), ] }; let expected_cols = TrackCounts { negative_implicit: 0, explicit: 2, positive_implicit: 1 }; @@ -481,9 +477,9 @@ mod tests { let mut sm = SlotMap::new(); vec![ // output order, node, style (grid coords), expected_placement (oz coords) - (2, sm.insert(()), (Auto, Auto, Line(2), Auto).into_grid_child(), (0, 1, 1, 2)), - (1, sm.insert(()), (Line(-4), Auto, Line(2), Auto).into_grid_child(), (-1, 0, 1, 2)), - (3, sm.insert(()), (Auto, Auto, Line(1), Auto).into_grid_child(), (0, 1, 0, 1)), + (2, sm.insert(()), (auto(), auto(), line(2), auto()).into_grid_child(), (0, 1, 1, 2)), + (1, sm.insert(()), (line(-4), auto(), line(2), auto()).into_grid_child(), (-1, 0, 1, 2)), + (3, sm.insert(()), (auto(), auto(), line(1), auto()).into_grid_child(), (0, 1, 0, 1)), ] }; let expected_cols = TrackCounts { negative_implicit: 1, explicit: 2, positive_implicit: 0 }; @@ -500,9 +496,9 @@ mod tests { let mut sm = SlotMap::new(); vec![ // output order, node, style (grid coords), expected_placement (oz coords) - (1, sm.insert(()), (Line(2), Auto, Line(1), Auto).into_grid_child(), (1, 2, 0, 1)), // Definitely positioned in column 2 - (2, sm.insert(()), (Span(2), Auto, Auto, Auto).into_grid_child(), (2, 4, 0, 1)), // Spans 2 columns, so positioned after item 1 - (3, sm.insert(()), (Auto, Auto, Auto, Auto).into_grid_child(), (0, 1, 0, 1)), // Spans 1 column, so should be positioned before item 1 + (1, sm.insert(()), (line(2), auto(), line(1), auto()).into_grid_child(), (1, 2, 0, 1)), // Definitely positioned in column 2 + (2, sm.insert(()), (span(2), auto(), auto(), auto()).into_grid_child(), (2, 4, 0, 1)), // Spans 2 columns, so positioned after item 1 + (3, sm.insert(()), (auto(), auto(), auto(), auto()).into_grid_child(), (0, 1, 0, 1)), // Spans 1 column, so should be positioned before item 1 ] }; let expected_cols = TrackCounts { negative_implicit: 0, explicit: 4, positive_implicit: 0 }; @@ -519,9 +515,9 @@ mod tests { let mut sm = SlotMap::new(); vec![ // output order, node, style (grid coords), expected_placement (oz coords) - (1, sm.insert(()), (Auto, Span(3), Auto, Auto).into_grid_child(), (0, 3, 0, 1)), // Width 3 - (2, sm.insert(()), (Auto, Span(3), Auto, Auto).into_grid_child(), (0, 3, 1, 2)), // Width 3 (wraps to next row) - (3, sm.insert(()), (Auto, Span(1), Auto, Auto).into_grid_child(), (3, 4, 1, 2)), // Width 1 (uses second row as we're already on it) + (1, sm.insert(()), (auto(), span(3), auto(), auto()).into_grid_child(), (0, 3, 0, 1)), // Width 3 + (2, sm.insert(()), (auto(), span(3), auto(), auto()).into_grid_child(), (0, 3, 1, 2)), // Width 3 (wraps to next row) + (3, sm.insert(()), (auto(), span(1), auto(), auto()).into_grid_child(), (3, 4, 1, 2)), // Width 1 (uses second row as we're already on it) ] }; let expected_cols = TrackCounts { negative_implicit: 0, explicit: 4, positive_implicit: 0 }; diff --git a/src/compute/grid/track_sizing.rs b/src/compute/grid/track_sizing.rs index a2ca95531..d001ae218 100644 --- a/src/compute/grid/track_sizing.rs +++ b/src/compute/grid/track_sizing.rs @@ -136,8 +136,8 @@ pub(super) fn compute_alignment_gutter_adjustment( /// Convert origin-zero coordinates track placement in grid track vector indexes pub(super) fn resolve_item_track_indexes(items: &mut [GridItem], column_counts: TrackCounts, row_counts: TrackCounts) { for item in items { - item.column_indexes = item.column.map(|oz_index| column_counts.oz_line_to_grid_track_vec_index(oz_index)); - item.row_indexes = item.row.map(|oz_index| row_counts.oz_line_to_grid_track_vec_index(oz_index)); + item.column_indexes = item.column.map(|line| line.into_track_vec_index(column_counts) as u16); + item.row_indexes = item.row.map(|line| line.into_track_vec_index(row_counts) as u16); } } diff --git a/src/compute/grid/types/cell_occupancy.rs b/src/compute/grid/types/cell_occupancy.rs index 8fa9450d2..88ec3043e 100644 --- a/src/compute/grid/types/cell_occupancy.rs +++ b/src/compute/grid/types/cell_occupancy.rs @@ -1,6 +1,7 @@ //! Contains CellOccupancyMatrix used to track occupied cells during grid placement use super::TrackCounts; use crate::axis::AbsoluteAxis; +use crate::compute::grid::OriginZeroLine; use crate::geometry::Line; use crate::sys::Vec; use core::cmp::{max, min}; @@ -140,8 +141,8 @@ impl CellOccupancyMatrix { pub fn mark_area_as( &mut self, primary_axis: AbsoluteAxis, - primary_span: Line, - secondary_span: Line, + primary_span: Line, + secondary_span: Line, value: CellOccupancyState, ) { let (row_span, column_span) = match primary_axis { @@ -170,13 +171,13 @@ impl CellOccupancyMatrix { /// Converts a span of grid lines in OriginZero coordinates into a range a tracks suitable /// for indexing into this CellOccupancyMatrix - pub fn lines_to_tracks(&self, axis: AbsoluteAxis, span: Line) -> Range { + pub fn lines_to_tracks(&self, axis: AbsoluteAxis, span: Line) -> Range { self.track_counts(axis).oz_line_range_to_track_range(span) } /// Converts a range a tracks indexes from this CellOccupancyMatrix into a span of grid lines /// in OriginZero coordinates - pub fn tracks_to_lines(&self, axis: AbsoluteAxis, span: Range) -> Line { + pub fn tracks_to_lines(&self, axis: AbsoluteAxis, span: Range) -> Line { self.track_counts(axis).track_range_to_oz_line_range(span) } @@ -185,8 +186,8 @@ impl CellOccupancyMatrix { pub fn line_area_is_unoccupied( &self, primary_axis: AbsoluteAxis, - primary_span: Line, - secondary_span: Line, + primary_span: Line, + secondary_span: Line, ) -> bool { let primary_range = self.track_counts(primary_axis).oz_line_range_to_track_range(primary_span); let secondary_range = self.track_counts(primary_axis.other_axis()).oz_line_range_to_track_range(secondary_span); @@ -240,9 +241,14 @@ impl CellOccupancyMatrix { /// Given an axis and a track index /// Search backwards from the end of the track and find the last grid cell matching the specified state (if any) /// Return the index of that cell or None. - pub fn last_of_type(&self, track_type: AbsoluteAxis, track_index: i16, kind: CellOccupancyState) -> Option { + pub fn last_of_type( + &self, + track_type: AbsoluteAxis, + start_at: OriginZeroLine, + kind: CellOccupancyState, + ) -> Option { let track_counts = self.track_counts(track_type.other_axis()); - let track_computed_index = track_counts.oz_line_to_next_track(track_index); + let track_computed_index = track_counts.oz_line_to_next_track(start_at); let maybe_index = match track_type { AbsoluteAxis::Horizontal => { diff --git a/src/compute/grid/types/coordinates.rs b/src/compute/grid/types/coordinates.rs new file mode 100644 index 000000000..d05e8e19b --- /dev/null +++ b/src/compute/grid/types/coordinates.rs @@ -0,0 +1,113 @@ +//! Taffy uses two coordinate systems to refer to grid lines (the gaps/gutters between rows/columns): +use super::super::types::TrackCounts; +use core::num::NonZeroI16; +use core::ops::{Add, AddAssign, Sub}; + +/// Represents a grid line position in "CSS Grid Line" coordinates +/// +/// "CSS Grid Line" coordinates are those used in grid-row/grid-column in the CSS grid spec: +/// - The line at left hand (or top) edge of the explicit grid is line 1 +/// (and counts up from there) +/// - The line at the right hand (or bottom) edge of the explicit grid in -1 +/// (and counts down from there) +/// - 0 is not a valid index +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(transparent)] +pub struct GridLine(pub NonZeroI16); + +impl From for GridLine { + fn from(value: NonZeroI16) -> Self { + Self(value) + } +} +impl TryFrom for GridLine { + type Error = (); + fn try_from(value: i16) -> Result { + NonZeroI16::new(value).map(GridLine).ok_or(()) + } +} + +impl GridLine { + /// Returns the underlying i16 + pub fn as_i16(self) -> i16 { + self.0.get() + } + + /// Convert into OriginZero coordinates using the specified explicit track count + pub(crate) fn into_origin_zero_line(self, explicit_track_count: u16) -> OriginZeroLine { + let grid_line = self.as_i16(); + + // Note: grid_line cannot be zero because it comes from a NonZeroI16 + let oz_line = if grid_line > 0 { + grid_line - 1 + } else { + let explicit_line_count = explicit_track_count + 1; + grid_line + explicit_line_count as i16 + }; + + OriginZeroLine(oz_line) + } +} + +/// Represents a grid line position in "OriginZero" coordinates +/// +/// "OriginZero" coordinates are a normalized form: +/// - The line at left hand (or top) edge of the explicit grid is line 0 +/// - The next line to the right (or down) is 1, and so on +/// - The next line to the left (or up) is -1, and so on +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[repr(transparent)] +pub struct OriginZeroLine(pub i16); + +// Add and Sub with Self +impl Add for OriginZeroLine { + type Output = Self; + fn add(self, rhs: OriginZeroLine) -> Self::Output { + OriginZeroLine(self.0 + rhs.0) + } +} +impl Sub for OriginZeroLine { + type Output = Self; + fn sub(self, rhs: OriginZeroLine) -> Self::Output { + OriginZeroLine(self.0 - rhs.0) + } +} + +// Add and Sub with u16 +impl Add for OriginZeroLine { + type Output = Self; + fn add(self, rhs: u16) -> Self::Output { + OriginZeroLine(self.0 + rhs as i16) + } +} +impl AddAssign for OriginZeroLine { + fn add_assign(&mut self, rhs: u16) { + self.0 += rhs as i16; + } +} +impl Sub for OriginZeroLine { + type Output = Self; + fn sub(self, rhs: u16) -> Self::Output { + OriginZeroLine(self.0 - rhs as i16) + } +} + +impl OriginZeroLine { + /// Converts a grid line in OriginZero coordinates into the index of that same grid line in the GridTrackVec. + pub(crate) fn into_track_vec_index(self, track_counts: TrackCounts) -> usize { + assert!( + self.0 >= -(track_counts.negative_implicit as i16), + "OriginZero grid line cannot be less than the number of negative grid lines" + ); + assert!( + self.0 <= (track_counts.explicit + track_counts.positive_implicit) as i16, + "OriginZero grid line cannot be more than the number of positive grid lines" + ); + 2 * ((self.0 + track_counts.negative_implicit as i16) as usize) + } +} + +/// A trait for the different coordinates used to define grid lines. +pub trait GridCoordinate: Copy {} +impl GridCoordinate for GridLine {} +impl GridCoordinate for OriginZeroLine {} diff --git a/src/compute/grid/types/grid_item.rs b/src/compute/grid/types/grid_item.rs index 57fa54eb6..c9643b398 100644 --- a/src/compute/grid/types/grid_item.rs +++ b/src/compute/grid/types/grid_item.rs @@ -2,6 +2,7 @@ use super::GridTrack; use crate::axis::AbstractAxis; use crate::compute::compute_node_layout; +use crate::compute::grid::OriginZeroLine; use crate::geometry::{Line, Rect, Size}; use crate::layout::{RunMode, SizingMode}; use crate::node::Node; @@ -26,10 +27,10 @@ pub(in super::super) struct GridItem { /// The item's definite row-start and row-end, as resolved by the placement algorithm /// (in origin-zero coordinates) - pub row: Line, + pub row: Line, /// The items definite column-start and column-end, as resolved by the placement algorithm /// (in origin-zero coordinates) - pub column: Line, + pub column: Line, /// The item's margin style pub margin: Rect, @@ -61,8 +62,8 @@ impl GridItem { /// Create a new item given a concrete placement in both axes pub fn new_with_placement_style_and_order( node: Node, - col_span: Line, - row_span: Line, + col_span: Line, + row_span: Line, style: &Style, source_order: u16, ) -> Self { @@ -84,7 +85,7 @@ impl GridItem { } /// This item's placement in the specified axis in OriginZero coordinates - pub fn placement(&self, axis: AbstractAxis) -> Line { + pub fn placement(&self, axis: AbstractAxis) -> Line { match axis { AbstractAxis::Block => self.row, AbstractAxis::Inline => self.column, @@ -110,8 +111,8 @@ impl GridItem { /// Returns the number of tracks that this item spans in the specified axis pub fn span(&self, axis: AbstractAxis) -> u16 { match axis { - AbstractAxis::Block => max(self.row.end - self.row.start, 0) as u16, - AbstractAxis::Inline => max(self.column.end - self.column.start, 0) as u16, + AbstractAxis::Block => max(self.row.end.0 - self.row.start.0, 0) as u16, + AbstractAxis::Inline => max(self.column.end.0 - self.column.start.0, 0) as u16, } } diff --git a/src/compute/grid/types/grid_track_counts.rs b/src/compute/grid/types/grid_track_counts.rs index efd6745ad..dc006605c 100644 --- a/src/compute/grid/types/grid_track_counts.rs +++ b/src/compute/grid/types/grid_track_counts.rs @@ -32,7 +32,7 @@ //! - Index 1 is the leftmost track of the implict grid. Index 3 is the second leftmost track, etc. //! - Index 0 is the leftmost grid line. Index 2 is the second leftmost line, etc. //! -use crate::geometry::Line; +use crate::{compute::grid::OriginZeroLine, geometry::Line}; use core::ops::Range; /// Stores the number of tracks in a given dimension. @@ -59,33 +59,17 @@ impl TrackCounts { } } -/// Conversion functions between OriginZero coordinates and GridTrackVec indexes -impl TrackCounts { - /// Converts a grid line in OriginZero coordinates into the index of that same grid line in the GridTrackVec. - pub fn oz_line_to_grid_track_vec_index(&self, index: i16) -> u16 { - assert!( - index >= -(self.negative_implicit as i16), - "OriginZero grid line cannot be less than the number of negative grid lines" - ); - assert!( - index <= (self.explicit + self.positive_implicit) as i16, - "OriginZero grid line cannot be more than the number of positive grid lines" - ); - 2 * ((index + self.negative_implicit as i16) as u16) - } -} - /// Conversion functions between OriginZero coordinates and CellOccupancyMatrix track indexes impl TrackCounts { /// Converts a grid line in OriginZero coordinates into the track immediately /// following that grid line as an index into the CellOccupancyMatrix. - pub fn oz_line_to_next_track(&self, index: i16) -> i16 { - index + (self.negative_implicit as i16) + pub fn oz_line_to_next_track(&self, index: OriginZeroLine) -> i16 { + index.0 + (self.negative_implicit as i16) } /// Converts start and end grid lines in OriginZero coordinates into a range of tracks /// as indexes into the CellOccupancyMatrix - pub fn oz_line_range_to_track_range(&self, input: Line) -> Range { + pub fn oz_line_range_to_track_range(&self, input: Line) -> Range { let start = self.oz_line_to_next_track(input.start); let end = self.oz_line_to_next_track(input.end); // Don't subtract 1 as output range is exclusive start..end @@ -93,13 +77,13 @@ impl TrackCounts { /// Converts a track as an index into the CellOccupancyMatrix into the grid line immediately /// preceeding that track in OriginZero coordinates. - pub fn track_to_prev_oz_line(&self, index: u16) -> i16 { - (index as i16) - (self.negative_implicit as i16) + pub fn track_to_prev_oz_line(&self, index: u16) -> OriginZeroLine { + OriginZeroLine((index as i16) - (self.negative_implicit as i16)) } /// Converts a range of tracks as indexes into the CellOccupancyMatrix into /// start and end grid lines in OriginZero coordinates - pub fn track_range_to_oz_line_range(&self, input: Range) -> Line { + pub fn track_range_to_oz_line_range(&self, input: Range) -> Line { let start = self.track_to_prev_oz_line(input.start as u16); let end = self.track_to_prev_oz_line(input.end as u16); // Don't add 1 as input range is exclusive Line { start, end } diff --git a/src/compute/grid/types/mod.rs b/src/compute/grid/types/mod.rs index 1260c9bfd..c9105fa1c 100644 --- a/src/compute/grid/types/mod.rs +++ b/src/compute/grid/types/mod.rs @@ -1,11 +1,13 @@ //! Structs and enums that are used within the grid module mod cell_occupancy; +mod coordinates; mod grid_item; mod grid_track; mod grid_track_counts; // Publish only locally in the grid module pub(super) use cell_occupancy::{CellOccupancyMatrix, CellOccupancyState}; +pub(crate) use coordinates::{GridCoordinate, GridLine, OriginZeroLine}; pub(super) use grid_item::GridItem; pub(super) use grid_track::GridTrack; pub(super) use grid_track_counts::TrackCounts; diff --git a/src/compute/grid/util/coordinates.rs b/src/compute/grid/util/coordinates.rs deleted file mode 100644 index 6e8de2086..000000000 --- a/src/compute/grid/util/coordinates.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! Taffy uses two coordinate systems to refer to grid lines (the gaps/gutters between rows/columns): -//! -//! "CSS Grid Line" coordinates are those used in grid-row/grid-column in the CSS grid spec: -//! - The line at left hand (or top) edge of the explicit grid is line 1 -//! (and counts up from there) -//! - The line at the right hand (or bottom) edge of the explicit grid in -1 -//! (and counts down from there) -//! - 0 is not a valid index -//! -//! "OriginZero" coordinates are a normalized form: -//! - The line at left hand (or top) edge of the explicit grid is line 0 -//! - The next line to the right (or down) is 1, and so on -//! - The next line to the left (or up) is -1, and so on -//! -use core::cmp::Ordering; - -/// Convert from CSS Grid Line coordinates to our custom OriginZero coordinates -pub(crate) fn css_grid_line_into_origin_zero_coords(grid_line: i16, explicit_track_count: u16) -> i16 { - let explicit_line_count = explicit_track_count + 1; - match grid_line.cmp(&0) { - Ordering::Greater => grid_line - 1, - Ordering::Less => grid_line + explicit_line_count as i16, - Ordering::Equal => panic!("Grid line of zero is invalid"), - } -} - -#[allow(dead_code)] -/// Convert from OriginZero coordinates to CSS Grid Line coordinates -pub(crate) fn origin_zero_coords_into_css_grid_line(origin_zero_line: i16, explicit_track_count: u16) -> i16 { - let explicit_line_count = explicit_track_count + 1; - if origin_zero_line >= 0 { - origin_zero_line + 1 - } else { - -(origin_zero_line + explicit_line_count as i16) - } -} diff --git a/src/compute/grid/util/mod.rs b/src/compute/grid/util/mod.rs index 2e5108a81..ea6a8ed2c 100644 --- a/src/compute/grid/util/mod.rs +++ b/src/compute/grid/util/mod.rs @@ -1,11 +1,6 @@ //! Utility functions used within the grid module -pub(super) mod coordinates; - -pub(super) use coordinates::css_grid_line_into_origin_zero_coords; -#[allow(unused_imports)] -pub(super) use coordinates::origin_zero_coords_into_css_grid_line; #[cfg(test)] pub(super) mod test_helpers; #[cfg(test)] -pub(super) use test_helpers::{CreateChildTestNode, CreateParentTestNode}; +pub(super) use test_helpers::{CreateChildTestNode, CreateExpectedPlacement, CreateParentTestNode}; diff --git a/src/compute/grid/util/test_helpers.rs b/src/compute/grid/util/test_helpers.rs index 5e43032c4..e129d88c5 100644 --- a/src/compute/grid/util/test_helpers.rs +++ b/src/compute/grid/util/test_helpers.rs @@ -1,4 +1,5 @@ //! Helpers for use in unit tests within the grid module +use super::super::OriginZeroLine; use crate::prelude::*; use crate::style::{Dimension, GridPlacement, Style}; @@ -29,3 +30,12 @@ impl CreateChildTestNode for (GridPlacement, GridPlacement, GridPlacement, GridP } } } + +pub(crate) trait CreateExpectedPlacement { + fn into_oz(self) -> (OriginZeroLine, OriginZeroLine, OriginZeroLine, OriginZeroLine); +} +impl CreateExpectedPlacement for (i16, i16, i16, i16) { + fn into_oz(self) -> (OriginZeroLine, OriginZeroLine, OriginZeroLine, OriginZeroLine) { + (OriginZeroLine(self.0), OriginZeroLine(self.1), OriginZeroLine(self.2), OriginZeroLine(self.3)) + } +} diff --git a/src/style/grid.rs b/src/style/grid.rs index 37a9f8afc..f28eb7e10 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -1,6 +1,7 @@ //! Style types for CSS Grid layout use super::{AlignContent, LengthPercentage, Style}; use crate::axis::{AbsoluteAxis, AbstractAxis}; +use crate::compute::grid::{GridCoordinate, GridLine, OriginZeroLine}; use crate::geometry::{Line, MinMax}; use crate::style::AvailableSpace; use crate::style_helpers::*; @@ -53,29 +54,41 @@ impl GridAutoFlow { } } -/// A grid line placement specification. Used for grid-[row/column]-[start/end]. Named tracks are not implemented. +/// A grid line placement specification which is generic over the coordinate system that it uses to define +/// grid line positions. /// -/// Defaults to [`GridLine::Auto`] +/// GenericGridPlacement is aliased as GridPlacement as is exposed to users of Taffy to defined styles with +/// GenericGridPlacement is aliased as OriginZeroGridPlacement and is used internally for placement computations /// -/// [Specification](https://www.w3.org/TR/css3-grid-layout/#typedef-grid-row-start-grid-line) +/// See [`crate::compute::grid::type::coordinates`] for documentation on the different coordinate systems. #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum GridPlacement { +pub enum GenericGridPlacement { /// Place item according to the auto-placement algorithm, and the parent's grid_auto_flow property Auto, /// Place item at specified line (column or row) index - Line(i16), + Line(LineType), /// Item should span specified number of tracks (columns or rows) Span(u16), } + +/// A grid line placement using the normalized OriginZero coordinates to specify line positions. +pub(crate) type OriginZeroGridPlacement = GenericGridPlacement; + +/// A grid line placement specification. Used for grid-[row/column]-[start/end]. Named tracks are not implemented. +/// +/// Defaults to [`GridLine::Auto`] +/// +/// [Specification](https://www.w3.org/TR/css3-grid-layout/#typedef-grid-row-start-grid-line) +pub type GridPlacement = GenericGridPlacement; impl TaffyAuto for GridPlacement { const AUTO: Self = Self::Auto; } impl TaffyGridLine for GridPlacement { fn from_line_index(index: i16) -> Self { - match index { - 0 => GridPlacement::Auto, - _ => GridPlacement::Line(index), + match GridLine::try_from(index) { + Ok(line) => GridPlacement::Line(line), + Err(_) => GridPlacement::Auto, } } } @@ -103,41 +116,68 @@ impl Default for GridPlacement { impl GridPlacement { /// Apply a mapping function if the [`GridPlacement`] is a `Track`. Otherwise return `self` unmodified. - pub fn map_track(&self, map_fn: impl FnOnce(i16) -> i16) -> Self { - use GridPlacement::*; - match *self { - Auto => Auto, - Span(span) => Span(span), - Line(track) => Line(map_fn(track)), + pub fn into_origin_zero_placement(self, explicit_track_count: u16) -> OriginZeroGridPlacement { + match self { + Self::Auto => OriginZeroGridPlacement::Auto, + Self::Span(span) => OriginZeroGridPlacement::Span(span), + Self::Line(line) => OriginZeroGridPlacement::Line(line.into_origin_zero_line(explicit_track_count)), } } } -impl Line { +impl Line> { #[inline] /// Whether the track position is definite in this axis (or the item will need auto placement) /// The track position is definite if least one of the start and end positions is a track index pub fn is_definite(&self) -> bool { - use GridPlacement::*; - matches!((self.start, self.end), (Line(_), _) | (_, Line(_))) + matches!((self.start, self.end), (GenericGridPlacement::Line(_), _) | (_, GenericGridPlacement::Line(_))) + } + + /// Resolves the span for an indefinite placement (a placement that does not consist of two `Track`s). + /// Panics if called on a definite placement + pub fn indefinite_span(&self) -> u16 { + use GenericGridPlacement as GP; + match (self.start, self.end) { + (GP::Line(_), GP::Auto) => 1, + (GP::Auto, GP::Line(_)) => 1, + (GP::Auto, GP::Auto) => 1, + (GP::Line(_), GP::Span(span)) => span, + (GP::Span(span), GP::Line(_)) => span, + (GP::Span(span), GP::Auto) => span, + (GP::Auto, GP::Span(span)) => span, + (GP::Span(span), GP::Span(_)) => span, + (GP::Line(_), GP::Line(_)) => panic!("indefinite_span should only be called on indefinite grid tracks"), + } } +} +impl Line { + /// Apply a mapping function if the [`GridPlacement`] is a `Track`. Otherwise return `self` unmodified. + pub fn into_origin_zero(&self, explicit_track_count: u16) -> Line { + Line { + start: self.start.into_origin_zero_placement(explicit_track_count), + end: self.end.into_origin_zero_placement(explicit_track_count), + } + } +} + +impl Line { /// If at least one of the of the start and end positions is a track index then the other end can be resolved /// into a track index purely based on the information contained with the placement specification - pub fn resolve_definite_grid_tracks(&self) -> Line { - use GridPlacement as GP; + pub fn resolve_definite_grid_lines(&self) -> Line { + use OriginZeroGridPlacement as GP; match (self.start, self.end) { - (GP::Line(track1), GP::Line(track2)) if track1 != 0 && track2 != 0 => { - if track1 == track2 { - Line { start: track1, end: track1 + 1 } + (GP::Line(line1), GP::Line(line2)) => { + if line1 == line2 { + Line { start: line1, end: line1 + 1 } } else { - Line { start: min(track1, track2), end: max(track1, track2) } + Line { start: min(line1, line2), end: max(line1, line2) } } } - (GP::Line(track), GP::Span(span)) => Line { start: track, end: track + span as i16 }, - (GP::Line(track), GP::Auto | GP::Line(0)) => Line { start: track, end: track + 1_i16 }, - (GP::Span(span), GP::Line(track)) => Line { start: track - span as i16, end: track }, - (GP::Auto | GP::Line(0), GP::Line(track)) => Line { start: track - 1_i16, end: track }, + (GP::Line(line), GP::Span(span)) => Line { start: line, end: line + span }, + (GP::Line(line), GP::Auto) => Line { start: line, end: line + 1 }, + (GP::Span(span), GP::Line(line)) => Line { start: line - span, end: line }, + (GP::Auto, GP::Line(line)) => Line { start: line - 1, end: line }, _ => panic!("resolve_definite_grid_tracks should only be called on definite grid tracks"), } } @@ -151,53 +191,36 @@ impl Line { /// /// When finally positioning the item, a value of None means that the item's grid area is bounded by the grid /// container's border box on that side. - pub fn resolve_absolutely_positioned_grid_tracks(&self) -> Line> { - use GridPlacement as GP; + pub fn resolve_absolutely_positioned_grid_tracks(&self) -> Line> { + use OriginZeroGridPlacement as GP; match (self.start, self.end) { - (GP::Line(track1), GP::Line(track2)) if track1 != 0 && track2 != 0 => { + (GP::Line(track1), GP::Line(track2)) => { if track1 == track2 { Line { start: Some(track1), end: Some(track1 + 1) } } else { Line { start: Some(min(track1, track2)), end: Some(max(track1, track2)) } } } - (GP::Line(track), GP::Span(span)) => Line { start: Some(track), end: Some(track + span as i16) }, - (GP::Line(track), GP::Auto | GP::Line(0)) => Line { start: Some(track), end: None }, - (GP::Span(span), GP::Line(track)) => Line { start: Some(track - span as i16), end: Some(track) }, - (GP::Auto | GP::Line(0), GP::Line(track)) => Line { start: None, end: Some(track) }, + (GP::Line(track), GP::Span(span)) => Line { start: Some(track), end: Some(track + span) }, + (GP::Line(track), GP::Auto) => Line { start: Some(track), end: None }, + (GP::Span(span), GP::Line(track)) => Line { start: Some(track - span), end: Some(track) }, + (GP::Auto, GP::Line(track)) => Line { start: None, end: Some(track) }, _ => Line { start: None, end: None }, } } /// If neither of the start and end positions is a track index then the other end can be resolved /// into a track index if a definite start position is supplied externally - pub fn resolve_indefinite_grid_tracks(&self, start: i16) -> Line { - use GridPlacement as GP; + pub fn resolve_indefinite_grid_tracks(&self, start: OriginZeroLine) -> Line { + use OriginZeroGridPlacement as GP; match (self.start, self.end) { (GP::Auto, GP::Auto) => Line { start, end: start + 1 }, - (GP::Span(span), GP::Auto) => Line { start, end: start + span as i16 }, - (GP::Auto, GP::Span(span)) => Line { start, end: start + span as i16 }, - (GP::Span(span), GP::Span(_)) => Line { start, end: start + span as i16 }, + (GP::Span(span), GP::Auto) => Line { start, end: start + span }, + (GP::Auto, GP::Span(span)) => Line { start, end: start + span }, + (GP::Span(span), GP::Span(_)) => Line { start, end: start + span }, _ => panic!("resolve_indefinite_grid_tracks should only be called on indefinite grid tracks"), } } - - /// Resolves the span for an indefinite placement (a placement that does not consist of two `Track`s). - /// Panics if called on a definite placement - pub fn indefinite_span(&self) -> u16 { - use GridPlacement as GP; - match (self.start, self.end) { - (GP::Line(_), GP::Auto) => 1, - (GP::Auto, GP::Line(_)) => 1, - (GP::Auto, GP::Auto) => 1, - (GP::Line(_), GP::Span(span)) => span, - (GP::Span(span), GP::Line(_)) => span, - (GP::Span(span), GP::Auto) => span, - (GP::Auto, GP::Span(span)) => span, - (GP::Span(span), GP::Span(_)) => span, - (GP::Line(_), GP::Line(_)) => panic!("indefinite_span should only be called on indefinite grid tracks"), - } - } } /// Represents the start and end points of a GridItem within a given axis diff --git a/src/style/mod.rs b/src/style/mod.rs index 6d5639a3b..a424bd702 100644 --- a/src/style/mod.rs +++ b/src/style/mod.rs @@ -10,6 +10,8 @@ pub use self::flex::{FlexDirection, FlexWrap}; #[cfg(feature = "grid")] mod grid; #[cfg(feature = "grid")] +pub(crate) use self::grid::{GenericGridPlacement, OriginZeroGridPlacement}; +#[cfg(feature = "grid")] pub use self::grid::{ GridAutoFlow, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction, MinTrackSizingFunction, NonRepeatedTrackSizingFunction, TrackSizingFunction, From a0b5ee900061b319c5b3b9f49948051beeb5c8c9 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Wed, 28 Dec 2022 00:54:24 +0000 Subject: [PATCH 03/12] Add test for correct grid line coordinate handling --- src/compute/grid/placement.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/compute/grid/placement.rs b/src/compute/grid/placement.rs index 7e56d9c9a..73f6920ac 100644 --- a/src/compute/grid/placement.rs +++ b/src/compute/grid/placement.rs @@ -381,6 +381,26 @@ mod tests { placement_test_runner(explicit_col_count, explicit_row_count, children, expected_cols, expected_rows, flow); } + #[test] + fn test_placement_spanning_origin() { + let flow = GridAutoFlow::Row; + let explicit_col_count = 2; + let explicit_row_count = 2; + let children = { + let mut sm = SlotMap::new(); + vec![ + // node, style (grid coords), expected_placement (oz coords) + (1, sm.insert(()), (line(-1), line(-1), line(-1), line(-1)).into_grid_child(), (2, 3, 2, 3)), + (2, sm.insert(()), (line(-1), span(2), line(-1), span(2)).into_grid_child(), (2, 4, 2, 4)), + (3, sm.insert(()), (line(-4), line(-4), line(-4), line(-4)).into_grid_child(), (-1, 0, -1, 0)), + (4, sm.insert(()), (line(-4), span(2), line(-4), span(2)).into_grid_child(), (-1, 1, -1, 1)), + ] + }; + let expected_cols = TrackCounts { negative_implicit: 1, explicit: 2, positive_implicit: 2 }; + let expected_rows = TrackCounts { negative_implicit: 1, explicit: 2, positive_implicit: 2 }; + placement_test_runner(explicit_col_count, explicit_row_count, children, expected_cols, expected_rows, flow); + } + #[test] fn test_only_auto_placement_row_flow() { let flow = GridAutoFlow::Row; From 8cf76ce6aab6768fa15447ef62452787aafe34b3 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Wed, 28 Dec 2022 04:17:14 +0000 Subject: [PATCH 04/12] Use i16 rather than NonZeroI16 as the backing storage for GridLine, and convert to Auto internally if zero is specified --- src/compute/grid/types/coordinates.rs | 30 +++++++++------------------ src/style/grid.rs | 12 ++++++----- src/style_helpers.rs | 5 ++++- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/compute/grid/types/coordinates.rs b/src/compute/grid/types/coordinates.rs index d05e8e19b..ed42e51c9 100644 --- a/src/compute/grid/types/coordinates.rs +++ b/src/compute/grid/types/coordinates.rs @@ -1,7 +1,7 @@ //! Taffy uses two coordinate systems to refer to grid lines (the gaps/gutters between rows/columns): use super::super::types::TrackCounts; -use core::num::NonZeroI16; use core::ops::{Add, AddAssign, Sub}; +use std::cmp::Ordering; /// Represents a grid line position in "CSS Grid Line" coordinates /// @@ -13,38 +13,28 @@ use core::ops::{Add, AddAssign, Sub}; /// - 0 is not a valid index #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(transparent)] -pub struct GridLine(pub NonZeroI16); +pub struct GridLine(i16); -impl From for GridLine { - fn from(value: NonZeroI16) -> Self { +impl From for GridLine { + fn from(value: i16) -> Self { Self(value) } } -impl TryFrom for GridLine { - type Error = (); - fn try_from(value: i16) -> Result { - NonZeroI16::new(value).map(GridLine).ok_or(()) - } -} impl GridLine { /// Returns the underlying i16 pub fn as_i16(self) -> i16 { - self.0.get() + self.0 } /// Convert into OriginZero coordinates using the specified explicit track count pub(crate) fn into_origin_zero_line(self, explicit_track_count: u16) -> OriginZeroLine { - let grid_line = self.as_i16(); - - // Note: grid_line cannot be zero because it comes from a NonZeroI16 - let oz_line = if grid_line > 0 { - grid_line - 1 - } else { - let explicit_line_count = explicit_track_count + 1; - grid_line + explicit_line_count as i16 + let explicit_line_count = explicit_track_count + 1; + let oz_line = match self.0.cmp(&0) { + Ordering::Greater => self.0 - 1, + Ordering::Less => self.0 + explicit_line_count as i16, + Ordering::Equal => panic!("Grid line of zero is invalid"), }; - OriginZeroLine(oz_line) } } diff --git a/src/style/grid.rs b/src/style/grid.rs index f28eb7e10..b0867ab4d 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -86,10 +86,7 @@ impl TaffyAuto for GridPlacement { } impl TaffyGridLine for GridPlacement { fn from_line_index(index: i16) -> Self { - match GridLine::try_from(index) { - Ok(line) => GridPlacement::Line(line), - Err(_) => GridPlacement::Auto, - } + GridPlacement::Line(GridLine::from(index)) } } impl TaffyGridLine for Line { @@ -120,7 +117,12 @@ impl GridPlacement { match self { Self::Auto => OriginZeroGridPlacement::Auto, Self::Span(span) => OriginZeroGridPlacement::Span(span), - Self::Line(line) => OriginZeroGridPlacement::Line(line.into_origin_zero_line(explicit_track_count)), + // Grid line zero is an invalid index, so it gets treated as Auto + // See: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-start#values + Self::Line(line) => match line.as_i16() { + 0 => OriginZeroGridPlacement::Auto, + _ => OriginZeroGridPlacement::Line(line.into_origin_zero_line(explicit_track_count)), + }, } } } diff --git a/src/style_helpers.rs b/src/style_helpers.rs index e2899e580..7d4d16fcf 100644 --- a/src/style_helpers.rs +++ b/src/style_helpers.rs @@ -16,7 +16,10 @@ pub fn repeat( TrackSizingFunction::AutoRepeat(repetition_kind, track_list) } -/// Returns a GridPlacement::Line +/// Specifies a grid line to place a grid item between in CSS Grid Line coordinates: +/// - Positive indicies count upwards from the start (top or left) of the explicit grid +/// - Negative indicies count downwards from the end (bottom or right) of the explicit grid +/// - ZERO IS INVALID index, and will be treated as a GridPlacement::Auto. pub fn line(index: i16) -> T { T::from_line_index(index) } From 024949b85a88821955ef1f60b28a69c7c207d749 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 30 Dec 2022 15:09:19 +0000 Subject: [PATCH 05/12] Update src/style/grid.rs Co-authored-by: Andreas Weibye <13300393+Weibye@users.noreply.github.com> --- src/style/grid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/style/grid.rs b/src/style/grid.rs index b0867ab4d..890052667 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -57,7 +57,7 @@ impl GridAutoFlow { /// A grid line placement specification which is generic over the coordinate system that it uses to define /// grid line positions. /// -/// GenericGridPlacement is aliased as GridPlacement as is exposed to users of Taffy to defined styles with +/// GenericGridPlacement is aliased as GridPlacement and is exposed to users of Taffy to define styles. /// GenericGridPlacement is aliased as OriginZeroGridPlacement and is used internally for placement computations /// /// See [`crate::compute::grid::type::coordinates`] for documentation on the different coordinate systems. From a1db91f47024d04f89a24a98453d208ca7cb5819 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 30 Dec 2022 15:09:27 +0000 Subject: [PATCH 06/12] Update src/style/grid.rs Co-authored-by: Andreas Weibye <13300393+Weibye@users.noreply.github.com> --- src/style/grid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/style/grid.rs b/src/style/grid.rs index 890052667..e06f49cdc 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -58,7 +58,7 @@ impl GridAutoFlow { /// grid line positions. /// /// GenericGridPlacement is aliased as GridPlacement and is exposed to users of Taffy to define styles. -/// GenericGridPlacement is aliased as OriginZeroGridPlacement and is used internally for placement computations +/// GenericGridPlacement is aliased as OriginZeroGridPlacement and is used internally for placement computations. /// /// See [`crate::compute::grid::type::coordinates`] for documentation on the different coordinate systems. #[derive(Copy, Clone, PartialEq, Eq, Debug)] From 7408fdc499b93246055083517547e223e9a2357b Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Fri, 30 Dec 2022 23:32:41 -0500 Subject: [PATCH 07/12] Fix typo --- src/compute/grid/types/coordinates.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compute/grid/types/coordinates.rs b/src/compute/grid/types/coordinates.rs index ed42e51c9..1b1f97898 100644 --- a/src/compute/grid/types/coordinates.rs +++ b/src/compute/grid/types/coordinates.rs @@ -8,7 +8,7 @@ use std::cmp::Ordering; /// "CSS Grid Line" coordinates are those used in grid-row/grid-column in the CSS grid spec: /// - The line at left hand (or top) edge of the explicit grid is line 1 /// (and counts up from there) -/// - The line at the right hand (or bottom) edge of the explicit grid in -1 +/// - The line at the right hand (or bottom) edge of the explicit grid is -1 /// (and counts down from there) /// - 0 is not a valid index #[derive(Debug, Clone, Copy, PartialEq, Eq)] From 32102202e9d5ba759df9329a18ed376d35c847d8 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 2 Jan 2023 11:57:39 +0000 Subject: [PATCH 08/12] Add unsigned_abs method to OriginZeroLine --- src/compute/grid/implicit_grid.rs | 8 ++++---- src/compute/grid/types/coordinates.rs | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/compute/grid/implicit_grid.rs b/src/compute/grid/implicit_grid.rs index a0008b611..d7dc89ea5 100644 --- a/src/compute/grid/implicit_grid.rs +++ b/src/compute/grid/implicit_grid.rs @@ -28,12 +28,12 @@ pub(crate) fn compute_grid_size_estimate<'a>( // Compute *track* count estimates for each axis from: // - The explicit track counts // - The origin-zero coordinate min and max grid line variables - let negative_implicit_inline_tracks = col_min.0.unsigned_abs(); + let negative_implicit_inline_tracks = col_min.unsigned_abs(); let explicit_inline_tracks = explicit_col_count; - let mut positive_implicit_inline_tracks = max(explicit_col_count, col_max.0.unsigned_abs()) - explicit_col_count; - let negative_implicit_block_tracks = row_min.0.unsigned_abs(); + let mut positive_implicit_inline_tracks = max(explicit_col_count, col_max.unsigned_abs()) - explicit_col_count; + let negative_implicit_block_tracks = row_min.unsigned_abs(); let explicit_block_tracks = explicit_row_count; - let mut positive_implicit_block_tracks = max(explicit_row_count, row_max.0.unsigned_abs()) - explicit_row_count; + let mut positive_implicit_block_tracks = max(explicit_row_count, row_max.unsigned_abs()) - explicit_row_count; // In each axis, adjust positive track estimate if any items have a span that does not fit within // the total number of tracks in the estimate diff --git a/src/compute/grid/types/coordinates.rs b/src/compute/grid/types/coordinates.rs index 1b1f97898..b238c5e53 100644 --- a/src/compute/grid/types/coordinates.rs +++ b/src/compute/grid/types/coordinates.rs @@ -95,6 +95,10 @@ impl OriginZeroLine { ); 2 * ((self.0 + track_counts.negative_implicit as i16) as usize) } + + pub(crate) fn unsigned_abs(self) -> u16 { + self.0.unsigned_abs() + } } /// A trait for the different coordinates used to define grid lines. From cfec1b85e76d41750b3d149cb5d86c50139ef3d5 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 2 Jan 2023 12:05:43 +0000 Subject: [PATCH 09/12] Improve estimate of grid size --- src/compute/grid/implicit_grid.rs | 8 ++++---- src/compute/grid/types/coordinates.rs | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/compute/grid/implicit_grid.rs b/src/compute/grid/implicit_grid.rs index d7dc89ea5..25b0ea350 100644 --- a/src/compute/grid/implicit_grid.rs +++ b/src/compute/grid/implicit_grid.rs @@ -28,12 +28,12 @@ pub(crate) fn compute_grid_size_estimate<'a>( // Compute *track* count estimates for each axis from: // - The explicit track counts // - The origin-zero coordinate min and max grid line variables - let negative_implicit_inline_tracks = col_min.unsigned_abs(); + let negative_implicit_inline_tracks = col_min.implied_negative_implicit_tracks(); let explicit_inline_tracks = explicit_col_count; - let mut positive_implicit_inline_tracks = max(explicit_col_count, col_max.unsigned_abs()) - explicit_col_count; - let negative_implicit_block_tracks = row_min.unsigned_abs(); + let mut positive_implicit_inline_tracks = col_max.implied_positive_implicit_tracks(explicit_col_count); + let negative_implicit_block_tracks = row_min.implied_negative_implicit_tracks(); let explicit_block_tracks = explicit_row_count; - let mut positive_implicit_block_tracks = max(explicit_row_count, row_max.unsigned_abs()) - explicit_row_count; + let mut positive_implicit_block_tracks = row_max.implied_positive_implicit_tracks(explicit_row_count); // In each axis, adjust positive track estimate if any items have a span that does not fit within // the total number of tracks in the estimate diff --git a/src/compute/grid/types/coordinates.rs b/src/compute/grid/types/coordinates.rs index b238c5e53..0c6a5d87a 100644 --- a/src/compute/grid/types/coordinates.rs +++ b/src/compute/grid/types/coordinates.rs @@ -96,8 +96,22 @@ impl OriginZeroLine { 2 * ((self.0 + track_counts.negative_implicit as i16) as usize) } - pub(crate) fn unsigned_abs(self) -> u16 { - self.0.unsigned_abs() + /// The minimum number of negative implicit track there must be if a grid item starts at this line. + pub(crate) fn implied_negative_implicit_tracks(self) -> u16 { + if self.0 < 0 { + self.0.unsigned_abs() + } else { + 0 + } + } + + /// The minimum number of positive implicit track there must be if a grid item end at this line. + pub(crate) fn implied_positive_implicit_tracks(self, explicit_track_count: u16) -> u16 { + if self.0 > explicit_track_count as i16 { + self.0 as u16 - explicit_track_count + } else { + 0 + } } } From 4a64cd965425f522e87b4a842d4a80bb8c890bea Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 2 Jan 2023 12:13:23 +0000 Subject: [PATCH 10/12] Add span method to Line --- src/compute/grid/types/coordinates.rs | 10 +++++++++- src/compute/grid/types/grid_item.rs | 5 ++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/compute/grid/types/coordinates.rs b/src/compute/grid/types/coordinates.rs index 0c6a5d87a..62525a8b6 100644 --- a/src/compute/grid/types/coordinates.rs +++ b/src/compute/grid/types/coordinates.rs @@ -1,7 +1,8 @@ //! Taffy uses two coordinate systems to refer to grid lines (the gaps/gutters between rows/columns): use super::super::types::TrackCounts; +use crate::geometry::Line; +use core::cmp::{max, Ordering}; use core::ops::{Add, AddAssign, Sub}; -use std::cmp::Ordering; /// Represents a grid line position in "CSS Grid Line" coordinates /// @@ -115,6 +116,13 @@ impl OriginZeroLine { } } +impl Line { + /// The number of tracks between the start and end lines + pub(crate) fn span(self) -> u16 { + max(self.end.0 - self.start.0, 0) as u16 + } +} + /// A trait for the different coordinates used to define grid lines. pub trait GridCoordinate: Copy {} impl GridCoordinate for GridLine {} diff --git a/src/compute/grid/types/grid_item.rs b/src/compute/grid/types/grid_item.rs index c9643b398..b38d84b15 100644 --- a/src/compute/grid/types/grid_item.rs +++ b/src/compute/grid/types/grid_item.rs @@ -10,7 +10,6 @@ use crate::prelude::LayoutTree; use crate::resolve::MaybeResolve; use crate::style::{AvailableSpace, LengthPercentageAuto, MaxTrackSizingFunction, MinTrackSizingFunction, Style}; use crate::style_helpers::*; -use core::cmp::max; use core::ops::Range; /// Represents a single grid item @@ -111,8 +110,8 @@ impl GridItem { /// Returns the number of tracks that this item spans in the specified axis pub fn span(&self, axis: AbstractAxis) -> u16 { match axis { - AbstractAxis::Block => max(self.row.end.0 - self.row.start.0, 0) as u16, - AbstractAxis::Inline => max(self.column.end.0 - self.column.start.0, 0) as u16, + AbstractAxis::Block => self.row.span(), + AbstractAxis::Inline => self.column.span(), } } From 695d247390793f982cc516d39fc4f667688394c0 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 2 Jan 2023 13:41:39 +0000 Subject: [PATCH 11/12] Fix auto placement in negative tracks --- .../generated/grid_placement_auto_negative.rs | 35 ++++++ ...ndary_axis_with_fully_definite_negative.rs | 41 +++++++ benches/generated/mod.rs | 8 ++ src/compute/grid/placement.rs | 116 +++++++++++------- src/compute/grid/types/cell_occupancy.rs | 12 -- src/compute/grid/types/grid_track_counts.rs | 11 ++ .../grid_placement_auto_negative.html | 19 +++ ...ary_axis_with_fully_definite_negative.html | 19 +++ .../generated/grid_placement_auto_negative.rs | 60 +++++++++ ...ndary_axis_with_fully_definite_negative.rs | 71 +++++++++++ tests/generated/mod.rs | 4 + 11 files changed, 343 insertions(+), 53 deletions(-) create mode 100644 benches/generated/grid_placement_auto_negative.rs create mode 100644 benches/generated/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.rs create mode 100644 test_fixtures/grid_placement_auto_negative.html create mode 100644 test_fixtures/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.html create mode 100644 tests/generated/grid_placement_auto_negative.rs create mode 100644 tests/generated/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.rs diff --git a/benches/generated/grid_placement_auto_negative.rs b/benches/generated/grid_placement_auto_negative.rs new file mode 100644 index 000000000..1898ac983 --- /dev/null +++ b/benches/generated/grid_placement_auto_negative.rs @@ -0,0 +1,35 @@ +pub fn compute() { + #[allow(unused_imports)] + use taffy::prelude::*; + let mut taffy = taffy::Taffy::new(); + let node0 = taffy + .new_leaf(taffy::style::Style { + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(-5i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node1 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); + let node2 = taffy + .new_leaf(taffy::style::Style { + grid_row: taffy::geometry::Line { start: line(2i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Grid, + grid_template_rows: vec![points(40f32), points(40f32)], + grid_template_columns: vec![points(40f32), points(40f32)], + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(120f32), + height: taffy::style::Dimension::Points(120f32), + }, + ..Default::default() + }, + &[node0, node1, node2], + ) + .unwrap(); + taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap(); +} diff --git a/benches/generated/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.rs b/benches/generated/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.rs new file mode 100644 index 000000000..840997a9b --- /dev/null +++ b/benches/generated/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.rs @@ -0,0 +1,41 @@ +pub fn compute() { + #[allow(unused_imports)] + use taffy::prelude::*; + let mut taffy = taffy::Taffy::new(); + let node0 = taffy + .new_leaf(taffy::style::Style { + grid_row: taffy::geometry::Line { start: line(2i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node1 = taffy + .new_leaf(taffy::style::Style { + grid_row: taffy::geometry::Line { start: line(2i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(-4i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node2 = taffy + .new_leaf(taffy::style::Style { + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node3 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Grid, + grid_template_rows: vec![points(40f32), points(40f32)], + grid_template_columns: vec![points(40f32), points(40f32)], + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(120f32), + height: taffy::style::Dimension::Points(120f32), + }, + ..Default::default() + }, + &[node0, node1, node2, node3], + ) + .unwrap(); + taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap(); +} diff --git a/benches/generated/mod.rs b/benches/generated/mod.rs index ea7234c7d..073f120a7 100644 --- a/benches/generated/mod.rs +++ b/benches/generated/mod.rs @@ -413,6 +413,10 @@ mod grid_percent_width_and_margin; #[cfg(feature = "grid")] mod grid_percent_width_and_padding; #[cfg(feature = "grid")] +mod grid_placement_auto_negative; +#[cfg(feature = "grid")] +mod grid_placement_definite_in_secondary_axis_with_fully_definite_negative; +#[cfg(feature = "grid")] mod grid_relayout_vertical_text; #[cfg(feature = "grid")] mod grid_size_child_fixed_tracks; @@ -923,6 +927,10 @@ fn benchmark(c: &mut Criterion) { #[cfg(feature = "grid")] grid_percent_width_and_padding::compute(); #[cfg(feature = "grid")] + grid_placement_auto_negative::compute(); + #[cfg(feature = "grid")] + grid_placement_definite_in_secondary_axis_with_fully_definite_negative::compute(); + #[cfg(feature = "grid")] grid_relayout_vertical_text::compute(); #[cfg(feature = "grid")] grid_size_child_fixed_tracks::compute(); diff --git a/src/compute/grid/placement.rs b/src/compute/grid/placement.rs index 73f6920ac..a05deb136 100644 --- a/src/compute/grid/placement.rs +++ b/src/compute/grid/placement.rs @@ -36,10 +36,15 @@ pub(super) fn place_grid_items<'a, ChildIter>( }; // 1. Place children with definite positions + let mut idx = 0; children_iter() .filter(|(_, _, child_style)| child_style.grid_row.is_definite() && child_style.grid_column.is_definite()) .map(map_child_style_to_origin_zero_placement) .for_each(|(index, child_node, child_placement, style)| { + idx += 1; + #[cfg(test)] + println!("Definite Item {idx}\n=============="); + let (row_span, col_span) = place_definite_grid_item(child_placement, primary_axis); record_grid_placement( cell_occupancy_matrix, @@ -55,6 +60,7 @@ pub(super) fn place_grid_items<'a, ChildIter>( }); // 2. Place remaining children with definite secondary axis positions + let mut idx = 0; children_iter() .filter(|(_, _, child_style)| { child_style.grid_placement(secondary_axis).is_definite() @@ -62,6 +68,10 @@ pub(super) fn place_grid_items<'a, ChildIter>( }) .map(map_child_style_to_origin_zero_placement) .for_each(|(index, child_node, child_placement, style)| { + idx += 1; + #[cfg(test)] + println!("Definite Secondary Item {idx}\n=============="); + let (primary_span, secondary_span) = place_definite_secondary_axis_item(&*cell_occupancy_matrix, child_placement, grid_auto_flow); @@ -97,7 +107,10 @@ pub(super) fn place_grid_items<'a, ChildIter>( // 4. Position the remaining grid items // (which either have definite position only in the secondary axis or indefinite positions in both axis) - let mut grid_position: (u16, u16) = (0, 0); + let x_neg_tracks = cell_occupancy_matrix.track_counts(AbsoluteAxis::Horizontal).negative_implicit as i16; + let y_neg_tracks = cell_occupancy_matrix.track_counts(AbsoluteAxis::Vertical).negative_implicit as i16; + let grid_start_position = (OriginZeroLine(-x_neg_tracks), OriginZeroLine(-y_neg_tracks)); + let mut grid_position = grid_start_position; let mut idx = 0; children_iter() .filter(|(_, _, child_style)| !child_style.grid_placement(secondary_axis).is_definite()) @@ -105,7 +118,7 @@ pub(super) fn place_grid_items<'a, ChildIter>( .for_each(|(index, child_node, child_placement, style)| { idx += 1; #[cfg(test)] - println!("\nItem {idx}\n=============="); + println!("\nAuto Item {idx}\n=============="); // Compute placement let (primary_span, secondary_span) = place_indefinitely_positioned_item( @@ -128,11 +141,11 @@ pub(super) fn place_grid_items<'a, ChildIter>( CellOccupancyState::AutoPlaced, ); - // If using the "dense" placement algorithm then reset the grid position back to (0, 0) ready for the next item + // If using the "dense" placement algorithm then reset the grid position back to grid_start_position ready for the next item // Otherwise set it to the position of the current item so that the next item it placed after it. grid_position = match grid_auto_flow.is_dense() { - true => (0, 0), - false => (primary_span.end.0 as u16, secondary_span.start.0 as u16), + true => grid_start_position, + false => (primary_span.end, secondary_span.start), } }); } @@ -161,11 +174,12 @@ fn place_definite_secondary_axis_item( let secondary_axis = primary_axis.other_axis(); let secondary_axis_placement = placement.get(secondary_axis).resolve_definite_grid_lines(); + let primary_axis_grid_start_line = cell_occupancy_matrix.track_counts(primary_axis).implicit_start_line(); let starting_position = match auto_flow.is_dense() { - true => OriginZeroLine(0), + true => primary_axis_grid_start_line, false => cell_occupancy_matrix .last_of_type(primary_axis, secondary_axis_placement.start, CellOccupancyState::AutoPlaced) - .unwrap_or(OriginZeroLine(0)), + .unwrap_or(primary_axis_grid_start_line), }; let mut position: OriginZeroLine = starting_position; @@ -192,7 +206,7 @@ fn place_indefinitely_positioned_item( cell_occupancy_matrix: &CellOccupancyMatrix, placement: InBothAbsAxis>, auto_flow: GridAutoFlow, - grid_position: (u16, u16), + grid_position: (OriginZeroLine, OriginZeroLine), ) -> (Line, Line) { let primary_axis = auto_flow.primary_axis(); @@ -202,23 +216,24 @@ fn place_indefinitely_positioned_item( let primary_span = primary_placement_style.indefinite_span(); let secondary_span = secondary_placement_style.indefinite_span(); let has_definite_primary_axis_position = primary_placement_style.is_definite(); - let primary_axis_length = cell_occupancy_matrix.track_counts(primary_axis).len() as i16; + let primary_axis_grid_start_line = cell_occupancy_matrix.track_counts(primary_axis).implicit_start_line(); + let primary_axis_grid_end_line = cell_occupancy_matrix.track_counts(primary_axis).implicit_end_line(); + let secondary_axis_grid_start_line = + cell_occupancy_matrix.track_counts(primary_axis.other_axis()).implicit_start_line(); - let track_area_is_unoccupied = |primary_range, secondary_range| { - cell_occupancy_matrix.track_area_is_unoccupied(primary_axis, primary_range, secondary_range) + let line_area_is_occupied = |primary_span, secondary_span| { + !cell_occupancy_matrix.line_area_is_unoccupied(primary_axis, primary_span, secondary_span) }; - let tracks_to_lines = |range| cell_occupancy_matrix.tracks_to_lines(primary_axis, range); let (mut primary_idx, mut secondary_idx) = grid_position; if has_definite_primary_axis_position { let definite_primary_placement = primary_placement_style.resolve_definite_grid_lines(); - let defined_primary_idx = - cell_occupancy_matrix.lines_to_tracks(primary_axis.other_axis(), definite_primary_placement).start as u16; + let defined_primary_idx = definite_primary_placement.start; // Compute starting position for search - if defined_primary_idx < primary_idx && secondary_idx != 0 { - secondary_idx = 0; + if defined_primary_idx < primary_idx && secondary_idx != secondary_axis_grid_start_line { + secondary_idx = secondary_axis_grid_start_line; primary_idx = defined_primary_idx + 1; } else { primary_idx = defined_primary_idx; @@ -227,43 +242,43 @@ fn place_indefinitely_positioned_item( // Item has fixed primary axis position: so we simply increment the secondary axis position // until we find a space that the item fits in loop { - let primary_range = (primary_idx as i16)..((primary_idx + primary_span) as i16); - let secondary_range = (secondary_idx as i16)..((secondary_idx + secondary_span) as i16); - - let place_here = track_area_is_unoccupied(primary_range.clone(), secondary_range.clone()); - if place_here { - let primary_span = tracks_to_lines(primary_range); - let secondary_span = tracks_to_lines(secondary_range); - return (primary_span, secondary_span); + let primary_span = Line { start: primary_idx, end: primary_idx + primary_span }; + let secondary_span = Line { start: secondary_idx, end: secondary_idx + secondary_span }; + + // If area is occupied, increment the index and try again + if line_area_is_occupied(primary_span, secondary_span) { + secondary_idx += 1; + continue; } - secondary_idx += 1; + // Once we find a free space, return that position + return (primary_span, secondary_span); } } else { // Item does not have any fixed axis, so we search along the primary axis until we hit the end of the already // existent tracks, and then we reset the primary axis back to zero and increment the secondary axis index. // We continue in this vein until we find a space that the item fits in. loop { - let primary_range = (primary_idx as i16)..((primary_idx + primary_span) as i16); - let secondary_range = (secondary_idx as i16)..((secondary_idx + secondary_span) as i16); - - // Check if item fits in it's current position, and if so place it there - let primary_out_of_bounds = primary_range.end > primary_axis_length; - let place_here = - !primary_out_of_bounds && track_area_is_unoccupied(primary_range.clone(), secondary_range.clone()); - if place_here { - let primary_span = tracks_to_lines(primary_range); - let secondary_span = tracks_to_lines(secondary_range); - return (primary_span, secondary_span); - } + let primary_span = Line { start: primary_idx, end: primary_idx + primary_span }; + let secondary_span = Line { start: secondary_idx, end: secondary_idx + secondary_span }; - // Else check the next position + // If the primary index is out of bounds, then increment the secondary index and reset the primary + // index back to the start of the grid + let primary_out_of_bounds = primary_span.end > primary_axis_grid_end_line; if primary_out_of_bounds { secondary_idx += 1; - primary_idx = 0; - } else { + primary_idx = primary_axis_grid_start_line; + continue; + } + + // If area is occupied, increment the primary index and try again + if line_area_is_occupied(primary_span, secondary_span) { primary_idx += 1; + continue; } + + // Once we find a free space that's in bounds, return that position + return (primary_span, secondary_span); } } } @@ -499,7 +514,7 @@ mod tests { // output order, node, style (grid coords), expected_placement (oz coords) (2, sm.insert(()), (auto(), auto(), line(2), auto()).into_grid_child(), (0, 1, 1, 2)), (1, sm.insert(()), (line(-4), auto(), line(2), auto()).into_grid_child(), (-1, 0, 1, 2)), - (3, sm.insert(()), (auto(), auto(), line(1), auto()).into_grid_child(), (0, 1, 0, 1)), + (3, sm.insert(()), (auto(), auto(), line(1), auto()).into_grid_child(), (-1, 0, 0, 1)), ] }; let expected_cols = TrackCounts { negative_implicit: 1, explicit: 2, positive_implicit: 0 }; @@ -544,5 +559,24 @@ mod tests { let expected_rows = TrackCounts { negative_implicit: 0, explicit: 4, positive_implicit: 0 }; placement_test_runner(explicit_col_count, explicit_row_count, children, expected_cols, expected_rows, flow); } + + #[test] + fn test_auto_placement_in_negative_tracks() { + let flow = GridAutoFlow::RowDense; + let explicit_col_count = 2; + let explicit_row_count = 2; + let children = { + let mut sm = SlotMap::new(); + vec![ + // output order, node, style (grid coords), expected_placement (oz coords) + (1, sm.insert(()), (line(-5), auto(), line(1), auto()).into_grid_child(), (-2, -1, 0, 1)), // Row 1. Definitely positioned in column -2 + (2, sm.insert(()), (auto(), auto(), line(2), auto()).into_grid_child(), (-2, -1, 1, 2)), // Row 2. Auto positioned in column -2 + (3, sm.insert(()), (auto(), auto(), auto(), auto()).into_grid_child(), (-1, 0, 0, 1)), // Row 1. Auto positioned in column -1 + ] + }; + let expected_cols = TrackCounts { negative_implicit: 2, explicit: 2, positive_implicit: 0 }; + let expected_rows = TrackCounts { negative_implicit: 0, explicit: 2, positive_implicit: 0 }; + placement_test_runner(explicit_col_count, explicit_row_count, children, expected_cols, expected_rows, flow); + } } } diff --git a/src/compute/grid/types/cell_occupancy.rs b/src/compute/grid/types/cell_occupancy.rs index 88ec3043e..35b3d5cef 100644 --- a/src/compute/grid/types/cell_occupancy.rs +++ b/src/compute/grid/types/cell_occupancy.rs @@ -169,18 +169,6 @@ impl CellOccupancyMatrix { } } - /// Converts a span of grid lines in OriginZero coordinates into a range a tracks suitable - /// for indexing into this CellOccupancyMatrix - pub fn lines_to_tracks(&self, axis: AbsoluteAxis, span: Line) -> Range { - self.track_counts(axis).oz_line_range_to_track_range(span) - } - - /// Converts a range a tracks indexes from this CellOccupancyMatrix into a span of grid lines - /// in OriginZero coordinates - pub fn tracks_to_lines(&self, axis: AbsoluteAxis, span: Range) -> Line { - self.track_counts(axis).track_range_to_oz_line_range(span) - } - /// Determines whether a grid area specified by the bounding grid lines in OriginZero coordinates /// is entirely unnocupied. Returns true if all grid cells within the grid area are unnocupied, else false. pub fn line_area_is_unoccupied( diff --git a/src/compute/grid/types/grid_track_counts.rs b/src/compute/grid/types/grid_track_counts.rs index dc006605c..8ab8ae309 100644 --- a/src/compute/grid/types/grid_track_counts.rs +++ b/src/compute/grid/types/grid_track_counts.rs @@ -57,9 +57,20 @@ impl TrackCounts { pub fn len(&self) -> usize { (self.negative_implicit + self.explicit + self.positive_implicit) as usize } + + /// The OriginZeroLine representing the start of the implicit grid + pub fn implicit_start_line(&self) -> OriginZeroLine { + OriginZeroLine(-(self.negative_implicit as i16)) + } + + /// The OriginZeroLine representing the end of the implicit grid + pub fn implicit_end_line(&self) -> OriginZeroLine { + OriginZeroLine((self.explicit + self.positive_implicit) as i16) + } } /// Conversion functions between OriginZero coordinates and CellOccupancyMatrix track indexes +#[allow(dead_code)] impl TrackCounts { /// Converts a grid line in OriginZero coordinates into the track immediately /// following that grid line as an index into the CellOccupancyMatrix. diff --git a/test_fixtures/grid_placement_auto_negative.html b/test_fixtures/grid_placement_auto_negative.html new file mode 100644 index 000000000..2491d5b76 --- /dev/null +++ b/test_fixtures/grid_placement_auto_negative.html @@ -0,0 +1,19 @@ + + + + + + + Test description + + + + +
+
+
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.html b/test_fixtures/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.html new file mode 100644 index 000000000..5f20f47c4 --- /dev/null +++ b/test_fixtures/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.html @@ -0,0 +1,19 @@ + + + + + + + Test description + + + + +
+
+
+
+
+ + + \ No newline at end of file diff --git a/tests/generated/grid_placement_auto_negative.rs b/tests/generated/grid_placement_auto_negative.rs new file mode 100644 index 000000000..d0323261d --- /dev/null +++ b/tests/generated/grid_placement_auto_negative.rs @@ -0,0 +1,60 @@ +#[test] +fn grid_placement_auto_negative() { + 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 { + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(-5i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node1 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); + let node2 = taffy + .new_leaf(taffy::style::Style { + grid_row: taffy::geometry::Line { start: line(2i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Grid, + grid_template_rows: vec![points(40f32), points(40f32)], + grid_template_columns: vec![points(40f32), points(40f32)], + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(120f32), + height: taffy::style::Dimension::Points(120f32), + }, + ..Default::default() + }, + &[node0, node1, node2], + ) + .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, 120f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 120f32, 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, 20f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 20f32, size.width); + assert_eq!(size.height, 40f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, 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, 20f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 20f32, size.width); + assert_eq!(size.height, 40f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 40f32, size.height); + assert_eq!(location.x, 20f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 20f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, location.y); + let Layout { size, location, .. } = taffy.layout(node2).unwrap(); + assert_eq!(size.width, 20f32, "width of node {:?}. Expected {}. Actual {}", node2.data(), 20f32, size.width); + assert_eq!(size.height, 40f32, "height of node {:?}. Expected {}. Actual {}", node2.data(), 40f32, size.height); + assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node2.data(), 0f32, location.x); + assert_eq!(location.y, 40f32, "y of node {:?}. Expected {}. Actual {}", node2.data(), 40f32, location.y); +} diff --git a/tests/generated/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.rs b/tests/generated/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.rs new file mode 100644 index 000000000..7159c01d8 --- /dev/null +++ b/tests/generated/grid_placement_definite_in_secondary_axis_with_fully_definite_negative.rs @@ -0,0 +1,71 @@ +#[test] +fn grid_placement_definite_in_secondary_axis_with_fully_definite_negative() { + 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 { + grid_row: taffy::geometry::Line { start: line(2i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node1 = taffy + .new_leaf(taffy::style::Style { + grid_row: taffy::geometry::Line { start: line(2i16), end: taffy::style::GridPlacement::Auto }, + grid_column: taffy::geometry::Line { start: line(-4i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node2 = taffy + .new_leaf(taffy::style::Style { + grid_row: taffy::geometry::Line { start: line(1i16), end: taffy::style::GridPlacement::Auto }, + ..Default::default() + }) + .unwrap(); + let node3 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Grid, + grid_template_rows: vec![points(40f32), points(40f32)], + grid_template_columns: vec![points(40f32), points(40f32)], + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(120f32), + height: taffy::style::Dimension::Points(120f32), + }, + ..Default::default() + }, + &[node0, node1, node2, node3], + ) + .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, 120f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 120f32, 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, 40f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, location.x); + assert_eq!(location.y, 40f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 40f32, location.y); + let Layout { size, location, .. } = taffy.layout(node1).unwrap(); + assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 40f32, size.width); + assert_eq!(size.height, 40f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 40f32, size.height); + assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, location.x); + assert_eq!(location.y, 40f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 40f32, location.y); + let Layout { size, location, .. } = taffy.layout(node2).unwrap(); + assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node2.data(), 40f32, size.width); + assert_eq!(size.height, 40f32, "height of node {:?}. Expected {}. Actual {}", node2.data(), 40f32, size.height); + assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node2.data(), 0f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node2.data(), 0f32, location.y); + let Layout { size, location, .. } = taffy.layout(node3).unwrap(); + assert_eq!(size.width, 40f32, "width of node {:?}. Expected {}. Actual {}", node3.data(), 40f32, size.width); + assert_eq!(size.height, 40f32, "height of node {:?}. Expected {}. Actual {}", node3.data(), 40f32, size.height); + assert_eq!(location.x, 40f32, "x of node {:?}. Expected {}. Actual {}", node3.data(), 40f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node3.data(), 0f32, location.y); +} diff --git a/tests/generated/mod.rs b/tests/generated/mod.rs index 30442ab48..0a7dd7489 100644 --- a/tests/generated/mod.rs +++ b/tests/generated/mod.rs @@ -412,6 +412,10 @@ mod grid_percent_width_and_margin; #[cfg(feature = "grid")] mod grid_percent_width_and_padding; #[cfg(feature = "grid")] +mod grid_placement_auto_negative; +#[cfg(feature = "grid")] +mod grid_placement_definite_in_secondary_axis_with_fully_definite_negative; +#[cfg(feature = "grid")] mod grid_relayout_vertical_text; #[cfg(feature = "grid")] mod grid_size_child_fixed_tracks; From 77728d3d2acd6334be2323809c1c11def00b60b5 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 2 Jan 2023 13:56:06 +0000 Subject: [PATCH 12/12] Update changelog with new GridLine type --- RELEASES.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index c3e92e967..af9b1a56a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -6,12 +6,13 @@ - `experimental_grid` feature named to just `grid` - `grid` feature enabled by default +- `GridPlacement::Line` now stores a `GridLine` newtype wrapper around an `i16` rather than a raw `i16`. If you are using the style helpers then this change will not affect you. +- *BREAKING:* `Position` is now renamed to `Inset` and is now in line with [CSS inset specs](https://developer.mozilla.org/en-US/docs/Web/CSS/inset) +- *BREAKING:* `PositionType` is now renamed to `Position` and is now in line with [CSS position specs](https://developer.mozilla.org/en-US/docs/Web/CSS/position) ### Fixes - Flexbox nodes sized under a min-content constraint now size correctly (#291) -- *BREAKING:* `Position` is now renamed to `Inset` and is now in line with [CSS inset specs](https://developer.mozilla.org/en-US/docs/Web/CSS/inset) -- *BREAKING:* `PositionType` is now renamed to `Position` and is now in line with [CSS position specs](https://developer.mozilla.org/en-US/docs/Web/CSS/position) ### Removed