Merge pull request #438 from Demonthos/stretch2_relative_layout

Use Taffy instead of stretch2 for tui and native core
This commit is contained in:
Jon Kelley authored and GitHub committed 2022-06-11 10:45:01 -04:00
commit e97072f387
9 files changed
+106 -112

No files matched your search

+1 -1
View File
@@ -15,7 +15,7 @@ dioxus-core = { path = "../core", version = "^0.2.1" }
dioxus-html = { path = "../html", version = "^0.2.1" } dioxus-html = { path = "../html", version = "^0.2.1" }
dioxus-core-macro = { path = "../core-macro", version = "^0.2.1" } dioxus-core-macro = { path = "../core-macro", version = "^0.2.1" }
stretch2 = "0.4.2" taffy = "0.1.0"
smallvec = "1.6" smallvec = "1.6"
fxhash = "0.2" fxhash = "0.2"
anymap = "0.12.1" anymap = "0.12.1"
+10 -25
View File
@@ -1,6 +1,6 @@
/* /*
- [ ] pub display: Display, - [ ] pub display: Display,
- [x] pub position_type: PositionType, --> kinda, stretch doesnt support everything - [x] pub position_type: PositionType, --> kinda, taffy doesnt support everything
- [ ] pub direction: Direction, - [ ] pub direction: Direction,
- [x] pub flex_direction: FlexDirection, - [x] pub flex_direction: FlexDirection,
@@ -9,7 +9,7 @@
- [x] pub flex_shrink: f32, - [x] pub flex_shrink: f32,
- [x] pub flex_basis: Dimension, - [x] pub flex_basis: Dimension,
- [x] pub overflow: Overflow, ---> kinda implemented... stretch doesnt have support for directional overflow - [x] pub overflow: Overflow, ---> kinda implemented... taffy doesnt have support for directional overflow
- [x] pub align_items: AlignItems, - [x] pub align_items: AlignItems,
- [x] pub align_self: AlignSelf, - [x] pub align_self: AlignSelf,
@@ -29,7 +29,10 @@
- [ ] pub aspect_ratio: Number, - [ ] pub aspect_ratio: Number,
*/ */
use stretch2::{prelude::*, style::PositionType}; use taffy::{
prelude::*,
style::{FlexDirection, PositionType},
};
/// applies the entire html namespace defined in dioxus-html /// applies the entire html namespace defined in dioxus-html
pub fn apply_layout_attributes(name: &str, value: &str, style: &mut Style) { pub fn apply_layout_attributes(name: &str, value: &str, style: &mut Style) {
@@ -109,13 +112,7 @@ pub fn apply_layout_attributes(name: &str, value: &str, style: &mut Style) {
"counter-reset" => {} "counter-reset" => {}
"cursor" => {} "cursor" => {}
"direction" => { "direction" => {}
match value {
"ltr" => style.direction = Direction::LTR,
"rtl" => style.direction = Direction::RTL,
_ => {}
}
}
"display" => apply_display(name, value, style), "display" => apply_display(name, value, style),
@@ -283,20 +280,8 @@ pub fn parse_value(value: &str) -> Option<UnitSystem> {
} }
} }
fn apply_overflow(name: &str, value: &str, style: &mut Style) { fn apply_overflow(_name: &str, _value: &str, _style: &mut Style) {
match name { // todo: add overflow support to taffy
// todo: add more overflow support to stretch2
"overflow" | "overflow-x" | "overflow-y" => {
style.overflow = match value {
"auto" => Overflow::Visible,
"hidden" => Overflow::Hidden,
"scroll" => Overflow::Scroll,
"visible" => Overflow::Visible,
_ => Overflow::Visible,
};
}
_ => {}
}
} }
fn apply_display(_name: &str, value: &str, style: &mut Style) { fn apply_display(_name: &str, value: &str, style: &mut Style) {
@@ -307,7 +292,7 @@ fn apply_display(_name: &str, value: &str, style: &mut Style) {
} }
// TODO: there are way more variants // TODO: there are way more variants
// stretch needs to be updated to handle them // taffy needs to be updated to handle them
// //
// "block" => Display::Block, // "block" => Display::Block,
// "inline" => Display::Inline, // "inline" => Display::Inline,
+1 -1
View File
@@ -23,7 +23,7 @@ crossterm = "0.23.0"
anyhow = "1.0.42" anyhow = "1.0.42"
tokio = { version = "1.15.0", features = ["full"] } tokio = { version = "1.15.0", features = ["full"] }
futures = "0.3.19" futures = "0.3.19"
stretch2 = "0.4.2" taffy = "0.1.0"
smallvec = "1.6" smallvec = "1.6"
fxhash = "0.2" fxhash = "0.2"
anymap = "0.12.1" anymap = "0.12.1"
+5 -5
View File
@@ -17,8 +17,8 @@ use std::{
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use stretch2::geometry::{Point, Size}; use taffy::geometry::{Point, Size};
use stretch2::{prelude::Layout, Stretch}; use taffy::{prelude::Layout, Taffy};
use crate::{Dom, Node}; use crate::{Dom, Node};
@@ -153,7 +153,7 @@ impl InnerInputState {
&mut self, &mut self,
evts: &mut [EventCore], evts: &mut [EventCore],
resolved_events: &mut Vec<UserEvent>, resolved_events: &mut Vec<UserEvent>,
layout: &Stretch, layout: &Taffy,
dom: &mut Dom, dom: &mut Dom,
) { ) {
let previous_mouse = self.mouse.clone(); let previous_mouse = self.mouse.clone();
@@ -175,7 +175,7 @@ impl InnerInputState {
&self, &self,
previous_mouse: Option<MouseData>, previous_mouse: Option<MouseData>,
resolved_events: &mut Vec<UserEvent>, resolved_events: &mut Vec<UserEvent>,
layout: &Stretch, layout: &Taffy,
dom: &mut Dom, dom: &mut Dom,
) { ) {
fn layout_contains_point(layout: &Layout, point: ScreenPoint) -> bool { fn layout_contains_point(layout: &Layout, point: ScreenPoint) -> bool {
@@ -523,7 +523,7 @@ impl RinkInputHandler {
) )
} }
pub(crate) fn get_events(&self, layout: &Stretch, dom: &mut Dom) -> Vec<UserEvent> { pub(crate) fn get_events(&self, layout: &Taffy, dom: &mut Dom) -> Vec<UserEvent> {
let mut resolved_events = Vec::new(); let mut resolved_events = Vec::new();
(*self.state).borrow_mut().update( (*self.state).borrow_mut().update(
+11 -12
View File
@@ -6,7 +6,7 @@ use dioxus_native_core::layout_attributes::apply_layout_attributes;
use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView}; use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView};
use dioxus_native_core::state::ChildDepState; use dioxus_native_core::state::ChildDepState;
use dioxus_native_core_macro::sorted_str_slice; use dioxus_native_core_macro::sorted_str_slice;
use stretch2::prelude::*; use taffy::prelude::*;
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) enum PossiblyUninitalized<T> { pub(crate) enum PossiblyUninitalized<T> {
@@ -28,13 +28,13 @@ impl<T> Default for PossiblyUninitalized<T> {
} }
#[derive(Clone, PartialEq, Default, Debug)] #[derive(Clone, PartialEq, Default, Debug)]
pub(crate) struct StretchLayout { pub(crate) struct TaffyLayout {
pub style: Style, pub style: Style,
pub node: PossiblyUninitalized<Node>, pub node: PossiblyUninitalized<Node>,
} }
impl ChildDepState for StretchLayout { impl ChildDepState for TaffyLayout {
type Ctx = Rc<RefCell<Stretch>>; type Ctx = Rc<RefCell<Taffy>>;
type DepState = Self; type DepState = Self;
// use tag to force this to be called when a node is built // use tag to force this to be called when a node is built
const NODE_MASK: NodeMask = const NODE_MASK: NodeMask =
@@ -53,7 +53,7 @@ impl ChildDepState for StretchLayout {
Self::DepState: 'a, Self::DepState: 'a,
{ {
let mut changed = false; let mut changed = false;
let mut stretch = ctx.borrow_mut(); let mut taffy = ctx.borrow_mut();
let mut style = Style::default(); let mut style = Style::default();
if let Some(text) = node.text() { if let Some(text) = node.text() {
let char_len = text.chars().count(); let char_len = text.chars().count();
@@ -70,11 +70,10 @@ impl ChildDepState for StretchLayout {
}; };
if let PossiblyUninitalized::Initialized(n) = self.node { if let PossiblyUninitalized::Initialized(n) = self.node {
if self.style != style { if self.style != style {
stretch.set_style(n, style).unwrap(); taffy.set_style(n, style).unwrap();
} }
} else { } else {
self.node = self.node = PossiblyUninitalized::Initialized(taffy.new_node(style, &[]).unwrap());
PossiblyUninitalized::Initialized(stretch.new_node(style, &[]).unwrap());
changed = true; changed = true;
} }
} else { } else {
@@ -100,14 +99,14 @@ impl ChildDepState for StretchLayout {
if let PossiblyUninitalized::Initialized(n) = self.node { if let PossiblyUninitalized::Initialized(n) = self.node {
if self.style != style { if self.style != style {
stretch.set_style(n, style).unwrap(); taffy.set_style(n, style).unwrap();
} }
if stretch.children(n).unwrap() != child_layout { if taffy.children(n).unwrap() != child_layout {
stretch.set_children(n, &child_layout).unwrap(); taffy.set_children(n, &child_layout).unwrap();
} }
} else { } else {
self.node = PossiblyUninitalized::Initialized( self.node = PossiblyUninitalized::Initialized(
stretch.new_node(style, &child_layout).unwrap(), taffy.new_node(style, &child_layout).unwrap(),
); );
changed = true; changed = true;
} }
+24 -17
View File
@@ -13,12 +13,12 @@ use futures::{
channel::mpsc::{UnboundedReceiver, UnboundedSender}, channel::mpsc::{UnboundedReceiver, UnboundedSender},
pin_mut, StreamExt, pin_mut, StreamExt,
}; };
use layout::StretchLayout; use layout::TaffyLayout;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::{io, time::Duration}; use std::{io, time::Duration};
use stretch2::{prelude::Size, Stretch};
use style_attributes::StyleModifier; use style_attributes::StyleModifier;
use taffy::{geometry::Point, prelude::Size, Taffy};
use tui::{backend::CrosstermBackend, layout::Rect, Terminal}; use tui::{backend::CrosstermBackend, layout::Rect, Terminal};
mod config; mod config;
@@ -37,8 +37,8 @@ type Node = dioxus_native_core::real_dom::Node<NodeState>;
#[derive(Debug, Clone, State, Default)] #[derive(Debug, Clone, State, Default)]
struct NodeState { struct NodeState {
#[child_dep_state(layout, RefCell<Stretch>)] #[child_dep_state(layout, RefCell<Taffy>)]
layout: StretchLayout, layout: TaffyLayout,
// depends on attributes, the C component of it's parent and a u8 context // depends on attributes, the C component of it's parent and a u8 context
#[parent_dep_state(style)] #[parent_dep_state(style)]
style: StyleModifier, style: StyleModifier,
@@ -88,9 +88,9 @@ pub fn launch_cfg(app: Component<()>, cfg: Config) {
let mut rdom: Dom = RealDom::new(); let mut rdom: Dom = RealDom::new();
let mutations = dom.rebuild(); let mutations = dom.rebuild();
let to_update = rdom.apply_mutations(vec![mutations]); let to_update = rdom.apply_mutations(vec![mutations]);
let stretch = Rc::new(RefCell::new(Stretch::new())); let taffy = Rc::new(RefCell::new(Taffy::new()));
let mut any_map = AnyMap::new(); let mut any_map = AnyMap::new();
any_map.insert(stretch.clone()); any_map.insert(taffy.clone());
let _to_rerender = rdom.update_state(&dom, to_update, any_map).unwrap(); let _to_rerender = rdom.update_state(&dom, to_update, any_map).unwrap();
render_vdom( render_vdom(
@@ -99,7 +99,7 @@ pub fn launch_cfg(app: Component<()>, cfg: Config) {
handler, handler,
cfg, cfg,
rdom, rdom,
stretch, taffy,
register_event, register_event,
) )
.unwrap(); .unwrap();
@@ -111,7 +111,7 @@ fn render_vdom(
handler: RinkInputHandler, handler: RinkInputHandler,
cfg: Config, cfg: Config,
mut rdom: Dom, mut rdom: Dom,
stretch: Rc<RefCell<Stretch>>, taffy: Rc<RefCell<Taffy>>,
mut register_event: impl FnMut(crossterm::event::Event), mut register_event: impl FnMut(crossterm::event::Event),
) -> Result<()> { ) -> Result<()> {
tokio::runtime::Builder::new_current_thread() tokio::runtime::Builder::new_current_thread()
@@ -146,17 +146,17 @@ fn render_vdom(
if !to_rerender.is_empty() || resized { if !to_rerender.is_empty() || resized {
resized = false; resized = false;
fn resize(dims: Rect, stretch: &mut Stretch, rdom: &Dom) { fn resize(dims: Rect, taffy: &mut Taffy, rdom: &Dom) {
let width = dims.width; let width = dims.width;
let height = dims.height; let height = dims.height;
let root_node = rdom[0].state.layout.node.unwrap(); let root_node = rdom[0].state.layout.node.unwrap();
stretch taffy
.compute_layout( .compute_layout(
root_node, root_node,
Size { Size {
width: stretch2::prelude::Number::Defined((width - 1) as f32), width: taffy::prelude::Number::Defined((width - 1) as f32),
height: stretch2::prelude::Number::Defined((height - 1) as f32), height: taffy::prelude::Number::Defined((height - 1) as f32),
}, },
) )
.unwrap(); .unwrap();
@@ -164,9 +164,16 @@ fn render_vdom(
if let Some(terminal) = &mut terminal { if let Some(terminal) = &mut terminal {
terminal.draw(|frame| { terminal.draw(|frame| {
// size is guaranteed to not change when rendering // size is guaranteed to not change when rendering
resize(frame.size(), &mut stretch.borrow_mut(), &rdom); resize(frame.size(), &mut taffy.borrow_mut(), &rdom);
let root = &rdom[0]; let root = &rdom[0];
render::render_vnode(frame, &stretch.borrow(), &rdom, root, cfg); render::render_vnode(
frame,
&taffy.borrow(),
&rdom,
root,
cfg,
Point::zero(),
);
})?; })?;
} else { } else {
resize( resize(
@@ -176,7 +183,7 @@ fn render_vdom(
width: 300, width: 300,
height: 300, height: 300,
}, },
&mut stretch.borrow_mut(), &mut taffy.borrow_mut(),
&rdom, &rdom,
); );
} }
@@ -216,7 +223,7 @@ fn render_vdom(
} }
{ {
let evts = handler.get_events(&stretch.borrow(), &mut rdom); let evts = handler.get_events(&taffy.borrow(), &mut rdom);
for e in evts { for e in evts {
vdom.handle_message(SchedulerMsg::Event(e)); vdom.handle_message(SchedulerMsg::Event(e));
} }
@@ -225,7 +232,7 @@ fn render_vdom(
let to_update = rdom.apply_mutations(mutations); let to_update = rdom.apply_mutations(mutations);
// update the style and layout // update the style and layout
let mut any_map = AnyMap::new(); let mut any_map = AnyMap::new();
any_map.insert(stretch.clone()); any_map.insert(taffy.clone());
to_rerender = rdom.update_state(vdom, to_update, any_map).unwrap(); to_rerender = rdom.update_state(vdom, to_update, any_map).unwrap();
} }
} }
+12 -7
View File
@@ -1,9 +1,9 @@
use dioxus_native_core::layout_attributes::UnitSystem; use dioxus_native_core::layout_attributes::UnitSystem;
use std::io::Stdout; use std::io::Stdout;
use stretch2::{ use taffy::{
geometry::Point, geometry::Point,
prelude::{Layout, Size}, prelude::{Layout, Size},
Stretch, Taffy,
}; };
use tui::{backend::CrosstermBackend, layout::Rect}; use tui::{backend::CrosstermBackend, layout::Rect};
@@ -18,10 +18,11 @@ const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5];
pub(crate) fn render_vnode( pub(crate) fn render_vnode(
frame: &mut tui::Frame<CrosstermBackend<Stdout>>, frame: &mut tui::Frame<CrosstermBackend<Stdout>>,
layout: &Stretch, layout: &Taffy,
rdom: &Dom, rdom: &Dom,
node: &Node, node: &Node,
cfg: Config, cfg: Config,
parent_location: Point<f32>,
) { ) {
use dioxus_native_core::real_dom::NodeType; use dioxus_native_core::real_dom::NodeType;
@@ -29,7 +30,11 @@ pub(crate) fn render_vnode(
return; return;
} }
let Layout { location, size, .. } = layout.layout(node.state.layout.node.unwrap()).unwrap(); let Layout {
mut location, size, ..
} = layout.layout(node.state.layout.node.unwrap()).unwrap();
location.x += parent_location.x;
location.y += parent_location.y;
let Point { x, y } = location; let Point { x, y } = location;
let Size { width, height } = size; let Size { width, height } = size;
@@ -57,7 +62,7 @@ pub(crate) fn render_vnode(
text, text,
style: node.state.style.core, style: node.state.style.core,
}; };
let area = Rect::new(*x as u16, *y as u16, *width as u16, *height as u16); let area = Rect::new(x as u16, y as u16, *width as u16, *height as u16);
// the renderer will panic if a node is rendered out of range even if the size is zero // the renderer will panic if a node is rendered out of range even if the size is zero
if area.width > 0 && area.height > 0 { if area.width > 0 && area.height > 0 {
@@ -65,7 +70,7 @@ pub(crate) fn render_vnode(
} }
} }
NodeType::Element { children, .. } => { NodeType::Element { children, .. } => {
let area = Rect::new(*x as u16, *y as u16, *width as u16, *height as u16); let area = Rect::new(x as u16, y as u16, *width as u16, *height as u16);
// the renderer will panic if a node is rendered out of range even if the size is zero // the renderer will panic if a node is rendered out of range even if the size is zero
if area.width > 0 && area.height > 0 { if area.width > 0 && area.height > 0 {
@@ -73,7 +78,7 @@ pub(crate) fn render_vnode(
} }
for c in children { for c in children {
render_vnode(frame, layout, rdom, &rdom[c.0], cfg); render_vnode(frame, layout, rdom, &rdom[c.0], cfg, location);
} }
} }
NodeType::Placeholder => unreachable!(), NodeType::Placeholder => unreachable!(),
+2 -2
View File
@@ -1,6 +1,6 @@
/* /*
- [ ] pub display: Display, - [ ] pub display: Display,
- [x] pub position_type: PositionType, --> kinda, stretch doesnt support everything - [x] pub position_type: PositionType, --> kinda, taffy doesnt support everything
- [ ] pub direction: Direction, - [ ] pub direction: Direction,
- [x] pub flex_direction: FlexDirection, - [x] pub flex_direction: FlexDirection,
@@ -9,7 +9,7 @@
- [x] pub flex_shrink: f32, - [x] pub flex_shrink: f32,
- [x] pub flex_basis: Dimension, - [x] pub flex_basis: Dimension,
- [x] pub overflow: Overflow, ---> kinda implemented... stretch doesnt have support for directional overflow - [x] pub overflow: Overflow, ---> kinda implemented... taffy doesnt have support for directional overflow
- [x] pub align_items: AlignItems, - [x] pub align_items: AlignItems,
- [x] pub align_self: AlignSelf, - [x] pub align_self: AlignSelf,
+40 -42
View File
@@ -1,15 +1,13 @@
use stretch2 as stretch;
#[test] #[test]
fn margin_and_flex_row() { fn margin_and_flex_row() {
let mut stretch = stretch::Stretch::new(); let mut taffy = taffy::Taffy::new();
let node0 = stretch let node0 = taffy
.new_node( .new_node(
stretch::style::Style { taffy::style::Style {
flex_grow: 1f32, flex_grow: 1f32,
margin: stretch::geometry::Rect { margin: taffy::geometry::Rect {
start: stretch::style::Dimension::Points(10f32), start: taffy::style::Dimension::Points(10f32),
end: stretch::style::Dimension::Points(10f32), end: taffy::style::Dimension::Points(10f32),
..Default::default() ..Default::default()
}, },
..Default::default() ..Default::default()
@@ -17,50 +15,50 @@ fn margin_and_flex_row() {
&[], &[],
) )
.unwrap(); .unwrap();
let node = stretch let node = taffy
.new_node( .new_node(
stretch::style::Style { taffy::style::Style {
size: stretch::geometry::Size { size: taffy::geometry::Size {
width: stretch::style::Dimension::Points(100f32), width: taffy::style::Dimension::Points(100f32),
height: stretch::style::Dimension::Points(100f32), height: taffy::style::Dimension::Points(100f32),
}, },
..Default::default() ..Default::default()
}, },
&[node0], &[node0],
) )
.unwrap(); .unwrap();
stretch taffy
.compute_layout(node, stretch::geometry::Size::undefined()) .compute_layout(node, taffy::geometry::Size::undefined())
.unwrap(); .unwrap();
assert_eq!(stretch.layout(node).unwrap().size.width, 100f32); assert_eq!(taffy.layout(node).unwrap().size.width, 100f32);
assert_eq!(stretch.layout(node).unwrap().size.height, 100f32); assert_eq!(taffy.layout(node).unwrap().size.height, 100f32);
assert_eq!(stretch.layout(node).unwrap().location.x, 0f32); assert_eq!(taffy.layout(node).unwrap().location.x, 0f32);
assert_eq!(stretch.layout(node).unwrap().location.y, 0f32); assert_eq!(taffy.layout(node).unwrap().location.y, 0f32);
assert_eq!(stretch.layout(node0).unwrap().size.width, 80f32); assert_eq!(taffy.layout(node0).unwrap().size.width, 80f32);
assert_eq!(stretch.layout(node0).unwrap().size.height, 100f32); assert_eq!(taffy.layout(node0).unwrap().size.height, 100f32);
assert_eq!(stretch.layout(node0).unwrap().location.x, 10f32); assert_eq!(taffy.layout(node0).unwrap().location.x, 10f32);
assert_eq!(stretch.layout(node0).unwrap().location.y, 0f32); assert_eq!(taffy.layout(node0).unwrap().location.y, 0f32);
} }
#[test] #[test]
fn margin_and_flex_row2() { fn margin_and_flex_row2() {
let mut stretch = stretch::Stretch::new(); let mut taffy = taffy::Taffy::new();
let node0 = stretch let node0 = taffy
.new_node( .new_node(
stretch::style::Style { taffy::style::Style {
flex_grow: 1f32, flex_grow: 1f32,
margin: stretch::geometry::Rect { margin: taffy::geometry::Rect {
// left // left
start: stretch::style::Dimension::Points(10f32), start: taffy::style::Dimension::Points(10f32),
// right? // right?
end: stretch::style::Dimension::Points(10f32), end: taffy::style::Dimension::Points(10f32),
// top? // top?
// top: stretch::style::Dimension::Points(10f32), // top: taffy::style::Dimension::Points(10f32),
// bottom? // bottom?
// bottom: stretch::style::Dimension::Points(10f32), // bottom: taffy::style::Dimension::Points(10f32),
..Default::default() ..Default::default()
}, },
..Default::default() ..Default::default()
@@ -69,12 +67,12 @@ fn margin_and_flex_row2() {
) )
.unwrap(); .unwrap();
let node = stretch let node = taffy
.new_node( .new_node(
stretch::style::Style { taffy::style::Style {
size: stretch::geometry::Size { size: taffy::geometry::Size {
width: stretch::style::Dimension::Points(100f32), width: taffy::style::Dimension::Points(100f32),
height: stretch::style::Dimension::Points(100f32), height: taffy::style::Dimension::Points(100f32),
}, },
..Default::default() ..Default::default()
}, },
@@ -82,12 +80,12 @@ fn margin_and_flex_row2() {
) )
.unwrap(); .unwrap();
stretch taffy
.compute_layout(node, stretch::geometry::Size::undefined()) .compute_layout(node, taffy::geometry::Size::undefined())
.unwrap(); .unwrap();
assert_eq!(stretch.layout(node).unwrap().size.width, 100f32); assert_eq!(taffy.layout(node).unwrap().size.width, 100f32);
assert_eq!(stretch.layout(node).unwrap().size.height, 100f32); assert_eq!(taffy.layout(node).unwrap().size.height, 100f32);
assert_eq!(stretch.layout(node).unwrap().location.x, 0f32); assert_eq!(taffy.layout(node).unwrap().location.x, 0f32);
assert_eq!(stretch.layout(node).unwrap().location.y, 0f32); assert_eq!(taffy.layout(node).unwrap().location.y, 0f32);
} }