From a4f9eea8e52a5cf98d602d060ae5fbf24c9bbc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 5 Sep 2018 13:35:06 +0000 Subject: [PATCH] Bug 1488414 - Use decomposition to interpolate matched perspective transform operations. r=birtles Looks like this produces sensible results for interpolation with 0, though I'm not really convinced about the results from, let's say, 1px to 2000px in the attached test-case, I would've expected a linear interpolation from that to go through normal length interpolation. css-transforms-1 says: > Two transform functions with the same name and the same number of arguments > are interpolated numerically without a former conversion. The calculated > value will be of the same transform function type with the same number of > arguments. > > Special rules apply to . Which is what we do... I was going to file a spec issue but turns out that it's already addressed in css-transforms-2: https://drafts.csswg.org/css-transforms-2/#interpolation-of-transform-functions Which says: > The transform functions , matrix3d() and perspective() get > converted into 4x4 matrices first and interpolated as defined in section > Interpolation of Matrices afterwards. Differential Revision: https://phabricator.services.mozilla.com/D4942 --HG-- extra : moz-landing-system : lando --- .../helpers/animated_properties.mako.rs | 24 ++++++++++++++++--- .../style/values/computed/transform.rs | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/servo/components/style/properties/helpers/animated_properties.mako.rs b/servo/components/style/properties/helpers/animated_properties.mako.rs index f6277a212713..437232d386a5 100644 --- a/servo/components/style/properties/helpers/animated_properties.mako.rs +++ b/servo/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/servo/components/style/values/computed/transform.rs b/servo/components/style/values/computed/transform.rs index bbf710c42956..a2849a0d4b35 100644 --- a/servo/components/style/values/computed/transform.rs +++ b/servo/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;