Add comparative benchmarks with Taffy 0.3 (#572)
* Taffy 0.3 flexbox benchmarks
* Add compute_layout method to BuildTree trait
* Simplify benchmarks with macros
c16e2b68359c50134de460348f6f02a5fb10a7e6 · por Nico Burns · (hace 2 años) · padre d4374b93f · ver el árbol en este commit
Delta semántico · 47
benches/benches/flexbox.rs
benches/src/taffy_03_helpers.rs
benches/src/taffy_helpers.rs
benches/src/yoga_helpers.rs
diff --git a/benches/Cargo.toml b/benches/Cargo.toml
index b83939ce5..3baa99c7a 100644
--- a/benches/Cargo.toml
+++ b/benches/Cargo.toml
@@ -14,9 +14,10 @@ license = "MIT"
[dependencies]
criterion = "0.5"
-taffy = { path = ".." }
rand = { version = "0.8.5" }
rand_chacha = "0.3.1"
+taffy = { path = ".." }
+taffy_03 = { package = "taffy", version = "0.3", optional = true }
yoga = { version = "0.4.0", optional = true }
ordered-float = { version = "3.4.0", optional = true }
slotmap = { version = "1.0.6", optional = true }
@@ -24,6 +25,7 @@ slotmap = { version = "1.0.6", optional = true }
[features]
yoga = ["dep:yoga", "dep:slotmap", "dep:ordered-float"]
yoga-super-deep = ["yoga"]
+taffy03 = ["dep:taffy_03"]
small = []
large = []
diff --git a/benches/benches/flexbox.rs b/benches/benches/flexbox.rs
index a2c532149..25d4838b9 100644
--- a/benches/benches/flexbox.rs
+++ b/benches/benches/flexbox.rs
@@ -7,10 +7,10 @@ use taffy::style::Style as TaffyStyle;
use taffy_benchmarks::{BuildTreeExt, FixedStyleGenerator, GenStyle, TaffyTreeBuilder};
+#[cfg(feature = "taffy03")]
+use taffy_benchmarks::taffy_03_helpers::Taffy03TreeBuilder;
#[cfg(feature = "yoga")]
-use taffy_benchmarks::yoga_helpers;
-#[cfg(feature = "yoga")]
-use yoga_helpers::{yg, YogaTreeBuilder};
+use taffy_benchmarks::yoga_helpers::YogaTreeBuilder;
fn random_dimension(rng: &mut impl Rng) -> Dimension {
match rng.gen_range(0.0..=1.0) {
@@ -19,6 +19,8 @@ fn random_dimension(rng: &mut impl Rng) -> Dimension {
_ => Dimension::Percent(rng.gen_range(0.0..1.0)),
}
}
+
+#[derive(Clone)]
pub struct RandomStyleGenerator;
impl GenStyle<TaffyStyle> for RandomStyleGenerator {
fn create_leaf_style(&mut self, rng: &mut impl Rng) -> TaffyStyle {
@@ -29,112 +31,78 @@ impl GenStyle<TaffyStyle> for RandomStyleGenerator {
}
}
-/// A deep tree that matches the shape and styling that yoga use on their benchmarks
-fn build_flat_hierarchy<G: GenStyle<TaffyStyle>, TreeBuilder: BuildTreeExt<G>>(
- target_node_count: u32,
- style_generator: impl FnOnce() -> G,
-) -> (TreeBuilder::Tree, TreeBuilder::Node) {
- let tree_builder = TreeBuilder::new(style_generator());
- tree_builder.build_flat_hierarchy(target_node_count)
-}
-
-/// A deep tree that matches the shape and styling that yoga use on their benchmarks
-fn build_deep_hierarchy<G: GenStyle<TaffyStyle>, TreeBuilder: BuildTreeExt<G>>(
- node_count: u32,
- branching_factor: u32,
- style_generator: impl FnOnce() -> G,
-) -> (TreeBuilder::Tree, TreeBuilder::Node) {
- let tree_builder = TreeBuilder::new(style_generator());
- tree_builder.build_deep_hierarchy(node_count, branching_factor)
+macro_rules! run_benchmark {
+ ($TreeBuilder: ty, $tree_builder_name: literal, $benchmark_name: expr, $group: ident, $builder: ident, $params: expr, $generate_style: expr, $generate_tree: expr) => {
+ let benchmark_id = BenchmarkId::new(format!("{} {}", $tree_builder_name, $benchmark_name), $params);
+ $group.bench_with_input(benchmark_id, $params, |b, _params| {
+ b.iter_batched(
+ || -> $TreeBuilder {
+ let mut $builder = <$TreeBuilder>::new($generate_style());
+ $generate_tree;
+ $builder
+ },
+ |mut builder| builder.compute_layout(None, None),
+ criterion::BatchSize::SmallInput,
+ )
+ });
+ };
}
-/// A deep tree that matches the shape and styling that yoga use on their benchmarks
-fn build_super_deep_hierarchy<G: GenStyle<TaffyStyle>, TreeBuilder: BuildTreeExt<G>>(
- depth: u32,
- nodes_per_level: u32,
- style_generator: impl FnOnce() -> G,
-) -> (TreeBuilder::Tree, TreeBuilder::Node) {
- let tree_builder = TreeBuilder::new(style_generator());
- tree_builder.build_super_deep_hierarchy(depth, nodes_per_level)
-}
+macro_rules! benchmark_each_library {
+ ($benchmark_name: expr, $group: ident, $builder: ident, $params: expr, $generate_style: expr, $generate_tree: expr) => {
+ #[cfg(feature = "yoga")]
+ run_benchmark!(YogaTreeBuilder<_, _>, "Yoga", $benchmark_name, $group, $builder, $params, $generate_style, $generate_tree);
+ #[cfg(feature = "taffy03")]
+ run_benchmark!(Taffy03TreeBuilder<_, _>, "Taffy 0.3", $benchmark_name, $group, $builder, $params, $generate_style, $generate_tree);
-/// A deep tree that matches the shape and styling that yoga use on their benchmarks
-fn build_huge_nested_hierarchy<G: GenStyle<TaffyStyle>, TreeBuilder: BuildTreeExt<G>>(
- node_count: u32,
- branching_factor: u32,
- style_generator: impl FnOnce() -> G,
-) -> (TreeBuilder::Tree, TreeBuilder::Node) {
- let tree_builder = TreeBuilder::new(style_generator());
- tree_builder.build_deep_hierarchy(node_count, branching_factor)
+ run_benchmark!(TaffyTreeBuilder<_, _>, "Taffy 0.4", $benchmark_name, $group, $builder, $params, $generate_style, $generate_tree);
+ };
}
fn huge_nested_benchmarks(c: &mut Criterion) {
- let mut group = c.benchmark_group("yoga 'huge nested'");
- let style = Style { size: length(10.0), flex_grow: 1.0, ..Default::default() };
- let style_gen = || FixedStyleGenerator(style.clone());
- for node_count in [
+ let node_counts = [
#[cfg(feature = "small")]
1_000u32,
10_000,
#[cfg(feature = "large")]
100_000,
- ]
- .iter()
- {
- #[cfg(feature = "yoga")]
- group.bench_with_input(BenchmarkId::new("Yoga", node_count), node_count, |b, &node_count| {
- b.iter_batched(
- || build_huge_nested_hierarchy::<_, YogaTreeBuilder<_, _>>(node_count, 10, style_gen),
- |(mut tree, root)| {
- tree[root].calculate_layout(f32::INFINITY, f32::INFINITY, yg::Direction::LTR);
- },
- criterion::BatchSize::SmallInput,
- )
- });
- group.bench_with_input(BenchmarkId::new("Taffy", node_count), node_count, |b, &node_count| {
- b.iter_batched(
- || build_huge_nested_hierarchy::<_, TaffyTreeBuilder<_, _>>(node_count, 10, style_gen),
- |(mut taffy, root)| taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(),
- criterion::BatchSize::SmallInput,
- )
- });
+ ];
+
+ let mut group = c.benchmark_group("yoga 'huge nested'");
+ let style = Style { size: length(10.0), flex_grow: 1.0, ..Default::default() };
+ for node_count in node_counts.iter() {
+ benchmark_each_library!(
+ "",
+ group,
+ builder,
+ node_count,
+ || FixedStyleGenerator(style.clone()),
+ builder.build_deep_hierarchy(*node_count, 10)
+ );
}
group.finish();
}
fn wide_benchmarks(c: &mut Criterion) {
- // Decrease sample size, because the tasks take longer
- let mut group = c.benchmark_group("Wide tree");
- group.sample_size(10);
- for node_count in [
+ let node_counts = [
#[cfg(feature = "small")]
1_000u32,
10_000,
#[cfg(feature = "large")]
100_000,
- ]
- .iter()
- {
- #[cfg(feature = "yoga")]
- let benchmark_id = BenchmarkId::new(format!("Yoga (2-level hierarchy)"), node_count);
- #[cfg(feature = "yoga")]
- group.bench_with_input(benchmark_id, node_count, |b, &node_count| {
- b.iter_batched(
- || build_flat_hierarchy::<_, YogaTreeBuilder<_, _>>(node_count, || RandomStyleGenerator),
- |(mut tree, root)| {
- tree[root].calculate_layout(f32::INFINITY, f32::INFINITY, yg::Direction::LTR);
- },
- criterion::BatchSize::SmallInput,
- )
- });
- let benchmark_id = BenchmarkId::new(format!("Taffy (2-level hierarchy)"), node_count);
- group.bench_with_input(benchmark_id, node_count, |b, &node_count| {
- b.iter_batched(
- || build_flat_hierarchy::<_, TaffyTreeBuilder<_, _>>(node_count, || RandomStyleGenerator),
- |(mut taffy, root)| taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(),
- criterion::BatchSize::SmallInput,
- )
- });
+ ];
+
+ let mut group = c.benchmark_group("Wide tree");
+ group.sample_size(10); // Decrease sample size, because the tasks take longer
+ for node_count in node_counts.iter() {
+ benchmark_each_library!(
+ "(2-level hierarchy)",
+ group,
+ builder,
+ node_count,
+ || RandomStyleGenerator,
+ builder.build_flat_hierarchy(*node_count)
+ );
}
group.finish();
}
@@ -150,64 +118,52 @@ fn deep_random_benchmarks(c: &mut Criterion) {
(100_000, "(17-level hierarchy)"),
];
for (node_count, label) in benches.iter() {
- #[cfg(feature = "yoga")]
- group.bench_with_input(BenchmarkId::new(format!("Yoga {label}"), node_count), node_count, |b, &node_count| {
- b.iter_batched(
- || build_deep_hierarchy::<_, YogaTreeBuilder<_, _>>(node_count, 2, || RandomStyleGenerator),
- |(mut tree, root)| {
- tree[root].calculate_layout(f32::INFINITY, f32::INFINITY, yg::Direction::LTR);
- },
- criterion::BatchSize::SmallInput,
- )
- });
- group.bench_with_input(BenchmarkId::new(format!("Taffy {label}"), node_count), node_count, |b, &node_count| {
- b.iter_batched(
- || build_deep_hierarchy::<_, TaffyTreeBuilder<_, _>>(node_count, 2, || RandomStyleGenerator),
- |(mut taffy, root)| taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(),
- criterion::BatchSize::SmallInput,
- )
- });
+ benchmark_each_library!(
+ label,
+ group,
+ builder,
+ node_count,
+ || RandomStyleGenerator,
+ builder.build_deep_hierarchy(*node_count, 2)
+ );
}
group.finish();
}
fn deep_auto_benchmarks(c: &mut Criterion) {
- // Decrease sample size, because the tasks take longer
- let mut group = c.benchmark_group("Deep tree (auto size)");
- group.sample_size(10);
- let style = Style { flex_grow: 1.0, margin: length(10.0), ..Default::default() };
- let style_gen = || FixedStyleGenerator(style.clone());
let benches = [
(4000, "(12-level hierarchy)"),
(10_000, "(14-level hierarchy)"),
#[cfg(feature = "large")]
(100_000, "(17-level hierarchy)"),
];
+ let style = Style { flex_grow: 1.0, margin: length(10.0), ..Default::default() };
+
+ let mut group = c.benchmark_group("Deep tree (auto size)");
+ group.sample_size(10); // Decrease sample size, because the tasks take longer
for (node_count, label) in benches.iter() {
- #[cfg(feature = "yoga")]
- group.bench_with_input(BenchmarkId::new(format!("Yoga {label}"), node_count), node_count, |b, &node_count| {
- b.iter_batched(
- || build_deep_hierarchy::<_, YogaTreeBuilder<_, _>>(node_count, 2, style_gen),
- |(mut tree, root)| {
- tree[root].calculate_layout(f32::INFINITY, f32::INFINITY, yg::Direction::LTR);
- },
- criterion::BatchSize::SmallInput,
- )
- });
- group.bench_with_input(BenchmarkId::new(format!("Taffy {label}"), node_count), node_count, |b, &node_count| {
- b.iter_batched(
- || build_deep_hierarchy::<_, TaffyTreeBuilder<_, _>>(node_count, 2, style_gen),
- |(mut taffy, root)| taffy.compute_layout(root, Size::MAX_CONTENT).unwrap(),
- criterion::BatchSize::SmallInput,
- )
- });
+ benchmark_each_library!(
+ label,
+ group,
+ builder,
+ node_count,
+ || FixedStyleGenerator(style.clone()),
+ builder.build_deep_hierarchy(*node_count, 2)
+ );
}
group.finish();
}
fn super_deep_benchmarks(c: &mut Criterion) {
- let mut group = c.benchmark_group("super deep");
- group.sample_size(10);
+ let benches = [
+ #[cfg(feature = "small")]
+ 50u32,
+ 100,
+ #[cfg(feature = "large")]
+ 200,
+ ];
+
+ #[derive(Clone)]
struct SuperDeepStyleGen;
impl GenStyle<TaffyStyle> for SuperDeepStyleGen {
fn create_leaf_style(&mut self, _rng: &mut impl Rng) -> TaffyStyle {
@@ -219,40 +175,45 @@ fn super_deep_benchmarks(c: &mut Criterion) {
self.create_leaf_style(rng)
}
}
- for depth in [
- #[cfg(feature = "small")]
- 50u32,
- 100,
- #[cfg(feature = "large")]
- 200,
- ]
- .iter()
- {
+
+ let mut group = c.benchmark_group("super deep");
+ group.sample_size(10);
+
+ for depth in benches.iter() {
// Yoga is particularly slow at these benchmarks, so we gate them behind a separate feature flag
#[cfg(all(feature = "yoga", feature = "yoga-super-deep"))]
- group.bench_with_input(BenchmarkId::new("Yoga", depth), depth, |b, &depth| {
- b.iter_batched(
- || build_super_deep_hierarchy::<_, YogaTreeBuilder<_, _>>(depth, 3, || SuperDeepStyleGen),
- |(mut tree, root)| {
- tree[root].calculate_layout(800., 800., yg::Direction::LTR);
- },
- criterion::BatchSize::SmallInput,
- )
- });
- group.bench_with_input(BenchmarkId::new("Taffy", depth), depth, |b, &depth| {
- b.iter_batched(
- || build_super_deep_hierarchy::<_, TaffyTreeBuilder<_, _>>(depth, 3, || SuperDeepStyleGen),
- |(mut taffy, root)| {
- taffy
- .compute_layout(
- root,
- Size { width: AvailableSpace::Definite(800.), height: AvailableSpace::Definite(800.) },
- )
- .unwrap()
- },
- criterion::BatchSize::SmallInput,
- )
- });
+ run_benchmark!(
+ YogaTreeBuilder<_,_>,
+ "Yoga",
+ "",
+ group,
+ builder,
+ depth,
+ || SuperDeepStyleGen,
+ builder.build_super_deep_hierarchy(*depth, 3)
+ );
+ #[cfg(feature = "taffy03")]
+ run_benchmark!(
+ Taffy03TreeBuilder<_,_>,
+ "Taffy 0.3",
+ "",
+ group,
+ builder,
+ depth,
+ || SuperDeepStyleGen,
+ builder.build_super_deep_hierarchy(*depth, 3)
+ );
+
+ run_benchmark!(
+ TaffyTreeBuilder<_,_>,
+ "Taffy 0.4",
+ "",
+ group,
+ builder,
+ depth,
+ || SuperDeepStyleGen,
+ builder.build_super_deep_hierarchy(*depth, 3)
+ );
}
group.finish();
}
diff --git a/benches/src/lib.rs b/benches/src/lib.rs
index 6d67c6774..3f419540e 100644
--- a/benches/src/lib.rs
+++ b/benches/src/lib.rs
@@ -5,6 +5,9 @@
pub mod taffy_helpers;
pub use taffy_helpers::TaffyTreeBuilder;
+#[cfg(feature = "taffy03")]
+pub mod taffy_03_helpers;
+
#[cfg(feature = "yoga")]
pub mod yoga_helpers;
#[cfg(feature = "yoga")]
@@ -17,7 +20,7 @@ use taffy::style::Style as TaffyStyle;
pub const STANDARD_RNG_SEED: u64 = 12345;
-pub trait GenStyle<Style: Default> {
+pub trait GenStyle<Style: Default>: Clone {
fn create_leaf_style(&mut self, rng: &mut impl Rng) -> Style;
fn create_container_style(&mut self, rng: &mut impl Rng) -> Style;
fn create_root_style(&mut self, _rng: &mut impl Rng) -> Style {
@@ -25,6 +28,7 @@ pub trait GenStyle<Style: Default> {
}
}
+#[derive(Clone)]
pub struct FixedStyleGenerator(pub TaffyStyle);
impl GenStyle<TaffyStyle> for FixedStyleGenerator {
fn create_leaf_style(&mut self, _rng: &mut impl Rng) -> TaffyStyle {
@@ -35,12 +39,14 @@ impl GenStyle<TaffyStyle> for FixedStyleGenerator {
}
}
-pub trait BuildTree<R: Rng, G: GenStyle<TaffyStyle>>: Sized {
+pub trait BuildTree<R: Rng, G: GenStyle<TaffyStyle>> {
+ const NAME: &'static str;
type Tree;
type Node: Clone;
fn with_rng(rng: R, style_generator: G) -> Self;
+ fn compute_layout_inner(&mut self, available_width: Option<f32>, available_height: Option<f32>);
fn random_usize(&mut self, range: impl SampleRange<usize>) -> usize;
fn create_leaf_node(&mut self) -> Self::Node;
fn create_container_node(&mut self, children: &[Self::Node]) -> Self::Node;
@@ -69,9 +75,26 @@ pub trait BuildTree<R: Rng, G: GenStyle<TaffyStyle>>: Sized {
})
.collect()
}
+}
+
+pub trait BuildTreeExt<G: GenStyle<TaffyStyle>>: BuildTree<ChaCha8Rng, G> {
+ fn with_seed(seed: u64, style_generator: G) -> Self
+ where
+ Self: Sized,
+ {
+ let rng = ChaCha8Rng::seed_from_u64(seed);
+ Self::with_rng(rng, style_generator)
+ }
+
+ fn new(style_generator: G) -> Self
+ where
+ Self: Sized,
+ {
+ Self::with_seed(STANDARD_RNG_SEED, style_generator)
+ }
/// A helper function to recursively construct a deep tree
- fn build_super_deep_hierarchy(mut self, depth: u32, nodes_per_level: u32) -> (Self::Tree, Self::Node) {
+ fn build_super_deep_hierarchy(&mut self, depth: u32, nodes_per_level: u32) {
let mut children = Vec::with_capacity(nodes_per_level as usize);
for _ in 0..depth {
let node_with_children = self.create_container_node(&children);
@@ -83,18 +106,16 @@ pub trait BuildTree<R: Rng, G: GenStyle<TaffyStyle>>: Sized {
}
}
self.set_root_children(&children);
- self.into_tree_and_root()
}
/// A tree with a higher depth for a more realistic scenario
- fn build_deep_hierarchy(mut self, node_count: u32, branching_factor: u32) -> (Self::Tree, Self::Node) {
+ fn build_deep_hierarchy(&mut self, node_count: u32, branching_factor: u32) {
let children = self.build_deep_tree(node_count, branching_factor);
self.set_root_children(&children);
- self.into_tree_and_root()
}
/// A tree with many children that have shallow depth
- fn build_flat_hierarchy(mut self, target_node_count: u32) -> (Self::Tree, Self::Node) {
+ fn build_flat_hierarchy(&mut self, target_node_count: u32) {
let mut children = Vec::new();
while self.total_node_count() < target_node_count as usize {
@@ -105,23 +126,10 @@ pub trait BuildTree<R: Rng, G: GenStyle<TaffyStyle>>: Sized {
}
self.set_root_children(&children);
- self.into_tree_and_root()
- }
-}
-
-pub trait BuildTreeExt<G: GenStyle<TaffyStyle>>: BuildTree<ChaCha8Rng, G> {
- fn with_seed(seed: u64, style_generator: G) -> Self
- where
- Self: Sized,
- {
- let rng = ChaCha8Rng::seed_from_u64(seed);
- Self::with_rng(rng, style_generator)
}
- fn new(style_generator: G) -> Self
- where
- Self: Sized,
- {
- Self::with_seed(STANDARD_RNG_SEED, style_generator)
+ /// Compute layout given a viewport size
+ fn compute_layout(&mut self, available_width: Option<f32>, available_height: Option<f32>) {
+ self.compute_layout_inner(available_width, available_height);
}
}
diff --git a/benches/src/taffy_03_helpers.rs b/benches/src/taffy_03_helpers.rs
new file mode 100644
index 000000000..391e2f1f2
--- /dev/null
+++ b/benches/src/taffy_03_helpers.rs
@@ -0,0 +1,176 @@
+use rand::distributions::uniform::SampleRange;
+use rand::Rng;
+use rand_chacha::ChaCha8Rng;
+use taffy::style::Style as TaffyStyle;
+
+use super::{BuildTree, BuildTreeExt, GenStyle};
+
+pub struct Taffy03TreeBuilder<R: Rng, G: GenStyle<TaffyStyle>> {
+ rng: R,
+ style_generator: G,
+ tree: taffy_03::Taffy,
+ root: taffy_03::prelude::Node,
+}
+
+// Implement the BuildTree trait
+impl<R: Rng, G: GenStyle<TaffyStyle>> BuildTree<R, G> for Taffy03TreeBuilder<R, G> {
+ const NAME: &'static str = "Taffy 0.3";
+ type Tree = taffy_03::Taffy;
+ type Node = taffy_03::prelude::Node;
+
+ fn with_rng(mut rng: R, mut style_generator: G) -> Self {
+ let mut tree = taffy_03::Taffy::new();
+ let root = tree.new_leaf(convert_style(style_generator.create_root_style(&mut rng))).unwrap();
+ Taffy03TreeBuilder { rng, style_generator, tree, root }
+ }
+
+ fn compute_layout_inner(&mut self, available_width: Option<f32>, available_height: Option<f32>) {
+ let available_space =
+ taffy_03::geometry::Size { width: available_width.into(), height: available_height.into() };
+ self.tree.compute_layout(self.root, available_space).unwrap();
+ }
+
+ fn random_usize(&mut self, range: impl SampleRange<usize>) -> usize {
+ self.rng.gen_range(range)
+ }
+
+ fn create_leaf_node(&mut self) -> Self::Node {
+ let style = self.style_generator.create_leaf_style(&mut self.rng);
+ self.tree.new_leaf(convert_style(style)).unwrap()
+ }
+
+ fn create_container_node(&mut self, children: &[Self::Node]) -> Self::Node {
+ let style = self.style_generator.create_container_style(&mut self.rng);
+ self.tree.new_with_children(convert_style(style), children).unwrap()
+ }
+
+ fn total_node_count(&mut self) -> usize {
+ self.tree.total_node_count()
+ }
+
+ fn set_root_children(&mut self, children: &[Self::Node]) {
+ self.tree.set_children(self.root, children).unwrap();
+ }
+
+ fn into_tree_and_root(self) -> (Self::Tree, Self::Node) {
+ (self.tree, self.root)
+ }
+}
+
+impl<G: GenStyle<TaffyStyle>> BuildTreeExt<G> for Taffy03TreeBuilder<ChaCha8Rng, G> {}
+
+fn convert_style(style: taffy::style::Style) -> taffy_03::style::Style {
+ taffy_03::style::Style {
+ display: convert_display(style.display),
+ position: convert_position(style.position),
+ inset: convert_rect(style.inset, convert_length_percentage_auto),
+ margin: convert_rect(style.margin, convert_length_percentage_auto),
+ padding: convert_rect(style.padding, convert_length_percentage),
+ border: convert_rect(style.border, convert_length_percentage),
+ size: convert_size(style.size, convert_dimension),
+ min_size: convert_size(style.min_size, convert_dimension),
+ max_size: convert_size(style.max_size, convert_dimension),
+ aspect_ratio: style.aspect_ratio,
+ gap: convert_size(style.gap, convert_length_percentage),
+ // Aligment
+ align_items: None,
+ align_self: None,
+ justify_items: None,
+ justify_self: None,
+ align_content: None,
+ justify_content: None,
+ // Flexbox
+ flex_direction: convert_flex_direction(style.flex_direction),
+ flex_wrap: convert_flex_wrap(style.flex_wrap),
+ flex_grow: style.flex_grow,
+ flex_shrink: style.flex_shrink,
+ flex_basis: convert_dimension(style.flex_basis),
+ // Grid
+ grid_template_rows: Vec::new(),
+ grid_template_columns: Vec::new(),
+ grid_auto_rows: Vec::new(),
+ grid_auto_columns: Vec::new(),
+ grid_auto_flow: taffy_03::style::GridAutoFlow::Row,
+ grid_row: taffy_03::geometry::Line {
+ start: taffy_03::style::GridPlacement::Auto,
+ end: taffy_03::style::GridPlacement::Auto,
+ },
+ grid_column: taffy_03::geometry::Line {
+ start: taffy_03::style::GridPlacement::Auto,
+ end: taffy_03::style::GridPlacement::Auto,
+ },
+ }
+}
+
+fn convert_rect<T, U, F: Fn(T) -> U>(input: taffy::geometry::Rect<T>, map: F) -> taffy_03::geometry::Rect<U> {
+ taffy_03::geometry::Rect {
+ left: map(input.left),
+ right: map(input.right),
+ top: map(input.top),
+ bottom: map(input.bottom),
+ }
+}
+
+fn convert_size<T, U, F: Fn(T) -> U>(input: taffy::geometry::Size<T>, map: F) -> taffy_03::geometry::Size<U> {
+ taffy_03::geometry::Size { width: map(input.width), height: map(input.height) }
+}
+
+fn convert_point<T, U, F: Fn(T) -> U>(input: taffy::geometry::Point<T>, map: F) -> taffy_03::geometry::Point<U> {
+ taffy_03::geometry::Point { x: map(input.x), y: map(input.y) }
+}
+
+fn convert_dimension(input: taffy::style::Dimension) -> taffy_03::style::Dimension {
+ match input {
+ taffy::style::Dimension::Length(val) => taffy_03::style::Dimension::Points(val),
+ taffy::style::Dimension::Percent(val) => taffy_03::style::Dimension::Percent(val),
+ taffy::style::Dimension::Auto => taffy_03::style::Dimension::Auto,
+ }
+}
+
+fn convert_length_percentage_auto(input: taffy::style::LengthPercentageAuto) -> taffy_03::style::LengthPercentageAuto {
+ match input {
+ taffy::style::LengthPercentageAuto::Length(val) => taffy_03::style::LengthPercentageAuto::Points(val),
+ taffy::style::LengthPercentageAuto::Percent(val) => taffy_03::style::LengthPercentageAuto::Percent(val),
+ taffy::style::LengthPercentageAuto::Auto => taffy_03::style::LengthPercentageAuto::Auto,
+ }
+}
+
+fn convert_length_percentage(input: taffy::style::LengthPercentage) -> taffy_03::style::LengthPercentage {
+ match input {
+ taffy::style::LengthPercentage::Length(val) => taffy_03::style::LengthPercentage::Points(val),
+ taffy::style::LengthPercentage::Percent(val) => taffy_03::style::LengthPercentage::Percent(val),
+ }
+}
+
+fn convert_display(input: taffy::style::Display) -> taffy_03::style::Display {
+ match input {
+ taffy::style::Display::None => taffy_03::style::Display::None,
+ taffy::style::Display::Flex => taffy_03::style::Display::Flex,
+ taffy::style::Display::Grid => taffy_03::style::Display::Grid,
+ taffy::style::Display::Block => panic!("Block layout not implemented in taffy 0.3"),
+ }
+}
+
+fn convert_position(input: taffy::style::Position) -> taffy_03::style::Position {
+ match input {
+ taffy::style::Position::Relative => taffy_03::style::Position::Relative,
+ taffy::style::Position::Absolute => taffy_03::style::Position::Absolute,
+ }
+}
+
+fn convert_flex_direction(input: taffy::style::FlexDirection) -> taffy_03::style::FlexDirection {
+ match input {
+ taffy::style::FlexDirection::Row => taffy_03::style::FlexDirection::Row,
+ taffy::style::FlexDirection::Column => taffy_03::style::FlexDirection::Column,
+ taffy::style::FlexDirection::RowReverse => taffy_03::style::FlexDirection::RowReverse,
+ taffy::style::FlexDirection::ColumnReverse => taffy_03::style::FlexDirection::ColumnReverse,
+ }
+}
+
+fn convert_flex_wrap(input: taffy::style::FlexWrap) -> taffy_03::style::FlexWrap {
+ match input {
+ taffy::style::FlexWrap::NoWrap => taffy_03::style::FlexWrap::NoWrap,
+ taffy::style::FlexWrap::Wrap => taffy_03::style::FlexWrap::Wrap,
+ taffy::style::FlexWrap::WrapReverse => taffy_03::style::FlexWrap::WrapReverse,
+ }
+}
diff --git a/benches/src/taffy_helpers.rs b/benches/src/taffy_helpers.rs
index e0fbb6b2a..0b9cebd88 100644
--- a/benches/src/taffy_helpers.rs
+++ b/benches/src/taffy_helpers.rs
@@ -16,6 +16,7 @@ pub struct TaffyTreeBuilder<R: Rng, G: GenStyle<TaffyStyle>> {
// Implement the BuildTree trait
impl<R: Rng, G: GenStyle<TaffyStyle>> BuildTree<R, G> for TaffyTreeBuilder<R, G> {
+ const NAME: &'static str = "Taffy 0.4";
type Tree = TaffyTree;
type Node = TaffyNodeId;
@@ -25,6 +26,11 @@ impl<R: Rng, G: GenStyle<TaffyStyle>> BuildTree<R, G> for TaffyTreeBuilder<R, G>
TaffyTreeBuilder { rng, style_generator, tree, root }
}
+ fn compute_layout_inner(&mut self, available_width: Option<f32>, available_height: Option<f32>) {
+ let available_space = taffy::geometry::Size { width: available_width.into(), height: available_height.into() };
+ self.tree.compute_layout(self.root, available_space).unwrap();
+ }
+
fn random_usize(&mut self, range: impl SampleRange<usize>) -> usize {
self.rng.gen_range(range)
}
diff --git a/benches/src/yoga_helpers.rs b/benches/src/yoga_helpers.rs
index b05d7e61d..cd2f72229 100644
--- a/benches/src/yoga_helpers.rs
+++ b/benches/src/yoga_helpers.rs
@@ -30,6 +30,7 @@ pub struct YogaTreeBuilder<R: Rng, G: GenStyle<TaffyStyle>> {
// Implement the BuildTree trait
impl<R: Rng, G: GenStyle<TaffyStyle>> BuildTree<R, G> for YogaTreeBuilder<R, G> {
+ const NAME: &'static str = "Yoga";
type Tree = yg::YogaTree;
type Node = DefaultKey;
@@ -39,6 +40,14 @@ impl<R: Rng, G: GenStyle<TaffyStyle>> BuildTree<R, G> for YogaTreeBuilder<R, G>
YogaTreeBuilder { rng, style_generator, tree, root }
}
+ fn compute_layout_inner(&mut self, available_width: Option<f32>, available_height: Option<f32>) {
+ self.tree[self.root].calculate_layout(
+ available_width.unwrap_or(f32::INFINITY),
+ available_height.unwrap_or(f32::INFINITY),
+ yg::Direction::LTR,
+ )
+ }
+
fn random_usize(&mut self, range: impl SampleRange<usize>) -> usize {
self.rng.gen_range(range)
}