Browse Source

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.
Andreas Kling 3 years ago
parent
commit
97f53de8a2

+ 6 - 4
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 we're in a row layout and looking for the width, just use the fit-content width.
     if (is_row_layout())
     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,
     // 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.
     // 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);
     LayoutState throwaway_state(&m_state);
     auto& box_state = throwaway_state.get_mutable(item.box);
     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
 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
 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
 float FlexFormattingContext::calculate_max_content_main_size(FlexItem const& item) const

+ 24 - 6
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));
     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<float> available_space) const
+float FormattingContext::calculate_fit_content_size(float min_content_size, float max_content_size, SizeConstraint constraint, Optional<float> 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)
     // 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))).
     // (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;
         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.
     // Otherwise, equal to the max-content size in that axis.
     return max_content_size;
     return max_content_size;
 }
 }
 
 
-float FormattingContext::calculate_fit_content_width(Layout::Box const& box, Optional<float> available_space) const
+float FormattingContext::calculate_fit_content_width(Layout::Box const& box, SizeConstraint constraint, Optional<float> 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<float> available_space) const
+float FormattingContext::calculate_fit_content_height(Layout::Box const& box, SizeConstraint constraint, Optional<float> 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)
 float FormattingContext::calculate_auto_height(LayoutState const& state, Box const& box)

+ 3 - 3
Userland/Libraries/LibWeb/Layout/FormattingContext.h

@@ -50,8 +50,8 @@ public:
     float calculate_min_content_height(Layout::Box const&) const;
     float calculate_min_content_height(Layout::Box const&) const;
     float calculate_max_content_height(Layout::Box const&) const;
     float calculate_max_content_height(Layout::Box const&) const;
 
 
-    float calculate_fit_content_height(Layout::Box const&, Optional<float> available_height) const;
-    float calculate_fit_content_width(Layout::Box const&, Optional<float> available_width) const;
+    float calculate_fit_content_height(Layout::Box const&, SizeConstraint, Optional<float> available_height) const;
+    float calculate_fit_content_width(Layout::Box const&, SizeConstraint, Optional<float> available_width) const;
 
 
     virtual float greatest_child_width(Box const&);
     virtual float greatest_child_width(Box const&);
 
 
@@ -66,7 +66,7 @@ public:
 protected:
 protected:
     FormattingContext(Type, LayoutState&, Box const&, FormattingContext* parent = nullptr);
     FormattingContext(Type, LayoutState&, Box const&, FormattingContext* parent = nullptr);
 
 
-    float calculate_fit_content_size(float min_content_size, float max_content_size, Optional<float> available_space) const;
+    float calculate_fit_content_size(float min_content_size, float max_content_size, SizeConstraint, Optional<float> available_space) const;
 
 
     OwnPtr<FormattingContext> layout_inside(Box const&, LayoutMode);
     OwnPtr<FormattingContext> layout_inside(Box const&, LayoutMode);
     void compute_inset(Box const& box);
     void compute_inset(Box const& box);