12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/base/math_util.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cmath>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/test/geometry_test_utils.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect_f.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/transform.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(MathUtilTest, ProjectionOfPerpendicularPlane) {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In this case, the m33() element of the transform becomes zero, which could
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // cause a divide-by-zero when projecting points/quads.
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform transform;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.MakeIdentity();
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  transform.matrix().set(2, 2, 0);
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::RectF rect = gfx::RectF(0, 0, 1, 1);
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::RectF projected_rect = MathUtil::ProjectClippedRect(transform, rect);
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, projected_rect.x());
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, projected_rect.y());
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(projected_rect.IsEmpty());
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(MathUtilTest, EnclosingClippedRectUsesCorrectInitialBounds) {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HomogeneousCoordinate h1(-100, -100, 0, 1);
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HomogeneousCoordinate h2(-10, -10, 0, 1);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HomogeneousCoordinate h3(10, 10, 0, -1);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HomogeneousCoordinate h4(100, 100, 0, -1);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The bounds of the enclosing clipped rect should be -100 to -10 for both x
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // and y. However, if there is a bug where the initial xmin/xmax/ymin/ymax are
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // initialized to numeric_limits<float>::min() (which is zero, not -flt_max)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // then the enclosing clipped rect will be computed incorrectly.
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::RectF result = MathUtil::ComputeEnclosingClippedRect(h1, h2, h3, h4);
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Due to floating point math in ComputeClippedPointForEdge this result
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // is fairly imprecise.  0.15f was empirically determined.
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_RECT_NEAR(
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)), result, 0.15f);
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(MathUtilTest, EnclosingRectOfVerticesUsesCorrectInitialBounds) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::PointF vertices[3];
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int num_vertices = 3;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  vertices[0] = gfx::PointF(-10, -100);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  vertices[1] = gfx::PointF(-100, -10);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  vertices[2] = gfx::PointF(-30, -30);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The bounds of the enclosing rect should be -100 to -10 for both x and y.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // However, if there is a bug where the initial xmin/xmax/ymin/ymax are
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // initialized to numeric_limits<float>::min() (which is zero, not -flt_max)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // then the enclosing clipped rect will be computed incorrectly.
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::RectF result =
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MathUtil::ComputeEnclosingRectOfVertices(vertices, num_vertices);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FLOAT_RECT_EQ(gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)),
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       result);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(MathUtilTest, SmallestAngleBetweenVectors) {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF x(1, 0);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF y(0, 1);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF test_vector(0.5, 0.5);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Orthogonal vectors are at an angle of 90 degress.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(90, MathUtil::SmallestAngleBetweenVectors(x, y));
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A vector makes a zero angle with itself.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, MathUtil::SmallestAngleBetweenVectors(x, x));
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, MathUtil::SmallestAngleBetweenVectors(y, y));
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, MathUtil::SmallestAngleBetweenVectors(test_vector, test_vector));
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Parallel but reversed vectors are at 180 degrees.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FLOAT_EQ(180, MathUtil::SmallestAngleBetweenVectors(x, -x));
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FLOAT_EQ(180, MathUtil::SmallestAngleBetweenVectors(y, -y));
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FLOAT_EQ(
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      180, MathUtil::SmallestAngleBetweenVectors(test_vector, -test_vector));
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The test vector is at a known angle.
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FLOAT_EQ(
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      45, std::floor(MathUtil::SmallestAngleBetweenVectors(test_vector, x)));
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FLOAT_EQ(
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      45, std::floor(MathUtil::SmallestAngleBetweenVectors(test_vector, y)));
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(MathUtilTest, VectorProjection) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF x(1, 0);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF y(0, 1);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF test_vector(0.3f, 0.7f);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Orthogonal vectors project to a zero vector.
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), MathUtil::ProjectVector(x, y));
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), MathUtil::ProjectVector(y, x));
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Projecting a vector onto the orthonormal basis gives the corresponding
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // component of the vector.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_VECTOR_EQ(gfx::Vector2dF(test_vector.x(), 0),
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   MathUtil::ProjectVector(test_vector, x));
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, test_vector.y()),
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   MathUtil::ProjectVector(test_vector, y));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Finally check than an arbitrary vector projected to another one gives a
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // vector parallel to the second vector.
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF target_vector(0.5, 0.2f);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF projected_vector =
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MathUtil::ProjectVector(test_vector, target_vector);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(projected_vector.x() / target_vector.x(),
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            projected_vector.y() / target_vector.y());
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST(MathUtilTest, MapEnclosedRectWith2dAxisAlignedTransform) {
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect input(1, 2, 3, 4);
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect output;
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Transform transform;
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Identity.
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(input, output);
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Integer translate.
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Translate(2.0, 3.0);
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(gfx::Rect(3, 5, 3, 4), output);
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Non-integer translate.
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Translate(0.5, 0.5);
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(gfx::Rect(4, 6, 2, 3), output);
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Scale.
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform = gfx::Transform();
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Scale(2.0, 3.0);
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(gfx::Rect(2, 6, 6, 12), output);
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Rotate Z.
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform = gfx::Transform();
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Translate(1.0, 2.0);
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.RotateAboutZAxis(90.0);
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Translate(-1.0, -2.0);
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(gfx::Rect(-3, 2, 4, 3), output);
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Rotate X.
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform = gfx::Transform();
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.RotateAboutXAxis(90.0);
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(output.IsEmpty());
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform = gfx::Transform();
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.RotateAboutXAxis(180.0);
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(gfx::Rect(1, -6, 3, 4), output);
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Rotate Y.
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform = gfx::Transform();
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.RotateAboutYAxis(90.0);
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(output.IsEmpty());
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform = gfx::Transform();
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.RotateAboutYAxis(180.0);
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(gfx::Rect(-4, 2, 3, 4), output);
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Translate Z.
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform = gfx::Transform();
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.ApplyPerspectiveDepth(10.0);
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Translate3d(0.0, 0.0, 5.0);
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  output =
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, input);
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(gfx::Rect(2, 4, 6, 8), output);
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
198