mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
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.
This commit is contained in:
parent
f19b17e089
commit
95d91a37d2
Notes:
sideshowbarker
2024-07-17 18:38:54 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/95d91a37d2 Pull-request: https://github.com/SerenityOS/serenity/pull/23150
7 changed files with 64 additions and 11 deletions
11
Tests/LibWeb/Ref/outlines.html
Normal file
11
Tests/LibWeb/Ref/outlines.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="match" href="reference/outlines-ref.html" />
|
||||||
|
<style>
|
||||||
|
.outline {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
outline: 5px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="outline">hello from paintable box</div>
|
||||||
|
<p><span class="outline">hello from inline paintable</span></p>
|
12
Tests/LibWeb/Ref/reference/outlines-ref.html
Normal file
12
Tests/LibWeb/Ref/reference/outlines-ref.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="match" href="reference/outlines-ref.html" />
|
||||||
|
<style>
|
||||||
|
.border {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border: 5px solid black;
|
||||||
|
margin: -5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="border">hello from paintable box</div>
|
||||||
|
<p><span class="border">hello from inline paintable</span></p>
|
|
@ -167,11 +167,9 @@ void InlinePaintable::paint(PaintContext& context, PaintPhase phase) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phase == PaintPhase::Outline) {
|
if (phase == PaintPhase::Outline) {
|
||||||
auto outline_width = computed_values().outline_width().to_px(layout_node());
|
auto maybe_outline_data = this->outline_data();
|
||||||
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())
|
||||||
if (maybe_outline_data.has_value()) {
|
|
||||||
paint_border_or_outline(maybe_outline_data.value(), computed_values().outline_offset().to_px(layout_node()));
|
paint_border_or_outline(maybe_outline_data.value(), computed_values().outline_offset().to_px(layout_node()));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phase == PaintPhase::Foreground) {
|
if (phase == PaintPhase::Foreground) {
|
||||||
|
|
|
@ -37,6 +37,12 @@ public:
|
||||||
void set_box_shadow_data(Vector<ShadowData>&& box_shadow_data) { m_box_shadow_data = move(box_shadow_data); }
|
void set_box_shadow_data(Vector<ShadowData>&& box_shadow_data) { m_box_shadow_data = move(box_shadow_data); }
|
||||||
Vector<ShadowData> const& box_shadow_data() const { return m_box_shadow_data; }
|
Vector<ShadowData> const& box_shadow_data() const { return m_box_shadow_data; }
|
||||||
|
|
||||||
|
void set_outline_data(Optional<BordersData> outline_data) { m_outline_data = outline_data; }
|
||||||
|
Optional<BordersData> 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<ScrollFrame> scroll_frame) { m_enclosing_scroll_frame = scroll_frame; }
|
void set_enclosing_scroll_frame(RefPtr<ScrollFrame> scroll_frame) { m_enclosing_scroll_frame = scroll_frame; }
|
||||||
void set_enclosing_clip_frame(RefPtr<ClipFrame> clip_frame) { m_enclosing_clip_frame = clip_frame; }
|
void set_enclosing_clip_frame(RefPtr<ClipFrame> clip_frame) { m_enclosing_clip_frame = clip_frame; }
|
||||||
|
|
||||||
|
@ -55,6 +61,8 @@ private:
|
||||||
RefPtr<ClipFrame const> m_enclosing_clip_frame;
|
RefPtr<ClipFrame const> m_enclosing_clip_frame;
|
||||||
|
|
||||||
Vector<ShadowData> m_box_shadow_data;
|
Vector<ShadowData> m_box_shadow_data;
|
||||||
|
Optional<BordersData> m_outline_data;
|
||||||
|
CSSPixels m_outline_offset { 0 };
|
||||||
Vector<PaintableFragment> m_fragments;
|
Vector<PaintableFragment> m_fragments;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -259,10 +259,9 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phase == PaintPhase::Outline) {
|
if (phase == PaintPhase::Outline) {
|
||||||
auto outline_width = computed_values().outline_width().to_px(layout_node());
|
auto const& outline_data = this->outline_data();
|
||||||
auto borders_data = borders_data_for_outline(layout_node(), computed_values().outline_color(), computed_values().outline_style(), outline_width);
|
if (outline_data.has_value()) {
|
||||||
if (borders_data.has_value()) {
|
auto outline_offset = this->outline_offset();
|
||||||
auto outline_offset = computed_values().outline_offset().to_px(layout_node());
|
|
||||||
auto border_radius_data = normalized_border_radii_data(ShrinkRadiiForBorders::No);
|
auto border_radius_data = normalized_border_radii_data(ShrinkRadiiForBorders::No);
|
||||||
auto borders_rect = absolute_border_box_rect();
|
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)
|
if ((borders_rect.height() / 2) + outline_offset_y < 0)
|
||||||
outline_offset_y = -borders_rect.height() / 2;
|
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);
|
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_width + outline_offset_y, outline_width + outline_offset_x, outline_width + outline_offset_y, outline_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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -195,6 +195,12 @@ public:
|
||||||
void set_transform_origin(CSSPixelPoint transform_origin) { m_transform_origin = transform_origin; }
|
void set_transform_origin(CSSPixelPoint transform_origin) { m_transform_origin = transform_origin; }
|
||||||
CSSPixelPoint const& transform_origin() const { return m_transform_origin; }
|
CSSPixelPoint const& transform_origin() const { return m_transform_origin; }
|
||||||
|
|
||||||
|
void set_outline_data(Optional<BordersData> outline_data) { m_outline_data = outline_data; }
|
||||||
|
Optional<BordersData> 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;
|
CSSPixelRect compute_absolute_padding_rect_with_css_transform_applied() const;
|
||||||
Gfx::AffineTransform compute_combined_css_transform() const;
|
Gfx::AffineTransform compute_combined_css_transform() const;
|
||||||
|
|
||||||
|
@ -243,6 +249,9 @@ 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;
|
||||||
|
|
||||||
|
Optional<BordersData> m_outline_data;
|
||||||
|
CSSPixels m_outline_offset { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class PaintableWithLines : public PaintableBox {
|
class PaintableWithLines : public PaintableBox {
|
||||||
|
|
|
@ -227,6 +227,7 @@ void ViewportPaintable::resolve_paint_only_properties()
|
||||||
// - Text shadows
|
// - Text shadows
|
||||||
// - Transforms
|
// - Transforms
|
||||||
// - Transform origins
|
// - Transform origins
|
||||||
|
// - Outlines
|
||||||
for_each_in_inclusive_subtree([&](Paintable& paintable) {
|
for_each_in_inclusive_subtree([&](Paintable& paintable) {
|
||||||
auto& node = paintable.layout_node();
|
auto& node = paintable.layout_node();
|
||||||
|
|
||||||
|
@ -416,6 +417,21 @@ void ViewportPaintable::resolve_paint_only_properties()
|
||||||
paintable_box.set_transform_origin({ x, y });
|
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<Painting::PaintableBox&>(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<Painting::InlinePaintable&>(paintable);
|
||||||
|
inline_paintable.set_outline_data(outline_data);
|
||||||
|
inline_paintable.set_outline_offset(outline_offset);
|
||||||
|
}
|
||||||
|
|
||||||
return TraversalDecision::Continue;
|
return TraversalDecision::Continue;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue