| 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
5 #include "impeller/geometry/path_source.h"
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"
11 #include "impeller/geometry/dashed_line_path_source.h"
12 #include "impeller/geometry/rect.h"
13 #include "impeller/geometry/round_rect.h"
14 #include "impeller/geometry/round_superellipse.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
impeller::DashedLinePathSource
A PathSource that generates the various segments of a dashed line.
Definition: dashed_line_path_source.h:15
impeller::DashedLinePathSource::IsConvex
bool IsConvex() const override
Definition: dashed_line_path_source.cc:25
impeller::DashedLinePathSource::GetFillType
FillType GetFillType() const override
Definition: dashed_line_path_source.cc:17
impeller::DashedLinePathSource::GetBounds
Rect GetBounds() const override
Definition: dashed_line_path_source.cc:21
impeller::DashedLinePathSource::Dispatch
void Dispatch(PathReceiver &receiver) const override
Definition: dashed_line_path_source.cc:29
impeller::DiffRoundRectPathSource
Definition: round_rect.h:169
impeller::DiffRoundRectPathSource::GetBounds
Rect GetBounds() const override
Definition: round_rect.cc:155
impeller::DiffRoundRectPathSource::IsConvex
bool IsConvex() const override
Definition: round_rect.cc:159
impeller::DiffRoundRectPathSource::Dispatch
void Dispatch(PathReceiver &receiver) const override
Definition: round_rect.cc:163
impeller::DiffRoundRectPathSource::GetFillType
FillType GetFillType() const override
Definition: round_rect.cc:151
impeller::EllipsePathSource
A PathSource object that provides path iteration for any ellipse inscribed within a Rect bounds.
Definition: path_source.h:90
impeller::EllipsePathSource::Dispatch
void Dispatch(PathReceiver &receiver) const override
Definition: path_source.cc:48
impeller::EllipsePathSource::IsConvex
bool IsConvex() const override
Definition: path_source.cc:44
impeller::EllipsePathSource::GetBounds
Rect GetBounds() const override
Definition: path_source.cc:40
impeller::EllipsePathSource::GetFillType
FillType GetFillType() const override
Definition: path_source.cc:36
impeller::PathTransformer
Definition: path_source.h:114
impeller::PathTransformer::LineTo
void LineTo(const Point &p2) override
Definition: path_source.h:124
impeller::PathTransformer::QuadTo
void QuadTo(const Point &cp, const Point &p2) override
Definition: path_source.h:126
impeller::PathTransformer::ConicTo
bool ConicTo(const Point &cp, const Point &p2, Scalar weight) override
Definition: path_source.h:130
impeller::PathTransformer::MoveTo
void MoveTo(const Point &p2, bool will_be_closed) override
Definition: path_source.h:120
impeller::PathTransformer::CubicTo
void CubicTo(const Point &cp1, const Point &cp2, const Point &p2) override
Definition: path_source.h:134
impeller::PathTransformer::Close
void Close() override
Definition: path_source.h:138
impeller::RectPathSource
A PathSource object that provides path iteration for any TRect.
Definition: path_source.h:65
impeller::RectPathSource::GetFillType
FillType GetFillType() const override
Definition: path_source.cc:15
impeller::RectPathSource::IsConvex
bool IsConvex() const override
Definition: path_source.cc:11
impeller::RectPathSource::GetBounds
Rect GetBounds() const override
Definition: path_source.cc:19
impeller::RectPathSource::Dispatch
void Dispatch(PathReceiver &receiver) const override
Definition: path_source.cc:23
impeller::RoundRectPathSource
Definition: round_rect.h:145
impeller::RoundRectPathSource::GetBounds
Rect GetBounds() const override
Definition: round_rect.cc:133
impeller::RoundRectPathSource::IsConvex
bool IsConvex() const override
Definition: round_rect.cc:137
impeller::RoundRectPathSource::Dispatch
void Dispatch(PathReceiver &receiver) const override
Definition: round_rect.cc:141
impeller::RoundRectPathSource::GetFillType
FillType GetFillType() const override
Definition: round_rect.cc:129
dashed_line_path_source.h
impeller::testing::TEST
TEST(AllocationSizeTest, CanCreateTypedAllocations)
Definition: allocation_size_unittests.cc:10
impeller
Definition: allocation.cc:12
impeller::kSqrt2Over2
constexpr float kSqrt2Over2
Definition: constants.h:51
impeller::FillType::kOdd
@ kOdd
impeller::FillType::kNonZero
@ kNonZero
impeller::Point
TPoint< Scalar > Point
Definition: point.h:425
impeller::Size
TSize< Scalar > Size
Definition: size.h:159
impeller::MoveTo
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:20
impeller::LineTo
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:24
impeller::CubicTo
void CubicTo(PathBuilder *builder, Scalar x1, Scalar y1, Scalar x2, Scalar y2, Scalar x3, Scalar y3)
Definition: tessellator.cc:28
impeller::Close
void Close(PathBuilder *builder)
Definition: tessellator.cc:38
path_source.h
rect.h
round_rect.h
round_superellipse.h
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Matrix::MakeTranslateScale
static constexpr Matrix MakeTranslateScale(const Vector3 &s, const Vector3 &t)
Definition: matrix.h:113
impeller::RoundRect
Definition: round_rect.h:16
impeller::RoundRect::MakeRectRadii
static RoundRect MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
Definition: round_rect.cc:9
impeller::RoundingRadii
Definition: rounding_radii.h:14
impeller::RoundingRadii::top_left
Size top_left
Definition: rounding_radii.h:15
impeller::TPoint< Scalar >
impeller::TRect< Scalar >
impeller::TRect::Contains
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
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129