diff --git a/impeller/entity/contents.cc b/impeller/entity/contents.cc index d5a2610245aba..62c6c89984c33 100644 --- a/impeller/entity/contents.cc +++ b/impeller/entity/contents.cc @@ -459,7 +459,23 @@ void SolidStrokeContents::SetStrokeCap(Cap cap) { FML_DLOG(ERROR) << "Unimplemented."; break; case Cap::kSquare: - FML_DLOG(ERROR) << "Unimplemented."; + cap_proc_ = [](VertexBufferBuilder& vtx_builder, + const Point& position, const Point& normal) { + SolidStrokeVertexShader::PerVertexData vtx; + vtx.vertex_position = position; + vtx.pen_down = 1.0; + + Point forward(normal.y, -normal.x); + + vtx.vertex_normal = normal; + vtx_builder.AppendVertex(vtx); + vtx.vertex_normal = -normal; + vtx_builder.AppendVertex(vtx); + vtx.vertex_normal = normal + forward; + vtx_builder.AppendVertex(vtx); + vtx.vertex_normal = -normal + forward; + vtx_builder.AppendVertex(vtx); + }; break; } } diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index 704e64b4379d1..25610122880b1 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -79,6 +79,51 @@ TEST_F(EntityTest, TriangleInsideASquare) { ASSERT_TRUE(OpenPlaygroundHere(callback)); } +TEST_F(EntityTest, StrokeCapAndJoinTest) { + auto callback = [&](ContentContext& context, RenderPass& pass) { + Entity entity; + + auto create_contents = [](SolidStrokeContents::Cap cap) { + auto contents = std::make_unique(); + contents->SetColor(Color::Red()); + contents->SetStrokeSize(20.0); + contents->SetStrokeCap(cap); + return contents; + }; + + const Point a_def(100, 100), b_def(100, 150), c_def(200, 100), + d_def(200, 50); + const Scalar r = 10; + + { + Point off(0, 0); + Point a, b, c, d; + std::tie(a, b) = IMPELLER_PLAYGROUND_LINE(off + a_def, off + b_def, r, + Color::Black(), Color::White()); + std::tie(c, d) = IMPELLER_PLAYGROUND_LINE(off + c_def, off + d_def, r, + Color::Black(), Color::White()); + entity.SetPath(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath()); + entity.SetContents(create_contents(SolidStrokeContents::Cap::kButt)); + entity.Render(context, pass); + } + + { + Point off(0, 100); + Point a, b, c, d; + std::tie(a, b) = IMPELLER_PLAYGROUND_LINE(off + a_def, off + b_def, r, + Color::Black(), Color::White()); + std::tie(c, d) = IMPELLER_PLAYGROUND_LINE(off + c_def, off + d_def, r, + Color::Black(), Color::White()); + entity.SetPath(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath()); + entity.SetContents(create_contents(SolidStrokeContents::Cap::kSquare)); + entity.Render(context, pass); + } + + return true; + }; + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + TEST_F(EntityTest, CubicCurveTest) { // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3 Path path = @@ -329,12 +374,25 @@ TEST_F(EntityTest, CubicCurveAndOverlapTest) { ASSERT_TRUE(OpenPlaygroundHere(entity)); } -TEST_F(EntityTest, SolidStrokeContentsSetStrokeDefaults) { - SolidStrokeContents stroke; - ASSERT_EQ(stroke.GetStrokeCap(), SolidStrokeContents::Cap::kButt); - ASSERT_EQ(stroke.GetStrokeJoin(), SolidStrokeContents::Join::kBevel); - // TODO(99089): Test that SetStroke[Cap|Join] works once there are multiple - // caps and joins. +TEST_F(EntityTest, SolidStrokeContentsSetStrokeCapsAndJoins) { + { + SolidStrokeContents stroke; + // Defaults. + ASSERT_EQ(stroke.GetStrokeCap(), SolidStrokeContents::Cap::kButt); + ASSERT_EQ(stroke.GetStrokeJoin(), SolidStrokeContents::Join::kBevel); + } + + { + SolidStrokeContents stroke; + stroke.SetStrokeCap(SolidStrokeContents::Cap::kSquare); + ASSERT_EQ(stroke.GetStrokeCap(), SolidStrokeContents::Cap::kSquare); + } + + { + SolidStrokeContents stroke; + stroke.SetStrokeCap(SolidStrokeContents::Cap::kRound); + ASSERT_EQ(stroke.GetStrokeCap(), SolidStrokeContents::Cap::kRound); + } } } // namespace testing