1
1
//! Computes the CSS block layout algorithm in the case that the block container being laid out contains only block-level boxes
2
2
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 } ;
4
4
use crate :: style_helpers:: TaffyMaxContent ;
5
5
use crate :: tree:: { CollapsibleMarginSet , Layout , LayoutInput , LayoutOutput , RunMode , SizingMode } ;
6
6
use crate :: tree:: { LayoutPartialTree , LayoutPartialTreeExt , NodeId } ;
@@ -9,6 +9,7 @@ use crate::util::sys::f32_max;
9
9
use crate :: util:: sys:: Vec ;
10
10
use crate :: util:: MaybeMath ;
11
11
use crate :: util:: { MaybeResolve , ResolveOrZero } ;
12
+ use crate :: { BoxGenerationMode , LayoutBlockContainer } ;
12
13
13
14
#[ cfg( feature = "content_size" ) ]
14
15
use super :: common:: content_size:: compute_content_size_contribution;
@@ -56,25 +57,31 @@ struct BlockItem {
56
57
can_be_collapsed_through : bool ,
57
58
}
58
59
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 {
61
66
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) ;
63
68
64
69
// 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 ) ;
71
76
let padding_border_size = ( padding + border) . sum_axes ( ) ;
72
77
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)
74
79
} else {
75
80
Size :: NONE
76
81
} ;
77
82
83
+ drop ( style) ;
84
+
78
85
// If both min and max in a given axis are set and max <= min then this determines the size in that axis
79
86
let min_max_definite_size = min_size. zip_map ( max_size, |min, max| match ( min, max) {
80
87
( 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,
103
110
compute_inner ( tree, node_id, LayoutInput { known_dimensions : styled_based_known_dimensions, ..inputs } )
104
111
}
105
112
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 {
108
115
let LayoutInput {
109
116
known_dimensions, parent_size, available_space, run_mode, vertical_margins_are_collapsible, ..
110
117
} = inputs;
111
118
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 ) ;
122
129
123
130
// Scrollbar gutters are reserved when the `overflow` property is set to `Overflow::Scroll`.
124
131
// However, the axis are switched (transposed) because a node that scrolls vertically needs
125
132
// *horizontal* space to be reserved for a scrollbar
126
133
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 ( ) ,
129
136
_ => 0.0 ,
130
137
} ) ;
131
138
// 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
139
146
// Determine margin collapsing behaviour
140
147
let own_margins_collapse_with_children = Line {
141
148
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
145
152
&& padding. top == 0.0
146
153
&& border. top == 0.0 ,
147
154
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
151
158
&& padding. bottom == 0.0
152
159
&& border. bottom == 0.0
153
160
&& size. height . is_none ( ) ,
154
161
} ;
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
159
166
|| padding. top > 0.0
160
167
|| padding. bottom > 0.0
161
168
|| border. top > 0.0
162
169
|| border. bottom > 0.0 ;
163
170
171
+ drop ( style) ;
172
+
164
173
// 1. Generate items
165
174
let mut items = generate_item_list ( tree, node_id, container_content_box_size) ;
166
175
@@ -212,7 +221,7 @@ fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: Lay
212
221
let len = tree. child_count ( node_id) ;
213
222
for order in 0 ..len {
214
223
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 {
216
225
tree. set_unrounded_layout ( child, & Layout :: with_order ( order as u32 ) ) ;
217
226
tree. perform_child_layout (
218
227
child,
@@ -258,30 +267,30 @@ fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: Lay
258
267
/// Create a `Vec` of `BlockItem` structs where each item in the `Vec` represents a child of the current node
259
268
#[ inline]
260
269
fn generate_item_list (
261
- tree : & impl LayoutPartialTree ,
270
+ tree : & impl LayoutBlockContainer ,
262
271
node : NodeId ,
263
272
node_inner_size : Size < Option < f32 > > ,
264
273
) -> Vec < BlockItem > {
265
274
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 )
268
277
. enumerate ( )
269
278
. 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) ;
273
282
BlockItem {
274
283
node_id : child_node_id,
275
284
order : order as u32 ,
276
285
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 ( ) ,
285
294
padding,
286
295
border,
287
296
padding_border_sum : ( padding + border) . sum_axes ( ) ,
@@ -488,7 +497,7 @@ fn perform_final_layout_on_in_flow_children(
488
497
/// Perform absolute layout on all absolutely positioned children.
489
498
#[ inline]
490
499
fn perform_absolute_layout_on_absolute_children (
491
- tree : & mut impl LayoutPartialTree ,
500
+ tree : & mut impl LayoutBlockContainer ,
492
501
items : & [ BlockItem ] ,
493
502
area_size : Size < f32 > ,
494
503
area_offset : Point < f32 > ,
@@ -500,36 +509,39 @@ fn perform_absolute_layout_on_absolute_children(
500
509
let mut absolute_content_size = Size :: ZERO ;
501
510
502
511
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 ) ;
504
513
505
514
// 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
+ {
507
517
continue ;
508
518
}
509
519
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) ) ;
514
524
let padding_border_sum = ( padding + border) . sum_axes ( ) ;
515
525
516
526
// 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) ;
521
531
522
532
// 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) ;
524
534
let min_size = child_style
525
- . min_size
535
+ . min_size ( )
526
536
. maybe_resolve ( area_size)
527
537
. maybe_apply_aspect_ratio ( aspect_ratio)
528
538
. or ( padding_border_sum. map ( Some ) )
529
539
. 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) ;
531
541
let mut known_dimensions = style_size. maybe_clamp ( min_size, max_size) ;
532
542
543
+ drop ( child_style) ;
544
+
533
545
// Fill in width from left/right and reapply aspect ratio if:
534
546
// - Width is not already known
535
547
// - Item has both left and right inset properties set
0 commit comments