Flutter Impeller
path_source_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 
7 #include "gtest/gtest.h"
8 
9 #include "flutter/display_list/testing/dl_test_mock_path_receiver.h"
10 #include "flutter/testing/testing.h"
12 #include "impeller/geometry/rect.h"
15 
16 namespace impeller {
17 namespace testing {
18 
19 using ::flutter::testing::DlPathReceiverMock;
20 using ::testing::Return;
21 
22 TEST(PathSourceTest, RectSourceTest) {
23  Rect rect = Rect::MakeLTRB(10, 15, 20, 30);
24  RectPathSource source(rect);
25 
26  EXPECT_TRUE(source.IsConvex());
27  EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
28  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 20, 30));
29 
30  ::testing::StrictMock<DlPathReceiverMock> receiver;
31 
32  {
33  ::testing::Sequence sequence;
34 
35  EXPECT_CALL(receiver, MoveTo(Point(10, 15), true));
36  EXPECT_CALL(receiver, LineTo(Point(20, 15)));
37  EXPECT_CALL(receiver, LineTo(Point(20, 30)));
38  EXPECT_CALL(receiver, LineTo(Point(10, 30)));
39  EXPECT_CALL(receiver, LineTo(Point(10, 15)));
40  EXPECT_CALL(receiver, Close());
41  }
42 
43  source.Dispatch(receiver);
44 }
45 
46 TEST(PathSourceTest, EllipseSourceTest) {
47  Rect rect = Rect::MakeLTRB(10, 15, 20, 30);
48  EllipsePathSource source(rect);
49 
50  EXPECT_TRUE(source.IsConvex());
51  EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
52  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 20, 30));
53 
54  ::testing::StrictMock<DlPathReceiverMock> receiver;
55 
56  {
57  ::testing::Sequence sequence;
58 
59  EXPECT_CALL(receiver, MoveTo(Point(10, 22.5), true));
60  EXPECT_CALL(receiver, ConicTo(Point(10, 15), Point(15, 15), kSqrt2Over2));
61  EXPECT_CALL(receiver, ConicTo(Point(20, 15), Point(20, 22.5), kSqrt2Over2));
62  EXPECT_CALL(receiver, ConicTo(Point(20, 30), Point(15, 30), kSqrt2Over2));
63  EXPECT_CALL(receiver, ConicTo(Point(10, 30), Point(10, 22.5), kSqrt2Over2));
64  EXPECT_CALL(receiver, Close());
65  }
66 
67  source.Dispatch(receiver);
68 }
69 
70 TEST(PathSourceTest, RoundRectSourceTest) {
71  Rect rect = Rect::MakeLTRB(10, 15, 40, 60);
72  RoundingRadii radii = {
73  .top_left = Size(1, 11),
74  .top_right = Size(2, 12),
75  .bottom_left = Size(4, 14),
76  .bottom_right = Size(3, 13),
77  };
78  RoundRect round_rect = RoundRect::MakeRectRadii(rect, radii);
79  RoundRectPathSource source(round_rect);
80 
81  EXPECT_TRUE(source.IsConvex());
82  EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
83  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 40, 60));
84 
85  ::testing::StrictMock<DlPathReceiverMock> receiver;
86 
87  {
88  ::testing::Sequence sequence;
89 
90  EXPECT_CALL(receiver, MoveTo(Point(11, 15), true));
91  EXPECT_CALL(receiver, LineTo(Point(38, 15)));
92  EXPECT_CALL(receiver, ConicTo(Point(40, 15), Point(40, 27), kSqrt2Over2));
93  EXPECT_CALL(receiver, LineTo(Point(40, 47)));
94  EXPECT_CALL(receiver, ConicTo(Point(40, 60), Point(37, 60), kSqrt2Over2));
95  EXPECT_CALL(receiver, LineTo(Point(14, 60)));
96  EXPECT_CALL(receiver, ConicTo(Point(10, 60), Point(10, 46), kSqrt2Over2));
97  EXPECT_CALL(receiver, LineTo(Point(10, 26)));
98  EXPECT_CALL(receiver, ConicTo(Point(10, 15), Point(11, 15), kSqrt2Over2));
99  EXPECT_CALL(receiver, Close());
100  }
101 
102  source.Dispatch(receiver);
103 }
104 
105 TEST(PathSourceTest, DiffRoundRectSourceTest) {
106  Rect outer_rect = Rect::MakeLTRB(10, 15, 200, 300);
107  Rect inner_rect = Rect::MakeLTRB(50, 60, 100, 200);
108  ASSERT_TRUE(outer_rect.Contains(inner_rect));
109  RoundingRadii radii = {
110  .top_left = Size(1, 11),
111  .top_right = Size(2, 12),
112  .bottom_left = Size(4, 14),
113  .bottom_right = Size(3, 13),
114  };
115  RoundRect outer_rrect = RoundRect::MakeRectRadii(outer_rect, radii);
116  RoundRect inner_rrect = RoundRect::MakeRectRadii(inner_rect, radii);
117  DiffRoundRectPathSource source(outer_rrect, inner_rrect);
118 
119  EXPECT_FALSE(source.IsConvex());
120  EXPECT_EQ(source.GetFillType(), FillType::kOdd);
121  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 200, 300));
122 
123  ::testing::StrictMock<DlPathReceiverMock> receiver;
124 
125  {
126  ::testing::Sequence sequence;
127 
128  EXPECT_CALL(receiver, MoveTo(Point(11, 15), true));
129  EXPECT_CALL(receiver, LineTo(Point(198, 15)));
130  EXPECT_CALL(receiver, ConicTo(Point(200, 15), Point(200, 27), kSqrt2Over2));
131  EXPECT_CALL(receiver, LineTo(Point(200, 287)));
132  EXPECT_CALL(receiver,
133  ConicTo(Point(200, 300), Point(197, 300), kSqrt2Over2));
134  EXPECT_CALL(receiver, LineTo(Point(14, 300)));
135  EXPECT_CALL(receiver, ConicTo(Point(10, 300), Point(10, 286), kSqrt2Over2));
136  EXPECT_CALL(receiver, LineTo(Point(10, 26)));
137  EXPECT_CALL(receiver, ConicTo(Point(10, 15), Point(11, 15), kSqrt2Over2));
138  // RetiresOnSaturation keeps identical calls from matching each other
139  EXPECT_CALL(receiver, Close()).RetiresOnSaturation();
140 
141  EXPECT_CALL(receiver, MoveTo(Point(51, 60), true));
142  EXPECT_CALL(receiver, LineTo(Point(98, 60)));
143  EXPECT_CALL(receiver, ConicTo(Point(100, 60), Point(100, 72), kSqrt2Over2));
144  EXPECT_CALL(receiver, LineTo(Point(100, 187)));
145  EXPECT_CALL(receiver,
146  ConicTo(Point(100, 200), Point(97, 200), kSqrt2Over2));
147  EXPECT_CALL(receiver, LineTo(Point(54, 200)));
148  EXPECT_CALL(receiver, ConicTo(Point(50, 200), Point(50, 186), kSqrt2Over2));
149  EXPECT_CALL(receiver, LineTo(Point(50, 71)));
150  EXPECT_CALL(receiver, ConicTo(Point(50, 60), Point(51, 60), kSqrt2Over2));
151  // RetiresOnSaturation keeps identical calls from matching each other
152  EXPECT_CALL(receiver, Close()).RetiresOnSaturation();
153  }
154 
155  source.Dispatch(receiver);
156 }
157 
158 TEST(PathSourceTest, DashedLinePathSource) {
159  DashedLinePathSource source(Point(10, 10), Point(30, 10), 5, 5);
160 
161  EXPECT_FALSE(source.IsConvex());
162  EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
163  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
164 
165  ::testing::StrictMock<DlPathReceiverMock> receiver;
166 
167  {
168  ::testing::Sequence sequence;
169 
170  EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
171  EXPECT_CALL(receiver, LineTo(Point(15, 10)));
172  EXPECT_CALL(receiver, MoveTo(Point(20, 10), false));
173  EXPECT_CALL(receiver, LineTo(Point(25, 10)));
174  }
175 
176  source.Dispatch(receiver);
177 }
178 
179 TEST(PathSourceTest, EmptyDashedLinePathSource) {
180  DashedLinePathSource source(Point(10, 10), Point(10, 10), 5, 5);
181 
182  EXPECT_FALSE(source.IsConvex());
183  EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
184  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 10, 10));
185 
186  ::testing::StrictMock<DlPathReceiverMock> receiver;
187 
188  {
189  ::testing::Sequence sequence;
190 
191  EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
192  EXPECT_CALL(receiver, LineTo(Point(10, 10)));
193  }
194 
195  source.Dispatch(receiver);
196 }
197 
198 TEST(PathSourceTest, DashedLinePathSourceZeroOffGaps) {
199  DashedLinePathSource source(Point(10, 10), Point(30, 10), 5, 0);
200 
201  EXPECT_FALSE(source.IsConvex());
202  EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
203  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
204 
205  ::testing::StrictMock<DlPathReceiverMock> receiver;
206 
207  {
208  ::testing::Sequence sequence;
209 
210  EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
211  EXPECT_CALL(receiver, LineTo(Point(30, 10)));
212  }
213 
214  source.Dispatch(receiver);
215 }
216 
217 TEST(PathSourceTest, DashedLinePathSourceInvalidOffGaps) {
218  DashedLinePathSource source(Point(10, 10), Point(30, 10), 5, -1);
219 
220  EXPECT_FALSE(source.IsConvex());
221  EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
222  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
223 
224  ::testing::StrictMock<DlPathReceiverMock> receiver;
225 
226  {
227  ::testing::Sequence sequence;
228 
229  EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
230  EXPECT_CALL(receiver, LineTo(Point(30, 10)));
231  }
232 
233  source.Dispatch(receiver);
234 }
235 
236 TEST(PathSourceTest, DashedLinePathSourceInvalidOnRegion) {
237  DashedLinePathSource source(Point(10, 10), Point(30, 10), -1, 5);
238 
239  EXPECT_FALSE(source.IsConvex());
240  EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
241  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
242 
243  ::testing::StrictMock<DlPathReceiverMock> receiver;
244 
245  {
246  ::testing::Sequence sequence;
247 
248  EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
249  EXPECT_CALL(receiver, LineTo(Point(30, 10)));
250  }
251 
252  source.Dispatch(receiver);
253 }
254 
255 TEST(PathSourceTest, PathTransformerRectSourceTest) {
256  Matrix matrix =
257  Matrix::MakeTranslateScale({2.0f, 3.0f, 1.0f}, {1.5f, 4.25f, 0.0f});
258  Rect rect = Rect::MakeLTRB(10, 15, 20, 30);
259  RectPathSource source(rect);
260 
261  EXPECT_TRUE(source.IsConvex());
262  EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
263  EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 20, 30));
264 
265  ::testing::StrictMock<DlPathReceiverMock> mock_receiver;
266  PathTransformer receiver = PathTransformer(mock_receiver, matrix);
267 
268  {
269  ::testing::Sequence sequence;
270 
271  EXPECT_CALL(mock_receiver, MoveTo(Point(21.5f, 49.25f), true));
272  EXPECT_CALL(mock_receiver, LineTo(Point(41.5f, 49.25f)));
273  EXPECT_CALL(mock_receiver, LineTo(Point(41.5f, 94.25f)));
274  EXPECT_CALL(mock_receiver, LineTo(Point(21.5f, 94.25f)));
275  EXPECT_CALL(mock_receiver, LineTo(Point(21.5f, 49.25f)));
276  EXPECT_CALL(mock_receiver, Close());
277  }
278 
279  source.Dispatch(receiver);
280 }
281 
282 TEST(PathSourceTest, PathTransformerAllSegmentsTest) {
283  Matrix matrix =
284  Matrix::MakeTranslateScale({2.0f, 3.0f, 1.0f}, {1.5f, 4.25f, 0.0f});
285 
286  ::testing::StrictMock<DlPathReceiverMock> mock_receiver;
287  PathTransformer receiver = PathTransformer(mock_receiver, matrix);
288 
289  {
290  ::testing::Sequence sequence;
291 
292  EXPECT_CALL(mock_receiver, MoveTo(Point(21.5f, 49.25f), false));
293  EXPECT_CALL(mock_receiver, LineTo(Point(41.5f, 49.25f)));
294 
295  EXPECT_CALL(mock_receiver, MoveTo(Point(221.5f, 349.25f), true));
296  EXPECT_CALL(mock_receiver,
297  QuadTo(Point(241.5f, 349.25f), Point(241.5f, 394.25f)));
298  EXPECT_CALL(mock_receiver,
299  ConicTo(Point(237.5f, 409.25f), Point(231.5f, 409.25f), 5))
300  .WillOnce(Return(true));
301  EXPECT_CALL(mock_receiver,
302  ConicTo(Point(225.5f, 409.25f), Point(221.5f, 394.25f), 6))
303  .WillOnce(Return(false));
304  EXPECT_CALL(mock_receiver,
305  CubicTo(Point(211.5f, 379.25f), Point(211.5f, 364.25f),
306  Point(221.5f, 349.25f)));
307  EXPECT_CALL(mock_receiver, Close());
308  }
309 
310  receiver.MoveTo(Point(10, 15), false);
311  receiver.LineTo(Point(20, 15));
312 
313  receiver.MoveTo(Point(110, 115), true);
314  receiver.QuadTo(Point(120, 115), Point(120, 130));
315  EXPECT_TRUE(receiver.ConicTo(Point(118, 135), Point(115, 135), 5));
316  EXPECT_FALSE(receiver.ConicTo(Point(112, 135), Point(110, 130), 6));
317  receiver.CubicTo(Point(105, 125), Point(105, 120), Point(110, 115));
318  receiver.Close();
319 }
320 
321 } // namespace testing
322 } // namespace impeller
A PathSource that generates the various segments of a dashed line.
FillType GetFillType() const override
void Dispatch(PathReceiver &receiver) const override
Rect GetBounds() const override
Definition: round_rect.cc:155
bool IsConvex() const override
Definition: round_rect.cc:159
void Dispatch(PathReceiver &receiver) const override
Definition: round_rect.cc:163
FillType GetFillType() const override
Definition: round_rect.cc:151
A PathSource object that provides path iteration for any ellipse inscribed within a Rect bounds.
Definition: path_source.h:90
void Dispatch(PathReceiver &receiver) const override
Definition: path_source.cc:48
bool IsConvex() const override
Definition: path_source.cc:44
Rect GetBounds() const override
Definition: path_source.cc:40
FillType GetFillType() const override
Definition: path_source.cc:36
void LineTo(const Point &p2) override
Definition: path_source.h:124
void QuadTo(const Point &cp, const Point &p2) override
Definition: path_source.h:126
bool ConicTo(const Point &cp, const Point &p2, Scalar weight) override
Definition: path_source.h:130
void MoveTo(const Point &p2, bool will_be_closed) override
Definition: path_source.h:120
void CubicTo(const Point &cp1, const Point &cp2, const Point &p2) override
Definition: path_source.h:134
void Close() override
Definition: path_source.h:138
A PathSource object that provides path iteration for any TRect.
Definition: path_source.h:65
FillType GetFillType() const override
Definition: path_source.cc:15
bool IsConvex() const override
Definition: path_source.cc:11
Rect GetBounds() const override
Definition: path_source.cc:19
void Dispatch(PathReceiver &receiver) const override
Definition: path_source.cc:23
Rect GetBounds() const override
Definition: round_rect.cc:133
bool IsConvex() const override
Definition: round_rect.cc:137
void Dispatch(PathReceiver &receiver) const override
Definition: round_rect.cc:141
FillType GetFillType() const override
Definition: round_rect.cc:129
TEST(AllocationSizeTest, CanCreateTypedAllocations)
constexpr float kSqrt2Over2
Definition: constants.h:51
TPoint< Scalar > Point
Definition: point.h:425
TSize< Scalar > Size
Definition: size.h:159
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:20
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:24
void CubicTo(PathBuilder *builder, Scalar x1, Scalar y1, Scalar x2, Scalar y2, Scalar x3, Scalar y3)
Definition: tessellator.cc:28
void Close(PathBuilder *builder)
Definition: tessellator.cc:38
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeTranslateScale(const Vector3 &s, const Vector3 &t)
Definition: matrix.h:113
static RoundRect MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
Definition: round_rect.cc:9
constexpr bool Contains(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
Definition: rect.h:231
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129