From ce91c551baa580df59a097c7d229693ca2bb5027 Mon Sep 17 00:00:00 2001 From: ldm0 Date: Sun, 30 Aug 2026 09:34:58 +0800 Subject: [PATCH] fix(geometry): apply DOMMatrix rotations in spec order --- moli-geometry/src/lib.rs | 23 +++++++++++++++++++ moli-geometry/src/matrix.rs | 8 +++---- .../geometry/dompoint-dommatrix-basic.html | 10 ++++---- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/moli-geometry/src/lib.rs b/moli-geometry/src/lib.rs index a392ec526c..a7fb2deec9 100644 --- a/moli-geometry/src/lib.rs +++ b/moli-geometry/src/lib.rs @@ -73,6 +73,29 @@ mod tests { assert_close(product.m43, 0.0); } + #[test] + fn combined_rotation_applies_z_then_y_then_x() { + let combined = DomMatrixComponents::identity().rotated(90.0, 90.0, 90.0); + let sequential = DomMatrixComponents::identity() + .rotated(0.0, 0.0, 90.0) + .rotated(0.0, 90.0, 0.0) + .rotated(90.0, 0.0, 0.0); + + for (actual, expected) in [ + (combined.m11, sequential.m11), + (combined.m12, sequential.m12), + (combined.m13, sequential.m13), + (combined.m21, sequential.m21), + (combined.m22, sequential.m22), + (combined.m23, sequential.m23), + (combined.m31, sequential.m31), + (combined.m32, sequential.m32), + (combined.m33, sequential.m33), + ] { + assert_close(actual, expected); + } + } + #[test] fn css_text_rejects_non_finite_components() { assert_eq!( diff --git a/moli-geometry/src/matrix.rs b/moli-geometry/src/matrix.rs index a21822b153..cd9399dd90 100644 --- a/moli-geometry/src/matrix.rs +++ b/moli-geometry/src/matrix.rs @@ -267,14 +267,14 @@ impl DomMatrixComponents { } pub fn rotated(mut self, rot_x: f64, rot_y: f64, rot_z: f64) -> Self { - if rot_x != 0.0 { - self = self.rotated_axis_angle(1.0, 0.0, 0.0, rot_x); + if rot_z != 0.0 { + self = self.rotated_z(rot_z); } if rot_y != 0.0 { self = self.rotated_axis_angle(0.0, 1.0, 0.0, rot_y); } - if rot_z != 0.0 { - self = self.rotated_z(rot_z); + if rot_x != 0.0 { + self = self.rotated_axis_angle(1.0, 0.0, 0.0, rot_x); } self } diff --git a/moli-wpt-compat/fixtures/wpt/ported/geometry/dompoint-dommatrix-basic.html b/moli-wpt-compat/fixtures/wpt/ported/geometry/dompoint-dommatrix-basic.html index d2689ddfd7..1951bc1737 100644 --- a/moli-wpt-compat/fixtures/wpt/ported/geometry/dompoint-dommatrix-basic.html +++ b/moli-wpt-compat/fixtures/wpt/ported/geometry/dompoint-dommatrix-basic.html @@ -373,16 +373,16 @@ test(function () { assert_approx_equals(zAxis.b, 1, 0.000001); const multiAxis = new DOMMatrix().rotate(45, 45, 0).transformPoint({ x: 0, y: 0, z: 1 }); - assert_approx_equals(multiAxis.x, Math.SQRT1_2, 0.000001); - assert_approx_equals(multiAxis.y, -0.5, 0.000001); + assert_approx_equals(multiAxis.x, 0.5, 0.000001); + assert_approx_equals(multiAxis.y, -Math.SQRT1_2, 0.000001); assert_approx_equals(multiAxis.z, 0.5, 0.000001); const ordered = new DOMMatrix().rotate(30, 40, 50); const explicit = new DOMMatrix() - .rotateAxisAngleSelf(1, 0, 0, 30) + .rotateAxisAngleSelf(0, 0, 1, 50) .rotateAxisAngleSelf(0, 1, 0, 40) - .rotateAxisAngleSelf(0, 0, 1, 50); - assert_matrix_approx_equals(ordered, explicit, "rotate(x, y, z) composes in X then Y then Z order"); + .rotateAxisAngleSelf(1, 0, 0, 30); + assert_matrix_approx_equals(ordered, explicit, "rotate(x, y, z) composes in Z then Y then X order"); }, "DOMMatrix rotate methods honor rotX, rotY, and rotZ"); test(function () {