6#include "gtest/gtest.h"
17TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
26 [](
const float* vertices,
size_t vertices_count,
27 const uint16_t* indices,
size_t indices_count) {
return true; });
41 [](
const float* vertices,
size_t vertices_count,
42 const uint16_t* indices,
size_t indices_count) {
return true; });
57 [](
const float* vertices,
size_t vertices_count,
58 const uint16_t* indices,
size_t indices_count) {
return true; });
67 for (
int i = 0;
i < 1000;
i++) {
68 auto coord =
i * 1.0f;
69 builder.
MoveTo({coord, coord}).
LineTo({coord + 1, coord + 1});
74 [](
const float* vertices,
size_t vertices_count,
75 const uint16_t* indices,
size_t indices_count) {
return true; });
90 [](
const float* vertices,
size_t vertices_count,
91 const uint16_t* indices,
size_t indices_count) {
return false; });
97TEST(TessellatorTest, TessellateConvex) {
100 std::vector<uint16_t> indices;
108 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}};
109 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
110 EXPECT_EQ(
points, expected);
111 EXPECT_EQ(indices, expected_indices);
115 std::vector<Point>
points;
116 std::vector<uint16_t> indices;
124 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10},
125 {0, 0}, {20, 20}, {30, 20}, {30, 30},
127 std::vector<uint16_t> expected_indices = {0, 1, 3, 2, 2, 5, 5, 6, 8, 7};
128 EXPECT_EQ(
points, expected);
129 EXPECT_EQ(indices, expected_indices);
134TEST(TessellatorTest, TessellateConvexUnclosedPath) {
135 std::vector<Point>
points;
136 std::vector<uint16_t> indices;
147 std::vector<Point> expected = {
148 {0, 0}, {100, 0}, {100, 100}, {0, 100}, {0, 0}};
149 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
150 EXPECT_EQ(
points, expected);
151 EXPECT_EQ(indices, expected_indices);
154TEST(TessellatorTest, CircleVertexCounts) {
164 double angle =
kPiOver2 / quadrant_divisions;
165 Point first = {radius, 0};
166 Point next = {
static_cast<Scalar>(cos(angle) * radius),
167 static_cast<Scalar>(sin(angle) * radius)};
168 Point midpoint = (first + next) * 0.5;
169 EXPECT_GE(midpoint.GetLength(),
171 <<
", transform = " <<
transform <<
", radius = " << radius
172 <<
", divisions = " << quadrant_divisions;
185 for (
int i = 36;
i < 10000;
i += 4) {
190TEST(TessellatorTest, FilledCircleTessellationVertices) {
198 auto vertex_count = generator.GetVertexCount();
199 auto vertices = std::vector<Point>();
200 generator.GenerateVertices([&vertices](
const Point& p) {
201 vertices.push_back(p);
203 EXPECT_EQ(vertices.size(), vertex_count);
204 ASSERT_EQ(vertex_count % 4, 0u);
206 auto quadrant_count = vertex_count / 4;
207 for (
size_t i = 0;
i < quadrant_count;
i++) {
208 double angle =
kPiOver2 *
i / (quadrant_count - 1);
209 double degrees = angle * 180.0 /
kPi;
210 double rsin = sin(angle) * radius;
212 double rcos = (
i == quadrant_count - 1) ? 0.0f : cos(angle) * radius;
214 Point(center.x - rcos, center.y + rsin))
215 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
217 Point(center.x - rcos, center.y - rsin))
218 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
220 Point(center.x + rcos, center.y - rsin))
221 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
223 Point(center.x + rcos, center.y + rsin))
224 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
229 test({}, {10, 10}, 2.0);
234TEST(TessellatorTest, StrokedCircleTessellationVertices) {
239 ASSERT_GT(radius, half_width);
244 auto vertex_count = generator.GetVertexCount();
245 auto vertices = std::vector<Point>();
246 generator.GenerateVertices([&vertices](
const Point& p) {
247 vertices.push_back(p);
249 EXPECT_EQ(vertices.size(), vertex_count);
250 ASSERT_EQ(vertex_count % 4, 0u);
252 auto quadrant_count = vertex_count / 8;
255 for (
size_t i = 0;
i < quadrant_count;
i++) {
256 double angle =
kPiOver2 *
i / (quadrant_count - 1);
257 double degrees = angle * 180.0 /
kPi;
258 double rsin = sin(angle) * (radius + half_width);
261 (
i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius + half_width);
263 Point(center.x - rcos, center.y - rsin))
264 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
266 Point(center.x + rsin, center.y - rcos))
267 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
269 Point(center.x + rcos, center.y + rsin))
270 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
272 Point(center.x - rsin, center.y + rcos))
273 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
277 for (
size_t i = 0;
i < quadrant_count;
i++) {
278 double angle =
kPiOver2 *
i / (quadrant_count - 1);
279 double degrees = angle * 180.0 /
kPi;
280 double rsin = sin(angle) * (radius - half_width);
283 (
i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius - half_width);
285 Point(center.x - rcos, center.y - rsin))
286 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
288 Point(center.x + rsin, center.y - rcos))
289 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
291 Point(center.x + rcos, center.y + rsin))
292 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
294 Point(center.x - rsin, center.y + rcos))
295 <<
"vertex " <<
i <<
", angle = " << degrees << std::endl;
299 test({}, {}, 2.0, 1.0);
300 test({}, {}, 2.0, 0.5);
301 test({}, {10, 10}, 2.0, 1.0);
306TEST(TessellatorTest, FilledArcStripTessellationVertices) {
314 auto vertex_count = generator.GetVertexCount();
315 auto vertices = std::vector<Point>();
316 generator.GenerateVertices([&vertices](
const Point& p) {
317 vertices.push_back(p);
319 EXPECT_EQ(vertices.size(), vertex_count);
321 auto center = arc.GetOvalBounds().GetCenter();
322 auto radius = arc.GetOvalSize().width * 0.5;
331 auto last_angle = arc.GetStart() + arc.GetSweep();
333 vertices[vertex_count - 1],
334 Point(center.x + cos(
Radians(last_angle).radians) * radius,
335 center.y + sin(
Radians(last_angle).radians) * radius));
338 Point origin = arc.IncludeCenter()
340 : (vertices[0] + vertices[vertex_count - 1]) * 0.5f;
341 for (
size_t i = 1;
i < vertex_count;
i += 2) {
346 auto previous_outer_point = vertices[0];
347 auto outer_increment_distance = (vertices[4] - vertices[2]).GetLength();
348 for (
size_t i = 2;
i < vertex_count;
i += 2) {
350 EXPECT_NEAR((vertices[
i] - center).GetLength(), radius,
kEhCloseEnough);
353 if (
i == 2 ||
i == vertex_count - 1) {
356 EXPECT_LE((vertices[
i] - previous_outer_point).GetLength(),
360 EXPECT_NEAR((vertices[
i] - previous_outer_point).GetLength(),
364 previous_outer_point = vertices[
i];
382TEST(TessellatorTest, RoundCapLineTessellationVertices) {
390 auto vertex_count = generator.GetVertexCount();
391 auto vertices = std::vector<Point>();
392 generator.GenerateVertices([&vertices](
const Point& p) {
393 vertices.push_back(p);
395 EXPECT_EQ(vertices.size(), vertex_count);
396 ASSERT_EQ(vertex_count % 4, 0u);
398 Point along = p1 - p0;
405 Point across = {-along.
y, along.
x};
407 auto quadrant_count = vertex_count / 4;
408 for (
size_t i = 0;
i < quadrant_count;
i++) {
409 double angle =
kPiOver2 *
i / (quadrant_count - 1);
410 double degrees = angle * 180.0 /
kPi;
412 Point relative_along =
413 along * ((
i == quadrant_count - 1) ? 0.0f : cos(angle));
414 Point relative_across = across * sin(angle);
416 p0 - relative_along + relative_across)
417 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
418 <<
"line = " << p0 <<
" => " << p1 <<
", "
419 <<
"radius = " << radius << std::endl;
421 p0 - relative_along - relative_across)
422 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
423 <<
"line = " << p0 <<
" => " << p1 <<
", "
424 <<
"radius = " << radius << std::endl;
426 p1 + relative_along - relative_across)
427 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
428 <<
"line = " << p0 <<
" => " << p1 <<
", "
429 <<
"radius = " << radius << std::endl;
431 p1 + relative_along + relative_across)
432 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
433 <<
"line = " << p0 <<
" => " << p1 <<
", "
434 <<
"radius = " << radius << std::endl;
440 test({}, {0, 0}, {0, 0}, 10);
442 test({}, {0, 0}, {10, 0}, 2);
443 test({}, {10, 0}, {0, 0}, 2);
444 test({}, {0, 0}, {10, 10}, 2);
455TEST(TessellatorTest, FilledEllipseTessellationVertices) {
459 auto center = bounds.GetCenter();
460 auto half_size = bounds.GetSize() * 0.5f;
465 auto vertex_count = generator.GetVertexCount();
466 auto vertices = std::vector<Point>();
467 generator.GenerateVertices([&vertices](
const Point& p) {
468 vertices.push_back(p);
470 EXPECT_EQ(vertices.size(), vertex_count);
471 ASSERT_EQ(vertex_count % 4, 0u);
473 auto quadrant_count = vertex_count / 4;
474 for (
size_t i = 0;
i < quadrant_count;
i++) {
475 double angle =
kPiOver2 *
i / (quadrant_count - 1);
476 double degrees = angle * 180.0 /
kPi;
479 (
i == quadrant_count - 1) ? 0.0f : cos(angle) * half_size.width;
480 double rsin = sin(angle) * half_size.height;
482 Point(center.x - rcos, center.y + rsin))
483 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
484 <<
"bounds = " << bounds << std::endl;
486 Point(center.x - rcos, center.y - rsin))
487 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
488 <<
"bounds = " << bounds << std::endl;
490 Point(center.x + rcos, center.y - rsin))
491 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
492 <<
"bounds = " << bounds << std::endl;
494 Point(center.x + rcos, center.y + rsin))
495 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
496 <<
"bounds = " << bounds << std::endl;
516TEST(TessellatorTest, FilledRoundRectTessellationVertices) {
521 FML_DCHECK(radii.width * 2 <= bounds.GetWidth()) << radii << bounds;
522 FML_DCHECK(radii.height * 2 <= bounds.GetHeight()) << radii << bounds;
524 Scalar middle_left = bounds.GetX() + radii.width;
525 Scalar middle_top = bounds.GetY() + radii.height;
526 Scalar middle_right = bounds.GetX() + bounds.GetWidth() - radii.width;
527 Scalar middle_bottom = bounds.GetY() + bounds.GetHeight() - radii.height;
532 auto vertex_count = generator.GetVertexCount();
533 auto vertices = std::vector<Point>();
534 generator.GenerateVertices([&vertices](
const Point& p) {
535 vertices.push_back(p);
537 EXPECT_EQ(vertices.size(), vertex_count);
538 ASSERT_EQ(vertex_count % 4, 0u);
540 auto quadrant_count = vertex_count / 4;
541 for (
size_t i = 0;
i < quadrant_count;
i++) {
542 double angle =
kPiOver2 *
i / (quadrant_count - 1);
543 double degrees = angle * 180.0 /
kPi;
545 double rcos = (
i == quadrant_count - 1) ? 0.0f : cos(angle) * radii.width;
546 double rsin = sin(angle) * radii.height;
548 Point(middle_left - rcos, middle_bottom + rsin))
549 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
550 <<
"bounds = " << bounds << std::endl;
552 Point(middle_left - rcos, middle_top - rsin))
553 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
554 <<
"bounds = " << bounds << std::endl;
556 Point(middle_right + rcos, middle_top - rsin))
557 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
558 <<
"bounds = " << bounds << std::endl;
560 Point(middle_right + rcos, middle_bottom + rsin))
561 <<
"vertex " <<
i <<
", angle = " << degrees <<
", "
562 <<
"bounds = " << bounds << std::endl;
590TEST(TessellatorTest, EarlyReturnEmptyConvexShape) {
597 std::vector<Point>
points;
598 std::vector<uint16_t> indices;
602 EXPECT_TRUE(
points.empty());
603 EXPECT_TRUE(indices.empty());
DlPathBuilder & LineTo(DlPoint p2)
Draw a line from the current point to the indicated point p2.
DlPathBuilder & MoveTo(DlPoint p2)
Start a new contour that will originate at the indicated point p2.
DlPathBuilder & SetFillType(DlPathFillType fill_type)
Set the fill type that should be used to determine the interior of this path to the indicated |fill_t...
const DlPath TakePath()
Returns the path constructed by this path builder and resets its internal state to the default state ...
DlPathBuilder & AddRect(const DlRect &rect)
Append a closed rectangular contour to the path.
static DlPath MakeRect(const DlRect &rect)
size_t GetVertexCount() const override
|VertexGenerator|
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
EllipticalVertexGenerator RoundCapLine(const Matrix &view_transform, const Point &p0, const Point &p1, Scalar radius)
Create a |VertexGenerator| that can produce vertices for a line with round end caps of the given radi...
EllipticalVertexGenerator FilledRoundRect(const Matrix &view_transform, const Rect &bounds, const Size &radii)
Create a |VertexGenerator| that can produce vertices for a filled round rect within the given bounds ...
static constexpr Scalar kCircleTolerance
The pixel tolerance used by the algorighm to determine how many divisions to create for a circle.
EllipticalVertexGenerator FilledCircle(const Matrix &view_transform, const Point ¢er, Scalar radius)
Create a |VertexGenerator| that can produce vertices for a filled circle of the given radius around t...
static void TessellateConvexInternal(const PathSource &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
EllipticalVertexGenerator StrokedCircle(const Matrix &view_transform, const Point ¢er, Scalar radius, Scalar half_width)
Create a |VertexGenerator| that can produce vertices for a stroked circle of the given radius and hal...
EllipticalVertexGenerator FilledEllipse(const Matrix &view_transform, const Rect &bounds)
Create a |VertexGenerator| that can produce vertices for a filled ellipse inscribed within the given ...
ArcVertexGenerator FilledArc(const Matrix &view_transform, const Arc &arc, bool supports_triangle_fans)
Create a |VertexGenerator| that can produce vertices for a stroked arc inscribed within the given ova...
An extended tessellator that offers arbitrary/concave tessellation via the libtess2 library.
TessellatorLibtess::Result Tessellate(const PathSource &source, Scalar tolerance, const BuilderCallback &callback)
Generates filled triangles from the path. A callback is invoked once for the entire tessellation.
#define FML_DCHECK(condition)
#define EXPECT_POINT_NEAR(a, b)
TEST(FrameTimingsRecorderTest, RecordVsync)
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
static constexpr DlScalar kPi
static constexpr DlScalar kEhCloseEnough
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
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)
std::vector< Point > points