1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/gfx/Matrix.h"
using namespace mozilla;
using namespace mozilla::gfx;
TEST(Matrix, TransformAndClipRect)
{
Rect c(100, 100, 100, 100);
Matrix4x4 m;
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 50, 20, 20), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(250, 50, 20, 20), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(250, 250, 20, 20), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 250, 20, 20), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 50, 100, 20), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(150, 50, 100, 20), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 250, 100, 20), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(150, 250, 100, 20), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 50, 20, 100), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 150, 20, 100), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(250, 50, 20, 100), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(250, 150, 20, 100), c).IsEmpty());
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 50, 100, 100), c)
.IsEqualInterior(Rect(100, 100, 50, 50)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(150, 50, 100, 100), c)
.IsEqualInterior(Rect(150, 100, 50, 50)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(150, 150, 100, 100), c)
.IsEqualInterior(Rect(150, 150, 50, 50)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 150, 100, 100), c)
.IsEqualInterior(Rect(100, 150, 50, 50)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(110, 110, 80, 80), c)
.IsEqualInterior(Rect(110, 110, 80, 80)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 50, 200, 200), c)
.IsEqualInterior(Rect(100, 100, 100, 100)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 50, 200, 100), c)
.IsEqualInterior(Rect(100, 100, 100, 50)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 150, 200, 100), c)
.IsEqualInterior(Rect(100, 150, 100, 50)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(50, 50, 100, 200), c)
.IsEqualInterior(Rect(100, 100, 50, 100)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(150, 50, 100, 200), c)
.IsEqualInterior(Rect(150, 100, 50, 100)));
Matrix4x4 m2 = Matrix4x4::From2D(Matrix(22.68, 0, 0, 12, 16, 164));
EXPECT_TRUE(
m2.TransformAndClipBounds(Rect(0, 0, 100, 100), Rect(1024, 1024, 0, 0))
.IsEmpty());
// Empty rectangles should still have meaningful corners.
EXPECT_TRUE(m.TransformAndClipBounds(Rect(150, 50, 0, 200), c)
.IsEqualEdges(Rect(150, 100, 0, 100)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(150, 150, 0, 0), c)
.IsEqualEdges(Rect(150, 150, 0, 0)));
EXPECT_TRUE(m.TransformAndClipBounds(Rect(150, 100, 300, 0), c)
.IsEqualEdges(Rect(150, 100, 50, 0)));
}
TEST(Matrix, RotateTransform)
{
gfx::Matrix4x4 transformMatrix;
gfx::Point3D trans, scale;
gfx::Quaternion orient;
auto floor = [&](float aValue, int aDecimal) {
const int digit = pow(10, aDecimal);
const float result = (int)(aValue * digit);
return result / digit;
};
// Test rotate 45 degree on x-axis.
gfx::Quaternion expectedOrient(0.382f, 0.0f, 0.0f, 0.923f);
transformMatrix.RotateX(0.785f);
// the orient would be (x:0.3825, y:0, z:0, w: 0.9239)
transformMatrix.Decompose(trans, orient, scale);
EXPECT_EQ(floor(orient.x, 3), expectedOrient.x);
EXPECT_EQ(floor(orient.y, 3), expectedOrient.y);
EXPECT_EQ(floor(orient.z, 3), expectedOrient.z);
EXPECT_EQ(floor(orient.w, 3), expectedOrient.w);
// Test set rotate matrix from a quaternion and
// compare it with the result from decompose.
transformMatrix = gfx::Matrix4x4();
transformMatrix.SetRotationFromQuaternion(orient);
transformMatrix.Decompose(trans, orient, scale);
EXPECT_EQ(floor(orient.x, 3), expectedOrient.x);
EXPECT_EQ(floor(orient.y, 3), expectedOrient.y);
EXPECT_EQ(floor(orient.z, 3), expectedOrient.z);
EXPECT_EQ(floor(orient.w, 3), expectedOrient.w);
// Test rotate -45 degree on axis: (0.577f, 0.577f, 0.577f).
transformMatrix = gfx::Matrix4x4();
transformMatrix.SetRotateAxisAngle(0.577f, 0.577f, 0.577f, -0.785f);
// the orient would be (x:-0.2208, y:-0.2208, z:-0.2208, w: 0.9239)
transformMatrix.Decompose(trans, orient, scale);
expectedOrient.Set(-0.220f, -0.220f, -0.220f, 0.923f);
EXPECT_EQ(floor(orient.x, 3), expectedOrient.x);
EXPECT_EQ(floor(orient.y, 3), expectedOrient.y);
EXPECT_EQ(floor(orient.z, 3), expectedOrient.z);
EXPECT_EQ(floor(orient.w, 3), expectedOrient.w);
// Test set rotate matrix from a quaternion and
// compare it with the result from decompose.
transformMatrix = gfx::Matrix4x4();
transformMatrix.SetRotationFromQuaternion(orient);
transformMatrix.Decompose(trans, orient, scale);
EXPECT_EQ(floor(orient.x, 3), expectedOrient.x);
EXPECT_EQ(floor(orient.y, 3), expectedOrient.y);
EXPECT_EQ(floor(orient.z, 3), expectedOrient.z);
EXPECT_EQ(floor(orient.w, 3), expectedOrient.w);
}
TEST(Matrix4x4Flagged, Mult)
{
Matrix4x4Flagged simple =
Matrix4x4::Translation(Point(42, 42)) * Matrix4x4::Scaling(3, 3, 1);
// For the general matrix, put a value in every field to make sure
// nothing gets dropped.
Matrix4x4 general(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2);
// Use Matrix4x4::operator*(Matrix4x4).
// For the purposes of this test, assume that's correct.
Matrix4x4Flagged realResult = Matrix4x4Flagged(simple.GetMatrix() * general);
// Check that Matrix4x4Flagged::operator*(Matrix4x4Flagged) produces the same
// result.
Matrix4x4Flagged flaggedResult = simple * Matrix4x4Flagged(general);
EXPECT_EQ(realResult, flaggedResult);
// Check that Matrix4x4Flagged::operator*(Matrix4x4) produces the same result.
Matrix4x4Flagged mixedResult = simple * general;
EXPECT_EQ(realResult, mixedResult);
}
|