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