15 {
16
17namespace {
18
19
20
21class SpyPathReceiver : public PathReceiver {
22 public:
23
24 using LineSegment = std::function<void(const Point&)>;
25 using CubicSegment =
26 std::function<void(const Point&, const Point&, const Point&)>;
27
28 void SpyLineTo(LineSegment line_to) { line_to_ = std::move(line_to); }
29
30 void SpyCubicTo(CubicSegment cubic_to) { cubic_to_ = std::move(cubic_to); }
31
32
33 void MoveTo(
const Point& p2,
bool will_be_closed)
override {}
34
35 void LineTo(
const Point& p2)
override {
36 if (line_to_) {
37 line_to_(p2);
38 }
39 }
40
41 void QuadTo(const Point& cp, const Point& p2) override {}
42
43 void CubicTo(
const Point& cp1,
const Point& cp2,
const Point& p2)
override {
44 if (cubic_to_) {
45 cubic_to_(cp1, cp2, p2);
46 }
47 }
48
49 void Close()
override {}
50
51 private:
52 LineSegment line_to_;
53 CubicSegment cubic_to_;
54};
55
56}
57
58namespace testing {
59
60TEST(RoundSuperellipseTest, EmptyDeclaration) {
61 RoundSuperellipse rse;
62
63 EXPECT_TRUE(rse.IsEmpty());
64 EXPECT_FALSE(rse.IsRect());
65 EXPECT_FALSE(rse.IsOval());
66 EXPECT_TRUE(rse.IsFinite());
67 EXPECT_TRUE(rse.GetBounds().IsEmpty());
68 EXPECT_EQ(rse.GetBounds(),
Rect());
69 EXPECT_EQ(rse.GetBounds().GetLeft(), 0.0f);
70 EXPECT_EQ(rse.GetBounds().GetTop(), 0.0f);
71 EXPECT_EQ(rse.GetBounds().GetRight(), 0.0f);
72 EXPECT_EQ(rse.GetBounds().GetBottom(), 0.0f);
73 EXPECT_EQ(rse.GetRadii().top_left,
Size());
74 EXPECT_EQ(rse.GetRadii().top_right,
Size());
75 EXPECT_EQ(rse.GetRadii().bottom_left,
Size());
76 EXPECT_EQ(rse.GetRadii().bottom_right,
Size());
77 EXPECT_EQ(rse.GetRadii().top_left.width, 0.0f);
78 EXPECT_EQ(rse.GetRadii().top_left.height, 0.0f);
79 EXPECT_EQ(rse.GetRadii().top_right.width, 0.0f);
80 EXPECT_EQ(rse.GetRadii().top_right.height, 0.0f);
81 EXPECT_EQ(rse.GetRadii().bottom_left.width, 0.0f);
82 EXPECT_EQ(rse.GetRadii().bottom_left.height, 0.0f);
83 EXPECT_EQ(rse.GetRadii().bottom_right.width, 0.0f);
84 EXPECT_EQ(rse.GetRadii().bottom_right.height, 0.0f);
85}
86
87TEST(RoundSuperellipseTest, DefaultConstructor) {
88 RoundSuperellipse rse = RoundSuperellipse();
89
90 EXPECT_TRUE(rse.IsEmpty());
91 EXPECT_FALSE(rse.IsRect());
92 EXPECT_FALSE(rse.IsOval());
93 EXPECT_TRUE(rse.IsFinite());
94 EXPECT_TRUE(rse.GetBounds().IsEmpty());
95 EXPECT_EQ(rse.GetBounds(),
Rect());
96 EXPECT_EQ(rse.GetRadii().top_left,
Size());
97 EXPECT_EQ(rse.GetRadii().top_right,
Size());
98 EXPECT_EQ(rse.GetRadii().bottom_left,
Size());
99 EXPECT_EQ(rse.GetRadii().bottom_right,
Size());
100}
101
102TEST(RoundSuperellipseTest, EmptyRectConstruction) {
103 RoundSuperellipse rse =
104 RoundSuperellipse::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
105
106 EXPECT_TRUE(rse.IsEmpty());
107 EXPECT_FALSE(rse.IsRect());
108 EXPECT_FALSE(rse.IsOval());
109 EXPECT_TRUE(rse.IsFinite());
110 EXPECT_TRUE(rse.GetBounds().IsEmpty());
111 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
112 EXPECT_EQ(rse.GetRadii().top_left,
Size());
113 EXPECT_EQ(rse.GetRadii().top_right,
Size());
114 EXPECT_EQ(rse.GetRadii().bottom_left,
Size());
115 EXPECT_EQ(rse.GetRadii().bottom_right,
Size());
116}
117
118TEST(RoundSuperellipseTest, RectConstructor) {
119 RoundSuperellipse rse =
120 RoundSuperellipse::MakeRect(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
121
122 EXPECT_FALSE(rse.IsEmpty());
123 EXPECT_TRUE(rse.IsRect());
124 EXPECT_FALSE(rse.IsOval());
125 EXPECT_TRUE(rse.IsFinite());
126 EXPECT_FALSE(rse.GetBounds().IsEmpty());
127 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
128 EXPECT_EQ(rse.GetRadii().top_left,
Size());
129 EXPECT_EQ(rse.GetRadii().top_right,
Size());
130 EXPECT_EQ(rse.GetRadii().bottom_left,
Size());
131 EXPECT_EQ(rse.GetRadii().bottom_right,
Size());
132}
133
134TEST(RoundSuperellipseTest, InvertedRectConstruction) {
135 RoundSuperellipse rse =
136 RoundSuperellipse::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f));
137
138 EXPECT_FALSE(rse.IsEmpty());
139 EXPECT_TRUE(rse.IsRect());
140 EXPECT_FALSE(rse.IsOval());
141 EXPECT_TRUE(rse.IsFinite());
142 EXPECT_FALSE(rse.GetBounds().IsEmpty());
143 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
144 EXPECT_EQ(rse.GetRadii().top_left,
Size());
145 EXPECT_EQ(rse.GetRadii().top_right,
Size());
146 EXPECT_EQ(rse.GetRadii().bottom_left,
Size());
147 EXPECT_EQ(rse.GetRadii().bottom_right,
Size());
148}
149
150TEST(RoundSuperellipseTest, EmptyOvalConstruction) {
151 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
152 Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f), 10.0f, 10.0f);
153
154 EXPECT_TRUE(rse.IsEmpty());
155 EXPECT_FALSE(rse.IsRect());
156 EXPECT_FALSE(rse.IsOval());
157 EXPECT_TRUE(rse.IsFinite());
158 EXPECT_TRUE(rse.GetBounds().IsEmpty());
159 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
160 EXPECT_EQ(rse.GetRadii().top_left,
Size());
161 EXPECT_EQ(rse.GetRadii().top_right,
Size());
162 EXPECT_EQ(rse.GetRadii().bottom_left,
Size());
163 EXPECT_EQ(rse.GetRadii().bottom_right,
Size());
164}
165
166TEST(RoundSuperellipseTest, OvalConstructor) {
167 RoundSuperellipse rse =
168 RoundSuperellipse::MakeOval(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
169
170 EXPECT_FALSE(rse.IsEmpty());
171 EXPECT_FALSE(rse.IsRect());
172 EXPECT_TRUE(rse.IsOval());
173 EXPECT_TRUE(rse.IsFinite());
174 EXPECT_FALSE(rse.GetBounds().IsEmpty());
175 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
176 EXPECT_EQ(rse.GetRadii().top_left,
Size(5.0f, 5.0f));
177 EXPECT_EQ(rse.GetRadii().top_right,
Size(5.0f, 5.0f));
178 EXPECT_EQ(rse.GetRadii().bottom_left,
Size(5.0f, 5.0f));
179 EXPECT_EQ(rse.GetRadii().bottom_right,
Size(5.0f, 5.0f));
180}
181
182TEST(RoundSuperellipseTest, InvertedOvalConstruction) {
183 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
184 Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f), 10.0f, 10.0f);
185
186 EXPECT_FALSE(rse.IsEmpty());
187 EXPECT_FALSE(rse.IsRect());
188 EXPECT_TRUE(rse.IsOval());
189 EXPECT_TRUE(rse.IsFinite());
190 EXPECT_FALSE(rse.GetBounds().IsEmpty());
191 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
192 EXPECT_EQ(rse.GetRadii().top_left,
Size(5.0f, 5.0f));
193 EXPECT_EQ(rse.GetRadii().top_right,
Size(5.0f, 5.0f));
194 EXPECT_EQ(rse.GetRadii().bottom_left,
Size(5.0f, 5.0f));
195 EXPECT_EQ(rse.GetRadii().bottom_right,
Size(5.0f, 5.0f));
196}
197
198TEST(RoundSuperellipseTest, RectRadiusConstructor) {
199 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadius(
200 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f);
201
202 EXPECT_FALSE(rse.IsEmpty());
203 EXPECT_FALSE(rse.IsRect());
204 EXPECT_FALSE(rse.IsOval());
205 EXPECT_TRUE(rse.IsFinite());
206 EXPECT_FALSE(rse.GetBounds().IsEmpty());
207 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
208 EXPECT_EQ(rse.GetRadii().top_left,
Size(2.0f, 2.0f));
209 EXPECT_EQ(rse.GetRadii().top_right,
Size(2.0f, 2.0f));
210 EXPECT_EQ(rse.GetRadii().bottom_left,
Size(2.0f, 2.0f));
211 EXPECT_EQ(rse.GetRadii().bottom_right,
Size(2.0f, 2.0f));
212}
213
214TEST(RoundSuperellipseTest, RectXYConstructor) {
215 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
216 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f, 3.0f);
217
218 EXPECT_FALSE(rse.IsEmpty());
219 EXPECT_FALSE(rse.IsRect());
220 EXPECT_FALSE(rse.IsOval());
221 EXPECT_TRUE(rse.IsFinite());
222 EXPECT_FALSE(rse.GetBounds().IsEmpty());
223 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
224 EXPECT_EQ(rse.GetRadii().top_left,
Size(2.0f, 3.0f));
225 EXPECT_EQ(rse.GetRadii().top_right,
Size(2.0f, 3.0f));
226 EXPECT_EQ(rse.GetRadii().bottom_left,
Size(2.0f, 3.0f));
227 EXPECT_EQ(rse.GetRadii().bottom_right,
Size(2.0f, 3.0f));
228}
229
230TEST(RoundSuperellipseTest, RectSizeConstructor) {
231 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
232 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
Size(2.0f, 3.0f));
233
234 EXPECT_FALSE(rse.IsEmpty());
235 EXPECT_FALSE(rse.IsRect());
236 EXPECT_FALSE(rse.IsOval());
237 EXPECT_TRUE(rse.IsFinite());
238 EXPECT_FALSE(rse.GetBounds().IsEmpty());
239 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
240 EXPECT_EQ(rse.GetRadii().top_left,
Size(2.0f, 3.0f));
241 EXPECT_EQ(rse.GetRadii().top_right,
Size(2.0f, 3.0f));
242 EXPECT_EQ(rse.GetRadii().bottom_left,
Size(2.0f, 3.0f));
243 EXPECT_EQ(rse.GetRadii().bottom_right,
Size(2.0f, 3.0f));
244}
245
246TEST(RoundSuperellipseTest, RectRadiiConstructor) {
247 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
248 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
249 {
250 .top_left =
Size(1.0, 1.5),
251 .top_right =
Size(2.0, 2.5f),
252 .bottom_left =
Size(3.0, 3.5f),
253 .bottom_right =
Size(4.0, 4.5f),
254 });
255
256 EXPECT_FALSE(rse.IsEmpty());
257 EXPECT_FALSE(rse.IsRect());
258 EXPECT_FALSE(rse.IsOval());
259 EXPECT_TRUE(rse.IsFinite());
260 EXPECT_FALSE(rse.GetBounds().IsEmpty());
261 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
262 EXPECT_EQ(rse.GetRadii().top_left,
Size(1.0f, 1.5f));
263 EXPECT_EQ(rse.GetRadii().top_right,
Size(2.0f, 2.5f));
264 EXPECT_EQ(rse.GetRadii().bottom_left,
Size(3.0f, 3.5f));
265 EXPECT_EQ(rse.GetRadii().bottom_right,
Size(4.0f, 4.5f));
266}
267
268TEST(RoundSuperellipseTest, RectRadiiOverflowWidthConstructor) {
269 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
270 Rect::MakeXYWH(10.0f, 10.0f, 6.0f, 30.0f),
271 {
272 .top_left =
Size(1.0f, 2.0f),
273 .top_right =
Size(3.0f, 4.0f),
274 .bottom_left =
Size(5.0f, 6.0f),
275 .bottom_right =
Size(7.0f, 8.0f),
276 });
277
278
279
280
281 EXPECT_FALSE(rse.IsEmpty());
282 EXPECT_FALSE(rse.IsRect());
283 EXPECT_FALSE(rse.IsOval());
284 EXPECT_TRUE(rse.IsFinite());
285 EXPECT_FALSE(rse.GetBounds().IsEmpty());
286 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 16.0f, 40.0f));
287 EXPECT_EQ(rse.GetRadii().top_left,
Size(0.5f, 1.0f));
288 EXPECT_EQ(rse.GetRadii().top_right,
Size(1.5f, 2.0f));
289 EXPECT_EQ(rse.GetRadii().bottom_left,
Size(2.5f, 3.0f));
290 EXPECT_EQ(rse.GetRadii().bottom_right,
Size(3.5f, 4.0f));
291}
292
293TEST(RoundSuperellipseTest, RectRadiiOverflowHeightConstructor) {
294 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
295 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 6.0f),
296 {
297 .top_left =
Size(1.0f, 2.0f),
298 .top_right =
Size(3.0f, 4.0f),
299 .bottom_left =
Size(5.0f, 6.0f),
300 .bottom_right =
Size(7.0f, 8.0f),
301 });
302
303
304
305
306 EXPECT_FALSE(rse.IsEmpty());
307 EXPECT_FALSE(rse.IsRect());
308 EXPECT_FALSE(rse.IsOval());
309 EXPECT_TRUE(rse.IsFinite());
310 EXPECT_FALSE(rse.GetBounds().IsEmpty());
311 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 40.0f, 16.0f));
312 EXPECT_EQ(rse.GetRadii().top_left,
Size(0.5f, 1.0f));
313 EXPECT_EQ(rse.GetRadii().top_right,
Size(1.5f, 2.0f));
314 EXPECT_EQ(rse.GetRadii().bottom_left,
Size(2.5f, 3.0f));
315 EXPECT_EQ(rse.GetRadii().bottom_right,
Size(3.5f, 4.0f));
316}
317
318TEST(RoundSuperellipseTest, Shift) {
319 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
320 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
321 {
322 .top_left =
Size(1.0f, 2.0f),
323 .top_right =
Size(3.0f, 4.0f),
324 .bottom_left =
Size(5.0f, 6.0f),
325 .bottom_right =
Size(7.0f, 8.0f),
326 });
327 RoundSuperellipse shifted = rse.Shift(5.0, 6.0);
328
329 EXPECT_FALSE(shifted.IsEmpty());
330 EXPECT_FALSE(shifted.IsRect());
331 EXPECT_FALSE(shifted.IsOval());
332 EXPECT_TRUE(shifted.IsFinite());
333 EXPECT_FALSE(shifted.GetBounds().IsEmpty());
334 EXPECT_EQ(shifted.GetBounds(), Rect::MakeLTRB(15.0f, 16.0f, 45.0f, 46.0f));
335 EXPECT_EQ(shifted.GetRadii().top_left,
Size(1.0f, 2.0f));
336 EXPECT_EQ(shifted.GetRadii().top_right,
Size(3.0f, 4.0f));
337 EXPECT_EQ(shifted.GetRadii().bottom_left,
Size(5.0f, 6.0f));
338 EXPECT_EQ(shifted.GetRadii().bottom_right,
Size(7.0f, 8.0f));
339
340 EXPECT_EQ(shifted, RoundSuperellipse::MakeRectRadii(
341 Rect::MakeXYWH(15.0f, 16.0f, 30.0f, 30.0f),
342 {
343 .top_left =
Size(1.0f, 2.0f),
344 .top_right =
Size(3.0f, 4.0f),
345 .bottom_left =
Size(5.0f, 6.0f),
346 .bottom_right =
Size(7.0f, 8.0f),
347 }));
348}
349
350TEST(RoundSuperellipseTest, ExpandScalar) {
351 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
352 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
353 {
354 .top_left =
Size(1.0f, 2.0f),
355 .top_right =
Size(3.0f, 4.0f),
356 .bottom_left =
Size(5.0f, 6.0f),
357 .bottom_right =
Size(7.0f, 8.0f),
358 });
359 RoundSuperellipse expanded = rse.Expand(5.0);
360
361 EXPECT_FALSE(expanded.IsEmpty());
362 EXPECT_FALSE(expanded.IsRect());
363 EXPECT_FALSE(expanded.IsOval());
364 EXPECT_TRUE(expanded.IsFinite());
365 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
366 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 5.0f, 45.0f, 45.0f));
367 EXPECT_EQ(expanded.GetRadii().top_left,
Size(1.0f, 2.0f));
368 EXPECT_EQ(expanded.GetRadii().top_right,
Size(3.0f, 4.0f));
369 EXPECT_EQ(expanded.GetRadii().bottom_left,
Size(5.0f, 6.0f));
370 EXPECT_EQ(expanded.GetRadii().bottom_right,
Size(7.0f, 8.0f));
371
372 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
373 Rect::MakeXYWH(5.0f, 5.0f, 40.0f, 40.0f),
374 {
375 .top_left =
Size(1.0f, 2.0f),
376 .top_right =
Size(3.0f, 4.0f),
377 .bottom_left =
Size(5.0f, 6.0f),
378 .bottom_right =
Size(7.0f, 8.0f),
379 }));
380}
381
382TEST(RoundSuperellipseTest, ExpandTwoScalars) {
383 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
384 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
385 {
386 .top_left =
Size(1.0f, 2.0f),
387 .top_right =
Size(3.0f, 4.0f),
388 .bottom_left =
Size(5.0f, 6.0f),
389 .bottom_right =
Size(7.0f, 8.0f),
390 });
391 RoundSuperellipse expanded = rse.Expand(5.0, 6.0);
392
393 EXPECT_FALSE(expanded.IsEmpty());
394 EXPECT_FALSE(expanded.IsRect());
395 EXPECT_FALSE(expanded.IsOval());
396 EXPECT_TRUE(expanded.IsFinite());
397 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
398 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 45.0f, 46.0f));
399 EXPECT_EQ(expanded.GetRadii().top_left,
Size(1.0f, 2.0f));
400 EXPECT_EQ(expanded.GetRadii().top_right,
Size(3.0f, 4.0f));
401 EXPECT_EQ(expanded.GetRadii().bottom_left,
Size(5.0f, 6.0f));
402 EXPECT_EQ(expanded.GetRadii().bottom_right,
Size(7.0f, 8.0f));
403
404 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
405 Rect::MakeXYWH(5.0f, 4.0f, 40.0f, 42.0f),
406 {
407 .top_left =
Size(1.0f, 2.0f),
408 .top_right =
Size(3.0f, 4.0f),
409 .bottom_left =
Size(5.0f, 6.0f),
410 .bottom_right =
Size(7.0f, 8.0f),
411 }));
412}
413
414TEST(RoundSuperellipseTest, ExpandFourScalars) {
415 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
416 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
417 {
418 .top_left =
Size(1.0f, 2.0f),
419 .top_right =
Size(3.0f, 4.0f),
420 .bottom_left =
Size(5.0f, 6.0f),
421 .bottom_right =
Size(7.0f, 8.0f),
422 });
423 RoundSuperellipse expanded = rse.Expand(5.0, 6.0, 7.0, 8.0);
424
425 EXPECT_FALSE(expanded.IsEmpty());
426 EXPECT_FALSE(expanded.IsRect());
427 EXPECT_FALSE(expanded.IsOval());
428 EXPECT_TRUE(expanded.IsFinite());
429 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
430 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 47.0f, 48.0f));
431 EXPECT_EQ(expanded.GetRadii().top_left,
Size(1.0f, 2.0f));
432 EXPECT_EQ(expanded.GetRadii().top_right,
Size(3.0f, 4.0f));
433 EXPECT_EQ(expanded.GetRadii().bottom_left,
Size(5.0f, 6.0f));
434 EXPECT_EQ(expanded.GetRadii().bottom_right,
Size(7.0f, 8.0f));
435
436 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
437 Rect::MakeXYWH(5.0f, 4.0f, 42.0f, 44.0f),
438 {
439 .top_left =
Size(1.0f, 2.0f),
440 .top_right =
Size(3.0f, 4.0f),
441 .bottom_left =
Size(5.0f, 6.0f),
442 .bottom_right =
Size(7.0f, 8.0f),
443 }));
444}
445
446TEST(RoundSuperellipseTest, ContractScalar) {
447 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
448 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
449 {
450 .top_left =
Size(1.0f, 2.0f),
451 .top_right =
Size(3.0f, 4.0f),
452 .bottom_left =
Size(5.0f, 6.0f),
453 .bottom_right =
Size(7.0f, 8.0f),
454 });
455 RoundSuperellipse expanded = rse.Expand(-2.0);
456
457 EXPECT_FALSE(expanded.IsEmpty());
458 EXPECT_FALSE(expanded.IsRect());
459 EXPECT_FALSE(expanded.IsOval());
460 EXPECT_TRUE(expanded.IsFinite());
461 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
462 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(12.0f, 12.0f, 38.0f, 38.0f));
463 EXPECT_EQ(expanded.GetRadii().top_left,
Size(1.0f, 2.0f));
464 EXPECT_EQ(expanded.GetRadii().top_right,
Size(3.0f, 4.0f));
465 EXPECT_EQ(expanded.GetRadii().bottom_left,
Size(5.0f, 6.0f));
466 EXPECT_EQ(expanded.GetRadii().bottom_right,
Size(7.0f, 8.0f));
467
468 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
469 Rect::MakeXYWH(12.0f, 12.0f, 26.0f, 26.0f),
470 {
471 .top_left =
Size(1.0f, 2.0f),
472 .top_right =
Size(3.0f, 4.0f),
473 .bottom_left =
Size(5.0f, 6.0f),
474 .bottom_right =
Size(7.0f, 8.0f),
475 }));
476}
477
478TEST(RoundSuperellipseTest, ContractTwoScalars) {
479 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
480 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
481 {
482 .top_left =
Size(1.0f, 2.0f),
483 .top_right =
Size(3.0f, 4.0f),
484 .bottom_left =
Size(5.0f, 6.0f),
485 .bottom_right =
Size(7.0f, 8.0f),
486 });
487 RoundSuperellipse expanded = rse.Expand(-1.0, -2.0);
488
489 EXPECT_FALSE(expanded.IsEmpty());
490 EXPECT_FALSE(expanded.IsRect());
491 EXPECT_FALSE(expanded.IsOval());
492 EXPECT_TRUE(expanded.IsFinite());
493 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
494 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 12.0f, 39.0f, 38.0f));
495 EXPECT_EQ(expanded.GetRadii().top_left,
Size(1.0f, 2.0f));
496 EXPECT_EQ(expanded.GetRadii().top_right,
Size(3.0f, 4.0f));
497 EXPECT_EQ(expanded.GetRadii().bottom_left,
Size(5.0f, 6.0f));
498 EXPECT_EQ(expanded.GetRadii().bottom_right,
Size(7.0f, 8.0f));
499
500 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
501 Rect::MakeXYWH(11.0f, 12.0f, 28.0f, 26.0f),
502 {
503 .top_left =
Size(1.0f, 2.0f),
504 .top_right =
Size(3.0f, 4.0f),
505 .bottom_left =
Size(5.0f, 6.0f),
506 .bottom_right =
Size(7.0f, 8.0f),
507 }));
508}
509
510TEST(RoundSuperellipseTest, ContractFourScalars) {
511 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
512 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
513 {
514 .top_left =
Size(1.0f, 2.0f),
515 .top_right =
Size(3.0f, 4.0f),
516 .bottom_left =
Size(5.0f, 6.0f),
517 .bottom_right =
Size(7.0f, 8.0f),
518 });
519 RoundSuperellipse expanded = rse.Expand(-1.0, -1.5, -2.0, -2.5);
520
521 EXPECT_FALSE(expanded.IsEmpty());
522 EXPECT_FALSE(expanded.IsRect());
523 EXPECT_FALSE(expanded.IsOval());
524 EXPECT_TRUE(expanded.IsFinite());
525 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
526 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 11.5f, 38.0f, 37.5f));
527 EXPECT_EQ(expanded.GetRadii().top_left,
Size(1.0f, 2.0f));
528 EXPECT_EQ(expanded.GetRadii().top_right,
Size(3.0f, 4.0f));
529 EXPECT_EQ(expanded.GetRadii().bottom_left,
Size(5.0f, 6.0f));
530 EXPECT_EQ(expanded.GetRadii().bottom_right,
Size(7.0f, 8.0f));
531
532 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
533 Rect::MakeXYWH(11.0f, 11.5f, 27.0f, 26.0f),
534 {
535 .top_left =
Size(1.0f, 2.0f),
536 .top_right =
Size(3.0f, 4.0f),
537 .bottom_left =
Size(5.0f, 6.0f),
538 .bottom_right =
Size(7.0f, 8.0f),
539 }));
540}
541
542TEST(RoundSuperellipseTest, ContractAndRequireRadiiAdjustment) {
543 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
544 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
545 {
546 .top_left =
Size(1.0f, 2.0f),
547 .top_right =
Size(3.0f, 4.0f),
548 .bottom_left =
Size(5.0f, 6.0f),
549 .bottom_right =
Size(7.0f, 8.0f),
550 });
551 RoundSuperellipse expanded = rse.Expand(-12.0);
552
553
554
555
556
557 EXPECT_FALSE(expanded.IsEmpty());
558 EXPECT_FALSE(expanded.IsRect());
559 EXPECT_FALSE(expanded.IsOval());
560 EXPECT_TRUE(expanded.IsFinite());
561 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
562 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(22.0f, 22.0f, 28.0f, 28.0f));
563 EXPECT_EQ(expanded.GetRadii().top_left,
Size(0.5f, 1.0f));
564 EXPECT_EQ(expanded.GetRadii().top_right,
Size(1.5f, 2.0f));
565 EXPECT_EQ(expanded.GetRadii().bottom_left,
Size(2.5f, 3.0f));
566 EXPECT_EQ(expanded.GetRadii().bottom_right,
Size(3.5f, 4.0f));
567
568
569
570 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
571 Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
572 {
573 .top_left =
Size(1.0f, 2.0f),
574 .top_right =
Size(3.0f, 4.0f),
575 .bottom_left =
Size(5.0f, 6.0f),
576 .bottom_right =
Size(7.0f, 8.0f),
577 }));
578
579
580
581
582 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
583 Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
584 {
585 .top_left =
Size(0.5f, 1.0f),
586 .top_right =
Size(1.5f, 2.0f),
587 .bottom_left =
Size(2.5f, 3.0f),
588 .bottom_right =
Size(3.5f, 4.0f),
589 }));
590}
591
592TEST(RoundSuperellipseTest, NoCornerRoundSuperellipseContains) {
593 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
594
595
596 auto no_corners = RoundSuperellipse::MakeRectRadii(
597 bounds, RoundingRadii::MakeRadii({0.0f, 0.0f}));
598
599 EXPECT_TRUE(no_corners.Contains({-50, -50}));
600
601
602 EXPECT_TRUE(no_corners.Contains({-50, 49.99}));
603 EXPECT_TRUE(no_corners.Contains({49.99, -50}));
604 EXPECT_TRUE(no_corners.Contains({49.99, 49.99}));
605 EXPECT_FALSE(no_corners.Contains({-50.01, -50}));
606 EXPECT_FALSE(no_corners.Contains({-50, -50.01}));
607 EXPECT_FALSE(no_corners.Contains({-50.01, 50}));
608 EXPECT_FALSE(no_corners.Contains({-50, 50.01}));
609 EXPECT_FALSE(no_corners.Contains({50.01, -50}));
610 EXPECT_FALSE(no_corners.Contains({50, -50.01}));
611 EXPECT_FALSE(no_corners.Contains({50.01, 50}));
612 EXPECT_FALSE(no_corners.Contains({50, 50.01}));
613}
614
615TEST(RoundSuperellipseTest, TinyCornerContains) {
616 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
617
618
619 auto tiny_corners = RoundSuperellipse::MakeRectRadii(
620 bounds, RoundingRadii::MakeRadii({0.01f, 0.01f}));
621
622 EXPECT_FALSE(tiny_corners.Contains({-50, -50}));
623 EXPECT_FALSE(tiny_corners.Contains({-50, 50}));
624 EXPECT_FALSE(tiny_corners.Contains({50, -50}));
625 EXPECT_FALSE(tiny_corners.Contains({50, 50}));
626}
627
628TEST(RoundSuperellipseTest, UniformSquareContains) {
629 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
630 auto rr = RoundSuperellipse::MakeRectRadii(
631 bounds, RoundingRadii::MakeRadii({5.0f, 5.0f}));
632
633#define CHECK_POINT_AND_MIRRORS(p) \
634 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, 0.02)); \
635 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(1, -1), Point(0.02, -0.02)); \
636 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, 1), Point(-0.02, 0.02)); \
637 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, -0.02));
638
646#undef CHECK_POINT_AND_MIRRORS
647}
648
649TEST(RoundSuperellipseTest, UniformEllipticalContains) {
650 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
651 auto rr = RoundSuperellipse::MakeRectRadii(
652 bounds, RoundingRadii::MakeRadii({5.0f, 10.0f}));
653
654#define CHECK_POINT_AND_MIRRORS(p) \
655 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, 0.02)); \
656 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(1, -1), Point(0.02, -0.02)); \
657 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, 1), Point(-0.02, 0.02)); \
658 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, -0.02));
659
667#undef CHECK_POINT_AND_MIRRORS
668}
669
670TEST(RoundSuperellipseTest, UniformRectangularContains) {
671
672 Rect bounds = Rect::MakeLTRB(0.0f, 0.0f, 50.0f, 100.0f);
673 auto rr = RoundSuperellipse::MakeRectRadii(
674 bounds, RoundingRadii::MakeRadii({23.0f, 30.0f}));
675
677#define CHECK_POINT_AND_MIRRORS(p) \
678 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(1, 1) + center, \
679 Point(0.02, 0.02)); \
680 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(1, -1) + center, \
681 Point(0.02, -0.02)); \
682 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(-1, 1) + center, \
683 Point(-0.02, 0.02)); \
684 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(-1, -1) + center, \
685 Point(-0.02, -0.02));
686
696
697#undef CHECK_POINT_AND_MIRRORS
698}
699
700TEST(RoundSuperellipseTest, SlimDiagonalContains) {
701
702
703 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
704 auto rr = RoundSuperellipse::MakeRectRadii(
705 bounds, {
706 .top_left =
Size(1.0, 1.0),
707 .top_right =
Size(99.0, 99.0),
708 .bottom_left =
Size(99.0, 99.0),
709 .bottom_right =
Size(1.0, 1.0),
710 });
711
712 EXPECT_TRUE(rr.Contains(Point{0, 0}));
713 EXPECT_FALSE(rr.Contains(Point{-49.999, -49.999}));
714 EXPECT_FALSE(rr.Contains(Point{-49.999, 49.999}));
715 EXPECT_FALSE(rr.Contains(Point{49.999, 49.999}));
716 EXPECT_FALSE(rr.Contains(Point{49.999, -49.999}));
717
718
721
722
723#define CHECK_DIAGONAL_POINTS(p) \
724 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, -0.02)); \
725 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, 0.02));
726
727
734#undef CHECK_POINT_AND_MIRRORS
735}
736
737TEST(RoundSuperellipseTest, PointsOutsideOfSharpCorner) {
738 Rect bounds = Rect::MakeLTRB(196.0f, 0.0f, 294.0f, 28.0f);
739
740
741
742
743 auto rr = RoundSuperellipseParam::MakeBoundsRadii(
744 bounds, {
745 .top_left =
Size(0.0, 0.0),
746 .top_right =
Size(3.0, 3.0),
747 .bottom_left =
Size(0.0, 0.0),
748 .bottom_right =
Size(3.0, 3.0),
749 });
750
751 EXPECT_FALSE(rr.Contains(Point{147.0, 14.0}));
752}
753
754TEST(RoundSuperellipseTest,
755 PathForRectangularRseWithShapeCornersShouldBeWithinBounds) {
756 Rect bounds = Rect::MakeLTRB(34.0f, 242.0f, 766.0f, 358.0f);
757
758
759
760
761
762
763
764 auto rr = RoundSuperellipseParam::MakeBoundsRadii(
765 bounds, {
766 .top_left =
Size(14.0, 14.0),
767 .top_right =
Size(14.0, 14.0),
768 .bottom_left =
Size(0.0, 0.0),
769 .bottom_right =
Size(0.0, 0.0),
770 });
771 SpyPathReceiver receiver;
772 receiver.SpyLineTo(
773 [&](const Point& p2) { EXPECT_TRUE(bounds.ContainsInclusive(p2)); });
774 receiver.SpyCubicTo([&](const Point& cp1, const Point& cp2, const Point& p2) {
775 EXPECT_TRUE(bounds.ContainsInclusive(p2));
776 });
777
778 rr.Dispatch(receiver);
779}
780
781}
782}
TEST(AsciiTableTest, Simple)
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
void CubicTo(PathBuilder *builder, Scalar x1, Scalar y1, Scalar x2, Scalar y2, Scalar x3, Scalar y3)
void Close(PathBuilder *builder)
#define CHECK_DIAGONAL_POINTS(p)
#define CHECK_POINT_AND_MIRRORS(p)