mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-25 03:36:36 +00:00
LibGfx+LibWeb: Add new Path class with Skia backend, use for 2D canvas
This thing is essentially a wrapper around an SkPath, although we do some indirection via a PathImpl class to keep the door open for alternative rasterizer/path backends in the future. We also update the 2D canvas code, since that was the only code that used Painter+DeprecatedPath, and this allows us to just drop that code instead of temporarily supporting it until the next commit.
This commit is contained in:
parent
c8f09312f7
commit
a3cc03f180
Notes:
github-actions[bot]
2024-08-20 07:38:18 +00:00
Author: https://github.com/awesomekling
Commit: a3cc03f180
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1024
15 changed files with 417 additions and 93 deletions
|
@ -6,7 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibGfx/DeprecatedPath.h>
|
||||
#include <LibGfx/Path.h>
|
||||
#include <LibWeb/Geometry/DOMPointReadOnly.h>
|
||||
#include <LibWeb/HTML/Canvas/CanvasState.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
|
@ -30,8 +30,8 @@ public:
|
|||
WebIDL::ExceptionOr<void> arc(float x, float y, float radius, float start_angle, float end_angle, bool counter_clockwise);
|
||||
WebIDL::ExceptionOr<void> ellipse(float x, float y, float radius_x, float radius_y, float rotation, float start_angle, float end_angle, bool counter_clockwise);
|
||||
|
||||
Gfx::DeprecatedPath& path() { return m_path; }
|
||||
Gfx::DeprecatedPath const& path() const { return m_path; }
|
||||
Gfx::Path& path() { return m_path; }
|
||||
Gfx::Path const& path() const { return m_path; }
|
||||
|
||||
protected:
|
||||
explicit CanvasPath(Bindings::PlatformObject& self)
|
||||
|
@ -52,7 +52,7 @@ private:
|
|||
|
||||
JS::NonnullGCPtr<Bindings::PlatformObject> m_self;
|
||||
Optional<CanvasState const&> m_canvas_state;
|
||||
Gfx::DeprecatedPath m_path;
|
||||
Gfx::Path m_path;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
#include <LibGfx/Color.h>
|
||||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/PaintStyle.h>
|
||||
#include <LibGfx/PathClipper.h>
|
||||
#include <LibGfx/Path.h>
|
||||
#include <LibGfx/WindingRule.h>
|
||||
#include <LibWeb/Bindings/CanvasRenderingContext2DPrototype.h>
|
||||
#include <LibWeb/HTML/CanvasGradient.h>
|
||||
#include <LibWeb/HTML/CanvasPattern.h>
|
||||
|
@ -23,6 +24,11 @@ namespace Web::HTML {
|
|||
// https://html.spec.whatwg.org/multipage/canvas.html#canvasstate
|
||||
class CanvasState {
|
||||
public:
|
||||
struct ClipPath {
|
||||
Gfx::Path path;
|
||||
Gfx::WindingRule winding_rule;
|
||||
};
|
||||
|
||||
virtual ~CanvasState() = default;
|
||||
|
||||
void save();
|
||||
|
@ -81,7 +87,7 @@ public:
|
|||
bool image_smoothing_enabled { true };
|
||||
Bindings::ImageSmoothingQuality image_smoothing_quality { Bindings::ImageSmoothingQuality::Low };
|
||||
float global_alpha = { 1 };
|
||||
Optional<Gfx::ClipPath> clip;
|
||||
Optional<ClipPath> clip;
|
||||
RefPtr<CSS::CSSStyleValue> font_style_value { nullptr };
|
||||
RefPtr<Gfx::Font const> current_font { nullptr };
|
||||
Bindings::CanvasTextAlign text_align { Bindings::CanvasTextAlign::Start };
|
||||
|
|
|
@ -71,7 +71,7 @@ JS::NonnullGCPtr<HTMLCanvasElement> CanvasRenderingContext2D::canvas_for_binding
|
|||
return *m_element;
|
||||
}
|
||||
|
||||
Gfx::DeprecatedPath CanvasRenderingContext2D::rect_path(float x, float y, float width, float height)
|
||||
Gfx::Path CanvasRenderingContext2D::rect_path(float x, float y, float width, float height)
|
||||
{
|
||||
auto& drawing_state = this->drawing_state();
|
||||
|
||||
|
@ -80,13 +80,12 @@ Gfx::DeprecatedPath CanvasRenderingContext2D::rect_path(float x, float y, float
|
|||
auto bottom_left = drawing_state.transform.map(Gfx::FloatPoint(x, y + height));
|
||||
auto bottom_right = drawing_state.transform.map(Gfx::FloatPoint(x + width, y + height));
|
||||
|
||||
Gfx::DeprecatedPath path;
|
||||
Gfx::Path path;
|
||||
path.move_to(top_left);
|
||||
path.line_to(top_right);
|
||||
path.line_to(bottom_right);
|
||||
path.line_to(bottom_left);
|
||||
path.line_to(top_left);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -191,7 +190,7 @@ Gfx::Painter* CanvasRenderingContext2D::painter()
|
|||
return m_painter.ptr();
|
||||
}
|
||||
|
||||
Gfx::DeprecatedPath CanvasRenderingContext2D::text_path(StringView text, float x, float y, Optional<double> max_width)
|
||||
Gfx::Path CanvasRenderingContext2D::text_path(StringView text, float x, float y, Optional<double> max_width)
|
||||
{
|
||||
if (max_width.has_value() && max_width.value() <= 0)
|
||||
return {};
|
||||
|
@ -199,7 +198,7 @@ Gfx::DeprecatedPath CanvasRenderingContext2D::text_path(StringView text, float x
|
|||
auto& drawing_state = this->drawing_state();
|
||||
auto font = current_font();
|
||||
|
||||
Gfx::DeprecatedPath path;
|
||||
Gfx::Path path;
|
||||
path.move_to({ x, y });
|
||||
path.text(Utf8View { text }, *font);
|
||||
|
||||
|
@ -241,8 +240,7 @@ Gfx::DeprecatedPath CanvasRenderingContext2D::text_path(StringView text, float x
|
|||
}
|
||||
|
||||
transform = Gfx::AffineTransform { drawing_state.transform }.multiply(transform);
|
||||
path = path.copy_transformed(transform);
|
||||
return path;
|
||||
return path.copy_transformed(transform);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fill_text(StringView text, float x, float y, Optional<double> max_width)
|
||||
|
@ -260,7 +258,7 @@ void CanvasRenderingContext2D::begin_path()
|
|||
path().clear();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::stroke_internal(Gfx::DeprecatedPath const& path)
|
||||
void CanvasRenderingContext2D::stroke_internal(Gfx::Path const& path)
|
||||
{
|
||||
auto* painter = this->painter();
|
||||
if (!painter)
|
||||
|
@ -298,7 +296,7 @@ static Gfx::WindingRule parse_fill_rule(StringView fill_rule)
|
|||
return Gfx::WindingRule::Nonzero;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fill_internal(Gfx::DeprecatedPath const& path, Gfx::WindingRule winding_rule)
|
||||
void CanvasRenderingContext2D::fill_internal(Gfx::Path const& path, Gfx::WindingRule winding_rule)
|
||||
{
|
||||
auto* painter = this->painter();
|
||||
if (!painter)
|
||||
|
@ -543,15 +541,17 @@ CanvasRenderingContext2D::PreparedText CanvasRenderingContext2D::prepare_text(By
|
|||
return prepared_text;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::clip_internal(Gfx::DeprecatedPath& path, Gfx::WindingRule winding_rule)
|
||||
void CanvasRenderingContext2D::clip_internal(Gfx::Path& path, Gfx::WindingRule winding_rule)
|
||||
{
|
||||
// FIXME: This should calculate the new clip path by intersecting the given path with the current one.
|
||||
// See: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-clip-dev
|
||||
path.close_all_subpaths();
|
||||
if (drawing_state().clip.has_value()) {
|
||||
dbgln("FIXME: CRC2D: Calculate the new clip path by intersecting the given path with the current one.");
|
||||
auto& current_clip = drawing_state().clip->path;
|
||||
current_clip.intersect(path);
|
||||
return;
|
||||
}
|
||||
drawing_state().clip = Gfx::ClipPath { path, winding_rule };
|
||||
drawing_state().clip = CanvasState::ClipPath { path, winding_rule };
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::clip(StringView fill_rule)
|
||||
|
|
|
@ -11,10 +11,9 @@
|
|||
#include <AK/Variant.h>
|
||||
#include <LibGfx/AffineTransform.h>
|
||||
#include <LibGfx/Color.h>
|
||||
#include <LibGfx/DeprecatedPath.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibGfx/Painter.h>
|
||||
#include <LibGfx/PathClipper.h>
|
||||
#include <LibGfx/Path.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/HTML/Canvas/CanvasCompositing.h>
|
||||
#include <LibWeb/HTML/Canvas/CanvasDrawImage.h>
|
||||
|
@ -124,13 +123,12 @@ private:
|
|||
|
||||
PreparedText prepare_text(ByteString const& text, float max_width = INFINITY);
|
||||
|
||||
Gfx::DeprecatedPath rect_path(float x, float y, float width, float height);
|
||||
[[nodiscard]] Gfx::Path rect_path(float x, float y, float width, float height);
|
||||
[[nodiscard]] Gfx::Path text_path(StringView text, float x, float y, Optional<double> max_width);
|
||||
|
||||
Gfx::DeprecatedPath text_path(StringView text, float x, float y, Optional<double> max_width);
|
||||
|
||||
void stroke_internal(Gfx::DeprecatedPath const&);
|
||||
void fill_internal(Gfx::DeprecatedPath const&, Gfx::WindingRule);
|
||||
void clip_internal(Gfx::DeprecatedPath&, Gfx::WindingRule);
|
||||
void stroke_internal(Gfx::Path const&);
|
||||
void fill_internal(Gfx::Path const&, Gfx::WindingRule);
|
||||
void clip_internal(Gfx::Path&, Gfx::WindingRule);
|
||||
|
||||
JS::NonnullGCPtr<HTMLCanvasElement> m_element;
|
||||
OwnPtr<Gfx::Painter> m_painter;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue