[Impeller] Change Path::CreatePolyline from tolerance to scale, and make it required (#39917)
[Impeller] Change Path::CreatePolyline from tolerance to scale, and make it required
diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc
index 7375922..7375598 100644
--- a/impeller/entity/contents/texture_contents.cc
+++ b/impeller/entity/contents/texture_contents.cc
@@ -123,7 +123,7 @@
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
{
const auto tess_result = renderer.GetTessellator()->Tessellate(
- path_.GetFillType(), path_.CreatePolyline(),
+ path_.GetFillType(), path_.CreatePolyline(1.0f),
[this, &vertex_builder, &coverage_rect, &texture_size](
const float* vertices, size_t vertices_size,
const uint16_t* indices, size_t indices_size) {
diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc
index fa3f201..c86eaa6 100644
--- a/impeller/entity/geometry.cc
+++ b/impeller/entity/geometry.cc
@@ -53,13 +53,11 @@
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) {
- auto tolerance =
- kDefaultCurveTolerance / entity.GetTransformation().GetMaxBasisLength();
-
VertexBuffer vertex_buffer;
auto& host_buffer = pass.GetTransientsBuffer();
auto tesselation_result = renderer.GetTessellator()->Tessellate(
- path_.GetFillType(), path_.CreatePolyline(tolerance),
+ path_.GetFillType(),
+ path_.CreatePolyline(entity.GetTransformation().GetMaxBasisLength()),
[&vertex_buffer, &host_buffer](
const float* vertices, size_t vertices_count, const uint16_t* indices,
size_t indices_count) {
@@ -151,7 +149,7 @@
join_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
const Point& position, const Point& start_offset,
const Point& end_offset, Scalar miter_limit,
- Scalar tolerance) {
+ Scalar scale) {
CreateBevelAndGetDirection(vtx_builder, position, start_offset,
end_offset);
};
@@ -160,7 +158,7 @@
join_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
const Point& position, const Point& start_offset,
const Point& end_offset, Scalar miter_limit,
- Scalar tolerance) {
+ Scalar scale) {
Point start_normal = start_offset.Normalize();
Point end_normal = end_offset.Normalize();
@@ -189,7 +187,7 @@
join_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
const Point& position, const Point& start_offset,
const Point& end_offset, Scalar miter_limit,
- Scalar tolerance) {
+ Scalar scale) {
Point start_normal = start_offset.Normalize();
Point end_normal = end_offset.Normalize();
@@ -216,7 +214,7 @@
auto arc_points = CubicPathComponent(start_offset, start_handle,
middle_handle, middle)
- .CreatePolyline(tolerance);
+ .CreatePolyline(scale);
VS::PerVertexData vtx;
for (const auto& point : arc_points) {
@@ -238,8 +236,7 @@
switch (stroke_cap) {
case Cap::kButt:
cap_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
- const Point& position, const Point& offset,
- Scalar tolerance) {
+ const Point& position, const Point& offset, Scalar scale) {
VS::PerVertexData vtx;
vtx.position = position + offset;
vtx_builder.AppendVertex(vtx);
@@ -249,8 +246,7 @@
break;
case Cap::kRound:
cap_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
- const Point& position, const Point& offset,
- Scalar tolerance) {
+ const Point& position, const Point& offset, Scalar scale) {
VS::PerVertexData vtx;
Point forward(offset.y, -offset.x);
@@ -260,7 +256,7 @@
CubicPathComponent(
offset, offset + forward * PathBuilder::kArcApproximationMagic,
forward + offset * PathBuilder::kArcApproximationMagic, forward)
- .CreatePolyline(tolerance);
+ .CreatePolyline(scale);
vtx.position = position + offset;
vtx_builder.AppendVertex(vtx);
@@ -276,8 +272,7 @@
break;
case Cap::kSquare:
cap_proc = [](VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
- const Point& position, const Point& offset,
- Scalar tolerance) {
+ const Point& position, const Point& offset, Scalar scale) {
VS::PerVertexData vtx;
Point forward(offset.y, -offset.x);
@@ -305,9 +300,9 @@
Cap cap,
const StrokePathGeometry::JoinProc& join_proc,
const StrokePathGeometry::CapProc& cap_proc,
- Scalar tolerance) {
+ Scalar scale) {
VertexBufferBuilder<VS::PerVertexData> vtx_builder;
- auto polyline = path.CreatePolyline();
+ auto polyline = path.CreatePolyline(scale);
VS::PerVertexData vtx;
@@ -333,8 +328,8 @@
switch (contour_end_point_i - contour_start_point_i) {
case 1: {
Point p = polyline.points[contour_start_point_i];
- cap_proc(vtx_builder, p, {-stroke_width * 0.5f, 0}, tolerance);
- cap_proc(vtx_builder, p, {stroke_width * 0.5f, 0}, tolerance);
+ cap_proc(vtx_builder, p, {-stroke_width * 0.5f, 0}, scale);
+ cap_proc(vtx_builder, p, {stroke_width * 0.5f, 0}, scale);
continue;
}
case 0:
@@ -381,7 +376,7 @@
}
auto cap_offset = direction * stroke_width * 0.5;
cap_proc(vtx_builder, polyline.points[contour_start_point_i], cap_offset,
- tolerance);
+ scale);
}
// Generate contour geometry.
@@ -402,7 +397,7 @@
// Generate join from the current line to the next line.
join_proc(vtx_builder, polyline.points[point_i], previous_offset,
- offset, scaled_miter_limit, tolerance);
+ offset, scaled_miter_limit, scale);
}
}
@@ -412,10 +407,10 @@
Vector2(-contour.end_direction.y, contour.end_direction.x) *
stroke_width * 0.5;
cap_proc(vtx_builder, polyline.points[contour_end_point_i - 1],
- cap_offset, tolerance);
+ cap_offset, scale);
} else {
join_proc(vtx_builder, polyline.points[contour_start_point_i], offset,
- contour_first_offset, scaled_miter_limit, tolerance);
+ contour_first_offset, scaled_miter_limit, scale);
}
}
@@ -437,15 +432,11 @@
Scalar min_size = 1.0f / sqrt(std::abs(determinant));
Scalar stroke_width = std::max(stroke_width_, min_size);
- auto tolerance =
- kDefaultCurveTolerance /
- (stroke_width_ * entity.GetTransformation().GetMaxBasisLength());
-
auto& host_buffer = pass.GetTransientsBuffer();
auto vertex_buffer = CreateSolidStrokeVertices(
path_, host_buffer, stroke_width, miter_limit_ * stroke_width_ * 0.5,
stroke_cap_, GetJoinProc(stroke_join_), GetCapProc(stroke_cap_),
- tolerance);
+ entity.GetTransformation().GetMaxBasisLength());
return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
diff --git a/impeller/entity/geometry.h b/impeller/entity/geometry.h
index d5eb6af..f595eee 100644
--- a/impeller/entity/geometry.h
+++ b/impeller/entity/geometry.h
@@ -134,14 +134,14 @@
std::function<void(VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
const Point& position,
const Point& offset,
- Scalar tolerance)>;
+ Scalar scale)>;
using JoinProc =
std::function<void(VertexBufferBuilder<VS::PerVertexData>& vtx_builder,
const Point& position,
const Point& start_offset,
const Point& end_offset,
Scalar miter_limit,
- Scalar tolerance)>;
+ Scalar scale)>;
// |Geometry|
GeometryResult GetPositionBuffer(const ContentContext& renderer,
@@ -167,7 +167,7 @@
Cap cap,
const JoinProc& join_proc,
const CapProc& cap_proc,
- Scalar tolerance);
+ Scalar scale);
static StrokePathGeometry::JoinProc GetJoinProc(Join stroke_join);
diff --git a/impeller/geometry/geometry_benchmarks.cc b/impeller/geometry/geometry_benchmarks.cc
index 06b514b..d3c1f9e 100644
--- a/impeller/geometry/geometry_benchmarks.cc
+++ b/impeller/geometry/geometry_benchmarks.cc
@@ -29,7 +29,7 @@
size_t point_count = 0u;
size_t single_point_count = 0u;
while (state.KeepRunning()) {
- auto polyline = path.CreatePolyline();
+ auto polyline = path.CreatePolyline(1.0f);
single_point_count = polyline.points.size();
point_count += single_point_count;
if (tessellate) {
diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc
index 8edada6..1e3db56 100644
--- a/impeller/geometry/geometry_unittests.cc
+++ b/impeller/geometry/geometry_unittests.cc
@@ -17,7 +17,6 @@
#include "impeller/geometry/rect.h"
#include "impeller/geometry/scalar.h"
#include "impeller/geometry/size.h"
-#include "path_component.h"
namespace impeller {
namespace testing {
@@ -577,7 +576,7 @@
path.GetContourComponentAtIndex(0, c);
ASSERT_POINT_NEAR(c.destination, Point());
- Path::Polyline polyline = path.CreatePolyline();
+ Path::Polyline polyline = path.CreatePolyline(1.0f);
ASSERT_TRUE(polyline.points.empty());
ASSERT_TRUE(polyline.contours.empty());
}
@@ -1596,7 +1595,7 @@
path.AddContourComponent({40, 40});
path.AddLinearComponent({40, 40}, {50, 50});
- auto polyline = path.CreatePolyline();
+ auto polyline = path.CreatePolyline(1.0f);
ASSERT_EQ(polyline.contours.size(), 2u);
ASSERT_EQ(polyline.points.size(), 5u);
@@ -1682,7 +1681,7 @@
.LineTo({200, 200})
.Close()
.TakePath()
- .CreatePolyline();
+ .CreatePolyline(1.0f);
ASSERT_EQ(polyline.points.size(), 6u);
ASSERT_EQ(polyline.contours.size(), 2u);
ASSERT_EQ(polyline.contours[0].is_closed, false);
@@ -1699,7 +1698,7 @@
.LineTo({200, 200})
.Close()
.TakePath()
- .CreatePolyline();
+ .CreatePolyline(1.0f);
size_t a1, a2, b1, b2;
std::tie(a1, a2) = polyline.GetContourPointBounds(0);
std::tie(b1, b2) = polyline.GetContourPointBounds(1);
@@ -1713,7 +1712,7 @@
Path::Polyline polyline = PathBuilder{}
.AddRect(Rect::MakeLTRB(50, 60, 70, 80))
.TakePath()
- .CreatePolyline();
+ .CreatePolyline(1.0f);
ASSERT_EQ(polyline.contours.size(), 1u);
ASSERT_TRUE(polyline.contours[0].is_closed);
ASSERT_EQ(polyline.contours[0].start_index, 0u);
@@ -1738,7 +1737,7 @@
.LineTo({0, 100})
.LineTo({0, 100}) // Insert duplicate at end of contour.
.TakePath()
- .CreatePolyline();
+ .CreatePolyline(1.0f);
ASSERT_EQ(polyline.contours.size(), 2u);
ASSERT_EQ(polyline.contours[0].start_index, 0u);
ASSERT_TRUE(polyline.contours[0].is_closed);
diff --git a/impeller/geometry/path.cc b/impeller/geometry/path.cc
index cad3774..b5f2693 100644
--- a/impeller/geometry/path.cc
+++ b/impeller/geometry/path.cc
@@ -7,6 +7,7 @@
#include <optional>
#include "impeller/geometry/path_component.h"
+#include "path_component.h"
namespace impeller {
@@ -221,8 +222,9 @@
return true;
}
-Path::Polyline Path::CreatePolyline(Scalar tolerance) const {
+Path::Polyline Path::CreatePolyline(Scalar scale) const {
Polyline polyline;
+ auto tolerance = kDefaultCurveTolerance / scale;
std::optional<Point> previous_contour_point;
auto collect_points = [&polyline, &previous_contour_point](
diff --git a/impeller/geometry/path.h b/impeller/geometry/path.h
index 9e348cd..0c4cf69 100644
--- a/impeller/geometry/path.h
+++ b/impeller/geometry/path.h
@@ -11,6 +11,7 @@
#include <vector>
#include "impeller/geometry/path_component.h"
+#include "path_component.h"
namespace impeller {
@@ -122,7 +123,12 @@
bool UpdateContourComponentAtIndex(size_t index,
const ContourComponent& contour);
- Polyline CreatePolyline(Scalar tolerance = kDefaultCurveTolerance) const;
+ /// Callers must provide the scale factor for how this path will be
+ /// transformed.
+ ///
+ /// It is suitable to use the max basis length of the matrix used to transform
+ /// the path. If the provided scale is 0, curves will revert to lines.
+ Polyline CreatePolyline(Scalar scale) const;
std::optional<Rect> GetBoundingBox() const;
diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc
index 79c79cb..aec9c77 100644
--- a/impeller/renderer/renderer_unittests.cc
+++ b/impeller/renderer/renderer_unittests.cc
@@ -396,7 +396,7 @@
PathBuilder{}
.AddRect(Rect::MakeXYWH(10, 10, 100, 100))
.TakePath()
- .CreatePolyline(),
+ .CreatePolyline(1.0f),
[&builder](const float* vertices, size_t vertices_size,
const uint16_t* indices, size_t indices_size) {
for (auto i = 0u; i < vertices_size; i += 2) {
diff --git a/impeller/tessellator/tessellator_unittests.cc b/impeller/tessellator/tessellator_unittests.cc
index 56c2478..0b943d1 100644
--- a/impeller/tessellator/tessellator_unittests.cc
+++ b/impeller/tessellator/tessellator_unittests.cc
@@ -14,7 +14,7 @@
// Zero points.
{
Tessellator t;
- auto polyline = PathBuilder{}.TakePath().CreatePolyline();
+ auto polyline = PathBuilder{}.TakePath().CreatePolyline(1.0f);
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,
@@ -27,7 +27,8 @@
// One point.
{
Tessellator t;
- auto polyline = PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline();
+ auto polyline =
+ PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline(1.0f);
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,
@@ -40,7 +41,7 @@
{
Tessellator t;
auto polyline =
- PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline();
+ PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(1.0f);
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,
@@ -58,7 +59,7 @@
auto coord = i * 1.0f;
builder.AddLine({coord, coord}, {coord + 1, coord + 1});
}
- auto polyline = builder.TakePath().CreatePolyline();
+ auto polyline = builder.TakePath().CreatePolyline(1.0f);
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,
@@ -72,7 +73,7 @@
{
Tessellator t;
auto polyline =
- PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline();
+ PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(1.0f);
Tessellator::Result result = t.Tessellate(
FillType::kPositive, polyline,
[](const float* vertices, size_t vertices_size, const uint16_t* indices,