From d4932196cc99ce1a753f203b5e103b92803e9173 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sat, 10 Feb 2024 17:52:57 +0100 Subject: [PATCH] LibWeb: Account for all clipped border radii in containing block chain With this change, instead of applying only the border-radius clipping from the closest containing block with hidden overflow, we now collect all boxes within the containing block chain and apply the clipping from all of them. --- ...ith-hidden-overflow-and-border-radius.html | 30 +++++++++++++ ...-hidden-overflow-and-border-radius-ref.png | Bin 0 -> 10230 bytes ...hidden-overflow-and-border-radius-ref.html | 10 +++++ .../LibWeb/Painting/BorderRadiiData.h | 14 ++++++ .../Libraries/LibWeb/Painting/ClipFrame.h | 40 ++++++++++++++++++ .../LibWeb/Painting/InlinePaintable.cpp | 2 +- .../LibWeb/Painting/PaintableBox.cpp | 40 +++++++++++------- .../Libraries/LibWeb/Painting/PaintableBox.h | 10 ++--- .../LibWeb/Painting/ViewportPaintable.cpp | 19 +++++---- 9 files changed, 133 insertions(+), 32 deletions(-) create mode 100644 Tests/LibWeb/Ref/nested-boxes-with-hidden-overflow-and-border-radius.html create mode 100644 Tests/LibWeb/Ref/reference/images/nested-boxes-with-hidden-overflow-and-border-radius-ref.png create mode 100644 Tests/LibWeb/Ref/reference/nested-boxes-with-hidden-overflow-and-border-radius-ref.html create mode 100644 Userland/Libraries/LibWeb/Painting/ClipFrame.h diff --git a/Tests/LibWeb/Ref/nested-boxes-with-hidden-overflow-and-border-radius.html b/Tests/LibWeb/Ref/nested-boxes-with-hidden-overflow-and-border-radius.html new file mode 100644 index 0000000000..4201da1ab0 --- /dev/null +++ b/Tests/LibWeb/Ref/nested-boxes-with-hidden-overflow-and-border-radius.html @@ -0,0 +1,30 @@ + + + +
+
+
+
+
diff --git a/Tests/LibWeb/Ref/reference/images/nested-boxes-with-hidden-overflow-and-border-radius-ref.png b/Tests/LibWeb/Ref/reference/images/nested-boxes-with-hidden-overflow-and-border-radius-ref.png new file mode 100644 index 0000000000000000000000000000000000000000..84b09d71a67e0a16e8447c0ad12790c43696421f GIT binary patch literal 10230 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 + * { + margin: 0; + } + + body { + background-color: white; + } + + diff --git a/Userland/Libraries/LibWeb/Painting/BorderRadiiData.h b/Userland/Libraries/LibWeb/Painting/BorderRadiiData.h index 8ebd81d26d..625cd31948 100644 --- a/Userland/Libraries/LibWeb/Painting/BorderRadiiData.h +++ b/Userland/Libraries/LibWeb/Painting/BorderRadiiData.h @@ -31,6 +31,12 @@ struct BorderRadiusData { if (vertical_radius != 0) vertical_radius = max(CSSPixels(0), vertical_radius - vertical); } + + inline void union_max_radii(BorderRadiusData const& other) + { + horizontal_radius = max(horizontal_radius, other.horizontal_radius); + vertical_radius = max(vertical_radius, other.vertical_radius); + } }; using CornerRadius = Gfx::AntiAliasingPainter::CornerRadius; @@ -58,6 +64,14 @@ struct BorderRadiiData { return top_left || top_right || bottom_right || bottom_left; } + inline void union_max_radii(BorderRadiiData const& other) + { + top_left.union_max_radii(other.top_left); + top_right.union_max_radii(other.top_right); + bottom_right.union_max_radii(other.bottom_right); + bottom_left.union_max_radii(other.bottom_left); + } + inline void shrink(CSSPixels top, CSSPixels right, CSSPixels bottom, CSSPixels left) { top_left.shrink(left, top); diff --git a/Userland/Libraries/LibWeb/Painting/ClipFrame.h b/Userland/Libraries/LibWeb/Painting/ClipFrame.h new file mode 100644 index 0000000000..43e34b70b1 --- /dev/null +++ b/Userland/Libraries/LibWeb/Painting/ClipFrame.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::Painting { + +struct BorderRadiiClip { + CSSPixelRect rect; + BorderRadiiData radii; +}; + +struct ClipFrame : public RefCounted { + Vector const& border_radii_clips() const { return m_border_radii_clips; } + void add_border_radii_clip(BorderRadiiClip border_radii_clip) + { + for (auto& existing_clip : m_border_radii_clips) { + if (border_radii_clip.rect == existing_clip.rect) { + existing_clip.radii.union_max_radii(border_radii_clip.radii); + return; + } + } + m_border_radii_clips.append(border_radii_clip); + } + + CSSPixelRect rect() const { return m_rect; } + void set_rect(CSSPixelRect rect) { m_rect = rect; } + +private: + CSSPixelRect m_rect; + Vector m_border_radii_clips; +}; + +} diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp index 0de7ec5e91..7a965240be 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp @@ -44,7 +44,7 @@ Optional InlinePaintable::enclosing_scroll_frame_offset() const Optional InlinePaintable::clip_rect() const { if (m_enclosing_clip_frame) - return m_enclosing_clip_frame->rect; + return m_enclosing_clip_frame->rect(); return {}; } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index cfc279cc1e..26ba547947 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -214,14 +214,14 @@ Optional PaintableBox::enclosing_scroll_frame_offset() const Optional PaintableBox::clip_rect() const { if (m_enclosing_clip_frame) - return m_enclosing_clip_frame->rect; + return m_enclosing_clip_frame->rect(); return {}; } -Optional PaintableBox::corner_clip_radii() const +Span PaintableBox::border_radii_clips() const { if (m_enclosing_clip_frame) - return m_enclosing_clip_frame->corner_clip_radii; + return m_enclosing_clip_frame->border_radii_clips(); return {}; } @@ -444,12 +444,17 @@ void PaintableBox::apply_clip_overflow_rect(PaintContext& context, PaintPhase ph m_clipping_overflow = true; context.recording_painter().save(); context.recording_painter().add_clip_rect(context.enclosing_device_rect(overflow_clip_rect).to_type()); - if (corner_clip_radii().has_value()) { - VERIFY(!m_corner_clipper_id.has_value()); - m_corner_clipper_id = context.allocate_corner_clipper_id(); - auto corner_radii = corner_clip_radii()->as_corners(context); - if (corner_radii.has_any_radius()) - context.recording_painter().sample_under_corners(*m_corner_clipper_id, corner_clip_radii()->as_corners(context), context.rounded_device_rect(overflow_clip_rect).to_type(), CornerClip::Outside); + auto const& border_radii_clips = this->border_radii_clips(); + m_corner_clipper_ids.resize(border_radii_clips.size()); + for (size_t corner_clip_index = 0; corner_clip_index < border_radii_clips.size(); ++corner_clip_index) { + auto const& corner_clip = border_radii_clips[corner_clip_index]; + auto corners = corner_clip.radii.as_corners(context); + if (!corners.has_any_radius()) + continue; + auto corner_clipper_id = context.allocate_corner_clipper_id(); + m_corner_clipper_ids[corner_clip_index] = corner_clipper_id; + auto rect = corner_clip.rect.translated(-combined_transform.translation().to_type()); + context.recording_painter().sample_under_corners(corner_clipper_id, corner_clip.radii.as_corners(context), context.rounded_device_rect(rect).to_type(), CornerClip::Outside); } } } @@ -461,12 +466,17 @@ void PaintableBox::clear_clip_overflow_rect(PaintContext& context, PaintPhase ph if (m_clipping_overflow) { m_clipping_overflow = false; - if (corner_clip_radii().has_value()) { - VERIFY(m_corner_clipper_id.has_value()); - auto corner_radii = corner_clip_radii()->as_corners(context); - if (corner_radii.has_any_radius()) - context.recording_painter().blit_corner_clipping(*m_corner_clipper_id, context.rounded_device_rect(*clip_rect()).to_type()); - m_corner_clipper_id = {}; + auto combined_transform = compute_combined_css_transform(); + auto const& border_radii_clips = this->border_radii_clips(); + for (size_t corner_clip_index = 0; corner_clip_index < border_radii_clips.size(); ++corner_clip_index) { + auto const& corner_clip = border_radii_clips[corner_clip_index]; + auto corners = corner_clip.radii.as_corners(context); + if (!corners.has_any_radius()) + continue; + auto corner_clipper_id = m_corner_clipper_ids[corner_clip_index]; + m_corner_clipper_ids[corner_clip_index] = corner_clipper_id; + auto rect = corner_clip.rect.translated(-combined_transform.translation().to_type()); + context.recording_painter().blit_corner_clipping(corner_clipper_id, context.rounded_device_rect(rect).to_type()); } context.recording_painter().restore(); } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index 4ce58e87a2..bd7458e689 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -19,11 +20,6 @@ struct ScrollFrame : public RefCounted { CSSPixelPoint offset; }; -struct ClipFrame : public RefCounted { - CSSPixelRect rect; - Optional corner_clip_radii; -}; - class PaintableBox : public Paintable { JS_CELL(PaintableBox, Paintable); @@ -210,7 +206,7 @@ public: Optional scroll_frame_id() const; Optional enclosing_scroll_frame_offset() const; Optional clip_rect() const; - Optional corner_clip_radii() const; + Span border_radii_clips() const; protected: explicit PaintableBox(Layout::Box const&); @@ -235,7 +231,7 @@ private: Optional mutable m_absolute_paint_rect; mutable bool m_clipping_overflow { false }; - mutable Optional m_corner_clipper_id; + mutable Vector m_corner_clipper_ids; RefPtr m_enclosing_scroll_frame; RefPtr m_enclosing_clip_frame; diff --git a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp index 5ee40397ca..c157cd8d61 100644 --- a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp @@ -149,21 +149,22 @@ void ViewportPaintable::refresh_clip_state() auto const& block_paintable_box = *block->paintable_box(); auto block_overflow_x = block_paintable_box.computed_values().overflow_x(); auto block_overflow_y = block_paintable_box.computed_values().overflow_y(); - if (block_overflow_x != CSS::Overflow::Visible && block_overflow_y != CSS::Overflow::Visible) - overflow_clip_rect.intersect(block_paintable_box.compute_absolute_padding_rect_with_css_transform_applied()); + if (block_overflow_x != CSS::Overflow::Visible && block_overflow_y != CSS::Overflow::Visible) { + auto rect = block_paintable_box.compute_absolute_padding_rect_with_css_transform_applied(); + overflow_clip_rect.intersect(rect); + auto border_radii_data = block_paintable_box.normalized_border_radii_data(ShrinkRadiiForBorders::Yes); + if (border_radii_data.has_any_radius()) { + BorderRadiiClip border_radii_clip { .rect = rect, .radii = border_radii_data }; + clip_frame.add_border_radii_clip(border_radii_clip); + } + } if (auto css_clip_property_rect = block->paintable_box()->get_clip_rect(); css_clip_property_rect.has_value()) overflow_clip_rect.intersect(css_clip_property_rect.value()); } clip_rect = overflow_clip_rect; } - auto border_radii_data = paintable_box.normalized_border_radii_data(ShrinkRadiiForBorders::Yes); - if (border_radii_data.has_any_radius()) { - // FIXME: Border radii of all boxes in containing block chain should be taken into account. - clip_frame.corner_clip_radii = border_radii_data; - } - - clip_frame.rect = *clip_rect; + clip_frame.set_rect(*clip_rect); } }