5 #include "gtest/gtest.h"
7 #include "flutter/testing/testing.h"
15 TEST(PathTest, CubicPathComponentPolylineDoesNotIncludePointOne) {
18 component.AppendPolylinePoints(1.0f,
polyline);
25 TEST(PathTest, PathCreatePolyLineDoesNotDuplicatePoints) {
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);
44 TEST(PathTest, PathBuilderSetsCorrectContourPropertiesForAddCommands) {
106 .
AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
125 TEST(PathTest, PathCreatePolylineGeneratesCorrectContourData) {
127 .
AddLine({100, 100}, {200, 100})
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);
142 TEST(PathTest, PolylineGetContourPointBoundsReturnsCorrectRanges) {
144 .
AddLine({100, 100}, {200, 100})
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);
160 TEST(PathTest, PathAddRectPolylineHasCorrectContourData) {
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);
176 TEST(PathTest, PathPolylineDuplicatesAreRemovedForSameContour) {
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);
205 TEST(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()));
223 TEST(PathTest, PolylineFailsWithNullptrBuffer) {
228 .CreatePolyline(1.0f,
nullptr),
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));
255 EXPECT_EQ(linear.
p1,
Point(1, 1));
256 EXPECT_EQ(linear.
p2,
Point(11, 11));
258 EXPECT_EQ(quad.
cp,
Point(16, 16));
259 EXPECT_EQ(quad.
p1,
Point(11, 11));
260 EXPECT_EQ(quad.
p2,
Point(21, 21));
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));
268 TEST(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})
290 TEST(PathTest, PathHorizontalLine) {
295 path.GetLinearComponentAtIndex(1, linear);
297 EXPECT_EQ(linear.
p1,
Point(0, 0));
298 EXPECT_EQ(linear.
p2,
Point(10, 0));
301 TEST(PathTest, PathVerticalLine) {
306 path.GetLinearComponentAtIndex(1, linear);
308 EXPECT_EQ(linear.
p1,
Point(0, 0));
309 EXPECT_EQ(linear.
p2,
Point(0, 10));
312 TEST(PathTest, QuadradicPath) {
317 path.GetQuadraticComponentAtIndex(1, quad);
319 EXPECT_EQ(quad.
p1,
Point(0, 0));
320 EXPECT_EQ(quad.
cp,
Point(10, 10));
321 EXPECT_EQ(quad.
p2,
Point(20, 20));
331 path.GetCubicComponentAtIndex(1, cubic);
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));
339 TEST(PathTest, BoundingBoxCubic) {
342 builder.
AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
344 auto box = path.GetBoundingBox();
346 ASSERT_TRUE(box.has_value());
350 TEST(PathTest, BoundingBoxOfCompositePathIsCorrect) {
357 ASSERT_TRUE(actual.has_value());
361 TEST(PathTest, ExtremaOfCubicPathComponentIsCorrect) {
363 {-6.2857933, 204.356461},
364 {-4.53997231, 156.552902},
365 {17.0067291, 109.472488}};
368 ASSERT_EQ(points.size(),
static_cast<size_t>(3));
372 TEST(PathTest, PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect) {
380 ASSERT_TRUE(actual.has_value());
386 ASSERT_EQ(path.GetComponentCount(), 1u);
389 path.GetContourComponentAtIndex(0, c);
393 ASSERT_TRUE(
polyline.points->empty());
394 ASSERT_TRUE(
polyline.contours.empty());
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);
416 ASSERT_EQ(linear.
p1, p1);
417 ASSERT_EQ(linear.
p2, p2);
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);
457 TEST(PathTest, RepeatCloseDoesNotAddNewLines) {
459 auto path = builder.
LineTo({0, 10})
466 EXPECT_EQ(path.GetComponentCount(), 5u);
471 TEST(PathTest, CloseAfterMoveDoesNotAddNewLines) {
473 auto path = builder.
LineTo({0, 10})
480 EXPECT_EQ(path.GetComponentCount(), 4u);
485 TEST(PathTest, CloseAtOriginDoesNotAddNewLineSegment) {
489 auto path = builder.
LineTo({10, 0})
496 EXPECT_EQ(path.GetComponentCount(), 6u);
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);
533 TEST(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) {
542 auto verify_path = [](
const Path& path,
bool is_mutated,
bool is_closed,
556 EXPECT_EQ(contour.
is_closed, is_closed) << label;
573 verify_path(path1,
false,
false, {},
574 "Initial Path1 state before " + label);
576 for (
int i = 0; i < 10; i++) {
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);
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");
639 false, {},
"Absolute HorizontalLineTo");
645 false, {},
"Relative HorizontalLineTo");
651 false, {},
"Absolute VerticalLineTo");
657 false, {},
"Relative VerticalLineTo");
663 false, {},
"Absolute QuadraticCurveTo");
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");
705 false, {},
"AddCircle");
712 false, {},
"AddArc");
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");