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