diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee3bddae0..ebca2eebf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: branches: - main - 0.2.x + - 0.3.x name: Continuous integration @@ -13,163 +14,95 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - uses: actions-rs/cargo@v1 - with: - command: build - args: --no-default-features - - uses: actions-rs/cargo@v1 - with: - command: test - args: --no-default-features + - uses: dtolnay/rust-toolchain@stable + - uses: Leafwing-Studios/cargo-cache@v1 + - run: cargo build --no-default-features + - run: cargo test --no-default-features test-features-default: name: "Test Suite [Features: Default]" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - uses: actions-rs/cargo@v1 - with: - command: build - - uses: actions-rs/cargo@v1 - with: - command: test + - uses: dtolnay/rust-toolchain@stable + - run: cargo build + - run: cargo test test-features-default-with-serde: name: "Test Suite [Features: Default + serde]" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features serde - - uses: actions-rs/cargo@v1 - with: - command: test - args: --features serde + - uses: dtolnay/rust-toolchain@stable + - run: cargo build --features serde + - run: cargo test --features serde test-features-alloc: name: "Test Suite [Features: alloc]" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - uses: actions-rs/cargo@v1 - with: - command: build - args: --no-default-features --features alloc,grid - - uses: actions-rs/cargo@v1 - with: - command: test - args: --no-default-features --features alloc,grid + - uses: dtolnay/rust-toolchain@stable + - run: cargo build --no-default-features --features alloc,grid + - run: cargo test --no-default-features --features alloc,grid test-features-alloc-no-grid: name: "Test Suite [Features: alloc (no grid)]" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - uses: actions-rs/cargo@v1 - with: - command: build - args: --no-default-features --features alloc - - uses: actions-rs/cargo@v1 - with: - command: test - args: --no-default-features --features alloc + - uses: dtolnay/rust-toolchain@stable + - run: cargo build --no-default-features --features alloc + - run: cargo test --no-default-features --features alloc test-features-default-no-grid: name: "Test Suite [Features: std (no grid)]" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - uses: actions-rs/cargo@v1 - with: - command: build - args: --no-default-features --features std - - uses: actions-rs/cargo@v1 - with: - command: test - args: --no-default-features --features std + - uses: dtolnay/rust-toolchain@stable + - uses: Leafwing-Studios/cargo-cache@v1 + - run: cargo build --no-default-features --features std + - run: cargo test --no-default-features --features std fmt: name: Rustfmt runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: stable - override: true - - run: rustup component add rustfmt - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + components: rustfmt + - uses: Leafwing-Studios/cargo-cache@v1 + - run: cargo fmt --all -- --check clippy: name: Clippy runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: nightly - override: true - - run: rustup component add clippy - - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --workspace -- -D warnings + components: clippy + - uses: Leafwing-Studios/cargo-cache@v1 + - run: cargo +nightly clippy --workspace -- -D warnings doc: name: Documentation runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: stable - override: true - - run: rustup component add clippy - - uses: actions-rs/cargo@v1 - with: - command: doc + components: clippy + - uses: Leafwing-Studios/cargo-cache@v1 + - run: cargo doc env: RUSTDOCFLAGS: "-D warnings" - markdownlint: name: Markdown Lint runs-on: ubuntu-latest diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 14df77370..2c953520a 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -22,12 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - name: Install cargo-deny - run: cargo install cargo-deny + - uses: taiki-e/install-action@cargo-deny - name: Check for security advisories and unmaintained crates run: cargo deny check advisories @@ -35,12 +30,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - name: Install cargo-deny - run: cargo install cargo-deny + - uses: taiki-e/install-action@cargo-deny - name: Check for banned and duplicated dependencies run: cargo deny check bans @@ -48,12 +38,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - name: Install cargo-deny - run: cargo install cargo-deny + - uses: taiki-e/install-action@cargo-deny - name: Check for unauthorized licenses run: cargo deny check licenses @@ -61,11 +46,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - name: Install cargo-deny - run: cargo install cargo-deny + - uses: taiki-e/install-action@cargo-deny - name: Checked for unauthorized crate sources run: cargo deny check sources diff --git a/Cargo.toml b/Cargo.toml index 963129e9a..fc415b670 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "taffy" -version = "0.3.4" +version = "0.3.11" authors = [ "Alice Cecile ", "Johnathan Kelley ", ] edition = "2021" include = ["src/**/*", "Cargo.toml", "README.md"] -description = "A flexible UI layout library" +description = "A flexible UI layout library " repository = "https://github.com/DioxusLabs/taffy" keywords = ["cross-platform", "layout", "flexbox", "css-grid", "grid"] categories = ["gui"] @@ -34,7 +34,7 @@ profile = [] [dev-dependencies] criterion = "0.4" -rstest = "0.16.0" +rstest = "0.17.0" rand = "0.8.5" rand_chacha = "0.3.1" yoga = "0.4.0" @@ -48,6 +48,11 @@ taffy = { path = ".", features = ["random"] } lto = true panic = 'abort' +[[bench]] +name = "tree_creation" +path = "benches/tree_creation.rs" +harness = false + [[bench]] name = "flexbox" path = "benches/flexbox.rs" diff --git a/RELEASES.md b/RELEASES.md index 52116b32c..47ba3a2f3 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,5 +1,49 @@ # Release Notes +## 0.3.11 + +### Fixes + +- Fix exponential blowup when laying out trees containing nodes with min and max sizes. + +## 0.3.10 + +### Fixes + +- Fix sizing of children when the available_space < min_size (#407) + +## 0.3.9 + +### Fixes + +- Fix caching bug where a cached result would sometimes be incorrectly used when the amount of available space increased (bevyengine/bevy#8111) and (bevyengine/bevy#8124) + +## 0.3.8 + +### Fixes + +- Fix incorrect min-content size for `flex-wrap: wrap` nodes (bevyengine/bevy#8082) + +## 0.3.7 + +### Fixes + +- Fix: Make `padding` and `border` floor node sizes (#372) +- Fix: Prevent percentages contributing to min-content sizes (#388) (also fixes bevyengine/bevy#8017) + +## 0.3.6 + +### Fixes + +- Fix: Ignore `align_content` when `flex_wrap` is set to `nowrap` (#383) + +## 0.3.5 + +### Fixes + +- Fix `display: none` when it is set on a flexbox child (#380) +- Fix `display: none` when it is set on a grid child (#381) + ## 0.3.4 ### Fixes diff --git a/benches/helpers/mod.rs b/benches/helpers/mod.rs index 66269b571..617fc6897 100644 --- a/benches/helpers/mod.rs +++ b/benches/helpers/mod.rs @@ -2,6 +2,7 @@ pub mod yoga_helpers; /// A helper function to recursively construct a deep tree +#[allow(dead_code)] pub fn build_deep_tree( tree: &mut T, max_nodes: u32, diff --git a/benches/helpers/yoga_helpers.rs b/benches/helpers/yoga_helpers.rs index 165ebdfea..787ea569e 100644 --- a/benches/helpers/yoga_helpers.rs +++ b/benches/helpers/yoga_helpers.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use slotmap::{DefaultKey, SlotMap}; pub mod yg { @@ -12,6 +13,17 @@ mod tf { pub use taffy::prelude::*; } +pub fn new_default_style_with_children( + tree: &mut SlotMap, + children: Vec, +) -> DefaultKey { + let mut node = yg::Node::new(); + for (i, child) in children.into_iter().enumerate() { + node.insert_child(&mut tree[child], i as u32); + } + tree.insert(node) +} + pub fn new_with_children( tree: &mut SlotMap, style: &tf::Style, diff --git a/benches/tree_creation.rs b/benches/tree_creation.rs new file mode 100644 index 000000000..10ce6a898 --- /dev/null +++ b/benches/tree_creation.rs @@ -0,0 +1,99 @@ +//! This file includes benchmarks for tree creation +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use rand::prelude::*; +use rand_chacha::ChaCha8Rng; +use taffy::prelude::*; +use taffy::style::Style; + +mod helpers; + +#[cfg(feature = "yoga_benchmark")] +use helpers::yoga_helpers; +#[cfg(feature = "yoga_benchmark")] +use slotmap::SlotMap; +#[cfg(feature = "yoga_benchmark")] +use yoga_helpers::yg; + +/// Build a random leaf node +fn build_random_leaf(taffy: &mut Taffy) -> Node { + taffy.new_with_children(Style::DEFAULT, &[]).unwrap() +} + +/// A tree with many children that have shallow depth +fn build_taffy_flat_hierarchy(total_node_count: u32, use_with_capacity: bool) -> (Taffy, Node) { + let mut taffy = if use_with_capacity { Taffy::with_capacity(total_node_count as usize) } else { Taffy::new() }; + let mut rng = ChaCha8Rng::seed_from_u64(12345); + let mut children = Vec::new(); + let mut node_count = 0; + + while node_count < total_node_count { + let sub_children_count = rng.gen_range(1..=4); + let sub_children: Vec = (0..sub_children_count).map(|_| build_random_leaf(&mut taffy)).collect(); + let node = taffy.new_with_children(Style::DEFAULT, &sub_children).unwrap(); + + children.push(node); + node_count += 1 + sub_children_count; + } + + let root = taffy.new_with_children(Style::DEFAULT, children.as_slice()).unwrap(); + (taffy, root) +} + +#[cfg(feature = "yoga_benchmark")] +/// A tree with many children that have shallow depth +fn build_yoga_flat_hierarchy(total_node_count: u32) -> (yg::YogaTree, Node) { + let mut tree = SlotMap::new(); + let mut rng = ChaCha8Rng::seed_from_u64(12345); + let mut children = Vec::new(); + let mut node_count = 0; + + while node_count < total_node_count { + let sub_children_count = rng.gen_range(1..=4); + let sub_children: Vec = + (0..sub_children_count).map(|_| yoga_helpers::new_default_style_with_children(&mut tree, vec![])).collect(); + let node = yoga_helpers::new_default_style_with_children(&mut tree, sub_children); + + children.push(node); + node_count += 1 + sub_children_count; + } + + let root = yoga_helpers::new_default_style_with_children(&mut tree, children); + (tree, root) +} + +fn taffy_benchmarks(c: &mut Criterion) { + let mut group = c.benchmark_group("Tree creation"); + for node_count in [1_000u32, 10_000, 100_000].iter() { + #[cfg(feature = "yoga_benchmark")] + let benchmark_id = BenchmarkId::new(format!("Yoga"), node_count); + #[cfg(feature = "yoga_benchmark")] + group.bench_with_input(benchmark_id, node_count, |b, &node_count| { + b.iter(|| { + let (taffy, root) = build_yoga_flat_hierarchy(node_count); + std::hint::black_box(taffy); + std::hint::black_box(root); + }) + }); + let benchmark_id = BenchmarkId::new(format!("Taffy::new"), node_count); + group.bench_with_input(benchmark_id, node_count, |b, &node_count| { + b.iter(|| { + let (tree, root) = build_taffy_flat_hierarchy(node_count, false); + std::hint::black_box(tree); + std::hint::black_box(root); + }) + }); + + let benchmark_id = BenchmarkId::new(format!("Taffy::with_capacity"), node_count); + group.bench_with_input(benchmark_id, node_count, |b, &node_count| { + b.iter(|| { + let (tree, root) = build_taffy_flat_hierarchy(node_count, true); + std::hint::black_box(tree); + std::hint::black_box(root); + }) + }); + } + group.finish(); +} + +criterion_group!(benches, taffy_benchmarks); +criterion_main!(benches); diff --git a/deny.toml b/deny.toml index 1283ab103..43d6315bc 100644 --- a/deny.toml +++ b/deny.toml @@ -35,7 +35,11 @@ skip = [ # This dependency won't actually end up in the final binary anyway as it a sub-dependency # of num-cpus and atty only when targetting the hermit unikernel OS # (https://github.com/hermitcore/rusty-hermit) - { name = "hermit-abi" } + { name = "hermit-abi" }, + + # Long-term we'll want to re-ban this. However it's going to take a while for the ecosystem to + # transition over to syn 2 and we don't want to block Taffy releases in the meantime. + { name = "syn" }, ] [sources] diff --git a/scripts/gentest/Cargo.toml b/scripts/gentest/Cargo.toml index 6669b24c4..f71b9aaa6 100644 --- a/scripts/gentest/Cargo.toml +++ b/scripts/gentest/Cargo.toml @@ -12,5 +12,5 @@ log = "0.4" proc-macro2 = "1.0.6" quote = "1.0.2" serde_json = "1" -syn = "1.0.7" +syn = "2.0.4" tokio = { version = "1.18", features = ["full"] } diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs index 9aa125a5a..c72416232 100644 --- a/src/compute/flexbox.rs +++ b/src/compute/flexbox.rs @@ -76,6 +76,8 @@ struct FlexItem { inset: Rect>, /// The margin of this item margin: Rect, + /// Whether each margin is an auto margin or not + margin_is_auto: Rect, /// The padding of this item padding: Rect, /// The border of this item @@ -141,6 +143,10 @@ struct AlgoConstants { /// Is the wrap direction inverted is_wrap_reverse: bool, + /// The item's min_size style + min_size: Size>, + /// The item's max_size style + max_size: Size>, /// The margin of this section margin: Rect, /// The border of this section @@ -153,6 +159,8 @@ struct AlgoConstants { align_items: AlignItems, /// The align_content property of this node align_content: AlignContent, + /// The justify_content property of this node + justify_content: Option, /// The border-box size of the node being laid out (if known) node_outer_size: Size>, @@ -175,10 +183,6 @@ pub fn compute( run_mode: RunMode, ) -> SizeAndBaselines { let style = tree.style(node); - let has_min_max_sizes = style.min_size.width.is_defined() - || style.min_size.height.is_defined() - || style.max_size.width.is_defined() - || style.max_size.height.is_defined(); // Pull these out earlier to avoid borrowing issues let aspect_ratio = style.aspect_ratio; @@ -202,35 +206,9 @@ pub fn compute( } } - if styled_based_known_dimensions.both_axis_defined() || !has_min_max_sizes { - #[cfg(feature = "debug")] - NODE_LOGGER.log("FLEX: single-pass"); - compute_preliminary(tree, node, styled_based_known_dimensions, parent_size, available_space, run_mode) - } else { - #[cfg(feature = "debug")] - NODE_LOGGER.log("FLEX: two-pass"); - let first_pass = compute_preliminary( - tree, - node, - styled_based_known_dimensions, - parent_size, - available_space, - RunMode::ComputeSize, - ) - .size; - - let clamped_first_pass_size = first_pass.maybe_clamp(min_size, max_size); - - compute_preliminary( - tree, - node, - styled_based_known_dimensions - .zip_map(clamped_first_pass_size, |known, first_pass| known.or_else(|| first_pass.into())), - parent_size, - available_space, - run_mode, - ) - } + #[cfg(feature = "debug")] + NODE_LOGGER.log("FLEX: single-pass"); + compute_preliminary(tree, node, styled_based_known_dimensions, parent_size, available_space, run_mode) } /// Compute a preliminary size for an item @@ -283,7 +261,7 @@ fn compute_preliminary( // 5. Collect flex items into flex lines. #[cfg(feature = "debug")] NODE_LOGGER.log("collect_flex_lines"); - let mut flex_lines = collect_flex_lines(tree, node, &constants, available_space, &mut flex_items); + let mut flex_lines = collect_flex_lines(&constants, available_space, &mut flex_items); // If container size is undefined, determine the container's main size // and then re-resolve gaps based on newly determined size @@ -309,7 +287,7 @@ fn compute_preliminary( #[cfg(feature = "debug")] NODE_LOGGER.log("resolve_flexible_lengths"); for line in &mut flex_lines { - resolve_flexible_lengths(tree, line, &constants, original_gap); + resolve_flexible_lengths(line, &constants, original_gap); } // 9.4. Cross Size Determination @@ -330,7 +308,7 @@ fn compute_preliminary( // 8. Calculate the cross size of each flex line. #[cfg(feature = "debug")] NODE_LOGGER.log("calculate_cross_size"); - calculate_cross_size(tree, &mut flex_lines, known_dimensions, &constants); + calculate_cross_size(&mut flex_lines, known_dimensions, &constants); // 9. Handle 'align-content: stretch'. #[cfg(feature = "debug")] @@ -362,14 +340,14 @@ fn compute_preliminary( // 12. Distribute any remaining free space. #[cfg(feature = "debug")] NODE_LOGGER.log("distribute_remaining_free_space"); - distribute_remaining_free_space(tree, &mut flex_lines, node, &constants); + distribute_remaining_free_space(&mut flex_lines, &constants); // 9.6. Cross-Axis Alignment // 13. Resolve cross-axis auto margins (also includes 14). #[cfg(feature = "debug")] NODE_LOGGER.log("resolve_cross_axis_auto_margins"); - resolve_cross_axis_auto_margins(tree, &mut flex_lines, &constants); + resolve_cross_axis_auto_margins(&mut flex_lines, &constants); // 15. Determine the flex container’s used cross size. #[cfg(feature = "debug")] @@ -385,7 +363,7 @@ fn compute_preliminary( // 16. Align all flex lines per align-content. #[cfg(feature = "debug")] NODE_LOGGER.log("align_flex_lines_per_align_content"); - align_flex_lines_per_align_content(tree, &mut flex_lines, node, &constants, total_line_cross_size); + align_flex_lines_per_align_content(&mut flex_lines, &constants, total_line_cross_size); // Do a final layout pass and gather the resulting layouts #[cfg(feature = "debug")] @@ -403,8 +381,8 @@ fn compute_preliminary( for order in 0..len { let child = tree.child(node, order); if tree.style(child).display == Display::None { - *tree.layout_mut(node) = Layout::with_order(order as u32); - GenericAlgorithm::measure_size( + *tree.layout_mut(child) = Layout::with_order(order as u32); + GenericAlgorithm::perform_layout( tree, child, Size::NONE, @@ -447,19 +425,18 @@ fn compute_constants( let is_wrap = matches!(style.flex_wrap, FlexWrap::Wrap | FlexWrap::WrapReverse); let is_wrap_reverse = style.flex_wrap == FlexWrap::WrapReverse; + let aspect_ratio = style.aspect_ratio; let margin = style.margin.resolve_or_zero(parent_size.width); let padding = style.padding.resolve_or_zero(parent_size.width); let border = style.border.resolve_or_zero(parent_size.width); - let align_items = style.align_items.unwrap_or(crate::style::AlignItems::Stretch); - let align_content = style.align_content.unwrap_or(crate::style::AlignContent::Stretch); + let align_items = style.align_items.unwrap_or(AlignItems::Stretch); + let align_content = style.align_content.unwrap_or(AlignContent::Stretch); + let justify_content = style.justify_content; let padding_border = padding + border; let node_outer_size = known_dimensions; - let node_inner_size = Size { - width: node_outer_size.width.maybe_sub(padding_border.horizontal_axis_sum()), - height: node_outer_size.height.maybe_sub(padding_border.vertical_axis_sum()), - }; + let node_inner_size = node_outer_size.maybe_sub(padding_border.sum_axes()); let gap = style.gap.resolve_or_zero(node_inner_size.or(Size::zero())); let container_size = Size::zero(); @@ -471,12 +448,15 @@ fn compute_constants( is_column, is_wrap, is_wrap_reverse, + min_size: style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio), + max_size: style.max_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio), margin, border, gap, padding_border, align_items, align_content, + justify_content, node_outer_size, node_inner_size, container_size, @@ -511,6 +491,7 @@ fn generate_anonymous_flex_items(tree: &impl LayoutTree, node: Node, constants: inset: child_style.inset.zip_size(constants.node_inner_size, |p, s| p.maybe_resolve(s)), margin: child_style.margin.resolve_or_zero(constants.node_inner_size.width), + margin_is_auto: child_style.margin.map(|m| m == LengthPercentageAuto::Auto), padding: child_style.padding.resolve_or_zero(constants.node_inner_size.width), border: child_style.border.resolve_or_zero(constants.node_inner_size.width), align_self: child_style.align_self.unwrap_or(constants.align_items), @@ -605,107 +586,143 @@ fn determine_flex_base_size( tree: &mut impl LayoutTree, constants: &AlgoConstants, available_space: Size, - flex_items: &mut Vec, + flex_items: &mut [FlexItem], ) { + let dir = constants.dir; + for child in flex_items.iter_mut() { let child_style = tree.style(child.node); - // A. If the item has a definite used flex basis, that’s the flex base size. + // Parent size for child sizing + let cross_axis_parent_size = constants.node_inner_size.cross(dir); - // B. If the flex item has an intrinsic aspect ratio, - // a used flex basis of content, and a definite cross size, - // then the flex base size is calculated from its inner - // cross size and the flex item’s intrinsic aspect ratio. + // Available space for child sizing + let cross_axis_margin_sum = constants.margin.cross_axis_sum(dir); + let child_min_cross = child.min_size.cross(dir).maybe_add(cross_axis_margin_sum); + let child_max_cross = child.max_size.cross(dir).maybe_add(cross_axis_margin_sum); + let cross_axis_available_space = cross_axis_parent_size.maybe_clamp(child_min_cross, child_max_cross).into(); - // Note: `child.size` has already been resolved against aspect_ratio in generate_anonymous_flex_items - // So B will just work here by using main_size without special handling for aspect_ratio + child.flex_basis = 'flex_basis: { + // A. If the item has a definite used flex basis, that’s the flex base size. - let flex_basis = child_style.flex_basis.maybe_resolve(constants.node_inner_size.main(constants.dir)); - let main_size = child.size.main(constants.dir); - if let Some(flex_basis) = flex_basis.or(main_size) { - child.flex_basis = flex_basis; - continue; - }; + // B. If the flex item has an intrinsic aspect ratio, + // a used flex basis of content, and a definite cross size, + // then the flex base size is calculated from its inner + // cross size and the flex item’s intrinsic aspect ratio. - // C. If the used flex basis is content or depends on its available space, - // and the flex container is being sized under a min-content or max-content - // constraint (e.g. when performing automatic table layout [CSS21]), - // size the item under that constraint. The flex base size is the item’s - // resulting main size. - - // This is covered by the implementation of E below, which passes the available_space constraint - // through to the child size computation. It may need a separate implementation if/when D is implemented. - - // D. Otherwise, if the used flex basis is content or depends on its - // available space, the available main size is infinite, and the flex item’s - // inline axis is parallel to the main axis, lay the item out using the rules - // for a box in an orthogonal flow [CSS3-WRITING-MODES]. The flex base size - // is the item’s max-content main size. - - // TODO if/when vertical writing modes are supported - - // E. Otherwise, size the item into the available space using its used flex basis - // in place of its main size, treating a value of content as max-content. - // If a cross size is needed to determine the main size (e.g. when the - // flex item’s main size is in its block axis) and the flex item’s cross size - // is auto and not definite, in this calculation use fit-content as the - // flex item’s cross size. The flex base size is the item’s resulting main size. - - let child_known_dimensions = { - let mut ckd = child.size; - if child.align_self == AlignSelf::Stretch && ckd.cross(constants.dir).is_none() { - ckd.set_cross( - constants.dir, - available_space - .cross(constants.dir) - .into_option() - .maybe_sub(constants.margin.cross_axis_sum(constants.dir)), - ); - } - ckd + // Note: `child.size` has already been resolved against aspect_ratio in generate_anonymous_flex_items + // So B will just work here by using main_size without special handling for aspect_ratio + + let flex_basis = child_style.flex_basis.maybe_resolve(constants.node_inner_size.main(dir)); + let main_size = child.size.main(dir); + if let Some(flex_basis) = flex_basis.or(main_size) { + break 'flex_basis flex_basis; + }; + + // C. If the used flex basis is content or depends on its available space, + // and the flex container is being sized under a min-content or max-content + // constraint (e.g. when performing automatic table layout [CSS21]), + // size the item under that constraint. The flex base size is the item’s + // resulting main size. + + // This is covered by the implementation of E below, which passes the available_space constraint + // through to the child size computation. It may need a separate implementation if/when D is implemented. + + // D. Otherwise, if the used flex basis is content or depends on its + // available space, the available main size is infinite, and the flex item’s + // inline axis is parallel to the main axis, lay the item out using the rules + // for a box in an orthogonal flow [CSS3-WRITING-MODES]. The flex base size + // is the item’s max-content main size. + + // TODO if/when vertical writing modes are supported + + // E. Otherwise, size the item into the available space using its used flex basis + // in place of its main size, treating a value of content as max-content. + // If a cross size is needed to determine the main size (e.g. when the + // flex item’s main size is in its block axis) and the flex item’s cross size + // is auto and not definite, in this calculation use fit-content as the + // flex item’s cross size. The flex base size is the item’s resulting main size. + + let child_parent_size = Size::NONE.with_cross(dir, cross_axis_parent_size); + let child_available_space = available_space.with_cross(dir, cross_axis_available_space); + + let child_known_dimensions = { + let mut ckd = child.size; + if child.align_self == AlignSelf::Stretch && ckd.cross(dir).is_none() { + ckd.set_cross( + dir, + child_available_space + .cross(dir) + .into_option() + .maybe_clamp(child_min_cross, child_max_cross) + .maybe_sub(constants.margin.cross_axis_sum(dir)), + ); + } + ckd + }; + + break 'flex_basis GenericAlgorithm::measure_size( + tree, + child.node, + child_known_dimensions, + child_parent_size, + child_available_space, + SizingMode::ContentSize, + ) + .main(dir); }; - child.flex_basis = GenericAlgorithm::measure_size( - tree, - child.node, - child_known_dimensions, - constants.node_inner_size, - available_space, - SizingMode::ContentSize, - ) - .main(constants.dir); - } + // Floor flex-basis by the padding_border_sum (floors inner_flex_basis at zero) + // This seems to be in violation of the spec which explicitly states that the content box should not be floored at zero + // (like it usually is) when calculating the flex-basis. But including this matches both Chrome and Firefox's behaviour. + // + // TODO: resolve spec violation + // Spec: https://www.w3.org/TR/css-flexbox-1/#intrinsic-item-contributions + // Spec: https://www.w3.org/TR/css-flexbox-1/#change-2016-max-contribution + let padding_border_sum = child.padding.main_axis_sum(constants.dir) + child.border.main_axis_sum(constants.dir); + child.flex_basis = child.flex_basis.max(padding_border_sum); - // The hypothetical main size is the item’s flex base size clamped according to its - // used min and max main sizes (and flooring the content box size at zero). + // The hypothetical main size is the item’s flex base size clamped according to its + // used min and max main sizes (and flooring the content box size at zero). - for child in flex_items { child.inner_flex_basis = child.flex_basis - child.padding.main_axis_sum(constants.dir) - child.border.main_axis_sum(constants.dir); - let hypothetical_inner_min_main = child.min_size.main(constants.dir); - child.hypothetical_inner_size.set_main( - constants.dir, - child.flex_basis.maybe_clamp(hypothetical_inner_min_main, child.max_size.main(constants.dir)), - ); - child.hypothetical_outer_size.set_main( - constants.dir, - child.hypothetical_inner_size.main(constants.dir) + child.margin.main_axis_sum(constants.dir), - ); + let padding_border_axes_sums = (child.padding + child.border).sum_axes().map(Some); + let hypothetical_inner_min_main = + child.min_size.main(constants.dir).maybe_max(padding_border_axes_sums.main(constants.dir)); + let hypothetical_inner_size = + child.flex_basis.maybe_clamp(hypothetical_inner_min_main, child.max_size.main(constants.dir)); + let hypothetical_outer_size = hypothetical_inner_size + child.margin.main_axis_sum(constants.dir); + + child.hypothetical_inner_size.set_main(constants.dir, hypothetical_inner_size); + child.hypothetical_outer_size.set_main(constants.dir, hypothetical_outer_size); + + // Note that it is important that the `parent_size` parameter in the main axis is not set for this + // function call as it used for resolving percentages, and percentage size in an axis should not contribute + // to a min-content contribution in that same axis. However the `parent_size` and `available_space` *should* + // be set to their usual values in the cross axis so that wrapping content can wrap correctly. + // + // See https://drafts.csswg.org/css-sizing-3/#min-percentage-contribution + let min_content_size = { + let child_parent_size = Size::NONE.with_cross(dir, cross_axis_parent_size); + let child_available_space = Size::MIN_CONTENT.with_cross(dir, cross_axis_available_space); - let min_content_size = GenericAlgorithm::measure_size( - tree, - child.node, - Size::NONE, - constants.node_inner_size, - Size::MIN_CONTENT, - SizingMode::ContentSize, - ); + GenericAlgorithm::measure_size( + tree, + child.node, + Size::NONE, + child_parent_size, + child_available_space, + SizingMode::ContentSize, + ) + }; // 4.5. Automatic Minimum Size of Flex Items // https://www.w3.org/TR/css-flexbox-1/#min-size-auto let clamped_min_content_size = min_content_size.maybe_min(child.size).maybe_min(child.max_size); - child.resolved_minimum_size = child.min_size.unwrap_or(clamped_min_content_size); + child.resolved_minimum_size = + child.min_size.unwrap_or(clamped_min_content_size).maybe_max(padding_border_axes_sums); } } @@ -728,13 +745,11 @@ fn determine_flex_base_size( /// **Note that the "collect as many" line will collect zero-sized flex items onto the end of the previous line even if the last non-zero item exactly "filled up" the line**. #[inline] fn collect_flex_lines<'a>( - tree: &impl LayoutTree, - node: Node, constants: &AlgoConstants, available_space: Size, flex_items: &'a mut Vec, ) -> Vec> { - if tree.style(node).flex_wrap == FlexWrap::NoWrap { + if !constants.is_wrap { let mut lines = new_vec_with_capacity(1); lines.push(FlexLine { items: flex_items.as_mut_slice(), cross_size: 0.0, offset_cross: 0.0 }); lines @@ -798,6 +813,8 @@ fn determine_container_main_size( lines: &mut Vec>, constants: &mut AlgoConstants, ) { + let main_padding_border = constants.padding_border.main_axis_sum(constants.dir); + let outer_main_size: f32 = constants.node_outer_size.main(constants.dir).unwrap_or_else(|| { match main_axis_available_space { AvailableSpace::Definite(main_axis_available_space) => { @@ -808,13 +825,16 @@ fn determine_container_main_size( let total_target_size = line .items .iter() - .map(|child| child.flex_basis + child.margin.main_axis_sum(constants.dir)) + .map(|child| { + let padding_border_sum = (child.padding + child.border).main_axis_sum(constants.dir); + (child.flex_basis + child.margin.main_axis_sum(constants.dir)).max(padding_border_sum) + }) .sum::(); total_target_size + line_main_axis_gap }) .max_by(|a, b| a.total_cmp(b)) .unwrap_or(0.0); - let size = longest_line_length + constants.padding_border.main_axis_sum(constants.dir); + let size = longest_line_length + main_padding_border; if lines.len() > 1 { f32_max(size, main_axis_available_space) } else { @@ -829,13 +849,16 @@ fn determine_container_main_size( let total_target_size = line .items .iter() - .map(|child| child.flex_basis + child.margin.main_axis_sum(constants.dir)) + .map(|child| { + let padding_border_sum = (child.padding + child.border).main_axis_sum(constants.dir); + (child.flex_basis + child.margin.main_axis_sum(constants.dir)).max(padding_border_sum) + }) .sum::(); total_target_size + line_main_axis_gap }) .max_by(|a, b| a.total_cmp(b)) .unwrap_or(0.0); - longest_line_length + constants.padding_border.main_axis_sum(constants.dir) + longest_line_length + main_padding_border } AvailableSpace::MinContent | AvailableSpace::MaxContent => { // Define a base main_size variable. This is mutated once for iteration over the outer @@ -848,23 +871,39 @@ fn determine_container_main_size( let style_min = item.min_size.main(constants.dir); let style_preferred = item.size.main(constants.dir); let style_max = item.max_size.main(constants.dir); - let flex_basis_min = Some(item.flex_basis).filter(|_| item.flex_shrink == 0.0); - let flex_basis_max = Some(item.flex_basis).filter(|_| item.flex_grow == 0.0); - let min_main_size = style_min.maybe_max(flex_basis_min).or(flex_basis_min); - let max_main_size = style_max.maybe_min(flex_basis_max).or(flex_basis_max); + + // The spec seems a bit unclear on this point (my initial reading was that the `.maybe_max(style_preferred)` should + // not be included here), however this matches both Chrome and Firefox as of 9th March 2023. + // + // Spec: https://www.w3.org/TR/css-flexbox-1/#intrinsic-item-contributions + // Spec modifcation: https://www.w3.org/TR/css-flexbox-1/#change-2016-max-contribution + // Issue: https://github.com/w3c/csswg-drafts/issues/1435 + // Gentest: padding_border_overrides_size_flex_basis_0.html + let clamping_basis = Some(item.flex_basis).maybe_max(style_preferred); + let flex_basis_min = clamping_basis.filter(|_| item.flex_shrink == 0.0); + let flex_basis_max = clamping_basis.filter(|_| item.flex_grow == 0.0); + + let resolved_min = item.resolved_minimum_size.main(constants.dir); + let min_main_size = style_min + .maybe_max(flex_basis_min) + .or(flex_basis_min) + .unwrap_or(resolved_min) + .max(resolved_min); + let max_main_size = + style_max.maybe_min(flex_basis_max).or(flex_basis_max).unwrap_or(f32::INFINITY); let content_contribution = match (min_main_size, style_preferred, max_main_size) { // If the clamping values are such that max <= min, then we can avoid the expensive step of computing the content size // as we know that the clamping values will override it anyway - (Some(min), Some(pref), Some(max)) if max <= min || max <= pref => { + (min, Some(pref), max) if max <= min || max <= pref => { pref.min(max).max(min) + item.margin.main_axis_sum(constants.dir) } - (Some(min), _, Some(max)) if max <= min => min + item.margin.main_axis_sum(constants.dir), - (_, Some(pref), Some(max)) if max <= pref => max + item.margin.main_axis_sum(constants.dir), + (min, _, max) if max <= min => min + item.margin.main_axis_sum(constants.dir), // Else compute the min- or -max content size and apply the full formula for computing the // min- or max- content contributuon _ => { // Either the min- or max- content size depending on which constraint we are sizing under. + // TODO: Optimise by using already computed values where available let content_main_size = GenericAlgorithm::measure_size( tree, item.node, @@ -889,9 +928,12 @@ fn determine_container_main_size( // Ultimately, this was not found by reading the spec, but by trial and error fixing tests to align with Webkit/Firefox output. // (see the `flex_basis_unconstraint_row` and `flex_basis_uncontraint_column` generated tests which demonstrate this) if constants.is_row { - content_main_size.maybe_clamp(style_min, style_max) + content_main_size.maybe_clamp(style_min, style_max).max(main_padding_border) } else { - content_main_size.max(item.flex_basis).maybe_clamp(style_min, style_max) + content_main_size + .max(item.flex_basis) + .maybe_clamp(style_min, style_max) + .max(main_padding_border) } } }; @@ -900,8 +942,7 @@ fn determine_container_main_size( if diff > 0.0 { diff / f32_max(1.0, item.flex_grow) } else if diff < 0.0 { - let scaled_shrink_factor = f32_max(1.0, item.flex_shrink) * item.inner_flex_basis; - // let scaled_shrink_factor - f32_max(1.0, item.flex_shrink * item.inner_flex_basis); + let scaled_shrink_factor = f32_max(1.0, item.flex_shrink * item.inner_flex_basis); diff / scaled_shrink_factor } else { // We are assuming that diff is 0.0 here and that we haven't accidentally introduced a NaN @@ -953,10 +994,15 @@ fn determine_container_main_size( main_size = f32_max(main_size, item_main_size_sum + gap_sum) } - main_size + constants.padding_border.main_axis_sum(constants.dir) + main_size + main_padding_border } } }); + + let outer_main_size = outer_main_size + .maybe_clamp(constants.min_size.main(constants.dir), constants.max_size.main(constants.dir)) + .max(main_padding_border); + // let outer_main_size = inner_main_size + constants.padding_border.main_axis_sum(constants.dir); let inner_main_size = outer_main_size - constants.padding_border.main_axis_sum(constants.dir); constants.container_size.set_main(constants.dir, outer_main_size); @@ -969,12 +1015,7 @@ fn determine_container_main_size( /// /// # [9.7. Resolving Flexible Lengths](https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) #[inline] -fn resolve_flexible_lengths( - tree: &mut impl LayoutTree, - line: &mut FlexLine, - constants: &AlgoConstants, - original_gap: Size, -) { +fn resolve_flexible_lengths(line: &mut FlexLine, constants: &AlgoConstants, original_gap: Size) { let total_original_main_axis_gap = sum_axis_gaps(original_gap.main(constants.dir), line.items.len()); let total_main_axis_gap = sum_axis_gaps(constants.gap.main(constants.dir), line.items.len()); @@ -1000,8 +1041,7 @@ fn resolve_flexible_lengths( let inner_target_size = child.hypothetical_inner_size.main(constants.dir); child.target_size.set_main(constants.dir, inner_target_size); - let child_style = tree.style(child.node); - if (child_style.flex_grow == 0.0 && child_style.flex_shrink == 0.0) + if (child.flex_grow == 0.0 && child.flex_shrink == 0.0) || (growing && child.flex_basis > child.hypothetical_inner_size.main(constants.dir)) || (shrinking && child.flex_basis < child.hypothetical_inner_size.main(constants.dir)) { @@ -1057,8 +1097,7 @@ fn resolve_flexible_lengths( let (sum_flex_grow, sum_flex_shrink): (f32, f32) = unfrozen.iter().fold((0.0, 0.0), |(flex_grow, flex_shrink), item| { - let style = tree.style(item.node); - (flex_grow + style.flex_grow, flex_shrink + style.flex_shrink) + (flex_grow + item.flex_grow, flex_shrink + item.flex_shrink) }); let free_space = if growing && sum_flex_grow < 1.0 { @@ -1094,18 +1133,17 @@ fn resolve_flexible_lengths( if free_space.is_normal() { if growing && sum_flex_grow > 0.0 { for child in &mut unfrozen { - child.target_size.set_main( - constants.dir, - child.flex_basis + free_space * (tree.style(child.node).flex_grow / sum_flex_grow), - ); + child + .target_size + .set_main(constants.dir, child.flex_basis + free_space * (child.flex_grow / sum_flex_grow)); } } else if shrinking && sum_flex_shrink > 0.0 { let sum_scaled_shrink_factor: f32 = - unfrozen.iter().map(|child| child.inner_flex_basis * tree.style(child.node).flex_shrink).sum(); + unfrozen.iter().map(|child| child.inner_flex_basis * child.flex_shrink).sum(); if sum_scaled_shrink_factor > 0.0 { for child in &mut unfrozen { - let scaled_shrink_factor = child.inner_flex_basis * tree.style(child.node).flex_shrink; + let scaled_shrink_factor = child.inner_flex_basis * child.flex_shrink; child.target_size.set_main( constants.dir, child.flex_basis + free_space * (scaled_shrink_factor / sum_scaled_shrink_factor), @@ -1169,13 +1207,22 @@ fn determine_hypothetical_cross_size( available_space: Size, ) { for child in line.items.iter_mut() { + let padding_border_sum = (child.padding + child.border).cross_axis_sum(constants.dir); + + let child_known_main = constants.container_size.main(constants.dir).into(); + let child_cross = child .size .cross(constants.dir) - .maybe_clamp(child.min_size.cross(constants.dir), child.max_size.cross(constants.dir)); + .maybe_clamp(child.min_size.cross(constants.dir), child.max_size.cross(constants.dir)) + .maybe_max(padding_border_sum); - child.hypothetical_inner_size.set_cross( - constants.dir, + let child_available_cross = available_space + .cross(constants.dir) + .maybe_clamp(child.min_size.cross(constants.dir), child.max_size.cross(constants.dir)) + .maybe_max(padding_border_sum); + + let child_inner_cross = child_cross.unwrap_or_else(|| { GenericAlgorithm::measure_size( tree, child.node, @@ -1185,27 +1232,19 @@ fn determine_hypothetical_cross_size( }, constants.node_inner_size, Size { - width: if constants.is_row { - constants.container_size.main(constants.dir).into() - } else { - available_space.width - }, - height: if constants.is_row { - available_space.height - } else { - constants.container_size.main(constants.dir).into() - }, + width: if constants.is_row { child_known_main } else { child_available_cross }, + height: if constants.is_row { child_available_cross } else { child_known_main }, }, SizingMode::ContentSize, ) .cross(constants.dir) - .maybe_clamp(child.min_size.cross(constants.dir), child.max_size.cross(constants.dir)), - ); + .maybe_clamp(child.min_size.cross(constants.dir), child.max_size.cross(constants.dir)) + .max(padding_border_sum) + }); + let child_outer_cross = child_inner_cross + child.margin.cross_axis_sum(constants.dir); - child.hypothetical_outer_size.set_cross( - constants.dir, - child.hypothetical_inner_size.cross(constants.dir) + child.margin.cross_axis_sum(constants.dir), - ); + child.hypothetical_inner_size.set_cross(constants.dir, child_inner_cross); + child.hypothetical_outer_size.set_cross(constants.dir, child_outer_cross); } } @@ -1299,24 +1338,27 @@ fn calculate_children_base_lines( /// If the flex container is single-line, then clamp the line’s cross-size to be within the container’s computed min and max cross sizes. /// **Note that if CSS 2.1’s definition of min/max-width/height applied more generally, this behavior would fall out automatically**. #[inline] -fn calculate_cross_size( - tree: &mut impl LayoutTree, - flex_lines: &mut [FlexLine], - node_size: Size>, - constants: &AlgoConstants, -) { +fn calculate_cross_size(flex_lines: &mut [FlexLine], node_size: Size>, constants: &AlgoConstants) { // Note: AlignContent::SpaceEvenly and AlignContent::SpaceAround behave like AlignContent::Stretch when there is only // a single flex line in the container. See: https://www.w3.org/TR/css-flexbox-1/#align-content-property + // Also: align_content is ignored entirely (and thus behaves like Stretch) when `flex_wrap` is set to `nowrap`. if flex_lines.len() == 1 && node_size.cross(constants.dir).is_some() - && matches!( - constants.align_content, - AlignContent::Stretch | AlignContent::SpaceEvenly | AlignContent::SpaceAround - ) + && (!constants.is_wrap + || matches!( + constants.align_content, + AlignContent::Stretch | AlignContent::SpaceEvenly | AlignContent::SpaceAround + )) { - flex_lines[0].cross_size = - (node_size.cross(constants.dir).maybe_sub(constants.padding_border.cross_axis_sum(constants.dir))) - .unwrap_or(0.0); + let cross_axis_padding_border = constants.padding_border.cross_axis_sum(constants.dir); + let cross_min_size = constants.min_size.cross(constants.dir); + let cross_max_size = constants.max_size.cross(constants.dir); + flex_lines[0].cross_size = node_size + .cross(constants.dir) + .maybe_clamp(cross_min_size, cross_max_size) + .maybe_sub(cross_axis_padding_border) + .maybe_max(0.0) + .unwrap_or(0.0); } else { for line in flex_lines.iter_mut() { // 1. Collect all the flex items whose inline-axis is parallel to the main-axis, whose @@ -1336,10 +1378,9 @@ fn calculate_cross_size( .items .iter() .map(|child| { - let child_style = tree.style(child.node); 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.margin_is_auto.cross_start(constants.dir) + && !child.margin_is_auto.cross_end(constants.dir) { max_baseline - child.baseline + child.hypothetical_outer_size.cross(constants.dir) } else { @@ -1360,15 +1401,23 @@ fn calculate_cross_size( /// increase the cross size of each flex line by equal amounts such that the sum of their cross sizes exactly equals the flex container’s inner cross size. #[inline] fn handle_align_content_stretch(flex_lines: &mut [FlexLine], node_size: Size>, constants: &AlgoConstants) { - if constants.align_content == AlignContent::Stretch && node_size.cross(constants.dir).is_some() { + if constants.align_content == AlignContent::Stretch { + let cross_axis_padding_border = constants.padding_border.cross_axis_sum(constants.dir); + let cross_min_size = constants.min_size.cross(constants.dir); + let cross_max_size = constants.max_size.cross(constants.dir); + let container_min_inner_cross = node_size + .cross(constants.dir) + .or(cross_min_size) + .maybe_clamp(cross_min_size, cross_max_size) + .maybe_sub(cross_axis_padding_border) + .maybe_max(0.0) + .unwrap_or(0.0); + let total_cross_axis_gap = sum_axis_gaps(constants.gap.cross(constants.dir), flex_lines.len()); - let total_cross: f32 = flex_lines.iter().map(|line| line.cross_size).sum::() + total_cross_axis_gap; - let inner_cross = - (node_size.cross(constants.dir).maybe_sub(constants.padding_border.cross_axis_sum(constants.dir))) - .unwrap_or(0.0); + let lines_total_cross: f32 = flex_lines.iter().map(|line| line.cross_size).sum::() + total_cross_axis_gap; - if total_cross < inner_cross { - let remaining = inner_cross - total_cross; + if lines_total_cross < container_min_inner_cross { + let remaining = container_min_inner_cross - lines_total_cross; let addition = remaining / flex_lines.len() as f32; flex_lines.iter_mut().for_each(|line| line.cross_size += addition); } @@ -1396,8 +1445,8 @@ fn determine_used_cross_size(tree: &mut impl LayoutTree, flex_lines: &mut [FlexL child.target_size.set_cross( constants.dir, if child.align_self == AlignSelf::Stretch - && child_style.margin.cross_start(constants.dir) != LengthPercentageAuto::Auto - && child_style.margin.cross_end(constants.dir) != LengthPercentageAuto::Auto + && !child.margin_is_auto.cross_start(constants.dir) + && !child.margin_is_auto.cross_end(constants.dir) && child_style.size.cross(constants.dir) == Dimension::Auto { // For some reason this particular usage of max_width is an exception to the rule that max_width's transfer @@ -1433,12 +1482,7 @@ fn determine_used_cross_size(tree: &mut impl LayoutTree, flex_lines: &mut [FlexL /// /// 2. Align the items along the main-axis per `justify-content`. #[inline] -fn distribute_remaining_free_space( - tree: &mut impl LayoutTree, - flex_lines: &mut [FlexLine], - node: Node, - constants: &AlgoConstants, -) { +fn distribute_remaining_free_space(flex_lines: &mut [FlexLine], constants: &AlgoConstants) { for line in flex_lines { let total_main_axis_gap = sum_axis_gaps(constants.gap.main(constants.dir), line.items.len()); let used_space: f32 = total_main_axis_gap @@ -1447,11 +1491,10 @@ fn distribute_remaining_free_space( let mut num_auto_margins = 0; for child in line.items.iter_mut() { - let child_style = tree.style(child.node); - if child_style.margin.main_start(constants.dir) == LengthPercentageAuto::Auto { + if child.margin_is_auto.main_start(constants.dir) { num_auto_margins += 1; } - if child_style.margin.main_end(constants.dir) == LengthPercentageAuto::Auto { + if child.margin_is_auto.main_end(constants.dir) { num_auto_margins += 1; } } @@ -1460,15 +1503,14 @@ fn distribute_remaining_free_space( let margin = free_space / num_auto_margins as f32; for child in line.items.iter_mut() { - let child_style = tree.style(child.node); - if child_style.margin.main_start(constants.dir) == LengthPercentageAuto::Auto { + if child.margin_is_auto.main_start(constants.dir) { if constants.is_row { child.margin.left = margin; } else { child.margin.top = margin; } } - if child_style.margin.main_end(constants.dir) == LengthPercentageAuto::Auto { + if child.margin_is_auto.main_end(constants.dir) { if constants.is_row { child.margin.right = margin; } else { @@ -1480,8 +1522,7 @@ fn distribute_remaining_free_space( let num_items = line.items.len(); let layout_reverse = constants.dir.is_reverse(); let gap = constants.gap.main(constants.dir); - let justify_content_mode: JustifyContent = - tree.style(node).justify_content.unwrap_or(JustifyContent::FlexStart); + let justify_content_mode = constants.justify_content.unwrap_or(JustifyContent::FlexStart); let justify_item = |(i, child): (usize, &mut FlexItem)| { child.offset_main = @@ -1510,18 +1551,15 @@ fn distribute_remaining_free_space( /// - Otherwise, if the block-start or inline-start margin (whichever is in the cross axis) is auto, set it to zero. /// Set the opposite margin so that the outer cross size of the item equals the cross size of its flex line. #[inline] -fn resolve_cross_axis_auto_margins(tree: &mut impl LayoutTree, flex_lines: &mut [FlexLine], constants: &AlgoConstants) { +fn resolve_cross_axis_auto_margins(flex_lines: &mut [FlexLine], constants: &AlgoConstants) { for line in flex_lines { let line_cross_size = line.cross_size; let max_baseline: f32 = line.items.iter_mut().map(|child| child.baseline).fold(0.0, |acc, x| acc.max(x)); for child in line.items.iter_mut() { let free_space = line_cross_size - child.outer_target_size.cross(constants.dir); - let child_style = tree.style(child.node); - if child_style.margin.cross_start(constants.dir) == LengthPercentageAuto::Auto - && child_style.margin.cross_end(constants.dir) == LengthPercentageAuto::Auto - { + if child.margin_is_auto.cross_start(constants.dir) && child.margin_is_auto.cross_end(constants.dir) { if constants.is_row { child.margin.top = free_space / 2.0; child.margin.bottom = free_space / 2.0; @@ -1529,13 +1567,13 @@ fn resolve_cross_axis_auto_margins(tree: &mut impl LayoutTree, flex_lines: &mut child.margin.left = free_space / 2.0; child.margin.right = free_space / 2.0; } - } else if child_style.margin.cross_start(constants.dir) == LengthPercentageAuto::Auto { + } else if child.margin_is_auto.cross_start(constants.dir) { if constants.is_row { child.margin.top = free_space; } else { child.margin.left = free_space; } - } else if child_style.margin.cross_end(constants.dir) == LengthPercentageAuto::Auto { + } else if child.margin_is_auto.cross_end(constants.dir) { if constants.is_row { child.margin.bottom = free_space; } else { @@ -1622,17 +1660,18 @@ fn determine_container_cross_size( let total_cross_axis_gap = sum_axis_gaps(constants.gap.cross(constants.dir), flex_lines.len()); let total_line_cross_size: f32 = flex_lines.iter().map(|line| line.cross_size).sum::(); - constants.container_size.set_cross( - constants.dir, - node_size.cross(constants.dir).unwrap_or( - total_line_cross_size + total_cross_axis_gap + constants.padding_border.cross_axis_sum(constants.dir), - ), - ); + let padding_border_sum = constants.padding_border.cross_axis_sum(constants.dir); + let min_cross_size = constants.min_size.cross(constants.dir); + let max_cross_size = constants.max_size.cross(constants.dir); + let outer_container_size = node_size + .cross(constants.dir) + .unwrap_or(total_line_cross_size + total_cross_axis_gap + padding_border_sum) + .maybe_clamp(min_cross_size, max_cross_size) + .max(padding_border_sum); + let inner_container_size = outer_container_size - padding_border_sum; - constants.inner_container_size.set_cross( - constants.dir, - constants.container_size.cross(constants.dir) - constants.padding_border.cross_axis_sum(constants.dir), - ); + constants.container_size.set_cross(constants.dir, outer_container_size); + constants.inner_container_size.set_cross(constants.dir, inner_container_size); total_line_cross_size } @@ -1643,16 +1682,10 @@ fn determine_container_cross_size( /// /// - [**Align all flex lines**](https://www.w3.org/TR/css-flexbox-1/#algo-line-align) per `align-content`. #[inline] -fn align_flex_lines_per_align_content( - tree: &impl LayoutTree, - flex_lines: &mut [FlexLine], - node: Node, - constants: &AlgoConstants, - total_cross_size: f32, -) { +fn align_flex_lines_per_align_content(flex_lines: &mut [FlexLine], constants: &AlgoConstants, total_cross_size: f32) { let num_lines = flex_lines.len(); let gap = constants.gap.cross(constants.dir); - let align_content_mode = tree.style(node).align_content.unwrap_or(AlignContent::Stretch); + let align_content_mode = constants.align_content; let total_cross_axis_gap = sum_axis_gaps(gap, num_lines); let free_space = constants.inner_container_size.cross(constants.dir) - total_cross_size - total_cross_axis_gap; @@ -1824,8 +1857,11 @@ fn perform_absolute_layout_on_absolute_children(tree: &mut impl LayoutTree, node } let aspect_ratio = child_style.aspect_ratio; - let margin = child_style.margin.map(|margin| margin.resolve_to_option(container_width)); let align_self = child_style.align_self.unwrap_or(constants.align_items); + let margin = child_style.margin.map(|margin| margin.resolve_to_option(container_width)); + let padding = child_style.padding.resolve_or_zero(Some(container_width)); + let border = child_style.border.resolve_or_zero(Some(container_width)); + let padding_border_sum = (padding + border).sum_axes(); // Resolve inset let left = child_style.inset.left.maybe_resolve(container_width); @@ -1836,8 +1872,12 @@ fn perform_absolute_layout_on_absolute_children(tree: &mut impl LayoutTree, node // Compute known dimensions from min/max/inherent size styles let style_size = child_style.size.maybe_resolve(constants.container_size).maybe_apply_aspect_ratio(aspect_ratio); - let min_size = - child_style.min_size.maybe_resolve(constants.container_size).maybe_apply_aspect_ratio(aspect_ratio); + let min_size = child_style + .min_size + .maybe_resolve(constants.container_size) + .maybe_apply_aspect_ratio(aspect_ratio) + .or(padding_border_sum.map(Some)) + .maybe_max(padding_border_sum); let max_size = child_style.max_size.maybe_resolve(constants.container_size).maybe_apply_aspect_ratio(aspect_ratio); let mut known_dimensions = style_size.maybe_clamp(min_size, max_size); @@ -1928,7 +1968,7 @@ fn perform_absolute_layout_on_absolute_children(tree: &mut impl LayoutTree, node } else { // Stretch is an invalid value for justify_content in the flexbox algorithm, so we // treat it as if it wasn't set (and thus we default to FlexStart behaviour) - match (tree.style(node).justify_content.unwrap_or(JustifyContent::Start), constants.is_wrap_reverse) { + match (constants.justify_content.unwrap_or(JustifyContent::Start), constants.is_wrap_reverse) { (JustifyContent::SpaceBetween, _) | (JustifyContent::Start, _) | (JustifyContent::Stretch, false) diff --git a/src/compute/grid/alignment.rs b/src/compute/grid/alignment.rs index 0c0ed9f81..0b85fb792 100644 --- a/src/compute/grid/alignment.rs +++ b/src/compute/grid/alignment.rs @@ -7,7 +7,7 @@ use crate::geometry::{Line, Point, Rect, Size}; use crate::layout::{Layout, SizingMode}; use crate::math::MaybeMath; use crate::node::Node; -use crate::resolve::MaybeResolve; +use crate::resolve::{MaybeResolve, ResolveOrZero}; use crate::style::{AlignContent, AlignItems, AlignSelf, AvailableSpace, Position}; use crate::sys::{f32_max, f32_min}; use crate::tree::LayoutTree; @@ -90,8 +90,16 @@ pub(super) fn align_and_position_item( let position = style.position; let inset_horizontal = style.inset.horizontal_components().map(|size| size.resolve_to_option(grid_area_size.width)); let inset_vertical = style.inset.vertical_components().map(|size| size.resolve_to_option(grid_area_size.height)); + let padding = style.padding.map(|p| p.resolve_or_zero(Some(grid_area_size.width))); + let border = style.border.map(|p| p.resolve_or_zero(Some(grid_area_size.width))); + let padding_border_size = (padding + border).sum_axes(); let inherent_size = style.size.maybe_resolve(grid_area_size).maybe_apply_aspect_ratio(aspect_ratio); - let min_size = style.min_size.maybe_resolve(grid_area_size).maybe_apply_aspect_ratio(aspect_ratio); + let min_size = style + .min_size + .maybe_resolve(grid_area_size) + .or(padding_border_size.map(Some)) + .maybe_max(padding_border_size) + .maybe_apply_aspect_ratio(aspect_ratio); let max_size = style.max_size.maybe_resolve(grid_area_size).maybe_apply_aspect_ratio(aspect_ratio); // Resolve default alignment styles if they are set on neither the parent or the node itself @@ -149,6 +157,7 @@ pub(super) fn align_and_position_item( None }); + // Reapply aspect ratio after stretch and absolute position width adjustments let Size { width, height } = Size { width, height: inherent_size.height }.maybe_apply_aspect_ratio(aspect_ratio); diff --git a/src/compute/grid/mod.rs b/src/compute/grid/mod.rs index 4e691eae5..09a91eb09 100644 --- a/src/compute/grid/mod.rs +++ b/src/compute/grid/mod.rs @@ -141,6 +141,7 @@ pub fn compute( // https://www.w3.org/TR/css-grid-1/#available-grid-space let padding = style.padding.resolve_or_zero(parent_size.width); let border = style.border.resolve_or_zero(parent_size.width); + let padding_border_size = (padding + border).sum_axes(); let aspect_ratio = style.aspect_ratio; let min_size = style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio); let max_size = style.max_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio); @@ -236,10 +237,12 @@ pub fn compute( let container_border_box = Size { width: resolved_style_size .get(AbstractAxis::Inline) - .unwrap_or_else(|| initial_column_sum + padding.horizontal_axis_sum() + border.horizontal_axis_sum()), + .unwrap_or_else(|| initial_column_sum + padding.horizontal_axis_sum() + border.horizontal_axis_sum()) + .max(padding_border_size.width), height: resolved_style_size .get(AbstractAxis::Block) - .unwrap_or_else(|| initial_row_sum + padding.vertical_axis_sum() + border.vertical_axis_sum()), + .unwrap_or_else(|| initial_row_sum + padding.vertical_axis_sum() + border.vertical_axis_sum()) + .max(padding_border_size.height), }; let container_content_box = Size { width: container_border_box.width - padding.horizontal_axis_sum() - border.horizontal_axis_sum(), @@ -449,7 +452,7 @@ pub fn compute( // Position hidden child if child_style.display == Display::None { - *tree.layout_mut(node) = Layout::with_order(order); + *tree.layout_mut(child) = Layout::with_order(order); GenericAlgorithm::perform_layout( tree, child, diff --git a/src/compute/leaf.rs b/src/compute/leaf.rs index 2c347a64d..6f95145db 100644 --- a/src/compute/leaf.rs +++ b/src/compute/leaf.rs @@ -72,6 +72,12 @@ pub(crate) fn compute( } }; + // Note: both horizontal and vertical percentage padding/borders are resolved against the container's inline size (i.e. width). + // This is not a bug, but is how CSS is specified (see: https://developer.mozilla.org/en-US/docs/Web/CSS/padding#values) + let padding = style.padding.resolve_or_zero(parent_size.width); + let border = style.border.resolve_or_zero(parent_size.width); + let padding_border = padding + border; + #[cfg(feature = "debug")] NODE_LOGGER.log("LEAF"); #[cfg(feature = "debug")] @@ -83,7 +89,9 @@ pub(crate) fn compute( // Return early if both width and height are known if let Size { width: Some(width), height: Some(height) } = node_size { - let size = Size { width, height }.maybe_clamp(node_min_size, node_max_size); + let size = Size { width, height } + .maybe_clamp(node_min_size, node_max_size) + .maybe_max(padding_border.sum_axes().map(Some)); return SizeAndBaselines { size, first_baselines: Point::NONE }; }; @@ -111,25 +119,29 @@ pub(crate) fn compute( }; let size = node_size.unwrap_or(measured_size).maybe_clamp(node_min_size, node_max_size); + let size = size.maybe_max(padding_border.sum_axes().map(Some)); 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). - // This is not a bug, but is how CSS is specified (see: https://developer.mozilla.org/en-US/docs/Web/CSS/padding#values) - let padding = style.padding.resolve_or_zero(parent_size.width); - let border = style.border.resolve_or_zero(parent_size.width); - let size = Size { width: node_size .width // .unwrap_or(0.0) + padding.horizontal_axis_sum() + border.horizontal_axis_sum(), // content-box - .unwrap_or(0.0 + padding.horizontal_axis_sum() + border.horizontal_axis_sum()) // border-box - .maybe_clamp(node_min_size.width, node_max_size.width), + .unwrap_or(0.0) // border-box + .maybe_clamp(node_min_size.width, node_max_size.width) + .maybe_max(padding_border.horizontal_axis_sum().into()), height: node_size .height // .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), + .unwrap_or(0.0) // border-box + .maybe_clamp(node_min_size.height, node_max_size.height) + .maybe_max(padding_border.vertical_axis_sum().into()), }; + + let size = Size { + width: f32_max(size.width, aspect_ratio.map(|ratio| size.height * ratio).unwrap_or(0.0)), + height: f32_max(size.height, aspect_ratio.map(|ratio| size.width / ratio).unwrap_or(0.0)), + }; + SizeAndBaselines { size, first_baselines: Point::NONE } } diff --git a/src/compute/mod.rs b/src/compute/mod.rs index 50280f474..35fc1b9b0 100644 --- a/src/compute/mod.rs +++ b/src/compute/mod.rs @@ -137,7 +137,7 @@ 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_and_baselines) = - compute_from_cache(tree, node, known_dimensions, available_space, cache_run_mode, sizing_mode) + compute_from_cache(tree, node, known_dimensions, available_space, cache_run_mode) { #[cfg(feature = "debug")] NODE_LOGGER.labelled_debug_log("CACHE", cached_size_and_baselines.size); @@ -247,6 +247,7 @@ fn debug_log_node( NODE_LOGGER.debug_log(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("parent_size", parent_size); NODE_LOGGER.labelled_debug_log("available_space", available_space); } @@ -307,7 +308,6 @@ fn compute_from_cache( known_dimensions: Size>, available_space: Size, run_mode: RunMode, - sizing_mode: SizingMode, ) -> Option { for idx in 0..CACHE_SIZE { let entry = tree.cache_mut(node, idx); @@ -324,15 +324,9 @@ fn compute_from_cache( && (known_dimensions.height == entry.known_dimensions.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() >= cached_size.width)) + || entry.available_space.width.is_roughly_equal(available_space.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() >= cached_size.height)) + || entry.available_space.height.is_roughly_equal(available_space.height)) { return Some(entry.cached_size_and_baselines); } diff --git a/src/geometry.rs b/src/geometry.rs index 3db779ed1..3f96d3d85 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -320,6 +320,33 @@ impl Size { } } + /// Creates a new value of type Self with the main axis set to value provided + /// + /// Whether this is the width or height depends on the `direction` provided + #[allow(dead_code)] + pub(crate) fn with_main(self, direction: FlexDirection, value: T) -> Self { + let mut new = self; + if direction.is_row() { + new.width = value + } else { + new.height = value + } + new + } + + /// Creates a new value of type Self with the cross axis set to value provided + /// + /// Whether this is the width or height depends on the `direction` provided + pub(crate) fn with_cross(self, direction: FlexDirection, value: T) -> Self { + let mut new = self; + if direction.is_row() { + new.height = value + } else { + new.width = value + } + new + } + /// Gets the extent of the main layout axis /// /// Whether this is the width or height depends on the `direction` provided diff --git a/src/style/dimension.rs b/src/style/dimension.rs index 21e3d7f1c..d4caade8e 100644 --- a/src/style/dimension.rs +++ b/src/style/dimension.rs @@ -135,11 +135,6 @@ impl From for Dimension { } impl Dimension { - /// Is this value defined? - pub(crate) fn is_defined(self) -> bool { - matches!(self, Dimension::Points(_) | Dimension::Percent(_)) - } - /// Get Points value if value is Points variant #[cfg(feature = "grid")] pub fn into_option(self) -> Option { diff --git a/src/style/grid.rs b/src/style/grid.rs index 1053f74ff..63ec1d284 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -314,7 +314,7 @@ impl MaxTrackSizingFunction { /// will if the available_space is `Some`). Otherwise returns None. #[inline(always)] pub fn definite_value(self, parent_size: Option) -> Option { - use MaxTrackSizingFunction::{Auto, *}; + use MaxTrackSizingFunction::*; match self { Fixed(LengthPercentage::Points(size)) => Some(size), Fixed(LengthPercentage::Percent(fraction)) => parent_size.map(|size| fraction * size), @@ -342,7 +342,7 @@ impl MaxTrackSizingFunction { /// Non-percentage values always return None. #[inline(always)] pub fn resolved_percentage_size(self, parent_size: f32) -> Option { - use MaxTrackSizingFunction::{Auto, *}; + use MaxTrackSizingFunction::*; match self { Fixed(LengthPercentage::Percent(fraction)) => Some(fraction * parent_size), Fixed(LengthPercentage::Points(_)) | MinContent | MaxContent | FitContent(_) | Auto | Fraction(_) => None, @@ -409,7 +409,7 @@ impl MinTrackSizingFunction { /// will if the available_space is `Some`). Otherwise returns `None`. #[inline(always)] pub fn definite_value(self, parent_size: Option) -> Option { - use MinTrackSizingFunction::{Auto, *}; + use MinTrackSizingFunction::*; match self { Fixed(LengthPercentage::Points(size)) => Some(size), Fixed(LengthPercentage::Percent(fraction)) => parent_size.map(|size| fraction * size), @@ -421,7 +421,7 @@ impl MinTrackSizingFunction { /// Non-percentage values always return None. #[inline(always)] pub fn resolved_percentage_size(self, parent_size: f32) -> Option { - use MinTrackSizingFunction::{Auto, *}; + use MinTrackSizingFunction::*; match self { Fixed(LengthPercentage::Percent(fraction)) => Some(fraction * parent_size), Fixed(LengthPercentage::Points(_)) | MinContent | MaxContent | Auto => None, diff --git a/test_fixtures/absolute_padding_border_overrides_max_size.html b/test_fixtures/absolute_padding_border_overrides_max_size.html new file mode 100644 index 000000000..04f16a34a --- /dev/null +++ b/test_fixtures/absolute_padding_border_overrides_max_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/absolute_padding_border_overrides_size.html b/test_fixtures/absolute_padding_border_overrides_size.html new file mode 100644 index 000000000..6cbc088af --- /dev/null +++ b/test_fixtures/absolute_padding_border_overrides_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/bevy_issue_7976_3_level.html b/test_fixtures/bevy_issue_7976_3_level.html new file mode 100644 index 000000000..50f3617b4 --- /dev/null +++ b/test_fixtures/bevy_issue_7976_3_level.html @@ -0,0 +1,19 @@ + + + + + + + Test description + + + + +
+
+
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/bevy_issue_7976_4_level.html b/test_fixtures/bevy_issue_7976_4_level.html new file mode 100644 index 000000000..80497279b --- /dev/null +++ b/test_fixtures/bevy_issue_7976_4_level.html @@ -0,0 +1,21 @@ + + + + + + + Test description + + + + +
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/bevy_issue_7976_reduced.html b/test_fixtures/bevy_issue_7976_reduced.html new file mode 100644 index 000000000..85d9c37ac --- /dev/null +++ b/test_fixtures/bevy_issue_7976_reduced.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/bevy_issue_8017.html b/test_fixtures/bevy_issue_8017.html new file mode 100644 index 000000000..9d38263da --- /dev/null +++ b/test_fixtures/bevy_issue_8017.html @@ -0,0 +1,24 @@ + + + + + + + Bevy #8017 + + + + +
+
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/bevy_issue_8017_reduced.html b/test_fixtures/bevy_issue_8017_reduced.html new file mode 100644 index 000000000..fe6362222 --- /dev/null +++ b/test_fixtures/bevy_issue_8017_reduced.html @@ -0,0 +1,22 @@ + + + + + + + Bevy #8017 + + + + +
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/bevy_issue_8082.html b/test_fixtures/bevy_issue_8082.html new file mode 100644 index 000000000..bd7c9d5ef --- /dev/null +++ b/test_fixtures/bevy_issue_8082.html @@ -0,0 +1,22 @@ + + + + + + + Test description + + + + +
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/bevy_issue_8082_percent.html b/test_fixtures/bevy_issue_8082_percent.html new file mode 100644 index 000000000..ca81dbeeb --- /dev/null +++ b/test_fixtures/bevy_issue_8082_percent.html @@ -0,0 +1,22 @@ + + + + + + + Test description + + + + +
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/flex_grow_within_constrained_min_max_column.html b/test_fixtures/flex_grow_within_constrained_min_max_column.html index 51c19d853..9cb289f1c 100644 --- a/test_fixtures/flex_grow_within_constrained_min_max_column.html +++ b/test_fixtures/flex_grow_within_constrained_min_max_column.html @@ -9,7 +9,7 @@ -
+
diff --git a/test_fixtures/grid_padding_border_overrides_container_max_size.html b/test_fixtures/grid_padding_border_overrides_container_max_size.html new file mode 100644 index 000000000..a58489fca --- /dev/null +++ b/test_fixtures/grid_padding_border_overrides_container_max_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/grid_padding_border_overrides_container_size.html b/test_fixtures/grid_padding_border_overrides_container_size.html new file mode 100644 index 000000000..a5cab4eed --- /dev/null +++ b/test_fixtures/grid_padding_border_overrides_container_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/grid_padding_border_overrides_max_size.html b/test_fixtures/grid_padding_border_overrides_max_size.html new file mode 100644 index 000000000..41ec1e05d --- /dev/null +++ b/test_fixtures/grid_padding_border_overrides_max_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/grid_padding_border_overrides_min_size.html b/test_fixtures/grid_padding_border_overrides_min_size.html new file mode 100644 index 000000000..629e26a33 --- /dev/null +++ b/test_fixtures/grid_padding_border_overrides_min_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/grid_padding_border_overrides_size.html b/test_fixtures/grid_padding_border_overrides_size.html new file mode 100644 index 000000000..4612b1b38 --- /dev/null +++ b/test_fixtures/grid_padding_border_overrides_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/leaf_padding_border_overrides_max_size.html b/test_fixtures/leaf_padding_border_overrides_max_size.html new file mode 100644 index 000000000..99f440a8b --- /dev/null +++ b/test_fixtures/leaf_padding_border_overrides_max_size.html @@ -0,0 +1,15 @@ + + + + + + + Test description + + + + +
+ + + \ No newline at end of file diff --git a/test_fixtures/leaf_padding_border_overrides_min_size.html b/test_fixtures/leaf_padding_border_overrides_min_size.html new file mode 100644 index 000000000..0482e8258 --- /dev/null +++ b/test_fixtures/leaf_padding_border_overrides_min_size.html @@ -0,0 +1,15 @@ + + + + + + + Test description + + + + +
+ + + \ No newline at end of file diff --git a/test_fixtures/leaf_padding_border_overrides_size.html b/test_fixtures/leaf_padding_border_overrides_size.html new file mode 100644 index 000000000..8aa54d19e --- /dev/null +++ b/test_fixtures/leaf_padding_border_overrides_size.html @@ -0,0 +1,15 @@ + + + + + + + Test description + + + + +
+ + + \ No newline at end of file diff --git a/test_fixtures/measure_child_with_min_size_greater_than_available_space.html b/test_fixtures/measure_child_with_min_size_greater_than_available_space.html new file mode 100644 index 000000000..3e46330f0 --- /dev/null +++ b/test_fixtures/measure_child_with_min_size_greater_than_available_space.html @@ -0,0 +1,14 @@ + + + + + + + Test description + + + + +
+
HHHHHHHH​HHHHHHHH
+
diff --git a/test_fixtures/padding_border_overrides_max_size.html b/test_fixtures/padding_border_overrides_max_size.html new file mode 100644 index 000000000..6d0bf7cf1 --- /dev/null +++ b/test_fixtures/padding_border_overrides_max_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/padding_border_overrides_min_size.html b/test_fixtures/padding_border_overrides_min_size.html new file mode 100644 index 000000000..d8223127a --- /dev/null +++ b/test_fixtures/padding_border_overrides_min_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/padding_border_overrides_size.html b/test_fixtures/padding_border_overrides_size.html new file mode 100644 index 000000000..7b2ed62d2 --- /dev/null +++ b/test_fixtures/padding_border_overrides_size.html @@ -0,0 +1,17 @@ + + + + + + + Test description + + + + +
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/padding_border_overrides_size_flex_basis_0.html b/test_fixtures/padding_border_overrides_size_flex_basis_0.html new file mode 100644 index 000000000..d51e820ce --- /dev/null +++ b/test_fixtures/padding_border_overrides_size_flex_basis_0.html @@ -0,0 +1,18 @@ + + + + + + + Test description + + + + +
+
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/padding_border_overrides_size_flex_basis_0_growable.html b/test_fixtures/padding_border_overrides_size_flex_basis_0_growable.html new file mode 100644 index 000000000..0b2ff0552 --- /dev/null +++ b/test_fixtures/padding_border_overrides_size_flex_basis_0_growable.html @@ -0,0 +1,18 @@ + + + + + + + Test description + + + + +
+
+
+
+ + + \ No newline at end of file diff --git a/test_fixtures/percentage_sizes_should_not_prevent_flex_shrinking.html b/test_fixtures/percentage_sizes_should_not_prevent_flex_shrinking.html new file mode 100644 index 000000000..d1bcfe8f4 --- /dev/null +++ b/test_fixtures/percentage_sizes_should_not_prevent_flex_shrinking.html @@ -0,0 +1,19 @@ + + + + + + + Bevy #8017 + + + + +
+
+
+
+
+ + + \ No newline at end of file diff --git a/tests/border_and_padding.rs b/tests/border_and_padding.rs index 26cfd1a1f..17a51914f 100644 --- a/tests/border_and_padding.rs +++ b/tests/border_and_padding.rs @@ -6,6 +6,7 @@ fn arr_to_rect(items: [T; 4]) -> Rect { } #[test] +#[ignore] fn border_on_a_single_axis_doesnt_increase_size() { for i in 0..4 { let mut taffy = Taffy::new(); @@ -33,6 +34,7 @@ fn border_on_a_single_axis_doesnt_increase_size() { } #[test] +#[ignore] fn padding_on_a_single_axis_doesnt_increase_size() { for i in 0..4 { let mut taffy = Taffy::new(); @@ -60,6 +62,7 @@ fn padding_on_a_single_axis_doesnt_increase_size() { } #[test] +#[ignore] fn border_and_padding_on_a_single_axis_doesnt_increase_size() { for i in 0..4 { let mut taffy = Taffy::new(); @@ -82,6 +85,7 @@ fn border_and_padding_on_a_single_axis_doesnt_increase_size() { } #[test] +#[ignore] fn vertical_border_and_padding_percentage_values_use_available_space_correctly() { let mut taffy = Taffy::new(); diff --git a/tests/caching.rs b/tests/caching.rs index 37eff95e2..581ce43e9 100644 --- a/tests/caching.rs +++ b/tests/caching.rs @@ -10,7 +10,7 @@ mod caching { let mut taffy = Taffy::new(); static NUM_MEASURES: AtomicU32 = AtomicU32::new(0); - let grandchild = taffy + let leaf = taffy .new_leaf_with_measure( Style { ..Default::default() }, MeasureFunc::Raw(|known_dimensions, _available_space| { @@ -23,12 +23,14 @@ mod caching { ) .unwrap(); - let child = taffy.new_with_children(Style::DEFAULT, &[grandchild]).unwrap(); + let mut node = taffy.new_with_children(Style::DEFAULT, &[leaf]).unwrap(); + for _ in 0..100 { + node = taffy.new_with_children(Style::DEFAULT, &[node]).unwrap(); + } - let node = taffy.new_with_children(Style::DEFAULT, &[child]).unwrap(); taffy.compute_layout(node, Size::MAX_CONTENT).unwrap(); - assert_eq!(NUM_MEASURES.load(Ordering::SeqCst), 2); + assert_eq!(NUM_MEASURES.load(Ordering::SeqCst), 8); } #[test] @@ -41,7 +43,7 @@ mod caching { let mut taffy = Taffy::new(); static NUM_MEASURES: AtomicU32 = AtomicU32::new(0); - let grandchild = taffy + let leaf = taffy .new_leaf_with_measure( style(), MeasureFunc::Raw(|known_dimensions, _available_space| { @@ -54,11 +56,12 @@ mod caching { ) .unwrap(); - let child = taffy.new_with_children(style(), &[grandchild]).unwrap(); - - let node = taffy.new_with_children(style(), &[child]).unwrap(); + let mut node = taffy.new_with_children(Style::DEFAULT, &[leaf]).unwrap(); + for _ in 0..100 { + node = taffy.new_with_children(Style::DEFAULT, &[node]).unwrap(); + } taffy.compute_layout(node, Size::MAX_CONTENT).unwrap(); - assert_eq!(NUM_MEASURES.load(Ordering::SeqCst), 2); + assert_eq!(NUM_MEASURES.load(Ordering::SeqCst), 8); } } diff --git a/tests/generated/absolute_padding_border_overrides_max_size.rs b/tests/generated/absolute_padding_border_overrides_max_size.rs new file mode 100644 index 000000000..b90bda2da --- /dev/null +++ b/tests/generated/absolute_padding_border_overrides_max_size.rs @@ -0,0 +1,44 @@ +#[test] +fn absolute_padding_border_overrides_max_size() { + 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 { + position: taffy::style::Position::Absolute, + max_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy.new_with_children(taffy::style::Style { ..Default::default() }, &[node0]).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, 0f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 0f32, size.width); + assert_eq!(size.height, 0f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 0f32, 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, 22f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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); +} diff --git a/tests/generated/absolute_padding_border_overrides_size.rs b/tests/generated/absolute_padding_border_overrides_size.rs new file mode 100644 index 000000000..f4303f2d8 --- /dev/null +++ b/tests/generated/absolute_padding_border_overrides_size.rs @@ -0,0 +1,44 @@ +#[test] +fn absolute_padding_border_overrides_size() { + 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 { + position: taffy::style::Position::Absolute, + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy.new_with_children(taffy::style::Style { ..Default::default() }, &[node0]).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, 0f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 0f32, size.width); + assert_eq!(size.height, 0f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 0f32, 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, 22f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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); +} diff --git a/tests/generated/bevy_issue_7976_3_level.rs b/tests/generated/bevy_issue_7976_3_level.rs new file mode 100644 index 000000000..ef9771efe --- /dev/null +++ b/tests/generated/bevy_issue_7976_3_level.rs @@ -0,0 +1,78 @@ +#[test] +fn bevy_issue_7976_3_level() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node00 = taffy + .new_leaf(taffy::style::Style { + size: taffy::geometry::Size { + width: taffy::style::Dimension::Percent(1f32), + height: taffy::style::Dimension::Percent(1f32), + }, + 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() + }) + .unwrap(); + let node0 = taffy + .new_with_children( + taffy::style::Style { + min_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(40f32), + height: taffy::style::Dimension::Points(40f32), + }, + 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), + }, + 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() + }, + &[node00], + ) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + align_content: Some(taffy::style::AlignContent::Start), + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(200f32), + height: taffy::style::Dimension::Points(200f32), + }, + ..Default::default() + }, + &[node0], + ) + .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, 200f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 200f32, size.width); + assert_eq!(size.height, 200f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 200f32, 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, 190f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 190f32, 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(node00).unwrap(); + assert_eq!(size.width, 30f32, "width of node {:?}. Expected {}. Actual {}", node00.data(), 30f32, size.width); + assert_eq!(size.height, 180f32, "height of node {:?}. Expected {}. Actual {}", node00.data(), 180f32, size.height); + assert_eq!(location.x, 5f32, "x of node {:?}. Expected {}. Actual {}", node00.data(), 5f32, location.x); + assert_eq!(location.y, 5f32, "y of node {:?}. Expected {}. Actual {}", node00.data(), 5f32, location.y); +} diff --git a/tests/generated/bevy_issue_7976_4_level.rs b/tests/generated/bevy_issue_7976_4_level.rs new file mode 100644 index 000000000..c6f2a03c4 --- /dev/null +++ b/tests/generated/bevy_issue_7976_4_level.rs @@ -0,0 +1,87 @@ +#[test] +fn bevy_issue_7976_4_level() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node000 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); + let node00 = taffy + .new_with_children( + taffy::style::Style { + size: taffy::geometry::Size { + width: taffy::style::Dimension::Percent(1f32), + height: taffy::style::Dimension::Percent(1f32), + }, + 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() + }, + &[node000], + ) + .unwrap(); + let node0 = taffy + .new_with_children( + taffy::style::Style { + min_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(40f32), + height: taffy::style::Dimension::Points(40f32), + }, + 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), + }, + 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() + }, + &[node00], + ) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + align_content: Some(taffy::style::AlignContent::Start), + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(200f32), + height: taffy::style::Dimension::Points(200f32), + }, + ..Default::default() + }, + &[node0], + ) + .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, 200f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 200f32, size.width); + assert_eq!(size.height, 200f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 200f32, 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, 190f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 190f32, 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(node00).unwrap(); + assert_eq!(size.width, 30f32, "width of node {:?}. Expected {}. Actual {}", node00.data(), 30f32, size.width); + assert_eq!(size.height, 180f32, "height of node {:?}. Expected {}. Actual {}", node00.data(), 180f32, size.height); + assert_eq!(location.x, 5f32, "x of node {:?}. Expected {}. Actual {}", node00.data(), 5f32, location.x); + assert_eq!(location.y, 5f32, "y of node {:?}. Expected {}. Actual {}", node00.data(), 5f32, location.y); + let Layout { size, location, .. } = taffy.layout(node000).unwrap(); + assert_eq!(size.width, 0f32, "width of node {:?}. Expected {}. Actual {}", node000.data(), 0f32, size.width); + assert_eq!(size.height, 170f32, "height of node {:?}. Expected {}. Actual {}", node000.data(), 170f32, size.height); + assert_eq!(location.x, 5f32, "x of node {:?}. Expected {}. Actual {}", node000.data(), 5f32, location.x); + assert_eq!(location.y, 5f32, "y of node {:?}. Expected {}. Actual {}", node000.data(), 5f32, location.y); +} diff --git a/tests/generated/bevy_issue_7976_reduced.rs b/tests/generated/bevy_issue_7976_reduced.rs new file mode 100644 index 000000000..10ea0ddcd --- /dev/null +++ b/tests/generated/bevy_issue_7976_reduced.rs @@ -0,0 +1,37 @@ +#[test] +fn bevy_issue_7976_reduced() { + 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(40f32), height: auto() }, + ..Default::default() + }) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + align_content: Some(taffy::style::AlignContent::Start), + size: taffy::geometry::Size { width: auto(), height: taffy::style::Dimension::Points(200f32) }, + ..Default::default() + }, + &[node0], + ) + .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, 40f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 40f32, size.width); + assert_eq!(size.height, 200f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 200f32, 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, 200f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 200f32, 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); +} diff --git a/tests/generated/bevy_issue_8017.rs b/tests/generated/bevy_issue_8017.rs new file mode 100644 index 000000000..bc0e48010 --- /dev/null +++ b/tests/generated/bevy_issue_8017.rs @@ -0,0 +1,140 @@ +#[test] +fn bevy_issue_8017() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node00 = taffy + .new_leaf(taffy::style::Style { + size: taffy::geometry::Size { + width: taffy::style::Dimension::Percent(1f32), + height: taffy::style::Dimension::Percent(1f32), + }, + ..Default::default() + }) + .unwrap(); + let node01 = taffy + .new_leaf(taffy::style::Style { + size: taffy::geometry::Size { + width: taffy::style::Dimension::Percent(1f32), + height: taffy::style::Dimension::Percent(1f32), + }, + ..Default::default() + }) + .unwrap(); + let node0 = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Flex, + gap: taffy::geometry::Size { + width: taffy::style::LengthPercentage::Points(8f32), + height: taffy::style::LengthPercentage::Points(8f32), + }, + size: taffy::geometry::Size { + width: taffy::style::Dimension::Percent(1f32), + height: taffy::style::Dimension::Percent(0.5f32), + }, + ..Default::default() + }, + &[node00, node01], + ) + .unwrap(); + let node10 = taffy + .new_leaf(taffy::style::Style { + size: taffy::geometry::Size { + width: taffy::style::Dimension::Percent(1f32), + height: taffy::style::Dimension::Percent(1f32), + }, + ..Default::default() + }) + .unwrap(); + let node11 = taffy + .new_leaf(taffy::style::Style { + size: taffy::geometry::Size { + width: taffy::style::Dimension::Percent(1f32), + height: taffy::style::Dimension::Percent(1f32), + }, + ..Default::default() + }) + .unwrap(); + let node1 = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Flex, + gap: taffy::geometry::Size { + width: taffy::style::LengthPercentage::Points(8f32), + height: taffy::style::LengthPercentage::Points(8f32), + }, + size: taffy::geometry::Size { + width: taffy::style::Dimension::Percent(1f32), + height: taffy::style::Dimension::Percent(0.5f32), + }, + ..Default::default() + }, + &[node10, node11], + ) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Flex, + flex_direction: taffy::style::FlexDirection::Column, + gap: taffy::geometry::Size { + width: taffy::style::LengthPercentage::Points(8f32), + height: taffy::style::LengthPercentage::Points(8f32), + }, + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(400f32), + height: taffy::style::Dimension::Points(400f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(8f32), + top: taffy::style::LengthPercentage::Points(8f32), + bottom: taffy::style::LengthPercentage::Points(8f32), + }, + ..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, 400f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 400f32, size.width); + assert_eq!(size.height, 400f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 400f32, 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, 384f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 384f32, size.width); + assert_eq!(size.height, 188f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 188f32, size.height); + assert_eq!(location.x, 8f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 8f32, location.x); + assert_eq!(location.y, 8f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 8f32, location.y); + let Layout { size, location, .. } = taffy.layout(node00).unwrap(); + assert_eq!(size.width, 188f32, "width of node {:?}. Expected {}. Actual {}", node00.data(), 188f32, size.width); + assert_eq!(size.height, 188f32, "height of node {:?}. Expected {}. Actual {}", node00.data(), 188f32, size.height); + assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.y); + let Layout { size, location, .. } = taffy.layout(node01).unwrap(); + assert_eq!(size.width, 188f32, "width of node {:?}. Expected {}. Actual {}", node01.data(), 188f32, size.width); + assert_eq!(size.height, 188f32, "height of node {:?}. Expected {}. Actual {}", node01.data(), 188f32, size.height); + assert_eq!(location.x, 196f32, "x of node {:?}. Expected {}. Actual {}", node01.data(), 196f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node01.data(), 0f32, location.y); + let Layout { size, location, .. } = taffy.layout(node1).unwrap(); + assert_eq!(size.width, 384f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 384f32, size.width); + assert_eq!(size.height, 188f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 188f32, size.height); + assert_eq!(location.x, 8f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 8f32, location.x); + assert_eq!(location.y, 204f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 204f32, location.y); + let Layout { size, location, .. } = taffy.layout(node10).unwrap(); + assert_eq!(size.width, 188f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 188f32, size.width); + assert_eq!(size.height, 188f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 188f32, 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, 188f32, "width of node {:?}. Expected {}. Actual {}", node11.data(), 188f32, size.width); + assert_eq!(size.height, 188f32, "height of node {:?}. Expected {}. Actual {}", node11.data(), 188f32, size.height); + assert_eq!(location.x, 196f32, "x of node {:?}. Expected {}. Actual {}", node11.data(), 196f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node11.data(), 0f32, location.y); +} diff --git a/tests/generated/bevy_issue_8017_reduced.rs b/tests/generated/bevy_issue_8017_reduced.rs new file mode 100644 index 000000000..309acb7a5 --- /dev/null +++ b/tests/generated/bevy_issue_8017_reduced.rs @@ -0,0 +1,73 @@ +#[test] +fn bevy_issue_8017_reduced() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node00 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); + let node0 = taffy + .new_with_children( + taffy::style::Style { + size: taffy::geometry::Size { width: auto(), height: taffy::style::Dimension::Percent(0.5f32) }, + ..Default::default() + }, + &[node00], + ) + .unwrap(); + let node10 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); + let node1 = taffy + .new_with_children( + taffy::style::Style { + size: taffy::geometry::Size { width: auto(), height: taffy::style::Dimension::Percent(0.5f32) }, + ..Default::default() + }, + &[node10], + ) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + flex_direction: taffy::style::FlexDirection::Column, + gap: taffy::geometry::Size { + width: taffy::style::LengthPercentage::Points(8f32), + height: taffy::style::LengthPercentage::Points(8f32), + }, + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(200f32), + height: taffy::style::Dimension::Points(400f32), + }, + ..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, 200f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 200f32, size.width); + assert_eq!(size.height, 400f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 400f32, 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, 200f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 200f32, size.width); + assert_eq!(size.height, 196f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 196f32, 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(node00).unwrap(); + assert_eq!(size.width, 0f32, "width of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, size.width); + assert_eq!(size.height, 196f32, "height of node {:?}. Expected {}. Actual {}", node00.data(), 196f32, size.height); + assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.y); + let Layout { size, location, .. } = taffy.layout(node1).unwrap(); + assert_eq!(size.width, 200f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 200f32, size.width); + assert_eq!(size.height, 196f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 196f32, size.height); + assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, location.x); + assert_eq!(location.y, 204f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 204f32, location.y); + let Layout { size, location, .. } = taffy.layout(node10).unwrap(); + assert_eq!(size.width, 0f32, "width of node {:?}. Expected {}. Actual {}", node10.data(), 0f32, size.width); + assert_eq!(size.height, 196f32, "height of node {:?}. Expected {}. Actual {}", node10.data(), 196f32, 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); +} diff --git a/tests/generated/bevy_issue_8082.rs b/tests/generated/bevy_issue_8082.rs new file mode 100644 index 000000000..cefd7548f --- /dev/null +++ b/tests/generated/bevy_issue_8082.rs @@ -0,0 +1,129 @@ +#[test] +fn bevy_issue_8082() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node00 = 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(10f32), + right: taffy::style::LengthPercentageAuto::Points(10f32), + top: taffy::style::LengthPercentageAuto::Points(10f32), + bottom: taffy::style::LengthPercentageAuto::Points(10f32), + }, + ..Default::default() + }) + .unwrap(); + let node01 = 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(10f32), + right: taffy::style::LengthPercentageAuto::Points(10f32), + top: taffy::style::LengthPercentageAuto::Points(10f32), + bottom: taffy::style::LengthPercentageAuto::Points(10f32), + }, + ..Default::default() + }) + .unwrap(); + let node02 = 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(10f32), + right: taffy::style::LengthPercentageAuto::Points(10f32), + top: taffy::style::LengthPercentageAuto::Points(10f32), + bottom: taffy::style::LengthPercentageAuto::Points(10f32), + }, + ..Default::default() + }) + .unwrap(); + let node03 = 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(10f32), + right: taffy::style::LengthPercentageAuto::Points(10f32), + top: taffy::style::LengthPercentageAuto::Points(10f32), + bottom: taffy::style::LengthPercentageAuto::Points(10f32), + }, + ..Default::default() + }) + .unwrap(); + let node0 = taffy + .new_with_children( + taffy::style::Style { + flex_wrap: taffy::style::FlexWrap::Wrap, + align_items: Some(taffy::style::AlignItems::FlexStart), + align_content: Some(taffy::style::AlignContent::Center), + justify_content: Some(taffy::style::JustifyContent::Center), + ..Default::default() + }, + &[node00, node01, node02, node03], + ) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + flex_direction: taffy::style::FlexDirection::Column, + align_items: Some(taffy::style::AlignItems::Stretch), + align_content: Some(taffy::style::AlignContent::Center), + justify_content: Some(taffy::style::JustifyContent::FlexStart), + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(200f32), + height: taffy::style::Dimension::Points(400f32), + }, + ..Default::default() + }, + &[node0], + ) + .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, 200f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 200f32, size.width); + assert_eq!(size.height, 400f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 400f32, 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, 200f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 200f32, size.width); + assert_eq!(size.height, 140f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 140f32, 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(node00).unwrap(); + assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node00.data(), 50f32, size.width); + assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node00.data(), 50f32, size.height); + assert_eq!(location.x, 40f32, "x of node {:?}. Expected {}. Actual {}", node00.data(), 40f32, location.x); + assert_eq!(location.y, 10f32, "y of node {:?}. Expected {}. Actual {}", node00.data(), 10f32, location.y); + let Layout { size, location, .. } = taffy.layout(node01).unwrap(); + assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node01.data(), 50f32, size.width); + assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node01.data(), 50f32, size.height); + assert_eq!(location.x, 110f32, "x of node {:?}. Expected {}. Actual {}", node01.data(), 110f32, location.x); + assert_eq!(location.y, 10f32, "y of node {:?}. Expected {}. Actual {}", node01.data(), 10f32, location.y); + let Layout { size, location, .. } = taffy.layout(node02).unwrap(); + assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node02.data(), 50f32, size.width); + assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node02.data(), 50f32, size.height); + assert_eq!(location.x, 40f32, "x of node {:?}. Expected {}. Actual {}", node02.data(), 40f32, location.x); + assert_eq!(location.y, 80f32, "y of node {:?}. Expected {}. Actual {}", node02.data(), 80f32, location.y); + let Layout { size, location, .. } = taffy.layout(node03).unwrap(); + assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node03.data(), 50f32, size.width); + assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node03.data(), 50f32, size.height); + assert_eq!(location.x, 110f32, "x of node {:?}. Expected {}. Actual {}", node03.data(), 110f32, location.x); + assert_eq!(location.y, 80f32, "y of node {:?}. Expected {}. Actual {}", node03.data(), 80f32, location.y); +} diff --git a/tests/generated/bevy_issue_8082_percent.rs b/tests/generated/bevy_issue_8082_percent.rs new file mode 100644 index 000000000..a18290a1a --- /dev/null +++ b/tests/generated/bevy_issue_8082_percent.rs @@ -0,0 +1,106 @@ +#[test] +fn bevy_issue_8082_percent() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node00 = 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 node01 = 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 node02 = 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 node03 = 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 node0 = taffy + .new_with_children( + taffy::style::Style { + flex_wrap: taffy::style::FlexWrap::Wrap, + align_items: Some(taffy::style::AlignItems::FlexStart), + align_content: Some(taffy::style::AlignContent::Center), + justify_content: Some(taffy::style::JustifyContent::Center), + size: taffy::geometry::Size { width: taffy::style::Dimension::Percent(0.5f32), height: auto() }, + ..Default::default() + }, + &[node00, node01, node02, node03], + ) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + flex_direction: taffy::style::FlexDirection::Column, + align_items: Some(taffy::style::AlignItems::Stretch), + align_content: Some(taffy::style::AlignContent::Center), + justify_content: Some(taffy::style::JustifyContent::FlexStart), + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(200f32), + height: taffy::style::Dimension::Points(400f32), + }, + ..Default::default() + }, + &[node0], + ) + .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, 200f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 200f32, size.width); + assert_eq!(size.height, 400f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 400f32, 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, 100f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 100f32, size.width); + assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 100f32, 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(node00).unwrap(); + assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node00.data(), 50f32, size.width); + assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node00.data(), 50f32, size.height); + assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.y); + let Layout { size, location, .. } = taffy.layout(node01).unwrap(); + assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node01.data(), 50f32, size.width); + assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node01.data(), 50f32, size.height); + assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node01.data(), 50f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node01.data(), 0f32, location.y); + let Layout { size, location, .. } = taffy.layout(node02).unwrap(); + assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node02.data(), 50f32, size.width); + assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node02.data(), 50f32, size.height); + assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node02.data(), 0f32, location.x); + assert_eq!(location.y, 50f32, "y of node {:?}. Expected {}. Actual {}", node02.data(), 50f32, location.y); + let Layout { size, location, .. } = taffy.layout(node03).unwrap(); + assert_eq!(size.width, 50f32, "width of node {:?}. Expected {}. Actual {}", node03.data(), 50f32, size.width); + assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node03.data(), 50f32, size.height); + assert_eq!(location.x, 50f32, "x of node {:?}. Expected {}. Actual {}", node03.data(), 50f32, location.x); + assert_eq!(location.y, 50f32, "y of node {:?}. Expected {}. Actual {}", node03.data(), 50f32, location.y); +} diff --git a/tests/generated/flex_grow_within_constrained_min_max_column.rs b/tests/generated/flex_grow_within_constrained_min_max_column.rs index c83aafc73..8e0fb2fb9 100644 --- a/tests/generated/flex_grow_within_constrained_min_max_column.rs +++ b/tests/generated/flex_grow_within_constrained_min_max_column.rs @@ -14,7 +14,9 @@ fn flex_grow_within_constrained_min_max_column() { let node = taffy .new_with_children( taffy::style::Style { + flex_direction: taffy::style::FlexDirection::Column, min_size: taffy::geometry::Size { width: auto(), height: taffy::style::Dimension::Points(100f32) }, + max_size: taffy::geometry::Size { width: auto(), height: taffy::style::Dimension::Points(200f32) }, ..Default::default() }, &[node0, node1], @@ -31,12 +33,12 @@ fn flex_grow_within_constrained_min_max_column() { 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, 0f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, size.width); - assert_eq!(size.height, 100f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 100f32, size.height); + 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, 0f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, size.width); assert_eq!(size.height, 50f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, size.height); assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, location.x); - assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, location.y); + assert_eq!(location.y, 50f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 50f32, location.y); } diff --git a/tests/generated/grid_padding_border_overrides_container_max_size.rs b/tests/generated/grid_padding_border_overrides_container_max_size.rs new file mode 100644 index 000000000..62ae9ebbe --- /dev/null +++ b/tests/generated/grid_padding_border_overrides_container_max_size.rs @@ -0,0 +1,47 @@ +#[test] +fn grid_padding_border_overrides_container_max_size() { + 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 { ..Default::default() }).unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Grid, + max_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }, + &[node0], + ) + .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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 0f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, size.width); + assert_eq!(size.height, 0f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, size.height); + assert_eq!(location.x, 15f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 15f32, location.x); + assert_eq!(location.y, 3f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 3f32, location.y); +} diff --git a/tests/generated/grid_padding_border_overrides_container_size.rs b/tests/generated/grid_padding_border_overrides_container_size.rs new file mode 100644 index 000000000..f60ea6885 --- /dev/null +++ b/tests/generated/grid_padding_border_overrides_container_size.rs @@ -0,0 +1,47 @@ +#[test] +fn grid_padding_border_overrides_container_size() { + 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 { ..Default::default() }).unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Grid, + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }, + &[node0], + ) + .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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 0f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, size.width); + assert_eq!(size.height, 0f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 0f32, size.height); + assert_eq!(location.x, 15f32, "x of node {:?}. Expected {}. Actual {}", node0.data(), 15f32, location.x); + assert_eq!(location.y, 3f32, "y of node {:?}. Expected {}. Actual {}", node0.data(), 3f32, location.y); +} diff --git a/tests/generated/grid_padding_border_overrides_max_size.rs b/tests/generated/grid_padding_border_overrides_max_size.rs new file mode 100644 index 000000000..2a874008c --- /dev/null +++ b/tests/generated/grid_padding_border_overrides_max_size.rs @@ -0,0 +1,45 @@ +#[test] +fn grid_padding_border_overrides_max_size() { + 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 { + max_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy + .new_with_children(taffy::style::Style { display: taffy::style::Display::Grid, ..Default::default() }, &[node0]) + .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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 22f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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); +} diff --git a/tests/generated/grid_padding_border_overrides_min_size.rs b/tests/generated/grid_padding_border_overrides_min_size.rs new file mode 100644 index 000000000..16ca50031 --- /dev/null +++ b/tests/generated/grid_padding_border_overrides_min_size.rs @@ -0,0 +1,45 @@ +#[test] +fn grid_padding_border_overrides_min_size() { + 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 { + min_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(0f32), + height: taffy::style::Dimension::Points(0f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy + .new_with_children(taffy::style::Style { display: taffy::style::Display::Grid, ..Default::default() }, &[node0]) + .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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 22f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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); +} diff --git a/tests/generated/grid_padding_border_overrides_size.rs b/tests/generated/grid_padding_border_overrides_size.rs new file mode 100644 index 000000000..e2a5162b5 --- /dev/null +++ b/tests/generated/grid_padding_border_overrides_size.rs @@ -0,0 +1,45 @@ +#[test] +fn grid_padding_border_overrides_size() { + 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(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy + .new_with_children(taffy::style::Style { display: taffy::style::Display::Grid, ..Default::default() }, &[node0]) + .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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 22f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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); +} diff --git a/tests/generated/leaf_padding_border_overrides_max_size.rs b/tests/generated/leaf_padding_border_overrides_max_size.rs new file mode 100644 index 000000000..3f61a2b56 --- /dev/null +++ b/tests/generated/leaf_padding_border_overrides_max_size.rs @@ -0,0 +1,37 @@ +#[test] +fn leaf_padding_border_overrides_max_size() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node = taffy + .new_leaf(taffy::style::Style { + max_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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); +} diff --git a/tests/generated/leaf_padding_border_overrides_min_size.rs b/tests/generated/leaf_padding_border_overrides_min_size.rs new file mode 100644 index 000000000..44323f5bb --- /dev/null +++ b/tests/generated/leaf_padding_border_overrides_min_size.rs @@ -0,0 +1,37 @@ +#[test] +fn leaf_padding_border_overrides_min_size() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node = taffy + .new_leaf(taffy::style::Style { + min_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(0f32), + height: taffy::style::Dimension::Points(0f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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); +} diff --git a/tests/generated/leaf_padding_border_overrides_size.rs b/tests/generated/leaf_padding_border_overrides_size.rs new file mode 100644 index 000000000..631c85b54 --- /dev/null +++ b/tests/generated/leaf_padding_border_overrides_size.rs @@ -0,0 +1,37 @@ +#[test] +fn leaf_padding_border_overrides_size() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node = taffy + .new_leaf(taffy::style::Style { + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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); +} diff --git a/tests/generated/measure_child_with_min_size_greater_than_available_space.rs b/tests/generated/measure_child_with_min_size_greater_than_available_space.rs new file mode 100644 index 000000000..d42622268 --- /dev/null +++ b/tests/generated/measure_child_with_min_size_greater_than_available_space.rs @@ -0,0 +1,50 @@ +#[test] +fn measure_child_with_min_size_greater_than_available_space() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node0 = taffy + .new_leaf_with_measure( + taffy::style::Style { + min_size: taffy::geometry::Size { width: taffy::style::Dimension::Points(200f32), height: auto() }, + ..Default::default() + }, + taffy::node::MeasureFunc::Raw(|known_dimensions, available_space| { + const TEXT: &str = "HHHHHHHH\u{200b}HHHHHHHH"; + super::measure_standard_text( + known_dimensions, + available_space, + TEXT, + super::WritingMode::Horizontal, + None, + ) + }), + ) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + display: taffy::style::Display::Flex, + flex_direction: taffy::style::FlexDirection::Column, + size: taffy::geometry::Size { width: taffy::style::Dimension::Points(100f32), height: auto() }, + ..Default::default() + }, + &[node0], + ) + .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, 10f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 10f32, 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, 200f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 200f32, size.width); + assert_eq!(size.height, 10f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 10f32, 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); +} diff --git a/tests/generated/mod.rs b/tests/generated/mod.rs index dfe95c1e0..4be363806 100644 --- a/tests/generated/mod.rs +++ b/tests/generated/mod.rs @@ -104,6 +104,8 @@ mod absolute_minmax_bottom_right_min_max; mod absolute_minmax_bottom_right_min_max_preferred; mod absolute_minmax_top_left_bottom_right_max; mod absolute_minmax_top_left_bottom_right_min_max; +mod absolute_padding_border_overrides_max_size; +mod absolute_padding_border_overrides_size; mod align_baseline; mod align_baseline_child; mod align_baseline_child_margin; @@ -196,6 +198,13 @@ mod aspect_ratio_flex_row_stretch_fill_height; mod aspect_ratio_flex_row_stretch_fill_max_height; mod aspect_ratio_flex_row_stretch_fill_max_width; mod aspect_ratio_flex_row_stretch_fill_width; +mod bevy_issue_7976_3_level; +mod bevy_issue_7976_4_level; +mod bevy_issue_7976_reduced; +mod bevy_issue_8017; +mod bevy_issue_8017_reduced; +mod bevy_issue_8082; +mod bevy_issue_8082_percent; mod border_center_child; mod border_container_match_child; mod border_flex_child; @@ -643,6 +652,16 @@ mod grid_out_of_order_items; #[cfg(feature = "grid")] mod grid_overflow_rows; #[cfg(feature = "grid")] +mod grid_padding_border_overrides_container_max_size; +#[cfg(feature = "grid")] +mod grid_padding_border_overrides_container_size; +#[cfg(feature = "grid")] +mod grid_padding_border_overrides_max_size; +#[cfg(feature = "grid")] +mod grid_padding_border_overrides_min_size; +#[cfg(feature = "grid")] +mod grid_padding_border_overrides_size; +#[cfg(feature = "grid")] mod grid_percent_item_inside_stretch_item; #[cfg(feature = "grid")] mod grid_percent_items_nested_inside_stretch_alignment; @@ -747,6 +766,9 @@ mod justify_content_row_min_width_and_margin; mod justify_content_row_space_around; mod justify_content_row_space_between; mod justify_content_row_space_evenly; +mod leaf_padding_border_overrides_max_size; +mod leaf_padding_border_overrides_min_size; +mod leaf_padding_border_overrides_size; mod margin_and_flex_column; mod margin_and_flex_row; mod margin_and_stretch_column; @@ -790,6 +812,7 @@ mod measure_child_constraint; mod measure_child_constraint_padding_parent; mod measure_child_with_flex_grow; mod measure_child_with_flex_shrink; +mod measure_child_with_min_size_greater_than_available_space; mod measure_flex_basis_overrides_measure; mod measure_height_overrides_measure; mod measure_remeasure_child_after_growing; @@ -817,6 +840,11 @@ mod only_shrinkable_item_with_flex_basis_zero; mod overflow_cross_axis; mod overflow_main_axis; mod padding_align_end_child; +mod padding_border_overrides_max_size; +mod padding_border_overrides_min_size; +mod padding_border_overrides_size; +mod padding_border_overrides_size_flex_basis_0; +mod padding_border_overrides_size_flex_basis_0_growable; mod padding_center_child; mod padding_container_match_child; mod padding_flex_child; @@ -849,6 +877,7 @@ mod percentage_position_bottom_right; mod percentage_position_left_top; mod percentage_size_based_on_parent_inner_size; mod percentage_size_of_flex_basis; +mod percentage_sizes_should_not_prevent_flex_shrinking; mod percentage_width_height; mod percentage_width_height_undefined_parent_size; mod position_root_with_rtl_should_position_withoutdirection; diff --git a/tests/generated/padding_border_overrides_max_size.rs b/tests/generated/padding_border_overrides_max_size.rs new file mode 100644 index 000000000..205073386 --- /dev/null +++ b/tests/generated/padding_border_overrides_max_size.rs @@ -0,0 +1,43 @@ +#[test] +fn padding_border_overrides_max_size() { + 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 { + max_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy.new_with_children(taffy::style::Style { ..Default::default() }, &[node0]).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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 22f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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); +} diff --git a/tests/generated/padding_border_overrides_min_size.rs b/tests/generated/padding_border_overrides_min_size.rs new file mode 100644 index 000000000..6b59e23db --- /dev/null +++ b/tests/generated/padding_border_overrides_min_size.rs @@ -0,0 +1,43 @@ +#[test] +fn padding_border_overrides_min_size() { + 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 { + min_size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(0f32), + height: taffy::style::Dimension::Points(0f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy.new_with_children(taffy::style::Style { ..Default::default() }, &[node0]).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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 22f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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); +} diff --git a/tests/generated/padding_border_overrides_size.rs b/tests/generated/padding_border_overrides_size.rs new file mode 100644 index 000000000..627b3e968 --- /dev/null +++ b/tests/generated/padding_border_overrides_size.rs @@ -0,0 +1,43 @@ +#[test] +fn padding_border_overrides_size() { + 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(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy.new_with_children(taffy::style::Style { ..Default::default() }, &[node0]).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, 22f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 22f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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); +} diff --git a/tests/generated/padding_border_overrides_size_flex_basis_0.rs b/tests/generated/padding_border_overrides_size_flex_basis_0.rs new file mode 100644 index 000000000..4df1dc66c --- /dev/null +++ b/tests/generated/padding_border_overrides_size_flex_basis_0.rs @@ -0,0 +1,59 @@ +#[test] +fn padding_border_overrides_size_flex_basis_0() { + 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 { + flex_basis: taffy::style::Dimension::Points(0f32), + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node1 = taffy + .new_leaf(taffy::style::Style { + flex_basis: taffy::style::Dimension::Points(0f32), + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy.new_with_children(taffy::style::Style { ..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, 34f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 34f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 22f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 22f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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, 0f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, size.width); + assert_eq!(size.height, 12f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 12f32, size.height); + assert_eq!(location.x, 22f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 22f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, location.y); +} diff --git a/tests/generated/padding_border_overrides_size_flex_basis_0_growable.rs b/tests/generated/padding_border_overrides_size_flex_basis_0_growable.rs new file mode 100644 index 000000000..5a1b4fadf --- /dev/null +++ b/tests/generated/padding_border_overrides_size_flex_basis_0_growable.rs @@ -0,0 +1,61 @@ +#[test] +fn padding_border_overrides_size_flex_basis_0_growable() { + 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 { + flex_grow: 1f32, + flex_basis: taffy::style::Dimension::Points(0f32), + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + padding: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(8f32), + right: taffy::style::LengthPercentage::Points(4f32), + top: taffy::style::LengthPercentage::Points(2f32), + bottom: taffy::style::LengthPercentage::Points(6f32), + }, + border: taffy::geometry::Rect { + left: taffy::style::LengthPercentage::Points(7f32), + right: taffy::style::LengthPercentage::Points(3f32), + top: taffy::style::LengthPercentage::Points(1f32), + bottom: taffy::style::LengthPercentage::Points(5f32), + }, + ..Default::default() + }) + .unwrap(); + let node1 = taffy + .new_leaf(taffy::style::Style { + flex_grow: 1f32, + flex_basis: taffy::style::Dimension::Points(0f32), + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(12f32), + height: taffy::style::Dimension::Points(12f32), + }, + ..Default::default() + }) + .unwrap(); + let node = taffy.new_with_children(taffy::style::Style { ..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, 34f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 34f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 14f32, 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, 28f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 28f32, size.width); + assert_eq!(size.height, 14f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 14f32, 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, 6f32, "width of node {:?}. Expected {}. Actual {}", node1.data(), 6f32, size.width); + assert_eq!(size.height, 12f32, "height of node {:?}. Expected {}. Actual {}", node1.data(), 12f32, size.height); + assert_eq!(location.x, 28f32, "x of node {:?}. Expected {}. Actual {}", node1.data(), 28f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node1.data(), 0f32, location.y); +} diff --git a/tests/generated/percentage_sizes_should_not_prevent_flex_shrinking.rs b/tests/generated/percentage_sizes_should_not_prevent_flex_shrinking.rs new file mode 100644 index 000000000..9864cf8e2 --- /dev/null +++ b/tests/generated/percentage_sizes_should_not_prevent_flex_shrinking.rs @@ -0,0 +1,48 @@ +#[test] +fn percentage_sizes_should_not_prevent_flex_shrinking() { + use slotmap::Key; + #[allow(unused_imports)] + use taffy::{layout::Layout, prelude::*}; + let mut taffy = taffy::Taffy::new(); + let node00 = taffy.new_leaf(taffy::style::Style { ..Default::default() }).unwrap(); + let node0 = taffy + .new_with_children( + taffy::style::Style { + size: taffy::geometry::Size { width: taffy::style::Dimension::Percent(1.2f32), height: auto() }, + ..Default::default() + }, + &[node00], + ) + .unwrap(); + let node = taffy + .new_with_children( + taffy::style::Style { + size: taffy::geometry::Size { + width: taffy::style::Dimension::Points(200f32), + height: taffy::style::Dimension::Points(200f32), + }, + ..Default::default() + }, + &[node0], + ) + .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, 200f32, "width of node {:?}. Expected {}. Actual {}", node.data(), 200f32, size.width); + assert_eq!(size.height, 200f32, "height of node {:?}. Expected {}. Actual {}", node.data(), 200f32, 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, 200f32, "width of node {:?}. Expected {}. Actual {}", node0.data(), 200f32, size.width); + assert_eq!(size.height, 200f32, "height of node {:?}. Expected {}. Actual {}", node0.data(), 200f32, 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(node00).unwrap(); + assert_eq!(size.width, 0f32, "width of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, size.width); + assert_eq!(size.height, 200f32, "height of node {:?}. Expected {}. Actual {}", node00.data(), 200f32, size.height); + assert_eq!(location.x, 0f32, "x of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.x); + assert_eq!(location.y, 0f32, "y of node {:?}. Expected {}. Actual {}", node00.data(), 0f32, location.y); +} diff --git a/tests/relayout.rs b/tests/relayout.rs index 067bd2b9a..1f4695127 100644 --- a/tests/relayout.rs +++ b/tests/relayout.rs @@ -1,11 +1,11 @@ -use taffy::style::{AvailableSpace, Dimension}; +use taffy::prelude::*; #[test] fn relayout() { let mut taffy = taffy::Taffy::new(); let node1 = taffy .new_leaf(taffy::style::Style { - size: taffy::geometry::Size { width: Dimension::Points(8f32), height: Dimension::Points(80f32) }, + size: taffy::geometry::Size { width: points(8.0), height: points(80.0) }, ..Default::default() }) .unwrap(); @@ -55,3 +55,232 @@ fn relayout() { assert_eq!(taffy.layout(node1).unwrap().location, initial1); } } + +#[test] +fn toggle_root_display_none() { + let hidden_style = Style { + display: Display::None, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + let flex_style = Style { + display: Display::Flex, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + // Setup + let mut taffy = taffy::Taffy::new(); + let node = taffy.new_leaf(hidden_style.clone()).unwrap(); + + // Layout 1 (None) + taffy.compute_layout(node, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(node).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); + + // Layout 2 (Flex) + taffy.set_style(node, flex_style).unwrap(); + taffy.compute_layout(node, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(node).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 100.0); + assert_eq!(layout.size.height, 100.0); + + // Layout 3 (None) + taffy.set_style(node, hidden_style).unwrap(); + taffy.compute_layout(node, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(node).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); +} + +#[test] +fn toggle_flex_child_display_none() { + let hidden_style = Style { + display: Display::None, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + let flex_style = Style { + display: Display::Flex, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + // Setup + let mut taffy = taffy::Taffy::new(); + let node = taffy.new_leaf(hidden_style.clone()).unwrap(); + let root = taffy.new_with_children(flex_style.clone(), &[node]).unwrap(); + + // Layout 1 (None) + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(node).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); + + // Layout 2 (Flex) + taffy.set_style(node, flex_style).unwrap(); + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(node).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 100.0); + assert_eq!(layout.size.height, 100.0); + + // Layout 3 (None) + taffy.set_style(node, hidden_style).unwrap(); + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(node).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); +} + +#[test] +fn toggle_flex_container_display_none() { + let hidden_style = Style { + display: Display::None, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + let flex_style = Style { + display: Display::Flex, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + // Setup + let mut taffy = taffy::Taffy::new(); + let node = taffy.new_leaf(hidden_style.clone()).unwrap(); + let root = taffy.new_with_children(hidden_style.clone(), &[node]).unwrap(); + + // Layout 1 (None) + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(root).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); + + // Layout 2 (Flex) + taffy.set_style(root, flex_style).unwrap(); + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(root).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 100.0); + assert_eq!(layout.size.height, 100.0); + + // Layout 3 (None) + taffy.set_style(root, hidden_style).unwrap(); + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(root).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); +} + +#[test] +fn toggle_grid_child_display_none() { + let hidden_style = Style { + display: Display::None, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + let grid_style = Style { + display: Display::Grid, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + // Setup + let mut taffy = taffy::Taffy::new(); + let node = taffy.new_leaf(hidden_style.clone()).unwrap(); + let root = taffy.new_with_children(grid_style.clone(), &[node]).unwrap(); + + // Layout 1 (None) + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(node).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); + + // Layout 2 (Flex) + taffy.set_style(node, grid_style).unwrap(); + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(node).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 100.0); + assert_eq!(layout.size.height, 100.0); + + // Layout 3 (None) + taffy.set_style(node, hidden_style).unwrap(); + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(node).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); +} + +#[test] +fn toggle_grid_container_display_none() { + let hidden_style = Style { + display: Display::None, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + let grid_style = Style { + display: Display::Grid, + size: Size { width: points(100.0), height: points(100.0) }, + ..Default::default() + }; + + // Setup + let mut taffy = taffy::Taffy::new(); + let node = taffy.new_leaf(hidden_style.clone()).unwrap(); + let root = taffy.new_with_children(hidden_style.clone(), &[node]).unwrap(); + + // Layout 1 (None) + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(root).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); + + // Layout 2 (Flex) + taffy.set_style(root, grid_style).unwrap(); + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(root).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 100.0); + assert_eq!(layout.size.height, 100.0); + + // Layout 3 (None) + taffy.set_style(root, hidden_style).unwrap(); + taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(); + let layout = taffy.layout(root).unwrap(); + assert_eq!(layout.location.x, 0.0); + assert_eq!(layout.location.y, 0.0); + assert_eq!(layout.size.width, 0.0); + assert_eq!(layout.size.height, 0.0); +}