--- a/layout/style/nsStyleTransformMatrix.cpp
+++ b/layout/style/nsStyleTransformMatrix.cpp
@@ -321,16 +321,23 @@ public:
gfxQuaternion result = gfxQuaternion(scale * aTwo.x,
scale * aTwo.y,
scale * aTwo.z,
cos(theta)) * aOne;
return result.ToMatrix();
}
+ static Matrix4x4 operateForFallback(const Matrix4x4& aMatrix1,
+ const Matrix4x4& aMatrix2,
+ double aProgress)
+ {
+ return aMatrix1;
+ }
+
static Matrix4x4 operateByServo(const Matrix4x4& aMatrix1,
const Matrix4x4& aMatrix2,
double aCount)
{
Matrix4x4 result;
Servo_MatrixTransform_Operate(MatrixTransformOperator::Accumulate,
&aMatrix1.components,
&aMatrix2.components,
@@ -364,16 +371,23 @@ public:
static Matrix4x4 operateForRotate(const gfxQuaternion& aOne,
const gfxQuaternion& aTwo,
double aCoeff)
{
return aOne.Slerp(aTwo, aCoeff).ToMatrix();
}
+ static Matrix4x4 operateForFallback(const Matrix4x4& aMatrix1,
+ const Matrix4x4& aMatrix2,
+ double aProgress)
+ {
+ return aProgress < 0.5 ? aMatrix1 : aMatrix2;
+ }
+
static Matrix4x4 operateByServo(const Matrix4x4& aMatrix1,
const Matrix4x4& aMatrix2,
double aProgress)
{
Matrix4x4 result;
Servo_MatrixTransform_Operate(MatrixTransformOperator::Interpolate,
&aMatrix1.components,
&aMatrix2.components,
@@ -393,36 +407,44 @@ public:
template <typename Operator>
static Matrix4x4
OperateTransformMatrix(const Matrix4x4 &aMatrix1,
const Matrix4x4 &aMatrix2,
double aProgress)
{
// Decompose both matrices
- // TODO: What do we do if one of these returns false (singular matrix)
Point3D scale1(1, 1, 1), translate1;
Point4D perspective1(0, 0, 0, 1);
gfxQuaternion rotate1;
nsStyleTransformMatrix::ShearArray shear1{0.0f, 0.0f, 0.0f};
Point3D scale2(1, 1, 1), translate2;
Point4D perspective2(0, 0, 0, 1);
gfxQuaternion rotate2;
nsStyleTransformMatrix::ShearArray shear2{0.0f, 0.0f, 0.0f};
+ // Check if both matrices are decomposable.
+ bool wasDecomposed;
Matrix matrix2d1, matrix2d2;
if (aMatrix1.Is2D(&matrix2d1) && aMatrix2.Is2D(&matrix2d2)) {
- Decompose2DMatrix(matrix2d1, scale1, shear1, rotate1, translate1);
- Decompose2DMatrix(matrix2d2, scale2, shear2, rotate2, translate2);
+ wasDecomposed =
+ Decompose2DMatrix(matrix2d1, scale1, shear1, rotate1, translate1) &&
+ Decompose2DMatrix(matrix2d2, scale2, shear2, rotate2, translate2);
} else {
- Decompose3DMatrix(aMatrix1, scale1, shear1,
- rotate1, translate1, perspective1);
- Decompose3DMatrix(aMatrix2, scale2, shear2,
- rotate2, translate2, perspective2);
+ wasDecomposed =
+ Decompose3DMatrix(aMatrix1, scale1, shear1,
+ rotate1, translate1, perspective1) &&
+ Decompose3DMatrix(aMatrix2, scale2, shear2,
+ rotate2, translate2, perspective2);
+ }
+
+ // Fallback to discrete operation if one of the matrices is not decomposable.
+ if (!wasDecomposed) {
+ return Operator::operateForFallback(aMatrix1, aMatrix2, aProgress);
}
Matrix4x4 result;
// Operate each of the pieces in response to |Operator|.
Point4D perspective =
Operator::operateForPerspective(perspective1, perspective2, aProgress);
result.SetTransposedVector(3, perspective);