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 "ui/gfx/quad_f.h"
7 #include "base/basictypes.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "ui/gfx/rect_f.h"
13 TEST(QuadTest
, Construction
) {
14 // Verify constructors.
23 QuadF
q4(BoundingRect(a
, c
));
24 EXPECT_EQ(q1
.ToString(), q2
.ToString());
25 EXPECT_EQ(q3
.ToString(), q4
.ToString());
28 EXPECT_EQ(q3
.p1().ToString(), a
.ToString());
29 EXPECT_EQ(q3
.p2().ToString(), b
.ToString());
30 EXPECT_EQ(q3
.p3().ToString(), c
.ToString());
31 EXPECT_EQ(q3
.p4().ToString(), d
.ToString());
38 EXPECT_EQ(q3
.p1().ToString(), b
.ToString());
39 EXPECT_EQ(q3
.p2().ToString(), c
.ToString());
40 EXPECT_EQ(q3
.p3().ToString(), d
.ToString());
41 EXPECT_EQ(q3
.p4().ToString(), a
.ToString());
43 // Verify operator=(Rect)
44 EXPECT_NE(q1
.ToString(), q4
.ToString());
45 q1
= BoundingRect(a
, c
);
46 EXPECT_EQ(q1
.ToString(), q4
.ToString());
48 // Verify operator=(Quad)
49 EXPECT_NE(q1
.ToString(), q3
.ToString());
51 EXPECT_EQ(q1
.ToString(), q3
.ToString());
54 TEST(QuadTest
, AddingVectors
) {
59 Vector2dF
v(3.5f
, -2.5f
);
64 QuadF
expected1(PointF(4.5f
, -1.5f
),
68 EXPECT_EQ(expected1
.ToString(), added
.ToString());
69 EXPECT_EQ(expected1
.ToString(), q1
.ToString());
72 QuadF subtracted
= q2
- v
;
74 QuadF
expected2(PointF(-2.5f
, 3.5f
),
78 EXPECT_EQ(expected2
.ToString(), subtracted
.ToString());
79 EXPECT_EQ(expected2
.ToString(), q2
.ToString());
84 EXPECT_EQ(QuadF(a
, b
, c
, d
).ToString(), q3
.ToString());
85 EXPECT_EQ(q3
.ToString(), (q3
+ v
- v
).ToString());
88 TEST(QuadTest
, IsRectilinear
) {
93 Vector2dF
v(3.5f
, -2.5f
);
95 EXPECT_TRUE(QuadF().IsRectilinear());
96 EXPECT_TRUE(QuadF(a
, b
, c
, d
).IsRectilinear());
97 EXPECT_TRUE((QuadF(a
, b
, c
, d
) + v
).IsRectilinear());
99 float epsilon
= std::numeric_limits
<float>::epsilon();
100 PointF
a2(1 + epsilon
/ 2, 1 + epsilon
/ 2);
101 PointF
b2(2 + epsilon
/ 2, 1 + epsilon
/ 2);
102 PointF
c2(2 + epsilon
/ 2, 2 + epsilon
/ 2);
103 PointF
d2(1 + epsilon
/ 2, 2 + epsilon
/ 2);
104 EXPECT_TRUE(QuadF(a2
, b
, c
, d
).IsRectilinear());
105 EXPECT_TRUE((QuadF(a2
, b
, c
, d
) + v
).IsRectilinear());
106 EXPECT_TRUE(QuadF(a
, b2
, c
, d
).IsRectilinear());
107 EXPECT_TRUE((QuadF(a
, b2
, c
, d
) + v
).IsRectilinear());
108 EXPECT_TRUE(QuadF(a
, b
, c2
, d
).IsRectilinear());
109 EXPECT_TRUE((QuadF(a
, b
, c2
, d
) + v
).IsRectilinear());
110 EXPECT_TRUE(QuadF(a
, b
, c
, d2
).IsRectilinear());
111 EXPECT_TRUE((QuadF(a
, b
, c
, d2
) + v
).IsRectilinear());
114 PointF a_off
, b_off
, c_off
, d_off
;
129 PointF(1.00001f
, 1.00001f
),
130 PointF(2.00001f
, 1.00001f
),
131 PointF(2.00001f
, 2.00001f
),
132 PointF(1.00001f
, 2.00001f
)
147 PointF(0.99999f
, 0.99999f
),
148 PointF(1.99999f
, 0.99999f
),
149 PointF(1.99999f
, 1.99999f
),
150 PointF(0.99999f
, 1.99999f
)
154 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
155 PointF a_off
= tests
[i
].a_off
;
156 PointF b_off
= tests
[i
].b_off
;
157 PointF c_off
= tests
[i
].c_off
;
158 PointF d_off
= tests
[i
].d_off
;
160 EXPECT_FALSE(QuadF(a_off
, b
, c
, d
).IsRectilinear());
161 EXPECT_FALSE((QuadF(a_off
, b
, c
, d
) + v
).IsRectilinear());
162 EXPECT_FALSE(QuadF(a
, b_off
, c
, d
).IsRectilinear());
163 EXPECT_FALSE((QuadF(a
, b_off
, c
, d
) + v
).IsRectilinear());
164 EXPECT_FALSE(QuadF(a
, b
, c_off
, d
).IsRectilinear());
165 EXPECT_FALSE((QuadF(a
, b
, c_off
, d
) + v
).IsRectilinear());
166 EXPECT_FALSE(QuadF(a
, b
, c
, d_off
).IsRectilinear());
167 EXPECT_FALSE((QuadF(a
, b
, c
, d_off
) + v
).IsRectilinear());
168 EXPECT_FALSE(QuadF(a_off
, b
, c_off
, d
).IsRectilinear());
169 EXPECT_FALSE((QuadF(a_off
, b
, c_off
, d
) + v
).IsRectilinear());
170 EXPECT_FALSE(QuadF(a
, b_off
, c
, d_off
).IsRectilinear());
171 EXPECT_FALSE((QuadF(a
, b_off
, c
, d_off
) + v
).IsRectilinear());
172 EXPECT_FALSE(QuadF(a
, b_off
, c_off
, d_off
).IsRectilinear());
173 EXPECT_FALSE((QuadF(a
, b_off
, c_off
, d_off
) + v
).IsRectilinear());
174 EXPECT_FALSE(QuadF(a_off
, b
, c_off
, d_off
).IsRectilinear());
175 EXPECT_FALSE((QuadF(a_off
, b
, c_off
, d_off
) + v
).IsRectilinear());
176 EXPECT_FALSE(QuadF(a_off
, b_off
, c
, d_off
).IsRectilinear());
177 EXPECT_FALSE((QuadF(a_off
, b_off
, c
, d_off
) + v
).IsRectilinear());
178 EXPECT_FALSE(QuadF(a_off
, b_off
, c_off
, d
).IsRectilinear());
179 EXPECT_FALSE((QuadF(a_off
, b_off
, c_off
, d
) + v
).IsRectilinear());
180 EXPECT_TRUE(QuadF(a_off
, b_off
, c_off
, d_off
).IsRectilinear());
181 EXPECT_TRUE((QuadF(a_off
, b_off
, c_off
, d_off
) + v
).IsRectilinear());
185 TEST(QuadTest
, IsCounterClockwise
) {
190 EXPECT_FALSE(QuadF(a1
, b1
, c1
, d1
).IsCounterClockwise());
191 EXPECT_FALSE(QuadF(b1
, c1
, d1
, a1
).IsCounterClockwise());
192 EXPECT_TRUE(QuadF(a1
, d1
, c1
, b1
).IsCounterClockwise());
193 EXPECT_TRUE(QuadF(c1
, b1
, a1
, d1
).IsCounterClockwise());
195 // Slightly more complicated quads should work just as easily.
196 PointF
a2(1.3f
, 1.4f
);
197 PointF
b2(-0.7f
, 4.9f
);
198 PointF
c2(1.8f
, 6.2f
);
199 PointF
d2(2.1f
, 1.6f
);
200 EXPECT_TRUE(QuadF(a2
, b2
, c2
, d2
).IsCounterClockwise());
201 EXPECT_TRUE(QuadF(b2
, c2
, d2
, a2
).IsCounterClockwise());
202 EXPECT_FALSE(QuadF(a2
, d2
, c2
, b2
).IsCounterClockwise());
203 EXPECT_FALSE(QuadF(c2
, b2
, a2
, d2
).IsCounterClockwise());
205 // Quads with 3 collinear points should work correctly, too.
210 EXPECT_FALSE(QuadF(a3
, b3
, c3
, d3
).IsCounterClockwise());
211 EXPECT_FALSE(QuadF(b3
, c3
, d3
, a3
).IsCounterClockwise());
212 EXPECT_TRUE(QuadF(a3
, d3
, c3
, b3
).IsCounterClockwise());
213 // The next expectation in particular would fail for an implementation
214 // that incorrectly uses only a cross product of the first 3 vertices.
215 EXPECT_TRUE(QuadF(c3
, b3
, a3
, d3
).IsCounterClockwise());
217 // Non-convex quads should work correctly, too.
222 EXPECT_FALSE(QuadF(a4
, b4
, c4
, d4
).IsCounterClockwise());
223 EXPECT_FALSE(QuadF(b4
, c4
, d4
, a4
).IsCounterClockwise());
224 EXPECT_TRUE(QuadF(a4
, d4
, c4
, b4
).IsCounterClockwise());
225 EXPECT_TRUE(QuadF(c4
, b4
, a4
, d4
).IsCounterClockwise());
227 // A quad with huge coordinates should not fail this check due to
228 // single-precision overflow.
229 PointF
a5(1e30f
, 1e30f
);
230 PointF
b5(1e35f
, 1e30f
);
231 PointF
c5(1e35f
, 1e35f
);
232 PointF
d5(1e30f
, 1e35f
);
233 EXPECT_FALSE(QuadF(a5
, b5
, c5
, d5
).IsCounterClockwise());
234 EXPECT_FALSE(QuadF(b5
, c5
, d5
, a5
).IsCounterClockwise());
235 EXPECT_TRUE(QuadF(a5
, d5
, c5
, b5
).IsCounterClockwise());
236 EXPECT_TRUE(QuadF(c5
, b5
, a5
, d5
).IsCounterClockwise());
239 TEST(QuadTest
, BoundingBox
) {
240 RectF
r(3.2f
, 5.4f
, 7.007f
, 12.01f
);
241 EXPECT_EQ(r
.ToString(), QuadF(r
).BoundingBox().ToString());
243 PointF
a(1.3f
, 1.4f
);
244 PointF
b(-0.7f
, 4.9f
);
245 PointF
c(1.8f
, 6.2f
);
246 PointF
d(2.1f
, 1.6f
);
251 EXPECT_EQ(RectF(left
, top
, right
- left
, bottom
- top
).ToString(),
252 QuadF(a
, b
, c
, d
).BoundingBox().ToString());
255 TEST(QuadTest
, ContainsPoint
) {
256 PointF
a(1.3f
, 1.4f
);
257 PointF
b(-0.8f
, 4.4f
);
258 PointF
c(1.8f
, 6.1f
);
259 PointF
d(2.1f
, 1.6f
);
261 Vector2dF
epsilon_x(2 * std::numeric_limits
<float>::epsilon(), 0);
262 Vector2dF
epsilon_y(0, 2 * std::numeric_limits
<float>::epsilon());
264 Vector2dF ac_center
= c
- a
;
265 ac_center
.Scale(0.5f
);
266 Vector2dF bd_center
= d
- b
;
267 bd_center
.Scale(0.5f
);
269 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(a
+ ac_center
));
270 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(b
+ bd_center
));
271 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(c
- ac_center
));
272 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(d
- bd_center
));
273 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(a
- ac_center
));
274 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(b
- bd_center
));
275 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(c
+ ac_center
));
276 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(d
+ bd_center
));
278 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(a
));
279 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(a
- epsilon_x
));
280 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(a
- epsilon_y
));
281 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(a
+ epsilon_x
));
282 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(a
+ epsilon_y
));
284 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(b
));
285 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(b
- epsilon_x
));
286 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(b
- epsilon_y
));
287 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(b
+ epsilon_x
));
288 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(b
+ epsilon_y
));
290 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(c
));
291 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(c
- epsilon_x
));
292 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(c
- epsilon_y
));
293 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(c
+ epsilon_x
));
294 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(c
+ epsilon_y
));
296 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(d
));
297 EXPECT_TRUE(QuadF(a
, b
, c
, d
).Contains(d
- epsilon_x
));
298 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(d
- epsilon_y
));
299 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(d
+ epsilon_x
));
300 EXPECT_FALSE(QuadF(a
, b
, c
, d
).Contains(d
+ epsilon_y
));
302 // Test a simple square.
308 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.1f
, -1.0f
)));
309 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, -1.0f
)));
310 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0.0f
, -1.0f
)));
311 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, -1.0f
)));
312 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.1f
, -1.0f
)));
314 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.1f
, 1.0f
)));
315 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, 1.0f
)));
316 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0.0f
, 1.0f
)));
317 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, 1.0f
)));
318 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.1f
, 1.0f
)));
320 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, -1.1f
)));
321 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, -1.0f
)));
322 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, 0.0f
)));
323 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, 1.0f
)));
324 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.0f
, 1.1f
)));
326 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, -1.1f
)));
327 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, -1.0f
)));
328 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, 0.0f
)));
329 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, 1.0f
)));
330 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.0f
, 1.1f
)));
332 EXPECT_TRUE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0, 0)));
334 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(-1.1f
, 0)));
335 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(1.1f
, 0)));
336 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0, -1.1f
)));
337 EXPECT_FALSE(QuadF(s1
, s2
, s3
, s4
).Contains(PointF(0, 1.1f
)));
340 TEST(QuadTest
, Scale
) {
341 PointF
a(1.3f
, 1.4f
);
342 PointF
b(-0.8f
, 4.4f
);
343 PointF
c(1.8f
, 6.1f
);
344 PointF
d(2.1f
, 1.6f
);
345 QuadF
q1(a
, b
, c
, d
);
348 PointF a_scaled
= ScalePoint(a
, 1.5f
);
349 PointF b_scaled
= ScalePoint(b
, 1.5f
);
350 PointF c_scaled
= ScalePoint(c
, 1.5f
);
351 PointF d_scaled
= ScalePoint(d
, 1.5f
);
352 EXPECT_EQ(q1
.ToString(),
353 QuadF(a_scaled
, b_scaled
, c_scaled
, d_scaled
).ToString());
357 EXPECT_EQ(q2
.ToString(), q2
.ToString());