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);
466 auto path_b = path_a;
468 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
469 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
470 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
472 auto poly_a = path_a.CreatePolyline(1.0);
473 auto poly_b = path_b.CreatePolyline(1.0);
475 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
476 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
478 for (
auto i = 0u; i < poly_a.points->size(); i++) {
479 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
482 for (
auto i = 0u; i < poly_a.contours.size(); i++) {
483 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
484 EXPECT_EQ(poly_a.contours[i].start_direction,
485 poly_b.contours[i].start_direction);
489 TEST(PathTest, PathBuilderDoesNotMutateCopiedPaths) {
490 auto test_isolation =
491 [](
const std::function<void(
PathBuilder & builder)>& mutator,
492 bool will_close,
Point mutation_offset,
const std::string& label) {
498 auto verify_path = [](
const Path& path,
bool is_mutated,
bool is_closed,
512 EXPECT_EQ(contour.
is_closed, is_closed) << label;
529 verify_path(path1,
false,
false, {},
530 "Initial Path1 state before " + label);
532 for (
int i = 0; i < 10; i++) {
535 path,
false,
false, {},
536 "Extra CopyPath #" + std::to_string(i + 1) +
" for " + label);
539 verify_path(path1,
false,
false, {},
540 "Path1 state after subsequent " + label);
543 verify_path(path1,
false,
false, {},
544 "Path1 state after subsequent " + label +
" and CopyPath");
545 verify_path(path2,
true, will_close, mutation_offset,
546 "Initial Path2 state with subsequent " + label);
553 false, {},
"SetConvex");
559 false, {},
"SetUnknownConvex");
569 builder.
MoveTo({20, 30},
false);
571 false, {},
"Absolute MoveTo");
575 builder.
MoveTo({20, 30},
true);
577 false, {},
"Relative MoveTo");
581 builder.
LineTo({20, 30},
false);
583 false, {},
"Absolute LineTo");
587 builder.
LineTo({20, 30},
true);
589 false, {},
"Relative LineTo");
595 false, {},
"Absolute HorizontalLineTo");
601 false, {},
"Relative HorizontalLineTo");
607 false, {},
"Absolute VerticalLineTo");
613 false, {},
"Relative VerticalLineTo");
619 false, {},
"Absolute QuadraticCurveTo");
625 false, {},
"Relative QuadraticCurveTo");
629 builder.
CubicCurveTo({20, 30}, {30, 20}, {30, 30},
false);
631 false, {},
"Absolute CubicCurveTo");
635 builder.
CubicCurveTo({20, 30}, {30, 20}, {30, 30},
true);
637 false, {},
"Relative CubicCurveTo");
641 builder.
AddLine({100, 100}, {150, 100});
643 false, {},
"AddLine");
649 false, {},
"AddRect");
655 false, {},
"AddOval");
661 false, {},
"AddCircle");
668 false, {},
"AddArc");
674 false, {},
"AddQuadraticCurve");
678 builder.
AddCubicCurve({100, 100}, {150, 100}, {100, 150}, {150, 150});
680 false, {},
"AddCubicCurve");
684 builder.
Shift({23, 42});
686 false, {23, 42},
"Shift");