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