From a8f4ea522620644e55dc0c65a6415a76a00ae188 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Tue, 6 Aug 2024 15:26:47 +0300 Subject: [PATCH] LibWeb: Fix "background-clip: text" for elements nested in scrollable Instead of carrying the display list for a mask in each command that might potentially be affected by "background-clip: text", this change introduces a new AddMask command that is applied once for all background layers within one box. The new AddMask command includes a rectangle for the mask destination that is translated by the corresponding scroll offset. Fixes https://github.com/LadybirdBrowser/ladybird/issues/857 --- ...ackground-clip-text-inside-scrollable.html | 30 +++++++++++++ ...round-clip-text-inside-scrollable-ref.html | 23 ++++++++++ .../CSS/StyleValues/AbstractImageStyleValue.h | 2 +- .../StyleValues/ConicGradientStyleValue.cpp | 4 +- .../CSS/StyleValues/ConicGradientStyleValue.h | 2 +- .../CSS/StyleValues/ImageStyleValue.cpp | 4 +- .../LibWeb/CSS/StyleValues/ImageStyleValue.h | 2 +- .../StyleValues/LinearGradientStyleValue.cpp | 4 +- .../StyleValues/LinearGradientStyleValue.h | 2 +- .../StyleValues/RadialGradientStyleValue.cpp | 4 +- .../StyleValues/RadialGradientStyleValue.h | 2 +- .../LibWeb/Painting/BackgroundPainting.cpp | 25 ++++++----- Userland/Libraries/LibWeb/Painting/Command.h | 20 +++++---- .../Libraries/LibWeb/Painting/DisplayList.cpp | 1 + .../Libraries/LibWeb/Painting/DisplayList.h | 1 + .../LibWeb/Painting/DisplayListPlayerSkia.cpp | 39 ++++------------ .../LibWeb/Painting/DisplayListPlayerSkia.h | 3 +- .../LibWeb/Painting/DisplayListRecorder.cpp | 45 +++++++++---------- .../LibWeb/Painting/DisplayListRecorder.h | 19 ++++---- 19 files changed, 135 insertions(+), 97 deletions(-) create mode 100644 Tests/LibWeb/Ref/background-clip-text-inside-scrollable.html create mode 100644 Tests/LibWeb/Ref/reference/background-clip-text-inside-scrollable-ref.html diff --git a/Tests/LibWeb/Ref/background-clip-text-inside-scrollable.html b/Tests/LibWeb/Ref/background-clip-text-inside-scrollable.html new file mode 100644 index 00000000000..98de81eeaa1 --- /dev/null +++ b/Tests/LibWeb/Ref/background-clip-text-inside-scrollable.html @@ -0,0 +1,30 @@ + + + +
+
+ ClipText +
+
+ diff --git a/Tests/LibWeb/Ref/reference/background-clip-text-inside-scrollable-ref.html b/Tests/LibWeb/Ref/reference/background-clip-text-inside-scrollable-ref.html new file mode 100644 index 00000000000..4d8039e62f3 --- /dev/null +++ b/Tests/LibWeb/Ref/reference/background-clip-text-inside-scrollable-ref.html @@ -0,0 +1,23 @@ + + +
+ ClipText +
diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/AbstractImageStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/AbstractImageStyleValue.h index eac8e478657..e0338a5247f 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/AbstractImageStyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/AbstractImageStyleValue.h @@ -36,7 +36,7 @@ public: virtual void resolve_for_size(Layout::NodeWithStyleAndBoxModelMetrics const&, CSSPixelSize) const {}; virtual bool is_paintable() const = 0; - virtual void paint(PaintContext& context, DevicePixelRect const& dest_rect, ImageRendering, RefPtr text_clip = {}) const = 0; + virtual void paint(PaintContext& context, DevicePixelRect const& dest_rect, ImageRendering) const = 0; virtual Optional color_if_single_pixel_bitmap() const { return {}; } }; diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ConicGradientStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/ConicGradientStyleValue.cpp index 669e1c70870..f8025bcaf0c 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/ConicGradientStyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ConicGradientStyleValue.cpp @@ -42,12 +42,12 @@ void ConicGradientStyleValue::resolve_for_size(Layout::NodeWithStyleAndBoxModelM m_resolved->position = m_properties.position->resolved(node, CSSPixelRect { { 0, 0 }, size }); } -void ConicGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr text_clip) const +void ConicGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering) const { VERIFY(m_resolved.has_value()); auto destination_rect = dest_rect.to_type(); auto position = context.rounded_device_point(m_resolved->position).to_type(); - context.display_list_recorder().fill_rect_with_conic_gradient(destination_rect, m_resolved->data, position, text_clip); + context.display_list_recorder().fill_rect_with_conic_gradient(destination_rect, m_resolved->data, position); } bool ConicGradientStyleValue::equals(StyleValue const& other) const diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ConicGradientStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/ConicGradientStyleValue.h index 0327abf6dad..4b1bad4fff1 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/ConicGradientStyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ConicGradientStyleValue.h @@ -25,7 +25,7 @@ public: virtual String to_string() const override; - void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr text_clip = {}) const override; + void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override; virtual bool equals(StyleValue const& other) const override; diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp index e6feb9e990c..306f4c0eafd 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp @@ -137,11 +137,11 @@ Optional ImageStyleValue::natural_aspect_ratio() const return {}; } -void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, RefPtr text_clip) const +void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const { if (auto const* b = bitmap(m_current_frame_index, dest_rect.size().to_type()); b != nullptr) { auto scaling_mode = to_gfx_scaling_mode(image_rendering, b->rect(), dest_rect.to_type()); - context.display_list_recorder().draw_scaled_immutable_bitmap(dest_rect.to_type(), *b, b->rect(), scaling_mode, text_clip); + context.display_list_recorder().draw_scaled_immutable_bitmap(dest_rect.to_type(), *b, b->rect(), scaling_mode); } } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h index bb833c978dc..fc6b6d09fc2 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h @@ -45,7 +45,7 @@ public: Optional natural_aspect_ratio() const override; virtual bool is_paintable() const override; - void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, RefPtr clip_paths = {}) const override; + void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const override; virtual Optional color_if_single_pixel_bitmap() const override; Gfx::ImmutableBitmap const* current_frame_bitmap(DevicePixelRect const& dest_rect) const; diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/LinearGradientStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/LinearGradientStyleValue.cpp index 37dc9b047e5..eb88c30c947 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/LinearGradientStyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/LinearGradientStyleValue.cpp @@ -109,10 +109,10 @@ void LinearGradientStyleValue::resolve_for_size(Layout::NodeWithStyleAndBoxModel m_resolved = ResolvedData { Painting::resolve_linear_gradient_data(node, size, *this), size }; } -void LinearGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr text_clip) const +void LinearGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering) const { VERIFY(m_resolved.has_value()); - context.display_list_recorder().fill_rect_with_linear_gradient(dest_rect.to_type(), m_resolved->data, text_clip); + context.display_list_recorder().fill_rect_with_linear_gradient(dest_rect.to_type(), m_resolved->data); } } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/LinearGradientStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/LinearGradientStyleValue.h index 53e7581d5a4..74f84de7861 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/LinearGradientStyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/LinearGradientStyleValue.h @@ -60,7 +60,7 @@ public: void resolve_for_size(Layout::NodeWithStyleAndBoxModelMetrics const&, CSSPixelSize) const override; bool is_paintable() const override { return true; } - void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering, RefPtr text_clip = {}) const override; + void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const override; private: LinearGradientStyleValue(GradientDirection direction, Vector color_stop_list, GradientType type, GradientRepeating repeating) diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/RadialGradientStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/RadialGradientStyleValue.cpp index c38324dc8c3..c0923861011 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/RadialGradientStyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/RadialGradientStyleValue.cpp @@ -207,12 +207,12 @@ bool RadialGradientStyleValue::equals(StyleValue const& other) const return m_properties == other_gradient.m_properties; } -void RadialGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr text_clip) const +void RadialGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering) const { VERIFY(m_resolved.has_value()); auto center = context.rounded_device_point(m_resolved->center).to_type(); auto size = context.rounded_device_size(m_resolved->gradient_size).to_type(); - context.display_list_recorder().fill_rect_with_radial_gradient(dest_rect.to_type(), m_resolved->data, center, size, text_clip); + context.display_list_recorder().fill_rect_with_radial_gradient(dest_rect.to_type(), m_resolved->data, center, size); } } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/RadialGradientStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/RadialGradientStyleValue.h index bd8f79f66c4..2f8c6bd795d 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/RadialGradientStyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/RadialGradientStyleValue.h @@ -51,7 +51,7 @@ public: virtual String to_string() const override; - void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering, RefPtr text_clip = {}) const override; + void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override; virtual bool equals(StyleValue const& other) const override; diff --git a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp index 1782d852e5d..f82dbec5229 100644 --- a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -56,10 +56,12 @@ static CSSPixelSize run_default_sizing_algorithm( return default_size; } -static RefPtr compute_text_clip_paths(PaintContext& context, Paintable const& paintable) +static RefPtr compute_text_clip_paths(PaintContext& context, Paintable const& paintable, CSSPixelPoint containing_block_location) { auto text_clip_paths = DisplayList::create(); DisplayListRecorder display_list_recorder(*text_clip_paths); + // Remove containing block offset, so executing the display list will produce mask at (0, 0) + display_list_recorder.translate(-context.floored_device_point(containing_block_location).to_type()); auto add_text_clip_path = [&](PaintableFragment const& fragment) { auto glyph_run = fragment.glyph_run(); if (!glyph_run || glyph_run->glyphs().is_empty()) @@ -116,13 +118,15 @@ static BackgroundBox get_box(CSS::BackgroundBox box_clip, BackgroundBox border_b // https://www.w3.org/TR/css-backgrounds-3/#backgrounds void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMetrics const& layout_node, CSS::ImageRendering image_rendering, ResolvedBackground resolved_background, BorderRadiiData const& border_radii) { - RefPtr text_clip; - if (resolved_background.needs_text_clip) { - text_clip = compute_text_clip_paths(context, *layout_node.paintable()); - } - auto& display_list_recorder = context.display_list_recorder(); + DisplayListRecorderStateSaver state { display_list_recorder }; + if (resolved_background.needs_text_clip) { + auto display_list = compute_text_clip_paths(context, *layout_node.paintable(), resolved_background.background_rect.location()); + auto rect = context.rounded_device_rect(resolved_background.background_rect); + display_list_recorder.add_mask(move(display_list), rect.to_type()); + } + BackgroundBox border_box { resolved_background.background_rect, border_radii @@ -136,8 +140,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet color_box.radii.top_left.as_corner(context), color_box.radii.top_right.as_corner(context), color_box.radii.bottom_right.as_corner(context), - color_box.radii.bottom_left.as_corner(context), - text_clip); + color_box.radii.bottom_left.as_corner(context)); struct { DevicePixels top { 0 }; @@ -332,17 +335,17 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet fill_rect = fill_rect->united(image_device_rect); } }); - display_list_recorder.fill_rect(fill_rect->to_type(), color.value(), text_clip); + display_list_recorder.fill_rect(fill_rect->to_type(), color.value()); } else if (is(image) && repeat_x && repeat_y && !repeat_x_has_gap && !repeat_y_has_gap) { // Use a dedicated painting command for repeated images instead of recording a separate command for each instance // of a repeated background, so the painter has the opportunity to optimize the painting of repeated images. auto dest_rect = context.rounded_device_rect(image_rect); auto const* bitmap = static_cast(image).current_frame_bitmap(dest_rect); auto scaling_mode = to_gfx_scaling_mode(image_rendering, bitmap->rect(), dest_rect.to_type()); - context.display_list_recorder().draw_repeated_immutable_bitmap(dest_rect.to_type(), clip_rect.to_type(), *bitmap, scaling_mode, { .x = repeat_x, .y = repeat_y }, text_clip); + context.display_list_recorder().draw_repeated_immutable_bitmap(dest_rect.to_type(), clip_rect.to_type(), *bitmap, scaling_mode, { .x = repeat_x, .y = repeat_y }); } else { for_each_image_device_rect([&](auto const& image_device_rect) { - image.paint(context, image_device_rect, image_rendering, text_clip); + image.paint(context, image_device_rect, image_rendering); }); } } diff --git a/Userland/Libraries/LibWeb/Painting/Command.h b/Userland/Libraries/LibWeb/Painting/Command.h index a27b1907b93..be22bfc51e1 100644 --- a/Userland/Libraries/LibWeb/Painting/Command.h +++ b/Userland/Libraries/LibWeb/Painting/Command.h @@ -50,7 +50,6 @@ struct DrawGlyphRun { struct FillRect { Gfx::IntRect rect; Color color; - RefPtr text_clip; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } @@ -71,7 +70,6 @@ struct DrawScaledImmutableBitmap { NonnullRefPtr bitmap; Gfx::IntRect src_rect; Gfx::ScalingMode scaling_mode; - RefPtr text_clip; [[nodiscard]] Gfx::IntRect bounding_rect() const { return dst_rect; } void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); } @@ -88,7 +86,6 @@ struct DrawRepeatedImmutableBitmap { NonnullRefPtr bitmap; Gfx::ScalingMode scaling_mode; Repeat repeat; - RefPtr text_clip; void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); } }; @@ -133,7 +130,6 @@ struct PopStackingContext { }; struct PaintLinearGradient { Gfx::IntRect gradient_rect; LinearGradientData linear_gradient_data; - RefPtr text_clip; [[nodiscard]] Gfx::IntRect bounding_rect() const { return gradient_rect; } @@ -174,7 +170,6 @@ struct FillRectWithRoundedCorners { Gfx::IntRect rect; Color color; CornerRadii corner_radii; - RefPtr text_clip; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } @@ -314,7 +309,6 @@ struct PaintRadialGradient { RadialGradientData radial_gradient_data; Gfx::IntPoint center; Gfx::IntSize size; - RefPtr text_clip; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } @@ -325,7 +319,6 @@ struct PaintConicGradient { Gfx::IntRect rect; ConicGradientData conic_gradient_data; Gfx::IntPoint position; - RefPtr text_clip; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } @@ -356,6 +349,16 @@ struct AddRoundedRectClip { void translate_by(Gfx::IntPoint const& offset) { border_rect.translate_by(offset); } }; +struct AddMask { + RefPtr display_list; + Gfx::IntRect rect; + + void translate_by(Gfx::IntPoint const& offset) + { + rect.translate_by(offset); + } +}; + using Command = Variant< DrawGlyphRun, FillRect, @@ -384,6 +387,7 @@ using Command = Variant< ApplyBackdropFilter, DrawRect, DrawTriangleWave, - AddRoundedRectClip>; + AddRoundedRectClip, + AddMask>; } diff --git a/Userland/Libraries/LibWeb/Painting/DisplayList.cpp b/Userland/Libraries/LibWeb/Painting/DisplayList.cpp index 6d80b0d298c..81be86eb436 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayList.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayList.cpp @@ -85,6 +85,7 @@ void DisplayListPlayer::execute(DisplayList& display_list) else HANDLE_COMMAND(DrawRect, draw_rect) else HANDLE_COMMAND(DrawTriangleWave, draw_triangle_wave) else HANDLE_COMMAND(AddRoundedRectClip, add_rounded_rect_clip) + else HANDLE_COMMAND(AddMask, add_mask) else VERIFY_NOT_REACHED(); // clang-format on } diff --git a/Userland/Libraries/LibWeb/Painting/DisplayList.h b/Userland/Libraries/LibWeb/Painting/DisplayList.h index a52c6d50143..25b86339b4d 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayList.h +++ b/Userland/Libraries/LibWeb/Painting/DisplayList.h @@ -69,6 +69,7 @@ private: virtual void draw_rect(DrawRect const&) = 0; virtual void draw_triangle_wave(DrawTriangleWave const&) = 0; virtual void add_rounded_rect_clip(AddRoundedRectClip const&) = 0; + virtual void add_mask(AddMask const&) = 0; virtual bool would_be_fully_clipped_by_painter(Gfx::IntRect) const = 0; }; diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp index 069b022ed81..244b7277fc4 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp @@ -374,15 +374,6 @@ static SkSamplingOptions to_skia_sampling_options(Gfx::ScalingMode scaling_mode) } } -#define APPLY_TEXT_CLIP_IF_NEEDED(MASK_RECT) \ - ScopeGuard const restore { [&] { \ - if (command.text_clip) \ - surface().canvas().restore(); \ - } }; \ - if (command.text_clip) { \ - apply_mask_painted_from(*command.text_clip, MASK_RECT); \ - } - DisplayListPlayerSkia::SkiaSurface& DisplayListPlayerSkia::surface() const { return static_cast(*m_surface); @@ -422,8 +413,6 @@ void DisplayListPlayerSkia::draw_glyph_run(DrawGlyphRun const& command) void DisplayListPlayerSkia::fill_rect(FillRect const& command) { - APPLY_TEXT_CLIP_IF_NEEDED(command.rect) - auto const& rect = command.rect; auto& canvas = surface().canvas(); SkPaint paint; @@ -444,8 +433,6 @@ void DisplayListPlayerSkia::draw_scaled_bitmap(DrawScaledBitmap const& command) void DisplayListPlayerSkia::draw_scaled_immutable_bitmap(DrawScaledImmutableBitmap const& command) { - APPLY_TEXT_CLIP_IF_NEEDED(command.dst_rect) - auto src_rect = to_skia_rect(command.src_rect); auto dst_rect = to_skia_rect(command.dst_rect); auto bitmap = to_skia_bitmap(command.bitmap->bitmap()); @@ -457,8 +444,6 @@ void DisplayListPlayerSkia::draw_scaled_immutable_bitmap(DrawScaledImmutableBitm void DisplayListPlayerSkia::draw_repeated_immutable_bitmap(DrawRepeatedImmutableBitmap const& command) { - APPLY_TEXT_CLIP_IF_NEEDED(command.clip_rect) - auto bitmap = to_skia_bitmap(command.bitmap->bitmap()); auto image = SkImages::RasterFromBitmap(bitmap); @@ -655,8 +640,6 @@ static ColorStopList expand_repeat_length(ColorStopList const& color_stop_list, void DisplayListPlayerSkia::paint_linear_gradient(PaintLinearGradient const& command) { - APPLY_TEXT_CLIP_IF_NEEDED(command.gradient_rect) - auto const& linear_gradient_data = command.linear_gradient_data; auto color_stop_list = linear_gradient_data.color_stops.list; auto const& repeat_length = linear_gradient_data.color_stops.repeat_length; @@ -833,8 +816,6 @@ void DisplayListPlayerSkia::paint_text_shadow(PaintTextShadow const& command) void DisplayListPlayerSkia::fill_rect_with_rounded_corners(FillRectWithRoundedCorners const& command) { - APPLY_TEXT_CLIP_IF_NEEDED(command.rect) - auto const& rect = command.rect; auto& canvas = surface().canvas(); @@ -1200,8 +1181,6 @@ void DisplayListPlayerSkia::draw_rect(DrawRect const& command) void DisplayListPlayerSkia::paint_radial_gradient(PaintRadialGradient const& command) { - APPLY_TEXT_CLIP_IF_NEEDED(command.rect) - auto const& radial_gradient_data = command.radial_gradient_data; auto color_stop_list = radial_gradient_data.color_stops.list; @@ -1249,8 +1228,6 @@ void DisplayListPlayerSkia::paint_radial_gradient(PaintRadialGradient const& com void DisplayListPlayerSkia::paint_conic_gradient(PaintConicGradient const& command) { - APPLY_TEXT_CLIP_IF_NEEDED(command.rect) - auto const& conic_gradient_data = command.conic_gradient_data; auto color_stop_list = conic_gradient_data.color_stops.list; @@ -1300,19 +1277,14 @@ void DisplayListPlayerSkia::add_rounded_rect_clip(AddRoundedRectClip const& comm canvas.clipRRect(rounded_rect, clip_op, true); } -bool DisplayListPlayerSkia::would_be_fully_clipped_by_painter(Gfx::IntRect rect) const -{ - return surface().canvas().quickReject(to_skia_rect(rect)); -} - -void DisplayListPlayerSkia::apply_mask_painted_from(DisplayList& display_list, Gfx::IntRect rect) +void DisplayListPlayerSkia::add_mask(AddMask const& command) { + auto const& rect = command.rect; auto mask_surface = m_surface->make_surface(rect.width(), rect.height()); auto previous_surface = move(m_surface); m_surface = make(mask_surface); - surface().canvas().translate(-rect.x(), -rect.y()); - execute(display_list); + execute(*command.display_list); m_surface = move(previous_surface); SkMatrix mask_matrix; @@ -1323,4 +1295,9 @@ void DisplayListPlayerSkia::apply_mask_painted_from(DisplayList& display_list, G surface().canvas().clipShader(shader); } +bool DisplayListPlayerSkia::would_be_fully_clipped_by_painter(Gfx::IntRect rect) const +{ + return surface().canvas().quickReject(to_skia_rect(rect)); +} + } diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h index de19198f5ee..4e3c9eecb46 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h +++ b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h @@ -76,11 +76,10 @@ private: void paint_conic_gradient(PaintConicGradient const&) override; void draw_triangle_wave(DrawTriangleWave const&) override; void add_rounded_rect_clip(AddRoundedRectClip const&) override; + void add_mask(AddMask const&) override; bool would_be_fully_clipped_by_painter(Gfx::IntRect) const override; - void apply_mask_painted_from(DisplayList&, Gfx::IntRect); - class SkiaSurface; SkiaSurface& surface() const; diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp index 65605fa57a1..9463fbfe733 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp @@ -30,14 +30,20 @@ void DisplayListRecorder::add_rounded_rect_clip(CornerRadii corner_radii, Gfx::I corner_clip }); } -void DisplayListRecorder::fill_rect(Gfx::IntRect const& rect, Color color, RefPtr text_clip) +void DisplayListRecorder::add_mask(RefPtr display_list, Gfx::IntRect rect) +{ + append(AddMask { + .display_list = move(display_list), + .rect = state().translation.map(rect) }); +} + +void DisplayListRecorder::fill_rect(Gfx::IntRect const& rect, Color color) { if (rect.is_empty()) return; append(FillRect { .rect = state().translation.map(rect), .color = color, - .text_clip = move(text_clip), }); } @@ -128,28 +134,26 @@ void DisplayListRecorder::fill_ellipse(Gfx::IntRect const& a_rect, Color color) }); } -void DisplayListRecorder::fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data, RefPtr text_clip) +void DisplayListRecorder::fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data) { if (gradient_rect.is_empty()) return; append(PaintLinearGradient { .gradient_rect = state().translation.map(gradient_rect), - .linear_gradient_data = data, - .text_clip = move(text_clip) }); + .linear_gradient_data = data }); } -void DisplayListRecorder::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position, RefPtr text_clip) +void DisplayListRecorder::fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position) { if (rect.is_empty()) return; append(PaintConicGradient { .rect = state().translation.map(rect), .conic_gradient_data = data, - .position = position, - .text_clip = move(text_clip) }); + .position = position }); } -void DisplayListRecorder::fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size, RefPtr text_clip) +void DisplayListRecorder::fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size) { if (rect.is_empty()) return; @@ -157,8 +161,7 @@ void DisplayListRecorder::fill_rect_with_radial_gradient(Gfx::IntRect const& rec .rect = state().translation.map(rect), .radial_gradient_data = data, .center = center, - .size = size, - .text_clip = move(text_clip) }); + .size = size }); } void DisplayListRecorder::draw_rect(Gfx::IntRect const& rect, Color color, bool rough) @@ -183,7 +186,7 @@ void DisplayListRecorder::draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx:: }); } -void DisplayListRecorder::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode, RefPtr text_clip) +void DisplayListRecorder::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode) { if (dst_rect.is_empty()) return; @@ -192,11 +195,10 @@ void DisplayListRecorder::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_r .bitmap = bitmap, .src_rect = src_rect, .scaling_mode = scaling_mode, - .text_clip = move(text_clip), }); } -void DisplayListRecorder::draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, NonnullRefPtr bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat repeat, RefPtr text_clip) +void DisplayListRecorder::draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, NonnullRefPtr bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat repeat) { append(DrawRepeatedImmutableBitmap { .dst_rect = dst_rect, @@ -204,7 +206,6 @@ void DisplayListRecorder::draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, .bitmap = move(bitmap), .scaling_mode = scaling_mode, .repeat = repeat, - .text_clip = move(text_clip), }); } @@ -352,13 +353,13 @@ void DisplayListRecorder::paint_text_shadow(int blur_radius, Gfx::IntRect boundi .draw_location = state().translation.map(draw_location) }); } -void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius, RefPtr text_clip) +void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius) { if (rect.is_empty()) return; if (!top_left_radius && !top_right_radius && !bottom_right_radius && !bottom_left_radius) { - fill_rect(rect, color, text_clip); + fill_rect(rect, color); return; } @@ -371,18 +372,17 @@ void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& rec .bottom_right = bottom_right_radius, .bottom_left = bottom_left_radius, }, - .text_clip = text_clip, }); } -void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius, RefPtr text_clip) +void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius) { if (a_rect.is_empty()) return; - fill_rect_with_rounded_corners(a_rect, color, radius, radius, radius, radius, move(text_clip)); + fill_rect_with_rounded_corners(a_rect, color, radius, radius, radius, radius); } -void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius, RefPtr text_clip) +void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius) { if (a_rect.is_empty()) return; @@ -390,8 +390,7 @@ void DisplayListRecorder::fill_rect_with_rounded_corners(Gfx::IntRect const& a_r { top_left_radius, top_left_radius }, { top_right_radius, top_right_radius }, { bottom_right_radius, bottom_right_radius }, - { bottom_left_radius, bottom_left_radius }, - move(text_clip)); + { bottom_left_radius, bottom_left_radius }); } void DisplayListRecorder::draw_triangle_wave(Gfx::IntPoint a_p1, Gfx::IntPoint a_p2, Color color, int amplitude, int thickness = 1) diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h index c12d16839cc..8e57b108212 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h +++ b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h @@ -40,7 +40,7 @@ class DisplayListRecorder { AK_MAKE_NONMOVABLE(DisplayListRecorder); public: - void fill_rect(Gfx::IntRect const& rect, Color color, RefPtr text_clip = {}); + void fill_rect(Gfx::IntRect const& rect, Color color); struct FillPathUsingColorParams { Gfx::Path path; @@ -80,16 +80,16 @@ public: void fill_ellipse(Gfx::IntRect const& a_rect, Color color); - void fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data, RefPtr text_clip = {}); - void fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position, RefPtr text_clip = {}); - void fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size, RefPtr text_clip = {}); + void fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data); + void fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position); + void fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size); void draw_rect(Gfx::IntRect const& rect, Color color, bool rough = false); void draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor); - void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor, RefPtr text_clip = {}); + void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor); - void draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, NonnullRefPtr bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat, RefPtr text_clip = {}); + void draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, NonnullRefPtr bitmap, Gfx::ScalingMode scaling_mode, DrawRepeatedImmutableBitmap::Repeat); void draw_line(Gfx::IntPoint from, Gfx::IntPoint to, Color color, int thickness = 1, Gfx::LineStyle style = Gfx::LineStyle::Solid, Color alternate_color = Color::Transparent); @@ -123,6 +123,7 @@ public: void pop_stacking_context(); void add_rounded_rect_clip(CornerRadii corner_radii, Gfx::IntRect border_rect, CornerClip corner_clip); + void add_mask(RefPtr display_list, Gfx::IntRect rect); void apply_backdrop_filter(Gfx::IntRect const& backdrop_region, BorderRadiiData const& border_radii_data, CSS::ResolvedBackdropFilter const& backdrop_filter); @@ -130,9 +131,9 @@ public: void paint_inner_box_shadow_params(PaintBoxShadowParams params); void paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Gfx::GlyphRun const&, double glyph_run_scale, Color color, Gfx::IntPoint draw_location); - void fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius, RefPtr text_clip = {}); - void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius, RefPtr text_clip = {}); - void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius, RefPtr text_clip = {}); + void fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius); + void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius); + void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius); void draw_triangle_wave(Gfx::IntPoint a_p1, Gfx::IntPoint a_p2, Color color, int amplitude, int thickness);