• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include <stddef.h>
6 
7 #include "base/macros.h"
8 #include "build/build_config.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/gfx/geometry/quad_f.h"
11 #include "ui/gfx/geometry/rect_f.h"
12 
13 namespace gfx {
14 
TEST(QuadTest,Construction)15 TEST(QuadTest, Construction) {
16   // Verify constructors.
17   PointF a(1, 1);
18   PointF b(2, 1);
19   PointF c(2, 2);
20   PointF d(1, 2);
21   PointF e;
22   QuadF q1;
23   QuadF q2(e, e, e, e);
24   QuadF q3(a, b, c, d);
25   QuadF q4(BoundingRect(a, c));
26   EXPECT_EQ(q1, q2);
27   EXPECT_EQ(q3, q4);
28 
29   // Verify getters.
30   EXPECT_EQ(q3.p1(), a);
31   EXPECT_EQ(q3.p2(), b);
32   EXPECT_EQ(q3.p3(), c);
33   EXPECT_EQ(q3.p4(), d);
34 
35   // Verify setters.
36   q3.set_p1(b);
37   q3.set_p2(c);
38   q3.set_p3(d);
39   q3.set_p4(a);
40   EXPECT_EQ(q3.p1(), b);
41   EXPECT_EQ(q3.p2(), c);
42   EXPECT_EQ(q3.p3(), d);
43   EXPECT_EQ(q3.p4(), a);
44 
45   // Verify operator=(Rect)
46   EXPECT_NE(q1, q4);
47   q1 = BoundingRect(a, c);
48   EXPECT_EQ(q1, q4);
49 
50   // Verify operator=(Quad)
51   EXPECT_NE(q1, q3);
52   q1 = q3;
53   EXPECT_EQ(q1, q3);
54 }
55 
TEST(QuadTest,AddingVectors)56 TEST(QuadTest, AddingVectors) {
57   PointF a(1, 1);
58   PointF b(2, 1);
59   PointF c(2, 2);
60   PointF d(1, 2);
61   Vector2dF v(3.5f, -2.5f);
62 
63   QuadF q1(a, b, c, d);
64   QuadF added = q1 + v;
65   q1 += v;
66   QuadF expected1(PointF(4.5f, -1.5f),
67                   PointF(5.5f, -1.5f),
68                   PointF(5.5f, -0.5f),
69                   PointF(4.5f, -0.5f));
70   EXPECT_EQ(expected1, added);
71   EXPECT_EQ(expected1, q1);
72 
73   QuadF q2(a, b, c, d);
74   QuadF subtracted = q2 - v;
75   q2 -= v;
76   QuadF expected2(PointF(-2.5f, 3.5f),
77                   PointF(-1.5f, 3.5f),
78                   PointF(-1.5f, 4.5f),
79                   PointF(-2.5f, 4.5f));
80   EXPECT_EQ(expected2, subtracted);
81   EXPECT_EQ(expected2, q2);
82 
83   QuadF q3(a, b, c, d);
84   q3 += v;
85   q3 -= v;
86   EXPECT_EQ(QuadF(a, b, c, d), q3);
87   EXPECT_EQ(q3, (q3 + v - v));
88 }
89 
TEST(QuadTest,IsRectilinear)90 TEST(QuadTest, IsRectilinear) {
91   PointF a(1, 1);
92   PointF b(2, 1);
93   PointF c(2, 2);
94   PointF d(1, 2);
95   Vector2dF v(3.5f, -2.5f);
96 
97   EXPECT_TRUE(QuadF().IsRectilinear());
98   EXPECT_TRUE(QuadF(a, b, c, d).IsRectilinear());
99   EXPECT_TRUE((QuadF(a, b, c, d) + v).IsRectilinear());
100 
101   float epsilon = std::numeric_limits<float>::epsilon();
102   PointF a2(1 + epsilon / 2, 1 + epsilon / 2);
103   PointF b2(2 + epsilon / 2, 1 + epsilon / 2);
104   PointF c2(2 + epsilon / 2, 2 + epsilon / 2);
105   PointF d2(1 + epsilon / 2, 2 + epsilon / 2);
106   EXPECT_TRUE(QuadF(a2, b, c, d).IsRectilinear());
107   EXPECT_TRUE((QuadF(a2, b, c, d) + v).IsRectilinear());
108   EXPECT_TRUE(QuadF(a, b2, c, d).IsRectilinear());
109   EXPECT_TRUE((QuadF(a, b2, c, d) + v).IsRectilinear());
110   EXPECT_TRUE(QuadF(a, b, c2, d).IsRectilinear());
111   EXPECT_TRUE((QuadF(a, b, c2, d) + v).IsRectilinear());
112   EXPECT_TRUE(QuadF(a, b, c, d2).IsRectilinear());
113   EXPECT_TRUE((QuadF(a, b, c, d2) + v).IsRectilinear());
114 
115   struct {
116     PointF a_off, b_off, c_off, d_off;
117   } tests[] = {
118     {
119       PointF(1, 1.00001f),
120       PointF(2, 1.00001f),
121       PointF(2, 2.00001f),
122       PointF(1, 2.00001f)
123     },
124     {
125       PointF(1.00001f, 1),
126       PointF(2.00001f, 1),
127       PointF(2.00001f, 2),
128       PointF(1.00001f, 2)
129     },
130     {
131       PointF(1.00001f, 1.00001f),
132       PointF(2.00001f, 1.00001f),
133       PointF(2.00001f, 2.00001f),
134       PointF(1.00001f, 2.00001f)
135     },
136     {
137       PointF(1, 0.99999f),
138       PointF(2, 0.99999f),
139       PointF(2, 1.99999f),
140       PointF(1, 1.99999f)
141     },
142     {
143       PointF(0.99999f, 1),
144       PointF(1.99999f, 1),
145       PointF(1.99999f, 2),
146       PointF(0.99999f, 2)
147     },
148     {
149       PointF(0.99999f, 0.99999f),
150       PointF(1.99999f, 0.99999f),
151       PointF(1.99999f, 1.99999f),
152       PointF(0.99999f, 1.99999f)
153     }
154   };
155 
156   for (size_t i = 0; i < arraysize(tests); ++i) {
157     PointF a_off = tests[i].a_off;
158     PointF b_off = tests[i].b_off;
159     PointF c_off = tests[i].c_off;
160     PointF d_off = tests[i].d_off;
161 
162     EXPECT_FALSE(QuadF(a_off, b, c, d).IsRectilinear());
163     EXPECT_FALSE((QuadF(a_off, b, c, d) + v).IsRectilinear());
164     EXPECT_FALSE(QuadF(a, b_off, c, d).IsRectilinear());
165     EXPECT_FALSE((QuadF(a, b_off, c, d) + v).IsRectilinear());
166     EXPECT_FALSE(QuadF(a, b, c_off, d).IsRectilinear());
167     EXPECT_FALSE((QuadF(a, b, c_off, d) + v).IsRectilinear());
168     EXPECT_FALSE(QuadF(a, b, c, d_off).IsRectilinear());
169     EXPECT_FALSE((QuadF(a, b, c, d_off) + v).IsRectilinear());
170     EXPECT_FALSE(QuadF(a_off, b, c_off, d).IsRectilinear());
171     EXPECT_FALSE((QuadF(a_off, b, c_off, d) + v).IsRectilinear());
172     EXPECT_FALSE(QuadF(a, b_off, c, d_off).IsRectilinear());
173     EXPECT_FALSE((QuadF(a, b_off, c, d_off) + v).IsRectilinear());
174     EXPECT_FALSE(QuadF(a, b_off, c_off, d_off).IsRectilinear());
175     EXPECT_FALSE((QuadF(a, b_off, c_off, d_off) + v).IsRectilinear());
176     EXPECT_FALSE(QuadF(a_off, b, c_off, d_off).IsRectilinear());
177     EXPECT_FALSE((QuadF(a_off, b, c_off, d_off) + v).IsRectilinear());
178     EXPECT_FALSE(QuadF(a_off, b_off, c, d_off).IsRectilinear());
179     EXPECT_FALSE((QuadF(a_off, b_off, c, d_off) + v).IsRectilinear());
180     EXPECT_FALSE(QuadF(a_off, b_off, c_off, d).IsRectilinear());
181     EXPECT_FALSE((QuadF(a_off, b_off, c_off, d) + v).IsRectilinear());
182     EXPECT_TRUE(QuadF(a_off, b_off, c_off, d_off).IsRectilinear());
183     EXPECT_TRUE((QuadF(a_off, b_off, c_off, d_off) + v).IsRectilinear());
184   }
185 }
186 
TEST(QuadTest,IsCounterClockwise)187 TEST(QuadTest, IsCounterClockwise) {
188   PointF a1(1, 1);
189   PointF b1(2, 1);
190   PointF c1(2, 2);
191   PointF d1(1, 2);
192   EXPECT_FALSE(QuadF(a1, b1, c1, d1).IsCounterClockwise());
193   EXPECT_FALSE(QuadF(b1, c1, d1, a1).IsCounterClockwise());
194   EXPECT_TRUE(QuadF(a1, d1, c1, b1).IsCounterClockwise());
195   EXPECT_TRUE(QuadF(c1, b1, a1, d1).IsCounterClockwise());
196 
197   // Slightly more complicated quads should work just as easily.
198   PointF a2(1.3f, 1.4f);
199   PointF b2(-0.7f, 4.9f);
200   PointF c2(1.8f, 6.2f);
201   PointF d2(2.1f, 1.6f);
202   EXPECT_TRUE(QuadF(a2, b2, c2, d2).IsCounterClockwise());
203   EXPECT_TRUE(QuadF(b2, c2, d2, a2).IsCounterClockwise());
204   EXPECT_FALSE(QuadF(a2, d2, c2, b2).IsCounterClockwise());
205   EXPECT_FALSE(QuadF(c2, b2, a2, d2).IsCounterClockwise());
206 
207   // Quads with 3 collinear points should work correctly, too.
208   PointF a3(0, 0);
209   PointF b3(1, 0);
210   PointF c3(2, 0);
211   PointF d3(1, 1);
212   EXPECT_FALSE(QuadF(a3, b3, c3, d3).IsCounterClockwise());
213   EXPECT_FALSE(QuadF(b3, c3, d3, a3).IsCounterClockwise());
214   EXPECT_TRUE(QuadF(a3, d3, c3, b3).IsCounterClockwise());
215   // The next expectation in particular would fail for an implementation
216   // that incorrectly uses only a cross product of the first 3 vertices.
217   EXPECT_TRUE(QuadF(c3, b3, a3, d3).IsCounterClockwise());
218 
219   // Non-convex quads should work correctly, too.
220   PointF a4(0, 0);
221   PointF b4(1, 1);
222   PointF c4(2, 0);
223   PointF d4(1, 3);
224   EXPECT_FALSE(QuadF(a4, b4, c4, d4).IsCounterClockwise());
225   EXPECT_FALSE(QuadF(b4, c4, d4, a4).IsCounterClockwise());
226   EXPECT_TRUE(QuadF(a4, d4, c4, b4).IsCounterClockwise());
227   EXPECT_TRUE(QuadF(c4, b4, a4, d4).IsCounterClockwise());
228 
229   // A quad with huge coordinates should not fail this check due to
230   // single-precision overflow.
231   PointF a5(1e30f, 1e30f);
232   PointF b5(1e35f, 1e30f);
233   PointF c5(1e35f, 1e35f);
234   PointF d5(1e30f, 1e35f);
235   EXPECT_FALSE(QuadF(a5, b5, c5, d5).IsCounterClockwise());
236   EXPECT_FALSE(QuadF(b5, c5, d5, a5).IsCounterClockwise());
237   EXPECT_TRUE(QuadF(a5, d5, c5, b5).IsCounterClockwise());
238   EXPECT_TRUE(QuadF(c5, b5, a5, d5).IsCounterClockwise());
239 }
240 
TEST(QuadTest,BoundingBox)241 TEST(QuadTest, BoundingBox) {
242   RectF r(3.2f, 5.4f, 7.007f, 12.01f);
243   EXPECT_EQ(r, QuadF(r).BoundingBox());
244 
245   PointF a(1.3f, 1.4f);
246   PointF b(-0.7f, 4.9f);
247   PointF c(1.8f, 6.2f);
248   PointF d(2.1f, 1.6f);
249   float left = -0.7f;
250   float top = 1.4f;
251   float right = 2.1f;
252   float bottom = 6.2f;
253   EXPECT_EQ(RectF(left, top, right - left, bottom - top),
254             QuadF(a, b, c, d).BoundingBox());
255 }
256 
TEST(QuadTest,ContainsPoint)257 TEST(QuadTest, ContainsPoint) {
258   PointF a(1.3f, 1.4f);
259   PointF b(-0.8f, 4.4f);
260   PointF c(1.8f, 6.1f);
261   PointF d(2.1f, 1.6f);
262 
263   Vector2dF epsilon_x(2 * std::numeric_limits<float>::epsilon(), 0);
264   Vector2dF epsilon_y(0, 2 * std::numeric_limits<float>::epsilon());
265 
266   Vector2dF ac_center = c - a;
267   ac_center.Scale(0.5f);
268   Vector2dF bd_center = d - b;
269   bd_center.Scale(0.5f);
270 
271   EXPECT_TRUE(QuadF(a, b, c, d).Contains(a + ac_center));
272   EXPECT_TRUE(QuadF(a, b, c, d).Contains(b + bd_center));
273   EXPECT_TRUE(QuadF(a, b, c, d).Contains(c - ac_center));
274   EXPECT_TRUE(QuadF(a, b, c, d).Contains(d - bd_center));
275   EXPECT_FALSE(QuadF(a, b, c, d).Contains(a - ac_center));
276   EXPECT_FALSE(QuadF(a, b, c, d).Contains(b - bd_center));
277   EXPECT_FALSE(QuadF(a, b, c, d).Contains(c + ac_center));
278   EXPECT_FALSE(QuadF(a, b, c, d).Contains(d + bd_center));
279 
280   EXPECT_TRUE(QuadF(a, b, c, d).Contains(a));
281   EXPECT_FALSE(QuadF(a, b, c, d).Contains(a - epsilon_x));
282   EXPECT_FALSE(QuadF(a, b, c, d).Contains(a - epsilon_y));
283   EXPECT_FALSE(QuadF(a, b, c, d).Contains(a + epsilon_x));
284   EXPECT_TRUE(QuadF(a, b, c, d).Contains(a + epsilon_y));
285 
286   EXPECT_TRUE(QuadF(a, b, c, d).Contains(b));
287   EXPECT_FALSE(QuadF(a, b, c, d).Contains(b - epsilon_x));
288   EXPECT_FALSE(QuadF(a, b, c, d).Contains(b - epsilon_y));
289   EXPECT_TRUE(QuadF(a, b, c, d).Contains(b + epsilon_x));
290   EXPECT_FALSE(QuadF(a, b, c, d).Contains(b + epsilon_y));
291 
292   EXPECT_TRUE(QuadF(a, b, c, d).Contains(c));
293   EXPECT_FALSE(QuadF(a, b, c, d).Contains(c - epsilon_x));
294   EXPECT_TRUE(QuadF(a, b, c, d).Contains(c - epsilon_y));
295   EXPECT_FALSE(QuadF(a, b, c, d).Contains(c + epsilon_x));
296   EXPECT_FALSE(QuadF(a, b, c, d).Contains(c + epsilon_y));
297 
298   EXPECT_TRUE(QuadF(a, b, c, d).Contains(d));
299   EXPECT_TRUE(QuadF(a, b, c, d).Contains(d - epsilon_x));
300   EXPECT_FALSE(QuadF(a, b, c, d).Contains(d - epsilon_y));
301   EXPECT_FALSE(QuadF(a, b, c, d).Contains(d + epsilon_x));
302   EXPECT_FALSE(QuadF(a, b, c, d).Contains(d + epsilon_y));
303 
304   // Test a simple square.
305   PointF s1(-1, -1);
306   PointF s2(1, -1);
307   PointF s3(1, 1);
308   PointF s4(-1, 1);
309   // Top edge.
310   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.1f, -1.0f)));
311   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, -1.0f)));
312   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(0.0f, -1.0f)));
313   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, -1.0f)));
314   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.1f, -1.0f)));
315   // Bottom edge.
316   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.1f, 1.0f)));
317   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 1.0f)));
318   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(0.0f, 1.0f)));
319   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 1.0f)));
320   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.1f, 1.0f)));
321   // Left edge.
322   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, -1.1f)));
323   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, -1.0f)));
324   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 0.0f)));
325   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 1.0f)));
326   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 1.1f)));
327   // Right edge.
328   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, -1.1f)));
329   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, -1.0f)));
330   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 0.0f)));
331   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 1.0f)));
332   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 1.1f)));
333   // Centered inside.
334   EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(0, 0)));
335   // Centered outside.
336   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.1f, 0)));
337   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.1f, 0)));
338   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(0, -1.1f)));
339   EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(0, 1.1f)));
340 }
341 
TEST(QuadTest,Scale)342 TEST(QuadTest, Scale) {
343   PointF a(1.3f, 1.4f);
344   PointF b(-0.8f, 4.4f);
345   PointF c(1.8f, 6.1f);
346   PointF d(2.1f, 1.6f);
347   QuadF q1(a, b, c, d);
348   q1.Scale(1.5f);
349 
350   PointF a_scaled = ScalePoint(a, 1.5f);
351   PointF b_scaled = ScalePoint(b, 1.5f);
352   PointF c_scaled = ScalePoint(c, 1.5f);
353   PointF d_scaled = ScalePoint(d, 1.5f);
354   EXPECT_EQ(q1, QuadF(a_scaled, b_scaled, c_scaled, d_scaled));
355 
356   QuadF q2;
357   q2.Scale(1.5f);
358   EXPECT_EQ(q2, q2);
359 }
360 
361 }  // namespace gfx
362