#include "config.h"
#include <public/WebTransformationMatrix.h>
#include "CCGeometryTestUtils.h"
#include <gtest/gtest.h>
#include <wtf/MathExtras.h>
#define EXPECT_ROW1_EQ(a, b, c, d, matrix) \
EXPECT_FLOAT_EQ((a), (matrix).m11()); \
EXPECT_FLOAT_EQ((b), (matrix).m21()); \
EXPECT_FLOAT_EQ((c), (matrix).m31()); \
EXPECT_FLOAT_EQ((d), (matrix).m41());
#define EXPECT_ROW2_EQ(a, b, c, d, matrix) \
EXPECT_FLOAT_EQ((a), (matrix).m12()); \
EXPECT_FLOAT_EQ((b), (matrix).m22()); \
EXPECT_FLOAT_EQ((c), (matrix).m32()); \
EXPECT_FLOAT_EQ((d), (matrix).m42());
#define EXPECT_ROW3_EQ(a, b, c, d, matrix) \
EXPECT_FLOAT_EQ((a), (matrix).m13()); \
EXPECT_FLOAT_EQ((b), (matrix).m23()); \
EXPECT_FLOAT_EQ((c), (matrix).m33()); \
EXPECT_FLOAT_EQ((d), (matrix).m43());
#define EXPECT_ROW4_EQ(a, b, c, d, matrix) \
EXPECT_FLOAT_EQ((a), (matrix).m14()); \
EXPECT_FLOAT_EQ((b), (matrix).m24()); \
EXPECT_FLOAT_EQ((c), (matrix).m34()); \
EXPECT_FLOAT_EQ((d), (matrix).m44()); \
#define EXPECT_ROW1_NEAR(a, b, c, d, matrix, errorThreshold) \
EXPECT_NEAR((a), (matrix).m11(), (errorThreshold)); \
EXPECT_NEAR((b), (matrix).m21(), (errorThreshold)); \
EXPECT_NEAR((c), (matrix).m31(), (errorThreshold)); \
EXPECT_NEAR((d), (matrix).m41(), (errorThreshold));
#define EXPECT_ROW2_NEAR(a, b, c, d, matrix, errorThreshold) \
EXPECT_NEAR((a), (matrix).m12(), (errorThreshold)); \
EXPECT_NEAR((b), (matrix).m22(), (errorThreshold)); \
EXPECT_NEAR((c), (matrix).m32(), (errorThreshold)); \
EXPECT_NEAR((d), (matrix).m42(), (errorThreshold));
#define EXPECT_ROW3_NEAR(a, b, c, d, matrix, errorThreshold) \
EXPECT_NEAR((a), (matrix).m13(), (errorThreshold)); \
EXPECT_NEAR((b), (matrix).m23(), (errorThreshold)); \
EXPECT_NEAR((c), (matrix).m33(), (errorThreshold)); \
EXPECT_NEAR((d), (matrix).m43(), (errorThreshold));
#define ERROR_THRESHOLD 1e-14
#define LOOSE_ERROR_THRESHOLD 1e-7
using namespace WebKit;
namespace {
static void initializeTestMatrix(WebTransformationMatrix& transform)
{
transform.setM11(10);
transform.setM12(11);
transform.setM13(12);
transform.setM14(13);
transform.setM21(14);
transform.setM22(15);
transform.setM23(16);
transform.setM24(17);
transform.setM31(18);
transform.setM32(19);
transform.setM33(20);
transform.setM34(21);
transform.setM41(22);
transform.setM42(23);
transform.setM43(24);
transform.setM44(25);
EXPECT_ROW1_EQ(10, 14, 18, 22, transform);
EXPECT_ROW2_EQ(11, 15, 19, 23, transform);
EXPECT_ROW3_EQ(12, 16, 20, 24, transform);
EXPECT_ROW4_EQ(13, 17, 21, 25, transform);
}
static void initializeTestMatrix2(WebTransformationMatrix& transform)
{
transform.setM11(30);
transform.setM12(31);
transform.setM13(32);
transform.setM14(33);
transform.setM21(34);
transform.setM22(35);
transform.setM23(36);
transform.setM24(37);
transform.setM31(38);
transform.setM32(39);
transform.setM33(40);
transform.setM34(41);
transform.setM41(42);
transform.setM42(43);
transform.setM43(44);
transform.setM44(45);
EXPECT_ROW1_EQ(30, 34, 38, 42, transform);
EXPECT_ROW2_EQ(31, 35, 39, 43, transform);
EXPECT_ROW3_EQ(32, 36, 40, 44, transform);
EXPECT_ROW4_EQ(33, 37, 41, 45, transform);
}
TEST(WebTransformationMatrixTest, verifyDefaultConstructorCreatesIdentityMatrix)
{
WebTransformationMatrix A;
EXPECT_ROW1_EQ(1, 0, 0, 0, A);
EXPECT_ROW2_EQ(0, 1, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
EXPECT_TRUE(A.isIdentity());
}
TEST(WebTransformationMatrixTest, verifyConstructorFor2dElements)
{
WebTransformationMatrix A(1, 2, 3, 4, 5, 6);
EXPECT_ROW1_EQ(1, 3, 0, 5, A);
EXPECT_ROW2_EQ(2, 4, 0, 6, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyConstructorForAllElements)
{
WebTransformationMatrix A(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
EXPECT_ROW1_EQ(1, 5, 9, 13, A);
EXPECT_ROW2_EQ(2, 6, 10, 14, A);
EXPECT_ROW3_EQ(3, 7, 11, 15, A);
EXPECT_ROW4_EQ(4, 8, 12, 16, A);
}
TEST(WebTransformationMatrixTest, verifyCopyConstructor)
{
WebTransformationMatrix A;
initializeTestMatrix(A);
WebTransformationMatrix B(A);
EXPECT_ROW1_EQ(10, 14, 18, 22, B);
EXPECT_ROW2_EQ(11, 15, 19, 23, B);
EXPECT_ROW3_EQ(12, 16, 20, 24, B);
EXPECT_ROW4_EQ(13, 17, 21, 25, B);
}
TEST(WebTransformationMatrixTest, verifyMatrixInversion)
{
WebTransformationMatrix translation;
translation.translate3d(2, 3, 4);
EXPECT_TRUE(translation.isInvertible());
WebTransformationMatrix inverseTranslation = translation.inverse();
EXPECT_ROW1_EQ(1, 0, 0, -2, inverseTranslation);
EXPECT_ROW2_EQ(0, 1, 0, -3, inverseTranslation);
EXPECT_ROW3_EQ(0, 0, 1, -4, inverseTranslation);
EXPECT_ROW4_EQ(0, 0, 0, 1, inverseTranslation);
EXPECT_ROW1_EQ(1, 0, 0, 2, translation);
EXPECT_ROW2_EQ(0, 1, 0, 3, translation);
EXPECT_ROW3_EQ(0, 0, 1, 4, translation);
EXPECT_ROW4_EQ(0, 0, 0, 1, translation);
WebTransformationMatrix scale;
scale.scale3d(4, 10, 100);
EXPECT_TRUE(scale.isInvertible());
WebTransformationMatrix inverseScale = scale.inverse();
EXPECT_ROW1_EQ(0.25, 0, 0, 0, inverseScale);
EXPECT_ROW2_EQ(0, .1f, 0, 0, inverseScale);
EXPECT_ROW3_EQ(0, 0, .01f, 0, inverseScale);
EXPECT_ROW4_EQ(0, 0, 0, 1, inverseScale);
WebTransformationMatrix notInvertible;
notInvertible.setM11(0);
notInvertible.setM22(0);
notInvertible.setM33(0);
notInvertible.setM44(0);
EXPECT_FALSE(notInvertible.isInvertible());
WebTransformationMatrix inverseOfNotInvertible;
initializeTestMatrix(inverseOfNotInvertible);
inverseOfNotInvertible = notInvertible.inverse();
EXPECT_TRUE(inverseOfNotInvertible.isIdentity());
}
TEST(WebTransformationMatrixTest, verifyTo2DTransform)
{
WebTransformationMatrix A;
initializeTestMatrix(A);
WebTransformationMatrix B = A.to2dTransform();
EXPECT_ROW1_EQ(10, 14, 0, 22, B);
EXPECT_ROW2_EQ(11, 15, 0, 23, B);
EXPECT_ROW3_EQ(0, 0, 1, 0, B);
EXPECT_ROW4_EQ(13, 17, 0, 25, B);
EXPECT_ROW1_EQ(10, 14, 18, 22, A);
EXPECT_ROW2_EQ(11, 15, 19, 23, A);
EXPECT_ROW3_EQ(12, 16, 20, 24, A);
EXPECT_ROW4_EQ(13, 17, 21, 25, A);
}
TEST(WebTransformationMatrixTest, verifyAssignmentOperator)
{
WebTransformationMatrix A;
initializeTestMatrix(A);
WebTransformationMatrix B;
initializeTestMatrix2(B);
WebTransformationMatrix C;
initializeTestMatrix2(C);
C = B = A;
EXPECT_ROW1_EQ(10, 14, 18, 22, B);
EXPECT_ROW2_EQ(11, 15, 19, 23, B);
EXPECT_ROW3_EQ(12, 16, 20, 24, B);
EXPECT_ROW4_EQ(13, 17, 21, 25, B);
EXPECT_ROW1_EQ(10, 14, 18, 22, C);
EXPECT_ROW2_EQ(11, 15, 19, 23, C);
EXPECT_ROW3_EQ(12, 16, 20, 24, C);
EXPECT_ROW4_EQ(13, 17, 21, 25, C);
}
TEST(WebTransformationMatrixTest, verifyEqualsBooleanOperator)
{
WebTransformationMatrix A;
initializeTestMatrix(A);
WebTransformationMatrix B;
initializeTestMatrix(B);
EXPECT_TRUE(A == B);
WebTransformationMatrix C;
initializeTestMatrix2(C);
EXPECT_FALSE(A == C);
WebTransformationMatrix D;
D = A;
D.setM11(0);
EXPECT_FALSE(A == D);
D = A;
D.setM12(0);
EXPECT_FALSE(A == D);
D = A;
D.setM13(0);
EXPECT_FALSE(A == D);
D = A;
D.setM14(0);
EXPECT_FALSE(A == D);
D = A;
D.setM21(0);
EXPECT_FALSE(A == D);
D = A;
D.setM22(0);
EXPECT_FALSE(A == D);
D = A;
D.setM23(0);
EXPECT_FALSE(A == D);
D = A;
D.setM24(0);
EXPECT_FALSE(A == D);
D = A;
D.setM31(0);
EXPECT_FALSE(A == D);
D = A;
D.setM32(0);
EXPECT_FALSE(A == D);
D = A;
D.setM33(0);
EXPECT_FALSE(A == D);
D = A;
D.setM34(0);
EXPECT_FALSE(A == D);
D = A;
D.setM41(0);
EXPECT_FALSE(A == D);
D = A;
D.setM42(0);
EXPECT_FALSE(A == D);
D = A;
D.setM43(0);
EXPECT_FALSE(A == D);
D = A;
D.setM44(0);
EXPECT_FALSE(A == D);
}
TEST(WebTransformationMatrixTest, verifyMultiplyOperator)
{
WebTransformationMatrix A;
initializeTestMatrix(A);
WebTransformationMatrix B;
initializeTestMatrix2(B);
WebTransformationMatrix C = A * B;
EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, C);
EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, C);
EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, C);
EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, C);
EXPECT_FALSE(A * B == B * A);
}
TEST(WebTransformationMatrixTest, verifyMatrixMultiplication)
{
WebTransformationMatrix A;
initializeTestMatrix(A);
WebTransformationMatrix B;
initializeTestMatrix2(B);
A.multiply(B);
EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, A);
EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, A);
EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, A);
EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, A);
}
TEST(WebTransformationMatrixTest, verifyMakeIdentiy)
{
WebTransformationMatrix A;
initializeTestMatrix(A);
A.makeIdentity();
EXPECT_ROW1_EQ(1, 0, 0, 0, A);
EXPECT_ROW2_EQ(0, 1, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
EXPECT_TRUE(A.isIdentity());
}
TEST(WebTransformationMatrixTest, verifyTranslate)
{
WebTransformationMatrix A;
A.translate(2, 3);
EXPECT_ROW1_EQ(1, 0, 0, 2, A);
EXPECT_ROW2_EQ(0, 1, 0, 3, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.scale(5);
A.translate(2, 3);
EXPECT_ROW1_EQ(5, 0, 0, 10, A);
EXPECT_ROW2_EQ(0, 5, 0, 15, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyTranslate3d)
{
WebTransformationMatrix A;
A.translate3d(2, 3, 4);
EXPECT_ROW1_EQ(1, 0, 0, 2, A);
EXPECT_ROW2_EQ(0, 1, 0, 3, A);
EXPECT_ROW3_EQ(0, 0, 1, 4, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.scale3d(6, 7, 8);
A.translate3d(2, 3, 4);
EXPECT_ROW1_EQ(6, 0, 0, 12, A);
EXPECT_ROW2_EQ(0, 7, 0, 21, A);
EXPECT_ROW3_EQ(0, 0, 8, 32, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyTranslateRight3d)
{
WebTransformationMatrix A;
A.translateRight3d(2, 3, 4);
EXPECT_ROW1_EQ(1, 0, 0, 2, A);
EXPECT_ROW2_EQ(0, 1, 0, 3, A);
EXPECT_ROW3_EQ(0, 0, 1, 4, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.scale3d(6, 7, 8);
A.translateRight3d(2, 3, 4);
EXPECT_ROW1_EQ(6, 0, 0, 2, A);
EXPECT_ROW2_EQ(0, 7, 0, 3, A);
EXPECT_ROW3_EQ(0, 0, 8, 4, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyScale)
{
WebTransformationMatrix A;
A.scale(5);
EXPECT_ROW1_EQ(5, 0, 0, 0, A);
EXPECT_ROW2_EQ(0, 5, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.translate3d(2, 3, 4);
A.scale(5);
EXPECT_ROW1_EQ(5, 0, 0, 2, A);
EXPECT_ROW2_EQ(0, 5, 0, 3, A);
EXPECT_ROW3_EQ(0, 0, 1, 4, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyNonUniformScale)
{
WebTransformationMatrix A;
A.scaleNonUniform(6, 7);
EXPECT_ROW1_EQ(6, 0, 0, 0, A);
EXPECT_ROW2_EQ(0, 7, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.translate3d(2, 3, 4);
A.scaleNonUniform(6, 7);
EXPECT_ROW1_EQ(6, 0, 0, 2, A);
EXPECT_ROW2_EQ(0, 7, 0, 3, A);
EXPECT_ROW3_EQ(0, 0, 1, 4, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyScale3d)
{
WebTransformationMatrix A;
A.scale3d(6, 7, 8);
EXPECT_ROW1_EQ(6, 0, 0, 0, A);
EXPECT_ROW2_EQ(0, 7, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 8, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.translate3d(2, 3, 4);
A.scale3d(6, 7, 8);
EXPECT_ROW1_EQ(6, 0, 0, 2, A);
EXPECT_ROW2_EQ(0, 7, 0, 3, A);
EXPECT_ROW3_EQ(0, 0, 8, 4, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyRotate)
{
WebTransformationMatrix A;
A.rotate(90);
EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.scale3d(6, 7, 8);
A.rotate(90);
EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 8, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyRotate3d)
{
WebTransformationMatrix A;
A.makeIdentity();
A.rotate3d(0, 0, 90);
EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.rotate3d(90, 0, 0);
EXPECT_ROW1_EQ(1, 0, 0, 0, A);
EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.rotate3d(0, 90, 0);
EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD);
EXPECT_ROW2_EQ(0, 1, 0, 0, A);
EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.scale3d(6, 7, 8);
A.rotate3d(0, 0, 90);
EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 8, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyRotate3dOrderOfCompositeRotations)
{
WebTransformationMatrix A;
A.makeIdentity();
A.rotate3d(10, 20, 30);
EXPECT_ROW1_NEAR(0.8137976813493738026394908,
-0.4409696105298823720630708,
0.3785223063697923939763257,
0, A, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0.4698463103929541584413698,
0.8825641192593856043657752,
0.0180283112362972230968694,
0, A, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(-0.3420201433256686573969318,
0.1631759111665348205288950,
0.9254165783983233639631294,
0, A, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyRotateAxisAngle3d)
{
WebTransformationMatrix A;
A.makeIdentity();
A.rotate3d(0, 0, 1, 90);
EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.rotate3d(1, 0, 0, 90);
EXPECT_ROW1_EQ(1, 0, 0, 0, A);
EXPECT_ROW2_NEAR(0, 0, -1, 0, A, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(0, 1, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.rotate3d(0, 1, 0, 90);
EXPECT_ROW1_NEAR(0, 0, 1, 0, A, ERROR_THRESHOLD);
EXPECT_ROW2_EQ(0, 1, 0, 0, A);
EXPECT_ROW3_NEAR(-1, 0, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.scale3d(6, 7, 8);
A.rotate3d(0, 0, 1, 90);
EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 8, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyRotateAxisAngle3dForArbitraryAxis)
{
WebTransformationMatrix A;
A.rotate3d(1, 1, 1, 90);
EXPECT_ROW1_NEAR(0.3333333333333334258519187,
-0.2440169358562924717404030,
0.9106836025229592124219380,
0, A, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0.9106836025229592124219380,
0.3333333333333334258519187,
-0.2440169358562924717404030,
0, A, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(-0.2440169358562924717404030,
0.9106836025229592124219380,
0.3333333333333334258519187,
0, A, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyRotateAxisAngle3dForDegenerateAxis)
{
WebTransformationMatrix A;
A.rotate3d(0, 0, 0, 90);
EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifySkewX)
{
WebTransformationMatrix A;
A.skewX(45);
EXPECT_ROW1_EQ(1, 1, 0, 0, A);
EXPECT_ROW2_EQ(0, 1, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.scale3d(6, 7, 8);
A.skewX(45);
EXPECT_ROW1_EQ(6, 6, 0, 0, A);
EXPECT_ROW2_EQ(0, 7, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 8, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifySkewY)
{
WebTransformationMatrix A;
A.skewY(45);
EXPECT_ROW1_EQ(1, 0, 0, 0, A);
EXPECT_ROW2_EQ(1, 1, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
A.makeIdentity();
A.scale3d(6, 7, 8);
A.skewY(45);
EXPECT_ROW1_EQ(6, 0, 0, 0, A);
EXPECT_ROW2_EQ(7, 7, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 8, 0, A);
EXPECT_ROW4_EQ(0, 0, 0, 1, A);
}
TEST(WebTransformationMatrixTest, verifyApplyPerspective)
{
WebTransformationMatrix A;
A.applyPerspective(1);
EXPECT_ROW1_EQ(1, 0, 0, 0, A);
EXPECT_ROW2_EQ(0, 1, 0, 0, A);
EXPECT_ROW3_EQ(0, 0, 1, 0, A);
EXPECT_ROW4_EQ(0, 0, -1, 1, A);
A.makeIdentity();
A.translate3d(2, 3, 4);
A.applyPerspective(1);
EXPECT_ROW1_EQ(1, 0, -2, 2, A);
EXPECT_ROW2_EQ(0, 1, -3, 3, A);
EXPECT_ROW3_EQ(0, 0, -3, 4, A);
EXPECT_ROW4_EQ(0, 0, -1, 1, A);
}
TEST(WebTransformationMatrixTest, verifyHasPerspective)
{
WebTransformationMatrix A;
A.applyPerspective(1);
EXPECT_TRUE(A.hasPerspective());
A.makeIdentity();
A.applyPerspective(0);
EXPECT_FALSE(A.hasPerspective());
A.makeIdentity();
A.setM34(-0.3);
EXPECT_TRUE(A.hasPerspective());
A.makeIdentity();
A.setM14(-1);
EXPECT_FALSE(A.hasPerspective());
A.makeIdentity();
A.setM24(-1);
EXPECT_FALSE(A.hasPerspective());
A.makeIdentity();
A.setM44(0.5);
EXPECT_FALSE(A.hasPerspective());
}
TEST(WebTransformationMatrixTest, verifyIsInvertible)
{
WebTransformationMatrix A;
A.makeIdentity();
EXPECT_TRUE(A.isInvertible());
A.makeIdentity();
A.translate3d(2, 3, 4);
EXPECT_TRUE(A.isInvertible());
A.makeIdentity();
A.scale3d(6, 7, 8);
EXPECT_TRUE(A.isInvertible());
A.makeIdentity();
A.rotate3d(10, 20, 30);
EXPECT_TRUE(A.isInvertible());
A.makeIdentity();
A.skewX(45);
EXPECT_TRUE(A.isInvertible());
A.makeIdentity();
A.applyPerspective(1);
EXPECT_TRUE(A.isInvertible());
A.makeIdentity();
A.applyPerspective(1);
A.setM44(0);
EXPECT_FALSE(A.isInvertible());
A.makeIdentity();
A.applyPerspective(1);
A.setM44(0);
A.scale3d(6, 7, 8);
A.rotate3d(10, 20, 30);
A.translate3d(6, 7, 8);
EXPECT_FALSE(A.isInvertible());
A.makeIdentity();
A.setM11(0);
A.setM22(0);
A.setM33(0);
A.setM44(0);
EXPECT_FALSE(A.isInvertible());
}
TEST(WebTransformationMatrixTest, verifyIsIdentity)
{
WebTransformationMatrix A;
initializeTestMatrix(A);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
EXPECT_TRUE(A.isIdentity());
A.makeIdentity();
A.setM11(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM12(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM13(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM14(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM21(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM22(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM23(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM24(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM31(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM32(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM33(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM34(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM41(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM42(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM43(2);
EXPECT_FALSE(A.isIdentity());
A.makeIdentity();
A.setM44(2);
EXPECT_FALSE(A.isIdentity());
}
TEST(WebTransformationMatrixTest, verifyIsIdentityOrTranslation)
{
WebTransformationMatrix A;
initializeTestMatrix(A);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
EXPECT_TRUE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM11(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM12(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM13(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM14(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM21(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM22(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM23(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM24(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM31(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM32(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM33(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM34(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM41(2);
EXPECT_TRUE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM42(2);
EXPECT_TRUE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM43(2);
EXPECT_TRUE(A.isIdentityOrTranslation());
A.makeIdentity();
A.setM44(2);
EXPECT_FALSE(A.isIdentityOrTranslation());
}
TEST(WebTransformationMatrixTest, verifyIsIntegerTranslation)
{
WebTransformationMatrix A;
A.makeIdentity();
A.translate(2, 3);
EXPECT_TRUE(A.isIntegerTranslation());
A.makeIdentity();
A.translate(2, 3);
EXPECT_TRUE(A.isIntegerTranslation());
A.makeIdentity();
A.translate(2.00001, 3);
EXPECT_FALSE(A.isIntegerTranslation());
A.makeIdentity();
A.translate(2, 2.99999);
EXPECT_FALSE(A.isIntegerTranslation());
A.makeIdentity();
for (int i = 0; i < 100000; ++i)
A.translate(2, 3);
EXPECT_TRUE(A.isIntegerTranslation());
}
TEST(WebTransformationMatrixTest, verifyBlendForTranslation)
{
WebTransformationMatrix from;
from.translate3d(100, 200, 100);
WebTransformationMatrix to;
to.makeIdentity();
to.translate3d(200, 100, 300);
to.blend(from, 0);
EXPECT_TRANSFORMATION_MATRIX_EQ(from, to);
to.makeIdentity();
to.translate3d(200, 100, 300);
to.blend(from, 0.25);
EXPECT_ROW1_EQ(1, 0, 0, 125, to);
EXPECT_ROW2_EQ(0, 1, 0, 175, to);
EXPECT_ROW3_EQ(0, 0, 1, 150, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.translate3d(200, 100, 300);
to.blend(from, 0.5);
EXPECT_ROW1_EQ(1, 0, 0, 150, to);
EXPECT_ROW2_EQ(0, 1, 0, 150, to);
EXPECT_ROW3_EQ(0, 0, 1, 200, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.translate3d(200, 100, 300);
to.blend(from, 1);
EXPECT_ROW1_EQ(1, 0, 0, 200, to);
EXPECT_ROW2_EQ(0, 1, 0, 100, to);
EXPECT_ROW3_EQ(0, 0, 1, 300, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
}
TEST(WebTransformationMatrixTest, verifyBlendForScale)
{
WebTransformationMatrix from;
from.scale3d(100, 200, 100);
WebTransformationMatrix to;
to.makeIdentity();
to.scale3d(200, 100, 300);
to.blend(from, 0);
EXPECT_TRANSFORMATION_MATRIX_EQ(from, to);
to.makeIdentity();
to.scale3d(200, 100, 300);
to.blend(from, 0.25);
EXPECT_ROW1_EQ(125, 0, 0, 0, to);
EXPECT_ROW2_EQ(0, 175, 0, 0, to);
EXPECT_ROW3_EQ(0, 0, 150, 0, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.scale3d(200, 100, 300);
to.blend(from, 0.5);
EXPECT_ROW1_EQ(150, 0, 0, 0, to);
EXPECT_ROW2_EQ(0, 150, 0, 0, to);
EXPECT_ROW3_EQ(0, 0, 200, 0, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.scale3d(200, 100, 300);
to.blend(from, 1);
EXPECT_ROW1_EQ(200, 0, 0, 0, to);
EXPECT_ROW2_EQ(0, 100, 0, 0, to);
EXPECT_ROW3_EQ(0, 0, 300, 0, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
}
TEST(WebTransformationMatrixTest, verifyBlendForSkewX)
{
WebTransformationMatrix from;
from.skewX(0);
WebTransformationMatrix to;
to.makeIdentity();
to.skewX(45);
to.blend(from, 0);
EXPECT_TRANSFORMATION_MATRIX_EQ(from, to);
to.makeIdentity();
to.skewX(45);
to.blend(from, 0.5);
EXPECT_ROW1_EQ(1, 0.5, 0, 0, to);
EXPECT_ROW2_EQ(0, 1, 0, 0, to);
EXPECT_ROW3_EQ(0, 0, 1, 0, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.skewX(45);
to.blend(from, 0.25);
EXPECT_ROW1_EQ(1, 0.25, 0, 0, to);
EXPECT_ROW2_EQ(0, 1, 0, 0, to);
EXPECT_ROW3_EQ(0, 0, 1, 0, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.skewX(45);
to.blend(from, 1);
EXPECT_ROW1_EQ(1, 1, 0, 0, to);
EXPECT_ROW2_EQ(0, 1, 0, 0, to);
EXPECT_ROW3_EQ(0, 0, 1, 0, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
}
TEST(WebTransformationMatrixTest, verifyBlendForSkewY)
{
WebTransformationMatrix from;
from.skewY(0);
WebTransformationMatrix to;
to.makeIdentity();
to.skewY(45);
to.blend(from, 0);
EXPECT_TRANSFORMATION_MATRIX_EQ(from, to);
to.makeIdentity();
to.skewY(45);
to.blend(from, 0.25);
EXPECT_ROW1_NEAR(1.0823489449280947471976333, 0.0464370719145053845178239, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0.2152925909665224513123150, 0.9541702441750861130032035, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 1, 0, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.skewY(45);
to.blend(from, 0.5);
EXPECT_ROW1_NEAR(1.1152212925809066312865525, 0.0676495144007326631996335, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0.4619397844342648662419037, 0.9519009045724774464858342, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 1, 0, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.skewY(45);
to.blend(from, 1);
EXPECT_ROW1_NEAR(1, 0, 0, 0, to, LOOSE_ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(1, 1, 0, 0, to, LOOSE_ERROR_THRESHOLD);
EXPECT_ROW3_EQ(0, 0, 1, 0, to);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
}
TEST(WebTransformationMatrixTest, verifyBlendForRotationAboutX)
{
WebTransformationMatrix from;
from.rotate3d(1, 0, 0, 0);
WebTransformationMatrix to;
to.makeIdentity();
to.rotate3d(1, 0, 0, 90);
to.blend(from, 0);
EXPECT_TRANSFORMATION_MATRIX_EQ(from, to);
double expectedRotationAngle = 22.5 * piDouble / 180.0;
to.makeIdentity();
to.rotate3d(1, 0, 0, 90);
to.blend(from, 0.25);
EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0, cos(expectedRotationAngle), -sin(expectedRotationAngle), 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(0, sin(expectedRotationAngle), cos(expectedRotationAngle), 0, to, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
expectedRotationAngle = 45 * piDouble / 180.0;
to.makeIdentity();
to.rotate3d(1, 0, 0, 90);
to.blend(from, 0.5);
EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0, cos(expectedRotationAngle), -sin(expectedRotationAngle), 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(0, sin(expectedRotationAngle), cos(expectedRotationAngle), 0, to, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.rotate3d(1, 0, 0, 90);
to.blend(from, 1);
EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0, 0, -1, 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
}
TEST(WebTransformationMatrixTest, verifyBlendForRotationAboutY)
{
WebTransformationMatrix from;
from.rotate3d(0, 1, 0, 0);
WebTransformationMatrix to;
to.makeIdentity();
to.rotate3d(0, 1, 0, 90);
to.blend(from, 0);
EXPECT_TRANSFORMATION_MATRIX_EQ(from, to);
double expectedRotationAngle = 22.5 * piDouble / 180.0;
to.makeIdentity();
to.rotate3d(0, 1, 0, 90);
to.blend(from, 0.25);
EXPECT_ROW1_NEAR(cos(expectedRotationAngle), 0, sin(expectedRotationAngle), 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(-sin(expectedRotationAngle), 0, cos(expectedRotationAngle), 0, to, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
expectedRotationAngle = 45 * piDouble / 180.0;
to.makeIdentity();
to.rotate3d(0, 1, 0, 90);
to.blend(from, 0.5);
EXPECT_ROW1_NEAR(cos(expectedRotationAngle), 0, sin(expectedRotationAngle), 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(-sin(expectedRotationAngle), 0, cos(expectedRotationAngle), 0, to, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.rotate3d(0, 1, 0, 90);
to.blend(from, 1);
EXPECT_ROW1_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(-1, 0, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
}
TEST(WebTransformationMatrixTest, verifyBlendForRotationAboutZ)
{
WebTransformationMatrix from;
from.rotate3d(0, 0, 1, 0);
WebTransformationMatrix to;
to.makeIdentity();
to.rotate3d(0, 0, 1, 90);
to.blend(from, 0);
EXPECT_TRANSFORMATION_MATRIX_EQ(from, to);
double expectedRotationAngle = 22.5 * piDouble / 180.0;
to.makeIdentity();
to.rotate3d(0, 0, 1, 90);
to.blend(from, 0.25);
EXPECT_ROW1_NEAR(cos(expectedRotationAngle), -sin(expectedRotationAngle), 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(sin(expectedRotationAngle), cos(expectedRotationAngle), 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
expectedRotationAngle = 45 * piDouble / 180.0;
to.makeIdentity();
to.rotate3d(0, 0, 1, 90);
to.blend(from, 0.5);
EXPECT_ROW1_NEAR(cos(expectedRotationAngle), -sin(expectedRotationAngle), 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(sin(expectedRotationAngle), cos(expectedRotationAngle), 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to.makeIdentity();
to.rotate3d(0, 0, 1, 90);
to.blend(from, 1);
EXPECT_ROW1_NEAR(0, -1, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW3_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD);
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
}
TEST(WebTransformationMatrixTest, verifyBlendForCompositeTransform)
{
WebTransformationMatrix from;
WebTransformationMatrix to;
WebTransformationMatrix expectedEndOfAnimation;
expectedEndOfAnimation.applyPerspective(1);
expectedEndOfAnimation.translate3d(10, 20, 30);
expectedEndOfAnimation.rotate3d(0, 0, 1, 25);
expectedEndOfAnimation.skewY(45);
expectedEndOfAnimation.scale3d(6, 7, 8);
to = expectedEndOfAnimation;
to.blend(from, 0);
EXPECT_TRANSFORMATION_MATRIX_EQ(from, to);
to = expectedEndOfAnimation;
to.blend(from, 1);
WebTransformationMatrix normalizedExpectedEndOfAnimation = expectedEndOfAnimation;
WebTransformationMatrix normalizationMatrix;
normalizationMatrix.setM11(1 / expectedEndOfAnimation.m44());
normalizationMatrix.setM22(1 / expectedEndOfAnimation.m44());
normalizationMatrix.setM33(1 / expectedEndOfAnimation.m44());
normalizationMatrix.setM44(1 / expectedEndOfAnimation.m44());
normalizedExpectedEndOfAnimation.multiply(normalizationMatrix);
EXPECT_TRANSFORMATION_MATRIX_EQ(normalizedExpectedEndOfAnimation, to);
}
}