Skip to content

Commit

Permalink
Support path fill types.
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmaygarde authored and dnfield committed Apr 27, 2022
1 parent 10487e3 commit f83a021
Show file tree
Hide file tree
Showing 13 changed files with 109 additions and 72 deletions.
41 changes: 33 additions & 8 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ TEST_F(AiksTest, CanRenderColoredRect) {
paint.color = Color::Red();
canvas.DrawPath(PathBuilder{}
.AddRect(Rect::MakeXYWH(100.0, 100.0, 100.0, 100.0))
.CreatePath(),
.TakePath(),
paint);
// ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
Expand Down Expand Up @@ -81,7 +81,7 @@ TEST_F(AiksTest, CanRenderStrokes) {
paint.color = Color::Red();
paint.stroke_width = 20.0;
paint.style = Paint::Style::kStroke;
canvas.DrawPath(PathBuilder{}.AddLine({200, 100}, {800, 100}).CreatePath(),
canvas.DrawPath(PathBuilder{}.AddLine({200, 100}, {800, 100}).TakePath(),
paint);
// ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
Expand All @@ -92,7 +92,7 @@ TEST_F(AiksTest, CanRenderCurvedStrokes) {
paint.color = Color::Red();
paint.stroke_width = 25.0;
paint.style = Paint::Style::kStroke;
canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).CreatePath(), paint);
canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

Expand All @@ -101,8 +101,8 @@ TEST_F(AiksTest, CanRenderClips) {
Paint paint;
paint.color = Color::Fuchsia();
canvas.ClipPath(
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 500, 500)).CreatePath());
canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).CreatePath(), paint);
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 500, 500)).TakePath());
canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

Expand Down Expand Up @@ -236,14 +236,39 @@ TEST_F(AiksTest, CanRenderRoundedRectWithNonUniformRadii) {
radii.bottom_right = {50, 25};
radii.bottom_left = {25, 50};

auto path = PathBuilder{}
.AddRoundedRect(Rect{100, 100, 500, 500}, radii)
.CreatePath();
auto path =
PathBuilder{}.AddRoundedRect(Rect{100, 100, 500, 500}, radii).TakePath();

canvas.DrawPath(path, paint);

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_F(AiksTest, CanRenderDifferencePaths) {
Canvas canvas;

Paint paint;
paint.color = Color::Red();

PathBuilder builder;

PathBuilder::RoundingRadii radii;
radii.top_left = {50, 25};
radii.top_right = {25, 50};
radii.bottom_right = {50, 25};
radii.bottom_left = {25, 50};

builder.AddRoundedRect({100, 100, 200, 200}, radii);
builder.AddCircle({200, 200}, 50);
auto path = builder.TakePath(FillType::kOdd);

canvas.DrawImage(
std::make_shared<Image>(CreateTextureForFixture("boston.jpg")), {10, 10},
Paint{});
canvas.DrawPath(std::move(path), paint);

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

} // namespace testing
} // namespace impeller
8 changes: 4 additions & 4 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ void Canvas::DrawPath(Path path, Paint paint) {
}

void Canvas::DrawRect(Rect rect, Paint paint) {
DrawPath(PathBuilder{}.AddRect(rect).CreatePath(), std::move(paint));
DrawPath(PathBuilder{}.AddRect(rect).TakePath(), std::move(paint));
}

void Canvas::DrawCircle(Point center, Scalar radius, Paint paint) {
DrawPath(PathBuilder{}.AddCircle(center, radius).CreatePath(),
DrawPath(PathBuilder{}.AddCircle(center, radius).TakePath(),
std::move(paint));
}

Expand All @@ -120,7 +120,7 @@ void Canvas::SaveLayer(Paint paint, std::optional<Rect> bounds) {
// the size of the render target that would have been allocated will be
// absent. Explicitly add back a clip to reproduce that behavior. Since
// clips never require a render target switch, this is a cheap operation.
ClipPath(PathBuilder{}.AddRect(bounds.value()).CreatePath());
ClipPath(PathBuilder{}.AddRect(bounds.value()).TakePath());
}
}

Expand Down Expand Up @@ -187,7 +187,7 @@ void Canvas::DrawImageRect(std::shared_ptr<Image> image,
contents->SetSourceRect(source);

Entity entity;
entity.SetPath(PathBuilder{}.AddRect(dest).CreatePath());
entity.SetPath(PathBuilder{}.AddRect(dest).TakePath());
entity.SetContents(contents);
entity.SetTransformation(GetCurrentTransformation());

Expand Down
14 changes: 7 additions & 7 deletions impeller/display_list/display_list_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ static Rect ToRect(const SkRect& rect) {
void DisplayListImpeller::clipRect(const SkRect& rect,
SkClipOp clip_op,
bool is_aa) {
auto path = PathBuilder{}.AddRect(ToRect(rect)).CreatePath();
auto path = PathBuilder{}.AddRect(ToRect(rect)).TakePath();
canvas_.ClipPath(std::move(path));
}

Expand All @@ -238,7 +238,7 @@ void DisplayListImpeller::clipRRect(const SkRRect& rrect,
auto path =
PathBuilder{}
.AddRoundedRect(ToRect(rrect.getBounds()), ToRoundingRadii(rrect))
.CreatePath();
.TakePath();
canvas_.ClipPath(std::move(path));
}

Expand Down Expand Up @@ -266,25 +266,25 @@ void DisplayListImpeller::drawPaint() {

// |flutter::Dispatcher|
void DisplayListImpeller::drawLine(const SkPoint& p0, const SkPoint& p1) {
auto path = PathBuilder{}.AddLine(ToPoint(p0), ToPoint(p1)).CreatePath();
auto path = PathBuilder{}.AddLine(ToPoint(p0), ToPoint(p1)).TakePath();
canvas_.DrawPath(std::move(path), paint_);
}

// |flutter::Dispatcher|
void DisplayListImpeller::drawRect(const SkRect& rect) {
auto path = PathBuilder{}.AddRect(ToRect(rect)).CreatePath();
auto path = PathBuilder{}.AddRect(ToRect(rect)).TakePath();
canvas_.DrawPath(std::move(path), paint_);
}

// |flutter::Dispatcher|
void DisplayListImpeller::drawOval(const SkRect& bounds) {
auto path = PathBuilder{}.AddOval(ToRect(bounds)).CreatePath();
auto path = PathBuilder{}.AddOval(ToRect(bounds)).TakePath();
canvas_.DrawPath(std::move(path), paint_);
}

// |flutter::Dispatcher|
void DisplayListImpeller::drawCircle(const SkPoint& center, SkScalar radius) {
auto path = PathBuilder{}.AddCircle(ToPoint(center), radius).CreatePath();
auto path = PathBuilder{}.AddCircle(ToPoint(center), radius).TakePath();
canvas_.DrawPath(std::move(path), paint_);
}

Expand All @@ -293,7 +293,7 @@ void DisplayListImpeller::drawRRect(const SkRRect& rrect) {
auto path =
PathBuilder{}
.AddRoundedRect(ToRect(rrect.getBounds()), ToRoundingRadii(rrect))
.CreatePath();
.TakePath();
canvas_.DrawPath(std::move(path), paint_);
}

Expand Down
33 changes: 17 additions & 16 deletions impeller/entity/contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ bool LinearGradientContents::Render(const ContentRenderer& renderer,

auto vertices_builder = VertexBufferBuilder<VS::PerVertexData>();
{
auto result = Tessellator{}.Tessellate(entity.GetPath().CreatePolyline(),
[&vertices_builder](Point point) {
VS::PerVertexData vtx;
vtx.vertices = point;
vertices_builder.AppendVertex(vtx);
});
auto result = Tessellator{entity.GetPath().GetFillType()}.Tessellate(
entity.GetPath().CreatePolyline(), [&vertices_builder](Point point) {
VS::PerVertexData vtx;
vtx.vertices = point;
vertices_builder.AppendVertex(vtx);
});
if (!result) {
return false;
}
Expand Down Expand Up @@ -124,7 +124,7 @@ static VertexBuffer CreateSolidFillVertices(const Path& path,

VertexBufferBuilder<VS::PerVertexData> vtx_builder;

auto tesselation_result = Tessellator{}.Tessellate(
auto tesselation_result = Tessellator{path.GetFillType()}.Tessellate(
path.CreatePolyline(), [&vtx_builder](auto point) {
VS::PerVertexData vtx;
vtx.vertices = point;
Expand Down Expand Up @@ -225,15 +225,16 @@ bool TextureContents::Render(const ContentRenderer& renderer,

VertexBufferBuilder<VS::PerVertexData> vertex_builder;
{
const auto tess_result = Tessellator{}.Tessellate(
entity.GetPath().CreatePolyline(),
[&vertex_builder, &coverage_rect](Point vtx) {
VS::PerVertexData data;
data.vertices = vtx;
data.texture_coords =
((vtx - coverage_rect->origin) / coverage_rect->size);
vertex_builder.AppendVertex(data);
});
const auto tess_result =
Tessellator{entity.GetPath().GetFillType()}.Tessellate(
entity.GetPath().CreatePolyline(),
[&vertex_builder, &coverage_rect](Point vtx) {
VS::PerVertexData data;
data.vertices = vtx;
data.texture_coords =
((vtx - coverage_rect->origin) / coverage_rect->size);
vertex_builder.AppendVertex(data);
});
if (!tess_result) {
return false;
}
Expand Down
3 changes: 1 addition & 2 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ bool EntityPass::Render(ContentRenderer& renderer,
}

Entity entity;
entity.SetPath(
PathBuilder{}.AddRect(subpass_coverage.value()).CreatePath());
entity.SetPath(PathBuilder{}.AddRect(subpass_coverage.value()).TakePath());
entity.SetContents(std::move(offscreen_texture_contents));
entity.SetStencilDepth(stencil_depth_);
entity.SetTransformation(xformation_);
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/entity_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ TEST_F(EntityTest, CanCreateEntity) {

TEST_F(EntityTest, CanDrawRect) {
Entity entity;
entity.SetPath(PathBuilder{}.AddRect({100, 100, 100, 100}).CreatePath());
entity.SetPath(PathBuilder{}.AddRect({100, 100, 100, 100}).TakePath());
entity.SetContents(SolidColorContents::Make(Color::Red()));
// ASSERT_TRUE(OpenPlaygroundHere(entity));
}
Expand Down
2 changes: 1 addition & 1 deletion impeller/geometry/geometry_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ TEST(GeometryTest, BoundingBoxCubic) {
TEST(GeometryTest, BoundingBoxOfCompositePathIsCorrect) {
PathBuilder builder;
builder.AddRoundedRect({{10, 10}, {300, 300}}, {50, 50, 50, 50});
auto path = builder.CreatePath();
auto path = builder.TakePath();
auto actual = path.GetBoundingBox();
Rect expected(10, 10, 300, 300);
ASSERT_TRUE(actual.has_value());
Expand Down
8 changes: 8 additions & 0 deletions impeller/geometry/path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ size_t Path::GetComponentCount() const {
return components_.size();
}

void Path::SetFillType(FillType fill) {
fill_ = fill;
}

FillType Path::GetFillType() const {
return fill_;
}

Path& Path::AddLinearComponent(Point p1, Point p2) {
linears_.emplace_back(p1, p2);
components_.emplace_back(ComponentType::kLinear, linears_.size() - 1);
Expand Down
13 changes: 13 additions & 0 deletions impeller/geometry/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@

namespace impeller {

enum class FillType {
kNonZero, // The default winding order.
kOdd,
kPositive,
kNegative,
kAbsGeqTwo,
};

//------------------------------------------------------------------------------
/// @brief Paths are lightweight objects that describe a collection of
/// linear, quadratic, or cubic segments.
Expand All @@ -36,6 +44,10 @@ class Path {

size_t GetComponentCount() const;

void SetFillType(FillType fill);

FillType GetFillType() const;

Path& AddLinearComponent(Point p1, Point p2);

Path& AddQuadraticComponent(Point p1, Point cp, Point p2);
Expand Down Expand Up @@ -82,6 +94,7 @@ class Path {
: type(aType), index(aIndex) {}
};

FillType fill_ = FillType::kNonZero;
std::vector<ComponentIndexPair> components_;
std::vector<LinearPathComponent> linears_;
std::vector<QuadraticPathComponent> quads_;
Expand Down
12 changes: 10 additions & 2 deletions impeller/geometry/path_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@ PathBuilder::PathBuilder() = default;

PathBuilder::~PathBuilder() = default;

Path PathBuilder::CreatePath() const {
return prototype_;
Path PathBuilder::CopyPath(FillType fill) const {
auto path = prototype_;
path.SetFillType(fill);
return path;
}

Path PathBuilder::TakePath(FillType fill) {
auto path = std::move(prototype_);
path.SetFillType(fill);
return path;
}

PathBuilder& PathBuilder::MoveTo(Point point, bool relative) {
Expand Down
4 changes: 3 additions & 1 deletion impeller/geometry/path_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class PathBuilder {

~PathBuilder();

Path CreatePath() const;
Path CopyPath(FillType fill = FillType::kNonZero) const;

Path TakePath(FillType fill = FillType::kNonZero);

const Path& GetCurrentPath() const;

Expand Down
24 changes: 8 additions & 16 deletions impeller/renderer/tessellator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,21 @@

namespace impeller {

Tessellator::Tessellator() {}
Tessellator::Tessellator(FillType type) : fill_type_(type) {}

Tessellator::~Tessellator() {}
Tessellator::~Tessellator() = default;

void Tessellator::SetFillType(FillType winding) {
fill_type_ = winding;
}

Tessellator::FillType Tessellator::GetFillType() const {
return fill_type_;
}

static int ToTessWindingRule(Tessellator::FillType fill_type) {
static int ToTessWindingRule(FillType fill_type) {
switch (fill_type) {
case Tessellator::FillType::kOdd:
case FillType::kOdd:
return TESS_WINDING_ODD;
case Tessellator::FillType::kNonZero:
case FillType::kNonZero:
return TESS_WINDING_NONZERO;
case Tessellator::FillType::kPositive:
case FillType::kPositive:
return TESS_WINDING_POSITIVE;
case Tessellator::FillType::kNegative:
case FillType::kNegative:
return TESS_WINDING_NEGATIVE;
case Tessellator::FillType::kAbsGeqTwo:
case FillType::kAbsGeqTwo:
return TESS_WINDING_ABS_GEQ_TWO;
}
return TESS_WINDING_ODD;
Expand Down
Loading

0 comments on commit f83a021

Please sign in to comment.