Flutter Engine
The Flutter Engine
path_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter 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 "gtest/gtest.h"
6
7#include "flutter/testing/testing.h"
11
12namespace impeller {
13namespace testing {
14
15TEST(PathTest, CubicPathComponentPolylineDoesNotIncludePointOne) {
16 CubicPathComponent component({10, 10}, {20, 35}, {35, 20}, {40, 40});
17 std::vector<Point> polyline;
18 component.AppendPolylinePoints(1.0f, polyline);
19 ASSERT_NE(polyline.front().x, 10);
20 ASSERT_NE(polyline.front().y, 10);
21 ASSERT_EQ(polyline.back().x, 40);
22 ASSERT_EQ(polyline.back().y, 40);
23}
24
25TEST(PathTest, PathCreatePolyLineDoesNotDuplicatePoints) {
27 builder.MoveTo({10, 10});
28 builder.LineTo({20, 20});
29 builder.LineTo({30, 30});
30 builder.MoveTo({40, 40});
31 builder.LineTo({50, 50});
32
33 auto polyline = builder.TakePath().CreatePolyline(1.0f);
34
35 ASSERT_EQ(polyline.contours.size(), 2u);
36 ASSERT_EQ(polyline.points->size(), 5u);
37 ASSERT_EQ(polyline.GetPoint(0).x, 10);
38 ASSERT_EQ(polyline.GetPoint(1).x, 20);
39 ASSERT_EQ(polyline.GetPoint(2).x, 30);
40 ASSERT_EQ(polyline.GetPoint(3).x, 40);
41 ASSERT_EQ(polyline.GetPoint(4).x, 50);
42}
43
44TEST(PathTest, PathBuilderSetsCorrectContourPropertiesForAddCommands) {
45 // Closed shapes.
46 {
47 Path path = PathBuilder{}.AddCircle({100, 100}, 50).TakePath();
49 path.GetContourComponentAtIndex(0, contour);
50 EXPECT_POINT_NEAR(contour.destination, Point(100, 50));
51 EXPECT_TRUE(contour.is_closed);
52 }
53
54 {
55 Path path =
56 PathBuilder{}.AddOval(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
58 path.GetContourComponentAtIndex(0, contour);
59 EXPECT_POINT_NEAR(contour.destination, Point(150, 100));
60 EXPECT_TRUE(contour.is_closed);
61 }
62
63 {
64 Path path =
65 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
67 path.GetContourComponentAtIndex(0, contour);
68 EXPECT_POINT_NEAR(contour.destination, Point(100, 100));
69 EXPECT_TRUE(contour.is_closed);
70 }
71
72 {
74 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), 10)
75 .TakePath();
77 path.GetContourComponentAtIndex(0, contour);
78 EXPECT_POINT_NEAR(contour.destination, Point(110, 100));
79 EXPECT_TRUE(contour.is_closed);
80 }
81
82 {
83 Path path =
85 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20))
86 .TakePath();
88 path.GetContourComponentAtIndex(0, contour);
89 EXPECT_POINT_NEAR(contour.destination, Point(110, 100));
90 EXPECT_TRUE(contour.is_closed);
91 }
92
93 // Open shapes.
94 {
95 Point p(100, 100);
96 Path path = PathBuilder{}.AddLine(p, {200, 100}).TakePath();
98 path.GetContourComponentAtIndex(0, contour);
99 ASSERT_POINT_NEAR(contour.destination, p);
100 ASSERT_FALSE(contour.is_closed);
101 }
102
103 {
104 Path path =
106 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
107 .TakePath();
109 path.GetContourComponentAtIndex(0, contour);
110 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
111 ASSERT_FALSE(contour.is_closed);
112 }
113
114 {
116 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
117 .TakePath();
119 path.GetContourComponentAtIndex(0, contour);
120 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
121 ASSERT_FALSE(contour.is_closed);
122 }
123}
124
125TEST(PathTest, PathCreatePolylineGeneratesCorrectContourData) {
127 .AddLine({100, 100}, {200, 100})
128 .MoveTo({100, 200})
129 .LineTo({150, 250})
130 .LineTo({200, 200})
131 .Close()
132 .TakePath()
133 .CreatePolyline(1.0f);
134 ASSERT_EQ(polyline.points->size(), 6u);
135 ASSERT_EQ(polyline.contours.size(), 2u);
136 ASSERT_EQ(polyline.contours[0].is_closed, false);
137 ASSERT_EQ(polyline.contours[0].start_index, 0u);
138 ASSERT_EQ(polyline.contours[1].is_closed, true);
139 ASSERT_EQ(polyline.contours[1].start_index, 2u);
140}
141
142TEST(PathTest, PolylineGetContourPointBoundsReturnsCorrectRanges) {
144 .AddLine({100, 100}, {200, 100})
145 .MoveTo({100, 200})
146 .LineTo({150, 250})
147 .LineTo({200, 200})
148 .Close()
149 .TakePath()
150 .CreatePolyline(1.0f);
151 size_t a1, a2, b1, b2;
152 std::tie(a1, a2) = polyline.GetContourPointBounds(0);
153 std::tie(b1, b2) = polyline.GetContourPointBounds(1);
154 ASSERT_EQ(a1, 0u);
155 ASSERT_EQ(a2, 2u);
156 ASSERT_EQ(b1, 2u);
157 ASSERT_EQ(b2, 6u);
158}
159
160TEST(PathTest, PathAddRectPolylineHasCorrectContourData) {
162 .AddRect(Rect::MakeLTRB(50, 60, 70, 80))
163 .TakePath()
164 .CreatePolyline(1.0f);
165 ASSERT_EQ(polyline.contours.size(), 1u);
166 ASSERT_TRUE(polyline.contours[0].is_closed);
167 ASSERT_EQ(polyline.contours[0].start_index, 0u);
168 ASSERT_EQ(polyline.points->size(), 5u);
169 ASSERT_EQ(polyline.GetPoint(0), Point(50, 60));
170 ASSERT_EQ(polyline.GetPoint(1), Point(70, 60));
171 ASSERT_EQ(polyline.GetPoint(2), Point(70, 80));
172 ASSERT_EQ(polyline.GetPoint(3), Point(50, 80));
173 ASSERT_EQ(polyline.GetPoint(4), Point(50, 60));
174}
175
176TEST(PathTest, PathPolylineDuplicatesAreRemovedForSameContour) {
179 .MoveTo({50, 50})
180 .LineTo({50, 50}) // Insert duplicate at beginning of contour.
181 .LineTo({100, 50})
182 .LineTo({100, 50}) // Insert duplicate at contour join.
183 .LineTo({100, 100})
184 .Close() // Implicitly insert duplicate {50, 50} across contours.
185 .LineTo({0, 50})
186 .LineTo({0, 100})
187 .LineTo({0, 100}) // Insert duplicate at end of contour.
188 .TakePath()
189 .CreatePolyline(1.0f);
190 ASSERT_EQ(polyline.contours.size(), 2u);
191 ASSERT_EQ(polyline.contours[0].start_index, 0u);
192 ASSERT_TRUE(polyline.contours[0].is_closed);
193 ASSERT_EQ(polyline.contours[1].start_index, 4u);
194 ASSERT_FALSE(polyline.contours[1].is_closed);
195 ASSERT_EQ(polyline.points->size(), 7u);
196 ASSERT_EQ(polyline.GetPoint(0), Point(50, 50));
197 ASSERT_EQ(polyline.GetPoint(1), Point(100, 50));
198 ASSERT_EQ(polyline.GetPoint(2), Point(100, 100));
199 ASSERT_EQ(polyline.GetPoint(3), Point(50, 50));
200 ASSERT_EQ(polyline.GetPoint(4), Point(50, 50));
201 ASSERT_EQ(polyline.GetPoint(5), Point(0, 50));
202 ASSERT_EQ(polyline.GetPoint(6), Point(0, 100));
203}
204
205TEST(PathTest, PolylineBufferReuse) {
206 auto point_buffer = std::make_unique<std::vector<Point>>();
207 auto point_buffer_address = reinterpret_cast<uintptr_t>(point_buffer.get());
210 .MoveTo({50, 50})
211 .LineTo({100, 100})
212 .TakePath()
213 .CreatePolyline(
214 1.0f, std::move(point_buffer),
215 [point_buffer_address](
216 Path::Polyline::PointBufferPtr point_buffer) {
217 ASSERT_EQ(point_buffer->size(), 0u);
218 ASSERT_EQ(point_buffer_address,
219 reinterpret_cast<uintptr_t>(point_buffer.get()));
220 });
221}
222
223TEST(PathTest, PolylineFailsWithNullptrBuffer) {
224 EXPECT_DEATH_IF_SUPPORTED(PathBuilder{}
225 .MoveTo({50, 50})
226 .LineTo({100, 100})
227 .TakePath()
228 .CreatePolyline(1.0f, nullptr),
229 "");
230}
231
232TEST(PathTest, PathShifting) {
234 auto path =
235 builder.AddLine(Point(0, 0), Point(10, 10))
236 .AddQuadraticCurve(Point(10, 10), Point(15, 15), Point(20, 20))
237 .AddCubicCurve(Point(20, 20), Point(25, 25), Point(-5, -5),
238 Point(30, 30))
239 .Close()
240 .Shift(Point(1, 1))
241 .TakePath();
242
247
248 ASSERT_TRUE(path.GetContourComponentAtIndex(0, contour));
249 ASSERT_TRUE(path.GetLinearComponentAtIndex(1, linear));
250 ASSERT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
251 ASSERT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
252
253 EXPECT_EQ(contour.destination, Point(1, 1));
254
255 EXPECT_EQ(linear.p1, Point(1, 1));
256 EXPECT_EQ(linear.p2, Point(11, 11));
257
258 EXPECT_EQ(quad.cp, Point(16, 16));
259 EXPECT_EQ(quad.p1, Point(11, 11));
260 EXPECT_EQ(quad.p2, Point(21, 21));
261
262 EXPECT_EQ(cubic.cp1, Point(26, 26));
263 EXPECT_EQ(cubic.cp2, Point(-4, -4));
264 EXPECT_EQ(cubic.p1, Point(21, 21));
265 EXPECT_EQ(cubic.p2, Point(31, 31));
266}
267
268TEST(PathTest, PathBuilderWillComputeBounds) {
270 auto path_1 = builder.AddLine({0, 0}, {1, 1}).TakePath();
271
272 ASSERT_EQ(path_1.GetBoundingBox().value_or(Rect::MakeMaximum()),
273 Rect::MakeLTRB(0, 0, 1, 1));
274
275 auto path_2 = builder.AddLine({-1, -1}, {1, 1}).TakePath();
276
277 // Verify that PathBuilder recomputes the bounds.
278 ASSERT_EQ(path_2.GetBoundingBox().value_or(Rect::MakeMaximum()),
279 Rect::MakeLTRB(-1, -1, 1, 1));
280
281 // PathBuilder can set the bounds to whatever it wants
282 auto path_3 = builder.AddLine({0, 0}, {1, 1})
283 .SetBounds(Rect::MakeLTRB(0, 0, 100, 100))
284 .TakePath();
285
286 ASSERT_EQ(path_3.GetBoundingBox().value_or(Rect::MakeMaximum()),
287 Rect::MakeLTRB(0, 0, 100, 100));
288}
289
290TEST(PathTest, PathHorizontalLine) {
292 auto path = builder.HorizontalLineTo(10).TakePath();
293
295 path.GetLinearComponentAtIndex(1, linear);
296
297 EXPECT_EQ(linear.p1, Point(0, 0));
298 EXPECT_EQ(linear.p2, Point(10, 0));
299}
300
301TEST(PathTest, PathVerticalLine) {
303 auto path = builder.VerticalLineTo(10).TakePath();
304
306 path.GetLinearComponentAtIndex(1, linear);
307
308 EXPECT_EQ(linear.p1, Point(0, 0));
309 EXPECT_EQ(linear.p2, Point(0, 10));
310}
311
312TEST(PathTest, QuadradicPath) {
314 auto path = builder.QuadraticCurveTo(Point(10, 10), Point(20, 20)).TakePath();
315
317 path.GetQuadraticComponentAtIndex(1, quad);
318
319 EXPECT_EQ(quad.p1, Point(0, 0));
320 EXPECT_EQ(quad.cp, Point(10, 10));
321 EXPECT_EQ(quad.p2, Point(20, 20));
322}
323
324TEST(PathTest, CubicPath) {
326 auto path =
327 builder.CubicCurveTo(Point(10, 10), Point(-10, -10), Point(20, 20))
328 .TakePath();
329
331 path.GetCubicComponentAtIndex(1, cubic);
332
333 EXPECT_EQ(cubic.p1, Point(0, 0));
334 EXPECT_EQ(cubic.cp1, Point(10, 10));
335 EXPECT_EQ(cubic.cp2, Point(-10, -10));
336 EXPECT_EQ(cubic.p2, Point(20, 20));
337}
338
339TEST(PathTest, BoundingBoxCubic) {
341 auto path =
342 builder.AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
343 .TakePath();
344 auto box = path.GetBoundingBox();
345 Rect expected = Rect::MakeXYWH(93.9101, 40, 126.09, 158.862);
346 ASSERT_TRUE(box.has_value());
347 ASSERT_RECT_NEAR(box.value_or(Rect::MakeMaximum()), expected);
348}
349
350TEST(PathTest, BoundingBoxOfCompositePathIsCorrect) {
352 builder.AddRoundedRect(Rect::MakeXYWH(10, 10, 300, 300), {50, 50, 50, 50});
353 auto path = builder.TakePath();
354 auto actual = path.GetBoundingBox();
355 Rect expected = Rect::MakeXYWH(10, 10, 300, 300);
356
357 ASSERT_TRUE(actual.has_value());
358 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
359}
360
361TEST(PathTest, ExtremaOfCubicPathComponentIsCorrect) {
362 CubicPathComponent cubic{{11.769268, 252.883148},
363 {-6.2857933, 204.356461},
364 {-4.53997231, 156.552902},
365 {17.0067291, 109.472488}};
366 auto points = cubic.Extrema();
367
368 ASSERT_EQ(points.size(), static_cast<size_t>(3));
369 ASSERT_POINT_NEAR(points[2], cubic.Solve(0.455916));
370}
371
372TEST(PathTest, PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect) {
374 // Straight diagonal line.
375 builder.AddCubicCurve({0, 1}, {2, 3}, {4, 5}, {6, 7});
376 auto path = builder.TakePath();
377 auto actual = path.GetBoundingBox();
378 auto expected = Rect::MakeLTRB(0, 1, 6, 7);
379
380 ASSERT_TRUE(actual.has_value());
381 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
382}
383
384TEST(PathTest, EmptyPath) {
385 auto path = PathBuilder{}.TakePath();
386 ASSERT_EQ(path.GetComponentCount(), 1u);
387
389 path.GetContourComponentAtIndex(0, c);
391
392 Path::Polyline polyline = path.CreatePolyline(1.0f);
393 ASSERT_TRUE(polyline.points->empty());
394 ASSERT_TRUE(polyline.contours.empty());
395}
396
397TEST(PathTest, SimplePath) {
399
400 auto path = builder.AddLine({0, 0}, {100, 100})
401 .AddQuadraticCurve({100, 100}, {200, 200}, {300, 300})
402 .AddCubicCurve({300, 300}, {400, 400}, {500, 500}, {600, 600})
403 .TakePath();
404
405 ASSERT_EQ(path.GetComponentCount(), 6u);
406 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 1u);
407 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kQuadratic), 1u);
408 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kCubic), 1u);
409 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 3u);
410
411 path.EnumerateComponents(
412 [](size_t index, const LinearPathComponent& linear) {
413 Point p1(0, 0);
414 Point p2(100, 100);
415 ASSERT_EQ(index, 1u);
416 ASSERT_EQ(linear.p1, p1);
417 ASSERT_EQ(linear.p2, p2);
418 },
419 [](size_t index, const QuadraticPathComponent& quad) {
420 Point p1(100, 100);
421 Point cp(200, 200);
422 Point p2(300, 300);
423 ASSERT_EQ(index, 3u);
424 ASSERT_EQ(quad.p1, p1);
425 ASSERT_EQ(quad.cp, cp);
426 ASSERT_EQ(quad.p2, p2);
427 },
428 [](size_t index, const CubicPathComponent& cubic) {
429 Point p1(300, 300);
430 Point cp1(400, 400);
431 Point cp2(500, 500);
432 Point p2(600, 600);
433 ASSERT_EQ(index, 5u);
434 ASSERT_EQ(cubic.p1, p1);
435 ASSERT_EQ(cubic.cp1, cp1);
436 ASSERT_EQ(cubic.cp2, cp2);
437 ASSERT_EQ(cubic.p2, p2);
438 },
439 [](size_t index, const ContourComponent& contour) {
440 // There is an initial countour added for each curve.
441 if (index == 0u) {
442 Point p1(0, 0);
443 ASSERT_EQ(contour.destination, p1);
444 } else if (index == 2u) {
445 Point p1(100, 100);
446 ASSERT_EQ(contour.destination, p1);
447 } else if (index == 4u) {
448 Point p1(300, 300);
449 ASSERT_EQ(contour.destination, p1);
450 } else {
451 ASSERT_FALSE(true);
452 }
453 ASSERT_FALSE(contour.is_closed);
454 });
455}
456
457TEST(PathTest, RepeatCloseDoesNotAddNewLines) {
459 auto path = builder.LineTo({0, 10})
460 .LineTo({10, 10})
461 .Close() // Returns to (0, 0)
462 .Close() // No Op
463 .Close() // Still No op
464 .TakePath();
465
466 EXPECT_EQ(path.GetComponentCount(), 5u);
467 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 3u);
468 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
469}
470
471TEST(PathTest, CloseAfterMoveDoesNotAddNewLines) {
473 auto path = builder.LineTo({0, 10})
474 .LineTo({10, 10})
475 .MoveTo({30, 30}) // Moves to (30, 30)
476 .Close() // No Op
477 .Close() // Still No op
478 .TakePath();
479
480 EXPECT_EQ(path.GetComponentCount(), 4u);
481 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 2u);
482 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
483}
484
485TEST(PathTest, CloseAtOriginDoesNotAddNewLineSegment) {
487 // Create a path that has a current position at the origin when close is
488 // called. This should not insert a new line segment
489 auto path = builder.LineTo({10, 0})
490 .LineTo({10, 10})
491 .LineTo({0, 10})
492 .LineTo({0, 0})
493 .Close()
494 .TakePath();
495
496 EXPECT_EQ(path.GetComponentCount(), 6u);
497 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 4u);
498 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
499}
500
501TEST(PathTest, CanBeCloned) {
503 builder.MoveTo({10, 10});
504 builder.LineTo({20, 20});
505 builder.SetBounds(Rect::MakeLTRB(0, 0, 100, 100));
506 builder.SetConvexity(Convexity::kConvex);
507
508 auto path_a = builder.TakePath(FillType::kOdd);
509 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
510 auto path_b = path_a;
511
512 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
513 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
514 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
515
516 auto poly_a = path_a.CreatePolyline(1.0);
517 auto poly_b = path_b.CreatePolyline(1.0);
518
519 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
520 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
521
522 for (auto i = 0u; i < poly_a.points->size(); i++) {
523 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
524 }
525
526 for (auto i = 0u; i < poly_a.contours.size(); i++) {
527 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
528 EXPECT_EQ(poly_a.contours[i].start_direction,
529 poly_b.contours[i].start_direction);
530 }
531}
532
533TEST(PathTest, PathBuilderDoesNotMutateCopiedPaths) {
534 auto test_isolation =
535 [](const std::function<void(PathBuilder & builder)>& mutator,
536 bool will_close, Point mutation_offset, const std::string& label) {
538 builder.MoveTo({10, 10});
539 builder.LineTo({20, 20});
540 builder.LineTo({20, 10});
541
542 auto verify_path = [](const Path& path, bool is_mutated, bool is_closed,
543 Point offset, const std::string& label) {
544 if (is_mutated) {
545 // We can only test the initial state before the mutator did
546 // its work. We have >= 3 components and the first 3 components
547 // will match what we saw before the mutation.
548 EXPECT_GE(path.GetComponentCount(), 3u) << label;
549 } else {
550 EXPECT_EQ(path.GetComponentCount(), 3u) << label;
551 }
552 {
554 EXPECT_TRUE(path.GetContourComponentAtIndex(0, contour)) << label;
555 EXPECT_EQ(contour.destination, offset + Point(10, 10)) << label;
556 EXPECT_EQ(contour.is_closed, is_closed) << label;
557 }
558 {
560 EXPECT_TRUE(path.GetLinearComponentAtIndex(1, line)) << label;
561 EXPECT_EQ(line.p1, offset + Point(10, 10)) << label;
562 EXPECT_EQ(line.p2, offset + Point(20, 20)) << label;
563 }
564 {
566 EXPECT_TRUE(path.GetLinearComponentAtIndex(2, line)) << label;
567 EXPECT_EQ(line.p1, offset + Point(20, 20)) << label;
568 EXPECT_EQ(line.p2, offset + Point(20, 10)) << label;
569 }
570 };
571
572 auto path1 = builder.CopyPath();
573 verify_path(path1, false, false, {},
574 "Initial Path1 state before " + label);
575
576 for (int i = 0; i < 10; i++) {
577 auto path = builder.CopyPath();
578 verify_path(
579 path, false, false, {},
580 "Extra CopyPath #" + std::to_string(i + 1) + " for " + label);
581 }
582 mutator(builder);
583 verify_path(path1, false, false, {},
584 "Path1 state after subsequent " + label);
585
586 auto path2 = builder.CopyPath();
587 verify_path(path1, false, false, {},
588 "Path1 state after subsequent " + label + " and CopyPath");
589 verify_path(path2, true, will_close, mutation_offset,
590 "Initial Path2 state with subsequent " + label);
591 };
592
593 test_isolation(
594 [](PathBuilder& builder) { //
595 builder.SetConvexity(Convexity::kConvex);
596 },
597 false, {}, "SetConvex");
598
599 test_isolation(
600 [](PathBuilder& builder) { //
601 builder.SetConvexity(Convexity::kUnknown);
602 },
603 false, {}, "SetUnknownConvex");
604
605 test_isolation(
606 [](PathBuilder& builder) { //
607 builder.Close();
608 },
609 true, {}, "Close");
610
611 test_isolation(
612 [](PathBuilder& builder) {
613 builder.MoveTo({20, 30}, false);
614 },
615 false, {}, "Absolute MoveTo");
616
617 test_isolation(
618 [](PathBuilder& builder) {
619 builder.MoveTo({20, 30}, true);
620 },
621 false, {}, "Relative MoveTo");
622
623 test_isolation(
624 [](PathBuilder& builder) {
625 builder.LineTo({20, 30}, false);
626 },
627 false, {}, "Absolute LineTo");
628
629 test_isolation(
630 [](PathBuilder& builder) {
631 builder.LineTo({20, 30}, true);
632 },
633 false, {}, "Relative LineTo");
634
635 test_isolation(
636 [](PathBuilder& builder) { //
637 builder.HorizontalLineTo(100, false);
638 },
639 false, {}, "Absolute HorizontalLineTo");
640
641 test_isolation(
642 [](PathBuilder& builder) { //
643 builder.HorizontalLineTo(100, true);
644 },
645 false, {}, "Relative HorizontalLineTo");
646
647 test_isolation(
648 [](PathBuilder& builder) { //
649 builder.VerticalLineTo(100, false);
650 },
651 false, {}, "Absolute VerticalLineTo");
652
653 test_isolation(
654 [](PathBuilder& builder) { //
655 builder.VerticalLineTo(100, true);
656 },
657 false, {}, "Relative VerticalLineTo");
658
659 test_isolation(
660 [](PathBuilder& builder) {
661 builder.QuadraticCurveTo({20, 30}, {30, 20}, false);
662 },
663 false, {}, "Absolute QuadraticCurveTo");
664
665 test_isolation(
666 [](PathBuilder& builder) {
667 builder.QuadraticCurveTo({20, 30}, {30, 20}, true);
668 },
669 false, {}, "Relative QuadraticCurveTo");
670
671 test_isolation(
672 [](PathBuilder& builder) {
673 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, false);
674 },
675 false, {}, "Absolute CubicCurveTo");
676
677 test_isolation(
678 [](PathBuilder& builder) {
679 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, true);
680 },
681 false, {}, "Relative CubicCurveTo");
682
683 test_isolation(
684 [](PathBuilder& builder) {
685 builder.AddLine({100, 100}, {150, 100});
686 },
687 false, {}, "AddLine");
688
689 test_isolation(
690 [](PathBuilder& builder) {
691 builder.AddRect(Rect::MakeLTRB(100, 100, 120, 120));
692 },
693 false, {}, "AddRect");
694
695 test_isolation(
696 [](PathBuilder& builder) {
697 builder.AddOval(Rect::MakeLTRB(100, 100, 120, 120));
698 },
699 false, {}, "AddOval");
700
701 test_isolation(
702 [](PathBuilder& builder) {
703 builder.AddCircle({100, 100}, 20);
704 },
705 false, {}, "AddCircle");
706
707 test_isolation(
708 [](PathBuilder& builder) {
709 builder.AddArc(Rect::MakeLTRB(100, 100, 120, 120), Degrees(10),
710 Degrees(170));
711 },
712 false, {}, "AddArc");
713
714 test_isolation(
715 [](PathBuilder& builder) {
716 builder.AddQuadraticCurve({100, 100}, {150, 100}, {150, 150});
717 },
718 false, {}, "AddQuadraticCurve");
719
720 test_isolation(
721 [](PathBuilder& builder) {
722 builder.AddCubicCurve({100, 100}, {150, 100}, {100, 150}, {150, 150});
723 },
724 false, {}, "AddCubicCurve");
725
726 test_isolation(
727 [](PathBuilder& builder) {
728 builder.Shift({23, 42});
729 },
730 false, {23, 42}, "Shift");
731}
732
733} // namespace testing
734} // namespace impeller
static const int points[]
static SkPath path1()
static SkPath path2()
PathBuilder & AddRect(Rect rect)
Path TakePath(FillType fill=FillType::kNonZero)
Definition: path_builder.cc:22
PathBuilder & MoveTo(Point point, bool relative=false)
Definition: path_builder.cc:33
PathBuilder & AddOval(const Rect &rect)
PathBuilder & AddCircle(const Point &center, Scalar radius)
PathBuilder & AddLine(const Point &p1, const Point &p2)
Move to point p1, then insert a line from p1 to p2.
PathBuilder & AddRoundedRect(Rect rect, RoundingRadii radii)
PathBuilder & AddQuadraticCurve(Point p1, Point cp, Point p2)
Move to point p1, then insert a quadradic curve from p1 to p2 with the control point cp.
PathBuilder & AddCubicCurve(Point p1, Point cp1, Point cp2, Point p2)
Move to point p1, then insert a cubic curve from p1 to p2 with control points cp1 and cp2.
Dart_NativeFunction function
Definition: fuchsia.cc:51
#define ASSERT_RECT_NEAR(a, b)
#define ASSERT_POINT_NEAR(a, b)
#define EXPECT_POINT_NEAR(a, b)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
TEST(AiksCanvasTest, EmptyCullRect)
TPoint< Scalar > Point
Definition: point.h:322
TSize< Scalar > Size
Definition: size.h:137
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:20
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:24
void Close(PathBuilder *builder)
Definition: tessellator.cc:38
AI float cubic(float precision, const SkPoint pts[], const VectorXform &vectorXform=VectorXform())
Definition: WangsFormula.h:195
static SkString to_string(int n)
Definition: nanobench.cpp:119
const Path::Polyline & polyline
SeparatedVector2 offset
std::unique_ptr< std::vector< Point > > PointBufferPtr
Definition: path.h:98
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
static constexpr TRect MakeMaximum()
Definition: rect.h:174
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)