LibWeb: Remove ClippableAndScrollable mixin

Initially ClippableAndScrollable was introduced, because we had
PaintableBox and InlinePaintable and both wanted to share clipping and
scrolling logic. Now, when InlinePaintable is gone, we could inline
ClippableAndScrollable implementation into PaintableBox.
This commit is contained in:
Aliaksandr Kalenik 2025-07-07 19:17:19 +02:00 committed by Alexander Kalenik
commit 5a874cc62a
Notes: github-actions[bot] 2025-07-07 20:06:47 +00:00
6 changed files with 95 additions and 136 deletions

View file

@ -707,7 +707,6 @@ set(SOURCES
Painting/CanvasPaintable.cpp Painting/CanvasPaintable.cpp
Painting/CheckBoxPaintable.cpp Painting/CheckBoxPaintable.cpp
Painting/ClipFrame.cpp Painting/ClipFrame.cpp
Painting/ClippableAndScrollable.cpp
Painting/Command.cpp Painting/Command.cpp
Painting/DisplayList.cpp Painting/DisplayList.cpp
Painting/DisplayListPlayerSkia.cpp Painting/DisplayListPlayerSkia.cpp

View file

@ -1,74 +0,0 @@
/*
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Painting/ClippableAndScrollable.h>
#include <LibWeb/Painting/DisplayListRecorder.h>
#include <LibWeb/Painting/PaintContext.h>
namespace Web::Painting {
Optional<int> ClippableAndScrollable::own_scroll_frame_id() const
{
if (m_own_scroll_frame)
return m_own_scroll_frame->id();
return {};
}
Optional<int> ClippableAndScrollable::scroll_frame_id() const
{
if (m_enclosing_scroll_frame)
return m_enclosing_scroll_frame->id();
return {};
}
CSSPixelPoint ClippableAndScrollable::cumulative_offset_of_enclosing_scroll_frame() const
{
if (m_enclosing_scroll_frame)
return m_enclosing_scroll_frame->cumulative_offset();
return {};
}
Optional<CSSPixelRect> ClippableAndScrollable::clip_rect_for_hit_testing() const
{
if (m_enclosing_clip_frame)
return m_enclosing_clip_frame->clip_rect_for_hit_testing();
return {};
}
void ClippableAndScrollable::apply_clip(PaintContext& context, RefPtr<ClipFrame const> from_clip_frame) const
{
auto const& clip_rects = from_clip_frame->clip_rects();
if (clip_rects.is_empty())
return;
auto& display_list_recorder = context.display_list_recorder();
display_list_recorder.save();
for (auto const& clip_rect : clip_rects) {
Optional<i32> clip_scroll_frame_id;
if (clip_rect.enclosing_scroll_frame)
clip_scroll_frame_id = clip_rect.enclosing_scroll_frame->id();
display_list_recorder.push_scroll_frame_id(clip_scroll_frame_id);
auto rect = context.rounded_device_rect(clip_rect.rect).to_type<int>();
auto corner_radii = clip_rect.corner_radii.as_corners(context);
if (corner_radii.has_any_radius()) {
display_list_recorder.add_rounded_rect_clip(corner_radii, rect, CornerClip::Outside);
} else {
display_list_recorder.add_clip_rect(rect);
}
display_list_recorder.pop_scroll_frame_id();
}
}
void ClippableAndScrollable::restore_clip(PaintContext& context, RefPtr<ClipFrame const> from_clip_frame) const
{
auto const& clip_rects = from_clip_frame->clip_rects();
if (clip_rects.is_empty())
return;
context.display_list_recorder().restore();
}
}

View file

@ -1,55 +0,0 @@
/*
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Painting/ClipFrame.h>
#include <LibWeb/Painting/ScrollFrame.h>
namespace Web::Painting {
class ClippableAndScrollable {
public:
virtual ~ClippableAndScrollable() = default;
void set_enclosing_scroll_frame(RefPtr<ScrollFrame const> scroll_frame) { m_enclosing_scroll_frame = scroll_frame; }
void set_own_scroll_frame(RefPtr<ScrollFrame> scroll_frame) { m_own_scroll_frame = scroll_frame; }
void set_enclosing_clip_frame(RefPtr<ClipFrame const> clip_frame) { m_enclosing_clip_frame = clip_frame; }
void set_own_clip_frame(RefPtr<ClipFrame const> clip_frame) { m_own_clip_frame = clip_frame; }
[[nodiscard]] RefPtr<ScrollFrame const> enclosing_scroll_frame() const { return m_enclosing_scroll_frame; }
[[nodiscard]] Optional<int> scroll_frame_id() const;
[[nodiscard]] CSSPixelPoint cumulative_offset_of_enclosing_scroll_frame() const;
[[nodiscard]] Optional<CSSPixelRect> clip_rect_for_hit_testing() const;
[[nodiscard]] RefPtr<ScrollFrame const> own_scroll_frame() const { return m_own_scroll_frame; }
[[nodiscard]] Optional<int> own_scroll_frame_id() const;
[[nodiscard]] CSSPixelPoint own_scroll_frame_offset() const
{
if (m_own_scroll_frame)
return m_own_scroll_frame->own_offset();
return {};
}
[[nodiscard]] RefPtr<ClipFrame const> enclosing_clip_frame() const { return m_enclosing_clip_frame; }
[[nodiscard]] RefPtr<ClipFrame const> own_clip_frame() const { return m_own_clip_frame; }
void apply_clip(PaintContext&, RefPtr<ClipFrame const>) const;
void restore_clip(PaintContext&, RefPtr<ClipFrame const>) const;
Gfx::AffineTransform const& combined_css_transform() const { return m_combined_css_transform; }
void set_combined_css_transform(Gfx::AffineTransform const& transform) { m_combined_css_transform = transform; }
private:
RefPtr<ScrollFrame const> m_enclosing_scroll_frame;
RefPtr<ScrollFrame const> m_own_scroll_frame;
RefPtr<ClipFrame const> m_enclosing_clip_frame;
RefPtr<ClipFrame const> m_own_clip_frame;
Gfx::AffineTransform m_combined_css_transform;
};
}

View file

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2022-2023, Andreas Kling <andreas@ladybird.org> * Copyright (c) 2022-2023, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2022-2025, Sam Atkins <sam@ladybird.org> * Copyright (c) 2022-2025, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com> * Copyright (c) 2024-2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org> * Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -619,6 +619,67 @@ BorderRadiiData PaintableBox::normalized_border_radii_data(ShrinkRadiiForBorders
return border_radii_data; return border_radii_data;
} }
Optional<int> PaintableBox::own_scroll_frame_id() const
{
if (m_own_scroll_frame)
return m_own_scroll_frame->id();
return {};
}
Optional<int> PaintableBox::scroll_frame_id() const
{
if (m_enclosing_scroll_frame)
return m_enclosing_scroll_frame->id();
return {};
}
CSSPixelPoint PaintableBox::cumulative_offset_of_enclosing_scroll_frame() const
{
if (m_enclosing_scroll_frame)
return m_enclosing_scroll_frame->cumulative_offset();
return {};
}
Optional<CSSPixelRect> PaintableBox::clip_rect_for_hit_testing() const
{
if (m_enclosing_clip_frame)
return m_enclosing_clip_frame->clip_rect_for_hit_testing();
return {};
}
void PaintableBox::apply_clip(PaintContext& context, RefPtr<ClipFrame const> const& from_clip_frame)
{
auto const& clip_rects = from_clip_frame->clip_rects();
if (clip_rects.is_empty())
return;
auto& display_list_recorder = context.display_list_recorder();
display_list_recorder.save();
for (auto const& clip_rect : clip_rects) {
Optional<i32> clip_scroll_frame_id;
if (clip_rect.enclosing_scroll_frame)
clip_scroll_frame_id = clip_rect.enclosing_scroll_frame->id();
display_list_recorder.push_scroll_frame_id(clip_scroll_frame_id);
auto rect = context.rounded_device_rect(clip_rect.rect).to_type<int>();
auto corner_radii = clip_rect.corner_radii.as_corners(context);
if (corner_radii.has_any_radius()) {
display_list_recorder.add_rounded_rect_clip(corner_radii, rect, CornerClip::Outside);
} else {
display_list_recorder.add_clip_rect(rect);
}
display_list_recorder.pop_scroll_frame_id();
}
}
void PaintableBox::restore_clip(PaintContext& context, RefPtr<ClipFrame const> const& from_clip_frame)
{
auto const& clip_rects = from_clip_frame->clip_rects();
if (clip_rects.is_empty())
return;
context.display_list_recorder().restore();
}
void PaintableBox::apply_scroll_offset(PaintContext& context) const void PaintableBox::apply_scroll_offset(PaintContext& context) const
{ {
if (scroll_frame_id().has_value()) { if (scroll_frame_id().has_value()) {

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2022-2025, Andreas Kling <andreas@ladybird.org> * Copyright (c) 2022-2025, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com> * Copyright (c) 2024-2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -16,7 +16,6 @@
#include <LibWeb/Painting/BorderPainting.h> #include <LibWeb/Painting/BorderPainting.h>
#include <LibWeb/Painting/BoxModelMetrics.h> #include <LibWeb/Painting/BoxModelMetrics.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>
@ -25,8 +24,7 @@ namespace Web::Painting {
extern bool g_paint_viewport_scrollbars; extern bool g_paint_viewport_scrollbars;
class PaintableBox : public Paintable class PaintableBox : public Paintable
, public Weakable<PaintableBox> , public Weakable<PaintableBox> {
, public ClippableAndScrollable {
GC_CELL(PaintableBox, Paintable); GC_CELL(PaintableBox, Paintable);
public: public:
@ -241,6 +239,28 @@ public:
void set_used_values_for_grid_template_rows(RefPtr<CSS::GridTrackSizeListStyleValue const> style_value) { m_used_values_for_grid_template_rows = move(style_value); } void set_used_values_for_grid_template_rows(RefPtr<CSS::GridTrackSizeListStyleValue const> style_value) { m_used_values_for_grid_template_rows = move(style_value); }
RefPtr<CSS::GridTrackSizeListStyleValue const> const& used_values_for_grid_template_rows() const { return m_used_values_for_grid_template_rows; } RefPtr<CSS::GridTrackSizeListStyleValue const> const& used_values_for_grid_template_rows() const { return m_used_values_for_grid_template_rows; }
void set_enclosing_scroll_frame(RefPtr<ScrollFrame const> const& scroll_frame) { m_enclosing_scroll_frame = scroll_frame; }
void set_own_scroll_frame(RefPtr<ScrollFrame> const& scroll_frame) { m_own_scroll_frame = scroll_frame; }
void set_enclosing_clip_frame(RefPtr<ClipFrame const> const& clip_frame) { m_enclosing_clip_frame = clip_frame; }
void set_own_clip_frame(RefPtr<ClipFrame const> const& clip_frame) { m_own_clip_frame = clip_frame; }
[[nodiscard]] RefPtr<ScrollFrame const> enclosing_scroll_frame() const { return m_enclosing_scroll_frame; }
[[nodiscard]] Optional<int> scroll_frame_id() const;
[[nodiscard]] CSSPixelPoint cumulative_offset_of_enclosing_scroll_frame() const;
[[nodiscard]] Optional<CSSPixelRect> clip_rect_for_hit_testing() const;
[[nodiscard]] RefPtr<ScrollFrame const> own_scroll_frame() const { return m_own_scroll_frame; }
[[nodiscard]] Optional<int> own_scroll_frame_id() const;
[[nodiscard]] CSSPixelPoint own_scroll_frame_offset() const
{
if (m_own_scroll_frame)
return m_own_scroll_frame->own_offset();
return {};
}
[[nodiscard]] RefPtr<ClipFrame const> enclosing_clip_frame() const { return m_enclosing_clip_frame; }
[[nodiscard]] RefPtr<ClipFrame const> own_clip_frame() const { return m_own_clip_frame; }
protected: protected:
explicit PaintableBox(Layout::Box const&); explicit PaintableBox(Layout::Box const&);
explicit PaintableBox(Layout::InlineNode const&); explicit PaintableBox(Layout::InlineNode const&);
@ -272,6 +292,9 @@ protected:
TraversalDecision hit_test_scrollbars(CSSPixelPoint position, Function<TraversalDecision(HitTestResult)> const& callback) const; TraversalDecision hit_test_scrollbars(CSSPixelPoint position, Function<TraversalDecision(HitTestResult)> const& callback) const;
CSSPixelPoint adjust_position_for_cumulative_scroll_offset(CSSPixelPoint) const; CSSPixelPoint adjust_position_for_cumulative_scroll_offset(CSSPixelPoint) const;
Gfx::AffineTransform const& combined_css_transform() const { return m_combined_css_transform; }
void set_combined_css_transform(Gfx::AffineTransform const& transform) { m_combined_css_transform = transform; }
private: private:
[[nodiscard]] virtual bool is_paintable_box() const final { return true; } [[nodiscard]] virtual bool is_paintable_box() const final { return true; }
@ -282,6 +305,9 @@ private:
bool scrollbar_contains_mouse_position(ScrollDirection, CSSPixelPoint); bool scrollbar_contains_mouse_position(ScrollDirection, CSSPixelPoint);
void scroll_to_mouse_position(CSSPixelPoint); void scroll_to_mouse_position(CSSPixelPoint);
static void apply_clip(PaintContext&, RefPtr<ClipFrame const> const&);
static void restore_clip(PaintContext&, RefPtr<ClipFrame const> const&);
OwnPtr<StackingContext> m_stacking_context; OwnPtr<StackingContext> m_stacking_context;
Optional<OverflowData> m_overflow_data; Optional<OverflowData> m_overflow_data;
@ -293,7 +319,9 @@ private:
Optional<CSSPixelRect> mutable m_absolute_paint_rect; Optional<CSSPixelRect> mutable m_absolute_paint_rect;
RefPtr<ScrollFrame const> m_enclosing_scroll_frame; RefPtr<ScrollFrame const> m_enclosing_scroll_frame;
RefPtr<ScrollFrame const> m_own_scroll_frame;
RefPtr<ClipFrame const> m_enclosing_clip_frame; RefPtr<ClipFrame const> m_enclosing_clip_frame;
RefPtr<ClipFrame const> m_own_clip_frame;
Optional<BordersDataWithElementKind> m_override_borders_data; Optional<BordersDataWithElementKind> m_override_borders_data;
Optional<TableCellCoordinates> m_table_cell_coordinates; Optional<TableCellCoordinates> m_table_cell_coordinates;
@ -302,6 +330,7 @@ private:
Vector<ShadowData> m_box_shadow_data; Vector<ShadowData> m_box_shadow_data;
Gfx::FloatMatrix4x4 m_transform { Gfx::FloatMatrix4x4::identity() }; Gfx::FloatMatrix4x4 m_transform { Gfx::FloatMatrix4x4::identity() };
CSSPixelPoint m_transform_origin; CSSPixelPoint m_transform_origin;
Gfx::AffineTransform m_combined_css_transform;
Optional<BordersData> m_outline_data; Optional<BordersData> m_outline_data;
CSSPixels m_outline_offset { 0 }; CSSPixels m_outline_offset { 0 };

View file

@ -16,7 +16,6 @@ source_set("Painting") {
"CanvasPaintable.cpp", "CanvasPaintable.cpp",
"CheckBoxPaintable.cpp", "CheckBoxPaintable.cpp",
"ClipFrame.cpp", "ClipFrame.cpp",
"ClippableAndScrollable.cpp",
"Command.cpp", "Command.cpp",
"DisplayList.cpp", "DisplayList.cpp",
"DisplayListPlayerSkia.cpp", "DisplayListPlayerSkia.cpp",