LibWeb+LibGfx: Allow filling with a paint style and opacity

This commit is contained in:
MacDue 2023-06-11 13:40:42 +01:00 committed by Andreas Kling
parent 8bd68198d6
commit eb4a58528e
8 changed files with 32 additions and 12 deletions

View file

@ -133,6 +133,17 @@
<rect x="115" y="15" width="170" height="110" fill="url(#grad7)" transform="rotate(45 200 70)" />
</svg>
<br>
<b>Linear gradient + transform with fill-opacity</b><br>
<svg height="150" width="400">
<defs>
<linearGradient id="grad7" x1="0" y1="0" x2="70%" y2="0">
<stop offset="0" stop-color="blue"/>
<stop offset="1" stop-color="magenta"/>
</linearGradient>
</defs>
<rect x="115" y="15" width="170" height="110" fill="url(#grad7)" fill-opacity="0.5" transform="rotate(5 200 70)" />
</svg>
<br>
<b>Stroke linear gradient + transform</b><br>
<svg height="150" width="400">
<defs>

View file

@ -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);

View file

@ -81,10 +81,19 @@ void EdgeFlagPathRasterizer<SamplesPerPixel>::fill(Painter& painter, Path const&
}
template<unsigned SamplesPerPixel>
void EdgeFlagPathRasterizer<SamplesPerPixel>::fill(Painter& painter, Path const& path, PaintStyle const& style, Painter::WindingRule winding_rule, FloatPoint offset)
void EdgeFlagPathRasterizer<SamplesPerPixel>::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>;

View file

@ -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<SamplesPerPixel>;

View file

@ -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
{

View file

@ -40,7 +40,7 @@ ErrorOr<void> 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 {};
}
}

View file

@ -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();
});

View file

@ -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(