diff --git a/Userland/Libraries/LibWeb/HTML/Path2D.cpp b/Userland/Libraries/LibWeb/HTML/Path2D.cpp
index 99ec7653e8..aa0708c939 100644
--- a/Userland/Libraries/LibWeb/HTML/Path2D.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Path2D.cpp
@@ -1,11 +1,13 @@
/*
* Copyright (c) 2022, Sam Atkins
* Copyright (c) 2022, Andreas Kling
+ * Copyright (c) 2023, Luke Wilde
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include
+#include
#include
#include
#include
@@ -62,4 +64,37 @@ JS::ThrowCompletionOr Path2D::initialize(JS::Realm& realm)
return {};
}
+// https://html.spec.whatwg.org/multipage/canvas.html#dom-path2d-addpath
+WebIDL::ExceptionOr Path2D::add_path(JS::NonnullGCPtr path, Geometry::DOMMatrix2DInit& transform)
+{
+ // The addPath(path, transform) method, when invoked on a Path2D object a, must run these steps:
+
+ // 1. If the Path2D object path has no subpaths, then return.
+ if (path->path().segments().is_empty())
+ return {};
+
+ // 2. Let matrix be the result of creating a DOMMatrix from the 2D dictionary transform.
+ auto matrix = TRY(Geometry::DOMMatrix::create_from_dom_matrix_2d_init(realm(), transform));
+
+ // 3. If one or more of matrix's m11 element, m12 element, m21 element, m22 element, m41 element, or m42 element are infinite or NaN, then return.
+ if (!isfinite(matrix->m11()) || !isfinite(matrix->m12()) || !isfinite(matrix->m21()) || !isfinite(matrix->m22()) || !isfinite(matrix->m41()) || !isfinite(matrix->m42()))
+ return {};
+
+ // 4. Create a copy of all the subpaths in path. Let this copy be known as c.
+ // 5. Transform all the coordinates and lines in c by the transform matrix matrix.
+ auto copy = path->path().copy_transformed(Gfx::AffineTransform { static_cast(matrix->m11()), static_cast(matrix->m12()), static_cast(matrix->m21()), static_cast(matrix->m22()), static_cast(matrix->m41()), static_cast(matrix->m42()) });
+
+ // 6. Let (x, y) be the last point in the last subpath of c.
+ auto xy = copy.segments().last().point();
+
+ // 7. Add all the subpaths in c to a.
+ // FIXME: Is this correct?
+ this->path().add_path(copy);
+
+ // 8. Create a new subpath in a with (x, y) as the only point in the subpath.
+ this->move_to(xy.x(), xy.y());
+
+ return {};
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/Path2D.h b/Userland/Libraries/LibWeb/HTML/Path2D.h
index 81f7155c05..0749f6480e 100644
--- a/Userland/Libraries/LibWeb/HTML/Path2D.h
+++ b/Userland/Libraries/LibWeb/HTML/Path2D.h
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
namespace Web::HTML {
@@ -25,6 +26,8 @@ public:
virtual ~Path2D() override;
+ WebIDL::ExceptionOr add_path(JS::NonnullGCPtr path, Geometry::DOMMatrix2DInit& transform);
+
private:
Path2D(JS::Realm&, Optional, DeprecatedString>> const&);
diff --git a/Userland/Libraries/LibWeb/HTML/Path2D.idl b/Userland/Libraries/LibWeb/HTML/Path2D.idl
index 64264dd2c9..8879e34018 100644
--- a/Userland/Libraries/LibWeb/HTML/Path2D.idl
+++ b/Userland/Libraries/LibWeb/HTML/Path2D.idl
@@ -1,3 +1,4 @@
+#import
#import
// https://html.spec.whatwg.org/multipage/canvas.html#path2d
@@ -5,7 +6,7 @@
interface Path2D {
constructor(optional (Path2D or DOMString) path);
- // FIXME: undefined addPath(Path2D path, optional DOMMatrix2DInit transform = {});
+ undefined addPath(Path2D path, optional DOMMatrix2DInit transform = {});
};
Path2D includes CanvasPath;