Quellcode durchsuchen

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/ :^)
Andreas Kling vor 2 Jahren
Ursprung
Commit
3ec9fd0aae

+ 3 - 0
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 <html> at (0,0) content-size 800x600 [BFC] children: not-inline
+    BlockContainer <body> at (9,9) content-size 100x100 children: not-inline

+ 8 - 0
Tests/LibWeb/Layout/input/transform-calc-length-values.html

@@ -0,0 +1,8 @@
+<style>
+body {
+    transform: translate3d(calc(50px), calc(100px), calc(0px));
+    border: 1px solid black;
+    width: 100px;
+    height: 100px;
+}
+</style>

+ 1 - 1
Userland/Libraries/LibWeb/CSS/StyleProperties.cpp

@@ -442,7 +442,7 @@ Vector<CSS::Transformation> 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()) {

+ 2 - 6
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<CSS::Length const&> 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;