Skip to content

Commit 19cae8f

Browse files
committed
Convert algorithms to traitified styles
1 parent d7ebe44 commit 19cae8f

14 files changed

+594
-303
lines changed

src/compute/block.rs

Lines changed: 76 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Computes the CSS block layout algorithm in the case that the block container being laid out contains only block-level boxes
22
use crate::geometry::{Line, Point, Rect, Size};
3-
use crate::style::{AvailableSpace, Display, LengthPercentageAuto, Overflow, Position};
3+
use crate::style::{AvailableSpace, CoreStyle, LengthPercentageAuto, Overflow, Position};
44
use crate::style_helpers::TaffyMaxContent;
55
use crate::tree::{CollapsibleMarginSet, Layout, LayoutInput, LayoutOutput, RunMode, SizingMode};
66
use crate::tree::{LayoutPartialTree, LayoutPartialTreeExt, NodeId};
@@ -9,6 +9,7 @@ use crate::util::sys::f32_max;
99
use crate::util::sys::Vec;
1010
use crate::util::MaybeMath;
1111
use crate::util::{MaybeResolve, ResolveOrZero};
12+
use crate::{BoxGenerationMode, LayoutBlockContainer};
1213

1314
#[cfg(feature = "content_size")]
1415
use super::common::content_size::compute_content_size_contribution;
@@ -56,25 +57,31 @@ struct BlockItem {
5657
can_be_collapsed_through: bool,
5758
}
5859

59-
/// Computes the layout of [`LayoutPartialTree`] according to the block layout algorithm
60-
pub fn compute_block_layout(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: LayoutInput) -> LayoutOutput {
60+
/// Computes the layout of [`LayoutBlockContainer`] according to the block layout algorithm
61+
pub fn compute_block_layout(
62+
tree: &mut impl LayoutBlockContainer,
63+
node_id: NodeId,
64+
inputs: LayoutInput,
65+
) -> LayoutOutput {
6166
let LayoutInput { known_dimensions, parent_size, available_space, run_mode, .. } = inputs;
62-
let style = tree.get_style(node_id);
67+
let style = tree.get_block_container_style(node_id);
6368

6469
// Pull these out earlier to avoid borrowing issues
65-
let aspect_ratio = style.aspect_ratio;
66-
let margin = style.margin.resolve_or_zero(parent_size.width);
67-
let min_size = style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
68-
let max_size = style.max_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
69-
let padding = style.padding.resolve_or_zero(parent_size.width);
70-
let border = style.border.resolve_or_zero(parent_size.width);
70+
let aspect_ratio = style.aspect_ratio();
71+
let margin = style.margin().resolve_or_zero(parent_size.width);
72+
let min_size = style.min_size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
73+
let max_size = style.max_size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
74+
let padding = style.padding().resolve_or_zero(parent_size.width);
75+
let border = style.border().resolve_or_zero(parent_size.width);
7176
let padding_border_size = (padding + border).sum_axes();
7277
let clamped_style_size = if inputs.sizing_mode == SizingMode::InherentSize {
73-
style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size)
78+
style.size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size)
7479
} else {
7580
Size::NONE
7681
};
7782

83+
drop(style);
84+
7885
// If both min and max in a given axis are set and max <= min then this determines the size in that axis
7986
let min_max_definite_size = min_size.zip_map(max_size, |min, max| match (min, max) {
8087
(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,
103110
compute_inner(tree, node_id, LayoutInput { known_dimensions: styled_based_known_dimensions, ..inputs })
104111
}
105112

106-
/// Computes the layout of [`LayoutPartialTree`] according to the block layout algorithm
107-
fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: LayoutInput) -> LayoutOutput {
113+
/// Computes the layout of [`LayoutBlockContainer`] according to the block layout algorithm
114+
fn compute_inner(tree: &mut impl LayoutBlockContainer, node_id: NodeId, inputs: LayoutInput) -> LayoutOutput {
108115
let LayoutInput {
109116
known_dimensions, parent_size, available_space, run_mode, vertical_margins_are_collapsible, ..
110117
} = inputs;
111118

112-
let style = tree.get_style(node_id);
113-
let raw_padding = style.padding;
114-
let raw_border = style.border;
115-
let raw_margin = style.margin;
116-
let aspect_ratio = style.aspect_ratio;
117-
let size = style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
118-
let min_size = style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
119-
let max_size = style.max_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
120-
let padding = style.padding.resolve_or_zero(parent_size.width);
121-
let border = style.border.resolve_or_zero(parent_size.width);
119+
let style = tree.get_block_container_style(node_id);
120+
let raw_padding = style.padding();
121+
let raw_border = style.border();
122+
let raw_margin = style.margin();
123+
let aspect_ratio = style.aspect_ratio();
124+
let size = style.size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
125+
let min_size = style.min_size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
126+
let max_size = style.max_size().maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
127+
let padding = style.padding().resolve_or_zero(parent_size.width);
128+
let border = style.border().resolve_or_zero(parent_size.width);
122129

123130
// Scrollbar gutters are reserved when the `overflow` property is set to `Overflow::Scroll`.
124131
// However, the axis are switched (transposed) because a node that scrolls vertically needs
125132
// *horizontal* space to be reserved for a scrollbar
126133
let scrollbar_gutter = {
127-
let offsets = style.overflow.transpose().map(|overflow| match overflow {
128-
Overflow::Scroll => style.scrollbar_width,
134+
let offsets = style.overflow().transpose().map(|overflow| match overflow {
135+
Overflow::Scroll => style.scrollbar_width(),
129136
_ => 0.0,
130137
});
131138
// 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
139146
// Determine margin collapsing behaviour
140147
let own_margins_collapse_with_children = Line {
141148
start: vertical_margins_are_collapsible.start
142-
&& !style.overflow.x.is_scroll_container()
143-
&& !style.overflow.y.is_scroll_container()
144-
&& style.position == Position::Relative
149+
&& !style.overflow().x.is_scroll_container()
150+
&& !style.overflow().y.is_scroll_container()
151+
&& style.position() == Position::Relative
145152
&& padding.top == 0.0
146153
&& border.top == 0.0,
147154
end: vertical_margins_are_collapsible.end
148-
&& !style.overflow.x.is_scroll_container()
149-
&& !style.overflow.y.is_scroll_container()
150-
&& style.position == Position::Relative
155+
&& !style.overflow().x.is_scroll_container()
156+
&& !style.overflow().y.is_scroll_container()
157+
&& style.position() == Position::Relative
151158
&& padding.bottom == 0.0
152159
&& border.bottom == 0.0
153160
&& size.height.is_none(),
154161
};
155-
let has_styles_preventing_being_collapsed_through = style.display != Display::Block
156-
|| style.overflow.x.is_scroll_container()
157-
|| style.overflow.y.is_scroll_container()
158-
|| style.position == Position::Absolute
162+
let has_styles_preventing_being_collapsed_through = false//style.display != Display::Block
163+
|| style.overflow().x.is_scroll_container()
164+
|| style.overflow().y.is_scroll_container()
165+
|| style.position() == Position::Absolute
159166
|| padding.top > 0.0
160167
|| padding.bottom > 0.0
161168
|| border.top > 0.0
162169
|| border.bottom > 0.0;
163170

171+
drop(style);
172+
164173
// 1. Generate items
165174
let mut items = generate_item_list(tree, node_id, container_content_box_size);
166175

@@ -212,7 +221,7 @@ fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: Lay
212221
let len = tree.child_count(node_id);
213222
for order in 0..len {
214223
let child = tree.get_child_id(node_id, order);
215-
if tree.get_style(child).display == Display::None {
224+
if tree.get_block_child_style(child).box_generation_mode() == BoxGenerationMode::None {
216225
tree.set_unrounded_layout(child, &Layout::with_order(order as u32));
217226
tree.perform_child_layout(
218227
child,
@@ -258,30 +267,30 @@ fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: Lay
258267
/// Create a `Vec` of `BlockItem` structs where each item in the `Vec` represents a child of the current node
259268
#[inline]
260269
fn generate_item_list(
261-
tree: &impl LayoutPartialTree,
270+
tree: &impl LayoutBlockContainer,
262271
node: NodeId,
263272
node_inner_size: Size<Option<f32>>,
264273
) -> Vec<BlockItem> {
265274
tree.child_ids(node)
266-
.map(|child_node_id| (child_node_id, tree.get_style(child_node_id)))
267-
.filter(|(_, style)| style.display != Display::None)
275+
.map(|child_node_id| (child_node_id, tree.get_block_child_style(child_node_id)))
276+
.filter(|(_, style)| style.box_generation_mode() != BoxGenerationMode::None)
268277
.enumerate()
269278
.map(|(order, (child_node_id, child_style))| {
270-
let aspect_ratio = child_style.aspect_ratio;
271-
let padding = child_style.padding.resolve_or_zero(node_inner_size);
272-
let border = child_style.border.resolve_or_zero(node_inner_size);
279+
let aspect_ratio = child_style.aspect_ratio();
280+
let padding = child_style.padding().resolve_or_zero(node_inner_size);
281+
let border = child_style.border().resolve_or_zero(node_inner_size);
273282
BlockItem {
274283
node_id: child_node_id,
275284
order: order as u32,
276285

277-
size: child_style.size.maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
278-
min_size: child_style.min_size.maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
279-
max_size: child_style.max_size.maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
280-
overflow: child_style.overflow,
281-
scrollbar_width: child_style.scrollbar_width,
282-
position: child_style.position,
283-
inset: child_style.inset,
284-
margin: child_style.margin,
286+
size: child_style.size().maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
287+
min_size: child_style.min_size().maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
288+
max_size: child_style.max_size().maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
289+
overflow: child_style.overflow(),
290+
scrollbar_width: child_style.scrollbar_width(),
291+
position: child_style.position(),
292+
inset: child_style.inset(),
293+
margin: child_style.margin(),
285294
padding,
286295
border,
287296
padding_border_sum: (padding + border).sum_axes(),
@@ -488,7 +497,7 @@ fn perform_final_layout_on_in_flow_children(
488497
/// Perform absolute layout on all absolutely positioned children.
489498
#[inline]
490499
fn perform_absolute_layout_on_absolute_children(
491-
tree: &mut impl LayoutPartialTree,
500+
tree: &mut impl LayoutBlockContainer,
492501
items: &[BlockItem],
493502
area_size: Size<f32>,
494503
area_offset: Point<f32>,
@@ -500,36 +509,39 @@ fn perform_absolute_layout_on_absolute_children(
500509
let mut absolute_content_size = Size::ZERO;
501510

502511
for item in items.iter().filter(|item| item.position == Position::Absolute) {
503-
let child_style = tree.get_style(item.node_id);
512+
let child_style = tree.get_block_child_style(item.node_id);
504513

505514
// Skip items that are display:none or are not position:absolute
506-
if child_style.display == Display::None || child_style.position != Position::Absolute {
515+
if child_style.box_generation_mode() == BoxGenerationMode::None || child_style.position() != Position::Absolute
516+
{
507517
continue;
508518
}
509519

510-
let aspect_ratio = child_style.aspect_ratio;
511-
let margin = child_style.margin.map(|margin| margin.resolve_to_option(area_width));
512-
let padding = child_style.padding.resolve_or_zero(Some(area_width));
513-
let border = child_style.border.resolve_or_zero(Some(area_width));
520+
let aspect_ratio = child_style.aspect_ratio();
521+
let margin = child_style.margin().map(|margin| margin.resolve_to_option(area_width));
522+
let padding = child_style.padding().resolve_or_zero(Some(area_width));
523+
let border = child_style.border().resolve_or_zero(Some(area_width));
514524
let padding_border_sum = (padding + border).sum_axes();
515525

516526
// Resolve inset
517-
let left = child_style.inset.left.maybe_resolve(area_width);
518-
let right = child_style.inset.right.maybe_resolve(area_width);
519-
let top = child_style.inset.top.maybe_resolve(area_height);
520-
let bottom = child_style.inset.bottom.maybe_resolve(area_height);
527+
let left = child_style.inset().left.maybe_resolve(area_width);
528+
let right = child_style.inset().right.maybe_resolve(area_width);
529+
let top = child_style.inset().top.maybe_resolve(area_height);
530+
let bottom = child_style.inset().bottom.maybe_resolve(area_height);
521531

522532
// Compute known dimensions from min/max/inherent size styles
523-
let style_size = child_style.size.maybe_resolve(area_size).maybe_apply_aspect_ratio(aspect_ratio);
533+
let style_size = child_style.size().maybe_resolve(area_size).maybe_apply_aspect_ratio(aspect_ratio);
524534
let min_size = child_style
525-
.min_size
535+
.min_size()
526536
.maybe_resolve(area_size)
527537
.maybe_apply_aspect_ratio(aspect_ratio)
528538
.or(padding_border_sum.map(Some))
529539
.maybe_max(padding_border_sum);
530-
let max_size = child_style.max_size.maybe_resolve(area_size).maybe_apply_aspect_ratio(aspect_ratio);
540+
let max_size = child_style.max_size().maybe_resolve(area_size).maybe_apply_aspect_ratio(aspect_ratio);
531541
let mut known_dimensions = style_size.maybe_clamp(min_size, max_size);
532542

543+
drop(child_style);
544+
533545
// Fill in width from left/right and reapply aspect ratio if:
534546
// - Width is not already known
535547
// - Item has both left and right inset properties set

0 commit comments

Comments
 (0)