浏览代码

LibWeb: More specialization of intrinsic sizing layout

This patch adds a separate entry point for this kind of layout.
We override it in BFC to set up initial width/height values for the
BFC root block.

Resulting dimensions are assigned as content_width and content_height
at the end of intrinsic sizing, for each axis, if it's either "auto"
or there's a min-content or max-content constraint in effect.
Andreas Kling 3 年之前
父节点
当前提交
61c27815e4

+ 27 - 7
Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp

@@ -369,8 +369,10 @@ void BlockFormattingContext::layout_inline_children(BlockContainer const& block_
     auto& block_container_state = m_state.get_mutable(block_container);
 
     if (layout_mode == LayoutMode::IntrinsicSizeDetermination) {
-        block_container_state.content_width = containing_block_width_for(block_container);
-        block_container_state.content_height = containing_block_height_for(block_container);
+        if (block_container.computed_values().width().is_auto() || block_container_state.width_constraint != SizeConstraint::None)
+            block_container_state.content_width = containing_block_width_for(block_container);
+        if (block_container.computed_values().height().is_auto() || block_container_state.height_constraint != SizeConstraint::None)
+            block_container_state.content_height = containing_block_height_for(block_container);
     }
 
     InlineFormattingContext context(m_state, block_container, *this);
@@ -385,7 +387,8 @@ void BlockFormattingContext::layout_inline_children(BlockContainer const& block_
     }
 
     if (layout_mode == LayoutMode::IntrinsicSizeDetermination) {
-        block_container_state.content_width = max_line_width;
+        if (block_container.computed_values().width().is_auto() || block_container_state.width_constraint != SizeConstraint::None)
+            block_container_state.content_width = max_line_width;
     }
 
     // FIXME: This is weird. Figure out a way to make callers responsible for setting the content height.
@@ -449,6 +452,19 @@ void BlockFormattingContext::layout_block_level_box(Box const& box, BlockContain
         independent_formatting_context->parent_context_did_dimension_child_root_box();
 }
 
+void BlockFormattingContext::run_intrinsic_size_determination(Box const& box)
+{
+    auto& box_state = m_state.get_mutable(box);
+
+    if (box.has_definite_width())
+        box_state.content_width = box.computed_values().width().resolved(box, CSS::Length::make_px(containing_block_width_for(box))).to_px(box);
+
+    if (box.has_definite_height())
+        box_state.content_height = box.computed_values().height().resolved(box, CSS::Length::make_px(containing_block_height_for(box))).to_px(box);
+
+    run(box, LayoutMode::IntrinsicSizeDetermination);
+}
+
 void BlockFormattingContext::layout_block_level_children(BlockContainer const& block_container, LayoutMode layout_mode)
 {
     VERIFY(!block_container.children_are_inline());
@@ -457,8 +473,10 @@ void BlockFormattingContext::layout_block_level_children(BlockContainer const& b
 
     if (layout_mode == LayoutMode::IntrinsicSizeDetermination) {
         auto& block_container_state = m_state.get_mutable(block_container);
-        block_container_state.content_width = containing_block_width_for(block_container);
-        block_container_state.content_height = containing_block_height_for(block_container);
+        if (block_container.computed_values().width().is_auto() || block_container_state.width_constraint != SizeConstraint::None)
+            block_container_state.content_width = containing_block_width_for(block_container);
+        if (block_container.computed_values().height().is_auto() || block_container_state.height_constraint != SizeConstraint::None)
+            block_container_state.content_height = containing_block_height_for(block_container);
     }
 
     block_container.for_each_child_of_type<Box>([&](Box& box) {
@@ -468,8 +486,10 @@ void BlockFormattingContext::layout_block_level_children(BlockContainer const& b
 
     if (layout_mode == LayoutMode::IntrinsicSizeDetermination) {
         auto& block_container_state = m_state.get_mutable(block_container);
-        block_container_state.content_width = greatest_child_width(block_container);
-        block_container_state.content_height = content_height;
+        if (block_container.computed_values().width().is_auto() || block_container_state.width_constraint != SizeConstraint::None)
+            block_container_state.content_width = greatest_child_width(block_container);
+        if (block_container.computed_values().height().is_auto() || block_container_state.height_constraint != SizeConstraint::None)
+            block_container_state.content_height = content_height;
     }
 }
 

+ 1 - 0
Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h

@@ -22,6 +22,7 @@ public:
     ~BlockFormattingContext();
 
     virtual void run(Box const&, LayoutMode) override;
+    virtual void run_intrinsic_size_determination(Box const&) override;
 
     bool is_initial() const;
 

+ 9 - 4
Userland/Libraries/LibWeb/Layout/FormattingContext.cpp

@@ -28,6 +28,11 @@ FormattingContext::FormattingContext(Type type, FormattingState& state, Box cons
 
 FormattingContext::~FormattingContext() = default;
 
+void FormattingContext::run_intrinsic_size_determination(Box const& box)
+{
+    run(box, LayoutMode::IntrinsicSizeDetermination);
+}
+
 bool FormattingContext::creates_block_formatting_context(Box const& box)
 {
     if (box.is_root_element())
@@ -863,7 +868,7 @@ float FormattingContext::calculate_min_content_width(Layout::Box const& box) con
 
     auto context = const_cast<FormattingContext*>(this)->create_independent_formatting_context_if_needed(throwaway_state, box);
     VERIFY(context);
-    context->run(box, LayoutMode::IntrinsicSizeDetermination);
+    context->run_intrinsic_size_determination(box);
     if (context->type() == FormattingContext::Type::Flex) {
         cache.min_content_width = box_state.content_width;
     } else {
@@ -893,7 +898,7 @@ float FormattingContext::calculate_max_content_width(Layout::Box const& box) con
 
     auto context = const_cast<FormattingContext*>(this)->create_independent_formatting_context_if_needed(throwaway_state, box);
     VERIFY(context);
-    context->run(box, LayoutMode::IntrinsicSizeDetermination);
+    context->run_intrinsic_size_determination(box);
     if (context->type() == FormattingContext::Type::Flex) {
         cache.max_content_width = box_state.content_width;
     } else {
@@ -924,7 +929,7 @@ float FormattingContext::calculate_min_content_height(Layout::Box const& box) co
 
     auto context = const_cast<FormattingContext*>(this)->create_independent_formatting_context_if_needed(throwaway_state, box);
     VERIFY(context);
-    context->run(box, LayoutMode::IntrinsicSizeDetermination);
+    context->run_intrinsic_size_determination(box);
     if (context->type() == FormattingContext::Type::Flex) {
         cache.min_content_height = box_state.content_height;
     } else {
@@ -955,7 +960,7 @@ float FormattingContext::calculate_max_content_height(Layout::Box const& box) co
 
     auto context = const_cast<FormattingContext*>(this)->create_independent_formatting_context_if_needed(throwaway_state, box);
     VERIFY(context);
-    context->run(box, LayoutMode::IntrinsicSizeDetermination);
+    context->run_intrinsic_size_determination(box);
     if (context->type() == FormattingContext::Type::Flex) {
         cache.max_content_height = box_state.content_height;
     } else {

+ 2 - 0
Userland/Libraries/LibWeb/Layout/FormattingContext.h

@@ -61,6 +61,8 @@ public:
     static float containing_block_width_for(Box const&, FormattingState const&);
     static float containing_block_height_for(Box const&, FormattingState const&);
 
+    virtual void run_intrinsic_size_determination(Box const&);
+
 protected:
     FormattingContext(Type, FormattingState&, Box const&, FormattingContext* parent = nullptr);