diff --git a/engine/src/flutter/impeller/display_list/aiks_dl_path_unittests.cc b/engine/src/flutter/impeller/display_list/aiks_dl_path_unittests.cc index 93ed97af54367..ccdfd214b7a7c 100644 --- a/engine/src/flutter/impeller/display_list/aiks_dl_path_unittests.cc +++ b/engine/src/flutter/impeller/display_list/aiks_dl_path_unittests.cc @@ -983,6 +983,32 @@ TEST_P(AiksTest, TwoContourPathWithSinglePointContour) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(AiksTest, TwoContourPathWithConnectingLines) { + DisplayListBuilder builder; + + DlPaint paint; + paint.setColor(DlColor::kRed()); + paint.setDrawStyle(DlDrawStyle::kStroke); + paint.setStrokeWidth(15.0); + + builder.Translate(100, 0); + for (auto join : std::vector{ + DlStrokeJoin::kMiter, DlStrokeJoin::kRound, DlStrokeJoin::kBevel}) { + builder.Translate(0, 100); + paint.setStrokeJoin(join); + + DlPathBuilder path_builder; + path_builder.MoveTo(DlPoint(0, 0)); + path_builder.LineTo(DlPoint(50, 50)); + path_builder.MoveTo(DlPoint(50, 50)); + path_builder.LineTo(DlPoint(100, 0)); + + builder.DrawPath(path_builder.TakePath(), paint); + } + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + TEST_P(AiksTest, StrokeCapsAndJoins) { DisplayListBuilder builder; builder.Scale(GetContentScale().x, GetContentScale().y); diff --git a/engine/src/flutter/impeller/entity/geometry/geometry_unittests.cc b/engine/src/flutter/impeller/entity/geometry/geometry_unittests.cc index d4cc85168ae93..0073102790cf3 100644 --- a/engine/src/flutter/impeller/entity/geometry/geometry_unittests.cc +++ b/engine/src/flutter/impeller/entity/geometry/geometry_unittests.cc @@ -810,7 +810,7 @@ TEST(EntityGeometryTest, TwoLineSegmentsRightTurnStrokeVerticesBevelJoin) { Point(30, 25), Point(30, 15), - // The points for the second segment (120, 20) -> (130, 20) + // The points for the second segment (30, 20) -> (30, 30) Point(25, 20), Point(35, 20), Point(25, 30), @@ -844,7 +844,7 @@ TEST(EntityGeometryTest, TwoLineSegmentsLeftTurnStrokeVerticesBevelJoin) { Point(30, 25), Point(30, 15), - // The points for the second segment (120, 20) -> (130, 20) + // The points for the second segment (30, 20) -> (30, 10) Point(35, 20), Point(25, 20), Point(35, 10), @@ -854,6 +854,53 @@ TEST(EntityGeometryTest, TwoLineSegmentsLeftTurnStrokeVerticesBevelJoin) { EXPECT_EQ(points, expected); } +TEST(EntityGeometryTest, TwoLineSegmentsInDifferentContoursAreNotJoined) { + flutter::DlPathBuilder path_builder; + // First contour with a single line. + path_builder.MoveTo({20, 20}); + path_builder.LineTo({30, 20}); + // Starts a new contour with a MoveTo command. The start of the new contour is + // specified to be the same as the end of the previous contour. + path_builder.MoveTo({30, 20}); + // Add a line in the second contour. + path_builder.LineTo({30, 30}); + flutter::DlPath path = path_builder.TakePath(); + + auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices( + path, + { + .width = 10.0f, + .cap = Cap::kButt, + .join = Join::kBevel, + .miter_limit = 4.0f, + }, + 1.0f); + + std::vector expected = { + // The points for the first segment (20, 20) -> (30, 20) + Point(20, 25), + Point(20, 15), + Point(30, 25), + Point(30, 15), + + // The glue points that allow us to "pick up the pen" between segments. + // This prevents segments in different contours from being unintentionally + // joined with a bevel. + Point(30, 20), + Point(30, 20), + Point(30, 20), + Point(30, 20), + + // The points for the second segment (30, 20) -> (30, 30) + Point(25, 20), + Point(35, 20), + Point(25, 30), + Point(35, 30), + }; + + EXPECT_EQ(points, expected); +} + TEST(EntityGeometryTest, TwoLineSegmentsRightTurnStrokeVerticesMiterJoin) { flutter::DlPathBuilder path_builder; path_builder.MoveTo({20, 20}); diff --git a/engine/src/flutter/impeller/entity/geometry/stroke_path_geometry.cc b/engine/src/flutter/impeller/entity/geometry/stroke_path_geometry.cc index 7d0f56282cb5d..ae00da7ca5768 100644 --- a/engine/src/flutter/impeller/entity/geometry/stroke_path_geometry.cc +++ b/engine/src/flutter/impeller/entity/geometry/stroke_path_geometry.cc @@ -155,7 +155,7 @@ class StrokePathSegmentReceiver : public PathAndArcSegmentReceiver { protected: // |SegmentReceiver| void BeginContour(Point origin, bool will_be_closed) override { - if (has_prior_contour_ && origin != last_point_) { + if (has_prior_contour_) { // We only append these extra points if we have had a prior contour. vtx_builder_.AppendVertex(last_point_); vtx_builder_.AppendVertex(last_point_);