Flutter Impeller
tessellator_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/testing/testing.h"
6 #include "gtest/gtest.h"
7 
8 #include "flutter/display_list/geometry/dl_path_builder.h"
12 
13 namespace impeller {
14 namespace testing {
15 
16 TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
17  // Zero points.
18  {
20  auto path = flutter::DlPathBuilder{} //
21  .SetFillType(FillType::kOdd)
22  .TakePath();
24  path, 1.0f,
25  [](const float* vertices, size_t vertices_count,
26  const uint16_t* indices, size_t indices_count) { return true; });
27 
28  ASSERT_EQ(result, TessellatorLibtess::Result::kInputError);
29  }
30 
31  // One point.
32  {
34  auto path = flutter::DlPathBuilder{}
35  .LineTo({0, 0})
36  .SetFillType(FillType::kOdd)
37  .TakePath();
39  path, 1.0f,
40  [](const float* vertices, size_t vertices_count,
41  const uint16_t* indices, size_t indices_count) { return true; });
42 
43  ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
44  }
45 
46  // Two points.
47  {
49  auto path = flutter::DlPathBuilder{}
50  .MoveTo({0, 0})
51  .LineTo({0, 1})
52  .SetFillType(FillType::kOdd)
53  .TakePath();
55  path, 1.0f,
56  [](const float* vertices, size_t vertices_count,
57  const uint16_t* indices, size_t indices_count) { return true; });
58 
59  ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
60  }
61 
62  // Many points.
63  {
65  flutter::DlPathBuilder builder;
66  for (int i = 0; i < 1000; i++) {
67  auto coord = i * 1.0f;
68  builder.MoveTo({coord, coord}).LineTo({coord + 1, coord + 1});
69  }
70  auto path = builder.SetFillType(FillType::kOdd).TakePath();
72  path, 1.0f,
73  [](const float* vertices, size_t vertices_count,
74  const uint16_t* indices, size_t indices_count) { return true; });
75 
76  ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
77  }
78 
79  // Closure fails.
80  {
82  auto path = flutter::DlPathBuilder{}
83  .MoveTo({0, 0})
84  .LineTo({0, 1})
85  .SetFillType(FillType::kOdd)
86  .TakePath();
88  path, 1.0f,
89  [](const float* vertices, size_t vertices_count,
90  const uint16_t* indices, size_t indices_count) { return false; });
91 
92  ASSERT_EQ(result, TessellatorLibtess::Result::kInputError);
93  }
94 }
95 
96 TEST(TessellatorTest, TessellateConvex) {
97  {
98  std::vector<Point> points;
99  std::vector<uint16_t> indices;
100  // Sanity check simple rectangle.
102  flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 10, 10)), points,
103  indices, 1.0);
104 
105  // Note: the origin point is repeated but not referenced in the indices
106  // below
107  std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}};
108  std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
109  EXPECT_EQ(points, expected);
110  EXPECT_EQ(indices, expected_indices);
111  }
112 
113  {
114  std::vector<Point> points;
115  std::vector<uint16_t> indices;
117  flutter::DlPath(flutter::DlPathBuilder{}
118  .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
119  .AddRect(Rect::MakeLTRB(20, 20, 30, 30))
120  .TakePath()),
121  points, indices, 1.0);
122 
123  std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10},
124  {0, 0}, {20, 20}, {30, 20}, {30, 30},
125  {20, 30}, {20, 20}};
126  std::vector<uint16_t> expected_indices = {0, 1, 3, 2, 2, 5, 5, 6, 8, 7};
127  EXPECT_EQ(points, expected);
128  EXPECT_EQ(indices, expected_indices);
129  }
130 }
131 
132 // Filled Paths without an explicit close should still be closed implicitly
133 TEST(TessellatorTest, TessellateConvexUnclosedPath) {
134  std::vector<Point> points;
135  std::vector<uint16_t> indices;
136 
137  // Create a rectangle that lacks an explicit close.
138  flutter::DlPath path = flutter::DlPathBuilder{}
139  .LineTo({100, 0})
140  .LineTo({100, 100})
141  .LineTo({0, 100})
142  .TakePath();
144  1.0);
145 
146  std::vector<Point> expected = {
147  {0, 0}, {100, 0}, {100, 100}, {0, 100}, {0, 0}};
148  std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
149  EXPECT_EQ(points, expected);
150  EXPECT_EQ(indices, expected_indices);
151 }
152 
153 TEST(TessellatorTest, CircleVertexCounts) {
154  auto tessellator = std::make_shared<Tessellator>();
155 
156  auto test = [&tessellator](const Matrix& transform, Scalar radius) {
157  auto generator = tessellator->FilledCircle(transform, {}, radius);
158  size_t quadrant_divisions = generator.GetVertexCount() / 4;
159 
160  // Confirm the approximation error is within the currently accepted
161  // |kCircleTolerance| value advertised by |CircleTessellator|.
162  // (With an additional 1% tolerance for floating point rounding.)
163  double angle = kPiOver2 / quadrant_divisions;
164  Point first = {radius, 0};
165  Point next = {static_cast<Scalar>(cos(angle) * radius),
166  static_cast<Scalar>(sin(angle) * radius)};
167  Point midpoint = (first + next) * 0.5;
168  EXPECT_GE(midpoint.GetLength(),
169  radius - Tessellator::kCircleTolerance * 1.01)
170  << ", transform = " << transform << ", radius = " << radius
171  << ", divisions = " << quadrant_divisions;
172  };
173 
174  test({}, 0.0);
175  test({}, 0.9);
176  test({}, 1.0);
177  test({}, 1.9);
178  test(Matrix::MakeScale(Vector2(2.0, 2.0)), 0.95);
179  test({}, 2.0);
180  test(Matrix::MakeScale(Vector2(2.0, 2.0)), 1.0);
181  test({}, 11.9);
182  test({}, 12.0);
183  test({}, 35.9);
184  for (int i = 36; i < 10000; i += 4) {
185  test({}, i);
186  }
187 }
188 
189 TEST(TessellatorTest, FilledCircleTessellationVertices) {
190  auto tessellator = std::make_shared<Tessellator>();
191 
192  auto test = [&tessellator](const Matrix& transform, const Point& center,
193  Scalar radius) {
194  auto generator = tessellator->FilledCircle(transform, center, radius);
195  EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
196 
197  auto vertex_count = generator.GetVertexCount();
198  auto vertices = std::vector<Point>();
199  generator.GenerateVertices([&vertices](const Point& p) { //
200  vertices.push_back(p);
201  });
202  EXPECT_EQ(vertices.size(), vertex_count);
203  ASSERT_EQ(vertex_count % 4, 0u);
204 
205  auto quadrant_count = vertex_count / 4;
206  for (size_t i = 0; i < quadrant_count; i++) {
207  double angle = kPiOver2 * i / (quadrant_count - 1);
208  double degrees = angle * 180.0 / kPi;
209  double rsin = sin(angle) * radius;
210  // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
211  double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radius;
212  EXPECT_POINT_NEAR(vertices[i * 2],
213  Point(center.x - rcos, center.y + rsin))
214  << "vertex " << i << ", angle = " << degrees << std::endl;
215  EXPECT_POINT_NEAR(vertices[i * 2 + 1],
216  Point(center.x - rcos, center.y - rsin))
217  << "vertex " << i << ", angle = " << degrees << std::endl;
218  EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
219  Point(center.x + rcos, center.y - rsin))
220  << "vertex " << i << ", angle = " << degrees << std::endl;
221  EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
222  Point(center.x + rcos, center.y + rsin))
223  << "vertex " << i << ", angle = " << degrees << std::endl;
224  }
225  };
226 
227  test({}, {}, 2.0);
228  test({}, {10, 10}, 2.0);
229  test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0);
230  test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0);
231 }
232 
233 TEST(TessellatorTest, StrokedCircleTessellationVertices) {
234  auto tessellator = std::make_shared<Tessellator>();
235 
236  auto test = [&tessellator](const Matrix& transform, const Point& center,
237  Scalar radius, Scalar half_width) {
238  ASSERT_GT(radius, half_width);
239  auto generator =
240  tessellator->StrokedCircle(transform, center, radius, half_width);
241  EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
242 
243  auto vertex_count = generator.GetVertexCount();
244  auto vertices = std::vector<Point>();
245  generator.GenerateVertices([&vertices](const Point& p) { //
246  vertices.push_back(p);
247  });
248  EXPECT_EQ(vertices.size(), vertex_count);
249  ASSERT_EQ(vertex_count % 4, 0u);
250 
251  auto quadrant_count = vertex_count / 8;
252 
253  // Test outer points first
254  for (size_t i = 0; i < quadrant_count; i++) {
255  double angle = kPiOver2 * i / (quadrant_count - 1);
256  double degrees = angle * 180.0 / kPi;
257  double rsin = sin(angle) * (radius + half_width);
258  // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
259  double rcos =
260  (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius + half_width);
261  EXPECT_POINT_NEAR(vertices[i * 2],
262  Point(center.x - rcos, center.y - rsin))
263  << "vertex " << i << ", angle = " << degrees << std::endl;
264  EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2],
265  Point(center.x + rsin, center.y - rcos))
266  << "vertex " << i << ", angle = " << degrees << std::endl;
267  EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2],
268  Point(center.x + rcos, center.y + rsin))
269  << "vertex " << i << ", angle = " << degrees << std::endl;
270  EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2],
271  Point(center.x - rsin, center.y + rcos))
272  << "vertex " << i << ", angle = " << degrees << std::endl;
273  }
274 
275  // Then test innerer points
276  for (size_t i = 0; i < quadrant_count; i++) {
277  double angle = kPiOver2 * i / (quadrant_count - 1);
278  double degrees = angle * 180.0 / kPi;
279  double rsin = sin(angle) * (radius - half_width);
280  // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
281  double rcos =
282  (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius - half_width);
283  EXPECT_POINT_NEAR(vertices[i * 2 + 1],
284  Point(center.x - rcos, center.y - rsin))
285  << "vertex " << i << ", angle = " << degrees << std::endl;
286  EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2 + 1],
287  Point(center.x + rsin, center.y - rcos))
288  << "vertex " << i << ", angle = " << degrees << std::endl;
289  EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2 + 1],
290  Point(center.x + rcos, center.y + rsin))
291  << "vertex " << i << ", angle = " << degrees << std::endl;
292  EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2 + 1],
293  Point(center.x - rsin, center.y + rcos))
294  << "vertex " << i << ", angle = " << degrees << std::endl;
295  }
296  };
297 
298  test({}, {}, 2.0, 1.0);
299  test({}, {}, 2.0, 0.5);
300  test({}, {10, 10}, 2.0, 1.0);
301  test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0, 1.0);
302  test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0, 10.0);
303 }
304 
305 TEST(TessellatorTest, RoundCapLineTessellationVertices) {
306  auto tessellator = std::make_shared<Tessellator>();
307 
308  auto test = [&tessellator](const Matrix& transform, const Point& p0,
309  const Point& p1, Scalar radius) {
310  auto generator = tessellator->RoundCapLine(transform, p0, p1, radius);
311  EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
312 
313  auto vertex_count = generator.GetVertexCount();
314  auto vertices = std::vector<Point>();
315  generator.GenerateVertices([&vertices](const Point& p) { //
316  vertices.push_back(p);
317  });
318  EXPECT_EQ(vertices.size(), vertex_count);
319  ASSERT_EQ(vertex_count % 4, 0u);
320 
321  Point along = p1 - p0;
322  Scalar length = along.GetLength();
323  if (length > 0) {
324  along *= radius / length;
325  } else {
326  along = {radius, 0};
327  }
328  Point across = {-along.y, along.x};
329 
330  auto quadrant_count = vertex_count / 4;
331  for (size_t i = 0; i < quadrant_count; i++) {
332  double angle = kPiOver2 * i / (quadrant_count - 1);
333  double degrees = angle * 180.0 / kPi;
334  // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
335  Point relative_along =
336  along * ((i == quadrant_count - 1) ? 0.0f : cos(angle));
337  Point relative_across = across * sin(angle);
338  EXPECT_POINT_NEAR(vertices[i * 2], //
339  p0 - relative_along + relative_across)
340  << "vertex " << i << ", angle = " << degrees << ", " //
341  << "line = " << p0 << " => " << p1 << ", " //
342  << "radius = " << radius << std::endl;
343  EXPECT_POINT_NEAR(vertices[i * 2 + 1], //
344  p0 - relative_along - relative_across)
345  << "vertex " << i << ", angle = " << degrees << ", " //
346  << "line = " << p0 << " => " << p1 << ", " //
347  << "radius = " << radius << std::endl;
348  EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1], //
349  p1 + relative_along - relative_across)
350  << "vertex " << i << ", angle = " << degrees << ", " //
351  << "line = " << p0 << " => " << p1 << ", " //
352  << "radius = " << radius << std::endl;
353  EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2], //
354  p1 + relative_along + relative_across)
355  << "vertex " << i << ", angle = " << degrees << ", " //
356  << "line = " << p0 << " => " << p1 << ", " //
357  << "radius = " << radius << std::endl;
358  }
359  };
360 
361  // Empty line should actually use the circle generator, but its
362  // results should match the same math as the round cap generator.
363  test({}, {0, 0}, {0, 0}, 10);
364 
365  test({}, {0, 0}, {10, 0}, 2);
366  test({}, {10, 0}, {0, 0}, 2);
367  test({}, {0, 0}, {10, 10}, 2);
368 
369  test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 0}, 2);
370  test(Matrix::MakeScale({500.0, 500.0, 0.0}), {10, 0}, {0, 0}, 2);
371  test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 10}, 2);
372 
373  test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 0}, 2);
374  test(Matrix::MakeScale({0.002, 0.002, 0.0}), {10, 0}, {0, 0}, 2);
375  test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 10}, 2);
376 }
377 
378 TEST(TessellatorTest, FilledEllipseTessellationVertices) {
379  auto tessellator = std::make_shared<Tessellator>();
380 
381  auto test = [&tessellator](const Matrix& transform, const Rect& bounds) {
382  auto center = bounds.GetCenter();
383  auto half_size = bounds.GetSize() * 0.5f;
384 
385  auto generator = tessellator->FilledEllipse(transform, bounds);
386  EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
387 
388  auto vertex_count = generator.GetVertexCount();
389  auto vertices = std::vector<Point>();
390  generator.GenerateVertices([&vertices](const Point& p) { //
391  vertices.push_back(p);
392  });
393  EXPECT_EQ(vertices.size(), vertex_count);
394  ASSERT_EQ(vertex_count % 4, 0u);
395 
396  auto quadrant_count = vertex_count / 4;
397  for (size_t i = 0; i < quadrant_count; i++) {
398  double angle = kPiOver2 * i / (quadrant_count - 1);
399  double degrees = angle * 180.0 / kPi;
400  // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
401  double rcos =
402  (i == quadrant_count - 1) ? 0.0f : cos(angle) * half_size.width;
403  double rsin = sin(angle) * half_size.height;
404  EXPECT_POINT_NEAR(vertices[i * 2],
405  Point(center.x - rcos, center.y + rsin))
406  << "vertex " << i << ", angle = " << degrees << ", " //
407  << "bounds = " << bounds << std::endl;
408  EXPECT_POINT_NEAR(vertices[i * 2 + 1],
409  Point(center.x - rcos, center.y - rsin))
410  << "vertex " << i << ", angle = " << degrees << ", " //
411  << "bounds = " << bounds << std::endl;
412  EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
413  Point(center.x + rcos, center.y - rsin))
414  << "vertex " << i << ", angle = " << degrees << ", " //
415  << "bounds = " << bounds << std::endl;
416  EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
417  Point(center.x + rcos, center.y + rsin))
418  << "vertex " << i << ", angle = " << degrees << ", " //
419  << "bounds = " << bounds << std::endl;
420  }
421  };
422 
423  // Square bounds should actually use the circle generator, but its
424  // results should match the same math as the ellipse generator.
425  test({}, Rect::MakeXYWH(0, 0, 2, 2));
426 
427  test({}, Rect::MakeXYWH(0, 0, 2, 3));
428  test({}, Rect::MakeXYWH(0, 0, 3, 2));
429  test({}, Rect::MakeXYWH(5, 10, 2, 3));
430  test({}, Rect::MakeXYWH(16, 7, 3, 2));
431  test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 3, 2));
432  test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 2, 3));
433  test(Matrix::MakeScale({0.002, 0.002, 0.0}),
434  Rect::MakeXYWH(5000, 10000, 3000, 2000));
435  test(Matrix::MakeScale({0.002, 0.002, 0.0}),
436  Rect::MakeXYWH(5000, 10000, 2000, 3000));
437 }
438 
439 TEST(TessellatorTest, FilledRoundRectTessellationVertices) {
440  auto tessellator = std::make_shared<Tessellator>();
441 
442  auto test = [&tessellator](const Matrix& transform, const Rect& bounds,
443  const Size& radii) {
444  FML_DCHECK(radii.width * 2 <= bounds.GetWidth()) << radii << bounds;
445  FML_DCHECK(radii.height * 2 <= bounds.GetHeight()) << radii << bounds;
446 
447  Scalar middle_left = bounds.GetX() + radii.width;
448  Scalar middle_top = bounds.GetY() + radii.height;
449  Scalar middle_right = bounds.GetX() + bounds.GetWidth() - radii.width;
450  Scalar middle_bottom = bounds.GetY() + bounds.GetHeight() - radii.height;
451 
452  auto generator = tessellator->FilledRoundRect(transform, bounds, radii);
453  EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
454 
455  auto vertex_count = generator.GetVertexCount();
456  auto vertices = std::vector<Point>();
457  generator.GenerateVertices([&vertices](const Point& p) { //
458  vertices.push_back(p);
459  });
460  EXPECT_EQ(vertices.size(), vertex_count);
461  ASSERT_EQ(vertex_count % 4, 0u);
462 
463  auto quadrant_count = vertex_count / 4;
464  for (size_t i = 0; i < quadrant_count; i++) {
465  double angle = kPiOver2 * i / (quadrant_count - 1);
466  double degrees = angle * 180.0 / kPi;
467  // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
468  double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radii.width;
469  double rsin = sin(angle) * radii.height;
470  EXPECT_POINT_NEAR(vertices[i * 2],
471  Point(middle_left - rcos, middle_bottom + rsin))
472  << "vertex " << i << ", angle = " << degrees << ", " //
473  << "bounds = " << bounds << std::endl;
474  EXPECT_POINT_NEAR(vertices[i * 2 + 1],
475  Point(middle_left - rcos, middle_top - rsin))
476  << "vertex " << i << ", angle = " << degrees << ", " //
477  << "bounds = " << bounds << std::endl;
478  EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
479  Point(middle_right + rcos, middle_top - rsin))
480  << "vertex " << i << ", angle = " << degrees << ", " //
481  << "bounds = " << bounds << std::endl;
482  EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
483  Point(middle_right + rcos, middle_bottom + rsin))
484  << "vertex " << i << ", angle = " << degrees << ", " //
485  << "bounds = " << bounds << std::endl;
486  }
487  };
488 
489  // Both radii spanning the bounds should actually use the circle/ellipse
490  // generator, but their results should match the same math as the round
491  // rect generator.
492  test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 10});
493 
494  // One radius spanning the bounds, but not the other will not match the
495  // round rect math if the generator transfers to circle/ellipse
496  test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 5});
497  test({}, Rect::MakeXYWH(0, 0, 20, 20), {5, 10});
498 
499  test({}, Rect::MakeXYWH(0, 0, 20, 30), {2, 2});
500  test({}, Rect::MakeXYWH(0, 0, 30, 20), {2, 2});
501  test({}, Rect::MakeXYWH(5, 10, 20, 30), {2, 3});
502  test({}, Rect::MakeXYWH(16, 7, 30, 20), {2, 3});
503  test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 30, 20),
504  {2, 3});
505  test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 20, 30),
506  {2, 3});
507  test(Matrix::MakeScale({0.002, 0.002, 0.0}),
508  Rect::MakeXYWH(5000, 10000, 3000, 2000), {50, 70});
509  test(Matrix::MakeScale({0.002, 0.002, 0.0}),
510  Rect::MakeXYWH(5000, 10000, 2000, 3000), {50, 70});
511 }
512 
513 TEST(TessellatorTest, EarlyReturnEmptyConvexShape) {
514  // This path is not technically empty (it has a size in one dimension), but
515  // it contains only move commands and no actual path segment definitions.
516  flutter::DlPathBuilder builder;
517  builder.MoveTo({0, 0});
518  builder.MoveTo({10, 10});
519 
520  std::vector<Point> points;
521  std::vector<uint16_t> indices;
522  Tessellator::TessellateConvexInternal(builder.TakePath(), points, indices,
523  3.0f);
524 
525  EXPECT_TRUE(points.empty());
526  EXPECT_TRUE(indices.empty());
527 }
528 
529 } // namespace testing
530 } // namespace impeller
static constexpr Scalar kCircleTolerance
The pixel tolerance used by the algorighm to determine how many divisions to create for a circle.
Definition: tessellator.h:263
static void TessellateConvexInternal(const PathSource &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
Definition: tessellator.cc:399
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 EXPECT_POINT_NEAR(a, b)
TEST(AllocationSizeTest, CanCreateTypedAllocations)
Point Vector2
Definition: point.h:331
constexpr float kPi
Definition: constants.h:26
float Scalar
Definition: scalar.h:19
TPoint< Scalar > Point
Definition: point.h:327
constexpr float kPiOver2
Definition: constants.h:32
flutter::DlPath DlPath
Definition: dl_dispatcher.h:29
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:24
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
constexpr Type GetLength() const
Definition: point.h:206
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
std::vector< Point > points