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;