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