diff --git a/src/algo.rs b/src/algo.rs
index 573010a6b..eac45f340 100644
--- a/src/algo.rs
+++ b/src/algo.rs
@@ -5,27 +5,29 @@ use libm::F32Ext;
use core::f32;
-use crate::layout;
-use crate::ref_eq::ref_eq;
+use std::rc::Rc;
+use std::cell::RefCell;
-use crate::style;
+use crate::node::InternalNode;
use crate::style::*;
+use crate::result;
+use crate::result::Result;
+
+use crate::ref_eq::ref_eq;
use crate::number::Number::*;
use crate::number::*;
-use crate::result::Result;
-
use crate::geometry::{Point, Rect, Size};
#[derive(Debug, Clone)]
pub struct ComputeResult {
pub size: Size<f32>,
- pub children: Vec<layout::Node>,
+ pub children: Vec<result::Layout>,
}
struct FlexItem<'a> {
- node: &'a style::Node,
+ node: &'a Rc<RefCell<InternalNode>>,
size: Size<Number>,
min_size: Size<Number>,
@@ -61,16 +63,16 @@ struct FlexLine<'a> {
offset_cross: f32,
}
-pub fn compute(root: &style::Node, size: Size<Number>) -> Result<layout::Node> {
- let has_root_min_max = root.min_size.width.is_defined()
- || root.min_size.height.is_defined()
- || root.max_size.width.is_defined()
- || root.max_size.height.is_defined();
+pub(crate) fn compute(root: &InternalNode, size: Size<Number>) -> Result<result::Layout> {
+ let has_root_min_max = root.style.min_size.width.is_defined()
+ || root.style.min_size.height.is_defined()
+ || root.style.max_size.width.is_defined()
+ || root.style.max_size.height.is_defined();
let result = if has_root_min_max {
let first_pass = compute_internal(
root,
- Size { width: root.size.width.resolve(size.width), height: root.size.height.resolve(size.height) },
+ Size { width: root.style.size.width.resolve(size.width), height: root.style.size.height.resolve(size.height) },
size,
false,
)?;
@@ -81,14 +83,14 @@ pub fn compute(root: &style::Node, size: Size<Number>) -> Result<layout::Node> {
width: first_pass
.size
.width
- .maybe_max(root.min_size.width.resolve(size.width))
- .maybe_min(root.max_size.width.resolve(size.width))
+ .maybe_max(root.style.min_size.width.resolve(size.width))
+ .maybe_min(root.style.max_size.width.resolve(size.width))
.to_number(),
height: first_pass
.size
.height
- .maybe_max(root.min_size.height.resolve(size.height))
- .maybe_min(root.max_size.height.resolve(size.height))
+ .maybe_max(root.style.min_size.height.resolve(size.height))
+ .maybe_min(root.style.max_size.height.resolve(size.height))
.to_number(),
},
size,
@@ -97,13 +99,13 @@ pub fn compute(root: &style::Node, size: Size<Number>) -> Result<layout::Node> {
} else {
compute_internal(
root,
- Size { width: root.size.width.resolve(size.width), height: root.size.height.resolve(size.height) },
+ Size { width: root.style.size.width.resolve(size.width), height: root.style.size.height.resolve(size.height) },
size,
true,
)?
};
- let mut layout = layout::Node {
+ let mut layout = result::Layout {
order: 0,
size: Size { width: result.size.width, height: result.size.height },
location: Point { x: 0.0, y: 0.0 },
@@ -114,7 +116,7 @@ pub fn compute(root: &style::Node, size: Size<Number>) -> Result<layout::Node> {
Ok(layout)
}
-fn round_layout(layout: &mut layout::Node, abs_x: f32, abs_y: f32) {
+fn round_layout(layout: &mut result::Layout, abs_x: f32, abs_y: f32) {
let abs_x = abs_x + layout.location.x;
let abs_y = abs_y + layout.location.y;
@@ -126,7 +128,7 @@ fn round_layout(layout: &mut layout::Node, abs_x: f32, abs_y: f32) {
}
fn compute_internal(
- node: &style::Node,
+ node: &InternalNode,
node_size: Size<Number>,
parent_size: Size<Number>,
perform_layout: bool,
@@ -167,7 +169,7 @@ fn compute_internal(
if let Some(ref measure) = node.measure {
let result = ComputeResult { size: measure(node_size)?, children: vec![] };
- node.layout_cache.replace(Some(LayoutCache {
+ node.layout_cache.replace(Some(result::Cache {
node_size,
parent_size,
perform_layout,
@@ -180,14 +182,14 @@ fn compute_internal(
// Define some general constants we will need for the remainder
// of the algorithm.
- let dir = node.flex_direction;
+ let dir = node.style.flex_direction;
let is_row = dir.is_row();
let is_column = dir.is_column();
- let is_wrap_reverse = node.flex_wrap == FlexWrap::WrapReverse;
+ let is_wrap_reverse = node.style.flex_wrap == FlexWrap::WrapReverse;
- let margin = node.margin.map(|n| n.resolve(parent_size.width).or_else(0.0));
- let padding = node.padding.map(|n| n.resolve(parent_size.width).or_else(0.0));
- let border = node.border.map(|n| n.resolve(parent_size.width).or_else(0.0));
+ let margin = node.style.margin.map(|n| n.resolve(parent_size.width).or_else(0.0));
+ let padding = node.style.padding.map(|n| n.resolve(parent_size.width).or_else(0.0));
+ let border = node.style.border.map(|n| n.resolve(parent_size.width).or_else(0.0));
let padding_border = Rect {
start: padding.start + border.start,
@@ -224,30 +226,30 @@ fn compute_internal(
let mut flex_items: Vec<FlexItem> = node
.children
.iter()
- .filter(|child| child.position_type != PositionType::Absolute)
- .filter(|child| child.display != Display::None)
+ .filter(|child| child.borrow().style.position_type != PositionType::Absolute)
+ .filter(|child| child.borrow().style.display != Display::None)
.map(|child| FlexItem {
node: child,
size: Size {
- width: child.size.width.resolve(node_inner_size.width),
- height: child.size.height.resolve(node_inner_size.height),
+ width: child.borrow().style.size.width.resolve(node_inner_size.width),
+ height: child.borrow().style.size.height.resolve(node_inner_size.height),
},
min_size: Size {
- width: child.min_size.width.resolve(node_inner_size.width),
- height: child.min_size.height.resolve(node_inner_size.height),
+ width: child.borrow().style.min_size.width.resolve(node_inner_size.width),
+ height: child.borrow().style.min_size.height.resolve(node_inner_size.height),
},
max_size: Size {
- width: child.max_size.width.resolve(node_inner_size.width),
- height: child.max_size.height.resolve(node_inner_size.height),
+ width: child.borrow().style.max_size.width.resolve(node_inner_size.width),
+ height: child.borrow().style.max_size.height.resolve(node_inner_size.height),
},
- position: child.position.map(|p| p.resolve(node_inner_size.width)),
- margin: child.margin.map(|m| m.resolve(node_inner_size.width).or_else(0.0)),
- padding: child.padding.map(|p| p.resolve(node_inner_size.width).or_else(0.0)),
- border: child.border.map(|b| b.resolve(node_inner_size.width).or_else(0.0)),
+ position: child.borrow().style.position.map(|p| p.resolve(node_inner_size.width)),
+ margin: child.borrow().style.margin.map(|m| m.resolve(node_inner_size.width).or_else(0.0)),
+ padding: child.borrow().style.padding.map(|p| p.resolve(node_inner_size.width).or_else(0.0)),
+ border: child.borrow().style.border.map(|b| b.resolve(node_inner_size.width).or_else(0.0)),
flex_basis: 0.0,
inner_flex_basis: 0.0,
@@ -271,7 +273,7 @@ fn compute_internal(
flex_items.iter_mut().try_for_each(|child| -> Result<()> {
// A. If the item has a definite used flex basis, that’s the flex base size.
- let flex_basis = child.node.flex_basis.resolve(node_inner_size.main(dir));
+ let flex_basis = child.node.borrow().style.flex_basis.resolve(node_inner_size.main(dir));
if flex_basis.is_defined() {
child.flex_basis = flex_basis.or_else(0.0);
return Ok(());
@@ -282,9 +284,9 @@ fn compute_internal(
// then the flex base size is calculated from its inner
// cross size and the flex item’s intrinsic aspect ratio.
- if let Defined(ratio) = child.node.aspect_ratio {
+ if let Defined(ratio) = child.node.borrow().style.aspect_ratio {
if let Defined(cross) = node_size.cross(dir) {
- if child.node.flex_basis == Dimension::Auto {
+ if child.node.borrow().style.flex_basis == Dimension::Auto {
child.flex_basis = cross * ratio;
return Ok(());
}
@@ -315,7 +317,7 @@ fn compute_internal(
// flex item’s cross size. The flex base size is the item’s resulting main size.
let width: Number = if !child.size.width.is_defined()
- && child.node.align_self(node) == style::AlignSelf::Stretch
+ && child.node.borrow().style.align_self(&node.style) == AlignSelf::Stretch
&& is_column
{
available_space.width
@@ -324,14 +326,14 @@ fn compute_internal(
};
let height: Number =
- if !child.size.height.is_defined() && child.node.align_self(node) == style::AlignSelf::Stretch && is_row {
+ if !child.size.height.is_defined() && child.node.borrow().style.align_self(&node.style) == AlignSelf::Stretch && is_row {
available_space.height
} else {
child.size.height
};
child.flex_basis = compute_internal(
- child.node,
+ &child.node.borrow(),
Size {
width: width.maybe_max(child.min_size.width).maybe_min(child.max_size.width),
height: height.maybe_max(child.min_size.height).maybe_min(child.max_size.height),
@@ -358,7 +360,7 @@ fn compute_internal(
// webkit handled various scenarios. Can probably be solved better by passing in
// min-content max-content constraints from the top
let min_main =
- compute_internal(child.node, Size { width: Undefined, height: Undefined }, available_space, false)?
+ compute_internal(&child.node.borrow(), Size { width: Undefined, height: Undefined }, available_space, false)?
.size
.main(dir)
.maybe_max(child.min_size.main(dir))
@@ -395,7 +397,7 @@ fn compute_internal(
let mut lines: Vec<FlexLine> = vec![];
let mut line_length = 0.0;
- if node.flex_wrap == FlexWrap::NoWrap {
+ if node.style.flex_wrap == FlexWrap::NoWrap {
lines.push(FlexLine { items: flex_items, cross_size: 0.0, offset_cross: 0.0 });
} else {
let mut line = FlexLine { items: vec![], cross_size: 0.0, offset_cross: 0.0 };
@@ -449,7 +451,7 @@ fn compute_internal(
child.target_size.set_main(
dir,
compute_internal(
- child.node,
+ &child.node.borrow(),
Size {
width: child.size.width.maybe_max(child.min_size.width).maybe_min(child.max_size.width),
height: child.size.height.maybe_max(child.min_size.height).maybe_min(child.max_size.height),
@@ -471,7 +473,7 @@ fn compute_internal(
child.outer_target_size.set_main(dir, child.target_size.main(dir) + child.margin.main(dir));
- if (child.node.flex_grow == 0.0 && child.node.flex_shrink == 0.0)
+ if (child.node.borrow().style.flex_grow == 0.0 && child.node.borrow().style.flex_shrink == 0.0)
|| (growing && child.flex_basis > child.hypothetical_inner_size.main(dir))
|| (shrinking && child.flex_basis < child.hypothetical_inner_size.main(dir))
{
@@ -528,8 +530,8 @@ fn compute_internal(
})
.sum();
- let sum_flex_grow: f32 = unfrozen.iter().map(|item| item.node.flex_grow).sum();
- let sum_flex_shrink: f32 = unfrozen.iter().map(|item| item.node.flex_shrink).sum();
+ let sum_flex_grow: f32 = unfrozen.iter().map(|item| item.node.borrow().style.flex_grow).sum();
+ let sum_flex_shrink: f32 = unfrozen.iter().map(|item| item.node.borrow().style.flex_shrink).sum();
let free_space = if growing && sum_flex_grow < 1.0 {
(initial_free_space * sum_flex_grow).maybe_min(node_inner_size.main(dir) - used_space)
@@ -563,15 +565,15 @@ fn compute_internal(
unfrozen.iter_mut().for_each(|child| {
child
.target_size
- .set_main(dir, child.flex_basis + free_space * (child.node.flex_grow / sum_flex_grow));
+ .set_main(dir, child.flex_basis + free_space * (child.node.borrow().style.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 * child.node.flex_shrink).sum();
+ unfrozen.iter().map(|child| child.inner_flex_basis * child.node.borrow().style.flex_shrink).sum();
if sum_scaled_shrink_factor > 0.0 {
unfrozen.iter_mut().for_each(|child| {
- let scaled_shrink_factor = child.inner_flex_basis * child.node.flex_shrink;
+ let scaled_shrink_factor = child.inner_flex_basis * child.node.borrow().style.flex_shrink;
child.target_size.set_main(
dir,
child.flex_basis + free_space * (scaled_shrink_factor / sum_scaled_shrink_factor),
@@ -592,8 +594,8 @@ fn compute_internal(
// webkit handled various scenarios. Can probably be solved better by passing in
// min-content max-content constraints from the top. Need to figure out correct thing to do here as
// just piling on more conditionals.
- let min_main = if is_row && child.node.measure.is_none() {
- compute_internal(child.node, Size { width: Undefined, height: Undefined }, available_space, false)?
+ let min_main = if is_row && child.node.borrow().measure.is_none() {
+ compute_internal(&child.node.borrow(), Size { width: Undefined, height: Undefined }, available_space, false)?
.size
.width
.maybe_min(child.size.width)
@@ -665,7 +667,7 @@ fn compute_internal(
child.hypothetical_inner_size.set_cross(
dir,
compute_internal(
- child.node,
+ &child.node.borrow(),
Size {
width: if is_row { child.target_size.width.to_number() } else { child_cross },
height: if is_row { child_cross } else { child.target_size.height.to_number() },
@@ -693,7 +695,7 @@ fn compute_internal(
// TODO - probably should move this somewhere else as it doesn't make a ton of sense here but we need it below
// TODO - This is expensive and should only be done if we really require a baseline. aka, make it lazy
- fn calc_baseline(layout: &layout::Node) -> f32 {
+ fn calc_baseline(layout: &result::Layout) -> f32 {
if layout.children.is_empty() {
layout.size.height
} else {
@@ -704,7 +706,7 @@ fn compute_internal(
flex_lines.iter_mut().try_for_each(|line| {
line.items.iter_mut().try_for_each(|child| -> Result<()> {
let result = compute_internal(
- child.node,
+ &child.node.borrow(),
Size {
width: if is_row {
child.target_size.width.to_number()
@@ -724,7 +726,7 @@ fn compute_internal(
true,
)?;
- child.baseline = calc_baseline(&layout::Node {
+ child.baseline = calc_baseline(&result::Layout {
order: node.children.iter().position(|n| ref_eq(n, child.node)).unwrap() as u32,
size: result.size,
location: Point { x: 0.0, y: 0.0 },
@@ -764,10 +766,10 @@ fn compute_internal(
.items
.iter()
.map(|child| {
- if child.node.align_self(node) == AlignSelf::Baseline
- && child.node.cross_margin_start(dir) != Dimension::Auto
- && child.node.cross_margin_end(dir) != Dimension::Auto
- && child.node.cross_size(dir) == Dimension::Auto
+ if child.node.borrow().style.align_self(&node.style) == AlignSelf::Baseline
+ && child.node.borrow().style.cross_margin_start(dir) != Dimension::Auto
+ && child.node.borrow().style.cross_margin_end(dir) != Dimension::Auto
+ && child.node.borrow().style.cross_size(dir) == Dimension::Auto
{
max_baseline - child.baseline + child.hypothetical_outer_size.cross(dir)
} else {
@@ -784,7 +786,7 @@ fn compute_internal(
// by equal amounts such that the sum of their cross sizes exactly equals the
// flex container’s inner cross size.
- if node.align_content == AlignContent::Stretch && node_size.cross(dir).is_defined() {
+ if node.style.align_content == AlignContent::Stretch && node_size.cross(dir).is_defined() {
let total_cross: f32 = flex_lines.iter().map(|line| line.cross_size).sum();
let inner_cross = (node_size.cross(dir) - padding_border.cross(dir)).or_else(0.0);
@@ -828,10 +830,10 @@ fn compute_internal(
line.items.iter_mut().for_each(|child| {
child.target_size.set_cross(
dir,
- if child.node.align_self(node) == AlignSelf::Stretch
- && child.node.cross_margin_start(dir) != Dimension::Auto
- && child.node.cross_margin_end(dir) != Dimension::Auto
- && child.node.cross_size(dir) == Dimension::Auto
+ if child.node.borrow().style.align_self(&node.style) == AlignSelf::Stretch
+ && child.node.borrow().style.cross_margin_start(dir) != Dimension::Auto
+ && child.node.borrow().style.cross_margin_end(dir) != Dimension::Auto
+ && child.node.borrow().style.cross_size(dir) == Dimension::Auto
{
(line_cross_size - child.margin.cross(dir))
.maybe_max(child.min_size.cross(dir))
@@ -859,10 +861,10 @@ fn compute_internal(
let mut num_auto_margins = 0;
line.items.iter_mut().for_each(|child| {
- if child.node.main_margin_start(dir) == Dimension::Auto {
+ if child.node.borrow().style.main_margin_start(dir) == Dimension::Auto {
num_auto_margins += 1;
}
- if child.node.main_margin_end(dir) == Dimension::Auto {
+ if child.node.borrow().style.main_margin_end(dir) == Dimension::Auto {
num_auto_margins += 1;
}
});
@@ -871,14 +873,14 @@ fn compute_internal(
let margin = free_space / num_auto_margins as f32;
line.items.iter_mut().for_each(|child| {
- if child.node.main_margin_start(dir) == Dimension::Auto {
+ if child.node.borrow().style.main_margin_start(dir) == Dimension::Auto {
if is_row {
child.margin.start = margin;
} else {
child.margin.top = margin;
}
}
- if child.node.main_margin_end(dir) == Dimension::Auto {
+ if child.node.borrow().style.main_margin_end(dir) == Dimension::Auto {
if is_row {
child.margin.end = margin;
} else {
@@ -893,7 +895,7 @@ fn compute_internal(
let justify_item = |(i, child): (usize, &mut FlexItem)| {
let is_first = i == 0;
- child.offset_main = match node.justify_content {
+ child.offset_main = match node.style.justify_content {
JustifyContent::FlexStart => {
if layout_reverse && is_first {
free_space
@@ -958,8 +960,8 @@ fn compute_internal(
line.items.iter_mut().for_each(|child| {
let free_space = line_cross_size - child.outer_target_size.cross(dir);
- if child.node.cross_margin_start(dir) == Dimension::Auto
- && child.node.cross_margin_end(dir) == Dimension::Auto
+ if child.node.borrow().style.cross_margin_start(dir) == Dimension::Auto
+ && child.node.borrow().style.cross_margin_end(dir) == Dimension::Auto
{
if is_row {
child.margin.top = free_space / 2.0;
@@ -968,13 +970,13 @@ fn compute_internal(
child.margin.start = free_space / 2.0;
child.margin.end = free_space / 2.0;
}
- } else if child.node.cross_margin_start(dir) == Dimension::Auto {
+ } else if child.node.borrow().style.cross_margin_start(dir) == Dimension::Auto {
if is_row {
child.margin.top = free_space;
} else {
child.margin.start = free_space;
}
- } else if child.node.cross_margin_end(dir) == Dimension::Auto {
+ } else if child.node.borrow().style.cross_margin_end(dir) == Dimension::Auto {
if is_row {
child.margin.bottom = free_space;
} else {
@@ -984,7 +986,7 @@ fn compute_internal(
// 14. Align all flex items along the cross-axis per align-self, if neither of the item’s
// cross-axis margins are auto.
- child.offset_cross = match child.node.align_self(node) {
+ child.offset_cross = match child.node.borrow().style.align_self(&node.style) {
AlignSelf::Auto => 0.0, // Should never happen
AlignSelf::FlexStart => {
if is_wrap_reverse {
@@ -1040,7 +1042,7 @@ fn compute_internal(
// layout we are done now.
if !perform_layout {
let result = ComputeResult { size: container_size, children: vec![] };
- node.layout_cache.replace(Some(LayoutCache { node_size, parent_size, perform_layout, result: result.clone() }));
+ node.layout_cache.replace(Some(result::Cache { node_size, parent_size, perform_layout, result: result.clone() }));
return Ok(result);
}
@@ -1052,7 +1054,7 @@ fn compute_internal(
let align_line = |(i, line): (usize, &mut FlexLine)| {
let is_first = i == 0;
- line.offset_cross = match node.align_content {
+ line.offset_cross = match node.style.align_content {
AlignContent::FlexStart => {
if is_first && is_wrap_reverse {
free_space
@@ -1099,18 +1101,18 @@ fn compute_internal(
}
// Do a final layout pass and gather the resulting layouts
- let mut children: Vec<layout::Node> = {
- let mut lines: Vec<Vec<layout::Node>> = vec![];
+ let mut children: Vec<result::Layout> = {
+ let mut lines: Vec<Vec<result::Layout>> = vec![];
let mut total_offset_cross = padding_border.cross_start(dir);
let layout_line = |line: &mut FlexLine| -> Result<()> {
- let mut children: Vec<layout::Node> = vec![];
+ let mut children: Vec<result::Layout> = vec![];
let mut total_offset_main = padding_border.main_start(dir);
let line_offset_cross = line.offset_cross;
let layout_item = |child: &mut FlexItem| -> Result<()> {
let result = compute_internal(
- child.node,
+ &child.node.borrow(),
child.target_size.map(|s| s.to_number()),
container_size.map(|s| s.to_number()),
true,
@@ -1127,7 +1129,7 @@ fn compute_internal(
+ child.margin.cross_start(dir)
+ (child.position.cross_start(dir).or_else(0.0) - child.position.cross_end(dir).or_else(0.0));
- children.push(layout::Node {
+ children.push(result::Layout {
order: node.children.iter().position(|n| ref_eq(n, child.node)).unwrap() as u32,
size: result.size,
location: Point {
@@ -1173,42 +1175,42 @@ fn compute_internal(
};
// Before returning we perform absolute layout on all absolutely positioned children
- let absolute_children: Vec<Result<layout::Node>> = node
+ let absolute_children: Vec<Result<result::Layout>> = node
.children
.iter()
.enumerate()
- .filter(|(_, child)| child.position_type == PositionType::Absolute)
+ .filter(|(_, child)| child.borrow().style.position_type == PositionType::Absolute)
.map(|(order, child)| {
let container_width = container_size.width.to_number();
let container_height = container_size.height.to_number();
- let start = child.position.start.resolve(container_width) + child.margin.start.resolve(container_width);
- let end = child.position.end.resolve(container_width) + child.margin.end.resolve(container_width);
- let top = child.position.top.resolve(container_height) + child.margin.top.resolve(container_height);
+ let start = child.borrow().style.position.start.resolve(container_width) + child.borrow().style.margin.start.resolve(container_width);
+ let end = child.borrow().style.position.end.resolve(container_width) + child.borrow().style.margin.end.resolve(container_width);
+ let top = child.borrow().style.position.top.resolve(container_height) + child.borrow().style.margin.top.resolve(container_height);
let bottom =
- child.position.bottom.resolve(container_height) + child.margin.bottom.resolve(container_height);
+ child.borrow().style.position.bottom.resolve(container_height) + child.borrow().style.margin.bottom.resolve(container_height);
let (start_main, end_main) = if is_row { (start, end) } else { (top, bottom) };
let (start_cross, end_cross) = if is_row { (top, bottom) } else { (start, end) };
- let width = child
+ let width = child.borrow().style
.size
.width
.resolve(container_width)
- .maybe_max(child.min_size.width.resolve(container_width))
- .maybe_min(child.max_size.width.resolve(container_width))
+ .maybe_max(child.borrow().style.min_size.width.resolve(container_width))
+ .maybe_min(child.borrow().style.max_size.width.resolve(container_width))
.or_else(if start.is_defined() && end.is_defined() {
container_width - start - end
} else {
Undefined
});
- let height = child
+ let height = child.borrow().style
.size
.height
.resolve(container_height)
- .maybe_max(child.min_size.height.resolve(container_height))
- .maybe_min(child.max_size.height.resolve(container_height))
+ .maybe_max(child.borrow().style.min_size.height.resolve(container_height))
+ .maybe_min(child.borrow().style.max_size.height.resolve(container_height))
.or_else(if top.is_defined() && bottom.is_defined() {
container_height - top - bottom
} else {
@@ -1216,7 +1218,7 @@ fn compute_internal(
});
let result = compute_internal(
- child,
+ &child.borrow(),
Size { width, height },
Size { width: container_width, height: container_height },
true,
@@ -1226,22 +1228,22 @@ fn compute_internal(
- result
.size
.main(dir)
- .maybe_max(child.min_main_size(dir).resolve(node_inner_size.main(dir)))
- .maybe_min(child.max_main_size(dir).resolve(node_inner_size.main(dir)));
+ .maybe_max(child.borrow().style.min_main_size(dir).resolve(node_inner_size.main(dir)))
+ .maybe_min(child.borrow().style.max_main_size(dir).resolve(node_inner_size.main(dir)));
let free_cross_space = container_size.cross(dir)
- result
.size
.cross(dir)
- .maybe_max(child.min_cross_size(dir).resolve(node_inner_size.cross(dir)))
- .maybe_min(child.max_cross_size(dir).resolve(node_inner_size.cross(dir)));
+ .maybe_max(child.borrow().style.min_cross_size(dir).resolve(node_inner_size.cross(dir)))
+ .maybe_min(child.borrow().style.max_cross_size(dir).resolve(node_inner_size.cross(dir)));
let offset_main = if start_main.is_defined() {
start_main.or_else(0.0) + border.main_start(dir)
} else if end_main.is_defined() {
free_main_space - end_main.or_else(0.0) - border.main_end(dir)
} else {
- match node.justify_content {
+ match node.style.justify_content {
JustifyContent::SpaceBetween | JustifyContent::FlexStart => padding_border.main_start(dir),
JustifyContent::FlexEnd => free_main_space - padding_border.main_end(dir),
JustifyContent::SpaceEvenly | JustifyContent::SpaceAround | JustifyContent::Center => {
@@ -1255,7 +1257,7 @@ fn compute_internal(
} else if end_cross.is_defined() {
free_cross_space - end_cross.or_else(0.0) - border.cross_end(dir)
} else {
- match child.align_self(node) {
+ match child.borrow().style.align_self(&node.style) {
AlignSelf::Auto => 0.0, // Should never happen
AlignSelf::FlexStart => {
if is_wrap_reverse {
@@ -1283,7 +1285,7 @@ fn compute_internal(
}
};
- Ok(layout::Node {
+ Ok(result::Layout {
order: order as u32,
size: result.size,
location: Point {
@@ -1299,21 +1301,21 @@ fn compute_internal(
children.push(abs_child?);
}
- fn hidden_layout(node: &style::Node, order: u32) -> layout::Node {
- layout::Node {
+ fn hidden_layout(node: &InternalNode, order: u32) -> result::Layout {
+ result::Layout {
order,
size: Size { width: 0.0, height: 0.0 },
location: Point { x: 0.0, y: 0.0 },
- children: node.children.iter().enumerate().map(|(order, child)| hidden_layout(child, order as _)).collect(),
+ children: node.children.iter().enumerate().map(|(order, child)| hidden_layout(&child.borrow(), order as _)).collect(),
}
}
- let mut hidden_children: Vec<layout::Node> = node
+ let mut hidden_children: Vec<result::Layout> = node
.children
.iter()
.enumerate()
- .filter(|(_, child)| child.display == Display::None)
- .map(|(order, child)| hidden_layout(child, order as _))
+ .filter(|(_, child)| child.borrow().style.display == Display::None)
+ .map(|(order, child)| hidden_layout(&child.borrow(), order as _))
.collect();
children.append(&mut hidden_children);
@@ -1321,6 +1323,6 @@ fn compute_internal(
children.sort_by(|c1, c2| c1.order.cmp(&c2.order));
let result = ComputeResult { size: container_size, children };
- node.layout_cache.replace(Some(LayoutCache { node_size, parent_size, perform_layout, result: result.clone() }));
+ node.layout_cache.replace(Some(result::Cache { node_size, parent_size, perform_layout, result: result.clone() }));
Ok(result)
}
diff --git a/src/layout.rs b/src/layout.rs
deleted file mode 100644
index 98f6798ae..000000000
--- a/src/layout.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#[cfg(not(feature = "std"))]
-use alloc::vec::Vec;
-
-use crate::geometry::{Point, Size};
-
-#[derive(Debug, Clone)]
-pub struct Node {
- pub(crate) order: u32,
- pub size: Size<f32>,
- pub location: Point<f32>,
- pub children: Vec<Node>,
-}
diff --git a/src/lib.rs b/src/lib.rs
index fc6369c67..3d5ca17b8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,11 +4,10 @@
extern crate alloc;
pub mod geometry;
-pub mod layout;
-pub mod number;
pub mod result;
+pub mod number;
pub mod style;
+pub mod node;
mod algo;
mod ref_eq;
-pub use crate::algo::compute;
diff --git a/src/node.rs b/src/node.rs
new file mode 100644
index 000000000..f66144d7f
--- /dev/null
+++ b/src/node.rs
@@ -0,0 +1,65 @@
+#[cfg(not(feature = "std"))]
+use alloc::{vec, vec::Vec};
+
+use std::rc::Rc;
+use std::rc::Weak;
+use std::cell::RefCell;
+
+use crate::style::*;
+use crate::algo;
+use crate::geometry::Size;
+use crate::number::Number;
+use crate::result::{Layout, Cache, Result};
+
+type MeasureFunc = Box<Fn(Size<Number>) -> Result<Size<f32>>>;
+
+pub(crate) struct InternalNode {
+ pub(crate) style: Style,
+ pub(crate) parents: Vec<Weak<RefCell<InternalNode>>>,
+ pub(crate) children: Vec<Rc<RefCell<InternalNode>>>,
+ pub(crate) measure: Option<MeasureFunc>,
+ pub(crate) layout_cache: RefCell<Option<Cache>>,
+}
+
+pub struct Node(Rc<RefCell<InternalNode>>);
+
+impl Node {
+ pub fn new(style: Style, children: Vec<&Node>) -> Node {
+ let mut parent = Node(Rc::new(RefCell::new(InternalNode {
+ style: style,
+ parents: vec![],
+ children: vec![],
+ measure: None,
+ layout_cache: RefCell::new(None),
+ })));
+
+ for child in children {
+ parent.add_child(child);
+ }
+
+ parent
+ }
+
+ pub fn add_child(&mut self, child: &Node) {
+ child.0.borrow_mut().parents.push(Rc::downgrade(&self.0));
+ self.0.borrow_mut().children.push(Rc::clone(&child.0));
+ }
+
+ // pub fn children(&self) -> Vec<Node> {}
+
+ // pub fn mark_dirty(&mut self) {}
+
+ // pub fn set_style(&mut self, Style) {}
+
+ // pub fn set_children(&mut self, Vec<Node>) {}
+
+ // pub fn add_child(&mut self, Node) {}
+
+ // pub fn remove_child(&mut self, Node) -> Node {}
+
+ // pub fn replace_child(&mut self, Node, u32) -> Node {}
+
+ pub fn compute_layout(&self, size: Size<Number>) -> Result<Layout> {
+ algo::compute(&self.0.borrow(), size)
+ }
+}
diff --git a/src/result.rs b/src/result.rs
index c5d2510ad..5167e2fec 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,3 +1,27 @@
+#[cfg(not(feature = "std"))]
+use alloc::vec::Vec;
+
use core::any::Any;
+use crate::geometry::{Point, Size};
+use crate::number::Number;
+use crate::algo::ComputeResult;
+
pub type Result<T> = core::result::Result<T, Box<Any>>;
+
+#[derive(Debug, Clone)]
+pub struct Layout {
+ pub(crate) order: u32,
+ pub size: Size<f32>,
+ pub location: Point<f32>,
+ pub children: Vec<Layout>,
+}
+
+#[derive(Debug, Clone)]
+pub struct Cache {
+ pub node_size: Size<Number>,
+ pub parent_size: Size<Number>,
+ pub perform_layout: bool,
+
+ pub result: ComputeResult,
+}
diff --git a/src/style.rs b/src/style.rs
index 2ca373f71..6ac803685 100644
--- a/src/style.rs
+++ b/src/style.rs
@@ -1,12 +1,8 @@
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
-#[cfg(not(feature = "std"))]
-use alloc::{vec, vec::Vec};
-use crate::algo;
use crate::geometry::{Rect, Size};
use crate::number::Number;
-use crate::result::Result;
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum AlignItems {
@@ -206,96 +202,60 @@ impl Default for Size<Dimension> {
}
}
-type MeasureFunc = Box<Fn(Size<Number>) -> Result<Size<f32>>>;
-
-#[derive(Debug, Clone)]
-pub struct LayoutCache {
- pub node_size: Size<Number>,
- pub parent_size: Size<Number>,
- pub perform_layout: bool,
-
- pub result: algo::ComputeResult,
-}
-
-pub struct Node {
+#[derive(Debug)]
+pub struct Style {
pub display: Display,
-
pub position_type: PositionType,
pub direction: Direction,
pub flex_direction: FlexDirection,
-
pub flex_wrap: FlexWrap,
pub overflow: Overflow,
-
pub align_items: AlignItems,
pub align_self: AlignSelf,
pub align_content: AlignContent,
-
pub justify_content: JustifyContent,
-
pub position: Rect<Dimension>,
pub margin: Rect<Dimension>,
pub padding: Rect<Dimension>,
pub border: Rect<Dimension>,
-
pub flex_grow: f32,
pub flex_shrink: f32,
pub flex_basis: Dimension,
-
pub size: Size<Dimension>,
pub min_size: Size<Dimension>,
pub max_size: Size<Dimension>,
-
pub aspect_ratio: Number,
- pub measure: Option<MeasureFunc>,
-
- pub children: Vec<Node>,
-
- pub layout_cache: core::cell::RefCell<Option<LayoutCache>>,
}
-impl Default for Node {
- fn default() -> Node {
- Node {
+impl Default for Style {
+ fn default() -> Style {
+ Style {
display: Default::default(),
-
position_type: Default::default(),
direction: Default::default(),
flex_direction: Default::default(),
-
flex_wrap: Default::default(),
overflow: Default::default(),
-
align_items: Default::default(),
align_self: Default::default(),
align_content: Default::default(),
-
justify_content: Default::default(),
-
position: Default::default(),
margin: Default::default(),
padding: Default::default(),
border: Default::default(),
-
flex_grow: 0.0,
flex_shrink: 1.0,
flex_basis: Dimension::Auto,
-
size: Default::default(),
min_size: Default::default(),
max_size: Default::default(),
-
aspect_ratio: Default::default(),
- measure: None,
-
- children: vec![],
-
- layout_cache: core::cell::RefCell::new(None),
}
}
}
-impl Node {
+impl Style {
pub(crate) fn min_main_size(&self, direction: FlexDirection) -> Dimension {
match direction {
FlexDirection::Row | FlexDirection::RowReverse => self.min_size.width,
@@ -359,7 +319,7 @@ impl Node {
}
}
- pub(crate) fn align_self(&self, parent: &Node) -> AlignSelf {
+ pub(crate) fn align_self(&self, parent: &Style) -> AlignSelf {
if self.align_self == AlignSelf::Auto {
match parent.align_items {
AlignItems::FlexStart => AlignSelf::FlexStart,