diff --git a/Tests/LibWeb/Text/expected/geometry/dommatrix-rotate.txt b/Tests/LibWeb/Text/expected/geometry/dommatrix-rotate.txt new file mode 100644 index 0000000000..f51dbb57de --- /dev/null +++ b/Tests/LibWeb/Text/expected/geometry/dommatrix-rotate.txt @@ -0,0 +1,8 @@ +1. 22.233366125282362 +2. 35.06980604270564 +3. 22.06722747248274 +4. 26.483172559777778 +5. {"a":30,"b":40,"c":-9.999999999999998,"d":-19.999999999999996,"e":50,"f":60,"m11":30,"m12":40,"m13":0,"m14":0,"m21":-9.999999999999998,"m22":-19.999999999999996,"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":30,"b":40,"c":-9.999999999999998,"d":-19.999999999999996,"e":50,"f":60,"m11":30,"m12":40,"m13":0,"m14":0,"m21":-9.999999999999998,"m22":-19.999999999999996,"m23":0,"m24":0,"m31":0,"m32":0,"m33":1,"m34":0,"m41":50,"m42":60,"m43":0,"m44":1,"is2D":true,"isIdentity":false} +7. {"a":9.84807753012208,"b":19.69615506024416,"c":30,"d":40,"e":50,"f":60,"m11":9.84807753012208,"m12":19.69615506024416,"m13":-0.17364817766693033,"m14":0,"m21":30,"m22":40,"m23":0,"m24":0,"m31":1.7364817766693033,"m32":3.4729635533386065,"m33":0.984807753012208,"m34":0,"m41":50,"m42":60,"m43":0,"m44":1,"is2D":false,"isIdentity":false} +8. {"a":9.84807753012208,"b":19.69615506024416,"c":30,"d":40,"e":50,"f":60,"m11":9.84807753012208,"m12":19.69615506024416,"m13":-0.17364817766693033,"m14":0,"m21":30,"m22":40,"m23":0,"m24":0,"m31":1.7364817766693033,"m32":3.4729635533386065,"m33":0.984807753012208,"m34":0,"m41":50,"m42":60,"m43":0,"m44":1,"is2D":false,"isIdentity":false} diff --git a/Tests/LibWeb/Text/input/geometry/dommatrix-rotate.html b/Tests/LibWeb/Text/input/geometry/dommatrix-rotate.html new file mode 100644 index 0000000000..0ac110c663 --- /dev/null +++ b/Tests/LibWeb/Text/input/geometry/dommatrix-rotate.html @@ -0,0 +1,33 @@ + + diff --git a/Userland/Libraries/LibWeb/Geometry/DOMMatrix.cpp b/Userland/Libraries/LibWeb/Geometry/DOMMatrix.cpp index 5d3a3f219b..5d2e5177cf 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMMatrix.cpp +++ b/Userland/Libraries/LibWeb/Geometry/DOMMatrix.cpp @@ -371,6 +371,67 @@ JS::NonnullGCPtr DOMMatrix::scale3d_self(Optional scale, Opti return *this; } +// https://drafts.fxtf.org/geometry/#dom-dommatrix-rotateself +JS::NonnullGCPtr DOMMatrix::rotate_self(Optional rot_x, Optional rot_y, Optional rot_z) +{ + // 1. If rotY and rotZ are both missing, set rotZ to the value of rotX and set rotX and rotY to 0. + if (!rot_y.has_value() && !rot_z.has_value()) { + rot_z = rot_x; + rot_x = 0; + rot_y = 0; + } + + // 2. If rotY is still missing, set rotY to 0. + if (!rot_y.has_value()) + rot_y = 0; + + // 3. If rotZ is still missing, set rotZ to 0. + if (!rot_z.has_value()) + rot_z = 0; + + // 4. If rotX or rotY are not 0 or -0, set is 2D of the current matrix to false. + if (rot_x != 0 || rot_x != -0 || rot_y != 0 || rot_y != -0) + m_is_2d = false; + + // 5. Post-multiply a rotation transformation on the current matrix around the vector 0, 0, 1 by the specified rotation rotZ in degrees. The 3D rotation matrix is described in CSS Transforms with alpha = rotZ in degrees. [CSS3-TRANSFORMS] + m_matrix = m_matrix * Gfx::rotation_matrix(Vector3 { 0.0, 0.0, 1.0 }, AK::to_radians(rot_z.value())); + + // 6. Post-multiply a rotation transformation on the current matrix around the vector 0, 1, 0 by the specified rotation rotY in degrees. The 3D rotation matrix is described in CSS Transforms with alpha = rotY in degrees. [CSS3-TRANSFORMS] + m_matrix = m_matrix * Gfx::rotation_matrix(Vector3 { 0.0, 1.0, 0.0 }, AK::to_radians(rot_y.value())); + + // 7. Post-multiply a rotation transformation on the current matrix around the vector 1, 0, 0 by the specified rotation rotX in degrees. The 3D rotation matrix is described in CSS Transforms with alpha = rotX in degrees. [CSS3-TRANSFORMS] + m_matrix = m_matrix * Gfx::rotation_matrix(Vector3 { 1.0, 0.0, 0.0 }, AK::to_radians(rot_x.value())); + + // 8. Return the current matrix. + return *this; +} + +JS::NonnullGCPtr DOMMatrix::rotate_from_vector_self(Optional x, Optional y) +{ + // 1. Post-multiply a rotation transformation on the current matrix. + // The rotation angle is determined by the angle between the vector (1,0)T and (x,y)T in the clockwise direction. If x and y should both be 0 or -0, the angle is specified as 0. + double angle = (x == 0 || x == -0) && (y == 0 || y == -0) ? 0.0 : atan2(y.value_or(0), x.value_or(0)); + + // The 2D rotation matrix is described in CSS Transforms where alpha is the angle between the vector (1,0)T and (x,y)T in degrees. [CSS3-TRANSFORMS] + m_matrix = m_matrix * Gfx::rotation_matrix(Vector3 { 0.0, 0.0, 1.0 }, angle); + + // 2. Return the current matrix. + return *this; +} + +JS::NonnullGCPtr DOMMatrix::rotate_axis_angle_self(Optional x, Optional y, Optional z, Optional angle) +{ + // 1. Post-multiply a rotation transformation on the current matrix around the specified vector x, y, z by the specified rotation angle in degrees. The 3D rotation matrix is described in CSS Transforms with alpha = angle in degrees. [CSS3-TRANSFORMS] + m_matrix = m_matrix * Gfx::rotation_matrix(Vector3 { x.value_or(0), y.value_or(0), z.value_or(0) }.normalized(), AK::to_radians(angle.value())); + + // 2. If x or y are not 0 or -0, set is 2D of the current matrix to false. + if (x != 0 || x != -0 || y != 0 || y != -0) + m_is_2d = false; + + // 3. Return the current matrix. + return *this; +} + // https://drafts.fxtf.org/geometry/#dom-dommatrix-skewxself JS::NonnullGCPtr DOMMatrix::skew_x_self(double sx) { diff --git a/Userland/Libraries/LibWeb/Geometry/DOMMatrix.h b/Userland/Libraries/LibWeb/Geometry/DOMMatrix.h index 6f9501b939..16ac205006 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMMatrix.h +++ b/Userland/Libraries/LibWeb/Geometry/DOMMatrix.h @@ -54,6 +54,9 @@ public: JS::NonnullGCPtr translate_self(Optional tx, Optional ty, Optional tz); JS::NonnullGCPtr scale_self(Optional scale_x, Optional scale_y, Optional scale_z, Optional origin_x, Optional origin_y, Optional origin_z); JS::NonnullGCPtr scale3d_self(Optional scale, Optional origin_x, Optional origin_y, Optional origin_z); + JS::NonnullGCPtr rotate_self(Optional rot_x, Optional rot_y, Optional rot_z); + JS::NonnullGCPtr rotate_from_vector_self(Optional x, Optional y); + JS::NonnullGCPtr rotate_axis_angle_self(Optional x, Optional y, Optional z, Optional angle); JS::NonnullGCPtr skew_x_self(double sx = 0); JS::NonnullGCPtr skew_y_self(double sy = 0); JS::NonnullGCPtr invert_self(); diff --git a/Userland/Libraries/LibWeb/Geometry/DOMMatrix.idl b/Userland/Libraries/LibWeb/Geometry/DOMMatrix.idl index 20f66bea45..c225218172 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMMatrix.idl +++ b/Userland/Libraries/LibWeb/Geometry/DOMMatrix.idl @@ -41,9 +41,9 @@ interface DOMMatrix : DOMMatrixReadOnly { DOMMatrix translateSelf(optional unrestricted double tx = 0, optional unrestricted double ty = 0, optional unrestricted double tz = 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); + DOMMatrix rotateSelf(optional unrestricted double rotX = 0, optional unrestricted double rotY, optional unrestricted double rotZ); + DOMMatrix rotateFromVectorSelf(optional unrestricted double x = 0, optional unrestricted double y = 0); + DOMMatrix rotateAxisAngleSelf(optional unrestricted double x = 0, optional unrestricted double y = 0, optional unrestricted double z = 0, optional unrestricted double angle = 0); DOMMatrix skewXSelf(optional unrestricted double sx = 0); DOMMatrix skewYSelf(optional unrestricted double sy = 0); DOMMatrix invertSelf(); diff --git a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp index a832cdf998..82df8aff53 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp +++ b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.cpp @@ -307,6 +307,36 @@ JS::NonnullGCPtr DOMMatrixReadOnly::scale3d(Optional scale, O return result->scale3d_self(scale, origin_x, origin_y, origin_z); } +JS::NonnullGCPtr DOMMatrixReadOnly::rotate(Optional rot_x, Optional rot_y, Optional rot_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 rotateSelf() transformation on result with the arguments rotX, rotY, rotZ. + // 3. Return result. + return result->rotate_self(rot_x, rot_y, rot_z); +} + +JS::NonnullGCPtr DOMMatrixReadOnly::rotate_from_vector(Optional x, Optional 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 rotateFromVectorSelf() transformation on result with the arguments x, y. + // 3. Return result. + return result->rotate_from_vector_self(x, y); +} + +JS::NonnullGCPtr DOMMatrixReadOnly::rotate_axis_angle(Optional x, Optional y, Optional z, Optional angle) +{ + // 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 rotateAxisAngleSelf() transformation on result with the arguments x, y, z, angle. + // 3. Return result. + return result->rotate_axis_angle_self(x, y, z, angle); +} + // https://drafts.fxtf.org/geometry/#dom-dommatrixreadonly-skewx JS::NonnullGCPtr DOMMatrixReadOnly::skew_x(double sx) const { diff --git a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.h b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.h index 1cb3017bec..cf93290898 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.h +++ b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.h @@ -89,6 +89,9 @@ public: 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 = {}); diff --git a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.idl b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.idl index 772a8596b0..d56ecbf5bd 100644 --- a/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.idl +++ b/Userland/Libraries/LibWeb/Geometry/DOMMatrixReadOnly.idl @@ -43,9 +43,9 @@ interface DOMMatrixReadOnly { [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); + [NewObject] DOMMatrix rotate(optional unrestricted double rotX = 0, optional unrestricted double rotY, optional unrestricted double rotZ); + [NewObject] DOMMatrix rotateFromVector(optional unrestricted double x = 0, optional unrestricted double y = 0); + [NewObject] DOMMatrix rotateAxisAngle(optional unrestricted double x = 0, optional unrestricted double y = 0, optional unrestricted double z = 0, optional unrestricted double angle = 0); [NewObject] DOMMatrix skewX(optional unrestricted double sx = 0); [NewObject] DOMMatrix skewY(optional unrestricted double sy = 0); [NewObject] DOMMatrix multiply(optional DOMMatrixInit other = {});