mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 12:19:54 +00:00
LibWeb+LibGfx: Implement shadowBlur for Canvas2D
This commit is contained in:
parent
b521badbef
commit
e8cc0dc998
Notes:
github-actions[bot]
2024-12-05 16:08:13 +00:00
Author: https://github.com/ananas-dev
Commit: e8cc0dc998
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2737
8 changed files with 73 additions and 19 deletions
|
@ -26,9 +26,11 @@ public:
|
|||
virtual void draw_bitmap(Gfx::FloatRect const& dst_rect, Gfx::ImmutableBitmap const& src_bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode, float global_alpha) = 0;
|
||||
|
||||
virtual void stroke_path(Gfx::Path const&, Gfx::Color, float thickness) = 0;
|
||||
virtual void stroke_path(Gfx::Path const&, Gfx::Color, float thickness, float blur_radius) = 0;
|
||||
virtual void stroke_path(Gfx::Path const&, Gfx::PaintStyle const&, float thickness, float global_alpha) = 0;
|
||||
|
||||
virtual void fill_path(Gfx::Path const&, Gfx::Color, Gfx::WindingRule) = 0;
|
||||
virtual void fill_path(Gfx::Path const&, Gfx::Color, Gfx::WindingRule, float blur_radius) = 0;
|
||||
virtual void fill_path(Gfx::Path const&, Gfx::PaintStyle const&, float global_alpha, Gfx::WindingRule) = 0;
|
||||
|
||||
virtual void set_transform(Gfx::AffineTransform const&) = 0;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <AK/TypeCasts.h>
|
||||
#include <core/SkCanvas.h>
|
||||
#include <core/SkPath.h>
|
||||
#include <effects/SkBlurMaskFilter.h>
|
||||
#include <effects/SkGradientShader.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
@ -120,21 +121,6 @@ void PainterSkia::set_transform(Gfx::AffineTransform const& transform)
|
|||
impl().canvas()->setMatrix(matrix);
|
||||
}
|
||||
|
||||
void PainterSkia::stroke_path(Gfx::Path const& path, Gfx::Color color, float thickness)
|
||||
{
|
||||
// Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing.
|
||||
if (!thickness)
|
||||
return;
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
paint.setStrokeWidth(thickness);
|
||||
paint.setColor(to_skia_color(color));
|
||||
auto sk_path = to_skia_path(path);
|
||||
impl().canvas()->drawPath(sk_path, paint);
|
||||
}
|
||||
|
||||
static SkPoint to_skia_point(auto const& point)
|
||||
{
|
||||
return SkPoint::Make(point.x(), point.y());
|
||||
|
@ -198,10 +184,41 @@ static SkPaint to_skia_paint(Gfx::PaintStyle const& style, Gfx::FloatRect const&
|
|||
return {};
|
||||
}
|
||||
|
||||
void PainterSkia::stroke_path(Gfx::Path const& path, Gfx::Color color, float thickness)
|
||||
{
|
||||
// Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing.
|
||||
if (thickness <= 0)
|
||||
return;
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
paint.setStrokeWidth(thickness);
|
||||
paint.setColor(to_skia_color(color));
|
||||
auto sk_path = to_skia_path(path);
|
||||
impl().canvas()->drawPath(sk_path, paint);
|
||||
}
|
||||
|
||||
void PainterSkia::stroke_path(Gfx::Path const& path, Gfx::Color color, float thickness, float blur_radius)
|
||||
{
|
||||
// Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing.
|
||||
if (thickness <= 0)
|
||||
return;
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, blur_radius / 2));
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
paint.setStrokeWidth(thickness);
|
||||
paint.setColor(to_skia_color(color));
|
||||
auto sk_path = to_skia_path(path);
|
||||
impl().canvas()->drawPath(sk_path, paint);
|
||||
}
|
||||
|
||||
void PainterSkia::stroke_path(Gfx::Path const& path, Gfx::PaintStyle const& paint_style, float thickness, float global_alpha)
|
||||
{
|
||||
// Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing.
|
||||
if (!thickness)
|
||||
if (thickness <= 0)
|
||||
return;
|
||||
|
||||
auto sk_path = to_skia_path(path);
|
||||
|
@ -223,6 +240,17 @@ void PainterSkia::fill_path(Gfx::Path const& path, Gfx::Color color, Gfx::Windin
|
|||
impl().canvas()->drawPath(sk_path, paint);
|
||||
}
|
||||
|
||||
void PainterSkia::fill_path(Gfx::Path const& path, Gfx::Color color, Gfx::WindingRule winding_rule, float blur_radius)
|
||||
{
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, blur_radius / 2));
|
||||
paint.setColor(to_skia_color(color));
|
||||
auto sk_path = to_skia_path(path);
|
||||
sk_path.setFillType(to_skia_path_fill_type(winding_rule));
|
||||
impl().canvas()->drawPath(sk_path, paint);
|
||||
}
|
||||
|
||||
void PainterSkia::fill_path(Gfx::Path const& path, Gfx::PaintStyle const& paint_style, float global_alpha, Gfx::WindingRule winding_rule)
|
||||
{
|
||||
auto sk_path = to_skia_path(path);
|
||||
|
|
|
@ -22,8 +22,10 @@ public:
|
|||
virtual void fill_rect(Gfx::FloatRect const&, Color) override;
|
||||
virtual void draw_bitmap(Gfx::FloatRect const& dst_rect, Gfx::ImmutableBitmap const& src_bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode, float global_alpha) override;
|
||||
virtual void stroke_path(Gfx::Path const&, Gfx::Color, float thickness) override;
|
||||
virtual void stroke_path(Gfx::Path const&, Gfx::Color, float thickness, float blur_radius) override;
|
||||
virtual void stroke_path(Gfx::Path const&, Gfx::PaintStyle const&, float thickness, float global_alpha) override;
|
||||
virtual void fill_path(Gfx::Path const&, Gfx::Color, Gfx::WindingRule) override;
|
||||
virtual void fill_path(Gfx::Path const&, Gfx::Color, Gfx::WindingRule, float blur_radius) override;
|
||||
virtual void fill_path(Gfx::Path const&, Gfx::PaintStyle const&, float global_alpha, Gfx::WindingRule) override;
|
||||
virtual void set_transform(Gfx::AffineTransform const&) override;
|
||||
virtual void save() override;
|
||||
|
|
|
@ -26,6 +26,9 @@ public:
|
|||
virtual float shadow_offset_y() const = 0;
|
||||
virtual void set_shadow_offset_y(float offsetY) = 0;
|
||||
|
||||
virtual float shadow_blur() const = 0;
|
||||
virtual void set_shadow_blur(float offsetY) = 0;
|
||||
|
||||
virtual String shadow_color() const = 0;
|
||||
virtual void set_shadow_color(String color) = 0;
|
||||
|
||||
|
|
|
@ -3,6 +3,6 @@ interface mixin CanvasShadowStyles {
|
|||
// shadows
|
||||
attribute unrestricted double shadowOffsetX; // (default 0)
|
||||
attribute unrestricted double shadowOffsetY; // (default 0)
|
||||
[FIXME] attribute unrestricted double shadowBlur; // (default 0)
|
||||
attribute unrestricted double shadowBlur; // (default 0)
|
||||
attribute DOMString shadowColor; // (default transparent black)
|
||||
};
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
FillOrStrokeStyle stroke_style { Gfx::Color::Black };
|
||||
float shadow_offset_x { 0.0f };
|
||||
float shadow_offset_y { 0.0f };
|
||||
float shadow_blur { 0.0f };
|
||||
Gfx::Color shadow_color { Gfx::Color::Transparent };
|
||||
float line_width { 1 };
|
||||
Bindings::CanvasLineCap line_cap { Bindings::CanvasLineCap::Butt };
|
||||
|
|
|
@ -782,6 +782,22 @@ void CanvasRenderingContext2D::set_shadow_offset_y(float offsetY)
|
|||
drawing_state().shadow_offset_y = offsetY;
|
||||
}
|
||||
|
||||
float CanvasRenderingContext2D::shadow_blur() const
|
||||
{
|
||||
return drawing_state().shadow_blur;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur
|
||||
void CanvasRenderingContext2D::set_shadow_blur(float blur_radius)
|
||||
{
|
||||
// On setting, the attribute must be set to the new value,
|
||||
// except if the value is negative, infinite or NaN, in which case the new value must be ignored.
|
||||
if (blur_radius < 0 || isinf(blur_radius) || isnan(blur_radius))
|
||||
return;
|
||||
|
||||
drawing_state().shadow_blur = blur_radius;
|
||||
}
|
||||
|
||||
String CanvasRenderingContext2D::shadow_color() const
|
||||
{
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowcolor
|
||||
|
@ -824,7 +840,7 @@ void CanvasRenderingContext2D::paint_shadow_for_fill_internal(Gfx::Path const& p
|
|||
Gfx::AffineTransform transform;
|
||||
transform.translate(state.shadow_offset_x, state.shadow_offset_y);
|
||||
painter->set_transform(transform);
|
||||
painter->fill_path(path_to_fill, state.shadow_color.with_opacity(state.global_alpha), winding_rule);
|
||||
painter->fill_path(path_to_fill, state.shadow_color.with_opacity(state.global_alpha), winding_rule, state.shadow_blur);
|
||||
|
||||
painter->restore();
|
||||
|
||||
|
@ -844,7 +860,7 @@ void CanvasRenderingContext2D::paint_shadow_for_stroke_internal(Gfx::Path const&
|
|||
Gfx::AffineTransform transform;
|
||||
transform.translate(state.shadow_offset_x, state.shadow_offset_y);
|
||||
painter->set_transform(transform);
|
||||
painter->stroke_path(path, state.shadow_color.with_opacity(state.global_alpha), state.line_width);
|
||||
painter->stroke_path(path, state.shadow_color.with_opacity(state.global_alpha), state.line_width, state.shadow_blur);
|
||||
|
||||
painter->restore();
|
||||
|
||||
|
|
|
@ -105,6 +105,8 @@ public:
|
|||
virtual void set_shadow_offset_x(float) override;
|
||||
virtual float shadow_offset_y() const override;
|
||||
virtual void set_shadow_offset_y(float) override;
|
||||
virtual float shadow_blur() const override;
|
||||
virtual void set_shadow_blur(float) override;
|
||||
virtual String shadow_color() const override;
|
||||
virtual void set_shadow_color(String) override;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue