5#include "flutter/testing/testing.h"
6#include "gtest/gtest.h"
17TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
24 [](
const float* vertices,
size_t vertices_count,
25 const uint16_t* indices,
size_t indices_count) {
return true; });
36 [](
const float* vertices,
size_t vertices_count,
37 const uint16_t* indices,
size_t indices_count) {
return true; });
48 [](
const float* vertices,
size_t vertices_count,
49 const uint16_t* indices,
size_t indices_count) {
return true; });
58 for (
int i = 0;
i < 1000;
i++) {
59 auto coord =
i * 1.0f;
60 builder.AddLine({coord, coord}, {coord + 1, coord + 1});
65 [](
const float* vertices,
size_t vertices_count,
66 const uint16_t* indices,
size_t indices_count) {
return true; });
77 [](
const float* vertices,
size_t vertices_count,
78 const uint16_t* indices,
size_t indices_count) {
return false; });
84TEST(TessellatorTest, TessellateConvex) {
87 std::vector<uint16_t> indices;
95 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}};
96 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
97 EXPECT_EQ(
points, expected);
98 EXPECT_EQ(indices, expected_indices);
102 std::vector<Point>
points;
103 std::vector<uint16_t> indices;
111 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10},
112 {0, 0}, {20, 20}, {30, 20}, {30, 30},
114 std::vector<uint16_t> expected_indices = {0, 1, 3, 2, 2, 5, 5, 6, 8, 7};
115 EXPECT_EQ(
points, expected);
116 EXPECT_EQ(indices, expected_indices);
121TEST(TessellatorTest, TessellateConvexUnclosedPath) {
122 std::vector<Point>
points;
123 std::vector<uint16_t> indices;
133 std::vector<Point> expected = {{0, 0}, {100, 0}, {100, 100}, {0, 100}};
134 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
135 EXPECT_EQ(
points, expected);
136 EXPECT_EQ(indices, expected_indices);
139TEST(TessellatorTest, CircleVertexCounts) {
140 auto tessellator = std::make_shared<Tessellator>();
143 auto generator = tessellator->FilledCircle(
transform, {}, radius);
144 size_t quadrant_divisions = generator.GetVertexCount() / 4;
149 double angle =
kPiOver2 / quadrant_divisions;
150 Point first = {radius, 0};
152 static_cast<Scalar>(sin(angle) * radius)};
154 EXPECT_GE(midpoint.GetLength(),
156 <<
", transform = " <<
transform <<
", radius = " << radius
157 <<
", divisions = " << quadrant_divisions;
170 for (
int i = 36;
i < 10000;
i += 4) {
175TEST(TessellatorTest, FilledCircleTessellationVertices) {
176 auto tessellator = std::make_shared<Tessellator>();
180 auto generator = tessellator->FilledCircle(
transform, center, radius);
183 auto vertex_count = generator.GetVertexCount();
184 auto vertices = std::vector<Point>();
185 generator.GenerateVertices([&vertices](
const Point&
p) {
186 vertices.push_back(
p);
188 EXPECT_EQ(vertices.size(), vertex_count);
189 ASSERT_EQ(vertex_count % 4, 0u);
191 auto quadrant_count = vertex_count / 4;
192 for (
size_t i = 0;
i < quadrant_count;
i++) {
193 double angle =
kPiOver2 *
i / (quadrant_count - 1);
194 double degrees = angle * 180.0 /
kPi;
195 double rsin = sin(angle) * radius;
197 double rcos = (
i == quadrant_count - 1) ? 0.0f : cos(angle) * radius;
199 Point(center.x - rcos, center.y + rsin))
200 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
202 Point(center.x - rcos, center.y - rsin))
203 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
205 Point(center.x + rcos, center.y - rsin))
206 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
208 Point(center.x + rcos, center.y + rsin))
209 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
214 test({}, {10, 10}, 2.0);
219TEST(TessellatorTest, StrokedCircleTessellationVertices) {
220 auto tessellator = std::make_shared<Tessellator>();
224 ASSERT_GT(radius, half_width);
226 tessellator->StrokedCircle(
transform, center, radius, half_width);
229 auto vertex_count = generator.GetVertexCount();
230 auto vertices = std::vector<Point>();
231 generator.GenerateVertices([&vertices](
const Point&
p) {
232 vertices.push_back(
p);
234 EXPECT_EQ(vertices.size(), vertex_count);
235 ASSERT_EQ(vertex_count % 4, 0u);
237 auto quadrant_count = vertex_count / 8;
240 for (
size_t i = 0;
i < quadrant_count;
i++) {
241 double angle =
kPiOver2 *
i / (quadrant_count - 1);
242 double degrees = angle * 180.0 /
kPi;
243 double rsin = sin(angle) * (radius + half_width);
246 (
i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius + half_width);
248 Point(center.x - rcos, center.y - rsin))
249 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
251 Point(center.x + rsin, center.y - rcos))
252 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
254 Point(center.x + rcos, center.y + rsin))
255 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
257 Point(center.x - rsin, center.y + rcos))
258 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
262 for (
size_t i = 0;
i < quadrant_count;
i++) {
263 double angle =
kPiOver2 *
i / (quadrant_count - 1);
264 double degrees = angle * 180.0 /
kPi;
265 double rsin = sin(angle) * (radius - half_width);
268 (
i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius - half_width);
270 Point(center.x - rcos, center.y - rsin))
271 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
273 Point(center.x + rsin, center.y - rcos))
274 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
276 Point(center.x + rcos, center.y + rsin))
277 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
279 Point(center.x - rsin, center.y + rcos))
280 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
284 test({}, {}, 2.0, 1.0);
285 test({}, {}, 2.0, 0.5);
286 test({}, {10, 10}, 2.0, 1.0);
291TEST(TessellatorTest, RoundCapLineTessellationVertices) {
292 auto tessellator = std::make_shared<Tessellator>();
296 auto generator = tessellator->RoundCapLine(
transform, p0, p1, radius);
299 auto vertex_count = generator.GetVertexCount();
300 auto vertices = std::vector<Point>();
301 generator.GenerateVertices([&vertices](
const Point&
p) {
302 vertices.push_back(
p);
304 EXPECT_EQ(vertices.size(), vertex_count);
305 ASSERT_EQ(vertex_count % 4, 0u);
307 Point along = p1 - p0;
314 Point across = {-along.
y, along.
x};
316 auto quadrant_count = vertex_count / 4;
317 for (
size_t i = 0;
i < quadrant_count;
i++) {
318 double angle =
kPiOver2 *
i / (quadrant_count - 1);
319 double degrees = angle * 180.0 /
kPi;
321 Point relative_along =
322 along * ((
i == quadrant_count - 1) ? 0.0f : cos(angle));
323 Point relative_across = across * sin(angle);
325 p0 - relative_along + relative_across)
326 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
327 <<
"line = " << p0 <<
" => " << p1 <<
", "
328 <<
"radius = " << radius << std::endl;
330 p0 - relative_along - relative_across)
331 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
332 <<
"line = " << p0 <<
" => " << p1 <<
", "
333 <<
"radius = " << radius << std::endl;
335 p1 + relative_along - relative_across)
336 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
337 <<
"line = " << p0 <<
" => " << p1 <<
", "
338 <<
"radius = " << radius << std::endl;
340 p1 + relative_along + relative_across)
341 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
342 <<
"line = " << p0 <<
" => " << p1 <<
", "
343 <<
"radius = " << radius << std::endl;
349 test({}, {0, 0}, {0, 0}, 10);
351 test({}, {0, 0}, {10, 0}, 2);
352 test({}, {10, 0}, {0, 0}, 2);
353 test({}, {0, 0}, {10, 10}, 2);
364TEST(TessellatorTest, FilledEllipseTessellationVertices) {
365 auto tessellator = std::make_shared<Tessellator>();
368 auto center =
bounds.GetCenter();
369 auto half_size =
bounds.GetSize() * 0.5f;
374 auto vertex_count = generator.GetVertexCount();
375 auto vertices = std::vector<Point>();
376 generator.GenerateVertices([&vertices](
const Point&
p) {
377 vertices.push_back(
p);
379 EXPECT_EQ(vertices.size(), vertex_count);
380 ASSERT_EQ(vertex_count % 4, 0u);
382 auto quadrant_count = vertex_count / 4;
383 for (
size_t i = 0;
i < quadrant_count;
i++) {
384 double angle =
kPiOver2 *
i / (quadrant_count - 1);
385 double degrees = angle * 180.0 /
kPi;
388 (
i == quadrant_count - 1) ? 0.0f : cos(angle) * half_size.width;
389 double rsin = sin(angle) * half_size.height;
391 Point(center.x - rcos, center.y + rsin))
392 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
393 <<
"bounds = " <<
bounds << std::endl;
395 Point(center.x - rcos, center.y - rsin))
396 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
397 <<
"bounds = " <<
bounds << std::endl;
399 Point(center.x + rcos, center.y - rsin))
400 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
401 <<
"bounds = " <<
bounds << std::endl;
403 Point(center.x + rcos, center.y + rsin))
404 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
405 <<
"bounds = " <<
bounds << std::endl;
425TEST(TessellatorTest, FilledRoundRectTessellationVertices) {
426 auto tessellator = std::make_shared<Tessellator>();
438 auto generator = tessellator->FilledRoundRect(
transform,
bounds, radii);
441 auto vertex_count = generator.GetVertexCount();
442 auto vertices = std::vector<Point>();
443 generator.GenerateVertices([&vertices](
const Point&
p) {
444 vertices.push_back(
p);
446 EXPECT_EQ(vertices.size(), vertex_count);
447 ASSERT_EQ(vertex_count % 4, 0u);
449 auto quadrant_count = vertex_count / 4;
450 for (
size_t i = 0;
i < quadrant_count;
i++) {
451 double angle =
kPiOver2 *
i / (quadrant_count - 1);
452 double degrees = angle * 180.0 /
kPi;
454 double rcos = (
i == quadrant_count - 1) ? 0.0f : cos(angle) * radii.width;
455 double rsin = sin(angle) * radii.height;
457 Point(middle_left - rcos, middle_bottom + rsin))
458 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
459 <<
"bounds = " <<
bounds << std::endl;
461 Point(middle_left - rcos, middle_top - rsin))
462 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
463 <<
"bounds = " <<
bounds << std::endl;
465 Point(middle_right + rcos, middle_top - rsin))
466 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
467 <<
"bounds = " <<
bounds << std::endl;
469 Point(middle_right + rcos, middle_bottom + rsin))
470 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
471 <<
"bounds = " <<
bounds << std::endl;
499TEST(TessellatorTest, EarlyReturnEmptyConvexShape) {
504 builder.MoveTo({10, 10},
true);
506 std::vector<Point>
points;
507 std::vector<uint16_t> indices;
515TEST(TessellatorTest, ChecksConcurrentPolylineUsage) {
516 auto tessellator = std::make_shared<Tessellator>();
518 builder.AddLine({0, 0}, {100, 100});
521 auto polyline = tessellator->CreateTempPolyline(
path, 0.1);
522 EXPECT_DEBUG_DEATH(tessellator->CreateTempPolyline(
path, 0.1),
static const int points[]
static float next(float f)
PathBuilder & AddRect(Rect rect)
Path TakePath(FillType fill=FillType::kNonZero)
PathBuilder & LineTo(Point point, bool relative=false)
Insert a line from the current position to point.
PathBuilder & AddLine(const Point &p1, const Point &p2)
Move to point p1, then insert a line from p1 to p2.
An extended tessellator that offers arbitrary/concave tessellation via the libtess2 library.
TessellatorLibtess::Result Tessellate(const Path &path, Scalar tolerance, const BuilderCallback &callback)
Generates filled triangles from the path. A callback is invoked once for the entire tessellation.
static constexpr Scalar kCircleTolerance
The pixel tolerance used by the algorighm to determine how many divisions to create for a circle.
static void TessellateConvexInternal(const Path &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
#define FML_DCHECK(condition)
#define EXPECT_POINT_NEAR(a, b)
Optional< SkRect > bounds
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
TEST(AiksCanvasTest, EmptyCullRect)
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
const Path::Polyline & polyline
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeScale(const Vector3 &s)
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
#define EXPECT_TRUE(handle)