5 #include "flutter/testing/testing.h"
6 #include "gtest/gtest.h"
16 TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
23 [](
const float* vertices,
size_t vertices_count,
24 const uint16_t* indices,
size_t indices_count) {
return true; });
35 [](
const float* vertices,
size_t vertices_count,
36 const uint16_t* indices,
size_t indices_count) {
return true; });
47 [](
const float* vertices,
size_t vertices_count,
48 const uint16_t* indices,
size_t indices_count) {
return true; });
57 for (
int i = 0; i < 1000; i++) {
58 auto coord = i * 1.0f;
59 builder.
AddLine({coord, coord}, {coord + 1, coord + 1});
64 [](
const float* vertices,
size_t vertices_count,
65 const uint16_t* indices,
size_t indices_count) {
return true; });
76 [](
const float* vertices,
size_t vertices_count,
77 const uint16_t* indices,
size_t indices_count) {
return false; });
86 for (
auto i = 0; i < 1000; i++) {
90 bool no_indices =
false;
94 [&no_indices, &count](
const float* vertices,
size_t vertices_count,
95 const uint16_t* indices,
size_t indices_count) {
96 no_indices = indices ==
nullptr;
97 count = vertices_count;
101 ASSERT_TRUE(no_indices);
102 ASSERT_TRUE(count >= USHRT_MAX);
107 TEST(TessellatorTest, TessellateConvex) {
114 std::vector<Point> expected = {{0, 0}, {10, 0}, {0, 10}, {10, 10}};
115 EXPECT_EQ(pts, expected);
126 std::vector<Point> expected = {{0, 0}, {10, 0}, {0, 10}, {10, 10},
127 {10, 10}, {20, 20}, {20, 20}, {30, 20},
129 EXPECT_EQ(pts, expected);
135 auto path = builder.
MoveTo({10, 10})
144 TEST(TessellatorTest, CircleVertexCounts) {
145 auto tessellator = std::make_shared<Tessellator>();
147 auto test = [&tessellator](
const Matrix& transform,
Scalar radius) {
148 auto generator = tessellator->FilledCircle(transform, {}, radius);
149 size_t quadrant_divisions = generator.GetVertexCount() / 4;
154 double angle =
kPiOver2 / quadrant_divisions;
155 Point first = {radius, 0};
156 Point next = {
static_cast<Scalar>(cos(angle) * radius),
157 static_cast<Scalar>(sin(angle) * radius)};
158 Point midpoint = (first + next) * 0.5;
161 <<
", transform = " << transform <<
", radius = " << radius
162 <<
", divisions = " << quadrant_divisions;
175 for (
int i = 36; i < 10000; i += 4) {
180 TEST(TessellatorTest, FilledCircleTessellationVertices) {
181 auto tessellator = std::make_shared<Tessellator>();
183 auto test = [&tessellator](
const Matrix& transform,
const Point& center,
185 auto generator = tessellator->FilledCircle(transform, center, radius);
188 auto vertex_count = generator.GetVertexCount();
189 auto vertices = std::vector<Point>();
190 generator.GenerateVertices([&vertices](
const Point& p) {
191 vertices.push_back(p);
193 EXPECT_EQ(vertices.size(), vertex_count);
194 ASSERT_EQ(vertex_count % 4, 0u);
196 auto quadrant_count = vertex_count / 4;
197 for (
size_t i = 0; i < quadrant_count; i++) {
198 double angle =
kPiOver2 * i / (quadrant_count - 1);
199 double degrees = angle * 180.0 /
kPi;
200 double rsin = sin(angle) * radius;
201 double rcos = cos(angle) * radius;
203 Point(center.x - rcos, center.y + rsin))
204 <<
"vertex " << i <<
", angle = " << degrees << std::endl;
206 Point(center.x - rcos, center.y - rsin))
207 <<
"vertex " << i <<
", angle = " << degrees << std::endl;
209 Point(center.x + rcos, center.y - rsin))
210 <<
"vertex " << i <<
", angle = " << degrees << std::endl;
212 Point(center.x + rcos, center.y + rsin))
213 <<
"vertex " << i <<
", angle = " << degrees << std::endl;
218 test({}, {10, 10}, 2.0);
223 TEST(TessellatorTest, StrokedCircleTessellationVertices) {
224 auto tessellator = std::make_shared<Tessellator>();
226 auto test = [&tessellator](
const Matrix& transform,
const Point& center,
228 ASSERT_GT(radius, half_width);
230 tessellator->StrokedCircle(transform, center, radius, half_width);
233 auto vertex_count = generator.GetVertexCount();
234 auto vertices = std::vector<Point>();
235 generator.GenerateVertices([&vertices](
const Point& p) {
236 vertices.push_back(p);
238 EXPECT_EQ(vertices.size(), vertex_count);
239 ASSERT_EQ(vertex_count % 4, 0u);
241 auto quadrant_count = vertex_count / 8;
244 for (
size_t i = 0; i < quadrant_count; i++) {
245 double angle =
kPiOver2 * i / (quadrant_count - 1);
246 double degrees = angle * 180.0 /
kPi;
247 double rsin = sin(angle) * (radius + half_width);
248 double rcos = cos(angle) * (radius + half_width);
250 Point(center.x - rcos, center.y - rsin))
251 <<
"vertex " << i <<
", angle = " << degrees << std::endl;
253 Point(center.x + rsin, center.y - rcos))
254 <<
"vertex " << i <<
", angle = " << degrees << std::endl;
256 Point(center.x + rcos, center.y + rsin))
257 <<
"vertex " << i <<
", angle = " << degrees << std::endl;
259 Point(center.x - rsin, center.y + rcos))
260 <<
"vertex " << i <<
", angle = " << degrees << std::endl;
264 for (
size_t i = 0; i < quadrant_count; i++) {
265 double angle =
kPiOver2 * i / (quadrant_count - 1);
266 double degrees = angle * 180.0 /
kPi;
267 double rsin = sin(angle) * (radius - half_width);
268 double rcos = 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);
291 TEST(TessellatorTest, RoundCapLineTessellationVertices) {
292 auto tessellator = std::make_shared<Tessellator>();
294 auto test = [&tessellator](
const Matrix& transform,
const Point& p0,
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;
310 along *= radius / length;
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;
320 Point relative_along = along * cos(angle);
321 Point relative_across = across * sin(angle);
323 p0 - relative_along + relative_across)
324 <<
"vertex " << i <<
", angle = " << degrees <<
", "
325 <<
"line = " << p0 <<
" => " << p1 <<
", "
326 <<
"radius = " << radius << std::endl;
328 p0 - relative_along - relative_across)
329 <<
"vertex " << i <<
", angle = " << degrees <<
", "
330 <<
"line = " << p0 <<
" => " << p1 <<
", "
331 <<
"radius = " << radius << std::endl;
333 p1 + relative_along - relative_across)
334 <<
"vertex " << i <<
", angle = " << degrees <<
", "
335 <<
"line = " << p0 <<
" => " << p1 <<
", "
336 <<
"radius = " << radius << std::endl;
338 p1 + relative_along + relative_across)
339 <<
"vertex " << i <<
", angle = " << degrees <<
", "
340 <<
"line = " << p0 <<
" => " << p1 <<
", "
341 <<
"radius = " << radius << std::endl;
347 test({}, {0, 0}, {0, 0}, 10);
349 test({}, {0, 0}, {10, 0}, 2);
350 test({}, {10, 0}, {0, 0}, 2);
351 test({}, {0, 0}, {10, 10}, 2);
362 TEST(TessellatorTest, FilledEllipseTessellationVertices) {
363 auto tessellator = std::make_shared<Tessellator>();
365 auto test = [&tessellator](
const Matrix& transform,
const Rect& bounds) {
366 auto center = bounds.GetCenter();
367 auto half_size = bounds.GetSize() * 0.5f;
369 auto generator = tessellator->FilledEllipse(transform, bounds);
372 auto vertex_count = generator.GetVertexCount();
373 auto vertices = std::vector<Point>();
374 generator.GenerateVertices([&vertices](
const Point& p) {
375 vertices.push_back(p);
377 EXPECT_EQ(vertices.size(), vertex_count);
378 ASSERT_EQ(vertex_count % 4, 0u);
380 auto quadrant_count = vertex_count / 4;
381 for (
size_t i = 0; i < quadrant_count; i++) {
382 double angle =
kPiOver2 * i / (quadrant_count - 1);
383 double degrees = angle * 180.0 /
kPi;
384 double rcos = cos(angle) * half_size.width;
385 double rsin = sin(angle) * half_size.height;
387 Point(center.x - rcos, center.y + rsin))
388 <<
"vertex " << i <<
", angle = " << degrees <<
", "
389 <<
"bounds = " << bounds << std::endl;
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;
421 TEST(TessellatorTest, FilledRoundRectTessellationVertices) {
422 auto tessellator = std::make_shared<Tessellator>();
424 auto test = [&tessellator](
const Matrix& transform,
const Rect& bounds,
426 FML_DCHECK(radii.width * 2 <= bounds.GetWidth()) << radii << bounds;
427 FML_DCHECK(radii.height * 2 <= bounds.GetHeight()) << radii << bounds;
429 Scalar middle_left = bounds.GetX() + radii.width;
430 Scalar middle_top = bounds.GetY() + radii.height;
431 Scalar middle_right = bounds.GetX() + bounds.GetWidth() - radii.width;
432 Scalar middle_bottom = bounds.GetY() + bounds.GetHeight() - radii.height;
434 auto generator = tessellator->FilledRoundRect(transform, bounds, radii);
437 auto vertex_count = generator.GetVertexCount();
438 auto vertices = std::vector<Point>();
439 generator.GenerateVertices([&vertices](
const Point& p) {
440 vertices.push_back(p);
442 EXPECT_EQ(vertices.size(), vertex_count);
443 ASSERT_EQ(vertex_count % 4, 0u);
445 auto quadrant_count = vertex_count / 4;
446 for (
size_t i = 0; i < quadrant_count; i++) {
447 double angle =
kPiOver2 * i / (quadrant_count - 1);
448 double degrees = angle * 180.0 /
kPi;
449 double rcos = cos(angle) * radii.width;
450 double rsin = sin(angle) * radii.height;
452 Point(middle_left - rcos, middle_bottom + rsin))
453 <<
"vertex " << i <<
", angle = " << degrees <<
", "
454 <<
"bounds = " << bounds << std::endl;
456 Point(middle_left - rcos, middle_top - rsin))
457 <<
"vertex " << i <<
", angle = " << degrees <<
", "
458 <<
"bounds = " << bounds << std::endl;
460 Point(middle_right + rcos, middle_top - rsin))
461 <<
"vertex " << i <<
", angle = " << degrees <<
", "
462 <<
"bounds = " << bounds << std::endl;
464 Point(middle_right + rcos, middle_bottom + rsin))
465 <<
"vertex " << i <<
", angle = " << degrees <<
", "
466 <<
"bounds = " << bounds << std::endl;
494 TEST(TessellatorTest, EarlyReturnEmptyConvexShape) {
497 auto tessellator = std::make_shared<Tessellator>();
500 builder.
MoveTo({10, 10},
true);
502 auto points = tessellator->TessellateConvex(builder.
TakePath(), 3.0);
504 EXPECT_TRUE(points.empty());
508 TEST(TessellatorTest, ChecksConcurrentPolylineUsage) {
509 auto tessellator = std::make_shared<Tessellator>();
511 builder.
AddLine({0, 0}, {100, 100});
514 auto polyline = tessellator->CreateTempPolyline(path, 0.1);
515 EXPECT_DEBUG_DEATH(tessellator->CreateTempPolyline(path, 0.1),