Переглянути джерело

LibWeb: Improve Layout::Box has-definite-size? computation

We now consider a layout box as having definite size in these cases:

- The size is a <length>.
- The size is a <percentage> and the containing block has definite size.

This is not complete, but a bit more accurate than what we had before.
Andreas Kling 3 роки тому
батько
коміт
cd5c17d88e

+ 5 - 1
Userland/Libraries/LibWeb/DOM/Document.cpp

@@ -571,10 +571,14 @@ void Document::update_layout()
     Layout::BlockFormattingContext root_formatting_context(formatting_state, *m_layout_root, nullptr);
     m_layout_root->build_stacking_context_tree();
 
-    auto& icb_state = formatting_state.get_mutable(*m_layout_root);
+    auto& icb = static_cast<Layout::InitialContainingBlock&>(*m_layout_root);
+    auto& icb_state = formatting_state.get_mutable(icb);
     icb_state.content_width = viewport_rect.width();
     icb_state.content_height = viewport_rect.height();
 
+    icb.set_has_definite_width(true);
+    icb.set_has_definite_height(true);
+
     root_formatting_context.run(*m_layout_root, Layout::LayoutMode::Default);
     formatting_state.commit();
 

+ 21 - 4
Userland/Libraries/LibWeb/Layout/Node.cpp

@@ -437,8 +437,27 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style)
     if (computed_values.opacity() == 0)
         m_visible = false;
 
-    if (auto width = specified_style.property(CSS::PropertyID::Width); width.has_value() && !width.value()->has_auto())
-        m_has_definite_width = true;
+    auto is_definite_size = [&](CSS::PropertyID property_id, bool width) {
+        auto maybe_value = specified_style.property(property_id);
+        if (!maybe_value.has_value() || maybe_value.value()->has_auto())
+            return false;
+        auto maybe_length_percentage = specified_style.length_percentage(property_id);
+        if (!maybe_length_percentage.has_value())
+            return false;
+        auto length_percentage = maybe_length_percentage.release_value();
+        if (length_percentage.is_length())
+            return true;
+        if (length_percentage.is_percentage()) {
+            auto* containing_block = this->containing_block();
+            return containing_block && (width ? containing_block->m_has_definite_width : containing_block->m_has_definite_height);
+        }
+        // FIXME: Determine if calc() value is definite.
+        return false;
+    };
+
+    m_has_definite_width = is_definite_size(CSS::PropertyID::Width, true);
+    m_has_definite_height = is_definite_size(CSS::PropertyID::Height, false);
+
     if (auto maybe_length_percentage = specified_style.length_percentage(CSS::PropertyID::Width); maybe_length_percentage.has_value())
         computed_values.set_width(maybe_length_percentage.release_value());
     if (auto maybe_length_percentage = specified_style.length_percentage(CSS::PropertyID::MinWidth); maybe_length_percentage.has_value())
@@ -446,8 +465,6 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style)
     if (auto maybe_length_percentage = specified_style.length_percentage(CSS::PropertyID::MaxWidth); maybe_length_percentage.has_value())
         computed_values.set_max_width(maybe_length_percentage.release_value());
 
-    if (auto height = specified_style.property(CSS::PropertyID::Height); height.has_value() && !height.value()->has_auto())
-        m_has_definite_height = true;
     if (auto maybe_length_percentage = specified_style.length_percentage(CSS::PropertyID::Height); maybe_length_percentage.has_value())
         computed_values.set_height(maybe_length_percentage.release_value());
     if (auto maybe_length_percentage = specified_style.length_percentage(CSS::PropertyID::MinHeight); maybe_length_percentage.has_value())