1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 02:17:34 +00:00

LibWeb: Convert FlexFormattingContext to new pixel units

This commit is contained in:
Sam Atkins 2022-11-03 17:10:17 +00:00 committed by Linus Groh
parent ace66d4a3e
commit f2c977251b
2 changed files with 172 additions and 172 deletions

View file

@ -37,7 +37,7 @@ static CSS::Size to_css_size(CSS::LengthPercentage const& length_percentage)
return CSS::Size::make_percentage(length_percentage.percentage()); return CSS::Size::make_percentage(length_percentage.percentage());
} }
float FlexFormattingContext::get_pixel_width(Box const& box, Optional<CSS::Size> const& size) const CSSPixels FlexFormattingContext::get_pixel_width(Box const& box, Optional<CSS::Size> const& size) const
{ {
if (!size.has_value()) if (!size.has_value())
return 0; return 0;
@ -53,7 +53,7 @@ float FlexFormattingContext::get_pixel_width(Box const& box, Optional<CSS::Size>
return size->resolved(box, inner_width).to_px(box); return size->resolved(box, inner_width).to_px(box);
} }
float FlexFormattingContext::get_pixel_height(Box const& box, Optional<CSS::Size> const& length_percentage) const CSSPixels FlexFormattingContext::get_pixel_height(Box const& box, Optional<CSS::Size> const& length_percentage) const
{ {
if (!length_percentage.has_value()) if (!length_percentage.has_value())
return 0; return 0;
@ -353,24 +353,24 @@ bool FlexFormattingContext::has_definite_main_size(Box const& box) const
return is_row_layout() ? used_values.has_definite_width() : used_values.has_definite_height(); return is_row_layout() ? used_values.has_definite_width() : used_values.has_definite_height();
} }
float FlexFormattingContext::specified_main_size(Box const& box) const CSSPixels FlexFormattingContext::specified_main_size(Box const& box) const
{ {
auto const& box_state = m_state.get(box); auto const& box_state = m_state.get(box);
return is_row_layout() ? box_state.content_width() : box_state.content_height(); return is_row_layout() ? box_state.content_width() : box_state.content_height();
} }
float FlexFormattingContext::specified_cross_size(Box const& box) const CSSPixels FlexFormattingContext::specified_cross_size(Box const& box) const
{ {
auto const& box_state = m_state.get(box); auto const& box_state = m_state.get(box);
return is_row_layout() ? box_state.content_height() : box_state.content_width(); return is_row_layout() ? box_state.content_height() : box_state.content_width();
} }
float FlexFormattingContext::resolved_definite_cross_size(FlexItem const& item) const CSSPixels FlexFormattingContext::resolved_definite_cross_size(FlexItem const& item) const
{ {
return !is_row_layout() ? m_state.resolved_definite_width(item.box) : m_state.resolved_definite_height(item.box); return !is_row_layout() ? m_state.resolved_definite_width(item.box) : m_state.resolved_definite_height(item.box);
} }
float FlexFormattingContext::resolved_definite_main_size(FlexItem const& item) const CSSPixels FlexFormattingContext::resolved_definite_main_size(FlexItem const& item) const
{ {
return is_row_layout() ? m_state.resolved_definite_width(item.box) : m_state.resolved_definite_height(item.box); return is_row_layout() ? m_state.resolved_definite_width(item.box) : m_state.resolved_definite_height(item.box);
} }
@ -393,14 +393,14 @@ bool FlexFormattingContext::has_definite_cross_size(Box const& box) const
return is_row_layout() ? used_values.has_definite_height() : used_values.has_definite_width(); return is_row_layout() ? used_values.has_definite_height() : used_values.has_definite_width();
} }
float FlexFormattingContext::specified_main_min_size(Box const& box) const CSSPixels FlexFormattingContext::specified_main_min_size(Box const& box) const
{ {
return is_row_layout() return is_row_layout()
? get_pixel_width(box, box.computed_values().min_width()) ? get_pixel_width(box, box.computed_values().min_width())
: get_pixel_height(box, box.computed_values().min_height()); : get_pixel_height(box, box.computed_values().min_height());
} }
float FlexFormattingContext::specified_cross_min_size(Box const& box) const CSSPixels FlexFormattingContext::specified_cross_min_size(Box const& box) const
{ {
return is_row_layout() return is_row_layout()
? get_pixel_height(box, box.computed_values().min_height()) ? get_pixel_height(box, box.computed_values().min_height())
@ -419,14 +419,14 @@ bool FlexFormattingContext::has_cross_max_size(Box const& box) const
return !value.is_none(); return !value.is_none();
} }
float FlexFormattingContext::specified_main_max_size(Box const& box) const CSSPixels FlexFormattingContext::specified_main_max_size(Box const& box) const
{ {
return is_row_layout() return is_row_layout()
? get_pixel_width(box, box.computed_values().max_width()) ? get_pixel_width(box, box.computed_values().max_width())
: get_pixel_height(box, box.computed_values().max_height()); : get_pixel_height(box, box.computed_values().max_height());
} }
float FlexFormattingContext::specified_cross_max_size(Box const& box) const CSSPixels FlexFormattingContext::specified_cross_max_size(Box const& box) const
{ {
return is_row_layout() return is_row_layout()
? get_pixel_height(box, box.computed_values().max_height()) ? get_pixel_height(box, box.computed_values().max_height())
@ -439,23 +439,23 @@ bool FlexFormattingContext::is_cross_auto(Box const& box) const
return cross_length.is_auto(); return cross_length.is_auto();
} }
void FlexFormattingContext::set_main_size(Box const& box, float size) void FlexFormattingContext::set_main_size(Box const& box, CSSPixels size)
{ {
if (is_row_layout()) if (is_row_layout())
m_state.get_mutable(box).set_content_width(size); m_state.get_mutable(box).set_content_width(size.value());
else else
m_state.get_mutable(box).set_content_height(size); m_state.get_mutable(box).set_content_height(size.value());
} }
void FlexFormattingContext::set_cross_size(Box const& box, float size) void FlexFormattingContext::set_cross_size(Box const& box, CSSPixels size)
{ {
if (is_row_layout()) if (is_row_layout())
m_state.get_mutable(box).set_content_height(size); m_state.get_mutable(box).set_content_height(size.value());
else else
m_state.get_mutable(box).set_content_width(size); m_state.get_mutable(box).set_content_width(size.value());
} }
void FlexFormattingContext::set_offset(Box const& box, float main_offset, float cross_offset) void FlexFormattingContext::set_offset(Box const& box, CSSPixels main_offset, CSSPixels cross_offset)
{ {
if (is_row_layout()) if (is_row_layout())
m_state.get_mutable(box).offset = Gfx::FloatPoint { main_offset, cross_offset }; m_state.get_mutable(box).offset = Gfx::FloatPoint { main_offset, cross_offset };
@ -463,22 +463,22 @@ void FlexFormattingContext::set_offset(Box const& box, float main_offset, float
m_state.get_mutable(box).offset = Gfx::FloatPoint { cross_offset, main_offset }; m_state.get_mutable(box).offset = Gfx::FloatPoint { cross_offset, main_offset };
} }
void FlexFormattingContext::set_main_axis_first_margin(FlexItem& item, float margin) void FlexFormattingContext::set_main_axis_first_margin(FlexItem& item, CSSPixels margin)
{ {
item.margins.main_before = margin; item.margins.main_before = margin;
if (is_row_layout()) if (is_row_layout())
m_state.get_mutable(item.box).margin_left = margin; m_state.get_mutable(item.box).margin_left = margin.value();
else else
m_state.get_mutable(item.box).margin_top = margin; m_state.get_mutable(item.box).margin_top = margin.value();
} }
void FlexFormattingContext::set_main_axis_second_margin(FlexItem& item, float margin) void FlexFormattingContext::set_main_axis_second_margin(FlexItem& item, CSSPixels margin)
{ {
item.margins.main_after = margin; item.margins.main_after = margin;
if (is_row_layout()) if (is_row_layout())
m_state.get_mutable(item.box).margin_right = margin; m_state.get_mutable(item.box).margin_right = margin.value();
else else
m_state.get_mutable(item.box).margin_bottom = margin; m_state.get_mutable(item.box).margin_bottom = margin.value();
} }
// https://drafts.csswg.org/css-flexbox-1/#algo-available // https://drafts.csswg.org/css-flexbox-1/#algo-available
@ -548,7 +548,7 @@ void FlexFormattingContext::determine_available_space_for_items(AvailableSpace c
} }
} }
float FlexFormattingContext::calculate_indefinite_main_size(FlexItem const& item) CSSPixels FlexFormattingContext::calculate_indefinite_main_size(FlexItem const& item)
{ {
VERIFY(!has_definite_main_size(item.box)); VERIFY(!has_definite_main_size(item.box));
@ -571,7 +571,7 @@ float FlexFormattingContext::calculate_indefinite_main_size(FlexItem const& item
if (cross_size_needed_to_determine_main_size) { if (cross_size_needed_to_determine_main_size) {
// Figure out the fit-content cross size, then layout with that and see what height comes out of it. // Figure out the fit-content cross size, then layout with that and see what height comes out of it.
float fit_content_cross_size = calculate_fit_content_cross_size(item); CSSPixels fit_content_cross_size = calculate_fit_content_cross_size(item);
LayoutState throwaway_state(&m_state); LayoutState throwaway_state(&m_state);
auto& box_state = throwaway_state.get_mutable(item.box); auto& box_state = throwaway_state.get_mutable(item.box);
@ -581,7 +581,7 @@ float FlexFormattingContext::calculate_indefinite_main_size(FlexItem const& item
// NOTE: Flex items should always create an independent formatting context! // NOTE: Flex items should always create an independent formatting context!
VERIFY(independent_formatting_context); VERIFY(independent_formatting_context);
box_state.set_content_width(fit_content_cross_size); box_state.set_content_width(fit_content_cross_size.value());
independent_formatting_context->run(item.box, LayoutMode::Normal, m_available_space_for_items->space); independent_formatting_context->run(item.box, LayoutMode::Normal, m_available_space_for_items->space);
return independent_formatting_context->automatic_content_height().value(); return independent_formatting_context->automatic_content_height().value();
@ -699,7 +699,7 @@ void FlexFormattingContext::determine_flex_base_size_and_hypothetical_main_size(
// The hypothetical main size is the items flex base size clamped according to its used min and max main sizes (and flooring the content box size at zero). // The hypothetical main size is the items flex base size clamped according to its used min and max main sizes (and flooring the content box size at zero).
auto clamp_min = has_main_min_size(child_box) ? specified_main_min_size(child_box) : automatic_minimum_size(flex_item); auto clamp_min = has_main_min_size(child_box) ? specified_main_min_size(child_box) : automatic_minimum_size(flex_item);
auto clamp_max = has_main_max_size(child_box) ? specified_main_max_size(child_box) : NumericLimits<float>::max(); auto clamp_max = has_main_max_size(child_box) ? specified_main_max_size(child_box) : NumericLimits<float>::max();
flex_item.hypothetical_main_size = max(0.0f, css_clamp(flex_item.flex_base_size, clamp_min, clamp_max)); flex_item.hypothetical_main_size = max(CSSPixels(0.0f), css_clamp(flex_item.flex_base_size, clamp_min, clamp_max));
// NOTE: At this point, we set the hypothetical main size as the flex item's *temporary* main size. // NOTE: At this point, we set the hypothetical main size as the flex item's *temporary* main size.
// The size may change again when we resolve flexible lengths, but this is necessary in order for // The size may change again when we resolve flexible lengths, but this is necessary in order for
@ -708,20 +708,20 @@ void FlexFormattingContext::determine_flex_base_size_and_hypothetical_main_size(
// The spec just barely hand-waves about this, but it seems to *roughly* match what other engines do. // The spec just barely hand-waves about this, but it seems to *roughly* match what other engines do.
// See "Note" section here: https://drafts.csswg.org/css-flexbox-1/#definite-sizes // See "Note" section here: https://drafts.csswg.org/css-flexbox-1/#definite-sizes
if (is_row_layout()) if (is_row_layout())
m_state.get_mutable(flex_item.box).set_temporary_content_width(flex_item.hypothetical_main_size); m_state.get_mutable(flex_item.box).set_temporary_content_width(flex_item.hypothetical_main_size.value());
else else
m_state.get_mutable(flex_item.box).set_temporary_content_height(flex_item.hypothetical_main_size); m_state.get_mutable(flex_item.box).set_temporary_content_height(flex_item.hypothetical_main_size.value());
} }
// https://drafts.csswg.org/css-flexbox-1/#min-size-auto // https://drafts.csswg.org/css-flexbox-1/#min-size-auto
float FlexFormattingContext::automatic_minimum_size(FlexItem const& item) const CSSPixels FlexFormattingContext::automatic_minimum_size(FlexItem const& item) const
{ {
// FIXME: Deal with scroll containers. // FIXME: Deal with scroll containers.
return content_based_minimum_size(item); return content_based_minimum_size(item);
} }
// https://drafts.csswg.org/css-flexbox-1/#specified-size-suggestion // https://drafts.csswg.org/css-flexbox-1/#specified-size-suggestion
Optional<float> FlexFormattingContext::specified_size_suggestion(FlexItem const& item) const Optional<CSSPixels> FlexFormattingContext::specified_size_suggestion(FlexItem const& item) const
{ {
// If the items preferred main size is definite and not automatic, // If the items preferred main size is definite and not automatic,
// then the specified size suggestion is that size. It is otherwise undefined. // then the specified size suggestion is that size. It is otherwise undefined.
@ -731,14 +731,14 @@ Optional<float> FlexFormattingContext::specified_size_suggestion(FlexItem const&
} }
// https://drafts.csswg.org/css-flexbox-1/#content-size-suggestion // https://drafts.csswg.org/css-flexbox-1/#content-size-suggestion
float FlexFormattingContext::content_size_suggestion(FlexItem const& item) const CSSPixels FlexFormattingContext::content_size_suggestion(FlexItem const& item) const
{ {
// FIXME: Apply clamps // FIXME: Apply clamps
return calculate_min_content_main_size(item); return calculate_min_content_main_size(item);
} }
// https://drafts.csswg.org/css-flexbox-1/#transferred-size-suggestion // https://drafts.csswg.org/css-flexbox-1/#transferred-size-suggestion
Optional<float> FlexFormattingContext::transferred_size_suggestion(FlexItem const& item) const Optional<CSSPixels> FlexFormattingContext::transferred_size_suggestion(FlexItem const& item) const
{ {
// If the item has a preferred aspect ratio and its preferred cross size is definite, // If the item has a preferred aspect ratio and its preferred cross size is definite,
// then the transferred size suggestion is that size // then the transferred size suggestion is that size
@ -754,7 +754,7 @@ Optional<float> FlexFormattingContext::transferred_size_suggestion(FlexItem cons
} }
// https://drafts.csswg.org/css-flexbox-1/#content-based-minimum-size // https://drafts.csswg.org/css-flexbox-1/#content-based-minimum-size
float FlexFormattingContext::content_based_minimum_size(FlexItem const& item) const CSSPixels FlexFormattingContext::content_based_minimum_size(FlexItem const& item) const
{ {
auto unclamped_size = [&] { auto unclamped_size = [&] {
// The content-based minimum size of a flex item is the smaller of its specified size suggestion // The content-based minimum size of a flex item is the smaller of its specified size suggestion
@ -860,7 +860,7 @@ void FlexFormattingContext::collect_flex_items_into_flex_lines()
// Repeat until all flex items have been collected into flex lines. // Repeat until all flex items have been collected into flex lines.
FlexLine line; FlexLine line;
float line_main_size = 0; CSSPixels line_main_size = 0;
for (auto& flex_item : m_flex_items) { for (auto& flex_item : m_flex_items) {
auto outer_hypothetical_main_size = flex_item.hypothetical_main_size + flex_item.margins.main_before + flex_item.margins.main_after + flex_item.borders.main_before + flex_item.borders.main_after + flex_item.padding.main_before + flex_item.padding.main_after; auto outer_hypothetical_main_size = flex_item.hypothetical_main_size + flex_item.margins.main_before + flex_item.margins.main_after + flex_item.borders.main_before + flex_item.borders.main_after + flex_item.padding.main_before + flex_item.padding.main_after;
if (!line.items.is_empty() && (line_main_size + outer_hypothetical_main_size) > specified_main_size(flex_container())) { if (!line.items.is_empty() && (line_main_size + outer_hypothetical_main_size) > specified_main_size(flex_container())) {
@ -887,7 +887,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
for (auto& flex_line : m_flex_lines) { for (auto& flex_line : m_flex_lines) {
size_t number_of_unfrozen_items_on_line = flex_line.items.size(); size_t number_of_unfrozen_items_on_line = flex_line.items.size();
float sum_of_hypothetical_main_sizes = 0; CSSPixels sum_of_hypothetical_main_sizes = 0;
for (auto& flex_item : flex_line.items) { for (auto& flex_item : flex_line.items) {
sum_of_hypothetical_main_sizes += (flex_item->hypothetical_main_size + flex_item->margins.main_before + flex_item->margins.main_after + flex_item->borders.main_before + flex_item->borders.main_after + flex_item->padding.main_before + flex_item->padding.main_after); sum_of_hypothetical_main_sizes += (flex_item->hypothetical_main_size + flex_item->margins.main_before + flex_item->margins.main_after + flex_item->borders.main_before + flex_item->borders.main_after + flex_item->padding.main_before + flex_item->padding.main_after);
} }
@ -926,7 +926,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
// 6.3. Calculate initial free space // 6.3. Calculate initial free space
auto calculate_free_space = [&]() { auto calculate_free_space = [&]() {
float sum_of_items_on_line = 0; CSSPixels sum_of_items_on_line = 0;
for (auto& flex_item : flex_line.items) { for (auto& flex_item : flex_line.items) {
if (flex_item->frozen) if (flex_item->frozen)
sum_of_items_on_line += flex_item->target_main_size + flex_item->margins.main_before + flex_item->margins.main_after + flex_item->borders.main_before + flex_item->borders.main_after + flex_item->padding.main_before + flex_item->padding.main_after; sum_of_items_on_line += flex_item->target_main_size + flex_item->margins.main_before + flex_item->margins.main_after + flex_item->borders.main_before + flex_item->borders.main_after + flex_item->padding.main_before + flex_item->padding.main_after;
@ -936,7 +936,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
return specified_main_size(flex_container()) - sum_of_items_on_line; return specified_main_size(flex_container()) - sum_of_items_on_line;
}; };
float initial_free_space = calculate_free_space(); CSSPixels initial_free_space = calculate_free_space();
flex_line.remaining_free_space = initial_free_space; flex_line.remaining_free_space = initial_free_space;
// 6.4 Loop // 6.4 Loop
@ -957,7 +957,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
if (sum_of_unfrozen_flex_items_flex_factors < 1) { if (sum_of_unfrozen_flex_items_flex_factors < 1) {
auto intermediate_free_space = initial_free_space * sum_of_unfrozen_flex_items_flex_factors; auto intermediate_free_space = initial_free_space * sum_of_unfrozen_flex_items_flex_factors;
if (AK::abs(intermediate_free_space) < AK::abs(flex_line.remaining_free_space)) if (abs(intermediate_free_space) < abs(flex_line.remaining_free_space))
flex_line.remaining_free_space = intermediate_free_space; flex_line.remaining_free_space = intermediate_free_space;
} }
@ -972,7 +972,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
} else if (used_flex_factor == FlexFactor::FlexShrinkFactor) { } else if (used_flex_factor == FlexFactor::FlexShrinkFactor) {
float sum_of_scaled_flex_shrink_factor_of_unfrozen_items = 0; float sum_of_scaled_flex_shrink_factor_of_unfrozen_items = 0;
for_each_unfrozen_item([&](FlexItem* flex_item) { for_each_unfrozen_item([&](FlexItem* flex_item) {
flex_item->scaled_flex_shrink_factor = flex_item->flex_factor.value_or(1) * flex_item->flex_base_size; flex_item->scaled_flex_shrink_factor = flex_item->flex_factor.value_or(1) * flex_item->flex_base_size.value();
sum_of_scaled_flex_shrink_factor_of_unfrozen_items += flex_item->scaled_flex_shrink_factor; sum_of_scaled_flex_shrink_factor_of_unfrozen_items += flex_item->scaled_flex_shrink_factor;
}); });
@ -980,7 +980,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
float ratio = 1.0f; float ratio = 1.0f;
if (sum_of_scaled_flex_shrink_factor_of_unfrozen_items != 0.0f) if (sum_of_scaled_flex_shrink_factor_of_unfrozen_items != 0.0f)
ratio = flex_item->scaled_flex_shrink_factor / sum_of_scaled_flex_shrink_factor_of_unfrozen_items; ratio = flex_item->scaled_flex_shrink_factor / sum_of_scaled_flex_shrink_factor_of_unfrozen_items;
flex_item->target_main_size = flex_item->flex_base_size - (AK::abs(flex_line.remaining_free_space) * ratio); flex_item->target_main_size = flex_item->flex_base_size - (abs(flex_line.remaining_free_space) * ratio);
}); });
} }
} else { } else {
@ -990,7 +990,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
}); });
} }
// d Fix min/max violations. // d Fix min/max violations.
float adjustments = 0.0f; CSSPixels adjustments = 0.0f;
for_each_unfrozen_item([&](FlexItem* item) { for_each_unfrozen_item([&](FlexItem* item) {
auto min_main = has_main_min_size(item->box) auto min_main = has_main_min_size(item->box)
? specified_main_min_size(item->box) ? specified_main_min_size(item->box)
@ -999,7 +999,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
? specified_main_max_size(item->box) ? specified_main_max_size(item->box)
: NumericLimits<float>::max(); : NumericLimits<float>::max();
float original_target_size = item->target_main_size; CSSPixels original_target_size = item->target_main_size;
if (item->target_main_size < min_main) { if (item->target_main_size < min_main) {
item->target_main_size = min_main; item->target_main_size = min_main;
@ -1010,11 +1010,11 @@ void FlexFormattingContext::resolve_flexible_lengths()
item->target_main_size = max_main; item->target_main_size = max_main;
item->is_max_violation = true; item->is_max_violation = true;
} }
float delta = item->target_main_size - original_target_size; CSSPixels delta = item->target_main_size - original_target_size;
adjustments += delta; adjustments += delta;
}); });
// e Freeze over-flexed items // e Freeze over-flexed items
float total_violation = adjustments; CSSPixels total_violation = adjustments;
if (total_violation == 0) { if (total_violation == 0) {
for_each_unfrozen_item([&](FlexItem* item) { for_each_unfrozen_item([&](FlexItem* item) {
--number_of_unfrozen_items_on_line; --number_of_unfrozen_items_on_line;
@ -1068,9 +1068,9 @@ void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem&
return; return;
} }
float cross_size = [&]() { auto cross_size = [&]() {
if (item.box.computed_values().box_sizing() == CSS::BoxSizing::BorderBox) { if (item.box.computed_values().box_sizing() == CSS::BoxSizing::BorderBox) {
return max(0.0f, resolved_definite_cross_size(item) - item.padding.cross_before - item.padding.cross_after - item.borders.cross_before - item.borders.cross_after); return max(CSSPixels(0.0f), resolved_definite_cross_size(item) - item.padding.cross_before - item.padding.cross_after - item.borders.cross_before - item.borders.cross_after);
} }
return resolved_definite_cross_size(item); return resolved_definite_cross_size(item);
@ -1091,9 +1091,9 @@ void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem&
auto& containing_block_state = throwaway_state.get_mutable(flex_container()); auto& containing_block_state = throwaway_state.get_mutable(flex_container());
if (is_row_layout()) { if (is_row_layout()) {
containing_block_state.set_content_width(item.main_size); containing_block_state.set_content_width(item.main_size.value());
} else { } else {
containing_block_state.set_content_height(item.main_size); containing_block_state.set_content_height(item.main_size.value());
} }
auto& box_state = throwaway_state.get_mutable(item.box); auto& box_state = throwaway_state.get_mutable(item.box);
@ -1108,7 +1108,7 @@ void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem&
auto automatic_cross_size = is_row_layout() ? independent_formatting_context->automatic_content_height() auto automatic_cross_size = is_row_layout() ? independent_formatting_context->automatic_content_height()
: box_state.content_width(); : box_state.content_width();
item.hypothetical_cross_size = css_clamp(automatic_cross_size.value(), clamp_min, clamp_max); item.hypothetical_cross_size = css_clamp(automatic_cross_size, clamp_min, clamp_max);
} }
// https://www.w3.org/TR/css-flexbox-1/#algo-cross-line // https://www.w3.org/TR/css-flexbox-1/#algo-cross-line
@ -1128,14 +1128,14 @@ void FlexFormattingContext::calculate_cross_size_of_each_flex_line()
// and its hypothetical outer cross-end edge, and sum these two values. // and its hypothetical outer cross-end edge, and sum these two values.
// 2. Among all the items not collected by the previous step, find the largest outer hypothetical cross size. // 2. Among all the items not collected by the previous step, find the largest outer hypothetical cross size.
float largest_hypothetical_cross_size = 0; CSSPixels largest_hypothetical_cross_size = 0;
for (auto& flex_item : flex_line.items) { for (auto& flex_item : flex_line.items) {
if (largest_hypothetical_cross_size < flex_item->hypothetical_cross_size_with_margins()) if (largest_hypothetical_cross_size < flex_item->hypothetical_cross_size_with_margins())
largest_hypothetical_cross_size = flex_item->hypothetical_cross_size_with_margins(); largest_hypothetical_cross_size = flex_item->hypothetical_cross_size_with_margins();
} }
// 3. The used cross-size of the flex line is the largest of the numbers found in the previous two steps and zero. // 3. The used cross-size of the flex line is the largest of the numbers found in the previous two steps and zero.
flex_line.cross_size = max(0.0f, largest_hypothetical_cross_size); flex_line.cross_size = max(CSSPixels(0.0f), largest_hypothetical_cross_size);
} }
// If the flex container is single-line, then clamp the lines cross-size to be within the containers computed min and max cross sizes. // If the flex container is single-line, then clamp the lines cross-size to be within the containers computed min and max cross sizes.
@ -1185,7 +1185,7 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
{ {
for (auto& flex_line : m_flex_lines) { for (auto& flex_line : m_flex_lines) {
// 12.1. // 12.1.
float used_main_space = 0; CSSPixels used_main_space = 0;
size_t auto_margins = 0; size_t auto_margins = 0;
for (auto& flex_item : flex_line.items) { for (auto& flex_item : flex_line.items) {
used_main_space += flex_item->main_size; used_main_space += flex_item->main_size;
@ -1201,7 +1201,7 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
} }
if (flex_line.remaining_free_space > 0) { if (flex_line.remaining_free_space > 0) {
float size_per_auto_margin = flex_line.remaining_free_space / (float)auto_margins; CSSPixels size_per_auto_margin = flex_line.remaining_free_space / (float)auto_margins;
for (auto& flex_item : flex_line.items) { for (auto& flex_item : flex_line.items) {
if (flex_item->margins.main_before_is_auto) if (flex_item->margins.main_before_is_auto)
set_main_axis_first_margin(*flex_item, size_per_auto_margin); set_main_axis_first_margin(*flex_item, size_per_auto_margin);
@ -1218,8 +1218,8 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
} }
// 12.2. // 12.2.
float space_between_items = 0; CSSPixels space_between_items = 0;
float initial_offset = 0; CSSPixels initial_offset = 0;
auto number_of_items = flex_line.items.size(); auto number_of_items = flex_line.items.size();
enum class FlexRegionRenderCursor { enum class FlexRegionRenderCursor {
@ -1266,14 +1266,14 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
// For reverse, we use FlexRegionRenderCursor::Right // For reverse, we use FlexRegionRenderCursor::Right
// to indicate the cursor offset is the end and render backwards // to indicate the cursor offset is the end and render backwards
// Otherwise the cursor offset is the 'start' of the region or initial offset // Otherwise the cursor offset is the 'start' of the region or initial offset
float cursor_offset = initial_offset; CSSPixels cursor_offset = initial_offset;
auto place_item = [&](FlexItem& item, bool is_first_item, bool is_last_item) { auto place_item = [&](FlexItem& item, bool is_first_item, bool is_last_item) {
// NOTE: For centered justifications (`center` and `space-around`) we ignore any margin // NOTE: For centered justifications (`center` and `space-around`) we ignore any margin
// before the first item, and after the last item. // before the first item, and after the last item.
float item_margin_before = item.margins.main_before; auto item_margin_before = item.margins.main_before;
float item_margin_after = item.margins.main_after; auto item_margin_after = item.margins.main_after;
if (justification_is_centered) { if (justification_is_centered) {
if (is_first_item) if (is_first_item)
item_margin_before = 0; item_margin_before = 0;
@ -1363,20 +1363,20 @@ void FlexFormattingContext::align_all_flex_items_along_the_cross_axis()
// FIXME: Take better care of margins // FIXME: Take better care of margins
for (auto& flex_line : m_flex_lines) { for (auto& flex_line : m_flex_lines) {
for (auto* flex_item : flex_line.items) { for (auto* flex_item : flex_line.items) {
float half_line_size = flex_line.cross_size / 2.0f; CSSPixels half_line_size = flex_line.cross_size / 2.0f;
switch (alignment_for_item(flex_item->box)) { switch (alignment_for_item(flex_item->box)) {
case CSS::AlignItems::Baseline: case CSS::AlignItems::Baseline:
// FIXME: Implement this // FIXME: Implement this
// Fallthrough // Fallthrough
case CSS::AlignItems::FlexStart: case CSS::AlignItems::FlexStart:
case CSS::AlignItems::Stretch: case CSS::AlignItems::Stretch:
flex_item->cross_offset = 0 - half_line_size + flex_item->margins.cross_before + flex_item->borders.cross_before + flex_item->padding.cross_before; flex_item->cross_offset = -half_line_size + flex_item->margins.cross_before + flex_item->borders.cross_before + flex_item->padding.cross_before;
break; break;
case CSS::AlignItems::FlexEnd: case CSS::AlignItems::FlexEnd:
flex_item->cross_offset = half_line_size - flex_item->cross_size - flex_item->margins.cross_after - flex_item->borders.cross_after - flex_item->padding.cross_after; flex_item->cross_offset = half_line_size - flex_item->cross_size - flex_item->margins.cross_after - flex_item->borders.cross_after - flex_item->padding.cross_after;
break; break;
case CSS::AlignItems::Center: case CSS::AlignItems::Center:
flex_item->cross_offset = 0 - (flex_item->cross_size / 2.0f); flex_item->cross_offset = -(flex_item->cross_size / 2.0f);
break; break;
default: default:
break; break;
@ -1388,7 +1388,7 @@ void FlexFormattingContext::align_all_flex_items_along_the_cross_axis()
// https://www.w3.org/TR/css-flexbox-1/#algo-cross-container // https://www.w3.org/TR/css-flexbox-1/#algo-cross-container
void FlexFormattingContext::determine_flex_container_used_cross_size() void FlexFormattingContext::determine_flex_container_used_cross_size()
{ {
float cross_size = 0; CSSPixels cross_size = 0;
if (has_definite_cross_size(flex_container())) { if (has_definite_cross_size(flex_container())) {
// Flex container has definite cross size: easy-peasy. // Flex container has definite cross size: easy-peasy.
cross_size = specified_cross_size(flex_container()); cross_size = specified_cross_size(flex_container());
@ -1397,7 +1397,7 @@ void FlexFormattingContext::determine_flex_container_used_cross_size()
auto cross_size_value = is_row_layout() ? flex_container().computed_values().height() : flex_container().computed_values().width(); auto cross_size_value = is_row_layout() ? flex_container().computed_values().height() : flex_container().computed_values().width();
if (cross_size_value.is_auto() || cross_size_value.contains_percentage()) { if (cross_size_value.is_auto() || cross_size_value.contains_percentage()) {
// If a content-based cross size is needed, use the sum of the flex lines' cross sizes. // If a content-based cross size is needed, use the sum of the flex lines' cross sizes.
float sum_of_flex_lines_cross_sizes = 0; CSSPixels sum_of_flex_lines_cross_sizes = 0;
for (auto& flex_line : m_flex_lines) { for (auto& flex_line : m_flex_lines) {
sum_of_flex_lines_cross_sizes += flex_line.cross_size; sum_of_flex_lines_cross_sizes += flex_line.cross_size;
} }
@ -1426,23 +1426,23 @@ void FlexFormattingContext::align_all_flex_lines()
// FIXME: Support reverse // FIXME: Support reverse
float cross_size_of_flex_container = specified_cross_size(flex_container()); CSSPixels cross_size_of_flex_container = specified_cross_size(flex_container());
if (is_single_line()) { if (is_single_line()) {
// For single-line flex containers, we only need to center the line along the cross axis. // For single-line flex containers, we only need to center the line along the cross axis.
auto& flex_line = m_flex_lines[0]; auto& flex_line = m_flex_lines[0];
float center_of_line = cross_size_of_flex_container / 2.0f; CSSPixels center_of_line = cross_size_of_flex_container / 2.0f;
for (auto* flex_item : flex_line.items) { for (auto* flex_item : flex_line.items) {
flex_item->cross_offset += center_of_line; flex_item->cross_offset += center_of_line;
} }
} else { } else {
float sum_of_flex_line_cross_sizes = 0; CSSPixels sum_of_flex_line_cross_sizes = 0;
for (auto& line : m_flex_lines) for (auto& line : m_flex_lines)
sum_of_flex_line_cross_sizes += line.cross_size; sum_of_flex_line_cross_sizes += line.cross_size;
float start_of_current_line = 0; CSSPixels start_of_current_line = 0;
float gap_size = 0; CSSPixels gap_size = 0;
switch (flex_container().computed_values().align_content()) { switch (flex_container().computed_values().align_content()) {
case CSS::AlignContent::FlexStart: case CSS::AlignContent::FlexStart:
start_of_current_line = 0; start_of_current_line = 0;
@ -1456,7 +1456,7 @@ void FlexFormattingContext::align_all_flex_lines()
case CSS::AlignContent::SpaceBetween: { case CSS::AlignContent::SpaceBetween: {
start_of_current_line = 0; start_of_current_line = 0;
float leftover_free_space = cross_size_of_flex_container - sum_of_flex_line_cross_sizes; auto leftover_free_space = cross_size_of_flex_container - sum_of_flex_line_cross_sizes;
if (leftover_free_space >= 0) { if (leftover_free_space >= 0) {
int gap_count = m_flex_lines.size() - 1; int gap_count = m_flex_lines.size() - 1;
gap_size = leftover_free_space / gap_count; gap_size = leftover_free_space / gap_count;
@ -1464,7 +1464,7 @@ void FlexFormattingContext::align_all_flex_lines()
break; break;
} }
case CSS::AlignContent::SpaceAround: { case CSS::AlignContent::SpaceAround: {
float leftover_free_space = cross_size_of_flex_container - sum_of_flex_line_cross_sizes; auto leftover_free_space = cross_size_of_flex_container - sum_of_flex_line_cross_sizes;
if (leftover_free_space < 0) { if (leftover_free_space < 0) {
// If the leftover free-space is negative this value is identical to center. // If the leftover free-space is negative this value is identical to center.
start_of_current_line = (cross_size_of_flex_container / 2) - (sum_of_flex_line_cross_sizes / 2); start_of_current_line = (cross_size_of_flex_container / 2) - (sum_of_flex_line_cross_sizes / 2);
@ -1483,7 +1483,7 @@ void FlexFormattingContext::align_all_flex_lines()
} }
for (auto& flex_line : m_flex_lines) { for (auto& flex_line : m_flex_lines) {
float center_of_current_line = start_of_current_line + (flex_line.cross_size / 2); CSSPixels center_of_current_line = start_of_current_line + (flex_line.cross_size / 2);
for (auto* flex_item : flex_line.items) { for (auto* flex_item : flex_line.items) {
flex_item->cross_offset += center_of_current_line; flex_item->cross_offset += center_of_current_line;
} }
@ -1523,23 +1523,23 @@ void FlexFormattingContext::copy_dimensions_from_flex_items_to_boxes()
void FlexFormattingContext::determine_intrinsic_size_of_flex_container() void FlexFormattingContext::determine_intrinsic_size_of_flex_container()
{ {
if (m_available_space_for_flex_container->main.is_intrinsic_sizing_constraint()) { if (m_available_space_for_flex_container->main.is_intrinsic_sizing_constraint()) {
float main_size = calculate_intrinsic_main_size_of_flex_container(); CSSPixels main_size = calculate_intrinsic_main_size_of_flex_container();
set_main_size(flex_container(), main_size); set_main_size(flex_container(), main_size);
} }
if (m_available_space_for_items->cross.is_intrinsic_sizing_constraint()) { if (m_available_space_for_items->cross.is_intrinsic_sizing_constraint()) {
float cross_size = calculate_intrinsic_cross_size_of_flex_container(); CSSPixels cross_size = calculate_intrinsic_cross_size_of_flex_container();
set_cross_size(flex_container(), cross_size); set_cross_size(flex_container(), cross_size);
} }
} }
// https://drafts.csswg.org/css-flexbox-1/#intrinsic-main-sizes // https://drafts.csswg.org/css-flexbox-1/#intrinsic-main-sizes
float FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container() CSSPixels FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container()
{ {
// The min-content main size of a single-line flex container is calculated identically to the max-content main size, // The min-content main size of a single-line flex container is calculated identically to the max-content main size,
// except that the flex items min-content contributions are used instead of their max-content contributions. // except that the flex items min-content contributions are used instead of their max-content contributions.
// However, for a multi-line container, it is simply the largest min-content contribution of all the non-collapsed flex items in the flex container. // However, for a multi-line container, it is simply the largest min-content contribution of all the non-collapsed flex items in the flex container.
if (!is_single_line() && m_available_space_for_items->main.is_min_content()) { if (!is_single_line() && m_available_space_for_items->main.is_min_content()) {
float largest_contribution = 0; CSSPixels largest_contribution = 0;
for (auto const& flex_item : m_flex_items) { for (auto const& flex_item : m_flex_items) {
// FIXME: Skip collapsed flex items. // FIXME: Skip collapsed flex items.
largest_contribution = max(largest_contribution, calculate_main_min_content_contribution(flex_item)); largest_contribution = max(largest_contribution, calculate_main_min_content_contribution(flex_item));
@ -1559,15 +1559,15 @@ float FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container()
// This is the items desired flex fraction. // This is the items desired flex fraction.
for (auto& flex_item : m_flex_items) { for (auto& flex_item : m_flex_items) {
float contribution = 0; CSSPixels contribution = 0;
if (m_available_space_for_items->main.is_min_content()) if (m_available_space_for_items->main.is_min_content())
contribution = calculate_main_min_content_contribution(flex_item); contribution = calculate_main_min_content_contribution(flex_item);
else if (m_available_space_for_items->main.is_max_content()) else if (m_available_space_for_items->main.is_max_content())
contribution = calculate_main_max_content_contribution(flex_item); contribution = calculate_main_max_content_contribution(flex_item);
float outer_flex_base_size = flex_item.flex_base_size + flex_item.margins.main_before + flex_item.margins.main_after + flex_item.borders.main_before + flex_item.borders.main_after + flex_item.padding.main_before + flex_item.padding.main_after; CSSPixels outer_flex_base_size = flex_item.flex_base_size + flex_item.margins.main_before + flex_item.margins.main_after + flex_item.borders.main_before + flex_item.borders.main_after + flex_item.padding.main_before + flex_item.padding.main_after;
float result = contribution - outer_flex_base_size; CSSPixels result = contribution - outer_flex_base_size;
if (result > 0) { if (result > 0) {
if (flex_item.box.computed_values().flex_grow() >= 1) { if (flex_item.box.computed_values().flex_grow() >= 1) {
result /= flex_item.box.computed_values().flex_grow(); result /= flex_item.box.computed_values().flex_grow();
@ -1581,7 +1581,7 @@ float FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container()
result /= flex_item.scaled_flex_shrink_factor; result /= flex_item.scaled_flex_shrink_factor;
} }
flex_item.desired_flex_fraction = result; flex_item.desired_flex_fraction = result.value();
} }
// 2. Place all flex items into lines of infinite length. // 2. Place all flex items into lines of infinite length.
@ -1619,12 +1619,12 @@ float FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container()
flex_line.chosen_flex_fraction = chosen_flex_fraction; flex_line.chosen_flex_fraction = chosen_flex_fraction;
} }
auto determine_main_size = [&]() -> float { auto determine_main_size = [&]() -> CSSPixels {
float largest_sum = 0; CSSPixels largest_sum = 0;
for (auto& flex_line : m_flex_lines) { for (auto& flex_line : m_flex_lines) {
// 4. Add each items flex base size to the product of its flex grow factor (scaled flex shrink factor, if shrinking) // 4. Add each items flex base size to the product of its flex grow factor (scaled flex shrink factor, if shrinking)
// and the chosen flex fraction, then clamp that result by the max main size floored by the min main size. // and the chosen flex fraction, then clamp that result by the max main size floored by the min main size.
float sum = 0; CSSPixels sum = 0;
for (auto& flex_item : flex_line.items) { for (auto& flex_item : flex_line.items) {
float product = 0; float product = 0;
if (flex_item->desired_flex_fraction > 0) if (flex_item->desired_flex_fraction > 0)
@ -1659,15 +1659,15 @@ float FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container()
} }
// https://drafts.csswg.org/css-flexbox-1/#intrinsic-cross-sizes // https://drafts.csswg.org/css-flexbox-1/#intrinsic-cross-sizes
float FlexFormattingContext::calculate_intrinsic_cross_size_of_flex_container() CSSPixels FlexFormattingContext::calculate_intrinsic_cross_size_of_flex_container()
{ {
// The min-content/max-content cross size of a single-line flex container // The min-content/max-content cross size of a single-line flex container
// is the largest min-content contribution/max-content contribution (respectively) of its flex items. // is the largest min-content contribution/max-content contribution (respectively) of its flex items.
if (is_single_line()) { if (is_single_line()) {
auto calculate_largest_contribution = [&](bool resolve_percentage_min_max_sizes) { auto calculate_largest_contribution = [&](bool resolve_percentage_min_max_sizes) {
float largest_contribution = 0; CSSPixels largest_contribution = 0;
for (auto& flex_item : m_flex_items) { for (auto& flex_item : m_flex_items) {
float contribution = 0; CSSPixels contribution = 0;
if (m_available_space_for_items->cross.is_min_content()) if (m_available_space_for_items->cross.is_min_content())
contribution = calculate_cross_min_content_contribution(flex_item, resolve_percentage_min_max_sizes); contribution = calculate_cross_min_content_contribution(flex_item, resolve_percentage_min_max_sizes);
else if (m_available_space_for_items->cross.is_max_content()) else if (m_available_space_for_items->cross.is_max_content())
@ -1696,9 +1696,9 @@ float FlexFormattingContext::calculate_intrinsic_cross_size_of_flex_container()
// The min-content cross size is the largest min-content contribution among all of its flex items. // The min-content cross size is the largest min-content contribution among all of its flex items.
if (m_available_space_for_items->cross.is_min_content()) { if (m_available_space_for_items->cross.is_min_content()) {
auto calculate_largest_contribution = [&](bool resolve_percentage_min_max_sizes) { auto calculate_largest_contribution = [&](bool resolve_percentage_min_max_sizes) {
float largest_contribution = 0; CSSPixels largest_contribution = 0;
for (auto& flex_item : m_flex_items) { for (auto& flex_item : m_flex_items) {
float contribution = calculate_cross_min_content_contribution(flex_item, resolve_percentage_min_max_sizes); CSSPixels contribution = calculate_cross_min_content_contribution(flex_item, resolve_percentage_min_max_sizes);
largest_contribution = max(largest_contribution, contribution); largest_contribution = max(largest_contribution, contribution);
} }
return largest_contribution; return largest_contribution;
@ -1728,7 +1728,7 @@ float FlexFormattingContext::calculate_intrinsic_cross_size_of_flex_container()
calculate_cross_size_of_each_flex_line(); calculate_cross_size_of_each_flex_line();
determine_used_cross_size_of_each_flex_item(); determine_used_cross_size_of_each_flex_item();
float sum_of_flex_line_cross_sizes = 0; CSSPixels sum_of_flex_line_cross_sizes = 0;
for (auto& flex_line : m_flex_lines) { for (auto& flex_line : m_flex_lines) {
sum_of_flex_line_cross_sizes += flex_line.cross_size; sum_of_flex_line_cross_sizes += flex_line.cross_size;
} }
@ -1736,7 +1736,7 @@ float FlexFormattingContext::calculate_intrinsic_cross_size_of_flex_container()
} }
// https://drafts.csswg.org/css-flexbox-1/#intrinsic-item-contributions // https://drafts.csswg.org/css-flexbox-1/#intrinsic-item-contributions
float FlexFormattingContext::calculate_main_min_content_contribution(FlexItem const& item) const CSSPixels FlexFormattingContext::calculate_main_min_content_contribution(FlexItem const& item) const
{ {
// The main-size min-content contribution of a flex item is // The main-size min-content contribution of a flex item is
// the larger of its outer min-content size and outer preferred size if that is not auto, // the larger of its outer min-content size and outer preferred size if that is not auto,
@ -1757,7 +1757,7 @@ float FlexFormattingContext::calculate_main_min_content_contribution(FlexItem co
} }
// https://drafts.csswg.org/css-flexbox-1/#intrinsic-item-contributions // https://drafts.csswg.org/css-flexbox-1/#intrinsic-item-contributions
float FlexFormattingContext::calculate_main_max_content_contribution(FlexItem const& item) const CSSPixels FlexFormattingContext::calculate_main_max_content_contribution(FlexItem const& item) const
{ {
// The main-size max-content contribution of a flex item is // The main-size max-content contribution of a flex item is
// the larger of its outer max-content size and outer preferred size if that is not auto, // the larger of its outer max-content size and outer preferred size if that is not auto,
@ -1791,7 +1791,7 @@ bool FlexFormattingContext::should_treat_cross_size_as_auto(Box const& box) cons
return should_treat_width_as_auto(box, m_available_space_for_items->space); return should_treat_width_as_auto(box, m_available_space_for_items->space);
} }
float FlexFormattingContext::calculate_cross_min_content_contribution(FlexItem const& item, bool resolve_percentage_min_max_sizes) const CSSPixels FlexFormattingContext::calculate_cross_min_content_contribution(FlexItem const& item, bool resolve_percentage_min_max_sizes) const
{ {
auto size = [&] { auto size = [&] {
if (should_treat_cross_size_as_auto(item.box)) if (should_treat_cross_size_as_auto(item.box))
@ -1810,7 +1810,7 @@ float FlexFormattingContext::calculate_cross_min_content_contribution(FlexItem c
return item.add_cross_margin_box_sizes(clamped_inner_size); return item.add_cross_margin_box_sizes(clamped_inner_size);
} }
float FlexFormattingContext::calculate_cross_max_content_contribution(FlexItem const& item, bool resolve_percentage_min_max_sizes) const CSSPixels FlexFormattingContext::calculate_cross_max_content_contribution(FlexItem const& item, bool resolve_percentage_min_max_sizes) const
{ {
auto size = [&] { auto size = [&] {
if (should_treat_cross_size_as_auto(item.box)) if (should_treat_cross_size_as_auto(item.box))
@ -1829,36 +1829,36 @@ float FlexFormattingContext::calculate_cross_max_content_contribution(FlexItem c
return item.add_cross_margin_box_sizes(clamped_inner_size); return item.add_cross_margin_box_sizes(clamped_inner_size);
} }
float FlexFormattingContext::calculate_min_content_main_size(FlexItem const& item) const CSSPixels FlexFormattingContext::calculate_min_content_main_size(FlexItem const& item) const
{ {
return is_row_layout() ? calculate_min_content_width(item.box).value() : calculate_min_content_height(item.box, m_available_space_for_items->space.width).value(); return is_row_layout() ? calculate_min_content_width(item.box) : calculate_min_content_height(item.box, m_available_space_for_items->space.width);
} }
float FlexFormattingContext::calculate_fit_content_main_size(FlexItem const& item) const CSSPixels FlexFormattingContext::calculate_fit_content_main_size(FlexItem const& item) const
{ {
return is_row_layout() ? calculate_fit_content_width(item.box, m_available_space_for_items->space).value() return is_row_layout() ? calculate_fit_content_width(item.box, m_available_space_for_items->space)
: calculate_fit_content_height(item.box, m_available_space_for_items->space).value(); : calculate_fit_content_height(item.box, m_available_space_for_items->space);
} }
float FlexFormattingContext::calculate_fit_content_cross_size(FlexItem const& item) const CSSPixels FlexFormattingContext::calculate_fit_content_cross_size(FlexItem const& item) const
{ {
return !is_row_layout() ? calculate_fit_content_width(item.box, m_available_space_for_items->space).value() return !is_row_layout() ? calculate_fit_content_width(item.box, m_available_space_for_items->space)
: calculate_fit_content_height(item.box, m_available_space_for_items->space).value(); : calculate_fit_content_height(item.box, m_available_space_for_items->space);
} }
float FlexFormattingContext::calculate_max_content_main_size(FlexItem const& item) const CSSPixels FlexFormattingContext::calculate_max_content_main_size(FlexItem const& item) const
{ {
return is_row_layout() ? calculate_max_content_width(item.box).value() : calculate_max_content_height(item.box, m_available_space_for_items->space.width).value(); return is_row_layout() ? calculate_max_content_width(item.box) : calculate_max_content_height(item.box, m_available_space_for_items->space.width);
} }
float FlexFormattingContext::calculate_min_content_cross_size(FlexItem const& item) const CSSPixels FlexFormattingContext::calculate_min_content_cross_size(FlexItem const& item) const
{ {
return is_row_layout() ? calculate_min_content_height(item.box, m_available_space_for_items->space.width).value() : calculate_min_content_width(item.box).value(); return is_row_layout() ? calculate_min_content_height(item.box, m_available_space_for_items->space.width) : calculate_min_content_width(item.box);
} }
float FlexFormattingContext::calculate_max_content_cross_size(FlexItem const& item) const CSSPixels FlexFormattingContext::calculate_max_content_cross_size(FlexItem const& item) const
{ {
return is_row_layout() ? calculate_max_content_height(item.box, m_available_space_for_items->space.width).value() : calculate_max_content_width(item.box).value(); return is_row_layout() ? calculate_max_content_height(item.box, m_available_space_for_items->space.width) : calculate_max_content_width(item.box);
} }
// https://drafts.csswg.org/css-flexbox-1/#stretched // https://drafts.csswg.org/css-flexbox-1/#stretched
@ -1915,7 +1915,7 @@ void FlexFormattingContext::resolve_cross_axis_auto_margins()
// distribute the difference in those sizes equally to the auto margins. // distribute the difference in those sizes equally to the auto margins.
auto outer_cross_size = item->cross_size + item->padding.cross_before + item->padding.cross_after + item->borders.cross_before + item->borders.cross_after; auto outer_cross_size = item->cross_size + item->padding.cross_before + item->padding.cross_after + item->borders.cross_before + item->borders.cross_after;
if (outer_cross_size < line.cross_size) { if (outer_cross_size < line.cross_size) {
float remainder = line.cross_size - outer_cross_size; CSSPixels remainder = line.cross_size - outer_cross_size;
if (item->margins.cross_before_is_auto && item->margins.cross_after_is_auto) { if (item->margins.cross_before_is_auto && item->margins.cross_after_is_auto) {
item->margins.cross_before = remainder / 2.0f; item->margins.cross_before = remainder / 2.0f;
item->margins.cross_after = remainder / 2.0f; item->margins.cross_after = remainder / 2.0f;
@ -1944,7 +1944,7 @@ void FlexFormattingContext::handle_align_content_stretch()
return; return;
// and the sum of the flex lines' cross sizes is less than the flex containers inner cross size, // and the sum of the flex lines' cross sizes is less than the flex containers inner cross size,
float sum_of_flex_line_cross_sizes = 0; CSSPixels sum_of_flex_line_cross_sizes = 0;
for (auto& line : m_flex_lines) for (auto& line : m_flex_lines)
sum_of_flex_line_cross_sizes += line.cross_size; sum_of_flex_line_cross_sizes += line.cross_size;
@ -1953,8 +1953,8 @@ void FlexFormattingContext::handle_align_content_stretch()
// increase the cross size of each flex line by equal amounts // increase the cross size of each flex line by equal amounts
// such that the sum of their cross sizes exactly equals the flex containers inner cross size. // such that the sum of their cross sizes exactly equals the flex containers inner cross size.
float remainder = specified_cross_size(flex_container()) - sum_of_flex_line_cross_sizes; CSSPixels remainder = specified_cross_size(flex_container()) - sum_of_flex_line_cross_sizes;
float extra_per_line = remainder / m_flex_lines.size(); CSSPixels extra_per_line = remainder / m_flex_lines.size();
for (auto& line : m_flex_lines) for (auto& line : m_flex_lines)
line.cross_size += extra_per_line; line.cross_size += extra_per_line;
@ -1965,16 +1965,16 @@ CSSPixelPoint FlexFormattingContext::calculate_static_position(Box const& box) c
{ {
// The cross-axis edges of the static-position rectangle of an absolutely-positioned child // The cross-axis edges of the static-position rectangle of an absolutely-positioned child
// of a flex container are the content edges of the flex container. // of a flex container are the content edges of the flex container.
float cross_offset = 0; CSSPixels cross_offset = 0;
float half_line_size = specified_cross_size(flex_container()) / 2; CSSPixels half_line_size = specified_cross_size(flex_container()) / 2;
auto const& box_state = m_state.get(box); auto const& box_state = m_state.get(box);
float cross_margin_before = is_row_layout() ? box_state.margin_top : box_state.margin_left; CSSPixels cross_margin_before = is_row_layout() ? box_state.margin_top : box_state.margin_left;
float cross_margin_after = is_row_layout() ? box_state.margin_bottom : box_state.margin_right; CSSPixels cross_margin_after = is_row_layout() ? box_state.margin_bottom : box_state.margin_right;
float cross_border_before = is_row_layout() ? box_state.border_top : box_state.border_left; CSSPixels cross_border_before = is_row_layout() ? box_state.border_top : box_state.border_left;
float cross_border_after = is_row_layout() ? box_state.border_bottom : box_state.border_right; CSSPixels cross_border_after = is_row_layout() ? box_state.border_bottom : box_state.border_right;
float cross_padding_before = is_row_layout() ? box_state.padding_top : box_state.padding_left; CSSPixels cross_padding_before = is_row_layout() ? box_state.padding_top : box_state.padding_left;
float cross_padding_after = is_row_layout() ? box_state.padding_bottom : box_state.padding_right; CSSPixels cross_padding_after = is_row_layout() ? box_state.padding_bottom : box_state.padding_right;
switch (alignment_for_item(box)) { switch (alignment_for_item(box)) {
case CSS::AlignItems::Baseline: case CSS::AlignItems::Baseline:
@ -1982,13 +1982,13 @@ CSSPixelPoint FlexFormattingContext::calculate_static_position(Box const& box) c
// Fallthrough // Fallthrough
case CSS::AlignItems::FlexStart: case CSS::AlignItems::FlexStart:
case CSS::AlignItems::Stretch: case CSS::AlignItems::Stretch:
cross_offset = 0 - half_line_size + cross_margin_before + cross_border_before + cross_padding_before; cross_offset = -half_line_size + cross_margin_before + cross_border_before + cross_padding_before;
break; break;
case CSS::AlignItems::FlexEnd: case CSS::AlignItems::FlexEnd:
cross_offset = half_line_size - specified_cross_size(box) - cross_margin_after - cross_border_after - cross_padding_after; cross_offset = half_line_size - specified_cross_size(box) - cross_margin_after - cross_border_after - cross_padding_after;
break; break;
case CSS::AlignItems::Center: case CSS::AlignItems::Center:
cross_offset = 0 - (specified_cross_size(box) / 2.0f); cross_offset = -(specified_cross_size(box) / 2.0f);
break; break;
default: default:
break; break;
@ -2002,7 +2002,7 @@ CSSPixelPoint FlexFormattingContext::calculate_static_position(Box const& box) c
// (For this purpose, auto margins are treated as zero. // (For this purpose, auto margins are treated as zero.
bool pack_from_end = true; bool pack_from_end = true;
float main_offset = 0; CSSPixels main_offset = 0;
switch (flex_container().computed_values().justify_content()) { switch (flex_container().computed_values().justify_content()) {
case CSS::JustifyContent::Start: case CSS::JustifyContent::Start:
if (is_direction_reverse()) { if (is_direction_reverse()) {

View file

@ -36,10 +36,10 @@ private:
void dump_items() const; void dump_items() const;
struct DirectionAgnosticMargins { struct DirectionAgnosticMargins {
float main_before { 0 }; CSSPixels main_before { 0 };
float main_after { 0 }; CSSPixels main_after { 0 };
float cross_before { 0 }; CSSPixels cross_before { 0 };
float cross_after { 0 }; CSSPixels cross_after { 0 };
bool main_before_is_auto { false }; bool main_before_is_auto { false };
bool main_after_is_auto { false }; bool main_after_is_auto { false };
@ -51,31 +51,31 @@ private:
Box& box; Box& box;
CSS::FlexBasisData used_flex_basis {}; CSS::FlexBasisData used_flex_basis {};
bool used_flex_basis_is_definite { false }; bool used_flex_basis_is_definite { false };
float flex_base_size { 0 }; CSSPixels flex_base_size { 0 };
float hypothetical_main_size { 0 }; CSSPixels hypothetical_main_size { 0 };
float hypothetical_cross_size { 0 }; CSSPixels hypothetical_cross_size { 0 };
float hypothetical_cross_size_with_margins() { return hypothetical_cross_size + margins.cross_before + margins.cross_after + borders.cross_after + borders.cross_before + padding.cross_after + padding.cross_before; } CSSPixels hypothetical_cross_size_with_margins() { return hypothetical_cross_size + margins.cross_before + margins.cross_after + borders.cross_after + borders.cross_before + padding.cross_after + padding.cross_before; }
float target_main_size { 0 }; CSSPixels target_main_size { 0 };
bool frozen { false }; bool frozen { false };
Optional<float> flex_factor {}; Optional<float> flex_factor {};
float scaled_flex_shrink_factor { 0 }; float scaled_flex_shrink_factor { 0 };
float desired_flex_fraction { 0 }; float desired_flex_fraction { 0 };
float main_size { 0 }; CSSPixels main_size { 0 };
float cross_size { 0 }; CSSPixels cross_size { 0 };
float main_offset { 0 }; CSSPixels main_offset { 0 };
float cross_offset { 0 }; CSSPixels cross_offset { 0 };
DirectionAgnosticMargins margins {}; DirectionAgnosticMargins margins {};
DirectionAgnosticMargins borders {}; DirectionAgnosticMargins borders {};
DirectionAgnosticMargins padding {}; DirectionAgnosticMargins padding {};
bool is_min_violation { false }; bool is_min_violation { false };
bool is_max_violation { false }; bool is_max_violation { false };
float add_main_margin_box_sizes(float content_size) const CSSPixels add_main_margin_box_sizes(CSSPixels content_size) const
{ {
return content_size + margins.main_before + margins.main_after + borders.main_before + borders.main_after + padding.main_before + padding.main_after; return content_size + margins.main_before + margins.main_after + borders.main_before + borders.main_after + padding.main_before + padding.main_after;
} }
float add_cross_margin_box_sizes(float content_size) const CSSPixels add_cross_margin_box_sizes(CSSPixels content_size) const
{ {
return content_size + margins.cross_before + margins.cross_after + borders.cross_before + borders.cross_after + padding.cross_before + padding.cross_after; return content_size + margins.cross_before + margins.cross_after + borders.cross_before + borders.cross_after + padding.cross_before + padding.cross_after;
} }
@ -83,31 +83,31 @@ private:
struct FlexLine { struct FlexLine {
Vector<FlexItem*> items; Vector<FlexItem*> items;
float cross_size { 0 }; CSSPixels cross_size { 0 };
float remaining_free_space { 0 }; CSSPixels remaining_free_space { 0 };
float chosen_flex_fraction { 0 }; float chosen_flex_fraction { 0 };
}; };
bool has_definite_main_size(Box const&) const; bool has_definite_main_size(Box const&) const;
bool has_definite_cross_size(Box const&) const; bool has_definite_cross_size(Box const&) const;
float specified_main_size(Box const&) const; CSSPixels specified_main_size(Box const&) const;
float specified_cross_size(Box const&) const; CSSPixels specified_cross_size(Box const&) const;
float resolved_definite_main_size(FlexItem const&) const; CSSPixels resolved_definite_main_size(FlexItem const&) const;
float resolved_definite_cross_size(FlexItem const&) const; CSSPixels resolved_definite_cross_size(FlexItem const&) const;
bool has_main_min_size(Box const&) const; bool has_main_min_size(Box const&) const;
bool has_cross_min_size(Box const&) const; bool has_cross_min_size(Box const&) const;
float specified_main_max_size(Box const&) const; CSSPixels specified_main_max_size(Box const&) const;
float specified_cross_max_size(Box const&) const; CSSPixels specified_cross_max_size(Box const&) const;
bool is_cross_auto(Box const&) const; bool is_cross_auto(Box const&) const;
float specified_main_min_size(Box const&) const; CSSPixels specified_main_min_size(Box const&) const;
float specified_cross_min_size(Box const&) const; CSSPixels specified_cross_min_size(Box const&) const;
bool has_main_max_size(Box const&) const; bool has_main_max_size(Box const&) const;
bool has_cross_max_size(Box const&) const; bool has_cross_max_size(Box const&) const;
float automatic_minimum_size(FlexItem const&) const; CSSPixels automatic_minimum_size(FlexItem const&) const;
float content_based_minimum_size(FlexItem const&) const; CSSPixels content_based_minimum_size(FlexItem const&) const;
Optional<float> specified_size_suggestion(FlexItem const&) const; Optional<CSSPixels> specified_size_suggestion(FlexItem const&) const;
Optional<float> transferred_size_suggestion(FlexItem const&) const; Optional<CSSPixels> transferred_size_suggestion(FlexItem const&) const;
float content_size_suggestion(FlexItem const&) const; CSSPixels content_size_suggestion(FlexItem const&) const;
CSS::Size const& computed_main_size(Box const&) const; CSS::Size const& computed_main_size(Box const&) const;
CSS::Size const& computed_main_min_size(Box const&) const; CSS::Size const& computed_main_min_size(Box const&) const;
CSS::Size const& computed_main_max_size(Box const&) const; CSS::Size const& computed_main_max_size(Box const&) const;
@ -115,16 +115,16 @@ private:
CSS::Size const& computed_cross_min_size(Box const&) const; CSS::Size const& computed_cross_min_size(Box const&) const;
CSS::Size const& computed_cross_max_size(Box const&) const; CSS::Size const& computed_cross_max_size(Box const&) const;
float get_pixel_width(Box const& box, Optional<CSS::Size> const& length_percentage) const; CSSPixels get_pixel_width(Box const& box, Optional<CSS::Size> const& length_percentage) const;
float get_pixel_height(Box const& box, Optional<CSS::Size> const& length_percentage) const; CSSPixels get_pixel_height(Box const& box, Optional<CSS::Size> const& length_percentage) const;
bool flex_item_is_stretched(FlexItem const&) const; bool flex_item_is_stretched(FlexItem const&) const;
void set_main_size(Box const&, float size); void set_main_size(Box const&, CSSPixels size);
void set_cross_size(Box const&, float size); void set_cross_size(Box const&, CSSPixels size);
void set_offset(Box const&, float main_offset, float cross_offset); void set_offset(Box const&, CSSPixels main_offset, CSSPixels cross_offset);
void set_main_axis_first_margin(FlexItem&, float margin); void set_main_axis_first_margin(FlexItem&, CSSPixels margin);
void set_main_axis_second_margin(FlexItem&, float margin); void set_main_axis_second_margin(FlexItem&, CSSPixels margin);
void copy_dimensions_from_flex_items_to_boxes(); void copy_dimensions_from_flex_items_to_boxes();
@ -132,7 +132,7 @@ private:
void determine_available_space_for_items(AvailableSpace const&); void determine_available_space_for_items(AvailableSpace const&);
float calculate_indefinite_main_size(FlexItem const&); CSSPixels calculate_indefinite_main_size(FlexItem const&);
void determine_flex_base_size_and_hypothetical_main_size(FlexItem&); void determine_flex_base_size_and_hypothetical_main_size(FlexItem&);
void determine_main_size_of_flex_container(); void determine_main_size_of_flex_container();
@ -167,21 +167,21 @@ private:
void populate_specified_margins(FlexItem&, CSS::FlexDirection) const; void populate_specified_margins(FlexItem&, CSS::FlexDirection) const;
void determine_intrinsic_size_of_flex_container(); void determine_intrinsic_size_of_flex_container();
[[nodiscard]] float calculate_intrinsic_main_size_of_flex_container(); [[nodiscard]] CSSPixels calculate_intrinsic_main_size_of_flex_container();
[[nodiscard]] float calculate_intrinsic_cross_size_of_flex_container(); [[nodiscard]] CSSPixels calculate_intrinsic_cross_size_of_flex_container();
[[nodiscard]] float calculate_cross_min_content_contribution(FlexItem const&, bool resolve_percentage_min_max_sizes) const; [[nodiscard]] CSSPixels calculate_cross_min_content_contribution(FlexItem const&, bool resolve_percentage_min_max_sizes) const;
[[nodiscard]] float calculate_cross_max_content_contribution(FlexItem const&, bool resolve_percentage_min_max_sizes) const; [[nodiscard]] CSSPixels calculate_cross_max_content_contribution(FlexItem const&, bool resolve_percentage_min_max_sizes) const;
[[nodiscard]] float calculate_main_min_content_contribution(FlexItem const&) const; [[nodiscard]] CSSPixels calculate_main_min_content_contribution(FlexItem const&) const;
[[nodiscard]] float calculate_main_max_content_contribution(FlexItem const&) const; [[nodiscard]] CSSPixels calculate_main_max_content_contribution(FlexItem const&) const;
[[nodiscard]] float calculate_min_content_main_size(FlexItem const&) const; [[nodiscard]] CSSPixels calculate_min_content_main_size(FlexItem const&) const;
[[nodiscard]] float calculate_max_content_main_size(FlexItem const&) const; [[nodiscard]] CSSPixels calculate_max_content_main_size(FlexItem const&) const;
[[nodiscard]] float calculate_min_content_cross_size(FlexItem const&) const; [[nodiscard]] CSSPixels calculate_min_content_cross_size(FlexItem const&) const;
[[nodiscard]] float calculate_max_content_cross_size(FlexItem const&) const; [[nodiscard]] CSSPixels calculate_max_content_cross_size(FlexItem const&) const;
[[nodiscard]] float calculate_fit_content_main_size(FlexItem const&) const; [[nodiscard]] CSSPixels calculate_fit_content_main_size(FlexItem const&) const;
[[nodiscard]] float calculate_fit_content_cross_size(FlexItem const&) const; [[nodiscard]] CSSPixels calculate_fit_content_cross_size(FlexItem const&) const;
virtual void parent_context_did_dimension_child_root_box() override; virtual void parent_context_did_dimension_child_root_box() override;