/* * Copyright (c) 2023, Luke Wilde * Copyright (c) 2023, Bastiaan van der Plaat * Copyright (c) 2024, Kenneth Myhra * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include namespace Web::Geometry { // https://drafts.fxtf.org/geometry/#dictdef-dommatrix2dinit struct DOMMatrix2DInit { Optional a; Optional b; Optional c; Optional d; Optional e; Optional f; Optional m11; Optional m12; Optional m21; Optional m22; Optional m41; Optional m42; }; // https://drafts.fxtf.org/geometry/#dictdef-dommatrixinit struct DOMMatrixInit : public DOMMatrix2DInit { double m13 { 0.0 }; double m14 { 0.0 }; double m23 { 0.0 }; double m24 { 0.0 }; double m31 { 0.0 }; double m32 { 0.0 }; double m33 { 0.0 }; double m34 { 0.0 }; double m43 { 0.0 }; double m44 { 0.0 }; Optional is2d; }; // https://drafts.fxtf.org/geometry/#dommatrixreadonly class DOMMatrixReadOnly : public Bindings::PlatformObject , public Bindings::Serializable { WEB_PLATFORM_OBJECT(DOMMatrixReadOnly, Bindings::PlatformObject); public: static WebIDL::ExceptionOr> construct_impl(JS::Realm&, Optional>> const& init); static WebIDL::ExceptionOr> create_from_dom_matrix_2d_init(JS::Realm&, DOMMatrix2DInit& init); static WebIDL::ExceptionOr> create_from_dom_matrix_init(JS::Realm&, DOMMatrixInit& init); static JS::NonnullGCPtr create(JS::Realm&); virtual ~DOMMatrixReadOnly() override; static WebIDL::ExceptionOr> from_matrix(JS::VM&, DOMMatrixInit& other); static WebIDL::ExceptionOr> from_float32_array(JS::VM&, JS::Handle const& array32); static WebIDL::ExceptionOr> from_float64_array(JS::VM&, JS::Handle const& array64); // https://drafts.fxtf.org/geometry/#dommatrix-attributes double m11() const { return m_matrix.elements()[0][0]; } double m12() const { return m_matrix.elements()[1][0]; } double m13() const { return m_matrix.elements()[2][0]; } double m14() const { return m_matrix.elements()[3][0]; } double m21() const { return m_matrix.elements()[0][1]; } double m22() const { return m_matrix.elements()[1][1]; } double m23() const { return m_matrix.elements()[2][1]; } double m24() const { return m_matrix.elements()[3][1]; } double m31() const { return m_matrix.elements()[0][2]; } double m32() const { return m_matrix.elements()[1][2]; } double m33() const { return m_matrix.elements()[2][2]; } double m34() const { return m_matrix.elements()[3][2]; } double m41() const { return m_matrix.elements()[0][3]; } double m42() const { return m_matrix.elements()[1][3]; } double m43() const { return m_matrix.elements()[2][3]; } double m44() const { return m_matrix.elements()[3][3]; } double a() const { return m11(); } double b() const { return m12(); } double c() const { return m21(); } double d() const { return m22(); } double e() const { return m41(); } double f() const { return m42(); } bool is2d() const { return m_is_2d; } bool is_identity() const; JS::NonnullGCPtr translate(Optional const& tx, Optional const& ty, Optional const& tz) const; JS::NonnullGCPtr scale(Optional scale_x, Optional scale_y, Optional scale_z, Optional origin_x, Optional origin_y, Optional origin_z); JS::NonnullGCPtr scale_non_uniform(Optional scale_x, Optional scale_y); JS::NonnullGCPtr scale3d(Optional scale, Optional origin_x, Optional origin_y, Optional origin_z); JS::NonnullGCPtr rotate(Optional rot_x, Optional rot_y, Optional rot_z); JS::NonnullGCPtr rotate_from_vector(Optional x, Optional y); JS::NonnullGCPtr rotate_axis_angle(Optional x, Optional y, Optional z, Optional angle); JS::NonnullGCPtr skew_x(double sx = 0) const; JS::NonnullGCPtr skew_y(double sy = 0) const; WebIDL::ExceptionOr> multiply(DOMMatrixInit other = {}); JS::NonnullGCPtr flip_x(); JS::NonnullGCPtr flip_y(); JS::NonnullGCPtr inverse() const; JS::NonnullGCPtr transform_point(DOMPointInit const&) const; JS::NonnullGCPtr transform_point(DOMPointReadOnly const&) const; JS::NonnullGCPtr to_float32_array() const; JS::NonnullGCPtr to_float64_array() const; WebIDL::ExceptionOr to_string() const; virtual StringView interface_name() const override { return "DOMMatrixReadOnly"sv; } virtual WebIDL::ExceptionOr serialization_steps(HTML::SerializationRecord&, bool for_storage, HTML::SerializationMemory&) override; virtual WebIDL::ExceptionOr deserialization_steps(ReadonlySpan const& record, size_t& position, HTML::DeserializationMemory&) override; protected: DOMMatrixReadOnly(JS::Realm&, double m11, double m12, double m21, double m22, double m41, double m42); DOMMatrixReadOnly(JS::Realm&, double m11, double m12, double m13, double m14, double m21, double m22, double m23, double m24, double m31, double m32, double m33, double m34, double m41, double m42, double m43, double m44); DOMMatrixReadOnly(JS::Realm&, DOMMatrixReadOnly const& other); explicit DOMMatrixReadOnly(JS::Realm&); // NOTE: The matrix used in the spec is column-major (https://drafts.fxtf.org/geometry/#4x4-abstract-matrix) but Gfx::Matrix4x4 is row-major so we need to transpose the values. Gfx::DoubleMatrix4x4 m_matrix { Gfx::DoubleMatrix4x4::identity() }; bool m_is_2d { true }; private: void initialize_from_create_2d_matrix(double m11, double m12, double m21, double m22, double m41, double m42); void initialize_from_create_3d_matrix(double m11, double m12, double m13, double m14, double m21, double m22, double m23, double m24, double m31, double m32, double m33, double m34, double m41, double m42, double m43, double m44); virtual void initialize(JS::Realm&) override; }; WebIDL::ExceptionOr validate_and_fixup_dom_matrix_2d_init(DOMMatrix2DInit& init); WebIDL::ExceptionOr validate_and_fixup_dom_matrix_init(DOMMatrixInit& init); struct ParsedMatrix { Gfx::DoubleMatrix4x4 matrix; bool is_2d_transform; }; WebIDL::ExceptionOr parse_dom_matrix_init_string(JS::Realm& realm, StringView transform_list); }