Skip to content

Commit 88a889a

Browse files
authored
[Impeller] Fix vertex allocation counts for flat curves (flutter#170194)
The code that estimated the vertex counts for filling paths was not taking into account that the minimum number of points allocated for a curve segment is 1. The iteration estimates will return "don't bother to subdivide the curve" cases as "0 subdivisions" and we estimated no vertices would be generated. In fact, the rendering code would always emit the final point regardless of the subdivision estimate. Other cases that returned a value >0 were already accurate.
1 parent 1b9502b commit 88a889a

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

engine/src/flutter/impeller/tessellator/path_tessellator.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,17 +194,21 @@ class StorageCounter : public SegmentReceiver {
194194
void RecordLine(Point p1, Point p2) override { point_count_++; }
195195

196196
void RecordQuad(Point p1, Point cp, Point p2) override {
197-
point_count_ += std::ceil(ComputeQuadradicSubdivisions(scale_, p1, cp, p2));
197+
size_t count = //
198+
std::ceilf(ComputeQuadradicSubdivisions(scale_, p1, cp, p2));
199+
point_count_ += std::max<size_t>(count, 1);
198200
}
199201

200202
void RecordConic(Point p1, Point cp, Point p2, Scalar weight) override {
201-
point_count_ +=
202-
std::ceil(ComputeConicSubdivisions(scale_, p1, cp, p2, weight));
203+
size_t count = //
204+
std::ceilf(ComputeConicSubdivisions(scale_, p1, cp, p2, weight));
205+
point_count_ += std::max<size_t>(count, 1);
203206
}
204207

205208
void RecordCubic(Point p1, Point cp1, Point cp2, Point p2) override {
206-
point_count_ +=
207-
std::ceil(ComputeCubicSubdivisions(scale_, p1, cp1, cp2, p2));
209+
size_t count = //
210+
std::ceilf(ComputeCubicSubdivisions(scale_, p1, cp1, cp2, p2));
211+
point_count_ += std::max<size_t>(count, 1);
208212
}
209213

210214
void EndContour(Point origin, bool with_close) override {

engine/src/flutter/impeller/tessellator/path_tessellator_unittests.cc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,5 +544,41 @@ TEST(PathTessellatorTest, ComplexPathTrailingMoveTo) {
544544
PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
545545
}
546546

547+
TEST(PathTessellatorTest, LinearQuadToPointCount) {
548+
flutter::DlPathBuilder builder;
549+
builder.MoveTo({316.3, 121.5});
550+
builder.QuadraticCurveTo({316.4, 121.5}, {316.5, 121.5});
551+
builder.Close();
552+
auto path = builder.TakePath();
553+
554+
auto [points, contours] = PathTessellator::CountFillStorage(path, 2.0f);
555+
EXPECT_EQ(points, 3u);
556+
EXPECT_EQ(contours, 1u);
557+
}
558+
559+
TEST(PathTessellatorTest, LinearConicToPointCount) {
560+
flutter::DlPathBuilder builder;
561+
builder.MoveTo({316.3, 121.5});
562+
builder.ConicCurveTo({316.4, 121.5}, {316.5, 121.5}, 2.0f);
563+
builder.Close();
564+
auto path = builder.TakePath();
565+
566+
auto [points, contours] = PathTessellator::CountFillStorage(path, 2.0f);
567+
EXPECT_EQ(points, 3u);
568+
EXPECT_EQ(contours, 1u);
569+
}
570+
571+
TEST(PathTessellatorTest, LinearCubicToPointCount) {
572+
flutter::DlPathBuilder builder;
573+
builder.MoveTo({316.3, 121.5});
574+
builder.CubicCurveTo({316.4, 121.5}, {316.5, 121.5}, {316.6, 121.5});
575+
builder.Close();
576+
auto path = builder.TakePath();
577+
578+
auto [points, contours] = PathTessellator::CountFillStorage(path, 2.0f);
579+
EXPECT_EQ(points, 3u);
580+
EXPECT_EQ(contours, 1u);
581+
}
582+
547583
} // namespace testing
548584
} // namespace impeller

0 commit comments

Comments
 (0)