From 5c11a541d3aa02dc2338005b1ee2a4c47e4d9d2c Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sat, 2 Aug 2025 20:04:12 +0200 Subject: [PATCH] LibWeb: Merge StrokePathUsingPaintStyle and StrokePathUsingColor Use `Variant` in new `StrokePath` instead of duplicating two almost identical display list items. --- Libraries/LibWeb/Forward.h | 2 ++ Libraries/LibWeb/Painting/DisplayList.cpp | 3 +- Libraries/LibWeb/Painting/DisplayList.h | 3 +- .../LibWeb/Painting/DisplayListCommand.cpp | 9 ++--- .../LibWeb/Painting/DisplayListCommand.h | 31 +++------------- .../LibWeb/Painting/DisplayListPlayerSkia.cpp | 32 ++++++----------- .../LibWeb/Painting/DisplayListPlayerSkia.h | 3 +- .../LibWeb/Painting/DisplayListRecorder.cpp | 36 +++---------------- .../LibWeb/Painting/DisplayListRecorder.h | 21 +++-------- Libraries/LibWeb/Painting/MediaPaintable.cpp | 3 +- Libraries/LibWeb/Painting/PaintableBox.cpp | 2 +- .../LibWeb/Painting/SVGPathPaintable.cpp | 6 ++-- 12 files changed, 37 insertions(+), 114 deletions(-) diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 989c6c6e58c..f5b52f7aec2 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -42,6 +43,7 @@ class DisplayListRecorder; class SVGGradientPaintStyle; class ScrollStateSnapshot; using PaintStyle = RefPtr; +using PaintStyleOrColor = Variant; using ScrollStateSnapshotByDisplayList = HashMap, ScrollStateSnapshot>; } diff --git a/Libraries/LibWeb/Painting/DisplayList.cpp b/Libraries/LibWeb/Painting/DisplayList.cpp index 0cbbcff3505..c4d4e921a92 100644 --- a/Libraries/LibWeb/Painting/DisplayList.cpp +++ b/Libraries/LibWeb/Painting/DisplayList.cpp @@ -216,8 +216,7 @@ void DisplayListPlayer::execute_impl(DisplayList& display_list, ScrollStateSnaps else HANDLE_COMMAND(FillRectWithRoundedCorners, fill_rect_with_rounded_corners) else HANDLE_COMMAND(FillPathUsingColor, fill_path_using_color) else HANDLE_COMMAND(FillPathUsingPaintStyle, fill_path_using_paint_style) - else HANDLE_COMMAND(StrokePathUsingColor, stroke_path_using_color) - else HANDLE_COMMAND(StrokePathUsingPaintStyle, stroke_path_using_paint_style) + else HANDLE_COMMAND(StrokePath, stroke_path) else HANDLE_COMMAND(DrawEllipse, draw_ellipse) else HANDLE_COMMAND(FillEllipse, fill_ellipse) else HANDLE_COMMAND(DrawLine, draw_line) diff --git a/Libraries/LibWeb/Painting/DisplayList.h b/Libraries/LibWeb/Painting/DisplayList.h index c4accafcf97..614e0522a4c 100644 --- a/Libraries/LibWeb/Painting/DisplayList.h +++ b/Libraries/LibWeb/Painting/DisplayList.h @@ -57,8 +57,7 @@ private: virtual void fill_rect_with_rounded_corners(FillRectWithRoundedCorners const&) = 0; virtual void fill_path_using_color(FillPathUsingColor const&) = 0; virtual void fill_path_using_paint_style(FillPathUsingPaintStyle const&) = 0; - virtual void stroke_path_using_color(StrokePathUsingColor const&) = 0; - virtual void stroke_path_using_paint_style(StrokePathUsingPaintStyle const&) = 0; + virtual void stroke_path(StrokePath const&) = 0; virtual void draw_ellipse(DrawEllipse const&) = 0; virtual void fill_ellipse(FillEllipse const&) = 0; virtual void draw_line(DrawLine const&) = 0; diff --git a/Libraries/LibWeb/Painting/DisplayListCommand.cpp b/Libraries/LibWeb/Painting/DisplayListCommand.cpp index ddf229b3328..fca042c9293 100644 --- a/Libraries/LibWeb/Painting/DisplayListCommand.cpp +++ b/Libraries/LibWeb/Painting/DisplayListCommand.cpp @@ -147,14 +147,9 @@ void FillPathUsingPaintStyle::dump(StringBuilder& builder) const builder.appendff("FillPathUsingPaintStyle"); } -void StrokePathUsingColor::dump(StringBuilder& builder) const +void StrokePath::dump(StringBuilder& builder) const { - builder.appendff("StrokePathUsingColor"); -} - -void StrokePathUsingPaintStyle::dump(StringBuilder& builder) const -{ - builder.appendff("StrokePathUsingPaintStyle"); + builder.appendff("StrokePath"); } void DrawEllipse::dump(StringBuilder& builder) const diff --git a/Libraries/LibWeb/Painting/DisplayListCommand.h b/Libraries/LibWeb/Painting/DisplayListCommand.h index edd90cd0d0a..1689306bed7 100644 --- a/Libraries/LibWeb/Painting/DisplayListCommand.h +++ b/Libraries/LibWeb/Painting/DisplayListCommand.h @@ -246,7 +246,7 @@ struct FillPathUsingPaintStyle { void dump(StringBuilder&) const; }; -struct StrokePathUsingColor { +struct StrokePath { Gfx::Path::CapStyle cap_style; Gfx::Path::JoinStyle join_style; float miter_limit; @@ -254,7 +254,8 @@ struct StrokePathUsingColor { float dash_offset; Gfx::IntRect path_bounding_rect; Gfx::Path path; - Color color; + float opacity; + PaintStyleOrColor paint_style_or_color; float thickness; Gfx::FloatPoint aa_translation; @@ -268,29 +269,6 @@ struct StrokePathUsingColor { void dump(StringBuilder&) const; }; -struct StrokePathUsingPaintStyle { - Gfx::Path::CapStyle cap_style; - Gfx::Path::JoinStyle join_style; - float miter_limit; - Vector dash_array; - float dash_offset; - Gfx::IntRect path_bounding_rect; - Gfx::Path path; - PaintStyle paint_style; - float thickness; - float opacity = 1.0f; - Gfx::FloatPoint aa_translation; - - [[nodiscard]] Gfx::IntRect bounding_rect() const { return path_bounding_rect; } - - void translate_by(Gfx::IntPoint const& offset) - { - path_bounding_rect.translate_by(offset); - aa_translation.translate_by(offset.to_type()); - } - void dump(StringBuilder&) const; -}; - struct DrawEllipse { Gfx::IntRect rect; Color color; @@ -508,8 +486,7 @@ using DisplayListCommand = Variant< FillRectWithRoundedCorners, FillPathUsingColor, FillPathUsingPaintStyle, - StrokePathUsingColor, - StrokePathUsingPaintStyle, + StrokePath, DrawEllipse, FillEllipse, DrawLine, diff --git a/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp b/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp index 2109a290b97..c91d9a8e4d4 100644 --- a/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp +++ b/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp @@ -660,30 +660,20 @@ void DisplayListPlayerSkia::fill_path_using_paint_style(FillPathUsingPaintStyle surface().canvas().drawPath(path, paint); } -void DisplayListPlayerSkia::stroke_path_using_color(StrokePathUsingColor const& command) +void DisplayListPlayerSkia::stroke_path(StrokePath const& command) { - auto& canvas = surface().canvas(); + auto path = to_skia_path(command.path); + path.offset(command.aa_translation.x(), command.aa_translation.y()); SkPaint paint; + if (command.paint_style_or_color.has()) { + auto const& paint_style = command.paint_style_or_color.get(); + paint = paint_style_to_skia_paint(*paint_style, command.bounding_rect().to_type()); + paint.setAlphaf(command.opacity); + } else { + auto const& color = command.paint_style_or_color.get(); + paint.setColor(to_skia_color(color)); + } paint.setAntiAlias(true); - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(command.thickness); - paint.setStrokeCap(to_skia_cap(command.cap_style)); - paint.setStrokeJoin(to_skia_join(command.join_style)); - paint.setColor(to_skia_color(command.color)); - paint.setStrokeMiter(command.miter_limit); - paint.setPathEffect(SkDashPathEffect::Make(command.dash_array.data(), command.dash_array.size(), command.dash_offset)); - auto path = to_skia_path(command.path); - path.offset(command.aa_translation.x(), command.aa_translation.y()); - canvas.drawPath(path, paint); -} - -void DisplayListPlayerSkia::stroke_path_using_paint_style(StrokePathUsingPaintStyle const& command) -{ - auto path = to_skia_path(command.path); - path.offset(command.aa_translation.x(), command.aa_translation.y()); - auto paint = paint_style_to_skia_paint(*command.paint_style, command.bounding_rect().to_type()); - paint.setAntiAlias(true); - paint.setAlphaf(command.opacity); paint.setStyle(SkPaint::Style::kStroke_Style); paint.setStrokeWidth(command.thickness); paint.setStrokeCap(to_skia_cap(command.cap_style)); diff --git a/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h b/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h index 900ca421044..fc6a26b2429 100644 --- a/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h +++ b/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h @@ -42,8 +42,7 @@ private: void fill_rect_with_rounded_corners(FillRectWithRoundedCorners const&) override; void fill_path_using_color(FillPathUsingColor const&) override; void fill_path_using_paint_style(FillPathUsingPaintStyle const&) override; - void stroke_path_using_color(StrokePathUsingColor const&) override; - void stroke_path_using_paint_style(StrokePathUsingPaintStyle const&) override; + void stroke_path(StrokePath const&) override; void draw_ellipse(DrawEllipse const&) override; void fill_ellipse(FillEllipse const&) override; void draw_line(DrawLine const&) override; diff --git a/Libraries/LibWeb/Painting/DisplayListRecorder.cpp b/Libraries/LibWeb/Painting/DisplayListRecorder.cpp index a6af08a33ea..7c36c86e3a0 100644 --- a/Libraries/LibWeb/Painting/DisplayListRecorder.cpp +++ b/Libraries/LibWeb/Painting/DisplayListRecorder.cpp @@ -99,12 +99,12 @@ void DisplayListRecorder::fill_path(FillPathUsingPaintStyleParams params) }); } -void DisplayListRecorder::stroke_path(StrokePathUsingColorParams params) +void DisplayListRecorder::stroke_path(StrokePathParams params) { // Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing. if (!params.thickness) return; - if (params.color.alpha() == 0) + if (params.paint_style_or_color.has() && params.paint_style_or_color.get().alpha() == 0) return; auto aa_translation = params.translation.value_or(Gfx::FloatPoint {}); auto path_bounding_rect = params.path.bounding_box().translated(aa_translation); @@ -113,7 +113,7 @@ void DisplayListRecorder::stroke_path(StrokePathUsingColorParams params) auto path_bounding_int_rect = enclosing_int_rect(path_bounding_rect); if (path_bounding_int_rect.is_empty()) return; - APPEND(StrokePathUsingColor { + APPEND(StrokePath { .cap_style = params.cap_style, .join_style = params.join_style, .miter_limit = params.miter_limit, @@ -121,35 +121,9 @@ void DisplayListRecorder::stroke_path(StrokePathUsingColorParams params) .dash_offset = params.dash_offset, .path_bounding_rect = path_bounding_int_rect, .path = move(params.path), - .color = params.color, - .thickness = params.thickness, - .aa_translation = aa_translation, - }); -} - -void DisplayListRecorder::stroke_path(StrokePathUsingPaintStyleParams params) -{ - // Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing. - if (!params.thickness) - return; - auto aa_translation = params.translation.value_or(Gfx::FloatPoint {}); - auto path_bounding_rect = params.path.bounding_box().translated(aa_translation); - // Increase path bounding box by `thickness` to account for stroke. - path_bounding_rect.inflate(params.thickness, params.thickness); - auto path_bounding_int_rect = enclosing_int_rect(path_bounding_rect); - if (path_bounding_int_rect.is_empty()) - return; - APPEND(StrokePathUsingPaintStyle { - .cap_style = params.cap_style, - .join_style = params.join_style, - .miter_limit = params.miter_limit, - .dash_array = move(params.dash_array), - .dash_offset = params.dash_offset, - .path_bounding_rect = path_bounding_int_rect, - .path = move(params.path), - .paint_style = params.paint_style, - .thickness = params.thickness, .opacity = params.opacity, + .paint_style_or_color = params.paint_style_or_color, + .thickness = params.thickness, .aa_translation = aa_translation, }); } diff --git a/Libraries/LibWeb/Painting/DisplayListRecorder.h b/Libraries/LibWeb/Painting/DisplayListRecorder.h index de99b581230..d401972c943 100644 --- a/Libraries/LibWeb/Painting/DisplayListRecorder.h +++ b/Libraries/LibWeb/Painting/DisplayListRecorder.h @@ -56,32 +56,19 @@ public: }; void fill_path(FillPathUsingPaintStyleParams params); - struct StrokePathUsingColorParams { + struct StrokePathParams { Gfx::Path::CapStyle cap_style; Gfx::Path::JoinStyle join_style; float miter_limit; Vector dash_array; float dash_offset; Gfx::Path path; - Gfx::Color color; + float opacity = 1.0f; + PaintStyleOrColor paint_style_or_color; float thickness; Optional translation = {}; }; - void stroke_path(StrokePathUsingColorParams params); - - struct StrokePathUsingPaintStyleParams { - Gfx::Path::CapStyle cap_style; - Gfx::Path::JoinStyle join_style; - float miter_limit; - Vector dash_array; - float dash_offset; - Gfx::Path path; - PaintStyle paint_style; - float thickness; - float opacity; - Optional translation = {}; - }; - void stroke_path(StrokePathUsingPaintStyleParams params); + void stroke_path(StrokePathParams); void draw_ellipse(Gfx::IntRect const& a_rect, Color color, int thickness); diff --git a/Libraries/LibWeb/Painting/MediaPaintable.cpp b/Libraries/LibWeb/Painting/MediaPaintable.cpp index 4d171e4cc32..8ed489b20d8 100644 --- a/Libraries/LibWeb/Painting/MediaPaintable.cpp +++ b/Libraries/LibWeb/Painting/MediaPaintable.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace Web::Painting { @@ -242,7 +243,7 @@ void MediaPaintable::paint_control_bar_speaker(DisplayListRecordingContext& cont .dash_array = {}, .dash_offset = 0, .path = path, - .color = speaker_button_color, + .paint_style_or_color = speaker_button_color, .thickness = 1, }); diff --git a/Libraries/LibWeb/Painting/PaintableBox.cpp b/Libraries/LibWeb/Painting/PaintableBox.cpp index c6721ccbd49..82d28606485 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -904,7 +904,7 @@ void paint_text_decoration(DisplayListRecordingContext& context, TextPaintable c .dash_array = {}, .dash_offset = 0, .path = build_triangle_wave_path(line_start_point.to_type(), line_end_point.to_type(), amplitude), - .color = line_color, + .paint_style_or_color = line_color, .thickness = static_cast(device_line_thickness.value()), }); break; diff --git a/Libraries/LibWeb/Painting/SVGPathPaintable.cpp b/Libraries/LibWeb/Painting/SVGPathPaintable.cpp index 8ac3448fe7b..ebd71941065 100644 --- a/Libraries/LibWeb/Painting/SVGPathPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGPathPaintable.cpp @@ -176,9 +176,9 @@ void SVGPathPaintable::paint(DisplayListRecordingContext& context, PaintPhase ph .dash_array = stroke_dasharray, .dash_offset = stroke_dashoffset, .path = path, - .paint_style = *paint_style, - .thickness = stroke_thickness, .opacity = stroke_opacity, + .paint_style_or_color = *paint_style, + .thickness = stroke_thickness, .translation = offset, }); } else if (auto stroke_color = graphics_element.stroke_color(); stroke_color.has_value()) { @@ -189,7 +189,7 @@ void SVGPathPaintable::paint(DisplayListRecordingContext& context, PaintPhase ph .dash_array = stroke_dasharray, .dash_offset = stroke_dashoffset, .path = path, - .color = stroke_color->with_opacity(stroke_opacity), + .paint_style_or_color = stroke_color->with_opacity(stroke_opacity), .thickness = stroke_thickness, .translation = offset, });