Fix flexbox baseline alignment (#325)
* Fix baseline alignment with margins and padding
* Don't run baseline alignment on flex columns
* Enable baseline child multiline tests
* Refactor baseline alignment to be returned by perform_layout function
- Introduce LayoutAlgorithm trait
* Only calculate child baseline for baseline alignment when necessary
* Add disabled test for grid item baseline alignment
* Apply suggestions from code review
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
* Add documentation on what a baseline is
* Rename compute_generic functions back to compute
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
b91874d4e34ecc9054b468a338ffcae6f61a1b4a · por Nico Burns · 2023-01-16T00:47:57Z (hace 3 años) · padre e05b9093d · ver el árbol en este commit
Delta semántico · 76
benches/generated/align_baseline_child_margin.rs
benches/generated/align_baseline_child_margin_percent.rs
benches/generated/align_baseline_child_multiline_no_override_on_secondline.rs
benches/generated/align_baseline_child_multiline_override.rs
benches/generated/align_baseline_child_padding.rs
benches/generated/align_baseline_multiline.rs
benches/generated/align_baseline_multiline_row_and_column.rs
src/compute/grid/alignment.rs
src/compute/grid/types/grid_item.rs
src/geometry.rs
nueva def NONE pub cambió de firma def ZERO pub
tests/generated/align_baseline_child_margin.rs
tests/generated/align_baseline_child_margin_percent.rs
tests/generated/align_baseline_child_multiline_no_override_on_secondline.rs
tests/generated/align_baseline_child_multiline_override.rs
tests/generated/align_baseline_child_padding.rs
tests/generated/align_baseline_multiline.rs
tests/generated/align_baseline_multiline_row_and_column.rs
diff --git a/benches/generated/align_baseline_child_margin.rs b/benches/generated/align_baseline_child_margin.rs
new file mode 100644
index 000000000..84ff33372
--- /dev/null
+++ b/benches/generated/align_baseline_child_margin.rs
@@ -0,0 +1,62 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(5f32),
+ right: taffy::style::LengthPercentageAuto::Points(5f32),
+ top: taffy::style::LengthPercentageAuto::Points(5f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(5f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(5f32),
+ right: taffy::style::LengthPercentageAuto::Points(5f32),
+ top: taffy::style::LengthPercentageAuto::Points(5f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(5f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/align_baseline_child_margin_percent.rs b/benches/generated/align_baseline_child_margin_percent.rs
new file mode 100644
index 000000000..d10b5fdc6
--- /dev/null
+++ b/benches/generated/align_baseline_child_margin_percent.rs
@@ -0,0 +1,62 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Percent(0.05f32),
+ right: taffy::style::LengthPercentageAuto::Percent(0.05f32),
+ top: taffy::style::LengthPercentageAuto::Percent(0.05f32),
+ bottom: taffy::style::LengthPercentageAuto::Percent(0.05f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Percent(0.01f32),
+ right: taffy::style::LengthPercentageAuto::Percent(0.01f32),
+ top: taffy::style::LengthPercentageAuto::Percent(0.01f32),
+ bottom: taffy::style::LengthPercentageAuto::Percent(0.01f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/align_baseline_child_multiline_no_override_on_secondline.rs b/benches/generated/align_baseline_child_multiline_no_override_on_secondline.rs
new file mode 100644
index 000000000..8bca54b9f
--- /dev/null
+++ b/benches/generated/align_baseline_child_multiline_no_override_on_secondline.rs
@@ -0,0 +1,78 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(60f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node11 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node12 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node13 = taffy
+ .new_leaf(taffy::style::Style {
+ align_self: Some(taffy::style::AlignSelf::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_wrap: taffy::style::FlexWrap::Wrap,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(25f32),
+ },
+ ..Default::default()
+ },
+ &[node10, node11, node12, node13],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/align_baseline_child_multiline_override.rs b/benches/generated/align_baseline_child_multiline_override.rs
new file mode 100644
index 000000000..f6f4cdc5f
--- /dev/null
+++ b/benches/generated/align_baseline_child_multiline_override.rs
@@ -0,0 +1,79 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(60f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node11 = taffy
+ .new_leaf(taffy::style::Style {
+ align_self: Some(taffy::style::AlignSelf::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node12 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node13 = taffy
+ .new_leaf(taffy::style::Style {
+ align_self: Some(taffy::style::AlignSelf::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_wrap: taffy::style::FlexWrap::Wrap,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(25f32),
+ },
+ ..Default::default()
+ },
+ &[node10, node11, node12, node13],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/align_baseline_child_padding.rs b/benches/generated/align_baseline_child_padding.rs
new file mode 100644
index 000000000..9600fac71
--- /dev/null
+++ b/benches/generated/align_baseline_child_padding.rs
@@ -0,0 +1,62 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ padding: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentage::Points(5f32),
+ right: taffy::style::LengthPercentage::Points(5f32),
+ top: taffy::style::LengthPercentage::Points(5f32),
+ bottom: taffy::style::LengthPercentage::Points(5f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ padding: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentage::Points(5f32),
+ right: taffy::style::LengthPercentage::Points(5f32),
+ top: taffy::style::LengthPercentage::Points(5f32),
+ bottom: taffy::style::LengthPercentage::Points(5f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/align_baseline_multiline.rs b/benches/generated/align_baseline_multiline.rs
new file mode 100644
index 000000000..048accde9
--- /dev/null
+++ b/benches/generated/align_baseline_multiline.rs
@@ -0,0 +1,82 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node20 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node2 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node20],
+ )
+ .unwrap();
+ let node3 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_wrap: taffy::style::FlexWrap::Wrap,
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1, node2, node3],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+}
diff --git a/benches/generated/align_baseline_multiline_row_and_column.rs b/benches/generated/align_baseline_multiline_row_and_column.rs
new file mode 100644
index 000000000..19c0e8a7a
--- /dev/null
+++ b/benches/generated/align_baseline_multiline_row_and_column.rs
@@ -0,0 +1,82 @@
+pub fn compute() {
+ #[allow(unused_imports)]
+ use taffy::prelude::*;
+ let mut taffy = taffy::Taffy::new();
+ let node0 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node20 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node2 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node20],
+ )
+ .unwrap();
+ let node3 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_wrap: taffy::style::FlexWrap::Wrap,
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..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 33a6c0582..dc6e01760 100644
--- a/benches/generated/mod.rs
+++ b/benches/generated/mod.rs
@@ -107,13 +107,20 @@ mod absolute_minmax_top_left_bottom_right_max;
mod absolute_minmax_top_left_bottom_right_min_max;
mod align_baseline;
mod align_baseline_child;
+mod align_baseline_child_margin;
+mod align_baseline_child_margin_percent;
mod align_baseline_child_multiline;
+mod align_baseline_child_multiline_no_override_on_secondline;
+mod align_baseline_child_multiline_override;
+mod align_baseline_child_padding;
mod align_baseline_child_top;
mod align_baseline_child_top2;
mod align_baseline_column;
mod align_baseline_double_nested_child;
+mod align_baseline_multiline;
mod align_baseline_multiline_column;
mod align_baseline_multiline_column2;
+mod align_baseline_multiline_row_and_column;
mod align_baseline_nested_child;
mod align_baseline_nested_column;
mod align_center_should_size_based_on_content;
@@ -768,13 +775,20 @@ fn benchmark(c: &mut Criterion) {
absolute_minmax_top_left_bottom_right_min_max::compute();
align_baseline::compute();
align_baseline_child::compute();
+ align_baseline_child_margin::compute();
+ align_baseline_child_margin_percent::compute();
align_baseline_child_multiline::compute();
+ align_baseline_child_multiline_no_override_on_secondline::compute();
+ align_baseline_child_multiline_override::compute();
+ align_baseline_child_padding::compute();
align_baseline_child_top::compute();
align_baseline_child_top2::compute();
align_baseline_column::compute();
align_baseline_double_nested_child::compute();
+ align_baseline_multiline::compute();
align_baseline_multiline_column::compute();
align_baseline_multiline_column2::compute();
+ align_baseline_multiline_row_and_column::compute();
align_baseline_nested_child::compute();
align_baseline_nested_column::compute();
align_center_should_size_based_on_content::compute();
diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index a77d25037..9bb26f3ff 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -4,9 +4,9 @@
use core::f32;
use crate::compute::common::alignment::compute_alignment_offset;
-use crate::compute::compute_node_layout;
+use crate::compute::{GenericAlgorithm, LayoutAlgorithm};
use crate::geometry::{Point, Rect, Size};
-use crate::layout::{Layout, RunMode, SizingMode};
+use crate::layout::{Layout, RunMode, SizeAndBaselines, SizingMode};
use crate::math::MaybeMath;
use crate::node::Node;
use crate::prelude::{TaffyMaxContent, TaffyMinContent};
@@ -23,6 +23,34 @@ use crate::tree::LayoutTree;
#[cfg(feature = "debug")]
use crate::debug::NODE_LOGGER;
+/// The public interface to Taffy's Flexbox algorithm implementation
+pub(crate) struct FlexboxAlgorithm;
+impl LayoutAlgorithm for FlexboxAlgorithm {
+ const NAME: &'static str = "FLEXBOX";
+
+ fn perform_layout(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ _sizing_mode: SizingMode,
+ ) -> SizeAndBaselines {
+ compute(tree, node, known_dimensions, parent_size, available_space, RunMode::PeformLayout)
+ }
+
+ fn measure_size(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ _sizing_mode: SizingMode,
+ ) -> Size<f32> {
+ compute(tree, node, known_dimensions, parent_size, available_space, RunMode::ComputeSize).size
+ }
+}
+
/// The intermediate results of a flexbox calculation for a single item
struct FlexItem {
/// The identifier for the associated [`Node`](crate::node::Node)
@@ -137,7 +165,7 @@ pub fn compute(
parent_size: Size<Option<f32>>,
available_space: Size<AvailableSpace>,
run_mode: RunMode,
-) -> Size<f32> {
+) -> SizeAndBaselines {
let style = tree.style(node);
let has_min_max_sizes = style.min_size.width.is_defined()
|| style.min_size.height.is_defined()
@@ -159,7 +187,8 @@ pub fn compute(
parent_size,
available_space,
RunMode::ComputeSize,
- );
+ )
+ .size;
let clamped_first_pass_size = first_pass.maybe_clamp(min_size, max_size);
@@ -186,7 +215,7 @@ fn compute_preliminary(
parent_size: Size<Option<f32>>,
available_space: Size<AvailableSpace>,
run_mode: RunMode,
-) -> Size<f32> {
+) -> SizeAndBaselines {
// Define some general constants we will need for the remainder of the algorithm.
let mut constants = compute_constants(tree.style(node), known_dimensions, parent_size);
@@ -206,8 +235,6 @@ fn compute_preliminary(
NODE_LOGGER.log("determine_available_space");
let available_space = determine_available_space(known_dimensions, available_space, &constants);
- let has_baseline_child = flex_items.iter().any(|child| child.align_self == AlignSelf::Baseline);
-
// 3. Determine the flex base size and hypothetical main size of each item.
#[cfg(feature = "debug")]
NODE_LOGGER.log("determine_flex_base_size");
@@ -279,13 +306,11 @@ fn compute_preliminary(
determine_hypothetical_cross_size(tree, line, &constants, available_space);
}
- // TODO - probably should move this somewhere else as it doesn't make a ton of sense here but we need it below
- // TODO - This is expensive and should only be done if we really require a baseline. aka, make it lazy
- if has_baseline_child {
- #[cfg(feature = "debug")]
- NODE_LOGGER.log("calculate_children_base_lines");
- calculate_children_base_lines(tree, node, known_dimensions, available_space, &mut flex_lines, &constants);
- }
+ // Calculate child baselines. This function is internally smart and only computes child baselines
+ // if they are necessary.
+ #[cfg(feature = "debug")]
+ NODE_LOGGER.log("calculate_children_base_lines");
+ calculate_children_base_lines(tree, known_dimensions, available_space, &mut flex_lines, &constants);
// 8. Calculate the cross size of each flex line.
#[cfg(feature = "debug")]
@@ -339,8 +364,7 @@ fn compute_preliminary(
// We have the container size.
// If our caller does not care about performing layout we are done now.
if run_mode == RunMode::ComputeSize {
- let container_size = constants.container_size;
- return container_size;
+ return SizeAndBaselines { size: constants.container_size, first_baselines: Point::NONE };
}
// 16. Align all flex lines per align-content.
@@ -365,19 +389,34 @@ fn compute_preliminary(
let child = tree.child(node, order);
if tree.style(child).display == Display::None {
*tree.layout_mut(node) = Layout::with_order(order as u32);
- compute_node_layout(
+ GenericAlgorithm::measure_size(
tree,
child,
Size::NONE,
Size::NONE,
Size::MAX_CONTENT,
- RunMode::PeformLayout,
SizingMode::InherentSize,
);
}
}
- constants.container_size
+ // 8.5. Flex Container Baselines: calculate the flex container's first baseline
+ // See https://www.w3.org/TR/css-flexbox-1/#flex-baselines
+ let first_vertical_baseline = if flex_lines.is_empty() {
+ None
+ } else {
+ flex_lines[0]
+ .items
+ .iter()
+ .find(|item| constants.is_column || item.align_self == AlignSelf::Baseline)
+ .or_else(|| flex_lines[0].items.iter().next())
+ .map(|child| {
+ let offset_vertical = if constants.is_row { child.offset_cross } else { child.offset_main };
+ offset_vertical + child.baseline
+ })
+ };
+
+ SizeAndBaselines { size: constants.container_size, first_baselines: Point { x: None, y: first_vertical_baseline } }
}
/// Compute constants that can be reused during the flexbox algorithm.
@@ -617,13 +656,12 @@ fn determine_flex_base_size(
ckd
};
- child.flex_basis = compute_node_layout(
+ child.flex_basis = GenericAlgorithm::measure_size(
tree,
child.node,
child_known_dimensions,
constants.node_inner_size,
available_space,
- RunMode::ComputeSize,
SizingMode::ContentSize,
)
.main(constants.dir);
@@ -636,13 +674,12 @@ fn determine_flex_base_size(
child.inner_flex_basis =
child.flex_basis - child.padding.main_axis_sum(constants.dir) - child.border.main_axis_sum(constants.dir);
- let min_content_size = compute_node_layout(
+ let min_content_size = GenericAlgorithm::measure_size(
tree,
child.node,
Size::NONE,
constants.node_inner_size,
Size::MIN_CONTENT,
- RunMode::ComputeSize,
SizingMode::ContentSize,
);
@@ -968,7 +1005,7 @@ fn determine_hypothetical_cross_size(
child.hypothetical_inner_size.set_cross(
constants.dir,
- compute_node_layout(
+ GenericAlgorithm::measure_size(
tree,
child.node,
Size {
@@ -988,7 +1025,6 @@ fn determine_hypothetical_cross_size(
constants.container_size.main(constants.dir).into()
},
},
- RunMode::ComputeSize,
SizingMode::ContentSize,
)
.cross(constants.dir)
@@ -1006,25 +1042,33 @@ fn determine_hypothetical_cross_size(
#[inline]
fn calculate_children_base_lines(
tree: &mut impl LayoutTree,
- node: Node,
node_size: Size<Option<f32>>,
available_space: Size<AvailableSpace>,
flex_lines: &mut [FlexLine],
constants: &AlgoConstants,
) {
- /// Recursively calculates the baseline for children
- fn calc_baseline(db: &impl LayoutTree, node: Node, layout: &Layout) -> f32 {
- if let Some(first_child) = db.children(node).next() {
- let layout = db.layout(*first_child);
- calc_baseline(db, *first_child, layout)
- } else {
- layout.size.height
- }
+ // Only compute baselines for flex rows because we only support baseline alignment in the cross axis
+ // where that axis is also the inline axis
+ // TODO: this may need revisiting if/when we support vertical writing modes
+ if !constants.is_row {
+ return;
}
for line in flex_lines {
+ // If a flex line has one or zero items participating in baseline alignment then baseline alignment is a no-op so we skip
+ let line_baseline_child_count =
+ line.items.iter().filter(|child| child.align_self == AlignSelf::Baseline).count();
+ if line_baseline_child_count <= 1 {
+ continue;
+ }
+
for child in line.items.iter_mut() {
- let preliminary_size = compute_node_layout(
+ // Only calculate baselines for children participating in baseline alignment
+ if child.align_self != AlignSelf::Baseline {
+ continue;
+ }
+
+ let measured_size_and_baselines = GenericAlgorithm::perform_layout(
tree,
child.node,
Size {
@@ -1052,19 +1096,13 @@ fn calculate_children_base_lines(
constants.container_size.height.into()
},
},
- RunMode::PeformLayout,
SizingMode::ContentSize,
);
- child.baseline = calc_baseline(
- tree,
- child.node,
- &Layout {
- order: tree.children(node).position(|n| *n == child.node).unwrap() as u32,
- size: preliminary_size,
- location: Point::zero(),
- },
- );
+ let baseline = measured_size_and_baselines.first_baselines.y;
+ let height = measured_size_and_baselines.size.height;
+
+ child.baseline = baseline.unwrap_or(height) + child.margin.top;
}
}
}
@@ -1131,7 +1169,6 @@ fn calculate_cross_size(
if child.align_self == AlignSelf::Baseline
&& child_style.margin.cross_start(constants.dir) != LengthPercentageAuto::Auto
&& child_style.margin.cross_end(constants.dir) != LengthPercentageAuto::Auto
- && child_style.size.cross(constants.dir) == Dimension::Auto
{
max_baseline - child.baseline + child.hypothetical_outer_size.cross(constants.dir)
} else {
@@ -1471,15 +1508,15 @@ fn calculate_flex_item(
node_inner_size: Size<Option<f32>>,
direction: FlexDirection,
) {
- let preliminary_size = compute_node_layout(
+ let preliminary_size_and_baselines = GenericAlgorithm::perform_layout(
tree,
item.node,
item.target_size.map(|s| s.into()),
node_inner_size,
container_size.map(|s| s.into()),
- RunMode::PeformLayout,
SizingMode::ContentSize,
);
+ let preliminary_size = preliminary_size_and_baselines.size;
let offset_main = *total_offset_main
+ item.offset_main
@@ -1492,11 +1529,21 @@ fn calculate_flex_item(
+ item.margin.cross_start(direction)
+ (item.inset.cross_start(direction).unwrap_or(0.0) - item.inset.cross_end(direction).unwrap_or(0.0));
+ if direction.is_row() {
+ let baseline_offset_cross = total_offset_cross + item.offset_cross + item.margin.cross_start(direction);
+ let inner_baseline = preliminary_size_and_baselines.first_baselines.y.unwrap_or(preliminary_size.height);
+ item.baseline = baseline_offset_cross + inner_baseline;
+ } else {
+ let baseline_offset_main = *total_offset_main + item.offset_main + item.margin.main_start(direction);
+ let inner_baseline = preliminary_size_and_baselines.first_baselines.y.unwrap_or(preliminary_size.height);
+ item.baseline = baseline_offset_main + inner_baseline;
+ }
+
let order = tree.children(node).position(|n| *n == item.node).unwrap() as u32;
*tree.layout_mut(item.node) = Layout {
order,
- size: preliminary_size,
+ size: preliminary_size_and_baselines.size,
location: Point {
x: if direction.is_row() { offset_main } else { offset_cross },
y: if direction.is_column() { offset_main } else { offset_cross },
@@ -1640,7 +1687,7 @@ fn perform_absolute_layout_on_absolute_children(tree: &mut impl LayoutTree, node
known_dimensions = known_dimensions.maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size);
}
- let measured_size = compute_node_layout(
+ let measured_size_and_baselines = GenericAlgorithm::perform_layout(
tree,
child,
known_dimensions,
@@ -1649,9 +1696,9 @@ fn perform_absolute_layout_on_absolute_children(tree: &mut impl LayoutTree, node
width: AvailableSpace::Definite(container_width.maybe_clamp(min_size.width, max_size.width)),
height: AvailableSpace::Definite(container_height.maybe_clamp(min_size.height, max_size.height)),
},
- RunMode::PeformLayout,
SizingMode::ContentSize,
);
+ let measured_size = measured_size_and_baselines.size;
let final_size = known_dimensions.unwrap_or(measured_size).maybe_clamp(min_size, max_size);
let non_auto_margin = margin.map(|m| m.unwrap_or(0.0));
diff --git a/src/compute/grid/alignment.rs b/src/compute/grid/alignment.rs
index cd8cf13f2..d1df39c55 100644
--- a/src/compute/grid/alignment.rs
+++ b/src/compute/grid/alignment.rs
@@ -2,9 +2,9 @@
use super::types::GridTrack;
use crate::axis::InBothAbsAxis;
use crate::compute::common::alignment::compute_alignment_offset;
-use crate::compute::compute_node_layout;
+use crate::compute::{GenericAlgorithm, LayoutAlgorithm};
use crate::geometry::{Line, Point, Rect, Size};
-use crate::layout::{Layout, RunMode, SizingMode};
+use crate::layout::{Layout, SizingMode};
use crate::math::MaybeMath;
use crate::node::Node;
use crate::resolve::MaybeResolve;
@@ -176,18 +176,18 @@ pub(super) fn align_and_position_item(
let Size { width, height } = Size { width, height }.maybe_clamp(min_size, max_size);
// Layout node
- let measured_size = compute_node_layout(
+ let measured_size_and_baselines = GenericAlgorithm::perform_layout(
tree,
node,
Size { width, height },
grid_area_size.map(Option::Some),
grid_area_minus_item_margins_size.map(AvailableSpace::Definite),
- RunMode::PeformLayout,
SizingMode::InherentSize,
);
// Resolve final size
- let Size { width, height } = Size { width, height }.unwrap_or(measured_size).maybe_clamp(min_size, max_size);
+ let Size { width, height } =
+ Size { width, height }.unwrap_or(measured_size_and_baselines.size).maybe_clamp(min_size, max_size);
let x = align_item_within_area(
Line { start: grid_area.left, end: grid_area.right },
diff --git a/src/compute/grid/mod.rs b/src/compute/grid/mod.rs
index 5cca095ce..dc74c3920 100644
--- a/src/compute/grid/mod.rs
+++ b/src/compute/grid/mod.rs
@@ -1,8 +1,8 @@
//! This module is a partial implementation of the CSS Grid Level 1 specification
//! https://www.w3.org/TR/css-grid-1/
use crate::axis::{AbsoluteAxis, AbstractAxis, InBothAbsAxis};
-use crate::geometry::{Line, Rect, Size};
-use crate::layout::{Layout, RunMode, SizingMode};
+use crate::geometry::{Line, Point, Rect, Size};
+use crate::layout::{Layout, RunMode, SizeAndBaselines, SizingMode};
use crate::math::MaybeMath;
use crate::node::Node;
use crate::resolve::{MaybeResolve, ResolveOrZero};
@@ -22,7 +22,7 @@ pub(crate) use types::{GridCoordinate, GridLine, OriginZeroLine};
#[cfg(feature = "debug")]
use crate::debug::NODE_LOGGER;
-use super::compute_node_layout;
+use super::{GenericAlgorithm, LayoutAlgorithm};
mod alignment;
mod explicit_grid;
@@ -32,6 +32,34 @@ mod track_sizing;
mod types;
mod util;
+/// The public interface to Taffy's CSS Grid algorithm implementation
+pub(crate) struct CssGridAlgorithm;
+impl LayoutAlgorithm for CssGridAlgorithm {
+ const NAME: &'static str = "CSS GRID";
+
+ fn perform_layout(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ _sizing_mode: SizingMode,
+ ) -> SizeAndBaselines {
+ compute(tree, node, known_dimensions, parent_size, available_space, RunMode::PeformLayout)
+ }
+
+ fn measure_size(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ _sizing_mode: SizingMode,
+ ) -> Size<f32> {
+ compute(tree, node, known_dimensions, parent_size, available_space, RunMode::ComputeSize).size
+ }
+}
+
/// Grid layout algorithm
/// This consists of a few phases:
/// - Resolving the explicit grid
@@ -44,7 +72,8 @@ pub fn compute(
known_dimensions: Size<Option<f32>>,
parent_size: Size<Option<f32>>,
available_space: Size<AvailableSpace>,
-) -> Size<f32> {
+ _run_mode: RunMode,
+) -> SizeAndBaselines {
let get_child_styles_iter = |node| tree.children(node).map(|child_node: &Node| tree.style(*child_node));
let style = tree.style(node).clone();
let child_styles_iter = get_child_styles_iter(node);
@@ -290,13 +319,12 @@ pub fn compute(
// Position hidden child
if child_style.display == Display::None {
*tree.layout_mut(node) = Layout::with_order(order);
- compute_node_layout(
+ GenericAlgorithm::perform_layout(
tree,
child,
Size::NONE,
Size::NONE,
Size::MAX_CONTENT,
- RunMode::PeformLayout,
SizingMode::InherentSize,
);
order += 1;
@@ -341,5 +369,5 @@ pub fn compute(
}
});
- container_border_box
+ SizeAndBaselines { size: container_border_box, first_baselines: Point::NONE }
}
diff --git a/src/compute/grid/types/grid_item.rs b/src/compute/grid/types/grid_item.rs
index fcd76cd41..7eef6da71 100644
--- a/src/compute/grid/types/grid_item.rs
+++ b/src/compute/grid/types/grid_item.rs
@@ -1,10 +1,10 @@
//! Contains GridItem used to represent a single grid item during layout
use super::GridTrack;
use crate::axis::AbstractAxis;
-use crate::compute::compute_node_layout;
use crate::compute::grid::OriginZeroLine;
+use crate::compute::{GenericAlgorithm, LayoutAlgorithm};
use crate::geometry::{Line, Rect, Size};
-use crate::layout::{RunMode, SizingMode};
+use crate::layout::SizingMode;
use crate::node::Node;
use crate::prelude::LayoutTree;
use crate::resolve::MaybeResolve;
@@ -188,13 +188,12 @@ impl GridItem {
inner_node_size: Size<Option<f32>>,
) -> Size<f32> {
self.min_content_contribution_cache.unwrap_or_else(|| {
- let size = compute_node_layout(
+ let size = GenericAlgorithm::measure_size(
tree,
self.node,
known_dimensions,
inner_node_size,
Size::MIN_CONTENT,
- RunMode::ComputeSize,
SizingMode::InherentSize,
);
self.min_content_contribution_cache = Some(size);
@@ -210,13 +209,12 @@ impl GridItem {
inner_node_size: Size<Option<f32>>,
) -> Size<f32> {
self.max_content_contribution_cache.unwrap_or_else(|| {
- let size = compute_node_layout(
+ let size = GenericAlgorithm::measure_size(
tree,
self.node,
known_dimensions,
inner_node_size,
Size::MAX_CONTENT,
- RunMode::ComputeSize,
SizingMode::InherentSize,
);
self.max_content_contribution_cache = Some(size);
diff --git a/src/compute/leaf.rs b/src/compute/leaf.rs
index 9257c10d1..2c347a64d 100644
--- a/src/compute/leaf.rs
+++ b/src/compute/leaf.rs
@@ -1,7 +1,8 @@
//! Computes size using styles and measure functions
-use crate::geometry::Size;
-use crate::layout::{RunMode, SizingMode};
+use crate::compute::LayoutAlgorithm;
+use crate::geometry::{Point, Size};
+use crate::layout::{SizeAndBaselines, SizingMode};
use crate::math::MaybeMath;
use crate::node::Node;
use crate::resolve::{MaybeResolve, ResolveOrZero};
@@ -12,6 +13,34 @@ use crate::tree::LayoutTree;
#[cfg(feature = "debug")]
use crate::debug::NODE_LOGGER;
+/// The public interface to Taffy's leaf node algorithm implementation
+pub(crate) struct LeafAlgorithm;
+impl LayoutAlgorithm for LeafAlgorithm {
+ const NAME: &'static str = "LEAF";
+
+ fn perform_layout(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+ ) -> SizeAndBaselines {
+ compute(tree, node, known_dimensions, parent_size, available_space, sizing_mode)
+ }
+
+ fn measure_size(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+ ) -> Size<f32> {
+ compute(tree, node, known_dimensions, parent_size, available_space, sizing_mode).size
+ }
+}
+
/// Compute the size of a leaf node (node with no children)
pub(crate) fn compute(
tree: &mut impl LayoutTree,
@@ -19,9 +48,8 @@ pub(crate) fn compute(
known_dimensions: Size<Option<f32>>,
parent_size: Size<Option<f32>>,
available_space: Size<AvailableSpace>,
- _run_mode: RunMode,
sizing_mode: SizingMode,
-) -> Size<f32> {
+) -> SizeAndBaselines {
let style = tree.style(node);
// Resolve node's preferred/min/max sizes (width/heights) against the available space (percentages resolve to pixel values)
@@ -55,7 +83,8 @@ pub(crate) fn compute(
// Return early if both width and height are known
if let Size { width: Some(width), height: Some(height) } = node_size {
- return Size { width, height }.maybe_clamp(node_min_size, node_max_size);
+ let size = Size { width, height }.maybe_clamp(node_min_size, node_max_size);
+ return SizeAndBaselines { size, first_baselines: Point::NONE };
};
if tree.needs_measure(node) {
@@ -81,7 +110,8 @@ pub(crate) fn compute(
height: f32_max(measured_size.height, aspect_ratio.map(|ratio| measured_size.width / ratio).unwrap_or(0.0)),
};
- return node_size.unwrap_or(measured_size).maybe_clamp(node_min_size, node_max_size);
+ let size = node_size.unwrap_or(measured_size).maybe_clamp(node_min_size, node_max_size);
+ return SizeAndBaselines { size, first_baselines: Point::NONE };
}
// Note: both horizontal and vertical percentage padding/borders are resolved against the container's inline size (i.e. width).
@@ -89,7 +119,7 @@ pub(crate) fn compute(
let padding = style.padding.resolve_or_zero(parent_size.width);
let border = style.border.resolve_or_zero(parent_size.width);
- Size {
+ let size = Size {
width: node_size
.width
// .unwrap_or(0.0) + padding.horizontal_axis_sum() + border.horizontal_axis_sum(), // content-box
@@ -100,5 +130,6 @@ pub(crate) fn compute(
// .unwrap_or(0.0) + padding.vertical_axis_sum() + border.vertical_axis_sum(), // content-box
.unwrap_or(0.0 + padding.vertical_axis_sum() + border.vertical_axis_sum()) // border-box
.maybe_clamp(node_min_size.height, node_max_size.height),
- }
+ };
+ SizeAndBaselines { size, first_baselines: Point::NONE }
}
diff --git a/src/compute/mod.rs b/src/compute/mod.rs
index 4c0357a58..8e9a20307 100644
--- a/src/compute/mod.rs
+++ b/src/compute/mod.rs
@@ -10,12 +10,16 @@ pub(crate) mod grid;
use crate::data::CACHE_SIZE;
use crate::error::TaffyError;
use crate::geometry::{Point, Size};
-use crate::layout::{Cache, Layout, RunMode, SizingMode};
+use crate::layout::{Cache, Layout, RunMode, SizeAndBaselines, SizingMode};
use crate::node::Node;
use crate::style::{AvailableSpace, Display};
use crate::sys::round;
use crate::tree::LayoutTree;
+use self::flexbox::FlexboxAlgorithm;
+use self::grid::CssGridAlgorithm;
+use self::leaf::LeafAlgorithm;
+
#[cfg(feature = "debug")]
use crate::debug::NODE_LOGGER;
@@ -26,17 +30,16 @@ pub fn compute_layout(
available_space: Size<AvailableSpace>,
) -> Result<(), TaffyError> {
// Recursively compute node layout
- let size = compute_node_layout(
+ let size_and_baselines = GenericAlgorithm::perform_layout(
tree,
root,
Size::NONE,
available_space.into_options(),
available_space,
- RunMode::PeformLayout,
SizingMode::InherentSize,
);
- let layout = Layout { order: 0, size, location: Point::ZERO };
+ let layout = Layout { order: 0, size: size_and_baselines.size, location: Point::ZERO };
*tree.layout_mut(root) = layout;
// Recursively round the layout's of this node and all children
@@ -45,6 +48,78 @@ pub fn compute_layout(
Ok(())
}
+/// A common interface that all Taffy layout algorithms conform to
+pub(crate) trait LayoutAlgorithm {
+ /// The name of the algorithm (mainly used for debug purposes)
+ const NAME: &'static str;
+
+ /// Compute the size of the node given the specified constraints
+ fn measure_size(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+ ) -> Size<f32>;
+
+ /// Perform a full layout on the node given the specified constraints
+ fn perform_layout(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+ ) -> SizeAndBaselines;
+}
+
+/// The public interface to a generic algorithm that abstracts over all of Taffy's algorithms
+/// and applies the correct one based on the `Display` style
+pub struct GenericAlgorithm;
+impl LayoutAlgorithm for GenericAlgorithm {
+ const NAME: &'static str = "GENERIC";
+
+ fn perform_layout(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+ ) -> SizeAndBaselines {
+ compute_node_layout(
+ tree,
+ node,
+ known_dimensions,
+ parent_size,
+ available_space,
+ RunMode::PeformLayout,
+ sizing_mode,
+ )
+ }
+
+ fn measure_size(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+ ) -> Size<f32> {
+ compute_node_layout(
+ tree,
+ node,
+ known_dimensions,
+ parent_size,
+ available_space,
+ RunMode::ComputeSize,
+ sizing_mode,
+ )
+ .size
+ }
+}
+
/// Updates the stored layout of the provided `node` and its children
fn compute_node_layout(
tree: &mut impl LayoutTree,
@@ -54,7 +129,7 @@ fn compute_node_layout(
available_space: Size<AvailableSpace>,
run_mode: RunMode,
sizing_mode: SizingMode,
-) -> Size<f32> {
+) -> SizeAndBaselines {
#[cfg(feature = "debug")]
NODE_LOGGER.push_node(node);
#[cfg(feature = "debug")]
@@ -62,69 +137,121 @@ fn compute_node_layout(
// First we check if we have a cached result for the given input
let cache_run_mode = if tree.is_childless(node) { RunMode::PeformLayout } else { run_mode };
- if let Some(cached_size) =
+ if let Some(cached_size_and_baselines) =
compute_from_cache(tree, node, known_dimensions, available_space, cache_run_mode, sizing_mode)
{
#[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("CACHE", cached_size);
- #[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("run_mode", run_mode);
+ NODE_LOGGER.labelled_debug_log("CACHE", cached_size_and_baselines.size);
#[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("sizing_mode", sizing_mode);
- #[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("known_dimensions", known_dimensions);
- #[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("available_space", available_space);
+ debug_log_node(known_dimensions, parent_size, available_space, run_mode, sizing_mode);
#[cfg(feature = "debug")]
NODE_LOGGER.pop_node();
- return cached_size;
+ return cached_size_and_baselines;
}
#[cfg(feature = "debug")]
NODE_LOGGER.log("COMPUTE");
#[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("run_mode", run_mode);
- #[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("sizing_mode", sizing_mode);
- #[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("known_dimensions", known_dimensions);
- #[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("available_space", available_space);
-
- // If this is a leaf node we can skip a lot of this function in some cases
- let computed_size = if tree.is_childless(node) {
+ debug_log_node(known_dimensions, parent_size, available_space, run_mode, sizing_mode);
+
+ /// Inlined function generic over the LayoutAlgorithm to reduce code duplication
+ #[inline(always)]
+ fn perform_computations<Algorithm: LayoutAlgorithm>(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ run_mode: RunMode,
+ sizing_mode: SizingMode,
+ ) -> SizeAndBaselines {
#[cfg(feature = "debug")]
- NODE_LOGGER.log("Algo: leaf");
- self::leaf::compute(tree, node, known_dimensions, parent_size, available_space, run_mode, sizing_mode)
+ NODE_LOGGER.log(Algorithm::NAME);
+
+ match run_mode {
+ RunMode::PeformLayout => {
+ Algorithm::perform_layout(tree, node, known_dimensions, parent_size, available_space, sizing_mode)
+ }
+ RunMode::ComputeSize => {
+ let size =
+ Algorithm::measure_size(tree, node, known_dimensions, parent_size, available_space, sizing_mode);
+ SizeAndBaselines { size, first_baselines: Point::NONE }
+ }
+ }
+ }
+
+ let computed_size_and_baselines = if tree.is_childless(node) {
+ perform_computations::<LeafAlgorithm>(
+ tree,
+ node,
+ known_dimensions,
+ parent_size,
+ available_space,
+ run_mode,
+ sizing_mode,
+ )
} else {
- // println!("match {:?}", tree.style(node).display);
match tree.style(node).display {
- Display::Flex => {
- #[cfg(feature = "debug")]
- NODE_LOGGER.log("Algo: flexbox");
- self::flexbox::compute(tree, node, known_dimensions, parent_size, available_space, run_mode)
- }
+ Display::Flex => perform_computations::<FlexboxAlgorithm>(
+ tree,
+ node,
+ known_dimensions,
+ parent_size,
+ available_space,
+ run_mode,
+ sizing_mode,
+ ),
#[cfg(feature = "grid")]
- Display::Grid => self::grid::compute(tree, node, known_dimensions, parent_size, available_space),
- Display::None => {
- #[cfg(feature = "debug")]
- NODE_LOGGER.log("Algo: none");
- perform_hidden_layout(tree, node)
- }
+ Display::Grid => perform_computations::<CssGridAlgorithm>(
+ tree,
+ node,
+ known_dimensions,
+ parent_size,
+ available_space,
+ run_mode,
+ sizing_mode,
+ ),
+ Display::None => perform_computations::<HiddenAlgorithm>(
+ tree,
+ node,
+ known_dimensions,
+ parent_size,
+ available_space,
+ run_mode,
+ sizing_mode,
+ ),
}
};
// Cache result
let cache_slot = compute_cache_slot(known_dimensions, available_space);
- *tree.cache_mut(node, cache_slot) =
- Some(Cache { known_dimensions, available_space, run_mode: cache_run_mode, cached_size: computed_size });
+ *tree.cache_mut(node, cache_slot) = Some(Cache {
+ known_dimensions,
+ available_space,
+ run_mode: cache_run_mode,
+ cached_size_and_baselines: computed_size_and_baselines,
+ });
#[cfg(feature = "debug")]
- NODE_LOGGER.labelled_debug_log("RESULT", computed_size);
+ NODE_LOGGER.labelled_debug_log("RESULT", computed_size_and_baselines.size);
#[cfg(feature = "debug")]
NODE_LOGGER.pop_node();
- computed_size
+ computed_size_and_baselines
+}
+
+#[cfg(feature = "debug")]
+fn debug_log_node(
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ run_mode: RunMode,
+ sizing_mode: SizingMode,
+) {
+ NODE_LOGGER.labelled_debug_log("run_mode", run_mode);
+ NODE_LOGGER.labelled_debug_log("sizing_mode", sizing_mode);
+ NODE_LOGGER.labelled_debug_log("known_dimensions", known_dimensions);
+ NODE_LOGGER.labelled_debug_log("available_space", available_space);
}
/// Return the cache slot to cache the current computed result in
@@ -180,7 +307,7 @@ fn compute_from_cache(
available_space: Size<AvailableSpace>,
run_mode: RunMode,
sizing_mode: SizingMode,
-) -> Option<Size<f32>> {
+) -> Option<SizeAndBaselines> {
for idx in 0..CACHE_SIZE {
let entry = tree.cache_mut(node, idx);
if let Some(entry) = entry {
@@ -189,22 +316,24 @@ fn compute_from_cache(
return None;
}
+ let cached_size = entry.cached_size_and_baselines.size;
+
if (known_dimensions.width == entry.known_dimensions.width
- || known_dimensions.width == Some(entry.cached_size.width))
+ || known_dimensions.width == Some(cached_size.width))
&& (known_dimensions.height == entry.known_dimensions.height
- || known_dimensions.height == Some(entry.cached_size.height))
+ || known_dimensions.height == Some(cached_size.height))
&& (known_dimensions.width.is_some()
|| entry.available_space.width.is_roughly_equal(available_space.width)
|| (sizing_mode == SizingMode::ContentSize
&& available_space.width.is_definite()
- && available_space.width.unwrap() >= entry.cached_size.width))
+ && available_space.width.unwrap() >= cached_size.width))
&& (known_dimensions.height.is_some()
|| entry.available_space.height.is_roughly_equal(available_space.height)
|| (sizing_mode == SizingMode::ContentSize
&& available_space.height.is_definite()
- && available_space.height.unwrap() >= entry.cached_size.height))
+ && available_space.height.unwrap() >= cached_size.height))
{
- return Some(entry.cached_size);
+ return Some(entry.cached_size_and_baselines);
}
}
}
@@ -212,9 +341,38 @@ fn compute_from_cache(
None
}
+/// The public interface to Taffy's hidden node algorithm implementation
+struct HiddenAlgorithm;
+impl LayoutAlgorithm for HiddenAlgorithm {
+ const NAME: &'static str = "NONE";
+
+ fn perform_layout(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ _known_dimensions: Size<Option<f32>>,
+ _parent_size: Size<Option<f32>>,
+ _available_space: Size<AvailableSpace>,
+ _sizing_mode: SizingMode,
+ ) -> SizeAndBaselines {
+ perform_hidden_layout(tree, node);
+ SizeAndBaselines { size: Size::ZERO, first_baselines: Point::NONE }
+ }
+
+ fn measure_size(
+ _tree: &mut impl LayoutTree,
+ _node: Node,
+ _known_dimensions: Size<Option<f32>>,
+ _parent_size: Size<Option<f32>>,
+ _available_space: Size<AvailableSpace>,
+ _sizing_mode: SizingMode,
+ ) -> Size<f32> {
+ Size::ZERO
+ }
+}
+
/// Creates a layout for this node and its children, recursively.
/// Each hidden node has zero size and is placed at the origin
-fn perform_hidden_layout(tree: &mut impl LayoutTree, node: Node) -> Size<f32> {
+fn perform_hidden_layout(tree: &mut impl LayoutTree, node: Node) {
/// Recursive function to apply hidden layout to all descendents
fn perform_hidden_layout_inner(tree: &mut impl LayoutTree, node: Node, order: u32) {
*tree.layout_mut(node) = Layout::with_order(order);
@@ -226,8 +384,6 @@ fn perform_hidden_layout(tree: &mut impl LayoutTree, node: Node) -> Size<f32> {
for order in 0..tree.child_count(node) {
perform_hidden_layout_inner(tree, tree.child(node, order), order as _);
}
-
- Size::ZERO
}
/// Rounds the calculated [`NodeData`] according to the spec
diff --git a/src/geometry.rs b/src/geometry.rs
index 3df769443..21a187b00 100644
--- a/src/geometry.rs
+++ b/src/geometry.rs
@@ -441,7 +441,12 @@ pub struct Point<T> {
impl Point<f32> {
/// A [`Point`] with values (0,0), representing the origin
- pub const ZERO: Point<f32> = Self { x: 0.0, y: 0.0 };
+ pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
+}
+
+impl Point<Option<f32>> {
+ /// A [`Point`] with values (None, None)
+ pub const NONE: Self = Self { x: None, y: None };
}
/// Generic struct which holds a "min" value and a "max" value
diff --git a/src/layout.rs b/src/layout.rs
index c9e343f6b..13fabe78e 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -22,8 +22,22 @@ pub enum SizingMode {
InherentSize,
}
+/// A struct containing both the size of a node and it's first baseline in each dimension (if it has any)
+///
+/// A baseline is the line on which text sits. Your node likely has a baseline if it is a text node, or contains
+/// children that may be text nodes. See https://www.w3.org/TR/css-writing-modes-3/#intro-baselines for details.
+/// If your node does not have a baseline (or you are unsure how to compute it), then simply return `Point::NONE`
+/// for the first_baselines field
+#[derive(Debug, Copy, Clone)]
+pub struct SizeAndBaselines {
+ /// The size of the node
+ pub size: Size<f32>,
+ /// The first baseline of the node in each dimension, if any
+ pub first_baselines: Point<Option<f32>>,
+}
+
/// The final result of a layout algorithm for a single [`Node`](crate::node::Node).
-#[derive(Copy, Debug, Clone)]
+#[derive(Debug, Copy, Clone)]
pub struct Layout {
/// The relative ordering of the node
///
@@ -67,6 +81,6 @@ pub struct Cache {
/// Whether or not layout should be recomputed
pub(crate) run_mode: RunMode,
- /// The cached size of the item
- pub(crate) cached_size: Size<f32>,
+ /// The cached size and baselines of the item
+ pub(crate) cached_size_and_baselines: SizeAndBaselines,
}
diff --git a/src/prelude.rs b/src/prelude.rs
index 2ec946cf6..2cff4edc5 100644
--- a/src/prelude.rs
+++ b/src/prelude.rs
@@ -1,7 +1,29 @@
//! Commonly used types
+use crate::compute::LayoutAlgorithm;
+use crate::layout::{SizeAndBaselines, SizingMode};
+
+/// Apply the flexbox algorithm and recursively layout the specified node
+#[inline(always)]
+pub fn layout_flexbox(
+ tree: &mut impl LayoutTree,
+ node: Node,
+ known_dimensions: Size<Option<f32>>,
+ parent_size: Size<Option<f32>>,
+ available_space: Size<AvailableSpace>,
+ sizing_mode: SizingMode,
+) -> SizeAndBaselines {
+ crate::compute::flexbox::FlexboxAlgorithm::perform_layout(
+ tree,
+ node,
+ known_dimensions,
+ parent_size,
+ available_space,
+ sizing_mode,
+ )
+}
+
pub use crate::{
- compute::flexbox::compute as layout_flexbox,
geometry::{Line, Rect, Size},
layout::Layout,
node::{Node, Taffy},
diff --git a/test_fixtures/xalign_baseline_child_margin.html b/test_fixtures/align_baseline_child_margin.html
similarity index 88%
rename from test_fixtures/xalign_baseline_child_margin.html
rename to test_fixtures/align_baseline_child_margin.html
index 79e7e4422..00cda4c96 100644
--- a/test_fixtures/xalign_baseline_child_margin.html
+++ b/test_fixtures/align_baseline_child_margin.html
@@ -12,7 +12,7 @@
<div id="test-root" style="width: 100px; height: 100px; flex-direction:row; align-items: baseline;">
<div style="width: 50px; height: 50px;margin: 5px;"></div>
<div style="flex-direction: column;width: 50px; height: 20px;">
- <div style="width: 50px; height: 10px;margin: 1px;"></div>
+ <div style="width: 50px; height: 10px;margin: 5px;"></div>
</div>
</div>
diff --git a/test_fixtures/xalign_baseline_child_margin_percent.html b/test_fixtures/align_baseline_child_margin_percent.html
similarity index 100%
rename from test_fixtures/xalign_baseline_child_margin_percent.html
rename to test_fixtures/align_baseline_child_margin_percent.html
diff --git a/test_fixtures/xalign_baseline_child_multiline_no_override_on_secondline.html b/test_fixtures/align_baseline_child_multiline_no_override_on_secondline.html
similarity index 100%
rename from test_fixtures/xalign_baseline_child_multiline_no_override_on_secondline.html
rename to test_fixtures/align_baseline_child_multiline_no_override_on_secondline.html
diff --git a/test_fixtures/xalign_baseline_child_multiline_override.html b/test_fixtures/align_baseline_child_multiline_override.html
similarity index 100%
rename from test_fixtures/xalign_baseline_child_multiline_override.html
rename to test_fixtures/align_baseline_child_multiline_override.html
diff --git a/test_fixtures/xalign_baseline_child_padding.html b/test_fixtures/align_baseline_child_padding.html
similarity index 100%
rename from test_fixtures/xalign_baseline_child_padding.html
rename to test_fixtures/align_baseline_child_padding.html
diff --git a/test_fixtures/xalign_baseline_multiline.html b/test_fixtures/align_baseline_multiline.html
similarity index 100%
rename from test_fixtures/xalign_baseline_multiline.html
rename to test_fixtures/align_baseline_multiline.html
diff --git a/test_fixtures/xalign_baseline_multiline_row_and_column.html b/test_fixtures/align_baseline_multiline_row_and_column.html
similarity index 100%
rename from test_fixtures/xalign_baseline_multiline_row_and_column.html
rename to test_fixtures/align_baseline_multiline_row_and_column.html
diff --git a/test_fixtures/xgrid_align_items_baseline_complex.html b/test_fixtures/xgrid_align_items_baseline_complex.html
new file mode 100644
index 000000000..31ff0b017
--- /dev/null
+++ b/test_fixtures/xgrid_align_items_baseline_complex.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="height: 120px; width: 120px; display: grid; grid-template-columns: 40px 40px 40px;grid-template-rows: 40px 40px 40px;align-items: baseline;">
+ <div style="height: 20px;width: 20px"></div>
+ <div style="height: 20px;width: 20px">
+ <div style="height: 10px"></div>
+ </div>
+ <div style="height: 20px;width: 20px">
+ <div style="height: 10px"></div>
+ </div>
+ <div style="height: 20px;width: 20px"></div>
+ <div style="height: 20px;width: 20px"></div>
+ <div style="height: 20px;width: 20px"></div>
+ <div style="height: 20px;width: 20px">
+ <div style="height: 10px"></div>
+ </div>
+ <div style="height: 20px;width: 20px">
+ <div style="height: 5px"></div>
+ </div>
+ <div style="height: 20px;width: 20px"></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/tests/generated/align_baseline_child_margin.rs b/tests/generated/align_baseline_child_margin.rs
new file mode 100644
index 000000000..fc4b78bdd
--- /dev/null
+++ b/tests/generated/align_baseline_child_margin.rs
@@ -0,0 +1,87 @@
+#[test]
+fn align_baseline_child_margin() {
+ 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 {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(5f32),
+ right: taffy::style::LengthPercentageAuto::Points(5f32),
+ top: taffy::style::LengthPercentageAuto::Points(5f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(5f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Points(5f32),
+ right: taffy::style::LengthPercentageAuto::Points(5f32),
+ top: taffy::style::LengthPercentageAuto::Points(5f32),
+ bottom: taffy::style::LengthPercentageAuto::Points(5f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+ println!("\nComputed tree:");
+ taffy::debug::print_tree(&taffy, node);
+ println!();
+ let Layout { size, location, .. } = taffy.layout(node).unwrap();
+ assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, 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, 50f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 50f32, size.height);
+ assert_eq!(location.x, 5f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 5f32, location.x);
+ assert_eq!(location.y, 5f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 5f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node1).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 20f32, size.height);
+ assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, location.x);
+ assert_eq!(location.y, 40f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 40f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node10).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 50f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 10f32, size.height);
+ assert_eq!(location.x, 5f32, "x of node {:?}. Expected {}. Actual {}", node10.data(), 5f32, location.x);
+ assert_eq!(location.y, 5f32, "y of node {:?}. Expected {}. Actual {}", node10.data(), 5f32, location.y);
+}
diff --git a/tests/generated/align_baseline_child_margin_percent.rs b/tests/generated/align_baseline_child_margin_percent.rs
new file mode 100644
index 000000000..f02ac320b
--- /dev/null
+++ b/tests/generated/align_baseline_child_margin_percent.rs
@@ -0,0 +1,87 @@
+#[test]
+fn align_baseline_child_margin_percent() {
+ 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 {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Percent(0.05f32),
+ right: taffy::style::LengthPercentageAuto::Percent(0.05f32),
+ top: taffy::style::LengthPercentageAuto::Percent(0.05f32),
+ bottom: taffy::style::LengthPercentageAuto::Percent(0.05f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ margin: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentageAuto::Percent(0.01f32),
+ right: taffy::style::LengthPercentageAuto::Percent(0.01f32),
+ top: taffy::style::LengthPercentageAuto::Percent(0.01f32),
+ bottom: taffy::style::LengthPercentageAuto::Percent(0.01f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+ println!("\nComputed tree:");
+ taffy::debug::print_tree(&taffy, node);
+ println!();
+ let Layout { size, location, .. } = taffy.layout(node).unwrap();
+ assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, 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, 50f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 50f32, size.height);
+ assert_eq!(location.x, 5f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 5f32, location.x);
+ assert_eq!(location.y, 5f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 5f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node1).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 20f32, size.height);
+ assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, location.x);
+ assert_eq!(location.y, 45f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 45f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node10).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 50f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 10f32, size.height);
+ assert_eq!(location.x, 1f32, "x of node {:?}. Expected {}. Actual {}", node10.data(), 1f32, location.x);
+ assert_eq!(location.y, 1f32, "y of node {:?}. Expected {}. Actual {}", node10.data(), 1f32, location.y);
+}
diff --git a/tests/generated/align_baseline_child_multiline_no_override_on_secondline.rs b/tests/generated/align_baseline_child_multiline_no_override_on_secondline.rs
new file mode 100644
index 000000000..e988cae89
--- /dev/null
+++ b/tests/generated/align_baseline_child_multiline_no_override_on_secondline.rs
@@ -0,0 +1,118 @@
+#[test]
+fn align_baseline_child_multiline_no_override_on_secondline() {
+ 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 {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(60f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node11 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node12 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node13 = taffy
+ .new_leaf(taffy::style::Style {
+ align_self: Some(taffy::style::AlignSelf::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_wrap: taffy::style::FlexWrap::Wrap,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(25f32),
+ },
+ ..Default::default()
+ },
+ &[node10, node11, node12, node13],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+ println!("\nComputed tree:");
+ taffy::debug::print_tree(&taffy, node);
+ println!();
+ let Layout { size, location, .. } = taffy.layout(node).unwrap();
+ assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, 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, 50f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 50f32, size.width);
+ assert_eq!(size.height, 60f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 60f32, 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, 50f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, size.width);
+ assert_eq!(size.height, 25f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 25f32, size.height);
+ assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, location.x);
+ assert_eq!(location.y, 40f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 40f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node10).unwrap();
+ assert_eq!(size.width, 25f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 25f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 20f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node10.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node10.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node11).unwrap();
+ assert_eq!(size.width, 25f32, "width of node {:?}. Expected {}. Actual {}", node11.data(), 25f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node11.data(), 10f32, size.height);
+ assert_eq!(location.x, 25f32, "x of node {:?}. Expected {}. Actual {}", node11.data(), 25f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node11.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node12).unwrap();
+ assert_eq!(size.width, 25f32, "width of node {:?}. Expected {}. Actual {}", node12.data(), 25f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node12.data(), 20f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node12.data(), 0f32, location.x);
+ assert_eq!(location.y, 20f32, "y of node {:?}. Expected {}. Actual {}", node12.data(), 20f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node13).unwrap();
+ assert_eq!(size.width, 25f32, "width of node {:?}. Expected {}. Actual {}", node13.data(), 25f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node13.data(), 10f32, size.height);
+ assert_eq!(location.x, 25f32, "x of node {:?}. Expected {}. Actual {}", node13.data(), 25f32, location.x);
+ assert_eq!(location.y, 20f32, "y of node {:?}. Expected {}. Actual {}", node13.data(), 20f32, location.y);
+}
diff --git a/tests/generated/align_baseline_child_multiline_override.rs b/tests/generated/align_baseline_child_multiline_override.rs
new file mode 100644
index 000000000..a4673a4fa
--- /dev/null
+++ b/tests/generated/align_baseline_child_multiline_override.rs
@@ -0,0 +1,119 @@
+#[test]
+fn align_baseline_child_multiline_override() {
+ 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 {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(60f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node11 = taffy
+ .new_leaf(taffy::style::Style {
+ align_self: Some(taffy::style::AlignSelf::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node12 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node13 = taffy
+ .new_leaf(taffy::style::Style {
+ align_self: Some(taffy::style::AlignSelf::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(25f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_wrap: taffy::style::FlexWrap::Wrap,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(25f32),
+ },
+ ..Default::default()
+ },
+ &[node10, node11, node12, node13],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+ println!("\nComputed tree:");
+ taffy::debug::print_tree(&taffy, node);
+ println!();
+ let Layout { size, location, .. } = taffy.layout(node).unwrap();
+ assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, 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, 50f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 50f32, size.width);
+ assert_eq!(size.height, 60f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 60f32, 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, 50f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, size.width);
+ assert_eq!(size.height, 25f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 25f32, size.height);
+ assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, location.x);
+ assert_eq!(location.y, 50f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node10).unwrap();
+ assert_eq!(size.width, 25f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 25f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 20f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node10.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node10.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node11).unwrap();
+ assert_eq!(size.width, 25f32, "width of node {:?}. Expected {}. Actual {}", node11.data(), 25f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node11.data(), 10f32, size.height);
+ assert_eq!(location.x, 25f32, "x of node {:?}. Expected {}. Actual {}", node11.data(), 25f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node11.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node12).unwrap();
+ assert_eq!(size.width, 25f32, "width of node {:?}. Expected {}. Actual {}", node12.data(), 25f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node12.data(), 20f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node12.data(), 0f32, location.x);
+ assert_eq!(location.y, 20f32, "y of node {:?}. Expected {}. Actual {}", node12.data(), 20f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node13).unwrap();
+ assert_eq!(size.width, 25f32, "width of node {:?}. Expected {}. Actual {}", node13.data(), 25f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node13.data(), 10f32, size.height);
+ assert_eq!(location.x, 25f32, "x of node {:?}. Expected {}. Actual {}", node13.data(), 25f32, location.x);
+ assert_eq!(location.y, 20f32, "y of node {:?}. Expected {}. Actual {}", node13.data(), 20f32, location.y);
+}
diff --git a/tests/generated/align_baseline_child_padding.rs b/tests/generated/align_baseline_child_padding.rs
new file mode 100644
index 000000000..650dcc43e
--- /dev/null
+++ b/tests/generated/align_baseline_child_padding.rs
@@ -0,0 +1,87 @@
+#[test]
+fn align_baseline_child_padding() {
+ 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 {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ padding: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentage::Points(5f32),
+ right: taffy::style::LengthPercentage::Points(5f32),
+ top: taffy::style::LengthPercentage::Points(5f32),
+ bottom: taffy::style::LengthPercentage::Points(5f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ padding: taffy::geometry::Rect {
+ left: taffy::style::LengthPercentage::Points(5f32),
+ right: taffy::style::LengthPercentage::Points(5f32),
+ top: taffy::style::LengthPercentage::Points(5f32),
+ bottom: taffy::style::LengthPercentage::Points(5f32),
+ },
+ ..Default::default()
+ },
+ &[node0, node1],
+ )
+ .unwrap();
+ taffy.compute_layout(node, taffy::geometry::Size::MAX_CONTENT).unwrap();
+ println!("\nComputed tree:");
+ taffy::debug::print_tree(&taffy, node);
+ println!();
+ let Layout { size, location, .. } = taffy.layout(node).unwrap();
+ assert_eq!(size.width, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, 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, 50f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 50f32, size.height);
+ assert_eq!(location.x, 5f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 5f32, location.x);
+ assert_eq!(location.y, 5f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 5f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node1).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 20f32, size.height);
+ assert_eq!(location.x, 45f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 45f32, location.x);
+ assert_eq!(location.y, 40f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 40f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node10).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 50f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 10f32, size.height);
+ assert_eq!(location.x, 5f32, "x of node {:?}. Expected {}. Actual {}", node10.data(), 5f32, location.x);
+ assert_eq!(location.y, 5f32, "y of node {:?}. Expected {}. Actual {}", node10.data(), 5f32, location.y);
+}
diff --git a/tests/generated/align_baseline_multiline.rs b/tests/generated/align_baseline_multiline.rs
new file mode 100644
index 000000000..f8313b493
--- /dev/null
+++ b/tests/generated/align_baseline_multiline.rs
@@ -0,0 +1,122 @@
+#[test]
+fn align_baseline_multiline() {
+ 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 {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node20 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node2 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node20],
+ )
+ .unwrap();
+ let node3 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_wrap: taffy::style::FlexWrap::Wrap,
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..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, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, 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, 50f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 50f32, size.width);
+ assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 50f32, 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, 50f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 20f32, size.height);
+ assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, location.x);
+ assert_eq!(location.y, 40f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 40f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node10).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 50f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 10f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node10.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node10.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node2).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node2.data(), 50f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node2.data(), 20f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node2.data(), 0f32, location.x);
+ assert_eq!(location.y, 100f32, "y of node {:?}. Expected {}. Actual {}", node2.data(), 100f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node20).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node20.data(), 50f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node20.data(), 10f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node20.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node20.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node3).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node3.data(), 50f32, size.width);
+ assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node3.data(), 50f32, size.height);
+ assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node3.data(), 50f32, location.x);
+ assert_eq!(location.y, 60f32, "y of node {:?}. Expected {}. Actual {}", node3.data(), 60f32, location.y);
+}
diff --git a/tests/generated/align_baseline_multiline_row_and_column.rs b/tests/generated/align_baseline_multiline_row_and_column.rs
new file mode 100644
index 000000000..0e0d0c0b8
--- /dev/null
+++ b/tests/generated/align_baseline_multiline_row_and_column.rs
@@ -0,0 +1,122 @@
+#[test]
+fn align_baseline_multiline_row_and_column() {
+ 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 {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node10 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node1 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(50f32),
+ },
+ ..Default::default()
+ },
+ &[node10],
+ )
+ .unwrap();
+ let node20 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(10f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node2 = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_direction: taffy::style::FlexDirection::Column,
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ },
+ &[node20],
+ )
+ .unwrap();
+ let node3 = taffy
+ .new_leaf(taffy::style::Style {
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(50f32),
+ height: taffy::style::Dimension::Points(20f32),
+ },
+ ..Default::default()
+ })
+ .unwrap();
+ let node = taffy
+ .new_with_children(
+ taffy::style::Style {
+ flex_wrap: taffy::style::FlexWrap::Wrap,
+ align_items: Some(taffy::style::AlignItems::Baseline),
+ size: taffy::geometry::Size {
+ width: taffy::style::Dimension::Points(100f32),
+ height: taffy::style::Dimension::Points(100f32),
+ },
+ ..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, 100f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 100f32, size.width);
+ assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 100f32, 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, 50f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 50f32, size.width);
+ assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 50f32, 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, 50f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, size.width);
+ assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, size.height);
+ assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, location.x);
+ assert_eq!(location.y, 40f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 40f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node10).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 50f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 10f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node10.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node10.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node2).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node2.data(), 50f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node2.data(), 20f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node2.data(), 0f32, location.x);
+ assert_eq!(location.y, 100f32, "y of node {:?}. Expected {}. Actual {}", node2.data(), 100f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node20).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node20.data(), 50f32, size.width);
+ assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node20.data(), 10f32, size.height);
+ assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node20.data(), 0f32, location.x);
+ assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node20.data(), 0f32, location.y);
+ let Layout { size, location, .. } = taffy.layout(node3).unwrap();
+ assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node3.data(), 50f32, size.width);
+ assert_eq!(size.height, 20f32, "height of node {:?}. Expected {}. Actual {}", node3.data(), 20f32, size.height);
+ assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node3.data(), 50f32, location.x);
+ assert_eq!(location.y, 90f32, "y of node {:?}. Expected {}. Actual {}", node3.data(), 90f32, location.y);
+}
diff --git a/tests/generated/mod.rs b/tests/generated/mod.rs
index 2fd953c58..829311ccb 100644
--- a/tests/generated/mod.rs
+++ b/tests/generated/mod.rs
@@ -106,13 +106,20 @@ mod absolute_minmax_top_left_bottom_right_max;
mod absolute_minmax_top_left_bottom_right_min_max;
mod align_baseline;
mod align_baseline_child;
+mod align_baseline_child_margin;
+mod align_baseline_child_margin_percent;
mod align_baseline_child_multiline;
+mod align_baseline_child_multiline_no_override_on_secondline;
+mod align_baseline_child_multiline_override;
+mod align_baseline_child_padding;
mod align_baseline_child_top;
mod align_baseline_child_top2;
mod align_baseline_column;
mod align_baseline_double_nested_child;
+mod align_baseline_multiline;
mod align_baseline_multiline_column;
mod align_baseline_multiline_column2;
+mod align_baseline_multiline_row_and_column;
mod align_baseline_nested_child;
mod align_baseline_nested_column;
mod align_center_should_size_based_on_content;