From 95d91a37d286b03ea6bfcb00e3442895032c97f4 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sun, 11 Feb 2024 01:56:39 +0100 Subject: [PATCH] LibWeb: Resolve outline CSS property before paint commands recording Refactor to resolve paint-only properties before painting, aiming to stop using layout nodes during recording of painting commands. Also adds a test, as we have not had any for outlines yet. --- Tests/LibWeb/Ref/outlines.html | 11 +++++++++++ Tests/LibWeb/Ref/reference/outlines-ref.html | 12 ++++++++++++ .../LibWeb/Painting/InlinePaintable.cpp | 6 ++---- .../Libraries/LibWeb/Painting/InlinePaintable.h | 8 ++++++++ .../Libraries/LibWeb/Painting/PaintableBox.cpp | 13 ++++++------- .../Libraries/LibWeb/Painting/PaintableBox.h | 9 +++++++++ .../LibWeb/Painting/ViewportPaintable.cpp | 16 ++++++++++++++++ 7 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 Tests/LibWeb/Ref/outlines.html create mode 100644 Tests/LibWeb/Ref/reference/outlines-ref.html diff --git a/Tests/LibWeb/Ref/outlines.html b/Tests/LibWeb/Ref/outlines.html new file mode 100644 index 00000000000..2a6488dfb62 --- /dev/null +++ b/Tests/LibWeb/Ref/outlines.html @@ -0,0 +1,11 @@ + + + +
hello from paintable box
+

hello from inline paintable

diff --git a/Tests/LibWeb/Ref/reference/outlines-ref.html b/Tests/LibWeb/Ref/reference/outlines-ref.html new file mode 100644 index 00000000000..df452dcde71 --- /dev/null +++ b/Tests/LibWeb/Ref/reference/outlines-ref.html @@ -0,0 +1,12 @@ + + + +
hello from paintable box
+

hello from inline paintable

diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp index 7a965240beb..0bafbda31f5 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp @@ -167,11 +167,9 @@ void InlinePaintable::paint(PaintContext& context, PaintPhase phase) const } if (phase == PaintPhase::Outline) { - auto outline_width = computed_values().outline_width().to_px(layout_node()); - auto maybe_outline_data = borders_data_for_outline(layout_node(), computed_values().outline_color(), computed_values().outline_style(), outline_width); - if (maybe_outline_data.has_value()) { + auto maybe_outline_data = this->outline_data(); + if (maybe_outline_data.has_value()) paint_border_or_outline(maybe_outline_data.value(), computed_values().outline_offset().to_px(layout_node())); - } } if (phase == PaintPhase::Foreground) { diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.h b/Userland/Libraries/LibWeb/Painting/InlinePaintable.h index ac65a752f76..84406e516b7 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.h +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.h @@ -37,6 +37,12 @@ public: void set_box_shadow_data(Vector&& box_shadow_data) { m_box_shadow_data = move(box_shadow_data); } Vector const& box_shadow_data() const { return m_box_shadow_data; } + void set_outline_data(Optional outline_data) { m_outline_data = outline_data; } + Optional const& outline_data() const { return m_outline_data; } + + void set_outline_offset(CSSPixels outline_offset) { m_outline_offset = outline_offset; } + CSSPixels outline_offset() const { return m_outline_offset; } + void set_enclosing_scroll_frame(RefPtr scroll_frame) { m_enclosing_scroll_frame = scroll_frame; } void set_enclosing_clip_frame(RefPtr clip_frame) { m_enclosing_clip_frame = clip_frame; } @@ -55,6 +61,8 @@ private: RefPtr m_enclosing_clip_frame; Vector m_box_shadow_data; + Optional m_outline_data; + CSSPixels m_outline_offset { 0 }; Vector m_fragments; }; diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 26ba547947a..43d72a94f52 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -259,10 +259,9 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const } if (phase == PaintPhase::Outline) { - auto outline_width = computed_values().outline_width().to_px(layout_node()); - auto borders_data = borders_data_for_outline(layout_node(), computed_values().outline_color(), computed_values().outline_style(), outline_width); - if (borders_data.has_value()) { - auto outline_offset = computed_values().outline_offset().to_px(layout_node()); + auto const& outline_data = this->outline_data(); + if (outline_data.has_value()) { + auto outline_offset = this->outline_offset(); auto border_radius_data = normalized_border_radii_data(ShrinkRadiiForBorders::No); auto borders_rect = absolute_border_box_rect(); @@ -279,10 +278,10 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const if ((borders_rect.height() / 2) + outline_offset_y < 0) outline_offset_y = -borders_rect.height() / 2; - border_radius_data.inflate(outline_width + outline_offset_y, outline_width + outline_offset_x, outline_width + outline_offset_y, outline_width + outline_offset_x); - borders_rect.inflate(outline_width + outline_offset_y, outline_width + outline_offset_x, outline_width + outline_offset_y, outline_width + outline_offset_x); + border_radius_data.inflate(outline_data->top.width + outline_offset_y, outline_data->right.width + outline_offset_x, outline_data->bottom.width + outline_offset_y, outline_data->left.width + outline_offset_x); + borders_rect.inflate(outline_data->top.width + outline_offset_y, outline_data->right.width + outline_offset_x, outline_data->bottom.width + outline_offset_y, outline_data->left.width + outline_offset_x); - context.recording_painter().paint_borders(context.rounded_device_rect(borders_rect), border_radius_data.as_corners(context), borders_data->to_device_pixels(context)); + context.recording_painter().paint_borders(context.rounded_device_rect(borders_rect), border_radius_data.as_corners(context), outline_data->to_device_pixels(context)); } } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index bd7458e6896..39ee2811f56 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -195,6 +195,12 @@ public: void set_transform_origin(CSSPixelPoint transform_origin) { m_transform_origin = transform_origin; } CSSPixelPoint const& transform_origin() const { return m_transform_origin; } + void set_outline_data(Optional outline_data) { m_outline_data = outline_data; } + Optional const& outline_data() const { return m_outline_data; } + + void set_outline_offset(CSSPixels outline_offset) { m_outline_offset = outline_offset; } + CSSPixels outline_offset() const { return m_outline_offset; } + CSSPixelRect compute_absolute_padding_rect_with_css_transform_applied() const; Gfx::AffineTransform compute_combined_css_transform() const; @@ -243,6 +249,9 @@ private: Vector m_box_shadow_data; Gfx::FloatMatrix4x4 m_transform { Gfx::FloatMatrix4x4::identity() }; CSSPixelPoint m_transform_origin; + + Optional m_outline_data; + CSSPixels m_outline_offset { 0 }; }; class PaintableWithLines : public PaintableBox { diff --git a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp index c157cd8d617..b0e3056bc9a 100644 --- a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp @@ -227,6 +227,7 @@ void ViewportPaintable::resolve_paint_only_properties() // - Text shadows // - Transforms // - Transform origins + // - Outlines for_each_in_inclusive_subtree([&](Paintable& paintable) { auto& node = paintable.layout_node(); @@ -416,6 +417,21 @@ void ViewportPaintable::resolve_paint_only_properties() paintable_box.set_transform_origin({ x, y }); } + // Outlines + auto const& computed_values = node.computed_values(); + auto outline_width = computed_values.outline_width().to_px(node); + auto outline_data = borders_data_for_outline(node, computed_values.outline_color(), computed_values.outline_style(), outline_width); + auto outline_offset = computed_values.outline_offset().to_px(node); + if (is_paintable_box) { + auto& paintable_box = static_cast(paintable); + paintable_box.set_outline_data(outline_data); + paintable_box.set_outline_offset(outline_offset); + } else if (is_inline_paintable) { + auto& inline_paintable = static_cast(paintable); + inline_paintable.set_outline_data(outline_data); + inline_paintable.set_outline_offset(outline_offset); + } + return TraversalDecision::Continue; }); }