1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
6 #include "testing/gtest/include/gtest/gtest.h"
7 #include "ui/gfx/geometry/quad_f.h"
8 #include "ui/gfx/geometry/rect_f.h"
12 TEST(QuadTest
, Construction
) {
13 // Verify constructors.
22 QuadF
q4(BoundingRect(a
, c
));
27 EXPECT_EQ(q3
.p1(), a
);
28 EXPECT_EQ(q3
.p2(), b
);
29 EXPECT_EQ(q3
.p3(), c
);
30 EXPECT_EQ(q3
.p4(), d
);
37 EXPECT_EQ(q3
.p1(), b
);
38 EXPECT_EQ(q3
.p2(), c
);
39 EXPECT_EQ(q3
.p3(), d
);
40 EXPECT_EQ(q3
.p4(), a
);
42 // Verify operator=(Rect)
44 q1
= BoundingRect(a
, c
);
47 // Verify operator=(Quad)
53 TEST(QuadTest
, AddingVectors
) {
58 Vector2dF
v(3.5f
, -2.5f
);
63 QuadF
expected1(PointF(4.5f
, -1.5f
),
67 EXPECT_EQ(expected1
, added
);
68 EXPECT_EQ(expected1
, q1
);
71 QuadF subtracted
= q2
- v
;
73 QuadF
expected2(PointF(-2.5f
, 3.5f
),
77 EXPECT_EQ(expected2
, subtracted
);
78 EXPECT_EQ(expected2
, q2
);
83 EXPECT_EQ(QuadF(a
, b
, c
, d
), q3
);
84 EXPECT_EQ(q3
, (q3
+ v
- v
));
87 TEST(QuadTest
, IsRectilinear
) {
92 Vector2dF
v(3.5f
, -2.5f
);
94 EXPECT_TRUE(QuadF().IsRectilinear());
95 EXPECT_TRUE(QuadF(a
, b
, c
, d
).IsRectilinear());
96 EXPECT_TRUE((QuadF(a
, b
, c
, d
) + v
).IsRectilinear());
98 float epsilon
= std::numeric_limits
<float>::epsilon();
99 PointF
a2(1 + epsilon
/ 2, 1 + epsilon
/ 2);
100 PointF
b2(2 + epsilon
/ 2, 1 + epsilon
/ 2);
101 PointF
c2(2 + epsilon
/ 2, 2 + epsilon
/ 2);
102 PointF
d2(1 + epsilon
/ 2, 2 + epsilon
/ 2);
103 EXPECT_TRUE(QuadF(a2
, b
, c
, d
).IsRectilinear());
104 EXPECT_TRUE((QuadF(a2
, b
, c
, d
) + v
).IsRectilinear());
105 EXPECT_TRUE(QuadF(a
, b2
, c
, d
).IsRectilinear());
106 EXPECT_TRUE((QuadF(a
, b2
, c
, d
) + v
).IsRectilinear());
107 EXPECT_TRUE(QuadF(a
, b
, c2
, d
).IsRectilinear());
108 EXPECT_TRUE((QuadF(a
, b
, c2
, d
) + v
).IsRectilinear());
109 EXPECT_TRUE(QuadF(a
, b
, c
, d2
).IsRectilinear());
110 EXPECT_TRUE((QuadF(a
, b
, c
, d2
) + v
).IsRectilinear());
113 PointF a_off
, b_off
, c_off
, d_off
;
128 PointF(1.00001f
, 1.00001f
),
129 PointF(2.00001f
, 1.00001f
),
130 PointF(2.00001f
, 2.00001f
),
131 PointF(1.00001f
, 2.00001f
)
146 PointF(0.99999f
, 0.99999f
),
147 PointF(1.99999f
, 0.99999f
),
148 PointF(1.99999f
, 1.99999f
),
149 PointF(0.99999f
, 1.99999f
)
153 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
154 PointF a_off
= tests
[i
].a_off
;
155 PointF b_off
= tests
[i
].b_off
;
156 PointF c_off
= tests
[i
].c_off
;
157 PointF d_off
= tests
[i
].d_off
;
159 EXPECT_FALSE(QuadF(a_off
, b
, c
, d
).IsRectilinear());
160 EXPECT_FALSE((QuadF(a_off
, b
, c
, d
) + v
).IsRectilinear());
161 EXPECT_FALSE(QuadF(a
, b_off
, c
, d
).IsRectilinear());
162 EXPECT_FALSE((QuadF(a
, b_off
, c
, d
) + v
).IsRectilinear());
163 EXPECT_FALSE(QuadF(a
, b
, c_off
, d
).IsRectilinear());
164 EXPECT_FALSE((QuadF(a
, b
, c_off
, d
) + v
).IsRectilinear());
165 EXPECT_FALSE(QuadF(a
, b
, c
, d_off
).IsRectilinear());
166 EXPECT_FALSE((QuadF(a
, b
, c
, d_off
) + v
).IsRectilinear());
167 EXPECT_FALSE(QuadF(a_off
, b
, c_off
, d
).IsRectilinear());
168 EXPECT_FALSE((QuadF(a_off
, b
, c_off
, d
) + v
).IsRectilinear());
169 EXPECT_FALSE(QuadF(a
, b_off
, c
, d_off
).IsRectilinear());
170 EXPECT_FALSE((QuadF(a
, b_off
, c
, d_off
) + v
).IsRectilinear());
171 EXPECT_FALSE(QuadF(a
, b_off
, c_off
, d_off
).IsRectilinear());
172 EXPECT_FALSE((QuadF(a
, b_off
, c_off
, d_off
) + v
).IsRectilinear());
173 EXPECT_FALSE(QuadF(a_off
, b
, c_off
, d_off
).IsRectilinear());
174 EXPECT_FALSE((QuadF(a_off
, b
, c_off
, d_off
) + v
).IsRectilinear());
175 EXPECT_FALSE(QuadF(a_off
, b_off
, c
, d_off
).IsRectilinear());
176 EXPECT_FALSE((QuadF(a_off
, b_off
, c
, d_off
) + v
).IsRectilinear());
177 EXPECT_FALSE(QuadF(a_off
, b_off
, c_off
, d
).IsRectilinear());
178 EXPECT_FALSE((QuadF(a_off
, b_off
, c_off
, d
) + v
).IsRectilinear());
179 EXPECT_TRUE(QuadF(a_off
, b_off
, c_off
, d_off
).IsRectilinear());
180 EXPECT_TRUE((QuadF(a_off
, b_off
, c_off
, d_off
) + v
).IsRectilinear());
184 TEST(QuadTest
, IsCounterClockwise
) {
189 EXPECT_FALSE(QuadF(a1
, b1
, c1
, d1
).IsCounterClockwise());
190 EXPECT_FALSE(QuadF(b1
, c1
, d1
, a1
).IsCounterClockwise());
191 EXPECT_TRUE(QuadF(a1
, d1
, c1
, b1
).IsCounterClockwise());
192 EXPECT_TRUE(QuadF(c1
, b1
, a1
, d1
).IsCounterClockwise());
194 // Slightly more complicated quads should work just as easily.
195 PointF
a2(1.3f
, 1.4f
);
196 PointF
b2(-0.7f
, 4.9f
);
197 PointF
c2(1.8f
, 6.2f
);
198 PointF
d2(2.1f
, 1.6f
);
199 EXPECT_TRUE(QuadF(a2
, b2
, c2
, d2
).IsCounterClockwise());
200 EXPECT_TRUE(QuadF(b2
, c2
, d2
, a2
).IsCounterClockwise());
201 EXPECT_FALSE(QuadF(a2
, d2
, c2
, b2
).IsCounterClockwise());
202 EXPECT_FALSE(QuadF(c2
, b2
, a2
, d2
).IsCounterClockwise());
204 // Quads with 3 collinear points should work correctly, too.
209 EXPECT_FALSE(QuadF(a3
, b3
, c3
, d3
).IsCounterClockwise());
210 EXPECT_FALSE(QuadF(b3
, c3
, d3
, a3
).IsCounterClockwise());
211 EXPECT_TRUE(QuadF(a3
, d3
, c3
, b3
).IsCounterClockwise());
212 // The next expectation in particular would fail for an implementation
213 // that incorrectly uses only a cross product of the first 3 vertices.
214 EXPECT_TRUE(QuadF(c3
, b3
, a3
, d3
).IsCounterClockwise());
216 // Non-convex quads should work correctly, too.
221 EXPECT_FALSE(QuadF(a4
, b4
, c4
, d4
).IsCounterClockwise());
222 EXPECT_FALSE(QuadF(b4
, c4
, d4
, a4
).IsCounterClockwise());
223 EXPECT_TRUE(QuadF(a4
, d4
, c4
, b4
).IsCounterClockwise());
224 EXPECT_TRUE(QuadF(c4
, b4
, a4
, d4
).IsCounterClockwise());
226 // A quad with huge coordinates should not fail this check due to
227 // single-precision overflow.
228 PointF
a5(1e30f
, 1e30f
);
229 PointF
b5(1e35f
, 1e30f
);
230 PointF
c5(1e35f
, 1e35f
);
231 PointF
d5(1e30f
, 1e35f
);
232 EXPECT_FALSE(QuadF(a5
, b5
, c5
, d5
).IsCounterClockwise());
233 EXPECT_FALSE(QuadF(b5
, c5
, d5
, a5
).IsCounterClockwise());
234 EXPECT_TRUE(QuadF(a5
, d5
, c5
, b5
).IsCounterClockwise());
235 EXPECT_TRUE(QuadF(c5
, b5
, a5
, d5
).IsCounterClockwise());
238 TEST(QuadTest
, BoundingBox
) {
239 RectF
r(3.2f
, 5.4f
, 7.007f
, 12.01f
);
240 EXPECT_EQ(r
, QuadF(r
).BoundingBox());
242 PointF
a(1.3f
, 1.4f
);
243 PointF
b(-0.7f
, 4.9f
);
244 PointF
c(1.8f
, 6.2f
);
245 PointF
d(2.1f
, 1.6f
);
250 EXPECT_EQ(RectF(left
, top
, right
- left
, bottom
- top
),
251 QuadF(a
, b
, c
, d
).BoundingBox());
254 TEST(QuadTest
, ContainsPoint
) {
255 PointF
a(1.3f
, 1.4f
);
256 PointF
b(-0.8f
, 4.4f
);
257 PointF
c(1.8f
, 6.1f
);
258 PointF
d(2.1f
, 1.6f
);
260 Vector2dF
epsilon_x(2 * std::numeric_limits
<float>::epsilon(), 0);
261 Vector2dF
epsilon_y(0, 2 * std::numeric_limits
<float>::epsilon());
263 Vector2dF ac_center
= c
- a
;
264 ac_center
.Scale(0.5f
);
265 Vector2dF bd_center
= d
- b
;
266 bd_center
.Scale(0.5f
);
268 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(a
+ ac_center
));
269 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(b
+ bd_center
));
270 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(c
- ac_center
));
271 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(d
- bd_center
));
272 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(a
- ac_center
));
273 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(b
- bd_center
));
274 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(c
+ ac_center
));
275 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(d
+ bd_center
));
277 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(a
));
278 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(a
- epsilon_x
));
279 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(a
- epsilon_y
));
280 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(a
+ epsilon_x
));
281 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(a
+ epsilon_y
));
283 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(b
));
284 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(b
- epsilon_x
));
285 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(b
- epsilon_y
));
286 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(b
+ epsilon_x
));
287 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(b
+ epsilon_y
));
289 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(c
));
290 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(c
- epsilon_x
));
291 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(c
- epsilon_y
));
292 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(c
+ epsilon_x
));
293 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(c
+ epsilon_y
));
295 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(d
));
296 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(d
- epsilon_x
));
297 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(d
- epsilon_y
));
298 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(d
+ epsilon_x
));
299 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(d
+ epsilon_y
));
301 // Test a simple square.
307 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.1f
, -1.0f
)));
308 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, -1.0f
)));
309 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0.0f
, -1.0f
)));
310 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, -1.0f
)));
311 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.1f
, -1.0f
)));
313 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.1f
, 1.0f
)));
314 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, 1.0f
)));
315 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0.0f
, 1.0f
)));
316 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, 1.0f
)));
317 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.1f
, 1.0f
)));
319 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, -1.1f
)));
320 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, -1.0f
)));
321 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, 0.0f
)));
322 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, 1.0f
)));
323 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, 1.1f
)));
325 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, -1.1f
)));
326 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, -1.0f
)));
327 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, 0.0f
)));
328 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, 1.0f
)));
329 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, 1.1f
)));
331 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0, 0)));
333 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.1f
, 0)));
334 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.1f
, 0)));
335 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0, -1.1f
)));
336 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0, 1.1f
)));
339 TEST(QuadTest
, Scale
) {
340 PointF
a(1.3f
, 1.4f
);
341 PointF
b(-0.8f
, 4.4f
);
342 PointF
c(1.8f
, 6.1f
);
343 PointF
d(2.1f
, 1.6f
);
344 QuadF
q1(a
, b
, c
, d
);
347 PointF a_scaled
= ScalePoint(a
, 1.5f
);
348 PointF b_scaled
= ScalePoint(b
, 1.5f
);
349 PointF c_scaled
= ScalePoint(c
, 1.5f
);
350 PointF d_scaled
= ScalePoint(d
, 1.5f
);
351 EXPECT_EQ(q1
, QuadF(a_scaled
, b_scaled
, c_scaled
, d_scaled
));