[chromium] Convert screen space scroll gestures to layer space
[WebKit-https.git] / Source / WebKit / chromium / tests / CCMathUtilTest.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "CCMathUtil.h"
28
29 #include "CCLayerTreeTestCommon.h"
30 #include "FloatRect.h"
31 #include <gmock/gmock.h>
32 #include <gtest/gtest.h>
33 #include <public/WebTransformationMatrix.h>
34
35 using namespace WebCore;
36 using WebKit::WebTransformationMatrix;
37
38 namespace {
39
40 TEST(CCMathUtilTest, verifyBackfaceVisibilityBasicCases)
41 {
42     WebTransformationMatrix transform;
43
44     transform.makeIdentity();
45     EXPECT_FALSE(transform.isBackFaceVisible());
46
47     transform.makeIdentity();
48     transform.rotate3d(0, 80, 0);
49     EXPECT_FALSE(transform.isBackFaceVisible());
50
51     transform.makeIdentity();
52     transform.rotate3d(0, 100, 0);
53     EXPECT_TRUE(transform.isBackFaceVisible());
54
55     // Edge case, 90 degree rotation should return false.
56     transform.makeIdentity();
57     transform.rotate3d(0, 90, 0);
58     EXPECT_FALSE(transform.isBackFaceVisible());
59 }
60
61 TEST(CCMathUtilTest, verifyBackfaceVisibilityForPerspective)
62 {
63     WebTransformationMatrix layerSpaceToProjectionPlane;
64
65     // This tests if isBackFaceVisible works properly under perspective transforms.
66     // Specifically, layers that may have their back face visible in orthographic
67     // projection, may not actually have back face visible under perspective projection.
68
69     // Case 1: Layer is rotated by slightly more than 90 degrees, at the center of the
70     //         prespective projection. In this case, the layer's back-side is visible to
71     //         the camera.
72     layerSpaceToProjectionPlane.makeIdentity();
73     layerSpaceToProjectionPlane.applyPerspective(1);
74     layerSpaceToProjectionPlane.translate3d(0, 0, 0);
75     layerSpaceToProjectionPlane.rotate3d(0, 100, 0);
76     EXPECT_TRUE(layerSpaceToProjectionPlane.isBackFaceVisible());
77
78     // Case 2: Layer is rotated by slightly more than 90 degrees, but shifted off to the
79     //         side of the camera. Because of the wide field-of-view, the layer's front
80     //         side is still visible.
81     //
82     //                       |<-- front side of layer is visible to perspective camera
83     //                    \  |            /
84     //                     \ |           /
85     //                      \|          /
86     //                       |         /
87     //                       |\       /<-- camera field of view
88     //                       | \     /
89     // back side of layer -->|  \   /
90     //                           \./ <-- camera origin
91     //
92     layerSpaceToProjectionPlane.makeIdentity();
93     layerSpaceToProjectionPlane.applyPerspective(1);
94     layerSpaceToProjectionPlane.translate3d(-10, 0, 0);
95     layerSpaceToProjectionPlane.rotate3d(0, 100, 0);
96     EXPECT_FALSE(layerSpaceToProjectionPlane.isBackFaceVisible());
97
98     // Case 3: Additionally rotating the layer by 180 degrees should of course show the
99     //         opposite result of case 2.
100     layerSpaceToProjectionPlane.rotate3d(0, 180, 0);
101     EXPECT_TRUE(layerSpaceToProjectionPlane.isBackFaceVisible());
102 }
103
104 TEST(CCMathUtilTest, verifyProjectionOfPerpendicularPlane)
105 {
106     // In this case, the m33() element of the transform becomes zero, which could cause a
107     // divide-by-zero when projecting points/quads.
108
109     WebTransformationMatrix transform;
110     transform.makeIdentity();
111     transform.setM33(0);
112
113     FloatRect rect = FloatRect(0, 0, 1, 1);
114     FloatRect projectedRect = CCMathUtil::projectClippedRect(transform, rect);
115
116     EXPECT_EQ(0, projectedRect.x());
117     EXPECT_EQ(0, projectedRect.y());
118     EXPECT_TRUE(projectedRect.isEmpty());
119 }
120
121 TEST(CCMathUtilTest, verifyEnclosingClippedRectUsesCorrectInitialBounds)
122 {
123     HomogeneousCoordinate h1(-100, -100, 0, 1);
124     HomogeneousCoordinate h2(-10, -10, 0, 1);
125     HomogeneousCoordinate h3(10, 10, 0, -1);
126     HomogeneousCoordinate h4(100, 100, 0, -1);
127
128     // The bounds of the enclosing clipped rect should be -100 to -10 for both x and y.
129     // However, if there is a bug where the initial xmin/xmax/ymin/ymax are initialized to
130     // numeric_limits<float>::min() (which is zero, not -flt_max) then the enclosing
131     // clipped rect will be computed incorrectly.
132     FloatRect result = CCMathUtil::computeEnclosingClippedRect(h1, h2, h3, h4);
133
134     EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint(-100, -100), FloatSize(90, 90)), result);
135 }
136
137 TEST(CCMathUtilTest, verifyEnclosingRectOfVerticesUsesCorrectInitialBounds)
138 {
139     FloatPoint vertices[3];
140     int numVertices = 3;
141
142     vertices[0] = FloatPoint(-10, -100);
143     vertices[1] = FloatPoint(-100, -10);
144     vertices[2] = FloatPoint(-30, -30);
145
146     // The bounds of the enclosing rect should be -100 to -10 for both x and y. However,
147     // if there is a bug where the initial xmin/xmax/ymin/ymax are initialized to
148     // numeric_limits<float>::min() (which is zero, not -flt_max) then the enclosing
149     // clipped rect will be computed incorrectly.
150     FloatRect result = CCMathUtil::computeEnclosingRectOfVertices(vertices, numVertices);
151
152     EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint(-100, -100), FloatSize(90, 90)), result);
153 }
154
155 TEST(CCMathUtilTest, smallestAngleBetweenVectors)
156 {
157     FloatSize x(1, 0);
158     FloatSize y(0, 1);
159     FloatSize testVector(0.5, 0.5);
160
161     // Orthogonal vectors are at an angle of 90 degress.
162     EXPECT_EQ(90, CCMathUtil::smallestAngleBetweenVectors(x, y));
163
164     // A vector makes a zero angle with itself.
165     EXPECT_EQ(0, CCMathUtil::smallestAngleBetweenVectors(x, x));
166     EXPECT_EQ(0, CCMathUtil::smallestAngleBetweenVectors(y, y));
167     EXPECT_EQ(0, CCMathUtil::smallestAngleBetweenVectors(testVector, testVector));
168
169     // Parallel but reversed vectors are at 180 degrees.
170     EXPECT_EQ(180, CCMathUtil::smallestAngleBetweenVectors(x, -x));
171     EXPECT_EQ(180, CCMathUtil::smallestAngleBetweenVectors(y, -y));
172     EXPECT_EQ(180, CCMathUtil::smallestAngleBetweenVectors(testVector, -testVector));
173
174     // The test vector is at a known angle.
175     EXPECT_EQ(45, floor(CCMathUtil::smallestAngleBetweenVectors(testVector, x)));
176     EXPECT_EQ(45, floor(CCMathUtil::smallestAngleBetweenVectors(testVector, y)));
177 }
178
179 TEST(CCMathUtilTest, vectorProjection)
180 {
181     FloatSize x(1, 0);
182     FloatSize y(0, 1);
183     FloatSize testVector(0.3, 0.7);
184
185     // Orthogonal vectors project to a zero vector.
186     EXPECT_EQ(FloatSize(0, 0), CCMathUtil::projectVector(x, y));
187     EXPECT_EQ(FloatSize(0, 0), CCMathUtil::projectVector(y, x));
188
189     // Projecting a vector onto the orthonormal basis gives the corresponding component of the
190     // vector.
191     EXPECT_EQ(FloatSize(testVector.width(), 0), CCMathUtil::projectVector(testVector, x));
192     EXPECT_EQ(FloatSize(0, testVector.height()), CCMathUtil::projectVector(testVector, y));
193
194     // Finally check than an arbitrary vector projected to another one gives a vector parallel to
195     // the second vector.
196     FloatSize targetVector(0.5, 0.2);
197     FloatSize projectedVector = CCMathUtil::projectVector(testVector, targetVector);
198     EXPECT_EQ(projectedVector.width() / targetVector.width(),
199               projectedVector.height() / targetVector.height());
200 }
201
202 } // namespace