Commit 18d38f29 authored by Kevin Ellis's avatar Kevin Ellis Committed by Commit Bot

Simplify interpolation of 2-D matrix transforms.

The decomposition of a transformation matrix into translations, rotation, scale and skew transforms is not unique. In some cases, the generalized 3-D decomposition does not align with the working draft for CSS transforms (https://drafts.csswg.org/css-transforms/).



In the special case where the transforms being interpolated are both 2-D, a simplified model provides more restricted set of decomposition transforms with less computational overhead.

Bug: 797472
Change-Id: I2b8ba99fe02c2eef878d94f5dfaea55c39652759
Reviewed-on: https://chromium-review.googlesource.com/c/1332253
Commit-Queue: Kevin Ellis <kevers@chromium.org>
Commit-Queue: Ian Vollick <vollick@chromium.org>
Reviewed-by: default avatarIan Vollick <vollick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613191}
parent 914caad0
......@@ -11,3 +11,12 @@ include_rules = [
"+third_party/blink/renderer/platform/json",
"+third_party/blink/renderer/platform/wtf",
]
specific_include_rules = {
# Additional allowed includes for tests.
".*_test(_.*)?\.(cc|h)" : [
# Test harness may use cc geometry test utilities.
# Avoid reimplementing fuzzy matrix comparison.
"+cc/test/geometry_test_utils.h"
],
}
......@@ -1713,11 +1713,28 @@ static inline void BlendFloat(double& from, double to, double progress) {
from = from + (to - from) * progress;
}
bool TransformationMatrix::Is2dTransform() const {
if (!IsFlat())
return false;
// Check perspective.
if (matrix_[0][3] != 0 || matrix_[1][3] != 0 || matrix_[2][3] != 0 ||
matrix_[3][3] != 1)
return false;
return true;
}
void TransformationMatrix::Blend(const TransformationMatrix& from,
double progress) {
if (from.IsIdentity() && IsIdentity())
return;
if (from.Is2dTransform() && Is2dTransform()) {
Blend2D(from, progress);
return;
}
// decompose
DecomposedType from_decomp;
DecomposedType to_decomp;
......@@ -1748,6 +1765,40 @@ void TransformationMatrix::Blend(const TransformationMatrix& from,
Recompose(from_decomp);
}
void TransformationMatrix::Blend2D(const TransformationMatrix& from,
double progress) {
// Decompose into scale, rotate, translate and skew transforms.
Decomposed2dType from_decomp;
Decomposed2dType to_decomp;
if (!from.Decompose2D(from_decomp) || !Decompose2D(to_decomp)) {
if (progress < 0.5)
*this = from;
return;
}
// Take the shorter of the clockwise or counter-clockwise paths.
double rotation = abs(from_decomp.angle - to_decomp.angle);
DCHECK(rotation < 2 * M_PI);
if (rotation > M_PI) {
if (from_decomp.angle > to_decomp.angle) {
from_decomp.angle -= 2 * M_PI;
} else {
to_decomp.angle -= 2 * M_PI;
}
}
// Interpolate.
BlendFloat(from_decomp.scale_x, to_decomp.scale_x, progress);
BlendFloat(from_decomp.scale_y, to_decomp.scale_y, progress);
BlendFloat(from_decomp.skew_xy, to_decomp.skew_xy, progress);
BlendFloat(from_decomp.translate_x, to_decomp.translate_x, progress);
BlendFloat(from_decomp.translate_y, to_decomp.translate_y, progress);
BlendFloat(from_decomp.angle, to_decomp.angle, progress);
// Recompose.
Recompose2D(from_decomp);
}
bool TransformationMatrix::Decompose(DecomposedType& decomp) const {
if (IsIdentity()) {
memset(&decomp, 0, sizeof(decomp));
......@@ -1762,6 +1813,100 @@ bool TransformationMatrix::Decompose(DecomposedType& decomp) const {
return true;
}
// Decompose a 2D transformation matrix of the form:
// [m11 m21 0 m41]
// [m12 m22 0 m42]
// [ 0 0 1 0 ]
// [ 0 0 0 1 ]
//
// The decomposition is of the form:
// M = translate * rotate * skew * scale
// [1 0 0 Tx] [cos(R) -sin(R) 0 0] [1 K 0 0] [Sx 0 0 0]
// = [0 1 0 Ty] [sin(R) cos(R) 0 0] [0 1 0 0] [0 Sy 0 0]
// [0 0 1 0 ] [ 0 0 1 0] [0 0 1 0] [0 0 1 0]
// [0 0 0 1 ] [ 0 0 0 1] [0 0 0 1] [0 0 0 1]
//
bool TransformationMatrix::Decompose2D(Decomposed2dType& decomp) const {
if (!Is2dTransform()) {
LOG(ERROR) << "2-D decomposition cannot be performed on a 3-D transform.";
return false;
}
double m11 = matrix_[0][0];
double m21 = matrix_[1][0];
double m12 = matrix_[0][1];
double m22 = matrix_[1][1];
double determinant = m11 * m22 - m12 * m21;
// Test for matrix being singular.
if (determinant == 0) {
return false;
}
// Translation transform.
// [m11 m21 0 m41] [1 0 0 Tx] [m11 m21 0 0]
// [m12 m22 0 m42] = [0 1 0 Ty] [m12 m22 0 0]
// [ 0 0 1 0 ] [0 0 1 0 ] [ 0 0 1 0]
// [ 0 0 0 1 ] [0 0 0 1 ] [ 0 0 0 1]
decomp.translate_x = matrix_[3][0];
decomp.translate_y = matrix_[3][1];
// For the remainder of the decomposition process, we can focus on the upper
// 2x2 submatrix
// [m11 m21] = [cos(R) -sin(R)] [1 K] [Sx 0 ]
// [m12 m22] [sin(R) cos(R)] [0 1] [0 Sy]
// = [Sx*cos(R) Sy*(K*cos(R) - sin(R))]
// [Sx*sin(R) Sy*(K*sin(R) + cos(R))]
// Determine sign of the x and y scale.
decomp.scale_x = 1;
decomp.scale_y = 1;
if (determinant < 0) {
// If the determinant is negative, we need to flip either the x or y scale.
// Flipping both is equivalent to rotating by 180 degrees.
// Flip the axis with the minimum unit vector dot product.
if (m11 < m22) {
decomp.scale_x = -decomp.scale_x;
} else {
decomp.scale_y = -decomp.scale_y;
}
}
// X Scale.
// m11^2 + m12^2 = Sx^2*(cos^2(R) + sin^2(R)) = Sx^2.
// Sx = +/-sqrt(m11^2 + m22^2)
decomp.scale_x *= sqrt(m11 * m11 + m12 * m12);
m11 /= decomp.scale_x;
m12 /= decomp.scale_x;
// Post normalization, the submatrix is now of the form:
// [m11 m21] = [cos(R) Sy*(K*cos(R) - sin(R))]
// [m12 m22] [sin(R) Sy*(K*sin(R) + cos(R))]
// XY Shear.
// m11 * m21 + m12 * m22 = Sy*K*cos^2(R) - Sy*sin(R)*cos(R) +
// Sy*K*sin^2(R) + Sy*cos(R)*sin(R)
// = Sy*K
double scaledShear = m11 * m21 + m12 * m22;
m21 -= m11 * scaledShear;
m22 -= m12 * scaledShear;
// Post normalization, the submatrix is now of the form:
// [m11 m21] = [cos(R) -Sy*sin(R)]
// [m12 m22] [sin(R) Sy*cos(R)]
// Y Scale.
// Similar process to determining x-scale.
decomp.scale_y *= sqrt(m21 * m21 + m22 * m22);
m21 /= decomp.scale_y;
m22 /= decomp.scale_y;
decomp.skew_xy = scaledShear / decomp.scale_y;
// Rotation transform.
decomp.angle = atan2(m12, m11);
return true;
}
void TransformationMatrix::Recompose(const DecomposedType& decomp) {
MakeIdentity();
......@@ -1816,6 +1961,32 @@ void TransformationMatrix::Recompose(const DecomposedType& decomp) {
Scale3d(decomp.scale_x, decomp.scale_y, decomp.scale_z);
}
void TransformationMatrix::Recompose2D(const Decomposed2dType& decomp) {
MakeIdentity();
// Translate transform.
SetM41(decomp.translate_x);
SetM42(decomp.translate_y);
// Rotate transform.
double cosAngle = cos(decomp.angle);
double sinAngle = sin(decomp.angle);
SetM11(cosAngle);
SetM21(-sinAngle);
SetM12(sinAngle);
SetM22(cosAngle);
// skew transform.
if (decomp.skew_xy) {
TransformationMatrix skewTransform;
skewTransform.SetM21(decomp.skew_xy);
Multiply(skewTransform);
}
// Scale transform.
Scale3d(decomp.scale_x, decomp.scale_y, 1);
}
bool TransformationMatrix::IsIntegerTranslation() const {
if (!IsIdentityOrTranslation())
return false;
......
......@@ -393,10 +393,20 @@ class PLATFORM_EXPORT TransformationMatrix {
double perspective_x, perspective_y, perspective_z, perspective_w;
} DecomposedType;
// Decompose 2-D transform matrix into its component parts.
typedef struct {
double scale_x, scale_y;
double skew_xy;
double translate_x, translate_y;
double angle;
} Decomposed2dType;
WARN_UNUSED_RESULT bool Decompose(DecomposedType&) const;
WARN_UNUSED_RESULT bool Decompose2D(Decomposed2dType&) const;
void Recompose(const DecomposedType&);
void Recompose2D(const Decomposed2dType&);
void Blend(const TransformationMatrix& from, double progress);
void Blend2D(const TransformationMatrix& from, double progress);
bool IsAffine() const {
return M13() == 0 && M14() == 0 && M23() == 0 && M24() == 0 && M31() == 0 &&
......@@ -475,6 +485,8 @@ class PLATFORM_EXPORT TransformationMatrix {
matrix_[2][3] == 0 && matrix_[3][2] == 0 && matrix_[3][3] == 1;
}
bool Is2dTransform() const;
bool IsIntegerTranslation() const;
// Returns true if axis-aligned 2d rects will remain axis-aligned after being
......
......@@ -4,10 +4,27 @@
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
#include "cc/test/geometry_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "ui/gfx/transform.h"
namespace blink {
// Allow non-zero tolerance when comparing floating point results to
// accommodate precision errors.
const double kFloatingPointErrorTolerance = 1e-6;
#define EXPECT_TRANSFORMATION_MATRIX(expected, actual) \
do { \
SCOPED_TRACE(""); \
cc::ExpectTransformationMatrixNear( \
TransformationMatrix::ToTransform(expected), \
TransformationMatrix::ToTransform(actual), \
kFloatingPointErrorTolerance); \
} while (false)
#define EXPECT_FLOAT(expected, actual) \
EXPECT_NEAR(expected, actual, kFloatingPointErrorTolerance)
TEST(TransformationMatrixTest, NonInvertableBlendTest) {
TransformationMatrix from;
......@@ -330,4 +347,75 @@ TEST(TransformationMatrix, IsInvertible) {
EXPECT_FALSE(TransformationMatrix().Scale(0).IsInvertible());
}
TEST(TransformationMatrixTest, Blend2dXFlipTest) {
// Test 2D x-flip (crbug.com/797472).
TransformationMatrix from;
from.SetMatrix(1, 0, 0, 1, 100, 150);
TransformationMatrix to;
to.SetMatrix(-1, 0, 0, 1, 400, 150);
EXPECT_TRUE(from.Is2dTransform());
EXPECT_TRUE(to.Is2dTransform());
// OK for interpolated transform to be degenerate.
TransformationMatrix result = to;
result.Blend(from, 0.5);
TransformationMatrix expected;
expected.SetMatrix(0, 0, 0, 1, 250, 150);
EXPECT_TRANSFORMATION_MATRIX(expected, result);
}
TEST(TransformationMatrixTest, Blend2dRotationDirectionTest) {
// Interpolate taking shorter rotation path.
TransformationMatrix from;
from.SetMatrix(-0.5, 0.86602575498, -0.86602575498, -0.5, 0, 0);
TransformationMatrix to;
to.SetMatrix(-0.5, -0.86602575498, 0.86602575498, -0.5, 0, 0);
// Expect clockwise Rotation.
TransformationMatrix result = to;
result.Blend(from, 0.5);
TransformationMatrix expected;
expected.SetMatrix(-1, 0, 0, -1, 0, 0);
EXPECT_TRANSFORMATION_MATRIX(expected, result);
// Reverse from and to.
// Expect same midpoint with counter-clockwise rotation.
result = from;
result.Blend(to, 0.5);
EXPECT_TRANSFORMATION_MATRIX(expected, result);
}
TEST(TransformationMatrixTest, Decompose2dShearTest) {
// Test that x and y-shear transforms are properly decomposed.
// The canonical decomposition is: transform, rotate, x-axis shear, scale.
TransformationMatrix transformShearX;
transformShearX.SetMatrix(1, 0, 1, 1, 0, 0);
TransformationMatrix::Decomposed2dType decompShearX;
EXPECT_TRUE(transformShearX.Decompose2D(decompShearX));
EXPECT_FLOAT(1, decompShearX.scale_x);
EXPECT_FLOAT(1, decompShearX.scale_y);
EXPECT_FLOAT(0, decompShearX.translate_x);
EXPECT_FLOAT(0, decompShearX.translate_y);
EXPECT_FLOAT(0, decompShearX.angle);
EXPECT_FLOAT(1, decompShearX.skew_xy);
TransformationMatrix recompShearX;
recompShearX.Recompose2D(decompShearX);
EXPECT_TRANSFORMATION_MATRIX(transformShearX, recompShearX);
TransformationMatrix transformShearY;
transformShearY.SetMatrix(1, 1, 0, 1, 0, 0);
TransformationMatrix::Decomposed2dType decompShearY;
EXPECT_TRUE(transformShearY.Decompose2D(decompShearY));
EXPECT_FLOAT(sqrt(2), decompShearY.scale_x);
EXPECT_FLOAT(1 / sqrt(2), decompShearY.scale_y);
EXPECT_FLOAT(0, decompShearY.translate_x);
EXPECT_FLOAT(0, decompShearY.translate_y);
EXPECT_FLOAT(M_PI / 4, decompShearY.angle);
EXPECT_FLOAT(1, decompShearY.skew_xy);
TransformationMatrix recompShearY;
recompShearY.Recompose2D(decompShearY);
EXPECT_TRANSFORMATION_MATRIX(transformShearY, recompShearY);
}
} // namespace blink
......@@ -507,18 +507,18 @@ PASS touch-action (type: discrete) has testAccumulation function
PASS touch-action: "none" onto "auto"
PASS touch-action: "auto" onto "none"
PASS transform (type: transformList) has testAccumulation function
FAIL transform: translate assert_approx_equals: expected matrix(1,0,0,1,-100,0) but got matrix(1, 0, 0, 1, -200, 0): The value should be matrix(1,0,0,1,-100,0) at 0ms but got matrix(1, 0, 0, 1, -200, 0) expected -100 +/- 0.0001 but got -200
FAIL transform: rotate assert_approx_equals: expected matrix(0.7071067811865476,-0.7071067811865475,0.7071067811865475,0.7071067811865476,0,0) but got matrix(6.12323e-17, -1, 1, 6.12323e-17, 0, 0): The value should be matrix(0.7071067811865476,-0.7071067811865475,0.7071067811865475,0.7071067811865476,0,0) at 0ms but got matrix(6.12323e-17, -1, 1, 6.12323e-17, 0, 0) expected 0.7071067811865476 +/- 0.0001 but got 6.12323e-17
FAIL transform: scale assert_approx_equals: expected matrix(-2,0,0,-2,0,0) but got matrix(-3, 0, 0, -3, 0, 0): The value should be matrix(-2,0,0,-2,0,0) at 0ms but got matrix(-3, 0, 0, -3, 0, 0) expected -2 +/- 0.0001 but got -3
FAIL transform: skew assert_approx_equals: expected matrix(1,0.5773502691896257,-0.36397023426620234,1,0,0) but got matrix(1, 0.36397, -0.57735, 1, 0, 0): The value should be matrix(1,0.5773502691896257,-0.36397023426620234,1,0,0) at 0ms but got matrix(1, 0.36397, -0.57735, 1, 0, 0) expected 0.5773502691896257 +/- 0.0001 but got 0.36397
FAIL transform: rotate on translate assert_approx_equals: expected matrix(0,1,-1,0,100,0) but got matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0): The value should be matrix(0,1,-1,0,100,0) at 0ms but got matrix(6.12323e-17, 1, -1, 6.12323e-17, 0, 0) expected 100 +/- 0.0001 but got 0
FAIL transform: translate on rotate assert_approx_equals: expected matrix(0,1,-1,0,100,0) but got matrix(1, 0, 0, 1, 100, 0): The value should be matrix(0,1,-1,0,100,0) at 0ms but got matrix(1, 0, 0, 1, 100, 0) expected 0 +/- 0.0001 but got 1
FAIL transform: rotate and translate on rotate assert_approx_equals: expected matrix(6.123233995736766e-17,1,-1,6.123233995736766e-17,0,0) but got matrix(0.707107, 0.707107, -0.707107, 0.707107, 0, 0): The value should be matrix(6.123233995736766e-17,1,-1,6.123233995736766e-17,0,0) at 0ms but got matrix(0.707107, 0.707107, -0.707107, 0.707107, 0, 0) expected 6.123233995736766e-17 +/- 0.0001 but got 0.707107
FAIL transform: rotate on rotate and translate assert_approx_equals: expected matrix(6.123233995736766e-17,1,-1,6.123233995736766e-17,6.123233995736766e-15,100) but got matrix(0.707107, 0.707107, -0.707107, 0.707107, 0, 0): The value should be matrix(6.123233995736766e-17,1,-1,6.123233995736766e-17,6.123233995736766e-15,100) at 0ms but got matrix(0.707107, 0.707107, -0.707107, 0.707107, 0, 0) expected 6.123233995736766e-17 +/- 0.0001 but got 0.707107
FAIL transform: matrix assert_approx_equals: expected matrix(0,1,-1,0,100,0) but got matrix(1, 0, 0, 1, 100, 0): The value should be matrix(0,1,-1,0,100,0) at 0ms but got matrix(1, 0, 0, 1, 100, 0) expected 0 +/- 0.0001 but got 1
FAIL transform: rotate3d assert_approx_equals: expected matrix3d(0.8535533905932737,0.1464466094067262,0.5,0,0.1464466094067262,0.8535533905932737,-0.5,0,-0.5,0.5,0.7071067811865476,0,0,0,0,1) but got matrix3d(0.5, 0.5, 0.707107, 0, 0.5, 0.5, -0.707107, 0, -0.707107, 0.707107, 6.12323e-17, 0, 0, 0, 0, 1): The value should be matrix3d(0.8535533905932737,0.1464466094067262,0.5,0,0.1464466094067262,0.8535533905932737,-0.5,0,-0.5,0.5,0.7071067811865476,0,0,0,0,1) at 0ms but got matrix3d(0.5, 0.5, 0.707107, 0, 0.5, 0.5, -0.707107, 0, -0.707107, 0.707107, 6.12323e-17, 0, 0, 0, 0, 1) expected 0.8535533905932737 +/- 0.0001 but got 0.5
FAIL transform: matrix3d assert_approx_equals: expected matrix3d(0.8535533905932737,0.1464466094067262,0.5,0,0.1464466094067262,0.8535533905932737,-0.5,0,-0.5,0.5,0.7071067811865476,0,0,0,0,1) but got matrix3d(0.5, 0.5, 0.707107, 0, 0.5, 0.5, -0.707107, 0, -0.707107, 0.707107, 4.44089e-16, 0, 0, 0, 0, 1): The value should be matrix3d(0.8535533905932737,0.1464466094067262,0.5,0,0.1464466094067262,0.8535533905932737,-0.5,0,-0.5,0.5,0.7071067811865476,0,0,0,0,1) at 0ms but got matrix3d(0.5, 0.5, 0.707107, 0, 0.5, 0.5, -0.707107, 0, -0.707107, 0.707107, 4.44089e-16, 0, 0, 0, 0, 1) expected 0.8535533905932737 +/- 0.0001 but got 0.5
FAIL transform: none assert_equals: dimension of the matrix: The value should be matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,1) at 0ms but got matrix(1, 0, 0, 1, 0, 0) expected 16 but got 6
FAIL transform: translate assert_approx_equals: expected matrix(1, 0, 0, 1, -100, 0) but got matrix(1, 0, 0, 1, -200, 0): The value should be matrix(1, 0, 0, 1, -100, 0) at 0ms but got matrix(1, 0, 0, 1, -200, 0) expected -100 +/- 0.0001 but got -200
FAIL transform: rotate assert_approx_equals: expected matrix(0.707107, -0.707107, 0.707107, 0.707107, 0, 0) but got matrix(0, -1, 1, 0, 0, 0): The value should be matrix(0.707107, -0.707107, 0.707107, 0.707107, 0, 0) at 0ms but got matrix(0, -1, 1, 0, 0, 0) expected 0.707107 +/- 0.0001 but got 0
FAIL transform: scale assert_approx_equals: expected matrix(-2, 0, 0, -2, 0, 0) but got matrix(-3, 0, 0, -3, 0, 0): The value should be matrix(-2, 0, 0, -2, 0, 0) at 0ms but got matrix(-3, 0, 0, -3, 0, 0) expected -2 +/- 0.0001 but got -3
FAIL transform: skew assert_approx_equals: expected matrix(1, 0.57735, -0.36397, 1, 0, 0) but got matrix(1, 0.36397, -0.57735, 1, 0, 0): The value should be matrix(1, 0.57735, -0.36397, 1, 0, 0) at 0ms but got matrix(1, 0.36397, -0.57735, 1, 0, 0) expected 0.57735 +/- 0.0001 but got 0.36397
FAIL transform: rotate on translate assert_approx_equals: expected matrix(0, 1, -1, 0, 100, 0) but got matrix(0, 1, -1, 0, 0, 0): The value should be matrix(0, 1, -1, 0, 100, 0) at 0ms but got matrix(0, 1, -1, 0, 0, 0) expected 100 +/- 0.0001 but got 0
FAIL transform: translate on rotate assert_approx_equals: expected matrix(0, 1, -1, 0, 100, 0) but got matrix(1, 0, 0, 1, 100, 0): The value should be matrix(0, 1, -1, 0, 100, 0) at 0ms but got matrix(1, 0, 0, 1, 100, 0) expected 0 +/- 0.0001 but got 1
FAIL transform: rotate and translate on rotate assert_approx_equals: expected matrix(0, 1, -1, 0, 0, 0) but got matrix(0.707107, 0.707107, -0.707107, 0.707107, 0, 0): The value should be matrix(0, 1, -1, 0, 0, 0) at 0ms but got matrix(0.707107, 0.707107, -0.707107, 0.707107, 0, 0) expected 0 +/- 0.0001 but got 0.707107
FAIL transform: rotate on rotate and translate assert_approx_equals: expected matrix(0, 1, -1, 0, 0, 100) but got matrix(0.707107, 0.707107, -0.707107, 0.707107, 0, 0): The value should be matrix(0, 1, -1, 0, 0, 100) at 0ms but got matrix(0.707107, 0.707107, -0.707107, 0.707107, 0, 0) expected 0 +/- 0.0001 but got 0.707107
FAIL transform: matrix assert_approx_equals: expected matrix(0, 1, -1, 0, 100, 0) but got matrix(1, 0, 0, 1, 100, 0): The value should be matrix(0, 1, -1, 0, 100, 0) at 0ms but got matrix(1, 0, 0, 1, 100, 0) expected 0 +/- 0.0001 but got 1
FAIL transform: rotate3d assert_approx_equals: expected matrix3d(0.853553, 0.146447, 0.5, 0, 0.146447, 0.853553, -0.5, 0, -0.5, 0.5, 0.707107, 0, 0, 0, 0, 1) but got matrix3d(0.5, 0.5, 0.707107, 0, 0.5, 0.5, -0.707107, 0, -0.707107, 0.707107, 0, 0, 0, 0, 0, 1): The value should be matrix3d(0.853553, 0.146447, 0.5, 0, 0.146447, 0.853553, -0.5, 0, -0.5, 0.5, 0.707107, 0, 0, 0, 0, 1) at 0ms but got matrix3d(0.5, 0.5, 0.707107, 0, 0.5, 0.5, -0.707107, 0, -0.707107, 0.707107, 0, 0, 0, 0, 0, 1) expected 0.853553 +/- 0.0001 but got 0.5
FAIL transform: matrix3d assert_approx_equals: expected matrix3d(0.853553, 0.146447, 0.5, 0, 0.146447, 0.853553, -0.5, 0, -0.5, 0.5, 0.707107, 0, 0, 0, 0, 1) but got matrix3d(0.5, 0.5, 0.707107, 0, 0.5, 0.5, -0.707107, 0, -0.707107, 0.707107, 0, 0, 0, 0, 0, 1): The value should be matrix3d(0.853553, 0.146447, 0.5, 0, 0.146447, 0.853553, -0.5, 0, -0.5, 0.5, 0.707107, 0, 0, 0, 0, 1) at 0ms but got matrix3d(0.5, 0.5, 0.707107, 0, 0.5, 0.5, -0.707107, 0, -0.707107, 0.707107, 0, 0, 0, 0, 0, 1) expected 0.853553 +/- 0.0001 but got 0.5
FAIL transform: none assert_equals: dimension of the matrix: The value should be matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1) at 0ms but got matrix(1, 0, 0, 1, 0, 0) expected 16 but got 6
PASS transform: non-invertible matrices (non-invertible onto invertible)
PASS transform: non-invertible matrices (invertible onto non-invertible)
PASS transform: non-invertible matrices in matched transform lists (non-invertible onto invertible)
......
This is a testharness.js-based test.
Found 701 tests; 643 PASS, 58 FAIL, 0 TIMEOUT, 0 NOTRUN.
Found 701 tests; 645 PASS, 56 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS Setup
PASS align-content (type: discrete) has testInterpolation function
PASS align-content uses discrete animation when animating between "flex-start" and "flex-end" with linear easing
......@@ -641,16 +641,16 @@ PASS transform: scale
PASS transform: skew
PASS transform: rotate and translate
PASS transform: translate and rotate
FAIL transform: extend shorter list (from) assert_approx_equals: expected matrix(-1,0,0,-1,-50,0) but got matrix(1, 0, 0, 1, 50, -3.67394e-14): The value should be matrix(-1,0,0,-1,-50,0) at 500ms but got matrix(1, 0, 0, 1, 50, -3.67394e-14) expected -1 +/- 0.0001 but got 1
FAIL transform: extend shorter list (to) assert_approx_equals: expected matrix(-1,0,0,-1,-50,0) but got matrix(1, 0, 0, 1, 50, 0): The value should be matrix(-1,0,0,-1,-50,0) at 500ms but got matrix(1, 0, 0, 1, 50, 0) expected -1 +/- 0.0001 but got 1
FAIL transform: mismatch order of translate and rotate assert_approx_equals: expected matrix(-0.7071067811865475,0.7071067811865476,-0.7071067811865476,-0.7071067811865475,100,50) but got matrix(0.707107, -0.707107, 0.707107, 0.707107, 100, 50): The value should be matrix(-0.7071067811865475,0.7071067811865476,-0.7071067811865476,-0.7071067811865475,100,50) at 500ms but got matrix(0.707107, -0.707107, 0.707107, 0.707107, 100, 50) expected -0.7071067811865475 +/- 0.0001 but got 0.707107
FAIL transform: matrix assert_approx_equals: expected matrix(-0.7071067811865475,0.7071067811865476,-0.7071067811865476,-0.7071067811865475,100,50) but got matrix(0.707107, -0.707107, 0.707107, 0.707107, 100, 50): The value should be matrix(-0.7071067811865475,0.7071067811865476,-0.7071067811865476,-0.7071067811865475,100,50) at 500ms but got matrix(0.707107, -0.707107, 0.707107, 0.707107, 100, 50) expected -0.7071067811865475 +/- 0.0001 but got 0.707107
FAIL transform: extend shorter list (from) assert_approx_equals: expected matrix(-1, 0, 0, -1, -50, 0) but got matrix(1, 0, 0, 1, 50, 0): The value should be matrix(-1, 0, 0, -1, -50, 0) at 500ms but got matrix(1, 0, 0, 1, 50, 0) expected -1 +/- 0.0001 but got 1
FAIL transform: extend shorter list (to) assert_approx_equals: expected matrix(-1, 0, 0, -1, -50, 0) but got matrix(1, 0, 0, 1, 50, 0): The value should be matrix(-1, 0, 0, -1, -50, 0) at 500ms but got matrix(1, 0, 0, 1, 50, 0) expected -1 +/- 0.0001 but got 1
PASS transform: mismatch order of translate and rotate
PASS transform: matrix
PASS transform: rotate3d
PASS transform: matrix3d
PASS transform: mismatched 3D transforms
PASS transform: rotateY
PASS transform: non-invertible matrices
FAIL transform: non-invertible matrices in matched transform lists assert_approx_equals: expected matrix(0,-1,1,0,250,0) but got matrix(0.705995, -0.708217, 0.708217, 0.705995, 274.95, 0): The value should be matrix(0,-1,1,0,250,0) at 499ms but got matrix(0.705995, -0.708217, 0.708217, 0.705995, 274.95, 0) expected 0 +/- 0.0001 but got 0.705995
FAIL transform: non-invertible matrices in matched transform lists assert_approx_equals: expected matrix(0, -1, 1, 0, 250, 0) but got matrix(0.705995, -0.708217, 0.708217, 0.705995, 274.95, 0): The value should be matrix(0, -1, 1, 0, 250, 0) at 499ms but got matrix(0.705995, -0.708217, 0.708217, 0.705995, 274.95, 0) expected 0 +/- 0.0001 but got 0.705995
PASS transform: non-invertible matrices in mismatched transform lists
PASS transform: perspective
PASS transform-box (type: discrete) has testInterpolation function
......
......@@ -1495,12 +1495,34 @@ function testAnimationSamplesWithAnyOrder(animation, idlName, testSamples) {
}
}
function RoundMatrix(style) {
var matrixMatch = style.match(/^(matrix(3d)?)\(.+\)$/);
if (!!matrixMatch) {
var matrixType = matrixMatch[1];
var matrixArgs = style.substr(matrixType.length);
var extractmatrix = function(matrixStr) {
var list = [];
var regex = /[+\-]?[0-9]+[.]?[0-9]*(e[+/-][0-9]+)?/g;
var match = undefined;
do {
match = regex.exec(matrixStr);
if (match) {
list.push(parseFloat(parseFloat(match[0]).toFixed(6)));
}
} while (match);
return list;
}
return matrixType + '(' + extractmatrix(matrixArgs).join(', ') + ')';
}
return style;
}
function testAnimationSampleMatrices(animation, idlName, testSamples) {
const target = animation.effect.target;
for (const testSample of testSamples) {
animation.currentTime = testSample.time;
const actual = getComputedStyle(target)[idlName];
const expected = createMatrixFromArray(testSample.expected);
const actual = RoundMatrix(getComputedStyle(target)[idlName]);
const expected = RoundMatrix(createMatrixFromArray(testSample.expected));
assert_matrix_equals(actual, expected,
`The value should be ${expected} at`
+ ` ${testSample.time}ms but got ${actual}`);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment