Sfoglia il codice sorgente

LibWeb: Add DOMMatrix fromFloat32Array and fromFloat64Array

Bastiaan van der Plaat 1 anno fa
parent
commit
3c27843cfe

+ 1 - 1
Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp

@@ -662,7 +662,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
     auto @cpp_name@ = JS::make_handle(TRY(@js_name@@js_suffix@.to_object(vm)));
     auto @cpp_name@ = JS::make_handle(TRY(@js_name@@js_suffix@.to_object(vm)));
 )~~~");
 )~~~");
         }
         }
-    } else if (parameter.type->name() == "BufferSource") {
+    } else if (parameter.type->name() == "BufferSource" || parameter.type->name() == "Float32Array" || parameter.type->name() == "Float64Array") {
         if (optional) {
         if (optional) {
             scoped_generator.append(R"~~~(
             scoped_generator.append(R"~~~(
     Optional<JS::Handle<JS::Object>> @cpp_name@;
     Optional<JS::Handle<JS::Object>> @cpp_name@;

+ 8 - 2
Tests/LibWeb/Text/expected/geometry/dommatrix-create.txt

@@ -1,4 +1,10 @@
 1. {"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}
 1. {"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}
-2. {"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}
-3. {"a":10,"b":20,"c":50,"d":60,"e":130,"f":140,"m11":10,"m12":20,"m13":30,"m14":40,"m21":50,"m22":60,"m23":70,"m24":80,"m31":90,"m32":100,"m33":110,"m34":120,"m41":130,"m42":140,"m43":150,"m44":160,"is2D":false,"isIdentity":false}
+2. {"a":10,"b":20,"c":50,"d":60,"e":130,"f":140,"m11":10,"m12":20,"m13":30,"m14":40,"m21":50,"m22":60,"m23":70,"m24":80,"m31":90,"m32":100,"m33":110,"m34":120,"m41":130,"m42":140,"m43":150,"m44":160,"is2D":false,"isIdentity":false}
+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. {"a":10,"b":20,"c":50,"d":60,"e":130,"f":140,"m11":10,"m12":20,"m13":30,"m14":40,"m21":50,"m22":60,"m23":70,"m24":80,"m31":90,"m32":100,"m33":110,"m34":120,"m41":130,"m42":140,"m43":150,"m44":160,"is2D":false,"isIdentity":false}
 4. {"a":10,"b":20,"c":50,"d":60,"e":130,"f":140,"m11":10,"m12":20,"m13":30,"m14":40,"m21":50,"m22":60,"m23":70,"m24":80,"m31":90,"m32":100,"m33":110,"m34":120,"m41":130,"m42":140,"m43":150,"m44":160,"is2D":false,"isIdentity":false}
+5. {"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}
+6. {"a":10,"b":20,"c":50,"d":60,"e":130,"f":140,"m11":10,"m12":20,"m13":30,"m14":40,"m21":50,"m22":60,"m23":70,"m24":80,"m31":90,"m32":100,"m33":110,"m34":120,"m41":130,"m42":140,"m43":150,"m44":160,"is2D":false,"isIdentity":false}
+7. {"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}
+8. {"a":10,"b":20,"c":50,"d":60,"e":130,"f":140,"m11":10,"m12":20,"m13":30,"m14":40,"m21":50,"m22":60,"m23":70,"m24":80,"m31":90,"m32":100,"m33":110,"m34":120,"m41":130,"m42":140,"m43":150,"m44":160,"is2D":false,"isIdentity":false}
+9. Exception: TypeError
+10. Exception: TypeError

+ 28 - 5
Tests/LibWeb/Text/input/geometry/dommatrix-create.html

@@ -3,19 +3,42 @@
     test(() => {
     test(() => {
         let testCounter = 1;
         let testCounter = 1;
         function testPart(part) {
         function testPart(part) {
-            println(`${testCounter++}. ${JSON.stringify(part())}`);
+            try {
+                println(`${testCounter}. ${JSON.stringify(part())}`);
+            } catch (e) {
+                println(`${testCounter}. Exception: ${e.name}`);
+            }
+            testCounter++;
         }
         }
 
 
         // 1. Creating a DOMMatrix
         // 1. Creating a DOMMatrix
         testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60]));
         testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60]));
 
 
-        // 2. Creating a DOMMatrix with fromMatrix
-        testPart(() => DOMMatrix.fromMatrix({ a: 10, b: 20, c: 30, d: 40, e: 50, f: 60 }));
-
-        // 3. Creating a DOMMatrix
+        // 2. Creating a DOMMatrix
         testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]));
         testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]));
 
 
+        // 3. Creating a DOMMatrix with fromMatrix
+        testPart(() => DOMMatrix.fromMatrix({ a: 10, b: 20, c: 30, d: 40, e: 50, f: 60 }));
+
         // 4. Creating a DOMMatrix with fromMatrix
         // 4. Creating a DOMMatrix with fromMatrix
         testPart(() => DOMMatrix.fromMatrix({ m11: 10, m12: 20, m13: 30, m14: 40, m21: 50, m22: 60, m23: 70, m24: 80, m31: 90, m32: 100, m33: 110, m34: 120, m41: 130, m42: 140, m43: 150, m44: 160 }));
         testPart(() => DOMMatrix.fromMatrix({ m11: 10, m12: 20, m13: 30, m14: 40, m21: 50, m22: 60, m23: 70, m24: 80, m31: 90, m32: 100, m33: 110, m34: 120, m41: 130, m42: 140, m43: 150, m44: 160 }));
+
+        // 5. Creating a DOMMatrix with fromFloat32Array
+        testPart(() => DOMMatrix.fromFloat32Array(new Float32Array([10, 20, 30, 40, 50, 60])));
+
+        // 6. Creating a DOMMatrix with fromFloat32Array
+        testPart(() => DOMMatrix.fromFloat32Array(new Float32Array([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160])));
+
+        // 7. Creating a DOMMatrix with fromFloat64Array
+        testPart(() => DOMMatrix.fromFloat64Array(new Float64Array([10, 20, 30, 40, 50, 60])));
+
+        // 8. Creating a DOMMatrix with fromFloat64Array
+        testPart(() => DOMMatrix.fromFloat64Array(new Float64Array([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160])));
+
+        // 9. Creating a DOMMatrix with fromFloat32Array wrong amount
+        testPart(() => DOMMatrix.fromFloat32Array(new Float32Array([10, 20, 30, 40])));
+
+        // 10. Creating a DOMMatrix with fromFloat64Array wrong amount
+        testPart(() => DOMMatrix.fromFloat64Array(new Float64Array([10, 20, 30, 40])));
     });
     });
 </script>
 </script>

+ 51 - 0
Userland/Libraries/LibWeb/Geometry/DOMMatrix.cpp

@@ -5,6 +5,7 @@
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
  */
  */
 
 
+#include <LibJS/Runtime/TypedArray.h>
 #include <LibWeb/Bindings/Intrinsics.h>
 #include <LibWeb/Bindings/Intrinsics.h>
 #include <LibWeb/Geometry/DOMMatrix.h>
 #include <LibWeb/Geometry/DOMMatrix.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
@@ -104,6 +105,56 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> DOMMatrix::from_matrix(JS::VM&
     return create_from_dom_matrix_init(*vm.current_realm(), other);
     return create_from_dom_matrix_init(*vm.current_realm(), other);
 }
 }
 
 
+// https://drafts.fxtf.org/geometry/#dom-dommatrix-fromfloat32array
+WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> DOMMatrix::from_float32_array(JS::VM& vm, JS::Handle<JS::Object> const& array32)
+{
+    if (!is<JS::Float32Array>(*array32))
+        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Float32Array");
+
+    auto& realm = *vm.current_realm();
+    auto& float32_array = static_cast<JS::Float32Array&>(*array32);
+    ReadonlySpan<float> elements = float32_array.data();
+
+    // If array32 has 6 elements, return the result of invoking create a 2d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers taking the values from array32 in the provided order.
+    if (elements.size() == 6)
+        return realm.heap().allocate<DOMMatrix>(realm, realm, elements.at(0), elements.at(1), elements.at(2), elements.at(3), elements.at(4), elements.at(5));
+
+    // If array32 has 16 elements, return the result of invoking create a 3d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers taking the values from array32 in the provided order.
+    if (elements.size() == 16)
+        return realm.heap().allocate<DOMMatrix>(realm, realm, elements.at(0), elements.at(1), elements.at(2), elements.at(3),
+            elements.at(4), elements.at(5), elements.at(6), elements.at(7),
+            elements.at(8), elements.at(9), elements.at(10), elements.at(11),
+            elements.at(12), elements.at(13), elements.at(14), elements.at(15));
+
+    // Otherwise, throw a TypeError exception.
+    return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Expected a Float32Array argument with 6 or 16 elements"_string };
+}
+
+// https://drafts.fxtf.org/geometry/#dom-dommatrix-fromfloat64array
+WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> DOMMatrix::from_float64_array(JS::VM& vm, JS::Handle<JS::Object> const& array64)
+{
+    if (!is<JS::Float64Array>(*array64))
+        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Float64Array");
+
+    auto& realm = *vm.current_realm();
+    auto& float64_array = static_cast<JS::Float64Array&>(*array64);
+    ReadonlySpan<double> elements = float64_array.data();
+
+    // If array64 has 6 elements, return the result of invoking create a 2d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers taking the values from array64 in the provided order.
+    if (elements.size() == 6)
+        return realm.heap().allocate<DOMMatrix>(realm, realm, elements.at(0), elements.at(1), elements.at(2), elements.at(3), elements.at(4), elements.at(5));
+
+    // If array64 has 16 elements, return the result of invoking create a 3d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers taking the values from array64 in the provided order.
+    if (elements.size() == 16)
+        return realm.heap().allocate<DOMMatrix>(realm, realm, elements.at(0), elements.at(1), elements.at(2), elements.at(3),
+            elements.at(4), elements.at(5), elements.at(6), elements.at(7),
+            elements.at(8), elements.at(9), elements.at(10), elements.at(11),
+            elements.at(12), elements.at(13), elements.at(14), elements.at(15));
+
+    // Otherwise, throw a TypeError exception.
+    return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Expected a Float64Array argument with 6 or 16 elements"_string };
+}
+
 // https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m11
 // https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-m11
 void DOMMatrix::set_m11(double value)
 void DOMMatrix::set_m11(double value)
 {
 {

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

@@ -24,6 +24,8 @@ public:
     virtual ~DOMMatrix() override;
     virtual ~DOMMatrix() override;
 
 
     static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> from_matrix(JS::VM&, DOMMatrixInit other = {});
     static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> from_matrix(JS::VM&, DOMMatrixInit other = {});
+    static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> from_float32_array(JS::VM&, JS::Handle<JS::Object> const& array32);
+    static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> from_float64_array(JS::VM&, JS::Handle<JS::Object> const& array64);
 
 
     void set_m11(double value);
     void set_m11(double value);
     void set_m12(double value);
     void set_m12(double value);

+ 2 - 2
Userland/Libraries/LibWeb/Geometry/DOMMatrix.idl

@@ -7,8 +7,8 @@ interface DOMMatrix : DOMMatrixReadOnly {
     constructor(optional (DOMString or sequence<unrestricted double>) init);
     constructor(optional (DOMString or sequence<unrestricted double>) init);
 
 
     [NewObject] static DOMMatrix fromMatrix(optional DOMMatrixInit other = {});
     [NewObject] static DOMMatrix fromMatrix(optional DOMMatrixInit other = {});
-    // FIXME: [NewObject] static DOMMatrix fromFloat32Array(Float32Array array32);
-    // FIXME: [NewObject] static DOMMatrix fromFloat64Array(Float64Array array64);
+    [NewObject] static DOMMatrix fromFloat32Array(Float32Array array32);
+    [NewObject] static DOMMatrix fromFloat64Array(Float64Array array64);
 
 
     // These attributes are simple aliases for certain elements of the 4x4 matrix
     // These attributes are simple aliases for certain elements of the 4x4 matrix
     inherit attribute unrestricted double a;
     inherit attribute unrestricted double a;

+ 50 - 1
Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp

@@ -5,7 +5,6 @@
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
  */
  */
 
 
-#include <LibJS/Runtime/ArrayBuffer.h>
 #include <LibJS/Runtime/TypedArray.h>
 #include <LibJS/Runtime/TypedArray.h>
 #include <LibWeb/Bindings/Intrinsics.h>
 #include <LibWeb/Bindings/Intrinsics.h>
 #include <LibWeb/Geometry/DOMMatrix.h>
 #include <LibWeb/Geometry/DOMMatrix.h>
@@ -208,6 +207,56 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrixReadOnly>> DOMMatrixReadOnly::from
     return create_from_dom_matrix_init(*vm.current_realm(), other);
     return create_from_dom_matrix_init(*vm.current_realm(), other);
 }
 }
 
 
+// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-fromfloat32array
+WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrixReadOnly>> DOMMatrixReadOnly::from_float32_array(JS::VM& vm, JS::Handle<JS::Object> const& array32)
+{
+    if (!is<JS::Float32Array>(*array32))
+        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Float32Array");
+
+    auto& realm = *vm.current_realm();
+    auto& float32_array = static_cast<JS::Float32Array&>(*array32);
+    ReadonlySpan<float> elements = float32_array.data();
+
+    // If array32 has 6 elements, return the result of invoking create a 2d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers taking the values from array32 in the provided order.
+    if (elements.size() == 6)
+        return realm.heap().allocate<DOMMatrix>(realm, realm, elements.at(0), elements.at(1), elements.at(2), elements.at(3), elements.at(4), elements.at(5));
+
+    // If array32 has 16 elements, return the result of invoking create a 3d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers taking the values from array32 in the provided order.
+    if (elements.size() == 16)
+        return realm.heap().allocate<DOMMatrix>(realm, realm, elements.at(0), elements.at(1), elements.at(2), elements.at(3),
+            elements.at(4), elements.at(5), elements.at(6), elements.at(7),
+            elements.at(8), elements.at(9), elements.at(10), elements.at(11),
+            elements.at(12), elements.at(13), elements.at(14), elements.at(15));
+
+    // Otherwise, throw a TypeError exception.
+    return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Expected a Float32Array argument with 6 or 16 elements"_string };
+}
+
+// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-fromfloat64array
+WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrixReadOnly>> DOMMatrixReadOnly::from_float64_array(JS::VM& vm, JS::Handle<JS::Object> const& array64)
+{
+    if (!is<JS::Float64Array>(*array64))
+        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Float64Array");
+
+    auto& realm = *vm.current_realm();
+    auto& float64_array = static_cast<JS::Float64Array&>(*array64);
+    ReadonlySpan<double> elements = float64_array.data();
+
+    // If array64 has 6 elements, return the result of invoking create a 2d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers taking the values from array64 in the provided order.
+    if (elements.size() == 6)
+        return realm.heap().allocate<DOMMatrix>(realm, realm, elements.at(0), elements.at(1), elements.at(2), elements.at(3), elements.at(4), elements.at(5));
+
+    // If array64 has 16 elements, return the result of invoking create a 3d matrix of type DOMMatrixReadOnly or DOMMatrix as appropriate, with a sequence of numbers taking the values from array64 in the provided order.
+    if (elements.size() == 16)
+        return realm.heap().allocate<DOMMatrix>(realm, realm, elements.at(0), elements.at(1), elements.at(2), elements.at(3),
+            elements.at(4), elements.at(5), elements.at(6), elements.at(7),
+            elements.at(8), elements.at(9), elements.at(10), elements.at(11),
+            elements.at(12), elements.at(13), elements.at(14), elements.at(15));
+
+    // Otherwise, throw a TypeError exception.
+    return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Expected a Float64Array argument with 6 or 16 elements"_string };
+}
+
 // https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-isidentity
 // https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-isidentity
 bool DOMMatrixReadOnly::is_identity() const
 bool DOMMatrixReadOnly::is_identity() const
 {
 {

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

@@ -56,6 +56,8 @@ public:
     virtual ~DOMMatrixReadOnly() override;
     virtual ~DOMMatrixReadOnly() override;
 
 
     static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrixReadOnly>> from_matrix(JS::VM&, DOMMatrixInit& other);
     static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrixReadOnly>> from_matrix(JS::VM&, DOMMatrixInit& other);
+    static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrixReadOnly>> from_float32_array(JS::VM&, JS::Handle<JS::Object> const& array32);
+    static WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrixReadOnly>> from_float64_array(JS::VM&, JS::Handle<JS::Object> const& array64);
 
 
     // https://drafts.fxtf.org/geometry/#dommatrix-attributes
     // https://drafts.fxtf.org/geometry/#dommatrix-attributes
     double m11() const { return m_matrix.elements()[0][0]; }
     double m11() const { return m_matrix.elements()[0][0]; }

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

@@ -7,8 +7,8 @@ interface DOMMatrixReadOnly {
     constructor(optional (DOMString or sequence<unrestricted double>) init);
     constructor(optional (DOMString or sequence<unrestricted double>) init);
 
 
     [NewObject] static DOMMatrixReadOnly fromMatrix(optional DOMMatrixInit other = {});
     [NewObject] static DOMMatrixReadOnly fromMatrix(optional DOMMatrixInit other = {});
-    // FIXME: [NewObject] static DOMMatrixReadOnly fromFloat32Array(Float32Array array32);
-    // FIXME: [NewObject] static DOMMatrixReadOnly fromFloat64Array(Float64Array array64);
+    [NewObject] static DOMMatrixReadOnly fromFloat32Array(Float32Array array32);
+    [NewObject] static DOMMatrixReadOnly fromFloat64Array(Float64Array array64);
 
 
     // These attributes are simple aliases for certain elements of the 4x4 matrix
     // These attributes are simple aliases for certain elements of the 4x4 matrix
     readonly attribute unrestricted double a;
     readonly attribute unrestricted double a;