Flutter Impeller
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 
5 #include <memory>
6 #include "flutter/testing/testing.h"
7 #include "gtest/gtest.h"
15 #include "impeller/renderer/testing/mocks.h"
16 
17 inline ::testing::AssertionResult SolidVerticesNear(
18  std::vector<impeller::Point> a,
19  std::vector<impeller::Point> b) {
20  if (a.size() != b.size()) {
21  return ::testing::AssertionFailure() << "Colors length does not match";
22  }
23  for (auto i = 0u; i < b.size(); i++) {
24  if (!PointNear(a[i], b[i])) {
25  return ::testing::AssertionFailure() << "Positions are not equal.";
26  }
27  }
28  return ::testing::AssertionSuccess();
29 }
30 
31 inline ::testing::AssertionResult TextureVerticesNear(
32  std::vector<impeller::TextureFillVertexShader::PerVertexData> a,
33  std::vector<impeller::TextureFillVertexShader::PerVertexData> b) {
34  if (a.size() != b.size()) {
35  return ::testing::AssertionFailure() << "Colors length does not match";
36  }
37  for (auto i = 0u; i < b.size(); i++) {
38  if (!PointNear(a[i].position, b[i].position)) {
39  return ::testing::AssertionFailure() << "Positions are not equal.";
40  }
41  if (!PointNear(a[i].texture_coords, b[i].texture_coords)) {
42  return ::testing::AssertionFailure() << "Texture coords are not equal.";
43  }
44  }
45  return ::testing::AssertionSuccess();
46 }
47 
48 #define EXPECT_SOLID_VERTICES_NEAR(a, b) \
49  EXPECT_PRED2(&::SolidVerticesNear, a, b)
50 #define EXPECT_TEXTURE_VERTICES_NEAR(a, b) \
51  EXPECT_PRED2(&::TextureVerticesNear, a, b)
52 
53 namespace impeller {
54 
56  public:
57  static std::vector<Point> GenerateSolidStrokeVertices(
58  const Path::Polyline& polyline,
60  Scalar miter_limit,
61  Join stroke_join,
62  Cap stroke_cap,
63  Scalar scale) {
64  return StrokePathGeometry::GenerateSolidStrokeVertices(
65  polyline, stroke_width, miter_limit, stroke_join, stroke_cap, scale);
66  }
67 };
68 
69 namespace testing {
70 
71 TEST(EntityGeometryTest, RectGeometryCoversArea) {
72  auto geometry = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 100, 100));
73  ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
74  ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
75  ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
76  ASSERT_TRUE(geometry->CoversArea({}, Rect()));
77 }
78 
79 TEST(EntityGeometryTest, FillPathGeometryCoversArea) {
80  auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
81  auto geometry = Geometry::MakeFillPath(
82  path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
83  ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
84  ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
85  ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
86  ASSERT_TRUE(geometry->CoversArea({}, Rect()));
87 }
88 
89 TEST(EntityGeometryTest, FillPathGeometryCoversAreaNoInnerRect) {
90  auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
91  auto geometry = Geometry::MakeFillPath(path);
92  ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
93  ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
94  ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
95  ASSERT_FALSE(geometry->CoversArea({}, Rect()));
96 }
97 
98 TEST(EntityGeometryTest, LineGeometryCoverage) {
99  {
100  auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kButt);
101  EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(10, 9, 20, 11));
102  EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(10, 9, 20, 11)));
103  }
104 
105  {
106  auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kSquare);
107  EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 21, 11));
108  EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 21, 11)));
109  }
110 
111  {
112  auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kButt);
113  EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 10, 11, 20));
114  EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 10, 11, 20)));
115  }
116 
117  {
118  auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kSquare);
119  EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 11, 21));
120  EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 11, 21)));
121  }
122 }
123 
124 TEST(EntityGeometryTest, RoundRectGeometryCoversArea) {
125  auto geometry =
126  Geometry::MakeRoundRect(Rect::MakeLTRB(0, 0, 100, 100), Size(20, 20));
127  EXPECT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(15, 15, 85, 85)));
128  EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(20, 20, 80, 80)));
129  EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(30, 1, 70, 99)));
130  EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 30, 99, 70)));
131 }
132 
133 TEST(EntityGeometryTest, GeometryResultHasReasonableDefaults) {
134  GeometryResult result;
135  EXPECT_EQ(result.type, PrimitiveType::kTriangleStrip);
136  EXPECT_EQ(result.transform, Matrix());
137  EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
138 }
139 
140 TEST(EntityGeometryTest, AlphaCoverageStrokePaths) {
141  auto matrix = Matrix::MakeScale(Vector2{3.0, 3.0});
142  EXPECT_EQ(Geometry::MakeStrokePath({}, 0.5)->ComputeAlphaCoverage(matrix), 1);
143  EXPECT_NEAR(Geometry::MakeStrokePath({}, 0.1)->ComputeAlphaCoverage(matrix),
144  0.6, 0.05);
145  EXPECT_NEAR(Geometry::MakeStrokePath({}, 0.05)->ComputeAlphaCoverage(matrix),
146  0.3, 0.05);
147  EXPECT_NEAR(Geometry::MakeStrokePath({}, 0.01)->ComputeAlphaCoverage(matrix),
148  0.1, 0.1);
149  EXPECT_NEAR(
150  Geometry::MakeStrokePath({}, 0.0000005)->ComputeAlphaCoverage(matrix),
151  1e-05, 0.001);
152  EXPECT_EQ(Geometry::MakeStrokePath({}, 0)->ComputeAlphaCoverage(matrix), 1);
153  EXPECT_EQ(Geometry::MakeStrokePath({}, 40)->ComputeAlphaCoverage(matrix), 1);
154 }
155 
156 } // namespace testing
157 } // namespace impeller
static std::unique_ptr< Geometry > MakeStrokePath(const Path &path, Scalar stroke_width=0.0, Scalar miter_limit=4.0, Cap stroke_cap=Cap::kButt, Join stroke_join=Join::kMiter)
Definition: geometry.cc:67
static std::unique_ptr< Geometry > MakeFillPath(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
Definition: geometry.cc:61
static std::unique_ptr< Geometry > MakeLine(const Point &p0, const Point &p1, Scalar width, Cap cap)
Definition: geometry.cc:92
static std::unique_ptr< Geometry > MakeRect(const Rect &rect)
Definition: geometry.cc:84
static std::unique_ptr< Geometry > MakeRoundRect(const Rect &rect, const Size &radii)
Definition: geometry.cc:110
static std::vector< Point > GenerateSolidStrokeVertices(const Path::Polyline &polyline, Scalar stroke_width, Scalar miter_limit, Join stroke_join, Cap stroke_cap, Scalar scale)
Path TakePath(FillType fill=FillType::kNonZero)
Definition: path_builder.cc:30
PathBuilder & AddRect(const Rect &rect)
inline ::testing::AssertionResult SolidVerticesNear(std::vector< impeller::Point > a, std::vector< impeller::Point > b)
inline ::testing::AssertionResult TextureVerticesNear(std::vector< impeller::TextureFillVertexShader::PerVertexData > a, std::vector< impeller::TextureFillVertexShader::PerVertexData > b)
inline ::testing::AssertionResult PointNear(impeller::Point a, impeller::Point b)
TEST(AllocationSizeTest, CanCreateTypedAllocations)
Join
Definition: path.h:26
float Scalar
Definition: scalar.h:18
Cap
Definition: path.h:20
TSize< Scalar > Size
Definition: size.h:159
const Scalar stroke_width
const Scalar scale
const Path::Polyline & polyline
PrimitiveType type
Definition: geometry.h:37
@ kNormal
The geometry has no overlapping triangles.
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129