Prechádzať zdrojové kódy

LibWeb: Add DOMMatrix scale and scale3d

Bastiaan van der Plaat 1 rok pred
rodič
commit
42c2a67c83

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

@@ -0,0 +1,6 @@
+1. {"a":10,"b":20,"c":60,"d":80,"e":50,"f":60,"m11":10,"m12":20,"m13":0,"m14":0,"m21":60,"m22":80,"m23":0,"m24":0,"m31":0,"m32":0,"m33":3,"m34":0,"m41":50,"m42":60,"m43":0,"m44":1,"is2D":false,"isIdentity":false}
+2. {"a":10,"b":20,"c":60,"d":80,"e":50,"f":60,"m11":10,"m12":20,"m13":0,"m14":0,"m21":60,"m22":80,"m23":0,"m24":0,"m31":0,"m32":0,"m33":3,"m34":0,"m41":50,"m42":60,"m43":0,"m44":1,"is2D":false,"isIdentity":false}
+3. {"a":10,"b":20,"c":100,"d":120,"e":130,"f":140,"m11":10,"m12":20,"m13":30,"m14":40,"m21":100,"m22":120,"m23":140,"m24":160,"m31":270,"m32":300,"m33":330,"m34":360,"m41":130,"m42":140,"m43":150,"m44":160,"is2D":false,"isIdentity":false}
+4. {"a":50,"b":100,"c":150,"d":200,"e":-470,"f":-740,"m11":50,"m12":100,"m13":0,"m14":0,"m21":150,"m22":200,"m23":0,"m24":0,"m31":0,"m32":0,"m33":5,"m34":0,"m41":-470,"m42":-740,"m43":-8,"m44":1,"is2D":false,"isIdentity":false}
+5. {"a":50,"b":100,"c":150,"d":200,"e":-470,"f":-740,"m11":50,"m12":100,"m13":0,"m14":0,"m21":150,"m22":200,"m23":0,"m24":0,"m31":0,"m32":0,"m33":5,"m34":0,"m41":-470,"m42":-740,"m43":-8,"m44":1,"is2D":false,"isIdentity":false}
+6. {"a":50,"b":100,"c":250,"d":300,"e":-1350,"f":-1700,"m11":50,"m12":100,"m13":150,"m14":200,"m21":250,"m22":300,"m23":350,"m24":400,"m31":450,"m32":500,"m33":550,"m34":600,"m41":-1350,"m42":-1700,"m43":-2050,"m44":-2400,"is2D":false,"isIdentity":false}

+ 27 - 0
Tests/LibWeb/Text/input/geometry/dommatrix-scale.html

@@ -0,0 +1,27 @@
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        let testCounter = 1;
+        function testPart(part) {
+            println(`${testCounter++}. ${JSON.stringify(part())}`);
+        }
+
+        // 1. Scale DOMMatrix
+        testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60]).scale(1, 2, 3));
+
+        // 2. Scale DOMMatrix with multiply
+        testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60]).multiply(new DOMMatrix().scale(1, 2, 3)));
+
+        // 3. Scale DOMMatrix with multiply
+        testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]).multiply(new DOMMatrix().scale(1, 2, 3)));
+
+        // 4. Scale 3D DOMMatrix
+        testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60]).scale3d(5, 4, 3, 2));
+
+        // 5. Scale 3D DOMMatrix with multiply
+        testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60]).multiply(new DOMMatrix().scale3d(5, 4, 3, 2)));
+
+        // 6. Scale 3D DOMMatrix with multiply
+        testPart(() => new DOMMatrix([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]).multiply(new DOMMatrix().scale3d(5, 4, 3, 2)));
+    });
+</script>

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

@@ -326,6 +326,51 @@ JS::NonnullGCPtr<DOMMatrix> DOMMatrix::translate_self(Optional<double> tx, Optio
     return *this;
 }
 
+// https://drafts.fxtf.org/geometry/#dom-dommatrix-scaleself
+JS::NonnullGCPtr<DOMMatrix> DOMMatrix::scale_self(Optional<double> scale_x, Optional<double> scale_y, Optional<double> scale_z, Optional<double> origin_x, Optional<double> origin_y, Optional<double> origin_z)
+{
+    // 1. Perform a translateSelf() transformation on the current matrix with the arguments originX, originY, originZ.
+    translate_self(origin_x, origin_y, origin_z);
+
+    // 2. If scaleY is missing, set scaleY to the value of scaleX.
+    if (!scale_y.has_value())
+        scale_y = scale_x.value_or(1);
+
+    // 3. Post-multiply a non-uniform scale transformation on the current matrix. The 3D scale matrix is described in CSS Transforms with sx = scaleX, sy = scaleY and sz = scaleZ. [CSS3-TRANSFORMS]
+    m_matrix = m_matrix * Gfx::scale_matrix(Vector3<double> { scale_x.value_or(1), scale_y.value(), scale_z.value_or(1) });
+
+    // 4. Negate originX, originY and originZ.
+    // 5. Perform a translateSelf() transformation on the current matrix with the arguments originX, originY, originZ.
+    translate_self(-origin_x.value_or(0), -origin_y.value_or(0), -origin_z.value_or(0));
+
+    // 6. If scaleZ is not 1, set is 2D of the current matrix to false.
+    if (scale_z != 1)
+        m_is_2d = false;
+
+    // 7. Return the current matrix.
+    return *this;
+}
+
+// https://drafts.fxtf.org/geometry/#dom-dommatrix-scale3dself
+JS::NonnullGCPtr<DOMMatrix> DOMMatrix::scale3d_self(Optional<double> scale, Optional<double> origin_x, Optional<double> origin_y, Optional<double> origin_z)
+{
+    // 1. Apply a translateSelf() transformation to the current matrix with the arguments originX, originY, originZ.
+    translate_self(origin_x, origin_y, origin_z);
+
+    // 2. Post-multiply a uniform 3D scale transformation (m11 = m22 = m33 = scale) on the current matrix. The 3D scale matrix is described in CSS Transforms with sx = sy = sz = scale. [CSS3-TRANSFORMS]
+    m_matrix = m_matrix * Gfx::scale_matrix(Vector3<double> { scale.value_or(1), scale.value_or(1), scale.value_or(1) });
+
+    // 3. Apply a translateSelf() transformation to the current matrix with the arguments -originX, -originY, -originZ.
+    translate_self(-origin_x.value_or(0), -origin_y.value_or(0), -origin_z.value_or(0));
+
+    // 4. If scale is not 1, set is 2D of the current matrix to false.
+    if (scale != 1)
+        m_is_2d = false;
+
+    // 5. Return the current matrix.
+    return *this;
+}
+
 // https://drafts.fxtf.org/geometry/#dom-dommatrix-skewxself
 JS::NonnullGCPtr<DOMMatrix> DOMMatrix::skew_x_self(double sx)
 {

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

@@ -52,6 +52,8 @@ public:
     WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> multiply_self(DOMMatrixInit other = {});
     WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> pre_multiply_self(DOMMatrixInit other = {});
     JS::NonnullGCPtr<DOMMatrix> translate_self(Optional<double> tx, Optional<double> ty, Optional<double> tz);
+    JS::NonnullGCPtr<DOMMatrix> scale_self(Optional<double> scale_x, Optional<double> scale_y, Optional<double> scale_z, Optional<double> origin_x, Optional<double> origin_y, Optional<double> origin_z);
+    JS::NonnullGCPtr<DOMMatrix> scale3d_self(Optional<double> scale, Optional<double> origin_x, Optional<double> origin_y, Optional<double> origin_z);
     JS::NonnullGCPtr<DOMMatrix> skew_x_self(double sx = 0);
     JS::NonnullGCPtr<DOMMatrix> skew_y_self(double sy = 0);
     JS::NonnullGCPtr<DOMMatrix> invert_self();

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

@@ -39,8 +39,8 @@ interface DOMMatrix : DOMMatrixReadOnly {
     DOMMatrix multiplySelf(optional DOMMatrixInit other = {});
     DOMMatrix preMultiplySelf(optional DOMMatrixInit other = {});
     DOMMatrix translateSelf(optional unrestricted double tx = 0, optional unrestricted double ty = 0, optional unrestricted double tz = 0);
-    // FIXME: DOMMatrix scaleSelf(optional unrestricted double scaleX = 1, optional unrestricted double scaleY, optional unrestricted double scaleZ = 1, optional unrestricted double originX = 0, optional unrestricted double originY = 0, optional unrestricted double originZ = 0);
-    // FIXME: DOMMatrix scale3dSelf(optional unrestricted double scale = 1, optional unrestricted double originX = 0, optional unrestricted double originY = 0, optional unrestricted double originZ = 0);
+    DOMMatrix scaleSelf(optional unrestricted double scaleX = 1, optional unrestricted double scaleY, optional unrestricted double scaleZ = 1, optional unrestricted double originX = 0, optional unrestricted double originY = 0, optional unrestricted double originZ = 0);
+    DOMMatrix scale3dSelf(optional unrestricted double scale = 1, optional unrestricted double originX = 0, optional unrestricted double originY = 0, optional unrestricted double originZ = 0);
     // FIXME: DOMMatrix rotateSelf(optional unrestricted double rotX = 0, optional unrestricted double rotY, optional unrestricted double rotZ);
     // FIXME: DOMMatrix rotateFromVectorSelf(optional unrestricted double x = 0, optional unrestricted double y = 0);
     // FIXME: DOMMatrix rotateAxisAngleSelf(optional unrestricted double x = 0, optional unrestricted double y = 0, optional unrestricted double z = 0, optional unrestricted double angle = 0);

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

@@ -270,6 +270,43 @@ JS::NonnullGCPtr<DOMMatrix> DOMMatrixReadOnly::translate(Optional<double> const&
     return result->translate_self(tx, ty, tz);
 }
 
+// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-scale
+JS::NonnullGCPtr<DOMMatrix> DOMMatrixReadOnly::scale(Optional<double> scale_x, Optional<double> scale_y, Optional<double> scale_z, Optional<double> origin_x, Optional<double> origin_y, Optional<double> origin_z)
+{
+    // 1. If scaleY is missing, set scaleY to the value of scaleX.
+    if (!scale_y.has_value())
+        scale_y = scale_x;
+
+    // 2. Let result be the resulting matrix initialized to the values of the current matrix.
+    auto result = DOMMatrix::create_from_dom_matrix_read_only(realm(), *this);
+
+    // 3. Perform a scaleSelf() transformation on result with the arguments scaleX, scaleY, scaleZ, originX, originY, originZ.
+    // 4. Return result.
+    return result->scale_self(scale_x, scale_y, scale_z, origin_x, origin_y, origin_z);
+}
+
+// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-scalenonuniform
+JS::NonnullGCPtr<DOMMatrix> DOMMatrixReadOnly::scale_non_uniform(Optional<double> scale_x, Optional<double> scale_y)
+{
+    // 1. Let result be the resulting matrix initialized to the values of the current matrix.
+    auto result = DOMMatrix::create_from_dom_matrix_read_only(realm(), *this);
+
+    // 2. Perform a scaleSelf() transformation on result with the arguments scaleX, scaleY, 1, 0, 0, 0.
+    // 3. Return result.
+    return result->scale_self(scale_x, scale_y, 1, 0, 0, 0);
+}
+
+// https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-scale3d
+JS::NonnullGCPtr<DOMMatrix> DOMMatrixReadOnly::scale3d(Optional<double> scale, Optional<double> origin_x, Optional<double> origin_y, Optional<double> origin_z)
+{
+    // 1. Let result be the resulting matrix initialized to the values of the current matrix.
+    auto result = DOMMatrix::create_from_dom_matrix_read_only(realm(), *this);
+
+    // 2. Perform a scale3dSelf() transformation on result with the arguments scale, originX, originY, originZ.
+    // 3. Return result.
+    return result->scale3d_self(scale, origin_x, origin_y, origin_z);
+}
+
 // https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-skewx
 JS::NonnullGCPtr<DOMMatrix> DOMMatrixReadOnly::skew_x(double sx) const
 {

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

@@ -86,6 +86,9 @@ public:
     bool is_identity() const;
 
     JS::NonnullGCPtr<DOMMatrix> translate(Optional<double> const& tx, Optional<double> const& ty, Optional<double> const& tz) const;
+    JS::NonnullGCPtr<DOMMatrix> scale(Optional<double> scale_x, Optional<double> scale_y, Optional<double> scale_z, Optional<double> origin_x, Optional<double> origin_y, Optional<double> origin_z);
+    JS::NonnullGCPtr<DOMMatrix> scale_non_uniform(Optional<double> scale_x, Optional<double> scale_y);
+    JS::NonnullGCPtr<DOMMatrix> scale3d(Optional<double> scale, Optional<double> origin_x, Optional<double> origin_y, Optional<double> origin_z);
     JS::NonnullGCPtr<DOMMatrix> skew_x(double sx = 0) const;
     JS::NonnullGCPtr<DOMMatrix> skew_y(double sy = 0) const;
     WebIDL::ExceptionOr<JS::NonnullGCPtr<DOMMatrix>> multiply(DOMMatrixInit other = {});

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

@@ -40,9 +40,9 @@ interface DOMMatrixReadOnly {
 
     // Immutable transform methods
     [NewObject] DOMMatrix translate(optional unrestricted double tx = 0, optional unrestricted double ty = 0, optional unrestricted double tz = 0);
-    // FIXME: [NewObject] DOMMatrix scale(optional unrestricted double scaleX = 1, optional unrestricted double scaleY, optional unrestricted double scaleZ = 1, optional unrestricted double originX = 0, optional unrestricted double originY = 0, optional unrestricted double originZ = 0);
-    // FIXME: [NewObject] DOMMatrix scaleNonUniform(optional unrestricted double scaleX = 1, optional unrestricted double scaleY = 1);
-    // FIXME: [NewObject] DOMMatrix scale3d(optional unrestricted double scale = 1, optional unrestricted double originX = 0, optional unrestricted double originY = 0, optional unrestricted double originZ = 0);
+    [NewObject] DOMMatrix scale(optional unrestricted double scaleX = 1, optional unrestricted double scaleY, optional unrestricted double scaleZ = 1, optional unrestricted double originX = 0, optional unrestricted double originY = 0, optional unrestricted double originZ = 0);
+    [NewObject] DOMMatrix scaleNonUniform(optional unrestricted double scaleX = 1, optional unrestricted double scaleY = 1);
+    [NewObject] DOMMatrix scale3d(optional unrestricted double scale = 1, optional unrestricted double originX = 0, optional unrestricted double originY = 0, optional unrestricted double originZ = 0);
     // FIXME: [NewObject] DOMMatrix rotate(optional unrestricted double rotX = 0, optional unrestricted double rotY, optional unrestricted double rotZ);
     // FIXME: [NewObject] DOMMatrix rotateFromVector(optional unrestricted double x = 0, optional unrestricted double y = 0);
     // FIXME: [NewObject] DOMMatrix rotateAxisAngle(optional unrestricted double x = 0, optional unrestricted double y = 0, optional unrestricted double z = 0, optional unrestricted double angle = 0);