Delta semántico · 93
src/compute/grid/alignment.rs
src/compute/grid/explicit_grid.rs
src/compute/grid/implicit_grid.rs
src/compute/grid/placement.rs
src/compute/grid/types/grid_item.rs
diff --git a/src/compute/block.rs b/src/compute/block.rs
index ea89f639c..edbbdaed8 100644
--- a/src/compute/block.rs
+++ b/src/compute/block.rs
@@ -1,6 +1,6 @@
//! Computes the CSS block layout algorithm in the case that the block container being laid out contains only block-level boxes
use crate::geometry::{Line, Point, Rect, Size};
-use crate::style::{AvailableSpace, Display, LengthPercentageAuto, Overflow, Position};
+use crate::style::{AvailableSpace, CoreStyle, LengthPercentageAuto, Overflow, Position};
use crate::style_helpers::TaffyMaxContent;
use crate::tree::{CollapsibleMarginSet, Layout, LayoutInput, LayoutOutput, RunMode, SizingMode};
use crate::tree::{LayoutPartialTree, LayoutPartialTreeExt, NodeId};
@@ -9,6 +9,7 @@ use crate::util::sys::f32_max;
use crate::util::sys::Vec;
use crate::util::MaybeMath;
use crate::util::{MaybeResolve, ResolveOrZero};
+use crate::{BoxGenerationMode, LayoutBlockContainer};
#[cfg(feature = "content_size")]
use super::common::content_size::compute_content_size_contribution;
@@ -56,25 +57,31 @@ struct BlockItem {
can_be_collapsed_through: bool,
}
-/// Computes the layout of [`LayoutPartialTree`] according to the block layout algorithm
-pub fn compute_block_layout(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: LayoutInput) -> LayoutOutput {
+/// Computes the layout of [`LayoutBlockContainer`] according to the block layout algorithm
+pub fn compute_block_layout(
+ tree: &mut impl LayoutBlockContainer,
+ node_id: NodeId,
+ inputs: LayoutInput,
+) -> LayoutOutput {
let LayoutInput { known_dimensions, parent_size, available_space, run_mode, .. } = inputs;
- let style = tree.get_style(node_id);
+ let style = tree.get_block_container_style(node_id);
// Pull these out earlier to avoid borrowing issues
- let aspect_ratio = style.aspect_ratio;
- let margin = style.margin.resolve_or_zero(parent_size.width);
- 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);
- let padding = style.padding.resolve_or_zero(parent_size.width);
- let border = style.border.resolve_or_zero(parent_size.width);
+ let aspect_ratio = style.aspect_ratio();
+ let margin = style.margin().resolve_or_zero(parent_size.width);
+ 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);
+ 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 clamped_style_size = if inputs.sizing_mode == SizingMode::InherentSize {
- style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size)
+ style.size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size)
} else {
Size::NONE
};
+ drop(style);
+
// If both min and max in a given axis are set and max <= min then this determines the size in that axis
let min_max_definite_size = min_size.zip_map(max_size, |min, max| match (min, max) {
(Some(min), Some(max)) if max <= min => Some(min),
@@ -103,29 +110,29 @@ pub fn compute_block_layout(tree: &mut impl LayoutPartialTree, node_id: NodeId,
compute_inner(tree, node_id, LayoutInput { known_dimensions: styled_based_known_dimensions, ..inputs })
}
-/// Computes the layout of [`LayoutPartialTree`] according to the block layout algorithm
-fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: LayoutInput) -> LayoutOutput {
+/// Computes the layout of [`LayoutBlockContainer`] according to the block layout algorithm
+fn compute_inner(tree: &mut impl LayoutBlockContainer, node_id: NodeId, inputs: LayoutInput) -> LayoutOutput {
let LayoutInput {
known_dimensions, parent_size, available_space, run_mode, vertical_margins_are_collapsible, ..
} = inputs;
- let style = tree.get_style(node_id);
- let raw_padding = style.padding;
- let raw_border = style.border;
- let raw_margin = style.margin;
- let aspect_ratio = style.aspect_ratio;
- let size = style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(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);
- let padding = style.padding.resolve_or_zero(parent_size.width);
- let border = style.border.resolve_or_zero(parent_size.width);
+ let style = tree.get_block_container_style(node_id);
+ let raw_padding = style.padding();
+ let raw_border = style.border();
+ let raw_margin = style.margin();
+ let aspect_ratio = style.aspect_ratio();
+ let size = style.size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(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);
+ let padding = style.padding().resolve_or_zero(parent_size.width);
+ let border = style.border().resolve_or_zero(parent_size.width);
// Scrollbar gutters are reserved when the `overflow` property is set to `Overflow::Scroll`.
// However, the axis are switched (transposed) because a node that scrolls vertically needs
// *horizontal* space to be reserved for a scrollbar
let scrollbar_gutter = {
- let offsets = style.overflow.transpose().map(|overflow| match overflow {
- Overflow::Scroll => style.scrollbar_width,
+ let offsets = style.overflow().transpose().map(|overflow| match overflow {
+ Overflow::Scroll => style.scrollbar_width(),
_ => 0.0,
});
// TODO: make side configurable based on the `direction` property
@@ -139,28 +146,30 @@ fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: Lay
// Determine margin collapsing behaviour
let own_margins_collapse_with_children = Line {
start: vertical_margins_are_collapsible.start
- && !style.overflow.x.is_scroll_container()
- && !style.overflow.y.is_scroll_container()
- && style.position == Position::Relative
+ && !style.overflow().x.is_scroll_container()
+ && !style.overflow().y.is_scroll_container()
+ && style.position() == Position::Relative
&& padding.top == 0.0
&& border.top == 0.0,
end: vertical_margins_are_collapsible.end
- && !style.overflow.x.is_scroll_container()
- && !style.overflow.y.is_scroll_container()
- && style.position == Position::Relative
+ && !style.overflow().x.is_scroll_container()
+ && !style.overflow().y.is_scroll_container()
+ && style.position() == Position::Relative
&& padding.bottom == 0.0
&& border.bottom == 0.0
&& size.height.is_none(),
};
- let has_styles_preventing_being_collapsed_through = style.display != Display::Block
- || style.overflow.x.is_scroll_container()
- || style.overflow.y.is_scroll_container()
- || style.position == Position::Absolute
+ let has_styles_preventing_being_collapsed_through = false//style.display != Display::Block
+ || style.overflow().x.is_scroll_container()
+ || style.overflow().y.is_scroll_container()
+ || style.position() == Position::Absolute
|| padding.top > 0.0
|| padding.bottom > 0.0
|| border.top > 0.0
|| border.bottom > 0.0;
+ drop(style);
+
// 1. Generate items
let mut items = generate_item_list(tree, node_id, container_content_box_size);
@@ -212,7 +221,7 @@ fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: Lay
let len = tree.child_count(node_id);
for order in 0..len {
let child = tree.get_child_id(node_id, order);
- if tree.get_style(child).display == Display::None {
+ if tree.get_block_child_style(child).box_generation_mode() == BoxGenerationMode::None {
tree.set_unrounded_layout(child, &Layout::with_order(order as u32));
tree.perform_child_layout(
child,
@@ -258,30 +267,30 @@ fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: Lay
/// Create a `Vec` of `BlockItem` structs where each item in the `Vec` represents a child of the current node
#[inline]
fn generate_item_list(
- tree: &impl LayoutPartialTree,
+ tree: &impl LayoutBlockContainer,
node: NodeId,
node_inner_size: Size<Option<f32>>,
) -> Vec<BlockItem> {
tree.child_ids(node)
- .map(|child_node_id| (child_node_id, tree.get_style(child_node_id)))
- .filter(|(_, style)| style.display != Display::None)
+ .map(|child_node_id| (child_node_id, tree.get_block_child_style(child_node_id)))
+ .filter(|(_, style)| style.box_generation_mode() != BoxGenerationMode::None)
.enumerate()
.map(|(order, (child_node_id, child_style))| {
- let aspect_ratio = child_style.aspect_ratio;
- let padding = child_style.padding.resolve_or_zero(node_inner_size);
- let border = child_style.border.resolve_or_zero(node_inner_size);
+ let aspect_ratio = child_style.aspect_ratio();
+ let padding = child_style.padding().resolve_or_zero(node_inner_size);
+ let border = child_style.border().resolve_or_zero(node_inner_size);
BlockItem {
node_id: child_node_id,
order: order as u32,
- size: child_style.size.maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
- min_size: child_style.min_size.maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
- max_size: child_style.max_size.maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
- overflow: child_style.overflow,
- scrollbar_width: child_style.scrollbar_width,
- position: child_style.position,
- inset: child_style.inset,
- margin: child_style.margin,
+ size: child_style.size().maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
+ min_size: child_style.min_size().maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
+ max_size: child_style.max_size().maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
+ overflow: child_style.overflow(),
+ scrollbar_width: child_style.scrollbar_width(),
+ position: child_style.position(),
+ inset: child_style.inset(),
+ margin: child_style.margin(),
padding,
border,
padding_border_sum: (padding + border).sum_axes(),
@@ -492,7 +501,7 @@ fn perform_final_layout_on_in_flow_children(
/// Perform absolute layout on all absolutely positioned children.
#[inline]
fn perform_absolute_layout_on_absolute_children(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutBlockContainer,
items: &[BlockItem],
area_size: Size<f32>,
area_offset: Point<f32>,
@@ -504,36 +513,39 @@ fn perform_absolute_layout_on_absolute_children(
let mut absolute_content_size = Size::ZERO;
for item in items.iter().filter(|item| item.position == Position::Absolute) {
- let child_style = tree.get_style(item.node_id);
+ let child_style = tree.get_block_child_style(item.node_id);
// Skip items that are display:none or are not position:absolute
- if child_style.display == Display::None || child_style.position != Position::Absolute {
+ if child_style.box_generation_mode() == BoxGenerationMode::None || child_style.position() != Position::Absolute
+ {
continue;
}
- let aspect_ratio = child_style.aspect_ratio;
- let margin = child_style.margin.map(|margin| margin.resolve_to_option(area_width));
- let padding = child_style.padding.resolve_or_zero(Some(area_width));
- let border = child_style.border.resolve_or_zero(Some(area_width));
+ let aspect_ratio = child_style.aspect_ratio();
+ let margin = child_style.margin().map(|margin| margin.resolve_to_option(area_width));
+ let padding = child_style.padding().resolve_or_zero(Some(area_width));
+ let border = child_style.border().resolve_or_zero(Some(area_width));
let padding_border_sum = (padding + border).sum_axes();
// Resolve inset
- let left = child_style.inset.left.maybe_resolve(area_width);
- let right = child_style.inset.right.maybe_resolve(area_width);
- let top = child_style.inset.top.maybe_resolve(area_height);
- let bottom = child_style.inset.bottom.maybe_resolve(area_height);
+ let left = child_style.inset().left.maybe_resolve(area_width);
+ let right = child_style.inset().right.maybe_resolve(area_width);
+ let top = child_style.inset().top.maybe_resolve(area_height);
+ let bottom = child_style.inset().bottom.maybe_resolve(area_height);
// Compute known dimensions from min/max/inherent size styles
- let style_size = child_style.size.maybe_resolve(area_size).maybe_apply_aspect_ratio(aspect_ratio);
+ let style_size = child_style.size().maybe_resolve(area_size).maybe_apply_aspect_ratio(aspect_ratio);
let min_size = child_style
- .min_size
+ .min_size()
.maybe_resolve(area_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(area_size).maybe_apply_aspect_ratio(aspect_ratio);
+ let max_size = child_style.max_size().maybe_resolve(area_size).maybe_apply_aspect_ratio(aspect_ratio);
let mut known_dimensions = style_size.maybe_clamp(min_size, max_size);
+ drop(child_style);
+
// Fill in width from left/right and reapply aspect ratio if:
// - Width is not already known
// - Item has both left and right inset properties set
diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index 67b094dfb..3812c82bb 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -2,17 +2,18 @@
use crate::compute::common::alignment::compute_alignment_offset;
use crate::geometry::{Line, Point, Rect, Size};
use crate::style::{
- AlignContent, AlignItems, AlignSelf, AvailableSpace, Dimension, Display, FlexWrap, JustifyContent,
- LengthPercentageAuto, Overflow, Position,
+ AlignContent, AlignItems, AlignSelf, AvailableSpace, Dimension, FlexWrap, JustifyContent, LengthPercentageAuto,
+ Overflow, Position,
};
-use crate::style::{FlexDirection, Style};
+use crate::style::{CoreStyle, FlexDirection, FlexboxContainerStyle, FlexboxItemStyle};
use crate::style_helpers::{TaffyMaxContent, TaffyMinContent};
use crate::tree::{Layout, LayoutInput, LayoutOutput, RunMode, SizingMode};
-use crate::tree::{LayoutPartialTree, LayoutPartialTreeExt, NodeId};
+use crate::tree::{LayoutFlexboxContainer, LayoutPartialTreeExt, NodeId};
use crate::util::debug::debug_log;
use crate::util::sys::{f32_max, new_vec_with_capacity, Vec};
use crate::util::MaybeMath;
use crate::util::{MaybeResolve, ResolveOrZero};
+use crate::BoxGenerationMode;
use super::common::alignment::apply_alignment_fallback;
#[cfg(feature = "content_size")]
@@ -153,23 +154,29 @@ struct AlgoConstants {
}
/// Computes the layout of [`LayoutPartialTree`] according to the flexbox algorithm
-pub fn compute_flexbox_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inputs: LayoutInput) -> LayoutOutput {
+pub fn compute_flexbox_layout(
+ tree: &mut impl LayoutFlexboxContainer,
+ node: NodeId,
+ inputs: LayoutInput,
+) -> LayoutOutput {
let LayoutInput { known_dimensions, parent_size, run_mode, .. } = inputs;
- let style = tree.get_style(node);
+ let style = tree.get_flexbox_container_style(node);
// Pull these out earlier to avoid borrowing issues
- 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);
- let padding = style.padding.resolve_or_zero(parent_size.width);
- let border = style.border.resolve_or_zero(parent_size.width);
+ 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);
+ let padding = style.padding().resolve_or_zero(parent_size.width);
+ let border = style.border().resolve_or_zero(parent_size.width);
let padding_border_sum = padding.sum_axes() + border.sum_axes();
let clamped_style_size = if inputs.sizing_mode == SizingMode::InherentSize {
- style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size)
+ style.size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size)
} else {
Size::NONE
};
+ drop(style);
+
// If both min and max in a given axis are set and max <= min then this determines the size in that axis
let min_max_definite_size = min_size.zip_map(max_size, |min, max| match (min, max) {
(Some(min), Some(max)) if max <= min => Some(min),
@@ -193,11 +200,11 @@ pub fn compute_flexbox_layout(tree: &mut impl LayoutPartialTree, node: NodeId, i
}
/// Compute a preliminary size for an item
-fn compute_preliminary(tree: &mut impl LayoutPartialTree, node: NodeId, inputs: LayoutInput) -> LayoutOutput {
+fn compute_preliminary(tree: &mut impl LayoutFlexboxContainer, node: NodeId, inputs: LayoutInput) -> LayoutOutput {
let LayoutInput { known_dimensions, parent_size, available_space, run_mode, .. } = inputs;
// Define some general constants we will need for the remainder of the algorithm.
- let mut constants = compute_constants(tree.get_style(node), known_dimensions, parent_size);
+ let mut constants = compute_constants(tree.get_flexbox_container_style(node), known_dimensions, parent_size);
// 9. Flex Layout Algorithm
@@ -253,9 +260,9 @@ fn compute_preliminary(tree: &mut impl LayoutPartialTree, node: NodeId, inputs:
debug_log!("constants.node_inner_size", dbg:constants.node_inner_size);
// Re-resolve percentage gaps
- let style = tree.get_style(node);
+ let style = tree.get_flexbox_container_style(node);
let inner_container_size = constants.inner_container_size.main(constants.dir);
- let new_gap = style.gap.main(constants.dir).maybe_resolve(inner_container_size).unwrap_or(0.0);
+ let new_gap = style.gap().main(constants.dir).maybe_resolve(inner_container_size).unwrap_or(0.0);
constants.gap.set_main(constants.dir, new_gap);
}
@@ -343,7 +350,7 @@ fn compute_preliminary(tree: &mut impl LayoutPartialTree, node: NodeId, inputs:
let len = tree.child_count(node);
for order in 0..len {
let child = tree.get_child_id(node, order);
- if tree.get_style(child).display == Display::None {
+ if tree.get_flexbox_child_style(child).box_generation_mode() == BoxGenerationMode::None {
tree.set_unrounded_layout(child, &Layout::with_order(order as u32));
tree.perform_child_layout(
child,
@@ -382,29 +389,29 @@ fn compute_preliminary(tree: &mut impl LayoutPartialTree, node: NodeId, inputs:
/// Compute constants that can be reused during the flexbox algorithm.
#[inline]
fn compute_constants(
- style: &Style,
+ style: impl FlexboxContainerStyle,
known_dimensions: Size<Option<f32>>,
parent_size: Size<Option<f32>>,
) -> AlgoConstants {
- let dir = style.flex_direction;
+ let dir = style.flex_direction();
let is_row = dir.is_row();
let is_column = dir.is_column();
- let is_wrap = matches!(style.flex_wrap, FlexWrap::Wrap | FlexWrap::WrapReverse);
- let is_wrap_reverse = style.flex_wrap == FlexWrap::WrapReverse;
+ 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(AlignItems::Stretch);
- let align_content = style.align_content.unwrap_or(AlignContent::Stretch);
- let justify_content = style.justify_content;
+ 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(AlignItems::Stretch);
+ let align_content = style.align_content().unwrap_or(AlignContent::Stretch);
+ let justify_content = style.justify_content();
// Scrollbar gutters are reserved when the `overflow` property is set to `Overflow::Scroll`.
// However, the axis are switched (transposed) because a node that scrolls vertically needs
// *horizontal* space to be reserved for a scrollbar
- let scrollbar_gutter = style.overflow.transpose().map(|overflow| match overflow {
- Overflow::Scroll => style.scrollbar_width,
+ let scrollbar_gutter = style.overflow().transpose().map(|overflow| match overflow {
+ Overflow::Scroll => style.scrollbar_width(),
_ => 0.0,
});
// TODO: make side configurable based on the `direction` property
@@ -414,7 +421,7 @@ fn compute_constants(
let node_outer_size = known_dimensions;
let node_inner_size = node_outer_size.maybe_sub(content_box_inset.sum_axes());
- let gap = style.gap.resolve_or_zero(node_inner_size.or(Size::zero()));
+ let gap = style.gap().resolve_or_zero(node_inner_size.or(Size::zero()));
let container_size = Size::zero();
let inner_container_size = Size::zero();
@@ -425,8 +432,8 @@ 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),
+ 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,
@@ -449,40 +456,43 @@ fn compute_constants(
/// - [**Generate anonymous flex items**](https://www.w3.org/TR/css-flexbox-1/#algo-anon-box) as described in [§4 Flex Items](https://www.w3.org/TR/css-flexbox-1/#flex-items).
#[inline]
fn generate_anonymous_flex_items(
- tree: &impl LayoutPartialTree,
+ tree: &impl LayoutFlexboxContainer,
node: NodeId,
constants: &AlgoConstants,
) -> Vec<FlexItem> {
tree.child_ids(node)
.enumerate()
- .map(|(index, child)| (index, child, tree.get_style(child)))
- .filter(|(_, _, style)| style.position != Position::Absolute)
- .filter(|(_, _, style)| style.display != Display::None)
+ .map(|(index, child)| (index, child, tree.get_flexbox_child_style(child)))
+ .filter(|(_, _, style)| style.position() != Position::Absolute)
+ .filter(|(_, _, style)| style.box_generation_mode() != BoxGenerationMode::None)
.map(|(index, child, child_style)| {
- let aspect_ratio = child_style.aspect_ratio;
+ let aspect_ratio = child_style.aspect_ratio();
FlexItem {
node: child,
order: index as u32,
- size: child_style.size.maybe_resolve(constants.node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
+ size: child_style
+ .size()
+ .maybe_resolve(constants.node_inner_size)
+ .maybe_apply_aspect_ratio(aspect_ratio),
min_size: child_style
- .min_size
+ .min_size()
.maybe_resolve(constants.node_inner_size)
.maybe_apply_aspect_ratio(aspect_ratio),
max_size: child_style
- .max_size
+ .max_size()
.maybe_resolve(constants.node_inner_size)
.maybe_apply_aspect_ratio(aspect_ratio),
- 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),
- overflow: child_style.overflow,
- scrollbar_width: child_style.scrollbar_width,
- flex_grow: child_style.flex_grow,
- flex_shrink: child_style.flex_shrink,
+ 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),
+ overflow: child_style.overflow(),
+ scrollbar_width: child_style.scrollbar_width(),
+ flex_grow: child_style.flex_grow(),
+ flex_shrink: child_style.flex_shrink(),
flex_basis: 0.0,
inner_flex_basis: 0.0,
violation: 0.0,
@@ -570,7 +580,7 @@ fn determine_available_space(
/// (For example, an item with a specified size of zero, positive padding, and box-sizing: border-box will have an outer flex base size of zero—and hence a negative inner flex base size.)
#[inline]
fn determine_flex_base_size(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutFlexboxContainer,
constants: &AlgoConstants,
available_space: Size<AvailableSpace>,
flex_items: &mut [FlexItem],
@@ -578,7 +588,8 @@ fn determine_flex_base_size(
let dir = constants.dir;
for child in flex_items.iter_mut() {
- let child_style = tree.get_style(child.node);
+ let child_style = tree.get_flexbox_child_style(child.node);
+ let flex_basis = child_style.flex_basis().maybe_resolve(constants.node_inner_size.main(dir));
// Parent size for child sizing
let cross_axis_parent_size = constants.node_inner_size.cross(dir);
@@ -605,6 +616,8 @@ fn determine_flex_base_size(
ckd
};
+ drop(child_style);
+
child.flex_basis = 'flex_basis: {
// A. If the item has a definite used flex basis, that’s the flex base size.
@@ -616,7 +629,6 @@ fn determine_flex_base_size(
// 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;
@@ -810,7 +822,7 @@ fn collect_flex_lines<'a>(
/// Determine the container's main size (if not already known)
fn determine_container_main_size(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutFlexboxContainer,
available_space: Size<AvailableSpace>,
lines: &mut [FlexLine<'_>],
constants: &mut AlgoConstants,
@@ -1216,7 +1228,7 @@ fn resolve_flexible_lengths(line: &mut FlexLine, constants: &AlgoConstants, orig
/// by performing layout with the used main size and the available space, treating auto as fit-content.
#[inline]
fn determine_hypothetical_cross_size(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutFlexboxContainer,
line: &mut FlexLine,
constants: &AlgoConstants,
available_space: Size<AvailableSpace>,
@@ -1266,7 +1278,7 @@ fn determine_hypothetical_cross_size(
/// Calculate the base lines of the children.
#[inline]
fn calculate_children_base_lines(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutFlexboxContainer,
node_size: Size<Option<f32>>,
available_space: Size<AvailableSpace>,
flex_lines: &mut [FlexLine],
@@ -1461,23 +1473,28 @@ fn handle_align_content_stretch(flex_lines: &mut [FlexLine], node_size: Size<Opt
///
/// **Note that this step does not affect the main size of the flex item, even if it has an intrinsic aspect ratio**.
#[inline]
-fn determine_used_cross_size(tree: &impl LayoutPartialTree, flex_lines: &mut [FlexLine], constants: &AlgoConstants) {
+fn determine_used_cross_size(
+ tree: &impl LayoutFlexboxContainer,
+ flex_lines: &mut [FlexLine],
+ constants: &AlgoConstants,
+) {
for line in flex_lines {
let line_cross_size = line.cross_size;
for child in line.items.iter_mut() {
- let child_style = tree.get_style(child.node);
+ let child_style = tree.get_flexbox_child_style(child.node);
child.target_size.set_cross(
constants.dir,
if child.align_self == AlignSelf::Stretch
&& !child.margin_is_auto.cross_start(constants.dir)
&& !child.margin_is_auto.cross_end(constants.dir)
- && child_style.size.cross(constants.dir) == Dimension::Auto
+ && 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
// using the aspect_ratio (if set). Both Chrome and Firefox agree on this. And reading the spec, it seems like
// a reasonable interpretation. Although it seems to me that the spec *should* apply aspect_ratio here.
- let max_size_ignoring_aspect_ratio = child_style.max_size.maybe_resolve(constants.node_inner_size);
+ let max_size_ignoring_aspect_ratio =
+ child_style.max_size().maybe_resolve(constants.node_inner_size);
(line_cross_size - child.margin.cross_axis_sum(constants.dir)).maybe_clamp(
child.min_size.cross(constants.dir),
@@ -1735,7 +1752,7 @@ fn align_flex_lines_per_align_content(flex_lines: &mut [FlexLine], constants: &A
/// Calculates the layout for a flex-item
#[allow(clippy::too_many_arguments)]
fn calculate_flex_item(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutFlexboxContainer,
item: &mut FlexItem,
total_offset_main: &mut f32,
total_offset_cross: f32,
@@ -1816,7 +1833,7 @@ fn calculate_flex_item(
/// Calculates the layout line
#[allow(clippy::too_many_arguments)]
fn calculate_layout_line(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutFlexboxContainer,
line: &mut FlexLine,
total_offset_cross: &mut f32,
#[cfg(feature = "content_size")] content_size: &mut Size<f32>,
@@ -1866,7 +1883,7 @@ fn calculate_layout_line(
/// Do a final layout pass and collect the resulting layouts.
#[inline]
fn final_layout_pass(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutFlexboxContainer,
flex_lines: &mut [FlexLine],
constants: &AlgoConstants,
) -> Size<f32> {
@@ -1911,7 +1928,7 @@ fn final_layout_pass(
/// Perform absolute layout on all absolutely positioned children.
#[inline]
fn perform_absolute_layout_on_absolute_children(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutFlexboxContainer,
node: NodeId,
constants: &AlgoConstants,
) -> Size<f32> {
@@ -1923,41 +1940,44 @@ fn perform_absolute_layout_on_absolute_children(
for order in 0..tree.child_count(node) {
let child = tree.get_child_id(node, order);
- let child_style = tree.get_style(child);
+ let child_style = tree.get_flexbox_child_style(child);
// Skip items that are display:none or are not position:absolute
- if child_style.display == Display::None || child_style.position != Position::Absolute {
+ if child_style.box_generation_mode() == BoxGenerationMode::None || child_style.position() != Position::Absolute
+ {
continue;
}
- let overflow = child_style.overflow;
- let scrollbar_width = child_style.scrollbar_width;
- let aspect_ratio = child_style.aspect_ratio;
- 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 overflow = child_style.overflow();
+ let scrollbar_width = child_style.scrollbar_width();
+ let aspect_ratio = child_style.aspect_ratio();
+ 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);
- let right = child_style.inset.right.maybe_resolve(container_width);
- let top = child_style.inset.top.maybe_resolve(container_height);
- let bottom = child_style.inset.bottom.maybe_resolve(container_height);
+ let left = child_style.inset().left.maybe_resolve(container_width);
+ let right = child_style.inset().right.maybe_resolve(container_width);
+ let top = child_style.inset().top.maybe_resolve(container_height);
+ let bottom = child_style.inset().bottom.maybe_resolve(container_height);
// 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);
+ child_style.size().maybe_resolve(constants.container_size).maybe_apply_aspect_ratio(aspect_ratio);
let min_size = child_style
- .min_size
+ .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);
+ 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);
+ drop(child_style);
+
// Fill in width from left/right and reapply aspect ratio if:
// - Width is not already known
// - Item has both left and right inset properties set
@@ -1975,7 +1995,6 @@ fn perform_absolute_layout_on_absolute_children(
known_dimensions.height = Some(f32_max(new_height_raw, 0.0));
known_dimensions = known_dimensions.maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size);
}
-
let layout_output = tree.perform_child_layout(
child,
known_dimensions,
diff --git a/src/compute/grid/alignment.rs b/src/compute/grid/alignment.rs
index 04a0e3b40..ad2bbf48b 100644
--- a/src/compute/grid/alignment.rs
+++ b/src/compute/grid/alignment.rs
@@ -2,13 +2,14 @@
use super::types::GridTrack;
use crate::compute::common::alignment::{apply_alignment_fallback, compute_alignment_offset};
use crate::geometry::{InBothAbsAxis, Line, Point, Rect, Size};
-use crate::style::{AlignContent, AlignItems, AlignSelf, AvailableSpace, Overflow, Position};
-use crate::tree::{Layout, LayoutPartialTree, LayoutPartialTreeExt, NodeId, SizingMode};
+use crate::style::{AlignContent, AlignItems, AlignSelf, AvailableSpace, CoreStyle, GridItemStyle, Overflow, Position};
+use crate::tree::{Layout, LayoutPartialTreeExt, NodeId, SizingMode};
use crate::util::sys::f32_max;
use crate::util::{MaybeMath, MaybeResolve, ResolveOrZero};
#[cfg(feature = "content_size")]
use crate::compute::common::content_size::compute_content_size_contribution;
+use crate::LayoutGridContainer;
/// Align the grid tracks within the grid according to the align-content (rows) or
/// justify-content (columns) property. This only does anything if the size of the
@@ -56,7 +57,7 @@ pub(super) fn align_tracks(
/// Align and size a grid item into it's final position
pub(super) fn align_and_position_item(
- tree: &mut impl LayoutPartialTree,
+ tree: &mut impl LayoutGridContainer,
node: NodeId,
order: u32,
grid_area: Rect<f32>,
@@ -65,28 +66,29 @@ pub(super) fn align_and_position_item(
) -> (Size<f32>, f32, f32) {
let grid_area_size = Size { width: grid_area.right - grid_area.left, height: grid_area.bottom - grid_area.top };
- let style = tree.get_style(node);
+ let style = tree.get_grid_child_style(node);
- let overflow = style.overflow;
- let scrollbar_width = style.scrollbar_width;
- let aspect_ratio = style.aspect_ratio;
- let justify_self = style.justify_self;
- let align_self = style.align_self;
+ let overflow = style.overflow();
+ let scrollbar_width = style.scrollbar_width();
+ let aspect_ratio = style.aspect_ratio();
+ let justify_self = style.justify_self();
+ let align_self = style.align_self();
- 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 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 inherent_size = style.size().maybe_resolve(grid_area_size).maybe_apply_aspect_ratio(aspect_ratio);
let min_size = style
- .min_size
+ .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);
+ 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
// Note: if the child has a preferred aspect ratio but neither width or height are set, then the width is stretched
@@ -111,7 +113,7 @@ pub(super) fn align_and_position_item(
// Note: This is not a bug. It is part of the CSS spec that both horizontal and vertical margins
// resolve against the WIDTH of the grid area.
- let margin = style.margin.map(|margin| margin.resolve_to_option(grid_area_size.width));
+ let margin = style.margin().map(|margin| margin.resolve_to_option(grid_area_size.width));
let grid_area_minus_item_margins_size = Size {
width: grid_area_size.width.maybe_sub(margin.left).maybe_sub(margin.right),
@@ -175,6 +177,7 @@ pub(super) fn align_and_position_item(
let Size { width, height } = Size { width, height }.maybe_clamp(min_size, max_size);
// Layout node
+ drop(style);
let layout_output = tree.perform_child_layout(
node,
Size { width, height },
diff --git a/src/compute/grid/explicit_grid.rs b/src/compute/grid/explicit_grid.rs
index 76ff737bf..fb05dbadf 100644
--- a/src/compute/grid/explicit_grid.rs
+++ b/src/compute/grid/explicit_grid.rs
@@ -2,18 +2,19 @@
//! This mainly consists of evaluating GridAutoTracks
use super::types::{GridTrack, TrackCounts};
use crate::geometry::{AbsoluteAxis, Size};
-use crate::style::{GridTrackRepetition, LengthPercentage, NonRepeatedTrackSizingFunction, Style, TrackSizingFunction};
+use crate::style::{GridTrackRepetition, LengthPercentage, NonRepeatedTrackSizingFunction, TrackSizingFunction};
use crate::style_helpers::TaffyAuto;
-use crate::util::sys::{GridTrackVec, Vec};
+use crate::util::sys::Vec;
use crate::util::MaybeMath;
use crate::util::ResolveOrZero;
+use crate::GridContainerStyle;
#[cfg(not(feature = "std"))]
use num_traits::float::FloatCore;
/// Compute the number of rows and columns in the explicit grid
pub(crate) fn compute_explicit_grid_size_in_axis(
- style: &Style,
+ style: &impl GridContainerStyle,
preferred_size: Size<Option<f32>>,
axis: AbsoluteAxis,
) -> u16 {
@@ -93,13 +94,13 @@ pub(crate) fn compute_explicit_grid_size_in_axis(
// - then the number of repetitions is the smallest possible positive integer that fulfills that minimum requirement
// Otherwise, the specified track list repeats only once.
let style_size = preferred_size.get_abs(axis);
- let style_min_size = style.min_size.get_abs(axis).into_option();
- let style_max_size = style.max_size.get_abs(axis).into_option();
+ let style_min_size = style.min_size().get_abs(axis).into_option();
+ let style_max_size = style.max_size().get_abs(axis).into_option();
let outer_container_size = style_size.maybe_min(style_max_size).or(style_max_size).or(style_min_size);
let inner_container_size = outer_container_size.map(|size| {
- let padding_sum = style.padding.resolve_or_zero(outer_container_size).grid_axis_sum(axis);
- let border_sum = style.border.resolve_or_zero(outer_container_size).grid_axis_sum(axis);
+ let padding_sum = style.padding().resolve_or_zero(outer_container_size).grid_axis_sum(axis);
+ let border_sum = style.border().resolve_or_zero(outer_container_size).grid_axis_sum(axis);
size - padding_sum - border_sum
});
let size_is_maximum = style_size.is_some() || style_max_size.is_some();
@@ -137,7 +138,7 @@ pub(crate) fn compute_explicit_grid_size_in_axis(
}
})
.sum();
- let gap_size = style.gap.get_abs(axis).resolve_or_zero(Some(inner_container_size));
+ let gap_size = style.gap().get_abs(axis).resolve_or_zero(Some(inner_container_size));
// Compute the amount of space that a single repetition of the repeated track list takes
let per_repetition_track_used_space: f32 = repetition_definition
@@ -185,7 +186,7 @@ pub(crate) fn compute_explicit_grid_size_in_axis(
pub(super) fn initialize_grid_tracks(
tracks: &mut Vec<GridTrack>,
counts: TrackCounts,
- track_template: &GridTrackVec<TrackSizingFunction>,
+ track_template: &[TrackSizingFunction],
auto_tracks: &[NonRepeatedTrackSizingFunction],
gap: LengthPercentage,
track_has_items: impl Fn(usize) -> bool,
diff --git a/src/compute/grid/implicit_grid.rs b/src/compute/grid/implicit_grid.rs
index 1836cbb5b..d1651218b 100644
--- a/src/compute/grid/implicit_grid.rs
+++ b/src/compute/grid/implicit_grid.rs
@@ -1,7 +1,8 @@
//! This module is not required for spec compliance, but is used as a performance optimisation
//! to reduce the number of allocations required when creating a grid.
use crate::geometry::Line;
-use crate::style::{GenericGridPlacement, GridPlacement, Style};
+use crate::style::{GenericGridPlacement, GridPlacement};
+use crate::GridItemStyle;
use core::cmp::{max, min};
use super::types::TrackCounts;
@@ -15,10 +16,10 @@ use super::OriginZeroLine;
/// in ways which are impossible to predict until the auto-placement algorithm is run.
///
/// Note that this function internally mixes use of grid track numbers and grid line numbers
-pub(crate) fn compute_grid_size_estimate<'a>(
+pub(crate) fn compute_grid_size_estimate<'a, S: GridItemStyle + 'a>(
explicit_col_count: u16,
explicit_row_count: u16,
- child_styles_iter: impl Iterator<Item = &'a Style>,
+ child_styles_iter: impl Iterator<Item = S>,
) -> (TrackCounts, TrackCounts) {
// Iterate over children, producing an estimate of the min and max grid lines (in origin-zero coordinates where)
// along with the span of each item
@@ -60,20 +61,20 @@ pub(crate) fn compute_grid_size_estimate<'a>(
///
/// Min and max grid lines are returned in origin-zero coordinates)
/// The span is measured in tracks spanned
-fn get_known_child_positions<'a>(
- children_iter: impl Iterator<Item = &'a Style>,
+fn get_known_child_positions<'a, S: GridItemStyle + 'a>(
+ children_iter: impl Iterator<Item = S>,
explicit_col_count: u16,
explicit_row_count: u16,
) -> (OriginZeroLine, OriginZeroLine, u16, OriginZeroLine, OriginZeroLine, u16) {
let (mut col_min, mut col_max, mut col_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0);
let (mut row_min, mut row_max, mut row_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0);
- children_iter.for_each(|child_style: &Style| {
+ children_iter.for_each(|child_style| {
// Note: that the children reference the lines in between (and around) the tracks not tracks themselves,
// and thus we must subtract 1 to get an accurate estimate of the number of tracks
let (child_col_min, child_col_max, child_col_span) =
- child_min_line_max_line_span(child_style.grid_column, explicit_col_count);
+ child_min_line_max_line_span(child_style.grid_column(), explicit_col_count);
let (child_row_min, child_row_max, child_row_span) =
- child_min_line_max_line_span(child_style.grid_row, explicit_row_count);
+ child_min_line_max_line_span(child_style.grid_row(), explicit_row_count);
col_min = min(col_min, child_col_min);
col_max = max(col_max, child_col_max);
col_max_span = max(col_max_span, child_col_span);
diff --git a/src/compute/grid/mod.rs b/src/compute/grid/mod.rs
index cc755769e..eec788bab 100644
--- a/src/compute/grid/mod.rs
+++ b/src/compute/grid/mod.rs
@@ -2,14 +2,14 @@
//! <https://www.w3.org/TR/css-grid-1>
use crate::geometry::{AbsoluteAxis, AbstractAxis, InBothAbsAxis};
use crate::geometry::{Line, Point, Rect, Size};
-use crate::style::{AlignContent, AlignItems, AlignSelf, AvailableSpace, Display, Overflow, Position};
-use crate::style_helpers::*;
-use crate::tree::{Layout, LayoutInput, LayoutOutput, RunMode, SizingMode};
-use crate::tree::{LayoutPartialTree, LayoutPartialTreeExt, NodeId};
+use crate::style::{AlignContent, AlignItems, AlignSelf, AvailableSpace, Overflow, Position};
+use crate::tree::{Layout, LayoutPartialTreeExt, NodeId};
+use crate::tree::{LayoutInput, LayoutOutput, RunMode, SizingMode};
use crate::util::debug::debug_log;
use crate::util::sys::{f32_max, GridTrackVec, Vec};
use crate::util::MaybeMath;
use crate::util::{MaybeResolve, ResolveOrZero};
+use crate::{style_helpers::*, BoxGenerationMode, CoreStyle, GridContainerStyle, GridItemStyle, LayoutGridContainer};
use alignment::{align_and_position_item, align_tracks};
use explicit_grid::{compute_explicit_grid_size_in_axis, initialize_grid_tracks};
use implicit_grid::compute_grid_size_estimate;
@@ -35,15 +35,16 @@ mod util;
/// - Placing items (which also resolves the implicit grid)
/// - Track (row/column) sizing
/// - Alignment & Final item placement
-pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inputs: LayoutInput) -> LayoutOutput {
+pub fn compute_grid_layout(tree: &mut impl LayoutGridContainer, node: NodeId, inputs: LayoutInput) -> LayoutOutput {
let LayoutInput { known_dimensions, parent_size, available_space, run_mode, .. } = inputs;
- let get_child_styles_iter = |node| tree.child_ids(node).map(|child_node: NodeId| tree.get_style(child_node));
- let style = tree.get_style(node).clone();
+ let get_child_styles_iter =
+ |node| tree.child_ids(node).map(|child_node: NodeId| tree.get_grid_child_style(child_node));
+ let style = tree.get_grid_container_style(node).clone();
let child_styles_iter = get_child_styles_iter(node);
let preferred_size = if inputs.sizing_mode == SizingMode::InherentSize {
- style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(style.aspect_ratio)
+ style.size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(style.aspect_ratio())
} else {
Size::NONE
};
@@ -66,16 +67,18 @@ pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inpu
let in_flow_children_iter = || {
tree.child_ids(node)
.enumerate()
- .map(|(index, child_node)| (index, child_node, tree.get_style(child_node)))
- .filter(|(_, _, style)| style.display != Display::None && style.position != Position::Absolute)
+ .map(|(index, child_node)| (index, child_node, tree.get_grid_child_style(child_node)))
+ .filter(|(_, _, style)| {
+ style.box_generation_mode() != BoxGenerationMode::None && style.position() != Position::Absolute
+ })
};
place_grid_items(
&mut cell_occupancy_matrix,
&mut items,
in_flow_children_iter,
- style.grid_auto_flow,
- style.align_items.unwrap_or(AlignItems::Stretch),
- style.justify_items.unwrap_or(AlignItems::Stretch),
+ style.grid_auto_flow(),
+ style.align_items().unwrap_or(AlignItems::Stretch),
+ style.justify_items().unwrap_or(AlignItems::Stretch),
);
// Extract track counts from previous step (auto-placement can expand the number of tracks)
@@ -90,36 +93,36 @@ pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inpu
initialize_grid_tracks(
&mut columns,
final_col_counts,
- &style.grid_template_columns,
- &style.grid_auto_columns,
- style.gap.width,
+ style.grid_template_columns(),
+ style.grid_auto_columns(),
+ style.gap().width,
|column_index| cell_occupancy_matrix.column_is_occupied(column_index),
);
initialize_grid_tracks(
&mut rows,
final_row_counts,
- &style.grid_template_rows,
- &style.grid_auto_rows,
- style.gap.height,
+ style.grid_template_rows(),
+ style.grid_auto_rows(),
+ style.gap().height,
|row_index| cell_occupancy_matrix.row_is_occupied(row_index),
);
// 4. Compute "available grid space"
// 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 = style.padding().resolve_or_zero(parent_size.width);
+ let border = style.border().resolve_or_zero(parent_size.width);
let padding_border = padding + border;
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);
+ 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);
let size = preferred_size;
// Scrollbar gutters are reserved when the `overflow` property is set to `Overflow::Scroll`.
// However, the axis are switched (transposed) because a node that scrolls vertically needs
// *horizontal* space to be reserved for a scrollbar
- let scrollbar_gutter = style.overflow.transpose().map(|overflow| match overflow {
- Overflow::Scroll => style.scrollbar_width,
+ let scrollbar_gutter = style.overflow().transpose().map(|overflow| match overflow {
+ Overflow::Scroll => style.scrollbar_width(),
_ => 0.0,
});
// TODO: make side configurable based on the `direction` property
@@ -388,7 +391,7 @@ pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inpu
Line { start: padding.left, end: padding.right },
Line { start: border.left, end: border.right },
&mut columns,
- style.justify_content.unwrap_or(AlignContent::Stretch),
+ style.justify_content().unwrap_or(AlignContent::Stretch),
);
// Align rows
align_tracks(
@@ -396,7 +399,7 @@ pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inpu
Line { start: padding.top, end: padding.bottom },
Line { start: border.top, end: border.bottom },
&mut rows,
- style.align_content.unwrap_or(AlignContent::Stretch),
+ style.align_content().unwrap_or(AlignContent::Stretch),
);
// 9. Size, Align, and Position Grid Items
@@ -407,7 +410,8 @@ pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inpu
// Sort items back into original order to allow them to be matched up with styles
items.sort_by_key(|item| item.source_order);
- let container_alignment_styles = InBothAbsAxis { horizontal: style.justify_items, vertical: style.align_items };
+ let container_alignment_styles = InBothAbsAxis { horizontal: style.justify_items(), vertical: style.align_items() };
+ drop(style);
// Position in-flow children (stored in items vector)
for (index, item) in items.iter_mut().enumerate() {
@@ -439,10 +443,11 @@ pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inpu
let mut order = items.len() as u32;
(0..tree.child_count(node)).for_each(|index| {
let child = tree.get_child_id(node, index);
- let child_style = tree.get_style(child);
+ let child_style = tree.get_grid_child_style(child);
// Position hidden child
- if child_style.display == Display::None {
+ if child_style.box_generation_mode() == BoxGenerationMode::None {
+ drop(child_style);
tree.set_unrounded_layout(child, &Layout::with_order(order));
tree.perform_child_layout(
child,
@@ -457,11 +462,11 @@ pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inpu
}
// Position absolutely positioned child
- if child_style.position == Position::Absolute {
+ if child_style.position() == Position::Absolute {
// Convert grid-col-{start/end} into Option's of indexes into the columns vector
// The Option is None if the style property is Auto and an unresolvable Span
let maybe_col_indexes = child_style
- .grid_column
+ .grid_column()
.into_origin_zero(final_col_counts.explicit)
.resolve_absolutely_positioned_grid_tracks()
.map(|maybe_grid_line| {
@@ -470,7 +475,7 @@ pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inpu
// Convert grid-row-{start/end} into Option's of indexes into the row vector
// The Option is None if the style property is Auto and an unresolvable Span
let maybe_row_indexes = child_style
- .grid_row
+ .grid_row()
.into_origin_zero(final_row_counts.explicit)
.resolve_absolutely_positioned_grid_tracks()
.map(|maybe_grid_line| {
@@ -489,6 +494,8 @@ pub fn compute_grid_layout(tree: &mut impl LayoutPartialTree, node: NodeId, inpu
.map(|index| columns[index].offset)
.unwrap_or(container_border_box.width - border.right),
};
+ drop(child_style);
+
// TODO: Baseline alignment support for absolutely positioned items (should check if is actuallty specified)
#[cfg_attr(not(feature = "content_size"), allow(unused_variables))]
let (content_size_contribution, _, _) =
diff --git a/src/compute/grid/placement.rs b/src/compute/grid/placement.rs
index bd760accb..695ac0291 100644
--- a/src/compute/grid/placement.rs
+++ b/src/compute/grid/placement.rs
@@ -4,15 +4,16 @@ use super::types::{CellOccupancyMatrix, CellOccupancyState, GridItem};
use super::OriginZeroLine;
use crate::geometry::Line;
use crate::geometry::{AbsoluteAxis, InBothAbsAxis};
-use crate::style::{AlignItems, GridAutoFlow, OriginZeroGridPlacement, Style};
+use crate::style::{AlignItems, GridAutoFlow, OriginZeroGridPlacement};
use crate::tree::NodeId;
use crate::util::sys::Vec;
+use crate::GridItemStyle;
/// 8.5. Grid Item Placement Algorithm
/// Place items into the grid, generating new rows/column into the implicit grid as required
///
/// [Specification](https://www.w3.org/TR/css-grid-2/#auto-placement-algo)
-pub(super) fn place_grid_items<'a, ChildIter>(
+pub(super) fn place_grid_items<'a, S, ChildIter>(
cell_occupancy_matrix: &mut CellOccupancyMatrix,
items: &mut Vec<GridItem>,
children_iter: impl Fn() -> ChildIter,
@@ -20,7 +21,8 @@ pub(super) fn place_grid_items<'a, ChildIter>(
align_items: AlignItems,
justify_items: AlignItems,
) where
- ChildIter: Iterator<Item = (usize, NodeId, &'a Style)>,
+ S: GridItemStyle + 'a,
+ ChildIter: Iterator<Item = (usize, NodeId, S)>,
{
let primary_axis = grid_auto_flow.primary_axis();
let secondary_axis = primary_axis.other_axis();
@@ -28,10 +30,12 @@ pub(super) fn place_grid_items<'a, ChildIter>(
let map_child_style_to_origin_zero_placement = {
let explicit_col_count = cell_occupancy_matrix.track_counts(AbsoluteAxis::Horizontal).explicit;
let explicit_row_count = cell_occupancy_matrix.track_counts(AbsoluteAxis::Vertical).explicit;
- move |(index, node, style): (usize, NodeId, &'a Style)| -> (_, _, _, &'a Style) {
+ move |(index, node, style): (usize, NodeId, S)| -> (_, _, _, S) {
let origin_zero_placement = InBothAbsAxis {
- horizontal: style.grid_column.map(|placement| placement.into_origin_zero_placement(explicit_col_count)),
- vertical: style.grid_row.map(|placement| placement.into_origin_zero_placement(explicit_row_count)),
+ horizontal: style
+ .grid_column()
+ .map(|placement| placement.into_origin_zero_placement(explicit_col_count)),
+ vertical: style.grid_row().map(|placement| placement.into_origin_zero_placement(explicit_row_count)),
};
(index, node, origin_zero_placement, style)
}
@@ -40,7 +44,7 @@ pub(super) fn place_grid_items<'a, ChildIter>(
// 1. Place children with definite positions
let mut idx = 0;
children_iter()
- .filter(|(_, _, child_style)| child_style.grid_row.is_definite() && child_style.grid_column.is_definite())
+ .filter(|(_, _, child_style)| child_style.grid_row().is_definite() && child_style.grid_column().is_definite())
.map(map_child_style_to_origin_zero_placement)
.for_each(|(index, child_node, child_placement, style)| {
idx += 1;
@@ -296,12 +300,12 @@ fn place_indefinitely_positioned_item(
/// Record the grid item in both CellOccupancyMatric and the GridItems list
/// once a definite placement has been determined
#[allow(clippy::too_many_arguments)]
-fn record_grid_placement(
+fn record_grid_placement<S: GridItemStyle>(
cell_occupancy_matrix: &mut CellOccupancyMatrix,
items: &mut Vec<GridItem>,
node: NodeId,
index: usize,
- style: &Style,
+ style: S,
parent_align_items: AlignItems,
parent_justify_items: AlignItems,
primary_axis: AbsoluteAxis,
diff --git a/src/compute/grid/types/grid_item.rs b/src/compute/grid/types/grid_item.rs
index 8c33798a6..acdc16a01 100644
--- a/src/compute/grid/types/grid_item.rs
+++ b/src/compute/grid/types/grid_item.rs
@@ -5,10 +5,11 @@ use crate::geometry::AbstractAxis;
use crate::geometry::{Line, Point, Rect, Size};
use crate::style::{
AlignItems, AlignSelf, AvailableSpace, Dimension, LengthPercentageAuto, MaxTrackSizingFunction,
- MinTrackSizingFunction, Overflow, Style,
+ MinTrackSizingFunction, Overflow,
};
use crate::tree::{LayoutPartialTree, LayoutPartialTreeExt, NodeId, SizingMode};
use crate::util::{MaybeMath, MaybeResolve, ResolveOrZero};
+use crate::GridItemStyle;
use core::ops::Range;
/// Represents a single grid item
@@ -86,11 +87,11 @@ pub(in super::super) struct GridItem {
impl GridItem {
/// Create a new item given a concrete placement in both axes
- pub fn new_with_placement_style_and_order(
+ pub fn new_with_placement_style_and_order<S: GridItemStyle>(
node: NodeId,
col_span: Line<OriginZeroLine>,
row_span: Line<OriginZeroLine>,
- style: &Style,
+ style: S,
parent_align_items: AlignItems,
parent_justify_items: AlignItems,
source_order: u16,
@@ -100,14 +101,14 @@ impl GridItem {
source_order,
row: row_span,
column: col_span,
- overflow: style.overflow,
- size: style.size,
- min_size: style.min_size,
- max_size: style.max_size,
- aspect_ratio: style.aspect_ratio,
- margin: style.margin,
- align_self: style.align_self.unwrap_or(parent_align_items),
- justify_self: style.justify_self.unwrap_or(parent_justify_items),
+ overflow: style.overflow(),
+ size: style.size(),
+ min_size: style.min_size(),
+ max_size: style.max_size(),
+ aspect_ratio: style.aspect_ratio(),
+ margin: style.margin(),
+ align_self: style.align_self().unwrap_or(parent_align_items),
+ justify_self: style.justify_self().unwrap_or(parent_justify_items),
baseline: None,
baseline_shim: 0.0,
row_indexes: Line { start: 0, end: 0 }, // Properly initialised later
diff --git a/src/compute/leaf.rs b/src/compute/leaf.rs
index c6bc177b7..ebcaecfaf 100644
--- a/src/compute/leaf.rs
+++ b/src/compute/leaf.rs
@@ -1,19 +1,20 @@
//! Computes size using styles and measure functions
use crate::geometry::{Point, Size};
-use crate::style::{AvailableSpace, Display, Overflow, Position, Style};
+use crate::style::{AvailableSpace, Overflow, Position};
use crate::tree::{CollapsibleMarginSet, RunMode};
use crate::tree::{LayoutInput, LayoutOutput, SizingMode};
use crate::util::debug::debug_log;
use crate::util::sys::f32_max;
use crate::util::MaybeMath;
use crate::util::{MaybeResolve, ResolveOrZero};
+use crate::CoreStyle;
use core::unreachable;
/// Compute the size of a leaf node (node with no children)
pub fn compute_leaf_layout<MeasureFunction>(
inputs: LayoutInput,
- style: &Style,
+ style: &impl CoreStyle,
measure_function: MeasureFunction,
) -> LayoutOutput
where
@@ -31,10 +32,10 @@ where
(node_size, node_min_size, node_max_size, None)
}
SizingMode::InherentSize => {
- let aspect_ratio = style.aspect_ratio;
- let style_size = style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
- let style_min_size = style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
- let style_max_size = style.max_size.maybe_resolve(parent_size);
+ let aspect_ratio = style.aspect_ratio();
+ let style_size = style.size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
+ let style_min_size = style.min_size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
+ let style_max_size = style.max_size().maybe_resolve(parent_size);
let node_size = known_dimensions.or(style_size);
(node_size, style_min_size, style_max_size, aspect_ratio)
@@ -43,16 +44,16 @@ where
// 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 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 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 padding_border = padding + border;
// Scrollbar gutters are reserved when the `overflow` property is set to `Overflow::Scroll`.
// However, the axis are switched (transposed) because a node that scrolls vertically needs
// *horizontal* space to be reserved for a scrollbar
- let scrollbar_gutter = style.overflow.transpose().map(|overflow| match overflow {
- Overflow::Scroll => style.scrollbar_width,
+ let scrollbar_gutter = style.overflow().transpose().map(|overflow| match overflow {
+ Overflow::Scroll => style.scrollbar_width(),
_ => 0.0,
});
// TODO: make side configurable based on the `direction` property
@@ -60,15 +61,10 @@ where
content_box_inset.right += scrollbar_gutter.x;
content_box_inset.bottom += scrollbar_gutter.y;
- #[cfg(feature = "block_layout")]
- let is_block = style.display == Display::Block;
- #[cfg(not(feature = "block_layout"))]
- let is_block = false;
-
- let has_styles_preventing_being_collapsed_through = !is_block
- || style.overflow.x.is_scroll_container()
- || style.overflow.y.is_scroll_container()
- || style.position == Position::Absolute
+ let has_styles_preventing_being_collapsed_through = !style.is_block()
+ || style.overflow().x.is_scroll_container()
+ || style.overflow().y.is_scroll_container()
+ || style.position() == Position::Absolute
|| padding.top > 0.0
|| padding.bottom > 0.0
|| border.top > 0.0
diff --git a/src/compute/mod.rs b/src/compute/mod.rs
index 746997af4..5af70e8fb 100644
--- a/src/compute/mod.rs
+++ b/src/compute/mod.rs
@@ -45,7 +45,7 @@ pub use self::flexbox::compute_flexbox_layout;
pub use self::grid::compute_grid_layout;
use crate::geometry::{Line, Point, Size};
-use crate::style::{AvailableSpace, Overflow};
+use crate::style::{AvailableSpace, CoreStyle, Overflow};
use crate::tree::{
Layout, LayoutInput, LayoutOutput, LayoutPartialTree, LayoutPartialTreeExt, NodeId, RoundTree, SizingMode,
};
@@ -65,13 +65,14 @@ pub fn compute_root_layout(tree: &mut impl LayoutPartialTree, root: NodeId, avai
Line::FALSE,
);
- let style = tree.get_style(root);
- let padding = style.padding.resolve_or_zero(available_space.width.into_option());
- let border = style.border.resolve_or_zero(available_space.width.into_option());
+ let style = tree.get_core_container_style(root);
+ let padding = style.padding().resolve_or_zero(available_space.width.into_option());
+ let border = style.border().resolve_or_zero(available_space.width.into_option());
let scrollbar_size = Size {
- width: if style.overflow.y == Overflow::Scroll { style.scrollbar_width } else { 0.0 },
- height: if style.overflow.x == Overflow::Scroll { style.scrollbar_width } else { 0.0 },
+ width: if style.overflow().y == Overflow::Scroll { style.scrollbar_width() } else { 0.0 },
+ height: if style.overflow().x == Overflow::Scroll { style.scrollbar_width() } else { 0.0 },
};
+ drop(style);
tree.set_unrounded_layout(
root,
diff --git a/src/style/grid.rs b/src/style/grid.rs
index 0394b763d..d2597e69c 100644
--- a/src/style/grid.rs
+++ b/src/style/grid.rs
@@ -63,6 +63,24 @@ pub trait GridContainerStyle: CoreStyle {
fn justify_items(&self) -> Option<AlignItems> {
Style::DEFAULT.justify_items
}
+
+ /// Get a grid item's row or column placement depending on the axis passed
+ #[inline(always)]
+ fn grid_template_tracks(&self, axis: AbsoluteAxis) -> &[TrackSizingFunction] {
+ match axis {
+ AbsoluteAxis::Horizontal => self.grid_template_columns(),
+ AbsoluteAxis::Vertical => self.grid_template_rows(),
+ }
+ }
+
+ /// Get a grid container's align-content or justify-content alignment depending on the axis passed
+ #[inline(always)]
+ fn grid_align_content(&self, axis: AbstractAxis) -> AlignContent {
+ match axis {
+ AbstractAxis::Inline => self.justify_content().unwrap_or(AlignContent::Stretch),
+ AbstractAxis::Block => self.align_content().unwrap_or(AlignContent::Stretch),
+ }
+ }
}
/// The set of styles required for a CSS Grid item (child of a CSS Grid container)
@@ -90,6 +108,15 @@ pub trait GridItemStyle: CoreStyle {
fn justify_self(&self) -> Option<AlignSelf> {
Style::DEFAULT.justify_self
}
+
+ /// Get a grid item's row or column placement depending on the axis passed
+ #[inline(always)]
+ fn grid_placement(&self, axis: AbsoluteAxis) -> Line<GridPlacement> {
+ match axis {
+ AbsoluteAxis::Horizontal => self.grid_column(),
+ AbsoluteAxis::Vertical => self.grid_row(),
+ }
+ }
}
/// Controls whether grid items are placed row-wise or column-wise. And whether the sparse or dense packing algorithm is used.
@@ -684,30 +711,3 @@ impl From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>> for TrackSizin
Self::Single(input)
}
}
-
-// Grid extensions to the Style struct
-impl Style {
- /// Get a grid item's row or column placement depending on the axis passed
- pub(crate) fn grid_template_tracks(&self, axis: AbsoluteAxis) -> &GridTrackVec<TrackSizingFunction> {
- match axis {
- AbsoluteAxis::Horizontal => &self.grid_template_columns,
- AbsoluteAxis::Vertical => &self.grid_template_rows,
- }
- }
-
- /// Get a grid item's row or column placement depending on the axis passed
- pub(crate) fn grid_placement(&self, axis: AbsoluteAxis) -> Line<GridPlacement> {
- match axis {
- AbsoluteAxis::Horizontal => self.grid_column,
- AbsoluteAxis::Vertical => self.grid_row,
- }
- }
-
- /// Get a grid container's align-content or justify-content alignment depending on the axis passed
- pub(crate) fn grid_align_content(&self, axis: AbstractAxis) -> AlignContent {
- match axis {
- AbstractAxis::Inline => self.justify_content.unwrap_or(AlignContent::Stretch),
- AbstractAxis::Block => self.align_content.unwrap_or(AlignContent::Stretch),
- }
- }
-}
diff --git a/src/style/mod.rs b/src/style/mod.rs
index bcc4a436e..dded20527 100644
--- a/src/style/mod.rs
+++ b/src/style/mod.rs
@@ -40,6 +40,11 @@ pub trait CoreStyle {
fn box_generation_mode(&self) -> BoxGenerationMode {
BoxGenerationMode::DEFAULT
}
+ /// Is block layout?
+ #[inline(always)]
+ fn is_block(&self) -> bool {
+ false
+ }
// Overflow properties
/// How children overflowing their container should affect layout
@@ -106,6 +111,12 @@ pub trait CoreStyle {
}
}
+// trait BlockChildStyle : CoreStyle {
+// fn is_block_node() -> bool {
+// false
+// }
+// }
+
/// Sets the layout used for the children of this node
///
/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None.
@@ -475,6 +486,11 @@ impl CoreStyle for Style {
}
}
#[inline(always)]
+ #[cfg(feature = "block_layout")]
+ fn is_block(&self) -> bool {
+ matches!(self.display, Display::Block)
+ }
+ #[inline(always)]
fn overflow(&self) -> Point<Overflow> {
self.overflow
}
@@ -520,8 +536,62 @@ impl CoreStyle for Style {
}
}
+impl<T: CoreStyle> CoreStyle for &'_ T {
+ #[inline(always)]
+ fn box_generation_mode(&self) -> BoxGenerationMode {
+ (*self).box_generation_mode()
+ }
+ fn is_block(&self) -> bool {
+ (*self).is_block()
+ }
+ #[inline(always)]
+ fn overflow(&self) -> Point<Overflow> {
+ (*self).overflow()
+ }
+ #[inline(always)]
+ fn scrollbar_width(&self) -> f32 {
+ (*self).scrollbar_width()
+ }
+ #[inline(always)]
+ fn position(&self) -> Position {
+ (*self).position()
+ }
+ #[inline(always)]
+ fn inset(&self) -> Rect<LengthPercentageAuto> {
+ (*self).inset()
+ }
+ #[inline(always)]
+ fn size(&self) -> Size<Dimension> {
+ (*self).size()
+ }
+ #[inline(always)]
+ fn min_size(&self) -> Size<Dimension> {
+ (*self).min_size()
+ }
+ #[inline(always)]
+ fn max_size(&self) -> Size<Dimension> {
+ (*self).max_size()
+ }
+ #[inline(always)]
+ fn aspect_ratio(&self) -> Option<f32> {
+ (*self).aspect_ratio()
+ }
+ #[inline(always)]
+ fn margin(&self) -> Rect<LengthPercentageAuto> {
+ (*self).margin()
+ }
+ #[inline(always)]
+ fn padding(&self) -> Rect<LengthPercentage> {
+ (*self).padding()
+ }
+ #[inline(always)]
+ fn border(&self) -> Rect<LengthPercentage> {
+ (*self).border()
+ }
+}
+
#[cfg(feature = "flexbox")]
-impl FlexboxContainerStyle for Style {
+impl FlexboxContainerStyle for &Style {
#[inline(always)]
fn flex_direction(&self) -> FlexDirection {
self.flex_direction
@@ -547,6 +617,35 @@ impl FlexboxContainerStyle for Style {
self.justify_content
}
}
+
+#[cfg(feature = "flexbox")]
+impl<T: FlexboxContainerStyle> FlexboxContainerStyle for &'_ T {
+ #[inline(always)]
+ fn flex_direction(&self) -> FlexDirection {
+ (*self).flex_direction()
+ }
+ #[inline(always)]
+ fn flex_wrap(&self) -> FlexWrap {
+ (*self).flex_wrap()
+ }
+ #[inline(always)]
+ fn gap(&self) -> Size<LengthPercentage> {
+ (*self).gap()
+ }
+ #[inline(always)]
+ fn align_content(&self) -> Option<AlignContent> {
+ (*self).align_content()
+ }
+ #[inline(always)]
+ fn align_items(&self) -> Option<AlignItems> {
+ (*self).align_items()
+ }
+ #[inline(always)]
+ fn justify_content(&self) -> Option<JustifyContent> {
+ (*self).justify_content()
+ }
+}
+
#[cfg(feature = "flexbox")]
impl FlexboxItemStyle for Style {
#[inline(always)]
@@ -567,6 +666,26 @@ impl FlexboxItemStyle for Style {
}
}
+#[cfg(feature = "flexbox")]
+impl<T: FlexboxItemStyle> FlexboxItemStyle for &'_ T {
+ #[inline(always)]
+ fn flex_basis(&self) -> Dimension {
+ (*self).flex_basis()
+ }
+ #[inline(always)]
+ fn flex_grow(&self) -> f32 {
+ (*self).flex_grow()
+ }
+ #[inline(always)]
+ fn flex_shrink(&self) -> f32 {
+ (*self).flex_shrink()
+ }
+ #[inline(always)]
+ fn align_self(&self) -> Option<AlignSelf> {
+ (*self).align_self()
+ }
+}
+
#[cfg(feature = "grid")]
impl GridContainerStyle for Style {
#[inline(always)]
@@ -610,8 +729,53 @@ impl GridContainerStyle for Style {
self.justify_items
}
}
+
#[cfg(feature = "grid")]
-impl GridItemStyle for Style {
+impl<T: GridContainerStyle> GridContainerStyle for &'_ T {
+ #[inline(always)]
+ fn grid_template_rows(&self) -> &[TrackSizingFunction] {
+ &(*self).grid_template_rows()
+ }
+ #[inline(always)]
+ fn grid_template_columns(&self) -> &[TrackSizingFunction] {
+ &(*self).grid_template_columns()
+ }
+ #[inline(always)]
+ fn grid_auto_rows(&self) -> &[NonRepeatedTrackSizingFunction] {
+ &(*self).grid_auto_rows()
+ }
+ #[inline(always)]
+ fn grid_auto_columns(&self) -> &[NonRepeatedTrackSizingFunction] {
+ &(*self).grid_auto_columns()
+ }
+ #[inline(always)]
+ fn grid_auto_flow(&self) -> GridAutoFlow {
+ (*self).grid_auto_flow()
+ }
+ #[inline(always)]
+ fn gap(&self) -> Size<LengthPercentage> {
+ (*self).gap()
+ }
+ #[inline(always)]
+ fn align_content(&self) -> Option<AlignContent> {
+ (*self).align_content()
+ }
+ #[inline(always)]
+ fn justify_content(&self) -> Option<JustifyContent> {
+ (*self).justify_content()
+ }
+ #[inline(always)]
+ fn align_items(&self) -> Option<AlignItems> {
+ (*self).align_items()
+ }
+ #[inline(always)]
+ fn justify_items(&self) -> Option<AlignItems> {
+ (*self).justify_items()
+ }
+}
+
+#[cfg(feature = "grid")]
+impl GridItemStyle for &'_ Style {
#[inline(always)]
fn grid_row(&self) -> Line<GridPlacement> {
self.grid_row
@@ -630,6 +794,26 @@ impl GridItemStyle for Style {
}
}
+#[cfg(feature = "grid")]
+impl<T: GridItemStyle> GridItemStyle for &'_ T {
+ #[inline(always)]
+ fn grid_row(&self) -> Line<GridPlacement> {
+ (*self).grid_row()
+ }
+ #[inline(always)]
+ fn grid_column(&self) -> Line<GridPlacement> {
+ (*self).grid_column()
+ }
+ #[inline(always)]
+ fn align_self(&self) -> Option<AlignSelf> {
+ (*self).align_self()
+ }
+ #[inline(always)]
+ fn justify_self(&self) -> Option<AlignSelf> {
+ (*self).justify_self()
+ }
+}
+
#[cfg(test)]
mod tests {
use super::Style;
diff --git a/src/tree/taffy_tree.rs b/src/tree/taffy_tree.rs
index 664dc71cd..72898bf09 100644
--- a/src/tree/taffy_tree.rs
+++ b/src/tree/taffy_tree.rs
@@ -23,6 +23,7 @@ use crate::compute::compute_grid_layout;
use crate::compute::{
compute_cached_layout, compute_hidden_layout, compute_leaf_layout, compute_root_layout, round_layout,
};
+use crate::{LayoutBlockContainer, LayoutFlexboxContainer, LayoutGridContainer};
/// The error Taffy generates on invalid operations
pub type TaffyResult<T> = Result<T, TaffyError>;
@@ -267,9 +268,11 @@ where
MeasureFunction:
FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
{
+ type CoreContainerStyle<'a> = &'a Style where Self : 'a;
+
#[inline(always)]
- fn get_style(&self, node: NodeId) -> &Style {
- &self.taffy.nodes[node.into()].style
+ fn get_core_container_style(&self, node_id: NodeId) -> Self::CoreContainerStyle<'_> {
+ &self.taffy.nodes[node_id.into()].style
}
#[inline(always)]
@@ -297,7 +300,7 @@ where
//
// If there was no cache match and a new result needs to be computed then that result will be added to the cache
compute_cached_layout(self, node, inputs, |tree, node, inputs| {
- let display_mode = tree.get_style(node).display;
+ let display_mode = tree.taffy.nodes[node.into()].style.display;
let has_children = tree.child_count(node) > 0;
debug_log!(display_mode);
@@ -333,6 +336,60 @@ where
}
}
+impl<'t, NodeContext, MeasureFunction> LayoutBlockContainer for TaffyView<'t, NodeContext, MeasureFunction>
+where
+ MeasureFunction: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>) -> Size<f32>,
+{
+ type ContainerStyle<'a> = &'a Style where Self: 'a;
+ type ItemStyle<'a> = &'a Style where Self: 'a;
+
+ #[inline(always)]
+ fn get_block_container_style(&self, node_id: NodeId) -> Self::ContainerStyle<'_> {
+ self.get_core_container_style(node_id)
+ }
+
+ #[inline(always)]
+ fn get_block_child_style(&self, child_node_id: NodeId) -> Self::ItemStyle<'_> {
+ self.get_core_container_style(child_node_id)
+ }
+}
+
+impl<'t, NodeContext, MeasureFunction> LayoutFlexboxContainer for TaffyView<'t, NodeContext, MeasureFunction>
+where
+ MeasureFunction: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>) -> Size<f32>,
+{
+ type ContainerStyle<'a> = &'a Style where Self: 'a;
+ type ItemStyle<'a> = &'a Style where Self: 'a;
+
+ #[inline(always)]
+ fn get_flexbox_container_style(&self, node_id: NodeId) -> Self::ContainerStyle<'_> {
+ &self.taffy.nodes[node_id.into()].style
+ }
+
+ #[inline(always)]
+ fn get_flexbox_child_style(&self, child_node_id: NodeId) -> Self::ItemStyle<'_> {
+ &self.taffy.nodes[child_node_id.into()].style
+ }
+}
+
+impl<'t, NodeContext, MeasureFunction> LayoutGridContainer for TaffyView<'t, NodeContext, MeasureFunction>
+where
+ MeasureFunction: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>) -> Size<f32>,
+{
+ type ContainerStyle = Style;
+ type ItemStyle<'a> = &'a Style where Self: 'a;
+
+ #[inline(always)]
+ fn get_grid_container_style(&self, node_id: NodeId) -> &Self::ContainerStyle {
+ &self.taffy.nodes[node_id.into()].style
+ }
+
+ #[inline(always)]
+ fn get_grid_child_style(&self, child_node_id: NodeId) -> Self::ItemStyle<'_> {
+ &self.taffy.nodes[child_node_id.into()].style
+ }
+}
+
// RoundTree impl for TaffyView
impl<'t, NodeContext, MeasureFunction> RoundTree for TaffyView<'t, NodeContext, MeasureFunction>
where
diff --git a/src/tree/traits.rs b/src/tree/traits.rs
index 87a91baac..02324dbf9 100644
--- a/src/tree/traits.rs
+++ b/src/tree/traits.rs
@@ -128,7 +128,7 @@
//!
use super::{Cache, Layout, LayoutInput, LayoutOutput, NodeId, RequestedAxis, RunMode, SizingMode};
use crate::geometry::{AbsoluteAxis, Line, Size};
-use crate::style::{AvailableSpace, CoreStyle, Style};
+use crate::style::{AvailableSpace, CoreStyle};
#[cfg(feature = "flexbox")]
use crate::style::{FlexboxContainerStyle, FlexboxItemStyle};
#[cfg(feature = "grid")]
@@ -161,8 +161,14 @@ pub trait TraverseTree: TraversePartialTree {}
/// Note that this trait extends [`TraversePartialTree`] (not [`TraverseTree`]). Taffy's algorithm implementations have been designed such that they can be used for a laying out a single
/// node that only has access to it's immediate children.
pub trait LayoutPartialTree: TraversePartialTree {
- /// Get a reference to the [`Style`] for this node.
- fn get_style(&self, node_id: NodeId) -> &Style;
+ /// The style type representing the core container styles that all containers should have
+ /// Used when laying out the root node of a tree
+ type CoreContainerStyle<'a>: CoreStyle
+ where
+ Self: 'a;
+
+ /// Get core style
+ fn get_core_container_style(&self, node_id: NodeId) -> Self::CoreContainerStyle<'_>;
/// Set the node's unrounded layout
fn set_unrounded_layout(&mut self, node_id: NodeId, layout: &Layout);
@@ -208,29 +214,28 @@ pub trait LayoutFlexboxContainer: LayoutPartialTree {
Self: 'a;
/// Get the container's styles
- fn get_container_style(&self, node_id: NodeId) -> Self::ContainerStyle<'_>;
+ fn get_flexbox_container_style(&self, node_id: NodeId) -> Self::ContainerStyle<'_>;
/// Get the child's styles
- fn get_child_style(&self, child_node_id: NodeId) -> Self::ItemStyle<'_>;
+ fn get_flexbox_child_style(&self, child_node_id: NodeId) -> Self::ItemStyle<'_>;
}
#[cfg(feature = "grid")]
/// Extends [`LayoutPartialTree`] with getters for the styles required for CSS Grid layout
pub trait LayoutGridContainer: LayoutPartialTree {
/// The style type representing the CSS Grid container's styles
- type ContainerStyle<'a>: GridContainerStyle
- where
- Self: 'a;
+ type ContainerStyle: GridContainerStyle + Clone;
+
/// The style type representing each CSS Grid item's styles
type ItemStyle<'a>: GridItemStyle
where
Self: 'a;
/// Get the container's styles
- fn get_container_style(&self, node_id: NodeId) -> Self::ContainerStyle<'_>;
+ fn get_grid_container_style(&self, node_id: NodeId) -> &Self::ContainerStyle;
/// Get the child's styles
- fn get_child_style(&self, child_node_id: NodeId) -> Self::ItemStyle<'_>;
+ fn get_grid_child_style(&self, child_node_id: NodeId) -> Self::ItemStyle<'_>;
}
#[cfg(feature = "block_layout")]
@@ -246,10 +251,10 @@ pub trait LayoutBlockContainer: LayoutPartialTree {
Self: 'a;
/// Get the container's styles
- fn get_container_style(&self, node_id: NodeId) -> Self::ContainerStyle<'_>;
+ fn get_block_container_style(&self, node_id: NodeId) -> Self::ContainerStyle<'_>;
/// Get the child's styles
- fn get_child_style(&self, child_node_id: NodeId) -> Self::ItemStyle<'_>;
+ fn get_block_child_style(&self, child_node_id: NodeId) -> Self::ItemStyle<'_>;
}
// --- PRIVATE TRAITS