| 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 "impeller/geometry/geometry_asserts.h"
9 #include "impeller/geometry/path.h"
10 #include "impeller/geometry/path_builder.h"
11 #include "impeller/tessellator/tessellator.h"
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);
21 Tessellator::Result result = t.Tessellate(
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);
33 Tessellator::Result result = t.Tessellate(
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);
45 Tessellator::Result result = t.Tessellate(
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);
62 Tessellator::Result result = t.Tessellate(
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);
74 Tessellator::Result result = t.Tessellate(
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;
92 Tessellator::Result result = t.Tessellate(
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