Просмотр исходного кода

LibWeb: Assign hypothetical flex item main sizes as temporary main size

This colors a bit outside the lines of the specification, but the spec
doesn't offer a proper explanation for how descendants of a flex item
are supposed to have access to the flex item's main size for purposes
of percentage resolution.

The approach I came up with here was to take the hypothetical main size
of each flex item, and assign it as a temporary main size. This allows
percentage resolution in descendants to work against the pre-flexing
main size of items. This seems to match how other engines behave,
although it feels somewhat dirty. If/when we learn more about this,
we can come up with something nicer.
Andreas Kling 2 лет назад
Родитель
Сommit
869b322a8f

+ 11 - 0
Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp

@@ -695,6 +695,17 @@ void FlexFormattingContext::determine_flex_base_size_and_hypothetical_main_size(
     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();
     flex_item.hypothetical_main_size = max(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.
+    //       The size may change again when we resolve flexible lengths, but this is necessary in order for
+    //       descendants of this flex item to resolve percentage sizes against something.
+    //
+    //       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
+    if (is_row_layout())
+        m_state.get_mutable(flex_item.box).set_temporary_content_width(flex_item.hypothetical_main_size);
+    else
+        m_state.get_mutable(flex_item.box).set_temporary_content_height(flex_item.hypothetical_main_size);
 }
 
 // https://drafts.csswg.org/css-flexbox-1/#min-size-auto

+ 10 - 0
Userland/Libraries/LibWeb/Layout/LayoutState.cpp

@@ -301,6 +301,16 @@ void LayoutState::UsedValues::set_content_height(float height)
     m_has_definite_height = true;
 }
 
+void LayoutState::UsedValues::set_temporary_content_width(float width)
+{
+    m_content_width = width;
+}
+
+void LayoutState::UsedValues::set_temporary_content_height(float height)
+{
+    m_content_height = height;
+}
+
 float LayoutState::resolved_definite_width(Box const& box) const
 {
     return get(box).content_width();

+ 5 - 0
Userland/Libraries/LibWeb/Layout/LayoutState.h

@@ -53,6 +53,11 @@ struct LayoutState {
         void set_content_width(float);
         void set_content_height(float);
 
+        // NOTE: These are used by FlexFormattingContext to assign a temporary main size to items
+        //       early on, so that descendants have something to resolve percentages against.
+        void set_temporary_content_width(float);
+        void set_temporary_content_height(float);
+
         bool has_definite_width() const { return m_has_definite_width && width_constraint == SizeConstraint::None; }
         bool has_definite_height() const { return m_has_definite_height && height_constraint == SizeConstraint::None; }