From 97f53de8a233766106868b1bbbea4e01ce71fac6 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 20 Jul 2022 17:59:46 +0200 Subject: [PATCH] LibWeb: Take size constraints into account in fit-content calculations Also avoid calculating both min-content and max-content sizes when only one of them is needed. --- .../LibWeb/Layout/FlexFormattingContext.cpp | 10 ++++--- .../LibWeb/Layout/FormattingContext.cpp | 30 +++++++++++++++---- .../LibWeb/Layout/FormattingContext.h | 6 ++-- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index 8b193246b1..388db2ecce 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -561,11 +561,11 @@ float FlexFormattingContext::calculate_indefinite_main_size(FlexItem const& item // If we're in a row layout and looking for the width, just use the fit-content width. if (is_row_layout()) - return calculate_fit_content_width(item.box, m_available_space->main); + return calculate_fit_content_width(item.box, m_state.get(item.box).width_constraint, m_available_space->main); // We're in a column layout, looking for the height. Figure out the fit-content width, // then layout with that and see what height comes out of it. - float fit_content_cross_size = calculate_fit_content_width(item.box, m_available_space->cross); + float fit_content_cross_size = calculate_fit_content_width(item.box, m_state.get(item.box).width_constraint, m_available_space->cross); LayoutState throwaway_state(&m_state); auto& box_state = throwaway_state.get_mutable(item.box); @@ -1629,12 +1629,14 @@ float FlexFormattingContext::calculate_min_content_main_size(FlexItem const& ite float FlexFormattingContext::calculate_fit_content_main_size(FlexItem const& item) const { - return is_row_layout() ? calculate_fit_content_width(item.box, m_available_space->main) : calculate_fit_content_height(item.box, m_available_space->main); + return is_row_layout() ? calculate_fit_content_width(item.box, m_state.get(item.box).width_constraint, m_available_space->main) + : calculate_fit_content_height(item.box, m_state.get(item.box).height_constraint, m_available_space->main); } float FlexFormattingContext::calculate_fit_content_cross_size(FlexItem const& item) const { - return is_row_layout() ? calculate_fit_content_height(item.box, m_available_space->cross) : calculate_fit_content_width(item.box, m_available_space->cross); + return !is_row_layout() ? calculate_fit_content_width(item.box, m_state.get(item.box).width_constraint, m_available_space->cross) + : calculate_fit_content_height(item.box, m_state.get(item.box).height_constraint, m_available_space->cross); } float FlexFormattingContext::calculate_max_content_main_size(FlexItem const& item) const diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 4a6d6fd5c9..24a29fa6a0 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -823,7 +823,7 @@ void FormattingContext::compute_inset(Box const& box) resolve_two_opposing_insets(computed_values.inset().top, computed_values.inset().bottom, box_state.inset_top, box_state.inset_bottom, containing_block_height_for(box)); } -float FormattingContext::calculate_fit_content_size(float min_content_size, float max_content_size, Optional available_space) const +float FormattingContext::calculate_fit_content_size(float min_content_size, float max_content_size, SizeConstraint constraint, Optional available_space) const { // If the available space in a given axis is definite, equal to clamp(min-content size, stretch-fit size, max-content size) // (i.e. max(min-content size, min(max-content size, stretch-fit size))). @@ -834,20 +834,38 @@ float FormattingContext::calculate_fit_content_size(float min_content_size, floa return s; } - // FIXME: When sizing under a min-content constraint, equal to the min-content size. + // When sizing under a min-content constraint, equal to the min-content size. + if (constraint == SizeConstraint::MinContent) + return min_content_size; // Otherwise, equal to the max-content size in that axis. return max_content_size; } -float FormattingContext::calculate_fit_content_width(Layout::Box const& box, Optional available_space) const +float FormattingContext::calculate_fit_content_width(Layout::Box const& box, SizeConstraint constraint, Optional available_space) const { - return calculate_fit_content_size(calculate_min_content_width(box), calculate_max_content_width(box), available_space); + // When sizing under a min-content constraint, equal to the min-content size. + // NOTE: We check this first, to avoid needlessly calculating the max-content size. + if (constraint == SizeConstraint::MinContent) + return calculate_min_content_width(box); + + if (constraint == SizeConstraint::MaxContent) + return calculate_max_content_width(box); + + return calculate_fit_content_size(calculate_min_content_width(box), calculate_max_content_width(box), constraint, available_space); } -float FormattingContext::calculate_fit_content_height(Layout::Box const& box, Optional available_space) const +float FormattingContext::calculate_fit_content_height(Layout::Box const& box, SizeConstraint constraint, Optional available_space) const { - return calculate_fit_content_size(calculate_min_content_height(box), calculate_max_content_height(box), available_space); + // When sizing under a min-content constraint, equal to the min-content size. + // NOTE: We check this first, to avoid needlessly calculating the max-content size. + if (constraint == SizeConstraint::MinContent) + return calculate_min_content_height(box); + + if (constraint == SizeConstraint::MaxContent) + return calculate_max_content_height(box); + + return calculate_fit_content_size(calculate_min_content_height(box), calculate_max_content_height(box), constraint, available_space); } float FormattingContext::calculate_auto_height(LayoutState const& state, Box const& box) diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h index 4ddf022fd1..9e50dbb9fe 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.h @@ -50,8 +50,8 @@ public: float calculate_min_content_height(Layout::Box const&) const; float calculate_max_content_height(Layout::Box const&) const; - float calculate_fit_content_height(Layout::Box const&, Optional available_height) const; - float calculate_fit_content_width(Layout::Box const&, Optional available_width) const; + float calculate_fit_content_height(Layout::Box const&, SizeConstraint, Optional available_height) const; + float calculate_fit_content_width(Layout::Box const&, SizeConstraint, Optional available_width) const; virtual float greatest_child_width(Box const&); @@ -66,7 +66,7 @@ public: protected: FormattingContext(Type, LayoutState&, Box const&, FormattingContext* parent = nullptr); - float calculate_fit_content_size(float min_content_size, float max_content_size, Optional available_space) const; + float calculate_fit_content_size(float min_content_size, float max_content_size, SizeConstraint, Optional available_space) const; OwnPtr layout_inside(Box const&, LayoutMode); void compute_inset(Box const& box);