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