1
1
/*
2
- * Copyright (c) 2021-2023 , Andreas Kling <kling@serenityos.org>
2
+ * Copyright (c) 2021-2024 , Andreas Kling <kling@serenityos.org>
3
3
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
4
4
*
5
5
* SPDX-License-Identifier: BSD-2-Clause
@@ -56,35 +56,17 @@ CSSPixels FlexFormattingContext::automatic_content_height() const
56
56
return m_flex_container_state.content_height ();
57
57
}
58
58
59
- void FlexFormattingContext::run (Box const & run_box, LayoutMode, AvailableSpace const & available_content_space )
59
+ void FlexFormattingContext::run (Box const & run_box, LayoutMode, AvailableSpace const & available_space )
60
60
{
61
61
VERIFY (&run_box == &flex_container ());
62
62
63
- // NOTE: The available space provided by the parent context is basically our *content box*.
64
- // FFC is currently written in a way that expects that to include padding and border as well,
65
- // so we pad out the available space here to accommodate that.
66
- // FIXME: Refactor the necessary parts of FFC so we don't need this hack!
67
-
68
- auto available_width = available_content_space.width ;
69
- if (available_width.is_definite ())
70
- available_width = AvailableSize::make_definite (available_width.to_px_or_zero () + m_flex_container_state.border_box_left () + m_flex_container_state.border_box_right ());
71
- auto available_height = available_content_space.height ;
72
- if (available_height.is_definite ())
73
- available_height = AvailableSize::make_definite (available_height.to_px_or_zero () + m_flex_container_state.border_box_top () + m_flex_container_state.border_box_bottom ());
74
-
75
- m_available_space_for_flex_container = AxisAgnosticAvailableSpace {
76
- .main = is_row_layout () ? available_width : available_height,
77
- .cross = !is_row_layout () ? available_width : available_height,
78
- .space = { available_width, available_height },
79
- };
80
-
81
63
// This implements https://www.w3.org/TR/css-flexbox-1/#layout-algorithm
82
64
83
65
// 1. Generate anonymous flex items
84
66
generate_anonymous_flex_items ();
85
67
86
68
// 2. Determine the available main and cross space for the flex items
87
- determine_available_space_for_items (AvailableSpace (available_width, available_height) );
69
+ determine_available_space_for_items (available_space );
88
70
89
71
{
90
72
// https://drafts.csswg.org/css-flexbox-1/#definite-sizes
@@ -114,12 +96,16 @@ void FlexFormattingContext::run(Box const& run_box, LayoutMode, AvailableSpace c
114
96
determine_flex_base_size_and_hypothetical_main_size (item);
115
97
}
116
98
117
- if (available_width. is_intrinsic_sizing_constraint () || available_height .is_intrinsic_sizing_constraint ()) {
99
+ if (available_space. width . is_intrinsic_sizing_constraint () || available_space. height .is_intrinsic_sizing_constraint ()) {
118
100
// We're computing intrinsic size for the flex container. This happens at the end of run().
119
101
} else {
120
-
121
102
// 4. Determine the main size of the flex container
122
- determine_main_size_of_flex_container ();
103
+ // Determine the main size of the flex container using the rules of the formatting context in which it participates.
104
+ // NOTE: The automatic block size of a block-level flex container is its max-content size.
105
+
106
+ // NOTE: We've already handled this in the parent formatting context.
107
+ // Specifically, all formatting contexts will have assigned width & height to the flex container
108
+ // before this formatting context runs.
123
109
}
124
110
125
111
// 5. Collect flex items into flex lines:
@@ -186,7 +172,7 @@ void FlexFormattingContext::run(Box const& run_box, LayoutMode, AvailableSpace c
186
172
// 16. Align all flex lines (per align-content)
187
173
align_all_flex_lines ();
188
174
189
- if (available_width. is_intrinsic_sizing_constraint () || available_height .is_intrinsic_sizing_constraint ()) {
175
+ if (available_space. width . is_intrinsic_sizing_constraint () || available_space. height .is_intrinsic_sizing_constraint ()) {
190
176
// We're computing intrinsic size for the flex container.
191
177
determine_intrinsic_size_of_flex_container ();
192
178
} else {
@@ -195,7 +181,7 @@ void FlexFormattingContext::run(Box const& run_box, LayoutMode, AvailableSpace c
195
181
copy_dimensions_from_flex_items_to_boxes ();
196
182
for (auto & item : m_flex_items) {
197
183
auto & box_state = m_state.get (item.box );
198
- if (auto independent_formatting_context = layout_inside (item.box , LayoutMode::Normal, box_state.available_inner_space_or_constraints_from (m_available_space_for_flex_container ->space )))
184
+ if (auto independent_formatting_context = layout_inside (item.box , LayoutMode::Normal, box_state.available_inner_space_or_constraints_from (m_available_space_for_items ->space )))
199
185
independent_formatting_context->parent_context_did_dimension_child_root_box ();
200
186
201
187
compute_inset (item.box );
@@ -443,66 +429,17 @@ void FlexFormattingContext::set_main_axis_second_margin(FlexItem& item, CSSPixel
443
429
// https://drafts.csswg.org/css-flexbox-1/#algo-available
444
430
void FlexFormattingContext::determine_available_space_for_items (AvailableSpace const & available_space)
445
431
{
446
- // For each dimension, if that dimension of the flex container’s content box is a definite size, use that;
447
- // if that dimension of the flex container is being sized under a min or max-content constraint, the available space in that dimension is that constraint;
448
- // otherwise, subtract the flex container’s margin, border, and padding from the space available to the flex container in that dimension and use that value.
449
- // This might result in an infinite value.
450
-
451
- Optional<AvailableSize> available_width_for_items;
452
- if (m_flex_container_state.has_definite_width ()) {
453
- available_width_for_items = AvailableSize::make_definite (m_flex_container_state.content_width ());
454
- } else {
455
- if (available_space.width .is_intrinsic_sizing_constraint ()) {
456
- available_width_for_items = available_space.width ;
457
- } else {
458
- if (available_space.width .is_definite ()) {
459
- auto remaining = available_space.width .to_px_or_zero ()
460
- - m_flex_container_state.margin_left
461
- - m_flex_container_state.margin_right
462
- - m_flex_container_state.border_left
463
- - m_flex_container_state.padding_right
464
- - m_flex_container_state.padding_left
465
- - m_flex_container_state.padding_right ;
466
- available_width_for_items = AvailableSize::make_definite (remaining);
467
- } else {
468
- available_width_for_items = AvailableSize::make_indefinite ();
469
- }
470
- }
471
- }
472
-
473
- Optional<AvailableSize> available_height_for_items;
474
- if (m_flex_container_state.has_definite_height ()) {
475
- available_height_for_items = AvailableSize::make_definite (m_flex_container_state.content_height ());
476
- } else {
477
- if (available_space.height .is_intrinsic_sizing_constraint ()) {
478
- available_height_for_items = available_space.height ;
479
- } else {
480
- if (available_space.height .is_definite ()) {
481
- auto remaining = available_space.height .to_px_or_zero ()
482
- - m_flex_container_state.margin_top
483
- - m_flex_container_state.margin_bottom
484
- - m_flex_container_state.border_top
485
- - m_flex_container_state.padding_bottom
486
- - m_flex_container_state.padding_top
487
- - m_flex_container_state.padding_bottom ;
488
- available_height_for_items = AvailableSize::make_definite (remaining);
489
- } else {
490
- available_height_for_items = AvailableSize::make_indefinite ();
491
- }
492
- }
493
- }
494
-
495
432
if (is_row_layout ()) {
496
433
m_available_space_for_items = AxisAgnosticAvailableSpace {
497
- .main = *available_width_for_items ,
498
- .cross = *available_height_for_items ,
499
- .space = { *available_width_for_items, *available_height_for_items },
434
+ .main = available_space. width ,
435
+ .cross = available_space. height ,
436
+ .space = { available_space. width , available_space. height },
500
437
};
501
438
} else {
502
439
m_available_space_for_items = AxisAgnosticAvailableSpace {
503
- .main = *available_height_for_items ,
504
- .cross = *available_width_for_items ,
505
- .space = { *available_width_for_items, *available_height_for_items },
440
+ .main = available_space. height ,
441
+ .cross = available_space. width ,
442
+ .space = { available_space. width , available_space. height },
506
443
};
507
444
}
508
445
}
@@ -785,59 +722,6 @@ CSSPixels FlexFormattingContext::content_based_minimum_size(FlexItem const& item
785
722
return unclamped_size;
786
723
}
787
724
788
- bool FlexFormattingContext::can_determine_size_of_child () const
789
- {
790
- return true ;
791
- }
792
-
793
- void FlexFormattingContext::determine_width_of_child (Box const &, AvailableSpace const &)
794
- {
795
- // NOTE: For now, we simply do nothing here. If a child context is calling up to us
796
- // and asking us to determine its width, we've already done so as part of the
797
- // flex layout algorithm.
798
- }
799
-
800
- void FlexFormattingContext::determine_height_of_child (Box const &, AvailableSpace const &)
801
- {
802
- // NOTE: For now, we simply do nothing here. If a child context is calling up to us
803
- // and asking us to determine its height, we've already done so as part of the
804
- // flex layout algorithm.
805
- }
806
-
807
- // https://drafts.csswg.org/css-flexbox-1/#algo-main-container
808
- void FlexFormattingContext::determine_main_size_of_flex_container ()
809
- {
810
- // Determine the main size of the flex container using the rules of the formatting context in which it participates.
811
- // NOTE: The automatic block size of a block-level flex container is its max-content size.
812
-
813
- // FIXME: The code below doesn't know how to size absolutely positioned flex containers at all.
814
- // We just leave it alone for now and let the parent context deal with it.
815
- if (flex_container ().is_absolutely_positioned ())
816
- return ;
817
-
818
- // FIXME: Once all parent contexts now how to size a given child, we can remove
819
- // `can_determine_size_of_child()`.
820
- if (parent ()->can_determine_size_of_child ()) {
821
- if (is_row_layout ()) {
822
- parent ()->determine_width_of_child (flex_container (), m_available_space_for_flex_container->space );
823
- } else {
824
- parent ()->determine_height_of_child (flex_container (), m_available_space_for_flex_container->space );
825
- }
826
- return ;
827
- }
828
-
829
- if (is_row_layout ()) {
830
- if (!flex_container ().is_out_of_flow (*parent ()) && m_state.get (*flex_container ().containing_block ()).has_definite_width ()) {
831
- set_main_size (flex_container (), calculate_stretch_fit_width (flex_container (), m_available_space_for_flex_container->space .width ));
832
- } else {
833
- set_main_size (flex_container (), calculate_max_content_width (flex_container ()));
834
- }
835
- } else {
836
- if (!has_definite_main_size (flex_container ()))
837
- set_main_size (flex_container (), calculate_max_content_height (flex_container (), m_available_space_for_flex_container->space .width .to_px_or_zero ()));
838
- }
839
- }
840
-
841
725
// https://www.w3.org/TR/css-flexbox-1/#algo-line-break
842
726
void FlexFormattingContext::collect_flex_items_into_flex_lines ()
843
727
{
@@ -1229,7 +1113,7 @@ void FlexFormattingContext::calculate_cross_size_of_each_flex_line()
1229
1113
// If the flex container is single-line, then clamp the line’s cross-size to be within the container’s computed min and max cross sizes.
1230
1114
// Note that if CSS 2.1’s definition of min/max-width/height applied more generally, this behavior would fall out automatically.
1231
1115
// AD-HOC: We don't do this when the flex container is being sized under a min-content or max-content constraint.
1232
- if (is_single_line () && !m_available_space_for_flex_container ->cross .is_intrinsic_sizing_constraint ()) {
1116
+ if (is_single_line () && !m_available_space_for_items ->cross .is_intrinsic_sizing_constraint ()) {
1233
1117
auto const & computed_min_size = this ->computed_cross_min_size (flex_container ());
1234
1118
auto const & computed_max_size = this ->computed_cross_max_size (flex_container ());
1235
1119
auto cross_min_size = (!computed_min_size.is_auto () && !computed_min_size.contains_percentage ()) ? specified_cross_min_size (flex_container ()) : 0 ;
@@ -1553,7 +1437,7 @@ void FlexFormattingContext::determine_flex_container_used_cross_size()
1553
1437
}
1554
1438
1555
1439
// AD-HOC: We don't apply min/max cross size constraints when sizing the flex container under an intrinsic sizing constraint.
1556
- if (!m_available_space_for_flex_container ->cross .is_intrinsic_sizing_constraint ()) {
1440
+ if (!m_available_space_for_items ->cross .is_intrinsic_sizing_constraint ()) {
1557
1441
auto const & computed_min_size = this ->computed_cross_min_size (flex_container ());
1558
1442
auto const & computed_max_size = this ->computed_cross_max_size (flex_container ());
1559
1443
auto cross_min_size = (!computed_min_size.is_auto () && !computed_min_size.contains_percentage ()) ? specified_cross_min_size (flex_container ()) : 0 ;
@@ -1689,7 +1573,7 @@ void FlexFormattingContext::copy_dimensions_from_flex_items_to_boxes()
1689
1573
// https://drafts.csswg.org/css-flexbox-1/#intrinsic-sizes
1690
1574
void FlexFormattingContext::determine_intrinsic_size_of_flex_container ()
1691
1575
{
1692
- if (m_available_space_for_flex_container ->main .is_intrinsic_sizing_constraint ()) {
1576
+ if (m_available_space_for_items ->main .is_intrinsic_sizing_constraint ()) {
1693
1577
CSSPixels main_size = calculate_intrinsic_main_size_of_flex_container ();
1694
1578
set_main_size (flex_container (), main_size);
1695
1579
}
@@ -2051,7 +1935,7 @@ CSSPixels FlexFormattingContext::calculate_fit_content_cross_size(FlexItem const
2051
1935
CSSPixels FlexFormattingContext::calculate_min_content_cross_size (FlexItem const & item) const
2052
1936
{
2053
1937
if (is_row_layout ()) {
2054
- auto available_space = m_state.get (item.box ).available_inner_space_or_constraints_from (m_available_space_for_flex_container ->space );
1938
+ auto available_space = m_state.get (item.box ).available_inner_space_or_constraints_from (m_available_space_for_items ->space );
2055
1939
if (available_space.width .is_indefinite ()) {
2056
1940
available_space.width = AvailableSize::make_definite (calculate_width_to_use_when_determining_intrinsic_height_of_item (item));
2057
1941
}
@@ -2063,7 +1947,7 @@ CSSPixels FlexFormattingContext::calculate_min_content_cross_size(FlexItem const
2063
1947
CSSPixels FlexFormattingContext::calculate_max_content_cross_size (FlexItem const & item) const
2064
1948
{
2065
1949
if (is_row_layout ()) {
2066
- auto available_space = m_state.get (item.box ).available_inner_space_or_constraints_from (m_available_space_for_flex_container ->space );
1950
+ auto available_space = m_state.get (item.box ).available_inner_space_or_constraints_from (m_available_space_for_items ->space );
2067
1951
if (available_space.width .is_indefinite ()) {
2068
1952
available_space.width = AvailableSize::make_definite (calculate_width_to_use_when_determining_intrinsic_height_of_item (item));
2069
1953
}
0 commit comments