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>, + parent_size: Size>, + available_space: Size, + _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>, + parent_size: Size>, + available_space: Size, + _sizing_mode: SizingMode, + ) -> Size { + 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>, available_space: Size, run_mode: RunMode, -) -> Size { +) -> 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>, available_space: Size, run_mode: RunMode, -) -> Size { +) -> 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>, available_space: Size, 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>, 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>, + parent_size: Size>, + available_space: Size, + _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>, + parent_size: Size>, + available_space: Size, + _sizing_mode: SizingMode, + ) -> Size { + 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>, parent_size: Size>, available_space: Size, -) -> Size { + _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>, ) -> Size { 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>, ) -> Size { 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>, + parent_size: Size>, + available_space: Size, + 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>, + parent_size: Size>, + available_space: Size, + sizing_mode: SizingMode, + ) -> Size { + 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>, parent_size: Size>, available_space: Size, - _run_mode: RunMode, sizing_mode: SizingMode, -) -> Size { +) -> 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, ) -> 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>, + parent_size: Size>, + available_space: Size, + sizing_mode: SizingMode, + ) -> Size; + + /// Perform a full layout on the node given the specified constraints + fn perform_layout( + tree: &mut impl LayoutTree, + node: Node, + known_dimensions: Size>, + parent_size: Size>, + available_space: Size, + 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>, + parent_size: Size>, + available_space: Size, + 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>, + parent_size: Size>, + available_space: Size, + sizing_mode: SizingMode, + ) -> Size { + 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, run_mode: RunMode, sizing_mode: SizingMode, -) -> Size { +) -> 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( + tree: &mut impl LayoutTree, + node: Node, + known_dimensions: Size>, + parent_size: Size>, + available_space: Size, + 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::( + 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::( + 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::( + tree, + node, + known_dimensions, + parent_size, + available_space, + run_mode, + sizing_mode, + ), + Display::None => perform_computations::( + 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>, + parent_size: Size>, + available_space: Size, + 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, run_mode: RunMode, sizing_mode: SizingMode, -) -> Option> { +) -> Option { 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>, + _parent_size: Size>, + _available_space: Size, + _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>, + _parent_size: Size>, + _available_space: Size, + _sizing_mode: SizingMode, + ) -> Size { + 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 { +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 { 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 { impl Point { /// A [`Point`] with values (0,0), representing the origin - pub const ZERO: Point = Self { x: 0.0, y: 0.0 }; + pub const ZERO: Self = Self { x: 0.0, y: 0.0 }; +} + +impl Point> { + /// 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, + /// The first baseline of the node in each dimension, if any + pub first_baselines: Point>, +} + /// 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, + /// 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>, + parent_size: Size>, + available_space: Size, + 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 @@
-
+
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 @@ + + + + + + + Test description + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + \ 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;