Update 0.3.x for 0.3.11 (#455)
* Fix layout of direct flex children with `display:none` set (#380)
* Add test for toggling display:none
* Add test for toggling display:none on a flexbox child
* Fix layout direct flex children with `display:none` set
* Add test for toggling display:none on flexbox container
* Fix setting display:none on a grid child (#382)
* Prepare for 0.3.5 release (#381)
* Prepare for 0.3.5 release
* Add grid PR to release notes
* Ignore align_content in non-wrapping flexbox containers (#383)
* Add tests for bevyengine/bevy#7976
* Simplify code in compute_constants
* Ignore align_contents if flex_wrap is set to no_wrap
* Remove commented out code
* Prepare for v0.3.6 release (#384)
* Use mutable slice rather mutable vec parameter
* Reduce style accesses (#386)
* Use cached flex_grow and flex_shrink values when resolving flexible lengths
* Cache auto margins on FlexItem struct
* Use constants.is_wrap instead of re-resolving style
* Use cached align_content value rather than re-resolving style
* Cache justify_content style in AlgoConstants
* Add failing tests for borders flooring node size
* Add failing tests for padding flooring node size
* Fix divide by zero in main size determination
* Add seperate leaf and flexbox tests for padding/border flooring node size
* Fix padding/border flooring leaf node size
* Fix flexbox children being floored by padding/border
* Combine padding and border tests + make edge dimensions uneven
* Add padding/border floor absolute child size
* Add padding/border floor node size tests for grid
* Add grid container test for padding/border flooring node size
* Fix padding/border flooring size of absolutely positioned children
* Rename grid padding/border tests so that they are all located together
* Make padding/border floor node size for grid children
* Make padding/border floor node size for grid containers
* Apply aspect ratio to leaf nodes whose size is determined by padding/border sum
* Add test for padding/border not affecting flex basis
* Convert flex basis determination to use break from block
* Add test for flex-basis 0 with flex grow
* Floor flex-basis limits by preferred size style value when determining flex container main size
* Floor outer flex-basis by padding_border sum (floors inner flex-basis at 0)
* Remove commented out code
* Add missing 0
* Test cases for bevyengine/bevy#8017 and Taffy #387
* Prevent percentage sizes from contributing a flex item's min-content size
* Prepare for 0.3.7 release (#389)
* Prepare for 0.3.7 release
* Fix duplicate content in the changelog
* Fix markdown lint
* Upgrade to better Github Actions for faster and better maintained CI (#390)
* Use taiki-e/install-action for installing cargo-deny
* Update CI to use dtolnay/rust-toolchain action
* Enable CI for 0.3.x branch
* Fix documentation CI
* Dummy Cargo.toml change
* Add fully reduced test case for #387 (#391)
* Fix wrapping nodes generating an incorrect min-content size (#395)
* Add tests for bevyengine/bevy#8082
* Debug log parent size
* Pass correct cross-axis parent_size/available_space when computing a flex item's min-content contribution
* Prepare for 0.3.8 release (#396)
* Don't allow cached results to be used for sizings with greater available space (#397)
* Don't allow cached results to be used for sizings with greater available space
* Update caching tests to use tree 100 nodes deep (relax permitted measure count to 7)
* Prepare for 0.3.9 release (#398)
* Prepare for 0.3.9 release
* Add bevyengine/bevy#8124 to release notes
* Allow multiple syn versions
* Tree creation benchmarks (#401)
* Add tree creation benchmarks
* Rename allocation benchmark to tree_creation
* Update rstest requirement from 0.16.0 to 0.17.0 (#402)
Updates the requirements on [rstest](https://github.com/la10736/rstest) to permit the latest version.
- [Release notes](https://github.com/la10736/rstest/releases)
- [Changelog](https://github.com/la10736/rstest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/la10736/rstest/compare/0.16.0...0.17.0)
---
updated-dependencies:
- dependency-name: rstest
dependency-type: direct:production
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Update syn requirement from 1.0.7 to 2.0.4 (#403)
Updates the requirements on [syn](https://github.com/dtolnay/syn) to permit the latest version.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/1.0.7...2.0.4)
---
updated-dependencies:
- dependency-name: syn
dependency-type: direct:production
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Fix: available space in the presence of a min width (#407)
* Add `with_main` and `with_cross` methods to Size
* Add test for min_width > available_space
* Clamp available cross space by min/max height when computing flex basis
* Clamp available cross space by min/max size when computing hypothetical cross size
* Bump measure func call counts to 8
* Prepare for 0.3.10 release (#411)
* Fix import lints (#416)
(cherry picked from commit 55225737802b3e2a0e0ce6194c9fce2603a18a30)
* Add caching to CI (#418)
* Optimise flexbox layouts with min/max sizes (#413)
* Remove 2-pass min/max code path + implement main size min/max clamping within determine_container_main_size method
* Fix typo in flex_grow_within_constrained_min_max_column test
* Implement cross-size min/max clamping inline in algorithm
* Remove debug log
* Remove commented code
* Prepare for 0.3.11 release (#419)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Andreas Weibye <13300393+Weibye@users.noreply.github.com>
Co-authored-by: TimJentzsch <commits@timjen.net>
1cc9406849daf4163f4c7780c73f58409c79b7ae · ruwaq Nico Burns · 2023-04-19T15:10:51Z (3 wata ñawpaq) · tayta 1e4b80d7c · kay commitpi sach'ata qhaway
Semántico sayk'uy · 96
benches/helpers/yoga_helpers.rs
src/compute/grid/alignment.rs
src/compute/grid/mod.rs
ukhunpi t'ikrakurqan fn compute pub
tests/generated/absolute_padding_border_overrides_max_size.rs
tests/generated/absolute_padding_border_overrides_size.rs
tests/generated/bevy_issue_7976_3_level.rs
tests/generated/bevy_issue_7976_4_level.rs
tests/generated/bevy_issue_7976_reduced.rs
tests/generated/bevy_issue_8017.rs
tests/generated/bevy_issue_8017_reduced.rs
tests/generated/bevy_issue_8082.rs
tests/generated/bevy_issue_8082_percent.rs
tests/generated/flex_grow_within_constrained_min_max_column.rs
tests/generated/grid_padding_border_overrides_container_max_size.rs
tests/generated/grid_padding_border_overrides_container_size.rs
tests/generated/grid_padding_border_overrides_max_size.rs
tests/generated/grid_padding_border_overrides_min_size.rs
tests/generated/grid_padding_border_overrides_size.rs
tests/generated/leaf_padding_border_overrides_max_size.rs
tests/generated/leaf_padding_border_overrides_min_size.rs
tests/generated/leaf_padding_border_overrides_size.rs
tests/generated/measure_child_with_min_size_greater_than_available_space.rs
tests/generated/padding_border_overrides_max_size.rs
tests/generated/padding_border_overrides_min_size.rs
tests/generated/padding_border_overrides_size.rs
tests/generated/padding_border_overrides_size_flex_basis_0.rs
tests/generated/padding_border_overrides_size_flex_basis_0_growable.rs
tests/generated/percentage_sizes_should_not_prevent_flex_shrinking.rs
71 qillqakuna · +2708 −427
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 <alice.i.cecile@gmail.com>",
"Johnathan Kelley <jkelleyrtp@gmail.com>",
]
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<T, N>(
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<DefaultKey, yg::Node>,
+ children: Vec<DefaultKey>,
+) -> 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<DefaultKey, yg::Node>,
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<Node> = (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<Node> =
+ (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<Option<f32>>,
/// The margin of this item
margin: Rect<f32>,
+ /// Whether each margin is an auto margin or not
+ margin_is_auto: Rect<bool>,
/// The padding of this item
padding: Rect<f32>,
/// 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<Option<f32>>,
+ /// The item's max_size style
+ max_size: Size<Option<f32>>,
/// The margin of this section
margin: Rect<f32>,
/// 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<JustifyContent>,
/// The border-box size of the node being laid out (if known)
node_outer_size: Size<Option<f32>>,
@@ -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<AvailableSpace>,
- flex_items: &mut Vec<FlexItem>,
+ 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<AvailableSpace>,
flex_items: &'a mut Vec<FlexItem>,
) -> Vec<FlexLine<'a>> {
- 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<FlexLine<'_>>,
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::<f32>();
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::<f32>();
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<f32>,
-) {
+fn resolve_flexible_lengths(line: &mut FlexLine, constants: &AlgoConstants, original_gap: Size<f32>) {
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<AvailableSpace>,
) {
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<Option<f32>>,
- constants: &AlgoConstants,
-) {
+fn calculate_cross_size(flex_lines: &mut [FlexLine], node_size: Size<Option<f32>>, 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<Option<f32>>, 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::<f32>() + 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::<f32>() + 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::<f32>();
- 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<Option<f32>>,
available_space: Size<AvailableSpace>,
run_mode: RunMode,
- sizing_mode: SizingMode,
) -> Option<SizeAndBaselines> {
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<T> Size<T> {
}
}
+ /// 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<LengthPercentageAuto> 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<f32> {
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<f32>) -> Option<f32> {
- 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<f32> {
- 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<f32>) -> Option<f32> {
- 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<f32> {
- 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root">
+ <div style="position:absolute;max-width: 12px; max-height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root">
+ <div style="position:absolute;width: 12px; height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="width: 200px; height: 200px; align-content: start">
+ <div style="min-width: 40px;min-height:40px;margin:5px;padding:5px;background-color:red">
+ <div style="width:100%;height:100%;padding:5px;background-color:green"></div>
+ </div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="width: 200px; height: 200px; align-content: start">
+ <div style="min-width: 40px;min-height:40px;margin:5px;padding:5px;background-color:red">
+ <div style="width:100%;height:100%;padding:5px;background-color:green">
+ <div></div>
+ </div>
+ </div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="height:200px;align-content: start">
+ <div style="width:40px;"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<script src="../scripts/gentest/test_helper.js"></script>
+<link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+<title>
+ Bevy #8017
+</title>
+</head>
+<body>
+
+<div id="test-root" style="display: flex; flex-direction: column; gap: 8px;width: 400px;height:400px;padding: 8px;">
+ <div style="display: flex; gap: 8px; width: 100%; height: 50%;">
+ <div style="width: 100%; height: 100%;"></div>
+ <div style="width: 100%; height: 100%;"></div>
+ </div>
+ <div style="display: flex; gap: 8px; width: 100%; height: 50%;">
+ <div style="width: 100%; height: 100%;"></div>
+ <div style="width: 100%; height: 100%;"></div>
+ </div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<script src="../scripts/gentest/test_helper.js"></script>
+<link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+<title>
+ Bevy #8017
+</title>
+</head>
+<body>
+
+<div id="test-root" style="flex-direction: column;width: 200px;height:400px;gap: 8px;">
+ <div style="height: 50%;">
+ <div></div>
+ </div>
+ <div style="height: 50%;">
+ <div></div>
+ </div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="width: 200px; height: 400px; align-content: center;justify-content: flex-start;align-items:stretch;flex-direction: column;">
+ <div style="flex-wrap: wrap;align-items:flex-start;align-content:center;justify-content: center;">
+ <div style="width: 50px; height: 50px;margin: 10px"></div>
+ <div style="width: 50px; height: 50px;margin: 10px"></div>
+ <div style="width: 50px; height: 50px;margin: 10px"></div>
+ <div style="width: 50px; height: 50px;margin: 10px"></div>
+ </div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="width: 200px; height: 400px; align-content: center;justify-content: flex-start;align-items:stretch;flex-direction: column;">
+ <div style="flex-wrap: wrap;align-items:flex-start;align-content:center;justify-content: center;width: 50%">
+ <div style="width: 50px; height: 50px"></div>
+ <div style="width: 50px; height: 50px"></div>
+ <div style="width: 50px; height: 50px"></div>
+ <div style="width: 50px; height: 50px"></div>
+ </div>
+</div>
+
+</body>
+</html>
\ 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 @@
<head/>
<body>
-<div id="test-root" style="min-height: 100px; max-height: 200px flex-direction: column;">
+<div id="test-root" style="min-height: 100px; max-height: 200px; flex-direction: column;">
<div style="flex-grow:1;"></div>
<div style="height: 50px;"></div>
</div>
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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="display: grid;max-width: 12px; max-height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red">
+ <div></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="display: grid;width: 12px; height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red solid red">
+ <div></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="display:grid">
+ <div style="max-width: 12px; max-height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="display: grid">
+ <div style="min-width: 0px; min-height: 0px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="display: grid">
+ <div style="width: 12px; height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="max-width: 12px; max-height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="min-width: 0px; min-height: 0px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="width: 12px; height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root" style="display: flex; flex-direction: column; width: 100px;">
+ <div style="min-width: 200px;">HHHHHHHH​HHHHHHHH</div>
+</div>
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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root">
+ <div style="max-width: 12px; max-height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root">
+ <div style="min-width: 0px; min-height: 0px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root">
+ <div style="width: 12px; height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root">
+ <div style="flex-basis: 0;width: 12px; height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+ <div style="flex-basis: 0;width: 12px; height: 12px"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="../scripts/gentest/test_helper.js"></script>
+ <link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+ <title>
+ Test description
+ </title>
+<head/>
+<body>
+
+<div id="test-root">
+ <div style="flex-basis: 0;flex-grow: 1;width: 12px; height: 12px;padding:2px 4px 6px 8px;border-width: 1px 3px 5px 7px;border-style:solid;border-color:red"></div>
+ <div style="flex-basis: 0;flex-grow: 1;width: 12px; height: 12px"></div>
+</div>
+
+</body>
+</html>
\ 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 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<script src="../scripts/gentest/test_helper.js"></script>
+<link rel="stylesheet" type="text/css" href="../scripts/gentest/test_base_style.css">
+<title>
+ Bevy #8017
+</title>
+</head>
+<body>
+
+<div id="test-root" style="width: 200px;height:200px">
+ <div style="width: 120%;">
+ <div></div>
+ </div>
+</div>
+
+</body>
+</html>
\ 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<T: Copy>(items: [T; 4]) -> Rect<T> {
}
#[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);
+}