diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index 84991756d3a2f..0bf56ff87efcc 100644 --- a/impeller/display_list/display_list_unittests.cc +++ b/impeller/display_list/display_list_unittests.cc @@ -121,13 +121,34 @@ TEST_P(DisplayListTest, CanDrawArc) { static float stroke_width = 10; static bool use_center = true; + static int selected_cap = 0; + const char* cap_names[] = {"Butt", "Round", "Square"}; + flutter::DlStrokeCap cap; + ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); ImGui::SliderFloat("Start angle", &start_angle, -360, 360); ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360); ImGui::SliderFloat("Stroke width", &stroke_width, 0, 100); + ImGui::Combo("Cap", &selected_cap, cap_names, + sizeof(cap_names) / sizeof(char*)); ImGui::Checkbox("Use center", &use_center); ImGui::End(); + switch (selected_cap) { + case 0: + cap = flutter::DlStrokeCap::kButt; + break; + case 1: + cap = flutter::DlStrokeCap::kRound; + break; + case 2: + cap = flutter::DlStrokeCap::kSquare; + break; + default: + cap = flutter::DlStrokeCap::kButt; + break; + } + auto [p1, p2] = IMPELLER_PLAYGROUND_LINE( Point(200, 200), Point(400, 400), 20, Color::White(), Color::White()); @@ -136,7 +157,7 @@ TEST_P(DisplayListTest, CanDrawArc) { Vector2 scale = GetContentScale(); builder.scale(scale.x, scale.y); builder.setStyle(flutter::DlDrawStyle::kStroke); - builder.setStrokeCap(flutter::DlStrokeCap::kButt); + builder.setStrokeCap(cap); builder.setStrokeJoin(flutter::DlStrokeJoin::kMiter); builder.setStrokeMiter(10); auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y); diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc index 6e1dd8a28df08..368cf4c06ba06 100644 --- a/impeller/entity/geometry.cc +++ b/impeller/entity/geometry.cc @@ -302,6 +302,7 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices( HostBuffer& buffer, Scalar stroke_width, Scalar scaled_miter_limit, + Cap cap, const StrokePathGeometry::JoinProc& join_proc, const StrokePathGeometry::CapProc& cap_proc, Scalar tolerance) { @@ -370,9 +371,15 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices( // Generate start cap. if (!polyline.contours[contour_i].is_closed) { - auto cap_offset = - Vector2(contour.start_direction.y, -contour.start_direction.x) * - stroke_width * 0.5; + Vector2 direction; + if (cap == Cap::kButt) { + direction = + Vector2(contour.start_direction.y, -contour.start_direction.x); + } else { + direction = + Vector2(-contour.start_direction.y, contour.start_direction.x); + } + auto cap_offset = direction * stroke_width * 0.5; cap_proc(vtx_builder, polyline.points[contour_start_point_i], cap_offset, tolerance); } @@ -439,7 +446,8 @@ GeometryResult StrokePathGeometry::GetPositionBuffer( auto& host_buffer = pass.GetTransientsBuffer(); auto vertex_buffer = CreateSolidStrokeVertices( path_, host_buffer, stroke_width, miter_limit_ * stroke_width_ * 0.5, - GetJoinProc(stroke_join_), GetCapProc(stroke_cap_), tolerance); + stroke_cap_, GetJoinProc(stroke_join_), GetCapProc(stroke_cap_), + tolerance); return GeometryResult{ .type = PrimitiveType::kTriangleStrip, diff --git a/impeller/entity/geometry.h b/impeller/entity/geometry.h index d3070a6e0fc08..d5eb6afe49dde 100644 --- a/impeller/entity/geometry.h +++ b/impeller/entity/geometry.h @@ -164,6 +164,7 @@ class StrokePathGeometry : public Geometry { HostBuffer& buffer, Scalar stroke_width, Scalar scaled_miter_limit, + Cap cap, const JoinProc& join_proc, const CapProc& cap_proc, Scalar tolerance);