7 #include "flutter/display_list/geometry/dl_path.h"
8 #include "flutter/display_list/geometry/dl_path_builder.h"
9 #include "gtest/gtest.h"
11 #include "flutter/third_party/skia/src/core/SkVerticesPriv.h"
12 #include "flutter/third_party/skia/src/utils/SkShadowTessellator.h"
14 #define SHADOW_UNITTEST_SHOW_VERTICES false
20 using flutter::DlPathBuilder;
26 #if SHADOW_UNITTEST_SHOW_VERTICES
27 void 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) {
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]] <<
")";
41 FML_LOG(ERROR) <<
"} // " << label;
45 constexpr
Scalar kEpsilonSquared =
49 return p1.GetDistanceSquared(p2) < kEpsilonSquared;
52 bool SimilarPointPair(std::array<Point, 2> pair1, std::array<Point, 2> pair2) {
53 if (SimilarPoint(pair1[1], pair2[1]) && SimilarPoint(pair1[2], pair2[2])) {
56 if (SimilarPoint(pair1[1], pair2[2]) && SimilarPoint(pair1[2], pair2[1])) {
62 bool 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]})) {
67 if (SimilarPoint(trio1[1], trio2[2]) &&
68 SimilarPointPair({trio1[2], trio1[3]}, {trio2[1], trio2[3]})) {
71 if (SimilarPoint(trio1[1], trio2[3]) &&
72 SimilarPointPair({trio1[2], trio1[3]}, {trio2[1], trio2[2]})) {
78 size_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();
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])) {
93 return duplicate_vertices;
96 size_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();
103 for (
size_t i = 3u; i < index_count; i += 3) {
105 vertices[indices[i + 0]],
106 vertices[indices[i + 1]],
107 vertices[indices[i + 2]],
109 for (
size_t j = 0; j < i; j += 3) {
111 vertices[indices[j + 0]],
112 vertices[indices[j + 1]],
113 vertices[indices[j + 2]],
115 if (SimilarPointTrio(trio1, trio2)) {
116 duplicate_triangles++;
121 return duplicate_triangles;
124 bool IsPointInsideTriangle(
Point p, std::array<Point, 3> triangle) {
125 if (SimilarPoint(p, triangle[0]) ||
126 SimilarPoint(p, triangle[1]) ||
127 SimilarPoint(p, triangle[2])) {
132 return direction *
Point::Cross(p, triangle[1], triangle[2]) > 0 &&
133 direction *
Point::Cross(p, triangle[2], triangle[0]) > 0;
140 bool 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();
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]],
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];
175 TEST(ShadowPathGeometryTest, EmptyPathTest) {
176 DlPathBuilder path_builder;
177 const DlPath path = path_builder.TakePath();
179 const Scalar height = 10.0f;
182 std::shared_ptr<ShadowVertices> shadow_vertices =
186 ASSERT_NE(shadow_vertices,
nullptr);
187 EXPECT_TRUE(shadow_vertices->IsEmpty());
190 TEST(ShadowPathGeometryTest, MoveToOnlyTest) {
191 DlPathBuilder path_builder;
192 path_builder.MoveTo(
DlPoint(100, 100));
193 const DlPath path = path_builder.TakePath();
195 const Scalar height = 10.0f;
198 std::shared_ptr<ShadowVertices> shadow_vertices =
202 ASSERT_NE(shadow_vertices,
nullptr);
203 EXPECT_TRUE(shadow_vertices->IsEmpty());
206 TEST(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();
212 const Scalar height = 10.0f;
215 std::shared_ptr<ShadowVertices> shadow_vertices =
219 ASSERT_NE(shadow_vertices,
nullptr);
220 EXPECT_TRUE(shadow_vertices->IsEmpty());
223 TEST(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();
230 const Scalar height = 10.0f;
233 std::shared_ptr<ShadowVertices> shadow_vertices =
237 ASSERT_NE(shadow_vertices,
nullptr);
238 EXPECT_TRUE(shadow_vertices->IsEmpty());
241 TEST(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();
250 const Scalar height = 10.0f;
253 std::shared_ptr<ShadowVertices> shadow_vertices =
257 ASSERT_NE(shadow_vertices,
nullptr);
258 EXPECT_TRUE(shadow_vertices->IsEmpty());
261 TEST(ShadowPathGeometryTest, GetAndTakeVertices) {
262 DlPath path = DlPath::MakeRectLTRB(100, 100, 200, 200);
263 const Scalar height = 10.0f;
269 for (
int i = 0; i < 10; i++) {
270 EXPECT_TRUE(geometry.GetShadowVertices());
274 EXPECT_TRUE(geometry.TakeShadowVertices());
277 EXPECT_FALSE(geometry.GetShadowVertices());
278 EXPECT_FALSE(geometry.TakeShadowVertices());
281 TEST(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();
289 const Scalar height = 10.0f;
292 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
306 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 2u);
307 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
308 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
310 #if SHADOW_UNITTEST_SHOW_VERTICES
311 ShowVertices(
"Impeller Vertices", shadow_vertices);
315 TEST(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();
323 const Scalar height = 10.0f;
326 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
340 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 2u);
341 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
342 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
344 #if SHADOW_UNITTEST_SHOW_VERTICES
345 ShowVertices(
"Impeller Vertices", shadow_vertices);
349 TEST(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();
358 const Scalar height = 10.0f;
361 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
374 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
375 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
376 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
378 #if SHADOW_UNITTEST_SHOW_VERTICES
379 ShowVertices(
"Impeller Vertices", shadow_vertices);
383 TEST(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();
392 const Scalar height = 10.0f;
395 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
408 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
409 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
410 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
412 #if SHADOW_UNITTEST_SHOW_VERTICES
413 ShowVertices(
"Impeller Vertices", shadow_vertices);
417 TEST(ShadowPathGeometryTest, ClockwiseRectExtraColinearPointsTest) {
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();
434 const Scalar height = 10.0f;
437 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
450 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
451 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
452 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
454 #if SHADOW_UNITTEST_SHOW_VERTICES
455 ShowVertices(
"Impeller Vertices", shadow_vertices);
459 TEST(ShadowPathGeometryTest, CounterClockwiseRectExtraColinearPointsTest) {
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();
476 const Scalar height = 10.0f;
479 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
492 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
493 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
494 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
496 #if SHADOW_UNITTEST_SHOW_VERTICES
497 ShowVertices(
"Impeller Vertices", shadow_vertices);
501 TEST(ShadowPathGeometryTest, ClockwiseRectTrickyColinearPointsTest) {
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();
517 const Scalar height = 10.0f;
520 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
533 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
534 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
535 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
537 #if SHADOW_UNITTEST_SHOW_VERTICES
538 ShowVertices(
"Impeller Vertices", shadow_vertices);
542 TEST(ShadowPathGeometryTest, CounterClockwiseRectTrickyColinearPointsTest) {
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();
558 const Scalar height = 10.0f;
561 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
574 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
575 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
576 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
578 #if SHADOW_UNITTEST_SHOW_VERTICES
579 ShowVertices(
"Impeller Vertices", shadow_vertices);
583 TEST(ShadowPathGeometryTest, ClockwiseRectTrickyDupColinearPointsTest) {
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();
605 const Scalar height = 10.0f;
608 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
621 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
622 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
623 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
625 #if SHADOW_UNITTEST_SHOW_VERTICES
626 ShowVertices(
"Impeller Vertices", shadow_vertices);
630 TEST(ShadowPathGeometryTest, CounterClockwiseRectTrickyDupColinearPointsTest) {
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();
652 const Scalar height = 10.0f;
655 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
668 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
669 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
670 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
672 #if SHADOW_UNITTEST_SHOW_VERTICES
673 ShowVertices(
"Impeller Vertices", shadow_vertices);
677 TEST(ShadowPathGeometryTest, ClockwiseRectNearlyColinearPointsTest) {
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();
694 const Scalar height = 10.0f;
697 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
710 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
711 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
712 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
714 #if SHADOW_UNITTEST_SHOW_VERTICES
715 ShowVertices(
"Impeller Vertices", shadow_vertices);
719 TEST(ShadowPathGeometryTest, CounterClockwiseRectNearlyColinearPointsTest) {
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();
736 const Scalar height = 10.0f;
739 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
752 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
753 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
754 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
756 #if SHADOW_UNITTEST_SHOW_VERTICES
757 ShowVertices(
"Impeller Vertices", shadow_vertices);
761 TEST(ShadowPathGeometryTest, ScaledRectTest) {
763 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 100, 80));
765 const Scalar height = 10.0f;
767 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
780 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
781 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
782 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
784 #if SHADOW_UNITTEST_SHOW_VERTICES
785 ShowVertices(
"Impeller Vertices", shadow_vertices);
789 TEST(ShadowPathGeometryTest, EllipseTest) {
791 DlPath path = DlPath::MakeOval(DlRect::MakeLTRB(0, 0, 100, 80));
793 const Scalar height = 10.0f;
795 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
808 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
809 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
810 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
813 TEST(ShadowPathGeometryTest, RoundRectTest) {
815 DlPath path = DlPath::MakeRoundRectXY(DlRect::MakeLTRB(0, 0, 100, 80), 5, 4);
817 const Scalar height = 10.0f;
819 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
833 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 2u);
834 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
835 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
838 TEST(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();
847 const Scalar height = 10.0f;
850 std::shared_ptr<ShadowVertices> shadow_vertices =
854 EXPECT_EQ(shadow_vertices,
nullptr);
857 TEST(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();
866 const Scalar height = 10.0f;
869 std::shared_ptr<ShadowVertices> shadow_vertices =
873 EXPECT_EQ(shadow_vertices,
nullptr);
876 TEST(ShadowPathGeometryTest, InnerToOuterOverturningSpiralTest) {
878 const Scalar height = 10.0f;
881 DlPathBuilder path_builder;
882 path_builder.MoveTo(
DlPoint(300, 200));
883 for (
int i = 1; i < step_count * 2; i++) {
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));
889 path_builder.Close();
890 DlPath path = path_builder.TakePath();
893 std::shared_ptr<ShadowVertices> shadow_vertices =
897 EXPECT_EQ(shadow_vertices,
nullptr);
900 TEST(ShadowPathGeometryTest, ReverseInnerToOuterOverturningSpiralTest) {
902 const Scalar height = 10.0f;
905 DlPathBuilder path_builder;
906 path_builder.MoveTo(
DlPoint(300, 200));
907 for (
int i = 1; i < step_count * 2; i++) {
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));
913 path_builder.Close();
914 DlPath path = path_builder.TakePath();
917 std::shared_ptr<ShadowVertices> shadow_vertices =
921 EXPECT_EQ(shadow_vertices,
nullptr);
924 TEST(ShadowPathGeometryTest, OuterToInnerOverturningSpiralTest) {
926 const Scalar height = 10.0f;
929 DlPathBuilder path_builder;
930 path_builder.MoveTo(
DlPoint(280, 200));
931 for (
int i = 1; i < step_count * 2; i++) {
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));
937 path_builder.Close();
938 DlPath path = path_builder.TakePath();
941 std::shared_ptr<ShadowVertices> shadow_vertices =
945 EXPECT_EQ(shadow_vertices,
nullptr);
948 TEST(ShadowPathGeometryTest, ReverseOuterToInnerOverturningSpiralTest) {
950 const Scalar height = 10.0f;
953 DlPathBuilder path_builder;
954 path_builder.MoveTo(
DlPoint(280, 200));
955 for (
int i = 1; i < step_count * 2; i++) {
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));
961 path_builder.Close();
962 DlPath path = path_builder.TakePath();
965 std::shared_ptr<ShadowVertices> shadow_vertices =
969 EXPECT_EQ(shadow_vertices,
nullptr);
972 TEST(ShadowPathGeometryTest, ClockwiseOctagonCollapsedUmbraPolygonTest) {
974 const Scalar height = 100.0f;
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();
989 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
1003 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 3u);
1004 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
1005 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
1008 TEST(ShadowPathGeometryTest, CounterClockwiseOctagonCollapsedUmbraPolygonTest) {
1010 const Scalar height = 100.0f;
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();
1025 std::shared_ptr<ShadowVertices> shadow_vertices =
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);
1039 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 3u);
1040 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
1041 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
1044 TEST(ShadowPathGeometryTest, MultipleContoursTest) {
1046 const Scalar height = 10.0f;
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();
1060 std::shared_ptr<ShadowVertices> shadow_vertices =
1064 EXPECT_EQ(shadow_vertices,
nullptr);
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...
TEST(AllocationSizeTest, CanCreateTypedAllocations)
constexpr float kEhCloseEnough
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeScale(const Vector3 &s)
constexpr Type Cross(const TPoint &p) const