From cfc6439c12f36fa7dc1bf05f169c8bdffed04f85 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Mon, 18 Aug 2025 16:21:09 +0100 Subject: [PATCH] LibWeb: Use `shape-rendering` to control anti aliasing for SVG paths Anti-aliasing is disabled if `shape-rendering` is set to `optimizeSpeed` or `crispEdges`. --- Libraries/LibWeb/Forward.h | 1 + Libraries/LibWeb/Painting/DisplayListCommand.h | 3 +++ .../LibWeb/Painting/DisplayListPlayerSkia.cpp | 4 ++-- .../LibWeb/Painting/DisplayListRecorder.cpp | 4 ++-- Libraries/LibWeb/Painting/DisplayListRecorder.h | 3 +++ Libraries/LibWeb/Painting/PaintableBox.h | 1 + Libraries/LibWeb/Painting/SVGPaintable.cpp | 8 ++++++++ Libraries/LibWeb/Painting/SVGPaintable.h | 2 ++ Libraries/LibWeb/Painting/SVGPathPaintable.cpp | 5 +++++ Libraries/LibWeb/Painting/ShouldAntiAlias.h | 16 ++++++++++++++++ 10 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 Libraries/LibWeb/Painting/ShouldAntiAlias.h diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 68905e8ca45..165e67c4e34 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -896,6 +896,7 @@ class VideoPaintable; class ViewportPaintable; enum class PaintPhase; +enum class ShouldAntiAlias : bool; struct BorderRadiiData; struct BorderRadiusData; diff --git a/Libraries/LibWeb/Painting/DisplayListCommand.h b/Libraries/LibWeb/Painting/DisplayListCommand.h index 8ae478cf8ad..6c849644f0c 100644 --- a/Libraries/LibWeb/Painting/DisplayListCommand.h +++ b/Libraries/LibWeb/Painting/DisplayListCommand.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace Web::Painting { @@ -217,6 +218,7 @@ struct FillPath { float opacity { 1.0f }; PaintStyleOrColor paint_style_or_color; Gfx::WindingRule winding_rule; + ShouldAntiAlias should_anti_alias { ShouldAntiAlias::Yes }; [[nodiscard]] Gfx::IntRect bounding_rect() const { return path_bounding_rect; } @@ -239,6 +241,7 @@ struct StrokePath { float opacity; PaintStyleOrColor paint_style_or_color; float thickness; + ShouldAntiAlias should_anti_alias { ShouldAntiAlias::Yes }; [[nodiscard]] Gfx::IntRect bounding_rect() const { return path_bounding_rect; } diff --git a/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp b/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp index 1458ecc25b4..f9779ddb757 100644 --- a/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp +++ b/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp @@ -654,7 +654,7 @@ void DisplayListPlayerSkia::fill_path(FillPath const& command) auto const& color = command.paint_style_or_color.get(); paint.setColor(to_skia_color(color)); } - paint.setAntiAlias(true); + paint.setAntiAlias(command.should_anti_alias == ShouldAntiAlias::Yes); surface().canvas().drawPath(path, paint); } @@ -670,7 +670,7 @@ void DisplayListPlayerSkia::stroke_path(StrokePath const& command) auto const& color = command.paint_style_or_color.get(); paint.setColor(to_skia_color(color)); } - paint.setAntiAlias(true); + paint.setAntiAlias(command.should_anti_alias == ShouldAntiAlias::Yes); paint.setStyle(SkPaint::Style::kStroke_Style); paint.setStrokeWidth(command.thickness); paint.setStrokeCap(to_skia_cap(command.cap_style)); diff --git a/Libraries/LibWeb/Painting/DisplayListRecorder.cpp b/Libraries/LibWeb/Painting/DisplayListRecorder.cpp index 192be791e23..b83070cba84 100644 --- a/Libraries/LibWeb/Painting/DisplayListRecorder.cpp +++ b/Libraries/LibWeb/Painting/DisplayListRecorder.cpp @@ -78,7 +78,7 @@ void DisplayListRecorder::fill_path(FillPathParams params) .opacity = params.opacity, .paint_style_or_color = params.paint_style_or_color, .winding_rule = params.winding_rule, - }); + .should_anti_alias = params.should_anti_alias }); } void DisplayListRecorder::stroke_path(StrokePathParams params) @@ -105,7 +105,7 @@ void DisplayListRecorder::stroke_path(StrokePathParams params) .opacity = params.opacity, .paint_style_or_color = params.paint_style_or_color, .thickness = params.thickness, - }); + .should_anti_alias = params.should_anti_alias }); } void DisplayListRecorder::draw_ellipse(Gfx::IntRect const& a_rect, Color color, int thickness) diff --git a/Libraries/LibWeb/Painting/DisplayListRecorder.h b/Libraries/LibWeb/Painting/DisplayListRecorder.h index 9937fec58c9..3a192efc799 100644 --- a/Libraries/LibWeb/Painting/DisplayListRecorder.h +++ b/Libraries/LibWeb/Painting/DisplayListRecorder.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace Web::Painting { @@ -45,6 +46,7 @@ public: float opacity = 1.0f; PaintStyleOrColor paint_style_or_color; Gfx::WindingRule winding_rule = Gfx::WindingRule::EvenOdd; + ShouldAntiAlias should_anti_alias { ShouldAntiAlias::Yes }; }; void fill_path(FillPathParams params); @@ -58,6 +60,7 @@ public: float opacity = 1.0f; PaintStyleOrColor paint_style_or_color; float thickness; + ShouldAntiAlias should_anti_alias { ShouldAntiAlias::Yes }; }; void stroke_path(StrokePathParams); diff --git a/Libraries/LibWeb/Painting/PaintableBox.h b/Libraries/LibWeb/Painting/PaintableBox.h index 8fe69915f2a..12574483247 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Libraries/LibWeb/Painting/PaintableBox.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace Web::Painting { diff --git a/Libraries/LibWeb/Painting/SVGPaintable.cpp b/Libraries/LibWeb/Painting/SVGPaintable.cpp index 95352a4dcee..a2cfd1383cd 100644 --- a/Libraries/LibWeb/Painting/SVGPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGPaintable.cpp @@ -33,4 +33,12 @@ CSSPixelRect SVGPaintable::compute_absolute_rect() const return PaintableBox::compute_absolute_rect(); } +ShouldAntiAlias SVGPaintable::should_anti_alias() const +{ + auto shape_rendering = computed_values().shape_rendering(); + if (first_is_one_of(shape_rendering, CSS::ShapeRendering::Optimizespeed, CSS::ShapeRendering::Crispedges)) + return ShouldAntiAlias::No; + return ShouldAntiAlias::Yes; +} + } diff --git a/Libraries/LibWeb/Painting/SVGPaintable.h b/Libraries/LibWeb/Painting/SVGPaintable.h index 2d592947755..f2c9385ba71 100644 --- a/Libraries/LibWeb/Painting/SVGPaintable.h +++ b/Libraries/LibWeb/Painting/SVGPaintable.h @@ -23,6 +23,8 @@ protected: SVGPaintable(Layout::SVGBox const&); virtual CSSPixelRect compute_absolute_rect() const override; + + ShouldAntiAlias should_anti_alias() const; }; template<> diff --git a/Libraries/LibWeb/Painting/SVGPathPaintable.cpp b/Libraries/LibWeb/Painting/SVGPathPaintable.cpp index a59d4be35ba..6f4f220b7ce 100644 --- a/Libraries/LibWeb/Painting/SVGPathPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGPathPaintable.cpp @@ -98,6 +98,7 @@ void SVGPathPaintable::paint(DisplayListRecordingContext& context, PaintPhase ph .path = closed_path(), .paint_style_or_color = Gfx::Color(Color::Black), .winding_rule = to_gfx_winding_rule(graphics_element.clip_rule().value_or(SVG::ClipRule::Nonzero)), + .should_anti_alias = should_anti_alias(), }); return; } @@ -116,12 +117,14 @@ void SVGPathPaintable::paint(DisplayListRecordingContext& context, PaintPhase ph .opacity = fill_opacity, .paint_style_or_color = *paint_style, .winding_rule = winding_rule, + .should_anti_alias = should_anti_alias(), }); } else if (auto fill_color = graphics_element.fill_color(); fill_color.has_value()) { context.display_list_recorder().fill_path({ .path = closed_path(), .paint_style_or_color = fill_color->with_opacity(fill_opacity), .winding_rule = winding_rule, + .should_anti_alias = should_anti_alias(), }); } @@ -177,6 +180,7 @@ void SVGPathPaintable::paint(DisplayListRecordingContext& context, PaintPhase ph .opacity = stroke_opacity, .paint_style_or_color = *paint_style, .thickness = stroke_thickness, + .should_anti_alias = should_anti_alias(), }); } else if (auto stroke_color = graphics_element.stroke_color(); stroke_color.has_value()) { context.display_list_recorder().stroke_path({ @@ -188,6 +192,7 @@ void SVGPathPaintable::paint(DisplayListRecordingContext& context, PaintPhase ph .path = path, .paint_style_or_color = stroke_color->with_opacity(stroke_opacity), .thickness = stroke_thickness, + .should_anti_alias = should_anti_alias(), }); } } diff --git a/Libraries/LibWeb/Painting/ShouldAntiAlias.h b/Libraries/LibWeb/Painting/ShouldAntiAlias.h new file mode 100644 index 00000000000..004d0be7b51 --- /dev/null +++ b/Libraries/LibWeb/Painting/ShouldAntiAlias.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025, Tim Ledbetter + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +namespace Web::Painting { + +enum class ShouldAntiAlias : bool { + Yes, + No, +}; + +}