diff --git a/Tests/LibWeb/Ref/outlines.html b/Tests/LibWeb/Ref/outlines.html
new file mode 100644
index 0000000000..2a6488dfb6
--- /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 0000000000..df452dcde7
--- /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 7a965240be..0bafbda31f 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 ac65a752f7..84406e516b 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 26ba547947..43d72a94f5 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 bd7458e689..39ee2811f5 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 c157cd8d61..b0e3056bc9 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;
});
}