Browse Source

LibWeb/Painting: Add ClippableAndScrollable mixin

Moves code that was duplicated across PaintableBox and InlinePaintable
into separate class.
Aliaksandr Kalenik 1 year ago
parent
commit
cd07249482

+ 1 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -527,6 +527,7 @@ set(SOURCES
     Painting/CommandExecutorCPU.cpp
     Painting/CommandExecutorCPU.cpp
     Painting/CommandList.cpp
     Painting/CommandList.cpp
     Painting/CheckBoxPaintable.cpp
     Painting/CheckBoxPaintable.cpp
+    Painting/ClippableAndScrollable.cpp
     Painting/GradientPainting.cpp
     Painting/GradientPainting.cpp
     Painting/FilterPainting.cpp
     Painting/FilterPainting.cpp
     Painting/ImagePaintable.cpp
     Painting/ImagePaintable.cpp

+ 1 - 0
Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp

@@ -12,6 +12,7 @@
 #include <LibWeb/Layout/Viewport.h>
 #include <LibWeb/Layout/Viewport.h>
 #include <LibWeb/Painting/BackgroundPainting.h>
 #include <LibWeb/Painting/BackgroundPainting.h>
 #include <LibWeb/Painting/InlinePaintable.h>
 #include <LibWeb/Painting/InlinePaintable.h>
+#include <LibWeb/Painting/PaintableBox.h>
 
 
 namespace Web::Painting {
 namespace Web::Painting {
 
 

+ 48 - 0
Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.cpp

@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/Painting/ClippableAndScrollable.h>
+
+namespace Web::Painting {
+
+Optional<int> ClippableAndScrollable::scroll_frame_id() const
+{
+    if (m_enclosing_scroll_frame)
+        return m_enclosing_scroll_frame->id;
+    return {};
+}
+
+Optional<CSSPixelPoint> ClippableAndScrollable::enclosing_scroll_frame_offset() const
+{
+    if (m_enclosing_scroll_frame)
+        return m_enclosing_scroll_frame->offset;
+    return {};
+}
+
+Optional<CSSPixelRect> ClippableAndScrollable::clip_rect() const
+{
+    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.
+        //       Similarly, for hit-testing, the transform must be removed from the clip rectangle since the position
+        //       includes the transform.
+        auto combined_transform = compute_combined_css_transform_for_clippable_and_scrollable();
+        rect.translate_by(-combined_transform.translation().to_type<CSSPixels>());
+        return rect;
+    }
+    return {};
+}
+
+Span<BorderRadiiClip const> ClippableAndScrollable::border_radii_clips() const
+{
+    if (m_enclosing_clip_frame)
+        return m_enclosing_clip_frame->border_radii_clips();
+    return {};
+}
+
+}

+ 37 - 0
Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.h

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/Painting/ClipFrame.h>
+
+namespace Web::Painting {
+
+struct ScrollFrame : public RefCounted<ScrollFrame> {
+    i32 id { -1 };
+    CSSPixelPoint offset;
+};
+
+class ClippableAndScrollable {
+public:
+    virtual ~ClippableAndScrollable() = default;
+
+    void set_enclosing_scroll_frame(RefPtr<ScrollFrame> scroll_frame) { m_enclosing_scroll_frame = scroll_frame; }
+    void set_enclosing_clip_frame(RefPtr<ClipFrame> clip_frame) { m_enclosing_clip_frame = clip_frame; }
+
+    [[nodiscard]] Optional<int> scroll_frame_id() const;
+    [[nodiscard]] Optional<CSSPixelPoint> enclosing_scroll_frame_offset() const;
+    [[nodiscard]] Optional<CSSPixelRect> clip_rect() const;
+    [[nodiscard]] Span<BorderRadiiClip const> border_radii_clips() const;
+
+    virtual Gfx::AffineTransform compute_combined_css_transform_for_clippable_and_scrollable() const = 0;
+
+private:
+    RefPtr<ScrollFrame const> m_enclosing_scroll_frame;
+    RefPtr<ClipFrame const> m_enclosing_clip_frame;
+};
+
+}

+ 1 - 30
Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp

@@ -30,35 +30,6 @@ Layout::InlineNode const& InlinePaintable::layout_node() const
     return static_cast<Layout::InlineNode const&>(Paintable::layout_node());
     return static_cast<Layout::InlineNode const&>(Paintable::layout_node());
 }
 }
 
 
-Optional<int> InlinePaintable::scroll_frame_id() const
-{
-    if (m_enclosing_scroll_frame)
-        return m_enclosing_scroll_frame->id;
-    return {};
-}
-
-Optional<CSSPixelPoint> InlinePaintable::enclosing_scroll_frame_offset() const
-{
-    if (m_enclosing_scroll_frame)
-        return m_enclosing_scroll_frame->offset;
-    return {};
-}
-
-Optional<CSSPixelRect> InlinePaintable::clip_rect() const
-{
-    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 {};
-}
-
 void InlinePaintable::before_paint(PaintContext& context, PaintPhase) const
 void InlinePaintable::before_paint(PaintContext& context, PaintPhase) const
 {
 {
     if (scroll_frame_id().has_value()) {
     if (scroll_frame_id().has_value()) {
@@ -218,7 +189,7 @@ void InlinePaintable::for_each_fragment(Callback callback) const
 
 
 TraversalDecision InlinePaintable::hit_test(CSSPixelPoint position, HitTestType type, Function<TraversalDecision(HitTestResult)> const& callback) const
 TraversalDecision InlinePaintable::hit_test(CSSPixelPoint position, HitTestType type, Function<TraversalDecision(HitTestResult)> const& callback) const
 {
 {
-    if (m_clip_rect.has_value() && !m_clip_rect.value().contains(position))
+    if (clip_rect().has_value() && !clip_rect().value().contains(position))
         return TraversalDecision::Continue;
         return TraversalDecision::Continue;
 
 
     auto position_adjusted_by_scroll_offset = position;
     auto position_adjusted_by_scroll_offset = position;

+ 8 - 12
Userland/Libraries/LibWeb/Painting/InlinePaintable.h

@@ -7,12 +7,14 @@
 #pragma once
 #pragma once
 
 
 #include <LibWeb/Layout/InlineNode.h>
 #include <LibWeb/Layout/InlineNode.h>
-#include <LibWeb/Painting/PaintableBox.h>
+#include <LibWeb/Painting/ClippableAndScrollable.h>
+#include <LibWeb/Painting/Paintable.h>
 #include <LibWeb/Painting/PaintableFragment.h>
 #include <LibWeb/Painting/PaintableFragment.h>
 
 
 namespace Web::Painting {
 namespace Web::Painting {
 
 
-class InlinePaintable final : public Paintable {
+class InlinePaintable final : public Paintable
+    , public ClippableAndScrollable {
     JS_CELL(InlinePaintable, Paintable);
     JS_CELL(InlinePaintable, Paintable);
     JS_DECLARE_ALLOCATOR(InlinePaintable);
     JS_DECLARE_ALLOCATOR(InlinePaintable);
 
 
@@ -44,12 +46,10 @@ public:
     void set_outline_offset(CSSPixels outline_offset) { m_outline_offset = outline_offset; }
     void set_outline_offset(CSSPixels outline_offset) { m_outline_offset = outline_offset; }
     CSSPixels outline_offset() const { return m_outline_offset; }
     CSSPixels outline_offset() const { return m_outline_offset; }
 
 
-    void set_enclosing_scroll_frame(RefPtr<ScrollFrame> scroll_frame) { m_enclosing_scroll_frame = scroll_frame; }
-    void set_enclosing_clip_frame(RefPtr<ClipFrame> clip_frame) { m_enclosing_clip_frame = clip_frame; }
-
-    Optional<int> scroll_frame_id() const;
-    Optional<CSSPixelPoint> enclosing_scroll_frame_offset() const;
-    Optional<CSSPixelRect> clip_rect() const;
+    virtual Gfx::AffineTransform compute_combined_css_transform_for_clippable_and_scrollable() const override
+    {
+        return compute_combined_css_transform();
+    }
 
 
 private:
 private:
     InlinePaintable(Layout::InlineNode const&);
     InlinePaintable(Layout::InlineNode const&);
@@ -57,10 +57,6 @@ private:
     template<typename Callback>
     template<typename Callback>
     void for_each_fragment(Callback) const;
     void for_each_fragment(Callback) const;
 
 
-    Optional<CSSPixelRect> m_clip_rect;
-    RefPtr<ScrollFrame const> m_enclosing_scroll_frame;
-    RefPtr<ClipFrame const> m_enclosing_clip_frame;
-
     Vector<ShadowData> m_box_shadow_data;
     Vector<ShadowData> m_box_shadow_data;
     Optional<BordersData> m_outline_data;
     Optional<BordersData> m_outline_data;
     CSSPixels m_outline_offset { 0 };
     CSSPixels m_outline_offset { 0 };

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

@@ -209,43 +209,6 @@ Optional<CSSPixelRect> PaintableBox::get_clip_rect() const
     return {};
     return {};
 }
 }
 
 
-Optional<int> PaintableBox::scroll_frame_id() const
-{
-    if (m_enclosing_scroll_frame)
-        return m_enclosing_scroll_frame->id;
-    return {};
-}
-
-Optional<CSSPixelPoint> PaintableBox::enclosing_scroll_frame_offset() const
-{
-    if (m_enclosing_scroll_frame)
-        return m_enclosing_scroll_frame->offset;
-    return {};
-}
-
-Optional<CSSPixelRect> PaintableBox::clip_rect() const
-{
-    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 in account, we need to remove the transform from the clip rect.
-        //       Otherwise, the transform will be applied twice to the clip rect.
-        //       Similarly, for hit-testing, the transform must be removed from the clip rectangle since the position
-        //       includes the transform.
-        auto combined_transform = compute_combined_css_transform();
-        rect.translate_by(-combined_transform.translation().to_type<CSSPixels>());
-        return rect;
-    }
-    return {};
-}
-
-Span<BorderRadiiClip const> PaintableBox::border_radii_clips() const
-{
-    if (m_enclosing_clip_frame)
-        return m_enclosing_clip_frame->border_radii_clips();
-    return {};
-}
-
 void PaintableBox::before_paint(PaintContext& context, [[maybe_unused]] PaintPhase phase) const
 void PaintableBox::before_paint(PaintContext& context, [[maybe_unused]] PaintPhase phase) const
 {
 {
     if (!is_visible())
     if (!is_visible())

+ 7 - 13
Userland/Libraries/LibWeb/Painting/PaintableBox.h

@@ -9,18 +9,15 @@
 #include <LibWeb/Painting/BorderPainting.h>
 #include <LibWeb/Painting/BorderPainting.h>
 #include <LibWeb/Painting/BorderRadiusCornerClipper.h>
 #include <LibWeb/Painting/BorderRadiusCornerClipper.h>
 #include <LibWeb/Painting/ClipFrame.h>
 #include <LibWeb/Painting/ClipFrame.h>
+#include <LibWeb/Painting/ClippableAndScrollable.h>
 #include <LibWeb/Painting/Paintable.h>
 #include <LibWeb/Painting/Paintable.h>
 #include <LibWeb/Painting/PaintableFragment.h>
 #include <LibWeb/Painting/PaintableFragment.h>
 #include <LibWeb/Painting/ShadowPainting.h>
 #include <LibWeb/Painting/ShadowPainting.h>
 
 
 namespace Web::Painting {
 namespace Web::Painting {
 
 
-struct ScrollFrame : public RefCounted<ScrollFrame> {
-    i32 id { -1 };
-    CSSPixelPoint offset;
-};
-
-class PaintableBox : public Paintable {
+class PaintableBox : public Paintable
+    , public ClippableAndScrollable {
     JS_CELL(PaintableBox, Paintable);
     JS_CELL(PaintableBox, Paintable);
 
 
 public:
 public:
@@ -206,13 +203,10 @@ public:
 
 
     Optional<CSSPixelRect> get_clip_rect() const;
     Optional<CSSPixelRect> get_clip_rect() const;
 
 
-    void set_enclosing_scroll_frame(RefPtr<ScrollFrame> scroll_frame) { m_enclosing_scroll_frame = scroll_frame; }
-    void set_enclosing_clip_frame(RefPtr<ClipFrame> clip_frame) { m_enclosing_clip_frame = clip_frame; }
-
-    Optional<int> scroll_frame_id() const;
-    Optional<CSSPixelPoint> enclosing_scroll_frame_offset() const;
-    Optional<CSSPixelRect> clip_rect() const;
-    Span<BorderRadiiClip const> border_radii_clips() const;
+    virtual Gfx::AffineTransform compute_combined_css_transform_for_clippable_and_scrollable() const override
+    {
+        return compute_combined_css_transform();
+    }
 
 
 protected:
 protected:
     explicit PaintableBox(Layout::Box const&);
     explicit PaintableBox(Layout::Box const&);