浏览代码

LibWeb: Remove CSS transform from InlinePaintable's clip rectangle

Fixes bug when CSS transform is applied twice to clip rect:
- While calculating absolute clip rectangles in `refresh_clip_state()`
- While executing `PushStackingContext` painting command.

Duplicated transform is already removed for PaintableBox and this change
adds this for InlinePaintable.
Aliaksandr Kalenik 1 年之前
父节点
当前提交
dc4192c149

+ 13 - 0
Tests/LibWeb/Ref/inline-paintable-inside-translated-container.html

@@ -0,0 +1,13 @@
+<!doctype html>
+<link rel="match" href="reference/inline-paintable-inside-translated-container-ref.html" />
+<style>
+body {
+    transform: translateY(100px);
+    position: absolute;
+    margin: 0;
+}
+div {
+    overflow: hidden;
+    outline: 1px solid black;
+}
+</style><body><div><span>hello

+ 11 - 0
Tests/LibWeb/Ref/reference/inline-paintable-inside-translated-container-ref.html

@@ -0,0 +1,11 @@
+<!doctype html>
+<link rel="match" href="reference/inline-paintable-inside-translated-container-ref.html" />
+<style>
+body {
+    margin-top: 100px;
+    margin-left: 0px;
+}
+span {
+    outline: 1px solid black;
+}
+</style><body><div><span>hello

+ 10 - 2
Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp

@@ -46,8 +46,16 @@ Optional<CSSPixelPoint> InlinePaintable::enclosing_scroll_frame_offset() const
 
 Optional<CSSPixelRect> InlinePaintable::clip_rect() const
 {
-    if (m_enclosing_clip_frame)
-        return m_enclosing_clip_frame->rect();
+    if (m_enclosing_clip_frame) {
+        auto rect = m_enclosing_clip_frame->rect();
+
+        // NOTE: Since the painting command executor applies a CSS transform and the clip rect is calculated
+        //       with this transform taken into account, we need to remove the transform from the clip rect.
+        //       Otherwise, the transform will be applied twice to the clip rect.
+        auto combined_transform = compute_combined_css_transform();
+        rect.translate_by(-combined_transform.translation().to_type<CSSPixels>());
+        return rect;
+    }
     return {};
 }
 

+ 15 - 0
Userland/Libraries/LibWeb/Painting/Paintable.cpp

@@ -174,4 +174,19 @@ CSSPixelPoint Paintable::box_type_agnostic_position() const
     return position;
 }
 
+Gfx::AffineTransform Paintable::compute_combined_css_transform() const
+{
+    Gfx::AffineTransform combined_transform;
+    if (is_paintable_box()) {
+        auto const& paintable_box = static_cast<PaintableBox const&>(*this);
+        auto affine_transform = Gfx::extract_2d_affine_transform(paintable_box.transform());
+        combined_transform = combined_transform.multiply(affine_transform);
+    }
+    for (auto const* ancestor = this->containing_block(); ancestor; ancestor = ancestor->containing_block()) {
+        auto affine_transform = Gfx::extract_2d_affine_transform(ancestor->transform());
+        combined_transform = combined_transform.multiply(affine_transform);
+    }
+    return combined_transform;
+}
+
 }

+ 2 - 0
Userland/Libraries/LibWeb/Painting/Paintable.h

@@ -218,6 +218,8 @@ public:
     SelectionState selection_state() const { return m_selection_state; }
     void set_selection_state(SelectionState state) { m_selection_state = state; }
 
+    Gfx::AffineTransform compute_combined_css_transform() const;
+
 protected:
     explicit Paintable(Layout::Node const&);
 

+ 0 - 10
Userland/Libraries/LibWeb/Painting/PaintableBox.cpp

@@ -164,16 +164,6 @@ CSSPixelRect PaintableBox::compute_absolute_padding_rect_with_css_transform_appl
     return padding_rect;
 }
 
-Gfx::AffineTransform PaintableBox::compute_combined_css_transform() const
-{
-    Gfx::AffineTransform combined_transform;
-    for (auto const* ancestor = this; ancestor; ancestor = ancestor->containing_block()) {
-        auto affine_transform = Gfx::extract_2d_affine_transform(ancestor->transform());
-        combined_transform = combined_transform.multiply(affine_transform);
-    }
-    return combined_transform;
-}
-
 CSSPixelRect PaintableBox::absolute_rect() const
 {
     if (!m_absolute_rect.has_value())

+ 0 - 1
Userland/Libraries/LibWeb/Painting/PaintableBox.h

@@ -203,7 +203,6 @@ public:
     CSSPixels outline_offset() const { return m_outline_offset; }
 
     CSSPixelRect compute_absolute_padding_rect_with_css_transform_applied() const;
-    Gfx::AffineTransform compute_combined_css_transform() const;
 
     Optional<CSSPixelRect> get_clip_rect() const;