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});
33 auto polyline = builder.TakePath().CreatePolyline(1.0f);
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);
44TEST(PathTest, PathBuilderSetsCorrectContourPropertiesForAddCommands) {
49 path.GetContourComponentAtIndex(0,
contour);
58 path.GetContourComponentAtIndex(0,
contour);
67 path.GetContourComponentAtIndex(0,
contour);
77 path.GetContourComponentAtIndex(0,
contour);
88 path.GetContourComponentAtIndex(0,
contour);
98 path.GetContourComponentAtIndex(0,
contour);
100 ASSERT_FALSE(
contour.is_closed);
106 .
AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
109 path.GetContourComponentAtIndex(0,
contour);
111 ASSERT_FALSE(
contour.is_closed);
119 path.GetContourComponentAtIndex(0,
contour);
121 ASSERT_FALSE(
contour.is_closed);
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());
214 1.0f, std::move(point_buffer),
215 [point_buffer_address](
217 ASSERT_EQ(point_buffer->size(), 0u);
218 ASSERT_EQ(point_buffer_address,
219 reinterpret_cast<uintptr_t
>(point_buffer.get()));
268TEST(PathTest, PathBuilderWillComputeBounds) {
270 auto path_1 = builder.AddLine({0, 0}, {1, 1}).TakePath();
275 auto path_2 = builder.AddLine({-1, -1}, {1, 1}).TakePath();
282 auto path_3 = builder.AddLine({0, 0}, {1, 1})
339TEST(PathTest, BoundingBoxCubic) {
342 builder.AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
344 auto box = path.GetBoundingBox();
346 ASSERT_TRUE(box.has_value());
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();
357 ASSERT_TRUE(actual.has_value());
361TEST(PathTest, ExtremaOfCubicPathComponentIsCorrect) {
363 {-6.2857933, 204.356461},
364 {-4.53997231, 156.552902},
365 {17.0067291, 109.472488}};
366 auto points = cubic.Extrema();
368 ASSERT_EQ(
points.size(),
static_cast<size_t>(3));
372TEST(PathTest, PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect) {
375 builder.AddCubicCurve({0, 1}, {2, 3}, {4, 5}, {6, 7});
376 auto path = builder.TakePath();
377 auto actual = path.GetBoundingBox();
380 ASSERT_TRUE(actual.has_value());
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})
405 ASSERT_EQ(path.GetComponentCount(), 6u);
411 path.EnumerateComponents(
415 ASSERT_EQ(index, 1u);
423 ASSERT_EQ(index, 3u);
424 ASSERT_EQ(quad.p1, p1);
425 ASSERT_EQ(quad.cp, cp);
426 ASSERT_EQ(quad.p2, p2);
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);
443 ASSERT_EQ(
contour.destination, p1);
444 }
else if (index == 2u) {
446 ASSERT_EQ(
contour.destination, p1);
447 }
else if (index == 4u) {
449 ASSERT_EQ(
contour.destination, p1);
453 ASSERT_FALSE(
contour.is_closed);
503 builder.MoveTo({10, 10});
504 builder.LineTo({20, 20});
510 auto path_b = path_a;
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());
516 auto poly_a = path_a.CreatePolyline(1.0);
517 auto poly_b = path_b.CreatePolyline(1.0);
519 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
520 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
522 for (
auto i = 0u; i < poly_a.points->size(); i++) {
523 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
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);
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});
542 auto verify_path = [](
const Path& path,
bool is_mutated,
bool is_closed,
548 EXPECT_GE(path.GetComponentCount(), 3u) << label;
550 EXPECT_EQ(path.GetComponentCount(), 3u) << label;
556 EXPECT_EQ(
contour.is_closed, is_closed) << label;
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;
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;
572 auto path1 = builder.CopyPath();
573 verify_path(
path1,
false,
false, {},
574 "Initial Path1 state before " + label);
576 for (
int i = 0; i < 10; i++) {
577 auto path = builder.CopyPath();
579 path,
false,
false, {},
580 "Extra CopyPath #" + std::to_string(i + 1) +
" for " + label);
583 verify_path(
path1,
false,
false, {},
584 "Path1 state after subsequent " + label);
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);
597 false, {},
"SetConvex");
603 false, {},
"SetUnknownConvex");
613 builder.MoveTo({20, 30},
false);
615 false, {},
"Absolute MoveTo");
619 builder.MoveTo({20, 30},
true);
621 false, {},
"Relative MoveTo");
625 builder.LineTo({20, 30},
false);
627 false, {},
"Absolute LineTo");
631 builder.LineTo({20, 30},
true);
633 false, {},
"Relative LineTo");
637 builder.HorizontalLineTo(100,
false);
639 false, {},
"Absolute HorizontalLineTo");
643 builder.HorizontalLineTo(100,
true);
645 false, {},
"Relative HorizontalLineTo");
649 builder.VerticalLineTo(100,
false);
651 false, {},
"Absolute VerticalLineTo");
655 builder.VerticalLineTo(100,
true);
657 false, {},
"Relative VerticalLineTo");
661 builder.QuadraticCurveTo({20, 30}, {30, 20},
false);
663 false, {},
"Absolute QuadraticCurveTo");
667 builder.QuadraticCurveTo({20, 30}, {30, 20},
true);
669 false, {},
"Relative QuadraticCurveTo");
673 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30},
false);
675 false, {},
"Absolute CubicCurveTo");
679 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30},
true);
681 false, {},
"Relative CubicCurveTo");
685 builder.AddLine({100, 100}, {150, 100});
687 false, {},
"AddLine");
693 false, {},
"AddRect");
699 false, {},
"AddOval");
703 builder.AddCircle({100, 100}, 20);
705 false, {},
"AddCircle");
712 false, {},
"AddArc");
716 builder.AddQuadraticCurve({100, 100}, {150, 100}, {150, 150});
718 false, {},
"AddQuadraticCurve");
722 builder.AddCubicCurve({100, 100}, {150, 100}, {100, 150}, {150, 150});
724 false, {},
"AddCubicCurve");
728 builder.Shift({23, 42});
730 false, {23, 42},
"Shift");
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.