diff --git a/Base/res/html/misc/svg-gradients.html b/Base/res/html/misc/svg-gradients.html index 23a4eaa826..c6701061c8 100644 --- a/Base/res/html/misc/svg-gradients.html +++ b/Base/res/html/misc/svg-gradients.html @@ -133,6 +133,17 @@
+Linear gradient + transform with fill-opacity
+ + + + + + + + + +
Stroke linear gradient + transform
diff --git a/Userland/Libraries/LibGfx/AntiAliasingPainter.h b/Userland/Libraries/LibGfx/AntiAliasingPainter.h index a6a1ed8790..6ef9889f96 100644 --- a/Userland/Libraries/LibGfx/AntiAliasingPainter.h +++ b/Userland/Libraries/LibGfx/AntiAliasingPainter.h @@ -34,7 +34,7 @@ public: } void fill_path(Path const&, Color, Painter::WindingRule rule = Painter::WindingRule::Nonzero); - void fill_path(Path const&, PaintStyle const& paint_style, Painter::WindingRule rule = Painter::WindingRule::Nonzero); + void fill_path(Path const&, PaintStyle const& paint_style, float opacity = 1.0f, Painter::WindingRule rule = Painter::WindingRule::Nonzero); void stroke_path(Path const&, Color, float thickness); void stroke_path(Path const&, PaintStyle const& paint_style, float thickness); diff --git a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp index 550ca63263..8a0e77b80b 100644 --- a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp +++ b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp @@ -81,10 +81,19 @@ void EdgeFlagPathRasterizer::fill(Painter& painter, Path const& } template -void EdgeFlagPathRasterizer::fill(Painter& painter, Path const& path, PaintStyle const& style, Painter::WindingRule winding_rule, FloatPoint offset) +void EdgeFlagPathRasterizer::fill(Painter& painter, Path const& path, PaintStyle const& style, float opacity, Painter::WindingRule winding_rule, FloatPoint offset) { style.paint(enclosing_int_rect(path.bounding_box()), [&](PaintStyle::SamplerFunction sampler) { - fill_internal(painter, path, move(sampler), winding_rule, offset); + if (opacity == 0.0f) + return; + if (opacity != 1.0f) { + return fill_internal( + painter, path, [=, sampler = move(sampler)](IntPoint point) { + return sampler(point).with_opacity(opacity); + }, + winding_rule, offset); + } + return fill_internal(painter, path, move(sampler), winding_rule, offset); }); } @@ -321,10 +330,10 @@ void Painter::fill_path(Path const& path, Color color, WindingRule winding_rule) rasterizer.fill(*this, path, color, winding_rule); } -void Painter::fill_path(Path const& path, PaintStyle const& paint_style, Painter::WindingRule winding_rule) +void Painter::fill_path(Path const& path, PaintStyle const& paint_style, float opacity, Painter::WindingRule winding_rule) { EdgeFlagPathRasterizer<8> rasterizer(path_bounds(path)); - rasterizer.fill(*this, path, paint_style, winding_rule); + rasterizer.fill(*this, path, paint_style, opacity, winding_rule); } void AntiAliasingPainter::fill_path(Path const& path, Color color, Painter::WindingRule winding_rule) @@ -333,10 +342,10 @@ void AntiAliasingPainter::fill_path(Path const& path, Color color, Painter::Wind rasterizer.fill(m_underlying_painter, path, color, winding_rule, m_transform.translation()); } -void AntiAliasingPainter::fill_path(Path const& path, PaintStyle const& paint_style, Painter::WindingRule winding_rule) +void AntiAliasingPainter::fill_path(Path const& path, PaintStyle const& paint_style, float opacity, Painter::WindingRule winding_rule) { EdgeFlagPathRasterizer<32> rasterizer(path_bounds(path)); - rasterizer.fill(m_underlying_painter, path, paint_style, winding_rule, m_transform.translation()); + rasterizer.fill(m_underlying_painter, path, paint_style, opacity, winding_rule, m_transform.translation()); } template class EdgeFlagPathRasterizer<8>; diff --git a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.h b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.h index 6c80e974f2..f74289b116 100644 --- a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.h +++ b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.h @@ -146,7 +146,7 @@ public: EdgeFlagPathRasterizer(IntSize); void fill(Painter&, Path const&, Color, Painter::WindingRule, FloatPoint offset = {}); - void fill(Painter&, Path const&, PaintStyle const&, Painter::WindingRule, FloatPoint offset = {}); + void fill(Painter&, Path const&, PaintStyle const&, float opacity, Painter::WindingRule, FloatPoint offset = {}); private: using SubpixelSample = Detail::Sample; diff --git a/Userland/Libraries/LibGfx/Painter.h b/Userland/Libraries/LibGfx/Painter.h index cd668af928..6bd99d12f3 100644 --- a/Userland/Libraries/LibGfx/Painter.h +++ b/Userland/Libraries/LibGfx/Painter.h @@ -145,7 +145,7 @@ public: }; void fill_path(Path const&, Color, WindingRule rule = WindingRule::Nonzero); - void fill_path(Path const&, PaintStyle const& paint_style, WindingRule rule = WindingRule::Nonzero); + void fill_path(Path const&, PaintStyle const& paint_style, float opacity = 1.0f, WindingRule rule = WindingRule::Nonzero); Font const& font() const { diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPathClipper.cpp b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPathClipper.cpp index 1798656067..0f79c39f91 100644 --- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPathClipper.cpp +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPathClipper.cpp @@ -40,7 +40,7 @@ ErrorOr CanvasPathClipper::apply_clip(Gfx::Painter& painter) painter.blit(actual_save_rect.location(), *m_saved_clip_region, m_saved_clip_region->rect(), 1.0f, false); Gfx::AntiAliasingPainter aa_painter { painter }; auto fill_offset = m_bounding_box.location() - actual_save_rect.location(); - aa_painter.fill_path(m_canvas_clip.path, TRY(Gfx::BitmapPaintStyle::create(clip_area, fill_offset)), m_canvas_clip.winding_rule); + aa_painter.fill_path(m_canvas_clip.path, TRY(Gfx::BitmapPaintStyle::create(clip_area, fill_offset)), 1.0f, m_canvas_clip.winding_rule); return {}; } } diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp index 55092aaa4d..85515d76c6 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -272,7 +272,7 @@ void CanvasRenderingContext2D::fill_internal(Gfx::Path& path, StringView fill_ru if (auto color = drawing_state.fill_style.as_color(); color.has_value()) { painter.fill_path(path, *color, fill_rule); } else { - painter.fill_path(path, drawing_state.fill_style.to_gfx_paint_style(), fill_rule); + painter.fill_path(path, drawing_state.fill_style.to_gfx_paint_style(), 1.0f, fill_rule); } return path.bounding_box(); }); diff --git a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp index 3cd9071f1f..3c48bcfe90 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp @@ -99,12 +99,12 @@ void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const .transform = paint_transform }; - // FIXME: Apply fill opacity to paint styles? auto fill_opacity = geometry_element.fill_opacity().value_or(svg_context.fill_opacity()); if (auto paint_style = geometry_element.fill_paint_style(paint_context); paint_style.has_value()) { painter.fill_path( closed_path(), *paint_style, + fill_opacity, Gfx::Painter::WindingRule::EvenOdd); } else if (auto fill_color = geometry_element.fill_color().value_or(svg_context.fill_color()).with_opacity(fill_opacity); fill_color.alpha() > 0) { painter.fill_path(