Flutter Engine
The Flutter Engine
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
14namespace impeller {
15namespace testing {
16
17TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) {
18 // Zero points.
19 {
23 path, 1.0f,
24 [](const float* vertices, size_t vertices_count,
25 const uint16_t* indices, size_t indices_count) { return true; });
26
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
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
52 }
53
54 // Many points.
55 {
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
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
81 }
82}
83
84TEST(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;
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
121TEST(TessellatorTest, TessellateConvexUnclosedPath) {
122 std::vector<Point> points;
123 std::vector<uint16_t> indices;
124
125 // Create a rectangle that lacks an explicit close.
127 .LineTo({100, 0})
128 .LineTo({100, 100})
129 .LineTo({0, 100})
130 .TakePath();
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
139TEST(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
175TEST(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
219TEST(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
291TEST(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
364TEST(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
425TEST(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
499TEST(TessellatorTest, EarlyReturnEmptyConvexShape) {
500 // This path is not technically empty (it has a size in one dimension),
501 // but is otherwise completely flat.
503 builder.MoveTo({0, 0});
504 builder.MoveTo({10, 10}, /*relative=*/true);
505
506 std::vector<Point> points;
507 std::vector<uint16_t> indices;
509 3.0);
510
511 EXPECT_TRUE(points.empty());
512}
513
514#if !NDEBUG
515TEST(TessellatorTest, ChecksConcurrentPolylineUsage) {
516 auto tessellator = std::make_shared<Tessellator>();
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
#define test(name)
static const int points[]
static float next(float f)
PathBuilder & AddRect(Rect rect)
Path TakePath(FillType fill=FillType::kNonZero)
Definition: path_builder.cc:22
PathBuilder & LineTo(Point point, bool relative=false)
Insert a line from the current position to point.
Definition: path_builder.cc:52
PathBuilder & AddLine(const Point &p1, const Point &p2)
Move to point p1, then insert a line from p1 to p2.
An extended tessellator that offers arbitrary/concave tessellation via the libtess2 library.
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.
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
static void TessellateConvexInternal(const Path &path, std::vector< Point > &point_buffer, std::vector< uint16_t > &index_buffer, Scalar tolerance)
Definition: tessellator.cc:62
GAsyncResult * result
#define FML_DCHECK(condition)
Definition: logging.h:103
#define EXPECT_POINT_NEAR(a, b)
size_t length
Optional< SkRect > bounds
Definition: SkRecords.h:189
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
TEST(AiksCanvasTest, EmptyCullRect)
Point Vector2
Definition: point.h:326
constexpr float kPi
Definition: constants.h:26
float Scalar
Definition: scalar.h:18
TPoint< Scalar > Point
Definition: point.h:322
constexpr float kPiOver2
Definition: constants.h:32
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:24
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47
const Path::Polyline & polyline
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678