[Impeller] Change Path::CreatePolyline from tolerance to scale, and make it required (flutter/engine#39917)

[Impeller] Change Path::CreatePolyline from tolerance to scale, and make it required
This commit is contained in:
Dan Field 2023-02-27 13:12:09 -08:00 committed by GitHub
parent a3d5c25a5c
commit 1d111e1732
9 changed files with 47 additions and 48 deletions

View File

@ -123,7 +123,7 @@ bool TextureContents::Render(const ContentContext& renderer,
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) {

View File

@ -53,13 +53,11 @@ GeometryResult FillPathGeometry::GetPositionBuffer(
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 @@ StrokePathGeometry::JoinProc StrokePathGeometry::GetJoinProc(Join stroke_join) {
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 @@ StrokePathGeometry::JoinProc StrokePathGeometry::GetJoinProc(Join stroke_join) {
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 @@ StrokePathGeometry::JoinProc StrokePathGeometry::GetJoinProc(Join stroke_join) {
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 @@ StrokePathGeometry::JoinProc StrokePathGeometry::GetJoinProc(Join stroke_join) {
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 @@ StrokePathGeometry::CapProc StrokePathGeometry::GetCapProc(Cap stroke_cap) {
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 @@ StrokePathGeometry::CapProc StrokePathGeometry::GetCapProc(Cap stroke_cap) {
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 @@ StrokePathGeometry::CapProc StrokePathGeometry::GetCapProc(Cap stroke_cap) {
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 @@ StrokePathGeometry::CapProc StrokePathGeometry::GetCapProc(Cap stroke_cap) {
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 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices(
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 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices(
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 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices(
}
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 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices(
// 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 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices(
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 @@ GeometryResult StrokePathGeometry::GetPositionBuffer(
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,

View File

@ -134,14 +134,14 @@ class StrokePathGeometry : public Geometry {
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 @@ class StrokePathGeometry : public Geometry {
Cap cap,
const JoinProc& join_proc,
const CapProc& cap_proc,
Scalar tolerance);
Scalar scale);
static StrokePathGeometry::JoinProc GetJoinProc(Join stroke_join);

View File

@ -29,7 +29,7 @@ static void BM_Polyline(benchmark::State& state, Args&&... args) {
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) {

View File

@ -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 @@ TEST(GeometryTest, EmptyPath) {
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 @@ TEST(GeometryTest, PathCreatePolyLineDoesNotDuplicatePoints) {
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 @@ TEST(GeometryTest, PathCreatePolylineGeneratesCorrectContourData) {
.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 @@ TEST(GeometryTest, PolylineGetContourPointBoundsReturnsCorrectRanges) {
.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 @@ TEST(GeometryTest, PathAddRectPolylineHasCorrectContourData) {
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 @@ TEST(GeometryTest, PathPolylineDuplicatesAreRemovedForSameContour) {
.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);

View File

@ -7,6 +7,7 @@
#include <optional>
#include "impeller/geometry/path_component.h"
#include "path_component.h"
namespace impeller {
@ -221,8 +222,9 @@ bool Path::UpdateContourComponentAtIndex(size_t index,
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](

View File

@ -11,6 +11,7 @@
#include <vector>
#include "impeller/geometry/path_component.h"
#include "path_component.h"
namespace impeller {
@ -122,7 +123,12 @@ class Path {
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;

View File

@ -396,7 +396,7 @@ TEST_P(RendererTest, CanRenderInstanced) {
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) {

View File

@ -14,7 +14,7 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
// 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 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
// 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 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
{
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 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
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 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
{
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,