浏览代码

LibWeb: Add DOMPoint matrixTransform and DOMMatrix transformPoint

Bastiaan van der Plaat 1 年之前
父节点
当前提交
b4ae719664

+ 6 - 0
Tests/LibWeb/Text/expected/geometry/dompoint.txt

@@ -0,0 +1,6 @@
+1. {"x":10,"y":20,"z":0,"w":1}
+2. {"x":1,"y":2,"z":3,"w":4}
+3. {"a":10,"b":20,"c":30,"d":40,"e":50,"f":60,"m11":10,"m12":20,"m13":0,"m14":0,"m21":30,"m22":40,"m23":0,"m24":0,"m31":0,"m32":0,"m33":1,"m34":0,"m41":50,"m42":60,"m43":0,"m44":1,"is2D":true,"isIdentity":false}
+4. {"x":750,"y":1060,"z":0,"w":1}
+5. {"x":750,"y":1060,"z":0,"w":1}
+6. {"x":750,"y":1060,"z":0,"w":1}

+ 37 - 0
Tests/LibWeb/Text/input/geometry/dompoint.html

@@ -0,0 +1,37 @@
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        let testCounter = 1;
+        function testPart(part) {
+            println(`${testCounter++}. ${JSON.stringify(part())}`);
+        }
+
+        // 1. Creating a DOMPoint
+        testPart(() => new DOMPoint(10, 20));
+
+        // 2. Creating DOMPoint with fromPoint
+        testPart(() => DOMPoint.fromPoint({ x: 1, y: 2, z: 3, w: 4 }));
+
+        // 3. Creating a DOMMatrix
+        testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60]));
+
+        // 4. Transforming a DOMPoint using a DOMMatrix
+        testPart(function () {
+            const matrix = new DOMMatrix([10, 20, 30, 40, 50, 60]);
+            const point = new DOMPoint(10, 20);
+            return point.matrixTransform(matrix);
+        });
+
+        // 5. Transforming a point using a DOMMatrix
+        testPart(function () {
+            const matrix = new DOMMatrix([10, 20, 30, 40, 50, 60]);
+            return matrix.transformPoint(new DOMPoint(10, 20));
+        });
+
+        // 6. Transforming a point using a DOMMatrix
+        testPart(function () {
+            const matrix = new DOMMatrix([10, 20, 30, 40, 50, 60]);
+            return matrix.transformPoint({x: 10, y: 20});
+        });
+    });
+</script>

+ 3 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -299,8 +299,11 @@ class File;
 
 
 namespace Web::Geometry {
 namespace Web::Geometry {
 class DOMMatrix;
 class DOMMatrix;
+struct DOMMatrix2DInit;
+struct DOMMatrixInit;
 class DOMMatrixReadOnly;
 class DOMMatrixReadOnly;
 class DOMPoint;
 class DOMPoint;
+struct DOMPointInit;
 class DOMPointReadOnly;
 class DOMPointReadOnly;
 class DOMQuad;
 class DOMQuad;
 class DOMRect;
 class DOMRect;

+ 34 - 0
Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp

@@ -7,6 +7,7 @@
 #include <LibWeb/Bindings/Intrinsics.h>
 #include <LibWeb/Bindings/Intrinsics.h>
 #include <LibWeb/Geometry/DOMMatrix.h>
 #include <LibWeb/Geometry/DOMMatrix.h>
 #include <LibWeb/Geometry/DOMMatrixReadOnly.h>
 #include <LibWeb/Geometry/DOMMatrixReadOnly.h>
+#include <LibWeb/Geometry/DOMPoint.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 
 
 namespace Web::Geometry {
 namespace Web::Geometry {
@@ -240,6 +241,39 @@ JS::NonnullGCPtr<DOMMatrix> DOMMatrixReadOnly::inverse() const
     return result->invert_self();
     return result->invert_self();
 }
 }
 
 
+// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-transformpoint
+JS::NonnullGCPtr<DOMPoint> DOMMatrixReadOnly::transform_point(DOMPointInit const& point) const
+{
+    // Let pointObject be the result of invoking create a DOMPoint from the dictionary point.
+    auto point_object = DOMPoint::from_point(realm().vm(), point);
+
+    // Return the result of invoking transform a point with a matrix, given pointObject and the current matrix. The passed argument does not get modified.
+    return transform_point(point_object);
+}
+
+// https://drafts.fxtf.org/geometry/#transform-a-point-with-a-matrix
+JS::NonnullGCPtr<DOMPoint> DOMMatrixReadOnly::transform_point(DOMPointReadOnly const& point) const
+{
+    // 1. Let x be point’s x coordinate.
+    // 2. Let y be point’s y coordinate.
+    // 3. Let z be point’s z coordinate.
+    // 4. Let w be point’s w perspective.
+    // 5. Let pointVector be a new column vector with the elements being x, y, z, and w, respectively.
+    Vector4<double> point_vector { point.x(), point.y(), point.z(), point.w() };
+
+    // 6. Set pointVector to pointVector pre-multiplied by matrix.
+    // This is really a post multiply because of the transposed m_matrix.
+    point_vector = m_matrix.transpose() * point_vector;
+
+    // 7. Let transformedPoint be a new DOMPoint object.
+    // 8. Set transformedPoint’s x coordinate to pointVector’s first element.
+    // 9. Set transformedPoint’s y coordinate to pointVector’s second element.
+    // 10. Set transformedPoint’s z coordinate to pointVector’s third element.
+    // 11. Set transformedPoint’s w perspective to pointVector’s fourth element.
+    // 12. Return transformedPoint.
+    return DOMPoint::construct_impl(realm(), point_vector.x(), point_vector.y(), point_vector.z(), point_vector.w());
+}
+
 // https://drafts.fxtf.org/geometry/#dommatrixreadonly-stringification-behavior
 // https://drafts.fxtf.org/geometry/#dommatrixreadonly-stringification-behavior
 WebIDL::ExceptionOr<String> DOMMatrixReadOnly::to_string() const
 WebIDL::ExceptionOr<String> DOMMatrixReadOnly::to_string() const
 {
 {

+ 4 - 0
Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.h

@@ -83,6 +83,10 @@ public:
 
 
     JS::NonnullGCPtr<DOMMatrix> inverse() const;
     JS::NonnullGCPtr<DOMMatrix> inverse() const;
 
 
+    JS::NonnullGCPtr<DOMPoint> transform_point(DOMPointInit const&) const;
+
+    JS::NonnullGCPtr<DOMPoint> transform_point(DOMPointReadOnly const&) const;
+
     WebIDL::ExceptionOr<String> to_string() const;
     WebIDL::ExceptionOr<String> to_string() const;
 
 
 protected:
 protected:

+ 2 - 1
Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.idl

@@ -1,4 +1,5 @@
 #import <Geometry/DOMMatrix.idl>
 #import <Geometry/DOMMatrix.idl>
+#import <Geometry/DOMPoint.idl>
 
 
 // https://drafts.fxtf.org/geometry/#dommatrixreadonly
 // https://drafts.fxtf.org/geometry/#dommatrixreadonly
 [Exposed=(Window,Worker), Serializable, UseNewAKString]
 [Exposed=(Window,Worker), Serializable, UseNewAKString]
@@ -52,7 +53,7 @@ interface DOMMatrixReadOnly {
     // FIXME: [NewObject] DOMMatrix flipY();
     // FIXME: [NewObject] DOMMatrix flipY();
     [NewObject] DOMMatrix inverse();
     [NewObject] DOMMatrix inverse();
 
 
-    // FIXME: [NewObject] DOMPoint transformPoint(optional DOMPointInit point = {});
+    [NewObject] DOMPoint transformPoint(optional DOMPointInit point = {});
     // FIXME: [NewObject] Float32Array toFloat32Array();
     // FIXME: [NewObject] Float32Array toFloat32Array();
     // FIXME: [NewObject] Float64Array toFloat64Array();
     // FIXME: [NewObject] Float64Array toFloat64Array();
 
 

+ 14 - 0
Userland/Libraries/LibWeb/Geometry/DOMPointReadOnly.cpp

@@ -6,6 +6,7 @@
  */
  */
 
 
 #include <LibWeb/Bindings/Intrinsics.h>
 #include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/Geometry/DOMMatrix.h>
 #include <LibWeb/Geometry/DOMPointReadOnly.h>
 #include <LibWeb/Geometry/DOMPointReadOnly.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 
 
@@ -34,6 +35,19 @@ JS::NonnullGCPtr<DOMPointReadOnly> DOMPointReadOnly::from_point(JS::VM& vm, DOMP
 
 
 DOMPointReadOnly::~DOMPointReadOnly() = default;
 DOMPointReadOnly::~DOMPointReadOnly() = default;
 
 
+// https://drafts.fxtf.org/geometry/#dom-dompointreadonly-matrixtransform
+WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMPoint>> DOMPointReadOnly::matrix_transform(DOMMatrixInit& matrix) const
+{
+    // 1. Let matrixObject be the result of invoking create a DOMMatrix from the dictionary matrix.
+    auto maybe_matrix_object = DOMMatrix::create_from_dom_matrix_2d_init(realm(), matrix);
+    if (maybe_matrix_object.is_exception())
+        return maybe_matrix_object.exception();
+    auto matrix_object = maybe_matrix_object.release_value();
+
+    // 2. Return the result of invoking transform a point with a matrix, given the current point and matrixObject. The current point does not get modified.
+    return matrix_object->transform_point(*this);
+}
+
 void DOMPointReadOnly::initialize(JS::Realm& realm)
 void DOMPointReadOnly::initialize(JS::Realm& realm)
 {
 {
     Base::initialize(realm);
     Base::initialize(realm);

+ 2 - 0
Userland/Libraries/LibWeb/Geometry/DOMPointReadOnly.h

@@ -36,6 +36,8 @@ public:
     double z() const { return m_z; }
     double z() const { return m_z; }
     double w() const { return m_w; }
     double w() const { return m_w; }
 
 
+    WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMPoint>> matrix_transform(DOMMatrixInit&) const;
+
 protected:
 protected:
     DOMPointReadOnly(JS::Realm&, double x, double y, double z, double w);
     DOMPointReadOnly(JS::Realm&, double x, double y, double z, double w);
 
 

+ 4 - 1
Userland/Libraries/LibWeb/Geometry/DOMPointReadOnly.idl

@@ -1,3 +1,6 @@
+#import <Geometry/DOMMatrixReadOnly.idl>
+#import <Geometry/DOMPoint.idl>
+
 // https://drafts.fxtf.org/geometry/#dompointreadonly
 // https://drafts.fxtf.org/geometry/#dompointreadonly
 [Exposed=(Window,Worker), Serializable]
 [Exposed=(Window,Worker), Serializable]
 interface DOMPointReadOnly {
 interface DOMPointReadOnly {
@@ -12,7 +15,7 @@ interface DOMPointReadOnly {
     readonly attribute unrestricted double z;
     readonly attribute unrestricted double z;
     readonly attribute unrestricted double w;
     readonly attribute unrestricted double w;
 
 
-    // FIXME: DOMPoint matrixTransform(optional DOMMatrixInit matrix = {});
+    [NewObject] DOMPoint matrixTransform(optional DOMMatrixInit matrix = {});
 
 
     [Default] object toJSON();
     [Default] object toJSON();
 };
 };