瀏覽代碼

LibWeb: Treate SVG paintable coordinates as relative to <svg> element

Normally, paintable coordinates are relative to the nearest containing
block, but in the SVG case, since <svg> doesn't form a containing block,
we have to specialize the computation of SVGPaintable::absolute_rect().
Andreas Kling 3 年之前
父節點
當前提交
d5aca1c6c4

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

@@ -66,14 +66,18 @@ Gfx::FloatPoint PaintableBox::effective_offset() const
     return m_offset;
 }
 
+Gfx::FloatRect PaintableBox::compute_absolute_rect() const
+{
+    Gfx::FloatRect rect { effective_offset(), content_size() };
+    for (auto const* block = containing_block(); block && block->paintable(); block = block->paintable()->containing_block())
+        rect.translate_by(block->paint_box()->effective_offset());
+    return rect;
+}
+
 Gfx::FloatRect PaintableBox::absolute_rect() const
 {
-    if (!m_absolute_rect.has_value()) {
-        Gfx::FloatRect rect { effective_offset(), content_size() };
-        for (auto const* block = containing_block(); block && block->paintable(); block = block->paintable()->containing_block())
-            rect.translate_by(block->paint_box()->effective_offset());
-        m_absolute_rect = rect;
-    }
+    if (!m_absolute_rect.has_value())
+        m_absolute_rect = compute_absolute_rect();
     return *m_absolute_rect;
 }
 

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

@@ -126,6 +126,8 @@ protected:
     virtual void paint_background(PaintContext&) const;
     virtual void paint_box_shadow(PaintContext&) const;
 
+    virtual Gfx::FloatRect compute_absolute_rect() const;
+
 private:
     Painting::BorderRadiusData normalized_border_radius_data() const;
 

+ 12 - 0
Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp

@@ -5,6 +5,7 @@
  */
 
 #include <LibWeb/Layout/ImageBox.h>
+#include <LibWeb/Layout/SVGSVGBox.h>
 #include <LibWeb/Painting/SVGPaintable.h>
 
 namespace Web::Painting {
@@ -35,4 +36,15 @@ void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase)
     context.svg_context().restore();
 }
 
+Gfx::FloatRect SVGPaintable::compute_absolute_rect() const
+{
+    if (auto* svg_svg_box = layout_box().first_ancestor_of_type<Layout::SVGSVGBox>()) {
+        Gfx::FloatRect rect { effective_offset(), content_size() };
+        for (Layout::Box const* ancestor = svg_svg_box; ancestor && ancestor->paintable(); ancestor = ancestor->paintable()->containing_block())
+            rect.translate_by(ancestor->paint_box()->effective_offset());
+        return rect;
+    }
+    return PaintableBox::compute_absolute_rect();
+}
+
 }

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

@@ -20,6 +20,8 @@ public:
 
 protected:
     SVGPaintable(Layout::SVGBox const&);
+
+    virtual Gfx::FloatRect compute_absolute_rect() const override;
 };
 
 }