1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:07:35 +00:00

LibWeb: Improve how layout nodes decide whether they have definite sizes

1. Make this decision *after* we've inserted the layout node into the
   layout tree. Otherwise, we can't reach its containing block!
2. Per css-sizing-3, consider auto-sized blocks whose sizes resolve
   solely against other definite sizes as definite themselves.

In particular, (2) makes us consider width:auto block children of a
definite-size containing block as having definite size. This becomes
very important in flex layout.
This commit is contained in:
Andreas Kling 2022-03-12 13:24:58 +01:00
parent d201378750
commit 12ac6861e3
3 changed files with 47 additions and 25 deletions

View file

@ -179,6 +179,43 @@ NodeWithStyle::NodeWithStyle(DOM::Document& document, DOM::Node* node, CSS::Comp
m_font = Gfx::FontDatabase::default_font();
}
void NodeWithStyle::did_insert_into_layout_tree(CSS::StyleProperties const& style)
{
// https://drafts.csswg.org/css-sizing-3/#definite
auto is_definite_size = [&](CSS::PropertyID property_id, bool width) {
// A size that can be determined without performing layout; that is,
// a <length>,
// a measure of text (without consideration of line-wrapping),
// a size of the initial containing block,
// or a <percentage> or other formula (such as the “stretch-fit” sizing of non-replaced blocks [CSS2]) that is resolved solely against definite sizes.
auto maybe_value = style.property(property_id);
auto const* containing_block = this->containing_block();
auto containing_block_has_definite_size = containing_block && (width ? containing_block->m_has_definite_width : containing_block->m_has_definite_height);
if (!maybe_value.has_value() || maybe_value.value()->has_auto()) {
// NOTE: The width of a non-flex-item block is considered definite if it's auto and the containing block has definite width.
if (width && is_block_container() && parent() && !parent()->computed_values().display().is_flex_inside())
return containing_block_has_definite_size;
return false;
}
auto maybe_length_percentage = 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())
return containing_block_has_definite_size;
// 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);
}
void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style)
{
auto& computed_values = static_cast<CSS::MutableComputedValues&>(m_computed_values);
@ -436,27 +473,6 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style)
if (computed_values.opacity() == 0)
m_visible = false;
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())