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