Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
shadow_path_geometry_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
9#include "gtest/gtest.h"
10
11#include "flutter/third_party/skia/src/core/SkVerticesPriv.h" // nogncheck
12#include "flutter/third_party/skia/src/utils/SkShadowTessellator.h" // nogncheck
13
14#define SHADOW_UNITTEST_SHOW_VERTICES false
15
16namespace impeller {
17namespace testing {
18
19using flutter::DlPath;
22using flutter::DlRect;
23
24namespace {
25
26#if SHADOW_UNITTEST_SHOW_VERTICES
27void ShowVertices(const std::string& label,
28 const std::shared_ptr<ShadowVertices>& shadow_vertices) {
29 auto vertices = shadow_vertices->GetVertices();
30 auto alphas = shadow_vertices->GetGaussians();
31 auto indices = shadow_vertices->GetIndices();
32 FML_LOG(ERROR) << label << "[" << indices.size() / 3 << "] = {";
33 for (size_t i = 0u; i < indices.size(); i += 3) {
34 // clang-format off
35 FML_LOG(ERROR)
36 << " (" << vertices[indices[i + 0]] << ", " << alphas[indices[i + 0]] << "), "
37 << " (" << vertices[indices[i + 1]] << ", " << alphas[indices[i + 1]] << "), "
38 << " (" << vertices[indices[i + 2]] << ", " << alphas[indices[i + 2]] << ")";
39 // clang-format on
40 }
41 FML_LOG(ERROR) << "} // " << label;
42}
43#endif
44
45constexpr Scalar kEpsilonSquared =
47
48bool SimilarPoint(Point p1, Point p2) {
49 return p1.GetDistanceSquared(p2) < kEpsilonSquared;
50}
51
52bool SimilarPointPair(std::array<Point, 2> pair1, std::array<Point, 2> pair2) {
53 if (SimilarPoint(pair1[1], pair2[1]) && SimilarPoint(pair1[2], pair2[2])) {
54 return true;
55 }
56 if (SimilarPoint(pair1[1], pair2[2]) && SimilarPoint(pair1[2], pair2[1])) {
57 return true;
58 }
59 return false;
60}
61
62bool SimilarPointTrio(std::array<Point, 3> trio1, std::array<Point, 3> trio2) {
63 if (SimilarPoint(trio1[1], trio2[1]) &&
64 SimilarPointPair({trio1[2], trio1[3]}, {trio2[2], trio2[3]})) {
65 return true;
66 }
67 if (SimilarPoint(trio1[1], trio2[2]) &&
68 SimilarPointPair({trio1[2], trio1[3]}, {trio2[1], trio2[3]})) {
69 return true;
70 }
71 if (SimilarPoint(trio1[1], trio2[3]) &&
72 SimilarPointPair({trio1[2], trio1[3]}, {trio2[1], trio2[2]})) {
73 return true;
74 }
75 return false;
76}
77
78size_t CountDuplicateVertices(
79 const std::shared_ptr<ShadowVertices>& shadow_vertices) {
80 size_t duplicate_vertices = 0u;
81 auto vertices = shadow_vertices->GetVertices();
82 size_t vertex_count = vertices.size();
83
84 for (size_t i = 1u; i < vertex_count; i++) {
85 Point& vertex = vertices[i];
86 for (size_t j = 0u; j < i; j++) {
87 if (SimilarPoint(vertex, vertices[j])) {
88 duplicate_vertices++;
89 }
90 }
91 }
92
93 return duplicate_vertices;
94}
95
96size_t CountDuplicateTriangles(
97 const std::shared_ptr<ShadowVertices>& shadow_vertices) {
98 size_t duplicate_triangles = 0u;
99 auto vertices = shadow_vertices->GetVertices();
100 auto indices = shadow_vertices->GetIndices();
101 size_t index_count = indices.size();
102
103 for (size_t i = 3u; i < index_count; i += 3) {
104 std::array trio1 = {
105 vertices[indices[i + 0]],
106 vertices[indices[i + 1]],
107 vertices[indices[i + 2]],
108 };
109 for (size_t j = 0; j < i; j += 3) {
110 std::array trio2 = {
111 vertices[indices[j + 0]],
112 vertices[indices[j + 1]],
113 vertices[indices[j + 2]],
114 };
115 if (SimilarPointTrio(trio1, trio2)) {
116 duplicate_triangles++;
117 }
118 }
119 }
120
121 return duplicate_triangles;
122}
123
124bool IsPointInsideTriangle(Point p, std::array<Point, 3> triangle) {
125 if (SimilarPoint(p, triangle[0]) || //
126 SimilarPoint(p, triangle[1]) || //
127 SimilarPoint(p, triangle[2])) {
128 return false;
129 }
130 Scalar direction = Point::Cross(p, triangle[0], triangle[1]);
131 // All 3 cross products must be non-zero and have the same sign.
132 return direction * Point::Cross(p, triangle[1], triangle[2]) > 0 &&
133 direction * Point::Cross(p, triangle[2], triangle[0]) > 0;
134};
135
136// This test verifies a condition that doesn't invalidate the process
137// per se, but we'd have to use overlap prevention to render the mesh
138// if this test returned true. We've carefully planned our meshes to
139// avoid that condition, though, so we're just making sure.
140bool DoTrianglesOverlap(
141 const std::shared_ptr<ShadowVertices>& shadow_vertices) {
142 auto vertices = shadow_vertices->GetVertices();
143 auto indices = shadow_vertices->GetIndices();
144 size_t index_count = indices.size();
145 size_t vertex_count = vertices.size();
146
147 for (size_t i = 0u; i < index_count; i += 3) {
148 std::array triangle = {
149 vertices[indices[i + 0]],
150 vertices[indices[i + 1]],
151 vertices[indices[i + 2]],
152 };
153 // Rather than check each pair of triangles to see if any of their
154 // vertices is inside the other, we just check the list of all vertices
155 // to see if that vertex is inside any triangle in the mesh.
156 for (size_t j = 0; j < vertex_count; j++) {
157 if (IsPointInsideTriangle(vertices[j], triangle)) {
158 FML_LOG(ERROR) << "Point " << vertices[j] << " inside triangle ["
159 << triangle[0] << ", " //
160 << triangle[1] << ", " //
161 << triangle[2] << "]";
162 FML_LOG(ERROR) << "Point - corner[0] == " << vertices[j] - triangle[0];
163 FML_LOG(ERROR) << "Point - corner[1] == " << vertices[j] - triangle[1];
164 FML_LOG(ERROR) << "Point - corner[2] == " << vertices[j] - triangle[2];
165 return true;
166 }
167 }
168 }
169
170 return false;
171}
172
173} // namespace
174
175TEST(ShadowPathGeometryTest, EmptyPathTest) {
176 DlPathBuilder path_builder;
177 const DlPath path = path_builder.TakePath();
178 const Matrix matrix;
179 const Scalar height = 10.0f;
180
181 Tessellator tessellator;
182 std::shared_ptr<ShadowVertices> shadow_vertices =
184 matrix);
185
186 ASSERT_NE(shadow_vertices, nullptr);
187 EXPECT_TRUE(shadow_vertices->IsEmpty());
188}
189
190TEST(ShadowPathGeometryTest, MoveToOnlyTest) {
191 DlPathBuilder path_builder;
192 path_builder.MoveTo(DlPoint(100, 100));
193 const DlPath path = path_builder.TakePath();
194 const Matrix matrix;
195 const Scalar height = 10.0f;
196
197 Tessellator tessellator;
198 std::shared_ptr<ShadowVertices> shadow_vertices =
200 matrix);
201
202 ASSERT_NE(shadow_vertices, nullptr);
203 EXPECT_TRUE(shadow_vertices->IsEmpty());
204}
205
206TEST(ShadowPathGeometryTest, OnePathSegmentTest) {
207 DlPathBuilder path_builder;
208 path_builder.MoveTo(DlPoint(100, 100));
209 path_builder.LineTo(DlPoint(200, 100));
210 const DlPath path = path_builder.TakePath();
211 const Matrix matrix;
212 const Scalar height = 10.0f;
213
214 Tessellator tessellator;
215 std::shared_ptr<ShadowVertices> shadow_vertices =
217 matrix);
218
219 ASSERT_NE(shadow_vertices, nullptr);
220 EXPECT_TRUE(shadow_vertices->IsEmpty());
221}
222
223TEST(ShadowPathGeometryTest, TwoColinearSegmentsTest) {
224 DlPathBuilder path_builder;
225 path_builder.MoveTo(DlPoint(100, 100));
226 path_builder.LineTo(DlPoint(200, 100));
227 path_builder.LineTo(DlPoint(300, 100));
228 const DlPath path = path_builder.TakePath();
229 const Matrix matrix;
230 const Scalar height = 10.0f;
231
232 Tessellator tessellator;
233 std::shared_ptr<ShadowVertices> shadow_vertices =
235 matrix);
236
237 ASSERT_NE(shadow_vertices, nullptr);
238 EXPECT_TRUE(shadow_vertices->IsEmpty());
239}
240
241TEST(ShadowPathGeometryTest, EmptyRectTest) {
242 DlPathBuilder path_builder;
243 path_builder.MoveTo(DlPoint(100, 100));
244 path_builder.LineTo(DlPoint(200, 100));
245 path_builder.LineTo(DlPoint(200, 100));
246 path_builder.LineTo(DlPoint(100, 100));
247 path_builder.Close();
248 const DlPath path = path_builder.TakePath();
249 const Matrix matrix;
250 const Scalar height = 10.0f;
251
252 Tessellator tessellator;
253 std::shared_ptr<ShadowVertices> shadow_vertices =
255 matrix);
256
257 ASSERT_NE(shadow_vertices, nullptr);
258 EXPECT_TRUE(shadow_vertices->IsEmpty());
259}
260
261TEST(ShadowPathGeometryTest, GetAndTakeVertices) {
262 DlPath path = DlPath::MakeRectLTRB(100, 100, 200, 200);
263 const Scalar height = 10.0f;
264
265 Tessellator tessellator;
266 ShadowPathGeometry geometry(tessellator, {}, path, height);
267
268 // Can call Get as many times as you want.
269 for (int i = 0; i < 10; i++) {
270 EXPECT_TRUE(geometry.GetShadowVertices());
271 }
272
273 // Can only call Take once.
274 EXPECT_TRUE(geometry.TakeShadowVertices());
275
276 // Further access wll then fail.
277 EXPECT_FALSE(geometry.GetShadowVertices());
278 EXPECT_FALSE(geometry.TakeShadowVertices());
279}
280
281TEST(ShadowPathGeometryTest, ClockwiseTriangleTest) {
282 DlPathBuilder path_builder;
283 path_builder.MoveTo(DlPoint(100, 0));
284 path_builder.LineTo(DlPoint(200, 110));
285 path_builder.LineTo(DlPoint(0, 110));
286 path_builder.Close();
287 const DlPath path = path_builder.TakePath();
288 const Matrix matrix;
289 const Scalar height = 10.0f;
290
291 Tessellator tessellator;
292 std::shared_ptr<ShadowVertices> shadow_vertices =
294 matrix);
295
296 ASSERT_NE(shadow_vertices, nullptr);
297 EXPECT_FALSE(shadow_vertices->IsEmpty());
298 EXPECT_EQ(shadow_vertices->GetVertexCount(), 33u);
299 EXPECT_EQ(shadow_vertices->GetIndexCount(), 102u);
300 EXPECT_EQ(shadow_vertices->GetVertices().size(), 33u);
301 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 33u);
302 EXPECT_EQ(shadow_vertices->GetIndices().size(), 102u);
303 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
304 // We repeat the first and last vertex that is on the outer umbra.
305 // There is another duplicate vertex from somewhere else not yet realized.
306 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 2u);
307 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
308 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
309
310#if SHADOW_UNITTEST_SHOW_VERTICES
311 ShowVertices("Impeller Vertices", shadow_vertices);
312#endif
313}
314
315TEST(ShadowPathGeometryTest, CounterClockwiseTriangleTest) {
316 DlPathBuilder path_builder;
317 path_builder.MoveTo(DlPoint(100, 0));
318 path_builder.LineTo(DlPoint(0, 110));
319 path_builder.LineTo(DlPoint(200, 110));
320 path_builder.Close();
321 const DlPath path = path_builder.TakePath();
322 const Matrix matrix;
323 const Scalar height = 10.0f;
324
325 Tessellator tessellator;
326 std::shared_ptr<ShadowVertices> shadow_vertices =
328 matrix);
329
330 ASSERT_NE(shadow_vertices, nullptr);
331 EXPECT_FALSE(shadow_vertices->IsEmpty());
332 EXPECT_EQ(shadow_vertices->GetVertexCount(), 33u);
333 EXPECT_EQ(shadow_vertices->GetIndexCount(), 102u);
334 EXPECT_EQ(shadow_vertices->GetVertices().size(), 33u);
335 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 33u);
336 EXPECT_EQ(shadow_vertices->GetIndices().size(), 102u);
337 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
338 // We repeat the first and last vertex that is on the outer umbra.
339 // There is another duplicate vertex from somewhere else not yet realized.
340 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 2u);
341 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
342 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
343
344#if SHADOW_UNITTEST_SHOW_VERTICES
345 ShowVertices("Impeller Vertices", shadow_vertices);
346#endif
347}
348
349TEST(ShadowPathGeometryTest, ClockwiseRectTest) {
350 DlPathBuilder path_builder;
351 path_builder.MoveTo(DlPoint(0, 0));
352 path_builder.LineTo(DlPoint(100, 0));
353 path_builder.LineTo(DlPoint(100, 80));
354 path_builder.LineTo(DlPoint(0, 80));
355 path_builder.Close();
356 const DlPath path = path_builder.TakePath();
357 const Matrix matrix;
358 const Scalar height = 10.0f;
359
360 Tessellator tessellator;
361 std::shared_ptr<ShadowVertices> shadow_vertices =
363 matrix);
364
365 ASSERT_NE(shadow_vertices, nullptr);
366 EXPECT_FALSE(shadow_vertices->IsEmpty());
367 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
368 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
369 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
370 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
371 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
372 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
373 // We repeat the first and last vertex that is on the outer umbra.
374 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
375 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
376 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
377
378#if SHADOW_UNITTEST_SHOW_VERTICES
379 ShowVertices("Impeller Vertices", shadow_vertices);
380#endif
381}
382
383TEST(ShadowPathGeometryTest, CounterClockwiseRectTest) {
384 DlPathBuilder path_builder;
385 path_builder.MoveTo(DlPoint(0, 0));
386 path_builder.LineTo(DlPoint(0, 80));
387 path_builder.LineTo(DlPoint(100, 80));
388 path_builder.LineTo(DlPoint(100, 0));
389 path_builder.Close();
390 DlPath path = path_builder.TakePath();
391 Matrix matrix;
392 const Scalar height = 10.0f;
393
394 Tessellator tessellator;
395 std::shared_ptr<ShadowVertices> shadow_vertices =
397 matrix);
398
399 ASSERT_NE(shadow_vertices, nullptr);
400 EXPECT_FALSE(shadow_vertices->IsEmpty());
401 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
402 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
403 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
404 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
405 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
406 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
407 // We repeat the first and last vertex that is on the outer umbra.
408 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
409 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
410 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
411
412#if SHADOW_UNITTEST_SHOW_VERTICES
413 ShowVertices("Impeller Vertices", shadow_vertices);
414#endif
415}
416
417TEST(ShadowPathGeometryTest, ClockwiseRectExtraColinearPointsTest) {
418 // This path includes a colinear point to each edge of the rectangle
419 // which should be trimmed out and ignored when generating the mesh
420 // resulting in the same number of vertices and triangles as the mesh
421 // above.
422 DlPathBuilder path_builder;
423 path_builder.MoveTo(DlPoint(0, 0));
424 path_builder.LineTo(DlPoint(50, 0));
425 path_builder.LineTo(DlPoint(100, 0));
426 path_builder.LineTo(DlPoint(100, 40));
427 path_builder.LineTo(DlPoint(100, 80));
428 path_builder.LineTo(DlPoint(50, 80));
429 path_builder.LineTo(DlPoint(0, 80));
430 path_builder.LineTo(DlPoint(0, 40));
431 path_builder.Close();
432 const DlPath path = path_builder.TakePath();
433 const Matrix matrix;
434 const Scalar height = 10.0f;
435
436 Tessellator tessellator;
437 std::shared_ptr<ShadowVertices> shadow_vertices =
439 matrix);
440
441 ASSERT_NE(shadow_vertices, nullptr);
442 EXPECT_FALSE(shadow_vertices->IsEmpty());
443 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
444 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
445 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
446 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
447 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
448 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
449 // We repeat the first and last vertex that is on the outer umbra.
450 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
451 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
452 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
453
454#if SHADOW_UNITTEST_SHOW_VERTICES
455 ShowVertices("Impeller Vertices", shadow_vertices);
456#endif
457}
458
459TEST(ShadowPathGeometryTest, CounterClockwiseRectExtraColinearPointsTest) {
460 // This path includes a colinear point to each edge of the rectangle
461 // which should be trimmed out and ignored when generating the mesh
462 // resulting in the same number of vertices and triangles as the mesh
463 // above.
464 DlPathBuilder path_builder;
465 path_builder.MoveTo(DlPoint(0, 0));
466 path_builder.LineTo(DlPoint(0, 40));
467 path_builder.LineTo(DlPoint(0, 80));
468 path_builder.LineTo(DlPoint(50, 80));
469 path_builder.LineTo(DlPoint(100, 80));
470 path_builder.LineTo(DlPoint(100, 40));
471 path_builder.LineTo(DlPoint(100, 0));
472 path_builder.LineTo(DlPoint(50, 0));
473 path_builder.Close();
474 DlPath path = path_builder.TakePath();
475 Matrix matrix;
476 const Scalar height = 10.0f;
477
478 Tessellator tessellator;
479 std::shared_ptr<ShadowVertices> shadow_vertices =
481 matrix);
482
483 ASSERT_NE(shadow_vertices, nullptr);
484 EXPECT_FALSE(shadow_vertices->IsEmpty());
485 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
486 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
487 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
488 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
489 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
490 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
491 // We repeat the first and last vertex that is on the outer umbra.
492 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
493 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
494 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
495
496#if SHADOW_UNITTEST_SHOW_VERTICES
497 ShowVertices("Impeller Vertices", shadow_vertices);
498#endif
499}
500
501TEST(ShadowPathGeometryTest, ClockwiseRectTrickyColinearPointsTest) {
502 // This path includes a colinear point added to each edge of the rectangle
503 // which seems to violate convexity, but is eliminated as not contributing
504 // to the path. We should be able to process the path anyway.
505 DlPathBuilder path_builder;
506 path_builder.MoveTo(DlPoint(0, 0));
507 path_builder.LineTo(DlPoint(-10, 0));
508 path_builder.LineTo(DlPoint(100, 0));
509 path_builder.LineTo(DlPoint(100, -10));
510 path_builder.LineTo(DlPoint(100, 80));
511 path_builder.LineTo(DlPoint(110, 80));
512 path_builder.LineTo(DlPoint(0, 80));
513 path_builder.LineTo(DlPoint(0, 90));
514 path_builder.Close();
515 const DlPath path = path_builder.TakePath();
516 const Matrix matrix;
517 const Scalar height = 10.0f;
518
519 Tessellator tessellator;
520 std::shared_ptr<ShadowVertices> shadow_vertices =
522 matrix);
523
524 ASSERT_NE(shadow_vertices, nullptr);
525 EXPECT_FALSE(shadow_vertices->IsEmpty());
526 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
527 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
528 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
529 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
530 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
531 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
532 // We repeat the first and last vertex that is on the outer umbra.
533 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
534 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
535 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
536
537#if SHADOW_UNITTEST_SHOW_VERTICES
538 ShowVertices("Impeller Vertices", shadow_vertices);
539#endif
540}
541
542TEST(ShadowPathGeometryTest, CounterClockwiseRectTrickyColinearPointsTest) {
543 // This path includes a colinear point added to each edge of the rectangle
544 // which seems to violate convexity, but is eliminated as not contributing
545 // to the path. We should be able to process the path anyway.
546 DlPathBuilder path_builder;
547 path_builder.MoveTo(DlPoint(0, 0));
548 path_builder.LineTo(DlPoint(0, -10));
549 path_builder.LineTo(DlPoint(0, 80));
550 path_builder.LineTo(DlPoint(-10, 80));
551 path_builder.LineTo(DlPoint(100, 80));
552 path_builder.LineTo(DlPoint(100, 90));
553 path_builder.LineTo(DlPoint(100, 0));
554 path_builder.LineTo(DlPoint(110, 0));
555 path_builder.Close();
556 DlPath path = path_builder.TakePath();
557 Matrix matrix;
558 const Scalar height = 10.0f;
559
560 Tessellator tessellator;
561 std::shared_ptr<ShadowVertices> shadow_vertices =
563 matrix);
564
565 ASSERT_NE(shadow_vertices, nullptr);
566 EXPECT_FALSE(shadow_vertices->IsEmpty());
567 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
568 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
569 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
570 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
571 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
572 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
573 // We repeat the first and last vertex that is on the outer umbra.
574 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
575 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
576 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
577
578#if SHADOW_UNITTEST_SHOW_VERTICES
579 ShowVertices("Impeller Vertices", shadow_vertices);
580#endif
581}
582
583TEST(ShadowPathGeometryTest, ClockwiseRectTrickyDupColinearPointsTest) {
584 // This path includes a colinear point added to each edge of the rectangle
585 // which seems to violate convexity, but is eliminated as not contributing
586 // to the path. We should be able to process the path anyway.
587 // It also includes multiple collinear points on the first and last points
588 // that end up back where we started to make sure that in that case we
589 // eliminate all of the collinear points and the duplicate, rather than
590 // just the intermediate collinear points.
591 DlPathBuilder path_builder;
592 path_builder.MoveTo(DlPoint(0, 0));
593 path_builder.LineTo(DlPoint(-10, 0));
594 path_builder.LineTo(DlPoint(0, 0));
595 path_builder.LineTo(DlPoint(100, 0));
596 path_builder.LineTo(DlPoint(100, -10));
597 path_builder.LineTo(DlPoint(100, 80));
598 path_builder.LineTo(DlPoint(110, 80));
599 path_builder.LineTo(DlPoint(0, 80));
600 path_builder.LineTo(DlPoint(0, 90));
601 path_builder.LineTo(DlPoint(0, 80));
602 path_builder.Close();
603 const DlPath path = path_builder.TakePath();
604 const Matrix matrix;
605 const Scalar height = 10.0f;
606
607 Tessellator tessellator;
608 std::shared_ptr<ShadowVertices> shadow_vertices =
610 matrix);
611
612 ASSERT_NE(shadow_vertices, nullptr);
613 EXPECT_FALSE(shadow_vertices->IsEmpty());
614 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
615 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
616 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
617 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
618 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
619 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
620 // We repeat the first and last vertex that is on the outer umbra.
621 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
622 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
623 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
624
625#if SHADOW_UNITTEST_SHOW_VERTICES
626 ShowVertices("Impeller Vertices", shadow_vertices);
627#endif
628}
629
630TEST(ShadowPathGeometryTest, CounterClockwiseRectTrickyDupColinearPointsTest) {
631 // This path includes a colinear point added to each edge of the rectangle
632 // which seems to violate convexity, but is eliminated as not contributing
633 // to the path. We should be able to process the path anyway.
634 // It also includes multiple collinear points on the first and last points
635 // that end up back where we started to make sure that in that case we
636 // eliminate all of the collinear points and the duplicate, rather than
637 // just the intermediate collinear points.
638 DlPathBuilder path_builder;
639 path_builder.MoveTo(DlPoint(0, 0));
640 path_builder.LineTo(DlPoint(0, -10));
641 path_builder.LineTo(DlPoint(0, 0));
642 path_builder.LineTo(DlPoint(0, 80));
643 path_builder.LineTo(DlPoint(-10, 80));
644 path_builder.LineTo(DlPoint(100, 80));
645 path_builder.LineTo(DlPoint(100, 90));
646 path_builder.LineTo(DlPoint(100, 0));
647 path_builder.LineTo(DlPoint(110, 0));
648 path_builder.LineTo(DlPoint(100, 0));
649 path_builder.Close();
650 DlPath path = path_builder.TakePath();
651 Matrix matrix;
652 const Scalar height = 10.0f;
653
654 Tessellator tessellator;
655 std::shared_ptr<ShadowVertices> shadow_vertices =
657 matrix);
658
659 ASSERT_NE(shadow_vertices, nullptr);
660 EXPECT_FALSE(shadow_vertices->IsEmpty());
661 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
662 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
663 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
664 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
665 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
666 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
667 // We repeat the first and last vertex that is on the outer umbra.
668 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
669 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
670 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
671
672#if SHADOW_UNITTEST_SHOW_VERTICES
673 ShowVertices("Impeller Vertices", shadow_vertices);
674#endif
675}
676
677TEST(ShadowPathGeometryTest, ClockwiseRectNearlyColinearPointsTest) {
678 // This path includes a bunch of colinear points and one point that
679 // is barely non-colinear but still convex. It should add exactly
680 // one extra set of vertices to the mesh (3 points and 3 triangles)
681 // compared to the regular rects.
682 DlPathBuilder path_builder;
683 path_builder.MoveTo(DlPoint(0, 0));
684 path_builder.LineTo(DlPoint(50, -0.065));
685 path_builder.LineTo(DlPoint(100, 0));
686 path_builder.LineTo(DlPoint(100, 40));
687 path_builder.LineTo(DlPoint(100, 80));
688 path_builder.LineTo(DlPoint(50, 80));
689 path_builder.LineTo(DlPoint(0, 80));
690 path_builder.LineTo(DlPoint(0, 40));
691 path_builder.Close();
692 const DlPath path = path_builder.TakePath();
693 const Matrix matrix;
694 const Scalar height = 10.0f;
695
696 Tessellator tessellator;
697 std::shared_ptr<ShadowVertices> shadow_vertices =
699 matrix);
700
701 ASSERT_NE(shadow_vertices, nullptr);
702 EXPECT_FALSE(shadow_vertices->IsEmpty());
703 EXPECT_EQ(shadow_vertices->GetVertexCount(), 37u);
704 EXPECT_EQ(shadow_vertices->GetIndexCount(), 120u);
705 EXPECT_EQ(shadow_vertices->GetVertices().size(), 37u);
706 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 37u);
707 EXPECT_EQ(shadow_vertices->GetIndices().size(), 120u);
708 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
709 // We repeat the first and last vertex that is on the outer umbra.
710 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
711 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
712 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
713
714#if SHADOW_UNITTEST_SHOW_VERTICES
715 ShowVertices("Impeller Vertices", shadow_vertices);
716#endif
717}
718
719TEST(ShadowPathGeometryTest, CounterClockwiseRectNearlyColinearPointsTest) {
720 // This path includes a bunch of colinear points and one point that
721 // is barely non-colinear but still convex. It should add exactly
722 // one extra set of vertices to the mesh (3 points and 3 triangles)
723 // compared to the regular rects.
724 DlPathBuilder path_builder;
725 path_builder.MoveTo(DlPoint(0, 0));
726 path_builder.LineTo(DlPoint(-0.065, 40));
727 path_builder.LineTo(DlPoint(0, 80));
728 path_builder.LineTo(DlPoint(50, 80));
729 path_builder.LineTo(DlPoint(100, 80));
730 path_builder.LineTo(DlPoint(100, 40));
731 path_builder.LineTo(DlPoint(100, 0));
732 path_builder.LineTo(DlPoint(50, 0));
733 path_builder.Close();
734 DlPath path = path_builder.TakePath();
735 Matrix matrix;
736 const Scalar height = 10.0f;
737
738 Tessellator tessellator;
739 std::shared_ptr<ShadowVertices> shadow_vertices =
741 matrix);
742
743 ASSERT_NE(shadow_vertices, nullptr);
744 EXPECT_FALSE(shadow_vertices->IsEmpty());
745 EXPECT_EQ(shadow_vertices->GetVertexCount(), 37u);
746 EXPECT_EQ(shadow_vertices->GetIndexCount(), 120u);
747 EXPECT_EQ(shadow_vertices->GetVertices().size(), 37u);
748 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 37u);
749 EXPECT_EQ(shadow_vertices->GetIndices().size(), 120u);
750 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
751 // We repeat the first and last vertex that is on the outer umbra.
752 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
753 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
754 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
755
756#if SHADOW_UNITTEST_SHOW_VERTICES
757 ShowVertices("Impeller Vertices", shadow_vertices);
758#endif
759}
760
761TEST(ShadowPathGeometryTest, ScaledRectTest) {
762 Tessellator tessellator;
764 Matrix matrix = Matrix::MakeScale({2, 3, 1});
765 const Scalar height = 10.0f;
766
767 std::shared_ptr<ShadowVertices> shadow_vertices =
769 matrix);
770
771 ASSERT_NE(shadow_vertices, nullptr);
772 EXPECT_FALSE(shadow_vertices->IsEmpty());
773 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
774 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
775 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
776 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
777 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
778 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
779 // We repeat the first and last vertex that is on the outer umbra.
780 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
781 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
782 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
783
784#if SHADOW_UNITTEST_SHOW_VERTICES
785 ShowVertices("Impeller Vertices", shadow_vertices);
786#endif
787}
788
789TEST(ShadowPathGeometryTest, EllipseTest) {
790 Tessellator tessellator;
792 Matrix matrix;
793 const Scalar height = 10.0f;
794
795 std::shared_ptr<ShadowVertices> shadow_vertices =
797 matrix);
798
799 ASSERT_NE(shadow_vertices, nullptr);
800 EXPECT_FALSE(shadow_vertices->IsEmpty());
801 EXPECT_EQ(shadow_vertices->GetVertexCount(), 122u);
802 EXPECT_EQ(shadow_vertices->GetIndexCount(), 480u);
803 EXPECT_EQ(shadow_vertices->GetVertices().size(), 122u);
804 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 122u);
805 EXPECT_EQ(shadow_vertices->GetIndices().size(), 480u);
806 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
807 // We repeat the first and last vertex that is on the outer umbra.
808 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
809 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
810 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
811}
812
813TEST(ShadowPathGeometryTest, RoundRectTest) {
814 Tessellator tessellator;
815 DlPath path = DlPath::MakeRoundRectXY(DlRect::MakeLTRB(0, 0, 100, 80), 5, 4);
816 Matrix matrix;
817 const Scalar height = 10.0f;
818
819 std::shared_ptr<ShadowVertices> shadow_vertices =
821 matrix);
822
823 ASSERT_NE(shadow_vertices, nullptr);
824 EXPECT_FALSE(shadow_vertices->IsEmpty());
825 EXPECT_EQ(shadow_vertices->GetVertexCount(), 55u);
826 EXPECT_EQ(shadow_vertices->GetIndexCount(), 168u);
827 EXPECT_EQ(shadow_vertices->GetVertices().size(), 55u);
828 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 55u);
829 EXPECT_EQ(shadow_vertices->GetIndices().size(), 168u);
830 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
831 // We repeat the first and last vertex that is on the outer umbra.
832 // There is another duplicate vertex from somewhere else not yet realized.
833 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 2u);
834 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
835 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
836}
837
838TEST(ShadowPathGeometryTest, HourglassSelfIntersectingTest) {
839 DlPathBuilder path_builder;
840 path_builder.MoveTo(DlPoint(0, 0));
841 path_builder.LineTo(DlPoint(100, 80));
842 path_builder.LineTo(DlPoint(100, 0));
843 path_builder.LineTo(DlPoint(0, 80));
844 path_builder.Close();
845 const DlPath path = path_builder.TakePath();
846 const Matrix matrix;
847 const Scalar height = 10.0f;
848
849 Tessellator tessellator;
850 std::shared_ptr<ShadowVertices> shadow_vertices =
852 matrix);
853
854 EXPECT_EQ(shadow_vertices, nullptr);
855}
856
857TEST(ShadowPathGeometryTest, ReverseHourglassSelfIntersectingTest) {
858 DlPathBuilder path_builder;
859 path_builder.MoveTo(DlPoint(0, 0));
860 path_builder.LineTo(DlPoint(100, 80));
861 path_builder.LineTo(DlPoint(0, 80));
862 path_builder.LineTo(DlPoint(100, 0));
863 path_builder.Close();
864 const DlPath path = path_builder.TakePath();
865 const Matrix matrix;
866 const Scalar height = 10.0f;
867
868 Tessellator tessellator;
869 std::shared_ptr<ShadowVertices> shadow_vertices =
871 matrix);
872
873 EXPECT_EQ(shadow_vertices, nullptr);
874}
875
876TEST(ShadowPathGeometryTest, InnerToOuterOverturningSpiralTest) {
877 const Matrix matrix;
878 const Scalar height = 10.0f;
879 int step_count = 20;
880
881 DlPathBuilder path_builder;
882 path_builder.MoveTo(DlPoint(300, 200));
883 for (int i = 1; i < step_count * 2; i++) {
884 Scalar angle = (k2Pi * i) / step_count;
885 Scalar radius = 80.0f + std::abs(i - step_count);
886 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
887 std::sin(angle) * radius));
888 }
889 path_builder.Close();
890 DlPath path = path_builder.TakePath();
891
892 Tessellator tessellator;
893 std::shared_ptr<ShadowVertices> shadow_vertices =
895 matrix);
896
897 EXPECT_EQ(shadow_vertices, nullptr);
898}
899
900TEST(ShadowPathGeometryTest, ReverseInnerToOuterOverturningSpiralTest) {
901 const Matrix matrix;
902 const Scalar height = 10.0f;
903 int step_count = 20;
904
905 DlPathBuilder path_builder;
906 path_builder.MoveTo(DlPoint(300, 200));
907 for (int i = 1; i < step_count * 2; i++) {
908 Scalar angle = -(k2Pi * i) / step_count;
909 Scalar radius = 80.0f + std::abs(i - step_count);
910 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
911 std::sin(angle) * radius));
912 }
913 path_builder.Close();
914 DlPath path = path_builder.TakePath();
915
916 Tessellator tessellator;
917 std::shared_ptr<ShadowVertices> shadow_vertices =
919 matrix);
920
921 EXPECT_EQ(shadow_vertices, nullptr);
922}
923
924TEST(ShadowPathGeometryTest, OuterToInnerOverturningSpiralTest) {
925 const Matrix matrix;
926 const Scalar height = 10.0f;
927 int step_count = 20;
928
929 DlPathBuilder path_builder;
930 path_builder.MoveTo(DlPoint(280, 200));
931 for (int i = 1; i < step_count * 2; i++) {
932 Scalar angle = (k2Pi * i) / step_count;
933 Scalar radius = 100.0f - std::abs(i - step_count);
934 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
935 std::sin(angle) * radius));
936 }
937 path_builder.Close();
938 DlPath path = path_builder.TakePath();
939
940 Tessellator tessellator;
941 std::shared_ptr<ShadowVertices> shadow_vertices =
943 matrix);
944
945 EXPECT_EQ(shadow_vertices, nullptr);
946}
947
948TEST(ShadowPathGeometryTest, ReverseOuterToInnerOverturningSpiralTest) {
949 const Matrix matrix;
950 const Scalar height = 10.0f;
951 int step_count = 20;
952
953 DlPathBuilder path_builder;
954 path_builder.MoveTo(DlPoint(280, 200));
955 for (int i = 1; i < step_count * 2; i++) {
956 Scalar angle = -(k2Pi * i) / step_count;
957 Scalar radius = 100.0f - std::abs(i - step_count);
958 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
959 std::sin(angle) * radius));
960 }
961 path_builder.Close();
962 DlPath path = path_builder.TakePath();
963
964 Tessellator tessellator;
965 std::shared_ptr<ShadowVertices> shadow_vertices =
967 matrix);
968
969 EXPECT_EQ(shadow_vertices, nullptr);
970}
971
972TEST(ShadowPathGeometryTest, ClockwiseOctagonCollapsedUmbraPolygonTest) {
973 const Matrix matrix = Matrix::MakeScale({2, 2, 1});
974 const Scalar height = 100.0f;
975
976 DlPathBuilder path_builder;
977 path_builder.MoveTo(DlPoint(100, 125));
978 path_builder.LineTo(DlPoint(125, 100));
979 path_builder.LineTo(DlPoint(275, 100));
980 path_builder.LineTo(DlPoint(300, 125));
981 path_builder.LineTo(DlPoint(300, 275));
982 path_builder.LineTo(DlPoint(275, 300));
983 path_builder.LineTo(DlPoint(125, 300));
984 path_builder.LineTo(DlPoint(100, 275));
985 path_builder.Close();
986 DlPath path = path_builder.TakePath();
987
988 Tessellator tessellator;
989 std::shared_ptr<ShadowVertices> shadow_vertices =
991 matrix);
992
993 ASSERT_NE(shadow_vertices, nullptr);
994 EXPECT_FALSE(shadow_vertices->IsEmpty());
995 EXPECT_EQ(shadow_vertices->GetVertexCount(), 87u);
996 EXPECT_EQ(shadow_vertices->GetIndexCount(), 267u);
997 EXPECT_EQ(shadow_vertices->GetVertices().size(), 87u);
998 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 87u);
999 EXPECT_EQ(shadow_vertices->GetIndices().size(), 267u);
1000 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
1001 // We repeat the first and last vertex that is on the outer umbra.
1002 // There are a couple additional duplicate vertices in this case.
1003 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 3u);
1004 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
1005 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
1006}
1007
1008TEST(ShadowPathGeometryTest, CounterClockwiseOctagonCollapsedUmbraPolygonTest) {
1009 const Matrix matrix = Matrix::MakeScale({2, 2, 1});
1010 const Scalar height = 100.0f;
1011
1012 DlPathBuilder path_builder;
1013 path_builder.MoveTo(DlPoint(100, 125));
1014 path_builder.LineTo(DlPoint(100, 275));
1015 path_builder.LineTo(DlPoint(125, 300));
1016 path_builder.LineTo(DlPoint(275, 300));
1017 path_builder.LineTo(DlPoint(300, 275));
1018 path_builder.LineTo(DlPoint(300, 125));
1019 path_builder.LineTo(DlPoint(275, 100));
1020 path_builder.LineTo(DlPoint(125, 100));
1021 path_builder.Close();
1022 DlPath path = path_builder.TakePath();
1023
1024 Tessellator tessellator;
1025 std::shared_ptr<ShadowVertices> shadow_vertices =
1027 matrix);
1028
1029 ASSERT_NE(shadow_vertices, nullptr);
1030 EXPECT_FALSE(shadow_vertices->IsEmpty());
1031 EXPECT_EQ(shadow_vertices->GetVertexCount(), 88u);
1032 EXPECT_EQ(shadow_vertices->GetIndexCount(), 267u);
1033 EXPECT_EQ(shadow_vertices->GetVertices().size(), 88u);
1034 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 88u);
1035 EXPECT_EQ(shadow_vertices->GetIndices().size(), 267u);
1036 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
1037 // We repeat the first and last vertex that is on the outer umbra.
1038 // There are a couple additional duplicate vertices in this case.
1039 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 3u);
1040 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
1041 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
1042}
1043
1044TEST(ShadowPathGeometryTest, MultipleContoursTest) {
1045 const Matrix matrix;
1046 const Scalar height = 10.0f;
1047
1048 DlPathBuilder path_builder;
1049 path_builder.MoveTo(DlPoint(150, 100));
1050 path_builder.LineTo(DlPoint(200, 300));
1051 path_builder.LineTo(DlPoint(100, 300));
1052 path_builder.Close();
1053 path_builder.MoveTo(DlPoint(250, 100));
1054 path_builder.LineTo(DlPoint(300, 300));
1055 path_builder.LineTo(DlPoint(200, 300));
1056 path_builder.Close();
1057 DlPath path = path_builder.TakePath();
1058
1059 Tessellator tessellator;
1060 std::shared_ptr<ShadowVertices> shadow_vertices =
1062 matrix);
1063
1064 EXPECT_EQ(shadow_vertices, nullptr);
1065}
1066
1067} // namespace testing
1068} // 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.
const DlPath TakePath()
Returns the path constructed by this path builder and resets its internal state to the default state ...
DlPathBuilder & Close()
The path is closed back to the location of the most recent MoveTo call. Contours that are filled are ...
static DlPath MakeRectLTRB(DlScalar left, DlScalar top, DlScalar right, DlScalar bottom)
Definition dl_path.cc:43
static DlPath MakeRect(const DlRect &rect)
Definition dl_path.cc:39
static DlPath MakeRoundRectXY(const DlRect &rect, DlScalar x_radius, DlScalar y_radius, bool counter_clock_wise=false)
Definition dl_path.cc:76
static DlPath MakeOval(const DlRect &bounds)
Definition dl_path.cc:57
static std::shared_ptr< ShadowVertices > MakeAmbientShadowVertices(Tessellator &tessellator, const PathSource &source, Scalar occluder_height, const Matrix &matrix)
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
Definition tessellator.h:37
#define FML_LOG(severity)
Definition logging.h:101
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 kEhCloseEnough
impeller::Point DlPoint
constexpr float k2Pi
Definition constants.h:29
float Scalar
Definition scalar.h:19
int32_t height
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
constexpr Type Cross(const TPoint &p) const
Definition point.h:295
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129