mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[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:
parent
a3d5c25a5c
commit
1d111e1732
@ -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) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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](
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user