diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index f6277a21271..437232d386a 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -1296,9 +1296,27 @@ impl Animate for ComputedTransformOperation { &TransformOperation::Perspective(ref fd), &TransformOperation::Perspective(ref td), ) => { - Ok(TransformOperation::Perspective( - fd.animate(td, procedure)? - )) + use values::computed::CSSPixelLength; + use values::generics::transform::create_perspective_matrix; + + // From https://drafts.csswg.org/css-transforms-2/#interpolation-of-transform-functions: + // + // The transform functions matrix(), matrix3d() and + // perspective() get converted into 4x4 matrices first and + // interpolated as defined in section Interpolation of + // Matrices afterwards. + // + let from = create_perspective_matrix(fd.px()); + let to = create_perspective_matrix(td.px()); + + let interpolated = + Matrix3D::from(from).animate(&Matrix3D::from(to), procedure)?; + + let decomposed = decompose_3d_matrix(interpolated)?; + let perspective_z = decomposed.perspective.2; + let used_value = + if perspective_z == 0. { 0. } else { -1. / perspective_z }; + Ok(TransformOperation::Perspective(CSSPixelLength::new(used_value))) }, _ if self.is_translate() && other.is_translate() => { self.to_translate_3d().animate(&other.to_translate_3d(), procedure) diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index bbf710c4295..a2849a0d4b3 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -42,6 +42,7 @@ impl TransformOrigin { /// computed value of matrix3d() pub type Matrix3D = generic::Matrix3D; + /// computed value of matrix() pub type Matrix = generic::Matrix;