5 #include "gtest/gtest.h"
7 #include "flutter/testing/testing.h"
16 TEST(PathTest, CubicPathComponentPolylineDoesNotIncludePointOne) {
19 component.AppendPolylinePoints(1.0f,
polyline);
26 TEST(PathTest, EmptyPathWithContour) {
30 EXPECT_TRUE(path.IsEmpty());
33 TEST(PathTest, PathCreatePolyLineDoesNotDuplicatePoints) {
43 ASSERT_EQ(
polyline.contours.size(), 2u);
44 ASSERT_EQ(
polyline.points->size(), 5u);
45 ASSERT_EQ(
polyline.GetPoint(0).x, 10);
46 ASSERT_EQ(
polyline.GetPoint(1).x, 20);
47 ASSERT_EQ(
polyline.GetPoint(2).x, 30);
48 ASSERT_EQ(
polyline.GetPoint(3).x, 40);
49 ASSERT_EQ(
polyline.GetPoint(4).x, 50);
52 TEST(PathTest, PathBuilderSetsCorrectContourPropertiesForAddCommands) {
114 .
AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
133 TEST(PathTest, PathCreatePolylineGeneratesCorrectContourData) {
135 .
AddLine({100, 100}, {200, 100})
141 .CreatePolyline(1.0f);
142 ASSERT_EQ(
polyline.points->size(), 6u);
143 ASSERT_EQ(
polyline.contours.size(), 2u);
144 ASSERT_EQ(
polyline.contours[0].is_closed,
false);
145 ASSERT_EQ(
polyline.contours[0].start_index, 0u);
146 ASSERT_EQ(
polyline.contours[1].is_closed,
true);
147 ASSERT_EQ(
polyline.contours[1].start_index, 2u);
150 TEST(PathTest, PolylineGetContourPointBoundsReturnsCorrectRanges) {
152 .
AddLine({100, 100}, {200, 100})
158 .CreatePolyline(1.0f);
159 size_t a1, a2, b1, b2;
160 std::tie(a1, a2) =
polyline.GetContourPointBounds(0);
161 std::tie(b1, b2) =
polyline.GetContourPointBounds(1);
168 TEST(PathTest, PathAddRectPolylineHasCorrectContourData) {
173 ASSERT_EQ(
polyline.contours.size(), 1u);
174 ASSERT_TRUE(
polyline.contours[0].is_closed);
175 ASSERT_EQ(
polyline.contours[0].start_index, 0u);
176 ASSERT_EQ(
polyline.points->size(), 5u);
184 TEST(PathTest, PathPolylineDuplicatesAreRemovedForSameContour) {
197 .CreatePolyline(1.0f);
198 ASSERT_EQ(
polyline.contours.size(), 2u);
199 ASSERT_EQ(
polyline.contours[0].start_index, 0u);
200 ASSERT_TRUE(
polyline.contours[0].is_closed);
201 ASSERT_EQ(
polyline.contours[1].start_index, 4u);
202 ASSERT_FALSE(
polyline.contours[1].is_closed);
203 ASSERT_EQ(
polyline.points->size(), 7u);
213 TEST(PathTest, PolylineBufferReuse) {
214 auto point_buffer = std::make_unique<std::vector<Point>>();
215 auto point_buffer_address =
reinterpret_cast<uintptr_t
>(point_buffer.get());
222 1.0f, std::move(point_buffer),
223 [point_buffer_address](
225 ASSERT_EQ(point_buffer->size(), 0u);
226 ASSERT_EQ(point_buffer_address,
227 reinterpret_cast<uintptr_t
>(point_buffer.get()));
231 TEST(PathTest, PolylineFailsWithNullptrBuffer) {
236 .CreatePolyline(1.0f,
nullptr),
256 ASSERT_TRUE(path.GetContourComponentAtIndex(0, contour));
257 ASSERT_TRUE(path.GetLinearComponentAtIndex(1, linear));
258 ASSERT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
259 ASSERT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
263 EXPECT_EQ(linear.
p1,
Point(1, 1));
264 EXPECT_EQ(linear.
p2,
Point(11, 11));
266 EXPECT_EQ(quad.
cp,
Point(16, 16));
267 EXPECT_EQ(quad.
p1,
Point(11, 11));
268 EXPECT_EQ(quad.
p2,
Point(21, 21));
270 EXPECT_EQ(cubic.
cp1,
Point(26, 26));
271 EXPECT_EQ(cubic.
cp2,
Point(-4, -4));
272 EXPECT_EQ(cubic.
p1,
Point(21, 21));
273 EXPECT_EQ(cubic.
p2,
Point(31, 31));
276 TEST(PathTest, PathBuilderWillComputeBounds) {
278 auto path_1 = builder.
AddLine({0, 0}, {1, 1}).TakePath();
283 auto path_2 = builder.
AddLine({-1, -1}, {1, 1}).TakePath();
290 auto path_3 = builder.
AddLine({0, 0}, {1, 1})
298 TEST(PathTest, PathHorizontalLine) {
303 path.GetLinearComponentAtIndex(1, linear);
305 EXPECT_EQ(linear.
p1,
Point(0, 0));
306 EXPECT_EQ(linear.
p2,
Point(10, 0));
309 TEST(PathTest, PathVerticalLine) {
314 path.GetLinearComponentAtIndex(1, linear);
316 EXPECT_EQ(linear.
p1,
Point(0, 0));
317 EXPECT_EQ(linear.
p2,
Point(0, 10));
320 TEST(PathTest, QuadradicPath) {
325 path.GetQuadraticComponentAtIndex(1, quad);
327 EXPECT_EQ(quad.
p1,
Point(0, 0));
328 EXPECT_EQ(quad.
cp,
Point(10, 10));
329 EXPECT_EQ(quad.
p2,
Point(20, 20));
339 path.GetCubicComponentAtIndex(1, cubic);
341 EXPECT_EQ(cubic.
p1,
Point(0, 0));
342 EXPECT_EQ(cubic.
cp1,
Point(10, 10));
343 EXPECT_EQ(cubic.
cp2,
Point(-10, -10));
344 EXPECT_EQ(cubic.
p2,
Point(20, 20));
347 TEST(PathTest, BoundingBoxCubic) {
350 builder.
AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
352 auto box = path.GetBoundingBox();
354 ASSERT_TRUE(box.has_value());
358 TEST(PathTest, BoundingBoxOfCompositePathIsCorrect) {
365 ASSERT_TRUE(actual.has_value());
369 TEST(PathTest, ExtremaOfCubicPathComponentIsCorrect) {
371 {-6.2857933, 204.356461},
372 {-4.53997231, 156.552902},
373 {17.0067291, 109.472488}};
376 ASSERT_EQ(points.size(),
static_cast<size_t>(3));
380 TEST(PathTest, PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect) {
388 ASSERT_TRUE(actual.has_value());
394 ASSERT_EQ(path.GetComponentCount(), 1u);
397 path.GetContourComponentAtIndex(0, c);
401 ASSERT_TRUE(
polyline.points->empty());
402 ASSERT_TRUE(
polyline.contours.empty());
408 auto path = builder.
AddLine({0, 0}, {100, 100})
409 .AddQuadraticCurve({100, 100}, {200, 200}, {300, 300})
410 .AddCubicCurve({300, 300}, {400, 400}, {500, 500}, {600, 600})
413 EXPECT_EQ(path.GetComponentCount(), 6u);
421 EXPECT_TRUE(path.GetLinearComponentAtIndex(1, linear));
425 EXPECT_EQ(linear.
p1, p1);
426 EXPECT_EQ(linear.
p2, p2);
431 EXPECT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
436 EXPECT_EQ(quad.
p1, p1);
437 EXPECT_EQ(quad.
cp, cp);
438 EXPECT_EQ(quad.
p2, p2);
443 EXPECT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
449 EXPECT_EQ(cubic.
p1, p1);
450 EXPECT_EQ(cubic.
cp1, cp1);
451 EXPECT_EQ(cubic.
cp2, cp2);
452 EXPECT_EQ(cubic.
p2, p2);
457 EXPECT_TRUE(path.GetContourComponentAtIndex(0, contour));
466 EXPECT_TRUE(path.GetContourComponentAtIndex(2, contour));
475 EXPECT_TRUE(path.GetContourComponentAtIndex(4, contour));
483 TEST(PathTest, RepeatCloseDoesNotAddNewLines) {
485 auto path = builder.
LineTo({0, 10})
492 EXPECT_EQ(path.GetComponentCount(), 5u);
497 TEST(PathTest, CloseAfterMoveDoesNotAddNewLines) {
499 auto path = builder.
LineTo({0, 10})
506 EXPECT_EQ(path.GetComponentCount(), 4u);
511 TEST(PathTest, CloseAtOriginDoesNotAddNewLineSegment) {
515 auto path = builder.
LineTo({10, 0})
522 EXPECT_EQ(path.GetComponentCount(), 6u);
536 auto path_b = path_a;
538 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
539 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
540 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
542 auto poly_a = path_a.CreatePolyline(1.0);
543 auto poly_b = path_b.CreatePolyline(1.0);
545 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
546 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
548 for (
auto i = 0u; i < poly_a.points->size(); i++) {
549 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
552 for (
auto i = 0u; i < poly_a.contours.size(); i++) {
553 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
554 EXPECT_EQ(poly_a.contours[i].start_direction,
555 poly_b.contours[i].start_direction);
559 TEST(PathTest, PathBuilderDoesNotMutateCopiedPaths) {
560 auto test_isolation =
561 [](
const std::function<void(
PathBuilder & builder)>& mutator,
562 bool will_close,
Point mutation_offset,
const std::string& label) {
568 auto verify_path = [](
const Path& path,
bool is_mutated,
bool is_closed,
582 EXPECT_EQ(contour.
IsClosed(), is_closed) << label;
599 verify_path(path1,
false,
false, {},
600 "Initial Path1 state before " + label);
602 for (
int i = 0; i < 10; i++) {
605 path,
false,
false, {},
606 "Extra CopyPath #" + std::to_string(i + 1) +
" for " + label);
609 verify_path(path1,
false,
false, {},
610 "Path1 state after subsequent " + label);
613 verify_path(path1,
false,
false, {},
614 "Path1 state after subsequent " + label +
" and CopyPath");
615 verify_path(path2,
true, will_close, mutation_offset,
616 "Initial Path2 state with subsequent " + label);
623 false, {},
"SetConvex");
629 false, {},
"SetUnknownConvex");
639 builder.
MoveTo({20, 30},
false);
641 false, {},
"Absolute MoveTo");
645 builder.
MoveTo({20, 30},
true);
647 false, {},
"Relative MoveTo");
651 builder.
LineTo({20, 30},
false);
653 false, {},
"Absolute LineTo");
657 builder.
LineTo({20, 30},
true);
659 false, {},
"Relative LineTo");
665 false, {},
"Absolute HorizontalLineTo");
671 false, {},
"Relative HorizontalLineTo");
677 false, {},
"Absolute VerticalLineTo");
683 false, {},
"Relative VerticalLineTo");
689 false, {},
"Absolute QuadraticCurveTo");
695 false, {},
"Relative QuadraticCurveTo");
699 builder.
CubicCurveTo({20, 30}, {30, 20}, {30, 30},
false);
701 false, {},
"Absolute CubicCurveTo");
705 builder.
CubicCurveTo({20, 30}, {30, 20}, {30, 30},
true);
707 false, {},
"Relative CubicCurveTo");
711 builder.
AddLine({100, 100}, {150, 100});
713 false, {},
"AddLine");
719 false, {},
"AddRect");
725 false, {},
"AddOval");
731 false, {},
"AddCircle");
738 false, {},
"AddArc");
744 false, {},
"AddQuadraticCurve");
748 builder.
AddCubicCurve({100, 100}, {150, 100}, {100, 150}, {150, 150});
750 false, {},
"AddCubicCurve");
754 builder.
Shift({23, 42});
756 false, {23, 42},
"Shift");