From a781e2f9af8f192ebaf28a34effea522811bc143 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 28 Feb 2022 14:28:16 -0800 Subject: [PATCH] Setup join/cap proc (#45) --- impeller/entity/contents.cc | 94 ++++++++++++++++++----------- impeller/entity/contents.h | 22 +++++-- impeller/entity/entity_unittests.cc | 9 +++ 3 files changed, 86 insertions(+), 39 deletions(-) diff --git a/impeller/entity/contents.cc b/impeller/entity/contents.cc index 0cb59466a7672..d5a2610245aba 100644 --- a/impeller/entity/contents.cc +++ b/impeller/entity/contents.cc @@ -282,7 +282,11 @@ const IRect& TextureContents::GetSourceRect() const { ******* SolidStrokeContents ******************************************************************************/ -SolidStrokeContents::SolidStrokeContents() = default; +SolidStrokeContents::SolidStrokeContents() { + SetStrokeCap(Cap::kButt); + // TODO(99089): Change this to kMiter once implemented. + SetStrokeJoin(Join::kBevel); +} SolidStrokeContents::~SolidStrokeContents() = default; @@ -294,32 +298,11 @@ const Color& SolidStrokeContents::GetColor() const { return color_; } -static void CreateCap( - VertexBufferBuilder& vtx_builder, - const Point& position, - const Point& normal) {} - -static void CreateJoin( - VertexBufferBuilder& vtx_builder, - const Point& position, - const Point& start_normal, - const Point& end_normal) { - SolidStrokeVertexShader::PerVertexData vtx; - vtx.vertex_position = position; - vtx.pen_down = 1.0; - vtx.vertex_normal = {}; - vtx_builder.AppendVertex(vtx); - - // A simple bevel join to start with. - Scalar dir = start_normal.Cross(end_normal) > 0 ? -1 : 1; - vtx.vertex_normal = start_normal * dir; - vtx_builder.AppendVertex(vtx); - vtx.vertex_normal = end_normal * dir; - vtx_builder.AppendVertex(vtx); -} - -static VertexBuffer CreateSolidStrokeVertices(const Path& path, - HostBuffer& buffer) { +static VertexBuffer CreateSolidStrokeVertices( + const Path& path, + HostBuffer& buffer, + const SolidStrokeContents::CapProc& cap_proc, + const SolidStrokeContents::JoinProc& join_proc) { using VS = SolidStrokeVertexShader; VertexBufferBuilder vtx_builder; @@ -372,7 +355,7 @@ static VertexBuffer CreateSolidStrokeVertices(const Path& path, // Generate start cap. if (!polyline.contours[contour_i].is_closed) { - CreateCap(vtx_builder, polyline.points[contour_start_point_i], -normal); + cap_proc(vtx_builder, polyline.points[contour_start_point_i], -normal); } // Generate contour geometry. @@ -396,18 +379,18 @@ static VertexBuffer CreateSolidStrokeVertices(const Path& path, compute_normal(point_i + 1); // Generate join from the current line to the next line. - CreateJoin(vtx_builder, polyline.points[point_i], previous_normal, - normal); + join_proc(vtx_builder, polyline.points[point_i], previous_normal, + normal); } } } // Generate end cap or join. if (!polyline.contours[contour_i].is_closed) { - CreateCap(vtx_builder, polyline.points[contour_end_point_i - 1], normal); + cap_proc(vtx_builder, polyline.points[contour_end_point_i - 1], normal); } else { - CreateJoin(vtx_builder, polyline.points[contour_start_point_i], normal, - contour_first_normal); + join_proc(vtx_builder, polyline.points[contour_start_point_i], normal, + contour_first_normal); } } @@ -436,8 +419,8 @@ bool SolidStrokeContents::Render(const ContentContext& renderer, cmd.label = "SolidStroke"; cmd.pipeline = renderer.GetSolidStrokePipeline(OptionsFromPass(pass)); cmd.stencil_reference = entity.GetStencilDepth(); - cmd.BindVertices( - CreateSolidStrokeVertices(entity.GetPath(), pass.GetTransientsBuffer())); + cmd.BindVertices(CreateSolidStrokeVertices( + entity.GetPath(), pass.GetTransientsBuffer(), cap_proc_, join_proc_)); VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); VS::BindStrokeInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(stroke_info)); @@ -465,6 +448,20 @@ Scalar SolidStrokeContents::GetStrokeMiter(Scalar miter) { void SolidStrokeContents::SetStrokeCap(Cap cap) { cap_ = cap; + + using VS = SolidStrokeVertexShader; + switch (cap) { + case Cap::kButt: + cap_proc_ = [](VertexBufferBuilder& vtx_builder, + const Point& position, const Point& normal) {}; + break; + case Cap::kRound: + FML_DLOG(ERROR) << "Unimplemented."; + break; + case Cap::kSquare: + FML_DLOG(ERROR) << "Unimplemented."; + break; + } } SolidStrokeContents::Cap SolidStrokeContents::GetStrokeCap() { @@ -473,6 +470,33 @@ SolidStrokeContents::Cap SolidStrokeContents::GetStrokeCap() { void SolidStrokeContents::SetStrokeJoin(Join join) { join_ = join; + + using VS = SolidStrokeVertexShader; + switch (join) { + case Join::kBevel: + join_proc_ = [](VertexBufferBuilder& vtx_builder, + const Point& position, const Point& start_normal, + const Point& end_normal) { + SolidStrokeVertexShader::PerVertexData vtx; + vtx.vertex_position = position; + vtx.pen_down = 1.0; + vtx.vertex_normal = {}; + vtx_builder.AppendVertex(vtx); + + Scalar dir = start_normal.Cross(end_normal) > 0 ? -1 : 1; + vtx.vertex_normal = start_normal * dir; + vtx_builder.AppendVertex(vtx); + vtx.vertex_normal = end_normal * dir; + vtx_builder.AppendVertex(vtx); + }; + break; + case Join::kMiter: + FML_DLOG(ERROR) << "Unimplemented."; + break; + case Join::kRound: + FML_DLOG(ERROR) << "Unimplemented."; + break; + } } SolidStrokeContents::Join SolidStrokeContents::GetStrokeJoin() { diff --git a/impeller/entity/contents.h b/impeller/entity/contents.h index 3b1bec7509690..2e03096d78e40 100644 --- a/impeller/entity/contents.h +++ b/impeller/entity/contents.h @@ -4,10 +4,12 @@ #pragma once +#include #include #include #include "flutter/fml/macros.h" +#include "impeller/entity/solid_stroke.vert.h" #include "impeller/geometry/color.h" #include "impeller/geometry/point.h" #include "impeller/geometry/rect.h" @@ -119,16 +121,24 @@ class SolidStrokeContents final : public Contents { kButt, kRound, kSquare, - kLast, }; enum class Join { kMiter, kRound, kBevel, - kLast, }; + using CapProc = std::function& vtx_builder, + const Point& position, + const Point& normal)>; + using JoinProc = std::function& vtx_builder, + const Point& position, + const Point& start_normal, + const Point& end_normal)>; + SolidStrokeContents(); ~SolidStrokeContents() override; @@ -162,8 +172,12 @@ class SolidStrokeContents final : public Contents { Color color_; Scalar stroke_size_ = 0.0; Scalar miter_ = 0.0; - Cap cap_ = Cap::kButt; - Join join_ = Join::kMiter; + + Cap cap_; + CapProc cap_proc_; + + Join join_; + JoinProc join_proc_; FML_DISALLOW_COPY_AND_ASSIGN(SolidStrokeContents); }; diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index 29b784e1c4f5e..704e64b4379d1 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "entity/contents.h" #include "flutter/testing/testing.h" #include "impeller/entity/entity.h" #include "impeller/entity/entity_playground.h" @@ -328,5 +329,13 @@ 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. +} + } // namespace testing } // namespace impeller