From 3ec9fd0aae6fc83ac0f161129fda04ce523e899b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 15 Jul 2023 10:23:43 +0200 Subject: [PATCH] LibWeb: Resolve calc() values in CSS transform There are two parts to this fix: - First, StyleProperties::transformations() would previously omit calc() values entirely when returning the list of transformations. This was very confusing to StackingContext which then tried to index into the list based on faulty assumptions. Fix this by emitting calc values. - Second, StackingContext::get_transformation_matrix() now always calls resolve() on length-percentages. This takes care of actually resolving calc() values. If no reference value for percentages is provided, we default to 0px. This stops LibWeb from asserting on websites with calc() in transform values, such as https://qt.io/ :^) --- .../Layout/expected/transform-calc-length-values.txt | 3 +++ .../LibWeb/Layout/input/transform-calc-length-values.html | 8 ++++++++ Userland/Libraries/LibWeb/CSS/StyleProperties.cpp | 2 +- Userland/Libraries/LibWeb/Painting/StackingContext.cpp | 8 ++------ 4 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/transform-calc-length-values.txt create mode 100644 Tests/LibWeb/Layout/input/transform-calc-length-values.html diff --git a/Tests/LibWeb/Layout/expected/transform-calc-length-values.txt b/Tests/LibWeb/Layout/expected/transform-calc-length-values.txt new file mode 100644 index 0000000000..8068691ead --- /dev/null +++ b/Tests/LibWeb/Layout/expected/transform-calc-length-values.txt @@ -0,0 +1,3 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (9,9) content-size 100x100 children: not-inline diff --git a/Tests/LibWeb/Layout/input/transform-calc-length-values.html b/Tests/LibWeb/Layout/input/transform-calc-length-values.html new file mode 100644 index 0000000000..c8fb1b3f24 --- /dev/null +++ b/Tests/LibWeb/Layout/input/transform-calc-length-values.html @@ -0,0 +1,8 @@ + diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index 85aa19a9ca..021b49c22b 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -442,7 +442,7 @@ Vector StyleProperties::transformations() const if (transformation_value->is_calculated()) { auto& calculated = transformation_value->as_calculated(); if (calculated.resolves_to_length()) { - dbgln("FIXME: Unable to resolve length with no layout node! {}", calculated.to_string()); + values.append(CSS::LengthPercentage { calculated }); } else if (calculated.resolves_to_percentage()) { values.append({ calculated.resolve_percentage().value() }); } else if (calculated.resolves_to_number()) { diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index 123e35dc38..796cd2c44c 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -238,14 +238,10 @@ void StackingContext::paint_internal(PaintContext& context) const Gfx::FloatMatrix4x4 StackingContext::get_transformation_matrix(CSS::Transformation const& transformation) const { auto count = transformation.values.size(); - auto value = [this, transformation](size_t index, Optional reference_length = {}) -> float { + auto value = [this, transformation](size_t index, CSS::Length const& reference_length = CSS::Length::make_px(0)) -> float { return transformation.values[index].visit( [this, reference_length](CSS::LengthPercentage const& value) -> double { - if (reference_length.has_value()) { - return value.resolved(m_box, reference_length.value()).to_px(m_box).to_float(); - } - - return value.length().to_px(m_box).to_float(); + return value.resolved(m_box, reference_length).to_px(m_box).to_float(); }, [this](CSS::AngleOrCalculated const& value) { return value.resolved(m_box).to_degrees() * M_DEG2RAD;